diff options
Diffstat (limited to 'tools/perf')
235 files changed, 11565 insertions, 2412 deletions
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index 3d1bb802dbf4..3db3db9278be 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore | |||
@@ -30,3 +30,4 @@ config.mak.autogen | |||
30 | *.pyo | 30 | *.pyo |
31 | .config-detected | 31 | .config-detected |
32 | util/intel-pt-decoder/inat-tables.c | 32 | util/intel-pt-decoder/inat-tables.c |
33 | arch/*/include/generated/ | ||
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt index 8484c3a04a6a..24a59998fc91 100644 --- a/tools/perf/Documentation/android.txt +++ b/tools/perf/Documentation/android.txt | |||
@@ -12,14 +12,14 @@ Set the NDK variable to point to the path where you installed the NDK: | |||
12 | 12 | ||
13 | 2. Set cross-compiling environment variables for NDK toolchain and sysroot. | 13 | 2. Set cross-compiling environment variables for NDK toolchain and sysroot. |
14 | For arm: | 14 | For arm: |
15 | export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi- | 15 | export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi- |
16 | export NDK_SYSROOT=${NDK}/platforms/android-9/arch-arm | 16 | export NDK_SYSROOT=${NDK}/platforms/android-24/arch-arm |
17 | For x86: | 17 | For x86: |
18 | export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.6/prebuilt/linux-x86/bin/i686-linux-android- | 18 | export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android- |
19 | export NDK_SYSROOT=${NDK}/platforms/android-9/arch-x86 | 19 | export NDK_SYSROOT=${NDK}/platforms/android-24/arch-x86 |
20 | 20 | ||
21 | This method is not working for Android NDK versions up to Revision 8b. | 21 | This method is only tested for Android NDK versions Revision 11b and later. |
22 | perf uses some bionic enhancements that are not included in these NDK versions. | 22 | perf uses some bionic enhancements that are not included in prior NDK versions. |
23 | You can use method (b) described below instead. | 23 | You can use method (b) described below instead. |
24 | 24 | ||
25 | (b). Use the Android source tree | 25 | (b). Use the Android source tree |
@@ -49,9 +49,9 @@ II. Compile perf for Android | |||
49 | ------------------------------------------------ | 49 | ------------------------------------------------ |
50 | You need to run make with the NDK toolchain and sysroot defined above: | 50 | You need to run make with the NDK toolchain and sysroot defined above: |
51 | For arm: | 51 | For arm: |
52 | make ARCH=arm CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}" | 52 | make WERROR=0 ARCH=arm CROSS_COMPILE=${NDK_TOOLCHAIN} EXTRA_CFLAGS="-pie --sysroot=${NDK_SYSROOT}" |
53 | For x86: | 53 | For x86: |
54 | make ARCH=x86 CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}" | 54 | make WERROR=0 ARCH=x86 CROSS_COMPILE=${NDK_TOOLCHAIN} EXTRA_CFLAGS="-pie --sysroot=${NDK_SYSROOT}" |
55 | 55 | ||
56 | III. Install perf | 56 | III. Install perf |
57 | ----------------------------------------------- | 57 | ----------------------------------------------- |
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index 778f54d4d0bd..8ffbd272952d 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt | |||
@@ -61,6 +61,13 @@ OPTIONS | |||
61 | 61 | ||
62 | --stdio:: Use the stdio interface. | 62 | --stdio:: Use the stdio interface. |
63 | 63 | ||
64 | --stdio-color:: | ||
65 | 'always', 'never' or 'auto', allowing configuring color output | ||
66 | via the command line, in addition to via "color.ui" .perfconfig. | ||
67 | Use '--stdio-color always' to generate color even when redirecting | ||
68 | to a pipe or file. Using just '--stdio-color' is equivalent to | ||
69 | using 'always'. | ||
70 | |||
64 | --tui:: Use the TUI interface. Use of --tui requires a tty, if one is not | 71 | --tui:: Use the TUI interface. Use of --tui requires a tty, if one is not |
65 | present, as when piping to other commands, the stdio interface is | 72 | present, as when piping to other commands, the stdio interface is |
66 | used. This interfaces starts by centering on the line with more | 73 | used. This interfaces starts by centering on the line with more |
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt index dd07b55f58d8..058064db39d2 100644 --- a/tools/perf/Documentation/perf-buildid-cache.txt +++ b/tools/perf/Documentation/perf-buildid-cache.txt | |||
@@ -15,6 +15,9 @@ DESCRIPTION | |||
15 | This command manages the build-id cache. It can add, remove, update and purge | 15 | This command manages the build-id cache. It can add, remove, update and purge |
16 | files to/from the cache. In the future it should as well set upper limits for | 16 | files to/from the cache. In the future it should as well set upper limits for |
17 | the space used by the cache, etc. | 17 | the space used by the cache, etc. |
18 | This also scans the target binary for SDT (Statically Defined Tracing) and | ||
19 | record it along with the buildid-cache, which will be used by perf-probe. | ||
20 | For more details, see linkperf:perf-probe[1]. | ||
18 | 21 | ||
19 | OPTIONS | 22 | OPTIONS |
20 | ------- | 23 | ------- |
diff --git a/tools/perf/Documentation/perf-data.txt b/tools/perf/Documentation/perf-data.txt index be8fa1a0a97e..f0796a47dfa3 100644 --- a/tools/perf/Documentation/perf-data.txt +++ b/tools/perf/Documentation/perf-data.txt | |||
@@ -34,6 +34,10 @@ OPTIONS for 'convert' | |||
34 | --verbose:: | 34 | --verbose:: |
35 | Be more verbose (show counter open errors, etc). | 35 | Be more verbose (show counter open errors, etc). |
36 | 36 | ||
37 | --all:: | ||
38 | Convert all events, including non-sample events (comm, fork, ...), to output. | ||
39 | Default is off, only convert samples. | ||
40 | |||
37 | SEE ALSO | 41 | SEE ALSO |
38 | -------- | 42 | -------- |
39 | linkperf:perf[1] | 43 | linkperf:perf[1] |
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt index 1d6092c460dd..73496320fca3 100644 --- a/tools/perf/Documentation/perf-mem.txt +++ b/tools/perf/Documentation/perf-mem.txt | |||
@@ -56,6 +56,9 @@ OPTIONS | |||
56 | --all-user:: | 56 | --all-user:: |
57 | Configure all used events to run in user space. | 57 | Configure all used events to run in user space. |
58 | 58 | ||
59 | --ldload:: | ||
60 | Specify desired latency for loads event. | ||
61 | |||
59 | SEE ALSO | 62 | SEE ALSO |
60 | -------- | 63 | -------- |
61 | linkperf:perf-record[1], linkperf:perf-report[1] | 64 | linkperf:perf-record[1], linkperf:perf-report[1] |
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 3a8a9ba2b041..736da44596e4 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt | |||
@@ -67,7 +67,10 @@ OPTIONS | |||
67 | 67 | ||
68 | -l:: | 68 | -l:: |
69 | --list[=[GROUP:]EVENT]:: | 69 | --list[=[GROUP:]EVENT]:: |
70 | List up current probe events. This can also accept filtering patterns of event names. | 70 | List up current probe events. This can also accept filtering patterns of |
71 | event names. | ||
72 | When this is used with --cache, perf shows all cached probes instead of | ||
73 | the live probes. | ||
71 | 74 | ||
72 | -L:: | 75 | -L:: |
73 | --line=:: | 76 | --line=:: |
@@ -109,6 +112,12 @@ OPTIONS | |||
109 | Dry run. With this option, --add and --del doesn't execute actual | 112 | Dry run. With this option, --add and --del doesn't execute actual |
110 | adding and removal operations. | 113 | adding and removal operations. |
111 | 114 | ||
115 | --cache:: | ||
116 | (With --add) Cache the probes. Any events which successfully added | ||
117 | are also stored in the cache file. | ||
118 | (With --list) Show cached probes. | ||
119 | (With --del) Remove cached probes. | ||
120 | |||
112 | --max-probes=NUM:: | 121 | --max-probes=NUM:: |
113 | Set the maximum number of probe points for an event. Default is 128. | 122 | Set the maximum number of probe points for an event. Default is 128. |
114 | 123 | ||
@@ -134,19 +143,30 @@ PROBE SYNTAX | |||
134 | Probe points are defined by following syntax. | 143 | Probe points are defined by following syntax. |
135 | 144 | ||
136 | 1) Define event based on function name | 145 | 1) Define event based on function name |
137 | [EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...] | 146 | [[GROUP:]EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...] |
138 | 147 | ||
139 | 2) Define event based on source file with line number | 148 | 2) Define event based on source file with line number |
140 | [EVENT=]SRC:ALN [ARG ...] | 149 | [[GROUP:]EVENT=]SRC:ALN [ARG ...] |
141 | 150 | ||
142 | 3) Define event based on source file with lazy pattern | 151 | 3) Define event based on source file with lazy pattern |
143 | [EVENT=]SRC;PTN [ARG ...] | 152 | [[GROUP:]EVENT=]SRC;PTN [ARG ...] |
144 | 153 | ||
154 | 4) Pre-defined SDT events or cached event with name | ||
155 | %[sdt_PROVIDER:]SDTEVENT | ||
156 | or, | ||
157 | sdt_PROVIDER:SDTEVENT | ||
145 | 158 | ||
146 | 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'. | 159 | 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. You can also specify a group name by 'GROUP', if omitted, set 'probe' is used for kprobe and 'probe_<bin>' is used for uprobe. |
160 | Note that using existing group name can conflict with other events. Especially, using the group name reserved for kernel modules can hide embedded events in the | ||
161 | modules. | ||
147 | 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function. | 162 | 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function. |
148 | It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern. | 163 | It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern. |
149 | 'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT). | 164 | 'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT). |
165 | 'SDTEVENT' and 'PROVIDER' is the pre-defined event name which is defined by user SDT (Statically Defined Tracing) or the pre-cached probes with event name. | ||
166 | Note that before using the SDT event, the target binary (on which SDT events are defined) must be scanned by linkperf:perf-buildid-cache[1] to make SDT events as cached events. | ||
167 | |||
168 | For details of the SDT, see below. | ||
169 | https://sourceware.org/gdb/onlinedocs/gdb/Static-Probe-Points.html | ||
150 | 170 | ||
151 | PROBE ARGUMENT | 171 | PROBE ARGUMENT |
152 | -------------- | 172 | -------------- |
@@ -226,4 +246,4 @@ Add probes at malloc() function on libc | |||
226 | 246 | ||
227 | SEE ALSO | 247 | SEE ALSO |
228 | -------- | 248 | -------- |
229 | linkperf:perf-trace[1], linkperf:perf-record[1] | 249 | linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1] |
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 8dbee832abd9..379a2bed07c0 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -192,6 +192,9 @@ OPTIONS | |||
192 | --period:: | 192 | --period:: |
193 | Record the sample period. | 193 | Record the sample period. |
194 | 194 | ||
195 | --sample-cpu:: | ||
196 | Record the sample cpu. | ||
197 | |||
195 | -n:: | 198 | -n:: |
196 | --no-samples:: | 199 | --no-samples:: |
197 | Don't sample. | 200 | Don't sample. |
@@ -360,6 +363,35 @@ particular perf.data snapshot should be kept or not. | |||
360 | 363 | ||
361 | Implies --timestamp-filename, --no-buildid and --no-buildid-cache. | 364 | Implies --timestamp-filename, --no-buildid and --no-buildid-cache. |
362 | 365 | ||
366 | --dry-run:: | ||
367 | Parse options then exit. --dry-run can be used to detect errors in cmdline | ||
368 | options. | ||
369 | |||
370 | 'perf record --dry-run -e' can act as a BPF script compiler if llvm.dump-obj | ||
371 | in config file is set to true. | ||
372 | |||
373 | --tail-synthesize:: | ||
374 | Instead of collecting non-sample events (for example, fork, comm, mmap) at | ||
375 | the beginning of record, collect them during finalizing an output file. | ||
376 | The collected non-sample events reflects the status of the system when | ||
377 | record is finished. | ||
378 | |||
379 | --overwrite:: | ||
380 | Makes all events use an overwritable ring buffer. An overwritable ring | ||
381 | buffer works like a flight recorder: when it gets full, the kernel will | ||
382 | overwrite the oldest records, that thus will never make it to the | ||
383 | perf.data file. | ||
384 | |||
385 | When '--overwrite' and '--switch-output' are used perf records and drops | ||
386 | events until it receives a signal, meaning that something unusual was | ||
387 | detected that warrants taking a snapshot of the most current events, | ||
388 | those fitting in the ring buffer at that moment. | ||
389 | |||
390 | 'overwrite' attribute can also be set or canceled for an event using | ||
391 | config terms. For example: 'cycles/overwrite/' and 'instructions/no-overwrite/'. | ||
392 | |||
393 | Implies --tail-synthesize. | ||
394 | |||
363 | SEE ALSO | 395 | SEE ALSO |
364 | -------- | 396 | -------- |
365 | linkperf:perf-stat[1], linkperf:perf-list[1] | 397 | linkperf:perf-stat[1], linkperf:perf-list[1] |
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 9cbddc290aff..2d1746295abf 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -265,6 +265,13 @@ OPTIONS | |||
265 | 265 | ||
266 | --stdio:: Use the stdio interface. | 266 | --stdio:: Use the stdio interface. |
267 | 267 | ||
268 | --stdio-color:: | ||
269 | 'always', 'never' or 'auto', allowing configuring color output | ||
270 | via the command line, in addition to via "color.ui" .perfconfig. | ||
271 | Use '--stdio-color always' to generate color even when redirecting | ||
272 | to a pipe or file. Using just '--stdio-color' is equivalent to | ||
273 | using 'always'. | ||
274 | |||
268 | --tui:: Use the TUI interface, that is integrated with annotate and allows | 275 | --tui:: Use the TUI interface, that is integrated with annotate and allows |
269 | zooming into DSOs or threads, among other features. Use of --tui | 276 | zooming into DSOs or threads, among other features. Use of --tui |
270 | requires a tty, if one is not present, as when piping to other | 277 | requires a tty, if one is not present, as when piping to other |
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 4fc44c75263f..1f6c70594f0f 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt | |||
@@ -119,13 +119,13 @@ OPTIONS | |||
119 | srcline, period, iregs, brstack, brstacksym, 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 |
123 | 123 | ||
124 | perf script -f <fields> | 124 | perf script -F <fields> |
125 | 125 | ||
126 | is equivalent to: | 126 | is equivalent to: |
127 | 127 | ||
128 | perf script -f trace:<fields> -f sw:<fields> -f hw:<fields> | 128 | perf script -F trace:<fields> -F sw:<fields> -F hw:<fields> |
129 | 129 | ||
130 | i.e., the specified fields apply to all event types if the type string | 130 | i.e., the specified fields apply to all event types if the type string |
131 | is not given. | 131 | is not given. |
@@ -133,9 +133,9 @@ OPTIONS | |||
133 | The arguments are processed in the order received. A later usage can | 133 | The arguments are processed in the order received. A later usage can |
134 | reset a prior request. e.g.: | 134 | reset a prior request. e.g.: |
135 | 135 | ||
136 | -f trace: -f comm,tid,time,ip,sym | 136 | -F trace: -F comm,tid,time,ip,sym |
137 | 137 | ||
138 | The first -f suppresses trace events (field list is ""), but then the | 138 | The first -F suppresses trace events (field list is ""), but then the |
139 | second invocation sets the fields to comm,tid,time,ip,sym. In this case a | 139 | second invocation sets the fields to comm,tid,time,ip,sym. In this case a |
140 | warning is given to the user: | 140 | warning is given to the user: |
141 | 141 | ||
@@ -143,9 +143,9 @@ OPTIONS | |||
143 | 143 | ||
144 | Alternatively, consider the order: | 144 | Alternatively, consider the order: |
145 | 145 | ||
146 | -f comm,tid,time,ip,sym -f trace: | 146 | -F comm,tid,time,ip,sym -F trace: |
147 | 147 | ||
148 | The first -f sets the fields for all events and the second -f | 148 | The first -F sets the fields for all events and the second -F |
149 | suppresses trace events. The user is given a warning message about | 149 | suppresses trace events. The user is given a warning message about |
150 | the override, and the result of the above is that only S/W and H/W | 150 | the override, and the result of the above is that only S/W and H/W |
151 | events are displayed with the given fields. | 151 | events are displayed with the given fields. |
@@ -154,14 +154,14 @@ OPTIONS | |||
154 | event type, a message is displayed to the user that the option is | 154 | event type, a message is displayed to the user that the option is |
155 | ignored for that type. For example: | 155 | ignored for that type. For example: |
156 | 156 | ||
157 | $ perf script -f comm,tid,trace | 157 | $ perf script -F comm,tid,trace |
158 | 'trace' not valid for hardware events. Ignoring. | 158 | 'trace' not valid for hardware events. Ignoring. |
159 | 'trace' not valid for software events. Ignoring. | 159 | 'trace' not valid for software events. Ignoring. |
160 | 160 | ||
161 | Alternatively, if the type is given an invalid field is specified it | 161 | Alternatively, if the type is given an invalid field is specified it |
162 | is an error. For example: | 162 | is an error. For example: |
163 | 163 | ||
164 | perf script -v -f sw:comm,tid,trace | 164 | perf script -v -F sw:comm,tid,trace |
165 | 'trace' not valid for software events. | 165 | 'trace' not valid for software events. |
166 | 166 | ||
167 | At this point usage is displayed, and perf-script exits. | 167 | At this point usage is displayed, and perf-script exits. |
@@ -170,10 +170,19 @@ OPTIONS | |||
170 | Trace decoding. The flags are "bcrosyiABEx" which stand for branch, | 170 | Trace decoding. The flags are "bcrosyiABEx" which stand for branch, |
171 | call, return, conditional, system, asynchronous, interrupt, | 171 | call, return, conditional, system, asynchronous, interrupt, |
172 | transaction abort, trace begin, trace end, and in transaction, | 172 | transaction abort, trace begin, trace end, and in transaction, |
173 | respectively. | 173 | respectively. Known combinations of flags are printed more nicely e.g. |
174 | "call" for "bc", "return" for "br", "jcc" for "bo", "jmp" for "b", | ||
175 | "int" for "bci", "iret" for "bri", "syscall" for "bcs", "sysret" for "brs", | ||
176 | "async" for "by", "hw int" for "bcyi", "tx abrt" for "bA", "tr strt" for "bB", | ||
177 | "tr end" for "bE". However the "x" flag will be display separately in those | ||
178 | cases e.g. "jcc (x)" for a condition branch within a transaction. | ||
179 | |||
180 | The callindent field is synthesized and may have a value when | ||
181 | Instruction Trace decoding. For calls and returns, it will display the | ||
182 | name of the symbol indented with spaces to reflect the stack depth. | ||
174 | 183 | ||
175 | Finally, a user may not set fields to none for all event types. | 184 | Finally, a user may not set fields to none for all event types. |
176 | i.e., -f "" is not allowed. | 185 | i.e., -F "" is not allowed. |
177 | 186 | ||
178 | The brstack output includes branch related information with raw addresses using the | 187 | The brstack output includes branch related information with raw addresses using the |
179 | /v/v/v/v/ syntax in the following order: | 188 | /v/v/v/v/ syntax in the following order: |
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 04f23b404bbc..d96ccd4844df 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt | |||
@@ -204,6 +204,38 @@ Aggregate counts per physical processor for system-wide mode measurements. | |||
204 | --no-aggr:: | 204 | --no-aggr:: |
205 | Do not aggregate counts across all monitored CPUs. | 205 | Do not aggregate counts across all monitored CPUs. |
206 | 206 | ||
207 | --topdown:: | ||
208 | Print top down level 1 metrics if supported by the CPU. This allows to | ||
209 | determine bottle necks in the CPU pipeline for CPU bound workloads, | ||
210 | by breaking the cycles consumed down into frontend bound, backend bound, | ||
211 | bad speculation and retiring. | ||
212 | |||
213 | Frontend bound means that the CPU cannot fetch and decode instructions fast | ||
214 | enough. Backend bound means that computation or memory access is the bottle | ||
215 | neck. Bad Speculation means that the CPU wasted cycles due to branch | ||
216 | mispredictions and similar issues. Retiring means that the CPU computed without | ||
217 | an apparently bottleneck. The bottleneck is only the real bottleneck | ||
218 | if the workload is actually bound by the CPU and not by something else. | ||
219 | |||
220 | For best results it is usually a good idea to use it with interval | ||
221 | mode like -I 1000, as the bottleneck of workloads can change often. | ||
222 | |||
223 | The top down metrics are collected per core instead of per | ||
224 | CPU thread. Per core mode is automatically enabled | ||
225 | and -a (global monitoring) is needed, requiring root rights or | ||
226 | perf.perf_event_paranoid=-1. | ||
227 | |||
228 | Topdown uses the full Performance Monitoring Unit, and needs | ||
229 | disabling of the NMI watchdog (as root): | ||
230 | echo 0 > /proc/sys/kernel/nmi_watchdog | ||
231 | for best results. Otherwise the bottlenecks may be inconsistent | ||
232 | on workload with changing phases. | ||
233 | |||
234 | This enables --metric-only, unless overriden with --no-metric-only. | ||
235 | |||
236 | To interpret the results it is usually needed to know on which | ||
237 | CPUs the workload runs on. If needed the CPUs can be forced using | ||
238 | taskset. | ||
207 | 239 | ||
208 | EXAMPLES | 240 | EXAMPLES |
209 | -------- | 241 | -------- |
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt index 31a5c3ea7f74..b329c65d7f40 100644 --- a/tools/perf/Documentation/perf-test.txt +++ b/tools/perf/Documentation/perf-test.txt | |||
@@ -30,3 +30,7 @@ OPTIONS | |||
30 | -v:: | 30 | -v:: |
31 | --verbose:: | 31 | --verbose:: |
32 | Be more verbose. | 32 | Be more verbose. |
33 | |||
34 | -F:: | ||
35 | --dont-fork:: | ||
36 | Do not fork child for each test, run all tests within single process. | ||
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt new file mode 100644 index 000000000000..fdc99fe6bbc3 --- /dev/null +++ b/tools/perf/Documentation/perf.data-file-format.txt | |||
@@ -0,0 +1,442 @@ | |||
1 | perf.data format | ||
2 | |||
3 | Uptodate as of v4.7 | ||
4 | |||
5 | This document describes the on-disk perf.data format, generated by perf record | ||
6 | or perf inject and consumed by the other perf tools. | ||
7 | |||
8 | On a high level perf.data contains the events generated by the PMUs, plus metadata. | ||
9 | |||
10 | All fields are in native-endian of the machine that generated the perf.data. | ||
11 | |||
12 | When perf is writing to a pipe it uses a special version of the file | ||
13 | format that does not rely on seeking to adjust data offsets. This | ||
14 | format is not described here. The pipe version can be converted to | ||
15 | normal perf.data with perf inject. | ||
16 | |||
17 | The file starts with a perf_header: | ||
18 | |||
19 | struct perf_header { | ||
20 | char magic[8]; /* PERFILE2 */ | ||
21 | uint64_t size; /* size of the header */ | ||
22 | uint64_t attr_size; /* size of an attribute in attrs */ | ||
23 | struct perf_file_section attrs; | ||
24 | struct perf_file_section data; | ||
25 | struct perf_file_section event_types; | ||
26 | uint64_t flags; | ||
27 | uint64_t flags1[3]; | ||
28 | }; | ||
29 | |||
30 | The magic number identifies the perf file and the version. Current perf versions | ||
31 | use PERFILE2. Old perf versions generated a version 1 format (PERFFILE). Version 1 | ||
32 | is not described here. The magic number also identifies the endian. When the | ||
33 | magic value is 64bit byte swapped compared the file is in non-native | ||
34 | endian. | ||
35 | |||
36 | A perf_file_section contains a pointer to another section of the perf file. | ||
37 | The header contains three such pointers: for attributes, data and event types. | ||
38 | |||
39 | struct perf_file_section { | ||
40 | uint64_t offset; /* offset from start of file */ | ||
41 | uint64_t size; /* size of the section */ | ||
42 | }; | ||
43 | |||
44 | Flags section: | ||
45 | |||
46 | The header is followed by different optional headers, described by the bits set | ||
47 | in flags. Only headers for which the bit is set are included. Each header | ||
48 | consists of a perf_file_section located after the initial header. | ||
49 | The respective perf_file_section points to the data of the additional | ||
50 | header and defines its size. | ||
51 | |||
52 | Some headers consist of strings, which are defined like this: | ||
53 | |||
54 | struct perf_header_string { | ||
55 | uint32_t len; | ||
56 | char string[len]; /* zero terminated */ | ||
57 | }; | ||
58 | |||
59 | Some headers consist of a sequence of strings, which start with a | ||
60 | |||
61 | struct perf_header_string_list { | ||
62 | uint32_t nr; | ||
63 | struct perf_header_string strings[nr]; /* variable length records */ | ||
64 | }; | ||
65 | |||
66 | The bits are the flags bits in a 256 bit bitmap starting with | ||
67 | flags. These define the valid bits: | ||
68 | |||
69 | HEADER_RESERVED = 0, /* always cleared */ | ||
70 | HEADER_FIRST_FEATURE = 1, | ||
71 | HEADER_TRACING_DATA = 1, | ||
72 | |||
73 | Describe me. | ||
74 | |||
75 | HEADER_BUILD_ID = 2, | ||
76 | |||
77 | The header consists of an sequence of build_id_event. The size of each record | ||
78 | is defined by header.size (see perf_event.h). Each event defines a ELF build id | ||
79 | for a executable file name for a pid. An ELF build id is a unique identifier | ||
80 | assigned by the linker to an executable. | ||
81 | |||
82 | struct build_id_event { | ||
83 | struct perf_event_header header; | ||
84 | pid_t pid; | ||
85 | uint8_t build_id[24]; | ||
86 | char filename[header.size - offsetof(struct build_id_event, filename)]; | ||
87 | }; | ||
88 | |||
89 | HEADER_HOSTNAME = 3, | ||
90 | |||
91 | A perf_header_string with the hostname where the data was collected | ||
92 | (uname -n) | ||
93 | |||
94 | HEADER_OSRELEASE = 4, | ||
95 | |||
96 | A perf_header_string with the os release where the data was collected | ||
97 | (uname -r) | ||
98 | |||
99 | HEADER_VERSION = 5, | ||
100 | |||
101 | A perf_header_string with the perf user tool version where the | ||
102 | data was collected. This is the same as the version of the source tree | ||
103 | the perf tool was built from. | ||
104 | |||
105 | HEADER_ARCH = 6, | ||
106 | |||
107 | A perf_header_string with the CPU architecture (uname -m) | ||
108 | |||
109 | HEADER_NRCPUS = 7, | ||
110 | |||
111 | A structure defining the number of CPUs. | ||
112 | |||
113 | struct nr_cpus { | ||
114 | uint32_t nr_cpus_online; | ||
115 | uint32_t nr_cpus_available; /* CPUs not yet onlined */ | ||
116 | }; | ||
117 | |||
118 | HEADER_CPUDESC = 8, | ||
119 | |||
120 | A perf_header_string with description of the CPU. On x86 this is the model name | ||
121 | in /proc/cpuinfo | ||
122 | |||
123 | HEADER_CPUID = 9, | ||
124 | |||
125 | A perf_header_string with the exact CPU type. On x86 this is | ||
126 | vendor,family,model,stepping. For example: GenuineIntel,6,69,1 | ||
127 | |||
128 | HEADER_TOTAL_MEM = 10, | ||
129 | |||
130 | An uint64_t with the total memory in bytes. | ||
131 | |||
132 | HEADER_CMDLINE = 11, | ||
133 | |||
134 | A perf_header_string with the perf command line used to collect the data. | ||
135 | |||
136 | HEADER_EVENT_DESC = 12, | ||
137 | |||
138 | Another description of the perf_event_attrs, more detailed than header.attrs | ||
139 | including IDs and names. See perf_event.h or the man page for a description | ||
140 | of a struct perf_event_attr. | ||
141 | |||
142 | struct { | ||
143 | uint32_t nr; /* number of events */ | ||
144 | uint32_t attr_size; /* size of each perf_event_attr */ | ||
145 | struct { | ||
146 | struct perf_event_attr attr; /* size of attr_size */ | ||
147 | uint32_t nr_ids; | ||
148 | struct perf_header_string event_string; | ||
149 | uint64_t ids[nr_ids]; | ||
150 | } events[nr]; /* Variable length records */ | ||
151 | }; | ||
152 | |||
153 | HEADER_CPU_TOPOLOGY = 13, | ||
154 | |||
155 | String lists defining the core and CPU threads topology. | ||
156 | |||
157 | struct { | ||
158 | struct perf_header_string_list cores; /* Variable length */ | ||
159 | struct perf_header_string_list threads; /* Variable length */ | ||
160 | }; | ||
161 | |||
162 | Example: | ||
163 | sibling cores : 0-3 | ||
164 | sibling threads : 0-1 | ||
165 | sibling threads : 2-3 | ||
166 | |||
167 | HEADER_NUMA_TOPOLOGY = 14, | ||
168 | |||
169 | A list of NUMA node descriptions | ||
170 | |||
171 | struct { | ||
172 | uint32_t nr; | ||
173 | struct { | ||
174 | uint32_t nodenr; | ||
175 | uint64_t mem_total; | ||
176 | uint64_t mem_free; | ||
177 | struct perf_header_string cpus; | ||
178 | } nodes[nr]; /* Variable length records */ | ||
179 | }; | ||
180 | |||
181 | HEADER_BRANCH_STACK = 15, | ||
182 | |||
183 | Not implemented in perf. | ||
184 | |||
185 | HEADER_PMU_MAPPINGS = 16, | ||
186 | |||
187 | A list of PMU structures, defining the different PMUs supported by perf. | ||
188 | |||
189 | struct { | ||
190 | uint32_t nr; | ||
191 | struct pmu { | ||
192 | uint32_t pmu_type; | ||
193 | struct perf_header_string pmu_name; | ||
194 | } [nr]; /* Variable length records */ | ||
195 | }; | ||
196 | |||
197 | HEADER_GROUP_DESC = 17, | ||
198 | |||
199 | Description of counter groups ({...} in perf syntax) | ||
200 | |||
201 | struct { | ||
202 | uint32_t nr; | ||
203 | struct { | ||
204 | struct perf_header_string string; | ||
205 | uint32_t leader_idx; | ||
206 | uint32_t nr_members; | ||
207 | } [nr]; /* Variable length records */ | ||
208 | }; | ||
209 | |||
210 | HEADER_AUXTRACE = 18, | ||
211 | |||
212 | Define additional auxtrace areas in the perf.data. auxtrace is used to store | ||
213 | undecoded hardware tracing information, such as Intel Processor Trace data. | ||
214 | |||
215 | /** | ||
216 | * struct auxtrace_index_entry - indexes a AUX area tracing event within a | ||
217 | * perf.data file. | ||
218 | * @file_offset: offset within the perf.data file | ||
219 | * @sz: size of the event | ||
220 | */ | ||
221 | struct auxtrace_index_entry { | ||
222 | u64 file_offset; | ||
223 | u64 sz; | ||
224 | }; | ||
225 | |||
226 | #define PERF_AUXTRACE_INDEX_ENTRY_COUNT 256 | ||
227 | |||
228 | /** | ||
229 | * struct auxtrace_index - index of AUX area tracing events within a perf.data | ||
230 | * file. | ||
231 | * @list: linking a number of arrays of entries | ||
232 | * @nr: number of entries | ||
233 | * @entries: array of entries | ||
234 | */ | ||
235 | struct auxtrace_index { | ||
236 | struct list_head list; | ||
237 | size_t nr; | ||
238 | struct auxtrace_index_entry entries[PERF_AUXTRACE_INDEX_ENTRY_COUNT]; | ||
239 | }; | ||
240 | |||
241 | other bits are reserved and should ignored for now | ||
242 | HEADER_FEAT_BITS = 256, | ||
243 | |||
244 | Attributes | ||
245 | |||
246 | This is an array of perf_event_attrs, each attr_size bytes long, which defines | ||
247 | each event collected. See perf_event.h or the man page for a detailed | ||
248 | description. | ||
249 | |||
250 | Data | ||
251 | |||
252 | This section is the bulk of the file. It consist of a stream of perf_events | ||
253 | describing events. This matches the format generated by the kernel. | ||
254 | See perf_event.h or the manpage for a detailed description. | ||
255 | |||
256 | Some notes on parsing: | ||
257 | |||
258 | Ordering | ||
259 | |||
260 | The events are not necessarily in time stamp order, as they can be | ||
261 | collected in parallel on different CPUs. If the events should be | ||
262 | processed in time order they need to be sorted first. It is possible | ||
263 | to only do a partial sort using the FINISHED_ROUND event header (see | ||
264 | below). perf record guarantees that there is no reordering over a | ||
265 | FINISHED_ROUND. | ||
266 | |||
267 | ID vs IDENTIFIER | ||
268 | |||
269 | When the event stream contains multiple events each event is identified | ||
270 | by an ID. This can be either through the PERF_SAMPLE_ID or the | ||
271 | PERF_SAMPLE_IDENTIFIER header. The PERF_SAMPLE_IDENTIFIER header is | ||
272 | at a fixed offset from the event header, which allows reliable | ||
273 | parsing of the header. Relying on ID may be ambigious. | ||
274 | IDENTIFIER is only supported by newer Linux kernels. | ||
275 | |||
276 | Perf record specific events: | ||
277 | |||
278 | In addition to the kernel generated event types perf record adds its | ||
279 | own event types (in addition it also synthesizes some kernel events, | ||
280 | for example MMAP events) | ||
281 | |||
282 | PERF_RECORD_USER_TYPE_START = 64, | ||
283 | PERF_RECORD_HEADER_ATTR = 64, | ||
284 | |||
285 | struct attr_event { | ||
286 | struct perf_event_header header; | ||
287 | struct perf_event_attr attr; | ||
288 | uint64_t id[]; | ||
289 | }; | ||
290 | |||
291 | PERF_RECORD_HEADER_EVENT_TYPE = 65, /* depreceated */ | ||
292 | |||
293 | #define MAX_EVENT_NAME 64 | ||
294 | |||
295 | struct perf_trace_event_type { | ||
296 | uint64_t event_id; | ||
297 | char name[MAX_EVENT_NAME]; | ||
298 | }; | ||
299 | |||
300 | struct event_type_event { | ||
301 | struct perf_event_header header; | ||
302 | struct perf_trace_event_type event_type; | ||
303 | }; | ||
304 | |||
305 | |||
306 | PERF_RECORD_HEADER_TRACING_DATA = 66, | ||
307 | |||
308 | Describe me | ||
309 | |||
310 | struct tracing_data_event { | ||
311 | struct perf_event_header header; | ||
312 | uint32_t size; | ||
313 | }; | ||
314 | |||
315 | PERF_RECORD_HEADER_BUILD_ID = 67, | ||
316 | |||
317 | Define a ELF build ID for a referenced executable. | ||
318 | |||
319 | struct build_id_event; /* See above */ | ||
320 | |||
321 | PERF_RECORD_FINISHED_ROUND = 68, | ||
322 | |||
323 | No event reordering over this header. No payload. | ||
324 | |||
325 | PERF_RECORD_ID_INDEX = 69, | ||
326 | |||
327 | Map event ids to CPUs and TIDs. | ||
328 | |||
329 | struct id_index_entry { | ||
330 | uint64_t id; | ||
331 | uint64_t idx; | ||
332 | uint64_t cpu; | ||
333 | uint64_t tid; | ||
334 | }; | ||
335 | |||
336 | struct id_index_event { | ||
337 | struct perf_event_header header; | ||
338 | uint64_t nr; | ||
339 | struct id_index_entry entries[nr]; | ||
340 | }; | ||
341 | |||
342 | PERF_RECORD_AUXTRACE_INFO = 70, | ||
343 | |||
344 | Auxtrace type specific information. Describe me | ||
345 | |||
346 | struct auxtrace_info_event { | ||
347 | struct perf_event_header header; | ||
348 | uint32_t type; | ||
349 | uint32_t reserved__; /* For alignment */ | ||
350 | uint64_t priv[]; | ||
351 | }; | ||
352 | |||
353 | PERF_RECORD_AUXTRACE = 71, | ||
354 | |||
355 | Defines auxtrace data. Followed by the actual data. The contents of | ||
356 | the auxtrace data is dependent on the event and the CPU. For example | ||
357 | for Intel Processor Trace it contains Processor Trace data generated | ||
358 | by the CPU. | ||
359 | |||
360 | struct auxtrace_event { | ||
361 | struct perf_event_header header; | ||
362 | uint64_t size; | ||
363 | uint64_t offset; | ||
364 | uint64_t reference; | ||
365 | uint32_t idx; | ||
366 | uint32_t tid; | ||
367 | uint32_t cpu; | ||
368 | uint32_t reserved__; /* For alignment */ | ||
369 | }; | ||
370 | |||
371 | struct aux_event { | ||
372 | struct perf_event_header header; | ||
373 | uint64_t aux_offset; | ||
374 | uint64_t aux_size; | ||
375 | uint64_t flags; | ||
376 | }; | ||
377 | |||
378 | PERF_RECORD_AUXTRACE_ERROR = 72, | ||
379 | |||
380 | Describes an error in hardware tracing | ||
381 | |||
382 | enum auxtrace_error_type { | ||
383 | PERF_AUXTRACE_ERROR_ITRACE = 1, | ||
384 | PERF_AUXTRACE_ERROR_MAX | ||
385 | }; | ||
386 | |||
387 | #define MAX_AUXTRACE_ERROR_MSG 64 | ||
388 | |||
389 | struct auxtrace_error_event { | ||
390 | struct perf_event_header header; | ||
391 | uint32_t type; | ||
392 | uint32_t code; | ||
393 | uint32_t cpu; | ||
394 | uint32_t pid; | ||
395 | uint32_t tid; | ||
396 | uint32_t reserved__; /* For alignment */ | ||
397 | uint64_t ip; | ||
398 | char msg[MAX_AUXTRACE_ERROR_MSG]; | ||
399 | }; | ||
400 | |||
401 | Event types | ||
402 | |||
403 | Define the event attributes with their IDs. | ||
404 | |||
405 | An array bound by the perf_file_section size. | ||
406 | |||
407 | struct { | ||
408 | struct perf_event_attr attr; /* Size defined by header.attr_size */ | ||
409 | struct perf_file_section ids; | ||
410 | } | ||
411 | |||
412 | ids points to a array of uint64_t defining the ids for event attr attr. | ||
413 | |||
414 | References: | ||
415 | |||
416 | include/uapi/linux/perf_event.h | ||
417 | |||
418 | This is the canonical description of the kernel generated perf_events | ||
419 | and the perf_event_attrs. | ||
420 | |||
421 | perf_events manpage | ||
422 | |||
423 | A manpage describing perf_event and perf_event_attr is here: | ||
424 | http://web.eece.maine.edu/~vweaver/projects/perf_events/programming.html | ||
425 | This tends to be slightly behind the kernel include, but has better | ||
426 | descriptions. An (typically older) version of the man page may be | ||
427 | included with the standard Linux man pages, available with "man | ||
428 | perf_events" | ||
429 | |||
430 | pmu-tools | ||
431 | |||
432 | https://github.com/andikleen/pmu-tools/tree/master/parser | ||
433 | |||
434 | A definition of the perf.data format in python "construct" format is available | ||
435 | in pmu-tools parser. This allows to read perf.data from python and dump it. | ||
436 | |||
437 | quipper | ||
438 | |||
439 | The quipper C++ parser is available at | ||
440 | https://chromium.googlesource.com/chromiumos/platform/chromiumos-wide-profiling/ | ||
441 | Unfortunately this parser tends to be many versions behind and may not be able | ||
442 | to parse data files generated by recent perf. | ||
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index 8c8c6b9ce915..ad2534df4ba6 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
@@ -12,13 +12,23 @@ tools/arch/sparc/include/asm/barrier_32.h | |||
12 | tools/arch/sparc/include/asm/barrier_64.h | 12 | tools/arch/sparc/include/asm/barrier_64.h |
13 | tools/arch/tile/include/asm/barrier.h | 13 | tools/arch/tile/include/asm/barrier.h |
14 | tools/arch/x86/include/asm/barrier.h | 14 | tools/arch/x86/include/asm/barrier.h |
15 | tools/arch/x86/include/asm/cpufeatures.h | ||
16 | tools/arch/x86/include/asm/disabled-features.h | ||
17 | tools/arch/x86/include/asm/required-features.h | ||
18 | tools/arch/x86/include/uapi/asm/svm.h | ||
19 | tools/arch/x86/include/uapi/asm/vmx.h | ||
20 | tools/arch/x86/include/uapi/asm/kvm.h | ||
21 | tools/arch/x86/include/uapi/asm/kvm_perf.h | ||
22 | tools/arch/x86/lib/memcpy_64.S | ||
23 | tools/arch/x86/lib/memset_64.S | ||
24 | tools/arch/s390/include/uapi/asm/kvm_perf.h | ||
25 | tools/arch/s390/include/uapi/asm/sie.h | ||
15 | tools/arch/xtensa/include/asm/barrier.h | 26 | tools/arch/xtensa/include/asm/barrier.h |
16 | tools/scripts | 27 | tools/scripts |
17 | tools/build | 28 | tools/build |
18 | tools/arch/x86/include/asm/atomic.h | 29 | tools/arch/x86/include/asm/atomic.h |
19 | tools/arch/x86/include/asm/rmwcc.h | 30 | tools/arch/x86/include/asm/rmwcc.h |
20 | tools/lib/traceevent | 31 | tools/lib/traceevent |
21 | tools/lib/bpf | ||
22 | tools/lib/api | 32 | tools/lib/api |
23 | tools/lib/bpf | 33 | tools/lib/bpf |
24 | tools/lib/subcmd | 34 | tools/lib/subcmd |
@@ -29,6 +39,9 @@ tools/lib/symbol/kallsyms.c | |||
29 | tools/lib/symbol/kallsyms.h | 39 | tools/lib/symbol/kallsyms.h |
30 | tools/lib/find_bit.c | 40 | tools/lib/find_bit.c |
31 | tools/lib/bitmap.c | 41 | tools/lib/bitmap.c |
42 | tools/lib/str_error_r.c | ||
43 | tools/lib/vsprintf.c | ||
44 | tools/include/asm/alternative-asm.h | ||
32 | tools/include/asm/atomic.h | 45 | tools/include/asm/atomic.h |
33 | tools/include/asm/barrier.h | 46 | tools/include/asm/barrier.h |
34 | tools/include/asm/bug.h | 47 | tools/include/asm/bug.h |
@@ -52,43 +65,16 @@ tools/include/linux/hash.h | |||
52 | tools/include/linux/kernel.h | 65 | tools/include/linux/kernel.h |
53 | tools/include/linux/list.h | 66 | tools/include/linux/list.h |
54 | tools/include/linux/log2.h | 67 | tools/include/linux/log2.h |
68 | tools/include/uapi/linux/bpf.h | ||
69 | tools/include/uapi/linux/bpf_common.h | ||
70 | tools/include/uapi/linux/hw_breakpoint.h | ||
71 | tools/include/uapi/linux/perf_event.h | ||
55 | tools/include/linux/poison.h | 72 | tools/include/linux/poison.h |
56 | tools/include/linux/rbtree.h | 73 | tools/include/linux/rbtree.h |
57 | tools/include/linux/rbtree_augmented.h | 74 | tools/include/linux/rbtree_augmented.h |
58 | tools/include/linux/string.h | 75 | tools/include/linux/string.h |
76 | tools/include/linux/stringify.h | ||
59 | tools/include/linux/types.h | 77 | tools/include/linux/types.h |
60 | tools/include/linux/err.h | 78 | tools/include/linux/err.h |
61 | tools/include/linux/bitmap.h | 79 | tools/include/linux/bitmap.h |
62 | include/asm-generic/bitops/arch_hweight.h | 80 | tools/arch/*/include/uapi/asm/perf_regs.h |
63 | include/asm-generic/bitops/const_hweight.h | ||
64 | include/asm-generic/bitops/fls64.h | ||
65 | include/asm-generic/bitops/__fls.h | ||
66 | include/asm-generic/bitops/fls.h | ||
67 | include/linux/perf_event.h | ||
68 | include/linux/list.h | ||
69 | include/linux/hash.h | ||
70 | include/linux/stringify.h | ||
71 | include/linux/swab.h | ||
72 | arch/*/include/asm/unistd*.h | ||
73 | arch/*/include/uapi/asm/unistd*.h | ||
74 | arch/*/include/uapi/asm/perf_regs.h | ||
75 | arch/*/lib/memcpy*.S | ||
76 | arch/*/lib/memset*.S | ||
77 | arch/*/include/asm/*features.h | ||
78 | include/linux/poison.h | ||
79 | include/linux/hw_breakpoint.h | ||
80 | include/uapi/linux/perf_event.h | ||
81 | include/uapi/linux/bpf.h | ||
82 | include/uapi/linux/bpf_common.h | ||
83 | include/uapi/linux/const.h | ||
84 | include/uapi/linux/swab.h | ||
85 | include/uapi/linux/hw_breakpoint.h | ||
86 | arch/x86/include/asm/svm.h | ||
87 | arch/x86/include/asm/vmx.h | ||
88 | arch/x86/include/asm/kvm_host.h | ||
89 | arch/x86/include/uapi/asm/svm.h | ||
90 | arch/x86/include/uapi/asm/vmx.h | ||
91 | arch/x86/include/uapi/asm/kvm.h | ||
92 | arch/x86/include/uapi/asm/kvm_perf.h | ||
93 | arch/s390/include/uapi/asm/sie.h | ||
94 | arch/s390/include/uapi/asm/kvm_perf.h | ||
diff --git a/tools/perf/config/Makefile b/tools/perf/Makefile.config index 5ad0255f8756..24803c58049a 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/Makefile.config | |||
@@ -73,17 +73,25 @@ endif | |||
73 | # | 73 | # |
74 | # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ | 74 | # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ |
75 | # | 75 | # |
76 | |||
77 | libunwind_arch_set_flags = $(eval $(libunwind_arch_set_flags_code)) | ||
78 | define libunwind_arch_set_flags_code | ||
79 | FEATURE_CHECK_CFLAGS-libunwind-$(1) = -I$(LIBUNWIND_DIR)/include | ||
80 | FEATURE_CHECK_LDFLAGS-libunwind-$(1) = -L$(LIBUNWIND_DIR)/lib | ||
81 | endef | ||
82 | |||
76 | ifdef LIBUNWIND_DIR | 83 | ifdef LIBUNWIND_DIR |
77 | LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include | 84 | LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include |
78 | LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib | 85 | LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib |
86 | LIBUNWIND_ARCHS = x86 x86_64 arm aarch64 debug-frame-arm debug-frame-aarch64 | ||
87 | $(foreach libunwind_arch,$(LIBUNWIND_ARCHS),$(call libunwind_arch_set_flags,$(libunwind_arch))) | ||
79 | endif | 88 | endif |
80 | LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS) | ||
81 | 89 | ||
82 | # Set per-feature check compilation flags | 90 | # Set per-feature check compilation flags |
83 | FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) | 91 | FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) |
84 | FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) | 92 | FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) |
85 | FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) | 93 | FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) |
86 | FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) | 94 | FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) |
87 | 95 | ||
88 | ifeq ($(NO_PERF_REGS),0) | 96 | ifeq ($(NO_PERF_REGS),0) |
89 | CFLAGS += -DHAVE_PERF_REGS_SUPPORT | 97 | CFLAGS += -DHAVE_PERF_REGS_SUPPORT |
@@ -107,7 +115,7 @@ endif | |||
107 | FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS) | 115 | FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS) |
108 | FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf | 116 | FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf |
109 | 117 | ||
110 | FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi | 118 | FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi |
111 | # include ARCH specific config | 119 | # include ARCH specific config |
112 | -include $(src-perf)/arch/$(ARCH)/Makefile | 120 | -include $(src-perf)/arch/$(ARCH)/Makefile |
113 | 121 | ||
@@ -198,11 +206,11 @@ endif | |||
198 | 206 | ||
199 | CFLAGS += -I$(src-perf)/util/include | 207 | CFLAGS += -I$(src-perf)/util/include |
200 | CFLAGS += -I$(src-perf)/arch/$(ARCH)/include | 208 | CFLAGS += -I$(src-perf)/arch/$(ARCH)/include |
209 | CFLAGS += -I$(srctree)/tools/include/uapi | ||
201 | CFLAGS += -I$(srctree)/tools/include/ | 210 | CFLAGS += -I$(srctree)/tools/include/ |
202 | CFLAGS += -I$(srctree)/arch/$(ARCH)/include/uapi | 211 | CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi |
203 | CFLAGS += -I$(srctree)/arch/$(ARCH)/include | 212 | CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/ |
204 | CFLAGS += -I$(srctree)/include/uapi | 213 | CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/ |
205 | CFLAGS += -I$(srctree)/include | ||
206 | 214 | ||
207 | # $(obj-perf) for generated common-cmds.h | 215 | # $(obj-perf) for generated common-cmds.h |
208 | # $(obj-perf)/util for generated bison/flex headers | 216 | # $(obj-perf)/util for generated bison/flex headers |
@@ -249,7 +257,7 @@ else | |||
249 | LIBC_SUPPORT := 1 | 257 | LIBC_SUPPORT := 1 |
250 | endif | 258 | endif |
251 | ifeq ($(LIBC_SUPPORT),1) | 259 | ifeq ($(LIBC_SUPPORT),1) |
252 | msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install elfutils-libelf-devel/libelf-dev); | 260 | msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install libelf-dev, libelf-devel or elfutils-libelf-devel); |
253 | 261 | ||
254 | NO_LIBELF := 1 | 262 | NO_LIBELF := 1 |
255 | NO_DWARF := 1 | 263 | NO_DWARF := 1 |
@@ -301,6 +309,16 @@ ifndef NO_LIBELF | |||
301 | CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT | 309 | CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT |
302 | endif | 310 | endif |
303 | 311 | ||
312 | ifeq ($(feature-libelf-gelf_getnote), 1) | ||
313 | CFLAGS += -DHAVE_GELF_GETNOTE_SUPPORT | ||
314 | else | ||
315 | msg := $(warning gelf_getnote() not found on libelf, SDT support disabled); | ||
316 | endif | ||
317 | |||
318 | ifeq ($(feature-libelf-getshdrstrndx), 1) | ||
319 | CFLAGS += -DHAVE_ELF_GETSHDRSTRNDX_SUPPORT | ||
320 | endif | ||
321 | |||
304 | ifndef NO_DWARF | 322 | ifndef NO_DWARF |
305 | ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) | 323 | ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) |
306 | msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); | 324 | msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); |
@@ -337,6 +355,16 @@ ifndef NO_LIBELF | |||
337 | endif # NO_LIBBPF | 355 | endif # NO_LIBBPF |
338 | endif # NO_LIBELF | 356 | endif # NO_LIBELF |
339 | 357 | ||
358 | ifndef NO_SDT | ||
359 | ifneq ($(feature-sdt), 1) | ||
360 | msg := $(warning No sys/sdt.h found, no SDT events are defined, please install systemtap-sdt-devel or systemtap-sdt-dev); | ||
361 | NO_SDT := 1; | ||
362 | else | ||
363 | CFLAGS += -DHAVE_SDT_EVENT | ||
364 | $(call detected,CONFIG_SDT_EVENT) | ||
365 | endif | ||
366 | endif | ||
367 | |||
340 | ifdef PERF_HAVE_JITDUMP | 368 | ifdef PERF_HAVE_JITDUMP |
341 | ifndef NO_DWARF | 369 | ifndef NO_DWARF |
342 | $(call detected,CONFIG_JITDUMP) | 370 | $(call detected,CONFIG_JITDUMP) |
@@ -351,10 +379,42 @@ ifeq ($(ARCH),powerpc) | |||
351 | endif | 379 | endif |
352 | 380 | ||
353 | ifndef NO_LIBUNWIND | 381 | ifndef NO_LIBUNWIND |
382 | have_libunwind := | ||
383 | |||
384 | ifeq ($(feature-libunwind-x86), 1) | ||
385 | $(call detected,CONFIG_LIBUNWIND_X86) | ||
386 | CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT | ||
387 | LDFLAGS += -lunwind-x86 | ||
388 | EXTLIBS_LIBUNWIND += -lunwind-x86 | ||
389 | have_libunwind = 1 | ||
390 | endif | ||
391 | |||
392 | ifeq ($(feature-libunwind-aarch64), 1) | ||
393 | $(call detected,CONFIG_LIBUNWIND_AARCH64) | ||
394 | CFLAGS += -DHAVE_LIBUNWIND_AARCH64_SUPPORT | ||
395 | LDFLAGS += -lunwind-aarch64 | ||
396 | EXTLIBS_LIBUNWIND += -lunwind-aarch64 | ||
397 | have_libunwind = 1 | ||
398 | $(call feature_check,libunwind-debug-frame-aarch64) | ||
399 | ifneq ($(feature-libunwind-debug-frame-aarch64), 1) | ||
400 | msg := $(warning No debug_frame support found in libunwind-aarch64); | ||
401 | CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_AARCH64 | ||
402 | endif | ||
403 | endif | ||
404 | |||
354 | ifneq ($(feature-libunwind), 1) | 405 | ifneq ($(feature-libunwind), 1) |
355 | msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); | 406 | msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); |
407 | NO_LOCAL_LIBUNWIND := 1 | ||
408 | else | ||
409 | have_libunwind := 1 | ||
410 | $(call detected,CONFIG_LOCAL_LIBUNWIND) | ||
411 | endif | ||
412 | |||
413 | ifneq ($(have_libunwind), 1) | ||
356 | NO_LIBUNWIND := 1 | 414 | NO_LIBUNWIND := 1 |
357 | endif | 415 | endif |
416 | else | ||
417 | NO_LOCAL_LIBUNWIND := 1 | ||
358 | endif | 418 | endif |
359 | 419 | ||
360 | ifndef NO_LIBBPF | 420 | ifndef NO_LIBBPF |
@@ -392,7 +452,7 @@ else | |||
392 | NO_DWARF_UNWIND := 1 | 452 | NO_DWARF_UNWIND := 1 |
393 | endif | 453 | endif |
394 | 454 | ||
395 | ifndef NO_LIBUNWIND | 455 | ifndef NO_LOCAL_LIBUNWIND |
396 | ifeq ($(ARCH),$(filter $(ARCH),arm arm64)) | 456 | ifeq ($(ARCH),$(filter $(ARCH),arm arm64)) |
397 | $(call feature_check,libunwind-debug-frame) | 457 | $(call feature_check,libunwind-debug-frame) |
398 | ifneq ($(feature-libunwind-debug-frame), 1) | 458 | ifneq ($(feature-libunwind-debug-frame), 1) |
@@ -403,10 +463,15 @@ ifndef NO_LIBUNWIND | |||
403 | # non-ARM has no dwarf_find_debug_frame() function: | 463 | # non-ARM has no dwarf_find_debug_frame() function: |
404 | CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME | 464 | CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME |
405 | endif | 465 | endif |
406 | CFLAGS += -DHAVE_LIBUNWIND_SUPPORT | ||
407 | EXTLIBS += $(LIBUNWIND_LIBS) | 466 | EXTLIBS += $(LIBUNWIND_LIBS) |
467 | LDFLAGS += $(LIBUNWIND_LIBS) | ||
468 | endif | ||
469 | |||
470 | ifndef NO_LIBUNWIND | ||
471 | CFLAGS += -DHAVE_LIBUNWIND_SUPPORT | ||
408 | CFLAGS += $(LIBUNWIND_CFLAGS) | 472 | CFLAGS += $(LIBUNWIND_CFLAGS) |
409 | LDFLAGS += $(LIBUNWIND_LDFLAGS) | 473 | LDFLAGS += $(LIBUNWIND_LDFLAGS) |
474 | EXTLIBS += $(EXTLIBS_LIBUNWIND) | ||
410 | endif | 475 | endif |
411 | 476 | ||
412 | ifndef NO_LIBAUDIT | 477 | ifndef NO_LIBAUDIT |
@@ -437,7 +502,7 @@ endif | |||
437 | 502 | ||
438 | ifndef NO_SLANG | 503 | ifndef NO_SLANG |
439 | ifneq ($(feature-libslang), 1) | 504 | ifneq ($(feature-libslang), 1) |
440 | msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev); | 505 | msg := $(warning slang not found, disables TUI support. Please install slang-devel, libslang-dev or libslang2-dev); |
441 | NO_SLANG := 1 | 506 | NO_SLANG := 1 |
442 | else | 507 | else |
443 | # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h | 508 | # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index bde8cbae7dd9..2d9087501633 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -81,6 +81,9 @@ include ../scripts/utilities.mak | |||
81 | # | 81 | # |
82 | # Define NO_LIBBPF if you do not want BPF support | 82 | # Define NO_LIBBPF if you do not want BPF support |
83 | # | 83 | # |
84 | # Define NO_SDT if you do not want to define SDT event in perf tools, | ||
85 | # note that it doesn't disable SDT scanning support. | ||
86 | # | ||
84 | # Define FEATURES_DUMP to provide features detection dump file | 87 | # Define FEATURES_DUMP to provide features detection dump file |
85 | # and bypass the feature detection | 88 | # and bypass the feature detection |
86 | 89 | ||
@@ -158,7 +161,7 @@ TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ | |||
158 | BPF_DIR = $(srctree)/tools/lib/bpf/ | 161 | BPF_DIR = $(srctree)/tools/lib/bpf/ |
159 | SUBCMD_DIR = $(srctree)/tools/lib/subcmd/ | 162 | SUBCMD_DIR = $(srctree)/tools/lib/subcmd/ |
160 | 163 | ||
161 | # include config/Makefile by default and rule out | 164 | # include Makefile.config by default and rule out |
162 | # non-config cases | 165 | # non-config cases |
163 | config := 1 | 166 | config := 1 |
164 | 167 | ||
@@ -180,7 +183,7 @@ ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump) | |||
180 | FEATURE_TESTS := all | 183 | FEATURE_TESTS := all |
181 | endif | 184 | endif |
182 | endif | 185 | endif |
183 | include config/Makefile | 186 | include Makefile.config |
184 | endif | 187 | endif |
185 | 188 | ||
186 | ifeq ($(config),0) | 189 | ifeq ($(config),0) |
@@ -254,7 +257,8 @@ PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) | |||
254 | PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) | 257 | PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) |
255 | 258 | ||
256 | $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) | 259 | $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) |
257 | $(QUIET_GEN)CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ | 260 | $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \ |
261 | CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ | ||
258 | $(PYTHON_WORD) util/setup.py \ | 262 | $(PYTHON_WORD) util/setup.py \ |
259 | --quiet build_ext; \ | 263 | --quiet build_ext; \ |
260 | mkdir -p $(OUTPUT)python && \ | 264 | mkdir -p $(OUTPUT)python && \ |
@@ -344,6 +348,87 @@ export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK | |||
344 | include $(srctree)/tools/build/Makefile.include | 348 | include $(srctree)/tools/build/Makefile.include |
345 | 349 | ||
346 | $(PERF_IN): prepare FORCE | 350 | $(PERF_IN): prepare FORCE |
351 | @(test -f ../../include/uapi/linux/perf_event.h && ( \ | ||
352 | (diff -B ../include/uapi/linux/perf_event.h ../../include/uapi/linux/perf_event.h >/dev/null) \ | ||
353 | || echo "Warning: tools/include/uapi/linux/perf_event.h differs from kernel" >&2 )) || true | ||
354 | @(test -f ../../include/linux/hash.h && ( \ | ||
355 | (diff -B ../include/linux/hash.h ../../include/linux/hash.h >/dev/null) \ | ||
356 | || echo "Warning: tools/include/linux/hash.h differs from kernel" >&2 )) || true | ||
357 | @(test -f ../../include/uapi/linux/hw_breakpoint.h && ( \ | ||
358 | (diff -B ../include/uapi/linux/hw_breakpoint.h ../../include/uapi/linux/hw_breakpoint.h >/dev/null) \ | ||
359 | || echo "Warning: tools/include/uapi/linux/hw_breakpoint.h differs from kernel" >&2 )) || true | ||
360 | @(test -f ../../arch/x86/include/asm/disabled-features.h && ( \ | ||
361 | (diff -B ../arch/x86/include/asm/disabled-features.h ../../arch/x86/include/asm/disabled-features.h >/dev/null) \ | ||
362 | || echo "Warning: tools/arch/x86/include/asm/disabled-features.h differs from kernel" >&2 )) || true | ||
363 | @(test -f ../../arch/x86/include/asm/required-features.h && ( \ | ||
364 | (diff -B ../arch/x86/include/asm/required-features.h ../../arch/x86/include/asm/required-features.h >/dev/null) \ | ||
365 | || echo "Warning: tools/arch/x86/include/asm/required-features.h differs from kernel" >&2 )) || true | ||
366 | @(test -f ../../arch/x86/include/asm/cpufeatures.h && ( \ | ||
367 | (diff -B ../arch/x86/include/asm/cpufeatures.h ../../arch/x86/include/asm/cpufeatures.h >/dev/null) \ | ||
368 | || echo "Warning: tools/arch/x86/include/asm/cpufeatures.h differs from kernel" >&2 )) || true | ||
369 | @(test -f ../../arch/x86/lib/memcpy_64.S && ( \ | ||
370 | (diff -B ../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memcpy_64.S >/dev/null) \ | ||
371 | || echo "Warning: tools/arch/x86/lib/memcpy_64.S differs from kernel" >&2 )) || true | ||
372 | @(test -f ../../arch/x86/lib/memset_64.S && ( \ | ||
373 | (diff -B ../arch/x86/lib/memset_64.S ../../arch/x86/lib/memset_64.S >/dev/null) \ | ||
374 | || echo "Warning: tools/arch/x86/lib/memset_64.S differs from kernel" >&2 )) || true | ||
375 | @(test -f ../../arch/arm/include/uapi/asm/perf_regs.h && ( \ | ||
376 | (diff -B ../arch/arm/include/uapi/asm/perf_regs.h ../../arch/arm/include/uapi/asm/perf_regs.h >/dev/null) \ | ||
377 | || echo "Warning: tools/arch/arm/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true | ||
378 | @(test -f ../../arch/arm64/include/uapi/asm/perf_regs.h && ( \ | ||
379 | (diff -B ../arch/arm64/include/uapi/asm/perf_regs.h ../../arch/arm64/include/uapi/asm/perf_regs.h >/dev/null) \ | ||
380 | || echo "Warning: tools/arch/arm64/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true | ||
381 | @(test -f ../../arch/powerpc/include/uapi/asm/perf_regs.h && ( \ | ||
382 | (diff -B ../arch/powerpc/include/uapi/asm/perf_regs.h ../../arch/powerpc/include/uapi/asm/perf_regs.h >/dev/null) \ | ||
383 | || echo "Warning: tools/arch/powerpc/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true | ||
384 | @(test -f ../../arch/x86/include/uapi/asm/perf_regs.h && ( \ | ||
385 | (diff -B ../arch/x86/include/uapi/asm/perf_regs.h ../../arch/x86/include/uapi/asm/perf_regs.h >/dev/null) \ | ||
386 | || echo "Warning: tools/arch/x86/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true | ||
387 | @(test -f ../../arch/x86/include/uapi/asm/kvm.h && ( \ | ||
388 | (diff -B ../arch/x86/include/uapi/asm/kvm.h ../../arch/x86/include/uapi/asm/kvm.h >/dev/null) \ | ||
389 | || echo "Warning: tools/arch/x86/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true | ||
390 | @(test -f ../../arch/x86/include/uapi/asm/kvm_perf.h && ( \ | ||
391 | (diff -B ../arch/x86/include/uapi/asm/kvm_perf.h ../../arch/x86/include/uapi/asm/kvm_perf.h >/dev/null) \ | ||
392 | || echo "Warning: tools/arch/x86/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true | ||
393 | @(test -f ../../arch/x86/include/uapi/asm/svm.h && ( \ | ||
394 | (diff -B ../arch/x86/include/uapi/asm/svm.h ../../arch/x86/include/uapi/asm/svm.h >/dev/null) \ | ||
395 | || echo "Warning: tools/arch/x86/include/uapi/asm/svm.h differs from kernel" >&2 )) || true | ||
396 | @(test -f ../../arch/x86/include/uapi/asm/vmx.h && ( \ | ||
397 | (diff -B ../arch/x86/include/uapi/asm/vmx.h ../../arch/x86/include/uapi/asm/vmx.h >/dev/null) \ | ||
398 | || echo "Warning: tools/arch/x86/include/uapi/asm/vmx.h differs from kernel" >&2 )) || true | ||
399 | @(test -f ../../arch/powerpc/include/uapi/asm/kvm.h && ( \ | ||
400 | (diff -B ../arch/powerpc/include/uapi/asm/kvm.h ../../arch/powerpc/include/uapi/asm/kvm.h >/dev/null) \ | ||
401 | || echo "Warning: tools/arch/powerpc/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true | ||
402 | @(test -f ../../arch/s390/include/uapi/asm/kvm.h && ( \ | ||
403 | (diff -B ../arch/s390/include/uapi/asm/kvm.h ../../arch/s390/include/uapi/asm/kvm.h >/dev/null) \ | ||
404 | || echo "Warning: tools/arch/s390/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true | ||
405 | @(test -f ../../arch/s390/include/uapi/asm/kvm_perf.h && ( \ | ||
406 | (diff -B ../arch/s390/include/uapi/asm/kvm_perf.h ../../arch/s390/include/uapi/asm/kvm_perf.h >/dev/null) \ | ||
407 | || echo "Warning: tools/arch/s390/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true | ||
408 | @(test -f ../../arch/s390/include/uapi/asm/sie.h && ( \ | ||
409 | (diff -B ../arch/s390/include/uapi/asm/sie.h ../../arch/s390/include/uapi/asm/sie.h >/dev/null) \ | ||
410 | || echo "Warning: tools/arch/s390/include/uapi/asm/sie.h differs from kernel" >&2 )) || true | ||
411 | @(test -f ../../arch/arm/include/uapi/asm/kvm.h && ( \ | ||
412 | (diff -B ../arch/arm/include/uapi/asm/kvm.h ../../arch/arm/include/uapi/asm/kvm.h >/dev/null) \ | ||
413 | || echo "Warning: tools/arch/arm/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true | ||
414 | @(test -f ../../arch/arm64/include/uapi/asm/kvm.h && ( \ | ||
415 | (diff -B ../arch/arm64/include/uapi/asm/kvm.h ../../arch/arm64/include/uapi/asm/kvm.h >/dev/null) \ | ||
416 | || echo "Warning: tools/arch/arm64/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true | ||
417 | @(test -f ../../include/asm-generic/bitops/arch_hweight.h && ( \ | ||
418 | (diff -B ../include/asm-generic/bitops/arch_hweight.h ../../include/asm-generic/bitops/arch_hweight.h >/dev/null) \ | ||
419 | || echo "Warning: tools/include/asm-generic/bitops/arch_hweight.h differs from kernel" >&2 )) || true | ||
420 | @(test -f ../../include/asm-generic/bitops/const_hweight.h && ( \ | ||
421 | (diff -B ../include/asm-generic/bitops/const_hweight.h ../../include/asm-generic/bitops/const_hweight.h >/dev/null) \ | ||
422 | || echo "Warning: tools/include/asm-generic/bitops/const_hweight.h differs from kernel" >&2 )) || true | ||
423 | @(test -f ../../include/asm-generic/bitops/__fls.h && ( \ | ||
424 | (diff -B ../include/asm-generic/bitops/__fls.h ../../include/asm-generic/bitops/__fls.h >/dev/null) \ | ||
425 | || echo "Warning: tools/include/asm-generic/bitops/__fls.h differs from kernel" >&2 )) || true | ||
426 | @(test -f ../../include/asm-generic/bitops/fls.h && ( \ | ||
427 | (diff -B ../include/asm-generic/bitops/fls.h ../../include/asm-generic/bitops/fls.h >/dev/null) \ | ||
428 | || echo "Warning: tools/include/asm-generic/bitops/fls.h differs from kernel" >&2 )) || true | ||
429 | @(test -f ../../include/asm-generic/bitops/fls64.h && ( \ | ||
430 | (diff -B ../include/asm-generic/bitops/fls64.h ../../include/asm-generic/bitops/fls64.h >/dev/null) \ | ||
431 | || echo "Warning: tools/include/asm-generic/bitops/fls64.h differs from kernel" >&2 )) || true | ||
347 | $(Q)$(MAKE) $(build)=perf | 432 | $(Q)$(MAKE) $(build)=perf |
348 | 433 | ||
349 | $(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) | 434 | $(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) |
@@ -621,7 +706,7 @@ $(INSTALL_DOC_TARGETS): | |||
621 | ### Cleaning rules | 706 | ### Cleaning rules |
622 | 707 | ||
623 | # | 708 | # |
624 | # This is here, not in config/Makefile, because config/Makefile does | 709 | # This is here, not in Makefile.config, because Makefile.config does |
625 | # not get included for the clean target: | 710 | # not get included for the clean target: |
626 | # | 711 | # |
627 | config-clean: | 712 | config-clean: |
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build index d22e3d07de3d..f98da17357c0 100644 --- a/tools/perf/arch/arm/util/Build +++ b/tools/perf/arch/arm/util/Build | |||
@@ -1,4 +1,4 @@ | |||
1 | libperf-$(CONFIG_DWARF) += dwarf-regs.o | 1 | libperf-$(CONFIG_DWARF) += dwarf-regs.o |
2 | 2 | ||
3 | libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o | 3 | libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o |
4 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o | 4 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o |
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build index e58123a8912b..02f41dba4f4f 100644 --- a/tools/perf/arch/arm64/util/Build +++ b/tools/perf/arch/arm64/util/Build | |||
@@ -1,2 +1,2 @@ | |||
1 | libperf-$(CONFIG_DWARF) += dwarf-regs.o | 1 | libperf-$(CONFIG_DWARF) += dwarf-regs.o |
2 | libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o | 2 | libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o |
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c index a87afa91a99e..c116b713f7f7 100644 --- a/tools/perf/arch/arm64/util/unwind-libunwind.c +++ b/tools/perf/arch/arm64/util/unwind-libunwind.c | |||
@@ -1,11 +1,13 @@ | |||
1 | 1 | ||
2 | #ifndef REMOTE_UNWIND_LIBUNWIND | ||
2 | #include <errno.h> | 3 | #include <errno.h> |
3 | #include <libunwind.h> | 4 | #include <libunwind.h> |
4 | #include "perf_regs.h" | 5 | #include "perf_regs.h" |
5 | #include "../../util/unwind.h" | 6 | #include "../../util/unwind.h" |
6 | #include "../../util/debug.h" | 7 | #include "../../util/debug.h" |
8 | #endif | ||
7 | 9 | ||
8 | int libunwind__arch_reg_id(int regnum) | 10 | int LIBUNWIND__ARCH_REG_ID(int regnum) |
9 | { | 11 | { |
10 | switch (regnum) { | 12 | switch (regnum) { |
11 | case UNW_AARCH64_X0: | 13 | case UNW_AARCH64_X0: |
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index e83c8ce24303..886dd2aaff0d 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include <stdio.h> | 1 | #include <stdio.h> |
2 | #include <sys/utsname.h> | 2 | #include <sys/utsname.h> |
3 | #include "common.h" | 3 | #include "common.h" |
4 | #include "../util/util.h" | ||
4 | #include "../util/debug.h" | 5 | #include "../util/debug.h" |
5 | 6 | ||
6 | const char *const arm_triplets[] = { | 7 | const char *const arm_triplets[] = { |
@@ -9,34 +10,44 @@ const char *const arm_triplets[] = { | |||
9 | "arm-unknown-linux-", | 10 | "arm-unknown-linux-", |
10 | "arm-unknown-linux-gnu-", | 11 | "arm-unknown-linux-gnu-", |
11 | "arm-unknown-linux-gnueabi-", | 12 | "arm-unknown-linux-gnueabi-", |
13 | "arm-linux-gnu-", | ||
14 | "arm-linux-gnueabihf-", | ||
15 | "arm-none-eabi-", | ||
12 | NULL | 16 | NULL |
13 | }; | 17 | }; |
14 | 18 | ||
15 | const char *const arm64_triplets[] = { | 19 | const char *const arm64_triplets[] = { |
16 | "aarch64-linux-android-", | 20 | "aarch64-linux-android-", |
21 | "aarch64-linux-gnu-", | ||
17 | NULL | 22 | NULL |
18 | }; | 23 | }; |
19 | 24 | ||
20 | const char *const powerpc_triplets[] = { | 25 | const char *const powerpc_triplets[] = { |
21 | "powerpc-unknown-linux-gnu-", | 26 | "powerpc-unknown-linux-gnu-", |
22 | "powerpc64-unknown-linux-gnu-", | 27 | "powerpc64-unknown-linux-gnu-", |
28 | "powerpc64-linux-gnu-", | ||
29 | "powerpc64le-linux-gnu-", | ||
23 | NULL | 30 | NULL |
24 | }; | 31 | }; |
25 | 32 | ||
26 | const char *const s390_triplets[] = { | 33 | const char *const s390_triplets[] = { |
27 | "s390-ibm-linux-", | 34 | "s390-ibm-linux-", |
35 | "s390x-linux-gnu-", | ||
28 | NULL | 36 | NULL |
29 | }; | 37 | }; |
30 | 38 | ||
31 | const char *const sh_triplets[] = { | 39 | const char *const sh_triplets[] = { |
32 | "sh-unknown-linux-gnu-", | 40 | "sh-unknown-linux-gnu-", |
33 | "sh64-unknown-linux-gnu-", | 41 | "sh64-unknown-linux-gnu-", |
42 | "sh-linux-gnu-", | ||
43 | "sh64-linux-gnu-", | ||
34 | NULL | 44 | NULL |
35 | }; | 45 | }; |
36 | 46 | ||
37 | const char *const sparc_triplets[] = { | 47 | const char *const sparc_triplets[] = { |
38 | "sparc-unknown-linux-gnu-", | 48 | "sparc-unknown-linux-gnu-", |
39 | "sparc64-unknown-linux-gnu-", | 49 | "sparc64-unknown-linux-gnu-", |
50 | "sparc64-linux-gnu-", | ||
40 | NULL | 51 | NULL |
41 | }; | 52 | }; |
42 | 53 | ||
@@ -49,12 +60,19 @@ const char *const x86_triplets[] = { | |||
49 | "i386-pc-linux-gnu-", | 60 | "i386-pc-linux-gnu-", |
50 | "i686-linux-android-", | 61 | "i686-linux-android-", |
51 | "i686-android-linux-", | 62 | "i686-android-linux-", |
63 | "x86_64-linux-gnu-", | ||
64 | "i586-linux-gnu-", | ||
52 | NULL | 65 | NULL |
53 | }; | 66 | }; |
54 | 67 | ||
55 | const char *const mips_triplets[] = { | 68 | const char *const mips_triplets[] = { |
56 | "mips-unknown-linux-gnu-", | 69 | "mips-unknown-linux-gnu-", |
57 | "mipsel-linux-android-", | 70 | "mipsel-linux-android-", |
71 | "mips-linux-gnu-", | ||
72 | "mips64-linux-gnu-", | ||
73 | "mips64el-linux-gnuabi64-", | ||
74 | "mips64-linux-gnuabi64-", | ||
75 | "mipsel-linux-gnu-", | ||
58 | NULL | 76 | NULL |
59 | }; | 77 | }; |
60 | 78 | ||
@@ -102,7 +120,7 @@ static int lookup_triplets(const char *const *triplets, const char *name) | |||
102 | * Return architecture name in a normalized form. | 120 | * Return architecture name in a normalized form. |
103 | * The conversion logic comes from the Makefile. | 121 | * The conversion logic comes from the Makefile. |
104 | */ | 122 | */ |
105 | static const char *normalize_arch(char *arch) | 123 | const char *normalize_arch(char *arch) |
106 | { | 124 | { |
107 | if (!strcmp(arch, "x86_64")) | 125 | if (!strcmp(arch, "x86_64")) |
108 | return "x86"; | 126 | return "x86"; |
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h index 7529cfb143ce..6b01c736b7d9 100644 --- a/tools/perf/arch/common.h +++ b/tools/perf/arch/common.h | |||
@@ -6,5 +6,6 @@ | |||
6 | extern const char *objdump_path; | 6 | extern const char *objdump_path; |
7 | 7 | ||
8 | int perf_env__lookup_objdump(struct perf_env *env); | 8 | int perf_env__lookup_objdump(struct perf_env *env); |
9 | const char *normalize_arch(char *arch); | ||
9 | 10 | ||
10 | #endif /* ARCH_PERF_COMMON_H */ | 11 | #endif /* ARCH_PERF_COMMON_H */ |
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build index 8a61372bb47a..5bd7b9260cc0 100644 --- a/tools/perf/arch/s390/util/Build +++ b/tools/perf/arch/s390/util/Build | |||
@@ -2,3 +2,5 @@ libperf-y += header.o | |||
2 | libperf-y += kvm-stat.o | 2 | libperf-y += kvm-stat.o |
3 | 3 | ||
4 | libperf-$(CONFIG_DWARF) += dwarf-regs.o | 4 | libperf-$(CONFIG_DWARF) += dwarf-regs.o |
5 | |||
6 | libperf-y += machine.o | ||
diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c new file mode 100644 index 000000000000..b9a95a1a8e69 --- /dev/null +++ b/tools/perf/arch/s390/util/machine.c | |||
@@ -0,0 +1,19 @@ | |||
1 | #include <unistd.h> | ||
2 | #include <stdio.h> | ||
3 | #include <string.h> | ||
4 | #include "util.h" | ||
5 | #include "machine.h" | ||
6 | #include "api/fs/fs.h" | ||
7 | |||
8 | int arch__fix_module_text_start(u64 *start, const char *name) | ||
9 | { | ||
10 | char path[PATH_MAX]; | ||
11 | |||
12 | snprintf(path, PATH_MAX, "module/%.*s/sections/.text", | ||
13 | (int)strlen(name) - 2, name + 1); | ||
14 | |||
15 | if (sysfs__read_ull(path, (unsigned long long *)start) < 0) | ||
16 | return -1; | ||
17 | |||
18 | return 0; | ||
19 | } | ||
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl index cac6d17ce5db..555263e385c9 100644 --- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl +++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl | |||
@@ -374,3 +374,5 @@ | |||
374 | 543 x32 io_setup compat_sys_io_setup | 374 | 543 x32 io_setup compat_sys_io_setup |
375 | 544 x32 io_submit compat_sys_io_submit | 375 | 544 x32 io_submit compat_sys_io_submit |
376 | 545 x32 execveat compat_sys_execveat/ptregs | 376 | 545 x32 execveat compat_sys_execveat/ptregs |
377 | 534 x32 preadv2 compat_sys_preadv2 | ||
378 | 535 x32 pwritev2 compat_sys_pwritev2 | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-32.c b/tools/perf/arch/x86/tests/insn-x86-dat-32.c index 3b491cfe204e..0f196eec9f48 100644 --- a/tools/perf/arch/x86/tests/insn-x86-dat-32.c +++ b/tools/perf/arch/x86/tests/insn-x86-dat-32.c | |||
@@ -6,6 +6,1016 @@ | |||
6 | 6 | ||
7 | {{0x0f, 0x31, }, 2, 0, "", "", | 7 | {{0x0f, 0x31, }, 2, 0, "", "", |
8 | "0f 31 \trdtsc ",}, | 8 | "0f 31 \trdtsc ",}, |
9 | {{0xc4, 0xe2, 0x7d, 0x13, 0xeb, }, 5, 0, "", "", | ||
10 | "c4 e2 7d 13 eb \tvcvtph2ps %xmm3,%ymm5",}, | ||
11 | {{0x62, 0x81, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
12 | "62 81 78 56 34 12 \tbound %eax,0x12345678(%ecx)",}, | ||
13 | {{0x62, 0x88, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
14 | "62 88 78 56 34 12 \tbound %ecx,0x12345678(%eax)",}, | ||
15 | {{0x62, 0x90, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
16 | "62 90 78 56 34 12 \tbound %edx,0x12345678(%eax)",}, | ||
17 | {{0x62, 0x98, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
18 | "62 98 78 56 34 12 \tbound %ebx,0x12345678(%eax)",}, | ||
19 | {{0x62, 0xa0, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
20 | "62 a0 78 56 34 12 \tbound %esp,0x12345678(%eax)",}, | ||
21 | {{0x62, 0xa8, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
22 | "62 a8 78 56 34 12 \tbound %ebp,0x12345678(%eax)",}, | ||
23 | {{0x62, 0xb0, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
24 | "62 b0 78 56 34 12 \tbound %esi,0x12345678(%eax)",}, | ||
25 | {{0x62, 0xb8, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
26 | "62 b8 78 56 34 12 \tbound %edi,0x12345678(%eax)",}, | ||
27 | {{0x62, 0x08, }, 2, 0, "", "", | ||
28 | "62 08 \tbound %ecx,(%eax)",}, | ||
29 | {{0x62, 0x05, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
30 | "62 05 78 56 34 12 \tbound %eax,0x12345678",}, | ||
31 | {{0x62, 0x14, 0x01, }, 3, 0, "", "", | ||
32 | "62 14 01 \tbound %edx,(%ecx,%eax,1)",}, | ||
33 | {{0x62, 0x14, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
34 | "62 14 05 78 56 34 12 \tbound %edx,0x12345678(,%eax,1)",}, | ||
35 | {{0x62, 0x14, 0x08, }, 3, 0, "", "", | ||
36 | "62 14 08 \tbound %edx,(%eax,%ecx,1)",}, | ||
37 | {{0x62, 0x14, 0xc8, }, 3, 0, "", "", | ||
38 | "62 14 c8 \tbound %edx,(%eax,%ecx,8)",}, | ||
39 | {{0x62, 0x50, 0x12, }, 3, 0, "", "", | ||
40 | "62 50 12 \tbound %edx,0x12(%eax)",}, | ||
41 | {{0x62, 0x55, 0x12, }, 3, 0, "", "", | ||
42 | "62 55 12 \tbound %edx,0x12(%ebp)",}, | ||
43 | {{0x62, 0x54, 0x01, 0x12, }, 4, 0, "", "", | ||
44 | "62 54 01 12 \tbound %edx,0x12(%ecx,%eax,1)",}, | ||
45 | {{0x62, 0x54, 0x05, 0x12, }, 4, 0, "", "", | ||
46 | "62 54 05 12 \tbound %edx,0x12(%ebp,%eax,1)",}, | ||
47 | {{0x62, 0x54, 0x08, 0x12, }, 4, 0, "", "", | ||
48 | "62 54 08 12 \tbound %edx,0x12(%eax,%ecx,1)",}, | ||
49 | {{0x62, 0x54, 0xc8, 0x12, }, 4, 0, "", "", | ||
50 | "62 54 c8 12 \tbound %edx,0x12(%eax,%ecx,8)",}, | ||
51 | {{0x62, 0x90, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
52 | "62 90 78 56 34 12 \tbound %edx,0x12345678(%eax)",}, | ||
53 | {{0x62, 0x95, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "", | ||
54 | "62 95 78 56 34 12 \tbound %edx,0x12345678(%ebp)",}, | ||
55 | {{0x62, 0x94, 0x01, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
56 | "62 94 01 78 56 34 12 \tbound %edx,0x12345678(%ecx,%eax,1)",}, | ||
57 | {{0x62, 0x94, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
58 | "62 94 05 78 56 34 12 \tbound %edx,0x12345678(%ebp,%eax,1)",}, | ||
59 | {{0x62, 0x94, 0x08, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
60 | "62 94 08 78 56 34 12 \tbound %edx,0x12345678(%eax,%ecx,1)",}, | ||
61 | {{0x62, 0x94, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
62 | "62 94 c8 78 56 34 12 \tbound %edx,0x12345678(%eax,%ecx,8)",}, | ||
63 | {{0x66, 0x62, 0x81, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
64 | "66 62 81 78 56 34 12 \tbound %ax,0x12345678(%ecx)",}, | ||
65 | {{0x66, 0x62, 0x88, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
66 | "66 62 88 78 56 34 12 \tbound %cx,0x12345678(%eax)",}, | ||
67 | {{0x66, 0x62, 0x90, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
68 | "66 62 90 78 56 34 12 \tbound %dx,0x12345678(%eax)",}, | ||
69 | {{0x66, 0x62, 0x98, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
70 | "66 62 98 78 56 34 12 \tbound %bx,0x12345678(%eax)",}, | ||
71 | {{0x66, 0x62, 0xa0, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
72 | "66 62 a0 78 56 34 12 \tbound %sp,0x12345678(%eax)",}, | ||
73 | {{0x66, 0x62, 0xa8, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
74 | "66 62 a8 78 56 34 12 \tbound %bp,0x12345678(%eax)",}, | ||
75 | {{0x66, 0x62, 0xb0, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
76 | "66 62 b0 78 56 34 12 \tbound %si,0x12345678(%eax)",}, | ||
77 | {{0x66, 0x62, 0xb8, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
78 | "66 62 b8 78 56 34 12 \tbound %di,0x12345678(%eax)",}, | ||
79 | {{0x66, 0x62, 0x08, }, 3, 0, "", "", | ||
80 | "66 62 08 \tbound %cx,(%eax)",}, | ||
81 | {{0x66, 0x62, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
82 | "66 62 05 78 56 34 12 \tbound %ax,0x12345678",}, | ||
83 | {{0x66, 0x62, 0x14, 0x01, }, 4, 0, "", "", | ||
84 | "66 62 14 01 \tbound %dx,(%ecx,%eax,1)",}, | ||
85 | {{0x66, 0x62, 0x14, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
86 | "66 62 14 05 78 56 34 12 \tbound %dx,0x12345678(,%eax,1)",}, | ||
87 | {{0x66, 0x62, 0x14, 0x08, }, 4, 0, "", "", | ||
88 | "66 62 14 08 \tbound %dx,(%eax,%ecx,1)",}, | ||
89 | {{0x66, 0x62, 0x14, 0xc8, }, 4, 0, "", "", | ||
90 | "66 62 14 c8 \tbound %dx,(%eax,%ecx,8)",}, | ||
91 | {{0x66, 0x62, 0x50, 0x12, }, 4, 0, "", "", | ||
92 | "66 62 50 12 \tbound %dx,0x12(%eax)",}, | ||
93 | {{0x66, 0x62, 0x55, 0x12, }, 4, 0, "", "", | ||
94 | "66 62 55 12 \tbound %dx,0x12(%ebp)",}, | ||
95 | {{0x66, 0x62, 0x54, 0x01, 0x12, }, 5, 0, "", "", | ||
96 | "66 62 54 01 12 \tbound %dx,0x12(%ecx,%eax,1)",}, | ||
97 | {{0x66, 0x62, 0x54, 0x05, 0x12, }, 5, 0, "", "", | ||
98 | "66 62 54 05 12 \tbound %dx,0x12(%ebp,%eax,1)",}, | ||
99 | {{0x66, 0x62, 0x54, 0x08, 0x12, }, 5, 0, "", "", | ||
100 | "66 62 54 08 12 \tbound %dx,0x12(%eax,%ecx,1)",}, | ||
101 | {{0x66, 0x62, 0x54, 0xc8, 0x12, }, 5, 0, "", "", | ||
102 | "66 62 54 c8 12 \tbound %dx,0x12(%eax,%ecx,8)",}, | ||
103 | {{0x66, 0x62, 0x90, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
104 | "66 62 90 78 56 34 12 \tbound %dx,0x12345678(%eax)",}, | ||
105 | {{0x66, 0x62, 0x95, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
106 | "66 62 95 78 56 34 12 \tbound %dx,0x12345678(%ebp)",}, | ||
107 | {{0x66, 0x62, 0x94, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
108 | "66 62 94 01 78 56 34 12 \tbound %dx,0x12345678(%ecx,%eax,1)",}, | ||
109 | {{0x66, 0x62, 0x94, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
110 | "66 62 94 05 78 56 34 12 \tbound %dx,0x12345678(%ebp,%eax,1)",}, | ||
111 | {{0x66, 0x62, 0x94, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
112 | "66 62 94 08 78 56 34 12 \tbound %dx,0x12345678(%eax,%ecx,1)",}, | ||
113 | {{0x66, 0x62, 0x94, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
114 | "66 62 94 c8 78 56 34 12 \tbound %dx,0x12345678(%eax,%ecx,8)",}, | ||
115 | {{0x0f, 0x41, 0xd8, }, 3, 0, "", "", | ||
116 | "0f 41 d8 \tcmovno %eax,%ebx",}, | ||
117 | {{0x0f, 0x41, 0x88, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
118 | "0f 41 88 78 56 34 12 \tcmovno 0x12345678(%eax),%ecx",}, | ||
119 | {{0x66, 0x0f, 0x41, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
120 | "66 0f 41 88 78 56 34 12 \tcmovno 0x12345678(%eax),%cx",}, | ||
121 | {{0x0f, 0x44, 0xd8, }, 3, 0, "", "", | ||
122 | "0f 44 d8 \tcmove %eax,%ebx",}, | ||
123 | {{0x0f, 0x44, 0x88, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
124 | "0f 44 88 78 56 34 12 \tcmove 0x12345678(%eax),%ecx",}, | ||
125 | {{0x66, 0x0f, 0x44, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
126 | "66 0f 44 88 78 56 34 12 \tcmove 0x12345678(%eax),%cx",}, | ||
127 | {{0x0f, 0x90, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
128 | "0f 90 80 78 56 34 12 \tseto 0x12345678(%eax)",}, | ||
129 | {{0x0f, 0x91, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
130 | "0f 91 80 78 56 34 12 \tsetno 0x12345678(%eax)",}, | ||
131 | {{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
132 | "0f 92 80 78 56 34 12 \tsetb 0x12345678(%eax)",}, | ||
133 | {{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
134 | "0f 92 80 78 56 34 12 \tsetb 0x12345678(%eax)",}, | ||
135 | {{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
136 | "0f 92 80 78 56 34 12 \tsetb 0x12345678(%eax)",}, | ||
137 | {{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
138 | "0f 93 80 78 56 34 12 \tsetae 0x12345678(%eax)",}, | ||
139 | {{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
140 | "0f 93 80 78 56 34 12 \tsetae 0x12345678(%eax)",}, | ||
141 | {{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
142 | "0f 93 80 78 56 34 12 \tsetae 0x12345678(%eax)",}, | ||
143 | {{0x0f, 0x98, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
144 | "0f 98 80 78 56 34 12 \tsets 0x12345678(%eax)",}, | ||
145 | {{0x0f, 0x99, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
146 | "0f 99 80 78 56 34 12 \tsetns 0x12345678(%eax)",}, | ||
147 | {{0xc5, 0xcc, 0x41, 0xef, }, 4, 0, "", "", | ||
148 | "c5 cc 41 ef \tkandw %k7,%k6,%k5",}, | ||
149 | {{0xc4, 0xe1, 0xcc, 0x41, 0xef, }, 5, 0, "", "", | ||
150 | "c4 e1 cc 41 ef \tkandq %k7,%k6,%k5",}, | ||
151 | {{0xc5, 0xcd, 0x41, 0xef, }, 4, 0, "", "", | ||
152 | "c5 cd 41 ef \tkandb %k7,%k6,%k5",}, | ||
153 | {{0xc4, 0xe1, 0xcd, 0x41, 0xef, }, 5, 0, "", "", | ||
154 | "c4 e1 cd 41 ef \tkandd %k7,%k6,%k5",}, | ||
155 | {{0xc5, 0xcc, 0x42, 0xef, }, 4, 0, "", "", | ||
156 | "c5 cc 42 ef \tkandnw %k7,%k6,%k5",}, | ||
157 | {{0xc4, 0xe1, 0xcc, 0x42, 0xef, }, 5, 0, "", "", | ||
158 | "c4 e1 cc 42 ef \tkandnq %k7,%k6,%k5",}, | ||
159 | {{0xc5, 0xcd, 0x42, 0xef, }, 4, 0, "", "", | ||
160 | "c5 cd 42 ef \tkandnb %k7,%k6,%k5",}, | ||
161 | {{0xc4, 0xe1, 0xcd, 0x42, 0xef, }, 5, 0, "", "", | ||
162 | "c4 e1 cd 42 ef \tkandnd %k7,%k6,%k5",}, | ||
163 | {{0xc5, 0xf8, 0x44, 0xf7, }, 4, 0, "", "", | ||
164 | "c5 f8 44 f7 \tknotw %k7,%k6",}, | ||
165 | {{0xc4, 0xe1, 0xf8, 0x44, 0xf7, }, 5, 0, "", "", | ||
166 | "c4 e1 f8 44 f7 \tknotq %k7,%k6",}, | ||
167 | {{0xc5, 0xf9, 0x44, 0xf7, }, 4, 0, "", "", | ||
168 | "c5 f9 44 f7 \tknotb %k7,%k6",}, | ||
169 | {{0xc4, 0xe1, 0xf9, 0x44, 0xf7, }, 5, 0, "", "", | ||
170 | "c4 e1 f9 44 f7 \tknotd %k7,%k6",}, | ||
171 | {{0xc5, 0xcc, 0x45, 0xef, }, 4, 0, "", "", | ||
172 | "c5 cc 45 ef \tkorw %k7,%k6,%k5",}, | ||
173 | {{0xc4, 0xe1, 0xcc, 0x45, 0xef, }, 5, 0, "", "", | ||
174 | "c4 e1 cc 45 ef \tkorq %k7,%k6,%k5",}, | ||
175 | {{0xc5, 0xcd, 0x45, 0xef, }, 4, 0, "", "", | ||
176 | "c5 cd 45 ef \tkorb %k7,%k6,%k5",}, | ||
177 | {{0xc4, 0xe1, 0xcd, 0x45, 0xef, }, 5, 0, "", "", | ||
178 | "c4 e1 cd 45 ef \tkord %k7,%k6,%k5",}, | ||
179 | {{0xc5, 0xcc, 0x46, 0xef, }, 4, 0, "", "", | ||
180 | "c5 cc 46 ef \tkxnorw %k7,%k6,%k5",}, | ||
181 | {{0xc4, 0xe1, 0xcc, 0x46, 0xef, }, 5, 0, "", "", | ||
182 | "c4 e1 cc 46 ef \tkxnorq %k7,%k6,%k5",}, | ||
183 | {{0xc5, 0xcd, 0x46, 0xef, }, 4, 0, "", "", | ||
184 | "c5 cd 46 ef \tkxnorb %k7,%k6,%k5",}, | ||
185 | {{0xc4, 0xe1, 0xcd, 0x46, 0xef, }, 5, 0, "", "", | ||
186 | "c4 e1 cd 46 ef \tkxnord %k7,%k6,%k5",}, | ||
187 | {{0xc5, 0xcc, 0x47, 0xef, }, 4, 0, "", "", | ||
188 | "c5 cc 47 ef \tkxorw %k7,%k6,%k5",}, | ||
189 | {{0xc4, 0xe1, 0xcc, 0x47, 0xef, }, 5, 0, "", "", | ||
190 | "c4 e1 cc 47 ef \tkxorq %k7,%k6,%k5",}, | ||
191 | {{0xc5, 0xcd, 0x47, 0xef, }, 4, 0, "", "", | ||
192 | "c5 cd 47 ef \tkxorb %k7,%k6,%k5",}, | ||
193 | {{0xc4, 0xe1, 0xcd, 0x47, 0xef, }, 5, 0, "", "", | ||
194 | "c4 e1 cd 47 ef \tkxord %k7,%k6,%k5",}, | ||
195 | {{0xc5, 0xcc, 0x4a, 0xef, }, 4, 0, "", "", | ||
196 | "c5 cc 4a ef \tkaddw %k7,%k6,%k5",}, | ||
197 | {{0xc4, 0xe1, 0xcc, 0x4a, 0xef, }, 5, 0, "", "", | ||
198 | "c4 e1 cc 4a ef \tkaddq %k7,%k6,%k5",}, | ||
199 | {{0xc5, 0xcd, 0x4a, 0xef, }, 4, 0, "", "", | ||
200 | "c5 cd 4a ef \tkaddb %k7,%k6,%k5",}, | ||
201 | {{0xc4, 0xe1, 0xcd, 0x4a, 0xef, }, 5, 0, "", "", | ||
202 | "c4 e1 cd 4a ef \tkaddd %k7,%k6,%k5",}, | ||
203 | {{0xc5, 0xcd, 0x4b, 0xef, }, 4, 0, "", "", | ||
204 | "c5 cd 4b ef \tkunpckbw %k7,%k6,%k5",}, | ||
205 | {{0xc5, 0xcc, 0x4b, 0xef, }, 4, 0, "", "", | ||
206 | "c5 cc 4b ef \tkunpckwd %k7,%k6,%k5",}, | ||
207 | {{0xc4, 0xe1, 0xcc, 0x4b, 0xef, }, 5, 0, "", "", | ||
208 | "c4 e1 cc 4b ef \tkunpckdq %k7,%k6,%k5",}, | ||
209 | {{0xc5, 0xf8, 0x90, 0xee, }, 4, 0, "", "", | ||
210 | "c5 f8 90 ee \tkmovw %k6,%k5",}, | ||
211 | {{0xc5, 0xf8, 0x90, 0x29, }, 4, 0, "", "", | ||
212 | "c5 f8 90 29 \tkmovw (%ecx),%k5",}, | ||
213 | {{0xc5, 0xf8, 0x90, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 9, 0, "", "", | ||
214 | "c5 f8 90 ac c8 23 01 00 00 \tkmovw 0x123(%eax,%ecx,8),%k5",}, | ||
215 | {{0xc5, 0xf8, 0x91, 0x29, }, 4, 0, "", "", | ||
216 | "c5 f8 91 29 \tkmovw %k5,(%ecx)",}, | ||
217 | {{0xc5, 0xf8, 0x91, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 9, 0, "", "", | ||
218 | "c5 f8 91 ac c8 23 01 00 00 \tkmovw %k5,0x123(%eax,%ecx,8)",}, | ||
219 | {{0xc5, 0xf8, 0x92, 0xe8, }, 4, 0, "", "", | ||
220 | "c5 f8 92 e8 \tkmovw %eax,%k5",}, | ||
221 | {{0xc5, 0xf8, 0x92, 0xed, }, 4, 0, "", "", | ||
222 | "c5 f8 92 ed \tkmovw %ebp,%k5",}, | ||
223 | {{0xc5, 0xf8, 0x93, 0xc5, }, 4, 0, "", "", | ||
224 | "c5 f8 93 c5 \tkmovw %k5,%eax",}, | ||
225 | {{0xc5, 0xf8, 0x93, 0xed, }, 4, 0, "", "", | ||
226 | "c5 f8 93 ed \tkmovw %k5,%ebp",}, | ||
227 | {{0xc4, 0xe1, 0xf8, 0x90, 0xee, }, 5, 0, "", "", | ||
228 | "c4 e1 f8 90 ee \tkmovq %k6,%k5",}, | ||
229 | {{0xc4, 0xe1, 0xf8, 0x90, 0x29, }, 5, 0, "", "", | ||
230 | "c4 e1 f8 90 29 \tkmovq (%ecx),%k5",}, | ||
231 | {{0xc4, 0xe1, 0xf8, 0x90, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
232 | "c4 e1 f8 90 ac c8 23 01 00 00 \tkmovq 0x123(%eax,%ecx,8),%k5",}, | ||
233 | {{0xc4, 0xe1, 0xf8, 0x91, 0x29, }, 5, 0, "", "", | ||
234 | "c4 e1 f8 91 29 \tkmovq %k5,(%ecx)",}, | ||
235 | {{0xc4, 0xe1, 0xf8, 0x91, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
236 | "c4 e1 f8 91 ac c8 23 01 00 00 \tkmovq %k5,0x123(%eax,%ecx,8)",}, | ||
237 | {{0xc5, 0xf9, 0x90, 0xee, }, 4, 0, "", "", | ||
238 | "c5 f9 90 ee \tkmovb %k6,%k5",}, | ||
239 | {{0xc5, 0xf9, 0x90, 0x29, }, 4, 0, "", "", | ||
240 | "c5 f9 90 29 \tkmovb (%ecx),%k5",}, | ||
241 | {{0xc5, 0xf9, 0x90, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 9, 0, "", "", | ||
242 | "c5 f9 90 ac c8 23 01 00 00 \tkmovb 0x123(%eax,%ecx,8),%k5",}, | ||
243 | {{0xc5, 0xf9, 0x91, 0x29, }, 4, 0, "", "", | ||
244 | "c5 f9 91 29 \tkmovb %k5,(%ecx)",}, | ||
245 | {{0xc5, 0xf9, 0x91, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 9, 0, "", "", | ||
246 | "c5 f9 91 ac c8 23 01 00 00 \tkmovb %k5,0x123(%eax,%ecx,8)",}, | ||
247 | {{0xc5, 0xf9, 0x92, 0xe8, }, 4, 0, "", "", | ||
248 | "c5 f9 92 e8 \tkmovb %eax,%k5",}, | ||
249 | {{0xc5, 0xf9, 0x92, 0xed, }, 4, 0, "", "", | ||
250 | "c5 f9 92 ed \tkmovb %ebp,%k5",}, | ||
251 | {{0xc5, 0xf9, 0x93, 0xc5, }, 4, 0, "", "", | ||
252 | "c5 f9 93 c5 \tkmovb %k5,%eax",}, | ||
253 | {{0xc5, 0xf9, 0x93, 0xed, }, 4, 0, "", "", | ||
254 | "c5 f9 93 ed \tkmovb %k5,%ebp",}, | ||
255 | {{0xc4, 0xe1, 0xf9, 0x90, 0xee, }, 5, 0, "", "", | ||
256 | "c4 e1 f9 90 ee \tkmovd %k6,%k5",}, | ||
257 | {{0xc4, 0xe1, 0xf9, 0x90, 0x29, }, 5, 0, "", "", | ||
258 | "c4 e1 f9 90 29 \tkmovd (%ecx),%k5",}, | ||
259 | {{0xc4, 0xe1, 0xf9, 0x90, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
260 | "c4 e1 f9 90 ac c8 23 01 00 00 \tkmovd 0x123(%eax,%ecx,8),%k5",}, | ||
261 | {{0xc4, 0xe1, 0xf9, 0x91, 0x29, }, 5, 0, "", "", | ||
262 | "c4 e1 f9 91 29 \tkmovd %k5,(%ecx)",}, | ||
263 | {{0xc4, 0xe1, 0xf9, 0x91, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
264 | "c4 e1 f9 91 ac c8 23 01 00 00 \tkmovd %k5,0x123(%eax,%ecx,8)",}, | ||
265 | {{0xc5, 0xfb, 0x92, 0xe8, }, 4, 0, "", "", | ||
266 | "c5 fb 92 e8 \tkmovd %eax,%k5",}, | ||
267 | {{0xc5, 0xfb, 0x92, 0xed, }, 4, 0, "", "", | ||
268 | "c5 fb 92 ed \tkmovd %ebp,%k5",}, | ||
269 | {{0xc5, 0xfb, 0x93, 0xc5, }, 4, 0, "", "", | ||
270 | "c5 fb 93 c5 \tkmovd %k5,%eax",}, | ||
271 | {{0xc5, 0xfb, 0x93, 0xed, }, 4, 0, "", "", | ||
272 | "c5 fb 93 ed \tkmovd %k5,%ebp",}, | ||
273 | {{0xc5, 0xf8, 0x98, 0xee, }, 4, 0, "", "", | ||
274 | "c5 f8 98 ee \tkortestw %k6,%k5",}, | ||
275 | {{0xc4, 0xe1, 0xf8, 0x98, 0xee, }, 5, 0, "", "", | ||
276 | "c4 e1 f8 98 ee \tkortestq %k6,%k5",}, | ||
277 | {{0xc5, 0xf9, 0x98, 0xee, }, 4, 0, "", "", | ||
278 | "c5 f9 98 ee \tkortestb %k6,%k5",}, | ||
279 | {{0xc4, 0xe1, 0xf9, 0x98, 0xee, }, 5, 0, "", "", | ||
280 | "c4 e1 f9 98 ee \tkortestd %k6,%k5",}, | ||
281 | {{0xc5, 0xf8, 0x99, 0xee, }, 4, 0, "", "", | ||
282 | "c5 f8 99 ee \tktestw %k6,%k5",}, | ||
283 | {{0xc4, 0xe1, 0xf8, 0x99, 0xee, }, 5, 0, "", "", | ||
284 | "c4 e1 f8 99 ee \tktestq %k6,%k5",}, | ||
285 | {{0xc5, 0xf9, 0x99, 0xee, }, 4, 0, "", "", | ||
286 | "c5 f9 99 ee \tktestb %k6,%k5",}, | ||
287 | {{0xc4, 0xe1, 0xf9, 0x99, 0xee, }, 5, 0, "", "", | ||
288 | "c4 e1 f9 99 ee \tktestd %k6,%k5",}, | ||
289 | {{0xc4, 0xe3, 0xf9, 0x30, 0xee, 0x12, }, 6, 0, "", "", | ||
290 | "c4 e3 f9 30 ee 12 \tkshiftrw $0x12,%k6,%k5",}, | ||
291 | {{0xc4, 0xe3, 0xf9, 0x31, 0xee, 0x5b, }, 6, 0, "", "", | ||
292 | "c4 e3 f9 31 ee 5b \tkshiftrq $0x5b,%k6,%k5",}, | ||
293 | {{0xc4, 0xe3, 0xf9, 0x32, 0xee, 0x12, }, 6, 0, "", "", | ||
294 | "c4 e3 f9 32 ee 12 \tkshiftlw $0x12,%k6,%k5",}, | ||
295 | {{0xc4, 0xe3, 0xf9, 0x33, 0xee, 0x5b, }, 6, 0, "", "", | ||
296 | "c4 e3 f9 33 ee 5b \tkshiftlq $0x5b,%k6,%k5",}, | ||
297 | {{0xc5, 0xf8, 0x5b, 0xf5, }, 4, 0, "", "", | ||
298 | "c5 f8 5b f5 \tvcvtdq2ps %xmm5,%xmm6",}, | ||
299 | {{0x62, 0xf1, 0xfc, 0x4f, 0x5b, 0xf5, }, 6, 0, "", "", | ||
300 | "62 f1 fc 4f 5b f5 \tvcvtqq2ps %zmm5,%ymm6{%k7}",}, | ||
301 | {{0xc5, 0xf9, 0x5b, 0xf5, }, 4, 0, "", "", | ||
302 | "c5 f9 5b f5 \tvcvtps2dq %xmm5,%xmm6",}, | ||
303 | {{0xc5, 0xfa, 0x5b, 0xf5, }, 4, 0, "", "", | ||
304 | "c5 fa 5b f5 \tvcvttps2dq %xmm5,%xmm6",}, | ||
305 | {{0x0f, 0x6f, 0xe0, }, 3, 0, "", "", | ||
306 | "0f 6f e0 \tmovq %mm0,%mm4",}, | ||
307 | {{0xc5, 0xfd, 0x6f, 0xf4, }, 4, 0, "", "", | ||
308 | "c5 fd 6f f4 \tvmovdqa %ymm4,%ymm6",}, | ||
309 | {{0x62, 0xf1, 0x7d, 0x48, 0x6f, 0xf5, }, 6, 0, "", "", | ||
310 | "62 f1 7d 48 6f f5 \tvmovdqa32 %zmm5,%zmm6",}, | ||
311 | {{0x62, 0xf1, 0xfd, 0x48, 0x6f, 0xf5, }, 6, 0, "", "", | ||
312 | "62 f1 fd 48 6f f5 \tvmovdqa64 %zmm5,%zmm6",}, | ||
313 | {{0xc5, 0xfe, 0x6f, 0xf4, }, 4, 0, "", "", | ||
314 | "c5 fe 6f f4 \tvmovdqu %ymm4,%ymm6",}, | ||
315 | {{0x62, 0xf1, 0x7e, 0x48, 0x6f, 0xf5, }, 6, 0, "", "", | ||
316 | "62 f1 7e 48 6f f5 \tvmovdqu32 %zmm5,%zmm6",}, | ||
317 | {{0x62, 0xf1, 0xfe, 0x48, 0x6f, 0xf5, }, 6, 0, "", "", | ||
318 | "62 f1 fe 48 6f f5 \tvmovdqu64 %zmm5,%zmm6",}, | ||
319 | {{0x62, 0xf1, 0x7f, 0x48, 0x6f, 0xf5, }, 6, 0, "", "", | ||
320 | "62 f1 7f 48 6f f5 \tvmovdqu8 %zmm5,%zmm6",}, | ||
321 | {{0x62, 0xf1, 0xff, 0x48, 0x6f, 0xf5, }, 6, 0, "", "", | ||
322 | "62 f1 ff 48 6f f5 \tvmovdqu16 %zmm5,%zmm6",}, | ||
323 | {{0x0f, 0x78, 0xc3, }, 3, 0, "", "", | ||
324 | "0f 78 c3 \tvmread %eax,%ebx",}, | ||
325 | {{0x62, 0xf1, 0x7c, 0x48, 0x78, 0xf5, }, 6, 0, "", "", | ||
326 | "62 f1 7c 48 78 f5 \tvcvttps2udq %zmm5,%zmm6",}, | ||
327 | {{0x62, 0xf1, 0xfc, 0x4f, 0x78, 0xf5, }, 6, 0, "", "", | ||
328 | "62 f1 fc 4f 78 f5 \tvcvttpd2udq %zmm5,%ymm6{%k7}",}, | ||
329 | {{0x62, 0xf1, 0x7f, 0x08, 0x78, 0xc6, }, 6, 0, "", "", | ||
330 | "62 f1 7f 08 78 c6 \tvcvttsd2usi %xmm6,%eax",}, | ||
331 | {{0x62, 0xf1, 0x7e, 0x08, 0x78, 0xc6, }, 6, 0, "", "", | ||
332 | "62 f1 7e 08 78 c6 \tvcvttss2usi %xmm6,%eax",}, | ||
333 | {{0x62, 0xf1, 0x7d, 0x4f, 0x78, 0xf5, }, 6, 0, "", "", | ||
334 | "62 f1 7d 4f 78 f5 \tvcvttps2uqq %ymm5,%zmm6{%k7}",}, | ||
335 | {{0x62, 0xf1, 0xfd, 0x48, 0x78, 0xf5, }, 6, 0, "", "", | ||
336 | "62 f1 fd 48 78 f5 \tvcvttpd2uqq %zmm5,%zmm6",}, | ||
337 | {{0x0f, 0x79, 0xd8, }, 3, 0, "", "", | ||
338 | "0f 79 d8 \tvmwrite %eax,%ebx",}, | ||
339 | {{0x62, 0xf1, 0x7c, 0x48, 0x79, 0xf5, }, 6, 0, "", "", | ||
340 | "62 f1 7c 48 79 f5 \tvcvtps2udq %zmm5,%zmm6",}, | ||
341 | {{0x62, 0xf1, 0xfc, 0x4f, 0x79, 0xf5, }, 6, 0, "", "", | ||
342 | "62 f1 fc 4f 79 f5 \tvcvtpd2udq %zmm5,%ymm6{%k7}",}, | ||
343 | {{0x62, 0xf1, 0x7f, 0x08, 0x79, 0xc6, }, 6, 0, "", "", | ||
344 | "62 f1 7f 08 79 c6 \tvcvtsd2usi %xmm6,%eax",}, | ||
345 | {{0x62, 0xf1, 0x7e, 0x08, 0x79, 0xc6, }, 6, 0, "", "", | ||
346 | "62 f1 7e 08 79 c6 \tvcvtss2usi %xmm6,%eax",}, | ||
347 | {{0x62, 0xf1, 0x7d, 0x4f, 0x79, 0xf5, }, 6, 0, "", "", | ||
348 | "62 f1 7d 4f 79 f5 \tvcvtps2uqq %ymm5,%zmm6{%k7}",}, | ||
349 | {{0x62, 0xf1, 0xfd, 0x48, 0x79, 0xf5, }, 6, 0, "", "", | ||
350 | "62 f1 fd 48 79 f5 \tvcvtpd2uqq %zmm5,%zmm6",}, | ||
351 | {{0x62, 0xf1, 0x7e, 0x4f, 0x7a, 0xf5, }, 6, 0, "", "", | ||
352 | "62 f1 7e 4f 7a f5 \tvcvtudq2pd %ymm5,%zmm6{%k7}",}, | ||
353 | {{0x62, 0xf1, 0xfe, 0x48, 0x7a, 0xf5, }, 6, 0, "", "", | ||
354 | "62 f1 fe 48 7a f5 \tvcvtuqq2pd %zmm5,%zmm6",}, | ||
355 | {{0x62, 0xf1, 0x7f, 0x48, 0x7a, 0xf5, }, 6, 0, "", "", | ||
356 | "62 f1 7f 48 7a f5 \tvcvtudq2ps %zmm5,%zmm6",}, | ||
357 | {{0x62, 0xf1, 0xff, 0x4f, 0x7a, 0xf5, }, 6, 0, "", "", | ||
358 | "62 f1 ff 4f 7a f5 \tvcvtuqq2ps %zmm5,%ymm6{%k7}",}, | ||
359 | {{0x62, 0xf1, 0x7d, 0x4f, 0x7a, 0xf5, }, 6, 0, "", "", | ||
360 | "62 f1 7d 4f 7a f5 \tvcvttps2qq %ymm5,%zmm6{%k7}",}, | ||
361 | {{0x62, 0xf1, 0xfd, 0x48, 0x7a, 0xf5, }, 6, 0, "", "", | ||
362 | "62 f1 fd 48 7a f5 \tvcvttpd2qq %zmm5,%zmm6",}, | ||
363 | {{0x62, 0xf1, 0x57, 0x08, 0x7b, 0xf0, }, 6, 0, "", "", | ||
364 | "62 f1 57 08 7b f0 \tvcvtusi2sd %eax,%xmm5,%xmm6",}, | ||
365 | {{0x62, 0xf1, 0x56, 0x08, 0x7b, 0xf0, }, 6, 0, "", "", | ||
366 | "62 f1 56 08 7b f0 \tvcvtusi2ss %eax,%xmm5,%xmm6",}, | ||
367 | {{0x62, 0xf1, 0x7d, 0x4f, 0x7b, 0xf5, }, 6, 0, "", "", | ||
368 | "62 f1 7d 4f 7b f5 \tvcvtps2qq %ymm5,%zmm6{%k7}",}, | ||
369 | {{0x62, 0xf1, 0xfd, 0x48, 0x7b, 0xf5, }, 6, 0, "", "", | ||
370 | "62 f1 fd 48 7b f5 \tvcvtpd2qq %zmm5,%zmm6",}, | ||
371 | {{0x0f, 0x7f, 0xc4, }, 3, 0, "", "", | ||
372 | "0f 7f c4 \tmovq %mm0,%mm4",}, | ||
373 | {{0xc5, 0xfd, 0x7f, 0xee, }, 4, 0, "", "", | ||
374 | "c5 fd 7f ee \tvmovdqa %ymm5,%ymm6",}, | ||
375 | {{0x62, 0xf1, 0x7d, 0x48, 0x7f, 0xee, }, 6, 0, "", "", | ||
376 | "62 f1 7d 48 7f ee \tvmovdqa32 %zmm5,%zmm6",}, | ||
377 | {{0x62, 0xf1, 0xfd, 0x48, 0x7f, 0xee, }, 6, 0, "", "", | ||
378 | "62 f1 fd 48 7f ee \tvmovdqa64 %zmm5,%zmm6",}, | ||
379 | {{0xc5, 0xfe, 0x7f, 0xee, }, 4, 0, "", "", | ||
380 | "c5 fe 7f ee \tvmovdqu %ymm5,%ymm6",}, | ||
381 | {{0x62, 0xf1, 0x7e, 0x48, 0x7f, 0xee, }, 6, 0, "", "", | ||
382 | "62 f1 7e 48 7f ee \tvmovdqu32 %zmm5,%zmm6",}, | ||
383 | {{0x62, 0xf1, 0xfe, 0x48, 0x7f, 0xee, }, 6, 0, "", "", | ||
384 | "62 f1 fe 48 7f ee \tvmovdqu64 %zmm5,%zmm6",}, | ||
385 | {{0x62, 0xf1, 0x7f, 0x48, 0x7f, 0xee, }, 6, 0, "", "", | ||
386 | "62 f1 7f 48 7f ee \tvmovdqu8 %zmm5,%zmm6",}, | ||
387 | {{0x62, 0xf1, 0xff, 0x48, 0x7f, 0xee, }, 6, 0, "", "", | ||
388 | "62 f1 ff 48 7f ee \tvmovdqu16 %zmm5,%zmm6",}, | ||
389 | {{0x0f, 0xdb, 0xd1, }, 3, 0, "", "", | ||
390 | "0f db d1 \tpand %mm1,%mm2",}, | ||
391 | {{0x66, 0x0f, 0xdb, 0xd1, }, 4, 0, "", "", | ||
392 | "66 0f db d1 \tpand %xmm1,%xmm2",}, | ||
393 | {{0xc5, 0xcd, 0xdb, 0xd4, }, 4, 0, "", "", | ||
394 | "c5 cd db d4 \tvpand %ymm4,%ymm6,%ymm2",}, | ||
395 | {{0x62, 0xf1, 0x55, 0x48, 0xdb, 0xf4, }, 6, 0, "", "", | ||
396 | "62 f1 55 48 db f4 \tvpandd %zmm4,%zmm5,%zmm6",}, | ||
397 | {{0x62, 0xf1, 0xd5, 0x48, 0xdb, 0xf4, }, 6, 0, "", "", | ||
398 | "62 f1 d5 48 db f4 \tvpandq %zmm4,%zmm5,%zmm6",}, | ||
399 | {{0x0f, 0xdf, 0xd1, }, 3, 0, "", "", | ||
400 | "0f df d1 \tpandn %mm1,%mm2",}, | ||
401 | {{0x66, 0x0f, 0xdf, 0xd1, }, 4, 0, "", "", | ||
402 | "66 0f df d1 \tpandn %xmm1,%xmm2",}, | ||
403 | {{0xc5, 0xcd, 0xdf, 0xd4, }, 4, 0, "", "", | ||
404 | "c5 cd df d4 \tvpandn %ymm4,%ymm6,%ymm2",}, | ||
405 | {{0x62, 0xf1, 0x55, 0x48, 0xdf, 0xf4, }, 6, 0, "", "", | ||
406 | "62 f1 55 48 df f4 \tvpandnd %zmm4,%zmm5,%zmm6",}, | ||
407 | {{0x62, 0xf1, 0xd5, 0x48, 0xdf, 0xf4, }, 6, 0, "", "", | ||
408 | "62 f1 d5 48 df f4 \tvpandnq %zmm4,%zmm5,%zmm6",}, | ||
409 | {{0xc5, 0xf9, 0xe6, 0xd1, }, 4, 0, "", "", | ||
410 | "c5 f9 e6 d1 \tvcvttpd2dq %xmm1,%xmm2",}, | ||
411 | {{0xc5, 0xfa, 0xe6, 0xf5, }, 4, 0, "", "", | ||
412 | "c5 fa e6 f5 \tvcvtdq2pd %xmm5,%xmm6",}, | ||
413 | {{0x62, 0xf1, 0x7e, 0x4f, 0xe6, 0xf5, }, 6, 0, "", "", | ||
414 | "62 f1 7e 4f e6 f5 \tvcvtdq2pd %ymm5,%zmm6{%k7}",}, | ||
415 | {{0x62, 0xf1, 0xfe, 0x48, 0xe6, 0xf5, }, 6, 0, "", "", | ||
416 | "62 f1 fe 48 e6 f5 \tvcvtqq2pd %zmm5,%zmm6",}, | ||
417 | {{0xc5, 0xfb, 0xe6, 0xd1, }, 4, 0, "", "", | ||
418 | "c5 fb e6 d1 \tvcvtpd2dq %xmm1,%xmm2",}, | ||
419 | {{0x0f, 0xeb, 0xf4, }, 3, 0, "", "", | ||
420 | "0f eb f4 \tpor %mm4,%mm6",}, | ||
421 | {{0xc5, 0xcd, 0xeb, 0xd4, }, 4, 0, "", "", | ||
422 | "c5 cd eb d4 \tvpor %ymm4,%ymm6,%ymm2",}, | ||
423 | {{0x62, 0xf1, 0x55, 0x48, 0xeb, 0xf4, }, 6, 0, "", "", | ||
424 | "62 f1 55 48 eb f4 \tvpord %zmm4,%zmm5,%zmm6",}, | ||
425 | {{0x62, 0xf1, 0xd5, 0x48, 0xeb, 0xf4, }, 6, 0, "", "", | ||
426 | "62 f1 d5 48 eb f4 \tvporq %zmm4,%zmm5,%zmm6",}, | ||
427 | {{0x0f, 0xef, 0xf4, }, 3, 0, "", "", | ||
428 | "0f ef f4 \tpxor %mm4,%mm6",}, | ||
429 | {{0xc5, 0xcd, 0xef, 0xd4, }, 4, 0, "", "", | ||
430 | "c5 cd ef d4 \tvpxor %ymm4,%ymm6,%ymm2",}, | ||
431 | {{0x62, 0xf1, 0x55, 0x48, 0xef, 0xf4, }, 6, 0, "", "", | ||
432 | "62 f1 55 48 ef f4 \tvpxord %zmm4,%zmm5,%zmm6",}, | ||
433 | {{0x62, 0xf1, 0xd5, 0x48, 0xef, 0xf4, }, 6, 0, "", "", | ||
434 | "62 f1 d5 48 ef f4 \tvpxorq %zmm4,%zmm5,%zmm6",}, | ||
435 | {{0x66, 0x0f, 0x38, 0x10, 0xc1, }, 5, 0, "", "", | ||
436 | "66 0f 38 10 c1 \tpblendvb %xmm0,%xmm1,%xmm0",}, | ||
437 | {{0x62, 0xf2, 0xd5, 0x48, 0x10, 0xf4, }, 6, 0, "", "", | ||
438 | "62 f2 d5 48 10 f4 \tvpsrlvw %zmm4,%zmm5,%zmm6",}, | ||
439 | {{0x62, 0xf2, 0x7e, 0x4f, 0x10, 0xee, }, 6, 0, "", "", | ||
440 | "62 f2 7e 4f 10 ee \tvpmovuswb %zmm5,%ymm6{%k7}",}, | ||
441 | {{0x62, 0xf2, 0x7e, 0x4f, 0x11, 0xee, }, 6, 0, "", "", | ||
442 | "62 f2 7e 4f 11 ee \tvpmovusdb %zmm5,%xmm6{%k7}",}, | ||
443 | {{0x62, 0xf2, 0xd5, 0x48, 0x11, 0xf4, }, 6, 0, "", "", | ||
444 | "62 f2 d5 48 11 f4 \tvpsravw %zmm4,%zmm5,%zmm6",}, | ||
445 | {{0x62, 0xf2, 0x7e, 0x4f, 0x12, 0xee, }, 6, 0, "", "", | ||
446 | "62 f2 7e 4f 12 ee \tvpmovusqb %zmm5,%xmm6{%k7}",}, | ||
447 | {{0x62, 0xf2, 0xd5, 0x48, 0x12, 0xf4, }, 6, 0, "", "", | ||
448 | "62 f2 d5 48 12 f4 \tvpsllvw %zmm4,%zmm5,%zmm6",}, | ||
449 | {{0xc4, 0xe2, 0x7d, 0x13, 0xeb, }, 5, 0, "", "", | ||
450 | "c4 e2 7d 13 eb \tvcvtph2ps %xmm3,%ymm5",}, | ||
451 | {{0x62, 0xf2, 0x7d, 0x4f, 0x13, 0xf5, }, 6, 0, "", "", | ||
452 | "62 f2 7d 4f 13 f5 \tvcvtph2ps %ymm5,%zmm6{%k7}",}, | ||
453 | {{0x62, 0xf2, 0x7e, 0x4f, 0x13, 0xee, }, 6, 0, "", "", | ||
454 | "62 f2 7e 4f 13 ee \tvpmovusdw %zmm5,%ymm6{%k7}",}, | ||
455 | {{0x66, 0x0f, 0x38, 0x14, 0xc1, }, 5, 0, "", "", | ||
456 | "66 0f 38 14 c1 \tblendvps %xmm0,%xmm1,%xmm0",}, | ||
457 | {{0x62, 0xf2, 0x7e, 0x4f, 0x14, 0xee, }, 6, 0, "", "", | ||
458 | "62 f2 7e 4f 14 ee \tvpmovusqw %zmm5,%xmm6{%k7}",}, | ||
459 | {{0x62, 0xf2, 0x55, 0x48, 0x14, 0xf4, }, 6, 0, "", "", | ||
460 | "62 f2 55 48 14 f4 \tvprorvd %zmm4,%zmm5,%zmm6",}, | ||
461 | {{0x62, 0xf2, 0xd5, 0x48, 0x14, 0xf4, }, 6, 0, "", "", | ||
462 | "62 f2 d5 48 14 f4 \tvprorvq %zmm4,%zmm5,%zmm6",}, | ||
463 | {{0x66, 0x0f, 0x38, 0x15, 0xc1, }, 5, 0, "", "", | ||
464 | "66 0f 38 15 c1 \tblendvpd %xmm0,%xmm1,%xmm0",}, | ||
465 | {{0x62, 0xf2, 0x7e, 0x4f, 0x15, 0xee, }, 6, 0, "", "", | ||
466 | "62 f2 7e 4f 15 ee \tvpmovusqd %zmm5,%ymm6{%k7}",}, | ||
467 | {{0x62, 0xf2, 0x55, 0x48, 0x15, 0xf4, }, 6, 0, "", "", | ||
468 | "62 f2 55 48 15 f4 \tvprolvd %zmm4,%zmm5,%zmm6",}, | ||
469 | {{0x62, 0xf2, 0xd5, 0x48, 0x15, 0xf4, }, 6, 0, "", "", | ||
470 | "62 f2 d5 48 15 f4 \tvprolvq %zmm4,%zmm5,%zmm6",}, | ||
471 | {{0xc4, 0xe2, 0x4d, 0x16, 0xd4, }, 5, 0, "", "", | ||
472 | "c4 e2 4d 16 d4 \tvpermps %ymm4,%ymm6,%ymm2",}, | ||
473 | {{0x62, 0xf2, 0x4d, 0x2f, 0x16, 0xd4, }, 6, 0, "", "", | ||
474 | "62 f2 4d 2f 16 d4 \tvpermps %ymm4,%ymm6,%ymm2{%k7}",}, | ||
475 | {{0x62, 0xf2, 0xcd, 0x2f, 0x16, 0xd4, }, 6, 0, "", "", | ||
476 | "62 f2 cd 2f 16 d4 \tvpermpd %ymm4,%ymm6,%ymm2{%k7}",}, | ||
477 | {{0xc4, 0xe2, 0x7d, 0x19, 0xf4, }, 5, 0, "", "", | ||
478 | "c4 e2 7d 19 f4 \tvbroadcastsd %xmm4,%ymm6",}, | ||
479 | {{0x62, 0xf2, 0x7d, 0x48, 0x19, 0xf7, }, 6, 0, "", "", | ||
480 | "62 f2 7d 48 19 f7 \tvbroadcastf32x2 %xmm7,%zmm6",}, | ||
481 | {{0xc4, 0xe2, 0x7d, 0x1a, 0x21, }, 5, 0, "", "", | ||
482 | "c4 e2 7d 1a 21 \tvbroadcastf128 (%ecx),%ymm4",}, | ||
483 | {{0x62, 0xf2, 0x7d, 0x48, 0x1a, 0x31, }, 6, 0, "", "", | ||
484 | "62 f2 7d 48 1a 31 \tvbroadcastf32x4 (%ecx),%zmm6",}, | ||
485 | {{0x62, 0xf2, 0xfd, 0x48, 0x1a, 0x31, }, 6, 0, "", "", | ||
486 | "62 f2 fd 48 1a 31 \tvbroadcastf64x2 (%ecx),%zmm6",}, | ||
487 | {{0x62, 0xf2, 0x7d, 0x48, 0x1b, 0x31, }, 6, 0, "", "", | ||
488 | "62 f2 7d 48 1b 31 \tvbroadcastf32x8 (%ecx),%zmm6",}, | ||
489 | {{0x62, 0xf2, 0xfd, 0x48, 0x1b, 0x31, }, 6, 0, "", "", | ||
490 | "62 f2 fd 48 1b 31 \tvbroadcastf64x4 (%ecx),%zmm6",}, | ||
491 | {{0x62, 0xf2, 0xfd, 0x48, 0x1f, 0xf4, }, 6, 0, "", "", | ||
492 | "62 f2 fd 48 1f f4 \tvpabsq %zmm4,%zmm6",}, | ||
493 | {{0xc4, 0xe2, 0x79, 0x20, 0xec, }, 5, 0, "", "", | ||
494 | "c4 e2 79 20 ec \tvpmovsxbw %xmm4,%xmm5",}, | ||
495 | {{0x62, 0xf2, 0x7e, 0x4f, 0x20, 0xee, }, 6, 0, "", "", | ||
496 | "62 f2 7e 4f 20 ee \tvpmovswb %zmm5,%ymm6{%k7}",}, | ||
497 | {{0xc4, 0xe2, 0x7d, 0x21, 0xf4, }, 5, 0, "", "", | ||
498 | "c4 e2 7d 21 f4 \tvpmovsxbd %xmm4,%ymm6",}, | ||
499 | {{0x62, 0xf2, 0x7e, 0x4f, 0x21, 0xee, }, 6, 0, "", "", | ||
500 | "62 f2 7e 4f 21 ee \tvpmovsdb %zmm5,%xmm6{%k7}",}, | ||
501 | {{0xc4, 0xe2, 0x7d, 0x22, 0xe4, }, 5, 0, "", "", | ||
502 | "c4 e2 7d 22 e4 \tvpmovsxbq %xmm4,%ymm4",}, | ||
503 | {{0x62, 0xf2, 0x7e, 0x4f, 0x22, 0xee, }, 6, 0, "", "", | ||
504 | "62 f2 7e 4f 22 ee \tvpmovsqb %zmm5,%xmm6{%k7}",}, | ||
505 | {{0xc4, 0xe2, 0x7d, 0x23, 0xe4, }, 5, 0, "", "", | ||
506 | "c4 e2 7d 23 e4 \tvpmovsxwd %xmm4,%ymm4",}, | ||
507 | {{0x62, 0xf2, 0x7e, 0x4f, 0x23, 0xee, }, 6, 0, "", "", | ||
508 | "62 f2 7e 4f 23 ee \tvpmovsdw %zmm5,%ymm6{%k7}",}, | ||
509 | {{0xc4, 0xe2, 0x7d, 0x24, 0xf4, }, 5, 0, "", "", | ||
510 | "c4 e2 7d 24 f4 \tvpmovsxwq %xmm4,%ymm6",}, | ||
511 | {{0x62, 0xf2, 0x7e, 0x4f, 0x24, 0xee, }, 6, 0, "", "", | ||
512 | "62 f2 7e 4f 24 ee \tvpmovsqw %zmm5,%xmm6{%k7}",}, | ||
513 | {{0xc4, 0xe2, 0x7d, 0x25, 0xe4, }, 5, 0, "", "", | ||
514 | "c4 e2 7d 25 e4 \tvpmovsxdq %xmm4,%ymm4",}, | ||
515 | {{0x62, 0xf2, 0x7e, 0x4f, 0x25, 0xee, }, 6, 0, "", "", | ||
516 | "62 f2 7e 4f 25 ee \tvpmovsqd %zmm5,%ymm6{%k7}",}, | ||
517 | {{0x62, 0xf2, 0x4d, 0x48, 0x26, 0xed, }, 6, 0, "", "", | ||
518 | "62 f2 4d 48 26 ed \tvptestmb %zmm5,%zmm6,%k5",}, | ||
519 | {{0x62, 0xf2, 0xcd, 0x48, 0x26, 0xed, }, 6, 0, "", "", | ||
520 | "62 f2 cd 48 26 ed \tvptestmw %zmm5,%zmm6,%k5",}, | ||
521 | {{0x62, 0xf2, 0x56, 0x48, 0x26, 0xec, }, 6, 0, "", "", | ||
522 | "62 f2 56 48 26 ec \tvptestnmb %zmm4,%zmm5,%k5",}, | ||
523 | {{0x62, 0xf2, 0xd6, 0x48, 0x26, 0xec, }, 6, 0, "", "", | ||
524 | "62 f2 d6 48 26 ec \tvptestnmw %zmm4,%zmm5,%k5",}, | ||
525 | {{0x62, 0xf2, 0x4d, 0x48, 0x27, 0xed, }, 6, 0, "", "", | ||
526 | "62 f2 4d 48 27 ed \tvptestmd %zmm5,%zmm6,%k5",}, | ||
527 | {{0x62, 0xf2, 0xcd, 0x48, 0x27, 0xed, }, 6, 0, "", "", | ||
528 | "62 f2 cd 48 27 ed \tvptestmq %zmm5,%zmm6,%k5",}, | ||
529 | {{0x62, 0xf2, 0x56, 0x48, 0x27, 0xec, }, 6, 0, "", "", | ||
530 | "62 f2 56 48 27 ec \tvptestnmd %zmm4,%zmm5,%k5",}, | ||
531 | {{0x62, 0xf2, 0xd6, 0x48, 0x27, 0xec, }, 6, 0, "", "", | ||
532 | "62 f2 d6 48 27 ec \tvptestnmq %zmm4,%zmm5,%k5",}, | ||
533 | {{0xc4, 0xe2, 0x4d, 0x28, 0xd4, }, 5, 0, "", "", | ||
534 | "c4 e2 4d 28 d4 \tvpmuldq %ymm4,%ymm6,%ymm2",}, | ||
535 | {{0x62, 0xf2, 0x7e, 0x48, 0x28, 0xf5, }, 6, 0, "", "", | ||
536 | "62 f2 7e 48 28 f5 \tvpmovm2b %k5,%zmm6",}, | ||
537 | {{0x62, 0xf2, 0xfe, 0x48, 0x28, 0xf5, }, 6, 0, "", "", | ||
538 | "62 f2 fe 48 28 f5 \tvpmovm2w %k5,%zmm6",}, | ||
539 | {{0xc4, 0xe2, 0x4d, 0x29, 0xd4, }, 5, 0, "", "", | ||
540 | "c4 e2 4d 29 d4 \tvpcmpeqq %ymm4,%ymm6,%ymm2",}, | ||
541 | {{0x62, 0xf2, 0x7e, 0x48, 0x29, 0xee, }, 6, 0, "", "", | ||
542 | "62 f2 7e 48 29 ee \tvpmovb2m %zmm6,%k5",}, | ||
543 | {{0x62, 0xf2, 0xfe, 0x48, 0x29, 0xee, }, 6, 0, "", "", | ||
544 | "62 f2 fe 48 29 ee \tvpmovw2m %zmm6,%k5",}, | ||
545 | {{0xc4, 0xe2, 0x7d, 0x2a, 0x21, }, 5, 0, "", "", | ||
546 | "c4 e2 7d 2a 21 \tvmovntdqa (%ecx),%ymm4",}, | ||
547 | {{0x62, 0xf2, 0xfe, 0x48, 0x2a, 0xce, }, 6, 0, "", "", | ||
548 | "62 f2 fe 48 2a ce \tvpbroadcastmb2q %k6,%zmm1",}, | ||
549 | {{0xc4, 0xe2, 0x5d, 0x2c, 0x31, }, 5, 0, "", "", | ||
550 | "c4 e2 5d 2c 31 \tvmaskmovps (%ecx),%ymm4,%ymm6",}, | ||
551 | {{0x62, 0xf2, 0x55, 0x48, 0x2c, 0xf4, }, 6, 0, "", "", | ||
552 | "62 f2 55 48 2c f4 \tvscalefps %zmm4,%zmm5,%zmm6",}, | ||
553 | {{0x62, 0xf2, 0xd5, 0x48, 0x2c, 0xf4, }, 6, 0, "", "", | ||
554 | "62 f2 d5 48 2c f4 \tvscalefpd %zmm4,%zmm5,%zmm6",}, | ||
555 | {{0xc4, 0xe2, 0x5d, 0x2d, 0x31, }, 5, 0, "", "", | ||
556 | "c4 e2 5d 2d 31 \tvmaskmovpd (%ecx),%ymm4,%ymm6",}, | ||
557 | {{0x62, 0xf2, 0x55, 0x0f, 0x2d, 0xf4, }, 6, 0, "", "", | ||
558 | "62 f2 55 0f 2d f4 \tvscalefss %xmm4,%xmm5,%xmm6{%k7}",}, | ||
559 | {{0x62, 0xf2, 0xd5, 0x0f, 0x2d, 0xf4, }, 6, 0, "", "", | ||
560 | "62 f2 d5 0f 2d f4 \tvscalefsd %xmm4,%xmm5,%xmm6{%k7}",}, | ||
561 | {{0xc4, 0xe2, 0x7d, 0x30, 0xe4, }, 5, 0, "", "", | ||
562 | "c4 e2 7d 30 e4 \tvpmovzxbw %xmm4,%ymm4",}, | ||
563 | {{0x62, 0xf2, 0x7e, 0x4f, 0x30, 0xee, }, 6, 0, "", "", | ||
564 | "62 f2 7e 4f 30 ee \tvpmovwb %zmm5,%ymm6{%k7}",}, | ||
565 | {{0xc4, 0xe2, 0x7d, 0x31, 0xf4, }, 5, 0, "", "", | ||
566 | "c4 e2 7d 31 f4 \tvpmovzxbd %xmm4,%ymm6",}, | ||
567 | {{0x62, 0xf2, 0x7e, 0x4f, 0x31, 0xee, }, 6, 0, "", "", | ||
568 | "62 f2 7e 4f 31 ee \tvpmovdb %zmm5,%xmm6{%k7}",}, | ||
569 | {{0xc4, 0xe2, 0x7d, 0x32, 0xe4, }, 5, 0, "", "", | ||
570 | "c4 e2 7d 32 e4 \tvpmovzxbq %xmm4,%ymm4",}, | ||
571 | {{0x62, 0xf2, 0x7e, 0x4f, 0x32, 0xee, }, 6, 0, "", "", | ||
572 | "62 f2 7e 4f 32 ee \tvpmovqb %zmm5,%xmm6{%k7}",}, | ||
573 | {{0xc4, 0xe2, 0x7d, 0x33, 0xe4, }, 5, 0, "", "", | ||
574 | "c4 e2 7d 33 e4 \tvpmovzxwd %xmm4,%ymm4",}, | ||
575 | {{0x62, 0xf2, 0x7e, 0x4f, 0x33, 0xee, }, 6, 0, "", "", | ||
576 | "62 f2 7e 4f 33 ee \tvpmovdw %zmm5,%ymm6{%k7}",}, | ||
577 | {{0xc4, 0xe2, 0x7d, 0x34, 0xf4, }, 5, 0, "", "", | ||
578 | "c4 e2 7d 34 f4 \tvpmovzxwq %xmm4,%ymm6",}, | ||
579 | {{0x62, 0xf2, 0x7e, 0x4f, 0x34, 0xee, }, 6, 0, "", "", | ||
580 | "62 f2 7e 4f 34 ee \tvpmovqw %zmm5,%xmm6{%k7}",}, | ||
581 | {{0xc4, 0xe2, 0x7d, 0x35, 0xe4, }, 5, 0, "", "", | ||
582 | "c4 e2 7d 35 e4 \tvpmovzxdq %xmm4,%ymm4",}, | ||
583 | {{0x62, 0xf2, 0x7e, 0x4f, 0x35, 0xee, }, 6, 0, "", "", | ||
584 | "62 f2 7e 4f 35 ee \tvpmovqd %zmm5,%ymm6{%k7}",}, | ||
585 | {{0xc4, 0xe2, 0x4d, 0x36, 0xd4, }, 5, 0, "", "", | ||
586 | "c4 e2 4d 36 d4 \tvpermd %ymm4,%ymm6,%ymm2",}, | ||
587 | {{0x62, 0xf2, 0x4d, 0x2f, 0x36, 0xd4, }, 6, 0, "", "", | ||
588 | "62 f2 4d 2f 36 d4 \tvpermd %ymm4,%ymm6,%ymm2{%k7}",}, | ||
589 | {{0x62, 0xf2, 0xcd, 0x2f, 0x36, 0xd4, }, 6, 0, "", "", | ||
590 | "62 f2 cd 2f 36 d4 \tvpermq %ymm4,%ymm6,%ymm2{%k7}",}, | ||
591 | {{0xc4, 0xe2, 0x4d, 0x38, 0xd4, }, 5, 0, "", "", | ||
592 | "c4 e2 4d 38 d4 \tvpminsb %ymm4,%ymm6,%ymm2",}, | ||
593 | {{0x62, 0xf2, 0x7e, 0x48, 0x38, 0xf5, }, 6, 0, "", "", | ||
594 | "62 f2 7e 48 38 f5 \tvpmovm2d %k5,%zmm6",}, | ||
595 | {{0x62, 0xf2, 0xfe, 0x48, 0x38, 0xf5, }, 6, 0, "", "", | ||
596 | "62 f2 fe 48 38 f5 \tvpmovm2q %k5,%zmm6",}, | ||
597 | {{0xc4, 0xe2, 0x69, 0x39, 0xd9, }, 5, 0, "", "", | ||
598 | "c4 e2 69 39 d9 \tvpminsd %xmm1,%xmm2,%xmm3",}, | ||
599 | {{0x62, 0xf2, 0x55, 0x48, 0x39, 0xf4, }, 6, 0, "", "", | ||
600 | "62 f2 55 48 39 f4 \tvpminsd %zmm4,%zmm5,%zmm6",}, | ||
601 | {{0x62, 0xf2, 0xd5, 0x48, 0x39, 0xf4, }, 6, 0, "", "", | ||
602 | "62 f2 d5 48 39 f4 \tvpminsq %zmm4,%zmm5,%zmm6",}, | ||
603 | {{0x62, 0xf2, 0x7e, 0x48, 0x39, 0xee, }, 6, 0, "", "", | ||
604 | "62 f2 7e 48 39 ee \tvpmovd2m %zmm6,%k5",}, | ||
605 | {{0x62, 0xf2, 0xfe, 0x48, 0x39, 0xee, }, 6, 0, "", "", | ||
606 | "62 f2 fe 48 39 ee \tvpmovq2m %zmm6,%k5",}, | ||
607 | {{0xc4, 0xe2, 0x4d, 0x3a, 0xd4, }, 5, 0, "", "", | ||
608 | "c4 e2 4d 3a d4 \tvpminuw %ymm4,%ymm6,%ymm2",}, | ||
609 | {{0x62, 0xf2, 0x7e, 0x48, 0x3a, 0xf6, }, 6, 0, "", "", | ||
610 | "62 f2 7e 48 3a f6 \tvpbroadcastmw2d %k6,%zmm6",}, | ||
611 | {{0xc4, 0xe2, 0x4d, 0x3b, 0xd4, }, 5, 0, "", "", | ||
612 | "c4 e2 4d 3b d4 \tvpminud %ymm4,%ymm6,%ymm2",}, | ||
613 | {{0x62, 0xf2, 0x55, 0x48, 0x3b, 0xf4, }, 6, 0, "", "", | ||
614 | "62 f2 55 48 3b f4 \tvpminud %zmm4,%zmm5,%zmm6",}, | ||
615 | {{0x62, 0xf2, 0xd5, 0x48, 0x3b, 0xf4, }, 6, 0, "", "", | ||
616 | "62 f2 d5 48 3b f4 \tvpminuq %zmm4,%zmm5,%zmm6",}, | ||
617 | {{0xc4, 0xe2, 0x4d, 0x3d, 0xd4, }, 5, 0, "", "", | ||
618 | "c4 e2 4d 3d d4 \tvpmaxsd %ymm4,%ymm6,%ymm2",}, | ||
619 | {{0x62, 0xf2, 0x55, 0x48, 0x3d, 0xf4, }, 6, 0, "", "", | ||
620 | "62 f2 55 48 3d f4 \tvpmaxsd %zmm4,%zmm5,%zmm6",}, | ||
621 | {{0x62, 0xf2, 0xd5, 0x48, 0x3d, 0xf4, }, 6, 0, "", "", | ||
622 | "62 f2 d5 48 3d f4 \tvpmaxsq %zmm4,%zmm5,%zmm6",}, | ||
623 | {{0xc4, 0xe2, 0x4d, 0x3f, 0xd4, }, 5, 0, "", "", | ||
624 | "c4 e2 4d 3f d4 \tvpmaxud %ymm4,%ymm6,%ymm2",}, | ||
625 | {{0x62, 0xf2, 0x55, 0x48, 0x3f, 0xf4, }, 6, 0, "", "", | ||
626 | "62 f2 55 48 3f f4 \tvpmaxud %zmm4,%zmm5,%zmm6",}, | ||
627 | {{0x62, 0xf2, 0xd5, 0x48, 0x3f, 0xf4, }, 6, 0, "", "", | ||
628 | "62 f2 d5 48 3f f4 \tvpmaxuq %zmm4,%zmm5,%zmm6",}, | ||
629 | {{0xc4, 0xe2, 0x4d, 0x40, 0xd4, }, 5, 0, "", "", | ||
630 | "c4 e2 4d 40 d4 \tvpmulld %ymm4,%ymm6,%ymm2",}, | ||
631 | {{0x62, 0xf2, 0x55, 0x48, 0x40, 0xf4, }, 6, 0, "", "", | ||
632 | "62 f2 55 48 40 f4 \tvpmulld %zmm4,%zmm5,%zmm6",}, | ||
633 | {{0x62, 0xf2, 0xd5, 0x48, 0x40, 0xf4, }, 6, 0, "", "", | ||
634 | "62 f2 d5 48 40 f4 \tvpmullq %zmm4,%zmm5,%zmm6",}, | ||
635 | {{0x62, 0xf2, 0x7d, 0x48, 0x42, 0xf5, }, 6, 0, "", "", | ||
636 | "62 f2 7d 48 42 f5 \tvgetexpps %zmm5,%zmm6",}, | ||
637 | {{0x62, 0xf2, 0xfd, 0x48, 0x42, 0xf5, }, 6, 0, "", "", | ||
638 | "62 f2 fd 48 42 f5 \tvgetexppd %zmm5,%zmm6",}, | ||
639 | {{0x62, 0xf2, 0x55, 0x0f, 0x43, 0xf4, }, 6, 0, "", "", | ||
640 | "62 f2 55 0f 43 f4 \tvgetexpss %xmm4,%xmm5,%xmm6{%k7}",}, | ||
641 | {{0x62, 0xf2, 0xe5, 0x0f, 0x43, 0xe2, }, 6, 0, "", "", | ||
642 | "62 f2 e5 0f 43 e2 \tvgetexpsd %xmm2,%xmm3,%xmm4{%k7}",}, | ||
643 | {{0x62, 0xf2, 0x7d, 0x48, 0x44, 0xf5, }, 6, 0, "", "", | ||
644 | "62 f2 7d 48 44 f5 \tvplzcntd %zmm5,%zmm6",}, | ||
645 | {{0x62, 0xf2, 0xfd, 0x48, 0x44, 0xf5, }, 6, 0, "", "", | ||
646 | "62 f2 fd 48 44 f5 \tvplzcntq %zmm5,%zmm6",}, | ||
647 | {{0xc4, 0xe2, 0x4d, 0x46, 0xd4, }, 5, 0, "", "", | ||
648 | "c4 e2 4d 46 d4 \tvpsravd %ymm4,%ymm6,%ymm2",}, | ||
649 | {{0x62, 0xf2, 0x55, 0x48, 0x46, 0xf4, }, 6, 0, "", "", | ||
650 | "62 f2 55 48 46 f4 \tvpsravd %zmm4,%zmm5,%zmm6",}, | ||
651 | {{0x62, 0xf2, 0xd5, 0x48, 0x46, 0xf4, }, 6, 0, "", "", | ||
652 | "62 f2 d5 48 46 f4 \tvpsravq %zmm4,%zmm5,%zmm6",}, | ||
653 | {{0x62, 0xf2, 0x7d, 0x48, 0x4c, 0xf5, }, 6, 0, "", "", | ||
654 | "62 f2 7d 48 4c f5 \tvrcp14ps %zmm5,%zmm6",}, | ||
655 | {{0x62, 0xf2, 0xfd, 0x48, 0x4c, 0xf5, }, 6, 0, "", "", | ||
656 | "62 f2 fd 48 4c f5 \tvrcp14pd %zmm5,%zmm6",}, | ||
657 | {{0x62, 0xf2, 0x55, 0x0f, 0x4d, 0xf4, }, 6, 0, "", "", | ||
658 | "62 f2 55 0f 4d f4 \tvrcp14ss %xmm4,%xmm5,%xmm6{%k7}",}, | ||
659 | {{0x62, 0xf2, 0xd5, 0x0f, 0x4d, 0xf4, }, 6, 0, "", "", | ||
660 | "62 f2 d5 0f 4d f4 \tvrcp14sd %xmm4,%xmm5,%xmm6{%k7}",}, | ||
661 | {{0x62, 0xf2, 0x7d, 0x48, 0x4e, 0xf5, }, 6, 0, "", "", | ||
662 | "62 f2 7d 48 4e f5 \tvrsqrt14ps %zmm5,%zmm6",}, | ||
663 | {{0x62, 0xf2, 0xfd, 0x48, 0x4e, 0xf5, }, 6, 0, "", "", | ||
664 | "62 f2 fd 48 4e f5 \tvrsqrt14pd %zmm5,%zmm6",}, | ||
665 | {{0x62, 0xf2, 0x55, 0x0f, 0x4f, 0xf4, }, 6, 0, "", "", | ||
666 | "62 f2 55 0f 4f f4 \tvrsqrt14ss %xmm4,%xmm5,%xmm6{%k7}",}, | ||
667 | {{0x62, 0xf2, 0xd5, 0x0f, 0x4f, 0xf4, }, 6, 0, "", "", | ||
668 | "62 f2 d5 0f 4f f4 \tvrsqrt14sd %xmm4,%xmm5,%xmm6{%k7}",}, | ||
669 | {{0xc4, 0xe2, 0x79, 0x59, 0xf4, }, 5, 0, "", "", | ||
670 | "c4 e2 79 59 f4 \tvpbroadcastq %xmm4,%xmm6",}, | ||
671 | {{0x62, 0xf2, 0x7d, 0x48, 0x59, 0xf7, }, 6, 0, "", "", | ||
672 | "62 f2 7d 48 59 f7 \tvbroadcasti32x2 %xmm7,%zmm6",}, | ||
673 | {{0xc4, 0xe2, 0x7d, 0x5a, 0x21, }, 5, 0, "", "", | ||
674 | "c4 e2 7d 5a 21 \tvbroadcasti128 (%ecx),%ymm4",}, | ||
675 | {{0x62, 0xf2, 0x7d, 0x48, 0x5a, 0x31, }, 6, 0, "", "", | ||
676 | "62 f2 7d 48 5a 31 \tvbroadcasti32x4 (%ecx),%zmm6",}, | ||
677 | {{0x62, 0xf2, 0xfd, 0x48, 0x5a, 0x31, }, 6, 0, "", "", | ||
678 | "62 f2 fd 48 5a 31 \tvbroadcasti64x2 (%ecx),%zmm6",}, | ||
679 | {{0x62, 0xf2, 0x7d, 0x48, 0x5b, 0x31, }, 6, 0, "", "", | ||
680 | "62 f2 7d 48 5b 31 \tvbroadcasti32x8 (%ecx),%zmm6",}, | ||
681 | {{0x62, 0xf2, 0xfd, 0x48, 0x5b, 0x31, }, 6, 0, "", "", | ||
682 | "62 f2 fd 48 5b 31 \tvbroadcasti64x4 (%ecx),%zmm6",}, | ||
683 | {{0x62, 0xf2, 0x55, 0x48, 0x64, 0xf4, }, 6, 0, "", "", | ||
684 | "62 f2 55 48 64 f4 \tvpblendmd %zmm4,%zmm5,%zmm6",}, | ||
685 | {{0x62, 0xf2, 0xd5, 0x48, 0x64, 0xf4, }, 6, 0, "", "", | ||
686 | "62 f2 d5 48 64 f4 \tvpblendmq %zmm4,%zmm5,%zmm6",}, | ||
687 | {{0x62, 0xf2, 0x55, 0x48, 0x65, 0xf4, }, 6, 0, "", "", | ||
688 | "62 f2 55 48 65 f4 \tvblendmps %zmm4,%zmm5,%zmm6",}, | ||
689 | {{0x62, 0xf2, 0xd5, 0x48, 0x65, 0xf4, }, 6, 0, "", "", | ||
690 | "62 f2 d5 48 65 f4 \tvblendmpd %zmm4,%zmm5,%zmm6",}, | ||
691 | {{0x62, 0xf2, 0x55, 0x48, 0x66, 0xf4, }, 6, 0, "", "", | ||
692 | "62 f2 55 48 66 f4 \tvpblendmb %zmm4,%zmm5,%zmm6",}, | ||
693 | {{0x62, 0xf2, 0xd5, 0x48, 0x66, 0xf4, }, 6, 0, "", "", | ||
694 | "62 f2 d5 48 66 f4 \tvpblendmw %zmm4,%zmm5,%zmm6",}, | ||
695 | {{0x62, 0xf2, 0x55, 0x48, 0x75, 0xf4, }, 6, 0, "", "", | ||
696 | "62 f2 55 48 75 f4 \tvpermi2b %zmm4,%zmm5,%zmm6",}, | ||
697 | {{0x62, 0xf2, 0xd5, 0x48, 0x75, 0xf4, }, 6, 0, "", "", | ||
698 | "62 f2 d5 48 75 f4 \tvpermi2w %zmm4,%zmm5,%zmm6",}, | ||
699 | {{0x62, 0xf2, 0x55, 0x48, 0x76, 0xf4, }, 6, 0, "", "", | ||
700 | "62 f2 55 48 76 f4 \tvpermi2d %zmm4,%zmm5,%zmm6",}, | ||
701 | {{0x62, 0xf2, 0xd5, 0x48, 0x76, 0xf4, }, 6, 0, "", "", | ||
702 | "62 f2 d5 48 76 f4 \tvpermi2q %zmm4,%zmm5,%zmm6",}, | ||
703 | {{0x62, 0xf2, 0x55, 0x48, 0x77, 0xf4, }, 6, 0, "", "", | ||
704 | "62 f2 55 48 77 f4 \tvpermi2ps %zmm4,%zmm5,%zmm6",}, | ||
705 | {{0x62, 0xf2, 0xd5, 0x48, 0x77, 0xf4, }, 6, 0, "", "", | ||
706 | "62 f2 d5 48 77 f4 \tvpermi2pd %zmm4,%zmm5,%zmm6",}, | ||
707 | {{0x62, 0xf2, 0x7d, 0x08, 0x7a, 0xd8, }, 6, 0, "", "", | ||
708 | "62 f2 7d 08 7a d8 \tvpbroadcastb %eax,%xmm3",}, | ||
709 | {{0x62, 0xf2, 0x7d, 0x08, 0x7b, 0xd8, }, 6, 0, "", "", | ||
710 | "62 f2 7d 08 7b d8 \tvpbroadcastw %eax,%xmm3",}, | ||
711 | {{0x62, 0xf2, 0x7d, 0x08, 0x7c, 0xd8, }, 6, 0, "", "", | ||
712 | "62 f2 7d 08 7c d8 \tvpbroadcastd %eax,%xmm3",}, | ||
713 | {{0x62, 0xf2, 0x55, 0x48, 0x7d, 0xf4, }, 6, 0, "", "", | ||
714 | "62 f2 55 48 7d f4 \tvpermt2b %zmm4,%zmm5,%zmm6",}, | ||
715 | {{0x62, 0xf2, 0xd5, 0x48, 0x7d, 0xf4, }, 6, 0, "", "", | ||
716 | "62 f2 d5 48 7d f4 \tvpermt2w %zmm4,%zmm5,%zmm6",}, | ||
717 | {{0x62, 0xf2, 0x55, 0x48, 0x7e, 0xf4, }, 6, 0, "", "", | ||
718 | "62 f2 55 48 7e f4 \tvpermt2d %zmm4,%zmm5,%zmm6",}, | ||
719 | {{0x62, 0xf2, 0xd5, 0x48, 0x7e, 0xf4, }, 6, 0, "", "", | ||
720 | "62 f2 d5 48 7e f4 \tvpermt2q %zmm4,%zmm5,%zmm6",}, | ||
721 | {{0x62, 0xf2, 0x55, 0x48, 0x7f, 0xf4, }, 6, 0, "", "", | ||
722 | "62 f2 55 48 7f f4 \tvpermt2ps %zmm4,%zmm5,%zmm6",}, | ||
723 | {{0x62, 0xf2, 0xd5, 0x48, 0x7f, 0xf4, }, 6, 0, "", "", | ||
724 | "62 f2 d5 48 7f f4 \tvpermt2pd %zmm4,%zmm5,%zmm6",}, | ||
725 | {{0x62, 0xf2, 0xd5, 0x48, 0x83, 0xf4, }, 6, 0, "", "", | ||
726 | "62 f2 d5 48 83 f4 \tvpmultishiftqb %zmm4,%zmm5,%zmm6",}, | ||
727 | {{0x62, 0xf2, 0x7d, 0x48, 0x88, 0x31, }, 6, 0, "", "", | ||
728 | "62 f2 7d 48 88 31 \tvexpandps (%ecx),%zmm6",}, | ||
729 | {{0x62, 0xf2, 0xfd, 0x48, 0x88, 0x31, }, 6, 0, "", "", | ||
730 | "62 f2 fd 48 88 31 \tvexpandpd (%ecx),%zmm6",}, | ||
731 | {{0x62, 0xf2, 0x7d, 0x48, 0x89, 0x31, }, 6, 0, "", "", | ||
732 | "62 f2 7d 48 89 31 \tvpexpandd (%ecx),%zmm6",}, | ||
733 | {{0x62, 0xf2, 0xfd, 0x48, 0x89, 0x31, }, 6, 0, "", "", | ||
734 | "62 f2 fd 48 89 31 \tvpexpandq (%ecx),%zmm6",}, | ||
735 | {{0x62, 0xf2, 0x7d, 0x48, 0x8a, 0x31, }, 6, 0, "", "", | ||
736 | "62 f2 7d 48 8a 31 \tvcompressps %zmm6,(%ecx)",}, | ||
737 | {{0x62, 0xf2, 0xfd, 0x48, 0x8a, 0x31, }, 6, 0, "", "", | ||
738 | "62 f2 fd 48 8a 31 \tvcompresspd %zmm6,(%ecx)",}, | ||
739 | {{0x62, 0xf2, 0x7d, 0x48, 0x8b, 0x31, }, 6, 0, "", "", | ||
740 | "62 f2 7d 48 8b 31 \tvpcompressd %zmm6,(%ecx)",}, | ||
741 | {{0x62, 0xf2, 0xfd, 0x48, 0x8b, 0x31, }, 6, 0, "", "", | ||
742 | "62 f2 fd 48 8b 31 \tvpcompressq %zmm6,(%ecx)",}, | ||
743 | {{0x62, 0xf2, 0x55, 0x48, 0x8d, 0xf4, }, 6, 0, "", "", | ||
744 | "62 f2 55 48 8d f4 \tvpermb %zmm4,%zmm5,%zmm6",}, | ||
745 | {{0x62, 0xf2, 0xd5, 0x48, 0x8d, 0xf4, }, 6, 0, "", "", | ||
746 | "62 f2 d5 48 8d f4 \tvpermw %zmm4,%zmm5,%zmm6",}, | ||
747 | {{0xc4, 0xe2, 0x69, 0x90, 0x4c, 0x7d, 0x02, }, 7, 0, "", "", | ||
748 | "c4 e2 69 90 4c 7d 02 \tvpgatherdd %xmm2,0x2(%ebp,%xmm7,2),%xmm1",}, | ||
749 | {{0xc4, 0xe2, 0xe9, 0x90, 0x4c, 0x7d, 0x04, }, 7, 0, "", "", | ||
750 | "c4 e2 e9 90 4c 7d 04 \tvpgatherdq %xmm2,0x4(%ebp,%xmm7,2),%xmm1",}, | ||
751 | {{0x62, 0xf2, 0x7d, 0x49, 0x90, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
752 | "62 f2 7d 49 90 b4 fd 7b 00 00 00 \tvpgatherdd 0x7b(%ebp,%zmm7,8),%zmm6{%k1}",}, | ||
753 | {{0x62, 0xf2, 0xfd, 0x49, 0x90, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
754 | "62 f2 fd 49 90 b4 fd 7b 00 00 00 \tvpgatherdq 0x7b(%ebp,%ymm7,8),%zmm6{%k1}",}, | ||
755 | {{0xc4, 0xe2, 0x69, 0x91, 0x4c, 0x7d, 0x02, }, 7, 0, "", "", | ||
756 | "c4 e2 69 91 4c 7d 02 \tvpgatherqd %xmm2,0x2(%ebp,%xmm7,2),%xmm1",}, | ||
757 | {{0xc4, 0xe2, 0xe9, 0x91, 0x4c, 0x7d, 0x02, }, 7, 0, "", "", | ||
758 | "c4 e2 e9 91 4c 7d 02 \tvpgatherqq %xmm2,0x2(%ebp,%xmm7,2),%xmm1",}, | ||
759 | {{0x62, 0xf2, 0x7d, 0x49, 0x91, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
760 | "62 f2 7d 49 91 b4 fd 7b 00 00 00 \tvpgatherqd 0x7b(%ebp,%zmm7,8),%ymm6{%k1}",}, | ||
761 | {{0x62, 0xf2, 0xfd, 0x49, 0x91, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
762 | "62 f2 fd 49 91 b4 fd 7b 00 00 00 \tvpgatherqq 0x7b(%ebp,%zmm7,8),%zmm6{%k1}",}, | ||
763 | {{0x62, 0xf2, 0x7d, 0x49, 0xa0, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
764 | "62 f2 7d 49 a0 b4 fd 7b 00 00 00 \tvpscatterdd %zmm6,0x7b(%ebp,%zmm7,8){%k1}",}, | ||
765 | {{0x62, 0xf2, 0xfd, 0x49, 0xa0, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
766 | "62 f2 fd 49 a0 b4 fd 7b 00 00 00 \tvpscatterdq %zmm6,0x7b(%ebp,%ymm7,8){%k1}",}, | ||
767 | {{0x62, 0xf2, 0x7d, 0x49, 0xa1, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
768 | "62 f2 7d 49 a1 b4 fd 7b 00 00 00 \tvpscatterqd %ymm6,0x7b(%ebp,%zmm7,8){%k1}",}, | ||
769 | {{0x62, 0xf2, 0xfd, 0x29, 0xa1, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
770 | "62 f2 fd 29 a1 b4 fd 7b 00 00 00 \tvpscatterqq %ymm6,0x7b(%ebp,%ymm7,8){%k1}",}, | ||
771 | {{0x62, 0xf2, 0x7d, 0x49, 0xa2, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
772 | "62 f2 7d 49 a2 b4 fd 7b 00 00 00 \tvscatterdps %zmm6,0x7b(%ebp,%zmm7,8){%k1}",}, | ||
773 | {{0x62, 0xf2, 0xfd, 0x49, 0xa2, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
774 | "62 f2 fd 49 a2 b4 fd 7b 00 00 00 \tvscatterdpd %zmm6,0x7b(%ebp,%ymm7,8){%k1}",}, | ||
775 | {{0x62, 0xf2, 0x7d, 0x49, 0xa3, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
776 | "62 f2 7d 49 a3 b4 fd 7b 00 00 00 \tvscatterqps %ymm6,0x7b(%ebp,%zmm7,8){%k1}",}, | ||
777 | {{0x62, 0xf2, 0xfd, 0x49, 0xa3, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
778 | "62 f2 fd 49 a3 b4 fd 7b 00 00 00 \tvscatterqpd %zmm6,0x7b(%ebp,%zmm7,8){%k1}",}, | ||
779 | {{0x62, 0xf2, 0xd5, 0x48, 0xb4, 0xf4, }, 6, 0, "", "", | ||
780 | "62 f2 d5 48 b4 f4 \tvpmadd52luq %zmm4,%zmm5,%zmm6",}, | ||
781 | {{0x62, 0xf2, 0xd5, 0x48, 0xb5, 0xf4, }, 6, 0, "", "", | ||
782 | "62 f2 d5 48 b5 f4 \tvpmadd52huq %zmm4,%zmm5,%zmm6",}, | ||
783 | {{0x62, 0xf2, 0x7d, 0x48, 0xc4, 0xf5, }, 6, 0, "", "", | ||
784 | "62 f2 7d 48 c4 f5 \tvpconflictd %zmm5,%zmm6",}, | ||
785 | {{0x62, 0xf2, 0xfd, 0x48, 0xc4, 0xf5, }, 6, 0, "", "", | ||
786 | "62 f2 fd 48 c4 f5 \tvpconflictq %zmm5,%zmm6",}, | ||
787 | {{0x62, 0xf2, 0x7d, 0x48, 0xc8, 0xfe, }, 6, 0, "", "", | ||
788 | "62 f2 7d 48 c8 fe \tvexp2ps %zmm6,%zmm7",}, | ||
789 | {{0x62, 0xf2, 0xfd, 0x48, 0xc8, 0xfe, }, 6, 0, "", "", | ||
790 | "62 f2 fd 48 c8 fe \tvexp2pd %zmm6,%zmm7",}, | ||
791 | {{0x62, 0xf2, 0x7d, 0x48, 0xca, 0xfe, }, 6, 0, "", "", | ||
792 | "62 f2 7d 48 ca fe \tvrcp28ps %zmm6,%zmm7",}, | ||
793 | {{0x62, 0xf2, 0xfd, 0x48, 0xca, 0xfe, }, 6, 0, "", "", | ||
794 | "62 f2 fd 48 ca fe \tvrcp28pd %zmm6,%zmm7",}, | ||
795 | {{0x62, 0xf2, 0x4d, 0x0f, 0xcb, 0xfd, }, 6, 0, "", "", | ||
796 | "62 f2 4d 0f cb fd \tvrcp28ss %xmm5,%xmm6,%xmm7{%k7}",}, | ||
797 | {{0x62, 0xf2, 0xcd, 0x0f, 0xcb, 0xfd, }, 6, 0, "", "", | ||
798 | "62 f2 cd 0f cb fd \tvrcp28sd %xmm5,%xmm6,%xmm7{%k7}",}, | ||
799 | {{0x62, 0xf2, 0x7d, 0x48, 0xcc, 0xfe, }, 6, 0, "", "", | ||
800 | "62 f2 7d 48 cc fe \tvrsqrt28ps %zmm6,%zmm7",}, | ||
801 | {{0x62, 0xf2, 0xfd, 0x48, 0xcc, 0xfe, }, 6, 0, "", "", | ||
802 | "62 f2 fd 48 cc fe \tvrsqrt28pd %zmm6,%zmm7",}, | ||
803 | {{0x62, 0xf2, 0x4d, 0x0f, 0xcd, 0xfd, }, 6, 0, "", "", | ||
804 | "62 f2 4d 0f cd fd \tvrsqrt28ss %xmm5,%xmm6,%xmm7{%k7}",}, | ||
805 | {{0x62, 0xf2, 0xcd, 0x0f, 0xcd, 0xfd, }, 6, 0, "", "", | ||
806 | "62 f2 cd 0f cd fd \tvrsqrt28sd %xmm5,%xmm6,%xmm7{%k7}",}, | ||
807 | {{0x62, 0xf3, 0x4d, 0x48, 0x03, 0xfd, 0x12, }, 7, 0, "", "", | ||
808 | "62 f3 4d 48 03 fd 12 \tvalignd $0x12,%zmm5,%zmm6,%zmm7",}, | ||
809 | {{0x62, 0xf3, 0xcd, 0x48, 0x03, 0xfd, 0x12, }, 7, 0, "", "", | ||
810 | "62 f3 cd 48 03 fd 12 \tvalignq $0x12,%zmm5,%zmm6,%zmm7",}, | ||
811 | {{0xc4, 0xe3, 0x7d, 0x08, 0xd6, 0x05, }, 6, 0, "", "", | ||
812 | "c4 e3 7d 08 d6 05 \tvroundps $0x5,%ymm6,%ymm2",}, | ||
813 | {{0x62, 0xf3, 0x7d, 0x48, 0x08, 0xf5, 0x12, }, 7, 0, "", "", | ||
814 | "62 f3 7d 48 08 f5 12 \tvrndscaleps $0x12,%zmm5,%zmm6",}, | ||
815 | {{0xc4, 0xe3, 0x7d, 0x09, 0xd6, 0x05, }, 6, 0, "", "", | ||
816 | "c4 e3 7d 09 d6 05 \tvroundpd $0x5,%ymm6,%ymm2",}, | ||
817 | {{0x62, 0xf3, 0xfd, 0x48, 0x09, 0xf5, 0x12, }, 7, 0, "", "", | ||
818 | "62 f3 fd 48 09 f5 12 \tvrndscalepd $0x12,%zmm5,%zmm6",}, | ||
819 | {{0xc4, 0xe3, 0x49, 0x0a, 0xd4, 0x05, }, 6, 0, "", "", | ||
820 | "c4 e3 49 0a d4 05 \tvroundss $0x5,%xmm4,%xmm6,%xmm2",}, | ||
821 | {{0x62, 0xf3, 0x55, 0x0f, 0x0a, 0xf4, 0x12, }, 7, 0, "", "", | ||
822 | "62 f3 55 0f 0a f4 12 \tvrndscaless $0x12,%xmm4,%xmm5,%xmm6{%k7}",}, | ||
823 | {{0xc4, 0xe3, 0x49, 0x0b, 0xd4, 0x05, }, 6, 0, "", "", | ||
824 | "c4 e3 49 0b d4 05 \tvroundsd $0x5,%xmm4,%xmm6,%xmm2",}, | ||
825 | {{0x62, 0xf3, 0xd5, 0x0f, 0x0b, 0xf4, 0x12, }, 7, 0, "", "", | ||
826 | "62 f3 d5 0f 0b f4 12 \tvrndscalesd $0x12,%xmm4,%xmm5,%xmm6{%k7}",}, | ||
827 | {{0xc4, 0xe3, 0x5d, 0x18, 0xf4, 0x05, }, 6, 0, "", "", | ||
828 | "c4 e3 5d 18 f4 05 \tvinsertf128 $0x5,%xmm4,%ymm4,%ymm6",}, | ||
829 | {{0x62, 0xf3, 0x55, 0x4f, 0x18, 0xf4, 0x12, }, 7, 0, "", "", | ||
830 | "62 f3 55 4f 18 f4 12 \tvinsertf32x4 $0x12,%xmm4,%zmm5,%zmm6{%k7}",}, | ||
831 | {{0x62, 0xf3, 0xd5, 0x4f, 0x18, 0xf4, 0x12, }, 7, 0, "", "", | ||
832 | "62 f3 d5 4f 18 f4 12 \tvinsertf64x2 $0x12,%xmm4,%zmm5,%zmm6{%k7}",}, | ||
833 | {{0xc4, 0xe3, 0x7d, 0x19, 0xe4, 0x05, }, 6, 0, "", "", | ||
834 | "c4 e3 7d 19 e4 05 \tvextractf128 $0x5,%ymm4,%xmm4",}, | ||
835 | {{0x62, 0xf3, 0x7d, 0x4f, 0x19, 0xee, 0x12, }, 7, 0, "", "", | ||
836 | "62 f3 7d 4f 19 ee 12 \tvextractf32x4 $0x12,%zmm5,%xmm6{%k7}",}, | ||
837 | {{0x62, 0xf3, 0xfd, 0x4f, 0x19, 0xee, 0x12, }, 7, 0, "", "", | ||
838 | "62 f3 fd 4f 19 ee 12 \tvextractf64x2 $0x12,%zmm5,%xmm6{%k7}",}, | ||
839 | {{0x62, 0xf3, 0x4d, 0x4f, 0x1a, 0xfd, 0x12, }, 7, 0, "", "", | ||
840 | "62 f3 4d 4f 1a fd 12 \tvinsertf32x8 $0x12,%ymm5,%zmm6,%zmm7{%k7}",}, | ||
841 | {{0x62, 0xf3, 0xcd, 0x4f, 0x1a, 0xfd, 0x12, }, 7, 0, "", "", | ||
842 | "62 f3 cd 4f 1a fd 12 \tvinsertf64x4 $0x12,%ymm5,%zmm6,%zmm7{%k7}",}, | ||
843 | {{0x62, 0xf3, 0x7d, 0x4f, 0x1b, 0xf7, 0x12, }, 7, 0, "", "", | ||
844 | "62 f3 7d 4f 1b f7 12 \tvextractf32x8 $0x12,%zmm6,%ymm7{%k7}",}, | ||
845 | {{0x62, 0xf3, 0xfd, 0x4f, 0x1b, 0xf7, 0x12, }, 7, 0, "", "", | ||
846 | "62 f3 fd 4f 1b f7 12 \tvextractf64x4 $0x12,%zmm6,%ymm7{%k7}",}, | ||
847 | {{0x62, 0xf3, 0x45, 0x48, 0x1e, 0xee, 0x12, }, 7, 0, "", "", | ||
848 | "62 f3 45 48 1e ee 12 \tvpcmpud $0x12,%zmm6,%zmm7,%k5",}, | ||
849 | {{0x62, 0xf3, 0xc5, 0x48, 0x1e, 0xee, 0x12, }, 7, 0, "", "", | ||
850 | "62 f3 c5 48 1e ee 12 \tvpcmpuq $0x12,%zmm6,%zmm7,%k5",}, | ||
851 | {{0x62, 0xf3, 0x45, 0x48, 0x1f, 0xee, 0x12, }, 7, 0, "", "", | ||
852 | "62 f3 45 48 1f ee 12 \tvpcmpd $0x12,%zmm6,%zmm7,%k5",}, | ||
853 | {{0x62, 0xf3, 0xc5, 0x48, 0x1f, 0xee, 0x12, }, 7, 0, "", "", | ||
854 | "62 f3 c5 48 1f ee 12 \tvpcmpq $0x12,%zmm6,%zmm7,%k5",}, | ||
855 | {{0x62, 0xf3, 0x4d, 0x48, 0x23, 0xfd, 0x12, }, 7, 0, "", "", | ||
856 | "62 f3 4d 48 23 fd 12 \tvshuff32x4 $0x12,%zmm5,%zmm6,%zmm7",}, | ||
857 | {{0x62, 0xf3, 0xcd, 0x48, 0x23, 0xfd, 0x12, }, 7, 0, "", "", | ||
858 | "62 f3 cd 48 23 fd 12 \tvshuff64x2 $0x12,%zmm5,%zmm6,%zmm7",}, | ||
859 | {{0x62, 0xf3, 0x4d, 0x48, 0x25, 0xfd, 0x12, }, 7, 0, "", "", | ||
860 | "62 f3 4d 48 25 fd 12 \tvpternlogd $0x12,%zmm5,%zmm6,%zmm7",}, | ||
861 | {{0x62, 0xf3, 0xcd, 0x48, 0x25, 0xfd, 0x12, }, 7, 0, "", "", | ||
862 | "62 f3 cd 48 25 fd 12 \tvpternlogq $0x12,%zmm5,%zmm6,%zmm7",}, | ||
863 | {{0x62, 0xf3, 0x7d, 0x48, 0x26, 0xfe, 0x12, }, 7, 0, "", "", | ||
864 | "62 f3 7d 48 26 fe 12 \tvgetmantps $0x12,%zmm6,%zmm7",}, | ||
865 | {{0x62, 0xf3, 0xfd, 0x48, 0x26, 0xfe, 0x12, }, 7, 0, "", "", | ||
866 | "62 f3 fd 48 26 fe 12 \tvgetmantpd $0x12,%zmm6,%zmm7",}, | ||
867 | {{0x62, 0xf3, 0x4d, 0x0f, 0x27, 0xfd, 0x12, }, 7, 0, "", "", | ||
868 | "62 f3 4d 0f 27 fd 12 \tvgetmantss $0x12,%xmm5,%xmm6,%xmm7{%k7}",}, | ||
869 | {{0x62, 0xf3, 0xcd, 0x0f, 0x27, 0xfd, 0x12, }, 7, 0, "", "", | ||
870 | "62 f3 cd 0f 27 fd 12 \tvgetmantsd $0x12,%xmm5,%xmm6,%xmm7{%k7}",}, | ||
871 | {{0xc4, 0xe3, 0x5d, 0x38, 0xf4, 0x05, }, 6, 0, "", "", | ||
872 | "c4 e3 5d 38 f4 05 \tvinserti128 $0x5,%xmm4,%ymm4,%ymm6",}, | ||
873 | {{0x62, 0xf3, 0x55, 0x4f, 0x38, 0xf4, 0x12, }, 7, 0, "", "", | ||
874 | "62 f3 55 4f 38 f4 12 \tvinserti32x4 $0x12,%xmm4,%zmm5,%zmm6{%k7}",}, | ||
875 | {{0x62, 0xf3, 0xd5, 0x4f, 0x38, 0xf4, 0x12, }, 7, 0, "", "", | ||
876 | "62 f3 d5 4f 38 f4 12 \tvinserti64x2 $0x12,%xmm4,%zmm5,%zmm6{%k7}",}, | ||
877 | {{0xc4, 0xe3, 0x7d, 0x39, 0xe6, 0x05, }, 6, 0, "", "", | ||
878 | "c4 e3 7d 39 e6 05 \tvextracti128 $0x5,%ymm4,%xmm6",}, | ||
879 | {{0x62, 0xf3, 0x7d, 0x4f, 0x39, 0xee, 0x12, }, 7, 0, "", "", | ||
880 | "62 f3 7d 4f 39 ee 12 \tvextracti32x4 $0x12,%zmm5,%xmm6{%k7}",}, | ||
881 | {{0x62, 0xf3, 0xfd, 0x4f, 0x39, 0xee, 0x12, }, 7, 0, "", "", | ||
882 | "62 f3 fd 4f 39 ee 12 \tvextracti64x2 $0x12,%zmm5,%xmm6{%k7}",}, | ||
883 | {{0x62, 0xf3, 0x4d, 0x4f, 0x3a, 0xfd, 0x12, }, 7, 0, "", "", | ||
884 | "62 f3 4d 4f 3a fd 12 \tvinserti32x8 $0x12,%ymm5,%zmm6,%zmm7{%k7}",}, | ||
885 | {{0x62, 0xf3, 0xcd, 0x4f, 0x3a, 0xfd, 0x12, }, 7, 0, "", "", | ||
886 | "62 f3 cd 4f 3a fd 12 \tvinserti64x4 $0x12,%ymm5,%zmm6,%zmm7{%k7}",}, | ||
887 | {{0x62, 0xf3, 0x7d, 0x4f, 0x3b, 0xf7, 0x12, }, 7, 0, "", "", | ||
888 | "62 f3 7d 4f 3b f7 12 \tvextracti32x8 $0x12,%zmm6,%ymm7{%k7}",}, | ||
889 | {{0x62, 0xf3, 0xfd, 0x4f, 0x3b, 0xf7, 0x12, }, 7, 0, "", "", | ||
890 | "62 f3 fd 4f 3b f7 12 \tvextracti64x4 $0x12,%zmm6,%ymm7{%k7}",}, | ||
891 | {{0x62, 0xf3, 0x45, 0x48, 0x3e, 0xee, 0x12, }, 7, 0, "", "", | ||
892 | "62 f3 45 48 3e ee 12 \tvpcmpub $0x12,%zmm6,%zmm7,%k5",}, | ||
893 | {{0x62, 0xf3, 0xc5, 0x48, 0x3e, 0xee, 0x12, }, 7, 0, "", "", | ||
894 | "62 f3 c5 48 3e ee 12 \tvpcmpuw $0x12,%zmm6,%zmm7,%k5",}, | ||
895 | {{0x62, 0xf3, 0x45, 0x48, 0x3f, 0xee, 0x12, }, 7, 0, "", "", | ||
896 | "62 f3 45 48 3f ee 12 \tvpcmpb $0x12,%zmm6,%zmm7,%k5",}, | ||
897 | {{0x62, 0xf3, 0xc5, 0x48, 0x3f, 0xee, 0x12, }, 7, 0, "", "", | ||
898 | "62 f3 c5 48 3f ee 12 \tvpcmpw $0x12,%zmm6,%zmm7,%k5",}, | ||
899 | {{0xc4, 0xe3, 0x4d, 0x42, 0xd4, 0x05, }, 6, 0, "", "", | ||
900 | "c4 e3 4d 42 d4 05 \tvmpsadbw $0x5,%ymm4,%ymm6,%ymm2",}, | ||
901 | {{0x62, 0xf3, 0x55, 0x48, 0x42, 0xf4, 0x12, }, 7, 0, "", "", | ||
902 | "62 f3 55 48 42 f4 12 \tvdbpsadbw $0x12,%zmm4,%zmm5,%zmm6",}, | ||
903 | {{0x62, 0xf3, 0x4d, 0x48, 0x43, 0xfd, 0x12, }, 7, 0, "", "", | ||
904 | "62 f3 4d 48 43 fd 12 \tvshufi32x4 $0x12,%zmm5,%zmm6,%zmm7",}, | ||
905 | {{0x62, 0xf3, 0xcd, 0x48, 0x43, 0xfd, 0x12, }, 7, 0, "", "", | ||
906 | "62 f3 cd 48 43 fd 12 \tvshufi64x2 $0x12,%zmm5,%zmm6,%zmm7",}, | ||
907 | {{0x62, 0xf3, 0x4d, 0x48, 0x50, 0xfd, 0x12, }, 7, 0, "", "", | ||
908 | "62 f3 4d 48 50 fd 12 \tvrangeps $0x12,%zmm5,%zmm6,%zmm7",}, | ||
909 | {{0x62, 0xf3, 0xcd, 0x48, 0x50, 0xfd, 0x12, }, 7, 0, "", "", | ||
910 | "62 f3 cd 48 50 fd 12 \tvrangepd $0x12,%zmm5,%zmm6,%zmm7",}, | ||
911 | {{0x62, 0xf3, 0x4d, 0x08, 0x51, 0xfd, 0x12, }, 7, 0, "", "", | ||
912 | "62 f3 4d 08 51 fd 12 \tvrangess $0x12,%xmm5,%xmm6,%xmm7",}, | ||
913 | {{0x62, 0xf3, 0xcd, 0x08, 0x51, 0xfd, 0x12, }, 7, 0, "", "", | ||
914 | "62 f3 cd 08 51 fd 12 \tvrangesd $0x12,%xmm5,%xmm6,%xmm7",}, | ||
915 | {{0x62, 0xf3, 0x4d, 0x48, 0x54, 0xfd, 0x12, }, 7, 0, "", "", | ||
916 | "62 f3 4d 48 54 fd 12 \tvfixupimmps $0x12,%zmm5,%zmm6,%zmm7",}, | ||
917 | {{0x62, 0xf3, 0xcd, 0x48, 0x54, 0xfd, 0x12, }, 7, 0, "", "", | ||
918 | "62 f3 cd 48 54 fd 12 \tvfixupimmpd $0x12,%zmm5,%zmm6,%zmm7",}, | ||
919 | {{0x62, 0xf3, 0x4d, 0x0f, 0x55, 0xfd, 0x12, }, 7, 0, "", "", | ||
920 | "62 f3 4d 0f 55 fd 12 \tvfixupimmss $0x12,%xmm5,%xmm6,%xmm7{%k7}",}, | ||
921 | {{0x62, 0xf3, 0xcd, 0x0f, 0x55, 0xfd, 0x12, }, 7, 0, "", "", | ||
922 | "62 f3 cd 0f 55 fd 12 \tvfixupimmsd $0x12,%xmm5,%xmm6,%xmm7{%k7}",}, | ||
923 | {{0x62, 0xf3, 0x7d, 0x48, 0x56, 0xfe, 0x12, }, 7, 0, "", "", | ||
924 | "62 f3 7d 48 56 fe 12 \tvreduceps $0x12,%zmm6,%zmm7",}, | ||
925 | {{0x62, 0xf3, 0xfd, 0x48, 0x56, 0xfe, 0x12, }, 7, 0, "", "", | ||
926 | "62 f3 fd 48 56 fe 12 \tvreducepd $0x12,%zmm6,%zmm7",}, | ||
927 | {{0x62, 0xf3, 0x4d, 0x08, 0x57, 0xfd, 0x12, }, 7, 0, "", "", | ||
928 | "62 f3 4d 08 57 fd 12 \tvreducess $0x12,%xmm5,%xmm6,%xmm7",}, | ||
929 | {{0x62, 0xf3, 0xcd, 0x08, 0x57, 0xfd, 0x12, }, 7, 0, "", "", | ||
930 | "62 f3 cd 08 57 fd 12 \tvreducesd $0x12,%xmm5,%xmm6,%xmm7",}, | ||
931 | {{0x62, 0xf3, 0x7d, 0x48, 0x66, 0xef, 0x12, }, 7, 0, "", "", | ||
932 | "62 f3 7d 48 66 ef 12 \tvfpclassps $0x12,%zmm7,%k5",}, | ||
933 | {{0x62, 0xf3, 0xfd, 0x48, 0x66, 0xef, 0x12, }, 7, 0, "", "", | ||
934 | "62 f3 fd 48 66 ef 12 \tvfpclasspd $0x12,%zmm7,%k5",}, | ||
935 | {{0x62, 0xf3, 0x7d, 0x08, 0x67, 0xef, 0x12, }, 7, 0, "", "", | ||
936 | "62 f3 7d 08 67 ef 12 \tvfpclassss $0x12,%xmm7,%k5",}, | ||
937 | {{0x62, 0xf3, 0xfd, 0x08, 0x67, 0xef, 0x12, }, 7, 0, "", "", | ||
938 | "62 f3 fd 08 67 ef 12 \tvfpclasssd $0x12,%xmm7,%k5",}, | ||
939 | {{0x62, 0xf1, 0x4d, 0x48, 0x72, 0xc5, 0x12, }, 7, 0, "", "", | ||
940 | "62 f1 4d 48 72 c5 12 \tvprord $0x12,%zmm5,%zmm6",}, | ||
941 | {{0x62, 0xf1, 0xcd, 0x48, 0x72, 0xc5, 0x12, }, 7, 0, "", "", | ||
942 | "62 f1 cd 48 72 c5 12 \tvprorq $0x12,%zmm5,%zmm6",}, | ||
943 | {{0x62, 0xf1, 0x4d, 0x48, 0x72, 0xcd, 0x12, }, 7, 0, "", "", | ||
944 | "62 f1 4d 48 72 cd 12 \tvprold $0x12,%zmm5,%zmm6",}, | ||
945 | {{0x62, 0xf1, 0xcd, 0x48, 0x72, 0xcd, 0x12, }, 7, 0, "", "", | ||
946 | "62 f1 cd 48 72 cd 12 \tvprolq $0x12,%zmm5,%zmm6",}, | ||
947 | {{0x0f, 0x72, 0xe6, 0x02, }, 4, 0, "", "", | ||
948 | "0f 72 e6 02 \tpsrad $0x2,%mm6",}, | ||
949 | {{0xc5, 0xed, 0x72, 0xe6, 0x05, }, 5, 0, "", "", | ||
950 | "c5 ed 72 e6 05 \tvpsrad $0x5,%ymm6,%ymm2",}, | ||
951 | {{0x62, 0xf1, 0x6d, 0x48, 0x72, 0xe6, 0x05, }, 7, 0, "", "", | ||
952 | "62 f1 6d 48 72 e6 05 \tvpsrad $0x5,%zmm6,%zmm2",}, | ||
953 | {{0x62, 0xf1, 0xed, 0x48, 0x72, 0xe6, 0x05, }, 7, 0, "", "", | ||
954 | "62 f1 ed 48 72 e6 05 \tvpsraq $0x5,%zmm6,%zmm2",}, | ||
955 | {{0x62, 0xf2, 0x7d, 0x49, 0xc6, 0x8c, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
956 | "62 f2 7d 49 c6 8c fd 7b 00 00 00 \tvgatherpf0dps 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
957 | {{0x62, 0xf2, 0xfd, 0x49, 0xc6, 0x8c, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
958 | "62 f2 fd 49 c6 8c fd 7b 00 00 00 \tvgatherpf0dpd 0x7b(%ebp,%ymm7,8){%k1}",}, | ||
959 | {{0x62, 0xf2, 0x7d, 0x49, 0xc6, 0x94, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
960 | "62 f2 7d 49 c6 94 fd 7b 00 00 00 \tvgatherpf1dps 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
961 | {{0x62, 0xf2, 0xfd, 0x49, 0xc6, 0x94, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
962 | "62 f2 fd 49 c6 94 fd 7b 00 00 00 \tvgatherpf1dpd 0x7b(%ebp,%ymm7,8){%k1}",}, | ||
963 | {{0x62, 0xf2, 0x7d, 0x49, 0xc6, 0xac, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
964 | "62 f2 7d 49 c6 ac fd 7b 00 00 00 \tvscatterpf0dps 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
965 | {{0x62, 0xf2, 0xfd, 0x49, 0xc6, 0xac, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
966 | "62 f2 fd 49 c6 ac fd 7b 00 00 00 \tvscatterpf0dpd 0x7b(%ebp,%ymm7,8){%k1}",}, | ||
967 | {{0x62, 0xf2, 0x7d, 0x49, 0xc6, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
968 | "62 f2 7d 49 c6 b4 fd 7b 00 00 00 \tvscatterpf1dps 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
969 | {{0x62, 0xf2, 0xfd, 0x49, 0xc6, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
970 | "62 f2 fd 49 c6 b4 fd 7b 00 00 00 \tvscatterpf1dpd 0x7b(%ebp,%ymm7,8){%k1}",}, | ||
971 | {{0x62, 0xf2, 0x7d, 0x49, 0xc7, 0x8c, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
972 | "62 f2 7d 49 c7 8c fd 7b 00 00 00 \tvgatherpf0qps 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
973 | {{0x62, 0xf2, 0xfd, 0x49, 0xc7, 0x8c, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
974 | "62 f2 fd 49 c7 8c fd 7b 00 00 00 \tvgatherpf0qpd 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
975 | {{0x62, 0xf2, 0x7d, 0x49, 0xc7, 0x94, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
976 | "62 f2 7d 49 c7 94 fd 7b 00 00 00 \tvgatherpf1qps 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
977 | {{0x62, 0xf2, 0xfd, 0x49, 0xc7, 0x94, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
978 | "62 f2 fd 49 c7 94 fd 7b 00 00 00 \tvgatherpf1qpd 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
979 | {{0x62, 0xf2, 0x7d, 0x49, 0xc7, 0xac, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
980 | "62 f2 7d 49 c7 ac fd 7b 00 00 00 \tvscatterpf0qps 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
981 | {{0x62, 0xf2, 0xfd, 0x49, 0xc7, 0xac, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
982 | "62 f2 fd 49 c7 ac fd 7b 00 00 00 \tvscatterpf0qpd 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
983 | {{0x62, 0xf2, 0x7d, 0x49, 0xc7, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
984 | "62 f2 7d 49 c7 b4 fd 7b 00 00 00 \tvscatterpf1qps 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
985 | {{0x62, 0xf2, 0xfd, 0x49, 0xc7, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
986 | "62 f2 fd 49 c7 b4 fd 7b 00 00 00 \tvscatterpf1qpd 0x7b(%ebp,%zmm7,8){%k1}",}, | ||
987 | {{0x62, 0xf1, 0xd5, 0x48, 0x58, 0xf4, }, 6, 0, "", "", | ||
988 | "62 f1 d5 48 58 f4 \tvaddpd %zmm4,%zmm5,%zmm6",}, | ||
989 | {{0x62, 0xf1, 0xd5, 0x4f, 0x58, 0xf4, }, 6, 0, "", "", | ||
990 | "62 f1 d5 4f 58 f4 \tvaddpd %zmm4,%zmm5,%zmm6{%k7}",}, | ||
991 | {{0x62, 0xf1, 0xd5, 0xcf, 0x58, 0xf4, }, 6, 0, "", "", | ||
992 | "62 f1 d5 cf 58 f4 \tvaddpd %zmm4,%zmm5,%zmm6{%k7}{z}",}, | ||
993 | {{0x62, 0xf1, 0xd5, 0x18, 0x58, 0xf4, }, 6, 0, "", "", | ||
994 | "62 f1 d5 18 58 f4 \tvaddpd {rn-sae},%zmm4,%zmm5,%zmm6",}, | ||
995 | {{0x62, 0xf1, 0xd5, 0x58, 0x58, 0xf4, }, 6, 0, "", "", | ||
996 | "62 f1 d5 58 58 f4 \tvaddpd {ru-sae},%zmm4,%zmm5,%zmm6",}, | ||
997 | {{0x62, 0xf1, 0xd5, 0x38, 0x58, 0xf4, }, 6, 0, "", "", | ||
998 | "62 f1 d5 38 58 f4 \tvaddpd {rd-sae},%zmm4,%zmm5,%zmm6",}, | ||
999 | {{0x62, 0xf1, 0xd5, 0x78, 0x58, 0xf4, }, 6, 0, "", "", | ||
1000 | "62 f1 d5 78 58 f4 \tvaddpd {rz-sae},%zmm4,%zmm5,%zmm6",}, | ||
1001 | {{0x62, 0xf1, 0xd5, 0x48, 0x58, 0x31, }, 6, 0, "", "", | ||
1002 | "62 f1 d5 48 58 31 \tvaddpd (%ecx),%zmm5,%zmm6",}, | ||
1003 | {{0x62, 0xf1, 0xd5, 0x48, 0x58, 0xb4, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 11, 0, "", "", | ||
1004 | "62 f1 d5 48 58 b4 c8 23 01 00 00 \tvaddpd 0x123(%eax,%ecx,8),%zmm5,%zmm6",}, | ||
1005 | {{0x62, 0xf1, 0xd5, 0x58, 0x58, 0x31, }, 6, 0, "", "", | ||
1006 | "62 f1 d5 58 58 31 \tvaddpd (%ecx){1to8},%zmm5,%zmm6",}, | ||
1007 | {{0x62, 0xf1, 0xd5, 0x48, 0x58, 0x72, 0x7f, }, 7, 0, "", "", | ||
1008 | "62 f1 d5 48 58 72 7f \tvaddpd 0x1fc0(%edx),%zmm5,%zmm6",}, | ||
1009 | {{0x62, 0xf1, 0xd5, 0x58, 0x58, 0x72, 0x7f, }, 7, 0, "", "", | ||
1010 | "62 f1 d5 58 58 72 7f \tvaddpd 0x3f8(%edx){1to8},%zmm5,%zmm6",}, | ||
1011 | {{0x62, 0xf1, 0x4c, 0x58, 0xc2, 0x6a, 0x7f, 0x08, }, 8, 0, "", "", | ||
1012 | "62 f1 4c 58 c2 6a 7f 08 \tvcmpeq_uqps 0x1fc(%edx){1to16},%zmm6,%k5",}, | ||
1013 | {{0x62, 0xf1, 0xe7, 0x0f, 0xc2, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, 0x01, }, 12, 0, "", "", | ||
1014 | "62 f1 e7 0f c2 ac c8 23 01 00 00 01 \tvcmpltsd 0x123(%eax,%ecx,8),%xmm3,%k5{%k7}",}, | ||
1015 | {{0x62, 0xf1, 0xd7, 0x1f, 0xc2, 0xec, 0x02, }, 7, 0, "", "", | ||
1016 | "62 f1 d7 1f c2 ec 02 \tvcmplesd {sae},%xmm4,%xmm5,%k5{%k7}",}, | ||
1017 | {{0x62, 0xf3, 0x5d, 0x0f, 0x27, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, 0x5b, }, 12, 0, "", "", | ||
1018 | "62 f3 5d 0f 27 ac c8 23 01 00 00 5b \tvgetmantss $0x5b,0x123(%eax,%ecx,8),%xmm4,%xmm5{%k7}",}, | ||
9 | {{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", | 1019 | {{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", |
10 | "f3 0f 1b 00 \tbndmk (%eax),%bnd0",}, | 1020 | "f3 0f 1b 00 \tbndmk (%eax),%bnd0",}, |
11 | {{0xf3, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | 1021 | {{0xf3, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", |
@@ -309,19 +1319,19 @@ | |||
309 | {{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | 1319 | {{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)",}, | 1320 | "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", | 1321 | {{0xf2, 0xe8, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "call", "unconditional", |
312 | "f2 e8 fc ff ff ff \tbnd call 3c3 <main+0x3c3>",}, | 1322 | "f2 e8 fc ff ff ff \tbnd call fce <main+0xfce>",}, |
313 | {{0xf2, 0xff, 0x10, }, 3, 0, "call", "indirect", | 1323 | {{0xf2, 0xff, 0x10, }, 3, 0, "call", "indirect", |
314 | "f2 ff 10 \tbnd call *(%eax)",}, | 1324 | "f2 ff 10 \tbnd call *(%eax)",}, |
315 | {{0xf2, 0xc3, }, 2, 0, "ret", "indirect", | 1325 | {{0xf2, 0xc3, }, 2, 0, "ret", "indirect", |
316 | "f2 c3 \tbnd ret ",}, | 1326 | "f2 c3 \tbnd ret ",}, |
317 | {{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional", | 1327 | {{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional", |
318 | "f2 e9 fc ff ff ff \tbnd jmp 3ce <main+0x3ce>",}, | 1328 | "f2 e9 fc ff ff ff \tbnd jmp fd9 <main+0xfd9>",}, |
319 | {{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional", | 1329 | {{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional", |
320 | "f2 e9 fc ff ff ff \tbnd jmp 3d4 <main+0x3d4>",}, | 1330 | "f2 e9 fc ff ff ff \tbnd jmp fdf <main+0xfdf>",}, |
321 | {{0xf2, 0xff, 0x21, }, 3, 0, "jmp", "indirect", | 1331 | {{0xf2, 0xff, 0x21, }, 3, 0, "jmp", "indirect", |
322 | "f2 ff 21 \tbnd jmp *(%ecx)",}, | 1332 | "f2 ff 21 \tbnd jmp *(%ecx)",}, |
323 | {{0xf2, 0x0f, 0x85, 0xfc, 0xff, 0xff, 0xff, }, 7, 0xfffffffc, "jcc", "conditional", | 1333 | {{0xf2, 0x0f, 0x85, 0xfc, 0xff, 0xff, 0xff, }, 7, 0xfffffffc, "jcc", "conditional", |
324 | "f2 0f 85 fc ff ff ff \tbnd jne 3de <main+0x3de>",}, | 1334 | "f2 0f 85 fc ff ff ff \tbnd jne fe9 <main+0xfe9>",}, |
325 | {{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "", | 1335 | {{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "", |
326 | "0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",}, | 1336 | "0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",}, |
327 | {{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "", | 1337 | {{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "", |
@@ -654,5 +1664,3 @@ | |||
654 | "0f c7 1d 78 56 34 12 \txrstors 0x12345678",}, | 1664 | "0f c7 1d 78 56 34 12 \txrstors 0x12345678",}, |
655 | {{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | 1665 | {{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", |
656 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",}, | 1666 | "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 index 4fe7cce179c4..af25bc8240d0 100644 --- a/tools/perf/arch/x86/tests/insn-x86-dat-64.c +++ b/tools/perf/arch/x86/tests/insn-x86-dat-64.c | |||
@@ -6,6 +6,938 @@ | |||
6 | 6 | ||
7 | {{0x0f, 0x31, }, 2, 0, "", "", | 7 | {{0x0f, 0x31, }, 2, 0, "", "", |
8 | "0f 31 \trdtsc ",}, | 8 | "0f 31 \trdtsc ",}, |
9 | {{0xc4, 0xe2, 0x7d, 0x13, 0xeb, }, 5, 0, "", "", | ||
10 | "c4 e2 7d 13 eb \tvcvtph2ps %xmm3,%ymm5",}, | ||
11 | {{0x48, 0x0f, 0x41, 0xd8, }, 4, 0, "", "", | ||
12 | "48 0f 41 d8 \tcmovno %rax,%rbx",}, | ||
13 | {{0x48, 0x0f, 0x41, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
14 | "48 0f 41 88 78 56 34 12 \tcmovno 0x12345678(%rax),%rcx",}, | ||
15 | {{0x66, 0x0f, 0x41, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
16 | "66 0f 41 88 78 56 34 12 \tcmovno 0x12345678(%rax),%cx",}, | ||
17 | {{0x48, 0x0f, 0x44, 0xd8, }, 4, 0, "", "", | ||
18 | "48 0f 44 d8 \tcmove %rax,%rbx",}, | ||
19 | {{0x48, 0x0f, 0x44, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
20 | "48 0f 44 88 78 56 34 12 \tcmove 0x12345678(%rax),%rcx",}, | ||
21 | {{0x66, 0x0f, 0x44, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
22 | "66 0f 44 88 78 56 34 12 \tcmove 0x12345678(%rax),%cx",}, | ||
23 | {{0x0f, 0x90, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
24 | "0f 90 80 78 56 34 12 \tseto 0x12345678(%rax)",}, | ||
25 | {{0x0f, 0x91, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
26 | "0f 91 80 78 56 34 12 \tsetno 0x12345678(%rax)",}, | ||
27 | {{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
28 | "0f 92 80 78 56 34 12 \tsetb 0x12345678(%rax)",}, | ||
29 | {{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
30 | "0f 92 80 78 56 34 12 \tsetb 0x12345678(%rax)",}, | ||
31 | {{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
32 | "0f 92 80 78 56 34 12 \tsetb 0x12345678(%rax)",}, | ||
33 | {{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
34 | "0f 93 80 78 56 34 12 \tsetae 0x12345678(%rax)",}, | ||
35 | {{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
36 | "0f 93 80 78 56 34 12 \tsetae 0x12345678(%rax)",}, | ||
37 | {{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
38 | "0f 93 80 78 56 34 12 \tsetae 0x12345678(%rax)",}, | ||
39 | {{0x0f, 0x98, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
40 | "0f 98 80 78 56 34 12 \tsets 0x12345678(%rax)",}, | ||
41 | {{0x0f, 0x99, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
42 | "0f 99 80 78 56 34 12 \tsetns 0x12345678(%rax)",}, | ||
43 | {{0xc5, 0xcc, 0x41, 0xef, }, 4, 0, "", "", | ||
44 | "c5 cc 41 ef \tkandw %k7,%k6,%k5",}, | ||
45 | {{0xc4, 0xe1, 0xcc, 0x41, 0xef, }, 5, 0, "", "", | ||
46 | "c4 e1 cc 41 ef \tkandq %k7,%k6,%k5",}, | ||
47 | {{0xc5, 0xcd, 0x41, 0xef, }, 4, 0, "", "", | ||
48 | "c5 cd 41 ef \tkandb %k7,%k6,%k5",}, | ||
49 | {{0xc4, 0xe1, 0xcd, 0x41, 0xef, }, 5, 0, "", "", | ||
50 | "c4 e1 cd 41 ef \tkandd %k7,%k6,%k5",}, | ||
51 | {{0xc5, 0xcc, 0x42, 0xef, }, 4, 0, "", "", | ||
52 | "c5 cc 42 ef \tkandnw %k7,%k6,%k5",}, | ||
53 | {{0xc4, 0xe1, 0xcc, 0x42, 0xef, }, 5, 0, "", "", | ||
54 | "c4 e1 cc 42 ef \tkandnq %k7,%k6,%k5",}, | ||
55 | {{0xc5, 0xcd, 0x42, 0xef, }, 4, 0, "", "", | ||
56 | "c5 cd 42 ef \tkandnb %k7,%k6,%k5",}, | ||
57 | {{0xc4, 0xe1, 0xcd, 0x42, 0xef, }, 5, 0, "", "", | ||
58 | "c4 e1 cd 42 ef \tkandnd %k7,%k6,%k5",}, | ||
59 | {{0xc5, 0xf8, 0x44, 0xf7, }, 4, 0, "", "", | ||
60 | "c5 f8 44 f7 \tknotw %k7,%k6",}, | ||
61 | {{0xc4, 0xe1, 0xf8, 0x44, 0xf7, }, 5, 0, "", "", | ||
62 | "c4 e1 f8 44 f7 \tknotq %k7,%k6",}, | ||
63 | {{0xc5, 0xf9, 0x44, 0xf7, }, 4, 0, "", "", | ||
64 | "c5 f9 44 f7 \tknotb %k7,%k6",}, | ||
65 | {{0xc4, 0xe1, 0xf9, 0x44, 0xf7, }, 5, 0, "", "", | ||
66 | "c4 e1 f9 44 f7 \tknotd %k7,%k6",}, | ||
67 | {{0xc5, 0xcc, 0x45, 0xef, }, 4, 0, "", "", | ||
68 | "c5 cc 45 ef \tkorw %k7,%k6,%k5",}, | ||
69 | {{0xc4, 0xe1, 0xcc, 0x45, 0xef, }, 5, 0, "", "", | ||
70 | "c4 e1 cc 45 ef \tkorq %k7,%k6,%k5",}, | ||
71 | {{0xc5, 0xcd, 0x45, 0xef, }, 4, 0, "", "", | ||
72 | "c5 cd 45 ef \tkorb %k7,%k6,%k5",}, | ||
73 | {{0xc4, 0xe1, 0xcd, 0x45, 0xef, }, 5, 0, "", "", | ||
74 | "c4 e1 cd 45 ef \tkord %k7,%k6,%k5",}, | ||
75 | {{0xc5, 0xcc, 0x46, 0xef, }, 4, 0, "", "", | ||
76 | "c5 cc 46 ef \tkxnorw %k7,%k6,%k5",}, | ||
77 | {{0xc4, 0xe1, 0xcc, 0x46, 0xef, }, 5, 0, "", "", | ||
78 | "c4 e1 cc 46 ef \tkxnorq %k7,%k6,%k5",}, | ||
79 | {{0xc5, 0xcd, 0x46, 0xef, }, 4, 0, "", "", | ||
80 | "c5 cd 46 ef \tkxnorb %k7,%k6,%k5",}, | ||
81 | {{0xc4, 0xe1, 0xcd, 0x46, 0xef, }, 5, 0, "", "", | ||
82 | "c4 e1 cd 46 ef \tkxnord %k7,%k6,%k5",}, | ||
83 | {{0xc5, 0xcc, 0x47, 0xef, }, 4, 0, "", "", | ||
84 | "c5 cc 47 ef \tkxorw %k7,%k6,%k5",}, | ||
85 | {{0xc4, 0xe1, 0xcc, 0x47, 0xef, }, 5, 0, "", "", | ||
86 | "c4 e1 cc 47 ef \tkxorq %k7,%k6,%k5",}, | ||
87 | {{0xc5, 0xcd, 0x47, 0xef, }, 4, 0, "", "", | ||
88 | "c5 cd 47 ef \tkxorb %k7,%k6,%k5",}, | ||
89 | {{0xc4, 0xe1, 0xcd, 0x47, 0xef, }, 5, 0, "", "", | ||
90 | "c4 e1 cd 47 ef \tkxord %k7,%k6,%k5",}, | ||
91 | {{0xc5, 0xcc, 0x4a, 0xef, }, 4, 0, "", "", | ||
92 | "c5 cc 4a ef \tkaddw %k7,%k6,%k5",}, | ||
93 | {{0xc4, 0xe1, 0xcc, 0x4a, 0xef, }, 5, 0, "", "", | ||
94 | "c4 e1 cc 4a ef \tkaddq %k7,%k6,%k5",}, | ||
95 | {{0xc5, 0xcd, 0x4a, 0xef, }, 4, 0, "", "", | ||
96 | "c5 cd 4a ef \tkaddb %k7,%k6,%k5",}, | ||
97 | {{0xc4, 0xe1, 0xcd, 0x4a, 0xef, }, 5, 0, "", "", | ||
98 | "c4 e1 cd 4a ef \tkaddd %k7,%k6,%k5",}, | ||
99 | {{0xc5, 0xcd, 0x4b, 0xef, }, 4, 0, "", "", | ||
100 | "c5 cd 4b ef \tkunpckbw %k7,%k6,%k5",}, | ||
101 | {{0xc5, 0xcc, 0x4b, 0xef, }, 4, 0, "", "", | ||
102 | "c5 cc 4b ef \tkunpckwd %k7,%k6,%k5",}, | ||
103 | {{0xc4, 0xe1, 0xcc, 0x4b, 0xef, }, 5, 0, "", "", | ||
104 | "c4 e1 cc 4b ef \tkunpckdq %k7,%k6,%k5",}, | ||
105 | {{0xc5, 0xf8, 0x90, 0xee, }, 4, 0, "", "", | ||
106 | "c5 f8 90 ee \tkmovw %k6,%k5",}, | ||
107 | {{0xc5, 0xf8, 0x90, 0x29, }, 4, 0, "", "", | ||
108 | "c5 f8 90 29 \tkmovw (%rcx),%k5",}, | ||
109 | {{0xc4, 0xa1, 0x78, 0x90, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
110 | "c4 a1 78 90 ac f0 23 01 00 00 \tkmovw 0x123(%rax,%r14,8),%k5",}, | ||
111 | {{0xc5, 0xf8, 0x91, 0x29, }, 4, 0, "", "", | ||
112 | "c5 f8 91 29 \tkmovw %k5,(%rcx)",}, | ||
113 | {{0xc4, 0xa1, 0x78, 0x91, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
114 | "c4 a1 78 91 ac f0 23 01 00 00 \tkmovw %k5,0x123(%rax,%r14,8)",}, | ||
115 | {{0xc5, 0xf8, 0x92, 0xe8, }, 4, 0, "", "", | ||
116 | "c5 f8 92 e8 \tkmovw %eax,%k5",}, | ||
117 | {{0xc5, 0xf8, 0x92, 0xed, }, 4, 0, "", "", | ||
118 | "c5 f8 92 ed \tkmovw %ebp,%k5",}, | ||
119 | {{0xc4, 0xc1, 0x78, 0x92, 0xed, }, 5, 0, "", "", | ||
120 | "c4 c1 78 92 ed \tkmovw %r13d,%k5",}, | ||
121 | {{0xc5, 0xf8, 0x93, 0xc5, }, 4, 0, "", "", | ||
122 | "c5 f8 93 c5 \tkmovw %k5,%eax",}, | ||
123 | {{0xc5, 0xf8, 0x93, 0xed, }, 4, 0, "", "", | ||
124 | "c5 f8 93 ed \tkmovw %k5,%ebp",}, | ||
125 | {{0xc5, 0x78, 0x93, 0xed, }, 4, 0, "", "", | ||
126 | "c5 78 93 ed \tkmovw %k5,%r13d",}, | ||
127 | {{0xc4, 0xe1, 0xf8, 0x90, 0xee, }, 5, 0, "", "", | ||
128 | "c4 e1 f8 90 ee \tkmovq %k6,%k5",}, | ||
129 | {{0xc4, 0xe1, 0xf8, 0x90, 0x29, }, 5, 0, "", "", | ||
130 | "c4 e1 f8 90 29 \tkmovq (%rcx),%k5",}, | ||
131 | {{0xc4, 0xa1, 0xf8, 0x90, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
132 | "c4 a1 f8 90 ac f0 23 01 00 00 \tkmovq 0x123(%rax,%r14,8),%k5",}, | ||
133 | {{0xc4, 0xe1, 0xf8, 0x91, 0x29, }, 5, 0, "", "", | ||
134 | "c4 e1 f8 91 29 \tkmovq %k5,(%rcx)",}, | ||
135 | {{0xc4, 0xa1, 0xf8, 0x91, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
136 | "c4 a1 f8 91 ac f0 23 01 00 00 \tkmovq %k5,0x123(%rax,%r14,8)",}, | ||
137 | {{0xc4, 0xe1, 0xfb, 0x92, 0xe8, }, 5, 0, "", "", | ||
138 | "c4 e1 fb 92 e8 \tkmovq %rax,%k5",}, | ||
139 | {{0xc4, 0xe1, 0xfb, 0x92, 0xed, }, 5, 0, "", "", | ||
140 | "c4 e1 fb 92 ed \tkmovq %rbp,%k5",}, | ||
141 | {{0xc4, 0xc1, 0xfb, 0x92, 0xed, }, 5, 0, "", "", | ||
142 | "c4 c1 fb 92 ed \tkmovq %r13,%k5",}, | ||
143 | {{0xc4, 0xe1, 0xfb, 0x93, 0xc5, }, 5, 0, "", "", | ||
144 | "c4 e1 fb 93 c5 \tkmovq %k5,%rax",}, | ||
145 | {{0xc4, 0xe1, 0xfb, 0x93, 0xed, }, 5, 0, "", "", | ||
146 | "c4 e1 fb 93 ed \tkmovq %k5,%rbp",}, | ||
147 | {{0xc4, 0x61, 0xfb, 0x93, 0xed, }, 5, 0, "", "", | ||
148 | "c4 61 fb 93 ed \tkmovq %k5,%r13",}, | ||
149 | {{0xc5, 0xf9, 0x90, 0xee, }, 4, 0, "", "", | ||
150 | "c5 f9 90 ee \tkmovb %k6,%k5",}, | ||
151 | {{0xc5, 0xf9, 0x90, 0x29, }, 4, 0, "", "", | ||
152 | "c5 f9 90 29 \tkmovb (%rcx),%k5",}, | ||
153 | {{0xc4, 0xa1, 0x79, 0x90, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
154 | "c4 a1 79 90 ac f0 23 01 00 00 \tkmovb 0x123(%rax,%r14,8),%k5",}, | ||
155 | {{0xc5, 0xf9, 0x91, 0x29, }, 4, 0, "", "", | ||
156 | "c5 f9 91 29 \tkmovb %k5,(%rcx)",}, | ||
157 | {{0xc4, 0xa1, 0x79, 0x91, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
158 | "c4 a1 79 91 ac f0 23 01 00 00 \tkmovb %k5,0x123(%rax,%r14,8)",}, | ||
159 | {{0xc5, 0xf9, 0x92, 0xe8, }, 4, 0, "", "", | ||
160 | "c5 f9 92 e8 \tkmovb %eax,%k5",}, | ||
161 | {{0xc5, 0xf9, 0x92, 0xed, }, 4, 0, "", "", | ||
162 | "c5 f9 92 ed \tkmovb %ebp,%k5",}, | ||
163 | {{0xc4, 0xc1, 0x79, 0x92, 0xed, }, 5, 0, "", "", | ||
164 | "c4 c1 79 92 ed \tkmovb %r13d,%k5",}, | ||
165 | {{0xc5, 0xf9, 0x93, 0xc5, }, 4, 0, "", "", | ||
166 | "c5 f9 93 c5 \tkmovb %k5,%eax",}, | ||
167 | {{0xc5, 0xf9, 0x93, 0xed, }, 4, 0, "", "", | ||
168 | "c5 f9 93 ed \tkmovb %k5,%ebp",}, | ||
169 | {{0xc5, 0x79, 0x93, 0xed, }, 4, 0, "", "", | ||
170 | "c5 79 93 ed \tkmovb %k5,%r13d",}, | ||
171 | {{0xc4, 0xe1, 0xf9, 0x90, 0xee, }, 5, 0, "", "", | ||
172 | "c4 e1 f9 90 ee \tkmovd %k6,%k5",}, | ||
173 | {{0xc4, 0xe1, 0xf9, 0x90, 0x29, }, 5, 0, "", "", | ||
174 | "c4 e1 f9 90 29 \tkmovd (%rcx),%k5",}, | ||
175 | {{0xc4, 0xa1, 0xf9, 0x90, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
176 | "c4 a1 f9 90 ac f0 23 01 00 00 \tkmovd 0x123(%rax,%r14,8),%k5",}, | ||
177 | {{0xc4, 0xe1, 0xf9, 0x91, 0x29, }, 5, 0, "", "", | ||
178 | "c4 e1 f9 91 29 \tkmovd %k5,(%rcx)",}, | ||
179 | {{0xc4, 0xa1, 0xf9, 0x91, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "", | ||
180 | "c4 a1 f9 91 ac f0 23 01 00 00 \tkmovd %k5,0x123(%rax,%r14,8)",}, | ||
181 | {{0xc5, 0xfb, 0x92, 0xe8, }, 4, 0, "", "", | ||
182 | "c5 fb 92 e8 \tkmovd %eax,%k5",}, | ||
183 | {{0xc5, 0xfb, 0x92, 0xed, }, 4, 0, "", "", | ||
184 | "c5 fb 92 ed \tkmovd %ebp,%k5",}, | ||
185 | {{0xc4, 0xc1, 0x7b, 0x92, 0xed, }, 5, 0, "", "", | ||
186 | "c4 c1 7b 92 ed \tkmovd %r13d,%k5",}, | ||
187 | {{0xc5, 0xfb, 0x93, 0xc5, }, 4, 0, "", "", | ||
188 | "c5 fb 93 c5 \tkmovd %k5,%eax",}, | ||
189 | {{0xc5, 0xfb, 0x93, 0xed, }, 4, 0, "", "", | ||
190 | "c5 fb 93 ed \tkmovd %k5,%ebp",}, | ||
191 | {{0xc5, 0x7b, 0x93, 0xed, }, 4, 0, "", "", | ||
192 | "c5 7b 93 ed \tkmovd %k5,%r13d",}, | ||
193 | {{0xc5, 0xf8, 0x98, 0xee, }, 4, 0, "", "", | ||
194 | "c5 f8 98 ee \tkortestw %k6,%k5",}, | ||
195 | {{0xc4, 0xe1, 0xf8, 0x98, 0xee, }, 5, 0, "", "", | ||
196 | "c4 e1 f8 98 ee \tkortestq %k6,%k5",}, | ||
197 | {{0xc5, 0xf9, 0x98, 0xee, }, 4, 0, "", "", | ||
198 | "c5 f9 98 ee \tkortestb %k6,%k5",}, | ||
199 | {{0xc4, 0xe1, 0xf9, 0x98, 0xee, }, 5, 0, "", "", | ||
200 | "c4 e1 f9 98 ee \tkortestd %k6,%k5",}, | ||
201 | {{0xc5, 0xf8, 0x99, 0xee, }, 4, 0, "", "", | ||
202 | "c5 f8 99 ee \tktestw %k6,%k5",}, | ||
203 | {{0xc4, 0xe1, 0xf8, 0x99, 0xee, }, 5, 0, "", "", | ||
204 | "c4 e1 f8 99 ee \tktestq %k6,%k5",}, | ||
205 | {{0xc5, 0xf9, 0x99, 0xee, }, 4, 0, "", "", | ||
206 | "c5 f9 99 ee \tktestb %k6,%k5",}, | ||
207 | {{0xc4, 0xe1, 0xf9, 0x99, 0xee, }, 5, 0, "", "", | ||
208 | "c4 e1 f9 99 ee \tktestd %k6,%k5",}, | ||
209 | {{0xc4, 0xe3, 0xf9, 0x30, 0xee, 0x12, }, 6, 0, "", "", | ||
210 | "c4 e3 f9 30 ee 12 \tkshiftrw $0x12,%k6,%k5",}, | ||
211 | {{0xc4, 0xe3, 0xf9, 0x31, 0xee, 0x5b, }, 6, 0, "", "", | ||
212 | "c4 e3 f9 31 ee 5b \tkshiftrq $0x5b,%k6,%k5",}, | ||
213 | {{0xc4, 0xe3, 0xf9, 0x32, 0xee, 0x12, }, 6, 0, "", "", | ||
214 | "c4 e3 f9 32 ee 12 \tkshiftlw $0x12,%k6,%k5",}, | ||
215 | {{0xc4, 0xe3, 0xf9, 0x33, 0xee, 0x5b, }, 6, 0, "", "", | ||
216 | "c4 e3 f9 33 ee 5b \tkshiftlq $0x5b,%k6,%k5",}, | ||
217 | {{0xc5, 0xf8, 0x5b, 0xf5, }, 4, 0, "", "", | ||
218 | "c5 f8 5b f5 \tvcvtdq2ps %xmm5,%xmm6",}, | ||
219 | {{0x62, 0x91, 0xfc, 0x4f, 0x5b, 0xf5, }, 6, 0, "", "", | ||
220 | "62 91 fc 4f 5b f5 \tvcvtqq2ps %zmm29,%ymm6{%k7}",}, | ||
221 | {{0xc5, 0xf9, 0x5b, 0xf5, }, 4, 0, "", "", | ||
222 | "c5 f9 5b f5 \tvcvtps2dq %xmm5,%xmm6",}, | ||
223 | {{0xc5, 0xfa, 0x5b, 0xf5, }, 4, 0, "", "", | ||
224 | "c5 fa 5b f5 \tvcvttps2dq %xmm5,%xmm6",}, | ||
225 | {{0x0f, 0x6f, 0xe0, }, 3, 0, "", "", | ||
226 | "0f 6f e0 \tmovq %mm0,%mm4",}, | ||
227 | {{0xc5, 0xfd, 0x6f, 0xf4, }, 4, 0, "", "", | ||
228 | "c5 fd 6f f4 \tvmovdqa %ymm4,%ymm6",}, | ||
229 | {{0x62, 0x01, 0x7d, 0x48, 0x6f, 0xd1, }, 6, 0, "", "", | ||
230 | "62 01 7d 48 6f d1 \tvmovdqa32 %zmm25,%zmm26",}, | ||
231 | {{0x62, 0x01, 0xfd, 0x48, 0x6f, 0xd1, }, 6, 0, "", "", | ||
232 | "62 01 fd 48 6f d1 \tvmovdqa64 %zmm25,%zmm26",}, | ||
233 | {{0xc5, 0xfe, 0x6f, 0xf4, }, 4, 0, "", "", | ||
234 | "c5 fe 6f f4 \tvmovdqu %ymm4,%ymm6",}, | ||
235 | {{0x62, 0x01, 0x7e, 0x48, 0x6f, 0xf5, }, 6, 0, "", "", | ||
236 | "62 01 7e 48 6f f5 \tvmovdqu32 %zmm29,%zmm30",}, | ||
237 | {{0x62, 0x01, 0xfe, 0x48, 0x6f, 0xd1, }, 6, 0, "", "", | ||
238 | "62 01 fe 48 6f d1 \tvmovdqu64 %zmm25,%zmm26",}, | ||
239 | {{0x62, 0x01, 0x7f, 0x48, 0x6f, 0xf5, }, 6, 0, "", "", | ||
240 | "62 01 7f 48 6f f5 \tvmovdqu8 %zmm29,%zmm30",}, | ||
241 | {{0x62, 0x01, 0xff, 0x48, 0x6f, 0xd1, }, 6, 0, "", "", | ||
242 | "62 01 ff 48 6f d1 \tvmovdqu16 %zmm25,%zmm26",}, | ||
243 | {{0x0f, 0x78, 0xc3, }, 3, 0, "", "", | ||
244 | "0f 78 c3 \tvmread %rax,%rbx",}, | ||
245 | {{0x62, 0x01, 0x7c, 0x48, 0x78, 0xd1, }, 6, 0, "", "", | ||
246 | "62 01 7c 48 78 d1 \tvcvttps2udq %zmm25,%zmm26",}, | ||
247 | {{0x62, 0x91, 0xfc, 0x4f, 0x78, 0xf5, }, 6, 0, "", "", | ||
248 | "62 91 fc 4f 78 f5 \tvcvttpd2udq %zmm29,%ymm6{%k7}",}, | ||
249 | {{0x62, 0xf1, 0xff, 0x08, 0x78, 0xc6, }, 6, 0, "", "", | ||
250 | "62 f1 ff 08 78 c6 \tvcvttsd2usi %xmm6,%rax",}, | ||
251 | {{0x62, 0xf1, 0xfe, 0x08, 0x78, 0xc6, }, 6, 0, "", "", | ||
252 | "62 f1 fe 08 78 c6 \tvcvttss2usi %xmm6,%rax",}, | ||
253 | {{0x62, 0x61, 0x7d, 0x4f, 0x78, 0xd5, }, 6, 0, "", "", | ||
254 | "62 61 7d 4f 78 d5 \tvcvttps2uqq %ymm5,%zmm26{%k7}",}, | ||
255 | {{0x62, 0x01, 0xfd, 0x48, 0x78, 0xf5, }, 6, 0, "", "", | ||
256 | "62 01 fd 48 78 f5 \tvcvttpd2uqq %zmm29,%zmm30",}, | ||
257 | {{0x0f, 0x79, 0xd8, }, 3, 0, "", "", | ||
258 | "0f 79 d8 \tvmwrite %rax,%rbx",}, | ||
259 | {{0x62, 0x01, 0x7c, 0x48, 0x79, 0xd1, }, 6, 0, "", "", | ||
260 | "62 01 7c 48 79 d1 \tvcvtps2udq %zmm25,%zmm26",}, | ||
261 | {{0x62, 0x91, 0xfc, 0x4f, 0x79, 0xf5, }, 6, 0, "", "", | ||
262 | "62 91 fc 4f 79 f5 \tvcvtpd2udq %zmm29,%ymm6{%k7}",}, | ||
263 | {{0x62, 0xf1, 0xff, 0x08, 0x79, 0xc6, }, 6, 0, "", "", | ||
264 | "62 f1 ff 08 79 c6 \tvcvtsd2usi %xmm6,%rax",}, | ||
265 | {{0x62, 0xf1, 0xfe, 0x08, 0x79, 0xc6, }, 6, 0, "", "", | ||
266 | "62 f1 fe 08 79 c6 \tvcvtss2usi %xmm6,%rax",}, | ||
267 | {{0x62, 0x61, 0x7d, 0x4f, 0x79, 0xd5, }, 6, 0, "", "", | ||
268 | "62 61 7d 4f 79 d5 \tvcvtps2uqq %ymm5,%zmm26{%k7}",}, | ||
269 | {{0x62, 0x01, 0xfd, 0x48, 0x79, 0xf5, }, 6, 0, "", "", | ||
270 | "62 01 fd 48 79 f5 \tvcvtpd2uqq %zmm29,%zmm30",}, | ||
271 | {{0x62, 0x61, 0x7e, 0x4f, 0x7a, 0xed, }, 6, 0, "", "", | ||
272 | "62 61 7e 4f 7a ed \tvcvtudq2pd %ymm5,%zmm29{%k7}",}, | ||
273 | {{0x62, 0x01, 0xfe, 0x48, 0x7a, 0xd1, }, 6, 0, "", "", | ||
274 | "62 01 fe 48 7a d1 \tvcvtuqq2pd %zmm25,%zmm26",}, | ||
275 | {{0x62, 0x01, 0x7f, 0x48, 0x7a, 0xf5, }, 6, 0, "", "", | ||
276 | "62 01 7f 48 7a f5 \tvcvtudq2ps %zmm29,%zmm30",}, | ||
277 | {{0x62, 0x01, 0xff, 0x4f, 0x7a, 0xd1, }, 6, 0, "", "", | ||
278 | "62 01 ff 4f 7a d1 \tvcvtuqq2ps %zmm25,%ymm26{%k7}",}, | ||
279 | {{0x62, 0x01, 0x7d, 0x4f, 0x7a, 0xd1, }, 6, 0, "", "", | ||
280 | "62 01 7d 4f 7a d1 \tvcvttps2qq %ymm25,%zmm26{%k7}",}, | ||
281 | {{0x62, 0x01, 0xfd, 0x48, 0x7a, 0xf5, }, 6, 0, "", "", | ||
282 | "62 01 fd 48 7a f5 \tvcvttpd2qq %zmm29,%zmm30",}, | ||
283 | {{0x62, 0xf1, 0x57, 0x08, 0x7b, 0xf0, }, 6, 0, "", "", | ||
284 | "62 f1 57 08 7b f0 \tvcvtusi2sd %eax,%xmm5,%xmm6",}, | ||
285 | {{0x62, 0xf1, 0x56, 0x08, 0x7b, 0xf0, }, 6, 0, "", "", | ||
286 | "62 f1 56 08 7b f0 \tvcvtusi2ss %eax,%xmm5,%xmm6",}, | ||
287 | {{0x62, 0x61, 0x7d, 0x4f, 0x7b, 0xd5, }, 6, 0, "", "", | ||
288 | "62 61 7d 4f 7b d5 \tvcvtps2qq %ymm5,%zmm26{%k7}",}, | ||
289 | {{0x62, 0x01, 0xfd, 0x48, 0x7b, 0xf5, }, 6, 0, "", "", | ||
290 | "62 01 fd 48 7b f5 \tvcvtpd2qq %zmm29,%zmm30",}, | ||
291 | {{0x0f, 0x7f, 0xc4, }, 3, 0, "", "", | ||
292 | "0f 7f c4 \tmovq %mm0,%mm4",}, | ||
293 | {{0xc5, 0x7d, 0x7f, 0xc6, }, 4, 0, "", "", | ||
294 | "c5 7d 7f c6 \tvmovdqa %ymm8,%ymm6",}, | ||
295 | {{0x62, 0x01, 0x7d, 0x48, 0x7f, 0xca, }, 6, 0, "", "", | ||
296 | "62 01 7d 48 7f ca \tvmovdqa32 %zmm25,%zmm26",}, | ||
297 | {{0x62, 0x01, 0xfd, 0x48, 0x7f, 0xca, }, 6, 0, "", "", | ||
298 | "62 01 fd 48 7f ca \tvmovdqa64 %zmm25,%zmm26",}, | ||
299 | {{0xc5, 0x7e, 0x7f, 0xc6, }, 4, 0, "", "", | ||
300 | "c5 7e 7f c6 \tvmovdqu %ymm8,%ymm6",}, | ||
301 | {{0x62, 0x01, 0x7e, 0x48, 0x7f, 0xca, }, 6, 0, "", "", | ||
302 | "62 01 7e 48 7f ca \tvmovdqu32 %zmm25,%zmm26",}, | ||
303 | {{0x62, 0x01, 0xfe, 0x48, 0x7f, 0xca, }, 6, 0, "", "", | ||
304 | "62 01 fe 48 7f ca \tvmovdqu64 %zmm25,%zmm26",}, | ||
305 | {{0x62, 0x61, 0x7f, 0x48, 0x7f, 0x31, }, 6, 0, "", "", | ||
306 | "62 61 7f 48 7f 31 \tvmovdqu8 %zmm30,(%rcx)",}, | ||
307 | {{0x62, 0x01, 0xff, 0x48, 0x7f, 0xca, }, 6, 0, "", "", | ||
308 | "62 01 ff 48 7f ca \tvmovdqu16 %zmm25,%zmm26",}, | ||
309 | {{0x0f, 0xdb, 0xd1, }, 3, 0, "", "", | ||
310 | "0f db d1 \tpand %mm1,%mm2",}, | ||
311 | {{0x66, 0x0f, 0xdb, 0xd1, }, 4, 0, "", "", | ||
312 | "66 0f db d1 \tpand %xmm1,%xmm2",}, | ||
313 | {{0xc5, 0xcd, 0xdb, 0xd4, }, 4, 0, "", "", | ||
314 | "c5 cd db d4 \tvpand %ymm4,%ymm6,%ymm2",}, | ||
315 | {{0x62, 0x01, 0x35, 0x40, 0xdb, 0xd0, }, 6, 0, "", "", | ||
316 | "62 01 35 40 db d0 \tvpandd %zmm24,%zmm25,%zmm26",}, | ||
317 | {{0x62, 0x01, 0xb5, 0x40, 0xdb, 0xd0, }, 6, 0, "", "", | ||
318 | "62 01 b5 40 db d0 \tvpandq %zmm24,%zmm25,%zmm26",}, | ||
319 | {{0x0f, 0xdf, 0xd1, }, 3, 0, "", "", | ||
320 | "0f df d1 \tpandn %mm1,%mm2",}, | ||
321 | {{0x66, 0x0f, 0xdf, 0xd1, }, 4, 0, "", "", | ||
322 | "66 0f df d1 \tpandn %xmm1,%xmm2",}, | ||
323 | {{0xc5, 0xcd, 0xdf, 0xd4, }, 4, 0, "", "", | ||
324 | "c5 cd df d4 \tvpandn %ymm4,%ymm6,%ymm2",}, | ||
325 | {{0x62, 0x01, 0x35, 0x40, 0xdf, 0xd0, }, 6, 0, "", "", | ||
326 | "62 01 35 40 df d0 \tvpandnd %zmm24,%zmm25,%zmm26",}, | ||
327 | {{0x62, 0x01, 0xb5, 0x40, 0xdf, 0xd0, }, 6, 0, "", "", | ||
328 | "62 01 b5 40 df d0 \tvpandnq %zmm24,%zmm25,%zmm26",}, | ||
329 | {{0xc5, 0xf9, 0xe6, 0xd1, }, 4, 0, "", "", | ||
330 | "c5 f9 e6 d1 \tvcvttpd2dq %xmm1,%xmm2",}, | ||
331 | {{0xc5, 0xfa, 0xe6, 0xf5, }, 4, 0, "", "", | ||
332 | "c5 fa e6 f5 \tvcvtdq2pd %xmm5,%xmm6",}, | ||
333 | {{0x62, 0x61, 0x7e, 0x4f, 0xe6, 0xd5, }, 6, 0, "", "", | ||
334 | "62 61 7e 4f e6 d5 \tvcvtdq2pd %ymm5,%zmm26{%k7}",}, | ||
335 | {{0x62, 0x01, 0xfe, 0x48, 0xe6, 0xd1, }, 6, 0, "", "", | ||
336 | "62 01 fe 48 e6 d1 \tvcvtqq2pd %zmm25,%zmm26",}, | ||
337 | {{0xc5, 0xfb, 0xe6, 0xd1, }, 4, 0, "", "", | ||
338 | "c5 fb e6 d1 \tvcvtpd2dq %xmm1,%xmm2",}, | ||
339 | {{0x0f, 0xeb, 0xf4, }, 3, 0, "", "", | ||
340 | "0f eb f4 \tpor %mm4,%mm6",}, | ||
341 | {{0xc5, 0xcd, 0xeb, 0xd4, }, 4, 0, "", "", | ||
342 | "c5 cd eb d4 \tvpor %ymm4,%ymm6,%ymm2",}, | ||
343 | {{0x62, 0x01, 0x35, 0x40, 0xeb, 0xd0, }, 6, 0, "", "", | ||
344 | "62 01 35 40 eb d0 \tvpord %zmm24,%zmm25,%zmm26",}, | ||
345 | {{0x62, 0x01, 0xb5, 0x40, 0xeb, 0xd0, }, 6, 0, "", "", | ||
346 | "62 01 b5 40 eb d0 \tvporq %zmm24,%zmm25,%zmm26",}, | ||
347 | {{0x0f, 0xef, 0xf4, }, 3, 0, "", "", | ||
348 | "0f ef f4 \tpxor %mm4,%mm6",}, | ||
349 | {{0xc5, 0xcd, 0xef, 0xd4, }, 4, 0, "", "", | ||
350 | "c5 cd ef d4 \tvpxor %ymm4,%ymm6,%ymm2",}, | ||
351 | {{0x62, 0x01, 0x35, 0x40, 0xef, 0xd0, }, 6, 0, "", "", | ||
352 | "62 01 35 40 ef d0 \tvpxord %zmm24,%zmm25,%zmm26",}, | ||
353 | {{0x62, 0x01, 0xb5, 0x40, 0xef, 0xd0, }, 6, 0, "", "", | ||
354 | "62 01 b5 40 ef d0 \tvpxorq %zmm24,%zmm25,%zmm26",}, | ||
355 | {{0x66, 0x0f, 0x38, 0x10, 0xc1, }, 5, 0, "", "", | ||
356 | "66 0f 38 10 c1 \tpblendvb %xmm0,%xmm1,%xmm0",}, | ||
357 | {{0x62, 0x02, 0x9d, 0x40, 0x10, 0xeb, }, 6, 0, "", "", | ||
358 | "62 02 9d 40 10 eb \tvpsrlvw %zmm27,%zmm28,%zmm29",}, | ||
359 | {{0x62, 0x62, 0x7e, 0x4f, 0x10, 0xe6, }, 6, 0, "", "", | ||
360 | "62 62 7e 4f 10 e6 \tvpmovuswb %zmm28,%ymm6{%k7}",}, | ||
361 | {{0x62, 0x62, 0x7e, 0x4f, 0x11, 0xe6, }, 6, 0, "", "", | ||
362 | "62 62 7e 4f 11 e6 \tvpmovusdb %zmm28,%xmm6{%k7}",}, | ||
363 | {{0x62, 0x02, 0x9d, 0x40, 0x11, 0xeb, }, 6, 0, "", "", | ||
364 | "62 02 9d 40 11 eb \tvpsravw %zmm27,%zmm28,%zmm29",}, | ||
365 | {{0x62, 0x62, 0x7e, 0x4f, 0x12, 0xde, }, 6, 0, "", "", | ||
366 | "62 62 7e 4f 12 de \tvpmovusqb %zmm27,%xmm6{%k7}",}, | ||
367 | {{0x62, 0x02, 0x9d, 0x40, 0x12, 0xeb, }, 6, 0, "", "", | ||
368 | "62 02 9d 40 12 eb \tvpsllvw %zmm27,%zmm28,%zmm29",}, | ||
369 | {{0xc4, 0xe2, 0x7d, 0x13, 0xeb, }, 5, 0, "", "", | ||
370 | "c4 e2 7d 13 eb \tvcvtph2ps %xmm3,%ymm5",}, | ||
371 | {{0x62, 0x62, 0x7d, 0x4f, 0x13, 0xdd, }, 6, 0, "", "", | ||
372 | "62 62 7d 4f 13 dd \tvcvtph2ps %ymm5,%zmm27{%k7}",}, | ||
373 | {{0x62, 0x62, 0x7e, 0x4f, 0x13, 0xde, }, 6, 0, "", "", | ||
374 | "62 62 7e 4f 13 de \tvpmovusdw %zmm27,%ymm6{%k7}",}, | ||
375 | {{0x66, 0x0f, 0x38, 0x14, 0xc1, }, 5, 0, "", "", | ||
376 | "66 0f 38 14 c1 \tblendvps %xmm0,%xmm1,%xmm0",}, | ||
377 | {{0x62, 0x62, 0x7e, 0x4f, 0x14, 0xde, }, 6, 0, "", "", | ||
378 | "62 62 7e 4f 14 de \tvpmovusqw %zmm27,%xmm6{%k7}",}, | ||
379 | {{0x62, 0x02, 0x1d, 0x40, 0x14, 0xeb, }, 6, 0, "", "", | ||
380 | "62 02 1d 40 14 eb \tvprorvd %zmm27,%zmm28,%zmm29",}, | ||
381 | {{0x62, 0x02, 0x9d, 0x40, 0x14, 0xeb, }, 6, 0, "", "", | ||
382 | "62 02 9d 40 14 eb \tvprorvq %zmm27,%zmm28,%zmm29",}, | ||
383 | {{0x66, 0x0f, 0x38, 0x15, 0xc1, }, 5, 0, "", "", | ||
384 | "66 0f 38 15 c1 \tblendvpd %xmm0,%xmm1,%xmm0",}, | ||
385 | {{0x62, 0x62, 0x7e, 0x4f, 0x15, 0xde, }, 6, 0, "", "", | ||
386 | "62 62 7e 4f 15 de \tvpmovusqd %zmm27,%ymm6{%k7}",}, | ||
387 | {{0x62, 0x02, 0x1d, 0x40, 0x15, 0xeb, }, 6, 0, "", "", | ||
388 | "62 02 1d 40 15 eb \tvprolvd %zmm27,%zmm28,%zmm29",}, | ||
389 | {{0x62, 0x02, 0x9d, 0x40, 0x15, 0xeb, }, 6, 0, "", "", | ||
390 | "62 02 9d 40 15 eb \tvprolvq %zmm27,%zmm28,%zmm29",}, | ||
391 | {{0xc4, 0xe2, 0x4d, 0x16, 0xd4, }, 5, 0, "", "", | ||
392 | "c4 e2 4d 16 d4 \tvpermps %ymm4,%ymm6,%ymm2",}, | ||
393 | {{0x62, 0x82, 0x2d, 0x27, 0x16, 0xf0, }, 6, 0, "", "", | ||
394 | "62 82 2d 27 16 f0 \tvpermps %ymm24,%ymm26,%ymm22{%k7}",}, | ||
395 | {{0x62, 0x82, 0xad, 0x27, 0x16, 0xf0, }, 6, 0, "", "", | ||
396 | "62 82 ad 27 16 f0 \tvpermpd %ymm24,%ymm26,%ymm22{%k7}",}, | ||
397 | {{0xc4, 0xe2, 0x7d, 0x19, 0xf4, }, 5, 0, "", "", | ||
398 | "c4 e2 7d 19 f4 \tvbroadcastsd %xmm4,%ymm6",}, | ||
399 | {{0x62, 0x02, 0x7d, 0x48, 0x19, 0xd3, }, 6, 0, "", "", | ||
400 | "62 02 7d 48 19 d3 \tvbroadcastf32x2 %xmm27,%zmm26",}, | ||
401 | {{0xc4, 0xe2, 0x7d, 0x1a, 0x21, }, 5, 0, "", "", | ||
402 | "c4 e2 7d 1a 21 \tvbroadcastf128 (%rcx),%ymm4",}, | ||
403 | {{0x62, 0x62, 0x7d, 0x48, 0x1a, 0x11, }, 6, 0, "", "", | ||
404 | "62 62 7d 48 1a 11 \tvbroadcastf32x4 (%rcx),%zmm26",}, | ||
405 | {{0x62, 0x62, 0xfd, 0x48, 0x1a, 0x11, }, 6, 0, "", "", | ||
406 | "62 62 fd 48 1a 11 \tvbroadcastf64x2 (%rcx),%zmm26",}, | ||
407 | {{0x62, 0x62, 0x7d, 0x48, 0x1b, 0x19, }, 6, 0, "", "", | ||
408 | "62 62 7d 48 1b 19 \tvbroadcastf32x8 (%rcx),%zmm27",}, | ||
409 | {{0x62, 0x62, 0xfd, 0x48, 0x1b, 0x11, }, 6, 0, "", "", | ||
410 | "62 62 fd 48 1b 11 \tvbroadcastf64x4 (%rcx),%zmm26",}, | ||
411 | {{0x62, 0x02, 0xfd, 0x48, 0x1f, 0xe3, }, 6, 0, "", "", | ||
412 | "62 02 fd 48 1f e3 \tvpabsq %zmm27,%zmm28",}, | ||
413 | {{0xc4, 0xe2, 0x79, 0x20, 0xec, }, 5, 0, "", "", | ||
414 | "c4 e2 79 20 ec \tvpmovsxbw %xmm4,%xmm5",}, | ||
415 | {{0x62, 0x62, 0x7e, 0x4f, 0x20, 0xde, }, 6, 0, "", "", | ||
416 | "62 62 7e 4f 20 de \tvpmovswb %zmm27,%ymm6{%k7}",}, | ||
417 | {{0xc4, 0xe2, 0x7d, 0x21, 0xf4, }, 5, 0, "", "", | ||
418 | "c4 e2 7d 21 f4 \tvpmovsxbd %xmm4,%ymm6",}, | ||
419 | {{0x62, 0x62, 0x7e, 0x4f, 0x21, 0xde, }, 6, 0, "", "", | ||
420 | "62 62 7e 4f 21 de \tvpmovsdb %zmm27,%xmm6{%k7}",}, | ||
421 | {{0xc4, 0xe2, 0x7d, 0x22, 0xe4, }, 5, 0, "", "", | ||
422 | "c4 e2 7d 22 e4 \tvpmovsxbq %xmm4,%ymm4",}, | ||
423 | {{0x62, 0x62, 0x7e, 0x4f, 0x22, 0xde, }, 6, 0, "", "", | ||
424 | "62 62 7e 4f 22 de \tvpmovsqb %zmm27,%xmm6{%k7}",}, | ||
425 | {{0xc4, 0xe2, 0x7d, 0x23, 0xe4, }, 5, 0, "", "", | ||
426 | "c4 e2 7d 23 e4 \tvpmovsxwd %xmm4,%ymm4",}, | ||
427 | {{0x62, 0x62, 0x7e, 0x4f, 0x23, 0xde, }, 6, 0, "", "", | ||
428 | "62 62 7e 4f 23 de \tvpmovsdw %zmm27,%ymm6{%k7}",}, | ||
429 | {{0xc4, 0xe2, 0x7d, 0x24, 0xf4, }, 5, 0, "", "", | ||
430 | "c4 e2 7d 24 f4 \tvpmovsxwq %xmm4,%ymm6",}, | ||
431 | {{0x62, 0x62, 0x7e, 0x4f, 0x24, 0xde, }, 6, 0, "", "", | ||
432 | "62 62 7e 4f 24 de \tvpmovsqw %zmm27,%xmm6{%k7}",}, | ||
433 | {{0xc4, 0xe2, 0x7d, 0x25, 0xe4, }, 5, 0, "", "", | ||
434 | "c4 e2 7d 25 e4 \tvpmovsxdq %xmm4,%ymm4",}, | ||
435 | {{0x62, 0x62, 0x7e, 0x4f, 0x25, 0xde, }, 6, 0, "", "", | ||
436 | "62 62 7e 4f 25 de \tvpmovsqd %zmm27,%ymm6{%k7}",}, | ||
437 | {{0x62, 0x92, 0x1d, 0x40, 0x26, 0xeb, }, 6, 0, "", "", | ||
438 | "62 92 1d 40 26 eb \tvptestmb %zmm27,%zmm28,%k5",}, | ||
439 | {{0x62, 0x92, 0x9d, 0x40, 0x26, 0xeb, }, 6, 0, "", "", | ||
440 | "62 92 9d 40 26 eb \tvptestmw %zmm27,%zmm28,%k5",}, | ||
441 | {{0x62, 0x92, 0x26, 0x40, 0x26, 0xea, }, 6, 0, "", "", | ||
442 | "62 92 26 40 26 ea \tvptestnmb %zmm26,%zmm27,%k5",}, | ||
443 | {{0x62, 0x92, 0xa6, 0x40, 0x26, 0xea, }, 6, 0, "", "", | ||
444 | "62 92 a6 40 26 ea \tvptestnmw %zmm26,%zmm27,%k5",}, | ||
445 | {{0x62, 0x92, 0x1d, 0x40, 0x27, 0xeb, }, 6, 0, "", "", | ||
446 | "62 92 1d 40 27 eb \tvptestmd %zmm27,%zmm28,%k5",}, | ||
447 | {{0x62, 0x92, 0x9d, 0x40, 0x27, 0xeb, }, 6, 0, "", "", | ||
448 | "62 92 9d 40 27 eb \tvptestmq %zmm27,%zmm28,%k5",}, | ||
449 | {{0x62, 0x92, 0x26, 0x40, 0x27, 0xea, }, 6, 0, "", "", | ||
450 | "62 92 26 40 27 ea \tvptestnmd %zmm26,%zmm27,%k5",}, | ||
451 | {{0x62, 0x92, 0xa6, 0x40, 0x27, 0xea, }, 6, 0, "", "", | ||
452 | "62 92 a6 40 27 ea \tvptestnmq %zmm26,%zmm27,%k5",}, | ||
453 | {{0xc4, 0xe2, 0x4d, 0x28, 0xd4, }, 5, 0, "", "", | ||
454 | "c4 e2 4d 28 d4 \tvpmuldq %ymm4,%ymm6,%ymm2",}, | ||
455 | {{0x62, 0x62, 0x7e, 0x48, 0x28, 0xe5, }, 6, 0, "", "", | ||
456 | "62 62 7e 48 28 e5 \tvpmovm2b %k5,%zmm28",}, | ||
457 | {{0x62, 0x62, 0xfe, 0x48, 0x28, 0xe5, }, 6, 0, "", "", | ||
458 | "62 62 fe 48 28 e5 \tvpmovm2w %k5,%zmm28",}, | ||
459 | {{0xc4, 0xe2, 0x4d, 0x29, 0xd4, }, 5, 0, "", "", | ||
460 | "c4 e2 4d 29 d4 \tvpcmpeqq %ymm4,%ymm6,%ymm2",}, | ||
461 | {{0x62, 0x92, 0x7e, 0x48, 0x29, 0xec, }, 6, 0, "", "", | ||
462 | "62 92 7e 48 29 ec \tvpmovb2m %zmm28,%k5",}, | ||
463 | {{0x62, 0x92, 0xfe, 0x48, 0x29, 0xec, }, 6, 0, "", "", | ||
464 | "62 92 fe 48 29 ec \tvpmovw2m %zmm28,%k5",}, | ||
465 | {{0xc4, 0xe2, 0x7d, 0x2a, 0x21, }, 5, 0, "", "", | ||
466 | "c4 e2 7d 2a 21 \tvmovntdqa (%rcx),%ymm4",}, | ||
467 | {{0x62, 0x62, 0xfe, 0x48, 0x2a, 0xf6, }, 6, 0, "", "", | ||
468 | "62 62 fe 48 2a f6 \tvpbroadcastmb2q %k6,%zmm30",}, | ||
469 | {{0xc4, 0xe2, 0x5d, 0x2c, 0x31, }, 5, 0, "", "", | ||
470 | "c4 e2 5d 2c 31 \tvmaskmovps (%rcx),%ymm4,%ymm6",}, | ||
471 | {{0x62, 0x02, 0x35, 0x40, 0x2c, 0xd0, }, 6, 0, "", "", | ||
472 | "62 02 35 40 2c d0 \tvscalefps %zmm24,%zmm25,%zmm26",}, | ||
473 | {{0x62, 0x02, 0xb5, 0x40, 0x2c, 0xd0, }, 6, 0, "", "", | ||
474 | "62 02 b5 40 2c d0 \tvscalefpd %zmm24,%zmm25,%zmm26",}, | ||
475 | {{0xc4, 0xe2, 0x5d, 0x2d, 0x31, }, 5, 0, "", "", | ||
476 | "c4 e2 5d 2d 31 \tvmaskmovpd (%rcx),%ymm4,%ymm6",}, | ||
477 | {{0x62, 0x02, 0x35, 0x07, 0x2d, 0xd0, }, 6, 0, "", "", | ||
478 | "62 02 35 07 2d d0 \tvscalefss %xmm24,%xmm25,%xmm26{%k7}",}, | ||
479 | {{0x62, 0x02, 0xb5, 0x07, 0x2d, 0xd0, }, 6, 0, "", "", | ||
480 | "62 02 b5 07 2d d0 \tvscalefsd %xmm24,%xmm25,%xmm26{%k7}",}, | ||
481 | {{0xc4, 0xe2, 0x7d, 0x30, 0xe4, }, 5, 0, "", "", | ||
482 | "c4 e2 7d 30 e4 \tvpmovzxbw %xmm4,%ymm4",}, | ||
483 | {{0x62, 0x62, 0x7e, 0x4f, 0x30, 0xde, }, 6, 0, "", "", | ||
484 | "62 62 7e 4f 30 de \tvpmovwb %zmm27,%ymm6{%k7}",}, | ||
485 | {{0xc4, 0xe2, 0x7d, 0x31, 0xf4, }, 5, 0, "", "", | ||
486 | "c4 e2 7d 31 f4 \tvpmovzxbd %xmm4,%ymm6",}, | ||
487 | {{0x62, 0x62, 0x7e, 0x4f, 0x31, 0xde, }, 6, 0, "", "", | ||
488 | "62 62 7e 4f 31 de \tvpmovdb %zmm27,%xmm6{%k7}",}, | ||
489 | {{0xc4, 0xe2, 0x7d, 0x32, 0xe4, }, 5, 0, "", "", | ||
490 | "c4 e2 7d 32 e4 \tvpmovzxbq %xmm4,%ymm4",}, | ||
491 | {{0x62, 0x62, 0x7e, 0x4f, 0x32, 0xde, }, 6, 0, "", "", | ||
492 | "62 62 7e 4f 32 de \tvpmovqb %zmm27,%xmm6{%k7}",}, | ||
493 | {{0xc4, 0xe2, 0x7d, 0x33, 0xe4, }, 5, 0, "", "", | ||
494 | "c4 e2 7d 33 e4 \tvpmovzxwd %xmm4,%ymm4",}, | ||
495 | {{0x62, 0x62, 0x7e, 0x4f, 0x33, 0xde, }, 6, 0, "", "", | ||
496 | "62 62 7e 4f 33 de \tvpmovdw %zmm27,%ymm6{%k7}",}, | ||
497 | {{0xc4, 0xe2, 0x7d, 0x34, 0xf4, }, 5, 0, "", "", | ||
498 | "c4 e2 7d 34 f4 \tvpmovzxwq %xmm4,%ymm6",}, | ||
499 | {{0x62, 0x62, 0x7e, 0x4f, 0x34, 0xde, }, 6, 0, "", "", | ||
500 | "62 62 7e 4f 34 de \tvpmovqw %zmm27,%xmm6{%k7}",}, | ||
501 | {{0xc4, 0xe2, 0x7d, 0x35, 0xe4, }, 5, 0, "", "", | ||
502 | "c4 e2 7d 35 e4 \tvpmovzxdq %xmm4,%ymm4",}, | ||
503 | {{0x62, 0x62, 0x7e, 0x4f, 0x35, 0xde, }, 6, 0, "", "", | ||
504 | "62 62 7e 4f 35 de \tvpmovqd %zmm27,%ymm6{%k7}",}, | ||
505 | {{0xc4, 0xe2, 0x4d, 0x36, 0xd4, }, 5, 0, "", "", | ||
506 | "c4 e2 4d 36 d4 \tvpermd %ymm4,%ymm6,%ymm2",}, | ||
507 | {{0x62, 0x82, 0x2d, 0x27, 0x36, 0xf0, }, 6, 0, "", "", | ||
508 | "62 82 2d 27 36 f0 \tvpermd %ymm24,%ymm26,%ymm22{%k7}",}, | ||
509 | {{0x62, 0x82, 0xad, 0x27, 0x36, 0xf0, }, 6, 0, "", "", | ||
510 | "62 82 ad 27 36 f0 \tvpermq %ymm24,%ymm26,%ymm22{%k7}",}, | ||
511 | {{0xc4, 0xe2, 0x4d, 0x38, 0xd4, }, 5, 0, "", "", | ||
512 | "c4 e2 4d 38 d4 \tvpminsb %ymm4,%ymm6,%ymm2",}, | ||
513 | {{0x62, 0x62, 0x7e, 0x48, 0x38, 0xe5, }, 6, 0, "", "", | ||
514 | "62 62 7e 48 38 e5 \tvpmovm2d %k5,%zmm28",}, | ||
515 | {{0x62, 0x62, 0xfe, 0x48, 0x38, 0xe5, }, 6, 0, "", "", | ||
516 | "62 62 fe 48 38 e5 \tvpmovm2q %k5,%zmm28",}, | ||
517 | {{0xc4, 0xe2, 0x69, 0x39, 0xd9, }, 5, 0, "", "", | ||
518 | "c4 e2 69 39 d9 \tvpminsd %xmm1,%xmm2,%xmm3",}, | ||
519 | {{0x62, 0x02, 0x35, 0x40, 0x39, 0xd0, }, 6, 0, "", "", | ||
520 | "62 02 35 40 39 d0 \tvpminsd %zmm24,%zmm25,%zmm26",}, | ||
521 | {{0x62, 0x02, 0xb5, 0x40, 0x39, 0xd0, }, 6, 0, "", "", | ||
522 | "62 02 b5 40 39 d0 \tvpminsq %zmm24,%zmm25,%zmm26",}, | ||
523 | {{0x62, 0x92, 0x7e, 0x48, 0x39, 0xec, }, 6, 0, "", "", | ||
524 | "62 92 7e 48 39 ec \tvpmovd2m %zmm28,%k5",}, | ||
525 | {{0x62, 0x92, 0xfe, 0x48, 0x39, 0xec, }, 6, 0, "", "", | ||
526 | "62 92 fe 48 39 ec \tvpmovq2m %zmm28,%k5",}, | ||
527 | {{0xc4, 0xe2, 0x4d, 0x3a, 0xd4, }, 5, 0, "", "", | ||
528 | "c4 e2 4d 3a d4 \tvpminuw %ymm4,%ymm6,%ymm2",}, | ||
529 | {{0x62, 0x62, 0x7e, 0x48, 0x3a, 0xe6, }, 6, 0, "", "", | ||
530 | "62 62 7e 48 3a e6 \tvpbroadcastmw2d %k6,%zmm28",}, | ||
531 | {{0xc4, 0xe2, 0x4d, 0x3b, 0xd4, }, 5, 0, "", "", | ||
532 | "c4 e2 4d 3b d4 \tvpminud %ymm4,%ymm6,%ymm2",}, | ||
533 | {{0x62, 0x02, 0x35, 0x40, 0x3b, 0xd0, }, 6, 0, "", "", | ||
534 | "62 02 35 40 3b d0 \tvpminud %zmm24,%zmm25,%zmm26",}, | ||
535 | {{0x62, 0x02, 0xb5, 0x40, 0x3b, 0xd0, }, 6, 0, "", "", | ||
536 | "62 02 b5 40 3b d0 \tvpminuq %zmm24,%zmm25,%zmm26",}, | ||
537 | {{0xc4, 0xe2, 0x4d, 0x3d, 0xd4, }, 5, 0, "", "", | ||
538 | "c4 e2 4d 3d d4 \tvpmaxsd %ymm4,%ymm6,%ymm2",}, | ||
539 | {{0x62, 0x02, 0x35, 0x40, 0x3d, 0xd0, }, 6, 0, "", "", | ||
540 | "62 02 35 40 3d d0 \tvpmaxsd %zmm24,%zmm25,%zmm26",}, | ||
541 | {{0x62, 0x02, 0xb5, 0x40, 0x3d, 0xd0, }, 6, 0, "", "", | ||
542 | "62 02 b5 40 3d d0 \tvpmaxsq %zmm24,%zmm25,%zmm26",}, | ||
543 | {{0xc4, 0xe2, 0x4d, 0x3f, 0xd4, }, 5, 0, "", "", | ||
544 | "c4 e2 4d 3f d4 \tvpmaxud %ymm4,%ymm6,%ymm2",}, | ||
545 | {{0x62, 0x02, 0x35, 0x40, 0x3f, 0xd0, }, 6, 0, "", "", | ||
546 | "62 02 35 40 3f d0 \tvpmaxud %zmm24,%zmm25,%zmm26",}, | ||
547 | {{0x62, 0x02, 0xb5, 0x40, 0x3f, 0xd0, }, 6, 0, "", "", | ||
548 | "62 02 b5 40 3f d0 \tvpmaxuq %zmm24,%zmm25,%zmm26",}, | ||
549 | {{0xc4, 0xe2, 0x4d, 0x40, 0xd4, }, 5, 0, "", "", | ||
550 | "c4 e2 4d 40 d4 \tvpmulld %ymm4,%ymm6,%ymm2",}, | ||
551 | {{0x62, 0x02, 0x35, 0x40, 0x40, 0xd0, }, 6, 0, "", "", | ||
552 | "62 02 35 40 40 d0 \tvpmulld %zmm24,%zmm25,%zmm26",}, | ||
553 | {{0x62, 0x02, 0xb5, 0x40, 0x40, 0xd0, }, 6, 0, "", "", | ||
554 | "62 02 b5 40 40 d0 \tvpmullq %zmm24,%zmm25,%zmm26",}, | ||
555 | {{0x62, 0x02, 0x7d, 0x48, 0x42, 0xd1, }, 6, 0, "", "", | ||
556 | "62 02 7d 48 42 d1 \tvgetexpps %zmm25,%zmm26",}, | ||
557 | {{0x62, 0x02, 0xfd, 0x48, 0x42, 0xe3, }, 6, 0, "", "", | ||
558 | "62 02 fd 48 42 e3 \tvgetexppd %zmm27,%zmm28",}, | ||
559 | {{0x62, 0x02, 0x35, 0x07, 0x43, 0xd0, }, 6, 0, "", "", | ||
560 | "62 02 35 07 43 d0 \tvgetexpss %xmm24,%xmm25,%xmm26{%k7}",}, | ||
561 | {{0x62, 0x02, 0x95, 0x07, 0x43, 0xf4, }, 6, 0, "", "", | ||
562 | "62 02 95 07 43 f4 \tvgetexpsd %xmm28,%xmm29,%xmm30{%k7}",}, | ||
563 | {{0x62, 0x02, 0x7d, 0x48, 0x44, 0xe3, }, 6, 0, "", "", | ||
564 | "62 02 7d 48 44 e3 \tvplzcntd %zmm27,%zmm28",}, | ||
565 | {{0x62, 0x02, 0xfd, 0x48, 0x44, 0xe3, }, 6, 0, "", "", | ||
566 | "62 02 fd 48 44 e3 \tvplzcntq %zmm27,%zmm28",}, | ||
567 | {{0xc4, 0xe2, 0x4d, 0x46, 0xd4, }, 5, 0, "", "", | ||
568 | "c4 e2 4d 46 d4 \tvpsravd %ymm4,%ymm6,%ymm2",}, | ||
569 | {{0x62, 0x02, 0x35, 0x40, 0x46, 0xd0, }, 6, 0, "", "", | ||
570 | "62 02 35 40 46 d0 \tvpsravd %zmm24,%zmm25,%zmm26",}, | ||
571 | {{0x62, 0x02, 0xb5, 0x40, 0x46, 0xd0, }, 6, 0, "", "", | ||
572 | "62 02 b5 40 46 d0 \tvpsravq %zmm24,%zmm25,%zmm26",}, | ||
573 | {{0x62, 0x02, 0x7d, 0x48, 0x4c, 0xd1, }, 6, 0, "", "", | ||
574 | "62 02 7d 48 4c d1 \tvrcp14ps %zmm25,%zmm26",}, | ||
575 | {{0x62, 0x02, 0xfd, 0x48, 0x4c, 0xe3, }, 6, 0, "", "", | ||
576 | "62 02 fd 48 4c e3 \tvrcp14pd %zmm27,%zmm28",}, | ||
577 | {{0x62, 0x02, 0x35, 0x07, 0x4d, 0xd0, }, 6, 0, "", "", | ||
578 | "62 02 35 07 4d d0 \tvrcp14ss %xmm24,%xmm25,%xmm26{%k7}",}, | ||
579 | {{0x62, 0x02, 0xb5, 0x07, 0x4d, 0xd0, }, 6, 0, "", "", | ||
580 | "62 02 b5 07 4d d0 \tvrcp14sd %xmm24,%xmm25,%xmm26{%k7}",}, | ||
581 | {{0x62, 0x02, 0x7d, 0x48, 0x4e, 0xd1, }, 6, 0, "", "", | ||
582 | "62 02 7d 48 4e d1 \tvrsqrt14ps %zmm25,%zmm26",}, | ||
583 | {{0x62, 0x02, 0xfd, 0x48, 0x4e, 0xe3, }, 6, 0, "", "", | ||
584 | "62 02 fd 48 4e e3 \tvrsqrt14pd %zmm27,%zmm28",}, | ||
585 | {{0x62, 0x02, 0x35, 0x07, 0x4f, 0xd0, }, 6, 0, "", "", | ||
586 | "62 02 35 07 4f d0 \tvrsqrt14ss %xmm24,%xmm25,%xmm26{%k7}",}, | ||
587 | {{0x62, 0x02, 0xb5, 0x07, 0x4f, 0xd0, }, 6, 0, "", "", | ||
588 | "62 02 b5 07 4f d0 \tvrsqrt14sd %xmm24,%xmm25,%xmm26{%k7}",}, | ||
589 | {{0xc4, 0xe2, 0x79, 0x59, 0xf4, }, 5, 0, "", "", | ||
590 | "c4 e2 79 59 f4 \tvpbroadcastq %xmm4,%xmm6",}, | ||
591 | {{0x62, 0x02, 0x7d, 0x48, 0x59, 0xd3, }, 6, 0, "", "", | ||
592 | "62 02 7d 48 59 d3 \tvbroadcasti32x2 %xmm27,%zmm26",}, | ||
593 | {{0xc4, 0xe2, 0x7d, 0x5a, 0x21, }, 5, 0, "", "", | ||
594 | "c4 e2 7d 5a 21 \tvbroadcasti128 (%rcx),%ymm4",}, | ||
595 | {{0x62, 0x62, 0x7d, 0x48, 0x5a, 0x11, }, 6, 0, "", "", | ||
596 | "62 62 7d 48 5a 11 \tvbroadcasti32x4 (%rcx),%zmm26",}, | ||
597 | {{0x62, 0x62, 0xfd, 0x48, 0x5a, 0x11, }, 6, 0, "", "", | ||
598 | "62 62 fd 48 5a 11 \tvbroadcasti64x2 (%rcx),%zmm26",}, | ||
599 | {{0x62, 0x62, 0x7d, 0x48, 0x5b, 0x21, }, 6, 0, "", "", | ||
600 | "62 62 7d 48 5b 21 \tvbroadcasti32x8 (%rcx),%zmm28",}, | ||
601 | {{0x62, 0x62, 0xfd, 0x48, 0x5b, 0x11, }, 6, 0, "", "", | ||
602 | "62 62 fd 48 5b 11 \tvbroadcasti64x4 (%rcx),%zmm26",}, | ||
603 | {{0x62, 0x02, 0x25, 0x40, 0x64, 0xe2, }, 6, 0, "", "", | ||
604 | "62 02 25 40 64 e2 \tvpblendmd %zmm26,%zmm27,%zmm28",}, | ||
605 | {{0x62, 0x02, 0xa5, 0x40, 0x64, 0xe2, }, 6, 0, "", "", | ||
606 | "62 02 a5 40 64 e2 \tvpblendmq %zmm26,%zmm27,%zmm28",}, | ||
607 | {{0x62, 0x02, 0x35, 0x40, 0x65, 0xd0, }, 6, 0, "", "", | ||
608 | "62 02 35 40 65 d0 \tvblendmps %zmm24,%zmm25,%zmm26",}, | ||
609 | {{0x62, 0x02, 0xa5, 0x40, 0x65, 0xe2, }, 6, 0, "", "", | ||
610 | "62 02 a5 40 65 e2 \tvblendmpd %zmm26,%zmm27,%zmm28",}, | ||
611 | {{0x62, 0x02, 0x25, 0x40, 0x66, 0xe2, }, 6, 0, "", "", | ||
612 | "62 02 25 40 66 e2 \tvpblendmb %zmm26,%zmm27,%zmm28",}, | ||
613 | {{0x62, 0x02, 0xa5, 0x40, 0x66, 0xe2, }, 6, 0, "", "", | ||
614 | "62 02 a5 40 66 e2 \tvpblendmw %zmm26,%zmm27,%zmm28",}, | ||
615 | {{0x62, 0x02, 0x35, 0x40, 0x75, 0xd0, }, 6, 0, "", "", | ||
616 | "62 02 35 40 75 d0 \tvpermi2b %zmm24,%zmm25,%zmm26",}, | ||
617 | {{0x62, 0x02, 0xa5, 0x40, 0x75, 0xe2, }, 6, 0, "", "", | ||
618 | "62 02 a5 40 75 e2 \tvpermi2w %zmm26,%zmm27,%zmm28",}, | ||
619 | {{0x62, 0x02, 0x25, 0x40, 0x76, 0xe2, }, 6, 0, "", "", | ||
620 | "62 02 25 40 76 e2 \tvpermi2d %zmm26,%zmm27,%zmm28",}, | ||
621 | {{0x62, 0x02, 0xa5, 0x40, 0x76, 0xe2, }, 6, 0, "", "", | ||
622 | "62 02 a5 40 76 e2 \tvpermi2q %zmm26,%zmm27,%zmm28",}, | ||
623 | {{0x62, 0x02, 0x25, 0x40, 0x77, 0xe2, }, 6, 0, "", "", | ||
624 | "62 02 25 40 77 e2 \tvpermi2ps %zmm26,%zmm27,%zmm28",}, | ||
625 | {{0x62, 0x02, 0xa5, 0x40, 0x77, 0xe2, }, 6, 0, "", "", | ||
626 | "62 02 a5 40 77 e2 \tvpermi2pd %zmm26,%zmm27,%zmm28",}, | ||
627 | {{0x62, 0x62, 0x7d, 0x08, 0x7a, 0xf0, }, 6, 0, "", "", | ||
628 | "62 62 7d 08 7a f0 \tvpbroadcastb %eax,%xmm30",}, | ||
629 | {{0x62, 0x62, 0x7d, 0x08, 0x7b, 0xf0, }, 6, 0, "", "", | ||
630 | "62 62 7d 08 7b f0 \tvpbroadcastw %eax,%xmm30",}, | ||
631 | {{0x62, 0x62, 0x7d, 0x08, 0x7c, 0xf0, }, 6, 0, "", "", | ||
632 | "62 62 7d 08 7c f0 \tvpbroadcastd %eax,%xmm30",}, | ||
633 | {{0x62, 0x62, 0xfd, 0x48, 0x7c, 0xf0, }, 6, 0, "", "", | ||
634 | "62 62 fd 48 7c f0 \tvpbroadcastq %rax,%zmm30",}, | ||
635 | {{0x62, 0x02, 0x25, 0x40, 0x7d, 0xe2, }, 6, 0, "", "", | ||
636 | "62 02 25 40 7d e2 \tvpermt2b %zmm26,%zmm27,%zmm28",}, | ||
637 | {{0x62, 0x02, 0xa5, 0x40, 0x7d, 0xe2, }, 6, 0, "", "", | ||
638 | "62 02 a5 40 7d e2 \tvpermt2w %zmm26,%zmm27,%zmm28",}, | ||
639 | {{0x62, 0x02, 0x25, 0x40, 0x7e, 0xe2, }, 6, 0, "", "", | ||
640 | "62 02 25 40 7e e2 \tvpermt2d %zmm26,%zmm27,%zmm28",}, | ||
641 | {{0x62, 0x02, 0xa5, 0x40, 0x7e, 0xe2, }, 6, 0, "", "", | ||
642 | "62 02 a5 40 7e e2 \tvpermt2q %zmm26,%zmm27,%zmm28",}, | ||
643 | {{0x62, 0x02, 0x25, 0x40, 0x7f, 0xe2, }, 6, 0, "", "", | ||
644 | "62 02 25 40 7f e2 \tvpermt2ps %zmm26,%zmm27,%zmm28",}, | ||
645 | {{0x62, 0x02, 0xa5, 0x40, 0x7f, 0xe2, }, 6, 0, "", "", | ||
646 | "62 02 a5 40 7f e2 \tvpermt2pd %zmm26,%zmm27,%zmm28",}, | ||
647 | {{0x62, 0x02, 0xa5, 0x40, 0x83, 0xe2, }, 6, 0, "", "", | ||
648 | "62 02 a5 40 83 e2 \tvpmultishiftqb %zmm26,%zmm27,%zmm28",}, | ||
649 | {{0x62, 0x62, 0x7d, 0x48, 0x88, 0x11, }, 6, 0, "", "", | ||
650 | "62 62 7d 48 88 11 \tvexpandps (%rcx),%zmm26",}, | ||
651 | {{0x62, 0x62, 0xfd, 0x48, 0x88, 0x21, }, 6, 0, "", "", | ||
652 | "62 62 fd 48 88 21 \tvexpandpd (%rcx),%zmm28",}, | ||
653 | {{0x62, 0x62, 0x7d, 0x48, 0x89, 0x21, }, 6, 0, "", "", | ||
654 | "62 62 7d 48 89 21 \tvpexpandd (%rcx),%zmm28",}, | ||
655 | {{0x62, 0x62, 0xfd, 0x48, 0x89, 0x11, }, 6, 0, "", "", | ||
656 | "62 62 fd 48 89 11 \tvpexpandq (%rcx),%zmm26",}, | ||
657 | {{0x62, 0x62, 0x7d, 0x48, 0x8a, 0x21, }, 6, 0, "", "", | ||
658 | "62 62 7d 48 8a 21 \tvcompressps %zmm28,(%rcx)",}, | ||
659 | {{0x62, 0x62, 0xfd, 0x48, 0x8a, 0x21, }, 6, 0, "", "", | ||
660 | "62 62 fd 48 8a 21 \tvcompresspd %zmm28,(%rcx)",}, | ||
661 | {{0x62, 0x62, 0x7d, 0x48, 0x8b, 0x21, }, 6, 0, "", "", | ||
662 | "62 62 7d 48 8b 21 \tvpcompressd %zmm28,(%rcx)",}, | ||
663 | {{0x62, 0x62, 0xfd, 0x48, 0x8b, 0x11, }, 6, 0, "", "", | ||
664 | "62 62 fd 48 8b 11 \tvpcompressq %zmm26,(%rcx)",}, | ||
665 | {{0x62, 0x02, 0x25, 0x40, 0x8d, 0xe2, }, 6, 0, "", "", | ||
666 | "62 02 25 40 8d e2 \tvpermb %zmm26,%zmm27,%zmm28",}, | ||
667 | {{0x62, 0x02, 0xa5, 0x40, 0x8d, 0xe2, }, 6, 0, "", "", | ||
668 | "62 02 a5 40 8d e2 \tvpermw %zmm26,%zmm27,%zmm28",}, | ||
669 | {{0xc4, 0xe2, 0x69, 0x90, 0x4c, 0x7d, 0x02, }, 7, 0, "", "", | ||
670 | "c4 e2 69 90 4c 7d 02 \tvpgatherdd %xmm2,0x2(%rbp,%xmm7,2),%xmm1",}, | ||
671 | {{0xc4, 0xe2, 0xe9, 0x90, 0x4c, 0x7d, 0x04, }, 7, 0, "", "", | ||
672 | "c4 e2 e9 90 4c 7d 04 \tvpgatherdq %xmm2,0x4(%rbp,%xmm7,2),%xmm1",}, | ||
673 | {{0x62, 0x22, 0x7d, 0x41, 0x90, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
674 | "62 22 7d 41 90 94 dd 7b 00 00 00 \tvpgatherdd 0x7b(%rbp,%zmm27,8),%zmm26{%k1}",}, | ||
675 | {{0x62, 0x22, 0xfd, 0x41, 0x90, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
676 | "62 22 fd 41 90 94 dd 7b 00 00 00 \tvpgatherdq 0x7b(%rbp,%ymm27,8),%zmm26{%k1}",}, | ||
677 | {{0xc4, 0xe2, 0x69, 0x91, 0x4c, 0x7d, 0x02, }, 7, 0, "", "", | ||
678 | "c4 e2 69 91 4c 7d 02 \tvpgatherqd %xmm2,0x2(%rbp,%xmm7,2),%xmm1",}, | ||
679 | {{0xc4, 0xe2, 0xe9, 0x91, 0x4c, 0x7d, 0x02, }, 7, 0, "", "", | ||
680 | "c4 e2 e9 91 4c 7d 02 \tvpgatherqq %xmm2,0x2(%rbp,%xmm7,2),%xmm1",}, | ||
681 | {{0x62, 0x22, 0x7d, 0x41, 0x91, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
682 | "62 22 7d 41 91 94 dd 7b 00 00 00 \tvpgatherqd 0x7b(%rbp,%zmm27,8),%ymm26{%k1}",}, | ||
683 | {{0x62, 0x22, 0xfd, 0x41, 0x91, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
684 | "62 22 fd 41 91 94 dd 7b 00 00 00 \tvpgatherqq 0x7b(%rbp,%zmm27,8),%zmm26{%k1}",}, | ||
685 | {{0x62, 0x22, 0x7d, 0x41, 0xa0, 0xa4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
686 | "62 22 7d 41 a0 a4 ed 7b 00 00 00 \tvpscatterdd %zmm28,0x7b(%rbp,%zmm29,8){%k1}",}, | ||
687 | {{0x62, 0x22, 0xfd, 0x41, 0xa0, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
688 | "62 22 fd 41 a0 94 dd 7b 00 00 00 \tvpscatterdq %zmm26,0x7b(%rbp,%ymm27,8){%k1}",}, | ||
689 | {{0x62, 0xb2, 0x7d, 0x41, 0xa1, 0xb4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
690 | "62 b2 7d 41 a1 b4 ed 7b 00 00 00 \tvpscatterqd %ymm6,0x7b(%rbp,%zmm29,8){%k1}",}, | ||
691 | {{0x62, 0xb2, 0xfd, 0x21, 0xa1, 0xb4, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
692 | "62 b2 fd 21 a1 b4 dd 7b 00 00 00 \tvpscatterqq %ymm6,0x7b(%rbp,%ymm27,8){%k1}",}, | ||
693 | {{0x62, 0x22, 0x7d, 0x41, 0xa2, 0xa4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
694 | "62 22 7d 41 a2 a4 ed 7b 00 00 00 \tvscatterdps %zmm28,0x7b(%rbp,%zmm29,8){%k1}",}, | ||
695 | {{0x62, 0x22, 0xfd, 0x41, 0xa2, 0xa4, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
696 | "62 22 fd 41 a2 a4 dd 7b 00 00 00 \tvscatterdpd %zmm28,0x7b(%rbp,%ymm27,8){%k1}",}, | ||
697 | {{0x62, 0xb2, 0x7d, 0x41, 0xa3, 0xb4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
698 | "62 b2 7d 41 a3 b4 ed 7b 00 00 00 \tvscatterqps %ymm6,0x7b(%rbp,%zmm29,8){%k1}",}, | ||
699 | {{0x62, 0x22, 0xfd, 0x41, 0xa3, 0xa4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
700 | "62 22 fd 41 a3 a4 ed 7b 00 00 00 \tvscatterqpd %zmm28,0x7b(%rbp,%zmm29,8){%k1}",}, | ||
701 | {{0x62, 0x02, 0xa5, 0x40, 0xb4, 0xe2, }, 6, 0, "", "", | ||
702 | "62 02 a5 40 b4 e2 \tvpmadd52luq %zmm26,%zmm27,%zmm28",}, | ||
703 | {{0x62, 0x02, 0xa5, 0x40, 0xb5, 0xe2, }, 6, 0, "", "", | ||
704 | "62 02 a5 40 b5 e2 \tvpmadd52huq %zmm26,%zmm27,%zmm28",}, | ||
705 | {{0x62, 0x02, 0x7d, 0x48, 0xc4, 0xda, }, 6, 0, "", "", | ||
706 | "62 02 7d 48 c4 da \tvpconflictd %zmm26,%zmm27",}, | ||
707 | {{0x62, 0x02, 0xfd, 0x48, 0xc4, 0xda, }, 6, 0, "", "", | ||
708 | "62 02 fd 48 c4 da \tvpconflictq %zmm26,%zmm27",}, | ||
709 | {{0x62, 0x02, 0x7d, 0x48, 0xc8, 0xf5, }, 6, 0, "", "", | ||
710 | "62 02 7d 48 c8 f5 \tvexp2ps %zmm29,%zmm30",}, | ||
711 | {{0x62, 0x02, 0xfd, 0x48, 0xc8, 0xda, }, 6, 0, "", "", | ||
712 | "62 02 fd 48 c8 da \tvexp2pd %zmm26,%zmm27",}, | ||
713 | {{0x62, 0x02, 0x7d, 0x48, 0xca, 0xf5, }, 6, 0, "", "", | ||
714 | "62 02 7d 48 ca f5 \tvrcp28ps %zmm29,%zmm30",}, | ||
715 | {{0x62, 0x02, 0xfd, 0x48, 0xca, 0xda, }, 6, 0, "", "", | ||
716 | "62 02 fd 48 ca da \tvrcp28pd %zmm26,%zmm27",}, | ||
717 | {{0x62, 0x02, 0x15, 0x07, 0xcb, 0xf4, }, 6, 0, "", "", | ||
718 | "62 02 15 07 cb f4 \tvrcp28ss %xmm28,%xmm29,%xmm30{%k7}",}, | ||
719 | {{0x62, 0x02, 0xad, 0x07, 0xcb, 0xd9, }, 6, 0, "", "", | ||
720 | "62 02 ad 07 cb d9 \tvrcp28sd %xmm25,%xmm26,%xmm27{%k7}",}, | ||
721 | {{0x62, 0x02, 0x7d, 0x48, 0xcc, 0xf5, }, 6, 0, "", "", | ||
722 | "62 02 7d 48 cc f5 \tvrsqrt28ps %zmm29,%zmm30",}, | ||
723 | {{0x62, 0x02, 0xfd, 0x48, 0xcc, 0xda, }, 6, 0, "", "", | ||
724 | "62 02 fd 48 cc da \tvrsqrt28pd %zmm26,%zmm27",}, | ||
725 | {{0x62, 0x02, 0x15, 0x07, 0xcd, 0xf4, }, 6, 0, "", "", | ||
726 | "62 02 15 07 cd f4 \tvrsqrt28ss %xmm28,%xmm29,%xmm30{%k7}",}, | ||
727 | {{0x62, 0x02, 0xad, 0x07, 0xcd, 0xd9, }, 6, 0, "", "", | ||
728 | "62 02 ad 07 cd d9 \tvrsqrt28sd %xmm25,%xmm26,%xmm27{%k7}",}, | ||
729 | {{0x62, 0x03, 0x15, 0x40, 0x03, 0xf4, 0x12, }, 7, 0, "", "", | ||
730 | "62 03 15 40 03 f4 12 \tvalignd $0x12,%zmm28,%zmm29,%zmm30",}, | ||
731 | {{0x62, 0x03, 0xad, 0x40, 0x03, 0xd9, 0x12, }, 7, 0, "", "", | ||
732 | "62 03 ad 40 03 d9 12 \tvalignq $0x12,%zmm25,%zmm26,%zmm27",}, | ||
733 | {{0xc4, 0xe3, 0x7d, 0x08, 0xd6, 0x05, }, 6, 0, "", "", | ||
734 | "c4 e3 7d 08 d6 05 \tvroundps $0x5,%ymm6,%ymm2",}, | ||
735 | {{0x62, 0x03, 0x7d, 0x48, 0x08, 0xd1, 0x12, }, 7, 0, "", "", | ||
736 | "62 03 7d 48 08 d1 12 \tvrndscaleps $0x12,%zmm25,%zmm26",}, | ||
737 | {{0xc4, 0xe3, 0x7d, 0x09, 0xd6, 0x05, }, 6, 0, "", "", | ||
738 | "c4 e3 7d 09 d6 05 \tvroundpd $0x5,%ymm6,%ymm2",}, | ||
739 | {{0x62, 0x03, 0xfd, 0x48, 0x09, 0xd1, 0x12, }, 7, 0, "", "", | ||
740 | "62 03 fd 48 09 d1 12 \tvrndscalepd $0x12,%zmm25,%zmm26",}, | ||
741 | {{0xc4, 0xe3, 0x49, 0x0a, 0xd4, 0x05, }, 6, 0, "", "", | ||
742 | "c4 e3 49 0a d4 05 \tvroundss $0x5,%xmm4,%xmm6,%xmm2",}, | ||
743 | {{0x62, 0x03, 0x35, 0x07, 0x0a, 0xd0, 0x12, }, 7, 0, "", "", | ||
744 | "62 03 35 07 0a d0 12 \tvrndscaless $0x12,%xmm24,%xmm25,%xmm26{%k7}",}, | ||
745 | {{0xc4, 0xe3, 0x49, 0x0b, 0xd4, 0x05, }, 6, 0, "", "", | ||
746 | "c4 e3 49 0b d4 05 \tvroundsd $0x5,%xmm4,%xmm6,%xmm2",}, | ||
747 | {{0x62, 0x03, 0xb5, 0x07, 0x0b, 0xd0, 0x12, }, 7, 0, "", "", | ||
748 | "62 03 b5 07 0b d0 12 \tvrndscalesd $0x12,%xmm24,%xmm25,%xmm26{%k7}",}, | ||
749 | {{0xc4, 0xe3, 0x5d, 0x18, 0xf4, 0x05, }, 6, 0, "", "", | ||
750 | "c4 e3 5d 18 f4 05 \tvinsertf128 $0x5,%xmm4,%ymm4,%ymm6",}, | ||
751 | {{0x62, 0x03, 0x35, 0x47, 0x18, 0xd0, 0x12, }, 7, 0, "", "", | ||
752 | "62 03 35 47 18 d0 12 \tvinsertf32x4 $0x12,%xmm24,%zmm25,%zmm26{%k7}",}, | ||
753 | {{0x62, 0x03, 0xb5, 0x47, 0x18, 0xd0, 0x12, }, 7, 0, "", "", | ||
754 | "62 03 b5 47 18 d0 12 \tvinsertf64x2 $0x12,%xmm24,%zmm25,%zmm26{%k7}",}, | ||
755 | {{0xc4, 0xe3, 0x7d, 0x19, 0xe4, 0x05, }, 6, 0, "", "", | ||
756 | "c4 e3 7d 19 e4 05 \tvextractf128 $0x5,%ymm4,%xmm4",}, | ||
757 | {{0x62, 0x03, 0x7d, 0x4f, 0x19, 0xca, 0x12, }, 7, 0, "", "", | ||
758 | "62 03 7d 4f 19 ca 12 \tvextractf32x4 $0x12,%zmm25,%xmm26{%k7}",}, | ||
759 | {{0x62, 0x03, 0xfd, 0x4f, 0x19, 0xca, 0x12, }, 7, 0, "", "", | ||
760 | "62 03 fd 4f 19 ca 12 \tvextractf64x2 $0x12,%zmm25,%xmm26{%k7}",}, | ||
761 | {{0x62, 0x03, 0x2d, 0x47, 0x1a, 0xd9, 0x12, }, 7, 0, "", "", | ||
762 | "62 03 2d 47 1a d9 12 \tvinsertf32x8 $0x12,%ymm25,%zmm26,%zmm27{%k7}",}, | ||
763 | {{0x62, 0x03, 0x95, 0x47, 0x1a, 0xf4, 0x12, }, 7, 0, "", "", | ||
764 | "62 03 95 47 1a f4 12 \tvinsertf64x4 $0x12,%ymm28,%zmm29,%zmm30{%k7}",}, | ||
765 | {{0x62, 0x03, 0x7d, 0x4f, 0x1b, 0xee, 0x12, }, 7, 0, "", "", | ||
766 | "62 03 7d 4f 1b ee 12 \tvextractf32x8 $0x12,%zmm29,%ymm30{%k7}",}, | ||
767 | {{0x62, 0x03, 0xfd, 0x4f, 0x1b, 0xd3, 0x12, }, 7, 0, "", "", | ||
768 | "62 03 fd 4f 1b d3 12 \tvextractf64x4 $0x12,%zmm26,%ymm27{%k7}",}, | ||
769 | {{0x62, 0x93, 0x0d, 0x40, 0x1e, 0xed, 0x12, }, 7, 0, "", "", | ||
770 | "62 93 0d 40 1e ed 12 \tvpcmpud $0x12,%zmm29,%zmm30,%k5",}, | ||
771 | {{0x62, 0x93, 0xa5, 0x40, 0x1e, 0xea, 0x12, }, 7, 0, "", "", | ||
772 | "62 93 a5 40 1e ea 12 \tvpcmpuq $0x12,%zmm26,%zmm27,%k5",}, | ||
773 | {{0x62, 0x93, 0x0d, 0x40, 0x1f, 0xed, 0x12, }, 7, 0, "", "", | ||
774 | "62 93 0d 40 1f ed 12 \tvpcmpd $0x12,%zmm29,%zmm30,%k5",}, | ||
775 | {{0x62, 0x93, 0xa5, 0x40, 0x1f, 0xea, 0x12, }, 7, 0, "", "", | ||
776 | "62 93 a5 40 1f ea 12 \tvpcmpq $0x12,%zmm26,%zmm27,%k5",}, | ||
777 | {{0x62, 0x03, 0x15, 0x40, 0x23, 0xf4, 0x12, }, 7, 0, "", "", | ||
778 | "62 03 15 40 23 f4 12 \tvshuff32x4 $0x12,%zmm28,%zmm29,%zmm30",}, | ||
779 | {{0x62, 0x03, 0xad, 0x40, 0x23, 0xd9, 0x12, }, 7, 0, "", "", | ||
780 | "62 03 ad 40 23 d9 12 \tvshuff64x2 $0x12,%zmm25,%zmm26,%zmm27",}, | ||
781 | {{0x62, 0x03, 0x15, 0x40, 0x25, 0xf4, 0x12, }, 7, 0, "", "", | ||
782 | "62 03 15 40 25 f4 12 \tvpternlogd $0x12,%zmm28,%zmm29,%zmm30",}, | ||
783 | {{0x62, 0x03, 0x95, 0x40, 0x25, 0xf4, 0x12, }, 7, 0, "", "", | ||
784 | "62 03 95 40 25 f4 12 \tvpternlogq $0x12,%zmm28,%zmm29,%zmm30",}, | ||
785 | {{0x62, 0x03, 0x7d, 0x48, 0x26, 0xda, 0x12, }, 7, 0, "", "", | ||
786 | "62 03 7d 48 26 da 12 \tvgetmantps $0x12,%zmm26,%zmm27",}, | ||
787 | {{0x62, 0x03, 0xfd, 0x48, 0x26, 0xf5, 0x12, }, 7, 0, "", "", | ||
788 | "62 03 fd 48 26 f5 12 \tvgetmantpd $0x12,%zmm29,%zmm30",}, | ||
789 | {{0x62, 0x03, 0x2d, 0x07, 0x27, 0xd9, 0x12, }, 7, 0, "", "", | ||
790 | "62 03 2d 07 27 d9 12 \tvgetmantss $0x12,%xmm25,%xmm26,%xmm27{%k7}",}, | ||
791 | {{0x62, 0x03, 0x95, 0x07, 0x27, 0xf4, 0x12, }, 7, 0, "", "", | ||
792 | "62 03 95 07 27 f4 12 \tvgetmantsd $0x12,%xmm28,%xmm29,%xmm30{%k7}",}, | ||
793 | {{0xc4, 0xe3, 0x5d, 0x38, 0xf4, 0x05, }, 6, 0, "", "", | ||
794 | "c4 e3 5d 38 f4 05 \tvinserti128 $0x5,%xmm4,%ymm4,%ymm6",}, | ||
795 | {{0x62, 0x03, 0x35, 0x47, 0x38, 0xd0, 0x12, }, 7, 0, "", "", | ||
796 | "62 03 35 47 38 d0 12 \tvinserti32x4 $0x12,%xmm24,%zmm25,%zmm26{%k7}",}, | ||
797 | {{0x62, 0x03, 0xb5, 0x47, 0x38, 0xd0, 0x12, }, 7, 0, "", "", | ||
798 | "62 03 b5 47 38 d0 12 \tvinserti64x2 $0x12,%xmm24,%zmm25,%zmm26{%k7}",}, | ||
799 | {{0xc4, 0xe3, 0x7d, 0x39, 0xe6, 0x05, }, 6, 0, "", "", | ||
800 | "c4 e3 7d 39 e6 05 \tvextracti128 $0x5,%ymm4,%xmm6",}, | ||
801 | {{0x62, 0x03, 0x7d, 0x4f, 0x39, 0xca, 0x12, }, 7, 0, "", "", | ||
802 | "62 03 7d 4f 39 ca 12 \tvextracti32x4 $0x12,%zmm25,%xmm26{%k7}",}, | ||
803 | {{0x62, 0x03, 0xfd, 0x4f, 0x39, 0xca, 0x12, }, 7, 0, "", "", | ||
804 | "62 03 fd 4f 39 ca 12 \tvextracti64x2 $0x12,%zmm25,%xmm26{%k7}",}, | ||
805 | {{0x62, 0x03, 0x15, 0x47, 0x3a, 0xf4, 0x12, }, 7, 0, "", "", | ||
806 | "62 03 15 47 3a f4 12 \tvinserti32x8 $0x12,%ymm28,%zmm29,%zmm30{%k7}",}, | ||
807 | {{0x62, 0x03, 0xad, 0x47, 0x3a, 0xd9, 0x12, }, 7, 0, "", "", | ||
808 | "62 03 ad 47 3a d9 12 \tvinserti64x4 $0x12,%ymm25,%zmm26,%zmm27{%k7}",}, | ||
809 | {{0x62, 0x03, 0x7d, 0x4f, 0x3b, 0xee, 0x12, }, 7, 0, "", "", | ||
810 | "62 03 7d 4f 3b ee 12 \tvextracti32x8 $0x12,%zmm29,%ymm30{%k7}",}, | ||
811 | {{0x62, 0x03, 0xfd, 0x4f, 0x3b, 0xd3, 0x12, }, 7, 0, "", "", | ||
812 | "62 03 fd 4f 3b d3 12 \tvextracti64x4 $0x12,%zmm26,%ymm27{%k7}",}, | ||
813 | {{0x62, 0x93, 0x0d, 0x40, 0x3e, 0xed, 0x12, }, 7, 0, "", "", | ||
814 | "62 93 0d 40 3e ed 12 \tvpcmpub $0x12,%zmm29,%zmm30,%k5",}, | ||
815 | {{0x62, 0x93, 0xa5, 0x40, 0x3e, 0xea, 0x12, }, 7, 0, "", "", | ||
816 | "62 93 a5 40 3e ea 12 \tvpcmpuw $0x12,%zmm26,%zmm27,%k5",}, | ||
817 | {{0x62, 0x93, 0x0d, 0x40, 0x3f, 0xed, 0x12, }, 7, 0, "", "", | ||
818 | "62 93 0d 40 3f ed 12 \tvpcmpb $0x12,%zmm29,%zmm30,%k5",}, | ||
819 | {{0x62, 0x93, 0xa5, 0x40, 0x3f, 0xea, 0x12, }, 7, 0, "", "", | ||
820 | "62 93 a5 40 3f ea 12 \tvpcmpw $0x12,%zmm26,%zmm27,%k5",}, | ||
821 | {{0xc4, 0xe3, 0x4d, 0x42, 0xd4, 0x05, }, 6, 0, "", "", | ||
822 | "c4 e3 4d 42 d4 05 \tvmpsadbw $0x5,%ymm4,%ymm6,%ymm2",}, | ||
823 | {{0x62, 0xf3, 0x55, 0x48, 0x42, 0xf4, 0x12, }, 7, 0, "", "", | ||
824 | "62 f3 55 48 42 f4 12 \tvdbpsadbw $0x12,%zmm4,%zmm5,%zmm6",}, | ||
825 | {{0x62, 0x03, 0x2d, 0x40, 0x43, 0xd9, 0x12, }, 7, 0, "", "", | ||
826 | "62 03 2d 40 43 d9 12 \tvshufi32x4 $0x12,%zmm25,%zmm26,%zmm27",}, | ||
827 | {{0x62, 0x03, 0x95, 0x40, 0x43, 0xf4, 0x12, }, 7, 0, "", "", | ||
828 | "62 03 95 40 43 f4 12 \tvshufi64x2 $0x12,%zmm28,%zmm29,%zmm30",}, | ||
829 | {{0x62, 0x03, 0x2d, 0x40, 0x50, 0xd9, 0x12, }, 7, 0, "", "", | ||
830 | "62 03 2d 40 50 d9 12 \tvrangeps $0x12,%zmm25,%zmm26,%zmm27",}, | ||
831 | {{0x62, 0x03, 0x95, 0x40, 0x50, 0xf4, 0x12, }, 7, 0, "", "", | ||
832 | "62 03 95 40 50 f4 12 \tvrangepd $0x12,%zmm28,%zmm29,%zmm30",}, | ||
833 | {{0x62, 0x03, 0x2d, 0x00, 0x51, 0xd9, 0x12, }, 7, 0, "", "", | ||
834 | "62 03 2d 00 51 d9 12 \tvrangess $0x12,%xmm25,%xmm26,%xmm27",}, | ||
835 | {{0x62, 0x03, 0x95, 0x00, 0x51, 0xf4, 0x12, }, 7, 0, "", "", | ||
836 | "62 03 95 00 51 f4 12 \tvrangesd $0x12,%xmm28,%xmm29,%xmm30",}, | ||
837 | {{0x62, 0x03, 0x15, 0x40, 0x54, 0xf4, 0x12, }, 7, 0, "", "", | ||
838 | "62 03 15 40 54 f4 12 \tvfixupimmps $0x12,%zmm28,%zmm29,%zmm30",}, | ||
839 | {{0x62, 0x03, 0xad, 0x40, 0x54, 0xd9, 0x12, }, 7, 0, "", "", | ||
840 | "62 03 ad 40 54 d9 12 \tvfixupimmpd $0x12,%zmm25,%zmm26,%zmm27",}, | ||
841 | {{0x62, 0x03, 0x15, 0x07, 0x55, 0xf4, 0x12, }, 7, 0, "", "", | ||
842 | "62 03 15 07 55 f4 12 \tvfixupimmss $0x12,%xmm28,%xmm29,%xmm30{%k7}",}, | ||
843 | {{0x62, 0x03, 0xad, 0x07, 0x55, 0xd9, 0x12, }, 7, 0, "", "", | ||
844 | "62 03 ad 07 55 d9 12 \tvfixupimmsd $0x12,%xmm25,%xmm26,%xmm27{%k7}",}, | ||
845 | {{0x62, 0x03, 0x7d, 0x48, 0x56, 0xda, 0x12, }, 7, 0, "", "", | ||
846 | "62 03 7d 48 56 da 12 \tvreduceps $0x12,%zmm26,%zmm27",}, | ||
847 | {{0x62, 0x03, 0xfd, 0x48, 0x56, 0xf5, 0x12, }, 7, 0, "", "", | ||
848 | "62 03 fd 48 56 f5 12 \tvreducepd $0x12,%zmm29,%zmm30",}, | ||
849 | {{0x62, 0x03, 0x2d, 0x00, 0x57, 0xd9, 0x12, }, 7, 0, "", "", | ||
850 | "62 03 2d 00 57 d9 12 \tvreducess $0x12,%xmm25,%xmm26,%xmm27",}, | ||
851 | {{0x62, 0x03, 0x95, 0x00, 0x57, 0xf4, 0x12, }, 7, 0, "", "", | ||
852 | "62 03 95 00 57 f4 12 \tvreducesd $0x12,%xmm28,%xmm29,%xmm30",}, | ||
853 | {{0x62, 0x93, 0x7d, 0x48, 0x66, 0xeb, 0x12, }, 7, 0, "", "", | ||
854 | "62 93 7d 48 66 eb 12 \tvfpclassps $0x12,%zmm27,%k5",}, | ||
855 | {{0x62, 0x93, 0xfd, 0x48, 0x66, 0xee, 0x12, }, 7, 0, "", "", | ||
856 | "62 93 fd 48 66 ee 12 \tvfpclasspd $0x12,%zmm30,%k5",}, | ||
857 | {{0x62, 0x93, 0x7d, 0x08, 0x67, 0xeb, 0x12, }, 7, 0, "", "", | ||
858 | "62 93 7d 08 67 eb 12 \tvfpclassss $0x12,%xmm27,%k5",}, | ||
859 | {{0x62, 0x93, 0xfd, 0x08, 0x67, 0xee, 0x12, }, 7, 0, "", "", | ||
860 | "62 93 fd 08 67 ee 12 \tvfpclasssd $0x12,%xmm30,%k5",}, | ||
861 | {{0x62, 0x91, 0x2d, 0x40, 0x72, 0xc1, 0x12, }, 7, 0, "", "", | ||
862 | "62 91 2d 40 72 c1 12 \tvprord $0x12,%zmm25,%zmm26",}, | ||
863 | {{0x62, 0x91, 0xad, 0x40, 0x72, 0xc1, 0x12, }, 7, 0, "", "", | ||
864 | "62 91 ad 40 72 c1 12 \tvprorq $0x12,%zmm25,%zmm26",}, | ||
865 | {{0x62, 0x91, 0x0d, 0x40, 0x72, 0xcd, 0x12, }, 7, 0, "", "", | ||
866 | "62 91 0d 40 72 cd 12 \tvprold $0x12,%zmm29,%zmm30",}, | ||
867 | {{0x62, 0x91, 0x8d, 0x40, 0x72, 0xcd, 0x12, }, 7, 0, "", "", | ||
868 | "62 91 8d 40 72 cd 12 \tvprolq $0x12,%zmm29,%zmm30",}, | ||
869 | {{0x0f, 0x72, 0xe6, 0x02, }, 4, 0, "", "", | ||
870 | "0f 72 e6 02 \tpsrad $0x2,%mm6",}, | ||
871 | {{0xc5, 0xed, 0x72, 0xe6, 0x05, }, 5, 0, "", "", | ||
872 | "c5 ed 72 e6 05 \tvpsrad $0x5,%ymm6,%ymm2",}, | ||
873 | {{0x62, 0x91, 0x4d, 0x40, 0x72, 0xe2, 0x05, }, 7, 0, "", "", | ||
874 | "62 91 4d 40 72 e2 05 \tvpsrad $0x5,%zmm26,%zmm22",}, | ||
875 | {{0x62, 0x91, 0xcd, 0x40, 0x72, 0xe2, 0x05, }, 7, 0, "", "", | ||
876 | "62 91 cd 40 72 e2 05 \tvpsraq $0x5,%zmm26,%zmm22",}, | ||
877 | {{0x62, 0x92, 0x7d, 0x41, 0xc6, 0x8c, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
878 | "62 92 7d 41 c6 8c fe 7b 00 00 00 \tvgatherpf0dps 0x7b(%r14,%zmm31,8){%k1}",}, | ||
879 | {{0x62, 0x92, 0xfd, 0x41, 0xc6, 0x8c, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
880 | "62 92 fd 41 c6 8c fe 7b 00 00 00 \tvgatherpf0dpd 0x7b(%r14,%ymm31,8){%k1}",}, | ||
881 | {{0x62, 0x92, 0x7d, 0x41, 0xc6, 0x94, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
882 | "62 92 7d 41 c6 94 fe 7b 00 00 00 \tvgatherpf1dps 0x7b(%r14,%zmm31,8){%k1}",}, | ||
883 | {{0x62, 0x92, 0xfd, 0x41, 0xc6, 0x94, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
884 | "62 92 fd 41 c6 94 fe 7b 00 00 00 \tvgatherpf1dpd 0x7b(%r14,%ymm31,8){%k1}",}, | ||
885 | {{0x62, 0x92, 0x7d, 0x41, 0xc6, 0xac, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
886 | "62 92 7d 41 c6 ac fe 7b 00 00 00 \tvscatterpf0dps 0x7b(%r14,%zmm31,8){%k1}",}, | ||
887 | {{0x62, 0x92, 0xfd, 0x41, 0xc6, 0xac, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
888 | "62 92 fd 41 c6 ac fe 7b 00 00 00 \tvscatterpf0dpd 0x7b(%r14,%ymm31,8){%k1}",}, | ||
889 | {{0x62, 0x92, 0x7d, 0x41, 0xc6, 0xb4, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
890 | "62 92 7d 41 c6 b4 fe 7b 00 00 00 \tvscatterpf1dps 0x7b(%r14,%zmm31,8){%k1}",}, | ||
891 | {{0x62, 0x92, 0xfd, 0x41, 0xc6, 0xb4, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
892 | "62 92 fd 41 c6 b4 fe 7b 00 00 00 \tvscatterpf1dpd 0x7b(%r14,%ymm31,8){%k1}",}, | ||
893 | {{0x62, 0x92, 0x7d, 0x41, 0xc7, 0x8c, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
894 | "62 92 7d 41 c7 8c fe 7b 00 00 00 \tvgatherpf0qps 0x7b(%r14,%zmm31,8){%k1}",}, | ||
895 | {{0x62, 0x92, 0xfd, 0x41, 0xc7, 0x8c, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
896 | "62 92 fd 41 c7 8c fe 7b 00 00 00 \tvgatherpf0qpd 0x7b(%r14,%zmm31,8){%k1}",}, | ||
897 | {{0x62, 0x92, 0x7d, 0x41, 0xc7, 0x94, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
898 | "62 92 7d 41 c7 94 fe 7b 00 00 00 \tvgatherpf1qps 0x7b(%r14,%zmm31,8){%k1}",}, | ||
899 | {{0x62, 0x92, 0xfd, 0x41, 0xc7, 0x94, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
900 | "62 92 fd 41 c7 94 fe 7b 00 00 00 \tvgatherpf1qpd 0x7b(%r14,%zmm31,8){%k1}",}, | ||
901 | {{0x62, 0x92, 0x7d, 0x41, 0xc7, 0xac, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
902 | "62 92 7d 41 c7 ac fe 7b 00 00 00 \tvscatterpf0qps 0x7b(%r14,%zmm31,8){%k1}",}, | ||
903 | {{0x62, 0x92, 0xfd, 0x41, 0xc7, 0xac, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
904 | "62 92 fd 41 c7 ac fe 7b 00 00 00 \tvscatterpf0qpd 0x7b(%r14,%zmm31,8){%k1}",}, | ||
905 | {{0x62, 0x92, 0x7d, 0x41, 0xc7, 0xb4, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
906 | "62 92 7d 41 c7 b4 fe 7b 00 00 00 \tvscatterpf1qps 0x7b(%r14,%zmm31,8){%k1}",}, | ||
907 | {{0x62, 0x92, 0xfd, 0x41, 0xc7, 0xb4, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "", | ||
908 | "62 92 fd 41 c7 b4 fe 7b 00 00 00 \tvscatterpf1qpd 0x7b(%r14,%zmm31,8){%k1}",}, | ||
909 | {{0x62, 0x01, 0x95, 0x40, 0x58, 0xf4, }, 6, 0, "", "", | ||
910 | "62 01 95 40 58 f4 \tvaddpd %zmm28,%zmm29,%zmm30",}, | ||
911 | {{0x62, 0x01, 0x95, 0x47, 0x58, 0xf4, }, 6, 0, "", "", | ||
912 | "62 01 95 47 58 f4 \tvaddpd %zmm28,%zmm29,%zmm30{%k7}",}, | ||
913 | {{0x62, 0x01, 0x95, 0xc7, 0x58, 0xf4, }, 6, 0, "", "", | ||
914 | "62 01 95 c7 58 f4 \tvaddpd %zmm28,%zmm29,%zmm30{%k7}{z}",}, | ||
915 | {{0x62, 0x01, 0x95, 0x10, 0x58, 0xf4, }, 6, 0, "", "", | ||
916 | "62 01 95 10 58 f4 \tvaddpd {rn-sae},%zmm28,%zmm29,%zmm30",}, | ||
917 | {{0x62, 0x01, 0x95, 0x50, 0x58, 0xf4, }, 6, 0, "", "", | ||
918 | "62 01 95 50 58 f4 \tvaddpd {ru-sae},%zmm28,%zmm29,%zmm30",}, | ||
919 | {{0x62, 0x01, 0x95, 0x30, 0x58, 0xf4, }, 6, 0, "", "", | ||
920 | "62 01 95 30 58 f4 \tvaddpd {rd-sae},%zmm28,%zmm29,%zmm30",}, | ||
921 | {{0x62, 0x01, 0x95, 0x70, 0x58, 0xf4, }, 6, 0, "", "", | ||
922 | "62 01 95 70 58 f4 \tvaddpd {rz-sae},%zmm28,%zmm29,%zmm30",}, | ||
923 | {{0x62, 0x61, 0x95, 0x40, 0x58, 0x31, }, 6, 0, "", "", | ||
924 | "62 61 95 40 58 31 \tvaddpd (%rcx),%zmm29,%zmm30",}, | ||
925 | {{0x62, 0x21, 0x95, 0x40, 0x58, 0xb4, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 11, 0, "", "", | ||
926 | "62 21 95 40 58 b4 f0 23 01 00 00 \tvaddpd 0x123(%rax,%r14,8),%zmm29,%zmm30",}, | ||
927 | {{0x62, 0x61, 0x95, 0x50, 0x58, 0x31, }, 6, 0, "", "", | ||
928 | "62 61 95 50 58 31 \tvaddpd (%rcx){1to8},%zmm29,%zmm30",}, | ||
929 | {{0x62, 0x61, 0x95, 0x40, 0x58, 0x72, 0x7f, }, 7, 0, "", "", | ||
930 | "62 61 95 40 58 72 7f \tvaddpd 0x1fc0(%rdx),%zmm29,%zmm30",}, | ||
931 | {{0x62, 0x61, 0x95, 0x50, 0x58, 0x72, 0x7f, }, 7, 0, "", "", | ||
932 | "62 61 95 50 58 72 7f \tvaddpd 0x3f8(%rdx){1to8},%zmm29,%zmm30",}, | ||
933 | {{0x62, 0xf1, 0x0c, 0x50, 0xc2, 0x6a, 0x7f, 0x08, }, 8, 0, "", "", | ||
934 | "62 f1 0c 50 c2 6a 7f 08 \tvcmpeq_uqps 0x1fc(%rdx){1to16},%zmm30,%k5",}, | ||
935 | {{0x62, 0xb1, 0x97, 0x07, 0xc2, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, 0x01, }, 12, 0, "", "", | ||
936 | "62 b1 97 07 c2 ac f0 23 01 00 00 01 \tvcmpltsd 0x123(%rax,%r14,8),%xmm29,%k5{%k7}",}, | ||
937 | {{0x62, 0x91, 0x97, 0x17, 0xc2, 0xec, 0x02, }, 7, 0, "", "", | ||
938 | "62 91 97 17 c2 ec 02 \tvcmplesd {sae},%xmm28,%xmm29,%k5{%k7}",}, | ||
939 | {{0x62, 0x23, 0x15, 0x07, 0x27, 0xb4, 0xf0, 0x23, 0x01, 0x00, 0x00, 0x5b, }, 12, 0, "", "", | ||
940 | "62 23 15 07 27 b4 f0 23 01 00 00 5b \tvgetmantss $0x5b,0x123(%rax,%r14,8),%xmm29,%xmm30{%k7}",}, | ||
9 | {{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", | 941 | {{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", |
10 | "f3 0f 1b 00 \tbndmk (%rax),%bnd0",}, | 942 | "f3 0f 1b 00 \tbndmk (%rax),%bnd0",}, |
11 | {{0xf3, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "", | 943 | {{0xf3, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "", |
@@ -325,19 +1257,19 @@ | |||
325 | {{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | 1257 | {{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)",}, | 1258 | "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", | 1259 | {{0xf2, 0xe8, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "call", "unconditional", |
328 | "f2 e8 00 00 00 00 \tbnd callq 3f6 <main+0x3f6>",}, | 1260 | "f2 e8 00 00 00 00 \tbnd callq f22 <main+0xf22>",}, |
329 | {{0x67, 0xf2, 0xff, 0x10, }, 4, 0, "call", "indirect", | 1261 | {{0x67, 0xf2, 0xff, 0x10, }, 4, 0, "call", "indirect", |
330 | "67 f2 ff 10 \tbnd callq *(%eax)",}, | 1262 | "67 f2 ff 10 \tbnd callq *(%eax)",}, |
331 | {{0xf2, 0xc3, }, 2, 0, "ret", "indirect", | 1263 | {{0xf2, 0xc3, }, 2, 0, "ret", "indirect", |
332 | "f2 c3 \tbnd retq ",}, | 1264 | "f2 c3 \tbnd retq ",}, |
333 | {{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional", | 1265 | {{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional", |
334 | "f2 e9 00 00 00 00 \tbnd jmpq 402 <main+0x402>",}, | 1266 | "f2 e9 00 00 00 00 \tbnd jmpq f2e <main+0xf2e>",}, |
335 | {{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional", | 1267 | {{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional", |
336 | "f2 e9 00 00 00 00 \tbnd jmpq 408 <main+0x408>",}, | 1268 | "f2 e9 00 00 00 00 \tbnd jmpq f34 <main+0xf34>",}, |
337 | {{0x67, 0xf2, 0xff, 0x21, }, 4, 0, "jmp", "indirect", | 1269 | {{0x67, 0xf2, 0xff, 0x21, }, 4, 0, "jmp", "indirect", |
338 | "67 f2 ff 21 \tbnd jmpq *(%ecx)",}, | 1270 | "67 f2 ff 21 \tbnd jmpq *(%ecx)",}, |
339 | {{0xf2, 0x0f, 0x85, 0x00, 0x00, 0x00, 0x00, }, 7, 0, "jcc", "conditional", | 1271 | {{0xf2, 0x0f, 0x85, 0x00, 0x00, 0x00, 0x00, }, 7, 0, "jcc", "conditional", |
340 | "f2 0f 85 00 00 00 00 \tbnd jne 413 <main+0x413>",}, | 1272 | "f2 0f 85 00 00 00 00 \tbnd jne f3f <main+0xf3f>",}, |
341 | {{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "", | 1273 | {{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "", |
342 | "0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",}, | 1274 | "0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",}, |
343 | {{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "", | 1275 | {{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "", |
@@ -764,5 +1696,3 @@ | |||
764 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",}, | 1696 | "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, "", "", | 1697 | {{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)",}, | 1698 | "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 index 41b1b1c62660..979487dae8d4 100644 --- a/tools/perf/arch/x86/tests/insn-x86-dat-src.c +++ b/tools/perf/arch/x86/tests/insn-x86-dat-src.c | |||
@@ -19,8 +19,882 @@ int main(void) | |||
19 | /* Following line is a marker for the awk script - do not change */ | 19 | /* Following line is a marker for the awk script - do not change */ |
20 | asm volatile("rdtsc"); /* Start here */ | 20 | asm volatile("rdtsc"); /* Start here */ |
21 | 21 | ||
22 | /* Test fix for vcvtph2ps in x86-opcode-map.txt */ | ||
23 | |||
24 | asm volatile("vcvtph2ps %xmm3,%ymm5"); | ||
25 | |||
22 | #ifdef __x86_64__ | 26 | #ifdef __x86_64__ |
23 | 27 | ||
28 | /* AVX-512: Instructions with the same op codes as Mask Instructions */ | ||
29 | |||
30 | asm volatile("cmovno %rax,%rbx"); | ||
31 | asm volatile("cmovno 0x12345678(%rax),%rcx"); | ||
32 | asm volatile("cmovno 0x12345678(%rax),%cx"); | ||
33 | |||
34 | asm volatile("cmove %rax,%rbx"); | ||
35 | asm volatile("cmove 0x12345678(%rax),%rcx"); | ||
36 | asm volatile("cmove 0x12345678(%rax),%cx"); | ||
37 | |||
38 | asm volatile("seto 0x12345678(%rax)"); | ||
39 | asm volatile("setno 0x12345678(%rax)"); | ||
40 | asm volatile("setb 0x12345678(%rax)"); | ||
41 | asm volatile("setc 0x12345678(%rax)"); | ||
42 | asm volatile("setnae 0x12345678(%rax)"); | ||
43 | asm volatile("setae 0x12345678(%rax)"); | ||
44 | asm volatile("setnb 0x12345678(%rax)"); | ||
45 | asm volatile("setnc 0x12345678(%rax)"); | ||
46 | asm volatile("sets 0x12345678(%rax)"); | ||
47 | asm volatile("setns 0x12345678(%rax)"); | ||
48 | |||
49 | /* AVX-512: Mask Instructions */ | ||
50 | |||
51 | asm volatile("kandw %k7,%k6,%k5"); | ||
52 | asm volatile("kandq %k7,%k6,%k5"); | ||
53 | asm volatile("kandb %k7,%k6,%k5"); | ||
54 | asm volatile("kandd %k7,%k6,%k5"); | ||
55 | |||
56 | asm volatile("kandnw %k7,%k6,%k5"); | ||
57 | asm volatile("kandnq %k7,%k6,%k5"); | ||
58 | asm volatile("kandnb %k7,%k6,%k5"); | ||
59 | asm volatile("kandnd %k7,%k6,%k5"); | ||
60 | |||
61 | asm volatile("knotw %k7,%k6"); | ||
62 | asm volatile("knotq %k7,%k6"); | ||
63 | asm volatile("knotb %k7,%k6"); | ||
64 | asm volatile("knotd %k7,%k6"); | ||
65 | |||
66 | asm volatile("korw %k7,%k6,%k5"); | ||
67 | asm volatile("korq %k7,%k6,%k5"); | ||
68 | asm volatile("korb %k7,%k6,%k5"); | ||
69 | asm volatile("kord %k7,%k6,%k5"); | ||
70 | |||
71 | asm volatile("kxnorw %k7,%k6,%k5"); | ||
72 | asm volatile("kxnorq %k7,%k6,%k5"); | ||
73 | asm volatile("kxnorb %k7,%k6,%k5"); | ||
74 | asm volatile("kxnord %k7,%k6,%k5"); | ||
75 | |||
76 | asm volatile("kxorw %k7,%k6,%k5"); | ||
77 | asm volatile("kxorq %k7,%k6,%k5"); | ||
78 | asm volatile("kxorb %k7,%k6,%k5"); | ||
79 | asm volatile("kxord %k7,%k6,%k5"); | ||
80 | |||
81 | asm volatile("kaddw %k7,%k6,%k5"); | ||
82 | asm volatile("kaddq %k7,%k6,%k5"); | ||
83 | asm volatile("kaddb %k7,%k6,%k5"); | ||
84 | asm volatile("kaddd %k7,%k6,%k5"); | ||
85 | |||
86 | asm volatile("kunpckbw %k7,%k6,%k5"); | ||
87 | asm volatile("kunpckwd %k7,%k6,%k5"); | ||
88 | asm volatile("kunpckdq %k7,%k6,%k5"); | ||
89 | |||
90 | asm volatile("kmovw %k6,%k5"); | ||
91 | asm volatile("kmovw (%rcx),%k5"); | ||
92 | asm volatile("kmovw 0x123(%rax,%r14,8),%k5"); | ||
93 | asm volatile("kmovw %k5,(%rcx)"); | ||
94 | asm volatile("kmovw %k5,0x123(%rax,%r14,8)"); | ||
95 | asm volatile("kmovw %eax,%k5"); | ||
96 | asm volatile("kmovw %ebp,%k5"); | ||
97 | asm volatile("kmovw %r13d,%k5"); | ||
98 | asm volatile("kmovw %k5,%eax"); | ||
99 | asm volatile("kmovw %k5,%ebp"); | ||
100 | asm volatile("kmovw %k5,%r13d"); | ||
101 | |||
102 | asm volatile("kmovq %k6,%k5"); | ||
103 | asm volatile("kmovq (%rcx),%k5"); | ||
104 | asm volatile("kmovq 0x123(%rax,%r14,8),%k5"); | ||
105 | asm volatile("kmovq %k5,(%rcx)"); | ||
106 | asm volatile("kmovq %k5,0x123(%rax,%r14,8)"); | ||
107 | asm volatile("kmovq %rax,%k5"); | ||
108 | asm volatile("kmovq %rbp,%k5"); | ||
109 | asm volatile("kmovq %r13,%k5"); | ||
110 | asm volatile("kmovq %k5,%rax"); | ||
111 | asm volatile("kmovq %k5,%rbp"); | ||
112 | asm volatile("kmovq %k5,%r13"); | ||
113 | |||
114 | asm volatile("kmovb %k6,%k5"); | ||
115 | asm volatile("kmovb (%rcx),%k5"); | ||
116 | asm volatile("kmovb 0x123(%rax,%r14,8),%k5"); | ||
117 | asm volatile("kmovb %k5,(%rcx)"); | ||
118 | asm volatile("kmovb %k5,0x123(%rax,%r14,8)"); | ||
119 | asm volatile("kmovb %eax,%k5"); | ||
120 | asm volatile("kmovb %ebp,%k5"); | ||
121 | asm volatile("kmovb %r13d,%k5"); | ||
122 | asm volatile("kmovb %k5,%eax"); | ||
123 | asm volatile("kmovb %k5,%ebp"); | ||
124 | asm volatile("kmovb %k5,%r13d"); | ||
125 | |||
126 | asm volatile("kmovd %k6,%k5"); | ||
127 | asm volatile("kmovd (%rcx),%k5"); | ||
128 | asm volatile("kmovd 0x123(%rax,%r14,8),%k5"); | ||
129 | asm volatile("kmovd %k5,(%rcx)"); | ||
130 | asm volatile("kmovd %k5,0x123(%rax,%r14,8)"); | ||
131 | asm volatile("kmovd %eax,%k5"); | ||
132 | asm volatile("kmovd %ebp,%k5"); | ||
133 | asm volatile("kmovd %r13d,%k5"); | ||
134 | asm volatile("kmovd %k5,%eax"); | ||
135 | asm volatile("kmovd %k5,%ebp"); | ||
136 | asm volatile("kmovd %k5,%r13d"); | ||
137 | |||
138 | asm volatile("kortestw %k6,%k5"); | ||
139 | asm volatile("kortestq %k6,%k5"); | ||
140 | asm volatile("kortestb %k6,%k5"); | ||
141 | asm volatile("kortestd %k6,%k5"); | ||
142 | |||
143 | asm volatile("ktestw %k6,%k5"); | ||
144 | asm volatile("ktestq %k6,%k5"); | ||
145 | asm volatile("ktestb %k6,%k5"); | ||
146 | asm volatile("ktestd %k6,%k5"); | ||
147 | |||
148 | asm volatile("kshiftrw $0x12,%k6,%k5"); | ||
149 | asm volatile("kshiftrq $0x5b,%k6,%k5"); | ||
150 | asm volatile("kshiftlw $0x12,%k6,%k5"); | ||
151 | asm volatile("kshiftlq $0x5b,%k6,%k5"); | ||
152 | |||
153 | /* AVX-512: Op code 0f 5b */ | ||
154 | asm volatile("vcvtdq2ps %xmm5,%xmm6"); | ||
155 | asm volatile("vcvtqq2ps %zmm29,%ymm6{%k7}"); | ||
156 | asm volatile("vcvtps2dq %xmm5,%xmm6"); | ||
157 | asm volatile("vcvttps2dq %xmm5,%xmm6"); | ||
158 | |||
159 | /* AVX-512: Op code 0f 6f */ | ||
160 | |||
161 | asm volatile("movq %mm0,%mm4"); | ||
162 | asm volatile("vmovdqa %ymm4,%ymm6"); | ||
163 | asm volatile("vmovdqa32 %zmm25,%zmm26"); | ||
164 | asm volatile("vmovdqa64 %zmm25,%zmm26"); | ||
165 | asm volatile("vmovdqu %ymm4,%ymm6"); | ||
166 | asm volatile("vmovdqu32 %zmm29,%zmm30"); | ||
167 | asm volatile("vmovdqu64 %zmm25,%zmm26"); | ||
168 | asm volatile("vmovdqu8 %zmm29,%zmm30"); | ||
169 | asm volatile("vmovdqu16 %zmm25,%zmm26"); | ||
170 | |||
171 | /* AVX-512: Op code 0f 78 */ | ||
172 | |||
173 | asm volatile("vmread %rax,%rbx"); | ||
174 | asm volatile("vcvttps2udq %zmm25,%zmm26"); | ||
175 | asm volatile("vcvttpd2udq %zmm29,%ymm6{%k7}"); | ||
176 | asm volatile("vcvttsd2usi %xmm6,%rax"); | ||
177 | asm volatile("vcvttss2usi %xmm6,%rax"); | ||
178 | asm volatile("vcvttps2uqq %ymm5,%zmm26{%k7}"); | ||
179 | asm volatile("vcvttpd2uqq %zmm29,%zmm30"); | ||
180 | |||
181 | /* AVX-512: Op code 0f 79 */ | ||
182 | |||
183 | asm volatile("vmwrite %rax,%rbx"); | ||
184 | asm volatile("vcvtps2udq %zmm25,%zmm26"); | ||
185 | asm volatile("vcvtpd2udq %zmm29,%ymm6{%k7}"); | ||
186 | asm volatile("vcvtsd2usi %xmm6,%rax"); | ||
187 | asm volatile("vcvtss2usi %xmm6,%rax"); | ||
188 | asm volatile("vcvtps2uqq %ymm5,%zmm26{%k7}"); | ||
189 | asm volatile("vcvtpd2uqq %zmm29,%zmm30"); | ||
190 | |||
191 | /* AVX-512: Op code 0f 7a */ | ||
192 | |||
193 | asm volatile("vcvtudq2pd %ymm5,%zmm29{%k7}"); | ||
194 | asm volatile("vcvtuqq2pd %zmm25,%zmm26"); | ||
195 | asm volatile("vcvtudq2ps %zmm29,%zmm30"); | ||
196 | asm volatile("vcvtuqq2ps %zmm25,%ymm26{%k7}"); | ||
197 | asm volatile("vcvttps2qq %ymm25,%zmm26{%k7}"); | ||
198 | asm volatile("vcvttpd2qq %zmm29,%zmm30"); | ||
199 | |||
200 | /* AVX-512: Op code 0f 7b */ | ||
201 | |||
202 | asm volatile("vcvtusi2sd %eax,%xmm5,%xmm6"); | ||
203 | asm volatile("vcvtusi2ss %eax,%xmm5,%xmm6"); | ||
204 | asm volatile("vcvtps2qq %ymm5,%zmm26{%k7}"); | ||
205 | asm volatile("vcvtpd2qq %zmm29,%zmm30"); | ||
206 | |||
207 | /* AVX-512: Op code 0f 7f */ | ||
208 | |||
209 | asm volatile("movq.s %mm0,%mm4"); | ||
210 | asm volatile("vmovdqa %ymm8,%ymm6"); | ||
211 | asm volatile("vmovdqa32.s %zmm25,%zmm26"); | ||
212 | asm volatile("vmovdqa64.s %zmm25,%zmm26"); | ||
213 | asm volatile("vmovdqu %ymm8,%ymm6"); | ||
214 | asm volatile("vmovdqu32.s %zmm25,%zmm26"); | ||
215 | asm volatile("vmovdqu64.s %zmm25,%zmm26"); | ||
216 | asm volatile("vmovdqu8.s %zmm30,(%rcx)"); | ||
217 | asm volatile("vmovdqu16.s %zmm25,%zmm26"); | ||
218 | |||
219 | /* AVX-512: Op code 0f db */ | ||
220 | |||
221 | asm volatile("pand %mm1,%mm2"); | ||
222 | asm volatile("pand %xmm1,%xmm2"); | ||
223 | asm volatile("vpand %ymm4,%ymm6,%ymm2"); | ||
224 | asm volatile("vpandd %zmm24,%zmm25,%zmm26"); | ||
225 | asm volatile("vpandq %zmm24,%zmm25,%zmm26"); | ||
226 | |||
227 | /* AVX-512: Op code 0f df */ | ||
228 | |||
229 | asm volatile("pandn %mm1,%mm2"); | ||
230 | asm volatile("pandn %xmm1,%xmm2"); | ||
231 | asm volatile("vpandn %ymm4,%ymm6,%ymm2"); | ||
232 | asm volatile("vpandnd %zmm24,%zmm25,%zmm26"); | ||
233 | asm volatile("vpandnq %zmm24,%zmm25,%zmm26"); | ||
234 | |||
235 | /* AVX-512: Op code 0f e6 */ | ||
236 | |||
237 | asm volatile("vcvttpd2dq %xmm1,%xmm2"); | ||
238 | asm volatile("vcvtdq2pd %xmm5,%xmm6"); | ||
239 | asm volatile("vcvtdq2pd %ymm5,%zmm26{%k7}"); | ||
240 | asm volatile("vcvtqq2pd %zmm25,%zmm26"); | ||
241 | asm volatile("vcvtpd2dq %xmm1,%xmm2"); | ||
242 | |||
243 | /* AVX-512: Op code 0f eb */ | ||
244 | |||
245 | asm volatile("por %mm4,%mm6"); | ||
246 | asm volatile("vpor %ymm4,%ymm6,%ymm2"); | ||
247 | asm volatile("vpord %zmm24,%zmm25,%zmm26"); | ||
248 | asm volatile("vporq %zmm24,%zmm25,%zmm26"); | ||
249 | |||
250 | /* AVX-512: Op code 0f ef */ | ||
251 | |||
252 | asm volatile("pxor %mm4,%mm6"); | ||
253 | asm volatile("vpxor %ymm4,%ymm6,%ymm2"); | ||
254 | asm volatile("vpxord %zmm24,%zmm25,%zmm26"); | ||
255 | asm volatile("vpxorq %zmm24,%zmm25,%zmm26"); | ||
256 | |||
257 | /* AVX-512: Op code 0f 38 10 */ | ||
258 | |||
259 | asm volatile("pblendvb %xmm1,%xmm0"); | ||
260 | asm volatile("vpsrlvw %zmm27,%zmm28,%zmm29"); | ||
261 | asm volatile("vpmovuswb %zmm28,%ymm6{%k7}"); | ||
262 | |||
263 | /* AVX-512: Op code 0f 38 11 */ | ||
264 | |||
265 | asm volatile("vpmovusdb %zmm28,%xmm6{%k7}"); | ||
266 | asm volatile("vpsravw %zmm27,%zmm28,%zmm29"); | ||
267 | |||
268 | /* AVX-512: Op code 0f 38 12 */ | ||
269 | |||
270 | asm volatile("vpmovusqb %zmm27,%xmm6{%k7}"); | ||
271 | asm volatile("vpsllvw %zmm27,%zmm28,%zmm29"); | ||
272 | |||
273 | /* AVX-512: Op code 0f 38 13 */ | ||
274 | |||
275 | asm volatile("vcvtph2ps %xmm3,%ymm5"); | ||
276 | asm volatile("vcvtph2ps %ymm5,%zmm27{%k7}"); | ||
277 | asm volatile("vpmovusdw %zmm27,%ymm6{%k7}"); | ||
278 | |||
279 | /* AVX-512: Op code 0f 38 14 */ | ||
280 | |||
281 | asm volatile("blendvps %xmm1,%xmm0"); | ||
282 | asm volatile("vpmovusqw %zmm27,%xmm6{%k7}"); | ||
283 | asm volatile("vprorvd %zmm27,%zmm28,%zmm29"); | ||
284 | asm volatile("vprorvq %zmm27,%zmm28,%zmm29"); | ||
285 | |||
286 | /* AVX-512: Op code 0f 38 15 */ | ||
287 | |||
288 | asm volatile("blendvpd %xmm1,%xmm0"); | ||
289 | asm volatile("vpmovusqd %zmm27,%ymm6{%k7}"); | ||
290 | asm volatile("vprolvd %zmm27,%zmm28,%zmm29"); | ||
291 | asm volatile("vprolvq %zmm27,%zmm28,%zmm29"); | ||
292 | |||
293 | /* AVX-512: Op code 0f 38 16 */ | ||
294 | |||
295 | asm volatile("vpermps %ymm4,%ymm6,%ymm2"); | ||
296 | asm volatile("vpermps %ymm24,%ymm26,%ymm22{%k7}"); | ||
297 | asm volatile("vpermpd %ymm24,%ymm26,%ymm22{%k7}"); | ||
298 | |||
299 | /* AVX-512: Op code 0f 38 19 */ | ||
300 | |||
301 | asm volatile("vbroadcastsd %xmm4,%ymm6"); | ||
302 | asm volatile("vbroadcastf32x2 %xmm27,%zmm26"); | ||
303 | |||
304 | /* AVX-512: Op code 0f 38 1a */ | ||
305 | |||
306 | asm volatile("vbroadcastf128 (%rcx),%ymm4"); | ||
307 | asm volatile("vbroadcastf32x4 (%rcx),%zmm26"); | ||
308 | asm volatile("vbroadcastf64x2 (%rcx),%zmm26"); | ||
309 | |||
310 | /* AVX-512: Op code 0f 38 1b */ | ||
311 | |||
312 | asm volatile("vbroadcastf32x8 (%rcx),%zmm27"); | ||
313 | asm volatile("vbroadcastf64x4 (%rcx),%zmm26"); | ||
314 | |||
315 | /* AVX-512: Op code 0f 38 1f */ | ||
316 | |||
317 | asm volatile("vpabsq %zmm27,%zmm28"); | ||
318 | |||
319 | /* AVX-512: Op code 0f 38 20 */ | ||
320 | |||
321 | asm volatile("vpmovsxbw %xmm4,%xmm5"); | ||
322 | asm volatile("vpmovswb %zmm27,%ymm6{%k7}"); | ||
323 | |||
324 | /* AVX-512: Op code 0f 38 21 */ | ||
325 | |||
326 | asm volatile("vpmovsxbd %xmm4,%ymm6"); | ||
327 | asm volatile("vpmovsdb %zmm27,%xmm6{%k7}"); | ||
328 | |||
329 | /* AVX-512: Op code 0f 38 22 */ | ||
330 | |||
331 | asm volatile("vpmovsxbq %xmm4,%ymm4"); | ||
332 | asm volatile("vpmovsqb %zmm27,%xmm6{%k7}"); | ||
333 | |||
334 | /* AVX-512: Op code 0f 38 23 */ | ||
335 | |||
336 | asm volatile("vpmovsxwd %xmm4,%ymm4"); | ||
337 | asm volatile("vpmovsdw %zmm27,%ymm6{%k7}"); | ||
338 | |||
339 | /* AVX-512: Op code 0f 38 24 */ | ||
340 | |||
341 | asm volatile("vpmovsxwq %xmm4,%ymm6"); | ||
342 | asm volatile("vpmovsqw %zmm27,%xmm6{%k7}"); | ||
343 | |||
344 | /* AVX-512: Op code 0f 38 25 */ | ||
345 | |||
346 | asm volatile("vpmovsxdq %xmm4,%ymm4"); | ||
347 | asm volatile("vpmovsqd %zmm27,%ymm6{%k7}"); | ||
348 | |||
349 | /* AVX-512: Op code 0f 38 26 */ | ||
350 | |||
351 | asm volatile("vptestmb %zmm27,%zmm28,%k5"); | ||
352 | asm volatile("vptestmw %zmm27,%zmm28,%k5"); | ||
353 | asm volatile("vptestnmb %zmm26,%zmm27,%k5"); | ||
354 | asm volatile("vptestnmw %zmm26,%zmm27,%k5"); | ||
355 | |||
356 | /* AVX-512: Op code 0f 38 27 */ | ||
357 | |||
358 | asm volatile("vptestmd %zmm27,%zmm28,%k5"); | ||
359 | asm volatile("vptestmq %zmm27,%zmm28,%k5"); | ||
360 | asm volatile("vptestnmd %zmm26,%zmm27,%k5"); | ||
361 | asm volatile("vptestnmq %zmm26,%zmm27,%k5"); | ||
362 | |||
363 | /* AVX-512: Op code 0f 38 28 */ | ||
364 | |||
365 | asm volatile("vpmuldq %ymm4,%ymm6,%ymm2"); | ||
366 | asm volatile("vpmovm2b %k5,%zmm28"); | ||
367 | asm volatile("vpmovm2w %k5,%zmm28"); | ||
368 | |||
369 | /* AVX-512: Op code 0f 38 29 */ | ||
370 | |||
371 | asm volatile("vpcmpeqq %ymm4,%ymm6,%ymm2"); | ||
372 | asm volatile("vpmovb2m %zmm28,%k5"); | ||
373 | asm volatile("vpmovw2m %zmm28,%k5"); | ||
374 | |||
375 | /* AVX-512: Op code 0f 38 2a */ | ||
376 | |||
377 | asm volatile("vmovntdqa (%rcx),%ymm4"); | ||
378 | asm volatile("vpbroadcastmb2q %k6,%zmm30"); | ||
379 | |||
380 | /* AVX-512: Op code 0f 38 2c */ | ||
381 | |||
382 | asm volatile("vmaskmovps (%rcx),%ymm4,%ymm6"); | ||
383 | asm volatile("vscalefps %zmm24,%zmm25,%zmm26"); | ||
384 | asm volatile("vscalefpd %zmm24,%zmm25,%zmm26"); | ||
385 | |||
386 | /* AVX-512: Op code 0f 38 2d */ | ||
387 | |||
388 | asm volatile("vmaskmovpd (%rcx),%ymm4,%ymm6"); | ||
389 | asm volatile("vscalefss %xmm24,%xmm25,%xmm26{%k7}"); | ||
390 | asm volatile("vscalefsd %xmm24,%xmm25,%xmm26{%k7}"); | ||
391 | |||
392 | /* AVX-512: Op code 0f 38 30 */ | ||
393 | |||
394 | asm volatile("vpmovzxbw %xmm4,%ymm4"); | ||
395 | asm volatile("vpmovwb %zmm27,%ymm6{%k7}"); | ||
396 | |||
397 | /* AVX-512: Op code 0f 38 31 */ | ||
398 | |||
399 | asm volatile("vpmovzxbd %xmm4,%ymm6"); | ||
400 | asm volatile("vpmovdb %zmm27,%xmm6{%k7}"); | ||
401 | |||
402 | /* AVX-512: Op code 0f 38 32 */ | ||
403 | |||
404 | asm volatile("vpmovzxbq %xmm4,%ymm4"); | ||
405 | asm volatile("vpmovqb %zmm27,%xmm6{%k7}"); | ||
406 | |||
407 | /* AVX-512: Op code 0f 38 33 */ | ||
408 | |||
409 | asm volatile("vpmovzxwd %xmm4,%ymm4"); | ||
410 | asm volatile("vpmovdw %zmm27,%ymm6{%k7}"); | ||
411 | |||
412 | /* AVX-512: Op code 0f 38 34 */ | ||
413 | |||
414 | asm volatile("vpmovzxwq %xmm4,%ymm6"); | ||
415 | asm volatile("vpmovqw %zmm27,%xmm6{%k7}"); | ||
416 | |||
417 | /* AVX-512: Op code 0f 38 35 */ | ||
418 | |||
419 | asm volatile("vpmovzxdq %xmm4,%ymm4"); | ||
420 | asm volatile("vpmovqd %zmm27,%ymm6{%k7}"); | ||
421 | |||
422 | /* AVX-512: Op code 0f 38 38 */ | ||
423 | |||
424 | asm volatile("vpermd %ymm4,%ymm6,%ymm2"); | ||
425 | asm volatile("vpermd %ymm24,%ymm26,%ymm22{%k7}"); | ||
426 | asm volatile("vpermq %ymm24,%ymm26,%ymm22{%k7}"); | ||
427 | |||
428 | /* AVX-512: Op code 0f 38 38 */ | ||
429 | |||
430 | asm volatile("vpminsb %ymm4,%ymm6,%ymm2"); | ||
431 | asm volatile("vpmovm2d %k5,%zmm28"); | ||
432 | asm volatile("vpmovm2q %k5,%zmm28"); | ||
433 | |||
434 | /* AVX-512: Op code 0f 38 39 */ | ||
435 | |||
436 | asm volatile("vpminsd %xmm1,%xmm2,%xmm3"); | ||
437 | asm volatile("vpminsd %zmm24,%zmm25,%zmm26"); | ||
438 | asm volatile("vpminsq %zmm24,%zmm25,%zmm26"); | ||
439 | asm volatile("vpmovd2m %zmm28,%k5"); | ||
440 | asm volatile("vpmovq2m %zmm28,%k5"); | ||
441 | |||
442 | /* AVX-512: Op code 0f 38 3a */ | ||
443 | |||
444 | asm volatile("vpminuw %ymm4,%ymm6,%ymm2"); | ||
445 | asm volatile("vpbroadcastmw2d %k6,%zmm28"); | ||
446 | |||
447 | /* AVX-512: Op code 0f 38 3b */ | ||
448 | |||
449 | asm volatile("vpminud %ymm4,%ymm6,%ymm2"); | ||
450 | asm volatile("vpminud %zmm24,%zmm25,%zmm26"); | ||
451 | asm volatile("vpminuq %zmm24,%zmm25,%zmm26"); | ||
452 | |||
453 | /* AVX-512: Op code 0f 38 3d */ | ||
454 | |||
455 | asm volatile("vpmaxsd %ymm4,%ymm6,%ymm2"); | ||
456 | asm volatile("vpmaxsd %zmm24,%zmm25,%zmm26"); | ||
457 | asm volatile("vpmaxsq %zmm24,%zmm25,%zmm26"); | ||
458 | |||
459 | /* AVX-512: Op code 0f 38 3f */ | ||
460 | |||
461 | asm volatile("vpmaxud %ymm4,%ymm6,%ymm2"); | ||
462 | asm volatile("vpmaxud %zmm24,%zmm25,%zmm26"); | ||
463 | asm volatile("vpmaxuq %zmm24,%zmm25,%zmm26"); | ||
464 | |||
465 | /* AVX-512: Op code 0f 38 42 */ | ||
466 | |||
467 | asm volatile("vpmulld %ymm4,%ymm6,%ymm2"); | ||
468 | asm volatile("vpmulld %zmm24,%zmm25,%zmm26"); | ||
469 | asm volatile("vpmullq %zmm24,%zmm25,%zmm26"); | ||
470 | |||
471 | /* AVX-512: Op code 0f 38 42 */ | ||
472 | |||
473 | asm volatile("vgetexpps %zmm25,%zmm26"); | ||
474 | asm volatile("vgetexppd %zmm27,%zmm28"); | ||
475 | |||
476 | /* AVX-512: Op code 0f 38 43 */ | ||
477 | |||
478 | asm volatile("vgetexpss %xmm24,%xmm25,%xmm26{%k7}"); | ||
479 | asm volatile("vgetexpsd %xmm28,%xmm29,%xmm30{%k7}"); | ||
480 | |||
481 | /* AVX-512: Op code 0f 38 44 */ | ||
482 | |||
483 | asm volatile("vplzcntd %zmm27,%zmm28"); | ||
484 | asm volatile("vplzcntq %zmm27,%zmm28"); | ||
485 | |||
486 | /* AVX-512: Op code 0f 38 46 */ | ||
487 | |||
488 | asm volatile("vpsravd %ymm4,%ymm6,%ymm2"); | ||
489 | asm volatile("vpsravd %zmm24,%zmm25,%zmm26"); | ||
490 | asm volatile("vpsravq %zmm24,%zmm25,%zmm26"); | ||
491 | |||
492 | /* AVX-512: Op code 0f 38 4c */ | ||
493 | |||
494 | asm volatile("vrcp14ps %zmm25,%zmm26"); | ||
495 | asm volatile("vrcp14pd %zmm27,%zmm28"); | ||
496 | |||
497 | /* AVX-512: Op code 0f 38 4d */ | ||
498 | |||
499 | asm volatile("vrcp14ss %xmm24,%xmm25,%xmm26{%k7}"); | ||
500 | asm volatile("vrcp14sd %xmm24,%xmm25,%xmm26{%k7}"); | ||
501 | |||
502 | /* AVX-512: Op code 0f 38 4e */ | ||
503 | |||
504 | asm volatile("vrsqrt14ps %zmm25,%zmm26"); | ||
505 | asm volatile("vrsqrt14pd %zmm27,%zmm28"); | ||
506 | |||
507 | /* AVX-512: Op code 0f 38 4f */ | ||
508 | |||
509 | asm volatile("vrsqrt14ss %xmm24,%xmm25,%xmm26{%k7}"); | ||
510 | asm volatile("vrsqrt14sd %xmm24,%xmm25,%xmm26{%k7}"); | ||
511 | |||
512 | /* AVX-512: Op code 0f 38 59 */ | ||
513 | |||
514 | asm volatile("vpbroadcastq %xmm4,%xmm6"); | ||
515 | asm volatile("vbroadcasti32x2 %xmm27,%zmm26"); | ||
516 | |||
517 | /* AVX-512: Op code 0f 38 5a */ | ||
518 | |||
519 | asm volatile("vbroadcasti128 (%rcx),%ymm4"); | ||
520 | asm volatile("vbroadcasti32x4 (%rcx),%zmm26"); | ||
521 | asm volatile("vbroadcasti64x2 (%rcx),%zmm26"); | ||
522 | |||
523 | /* AVX-512: Op code 0f 38 5b */ | ||
524 | |||
525 | asm volatile("vbroadcasti32x8 (%rcx),%zmm28"); | ||
526 | asm volatile("vbroadcasti64x4 (%rcx),%zmm26"); | ||
527 | |||
528 | /* AVX-512: Op code 0f 38 64 */ | ||
529 | |||
530 | asm volatile("vpblendmd %zmm26,%zmm27,%zmm28"); | ||
531 | asm volatile("vpblendmq %zmm26,%zmm27,%zmm28"); | ||
532 | |||
533 | /* AVX-512: Op code 0f 38 65 */ | ||
534 | |||
535 | asm volatile("vblendmps %zmm24,%zmm25,%zmm26"); | ||
536 | asm volatile("vblendmpd %zmm26,%zmm27,%zmm28"); | ||
537 | |||
538 | /* AVX-512: Op code 0f 38 66 */ | ||
539 | |||
540 | asm volatile("vpblendmb %zmm26,%zmm27,%zmm28"); | ||
541 | asm volatile("vpblendmw %zmm26,%zmm27,%zmm28"); | ||
542 | |||
543 | /* AVX-512: Op code 0f 38 75 */ | ||
544 | |||
545 | asm volatile("vpermi2b %zmm24,%zmm25,%zmm26"); | ||
546 | asm volatile("vpermi2w %zmm26,%zmm27,%zmm28"); | ||
547 | |||
548 | /* AVX-512: Op code 0f 38 76 */ | ||
549 | |||
550 | asm volatile("vpermi2d %zmm26,%zmm27,%zmm28"); | ||
551 | asm volatile("vpermi2q %zmm26,%zmm27,%zmm28"); | ||
552 | |||
553 | /* AVX-512: Op code 0f 38 77 */ | ||
554 | |||
555 | asm volatile("vpermi2ps %zmm26,%zmm27,%zmm28"); | ||
556 | asm volatile("vpermi2pd %zmm26,%zmm27,%zmm28"); | ||
557 | |||
558 | /* AVX-512: Op code 0f 38 7a */ | ||
559 | |||
560 | asm volatile("vpbroadcastb %eax,%xmm30"); | ||
561 | |||
562 | /* AVX-512: Op code 0f 38 7b */ | ||
563 | |||
564 | asm volatile("vpbroadcastw %eax,%xmm30"); | ||
565 | |||
566 | /* AVX-512: Op code 0f 38 7c */ | ||
567 | |||
568 | asm volatile("vpbroadcastd %eax,%xmm30"); | ||
569 | asm volatile("vpbroadcastq %rax,%zmm30"); | ||
570 | |||
571 | /* AVX-512: Op code 0f 38 7d */ | ||
572 | |||
573 | asm volatile("vpermt2b %zmm26,%zmm27,%zmm28"); | ||
574 | asm volatile("vpermt2w %zmm26,%zmm27,%zmm28"); | ||
575 | |||
576 | /* AVX-512: Op code 0f 38 7e */ | ||
577 | |||
578 | asm volatile("vpermt2d %zmm26,%zmm27,%zmm28"); | ||
579 | asm volatile("vpermt2q %zmm26,%zmm27,%zmm28"); | ||
580 | |||
581 | /* AVX-512: Op code 0f 38 7f */ | ||
582 | |||
583 | asm volatile("vpermt2ps %zmm26,%zmm27,%zmm28"); | ||
584 | asm volatile("vpermt2pd %zmm26,%zmm27,%zmm28"); | ||
585 | |||
586 | /* AVX-512: Op code 0f 38 83 */ | ||
587 | |||
588 | asm volatile("vpmultishiftqb %zmm26,%zmm27,%zmm28"); | ||
589 | |||
590 | /* AVX-512: Op code 0f 38 88 */ | ||
591 | |||
592 | asm volatile("vexpandps (%rcx),%zmm26"); | ||
593 | asm volatile("vexpandpd (%rcx),%zmm28"); | ||
594 | |||
595 | /* AVX-512: Op code 0f 38 89 */ | ||
596 | |||
597 | asm volatile("vpexpandd (%rcx),%zmm28"); | ||
598 | asm volatile("vpexpandq (%rcx),%zmm26"); | ||
599 | |||
600 | /* AVX-512: Op code 0f 38 8a */ | ||
601 | |||
602 | asm volatile("vcompressps %zmm28,(%rcx)"); | ||
603 | asm volatile("vcompresspd %zmm28,(%rcx)"); | ||
604 | |||
605 | /* AVX-512: Op code 0f 38 8b */ | ||
606 | |||
607 | asm volatile("vpcompressd %zmm28,(%rcx)"); | ||
608 | asm volatile("vpcompressq %zmm26,(%rcx)"); | ||
609 | |||
610 | /* AVX-512: Op code 0f 38 8d */ | ||
611 | |||
612 | asm volatile("vpermb %zmm26,%zmm27,%zmm28"); | ||
613 | asm volatile("vpermw %zmm26,%zmm27,%zmm28"); | ||
614 | |||
615 | /* AVX-512: Op code 0f 38 90 */ | ||
616 | |||
617 | asm volatile("vpgatherdd %xmm2,0x02(%rbp,%xmm7,2),%xmm1"); | ||
618 | asm volatile("vpgatherdq %xmm2,0x04(%rbp,%xmm7,2),%xmm1"); | ||
619 | asm volatile("vpgatherdd 0x7b(%rbp,%zmm27,8),%zmm26{%k1}"); | ||
620 | asm volatile("vpgatherdq 0x7b(%rbp,%ymm27,8),%zmm26{%k1}"); | ||
621 | |||
622 | /* AVX-512: Op code 0f 38 91 */ | ||
623 | |||
624 | asm volatile("vpgatherqd %xmm2,0x02(%rbp,%xmm7,2),%xmm1"); | ||
625 | asm volatile("vpgatherqq %xmm2,0x02(%rbp,%xmm7,2),%xmm1"); | ||
626 | asm volatile("vpgatherqd 0x7b(%rbp,%zmm27,8),%ymm26{%k1}"); | ||
627 | asm volatile("vpgatherqq 0x7b(%rbp,%zmm27,8),%zmm26{%k1}"); | ||
628 | |||
629 | /* AVX-512: Op code 0f 38 a0 */ | ||
630 | |||
631 | asm volatile("vpscatterdd %zmm28,0x7b(%rbp,%zmm29,8){%k1}"); | ||
632 | asm volatile("vpscatterdq %zmm26,0x7b(%rbp,%ymm27,8){%k1}"); | ||
633 | |||
634 | /* AVX-512: Op code 0f 38 a1 */ | ||
635 | |||
636 | asm volatile("vpscatterqd %ymm6,0x7b(%rbp,%zmm29,8){%k1}"); | ||
637 | asm volatile("vpscatterqq %ymm6,0x7b(%rbp,%ymm27,8){%k1}"); | ||
638 | |||
639 | /* AVX-512: Op code 0f 38 a2 */ | ||
640 | |||
641 | asm volatile("vscatterdps %zmm28,0x7b(%rbp,%zmm29,8){%k1}"); | ||
642 | asm volatile("vscatterdpd %zmm28,0x7b(%rbp,%ymm27,8){%k1}"); | ||
643 | |||
644 | /* AVX-512: Op code 0f 38 a3 */ | ||
645 | |||
646 | asm volatile("vscatterqps %ymm6,0x7b(%rbp,%zmm29,8){%k1}"); | ||
647 | asm volatile("vscatterqpd %zmm28,0x7b(%rbp,%zmm29,8){%k1}"); | ||
648 | |||
649 | /* AVX-512: Op code 0f 38 b4 */ | ||
650 | |||
651 | asm volatile("vpmadd52luq %zmm26,%zmm27,%zmm28"); | ||
652 | |||
653 | /* AVX-512: Op code 0f 38 b5 */ | ||
654 | |||
655 | asm volatile("vpmadd52huq %zmm26,%zmm27,%zmm28"); | ||
656 | |||
657 | /* AVX-512: Op code 0f 38 c4 */ | ||
658 | |||
659 | asm volatile("vpconflictd %zmm26,%zmm27"); | ||
660 | asm volatile("vpconflictq %zmm26,%zmm27"); | ||
661 | |||
662 | /* AVX-512: Op code 0f 38 c8 */ | ||
663 | |||
664 | asm volatile("vexp2ps %zmm29,%zmm30"); | ||
665 | asm volatile("vexp2pd %zmm26,%zmm27"); | ||
666 | |||
667 | /* AVX-512: Op code 0f 38 ca */ | ||
668 | |||
669 | asm volatile("vrcp28ps %zmm29,%zmm30"); | ||
670 | asm volatile("vrcp28pd %zmm26,%zmm27"); | ||
671 | |||
672 | /* AVX-512: Op code 0f 38 cb */ | ||
673 | |||
674 | asm volatile("vrcp28ss %xmm28,%xmm29,%xmm30{%k7}"); | ||
675 | asm volatile("vrcp28sd %xmm25,%xmm26,%xmm27{%k7}"); | ||
676 | |||
677 | /* AVX-512: Op code 0f 38 cc */ | ||
678 | |||
679 | asm volatile("vrsqrt28ps %zmm29,%zmm30"); | ||
680 | asm volatile("vrsqrt28pd %zmm26,%zmm27"); | ||
681 | |||
682 | /* AVX-512: Op code 0f 38 cd */ | ||
683 | |||
684 | asm volatile("vrsqrt28ss %xmm28,%xmm29,%xmm30{%k7}"); | ||
685 | asm volatile("vrsqrt28sd %xmm25,%xmm26,%xmm27{%k7}"); | ||
686 | |||
687 | /* AVX-512: Op code 0f 3a 03 */ | ||
688 | |||
689 | asm volatile("valignd $0x12,%zmm28,%zmm29,%zmm30"); | ||
690 | asm volatile("valignq $0x12,%zmm25,%zmm26,%zmm27"); | ||
691 | |||
692 | /* AVX-512: Op code 0f 3a 08 */ | ||
693 | |||
694 | asm volatile("vroundps $0x5,%ymm6,%ymm2"); | ||
695 | asm volatile("vrndscaleps $0x12,%zmm25,%zmm26"); | ||
696 | |||
697 | /* AVX-512: Op code 0f 3a 09 */ | ||
698 | |||
699 | asm volatile("vroundpd $0x5,%ymm6,%ymm2"); | ||
700 | asm volatile("vrndscalepd $0x12,%zmm25,%zmm26"); | ||
701 | |||
702 | /* AVX-512: Op code 0f 3a 1a */ | ||
703 | |||
704 | asm volatile("vroundss $0x5,%xmm4,%xmm6,%xmm2"); | ||
705 | asm volatile("vrndscaless $0x12,%xmm24,%xmm25,%xmm26{%k7}"); | ||
706 | |||
707 | /* AVX-512: Op code 0f 3a 0b */ | ||
708 | |||
709 | asm volatile("vroundsd $0x5,%xmm4,%xmm6,%xmm2"); | ||
710 | asm volatile("vrndscalesd $0x12,%xmm24,%xmm25,%xmm26{%k7}"); | ||
711 | |||
712 | /* AVX-512: Op code 0f 3a 18 */ | ||
713 | |||
714 | asm volatile("vinsertf128 $0x5,%xmm4,%ymm4,%ymm6"); | ||
715 | asm volatile("vinsertf32x4 $0x12,%xmm24,%zmm25,%zmm26{%k7}"); | ||
716 | asm volatile("vinsertf64x2 $0x12,%xmm24,%zmm25,%zmm26{%k7}"); | ||
717 | |||
718 | /* AVX-512: Op code 0f 3a 19 */ | ||
719 | |||
720 | asm volatile("vextractf128 $0x5,%ymm4,%xmm4"); | ||
721 | asm volatile("vextractf32x4 $0x12,%zmm25,%xmm26{%k7}"); | ||
722 | asm volatile("vextractf64x2 $0x12,%zmm25,%xmm26{%k7}"); | ||
723 | |||
724 | /* AVX-512: Op code 0f 3a 1a */ | ||
725 | |||
726 | asm volatile("vinsertf32x8 $0x12,%ymm25,%zmm26,%zmm27{%k7}"); | ||
727 | asm volatile("vinsertf64x4 $0x12,%ymm28,%zmm29,%zmm30{%k7}"); | ||
728 | |||
729 | /* AVX-512: Op code 0f 3a 1b */ | ||
730 | |||
731 | asm volatile("vextractf32x8 $0x12,%zmm29,%ymm30{%k7}"); | ||
732 | asm volatile("vextractf64x4 $0x12,%zmm26,%ymm27{%k7}"); | ||
733 | |||
734 | /* AVX-512: Op code 0f 3a 1e */ | ||
735 | |||
736 | asm volatile("vpcmpud $0x12,%zmm29,%zmm30,%k5"); | ||
737 | asm volatile("vpcmpuq $0x12,%zmm26,%zmm27,%k5"); | ||
738 | |||
739 | /* AVX-512: Op code 0f 3a 1f */ | ||
740 | |||
741 | asm volatile("vpcmpd $0x12,%zmm29,%zmm30,%k5"); | ||
742 | asm volatile("vpcmpq $0x12,%zmm26,%zmm27,%k5"); | ||
743 | |||
744 | /* AVX-512: Op code 0f 3a 23 */ | ||
745 | |||
746 | asm volatile("vshuff32x4 $0x12,%zmm28,%zmm29,%zmm30"); | ||
747 | asm volatile("vshuff64x2 $0x12,%zmm25,%zmm26,%zmm27"); | ||
748 | |||
749 | /* AVX-512: Op code 0f 3a 25 */ | ||
750 | |||
751 | asm volatile("vpternlogd $0x12,%zmm28,%zmm29,%zmm30"); | ||
752 | asm volatile("vpternlogq $0x12,%zmm28,%zmm29,%zmm30"); | ||
753 | |||
754 | /* AVX-512: Op code 0f 3a 26 */ | ||
755 | |||
756 | asm volatile("vgetmantps $0x12,%zmm26,%zmm27"); | ||
757 | asm volatile("vgetmantpd $0x12,%zmm29,%zmm30"); | ||
758 | |||
759 | /* AVX-512: Op code 0f 3a 27 */ | ||
760 | |||
761 | asm volatile("vgetmantss $0x12,%xmm25,%xmm26,%xmm27{%k7}"); | ||
762 | asm volatile("vgetmantsd $0x12,%xmm28,%xmm29,%xmm30{%k7}"); | ||
763 | |||
764 | /* AVX-512: Op code 0f 3a 38 */ | ||
765 | |||
766 | asm volatile("vinserti128 $0x5,%xmm4,%ymm4,%ymm6"); | ||
767 | asm volatile("vinserti32x4 $0x12,%xmm24,%zmm25,%zmm26{%k7}"); | ||
768 | asm volatile("vinserti64x2 $0x12,%xmm24,%zmm25,%zmm26{%k7}"); | ||
769 | |||
770 | /* AVX-512: Op code 0f 3a 39 */ | ||
771 | |||
772 | asm volatile("vextracti128 $0x5,%ymm4,%xmm6"); | ||
773 | asm volatile("vextracti32x4 $0x12,%zmm25,%xmm26{%k7}"); | ||
774 | asm volatile("vextracti64x2 $0x12,%zmm25,%xmm26{%k7}"); | ||
775 | |||
776 | /* AVX-512: Op code 0f 3a 3a */ | ||
777 | |||
778 | asm volatile("vinserti32x8 $0x12,%ymm28,%zmm29,%zmm30{%k7}"); | ||
779 | asm volatile("vinserti64x4 $0x12,%ymm25,%zmm26,%zmm27{%k7}"); | ||
780 | |||
781 | /* AVX-512: Op code 0f 3a 3b */ | ||
782 | |||
783 | asm volatile("vextracti32x8 $0x12,%zmm29,%ymm30{%k7}"); | ||
784 | asm volatile("vextracti64x4 $0x12,%zmm26,%ymm27{%k7}"); | ||
785 | |||
786 | /* AVX-512: Op code 0f 3a 3e */ | ||
787 | |||
788 | asm volatile("vpcmpub $0x12,%zmm29,%zmm30,%k5"); | ||
789 | asm volatile("vpcmpuw $0x12,%zmm26,%zmm27,%k5"); | ||
790 | |||
791 | /* AVX-512: Op code 0f 3a 3f */ | ||
792 | |||
793 | asm volatile("vpcmpb $0x12,%zmm29,%zmm30,%k5"); | ||
794 | asm volatile("vpcmpw $0x12,%zmm26,%zmm27,%k5"); | ||
795 | |||
796 | /* AVX-512: Op code 0f 3a 43 */ | ||
797 | |||
798 | asm volatile("vmpsadbw $0x5,%ymm4,%ymm6,%ymm2"); | ||
799 | asm volatile("vdbpsadbw $0x12,%zmm4,%zmm5,%zmm6"); | ||
800 | |||
801 | /* AVX-512: Op code 0f 3a 43 */ | ||
802 | |||
803 | asm volatile("vshufi32x4 $0x12,%zmm25,%zmm26,%zmm27"); | ||
804 | asm volatile("vshufi64x2 $0x12,%zmm28,%zmm29,%zmm30"); | ||
805 | |||
806 | /* AVX-512: Op code 0f 3a 50 */ | ||
807 | |||
808 | asm volatile("vrangeps $0x12,%zmm25,%zmm26,%zmm27"); | ||
809 | asm volatile("vrangepd $0x12,%zmm28,%zmm29,%zmm30"); | ||
810 | |||
811 | /* AVX-512: Op code 0f 3a 51 */ | ||
812 | |||
813 | asm volatile("vrangess $0x12,%xmm25,%xmm26,%xmm27"); | ||
814 | asm volatile("vrangesd $0x12,%xmm28,%xmm29,%xmm30"); | ||
815 | |||
816 | /* AVX-512: Op code 0f 3a 54 */ | ||
817 | |||
818 | asm volatile("vfixupimmps $0x12,%zmm28,%zmm29,%zmm30"); | ||
819 | asm volatile("vfixupimmpd $0x12,%zmm25,%zmm26,%zmm27"); | ||
820 | |||
821 | /* AVX-512: Op code 0f 3a 55 */ | ||
822 | |||
823 | asm volatile("vfixupimmss $0x12,%xmm28,%xmm29,%xmm30{%k7}"); | ||
824 | asm volatile("vfixupimmsd $0x12,%xmm25,%xmm26,%xmm27{%k7}"); | ||
825 | |||
826 | /* AVX-512: Op code 0f 3a 56 */ | ||
827 | |||
828 | asm volatile("vreduceps $0x12,%zmm26,%zmm27"); | ||
829 | asm volatile("vreducepd $0x12,%zmm29,%zmm30"); | ||
830 | |||
831 | /* AVX-512: Op code 0f 3a 57 */ | ||
832 | |||
833 | asm volatile("vreducess $0x12,%xmm25,%xmm26,%xmm27"); | ||
834 | asm volatile("vreducesd $0x12,%xmm28,%xmm29,%xmm30"); | ||
835 | |||
836 | /* AVX-512: Op code 0f 3a 66 */ | ||
837 | |||
838 | asm volatile("vfpclassps $0x12,%zmm27,%k5"); | ||
839 | asm volatile("vfpclasspd $0x12,%zmm30,%k5"); | ||
840 | |||
841 | /* AVX-512: Op code 0f 3a 67 */ | ||
842 | |||
843 | asm volatile("vfpclassss $0x12,%xmm27,%k5"); | ||
844 | asm volatile("vfpclasssd $0x12,%xmm30,%k5"); | ||
845 | |||
846 | /* AVX-512: Op code 0f 72 (Grp13) */ | ||
847 | |||
848 | asm volatile("vprord $0x12,%zmm25,%zmm26"); | ||
849 | asm volatile("vprorq $0x12,%zmm25,%zmm26"); | ||
850 | asm volatile("vprold $0x12,%zmm29,%zmm30"); | ||
851 | asm volatile("vprolq $0x12,%zmm29,%zmm30"); | ||
852 | asm volatile("psrad $0x2,%mm6"); | ||
853 | asm volatile("vpsrad $0x5,%ymm6,%ymm2"); | ||
854 | asm volatile("vpsrad $0x5,%zmm26,%zmm22"); | ||
855 | asm volatile("vpsraq $0x5,%zmm26,%zmm22"); | ||
856 | |||
857 | /* AVX-512: Op code 0f 38 c6 (Grp18) */ | ||
858 | |||
859 | asm volatile("vgatherpf0dps 0x7b(%r14,%zmm31,8){%k1}"); | ||
860 | asm volatile("vgatherpf0dpd 0x7b(%r14,%ymm31,8){%k1}"); | ||
861 | asm volatile("vgatherpf1dps 0x7b(%r14,%zmm31,8){%k1}"); | ||
862 | asm volatile("vgatherpf1dpd 0x7b(%r14,%ymm31,8){%k1}"); | ||
863 | asm volatile("vscatterpf0dps 0x7b(%r14,%zmm31,8){%k1}"); | ||
864 | asm volatile("vscatterpf0dpd 0x7b(%r14,%ymm31,8){%k1}"); | ||
865 | asm volatile("vscatterpf1dps 0x7b(%r14,%zmm31,8){%k1}"); | ||
866 | asm volatile("vscatterpf1dpd 0x7b(%r14,%ymm31,8){%k1}"); | ||
867 | |||
868 | /* AVX-512: Op code 0f 38 c7 (Grp19) */ | ||
869 | |||
870 | asm volatile("vgatherpf0qps 0x7b(%r14,%zmm31,8){%k1}"); | ||
871 | asm volatile("vgatherpf0qpd 0x7b(%r14,%zmm31,8){%k1}"); | ||
872 | asm volatile("vgatherpf1qps 0x7b(%r14,%zmm31,8){%k1}"); | ||
873 | asm volatile("vgatherpf1qpd 0x7b(%r14,%zmm31,8){%k1}"); | ||
874 | asm volatile("vscatterpf0qps 0x7b(%r14,%zmm31,8){%k1}"); | ||
875 | asm volatile("vscatterpf0qpd 0x7b(%r14,%zmm31,8){%k1}"); | ||
876 | asm volatile("vscatterpf1qps 0x7b(%r14,%zmm31,8){%k1}"); | ||
877 | asm volatile("vscatterpf1qpd 0x7b(%r14,%zmm31,8){%k1}"); | ||
878 | |||
879 | /* AVX-512: Examples */ | ||
880 | |||
881 | asm volatile("vaddpd %zmm28,%zmm29,%zmm30"); | ||
882 | asm volatile("vaddpd %zmm28,%zmm29,%zmm30{%k7}"); | ||
883 | asm volatile("vaddpd %zmm28,%zmm29,%zmm30{%k7}{z}"); | ||
884 | asm volatile("vaddpd {rn-sae},%zmm28,%zmm29,%zmm30"); | ||
885 | asm volatile("vaddpd {ru-sae},%zmm28,%zmm29,%zmm30"); | ||
886 | asm volatile("vaddpd {rd-sae},%zmm28,%zmm29,%zmm30"); | ||
887 | asm volatile("vaddpd {rz-sae},%zmm28,%zmm29,%zmm30"); | ||
888 | asm volatile("vaddpd (%rcx),%zmm29,%zmm30"); | ||
889 | asm volatile("vaddpd 0x123(%rax,%r14,8),%zmm29,%zmm30"); | ||
890 | asm volatile("vaddpd (%rcx){1to8},%zmm29,%zmm30"); | ||
891 | asm volatile("vaddpd 0x1fc0(%rdx),%zmm29,%zmm30"); | ||
892 | asm volatile("vaddpd 0x3f8(%rdx){1to8},%zmm29,%zmm30"); | ||
893 | asm volatile("vcmpeq_uqps 0x1fc(%rdx){1to16},%zmm30,%k5"); | ||
894 | asm volatile("vcmpltsd 0x123(%rax,%r14,8),%xmm29,%k5{%k7}"); | ||
895 | asm volatile("vcmplesd {sae},%xmm28,%xmm29,%k5{%k7}"); | ||
896 | asm volatile("vgetmantss $0x5b,0x123(%rax,%r14,8),%xmm29,%xmm30{%k7}"); | ||
897 | |||
24 | /* bndmk m64, bnd */ | 898 | /* bndmk m64, bnd */ |
25 | 899 | ||
26 | asm volatile("bndmk (%rax), %bnd0"); | 900 | asm volatile("bndmk (%rax), %bnd0"); |
@@ -471,6 +1345,921 @@ int main(void) | |||
471 | 1345 | ||
472 | #else /* #ifdef __x86_64__ */ | 1346 | #else /* #ifdef __x86_64__ */ |
473 | 1347 | ||
1348 | /* bound r32, mem (same op code as EVEX prefix) */ | ||
1349 | |||
1350 | asm volatile("bound %eax, 0x12345678(%ecx)"); | ||
1351 | asm volatile("bound %ecx, 0x12345678(%eax)"); | ||
1352 | asm volatile("bound %edx, 0x12345678(%eax)"); | ||
1353 | asm volatile("bound %ebx, 0x12345678(%eax)"); | ||
1354 | asm volatile("bound %esp, 0x12345678(%eax)"); | ||
1355 | asm volatile("bound %ebp, 0x12345678(%eax)"); | ||
1356 | asm volatile("bound %esi, 0x12345678(%eax)"); | ||
1357 | asm volatile("bound %edi, 0x12345678(%eax)"); | ||
1358 | asm volatile("bound %ecx, (%eax)"); | ||
1359 | asm volatile("bound %eax, (0x12345678)"); | ||
1360 | asm volatile("bound %edx, (%ecx,%eax,1)"); | ||
1361 | asm volatile("bound %edx, 0x12345678(,%eax,1)"); | ||
1362 | asm volatile("bound %edx, (%eax,%ecx,1)"); | ||
1363 | asm volatile("bound %edx, (%eax,%ecx,8)"); | ||
1364 | asm volatile("bound %edx, 0x12(%eax)"); | ||
1365 | asm volatile("bound %edx, 0x12(%ebp)"); | ||
1366 | asm volatile("bound %edx, 0x12(%ecx,%eax,1)"); | ||
1367 | asm volatile("bound %edx, 0x12(%ebp,%eax,1)"); | ||
1368 | asm volatile("bound %edx, 0x12(%eax,%ecx,1)"); | ||
1369 | asm volatile("bound %edx, 0x12(%eax,%ecx,8)"); | ||
1370 | asm volatile("bound %edx, 0x12345678(%eax)"); | ||
1371 | asm volatile("bound %edx, 0x12345678(%ebp)"); | ||
1372 | asm volatile("bound %edx, 0x12345678(%ecx,%eax,1)"); | ||
1373 | asm volatile("bound %edx, 0x12345678(%ebp,%eax,1)"); | ||
1374 | asm volatile("bound %edx, 0x12345678(%eax,%ecx,1)"); | ||
1375 | asm volatile("bound %edx, 0x12345678(%eax,%ecx,8)"); | ||
1376 | |||
1377 | /* bound r16, mem (same op code as EVEX prefix) */ | ||
1378 | |||
1379 | asm volatile("bound %ax, 0x12345678(%ecx)"); | ||
1380 | asm volatile("bound %cx, 0x12345678(%eax)"); | ||
1381 | asm volatile("bound %dx, 0x12345678(%eax)"); | ||
1382 | asm volatile("bound %bx, 0x12345678(%eax)"); | ||
1383 | asm volatile("bound %sp, 0x12345678(%eax)"); | ||
1384 | asm volatile("bound %bp, 0x12345678(%eax)"); | ||
1385 | asm volatile("bound %si, 0x12345678(%eax)"); | ||
1386 | asm volatile("bound %di, 0x12345678(%eax)"); | ||
1387 | asm volatile("bound %cx, (%eax)"); | ||
1388 | asm volatile("bound %ax, (0x12345678)"); | ||
1389 | asm volatile("bound %dx, (%ecx,%eax,1)"); | ||
1390 | asm volatile("bound %dx, 0x12345678(,%eax,1)"); | ||
1391 | asm volatile("bound %dx, (%eax,%ecx,1)"); | ||
1392 | asm volatile("bound %dx, (%eax,%ecx,8)"); | ||
1393 | asm volatile("bound %dx, 0x12(%eax)"); | ||
1394 | asm volatile("bound %dx, 0x12(%ebp)"); | ||
1395 | asm volatile("bound %dx, 0x12(%ecx,%eax,1)"); | ||
1396 | asm volatile("bound %dx, 0x12(%ebp,%eax,1)"); | ||
1397 | asm volatile("bound %dx, 0x12(%eax,%ecx,1)"); | ||
1398 | asm volatile("bound %dx, 0x12(%eax,%ecx,8)"); | ||
1399 | asm volatile("bound %dx, 0x12345678(%eax)"); | ||
1400 | asm volatile("bound %dx, 0x12345678(%ebp)"); | ||
1401 | asm volatile("bound %dx, 0x12345678(%ecx,%eax,1)"); | ||
1402 | asm volatile("bound %dx, 0x12345678(%ebp,%eax,1)"); | ||
1403 | asm volatile("bound %dx, 0x12345678(%eax,%ecx,1)"); | ||
1404 | asm volatile("bound %dx, 0x12345678(%eax,%ecx,8)"); | ||
1405 | |||
1406 | /* AVX-512: Instructions with the same op codes as Mask Instructions */ | ||
1407 | |||
1408 | asm volatile("cmovno %eax,%ebx"); | ||
1409 | asm volatile("cmovno 0x12345678(%eax),%ecx"); | ||
1410 | asm volatile("cmovno 0x12345678(%eax),%cx"); | ||
1411 | |||
1412 | asm volatile("cmove %eax,%ebx"); | ||
1413 | asm volatile("cmove 0x12345678(%eax),%ecx"); | ||
1414 | asm volatile("cmove 0x12345678(%eax),%cx"); | ||
1415 | |||
1416 | asm volatile("seto 0x12345678(%eax)"); | ||
1417 | asm volatile("setno 0x12345678(%eax)"); | ||
1418 | asm volatile("setb 0x12345678(%eax)"); | ||
1419 | asm volatile("setc 0x12345678(%eax)"); | ||
1420 | asm volatile("setnae 0x12345678(%eax)"); | ||
1421 | asm volatile("setae 0x12345678(%eax)"); | ||
1422 | asm volatile("setnb 0x12345678(%eax)"); | ||
1423 | asm volatile("setnc 0x12345678(%eax)"); | ||
1424 | asm volatile("sets 0x12345678(%eax)"); | ||
1425 | asm volatile("setns 0x12345678(%eax)"); | ||
1426 | |||
1427 | /* AVX-512: Mask Instructions */ | ||
1428 | |||
1429 | asm volatile("kandw %k7,%k6,%k5"); | ||
1430 | asm volatile("kandq %k7,%k6,%k5"); | ||
1431 | asm volatile("kandb %k7,%k6,%k5"); | ||
1432 | asm volatile("kandd %k7,%k6,%k5"); | ||
1433 | |||
1434 | asm volatile("kandnw %k7,%k6,%k5"); | ||
1435 | asm volatile("kandnq %k7,%k6,%k5"); | ||
1436 | asm volatile("kandnb %k7,%k6,%k5"); | ||
1437 | asm volatile("kandnd %k7,%k6,%k5"); | ||
1438 | |||
1439 | asm volatile("knotw %k7,%k6"); | ||
1440 | asm volatile("knotq %k7,%k6"); | ||
1441 | asm volatile("knotb %k7,%k6"); | ||
1442 | asm volatile("knotd %k7,%k6"); | ||
1443 | |||
1444 | asm volatile("korw %k7,%k6,%k5"); | ||
1445 | asm volatile("korq %k7,%k6,%k5"); | ||
1446 | asm volatile("korb %k7,%k6,%k5"); | ||
1447 | asm volatile("kord %k7,%k6,%k5"); | ||
1448 | |||
1449 | asm volatile("kxnorw %k7,%k6,%k5"); | ||
1450 | asm volatile("kxnorq %k7,%k6,%k5"); | ||
1451 | asm volatile("kxnorb %k7,%k6,%k5"); | ||
1452 | asm volatile("kxnord %k7,%k6,%k5"); | ||
1453 | |||
1454 | asm volatile("kxorw %k7,%k6,%k5"); | ||
1455 | asm volatile("kxorq %k7,%k6,%k5"); | ||
1456 | asm volatile("kxorb %k7,%k6,%k5"); | ||
1457 | asm volatile("kxord %k7,%k6,%k5"); | ||
1458 | |||
1459 | asm volatile("kaddw %k7,%k6,%k5"); | ||
1460 | asm volatile("kaddq %k7,%k6,%k5"); | ||
1461 | asm volatile("kaddb %k7,%k6,%k5"); | ||
1462 | asm volatile("kaddd %k7,%k6,%k5"); | ||
1463 | |||
1464 | asm volatile("kunpckbw %k7,%k6,%k5"); | ||
1465 | asm volatile("kunpckwd %k7,%k6,%k5"); | ||
1466 | asm volatile("kunpckdq %k7,%k6,%k5"); | ||
1467 | |||
1468 | asm volatile("kmovw %k6,%k5"); | ||
1469 | asm volatile("kmovw (%ecx),%k5"); | ||
1470 | asm volatile("kmovw 0x123(%eax,%ecx,8),%k5"); | ||
1471 | asm volatile("kmovw %k5,(%ecx)"); | ||
1472 | asm volatile("kmovw %k5,0x123(%eax,%ecx,8)"); | ||
1473 | asm volatile("kmovw %eax,%k5"); | ||
1474 | asm volatile("kmovw %ebp,%k5"); | ||
1475 | asm volatile("kmovw %k5,%eax"); | ||
1476 | asm volatile("kmovw %k5,%ebp"); | ||
1477 | |||
1478 | asm volatile("kmovq %k6,%k5"); | ||
1479 | asm volatile("kmovq (%ecx),%k5"); | ||
1480 | asm volatile("kmovq 0x123(%eax,%ecx,8),%k5"); | ||
1481 | asm volatile("kmovq %k5,(%ecx)"); | ||
1482 | asm volatile("kmovq %k5,0x123(%eax,%ecx,8)"); | ||
1483 | |||
1484 | asm volatile("kmovb %k6,%k5"); | ||
1485 | asm volatile("kmovb (%ecx),%k5"); | ||
1486 | asm volatile("kmovb 0x123(%eax,%ecx,8),%k5"); | ||
1487 | asm volatile("kmovb %k5,(%ecx)"); | ||
1488 | asm volatile("kmovb %k5,0x123(%eax,%ecx,8)"); | ||
1489 | asm volatile("kmovb %eax,%k5"); | ||
1490 | asm volatile("kmovb %ebp,%k5"); | ||
1491 | asm volatile("kmovb %k5,%eax"); | ||
1492 | asm volatile("kmovb %k5,%ebp"); | ||
1493 | |||
1494 | asm volatile("kmovd %k6,%k5"); | ||
1495 | asm volatile("kmovd (%ecx),%k5"); | ||
1496 | asm volatile("kmovd 0x123(%eax,%ecx,8),%k5"); | ||
1497 | asm volatile("kmovd %k5,(%ecx)"); | ||
1498 | asm volatile("kmovd %k5,0x123(%eax,%ecx,8)"); | ||
1499 | asm volatile("kmovd %eax,%k5"); | ||
1500 | asm volatile("kmovd %ebp,%k5"); | ||
1501 | asm volatile("kmovd %k5,%eax"); | ||
1502 | asm volatile("kmovd %k5,%ebp"); | ||
1503 | |||
1504 | asm volatile("kortestw %k6,%k5"); | ||
1505 | asm volatile("kortestq %k6,%k5"); | ||
1506 | asm volatile("kortestb %k6,%k5"); | ||
1507 | asm volatile("kortestd %k6,%k5"); | ||
1508 | |||
1509 | asm volatile("ktestw %k6,%k5"); | ||
1510 | asm volatile("ktestq %k6,%k5"); | ||
1511 | asm volatile("ktestb %k6,%k5"); | ||
1512 | asm volatile("ktestd %k6,%k5"); | ||
1513 | |||
1514 | asm volatile("kshiftrw $0x12,%k6,%k5"); | ||
1515 | asm volatile("kshiftrq $0x5b,%k6,%k5"); | ||
1516 | asm volatile("kshiftlw $0x12,%k6,%k5"); | ||
1517 | asm volatile("kshiftlq $0x5b,%k6,%k5"); | ||
1518 | |||
1519 | /* AVX-512: Op code 0f 5b */ | ||
1520 | asm volatile("vcvtdq2ps %xmm5,%xmm6"); | ||
1521 | asm volatile("vcvtqq2ps %zmm5,%ymm6{%k7}"); | ||
1522 | asm volatile("vcvtps2dq %xmm5,%xmm6"); | ||
1523 | asm volatile("vcvttps2dq %xmm5,%xmm6"); | ||
1524 | |||
1525 | /* AVX-512: Op code 0f 6f */ | ||
1526 | |||
1527 | asm volatile("movq %mm0,%mm4"); | ||
1528 | asm volatile("vmovdqa %ymm4,%ymm6"); | ||
1529 | asm volatile("vmovdqa32 %zmm5,%zmm6"); | ||
1530 | asm volatile("vmovdqa64 %zmm5,%zmm6"); | ||
1531 | asm volatile("vmovdqu %ymm4,%ymm6"); | ||
1532 | asm volatile("vmovdqu32 %zmm5,%zmm6"); | ||
1533 | asm volatile("vmovdqu64 %zmm5,%zmm6"); | ||
1534 | asm volatile("vmovdqu8 %zmm5,%zmm6"); | ||
1535 | asm volatile("vmovdqu16 %zmm5,%zmm6"); | ||
1536 | |||
1537 | /* AVX-512: Op code 0f 78 */ | ||
1538 | |||
1539 | asm volatile("vmread %eax,%ebx"); | ||
1540 | asm volatile("vcvttps2udq %zmm5,%zmm6"); | ||
1541 | asm volatile("vcvttpd2udq %zmm5,%ymm6{%k7}"); | ||
1542 | asm volatile("vcvttsd2usi %xmm6,%eax"); | ||
1543 | asm volatile("vcvttss2usi %xmm6,%eax"); | ||
1544 | asm volatile("vcvttps2uqq %ymm5,%zmm6{%k7}"); | ||
1545 | asm volatile("vcvttpd2uqq %zmm5,%zmm6"); | ||
1546 | |||
1547 | /* AVX-512: Op code 0f 79 */ | ||
1548 | |||
1549 | asm volatile("vmwrite %eax,%ebx"); | ||
1550 | asm volatile("vcvtps2udq %zmm5,%zmm6"); | ||
1551 | asm volatile("vcvtpd2udq %zmm5,%ymm6{%k7}"); | ||
1552 | asm volatile("vcvtsd2usi %xmm6,%eax"); | ||
1553 | asm volatile("vcvtss2usi %xmm6,%eax"); | ||
1554 | asm volatile("vcvtps2uqq %ymm5,%zmm6{%k7}"); | ||
1555 | asm volatile("vcvtpd2uqq %zmm5,%zmm6"); | ||
1556 | |||
1557 | /* AVX-512: Op code 0f 7a */ | ||
1558 | |||
1559 | asm volatile("vcvtudq2pd %ymm5,%zmm6{%k7}"); | ||
1560 | asm volatile("vcvtuqq2pd %zmm5,%zmm6"); | ||
1561 | asm volatile("vcvtudq2ps %zmm5,%zmm6"); | ||
1562 | asm volatile("vcvtuqq2ps %zmm5,%ymm6{%k7}"); | ||
1563 | asm volatile("vcvttps2qq %ymm5,%zmm6{%k7}"); | ||
1564 | asm volatile("vcvttpd2qq %zmm5,%zmm6"); | ||
1565 | |||
1566 | /* AVX-512: Op code 0f 7b */ | ||
1567 | |||
1568 | asm volatile("vcvtusi2sd %eax,%xmm5,%xmm6"); | ||
1569 | asm volatile("vcvtusi2ss %eax,%xmm5,%xmm6"); | ||
1570 | asm volatile("vcvtps2qq %ymm5,%zmm6{%k7}"); | ||
1571 | asm volatile("vcvtpd2qq %zmm5,%zmm6"); | ||
1572 | |||
1573 | /* AVX-512: Op code 0f 7f */ | ||
1574 | |||
1575 | asm volatile("movq.s %mm0,%mm4"); | ||
1576 | asm volatile("vmovdqa.s %ymm5,%ymm6"); | ||
1577 | asm volatile("vmovdqa32.s %zmm5,%zmm6"); | ||
1578 | asm volatile("vmovdqa64.s %zmm5,%zmm6"); | ||
1579 | asm volatile("vmovdqu.s %ymm5,%ymm6"); | ||
1580 | asm volatile("vmovdqu32.s %zmm5,%zmm6"); | ||
1581 | asm volatile("vmovdqu64.s %zmm5,%zmm6"); | ||
1582 | asm volatile("vmovdqu8.s %zmm5,%zmm6"); | ||
1583 | asm volatile("vmovdqu16.s %zmm5,%zmm6"); | ||
1584 | |||
1585 | /* AVX-512: Op code 0f db */ | ||
1586 | |||
1587 | asm volatile("pand %mm1,%mm2"); | ||
1588 | asm volatile("pand %xmm1,%xmm2"); | ||
1589 | asm volatile("vpand %ymm4,%ymm6,%ymm2"); | ||
1590 | asm volatile("vpandd %zmm4,%zmm5,%zmm6"); | ||
1591 | asm volatile("vpandq %zmm4,%zmm5,%zmm6"); | ||
1592 | |||
1593 | /* AVX-512: Op code 0f df */ | ||
1594 | |||
1595 | asm volatile("pandn %mm1,%mm2"); | ||
1596 | asm volatile("pandn %xmm1,%xmm2"); | ||
1597 | asm volatile("vpandn %ymm4,%ymm6,%ymm2"); | ||
1598 | asm volatile("vpandnd %zmm4,%zmm5,%zmm6"); | ||
1599 | asm volatile("vpandnq %zmm4,%zmm5,%zmm6"); | ||
1600 | |||
1601 | /* AVX-512: Op code 0f e6 */ | ||
1602 | |||
1603 | asm volatile("vcvttpd2dq %xmm1,%xmm2"); | ||
1604 | asm volatile("vcvtdq2pd %xmm5,%xmm6"); | ||
1605 | asm volatile("vcvtdq2pd %ymm5,%zmm6{%k7}"); | ||
1606 | asm volatile("vcvtqq2pd %zmm5,%zmm6"); | ||
1607 | asm volatile("vcvtpd2dq %xmm1,%xmm2"); | ||
1608 | |||
1609 | /* AVX-512: Op code 0f eb */ | ||
1610 | |||
1611 | asm volatile("por %mm4,%mm6"); | ||
1612 | asm volatile("vpor %ymm4,%ymm6,%ymm2"); | ||
1613 | asm volatile("vpord %zmm4,%zmm5,%zmm6"); | ||
1614 | asm volatile("vporq %zmm4,%zmm5,%zmm6"); | ||
1615 | |||
1616 | /* AVX-512: Op code 0f ef */ | ||
1617 | |||
1618 | asm volatile("pxor %mm4,%mm6"); | ||
1619 | asm volatile("vpxor %ymm4,%ymm6,%ymm2"); | ||
1620 | asm volatile("vpxord %zmm4,%zmm5,%zmm6"); | ||
1621 | asm volatile("vpxorq %zmm4,%zmm5,%zmm6"); | ||
1622 | |||
1623 | /* AVX-512: Op code 0f 38 10 */ | ||
1624 | |||
1625 | asm volatile("pblendvb %xmm1,%xmm0"); | ||
1626 | asm volatile("vpsrlvw %zmm4,%zmm5,%zmm6"); | ||
1627 | asm volatile("vpmovuswb %zmm5,%ymm6{%k7}"); | ||
1628 | |||
1629 | /* AVX-512: Op code 0f 38 11 */ | ||
1630 | |||
1631 | asm volatile("vpmovusdb %zmm5,%xmm6{%k7}"); | ||
1632 | asm volatile("vpsravw %zmm4,%zmm5,%zmm6"); | ||
1633 | |||
1634 | /* AVX-512: Op code 0f 38 12 */ | ||
1635 | |||
1636 | asm volatile("vpmovusqb %zmm5,%xmm6{%k7}"); | ||
1637 | asm volatile("vpsllvw %zmm4,%zmm5,%zmm6"); | ||
1638 | |||
1639 | /* AVX-512: Op code 0f 38 13 */ | ||
1640 | |||
1641 | asm volatile("vcvtph2ps %xmm3,%ymm5"); | ||
1642 | asm volatile("vcvtph2ps %ymm5,%zmm6{%k7}"); | ||
1643 | asm volatile("vpmovusdw %zmm5,%ymm6{%k7}"); | ||
1644 | |||
1645 | /* AVX-512: Op code 0f 38 14 */ | ||
1646 | |||
1647 | asm volatile("blendvps %xmm1,%xmm0"); | ||
1648 | asm volatile("vpmovusqw %zmm5,%xmm6{%k7}"); | ||
1649 | asm volatile("vprorvd %zmm4,%zmm5,%zmm6"); | ||
1650 | asm volatile("vprorvq %zmm4,%zmm5,%zmm6"); | ||
1651 | |||
1652 | /* AVX-512: Op code 0f 38 15 */ | ||
1653 | |||
1654 | asm volatile("blendvpd %xmm1,%xmm0"); | ||
1655 | asm volatile("vpmovusqd %zmm5,%ymm6{%k7}"); | ||
1656 | asm volatile("vprolvd %zmm4,%zmm5,%zmm6"); | ||
1657 | asm volatile("vprolvq %zmm4,%zmm5,%zmm6"); | ||
1658 | |||
1659 | /* AVX-512: Op code 0f 38 16 */ | ||
1660 | |||
1661 | asm volatile("vpermps %ymm4,%ymm6,%ymm2"); | ||
1662 | asm volatile("vpermps %ymm4,%ymm6,%ymm2{%k7}"); | ||
1663 | asm volatile("vpermpd %ymm4,%ymm6,%ymm2{%k7}"); | ||
1664 | |||
1665 | /* AVX-512: Op code 0f 38 19 */ | ||
1666 | |||
1667 | asm volatile("vbroadcastsd %xmm4,%ymm6"); | ||
1668 | asm volatile("vbroadcastf32x2 %xmm7,%zmm6"); | ||
1669 | |||
1670 | /* AVX-512: Op code 0f 38 1a */ | ||
1671 | |||
1672 | asm volatile("vbroadcastf128 (%ecx),%ymm4"); | ||
1673 | asm volatile("vbroadcastf32x4 (%ecx),%zmm6"); | ||
1674 | asm volatile("vbroadcastf64x2 (%ecx),%zmm6"); | ||
1675 | |||
1676 | /* AVX-512: Op code 0f 38 1b */ | ||
1677 | |||
1678 | asm volatile("vbroadcastf32x8 (%ecx),%zmm6"); | ||
1679 | asm volatile("vbroadcastf64x4 (%ecx),%zmm6"); | ||
1680 | |||
1681 | /* AVX-512: Op code 0f 38 1f */ | ||
1682 | |||
1683 | asm volatile("vpabsq %zmm4,%zmm6"); | ||
1684 | |||
1685 | /* AVX-512: Op code 0f 38 20 */ | ||
1686 | |||
1687 | asm volatile("vpmovsxbw %xmm4,%xmm5"); | ||
1688 | asm volatile("vpmovswb %zmm5,%ymm6{%k7}"); | ||
1689 | |||
1690 | /* AVX-512: Op code 0f 38 21 */ | ||
1691 | |||
1692 | asm volatile("vpmovsxbd %xmm4,%ymm6"); | ||
1693 | asm volatile("vpmovsdb %zmm5,%xmm6{%k7}"); | ||
1694 | |||
1695 | /* AVX-512: Op code 0f 38 22 */ | ||
1696 | |||
1697 | asm volatile("vpmovsxbq %xmm4,%ymm4"); | ||
1698 | asm volatile("vpmovsqb %zmm5,%xmm6{%k7}"); | ||
1699 | |||
1700 | /* AVX-512: Op code 0f 38 23 */ | ||
1701 | |||
1702 | asm volatile("vpmovsxwd %xmm4,%ymm4"); | ||
1703 | asm volatile("vpmovsdw %zmm5,%ymm6{%k7}"); | ||
1704 | |||
1705 | /* AVX-512: Op code 0f 38 24 */ | ||
1706 | |||
1707 | asm volatile("vpmovsxwq %xmm4,%ymm6"); | ||
1708 | asm volatile("vpmovsqw %zmm5,%xmm6{%k7}"); | ||
1709 | |||
1710 | /* AVX-512: Op code 0f 38 25 */ | ||
1711 | |||
1712 | asm volatile("vpmovsxdq %xmm4,%ymm4"); | ||
1713 | asm volatile("vpmovsqd %zmm5,%ymm6{%k7}"); | ||
1714 | |||
1715 | /* AVX-512: Op code 0f 38 26 */ | ||
1716 | |||
1717 | asm volatile("vptestmb %zmm5,%zmm6,%k5"); | ||
1718 | asm volatile("vptestmw %zmm5,%zmm6,%k5"); | ||
1719 | asm volatile("vptestnmb %zmm4,%zmm5,%k5"); | ||
1720 | asm volatile("vptestnmw %zmm4,%zmm5,%k5"); | ||
1721 | |||
1722 | /* AVX-512: Op code 0f 38 27 */ | ||
1723 | |||
1724 | asm volatile("vptestmd %zmm5,%zmm6,%k5"); | ||
1725 | asm volatile("vptestmq %zmm5,%zmm6,%k5"); | ||
1726 | asm volatile("vptestnmd %zmm4,%zmm5,%k5"); | ||
1727 | asm volatile("vptestnmq %zmm4,%zmm5,%k5"); | ||
1728 | |||
1729 | /* AVX-512: Op code 0f 38 28 */ | ||
1730 | |||
1731 | asm volatile("vpmuldq %ymm4,%ymm6,%ymm2"); | ||
1732 | asm volatile("vpmovm2b %k5,%zmm6"); | ||
1733 | asm volatile("vpmovm2w %k5,%zmm6"); | ||
1734 | |||
1735 | /* AVX-512: Op code 0f 38 29 */ | ||
1736 | |||
1737 | asm volatile("vpcmpeqq %ymm4,%ymm6,%ymm2"); | ||
1738 | asm volatile("vpmovb2m %zmm6,%k5"); | ||
1739 | asm volatile("vpmovw2m %zmm6,%k5"); | ||
1740 | |||
1741 | /* AVX-512: Op code 0f 38 2a */ | ||
1742 | |||
1743 | asm volatile("vmovntdqa (%ecx),%ymm4"); | ||
1744 | asm volatile("vpbroadcastmb2q %k6,%zmm1"); | ||
1745 | |||
1746 | /* AVX-512: Op code 0f 38 2c */ | ||
1747 | |||
1748 | asm volatile("vmaskmovps (%ecx),%ymm4,%ymm6"); | ||
1749 | asm volatile("vscalefps %zmm4,%zmm5,%zmm6"); | ||
1750 | asm volatile("vscalefpd %zmm4,%zmm5,%zmm6"); | ||
1751 | |||
1752 | /* AVX-512: Op code 0f 38 2d */ | ||
1753 | |||
1754 | asm volatile("vmaskmovpd (%ecx),%ymm4,%ymm6"); | ||
1755 | asm volatile("vscalefss %xmm4,%xmm5,%xmm6{%k7}"); | ||
1756 | asm volatile("vscalefsd %xmm4,%xmm5,%xmm6{%k7}"); | ||
1757 | |||
1758 | /* AVX-512: Op code 0f 38 30 */ | ||
1759 | |||
1760 | asm volatile("vpmovzxbw %xmm4,%ymm4"); | ||
1761 | asm volatile("vpmovwb %zmm5,%ymm6{%k7}"); | ||
1762 | |||
1763 | /* AVX-512: Op code 0f 38 31 */ | ||
1764 | |||
1765 | asm volatile("vpmovzxbd %xmm4,%ymm6"); | ||
1766 | asm volatile("vpmovdb %zmm5,%xmm6{%k7}"); | ||
1767 | |||
1768 | /* AVX-512: Op code 0f 38 32 */ | ||
1769 | |||
1770 | asm volatile("vpmovzxbq %xmm4,%ymm4"); | ||
1771 | asm volatile("vpmovqb %zmm5,%xmm6{%k7}"); | ||
1772 | |||
1773 | /* AVX-512: Op code 0f 38 33 */ | ||
1774 | |||
1775 | asm volatile("vpmovzxwd %xmm4,%ymm4"); | ||
1776 | asm volatile("vpmovdw %zmm5,%ymm6{%k7}"); | ||
1777 | |||
1778 | /* AVX-512: Op code 0f 38 34 */ | ||
1779 | |||
1780 | asm volatile("vpmovzxwq %xmm4,%ymm6"); | ||
1781 | asm volatile("vpmovqw %zmm5,%xmm6{%k7}"); | ||
1782 | |||
1783 | /* AVX-512: Op code 0f 38 35 */ | ||
1784 | |||
1785 | asm volatile("vpmovzxdq %xmm4,%ymm4"); | ||
1786 | asm volatile("vpmovqd %zmm5,%ymm6{%k7}"); | ||
1787 | |||
1788 | /* AVX-512: Op code 0f 38 36 */ | ||
1789 | |||
1790 | asm volatile("vpermd %ymm4,%ymm6,%ymm2"); | ||
1791 | asm volatile("vpermd %ymm4,%ymm6,%ymm2{%k7}"); | ||
1792 | asm volatile("vpermq %ymm4,%ymm6,%ymm2{%k7}"); | ||
1793 | |||
1794 | /* AVX-512: Op code 0f 38 38 */ | ||
1795 | |||
1796 | asm volatile("vpminsb %ymm4,%ymm6,%ymm2"); | ||
1797 | asm volatile("vpmovm2d %k5,%zmm6"); | ||
1798 | asm volatile("vpmovm2q %k5,%zmm6"); | ||
1799 | |||
1800 | /* AVX-512: Op code 0f 38 39 */ | ||
1801 | |||
1802 | asm volatile("vpminsd %xmm1,%xmm2,%xmm3"); | ||
1803 | asm volatile("vpminsd %zmm4,%zmm5,%zmm6"); | ||
1804 | asm volatile("vpminsq %zmm4,%zmm5,%zmm6"); | ||
1805 | asm volatile("vpmovd2m %zmm6,%k5"); | ||
1806 | asm volatile("vpmovq2m %zmm6,%k5"); | ||
1807 | |||
1808 | /* AVX-512: Op code 0f 38 3a */ | ||
1809 | |||
1810 | asm volatile("vpminuw %ymm4,%ymm6,%ymm2"); | ||
1811 | asm volatile("vpbroadcastmw2d %k6,%zmm6"); | ||
1812 | |||
1813 | /* AVX-512: Op code 0f 38 3b */ | ||
1814 | |||
1815 | asm volatile("vpminud %ymm4,%ymm6,%ymm2"); | ||
1816 | asm volatile("vpminud %zmm4,%zmm5,%zmm6"); | ||
1817 | asm volatile("vpminuq %zmm4,%zmm5,%zmm6"); | ||
1818 | |||
1819 | /* AVX-512: Op code 0f 38 3d */ | ||
1820 | |||
1821 | asm volatile("vpmaxsd %ymm4,%ymm6,%ymm2"); | ||
1822 | asm volatile("vpmaxsd %zmm4,%zmm5,%zmm6"); | ||
1823 | asm volatile("vpmaxsq %zmm4,%zmm5,%zmm6"); | ||
1824 | |||
1825 | /* AVX-512: Op code 0f 38 3f */ | ||
1826 | |||
1827 | asm volatile("vpmaxud %ymm4,%ymm6,%ymm2"); | ||
1828 | asm volatile("vpmaxud %zmm4,%zmm5,%zmm6"); | ||
1829 | asm volatile("vpmaxuq %zmm4,%zmm5,%zmm6"); | ||
1830 | |||
1831 | /* AVX-512: Op code 0f 38 40 */ | ||
1832 | |||
1833 | asm volatile("vpmulld %ymm4,%ymm6,%ymm2"); | ||
1834 | asm volatile("vpmulld %zmm4,%zmm5,%zmm6"); | ||
1835 | asm volatile("vpmullq %zmm4,%zmm5,%zmm6"); | ||
1836 | |||
1837 | /* AVX-512: Op code 0f 38 42 */ | ||
1838 | |||
1839 | asm volatile("vgetexpps %zmm5,%zmm6"); | ||
1840 | asm volatile("vgetexppd %zmm5,%zmm6"); | ||
1841 | |||
1842 | /* AVX-512: Op code 0f 38 43 */ | ||
1843 | |||
1844 | asm volatile("vgetexpss %xmm4,%xmm5,%xmm6{%k7}"); | ||
1845 | asm volatile("vgetexpsd %xmm2,%xmm3,%xmm4{%k7}"); | ||
1846 | |||
1847 | /* AVX-512: Op code 0f 38 44 */ | ||
1848 | |||
1849 | asm volatile("vplzcntd %zmm5,%zmm6"); | ||
1850 | asm volatile("vplzcntq %zmm5,%zmm6"); | ||
1851 | |||
1852 | /* AVX-512: Op code 0f 38 46 */ | ||
1853 | |||
1854 | asm volatile("vpsravd %ymm4,%ymm6,%ymm2"); | ||
1855 | asm volatile("vpsravd %zmm4,%zmm5,%zmm6"); | ||
1856 | asm volatile("vpsravq %zmm4,%zmm5,%zmm6"); | ||
1857 | |||
1858 | /* AVX-512: Op code 0f 38 4c */ | ||
1859 | |||
1860 | asm volatile("vrcp14ps %zmm5,%zmm6"); | ||
1861 | asm volatile("vrcp14pd %zmm5,%zmm6"); | ||
1862 | |||
1863 | /* AVX-512: Op code 0f 38 4d */ | ||
1864 | |||
1865 | asm volatile("vrcp14ss %xmm4,%xmm5,%xmm6{%k7}"); | ||
1866 | asm volatile("vrcp14sd %xmm4,%xmm5,%xmm6{%k7}"); | ||
1867 | |||
1868 | /* AVX-512: Op code 0f 38 4e */ | ||
1869 | |||
1870 | asm volatile("vrsqrt14ps %zmm5,%zmm6"); | ||
1871 | asm volatile("vrsqrt14pd %zmm5,%zmm6"); | ||
1872 | |||
1873 | /* AVX-512: Op code 0f 38 4f */ | ||
1874 | |||
1875 | asm volatile("vrsqrt14ss %xmm4,%xmm5,%xmm6{%k7}"); | ||
1876 | asm volatile("vrsqrt14sd %xmm4,%xmm5,%xmm6{%k7}"); | ||
1877 | |||
1878 | /* AVX-512: Op code 0f 38 59 */ | ||
1879 | |||
1880 | asm volatile("vpbroadcastq %xmm4,%xmm6"); | ||
1881 | asm volatile("vbroadcasti32x2 %xmm7,%zmm6"); | ||
1882 | |||
1883 | /* AVX-512: Op code 0f 38 5a */ | ||
1884 | |||
1885 | asm volatile("vbroadcasti128 (%ecx),%ymm4"); | ||
1886 | asm volatile("vbroadcasti32x4 (%ecx),%zmm6"); | ||
1887 | asm volatile("vbroadcasti64x2 (%ecx),%zmm6"); | ||
1888 | |||
1889 | /* AVX-512: Op code 0f 38 5b */ | ||
1890 | |||
1891 | asm volatile("vbroadcasti32x8 (%ecx),%zmm6"); | ||
1892 | asm volatile("vbroadcasti64x4 (%ecx),%zmm6"); | ||
1893 | |||
1894 | /* AVX-512: Op code 0f 38 64 */ | ||
1895 | |||
1896 | asm volatile("vpblendmd %zmm4,%zmm5,%zmm6"); | ||
1897 | asm volatile("vpblendmq %zmm4,%zmm5,%zmm6"); | ||
1898 | |||
1899 | /* AVX-512: Op code 0f 38 65 */ | ||
1900 | |||
1901 | asm volatile("vblendmps %zmm4,%zmm5,%zmm6"); | ||
1902 | asm volatile("vblendmpd %zmm4,%zmm5,%zmm6"); | ||
1903 | |||
1904 | /* AVX-512: Op code 0f 38 66 */ | ||
1905 | |||
1906 | asm volatile("vpblendmb %zmm4,%zmm5,%zmm6"); | ||
1907 | asm volatile("vpblendmw %zmm4,%zmm5,%zmm6"); | ||
1908 | |||
1909 | /* AVX-512: Op code 0f 38 75 */ | ||
1910 | |||
1911 | asm volatile("vpermi2b %zmm4,%zmm5,%zmm6"); | ||
1912 | asm volatile("vpermi2w %zmm4,%zmm5,%zmm6"); | ||
1913 | |||
1914 | /* AVX-512: Op code 0f 38 76 */ | ||
1915 | |||
1916 | asm volatile("vpermi2d %zmm4,%zmm5,%zmm6"); | ||
1917 | asm volatile("vpermi2q %zmm4,%zmm5,%zmm6"); | ||
1918 | |||
1919 | /* AVX-512: Op code 0f 38 77 */ | ||
1920 | |||
1921 | asm volatile("vpermi2ps %zmm4,%zmm5,%zmm6"); | ||
1922 | asm volatile("vpermi2pd %zmm4,%zmm5,%zmm6"); | ||
1923 | |||
1924 | /* AVX-512: Op code 0f 38 7a */ | ||
1925 | |||
1926 | asm volatile("vpbroadcastb %eax,%xmm3"); | ||
1927 | |||
1928 | /* AVX-512: Op code 0f 38 7b */ | ||
1929 | |||
1930 | asm volatile("vpbroadcastw %eax,%xmm3"); | ||
1931 | |||
1932 | /* AVX-512: Op code 0f 38 7c */ | ||
1933 | |||
1934 | asm volatile("vpbroadcastd %eax,%xmm3"); | ||
1935 | |||
1936 | /* AVX-512: Op code 0f 38 7d */ | ||
1937 | |||
1938 | asm volatile("vpermt2b %zmm4,%zmm5,%zmm6"); | ||
1939 | asm volatile("vpermt2w %zmm4,%zmm5,%zmm6"); | ||
1940 | |||
1941 | /* AVX-512: Op code 0f 38 7e */ | ||
1942 | |||
1943 | asm volatile("vpermt2d %zmm4,%zmm5,%zmm6"); | ||
1944 | asm volatile("vpermt2q %zmm4,%zmm5,%zmm6"); | ||
1945 | |||
1946 | /* AVX-512: Op code 0f 38 7f */ | ||
1947 | |||
1948 | asm volatile("vpermt2ps %zmm4,%zmm5,%zmm6"); | ||
1949 | asm volatile("vpermt2pd %zmm4,%zmm5,%zmm6"); | ||
1950 | |||
1951 | /* AVX-512: Op code 0f 38 83 */ | ||
1952 | |||
1953 | asm volatile("vpmultishiftqb %zmm4,%zmm5,%zmm6"); | ||
1954 | |||
1955 | /* AVX-512: Op code 0f 38 88 */ | ||
1956 | |||
1957 | asm volatile("vexpandps (%ecx),%zmm6"); | ||
1958 | asm volatile("vexpandpd (%ecx),%zmm6"); | ||
1959 | |||
1960 | /* AVX-512: Op code 0f 38 89 */ | ||
1961 | |||
1962 | asm volatile("vpexpandd (%ecx),%zmm6"); | ||
1963 | asm volatile("vpexpandq (%ecx),%zmm6"); | ||
1964 | |||
1965 | /* AVX-512: Op code 0f 38 8a */ | ||
1966 | |||
1967 | asm volatile("vcompressps %zmm6,(%ecx)"); | ||
1968 | asm volatile("vcompresspd %zmm6,(%ecx)"); | ||
1969 | |||
1970 | /* AVX-512: Op code 0f 38 8b */ | ||
1971 | |||
1972 | asm volatile("vpcompressd %zmm6,(%ecx)"); | ||
1973 | asm volatile("vpcompressq %zmm6,(%ecx)"); | ||
1974 | |||
1975 | /* AVX-512: Op code 0f 38 8d */ | ||
1976 | |||
1977 | asm volatile("vpermb %zmm4,%zmm5,%zmm6"); | ||
1978 | asm volatile("vpermw %zmm4,%zmm5,%zmm6"); | ||
1979 | |||
1980 | /* AVX-512: Op code 0f 38 90 */ | ||
1981 | |||
1982 | asm volatile("vpgatherdd %xmm2,0x02(%ebp,%xmm7,2),%xmm1"); | ||
1983 | asm volatile("vpgatherdq %xmm2,0x04(%ebp,%xmm7,2),%xmm1"); | ||
1984 | asm volatile("vpgatherdd 0x7b(%ebp,%zmm7,8),%zmm6{%k1}"); | ||
1985 | asm volatile("vpgatherdq 0x7b(%ebp,%ymm7,8),%zmm6{%k1}"); | ||
1986 | |||
1987 | /* AVX-512: Op code 0f 38 91 */ | ||
1988 | |||
1989 | asm volatile("vpgatherqd %xmm2,0x02(%ebp,%xmm7,2),%xmm1"); | ||
1990 | asm volatile("vpgatherqq %xmm2,0x02(%ebp,%xmm7,2),%xmm1"); | ||
1991 | asm volatile("vpgatherqd 0x7b(%ebp,%zmm7,8),%ymm6{%k1}"); | ||
1992 | asm volatile("vpgatherqq 0x7b(%ebp,%zmm7,8),%zmm6{%k1}"); | ||
1993 | |||
1994 | /* AVX-512: Op code 0f 38 a0 */ | ||
1995 | |||
1996 | asm volatile("vpscatterdd %zmm6,0x7b(%ebp,%zmm7,8){%k1}"); | ||
1997 | asm volatile("vpscatterdq %zmm6,0x7b(%ebp,%ymm7,8){%k1}"); | ||
1998 | |||
1999 | /* AVX-512: Op code 0f 38 a1 */ | ||
2000 | |||
2001 | asm volatile("vpscatterqd %ymm6,0x7b(%ebp,%zmm7,8){%k1}"); | ||
2002 | asm volatile("vpscatterqq %ymm6,0x7b(%ebp,%ymm7,8){%k1}"); | ||
2003 | |||
2004 | /* AVX-512: Op code 0f 38 a2 */ | ||
2005 | |||
2006 | asm volatile("vscatterdps %zmm6,0x7b(%ebp,%zmm7,8){%k1}"); | ||
2007 | asm volatile("vscatterdpd %zmm6,0x7b(%ebp,%ymm7,8){%k1}"); | ||
2008 | |||
2009 | /* AVX-512: Op code 0f 38 a3 */ | ||
2010 | |||
2011 | asm volatile("vscatterqps %ymm6,0x7b(%ebp,%zmm7,8){%k1}"); | ||
2012 | asm volatile("vscatterqpd %zmm6,0x7b(%ebp,%zmm7,8){%k1}"); | ||
2013 | |||
2014 | /* AVX-512: Op code 0f 38 b4 */ | ||
2015 | |||
2016 | asm volatile("vpmadd52luq %zmm4,%zmm5,%zmm6"); | ||
2017 | |||
2018 | /* AVX-512: Op code 0f 38 b5 */ | ||
2019 | |||
2020 | asm volatile("vpmadd52huq %zmm4,%zmm5,%zmm6"); | ||
2021 | |||
2022 | /* AVX-512: Op code 0f 38 c4 */ | ||
2023 | |||
2024 | asm volatile("vpconflictd %zmm5,%zmm6"); | ||
2025 | asm volatile("vpconflictq %zmm5,%zmm6"); | ||
2026 | |||
2027 | /* AVX-512: Op code 0f 38 c8 */ | ||
2028 | |||
2029 | asm volatile("vexp2ps %zmm6,%zmm7"); | ||
2030 | asm volatile("vexp2pd %zmm6,%zmm7"); | ||
2031 | |||
2032 | /* AVX-512: Op code 0f 38 ca */ | ||
2033 | |||
2034 | asm volatile("vrcp28ps %zmm6,%zmm7"); | ||
2035 | asm volatile("vrcp28pd %zmm6,%zmm7"); | ||
2036 | |||
2037 | /* AVX-512: Op code 0f 38 cb */ | ||
2038 | |||
2039 | asm volatile("vrcp28ss %xmm5,%xmm6,%xmm7{%k7}"); | ||
2040 | asm volatile("vrcp28sd %xmm5,%xmm6,%xmm7{%k7}"); | ||
2041 | |||
2042 | /* AVX-512: Op code 0f 38 cc */ | ||
2043 | |||
2044 | asm volatile("vrsqrt28ps %zmm6,%zmm7"); | ||
2045 | asm volatile("vrsqrt28pd %zmm6,%zmm7"); | ||
2046 | |||
2047 | /* AVX-512: Op code 0f 38 cd */ | ||
2048 | |||
2049 | asm volatile("vrsqrt28ss %xmm5,%xmm6,%xmm7{%k7}"); | ||
2050 | asm volatile("vrsqrt28sd %xmm5,%xmm6,%xmm7{%k7}"); | ||
2051 | |||
2052 | /* AVX-512: Op code 0f 3a 03 */ | ||
2053 | |||
2054 | asm volatile("valignd $0x12,%zmm5,%zmm6,%zmm7"); | ||
2055 | asm volatile("valignq $0x12,%zmm5,%zmm6,%zmm7"); | ||
2056 | |||
2057 | /* AVX-512: Op code 0f 3a 08 */ | ||
2058 | |||
2059 | asm volatile("vroundps $0x5,%ymm6,%ymm2"); | ||
2060 | asm volatile("vrndscaleps $0x12,%zmm5,%zmm6"); | ||
2061 | |||
2062 | /* AVX-512: Op code 0f 3a 09 */ | ||
2063 | |||
2064 | asm volatile("vroundpd $0x5,%ymm6,%ymm2"); | ||
2065 | asm volatile("vrndscalepd $0x12,%zmm5,%zmm6"); | ||
2066 | |||
2067 | /* AVX-512: Op code 0f 3a 0a */ | ||
2068 | |||
2069 | asm volatile("vroundss $0x5,%xmm4,%xmm6,%xmm2"); | ||
2070 | asm volatile("vrndscaless $0x12,%xmm4,%xmm5,%xmm6{%k7}"); | ||
2071 | |||
2072 | /* AVX-512: Op code 0f 3a 0b */ | ||
2073 | |||
2074 | asm volatile("vroundsd $0x5,%xmm4,%xmm6,%xmm2"); | ||
2075 | asm volatile("vrndscalesd $0x12,%xmm4,%xmm5,%xmm6{%k7}"); | ||
2076 | |||
2077 | /* AVX-512: Op code 0f 3a 18 */ | ||
2078 | |||
2079 | asm volatile("vinsertf128 $0x5,%xmm4,%ymm4,%ymm6"); | ||
2080 | asm volatile("vinsertf32x4 $0x12,%xmm4,%zmm5,%zmm6{%k7}"); | ||
2081 | asm volatile("vinsertf64x2 $0x12,%xmm4,%zmm5,%zmm6{%k7}"); | ||
2082 | |||
2083 | /* AVX-512: Op code 0f 3a 19 */ | ||
2084 | |||
2085 | asm volatile("vextractf128 $0x5,%ymm4,%xmm4"); | ||
2086 | asm volatile("vextractf32x4 $0x12,%zmm5,%xmm6{%k7}"); | ||
2087 | asm volatile("vextractf64x2 $0x12,%zmm5,%xmm6{%k7}"); | ||
2088 | |||
2089 | /* AVX-512: Op code 0f 3a 1a */ | ||
2090 | |||
2091 | asm volatile("vinsertf32x8 $0x12,%ymm5,%zmm6,%zmm7{%k7}"); | ||
2092 | asm volatile("vinsertf64x4 $0x12,%ymm5,%zmm6,%zmm7{%k7}"); | ||
2093 | |||
2094 | /* AVX-512: Op code 0f 3a 1b */ | ||
2095 | |||
2096 | asm volatile("vextractf32x8 $0x12,%zmm6,%ymm7{%k7}"); | ||
2097 | asm volatile("vextractf64x4 $0x12,%zmm6,%ymm7{%k7}"); | ||
2098 | |||
2099 | /* AVX-512: Op code 0f 3a 1e */ | ||
2100 | |||
2101 | asm volatile("vpcmpud $0x12,%zmm6,%zmm7,%k5"); | ||
2102 | asm volatile("vpcmpuq $0x12,%zmm6,%zmm7,%k5"); | ||
2103 | |||
2104 | /* AVX-512: Op code 0f 3a 1f */ | ||
2105 | |||
2106 | asm volatile("vpcmpd $0x12,%zmm6,%zmm7,%k5"); | ||
2107 | asm volatile("vpcmpq $0x12,%zmm6,%zmm7,%k5"); | ||
2108 | |||
2109 | /* AVX-512: Op code 0f 3a 23 */ | ||
2110 | |||
2111 | asm volatile("vshuff32x4 $0x12,%zmm5,%zmm6,%zmm7"); | ||
2112 | asm volatile("vshuff64x2 $0x12,%zmm5,%zmm6,%zmm7"); | ||
2113 | |||
2114 | /* AVX-512: Op code 0f 3a 25 */ | ||
2115 | |||
2116 | asm volatile("vpternlogd $0x12,%zmm5,%zmm6,%zmm7"); | ||
2117 | asm volatile("vpternlogq $0x12,%zmm5,%zmm6,%zmm7"); | ||
2118 | |||
2119 | /* AVX-512: Op code 0f 3a 26 */ | ||
2120 | |||
2121 | asm volatile("vgetmantps $0x12,%zmm6,%zmm7"); | ||
2122 | asm volatile("vgetmantpd $0x12,%zmm6,%zmm7"); | ||
2123 | |||
2124 | /* AVX-512: Op code 0f 3a 27 */ | ||
2125 | |||
2126 | asm volatile("vgetmantss $0x12,%xmm5,%xmm6,%xmm7{%k7}"); | ||
2127 | asm volatile("vgetmantsd $0x12,%xmm5,%xmm6,%xmm7{%k7}"); | ||
2128 | |||
2129 | /* AVX-512: Op code 0f 3a 38 */ | ||
2130 | |||
2131 | asm volatile("vinserti128 $0x5,%xmm4,%ymm4,%ymm6"); | ||
2132 | asm volatile("vinserti32x4 $0x12,%xmm4,%zmm5,%zmm6{%k7}"); | ||
2133 | asm volatile("vinserti64x2 $0x12,%xmm4,%zmm5,%zmm6{%k7}"); | ||
2134 | |||
2135 | /* AVX-512: Op code 0f 3a 39 */ | ||
2136 | |||
2137 | asm volatile("vextracti128 $0x5,%ymm4,%xmm6"); | ||
2138 | asm volatile("vextracti32x4 $0x12,%zmm5,%xmm6{%k7}"); | ||
2139 | asm volatile("vextracti64x2 $0x12,%zmm5,%xmm6{%k7}"); | ||
2140 | |||
2141 | /* AVX-512: Op code 0f 3a 3a */ | ||
2142 | |||
2143 | asm volatile("vinserti32x8 $0x12,%ymm5,%zmm6,%zmm7{%k7}"); | ||
2144 | asm volatile("vinserti64x4 $0x12,%ymm5,%zmm6,%zmm7{%k7}"); | ||
2145 | |||
2146 | /* AVX-512: Op code 0f 3a 3b */ | ||
2147 | |||
2148 | asm volatile("vextracti32x8 $0x12,%zmm6,%ymm7{%k7}"); | ||
2149 | asm volatile("vextracti64x4 $0x12,%zmm6,%ymm7{%k7}"); | ||
2150 | |||
2151 | /* AVX-512: Op code 0f 3a 3e */ | ||
2152 | |||
2153 | asm volatile("vpcmpub $0x12,%zmm6,%zmm7,%k5"); | ||
2154 | asm volatile("vpcmpuw $0x12,%zmm6,%zmm7,%k5"); | ||
2155 | |||
2156 | /* AVX-512: Op code 0f 3a 3f */ | ||
2157 | |||
2158 | asm volatile("vpcmpb $0x12,%zmm6,%zmm7,%k5"); | ||
2159 | asm volatile("vpcmpw $0x12,%zmm6,%zmm7,%k5"); | ||
2160 | |||
2161 | /* AVX-512: Op code 0f 3a 42 */ | ||
2162 | |||
2163 | asm volatile("vmpsadbw $0x5,%ymm4,%ymm6,%ymm2"); | ||
2164 | asm volatile("vdbpsadbw $0x12,%zmm4,%zmm5,%zmm6"); | ||
2165 | |||
2166 | /* AVX-512: Op code 0f 3a 43 */ | ||
2167 | |||
2168 | asm volatile("vshufi32x4 $0x12,%zmm5,%zmm6,%zmm7"); | ||
2169 | asm volatile("vshufi64x2 $0x12,%zmm5,%zmm6,%zmm7"); | ||
2170 | |||
2171 | /* AVX-512: Op code 0f 3a 50 */ | ||
2172 | |||
2173 | asm volatile("vrangeps $0x12,%zmm5,%zmm6,%zmm7"); | ||
2174 | asm volatile("vrangepd $0x12,%zmm5,%zmm6,%zmm7"); | ||
2175 | |||
2176 | /* AVX-512: Op code 0f 3a 51 */ | ||
2177 | |||
2178 | asm volatile("vrangess $0x12,%xmm5,%xmm6,%xmm7"); | ||
2179 | asm volatile("vrangesd $0x12,%xmm5,%xmm6,%xmm7"); | ||
2180 | |||
2181 | /* AVX-512: Op code 0f 3a 54 */ | ||
2182 | |||
2183 | asm volatile("vfixupimmps $0x12,%zmm5,%zmm6,%zmm7"); | ||
2184 | asm volatile("vfixupimmpd $0x12,%zmm5,%zmm6,%zmm7"); | ||
2185 | |||
2186 | /* AVX-512: Op code 0f 3a 55 */ | ||
2187 | |||
2188 | asm volatile("vfixupimmss $0x12,%xmm5,%xmm6,%xmm7{%k7}"); | ||
2189 | asm volatile("vfixupimmsd $0x12,%xmm5,%xmm6,%xmm7{%k7}"); | ||
2190 | |||
2191 | /* AVX-512: Op code 0f 3a 56 */ | ||
2192 | |||
2193 | asm volatile("vreduceps $0x12,%zmm6,%zmm7"); | ||
2194 | asm volatile("vreducepd $0x12,%zmm6,%zmm7"); | ||
2195 | |||
2196 | /* AVX-512: Op code 0f 3a 57 */ | ||
2197 | |||
2198 | asm volatile("vreducess $0x12,%xmm5,%xmm6,%xmm7"); | ||
2199 | asm volatile("vreducesd $0x12,%xmm5,%xmm6,%xmm7"); | ||
2200 | |||
2201 | /* AVX-512: Op code 0f 3a 66 */ | ||
2202 | |||
2203 | asm volatile("vfpclassps $0x12,%zmm7,%k5"); | ||
2204 | asm volatile("vfpclasspd $0x12,%zmm7,%k5"); | ||
2205 | |||
2206 | /* AVX-512: Op code 0f 3a 67 */ | ||
2207 | |||
2208 | asm volatile("vfpclassss $0x12,%xmm7,%k5"); | ||
2209 | asm volatile("vfpclasssd $0x12,%xmm7,%k5"); | ||
2210 | |||
2211 | /* AVX-512: Op code 0f 72 (Grp13) */ | ||
2212 | |||
2213 | asm volatile("vprord $0x12,%zmm5,%zmm6"); | ||
2214 | asm volatile("vprorq $0x12,%zmm5,%zmm6"); | ||
2215 | asm volatile("vprold $0x12,%zmm5,%zmm6"); | ||
2216 | asm volatile("vprolq $0x12,%zmm5,%zmm6"); | ||
2217 | asm volatile("psrad $0x2,%mm6"); | ||
2218 | asm volatile("vpsrad $0x5,%ymm6,%ymm2"); | ||
2219 | asm volatile("vpsrad $0x5,%zmm6,%zmm2"); | ||
2220 | asm volatile("vpsraq $0x5,%zmm6,%zmm2"); | ||
2221 | |||
2222 | /* AVX-512: Op code 0f 38 c6 (Grp18) */ | ||
2223 | |||
2224 | asm volatile("vgatherpf0dps 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2225 | asm volatile("vgatherpf0dpd 0x7b(%ebp,%ymm7,8){%k1}"); | ||
2226 | asm volatile("vgatherpf1dps 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2227 | asm volatile("vgatherpf1dpd 0x7b(%ebp,%ymm7,8){%k1}"); | ||
2228 | asm volatile("vscatterpf0dps 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2229 | asm volatile("vscatterpf0dpd 0x7b(%ebp,%ymm7,8){%k1}"); | ||
2230 | asm volatile("vscatterpf1dps 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2231 | asm volatile("vscatterpf1dpd 0x7b(%ebp,%ymm7,8){%k1}"); | ||
2232 | |||
2233 | /* AVX-512: Op code 0f 38 c7 (Grp19) */ | ||
2234 | |||
2235 | asm volatile("vgatherpf0qps 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2236 | asm volatile("vgatherpf0qpd 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2237 | asm volatile("vgatherpf1qps 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2238 | asm volatile("vgatherpf1qpd 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2239 | asm volatile("vscatterpf0qps 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2240 | asm volatile("vscatterpf0qpd 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2241 | asm volatile("vscatterpf1qps 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2242 | asm volatile("vscatterpf1qpd 0x7b(%ebp,%zmm7,8){%k1}"); | ||
2243 | |||
2244 | /* AVX-512: Examples */ | ||
2245 | |||
2246 | asm volatile("vaddpd %zmm4,%zmm5,%zmm6"); | ||
2247 | asm volatile("vaddpd %zmm4,%zmm5,%zmm6{%k7}"); | ||
2248 | asm volatile("vaddpd %zmm4,%zmm5,%zmm6{%k7}{z}"); | ||
2249 | asm volatile("vaddpd {rn-sae},%zmm4,%zmm5,%zmm6"); | ||
2250 | asm volatile("vaddpd {ru-sae},%zmm4,%zmm5,%zmm6"); | ||
2251 | asm volatile("vaddpd {rd-sae},%zmm4,%zmm5,%zmm6"); | ||
2252 | asm volatile("vaddpd {rz-sae},%zmm4,%zmm5,%zmm6"); | ||
2253 | asm volatile("vaddpd (%ecx),%zmm5,%zmm6"); | ||
2254 | asm volatile("vaddpd 0x123(%eax,%ecx,8),%zmm5,%zmm6"); | ||
2255 | asm volatile("vaddpd (%ecx){1to8},%zmm5,%zmm6"); | ||
2256 | asm volatile("vaddpd 0x1fc0(%edx),%zmm5,%zmm6"); | ||
2257 | asm volatile("vaddpd 0x3f8(%edx){1to8},%zmm5,%zmm6"); | ||
2258 | asm volatile("vcmpeq_uqps 0x1fc(%edx){1to16},%zmm6,%k5"); | ||
2259 | asm volatile("vcmpltsd 0x123(%eax,%ecx,8),%xmm3,%k5{%k7}"); | ||
2260 | asm volatile("vcmplesd {sae},%xmm4,%xmm5,%k5{%k7}"); | ||
2261 | asm volatile("vgetmantss $0x5b,0x123(%eax,%ecx,8),%xmm4,%xmm5{%k7}"); | ||
2262 | |||
474 | /* bndmk m32, bnd */ | 2263 | /* bndmk m32, bnd */ |
475 | 2264 | ||
476 | asm volatile("bndmk (%eax), %bnd0"); | 2265 | asm volatile("bndmk (%eax), %bnd0"); |
@@ -866,10 +2655,6 @@ int main(void) | |||
866 | 2655 | ||
867 | #endif /* #ifndef __x86_64__ */ | 2656 | #endif /* #ifndef __x86_64__ */ |
868 | 2657 | ||
869 | /* pcommit */ | ||
870 | |||
871 | asm volatile("pcommit"); | ||
872 | |||
873 | /* Following line is a marker for the awk script - do not change */ | 2658 | /* Following line is a marker for the awk script - do not change */ |
874 | asm volatile("rdtsc"); /* Stop here */ | 2659 | asm volatile("rdtsc"); /* Stop here */ |
875 | 2660 | ||
diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index d4aa567a29c4..5c76cc83186a 100644 --- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c | |||
@@ -154,10 +154,6 @@ next_event: | |||
154 | err = 0; | 154 | err = 0; |
155 | 155 | ||
156 | out_err: | 156 | out_err: |
157 | if (evlist) { | 157 | perf_evlist__delete(evlist); |
158 | perf_evlist__disable(evlist); | ||
159 | perf_evlist__delete(evlist); | ||
160 | } | ||
161 | |||
162 | return err; | 158 | return err; |
163 | } | 159 | } |
diff --git a/tools/perf/arch/x86/tests/rdpmc.c b/tools/perf/arch/x86/tests/rdpmc.c index 72193f19d6d7..500cf96db979 100644 --- a/tools/perf/arch/x86/tests/rdpmc.c +++ b/tools/perf/arch/x86/tests/rdpmc.c | |||
@@ -1,12 +1,16 @@ | |||
1 | #include <errno.h> | ||
1 | #include <unistd.h> | 2 | #include <unistd.h> |
2 | #include <stdlib.h> | 3 | #include <stdlib.h> |
3 | #include <signal.h> | 4 | #include <signal.h> |
4 | #include <sys/mman.h> | 5 | #include <sys/mman.h> |
6 | #include <sys/types.h> | ||
7 | #include <sys/wait.h> | ||
5 | #include <linux/types.h> | 8 | #include <linux/types.h> |
6 | #include "perf.h" | 9 | #include "perf.h" |
7 | #include "debug.h" | 10 | #include "debug.h" |
8 | #include "tests/tests.h" | 11 | #include "tests/tests.h" |
9 | #include "cloexec.h" | 12 | #include "cloexec.h" |
13 | #include "util.h" | ||
10 | #include "arch-tests.h" | 14 | #include "arch-tests.h" |
11 | 15 | ||
12 | static u64 rdpmc(unsigned int counter) | 16 | static u64 rdpmc(unsigned int counter) |
@@ -111,14 +115,14 @@ static int __test__rdpmc(void) | |||
111 | if (fd < 0) { | 115 | if (fd < 0) { |
112 | pr_err("Error: sys_perf_event_open() syscall returned " | 116 | pr_err("Error: sys_perf_event_open() syscall returned " |
113 | "with %d (%s)\n", fd, | 117 | "with %d (%s)\n", fd, |
114 | strerror_r(errno, sbuf, sizeof(sbuf))); | 118 | str_error_r(errno, sbuf, sizeof(sbuf))); |
115 | return -1; | 119 | return -1; |
116 | } | 120 | } |
117 | 121 | ||
118 | addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); | 122 | addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); |
119 | if (addr == (void *)(-1)) { | 123 | if (addr == (void *)(-1)) { |
120 | pr_err("Error: mmap() syscall returned with (%s)\n", | 124 | pr_err("Error: mmap() syscall returned with (%s)\n", |
121 | strerror_r(errno, sbuf, sizeof(sbuf))); | 125 | str_error_r(errno, sbuf, sizeof(sbuf))); |
122 | goto out_close; | 126 | goto out_close; |
123 | } | 127 | } |
124 | 128 | ||
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build index 465970370f3e..f95e6f46ef0d 100644 --- a/tools/perf/arch/x86/util/Build +++ b/tools/perf/arch/x86/util/Build | |||
@@ -3,11 +3,12 @@ libperf-y += tsc.o | |||
3 | libperf-y += pmu.o | 3 | libperf-y += pmu.o |
4 | libperf-y += kvm-stat.o | 4 | libperf-y += kvm-stat.o |
5 | libperf-y += perf_regs.o | 5 | libperf-y += perf_regs.o |
6 | libperf-y += group.o | ||
6 | 7 | ||
7 | libperf-$(CONFIG_DWARF) += dwarf-regs.o | 8 | libperf-$(CONFIG_DWARF) += dwarf-regs.o |
8 | libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o | 9 | libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o |
9 | 10 | ||
10 | libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o | 11 | libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o |
11 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o | 12 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o |
12 | 13 | ||
13 | libperf-$(CONFIG_AUXTRACE) += auxtrace.o | 14 | libperf-$(CONFIG_AUXTRACE) += auxtrace.o |
diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c index 7a7805583e3f..cc1d865e31f1 100644 --- a/tools/perf/arch/x86/util/auxtrace.c +++ b/tools/perf/arch/x86/util/auxtrace.c | |||
@@ -37,7 +37,7 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist, | |||
37 | intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); | 37 | intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); |
38 | 38 | ||
39 | if (evlist) { | 39 | if (evlist) { |
40 | evlist__for_each(evlist, evsel) { | 40 | evlist__for_each_entry(evlist, evsel) { |
41 | if (intel_pt_pmu && | 41 | if (intel_pt_pmu && |
42 | evsel->attr.type == intel_pt_pmu->type) | 42 | evsel->attr.type == intel_pt_pmu->type) |
43 | found_pt = true; | 43 | found_pt = true; |
diff --git a/tools/perf/arch/x86/util/group.c b/tools/perf/arch/x86/util/group.c new file mode 100644 index 000000000000..37f92aa39a5d --- /dev/null +++ b/tools/perf/arch/x86/util/group.c | |||
@@ -0,0 +1,27 @@ | |||
1 | #include <stdio.h> | ||
2 | #include "api/fs/fs.h" | ||
3 | #include "util/group.h" | ||
4 | |||
5 | /* | ||
6 | * Check whether we can use a group for top down. | ||
7 | * Without a group may get bad results due to multiplexing. | ||
8 | */ | ||
9 | bool arch_topdown_check_group(bool *warn) | ||
10 | { | ||
11 | int n; | ||
12 | |||
13 | if (sysctl__read_int("kernel/nmi_watchdog", &n) < 0) | ||
14 | return false; | ||
15 | if (n > 0) { | ||
16 | *warn = true; | ||
17 | return false; | ||
18 | } | ||
19 | return true; | ||
20 | } | ||
21 | |||
22 | void arch_topdown_group_warn(void) | ||
23 | { | ||
24 | fprintf(stderr, | ||
25 | "nmi_watchdog enabled with topdown. May give wrong results.\n" | ||
26 | "Disable with echo 0 > /proc/sys/kernel/nmi_watchdog\n"); | ||
27 | } | ||
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index 7dc30637cf66..5132775a044f 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c | |||
@@ -124,7 +124,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr, | |||
124 | btsr->evlist = evlist; | 124 | btsr->evlist = evlist; |
125 | btsr->snapshot_mode = opts->auxtrace_snapshot_mode; | 125 | btsr->snapshot_mode = opts->auxtrace_snapshot_mode; |
126 | 126 | ||
127 | evlist__for_each(evlist, evsel) { | 127 | evlist__for_each_entry(evlist, evsel) { |
128 | if (evsel->attr.type == intel_bts_pmu->type) { | 128 | if (evsel->attr.type == intel_bts_pmu->type) { |
129 | if (intel_bts_evsel) { | 129 | if (intel_bts_evsel) { |
130 | pr_err("There may be only one " INTEL_BTS_PMU_NAME " event\n"); | 130 | pr_err("There may be only one " INTEL_BTS_PMU_NAME " event\n"); |
@@ -327,7 +327,7 @@ static int intel_bts_snapshot_start(struct auxtrace_record *itr) | |||
327 | container_of(itr, struct intel_bts_recording, itr); | 327 | container_of(itr, struct intel_bts_recording, itr); |
328 | struct perf_evsel *evsel; | 328 | struct perf_evsel *evsel; |
329 | 329 | ||
330 | evlist__for_each(btsr->evlist, evsel) { | 330 | evlist__for_each_entry(btsr->evlist, evsel) { |
331 | if (evsel->attr.type == btsr->intel_bts_pmu->type) | 331 | if (evsel->attr.type == btsr->intel_bts_pmu->type) |
332 | return perf_evsel__disable(evsel); | 332 | return perf_evsel__disable(evsel); |
333 | } | 333 | } |
@@ -340,7 +340,7 @@ static int intel_bts_snapshot_finish(struct auxtrace_record *itr) | |||
340 | container_of(itr, struct intel_bts_recording, itr); | 340 | container_of(itr, struct intel_bts_recording, itr); |
341 | struct perf_evsel *evsel; | 341 | struct perf_evsel *evsel; |
342 | 342 | ||
343 | evlist__for_each(btsr->evlist, evsel) { | 343 | evlist__for_each_entry(btsr->evlist, evsel) { |
344 | if (evsel->attr.type == btsr->intel_bts_pmu->type) | 344 | if (evsel->attr.type == btsr->intel_bts_pmu->type) |
345 | return perf_evsel__enable(evsel); | 345 | return perf_evsel__enable(evsel); |
346 | } | 346 | } |
@@ -422,7 +422,7 @@ static int intel_bts_read_finish(struct auxtrace_record *itr, int idx) | |||
422 | container_of(itr, struct intel_bts_recording, itr); | 422 | container_of(itr, struct intel_bts_recording, itr); |
423 | struct perf_evsel *evsel; | 423 | struct perf_evsel *evsel; |
424 | 424 | ||
425 | evlist__for_each(btsr->evlist, evsel) { | 425 | evlist__for_each_entry(btsr->evlist, evsel) { |
426 | if (evsel->attr.type == btsr->intel_bts_pmu->type) | 426 | if (evsel->attr.type == btsr->intel_bts_pmu->type) |
427 | return perf_evlist__enable_event_idx(btsr->evlist, | 427 | return perf_evlist__enable_event_idx(btsr->evlist, |
428 | evsel, idx); | 428 | evsel, idx); |
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index a07b9605e93b..fb51457ba338 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c | |||
@@ -131,7 +131,7 @@ static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str, | |||
131 | if (!mask) | 131 | if (!mask) |
132 | return -EINVAL; | 132 | return -EINVAL; |
133 | 133 | ||
134 | evlist__for_each(evlist, evsel) { | 134 | evlist__for_each_entry(evlist, evsel) { |
135 | if (evsel->attr.type == intel_pt_pmu->type) { | 135 | if (evsel->attr.type == intel_pt_pmu->type) { |
136 | *res = intel_pt_masked_bits(mask, evsel->attr.config); | 136 | *res = intel_pt_masked_bits(mask, evsel->attr.config); |
137 | return 0; | 137 | return 0; |
@@ -511,7 +511,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
511 | ptr->evlist = evlist; | 511 | ptr->evlist = evlist; |
512 | ptr->snapshot_mode = opts->auxtrace_snapshot_mode; | 512 | ptr->snapshot_mode = opts->auxtrace_snapshot_mode; |
513 | 513 | ||
514 | evlist__for_each(evlist, evsel) { | 514 | evlist__for_each_entry(evlist, evsel) { |
515 | if (evsel->attr.type == intel_pt_pmu->type) { | 515 | if (evsel->attr.type == intel_pt_pmu->type) { |
516 | if (intel_pt_evsel) { | 516 | if (intel_pt_evsel) { |
517 | pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n"); | 517 | pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n"); |
@@ -725,7 +725,7 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr) | |||
725 | container_of(itr, struct intel_pt_recording, itr); | 725 | container_of(itr, struct intel_pt_recording, itr); |
726 | struct perf_evsel *evsel; | 726 | struct perf_evsel *evsel; |
727 | 727 | ||
728 | evlist__for_each(ptr->evlist, evsel) { | 728 | evlist__for_each_entry(ptr->evlist, evsel) { |
729 | if (evsel->attr.type == ptr->intel_pt_pmu->type) | 729 | if (evsel->attr.type == ptr->intel_pt_pmu->type) |
730 | return perf_evsel__disable(evsel); | 730 | return perf_evsel__disable(evsel); |
731 | } | 731 | } |
@@ -738,7 +738,7 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr) | |||
738 | container_of(itr, struct intel_pt_recording, itr); | 738 | container_of(itr, struct intel_pt_recording, itr); |
739 | struct perf_evsel *evsel; | 739 | struct perf_evsel *evsel; |
740 | 740 | ||
741 | evlist__for_each(ptr->evlist, evsel) { | 741 | evlist__for_each_entry(ptr->evlist, evsel) { |
742 | if (evsel->attr.type == ptr->intel_pt_pmu->type) | 742 | if (evsel->attr.type == ptr->intel_pt_pmu->type) |
743 | return perf_evsel__enable(evsel); | 743 | return perf_evsel__enable(evsel); |
744 | } | 744 | } |
@@ -1011,7 +1011,7 @@ static int intel_pt_read_finish(struct auxtrace_record *itr, int idx) | |||
1011 | container_of(itr, struct intel_pt_recording, itr); | 1011 | container_of(itr, struct intel_pt_recording, itr); |
1012 | struct perf_evsel *evsel; | 1012 | struct perf_evsel *evsel; |
1013 | 1013 | ||
1014 | evlist__for_each(ptr->evlist, evsel) { | 1014 | evlist__for_each_entry(ptr->evlist, evsel) { |
1015 | if (evsel->attr.type == ptr->intel_pt_pmu->type) | 1015 | if (evsel->attr.type == ptr->intel_pt_pmu->type) |
1016 | return perf_evlist__enable_event_idx(ptr->evlist, evsel, | 1016 | return perf_evlist__enable_event_idx(ptr->evlist, evsel, |
1017 | idx); | 1017 | idx); |
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c index 357f1b13b5ae..2e5567c94e09 100644 --- a/tools/perf/arch/x86/util/tsc.c +++ b/tools/perf/arch/x86/util/tsc.c | |||
@@ -62,6 +62,8 @@ int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc, | |||
62 | struct perf_tsc_conversion tc; | 62 | struct perf_tsc_conversion tc; |
63 | int err; | 63 | int err; |
64 | 64 | ||
65 | if (!pc) | ||
66 | return 0; | ||
65 | err = perf_read_tsc_conversion(pc, &tc); | 67 | err = perf_read_tsc_conversion(pc, &tc); |
66 | if (err == -EOPNOTSUPP) | 68 | if (err == -EOPNOTSUPP) |
67 | return 0; | 69 | return 0; |
diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c index db25e93d989c..4f16661cbdbb 100644 --- a/tools/perf/arch/x86/util/unwind-libunwind.c +++ b/tools/perf/arch/x86/util/unwind-libunwind.c | |||
@@ -1,12 +1,14 @@ | |||
1 | 1 | ||
2 | #ifndef REMOTE_UNWIND_LIBUNWIND | ||
2 | #include <errno.h> | 3 | #include <errno.h> |
3 | #include <libunwind.h> | 4 | #include <libunwind.h> |
4 | #include "perf_regs.h" | 5 | #include "perf_regs.h" |
5 | #include "../../util/unwind.h" | 6 | #include "../../util/unwind.h" |
6 | #include "../../util/debug.h" | 7 | #include "../../util/debug.h" |
8 | #endif | ||
7 | 9 | ||
8 | #ifdef HAVE_ARCH_X86_64_SUPPORT | 10 | #ifdef HAVE_ARCH_X86_64_SUPPORT |
9 | int libunwind__arch_reg_id(int regnum) | 11 | int LIBUNWIND__ARCH_REG_ID(int regnum) |
10 | { | 12 | { |
11 | int id; | 13 | int id; |
12 | 14 | ||
@@ -70,7 +72,7 @@ int libunwind__arch_reg_id(int regnum) | |||
70 | return id; | 72 | return id; |
71 | } | 73 | } |
72 | #else | 74 | #else |
73 | int libunwind__arch_reg_id(int regnum) | 75 | int LIBUNWIND__ARCH_REG_ID(int regnum) |
74 | { | 76 | { |
75 | int id; | 77 | int id; |
76 | 78 | ||
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c index 0999ac536d86..8024cd5febd2 100644 --- a/tools/perf/bench/futex-hash.c +++ b/tools/perf/bench/futex-hash.c | |||
@@ -8,18 +8,23 @@ | |||
8 | * many threads and futexes as possible. | 8 | * many threads and futexes as possible. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include "../perf.h" | 11 | /* For the CLR_() macros */ |
12 | #include "../util/util.h" | 12 | #include <pthread.h> |
13 | |||
14 | #include <errno.h> | ||
15 | #include <signal.h> | ||
16 | #include <stdlib.h> | ||
17 | #include <linux/compiler.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <sys/time.h> | ||
20 | |||
13 | #include "../util/stat.h" | 21 | #include "../util/stat.h" |
14 | #include <subcmd/parse-options.h> | 22 | #include <subcmd/parse-options.h> |
15 | #include "../util/header.h" | ||
16 | #include "bench.h" | 23 | #include "bench.h" |
17 | #include "futex.h" | 24 | #include "futex.h" |
18 | 25 | ||
19 | #include <err.h> | 26 | #include <err.h> |
20 | #include <stdlib.h> | ||
21 | #include <sys/time.h> | 27 | #include <sys/time.h> |
22 | #include <pthread.h> | ||
23 | 28 | ||
24 | static unsigned int nthreads = 0; | 29 | static unsigned int nthreads = 0; |
25 | static unsigned int nsecs = 10; | 30 | static unsigned int nsecs = 10; |
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c index 6952db65508a..936d89d30483 100644 --- a/tools/perf/bench/futex-lock-pi.c +++ b/tools/perf/bench/futex-lock-pi.c | |||
@@ -2,18 +2,21 @@ | |||
2 | * Copyright (C) 2015 Davidlohr Bueso. | 2 | * Copyright (C) 2015 Davidlohr Bueso. |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include "../perf.h" | 5 | /* For the CLR_() macros */ |
6 | #include "../util/util.h" | 6 | #include <pthread.h> |
7 | |||
8 | #include <signal.h> | ||
7 | #include "../util/stat.h" | 9 | #include "../util/stat.h" |
8 | #include <subcmd/parse-options.h> | 10 | #include <subcmd/parse-options.h> |
9 | #include "../util/header.h" | 11 | #include <linux/compiler.h> |
12 | #include <linux/kernel.h> | ||
13 | #include <errno.h> | ||
10 | #include "bench.h" | 14 | #include "bench.h" |
11 | #include "futex.h" | 15 | #include "futex.h" |
12 | 16 | ||
13 | #include <err.h> | 17 | #include <err.h> |
14 | #include <stdlib.h> | 18 | #include <stdlib.h> |
15 | #include <sys/time.h> | 19 | #include <sys/time.h> |
16 | #include <pthread.h> | ||
17 | 20 | ||
18 | struct worker { | 21 | struct worker { |
19 | int tid; | 22 | int tid; |
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c index 718238683013..f96e22ed9f87 100644 --- a/tools/perf/bench/futex-requeue.c +++ b/tools/perf/bench/futex-requeue.c | |||
@@ -8,18 +8,21 @@ | |||
8 | * requeues without waking up any tasks -- thus mimicking a regular futex_wait. | 8 | * requeues without waking up any tasks -- thus mimicking a regular futex_wait. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include "../perf.h" | 11 | /* For the CLR_() macros */ |
12 | #include "../util/util.h" | 12 | #include <pthread.h> |
13 | |||
14 | #include <signal.h> | ||
13 | #include "../util/stat.h" | 15 | #include "../util/stat.h" |
14 | #include <subcmd/parse-options.h> | 16 | #include <subcmd/parse-options.h> |
15 | #include "../util/header.h" | 17 | #include <linux/compiler.h> |
18 | #include <linux/kernel.h> | ||
19 | #include <errno.h> | ||
16 | #include "bench.h" | 20 | #include "bench.h" |
17 | #include "futex.h" | 21 | #include "futex.h" |
18 | 22 | ||
19 | #include <err.h> | 23 | #include <err.h> |
20 | #include <stdlib.h> | 24 | #include <stdlib.h> |
21 | #include <sys/time.h> | 25 | #include <sys/time.h> |
22 | #include <pthread.h> | ||
23 | 26 | ||
24 | static u_int32_t futex1 = 0, futex2 = 0; | 27 | static u_int32_t futex1 = 0, futex2 = 0; |
25 | 28 | ||
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c index 91aaf2a1fa90..4a2ecd7438ca 100644 --- a/tools/perf/bench/futex-wake-parallel.c +++ b/tools/perf/bench/futex-wake-parallel.c | |||
@@ -7,18 +7,21 @@ | |||
7 | * it can be used to measure futex_wake() changes. | 7 | * it can be used to measure futex_wake() changes. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "../perf.h" | 10 | /* For the CLR_() macros */ |
11 | #include "../util/util.h" | 11 | #include <pthread.h> |
12 | |||
13 | #include <signal.h> | ||
12 | #include "../util/stat.h" | 14 | #include "../util/stat.h" |
13 | #include <subcmd/parse-options.h> | 15 | #include <subcmd/parse-options.h> |
14 | #include "../util/header.h" | 16 | #include <linux/compiler.h> |
17 | #include <linux/kernel.h> | ||
18 | #include <errno.h> | ||
15 | #include "bench.h" | 19 | #include "bench.h" |
16 | #include "futex.h" | 20 | #include "futex.h" |
17 | 21 | ||
18 | #include <err.h> | 22 | #include <err.h> |
19 | #include <stdlib.h> | 23 | #include <stdlib.h> |
20 | #include <sys/time.h> | 24 | #include <sys/time.h> |
21 | #include <pthread.h> | ||
22 | 25 | ||
23 | struct thread_data { | 26 | struct thread_data { |
24 | pthread_t worker; | 27 | pthread_t worker; |
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c index f416bd705f66..87d8f4f292d9 100644 --- a/tools/perf/bench/futex-wake.c +++ b/tools/perf/bench/futex-wake.c | |||
@@ -8,18 +8,21 @@ | |||
8 | * one or more tasks, and thus the waitqueue is never empty. | 8 | * one or more tasks, and thus the waitqueue is never empty. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include "../perf.h" | 11 | /* For the CLR_() macros */ |
12 | #include "../util/util.h" | 12 | #include <pthread.h> |
13 | |||
14 | #include <signal.h> | ||
13 | #include "../util/stat.h" | 15 | #include "../util/stat.h" |
14 | #include <subcmd/parse-options.h> | 16 | #include <subcmd/parse-options.h> |
15 | #include "../util/header.h" | 17 | #include <linux/compiler.h> |
18 | #include <linux/kernel.h> | ||
19 | #include <errno.h> | ||
16 | #include "bench.h" | 20 | #include "bench.h" |
17 | #include "futex.h" | 21 | #include "futex.h" |
18 | 22 | ||
19 | #include <err.h> | 23 | #include <err.h> |
20 | #include <stdlib.h> | 24 | #include <stdlib.h> |
21 | #include <sys/time.h> | 25 | #include <sys/time.h> |
22 | #include <pthread.h> | ||
23 | 26 | ||
24 | /* all threads will block on the same futex */ | 27 | /* all threads will block on the same futex */ |
25 | static u_int32_t futex1 = 0; | 28 | static u_int32_t futex1 = 0; |
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S index 5c3cce082cb8..f700369bb0f6 100644 --- a/tools/perf/bench/mem-memcpy-x86-64-asm.S +++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S | |||
@@ -6,7 +6,7 @@ | |||
6 | #define globl p2align 4; .globl | 6 | #define globl p2align 4; .globl |
7 | #define _ASM_EXTABLE_FAULT(x, y) | 7 | #define _ASM_EXTABLE_FAULT(x, y) |
8 | 8 | ||
9 | #include "../../../arch/x86/lib/memcpy_64.S" | 9 | #include "../../arch/x86/lib/memcpy_64.S" |
10 | /* | 10 | /* |
11 | * We need to provide note.GNU-stack section, saying that we want | 11 | * We need to provide note.GNU-stack section, saying that we want |
12 | * NOT executable stack. Otherwise the final linking will assume that | 12 | * NOT executable stack. Otherwise the final linking will assume that |
diff --git a/tools/perf/bench/mem-memset-x86-64-asm.S b/tools/perf/bench/mem-memset-x86-64-asm.S index de278784c866..58407aa24c1b 100644 --- a/tools/perf/bench/mem-memset-x86-64-asm.S +++ b/tools/perf/bench/mem-memset-x86-64-asm.S | |||
@@ -1,7 +1,7 @@ | |||
1 | #define memset MEMSET /* don't hide glibc's memset() */ | 1 | #define memset MEMSET /* don't hide glibc's memset() */ |
2 | #define altinstr_replacement text | 2 | #define altinstr_replacement text |
3 | #define globl p2align 4; .globl | 3 | #define globl p2align 4; .globl |
4 | #include "../../../arch/x86/lib/memset_64.S" | 4 | #include "../../arch/x86/lib/memset_64.S" |
5 | 5 | ||
6 | /* | 6 | /* |
7 | * We need to provide note.GNU-stack section, saying that we want | 7 | * We need to provide note.GNU-stack section, saying that we want |
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c index 7500d959d7eb..f7f530081aa9 100644 --- a/tools/perf/bench/numa.c +++ b/tools/perf/bench/numa.c | |||
@@ -4,6 +4,9 @@ | |||
4 | * numa: Simulate NUMA-sensitive workload and measure their NUMA performance | 4 | * numa: Simulate NUMA-sensitive workload and measure their NUMA performance |
5 | */ | 5 | */ |
6 | 6 | ||
7 | /* For the CLR_() macros */ | ||
8 | #include <pthread.h> | ||
9 | |||
7 | #include "../perf.h" | 10 | #include "../perf.h" |
8 | #include "../builtin.h" | 11 | #include "../builtin.h" |
9 | #include "../util/util.h" | 12 | #include "../util/util.h" |
@@ -21,7 +24,6 @@ | |||
21 | #include <stdlib.h> | 24 | #include <stdlib.h> |
22 | #include <string.h> | 25 | #include <string.h> |
23 | #include <unistd.h> | 26 | #include <unistd.h> |
24 | #include <pthread.h> | ||
25 | #include <sys/mman.h> | 27 | #include <sys/mman.h> |
26 | #include <sys/time.h> | 28 | #include <sys/time.h> |
27 | #include <sys/resource.h> | 29 | #include <sys/resource.h> |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 25c81734a950..9c1034d81b4f 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -75,7 +75,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, | |||
75 | sample->period = 1; | 75 | sample->period = 1; |
76 | sample->weight = 1; | 76 | sample->weight = 1; |
77 | 77 | ||
78 | he = __hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); | 78 | he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); |
79 | if (he == NULL) | 79 | if (he == NULL) |
80 | return -ENOMEM; | 80 | return -ENOMEM; |
81 | 81 | ||
@@ -236,7 +236,7 @@ static int __cmd_annotate(struct perf_annotate *ann) | |||
236 | perf_session__fprintf_dsos(session, stdout); | 236 | perf_session__fprintf_dsos(session, stdout); |
237 | 237 | ||
238 | total_nr_samples = 0; | 238 | total_nr_samples = 0; |
239 | evlist__for_each(session->evlist, pos) { | 239 | evlist__for_each_entry(session->evlist, pos) { |
240 | struct hists *hists = evsel__hists(pos); | 240 | struct hists *hists = evsel__hists(pos); |
241 | u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; | 241 | u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; |
242 | 242 | ||
@@ -339,6 +339,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) | |||
339 | "Show event group information together"), | 339 | "Show event group information together"), |
340 | OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, | 340 | OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, |
341 | "Show a column with the sum of periods"), | 341 | "Show a column with the sum of periods"), |
342 | OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode", | ||
343 | "'always' (default), 'never' or 'auto' only applicable to --stdio mode", | ||
344 | stdio__config_color, "always"), | ||
342 | OPT_END() | 345 | OPT_END() |
343 | }; | 346 | }; |
344 | int ret = hists__init(); | 347 | int ret = hists__init(); |
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index d75bded21fe0..30e2b2cb2421 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c | |||
@@ -209,7 +209,7 @@ static int build_id_cache__purge_path(const char *pathname) | |||
209 | if (err) | 209 | if (err) |
210 | goto out; | 210 | goto out; |
211 | 211 | ||
212 | strlist__for_each(pos, list) { | 212 | strlist__for_each_entry(pos, list) { |
213 | err = build_id_cache__remove_s(pos->s); | 213 | err = build_id_cache__remove_s(pos->s); |
214 | pr_debug("Removing %s %s: %s\n", pos->s, pathname, | 214 | pr_debug("Removing %s %s: %s\n", pos->s, pathname, |
215 | err ? "FAIL" : "Ok"); | 215 | err ? "FAIL" : "Ok"); |
@@ -343,7 +343,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
343 | if (add_name_list_str) { | 343 | if (add_name_list_str) { |
344 | list = strlist__new(add_name_list_str, NULL); | 344 | list = strlist__new(add_name_list_str, NULL); |
345 | if (list) { | 345 | if (list) { |
346 | strlist__for_each(pos, list) | 346 | strlist__for_each_entry(pos, list) |
347 | if (build_id_cache__add_file(pos->s)) { | 347 | if (build_id_cache__add_file(pos->s)) { |
348 | if (errno == EEXIST) { | 348 | if (errno == EEXIST) { |
349 | pr_debug("%s already in the cache\n", | 349 | pr_debug("%s already in the cache\n", |
@@ -351,7 +351,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
351 | continue; | 351 | continue; |
352 | } | 352 | } |
353 | pr_warning("Couldn't add %s: %s\n", | 353 | pr_warning("Couldn't add %s: %s\n", |
354 | pos->s, strerror_r(errno, sbuf, sizeof(sbuf))); | 354 | pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); |
355 | } | 355 | } |
356 | 356 | ||
357 | strlist__delete(list); | 357 | strlist__delete(list); |
@@ -361,7 +361,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
361 | if (remove_name_list_str) { | 361 | if (remove_name_list_str) { |
362 | list = strlist__new(remove_name_list_str, NULL); | 362 | list = strlist__new(remove_name_list_str, NULL); |
363 | if (list) { | 363 | if (list) { |
364 | strlist__for_each(pos, list) | 364 | strlist__for_each_entry(pos, list) |
365 | if (build_id_cache__remove_file(pos->s)) { | 365 | if (build_id_cache__remove_file(pos->s)) { |
366 | if (errno == ENOENT) { | 366 | if (errno == ENOENT) { |
367 | pr_debug("%s wasn't in the cache\n", | 367 | pr_debug("%s wasn't in the cache\n", |
@@ -369,7 +369,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
369 | continue; | 369 | continue; |
370 | } | 370 | } |
371 | pr_warning("Couldn't remove %s: %s\n", | 371 | pr_warning("Couldn't remove %s: %s\n", |
372 | pos->s, strerror_r(errno, sbuf, sizeof(sbuf))); | 372 | pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); |
373 | } | 373 | } |
374 | 374 | ||
375 | strlist__delete(list); | 375 | strlist__delete(list); |
@@ -379,7 +379,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
379 | if (purge_name_list_str) { | 379 | if (purge_name_list_str) { |
380 | list = strlist__new(purge_name_list_str, NULL); | 380 | list = strlist__new(purge_name_list_str, NULL); |
381 | if (list) { | 381 | if (list) { |
382 | strlist__for_each(pos, list) | 382 | strlist__for_each_entry(pos, list) |
383 | if (build_id_cache__purge_path(pos->s)) { | 383 | if (build_id_cache__purge_path(pos->s)) { |
384 | if (errno == ENOENT) { | 384 | if (errno == ENOENT) { |
385 | pr_debug("%s wasn't in the cache\n", | 385 | pr_debug("%s wasn't in the cache\n", |
@@ -387,7 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
387 | continue; | 387 | continue; |
388 | } | 388 | } |
389 | pr_warning("Couldn't remove %s: %s\n", | 389 | pr_warning("Couldn't remove %s: %s\n", |
390 | pos->s, strerror_r(errno, sbuf, sizeof(sbuf))); | 390 | pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); |
391 | } | 391 | } |
392 | 392 | ||
393 | strlist__delete(list); | 393 | strlist__delete(list); |
@@ -400,7 +400,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
400 | if (update_name_list_str) { | 400 | if (update_name_list_str) { |
401 | list = strlist__new(update_name_list_str, NULL); | 401 | list = strlist__new(update_name_list_str, NULL); |
402 | if (list) { | 402 | if (list) { |
403 | strlist__for_each(pos, list) | 403 | strlist__for_each_entry(pos, list) |
404 | if (build_id_cache__update_file(pos->s)) { | 404 | if (build_id_cache__update_file(pos->s)) { |
405 | if (errno == ENOENT) { | 405 | if (errno == ENOENT) { |
406 | pr_debug("%s wasn't in the cache\n", | 406 | pr_debug("%s wasn't in the cache\n", |
@@ -408,7 +408,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
408 | continue; | 408 | continue; |
409 | } | 409 | } |
410 | pr_warning("Couldn't update %s: %s\n", | 410 | pr_warning("Couldn't update %s: %s\n", |
411 | pos->s, strerror_r(errno, sbuf, sizeof(sbuf))); | 411 | pos->s, str_error_r(errno, sbuf, sizeof(sbuf))); |
412 | } | 412 | } |
413 | 413 | ||
414 | strlist__delete(list); | 414 | strlist__delete(list); |
@@ -419,8 +419,7 @@ int cmd_buildid_cache(int argc, const char **argv, | |||
419 | pr_warning("Couldn't add %s\n", kcore_filename); | 419 | pr_warning("Couldn't add %s\n", kcore_filename); |
420 | 420 | ||
421 | out: | 421 | out: |
422 | if (session) | 422 | perf_session__delete(session); |
423 | perf_session__delete(session); | ||
424 | 423 | ||
425 | return ret; | 424 | return ret; |
426 | } | 425 | } |
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index fe1b77fa21f9..e4207a23b52c 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c | |||
@@ -37,23 +37,16 @@ static int show_config(struct perf_config_set *set) | |||
37 | { | 37 | { |
38 | struct perf_config_section *section; | 38 | struct perf_config_section *section; |
39 | struct perf_config_item *item; | 39 | struct perf_config_item *item; |
40 | struct list_head *sections; | ||
41 | 40 | ||
42 | if (set == NULL) | 41 | if (set == NULL) |
43 | return -1; | 42 | return -1; |
44 | 43 | ||
45 | sections = &set->sections; | 44 | perf_config_set__for_each_entry(set, section, item) { |
46 | if (list_empty(sections)) | 45 | char *value = item->value; |
47 | return -1; | ||
48 | |||
49 | list_for_each_entry(section, sections, node) { | ||
50 | list_for_each_entry(item, §ion->items, node) { | ||
51 | char *value = item->value; | ||
52 | 46 | ||
53 | if (value) | 47 | if (value) |
54 | printf("%s.%s=%s\n", section->name, | 48 | printf("%s.%s=%s\n", section->name, |
55 | item->name, value); | 49 | item->name, value); |
56 | } | ||
57 | } | 50 | } |
58 | 51 | ||
59 | return 0; | 52 | return 0; |
@@ -80,6 +73,10 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) | |||
80 | else if (use_user_config) | 73 | else if (use_user_config) |
81 | config_exclusive_filename = user_config; | 74 | config_exclusive_filename = user_config; |
82 | 75 | ||
76 | /* | ||
77 | * At only 'config' sub-command, individually use the config set | ||
78 | * because of reinitializing with options config file location. | ||
79 | */ | ||
83 | set = perf_config_set__new(); | 80 | set = perf_config_set__new(); |
84 | if (!set) { | 81 | if (!set) { |
85 | ret = -1; | 82 | ret = -1; |
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c index b97bc1518b44..7ad6e17ac6b3 100644 --- a/tools/perf/builtin-data.c +++ b/tools/perf/builtin-data.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "perf.h" | 3 | #include "perf.h" |
4 | #include "debug.h" | 4 | #include "debug.h" |
5 | #include <subcmd/parse-options.h> | 5 | #include <subcmd/parse-options.h> |
6 | #include "data-convert.h" | ||
6 | #include "data-convert-bt.h" | 7 | #include "data-convert-bt.h" |
7 | 8 | ||
8 | typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix); | 9 | typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix); |
@@ -53,14 +54,18 @@ static int cmd_data_convert(int argc, const char **argv, | |||
53 | const char *prefix __maybe_unused) | 54 | const char *prefix __maybe_unused) |
54 | { | 55 | { |
55 | const char *to_ctf = NULL; | 56 | const char *to_ctf = NULL; |
56 | bool force = false; | 57 | struct perf_data_convert_opts opts = { |
58 | .force = false, | ||
59 | .all = false, | ||
60 | }; | ||
57 | const struct option options[] = { | 61 | const struct option options[] = { |
58 | OPT_INCR('v', "verbose", &verbose, "be more verbose"), | 62 | OPT_INCR('v', "verbose", &verbose, "be more verbose"), |
59 | OPT_STRING('i', "input", &input_name, "file", "input file name"), | 63 | OPT_STRING('i', "input", &input_name, "file", "input file name"), |
60 | #ifdef HAVE_LIBBABELTRACE_SUPPORT | 64 | #ifdef HAVE_LIBBABELTRACE_SUPPORT |
61 | OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"), | 65 | OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"), |
62 | #endif | 66 | #endif |
63 | OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), | 67 | OPT_BOOLEAN('f', "force", &opts.force, "don't complain, do it"), |
68 | OPT_BOOLEAN(0, "all", &opts.all, "Convert all events"), | ||
64 | OPT_END() | 69 | OPT_END() |
65 | }; | 70 | }; |
66 | 71 | ||
@@ -78,7 +83,7 @@ static int cmd_data_convert(int argc, const char **argv, | |||
78 | 83 | ||
79 | if (to_ctf) { | 84 | if (to_ctf) { |
80 | #ifdef HAVE_LIBBABELTRACE_SUPPORT | 85 | #ifdef HAVE_LIBBABELTRACE_SUPPORT |
81 | return bt_convert__perf2ctf(input_name, to_ctf, force); | 86 | return bt_convert__perf2ctf(input_name, to_ctf, &opts); |
82 | #else | 87 | #else |
83 | pr_err("The libbabeltrace support is not compiled in.\n"); | 88 | pr_err("The libbabeltrace support is not compiled in.\n"); |
84 | return -1; | 89 | return -1; |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index f7645a42708e..21ee753211ad 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -310,16 +310,6 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair, | |||
310 | return -1; | 310 | return -1; |
311 | } | 311 | } |
312 | 312 | ||
313 | static int hists__add_entry(struct hists *hists, | ||
314 | struct addr_location *al, | ||
315 | struct perf_sample *sample) | ||
316 | { | ||
317 | if (__hists__add_entry(hists, al, NULL, NULL, NULL, | ||
318 | sample, true) != NULL) | ||
319 | return 0; | ||
320 | return -ENOMEM; | ||
321 | } | ||
322 | |||
323 | static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, | 313 | static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, |
324 | union perf_event *event, | 314 | union perf_event *event, |
325 | struct perf_sample *sample, | 315 | struct perf_sample *sample, |
@@ -336,7 +326,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, | |||
336 | return -1; | 326 | return -1; |
337 | } | 327 | } |
338 | 328 | ||
339 | if (hists__add_entry(hists, &al, sample)) { | 329 | if (!hists__add_entry(hists, &al, NULL, NULL, NULL, sample, true)) { |
340 | pr_warning("problem incrementing symbol period, skipping event\n"); | 330 | pr_warning("problem incrementing symbol period, skipping event\n"); |
341 | goto out_put; | 331 | goto out_put; |
342 | } | 332 | } |
@@ -373,7 +363,7 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel, | |||
373 | { | 363 | { |
374 | struct perf_evsel *e; | 364 | struct perf_evsel *e; |
375 | 365 | ||
376 | evlist__for_each(evlist, e) { | 366 | evlist__for_each_entry(evlist, e) { |
377 | if (perf_evsel__match2(evsel, e)) | 367 | if (perf_evsel__match2(evsel, e)) |
378 | return e; | 368 | return e; |
379 | } | 369 | } |
@@ -385,7 +375,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist) | |||
385 | { | 375 | { |
386 | struct perf_evsel *evsel; | 376 | struct perf_evsel *evsel; |
387 | 377 | ||
388 | evlist__for_each(evlist, evsel) { | 378 | evlist__for_each_entry(evlist, evsel) { |
389 | struct hists *hists = evsel__hists(evsel); | 379 | struct hists *hists = evsel__hists(evsel); |
390 | 380 | ||
391 | hists__collapse_resort(hists, NULL); | 381 | hists__collapse_resort(hists, NULL); |
@@ -666,7 +656,8 @@ static void hists__process(struct hists *hists) | |||
666 | hists__precompute(hists); | 656 | hists__precompute(hists); |
667 | hists__output_resort(hists, NULL); | 657 | hists__output_resort(hists, NULL); |
668 | 658 | ||
669 | hists__fprintf(hists, true, 0, 0, 0, stdout); | 659 | hists__fprintf(hists, true, 0, 0, 0, stdout, |
660 | symbol_conf.use_callchain); | ||
670 | } | 661 | } |
671 | 662 | ||
672 | static void data__fprintf(void) | 663 | static void data__fprintf(void) |
@@ -690,7 +681,7 @@ static void data_process(void) | |||
690 | struct perf_evsel *evsel_base; | 681 | struct perf_evsel *evsel_base; |
691 | bool first = true; | 682 | bool first = true; |
692 | 683 | ||
693 | evlist__for_each(evlist_base, evsel_base) { | 684 | evlist__for_each_entry(evlist_base, evsel_base) { |
694 | struct hists *hists_base = evsel__hists(evsel_base); | 685 | struct hists *hists_base = evsel__hists(evsel_base); |
695 | struct data__file *d; | 686 | struct data__file *d; |
696 | int i; | 687 | int i; |
@@ -765,9 +756,7 @@ static int __cmd_diff(void) | |||
765 | 756 | ||
766 | out_delete: | 757 | out_delete: |
767 | data__for_each_file(i, d) { | 758 | data__for_each_file(i, d) { |
768 | if (d->session) | 759 | perf_session__delete(d->session); |
769 | perf_session__delete(d->session); | ||
770 | |||
771 | data__free(d); | 760 | data__free(d); |
772 | } | 761 | } |
773 | 762 | ||
@@ -1044,7 +1033,7 @@ static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp, | |||
1044 | } | 1033 | } |
1045 | 1034 | ||
1046 | static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 1035 | static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
1047 | struct perf_evsel *evsel __maybe_unused) | 1036 | struct hists *hists __maybe_unused) |
1048 | { | 1037 | { |
1049 | struct diff_hpp_fmt *dfmt = | 1038 | struct diff_hpp_fmt *dfmt = |
1050 | container_of(fmt, struct diff_hpp_fmt, fmt); | 1039 | container_of(fmt, struct diff_hpp_fmt, fmt); |
@@ -1055,7 +1044,7 @@ static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | |||
1055 | 1044 | ||
1056 | static int hpp__width(struct perf_hpp_fmt *fmt, | 1045 | static int hpp__width(struct perf_hpp_fmt *fmt, |
1057 | struct perf_hpp *hpp __maybe_unused, | 1046 | struct perf_hpp *hpp __maybe_unused, |
1058 | struct perf_evsel *evsel __maybe_unused) | 1047 | struct hists *hists __maybe_unused) |
1059 | { | 1048 | { |
1060 | struct diff_hpp_fmt *dfmt = | 1049 | struct diff_hpp_fmt *dfmt = |
1061 | container_of(fmt, struct diff_hpp_fmt, fmt); | 1050 | container_of(fmt, struct diff_hpp_fmt, fmt); |
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index 8a31f511e1a0..e09c4287fe87 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c | |||
@@ -32,7 +32,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details | |||
32 | if (session == NULL) | 32 | if (session == NULL) |
33 | return -1; | 33 | return -1; |
34 | 34 | ||
35 | evlist__for_each(session->evlist, pos) { | 35 | evlist__for_each_entry(session->evlist, pos) { |
36 | perf_evsel__fprintf(pos, details, stdout); | 36 | perf_evsel__fprintf(pos, details, stdout); |
37 | 37 | ||
38 | if (pos->attr.type == PERF_TYPE_TRACEPOINT) | 38 | if (pos->attr.type == PERF_TYPE_TRACEPOINT) |
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index f9830c902b78..3bdb2c78a21b 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Builtin help command | 4 | * Builtin help command |
5 | */ | 5 | */ |
6 | #include "perf.h" | 6 | #include "perf.h" |
7 | #include "util/cache.h" | 7 | #include "util/config.h" |
8 | #include "builtin.h" | 8 | #include "builtin.h" |
9 | #include <subcmd/exec-cmd.h> | 9 | #include <subcmd/exec-cmd.h> |
10 | #include "common-cmds.h" | 10 | #include "common-cmds.h" |
@@ -117,7 +117,7 @@ static void exec_woman_emacs(const char *path, const char *page) | |||
117 | free(man_page); | 117 | free(man_page); |
118 | } | 118 | } |
119 | warning("failed to exec '%s': %s", path, | 119 | warning("failed to exec '%s': %s", path, |
120 | strerror_r(errno, sbuf, sizeof(sbuf))); | 120 | str_error_r(errno, sbuf, sizeof(sbuf))); |
121 | } | 121 | } |
122 | } | 122 | } |
123 | 123 | ||
@@ -150,7 +150,7 @@ static void exec_man_konqueror(const char *path, const char *page) | |||
150 | free(man_page); | 150 | free(man_page); |
151 | } | 151 | } |
152 | warning("failed to exec '%s': %s", path, | 152 | warning("failed to exec '%s': %s", path, |
153 | strerror_r(errno, sbuf, sizeof(sbuf))); | 153 | str_error_r(errno, sbuf, sizeof(sbuf))); |
154 | } | 154 | } |
155 | } | 155 | } |
156 | 156 | ||
@@ -162,7 +162,7 @@ static void exec_man_man(const char *path, const char *page) | |||
162 | path = "man"; | 162 | path = "man"; |
163 | execlp(path, "man", page, NULL); | 163 | execlp(path, "man", page, NULL); |
164 | warning("failed to exec '%s': %s", path, | 164 | warning("failed to exec '%s': %s", path, |
165 | strerror_r(errno, sbuf, sizeof(sbuf))); | 165 | str_error_r(errno, sbuf, sizeof(sbuf))); |
166 | } | 166 | } |
167 | 167 | ||
168 | static void exec_man_cmd(const char *cmd, const char *page) | 168 | static void exec_man_cmd(const char *cmd, const char *page) |
@@ -175,7 +175,7 @@ static void exec_man_cmd(const char *cmd, const char *page) | |||
175 | free(shell_cmd); | 175 | free(shell_cmd); |
176 | } | 176 | } |
177 | warning("failed to exec '%s': %s", cmd, | 177 | warning("failed to exec '%s': %s", cmd, |
178 | strerror_r(errno, sbuf, sizeof(sbuf))); | 178 | str_error_r(errno, sbuf, sizeof(sbuf))); |
179 | } | 179 | } |
180 | 180 | ||
181 | static void add_man_viewer(const char *name) | 181 | static void add_man_viewer(const char *name) |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index e5afa8fe1bf1..73c1c4cc3600 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -562,7 +562,7 @@ static void strip_init(struct perf_inject *inject) | |||
562 | 562 | ||
563 | inject->tool.context_switch = perf_event__drop; | 563 | inject->tool.context_switch = perf_event__drop; |
564 | 564 | ||
565 | evlist__for_each(evlist, evsel) | 565 | evlist__for_each_entry(evlist, evsel) |
566 | evsel->handler = drop_sample; | 566 | evsel->handler = drop_sample; |
567 | } | 567 | } |
568 | 568 | ||
@@ -590,7 +590,7 @@ static bool ok_to_remove(struct perf_evlist *evlist, | |||
590 | if (!has_tracking(evsel_to_remove)) | 590 | if (!has_tracking(evsel_to_remove)) |
591 | return true; | 591 | return true; |
592 | 592 | ||
593 | evlist__for_each(evlist, evsel) { | 593 | evlist__for_each_entry(evlist, evsel) { |
594 | if (evsel->handler != drop_sample) { | 594 | if (evsel->handler != drop_sample) { |
595 | cnt += 1; | 595 | cnt += 1; |
596 | if ((evsel->attr.sample_type & COMPAT_MASK) == | 596 | if ((evsel->attr.sample_type & COMPAT_MASK) == |
@@ -608,7 +608,7 @@ static void strip_fini(struct perf_inject *inject) | |||
608 | struct perf_evsel *evsel, *tmp; | 608 | struct perf_evsel *evsel, *tmp; |
609 | 609 | ||
610 | /* Remove non-synthesized evsels if possible */ | 610 | /* Remove non-synthesized evsels if possible */ |
611 | evlist__for_each_safe(evlist, tmp, evsel) { | 611 | evlist__for_each_entry_safe(evlist, tmp, evsel) { |
612 | if (evsel->handler == drop_sample && | 612 | if (evsel->handler == drop_sample && |
613 | ok_to_remove(evlist, evsel)) { | 613 | ok_to_remove(evlist, evsel)) { |
614 | pr_debug("Deleting %s\n", perf_evsel__name(evsel)); | 614 | pr_debug("Deleting %s\n", perf_evsel__name(evsel)); |
@@ -643,7 +643,7 @@ static int __cmd_inject(struct perf_inject *inject) | |||
643 | } else if (inject->sched_stat) { | 643 | } else if (inject->sched_stat) { |
644 | struct perf_evsel *evsel; | 644 | struct perf_evsel *evsel; |
645 | 645 | ||
646 | evlist__for_each(session->evlist, evsel) { | 646 | evlist__for_each_entry(session->evlist, evsel) { |
647 | const char *name = perf_evsel__name(evsel); | 647 | const char *name = perf_evsel__name(evsel); |
648 | 648 | ||
649 | if (!strcmp(name, "sched:sched_switch")) { | 649 | if (!strcmp(name, "sched:sched_switch")) { |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 58adfee230de..fdde1bd3e306 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -4,7 +4,7 @@ | |||
4 | #include "util/evlist.h" | 4 | #include "util/evlist.h" |
5 | #include "util/evsel.h" | 5 | #include "util/evsel.h" |
6 | #include "util/util.h" | 6 | #include "util/util.h" |
7 | #include "util/cache.h" | 7 | #include "util/config.h" |
8 | #include "util/symbol.h" | 8 | #include "util/symbol.h" |
9 | #include "util/thread.h" | 9 | #include "util/thread.h" |
10 | #include "util/header.h" | 10 | #include "util/header.h" |
@@ -608,6 +608,7 @@ static const struct { | |||
608 | const char *compact; | 608 | const char *compact; |
609 | } gfp_compact_table[] = { | 609 | } gfp_compact_table[] = { |
610 | { "GFP_TRANSHUGE", "THP" }, | 610 | { "GFP_TRANSHUGE", "THP" }, |
611 | { "GFP_TRANSHUGE_LIGHT", "THL" }, | ||
611 | { "GFP_HIGHUSER_MOVABLE", "HUM" }, | 612 | { "GFP_HIGHUSER_MOVABLE", "HUM" }, |
612 | { "GFP_HIGHUSER", "HU" }, | 613 | { "GFP_HIGHUSER", "HU" }, |
613 | { "GFP_USER", "U" }, | 614 | { "GFP_USER", "U" }, |
@@ -1354,7 +1355,7 @@ static int __cmd_kmem(struct perf_session *session) | |||
1354 | goto out; | 1355 | goto out; |
1355 | } | 1356 | } |
1356 | 1357 | ||
1357 | evlist__for_each(session->evlist, evsel) { | 1358 | evlist__for_each_entry(session->evlist, evsel) { |
1358 | if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") && | 1359 | if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") && |
1359 | perf_evsel__field(evsel, "pfn")) { | 1360 | perf_evsel__field(evsel, "pfn")) { |
1360 | use_pfn = true; | 1361 | use_pfn = true; |
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 6487c06d2708..5e2127e04f83 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -988,7 +988,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) | |||
988 | * Note: exclude_{guest,host} do not apply here. | 988 | * Note: exclude_{guest,host} do not apply here. |
989 | * This command processes KVM tracepoints from host only | 989 | * This command processes KVM tracepoints from host only |
990 | */ | 990 | */ |
991 | evlist__for_each(evlist, pos) { | 991 | evlist__for_each_entry(evlist, pos) { |
992 | struct perf_event_attr *attr = &pos->attr; | 992 | struct perf_event_attr *attr = &pos->attr; |
993 | 993 | ||
994 | /* make sure these *are* set */ | 994 | /* make sure these *are* set */ |
@@ -1018,13 +1018,13 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) | |||
1018 | err = perf_evlist__open(evlist); | 1018 | err = perf_evlist__open(evlist); |
1019 | if (err < 0) { | 1019 | if (err < 0) { |
1020 | printf("Couldn't create the events: %s\n", | 1020 | printf("Couldn't create the events: %s\n", |
1021 | strerror_r(errno, sbuf, sizeof(sbuf))); | 1021 | str_error_r(errno, sbuf, sizeof(sbuf))); |
1022 | goto out; | 1022 | goto out; |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { | 1025 | if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { |
1026 | ui__error("Failed to mmap the events: %s\n", | 1026 | ui__error("Failed to mmap the events: %s\n", |
1027 | strerror_r(errno, sbuf, sizeof(sbuf))); | 1027 | str_error_r(errno, sbuf, sizeof(sbuf))); |
1028 | perf_evlist__close(evlist); | 1028 | perf_evlist__close(evlist); |
1029 | goto out; | 1029 | goto out; |
1030 | } | 1030 | } |
@@ -1426,11 +1426,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1426 | err = kvm_events_live_report(kvm); | 1426 | err = kvm_events_live_report(kvm); |
1427 | 1427 | ||
1428 | out: | 1428 | out: |
1429 | if (kvm->session) | 1429 | perf_session__delete(kvm->session); |
1430 | perf_session__delete(kvm->session); | ||
1431 | kvm->session = NULL; | 1430 | kvm->session = NULL; |
1432 | if (kvm->evlist) | 1431 | perf_evlist__delete(kvm->evlist); |
1433 | perf_evlist__delete(kvm->evlist); | ||
1434 | 1432 | ||
1435 | return err; | 1433 | return err; |
1436 | } | 1434 | } |
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 5e22db4684b8..88ee419e5189 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c | |||
@@ -25,7 +25,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
25 | OPT_END() | 25 | OPT_END() |
26 | }; | 26 | }; |
27 | const char * const list_usage[] = { | 27 | const char * const list_usage[] = { |
28 | "perf list [hw|sw|cache|tracepoint|pmu|event_glob]", | 28 | "perf list [hw|sw|cache|tracepoint|pmu|sdt|event_glob]", |
29 | NULL | 29 | NULL |
30 | }; | 30 | }; |
31 | 31 | ||
@@ -62,6 +62,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
62 | print_hwcache_events(NULL, raw_dump); | 62 | print_hwcache_events(NULL, raw_dump); |
63 | else if (strcmp(argv[i], "pmu") == 0) | 63 | else if (strcmp(argv[i], "pmu") == 0) |
64 | print_pmu_events(NULL, raw_dump); | 64 | print_pmu_events(NULL, raw_dump); |
65 | else if (strcmp(argv[i], "sdt") == 0) | ||
66 | print_sdt_events(NULL, NULL, raw_dump); | ||
65 | else if ((sep = strchr(argv[i], ':')) != NULL) { | 67 | else if ((sep = strchr(argv[i], ':')) != NULL) { |
66 | int sep_idx; | 68 | int sep_idx; |
67 | 69 | ||
@@ -76,6 +78,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
76 | 78 | ||
77 | s[sep_idx] = '\0'; | 79 | s[sep_idx] = '\0'; |
78 | print_tracepoint_events(s, s + sep_idx + 1, raw_dump); | 80 | print_tracepoint_events(s, s + sep_idx + 1, raw_dump); |
81 | print_sdt_events(s, s + sep_idx + 1, raw_dump); | ||
79 | free(s); | 82 | free(s); |
80 | } else { | 83 | } else { |
81 | if (asprintf(&s, "*%s*", argv[i]) < 0) { | 84 | if (asprintf(&s, "*%s*", argv[i]) < 0) { |
@@ -89,6 +92,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
89 | print_hwcache_events(s, raw_dump); | 92 | print_hwcache_events(s, raw_dump); |
90 | print_pmu_events(s, raw_dump); | 93 | print_pmu_events(s, raw_dump); |
91 | print_tracepoint_events(NULL, s, raw_dump); | 94 | print_tracepoint_events(NULL, s, raw_dump); |
95 | print_sdt_events(NULL, s, raw_dump); | ||
92 | free(s); | 96 | free(s); |
93 | } | 97 | } |
94 | } | 98 | } |
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 1dc140c5481d..d608a2c9e48c 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -67,6 +67,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) | |||
67 | OPT_CALLBACK('e', "event", &mem, "event", | 67 | OPT_CALLBACK('e', "event", &mem, "event", |
68 | "event selector. use 'perf mem record -e list' to list available events", | 68 | "event selector. use 'perf mem record -e list' to list available events", |
69 | parse_record_events), | 69 | parse_record_events), |
70 | OPT_UINTEGER(0, "ldlat", &perf_mem_events__loads_ldlat, "mem-loads latency"), | ||
70 | OPT_INCR('v', "verbose", &verbose, | 71 | OPT_INCR('v', "verbose", &verbose, |
71 | "be more verbose (show counter open errors, etc)"), | 72 | "be more verbose (show counter open errors, etc)"), |
72 | OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"), | 73 | OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"), |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 9af859b28b15..ee5b42173ba3 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -44,7 +44,7 @@ | |||
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 "!_*" |
47 | #define DEFAULT_LIST_FILTER "*:*" | 47 | #define DEFAULT_LIST_FILTER "*" |
48 | 48 | ||
49 | /* Session management structure */ | 49 | /* Session management structure */ |
50 | static struct { | 50 | static struct { |
@@ -308,7 +308,7 @@ static void pr_err_with_code(const char *msg, int err) | |||
308 | 308 | ||
309 | pr_err("%s", msg); | 309 | pr_err("%s", msg); |
310 | pr_debug(" Reason: %s (Code: %d)", | 310 | pr_debug(" Reason: %s (Code: %d)", |
311 | strerror_r(-err, sbuf, sizeof(sbuf)), err); | 311 | str_error_r(-err, sbuf, sizeof(sbuf)), err); |
312 | pr_err("\n"); | 312 | pr_err("\n"); |
313 | } | 313 | } |
314 | 314 | ||
@@ -363,6 +363,32 @@ out_cleanup: | |||
363 | return ret; | 363 | return ret; |
364 | } | 364 | } |
365 | 365 | ||
366 | static int del_perf_probe_caches(struct strfilter *filter) | ||
367 | { | ||
368 | struct probe_cache *cache; | ||
369 | struct strlist *bidlist; | ||
370 | struct str_node *nd; | ||
371 | int ret; | ||
372 | |||
373 | bidlist = build_id_cache__list_all(false); | ||
374 | if (!bidlist) { | ||
375 | ret = -errno; | ||
376 | pr_debug("Failed to get buildids: %d\n", ret); | ||
377 | return ret ?: -ENOMEM; | ||
378 | } | ||
379 | |||
380 | strlist__for_each_entry(nd, bidlist) { | ||
381 | cache = probe_cache__new(nd->s); | ||
382 | if (!cache) | ||
383 | continue; | ||
384 | if (probe_cache__filter_purge(cache, filter) < 0 || | ||
385 | probe_cache__commit(cache) < 0) | ||
386 | pr_warning("Failed to remove entries for %s\n", nd->s); | ||
387 | probe_cache__delete(cache); | ||
388 | } | ||
389 | return 0; | ||
390 | } | ||
391 | |||
366 | static int perf_del_probe_events(struct strfilter *filter) | 392 | static int perf_del_probe_events(struct strfilter *filter) |
367 | { | 393 | { |
368 | int ret, ret2, ufd = -1, kfd = -1; | 394 | int ret, ret2, ufd = -1, kfd = -1; |
@@ -375,6 +401,9 @@ static int perf_del_probe_events(struct strfilter *filter) | |||
375 | 401 | ||
376 | pr_debug("Delete filter: \'%s\'\n", str); | 402 | pr_debug("Delete filter: \'%s\'\n", str); |
377 | 403 | ||
404 | if (probe_conf.cache) | ||
405 | return del_perf_probe_caches(filter); | ||
406 | |||
378 | /* Get current event names */ | 407 | /* Get current event names */ |
379 | ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); | 408 | ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); |
380 | if (ret < 0) | 409 | if (ret < 0) |
@@ -389,7 +418,7 @@ static int perf_del_probe_events(struct strfilter *filter) | |||
389 | 418 | ||
390 | ret = probe_file__get_events(kfd, filter, klist); | 419 | ret = probe_file__get_events(kfd, filter, klist); |
391 | if (ret == 0) { | 420 | if (ret == 0) { |
392 | strlist__for_each(ent, klist) | 421 | strlist__for_each_entry(ent, klist) |
393 | pr_info("Removed event: %s\n", ent->s); | 422 | pr_info("Removed event: %s\n", ent->s); |
394 | 423 | ||
395 | ret = probe_file__del_strlist(kfd, klist); | 424 | ret = probe_file__del_strlist(kfd, klist); |
@@ -399,7 +428,7 @@ static int perf_del_probe_events(struct strfilter *filter) | |||
399 | 428 | ||
400 | ret2 = probe_file__get_events(ufd, filter, ulist); | 429 | ret2 = probe_file__get_events(ufd, filter, ulist); |
401 | if (ret2 == 0) { | 430 | if (ret2 == 0) { |
402 | strlist__for_each(ent, ulist) | 431 | strlist__for_each_entry(ent, ulist) |
403 | pr_info("Removed event: %s\n", ent->s); | 432 | pr_info("Removed event: %s\n", ent->s); |
404 | 433 | ||
405 | ret2 = probe_file__del_strlist(ufd, ulist); | 434 | ret2 = probe_file__del_strlist(ufd, ulist); |
@@ -512,6 +541,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
512 | "Enable symbol demangling"), | 541 | "Enable symbol demangling"), |
513 | OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, | 542 | OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, |
514 | "Enable kernel symbol demangling"), | 543 | "Enable kernel symbol demangling"), |
544 | OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"), | ||
515 | OPT_END() | 545 | OPT_END() |
516 | }; | 546 | }; |
517 | int ret; | 547 | int ret; |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index dc3fcb597e4c..6355902fbfc8 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "util/util.h" | 13 | #include "util/util.h" |
14 | #include <subcmd/parse-options.h> | 14 | #include <subcmd/parse-options.h> |
15 | #include "util/parse-events.h" | 15 | #include "util/parse-events.h" |
16 | #include "util/config.h" | ||
16 | 17 | ||
17 | #include "util/callchain.h" | 18 | #include "util/callchain.h" |
18 | #include "util/cgroup.h" | 19 | #include "util/cgroup.h" |
@@ -118,11 +119,10 @@ backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end) | |||
118 | } | 119 | } |
119 | 120 | ||
120 | static int | 121 | static int |
121 | rb_find_range(struct perf_evlist *evlist, | 122 | rb_find_range(void *data, int mask, u64 head, u64 old, |
122 | void *data, int mask, u64 head, u64 old, | 123 | u64 *start, u64 *end, bool backward) |
123 | u64 *start, u64 *end) | ||
124 | { | 124 | { |
125 | if (!evlist->backward) { | 125 | if (!backward) { |
126 | *start = old; | 126 | *start = old; |
127 | *end = head; | 127 | *end = head; |
128 | return 0; | 128 | return 0; |
@@ -131,9 +131,10 @@ rb_find_range(struct perf_evlist *evlist, | |||
131 | return backward_rb_find_range(data, mask, head, start, end); | 131 | return backward_rb_find_range(data, mask, head, start, end); |
132 | } | 132 | } |
133 | 133 | ||
134 | static int record__mmap_read(struct record *rec, int idx) | 134 | static int |
135 | record__mmap_read(struct record *rec, struct perf_mmap *md, | ||
136 | bool overwrite, bool backward) | ||
135 | { | 137 | { |
136 | struct perf_mmap *md = &rec->evlist->mmap[idx]; | ||
137 | u64 head = perf_mmap__read_head(md); | 138 | u64 head = perf_mmap__read_head(md); |
138 | u64 old = md->prev; | 139 | u64 old = md->prev; |
139 | u64 end = head, start = old; | 140 | u64 end = head, start = old; |
@@ -142,8 +143,8 @@ static int record__mmap_read(struct record *rec, int idx) | |||
142 | void *buf; | 143 | void *buf; |
143 | int rc = 0; | 144 | int rc = 0; |
144 | 145 | ||
145 | if (rb_find_range(rec->evlist, data, md->mask, head, | 146 | if (rb_find_range(data, md->mask, head, |
146 | old, &start, &end)) | 147 | old, &start, &end, backward)) |
147 | return -1; | 148 | return -1; |
148 | 149 | ||
149 | if (start == end) | 150 | if (start == end) |
@@ -156,7 +157,7 @@ static int record__mmap_read(struct record *rec, int idx) | |||
156 | WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); | 157 | WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); |
157 | 158 | ||
158 | md->prev = head; | 159 | md->prev = head; |
159 | perf_evlist__mmap_consume(rec->evlist, idx); | 160 | perf_mmap__consume(md, overwrite || backward); |
160 | return 0; | 161 | return 0; |
161 | } | 162 | } |
162 | 163 | ||
@@ -181,7 +182,7 @@ static int record__mmap_read(struct record *rec, int idx) | |||
181 | } | 182 | } |
182 | 183 | ||
183 | md->prev = head; | 184 | md->prev = head; |
184 | perf_evlist__mmap_consume(rec->evlist, idx); | 185 | perf_mmap__consume(md, overwrite || backward); |
185 | out: | 186 | out: |
186 | return rc; | 187 | return rc; |
187 | } | 188 | } |
@@ -341,6 +342,40 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused) | |||
341 | 342 | ||
342 | #endif | 343 | #endif |
343 | 344 | ||
345 | static int record__mmap_evlist(struct record *rec, | ||
346 | struct perf_evlist *evlist) | ||
347 | { | ||
348 | struct record_opts *opts = &rec->opts; | ||
349 | char msg[512]; | ||
350 | |||
351 | if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, | ||
352 | opts->auxtrace_mmap_pages, | ||
353 | opts->auxtrace_snapshot_mode) < 0) { | ||
354 | if (errno == EPERM) { | ||
355 | pr_err("Permission error mapping pages.\n" | ||
356 | "Consider increasing " | ||
357 | "/proc/sys/kernel/perf_event_mlock_kb,\n" | ||
358 | "or try again with a smaller value of -m/--mmap_pages.\n" | ||
359 | "(current value: %u,%u)\n", | ||
360 | opts->mmap_pages, opts->auxtrace_mmap_pages); | ||
361 | return -errno; | ||
362 | } else { | ||
363 | pr_err("failed to mmap with %d (%s)\n", errno, | ||
364 | str_error_r(errno, msg, sizeof(msg))); | ||
365 | if (errno) | ||
366 | return -errno; | ||
367 | else | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | } | ||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static int record__mmap(struct record *rec) | ||
375 | { | ||
376 | return record__mmap_evlist(rec, rec->evlist); | ||
377 | } | ||
378 | |||
344 | static int record__open(struct record *rec) | 379 | static int record__open(struct record *rec) |
345 | { | 380 | { |
346 | char msg[512]; | 381 | char msg[512]; |
@@ -352,7 +387,7 @@ static int record__open(struct record *rec) | |||
352 | 387 | ||
353 | perf_evlist__config(evlist, opts, &callchain_param); | 388 | perf_evlist__config(evlist, opts, &callchain_param); |
354 | 389 | ||
355 | evlist__for_each(evlist, pos) { | 390 | evlist__for_each_entry(evlist, pos) { |
356 | try_again: | 391 | try_again: |
357 | if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { | 392 | if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { |
358 | if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { | 393 | if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { |
@@ -372,32 +407,14 @@ try_again: | |||
372 | if (perf_evlist__apply_filters(evlist, &pos)) { | 407 | if (perf_evlist__apply_filters(evlist, &pos)) { |
373 | error("failed to set filter \"%s\" on event %s with %d (%s)\n", | 408 | error("failed to set filter \"%s\" on event %s with %d (%s)\n", |
374 | pos->filter, perf_evsel__name(pos), errno, | 409 | pos->filter, perf_evsel__name(pos), errno, |
375 | strerror_r(errno, msg, sizeof(msg))); | 410 | str_error_r(errno, msg, sizeof(msg))); |
376 | rc = -1; | 411 | rc = -1; |
377 | goto out; | 412 | goto out; |
378 | } | 413 | } |
379 | 414 | ||
380 | if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, | 415 | rc = record__mmap(rec); |
381 | opts->auxtrace_mmap_pages, | 416 | if (rc) |
382 | opts->auxtrace_snapshot_mode) < 0) { | ||
383 | if (errno == EPERM) { | ||
384 | pr_err("Permission error mapping pages.\n" | ||
385 | "Consider increasing " | ||
386 | "/proc/sys/kernel/perf_event_mlock_kb,\n" | ||
387 | "or try again with a smaller value of -m/--mmap_pages.\n" | ||
388 | "(current value: %u,%u)\n", | ||
389 | opts->mmap_pages, opts->auxtrace_mmap_pages); | ||
390 | rc = -errno; | ||
391 | } else { | ||
392 | pr_err("failed to mmap with %d (%s)\n", errno, | ||
393 | strerror_r(errno, msg, sizeof(msg))); | ||
394 | if (errno) | ||
395 | rc = -errno; | ||
396 | else | ||
397 | rc = -EINVAL; | ||
398 | } | ||
399 | goto out; | 417 | goto out; |
400 | } | ||
401 | 418 | ||
402 | session->evlist = evlist; | 419 | session->evlist = evlist; |
403 | perf_session__set_id_hdr_size(session); | 420 | perf_session__set_id_hdr_size(session); |
@@ -481,17 +498,30 @@ static struct perf_event_header finished_round_event = { | |||
481 | .type = PERF_RECORD_FINISHED_ROUND, | 498 | .type = PERF_RECORD_FINISHED_ROUND, |
482 | }; | 499 | }; |
483 | 500 | ||
484 | static int record__mmap_read_all(struct record *rec) | 501 | static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist, |
502 | bool backward) | ||
485 | { | 503 | { |
486 | u64 bytes_written = rec->bytes_written; | 504 | u64 bytes_written = rec->bytes_written; |
487 | int i; | 505 | int i; |
488 | int rc = 0; | 506 | int rc = 0; |
507 | struct perf_mmap *maps; | ||
489 | 508 | ||
490 | for (i = 0; i < rec->evlist->nr_mmaps; i++) { | 509 | if (!evlist) |
491 | struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; | 510 | return 0; |
492 | 511 | ||
493 | if (rec->evlist->mmap[i].base) { | 512 | maps = backward ? evlist->backward_mmap : evlist->mmap; |
494 | if (record__mmap_read(rec, i) != 0) { | 513 | if (!maps) |
514 | return 0; | ||
515 | |||
516 | if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING) | ||
517 | return 0; | ||
518 | |||
519 | for (i = 0; i < evlist->nr_mmaps; i++) { | ||
520 | struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap; | ||
521 | |||
522 | if (maps[i].base) { | ||
523 | if (record__mmap_read(rec, &maps[i], | ||
524 | evlist->overwrite, backward) != 0) { | ||
495 | rc = -1; | 525 | rc = -1; |
496 | goto out; | 526 | goto out; |
497 | } | 527 | } |
@@ -511,10 +541,23 @@ static int record__mmap_read_all(struct record *rec) | |||
511 | if (bytes_written != rec->bytes_written) | 541 | if (bytes_written != rec->bytes_written) |
512 | rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); | 542 | rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); |
513 | 543 | ||
544 | if (backward) | ||
545 | perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY); | ||
514 | out: | 546 | out: |
515 | return rc; | 547 | return rc; |
516 | } | 548 | } |
517 | 549 | ||
550 | static int record__mmap_read_all(struct record *rec) | ||
551 | { | ||
552 | int err; | ||
553 | |||
554 | err = record__mmap_read_evlist(rec, rec->evlist, false); | ||
555 | if (err) | ||
556 | return err; | ||
557 | |||
558 | return record__mmap_read_evlist(rec, rec->evlist, true); | ||
559 | } | ||
560 | |||
518 | static void record__init_features(struct record *rec) | 561 | static void record__init_features(struct record *rec) |
519 | { | 562 | { |
520 | struct perf_session *session = rec->session; | 563 | struct perf_session *session = rec->session; |
@@ -561,13 +604,16 @@ record__finish_output(struct record *rec) | |||
561 | return; | 604 | return; |
562 | } | 605 | } |
563 | 606 | ||
564 | static int record__synthesize_workload(struct record *rec) | 607 | static int record__synthesize_workload(struct record *rec, bool tail) |
565 | { | 608 | { |
566 | struct { | 609 | struct { |
567 | struct thread_map map; | 610 | struct thread_map map; |
568 | struct thread_map_data map_data; | 611 | struct thread_map_data map_data; |
569 | } thread_map; | 612 | } thread_map; |
570 | 613 | ||
614 | if (rec->opts.tail_synthesize != tail) | ||
615 | return 0; | ||
616 | |||
571 | thread_map.map.nr = 1; | 617 | thread_map.map.nr = 1; |
572 | thread_map.map.map[0].pid = rec->evlist->workload.pid; | 618 | thread_map.map.map[0].pid = rec->evlist->workload.pid; |
573 | thread_map.map.map[0].comm = NULL; | 619 | thread_map.map.map[0].comm = NULL; |
@@ -578,7 +624,7 @@ static int record__synthesize_workload(struct record *rec) | |||
578 | rec->opts.proc_map_timeout); | 624 | rec->opts.proc_map_timeout); |
579 | } | 625 | } |
580 | 626 | ||
581 | static int record__synthesize(struct record *rec); | 627 | static int record__synthesize(struct record *rec, bool tail); |
582 | 628 | ||
583 | static int | 629 | static int |
584 | record__switch_output(struct record *rec, bool at_exit) | 630 | record__switch_output(struct record *rec, bool at_exit) |
@@ -589,6 +635,10 @@ record__switch_output(struct record *rec, bool at_exit) | |||
589 | /* Same Size: "2015122520103046"*/ | 635 | /* Same Size: "2015122520103046"*/ |
590 | char timestamp[] = "InvalidTimestamp"; | 636 | char timestamp[] = "InvalidTimestamp"; |
591 | 637 | ||
638 | record__synthesize(rec, true); | ||
639 | if (target__none(&rec->opts.target)) | ||
640 | record__synthesize_workload(rec, true); | ||
641 | |||
592 | rec->samples = 0; | 642 | rec->samples = 0; |
593 | record__finish_output(rec); | 643 | record__finish_output(rec); |
594 | err = fetch_current_timestamp(timestamp, sizeof(timestamp)); | 644 | err = fetch_current_timestamp(timestamp, sizeof(timestamp)); |
@@ -611,7 +661,7 @@ record__switch_output(struct record *rec, bool at_exit) | |||
611 | 661 | ||
612 | /* Output tracking events */ | 662 | /* Output tracking events */ |
613 | if (!at_exit) { | 663 | if (!at_exit) { |
614 | record__synthesize(rec); | 664 | record__synthesize(rec, false); |
615 | 665 | ||
616 | /* | 666 | /* |
617 | * In 'perf record --switch-output' without -a, | 667 | * In 'perf record --switch-output' without -a, |
@@ -623,7 +673,7 @@ record__switch_output(struct record *rec, bool at_exit) | |||
623 | * perf_event__synthesize_thread_map() for those events. | 673 | * perf_event__synthesize_thread_map() for those events. |
624 | */ | 674 | */ |
625 | if (target__none(&rec->opts.target)) | 675 | if (target__none(&rec->opts.target)) |
626 | record__synthesize_workload(rec); | 676 | record__synthesize_workload(rec, false); |
627 | } | 677 | } |
628 | return fd; | 678 | return fd; |
629 | } | 679 | } |
@@ -655,7 +705,29 @@ perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused | |||
655 | return 0; | 705 | return 0; |
656 | } | 706 | } |
657 | 707 | ||
658 | static int record__synthesize(struct record *rec) | 708 | static const struct perf_event_mmap_page * |
709 | perf_evlist__pick_pc(struct perf_evlist *evlist) | ||
710 | { | ||
711 | if (evlist) { | ||
712 | if (evlist->mmap && evlist->mmap[0].base) | ||
713 | return evlist->mmap[0].base; | ||
714 | if (evlist->backward_mmap && evlist->backward_mmap[0].base) | ||
715 | return evlist->backward_mmap[0].base; | ||
716 | } | ||
717 | return NULL; | ||
718 | } | ||
719 | |||
720 | static const struct perf_event_mmap_page *record__pick_pc(struct record *rec) | ||
721 | { | ||
722 | const struct perf_event_mmap_page *pc; | ||
723 | |||
724 | pc = perf_evlist__pick_pc(rec->evlist); | ||
725 | if (pc) | ||
726 | return pc; | ||
727 | return NULL; | ||
728 | } | ||
729 | |||
730 | static int record__synthesize(struct record *rec, bool tail) | ||
659 | { | 731 | { |
660 | struct perf_session *session = rec->session; | 732 | struct perf_session *session = rec->session; |
661 | struct machine *machine = &session->machines.host; | 733 | struct machine *machine = &session->machines.host; |
@@ -665,6 +737,9 @@ static int record__synthesize(struct record *rec) | |||
665 | int fd = perf_data_file__fd(file); | 737 | int fd = perf_data_file__fd(file); |
666 | int err = 0; | 738 | int err = 0; |
667 | 739 | ||
740 | if (rec->opts.tail_synthesize != tail) | ||
741 | return 0; | ||
742 | |||
668 | if (file->is_pipe) { | 743 | if (file->is_pipe) { |
669 | err = perf_event__synthesize_attrs(tool, session, | 744 | err = perf_event__synthesize_attrs(tool, session, |
670 | process_synthesized_event); | 745 | process_synthesized_event); |
@@ -692,7 +767,7 @@ static int record__synthesize(struct record *rec) | |||
692 | } | 767 | } |
693 | } | 768 | } |
694 | 769 | ||
695 | err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool, | 770 | err = perf_event__synth_time_conv(record__pick_pc(rec), tool, |
696 | process_synthesized_event, machine); | 771 | process_synthesized_event, machine); |
697 | if (err) | 772 | if (err) |
698 | goto out; | 773 | goto out; |
@@ -828,7 +903,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
828 | 903 | ||
829 | machine = &session->machines.host; | 904 | machine = &session->machines.host; |
830 | 905 | ||
831 | err = record__synthesize(rec); | 906 | err = record__synthesize(rec, false); |
832 | if (err < 0) | 907 | if (err < 0) |
833 | goto out_child; | 908 | goto out_child; |
834 | 909 | ||
@@ -888,6 +963,17 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
888 | for (;;) { | 963 | for (;;) { |
889 | unsigned long long hits = rec->samples; | 964 | unsigned long long hits = rec->samples; |
890 | 965 | ||
966 | /* | ||
967 | * rec->evlist->bkw_mmap_state is possible to be | ||
968 | * BKW_MMAP_EMPTY here: when done == true and | ||
969 | * hits != rec->samples in previous round. | ||
970 | * | ||
971 | * perf_evlist__toggle_bkw_mmap ensure we never | ||
972 | * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING. | ||
973 | */ | ||
974 | if (trigger_is_hit(&switch_output_trigger) || done || draining) | ||
975 | perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING); | ||
976 | |||
891 | if (record__mmap_read_all(rec) < 0) { | 977 | if (record__mmap_read_all(rec) < 0) { |
892 | trigger_error(&auxtrace_snapshot_trigger); | 978 | trigger_error(&auxtrace_snapshot_trigger); |
893 | trigger_error(&switch_output_trigger); | 979 | trigger_error(&switch_output_trigger); |
@@ -907,8 +993,26 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
907 | } | 993 | } |
908 | 994 | ||
909 | if (trigger_is_hit(&switch_output_trigger)) { | 995 | if (trigger_is_hit(&switch_output_trigger)) { |
996 | /* | ||
997 | * If switch_output_trigger is hit, the data in | ||
998 | * overwritable ring buffer should have been collected, | ||
999 | * so bkw_mmap_state should be set to BKW_MMAP_EMPTY. | ||
1000 | * | ||
1001 | * If SIGUSR2 raise after or during record__mmap_read_all(), | ||
1002 | * record__mmap_read_all() didn't collect data from | ||
1003 | * overwritable ring buffer. Read again. | ||
1004 | */ | ||
1005 | if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING) | ||
1006 | continue; | ||
910 | trigger_ready(&switch_output_trigger); | 1007 | trigger_ready(&switch_output_trigger); |
911 | 1008 | ||
1009 | /* | ||
1010 | * Reenable events in overwrite ring buffer after | ||
1011 | * record__mmap_read_all(): we should have collected | ||
1012 | * data from it. | ||
1013 | */ | ||
1014 | perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING); | ||
1015 | |||
912 | if (!quiet) | 1016 | if (!quiet) |
913 | fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", | 1017 | fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", |
914 | waking); | 1018 | waking); |
@@ -954,7 +1058,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
954 | 1058 | ||
955 | if (forks && workload_exec_errno) { | 1059 | if (forks && workload_exec_errno) { |
956 | char msg[STRERR_BUFSIZE]; | 1060 | char msg[STRERR_BUFSIZE]; |
957 | const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); | 1061 | const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); |
958 | pr_err("Workload failed: %s\n", emsg); | 1062 | pr_err("Workload failed: %s\n", emsg); |
959 | err = -1; | 1063 | err = -1; |
960 | goto out_child; | 1064 | goto out_child; |
@@ -963,6 +1067,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
963 | if (!quiet) | 1067 | if (!quiet) |
964 | fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); | 1068 | fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); |
965 | 1069 | ||
1070 | if (target__none(&rec->opts.target)) | ||
1071 | record__synthesize_workload(rec, true); | ||
1072 | |||
966 | out_child: | 1073 | out_child: |
967 | if (forks) { | 1074 | if (forks) { |
968 | int exit_status; | 1075 | int exit_status; |
@@ -981,6 +1088,7 @@ out_child: | |||
981 | } else | 1088 | } else |
982 | status = err; | 1089 | status = err; |
983 | 1090 | ||
1091 | record__synthesize(rec, true); | ||
984 | /* this will be recalculated during process_buildids() */ | 1092 | /* this will be recalculated during process_buildids() */ |
985 | rec->samples = 0; | 1093 | rec->samples = 0; |
986 | 1094 | ||
@@ -1267,6 +1375,8 @@ static struct record record = { | |||
1267 | const char record_callchain_help[] = CALLCHAIN_RECORD_HELP | 1375 | const char record_callchain_help[] = CALLCHAIN_RECORD_HELP |
1268 | "\n\t\t\t\tDefault: fp"; | 1376 | "\n\t\t\t\tDefault: fp"; |
1269 | 1377 | ||
1378 | static bool dry_run; | ||
1379 | |||
1270 | /* | 1380 | /* |
1271 | * XXX Will stay a global variable till we fix builtin-script.c to stop messing | 1381 | * XXX Will stay a global variable till we fix builtin-script.c to stop messing |
1272 | * with it and switch to use the library functions in perf_evlist that came | 1382 | * with it and switch to use the library functions in perf_evlist that came |
@@ -1303,6 +1413,9 @@ struct option __record_options[] = { | |||
1303 | OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, | 1413 | OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, |
1304 | &record.opts.no_inherit_set, | 1414 | &record.opts.no_inherit_set, |
1305 | "child tasks do not inherit counters"), | 1415 | "child tasks do not inherit counters"), |
1416 | OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize, | ||
1417 | "synthesize non-sample events at the end of output"), | ||
1418 | OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"), | ||
1306 | OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), | 1419 | OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), |
1307 | OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", | 1420 | OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", |
1308 | "number of mmap data pages and AUX area tracing mmap pages", | 1421 | "number of mmap data pages and AUX area tracing mmap pages", |
@@ -1321,6 +1434,7 @@ struct option __record_options[] = { | |||
1321 | OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, | 1434 | OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, |
1322 | "per thread counts"), | 1435 | "per thread counts"), |
1323 | OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), | 1436 | OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), |
1437 | OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"), | ||
1324 | OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, | 1438 | OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, |
1325 | &record.opts.sample_time_set, | 1439 | &record.opts.sample_time_set, |
1326 | "Record the sample timestamps"), | 1440 | "Record the sample timestamps"), |
@@ -1386,6 +1500,8 @@ struct option __record_options[] = { | |||
1386 | "append timestamp to output filename"), | 1500 | "append timestamp to output filename"), |
1387 | OPT_BOOLEAN(0, "switch-output", &record.switch_output, | 1501 | OPT_BOOLEAN(0, "switch-output", &record.switch_output, |
1388 | "Switch output when receive SIGUSR2"), | 1502 | "Switch output when receive SIGUSR2"), |
1503 | OPT_BOOLEAN(0, "dry-run", &dry_run, | ||
1504 | "Parse options then exit"), | ||
1389 | OPT_END() | 1505 | OPT_END() |
1390 | }; | 1506 | }; |
1391 | 1507 | ||
@@ -1455,6 +1571,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1455 | if (err) | 1571 | if (err) |
1456 | return err; | 1572 | return err; |
1457 | 1573 | ||
1574 | if (dry_run) | ||
1575 | return 0; | ||
1576 | |||
1458 | err = bpf__setup_stdout(rec->evlist); | 1577 | err = bpf__setup_stdout(rec->evlist); |
1459 | if (err) { | 1578 | if (err) { |
1460 | bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); | 1579 | bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); |
@@ -1508,6 +1627,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1508 | } | 1627 | } |
1509 | } | 1628 | } |
1510 | 1629 | ||
1630 | if (record.opts.overwrite) | ||
1631 | record.opts.tail_synthesize = true; | ||
1632 | |||
1511 | if (rec->evlist->nr_entries == 0 && | 1633 | if (rec->evlist->nr_entries == 0 && |
1512 | perf_evlist__add_default(rec->evlist) < 0) { | 1634 | perf_evlist__add_default(rec->evlist) < 0) { |
1513 | pr_err("Not enough memory for event selector list\n"); | 1635 | pr_err("Not enough memory for event selector list\n"); |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index a87cb338bdf1..949e5a15c960 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -8,7 +8,7 @@ | |||
8 | #include "builtin.h" | 8 | #include "builtin.h" |
9 | 9 | ||
10 | #include "util/util.h" | 10 | #include "util/util.h" |
11 | #include "util/cache.h" | 11 | #include "util/config.h" |
12 | 12 | ||
13 | #include "util/annotate.h" | 13 | #include "util/annotate.h" |
14 | #include "util/color.h" | 14 | #include "util/color.h" |
@@ -361,7 +361,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, | |||
361 | struct perf_evsel *pos; | 361 | struct perf_evsel *pos; |
362 | 362 | ||
363 | fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples); | 363 | fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples); |
364 | evlist__for_each(evlist, pos) { | 364 | evlist__for_each_entry(evlist, pos) { |
365 | struct hists *hists = evsel__hists(pos); | 365 | struct hists *hists = evsel__hists(pos); |
366 | const char *evname = perf_evsel__name(pos); | 366 | const char *evname = perf_evsel__name(pos); |
367 | 367 | ||
@@ -370,7 +370,8 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, | |||
370 | continue; | 370 | continue; |
371 | 371 | ||
372 | hists__fprintf_nr_sample_events(hists, rep, evname, stdout); | 372 | hists__fprintf_nr_sample_events(hists, rep, evname, stdout); |
373 | hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout); | 373 | hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout, |
374 | symbol_conf.use_callchain); | ||
374 | fprintf(stdout, "\n\n"); | 375 | fprintf(stdout, "\n\n"); |
375 | } | 376 | } |
376 | 377 | ||
@@ -477,7 +478,7 @@ static int report__collapse_hists(struct report *rep) | |||
477 | 478 | ||
478 | ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); | 479 | ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); |
479 | 480 | ||
480 | evlist__for_each(rep->session->evlist, pos) { | 481 | evlist__for_each_entry(rep->session->evlist, pos) { |
481 | struct hists *hists = evsel__hists(pos); | 482 | struct hists *hists = evsel__hists(pos); |
482 | 483 | ||
483 | if (pos->idx == 0) | 484 | if (pos->idx == 0) |
@@ -510,7 +511,7 @@ static void report__output_resort(struct report *rep) | |||
510 | 511 | ||
511 | ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); | 512 | ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); |
512 | 513 | ||
513 | evlist__for_each(rep->session->evlist, pos) | 514 | evlist__for_each_entry(rep->session->evlist, pos) |
514 | perf_evsel__output_resort(pos, &prog); | 515 | perf_evsel__output_resort(pos, &prog); |
515 | 516 | ||
516 | ui_progress__finish(); | 517 | ui_progress__finish(); |
@@ -551,7 +552,7 @@ static int __cmd_report(struct report *rep) | |||
551 | 552 | ||
552 | report__warn_kptr_restrict(rep); | 553 | report__warn_kptr_restrict(rep); |
553 | 554 | ||
554 | evlist__for_each(session->evlist, pos) | 555 | evlist__for_each_entry(session->evlist, pos) |
555 | rep->nr_entries += evsel__hists(pos)->nr_entries; | 556 | rep->nr_entries += evsel__hists(pos)->nr_entries; |
556 | 557 | ||
557 | if (use_browser == 0) { | 558 | if (use_browser == 0) { |
@@ -582,7 +583,7 @@ static int __cmd_report(struct report *rep) | |||
582 | * might be changed during the collapse phase. | 583 | * might be changed during the collapse phase. |
583 | */ | 584 | */ |
584 | rep->nr_entries = 0; | 585 | rep->nr_entries = 0; |
585 | evlist__for_each(session->evlist, pos) | 586 | evlist__for_each_entry(session->evlist, pos) |
586 | rep->nr_entries += evsel__hists(pos)->nr_entries; | 587 | rep->nr_entries += evsel__hists(pos)->nr_entries; |
587 | 588 | ||
588 | if (rep->nr_entries == 0) { | 589 | if (rep->nr_entries == 0) { |
@@ -816,6 +817,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
816 | "Show raw trace event output (do not use print fmt or plugins)"), | 817 | "Show raw trace event output (do not use print fmt or plugins)"), |
817 | OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, | 818 | OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, |
818 | "Show entries in a hierarchy"), | 819 | "Show entries in a hierarchy"), |
820 | OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode", | ||
821 | "'always' (default), 'never' or 'auto' only applicable to --stdio mode", | ||
822 | stdio__config_color, "always"), | ||
819 | OPT_END() | 823 | OPT_END() |
820 | }; | 824 | }; |
821 | struct perf_data_file file = { | 825 | struct perf_data_file file = { |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index afa057666c2a..0dfe8df2ab9b 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -494,7 +494,7 @@ force_again: | |||
494 | } | 494 | } |
495 | pr_err("Error: sys_perf_event_open() syscall returned " | 495 | pr_err("Error: sys_perf_event_open() syscall returned " |
496 | "with %d (%s)\n%s", fd, | 496 | "with %d (%s)\n%s", fd, |
497 | strerror_r(errno, sbuf, sizeof(sbuf)), info); | 497 | str_error_r(errno, sbuf, sizeof(sbuf)), info); |
498 | exit(EXIT_FAILURE); | 498 | exit(EXIT_FAILURE); |
499 | } | 499 | } |
500 | return fd; | 500 | return fd; |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index e3ce2f34d3ad..971ff91b16cb 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "util/cpumap.h" | 21 | #include "util/cpumap.h" |
22 | #include "util/thread_map.h" | 22 | #include "util/thread_map.h" |
23 | #include "util/stat.h" | 23 | #include "util/stat.h" |
24 | #include "util/thread-stack.h" | ||
24 | #include <linux/bitmap.h> | 25 | #include <linux/bitmap.h> |
25 | #include <linux/stringify.h> | 26 | #include <linux/stringify.h> |
26 | #include "asm/bug.h" | 27 | #include "asm/bug.h" |
@@ -63,6 +64,7 @@ enum perf_output_field { | |||
63 | PERF_OUTPUT_DATA_SRC = 1U << 17, | 64 | PERF_OUTPUT_DATA_SRC = 1U << 17, |
64 | PERF_OUTPUT_WEIGHT = 1U << 18, | 65 | PERF_OUTPUT_WEIGHT = 1U << 18, |
65 | PERF_OUTPUT_BPF_OUTPUT = 1U << 19, | 66 | PERF_OUTPUT_BPF_OUTPUT = 1U << 19, |
67 | PERF_OUTPUT_CALLINDENT = 1U << 20, | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | struct output_option { | 70 | struct output_option { |
@@ -89,6 +91,7 @@ struct output_option { | |||
89 | {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC}, | 91 | {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC}, |
90 | {.str = "weight", .field = PERF_OUTPUT_WEIGHT}, | 92 | {.str = "weight", .field = PERF_OUTPUT_WEIGHT}, |
91 | {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT}, | 93 | {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT}, |
94 | {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT}, | ||
92 | }; | 95 | }; |
93 | 96 | ||
94 | /* default set to maintain compatibility with current format */ | 97 | /* default set to maintain compatibility with current format */ |
@@ -339,7 +342,7 @@ static void set_print_ip_opts(struct perf_event_attr *attr) | |||
339 | */ | 342 | */ |
340 | static int perf_session__check_output_opt(struct perf_session *session) | 343 | static int perf_session__check_output_opt(struct perf_session *session) |
341 | { | 344 | { |
342 | int j; | 345 | unsigned int j; |
343 | struct perf_evsel *evsel; | 346 | struct perf_evsel *evsel; |
344 | 347 | ||
345 | for (j = 0; j < PERF_TYPE_MAX; ++j) { | 348 | for (j = 0; j < PERF_TYPE_MAX; ++j) { |
@@ -369,7 +372,7 @@ static int perf_session__check_output_opt(struct perf_session *session) | |||
369 | if (!no_callchain) { | 372 | if (!no_callchain) { |
370 | bool use_callchain = false; | 373 | bool use_callchain = false; |
371 | 374 | ||
372 | evlist__for_each(session->evlist, evsel) { | 375 | evlist__for_each_entry(session->evlist, evsel) { |
373 | if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { | 376 | if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { |
374 | use_callchain = true; | 377 | use_callchain = true; |
375 | break; | 378 | break; |
@@ -388,17 +391,20 @@ static int perf_session__check_output_opt(struct perf_session *session) | |||
388 | struct perf_event_attr *attr; | 391 | struct perf_event_attr *attr; |
389 | 392 | ||
390 | j = PERF_TYPE_TRACEPOINT; | 393 | j = PERF_TYPE_TRACEPOINT; |
391 | evsel = perf_session__find_first_evtype(session, j); | ||
392 | if (evsel == NULL) | ||
393 | goto out; | ||
394 | 394 | ||
395 | attr = &evsel->attr; | 395 | evlist__for_each_entry(session->evlist, evsel) { |
396 | if (evsel->attr.type != j) | ||
397 | continue; | ||
398 | |||
399 | attr = &evsel->attr; | ||
396 | 400 | ||
397 | if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { | 401 | if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { |
398 | output[j].fields |= PERF_OUTPUT_IP; | 402 | output[j].fields |= PERF_OUTPUT_IP; |
399 | output[j].fields |= PERF_OUTPUT_SYM; | 403 | output[j].fields |= PERF_OUTPUT_SYM; |
400 | output[j].fields |= PERF_OUTPUT_DSO; | 404 | output[j].fields |= PERF_OUTPUT_DSO; |
401 | set_print_ip_opts(attr); | 405 | set_print_ip_opts(attr); |
406 | goto out; | ||
407 | } | ||
402 | } | 408 | } |
403 | } | 409 | } |
404 | 410 | ||
@@ -559,6 +565,62 @@ static void print_sample_addr(struct perf_sample *sample, | |||
559 | } | 565 | } |
560 | } | 566 | } |
561 | 567 | ||
568 | static void print_sample_callindent(struct perf_sample *sample, | ||
569 | struct perf_evsel *evsel, | ||
570 | struct thread *thread, | ||
571 | struct addr_location *al) | ||
572 | { | ||
573 | struct perf_event_attr *attr = &evsel->attr; | ||
574 | size_t depth = thread_stack__depth(thread); | ||
575 | struct addr_location addr_al; | ||
576 | const char *name = NULL; | ||
577 | static int spacing; | ||
578 | int len = 0; | ||
579 | u64 ip = 0; | ||
580 | |||
581 | /* | ||
582 | * The 'return' has already been popped off the stack so the depth has | ||
583 | * to be adjusted to match the 'call'. | ||
584 | */ | ||
585 | if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN) | ||
586 | depth += 1; | ||
587 | |||
588 | if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) { | ||
589 | if (sample_addr_correlates_sym(attr)) { | ||
590 | thread__resolve(thread, &addr_al, sample); | ||
591 | if (addr_al.sym) | ||
592 | name = addr_al.sym->name; | ||
593 | else | ||
594 | ip = sample->addr; | ||
595 | } else { | ||
596 | ip = sample->addr; | ||
597 | } | ||
598 | } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) { | ||
599 | if (al->sym) | ||
600 | name = al->sym->name; | ||
601 | else | ||
602 | ip = sample->ip; | ||
603 | } | ||
604 | |||
605 | if (name) | ||
606 | len = printf("%*s%s", (int)depth * 4, "", name); | ||
607 | else if (ip) | ||
608 | len = printf("%*s%16" PRIx64, (int)depth * 4, "", ip); | ||
609 | |||
610 | if (len < 0) | ||
611 | return; | ||
612 | |||
613 | /* | ||
614 | * Try to keep the output length from changing frequently so that the | ||
615 | * output lines up more nicely. | ||
616 | */ | ||
617 | if (len > spacing || (len && len < spacing - 52)) | ||
618 | spacing = round_up(len + 4, 32); | ||
619 | |||
620 | if (len < spacing) | ||
621 | printf("%*s", spacing - len, ""); | ||
622 | } | ||
623 | |||
562 | static void print_sample_bts(struct perf_sample *sample, | 624 | static void print_sample_bts(struct perf_sample *sample, |
563 | struct perf_evsel *evsel, | 625 | struct perf_evsel *evsel, |
564 | struct thread *thread, | 626 | struct thread *thread, |
@@ -567,6 +629,9 @@ static void print_sample_bts(struct perf_sample *sample, | |||
567 | struct perf_event_attr *attr = &evsel->attr; | 629 | struct perf_event_attr *attr = &evsel->attr; |
568 | bool print_srcline_last = false; | 630 | bool print_srcline_last = false; |
569 | 631 | ||
632 | if (PRINT_FIELD(CALLINDENT)) | ||
633 | print_sample_callindent(sample, evsel, thread, al); | ||
634 | |||
570 | /* print branch_from information */ | 635 | /* print branch_from information */ |
571 | if (PRINT_FIELD(IP)) { | 636 | if (PRINT_FIELD(IP)) { |
572 | unsigned int print_opts = output[attr->type].print_ip_opts; | 637 | unsigned int print_opts = output[attr->type].print_ip_opts; |
@@ -603,13 +668,42 @@ static void print_sample_bts(struct perf_sample *sample, | |||
603 | printf("\n"); | 668 | printf("\n"); |
604 | } | 669 | } |
605 | 670 | ||
671 | static struct { | ||
672 | u32 flags; | ||
673 | const char *name; | ||
674 | } sample_flags[] = { | ||
675 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"}, | ||
676 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"}, | ||
677 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"}, | ||
678 | {PERF_IP_FLAG_BRANCH, "jmp"}, | ||
679 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"}, | ||
680 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"}, | ||
681 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"}, | ||
682 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"}, | ||
683 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"}, | ||
684 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, "hw int"}, | ||
685 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"}, | ||
686 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"}, | ||
687 | {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"}, | ||
688 | {0, NULL} | ||
689 | }; | ||
690 | |||
606 | static void print_sample_flags(u32 flags) | 691 | static void print_sample_flags(u32 flags) |
607 | { | 692 | { |
608 | const char *chars = PERF_IP_FLAG_CHARS; | 693 | const char *chars = PERF_IP_FLAG_CHARS; |
609 | const int n = strlen(PERF_IP_FLAG_CHARS); | 694 | const int n = strlen(PERF_IP_FLAG_CHARS); |
695 | bool in_tx = flags & PERF_IP_FLAG_IN_TX; | ||
696 | const char *name = NULL; | ||
610 | char str[33]; | 697 | char str[33]; |
611 | int i, pos = 0; | 698 | int i, pos = 0; |
612 | 699 | ||
700 | for (i = 0; sample_flags[i].name ; i++) { | ||
701 | if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) { | ||
702 | name = sample_flags[i].name; | ||
703 | break; | ||
704 | } | ||
705 | } | ||
706 | |||
613 | for (i = 0; i < n; i++, flags >>= 1) { | 707 | for (i = 0; i < n; i++, flags >>= 1) { |
614 | if (flags & 1) | 708 | if (flags & 1) |
615 | str[pos++] = chars[i]; | 709 | str[pos++] = chars[i]; |
@@ -619,7 +713,11 @@ static void print_sample_flags(u32 flags) | |||
619 | str[pos++] = '?'; | 713 | str[pos++] = '?'; |
620 | } | 714 | } |
621 | str[pos] = 0; | 715 | str[pos] = 0; |
622 | printf(" %-4s ", str); | 716 | |
717 | if (name) | ||
718 | printf(" %-7s%4s ", name, in_tx ? "(x)" : ""); | ||
719 | else | ||
720 | printf(" %-11s ", str); | ||
623 | } | 721 | } |
624 | 722 | ||
625 | struct printer_data { | 723 | struct printer_data { |
@@ -717,7 +815,7 @@ static int perf_evlist__max_name_len(struct perf_evlist *evlist) | |||
717 | struct perf_evsel *evsel; | 815 | struct perf_evsel *evsel; |
718 | int max = 0; | 816 | int max = 0; |
719 | 817 | ||
720 | evlist__for_each(evlist, evsel) { | 818 | evlist__for_each_entry(evlist, evsel) { |
721 | int len = strlen(perf_evsel__name(evsel)); | 819 | int len = strlen(perf_evsel__name(evsel)); |
722 | 820 | ||
723 | max = MAX(len, max); | 821 | max = MAX(len, max); |
@@ -942,7 +1040,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, | |||
942 | if (evsel->attr.type >= PERF_TYPE_MAX) | 1040 | if (evsel->attr.type >= PERF_TYPE_MAX) |
943 | return 0; | 1041 | return 0; |
944 | 1042 | ||
945 | evlist__for_each(evlist, pos) { | 1043 | evlist__for_each_entry(evlist, pos) { |
946 | if (pos->attr.type == evsel->attr.type && pos != evsel) | 1044 | if (pos->attr.type == evsel->attr.type && pos != evsel) |
947 | return 0; | 1045 | return 0; |
948 | } | 1046 | } |
@@ -1668,7 +1766,7 @@ static int check_ev_match(char *dir_name, char *scriptname, | |||
1668 | snprintf(evname, len + 1, "%s", p); | 1766 | snprintf(evname, len + 1, "%s", p); |
1669 | 1767 | ||
1670 | match = 0; | 1768 | match = 0; |
1671 | evlist__for_each(session->evlist, pos) { | 1769 | evlist__for_each_entry(session->evlist, pos) { |
1672 | if (!strcmp(perf_evsel__name(pos), evname)) { | 1770 | if (!strcmp(perf_evsel__name(pos), evname)) { |
1673 | match = 1; | 1771 | match = 1; |
1674 | break; | 1772 | break; |
@@ -1870,7 +1968,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused, | |||
1870 | struct stat_round_event *round = &event->stat_round; | 1968 | struct stat_round_event *round = &event->stat_round; |
1871 | struct perf_evsel *counter; | 1969 | struct perf_evsel *counter; |
1872 | 1970 | ||
1873 | evlist__for_each(session->evlist, counter) { | 1971 | evlist__for_each_entry(session->evlist, counter) { |
1874 | perf_stat_process_counter(&stat_config, counter); | 1972 | perf_stat_process_counter(&stat_config, counter); |
1875 | process_stat(counter, round->time); | 1973 | process_stat(counter, round->time); |
1876 | } | 1974 | } |
@@ -2017,7 +2115,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2017 | "comma separated output fields prepend with 'type:'. " | 2115 | "comma separated output fields prepend with 'type:'. " |
2018 | "Valid types: hw,sw,trace,raw. " | 2116 | "Valid types: hw,sw,trace,raw. " |
2019 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," | 2117 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," |
2020 | "addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields), | 2118 | "addr,symoff,period,iregs,brstack,brstacksym,flags," |
2119 | "callindent", parse_output_fields), | ||
2021 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 2120 | OPT_BOOLEAN('a', "all-cpus", &system_wide, |
2022 | "system-wide collection from all CPUs"), | 2121 | "system-wide collection from all CPUs"), |
2023 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", | 2122 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", |
@@ -2256,6 +2355,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2256 | script.session = session; | 2355 | script.session = session; |
2257 | script__setup_sample_type(&script); | 2356 | script__setup_sample_type(&script); |
2258 | 2357 | ||
2358 | if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT) | ||
2359 | itrace_synth_opts.thread_stack = true; | ||
2360 | |||
2259 | session->itrace_synth_opts = &itrace_synth_opts; | 2361 | session->itrace_synth_opts = &itrace_synth_opts; |
2260 | 2362 | ||
2261 | if (cpu_list) { | 2363 | if (cpu_list) { |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index ee7ada78d86f..0c16d20d7e32 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -59,10 +59,13 @@ | |||
59 | #include "util/thread.h" | 59 | #include "util/thread.h" |
60 | #include "util/thread_map.h" | 60 | #include "util/thread_map.h" |
61 | #include "util/counts.h" | 61 | #include "util/counts.h" |
62 | #include "util/group.h" | ||
62 | #include "util/session.h" | 63 | #include "util/session.h" |
63 | #include "util/tool.h" | 64 | #include "util/tool.h" |
65 | #include "util/group.h" | ||
64 | #include "asm/bug.h" | 66 | #include "asm/bug.h" |
65 | 67 | ||
68 | #include <api/fs/fs.h> | ||
66 | #include <stdlib.h> | 69 | #include <stdlib.h> |
67 | #include <sys/prctl.h> | 70 | #include <sys/prctl.h> |
68 | #include <locale.h> | 71 | #include <locale.h> |
@@ -98,6 +101,15 @@ static const char * transaction_limited_attrs = { | |||
98 | "}" | 101 | "}" |
99 | }; | 102 | }; |
100 | 103 | ||
104 | static const char * topdown_attrs[] = { | ||
105 | "topdown-total-slots", | ||
106 | "topdown-slots-retired", | ||
107 | "topdown-recovery-bubbles", | ||
108 | "topdown-fetch-bubbles", | ||
109 | "topdown-slots-issued", | ||
110 | NULL, | ||
111 | }; | ||
112 | |||
101 | static struct perf_evlist *evsel_list; | 113 | static struct perf_evlist *evsel_list; |
102 | 114 | ||
103 | static struct target target = { | 115 | static struct target target = { |
@@ -112,6 +124,7 @@ static volatile pid_t child_pid = -1; | |||
112 | static bool null_run = false; | 124 | static bool null_run = false; |
113 | static int detailed_run = 0; | 125 | static int detailed_run = 0; |
114 | static bool transaction_run; | 126 | static bool transaction_run; |
127 | static bool topdown_run = false; | ||
115 | static bool big_num = true; | 128 | static bool big_num = true; |
116 | static int big_num_opt = -1; | 129 | static int big_num_opt = -1; |
117 | static const char *csv_sep = NULL; | 130 | static const char *csv_sep = NULL; |
@@ -124,6 +137,7 @@ static unsigned int initial_delay = 0; | |||
124 | static unsigned int unit_width = 4; /* strlen("unit") */ | 137 | static unsigned int unit_width = 4; /* strlen("unit") */ |
125 | static bool forever = false; | 138 | static bool forever = false; |
126 | static bool metric_only = false; | 139 | static bool metric_only = false; |
140 | static bool force_metric_only = false; | ||
127 | static struct timespec ref_time; | 141 | static struct timespec ref_time; |
128 | static struct cpu_map *aggr_map; | 142 | static struct cpu_map *aggr_map; |
129 | static aggr_get_id_t aggr_get_id; | 143 | static aggr_get_id_t aggr_get_id; |
@@ -276,8 +290,12 @@ perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread, | |||
276 | static int read_counter(struct perf_evsel *counter) | 290 | static int read_counter(struct perf_evsel *counter) |
277 | { | 291 | { |
278 | int nthreads = thread_map__nr(evsel_list->threads); | 292 | int nthreads = thread_map__nr(evsel_list->threads); |
279 | int ncpus = perf_evsel__nr_cpus(counter); | 293 | int ncpus, cpu, thread; |
280 | int cpu, thread; | 294 | |
295 | if (target__has_cpu(&target)) | ||
296 | ncpus = perf_evsel__nr_cpus(counter); | ||
297 | else | ||
298 | ncpus = 1; | ||
281 | 299 | ||
282 | if (!counter->supported) | 300 | if (!counter->supported) |
283 | return -ENOENT; | 301 | return -ENOENT; |
@@ -317,7 +335,7 @@ static void read_counters(bool close_counters) | |||
317 | { | 335 | { |
318 | struct perf_evsel *counter; | 336 | struct perf_evsel *counter; |
319 | 337 | ||
320 | evlist__for_each(evsel_list, counter) { | 338 | evlist__for_each_entry(evsel_list, counter) { |
321 | if (read_counter(counter)) | 339 | if (read_counter(counter)) |
322 | pr_debug("failed to read counter %s\n", counter->name); | 340 | pr_debug("failed to read counter %s\n", counter->name); |
323 | 341 | ||
@@ -403,7 +421,7 @@ static int perf_stat_synthesize_config(bool is_pipe) | |||
403 | * Synthesize other events stuff not carried within | 421 | * Synthesize other events stuff not carried within |
404 | * attr event - unit, scale, name | 422 | * attr event - unit, scale, name |
405 | */ | 423 | */ |
406 | evlist__for_each(evsel_list, counter) { | 424 | evlist__for_each_entry(evsel_list, counter) { |
407 | if (!counter->supported) | 425 | if (!counter->supported) |
408 | continue; | 426 | continue; |
409 | 427 | ||
@@ -536,7 +554,7 @@ static int __run_perf_stat(int argc, const char **argv) | |||
536 | if (group) | 554 | if (group) |
537 | perf_evlist__set_leader(evsel_list); | 555 | perf_evlist__set_leader(evsel_list); |
538 | 556 | ||
539 | evlist__for_each(evsel_list, counter) { | 557 | evlist__for_each_entry(evsel_list, counter) { |
540 | try_again: | 558 | try_again: |
541 | if (create_perf_stat_counter(counter) < 0) { | 559 | if (create_perf_stat_counter(counter) < 0) { |
542 | /* | 560 | /* |
@@ -582,7 +600,7 @@ try_again: | |||
582 | if (perf_evlist__apply_filters(evsel_list, &counter)) { | 600 | if (perf_evlist__apply_filters(evsel_list, &counter)) { |
583 | error("failed to set filter \"%s\" on event %s with %d (%s)\n", | 601 | error("failed to set filter \"%s\" on event %s with %d (%s)\n", |
584 | counter->filter, perf_evsel__name(counter), errno, | 602 | counter->filter, perf_evsel__name(counter), errno, |
585 | strerror_r(errno, msg, sizeof(msg))); | 603 | str_error_r(errno, msg, sizeof(msg))); |
586 | return -1; | 604 | return -1; |
587 | } | 605 | } |
588 | 606 | ||
@@ -623,7 +641,7 @@ try_again: | |||
623 | wait(&status); | 641 | wait(&status); |
624 | 642 | ||
625 | if (workload_exec_errno) { | 643 | if (workload_exec_errno) { |
626 | const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); | 644 | const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); |
627 | pr_err("Workload failed: %s\n", emsg); | 645 | pr_err("Workload failed: %s\n", emsg); |
628 | return -1; | 646 | return -1; |
629 | } | 647 | } |
@@ -1120,7 +1138,7 @@ static void aggr_update_shadow(void) | |||
1120 | 1138 | ||
1121 | for (s = 0; s < aggr_map->nr; s++) { | 1139 | for (s = 0; s < aggr_map->nr; s++) { |
1122 | id = aggr_map->map[s]; | 1140 | id = aggr_map->map[s]; |
1123 | evlist__for_each(evsel_list, counter) { | 1141 | evlist__for_each_entry(evsel_list, counter) { |
1124 | val = 0; | 1142 | val = 0; |
1125 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { | 1143 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { |
1126 | s2 = aggr_get_id(evsel_list->cpus, cpu); | 1144 | s2 = aggr_get_id(evsel_list->cpus, cpu); |
@@ -1159,7 +1177,7 @@ static void print_aggr(char *prefix) | |||
1159 | 1177 | ||
1160 | id = aggr_map->map[s]; | 1178 | id = aggr_map->map[s]; |
1161 | first = true; | 1179 | first = true; |
1162 | evlist__for_each(evsel_list, counter) { | 1180 | evlist__for_each_entry(evsel_list, counter) { |
1163 | val = ena = run = 0; | 1181 | val = ena = run = 0; |
1164 | nr = 0; | 1182 | nr = 0; |
1165 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { | 1183 | for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { |
@@ -1278,7 +1296,7 @@ static void print_no_aggr_metric(char *prefix) | |||
1278 | 1296 | ||
1279 | if (prefix) | 1297 | if (prefix) |
1280 | fputs(prefix, stat_config.output); | 1298 | fputs(prefix, stat_config.output); |
1281 | evlist__for_each(evsel_list, counter) { | 1299 | evlist__for_each_entry(evsel_list, counter) { |
1282 | if (first) { | 1300 | if (first) { |
1283 | aggr_printout(counter, cpu, 0); | 1301 | aggr_printout(counter, cpu, 0); |
1284 | first = false; | 1302 | first = false; |
@@ -1302,7 +1320,15 @@ static int aggr_header_lens[] = { | |||
1302 | [AGGR_GLOBAL] = 0, | 1320 | [AGGR_GLOBAL] = 0, |
1303 | }; | 1321 | }; |
1304 | 1322 | ||
1305 | static void print_metric_headers(char *prefix) | 1323 | static const char *aggr_header_csv[] = { |
1324 | [AGGR_CORE] = "core,cpus,", | ||
1325 | [AGGR_SOCKET] = "socket,cpus", | ||
1326 | [AGGR_NONE] = "cpu,", | ||
1327 | [AGGR_THREAD] = "comm-pid,", | ||
1328 | [AGGR_GLOBAL] = "" | ||
1329 | }; | ||
1330 | |||
1331 | static void print_metric_headers(const char *prefix, bool no_indent) | ||
1306 | { | 1332 | { |
1307 | struct perf_stat_output_ctx out; | 1333 | struct perf_stat_output_ctx out; |
1308 | struct perf_evsel *counter; | 1334 | struct perf_evsel *counter; |
@@ -1313,12 +1339,18 @@ static void print_metric_headers(char *prefix) | |||
1313 | if (prefix) | 1339 | if (prefix) |
1314 | fprintf(stat_config.output, "%s", prefix); | 1340 | fprintf(stat_config.output, "%s", prefix); |
1315 | 1341 | ||
1316 | if (!csv_output) | 1342 | if (!csv_output && !no_indent) |
1317 | fprintf(stat_config.output, "%*s", | 1343 | fprintf(stat_config.output, "%*s", |
1318 | aggr_header_lens[stat_config.aggr_mode], ""); | 1344 | aggr_header_lens[stat_config.aggr_mode], ""); |
1345 | if (csv_output) { | ||
1346 | if (stat_config.interval) | ||
1347 | fputs("time,", stat_config.output); | ||
1348 | fputs(aggr_header_csv[stat_config.aggr_mode], | ||
1349 | stat_config.output); | ||
1350 | } | ||
1319 | 1351 | ||
1320 | /* Print metrics headers only */ | 1352 | /* Print metrics headers only */ |
1321 | evlist__for_each(evsel_list, counter) { | 1353 | evlist__for_each_entry(evsel_list, counter) { |
1322 | os.evsel = counter; | 1354 | os.evsel = counter; |
1323 | out.ctx = &os; | 1355 | out.ctx = &os; |
1324 | out.print_metric = print_metric_header; | 1356 | out.print_metric = print_metric_header; |
@@ -1338,28 +1370,40 @@ static void print_interval(char *prefix, struct timespec *ts) | |||
1338 | 1370 | ||
1339 | sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); | 1371 | sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); |
1340 | 1372 | ||
1341 | if (num_print_interval == 0 && !csv_output && !metric_only) { | 1373 | if (num_print_interval == 0 && !csv_output) { |
1342 | switch (stat_config.aggr_mode) { | 1374 | switch (stat_config.aggr_mode) { |
1343 | case AGGR_SOCKET: | 1375 | case AGGR_SOCKET: |
1344 | fprintf(output, "# time socket cpus counts %*s events\n", unit_width, "unit"); | 1376 | fprintf(output, "# time socket cpus"); |
1377 | if (!metric_only) | ||
1378 | fprintf(output, " counts %*s events\n", unit_width, "unit"); | ||
1345 | break; | 1379 | break; |
1346 | case AGGR_CORE: | 1380 | case AGGR_CORE: |
1347 | fprintf(output, "# time core cpus counts %*s events\n", unit_width, "unit"); | 1381 | fprintf(output, "# time core cpus"); |
1382 | if (!metric_only) | ||
1383 | fprintf(output, " counts %*s events\n", unit_width, "unit"); | ||
1348 | break; | 1384 | break; |
1349 | case AGGR_NONE: | 1385 | case AGGR_NONE: |
1350 | fprintf(output, "# time CPU counts %*s events\n", unit_width, "unit"); | 1386 | fprintf(output, "# time CPU"); |
1387 | if (!metric_only) | ||
1388 | fprintf(output, " counts %*s events\n", unit_width, "unit"); | ||
1351 | break; | 1389 | break; |
1352 | case AGGR_THREAD: | 1390 | case AGGR_THREAD: |
1353 | fprintf(output, "# time comm-pid counts %*s events\n", unit_width, "unit"); | 1391 | fprintf(output, "# time comm-pid"); |
1392 | if (!metric_only) | ||
1393 | fprintf(output, " counts %*s events\n", unit_width, "unit"); | ||
1354 | break; | 1394 | break; |
1355 | case AGGR_GLOBAL: | 1395 | case AGGR_GLOBAL: |
1356 | default: | 1396 | default: |
1357 | fprintf(output, "# time counts %*s events\n", unit_width, "unit"); | 1397 | fprintf(output, "# time"); |
1398 | if (!metric_only) | ||
1399 | fprintf(output, " counts %*s events\n", unit_width, "unit"); | ||
1358 | case AGGR_UNSET: | 1400 | case AGGR_UNSET: |
1359 | break; | 1401 | break; |
1360 | } | 1402 | } |
1361 | } | 1403 | } |
1362 | 1404 | ||
1405 | if (num_print_interval == 0 && metric_only) | ||
1406 | print_metric_headers(" ", true); | ||
1363 | if (++num_print_interval == 25) | 1407 | if (++num_print_interval == 25) |
1364 | num_print_interval = 0; | 1408 | num_print_interval = 0; |
1365 | } | 1409 | } |
@@ -1428,8 +1472,8 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) | |||
1428 | if (metric_only) { | 1472 | if (metric_only) { |
1429 | static int num_print_iv; | 1473 | static int num_print_iv; |
1430 | 1474 | ||
1431 | if (num_print_iv == 0) | 1475 | if (num_print_iv == 0 && !interval) |
1432 | print_metric_headers(prefix); | 1476 | print_metric_headers(prefix, false); |
1433 | if (num_print_iv++ == 25) | 1477 | if (num_print_iv++ == 25) |
1434 | num_print_iv = 0; | 1478 | num_print_iv = 0; |
1435 | if (stat_config.aggr_mode == AGGR_GLOBAL && prefix) | 1479 | if (stat_config.aggr_mode == AGGR_GLOBAL && prefix) |
@@ -1442,11 +1486,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) | |||
1442 | print_aggr(prefix); | 1486 | print_aggr(prefix); |
1443 | break; | 1487 | break; |
1444 | case AGGR_THREAD: | 1488 | case AGGR_THREAD: |
1445 | evlist__for_each(evsel_list, counter) | 1489 | evlist__for_each_entry(evsel_list, counter) |
1446 | print_aggr_thread(counter, prefix); | 1490 | print_aggr_thread(counter, prefix); |
1447 | break; | 1491 | break; |
1448 | case AGGR_GLOBAL: | 1492 | case AGGR_GLOBAL: |
1449 | evlist__for_each(evsel_list, counter) | 1493 | evlist__for_each_entry(evsel_list, counter) |
1450 | print_counter_aggr(counter, prefix); | 1494 | print_counter_aggr(counter, prefix); |
1451 | if (metric_only) | 1495 | if (metric_only) |
1452 | fputc('\n', stat_config.output); | 1496 | fputc('\n', stat_config.output); |
@@ -1455,7 +1499,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) | |||
1455 | if (metric_only) | 1499 | if (metric_only) |
1456 | print_no_aggr_metric(prefix); | 1500 | print_no_aggr_metric(prefix); |
1457 | else { | 1501 | else { |
1458 | evlist__for_each(evsel_list, counter) | 1502 | evlist__for_each_entry(evsel_list, counter) |
1459 | print_counter(counter, prefix); | 1503 | print_counter(counter, prefix); |
1460 | } | 1504 | } |
1461 | break; | 1505 | break; |
@@ -1520,6 +1564,14 @@ static int stat__set_big_num(const struct option *opt __maybe_unused, | |||
1520 | return 0; | 1564 | return 0; |
1521 | } | 1565 | } |
1522 | 1566 | ||
1567 | static int enable_metric_only(const struct option *opt __maybe_unused, | ||
1568 | const char *s __maybe_unused, int unset) | ||
1569 | { | ||
1570 | force_metric_only = true; | ||
1571 | metric_only = !unset; | ||
1572 | return 0; | ||
1573 | } | ||
1574 | |||
1523 | static const struct option stat_options[] = { | 1575 | static const struct option stat_options[] = { |
1524 | OPT_BOOLEAN('T', "transaction", &transaction_run, | 1576 | OPT_BOOLEAN('T', "transaction", &transaction_run, |
1525 | "hardware transaction statistics"), | 1577 | "hardware transaction statistics"), |
@@ -1578,8 +1630,10 @@ static const struct option stat_options[] = { | |||
1578 | "aggregate counts per thread", AGGR_THREAD), | 1630 | "aggregate counts per thread", AGGR_THREAD), |
1579 | OPT_UINTEGER('D', "delay", &initial_delay, | 1631 | OPT_UINTEGER('D', "delay", &initial_delay, |
1580 | "ms to wait before starting measurement after program start"), | 1632 | "ms to wait before starting measurement after program start"), |
1581 | OPT_BOOLEAN(0, "metric-only", &metric_only, | 1633 | OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL, |
1582 | "Only print computed metrics. No raw values"), | 1634 | "Only print computed metrics. No raw values", enable_metric_only), |
1635 | OPT_BOOLEAN(0, "topdown", &topdown_run, | ||
1636 | "measure topdown level 1 statistics"), | ||
1583 | OPT_END() | 1637 | OPT_END() |
1584 | }; | 1638 | }; |
1585 | 1639 | ||
@@ -1772,12 +1826,62 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st) | |||
1772 | return 0; | 1826 | return 0; |
1773 | } | 1827 | } |
1774 | 1828 | ||
1829 | static int topdown_filter_events(const char **attr, char **str, bool use_group) | ||
1830 | { | ||
1831 | int off = 0; | ||
1832 | int i; | ||
1833 | int len = 0; | ||
1834 | char *s; | ||
1835 | |||
1836 | for (i = 0; attr[i]; i++) { | ||
1837 | if (pmu_have_event("cpu", attr[i])) { | ||
1838 | len += strlen(attr[i]) + 1; | ||
1839 | attr[i - off] = attr[i]; | ||
1840 | } else | ||
1841 | off++; | ||
1842 | } | ||
1843 | attr[i - off] = NULL; | ||
1844 | |||
1845 | *str = malloc(len + 1 + 2); | ||
1846 | if (!*str) | ||
1847 | return -1; | ||
1848 | s = *str; | ||
1849 | if (i - off == 0) { | ||
1850 | *s = 0; | ||
1851 | return 0; | ||
1852 | } | ||
1853 | if (use_group) | ||
1854 | *s++ = '{'; | ||
1855 | for (i = 0; attr[i]; i++) { | ||
1856 | strcpy(s, attr[i]); | ||
1857 | s += strlen(s); | ||
1858 | *s++ = ','; | ||
1859 | } | ||
1860 | if (use_group) { | ||
1861 | s[-1] = '}'; | ||
1862 | *s = 0; | ||
1863 | } else | ||
1864 | s[-1] = 0; | ||
1865 | return 0; | ||
1866 | } | ||
1867 | |||
1868 | __weak bool arch_topdown_check_group(bool *warn) | ||
1869 | { | ||
1870 | *warn = false; | ||
1871 | return false; | ||
1872 | } | ||
1873 | |||
1874 | __weak void arch_topdown_group_warn(void) | ||
1875 | { | ||
1876 | } | ||
1877 | |||
1775 | /* | 1878 | /* |
1776 | * Add default attributes, if there were no attributes specified or | 1879 | * Add default attributes, if there were no attributes specified or |
1777 | * if -d/--detailed, -d -d or -d -d -d is used: | 1880 | * if -d/--detailed, -d -d or -d -d -d is used: |
1778 | */ | 1881 | */ |
1779 | static int add_default_attributes(void) | 1882 | static int add_default_attributes(void) |
1780 | { | 1883 | { |
1884 | int err; | ||
1781 | struct perf_event_attr default_attrs0[] = { | 1885 | struct perf_event_attr default_attrs0[] = { |
1782 | 1886 | ||
1783 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, | 1887 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, |
@@ -1896,7 +2000,6 @@ static int add_default_attributes(void) | |||
1896 | return 0; | 2000 | return 0; |
1897 | 2001 | ||
1898 | if (transaction_run) { | 2002 | if (transaction_run) { |
1899 | int err; | ||
1900 | if (pmu_have_event("cpu", "cycles-ct") && | 2003 | if (pmu_have_event("cpu", "cycles-ct") && |
1901 | pmu_have_event("cpu", "el-start")) | 2004 | pmu_have_event("cpu", "el-start")) |
1902 | err = parse_events(evsel_list, transaction_attrs, NULL); | 2005 | err = parse_events(evsel_list, transaction_attrs, NULL); |
@@ -1909,6 +2012,46 @@ static int add_default_attributes(void) | |||
1909 | return 0; | 2012 | return 0; |
1910 | } | 2013 | } |
1911 | 2014 | ||
2015 | if (topdown_run) { | ||
2016 | char *str = NULL; | ||
2017 | bool warn = false; | ||
2018 | |||
2019 | if (stat_config.aggr_mode != AGGR_GLOBAL && | ||
2020 | stat_config.aggr_mode != AGGR_CORE) { | ||
2021 | pr_err("top down event configuration requires --per-core mode\n"); | ||
2022 | return -1; | ||
2023 | } | ||
2024 | stat_config.aggr_mode = AGGR_CORE; | ||
2025 | if (nr_cgroups || !target__has_cpu(&target)) { | ||
2026 | pr_err("top down event configuration requires system-wide mode (-a)\n"); | ||
2027 | return -1; | ||
2028 | } | ||
2029 | |||
2030 | if (!force_metric_only) | ||
2031 | metric_only = true; | ||
2032 | if (topdown_filter_events(topdown_attrs, &str, | ||
2033 | arch_topdown_check_group(&warn)) < 0) { | ||
2034 | pr_err("Out of memory\n"); | ||
2035 | return -1; | ||
2036 | } | ||
2037 | if (topdown_attrs[0] && str) { | ||
2038 | if (warn) | ||
2039 | arch_topdown_group_warn(); | ||
2040 | err = parse_events(evsel_list, str, NULL); | ||
2041 | if (err) { | ||
2042 | fprintf(stderr, | ||
2043 | "Cannot set up top down events %s: %d\n", | ||
2044 | str, err); | ||
2045 | free(str); | ||
2046 | return -1; | ||
2047 | } | ||
2048 | } else { | ||
2049 | fprintf(stderr, "System does not support topdown\n"); | ||
2050 | return -1; | ||
2051 | } | ||
2052 | free(str); | ||
2053 | } | ||
2054 | |||
1912 | if (!evsel_list->nr_entries) { | 2055 | if (!evsel_list->nr_entries) { |
1913 | if (target__has_cpu(&target)) | 2056 | if (target__has_cpu(&target)) |
1914 | default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; | 2057 | default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; |
@@ -2010,7 +2153,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused, | |||
2010 | const char **argv = session->header.env.cmdline_argv; | 2153 | const char **argv = session->header.env.cmdline_argv; |
2011 | int argc = session->header.env.nr_cmdline; | 2154 | int argc = session->header.env.nr_cmdline; |
2012 | 2155 | ||
2013 | evlist__for_each(evsel_list, counter) | 2156 | evlist__for_each_entry(evsel_list, counter) |
2014 | perf_stat_process_counter(&stat_config, counter); | 2157 | perf_stat_process_counter(&stat_config, counter); |
2015 | 2158 | ||
2016 | if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL) | 2159 | if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL) |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 2a6cc254ad0c..418ed94756d3 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include "perf.h" | 22 | #include "perf.h" |
23 | 23 | ||
24 | #include "util/annotate.h" | 24 | #include "util/annotate.h" |
25 | #include "util/cache.h" | 25 | #include "util/config.h" |
26 | #include "util/color.h" | 26 | #include "util/color.h" |
27 | #include "util/evlist.h" | 27 | #include "util/evlist.h" |
28 | #include "util/evsel.h" | 28 | #include "util/evsel.h" |
@@ -128,10 +128,14 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he) | |||
128 | return err; | 128 | return err; |
129 | } | 129 | } |
130 | 130 | ||
131 | err = symbol__annotate(sym, map, 0); | 131 | err = symbol__disassemble(sym, map, 0); |
132 | if (err == 0) { | 132 | if (err == 0) { |
133 | out_assign: | 133 | out_assign: |
134 | top->sym_filter_entry = he; | 134 | top->sym_filter_entry = he; |
135 | } else { | ||
136 | char msg[BUFSIZ]; | ||
137 | symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); | ||
138 | pr_err("Couldn't annotate %s: %s\n", sym->name, msg); | ||
135 | } | 139 | } |
136 | 140 | ||
137 | pthread_mutex_unlock(¬es->lock); | 141 | pthread_mutex_unlock(¬es->lock); |
@@ -295,7 +299,7 @@ static void perf_top__print_sym_table(struct perf_top *top) | |||
295 | hists__output_recalc_col_len(hists, top->print_entries - printed); | 299 | hists__output_recalc_col_len(hists, top->print_entries - printed); |
296 | putchar('\n'); | 300 | putchar('\n'); |
297 | hists__fprintf(hists, false, top->print_entries - printed, win_width, | 301 | hists__fprintf(hists, false, top->print_entries - printed, win_width, |
298 | top->min_percent, stdout); | 302 | top->min_percent, stdout, symbol_conf.use_callchain); |
299 | } | 303 | } |
300 | 304 | ||
301 | static void prompt_integer(int *target, const char *msg) | 305 | static void prompt_integer(int *target, const char *msg) |
@@ -479,7 +483,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) | |||
479 | 483 | ||
480 | fprintf(stderr, "\nAvailable events:"); | 484 | fprintf(stderr, "\nAvailable events:"); |
481 | 485 | ||
482 | evlist__for_each(top->evlist, top->sym_evsel) | 486 | evlist__for_each_entry(top->evlist, top->sym_evsel) |
483 | fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel)); | 487 | fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel)); |
484 | 488 | ||
485 | prompt_integer(&counter, "Enter details event counter"); | 489 | prompt_integer(&counter, "Enter details event counter"); |
@@ -490,7 +494,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) | |||
490 | sleep(1); | 494 | sleep(1); |
491 | break; | 495 | break; |
492 | } | 496 | } |
493 | evlist__for_each(top->evlist, top->sym_evsel) | 497 | evlist__for_each_entry(top->evlist, top->sym_evsel) |
494 | if (top->sym_evsel->idx == counter) | 498 | if (top->sym_evsel->idx == counter) |
495 | break; | 499 | break; |
496 | } else | 500 | } else |
@@ -583,7 +587,7 @@ static void *display_thread_tui(void *arg) | |||
583 | * Zooming in/out UIDs. For now juse use whatever the user passed | 587 | * Zooming in/out UIDs. For now juse use whatever the user passed |
584 | * via --uid. | 588 | * via --uid. |
585 | */ | 589 | */ |
586 | evlist__for_each(top->evlist, pos) { | 590 | evlist__for_each_entry(top->evlist, pos) { |
587 | struct hists *hists = evsel__hists(pos); | 591 | struct hists *hists = evsel__hists(pos); |
588 | hists->uid_filter_str = top->record_opts.target.uid_str; | 592 | hists->uid_filter_str = top->record_opts.target.uid_str; |
589 | } | 593 | } |
@@ -888,7 +892,7 @@ static int perf_top__start_counters(struct perf_top *top) | |||
888 | 892 | ||
889 | perf_evlist__config(evlist, opts, &callchain_param); | 893 | perf_evlist__config(evlist, opts, &callchain_param); |
890 | 894 | ||
891 | evlist__for_each(evlist, counter) { | 895 | evlist__for_each_entry(evlist, counter) { |
892 | try_again: | 896 | try_again: |
893 | if (perf_evsel__open(counter, top->evlist->cpus, | 897 | if (perf_evsel__open(counter, top->evlist->cpus, |
894 | top->evlist->threads) < 0) { | 898 | top->evlist->threads) < 0) { |
@@ -907,7 +911,7 @@ try_again: | |||
907 | 911 | ||
908 | if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { | 912 | if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { |
909 | ui__error("Failed to mmap with %d (%s)\n", | 913 | ui__error("Failed to mmap with %d (%s)\n", |
910 | errno, strerror_r(errno, msg, sizeof(msg))); | 914 | errno, str_error_r(errno, msg, sizeof(msg))); |
911 | goto out_err; | 915 | goto out_err; |
912 | } | 916 | } |
913 | 917 | ||
@@ -1028,7 +1032,7 @@ out_delete: | |||
1028 | 1032 | ||
1029 | out_err_cpu_topo: { | 1033 | out_err_cpu_topo: { |
1030 | char errbuf[BUFSIZ]; | 1034 | char errbuf[BUFSIZ]; |
1031 | const char *err = strerror_r(-ret, errbuf, sizeof(errbuf)); | 1035 | const char *err = str_error_r(-ret, errbuf, sizeof(errbuf)); |
1032 | 1036 | ||
1033 | ui__error("Could not read the CPU topology map: %s\n", err); | 1037 | ui__error("Could not read the CPU topology map: %s\n", err); |
1034 | goto out_delete; | 1038 | goto out_delete; |
@@ -1295,7 +1299,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1295 | 1299 | ||
1296 | if (perf_evlist__create_maps(top.evlist, target) < 0) { | 1300 | if (perf_evlist__create_maps(top.evlist, target) < 0) { |
1297 | ui__error("Couldn't create thread/CPU maps: %s\n", | 1301 | ui__error("Couldn't create thread/CPU maps: %s\n", |
1298 | errno == ENOENT ? "No such process" : strerror_r(errno, errbuf, sizeof(errbuf))); | 1302 | errno == ENOENT ? "No such process" : str_error_r(errno, errbuf, sizeof(errbuf))); |
1299 | goto out_delete_evlist; | 1303 | goto out_delete_evlist; |
1300 | } | 1304 | } |
1301 | 1305 | ||
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 5c50fe70d6b3..b8c6766301db 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/err.h> | 43 | #include <linux/err.h> |
44 | #include <linux/filter.h> | 44 | #include <linux/filter.h> |
45 | #include <linux/audit.h> | 45 | #include <linux/audit.h> |
46 | #include <sys/ptrace.h> | ||
47 | #include <linux/random.h> | 46 | #include <linux/random.h> |
48 | #include <linux/stringify.h> | 47 | #include <linux/stringify.h> |
49 | 48 | ||
@@ -334,6 +333,10 @@ static size_t syscall_arg__scnprintf_fd(char *bf, size_t size, | |||
334 | 333 | ||
335 | #define SCA_FD syscall_arg__scnprintf_fd | 334 | #define SCA_FD syscall_arg__scnprintf_fd |
336 | 335 | ||
336 | #ifndef AT_FDCWD | ||
337 | #define AT_FDCWD -100 | ||
338 | #endif | ||
339 | |||
337 | static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size, | 340 | static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size, |
338 | struct syscall_arg *arg) | 341 | struct syscall_arg *arg) |
339 | { | 342 | { |
@@ -1247,7 +1250,7 @@ static int trace__validate_ev_qualifier(struct trace *trace) | |||
1247 | 1250 | ||
1248 | i = 0; | 1251 | i = 0; |
1249 | 1252 | ||
1250 | strlist__for_each(pos, trace->ev_qualifier) { | 1253 | strlist__for_each_entry(pos, trace->ev_qualifier) { |
1251 | const char *sc = pos->s; | 1254 | const char *sc = pos->s; |
1252 | int id = syscalltbl__id(trace->sctbl, sc); | 1255 | int id = syscalltbl__id(trace->sctbl, sc); |
1253 | 1256 | ||
@@ -1601,7 +1604,7 @@ signed_print: | |||
1601 | fprintf(trace->output, ") = %ld", ret); | 1604 | fprintf(trace->output, ") = %ld", ret); |
1602 | } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) { | 1605 | } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) { |
1603 | char bf[STRERR_BUFSIZE]; | 1606 | char bf[STRERR_BUFSIZE]; |
1604 | const char *emsg = strerror_r(-ret, bf, sizeof(bf)), | 1607 | const char *emsg = str_error_r(-ret, bf, sizeof(bf)), |
1605 | *e = audit_errno_to_name(-ret); | 1608 | *e = audit_errno_to_name(-ret); |
1606 | 1609 | ||
1607 | fprintf(trace->output, ") = -1 %s %s", e, emsg); | 1610 | fprintf(trace->output, ") = -1 %s %s", e, emsg); |
@@ -2402,7 +2405,7 @@ out_error_apply_filters: | |||
2402 | fprintf(trace->output, | 2405 | fprintf(trace->output, |
2403 | "Failed to set filter \"%s\" on event %s with %d (%s)\n", | 2406 | "Failed to set filter \"%s\" on event %s with %d (%s)\n", |
2404 | evsel->filter, perf_evsel__name(evsel), errno, | 2407 | evsel->filter, perf_evsel__name(evsel), errno, |
2405 | strerror_r(errno, errbuf, sizeof(errbuf))); | 2408 | str_error_r(errno, errbuf, sizeof(errbuf))); |
2406 | goto out_delete_evlist; | 2409 | goto out_delete_evlist; |
2407 | } | 2410 | } |
2408 | out_error_mem: | 2411 | out_error_mem: |
@@ -2483,7 +2486,7 @@ static int trace__replay(struct trace *trace) | |||
2483 | goto out; | 2486 | goto out; |
2484 | } | 2487 | } |
2485 | 2488 | ||
2486 | evlist__for_each(session->evlist, evsel) { | 2489 | evlist__for_each_entry(session->evlist, evsel) { |
2487 | if (evsel->attr.type == PERF_TYPE_SOFTWARE && | 2490 | if (evsel->attr.type == PERF_TYPE_SOFTWARE && |
2488 | (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ || | 2491 | (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ || |
2489 | evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN || | 2492 | evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN || |
@@ -2550,7 +2553,7 @@ static size_t thread__dump_stats(struct thread_trace *ttrace, | |||
2550 | printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n"); | 2553 | printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n"); |
2551 | printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n"); | 2554 | printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n"); |
2552 | 2555 | ||
2553 | resort_rb__for_each(nd, syscall_stats) { | 2556 | resort_rb__for_each_entry(nd, syscall_stats) { |
2554 | struct stats *stats = syscall_stats_entry->stats; | 2557 | struct stats *stats = syscall_stats_entry->stats; |
2555 | if (stats) { | 2558 | if (stats) { |
2556 | double min = (double)(stats->min) / NSEC_PER_MSEC; | 2559 | double min = (double)(stats->min) / NSEC_PER_MSEC; |
@@ -2627,7 +2630,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) | |||
2627 | return 0; | 2630 | return 0; |
2628 | } | 2631 | } |
2629 | 2632 | ||
2630 | resort_rb__for_each(nd, threads) | 2633 | resort_rb__for_each_entry(nd, threads) |
2631 | printed += trace__fprintf_thread(fp, threads_entry->thread, trace); | 2634 | printed += trace__fprintf_thread(fp, threads_entry->thread, trace); |
2632 | 2635 | ||
2633 | resort_rb__delete(threads); | 2636 | resort_rb__delete(threads); |
@@ -2714,7 +2717,7 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler) | |||
2714 | { | 2717 | { |
2715 | struct perf_evsel *evsel; | 2718 | struct perf_evsel *evsel; |
2716 | 2719 | ||
2717 | evlist__for_each(evlist, evsel) | 2720 | evlist__for_each_entry(evlist, evsel) |
2718 | evsel->handler = handler; | 2721 | evsel->handler = handler; |
2719 | } | 2722 | } |
2720 | 2723 | ||
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c index 3573f315f955..55daefff0d54 100644 --- a/tools/perf/jvmti/jvmti_agent.c +++ b/tools/perf/jvmti/jvmti_agent.c | |||
@@ -59,7 +59,6 @@ static int get_e_machine(struct jitheader *hdr) | |||
59 | ssize_t sret; | 59 | ssize_t sret; |
60 | char id[16]; | 60 | char id[16]; |
61 | int fd, ret = -1; | 61 | int fd, ret = -1; |
62 | int m = -1; | ||
63 | struct { | 62 | struct { |
64 | uint16_t e_type; | 63 | uint16_t e_type; |
65 | uint16_t e_machine; | 64 | uint16_t e_machine; |
@@ -81,11 +80,7 @@ static int get_e_machine(struct jitheader *hdr) | |||
81 | if (sret != sizeof(info)) | 80 | if (sret != sizeof(info)) |
82 | goto error; | 81 | goto error; |
83 | 82 | ||
84 | m = info.e_machine; | 83 | hdr->elf_mach = info.e_machine; |
85 | if (m < 0) | ||
86 | m = 0; /* ELF EM_NONE */ | ||
87 | |||
88 | hdr->elf_mach = m; | ||
89 | ret = 0; | 84 | ret = 0; |
90 | error: | 85 | error: |
91 | close(fd); | 86 | close(fd); |
@@ -491,10 +486,11 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file, | |||
491 | if (sret != 1) | 486 | if (sret != 1) |
492 | goto error; | 487 | goto error; |
493 | } | 488 | } |
494 | if (padding_count) | 489 | if (padding_count) { |
495 | sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp); | 490 | sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp); |
496 | if (sret != 1) | 491 | if (sret != 1) |
497 | goto error; | 492 | goto error; |
493 | } | ||
498 | 494 | ||
499 | funlockfile(fp); | 495 | funlockfile(fp); |
500 | return 0; | 496 | return 0; |
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h index 83a25cef82fd..7ed72a475c57 100644 --- a/tools/perf/perf-sys.h +++ b/tools/perf/perf-sys.h | |||
@@ -5,35 +5,18 @@ | |||
5 | #include <sys/types.h> | 5 | #include <sys/types.h> |
6 | #include <sys/syscall.h> | 6 | #include <sys/syscall.h> |
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | #include <linux/compiler.h> | ||
8 | #include <linux/perf_event.h> | 9 | #include <linux/perf_event.h> |
9 | #include <asm/barrier.h> | 10 | #include <asm/barrier.h> |
10 | 11 | ||
11 | #if defined(__i386__) | 12 | #if defined(__i386__) |
12 | #define cpu_relax() asm volatile("rep; nop" ::: "memory"); | 13 | #define cpu_relax() asm volatile("rep; nop" ::: "memory"); |
13 | #define CPUINFO_PROC {"model name"} | 14 | #define CPUINFO_PROC {"model name"} |
14 | #ifndef __NR_perf_event_open | ||
15 | # define __NR_perf_event_open 336 | ||
16 | #endif | ||
17 | #ifndef __NR_futex | ||
18 | # define __NR_futex 240 | ||
19 | #endif | ||
20 | #ifndef __NR_gettid | ||
21 | # define __NR_gettid 224 | ||
22 | #endif | ||
23 | #endif | 15 | #endif |
24 | 16 | ||
25 | #if defined(__x86_64__) | 17 | #if defined(__x86_64__) |
26 | #define cpu_relax() asm volatile("rep; nop" ::: "memory"); | 18 | #define cpu_relax() asm volatile("rep; nop" ::: "memory"); |
27 | #define CPUINFO_PROC {"model name"} | 19 | #define CPUINFO_PROC {"model name"} |
28 | #ifndef __NR_perf_event_open | ||
29 | # define __NR_perf_event_open 298 | ||
30 | #endif | ||
31 | #ifndef __NR_futex | ||
32 | # define __NR_futex 202 | ||
33 | #endif | ||
34 | #ifndef __NR_gettid | ||
35 | # define __NR_gettid 186 | ||
36 | #endif | ||
37 | #endif | 20 | #endif |
38 | 21 | ||
39 | #ifdef __powerpc__ | 22 | #ifdef __powerpc__ |
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 15982cee5ef3..64c06961bfe4 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | #include "util/env.h" | 11 | #include "util/env.h" |
12 | #include <subcmd/exec-cmd.h> | 12 | #include <subcmd/exec-cmd.h> |
13 | #include "util/cache.h" | 13 | #include "util/config.h" |
14 | #include "util/quote.h" | 14 | #include "util/quote.h" |
15 | #include <subcmd/run-command.h> | 15 | #include <subcmd/run-command.h> |
16 | #include "util/parse-events.h" | 16 | #include "util/parse-events.h" |
@@ -139,8 +139,6 @@ struct option options[] = { | |||
139 | OPT_ARGUMENT("html-path", "html-path"), | 139 | OPT_ARGUMENT("html-path", "html-path"), |
140 | OPT_ARGUMENT("paginate", "paginate"), | 140 | OPT_ARGUMENT("paginate", "paginate"), |
141 | OPT_ARGUMENT("no-pager", "no-pager"), | 141 | OPT_ARGUMENT("no-pager", "no-pager"), |
142 | OPT_ARGUMENT("perf-dir", "perf-dir"), | ||
143 | OPT_ARGUMENT("work-tree", "work-tree"), | ||
144 | OPT_ARGUMENT("debugfs-dir", "debugfs-dir"), | 142 | OPT_ARGUMENT("debugfs-dir", "debugfs-dir"), |
145 | OPT_ARGUMENT("buildid-dir", "buildid-dir"), | 143 | OPT_ARGUMENT("buildid-dir", "buildid-dir"), |
146 | OPT_ARGUMENT("list-cmds", "list-cmds"), | 144 | OPT_ARGUMENT("list-cmds", "list-cmds"), |
@@ -200,35 +198,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) | |||
200 | use_pager = 0; | 198 | use_pager = 0; |
201 | if (envchanged) | 199 | if (envchanged) |
202 | *envchanged = 1; | 200 | *envchanged = 1; |
203 | } else if (!strcmp(cmd, "--perf-dir")) { | ||
204 | if (*argc < 2) { | ||
205 | fprintf(stderr, "No directory given for --perf-dir.\n"); | ||
206 | usage(perf_usage_string); | ||
207 | } | ||
208 | setenv(PERF_DIR_ENVIRONMENT, (*argv)[1], 1); | ||
209 | if (envchanged) | ||
210 | *envchanged = 1; | ||
211 | (*argv)++; | ||
212 | (*argc)--; | ||
213 | handled++; | ||
214 | } else if (!prefixcmp(cmd, CMD_PERF_DIR)) { | ||
215 | setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1); | ||
216 | if (envchanged) | ||
217 | *envchanged = 1; | ||
218 | } else if (!strcmp(cmd, "--work-tree")) { | ||
219 | if (*argc < 2) { | ||
220 | fprintf(stderr, "No directory given for --work-tree.\n"); | ||
221 | usage(perf_usage_string); | ||
222 | } | ||
223 | setenv(PERF_WORK_TREE_ENVIRONMENT, (*argv)[1], 1); | ||
224 | if (envchanged) | ||
225 | *envchanged = 1; | ||
226 | (*argv)++; | ||
227 | (*argc)--; | ||
228 | } else if (!prefixcmp(cmd, CMD_WORK_TREE)) { | ||
229 | setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1); | ||
230 | if (envchanged) | ||
231 | *envchanged = 1; | ||
232 | } else if (!strcmp(cmd, "--debugfs-dir")) { | 201 | } else if (!strcmp(cmd, "--debugfs-dir")) { |
233 | if (*argc < 2) { | 202 | if (*argc < 2) { |
234 | fprintf(stderr, "No directory given for --debugfs-dir.\n"); | 203 | fprintf(stderr, "No directory given for --debugfs-dir.\n"); |
@@ -363,11 +332,6 @@ const char perf_version_string[] = PERF_VERSION; | |||
363 | 332 | ||
364 | #define RUN_SETUP (1<<0) | 333 | #define RUN_SETUP (1<<0) |
365 | #define USE_PAGER (1<<1) | 334 | #define USE_PAGER (1<<1) |
366 | /* | ||
367 | * require working tree to be present -- anything uses this needs | ||
368 | * RUN_SETUP for reading from the configuration file. | ||
369 | */ | ||
370 | #define NEED_WORK_TREE (1<<2) | ||
371 | 335 | ||
372 | static int run_builtin(struct cmd_struct *p, int argc, const char **argv) | 336 | static int run_builtin(struct cmd_struct *p, int argc, const char **argv) |
373 | { | 337 | { |
@@ -391,6 +355,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) | |||
391 | 355 | ||
392 | perf_env__set_cmdline(&perf_env, argc, argv); | 356 | perf_env__set_cmdline(&perf_env, argc, argv); |
393 | status = p->fn(argc, argv, prefix); | 357 | status = p->fn(argc, argv, prefix); |
358 | perf_config__exit(); | ||
394 | exit_browser(status); | 359 | exit_browser(status); |
395 | perf_env__exit(&perf_env); | 360 | perf_env__exit(&perf_env); |
396 | bpf__clear(); | 361 | bpf__clear(); |
@@ -409,7 +374,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) | |||
409 | /* Check for ENOSPC and EIO errors.. */ | 374 | /* Check for ENOSPC and EIO errors.. */ |
410 | if (fflush(stdout)) { | 375 | if (fflush(stdout)) { |
411 | fprintf(stderr, "write failure on standard output: %s", | 376 | fprintf(stderr, "write failure on standard output: %s", |
412 | strerror_r(errno, sbuf, sizeof(sbuf))); | 377 | str_error_r(errno, sbuf, sizeof(sbuf))); |
413 | goto out; | 378 | goto out; |
414 | } | 379 | } |
415 | if (ferror(stdout)) { | 380 | if (ferror(stdout)) { |
@@ -418,7 +383,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) | |||
418 | } | 383 | } |
419 | if (fclose(stdout)) { | 384 | if (fclose(stdout)) { |
420 | fprintf(stderr, "close failed on standard output: %s", | 385 | fprintf(stderr, "close failed on standard output: %s", |
421 | strerror_r(errno, sbuf, sizeof(sbuf))); | 386 | str_error_r(errno, sbuf, sizeof(sbuf))); |
422 | goto out; | 387 | goto out; |
423 | } | 388 | } |
424 | status = 0; | 389 | status = 0; |
@@ -532,6 +497,16 @@ void pthread__unblock_sigwinch(void) | |||
532 | pthread_sigmask(SIG_UNBLOCK, &set, NULL); | 497 | pthread_sigmask(SIG_UNBLOCK, &set, NULL); |
533 | } | 498 | } |
534 | 499 | ||
500 | #ifdef _SC_LEVEL1_DCACHE_LINESIZE | ||
501 | #define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE) | ||
502 | #else | ||
503 | static void cache_line_size(int *cacheline_sizep) | ||
504 | { | ||
505 | if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep)) | ||
506 | pr_debug("cannot determine cache line size"); | ||
507 | } | ||
508 | #endif | ||
509 | |||
535 | int main(int argc, const char **argv) | 510 | int main(int argc, const char **argv) |
536 | { | 511 | { |
537 | const char *cmd; | 512 | const char *cmd; |
@@ -544,7 +519,7 @@ int main(int argc, const char **argv) | |||
544 | 519 | ||
545 | /* The page_size is placed in util object. */ | 520 | /* The page_size is placed in util object. */ |
546 | page_size = sysconf(_SC_PAGE_SIZE); | 521 | page_size = sysconf(_SC_PAGE_SIZE); |
547 | cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); | 522 | cache_line_size(&cacheline_size); |
548 | 523 | ||
549 | if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) | 524 | if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) |
550 | sysctl_perf_event_max_stack = value; | 525 | sysctl_perf_event_max_stack = value; |
@@ -558,6 +533,7 @@ int main(int argc, const char **argv) | |||
558 | 533 | ||
559 | srandom(time(NULL)); | 534 | srandom(time(NULL)); |
560 | 535 | ||
536 | perf_config__init(); | ||
561 | perf_config(perf_default_config, NULL); | 537 | perf_config(perf_default_config, NULL); |
562 | set_buildid_dir(NULL); | 538 | set_buildid_dir(NULL); |
563 | 539 | ||
@@ -649,7 +625,7 @@ int main(int argc, const char **argv) | |||
649 | } | 625 | } |
650 | 626 | ||
651 | fprintf(stderr, "Failed to run command '%s': %s\n", | 627 | fprintf(stderr, "Failed to run command '%s': %s\n", |
652 | cmd, strerror_r(errno, sbuf, sizeof(sbuf))); | 628 | cmd, str_error_r(errno, sbuf, sizeof(sbuf))); |
653 | out: | 629 | out: |
654 | return 1; | 630 | return 1; |
655 | } | 631 | } |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index cd8f1b150f9e..cb0f1356ff81 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -52,6 +52,7 @@ struct record_opts { | |||
52 | bool sample_weight; | 52 | bool sample_weight; |
53 | bool sample_time; | 53 | bool sample_time; |
54 | bool sample_time_set; | 54 | bool sample_time_set; |
55 | bool sample_cpu; | ||
55 | bool period; | 56 | bool period; |
56 | bool running_time; | 57 | bool running_time; |
57 | bool full_auxtrace; | 58 | bool full_auxtrace; |
@@ -59,6 +60,8 @@ struct record_opts { | |||
59 | bool record_switch_events; | 60 | bool record_switch_events; |
60 | bool all_kernel; | 61 | bool all_kernel; |
61 | bool all_user; | 62 | bool all_user; |
63 | bool tail_synthesize; | ||
64 | bool overwrite; | ||
62 | unsigned int freq; | 65 | unsigned int freq; |
63 | unsigned int mmap_pages; | 66 | unsigned int mmap_pages; |
64 | unsigned int auxtrace_mmap_pages; | 67 | unsigned int auxtrace_mmap_pages; |
diff --git a/tools/perf/python/tracepoint.py b/tools/perf/python/tracepoint.py new file mode 100755 index 000000000000..eb4dbed57de7 --- /dev/null +++ b/tools/perf/python/tracepoint.py | |||
@@ -0,0 +1,47 @@ | |||
1 | #! /usr/bin/python | ||
2 | # -*- python -*- | ||
3 | # -*- coding: utf-8 -*- | ||
4 | |||
5 | import perf | ||
6 | |||
7 | class tracepoint(perf.evsel): | ||
8 | def __init__(self, sys, name): | ||
9 | config = perf.tracepoint(sys, name) | ||
10 | perf.evsel.__init__(self, | ||
11 | type = perf.TYPE_TRACEPOINT, | ||
12 | config = config, | ||
13 | freq = 0, sample_period = 1, wakeup_events = 1, | ||
14 | sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_RAW | perf.SAMPLE_TIME) | ||
15 | |||
16 | def main(): | ||
17 | tp = tracepoint("sched", "sched_switch") | ||
18 | cpus = perf.cpu_map() | ||
19 | threads = perf.thread_map(-1) | ||
20 | |||
21 | evlist = perf.evlist(cpus, threads) | ||
22 | evlist.add(tp) | ||
23 | evlist.open() | ||
24 | evlist.mmap() | ||
25 | |||
26 | while True: | ||
27 | evlist.poll(timeout = -1) | ||
28 | for cpu in cpus: | ||
29 | event = evlist.read_on_cpu(cpu) | ||
30 | if not event: | ||
31 | continue | ||
32 | |||
33 | if not isinstance(event, perf.sample_event): | ||
34 | continue | ||
35 | |||
36 | print "time %u prev_comm=%s prev_pid=%d prev_prio=%d prev_state=0x%x ==> next_comm=%s next_pid=%d next_prio=%d" % ( | ||
37 | event.sample_time, | ||
38 | event.prev_comm, | ||
39 | event.prev_pid, | ||
40 | event.prev_prio, | ||
41 | event.prev_state, | ||
42 | event.next_comm, | ||
43 | event.next_pid, | ||
44 | event.next_prio) | ||
45 | |||
46 | if __name__ == '__main__': | ||
47 | main() | ||
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Build b/tools/perf/scripts/perl/Perf-Trace-Util/Build index 928e110179cb..34faecf774ae 100644 --- a/tools/perf/scripts/perl/Perf-Trace-Util/Build +++ b/tools/perf/scripts/perl/Perf-Trace-Util/Build | |||
@@ -1,3 +1,5 @@ | |||
1 | libperf-y += Context.o | 1 | libperf-y += Context.o |
2 | 2 | ||
3 | CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default | 3 | CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes |
4 | CFLAGS_Context.o += -Wno-unused-parameter -Wno-nested-externs -Wno-undef | ||
5 | CFLAGS_Context.o += -Wno-switch-default -Wno-shadow | ||
diff --git a/tools/perf/scripts/python/bin/stackcollapse-record b/tools/perf/scripts/python/bin/stackcollapse-record new file mode 100755 index 000000000000..9d8f9f0f3a17 --- /dev/null +++ b/tools/perf/scripts/python/bin/stackcollapse-record | |||
@@ -0,0 +1,8 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | # | ||
4 | # stackcollapse.py can cover all type of perf samples including | ||
5 | # the tracepoints, so no special record requirements, just record what | ||
6 | # you want to analyze. | ||
7 | # | ||
8 | perf record "$@" | ||
diff --git a/tools/perf/scripts/python/bin/stackcollapse-report b/tools/perf/scripts/python/bin/stackcollapse-report new file mode 100755 index 000000000000..356b9656393d --- /dev/null +++ b/tools/perf/scripts/python/bin/stackcollapse-report | |||
@@ -0,0 +1,3 @@ | |||
1 | #!/bin/sh | ||
2 | # description: produce callgraphs in short form for scripting use | ||
3 | perf script -s "$PERF_EXEC_PATH"/scripts/python/stackcollapse.py -- "$@" | ||
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py index 4d21ef2d601d..4c6f09ac7d12 100644 --- a/tools/perf/scripts/python/netdev-times.py +++ b/tools/perf/scripts/python/netdev-times.py | |||
@@ -252,9 +252,10 @@ def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, i | |||
252 | event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret) | 252 | event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret) |
253 | all_event_list.append(event_info) | 253 | all_event_list.append(event_info) |
254 | 254 | ||
255 | def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name): | 255 | def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, |
256 | dev_name, work=None, budget=None): | ||
256 | event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, | 257 | event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, |
257 | napi, dev_name) | 258 | napi, dev_name, work, budget) |
258 | all_event_list.append(event_info) | 259 | all_event_list.append(event_info) |
259 | 260 | ||
260 | def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, | 261 | def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, |
@@ -354,11 +355,13 @@ def handle_irq_softirq_exit(event_info): | |||
354 | receive_hunk_list.append(rec_data) | 355 | receive_hunk_list.append(rec_data) |
355 | 356 | ||
356 | def handle_napi_poll(event_info): | 357 | def handle_napi_poll(event_info): |
357 | (name, context, cpu, time, pid, comm, napi, dev_name) = event_info | 358 | (name, context, cpu, time, pid, comm, napi, dev_name, |
359 | work, budget) = event_info | ||
358 | if cpu in net_rx_dic.keys(): | 360 | if cpu in net_rx_dic.keys(): |
359 | event_list = net_rx_dic[cpu]['event_list'] | 361 | event_list = net_rx_dic[cpu]['event_list'] |
360 | rec_data = {'event_name':'napi_poll', | 362 | rec_data = {'event_name':'napi_poll', |
361 | 'dev':dev_name, 'event_t':time} | 363 | 'dev':dev_name, 'event_t':time, |
364 | 'work':work, 'budget':budget} | ||
362 | event_list.append(rec_data) | 365 | event_list.append(rec_data) |
363 | 366 | ||
364 | def handle_netif_rx(event_info): | 367 | def handle_netif_rx(event_info): |
diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py new file mode 100755 index 000000000000..5a605f70ef32 --- /dev/null +++ b/tools/perf/scripts/python/stackcollapse.py | |||
@@ -0,0 +1,125 @@ | |||
1 | # stackcollapse.py - format perf samples with one line per distinct call stack | ||
2 | # | ||
3 | # This script's output has two space-separated fields. The first is a semicolon | ||
4 | # separated stack including the program name (from the "comm" field) and the | ||
5 | # function names from the call stack. The second is a count: | ||
6 | # | ||
7 | # swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 2 | ||
8 | # | ||
9 | # The file is sorted according to the first field. | ||
10 | # | ||
11 | # Input may be created and processed using: | ||
12 | # | ||
13 | # perf record -a -g -F 99 sleep 60 | ||
14 | # perf script report stackcollapse > out.stacks-folded | ||
15 | # | ||
16 | # (perf script record stackcollapse works too). | ||
17 | # | ||
18 | # Written by Paolo Bonzini <pbonzini@redhat.com> | ||
19 | # Based on Brendan Gregg's stackcollapse-perf.pl script. | ||
20 | |||
21 | import os | ||
22 | import sys | ||
23 | from collections import defaultdict | ||
24 | from optparse import OptionParser, make_option | ||
25 | |||
26 | sys.path.append(os.environ['PERF_EXEC_PATH'] + \ | ||
27 | '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') | ||
28 | |||
29 | from perf_trace_context import * | ||
30 | from Core import * | ||
31 | from EventClass import * | ||
32 | |||
33 | # command line parsing | ||
34 | |||
35 | option_list = [ | ||
36 | # formatting options for the bottom entry of the stack | ||
37 | make_option("--include-tid", dest="include_tid", | ||
38 | action="store_true", default=False, | ||
39 | help="include thread id in stack"), | ||
40 | make_option("--include-pid", dest="include_pid", | ||
41 | action="store_true", default=False, | ||
42 | help="include process id in stack"), | ||
43 | make_option("--no-comm", dest="include_comm", | ||
44 | action="store_false", default=True, | ||
45 | help="do not separate stacks according to comm"), | ||
46 | make_option("--tidy-java", dest="tidy_java", | ||
47 | action="store_true", default=False, | ||
48 | help="beautify Java signatures"), | ||
49 | make_option("--kernel", dest="annotate_kernel", | ||
50 | action="store_true", default=False, | ||
51 | help="annotate kernel functions with _[k]") | ||
52 | ] | ||
53 | |||
54 | parser = OptionParser(option_list=option_list) | ||
55 | (opts, args) = parser.parse_args() | ||
56 | |||
57 | if len(args) != 0: | ||
58 | parser.error("unexpected command line argument") | ||
59 | if opts.include_tid and not opts.include_comm: | ||
60 | parser.error("requesting tid but not comm is invalid") | ||
61 | if opts.include_pid and not opts.include_comm: | ||
62 | parser.error("requesting pid but not comm is invalid") | ||
63 | |||
64 | # event handlers | ||
65 | |||
66 | lines = defaultdict(lambda: 0) | ||
67 | |||
68 | def process_event(param_dict): | ||
69 | def tidy_function_name(sym, dso): | ||
70 | if sym is None: | ||
71 | sym = '[unknown]' | ||
72 | |||
73 | sym = sym.replace(';', ':') | ||
74 | if opts.tidy_java: | ||
75 | # the original stackcollapse-perf.pl script gives the | ||
76 | # example of converting this: | ||
77 | # Lorg/mozilla/javascript/MemberBox;.<init>(Ljava/lang/reflect/Method;)V | ||
78 | # to this: | ||
79 | # org/mozilla/javascript/MemberBox:.init | ||
80 | sym = sym.replace('<', '') | ||
81 | sym = sym.replace('>', '') | ||
82 | if sym[0] == 'L' and sym.find('/'): | ||
83 | sym = sym[1:] | ||
84 | try: | ||
85 | sym = sym[:sym.index('(')] | ||
86 | except ValueError: | ||
87 | pass | ||
88 | |||
89 | if opts.annotate_kernel and dso == '[kernel.kallsyms]': | ||
90 | return sym + '_[k]' | ||
91 | else: | ||
92 | return sym | ||
93 | |||
94 | stack = list() | ||
95 | if 'callchain' in param_dict: | ||
96 | for entry in param_dict['callchain']: | ||
97 | entry.setdefault('sym', dict()) | ||
98 | entry['sym'].setdefault('name', None) | ||
99 | entry.setdefault('dso', None) | ||
100 | stack.append(tidy_function_name(entry['sym']['name'], | ||
101 | entry['dso'])) | ||
102 | else: | ||
103 | param_dict.setdefault('symbol', None) | ||
104 | param_dict.setdefault('dso', None) | ||
105 | stack.append(tidy_function_name(param_dict['symbol'], | ||
106 | param_dict['dso'])) | ||
107 | |||
108 | if opts.include_comm: | ||
109 | comm = param_dict["comm"].replace(' ', '_') | ||
110 | sep = "-" | ||
111 | if opts.include_pid: | ||
112 | comm = comm + sep + str(param_dict['sample']['pid']) | ||
113 | sep = "/" | ||
114 | if opts.include_tid: | ||
115 | comm = comm + sep + str(param_dict['sample']['tid']) | ||
116 | stack.append(comm) | ||
117 | |||
118 | stack_string = ';'.join(reversed(stack)) | ||
119 | lines[stack_string] = lines[stack_string] + 1 | ||
120 | |||
121 | def trace_end(): | ||
122 | list = lines.keys() | ||
123 | list.sort() | ||
124 | for stack in list: | ||
125 | print "%s %d" % (stack, lines[stack]) | ||
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 66a28982547b..dc51bc570e51 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build | |||
@@ -39,6 +39,9 @@ perf-y += stat.o | |||
39 | perf-y += event_update.o | 39 | perf-y += event_update.o |
40 | perf-y += event-times.o | 40 | perf-y += event-times.o |
41 | perf-y += backward-ring-buffer.o | 41 | perf-y += backward-ring-buffer.o |
42 | perf-y += sdt.o | ||
43 | perf-y += is_printable_array.o | ||
44 | perf-y += bitmap.o | ||
42 | 45 | ||
43 | $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build | 46 | $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build |
44 | $(call rule_mkdir) | 47 | $(call rule_mkdir) |
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index d9ba991a9a30..615780cbfe1d 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c | |||
@@ -31,8 +31,8 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count, | |||
31 | for (i = 0; i < evlist->nr_mmaps; i++) { | 31 | for (i = 0; i < evlist->nr_mmaps; i++) { |
32 | union perf_event *event; | 32 | union perf_event *event; |
33 | 33 | ||
34 | perf_evlist__mmap_read_catchup(evlist, i); | 34 | perf_mmap__read_catchup(&evlist->backward_mmap[i]); |
35 | while ((event = perf_evlist__mmap_read_backward(evlist, i)) != NULL) { | 35 | while ((event = perf_mmap__read_backward(&evlist->backward_mmap[i])) != NULL) { |
36 | const u32 type = event->header.type; | 36 | const u32 type = event->header.type; |
37 | 37 | ||
38 | switch (type) { | 38 | switch (type) { |
@@ -60,7 +60,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages, | |||
60 | err = perf_evlist__mmap(evlist, mmap_pages, true); | 60 | err = perf_evlist__mmap(evlist, mmap_pages, true); |
61 | if (err < 0) { | 61 | if (err < 0) { |
62 | pr_debug("perf_evlist__mmap: %s\n", | 62 | pr_debug("perf_evlist__mmap: %s\n", |
63 | strerror_r(errno, sbuf, sizeof(sbuf))); | 63 | str_error_r(errno, sbuf, sizeof(sbuf))); |
64 | return TEST_FAIL; | 64 | return TEST_FAIL; |
65 | } | 65 | } |
66 | 66 | ||
@@ -108,7 +108,11 @@ int test__backward_ring_buffer(int subtest __maybe_unused) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | bzero(&parse_error, sizeof(parse_error)); | 110 | bzero(&parse_error, sizeof(parse_error)); |
111 | err = parse_events(evlist, "syscalls:sys_enter_prctl", &parse_error); | 111 | /* |
112 | * Set backward bit, ring buffer should be writing from end. Record | ||
113 | * it in aux evlist | ||
114 | */ | ||
115 | err = parse_events(evlist, "syscalls:sys_enter_prctl/overwrite/", &parse_error); | ||
112 | if (err) { | 116 | if (err) { |
113 | pr_debug("Failed to parse tracepoint event, try use root\n"); | 117 | pr_debug("Failed to parse tracepoint event, try use root\n"); |
114 | ret = TEST_SKIP; | 118 | ret = TEST_SKIP; |
@@ -117,14 +121,10 @@ int test__backward_ring_buffer(int subtest __maybe_unused) | |||
117 | 121 | ||
118 | perf_evlist__config(evlist, &opts, NULL); | 122 | perf_evlist__config(evlist, &opts, NULL); |
119 | 123 | ||
120 | /* Set backward bit, ring buffer should be writing from end */ | ||
121 | evlist__for_each(evlist, evsel) | ||
122 | evsel->attr.write_backward = 1; | ||
123 | |||
124 | err = perf_evlist__open(evlist); | 124 | err = perf_evlist__open(evlist); |
125 | if (err < 0) { | 125 | if (err < 0) { |
126 | pr_debug("perf_evlist__open: %s\n", | 126 | pr_debug("perf_evlist__open: %s\n", |
127 | strerror_r(errno, sbuf, sizeof(sbuf))); | 127 | str_error_r(errno, sbuf, sizeof(sbuf))); |
128 | goto out_delete_evlist; | 128 | goto out_delete_evlist; |
129 | } | 129 | } |
130 | 130 | ||
diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c new file mode 100644 index 000000000000..9abe6c13090f --- /dev/null +++ b/tools/perf/tests/bitmap.c | |||
@@ -0,0 +1,53 @@ | |||
1 | #include <linux/compiler.h> | ||
2 | #include <linux/bitmap.h> | ||
3 | #include "tests.h" | ||
4 | #include "cpumap.h" | ||
5 | #include "debug.h" | ||
6 | |||
7 | #define NBITS 100 | ||
8 | |||
9 | static unsigned long *get_bitmap(const char *str, int nbits) | ||
10 | { | ||
11 | struct cpu_map *map = cpu_map__new(str); | ||
12 | unsigned long *bm = NULL; | ||
13 | int i; | ||
14 | |||
15 | bm = bitmap_alloc(nbits); | ||
16 | |||
17 | if (map && bm) { | ||
18 | bitmap_zero(bm, nbits); | ||
19 | |||
20 | for (i = 0; i < map->nr; i++) | ||
21 | set_bit(map->map[i], bm); | ||
22 | } | ||
23 | |||
24 | if (map) | ||
25 | cpu_map__put(map); | ||
26 | return bm; | ||
27 | } | ||
28 | |||
29 | static int test_bitmap(const char *str) | ||
30 | { | ||
31 | unsigned long *bm = get_bitmap(str, NBITS); | ||
32 | char buf[100]; | ||
33 | int ret; | ||
34 | |||
35 | bitmap_scnprintf(bm, NBITS, buf, sizeof(buf)); | ||
36 | pr_debug("bitmap: %s\n", buf); | ||
37 | |||
38 | ret = !strcmp(buf, str); | ||
39 | free(bm); | ||
40 | return ret; | ||
41 | } | ||
42 | |||
43 | int test__bitmap_print(int subtest __maybe_unused) | ||
44 | { | ||
45 | TEST_ASSERT_VAL("failed to convert map", test_bitmap("1")); | ||
46 | TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,5")); | ||
47 | TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3,5,7,9,11,13,15,17,19,21-40")); | ||
48 | TEST_ASSERT_VAL("failed to convert map", test_bitmap("2-5")); | ||
49 | TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37")); | ||
50 | TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37")); | ||
51 | TEST_ASSERT_VAL("failed to convert map", test_bitmap("1-10,12-20,22-30,32-40")); | ||
52 | return 0; | ||
53 | } | ||
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c index 0ec9c2c03164..268e5f8e4aa2 100644 --- a/tools/perf/tests/bpf-script-example.c +++ b/tools/perf/tests/bpf-script-example.c | |||
@@ -31,8 +31,8 @@ struct bpf_map_def SEC("maps") flip_table = { | |||
31 | .max_entries = 1, | 31 | .max_entries = 1, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | SEC("func=sys_epoll_pwait") | 34 | SEC("func=SyS_epoll_wait") |
35 | int bpf_func__sys_epoll_pwait(void *ctx) | 35 | int bpf_func__SyS_epoll_wait(void *ctx) |
36 | { | 36 | { |
37 | int ind =0; | 37 | int ind =0; |
38 | int *flag = bpf_map_lookup_elem(&flip_table, &ind); | 38 | int *flag = bpf_map_lookup_elem(&flip_table, &ind); |
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index f31eed31c1a9..fc54064b9186 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c | |||
@@ -13,13 +13,13 @@ | |||
13 | 13 | ||
14 | #ifdef HAVE_LIBBPF_SUPPORT | 14 | #ifdef HAVE_LIBBPF_SUPPORT |
15 | 15 | ||
16 | static int epoll_pwait_loop(void) | 16 | static int epoll_wait_loop(void) |
17 | { | 17 | { |
18 | int i; | 18 | int i; |
19 | 19 | ||
20 | /* Should fail NR_ITERS times */ | 20 | /* Should fail NR_ITERS times */ |
21 | for (i = 0; i < NR_ITERS; i++) | 21 | for (i = 0; i < NR_ITERS; i++) |
22 | epoll_pwait(-(i + 1), NULL, 0, 0, NULL); | 22 | epoll_wait(-(i + 1), NULL, 0, 0); |
23 | return 0; | 23 | return 0; |
24 | } | 24 | } |
25 | 25 | ||
@@ -61,7 +61,7 @@ static struct { | |||
61 | "[basic_bpf_test]", | 61 | "[basic_bpf_test]", |
62 | "fix 'perf test LLVM' first", | 62 | "fix 'perf test LLVM' first", |
63 | "load bpf object failed", | 63 | "load bpf object failed", |
64 | &epoll_pwait_loop, | 64 | &epoll_wait_loop, |
65 | (NR_ITERS + 1) / 2, | 65 | (NR_ITERS + 1) / 2, |
66 | }, | 66 | }, |
67 | #ifdef HAVE_BPF_PROLOGUE | 67 | #ifdef HAVE_BPF_PROLOGUE |
@@ -143,14 +143,14 @@ static int do_test(struct bpf_object *obj, int (*func)(void), | |||
143 | err = perf_evlist__open(evlist); | 143 | err = perf_evlist__open(evlist); |
144 | if (err < 0) { | 144 | if (err < 0) { |
145 | pr_debug("perf_evlist__open: %s\n", | 145 | pr_debug("perf_evlist__open: %s\n", |
146 | strerror_r(errno, sbuf, sizeof(sbuf))); | 146 | str_error_r(errno, sbuf, sizeof(sbuf))); |
147 | goto out_delete_evlist; | 147 | goto out_delete_evlist; |
148 | } | 148 | } |
149 | 149 | ||
150 | err = perf_evlist__mmap(evlist, opts.mmap_pages, false); | 150 | err = perf_evlist__mmap(evlist, opts.mmap_pages, false); |
151 | if (err < 0) { | 151 | if (err < 0) { |
152 | pr_debug("perf_evlist__mmap: %s\n", | 152 | pr_debug("perf_evlist__mmap: %s\n", |
153 | strerror_r(errno, sbuf, sizeof(sbuf))); | 153 | str_error_r(errno, sbuf, sizeof(sbuf))); |
154 | goto out_delete_evlist; | 154 | goto out_delete_evlist; |
155 | } | 155 | } |
156 | 156 | ||
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 0e95c20ecf6e..778668a2a966 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <subcmd/parse-options.h> | 14 | #include <subcmd/parse-options.h> |
15 | #include "symbol.h" | 15 | #include "symbol.h" |
16 | 16 | ||
17 | static bool dont_fork; | ||
18 | |||
17 | struct test __weak arch_tests[] = { | 19 | struct test __weak arch_tests[] = { |
18 | { | 20 | { |
19 | .func = NULL, | 21 | .func = NULL, |
@@ -212,6 +214,22 @@ static struct test generic_tests[] = { | |||
212 | .func = test__backward_ring_buffer, | 214 | .func = test__backward_ring_buffer, |
213 | }, | 215 | }, |
214 | { | 216 | { |
217 | .desc = "Test cpu map print", | ||
218 | .func = test__cpu_map_print, | ||
219 | }, | ||
220 | { | ||
221 | .desc = "Test SDT event probing", | ||
222 | .func = test__sdt_event, | ||
223 | }, | ||
224 | { | ||
225 | .desc = "Test is_printable_array function", | ||
226 | .func = test__is_printable_array, | ||
227 | }, | ||
228 | { | ||
229 | .desc = "Test bitmap print", | ||
230 | .func = test__bitmap_print, | ||
231 | }, | ||
232 | { | ||
215 | .func = NULL, | 233 | .func = NULL, |
216 | }, | 234 | }, |
217 | }; | 235 | }; |
@@ -247,44 +265,51 @@ static bool perf_test__matches(struct test *test, int curr, int argc, const char | |||
247 | 265 | ||
248 | static int run_test(struct test *test, int subtest) | 266 | static int run_test(struct test *test, int subtest) |
249 | { | 267 | { |
250 | int status, err = -1, child = fork(); | 268 | int status, err = -1, child = dont_fork ? 0 : fork(); |
251 | char sbuf[STRERR_BUFSIZE]; | 269 | char sbuf[STRERR_BUFSIZE]; |
252 | 270 | ||
253 | if (child < 0) { | 271 | if (child < 0) { |
254 | pr_err("failed to fork test: %s\n", | 272 | pr_err("failed to fork test: %s\n", |
255 | strerror_r(errno, sbuf, sizeof(sbuf))); | 273 | str_error_r(errno, sbuf, sizeof(sbuf))); |
256 | return -1; | 274 | return -1; |
257 | } | 275 | } |
258 | 276 | ||
259 | if (!child) { | 277 | if (!child) { |
260 | pr_debug("test child forked, pid %d\n", getpid()); | 278 | if (!dont_fork) { |
261 | if (!verbose) { | 279 | pr_debug("test child forked, pid %d\n", getpid()); |
262 | int nullfd = open("/dev/null", O_WRONLY); | 280 | |
263 | if (nullfd >= 0) { | 281 | if (!verbose) { |
264 | close(STDERR_FILENO); | 282 | int nullfd = open("/dev/null", O_WRONLY); |
265 | close(STDOUT_FILENO); | 283 | |
266 | 284 | if (nullfd >= 0) { | |
267 | dup2(nullfd, STDOUT_FILENO); | 285 | close(STDERR_FILENO); |
268 | dup2(STDOUT_FILENO, STDERR_FILENO); | 286 | close(STDOUT_FILENO); |
269 | close(nullfd); | 287 | |
288 | dup2(nullfd, STDOUT_FILENO); | ||
289 | dup2(STDOUT_FILENO, STDERR_FILENO); | ||
290 | close(nullfd); | ||
291 | } | ||
292 | } else { | ||
293 | signal(SIGSEGV, sighandler_dump_stack); | ||
294 | signal(SIGFPE, sighandler_dump_stack); | ||
270 | } | 295 | } |
271 | } else { | ||
272 | signal(SIGSEGV, sighandler_dump_stack); | ||
273 | signal(SIGFPE, sighandler_dump_stack); | ||
274 | } | 296 | } |
275 | 297 | ||
276 | err = test->func(subtest); | 298 | err = test->func(subtest); |
277 | exit(err); | 299 | if (!dont_fork) |
300 | exit(err); | ||
278 | } | 301 | } |
279 | 302 | ||
280 | wait(&status); | 303 | if (!dont_fork) { |
304 | wait(&status); | ||
281 | 305 | ||
282 | if (WIFEXITED(status)) { | 306 | if (WIFEXITED(status)) { |
283 | err = (signed char)WEXITSTATUS(status); | 307 | err = (signed char)WEXITSTATUS(status); |
284 | pr_debug("test child finished with %d\n", err); | 308 | pr_debug("test child finished with %d\n", err); |
285 | } else if (WIFSIGNALED(status)) { | 309 | } else if (WIFSIGNALED(status)) { |
286 | err = -1; | 310 | err = -1; |
287 | pr_debug("test child interrupted\n"); | 311 | pr_debug("test child interrupted\n"); |
312 | } | ||
288 | } | 313 | } |
289 | 314 | ||
290 | return err; | 315 | return err; |
@@ -425,6 +450,8 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) | |||
425 | OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), | 450 | OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), |
426 | OPT_INCR('v', "verbose", &verbose, | 451 | OPT_INCR('v', "verbose", &verbose, |
427 | "be more verbose (show symbol address, etc)"), | 452 | "be more verbose (show symbol address, etc)"), |
453 | OPT_BOOLEAN('F', "dont-fork", &dont_fork, | ||
454 | "Do not fork for testcase"), | ||
428 | OPT_END() | 455 | OPT_END() |
429 | }; | 456 | }; |
430 | const char * const test_subcommands[] = { "list", NULL }; | 457 | const char * const test_subcommands[] = { "list", NULL }; |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 68a69a195545..2af156a8d4e5 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -33,44 +33,86 @@ static unsigned int hex(char c) | |||
33 | return c - 'A' + 10; | 33 | return c - 'A' + 10; |
34 | } | 34 | } |
35 | 35 | ||
36 | static size_t read_objdump_line(const char *line, size_t line_len, void *buf, | 36 | static size_t read_objdump_chunk(const char **line, unsigned char **buf, |
37 | size_t len) | 37 | size_t *buf_len) |
38 | { | 38 | { |
39 | const char *p; | 39 | size_t bytes_read = 0; |
40 | size_t i, j = 0; | 40 | unsigned char *chunk_start = *buf; |
41 | |||
42 | /* Skip to a colon */ | ||
43 | p = strchr(line, ':'); | ||
44 | if (!p) | ||
45 | return 0; | ||
46 | i = p + 1 - line; | ||
47 | 41 | ||
48 | /* Read bytes */ | 42 | /* Read bytes */ |
49 | while (j < len) { | 43 | while (*buf_len > 0) { |
50 | char c1, c2; | 44 | char c1, c2; |
51 | 45 | ||
52 | /* Skip spaces */ | ||
53 | for (; i < line_len; i++) { | ||
54 | if (!isspace(line[i])) | ||
55 | break; | ||
56 | } | ||
57 | /* Get 2 hex digits */ | 46 | /* Get 2 hex digits */ |
58 | if (i >= line_len || !isxdigit(line[i])) | 47 | c1 = *(*line)++; |
48 | if (!isxdigit(c1)) | ||
59 | break; | 49 | break; |
60 | c1 = line[i++]; | 50 | c2 = *(*line)++; |
61 | if (i >= line_len || !isxdigit(line[i])) | 51 | if (!isxdigit(c2)) |
62 | break; | 52 | break; |
63 | c2 = line[i++]; | 53 | |
64 | /* Followed by a space */ | 54 | /* Store byte and advance buf */ |
65 | if (i < line_len && line[i] && !isspace(line[i])) | 55 | **buf = (hex(c1) << 4) | hex(c2); |
56 | (*buf)++; | ||
57 | (*buf_len)--; | ||
58 | bytes_read++; | ||
59 | |||
60 | /* End of chunk? */ | ||
61 | if (isspace(**line)) | ||
66 | break; | 62 | break; |
67 | /* Store byte */ | ||
68 | *(unsigned char *)buf = (hex(c1) << 4) | hex(c2); | ||
69 | buf += 1; | ||
70 | j++; | ||
71 | } | 63 | } |
64 | |||
65 | /* | ||
66 | * objdump will display raw insn as LE if code endian | ||
67 | * is LE and bytes_per_chunk > 1. In that case reverse | ||
68 | * the chunk we just read. | ||
69 | * | ||
70 | * see disassemble_bytes() at binutils/objdump.c for details | ||
71 | * how objdump chooses display endian) | ||
72 | */ | ||
73 | if (bytes_read > 1 && !bigendian()) { | ||
74 | unsigned char *chunk_end = chunk_start + bytes_read - 1; | ||
75 | unsigned char tmp; | ||
76 | |||
77 | while (chunk_start < chunk_end) { | ||
78 | tmp = *chunk_start; | ||
79 | *chunk_start = *chunk_end; | ||
80 | *chunk_end = tmp; | ||
81 | chunk_start++; | ||
82 | chunk_end--; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | return bytes_read; | ||
87 | } | ||
88 | |||
89 | static size_t read_objdump_line(const char *line, unsigned char *buf, | ||
90 | size_t buf_len) | ||
91 | { | ||
92 | const char *p; | ||
93 | size_t ret, bytes_read = 0; | ||
94 | |||
95 | /* Skip to a colon */ | ||
96 | p = strchr(line, ':'); | ||
97 | if (!p) | ||
98 | return 0; | ||
99 | p++; | ||
100 | |||
101 | /* Skip initial spaces */ | ||
102 | while (*p) { | ||
103 | if (!isspace(*p)) | ||
104 | break; | ||
105 | p++; | ||
106 | } | ||
107 | |||
108 | do { | ||
109 | ret = read_objdump_chunk(&p, &buf, &buf_len); | ||
110 | bytes_read += ret; | ||
111 | p++; | ||
112 | } while (ret > 0); | ||
113 | |||
72 | /* return number of successfully read bytes */ | 114 | /* return number of successfully read bytes */ |
73 | return j; | 115 | return bytes_read; |
74 | } | 116 | } |
75 | 117 | ||
76 | static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr) | 118 | static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr) |
@@ -95,7 +137,7 @@ static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr) | |||
95 | } | 137 | } |
96 | 138 | ||
97 | /* read objdump data into temporary buffer */ | 139 | /* read objdump data into temporary buffer */ |
98 | read_bytes = read_objdump_line(line, ret, tmp, sizeof(tmp)); | 140 | read_bytes = read_objdump_line(line, tmp, sizeof(tmp)); |
99 | if (!read_bytes) | 141 | if (!read_bytes) |
100 | continue; | 142 | continue; |
101 | 143 | ||
@@ -152,7 +194,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf, | |||
152 | 194 | ||
153 | ret = read_objdump_output(f, buf, &len, addr); | 195 | ret = read_objdump_output(f, buf, &len, addr); |
154 | if (len) { | 196 | if (len) { |
155 | pr_debug("objdump read too few bytes\n"); | 197 | pr_debug("objdump read too few bytes: %zd\n", len); |
156 | if (!ret) | 198 | if (!ret) |
157 | ret = len; | 199 | ret = len; |
158 | } | 200 | } |
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c index 4cb6418a8ffc..f168a85992d0 100644 --- a/tools/perf/tests/cpumap.c +++ b/tools/perf/tests/cpumap.c | |||
@@ -1,5 +1,12 @@ | |||
1 | #include "tests.h" | 1 | #include "tests.h" |
2 | #include <stdio.h> | ||
2 | #include "cpumap.h" | 3 | #include "cpumap.h" |
4 | #include "event.h" | ||
5 | #include <string.h> | ||
6 | #include <linux/bitops.h> | ||
7 | #include "debug.h" | ||
8 | |||
9 | struct machine; | ||
3 | 10 | ||
4 | static int process_event_mask(struct perf_tool *tool __maybe_unused, | 11 | static int process_event_mask(struct perf_tool *tool __maybe_unused, |
5 | union perf_event *event, | 12 | union perf_event *event, |
@@ -86,3 +93,27 @@ int test__cpu_map_synthesize(int subtest __maybe_unused) | |||
86 | cpu_map__put(cpus); | 93 | cpu_map__put(cpus); |
87 | return 0; | 94 | return 0; |
88 | } | 95 | } |
96 | |||
97 | static int cpu_map_print(const char *str) | ||
98 | { | ||
99 | struct cpu_map *map = cpu_map__new(str); | ||
100 | char buf[100]; | ||
101 | |||
102 | if (!map) | ||
103 | return -1; | ||
104 | |||
105 | cpu_map__snprint(map, buf, sizeof(buf)); | ||
106 | return !strcmp(buf, str); | ||
107 | } | ||
108 | |||
109 | int test__cpu_map_print(int subtest __maybe_unused) | ||
110 | { | ||
111 | TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1")); | ||
112 | TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,5")); | ||
113 | TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,3,5,7,9,11,13,15,17,19,21-40")); | ||
114 | TEST_ASSERT_VAL("failed to convert map", cpu_map_print("2-5")); | ||
115 | TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,3-6,8-10,24,35-37")); | ||
116 | TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,3-6,8-10,24,35-37")); | ||
117 | TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1-10,12-20,22-30,32-40")); | ||
118 | return 0; | ||
119 | } | ||
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c index 8cf0d9e189a8..13725e09ba22 100644 --- a/tools/perf/tests/dso-data.c +++ b/tools/perf/tests/dso-data.c | |||
@@ -251,6 +251,9 @@ int test__dso_data_cache(int subtest __maybe_unused) | |||
251 | long nr_end, nr = open_files_cnt(); | 251 | long nr_end, nr = open_files_cnt(); |
252 | int dso_cnt, limit, i, fd; | 252 | int dso_cnt, limit, i, fd; |
253 | 253 | ||
254 | /* Rest the internal dso open counter limit. */ | ||
255 | reset_fd_limit(); | ||
256 | |||
254 | memset(&machine, 0, sizeof(machine)); | 257 | memset(&machine, 0, sizeof(machine)); |
255 | 258 | ||
256 | /* set as system limit */ | 259 | /* set as system limit */ |
@@ -312,6 +315,9 @@ int test__dso_data_reopen(int subtest __maybe_unused) | |||
312 | #define dso_1 (dsos[1]) | 315 | #define dso_1 (dsos[1]) |
313 | #define dso_2 (dsos[2]) | 316 | #define dso_2 (dsos[2]) |
314 | 317 | ||
318 | /* Rest the internal dso open counter limit. */ | ||
319 | reset_fd_limit(); | ||
320 | |||
315 | memset(&machine, 0, sizeof(machine)); | 321 | memset(&machine, 0, sizeof(machine)); |
316 | 322 | ||
317 | /* | 323 | /* |
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index 95fb744f6628..19ef77bd6eb4 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c | |||
@@ -37,7 +37,7 @@ static int attach__enable_on_exec(struct perf_evlist *evlist) | |||
37 | err = perf_evlist__open(evlist); | 37 | err = perf_evlist__open(evlist); |
38 | if (err < 0) { | 38 | if (err < 0) { |
39 | pr_debug("perf_evlist__open: %s\n", | 39 | pr_debug("perf_evlist__open: %s\n", |
40 | strerror_r(errno, sbuf, sizeof(sbuf))); | 40 | str_error_r(errno, sbuf, sizeof(sbuf))); |
41 | return err; | 41 | return err; |
42 | } | 42 | } |
43 | 43 | ||
@@ -200,8 +200,7 @@ static int test_times(int (attach)(struct perf_evlist *), | |||
200 | count.ena, count.run); | 200 | count.ena, count.run); |
201 | 201 | ||
202 | out_err: | 202 | out_err: |
203 | if (evlist) | 203 | perf_evlist__delete(evlist); |
204 | perf_evlist__delete(evlist); | ||
205 | return !err ? TEST_OK : TEST_FAIL; | 204 | return !err ? TEST_OK : TEST_FAIL; |
206 | } | 205 | } |
207 | 206 | ||
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c index 2de4a4f2c3ed..60926a1f6fd7 100644 --- a/tools/perf/tests/evsel-roundtrip-name.c +++ b/tools/perf/tests/evsel-roundtrip-name.c | |||
@@ -80,7 +80,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names) | |||
80 | } | 80 | } |
81 | 81 | ||
82 | err = 0; | 82 | err = 0; |
83 | evlist__for_each(evlist, evsel) { | 83 | evlist__for_each_entry(evlist, evsel) { |
84 | if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { | 84 | if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { |
85 | --err; | 85 | --err; |
86 | pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); | 86 | pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); |
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c index c809463edbe5..a2b5ff9bf83d 100644 --- a/tools/perf/tests/fdarray.c +++ b/tools/perf/tests/fdarray.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <api/fd/array.h> | 1 | #include <api/fd/array.h> |
2 | #include <poll.h> | ||
2 | #include "util/debug.h" | 3 | #include "util/debug.h" |
3 | #include "tests/tests.h" | 4 | #include "tests/tests.h" |
4 | 5 | ||
@@ -36,7 +37,7 @@ int test__fdarray__filter(int subtest __maybe_unused) | |||
36 | } | 37 | } |
37 | 38 | ||
38 | fdarray__init_revents(fda, POLLIN); | 39 | fdarray__init_revents(fda, POLLIN); |
39 | nr_fds = fdarray__filter(fda, POLLHUP, NULL); | 40 | nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); |
40 | if (nr_fds != fda->nr_alloc) { | 41 | if (nr_fds != fda->nr_alloc) { |
41 | pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything", | 42 | pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything", |
42 | nr_fds, fda->nr_alloc); | 43 | nr_fds, fda->nr_alloc); |
@@ -44,7 +45,7 @@ int test__fdarray__filter(int subtest __maybe_unused) | |||
44 | } | 45 | } |
45 | 46 | ||
46 | fdarray__init_revents(fda, POLLHUP); | 47 | fdarray__init_revents(fda, POLLHUP); |
47 | nr_fds = fdarray__filter(fda, POLLHUP, NULL); | 48 | nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); |
48 | if (nr_fds != 0) { | 49 | if (nr_fds != 0) { |
49 | pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds", | 50 | pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds", |
50 | nr_fds, fda->nr_alloc); | 51 | nr_fds, fda->nr_alloc); |
@@ -57,7 +58,7 @@ int test__fdarray__filter(int subtest __maybe_unused) | |||
57 | 58 | ||
58 | pr_debug("\nfiltering all but fda->entries[2]:"); | 59 | pr_debug("\nfiltering all but fda->entries[2]:"); |
59 | fdarray__fprintf_prefix(fda, "before", stderr); | 60 | fdarray__fprintf_prefix(fda, "before", stderr); |
60 | nr_fds = fdarray__filter(fda, POLLHUP, NULL); | 61 | nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); |
61 | fdarray__fprintf_prefix(fda, " after", stderr); | 62 | fdarray__fprintf_prefix(fda, " after", stderr); |
62 | if (nr_fds != 1) { | 63 | if (nr_fds != 1) { |
63 | pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds); | 64 | pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds); |
@@ -78,7 +79,7 @@ int test__fdarray__filter(int subtest __maybe_unused) | |||
78 | 79 | ||
79 | pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):"); | 80 | pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):"); |
80 | fdarray__fprintf_prefix(fda, "before", stderr); | 81 | fdarray__fprintf_prefix(fda, "before", stderr); |
81 | nr_fds = fdarray__filter(fda, POLLHUP, NULL); | 82 | nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); |
82 | fdarray__fprintf_prefix(fda, " after", stderr); | 83 | fdarray__fprintf_prefix(fda, " after", stderr); |
83 | if (nr_fds != 2) { | 84 | if (nr_fds != 2) { |
84 | pr_debug("\nfdarray__filter()=%d != 2, should have left just two events", | 85 | pr_debug("\nfdarray__filter()=%d != 2, should have left just two events", |
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index a9e3db3afac4..9fd54b79a788 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c | |||
@@ -216,6 +216,8 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec | |||
216 | 216 | ||
217 | /* check callchain entries */ | 217 | /* check callchain entries */ |
218 | root = &he->callchain->node.rb_root; | 218 | root = &he->callchain->node.rb_root; |
219 | |||
220 | TEST_ASSERT_VAL("callchains expected", !RB_EMPTY_ROOT(root)); | ||
219 | cnode = rb_entry(rb_first(root), struct callchain_node, rb_node); | 221 | cnode = rb_entry(rb_first(root), struct callchain_node, rb_node); |
220 | 222 | ||
221 | c = 0; | 223 | c = 0; |
@@ -666,6 +668,8 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) | |||
666 | perf_evsel__set_sample_bit(evsel, CALLCHAIN); | 668 | perf_evsel__set_sample_bit(evsel, CALLCHAIN); |
667 | 669 | ||
668 | setup_sorting(NULL); | 670 | setup_sorting(NULL); |
671 | |||
672 | callchain_param = callchain_param_default; | ||
669 | callchain_register_param(&callchain_param); | 673 | callchain_register_param(&callchain_param); |
670 | 674 | ||
671 | err = add_hist_entries(hists, machine); | 675 | err = add_hist_entries(hists, machine); |
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index e846f8c42013..62efb14f3a5a 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c | |||
@@ -56,7 +56,7 @@ static int add_hist_entries(struct perf_evlist *evlist, | |||
56 | * (perf [perf] main) will be collapsed to an existing entry | 56 | * (perf [perf] main) will be collapsed to an existing entry |
57 | * so total 9 entries will be in the tree. | 57 | * so total 9 entries will be in the tree. |
58 | */ | 58 | */ |
59 | evlist__for_each(evlist, evsel) { | 59 | evlist__for_each_entry(evlist, evsel) { |
60 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { | 60 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { |
61 | struct hist_entry_iter iter = { | 61 | struct hist_entry_iter iter = { |
62 | .evsel = evsel, | 62 | .evsel = evsel, |
@@ -136,7 +136,7 @@ int test__hists_filter(int subtest __maybe_unused) | |||
136 | if (err < 0) | 136 | if (err < 0) |
137 | goto out; | 137 | goto out; |
138 | 138 | ||
139 | evlist__for_each(evlist, evsel) { | 139 | evlist__for_each_entry(evlist, evsel) { |
140 | struct hists *hists = evsel__hists(evsel); | 140 | struct hists *hists = evsel__hists(evsel); |
141 | 141 | ||
142 | hists__collapse_resort(hists, NULL); | 142 | hists__collapse_resort(hists, NULL); |
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index acf5a1301c07..eddc7407ff8a 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c | |||
@@ -72,7 +72,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
72 | * However the second evsel also has a collapsed entry for | 72 | * However the second evsel also has a collapsed entry for |
73 | * "bash [libc] malloc" so total 9 entries will be in the tree. | 73 | * "bash [libc] malloc" so total 9 entries will be in the tree. |
74 | */ | 74 | */ |
75 | evlist__for_each(evlist, evsel) { | 75 | evlist__for_each_entry(evlist, evsel) { |
76 | struct hists *hists = evsel__hists(evsel); | 76 | struct hists *hists = evsel__hists(evsel); |
77 | 77 | ||
78 | for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { | 78 | for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { |
@@ -84,7 +84,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
84 | if (machine__resolve(machine, &al, &sample) < 0) | 84 | if (machine__resolve(machine, &al, &sample) < 0) |
85 | goto out; | 85 | goto out; |
86 | 86 | ||
87 | he = __hists__add_entry(hists, &al, NULL, | 87 | he = hists__add_entry(hists, &al, NULL, |
88 | NULL, NULL, &sample, true); | 88 | NULL, NULL, &sample, true); |
89 | if (he == NULL) { | 89 | if (he == NULL) { |
90 | addr_location__put(&al); | 90 | addr_location__put(&al); |
@@ -103,7 +103,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
103 | if (machine__resolve(machine, &al, &sample) < 0) | 103 | if (machine__resolve(machine, &al, &sample) < 0) |
104 | goto out; | 104 | goto out; |
105 | 105 | ||
106 | he = __hists__add_entry(hists, &al, NULL, | 106 | he = hists__add_entry(hists, &al, NULL, |
107 | NULL, NULL, &sample, true); | 107 | NULL, NULL, &sample, true); |
108 | if (he == NULL) { | 108 | if (he == NULL) { |
109 | addr_location__put(&al); | 109 | addr_location__put(&al); |
@@ -301,7 +301,7 @@ int test__hists_link(int subtest __maybe_unused) | |||
301 | if (err < 0) | 301 | if (err < 0) |
302 | goto out; | 302 | goto out; |
303 | 303 | ||
304 | evlist__for_each(evlist, evsel) { | 304 | evlist__for_each_entry(evlist, evsel) { |
305 | hists = evsel__hists(evsel); | 305 | hists = evsel__hists(evsel); |
306 | hists__collapse_resort(hists, NULL); | 306 | hists__collapse_resort(hists, NULL); |
307 | 307 | ||
diff --git a/tools/perf/tests/is_printable_array.c b/tools/perf/tests/is_printable_array.c new file mode 100644 index 000000000000..42e13393e502 --- /dev/null +++ b/tools/perf/tests/is_printable_array.c | |||
@@ -0,0 +1,36 @@ | |||
1 | #include <linux/compiler.h> | ||
2 | #include "tests.h" | ||
3 | #include "debug.h" | ||
4 | #include "util.h" | ||
5 | |||
6 | int test__is_printable_array(int subtest __maybe_unused) | ||
7 | { | ||
8 | char buf1[] = { 'k', 'r', 4, 'v', 'a', 0 }; | ||
9 | char buf2[] = { 'k', 'r', 'a', 'v', 4, 0 }; | ||
10 | struct { | ||
11 | char *buf; | ||
12 | unsigned int len; | ||
13 | int ret; | ||
14 | } t[] = { | ||
15 | { (char *) "krava", sizeof("krava"), 1 }, | ||
16 | { (char *) "krava", sizeof("krava") - 1, 0 }, | ||
17 | { (char *) "", sizeof(""), 1 }, | ||
18 | { (char *) "", 0, 0 }, | ||
19 | { NULL, 0, 0 }, | ||
20 | { buf1, sizeof(buf1), 0 }, | ||
21 | { buf2, sizeof(buf2), 0 }, | ||
22 | }; | ||
23 | unsigned int i; | ||
24 | |||
25 | for (i = 0; i < ARRAY_SIZE(t); i++) { | ||
26 | int ret; | ||
27 | |||
28 | ret = is_printable_array((char *) t[i].buf, t[i].len); | ||
29 | if (ret != t[i].ret) { | ||
30 | pr_err("failed: test %u\n", i); | ||
31 | return TEST_FAIL; | ||
32 | } | ||
33 | } | ||
34 | |||
35 | return TEST_OK; | ||
36 | } | ||
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c index d2af78193153..76f41f249944 100644 --- a/tools/perf/tests/kmod-path.c +++ b/tools/perf/tests/kmod-path.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <stdbool.h> | 1 | #include <stdbool.h> |
2 | #include <stdlib.h> | ||
2 | #include "tests.h" | 3 | #include "tests.h" |
3 | #include "dso.h" | 4 | #include "dso.h" |
4 | #include "debug.h" | 5 | #include "debug.h" |
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c index cff564fb4b66..b798a4bfd238 100644 --- a/tools/perf/tests/llvm.c +++ b/tools/perf/tests/llvm.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "llvm.h" | 5 | #include "llvm.h" |
6 | #include "tests.h" | 6 | #include "tests.h" |
7 | #include "debug.h" | 7 | #include "debug.h" |
8 | #include "util.h" | ||
8 | 9 | ||
9 | #ifdef HAVE_LIBBPF_SUPPORT | 10 | #ifdef HAVE_LIBBPF_SUPPORT |
10 | static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) | 11 | static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) |
diff --git a/tools/perf/tests/make b/tools/perf/tests/make index cac15d93aea6..143f4d549769 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make | |||
@@ -81,6 +81,8 @@ make_no_libbionic := NO_LIBBIONIC=1 | |||
81 | make_no_auxtrace := NO_AUXTRACE=1 | 81 | make_no_auxtrace := NO_AUXTRACE=1 |
82 | make_no_libbpf := NO_LIBBPF=1 | 82 | make_no_libbpf := NO_LIBBPF=1 |
83 | make_no_libcrypto := NO_LIBCRYPTO=1 | 83 | make_no_libcrypto := NO_LIBCRYPTO=1 |
84 | make_with_babeltrace:= LIBBABELTRACE=1 | ||
85 | make_no_sdt := NO_SDT=1 | ||
84 | make_tags := tags | 86 | make_tags := tags |
85 | make_cscope := cscope | 87 | make_cscope := cscope |
86 | make_help := help | 88 | make_help := help |
@@ -104,7 +106,7 @@ make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 | |||
104 | make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 | 106 | make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 |
105 | make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 | 107 | make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 |
106 | make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 | 108 | make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 |
107 | make_minimal += NO_LIBCRYPTO=1 | 109 | make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 |
108 | 110 | ||
109 | # $(run) contains all available tests | 111 | # $(run) contains all available tests |
110 | run := make_pure | 112 | run := make_pure |
@@ -136,6 +138,7 @@ run += make_no_libaudit | |||
136 | run += make_no_libbionic | 138 | run += make_no_libbionic |
137 | run += make_no_auxtrace | 139 | run += make_no_auxtrace |
138 | run += make_no_libbpf | 140 | run += make_no_libbpf |
141 | run += make_with_babeltrace | ||
139 | run += make_help | 142 | run += make_help |
140 | run += make_doc | 143 | run += make_doc |
141 | run += make_perf_o | 144 | run += make_perf_o |
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 359e98fcd94c..634bce9caebd 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c | |||
@@ -1,3 +1,6 @@ | |||
1 | /* For the CLR_() macros */ | ||
2 | #include <pthread.h> | ||
3 | |||
1 | #include "evlist.h" | 4 | #include "evlist.h" |
2 | #include "evsel.h" | 5 | #include "evsel.h" |
3 | #include "thread_map.h" | 6 | #include "thread_map.h" |
@@ -49,7 +52,7 @@ int test__basic_mmap(int subtest __maybe_unused) | |||
49 | sched_setaffinity(0, sizeof(cpu_set), &cpu_set); | 52 | sched_setaffinity(0, sizeof(cpu_set), &cpu_set); |
50 | if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { | 53 | if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { |
51 | pr_debug("sched_setaffinity() failed on CPU %d: %s ", | 54 | pr_debug("sched_setaffinity() failed on CPU %d: %s ", |
52 | cpus->map[0], strerror_r(errno, sbuf, sizeof(sbuf))); | 55 | cpus->map[0], str_error_r(errno, sbuf, sizeof(sbuf))); |
53 | goto out_free_cpus; | 56 | goto out_free_cpus; |
54 | } | 57 | } |
55 | 58 | ||
@@ -79,7 +82,7 @@ int test__basic_mmap(int subtest __maybe_unused) | |||
79 | if (perf_evsel__open(evsels[i], cpus, threads) < 0) { | 82 | if (perf_evsel__open(evsels[i], cpus, threads) < 0) { |
80 | pr_debug("failed to open counter: %s, " | 83 | pr_debug("failed to open counter: %s, " |
81 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | 84 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", |
82 | strerror_r(errno, sbuf, sizeof(sbuf))); | 85 | str_error_r(errno, sbuf, sizeof(sbuf))); |
83 | goto out_delete_evlist; | 86 | goto out_delete_evlist; |
84 | } | 87 | } |
85 | 88 | ||
@@ -89,7 +92,7 @@ int test__basic_mmap(int subtest __maybe_unused) | |||
89 | 92 | ||
90 | if (perf_evlist__mmap(evlist, 128, true) < 0) { | 93 | if (perf_evlist__mmap(evlist, 128, true) < 0) { |
91 | pr_debug("failed to mmap events: %d (%s)\n", errno, | 94 | pr_debug("failed to mmap events: %d (%s)\n", errno, |
92 | strerror_r(errno, sbuf, sizeof(sbuf))); | 95 | str_error_r(errno, sbuf, sizeof(sbuf))); |
93 | goto out_delete_evlist; | 96 | goto out_delete_evlist; |
94 | } | 97 | } |
95 | 98 | ||
@@ -126,7 +129,7 @@ int test__basic_mmap(int subtest __maybe_unused) | |||
126 | } | 129 | } |
127 | 130 | ||
128 | err = 0; | 131 | err = 0; |
129 | evlist__for_each(evlist, evsel) { | 132 | evlist__for_each_entry(evlist, evsel) { |
130 | if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { | 133 | if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { |
131 | pr_debug("expected %d %s events, got %d\n", | 134 | pr_debug("expected %d %s events, got %d\n", |
132 | expected_nr_events[evsel->idx], | 135 | expected_nr_events[evsel->idx], |
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index ad1cb63139a7..c8d9592eb142 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c | |||
@@ -1,3 +1,6 @@ | |||
1 | /* For the CPU_* macros */ | ||
2 | #include <pthread.h> | ||
3 | |||
1 | #include <api/fs/fs.h> | 4 | #include <api/fs/fs.h> |
2 | #include <linux/err.h> | 5 | #include <linux/err.h> |
3 | #include "evsel.h" | 6 | #include "evsel.h" |
@@ -41,7 +44,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused) | |||
41 | if (perf_evsel__open(evsel, cpus, threads) < 0) { | 44 | if (perf_evsel__open(evsel, cpus, threads) < 0) { |
42 | pr_debug("failed to open counter: %s, " | 45 | pr_debug("failed to open counter: %s, " |
43 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | 46 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", |
44 | strerror_r(errno, sbuf, sizeof(sbuf))); | 47 | str_error_r(errno, sbuf, sizeof(sbuf))); |
45 | goto out_evsel_delete; | 48 | goto out_evsel_delete; |
46 | } | 49 | } |
47 | 50 | ||
@@ -62,7 +65,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused) | |||
62 | if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { | 65 | if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { |
63 | pr_debug("sched_setaffinity() failed on CPU %d: %s ", | 66 | pr_debug("sched_setaffinity() failed on CPU %d: %s ", |
64 | cpus->map[cpu], | 67 | cpus->map[cpu], |
65 | strerror_r(errno, sbuf, sizeof(sbuf))); | 68 | str_error_r(errno, sbuf, sizeof(sbuf))); |
66 | goto out_close_fd; | 69 | goto out_close_fd; |
67 | } | 70 | } |
68 | for (i = 0; i < ncalls; ++i) { | 71 | for (i = 0; i < ncalls; ++i) { |
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 4344fe482c1d..f52239fed361 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c | |||
@@ -6,6 +6,13 @@ | |||
6 | #include "tests.h" | 6 | #include "tests.h" |
7 | #include "debug.h" | 7 | #include "debug.h" |
8 | 8 | ||
9 | #ifndef O_DIRECTORY | ||
10 | #define O_DIRECTORY 00200000 | ||
11 | #endif | ||
12 | #ifndef AT_FDCWD | ||
13 | #define AT_FDCWD -100 | ||
14 | #endif | ||
15 | |||
9 | int test__syscall_openat_tp_fields(int subtest __maybe_unused) | 16 | int test__syscall_openat_tp_fields(int subtest __maybe_unused) |
10 | { | 17 | { |
11 | struct record_opts opts = { | 18 | struct record_opts opts = { |
@@ -51,14 +58,14 @@ int test__syscall_openat_tp_fields(int subtest __maybe_unused) | |||
51 | err = perf_evlist__open(evlist); | 58 | err = perf_evlist__open(evlist); |
52 | if (err < 0) { | 59 | if (err < 0) { |
53 | pr_debug("perf_evlist__open: %s\n", | 60 | pr_debug("perf_evlist__open: %s\n", |
54 | strerror_r(errno, sbuf, sizeof(sbuf))); | 61 | str_error_r(errno, sbuf, sizeof(sbuf))); |
55 | goto out_delete_evlist; | 62 | goto out_delete_evlist; |
56 | } | 63 | } |
57 | 64 | ||
58 | err = perf_evlist__mmap(evlist, UINT_MAX, false); | 65 | err = perf_evlist__mmap(evlist, UINT_MAX, false); |
59 | if (err < 0) { | 66 | if (err < 0) { |
60 | pr_debug("perf_evlist__mmap: %s\n", | 67 | pr_debug("perf_evlist__mmap: %s\n", |
61 | strerror_r(errno, sbuf, sizeof(sbuf))); | 68 | str_error_r(errno, sbuf, sizeof(sbuf))); |
62 | goto out_delete_evlist; | 69 | goto out_delete_evlist; |
63 | } | 70 | } |
64 | 71 | ||
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index 1184f9ba6499..d7414128d7fe 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c | |||
@@ -29,7 +29,7 @@ int test__openat_syscall_event(int subtest __maybe_unused) | |||
29 | if (perf_evsel__open_per_thread(evsel, threads) < 0) { | 29 | if (perf_evsel__open_per_thread(evsel, threads) < 0) { |
30 | pr_debug("failed to open counter: %s, " | 30 | pr_debug("failed to open counter: %s, " |
31 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | 31 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", |
32 | strerror_r(errno, sbuf, sizeof(sbuf))); | 32 | str_error_r(errno, sbuf, sizeof(sbuf))); |
33 | goto out_evsel_delete; | 33 | goto out_evsel_delete; |
34 | } | 34 | } |
35 | 35 | ||
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 7865f68dc0d8..20c2e641c422 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c | |||
@@ -32,7 +32,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) | |||
32 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); | 32 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); |
33 | TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); | 33 | TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); |
34 | 34 | ||
35 | evlist__for_each(evlist, evsel) { | 35 | evlist__for_each_entry(evlist, evsel) { |
36 | TEST_ASSERT_VAL("wrong type", | 36 | TEST_ASSERT_VAL("wrong type", |
37 | PERF_TYPE_TRACEPOINT == evsel->attr.type); | 37 | PERF_TYPE_TRACEPOINT == evsel->attr.type); |
38 | TEST_ASSERT_VAL("wrong sample_type", | 38 | TEST_ASSERT_VAL("wrong sample_type", |
@@ -207,7 +207,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist) | |||
207 | 207 | ||
208 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); | 208 | TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); |
209 | 209 | ||
210 | evlist__for_each(evlist, evsel) { | 210 | evlist__for_each_entry(evlist, evsel) { |
211 | TEST_ASSERT_VAL("wrong exclude_user", | 211 | TEST_ASSERT_VAL("wrong exclude_user", |
212 | !evsel->attr.exclude_user); | 212 | !evsel->attr.exclude_user); |
213 | TEST_ASSERT_VAL("wrong exclude_kernel", | 213 | TEST_ASSERT_VAL("wrong exclude_kernel", |
@@ -1783,8 +1783,8 @@ static int test_pmu_events(void) | |||
1783 | struct evlist_test e; | 1783 | struct evlist_test e; |
1784 | char name[MAX_NAME]; | 1784 | char name[MAX_NAME]; |
1785 | 1785 | ||
1786 | if (!strcmp(ent->d_name, ".") || | 1786 | /* Names containing . are special and cannot be used directly */ |
1787 | !strcmp(ent->d_name, "..")) | 1787 | if (strchr(ent->d_name, '.')) |
1788 | continue; | 1788 | continue; |
1789 | 1789 | ||
1790 | snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name); | 1790 | snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name); |
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c index 294c76b01b41..81c6eeaca0f5 100644 --- a/tools/perf/tests/parse-no-sample-id-all.c +++ b/tools/perf/tests/parse-no-sample-id-all.c | |||
@@ -44,8 +44,7 @@ static int process_events(union perf_event **events, size_t count) | |||
44 | for (i = 0; i < count && !err; i++) | 44 | for (i = 0; i < count && !err; i++) |
45 | err = process_event(&evlist, events[i]); | 45 | err = process_event(&evlist, events[i]); |
46 | 46 | ||
47 | if (evlist) | 47 | perf_evlist__delete(evlist); |
48 | perf_evlist__delete(evlist); | ||
49 | 48 | ||
50 | return err; | 49 | return err; |
51 | } | 50 | } |
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index b836ee6a8d9b..8f2e1de6d0ea 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c | |||
@@ -1,3 +1,6 @@ | |||
1 | /* For the CLR_() macros */ | ||
2 | #include <pthread.h> | ||
3 | |||
1 | #include <sched.h> | 4 | #include <sched.h> |
2 | #include "evlist.h" | 5 | #include "evlist.h" |
3 | #include "evsel.h" | 6 | #include "evsel.h" |
@@ -104,7 +107,7 @@ int test__PERF_RECORD(int subtest __maybe_unused) | |||
104 | err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); | 107 | err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); |
105 | if (err < 0) { | 108 | if (err < 0) { |
106 | pr_debug("sched__get_first_possible_cpu: %s\n", | 109 | pr_debug("sched__get_first_possible_cpu: %s\n", |
107 | strerror_r(errno, sbuf, sizeof(sbuf))); | 110 | str_error_r(errno, sbuf, sizeof(sbuf))); |
108 | goto out_delete_evlist; | 111 | goto out_delete_evlist; |
109 | } | 112 | } |
110 | 113 | ||
@@ -115,7 +118,7 @@ int test__PERF_RECORD(int subtest __maybe_unused) | |||
115 | */ | 118 | */ |
116 | if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { | 119 | if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { |
117 | pr_debug("sched_setaffinity: %s\n", | 120 | pr_debug("sched_setaffinity: %s\n", |
118 | strerror_r(errno, sbuf, sizeof(sbuf))); | 121 | str_error_r(errno, sbuf, sizeof(sbuf))); |
119 | goto out_delete_evlist; | 122 | goto out_delete_evlist; |
120 | } | 123 | } |
121 | 124 | ||
@@ -126,7 +129,7 @@ int test__PERF_RECORD(int subtest __maybe_unused) | |||
126 | err = perf_evlist__open(evlist); | 129 | err = perf_evlist__open(evlist); |
127 | if (err < 0) { | 130 | if (err < 0) { |
128 | pr_debug("perf_evlist__open: %s\n", | 131 | pr_debug("perf_evlist__open: %s\n", |
129 | strerror_r(errno, sbuf, sizeof(sbuf))); | 132 | str_error_r(errno, sbuf, sizeof(sbuf))); |
130 | goto out_delete_evlist; | 133 | goto out_delete_evlist; |
131 | } | 134 | } |
132 | 135 | ||
@@ -138,7 +141,7 @@ int test__PERF_RECORD(int subtest __maybe_unused) | |||
138 | err = perf_evlist__mmap(evlist, opts.mmap_pages, false); | 141 | err = perf_evlist__mmap(evlist, opts.mmap_pages, false); |
139 | if (err < 0) { | 142 | if (err < 0) { |
140 | pr_debug("perf_evlist__mmap: %s\n", | 143 | pr_debug("perf_evlist__mmap: %s\n", |
141 | strerror_r(errno, sbuf, sizeof(sbuf))); | 144 | str_error_r(errno, sbuf, sizeof(sbuf))); |
142 | goto out_delete_evlist; | 145 | goto out_delete_evlist; |
143 | } | 146 | } |
144 | 147 | ||
diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c new file mode 100644 index 000000000000..f59d210e1baf --- /dev/null +++ b/tools/perf/tests/sdt.c | |||
@@ -0,0 +1,115 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <sys/epoll.h> | ||
3 | #include <util/util.h> | ||
4 | #include <util/evlist.h> | ||
5 | #include <linux/filter.h> | ||
6 | #include "tests.h" | ||
7 | #include "debug.h" | ||
8 | #include "probe-file.h" | ||
9 | #include "build-id.h" | ||
10 | |||
11 | /* To test SDT event, we need libelf support to scan elf binary */ | ||
12 | #if defined(HAVE_SDT_EVENT) && defined(HAVE_LIBELF_SUPPORT) | ||
13 | |||
14 | #include <sys/sdt.h> | ||
15 | |||
16 | static int target_function(void) | ||
17 | { | ||
18 | DTRACE_PROBE(perf, test_target); | ||
19 | return TEST_OK; | ||
20 | } | ||
21 | |||
22 | /* Copied from builtin-buildid-cache.c */ | ||
23 | static int build_id_cache__add_file(const char *filename) | ||
24 | { | ||
25 | char sbuild_id[SBUILD_ID_SIZE]; | ||
26 | u8 build_id[BUILD_ID_SIZE]; | ||
27 | int err; | ||
28 | |||
29 | err = filename__read_build_id(filename, &build_id, sizeof(build_id)); | ||
30 | if (err < 0) { | ||
31 | pr_debug("Failed to read build id of %s\n", filename); | ||
32 | return err; | ||
33 | } | ||
34 | |||
35 | build_id__sprintf(build_id, sizeof(build_id), sbuild_id); | ||
36 | err = build_id_cache__add_s(sbuild_id, filename, false, false); | ||
37 | if (err < 0) | ||
38 | pr_debug("Failed to add build id cache of %s\n", filename); | ||
39 | return err; | ||
40 | } | ||
41 | |||
42 | static char *get_self_path(void) | ||
43 | { | ||
44 | char *buf = calloc(PATH_MAX, sizeof(char)); | ||
45 | |||
46 | if (buf && readlink("/proc/self/exe", buf, PATH_MAX) < 0) { | ||
47 | pr_debug("Failed to get correct path of perf\n"); | ||
48 | free(buf); | ||
49 | return NULL; | ||
50 | } | ||
51 | return buf; | ||
52 | } | ||
53 | |||
54 | static int search_cached_probe(const char *target, | ||
55 | const char *group, const char *event) | ||
56 | { | ||
57 | struct probe_cache *cache = probe_cache__new(target); | ||
58 | int ret = 0; | ||
59 | |||
60 | if (!cache) { | ||
61 | pr_debug("Failed to open probe cache of %s\n", target); | ||
62 | return -EINVAL; | ||
63 | } | ||
64 | |||
65 | if (!probe_cache__find_by_name(cache, group, event)) { | ||
66 | pr_debug("Failed to find %s:%s in the cache\n", group, event); | ||
67 | ret = -ENOENT; | ||
68 | } | ||
69 | probe_cache__delete(cache); | ||
70 | |||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | int test__sdt_event(int subtests __maybe_unused) | ||
75 | { | ||
76 | int ret = TEST_FAIL; | ||
77 | char __tempdir[] = "./test-buildid-XXXXXX"; | ||
78 | char *tempdir = NULL, *myself = get_self_path(); | ||
79 | |||
80 | if (myself == NULL || mkdtemp(__tempdir) == NULL) { | ||
81 | pr_debug("Failed to make a tempdir for build-id cache\n"); | ||
82 | goto error; | ||
83 | } | ||
84 | /* Note that buildid_dir must be an absolute path */ | ||
85 | tempdir = realpath(__tempdir, NULL); | ||
86 | |||
87 | /* At first, scan itself */ | ||
88 | set_buildid_dir(tempdir); | ||
89 | if (build_id_cache__add_file(myself) < 0) | ||
90 | goto error_rmdir; | ||
91 | |||
92 | /* Open a cache and make sure the SDT is stored */ | ||
93 | if (search_cached_probe(myself, "sdt_perf", "test_target") < 0) | ||
94 | goto error_rmdir; | ||
95 | |||
96 | /* TBD: probing on the SDT event and collect logs */ | ||
97 | |||
98 | /* Call the target and get an event */ | ||
99 | ret = target_function(); | ||
100 | |||
101 | error_rmdir: | ||
102 | /* Cleanup temporary buildid dir */ | ||
103 | rm_rf(tempdir); | ||
104 | error: | ||
105 | free(tempdir); | ||
106 | free(myself); | ||
107 | return ret; | ||
108 | } | ||
109 | #else | ||
110 | int test__sdt_event(int subtests __maybe_unused) | ||
111 | { | ||
112 | pr_debug("Skip SDT event test because SDT support is not compiled\n"); | ||
113 | return TEST_SKIP; | ||
114 | } | ||
115 | #endif | ||
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 36e8ce1550e3..4c9fd046d57b 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c | |||
@@ -70,7 +70,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
70 | 70 | ||
71 | err = -errno; | 71 | err = -errno; |
72 | pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", | 72 | pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", |
73 | strerror_r(errno, sbuf, sizeof(sbuf)), | 73 | str_error_r(errno, sbuf, sizeof(sbuf)), |
74 | knob, (u64)attr.sample_freq); | 74 | knob, (u64)attr.sample_freq); |
75 | goto out_delete_evlist; | 75 | goto out_delete_evlist; |
76 | } | 76 | } |
@@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
78 | err = perf_evlist__mmap(evlist, 128, true); | 78 | err = perf_evlist__mmap(evlist, 128, true); |
79 | if (err < 0) { | 79 | if (err < 0) { |
80 | pr_debug("failed to mmap event: %d (%s)\n", errno, | 80 | pr_debug("failed to mmap event: %d (%s)\n", errno, |
81 | strerror_r(errno, sbuf, sizeof(sbuf))); | 81 | str_error_r(errno, sbuf, sizeof(sbuf))); |
82 | goto out_delete_evlist; | 82 | goto out_delete_evlist; |
83 | } | 83 | } |
84 | 84 | ||
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 39a689bf7574..7ddbe267d0ac 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c | |||
@@ -432,7 +432,7 @@ int test__switch_tracking(int subtest __maybe_unused) | |||
432 | } | 432 | } |
433 | 433 | ||
434 | /* Check non-tracking events are not tracking */ | 434 | /* Check non-tracking events are not tracking */ |
435 | evlist__for_each(evlist, evsel) { | 435 | evlist__for_each_entry(evlist, evsel) { |
436 | if (evsel != tracking_evsel) { | 436 | if (evsel != tracking_evsel) { |
437 | if (evsel->attr.mmap || evsel->attr.comm) { | 437 | if (evsel->attr.mmap || evsel->attr.comm) { |
438 | pr_debug("Non-tracking event is tracking\n"); | 438 | pr_debug("Non-tracking event is tracking\n"); |
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index 2dfff7ac8ef3..01a5ba2788c6 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c | |||
@@ -91,13 +91,13 @@ int test__task_exit(int subtest __maybe_unused) | |||
91 | err = perf_evlist__open(evlist); | 91 | err = perf_evlist__open(evlist); |
92 | if (err < 0) { | 92 | if (err < 0) { |
93 | pr_debug("Couldn't open the evlist: %s\n", | 93 | pr_debug("Couldn't open the evlist: %s\n", |
94 | strerror_r(-err, sbuf, sizeof(sbuf))); | 94 | str_error_r(-err, sbuf, sizeof(sbuf))); |
95 | goto out_delete_evlist; | 95 | goto out_delete_evlist; |
96 | } | 96 | } |
97 | 97 | ||
98 | if (perf_evlist__mmap(evlist, 128, true) < 0) { | 98 | if (perf_evlist__mmap(evlist, 128, true) < 0) { |
99 | pr_debug("failed to mmap events: %d (%s)\n", errno, | 99 | pr_debug("failed to mmap events: %d (%s)\n", errno, |
100 | strerror_r(errno, sbuf, sizeof(sbuf))); | 100 | str_error_r(errno, sbuf, sizeof(sbuf))); |
101 | goto out_delete_evlist; | 101 | goto out_delete_evlist; |
102 | } | 102 | } |
103 | 103 | ||
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index c57e72c826d2..7c196c585472 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
@@ -87,6 +87,10 @@ int test__synthesize_stat_round(int subtest); | |||
87 | int test__event_update(int subtest); | 87 | int test__event_update(int subtest); |
88 | int test__event_times(int subtest); | 88 | int test__event_times(int subtest); |
89 | int test__backward_ring_buffer(int subtest); | 89 | int test__backward_ring_buffer(int subtest); |
90 | int test__cpu_map_print(int subtest); | ||
91 | int test__sdt_event(int subtest); | ||
92 | int test__is_printable_array(int subtest); | ||
93 | int test__bitmap_print(int subtest); | ||
90 | 94 | ||
91 | #if defined(__arm__) || defined(__aarch64__) | 95 | #if defined(__arm__) || defined(__aarch64__) |
92 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 96 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c index fccde848fe9c..cee2a2cdc933 100644 --- a/tools/perf/tests/thread-map.c +++ b/tools/perf/tests/thread-map.c | |||
@@ -1,13 +1,20 @@ | |||
1 | #include <sys/types.h> | 1 | #include <sys/types.h> |
2 | #include <unistd.h> | 2 | #include <unistd.h> |
3 | #include <sys/prctl.h> | ||
3 | #include "tests.h" | 4 | #include "tests.h" |
4 | #include "thread_map.h" | 5 | #include "thread_map.h" |
5 | #include "debug.h" | 6 | #include "debug.h" |
6 | 7 | ||
8 | #define NAME (const char *) "perf" | ||
9 | #define NAMEUL (unsigned long) NAME | ||
10 | |||
7 | int test__thread_map(int subtest __maybe_unused) | 11 | int test__thread_map(int subtest __maybe_unused) |
8 | { | 12 | { |
9 | struct thread_map *map; | 13 | struct thread_map *map; |
10 | 14 | ||
15 | TEST_ASSERT_VAL("failed to set process name", | ||
16 | !prctl(PR_SET_NAME, NAMEUL, 0, 0, 0)); | ||
17 | |||
11 | /* test map on current pid */ | 18 | /* test map on current pid */ |
12 | map = thread_map__new_by_pid(getpid()); | 19 | map = thread_map__new_by_pid(getpid()); |
13 | TEST_ASSERT_VAL("failed to alloc map", map); | 20 | TEST_ASSERT_VAL("failed to alloc map", map); |
@@ -19,7 +26,7 @@ int test__thread_map(int subtest __maybe_unused) | |||
19 | thread_map__pid(map, 0) == getpid()); | 26 | thread_map__pid(map, 0) == getpid()); |
20 | TEST_ASSERT_VAL("wrong comm", | 27 | TEST_ASSERT_VAL("wrong comm", |
21 | thread_map__comm(map, 0) && | 28 | thread_map__comm(map, 0) && |
22 | !strcmp(thread_map__comm(map, 0), "perf")); | 29 | !strcmp(thread_map__comm(map, 0), NAME)); |
23 | TEST_ASSERT_VAL("wrong refcnt", | 30 | TEST_ASSERT_VAL("wrong refcnt", |
24 | atomic_read(&map->refcnt) == 1); | 31 | atomic_read(&map->refcnt) == 1); |
25 | thread_map__put(map); | 32 | thread_map__put(map); |
@@ -51,7 +58,7 @@ static int process_event(struct perf_tool *tool __maybe_unused, | |||
51 | 58 | ||
52 | TEST_ASSERT_VAL("wrong nr", map->nr == 1); | 59 | TEST_ASSERT_VAL("wrong nr", map->nr == 1); |
53 | TEST_ASSERT_VAL("wrong pid", map->entries[0].pid == (u64) getpid()); | 60 | TEST_ASSERT_VAL("wrong pid", map->entries[0].pid == (u64) getpid()); |
54 | TEST_ASSERT_VAL("wrong comm", !strcmp(map->entries[0].comm, "perf")); | 61 | TEST_ASSERT_VAL("wrong comm", !strcmp(map->entries[0].comm, NAME)); |
55 | 62 | ||
56 | threads = thread_map__new_event(&event->thread_map); | 63 | threads = thread_map__new_event(&event->thread_map); |
57 | TEST_ASSERT_VAL("failed to alloc map", threads); | 64 | TEST_ASSERT_VAL("failed to alloc map", threads); |
@@ -61,7 +68,7 @@ static int process_event(struct perf_tool *tool __maybe_unused, | |||
61 | thread_map__pid(threads, 0) == getpid()); | 68 | thread_map__pid(threads, 0) == getpid()); |
62 | TEST_ASSERT_VAL("wrong comm", | 69 | TEST_ASSERT_VAL("wrong comm", |
63 | thread_map__comm(threads, 0) && | 70 | thread_map__comm(threads, 0) && |
64 | !strcmp(thread_map__comm(threads, 0), "perf")); | 71 | !strcmp(thread_map__comm(threads, 0), NAME)); |
65 | TEST_ASSERT_VAL("wrong refcnt", | 72 | TEST_ASSERT_VAL("wrong refcnt", |
66 | atomic_read(&threads->refcnt) == 1); | 73 | atomic_read(&threads->refcnt) == 1); |
67 | thread_map__put(threads); | 74 | thread_map__put(threads); |
@@ -72,6 +79,9 @@ int test__thread_map_synthesize(int subtest __maybe_unused) | |||
72 | { | 79 | { |
73 | struct thread_map *threads; | 80 | struct thread_map *threads; |
74 | 81 | ||
82 | TEST_ASSERT_VAL("failed to set process name", | ||
83 | !prctl(PR_SET_NAME, NAMEUL, 0, 0, 0)); | ||
84 | |||
75 | /* test map on current pid */ | 85 | /* test map on current pid */ |
76 | threads = thread_map__new_by_pid(getpid()); | 86 | threads = thread_map__new_by_pid(getpid()); |
77 | TEST_ASSERT_VAL("failed to alloc map", threads); | 87 | TEST_ASSERT_VAL("failed to alloc map", threads); |
diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c index d64f4a9128a1..b08f21eb6f4d 100644 --- a/tools/perf/trace/beauty/eventfd.c +++ b/tools/perf/trace/beauty/eventfd.c | |||
@@ -1,5 +1,3 @@ | |||
1 | #include <sys/eventfd.h> | ||
2 | |||
3 | #ifndef EFD_SEMAPHORE | 1 | #ifndef EFD_SEMAPHORE |
4 | #define EFD_SEMAPHORE 1 | 2 | #define EFD_SEMAPHORE 1 |
5 | #endif | 3 | #endif |
diff --git a/tools/perf/trace/beauty/flock.c b/tools/perf/trace/beauty/flock.c index 021bb48c6336..74613703a14e 100644 --- a/tools/perf/trace/beauty/flock.c +++ b/tools/perf/trace/beauty/flock.c | |||
@@ -1,3 +1,20 @@ | |||
1 | #include <fcntl.h> | ||
2 | |||
3 | #ifndef LOCK_MAND | ||
4 | #define LOCK_MAND 32 | ||
5 | #endif | ||
6 | |||
7 | #ifndef LOCK_READ | ||
8 | #define LOCK_READ 64 | ||
9 | #endif | ||
10 | |||
11 | #ifndef LOCK_WRITE | ||
12 | #define LOCK_WRITE 128 | ||
13 | #endif | ||
14 | |||
15 | #ifndef LOCK_RW | ||
16 | #define LOCK_RW 192 | ||
17 | #endif | ||
1 | 18 | ||
2 | static size_t syscall_arg__scnprintf_flock(char *bf, size_t size, | 19 | static size_t syscall_arg__scnprintf_flock(char *bf, size_t size, |
3 | struct syscall_arg *arg) | 20 | struct syscall_arg *arg) |
diff --git a/tools/perf/trace/beauty/futex_op.c b/tools/perf/trace/beauty/futex_op.c index e2476211f22d..bfd3359b09b6 100644 --- a/tools/perf/trace/beauty/futex_op.c +++ b/tools/perf/trace/beauty/futex_op.c | |||
@@ -1,5 +1,21 @@ | |||
1 | #include <linux/futex.h> | 1 | #include <linux/futex.h> |
2 | 2 | ||
3 | #ifndef FUTEX_WAIT_BITSET | ||
4 | #define FUTEX_WAIT_BITSET 9 | ||
5 | #endif | ||
6 | #ifndef FUTEX_WAKE_BITSET | ||
7 | #define FUTEX_WAKE_BITSET 10 | ||
8 | #endif | ||
9 | #ifndef FUTEX_WAIT_REQUEUE_PI | ||
10 | #define FUTEX_WAIT_REQUEUE_PI 11 | ||
11 | #endif | ||
12 | #ifndef FUTEX_CMP_REQUEUE_PI | ||
13 | #define FUTEX_CMP_REQUEUE_PI 12 | ||
14 | #endif | ||
15 | #ifndef FUTEX_CLOCK_REALTIME | ||
16 | #define FUTEX_CLOCK_REALTIME 256 | ||
17 | #endif | ||
18 | |||
3 | static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg) | 19 | static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg) |
4 | { | 20 | { |
5 | enum syscall_futex_args { | 21 | enum syscall_futex_args { |
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c index 3444a4d5382d..d0a3a8e402e7 100644 --- a/tools/perf/trace/beauty/mmap.c +++ b/tools/perf/trace/beauty/mmap.c | |||
@@ -1,5 +1,9 @@ | |||
1 | #include <sys/mman.h> | 1 | #include <sys/mman.h> |
2 | 2 | ||
3 | #ifndef PROT_SEM | ||
4 | #define PROT_SEM 0x8 | ||
5 | #endif | ||
6 | |||
3 | static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, | 7 | static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, |
4 | struct syscall_arg *arg) | 8 | struct syscall_arg *arg) |
5 | { | 9 | { |
@@ -16,9 +20,7 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, | |||
16 | P_MMAP_PROT(EXEC); | 20 | P_MMAP_PROT(EXEC); |
17 | P_MMAP_PROT(READ); | 21 | P_MMAP_PROT(READ); |
18 | P_MMAP_PROT(WRITE); | 22 | P_MMAP_PROT(WRITE); |
19 | #ifdef PROT_SEM | ||
20 | P_MMAP_PROT(SEM); | 23 | P_MMAP_PROT(SEM); |
21 | #endif | ||
22 | P_MMAP_PROT(GROWSDOWN); | 24 | P_MMAP_PROT(GROWSDOWN); |
23 | P_MMAP_PROT(GROWSUP); | 25 | P_MMAP_PROT(GROWSUP); |
24 | #undef P_MMAP_PROT | 26 | #undef P_MMAP_PROT |
@@ -31,10 +33,31 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, | |||
31 | 33 | ||
32 | #define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot | 34 | #define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot |
33 | 35 | ||
36 | #ifndef MAP_FIXED | ||
37 | #define MAP_FIXED 0x10 | ||
38 | #endif | ||
39 | |||
40 | #ifndef MAP_ANONYMOUS | ||
41 | #define MAP_ANONYMOUS 0x20 | ||
42 | #endif | ||
43 | |||
44 | #ifndef MAP_32BIT | ||
45 | #define MAP_32BIT 0x40 | ||
46 | #endif | ||
47 | |||
34 | #ifndef MAP_STACK | 48 | #ifndef MAP_STACK |
35 | # define MAP_STACK 0x20000 | 49 | #define MAP_STACK 0x20000 |
36 | #endif | 50 | #endif |
37 | 51 | ||
52 | #ifndef MAP_HUGETLB | ||
53 | #define MAP_HUGETLB 0x40000 | ||
54 | #endif | ||
55 | |||
56 | #ifndef MAP_UNINITIALIZED | ||
57 | #define MAP_UNINITIALIZED 0x4000000 | ||
58 | #endif | ||
59 | |||
60 | |||
38 | static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, | 61 | static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, |
39 | struct syscall_arg *arg) | 62 | struct syscall_arg *arg) |
40 | { | 63 | { |
@@ -48,26 +71,20 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, | |||
48 | 71 | ||
49 | P_MMAP_FLAG(SHARED); | 72 | P_MMAP_FLAG(SHARED); |
50 | P_MMAP_FLAG(PRIVATE); | 73 | P_MMAP_FLAG(PRIVATE); |
51 | #ifdef MAP_32BIT | ||
52 | P_MMAP_FLAG(32BIT); | 74 | P_MMAP_FLAG(32BIT); |
53 | #endif | ||
54 | P_MMAP_FLAG(ANONYMOUS); | 75 | P_MMAP_FLAG(ANONYMOUS); |
55 | P_MMAP_FLAG(DENYWRITE); | 76 | P_MMAP_FLAG(DENYWRITE); |
56 | P_MMAP_FLAG(EXECUTABLE); | 77 | P_MMAP_FLAG(EXECUTABLE); |
57 | P_MMAP_FLAG(FILE); | 78 | P_MMAP_FLAG(FILE); |
58 | P_MMAP_FLAG(FIXED); | 79 | P_MMAP_FLAG(FIXED); |
59 | P_MMAP_FLAG(GROWSDOWN); | 80 | P_MMAP_FLAG(GROWSDOWN); |
60 | #ifdef MAP_HUGETLB | ||
61 | P_MMAP_FLAG(HUGETLB); | 81 | P_MMAP_FLAG(HUGETLB); |
62 | #endif | ||
63 | P_MMAP_FLAG(LOCKED); | 82 | P_MMAP_FLAG(LOCKED); |
64 | P_MMAP_FLAG(NONBLOCK); | 83 | P_MMAP_FLAG(NONBLOCK); |
65 | P_MMAP_FLAG(NORESERVE); | 84 | P_MMAP_FLAG(NORESERVE); |
66 | P_MMAP_FLAG(POPULATE); | 85 | P_MMAP_FLAG(POPULATE); |
67 | P_MMAP_FLAG(STACK); | 86 | P_MMAP_FLAG(STACK); |
68 | #ifdef MAP_UNINITIALIZED | ||
69 | P_MMAP_FLAG(UNINITIALIZED); | 87 | P_MMAP_FLAG(UNINITIALIZED); |
70 | #endif | ||
71 | #undef P_MMAP_FLAG | 88 | #undef P_MMAP_FLAG |
72 | 89 | ||
73 | if (flags) | 90 | if (flags) |
@@ -78,6 +95,13 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, | |||
78 | 95 | ||
79 | #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags | 96 | #define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags |
80 | 97 | ||
98 | #ifndef MREMAP_MAYMOVE | ||
99 | #define MREMAP_MAYMOVE 1 | ||
100 | #endif | ||
101 | #ifndef MREMAP_FIXED | ||
102 | #define MREMAP_FIXED 2 | ||
103 | #endif | ||
104 | |||
81 | static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, | 105 | static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, |
82 | struct syscall_arg *arg) | 106 | struct syscall_arg *arg) |
83 | { | 107 | { |
@@ -90,9 +114,7 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, | |||
90 | } | 114 | } |
91 | 115 | ||
92 | P_MREMAP_FLAG(MAYMOVE); | 116 | P_MREMAP_FLAG(MAYMOVE); |
93 | #ifdef MREMAP_FIXED | ||
94 | P_MREMAP_FLAG(FIXED); | 117 | P_MREMAP_FLAG(FIXED); |
95 | #endif | ||
96 | #undef P_MREMAP_FLAG | 118 | #undef P_MREMAP_FLAG |
97 | 119 | ||
98 | if (flags) | 120 | if (flags) |
@@ -107,6 +129,10 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, | |||
107 | #define MADV_HWPOISON 100 | 129 | #define MADV_HWPOISON 100 |
108 | #endif | 130 | #endif |
109 | 131 | ||
132 | #ifndef MADV_SOFT_OFFLINE | ||
133 | #define MADV_SOFT_OFFLINE 101 | ||
134 | #endif | ||
135 | |||
110 | #ifndef MADV_MERGEABLE | 136 | #ifndef MADV_MERGEABLE |
111 | #define MADV_MERGEABLE 12 | 137 | #define MADV_MERGEABLE 12 |
112 | #endif | 138 | #endif |
@@ -115,6 +141,23 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, | |||
115 | #define MADV_UNMERGEABLE 13 | 141 | #define MADV_UNMERGEABLE 13 |
116 | #endif | 142 | #endif |
117 | 143 | ||
144 | #ifndef MADV_HUGEPAGE | ||
145 | #define MADV_HUGEPAGE 14 | ||
146 | #endif | ||
147 | |||
148 | #ifndef MADV_NOHUGEPAGE | ||
149 | #define MADV_NOHUGEPAGE 15 | ||
150 | #endif | ||
151 | |||
152 | #ifndef MADV_DONTDUMP | ||
153 | #define MADV_DONTDUMP 16 | ||
154 | #endif | ||
155 | |||
156 | #ifndef MADV_DODUMP | ||
157 | #define MADV_DODUMP 17 | ||
158 | #endif | ||
159 | |||
160 | |||
118 | static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, | 161 | static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, |
119 | struct syscall_arg *arg) | 162 | struct syscall_arg *arg) |
120 | { | 163 | { |
@@ -131,24 +174,14 @@ static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, | |||
131 | P_MADV_BHV(DONTFORK); | 174 | P_MADV_BHV(DONTFORK); |
132 | P_MADV_BHV(DOFORK); | 175 | P_MADV_BHV(DOFORK); |
133 | P_MADV_BHV(HWPOISON); | 176 | P_MADV_BHV(HWPOISON); |
134 | #ifdef MADV_SOFT_OFFLINE | ||
135 | P_MADV_BHV(SOFT_OFFLINE); | 177 | P_MADV_BHV(SOFT_OFFLINE); |
136 | #endif | ||
137 | P_MADV_BHV(MERGEABLE); | 178 | P_MADV_BHV(MERGEABLE); |
138 | P_MADV_BHV(UNMERGEABLE); | 179 | P_MADV_BHV(UNMERGEABLE); |
139 | #ifdef MADV_HUGEPAGE | ||
140 | P_MADV_BHV(HUGEPAGE); | 180 | P_MADV_BHV(HUGEPAGE); |
141 | #endif | ||
142 | #ifdef MADV_NOHUGEPAGE | ||
143 | P_MADV_BHV(NOHUGEPAGE); | 181 | P_MADV_BHV(NOHUGEPAGE); |
144 | #endif | ||
145 | #ifdef MADV_DONTDUMP | ||
146 | P_MADV_BHV(DONTDUMP); | 182 | P_MADV_BHV(DONTDUMP); |
147 | #endif | ||
148 | #ifdef MADV_DODUMP | ||
149 | P_MADV_BHV(DODUMP); | 183 | P_MADV_BHV(DODUMP); |
150 | #endif | 184 | #undef P_MADV_BHV |
151 | #undef P_MADV_PHV | ||
152 | default: break; | 185 | default: break; |
153 | } | 186 | } |
154 | 187 | ||
diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c index 07fa8a0acad6..1106c8960cc4 100644 --- a/tools/perf/trace/beauty/msg_flags.c +++ b/tools/perf/trace/beauty/msg_flags.c | |||
@@ -33,7 +33,6 @@ static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size, | |||
33 | P_MSG_FLAG(OOB); | 33 | P_MSG_FLAG(OOB); |
34 | P_MSG_FLAG(PEEK); | 34 | P_MSG_FLAG(PEEK); |
35 | P_MSG_FLAG(DONTROUTE); | 35 | P_MSG_FLAG(DONTROUTE); |
36 | P_MSG_FLAG(TRYHARD); | ||
37 | P_MSG_FLAG(CTRUNC); | 36 | P_MSG_FLAG(CTRUNC); |
38 | P_MSG_FLAG(PROBE); | 37 | P_MSG_FLAG(PROBE); |
39 | P_MSG_FLAG(TRUNC); | 38 | P_MSG_FLAG(TRUNC); |
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c index 0f3679e0cdcf..f55a4597fc38 100644 --- a/tools/perf/trace/beauty/open_flags.c +++ b/tools/perf/trace/beauty/open_flags.c | |||
@@ -1,3 +1,18 @@ | |||
1 | #include <sys/types.h> | ||
2 | #include <sys/stat.h> | ||
3 | #include <fcntl.h> | ||
4 | |||
5 | #ifndef O_DIRECT | ||
6 | #define O_DIRECT 00040000 | ||
7 | #endif | ||
8 | |||
9 | #ifndef O_DIRECTORY | ||
10 | #define O_DIRECTORY 00200000 | ||
11 | #endif | ||
12 | |||
13 | #ifndef O_NOATIME | ||
14 | #define O_NOATIME 01000000 | ||
15 | #endif | ||
1 | 16 | ||
2 | static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, | 17 | static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, |
3 | struct syscall_arg *arg) | 18 | struct syscall_arg *arg) |
diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c index c205bc608b3c..34775295b9b3 100644 --- a/tools/perf/trace/beauty/sched_policy.c +++ b/tools/perf/trace/beauty/sched_policy.c | |||
@@ -9,6 +9,9 @@ | |||
9 | #ifndef SCHED_DEADLINE | 9 | #ifndef SCHED_DEADLINE |
10 | #define SCHED_DEADLINE 6 | 10 | #define SCHED_DEADLINE 6 |
11 | #endif | 11 | #endif |
12 | #ifndef SCHED_RESET_ON_FORK | ||
13 | #define SCHED_RESET_ON_FORK 0x40000000 | ||
14 | #endif | ||
12 | 15 | ||
13 | static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, | 16 | static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, |
14 | struct syscall_arg *arg) | 17 | struct syscall_arg *arg) |
diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c index 213c5a7e3e92..356441bce27d 100644 --- a/tools/perf/trace/beauty/seccomp.c +++ b/tools/perf/trace/beauty/seccomp.c | |||
@@ -1,5 +1,3 @@ | |||
1 | #include <linux/seccomp.h> | ||
2 | |||
3 | #ifndef SECCOMP_SET_MODE_STRICT | 1 | #ifndef SECCOMP_SET_MODE_STRICT |
4 | #define SECCOMP_SET_MODE_STRICT 0 | 2 | #define SECCOMP_SET_MODE_STRICT 0 |
5 | #endif | 3 | #endif |
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index af68a9d488bf..3eb3edb307a4 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c | |||
@@ -1,5 +1,5 @@ | |||
1 | #include "../util.h" | 1 | #include "../util.h" |
2 | #include "../cache.h" | 2 | #include "../config.h" |
3 | #include "../../perf.h" | 3 | #include "../../perf.h" |
4 | #include "libslang.h" | 4 | #include "libslang.h" |
5 | #include "ui.h" | 5 | #include "ui.h" |
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 4fc208e82c6f..2e2d10022355 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include "../../util/sort.h" | 8 | #include "../../util/sort.h" |
9 | #include "../../util/symbol.h" | 9 | #include "../../util/symbol.h" |
10 | #include "../../util/evsel.h" | 10 | #include "../../util/evsel.h" |
11 | #include "../../util/config.h" | ||
11 | #include <pthread.h> | 12 | #include <pthread.h> |
12 | 13 | ||
13 | struct disasm_line_samples { | 14 | struct disasm_line_samples { |
@@ -222,16 +223,14 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int | |||
222 | } else if (ins__is_call(dl->ins)) { | 223 | } else if (ins__is_call(dl->ins)) { |
223 | ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); | 224 | ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); |
224 | SLsmg_write_char(' '); | 225 | SLsmg_write_char(' '); |
226 | } else if (ins__is_ret(dl->ins)) { | ||
227 | ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); | ||
228 | SLsmg_write_char(' '); | ||
225 | } else { | 229 | } else { |
226 | ui_browser__write_nstring(browser, " ", 2); | 230 | ui_browser__write_nstring(browser, " ", 2); |
227 | } | 231 | } |
228 | } else { | 232 | } else { |
229 | if (strcmp(dl->name, "retq")) { | 233 | ui_browser__write_nstring(browser, " ", 2); |
230 | ui_browser__write_nstring(browser, " ", 2); | ||
231 | } else { | ||
232 | ui_browser__write_graph(browser, SLSMG_LARROW_CHAR); | ||
233 | SLsmg_write_char(' '); | ||
234 | } | ||
235 | } | 234 | } |
236 | 235 | ||
237 | disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); | 236 | disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); |
@@ -842,14 +841,14 @@ show_help: | |||
842 | ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); | 841 | ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); |
843 | else if (browser->selection->offset == -1) | 842 | else if (browser->selection->offset == -1) |
844 | ui_helpline__puts("Actions are only available for assembly lines."); | 843 | ui_helpline__puts("Actions are only available for assembly lines."); |
845 | else if (!browser->selection->ins) { | 844 | else if (!browser->selection->ins) |
846 | if (strcmp(browser->selection->name, "retq")) | 845 | goto show_sup_ins; |
847 | goto show_sup_ins; | 846 | else if (ins__is_ret(browser->selection->ins)) |
848 | goto out; | 847 | goto out; |
849 | } else if (!(annotate_browser__jump(browser) || | 848 | else if (!(annotate_browser__jump(browser) || |
850 | annotate_browser__callq(browser, evsel, hbt))) { | 849 | annotate_browser__callq(browser, evsel, hbt))) { |
851 | show_sup_ins: | 850 | show_sup_ins: |
852 | ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); | 851 | ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); |
853 | } | 852 | } |
854 | continue; | 853 | continue; |
855 | case 't': | 854 | case 't': |
@@ -1027,7 +1026,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, | |||
1027 | .use_navkeypressed = true, | 1026 | .use_navkeypressed = true, |
1028 | }, | 1027 | }, |
1029 | }; | 1028 | }; |
1030 | int ret = -1; | 1029 | int ret = -1, err; |
1031 | int nr_pcnt = 1; | 1030 | int nr_pcnt = 1; |
1032 | size_t sizeof_bdl = sizeof(struct browser_disasm_line); | 1031 | size_t sizeof_bdl = sizeof(struct browser_disasm_line); |
1033 | 1032 | ||
@@ -1051,8 +1050,11 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, | |||
1051 | (nr_pcnt - 1); | 1050 | (nr_pcnt - 1); |
1052 | } | 1051 | } |
1053 | 1052 | ||
1054 | if (symbol__annotate(sym, map, sizeof_bdl) < 0) { | 1053 | err = symbol__disassemble(sym, map, sizeof_bdl); |
1055 | ui__error("%s", ui_helpline__last_msg); | 1054 | if (err) { |
1055 | char msg[BUFSIZ]; | ||
1056 | symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); | ||
1057 | ui__error("Couldn't annotate %s:\n%s", sym->name, msg); | ||
1056 | goto out_free_offsets; | 1058 | goto out_free_offsets; |
1057 | } | 1059 | } |
1058 | 1060 | ||
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 538bae880bfe..13d414384739 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -12,35 +12,17 @@ | |||
12 | #include "../../util/top.h" | 12 | #include "../../util/top.h" |
13 | #include "../../arch/common.h" | 13 | #include "../../arch/common.h" |
14 | 14 | ||
15 | #include "../browser.h" | 15 | #include "../browsers/hists.h" |
16 | #include "../helpline.h" | 16 | #include "../helpline.h" |
17 | #include "../util.h" | 17 | #include "../util.h" |
18 | #include "../ui.h" | 18 | #include "../ui.h" |
19 | #include "map.h" | 19 | #include "map.h" |
20 | #include "annotate.h" | 20 | #include "annotate.h" |
21 | 21 | ||
22 | struct hist_browser { | ||
23 | struct ui_browser b; | ||
24 | struct hists *hists; | ||
25 | struct hist_entry *he_selection; | ||
26 | struct map_symbol *selection; | ||
27 | struct hist_browser_timer *hbt; | ||
28 | struct pstack *pstack; | ||
29 | struct perf_env *env; | ||
30 | int print_seq; | ||
31 | bool show_dso; | ||
32 | bool show_headers; | ||
33 | float min_pcnt; | ||
34 | u64 nr_non_filtered_entries; | ||
35 | u64 nr_hierarchy_entries; | ||
36 | u64 nr_callchain_rows; | ||
37 | }; | ||
38 | |||
39 | extern void hist_browser__init_hpp(void); | 22 | extern void hist_browser__init_hpp(void); |
40 | 23 | ||
41 | static int hists__browser_title(struct hists *hists, | 24 | static int perf_evsel_browser_title(struct hist_browser *browser, |
42 | struct hist_browser_timer *hbt, | 25 | char *bf, size_t size); |
43 | char *bf, size_t size); | ||
44 | static void hist_browser__update_nr_entries(struct hist_browser *hb); | 26 | static void hist_browser__update_nr_entries(struct hist_browser *hb); |
45 | 27 | ||
46 | static struct rb_node *hists__filter_entries(struct rb_node *nd, | 28 | static struct rb_node *hists__filter_entries(struct rb_node *nd, |
@@ -585,7 +567,12 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser) | |||
585 | "Or reduce the sampling frequency."); | 567 | "Or reduce the sampling frequency."); |
586 | } | 568 | } |
587 | 569 | ||
588 | static int hist_browser__run(struct hist_browser *browser, const char *help) | 570 | static int hist_browser__title(struct hist_browser *browser, char *bf, size_t size) |
571 | { | ||
572 | return browser->title ? browser->title(browser, bf, size) : 0; | ||
573 | } | ||
574 | |||
575 | int hist_browser__run(struct hist_browser *browser, const char *help) | ||
589 | { | 576 | { |
590 | int key; | 577 | int key; |
591 | char title[160]; | 578 | char title[160]; |
@@ -595,7 +582,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *help) | |||
595 | browser->b.entries = &browser->hists->entries; | 582 | browser->b.entries = &browser->hists->entries; |
596 | browser->b.nr_entries = hist_browser__nr_entries(browser); | 583 | browser->b.nr_entries = hist_browser__nr_entries(browser); |
597 | 584 | ||
598 | hists__browser_title(browser->hists, hbt, title, sizeof(title)); | 585 | hist_browser__title(browser, title, sizeof(title)); |
599 | 586 | ||
600 | if (ui_browser__show(&browser->b, title, "%s", help) < 0) | 587 | if (ui_browser__show(&browser->b, title, "%s", help) < 0) |
601 | return -1; | 588 | return -1; |
@@ -621,8 +608,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *help) | |||
621 | ui_browser__warn_lost_events(&browser->b); | 608 | ui_browser__warn_lost_events(&browser->b); |
622 | } | 609 | } |
623 | 610 | ||
624 | hists__browser_title(browser->hists, | 611 | hist_browser__title(browser, title, sizeof(title)); |
625 | hbt, title, sizeof(title)); | ||
626 | ui_browser__show_title(&browser->b, title); | 612 | ui_browser__show_title(&browser->b, title); |
627 | continue; | 613 | continue; |
628 | } | 614 | } |
@@ -1470,7 +1456,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser, | |||
1470 | column++ < browser->b.horiz_scroll) | 1456 | column++ < browser->b.horiz_scroll) |
1471 | continue; | 1457 | continue; |
1472 | 1458 | ||
1473 | ret = fmt->width(fmt, NULL, hists_to_evsel(browser->hists)); | 1459 | ret = fmt->width(fmt, NULL, browser->hists); |
1474 | 1460 | ||
1475 | if (first) { | 1461 | if (first) { |
1476 | /* for folded sign */ | 1462 | /* for folded sign */ |
@@ -1531,7 +1517,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char * | |||
1531 | if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) | 1517 | if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) |
1532 | continue; | 1518 | continue; |
1533 | 1519 | ||
1534 | ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); | 1520 | ret = fmt->header(fmt, &dummy_hpp, hists); |
1535 | if (advance_hpp_check(&dummy_hpp, ret)) | 1521 | if (advance_hpp_check(&dummy_hpp, ret)) |
1536 | break; | 1522 | break; |
1537 | 1523 | ||
@@ -1568,7 +1554,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows | |||
1568 | if (column++ < browser->b.horiz_scroll) | 1554 | if (column++ < browser->b.horiz_scroll) |
1569 | continue; | 1555 | continue; |
1570 | 1556 | ||
1571 | ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); | 1557 | ret = fmt->header(fmt, &dummy_hpp, hists); |
1572 | if (advance_hpp_check(&dummy_hpp, ret)) | 1558 | if (advance_hpp_check(&dummy_hpp, ret)) |
1573 | break; | 1559 | break; |
1574 | 1560 | ||
@@ -1605,7 +1591,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows | |||
1605 | } | 1591 | } |
1606 | first_col = false; | 1592 | first_col = false; |
1607 | 1593 | ||
1608 | ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); | 1594 | ret = fmt->header(fmt, &dummy_hpp, hists); |
1609 | dummy_hpp.buf[ret] = '\0'; | 1595 | dummy_hpp.buf[ret] = '\0'; |
1610 | 1596 | ||
1611 | start = trim(dummy_hpp.buf); | 1597 | start = trim(dummy_hpp.buf); |
@@ -1622,21 +1608,38 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows | |||
1622 | return ret; | 1608 | return ret; |
1623 | } | 1609 | } |
1624 | 1610 | ||
1625 | static void hist_browser__show_headers(struct hist_browser *browser) | 1611 | static void hists_browser__hierarchy_headers(struct hist_browser *browser) |
1626 | { | 1612 | { |
1627 | char headers[1024]; | 1613 | char headers[1024]; |
1628 | 1614 | ||
1629 | if (symbol_conf.report_hierarchy) | 1615 | hists_browser__scnprintf_hierarchy_headers(browser, headers, |
1630 | hists_browser__scnprintf_hierarchy_headers(browser, headers, | 1616 | sizeof(headers)); |
1631 | sizeof(headers)); | 1617 | |
1632 | else | 1618 | ui_browser__gotorc(&browser->b, 0, 0); |
1633 | hists_browser__scnprintf_headers(browser, headers, | 1619 | ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); |
1634 | sizeof(headers)); | 1620 | ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); |
1621 | } | ||
1622 | |||
1623 | static void hists_browser__headers(struct hist_browser *browser) | ||
1624 | { | ||
1625 | char headers[1024]; | ||
1626 | |||
1627 | hists_browser__scnprintf_headers(browser, headers, | ||
1628 | sizeof(headers)); | ||
1629 | |||
1635 | ui_browser__gotorc(&browser->b, 0, 0); | 1630 | ui_browser__gotorc(&browser->b, 0, 0); |
1636 | ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); | 1631 | ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); |
1637 | ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); | 1632 | ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); |
1638 | } | 1633 | } |
1639 | 1634 | ||
1635 | static void hist_browser__show_headers(struct hist_browser *browser) | ||
1636 | { | ||
1637 | if (symbol_conf.report_hierarchy) | ||
1638 | hists_browser__hierarchy_headers(browser); | ||
1639 | else | ||
1640 | hists_browser__headers(browser); | ||
1641 | } | ||
1642 | |||
1640 | static void ui_browser__hists_init_top(struct ui_browser *browser) | 1643 | static void ui_browser__hists_init_top(struct ui_browser *browser) |
1641 | { | 1644 | { |
1642 | if (browser->top == NULL) { | 1645 | if (browser->top == NULL) { |
@@ -2026,7 +2029,7 @@ static int hist_browser__dump(struct hist_browser *browser) | |||
2026 | fp = fopen(filename, "w"); | 2029 | fp = fopen(filename, "w"); |
2027 | if (fp == NULL) { | 2030 | if (fp == NULL) { |
2028 | char bf[64]; | 2031 | char bf[64]; |
2029 | const char *err = strerror_r(errno, bf, sizeof(bf)); | 2032 | const char *err = str_error_r(errno, bf, sizeof(bf)); |
2030 | ui_helpline__fpush("Couldn't write to %s: %s", filename, err); | 2033 | ui_helpline__fpush("Couldn't write to %s: %s", filename, err); |
2031 | return -1; | 2034 | return -1; |
2032 | } | 2035 | } |
@@ -2039,27 +2042,50 @@ static int hist_browser__dump(struct hist_browser *browser) | |||
2039 | return 0; | 2042 | return 0; |
2040 | } | 2043 | } |
2041 | 2044 | ||
2042 | static struct hist_browser *hist_browser__new(struct hists *hists, | 2045 | void hist_browser__init(struct hist_browser *browser, |
2043 | struct hist_browser_timer *hbt, | 2046 | struct hists *hists) |
2044 | struct perf_env *env) | 2047 | { |
2048 | struct perf_hpp_fmt *fmt; | ||
2049 | |||
2050 | browser->hists = hists; | ||
2051 | browser->b.refresh = hist_browser__refresh; | ||
2052 | browser->b.refresh_dimensions = hist_browser__refresh_dimensions; | ||
2053 | browser->b.seek = ui_browser__hists_seek; | ||
2054 | browser->b.use_navkeypressed = true; | ||
2055 | browser->show_headers = symbol_conf.show_hist_headers; | ||
2056 | |||
2057 | hists__for_each_format(hists, fmt) { | ||
2058 | perf_hpp__reset_width(fmt, hists); | ||
2059 | ++browser->b.columns; | ||
2060 | } | ||
2061 | } | ||
2062 | |||
2063 | struct hist_browser *hist_browser__new(struct hists *hists) | ||
2045 | { | 2064 | { |
2046 | struct hist_browser *browser = zalloc(sizeof(*browser)); | 2065 | struct hist_browser *browser = zalloc(sizeof(*browser)); |
2047 | 2066 | ||
2067 | if (browser) | ||
2068 | hist_browser__init(browser, hists); | ||
2069 | |||
2070 | return browser; | ||
2071 | } | ||
2072 | |||
2073 | static struct hist_browser * | ||
2074 | perf_evsel_browser__new(struct perf_evsel *evsel, | ||
2075 | struct hist_browser_timer *hbt, | ||
2076 | struct perf_env *env) | ||
2077 | { | ||
2078 | struct hist_browser *browser = hist_browser__new(evsel__hists(evsel)); | ||
2079 | |||
2048 | if (browser) { | 2080 | if (browser) { |
2049 | browser->hists = hists; | 2081 | browser->hbt = hbt; |
2050 | browser->b.refresh = hist_browser__refresh; | 2082 | browser->env = env; |
2051 | browser->b.refresh_dimensions = hist_browser__refresh_dimensions; | 2083 | browser->title = perf_evsel_browser_title; |
2052 | browser->b.seek = ui_browser__hists_seek; | ||
2053 | browser->b.use_navkeypressed = true; | ||
2054 | browser->show_headers = symbol_conf.show_hist_headers; | ||
2055 | browser->hbt = hbt; | ||
2056 | browser->env = env; | ||
2057 | } | 2084 | } |
2058 | |||
2059 | return browser; | 2085 | return browser; |
2060 | } | 2086 | } |
2061 | 2087 | ||
2062 | static void hist_browser__delete(struct hist_browser *browser) | 2088 | void hist_browser__delete(struct hist_browser *browser) |
2063 | { | 2089 | { |
2064 | free(browser); | 2090 | free(browser); |
2065 | } | 2091 | } |
@@ -2080,10 +2106,11 @@ static inline bool is_report_browser(void *timer) | |||
2080 | return timer == NULL; | 2106 | return timer == NULL; |
2081 | } | 2107 | } |
2082 | 2108 | ||
2083 | static int hists__browser_title(struct hists *hists, | 2109 | static int perf_evsel_browser_title(struct hist_browser *browser, |
2084 | struct hist_browser_timer *hbt, | ||
2085 | char *bf, size_t size) | 2110 | char *bf, size_t size) |
2086 | { | 2111 | { |
2112 | struct hist_browser_timer *hbt = browser->hbt; | ||
2113 | struct hists *hists = browser->hists; | ||
2087 | char unit; | 2114 | char unit; |
2088 | int printed; | 2115 | int printed; |
2089 | const struct dso *dso = hists->dso_filter; | 2116 | const struct dso *dso = hists->dso_filter; |
@@ -2640,7 +2667,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
2640 | struct perf_env *env) | 2667 | struct perf_env *env) |
2641 | { | 2668 | { |
2642 | struct hists *hists = evsel__hists(evsel); | 2669 | struct hists *hists = evsel__hists(evsel); |
2643 | struct hist_browser *browser = hist_browser__new(hists, hbt, env); | 2670 | struct hist_browser *browser = perf_evsel_browser__new(evsel, hbt, env); |
2644 | struct branch_info *bi; | 2671 | struct branch_info *bi; |
2645 | #define MAX_OPTIONS 16 | 2672 | #define MAX_OPTIONS 16 |
2646 | char *options[MAX_OPTIONS]; | 2673 | char *options[MAX_OPTIONS]; |
@@ -2649,7 +2676,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
2649 | int key = -1; | 2676 | int key = -1; |
2650 | char buf[64]; | 2677 | char buf[64]; |
2651 | int delay_secs = hbt ? hbt->refresh : 0; | 2678 | int delay_secs = hbt ? hbt->refresh : 0; |
2652 | struct perf_hpp_fmt *fmt; | ||
2653 | 2679 | ||
2654 | #define HIST_BROWSER_HELP_COMMON \ | 2680 | #define HIST_BROWSER_HELP_COMMON \ |
2655 | "h/?/F1 Show this window\n" \ | 2681 | "h/?/F1 Show this window\n" \ |
@@ -2708,18 +2734,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
2708 | memset(options, 0, sizeof(options)); | 2734 | memset(options, 0, sizeof(options)); |
2709 | memset(actions, 0, sizeof(actions)); | 2735 | memset(actions, 0, sizeof(actions)); |
2710 | 2736 | ||
2711 | hists__for_each_format(browser->hists, fmt) { | ||
2712 | perf_hpp__reset_width(fmt, hists); | ||
2713 | /* | ||
2714 | * This is done just once, and activates the horizontal scrolling | ||
2715 | * code in the ui_browser code, it would be better to have a the | ||
2716 | * counter in the perf_hpp code, but I couldn't find doing it here | ||
2717 | * works, FIXME by setting this in hist_browser__new, for now, be | ||
2718 | * clever 8-) | ||
2719 | */ | ||
2720 | ++browser->b.columns; | ||
2721 | } | ||
2722 | |||
2723 | if (symbol_conf.col_width_list_str) | 2737 | if (symbol_conf.col_width_list_str) |
2724 | perf_hpp__set_user_width(symbol_conf.col_width_list_str); | 2738 | perf_hpp__set_user_width(symbol_conf.col_width_list_str); |
2725 | 2739 | ||
@@ -3185,7 +3199,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, | |||
3185 | 3199 | ||
3186 | ui_helpline__push("Press ESC to exit"); | 3200 | ui_helpline__push("Press ESC to exit"); |
3187 | 3201 | ||
3188 | evlist__for_each(evlist, pos) { | 3202 | evlist__for_each_entry(evlist, pos) { |
3189 | const char *ev_name = perf_evsel__name(pos); | 3203 | const char *ev_name = perf_evsel__name(pos); |
3190 | size_t line_len = strlen(ev_name) + 7; | 3204 | size_t line_len = strlen(ev_name) + 7; |
3191 | 3205 | ||
@@ -3216,7 +3230,7 @@ single_entry: | |||
3216 | struct perf_evsel *pos; | 3230 | struct perf_evsel *pos; |
3217 | 3231 | ||
3218 | nr_entries = 0; | 3232 | nr_entries = 0; |
3219 | evlist__for_each(evlist, pos) { | 3233 | evlist__for_each_entry(evlist, pos) { |
3220 | if (perf_evsel__is_group_leader(pos)) | 3234 | if (perf_evsel__is_group_leader(pos)) |
3221 | nr_entries++; | 3235 | nr_entries++; |
3222 | } | 3236 | } |
diff --git a/tools/perf/ui/browsers/hists.h b/tools/perf/ui/browsers/hists.h new file mode 100644 index 000000000000..39bd0f28f211 --- /dev/null +++ b/tools/perf/ui/browsers/hists.h | |||
@@ -0,0 +1,32 @@ | |||
1 | #ifndef _PERF_UI_BROWSER_HISTS_H_ | ||
2 | #define _PERF_UI_BROWSER_HISTS_H_ 1 | ||
3 | |||
4 | #include "ui/browser.h" | ||
5 | |||
6 | struct hist_browser { | ||
7 | struct ui_browser b; | ||
8 | struct hists *hists; | ||
9 | struct hist_entry *he_selection; | ||
10 | struct map_symbol *selection; | ||
11 | struct hist_browser_timer *hbt; | ||
12 | struct pstack *pstack; | ||
13 | struct perf_env *env; | ||
14 | int print_seq; | ||
15 | bool show_dso; | ||
16 | bool show_headers; | ||
17 | float min_pcnt; | ||
18 | u64 nr_non_filtered_entries; | ||
19 | u64 nr_hierarchy_entries; | ||
20 | u64 nr_callchain_rows; | ||
21 | |||
22 | /* Get title string. */ | ||
23 | int (*title)(struct hist_browser *browser, | ||
24 | char *bf, size_t size); | ||
25 | }; | ||
26 | |||
27 | struct hist_browser *hist_browser__new(struct hists *hists); | ||
28 | void hist_browser__delete(struct hist_browser *browser); | ||
29 | int hist_browser__run(struct hist_browser *browser, const char *help); | ||
30 | void hist_browser__init(struct hist_browser *browser, | ||
31 | struct hists *hists); | ||
32 | #endif /* _PERF_UI_BROWSER_HISTS_H_ */ | ||
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c index 9c7ff8d31b27..42d319927762 100644 --- a/tools/perf/ui/gtk/annotate.c +++ b/tools/perf/ui/gtk/annotate.c | |||
@@ -162,12 +162,16 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map, | |||
162 | GtkWidget *notebook; | 162 | GtkWidget *notebook; |
163 | GtkWidget *scrolled_window; | 163 | GtkWidget *scrolled_window; |
164 | GtkWidget *tab_label; | 164 | GtkWidget *tab_label; |
165 | int err; | ||
165 | 166 | ||
166 | if (map->dso->annotate_warned) | 167 | if (map->dso->annotate_warned) |
167 | return -1; | 168 | return -1; |
168 | 169 | ||
169 | if (symbol__annotate(sym, map, 0) < 0) { | 170 | err = symbol__disassemble(sym, map, 0); |
170 | ui__error("%s", ui_helpline__current); | 171 | if (err) { |
172 | char msg[BUFSIZ]; | ||
173 | symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); | ||
174 | ui__error("Couldn't annotate %s: %s\n", sym->name, msg); | ||
171 | return -1; | 175 | return -1; |
172 | } | 176 | } |
173 | 177 | ||
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 932adfaa05af..c5f3677f6679 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c | |||
@@ -549,7 +549,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists, | |||
549 | strcat(buf, "+"); | 549 | strcat(buf, "+"); |
550 | first_col = false; | 550 | first_col = false; |
551 | 551 | ||
552 | fmt->header(fmt, &hpp, hists_to_evsel(hists)); | 552 | fmt->header(fmt, &hpp, hists); |
553 | strcat(buf, ltrim(rtrim(hpp.buf))); | 553 | strcat(buf, ltrim(rtrim(hpp.buf))); |
554 | } | 554 | } |
555 | } | 555 | } |
@@ -627,7 +627,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, | |||
627 | 627 | ||
628 | gtk_container_add(GTK_CONTAINER(window), vbox); | 628 | gtk_container_add(GTK_CONTAINER(window), vbox); |
629 | 629 | ||
630 | evlist__for_each(evlist, pos) { | 630 | evlist__for_each_entry(evlist, pos) { |
631 | struct hists *hists = evsel__hists(pos); | 631 | struct hists *hists = evsel__hists(pos); |
632 | const char *evname = perf_evsel__name(pos); | 632 | const char *evname = perf_evsel__name(pos); |
633 | GtkWidget *scrolled_window; | 633 | GtkWidget *scrolled_window; |
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c index 52e7fc48af9f..00b91921edb1 100644 --- a/tools/perf/ui/gtk/util.c +++ b/tools/perf/ui/gtk/util.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include "../util.h" | 1 | #include "../util.h" |
2 | #include "../../util/util.h" | ||
2 | #include "../../util/debug.h" | 3 | #include "../../util/debug.h" |
3 | #include "gtk.h" | 4 | #include "gtk.h" |
4 | 5 | ||
diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c index 700fb3cfa1c7..5b74a7eba210 100644 --- a/tools/perf/ui/helpline.c +++ b/tools/perf/ui/helpline.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "../debug.h" | 5 | #include "../debug.h" |
6 | #include "helpline.h" | 6 | #include "helpline.h" |
7 | #include "ui.h" | 7 | #include "ui.h" |
8 | #include "../util.h" | ||
8 | 9 | ||
9 | char ui_helpline__current[512]; | 10 | char ui_helpline__current[512]; |
10 | 11 | ||
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index af07ffb129ca..4274969ddc89 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
@@ -215,9 +215,10 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b, | |||
215 | 215 | ||
216 | static int hpp__width_fn(struct perf_hpp_fmt *fmt, | 216 | static int hpp__width_fn(struct perf_hpp_fmt *fmt, |
217 | struct perf_hpp *hpp __maybe_unused, | 217 | struct perf_hpp *hpp __maybe_unused, |
218 | struct perf_evsel *evsel) | 218 | struct hists *hists) |
219 | { | 219 | { |
220 | int len = fmt->user_len ?: fmt->len; | 220 | int len = fmt->user_len ?: fmt->len; |
221 | struct perf_evsel *evsel = hists_to_evsel(hists); | ||
221 | 222 | ||
222 | if (symbol_conf.event_group) | 223 | if (symbol_conf.event_group) |
223 | len = max(len, evsel->nr_members * fmt->len); | 224 | len = max(len, evsel->nr_members * fmt->len); |
@@ -229,9 +230,9 @@ static int hpp__width_fn(struct perf_hpp_fmt *fmt, | |||
229 | } | 230 | } |
230 | 231 | ||
231 | static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 232 | static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
232 | struct perf_evsel *evsel) | 233 | struct hists *hists) |
233 | { | 234 | { |
234 | int len = hpp__width_fn(fmt, hpp, evsel); | 235 | int len = hpp__width_fn(fmt, hpp, hists); |
235 | return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name); | 236 | return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name); |
236 | } | 237 | } |
237 | 238 | ||
@@ -632,7 +633,7 @@ unsigned int hists__sort_list_width(struct hists *hists) | |||
632 | else | 633 | else |
633 | ret += 2; | 634 | ret += 2; |
634 | 635 | ||
635 | ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); | 636 | ret += fmt->width(fmt, &dummy_hpp, hists); |
636 | } | 637 | } |
637 | 638 | ||
638 | if (verbose && hists__has(hists, sym)) /* Addr + origin */ | 639 | if (verbose && hists__has(hists, sym)) /* Addr + origin */ |
@@ -657,7 +658,7 @@ unsigned int hists__overhead_width(struct hists *hists) | |||
657 | else | 658 | else |
658 | ret += 2; | 659 | ret += 2; |
659 | 660 | ||
660 | ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); | 661 | ret += fmt->width(fmt, &dummy_hpp, hists); |
661 | } | 662 | } |
662 | 663 | ||
663 | return ret; | 664 | return ret; |
@@ -765,7 +766,7 @@ int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, | |||
765 | if (!symbol_conf.report_hierarchy) | 766 | if (!symbol_conf.report_hierarchy) |
766 | return 0; | 767 | return 0; |
767 | 768 | ||
768 | evlist__for_each(evlist, evsel) { | 769 | evlist__for_each_entry(evlist, evsel) { |
769 | hists = evsel__hists(evsel); | 770 | hists = evsel__hists(evsel); |
770 | 771 | ||
771 | perf_hpp_list__for_each_sort_list(list, fmt) { | 772 | perf_hpp_list__for_each_sort_list(list, fmt) { |
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c index ba51fa8a1176..1f6b0994f4f4 100644 --- a/tools/perf/ui/setup.c +++ b/tools/perf/ui/setup.c | |||
@@ -60,6 +60,13 @@ static inline int setup_gtk_browser(void) { return -1; } | |||
60 | static inline void exit_gtk_browser(bool wait_for_ok __maybe_unused) {} | 60 | static inline void exit_gtk_browser(bool wait_for_ok __maybe_unused) {} |
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | int stdio__config_color(const struct option *opt __maybe_unused, | ||
64 | const char *mode, int unset __maybe_unused) | ||
65 | { | ||
66 | perf_use_color_default = perf_config_colorbool("color.ui", mode, -1); | ||
67 | return 0; | ||
68 | } | ||
69 | |||
63 | void setup_browser(bool fallback_to_pager) | 70 | void setup_browser(bool fallback_to_pager) |
64 | { | 71 | { |
65 | if (use_browser < 2 && (!isatty(1) || dump_trace)) | 72 | if (use_browser < 2 && (!isatty(1) || dump_trace)) |
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 560eb47d56f9..f04a63112079 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
@@ -492,14 +492,15 @@ out: | |||
492 | } | 492 | } |
493 | 493 | ||
494 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, | 494 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, |
495 | struct hists *hists, | 495 | char *bf, size_t bfsz, FILE *fp, |
496 | char *bf, size_t bfsz, FILE *fp) | 496 | bool use_callchain) |
497 | { | 497 | { |
498 | int ret; | 498 | int ret; |
499 | struct perf_hpp hpp = { | 499 | struct perf_hpp hpp = { |
500 | .buf = bf, | 500 | .buf = bf, |
501 | .size = size, | 501 | .size = size, |
502 | }; | 502 | }; |
503 | struct hists *hists = he->hists; | ||
503 | u64 total_period = hists->stats.total_period; | 504 | u64 total_period = hists->stats.total_period; |
504 | 505 | ||
505 | if (size == 0 || size > bfsz) | 506 | if (size == 0 || size > bfsz) |
@@ -512,7 +513,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, | |||
512 | 513 | ||
513 | ret = fprintf(fp, "%s\n", bf); | 514 | ret = fprintf(fp, "%s\n", bf); |
514 | 515 | ||
515 | if (symbol_conf.use_callchain) | 516 | if (use_callchain) |
516 | ret += hist_entry_callchain__fprintf(he, total_period, 0, fp); | 517 | ret += hist_entry_callchain__fprintf(he, total_period, 0, fp); |
517 | 518 | ||
518 | return ret; | 519 | return ret; |
@@ -548,7 +549,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, | |||
548 | struct perf_hpp_list_node, list); | 549 | struct perf_hpp_list_node, list); |
549 | 550 | ||
550 | perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { | 551 | perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { |
551 | fmt->header(fmt, hpp, hists_to_evsel(hists)); | 552 | fmt->header(fmt, hpp, hists); |
552 | fprintf(fp, "%s%s", hpp->buf, sep ?: " "); | 553 | fprintf(fp, "%s%s", hpp->buf, sep ?: " "); |
553 | } | 554 | } |
554 | 555 | ||
@@ -568,7 +569,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, | |||
568 | header_width += fprintf(fp, "+"); | 569 | header_width += fprintf(fp, "+"); |
569 | first_col = false; | 570 | first_col = false; |
570 | 571 | ||
571 | fmt->header(fmt, hpp, hists_to_evsel(hists)); | 572 | fmt->header(fmt, hpp, hists); |
572 | 573 | ||
573 | header_width += fprintf(fp, "%s", trim(hpp->buf)); | 574 | header_width += fprintf(fp, "%s", trim(hpp->buf)); |
574 | } | 575 | } |
@@ -589,7 +590,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, | |||
589 | fprintf(fp, "%s", sep ?: ".."); | 590 | fprintf(fp, "%s", sep ?: ".."); |
590 | first_col = false; | 591 | first_col = false; |
591 | 592 | ||
592 | width = fmt->width(fmt, hpp, hists_to_evsel(hists)); | 593 | width = fmt->width(fmt, hpp, hists); |
593 | fprintf(fp, "%.*s", width, dots); | 594 | fprintf(fp, "%.*s", width, dots); |
594 | } | 595 | } |
595 | 596 | ||
@@ -606,7 +607,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, | |||
606 | width++; /* for '+' sign between column header */ | 607 | width++; /* for '+' sign between column header */ |
607 | first_col = false; | 608 | first_col = false; |
608 | 609 | ||
609 | width += fmt->width(fmt, hpp, hists_to_evsel(hists)); | 610 | width += fmt->width(fmt, hpp, hists); |
610 | } | 611 | } |
611 | 612 | ||
612 | if (width > header_width) | 613 | if (width > header_width) |
@@ -622,47 +623,31 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, | |||
622 | return 2; | 623 | return 2; |
623 | } | 624 | } |
624 | 625 | ||
625 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | 626 | static int |
626 | int max_cols, float min_pcnt, FILE *fp) | 627 | hists__fprintf_hierarchy_headers(struct hists *hists, |
628 | struct perf_hpp *hpp, | ||
629 | FILE *fp) | ||
627 | { | 630 | { |
628 | struct perf_hpp_fmt *fmt; | ||
629 | struct perf_hpp_list_node *fmt_node; | 631 | struct perf_hpp_list_node *fmt_node; |
630 | struct rb_node *nd; | 632 | struct perf_hpp_fmt *fmt; |
631 | size_t ret = 0; | ||
632 | unsigned int width; | ||
633 | const char *sep = symbol_conf.field_sep; | ||
634 | int nr_rows = 0; | ||
635 | char bf[96]; | ||
636 | struct perf_hpp dummy_hpp = { | ||
637 | .buf = bf, | ||
638 | .size = sizeof(bf), | ||
639 | }; | ||
640 | bool first = true; | ||
641 | size_t linesz; | ||
642 | char *line = NULL; | ||
643 | unsigned indent; | ||
644 | |||
645 | init_rem_hits(); | ||
646 | |||
647 | hists__for_each_format(hists, fmt) | ||
648 | perf_hpp__reset_width(fmt, hists); | ||
649 | |||
650 | if (symbol_conf.col_width_list_str) | ||
651 | perf_hpp__set_user_width(symbol_conf.col_width_list_str); | ||
652 | 633 | ||
653 | if (!show_header) | 634 | list_for_each_entry(fmt_node, &hists->hpp_formats, list) { |
654 | goto print_entries; | 635 | perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) |
636 | perf_hpp__reset_width(fmt, hists); | ||
637 | } | ||
655 | 638 | ||
656 | fprintf(fp, "# "); | 639 | return print_hierarchy_header(hists, hpp, symbol_conf.field_sep, fp); |
640 | } | ||
657 | 641 | ||
658 | if (symbol_conf.report_hierarchy) { | 642 | static int |
659 | list_for_each_entry(fmt_node, &hists->hpp_formats, list) { | 643 | hists__fprintf_standard_headers(struct hists *hists, |
660 | perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) | 644 | struct perf_hpp *hpp, |
661 | perf_hpp__reset_width(fmt, hists); | 645 | FILE *fp) |
662 | } | 646 | { |
663 | nr_rows += print_hierarchy_header(hists, &dummy_hpp, sep, fp); | 647 | struct perf_hpp_fmt *fmt; |
664 | goto print_entries; | 648 | unsigned int width; |
665 | } | 649 | const char *sep = symbol_conf.field_sep; |
650 | bool first = true; | ||
666 | 651 | ||
667 | hists__for_each_format(hists, fmt) { | 652 | hists__for_each_format(hists, fmt) { |
668 | if (perf_hpp__should_skip(fmt, hists)) | 653 | if (perf_hpp__should_skip(fmt, hists)) |
@@ -673,16 +658,14 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | |||
673 | else | 658 | else |
674 | first = false; | 659 | first = false; |
675 | 660 | ||
676 | fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); | 661 | fmt->header(fmt, hpp, hists); |
677 | fprintf(fp, "%s", bf); | 662 | fprintf(fp, "%s", hpp->buf); |
678 | } | 663 | } |
679 | 664 | ||
680 | fprintf(fp, "\n"); | 665 | fprintf(fp, "\n"); |
681 | if (max_rows && ++nr_rows >= max_rows) | ||
682 | goto out; | ||
683 | 666 | ||
684 | if (sep) | 667 | if (sep) |
685 | goto print_entries; | 668 | return 1; |
686 | 669 | ||
687 | first = true; | 670 | first = true; |
688 | 671 | ||
@@ -699,20 +682,60 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | |||
699 | else | 682 | else |
700 | first = false; | 683 | first = false; |
701 | 684 | ||
702 | width = fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); | 685 | width = fmt->width(fmt, hpp, hists); |
703 | for (i = 0; i < width; i++) | 686 | for (i = 0; i < width; i++) |
704 | fprintf(fp, "."); | 687 | fprintf(fp, "."); |
705 | } | 688 | } |
706 | 689 | ||
707 | fprintf(fp, "\n"); | 690 | fprintf(fp, "\n"); |
708 | if (max_rows && ++nr_rows >= max_rows) | ||
709 | goto out; | ||
710 | |||
711 | fprintf(fp, "#\n"); | 691 | fprintf(fp, "#\n"); |
712 | if (max_rows && ++nr_rows >= max_rows) | 692 | return 3; |
693 | } | ||
694 | |||
695 | static int hists__fprintf_headers(struct hists *hists, FILE *fp) | ||
696 | { | ||
697 | char bf[96]; | ||
698 | struct perf_hpp dummy_hpp = { | ||
699 | .buf = bf, | ||
700 | .size = sizeof(bf), | ||
701 | }; | ||
702 | |||
703 | fprintf(fp, "# "); | ||
704 | |||
705 | if (symbol_conf.report_hierarchy) | ||
706 | return hists__fprintf_hierarchy_headers(hists, &dummy_hpp, fp); | ||
707 | else | ||
708 | return hists__fprintf_standard_headers(hists, &dummy_hpp, fp); | ||
709 | |||
710 | } | ||
711 | |||
712 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | ||
713 | int max_cols, float min_pcnt, FILE *fp, | ||
714 | bool use_callchain) | ||
715 | { | ||
716 | struct perf_hpp_fmt *fmt; | ||
717 | struct rb_node *nd; | ||
718 | size_t ret = 0; | ||
719 | const char *sep = symbol_conf.field_sep; | ||
720 | int nr_rows = 0; | ||
721 | size_t linesz; | ||
722 | char *line = NULL; | ||
723 | unsigned indent; | ||
724 | |||
725 | init_rem_hits(); | ||
726 | |||
727 | hists__for_each_format(hists, fmt) | ||
728 | perf_hpp__reset_width(fmt, hists); | ||
729 | |||
730 | if (symbol_conf.col_width_list_str) | ||
731 | perf_hpp__set_user_width(symbol_conf.col_width_list_str); | ||
732 | |||
733 | if (show_header) | ||
734 | nr_rows += hists__fprintf_headers(hists, fp); | ||
735 | |||
736 | if (max_rows && nr_rows >= max_rows) | ||
713 | goto out; | 737 | goto out; |
714 | 738 | ||
715 | print_entries: | ||
716 | linesz = hists__sort_list_width(hists) + 3 + 1; | 739 | linesz = hists__sort_list_width(hists) + 3 + 1; |
717 | linesz += perf_hpp__color_overhead(); | 740 | linesz += perf_hpp__color_overhead(); |
718 | line = malloc(linesz); | 741 | line = malloc(linesz); |
@@ -734,7 +757,7 @@ print_entries: | |||
734 | if (percent < min_pcnt) | 757 | if (percent < min_pcnt) |
735 | continue; | 758 | continue; |
736 | 759 | ||
737 | ret += hist_entry__fprintf(h, max_cols, hists, line, linesz, fp); | 760 | ret += hist_entry__fprintf(h, max_cols, line, linesz, fp, use_callchain); |
738 | 761 | ||
739 | if (max_rows && ++nr_rows >= max_rows) | 762 | if (max_rows && ++nr_rows >= max_rows) |
740 | break; | 763 | break; |
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c index 7dfeba0a91f3..4ea2ba861fc2 100644 --- a/tools/perf/ui/tui/setup.c +++ b/tools/perf/ui/tui/setup.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <errno.h> | ||
1 | #include <signal.h> | 2 | #include <signal.h> |
2 | #include <stdbool.h> | 3 | #include <stdbool.h> |
3 | #ifdef HAVE_BACKTRACE_SUPPORT | 4 | #ifdef HAVE_BACKTRACE_SUPPORT |
@@ -6,6 +7,7 @@ | |||
6 | 7 | ||
7 | #include "../../util/cache.h" | 8 | #include "../../util/cache.h" |
8 | #include "../../util/debug.h" | 9 | #include "../../util/debug.h" |
10 | #include "../../util/util.h" | ||
9 | #include "../browser.h" | 11 | #include "../browser.h" |
10 | #include "../helpline.h" | 12 | #include "../helpline.h" |
11 | #include "../ui.h" | 13 | #include "../ui.h" |
diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h index ab88383f8be8..4b6fb6c7a542 100644 --- a/tools/perf/ui/ui.h +++ b/tools/perf/ui/ui.h | |||
@@ -26,4 +26,8 @@ static inline void ui__exit(bool wait_for_ok __maybe_unused) {} | |||
26 | 26 | ||
27 | void ui__refresh_dimensions(bool force); | 27 | void ui__refresh_dimensions(bool force); |
28 | 28 | ||
29 | struct option; | ||
30 | |||
31 | int stdio__config_color(const struct option *opt, const char *mode, int unset); | ||
32 | |||
29 | #endif /* _PERF_UI_H_ */ | 33 | #endif /* _PERF_UI_H_ */ |
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 8c6c8a0ca642..91c5f6e1af59 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
@@ -84,6 +84,7 @@ libperf-y += parse-regs-options.o | |||
84 | libperf-y += term.o | 84 | libperf-y += term.o |
85 | libperf-y += help-unknown-cmd.o | 85 | libperf-y += help-unknown-cmd.o |
86 | libperf-y += mem-events.o | 86 | libperf-y += mem-events.o |
87 | libperf-y += vsprintf.o | ||
87 | 88 | ||
88 | libperf-$(CONFIG_LIBBPF) += bpf-loader.o | 89 | libperf-$(CONFIG_LIBBPF) += bpf-loader.o |
89 | libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o | 90 | libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o |
@@ -99,7 +100,10 @@ libperf-$(CONFIG_DWARF) += probe-finder.o | |||
99 | libperf-$(CONFIG_DWARF) += dwarf-aux.o | 100 | libperf-$(CONFIG_DWARF) += dwarf-aux.o |
100 | 101 | ||
101 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o | 102 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o |
103 | libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o | ||
102 | libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o | 104 | libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o |
105 | libperf-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o | ||
106 | libperf-$(CONFIG_LIBUNWIND_AARCH64) += libunwind/arm64.o | ||
103 | 107 | ||
104 | libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o | 108 | libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o |
105 | 109 | ||
@@ -108,6 +112,7 @@ libperf-y += scripting-engines/ | |||
108 | libperf-$(CONFIG_ZLIB) += zlib.o | 112 | libperf-$(CONFIG_ZLIB) += zlib.o |
109 | libperf-$(CONFIG_LZMA) += lzma.o | 113 | libperf-$(CONFIG_LZMA) += lzma.o |
110 | libperf-y += demangle-java.o | 114 | libperf-y += demangle-java.o |
115 | libperf-y += demangle-rust.o | ||
111 | 116 | ||
112 | ifdef CONFIG_JITDUMP | 117 | ifdef CONFIG_JITDUMP |
113 | libperf-$(CONFIG_LIBELF) += jitdump.o | 118 | libperf-$(CONFIG_LIBELF) += jitdump.o |
@@ -173,3 +178,7 @@ $(OUTPUT)util/libstring.o: ../lib/string.c FORCE | |||
173 | $(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE | 178 | $(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE |
174 | $(call rule_mkdir) | 179 | $(call rule_mkdir) |
175 | $(call if_changed_dep,cc_o_c) | 180 | $(call if_changed_dep,cc_o_c) |
181 | |||
182 | $(OUTPUT)util/vsprintf.o: ../lib/vsprintf.c FORCE | ||
183 | $(call rule_mkdir) | ||
184 | $(call if_changed_dep,cc_o_c) | ||
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c index c0b43ee40d95..6455471d9cd1 100644 --- a/tools/perf/util/alias.c +++ b/tools/perf/util/alias.c | |||
@@ -1,4 +1,6 @@ | |||
1 | #include "cache.h" | 1 | #include "cache.h" |
2 | #include "util.h" | ||
3 | #include "config.h" | ||
2 | 4 | ||
3 | static const char *alias_key; | 5 | static const char *alias_key; |
4 | static char *alias_val; | 6 | static char *alias_val; |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 7e5a1e8874ce..4024d309bb00 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -354,6 +354,15 @@ static struct ins_ops nop_ops = { | |||
354 | .scnprintf = nop__scnprintf, | 354 | .scnprintf = nop__scnprintf, |
355 | }; | 355 | }; |
356 | 356 | ||
357 | static struct ins_ops ret_ops = { | ||
358 | .scnprintf = ins__raw_scnprintf, | ||
359 | }; | ||
360 | |||
361 | bool ins__is_ret(const struct ins *ins) | ||
362 | { | ||
363 | return ins->ops == &ret_ops; | ||
364 | } | ||
365 | |||
357 | static struct ins instructions[] = { | 366 | static struct ins instructions[] = { |
358 | { .name = "add", .ops = &mov_ops, }, | 367 | { .name = "add", .ops = &mov_ops, }, |
359 | { .name = "addl", .ops = &mov_ops, }, | 368 | { .name = "addl", .ops = &mov_ops, }, |
@@ -444,6 +453,7 @@ static struct ins instructions[] = { | |||
444 | { .name = "xadd", .ops = &mov_ops, }, | 453 | { .name = "xadd", .ops = &mov_ops, }, |
445 | { .name = "xbeginl", .ops = &jump_ops, }, | 454 | { .name = "xbeginl", .ops = &jump_ops, }, |
446 | { .name = "xbeginq", .ops = &jump_ops, }, | 455 | { .name = "xbeginq", .ops = &jump_ops, }, |
456 | { .name = "retq", .ops = &ret_ops, }, | ||
447 | }; | 457 | }; |
448 | 458 | ||
449 | static int ins__key_cmp(const void *name, const void *insp) | 459 | static int ins__key_cmp(const void *name, const void *insp) |
@@ -1113,7 +1123,46 @@ static void delete_last_nop(struct symbol *sym) | |||
1113 | } | 1123 | } |
1114 | } | 1124 | } |
1115 | 1125 | ||
1116 | int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) | 1126 | int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map, |
1127 | int errnum, char *buf, size_t buflen) | ||
1128 | { | ||
1129 | struct dso *dso = map->dso; | ||
1130 | |||
1131 | BUG_ON(buflen == 0); | ||
1132 | |||
1133 | if (errnum >= 0) { | ||
1134 | str_error_r(errnum, buf, buflen); | ||
1135 | return 0; | ||
1136 | } | ||
1137 | |||
1138 | switch (errnum) { | ||
1139 | case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: { | ||
1140 | char bf[SBUILD_ID_SIZE + 15] = " with build id "; | ||
1141 | char *build_id_msg = NULL; | ||
1142 | |||
1143 | if (dso->has_build_id) { | ||
1144 | build_id__sprintf(dso->build_id, | ||
1145 | sizeof(dso->build_id), bf + 15); | ||
1146 | build_id_msg = bf; | ||
1147 | } | ||
1148 | scnprintf(buf, buflen, | ||
1149 | "No vmlinux file%s\nwas found in the path.\n\n" | ||
1150 | "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" | ||
1151 | "Please use:\n\n" | ||
1152 | " perf buildid-cache -vu vmlinux\n\n" | ||
1153 | "or:\n\n" | ||
1154 | " --vmlinux vmlinux\n", build_id_msg ?: ""); | ||
1155 | } | ||
1156 | break; | ||
1157 | default: | ||
1158 | scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum); | ||
1159 | break; | ||
1160 | } | ||
1161 | |||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1165 | int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) | ||
1117 | { | 1166 | { |
1118 | struct dso *dso = map->dso; | 1167 | struct dso *dso = map->dso; |
1119 | char *filename = dso__build_id_filename(dso, NULL, 0); | 1168 | char *filename = dso__build_id_filename(dso, NULL, 0); |
@@ -1124,22 +1173,20 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) | |||
1124 | char symfs_filename[PATH_MAX]; | 1173 | char symfs_filename[PATH_MAX]; |
1125 | struct kcore_extract kce; | 1174 | struct kcore_extract kce; |
1126 | bool delete_extract = false; | 1175 | bool delete_extract = false; |
1176 | int stdout_fd[2]; | ||
1127 | int lineno = 0; | 1177 | int lineno = 0; |
1128 | int nline; | 1178 | int nline; |
1179 | pid_t pid; | ||
1129 | 1180 | ||
1130 | if (filename) | 1181 | if (filename) |
1131 | symbol__join_symfs(symfs_filename, filename); | 1182 | symbol__join_symfs(symfs_filename, filename); |
1132 | 1183 | ||
1133 | if (filename == NULL) { | 1184 | if (filename == NULL) { |
1134 | if (dso->has_build_id) { | 1185 | if (dso->has_build_id) |
1135 | pr_err("Can't annotate %s: not enough memory\n", | 1186 | return ENOMEM; |
1136 | sym->name); | ||
1137 | return -ENOMEM; | ||
1138 | } | ||
1139 | goto fallback; | ||
1140 | } else if (dso__is_kcore(dso)) { | ||
1141 | goto fallback; | 1187 | goto fallback; |
1142 | } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || | 1188 | } else if (dso__is_kcore(dso) || |
1189 | readlink(symfs_filename, command, sizeof(command)) < 0 || | ||
1143 | strstr(command, DSO__NAME_KALLSYMS) || | 1190 | strstr(command, DSO__NAME_KALLSYMS) || |
1144 | access(symfs_filename, R_OK)) { | 1191 | access(symfs_filename, R_OK)) { |
1145 | free(filename); | 1192 | free(filename); |
@@ -1156,27 +1203,7 @@ fallback: | |||
1156 | 1203 | ||
1157 | if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && | 1204 | if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && |
1158 | !dso__is_kcore(dso)) { | 1205 | !dso__is_kcore(dso)) { |
1159 | char bf[SBUILD_ID_SIZE + 15] = " with build id "; | 1206 | err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; |
1160 | char *build_id_msg = NULL; | ||
1161 | |||
1162 | if (dso->annotate_warned) | ||
1163 | goto out_free_filename; | ||
1164 | |||
1165 | if (dso->has_build_id) { | ||
1166 | build_id__sprintf(dso->build_id, | ||
1167 | sizeof(dso->build_id), bf + 15); | ||
1168 | build_id_msg = bf; | ||
1169 | } | ||
1170 | err = -ENOENT; | ||
1171 | dso->annotate_warned = 1; | ||
1172 | pr_err("Can't annotate %s:\n\n" | ||
1173 | "No vmlinux file%s\nwas found in the path.\n\n" | ||
1174 | "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n" | ||
1175 | "Please use:\n\n" | ||
1176 | " perf buildid-cache -vu vmlinux\n\n" | ||
1177 | "or:\n\n" | ||
1178 | " --vmlinux vmlinux\n", | ||
1179 | sym->name, build_id_msg ?: ""); | ||
1180 | goto out_free_filename; | 1207 | goto out_free_filename; |
1181 | } | 1208 | } |
1182 | 1209 | ||
@@ -1248,9 +1275,32 @@ fallback: | |||
1248 | 1275 | ||
1249 | pr_debug("Executing: %s\n", command); | 1276 | pr_debug("Executing: %s\n", command); |
1250 | 1277 | ||
1251 | file = popen(command, "r"); | 1278 | err = -1; |
1279 | if (pipe(stdout_fd) < 0) { | ||
1280 | pr_err("Failure creating the pipe to run %s\n", command); | ||
1281 | goto out_remove_tmp; | ||
1282 | } | ||
1283 | |||
1284 | pid = fork(); | ||
1285 | if (pid < 0) { | ||
1286 | pr_err("Failure forking to run %s\n", command); | ||
1287 | goto out_close_stdout; | ||
1288 | } | ||
1289 | |||
1290 | if (pid == 0) { | ||
1291 | close(stdout_fd[0]); | ||
1292 | dup2(stdout_fd[1], 1); | ||
1293 | close(stdout_fd[1]); | ||
1294 | execl("/bin/sh", "sh", "-c", command, NULL); | ||
1295 | perror(command); | ||
1296 | exit(-1); | ||
1297 | } | ||
1298 | |||
1299 | close(stdout_fd[1]); | ||
1300 | |||
1301 | file = fdopen(stdout_fd[0], "r"); | ||
1252 | if (!file) { | 1302 | if (!file) { |
1253 | pr_err("Failure running %s\n", command); | 1303 | pr_err("Failure creating FILE stream for %s\n", command); |
1254 | /* | 1304 | /* |
1255 | * If we were using debug info should retry with | 1305 | * If we were using debug info should retry with |
1256 | * original binary. | 1306 | * original binary. |
@@ -1276,9 +1326,11 @@ fallback: | |||
1276 | if (dso__is_kcore(dso)) | 1326 | if (dso__is_kcore(dso)) |
1277 | delete_last_nop(sym); | 1327 | delete_last_nop(sym); |
1278 | 1328 | ||
1279 | pclose(file); | 1329 | fclose(file); |
1280 | 1330 | err = 0; | |
1281 | out_remove_tmp: | 1331 | out_remove_tmp: |
1332 | close(stdout_fd[0]); | ||
1333 | |||
1282 | if (dso__needs_decompress(dso)) | 1334 | if (dso__needs_decompress(dso)) |
1283 | unlink(symfs_filename); | 1335 | unlink(symfs_filename); |
1284 | out_free_filename: | 1336 | out_free_filename: |
@@ -1287,6 +1339,10 @@ out_free_filename: | |||
1287 | if (free_filename) | 1339 | if (free_filename) |
1288 | free(filename); | 1340 | free(filename); |
1289 | return err; | 1341 | return err; |
1342 | |||
1343 | out_close_stdout: | ||
1344 | close(stdout_fd[1]); | ||
1345 | goto out_remove_tmp; | ||
1290 | } | 1346 | } |
1291 | 1347 | ||
1292 | static void insert_source_line(struct rb_root *root, struct source_line *src_line) | 1348 | static void insert_source_line(struct rb_root *root, struct source_line *src_line) |
@@ -1512,13 +1568,14 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, | |||
1512 | const char *d_filename; | 1568 | const char *d_filename; |
1513 | const char *evsel_name = perf_evsel__name(evsel); | 1569 | const char *evsel_name = perf_evsel__name(evsel); |
1514 | struct annotation *notes = symbol__annotation(sym); | 1570 | struct annotation *notes = symbol__annotation(sym); |
1571 | struct sym_hist *h = annotation__histogram(notes, evsel->idx); | ||
1515 | struct disasm_line *pos, *queue = NULL; | 1572 | struct disasm_line *pos, *queue = NULL; |
1516 | u64 start = map__rip_2objdump(map, sym->start); | 1573 | u64 start = map__rip_2objdump(map, sym->start); |
1517 | int printed = 2, queue_len = 0; | 1574 | int printed = 2, queue_len = 0; |
1518 | int more = 0; | 1575 | int more = 0; |
1519 | u64 len; | 1576 | u64 len; |
1520 | int width = 8; | 1577 | int width = 8; |
1521 | int namelen, evsel_name_len, graph_dotted_len; | 1578 | int graph_dotted_len; |
1522 | 1579 | ||
1523 | filename = strdup(dso->long_name); | 1580 | filename = strdup(dso->long_name); |
1524 | if (!filename) | 1581 | if (!filename) |
@@ -1530,17 +1587,14 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, | |||
1530 | d_filename = basename(filename); | 1587 | d_filename = basename(filename); |
1531 | 1588 | ||
1532 | len = symbol__size(sym); | 1589 | len = symbol__size(sym); |
1533 | namelen = strlen(d_filename); | ||
1534 | evsel_name_len = strlen(evsel_name); | ||
1535 | 1590 | ||
1536 | if (perf_evsel__is_group_event(evsel)) | 1591 | if (perf_evsel__is_group_event(evsel)) |
1537 | width *= evsel->nr_members; | 1592 | width *= evsel->nr_members; |
1538 | 1593 | ||
1539 | printf(" %-*.*s| Source code & Disassembly of %s for %s\n", | 1594 | graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", |
1540 | width, width, "Percent", d_filename, evsel_name); | 1595 | width, width, "Percent", d_filename, evsel_name, h->sum); |
1541 | 1596 | ||
1542 | graph_dotted_len = width + namelen + evsel_name_len; | 1597 | printf("%-*.*s----\n", |
1543 | printf("-%-*.*s-----------------------------------------\n", | ||
1544 | graph_dotted_len, graph_dotted_len, graph_dotted_line); | 1598 | graph_dotted_len, graph_dotted_len, graph_dotted_line); |
1545 | 1599 | ||
1546 | if (verbose) | 1600 | if (verbose) |
@@ -1655,7 +1709,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, | |||
1655 | struct rb_root source_line = RB_ROOT; | 1709 | struct rb_root source_line = RB_ROOT; |
1656 | u64 len; | 1710 | u64 len; |
1657 | 1711 | ||
1658 | if (symbol__annotate(sym, map, 0) < 0) | 1712 | if (symbol__disassemble(sym, map, 0) < 0) |
1659 | return -1; | 1713 | return -1; |
1660 | 1714 | ||
1661 | len = symbol__size(sym); | 1715 | len = symbol__size(sym); |
@@ -1676,11 +1730,6 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, | |||
1676 | return 0; | 1730 | return 0; |
1677 | } | 1731 | } |
1678 | 1732 | ||
1679 | int hist_entry__annotate(struct hist_entry *he, size_t privsize) | ||
1680 | { | ||
1681 | return symbol__annotate(he->ms.sym, he->ms.map, privsize); | ||
1682 | } | ||
1683 | |||
1684 | bool ui__has_annotation(void) | 1733 | bool ui__has_annotation(void) |
1685 | { | 1734 | { |
1686 | return use_browser == 1 && perf_hpp_list.sym; | 1735 | return use_browser == 1 && perf_hpp_list.sym; |
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 9241f8c2b7e1..f67ccb027561 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
@@ -48,6 +48,7 @@ struct ins { | |||
48 | 48 | ||
49 | bool ins__is_jump(const struct ins *ins); | 49 | bool ins__is_jump(const struct ins *ins); |
50 | bool ins__is_call(const struct ins *ins); | 50 | bool ins__is_call(const struct ins *ins); |
51 | bool ins__is_ret(const struct ins *ins); | ||
51 | int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); | 52 | int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); |
52 | 53 | ||
53 | struct annotation; | 54 | struct annotation; |
@@ -154,9 +155,27 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr); | |||
154 | int symbol__alloc_hist(struct symbol *sym); | 155 | int symbol__alloc_hist(struct symbol *sym); |
155 | void symbol__annotate_zero_histograms(struct symbol *sym); | 156 | void symbol__annotate_zero_histograms(struct symbol *sym); |
156 | 157 | ||
157 | int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); | 158 | int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize); |
158 | 159 | ||
159 | int hist_entry__annotate(struct hist_entry *he, size_t privsize); | 160 | enum symbol_disassemble_errno { |
161 | SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, | ||
162 | |||
163 | /* | ||
164 | * Choose an arbitrary negative big number not to clash with standard | ||
165 | * errno since SUS requires the errno has distinct positive values. | ||
166 | * See 'Issue 6' in the link below. | ||
167 | * | ||
168 | * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html | ||
169 | */ | ||
170 | __SYMBOL_ANNOTATE_ERRNO__START = -10000, | ||
171 | |||
172 | SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START, | ||
173 | |||
174 | __SYMBOL_ANNOTATE_ERRNO__END, | ||
175 | }; | ||
176 | |||
177 | int symbol__strerror_disassemble(struct symbol *sym, struct map *map, | ||
178 | int errnum, char *buf, size_t buflen); | ||
160 | 179 | ||
161 | int symbol__annotate_init(struct map *map, struct symbol *sym); | 180 | int symbol__annotate_init(struct map *map, struct symbol *sym); |
162 | int symbol__annotate_printf(struct symbol *sym, struct map *map, | 181 | int symbol__annotate_printf(struct symbol *sym, struct map *map, |
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 767989e0e312..ac5f0d7167e6 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h | |||
@@ -63,6 +63,7 @@ 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 | * @thread_stack: feed branches to the thread_stack | ||
66 | * @last_branch: add branch context to 'instruction' events | 67 | * @last_branch: add branch context to 'instruction' events |
67 | * @callchain_sz: maximum callchain size | 68 | * @callchain_sz: maximum callchain size |
68 | * @last_branch_sz: branch context size | 69 | * @last_branch_sz: branch context size |
@@ -82,6 +83,7 @@ struct itrace_synth_opts { | |||
82 | bool calls; | 83 | bool calls; |
83 | bool returns; | 84 | bool returns; |
84 | bool callchain; | 85 | bool callchain; |
86 | bool thread_stack; | ||
85 | bool last_branch; | 87 | bool last_branch; |
86 | unsigned int callchain_sz; | 88 | unsigned int callchain_sz; |
87 | unsigned int last_branch_sz; | 89 | unsigned int last_branch_sz; |
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 493307d1414c..1f12e4e40006 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c | |||
@@ -37,6 +37,9 @@ DEFINE_PRINT_FN(info, 1) | |||
37 | DEFINE_PRINT_FN(debug, 1) | 37 | DEFINE_PRINT_FN(debug, 1) |
38 | 38 | ||
39 | struct bpf_prog_priv { | 39 | struct bpf_prog_priv { |
40 | bool is_tp; | ||
41 | char *sys_name; | ||
42 | char *evt_name; | ||
40 | struct perf_probe_event pev; | 43 | struct perf_probe_event pev; |
41 | bool need_prologue; | 44 | bool need_prologue; |
42 | struct bpf_insn *insns_buf; | 45 | struct bpf_insn *insns_buf; |
@@ -118,6 +121,8 @@ clear_prog_priv(struct bpf_program *prog __maybe_unused, | |||
118 | cleanup_perf_probe_events(&priv->pev, 1); | 121 | cleanup_perf_probe_events(&priv->pev, 1); |
119 | zfree(&priv->insns_buf); | 122 | zfree(&priv->insns_buf); |
120 | zfree(&priv->type_mapping); | 123 | zfree(&priv->type_mapping); |
124 | zfree(&priv->sys_name); | ||
125 | zfree(&priv->evt_name); | ||
121 | free(priv); | 126 | free(priv); |
122 | } | 127 | } |
123 | 128 | ||
@@ -269,7 +274,8 @@ nextline: | |||
269 | } | 274 | } |
270 | 275 | ||
271 | static int | 276 | static int |
272 | parse_prog_config(const char *config_str, struct perf_probe_event *pev) | 277 | parse_prog_config(const char *config_str, const char **p_main_str, |
278 | bool *is_tp, struct perf_probe_event *pev) | ||
273 | { | 279 | { |
274 | int err; | 280 | int err; |
275 | const char *main_str = parse_prog_config_kvpair(config_str, pev); | 281 | const char *main_str = parse_prog_config_kvpair(config_str, pev); |
@@ -277,6 +283,22 @@ parse_prog_config(const char *config_str, struct perf_probe_event *pev) | |||
277 | if (IS_ERR(main_str)) | 283 | if (IS_ERR(main_str)) |
278 | return PTR_ERR(main_str); | 284 | return PTR_ERR(main_str); |
279 | 285 | ||
286 | *p_main_str = main_str; | ||
287 | if (!strchr(main_str, '=')) { | ||
288 | /* Is a tracepoint event? */ | ||
289 | const char *s = strchr(main_str, ':'); | ||
290 | |||
291 | if (!s) { | ||
292 | pr_debug("bpf: '%s' is not a valid tracepoint\n", | ||
293 | config_str); | ||
294 | return -BPF_LOADER_ERRNO__CONFIG; | ||
295 | } | ||
296 | |||
297 | *is_tp = true; | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | *is_tp = false; | ||
280 | err = parse_perf_probe_command(main_str, pev); | 302 | err = parse_perf_probe_command(main_str, pev); |
281 | if (err < 0) { | 303 | if (err < 0) { |
282 | pr_debug("bpf: '%s' is not a valid config string\n", | 304 | pr_debug("bpf: '%s' is not a valid config string\n", |
@@ -292,7 +314,8 @@ config_bpf_program(struct bpf_program *prog) | |||
292 | { | 314 | { |
293 | struct perf_probe_event *pev = NULL; | 315 | struct perf_probe_event *pev = NULL; |
294 | struct bpf_prog_priv *priv = NULL; | 316 | struct bpf_prog_priv *priv = NULL; |
295 | const char *config_str; | 317 | const char *config_str, *main_str; |
318 | bool is_tp = false; | ||
296 | int err; | 319 | int err; |
297 | 320 | ||
298 | /* Initialize per-program probing setting */ | 321 | /* Initialize per-program probing setting */ |
@@ -313,10 +336,19 @@ config_bpf_program(struct bpf_program *prog) | |||
313 | pev = &priv->pev; | 336 | pev = &priv->pev; |
314 | 337 | ||
315 | pr_debug("bpf: config program '%s'\n", config_str); | 338 | pr_debug("bpf: config program '%s'\n", config_str); |
316 | err = parse_prog_config(config_str, pev); | 339 | err = parse_prog_config(config_str, &main_str, &is_tp, pev); |
317 | if (err) | 340 | if (err) |
318 | goto errout; | 341 | goto errout; |
319 | 342 | ||
343 | if (is_tp) { | ||
344 | char *s = strchr(main_str, ':'); | ||
345 | |||
346 | priv->is_tp = true; | ||
347 | priv->sys_name = strndup(main_str, s - main_str); | ||
348 | priv->evt_name = strdup(s + 1); | ||
349 | goto set_priv; | ||
350 | } | ||
351 | |||
320 | if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { | 352 | if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { |
321 | pr_debug("bpf: '%s': group for event is set and not '%s'.\n", | 353 | pr_debug("bpf: '%s': group for event is set and not '%s'.\n", |
322 | config_str, PERF_BPF_PROBE_GROUP); | 354 | config_str, PERF_BPF_PROBE_GROUP); |
@@ -339,7 +371,8 @@ config_bpf_program(struct bpf_program *prog) | |||
339 | } | 371 | } |
340 | pr_debug("bpf: config '%s' is ok\n", config_str); | 372 | pr_debug("bpf: config '%s' is ok\n", config_str); |
341 | 373 | ||
342 | err = bpf_program__set_private(prog, priv, clear_prog_priv); | 374 | set_priv: |
375 | err = bpf_program__set_priv(prog, priv, clear_prog_priv); | ||
343 | if (err) { | 376 | if (err) { |
344 | pr_debug("Failed to set priv for program '%s'\n", config_str); | 377 | pr_debug("Failed to set priv for program '%s'\n", config_str); |
345 | goto errout; | 378 | goto errout; |
@@ -380,15 +413,14 @@ preproc_gen_prologue(struct bpf_program *prog, int n, | |||
380 | struct bpf_insn *orig_insns, int orig_insns_cnt, | 413 | struct bpf_insn *orig_insns, int orig_insns_cnt, |
381 | struct bpf_prog_prep_result *res) | 414 | struct bpf_prog_prep_result *res) |
382 | { | 415 | { |
416 | struct bpf_prog_priv *priv = bpf_program__priv(prog); | ||
383 | struct probe_trace_event *tev; | 417 | struct probe_trace_event *tev; |
384 | struct perf_probe_event *pev; | 418 | struct perf_probe_event *pev; |
385 | struct bpf_prog_priv *priv; | ||
386 | struct bpf_insn *buf; | 419 | struct bpf_insn *buf; |
387 | size_t prologue_cnt = 0; | 420 | size_t prologue_cnt = 0; |
388 | int i, err; | 421 | int i, err; |
389 | 422 | ||
390 | err = bpf_program__get_private(prog, (void **)&priv); | 423 | if (IS_ERR(priv) || !priv || priv->is_tp) |
391 | if (err || !priv) | ||
392 | goto errout; | 424 | goto errout; |
393 | 425 | ||
394 | pev = &priv->pev; | 426 | pev = &priv->pev; |
@@ -535,17 +567,21 @@ static int map_prologue(struct perf_probe_event *pev, int *mapping, | |||
535 | 567 | ||
536 | static int hook_load_preprocessor(struct bpf_program *prog) | 568 | static int hook_load_preprocessor(struct bpf_program *prog) |
537 | { | 569 | { |
570 | struct bpf_prog_priv *priv = bpf_program__priv(prog); | ||
538 | struct perf_probe_event *pev; | 571 | struct perf_probe_event *pev; |
539 | struct bpf_prog_priv *priv; | ||
540 | bool need_prologue = false; | 572 | bool need_prologue = false; |
541 | int err, i; | 573 | int err, i; |
542 | 574 | ||
543 | err = bpf_program__get_private(prog, (void **)&priv); | 575 | if (IS_ERR(priv) || !priv) { |
544 | if (err || !priv) { | ||
545 | pr_debug("Internal error when hook preprocessor\n"); | 576 | pr_debug("Internal error when hook preprocessor\n"); |
546 | return -BPF_LOADER_ERRNO__INTERNAL; | 577 | return -BPF_LOADER_ERRNO__INTERNAL; |
547 | } | 578 | } |
548 | 579 | ||
580 | if (priv->is_tp) { | ||
581 | priv->need_prologue = false; | ||
582 | return 0; | ||
583 | } | ||
584 | |||
549 | pev = &priv->pev; | 585 | pev = &priv->pev; |
550 | for (i = 0; i < pev->ntevs; i++) { | 586 | for (i = 0; i < pev->ntevs; i++) { |
551 | struct probe_trace_event *tev = &pev->tevs[i]; | 587 | struct probe_trace_event *tev = &pev->tevs[i]; |
@@ -607,9 +643,18 @@ int bpf__probe(struct bpf_object *obj) | |||
607 | if (err) | 643 | if (err) |
608 | goto out; | 644 | goto out; |
609 | 645 | ||
610 | err = bpf_program__get_private(prog, (void **)&priv); | 646 | priv = bpf_program__priv(prog); |
611 | if (err || !priv) | 647 | if (IS_ERR(priv) || !priv) { |
648 | err = PTR_ERR(priv); | ||
612 | goto out; | 649 | goto out; |
650 | } | ||
651 | |||
652 | if (priv->is_tp) { | ||
653 | bpf_program__set_tracepoint(prog); | ||
654 | continue; | ||
655 | } | ||
656 | |||
657 | bpf_program__set_kprobe(prog); | ||
613 | pev = &priv->pev; | 658 | pev = &priv->pev; |
614 | 659 | ||
615 | err = convert_perf_probe_events(pev, 1); | 660 | err = convert_perf_probe_events(pev, 1); |
@@ -645,13 +690,12 @@ int bpf__unprobe(struct bpf_object *obj) | |||
645 | { | 690 | { |
646 | int err, ret = 0; | 691 | int err, ret = 0; |
647 | struct bpf_program *prog; | 692 | struct bpf_program *prog; |
648 | struct bpf_prog_priv *priv; | ||
649 | 693 | ||
650 | bpf_object__for_each_program(prog, obj) { | 694 | bpf_object__for_each_program(prog, obj) { |
695 | struct bpf_prog_priv *priv = bpf_program__priv(prog); | ||
651 | int i; | 696 | int i; |
652 | 697 | ||
653 | err = bpf_program__get_private(prog, (void **)&priv); | 698 | if (IS_ERR(priv) || !priv || priv->is_tp) |
654 | if (err || !priv) | ||
655 | continue; | 699 | continue; |
656 | 700 | ||
657 | for (i = 0; i < priv->pev.ntevs; i++) { | 701 | for (i = 0; i < priv->pev.ntevs; i++) { |
@@ -694,26 +738,34 @@ int bpf__load(struct bpf_object *obj) | |||
694 | return 0; | 738 | return 0; |
695 | } | 739 | } |
696 | 740 | ||
697 | int bpf__foreach_tev(struct bpf_object *obj, | 741 | int bpf__foreach_event(struct bpf_object *obj, |
698 | bpf_prog_iter_callback_t func, | 742 | bpf_prog_iter_callback_t func, |
699 | void *arg) | 743 | void *arg) |
700 | { | 744 | { |
701 | struct bpf_program *prog; | 745 | struct bpf_program *prog; |
702 | int err; | 746 | int err; |
703 | 747 | ||
704 | bpf_object__for_each_program(prog, obj) { | 748 | bpf_object__for_each_program(prog, obj) { |
749 | struct bpf_prog_priv *priv = bpf_program__priv(prog); | ||
705 | struct probe_trace_event *tev; | 750 | struct probe_trace_event *tev; |
706 | struct perf_probe_event *pev; | 751 | struct perf_probe_event *pev; |
707 | struct bpf_prog_priv *priv; | ||
708 | int i, fd; | 752 | int i, fd; |
709 | 753 | ||
710 | err = bpf_program__get_private(prog, | 754 | if (IS_ERR(priv) || !priv) { |
711 | (void **)&priv); | ||
712 | if (err || !priv) { | ||
713 | pr_debug("bpf: failed to get private field\n"); | 755 | pr_debug("bpf: failed to get private field\n"); |
714 | return -BPF_LOADER_ERRNO__INTERNAL; | 756 | return -BPF_LOADER_ERRNO__INTERNAL; |
715 | } | 757 | } |
716 | 758 | ||
759 | if (priv->is_tp) { | ||
760 | fd = bpf_program__fd(prog); | ||
761 | err = (*func)(priv->sys_name, priv->evt_name, fd, arg); | ||
762 | if (err) { | ||
763 | pr_debug("bpf: tracepoint call back failed, stop iterate\n"); | ||
764 | return err; | ||
765 | } | ||
766 | continue; | ||
767 | } | ||
768 | |||
717 | pev = &priv->pev; | 769 | pev = &priv->pev; |
718 | for (i = 0; i < pev->ntevs; i++) { | 770 | for (i = 0; i < pev->ntevs; i++) { |
719 | tev = &pev->tevs[i]; | 771 | tev = &pev->tevs[i]; |
@@ -731,7 +783,7 @@ int bpf__foreach_tev(struct bpf_object *obj, | |||
731 | return fd; | 783 | return fd; |
732 | } | 784 | } |
733 | 785 | ||
734 | err = (*func)(tev, fd, arg); | 786 | err = (*func)(tev->group, tev->event, fd, arg); |
735 | if (err) { | 787 | if (err) { |
736 | pr_debug("bpf: call back failed, stop iterate\n"); | 788 | pr_debug("bpf: call back failed, stop iterate\n"); |
737 | return err; | 789 | return err; |
@@ -897,15 +949,12 @@ bpf_map_priv__clone(struct bpf_map_priv *priv) | |||
897 | static int | 949 | static int |
898 | bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op) | 950 | bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op) |
899 | { | 951 | { |
900 | struct bpf_map_priv *priv; | 952 | const char *map_name = bpf_map__name(map); |
901 | const char *map_name; | 953 | struct bpf_map_priv *priv = bpf_map__priv(map); |
902 | int err; | ||
903 | 954 | ||
904 | map_name = bpf_map__get_name(map); | 955 | if (IS_ERR(priv)) { |
905 | err = bpf_map__get_private(map, (void **)&priv); | ||
906 | if (err) { | ||
907 | pr_debug("Failed to get private from map %s\n", map_name); | 956 | pr_debug("Failed to get private from map %s\n", map_name); |
908 | return err; | 957 | return PTR_ERR(priv); |
909 | } | 958 | } |
910 | 959 | ||
911 | if (!priv) { | 960 | if (!priv) { |
@@ -916,7 +965,7 @@ bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op) | |||
916 | } | 965 | } |
917 | INIT_LIST_HEAD(&priv->ops_list); | 966 | INIT_LIST_HEAD(&priv->ops_list); |
918 | 967 | ||
919 | if (bpf_map__set_private(map, priv, bpf_map_priv__clear)) { | 968 | if (bpf_map__set_priv(map, priv, bpf_map_priv__clear)) { |
920 | free(priv); | 969 | free(priv); |
921 | return -BPF_LOADER_ERRNO__INTERNAL; | 970 | return -BPF_LOADER_ERRNO__INTERNAL; |
922 | } | 971 | } |
@@ -948,30 +997,26 @@ static int | |||
948 | __bpf_map__config_value(struct bpf_map *map, | 997 | __bpf_map__config_value(struct bpf_map *map, |
949 | struct parse_events_term *term) | 998 | struct parse_events_term *term) |
950 | { | 999 | { |
951 | struct bpf_map_def def; | ||
952 | struct bpf_map_op *op; | 1000 | struct bpf_map_op *op; |
953 | const char *map_name; | 1001 | const char *map_name = bpf_map__name(map); |
954 | int err; | 1002 | const struct bpf_map_def *def = bpf_map__def(map); |
955 | 1003 | ||
956 | map_name = bpf_map__get_name(map); | 1004 | if (IS_ERR(def)) { |
957 | |||
958 | err = bpf_map__get_def(map, &def); | ||
959 | if (err) { | ||
960 | pr_debug("Unable to get map definition from '%s'\n", | 1005 | pr_debug("Unable to get map definition from '%s'\n", |
961 | map_name); | 1006 | map_name); |
962 | return -BPF_LOADER_ERRNO__INTERNAL; | 1007 | return -BPF_LOADER_ERRNO__INTERNAL; |
963 | } | 1008 | } |
964 | 1009 | ||
965 | if (def.type != BPF_MAP_TYPE_ARRAY) { | 1010 | if (def->type != BPF_MAP_TYPE_ARRAY) { |
966 | pr_debug("Map %s type is not BPF_MAP_TYPE_ARRAY\n", | 1011 | pr_debug("Map %s type is not BPF_MAP_TYPE_ARRAY\n", |
967 | map_name); | 1012 | map_name); |
968 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; | 1013 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; |
969 | } | 1014 | } |
970 | if (def.key_size < sizeof(unsigned int)) { | 1015 | if (def->key_size < sizeof(unsigned int)) { |
971 | pr_debug("Map %s has incorrect key size\n", map_name); | 1016 | pr_debug("Map %s has incorrect key size\n", map_name); |
972 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE; | 1017 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE; |
973 | } | 1018 | } |
974 | switch (def.value_size) { | 1019 | switch (def->value_size) { |
975 | case 1: | 1020 | case 1: |
976 | case 2: | 1021 | case 2: |
977 | case 4: | 1022 | case 4: |
@@ -1014,12 +1059,10 @@ __bpf_map__config_event(struct bpf_map *map, | |||
1014 | struct perf_evlist *evlist) | 1059 | struct perf_evlist *evlist) |
1015 | { | 1060 | { |
1016 | struct perf_evsel *evsel; | 1061 | struct perf_evsel *evsel; |
1017 | struct bpf_map_def def; | 1062 | const struct bpf_map_def *def; |
1018 | struct bpf_map_op *op; | 1063 | struct bpf_map_op *op; |
1019 | const char *map_name; | 1064 | const char *map_name = bpf_map__name(map); |
1020 | int err; | ||
1021 | 1065 | ||
1022 | map_name = bpf_map__get_name(map); | ||
1023 | evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str); | 1066 | evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str); |
1024 | if (!evsel) { | 1067 | if (!evsel) { |
1025 | pr_debug("Event (for '%s') '%s' doesn't exist\n", | 1068 | pr_debug("Event (for '%s') '%s' doesn't exist\n", |
@@ -1027,18 +1070,18 @@ __bpf_map__config_event(struct bpf_map *map, | |||
1027 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT; | 1070 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT; |
1028 | } | 1071 | } |
1029 | 1072 | ||
1030 | err = bpf_map__get_def(map, &def); | 1073 | def = bpf_map__def(map); |
1031 | if (err) { | 1074 | if (IS_ERR(def)) { |
1032 | pr_debug("Unable to get map definition from '%s'\n", | 1075 | pr_debug("Unable to get map definition from '%s'\n", |
1033 | map_name); | 1076 | map_name); |
1034 | return err; | 1077 | return PTR_ERR(def); |
1035 | } | 1078 | } |
1036 | 1079 | ||
1037 | /* | 1080 | /* |
1038 | * No need to check key_size and value_size: | 1081 | * No need to check key_size and value_size: |
1039 | * kernel has already checked them. | 1082 | * kernel has already checked them. |
1040 | */ | 1083 | */ |
1041 | if (def.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) { | 1084 | if (def->type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) { |
1042 | pr_debug("Map %s type is not BPF_MAP_TYPE_PERF_EVENT_ARRAY\n", | 1085 | pr_debug("Map %s type is not BPF_MAP_TYPE_PERF_EVENT_ARRAY\n", |
1043 | map_name); | 1086 | map_name); |
1044 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; | 1087 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; |
@@ -1087,9 +1130,8 @@ config_map_indices_range_check(struct parse_events_term *term, | |||
1087 | const char *map_name) | 1130 | const char *map_name) |
1088 | { | 1131 | { |
1089 | struct parse_events_array *array = &term->array; | 1132 | struct parse_events_array *array = &term->array; |
1090 | struct bpf_map_def def; | 1133 | const struct bpf_map_def *def; |
1091 | unsigned int i; | 1134 | unsigned int i; |
1092 | int err; | ||
1093 | 1135 | ||
1094 | if (!array->nr_ranges) | 1136 | if (!array->nr_ranges) |
1095 | return 0; | 1137 | return 0; |
@@ -1099,8 +1141,8 @@ config_map_indices_range_check(struct parse_events_term *term, | |||
1099 | return -BPF_LOADER_ERRNO__INTERNAL; | 1141 | return -BPF_LOADER_ERRNO__INTERNAL; |
1100 | } | 1142 | } |
1101 | 1143 | ||
1102 | err = bpf_map__get_def(map, &def); | 1144 | def = bpf_map__def(map); |
1103 | if (err) { | 1145 | if (IS_ERR(def)) { |
1104 | pr_debug("ERROR: Unable to get map definition from '%s'\n", | 1146 | pr_debug("ERROR: Unable to get map definition from '%s'\n", |
1105 | map_name); | 1147 | map_name); |
1106 | return -BPF_LOADER_ERRNO__INTERNAL; | 1148 | return -BPF_LOADER_ERRNO__INTERNAL; |
@@ -1111,7 +1153,7 @@ config_map_indices_range_check(struct parse_events_term *term, | |||
1111 | size_t length = array->ranges[i].length; | 1153 | size_t length = array->ranges[i].length; |
1112 | unsigned int idx = start + length - 1; | 1154 | unsigned int idx = start + length - 1; |
1113 | 1155 | ||
1114 | if (idx >= def.max_entries) { | 1156 | if (idx >= def->max_entries) { |
1115 | pr_debug("ERROR: index %d too large\n", idx); | 1157 | pr_debug("ERROR: index %d too large\n", idx); |
1116 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG; | 1158 | return -BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG; |
1117 | } | 1159 | } |
@@ -1147,7 +1189,7 @@ bpf__obj_config_map(struct bpf_object *obj, | |||
1147 | goto out; | 1189 | goto out; |
1148 | } | 1190 | } |
1149 | 1191 | ||
1150 | map = bpf_object__get_map_by_name(obj, map_name); | 1192 | map = bpf_object__find_map_by_name(obj, map_name); |
1151 | if (!map) { | 1193 | if (!map) { |
1152 | pr_debug("ERROR: Map %s doesn't exist\n", map_name); | 1194 | pr_debug("ERROR: Map %s doesn't exist\n", map_name); |
1153 | err = -BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST; | 1195 | err = -BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST; |
@@ -1204,14 +1246,14 @@ out: | |||
1204 | } | 1246 | } |
1205 | 1247 | ||
1206 | typedef int (*map_config_func_t)(const char *name, int map_fd, | 1248 | typedef int (*map_config_func_t)(const char *name, int map_fd, |
1207 | struct bpf_map_def *pdef, | 1249 | const struct bpf_map_def *pdef, |
1208 | struct bpf_map_op *op, | 1250 | struct bpf_map_op *op, |
1209 | void *pkey, void *arg); | 1251 | void *pkey, void *arg); |
1210 | 1252 | ||
1211 | static int | 1253 | static int |
1212 | foreach_key_array_all(map_config_func_t func, | 1254 | foreach_key_array_all(map_config_func_t func, |
1213 | void *arg, const char *name, | 1255 | void *arg, const char *name, |
1214 | int map_fd, struct bpf_map_def *pdef, | 1256 | int map_fd, const struct bpf_map_def *pdef, |
1215 | struct bpf_map_op *op) | 1257 | struct bpf_map_op *op) |
1216 | { | 1258 | { |
1217 | unsigned int i; | 1259 | unsigned int i; |
@@ -1231,7 +1273,7 @@ foreach_key_array_all(map_config_func_t func, | |||
1231 | static int | 1273 | static int |
1232 | foreach_key_array_ranges(map_config_func_t func, void *arg, | 1274 | foreach_key_array_ranges(map_config_func_t func, void *arg, |
1233 | const char *name, int map_fd, | 1275 | const char *name, int map_fd, |
1234 | struct bpf_map_def *pdef, | 1276 | const struct bpf_map_def *pdef, |
1235 | struct bpf_map_op *op) | 1277 | struct bpf_map_op *op) |
1236 | { | 1278 | { |
1237 | unsigned int i, j; | 1279 | unsigned int i, j; |
@@ -1261,15 +1303,12 @@ bpf_map_config_foreach_key(struct bpf_map *map, | |||
1261 | void *arg) | 1303 | void *arg) |
1262 | { | 1304 | { |
1263 | int err, map_fd; | 1305 | int err, map_fd; |
1264 | const char *name; | ||
1265 | struct bpf_map_op *op; | 1306 | struct bpf_map_op *op; |
1266 | struct bpf_map_def def; | 1307 | const struct bpf_map_def *def; |
1267 | struct bpf_map_priv *priv; | 1308 | const char *name = bpf_map__name(map); |
1309 | struct bpf_map_priv *priv = bpf_map__priv(map); | ||
1268 | 1310 | ||
1269 | name = bpf_map__get_name(map); | 1311 | if (IS_ERR(priv)) { |
1270 | |||
1271 | err = bpf_map__get_private(map, (void **)&priv); | ||
1272 | if (err) { | ||
1273 | pr_debug("ERROR: failed to get private from map %s\n", name); | 1312 | pr_debug("ERROR: failed to get private from map %s\n", name); |
1274 | return -BPF_LOADER_ERRNO__INTERNAL; | 1313 | return -BPF_LOADER_ERRNO__INTERNAL; |
1275 | } | 1314 | } |
@@ -1278,29 +1317,29 @@ bpf_map_config_foreach_key(struct bpf_map *map, | |||
1278 | return 0; | 1317 | return 0; |
1279 | } | 1318 | } |
1280 | 1319 | ||
1281 | err = bpf_map__get_def(map, &def); | 1320 | def = bpf_map__def(map); |
1282 | if (err) { | 1321 | if (IS_ERR(def)) { |
1283 | pr_debug("ERROR: failed to get definition from map %s\n", name); | 1322 | pr_debug("ERROR: failed to get definition from map %s\n", name); |
1284 | return -BPF_LOADER_ERRNO__INTERNAL; | 1323 | return -BPF_LOADER_ERRNO__INTERNAL; |
1285 | } | 1324 | } |
1286 | map_fd = bpf_map__get_fd(map); | 1325 | map_fd = bpf_map__fd(map); |
1287 | if (map_fd < 0) { | 1326 | if (map_fd < 0) { |
1288 | pr_debug("ERROR: failed to get fd from map %s\n", name); | 1327 | pr_debug("ERROR: failed to get fd from map %s\n", name); |
1289 | return map_fd; | 1328 | return map_fd; |
1290 | } | 1329 | } |
1291 | 1330 | ||
1292 | list_for_each_entry(op, &priv->ops_list, list) { | 1331 | list_for_each_entry(op, &priv->ops_list, list) { |
1293 | switch (def.type) { | 1332 | switch (def->type) { |
1294 | case BPF_MAP_TYPE_ARRAY: | 1333 | case BPF_MAP_TYPE_ARRAY: |
1295 | case BPF_MAP_TYPE_PERF_EVENT_ARRAY: | 1334 | case BPF_MAP_TYPE_PERF_EVENT_ARRAY: |
1296 | switch (op->key_type) { | 1335 | switch (op->key_type) { |
1297 | case BPF_MAP_KEY_ALL: | 1336 | case BPF_MAP_KEY_ALL: |
1298 | err = foreach_key_array_all(func, arg, name, | 1337 | err = foreach_key_array_all(func, arg, name, |
1299 | map_fd, &def, op); | 1338 | map_fd, def, op); |
1300 | break; | 1339 | break; |
1301 | case BPF_MAP_KEY_RANGES: | 1340 | case BPF_MAP_KEY_RANGES: |
1302 | err = foreach_key_array_ranges(func, arg, name, | 1341 | err = foreach_key_array_ranges(func, arg, name, |
1303 | map_fd, &def, | 1342 | map_fd, def, |
1304 | op); | 1343 | op); |
1305 | break; | 1344 | break; |
1306 | default: | 1345 | default: |
@@ -1410,7 +1449,7 @@ apply_config_evsel_for_key(const char *name, int map_fd, void *pkey, | |||
1410 | 1449 | ||
1411 | static int | 1450 | static int |
1412 | apply_obj_config_map_for_key(const char *name, int map_fd, | 1451 | apply_obj_config_map_for_key(const char *name, int map_fd, |
1413 | struct bpf_map_def *pdef __maybe_unused, | 1452 | const struct bpf_map_def *pdef, |
1414 | struct bpf_map_op *op, | 1453 | struct bpf_map_op *op, |
1415 | void *pkey, void *arg __maybe_unused) | 1454 | void *pkey, void *arg __maybe_unused) |
1416 | { | 1455 | { |
@@ -1475,9 +1514,9 @@ int bpf__apply_obj_config(void) | |||
1475 | 1514 | ||
1476 | #define bpf__for_each_stdout_map(pos, obj, objtmp) \ | 1515 | #define bpf__for_each_stdout_map(pos, obj, objtmp) \ |
1477 | bpf__for_each_map(pos, obj, objtmp) \ | 1516 | bpf__for_each_map(pos, obj, objtmp) \ |
1478 | if (bpf_map__get_name(pos) && \ | 1517 | if (bpf_map__name(pos) && \ |
1479 | (strcmp("__bpf_stdout__", \ | 1518 | (strcmp("__bpf_stdout__", \ |
1480 | bpf_map__get_name(pos)) == 0)) | 1519 | bpf_map__name(pos)) == 0)) |
1481 | 1520 | ||
1482 | int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) | 1521 | int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) |
1483 | { | 1522 | { |
@@ -1489,10 +1528,9 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) | |||
1489 | bool need_init = false; | 1528 | bool need_init = false; |
1490 | 1529 | ||
1491 | bpf__for_each_stdout_map(map, obj, tmp) { | 1530 | bpf__for_each_stdout_map(map, obj, tmp) { |
1492 | struct bpf_map_priv *priv; | 1531 | struct bpf_map_priv *priv = bpf_map__priv(map); |
1493 | 1532 | ||
1494 | err = bpf_map__get_private(map, (void **)&priv); | 1533 | if (IS_ERR(priv)) |
1495 | if (err) | ||
1496 | return -BPF_LOADER_ERRNO__INTERNAL; | 1534 | return -BPF_LOADER_ERRNO__INTERNAL; |
1497 | 1535 | ||
1498 | /* | 1536 | /* |
@@ -1520,10 +1558,9 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) | |||
1520 | } | 1558 | } |
1521 | 1559 | ||
1522 | bpf__for_each_stdout_map(map, obj, tmp) { | 1560 | bpf__for_each_stdout_map(map, obj, tmp) { |
1523 | struct bpf_map_priv *priv; | 1561 | struct bpf_map_priv *priv = bpf_map__priv(map); |
1524 | 1562 | ||
1525 | err = bpf_map__get_private(map, (void **)&priv); | 1563 | if (IS_ERR(priv)) |
1526 | if (err) | ||
1527 | return -BPF_LOADER_ERRNO__INTERNAL; | 1564 | return -BPF_LOADER_ERRNO__INTERNAL; |
1528 | if (priv) | 1565 | if (priv) |
1529 | continue; | 1566 | continue; |
@@ -1533,7 +1570,7 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) | |||
1533 | if (!priv) | 1570 | if (!priv) |
1534 | return -ENOMEM; | 1571 | return -ENOMEM; |
1535 | 1572 | ||
1536 | err = bpf_map__set_private(map, priv, bpf_map_priv__clear); | 1573 | err = bpf_map__set_priv(map, priv, bpf_map_priv__clear); |
1537 | if (err) { | 1574 | if (err) { |
1538 | bpf_map_priv__clear(map, priv); | 1575 | bpf_map_priv__clear(map, priv); |
1539 | return err; | 1576 | return err; |
@@ -1607,7 +1644,7 @@ bpf_loader_strerror(int err, char *buf, size_t size) | |||
1607 | snprintf(buf, size, "Unknown bpf loader error %d", err); | 1644 | snprintf(buf, size, "Unknown bpf loader error %d", err); |
1608 | else | 1645 | else |
1609 | snprintf(buf, size, "%s", | 1646 | snprintf(buf, size, "%s", |
1610 | strerror_r(err, sbuf, sizeof(sbuf))); | 1647 | str_error_r(err, sbuf, sizeof(sbuf))); |
1611 | 1648 | ||
1612 | buf[size - 1] = '\0'; | 1649 | buf[size - 1] = '\0'; |
1613 | return -1; | 1650 | return -1; |
@@ -1677,7 +1714,7 @@ int bpf__strerror_load(struct bpf_object *obj, | |||
1677 | { | 1714 | { |
1678 | bpf__strerror_head(err, buf, size); | 1715 | bpf__strerror_head(err, buf, size); |
1679 | case LIBBPF_ERRNO__KVER: { | 1716 | case LIBBPF_ERRNO__KVER: { |
1680 | unsigned int obj_kver = bpf_object__get_kversion(obj); | 1717 | unsigned int obj_kver = bpf_object__kversion(obj); |
1681 | unsigned int real_kver; | 1718 | unsigned int real_kver; |
1682 | 1719 | ||
1683 | if (fetch_kernel_version(&real_kver, NULL, 0)) { | 1720 | if (fetch_kernel_version(&real_kver, NULL, 0)) { |
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h index 941e17275aa7..f2b737b225f2 100644 --- a/tools/perf/util/bpf-loader.h +++ b/tools/perf/util/bpf-loader.h | |||
@@ -46,7 +46,7 @@ struct bpf_object; | |||
46 | struct parse_events_term; | 46 | struct parse_events_term; |
47 | #define PERF_BPF_PROBE_GROUP "perf_bpf_probe" | 47 | #define PERF_BPF_PROBE_GROUP "perf_bpf_probe" |
48 | 48 | ||
49 | typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev, | 49 | typedef int (*bpf_prog_iter_callback_t)(const char *group, const char *event, |
50 | int fd, void *arg); | 50 | int fd, void *arg); |
51 | 51 | ||
52 | #ifdef HAVE_LIBBPF_SUPPORT | 52 | #ifdef HAVE_LIBBPF_SUPPORT |
@@ -67,8 +67,8 @@ int bpf__strerror_probe(struct bpf_object *obj, int err, | |||
67 | int bpf__load(struct bpf_object *obj); | 67 | int bpf__load(struct bpf_object *obj); |
68 | int bpf__strerror_load(struct bpf_object *obj, int err, | 68 | int bpf__strerror_load(struct bpf_object *obj, int err, |
69 | char *buf, size_t size); | 69 | char *buf, size_t size); |
70 | int bpf__foreach_tev(struct bpf_object *obj, | 70 | int bpf__foreach_event(struct bpf_object *obj, |
71 | bpf_prog_iter_callback_t func, void *arg); | 71 | bpf_prog_iter_callback_t func, void *arg); |
72 | 72 | ||
73 | int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term, | 73 | int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term, |
74 | struct perf_evlist *evlist, int *error_pos); | 74 | struct perf_evlist *evlist, int *error_pos); |
@@ -107,9 +107,9 @@ static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0 | |||
107 | static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; } | 107 | static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; } |
108 | 108 | ||
109 | static inline int | 109 | static inline int |
110 | bpf__foreach_tev(struct bpf_object *obj __maybe_unused, | 110 | bpf__foreach_event(struct bpf_object *obj __maybe_unused, |
111 | bpf_prog_iter_callback_t func __maybe_unused, | 111 | bpf_prog_iter_callback_t func __maybe_unused, |
112 | void *arg __maybe_unused) | 112 | void *arg __maybe_unused) |
113 | { | 113 | { |
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 67e5966503b2..5651f3c12f93 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "tool.h" | 17 | #include "tool.h" |
18 | #include "header.h" | 18 | #include "header.h" |
19 | #include "vdso.h" | 19 | #include "vdso.h" |
20 | #include "probe-file.h" | ||
20 | 21 | ||
21 | 22 | ||
22 | static bool no_buildid_cache; | 23 | static bool no_buildid_cache; |
@@ -144,7 +145,28 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...) | |||
144 | return ret; | 145 | return ret; |
145 | } | 146 | } |
146 | 147 | ||
147 | static char *build_id__filename(const char *sbuild_id, char *bf, size_t size) | 148 | char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf, |
149 | size_t size) | ||
150 | { | ||
151 | bool retry_old = true; | ||
152 | |||
153 | snprintf(bf, size, "%s/%s/%s/kallsyms", | ||
154 | buildid_dir, DSO__NAME_KALLSYMS, sbuild_id); | ||
155 | retry: | ||
156 | if (!access(bf, F_OK)) | ||
157 | return bf; | ||
158 | if (retry_old) { | ||
159 | /* Try old style kallsyms cache */ | ||
160 | snprintf(bf, size, "%s/%s/%s", | ||
161 | buildid_dir, DSO__NAME_KALLSYMS, sbuild_id); | ||
162 | retry_old = false; | ||
163 | goto retry; | ||
164 | } | ||
165 | |||
166 | return NULL; | ||
167 | } | ||
168 | |||
169 | char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size) | ||
148 | { | 170 | { |
149 | char *tmp = bf; | 171 | char *tmp = bf; |
150 | int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir, | 172 | int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir, |
@@ -154,23 +176,107 @@ static char *build_id__filename(const char *sbuild_id, char *bf, size_t size) | |||
154 | return bf; | 176 | return bf; |
155 | } | 177 | } |
156 | 178 | ||
179 | char *build_id_cache__origname(const char *sbuild_id) | ||
180 | { | ||
181 | char *linkname; | ||
182 | char buf[PATH_MAX]; | ||
183 | char *ret = NULL, *p; | ||
184 | size_t offs = 5; /* == strlen("../..") */ | ||
185 | |||
186 | linkname = build_id_cache__linkname(sbuild_id, NULL, 0); | ||
187 | if (!linkname) | ||
188 | return NULL; | ||
189 | |||
190 | if (readlink(linkname, buf, PATH_MAX) < 0) | ||
191 | goto out; | ||
192 | /* The link should be "../..<origpath>/<sbuild_id>" */ | ||
193 | p = strrchr(buf, '/'); /* Cut off the "/<sbuild_id>" */ | ||
194 | if (p && (p > buf + offs)) { | ||
195 | *p = '\0'; | ||
196 | if (buf[offs + 1] == '[') | ||
197 | offs++; /* | ||
198 | * This is a DSO name, like [kernel.kallsyms]. | ||
199 | * Skip the first '/', since this is not the | ||
200 | * cache of a regular file. | ||
201 | */ | ||
202 | ret = strdup(buf + offs); /* Skip "../..[/]" */ | ||
203 | } | ||
204 | out: | ||
205 | free(linkname); | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | /* Check if the given build_id cache is valid on current running system */ | ||
210 | static bool build_id_cache__valid_id(char *sbuild_id) | ||
211 | { | ||
212 | char real_sbuild_id[SBUILD_ID_SIZE] = ""; | ||
213 | char *pathname; | ||
214 | int ret = 0; | ||
215 | bool result = false; | ||
216 | |||
217 | pathname = build_id_cache__origname(sbuild_id); | ||
218 | if (!pathname) | ||
219 | return false; | ||
220 | |||
221 | if (!strcmp(pathname, DSO__NAME_KALLSYMS)) | ||
222 | ret = sysfs__sprintf_build_id("/", real_sbuild_id); | ||
223 | else if (pathname[0] == '/') | ||
224 | ret = filename__sprintf_build_id(pathname, real_sbuild_id); | ||
225 | else | ||
226 | ret = -EINVAL; /* Should we support other special DSO cache? */ | ||
227 | if (ret >= 0) | ||
228 | result = (strcmp(sbuild_id, real_sbuild_id) == 0); | ||
229 | free(pathname); | ||
230 | |||
231 | return result; | ||
232 | } | ||
233 | |||
234 | static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso) | ||
235 | { | ||
236 | return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf"); | ||
237 | } | ||
238 | |||
157 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) | 239 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) |
158 | { | 240 | { |
159 | char build_id_hex[SBUILD_ID_SIZE]; | 241 | bool is_kallsyms = dso__is_kallsyms((struct dso *)dso); |
242 | bool is_vdso = dso__is_vdso((struct dso *)dso); | ||
243 | char sbuild_id[SBUILD_ID_SIZE]; | ||
244 | char *linkname; | ||
245 | bool alloc = (bf == NULL); | ||
246 | int ret; | ||
160 | 247 | ||
161 | if (!dso->has_build_id) | 248 | if (!dso->has_build_id) |
162 | return NULL; | 249 | return NULL; |
163 | 250 | ||
164 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex); | 251 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); |
165 | return build_id__filename(build_id_hex, bf, size); | 252 | linkname = build_id_cache__linkname(sbuild_id, NULL, 0); |
253 | if (!linkname) | ||
254 | return NULL; | ||
255 | |||
256 | /* Check if old style build_id cache */ | ||
257 | if (is_regular_file(linkname)) | ||
258 | ret = asnprintf(&bf, size, "%s", linkname); | ||
259 | else | ||
260 | ret = asnprintf(&bf, size, "%s/%s", linkname, | ||
261 | build_id_cache__basename(is_kallsyms, is_vdso)); | ||
262 | if (ret < 0 || (!alloc && size < (unsigned int)ret)) | ||
263 | bf = NULL; | ||
264 | free(linkname); | ||
265 | |||
266 | return bf; | ||
166 | } | 267 | } |
167 | 268 | ||
168 | bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size) | 269 | bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size) |
169 | { | 270 | { |
170 | char *id_name, *ch; | 271 | char *id_name = NULL, *ch; |
171 | struct stat sb; | 272 | struct stat sb; |
273 | char sbuild_id[SBUILD_ID_SIZE]; | ||
172 | 274 | ||
173 | id_name = dso__build_id_filename(dso, bf, size); | 275 | if (!dso->has_build_id) |
276 | goto err; | ||
277 | |||
278 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | ||
279 | id_name = build_id_cache__linkname(sbuild_id, NULL, 0); | ||
174 | if (!id_name) | 280 | if (!id_name) |
175 | goto err; | 281 | goto err; |
176 | if (access(id_name, F_OK)) | 282 | if (access(id_name, F_OK)) |
@@ -194,18 +300,14 @@ bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size) | |||
194 | if (ch - 3 < bf) | 300 | if (ch - 3 < bf) |
195 | goto err; | 301 | goto err; |
196 | 302 | ||
303 | free(id_name); | ||
197 | return strncmp(".ko", ch - 3, 3) == 0; | 304 | return strncmp(".ko", ch - 3, 3) == 0; |
198 | err: | 305 | err: |
199 | /* | ||
200 | * If dso__build_id_filename work, get id_name again, | ||
201 | * because id_name points to bf and is broken. | ||
202 | */ | ||
203 | if (id_name) | ||
204 | id_name = dso__build_id_filename(dso, bf, size); | ||
205 | pr_err("Invalid build id: %s\n", id_name ? : | 306 | pr_err("Invalid build id: %s\n", id_name ? : |
206 | dso->long_name ? : | 307 | dso->long_name ? : |
207 | dso->short_name ? : | 308 | dso->short_name ? : |
208 | "[unknown]"); | 309 | "[unknown]"); |
310 | free(id_name); | ||
209 | return false; | 311 | return false; |
210 | } | 312 | } |
211 | 313 | ||
@@ -340,8 +442,132 @@ void disable_buildid_cache(void) | |||
340 | no_buildid_cache = true; | 442 | no_buildid_cache = true; |
341 | } | 443 | } |
342 | 444 | ||
343 | static char *build_id_cache__dirname_from_path(const char *name, | 445 | static bool lsdir_bid_head_filter(const char *name __maybe_unused, |
344 | bool is_kallsyms, bool is_vdso) | 446 | struct dirent *d __maybe_unused) |
447 | { | ||
448 | return (strlen(d->d_name) == 2) && | ||
449 | isxdigit(d->d_name[0]) && isxdigit(d->d_name[1]); | ||
450 | } | ||
451 | |||
452 | static bool lsdir_bid_tail_filter(const char *name __maybe_unused, | ||
453 | struct dirent *d __maybe_unused) | ||
454 | { | ||
455 | int i = 0; | ||
456 | while (isxdigit(d->d_name[i]) && i < SBUILD_ID_SIZE - 3) | ||
457 | i++; | ||
458 | return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0'); | ||
459 | } | ||
460 | |||
461 | struct strlist *build_id_cache__list_all(bool validonly) | ||
462 | { | ||
463 | struct strlist *toplist, *linklist = NULL, *bidlist; | ||
464 | struct str_node *nd, *nd2; | ||
465 | char *topdir, *linkdir = NULL; | ||
466 | char sbuild_id[SBUILD_ID_SIZE]; | ||
467 | |||
468 | /* for filename__ functions */ | ||
469 | if (validonly) | ||
470 | symbol__init(NULL); | ||
471 | |||
472 | /* Open the top-level directory */ | ||
473 | if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0) | ||
474 | return NULL; | ||
475 | |||
476 | bidlist = strlist__new(NULL, NULL); | ||
477 | if (!bidlist) | ||
478 | goto out; | ||
479 | |||
480 | toplist = lsdir(topdir, lsdir_bid_head_filter); | ||
481 | if (!toplist) { | ||
482 | pr_debug("Error in lsdir(%s): %d\n", topdir, errno); | ||
483 | /* If there is no buildid cache, return an empty list */ | ||
484 | if (errno == ENOENT) | ||
485 | goto out; | ||
486 | goto err_out; | ||
487 | } | ||
488 | |||
489 | strlist__for_each_entry(nd, toplist) { | ||
490 | if (asprintf(&linkdir, "%s/%s", topdir, nd->s) < 0) | ||
491 | goto err_out; | ||
492 | /* Open the lower-level directory */ | ||
493 | linklist = lsdir(linkdir, lsdir_bid_tail_filter); | ||
494 | if (!linklist) { | ||
495 | pr_debug("Error in lsdir(%s): %d\n", linkdir, errno); | ||
496 | goto err_out; | ||
497 | } | ||
498 | strlist__for_each_entry(nd2, linklist) { | ||
499 | if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s", | ||
500 | nd->s, nd2->s) != SBUILD_ID_SIZE - 1) | ||
501 | goto err_out; | ||
502 | if (validonly && !build_id_cache__valid_id(sbuild_id)) | ||
503 | continue; | ||
504 | if (strlist__add(bidlist, sbuild_id) < 0) | ||
505 | goto err_out; | ||
506 | } | ||
507 | strlist__delete(linklist); | ||
508 | zfree(&linkdir); | ||
509 | } | ||
510 | |||
511 | out_free: | ||
512 | strlist__delete(toplist); | ||
513 | out: | ||
514 | free(topdir); | ||
515 | |||
516 | return bidlist; | ||
517 | |||
518 | err_out: | ||
519 | strlist__delete(linklist); | ||
520 | zfree(&linkdir); | ||
521 | strlist__delete(bidlist); | ||
522 | bidlist = NULL; | ||
523 | goto out_free; | ||
524 | } | ||
525 | |||
526 | static bool str_is_build_id(const char *maybe_sbuild_id, size_t len) | ||
527 | { | ||
528 | size_t i; | ||
529 | |||
530 | for (i = 0; i < len; i++) { | ||
531 | if (!isxdigit(maybe_sbuild_id[i])) | ||
532 | return false; | ||
533 | } | ||
534 | return true; | ||
535 | } | ||
536 | |||
537 | /* Return the valid complete build-id */ | ||
538 | char *build_id_cache__complement(const char *incomplete_sbuild_id) | ||
539 | { | ||
540 | struct strlist *bidlist; | ||
541 | struct str_node *nd, *cand = NULL; | ||
542 | char *sbuild_id = NULL; | ||
543 | size_t len = strlen(incomplete_sbuild_id); | ||
544 | |||
545 | if (len >= SBUILD_ID_SIZE || | ||
546 | !str_is_build_id(incomplete_sbuild_id, len)) | ||
547 | return NULL; | ||
548 | |||
549 | bidlist = build_id_cache__list_all(true); | ||
550 | if (!bidlist) | ||
551 | return NULL; | ||
552 | |||
553 | strlist__for_each_entry(nd, bidlist) { | ||
554 | if (strncmp(nd->s, incomplete_sbuild_id, len) != 0) | ||
555 | continue; | ||
556 | if (cand) { /* Error: There are more than 2 candidates. */ | ||
557 | cand = NULL; | ||
558 | break; | ||
559 | } | ||
560 | cand = nd; | ||
561 | } | ||
562 | if (cand) | ||
563 | sbuild_id = strdup(cand->s); | ||
564 | strlist__delete(bidlist); | ||
565 | |||
566 | return sbuild_id; | ||
567 | } | ||
568 | |||
569 | char *build_id_cache__cachedir(const char *sbuild_id, const char *name, | ||
570 | bool is_kallsyms, bool is_vdso) | ||
345 | { | 571 | { |
346 | char *realname = (char *)name, *filename; | 572 | char *realname = (char *)name, *filename; |
347 | bool slash = is_kallsyms || is_vdso; | 573 | bool slash = is_kallsyms || is_vdso; |
@@ -352,8 +578,9 @@ static char *build_id_cache__dirname_from_path(const char *name, | |||
352 | return NULL; | 578 | return NULL; |
353 | } | 579 | } |
354 | 580 | ||
355 | if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "", | 581 | if (asprintf(&filename, "%s%s%s%s%s", buildid_dir, slash ? "/" : "", |
356 | is_vdso ? DSO__NAME_VDSO : realname) < 0) | 582 | is_vdso ? DSO__NAME_VDSO : realname, |
583 | sbuild_id ? "/" : "", sbuild_id ?: "") < 0) | ||
357 | filename = NULL; | 584 | filename = NULL; |
358 | 585 | ||
359 | if (!slash) | 586 | if (!slash) |
@@ -368,7 +595,7 @@ int build_id_cache__list_build_ids(const char *pathname, | |||
368 | char *dir_name; | 595 | char *dir_name; |
369 | int ret = 0; | 596 | int ret = 0; |
370 | 597 | ||
371 | dir_name = build_id_cache__dirname_from_path(pathname, false, false); | 598 | dir_name = build_id_cache__cachedir(NULL, pathname, false, false); |
372 | if (!dir_name) | 599 | if (!dir_name) |
373 | return -ENOMEM; | 600 | return -ENOMEM; |
374 | 601 | ||
@@ -380,12 +607,36 @@ int build_id_cache__list_build_ids(const char *pathname, | |||
380 | return ret; | 607 | return ret; |
381 | } | 608 | } |
382 | 609 | ||
610 | #if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT) | ||
611 | static int build_id_cache__add_sdt_cache(const char *sbuild_id, | ||
612 | const char *realname) | ||
613 | { | ||
614 | struct probe_cache *cache; | ||
615 | int ret; | ||
616 | |||
617 | cache = probe_cache__new(sbuild_id); | ||
618 | if (!cache) | ||
619 | return -1; | ||
620 | |||
621 | ret = probe_cache__scan_sdt(cache, realname); | ||
622 | if (ret >= 0) { | ||
623 | pr_debug("Found %d SDTs in %s\n", ret, realname); | ||
624 | if (probe_cache__commit(cache) < 0) | ||
625 | ret = -1; | ||
626 | } | ||
627 | probe_cache__delete(cache); | ||
628 | return ret; | ||
629 | } | ||
630 | #else | ||
631 | #define build_id_cache__add_sdt_cache(sbuild_id, realname) (0) | ||
632 | #endif | ||
633 | |||
383 | int build_id_cache__add_s(const char *sbuild_id, const char *name, | 634 | int build_id_cache__add_s(const char *sbuild_id, const char *name, |
384 | bool is_kallsyms, bool is_vdso) | 635 | bool is_kallsyms, bool is_vdso) |
385 | { | 636 | { |
386 | const size_t size = PATH_MAX; | 637 | const size_t size = PATH_MAX; |
387 | char *realname = NULL, *filename = NULL, *dir_name = NULL, | 638 | char *realname = NULL, *filename = NULL, *dir_name = NULL, |
388 | *linkname = zalloc(size), *targetname, *tmp; | 639 | *linkname = zalloc(size), *tmp; |
389 | int err = -1; | 640 | int err = -1; |
390 | 641 | ||
391 | if (!is_kallsyms) { | 642 | if (!is_kallsyms) { |
@@ -394,14 +645,22 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name, | |||
394 | goto out_free; | 645 | goto out_free; |
395 | } | 646 | } |
396 | 647 | ||
397 | dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso); | 648 | dir_name = build_id_cache__cachedir(sbuild_id, name, |
649 | is_kallsyms, is_vdso); | ||
398 | if (!dir_name) | 650 | if (!dir_name) |
399 | goto out_free; | 651 | goto out_free; |
400 | 652 | ||
653 | /* Remove old style build-id cache */ | ||
654 | if (is_regular_file(dir_name)) | ||
655 | if (unlink(dir_name)) | ||
656 | goto out_free; | ||
657 | |||
401 | if (mkdir_p(dir_name, 0755)) | 658 | if (mkdir_p(dir_name, 0755)) |
402 | goto out_free; | 659 | goto out_free; |
403 | 660 | ||
404 | if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) { | 661 | /* Save the allocated buildid dirname */ |
662 | if (asprintf(&filename, "%s/%s", dir_name, | ||
663 | build_id_cache__basename(is_kallsyms, is_vdso)) < 0) { | ||
405 | filename = NULL; | 664 | filename = NULL; |
406 | goto out_free; | 665 | goto out_free; |
407 | } | 666 | } |
@@ -415,7 +674,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name, | |||
415 | goto out_free; | 674 | goto out_free; |
416 | } | 675 | } |
417 | 676 | ||
418 | if (!build_id__filename(sbuild_id, linkname, size)) | 677 | if (!build_id_cache__linkname(sbuild_id, linkname, size)) |
419 | goto out_free; | 678 | goto out_free; |
420 | tmp = strrchr(linkname, '/'); | 679 | tmp = strrchr(linkname, '/'); |
421 | *tmp = '\0'; | 680 | *tmp = '\0'; |
@@ -424,11 +683,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name, | |||
424 | goto out_free; | 683 | goto out_free; |
425 | 684 | ||
426 | *tmp = '/'; | 685 | *tmp = '/'; |
427 | targetname = filename + strlen(buildid_dir) - 5; | 686 | tmp = dir_name + strlen(buildid_dir) - 5; |
428 | memcpy(targetname, "../..", 5); | 687 | memcpy(tmp, "../..", 5); |
429 | 688 | ||
430 | if (symlink(targetname, linkname) == 0) | 689 | if (symlink(tmp, linkname) == 0) |
431 | err = 0; | 690 | err = 0; |
691 | |||
692 | /* Update SDT cache : error is just warned */ | ||
693 | if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) | ||
694 | pr_debug("Failed to update/scan SDT cache for %s\n", realname); | ||
695 | |||
432 | out_free: | 696 | out_free: |
433 | if (!is_kallsyms) | 697 | if (!is_kallsyms) |
434 | free(realname); | 698 | free(realname); |
@@ -452,7 +716,7 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, | |||
452 | bool build_id_cache__cached(const char *sbuild_id) | 716 | bool build_id_cache__cached(const char *sbuild_id) |
453 | { | 717 | { |
454 | bool ret = false; | 718 | bool ret = false; |
455 | char *filename = build_id__filename(sbuild_id, NULL, 0); | 719 | char *filename = build_id_cache__linkname(sbuild_id, NULL, 0); |
456 | 720 | ||
457 | if (filename && !access(filename, F_OK)) | 721 | if (filename && !access(filename, F_OK)) |
458 | ret = true; | 722 | ret = true; |
@@ -471,7 +735,7 @@ int build_id_cache__remove_s(const char *sbuild_id) | |||
471 | if (filename == NULL || linkname == NULL) | 735 | if (filename == NULL || linkname == NULL) |
472 | goto out_free; | 736 | goto out_free; |
473 | 737 | ||
474 | if (!build_id__filename(sbuild_id, linkname, size)) | 738 | if (!build_id_cache__linkname(sbuild_id, linkname, size)) |
475 | goto out_free; | 739 | goto out_free; |
476 | 740 | ||
477 | if (access(linkname, F_OK)) | 741 | if (access(linkname, F_OK)) |
@@ -489,7 +753,7 @@ int build_id_cache__remove_s(const char *sbuild_id) | |||
489 | tmp = strrchr(linkname, '/') + 1; | 753 | tmp = strrchr(linkname, '/') + 1; |
490 | snprintf(tmp, size - (tmp - linkname), "%s", filename); | 754 | snprintf(tmp, size - (tmp - linkname), "%s", filename); |
491 | 755 | ||
492 | if (unlink(linkname)) | 756 | if (rm_rf(linkname)) |
493 | goto out_free; | 757 | goto out_free; |
494 | 758 | ||
495 | err = 0; | 759 | err = 0; |
@@ -501,7 +765,7 @@ out_free: | |||
501 | 765 | ||
502 | static int dso__cache_build_id(struct dso *dso, struct machine *machine) | 766 | static int dso__cache_build_id(struct dso *dso, struct machine *machine) |
503 | { | 767 | { |
504 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; | 768 | bool is_kallsyms = dso__is_kallsyms(dso); |
505 | bool is_vdso = dso__is_vdso(dso); | 769 | bool is_vdso = dso__is_vdso(dso); |
506 | const char *name = dso->long_name; | 770 | const char *name = dso->long_name; |
507 | char nm[PATH_MAX]; | 771 | char nm[PATH_MAX]; |
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 64af3e20610d..d27990610f9f 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h | |||
@@ -14,6 +14,8 @@ struct dso; | |||
14 | int build_id__sprintf(const u8 *build_id, int len, char *bf); | 14 | int build_id__sprintf(const u8 *build_id, int len, char *bf); |
15 | int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id); | 15 | int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id); |
16 | int filename__sprintf_build_id(const char *pathname, char *sbuild_id); | 16 | int filename__sprintf_build_id(const char *pathname, char *sbuild_id); |
17 | char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf, | ||
18 | size_t size); | ||
17 | 19 | ||
18 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); | 20 | char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); |
19 | bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size); | 21 | bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size); |
@@ -28,6 +30,12 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits); | |||
28 | int perf_session__write_buildid_table(struct perf_session *session, int fd); | 30 | int perf_session__write_buildid_table(struct perf_session *session, int fd); |
29 | int perf_session__cache_build_ids(struct perf_session *session); | 31 | int perf_session__cache_build_ids(struct perf_session *session); |
30 | 32 | ||
33 | char *build_id_cache__origname(const char *sbuild_id); | ||
34 | char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size); | ||
35 | char *build_id_cache__cachedir(const char *sbuild_id, const char *name, | ||
36 | bool is_kallsyms, bool is_vdso); | ||
37 | struct strlist *build_id_cache__list_all(bool validonly); | ||
38 | char *build_id_cache__complement(const char *incomplete_sbuild_id); | ||
31 | int build_id_cache__list_build_ids(const char *pathname, | 39 | int build_id_cache__list_build_ids(const char *pathname, |
32 | struct strlist **result); | 40 | struct strlist **result); |
33 | bool build_id_cache__cached(const char *sbuild_id); | 41 | bool build_id_cache__cached(const char *sbuild_id); |
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 0d814bb74661..512c0c83fbc6 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
@@ -1,40 +1,20 @@ | |||
1 | #ifndef __PERF_CACHE_H | 1 | #ifndef __PERF_CACHE_H |
2 | #define __PERF_CACHE_H | 2 | #define __PERF_CACHE_H |
3 | 3 | ||
4 | #include <stdbool.h> | ||
5 | #include "util.h" | ||
6 | #include "strbuf.h" | 4 | #include "strbuf.h" |
7 | #include <subcmd/pager.h> | 5 | #include <subcmd/pager.h> |
8 | #include "../perf.h" | ||
9 | #include "../ui/ui.h" | 6 | #include "../ui/ui.h" |
10 | 7 | ||
11 | #include <linux/string.h> | 8 | #include <linux/string.h> |
12 | 9 | ||
13 | #define CMD_EXEC_PATH "--exec-path" | 10 | #define CMD_EXEC_PATH "--exec-path" |
14 | #define CMD_PERF_DIR "--perf-dir=" | ||
15 | #define CMD_WORK_TREE "--work-tree=" | ||
16 | #define CMD_DEBUGFS_DIR "--debugfs-dir=" | 11 | #define CMD_DEBUGFS_DIR "--debugfs-dir=" |
17 | 12 | ||
18 | #define PERF_DIR_ENVIRONMENT "PERF_DIR" | ||
19 | #define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" | ||
20 | #define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH" | 13 | #define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH" |
21 | #define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" | ||
22 | #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" | 14 | #define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" |
23 | #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" | 15 | #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" |
24 | #define PERF_PAGER_ENVIRONMENT "PERF_PAGER" | 16 | #define PERF_PAGER_ENVIRONMENT "PERF_PAGER" |
25 | 17 | ||
26 | extern const char *config_exclusive_filename; | ||
27 | |||
28 | typedef int (*config_fn_t)(const char *, const char *, void *); | ||
29 | int perf_default_config(const char *, const char *, void *); | ||
30 | int perf_config(config_fn_t fn, void *); | ||
31 | int perf_config_int(const char *, const char *); | ||
32 | u64 perf_config_u64(const char *, const char *); | ||
33 | int perf_config_bool(const char *, const char *); | ||
34 | int config_error_nonbool(const char *); | ||
35 | const char *perf_config_dirname(const char *, const char *); | ||
36 | const char *perf_etc_perfconfig(void); | ||
37 | |||
38 | char *alias_lookup(const char *alias); | 18 | char *alias_lookup(const char *alias); |
39 | int split_cmdline(char *cmdline, const char ***argv); | 19 | int split_cmdline(char *cmdline, const char ***argv); |
40 | 20 | ||
@@ -45,9 +25,6 @@ static inline int is_absolute_path(const char *path) | |||
45 | return path[0] == '/'; | 25 | return path[0] == '/'; |
46 | } | 26 | } |
47 | 27 | ||
48 | char *strip_path_suffix(const char *path, const char *suffix); | ||
49 | |||
50 | char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | 28 | char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); |
51 | char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | ||
52 | 29 | ||
53 | #endif /* __PERF_CACHE_H */ | 30 | #endif /* __PERF_CACHE_H */ |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 65e2a4f7cb4e..13e75549c440 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -94,6 +94,7 @@ struct callchain_param { | |||
94 | enum perf_call_graph_mode record_mode; | 94 | enum perf_call_graph_mode record_mode; |
95 | u32 dump_size; | 95 | u32 dump_size; |
96 | enum chain_mode mode; | 96 | enum chain_mode mode; |
97 | u16 max_stack; | ||
97 | u32 print_limit; | 98 | u32 print_limit; |
98 | double min_percent; | 99 | double min_percent; |
99 | sort_chain_func_t sort; | 100 | sort_chain_func_t sort; |
@@ -105,6 +106,7 @@ struct callchain_param { | |||
105 | }; | 106 | }; |
106 | 107 | ||
107 | extern struct callchain_param callchain_param; | 108 | extern struct callchain_param callchain_param; |
109 | extern struct callchain_param callchain_param_default; | ||
108 | 110 | ||
109 | struct callchain_list { | 111 | struct callchain_list { |
110 | u64 ip; | 112 | u64 ip; |
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 90aa1b46b2e5..8fdee24725a7 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c | |||
@@ -81,7 +81,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str) | |||
81 | /* | 81 | /* |
82 | * check if cgrp is already defined, if so we reuse it | 82 | * check if cgrp is already defined, if so we reuse it |
83 | */ | 83 | */ |
84 | evlist__for_each(evlist, counter) { | 84 | evlist__for_each_entry(evlist, counter) { |
85 | cgrp = counter->cgrp; | 85 | cgrp = counter->cgrp; |
86 | if (!cgrp) | 86 | if (!cgrp) |
87 | continue; | 87 | continue; |
@@ -110,7 +110,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str) | |||
110 | * if add cgroup N, then need to find event N | 110 | * if add cgroup N, then need to find event N |
111 | */ | 111 | */ |
112 | n = 0; | 112 | n = 0; |
113 | evlist__for_each(evlist, counter) { | 113 | evlist__for_each_entry(evlist, counter) { |
114 | if (n == nr_cgroups) | 114 | if (n == nr_cgroups) |
115 | goto found; | 115 | goto found; |
116 | n++; | 116 | n++; |
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c index 2babddaa2481..f0dcd0ee0afa 100644 --- a/tools/perf/util/cloexec.c +++ b/tools/perf/util/cloexec.c | |||
@@ -4,18 +4,24 @@ | |||
4 | #include "cloexec.h" | 4 | #include "cloexec.h" |
5 | #include "asm/bug.h" | 5 | #include "asm/bug.h" |
6 | #include "debug.h" | 6 | #include "debug.h" |
7 | #include <unistd.h> | ||
8 | #include <asm/unistd.h> | ||
9 | #include <sys/syscall.h> | ||
7 | 10 | ||
8 | static unsigned long flag = PERF_FLAG_FD_CLOEXEC; | 11 | static unsigned long flag = PERF_FLAG_FD_CLOEXEC; |
9 | 12 | ||
10 | #ifdef __GLIBC_PREREQ | ||
11 | #if !__GLIBC_PREREQ(2, 6) | ||
12 | int __weak sched_getcpu(void) | 13 | int __weak sched_getcpu(void) |
13 | { | 14 | { |
15 | #ifdef __NR_getcpu | ||
16 | unsigned cpu; | ||
17 | int err = syscall(__NR_getcpu, &cpu, NULL, NULL); | ||
18 | if (!err) | ||
19 | return cpu; | ||
20 | #else | ||
14 | errno = ENOSYS; | 21 | errno = ENOSYS; |
22 | #endif | ||
15 | return -1; | 23 | return -1; |
16 | } | 24 | } |
17 | #endif | ||
18 | #endif | ||
19 | 25 | ||
20 | static int perf_flag_probe(void) | 26 | static int perf_flag_probe(void) |
21 | { | 27 | { |
@@ -58,7 +64,7 @@ static int perf_flag_probe(void) | |||
58 | 64 | ||
59 | WARN_ONCE(err != EINVAL && err != EBUSY, | 65 | WARN_ONCE(err != EINVAL && err != EBUSY, |
60 | "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", | 66 | "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", |
61 | err, strerror_r(err, sbuf, sizeof(sbuf))); | 67 | err, str_error_r(err, sbuf, sizeof(sbuf))); |
62 | 68 | ||
63 | /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ | 69 | /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ |
64 | while (1) { | 70 | while (1) { |
@@ -76,7 +82,7 @@ static int perf_flag_probe(void) | |||
76 | 82 | ||
77 | if (WARN_ONCE(fd < 0 && err != EBUSY, | 83 | if (WARN_ONCE(fd < 0 && err != EBUSY, |
78 | "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", | 84 | "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", |
79 | err, strerror_r(err, sbuf, sizeof(sbuf)))) | 85 | err, str_error_r(err, sbuf, sizeof(sbuf)))) |
80 | return -1; | 86 | return -1; |
81 | 87 | ||
82 | return 0; | 88 | return 0; |
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 43e84aa27e4a..dbbf89b050a5 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c | |||
@@ -1,7 +1,11 @@ | |||
1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
2 | #include "cache.h" | 2 | #include "cache.h" |
3 | #include "config.h" | ||
4 | #include <stdlib.h> | ||
5 | #include <stdio.h> | ||
3 | #include "color.h" | 6 | #include "color.h" |
4 | #include <math.h> | 7 | #include <math.h> |
8 | #include <unistd.h> | ||
5 | 9 | ||
6 | int perf_use_color_default = -1; | 10 | int perf_use_color_default = -1; |
7 | 11 | ||
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index dad7d8272168..18dae745034f 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c | |||
@@ -26,6 +26,7 @@ static FILE *config_file; | |||
26 | static const char *config_file_name; | 26 | static const char *config_file_name; |
27 | static int config_linenr; | 27 | static int config_linenr; |
28 | static int config_file_eof; | 28 | static int config_file_eof; |
29 | static struct perf_config_set *config_set; | ||
29 | 30 | ||
30 | const char *config_exclusive_filename; | 31 | const char *config_exclusive_filename; |
31 | 32 | ||
@@ -275,7 +276,8 @@ static int perf_parse_file(config_fn_t fn, void *data) | |||
275 | break; | 276 | break; |
276 | } | 277 | } |
277 | } | 278 | } |
278 | die("bad config file line %d in %s", config_linenr, config_file_name); | 279 | pr_err("bad config file line %d in %s\n", config_linenr, config_file_name); |
280 | return -1; | ||
279 | } | 281 | } |
280 | 282 | ||
281 | static int parse_unit_factor(const char *end, unsigned long *val) | 283 | static int parse_unit_factor(const char *end, unsigned long *val) |
@@ -371,7 +373,7 @@ int perf_config_bool(const char *name, const char *value) | |||
371 | return !!perf_config_bool_or_int(name, value, &discard); | 373 | return !!perf_config_bool_or_int(name, value, &discard); |
372 | } | 374 | } |
373 | 375 | ||
374 | const char *perf_config_dirname(const char *name, const char *value) | 376 | static const char *perf_config_dirname(const char *name, const char *value) |
375 | { | 377 | { |
376 | if (!name) | 378 | if (!name) |
377 | return NULL; | 379 | return NULL; |
@@ -477,54 +479,6 @@ static int perf_config_global(void) | |||
477 | return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); | 479 | return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); |
478 | } | 480 | } |
479 | 481 | ||
480 | int perf_config(config_fn_t fn, void *data) | ||
481 | { | ||
482 | int ret = 0, found = 0; | ||
483 | const char *home = NULL; | ||
484 | |||
485 | /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ | ||
486 | if (config_exclusive_filename) | ||
487 | return perf_config_from_file(fn, config_exclusive_filename, data); | ||
488 | if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { | ||
489 | ret += perf_config_from_file(fn, perf_etc_perfconfig(), | ||
490 | data); | ||
491 | found += 1; | ||
492 | } | ||
493 | |||
494 | home = getenv("HOME"); | ||
495 | if (perf_config_global() && home) { | ||
496 | char *user_config = strdup(mkpath("%s/.perfconfig", home)); | ||
497 | struct stat st; | ||
498 | |||
499 | if (user_config == NULL) { | ||
500 | warning("Not enough memory to process %s/.perfconfig, " | ||
501 | "ignoring it.", home); | ||
502 | goto out; | ||
503 | } | ||
504 | |||
505 | if (stat(user_config, &st) < 0) | ||
506 | goto out_free; | ||
507 | |||
508 | if (st.st_uid && (st.st_uid != geteuid())) { | ||
509 | warning("File %s not owned by current user or root, " | ||
510 | "ignoring it.", user_config); | ||
511 | goto out_free; | ||
512 | } | ||
513 | |||
514 | if (!st.st_size) | ||
515 | goto out_free; | ||
516 | |||
517 | ret += perf_config_from_file(fn, user_config, data); | ||
518 | found += 1; | ||
519 | out_free: | ||
520 | free(user_config); | ||
521 | } | ||
522 | out: | ||
523 | if (found == 0) | ||
524 | return -1; | ||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | static struct perf_config_section *find_section(struct list_head *sections, | 482 | static struct perf_config_section *find_section(struct list_head *sections, |
529 | const char *section_name) | 483 | const char *section_name) |
530 | { | 484 | { |
@@ -609,8 +563,12 @@ static int collect_config(const char *var, const char *value, | |||
609 | struct perf_config_section *section = NULL; | 563 | struct perf_config_section *section = NULL; |
610 | struct perf_config_item *item = NULL; | 564 | struct perf_config_item *item = NULL; |
611 | struct perf_config_set *set = perf_config_set; | 565 | struct perf_config_set *set = perf_config_set; |
612 | struct list_head *sections = &set->sections; | 566 | struct list_head *sections; |
567 | |||
568 | if (set == NULL) | ||
569 | return -1; | ||
613 | 570 | ||
571 | sections = &set->sections; | ||
614 | key = ptr = strdup(var); | 572 | key = ptr = strdup(var); |
615 | if (!key) { | 573 | if (!key) { |
616 | pr_debug("%s: strdup failed\n", __func__); | 574 | pr_debug("%s: strdup failed\n", __func__); |
@@ -641,22 +599,115 @@ static int collect_config(const char *var, const char *value, | |||
641 | 599 | ||
642 | out_free: | 600 | out_free: |
643 | free(key); | 601 | free(key); |
644 | perf_config_set__delete(set); | ||
645 | return -1; | 602 | return -1; |
646 | } | 603 | } |
647 | 604 | ||
605 | static int perf_config_set__init(struct perf_config_set *set) | ||
606 | { | ||
607 | int ret = -1; | ||
608 | const char *home = NULL; | ||
609 | |||
610 | /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ | ||
611 | if (config_exclusive_filename) | ||
612 | return perf_config_from_file(collect_config, config_exclusive_filename, set); | ||
613 | if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { | ||
614 | if (perf_config_from_file(collect_config, perf_etc_perfconfig(), set) < 0) | ||
615 | goto out; | ||
616 | } | ||
617 | |||
618 | home = getenv("HOME"); | ||
619 | if (perf_config_global() && home) { | ||
620 | char *user_config = strdup(mkpath("%s/.perfconfig", home)); | ||
621 | struct stat st; | ||
622 | |||
623 | if (user_config == NULL) { | ||
624 | warning("Not enough memory to process %s/.perfconfig, " | ||
625 | "ignoring it.", home); | ||
626 | goto out; | ||
627 | } | ||
628 | |||
629 | if (stat(user_config, &st) < 0) | ||
630 | goto out_free; | ||
631 | |||
632 | if (st.st_uid && (st.st_uid != geteuid())) { | ||
633 | warning("File %s not owned by current user or root, " | ||
634 | "ignoring it.", user_config); | ||
635 | goto out_free; | ||
636 | } | ||
637 | |||
638 | if (!st.st_size) | ||
639 | goto out_free; | ||
640 | |||
641 | ret = perf_config_from_file(collect_config, user_config, set); | ||
642 | |||
643 | out_free: | ||
644 | free(user_config); | ||
645 | } | ||
646 | out: | ||
647 | return ret; | ||
648 | } | ||
649 | |||
648 | struct perf_config_set *perf_config_set__new(void) | 650 | struct perf_config_set *perf_config_set__new(void) |
649 | { | 651 | { |
650 | struct perf_config_set *set = zalloc(sizeof(*set)); | 652 | struct perf_config_set *set = zalloc(sizeof(*set)); |
651 | 653 | ||
652 | if (set) { | 654 | if (set) { |
653 | INIT_LIST_HEAD(&set->sections); | 655 | INIT_LIST_HEAD(&set->sections); |
654 | perf_config(collect_config, set); | 656 | if (perf_config_set__init(set) < 0) { |
657 | perf_config_set__delete(set); | ||
658 | set = NULL; | ||
659 | } | ||
655 | } | 660 | } |
656 | 661 | ||
657 | return set; | 662 | return set; |
658 | } | 663 | } |
659 | 664 | ||
665 | int perf_config(config_fn_t fn, void *data) | ||
666 | { | ||
667 | int ret = 0; | ||
668 | char key[BUFSIZ]; | ||
669 | struct perf_config_section *section; | ||
670 | struct perf_config_item *item; | ||
671 | |||
672 | if (config_set == NULL) | ||
673 | return -1; | ||
674 | |||
675 | perf_config_set__for_each_entry(config_set, section, item) { | ||
676 | char *value = item->value; | ||
677 | |||
678 | if (value) { | ||
679 | scnprintf(key, sizeof(key), "%s.%s", | ||
680 | section->name, item->name); | ||
681 | ret = fn(key, value, data); | ||
682 | if (ret < 0) { | ||
683 | pr_err("Error: wrong config key-value pair %s=%s\n", | ||
684 | key, value); | ||
685 | break; | ||
686 | } | ||
687 | } | ||
688 | } | ||
689 | |||
690 | return ret; | ||
691 | } | ||
692 | |||
693 | void perf_config__init(void) | ||
694 | { | ||
695 | if (config_set == NULL) | ||
696 | config_set = perf_config_set__new(); | ||
697 | } | ||
698 | |||
699 | void perf_config__exit(void) | ||
700 | { | ||
701 | perf_config_set__delete(config_set); | ||
702 | config_set = NULL; | ||
703 | } | ||
704 | |||
705 | void perf_config__refresh(void) | ||
706 | { | ||
707 | perf_config__exit(); | ||
708 | perf_config__init(); | ||
709 | } | ||
710 | |||
660 | static void perf_config_item__delete(struct perf_config_item *item) | 711 | static void perf_config_item__delete(struct perf_config_item *item) |
661 | { | 712 | { |
662 | zfree(&item->name); | 713 | zfree(&item->name); |
@@ -693,6 +744,9 @@ static void perf_config_set__purge(struct perf_config_set *set) | |||
693 | 744 | ||
694 | void perf_config_set__delete(struct perf_config_set *set) | 745 | void perf_config_set__delete(struct perf_config_set *set) |
695 | { | 746 | { |
747 | if (set == NULL) | ||
748 | return; | ||
749 | |||
696 | perf_config_set__purge(set); | 750 | perf_config_set__purge(set); |
697 | free(set); | 751 | free(set); |
698 | } | 752 | } |
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h index 22ec626ac718..6f813d46045e 100644 --- a/tools/perf/util/config.h +++ b/tools/perf/util/config.h | |||
@@ -20,7 +20,47 @@ struct perf_config_set { | |||
20 | struct list_head sections; | 20 | struct list_head sections; |
21 | }; | 21 | }; |
22 | 22 | ||
23 | extern const char *config_exclusive_filename; | ||
24 | |||
25 | typedef int (*config_fn_t)(const char *, const char *, void *); | ||
26 | int perf_default_config(const char *, const char *, void *); | ||
27 | int perf_config(config_fn_t fn, void *); | ||
28 | int perf_config_int(const char *, const char *); | ||
29 | u64 perf_config_u64(const char *, const char *); | ||
30 | int perf_config_bool(const char *, const char *); | ||
31 | int config_error_nonbool(const char *); | ||
32 | const char *perf_etc_perfconfig(void); | ||
33 | |||
23 | struct perf_config_set *perf_config_set__new(void); | 34 | struct perf_config_set *perf_config_set__new(void); |
24 | void perf_config_set__delete(struct perf_config_set *set); | 35 | void perf_config_set__delete(struct perf_config_set *set); |
36 | void perf_config__init(void); | ||
37 | void perf_config__exit(void); | ||
38 | void perf_config__refresh(void); | ||
39 | |||
40 | /** | ||
41 | * perf_config_sections__for_each - iterate thru all the sections | ||
42 | * @list: list_head instance to iterate | ||
43 | * @section: struct perf_config_section iterator | ||
44 | */ | ||
45 | #define perf_config_sections__for_each_entry(list, section) \ | ||
46 | list_for_each_entry(section, list, node) | ||
47 | |||
48 | /** | ||
49 | * perf_config_items__for_each - iterate thru all the items | ||
50 | * @list: list_head instance to iterate | ||
51 | * @item: struct perf_config_item iterator | ||
52 | */ | ||
53 | #define perf_config_items__for_each_entry(list, item) \ | ||
54 | list_for_each_entry(item, list, node) | ||
55 | |||
56 | /** | ||
57 | * perf_config_set__for_each - iterate thru all the config section-item pairs | ||
58 | * @set: evlist instance to iterate | ||
59 | * @section: struct perf_config_section iterator | ||
60 | * @item: struct perf_config_item iterator | ||
61 | */ | ||
62 | #define perf_config_set__for_each_entry(set, section, item) \ | ||
63 | perf_config_sections__for_each_entry(&set->sections, section) \ | ||
64 | perf_config_items__for_each_entry(§ion->items, item) | ||
25 | 65 | ||
26 | #endif /* __PERF_CONFIG_H */ | 66 | #endif /* __PERF_CONFIG_H */ |
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 02d801670f30..2c0b52264a46 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c | |||
@@ -236,13 +236,12 @@ struct cpu_map *cpu_map__new_data(struct cpu_map_data *data) | |||
236 | 236 | ||
237 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp) | 237 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp) |
238 | { | 238 | { |
239 | int i; | 239 | #define BUFSIZE 1024 |
240 | size_t printed = fprintf(fp, "%d cpu%s: ", | 240 | char buf[BUFSIZE]; |
241 | map->nr, map->nr > 1 ? "s" : ""); | ||
242 | for (i = 0; i < map->nr; ++i) | ||
243 | printed += fprintf(fp, "%s%d", i ? ", " : "", map->map[i]); | ||
244 | 241 | ||
245 | return printed + fprintf(fp, "\n"); | 242 | cpu_map__snprint(map, buf, sizeof(buf)); |
243 | return fprintf(fp, "%s\n", buf); | ||
244 | #undef BUFSIZE | ||
246 | } | 245 | } |
247 | 246 | ||
248 | struct cpu_map *cpu_map__dummy_new(void) | 247 | struct cpu_map *cpu_map__dummy_new(void) |
@@ -590,12 +589,65 @@ int cpu__setup_cpunode_map(void) | |||
590 | 589 | ||
591 | bool cpu_map__has(struct cpu_map *cpus, int cpu) | 590 | bool cpu_map__has(struct cpu_map *cpus, int cpu) |
592 | { | 591 | { |
592 | return cpu_map__idx(cpus, cpu) != -1; | ||
593 | } | ||
594 | |||
595 | int cpu_map__idx(struct cpu_map *cpus, int cpu) | ||
596 | { | ||
593 | int i; | 597 | int i; |
594 | 598 | ||
595 | for (i = 0; i < cpus->nr; ++i) { | 599 | for (i = 0; i < cpus->nr; ++i) { |
596 | if (cpus->map[i] == cpu) | 600 | if (cpus->map[i] == cpu) |
597 | return true; | 601 | return i; |
602 | } | ||
603 | |||
604 | return -1; | ||
605 | } | ||
606 | |||
607 | int cpu_map__cpu(struct cpu_map *cpus, int idx) | ||
608 | { | ||
609 | return cpus->map[idx]; | ||
610 | } | ||
611 | |||
612 | size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size) | ||
613 | { | ||
614 | int i, cpu, start = -1; | ||
615 | bool first = true; | ||
616 | size_t ret = 0; | ||
617 | |||
618 | #define COMMA first ? "" : "," | ||
619 | |||
620 | for (i = 0; i < map->nr + 1; i++) { | ||
621 | bool last = i == map->nr; | ||
622 | |||
623 | cpu = last ? INT_MAX : map->map[i]; | ||
624 | |||
625 | if (start == -1) { | ||
626 | start = i; | ||
627 | if (last) { | ||
628 | ret += snprintf(buf + ret, size - ret, | ||
629 | "%s%d", COMMA, | ||
630 | map->map[i]); | ||
631 | } | ||
632 | } else if (((i - start) != (cpu - map->map[start])) || last) { | ||
633 | int end = i - 1; | ||
634 | |||
635 | if (start == end) { | ||
636 | ret += snprintf(buf + ret, size - ret, | ||
637 | "%s%d", COMMA, | ||
638 | map->map[start]); | ||
639 | } else { | ||
640 | ret += snprintf(buf + ret, size - ret, | ||
641 | "%s%d-%d", COMMA, | ||
642 | map->map[start], map->map[end]); | ||
643 | } | ||
644 | first = false; | ||
645 | start = i; | ||
646 | } | ||
598 | } | 647 | } |
599 | 648 | ||
600 | return false; | 649 | #undef COMMA |
650 | |||
651 | pr_debug("cpumask list: %s\n", buf); | ||
652 | return ret; | ||
601 | } | 653 | } |
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 1a0a35073ce1..06bd689f5989 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h | |||
@@ -19,6 +19,7 @@ struct cpu_map *cpu_map__empty_new(int nr); | |||
19 | struct cpu_map *cpu_map__dummy_new(void); | 19 | struct cpu_map *cpu_map__dummy_new(void); |
20 | struct cpu_map *cpu_map__new_data(struct cpu_map_data *data); | 20 | struct cpu_map *cpu_map__new_data(struct cpu_map_data *data); |
21 | struct cpu_map *cpu_map__read(FILE *file); | 21 | struct cpu_map *cpu_map__read(FILE *file); |
22 | size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size); | ||
22 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); | 23 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); |
23 | int cpu_map__get_socket_id(int cpu); | 24 | int cpu_map__get_socket_id(int cpu); |
24 | int cpu_map__get_socket(struct cpu_map *map, int idx, void *data); | 25 | int cpu_map__get_socket(struct cpu_map *map, int idx, void *data); |
@@ -67,5 +68,7 @@ int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, | |||
67 | int (*f)(struct cpu_map *map, int cpu, void *data), | 68 | int (*f)(struct cpu_map *map, int cpu, void *data), |
68 | void *data); | 69 | void *data); |
69 | 70 | ||
71 | int cpu_map__cpu(struct cpu_map *cpus, int idx); | ||
70 | bool cpu_map__has(struct cpu_map *cpus, int cpu); | 72 | bool cpu_map__has(struct cpu_map *cpus, int cpu); |
73 | int cpu_map__idx(struct cpu_map *cpus, int cpu); | ||
71 | #endif /* __PERF_CPUMAP_H */ | 74 | #endif /* __PERF_CPUMAP_H */ |
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 9f53020c3269..4f979bb27b6c 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "evlist.h" | 26 | #include "evlist.h" |
27 | #include "evsel.h" | 27 | #include "evsel.h" |
28 | #include "machine.h" | 28 | #include "machine.h" |
29 | #include "config.h" | ||
29 | 30 | ||
30 | #define pr_N(n, fmt, ...) \ | 31 | #define pr_N(n, fmt, ...) \ |
31 | eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) | 32 | eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) |
@@ -68,6 +69,9 @@ struct ctf_writer { | |||
68 | }; | 69 | }; |
69 | struct bt_ctf_field_type *array[6]; | 70 | struct bt_ctf_field_type *array[6]; |
70 | } data; | 71 | } data; |
72 | struct bt_ctf_event_class *comm_class; | ||
73 | struct bt_ctf_event_class *exit_class; | ||
74 | struct bt_ctf_event_class *fork_class; | ||
71 | }; | 75 | }; |
72 | 76 | ||
73 | struct convert { | 77 | struct convert { |
@@ -76,6 +80,7 @@ struct convert { | |||
76 | 80 | ||
77 | u64 events_size; | 81 | u64 events_size; |
78 | u64 events_count; | 82 | u64 events_count; |
83 | u64 non_sample_count; | ||
79 | 84 | ||
80 | /* Ordered events configured queue size. */ | 85 | /* Ordered events configured queue size. */ |
81 | u64 queue_size; | 86 | u64 queue_size; |
@@ -140,6 +145,36 @@ FUNC_VALUE_SET(s64) | |||
140 | FUNC_VALUE_SET(u64) | 145 | FUNC_VALUE_SET(u64) |
141 | __FUNC_VALUE_SET(u64_hex, u64) | 146 | __FUNC_VALUE_SET(u64_hex, u64) |
142 | 147 | ||
148 | static int string_set_value(struct bt_ctf_field *field, const char *string); | ||
149 | static __maybe_unused int | ||
150 | value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event, | ||
151 | const char *name, const char *string) | ||
152 | { | ||
153 | struct bt_ctf_field_type *type = cw->data.string; | ||
154 | struct bt_ctf_field *field; | ||
155 | int ret = 0; | ||
156 | |||
157 | field = bt_ctf_field_create(type); | ||
158 | if (!field) { | ||
159 | pr_err("failed to create a field %s\n", name); | ||
160 | return -1; | ||
161 | } | ||
162 | |||
163 | ret = string_set_value(field, string); | ||
164 | if (ret) { | ||
165 | pr_err("failed to set value %s\n", name); | ||
166 | goto err_put_field; | ||
167 | } | ||
168 | |||
169 | ret = bt_ctf_event_set_payload(event, name, field); | ||
170 | if (ret) | ||
171 | pr_err("failed to set payload %s\n", name); | ||
172 | |||
173 | err_put_field: | ||
174 | bt_ctf_field_put(field); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
143 | static struct bt_ctf_field_type* | 178 | static struct bt_ctf_field_type* |
144 | get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) | 179 | get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) |
145 | { | 180 | { |
@@ -731,6 +766,72 @@ static int process_sample_event(struct perf_tool *tool, | |||
731 | return cs ? 0 : -1; | 766 | return cs ? 0 : -1; |
732 | } | 767 | } |
733 | 768 | ||
769 | #define __NON_SAMPLE_SET_FIELD(_name, _type, _field) \ | ||
770 | do { \ | ||
771 | ret = value_set_##_type(cw, event, #_field, _event->_name._field);\ | ||
772 | if (ret) \ | ||
773 | return -1; \ | ||
774 | } while(0) | ||
775 | |||
776 | #define __FUNC_PROCESS_NON_SAMPLE(_name, body) \ | ||
777 | static int process_##_name##_event(struct perf_tool *tool, \ | ||
778 | union perf_event *_event, \ | ||
779 | struct perf_sample *sample, \ | ||
780 | struct machine *machine) \ | ||
781 | { \ | ||
782 | struct convert *c = container_of(tool, struct convert, tool);\ | ||
783 | struct ctf_writer *cw = &c->writer; \ | ||
784 | struct bt_ctf_event_class *event_class = cw->_name##_class;\ | ||
785 | struct bt_ctf_event *event; \ | ||
786 | struct ctf_stream *cs; \ | ||
787 | int ret; \ | ||
788 | \ | ||
789 | c->non_sample_count++; \ | ||
790 | c->events_size += _event->header.size; \ | ||
791 | event = bt_ctf_event_create(event_class); \ | ||
792 | if (!event) { \ | ||
793 | pr_err("Failed to create an CTF event\n"); \ | ||
794 | return -1; \ | ||
795 | } \ | ||
796 | \ | ||
797 | bt_ctf_clock_set_time(cw->clock, sample->time); \ | ||
798 | body \ | ||
799 | cs = ctf_stream(cw, 0); \ | ||
800 | if (cs) { \ | ||
801 | if (is_flush_needed(cs)) \ | ||
802 | ctf_stream__flush(cs); \ | ||
803 | \ | ||
804 | cs->count++; \ | ||
805 | bt_ctf_stream_append_event(cs->stream, event); \ | ||
806 | } \ | ||
807 | bt_ctf_event_put(event); \ | ||
808 | \ | ||
809 | return perf_event__process_##_name(tool, _event, sample, machine);\ | ||
810 | } | ||
811 | |||
812 | __FUNC_PROCESS_NON_SAMPLE(comm, | ||
813 | __NON_SAMPLE_SET_FIELD(comm, u32, pid); | ||
814 | __NON_SAMPLE_SET_FIELD(comm, u32, tid); | ||
815 | __NON_SAMPLE_SET_FIELD(comm, string, comm); | ||
816 | ) | ||
817 | __FUNC_PROCESS_NON_SAMPLE(fork, | ||
818 | __NON_SAMPLE_SET_FIELD(fork, u32, pid); | ||
819 | __NON_SAMPLE_SET_FIELD(fork, u32, ppid); | ||
820 | __NON_SAMPLE_SET_FIELD(fork, u32, tid); | ||
821 | __NON_SAMPLE_SET_FIELD(fork, u32, ptid); | ||
822 | __NON_SAMPLE_SET_FIELD(fork, u64, time); | ||
823 | ) | ||
824 | |||
825 | __FUNC_PROCESS_NON_SAMPLE(exit, | ||
826 | __NON_SAMPLE_SET_FIELD(fork, u32, pid); | ||
827 | __NON_SAMPLE_SET_FIELD(fork, u32, ppid); | ||
828 | __NON_SAMPLE_SET_FIELD(fork, u32, tid); | ||
829 | __NON_SAMPLE_SET_FIELD(fork, u32, ptid); | ||
830 | __NON_SAMPLE_SET_FIELD(fork, u64, time); | ||
831 | ) | ||
832 | #undef __NON_SAMPLE_SET_FIELD | ||
833 | #undef __FUNC_PROCESS_NON_SAMPLE | ||
834 | |||
734 | /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */ | 835 | /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */ |
735 | static char *change_name(char *name, char *orig_name, int dup) | 836 | static char *change_name(char *name, char *orig_name, int dup) |
736 | { | 837 | { |
@@ -997,7 +1098,7 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session) | |||
997 | struct perf_evsel *evsel; | 1098 | struct perf_evsel *evsel; |
998 | int ret; | 1099 | int ret; |
999 | 1100 | ||
1000 | evlist__for_each(evlist, evsel) { | 1101 | evlist__for_each_entry(evlist, evsel) { |
1001 | ret = add_event(cw, evsel); | 1102 | ret = add_event(cw, evsel); |
1002 | if (ret) | 1103 | if (ret) |
1003 | return ret; | 1104 | return ret; |
@@ -1005,12 +1106,86 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session) | |||
1005 | return 0; | 1106 | return 0; |
1006 | } | 1107 | } |
1007 | 1108 | ||
1109 | #define __NON_SAMPLE_ADD_FIELD(t, n) \ | ||
1110 | do { \ | ||
1111 | pr2(" field '%s'\n", #n); \ | ||
1112 | if (bt_ctf_event_class_add_field(event_class, cw->data.t, #n)) {\ | ||
1113 | pr_err("Failed to add field '%s';\n", #n);\ | ||
1114 | return -1; \ | ||
1115 | } \ | ||
1116 | } while(0) | ||
1117 | |||
1118 | #define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body) \ | ||
1119 | static int add_##_name##_event(struct ctf_writer *cw) \ | ||
1120 | { \ | ||
1121 | struct bt_ctf_event_class *event_class; \ | ||
1122 | int ret; \ | ||
1123 | \ | ||
1124 | pr("Adding "#_name" event\n"); \ | ||
1125 | event_class = bt_ctf_event_class_create("perf_" #_name);\ | ||
1126 | if (!event_class) \ | ||
1127 | return -1; \ | ||
1128 | body \ | ||
1129 | \ | ||
1130 | ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);\ | ||
1131 | if (ret) { \ | ||
1132 | pr("Failed to add event class '"#_name"' into stream.\n");\ | ||
1133 | return ret; \ | ||
1134 | } \ | ||
1135 | \ | ||
1136 | cw->_name##_class = event_class; \ | ||
1137 | bt_ctf_event_class_put(event_class); \ | ||
1138 | return 0; \ | ||
1139 | } | ||
1140 | |||
1141 | __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm, | ||
1142 | __NON_SAMPLE_ADD_FIELD(u32, pid); | ||
1143 | __NON_SAMPLE_ADD_FIELD(u32, tid); | ||
1144 | __NON_SAMPLE_ADD_FIELD(string, comm); | ||
1145 | ) | ||
1146 | |||
1147 | __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(fork, | ||
1148 | __NON_SAMPLE_ADD_FIELD(u32, pid); | ||
1149 | __NON_SAMPLE_ADD_FIELD(u32, ppid); | ||
1150 | __NON_SAMPLE_ADD_FIELD(u32, tid); | ||
1151 | __NON_SAMPLE_ADD_FIELD(u32, ptid); | ||
1152 | __NON_SAMPLE_ADD_FIELD(u64, time); | ||
1153 | ) | ||
1154 | |||
1155 | __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit, | ||
1156 | __NON_SAMPLE_ADD_FIELD(u32, pid); | ||
1157 | __NON_SAMPLE_ADD_FIELD(u32, ppid); | ||
1158 | __NON_SAMPLE_ADD_FIELD(u32, tid); | ||
1159 | __NON_SAMPLE_ADD_FIELD(u32, ptid); | ||
1160 | __NON_SAMPLE_ADD_FIELD(u64, time); | ||
1161 | ) | ||
1162 | |||
1163 | #undef __NON_SAMPLE_ADD_FIELD | ||
1164 | #undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS | ||
1165 | |||
1166 | static int setup_non_sample_events(struct ctf_writer *cw, | ||
1167 | struct perf_session *session __maybe_unused) | ||
1168 | { | ||
1169 | int ret; | ||
1170 | |||
1171 | ret = add_comm_event(cw); | ||
1172 | if (ret) | ||
1173 | return ret; | ||
1174 | ret = add_exit_event(cw); | ||
1175 | if (ret) | ||
1176 | return ret; | ||
1177 | ret = add_fork_event(cw); | ||
1178 | if (ret) | ||
1179 | return ret; | ||
1180 | return 0; | ||
1181 | } | ||
1182 | |||
1008 | static void cleanup_events(struct perf_session *session) | 1183 | static void cleanup_events(struct perf_session *session) |
1009 | { | 1184 | { |
1010 | struct perf_evlist *evlist = session->evlist; | 1185 | struct perf_evlist *evlist = session->evlist; |
1011 | struct perf_evsel *evsel; | 1186 | struct perf_evsel *evsel; |
1012 | 1187 | ||
1013 | evlist__for_each(evlist, evsel) { | 1188 | evlist__for_each_entry(evlist, evsel) { |
1014 | struct evsel_priv *priv; | 1189 | struct evsel_priv *priv; |
1015 | 1190 | ||
1016 | priv = evsel->priv; | 1191 | priv = evsel->priv; |
@@ -1273,13 +1448,14 @@ static int convert__config(const char *var, const char *value, void *cb) | |||
1273 | return 0; | 1448 | return 0; |
1274 | } | 1449 | } |
1275 | 1450 | ||
1276 | int bt_convert__perf2ctf(const char *input, const char *path, bool force) | 1451 | int bt_convert__perf2ctf(const char *input, const char *path, |
1452 | struct perf_data_convert_opts *opts) | ||
1277 | { | 1453 | { |
1278 | struct perf_session *session; | 1454 | struct perf_session *session; |
1279 | struct perf_data_file file = { | 1455 | struct perf_data_file file = { |
1280 | .path = input, | 1456 | .path = input, |
1281 | .mode = PERF_DATA_MODE_READ, | 1457 | .mode = PERF_DATA_MODE_READ, |
1282 | .force = force, | 1458 | .force = opts->force, |
1283 | }; | 1459 | }; |
1284 | struct convert c = { | 1460 | struct convert c = { |
1285 | .tool = { | 1461 | .tool = { |
@@ -1299,6 +1475,12 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force) | |||
1299 | struct ctf_writer *cw = &c.writer; | 1475 | struct ctf_writer *cw = &c.writer; |
1300 | int err = -1; | 1476 | int err = -1; |
1301 | 1477 | ||
1478 | if (opts->all) { | ||
1479 | c.tool.comm = process_comm_event; | ||
1480 | c.tool.exit = process_exit_event; | ||
1481 | c.tool.fork = process_fork_event; | ||
1482 | } | ||
1483 | |||
1302 | perf_config(convert__config, &c); | 1484 | perf_config(convert__config, &c); |
1303 | 1485 | ||
1304 | /* CTF writer */ | 1486 | /* CTF writer */ |
@@ -1323,6 +1505,9 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force) | |||
1323 | if (setup_events(cw, session)) | 1505 | if (setup_events(cw, session)) |
1324 | goto free_session; | 1506 | goto free_session; |
1325 | 1507 | ||
1508 | if (opts->all && setup_non_sample_events(cw, session)) | ||
1509 | goto free_session; | ||
1510 | |||
1326 | if (setup_streams(cw, session)) | 1511 | if (setup_streams(cw, session)) |
1327 | goto free_session; | 1512 | goto free_session; |
1328 | 1513 | ||
@@ -1337,10 +1522,15 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force) | |||
1337 | file.path, path); | 1522 | file.path, path); |
1338 | 1523 | ||
1339 | fprintf(stderr, | 1524 | fprintf(stderr, |
1340 | "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n", | 1525 | "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples", |
1341 | (double) c.events_size / 1024.0 / 1024.0, | 1526 | (double) c.events_size / 1024.0 / 1024.0, |
1342 | c.events_count); | 1527 | c.events_count); |
1343 | 1528 | ||
1529 | if (!c.non_sample_count) | ||
1530 | fprintf(stderr, ") ]\n"); | ||
1531 | else | ||
1532 | fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count); | ||
1533 | |||
1344 | cleanup_events(session); | 1534 | cleanup_events(session); |
1345 | perf_session__delete(session); | 1535 | perf_session__delete(session); |
1346 | ctf_writer__cleanup(cw); | 1536 | ctf_writer__cleanup(cw); |
diff --git a/tools/perf/util/data-convert-bt.h b/tools/perf/util/data-convert-bt.h index 4c204342a9d8..9a3b587f76c1 100644 --- a/tools/perf/util/data-convert-bt.h +++ b/tools/perf/util/data-convert-bt.h | |||
@@ -1,8 +1,10 @@ | |||
1 | #ifndef __DATA_CONVERT_BT_H | 1 | #ifndef __DATA_CONVERT_BT_H |
2 | #define __DATA_CONVERT_BT_H | 2 | #define __DATA_CONVERT_BT_H |
3 | #include "data-convert.h" | ||
3 | #ifdef HAVE_LIBBABELTRACE_SUPPORT | 4 | #ifdef HAVE_LIBBABELTRACE_SUPPORT |
4 | 5 | ||
5 | int bt_convert__perf2ctf(const char *input_name, const char *to_ctf, bool force); | 6 | int bt_convert__perf2ctf(const char *input_name, const char *to_ctf, |
7 | struct perf_data_convert_opts *opts); | ||
6 | 8 | ||
7 | #endif /* HAVE_LIBBABELTRACE_SUPPORT */ | 9 | #endif /* HAVE_LIBBABELTRACE_SUPPORT */ |
8 | #endif /* __DATA_CONVERT_BT_H */ | 10 | #endif /* __DATA_CONVERT_BT_H */ |
diff --git a/tools/perf/util/data-convert.h b/tools/perf/util/data-convert.h new file mode 100644 index 000000000000..5314962fe95b --- /dev/null +++ b/tools/perf/util/data-convert.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef __DATA_CONVERT_H | ||
2 | #define __DATA_CONVERT_H | ||
3 | |||
4 | struct perf_data_convert_opts { | ||
5 | bool force; | ||
6 | bool all; | ||
7 | }; | ||
8 | |||
9 | #endif /* __DATA_CONVERT_H */ | ||
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c index be83516155ee..60bfc9ca1e22 100644 --- a/tools/perf/util/data.c +++ b/tools/perf/util/data.c | |||
@@ -57,7 +57,7 @@ static int open_file_read(struct perf_data_file *file) | |||
57 | int err = errno; | 57 | int err = errno; |
58 | 58 | ||
59 | pr_err("failed to open %s: %s", file->path, | 59 | pr_err("failed to open %s: %s", file->path, |
60 | strerror_r(err, sbuf, sizeof(sbuf))); | 60 | str_error_r(err, sbuf, sizeof(sbuf))); |
61 | if (err == ENOENT && !strcmp(file->path, "perf.data")) | 61 | if (err == ENOENT && !strcmp(file->path, "perf.data")) |
62 | pr_err(" (try 'perf record' first)"); | 62 | pr_err(" (try 'perf record' first)"); |
63 | pr_err("\n"); | 63 | pr_err("\n"); |
@@ -99,7 +99,7 @@ static int open_file_write(struct perf_data_file *file) | |||
99 | 99 | ||
100 | if (fd < 0) | 100 | if (fd < 0) |
101 | pr_err("failed to open %s : %s\n", file->path, | 101 | pr_err("failed to open %s : %s\n", file->path, |
102 | strerror_r(errno, sbuf, sizeof(sbuf))); | 102 | str_error_r(errno, sbuf, sizeof(sbuf))); |
103 | 103 | ||
104 | return fd; | 104 | return fd; |
105 | } | 105 | } |
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index c9a6dc173e74..b0c2b5c5d337 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c | |||
@@ -233,17 +233,6 @@ int db_export__symbol(struct db_export *dbe, struct symbol *sym, | |||
233 | return 0; | 233 | return 0; |
234 | } | 234 | } |
235 | 235 | ||
236 | static struct thread *get_main_thread(struct machine *machine, struct thread *thread) | ||
237 | { | ||
238 | if (thread->pid_ == thread->tid) | ||
239 | return thread__get(thread); | ||
240 | |||
241 | if (thread->pid_ == -1) | ||
242 | return NULL; | ||
243 | |||
244 | return machine__find_thread(machine, thread->pid_, thread->pid_); | ||
245 | } | ||
246 | |||
247 | static int db_ids_from_al(struct db_export *dbe, struct addr_location *al, | 236 | static int db_ids_from_al(struct db_export *dbe, struct addr_location *al, |
248 | u64 *dso_db_id, u64 *sym_db_id, u64 *offset) | 237 | u64 *dso_db_id, u64 *sym_db_id, u64 *offset) |
249 | { | 238 | { |
@@ -382,7 +371,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event, | |||
382 | if (err) | 371 | if (err) |
383 | return err; | 372 | return err; |
384 | 373 | ||
385 | main_thread = get_main_thread(al->machine, thread); | 374 | main_thread = thread__main_thread(al->machine, thread); |
386 | if (main_thread) | 375 | if (main_thread) |
387 | comm = machine__thread_exec_comm(al->machine, main_thread); | 376 | comm = machine__thread_exec_comm(al->machine, main_thread); |
388 | 377 | ||
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 14bafda79eda..d242adc3d5a2 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h | |||
@@ -38,7 +38,7 @@ extern int debug_data_convert; | |||
38 | #define pr_oe_time(t, fmt, ...) pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__) | 38 | #define pr_oe_time(t, fmt, ...) pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__) |
39 | #define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__) | 39 | #define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__) |
40 | 40 | ||
41 | #define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */ | 41 | #define STRERR_BUFSIZE 128 /* For the buffer size of str_error_r */ |
42 | 42 | ||
43 | int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); | 43 | int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); |
44 | void trace_event(union perf_event *event); | 44 | void trace_event(union perf_event *event); |
diff --git a/tools/perf/util/demangle-rust.c b/tools/perf/util/demangle-rust.c new file mode 100644 index 000000000000..f9dafa888c06 --- /dev/null +++ b/tools/perf/util/demangle-rust.c | |||
@@ -0,0 +1,269 @@ | |||
1 | #include <string.h> | ||
2 | #include "util.h" | ||
3 | #include "debug.h" | ||
4 | |||
5 | #include "demangle-rust.h" | ||
6 | |||
7 | /* | ||
8 | * Mangled Rust symbols look like this: | ||
9 | * | ||
10 | * _$LT$std..sys..fd..FileDesc$u20$as$u20$core..ops..Drop$GT$::drop::hc68340e1baa4987a | ||
11 | * | ||
12 | * The original symbol is: | ||
13 | * | ||
14 | * <std::sys::fd::FileDesc as core::ops::Drop>::drop | ||
15 | * | ||
16 | * The last component of the path is a 64-bit hash in lowercase hex, prefixed | ||
17 | * with "h". Rust does not have a global namespace between crates, an illusion | ||
18 | * which Rust maintains by using the hash to distinguish things that would | ||
19 | * otherwise have the same symbol. | ||
20 | * | ||
21 | * Any path component not starting with a XID_Start character is prefixed with | ||
22 | * "_". | ||
23 | * | ||
24 | * The following escape sequences are used: | ||
25 | * | ||
26 | * "," => $C$ | ||
27 | * "@" => $SP$ | ||
28 | * "*" => $BP$ | ||
29 | * "&" => $RF$ | ||
30 | * "<" => $LT$ | ||
31 | * ">" => $GT$ | ||
32 | * "(" => $LP$ | ||
33 | * ")" => $RP$ | ||
34 | * " " => $u20$ | ||
35 | * "'" => $u27$ | ||
36 | * "[" => $u5b$ | ||
37 | * "]" => $u5d$ | ||
38 | * "~" => $u7e$ | ||
39 | * | ||
40 | * A double ".." means "::" and a single "." means "-". | ||
41 | * | ||
42 | * The only characters allowed in the mangled symbol are a-zA-Z0-9 and _.:$ | ||
43 | */ | ||
44 | |||
45 | static const char *hash_prefix = "::h"; | ||
46 | static const size_t hash_prefix_len = 3; | ||
47 | static const size_t hash_len = 16; | ||
48 | |||
49 | static bool is_prefixed_hash(const char *start); | ||
50 | static bool looks_like_rust(const char *sym, size_t len); | ||
51 | static bool unescape(const char **in, char **out, const char *seq, char value); | ||
52 | |||
53 | /* | ||
54 | * INPUT: | ||
55 | * sym: symbol that has been through BFD-demangling | ||
56 | * | ||
57 | * This function looks for the following indicators: | ||
58 | * | ||
59 | * 1. The hash must consist of "h" followed by 16 lowercase hex digits. | ||
60 | * | ||
61 | * 2. As a sanity check, the hash must use between 5 and 15 of the 16 possible | ||
62 | * hex digits. This is true of 99.9998% of hashes so once in your life you | ||
63 | * may see a false negative. The point is to notice path components that | ||
64 | * could be Rust hashes but are probably not, like "haaaaaaaaaaaaaaaa". In | ||
65 | * this case a false positive (non-Rust symbol has an important path | ||
66 | * component removed because it looks like a Rust hash) is worse than a | ||
67 | * false negative (the rare Rust symbol is not demangled) so this sets the | ||
68 | * balance in favor of false negatives. | ||
69 | * | ||
70 | * 3. There must be no characters other than a-zA-Z0-9 and _.:$ | ||
71 | * | ||
72 | * 4. There must be no unrecognized $-sign sequences. | ||
73 | * | ||
74 | * 5. There must be no sequence of three or more dots in a row ("..."). | ||
75 | */ | ||
76 | bool | ||
77 | rust_is_mangled(const char *sym) | ||
78 | { | ||
79 | size_t len, len_without_hash; | ||
80 | |||
81 | if (!sym) | ||
82 | return false; | ||
83 | |||
84 | len = strlen(sym); | ||
85 | if (len <= hash_prefix_len + hash_len) | ||
86 | /* Not long enough to contain "::h" + hash + something else */ | ||
87 | return false; | ||
88 | |||
89 | len_without_hash = len - (hash_prefix_len + hash_len); | ||
90 | if (!is_prefixed_hash(sym + len_without_hash)) | ||
91 | return false; | ||
92 | |||
93 | return looks_like_rust(sym, len_without_hash); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * A hash is the prefix "::h" followed by 16 lowercase hex digits. The hex | ||
98 | * digits must comprise between 5 and 15 (inclusive) distinct digits. | ||
99 | */ | ||
100 | static bool is_prefixed_hash(const char *str) | ||
101 | { | ||
102 | const char *end; | ||
103 | bool seen[16]; | ||
104 | size_t i; | ||
105 | int count; | ||
106 | |||
107 | if (strncmp(str, hash_prefix, hash_prefix_len)) | ||
108 | return false; | ||
109 | str += hash_prefix_len; | ||
110 | |||
111 | memset(seen, false, sizeof(seen)); | ||
112 | for (end = str + hash_len; str < end; str++) | ||
113 | if (*str >= '0' && *str <= '9') | ||
114 | seen[*str - '0'] = true; | ||
115 | else if (*str >= 'a' && *str <= 'f') | ||
116 | seen[*str - 'a' + 10] = true; | ||
117 | else | ||
118 | return false; | ||
119 | |||
120 | /* Count how many distinct digits seen */ | ||
121 | count = 0; | ||
122 | for (i = 0; i < 16; i++) | ||
123 | if (seen[i]) | ||
124 | count++; | ||
125 | |||
126 | return count >= 5 && count <= 15; | ||
127 | } | ||
128 | |||
129 | static bool looks_like_rust(const char *str, size_t len) | ||
130 | { | ||
131 | const char *end = str + len; | ||
132 | |||
133 | while (str < end) | ||
134 | switch (*str) { | ||
135 | case '$': | ||
136 | if (!strncmp(str, "$C$", 3)) | ||
137 | str += 3; | ||
138 | else if (!strncmp(str, "$SP$", 4) | ||
139 | || !strncmp(str, "$BP$", 4) | ||
140 | || !strncmp(str, "$RF$", 4) | ||
141 | || !strncmp(str, "$LT$", 4) | ||
142 | || !strncmp(str, "$GT$", 4) | ||
143 | || !strncmp(str, "$LP$", 4) | ||
144 | || !strncmp(str, "$RP$", 4)) | ||
145 | str += 4; | ||
146 | else if (!strncmp(str, "$u20$", 5) | ||
147 | || !strncmp(str, "$u27$", 5) | ||
148 | || !strncmp(str, "$u5b$", 5) | ||
149 | || !strncmp(str, "$u5d$", 5) | ||
150 | || !strncmp(str, "$u7e$", 5)) | ||
151 | str += 5; | ||
152 | else | ||
153 | return false; | ||
154 | break; | ||
155 | case '.': | ||
156 | /* Do not allow three or more consecutive dots */ | ||
157 | if (!strncmp(str, "...", 3)) | ||
158 | return false; | ||
159 | /* Fall through */ | ||
160 | case 'a' ... 'z': | ||
161 | case 'A' ... 'Z': | ||
162 | case '0' ... '9': | ||
163 | case '_': | ||
164 | case ':': | ||
165 | str++; | ||
166 | break; | ||
167 | default: | ||
168 | return false; | ||
169 | } | ||
170 | |||
171 | return true; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * INPUT: | ||
176 | * sym: symbol for which rust_is_mangled(sym) returns true | ||
177 | * | ||
178 | * The input is demangled in-place because the mangled name is always longer | ||
179 | * than the demangled one. | ||
180 | */ | ||
181 | void | ||
182 | rust_demangle_sym(char *sym) | ||
183 | { | ||
184 | const char *in; | ||
185 | char *out; | ||
186 | const char *end; | ||
187 | |||
188 | if (!sym) | ||
189 | return; | ||
190 | |||
191 | in = sym; | ||
192 | out = sym; | ||
193 | end = sym + strlen(sym) - (hash_prefix_len + hash_len); | ||
194 | |||
195 | while (in < end) | ||
196 | switch (*in) { | ||
197 | case '$': | ||
198 | if (!(unescape(&in, &out, "$C$", ',') | ||
199 | || unescape(&in, &out, "$SP$", '@') | ||
200 | || unescape(&in, &out, "$BP$", '*') | ||
201 | || unescape(&in, &out, "$RF$", '&') | ||
202 | || unescape(&in, &out, "$LT$", '<') | ||
203 | || unescape(&in, &out, "$GT$", '>') | ||
204 | || unescape(&in, &out, "$LP$", '(') | ||
205 | || unescape(&in, &out, "$RP$", ')') | ||
206 | || unescape(&in, &out, "$u20$", ' ') | ||
207 | || unescape(&in, &out, "$u27$", '\'') | ||
208 | || unescape(&in, &out, "$u5b$", '[') | ||
209 | || unescape(&in, &out, "$u5d$", ']') | ||
210 | || unescape(&in, &out, "$u7e$", '~'))) { | ||
211 | pr_err("demangle-rust: unexpected escape sequence"); | ||
212 | goto done; | ||
213 | } | ||
214 | break; | ||
215 | case '_': | ||
216 | /* | ||
217 | * If this is the start of a path component and the next | ||
218 | * character is an escape sequence, ignore the | ||
219 | * underscore. The mangler inserts an underscore to make | ||
220 | * sure the path component begins with a XID_Start | ||
221 | * character. | ||
222 | */ | ||
223 | if ((in == sym || in[-1] == ':') && in[1] == '$') | ||
224 | in++; | ||
225 | else | ||
226 | *out++ = *in++; | ||
227 | break; | ||
228 | case '.': | ||
229 | if (in[1] == '.') { | ||
230 | /* ".." becomes "::" */ | ||
231 | *out++ = ':'; | ||
232 | *out++ = ':'; | ||
233 | in += 2; | ||
234 | } else { | ||
235 | /* "." becomes "-" */ | ||
236 | *out++ = '-'; | ||
237 | in++; | ||
238 | } | ||
239 | break; | ||
240 | case 'a' ... 'z': | ||
241 | case 'A' ... 'Z': | ||
242 | case '0' ... '9': | ||
243 | case ':': | ||
244 | *out++ = *in++; | ||
245 | break; | ||
246 | default: | ||
247 | pr_err("demangle-rust: unexpected character '%c' in symbol\n", | ||
248 | *in); | ||
249 | goto done; | ||
250 | } | ||
251 | |||
252 | done: | ||
253 | *out = '\0'; | ||
254 | } | ||
255 | |||
256 | static bool unescape(const char **in, char **out, const char *seq, char value) | ||
257 | { | ||
258 | size_t len = strlen(seq); | ||
259 | |||
260 | if (strncmp(*in, seq, len)) | ||
261 | return false; | ||
262 | |||
263 | **out = value; | ||
264 | |||
265 | *in += len; | ||
266 | *out += 1; | ||
267 | |||
268 | return true; | ||
269 | } | ||
diff --git a/tools/perf/util/demangle-rust.h b/tools/perf/util/demangle-rust.h new file mode 100644 index 000000000000..7b41ead7e0dd --- /dev/null +++ b/tools/perf/util/demangle-rust.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __PERF_DEMANGLE_RUST | ||
2 | #define __PERF_DEMANGLE_RUST 1 | ||
3 | |||
4 | bool rust_is_mangled(const char *str); | ||
5 | void rust_demangle_sym(char *str); | ||
6 | |||
7 | #endif /* __PERF_DEMANGLE_RUST */ | ||
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 5d286f5d7906..774f6ec884d5 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
@@ -335,7 +335,7 @@ static int do_open(char *name) | |||
335 | return fd; | 335 | return fd; |
336 | 336 | ||
337 | pr_debug("dso open failed: %s\n", | 337 | pr_debug("dso open failed: %s\n", |
338 | strerror_r(errno, sbuf, sizeof(sbuf))); | 338 | str_error_r(errno, sbuf, sizeof(sbuf))); |
339 | if (!dso__data_open_cnt || errno != EMFILE) | 339 | if (!dso__data_open_cnt || errno != EMFILE) |
340 | break; | 340 | break; |
341 | 341 | ||
@@ -442,17 +442,27 @@ static rlim_t get_fd_limit(void) | |||
442 | return limit; | 442 | return limit; |
443 | } | 443 | } |
444 | 444 | ||
445 | static bool may_cache_fd(void) | 445 | static rlim_t fd_limit; |
446 | |||
447 | /* | ||
448 | * Used only by tests/dso-data.c to reset the environment | ||
449 | * for tests. I dont expect we should change this during | ||
450 | * standard runtime. | ||
451 | */ | ||
452 | void reset_fd_limit(void) | ||
446 | { | 453 | { |
447 | static rlim_t limit; | 454 | fd_limit = 0; |
455 | } | ||
448 | 456 | ||
449 | if (!limit) | 457 | static bool may_cache_fd(void) |
450 | limit = get_fd_limit(); | 458 | { |
459 | if (!fd_limit) | ||
460 | fd_limit = get_fd_limit(); | ||
451 | 461 | ||
452 | if (limit == RLIM_INFINITY) | 462 | if (fd_limit == RLIM_INFINITY) |
453 | return true; | 463 | return true; |
454 | 464 | ||
455 | return limit > (rlim_t) dso__data_open_cnt; | 465 | return fd_limit > (rlim_t) dso__data_open_cnt; |
456 | } | 466 | } |
457 | 467 | ||
458 | /* | 468 | /* |
@@ -776,7 +786,7 @@ static int data_file_size(struct dso *dso, struct machine *machine) | |||
776 | if (fstat(dso->data.fd, &st) < 0) { | 786 | if (fstat(dso->data.fd, &st) < 0) { |
777 | ret = -errno; | 787 | ret = -errno; |
778 | pr_err("dso cache fstat failed: %s\n", | 788 | pr_err("dso cache fstat failed: %s\n", |
779 | strerror_r(errno, sbuf, sizeof(sbuf))); | 789 | str_error_r(errno, sbuf, sizeof(sbuf))); |
780 | dso->data.status = DSO_DATA_STATUS_ERROR; | 790 | dso->data.status = DSO_DATA_STATUS_ERROR; |
781 | goto out; | 791 | goto out; |
782 | } | 792 | } |
@@ -1356,7 +1366,7 @@ int dso__strerror_load(struct dso *dso, char *buf, size_t buflen) | |||
1356 | BUG_ON(buflen == 0); | 1366 | BUG_ON(buflen == 0); |
1357 | 1367 | ||
1358 | if (errnum >= 0) { | 1368 | if (errnum >= 0) { |
1359 | const char *err = strerror_r(errnum, buf, buflen); | 1369 | const char *err = str_error_r(errnum, buf, buflen); |
1360 | 1370 | ||
1361 | if (err != buf) | 1371 | if (err != buf) |
1362 | scnprintf(buf, buflen, "%s", err); | 1372 | scnprintf(buf, buflen, "%s", err); |
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 0953280629cf..ecc4bbd3f82e 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/atomic.h> | 4 | #include <linux/atomic.h> |
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <linux/rbtree.h> | 6 | #include <linux/rbtree.h> |
7 | #include <sys/types.h> | ||
7 | #include <stdbool.h> | 8 | #include <stdbool.h> |
8 | #include <pthread.h> | 9 | #include <pthread.h> |
9 | #include <linux/types.h> | 10 | #include <linux/types.h> |
@@ -349,10 +350,17 @@ static inline bool dso__is_kcore(struct dso *dso) | |||
349 | dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE; | 350 | dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE; |
350 | } | 351 | } |
351 | 352 | ||
353 | static inline bool dso__is_kallsyms(struct dso *dso) | ||
354 | { | ||
355 | return dso->kernel && dso->long_name[0] != '/'; | ||
356 | } | ||
357 | |||
352 | void dso__free_a2l(struct dso *dso); | 358 | void dso__free_a2l(struct dso *dso); |
353 | 359 | ||
354 | enum dso_type dso__type(struct dso *dso, struct machine *machine); | 360 | enum dso_type dso__type(struct dso *dso, struct machine *machine); |
355 | 361 | ||
356 | int dso__strerror_load(struct dso *dso, char *buf, size_t buflen); | 362 | int dso__strerror_load(struct dso *dso, char *buf, size_t buflen); |
357 | 363 | ||
364 | void reset_fd_limit(void); | ||
365 | |||
358 | #endif /* __PERF_DSO */ | 366 | #endif /* __PERF_DSO */ |
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c index 49a11d9d8b8f..bb964e86b09d 100644 --- a/tools/perf/util/env.c +++ b/tools/perf/util/env.c | |||
@@ -18,10 +18,13 @@ void perf_env__exit(struct perf_env *env) | |||
18 | zfree(&env->cmdline_argv); | 18 | zfree(&env->cmdline_argv); |
19 | zfree(&env->sibling_cores); | 19 | zfree(&env->sibling_cores); |
20 | zfree(&env->sibling_threads); | 20 | zfree(&env->sibling_threads); |
21 | zfree(&env->numa_nodes); | ||
22 | zfree(&env->pmu_mappings); | 21 | zfree(&env->pmu_mappings); |
23 | zfree(&env->cpu); | 22 | zfree(&env->cpu); |
24 | 23 | ||
24 | for (i = 0; i < env->nr_numa_nodes; i++) | ||
25 | cpu_map__put(env->numa_nodes[i].map); | ||
26 | zfree(&env->numa_nodes); | ||
27 | |||
25 | for (i = 0; i < env->caches_cnt; i++) | 28 | for (i = 0; i < env->caches_cnt; i++) |
26 | cpu_cache_level__free(&env->caches[i]); | 29 | cpu_cache_level__free(&env->caches[i]); |
27 | zfree(&env->caches); | 30 | zfree(&env->caches); |
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h index 56cffb60a0b4..b164dfd2dcbf 100644 --- a/tools/perf/util/env.h +++ b/tools/perf/util/env.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __PERF_ENV_H | 2 | #define __PERF_ENV_H |
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include "cpumap.h" | ||
5 | 6 | ||
6 | struct cpu_topology_map { | 7 | struct cpu_topology_map { |
7 | int socket_id; | 8 | int socket_id; |
@@ -18,6 +19,13 @@ struct cpu_cache_level { | |||
18 | char *map; | 19 | char *map; |
19 | }; | 20 | }; |
20 | 21 | ||
22 | struct numa_node { | ||
23 | u32 node; | ||
24 | u64 mem_total; | ||
25 | u64 mem_free; | ||
26 | struct cpu_map *map; | ||
27 | }; | ||
28 | |||
21 | struct perf_env { | 29 | struct perf_env { |
22 | char *hostname; | 30 | char *hostname; |
23 | char *os_release; | 31 | char *os_release; |
@@ -40,11 +48,11 @@ struct perf_env { | |||
40 | const char **cmdline_argv; | 48 | const char **cmdline_argv; |
41 | char *sibling_cores; | 49 | char *sibling_cores; |
42 | char *sibling_threads; | 50 | char *sibling_threads; |
43 | char *numa_nodes; | ||
44 | char *pmu_mappings; | 51 | char *pmu_mappings; |
45 | struct cpu_topology_map *cpu; | 52 | struct cpu_topology_map *cpu; |
46 | struct cpu_cache_level *caches; | 53 | struct cpu_cache_level *caches; |
47 | int caches_cnt; | 54 | int caches_cnt; |
55 | struct numa_node *numa_nodes; | ||
48 | }; | 56 | }; |
49 | 57 | ||
50 | extern struct perf_env perf_env; | 58 | extern struct perf_env perf_env; |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 9b141f12329e..e20438b784be 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -1092,7 +1092,7 @@ size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp) | |||
1092 | struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data); | 1092 | struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data); |
1093 | size_t ret; | 1093 | size_t ret; |
1094 | 1094 | ||
1095 | ret = fprintf(fp, " nr: "); | 1095 | ret = fprintf(fp, ": "); |
1096 | 1096 | ||
1097 | if (cpus) | 1097 | if (cpus) |
1098 | ret += cpu_map__fprintf(cpus, fp); | 1098 | ret += cpu_map__fprintf(cpus, fp); |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index e82ba90cc969..097b3ed77fdd 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "evlist.h" | 15 | #include "evlist.h" |
16 | #include "evsel.h" | 16 | #include "evsel.h" |
17 | #include "debug.h" | 17 | #include "debug.h" |
18 | #include "asm/bug.h" | ||
18 | #include <unistd.h> | 19 | #include <unistd.h> |
19 | 20 | ||
20 | #include "parse-events.h" | 21 | #include "parse-events.h" |
@@ -27,8 +28,8 @@ | |||
27 | #include <linux/log2.h> | 28 | #include <linux/log2.h> |
28 | #include <linux/err.h> | 29 | #include <linux/err.h> |
29 | 30 | ||
30 | static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); | 31 | static void perf_mmap__munmap(struct perf_mmap *map); |
31 | static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); | 32 | static void perf_mmap__put(struct perf_mmap *map); |
32 | 33 | ||
33 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 34 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
34 | #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) | 35 | #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) |
@@ -44,7 +45,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, | |||
44 | perf_evlist__set_maps(evlist, cpus, threads); | 45 | perf_evlist__set_maps(evlist, cpus, threads); |
45 | fdarray__init(&evlist->pollfd, 64); | 46 | fdarray__init(&evlist->pollfd, 64); |
46 | evlist->workload.pid = -1; | 47 | evlist->workload.pid = -1; |
47 | evlist->backward = false; | 48 | evlist->bkw_mmap_state = BKW_MMAP_NOTREADY; |
48 | } | 49 | } |
49 | 50 | ||
50 | struct perf_evlist *perf_evlist__new(void) | 51 | struct perf_evlist *perf_evlist__new(void) |
@@ -100,7 +101,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist) | |||
100 | { | 101 | { |
101 | struct perf_evsel *evsel; | 102 | struct perf_evsel *evsel; |
102 | 103 | ||
103 | evlist__for_each(evlist, evsel) | 104 | evlist__for_each_entry(evlist, evsel) |
104 | perf_evsel__calc_id_pos(evsel); | 105 | perf_evsel__calc_id_pos(evsel); |
105 | 106 | ||
106 | perf_evlist__set_id_pos(evlist); | 107 | perf_evlist__set_id_pos(evlist); |
@@ -110,7 +111,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist) | |||
110 | { | 111 | { |
111 | struct perf_evsel *pos, *n; | 112 | struct perf_evsel *pos, *n; |
112 | 113 | ||
113 | evlist__for_each_safe(evlist, n, pos) { | 114 | evlist__for_each_entry_safe(evlist, n, pos) { |
114 | list_del_init(&pos->node); | 115 | list_del_init(&pos->node); |
115 | pos->evlist = NULL; | 116 | pos->evlist = NULL; |
116 | perf_evsel__delete(pos); | 117 | perf_evsel__delete(pos); |
@@ -122,11 +123,15 @@ static void perf_evlist__purge(struct perf_evlist *evlist) | |||
122 | void perf_evlist__exit(struct perf_evlist *evlist) | 123 | void perf_evlist__exit(struct perf_evlist *evlist) |
123 | { | 124 | { |
124 | zfree(&evlist->mmap); | 125 | zfree(&evlist->mmap); |
126 | zfree(&evlist->backward_mmap); | ||
125 | fdarray__exit(&evlist->pollfd); | 127 | fdarray__exit(&evlist->pollfd); |
126 | } | 128 | } |
127 | 129 | ||
128 | void perf_evlist__delete(struct perf_evlist *evlist) | 130 | void perf_evlist__delete(struct perf_evlist *evlist) |
129 | { | 131 | { |
132 | if (evlist == NULL) | ||
133 | return; | ||
134 | |||
130 | perf_evlist__munmap(evlist); | 135 | perf_evlist__munmap(evlist); |
131 | perf_evlist__close(evlist); | 136 | perf_evlist__close(evlist); |
132 | cpu_map__put(evlist->cpus); | 137 | cpu_map__put(evlist->cpus); |
@@ -161,7 +166,7 @@ static void perf_evlist__propagate_maps(struct perf_evlist *evlist) | |||
161 | { | 166 | { |
162 | struct perf_evsel *evsel; | 167 | struct perf_evsel *evsel; |
163 | 168 | ||
164 | evlist__for_each(evlist, evsel) | 169 | evlist__for_each_entry(evlist, evsel) |
165 | __perf_evlist__propagate_maps(evlist, evsel); | 170 | __perf_evlist__propagate_maps(evlist, evsel); |
166 | } | 171 | } |
167 | 172 | ||
@@ -190,7 +195,7 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist, | |||
190 | { | 195 | { |
191 | struct perf_evsel *evsel, *temp; | 196 | struct perf_evsel *evsel, *temp; |
192 | 197 | ||
193 | __evlist__for_each_safe(list, temp, evsel) { | 198 | __evlist__for_each_entry_safe(list, temp, evsel) { |
194 | list_del_init(&evsel->node); | 199 | list_del_init(&evsel->node); |
195 | perf_evlist__add(evlist, evsel); | 200 | perf_evlist__add(evlist, evsel); |
196 | } | 201 | } |
@@ -205,7 +210,7 @@ void __perf_evlist__set_leader(struct list_head *list) | |||
205 | 210 | ||
206 | leader->nr_members = evsel->idx - leader->idx + 1; | 211 | leader->nr_members = evsel->idx - leader->idx + 1; |
207 | 212 | ||
208 | __evlist__for_each(list, evsel) { | 213 | __evlist__for_each_entry(list, evsel) { |
209 | evsel->leader = leader; | 214 | evsel->leader = leader; |
210 | } | 215 | } |
211 | } | 216 | } |
@@ -234,31 +239,13 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr) | |||
234 | 239 | ||
235 | int perf_evlist__add_default(struct perf_evlist *evlist) | 240 | int perf_evlist__add_default(struct perf_evlist *evlist) |
236 | { | 241 | { |
237 | struct perf_event_attr attr = { | 242 | struct perf_evsel *evsel = perf_evsel__new_cycles(); |
238 | .type = PERF_TYPE_HARDWARE, | ||
239 | .config = PERF_COUNT_HW_CPU_CYCLES, | ||
240 | }; | ||
241 | struct perf_evsel *evsel; | ||
242 | |||
243 | event_attr_init(&attr); | ||
244 | 243 | ||
245 | perf_event_attr__set_max_precise_ip(&attr); | ||
246 | |||
247 | evsel = perf_evsel__new(&attr); | ||
248 | if (evsel == NULL) | 244 | if (evsel == NULL) |
249 | goto error; | 245 | return -ENOMEM; |
250 | |||
251 | /* use asprintf() because free(evsel) assumes name is allocated */ | ||
252 | if (asprintf(&evsel->name, "cycles%.*s", | ||
253 | attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0) | ||
254 | goto error_free; | ||
255 | 246 | ||
256 | perf_evlist__add(evlist, evsel); | 247 | perf_evlist__add(evlist, evsel); |
257 | return 0; | 248 | return 0; |
258 | error_free: | ||
259 | perf_evsel__delete(evsel); | ||
260 | error: | ||
261 | return -ENOMEM; | ||
262 | } | 249 | } |
263 | 250 | ||
264 | int perf_evlist__add_dummy(struct perf_evlist *evlist) | 251 | int perf_evlist__add_dummy(struct perf_evlist *evlist) |
@@ -296,7 +283,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist, | |||
296 | return 0; | 283 | return 0; |
297 | 284 | ||
298 | out_delete_partial_list: | 285 | out_delete_partial_list: |
299 | __evlist__for_each_safe(&head, n, evsel) | 286 | __evlist__for_each_entry_safe(&head, n, evsel) |
300 | perf_evsel__delete(evsel); | 287 | perf_evsel__delete(evsel); |
301 | return -1; | 288 | return -1; |
302 | } | 289 | } |
@@ -317,7 +304,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) | |||
317 | { | 304 | { |
318 | struct perf_evsel *evsel; | 305 | struct perf_evsel *evsel; |
319 | 306 | ||
320 | evlist__for_each(evlist, evsel) { | 307 | evlist__for_each_entry(evlist, evsel) { |
321 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT && | 308 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT && |
322 | (int)evsel->attr.config == id) | 309 | (int)evsel->attr.config == id) |
323 | return evsel; | 310 | return evsel; |
@@ -332,7 +319,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, | |||
332 | { | 319 | { |
333 | struct perf_evsel *evsel; | 320 | struct perf_evsel *evsel; |
334 | 321 | ||
335 | evlist__for_each(evlist, evsel) { | 322 | evlist__for_each_entry(evlist, evsel) { |
336 | if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && | 323 | if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && |
337 | (strcmp(evsel->name, name) == 0)) | 324 | (strcmp(evsel->name, name) == 0)) |
338 | return evsel; | 325 | return evsel; |
@@ -367,7 +354,7 @@ void perf_evlist__disable(struct perf_evlist *evlist) | |||
367 | { | 354 | { |
368 | struct perf_evsel *pos; | 355 | struct perf_evsel *pos; |
369 | 356 | ||
370 | evlist__for_each(evlist, pos) { | 357 | evlist__for_each_entry(evlist, pos) { |
371 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 358 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
372 | continue; | 359 | continue; |
373 | perf_evsel__disable(pos); | 360 | perf_evsel__disable(pos); |
@@ -380,7 +367,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) | |||
380 | { | 367 | { |
381 | struct perf_evsel *pos; | 368 | struct perf_evsel *pos; |
382 | 369 | ||
383 | evlist__for_each(evlist, pos) { | 370 | evlist__for_each_entry(evlist, pos) { |
384 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 371 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
385 | continue; | 372 | continue; |
386 | perf_evsel__enable(pos); | 373 | perf_evsel__enable(pos); |
@@ -448,7 +435,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) | |||
448 | int nfds = 0; | 435 | int nfds = 0; |
449 | struct perf_evsel *evsel; | 436 | struct perf_evsel *evsel; |
450 | 437 | ||
451 | evlist__for_each(evlist, evsel) { | 438 | evlist__for_each_entry(evlist, evsel) { |
452 | if (evsel->system_wide) | 439 | if (evsel->system_wide) |
453 | nfds += nr_cpus; | 440 | nfds += nr_cpus; |
454 | else | 441 | else |
@@ -462,15 +449,16 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) | |||
462 | return 0; | 449 | return 0; |
463 | } | 450 | } |
464 | 451 | ||
465 | static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx) | 452 | static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, |
453 | struct perf_mmap *map, short revent) | ||
466 | { | 454 | { |
467 | int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP); | 455 | int pos = fdarray__add(&evlist->pollfd, fd, revent | POLLERR | POLLHUP); |
468 | /* | 456 | /* |
469 | * Save the idx so that when we filter out fds POLLHUP'ed we can | 457 | * Save the idx so that when we filter out fds POLLHUP'ed we can |
470 | * close the associated evlist->mmap[] entry. | 458 | * close the associated evlist->mmap[] entry. |
471 | */ | 459 | */ |
472 | if (pos >= 0) { | 460 | if (pos >= 0) { |
473 | evlist->pollfd.priv[pos].idx = idx; | 461 | evlist->pollfd.priv[pos].ptr = map; |
474 | 462 | ||
475 | fcntl(fd, F_SETFL, O_NONBLOCK); | 463 | fcntl(fd, F_SETFL, O_NONBLOCK); |
476 | } | 464 | } |
@@ -480,20 +468,22 @@ static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx | |||
480 | 468 | ||
481 | int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) | 469 | int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) |
482 | { | 470 | { |
483 | return __perf_evlist__add_pollfd(evlist, fd, -1); | 471 | return __perf_evlist__add_pollfd(evlist, fd, NULL, POLLIN); |
484 | } | 472 | } |
485 | 473 | ||
486 | static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd) | 474 | static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd, |
475 | void *arg __maybe_unused) | ||
487 | { | 476 | { |
488 | struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd); | 477 | struct perf_mmap *map = fda->priv[fd].ptr; |
489 | 478 | ||
490 | perf_evlist__mmap_put(evlist, fda->priv[fd].idx); | 479 | if (map) |
480 | perf_mmap__put(map); | ||
491 | } | 481 | } |
492 | 482 | ||
493 | int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) | 483 | int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) |
494 | { | 484 | { |
495 | return fdarray__filter(&evlist->pollfd, revents_and_mask, | 485 | return fdarray__filter(&evlist->pollfd, revents_and_mask, |
496 | perf_evlist__munmap_filtered); | 486 | perf_evlist__munmap_filtered, NULL); |
497 | } | 487 | } |
498 | 488 | ||
499 | int perf_evlist__poll(struct perf_evlist *evlist, int timeout) | 489 | int perf_evlist__poll(struct perf_evlist *evlist, int timeout) |
@@ -647,8 +637,8 @@ static int perf_evlist__event2id(struct perf_evlist *evlist, | |||
647 | return 0; | 637 | return 0; |
648 | } | 638 | } |
649 | 639 | ||
650 | static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, | 640 | struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, |
651 | union perf_event *event) | 641 | union perf_event *event) |
652 | { | 642 | { |
653 | struct perf_evsel *first = perf_evlist__first(evlist); | 643 | struct perf_evsel *first = perf_evlist__first(evlist); |
654 | struct hlist_head *head; | 644 | struct hlist_head *head; |
@@ -684,8 +674,11 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value) | |||
684 | { | 674 | { |
685 | int i; | 675 | int i; |
686 | 676 | ||
677 | if (!evlist->backward_mmap) | ||
678 | return 0; | ||
679 | |||
687 | for (i = 0; i < evlist->nr_mmaps; i++) { | 680 | for (i = 0; i < evlist->nr_mmaps; i++) { |
688 | int fd = evlist->mmap[i].fd; | 681 | int fd = evlist->backward_mmap[i].fd; |
689 | int err; | 682 | int err; |
690 | 683 | ||
691 | if (fd < 0) | 684 | if (fd < 0) |
@@ -697,12 +690,12 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value) | |||
697 | return 0; | 690 | return 0; |
698 | } | 691 | } |
699 | 692 | ||
700 | int perf_evlist__pause(struct perf_evlist *evlist) | 693 | static int perf_evlist__pause(struct perf_evlist *evlist) |
701 | { | 694 | { |
702 | return perf_evlist__set_paused(evlist, true); | 695 | return perf_evlist__set_paused(evlist, true); |
703 | } | 696 | } |
704 | 697 | ||
705 | int perf_evlist__resume(struct perf_evlist *evlist) | 698 | static int perf_evlist__resume(struct perf_evlist *evlist) |
706 | { | 699 | { |
707 | return perf_evlist__set_paused(evlist, false); | 700 | return perf_evlist__set_paused(evlist, false); |
708 | } | 701 | } |
@@ -777,9 +770,8 @@ broken_event: | |||
777 | return event; | 770 | return event; |
778 | } | 771 | } |
779 | 772 | ||
780 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | 773 | union perf_event *perf_mmap__read_forward(struct perf_mmap *md, bool check_messup) |
781 | { | 774 | { |
782 | struct perf_mmap *md = &evlist->mmap[idx]; | ||
783 | u64 head; | 775 | u64 head; |
784 | u64 old = md->prev; | 776 | u64 old = md->prev; |
785 | 777 | ||
@@ -791,13 +783,12 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | |||
791 | 783 | ||
792 | head = perf_mmap__read_head(md); | 784 | head = perf_mmap__read_head(md); |
793 | 785 | ||
794 | return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev); | 786 | return perf_mmap__read(md, check_messup, old, head, &md->prev); |
795 | } | 787 | } |
796 | 788 | ||
797 | union perf_event * | 789 | union perf_event * |
798 | perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx) | 790 | perf_mmap__read_backward(struct perf_mmap *md) |
799 | { | 791 | { |
800 | struct perf_mmap *md = &evlist->mmap[idx]; | ||
801 | u64 head, end; | 792 | u64 head, end; |
802 | u64 start = md->prev; | 793 | u64 start = md->prev; |
803 | 794 | ||
@@ -832,9 +823,38 @@ perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx) | |||
832 | return perf_mmap__read(md, false, start, end, &md->prev); | 823 | return perf_mmap__read(md, false, start, end, &md->prev); |
833 | } | 824 | } |
834 | 825 | ||
835 | void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) | 826 | union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx) |
827 | { | ||
828 | struct perf_mmap *md = &evlist->mmap[idx]; | ||
829 | |||
830 | /* | ||
831 | * Check messup is required for forward overwritable ring buffer: | ||
832 | * memory pointed by md->prev can be overwritten in this case. | ||
833 | * No need for read-write ring buffer: kernel stop outputting when | ||
834 | * it hit md->prev (perf_mmap__consume()). | ||
835 | */ | ||
836 | return perf_mmap__read_forward(md, evlist->overwrite); | ||
837 | } | ||
838 | |||
839 | union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx) | ||
836 | { | 840 | { |
837 | struct perf_mmap *md = &evlist->mmap[idx]; | 841 | struct perf_mmap *md = &evlist->mmap[idx]; |
842 | |||
843 | /* | ||
844 | * No need to check messup for backward ring buffer: | ||
845 | * We can always read arbitrary long data from a backward | ||
846 | * ring buffer unless we forget to pause it before reading. | ||
847 | */ | ||
848 | return perf_mmap__read_backward(md); | ||
849 | } | ||
850 | |||
851 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | ||
852 | { | ||
853 | return perf_evlist__mmap_read_forward(evlist, idx); | ||
854 | } | ||
855 | |||
856 | void perf_mmap__read_catchup(struct perf_mmap *md) | ||
857 | { | ||
838 | u64 head; | 858 | u64 head; |
839 | 859 | ||
840 | if (!atomic_read(&md->refcnt)) | 860 | if (!atomic_read(&md->refcnt)) |
@@ -844,36 +864,44 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) | |||
844 | md->prev = head; | 864 | md->prev = head; |
845 | } | 865 | } |
846 | 866 | ||
867 | void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) | ||
868 | { | ||
869 | perf_mmap__read_catchup(&evlist->mmap[idx]); | ||
870 | } | ||
871 | |||
847 | static bool perf_mmap__empty(struct perf_mmap *md) | 872 | static bool perf_mmap__empty(struct perf_mmap *md) |
848 | { | 873 | { |
849 | return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; | 874 | return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; |
850 | } | 875 | } |
851 | 876 | ||
852 | static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) | 877 | static void perf_mmap__get(struct perf_mmap *map) |
853 | { | 878 | { |
854 | atomic_inc(&evlist->mmap[idx].refcnt); | 879 | atomic_inc(&map->refcnt); |
855 | } | 880 | } |
856 | 881 | ||
857 | static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx) | 882 | static void perf_mmap__put(struct perf_mmap *md) |
858 | { | 883 | { |
859 | BUG_ON(atomic_read(&evlist->mmap[idx].refcnt) == 0); | 884 | BUG_ON(md->base && atomic_read(&md->refcnt) == 0); |
860 | 885 | ||
861 | if (atomic_dec_and_test(&evlist->mmap[idx].refcnt)) | 886 | if (atomic_dec_and_test(&md->refcnt)) |
862 | __perf_evlist__munmap(evlist, idx); | 887 | perf_mmap__munmap(md); |
863 | } | 888 | } |
864 | 889 | ||
865 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) | 890 | void perf_mmap__consume(struct perf_mmap *md, bool overwrite) |
866 | { | 891 | { |
867 | struct perf_mmap *md = &evlist->mmap[idx]; | 892 | if (!overwrite) { |
868 | |||
869 | if (!evlist->overwrite) { | ||
870 | u64 old = md->prev; | 893 | u64 old = md->prev; |
871 | 894 | ||
872 | perf_mmap__write_tail(md, old); | 895 | perf_mmap__write_tail(md, old); |
873 | } | 896 | } |
874 | 897 | ||
875 | if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md)) | 898 | if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md)) |
876 | perf_evlist__mmap_put(evlist, idx); | 899 | perf_mmap__put(md); |
900 | } | ||
901 | |||
902 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) | ||
903 | { | ||
904 | perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite); | ||
877 | } | 905 | } |
878 | 906 | ||
879 | int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused, | 907 | int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused, |
@@ -904,41 +932,52 @@ void __weak auxtrace_mmap_params__set_idx( | |||
904 | { | 932 | { |
905 | } | 933 | } |
906 | 934 | ||
907 | static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) | 935 | static void perf_mmap__munmap(struct perf_mmap *map) |
908 | { | 936 | { |
909 | if (evlist->mmap[idx].base != NULL) { | 937 | if (map->base != NULL) { |
910 | munmap(evlist->mmap[idx].base, evlist->mmap_len); | 938 | munmap(map->base, perf_mmap__mmap_len(map)); |
911 | evlist->mmap[idx].base = NULL; | 939 | map->base = NULL; |
912 | evlist->mmap[idx].fd = -1; | 940 | map->fd = -1; |
913 | atomic_set(&evlist->mmap[idx].refcnt, 0); | 941 | atomic_set(&map->refcnt, 0); |
914 | } | 942 | } |
915 | auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); | 943 | auxtrace_mmap__munmap(&map->auxtrace_mmap); |
916 | } | 944 | } |
917 | 945 | ||
918 | void perf_evlist__munmap(struct perf_evlist *evlist) | 946 | static void perf_evlist__munmap_nofree(struct perf_evlist *evlist) |
919 | { | 947 | { |
920 | int i; | 948 | int i; |
921 | 949 | ||
922 | if (evlist->mmap == NULL) | 950 | if (evlist->mmap) |
923 | return; | 951 | for (i = 0; i < evlist->nr_mmaps; i++) |
952 | perf_mmap__munmap(&evlist->mmap[i]); | ||
924 | 953 | ||
925 | for (i = 0; i < evlist->nr_mmaps; i++) | 954 | if (evlist->backward_mmap) |
926 | __perf_evlist__munmap(evlist, i); | 955 | for (i = 0; i < evlist->nr_mmaps; i++) |
956 | perf_mmap__munmap(&evlist->backward_mmap[i]); | ||
957 | } | ||
927 | 958 | ||
959 | void perf_evlist__munmap(struct perf_evlist *evlist) | ||
960 | { | ||
961 | perf_evlist__munmap_nofree(evlist); | ||
928 | zfree(&evlist->mmap); | 962 | zfree(&evlist->mmap); |
963 | zfree(&evlist->backward_mmap); | ||
929 | } | 964 | } |
930 | 965 | ||
931 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | 966 | static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist) |
932 | { | 967 | { |
933 | int i; | 968 | int i; |
969 | struct perf_mmap *map; | ||
934 | 970 | ||
935 | evlist->nr_mmaps = cpu_map__nr(evlist->cpus); | 971 | evlist->nr_mmaps = cpu_map__nr(evlist->cpus); |
936 | if (cpu_map__empty(evlist->cpus)) | 972 | if (cpu_map__empty(evlist->cpus)) |
937 | evlist->nr_mmaps = thread_map__nr(evlist->threads); | 973 | evlist->nr_mmaps = thread_map__nr(evlist->threads); |
938 | evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); | 974 | map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); |
975 | if (!map) | ||
976 | return NULL; | ||
977 | |||
939 | for (i = 0; i < evlist->nr_mmaps; i++) | 978 | for (i = 0; i < evlist->nr_mmaps; i++) |
940 | evlist->mmap[i].fd = -1; | 979 | map[i].fd = -1; |
941 | return evlist->mmap != NULL ? 0 : -ENOMEM; | 980 | return map; |
942 | } | 981 | } |
943 | 982 | ||
944 | struct mmap_params { | 983 | struct mmap_params { |
@@ -947,8 +986,8 @@ struct mmap_params { | |||
947 | struct auxtrace_mmap_params auxtrace_mp; | 986 | struct auxtrace_mmap_params auxtrace_mp; |
948 | }; | 987 | }; |
949 | 988 | ||
950 | static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, | 989 | static int perf_mmap__mmap(struct perf_mmap *map, |
951 | struct mmap_params *mp, int fd) | 990 | struct mmap_params *mp, int fd) |
952 | { | 991 | { |
953 | /* | 992 | /* |
954 | * The last one will be done at perf_evlist__mmap_consume(), so that we | 993 | * The last one will be done at perf_evlist__mmap_consume(), so that we |
@@ -963,35 +1002,61 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, | |||
963 | * evlist layer can't just drop it when filtering events in | 1002 | * evlist layer can't just drop it when filtering events in |
964 | * perf_evlist__filter_pollfd(). | 1003 | * perf_evlist__filter_pollfd(). |
965 | */ | 1004 | */ |
966 | atomic_set(&evlist->mmap[idx].refcnt, 2); | 1005 | atomic_set(&map->refcnt, 2); |
967 | evlist->mmap[idx].prev = 0; | 1006 | map->prev = 0; |
968 | evlist->mmap[idx].mask = mp->mask; | 1007 | map->mask = mp->mask; |
969 | evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, | 1008 | map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot, |
970 | MAP_SHARED, fd, 0); | 1009 | MAP_SHARED, fd, 0); |
971 | if (evlist->mmap[idx].base == MAP_FAILED) { | 1010 | if (map->base == MAP_FAILED) { |
972 | pr_debug2("failed to mmap perf event ring buffer, error %d\n", | 1011 | pr_debug2("failed to mmap perf event ring buffer, error %d\n", |
973 | errno); | 1012 | errno); |
974 | evlist->mmap[idx].base = NULL; | 1013 | map->base = NULL; |
975 | return -1; | 1014 | return -1; |
976 | } | 1015 | } |
977 | evlist->mmap[idx].fd = fd; | 1016 | map->fd = fd; |
978 | 1017 | ||
979 | if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, | 1018 | if (auxtrace_mmap__mmap(&map->auxtrace_mmap, |
980 | &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) | 1019 | &mp->auxtrace_mp, map->base, fd)) |
981 | return -1; | 1020 | return -1; |
982 | 1021 | ||
983 | return 0; | 1022 | return 0; |
984 | } | 1023 | } |
985 | 1024 | ||
1025 | static bool | ||
1026 | perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused, | ||
1027 | struct perf_evsel *evsel) | ||
1028 | { | ||
1029 | if (evsel->attr.write_backward) | ||
1030 | return false; | ||
1031 | return true; | ||
1032 | } | ||
1033 | |||
986 | static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | 1034 | static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, |
987 | struct mmap_params *mp, int cpu, | 1035 | struct mmap_params *mp, int cpu, |
988 | int thread, int *output) | 1036 | int thread, int *_output, int *_output_backward) |
989 | { | 1037 | { |
990 | struct perf_evsel *evsel; | 1038 | struct perf_evsel *evsel; |
1039 | int revent; | ||
991 | 1040 | ||
992 | evlist__for_each(evlist, evsel) { | 1041 | evlist__for_each_entry(evlist, evsel) { |
1042 | struct perf_mmap *maps = evlist->mmap; | ||
1043 | int *output = _output; | ||
993 | int fd; | 1044 | int fd; |
994 | 1045 | ||
1046 | if (evsel->attr.write_backward) { | ||
1047 | output = _output_backward; | ||
1048 | maps = evlist->backward_mmap; | ||
1049 | |||
1050 | if (!maps) { | ||
1051 | maps = perf_evlist__alloc_mmap(evlist); | ||
1052 | if (!maps) | ||
1053 | return -1; | ||
1054 | evlist->backward_mmap = maps; | ||
1055 | if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY) | ||
1056 | perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING); | ||
1057 | } | ||
1058 | } | ||
1059 | |||
995 | if (evsel->system_wide && thread) | 1060 | if (evsel->system_wide && thread) |
996 | continue; | 1061 | continue; |
997 | 1062 | ||
@@ -999,15 +1064,18 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
999 | 1064 | ||
1000 | if (*output == -1) { | 1065 | if (*output == -1) { |
1001 | *output = fd; | 1066 | *output = fd; |
1002 | if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0) | 1067 | |
1068 | if (perf_mmap__mmap(&maps[idx], mp, *output) < 0) | ||
1003 | return -1; | 1069 | return -1; |
1004 | } else { | 1070 | } else { |
1005 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) | 1071 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) |
1006 | return -1; | 1072 | return -1; |
1007 | 1073 | ||
1008 | perf_evlist__mmap_get(evlist, idx); | 1074 | perf_mmap__get(&maps[idx]); |
1009 | } | 1075 | } |
1010 | 1076 | ||
1077 | revent = perf_evlist__should_poll(evlist, evsel) ? POLLIN : 0; | ||
1078 | |||
1011 | /* | 1079 | /* |
1012 | * The system_wide flag causes a selected event to be opened | 1080 | * The system_wide flag causes a selected event to be opened |
1013 | * always without a pid. Consequently it will never get a | 1081 | * always without a pid. Consequently it will never get a |
@@ -1016,8 +1084,8 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
1016 | * Therefore don't add it for polling. | 1084 | * Therefore don't add it for polling. |
1017 | */ | 1085 | */ |
1018 | if (!evsel->system_wide && | 1086 | if (!evsel->system_wide && |
1019 | __perf_evlist__add_pollfd(evlist, fd, idx) < 0) { | 1087 | __perf_evlist__add_pollfd(evlist, fd, &maps[idx], revent) < 0) { |
1020 | perf_evlist__mmap_put(evlist, idx); | 1088 | perf_mmap__put(&maps[idx]); |
1021 | return -1; | 1089 | return -1; |
1022 | } | 1090 | } |
1023 | 1091 | ||
@@ -1043,13 +1111,14 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, | |||
1043 | pr_debug2("perf event ring buffer mmapped per cpu\n"); | 1111 | pr_debug2("perf event ring buffer mmapped per cpu\n"); |
1044 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 1112 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
1045 | int output = -1; | 1113 | int output = -1; |
1114 | int output_backward = -1; | ||
1046 | 1115 | ||
1047 | auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu, | 1116 | auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu, |
1048 | true); | 1117 | true); |
1049 | 1118 | ||
1050 | for (thread = 0; thread < nr_threads; thread++) { | 1119 | for (thread = 0; thread < nr_threads; thread++) { |
1051 | if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, | 1120 | if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, |
1052 | thread, &output)) | 1121 | thread, &output, &output_backward)) |
1053 | goto out_unmap; | 1122 | goto out_unmap; |
1054 | } | 1123 | } |
1055 | } | 1124 | } |
@@ -1057,8 +1126,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, | |||
1057 | return 0; | 1126 | return 0; |
1058 | 1127 | ||
1059 | out_unmap: | 1128 | out_unmap: |
1060 | for (cpu = 0; cpu < nr_cpus; cpu++) | 1129 | perf_evlist__munmap_nofree(evlist); |
1061 | __perf_evlist__munmap(evlist, cpu); | ||
1062 | return -1; | 1130 | return -1; |
1063 | } | 1131 | } |
1064 | 1132 | ||
@@ -1071,20 +1139,20 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, | |||
1071 | pr_debug2("perf event ring buffer mmapped per thread\n"); | 1139 | pr_debug2("perf event ring buffer mmapped per thread\n"); |
1072 | for (thread = 0; thread < nr_threads; thread++) { | 1140 | for (thread = 0; thread < nr_threads; thread++) { |
1073 | int output = -1; | 1141 | int output = -1; |
1142 | int output_backward = -1; | ||
1074 | 1143 | ||
1075 | auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread, | 1144 | auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread, |
1076 | false); | 1145 | false); |
1077 | 1146 | ||
1078 | if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, | 1147 | if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, |
1079 | &output)) | 1148 | &output, &output_backward)) |
1080 | goto out_unmap; | 1149 | goto out_unmap; |
1081 | } | 1150 | } |
1082 | 1151 | ||
1083 | return 0; | 1152 | return 0; |
1084 | 1153 | ||
1085 | out_unmap: | 1154 | out_unmap: |
1086 | for (thread = 0; thread < nr_threads; thread++) | 1155 | perf_evlist__munmap_nofree(evlist); |
1087 | __perf_evlist__munmap(evlist, thread); | ||
1088 | return -1; | 1156 | return -1; |
1089 | } | 1157 | } |
1090 | 1158 | ||
@@ -1217,7 +1285,9 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, | |||
1217 | .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), | 1285 | .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), |
1218 | }; | 1286 | }; |
1219 | 1287 | ||
1220 | if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) | 1288 | if (!evlist->mmap) |
1289 | evlist->mmap = perf_evlist__alloc_mmap(evlist); | ||
1290 | if (!evlist->mmap) | ||
1221 | return -ENOMEM; | 1291 | return -ENOMEM; |
1222 | 1292 | ||
1223 | if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) | 1293 | if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) |
@@ -1231,7 +1301,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, | |||
1231 | auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len, | 1301 | auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len, |
1232 | auxtrace_pages, auxtrace_overwrite); | 1302 | auxtrace_pages, auxtrace_overwrite); |
1233 | 1303 | ||
1234 | evlist__for_each(evlist, evsel) { | 1304 | evlist__for_each_entry(evlist, evsel) { |
1235 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | 1305 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
1236 | evsel->sample_id == NULL && | 1306 | evsel->sample_id == NULL && |
1237 | perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) | 1307 | perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) |
@@ -1307,7 +1377,7 @@ void __perf_evlist__set_sample_bit(struct perf_evlist *evlist, | |||
1307 | { | 1377 | { |
1308 | struct perf_evsel *evsel; | 1378 | struct perf_evsel *evsel; |
1309 | 1379 | ||
1310 | evlist__for_each(evlist, evsel) | 1380 | evlist__for_each_entry(evlist, evsel) |
1311 | __perf_evsel__set_sample_bit(evsel, bit); | 1381 | __perf_evsel__set_sample_bit(evsel, bit); |
1312 | } | 1382 | } |
1313 | 1383 | ||
@@ -1316,7 +1386,7 @@ void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist, | |||
1316 | { | 1386 | { |
1317 | struct perf_evsel *evsel; | 1387 | struct perf_evsel *evsel; |
1318 | 1388 | ||
1319 | evlist__for_each(evlist, evsel) | 1389 | evlist__for_each_entry(evlist, evsel) |
1320 | __perf_evsel__reset_sample_bit(evsel, bit); | 1390 | __perf_evsel__reset_sample_bit(evsel, bit); |
1321 | } | 1391 | } |
1322 | 1392 | ||
@@ -1327,7 +1397,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e | |||
1327 | const int ncpus = cpu_map__nr(evlist->cpus), | 1397 | const int ncpus = cpu_map__nr(evlist->cpus), |
1328 | nthreads = thread_map__nr(evlist->threads); | 1398 | nthreads = thread_map__nr(evlist->threads); |
1329 | 1399 | ||
1330 | evlist__for_each(evlist, evsel) { | 1400 | evlist__for_each_entry(evlist, evsel) { |
1331 | if (evsel->filter == NULL) | 1401 | if (evsel->filter == NULL) |
1332 | continue; | 1402 | continue; |
1333 | 1403 | ||
@@ -1350,7 +1420,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) | |||
1350 | struct perf_evsel *evsel; | 1420 | struct perf_evsel *evsel; |
1351 | int err = 0; | 1421 | int err = 0; |
1352 | 1422 | ||
1353 | evlist__for_each(evlist, evsel) { | 1423 | evlist__for_each_entry(evlist, evsel) { |
1354 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) | 1424 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) |
1355 | continue; | 1425 | continue; |
1356 | 1426 | ||
@@ -1404,7 +1474,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) | |||
1404 | if (evlist->id_pos < 0 || evlist->is_pos < 0) | 1474 | if (evlist->id_pos < 0 || evlist->is_pos < 0) |
1405 | return false; | 1475 | return false; |
1406 | 1476 | ||
1407 | evlist__for_each(evlist, pos) { | 1477 | evlist__for_each_entry(evlist, pos) { |
1408 | if (pos->id_pos != evlist->id_pos || | 1478 | if (pos->id_pos != evlist->id_pos || |
1409 | pos->is_pos != evlist->is_pos) | 1479 | pos->is_pos != evlist->is_pos) |
1410 | return false; | 1480 | return false; |
@@ -1420,7 +1490,7 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) | |||
1420 | if (evlist->combined_sample_type) | 1490 | if (evlist->combined_sample_type) |
1421 | return evlist->combined_sample_type; | 1491 | return evlist->combined_sample_type; |
1422 | 1492 | ||
1423 | evlist__for_each(evlist, evsel) | 1493 | evlist__for_each_entry(evlist, evsel) |
1424 | evlist->combined_sample_type |= evsel->attr.sample_type; | 1494 | evlist->combined_sample_type |= evsel->attr.sample_type; |
1425 | 1495 | ||
1426 | return evlist->combined_sample_type; | 1496 | return evlist->combined_sample_type; |
@@ -1437,7 +1507,7 @@ u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist) | |||
1437 | struct perf_evsel *evsel; | 1507 | struct perf_evsel *evsel; |
1438 | u64 branch_type = 0; | 1508 | u64 branch_type = 0; |
1439 | 1509 | ||
1440 | evlist__for_each(evlist, evsel) | 1510 | evlist__for_each_entry(evlist, evsel) |
1441 | branch_type |= evsel->attr.branch_sample_type; | 1511 | branch_type |= evsel->attr.branch_sample_type; |
1442 | return branch_type; | 1512 | return branch_type; |
1443 | } | 1513 | } |
@@ -1448,7 +1518,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist) | |||
1448 | u64 read_format = first->attr.read_format; | 1518 | u64 read_format = first->attr.read_format; |
1449 | u64 sample_type = first->attr.sample_type; | 1519 | u64 sample_type = first->attr.sample_type; |
1450 | 1520 | ||
1451 | evlist__for_each(evlist, pos) { | 1521 | evlist__for_each_entry(evlist, pos) { |
1452 | if (read_format != pos->attr.read_format) | 1522 | if (read_format != pos->attr.read_format) |
1453 | return false; | 1523 | return false; |
1454 | } | 1524 | } |
@@ -1505,7 +1575,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) | |||
1505 | { | 1575 | { |
1506 | struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; | 1576 | struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; |
1507 | 1577 | ||
1508 | evlist__for_each_continue(evlist, pos) { | 1578 | evlist__for_each_entry_continue(evlist, pos) { |
1509 | if (first->attr.sample_id_all != pos->attr.sample_id_all) | 1579 | if (first->attr.sample_id_all != pos->attr.sample_id_all) |
1510 | return false; | 1580 | return false; |
1511 | } | 1581 | } |
@@ -1532,7 +1602,7 @@ void perf_evlist__close(struct perf_evlist *evlist) | |||
1532 | int nthreads = thread_map__nr(evlist->threads); | 1602 | int nthreads = thread_map__nr(evlist->threads); |
1533 | int n; | 1603 | int n; |
1534 | 1604 | ||
1535 | evlist__for_each_reverse(evlist, evsel) { | 1605 | evlist__for_each_entry_reverse(evlist, evsel) { |
1536 | n = evsel->cpus ? evsel->cpus->nr : ncpus; | 1606 | n = evsel->cpus ? evsel->cpus->nr : ncpus; |
1537 | perf_evsel__close(evsel, n, nthreads); | 1607 | perf_evsel__close(evsel, n, nthreads); |
1538 | } | 1608 | } |
@@ -1586,7 +1656,7 @@ int perf_evlist__open(struct perf_evlist *evlist) | |||
1586 | 1656 | ||
1587 | perf_evlist__update_id_pos(evlist); | 1657 | perf_evlist__update_id_pos(evlist); |
1588 | 1658 | ||
1589 | evlist__for_each(evlist, evsel) { | 1659 | evlist__for_each_entry(evlist, evsel) { |
1590 | err = perf_evsel__open(evsel, evsel->cpus, evsel->threads); | 1660 | err = perf_evsel__open(evsel, evsel->cpus, evsel->threads); |
1591 | if (err < 0) | 1661 | if (err < 0) |
1592 | goto out_err; | 1662 | goto out_err; |
@@ -1747,7 +1817,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) | |||
1747 | struct perf_evsel *evsel; | 1817 | struct perf_evsel *evsel; |
1748 | size_t printed = 0; | 1818 | size_t printed = 0; |
1749 | 1819 | ||
1750 | evlist__for_each(evlist, evsel) { | 1820 | evlist__for_each_entry(evlist, evsel) { |
1751 | printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", | 1821 | printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", |
1752 | perf_evsel__name(evsel)); | 1822 | perf_evsel__name(evsel)); |
1753 | } | 1823 | } |
@@ -1759,7 +1829,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist, | |||
1759 | int err, char *buf, size_t size) | 1829 | int err, char *buf, size_t size) |
1760 | { | 1830 | { |
1761 | int printed, value; | 1831 | int printed, value; |
1762 | char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); | 1832 | char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); |
1763 | 1833 | ||
1764 | switch (err) { | 1834 | switch (err) { |
1765 | case EACCES: | 1835 | case EACCES: |
@@ -1811,7 +1881,7 @@ out_default: | |||
1811 | 1881 | ||
1812 | int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) | 1882 | int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) |
1813 | { | 1883 | { |
1814 | char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); | 1884 | char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); |
1815 | int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0; | 1885 | int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0; |
1816 | 1886 | ||
1817 | switch (err) { | 1887 | switch (err) { |
@@ -1849,7 +1919,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist, | |||
1849 | if (move_evsel == perf_evlist__first(evlist)) | 1919 | if (move_evsel == perf_evlist__first(evlist)) |
1850 | return; | 1920 | return; |
1851 | 1921 | ||
1852 | evlist__for_each_safe(evlist, n, evsel) { | 1922 | evlist__for_each_entry_safe(evlist, n, evsel) { |
1853 | if (evsel->leader == move_evsel->leader) | 1923 | if (evsel->leader == move_evsel->leader) |
1854 | list_move_tail(&evsel->node, &move); | 1924 | list_move_tail(&evsel->node, &move); |
1855 | } | 1925 | } |
@@ -1865,7 +1935,7 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist, | |||
1865 | if (tracking_evsel->tracking) | 1935 | if (tracking_evsel->tracking) |
1866 | return; | 1936 | return; |
1867 | 1937 | ||
1868 | evlist__for_each(evlist, evsel) { | 1938 | evlist__for_each_entry(evlist, evsel) { |
1869 | if (evsel != tracking_evsel) | 1939 | if (evsel != tracking_evsel) |
1870 | evsel->tracking = false; | 1940 | evsel->tracking = false; |
1871 | } | 1941 | } |
@@ -1879,7 +1949,7 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, | |||
1879 | { | 1949 | { |
1880 | struct perf_evsel *evsel; | 1950 | struct perf_evsel *evsel; |
1881 | 1951 | ||
1882 | evlist__for_each(evlist, evsel) { | 1952 | evlist__for_each_entry(evlist, evsel) { |
1883 | if (!evsel->name) | 1953 | if (!evsel->name) |
1884 | continue; | 1954 | continue; |
1885 | if (strcmp(str, evsel->name) == 0) | 1955 | if (strcmp(str, evsel->name) == 0) |
@@ -1888,3 +1958,61 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, | |||
1888 | 1958 | ||
1889 | return NULL; | 1959 | return NULL; |
1890 | } | 1960 | } |
1961 | |||
1962 | void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, | ||
1963 | enum bkw_mmap_state state) | ||
1964 | { | ||
1965 | enum bkw_mmap_state old_state = evlist->bkw_mmap_state; | ||
1966 | enum action { | ||
1967 | NONE, | ||
1968 | PAUSE, | ||
1969 | RESUME, | ||
1970 | } action = NONE; | ||
1971 | |||
1972 | if (!evlist->backward_mmap) | ||
1973 | return; | ||
1974 | |||
1975 | switch (old_state) { | ||
1976 | case BKW_MMAP_NOTREADY: { | ||
1977 | if (state != BKW_MMAP_RUNNING) | ||
1978 | goto state_err;; | ||
1979 | break; | ||
1980 | } | ||
1981 | case BKW_MMAP_RUNNING: { | ||
1982 | if (state != BKW_MMAP_DATA_PENDING) | ||
1983 | goto state_err; | ||
1984 | action = PAUSE; | ||
1985 | break; | ||
1986 | } | ||
1987 | case BKW_MMAP_DATA_PENDING: { | ||
1988 | if (state != BKW_MMAP_EMPTY) | ||
1989 | goto state_err; | ||
1990 | break; | ||
1991 | } | ||
1992 | case BKW_MMAP_EMPTY: { | ||
1993 | if (state != BKW_MMAP_RUNNING) | ||
1994 | goto state_err; | ||
1995 | action = RESUME; | ||
1996 | break; | ||
1997 | } | ||
1998 | default: | ||
1999 | WARN_ONCE(1, "Shouldn't get there\n"); | ||
2000 | } | ||
2001 | |||
2002 | evlist->bkw_mmap_state = state; | ||
2003 | |||
2004 | switch (action) { | ||
2005 | case PAUSE: | ||
2006 | perf_evlist__pause(evlist); | ||
2007 | break; | ||
2008 | case RESUME: | ||
2009 | perf_evlist__resume(evlist); | ||
2010 | break; | ||
2011 | case NONE: | ||
2012 | default: | ||
2013 | break; | ||
2014 | } | ||
2015 | |||
2016 | state_err: | ||
2017 | return; | ||
2018 | } | ||
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index d740fb877ab6..4fd034f22d2f 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -35,6 +35,40 @@ struct perf_mmap { | |||
35 | char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); | 35 | char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static inline size_t | ||
39 | perf_mmap__mmap_len(struct perf_mmap *map) | ||
40 | { | ||
41 | return map->mask + 1 + page_size; | ||
42 | } | ||
43 | |||
44 | /* | ||
45 | * State machine of bkw_mmap_state: | ||
46 | * | ||
47 | * .________________(forbid)_____________. | ||
48 | * | V | ||
49 | * NOTREADY --(0)--> RUNNING --(1)--> DATA_PENDING --(2)--> EMPTY | ||
50 | * ^ ^ | ^ | | ||
51 | * | |__(forbid)____/ |___(forbid)___/| | ||
52 | * | | | ||
53 | * \_________________(3)_______________/ | ||
54 | * | ||
55 | * NOTREADY : Backward ring buffers are not ready | ||
56 | * RUNNING : Backward ring buffers are recording | ||
57 | * DATA_PENDING : We are required to collect data from backward ring buffers | ||
58 | * EMPTY : We have collected data from backward ring buffers. | ||
59 | * | ||
60 | * (0): Setup backward ring buffer | ||
61 | * (1): Pause ring buffers for reading | ||
62 | * (2): Read from ring buffers | ||
63 | * (3): Resume ring buffers for recording | ||
64 | */ | ||
65 | enum bkw_mmap_state { | ||
66 | BKW_MMAP_NOTREADY, | ||
67 | BKW_MMAP_RUNNING, | ||
68 | BKW_MMAP_DATA_PENDING, | ||
69 | BKW_MMAP_EMPTY, | ||
70 | }; | ||
71 | |||
38 | struct perf_evlist { | 72 | struct perf_evlist { |
39 | struct list_head entries; | 73 | struct list_head entries; |
40 | struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; | 74 | struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; |
@@ -44,17 +78,18 @@ struct perf_evlist { | |||
44 | bool overwrite; | 78 | bool overwrite; |
45 | bool enabled; | 79 | bool enabled; |
46 | bool has_user_cpus; | 80 | bool has_user_cpus; |
47 | bool backward; | ||
48 | size_t mmap_len; | 81 | size_t mmap_len; |
49 | int id_pos; | 82 | int id_pos; |
50 | int is_pos; | 83 | int is_pos; |
51 | u64 combined_sample_type; | 84 | u64 combined_sample_type; |
85 | enum bkw_mmap_state bkw_mmap_state; | ||
52 | struct { | 86 | struct { |
53 | int cork_fd; | 87 | int cork_fd; |
54 | pid_t pid; | 88 | pid_t pid; |
55 | } workload; | 89 | } workload; |
56 | struct fdarray pollfd; | 90 | struct fdarray pollfd; |
57 | struct perf_mmap *mmap; | 91 | struct perf_mmap *mmap; |
92 | struct perf_mmap *backward_mmap; | ||
58 | struct thread_map *threads; | 93 | struct thread_map *threads; |
59 | struct cpu_map *cpus; | 94 | struct cpu_map *cpus; |
60 | struct perf_evsel *selected; | 95 | struct perf_evsel *selected; |
@@ -129,16 +164,24 @@ struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, | |||
129 | 164 | ||
130 | struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); | 165 | struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); |
131 | 166 | ||
167 | void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state); | ||
168 | |||
169 | union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool check_messup); | ||
170 | union perf_event *perf_mmap__read_backward(struct perf_mmap *map); | ||
171 | |||
172 | void perf_mmap__read_catchup(struct perf_mmap *md); | ||
173 | void perf_mmap__consume(struct perf_mmap *md, bool overwrite); | ||
174 | |||
132 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); | 175 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); |
133 | 176 | ||
177 | union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, | ||
178 | int idx); | ||
134 | union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, | 179 | union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, |
135 | int idx); | 180 | int idx); |
136 | void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx); | 181 | void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx); |
137 | 182 | ||
138 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); | 183 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); |
139 | 184 | ||
140 | int perf_evlist__pause(struct perf_evlist *evlist); | ||
141 | int perf_evlist__resume(struct perf_evlist *evlist); | ||
142 | int perf_evlist__open(struct perf_evlist *evlist); | 185 | int perf_evlist__open(struct perf_evlist *evlist); |
143 | void perf_evlist__close(struct perf_evlist *evlist); | 186 | void perf_evlist__close(struct perf_evlist *evlist); |
144 | 187 | ||
@@ -249,70 +292,70 @@ void perf_evlist__to_front(struct perf_evlist *evlist, | |||
249 | struct perf_evsel *move_evsel); | 292 | struct perf_evsel *move_evsel); |
250 | 293 | ||
251 | /** | 294 | /** |
252 | * __evlist__for_each - iterate thru all the evsels | 295 | * __evlist__for_each_entry - iterate thru all the evsels |
253 | * @list: list_head instance to iterate | 296 | * @list: list_head instance to iterate |
254 | * @evsel: struct evsel iterator | 297 | * @evsel: struct evsel iterator |
255 | */ | 298 | */ |
256 | #define __evlist__for_each(list, evsel) \ | 299 | #define __evlist__for_each_entry(list, evsel) \ |
257 | list_for_each_entry(evsel, list, node) | 300 | list_for_each_entry(evsel, list, node) |
258 | 301 | ||
259 | /** | 302 | /** |
260 | * evlist__for_each - iterate thru all the evsels | 303 | * evlist__for_each_entry - iterate thru all the evsels |
261 | * @evlist: evlist instance to iterate | 304 | * @evlist: evlist instance to iterate |
262 | * @evsel: struct evsel iterator | 305 | * @evsel: struct evsel iterator |
263 | */ | 306 | */ |
264 | #define evlist__for_each(evlist, evsel) \ | 307 | #define evlist__for_each_entry(evlist, evsel) \ |
265 | __evlist__for_each(&(evlist)->entries, evsel) | 308 | __evlist__for_each_entry(&(evlist)->entries, evsel) |
266 | 309 | ||
267 | /** | 310 | /** |
268 | * __evlist__for_each_continue - continue iteration thru all the evsels | 311 | * __evlist__for_each_entry_continue - continue iteration thru all the evsels |
269 | * @list: list_head instance to iterate | 312 | * @list: list_head instance to iterate |
270 | * @evsel: struct evsel iterator | 313 | * @evsel: struct evsel iterator |
271 | */ | 314 | */ |
272 | #define __evlist__for_each_continue(list, evsel) \ | 315 | #define __evlist__for_each_entry_continue(list, evsel) \ |
273 | list_for_each_entry_continue(evsel, list, node) | 316 | list_for_each_entry_continue(evsel, list, node) |
274 | 317 | ||
275 | /** | 318 | /** |
276 | * evlist__for_each_continue - continue iteration thru all the evsels | 319 | * evlist__for_each_entry_continue - continue iteration thru all the evsels |
277 | * @evlist: evlist instance to iterate | 320 | * @evlist: evlist instance to iterate |
278 | * @evsel: struct evsel iterator | 321 | * @evsel: struct evsel iterator |
279 | */ | 322 | */ |
280 | #define evlist__for_each_continue(evlist, evsel) \ | 323 | #define evlist__for_each_entry_continue(evlist, evsel) \ |
281 | __evlist__for_each_continue(&(evlist)->entries, evsel) | 324 | __evlist__for_each_entry_continue(&(evlist)->entries, evsel) |
282 | 325 | ||
283 | /** | 326 | /** |
284 | * __evlist__for_each_reverse - iterate thru all the evsels in reverse order | 327 | * __evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order |
285 | * @list: list_head instance to iterate | 328 | * @list: list_head instance to iterate |
286 | * @evsel: struct evsel iterator | 329 | * @evsel: struct evsel iterator |
287 | */ | 330 | */ |
288 | #define __evlist__for_each_reverse(list, evsel) \ | 331 | #define __evlist__for_each_entry_reverse(list, evsel) \ |
289 | list_for_each_entry_reverse(evsel, list, node) | 332 | list_for_each_entry_reverse(evsel, list, node) |
290 | 333 | ||
291 | /** | 334 | /** |
292 | * evlist__for_each_reverse - iterate thru all the evsels in reverse order | 335 | * evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order |
293 | * @evlist: evlist instance to iterate | 336 | * @evlist: evlist instance to iterate |
294 | * @evsel: struct evsel iterator | 337 | * @evsel: struct evsel iterator |
295 | */ | 338 | */ |
296 | #define evlist__for_each_reverse(evlist, evsel) \ | 339 | #define evlist__for_each_entry_reverse(evlist, evsel) \ |
297 | __evlist__for_each_reverse(&(evlist)->entries, evsel) | 340 | __evlist__for_each_entry_reverse(&(evlist)->entries, evsel) |
298 | 341 | ||
299 | /** | 342 | /** |
300 | * __evlist__for_each_safe - safely iterate thru all the evsels | 343 | * __evlist__for_each_entry_safe - safely iterate thru all the evsels |
301 | * @list: list_head instance to iterate | 344 | * @list: list_head instance to iterate |
302 | * @tmp: struct evsel temp iterator | 345 | * @tmp: struct evsel temp iterator |
303 | * @evsel: struct evsel iterator | 346 | * @evsel: struct evsel iterator |
304 | */ | 347 | */ |
305 | #define __evlist__for_each_safe(list, tmp, evsel) \ | 348 | #define __evlist__for_each_entry_safe(list, tmp, evsel) \ |
306 | list_for_each_entry_safe(evsel, tmp, list, node) | 349 | list_for_each_entry_safe(evsel, tmp, list, node) |
307 | 350 | ||
308 | /** | 351 | /** |
309 | * evlist__for_each_safe - safely iterate thru all the evsels | 352 | * evlist__for_each_entry_safe - safely iterate thru all the evsels |
310 | * @evlist: evlist instance to iterate | 353 | * @evlist: evlist instance to iterate |
311 | * @evsel: struct evsel iterator | 354 | * @evsel: struct evsel iterator |
312 | * @tmp: struct evsel temp iterator | 355 | * @tmp: struct evsel temp iterator |
313 | */ | 356 | */ |
314 | #define evlist__for_each_safe(evlist, tmp, evsel) \ | 357 | #define evlist__for_each_entry_safe(evlist, tmp, evsel) \ |
315 | __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) | 358 | __evlist__for_each_entry_safe(&(evlist)->entries, tmp, evsel) |
316 | 359 | ||
317 | void perf_evlist__set_tracking_event(struct perf_evlist *evlist, | 360 | void perf_evlist__set_tracking_event(struct perf_evlist *evlist, |
318 | struct perf_evsel *tracking_evsel); | 361 | struct perf_evsel *tracking_evsel); |
@@ -321,4 +364,7 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr); | |||
321 | 364 | ||
322 | struct perf_evsel * | 365 | struct perf_evsel * |
323 | perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str); | 366 | perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str); |
367 | |||
368 | struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, | ||
369 | union perf_event *event); | ||
324 | #endif /* __PERF_EVLIST_H */ | 370 | #endif /* __PERF_EVLIST_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 5d7037ef7d3b..d9b80ef881cd 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -200,6 +200,24 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel, | |||
200 | evsel->attr.read_format |= PERF_FORMAT_ID; | 200 | evsel->attr.read_format |= PERF_FORMAT_ID; |
201 | } | 201 | } |
202 | 202 | ||
203 | /** | ||
204 | * perf_evsel__is_function_event - Return whether given evsel is a function | ||
205 | * trace event | ||
206 | * | ||
207 | * @evsel - evsel selector to be tested | ||
208 | * | ||
209 | * Return %true if event is function trace event | ||
210 | */ | ||
211 | bool perf_evsel__is_function_event(struct perf_evsel *evsel) | ||
212 | { | ||
213 | #define FUNCTION_EVENT "ftrace:function" | ||
214 | |||
215 | return evsel->name && | ||
216 | !strncmp(FUNCTION_EVENT, evsel->name, sizeof(FUNCTION_EVENT)); | ||
217 | |||
218 | #undef FUNCTION_EVENT | ||
219 | } | ||
220 | |||
203 | void perf_evsel__init(struct perf_evsel *evsel, | 221 | void perf_evsel__init(struct perf_evsel *evsel, |
204 | struct perf_event_attr *attr, int idx) | 222 | struct perf_event_attr *attr, int idx) |
205 | { | 223 | { |
@@ -235,6 +253,34 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) | |||
235 | return evsel; | 253 | return evsel; |
236 | } | 254 | } |
237 | 255 | ||
256 | struct perf_evsel *perf_evsel__new_cycles(void) | ||
257 | { | ||
258 | struct perf_event_attr attr = { | ||
259 | .type = PERF_TYPE_HARDWARE, | ||
260 | .config = PERF_COUNT_HW_CPU_CYCLES, | ||
261 | }; | ||
262 | struct perf_evsel *evsel; | ||
263 | |||
264 | event_attr_init(&attr); | ||
265 | |||
266 | perf_event_attr__set_max_precise_ip(&attr); | ||
267 | |||
268 | evsel = perf_evsel__new(&attr); | ||
269 | if (evsel == NULL) | ||
270 | goto out; | ||
271 | |||
272 | /* use asprintf() because free(evsel) assumes name is allocated */ | ||
273 | if (asprintf(&evsel->name, "cycles%.*s", | ||
274 | attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0) | ||
275 | goto error_free; | ||
276 | out: | ||
277 | return evsel; | ||
278 | error_free: | ||
279 | perf_evsel__delete(evsel); | ||
280 | evsel = NULL; | ||
281 | goto out; | ||
282 | } | ||
283 | |||
238 | /* | 284 | /* |
239 | * Returns pointer with encoded error via <linux/err.h> interface. | 285 | * Returns pointer with encoded error via <linux/err.h> interface. |
240 | */ | 286 | */ |
@@ -572,6 +618,8 @@ void perf_evsel__config_callchain(struct perf_evsel *evsel, | |||
572 | 618 | ||
573 | perf_evsel__set_sample_bit(evsel, CALLCHAIN); | 619 | perf_evsel__set_sample_bit(evsel, CALLCHAIN); |
574 | 620 | ||
621 | attr->sample_max_stack = param->max_stack; | ||
622 | |||
575 | if (param->record_mode == CALLCHAIN_LBR) { | 623 | if (param->record_mode == CALLCHAIN_LBR) { |
576 | if (!opts->branch_stack) { | 624 | if (!opts->branch_stack) { |
577 | if (attr->exclude_user) { | 625 | if (attr->exclude_user) { |
@@ -635,7 +683,8 @@ static void apply_config_terms(struct perf_evsel *evsel, | |||
635 | struct perf_event_attr *attr = &evsel->attr; | 683 | struct perf_event_attr *attr = &evsel->attr; |
636 | struct callchain_param param; | 684 | struct callchain_param param; |
637 | u32 dump_size = 0; | 685 | u32 dump_size = 0; |
638 | char *callgraph_buf = NULL; | 686 | int max_stack = 0; |
687 | const char *callgraph_buf = NULL; | ||
639 | 688 | ||
640 | /* callgraph default */ | 689 | /* callgraph default */ |
641 | param.record_mode = callchain_param.record_mode; | 690 | param.record_mode = callchain_param.record_mode; |
@@ -662,6 +711,9 @@ static void apply_config_terms(struct perf_evsel *evsel, | |||
662 | case PERF_EVSEL__CONFIG_TERM_STACK_USER: | 711 | case PERF_EVSEL__CONFIG_TERM_STACK_USER: |
663 | dump_size = term->val.stack_user; | 712 | dump_size = term->val.stack_user; |
664 | break; | 713 | break; |
714 | case PERF_EVSEL__CONFIG_TERM_MAX_STACK: | ||
715 | max_stack = term->val.max_stack; | ||
716 | break; | ||
665 | case PERF_EVSEL__CONFIG_TERM_INHERIT: | 717 | case PERF_EVSEL__CONFIG_TERM_INHERIT: |
666 | /* | 718 | /* |
667 | * attr->inherit should has already been set by | 719 | * attr->inherit should has already been set by |
@@ -671,13 +723,21 @@ static void apply_config_terms(struct perf_evsel *evsel, | |||
671 | */ | 723 | */ |
672 | attr->inherit = term->val.inherit ? 1 : 0; | 724 | attr->inherit = term->val.inherit ? 1 : 0; |
673 | break; | 725 | break; |
726 | case PERF_EVSEL__CONFIG_TERM_OVERWRITE: | ||
727 | attr->write_backward = term->val.overwrite ? 1 : 0; | ||
728 | break; | ||
674 | default: | 729 | default: |
675 | break; | 730 | break; |
676 | } | 731 | } |
677 | } | 732 | } |
678 | 733 | ||
679 | /* User explicitly set per-event callgraph, clear the old setting and reset. */ | 734 | /* User explicitly set per-event callgraph, clear the old setting and reset. */ |
680 | if ((callgraph_buf != NULL) || (dump_size > 0)) { | 735 | if ((callgraph_buf != NULL) || (dump_size > 0) || max_stack) { |
736 | if (max_stack) { | ||
737 | param.max_stack = max_stack; | ||
738 | if (callgraph_buf == NULL) | ||
739 | callgraph_buf = "fp"; | ||
740 | } | ||
681 | 741 | ||
682 | /* parse callgraph parameters */ | 742 | /* parse callgraph parameters */ |
683 | if (callgraph_buf != NULL) { | 743 | if (callgraph_buf != NULL) { |
@@ -747,6 +807,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, | |||
747 | 807 | ||
748 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; | 808 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; |
749 | attr->inherit = !opts->no_inherit; | 809 | attr->inherit = !opts->no_inherit; |
810 | attr->write_backward = opts->overwrite ? 1 : 0; | ||
750 | 811 | ||
751 | perf_evsel__set_sample_bit(evsel, IP); | 812 | perf_evsel__set_sample_bit(evsel, IP); |
752 | perf_evsel__set_sample_bit(evsel, TID); | 813 | perf_evsel__set_sample_bit(evsel, TID); |
@@ -821,7 +882,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, | |||
821 | perf_evsel__set_sample_bit(evsel, REGS_INTR); | 882 | perf_evsel__set_sample_bit(evsel, REGS_INTR); |
822 | } | 883 | } |
823 | 884 | ||
824 | if (target__has_cpu(&opts->target)) | 885 | if (target__has_cpu(&opts->target) || opts->sample_cpu) |
825 | perf_evsel__set_sample_bit(evsel, CPU); | 886 | perf_evsel__set_sample_bit(evsel, CPU); |
826 | 887 | ||
827 | if (opts->period) | 888 | if (opts->period) |
@@ -1329,6 +1390,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, | |||
1329 | PRINT_ATTRf(clockid, p_signed); | 1390 | PRINT_ATTRf(clockid, p_signed); |
1330 | PRINT_ATTRf(sample_regs_intr, p_hex); | 1391 | PRINT_ATTRf(sample_regs_intr, p_hex); |
1331 | PRINT_ATTRf(aux_watermark, p_unsigned); | 1392 | PRINT_ATTRf(aux_watermark, p_unsigned); |
1393 | PRINT_ATTRf(sample_max_stack, p_unsigned); | ||
1332 | 1394 | ||
1333 | return ret; | 1395 | return ret; |
1334 | } | 1396 | } |
@@ -1347,6 +1409,9 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
1347 | int pid = -1, err; | 1409 | int pid = -1, err; |
1348 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; | 1410 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; |
1349 | 1411 | ||
1412 | if (perf_missing_features.write_backward && evsel->attr.write_backward) | ||
1413 | return -EINVAL; | ||
1414 | |||
1350 | if (evsel->system_wide) | 1415 | if (evsel->system_wide) |
1351 | nthreads = 1; | 1416 | nthreads = 1; |
1352 | else | 1417 | else |
@@ -1377,8 +1442,6 @@ fallback_missing_features: | |||
1377 | if (perf_missing_features.lbr_flags) | 1442 | if (perf_missing_features.lbr_flags) |
1378 | evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | | 1443 | evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | |
1379 | PERF_SAMPLE_BRANCH_NO_CYCLES); | 1444 | PERF_SAMPLE_BRANCH_NO_CYCLES); |
1380 | if (perf_missing_features.write_backward) | ||
1381 | evsel->attr.write_backward = false; | ||
1382 | retry_sample_id: | 1445 | retry_sample_id: |
1383 | if (perf_missing_features.sample_id_all) | 1446 | if (perf_missing_features.sample_id_all) |
1384 | evsel->attr.sample_id_all = 0; | 1447 | evsel->attr.sample_id_all = 0; |
@@ -1441,12 +1504,6 @@ retry_open: | |||
1441 | err = -EINVAL; | 1504 | err = -EINVAL; |
1442 | goto out_close; | 1505 | goto out_close; |
1443 | } | 1506 | } |
1444 | |||
1445 | if (evsel->overwrite && | ||
1446 | perf_missing_features.write_backward) { | ||
1447 | err = -EINVAL; | ||
1448 | goto out_close; | ||
1449 | } | ||
1450 | } | 1507 | } |
1451 | } | 1508 | } |
1452 | 1509 | ||
@@ -1484,7 +1541,10 @@ try_fallback: | |||
1484 | * Must probe features in the order they were added to the | 1541 | * Must probe features in the order they were added to the |
1485 | * perf_event_attr interface. | 1542 | * perf_event_attr interface. |
1486 | */ | 1543 | */ |
1487 | if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { | 1544 | if (!perf_missing_features.write_backward && evsel->attr.write_backward) { |
1545 | perf_missing_features.write_backward = true; | ||
1546 | goto out_close; | ||
1547 | } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { | ||
1488 | perf_missing_features.clockid_wrong = true; | 1548 | perf_missing_features.clockid_wrong = true; |
1489 | goto fallback_missing_features; | 1549 | goto fallback_missing_features; |
1490 | } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { | 1550 | } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { |
@@ -1509,12 +1569,7 @@ try_fallback: | |||
1509 | PERF_SAMPLE_BRANCH_NO_FLAGS))) { | 1569 | PERF_SAMPLE_BRANCH_NO_FLAGS))) { |
1510 | perf_missing_features.lbr_flags = true; | 1570 | perf_missing_features.lbr_flags = true; |
1511 | goto fallback_missing_features; | 1571 | goto fallback_missing_features; |
1512 | } else if (!perf_missing_features.write_backward && | ||
1513 | evsel->attr.write_backward) { | ||
1514 | perf_missing_features.write_backward = true; | ||
1515 | goto fallback_missing_features; | ||
1516 | } | 1572 | } |
1517 | |||
1518 | out_close: | 1573 | out_close: |
1519 | do { | 1574 | do { |
1520 | while (--thread >= 0) { | 1575 | while (--thread >= 0) { |
@@ -2239,17 +2294,11 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, | |||
2239 | return sample->raw_data + offset; | 2294 | return sample->raw_data + offset; |
2240 | } | 2295 | } |
2241 | 2296 | ||
2242 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | 2297 | u64 format_field__intval(struct format_field *field, struct perf_sample *sample, |
2243 | const char *name) | 2298 | bool needs_swap) |
2244 | { | 2299 | { |
2245 | struct format_field *field = perf_evsel__field(evsel, name); | ||
2246 | void *ptr; | ||
2247 | u64 value; | 2300 | u64 value; |
2248 | 2301 | void *ptr = sample->raw_data + field->offset; | |
2249 | if (!field) | ||
2250 | return 0; | ||
2251 | |||
2252 | ptr = sample->raw_data + field->offset; | ||
2253 | 2302 | ||
2254 | switch (field->size) { | 2303 | switch (field->size) { |
2255 | case 1: | 2304 | case 1: |
@@ -2267,7 +2316,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
2267 | return 0; | 2316 | return 0; |
2268 | } | 2317 | } |
2269 | 2318 | ||
2270 | if (!evsel->needs_swap) | 2319 | if (!needs_swap) |
2271 | return value; | 2320 | return value; |
2272 | 2321 | ||
2273 | switch (field->size) { | 2322 | switch (field->size) { |
@@ -2284,6 +2333,17 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
2284 | return 0; | 2333 | return 0; |
2285 | } | 2334 | } |
2286 | 2335 | ||
2336 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | ||
2337 | const char *name) | ||
2338 | { | ||
2339 | struct format_field *field = perf_evsel__field(evsel, name); | ||
2340 | |||
2341 | if (!field) | ||
2342 | return 0; | ||
2343 | |||
2344 | return field ? format_field__intval(field, sample, evsel->needs_swap) : 0; | ||
2345 | } | ||
2346 | |||
2287 | bool perf_evsel__fallback(struct perf_evsel *evsel, int err, | 2347 | bool perf_evsel__fallback(struct perf_evsel *evsel, int err, |
2288 | char *msg, size_t msgsize) | 2348 | char *msg, size_t msgsize) |
2289 | { | 2349 | { |
@@ -2372,6 +2432,9 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, | |||
2372 | "No such device - did you specify an out-of-range profile CPU?"); | 2432 | "No such device - did you specify an out-of-range profile CPU?"); |
2373 | break; | 2433 | break; |
2374 | case EOPNOTSUPP: | 2434 | case EOPNOTSUPP: |
2435 | if (evsel->attr.sample_period != 0) | ||
2436 | return scnprintf(msg, size, "%s", | ||
2437 | "PMU Hardware doesn't support sampling/overflow-interrupts."); | ||
2375 | if (evsel->attr.precise_ip) | 2438 | if (evsel->attr.precise_ip) |
2376 | return scnprintf(msg, size, "%s", | 2439 | return scnprintf(msg, size, "%s", |
2377 | "\'precise\' request may not be supported. Try removing 'p' modifier."); | 2440 | "\'precise\' request may not be supported. Try removing 'p' modifier."); |
@@ -2389,6 +2452,8 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, | |||
2389 | "We found oprofile daemon running, please stop it and try again."); | 2452 | "We found oprofile daemon running, please stop it and try again."); |
2390 | break; | 2453 | break; |
2391 | case EINVAL: | 2454 | case EINVAL: |
2455 | if (evsel->attr.write_backward && perf_missing_features.write_backward) | ||
2456 | return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel."); | ||
2392 | if (perf_missing_features.clockid) | 2457 | if (perf_missing_features.clockid) |
2393 | return scnprintf(msg, size, "clockid feature not supported."); | 2458 | return scnprintf(msg, size, "clockid feature not supported."); |
2394 | if (perf_missing_features.clockid_wrong) | 2459 | if (perf_missing_features.clockid_wrong) |
@@ -2402,6 +2467,13 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, | |||
2402 | "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" | 2467 | "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" |
2403 | "/bin/dmesg may provide additional information.\n" | 2468 | "/bin/dmesg may provide additional information.\n" |
2404 | "No CONFIG_PERF_EVENTS=y kernel support configured?", | 2469 | "No CONFIG_PERF_EVENTS=y kernel support configured?", |
2405 | err, strerror_r(err, sbuf, sizeof(sbuf)), | 2470 | err, str_error_r(err, sbuf, sizeof(sbuf)), |
2406 | perf_evsel__name(evsel)); | 2471 | perf_evsel__name(evsel)); |
2407 | } | 2472 | } |
2473 | |||
2474 | char *perf_evsel__env_arch(struct perf_evsel *evsel) | ||
2475 | { | ||
2476 | if (evsel && evsel->evlist && evsel->evlist->env) | ||
2477 | return evsel->evlist->env->arch; | ||
2478 | return NULL; | ||
2479 | } | ||
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index c1f10159804c..4d44129e050b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -44,6 +44,8 @@ enum { | |||
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_INHERIT, |
47 | PERF_EVSEL__CONFIG_TERM_MAX_STACK, | ||
48 | PERF_EVSEL__CONFIG_TERM_OVERWRITE, | ||
47 | PERF_EVSEL__CONFIG_TERM_MAX, | 49 | PERF_EVSEL__CONFIG_TERM_MAX, |
48 | }; | 50 | }; |
49 | 51 | ||
@@ -56,7 +58,9 @@ struct perf_evsel_config_term { | |||
56 | bool time; | 58 | bool time; |
57 | char *callgraph; | 59 | char *callgraph; |
58 | u64 stack_user; | 60 | u64 stack_user; |
61 | int max_stack; | ||
59 | bool inherit; | 62 | bool inherit; |
63 | bool overwrite; | ||
60 | } val; | 64 | } val; |
61 | }; | 65 | }; |
62 | 66 | ||
@@ -112,7 +116,6 @@ struct perf_evsel { | |||
112 | bool tracking; | 116 | bool tracking; |
113 | bool per_pkg; | 117 | bool per_pkg; |
114 | bool precise_max; | 118 | bool precise_max; |
115 | bool overwrite; | ||
116 | /* parse modifier helper */ | 119 | /* parse modifier helper */ |
117 | int exclude_GH; | 120 | int exclude_GH; |
118 | int nr_members; | 121 | int nr_members; |
@@ -172,6 +175,8 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char * | |||
172 | return perf_evsel__newtp_idx(sys, name, 0); | 175 | return perf_evsel__newtp_idx(sys, name, 0); |
173 | } | 176 | } |
174 | 177 | ||
178 | struct perf_evsel *perf_evsel__new_cycles(void); | ||
179 | |||
175 | struct event_format *event_format__new(const char *sys, const char *name); | 180 | struct event_format *event_format__new(const char *sys, const char *name); |
176 | 181 | ||
177 | void perf_evsel__init(struct perf_evsel *evsel, | 182 | void perf_evsel__init(struct perf_evsel *evsel, |
@@ -259,6 +264,8 @@ static inline char *perf_evsel__strval(struct perf_evsel *evsel, | |||
259 | 264 | ||
260 | struct format_field; | 265 | struct format_field; |
261 | 266 | ||
267 | u64 format_field__intval(struct format_field *field, struct perf_sample *sample, bool needs_swap); | ||
268 | |||
262 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); | 269 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); |
263 | 270 | ||
264 | #define perf_evsel__match(evsel, t, c) \ | 271 | #define perf_evsel__match(evsel, t, c) \ |
@@ -351,23 +358,7 @@ static inline bool perf_evsel__is_group_event(struct perf_evsel *evsel) | |||
351 | return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1; | 358 | return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1; |
352 | } | 359 | } |
353 | 360 | ||
354 | /** | 361 | bool perf_evsel__is_function_event(struct perf_evsel *evsel); |
355 | * perf_evsel__is_function_event - Return whether given evsel is a function | ||
356 | * trace event | ||
357 | * | ||
358 | * @evsel - evsel selector to be tested | ||
359 | * | ||
360 | * Return %true if event is function trace event | ||
361 | */ | ||
362 | static inline bool perf_evsel__is_function_event(struct perf_evsel *evsel) | ||
363 | { | ||
364 | #define FUNCTION_EVENT "ftrace:function" | ||
365 | |||
366 | return evsel->name && | ||
367 | !strncmp(FUNCTION_EVENT, evsel->name, sizeof(FUNCTION_EVENT)); | ||
368 | |||
369 | #undef FUNCTION_EVENT | ||
370 | } | ||
371 | 362 | ||
372 | static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel) | 363 | static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel) |
373 | { | 364 | { |
@@ -431,4 +422,6 @@ typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *); | |||
431 | int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, | 422 | int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, |
432 | attr__fprintf_f attr__fprintf, void *priv); | 423 | attr__fprintf_f attr__fprintf, void *priv); |
433 | 424 | ||
425 | char *perf_evsel__env_arch(struct perf_evsel *evsel); | ||
426 | |||
434 | #endif /* __PERF_EVSEL_H */ | 427 | #endif /* __PERF_EVSEL_H */ |
diff --git a/tools/perf/util/group.h b/tools/perf/util/group.h new file mode 100644 index 000000000000..116debe7a995 --- /dev/null +++ b/tools/perf/util/group.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef GROUP_H | ||
2 | #define GROUP_H 1 | ||
3 | |||
4 | bool arch_topdown_check_group(bool *warn); | ||
5 | void arch_topdown_group_warn(void); | ||
6 | |||
7 | #endif | ||
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 08852dde1378..8f0db4007282 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -336,7 +336,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused, | |||
336 | if (ret < 0) | 336 | if (ret < 0) |
337 | return ret; | 337 | return ret; |
338 | 338 | ||
339 | evlist__for_each(evlist, evsel) { | 339 | evlist__for_each_entry(evlist, evsel) { |
340 | ret = do_write(fd, &evsel->attr, sz); | 340 | ret = do_write(fd, &evsel->attr, sz); |
341 | if (ret < 0) | 341 | if (ret < 0) |
342 | return ret; | 342 | return ret; |
@@ -801,7 +801,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused, | |||
801 | if (ret < 0) | 801 | if (ret < 0) |
802 | return ret; | 802 | return ret; |
803 | 803 | ||
804 | evlist__for_each(evlist, evsel) { | 804 | evlist__for_each_entry(evlist, evsel) { |
805 | if (perf_evsel__is_group_leader(evsel) && | 805 | if (perf_evsel__is_group_leader(evsel) && |
806 | evsel->nr_members > 1) { | 806 | evsel->nr_members > 1) { |
807 | const char *name = evsel->group_name ?: "{anon_group}"; | 807 | const char *name = evsel->group_name ?: "{anon_group}"; |
@@ -1306,42 +1306,19 @@ static void print_total_mem(struct perf_header *ph, int fd __maybe_unused, | |||
1306 | static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused, | 1306 | static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused, |
1307 | FILE *fp) | 1307 | FILE *fp) |
1308 | { | 1308 | { |
1309 | u32 nr, c, i; | 1309 | int i; |
1310 | char *str, *tmp; | 1310 | struct numa_node *n; |
1311 | uint64_t mem_total, mem_free; | ||
1312 | |||
1313 | /* nr nodes */ | ||
1314 | nr = ph->env.nr_numa_nodes; | ||
1315 | str = ph->env.numa_nodes; | ||
1316 | |||
1317 | for (i = 0; i < nr; i++) { | ||
1318 | /* node number */ | ||
1319 | c = strtoul(str, &tmp, 0); | ||
1320 | if (*tmp != ':') | ||
1321 | goto error; | ||
1322 | |||
1323 | str = tmp + 1; | ||
1324 | mem_total = strtoull(str, &tmp, 0); | ||
1325 | if (*tmp != ':') | ||
1326 | goto error; | ||
1327 | 1311 | ||
1328 | str = tmp + 1; | 1312 | for (i = 0; i < ph->env.nr_numa_nodes; i++) { |
1329 | mem_free = strtoull(str, &tmp, 0); | 1313 | n = &ph->env.numa_nodes[i]; |
1330 | if (*tmp != ':') | ||
1331 | goto error; | ||
1332 | 1314 | ||
1333 | fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," | 1315 | fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," |
1334 | " free = %"PRIu64" kB\n", | 1316 | " free = %"PRIu64" kB\n", |
1335 | c, mem_total, mem_free); | 1317 | n->node, n->mem_total, n->mem_free); |
1336 | 1318 | ||
1337 | str = tmp + 1; | 1319 | fprintf(fp, "# node%u cpu list : ", n->node); |
1338 | fprintf(fp, "# node%u cpu list : %s\n", c, str); | 1320 | cpu_map__fprintf(n->map, fp); |
1339 | |||
1340 | str += strlen(str) + 1; | ||
1341 | } | 1321 | } |
1342 | return; | ||
1343 | error: | ||
1344 | fprintf(fp, "# numa topology : not available\n"); | ||
1345 | } | 1322 | } |
1346 | 1323 | ||
1347 | static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp) | 1324 | static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp) |
@@ -1425,7 +1402,7 @@ static void print_group_desc(struct perf_header *ph, int fd __maybe_unused, | |||
1425 | 1402 | ||
1426 | session = container_of(ph, struct perf_session, header); | 1403 | session = container_of(ph, struct perf_session, header); |
1427 | 1404 | ||
1428 | evlist__for_each(session->evlist, evsel) { | 1405 | evlist__for_each_entry(session->evlist, evsel) { |
1429 | if (perf_evsel__is_group_leader(evsel) && | 1406 | if (perf_evsel__is_group_leader(evsel) && |
1430 | evsel->nr_members > 1) { | 1407 | evsel->nr_members > 1) { |
1431 | fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", | 1408 | fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", |
@@ -1703,7 +1680,7 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) | |||
1703 | { | 1680 | { |
1704 | struct perf_evsel *evsel; | 1681 | struct perf_evsel *evsel; |
1705 | 1682 | ||
1706 | evlist__for_each(evlist, evsel) { | 1683 | evlist__for_each_entry(evlist, evsel) { |
1707 | if (evsel->idx == idx) | 1684 | if (evsel->idx == idx) |
1708 | return evsel; | 1685 | return evsel; |
1709 | } | 1686 | } |
@@ -1906,11 +1883,10 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse | |||
1906 | struct perf_header *ph, int fd, | 1883 | struct perf_header *ph, int fd, |
1907 | void *data __maybe_unused) | 1884 | void *data __maybe_unused) |
1908 | { | 1885 | { |
1886 | struct numa_node *nodes, *n; | ||
1909 | ssize_t ret; | 1887 | ssize_t ret; |
1910 | u32 nr, node, i; | 1888 | u32 nr, i; |
1911 | char *str; | 1889 | char *str; |
1912 | uint64_t mem_total, mem_free; | ||
1913 | struct strbuf sb; | ||
1914 | 1890 | ||
1915 | /* nr nodes */ | 1891 | /* nr nodes */ |
1916 | ret = readn(fd, &nr, sizeof(nr)); | 1892 | ret = readn(fd, &nr, sizeof(nr)); |
@@ -1921,47 +1897,47 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse | |||
1921 | nr = bswap_32(nr); | 1897 | nr = bswap_32(nr); |
1922 | 1898 | ||
1923 | ph->env.nr_numa_nodes = nr; | 1899 | ph->env.nr_numa_nodes = nr; |
1924 | if (strbuf_init(&sb, 256) < 0) | 1900 | nodes = zalloc(sizeof(*nodes) * nr); |
1925 | return -1; | 1901 | if (!nodes) |
1902 | return -ENOMEM; | ||
1926 | 1903 | ||
1927 | for (i = 0; i < nr; i++) { | 1904 | for (i = 0; i < nr; i++) { |
1905 | n = &nodes[i]; | ||
1906 | |||
1928 | /* node number */ | 1907 | /* node number */ |
1929 | ret = readn(fd, &node, sizeof(node)); | 1908 | ret = readn(fd, &n->node, sizeof(u32)); |
1930 | if (ret != sizeof(node)) | 1909 | if (ret != sizeof(n->node)) |
1931 | goto error; | 1910 | goto error; |
1932 | 1911 | ||
1933 | ret = readn(fd, &mem_total, sizeof(u64)); | 1912 | ret = readn(fd, &n->mem_total, sizeof(u64)); |
1934 | if (ret != sizeof(u64)) | 1913 | if (ret != sizeof(u64)) |
1935 | goto error; | 1914 | goto error; |
1936 | 1915 | ||
1937 | ret = readn(fd, &mem_free, sizeof(u64)); | 1916 | ret = readn(fd, &n->mem_free, sizeof(u64)); |
1938 | if (ret != sizeof(u64)) | 1917 | if (ret != sizeof(u64)) |
1939 | goto error; | 1918 | goto error; |
1940 | 1919 | ||
1941 | if (ph->needs_swap) { | 1920 | if (ph->needs_swap) { |
1942 | node = bswap_32(node); | 1921 | n->node = bswap_32(n->node); |
1943 | mem_total = bswap_64(mem_total); | 1922 | n->mem_total = bswap_64(n->mem_total); |
1944 | mem_free = bswap_64(mem_free); | 1923 | n->mem_free = bswap_64(n->mem_free); |
1945 | } | 1924 | } |
1946 | 1925 | ||
1947 | if (strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":", | ||
1948 | node, mem_total, mem_free) < 0) | ||
1949 | goto error; | ||
1950 | |||
1951 | str = do_read_string(fd, ph); | 1926 | str = do_read_string(fd, ph); |
1952 | if (!str) | 1927 | if (!str) |
1953 | goto error; | 1928 | goto error; |
1954 | 1929 | ||
1955 | /* include a NULL character at the end */ | 1930 | n->map = cpu_map__new(str); |
1956 | if (strbuf_add(&sb, str, strlen(str) + 1) < 0) | 1931 | if (!n->map) |
1957 | goto error; | 1932 | goto error; |
1933 | |||
1958 | free(str); | 1934 | free(str); |
1959 | } | 1935 | } |
1960 | ph->env.numa_nodes = strbuf_detach(&sb, NULL); | 1936 | ph->env.numa_nodes = nodes; |
1961 | return 0; | 1937 | return 0; |
1962 | 1938 | ||
1963 | error: | 1939 | error: |
1964 | strbuf_release(&sb); | 1940 | free(nodes); |
1965 | return -1; | 1941 | return -1; |
1966 | } | 1942 | } |
1967 | 1943 | ||
@@ -2075,7 +2051,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused, | |||
2075 | session->evlist->nr_groups = nr_groups; | 2051 | session->evlist->nr_groups = nr_groups; |
2076 | 2052 | ||
2077 | i = nr = 0; | 2053 | i = nr = 0; |
2078 | evlist__for_each(session->evlist, evsel) { | 2054 | evlist__for_each_entry(session->evlist, evsel) { |
2079 | if (evsel->idx == (int) desc[i].leader_idx) { | 2055 | if (evsel->idx == (int) desc[i].leader_idx) { |
2080 | evsel->leader = evsel; | 2056 | evsel->leader = evsel; |
2081 | /* {anon_group} is a dummy name */ | 2057 | /* {anon_group} is a dummy name */ |
@@ -2383,7 +2359,7 @@ int perf_session__write_header(struct perf_session *session, | |||
2383 | 2359 | ||
2384 | lseek(fd, sizeof(f_header), SEEK_SET); | 2360 | lseek(fd, sizeof(f_header), SEEK_SET); |
2385 | 2361 | ||
2386 | evlist__for_each(session->evlist, evsel) { | 2362 | evlist__for_each_entry(session->evlist, evsel) { |
2387 | evsel->id_offset = lseek(fd, 0, SEEK_CUR); | 2363 | evsel->id_offset = lseek(fd, 0, SEEK_CUR); |
2388 | err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); | 2364 | err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); |
2389 | if (err < 0) { | 2365 | if (err < 0) { |
@@ -2394,7 +2370,7 @@ int perf_session__write_header(struct perf_session *session, | |||
2394 | 2370 | ||
2395 | attr_offset = lseek(fd, 0, SEEK_CUR); | 2371 | attr_offset = lseek(fd, 0, SEEK_CUR); |
2396 | 2372 | ||
2397 | evlist__for_each(evlist, evsel) { | 2373 | evlist__for_each_entry(evlist, evsel) { |
2398 | f_attr = (struct perf_file_attr){ | 2374 | f_attr = (struct perf_file_attr){ |
2399 | .attr = evsel->attr, | 2375 | .attr = evsel->attr, |
2400 | .ids = { | 2376 | .ids = { |
@@ -2828,7 +2804,7 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, | |||
2828 | { | 2804 | { |
2829 | struct perf_evsel *pos; | 2805 | struct perf_evsel *pos; |
2830 | 2806 | ||
2831 | evlist__for_each(evlist, pos) { | 2807 | evlist__for_each_entry(evlist, pos) { |
2832 | if (pos->attr.type == PERF_TYPE_TRACEPOINT && | 2808 | if (pos->attr.type == PERF_TYPE_TRACEPOINT && |
2833 | perf_evsel__prepare_tracepoint_event(pos, pevent)) | 2809 | perf_evsel__prepare_tracepoint_event(pos, pevent)) |
2834 | return -1; | 2810 | return -1; |
@@ -3127,7 +3103,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, | |||
3127 | struct perf_evsel *evsel; | 3103 | struct perf_evsel *evsel; |
3128 | int err = 0; | 3104 | int err = 0; |
3129 | 3105 | ||
3130 | evlist__for_each(session->evlist, evsel) { | 3106 | evlist__for_each_entry(session->evlist, evsel) { |
3131 | err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, | 3107 | err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, |
3132 | evsel->id, process); | 3108 | evsel->id, process); |
3133 | if (err) { | 3109 | if (err) { |
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c index d62ccaeeadd6..2821f8d77e52 100644 --- a/tools/perf/util/help-unknown-cmd.c +++ b/tools/perf/util/help-unknown-cmd.c | |||
@@ -1,4 +1,6 @@ | |||
1 | #include "cache.h" | 1 | #include "cache.h" |
2 | #include "config.h" | ||
3 | #include <stdio.h> | ||
2 | #include <subcmd/help.h> | 4 | #include <subcmd/help.h> |
3 | #include "../builtin.h" | 5 | #include "../builtin.h" |
4 | #include "levenshtein.h" | 6 | #include "levenshtein.h" |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index d1f19e0012d4..de15dbcdcecf 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -79,7 +79,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) | |||
79 | 79 | ||
80 | len = thread__comm_len(h->thread); | 80 | len = thread__comm_len(h->thread); |
81 | if (hists__new_col_len(hists, HISTC_COMM, len)) | 81 | if (hists__new_col_len(hists, HISTC_COMM, len)) |
82 | hists__set_col_len(hists, HISTC_THREAD, len + 6); | 82 | hists__set_col_len(hists, HISTC_THREAD, len + 8); |
83 | 83 | ||
84 | if (h->ms.map) { | 84 | if (h->ms.map) { |
85 | len = dso__name_len(h->ms.map->dso); | 85 | len = dso__name_len(h->ms.map->dso); |
@@ -352,86 +352,114 @@ void hists__delete_entries(struct hists *hists) | |||
352 | * histogram, sorted on item, collects periods | 352 | * histogram, sorted on item, collects periods |
353 | */ | 353 | */ |
354 | 354 | ||
355 | static struct hist_entry *hist_entry__new(struct hist_entry *template, | 355 | static int hist_entry__init(struct hist_entry *he, |
356 | bool sample_self) | 356 | struct hist_entry *template, |
357 | bool sample_self) | ||
357 | { | 358 | { |
358 | size_t callchain_size = 0; | 359 | *he = *template; |
359 | struct hist_entry *he; | ||
360 | 360 | ||
361 | if (symbol_conf.use_callchain) | 361 | if (symbol_conf.cumulate_callchain) { |
362 | callchain_size = sizeof(struct callchain_root); | 362 | he->stat_acc = malloc(sizeof(he->stat)); |
363 | if (he->stat_acc == NULL) | ||
364 | return -ENOMEM; | ||
365 | memcpy(he->stat_acc, &he->stat, sizeof(he->stat)); | ||
366 | if (!sample_self) | ||
367 | memset(&he->stat, 0, sizeof(he->stat)); | ||
368 | } | ||
369 | |||
370 | map__get(he->ms.map); | ||
371 | |||
372 | if (he->branch_info) { | ||
373 | /* | ||
374 | * This branch info is (a part of) allocated from | ||
375 | * sample__resolve_bstack() and will be freed after | ||
376 | * adding new entries. So we need to save a copy. | ||
377 | */ | ||
378 | he->branch_info = malloc(sizeof(*he->branch_info)); | ||
379 | if (he->branch_info == NULL) { | ||
380 | map__zput(he->ms.map); | ||
381 | free(he->stat_acc); | ||
382 | return -ENOMEM; | ||
383 | } | ||
384 | |||
385 | memcpy(he->branch_info, template->branch_info, | ||
386 | sizeof(*he->branch_info)); | ||
387 | |||
388 | map__get(he->branch_info->from.map); | ||
389 | map__get(he->branch_info->to.map); | ||
390 | } | ||
391 | |||
392 | if (he->mem_info) { | ||
393 | map__get(he->mem_info->iaddr.map); | ||
394 | map__get(he->mem_info->daddr.map); | ||
395 | } | ||
363 | 396 | ||
364 | he = zalloc(sizeof(*he) + callchain_size); | 397 | if (symbol_conf.use_callchain) |
398 | callchain_init(he->callchain); | ||
365 | 399 | ||
366 | if (he != NULL) { | 400 | if (he->raw_data) { |
367 | *he = *template; | 401 | he->raw_data = memdup(he->raw_data, he->raw_size); |
368 | 402 | ||
369 | if (symbol_conf.cumulate_callchain) { | 403 | if (he->raw_data == NULL) { |
370 | he->stat_acc = malloc(sizeof(he->stat)); | 404 | map__put(he->ms.map); |
371 | if (he->stat_acc == NULL) { | 405 | if (he->branch_info) { |
372 | free(he); | 406 | map__put(he->branch_info->from.map); |
373 | return NULL; | 407 | map__put(he->branch_info->to.map); |
408 | free(he->branch_info); | ||
409 | } | ||
410 | if (he->mem_info) { | ||
411 | map__put(he->mem_info->iaddr.map); | ||
412 | map__put(he->mem_info->daddr.map); | ||
374 | } | 413 | } |
375 | memcpy(he->stat_acc, &he->stat, sizeof(he->stat)); | 414 | free(he->stat_acc); |
376 | if (!sample_self) | 415 | return -ENOMEM; |
377 | memset(&he->stat, 0, sizeof(he->stat)); | ||
378 | } | 416 | } |
417 | } | ||
418 | INIT_LIST_HEAD(&he->pairs.node); | ||
419 | thread__get(he->thread); | ||
379 | 420 | ||
380 | map__get(he->ms.map); | 421 | if (!symbol_conf.report_hierarchy) |
422 | he->leaf = true; | ||
381 | 423 | ||
382 | if (he->branch_info) { | 424 | return 0; |
383 | /* | 425 | } |
384 | * This branch info is (a part of) allocated from | ||
385 | * sample__resolve_bstack() and will be freed after | ||
386 | * adding new entries. So we need to save a copy. | ||
387 | */ | ||
388 | he->branch_info = malloc(sizeof(*he->branch_info)); | ||
389 | if (he->branch_info == NULL) { | ||
390 | map__zput(he->ms.map); | ||
391 | free(he->stat_acc); | ||
392 | free(he); | ||
393 | return NULL; | ||
394 | } | ||
395 | 426 | ||
396 | memcpy(he->branch_info, template->branch_info, | 427 | static void *hist_entry__zalloc(size_t size) |
397 | sizeof(*he->branch_info)); | 428 | { |
429 | return zalloc(size + sizeof(struct hist_entry)); | ||
430 | } | ||
398 | 431 | ||
399 | map__get(he->branch_info->from.map); | 432 | static void hist_entry__free(void *ptr) |
400 | map__get(he->branch_info->to.map); | 433 | { |
401 | } | 434 | free(ptr); |
435 | } | ||
402 | 436 | ||
403 | if (he->mem_info) { | 437 | static struct hist_entry_ops default_ops = { |
404 | map__get(he->mem_info->iaddr.map); | 438 | .new = hist_entry__zalloc, |
405 | map__get(he->mem_info->daddr.map); | 439 | .free = hist_entry__free, |
406 | } | 440 | }; |
407 | 441 | ||
408 | if (symbol_conf.use_callchain) | 442 | static struct hist_entry *hist_entry__new(struct hist_entry *template, |
409 | callchain_init(he->callchain); | 443 | bool sample_self) |
444 | { | ||
445 | struct hist_entry_ops *ops = template->ops; | ||
446 | size_t callchain_size = 0; | ||
447 | struct hist_entry *he; | ||
448 | int err = 0; | ||
410 | 449 | ||
411 | if (he->raw_data) { | 450 | if (!ops) |
412 | he->raw_data = memdup(he->raw_data, he->raw_size); | 451 | ops = template->ops = &default_ops; |
413 | 452 | ||
414 | if (he->raw_data == NULL) { | 453 | if (symbol_conf.use_callchain) |
415 | map__put(he->ms.map); | 454 | callchain_size = sizeof(struct callchain_root); |
416 | if (he->branch_info) { | ||
417 | map__put(he->branch_info->from.map); | ||
418 | map__put(he->branch_info->to.map); | ||
419 | free(he->branch_info); | ||
420 | } | ||
421 | if (he->mem_info) { | ||
422 | map__put(he->mem_info->iaddr.map); | ||
423 | map__put(he->mem_info->daddr.map); | ||
424 | } | ||
425 | free(he->stat_acc); | ||
426 | free(he); | ||
427 | return NULL; | ||
428 | } | ||
429 | } | ||
430 | INIT_LIST_HEAD(&he->pairs.node); | ||
431 | thread__get(he->thread); | ||
432 | 455 | ||
433 | if (!symbol_conf.report_hierarchy) | 456 | he = ops->new(callchain_size); |
434 | he->leaf = true; | 457 | if (he) { |
458 | err = hist_entry__init(he, template, sample_self); | ||
459 | if (err) { | ||
460 | ops->free(he); | ||
461 | he = NULL; | ||
462 | } | ||
435 | } | 463 | } |
436 | 464 | ||
437 | return he; | 465 | return he; |
@@ -531,13 +559,15 @@ out: | |||
531 | return he; | 559 | return he; |
532 | } | 560 | } |
533 | 561 | ||
534 | struct hist_entry *__hists__add_entry(struct hists *hists, | 562 | static struct hist_entry* |
535 | struct addr_location *al, | 563 | __hists__add_entry(struct hists *hists, |
536 | struct symbol *sym_parent, | 564 | struct addr_location *al, |
537 | struct branch_info *bi, | 565 | struct symbol *sym_parent, |
538 | struct mem_info *mi, | 566 | struct branch_info *bi, |
539 | struct perf_sample *sample, | 567 | struct mem_info *mi, |
540 | bool sample_self) | 568 | struct perf_sample *sample, |
569 | bool sample_self, | ||
570 | struct hist_entry_ops *ops) | ||
541 | { | 571 | { |
542 | struct hist_entry entry = { | 572 | struct hist_entry entry = { |
543 | .thread = al->thread, | 573 | .thread = al->thread, |
@@ -564,11 +594,37 @@ struct hist_entry *__hists__add_entry(struct hists *hists, | |||
564 | .transaction = sample->transaction, | 594 | .transaction = sample->transaction, |
565 | .raw_data = sample->raw_data, | 595 | .raw_data = sample->raw_data, |
566 | .raw_size = sample->raw_size, | 596 | .raw_size = sample->raw_size, |
597 | .ops = ops, | ||
567 | }; | 598 | }; |
568 | 599 | ||
569 | return hists__findnew_entry(hists, &entry, al, sample_self); | 600 | return hists__findnew_entry(hists, &entry, al, sample_self); |
570 | } | 601 | } |
571 | 602 | ||
603 | struct hist_entry *hists__add_entry(struct hists *hists, | ||
604 | struct addr_location *al, | ||
605 | struct symbol *sym_parent, | ||
606 | struct branch_info *bi, | ||
607 | struct mem_info *mi, | ||
608 | struct perf_sample *sample, | ||
609 | bool sample_self) | ||
610 | { | ||
611 | return __hists__add_entry(hists, al, sym_parent, bi, mi, | ||
612 | sample, sample_self, NULL); | ||
613 | } | ||
614 | |||
615 | struct hist_entry *hists__add_entry_ops(struct hists *hists, | ||
616 | struct hist_entry_ops *ops, | ||
617 | struct addr_location *al, | ||
618 | struct symbol *sym_parent, | ||
619 | struct branch_info *bi, | ||
620 | struct mem_info *mi, | ||
621 | struct perf_sample *sample, | ||
622 | bool sample_self) | ||
623 | { | ||
624 | return __hists__add_entry(hists, al, sym_parent, bi, mi, | ||
625 | sample, sample_self, ops); | ||
626 | } | ||
627 | |||
572 | static int | 628 | static int |
573 | iter_next_nop_entry(struct hist_entry_iter *iter __maybe_unused, | 629 | iter_next_nop_entry(struct hist_entry_iter *iter __maybe_unused, |
574 | struct addr_location *al __maybe_unused) | 630 | struct addr_location *al __maybe_unused) |
@@ -622,8 +678,8 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al | |||
622 | */ | 678 | */ |
623 | sample->period = cost; | 679 | sample->period = cost; |
624 | 680 | ||
625 | he = __hists__add_entry(hists, al, iter->parent, NULL, mi, | 681 | he = hists__add_entry(hists, al, iter->parent, NULL, mi, |
626 | sample, true); | 682 | sample, true); |
627 | if (!he) | 683 | if (!he) |
628 | return -ENOMEM; | 684 | return -ENOMEM; |
629 | 685 | ||
@@ -727,8 +783,8 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a | |||
727 | sample->period = 1; | 783 | sample->period = 1; |
728 | sample->weight = bi->flags.cycles ? bi->flags.cycles : 1; | 784 | sample->weight = bi->flags.cycles ? bi->flags.cycles : 1; |
729 | 785 | ||
730 | he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL, | 786 | he = hists__add_entry(hists, al, iter->parent, &bi[i], NULL, |
731 | sample, true); | 787 | sample, true); |
732 | if (he == NULL) | 788 | if (he == NULL) |
733 | return -ENOMEM; | 789 | return -ENOMEM; |
734 | 790 | ||
@@ -764,8 +820,8 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location | |||
764 | struct perf_sample *sample = iter->sample; | 820 | struct perf_sample *sample = iter->sample; |
765 | struct hist_entry *he; | 821 | struct hist_entry *he; |
766 | 822 | ||
767 | he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, | 823 | he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, |
768 | sample, true); | 824 | sample, true); |
769 | if (he == NULL) | 825 | if (he == NULL) |
770 | return -ENOMEM; | 826 | return -ENOMEM; |
771 | 827 | ||
@@ -825,8 +881,8 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter, | |||
825 | struct hist_entry *he; | 881 | struct hist_entry *he; |
826 | int err = 0; | 882 | int err = 0; |
827 | 883 | ||
828 | he = __hists__add_entry(hists, al, iter->parent, NULL, NULL, | 884 | he = hists__add_entry(hists, al, iter->parent, NULL, NULL, |
829 | sample, true); | 885 | sample, true); |
830 | if (he == NULL) | 886 | if (he == NULL) |
831 | return -ENOMEM; | 887 | return -ENOMEM; |
832 | 888 | ||
@@ -900,8 +956,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter, | |||
900 | } | 956 | } |
901 | } | 957 | } |
902 | 958 | ||
903 | he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, | 959 | he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, |
904 | sample, false); | 960 | sample, false); |
905 | if (he == NULL) | 961 | if (he == NULL) |
906 | return -ENOMEM; | 962 | return -ENOMEM; |
907 | 963 | ||
@@ -1043,6 +1099,8 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) | |||
1043 | 1099 | ||
1044 | void hist_entry__delete(struct hist_entry *he) | 1100 | void hist_entry__delete(struct hist_entry *he) |
1045 | { | 1101 | { |
1102 | struct hist_entry_ops *ops = he->ops; | ||
1103 | |||
1046 | thread__zput(he->thread); | 1104 | thread__zput(he->thread); |
1047 | map__zput(he->ms.map); | 1105 | map__zput(he->ms.map); |
1048 | 1106 | ||
@@ -1067,7 +1125,7 @@ void hist_entry__delete(struct hist_entry *he) | |||
1067 | free_callchain(he->callchain); | 1125 | free_callchain(he->callchain); |
1068 | free(he->trace_output); | 1126 | free(he->trace_output); |
1069 | free(he->raw_data); | 1127 | free(he->raw_data); |
1070 | free(he); | 1128 | ops->free(he); |
1071 | } | 1129 | } |
1072 | 1130 | ||
1073 | /* | 1131 | /* |
@@ -1081,7 +1139,7 @@ int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp, | |||
1081 | struct perf_hpp_fmt *fmt, int printed) | 1139 | struct perf_hpp_fmt *fmt, int printed) |
1082 | { | 1140 | { |
1083 | if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) { | 1141 | if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) { |
1084 | const int width = fmt->width(fmt, hpp, hists_to_evsel(he->hists)); | 1142 | const int width = fmt->width(fmt, hpp, he->hists); |
1085 | if (printed < width) { | 1143 | if (printed < width) { |
1086 | advance_hpp(hpp, printed); | 1144 | advance_hpp(hpp, printed); |
1087 | printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " "); | 1145 | printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " "); |
@@ -1614,7 +1672,7 @@ static void __hists__insert_output_entry(struct rb_root *entries, | |||
1614 | } | 1672 | } |
1615 | 1673 | ||
1616 | static void output_resort(struct hists *hists, struct ui_progress *prog, | 1674 | static void output_resort(struct hists *hists, struct ui_progress *prog, |
1617 | bool use_callchain) | 1675 | bool use_callchain, hists__resort_cb_t cb) |
1618 | { | 1676 | { |
1619 | struct rb_root *root; | 1677 | struct rb_root *root; |
1620 | struct rb_node *next; | 1678 | struct rb_node *next; |
@@ -1653,6 +1711,9 @@ static void output_resort(struct hists *hists, struct ui_progress *prog, | |||
1653 | n = rb_entry(next, struct hist_entry, rb_node_in); | 1711 | n = rb_entry(next, struct hist_entry, rb_node_in); |
1654 | next = rb_next(&n->rb_node_in); | 1712 | next = rb_next(&n->rb_node_in); |
1655 | 1713 | ||
1714 | if (cb && cb(n)) | ||
1715 | continue; | ||
1716 | |||
1656 | __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain); | 1717 | __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain); |
1657 | hists__inc_stats(hists, n); | 1718 | hists__inc_stats(hists, n); |
1658 | 1719 | ||
@@ -1673,12 +1734,18 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro | |||
1673 | else | 1734 | else |
1674 | use_callchain = symbol_conf.use_callchain; | 1735 | use_callchain = symbol_conf.use_callchain; |
1675 | 1736 | ||
1676 | output_resort(evsel__hists(evsel), prog, use_callchain); | 1737 | output_resort(evsel__hists(evsel), prog, use_callchain, NULL); |
1677 | } | 1738 | } |
1678 | 1739 | ||
1679 | void hists__output_resort(struct hists *hists, struct ui_progress *prog) | 1740 | void hists__output_resort(struct hists *hists, struct ui_progress *prog) |
1680 | { | 1741 | { |
1681 | output_resort(hists, prog, symbol_conf.use_callchain); | 1742 | output_resort(hists, prog, symbol_conf.use_callchain, NULL); |
1743 | } | ||
1744 | |||
1745 | void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog, | ||
1746 | hists__resort_cb_t cb) | ||
1747 | { | ||
1748 | output_resort(hists, prog, symbol_conf.use_callchain, cb); | ||
1682 | } | 1749 | } |
1683 | 1750 | ||
1684 | static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd) | 1751 | static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd) |
@@ -2199,7 +2266,7 @@ size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp) | |||
2199 | struct perf_evsel *pos; | 2266 | struct perf_evsel *pos; |
2200 | size_t ret = 0; | 2267 | size_t ret = 0; |
2201 | 2268 | ||
2202 | evlist__for_each(evlist, pos) { | 2269 | evlist__for_each_entry(evlist, pos) { |
2203 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); | 2270 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); |
2204 | ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp); | 2271 | ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp); |
2205 | } | 2272 | } |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 7b54ccf1b737..0a1edf1ab450 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "ui/progress.h" | 10 | #include "ui/progress.h" |
11 | 11 | ||
12 | struct hist_entry; | 12 | struct hist_entry; |
13 | struct hist_entry_ops; | ||
13 | struct addr_location; | 14 | struct addr_location; |
14 | struct symbol; | 15 | struct symbol; |
15 | 16 | ||
@@ -120,13 +121,23 @@ extern const struct hist_iter_ops hist_iter_branch; | |||
120 | extern const struct hist_iter_ops hist_iter_mem; | 121 | extern const struct hist_iter_ops hist_iter_mem; |
121 | extern const struct hist_iter_ops hist_iter_cumulative; | 122 | extern const struct hist_iter_ops hist_iter_cumulative; |
122 | 123 | ||
123 | struct hist_entry *__hists__add_entry(struct hists *hists, | 124 | struct hist_entry *hists__add_entry(struct hists *hists, |
124 | struct addr_location *al, | 125 | struct addr_location *al, |
125 | struct symbol *parent, | 126 | struct symbol *parent, |
126 | struct branch_info *bi, | 127 | struct branch_info *bi, |
127 | struct mem_info *mi, | 128 | struct mem_info *mi, |
128 | struct perf_sample *sample, | 129 | struct perf_sample *sample, |
129 | bool sample_self); | 130 | bool sample_self); |
131 | |||
132 | struct hist_entry *hists__add_entry_ops(struct hists *hists, | ||
133 | struct hist_entry_ops *ops, | ||
134 | struct addr_location *al, | ||
135 | struct symbol *sym_parent, | ||
136 | struct branch_info *bi, | ||
137 | struct mem_info *mi, | ||
138 | struct perf_sample *sample, | ||
139 | bool sample_self); | ||
140 | |||
130 | int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, | 141 | int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, |
131 | int max_stack_depth, void *arg); | 142 | int max_stack_depth, void *arg); |
132 | 143 | ||
@@ -142,8 +153,12 @@ int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp, | |||
142 | struct perf_hpp_fmt *fmt, int printed); | 153 | struct perf_hpp_fmt *fmt, int printed); |
143 | void hist_entry__delete(struct hist_entry *he); | 154 | void hist_entry__delete(struct hist_entry *he); |
144 | 155 | ||
156 | typedef int (*hists__resort_cb_t)(struct hist_entry *he); | ||
157 | |||
145 | void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); | 158 | void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); |
146 | void hists__output_resort(struct hists *hists, struct ui_progress *prog); | 159 | void hists__output_resort(struct hists *hists, struct ui_progress *prog); |
160 | void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog, | ||
161 | hists__resort_cb_t cb); | ||
147 | int hists__collapse_resort(struct hists *hists, struct ui_progress *prog); | 162 | int hists__collapse_resort(struct hists *hists, struct ui_progress *prog); |
148 | 163 | ||
149 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); | 164 | void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); |
@@ -159,7 +174,8 @@ void events_stats__inc(struct events_stats *stats, u32 type); | |||
159 | size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); | 174 | size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); |
160 | 175 | ||
161 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | 176 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, |
162 | int max_cols, float min_pcnt, FILE *fp); | 177 | int max_cols, float min_pcnt, FILE *fp, |
178 | bool use_callchain); | ||
163 | size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp); | 179 | size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp); |
164 | 180 | ||
165 | void hists__filter_by_dso(struct hists *hists); | 181 | void hists__filter_by_dso(struct hists *hists); |
@@ -214,9 +230,9 @@ struct perf_hpp { | |||
214 | struct perf_hpp_fmt { | 230 | struct perf_hpp_fmt { |
215 | const char *name; | 231 | const char *name; |
216 | int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 232 | int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
217 | struct perf_evsel *evsel); | 233 | struct hists *hists); |
218 | int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 234 | int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
219 | struct perf_evsel *evsel); | 235 | struct hists *hists); |
220 | int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 236 | int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
221 | struct hist_entry *he); | 237 | struct hist_entry *he); |
222 | int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 238 | int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
diff --git a/tools/perf/util/include/asm/alternative-asm.h b/tools/perf/util/include/asm/alternative-asm.h deleted file mode 100644 index 3a3a0f16456a..000000000000 --- a/tools/perf/util/include/asm/alternative-asm.h +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | #ifndef _PERF_ASM_ALTERNATIVE_ASM_H | ||
2 | #define _PERF_ASM_ALTERNATIVE_ASM_H | ||
3 | |||
4 | /* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */ | ||
5 | |||
6 | #define altinstruction_entry # | ||
7 | #define ALTERNATIVE_2 # | ||
8 | |||
9 | #endif | ||
diff --git a/tools/perf/util/include/asm/byteorder.h b/tools/perf/util/include/asm/byteorder.h deleted file mode 100644 index 2a9bdc066307..000000000000 --- a/tools/perf/util/include/asm/byteorder.h +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | #include <asm/types.h> | ||
2 | #include "../../../../include/uapi/linux/swab.h" | ||
diff --git a/tools/perf/util/include/asm/unistd_32.h b/tools/perf/util/include/asm/unistd_32.h deleted file mode 100644 index 8b137891791f..000000000000 --- a/tools/perf/util/include/asm/unistd_32.h +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | |||
diff --git a/tools/perf/util/include/asm/unistd_64.h b/tools/perf/util/include/asm/unistd_64.h deleted file mode 100644 index 8b137891791f..000000000000 --- a/tools/perf/util/include/asm/unistd_64.h +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | |||
diff --git a/tools/perf/util/include/linux/const.h b/tools/perf/util/include/linux/const.h deleted file mode 100644 index c10a35e1afb8..000000000000 --- a/tools/perf/util/include/linux/const.h +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | #include "../../../../include/uapi/linux/const.h" | ||
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index 9df996085563..749e6f2e37ca 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c | |||
@@ -422,7 +422,8 @@ static int intel_bts_get_branch_type(struct intel_bts_queue *btsq, | |||
422 | } | 422 | } |
423 | 423 | ||
424 | static int intel_bts_process_buffer(struct intel_bts_queue *btsq, | 424 | static int intel_bts_process_buffer(struct intel_bts_queue *btsq, |
425 | struct auxtrace_buffer *buffer) | 425 | struct auxtrace_buffer *buffer, |
426 | struct thread *thread) | ||
426 | { | 427 | { |
427 | struct branch *branch; | 428 | struct branch *branch; |
428 | size_t sz, bsz = sizeof(struct branch); | 429 | size_t sz, bsz = sizeof(struct branch); |
@@ -444,6 +445,12 @@ static int intel_bts_process_buffer(struct intel_bts_queue *btsq, | |||
444 | if (!branch->from && !branch->to) | 445 | if (!branch->from && !branch->to) |
445 | continue; | 446 | continue; |
446 | intel_bts_get_branch_type(btsq, branch); | 447 | intel_bts_get_branch_type(btsq, branch); |
448 | if (btsq->bts->synth_opts.thread_stack) | ||
449 | thread_stack__event(thread, btsq->sample_flags, | ||
450 | le64_to_cpu(branch->from), | ||
451 | le64_to_cpu(branch->to), | ||
452 | btsq->intel_pt_insn.length, | ||
453 | buffer->buffer_nr + 1); | ||
447 | if (filter && !(filter & btsq->sample_flags)) | 454 | if (filter && !(filter & btsq->sample_flags)) |
448 | continue; | 455 | continue; |
449 | err = intel_bts_synth_branch_sample(btsq, branch); | 456 | err = intel_bts_synth_branch_sample(btsq, branch); |
@@ -507,12 +514,13 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp) | |||
507 | goto out_put; | 514 | goto out_put; |
508 | } | 515 | } |
509 | 516 | ||
510 | if (!btsq->bts->synth_opts.callchain && thread && | 517 | if (!btsq->bts->synth_opts.callchain && |
518 | !btsq->bts->synth_opts.thread_stack && thread && | ||
511 | (!old_buffer || btsq->bts->sampling_mode || | 519 | (!old_buffer || btsq->bts->sampling_mode || |
512 | (btsq->bts->snapshot_mode && !buffer->consecutive))) | 520 | (btsq->bts->snapshot_mode && !buffer->consecutive))) |
513 | thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1); | 521 | thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1); |
514 | 522 | ||
515 | err = intel_bts_process_buffer(btsq, buffer); | 523 | err = intel_bts_process_buffer(btsq, buffer, thread); |
516 | 524 | ||
517 | auxtrace_buffer__drop_data(buffer); | 525 | auxtrace_buffer__drop_data(buffer); |
518 | 526 | ||
@@ -777,7 +785,7 @@ static int intel_bts_synth_events(struct intel_bts *bts, | |||
777 | u64 id; | 785 | u64 id; |
778 | int err; | 786 | int err; |
779 | 787 | ||
780 | evlist__for_each(evlist, evsel) { | 788 | evlist__for_each_entry(evlist, evsel) { |
781 | if (evsel->attr.type == bts->pmu_type && evsel->ids) { | 789 | if (evsel->attr.type == bts->pmu_type && evsel->ids) { |
782 | found = true; | 790 | found = true; |
783 | break; | 791 | break; |
@@ -905,10 +913,14 @@ int intel_bts_process_auxtrace_info(union perf_event *event, | |||
905 | if (dump_trace) | 913 | if (dump_trace) |
906 | return 0; | 914 | return 0; |
907 | 915 | ||
908 | if (session->itrace_synth_opts && session->itrace_synth_opts->set) | 916 | if (session->itrace_synth_opts && session->itrace_synth_opts->set) { |
909 | bts->synth_opts = *session->itrace_synth_opts; | 917 | bts->synth_opts = *session->itrace_synth_opts; |
910 | else | 918 | } else { |
911 | itrace_synth_opts__set_default(&bts->synth_opts); | 919 | itrace_synth_opts__set_default(&bts->synth_opts); |
920 | if (session->itrace_synth_opts) | ||
921 | bts->synth_opts.thread_stack = | ||
922 | session->itrace_synth_opts->thread_stack; | ||
923 | } | ||
912 | 924 | ||
913 | if (bts->synth_opts.calls) | 925 | if (bts->synth_opts.calls) |
914 | bts->branches_filter |= PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | | 926 | bts->branches_filter |= PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | |
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build index 0611d619a42e..9b742ea8bfe8 100644 --- a/tools/perf/util/intel-pt-decoder/Build +++ b/tools/perf/util/intel-pt-decoder/Build | |||
@@ -7,8 +7,11 @@ $(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 | # Busybox's diff doesn't have -I, avoid warning in the case | ||
11 | |||
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 | 12 | $(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 && (( \ | 13 | @(diff -I 2>&1 | grep -q 'option requires an argument' && \ |
14 | 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 && \ | 15 | 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 && \ | 16 | 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 && \ | 17 | diff -B util/intel-pt-decoder/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \ |
diff --git a/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk b/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk index 517567347aac..54e961659514 100644 --- a/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk +++ b/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk | |||
@@ -72,12 +72,14 @@ BEGIN { | |||
72 | lprefix_expr = "\\((66|F2|F3)\\)" | 72 | lprefix_expr = "\\((66|F2|F3)\\)" |
73 | max_lprefix = 4 | 73 | max_lprefix = 4 |
74 | 74 | ||
75 | # All opcodes starting with lower-case 'v' or with (v1) superscript | 75 | # All opcodes starting with lower-case 'v', 'k' or with (v1) superscript |
76 | # accepts VEX prefix | 76 | # accepts VEX prefix |
77 | vexok_opcode_expr = "^v.*" | 77 | vexok_opcode_expr = "^[vk].*" |
78 | vexok_expr = "\\(v1\\)" | 78 | vexok_expr = "\\(v1\\)" |
79 | # All opcodes with (v) superscript supports *only* VEX prefix | 79 | # All opcodes with (v) superscript supports *only* VEX prefix |
80 | vexonly_expr = "\\(v\\)" | 80 | vexonly_expr = "\\(v\\)" |
81 | # All opcodes with (ev) superscript supports *only* EVEX prefix | ||
82 | evexonly_expr = "\\(ev\\)" | ||
81 | 83 | ||
82 | prefix_expr = "\\(Prefix\\)" | 84 | prefix_expr = "\\(Prefix\\)" |
83 | prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" | 85 | prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" |
@@ -95,6 +97,7 @@ BEGIN { | |||
95 | prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ" | 97 | prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ" |
96 | prefix_num["VEX+1byte"] = "INAT_PFX_VEX2" | 98 | prefix_num["VEX+1byte"] = "INAT_PFX_VEX2" |
97 | prefix_num["VEX+2byte"] = "INAT_PFX_VEX3" | 99 | prefix_num["VEX+2byte"] = "INAT_PFX_VEX3" |
100 | prefix_num["EVEX"] = "INAT_PFX_EVEX" | ||
98 | 101 | ||
99 | clear_vars() | 102 | clear_vars() |
100 | } | 103 | } |
@@ -319,7 +322,9 @@ function convert_operands(count,opnd, i,j,imm,mod) | |||
319 | flags = add_flags(flags, "INAT_MODRM") | 322 | flags = add_flags(flags, "INAT_MODRM") |
320 | 323 | ||
321 | # check VEX codes | 324 | # check VEX codes |
322 | if (match(ext, vexonly_expr)) | 325 | if (match(ext, evexonly_expr)) |
326 | flags = add_flags(flags, "INAT_VEXOK | INAT_EVEXONLY") | ||
327 | else if (match(ext, vexonly_expr)) | ||
323 | flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") | 328 | flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") |
324 | else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr)) | 329 | else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr)) |
325 | flags = add_flags(flags, "INAT_VEXOK") | 330 | flags = add_flags(flags, "INAT_VEXOK") |
diff --git a/tools/perf/util/intel-pt-decoder/inat.h b/tools/perf/util/intel-pt-decoder/inat.h index 611645e903a8..125ecd2a300d 100644 --- a/tools/perf/util/intel-pt-decoder/inat.h +++ b/tools/perf/util/intel-pt-decoder/inat.h | |||
@@ -48,6 +48,7 @@ | |||
48 | /* AVX VEX prefixes */ | 48 | /* AVX VEX prefixes */ |
49 | #define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */ | 49 | #define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */ |
50 | #define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */ | 50 | #define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */ |
51 | #define INAT_PFX_EVEX 15 /* EVEX prefix */ | ||
51 | 52 | ||
52 | #define INAT_LSTPFX_MAX 3 | 53 | #define INAT_LSTPFX_MAX 3 |
53 | #define INAT_LGCPFX_MAX 11 | 54 | #define INAT_LGCPFX_MAX 11 |
@@ -89,6 +90,7 @@ | |||
89 | #define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) | 90 | #define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) |
90 | #define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) | 91 | #define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) |
91 | #define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) | 92 | #define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) |
93 | #define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7)) | ||
92 | /* Attribute making macros for attribute tables */ | 94 | /* Attribute making macros for attribute tables */ |
93 | #define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS) | 95 | #define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS) |
94 | #define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS) | 96 | #define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS) |
@@ -141,7 +143,13 @@ static inline int inat_last_prefix_id(insn_attr_t attr) | |||
141 | static inline int inat_is_vex_prefix(insn_attr_t attr) | 143 | static inline int inat_is_vex_prefix(insn_attr_t attr) |
142 | { | 144 | { |
143 | attr &= INAT_PFX_MASK; | 145 | attr &= INAT_PFX_MASK; |
144 | return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3; | 146 | return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3 || |
147 | attr == INAT_PFX_EVEX; | ||
148 | } | ||
149 | |||
150 | static inline int inat_is_evex_prefix(insn_attr_t attr) | ||
151 | { | ||
152 | return (attr & INAT_PFX_MASK) == INAT_PFX_EVEX; | ||
145 | } | 153 | } |
146 | 154 | ||
147 | static inline int inat_is_vex3_prefix(insn_attr_t attr) | 155 | static inline int inat_is_vex3_prefix(insn_attr_t attr) |
@@ -216,6 +224,11 @@ static inline int inat_accept_vex(insn_attr_t attr) | |||
216 | 224 | ||
217 | static inline int inat_must_vex(insn_attr_t attr) | 225 | static inline int inat_must_vex(insn_attr_t attr) |
218 | { | 226 | { |
219 | return attr & INAT_VEXONLY; | 227 | return attr & (INAT_VEXONLY | INAT_EVEXONLY); |
228 | } | ||
229 | |||
230 | static inline int inat_must_evex(insn_attr_t attr) | ||
231 | { | ||
232 | return attr & INAT_EVEXONLY; | ||
220 | } | 233 | } |
221 | #endif | 234 | #endif |
diff --git a/tools/perf/util/intel-pt-decoder/insn.c b/tools/perf/util/intel-pt-decoder/insn.c index 9f26eae6c9f0..ca983e2bea8b 100644 --- a/tools/perf/util/intel-pt-decoder/insn.c +++ b/tools/perf/util/intel-pt-decoder/insn.c | |||
@@ -155,14 +155,24 @@ found: | |||
155 | /* | 155 | /* |
156 | * In 32-bits mode, if the [7:6] bits (mod bits of | 156 | * In 32-bits mode, if the [7:6] bits (mod bits of |
157 | * ModRM) on the second byte are not 11b, it is | 157 | * ModRM) on the second byte are not 11b, it is |
158 | * LDS or LES. | 158 | * LDS or LES or BOUND. |
159 | */ | 159 | */ |
160 | if (X86_MODRM_MOD(b2) != 3) | 160 | if (X86_MODRM_MOD(b2) != 3) |
161 | goto vex_end; | 161 | goto vex_end; |
162 | } | 162 | } |
163 | insn->vex_prefix.bytes[0] = b; | 163 | insn->vex_prefix.bytes[0] = b; |
164 | insn->vex_prefix.bytes[1] = b2; | 164 | insn->vex_prefix.bytes[1] = b2; |
165 | if (inat_is_vex3_prefix(attr)) { | 165 | if (inat_is_evex_prefix(attr)) { |
166 | b2 = peek_nbyte_next(insn_byte_t, insn, 2); | ||
167 | insn->vex_prefix.bytes[2] = b2; | ||
168 | b2 = peek_nbyte_next(insn_byte_t, insn, 3); | ||
169 | insn->vex_prefix.bytes[3] = b2; | ||
170 | insn->vex_prefix.nbytes = 4; | ||
171 | insn->next_byte += 4; | ||
172 | if (insn->x86_64 && X86_VEX_W(b2)) | ||
173 | /* VEX.W overrides opnd_size */ | ||
174 | insn->opnd_bytes = 8; | ||
175 | } else if (inat_is_vex3_prefix(attr)) { | ||
166 | b2 = peek_nbyte_next(insn_byte_t, insn, 2); | 176 | b2 = peek_nbyte_next(insn_byte_t, insn, 2); |
167 | insn->vex_prefix.bytes[2] = b2; | 177 | insn->vex_prefix.bytes[2] = b2; |
168 | insn->vex_prefix.nbytes = 3; | 178 | insn->vex_prefix.nbytes = 3; |
@@ -221,7 +231,9 @@ void insn_get_opcode(struct insn *insn) | |||
221 | m = insn_vex_m_bits(insn); | 231 | m = insn_vex_m_bits(insn); |
222 | p = insn_vex_p_bits(insn); | 232 | p = insn_vex_p_bits(insn); |
223 | insn->attr = inat_get_avx_attribute(op, m, p); | 233 | insn->attr = inat_get_avx_attribute(op, m, p); |
224 | if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr)) | 234 | if ((inat_must_evex(insn->attr) && !insn_is_evex(insn)) || |
235 | (!inat_accept_vex(insn->attr) && | ||
236 | !inat_is_group(insn->attr))) | ||
225 | insn->attr = 0; /* This instruction is bad */ | 237 | insn->attr = 0; /* This instruction is bad */ |
226 | goto end; /* VEX has only 1 byte for opcode */ | 238 | goto end; /* VEX has only 1 byte for opcode */ |
227 | } | 239 | } |
diff --git a/tools/perf/util/intel-pt-decoder/insn.h b/tools/perf/util/intel-pt-decoder/insn.h index dd12da0f4593..e23578c7b1be 100644 --- a/tools/perf/util/intel-pt-decoder/insn.h +++ b/tools/perf/util/intel-pt-decoder/insn.h | |||
@@ -91,6 +91,7 @@ struct insn { | |||
91 | #define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */ | 91 | #define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */ |
92 | #define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */ | 92 | #define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */ |
93 | /* VEX bit fields */ | 93 | /* VEX bit fields */ |
94 | #define X86_EVEX_M(vex) ((vex) & 0x03) /* EVEX Byte1 */ | ||
94 | #define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */ | 95 | #define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */ |
95 | #define X86_VEX2_M 1 /* VEX2.M always 1 */ | 96 | #define X86_VEX2_M 1 /* VEX2.M always 1 */ |
96 | #define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */ | 97 | #define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */ |
@@ -133,6 +134,13 @@ static inline int insn_is_avx(struct insn *insn) | |||
133 | return (insn->vex_prefix.value != 0); | 134 | return (insn->vex_prefix.value != 0); |
134 | } | 135 | } |
135 | 136 | ||
137 | static inline int insn_is_evex(struct insn *insn) | ||
138 | { | ||
139 | if (!insn->prefixes.got) | ||
140 | insn_get_prefixes(insn); | ||
141 | return (insn->vex_prefix.nbytes == 4); | ||
142 | } | ||
143 | |||
136 | /* Ensure this instruction is decoded completely */ | 144 | /* Ensure this instruction is decoded completely */ |
137 | static inline int insn_complete(struct insn *insn) | 145 | static inline int insn_complete(struct insn *insn) |
138 | { | 146 | { |
@@ -144,8 +152,10 @@ static inline insn_byte_t insn_vex_m_bits(struct insn *insn) | |||
144 | { | 152 | { |
145 | if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */ | 153 | if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */ |
146 | return X86_VEX2_M; | 154 | return X86_VEX2_M; |
147 | else | 155 | else if (insn->vex_prefix.nbytes == 3) /* 3 bytes VEX */ |
148 | return X86_VEX3_M(insn->vex_prefix.bytes[1]); | 156 | return X86_VEX3_M(insn->vex_prefix.bytes[1]); |
157 | else /* EVEX */ | ||
158 | return X86_EVEX_M(insn->vex_prefix.bytes[1]); | ||
149 | } | 159 | } |
150 | 160 | ||
151 | static inline insn_byte_t insn_vex_p_bits(struct insn *insn) | 161 | static inline insn_byte_t insn_vex_p_bits(struct insn *insn) |
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 d388de72eaca..767be7c76034 100644 --- a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt +++ b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt | |||
@@ -13,12 +13,17 @@ | |||
13 | # opcode: escape # escaped-name | 13 | # opcode: escape # escaped-name |
14 | # EndTable | 14 | # EndTable |
15 | # | 15 | # |
16 | # mnemonics that begin with lowercase 'v' accept a VEX or EVEX prefix | ||
17 | # mnemonics that begin with lowercase 'k' accept a VEX prefix | ||
18 | # | ||
16 | #<group maps> | 19 | #<group maps> |
17 | # GrpTable: GrpXXX | 20 | # GrpTable: GrpXXX |
18 | # reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...] | 21 | # reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...] |
19 | # EndTable | 22 | # EndTable |
20 | # | 23 | # |
21 | # AVX Superscripts | 24 | # AVX Superscripts |
25 | # (ev): this opcode requires EVEX prefix. | ||
26 | # (evo): this opcode is changed by EVEX prefix (EVEX opcode) | ||
22 | # (v): this opcode requires VEX prefix. | 27 | # (v): this opcode requires VEX prefix. |
23 | # (v1): this opcode only supports 128bit VEX. | 28 | # (v1): this opcode only supports 128bit VEX. |
24 | # | 29 | # |
@@ -137,7 +142,7 @@ AVXcode: | |||
137 | # 0x60 - 0x6f | 142 | # 0x60 - 0x6f |
138 | 60: PUSHA/PUSHAD (i64) | 143 | 60: PUSHA/PUSHAD (i64) |
139 | 61: POPA/POPAD (i64) | 144 | 61: POPA/POPAD (i64) |
140 | 62: BOUND Gv,Ma (i64) | 145 | 62: BOUND Gv,Ma (i64) | EVEX (Prefix) |
141 | 63: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64) | 146 | 63: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64) |
142 | 64: SEG=FS (Prefix) | 147 | 64: SEG=FS (Prefix) |
143 | 65: SEG=GS (Prefix) | 148 | 65: SEG=GS (Prefix) |
@@ -399,17 +404,17 @@ AVXcode: 1 | |||
399 | 3f: | 404 | 3f: |
400 | # 0x0f 0x40-0x4f | 405 | # 0x0f 0x40-0x4f |
401 | 40: CMOVO Gv,Ev | 406 | 40: CMOVO Gv,Ev |
402 | 41: CMOVNO Gv,Ev | 407 | 41: CMOVNO Gv,Ev | kandw/q Vk,Hk,Uk | kandb/d Vk,Hk,Uk (66) |
403 | 42: CMOVB/C/NAE Gv,Ev | 408 | 42: CMOVB/C/NAE Gv,Ev | kandnw/q Vk,Hk,Uk | kandnb/d Vk,Hk,Uk (66) |
404 | 43: CMOVAE/NB/NC Gv,Ev | 409 | 43: CMOVAE/NB/NC Gv,Ev |
405 | 44: CMOVE/Z Gv,Ev | 410 | 44: CMOVE/Z Gv,Ev | knotw/q Vk,Uk | knotb/d Vk,Uk (66) |
406 | 45: CMOVNE/NZ Gv,Ev | 411 | 45: CMOVNE/NZ Gv,Ev | korw/q Vk,Hk,Uk | korb/d Vk,Hk,Uk (66) |
407 | 46: CMOVBE/NA Gv,Ev | 412 | 46: CMOVBE/NA Gv,Ev | kxnorw/q Vk,Hk,Uk | kxnorb/d Vk,Hk,Uk (66) |
408 | 47: CMOVA/NBE Gv,Ev | 413 | 47: CMOVA/NBE Gv,Ev | kxorw/q Vk,Hk,Uk | kxorb/d Vk,Hk,Uk (66) |
409 | 48: CMOVS Gv,Ev | 414 | 48: CMOVS Gv,Ev |
410 | 49: CMOVNS Gv,Ev | 415 | 49: CMOVNS Gv,Ev |
411 | 4a: CMOVP/PE Gv,Ev | 416 | 4a: CMOVP/PE Gv,Ev | kaddw/q Vk,Hk,Uk | kaddb/d Vk,Hk,Uk (66) |
412 | 4b: CMOVNP/PO Gv,Ev | 417 | 4b: CMOVNP/PO Gv,Ev | kunpckbw Vk,Hk,Uk (66) | kunpckwd/dq Vk,Hk,Uk |
413 | 4c: CMOVL/NGE Gv,Ev | 418 | 4c: CMOVL/NGE Gv,Ev |
414 | 4d: CMOVNL/GE Gv,Ev | 419 | 4d: CMOVNL/GE Gv,Ev |
415 | 4e: CMOVLE/NG Gv,Ev | 420 | 4e: CMOVLE/NG Gv,Ev |
@@ -426,7 +431,7 @@ AVXcode: 1 | |||
426 | 58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1) | 431 | 58: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1) |
427 | 59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1) | 432 | 59: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1) |
428 | 5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1) | 433 | 5a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1) |
429 | 5b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3) | 434 | 5b: vcvtdq2ps Vps,Wdq | vcvtqq2ps Vps,Wqq (evo) | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3) |
430 | 5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1) | 435 | 5c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1) |
431 | 5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1) | 436 | 5d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1) |
432 | 5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1) | 437 | 5e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1) |
@@ -447,7 +452,7 @@ AVXcode: 1 | |||
447 | 6c: vpunpcklqdq Vx,Hx,Wx (66),(v1) | 452 | 6c: vpunpcklqdq Vx,Hx,Wx (66),(v1) |
448 | 6d: vpunpckhqdq Vx,Hx,Wx (66),(v1) | 453 | 6d: vpunpckhqdq Vx,Hx,Wx (66),(v1) |
449 | 6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1) | 454 | 6e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1) |
450 | 6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3) | 455 | 6f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqa32/64 Vx,Wx (66),(evo) | vmovdqu Vx,Wx (F3) | vmovdqu32/64 Vx,Wx (F3),(evo) | vmovdqu8/16 Vx,Wx (F2),(ev) |
451 | # 0x0f 0x70-0x7f | 456 | # 0x0f 0x70-0x7f |
452 | 70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1) | 457 | 70: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1) |
453 | 71: Grp12 (1A) | 458 | 71: Grp12 (1A) |
@@ -458,14 +463,14 @@ AVXcode: 1 | |||
458 | 76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1) | 463 | 76: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1) |
459 | # Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX. | 464 | # Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX. |
460 | 77: emms | vzeroupper | vzeroall | 465 | 77: emms | vzeroupper | vzeroall |
461 | 78: VMREAD Ey,Gy | 466 | 78: VMREAD Ey,Gy | vcvttps2udq/pd2udq Vx,Wpd (evo) | vcvttsd2usi Gv,Wx (F2),(ev) | vcvttss2usi Gv,Wx (F3),(ev) | vcvttps2uqq/pd2uqq Vx,Wx (66),(ev) |
462 | 79: VMWRITE Gy,Ey | 467 | 79: VMWRITE Gy,Ey | vcvtps2udq/pd2udq Vx,Wpd (evo) | vcvtsd2usi Gv,Wx (F2),(ev) | vcvtss2usi Gv,Wx (F3),(ev) | vcvtps2uqq/pd2uqq Vx,Wx (66),(ev) |
463 | 7a: | 468 | 7a: vcvtudq2pd/uqq2pd Vpd,Wx (F3),(ev) | vcvtudq2ps/uqq2ps Vpd,Wx (F2),(ev) | vcvttps2qq/pd2qq Vx,Wx (66),(ev) |
464 | 7b: | 469 | 7b: vcvtusi2sd Vpd,Hpd,Ev (F2),(ev) | vcvtusi2ss Vps,Hps,Ev (F3),(ev) | vcvtps2qq/pd2qq Vx,Wx (66),(ev) |
465 | 7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2) | 470 | 7c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2) |
466 | 7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2) | 471 | 7d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2) |
467 | 7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1) | 472 | 7e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1) |
468 | 7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3) | 473 | 7f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqa32/64 Wx,Vx (66),(evo) | vmovdqu Wx,Vx (F3) | vmovdqu32/64 Wx,Vx (F3),(evo) | vmovdqu8/16 Wx,Vx (F2),(ev) |
469 | # 0x0f 0x80-0x8f | 474 | # 0x0f 0x80-0x8f |
470 | # Note: "forced64" is Intel CPU behavior (see comment about CALL insn). | 475 | # Note: "forced64" is Intel CPU behavior (see comment about CALL insn). |
471 | 80: JO Jz (f64) | 476 | 80: JO Jz (f64) |
@@ -485,16 +490,16 @@ AVXcode: 1 | |||
485 | 8e: JLE/JNG Jz (f64) | 490 | 8e: JLE/JNG Jz (f64) |
486 | 8f: JNLE/JG Jz (f64) | 491 | 8f: JNLE/JG Jz (f64) |
487 | # 0x0f 0x90-0x9f | 492 | # 0x0f 0x90-0x9f |
488 | 90: SETO Eb | 493 | 90: SETO Eb | kmovw/q Vk,Wk | kmovb/d Vk,Wk (66) |
489 | 91: SETNO Eb | 494 | 91: SETNO Eb | kmovw/q Mv,Vk | kmovb/d Mv,Vk (66) |
490 | 92: SETB/C/NAE Eb | 495 | 92: SETB/C/NAE Eb | kmovw Vk,Rv | kmovb Vk,Rv (66) | kmovq/d Vk,Rv (F2) |
491 | 93: SETAE/NB/NC Eb | 496 | 93: SETAE/NB/NC Eb | kmovw Gv,Uk | kmovb Gv,Uk (66) | kmovq/d Gv,Uk (F2) |
492 | 94: SETE/Z Eb | 497 | 94: SETE/Z Eb |
493 | 95: SETNE/NZ Eb | 498 | 95: SETNE/NZ Eb |
494 | 96: SETBE/NA Eb | 499 | 96: SETBE/NA Eb |
495 | 97: SETA/NBE Eb | 500 | 97: SETA/NBE Eb |
496 | 98: SETS Eb | 501 | 98: SETS Eb | kortestw/q Vk,Uk | kortestb/d Vk,Uk (66) |
497 | 99: SETNS Eb | 502 | 99: SETNS Eb | ktestw/q Vk,Uk | ktestb/d Vk,Uk (66) |
498 | 9a: SETP/PE Eb | 503 | 9a: SETP/PE Eb |
499 | 9b: SETNP/PO Eb | 504 | 9b: SETNP/PO Eb |
500 | 9c: SETL/NGE Eb | 505 | 9c: SETL/NGE Eb |
@@ -564,11 +569,11 @@ d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1) | |||
564 | d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1) | 569 | d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1) |
565 | d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1) | 570 | d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1) |
566 | da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1) | 571 | da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1) |
567 | db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1) | 572 | db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1) | vpandd/q Vx,Hx,Wx (66),(evo) |
568 | dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1) | 573 | dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1) |
569 | dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1) | 574 | dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1) |
570 | de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1) | 575 | de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1) |
571 | df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1) | 576 | df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1) | vpandnd/q Vx,Hx,Wx (66),(evo) |
572 | # 0x0f 0xe0-0xef | 577 | # 0x0f 0xe0-0xef |
573 | e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1) | 578 | e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1) |
574 | e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1) | 579 | e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1) |
@@ -576,16 +581,16 @@ e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1) | |||
576 | e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1) | 581 | e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1) |
577 | e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1) | 582 | e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1) |
578 | e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1) | 583 | e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1) |
579 | e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2) | 584 | e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtdq2pd/qq2pd Vx,Wdq (F3),(evo) | vcvtpd2dq Vx,Wpd (F2) |
580 | e7: movntq Mq,Pq | vmovntdq Mx,Vx (66) | 585 | e7: movntq Mq,Pq | vmovntdq Mx,Vx (66) |
581 | e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1) | 586 | e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1) |
582 | e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1) | 587 | e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1) |
583 | ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1) | 588 | ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1) |
584 | eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1) | 589 | eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1) | vpord/q Vx,Hx,Wx (66),(evo) |
585 | ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1) | 590 | ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1) |
586 | ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1) | 591 | ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1) |
587 | ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1) | 592 | ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1) |
588 | ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1) | 593 | ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1) | vpxord/q Vx,Hx,Wx (66),(evo) |
589 | # 0x0f 0xf0-0xff | 594 | # 0x0f 0xf0-0xff |
590 | f0: vlddqu Vx,Mx (F2) | 595 | f0: vlddqu Vx,Mx (F2) |
591 | f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1) | 596 | f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1) |
@@ -626,81 +631,105 @@ AVXcode: 2 | |||
626 | 0e: vtestps Vx,Wx (66),(v) | 631 | 0e: vtestps Vx,Wx (66),(v) |
627 | 0f: vtestpd Vx,Wx (66),(v) | 632 | 0f: vtestpd Vx,Wx (66),(v) |
628 | # 0x0f 0x38 0x10-0x1f | 633 | # 0x0f 0x38 0x10-0x1f |
629 | 10: pblendvb Vdq,Wdq (66) | 634 | 10: pblendvb Vdq,Wdq (66) | vpsrlvw Vx,Hx,Wx (66),(evo) | vpmovuswb Wx,Vx (F3),(ev) |
630 | 11: | 635 | 11: vpmovusdb Wx,Vd (F3),(ev) | vpsravw Vx,Hx,Wx (66),(ev) |
631 | 12: | 636 | 12: vpmovusqb Wx,Vq (F3),(ev) | vpsllvw Vx,Hx,Wx (66),(ev) |
632 | 13: vcvtph2ps Vx,Wx,Ib (66),(v) | 637 | 13: vcvtph2ps Vx,Wx (66),(v) | vpmovusdw Wx,Vd (F3),(ev) |
633 | 14: blendvps Vdq,Wdq (66) | 638 | 14: blendvps Vdq,Wdq (66) | vpmovusqw Wx,Vq (F3),(ev) | vprorvd/q Vx,Hx,Wx (66),(evo) |
634 | 15: blendvpd Vdq,Wdq (66) | 639 | 15: blendvpd Vdq,Wdq (66) | vpmovusqd Wx,Vq (F3),(ev) | vprolvd/q Vx,Hx,Wx (66),(evo) |
635 | 16: vpermps Vqq,Hqq,Wqq (66),(v) | 640 | 16: vpermps Vqq,Hqq,Wqq (66),(v) | vpermps/d Vqq,Hqq,Wqq (66),(evo) |
636 | 17: vptest Vx,Wx (66) | 641 | 17: vptest Vx,Wx (66) |
637 | 18: vbroadcastss Vx,Wd (66),(v) | 642 | 18: vbroadcastss Vx,Wd (66),(v) |
638 | 19: vbroadcastsd Vqq,Wq (66),(v) | 643 | 19: vbroadcastsd Vqq,Wq (66),(v) | vbroadcastf32x2 Vqq,Wq (66),(evo) |
639 | 1a: vbroadcastf128 Vqq,Mdq (66),(v) | 644 | 1a: vbroadcastf128 Vqq,Mdq (66),(v) | vbroadcastf32x4/64x2 Vqq,Wq (66),(evo) |
640 | 1b: | 645 | 1b: vbroadcastf32x8/64x4 Vqq,Mdq (66),(ev) |
641 | 1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1) | 646 | 1c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1) |
642 | 1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1) | 647 | 1d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1) |
643 | 1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1) | 648 | 1e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1) |
644 | 1f: | 649 | 1f: vpabsq Vx,Wx (66),(ev) |
645 | # 0x0f 0x38 0x20-0x2f | 650 | # 0x0f 0x38 0x20-0x2f |
646 | 20: vpmovsxbw Vx,Ux/Mq (66),(v1) | 651 | 20: vpmovsxbw Vx,Ux/Mq (66),(v1) | vpmovswb Wx,Vx (F3),(ev) |
647 | 21: vpmovsxbd Vx,Ux/Md (66),(v1) | 652 | 21: vpmovsxbd Vx,Ux/Md (66),(v1) | vpmovsdb Wx,Vd (F3),(ev) |
648 | 22: vpmovsxbq Vx,Ux/Mw (66),(v1) | 653 | 22: vpmovsxbq Vx,Ux/Mw (66),(v1) | vpmovsqb Wx,Vq (F3),(ev) |
649 | 23: vpmovsxwd Vx,Ux/Mq (66),(v1) | 654 | 23: vpmovsxwd Vx,Ux/Mq (66),(v1) | vpmovsdw Wx,Vd (F3),(ev) |
650 | 24: vpmovsxwq Vx,Ux/Md (66),(v1) | 655 | 24: vpmovsxwq Vx,Ux/Md (66),(v1) | vpmovsqw Wx,Vq (F3),(ev) |
651 | 25: vpmovsxdq Vx,Ux/Mq (66),(v1) | 656 | 25: vpmovsxdq Vx,Ux/Mq (66),(v1) | vpmovsqd Wx,Vq (F3),(ev) |
652 | 26: | 657 | 26: vptestmb/w Vk,Hx,Wx (66),(ev) | vptestnmb/w Vk,Hx,Wx (F3),(ev) |
653 | 27: | 658 | 27: vptestmd/q Vk,Hx,Wx (66),(ev) | vptestnmd/q Vk,Hx,Wx (F3),(ev) |
654 | 28: vpmuldq Vx,Hx,Wx (66),(v1) | 659 | 28: vpmuldq Vx,Hx,Wx (66),(v1) | vpmovm2b/w Vx,Uk (F3),(ev) |
655 | 29: vpcmpeqq Vx,Hx,Wx (66),(v1) | 660 | 29: vpcmpeqq Vx,Hx,Wx (66),(v1) | vpmovb2m/w2m Vk,Ux (F3),(ev) |
656 | 2a: vmovntdqa Vx,Mx (66),(v1) | 661 | 2a: vmovntdqa Vx,Mx (66),(v1) | vpbroadcastmb2q Vx,Uk (F3),(ev) |
657 | 2b: vpackusdw Vx,Hx,Wx (66),(v1) | 662 | 2b: vpackusdw Vx,Hx,Wx (66),(v1) |
658 | 2c: vmaskmovps Vx,Hx,Mx (66),(v) | 663 | 2c: vmaskmovps Vx,Hx,Mx (66),(v) | vscalefps/d Vx,Hx,Wx (66),(evo) |
659 | 2d: vmaskmovpd Vx,Hx,Mx (66),(v) | 664 | 2d: vmaskmovpd Vx,Hx,Mx (66),(v) | vscalefss/d Vx,Hx,Wx (66),(evo) |
660 | 2e: vmaskmovps Mx,Hx,Vx (66),(v) | 665 | 2e: vmaskmovps Mx,Hx,Vx (66),(v) |
661 | 2f: vmaskmovpd Mx,Hx,Vx (66),(v) | 666 | 2f: vmaskmovpd Mx,Hx,Vx (66),(v) |
662 | # 0x0f 0x38 0x30-0x3f | 667 | # 0x0f 0x38 0x30-0x3f |
663 | 30: vpmovzxbw Vx,Ux/Mq (66),(v1) | 668 | 30: vpmovzxbw Vx,Ux/Mq (66),(v1) | vpmovwb Wx,Vx (F3),(ev) |
664 | 31: vpmovzxbd Vx,Ux/Md (66),(v1) | 669 | 31: vpmovzxbd Vx,Ux/Md (66),(v1) | vpmovdb Wx,Vd (F3),(ev) |
665 | 32: vpmovzxbq Vx,Ux/Mw (66),(v1) | 670 | 32: vpmovzxbq Vx,Ux/Mw (66),(v1) | vpmovqb Wx,Vq (F3),(ev) |
666 | 33: vpmovzxwd Vx,Ux/Mq (66),(v1) | 671 | 33: vpmovzxwd Vx,Ux/Mq (66),(v1) | vpmovdw Wx,Vd (F3),(ev) |
667 | 34: vpmovzxwq Vx,Ux/Md (66),(v1) | 672 | 34: vpmovzxwq Vx,Ux/Md (66),(v1) | vpmovqw Wx,Vq (F3),(ev) |
668 | 35: vpmovzxdq Vx,Ux/Mq (66),(v1) | 673 | 35: vpmovzxdq Vx,Ux/Mq (66),(v1) | vpmovqd Wx,Vq (F3),(ev) |
669 | 36: vpermd Vqq,Hqq,Wqq (66),(v) | 674 | 36: vpermd Vqq,Hqq,Wqq (66),(v) | vpermd/q Vqq,Hqq,Wqq (66),(evo) |
670 | 37: vpcmpgtq Vx,Hx,Wx (66),(v1) | 675 | 37: vpcmpgtq Vx,Hx,Wx (66),(v1) |
671 | 38: vpminsb Vx,Hx,Wx (66),(v1) | 676 | 38: vpminsb Vx,Hx,Wx (66),(v1) | vpmovm2d/q Vx,Uk (F3),(ev) |
672 | 39: vpminsd Vx,Hx,Wx (66),(v1) | 677 | 39: vpminsd Vx,Hx,Wx (66),(v1) | vpminsd/q Vx,Hx,Wx (66),(evo) | vpmovd2m/q2m Vk,Ux (F3),(ev) |
673 | 3a: vpminuw Vx,Hx,Wx (66),(v1) | 678 | 3a: vpminuw Vx,Hx,Wx (66),(v1) | vpbroadcastmw2d Vx,Uk (F3),(ev) |
674 | 3b: vpminud Vx,Hx,Wx (66),(v1) | 679 | 3b: vpminud Vx,Hx,Wx (66),(v1) | vpminud/q Vx,Hx,Wx (66),(evo) |
675 | 3c: vpmaxsb Vx,Hx,Wx (66),(v1) | 680 | 3c: vpmaxsb Vx,Hx,Wx (66),(v1) |
676 | 3d: vpmaxsd Vx,Hx,Wx (66),(v1) | 681 | 3d: vpmaxsd Vx,Hx,Wx (66),(v1) | vpmaxsd/q Vx,Hx,Wx (66),(evo) |
677 | 3e: vpmaxuw Vx,Hx,Wx (66),(v1) | 682 | 3e: vpmaxuw Vx,Hx,Wx (66),(v1) |
678 | 3f: vpmaxud Vx,Hx,Wx (66),(v1) | 683 | 3f: vpmaxud Vx,Hx,Wx (66),(v1) | vpmaxud/q Vx,Hx,Wx (66),(evo) |
679 | # 0x0f 0x38 0x40-0x8f | 684 | # 0x0f 0x38 0x40-0x8f |
680 | 40: vpmulld Vx,Hx,Wx (66),(v1) | 685 | 40: vpmulld Vx,Hx,Wx (66),(v1) | vpmulld/q Vx,Hx,Wx (66),(evo) |
681 | 41: vphminposuw Vdq,Wdq (66),(v1) | 686 | 41: vphminposuw Vdq,Wdq (66),(v1) |
682 | 42: | 687 | 42: vgetexpps/d Vx,Wx (66),(ev) |
683 | 43: | 688 | 43: vgetexpss/d Vx,Hx,Wx (66),(ev) |
684 | 44: | 689 | 44: vplzcntd/q Vx,Wx (66),(ev) |
685 | 45: vpsrlvd/q Vx,Hx,Wx (66),(v) | 690 | 45: vpsrlvd/q Vx,Hx,Wx (66),(v) |
686 | 46: vpsravd Vx,Hx,Wx (66),(v) | 691 | 46: vpsravd Vx,Hx,Wx (66),(v) | vpsravd/q Vx,Hx,Wx (66),(evo) |
687 | 47: vpsllvd/q Vx,Hx,Wx (66),(v) | 692 | 47: vpsllvd/q Vx,Hx,Wx (66),(v) |
688 | # Skip 0x48-0x57 | 693 | # Skip 0x48-0x4b |
694 | 4c: vrcp14ps/d Vpd,Wpd (66),(ev) | ||
695 | 4d: vrcp14ss/d Vsd,Hpd,Wsd (66),(ev) | ||
696 | 4e: vrsqrt14ps/d Vpd,Wpd (66),(ev) | ||
697 | 4f: vrsqrt14ss/d Vsd,Hsd,Wsd (66),(ev) | ||
698 | # Skip 0x50-0x57 | ||
689 | 58: vpbroadcastd Vx,Wx (66),(v) | 699 | 58: vpbroadcastd Vx,Wx (66),(v) |
690 | 59: vpbroadcastq Vx,Wx (66),(v) | 700 | 59: vpbroadcastq Vx,Wx (66),(v) | vbroadcasti32x2 Vx,Wx (66),(evo) |
691 | 5a: vbroadcasti128 Vqq,Mdq (66),(v) | 701 | 5a: vbroadcasti128 Vqq,Mdq (66),(v) | vbroadcasti32x4/64x2 Vx,Wx (66),(evo) |
692 | # Skip 0x5b-0x77 | 702 | 5b: vbroadcasti32x8/64x4 Vqq,Mdq (66),(ev) |
703 | # Skip 0x5c-0x63 | ||
704 | 64: vpblendmd/q Vx,Hx,Wx (66),(ev) | ||
705 | 65: vblendmps/d Vx,Hx,Wx (66),(ev) | ||
706 | 66: vpblendmb/w Vx,Hx,Wx (66),(ev) | ||
707 | # Skip 0x67-0x74 | ||
708 | 75: vpermi2b/w Vx,Hx,Wx (66),(ev) | ||
709 | 76: vpermi2d/q Vx,Hx,Wx (66),(ev) | ||
710 | 77: vpermi2ps/d Vx,Hx,Wx (66),(ev) | ||
693 | 78: vpbroadcastb Vx,Wx (66),(v) | 711 | 78: vpbroadcastb Vx,Wx (66),(v) |
694 | 79: vpbroadcastw Vx,Wx (66),(v) | 712 | 79: vpbroadcastw Vx,Wx (66),(v) |
695 | # Skip 0x7a-0x7f | 713 | 7a: vpbroadcastb Vx,Rv (66),(ev) |
714 | 7b: vpbroadcastw Vx,Rv (66),(ev) | ||
715 | 7c: vpbroadcastd/q Vx,Rv (66),(ev) | ||
716 | 7d: vpermt2b/w Vx,Hx,Wx (66),(ev) | ||
717 | 7e: vpermt2d/q Vx,Hx,Wx (66),(ev) | ||
718 | 7f: vpermt2ps/d Vx,Hx,Wx (66),(ev) | ||
696 | 80: INVEPT Gy,Mdq (66) | 719 | 80: INVEPT Gy,Mdq (66) |
697 | 81: INVPID Gy,Mdq (66) | 720 | 81: INVPID Gy,Mdq (66) |
698 | 82: INVPCID Gy,Mdq (66) | 721 | 82: INVPCID Gy,Mdq (66) |
722 | 83: vpmultishiftqb Vx,Hx,Wx (66),(ev) | ||
723 | 88: vexpandps/d Vpd,Wpd (66),(ev) | ||
724 | 89: vpexpandd/q Vx,Wx (66),(ev) | ||
725 | 8a: vcompressps/d Wx,Vx (66),(ev) | ||
726 | 8b: vpcompressd/q Wx,Vx (66),(ev) | ||
699 | 8c: vpmaskmovd/q Vx,Hx,Mx (66),(v) | 727 | 8c: vpmaskmovd/q Vx,Hx,Mx (66),(v) |
728 | 8d: vpermb/w Vx,Hx,Wx (66),(ev) | ||
700 | 8e: vpmaskmovd/q Mx,Vx,Hx (66),(v) | 729 | 8e: vpmaskmovd/q Mx,Vx,Hx (66),(v) |
701 | # 0x0f 0x38 0x90-0xbf (FMA) | 730 | # 0x0f 0x38 0x90-0xbf (FMA) |
702 | 90: vgatherdd/q Vx,Hx,Wx (66),(v) | 731 | 90: vgatherdd/q Vx,Hx,Wx (66),(v) | vpgatherdd/q Vx,Wx (66),(evo) |
703 | 91: vgatherqd/q Vx,Hx,Wx (66),(v) | 732 | 91: vgatherqd/q Vx,Hx,Wx (66),(v) | vpgatherqd/q Vx,Wx (66),(evo) |
704 | 92: vgatherdps/d Vx,Hx,Wx (66),(v) | 733 | 92: vgatherdps/d Vx,Hx,Wx (66),(v) |
705 | 93: vgatherqps/d Vx,Hx,Wx (66),(v) | 734 | 93: vgatherqps/d Vx,Hx,Wx (66),(v) |
706 | 94: | 735 | 94: |
@@ -715,6 +744,10 @@ AVXcode: 2 | |||
715 | 9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1) | 744 | 9d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1) |
716 | 9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v) | 745 | 9e: vfnmsub132ps/d Vx,Hx,Wx (66),(v) |
717 | 9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1) | 746 | 9f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1) |
747 | a0: vpscatterdd/q Wx,Vx (66),(ev) | ||
748 | a1: vpscatterqd/q Wx,Vx (66),(ev) | ||
749 | a2: vscatterdps/d Wx,Vx (66),(ev) | ||
750 | a3: vscatterqps/d Wx,Vx (66),(ev) | ||
718 | a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v) | 751 | a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v) |
719 | a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v) | 752 | a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v) |
720 | a8: vfmadd213ps/d Vx,Hx,Wx (66),(v) | 753 | a8: vfmadd213ps/d Vx,Hx,Wx (66),(v) |
@@ -725,6 +758,8 @@ ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v) | |||
725 | ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1) | 758 | ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1) |
726 | ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v) | 759 | ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v) |
727 | af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1) | 760 | af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1) |
761 | b4: vpmadd52luq Vx,Hx,Wx (66),(ev) | ||
762 | b5: vpmadd52huq Vx,Hx,Wx (66),(ev) | ||
728 | b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v) | 763 | b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v) |
729 | b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v) | 764 | b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v) |
730 | b8: vfmadd231ps/d Vx,Hx,Wx (66),(v) | 765 | b8: vfmadd231ps/d Vx,Hx,Wx (66),(v) |
@@ -736,12 +771,15 @@ bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1) | |||
736 | be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) | 771 | be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) |
737 | bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) | 772 | bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) |
738 | # 0x0f 0x38 0xc0-0xff | 773 | # 0x0f 0x38 0xc0-0xff |
739 | c8: sha1nexte Vdq,Wdq | 774 | c4: vpconflictd/q Vx,Wx (66),(ev) |
775 | c6: Grp18 (1A) | ||
776 | c7: Grp19 (1A) | ||
777 | c8: sha1nexte Vdq,Wdq | vexp2ps/d Vx,Wx (66),(ev) | ||
740 | c9: sha1msg1 Vdq,Wdq | 778 | c9: sha1msg1 Vdq,Wdq |
741 | ca: sha1msg2 Vdq,Wdq | 779 | ca: sha1msg2 Vdq,Wdq | vrcp28ps/d Vx,Wx (66),(ev) |
742 | cb: sha256rnds2 Vdq,Wdq | 780 | cb: sha256rnds2 Vdq,Wdq | vrcp28ss/d Vx,Hx,Wx (66),(ev) |
743 | cc: sha256msg1 Vdq,Wdq | 781 | cc: sha256msg1 Vdq,Wdq | vrsqrt28ps/d Vx,Wx (66),(ev) |
744 | cd: sha256msg2 Vdq,Wdq | 782 | cd: sha256msg2 Vdq,Wdq | vrsqrt28ss/d Vx,Hx,Wx (66),(ev) |
745 | db: VAESIMC Vdq,Wdq (66),(v1) | 783 | db: VAESIMC Vdq,Wdq (66),(v1) |
746 | dc: VAESENC Vdq,Hdq,Wdq (66),(v1) | 784 | dc: VAESENC Vdq,Hdq,Wdq (66),(v1) |
747 | dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) | 785 | dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) |
@@ -763,15 +801,15 @@ AVXcode: 3 | |||
763 | 00: vpermq Vqq,Wqq,Ib (66),(v) | 801 | 00: vpermq Vqq,Wqq,Ib (66),(v) |
764 | 01: vpermpd Vqq,Wqq,Ib (66),(v) | 802 | 01: vpermpd Vqq,Wqq,Ib (66),(v) |
765 | 02: vpblendd Vx,Hx,Wx,Ib (66),(v) | 803 | 02: vpblendd Vx,Hx,Wx,Ib (66),(v) |
766 | 03: | 804 | 03: valignd/q Vx,Hx,Wx,Ib (66),(ev) |
767 | 04: vpermilps Vx,Wx,Ib (66),(v) | 805 | 04: vpermilps Vx,Wx,Ib (66),(v) |
768 | 05: vpermilpd Vx,Wx,Ib (66),(v) | 806 | 05: vpermilpd Vx,Wx,Ib (66),(v) |
769 | 06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v) | 807 | 06: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v) |
770 | 07: | 808 | 07: |
771 | 08: vroundps Vx,Wx,Ib (66) | 809 | 08: vroundps Vx,Wx,Ib (66) | vrndscaleps Vx,Wx,Ib (66),(evo) |
772 | 09: vroundpd Vx,Wx,Ib (66) | 810 | 09: vroundpd Vx,Wx,Ib (66) | vrndscalepd Vx,Wx,Ib (66),(evo) |
773 | 0a: vroundss Vss,Wss,Ib (66),(v1) | 811 | 0a: vroundss Vss,Wss,Ib (66),(v1) | vrndscaless Vx,Hx,Wx,Ib (66),(evo) |
774 | 0b: vroundsd Vsd,Wsd,Ib (66),(v1) | 812 | 0b: vroundsd Vsd,Wsd,Ib (66),(v1) | vrndscalesd Vx,Hx,Wx,Ib (66),(evo) |
775 | 0c: vblendps Vx,Hx,Wx,Ib (66) | 813 | 0c: vblendps Vx,Hx,Wx,Ib (66) |
776 | 0d: vblendpd Vx,Hx,Wx,Ib (66) | 814 | 0d: vblendpd Vx,Hx,Wx,Ib (66) |
777 | 0e: vpblendw Vx,Hx,Wx,Ib (66),(v1) | 815 | 0e: vpblendw Vx,Hx,Wx,Ib (66),(v1) |
@@ -780,26 +818,51 @@ AVXcode: 3 | |||
780 | 15: vpextrw Rd/Mw,Vdq,Ib (66),(v1) | 818 | 15: vpextrw Rd/Mw,Vdq,Ib (66),(v1) |
781 | 16: vpextrd/q Ey,Vdq,Ib (66),(v1) | 819 | 16: vpextrd/q Ey,Vdq,Ib (66),(v1) |
782 | 17: vextractps Ed,Vdq,Ib (66),(v1) | 820 | 17: vextractps Ed,Vdq,Ib (66),(v1) |
783 | 18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v) | 821 | 18: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v) | vinsertf32x4/64x2 Vqq,Hqq,Wqq,Ib (66),(evo) |
784 | 19: vextractf128 Wdq,Vqq,Ib (66),(v) | 822 | 19: vextractf128 Wdq,Vqq,Ib (66),(v) | vextractf32x4/64x2 Wdq,Vqq,Ib (66),(evo) |
823 | 1a: vinsertf32x8/64x4 Vqq,Hqq,Wqq,Ib (66),(ev) | ||
824 | 1b: vextractf32x8/64x4 Wdq,Vqq,Ib (66),(ev) | ||
785 | 1d: vcvtps2ph Wx,Vx,Ib (66),(v) | 825 | 1d: vcvtps2ph Wx,Vx,Ib (66),(v) |
826 | 1e: vpcmpud/q Vk,Hd,Wd,Ib (66),(ev) | ||
827 | 1f: vpcmpd/q Vk,Hd,Wd,Ib (66),(ev) | ||
786 | 20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1) | 828 | 20: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1) |
787 | 21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1) | 829 | 21: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1) |
788 | 22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1) | 830 | 22: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1) |
789 | 38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v) | 831 | 23: vshuff32x4/64x2 Vx,Hx,Wx,Ib (66),(ev) |
790 | 39: vextracti128 Wdq,Vqq,Ib (66),(v) | 832 | 25: vpternlogd/q Vx,Hx,Wx,Ib (66),(ev) |
833 | 26: vgetmantps/d Vx,Wx,Ib (66),(ev) | ||
834 | 27: vgetmantss/d Vx,Hx,Wx,Ib (66),(ev) | ||
835 | 30: kshiftrb/w Vk,Uk,Ib (66),(v) | ||
836 | 31: kshiftrd/q Vk,Uk,Ib (66),(v) | ||
837 | 32: kshiftlb/w Vk,Uk,Ib (66),(v) | ||
838 | 33: kshiftld/q Vk,Uk,Ib (66),(v) | ||
839 | 38: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v) | vinserti32x4/64x2 Vqq,Hqq,Wqq,Ib (66),(evo) | ||
840 | 39: vextracti128 Wdq,Vqq,Ib (66),(v) | vextracti32x4/64x2 Wdq,Vqq,Ib (66),(evo) | ||
841 | 3a: vinserti32x8/64x4 Vqq,Hqq,Wqq,Ib (66),(ev) | ||
842 | 3b: vextracti32x8/64x4 Wdq,Vqq,Ib (66),(ev) | ||
843 | 3e: vpcmpub/w Vk,Hk,Wx,Ib (66),(ev) | ||
844 | 3f: vpcmpb/w Vk,Hk,Wx,Ib (66),(ev) | ||
791 | 40: vdpps Vx,Hx,Wx,Ib (66) | 845 | 40: vdpps Vx,Hx,Wx,Ib (66) |
792 | 41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1) | 846 | 41: vdppd Vdq,Hdq,Wdq,Ib (66),(v1) |
793 | 42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1) | 847 | 42: vmpsadbw Vx,Hx,Wx,Ib (66),(v1) | vdbpsadbw Vx,Hx,Wx,Ib (66),(evo) |
848 | 43: vshufi32x4/64x2 Vx,Hx,Wx,Ib (66),(ev) | ||
794 | 44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1) | 849 | 44: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1) |
795 | 46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v) | 850 | 46: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v) |
796 | 4a: vblendvps Vx,Hx,Wx,Lx (66),(v) | 851 | 4a: vblendvps Vx,Hx,Wx,Lx (66),(v) |
797 | 4b: vblendvpd Vx,Hx,Wx,Lx (66),(v) | 852 | 4b: vblendvpd Vx,Hx,Wx,Lx (66),(v) |
798 | 4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1) | 853 | 4c: vpblendvb Vx,Hx,Wx,Lx (66),(v1) |
854 | 50: vrangeps/d Vx,Hx,Wx,Ib (66),(ev) | ||
855 | 51: vrangess/d Vx,Hx,Wx,Ib (66),(ev) | ||
856 | 54: vfixupimmps/d Vx,Hx,Wx,Ib (66),(ev) | ||
857 | 55: vfixupimmss/d Vx,Hx,Wx,Ib (66),(ev) | ||
858 | 56: vreduceps/d Vx,Wx,Ib (66),(ev) | ||
859 | 57: vreducess/d Vx,Hx,Wx,Ib (66),(ev) | ||
799 | 60: vpcmpestrm Vdq,Wdq,Ib (66),(v1) | 860 | 60: vpcmpestrm Vdq,Wdq,Ib (66),(v1) |
800 | 61: vpcmpestri Vdq,Wdq,Ib (66),(v1) | 861 | 61: vpcmpestri Vdq,Wdq,Ib (66),(v1) |
801 | 62: vpcmpistrm Vdq,Wdq,Ib (66),(v1) | 862 | 62: vpcmpistrm Vdq,Wdq,Ib (66),(v1) |
802 | 63: vpcmpistri Vdq,Wdq,Ib (66),(v1) | 863 | 63: vpcmpistri Vdq,Wdq,Ib (66),(v1) |
864 | 66: vfpclassps/d Vk,Wx,Ib (66),(ev) | ||
865 | 67: vfpclassss/d Vk,Wx,Ib (66),(ev) | ||
803 | cc: sha1rnds4 Vdq,Wdq,Ib | 866 | cc: sha1rnds4 Vdq,Wdq,Ib |
804 | df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) | 867 | df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) |
805 | f0: RORX Gy,Ey,Ib (F2),(v) | 868 | f0: RORX Gy,Ey,Ib (F2),(v) |
@@ -927,8 +990,10 @@ GrpTable: Grp12 | |||
927 | EndTable | 990 | EndTable |
928 | 991 | ||
929 | GrpTable: Grp13 | 992 | GrpTable: Grp13 |
993 | 0: vprord/q Hx,Wx,Ib (66),(ev) | ||
994 | 1: vprold/q Hx,Wx,Ib (66),(ev) | ||
930 | 2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1) | 995 | 2: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1) |
931 | 4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1) | 996 | 4: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1) | vpsrad/q Hx,Ux,Ib (66),(evo) |
932 | 6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1) | 997 | 6: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1) |
933 | EndTable | 998 | EndTable |
934 | 999 | ||
@@ -947,7 +1012,7 @@ GrpTable: Grp15 | |||
947 | 4: XSAVE | 1012 | 4: XSAVE |
948 | 5: XRSTOR | lfence (11B) | 1013 | 5: XRSTOR | lfence (11B) |
949 | 6: XSAVEOPT | clwb (66) | mfence (11B) | 1014 | 6: XSAVEOPT | clwb (66) | mfence (11B) |
950 | 7: clflush | clflushopt (66) | sfence (11B) | pcommit (66),(11B) | 1015 | 7: clflush | clflushopt (66) | sfence (11B) |
951 | EndTable | 1016 | EndTable |
952 | 1017 | ||
953 | GrpTable: Grp16 | 1018 | GrpTable: Grp16 |
@@ -963,6 +1028,20 @@ GrpTable: Grp17 | |||
963 | 3: BLSI By,Ey (v) | 1028 | 3: BLSI By,Ey (v) |
964 | EndTable | 1029 | EndTable |
965 | 1030 | ||
1031 | GrpTable: Grp18 | ||
1032 | 1: vgatherpf0dps/d Wx (66),(ev) | ||
1033 | 2: vgatherpf1dps/d Wx (66),(ev) | ||
1034 | 5: vscatterpf0dps/d Wx (66),(ev) | ||
1035 | 6: vscatterpf1dps/d Wx (66),(ev) | ||
1036 | EndTable | ||
1037 | |||
1038 | GrpTable: Grp19 | ||
1039 | 1: vgatherpf0qps/d Wx (66),(ev) | ||
1040 | 2: vgatherpf1qps/d Wx (66),(ev) | ||
1041 | 5: vscatterpf0qps/d Wx (66),(ev) | ||
1042 | 6: vscatterpf1qps/d Wx (66),(ev) | ||
1043 | EndTable | ||
1044 | |||
966 | # AMD's Prefetch Group | 1045 | # AMD's Prefetch Group |
967 | GrpTable: GrpP | 1046 | GrpTable: GrpP |
968 | 0: PREFETCH | 1047 | 0: PREFETCH |
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index 137196990012..551ff6f640be 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include "auxtrace.h" | 39 | #include "auxtrace.h" |
40 | #include "tsc.h" | 40 | #include "tsc.h" |
41 | #include "intel-pt.h" | 41 | #include "intel-pt.h" |
42 | #include "config.h" | ||
42 | 43 | ||
43 | #include "intel-pt-decoder/intel-pt-log.h" | 44 | #include "intel-pt-decoder/intel-pt-log.h" |
44 | #include "intel-pt-decoder/intel-pt-decoder.h" | 45 | #include "intel-pt-decoder/intel-pt-decoder.h" |
@@ -556,7 +557,7 @@ static bool intel_pt_exclude_kernel(struct intel_pt *pt) | |||
556 | { | 557 | { |
557 | struct perf_evsel *evsel; | 558 | struct perf_evsel *evsel; |
558 | 559 | ||
559 | evlist__for_each(pt->session->evlist, evsel) { | 560 | evlist__for_each_entry(pt->session->evlist, evsel) { |
560 | if (intel_pt_get_config(pt, &evsel->attr, NULL) && | 561 | if (intel_pt_get_config(pt, &evsel->attr, NULL) && |
561 | !evsel->attr.exclude_kernel) | 562 | !evsel->attr.exclude_kernel) |
562 | return false; | 563 | return false; |
@@ -572,7 +573,7 @@ static bool intel_pt_return_compression(struct intel_pt *pt) | |||
572 | if (!pt->noretcomp_bit) | 573 | if (!pt->noretcomp_bit) |
573 | return true; | 574 | return true; |
574 | 575 | ||
575 | evlist__for_each(pt->session->evlist, evsel) { | 576 | evlist__for_each_entry(pt->session->evlist, evsel) { |
576 | if (intel_pt_get_config(pt, &evsel->attr, &config) && | 577 | if (intel_pt_get_config(pt, &evsel->attr, &config) && |
577 | (config & pt->noretcomp_bit)) | 578 | (config & pt->noretcomp_bit)) |
578 | return false; | 579 | return false; |
@@ -592,7 +593,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt) | |||
592 | for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++) | 593 | for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++) |
593 | config >>= 1; | 594 | config >>= 1; |
594 | 595 | ||
595 | evlist__for_each(pt->session->evlist, evsel) { | 596 | evlist__for_each_entry(pt->session->evlist, evsel) { |
596 | if (intel_pt_get_config(pt, &evsel->attr, &config)) | 597 | if (intel_pt_get_config(pt, &evsel->attr, &config)) |
597 | return (config & pt->mtc_freq_bits) >> shift; | 598 | return (config & pt->mtc_freq_bits) >> shift; |
598 | } | 599 | } |
@@ -608,7 +609,7 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt) | |||
608 | if (!pt->tsc_bit || !pt->cap_user_time_zero) | 609 | if (!pt->tsc_bit || !pt->cap_user_time_zero) |
609 | return true; | 610 | return true; |
610 | 611 | ||
611 | evlist__for_each(pt->session->evlist, evsel) { | 612 | evlist__for_each_entry(pt->session->evlist, evsel) { |
612 | if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME)) | 613 | if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME)) |
613 | return true; | 614 | return true; |
614 | if (intel_pt_get_config(pt, &evsel->attr, &config)) { | 615 | if (intel_pt_get_config(pt, &evsel->attr, &config)) { |
@@ -625,7 +626,7 @@ static bool intel_pt_tracing_kernel(struct intel_pt *pt) | |||
625 | { | 626 | { |
626 | struct perf_evsel *evsel; | 627 | struct perf_evsel *evsel; |
627 | 628 | ||
628 | evlist__for_each(pt->session->evlist, evsel) { | 629 | evlist__for_each_entry(pt->session->evlist, evsel) { |
629 | if (intel_pt_get_config(pt, &evsel->attr, NULL) && | 630 | if (intel_pt_get_config(pt, &evsel->attr, NULL) && |
630 | !evsel->attr.exclude_kernel) | 631 | !evsel->attr.exclude_kernel) |
631 | return true; | 632 | return true; |
@@ -642,7 +643,7 @@ static bool intel_pt_have_tsc(struct intel_pt *pt) | |||
642 | if (!pt->tsc_bit) | 643 | if (!pt->tsc_bit) |
643 | return false; | 644 | return false; |
644 | 645 | ||
645 | evlist__for_each(pt->session->evlist, evsel) { | 646 | evlist__for_each_entry(pt->session->evlist, evsel) { |
646 | if (intel_pt_get_config(pt, &evsel->attr, &config)) { | 647 | if (intel_pt_get_config(pt, &evsel->attr, &config)) { |
647 | if (config & pt->tsc_bit) | 648 | if (config & pt->tsc_bit) |
648 | have_tsc = true; | 649 | have_tsc = true; |
@@ -1233,7 +1234,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) | |||
1233 | if (!(state->type & INTEL_PT_BRANCH)) | 1234 | if (!(state->type & INTEL_PT_BRANCH)) |
1234 | return 0; | 1235 | return 0; |
1235 | 1236 | ||
1236 | if (pt->synth_opts.callchain) | 1237 | if (pt->synth_opts.callchain || pt->synth_opts.thread_stack) |
1237 | thread_stack__event(ptq->thread, ptq->flags, state->from_ip, | 1238 | thread_stack__event(ptq->thread, ptq->flags, state->from_ip, |
1238 | state->to_ip, ptq->insn_len, | 1239 | state->to_ip, ptq->insn_len, |
1239 | state->trace_nr); | 1240 | state->trace_nr); |
@@ -1850,7 +1851,7 @@ static int intel_pt_synth_events(struct intel_pt *pt, | |||
1850 | u64 id; | 1851 | u64 id; |
1851 | int err; | 1852 | int err; |
1852 | 1853 | ||
1853 | evlist__for_each(evlist, evsel) { | 1854 | evlist__for_each_entry(evlist, evsel) { |
1854 | if (evsel->attr.type == pt->pmu_type && evsel->ids) { | 1855 | if (evsel->attr.type == pt->pmu_type && evsel->ids) { |
1855 | found = true; | 1856 | found = true; |
1856 | break; | 1857 | break; |
@@ -1930,7 +1931,7 @@ static int intel_pt_synth_events(struct intel_pt *pt, | |||
1930 | pt->sample_transactions = true; | 1931 | pt->sample_transactions = true; |
1931 | pt->transactions_id = id; | 1932 | pt->transactions_id = id; |
1932 | id += 1; | 1933 | id += 1; |
1933 | evlist__for_each(evlist, evsel) { | 1934 | evlist__for_each_entry(evlist, evsel) { |
1934 | if (evsel->id && evsel->id[0] == pt->transactions_id) { | 1935 | if (evsel->id && evsel->id[0] == pt->transactions_id) { |
1935 | if (evsel->name) | 1936 | if (evsel->name) |
1936 | zfree(&evsel->name); | 1937 | zfree(&evsel->name); |
@@ -1968,7 +1969,7 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) | |||
1968 | { | 1969 | { |
1969 | struct perf_evsel *evsel; | 1970 | struct perf_evsel *evsel; |
1970 | 1971 | ||
1971 | evlist__for_each_reverse(evlist, evsel) { | 1972 | evlist__for_each_entry_reverse(evlist, evsel) { |
1972 | const char *name = perf_evsel__name(evsel); | 1973 | const char *name = perf_evsel__name(evsel); |
1973 | 1974 | ||
1974 | if (!strcmp(name, "sched:sched_switch")) | 1975 | if (!strcmp(name, "sched:sched_switch")) |
@@ -1982,7 +1983,7 @@ static bool intel_pt_find_switch(struct perf_evlist *evlist) | |||
1982 | { | 1983 | { |
1983 | struct perf_evsel *evsel; | 1984 | struct perf_evsel *evsel; |
1984 | 1985 | ||
1985 | evlist__for_each(evlist, evsel) { | 1986 | evlist__for_each_entry(evlist, evsel) { |
1986 | if (evsel->attr.context_switch) | 1987 | if (evsel->attr.context_switch) |
1987 | return true; | 1988 | return true; |
1988 | } | 1989 | } |
@@ -2136,6 +2137,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event, | |||
2136 | pt->synth_opts.branches = false; | 2137 | pt->synth_opts.branches = false; |
2137 | pt->synth_opts.callchain = true; | 2138 | pt->synth_opts.callchain = true; |
2138 | } | 2139 | } |
2140 | if (session->itrace_synth_opts) | ||
2141 | pt->synth_opts.thread_stack = | ||
2142 | session->itrace_synth_opts->thread_stack; | ||
2139 | } | 2143 | } |
2140 | 2144 | ||
2141 | if (pt->synth_opts.log) | 2145 | if (pt->synth_opts.log) |
diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h index aa6877d36858..020b9ca1b47e 100644 --- a/tools/perf/util/intlist.h +++ b/tools/perf/util/intlist.h | |||
@@ -57,21 +57,21 @@ static inline struct int_node *intlist__next(struct int_node *in) | |||
57 | } | 57 | } |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * intlist_for_each - iterate over a intlist | 60 | * intlist__for_each_entry - iterate over a intlist |
61 | * @pos: the &struct int_node to use as a loop cursor. | 61 | * @pos: the &struct int_node to use as a loop cursor. |
62 | * @ilist: the &struct intlist for loop. | 62 | * @ilist: the &struct intlist for loop. |
63 | */ | 63 | */ |
64 | #define intlist__for_each(pos, ilist) \ | 64 | #define intlist__for_each_entry(pos, ilist) \ |
65 | for (pos = intlist__first(ilist); pos; pos = intlist__next(pos)) | 65 | for (pos = intlist__first(ilist); pos; pos = intlist__next(pos)) |
66 | 66 | ||
67 | /** | 67 | /** |
68 | * intlist_for_each_safe - iterate over a intlist safe against removal of | 68 | * intlist__for_each_entry_safe - iterate over a intlist safe against removal of |
69 | * int_node | 69 | * int_node |
70 | * @pos: the &struct int_node to use as a loop cursor. | 70 | * @pos: the &struct int_node to use as a loop cursor. |
71 | * @n: another &struct int_node to use as temporary storage. | 71 | * @n: another &struct int_node to use as temporary storage. |
72 | * @ilist: the &struct intlist for loop. | 72 | * @ilist: the &struct intlist for loop. |
73 | */ | 73 | */ |
74 | #define intlist__for_each_safe(pos, n, ilist) \ | 74 | #define intlist__for_each_entry_safe(pos, n, ilist) \ |
75 | for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\ | 75 | for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\ |
76 | pos = n, n = intlist__next(n)) | 76 | pos = n, n = intlist__next(n)) |
77 | #endif /* __PERF_INTLIST_H */ | 77 | #endif /* __PERF_INTLIST_H */ |
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 86afe9618bb0..9f3305f6b6d5 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c | |||
@@ -108,7 +108,7 @@ jit_validate_events(struct perf_session *session) | |||
108 | /* | 108 | /* |
109 | * check that all events use CLOCK_MONOTONIC | 109 | * check that all events use CLOCK_MONOTONIC |
110 | */ | 110 | */ |
111 | evlist__for_each(session->evlist, evsel) { | 111 | evlist__for_each_entry(session->evlist, evsel) { |
112 | if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC) | 112 | if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC) |
113 | return -1; | 113 | return -1; |
114 | } | 114 | } |
diff --git a/tools/perf/util/levenshtein.c b/tools/perf/util/levenshtein.c index e521d1516df6..f616e4f65b67 100644 --- a/tools/perf/util/levenshtein.c +++ b/tools/perf/util/levenshtein.c | |||
@@ -1,5 +1,7 @@ | |||
1 | #include "cache.h" | ||
2 | #include "levenshtein.h" | 1 | #include "levenshtein.h" |
2 | #include <errno.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
3 | 5 | ||
4 | /* | 6 | /* |
5 | * This function implements the Damerau-Levenshtein algorithm to | 7 | * This function implements the Damerau-Levenshtein algorithm to |
diff --git a/tools/perf/util/libunwind/arm64.c b/tools/perf/util/libunwind/arm64.c new file mode 100644 index 000000000000..6559bc586643 --- /dev/null +++ b/tools/perf/util/libunwind/arm64.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * This file setups defines to compile arch specific binary from the | ||
3 | * generic one. | ||
4 | * | ||
5 | * The function 'LIBUNWIND__ARCH_REG_ID' name is set according to arch | ||
6 | * name and the defination of this function is included directly from | ||
7 | * 'arch/arm64/util/unwind-libunwind.c', to make sure that this function | ||
8 | * is defined no matter what arch the host is. | ||
9 | * | ||
10 | * Finally, the arch specific unwind methods are exported which will | ||
11 | * be assigned to each arm64 thread. | ||
12 | */ | ||
13 | |||
14 | #define REMOTE_UNWIND_LIBUNWIND | ||
15 | |||
16 | /* Define arch specific functions & regs for libunwind, should be | ||
17 | * defined before including "unwind.h" | ||
18 | */ | ||
19 | #define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arm64_reg_id(regnum) | ||
20 | #define LIBUNWIND__ARCH_REG_IP PERF_REG_ARM64_PC | ||
21 | #define LIBUNWIND__ARCH_REG_SP PERF_REG_ARM64_SP | ||
22 | |||
23 | #include "unwind.h" | ||
24 | #include "debug.h" | ||
25 | #include "libunwind-aarch64.h" | ||
26 | #include <../../../../arch/arm64/include/uapi/asm/perf_regs.h> | ||
27 | #include "../../arch/arm64/util/unwind-libunwind.c" | ||
28 | |||
29 | /* NO_LIBUNWIND_DEBUG_FRAME is a feature flag for local libunwind, | ||
30 | * assign NO_LIBUNWIND_DEBUG_FRAME_AARCH64 to it for compiling arm64 | ||
31 | * unwind methods. | ||
32 | */ | ||
33 | #undef NO_LIBUNWIND_DEBUG_FRAME | ||
34 | #ifdef NO_LIBUNWIND_DEBUG_FRAME_AARCH64 | ||
35 | #define NO_LIBUNWIND_DEBUG_FRAME | ||
36 | #endif | ||
37 | #include "util/unwind-libunwind-local.c" | ||
38 | |||
39 | struct unwind_libunwind_ops * | ||
40 | arm64_unwind_libunwind_ops = &_unwind_libunwind_ops; | ||
diff --git a/tools/perf/util/libunwind/x86_32.c b/tools/perf/util/libunwind/x86_32.c new file mode 100644 index 000000000000..957ffff72428 --- /dev/null +++ b/tools/perf/util/libunwind/x86_32.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * This file setups defines to compile arch specific binary from the | ||
3 | * generic one. | ||
4 | * | ||
5 | * The function 'LIBUNWIND__ARCH_REG_ID' name is set according to arch | ||
6 | * name and the defination of this function is included directly from | ||
7 | * 'arch/x86/util/unwind-libunwind.c', to make sure that this function | ||
8 | * is defined no matter what arch the host is. | ||
9 | * | ||
10 | * Finally, the arch specific unwind methods are exported which will | ||
11 | * be assigned to each x86 thread. | ||
12 | */ | ||
13 | |||
14 | #define REMOTE_UNWIND_LIBUNWIND | ||
15 | |||
16 | /* Define arch specific functions & regs for libunwind, should be | ||
17 | * defined before including "unwind.h" | ||
18 | */ | ||
19 | #define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__x86_reg_id(regnum) | ||
20 | #define LIBUNWIND__ARCH_REG_IP PERF_REG_X86_IP | ||
21 | #define LIBUNWIND__ARCH_REG_SP PERF_REG_X86_SP | ||
22 | |||
23 | #include "unwind.h" | ||
24 | #include "debug.h" | ||
25 | #include "libunwind-x86.h" | ||
26 | #include <../../../../arch/x86/include/uapi/asm/perf_regs.h> | ||
27 | |||
28 | /* HAVE_ARCH_X86_64_SUPPORT is used in'arch/x86/util/unwind-libunwind.c' | ||
29 | * for x86_32, we undef it to compile code for x86_32 only. | ||
30 | */ | ||
31 | #undef HAVE_ARCH_X86_64_SUPPORT | ||
32 | #include "../../arch/x86/util/unwind-libunwind.c" | ||
33 | |||
34 | /* Explicitly define NO_LIBUNWIND_DEBUG_FRAME, because non-ARM has no | ||
35 | * dwarf_find_debug_frame() function. | ||
36 | */ | ||
37 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | ||
38 | #define NO_LIBUNWIND_DEBUG_FRAME | ||
39 | #endif | ||
40 | #include "util/unwind-libunwind-local.c" | ||
41 | |||
42 | struct unwind_libunwind_ops * | ||
43 | x86_32_unwind_libunwind_ops = &_unwind_libunwind_ops; | ||
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c index 33071d6159bc..bf7216b8731d 100644 --- a/tools/perf/util/llvm-utils.c +++ b/tools/perf/util/llvm-utils.c | |||
@@ -3,11 +3,14 @@ | |||
3 | * Copyright (C) 2015, Huawei Inc. | 3 | * Copyright (C) 2015, Huawei Inc. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <errno.h> | ||
6 | #include <limits.h> | 7 | #include <limits.h> |
7 | #include <stdio.h> | 8 | #include <stdio.h> |
8 | #include <stdlib.h> | 9 | #include <stdlib.h> |
9 | #include "debug.h" | 10 | #include "debug.h" |
10 | #include "llvm-utils.h" | 11 | #include "llvm-utils.h" |
12 | #include "config.h" | ||
13 | #include "util.h" | ||
11 | 14 | ||
12 | #define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ | 15 | #define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ |
13 | "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ | 16 | "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ |
@@ -42,6 +45,8 @@ int perf_llvm_config(const char *var, const char *value) | |||
42 | llvm_param.kbuild_dir = strdup(value); | 45 | llvm_param.kbuild_dir = strdup(value); |
43 | else if (!strcmp(var, "kbuild-opts")) | 46 | else if (!strcmp(var, "kbuild-opts")) |
44 | llvm_param.kbuild_opts = strdup(value); | 47 | llvm_param.kbuild_opts = strdup(value); |
48 | else if (!strcmp(var, "dump-obj")) | ||
49 | llvm_param.dump_obj = !!perf_config_bool(var, value); | ||
45 | else | 50 | else |
46 | return -1; | 51 | return -1; |
47 | llvm_param.user_set_param = true; | 52 | llvm_param.user_set_param = true; |
@@ -103,7 +108,7 @@ read_from_pipe(const char *cmd, void **p_buf, size_t *p_read_sz) | |||
103 | file = popen(cmd, "r"); | 108 | file = popen(cmd, "r"); |
104 | if (!file) { | 109 | if (!file) { |
105 | pr_err("ERROR: unable to popen cmd: %s\n", | 110 | pr_err("ERROR: unable to popen cmd: %s\n", |
106 | strerror_r(errno, serr, sizeof(serr))); | 111 | str_error_r(errno, serr, sizeof(serr))); |
107 | return -EINVAL; | 112 | return -EINVAL; |
108 | } | 113 | } |
109 | 114 | ||
@@ -137,7 +142,7 @@ read_from_pipe(const char *cmd, void **p_buf, size_t *p_read_sz) | |||
137 | 142 | ||
138 | if (ferror(file)) { | 143 | if (ferror(file)) { |
139 | pr_err("ERROR: error occurred when reading from pipe: %s\n", | 144 | pr_err("ERROR: error occurred when reading from pipe: %s\n", |
140 | strerror_r(errno, serr, sizeof(serr))); | 145 | str_error_r(errno, serr, sizeof(serr))); |
141 | err = -EIO; | 146 | err = -EIO; |
142 | goto errout; | 147 | goto errout; |
143 | } | 148 | } |
@@ -326,6 +331,42 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts) | |||
326 | pr_debug("include option is set to %s\n", *kbuild_include_opts); | 331 | pr_debug("include option is set to %s\n", *kbuild_include_opts); |
327 | } | 332 | } |
328 | 333 | ||
334 | static void | ||
335 | dump_obj(const char *path, void *obj_buf, size_t size) | ||
336 | { | ||
337 | char *obj_path = strdup(path); | ||
338 | FILE *fp; | ||
339 | char *p; | ||
340 | |||
341 | if (!obj_path) { | ||
342 | pr_warning("WARNING: No enough memory, skip object dumping\n"); | ||
343 | return; | ||
344 | } | ||
345 | |||
346 | p = strrchr(obj_path, '.'); | ||
347 | if (!p || (strcmp(p, ".c") != 0)) { | ||
348 | pr_warning("WARNING: invalid llvm source path: '%s', skip object dumping\n", | ||
349 | obj_path); | ||
350 | goto out; | ||
351 | } | ||
352 | |||
353 | p[1] = 'o'; | ||
354 | fp = fopen(obj_path, "wb"); | ||
355 | if (!fp) { | ||
356 | pr_warning("WARNING: failed to open '%s': %s, skip object dumping\n", | ||
357 | obj_path, strerror(errno)); | ||
358 | goto out; | ||
359 | } | ||
360 | |||
361 | pr_info("LLVM: dumping %s\n", obj_path); | ||
362 | if (fwrite(obj_buf, size, 1, fp) != 1) | ||
363 | pr_warning("WARNING: failed to write to file '%s': %s, skip object dumping\n", | ||
364 | obj_path, strerror(errno)); | ||
365 | fclose(fp); | ||
366 | out: | ||
367 | free(obj_path); | ||
368 | } | ||
369 | |||
329 | int llvm__compile_bpf(const char *path, void **p_obj_buf, | 370 | int llvm__compile_bpf(const char *path, void **p_obj_buf, |
330 | size_t *p_obj_buf_sz) | 371 | size_t *p_obj_buf_sz) |
331 | { | 372 | { |
@@ -343,7 +384,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, | |||
343 | if (path[0] != '-' && realpath(path, abspath) == NULL) { | 384 | if (path[0] != '-' && realpath(path, abspath) == NULL) { |
344 | err = errno; | 385 | err = errno; |
345 | pr_err("ERROR: problems with path %s: %s\n", | 386 | pr_err("ERROR: problems with path %s: %s\n", |
346 | path, strerror_r(err, serr, sizeof(serr))); | 387 | path, str_error_r(err, serr, sizeof(serr))); |
347 | return -err; | 388 | return -err; |
348 | } | 389 | } |
349 | 390 | ||
@@ -371,7 +412,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, | |||
371 | if (nr_cpus_avail <= 0) { | 412 | if (nr_cpus_avail <= 0) { |
372 | pr_err( | 413 | pr_err( |
373 | "WARNING:\tunable to get available CPUs in this system: %s\n" | 414 | "WARNING:\tunable to get available CPUs in this system: %s\n" |
374 | " \tUse 128 instead.\n", strerror_r(errno, serr, sizeof(serr))); | 415 | " \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr))); |
375 | nr_cpus_avail = 128; | 416 | nr_cpus_avail = 128; |
376 | } | 417 | } |
377 | snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d", | 418 | snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d", |
@@ -411,6 +452,10 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, | |||
411 | 452 | ||
412 | free(kbuild_dir); | 453 | free(kbuild_dir); |
413 | free(kbuild_include_opts); | 454 | free(kbuild_include_opts); |
455 | |||
456 | if (llvm_param.dump_obj) | ||
457 | dump_obj(path, obj_buf, obj_buf_sz); | ||
458 | |||
414 | if (!p_obj_buf) | 459 | if (!p_obj_buf) |
415 | free(obj_buf); | 460 | free(obj_buf); |
416 | else | 461 | else |
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h index 23b9a743fe72..9f501cef06a1 100644 --- a/tools/perf/util/llvm-utils.h +++ b/tools/perf/util/llvm-utils.h | |||
@@ -30,6 +30,11 @@ struct llvm_param { | |||
30 | */ | 30 | */ |
31 | const char *kbuild_opts; | 31 | const char *kbuild_opts; |
32 | /* | 32 | /* |
33 | * Default is false. If set to true, write compiling result | ||
34 | * to object file. | ||
35 | */ | ||
36 | bool dump_obj; | ||
37 | /* | ||
33 | * Default is false. If one of the above fields is set by user | 38 | * Default is false. If one of the above fields is set by user |
34 | * explicitly then user_set_llvm is set to true. This is used | 39 | * explicitly then user_set_llvm is set to true. This is used |
35 | * for perf test. If user doesn't set anything in .perfconfig | 40 | * for perf test. If user doesn't set anything in .perfconfig |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index b1772180c820..cb6388dbdd98 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -138,8 +138,10 @@ void machine__exit(struct machine *machine) | |||
138 | 138 | ||
139 | void machine__delete(struct machine *machine) | 139 | void machine__delete(struct machine *machine) |
140 | { | 140 | { |
141 | machine__exit(machine); | 141 | if (machine) { |
142 | free(machine); | 142 | machine__exit(machine); |
143 | free(machine); | ||
144 | } | ||
143 | } | 145 | } |
144 | 146 | ||
145 | void machines__init(struct machines *machines) | 147 | void machines__init(struct machines *machines) |
@@ -1091,12 +1093,20 @@ static int machine__set_modules_path(struct machine *machine) | |||
1091 | 1093 | ||
1092 | return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); | 1094 | return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); |
1093 | } | 1095 | } |
1096 | int __weak arch__fix_module_text_start(u64 *start __maybe_unused, | ||
1097 | const char *name __maybe_unused) | ||
1098 | { | ||
1099 | return 0; | ||
1100 | } | ||
1094 | 1101 | ||
1095 | static int machine__create_module(void *arg, const char *name, u64 start) | 1102 | static int machine__create_module(void *arg, const char *name, u64 start) |
1096 | { | 1103 | { |
1097 | struct machine *machine = arg; | 1104 | struct machine *machine = arg; |
1098 | struct map *map; | 1105 | struct map *map; |
1099 | 1106 | ||
1107 | if (arch__fix_module_text_start(&start, name) < 0) | ||
1108 | return -1; | ||
1109 | |||
1100 | map = machine__findnew_module_map(machine, start, name); | 1110 | map = machine__findnew_module_map(machine, start, name); |
1101 | if (map == NULL) | 1111 | if (map == NULL) |
1102 | return -1; | 1112 | return -1; |
@@ -1353,11 +1363,16 @@ int machine__process_mmap2_event(struct machine *machine, | |||
1353 | if (map == NULL) | 1363 | if (map == NULL) |
1354 | goto out_problem_map; | 1364 | goto out_problem_map; |
1355 | 1365 | ||
1356 | thread__insert_map(thread, map); | 1366 | ret = thread__insert_map(thread, map); |
1367 | if (ret) | ||
1368 | goto out_problem_insert; | ||
1369 | |||
1357 | thread__put(thread); | 1370 | thread__put(thread); |
1358 | map__put(map); | 1371 | map__put(map); |
1359 | return 0; | 1372 | return 0; |
1360 | 1373 | ||
1374 | out_problem_insert: | ||
1375 | map__put(map); | ||
1361 | out_problem_map: | 1376 | out_problem_map: |
1362 | thread__put(thread); | 1377 | thread__put(thread); |
1363 | out_problem: | 1378 | out_problem: |
@@ -1403,11 +1418,16 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event | |||
1403 | if (map == NULL) | 1418 | if (map == NULL) |
1404 | goto out_problem_map; | 1419 | goto out_problem_map; |
1405 | 1420 | ||
1406 | thread__insert_map(thread, map); | 1421 | ret = thread__insert_map(thread, map); |
1422 | if (ret) | ||
1423 | goto out_problem_insert; | ||
1424 | |||
1407 | thread__put(thread); | 1425 | thread__put(thread); |
1408 | map__put(map); | 1426 | map__put(map); |
1409 | return 0; | 1427 | return 0; |
1410 | 1428 | ||
1429 | out_problem_insert: | ||
1430 | map__put(map); | ||
1411 | out_problem_map: | 1431 | out_problem_map: |
1412 | thread__put(thread); | 1432 | thread__put(thread); |
1413 | out_problem: | 1433 | out_problem: |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 41ac9cfd416b..20739f746bc4 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -216,6 +216,7 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *machine, | |||
216 | 216 | ||
217 | struct map *machine__findnew_module_map(struct machine *machine, u64 start, | 217 | struct map *machine__findnew_module_map(struct machine *machine, u64 start, |
218 | const char *filename); | 218 | const char *filename); |
219 | int arch__fix_module_text_start(u64 *start, const char *name); | ||
219 | 220 | ||
220 | int __machine__load_kallsyms(struct machine *machine, const char *filename, | 221 | int __machine__load_kallsyms(struct machine *machine, const char *filename, |
221 | enum map_type type, bool no_kcore, symbol_filter_t filter); | 222 | enum map_type type, bool no_kcore, symbol_filter_t filter); |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index b19bcd3b7128..728129ac653a 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "debug.h" | 15 | #include "debug.h" |
16 | #include "machine.h" | 16 | #include "machine.h" |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #include "unwind.h" | ||
18 | 19 | ||
19 | static void __maps__insert(struct maps *maps, struct map *map); | 20 | static void __maps__insert(struct maps *maps, struct map *map); |
20 | 21 | ||
@@ -311,6 +312,9 @@ int map__load(struct map *map, symbol_filter_t filter) | |||
311 | pr_warning("%.*s was updated (is prelink enabled?). " | 312 | pr_warning("%.*s was updated (is prelink enabled?). " |
312 | "Restart the long running apps that use it!\n", | 313 | "Restart the long running apps that use it!\n", |
313 | (int)real_len, name); | 314 | (int)real_len, name); |
315 | } else if (filter) { | ||
316 | pr_warning("no symbols passed the given filter.\n"); | ||
317 | return -2; /* Empty but maybe by the filter */ | ||
314 | } else { | 318 | } else { |
315 | pr_warning("no symbols found in %s, maybe install " | 319 | pr_warning("no symbols found in %s, maybe install " |
316 | "a debug package?\n", name); | 320 | "a debug package?\n", name); |
@@ -744,9 +748,10 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, | |||
744 | /* | 748 | /* |
745 | * XXX This should not really _copy_ te maps, but refcount them. | 749 | * XXX This should not really _copy_ te maps, but refcount them. |
746 | */ | 750 | */ |
747 | int map_groups__clone(struct map_groups *mg, | 751 | int map_groups__clone(struct thread *thread, |
748 | struct map_groups *parent, enum map_type type) | 752 | struct map_groups *parent, enum map_type type) |
749 | { | 753 | { |
754 | struct map_groups *mg = thread->mg; | ||
750 | int err = -ENOMEM; | 755 | int err = -ENOMEM; |
751 | struct map *map; | 756 | struct map *map; |
752 | struct maps *maps = &parent->maps[type]; | 757 | struct maps *maps = &parent->maps[type]; |
@@ -757,6 +762,11 @@ int map_groups__clone(struct map_groups *mg, | |||
757 | struct map *new = map__clone(map); | 762 | struct map *new = map__clone(map); |
758 | if (new == NULL) | 763 | if (new == NULL) |
759 | goto out_unlock; | 764 | goto out_unlock; |
765 | |||
766 | err = unwind__prepare_access(thread, new, NULL); | ||
767 | if (err) | ||
768 | goto out_unlock; | ||
769 | |||
760 | map_groups__insert(mg, new); | 770 | map_groups__insert(mg, new); |
761 | map__put(new); | 771 | map__put(new); |
762 | } | 772 | } |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 7309d64ce39e..d83396ceecba 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -194,7 +194,7 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, | |||
194 | struct map **mapp, symbol_filter_t filter); | 194 | struct map **mapp, symbol_filter_t filter); |
195 | void map_groups__init(struct map_groups *mg, struct machine *machine); | 195 | void map_groups__init(struct map_groups *mg, struct machine *machine); |
196 | void map_groups__exit(struct map_groups *mg); | 196 | void map_groups__exit(struct map_groups *mg); |
197 | int map_groups__clone(struct map_groups *mg, | 197 | int map_groups__clone(struct thread *thread, |
198 | struct map_groups *parent, enum map_type type); | 198 | struct map_groups *parent, enum map_type type); |
199 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); | 199 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); |
200 | 200 | ||
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c index 75465f89a413..bbc368e7d1e4 100644 --- a/tools/perf/util/mem-events.c +++ b/tools/perf/util/mem-events.c | |||
@@ -10,18 +10,33 @@ | |||
10 | #include "debug.h" | 10 | #include "debug.h" |
11 | #include "symbol.h" | 11 | #include "symbol.h" |
12 | 12 | ||
13 | unsigned int perf_mem_events__loads_ldlat = 30; | ||
14 | |||
13 | #define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s } | 15 | #define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s } |
14 | 16 | ||
15 | struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = { | 17 | struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = { |
16 | E("ldlat-loads", "cpu/mem-loads,ldlat=30/P", "mem-loads"), | 18 | E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "mem-loads"), |
17 | E("ldlat-stores", "cpu/mem-stores/P", "mem-stores"), | 19 | E("ldlat-stores", "cpu/mem-stores/P", "mem-stores"), |
18 | }; | 20 | }; |
19 | #undef E | 21 | #undef E |
20 | 22 | ||
21 | #undef E | 23 | #undef E |
22 | 24 | ||
25 | static char mem_loads_name[100]; | ||
26 | static bool mem_loads_name__init; | ||
27 | |||
23 | char *perf_mem_events__name(int i) | 28 | char *perf_mem_events__name(int i) |
24 | { | 29 | { |
30 | if (i == PERF_MEM_EVENTS__LOAD) { | ||
31 | if (!mem_loads_name__init) { | ||
32 | mem_loads_name__init = true; | ||
33 | scnprintf(mem_loads_name, sizeof(mem_loads_name), | ||
34 | perf_mem_events[i].name, | ||
35 | perf_mem_events__loads_ldlat); | ||
36 | } | ||
37 | return mem_loads_name; | ||
38 | } | ||
39 | |||
25 | return (char *)perf_mem_events[i].name; | 40 | return (char *)perf_mem_events[i].name; |
26 | } | 41 | } |
27 | 42 | ||
diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h index 5d6d93066a6e..7f69bf9d789d 100644 --- a/tools/perf/util/mem-events.h +++ b/tools/perf/util/mem-events.h | |||
@@ -18,6 +18,7 @@ enum { | |||
18 | }; | 18 | }; |
19 | 19 | ||
20 | extern struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX]; | 20 | extern struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX]; |
21 | extern unsigned int perf_mem_events__loads_ldlat; | ||
21 | 22 | ||
22 | int perf_mem_events__parse(const char *str); | 23 | int perf_mem_events__parse(const char *str); |
23 | int perf_mem_events__init(void); | 24 | int perf_mem_events__init(void); |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index c6fd0479f4cd..6c913c3914fb 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "pmu.h" | 20 | #include "pmu.h" |
21 | #include "thread_map.h" | 21 | #include "thread_map.h" |
22 | #include "cpumap.h" | 22 | #include "cpumap.h" |
23 | #include "probe-file.h" | ||
23 | #include "asm/bug.h" | 24 | #include "asm/bug.h" |
24 | 25 | ||
25 | #define MAX_NAME_LEN 100 | 26 | #define MAX_NAME_LEN 100 |
@@ -436,7 +437,7 @@ int parse_events_add_cache(struct list_head *list, int *idx, | |||
436 | } | 437 | } |
437 | 438 | ||
438 | static void tracepoint_error(struct parse_events_error *e, int err, | 439 | static void tracepoint_error(struct parse_events_error *e, int err, |
439 | char *sys, char *name) | 440 | const char *sys, const char *name) |
440 | { | 441 | { |
441 | char help[BUFSIZ]; | 442 | char help[BUFSIZ]; |
442 | 443 | ||
@@ -466,7 +467,7 @@ static void tracepoint_error(struct parse_events_error *e, int err, | |||
466 | } | 467 | } |
467 | 468 | ||
468 | static int add_tracepoint(struct list_head *list, int *idx, | 469 | static int add_tracepoint(struct list_head *list, int *idx, |
469 | char *sys_name, char *evt_name, | 470 | const char *sys_name, const char *evt_name, |
470 | struct parse_events_error *err, | 471 | struct parse_events_error *err, |
471 | struct list_head *head_config) | 472 | struct list_head *head_config) |
472 | { | 473 | { |
@@ -491,7 +492,7 @@ static int add_tracepoint(struct list_head *list, int *idx, | |||
491 | } | 492 | } |
492 | 493 | ||
493 | static int add_tracepoint_multi_event(struct list_head *list, int *idx, | 494 | static int add_tracepoint_multi_event(struct list_head *list, int *idx, |
494 | char *sys_name, char *evt_name, | 495 | const char *sys_name, const char *evt_name, |
495 | struct parse_events_error *err, | 496 | struct parse_events_error *err, |
496 | struct list_head *head_config) | 497 | struct list_head *head_config) |
497 | { | 498 | { |
@@ -533,7 +534,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, | |||
533 | } | 534 | } |
534 | 535 | ||
535 | static int add_tracepoint_event(struct list_head *list, int *idx, | 536 | static int add_tracepoint_event(struct list_head *list, int *idx, |
536 | char *sys_name, char *evt_name, | 537 | const char *sys_name, const char *evt_name, |
537 | struct parse_events_error *err, | 538 | struct parse_events_error *err, |
538 | struct list_head *head_config) | 539 | struct list_head *head_config) |
539 | { | 540 | { |
@@ -545,7 +546,7 @@ static int add_tracepoint_event(struct list_head *list, int *idx, | |||
545 | } | 546 | } |
546 | 547 | ||
547 | static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | 548 | static int add_tracepoint_multi_sys(struct list_head *list, int *idx, |
548 | char *sys_name, char *evt_name, | 549 | const char *sys_name, const char *evt_name, |
549 | struct parse_events_error *err, | 550 | struct parse_events_error *err, |
550 | struct list_head *head_config) | 551 | struct list_head *head_config) |
551 | { | 552 | { |
@@ -584,7 +585,7 @@ struct __add_bpf_event_param { | |||
584 | struct list_head *head_config; | 585 | struct list_head *head_config; |
585 | }; | 586 | }; |
586 | 587 | ||
587 | static int add_bpf_event(struct probe_trace_event *tev, int fd, | 588 | static int add_bpf_event(const char *group, const char *event, int fd, |
588 | void *_param) | 589 | void *_param) |
589 | { | 590 | { |
590 | LIST_HEAD(new_evsels); | 591 | LIST_HEAD(new_evsels); |
@@ -595,27 +596,27 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd, | |||
595 | int err; | 596 | int err; |
596 | 597 | ||
597 | pr_debug("add bpf event %s:%s and attach bpf program %d\n", | 598 | pr_debug("add bpf event %s:%s and attach bpf program %d\n", |
598 | tev->group, tev->event, fd); | 599 | group, event, fd); |
599 | 600 | ||
600 | err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group, | 601 | err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, group, |
601 | tev->event, evlist->error, | 602 | event, evlist->error, |
602 | param->head_config); | 603 | param->head_config); |
603 | if (err) { | 604 | if (err) { |
604 | struct perf_evsel *evsel, *tmp; | 605 | struct perf_evsel *evsel, *tmp; |
605 | 606 | ||
606 | pr_debug("Failed to add BPF event %s:%s\n", | 607 | pr_debug("Failed to add BPF event %s:%s\n", |
607 | tev->group, tev->event); | 608 | group, event); |
608 | list_for_each_entry_safe(evsel, tmp, &new_evsels, node) { | 609 | list_for_each_entry_safe(evsel, tmp, &new_evsels, node) { |
609 | list_del(&evsel->node); | 610 | list_del(&evsel->node); |
610 | perf_evsel__delete(evsel); | 611 | perf_evsel__delete(evsel); |
611 | } | 612 | } |
612 | return err; | 613 | return err; |
613 | } | 614 | } |
614 | pr_debug("adding %s:%s\n", tev->group, tev->event); | 615 | pr_debug("adding %s:%s\n", group, event); |
615 | 616 | ||
616 | list_for_each_entry(pos, &new_evsels, node) { | 617 | list_for_each_entry(pos, &new_evsels, node) { |
617 | pr_debug("adding %s:%s to %p\n", | 618 | pr_debug("adding %s:%s to %p\n", |
618 | tev->group, tev->event, pos); | 619 | group, event, pos); |
619 | pos->bpf_fd = fd; | 620 | pos->bpf_fd = fd; |
620 | } | 621 | } |
621 | list_splice(&new_evsels, list); | 622 | list_splice(&new_evsels, list); |
@@ -661,7 +662,7 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data, | |||
661 | goto errout; | 662 | goto errout; |
662 | } | 663 | } |
663 | 664 | ||
664 | err = bpf__foreach_tev(obj, add_bpf_event, ¶m); | 665 | err = bpf__foreach_event(obj, add_bpf_event, ¶m); |
665 | if (err) { | 666 | if (err) { |
666 | snprintf(errbuf, sizeof(errbuf), | 667 | snprintf(errbuf, sizeof(errbuf), |
667 | "Attach events in BPF object failed"); | 668 | "Attach events in BPF object failed"); |
@@ -900,6 +901,9 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = { | |||
900 | [PARSE_EVENTS__TERM_TYPE_STACKSIZE] = "stack-size", | 901 | [PARSE_EVENTS__TERM_TYPE_STACKSIZE] = "stack-size", |
901 | [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", | 902 | [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", |
902 | [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", | 903 | [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", |
904 | [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", | ||
905 | [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", | ||
906 | [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", | ||
903 | }; | 907 | }; |
904 | 908 | ||
905 | static bool config_term_shrinked; | 909 | static bool config_term_shrinked; |
@@ -992,9 +996,18 @@ do { \ | |||
992 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: | 996 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: |
993 | CHECK_TYPE_VAL(NUM); | 997 | CHECK_TYPE_VAL(NUM); |
994 | break; | 998 | break; |
999 | case PARSE_EVENTS__TERM_TYPE_OVERWRITE: | ||
1000 | CHECK_TYPE_VAL(NUM); | ||
1001 | break; | ||
1002 | case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: | ||
1003 | CHECK_TYPE_VAL(NUM); | ||
1004 | break; | ||
995 | case PARSE_EVENTS__TERM_TYPE_NAME: | 1005 | case PARSE_EVENTS__TERM_TYPE_NAME: |
996 | CHECK_TYPE_VAL(STR); | 1006 | CHECK_TYPE_VAL(STR); |
997 | break; | 1007 | break; |
1008 | case PARSE_EVENTS__TERM_TYPE_MAX_STACK: | ||
1009 | CHECK_TYPE_VAL(NUM); | ||
1010 | break; | ||
998 | default: | 1011 | default: |
999 | err->str = strdup("unknown term"); | 1012 | err->str = strdup("unknown term"); |
1000 | err->idx = term->err_term; | 1013 | err->idx = term->err_term; |
@@ -1040,6 +1053,9 @@ static int config_term_tracepoint(struct perf_event_attr *attr, | |||
1040 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: | 1053 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: |
1041 | case PARSE_EVENTS__TERM_TYPE_INHERIT: | 1054 | case PARSE_EVENTS__TERM_TYPE_INHERIT: |
1042 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: | 1055 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: |
1056 | case PARSE_EVENTS__TERM_TYPE_MAX_STACK: | ||
1057 | case PARSE_EVENTS__TERM_TYPE_OVERWRITE: | ||
1058 | case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: | ||
1043 | return config_term_common(attr, term, err); | 1059 | return config_term_common(attr, term, err); |
1044 | default: | 1060 | default: |
1045 | if (err) { | 1061 | if (err) { |
@@ -1109,6 +1125,15 @@ do { \ | |||
1109 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: | 1125 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: |
1110 | ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1); | 1126 | ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1); |
1111 | break; | 1127 | break; |
1128 | case PARSE_EVENTS__TERM_TYPE_MAX_STACK: | ||
1129 | ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num); | ||
1130 | break; | ||
1131 | case PARSE_EVENTS__TERM_TYPE_OVERWRITE: | ||
1132 | ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0); | ||
1133 | break; | ||
1134 | case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: | ||
1135 | ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1); | ||
1136 | break; | ||
1112 | default: | 1137 | default: |
1113 | break; | 1138 | break; |
1114 | } | 1139 | } |
@@ -1118,7 +1143,7 @@ do { \ | |||
1118 | } | 1143 | } |
1119 | 1144 | ||
1120 | int parse_events_add_tracepoint(struct list_head *list, int *idx, | 1145 | int parse_events_add_tracepoint(struct list_head *list, int *idx, |
1121 | char *sys, char *event, | 1146 | const char *sys, const char *event, |
1122 | struct parse_events_error *err, | 1147 | struct parse_events_error *err, |
1123 | struct list_head *head_config) | 1148 | struct list_head *head_config) |
1124 | { | 1149 | { |
@@ -1388,7 +1413,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) | |||
1388 | if (!add && get_event_modifier(&mod, str, NULL)) | 1413 | if (!add && get_event_modifier(&mod, str, NULL)) |
1389 | return -EINVAL; | 1414 | return -EINVAL; |
1390 | 1415 | ||
1391 | __evlist__for_each(list, evsel) { | 1416 | __evlist__for_each_entry(list, evsel) { |
1392 | if (add && get_event_modifier(&mod, str, evsel)) | 1417 | if (add && get_event_modifier(&mod, str, evsel)) |
1393 | return -EINVAL; | 1418 | return -EINVAL; |
1394 | 1419 | ||
@@ -1414,7 +1439,7 @@ int parse_events_name(struct list_head *list, char *name) | |||
1414 | { | 1439 | { |
1415 | struct perf_evsel *evsel; | 1440 | struct perf_evsel *evsel; |
1416 | 1441 | ||
1417 | __evlist__for_each(list, evsel) { | 1442 | __evlist__for_each_entry(list, evsel) { |
1418 | if (!evsel->name) | 1443 | if (!evsel->name) |
1419 | evsel->name = strdup(name); | 1444 | evsel->name = strdup(name); |
1420 | } | 1445 | } |
@@ -1976,6 +2001,85 @@ static bool is_event_supported(u8 type, unsigned config) | |||
1976 | return ret; | 2001 | return ret; |
1977 | } | 2002 | } |
1978 | 2003 | ||
2004 | void print_sdt_events(const char *subsys_glob, const char *event_glob, | ||
2005 | bool name_only) | ||
2006 | { | ||
2007 | struct probe_cache *pcache; | ||
2008 | struct probe_cache_entry *ent; | ||
2009 | struct strlist *bidlist, *sdtlist; | ||
2010 | struct strlist_config cfg = {.dont_dupstr = true}; | ||
2011 | struct str_node *nd, *nd2; | ||
2012 | char *buf, *path, *ptr = NULL; | ||
2013 | bool show_detail = false; | ||
2014 | int ret; | ||
2015 | |||
2016 | sdtlist = strlist__new(NULL, &cfg); | ||
2017 | if (!sdtlist) { | ||
2018 | pr_debug("Failed to allocate new strlist for SDT\n"); | ||
2019 | return; | ||
2020 | } | ||
2021 | bidlist = build_id_cache__list_all(true); | ||
2022 | if (!bidlist) { | ||
2023 | pr_debug("Failed to get buildids: %d\n", errno); | ||
2024 | return; | ||
2025 | } | ||
2026 | strlist__for_each_entry(nd, bidlist) { | ||
2027 | pcache = probe_cache__new(nd->s); | ||
2028 | if (!pcache) | ||
2029 | continue; | ||
2030 | list_for_each_entry(ent, &pcache->entries, node) { | ||
2031 | if (!ent->sdt) | ||
2032 | continue; | ||
2033 | if (subsys_glob && | ||
2034 | !strglobmatch(ent->pev.group, subsys_glob)) | ||
2035 | continue; | ||
2036 | if (event_glob && | ||
2037 | !strglobmatch(ent->pev.event, event_glob)) | ||
2038 | continue; | ||
2039 | ret = asprintf(&buf, "%s:%s@%s", ent->pev.group, | ||
2040 | ent->pev.event, nd->s); | ||
2041 | if (ret > 0) | ||
2042 | strlist__add(sdtlist, buf); | ||
2043 | } | ||
2044 | probe_cache__delete(pcache); | ||
2045 | } | ||
2046 | strlist__delete(bidlist); | ||
2047 | |||
2048 | strlist__for_each_entry(nd, sdtlist) { | ||
2049 | buf = strchr(nd->s, '@'); | ||
2050 | if (buf) | ||
2051 | *(buf++) = '\0'; | ||
2052 | if (name_only) { | ||
2053 | printf("%s ", nd->s); | ||
2054 | continue; | ||
2055 | } | ||
2056 | nd2 = strlist__next(nd); | ||
2057 | if (nd2) { | ||
2058 | ptr = strchr(nd2->s, '@'); | ||
2059 | if (ptr) | ||
2060 | *ptr = '\0'; | ||
2061 | if (strcmp(nd->s, nd2->s) == 0) | ||
2062 | show_detail = true; | ||
2063 | } | ||
2064 | if (show_detail) { | ||
2065 | path = build_id_cache__origname(buf); | ||
2066 | ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf); | ||
2067 | if (ret > 0) { | ||
2068 | printf(" %-50s [%s]\n", buf, "SDT event"); | ||
2069 | free(buf); | ||
2070 | } | ||
2071 | } else | ||
2072 | printf(" %-50s [%s]\n", nd->s, "SDT event"); | ||
2073 | if (nd2) { | ||
2074 | if (strcmp(nd->s, nd2->s) != 0) | ||
2075 | show_detail = false; | ||
2076 | if (ptr) | ||
2077 | *ptr = '@'; | ||
2078 | } | ||
2079 | } | ||
2080 | strlist__delete(sdtlist); | ||
2081 | } | ||
2082 | |||
1979 | int print_hwcache_events(const char *event_glob, bool name_only) | 2083 | int print_hwcache_events(const char *event_glob, bool name_only) |
1980 | { | 2084 | { |
1981 | unsigned int type, op, i, evt_i = 0, evt_num = 0; | 2085 | unsigned int type, op, i, evt_i = 0, evt_num = 0; |
@@ -2158,6 +2262,8 @@ void print_events(const char *event_glob, bool name_only) | |||
2158 | } | 2262 | } |
2159 | 2263 | ||
2160 | print_tracepoint_events(NULL, NULL, name_only); | 2264 | print_tracepoint_events(NULL, NULL, name_only); |
2265 | |||
2266 | print_sdt_events(NULL, NULL, name_only); | ||
2161 | } | 2267 | } |
2162 | 2268 | ||
2163 | int parse_events__is_hardcoded_term(struct parse_events_term *term) | 2269 | int parse_events__is_hardcoded_term(struct parse_events_term *term) |
@@ -2322,9 +2428,9 @@ static void config_terms_list(char *buf, size_t buf_sz) | |||
2322 | char *parse_events_formats_error_string(char *additional_terms) | 2428 | char *parse_events_formats_error_string(char *additional_terms) |
2323 | { | 2429 | { |
2324 | char *str; | 2430 | char *str; |
2325 | /* "branch_type" is the longest name */ | 2431 | /* "no-overwrite" is the longest name */ |
2326 | char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * | 2432 | char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * |
2327 | (sizeof("branch_type") - 1)]; | 2433 | (sizeof("no-overwrite") - 1)]; |
2328 | 2434 | ||
2329 | config_terms_list(static_terms, sizeof(static_terms)); | 2435 | config_terms_list(static_terms, sizeof(static_terms)); |
2330 | /* valid terms */ | 2436 | /* valid terms */ |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index d740c3ca9a1d..d1edbf8cc66a 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -68,6 +68,9 @@ enum { | |||
68 | PARSE_EVENTS__TERM_TYPE_STACKSIZE, | 68 | PARSE_EVENTS__TERM_TYPE_STACKSIZE, |
69 | PARSE_EVENTS__TERM_TYPE_NOINHERIT, | 69 | PARSE_EVENTS__TERM_TYPE_NOINHERIT, |
70 | PARSE_EVENTS__TERM_TYPE_INHERIT, | 70 | PARSE_EVENTS__TERM_TYPE_INHERIT, |
71 | PARSE_EVENTS__TERM_TYPE_MAX_STACK, | ||
72 | PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, | ||
73 | PARSE_EVENTS__TERM_TYPE_OVERWRITE, | ||
71 | __PARSE_EVENTS__TERM_TYPE_NR, | 74 | __PARSE_EVENTS__TERM_TYPE_NR, |
72 | }; | 75 | }; |
73 | 76 | ||
@@ -133,7 +136,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add); | |||
133 | int parse_events__modifier_group(struct list_head *list, char *event_mod); | 136 | int parse_events__modifier_group(struct list_head *list, char *event_mod); |
134 | int parse_events_name(struct list_head *list, char *name); | 137 | int parse_events_name(struct list_head *list, char *name); |
135 | int parse_events_add_tracepoint(struct list_head *list, int *idx, | 138 | int parse_events_add_tracepoint(struct list_head *list, int *idx, |
136 | char *sys, char *event, | 139 | const char *sys, const char *event, |
137 | struct parse_events_error *error, | 140 | struct parse_events_error *error, |
138 | struct list_head *head_config); | 141 | struct list_head *head_config); |
139 | int parse_events_load_bpf(struct parse_events_evlist *data, | 142 | int parse_events_load_bpf(struct parse_events_evlist *data, |
@@ -182,6 +185,8 @@ void print_symbol_events(const char *event_glob, unsigned type, | |||
182 | void print_tracepoint_events(const char *subsys_glob, const char *event_glob, | 185 | void print_tracepoint_events(const char *subsys_glob, const char *event_glob, |
183 | bool name_only); | 186 | bool name_only); |
184 | int print_hwcache_events(const char *event_glob, bool name_only); | 187 | int print_hwcache_events(const char *event_glob, bool name_only); |
188 | void print_sdt_events(const char *subsys_glob, const char *event_glob, | ||
189 | bool name_only); | ||
185 | int is_valid_tracepoint(const char *event_string); | 190 | int is_valid_tracepoint(const char *event_string); |
186 | 191 | ||
187 | int valid_event_mount(const char *eventfs); | 192 | int valid_event_mount(const char *eventfs); |
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 1477fbc78993..7a2519435da0 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
@@ -199,8 +199,11 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE | |||
199 | time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } | 199 | time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } |
200 | call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } | 200 | call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } |
201 | stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } | 201 | stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } |
202 | max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); } | ||
202 | inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } | 203 | inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } |
203 | no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } | 204 | no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } |
205 | overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); } | ||
206 | no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); } | ||
204 | , { return ','; } | 207 | , { return ','; } |
205 | "/" { BEGIN(INITIAL); return '/'; } | 208 | "/" { BEGIN(INITIAL); return '/'; } |
206 | {name_minus} { return str(yyscanner, PE_NAME); } | 209 | {name_minus} { return str(yyscanner, PE_NAME); } |
@@ -259,6 +262,7 @@ cycles-ct { return str(yyscanner, PE_KERNEL_PMU_EVENT); } | |||
259 | cycles-t { return str(yyscanner, PE_KERNEL_PMU_EVENT); } | 262 | cycles-t { return str(yyscanner, PE_KERNEL_PMU_EVENT); } |
260 | mem-loads { return str(yyscanner, PE_KERNEL_PMU_EVENT); } | 263 | mem-loads { return str(yyscanner, PE_KERNEL_PMU_EVENT); } |
261 | mem-stores { return str(yyscanner, PE_KERNEL_PMU_EVENT); } | 264 | mem-stores { return str(yyscanner, PE_KERNEL_PMU_EVENT); } |
265 | topdown-[a-z-]+ { return str(yyscanner, PE_KERNEL_PMU_EVENT); } | ||
262 | 266 | ||
263 | L1-dcache|l1-d|l1d|L1-data | | 267 | L1-dcache|l1-d|l1d|L1-data | |
264 | L1-icache|l1-i|l1i|L1-instruction | | 268 | L1-icache|l1-i|l1i|L1-instruction | |
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c index 3bf6bf82ff2d..7c7630be5a89 100644 --- a/tools/perf/util/path.c +++ b/tools/perf/util/path.c | |||
@@ -11,17 +11,13 @@ | |||
11 | * which is what it's designed for. | 11 | * which is what it's designed for. |
12 | */ | 12 | */ |
13 | #include "cache.h" | 13 | #include "cache.h" |
14 | #include "util.h" | ||
15 | #include <limits.h> | ||
14 | 16 | ||
15 | static char bad_path[] = "/bad-path/"; | 17 | static char bad_path[] = "/bad-path/"; |
16 | /* | 18 | /* |
17 | * Two hacks: | 19 | * One hack: |
18 | */ | 20 | */ |
19 | |||
20 | static const char *get_perf_dir(void) | ||
21 | { | ||
22 | return "."; | ||
23 | } | ||
24 | |||
25 | static char *get_pathname(void) | 21 | static char *get_pathname(void) |
26 | { | 22 | { |
27 | static char pathname_array[4][PATH_MAX]; | 23 | static char pathname_array[4][PATH_MAX]; |
@@ -54,60 +50,3 @@ char *mkpath(const char *fmt, ...) | |||
54 | return bad_path; | 50 | return bad_path; |
55 | return cleanup_path(pathname); | 51 | return cleanup_path(pathname); |
56 | } | 52 | } |
57 | |||
58 | char *perf_path(const char *fmt, ...) | ||
59 | { | ||
60 | const char *perf_dir = get_perf_dir(); | ||
61 | char *pathname = get_pathname(); | ||
62 | va_list args; | ||
63 | unsigned len; | ||
64 | |||
65 | len = strlen(perf_dir); | ||
66 | if (len > PATH_MAX-100) | ||
67 | return bad_path; | ||
68 | memcpy(pathname, perf_dir, len); | ||
69 | if (len && perf_dir[len-1] != '/') | ||
70 | pathname[len++] = '/'; | ||
71 | va_start(args, fmt); | ||
72 | len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args); | ||
73 | va_end(args); | ||
74 | if (len >= PATH_MAX) | ||
75 | return bad_path; | ||
76 | return cleanup_path(pathname); | ||
77 | } | ||
78 | |||
79 | /* strip arbitrary amount of directory separators at end of path */ | ||
80 | static inline int chomp_trailing_dir_sep(const char *path, int len) | ||
81 | { | ||
82 | while (len && is_dir_sep(path[len - 1])) | ||
83 | len--; | ||
84 | return len; | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * If path ends with suffix (complete path components), returns the | ||
89 | * part before suffix (sans trailing directory separators). | ||
90 | * Otherwise returns NULL. | ||
91 | */ | ||
92 | char *strip_path_suffix(const char *path, const char *suffix) | ||
93 | { | ||
94 | int path_len = strlen(path), suffix_len = strlen(suffix); | ||
95 | |||
96 | while (suffix_len) { | ||
97 | if (!path_len) | ||
98 | return NULL; | ||
99 | |||
100 | if (is_dir_sep(path[path_len - 1])) { | ||
101 | if (!is_dir_sep(suffix[suffix_len - 1])) | ||
102 | return NULL; | ||
103 | path_len = chomp_trailing_dir_sep(path, path_len); | ||
104 | suffix_len = chomp_trailing_dir_sep(suffix, suffix_len); | ||
105 | } | ||
106 | else if (path[--path_len] != suffix[--suffix_len]) | ||
107 | return NULL; | ||
108 | } | ||
109 | |||
110 | if (path_len && !is_dir_sep(path[path_len - 1])) | ||
111 | return NULL; | ||
112 | return strndup(path, chomp_trailing_dir_sep(path, path_len)); | ||
113 | } | ||
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 74401a20106d..953dc1ab2ed7 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -67,7 +67,6 @@ int e_snprintf(char *str, size_t size, const char *format, ...) | |||
67 | return ret; | 67 | return ret; |
68 | } | 68 | } |
69 | 69 | ||
70 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp); | ||
71 | static struct machine *host_machine; | 70 | static struct machine *host_machine; |
72 | 71 | ||
73 | /* Initialize symbol maps and path of vmlinux/modules */ | 72 | /* Initialize symbol maps and path of vmlinux/modules */ |
@@ -103,10 +102,8 @@ out: | |||
103 | 102 | ||
104 | void exit_probe_symbol_maps(void) | 103 | void exit_probe_symbol_maps(void) |
105 | { | 104 | { |
106 | if (host_machine) { | 105 | machine__delete(host_machine); |
107 | machine__delete(host_machine); | 106 | host_machine = NULL; |
108 | host_machine = NULL; | ||
109 | } | ||
110 | symbol__exit(); | 107 | symbol__exit(); |
111 | } | 108 | } |
112 | 109 | ||
@@ -471,7 +468,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent) | |||
471 | err = kernel_get_module_dso(module, &dso); | 468 | err = kernel_get_module_dso(module, &dso); |
472 | if (err < 0) { | 469 | if (err < 0) { |
473 | if (!dso || dso->load_errno == 0) { | 470 | if (!dso || dso->load_errno == 0) { |
474 | if (!strerror_r(-err, reason, STRERR_BUFSIZE)) | 471 | if (!str_error_r(-err, reason, STRERR_BUFSIZE)) |
475 | strcpy(reason, "(unknown)"); | 472 | strcpy(reason, "(unknown)"); |
476 | } else | 473 | } else |
477 | dso__strerror_load(dso, reason, STRERR_BUFSIZE); | 474 | dso__strerror_load(dso, reason, STRERR_BUFSIZE); |
@@ -809,7 +806,7 @@ static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) | |||
809 | error: | 806 | error: |
810 | if (ferror(fp)) { | 807 | if (ferror(fp)) { |
811 | pr_warning("File read error: %s\n", | 808 | pr_warning("File read error: %s\n", |
812 | strerror_r(errno, sbuf, sizeof(sbuf))); | 809 | str_error_r(errno, sbuf, sizeof(sbuf))); |
813 | return -1; | 810 | return -1; |
814 | } | 811 | } |
815 | return 0; | 812 | return 0; |
@@ -889,7 +886,7 @@ static int __show_line_range(struct line_range *lr, const char *module, | |||
889 | fp = fopen(lr->path, "r"); | 886 | fp = fopen(lr->path, "r"); |
890 | if (fp == NULL) { | 887 | if (fp == NULL) { |
891 | pr_warning("Failed to open %s: %s\n", lr->path, | 888 | pr_warning("Failed to open %s: %s\n", lr->path, |
892 | strerror_r(errno, sbuf, sizeof(sbuf))); | 889 | str_error_r(errno, sbuf, sizeof(sbuf))); |
893 | return -errno; | 890 | return -errno; |
894 | } | 891 | } |
895 | /* Skip to starting line number */ | 892 | /* Skip to starting line number */ |
@@ -899,7 +896,7 @@ static int __show_line_range(struct line_range *lr, const char *module, | |||
899 | goto end; | 896 | goto end; |
900 | } | 897 | } |
901 | 898 | ||
902 | intlist__for_each(ln, lr->line_list) { | 899 | intlist__for_each_entry(ln, lr->line_list) { |
903 | for (; ln->i > l; l++) { | 900 | for (; ln->i > l; l++) { |
904 | ret = show_one_line(fp, l - lr->offset); | 901 | ret = show_one_line(fp, l - lr->offset); |
905 | if (ret < 0) | 902 | if (ret < 0) |
@@ -983,7 +980,7 @@ static int show_available_vars_at(struct debuginfo *dinfo, | |||
983 | zfree(&vl->point.symbol); | 980 | zfree(&vl->point.symbol); |
984 | nvars = 0; | 981 | nvars = 0; |
985 | if (vl->vars) { | 982 | if (vl->vars) { |
986 | strlist__for_each(node, vl->vars) { | 983 | strlist__for_each_entry(node, vl->vars) { |
987 | var = strchr(node->s, '\t') + 1; | 984 | var = strchr(node->s, '\t') + 1; |
988 | if (strfilter__compare(_filter, var)) { | 985 | if (strfilter__compare(_filter, var)) { |
989 | fprintf(stdout, "\t\t%s\n", node->s); | 986 | fprintf(stdout, "\t\t%s\n", node->s); |
@@ -1200,6 +1197,34 @@ err: | |||
1200 | return err; | 1197 | return err; |
1201 | } | 1198 | } |
1202 | 1199 | ||
1200 | static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev) | ||
1201 | { | ||
1202 | char *ptr; | ||
1203 | |||
1204 | ptr = strchr(*arg, ':'); | ||
1205 | if (ptr) { | ||
1206 | *ptr = '\0'; | ||
1207 | if (!pev->sdt && !is_c_func_name(*arg)) | ||
1208 | goto ng_name; | ||
1209 | pev->group = strdup(*arg); | ||
1210 | if (!pev->group) | ||
1211 | return -ENOMEM; | ||
1212 | *arg = ptr + 1; | ||
1213 | } else | ||
1214 | pev->group = NULL; | ||
1215 | if (!pev->sdt && !is_c_func_name(*arg)) { | ||
1216 | ng_name: | ||
1217 | semantic_error("%s is bad for event name -it must " | ||
1218 | "follow C symbol-naming rule.\n", *arg); | ||
1219 | return -EINVAL; | ||
1220 | } | ||
1221 | pev->event = strdup(*arg); | ||
1222 | if (pev->event == NULL) | ||
1223 | return -ENOMEM; | ||
1224 | |||
1225 | return 0; | ||
1226 | } | ||
1227 | |||
1203 | /* Parse probepoint definition. */ | 1228 | /* Parse probepoint definition. */ |
1204 | static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) | 1229 | static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) |
1205 | { | 1230 | { |
@@ -1207,33 +1232,64 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) | |||
1207 | char *ptr, *tmp; | 1232 | char *ptr, *tmp; |
1208 | char c, nc = 0; | 1233 | char c, nc = 0; |
1209 | bool file_spec = false; | 1234 | bool file_spec = false; |
1235 | int ret; | ||
1236 | |||
1210 | /* | 1237 | /* |
1211 | * <Syntax> | 1238 | * <Syntax> |
1212 | * perf probe [EVENT=]SRC[:LN|;PTN] | 1239 | * perf probe [GRP:][EVENT=]SRC[:LN|;PTN] |
1213 | * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] | 1240 | * perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] |
1214 | * | 1241 | * perf probe %[GRP:]SDT_EVENT |
1215 | * TODO:Group name support | ||
1216 | */ | 1242 | */ |
1217 | if (!arg) | 1243 | if (!arg) |
1218 | return -EINVAL; | 1244 | return -EINVAL; |
1219 | 1245 | ||
1246 | /* | ||
1247 | * If the probe point starts with '%', | ||
1248 | * or starts with "sdt_" and has a ':' but no '=', | ||
1249 | * then it should be a SDT/cached probe point. | ||
1250 | */ | ||
1251 | if (arg[0] == '%' || | ||
1252 | (!strncmp(arg, "sdt_", 4) && | ||
1253 | !!strchr(arg, ':') && !strchr(arg, '='))) { | ||
1254 | pev->sdt = true; | ||
1255 | if (arg[0] == '%') | ||
1256 | arg++; | ||
1257 | } | ||
1258 | |||
1220 | ptr = strpbrk(arg, ";=@+%"); | 1259 | ptr = strpbrk(arg, ";=@+%"); |
1260 | if (pev->sdt) { | ||
1261 | if (ptr) { | ||
1262 | if (*ptr != '@') { | ||
1263 | semantic_error("%s must be an SDT name.\n", | ||
1264 | arg); | ||
1265 | return -EINVAL; | ||
1266 | } | ||
1267 | /* This must be a target file name or build id */ | ||
1268 | tmp = build_id_cache__complement(ptr + 1); | ||
1269 | if (tmp) { | ||
1270 | pev->target = build_id_cache__origname(tmp); | ||
1271 | free(tmp); | ||
1272 | } else | ||
1273 | pev->target = strdup(ptr + 1); | ||
1274 | if (!pev->target) | ||
1275 | return -ENOMEM; | ||
1276 | *ptr = '\0'; | ||
1277 | } | ||
1278 | ret = parse_perf_probe_event_name(&arg, pev); | ||
1279 | if (ret == 0) { | ||
1280 | if (asprintf(&pev->point.function, "%%%s", pev->event) < 0) | ||
1281 | ret = -errno; | ||
1282 | } | ||
1283 | return ret; | ||
1284 | } | ||
1285 | |||
1221 | if (ptr && *ptr == '=') { /* Event name */ | 1286 | if (ptr && *ptr == '=') { /* Event name */ |
1222 | *ptr = '\0'; | 1287 | *ptr = '\0'; |
1223 | tmp = ptr + 1; | 1288 | tmp = ptr + 1; |
1224 | if (strchr(arg, ':')) { | 1289 | ret = parse_perf_probe_event_name(&arg, pev); |
1225 | semantic_error("Group name is not supported yet.\n"); | 1290 | if (ret < 0) |
1226 | return -ENOTSUP; | 1291 | return ret; |
1227 | } | 1292 | |
1228 | if (!is_c_func_name(arg)) { | ||
1229 | semantic_error("%s is bad for event name -it must " | ||
1230 | "follow C symbol-naming rule.\n", arg); | ||
1231 | return -EINVAL; | ||
1232 | } | ||
1233 | pev->event = strdup(arg); | ||
1234 | if (pev->event == NULL) | ||
1235 | return -ENOMEM; | ||
1236 | pev->group = NULL; | ||
1237 | arg = tmp; | 1293 | arg = tmp; |
1238 | } | 1294 | } |
1239 | 1295 | ||
@@ -1545,7 +1601,9 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) | |||
1545 | return true; | 1601 | return true; |
1546 | 1602 | ||
1547 | for (i = 0; i < pev->nargs; i++) | 1603 | for (i = 0; i < pev->nargs; i++) |
1548 | if (is_c_varname(pev->args[i].var)) | 1604 | if (is_c_varname(pev->args[i].var) || |
1605 | !strcmp(pev->args[i].var, "$params") || | ||
1606 | !strcmp(pev->args[i].var, "$vars")) | ||
1549 | return true; | 1607 | return true; |
1550 | 1608 | ||
1551 | return false; | 1609 | return false; |
@@ -1603,6 +1661,11 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev) | |||
1603 | p = strchr(argv[1], ':'); | 1661 | p = strchr(argv[1], ':'); |
1604 | if (p) { | 1662 | if (p) { |
1605 | tp->module = strndup(argv[1], p - argv[1]); | 1663 | tp->module = strndup(argv[1], p - argv[1]); |
1664 | if (!tp->module) { | ||
1665 | ret = -ENOMEM; | ||
1666 | goto out; | ||
1667 | } | ||
1668 | tev->uprobes = (tp->module[0] == '/'); | ||
1606 | p++; | 1669 | p++; |
1607 | } else | 1670 | } else |
1608 | p = argv[1]; | 1671 | p = argv[1]; |
@@ -1712,7 +1775,7 @@ out: | |||
1712 | } | 1775 | } |
1713 | 1776 | ||
1714 | /* Compose only probe point (not argument) */ | 1777 | /* Compose only probe point (not argument) */ |
1715 | static char *synthesize_perf_probe_point(struct perf_probe_point *pp) | 1778 | char *synthesize_perf_probe_point(struct perf_probe_point *pp) |
1716 | { | 1779 | { |
1717 | struct strbuf buf; | 1780 | struct strbuf buf; |
1718 | char *tmp, *ret = NULL; | 1781 | char *tmp, *ret = NULL; |
@@ -1751,30 +1814,36 @@ out: | |||
1751 | return ret; | 1814 | return ret; |
1752 | } | 1815 | } |
1753 | 1816 | ||
1754 | #if 0 | ||
1755 | char *synthesize_perf_probe_command(struct perf_probe_event *pev) | 1817 | char *synthesize_perf_probe_command(struct perf_probe_event *pev) |
1756 | { | 1818 | { |
1757 | char *buf; | 1819 | struct strbuf buf; |
1758 | int i, len, ret; | 1820 | char *tmp, *ret = NULL; |
1821 | int i; | ||
1759 | 1822 | ||
1760 | buf = synthesize_perf_probe_point(&pev->point); | 1823 | if (strbuf_init(&buf, 64)) |
1761 | if (!buf) | ||
1762 | return NULL; | 1824 | return NULL; |
1825 | if (pev->event) | ||
1826 | if (strbuf_addf(&buf, "%s:%s=", pev->group ?: PERFPROBE_GROUP, | ||
1827 | pev->event) < 0) | ||
1828 | goto out; | ||
1829 | |||
1830 | tmp = synthesize_perf_probe_point(&pev->point); | ||
1831 | if (!tmp || strbuf_addstr(&buf, tmp) < 0) | ||
1832 | goto out; | ||
1833 | free(tmp); | ||
1763 | 1834 | ||
1764 | len = strlen(buf); | ||
1765 | for (i = 0; i < pev->nargs; i++) { | 1835 | for (i = 0; i < pev->nargs; i++) { |
1766 | ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", | 1836 | tmp = synthesize_perf_probe_arg(pev->args + i); |
1767 | pev->args[i].name); | 1837 | if (!tmp || strbuf_addf(&buf, " %s", tmp) < 0) |
1768 | if (ret <= 0) { | 1838 | goto out; |
1769 | free(buf); | 1839 | free(tmp); |
1770 | return NULL; | ||
1771 | } | ||
1772 | len += ret; | ||
1773 | } | 1840 | } |
1774 | 1841 | ||
1775 | return buf; | 1842 | ret = strbuf_detach(&buf, NULL); |
1843 | out: | ||
1844 | strbuf_release(&buf); | ||
1845 | return ret; | ||
1776 | } | 1846 | } |
1777 | #endif | ||
1778 | 1847 | ||
1779 | static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, | 1848 | static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, |
1780 | struct strbuf *buf, int depth) | 1849 | struct strbuf *buf, int depth) |
@@ -2026,6 +2095,79 @@ void clear_perf_probe_event(struct perf_probe_event *pev) | |||
2026 | memset(pev, 0, sizeof(*pev)); | 2095 | memset(pev, 0, sizeof(*pev)); |
2027 | } | 2096 | } |
2028 | 2097 | ||
2098 | #define strdup_or_goto(str, label) \ | ||
2099 | ({ char *__p = NULL; if (str && !(__p = strdup(str))) goto label; __p; }) | ||
2100 | |||
2101 | static int perf_probe_point__copy(struct perf_probe_point *dst, | ||
2102 | struct perf_probe_point *src) | ||
2103 | { | ||
2104 | dst->file = strdup_or_goto(src->file, out_err); | ||
2105 | dst->function = strdup_or_goto(src->function, out_err); | ||
2106 | dst->lazy_line = strdup_or_goto(src->lazy_line, out_err); | ||
2107 | dst->line = src->line; | ||
2108 | dst->retprobe = src->retprobe; | ||
2109 | dst->offset = src->offset; | ||
2110 | return 0; | ||
2111 | |||
2112 | out_err: | ||
2113 | clear_perf_probe_point(dst); | ||
2114 | return -ENOMEM; | ||
2115 | } | ||
2116 | |||
2117 | static int perf_probe_arg__copy(struct perf_probe_arg *dst, | ||
2118 | struct perf_probe_arg *src) | ||
2119 | { | ||
2120 | struct perf_probe_arg_field *field, **ppfield; | ||
2121 | |||
2122 | dst->name = strdup_or_goto(src->name, out_err); | ||
2123 | dst->var = strdup_or_goto(src->var, out_err); | ||
2124 | dst->type = strdup_or_goto(src->type, out_err); | ||
2125 | |||
2126 | field = src->field; | ||
2127 | ppfield = &(dst->field); | ||
2128 | while (field) { | ||
2129 | *ppfield = zalloc(sizeof(*field)); | ||
2130 | if (!*ppfield) | ||
2131 | goto out_err; | ||
2132 | (*ppfield)->name = strdup_or_goto(field->name, out_err); | ||
2133 | (*ppfield)->index = field->index; | ||
2134 | (*ppfield)->ref = field->ref; | ||
2135 | field = field->next; | ||
2136 | ppfield = &((*ppfield)->next); | ||
2137 | } | ||
2138 | return 0; | ||
2139 | out_err: | ||
2140 | return -ENOMEM; | ||
2141 | } | ||
2142 | |||
2143 | int perf_probe_event__copy(struct perf_probe_event *dst, | ||
2144 | struct perf_probe_event *src) | ||
2145 | { | ||
2146 | int i; | ||
2147 | |||
2148 | dst->event = strdup_or_goto(src->event, out_err); | ||
2149 | dst->group = strdup_or_goto(src->group, out_err); | ||
2150 | dst->target = strdup_or_goto(src->target, out_err); | ||
2151 | dst->uprobes = src->uprobes; | ||
2152 | |||
2153 | if (perf_probe_point__copy(&dst->point, &src->point) < 0) | ||
2154 | goto out_err; | ||
2155 | |||
2156 | dst->args = zalloc(sizeof(struct perf_probe_arg) * src->nargs); | ||
2157 | if (!dst->args) | ||
2158 | goto out_err; | ||
2159 | dst->nargs = src->nargs; | ||
2160 | |||
2161 | for (i = 0; i < src->nargs; i++) | ||
2162 | if (perf_probe_arg__copy(&dst->args[i], &src->args[i]) < 0) | ||
2163 | goto out_err; | ||
2164 | return 0; | ||
2165 | |||
2166 | out_err: | ||
2167 | clear_perf_probe_event(dst); | ||
2168 | return -ENOMEM; | ||
2169 | } | ||
2170 | |||
2029 | void clear_probe_trace_event(struct probe_trace_event *tev) | 2171 | void clear_probe_trace_event(struct probe_trace_event *tev) |
2030 | { | 2172 | { |
2031 | struct probe_trace_arg_ref *ref, *next; | 2173 | struct probe_trace_arg_ref *ref, *next; |
@@ -2253,7 +2395,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe, | |||
2253 | if (!rawlist) | 2395 | if (!rawlist) |
2254 | return -ENOMEM; | 2396 | return -ENOMEM; |
2255 | 2397 | ||
2256 | strlist__for_each(ent, rawlist) { | 2398 | strlist__for_each_entry(ent, rawlist) { |
2257 | ret = parse_probe_trace_command(ent->s, &tev); | 2399 | ret = parse_probe_trace_command(ent->s, &tev); |
2258 | if (ret >= 0) { | 2400 | if (ret >= 0) { |
2259 | if (!filter_probe_trace_event(&tev, filter)) | 2401 | if (!filter_probe_trace_event(&tev, filter)) |
@@ -2286,6 +2428,9 @@ int show_perf_probe_events(struct strfilter *filter) | |||
2286 | 2428 | ||
2287 | setup_pager(); | 2429 | setup_pager(); |
2288 | 2430 | ||
2431 | if (probe_conf.cache) | ||
2432 | return probe_cache__show_all_caches(filter); | ||
2433 | |||
2289 | ret = init_probe_symbol_maps(false); | 2434 | ret = init_probe_symbol_maps(false); |
2290 | if (ret < 0) | 2435 | if (ret < 0) |
2291 | return ret; | 2436 | return ret; |
@@ -2394,17 +2539,24 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev, | |||
2394 | char buf[64]; | 2539 | char buf[64]; |
2395 | int ret; | 2540 | int ret; |
2396 | 2541 | ||
2397 | if (pev->event) | 2542 | /* If probe_event or trace_event already have the name, reuse it */ |
2543 | if (pev->event && !pev->sdt) | ||
2398 | event = pev->event; | 2544 | event = pev->event; |
2399 | else | 2545 | else if (tev->event) |
2546 | event = tev->event; | ||
2547 | else { | ||
2548 | /* Or generate new one from probe point */ | ||
2400 | if (pev->point.function && | 2549 | if (pev->point.function && |
2401 | (strncmp(pev->point.function, "0x", 2) != 0) && | 2550 | (strncmp(pev->point.function, "0x", 2) != 0) && |
2402 | !strisglob(pev->point.function)) | 2551 | !strisglob(pev->point.function)) |
2403 | event = pev->point.function; | 2552 | event = pev->point.function; |
2404 | else | 2553 | else |
2405 | event = tev->point.realname; | 2554 | event = tev->point.realname; |
2406 | if (pev->group) | 2555 | } |
2556 | if (pev->group && !pev->sdt) | ||
2407 | group = pev->group; | 2557 | group = pev->group; |
2558 | else if (tev->group) | ||
2559 | group = tev->group; | ||
2408 | else | 2560 | else |
2409 | group = PERFPROBE_GROUP; | 2561 | group = PERFPROBE_GROUP; |
2410 | 2562 | ||
@@ -2426,40 +2578,60 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev, | |||
2426 | return 0; | 2578 | return 0; |
2427 | } | 2579 | } |
2428 | 2580 | ||
2429 | static int __add_probe_trace_events(struct perf_probe_event *pev, | 2581 | static int __open_probe_file_and_namelist(bool uprobe, |
2430 | struct probe_trace_event *tevs, | 2582 | struct strlist **namelist) |
2431 | int ntevs, bool allow_suffix) | ||
2432 | { | 2583 | { |
2433 | int i, fd, ret; | 2584 | int fd; |
2434 | struct probe_trace_event *tev = NULL; | ||
2435 | struct strlist *namelist; | ||
2436 | 2585 | ||
2437 | fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0)); | 2586 | fd = probe_file__open(PF_FL_RW | (uprobe ? PF_FL_UPROBE : 0)); |
2438 | if (fd < 0) | 2587 | if (fd < 0) |
2439 | return fd; | 2588 | return fd; |
2440 | 2589 | ||
2441 | /* Get current event names */ | 2590 | /* Get current event names */ |
2442 | namelist = probe_file__get_namelist(fd); | 2591 | *namelist = probe_file__get_namelist(fd); |
2443 | if (!namelist) { | 2592 | if (!(*namelist)) { |
2444 | pr_debug("Failed to get current event list.\n"); | 2593 | pr_debug("Failed to get current event list.\n"); |
2445 | ret = -ENOMEM; | 2594 | close(fd); |
2446 | goto close_out; | 2595 | return -ENOMEM; |
2447 | } | 2596 | } |
2597 | return fd; | ||
2598 | } | ||
2599 | |||
2600 | static int __add_probe_trace_events(struct perf_probe_event *pev, | ||
2601 | struct probe_trace_event *tevs, | ||
2602 | int ntevs, bool allow_suffix) | ||
2603 | { | ||
2604 | int i, fd[2] = {-1, -1}, up, ret; | ||
2605 | struct probe_trace_event *tev = NULL; | ||
2606 | struct probe_cache *cache = NULL; | ||
2607 | struct strlist *namelist[2] = {NULL, NULL}; | ||
2608 | |||
2609 | up = pev->uprobes ? 1 : 0; | ||
2610 | fd[up] = __open_probe_file_and_namelist(up, &namelist[up]); | ||
2611 | if (fd[up] < 0) | ||
2612 | return fd[up]; | ||
2448 | 2613 | ||
2449 | ret = 0; | 2614 | ret = 0; |
2450 | for (i = 0; i < ntevs; i++) { | 2615 | for (i = 0; i < ntevs; i++) { |
2451 | tev = &tevs[i]; | 2616 | tev = &tevs[i]; |
2617 | up = tev->uprobes ? 1 : 0; | ||
2618 | if (fd[up] == -1) { /* Open the kprobe/uprobe_events */ | ||
2619 | fd[up] = __open_probe_file_and_namelist(up, | ||
2620 | &namelist[up]); | ||
2621 | if (fd[up] < 0) | ||
2622 | goto close_out; | ||
2623 | } | ||
2452 | /* Skip if the symbol is out of .text or blacklisted */ | 2624 | /* Skip if the symbol is out of .text or blacklisted */ |
2453 | if (!tev->point.symbol) | 2625 | if (!tev->point.symbol && !pev->uprobes) |
2454 | continue; | 2626 | continue; |
2455 | 2627 | ||
2456 | /* Set new name for tev (and update namelist) */ | 2628 | /* Set new name for tev (and update namelist) */ |
2457 | ret = probe_trace_event__set_name(tev, pev, namelist, | 2629 | ret = probe_trace_event__set_name(tev, pev, namelist[up], |
2458 | allow_suffix); | 2630 | allow_suffix); |
2459 | if (ret < 0) | 2631 | if (ret < 0) |
2460 | break; | 2632 | break; |
2461 | 2633 | ||
2462 | ret = probe_file__add_event(fd, tev); | 2634 | ret = probe_file__add_event(fd[up], tev); |
2463 | if (ret < 0) | 2635 | if (ret < 0) |
2464 | break; | 2636 | break; |
2465 | 2637 | ||
@@ -2473,10 +2645,21 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
2473 | } | 2645 | } |
2474 | if (ret == -EINVAL && pev->uprobes) | 2646 | if (ret == -EINVAL && pev->uprobes) |
2475 | warn_uprobe_event_compat(tev); | 2647 | warn_uprobe_event_compat(tev); |
2648 | if (ret == 0 && probe_conf.cache) { | ||
2649 | cache = probe_cache__new(pev->target); | ||
2650 | if (!cache || | ||
2651 | probe_cache__add_entry(cache, pev, tevs, ntevs) < 0 || | ||
2652 | probe_cache__commit(cache) < 0) | ||
2653 | pr_warning("Failed to add event to probe cache\n"); | ||
2654 | probe_cache__delete(cache); | ||
2655 | } | ||
2476 | 2656 | ||
2477 | strlist__delete(namelist); | ||
2478 | close_out: | 2657 | close_out: |
2479 | close(fd); | 2658 | for (up = 0; up < 2; up++) { |
2659 | strlist__delete(namelist[up]); | ||
2660 | if (fd[up] >= 0) | ||
2661 | close(fd[up]); | ||
2662 | } | ||
2480 | return ret; | 2663 | return ret; |
2481 | } | 2664 | } |
2482 | 2665 | ||
@@ -2501,9 +2684,6 @@ static int find_probe_functions(struct map *map, char *name, | |||
2501 | return found; | 2684 | return found; |
2502 | } | 2685 | } |
2503 | 2686 | ||
2504 | #define strdup_or_goto(str, label) \ | ||
2505 | ({ char *__p = strdup(str); if (!__p) goto label; __p; }) | ||
2506 | |||
2507 | void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused, | 2687 | void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused, |
2508 | struct probe_trace_event *tev __maybe_unused, | 2688 | struct probe_trace_event *tev __maybe_unused, |
2509 | struct map *map __maybe_unused, | 2689 | struct map *map __maybe_unused, |
@@ -2758,12 +2938,205 @@ errout: | |||
2758 | 2938 | ||
2759 | bool __weak arch__prefers_symtab(void) { return false; } | 2939 | bool __weak arch__prefers_symtab(void) { return false; } |
2760 | 2940 | ||
2941 | /* Concatinate two arrays */ | ||
2942 | static void *memcat(void *a, size_t sz_a, void *b, size_t sz_b) | ||
2943 | { | ||
2944 | void *ret; | ||
2945 | |||
2946 | ret = malloc(sz_a + sz_b); | ||
2947 | if (ret) { | ||
2948 | memcpy(ret, a, sz_a); | ||
2949 | memcpy(ret + sz_a, b, sz_b); | ||
2950 | } | ||
2951 | return ret; | ||
2952 | } | ||
2953 | |||
2954 | static int | ||
2955 | concat_probe_trace_events(struct probe_trace_event **tevs, int *ntevs, | ||
2956 | struct probe_trace_event **tevs2, int ntevs2) | ||
2957 | { | ||
2958 | struct probe_trace_event *new_tevs; | ||
2959 | int ret = 0; | ||
2960 | |||
2961 | if (ntevs == 0) { | ||
2962 | *tevs = *tevs2; | ||
2963 | *ntevs = ntevs2; | ||
2964 | *tevs2 = NULL; | ||
2965 | return 0; | ||
2966 | } | ||
2967 | |||
2968 | if (*ntevs + ntevs2 > probe_conf.max_probes) | ||
2969 | ret = -E2BIG; | ||
2970 | else { | ||
2971 | /* Concatinate the array of probe_trace_event */ | ||
2972 | new_tevs = memcat(*tevs, (*ntevs) * sizeof(**tevs), | ||
2973 | *tevs2, ntevs2 * sizeof(**tevs2)); | ||
2974 | if (!new_tevs) | ||
2975 | ret = -ENOMEM; | ||
2976 | else { | ||
2977 | free(*tevs); | ||
2978 | *tevs = new_tevs; | ||
2979 | *ntevs += ntevs2; | ||
2980 | } | ||
2981 | } | ||
2982 | if (ret < 0) | ||
2983 | clear_probe_trace_events(*tevs2, ntevs2); | ||
2984 | zfree(tevs2); | ||
2985 | |||
2986 | return ret; | ||
2987 | } | ||
2988 | |||
2989 | /* | ||
2990 | * Try to find probe_trace_event from given probe caches. Return the number | ||
2991 | * of cached events found, if an error occurs return the error. | ||
2992 | */ | ||
2993 | static int find_cached_events(struct perf_probe_event *pev, | ||
2994 | struct probe_trace_event **tevs, | ||
2995 | const char *target) | ||
2996 | { | ||
2997 | struct probe_cache *cache; | ||
2998 | struct probe_cache_entry *entry; | ||
2999 | struct probe_trace_event *tmp_tevs = NULL; | ||
3000 | int ntevs = 0; | ||
3001 | int ret = 0; | ||
3002 | |||
3003 | cache = probe_cache__new(target); | ||
3004 | /* Return 0 ("not found") if the target has no probe cache. */ | ||
3005 | if (!cache) | ||
3006 | return 0; | ||
3007 | |||
3008 | for_each_probe_cache_entry(entry, cache) { | ||
3009 | /* Skip the cache entry which has no name */ | ||
3010 | if (!entry->pev.event || !entry->pev.group) | ||
3011 | continue; | ||
3012 | if ((!pev->group || strglobmatch(entry->pev.group, pev->group)) && | ||
3013 | strglobmatch(entry->pev.event, pev->event)) { | ||
3014 | ret = probe_cache_entry__get_event(entry, &tmp_tevs); | ||
3015 | if (ret > 0) | ||
3016 | ret = concat_probe_trace_events(tevs, &ntevs, | ||
3017 | &tmp_tevs, ret); | ||
3018 | if (ret < 0) | ||
3019 | break; | ||
3020 | } | ||
3021 | } | ||
3022 | probe_cache__delete(cache); | ||
3023 | if (ret < 0) { | ||
3024 | clear_probe_trace_events(*tevs, ntevs); | ||
3025 | zfree(tevs); | ||
3026 | } else { | ||
3027 | ret = ntevs; | ||
3028 | if (ntevs > 0 && target && target[0] == '/') | ||
3029 | pev->uprobes = true; | ||
3030 | } | ||
3031 | |||
3032 | return ret; | ||
3033 | } | ||
3034 | |||
3035 | /* Try to find probe_trace_event from all probe caches */ | ||
3036 | static int find_cached_events_all(struct perf_probe_event *pev, | ||
3037 | struct probe_trace_event **tevs) | ||
3038 | { | ||
3039 | struct probe_trace_event *tmp_tevs = NULL; | ||
3040 | struct strlist *bidlist; | ||
3041 | struct str_node *nd; | ||
3042 | char *pathname; | ||
3043 | int ntevs = 0; | ||
3044 | int ret; | ||
3045 | |||
3046 | /* Get the buildid list of all valid caches */ | ||
3047 | bidlist = build_id_cache__list_all(true); | ||
3048 | if (!bidlist) { | ||
3049 | ret = -errno; | ||
3050 | pr_debug("Failed to get buildids: %d\n", ret); | ||
3051 | return ret; | ||
3052 | } | ||
3053 | |||
3054 | ret = 0; | ||
3055 | strlist__for_each_entry(nd, bidlist) { | ||
3056 | pathname = build_id_cache__origname(nd->s); | ||
3057 | ret = find_cached_events(pev, &tmp_tevs, pathname); | ||
3058 | /* In the case of cnt == 0, we just skip it */ | ||
3059 | if (ret > 0) | ||
3060 | ret = concat_probe_trace_events(tevs, &ntevs, | ||
3061 | &tmp_tevs, ret); | ||
3062 | free(pathname); | ||
3063 | if (ret < 0) | ||
3064 | break; | ||
3065 | } | ||
3066 | strlist__delete(bidlist); | ||
3067 | |||
3068 | if (ret < 0) { | ||
3069 | clear_probe_trace_events(*tevs, ntevs); | ||
3070 | zfree(tevs); | ||
3071 | } else | ||
3072 | ret = ntevs; | ||
3073 | |||
3074 | return ret; | ||
3075 | } | ||
3076 | |||
3077 | static int find_probe_trace_events_from_cache(struct perf_probe_event *pev, | ||
3078 | struct probe_trace_event **tevs) | ||
3079 | { | ||
3080 | struct probe_cache *cache; | ||
3081 | struct probe_cache_entry *entry; | ||
3082 | struct probe_trace_event *tev; | ||
3083 | struct str_node *node; | ||
3084 | int ret, i; | ||
3085 | |||
3086 | if (pev->sdt) { | ||
3087 | /* For SDT/cached events, we use special search functions */ | ||
3088 | if (!pev->target) | ||
3089 | return find_cached_events_all(pev, tevs); | ||
3090 | else | ||
3091 | return find_cached_events(pev, tevs, pev->target); | ||
3092 | } | ||
3093 | cache = probe_cache__new(pev->target); | ||
3094 | if (!cache) | ||
3095 | return 0; | ||
3096 | |||
3097 | entry = probe_cache__find(cache, pev); | ||
3098 | if (!entry) { | ||
3099 | /* SDT must be in the cache */ | ||
3100 | ret = pev->sdt ? -ENOENT : 0; | ||
3101 | goto out; | ||
3102 | } | ||
3103 | |||
3104 | ret = strlist__nr_entries(entry->tevlist); | ||
3105 | if (ret > probe_conf.max_probes) { | ||
3106 | pr_debug("Too many entries matched in the cache of %s\n", | ||
3107 | pev->target ? : "kernel"); | ||
3108 | ret = -E2BIG; | ||
3109 | goto out; | ||
3110 | } | ||
3111 | |||
3112 | *tevs = zalloc(ret * sizeof(*tev)); | ||
3113 | if (!*tevs) { | ||
3114 | ret = -ENOMEM; | ||
3115 | goto out; | ||
3116 | } | ||
3117 | |||
3118 | i = 0; | ||
3119 | strlist__for_each_entry(node, entry->tevlist) { | ||
3120 | tev = &(*tevs)[i++]; | ||
3121 | ret = parse_probe_trace_command(node->s, tev); | ||
3122 | if (ret < 0) | ||
3123 | goto out; | ||
3124 | /* Set the uprobes attribute as same as original */ | ||
3125 | tev->uprobes = pev->uprobes; | ||
3126 | } | ||
3127 | ret = i; | ||
3128 | |||
3129 | out: | ||
3130 | probe_cache__delete(cache); | ||
3131 | return ret; | ||
3132 | } | ||
3133 | |||
2761 | static int convert_to_probe_trace_events(struct perf_probe_event *pev, | 3134 | static int convert_to_probe_trace_events(struct perf_probe_event *pev, |
2762 | struct probe_trace_event **tevs) | 3135 | struct probe_trace_event **tevs) |
2763 | { | 3136 | { |
2764 | int ret; | 3137 | int ret; |
2765 | 3138 | ||
2766 | if (!pev->group) { | 3139 | if (!pev->group && !pev->sdt) { |
2767 | /* Set group name if not given */ | 3140 | /* Set group name if not given */ |
2768 | if (!pev->uprobes) { | 3141 | if (!pev->uprobes) { |
2769 | pev->group = strdup(PERFPROBE_GROUP); | 3142 | pev->group = strdup(PERFPROBE_GROUP); |
@@ -2780,6 +3153,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
2780 | if (ret > 0) | 3153 | if (ret > 0) |
2781 | return ret; | 3154 | return ret; |
2782 | 3155 | ||
3156 | /* At first, we need to lookup cache entry */ | ||
3157 | ret = find_probe_trace_events_from_cache(pev, tevs); | ||
3158 | if (ret > 0 || pev->sdt) /* SDT can be found only in the cache */ | ||
3159 | return ret == 0 ? -ENOENT : ret; /* Found in probe cache */ | ||
3160 | |||
2783 | if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { | 3161 | if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { |
2784 | ret = find_probe_trace_events_from_map(pev, tevs); | 3162 | ret = find_probe_trace_events_from_map(pev, tevs); |
2785 | if (ret > 0) | 3163 | if (ret > 0) |
@@ -2934,8 +3312,16 @@ int show_available_funcs(const char *target, struct strfilter *_filter, | |||
2934 | 3312 | ||
2935 | /* Load symbols with given filter */ | 3313 | /* Load symbols with given filter */ |
2936 | available_func_filter = _filter; | 3314 | available_func_filter = _filter; |
2937 | if (map__load(map, filter_available_functions)) { | 3315 | ret = map__load(map, filter_available_functions); |
2938 | pr_err("Failed to load symbols in %s\n", (target) ? : "kernel"); | 3316 | if (ret) { |
3317 | if (ret == -2) { | ||
3318 | char *str = strfilter__string(_filter); | ||
3319 | pr_err("Failed to find symbols matched to \"%s\"\n", | ||
3320 | str); | ||
3321 | free(str); | ||
3322 | } else | ||
3323 | pr_err("Failed to load symbols in %s\n", | ||
3324 | (target) ? : "kernel"); | ||
2939 | goto end; | 3325 | goto end; |
2940 | } | 3326 | } |
2941 | if (!dso__sorted_by_name(map->dso, map->type)) | 3327 | if (!dso__sorted_by_name(map->dso, map->type)) |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 5a27eb4fad05..e18ea9fe6385 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -12,6 +12,7 @@ struct probe_conf { | |||
12 | bool show_location_range; | 12 | bool show_location_range; |
13 | bool force_add; | 13 | bool force_add; |
14 | bool no_inlines; | 14 | bool no_inlines; |
15 | bool cache; | ||
15 | int max_probes; | 16 | int max_probes; |
16 | }; | 17 | }; |
17 | extern struct probe_conf probe_conf; | 18 | extern struct probe_conf probe_conf; |
@@ -84,6 +85,7 @@ struct perf_probe_event { | |||
84 | char *group; /* Group name */ | 85 | char *group; /* Group name */ |
85 | struct perf_probe_point point; /* Probe point */ | 86 | struct perf_probe_point point; /* Probe point */ |
86 | int nargs; /* Number of arguments */ | 87 | int nargs; /* Number of arguments */ |
88 | bool sdt; /* SDT/cached event flag */ | ||
87 | bool uprobes; /* Uprobe event flag */ | 89 | bool uprobes; /* Uprobe event flag */ |
88 | char *target; /* Target binary */ | 90 | char *target; /* Target binary */ |
89 | struct perf_probe_arg *args; /* Arguments */ | 91 | struct perf_probe_arg *args; /* Arguments */ |
@@ -121,6 +123,10 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev); | |||
121 | char *synthesize_perf_probe_command(struct perf_probe_event *pev); | 123 | char *synthesize_perf_probe_command(struct perf_probe_event *pev); |
122 | char *synthesize_probe_trace_command(struct probe_trace_event *tev); | 124 | char *synthesize_probe_trace_command(struct probe_trace_event *tev); |
123 | char *synthesize_perf_probe_arg(struct perf_probe_arg *pa); | 125 | char *synthesize_perf_probe_arg(struct perf_probe_arg *pa); |
126 | char *synthesize_perf_probe_point(struct perf_probe_point *pp); | ||
127 | |||
128 | int perf_probe_event__copy(struct perf_probe_event *dst, | ||
129 | struct perf_probe_event *src); | ||
124 | 130 | ||
125 | /* Check the perf_probe_event needs debuginfo */ | 131 | /* Check the perf_probe_event needs debuginfo */ |
126 | bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); | 132 | bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); |
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c index 3fe6214970e6..9aed9c332da6 100644 --- a/tools/perf/util/probe-file.c +++ b/tools/perf/util/probe-file.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | #include <sys/uio.h> | ||
17 | #include "util.h" | 18 | #include "util.h" |
18 | #include "event.h" | 19 | #include "event.h" |
19 | #include "strlist.h" | 20 | #include "strlist.h" |
@@ -49,7 +50,7 @@ static void print_open_warning(int err, bool uprobe) | |||
49 | else | 50 | else |
50 | pr_warning("Failed to open %cprobe_events: %s\n", | 51 | pr_warning("Failed to open %cprobe_events: %s\n", |
51 | uprobe ? 'u' : 'k', | 52 | uprobe ? 'u' : 'k', |
52 | strerror_r(-err, sbuf, sizeof(sbuf))); | 53 | str_error_r(-err, sbuf, sizeof(sbuf))); |
53 | } | 54 | } |
54 | 55 | ||
55 | static void print_both_open_warning(int kerr, int uerr) | 56 | static void print_both_open_warning(int kerr, int uerr) |
@@ -63,9 +64,9 @@ static void print_both_open_warning(int kerr, int uerr) | |||
63 | else { | 64 | else { |
64 | char sbuf[STRERR_BUFSIZE]; | 65 | char sbuf[STRERR_BUFSIZE]; |
65 | pr_warning("Failed to open kprobe events: %s.\n", | 66 | pr_warning("Failed to open kprobe events: %s.\n", |
66 | strerror_r(-kerr, sbuf, sizeof(sbuf))); | 67 | str_error_r(-kerr, sbuf, sizeof(sbuf))); |
67 | pr_warning("Failed to open uprobe events: %s.\n", | 68 | pr_warning("Failed to open uprobe events: %s.\n", |
68 | strerror_r(-uerr, sbuf, sizeof(sbuf))); | 69 | str_error_r(-uerr, sbuf, sizeof(sbuf))); |
69 | } | 70 | } |
70 | } | 71 | } |
71 | 72 | ||
@@ -177,7 +178,7 @@ static struct strlist *__probe_file__get_namelist(int fd, bool include_group) | |||
177 | if (!rawlist) | 178 | if (!rawlist) |
178 | return NULL; | 179 | return NULL; |
179 | sl = strlist__new(NULL, NULL); | 180 | sl = strlist__new(NULL, NULL); |
180 | strlist__for_each(ent, rawlist) { | 181 | strlist__for_each_entry(ent, rawlist) { |
181 | ret = parse_probe_trace_command(ent->s, &tev); | 182 | ret = parse_probe_trace_command(ent->s, &tev); |
182 | if (ret < 0) | 183 | if (ret < 0) |
183 | break; | 184 | break; |
@@ -223,7 +224,7 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev) | |||
223 | if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) { | 224 | if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) { |
224 | ret = -errno; | 225 | ret = -errno; |
225 | pr_warning("Failed to write event: %s\n", | 226 | pr_warning("Failed to write event: %s\n", |
226 | strerror_r(errno, sbuf, sizeof(sbuf))); | 227 | str_error_r(errno, sbuf, sizeof(sbuf))); |
227 | } | 228 | } |
228 | } | 229 | } |
229 | free(buf); | 230 | free(buf); |
@@ -261,7 +262,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent) | |||
261 | return 0; | 262 | return 0; |
262 | error: | 263 | error: |
263 | pr_warning("Failed to delete event: %s\n", | 264 | pr_warning("Failed to delete event: %s\n", |
264 | strerror_r(-ret, buf, sizeof(buf))); | 265 | str_error_r(-ret, buf, sizeof(buf))); |
265 | return ret; | 266 | return ret; |
266 | } | 267 | } |
267 | 268 | ||
@@ -280,7 +281,7 @@ int probe_file__get_events(int fd, struct strfilter *filter, | |||
280 | if (!namelist) | 281 | if (!namelist) |
281 | return -ENOENT; | 282 | return -ENOENT; |
282 | 283 | ||
283 | strlist__for_each(ent, namelist) { | 284 | strlist__for_each_entry(ent, namelist) { |
284 | p = strchr(ent->s, ':'); | 285 | p = strchr(ent->s, ':'); |
285 | if ((p && strfilter__compare(filter, p + 1)) || | 286 | if ((p && strfilter__compare(filter, p + 1)) || |
286 | strfilter__compare(filter, ent->s)) { | 287 | strfilter__compare(filter, ent->s)) { |
@@ -298,7 +299,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist) | |||
298 | int ret = 0; | 299 | int ret = 0; |
299 | struct str_node *ent; | 300 | struct str_node *ent; |
300 | 301 | ||
301 | strlist__for_each(ent, namelist) { | 302 | strlist__for_each_entry(ent, namelist) { |
302 | ret = __del_trace_probe_event(fd, ent); | 303 | ret = __del_trace_probe_event(fd, ent); |
303 | if (ret < 0) | 304 | if (ret < 0) |
304 | break; | 305 | break; |
@@ -324,3 +325,533 @@ int probe_file__del_events(int fd, struct strfilter *filter) | |||
324 | 325 | ||
325 | return ret; | 326 | return ret; |
326 | } | 327 | } |
328 | |||
329 | /* Caller must ensure to remove this entry from list */ | ||
330 | static void probe_cache_entry__delete(struct probe_cache_entry *entry) | ||
331 | { | ||
332 | if (entry) { | ||
333 | BUG_ON(!list_empty(&entry->node)); | ||
334 | |||
335 | strlist__delete(entry->tevlist); | ||
336 | clear_perf_probe_event(&entry->pev); | ||
337 | zfree(&entry->spev); | ||
338 | free(entry); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | static struct probe_cache_entry * | ||
343 | probe_cache_entry__new(struct perf_probe_event *pev) | ||
344 | { | ||
345 | struct probe_cache_entry *entry = zalloc(sizeof(*entry)); | ||
346 | |||
347 | if (entry) { | ||
348 | INIT_LIST_HEAD(&entry->node); | ||
349 | entry->tevlist = strlist__new(NULL, NULL); | ||
350 | if (!entry->tevlist) | ||
351 | zfree(&entry); | ||
352 | else if (pev) { | ||
353 | entry->spev = synthesize_perf_probe_command(pev); | ||
354 | if (!entry->spev || | ||
355 | perf_probe_event__copy(&entry->pev, pev) < 0) { | ||
356 | probe_cache_entry__delete(entry); | ||
357 | return NULL; | ||
358 | } | ||
359 | } | ||
360 | } | ||
361 | |||
362 | return entry; | ||
363 | } | ||
364 | |||
365 | int probe_cache_entry__get_event(struct probe_cache_entry *entry, | ||
366 | struct probe_trace_event **tevs) | ||
367 | { | ||
368 | struct probe_trace_event *tev; | ||
369 | struct str_node *node; | ||
370 | int ret, i; | ||
371 | |||
372 | ret = strlist__nr_entries(entry->tevlist); | ||
373 | if (ret > probe_conf.max_probes) | ||
374 | return -E2BIG; | ||
375 | |||
376 | *tevs = zalloc(ret * sizeof(*tev)); | ||
377 | if (!*tevs) | ||
378 | return -ENOMEM; | ||
379 | |||
380 | i = 0; | ||
381 | strlist__for_each_entry(node, entry->tevlist) { | ||
382 | tev = &(*tevs)[i++]; | ||
383 | ret = parse_probe_trace_command(node->s, tev); | ||
384 | if (ret < 0) | ||
385 | break; | ||
386 | } | ||
387 | return i; | ||
388 | } | ||
389 | |||
390 | /* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */ | ||
391 | static int probe_cache__open(struct probe_cache *pcache, const char *target) | ||
392 | { | ||
393 | char cpath[PATH_MAX]; | ||
394 | char sbuildid[SBUILD_ID_SIZE]; | ||
395 | char *dir_name = NULL; | ||
396 | bool is_kallsyms = false; | ||
397 | int ret, fd; | ||
398 | |||
399 | if (target && build_id_cache__cached(target)) { | ||
400 | /* This is a cached buildid */ | ||
401 | strncpy(sbuildid, target, SBUILD_ID_SIZE); | ||
402 | dir_name = build_id_cache__linkname(sbuildid, NULL, 0); | ||
403 | goto found; | ||
404 | } | ||
405 | |||
406 | if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) { | ||
407 | target = DSO__NAME_KALLSYMS; | ||
408 | is_kallsyms = true; | ||
409 | ret = sysfs__sprintf_build_id("/", sbuildid); | ||
410 | } else | ||
411 | ret = filename__sprintf_build_id(target, sbuildid); | ||
412 | |||
413 | if (ret < 0) { | ||
414 | pr_debug("Failed to get build-id from %s.\n", target); | ||
415 | return ret; | ||
416 | } | ||
417 | |||
418 | /* If we have no buildid cache, make it */ | ||
419 | if (!build_id_cache__cached(sbuildid)) { | ||
420 | ret = build_id_cache__add_s(sbuildid, target, | ||
421 | is_kallsyms, NULL); | ||
422 | if (ret < 0) { | ||
423 | pr_debug("Failed to add build-id cache: %s\n", target); | ||
424 | return ret; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms, | ||
429 | false); | ||
430 | found: | ||
431 | if (!dir_name) { | ||
432 | pr_debug("Failed to get cache from %s\n", target); | ||
433 | return -ENOMEM; | ||
434 | } | ||
435 | |||
436 | snprintf(cpath, PATH_MAX, "%s/probes", dir_name); | ||
437 | fd = open(cpath, O_CREAT | O_RDWR, 0644); | ||
438 | if (fd < 0) | ||
439 | pr_debug("Failed to open cache(%d): %s\n", fd, cpath); | ||
440 | free(dir_name); | ||
441 | pcache->fd = fd; | ||
442 | |||
443 | return fd; | ||
444 | } | ||
445 | |||
446 | static int probe_cache__load(struct probe_cache *pcache) | ||
447 | { | ||
448 | struct probe_cache_entry *entry = NULL; | ||
449 | char buf[MAX_CMDLEN], *p; | ||
450 | int ret = 0; | ||
451 | FILE *fp; | ||
452 | |||
453 | fp = fdopen(dup(pcache->fd), "r"); | ||
454 | if (!fp) | ||
455 | return -EINVAL; | ||
456 | |||
457 | while (!feof(fp)) { | ||
458 | if (!fgets(buf, MAX_CMDLEN, fp)) | ||
459 | break; | ||
460 | p = strchr(buf, '\n'); | ||
461 | if (p) | ||
462 | *p = '\0'; | ||
463 | /* #perf_probe_event or %sdt_event */ | ||
464 | if (buf[0] == '#' || buf[0] == '%') { | ||
465 | entry = probe_cache_entry__new(NULL); | ||
466 | if (!entry) { | ||
467 | ret = -ENOMEM; | ||
468 | goto out; | ||
469 | } | ||
470 | if (buf[0] == '%') | ||
471 | entry->sdt = true; | ||
472 | entry->spev = strdup(buf + 1); | ||
473 | if (entry->spev) | ||
474 | ret = parse_perf_probe_command(buf + 1, | ||
475 | &entry->pev); | ||
476 | else | ||
477 | ret = -ENOMEM; | ||
478 | if (ret < 0) { | ||
479 | probe_cache_entry__delete(entry); | ||
480 | goto out; | ||
481 | } | ||
482 | list_add_tail(&entry->node, &pcache->entries); | ||
483 | } else { /* trace_probe_event */ | ||
484 | if (!entry) { | ||
485 | ret = -EINVAL; | ||
486 | goto out; | ||
487 | } | ||
488 | strlist__add(entry->tevlist, buf); | ||
489 | } | ||
490 | } | ||
491 | out: | ||
492 | fclose(fp); | ||
493 | return ret; | ||
494 | } | ||
495 | |||
496 | static struct probe_cache *probe_cache__alloc(void) | ||
497 | { | ||
498 | struct probe_cache *pcache = zalloc(sizeof(*pcache)); | ||
499 | |||
500 | if (pcache) { | ||
501 | INIT_LIST_HEAD(&pcache->entries); | ||
502 | pcache->fd = -EINVAL; | ||
503 | } | ||
504 | return pcache; | ||
505 | } | ||
506 | |||
507 | void probe_cache__purge(struct probe_cache *pcache) | ||
508 | { | ||
509 | struct probe_cache_entry *entry, *n; | ||
510 | |||
511 | list_for_each_entry_safe(entry, n, &pcache->entries, node) { | ||
512 | list_del_init(&entry->node); | ||
513 | probe_cache_entry__delete(entry); | ||
514 | } | ||
515 | } | ||
516 | |||
517 | void probe_cache__delete(struct probe_cache *pcache) | ||
518 | { | ||
519 | if (!pcache) | ||
520 | return; | ||
521 | |||
522 | probe_cache__purge(pcache); | ||
523 | if (pcache->fd > 0) | ||
524 | close(pcache->fd); | ||
525 | free(pcache); | ||
526 | } | ||
527 | |||
528 | struct probe_cache *probe_cache__new(const char *target) | ||
529 | { | ||
530 | struct probe_cache *pcache = probe_cache__alloc(); | ||
531 | int ret; | ||
532 | |||
533 | if (!pcache) | ||
534 | return NULL; | ||
535 | |||
536 | ret = probe_cache__open(pcache, target); | ||
537 | if (ret < 0) { | ||
538 | pr_debug("Cache open error: %d\n", ret); | ||
539 | goto out_err; | ||
540 | } | ||
541 | |||
542 | ret = probe_cache__load(pcache); | ||
543 | if (ret < 0) { | ||
544 | pr_debug("Cache read error: %d\n", ret); | ||
545 | goto out_err; | ||
546 | } | ||
547 | |||
548 | return pcache; | ||
549 | |||
550 | out_err: | ||
551 | probe_cache__delete(pcache); | ||
552 | return NULL; | ||
553 | } | ||
554 | |||
555 | static bool streql(const char *a, const char *b) | ||
556 | { | ||
557 | if (a == b) | ||
558 | return true; | ||
559 | |||
560 | if (!a || !b) | ||
561 | return false; | ||
562 | |||
563 | return !strcmp(a, b); | ||
564 | } | ||
565 | |||
566 | struct probe_cache_entry * | ||
567 | probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev) | ||
568 | { | ||
569 | struct probe_cache_entry *entry = NULL; | ||
570 | char *cmd = synthesize_perf_probe_command(pev); | ||
571 | |||
572 | if (!cmd) | ||
573 | return NULL; | ||
574 | |||
575 | for_each_probe_cache_entry(entry, pcache) { | ||
576 | if (pev->sdt) { | ||
577 | if (entry->pev.event && | ||
578 | streql(entry->pev.event, pev->event) && | ||
579 | (!pev->group || | ||
580 | streql(entry->pev.group, pev->group))) | ||
581 | goto found; | ||
582 | |||
583 | continue; | ||
584 | } | ||
585 | /* Hit if same event name or same command-string */ | ||
586 | if ((pev->event && | ||
587 | (streql(entry->pev.group, pev->group) && | ||
588 | streql(entry->pev.event, pev->event))) || | ||
589 | (!strcmp(entry->spev, cmd))) | ||
590 | goto found; | ||
591 | } | ||
592 | entry = NULL; | ||
593 | |||
594 | found: | ||
595 | free(cmd); | ||
596 | return entry; | ||
597 | } | ||
598 | |||
599 | struct probe_cache_entry * | ||
600 | probe_cache__find_by_name(struct probe_cache *pcache, | ||
601 | const char *group, const char *event) | ||
602 | { | ||
603 | struct probe_cache_entry *entry = NULL; | ||
604 | |||
605 | for_each_probe_cache_entry(entry, pcache) { | ||
606 | /* Hit if same event name or same command-string */ | ||
607 | if (streql(entry->pev.group, group) && | ||
608 | streql(entry->pev.event, event)) | ||
609 | goto found; | ||
610 | } | ||
611 | entry = NULL; | ||
612 | |||
613 | found: | ||
614 | return entry; | ||
615 | } | ||
616 | |||
617 | int probe_cache__add_entry(struct probe_cache *pcache, | ||
618 | struct perf_probe_event *pev, | ||
619 | struct probe_trace_event *tevs, int ntevs) | ||
620 | { | ||
621 | struct probe_cache_entry *entry = NULL; | ||
622 | char *command; | ||
623 | int i, ret = 0; | ||
624 | |||
625 | if (!pcache || !pev || !tevs || ntevs <= 0) { | ||
626 | ret = -EINVAL; | ||
627 | goto out_err; | ||
628 | } | ||
629 | |||
630 | /* Remove old cache entry */ | ||
631 | entry = probe_cache__find(pcache, pev); | ||
632 | if (entry) { | ||
633 | list_del_init(&entry->node); | ||
634 | probe_cache_entry__delete(entry); | ||
635 | } | ||
636 | |||
637 | ret = -ENOMEM; | ||
638 | entry = probe_cache_entry__new(pev); | ||
639 | if (!entry) | ||
640 | goto out_err; | ||
641 | |||
642 | for (i = 0; i < ntevs; i++) { | ||
643 | if (!tevs[i].point.symbol) | ||
644 | continue; | ||
645 | |||
646 | command = synthesize_probe_trace_command(&tevs[i]); | ||
647 | if (!command) | ||
648 | goto out_err; | ||
649 | strlist__add(entry->tevlist, command); | ||
650 | free(command); | ||
651 | } | ||
652 | list_add_tail(&entry->node, &pcache->entries); | ||
653 | pr_debug("Added probe cache: %d\n", ntevs); | ||
654 | return 0; | ||
655 | |||
656 | out_err: | ||
657 | pr_debug("Failed to add probe caches\n"); | ||
658 | probe_cache_entry__delete(entry); | ||
659 | return ret; | ||
660 | } | ||
661 | |||
662 | #ifdef HAVE_GELF_GETNOTE_SUPPORT | ||
663 | static unsigned long long sdt_note__get_addr(struct sdt_note *note) | ||
664 | { | ||
665 | return note->bit32 ? (unsigned long long)note->addr.a32[0] | ||
666 | : (unsigned long long)note->addr.a64[0]; | ||
667 | } | ||
668 | |||
669 | int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname) | ||
670 | { | ||
671 | struct probe_cache_entry *entry = NULL; | ||
672 | struct list_head sdtlist; | ||
673 | struct sdt_note *note; | ||
674 | char *buf; | ||
675 | char sdtgrp[64]; | ||
676 | int ret; | ||
677 | |||
678 | INIT_LIST_HEAD(&sdtlist); | ||
679 | ret = get_sdt_note_list(&sdtlist, pathname); | ||
680 | if (ret < 0) { | ||
681 | pr_debug("Failed to get sdt note: %d\n", ret); | ||
682 | return ret; | ||
683 | } | ||
684 | list_for_each_entry(note, &sdtlist, note_list) { | ||
685 | ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider); | ||
686 | if (ret < 0) | ||
687 | break; | ||
688 | /* Try to find same-name entry */ | ||
689 | entry = probe_cache__find_by_name(pcache, sdtgrp, note->name); | ||
690 | if (!entry) { | ||
691 | entry = probe_cache_entry__new(NULL); | ||
692 | if (!entry) { | ||
693 | ret = -ENOMEM; | ||
694 | break; | ||
695 | } | ||
696 | entry->sdt = true; | ||
697 | ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp, | ||
698 | note->name, note->name); | ||
699 | if (ret < 0) | ||
700 | break; | ||
701 | entry->pev.event = strdup(note->name); | ||
702 | entry->pev.group = strdup(sdtgrp); | ||
703 | list_add_tail(&entry->node, &pcache->entries); | ||
704 | } | ||
705 | ret = asprintf(&buf, "p:%s/%s %s:0x%llx", | ||
706 | sdtgrp, note->name, pathname, | ||
707 | sdt_note__get_addr(note)); | ||
708 | if (ret < 0) | ||
709 | break; | ||
710 | strlist__add(entry->tevlist, buf); | ||
711 | free(buf); | ||
712 | entry = NULL; | ||
713 | } | ||
714 | if (entry) { | ||
715 | list_del_init(&entry->node); | ||
716 | probe_cache_entry__delete(entry); | ||
717 | } | ||
718 | cleanup_sdt_note_list(&sdtlist); | ||
719 | return ret; | ||
720 | } | ||
721 | #endif | ||
722 | |||
723 | static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd) | ||
724 | { | ||
725 | struct str_node *snode; | ||
726 | struct stat st; | ||
727 | struct iovec iov[3]; | ||
728 | const char *prefix = entry->sdt ? "%" : "#"; | ||
729 | int ret; | ||
730 | /* Save stat for rollback */ | ||
731 | ret = fstat(fd, &st); | ||
732 | if (ret < 0) | ||
733 | return ret; | ||
734 | |||
735 | pr_debug("Writing cache: %s%s\n", prefix, entry->spev); | ||
736 | iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1; | ||
737 | iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev); | ||
738 | iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1; | ||
739 | ret = writev(fd, iov, 3); | ||
740 | if (ret < (int)iov[1].iov_len + 2) | ||
741 | goto rollback; | ||
742 | |||
743 | strlist__for_each_entry(snode, entry->tevlist) { | ||
744 | iov[0].iov_base = (void *)snode->s; | ||
745 | iov[0].iov_len = strlen(snode->s); | ||
746 | iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1; | ||
747 | ret = writev(fd, iov, 2); | ||
748 | if (ret < (int)iov[0].iov_len + 1) | ||
749 | goto rollback; | ||
750 | } | ||
751 | return 0; | ||
752 | |||
753 | rollback: | ||
754 | /* Rollback to avoid cache file corruption */ | ||
755 | if (ret > 0) | ||
756 | ret = -1; | ||
757 | if (ftruncate(fd, st.st_size) < 0) | ||
758 | ret = -2; | ||
759 | |||
760 | return ret; | ||
761 | } | ||
762 | |||
763 | int probe_cache__commit(struct probe_cache *pcache) | ||
764 | { | ||
765 | struct probe_cache_entry *entry; | ||
766 | int ret = 0; | ||
767 | |||
768 | /* TBD: if we do not update existing entries, skip it */ | ||
769 | ret = lseek(pcache->fd, 0, SEEK_SET); | ||
770 | if (ret < 0) | ||
771 | goto out; | ||
772 | |||
773 | ret = ftruncate(pcache->fd, 0); | ||
774 | if (ret < 0) | ||
775 | goto out; | ||
776 | |||
777 | for_each_probe_cache_entry(entry, pcache) { | ||
778 | ret = probe_cache_entry__write(entry, pcache->fd); | ||
779 | pr_debug("Cache committed: %d\n", ret); | ||
780 | if (ret < 0) | ||
781 | break; | ||
782 | } | ||
783 | out: | ||
784 | return ret; | ||
785 | } | ||
786 | |||
787 | static bool probe_cache_entry__compare(struct probe_cache_entry *entry, | ||
788 | struct strfilter *filter) | ||
789 | { | ||
790 | char buf[128], *ptr = entry->spev; | ||
791 | |||
792 | if (entry->pev.event) { | ||
793 | snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event); | ||
794 | ptr = buf; | ||
795 | } | ||
796 | return strfilter__compare(filter, ptr); | ||
797 | } | ||
798 | |||
799 | int probe_cache__filter_purge(struct probe_cache *pcache, | ||
800 | struct strfilter *filter) | ||
801 | { | ||
802 | struct probe_cache_entry *entry, *tmp; | ||
803 | |||
804 | list_for_each_entry_safe(entry, tmp, &pcache->entries, node) { | ||
805 | if (probe_cache_entry__compare(entry, filter)) { | ||
806 | pr_info("Removed cached event: %s\n", entry->spev); | ||
807 | list_del_init(&entry->node); | ||
808 | probe_cache_entry__delete(entry); | ||
809 | } | ||
810 | } | ||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | static int probe_cache__show_entries(struct probe_cache *pcache, | ||
815 | struct strfilter *filter) | ||
816 | { | ||
817 | struct probe_cache_entry *entry; | ||
818 | |||
819 | for_each_probe_cache_entry(entry, pcache) { | ||
820 | if (probe_cache_entry__compare(entry, filter)) | ||
821 | printf("%s\n", entry->spev); | ||
822 | } | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | /* Show all cached probes */ | ||
827 | int probe_cache__show_all_caches(struct strfilter *filter) | ||
828 | { | ||
829 | struct probe_cache *pcache; | ||
830 | struct strlist *bidlist; | ||
831 | struct str_node *nd; | ||
832 | char *buf = strfilter__string(filter); | ||
833 | |||
834 | pr_debug("list cache with filter: %s\n", buf); | ||
835 | free(buf); | ||
836 | |||
837 | bidlist = build_id_cache__list_all(true); | ||
838 | if (!bidlist) { | ||
839 | pr_debug("Failed to get buildids: %d\n", errno); | ||
840 | return -EINVAL; | ||
841 | } | ||
842 | strlist__for_each_entry(nd, bidlist) { | ||
843 | pcache = probe_cache__new(nd->s); | ||
844 | if (!pcache) | ||
845 | continue; | ||
846 | if (!list_empty(&pcache->entries)) { | ||
847 | buf = build_id_cache__origname(nd->s); | ||
848 | printf("%s (%s):\n", buf, nd->s); | ||
849 | free(buf); | ||
850 | probe_cache__show_entries(pcache, filter); | ||
851 | } | ||
852 | probe_cache__delete(pcache); | ||
853 | } | ||
854 | strlist__delete(bidlist); | ||
855 | |||
856 | return 0; | ||
857 | } | ||
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h index 18ac9cf51c34..9577b5c0b487 100644 --- a/tools/perf/util/probe-file.h +++ b/tools/perf/util/probe-file.h | |||
@@ -5,9 +5,27 @@ | |||
5 | #include "strfilter.h" | 5 | #include "strfilter.h" |
6 | #include "probe-event.h" | 6 | #include "probe-event.h" |
7 | 7 | ||
8 | /* Cache of probe definitions */ | ||
9 | struct probe_cache_entry { | ||
10 | struct list_head node; | ||
11 | bool sdt; | ||
12 | struct perf_probe_event pev; | ||
13 | char *spev; | ||
14 | struct strlist *tevlist; | ||
15 | }; | ||
16 | |||
17 | struct probe_cache { | ||
18 | int fd; | ||
19 | struct list_head entries; | ||
20 | }; | ||
21 | |||
8 | #define PF_FL_UPROBE 1 | 22 | #define PF_FL_UPROBE 1 |
9 | #define PF_FL_RW 2 | 23 | #define PF_FL_RW 2 |
24 | #define for_each_probe_cache_entry(entry, pcache) \ | ||
25 | list_for_each_entry(entry, &pcache->entries, node) | ||
10 | 26 | ||
27 | /* probe-file.c depends on libelf */ | ||
28 | #ifdef HAVE_LIBELF_SUPPORT | ||
11 | int probe_file__open(int flag); | 29 | int probe_file__open(int flag); |
12 | int probe_file__open_both(int *kfd, int *ufd, int flag); | 30 | int probe_file__open_both(int *kfd, int *ufd, int flag); |
13 | struct strlist *probe_file__get_namelist(int fd); | 31 | struct strlist *probe_file__get_namelist(int fd); |
@@ -18,5 +36,29 @@ int probe_file__get_events(int fd, struct strfilter *filter, | |||
18 | struct strlist *plist); | 36 | struct strlist *plist); |
19 | int probe_file__del_strlist(int fd, struct strlist *namelist); | 37 | int probe_file__del_strlist(int fd, struct strlist *namelist); |
20 | 38 | ||
39 | int probe_cache_entry__get_event(struct probe_cache_entry *entry, | ||
40 | struct probe_trace_event **tevs); | ||
21 | 41 | ||
42 | struct probe_cache *probe_cache__new(const char *target); | ||
43 | int probe_cache__add_entry(struct probe_cache *pcache, | ||
44 | struct perf_probe_event *pev, | ||
45 | struct probe_trace_event *tevs, int ntevs); | ||
46 | int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname); | ||
47 | int probe_cache__commit(struct probe_cache *pcache); | ||
48 | void probe_cache__purge(struct probe_cache *pcache); | ||
49 | void probe_cache__delete(struct probe_cache *pcache); | ||
50 | int probe_cache__filter_purge(struct probe_cache *pcache, | ||
51 | struct strfilter *filter); | ||
52 | struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache, | ||
53 | struct perf_probe_event *pev); | ||
54 | struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache, | ||
55 | const char *group, const char *event); | ||
56 | int probe_cache__show_all_caches(struct strfilter *filter); | ||
57 | #else /* ! HAVE_LIBELF_SUPPORT */ | ||
58 | static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused) | ||
59 | { | ||
60 | return NULL; | ||
61 | } | ||
62 | #define probe_cache__delete(pcache) do {} while (0) | ||
63 | #endif | ||
22 | #endif | 64 | #endif |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 1259839dbf6d..f2d9ff064e2d 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -381,7 +381,7 @@ formatted: | |||
381 | if (ret >= 16) | 381 | if (ret >= 16) |
382 | ret = -E2BIG; | 382 | ret = -E2BIG; |
383 | pr_warning("Failed to convert variable type: %s\n", | 383 | pr_warning("Failed to convert variable type: %s\n", |
384 | strerror_r(-ret, sbuf, sizeof(sbuf))); | 384 | str_error_r(-ret, sbuf, sizeof(sbuf))); |
385 | return ret; | 385 | return ret; |
386 | } | 386 | } |
387 | tvar->type = strdup(buf); | 387 | tvar->type = strdup(buf); |
@@ -809,7 +809,7 @@ static int find_lazy_match_lines(struct intlist *list, | |||
809 | fp = fopen(fname, "r"); | 809 | fp = fopen(fname, "r"); |
810 | if (!fp) { | 810 | if (!fp) { |
811 | pr_warning("Failed to open %s: %s\n", fname, | 811 | pr_warning("Failed to open %s: %s\n", fname, |
812 | strerror_r(errno, sbuf, sizeof(sbuf))); | 812 | str_error_r(errno, sbuf, sizeof(sbuf))); |
813 | return -errno; | 813 | return -errno; |
814 | } | 814 | } |
815 | 815 | ||
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 36c6862119e3..b7d4f4aeee61 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources | |||
@@ -13,6 +13,7 @@ util/cpumap.c | |||
13 | ../lib/bitmap.c | 13 | ../lib/bitmap.c |
14 | ../lib/find_bit.c | 14 | ../lib/find_bit.c |
15 | ../lib/hweight.c | 15 | ../lib/hweight.c |
16 | ../lib/vsprintf.c | ||
16 | util/thread_map.c | 17 | util/thread_map.c |
17 | util/util.c | 18 | util/util.c |
18 | util/xyarray.c | 19 | util/xyarray.c |
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 98f127abfa42..a5fbc012e3df 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <structmember.h> | 2 | #include <structmember.h> |
3 | #include <inttypes.h> | 3 | #include <inttypes.h> |
4 | #include <poll.h> | 4 | #include <poll.h> |
5 | #include <linux/err.h> | ||
5 | #include "evlist.h" | 6 | #include "evlist.h" |
6 | #include "evsel.h" | 7 | #include "evsel.h" |
7 | #include "event.h" | 8 | #include "event.h" |
@@ -47,6 +48,7 @@ PyMODINIT_FUNC initperf(void); | |||
47 | 48 | ||
48 | struct pyrf_event { | 49 | struct pyrf_event { |
49 | PyObject_HEAD | 50 | PyObject_HEAD |
51 | struct perf_evsel *evsel; | ||
50 | struct perf_sample sample; | 52 | struct perf_sample sample; |
51 | union perf_event event; | 53 | union perf_event event; |
52 | }; | 54 | }; |
@@ -288,6 +290,85 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent) | |||
288 | return ret; | 290 | return ret; |
289 | } | 291 | } |
290 | 292 | ||
293 | static bool is_tracepoint(struct pyrf_event *pevent) | ||
294 | { | ||
295 | return pevent->evsel->attr.type == PERF_TYPE_TRACEPOINT; | ||
296 | } | ||
297 | |||
298 | static PyObject* | ||
299 | tracepoint_field(struct pyrf_event *pe, struct format_field *field) | ||
300 | { | ||
301 | struct pevent *pevent = field->event->pevent; | ||
302 | void *data = pe->sample.raw_data; | ||
303 | PyObject *ret = NULL; | ||
304 | unsigned long long val; | ||
305 | unsigned int offset, len; | ||
306 | |||
307 | if (field->flags & FIELD_IS_ARRAY) { | ||
308 | offset = field->offset; | ||
309 | len = field->size; | ||
310 | if (field->flags & FIELD_IS_DYNAMIC) { | ||
311 | val = pevent_read_number(pevent, data + offset, len); | ||
312 | offset = val; | ||
313 | len = offset >> 16; | ||
314 | offset &= 0xffff; | ||
315 | } | ||
316 | if (field->flags & FIELD_IS_STRING && | ||
317 | is_printable_array(data + offset, len)) { | ||
318 | ret = PyString_FromString((char *)data + offset); | ||
319 | } else { | ||
320 | ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); | ||
321 | field->flags &= ~FIELD_IS_STRING; | ||
322 | } | ||
323 | } else { | ||
324 | val = pevent_read_number(pevent, data + field->offset, | ||
325 | field->size); | ||
326 | if (field->flags & FIELD_IS_POINTER) | ||
327 | ret = PyLong_FromUnsignedLong((unsigned long) val); | ||
328 | else if (field->flags & FIELD_IS_SIGNED) | ||
329 | ret = PyLong_FromLong((long) val); | ||
330 | else | ||
331 | ret = PyLong_FromUnsignedLong((unsigned long) val); | ||
332 | } | ||
333 | |||
334 | return ret; | ||
335 | } | ||
336 | |||
337 | static PyObject* | ||
338 | get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) | ||
339 | { | ||
340 | const char *str = PyString_AsString(PyObject_Str(attr_name)); | ||
341 | struct perf_evsel *evsel = pevent->evsel; | ||
342 | struct format_field *field; | ||
343 | |||
344 | if (!evsel->tp_format) { | ||
345 | struct event_format *tp_format; | ||
346 | |||
347 | tp_format = trace_event__tp_format_id(evsel->attr.config); | ||
348 | if (!tp_format) | ||
349 | return NULL; | ||
350 | |||
351 | evsel->tp_format = tp_format; | ||
352 | } | ||
353 | |||
354 | field = pevent_find_any_field(evsel->tp_format, str); | ||
355 | if (!field) | ||
356 | return NULL; | ||
357 | |||
358 | return tracepoint_field(pevent, field); | ||
359 | } | ||
360 | |||
361 | static PyObject* | ||
362 | pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name) | ||
363 | { | ||
364 | PyObject *obj = NULL; | ||
365 | |||
366 | if (is_tracepoint(pevent)) | ||
367 | obj = get_tracepoint_field(pevent, attr_name); | ||
368 | |||
369 | return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name); | ||
370 | } | ||
371 | |||
291 | static PyTypeObject pyrf_sample_event__type = { | 372 | static PyTypeObject pyrf_sample_event__type = { |
292 | PyVarObject_HEAD_INIT(NULL, 0) | 373 | PyVarObject_HEAD_INIT(NULL, 0) |
293 | .tp_name = "perf.sample_event", | 374 | .tp_name = "perf.sample_event", |
@@ -296,6 +377,7 @@ static PyTypeObject pyrf_sample_event__type = { | |||
296 | .tp_doc = pyrf_sample_event__doc, | 377 | .tp_doc = pyrf_sample_event__doc, |
297 | .tp_members = pyrf_sample_event__members, | 378 | .tp_members = pyrf_sample_event__members, |
298 | .tp_repr = (reprfunc)pyrf_sample_event__repr, | 379 | .tp_repr = (reprfunc)pyrf_sample_event__repr, |
380 | .tp_getattro = (getattrofunc) pyrf_sample_event__getattro, | ||
299 | }; | 381 | }; |
300 | 382 | ||
301 | static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); | 383 | static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); |
@@ -653,6 +735,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, | |||
653 | attr.precise_ip = precise_ip; | 735 | attr.precise_ip = precise_ip; |
654 | attr.mmap_data = mmap_data; | 736 | attr.mmap_data = mmap_data; |
655 | attr.sample_id_all = sample_id_all; | 737 | attr.sample_id_all = sample_id_all; |
738 | attr.size = sizeof(attr); | ||
656 | 739 | ||
657 | perf_evsel__init(&pevsel->evsel, &attr, idx); | 740 | perf_evsel__init(&pevsel->evsel, &attr, idx); |
658 | return 0; | 741 | return 0; |
@@ -863,13 +946,22 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, | |||
863 | if (event != NULL) { | 946 | if (event != NULL) { |
864 | PyObject *pyevent = pyrf_event__new(event); | 947 | PyObject *pyevent = pyrf_event__new(event); |
865 | struct pyrf_event *pevent = (struct pyrf_event *)pyevent; | 948 | struct pyrf_event *pevent = (struct pyrf_event *)pyevent; |
866 | 949 | struct perf_evsel *evsel; | |
867 | perf_evlist__mmap_consume(evlist, cpu); | ||
868 | 950 | ||
869 | if (pyevent == NULL) | 951 | if (pyevent == NULL) |
870 | return PyErr_NoMemory(); | 952 | return PyErr_NoMemory(); |
871 | 953 | ||
872 | err = perf_evlist__parse_sample(evlist, event, &pevent->sample); | 954 | evsel = perf_evlist__event2evsel(evlist, event); |
955 | if (!evsel) | ||
956 | return Py_None; | ||
957 | |||
958 | pevent->evsel = evsel; | ||
959 | |||
960 | err = perf_evsel__parse_sample(evsel, event, &pevent->sample); | ||
961 | |||
962 | /* Consume the even only after we parsed it out. */ | ||
963 | perf_evlist__mmap_consume(evlist, cpu); | ||
964 | |||
873 | if (err) | 965 | if (err) |
874 | return PyErr_Format(PyExc_OSError, | 966 | return PyErr_Format(PyExc_OSError, |
875 | "perf: can't parse sample, err=%d", err); | 967 | "perf: can't parse sample, err=%d", err); |
@@ -957,7 +1049,7 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) | |||
957 | if (i >= pevlist->evlist.nr_entries) | 1049 | if (i >= pevlist->evlist.nr_entries) |
958 | return NULL; | 1050 | return NULL; |
959 | 1051 | ||
960 | evlist__for_each(&pevlist->evlist, pos) { | 1052 | evlist__for_each_entry(&pevlist->evlist, pos) { |
961 | if (i-- == 0) | 1053 | if (i-- == 0) |
962 | break; | 1054 | break; |
963 | } | 1055 | } |
@@ -1073,7 +1165,32 @@ static struct { | |||
1073 | { .name = NULL, }, | 1165 | { .name = NULL, }, |
1074 | }; | 1166 | }; |
1075 | 1167 | ||
1168 | static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel, | ||
1169 | PyObject *args, PyObject *kwargs) | ||
1170 | { | ||
1171 | struct event_format *tp_format; | ||
1172 | static char *kwlist[] = { "sys", "name", NULL }; | ||
1173 | char *sys = NULL; | ||
1174 | char *name = NULL; | ||
1175 | |||
1176 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss", kwlist, | ||
1177 | &sys, &name)) | ||
1178 | return NULL; | ||
1179 | |||
1180 | tp_format = trace_event__tp_format(sys, name); | ||
1181 | if (IS_ERR(tp_format)) | ||
1182 | return PyInt_FromLong(-1); | ||
1183 | |||
1184 | return PyInt_FromLong(tp_format->id); | ||
1185 | } | ||
1186 | |||
1076 | static PyMethodDef perf__methods[] = { | 1187 | static PyMethodDef perf__methods[] = { |
1188 | { | ||
1189 | .ml_name = "tracepoint", | ||
1190 | .ml_meth = (PyCFunction) pyrf__tracepoint, | ||
1191 | .ml_flags = METH_VARARGS | METH_KEYWORDS, | ||
1192 | .ml_doc = PyDoc_STR("Get tracepoint config.") | ||
1193 | }, | ||
1077 | { .ml_name = NULL, } | 1194 | { .ml_name = NULL, } |
1078 | }; | 1195 | }; |
1079 | 1196 | ||
@@ -1100,6 +1217,33 @@ PyMODINIT_FUNC initperf(void) | |||
1100 | Py_INCREF(&pyrf_evsel__type); | 1217 | Py_INCREF(&pyrf_evsel__type); |
1101 | PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type); | 1218 | PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type); |
1102 | 1219 | ||
1220 | Py_INCREF(&pyrf_mmap_event__type); | ||
1221 | PyModule_AddObject(module, "mmap_event", (PyObject *)&pyrf_mmap_event__type); | ||
1222 | |||
1223 | Py_INCREF(&pyrf_lost_event__type); | ||
1224 | PyModule_AddObject(module, "lost_event", (PyObject *)&pyrf_lost_event__type); | ||
1225 | |||
1226 | Py_INCREF(&pyrf_comm_event__type); | ||
1227 | PyModule_AddObject(module, "comm_event", (PyObject *)&pyrf_comm_event__type); | ||
1228 | |||
1229 | Py_INCREF(&pyrf_task_event__type); | ||
1230 | PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type); | ||
1231 | |||
1232 | Py_INCREF(&pyrf_throttle_event__type); | ||
1233 | PyModule_AddObject(module, "throttle_event", (PyObject *)&pyrf_throttle_event__type); | ||
1234 | |||
1235 | Py_INCREF(&pyrf_task_event__type); | ||
1236 | PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type); | ||
1237 | |||
1238 | Py_INCREF(&pyrf_read_event__type); | ||
1239 | PyModule_AddObject(module, "read_event", (PyObject *)&pyrf_read_event__type); | ||
1240 | |||
1241 | Py_INCREF(&pyrf_sample_event__type); | ||
1242 | PyModule_AddObject(module, "sample_event", (PyObject *)&pyrf_sample_event__type); | ||
1243 | |||
1244 | Py_INCREF(&pyrf_context_switch_event__type); | ||
1245 | PyModule_AddObject(module, "switch_event", (PyObject *)&pyrf_context_switch_event__type); | ||
1246 | |||
1103 | Py_INCREF(&pyrf_thread_map__type); | 1247 | Py_INCREF(&pyrf_thread_map__type); |
1104 | PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type); | 1248 | PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type); |
1105 | 1249 | ||
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c index c6d4ee2de752..639d1da2f978 100644 --- a/tools/perf/util/quote.c +++ b/tools/perf/util/quote.c | |||
@@ -1,5 +1,7 @@ | |||
1 | #include "cache.h" | 1 | #include <stdlib.h> |
2 | #include "strbuf.h" | ||
2 | #include "quote.h" | 3 | #include "quote.h" |
4 | #include "util.h" | ||
3 | 5 | ||
4 | /* Help to copy the thing properly quoted for the shell safety. | 6 | /* Help to copy the thing properly quoted for the shell safety. |
5 | * any single quote is replaced with '\'', any exclamation point | 7 | * any single quote is replaced with '\'', any exclamation point |
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h index e1ec19146fb0..055ca45bed99 100644 --- a/tools/perf/util/quote.h +++ b/tools/perf/util/quote.h | |||
@@ -2,7 +2,6 @@ | |||
2 | #define __PERF_QUOTE_H | 2 | #define __PERF_QUOTE_H |
3 | 3 | ||
4 | #include <stddef.h> | 4 | #include <stddef.h> |
5 | #include <stdio.h> | ||
6 | 5 | ||
7 | /* Help to copy the thing properly quoted for the shell safety. | 6 | /* Help to copy the thing properly quoted for the shell safety. |
8 | * any single quote is replaced with '\'', any exclamation point | 7 | * any single quote is replaced with '\'', any exclamation point |
@@ -24,6 +23,8 @@ | |||
24 | * sq_quote() in a real application. | 23 | * sq_quote() in a real application. |
25 | */ | 24 | */ |
26 | 25 | ||
26 | struct strbuf; | ||
27 | |||
27 | int sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); | 28 | int sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); |
28 | 29 | ||
29 | #endif /* __PERF_QUOTE_H */ | 30 | #endif /* __PERF_QUOTE_H */ |
diff --git a/tools/perf/util/rb_resort.h b/tools/perf/util/rb_resort.h index abc76e3d3098..808cc45611fe 100644 --- a/tools/perf/util/rb_resort.h +++ b/tools/perf/util/rb_resort.h | |||
@@ -35,7 +35,7 @@ DEFINE_RB_RESORT_RB(threads, strcmp(a->thread->shortname, | |||
35 | 35 | ||
36 | struct rb_node *nd; | 36 | struct rb_node *nd; |
37 | 37 | ||
38 | resort_rb__for_each(nd, threads) { | 38 | resort_rb__for_each_entry(nd, threads) { |
39 | struct thread *t = threads_entry; | 39 | struct thread *t = threads_entry; |
40 | printf("%s: %d\n", t->shortname, t->tid); | 40 | printf("%s: %d\n", t->shortname, t->tid); |
41 | } | 41 | } |
@@ -123,7 +123,7 @@ static void __name##_sorted__init_entry(struct rb_node *nd, \ | |||
123 | struct __name##_sorted_entry *__name##_entry; \ | 123 | struct __name##_sorted_entry *__name##_entry; \ |
124 | struct __name##_sorted *__name = __name##_sorted__new | 124 | struct __name##_sorted *__name = __name##_sorted__new |
125 | 125 | ||
126 | #define resort_rb__for_each(__nd, __name) \ | 126 | #define resort_rb__for_each_entry(__nd, __name) \ |
127 | for (__nd = rb_first(&__name->entries); \ | 127 | for (__nd = rb_first(&__name->entries); \ |
128 | __name##_entry = rb_entry(__nd, struct __name##_sorted_entry, \ | 128 | __name##_entry = rb_entry(__nd, struct __name##_sorted_entry, \ |
129 | rb_node), __nd; \ | 129 | rb_node), __nd; \ |
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 481792c7484b..98bf584853ea 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c | |||
@@ -148,7 +148,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, | |||
148 | 148 | ||
149 | use_comm_exec = perf_can_comm_exec(); | 149 | use_comm_exec = perf_can_comm_exec(); |
150 | 150 | ||
151 | evlist__for_each(evlist, evsel) { | 151 | evlist__for_each_entry(evlist, evsel) { |
152 | perf_evsel__config(evsel, opts, callchain); | 152 | perf_evsel__config(evsel, opts, callchain); |
153 | if (evsel->tracking && use_comm_exec) | 153 | if (evsel->tracking && use_comm_exec) |
154 | evsel->attr.comm_exec = 1; | 154 | evsel->attr.comm_exec = 1; |
@@ -161,18 +161,18 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, | |||
161 | * match the id. | 161 | * match the id. |
162 | */ | 162 | */ |
163 | use_sample_identifier = perf_can_sample_identifier(); | 163 | use_sample_identifier = perf_can_sample_identifier(); |
164 | evlist__for_each(evlist, evsel) | 164 | evlist__for_each_entry(evlist, evsel) |
165 | perf_evsel__set_sample_id(evsel, use_sample_identifier); | 165 | perf_evsel__set_sample_id(evsel, use_sample_identifier); |
166 | } else if (evlist->nr_entries > 1) { | 166 | } else if (evlist->nr_entries > 1) { |
167 | struct perf_evsel *first = perf_evlist__first(evlist); | 167 | struct perf_evsel *first = perf_evlist__first(evlist); |
168 | 168 | ||
169 | evlist__for_each(evlist, evsel) { | 169 | evlist__for_each_entry(evlist, evsel) { |
170 | if (evsel->attr.sample_type == first->attr.sample_type) | 170 | if (evsel->attr.sample_type == first->attr.sample_type) |
171 | continue; | 171 | continue; |
172 | use_sample_identifier = perf_can_sample_identifier(); | 172 | use_sample_identifier = perf_can_sample_identifier(); |
173 | break; | 173 | break; |
174 | } | 174 | } |
175 | evlist__for_each(evlist, evsel) | 175 | evlist__for_each_entry(evlist, evsel) |
176 | perf_evsel__set_sample_id(evsel, use_sample_identifier); | 176 | perf_evsel__set_sample_id(evsel, use_sample_identifier); |
177 | } | 177 | } |
178 | 178 | ||
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index ff134700bf30..e0203b979474 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -273,7 +273,7 @@ static PyObject *get_field_numeric_entry(struct event_format *event, | |||
273 | struct format_field *field, void *data) | 273 | struct format_field *field, void *data) |
274 | { | 274 | { |
275 | bool is_array = field->flags & FIELD_IS_ARRAY; | 275 | bool is_array = field->flags & FIELD_IS_ARRAY; |
276 | PyObject *obj, *list = NULL; | 276 | PyObject *obj = NULL, *list = NULL; |
277 | unsigned long long val; | 277 | unsigned long long val; |
278 | unsigned int item_size, n_items, i; | 278 | unsigned int item_size, n_items, i; |
279 | 279 | ||
@@ -386,13 +386,12 @@ exit: | |||
386 | return pylist; | 386 | return pylist; |
387 | } | 387 | } |
388 | 388 | ||
389 | |||
390 | static void python_process_tracepoint(struct perf_sample *sample, | 389 | static void python_process_tracepoint(struct perf_sample *sample, |
391 | struct perf_evsel *evsel, | 390 | struct perf_evsel *evsel, |
392 | struct addr_location *al) | 391 | struct addr_location *al) |
393 | { | 392 | { |
394 | struct event_format *event = evsel->tp_format; | 393 | struct event_format *event = evsel->tp_format; |
395 | PyObject *handler, *context, *t, *obj, *callchain; | 394 | PyObject *handler, *context, *t, *obj = NULL, *callchain; |
396 | PyObject *dict = NULL; | 395 | PyObject *dict = NULL; |
397 | static char handler_name[256]; | 396 | static char handler_name[256]; |
398 | struct format_field *field; | 397 | struct format_field *field; |
@@ -457,14 +456,26 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
457 | pydict_set_item_string_decref(dict, "common_callchain", callchain); | 456 | pydict_set_item_string_decref(dict, "common_callchain", callchain); |
458 | } | 457 | } |
459 | for (field = event->format.fields; field; field = field->next) { | 458 | for (field = event->format.fields; field; field = field->next) { |
460 | if (field->flags & FIELD_IS_STRING) { | 459 | unsigned int offset, len; |
461 | int offset; | 460 | unsigned long long val; |
461 | |||
462 | if (field->flags & FIELD_IS_ARRAY) { | ||
463 | offset = field->offset; | ||
464 | len = field->size; | ||
462 | if (field->flags & FIELD_IS_DYNAMIC) { | 465 | if (field->flags & FIELD_IS_DYNAMIC) { |
463 | offset = *(int *)(data + field->offset); | 466 | val = pevent_read_number(scripting_context->pevent, |
467 | data + offset, len); | ||
468 | offset = val; | ||
469 | len = offset >> 16; | ||
464 | offset &= 0xffff; | 470 | offset &= 0xffff; |
465 | } else | 471 | } |
466 | offset = field->offset; | 472 | if (field->flags & FIELD_IS_STRING && |
467 | obj = PyString_FromString((char *)data + offset); | 473 | is_printable_array(data + offset, len)) { |
474 | obj = PyString_FromString((char *) data + offset); | ||
475 | } else { | ||
476 | obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); | ||
477 | field->flags &= ~FIELD_IS_STRING; | ||
478 | } | ||
468 | } else { /* FIELD_IS_NUMERIC */ | 479 | } else { /* FIELD_IS_NUMERIC */ |
469 | obj = get_field_numeric_entry(event, field, data); | 480 | obj = get_field_numeric_entry(event, field, data); |
470 | } | 481 | } |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 5214974e841a..5d61242a6e64 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -83,7 +83,7 @@ static bool perf_session__has_comm_exec(struct perf_session *session) | |||
83 | { | 83 | { |
84 | struct perf_evsel *evsel; | 84 | struct perf_evsel *evsel; |
85 | 85 | ||
86 | evlist__for_each(session->evlist, evsel) { | 86 | evlist__for_each_entry(session->evlist, evsel) { |
87 | if (evsel->attr.comm_exec) | 87 | if (evsel->attr.comm_exec) |
88 | return true; | 88 | return true; |
89 | } | 89 | } |
@@ -178,6 +178,8 @@ static void perf_session__delete_threads(struct perf_session *session) | |||
178 | 178 | ||
179 | void perf_session__delete(struct perf_session *session) | 179 | void perf_session__delete(struct perf_session *session) |
180 | { | 180 | { |
181 | if (session == NULL) | ||
182 | return; | ||
181 | auxtrace__free(session); | 183 | auxtrace__free(session); |
182 | auxtrace_index__free(&session->auxtrace_index); | 184 | auxtrace_index__free(&session->auxtrace_index); |
183 | perf_session__destroy_kernel_maps(session); | 185 | perf_session__destroy_kernel_maps(session); |
@@ -593,6 +595,7 @@ do { \ | |||
593 | if (bswap_safe(f, 0)) \ | 595 | if (bswap_safe(f, 0)) \ |
594 | attr->f = bswap_##sz(attr->f); \ | 596 | attr->f = bswap_##sz(attr->f); \ |
595 | } while(0) | 597 | } while(0) |
598 | #define bswap_field_16(f) bswap_field(f, 16) | ||
596 | #define bswap_field_32(f) bswap_field(f, 32) | 599 | #define bswap_field_32(f) bswap_field(f, 32) |
597 | #define bswap_field_64(f) bswap_field(f, 64) | 600 | #define bswap_field_64(f) bswap_field(f, 64) |
598 | 601 | ||
@@ -608,6 +611,7 @@ do { \ | |||
608 | bswap_field_64(sample_regs_user); | 611 | bswap_field_64(sample_regs_user); |
609 | bswap_field_32(sample_stack_user); | 612 | bswap_field_32(sample_stack_user); |
610 | bswap_field_32(aux_watermark); | 613 | bswap_field_32(aux_watermark); |
614 | bswap_field_16(sample_max_stack); | ||
611 | 615 | ||
612 | /* | 616 | /* |
613 | * After read_format are bitfields. Check read_format because | 617 | * After read_format are bitfields. Check read_format because |
@@ -1495,10 +1499,27 @@ int perf_session__register_idle_thread(struct perf_session *session) | |||
1495 | return err; | 1499 | return err; |
1496 | } | 1500 | } |
1497 | 1501 | ||
1502 | static void | ||
1503 | perf_session__warn_order(const struct perf_session *session) | ||
1504 | { | ||
1505 | const struct ordered_events *oe = &session->ordered_events; | ||
1506 | struct perf_evsel *evsel; | ||
1507 | bool should_warn = true; | ||
1508 | |||
1509 | evlist__for_each_entry(session->evlist, evsel) { | ||
1510 | if (evsel->attr.write_backward) | ||
1511 | should_warn = false; | ||
1512 | } | ||
1513 | |||
1514 | if (!should_warn) | ||
1515 | return; | ||
1516 | if (oe->nr_unordered_events != 0) | ||
1517 | ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events); | ||
1518 | } | ||
1519 | |||
1498 | static void perf_session__warn_about_errors(const struct perf_session *session) | 1520 | static void perf_session__warn_about_errors(const struct perf_session *session) |
1499 | { | 1521 | { |
1500 | const struct events_stats *stats = &session->evlist->stats; | 1522 | const struct events_stats *stats = &session->evlist->stats; |
1501 | const struct ordered_events *oe = &session->ordered_events; | ||
1502 | 1523 | ||
1503 | if (session->tool->lost == perf_event__process_lost && | 1524 | if (session->tool->lost == perf_event__process_lost && |
1504 | stats->nr_events[PERF_RECORD_LOST] != 0) { | 1525 | stats->nr_events[PERF_RECORD_LOST] != 0) { |
@@ -1555,8 +1576,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session) | |||
1555 | stats->nr_unprocessable_samples); | 1576 | stats->nr_unprocessable_samples); |
1556 | } | 1577 | } |
1557 | 1578 | ||
1558 | if (oe->nr_unordered_events != 0) | 1579 | perf_session__warn_order(session); |
1559 | ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events); | ||
1560 | 1580 | ||
1561 | events_stats__auxtrace_error_warn(stats); | 1581 | events_stats__auxtrace_error_warn(stats); |
1562 | 1582 | ||
@@ -1868,7 +1888,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg) | |||
1868 | { | 1888 | { |
1869 | struct perf_evsel *evsel; | 1889 | struct perf_evsel *evsel; |
1870 | 1890 | ||
1871 | evlist__for_each(session->evlist, evsel) { | 1891 | evlist__for_each_entry(session->evlist, evsel) { |
1872 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT) | 1892 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT) |
1873 | return true; | 1893 | return true; |
1874 | } | 1894 | } |
@@ -1950,7 +1970,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, | |||
1950 | { | 1970 | { |
1951 | struct perf_evsel *pos; | 1971 | struct perf_evsel *pos; |
1952 | 1972 | ||
1953 | evlist__for_each(session->evlist, pos) { | 1973 | evlist__for_each_entry(session->evlist, pos) { |
1954 | if (pos->attr.type == type) | 1974 | if (pos->attr.type == type) |
1955 | return pos; | 1975 | return pos; |
1956 | } | 1976 | } |
@@ -2105,7 +2125,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool, | |||
2105 | max_nr = (UINT16_MAX - sizeof(struct id_index_event)) / | 2125 | max_nr = (UINT16_MAX - sizeof(struct id_index_event)) / |
2106 | sizeof(struct id_index_entry); | 2126 | sizeof(struct id_index_entry); |
2107 | 2127 | ||
2108 | evlist__for_each(evlist, evsel) | 2128 | evlist__for_each_entry(evlist, evsel) |
2109 | nr += evsel->ids; | 2129 | nr += evsel->ids; |
2110 | 2130 | ||
2111 | n = nr > max_nr ? max_nr : nr; | 2131 | n = nr > max_nr ? max_nr : nr; |
@@ -2118,7 +2138,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool, | |||
2118 | ev->id_index.header.size = sz; | 2138 | ev->id_index.header.size = sz; |
2119 | ev->id_index.nr = n; | 2139 | ev->id_index.nr = n; |
2120 | 2140 | ||
2121 | evlist__for_each(evlist, evsel) { | 2141 | evlist__for_each_entry(evlist, evsel) { |
2122 | u32 j; | 2142 | u32 j; |
2123 | 2143 | ||
2124 | for (j = 0; j < evsel->ids; j++) { | 2144 | for (j = 0; j < evsel->ids; j++) { |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index c4e9bd70723c..947d21f38398 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -79,8 +79,8 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf, | |||
79 | { | 79 | { |
80 | const char *comm = thread__comm_str(he->thread); | 80 | const char *comm = thread__comm_str(he->thread); |
81 | 81 | ||
82 | width = max(7U, width) - 6; | 82 | width = max(7U, width) - 8; |
83 | return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid, | 83 | return repsep_snprintf(bf, size, "%7d:%-*.*s", he->thread->tid, |
84 | width, width, comm ?: ""); | 84 | width, width, comm ?: ""); |
85 | } | 85 | } |
86 | 86 | ||
@@ -95,7 +95,7 @@ static int hist_entry__thread_filter(struct hist_entry *he, int type, const void | |||
95 | } | 95 | } |
96 | 96 | ||
97 | struct sort_entry sort_thread = { | 97 | struct sort_entry sort_thread = { |
98 | .se_header = " Pid:Command", | 98 | .se_header = " Pid:Command", |
99 | .se_cmp = sort__thread_cmp, | 99 | .se_cmp = sort__thread_cmp, |
100 | .se_snprintf = hist_entry__thread_snprintf, | 100 | .se_snprintf = hist_entry__thread_snprintf, |
101 | .se_filter = hist_entry__thread_filter, | 101 | .se_filter = hist_entry__thread_filter, |
@@ -1218,7 +1218,7 @@ struct sort_entry sort_mem_daddr_dso = { | |||
1218 | .se_header = "Data Object", | 1218 | .se_header = "Data Object", |
1219 | .se_cmp = sort__dso_daddr_cmp, | 1219 | .se_cmp = sort__dso_daddr_cmp, |
1220 | .se_snprintf = hist_entry__dso_daddr_snprintf, | 1220 | .se_snprintf = hist_entry__dso_daddr_snprintf, |
1221 | .se_width_idx = HISTC_MEM_DADDR_SYMBOL, | 1221 | .se_width_idx = HISTC_MEM_DADDR_DSO, |
1222 | }; | 1222 | }; |
1223 | 1223 | ||
1224 | struct sort_entry sort_mem_locked = { | 1224 | struct sort_entry sort_mem_locked = { |
@@ -1488,7 +1488,7 @@ void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists) | |||
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 1490 | static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
1491 | struct perf_evsel *evsel) | 1491 | struct hists *hists) |
1492 | { | 1492 | { |
1493 | struct hpp_sort_entry *hse; | 1493 | struct hpp_sort_entry *hse; |
1494 | size_t len = fmt->user_len; | 1494 | size_t len = fmt->user_len; |
@@ -1496,14 +1496,14 @@ static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | |||
1496 | hse = container_of(fmt, struct hpp_sort_entry, hpp); | 1496 | hse = container_of(fmt, struct hpp_sort_entry, hpp); |
1497 | 1497 | ||
1498 | if (!len) | 1498 | if (!len) |
1499 | len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx); | 1499 | len = hists__col_len(hists, hse->se->se_width_idx); |
1500 | 1500 | ||
1501 | return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name); | 1501 | return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name); |
1502 | } | 1502 | } |
1503 | 1503 | ||
1504 | static int __sort__hpp_width(struct perf_hpp_fmt *fmt, | 1504 | static int __sort__hpp_width(struct perf_hpp_fmt *fmt, |
1505 | struct perf_hpp *hpp __maybe_unused, | 1505 | struct perf_hpp *hpp __maybe_unused, |
1506 | struct perf_evsel *evsel) | 1506 | struct hists *hists) |
1507 | { | 1507 | { |
1508 | struct hpp_sort_entry *hse; | 1508 | struct hpp_sort_entry *hse; |
1509 | size_t len = fmt->user_len; | 1509 | size_t len = fmt->user_len; |
@@ -1511,7 +1511,7 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt, | |||
1511 | hse = container_of(fmt, struct hpp_sort_entry, hpp); | 1511 | hse = container_of(fmt, struct hpp_sort_entry, hpp); |
1512 | 1512 | ||
1513 | if (!len) | 1513 | if (!len) |
1514 | len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx); | 1514 | len = hists__col_len(hists, hse->se->se_width_idx); |
1515 | 1515 | ||
1516 | return len; | 1516 | return len; |
1517 | } | 1517 | } |
@@ -1793,7 +1793,7 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde, | |||
1793 | } | 1793 | } |
1794 | 1794 | ||
1795 | static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 1795 | static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
1796 | struct perf_evsel *evsel __maybe_unused) | 1796 | struct hists *hists __maybe_unused) |
1797 | { | 1797 | { |
1798 | struct hpp_dynamic_entry *hde; | 1798 | struct hpp_dynamic_entry *hde; |
1799 | size_t len = fmt->user_len; | 1799 | size_t len = fmt->user_len; |
@@ -1808,7 +1808,7 @@ static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | |||
1808 | 1808 | ||
1809 | static int __sort__hde_width(struct perf_hpp_fmt *fmt, | 1809 | static int __sort__hde_width(struct perf_hpp_fmt *fmt, |
1810 | struct perf_hpp *hpp __maybe_unused, | 1810 | struct perf_hpp *hpp __maybe_unused, |
1811 | struct perf_evsel *evsel __maybe_unused) | 1811 | struct hists *hists __maybe_unused) |
1812 | { | 1812 | { |
1813 | struct hpp_dynamic_entry *hde; | 1813 | struct hpp_dynamic_entry *hde; |
1814 | size_t len = fmt->user_len; | 1814 | size_t len = fmt->user_len; |
@@ -2069,7 +2069,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam | |||
2069 | } | 2069 | } |
2070 | 2070 | ||
2071 | full_name = !!strchr(event_name, ':'); | 2071 | full_name = !!strchr(event_name, ':'); |
2072 | evlist__for_each(evlist, pos) { | 2072 | evlist__for_each_entry(evlist, pos) { |
2073 | /* case 2 */ | 2073 | /* case 2 */ |
2074 | if (full_name && !strcmp(pos->name, event_name)) | 2074 | if (full_name && !strcmp(pos->name, event_name)) |
2075 | return pos; | 2075 | return pos; |
@@ -2125,7 +2125,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace, | |||
2125 | int ret; | 2125 | int ret; |
2126 | struct perf_evsel *evsel; | 2126 | struct perf_evsel *evsel; |
2127 | 2127 | ||
2128 | evlist__for_each(evlist, evsel) { | 2128 | evlist__for_each_entry(evlist, evsel) { |
2129 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) | 2129 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) |
2130 | continue; | 2130 | continue; |
2131 | 2131 | ||
@@ -2143,7 +2143,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist, | |||
2143 | struct perf_evsel *evsel; | 2143 | struct perf_evsel *evsel; |
2144 | struct format_field *field; | 2144 | struct format_field *field; |
2145 | 2145 | ||
2146 | evlist__for_each(evlist, evsel) { | 2146 | evlist__for_each_entry(evlist, evsel) { |
2147 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) | 2147 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) |
2148 | continue; | 2148 | continue; |
2149 | 2149 | ||
@@ -2381,6 +2381,9 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, | |||
2381 | if (sort__mode != SORT_MODE__MEMORY) | 2381 | if (sort__mode != SORT_MODE__MEMORY) |
2382 | return -EINVAL; | 2382 | return -EINVAL; |
2383 | 2383 | ||
2384 | if (sd->entry == &sort_mem_dcacheline && cacheline_size == 0) | ||
2385 | return -EINVAL; | ||
2386 | |||
2384 | if (sd->entry == &sort_mem_daddr_sym) | 2387 | if (sd->entry == &sort_mem_daddr_sym) |
2385 | list->sym = 1; | 2388 | list->sym = 1; |
2386 | 2389 | ||
@@ -2424,7 +2427,10 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str, | |||
2424 | if (*tok) { | 2427 | if (*tok) { |
2425 | ret = sort_dimension__add(list, tok, evlist, level); | 2428 | ret = sort_dimension__add(list, tok, evlist, level); |
2426 | if (ret == -EINVAL) { | 2429 | if (ret == -EINVAL) { |
2427 | error("Invalid --sort key: `%s'", tok); | 2430 | if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok))) |
2431 | error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system"); | ||
2432 | else | ||
2433 | error("Invalid --sort key: `%s'", tok); | ||
2428 | break; | 2434 | break; |
2429 | } else if (ret == -ESRCH) { | 2435 | } else if (ret == -ESRCH) { |
2430 | error("Unknown --sort key: `%s'", tok); | 2436 | error("Unknown --sort key: `%s'", tok); |
@@ -2456,7 +2462,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist) | |||
2456 | if (evlist == NULL) | 2462 | if (evlist == NULL) |
2457 | goto out_no_evlist; | 2463 | goto out_no_evlist; |
2458 | 2464 | ||
2459 | evlist__for_each(evlist, evsel) { | 2465 | evlist__for_each_entry(evlist, evsel) { |
2460 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { | 2466 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { |
2461 | use_trace = false; | 2467 | use_trace = false; |
2462 | break; | 2468 | break; |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index ebb59cacd092..7ca37ea17395 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -67,6 +67,11 @@ struct hist_entry_diff { | |||
67 | }; | 67 | }; |
68 | }; | 68 | }; |
69 | 69 | ||
70 | struct hist_entry_ops { | ||
71 | void *(*new)(size_t size); | ||
72 | void (*free)(void *ptr); | ||
73 | }; | ||
74 | |||
70 | /** | 75 | /** |
71 | * struct hist_entry - histogram entry | 76 | * struct hist_entry - histogram entry |
72 | * | 77 | * |
@@ -125,6 +130,7 @@ struct hist_entry { | |||
125 | void *trace_output; | 130 | void *trace_output; |
126 | struct perf_hpp_list *hpp_list; | 131 | struct perf_hpp_list *hpp_list; |
127 | struct hist_entry *parent_he; | 132 | struct hist_entry *parent_he; |
133 | struct hist_entry_ops *ops; | ||
128 | union { | 134 | union { |
129 | /* this is for hierarchical entry structure */ | 135 | /* this is for hierarchical entry structure */ |
130 | struct { | 136 | struct { |
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index aa9efe08762b..8a2bbd2a4d82 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c | |||
@@ -36,6 +36,11 @@ static struct stats runtime_dtlb_cache_stats[NUM_CTX][MAX_NR_CPUS]; | |||
36 | static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS]; | 36 | static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS]; |
37 | static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS]; | 37 | static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS]; |
38 | static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS]; | 38 | static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS]; |
39 | static struct stats runtime_topdown_total_slots[NUM_CTX][MAX_NR_CPUS]; | ||
40 | static struct stats runtime_topdown_slots_issued[NUM_CTX][MAX_NR_CPUS]; | ||
41 | static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS]; | ||
42 | static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS]; | ||
43 | static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS]; | ||
39 | static bool have_frontend_stalled; | 44 | static bool have_frontend_stalled; |
40 | 45 | ||
41 | struct stats walltime_nsecs_stats; | 46 | struct stats walltime_nsecs_stats; |
@@ -82,6 +87,11 @@ void perf_stat__reset_shadow_stats(void) | |||
82 | sizeof(runtime_transaction_stats)); | 87 | sizeof(runtime_transaction_stats)); |
83 | memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats)); | 88 | memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats)); |
84 | memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); | 89 | memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); |
90 | memset(runtime_topdown_total_slots, 0, sizeof(runtime_topdown_total_slots)); | ||
91 | memset(runtime_topdown_slots_retired, 0, sizeof(runtime_topdown_slots_retired)); | ||
92 | memset(runtime_topdown_slots_issued, 0, sizeof(runtime_topdown_slots_issued)); | ||
93 | memset(runtime_topdown_fetch_bubbles, 0, sizeof(runtime_topdown_fetch_bubbles)); | ||
94 | memset(runtime_topdown_recovery_bubbles, 0, sizeof(runtime_topdown_recovery_bubbles)); | ||
85 | } | 95 | } |
86 | 96 | ||
87 | /* | 97 | /* |
@@ -105,6 +115,16 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, | |||
105 | update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); | 115 | update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); |
106 | else if (perf_stat_evsel__is(counter, ELISION_START)) | 116 | else if (perf_stat_evsel__is(counter, ELISION_START)) |
107 | update_stats(&runtime_elision_stats[ctx][cpu], count[0]); | 117 | update_stats(&runtime_elision_stats[ctx][cpu], count[0]); |
118 | else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS)) | ||
119 | update_stats(&runtime_topdown_total_slots[ctx][cpu], count[0]); | ||
120 | else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED)) | ||
121 | update_stats(&runtime_topdown_slots_issued[ctx][cpu], count[0]); | ||
122 | else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED)) | ||
123 | update_stats(&runtime_topdown_slots_retired[ctx][cpu], count[0]); | ||
124 | else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES)) | ||
125 | update_stats(&runtime_topdown_fetch_bubbles[ctx][cpu],count[0]); | ||
126 | else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES)) | ||
127 | update_stats(&runtime_topdown_recovery_bubbles[ctx][cpu], count[0]); | ||
108 | else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) | 128 | else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) |
109 | update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]); | 129 | update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]); |
110 | else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) | 130 | else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) |
@@ -302,6 +322,107 @@ static void print_ll_cache_misses(int cpu, | |||
302 | out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); | 322 | out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); |
303 | } | 323 | } |
304 | 324 | ||
325 | /* | ||
326 | * High level "TopDown" CPU core pipe line bottleneck break down. | ||
327 | * | ||
328 | * Basic concept following | ||
329 | * Yasin, A Top Down Method for Performance analysis and Counter architecture | ||
330 | * ISPASS14 | ||
331 | * | ||
332 | * The CPU pipeline is divided into 4 areas that can be bottlenecks: | ||
333 | * | ||
334 | * Frontend -> Backend -> Retiring | ||
335 | * BadSpeculation in addition means out of order execution that is thrown away | ||
336 | * (for example branch mispredictions) | ||
337 | * Frontend is instruction decoding. | ||
338 | * Backend is execution, like computation and accessing data in memory | ||
339 | * Retiring is good execution that is not directly bottlenecked | ||
340 | * | ||
341 | * The formulas are computed in slots. | ||
342 | * A slot is an entry in the pipeline each for the pipeline width | ||
343 | * (for example a 4-wide pipeline has 4 slots for each cycle) | ||
344 | * | ||
345 | * Formulas: | ||
346 | * BadSpeculation = ((SlotsIssued - SlotsRetired) + RecoveryBubbles) / | ||
347 | * TotalSlots | ||
348 | * Retiring = SlotsRetired / TotalSlots | ||
349 | * FrontendBound = FetchBubbles / TotalSlots | ||
350 | * BackendBound = 1.0 - BadSpeculation - Retiring - FrontendBound | ||
351 | * | ||
352 | * The kernel provides the mapping to the low level CPU events and any scaling | ||
353 | * needed for the CPU pipeline width, for example: | ||
354 | * | ||
355 | * TotalSlots = Cycles * 4 | ||
356 | * | ||
357 | * The scaling factor is communicated in the sysfs unit. | ||
358 | * | ||
359 | * In some cases the CPU may not be able to measure all the formulas due to | ||
360 | * missing events. In this case multiple formulas are combined, as possible. | ||
361 | * | ||
362 | * Full TopDown supports more levels to sub-divide each area: for example | ||
363 | * BackendBound into computing bound and memory bound. For now we only | ||
364 | * support Level 1 TopDown. | ||
365 | */ | ||
366 | |||
367 | static double sanitize_val(double x) | ||
368 | { | ||
369 | if (x < 0 && x >= -0.02) | ||
370 | return 0.0; | ||
371 | return x; | ||
372 | } | ||
373 | |||
374 | static double td_total_slots(int ctx, int cpu) | ||
375 | { | ||
376 | return avg_stats(&runtime_topdown_total_slots[ctx][cpu]); | ||
377 | } | ||
378 | |||
379 | static double td_bad_spec(int ctx, int cpu) | ||
380 | { | ||
381 | double bad_spec = 0; | ||
382 | double total_slots; | ||
383 | double total; | ||
384 | |||
385 | total = avg_stats(&runtime_topdown_slots_issued[ctx][cpu]) - | ||
386 | avg_stats(&runtime_topdown_slots_retired[ctx][cpu]) + | ||
387 | avg_stats(&runtime_topdown_recovery_bubbles[ctx][cpu]); | ||
388 | total_slots = td_total_slots(ctx, cpu); | ||
389 | if (total_slots) | ||
390 | bad_spec = total / total_slots; | ||
391 | return sanitize_val(bad_spec); | ||
392 | } | ||
393 | |||
394 | static double td_retiring(int ctx, int cpu) | ||
395 | { | ||
396 | double retiring = 0; | ||
397 | double total_slots = td_total_slots(ctx, cpu); | ||
398 | double ret_slots = avg_stats(&runtime_topdown_slots_retired[ctx][cpu]); | ||
399 | |||
400 | if (total_slots) | ||
401 | retiring = ret_slots / total_slots; | ||
402 | return retiring; | ||
403 | } | ||
404 | |||
405 | static double td_fe_bound(int ctx, int cpu) | ||
406 | { | ||
407 | double fe_bound = 0; | ||
408 | double total_slots = td_total_slots(ctx, cpu); | ||
409 | double fetch_bub = avg_stats(&runtime_topdown_fetch_bubbles[ctx][cpu]); | ||
410 | |||
411 | if (total_slots) | ||
412 | fe_bound = fetch_bub / total_slots; | ||
413 | return fe_bound; | ||
414 | } | ||
415 | |||
416 | static double td_be_bound(int ctx, int cpu) | ||
417 | { | ||
418 | double sum = (td_fe_bound(ctx, cpu) + | ||
419 | td_bad_spec(ctx, cpu) + | ||
420 | td_retiring(ctx, cpu)); | ||
421 | if (sum == 0) | ||
422 | return 0; | ||
423 | return sanitize_val(1.0 - sum); | ||
424 | } | ||
425 | |||
305 | void perf_stat__print_shadow_stats(struct perf_evsel *evsel, | 426 | void perf_stat__print_shadow_stats(struct perf_evsel *evsel, |
306 | double avg, int cpu, | 427 | double avg, int cpu, |
307 | struct perf_stat_output_ctx *out) | 428 | struct perf_stat_output_ctx *out) |
@@ -309,6 +430,7 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, | |||
309 | void *ctxp = out->ctx; | 430 | void *ctxp = out->ctx; |
310 | print_metric_t print_metric = out->print_metric; | 431 | print_metric_t print_metric = out->print_metric; |
311 | double total, ratio = 0.0, total2; | 432 | double total, ratio = 0.0, total2; |
433 | const char *color = NULL; | ||
312 | int ctx = evsel_context(evsel); | 434 | int ctx = evsel_context(evsel); |
313 | 435 | ||
314 | if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { | 436 | if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { |
@@ -452,6 +574,46 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, | |||
452 | avg / ratio); | 574 | avg / ratio); |
453 | else | 575 | else |
454 | print_metric(ctxp, NULL, NULL, "CPUs utilized", 0); | 576 | print_metric(ctxp, NULL, NULL, "CPUs utilized", 0); |
577 | } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) { | ||
578 | double fe_bound = td_fe_bound(ctx, cpu); | ||
579 | |||
580 | if (fe_bound > 0.2) | ||
581 | color = PERF_COLOR_RED; | ||
582 | print_metric(ctxp, color, "%8.1f%%", "frontend bound", | ||
583 | fe_bound * 100.); | ||
584 | } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) { | ||
585 | double retiring = td_retiring(ctx, cpu); | ||
586 | |||
587 | if (retiring > 0.7) | ||
588 | color = PERF_COLOR_GREEN; | ||
589 | print_metric(ctxp, color, "%8.1f%%", "retiring", | ||
590 | retiring * 100.); | ||
591 | } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) { | ||
592 | double bad_spec = td_bad_spec(ctx, cpu); | ||
593 | |||
594 | if (bad_spec > 0.1) | ||
595 | color = PERF_COLOR_RED; | ||
596 | print_metric(ctxp, color, "%8.1f%%", "bad speculation", | ||
597 | bad_spec * 100.); | ||
598 | } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) { | ||
599 | double be_bound = td_be_bound(ctx, cpu); | ||
600 | const char *name = "backend bound"; | ||
601 | static int have_recovery_bubbles = -1; | ||
602 | |||
603 | /* In case the CPU does not support topdown-recovery-bubbles */ | ||
604 | if (have_recovery_bubbles < 0) | ||
605 | have_recovery_bubbles = pmu_have_event("cpu", | ||
606 | "topdown-recovery-bubbles"); | ||
607 | if (!have_recovery_bubbles) | ||
608 | name = "backend bound/bad spec"; | ||
609 | |||
610 | if (be_bound > 0.2) | ||
611 | color = PERF_COLOR_RED; | ||
612 | if (td_total_slots(ctx, cpu) > 0) | ||
613 | print_metric(ctxp, color, "%8.1f%%", name, | ||
614 | be_bound * 100.); | ||
615 | else | ||
616 | print_metric(ctxp, NULL, NULL, name, 0); | ||
455 | } else if (runtime_nsecs_stats[cpu].n != 0) { | 617 | } else if (runtime_nsecs_stats[cpu].n != 0) { |
456 | char unit = 'M'; | 618 | char unit = 'M'; |
457 | char unit_buf[10]; | 619 | char unit_buf[10]; |
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index ffa1d0653861..39345c2ddfc2 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c | |||
@@ -79,6 +79,11 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = { | |||
79 | ID(TRANSACTION_START, cpu/tx-start/), | 79 | ID(TRANSACTION_START, cpu/tx-start/), |
80 | ID(ELISION_START, cpu/el-start/), | 80 | ID(ELISION_START, cpu/el-start/), |
81 | ID(CYCLES_IN_TX_CP, cpu/cycles-ct/), | 81 | ID(CYCLES_IN_TX_CP, cpu/cycles-ct/), |
82 | ID(TOPDOWN_TOTAL_SLOTS, topdown-total-slots), | ||
83 | ID(TOPDOWN_SLOTS_ISSUED, topdown-slots-issued), | ||
84 | ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired), | ||
85 | ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles), | ||
86 | ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles), | ||
82 | }; | 87 | }; |
83 | #undef ID | 88 | #undef ID |
84 | 89 | ||
@@ -157,7 +162,7 @@ int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw) | |||
157 | { | 162 | { |
158 | struct perf_evsel *evsel; | 163 | struct perf_evsel *evsel; |
159 | 164 | ||
160 | evlist__for_each(evlist, evsel) { | 165 | evlist__for_each_entry(evlist, evsel) { |
161 | if (perf_evsel__alloc_stats(evsel, alloc_raw)) | 166 | if (perf_evsel__alloc_stats(evsel, alloc_raw)) |
162 | goto out_free; | 167 | goto out_free; |
163 | } | 168 | } |
@@ -173,7 +178,7 @@ void perf_evlist__free_stats(struct perf_evlist *evlist) | |||
173 | { | 178 | { |
174 | struct perf_evsel *evsel; | 179 | struct perf_evsel *evsel; |
175 | 180 | ||
176 | evlist__for_each(evlist, evsel) { | 181 | evlist__for_each_entry(evlist, evsel) { |
177 | perf_evsel__free_stat_priv(evsel); | 182 | perf_evsel__free_stat_priv(evsel); |
178 | perf_evsel__free_counts(evsel); | 183 | perf_evsel__free_counts(evsel); |
179 | perf_evsel__free_prev_raw_counts(evsel); | 184 | perf_evsel__free_prev_raw_counts(evsel); |
@@ -184,7 +189,7 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist) | |||
184 | { | 189 | { |
185 | struct perf_evsel *evsel; | 190 | struct perf_evsel *evsel; |
186 | 191 | ||
187 | evlist__for_each(evlist, evsel) { | 192 | evlist__for_each_entry(evlist, evsel) { |
188 | perf_evsel__reset_stat_priv(evsel); | 193 | perf_evsel__reset_stat_priv(evsel); |
189 | perf_evsel__reset_counts(evsel); | 194 | perf_evsel__reset_counts(evsel); |
190 | } | 195 | } |
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 0150e786ccc7..c29bb94c48a4 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h | |||
@@ -17,6 +17,11 @@ enum perf_stat_evsel_id { | |||
17 | PERF_STAT_EVSEL_ID__TRANSACTION_START, | 17 | PERF_STAT_EVSEL_ID__TRANSACTION_START, |
18 | PERF_STAT_EVSEL_ID__ELISION_START, | 18 | PERF_STAT_EVSEL_ID__ELISION_START, |
19 | PERF_STAT_EVSEL_ID__CYCLES_IN_TX_CP, | 19 | PERF_STAT_EVSEL_ID__CYCLES_IN_TX_CP, |
20 | PERF_STAT_EVSEL_ID__TOPDOWN_TOTAL_SLOTS, | ||
21 | PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_ISSUED, | ||
22 | PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_RETIRED, | ||
23 | PERF_STAT_EVSEL_ID__TOPDOWN_FETCH_BUBBLES, | ||
24 | PERF_STAT_EVSEL_ID__TOPDOWN_RECOVERY_BUBBLES, | ||
20 | PERF_STAT_EVSEL_ID__MAX, | 25 | PERF_STAT_EVSEL_ID__MAX, |
21 | }; | 26 | }; |
22 | 27 | ||
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index f95f682aa2b2..817593908d47 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c | |||
@@ -1,5 +1,5 @@ | |||
1 | #include "debug.h" | 1 | #include "debug.h" |
2 | #include "cache.h" | 2 | #include "util.h" |
3 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
4 | 4 | ||
5 | int prefixcmp(const char *str, const char *prefix) | 5 | int prefixcmp(const char *str, const char *prefix) |
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index 54b409297d4a..b268a6648a5d 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h | |||
@@ -40,6 +40,9 @@ | |||
40 | 40 | ||
41 | #include <assert.h> | 41 | #include <assert.h> |
42 | #include <stdarg.h> | 42 | #include <stdarg.h> |
43 | #include <stddef.h> | ||
44 | #include <string.h> | ||
45 | #include <sys/types.h> | ||
43 | 46 | ||
44 | extern char strbuf_slopbuf[]; | 47 | extern char strbuf_slopbuf[]; |
45 | struct strbuf { | 48 | struct strbuf { |
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h index ca990029e243..19207e50fce5 100644 --- a/tools/perf/util/strlist.h +++ b/tools/perf/util/strlist.h | |||
@@ -73,7 +73,7 @@ static inline struct str_node *strlist__next(struct str_node *sn) | |||
73 | * @pos: the &struct str_node to use as a loop cursor. | 73 | * @pos: the &struct str_node to use as a loop cursor. |
74 | * @slist: the &struct strlist for loop. | 74 | * @slist: the &struct strlist for loop. |
75 | */ | 75 | */ |
76 | #define strlist__for_each(pos, slist) \ | 76 | #define strlist__for_each_entry(pos, slist) \ |
77 | for (pos = strlist__first(slist); pos; pos = strlist__next(pos)) | 77 | for (pos = strlist__first(slist); pos; pos = strlist__next(pos)) |
78 | 78 | ||
79 | /** | 79 | /** |
@@ -83,7 +83,7 @@ static inline struct str_node *strlist__next(struct str_node *sn) | |||
83 | * @n: another &struct str_node to use as temporary storage. | 83 | * @n: another &struct str_node to use as temporary storage. |
84 | * @slist: the &struct strlist for loop. | 84 | * @slist: the &struct strlist for loop. |
85 | */ | 85 | */ |
86 | #define strlist__for_each_safe(pos, n, slist) \ | 86 | #define strlist__for_each_entry_safe(pos, n, slist) \ |
87 | for (pos = strlist__first(slist), n = strlist__next(pos); pos;\ | 87 | for (pos = strlist__first(slist), n = strlist__next(pos); pos;\ |
88 | pos = n, n = strlist__next(n)) | 88 | pos = n, n = strlist__next(n)) |
89 | #endif /* __PERF_STRLIST_H */ | 89 | #endif /* __PERF_STRLIST_H */ |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 87a297dd8901..a34321e9b44d 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | #include "symbol.h" | 8 | #include "symbol.h" |
9 | #include "demangle-java.h" | 9 | #include "demangle-java.h" |
10 | #include "demangle-rust.h" | ||
10 | #include "machine.h" | 11 | #include "machine.h" |
11 | #include "vdso.h" | 12 | #include "vdso.h" |
12 | #include <symbol/kallsyms.h> | 13 | #include <symbol/kallsyms.h> |
@@ -16,6 +17,7 @@ | |||
16 | #define EM_AARCH64 183 /* ARM 64 bit */ | 17 | #define EM_AARCH64 183 /* ARM 64 bit */ |
17 | #endif | 18 | #endif |
18 | 19 | ||
20 | typedef Elf64_Nhdr GElf_Nhdr; | ||
19 | 21 | ||
20 | #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT | 22 | #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT |
21 | extern char *cplus_demangle(const char *, int); | 23 | extern char *cplus_demangle(const char *, int); |
@@ -54,6 +56,14 @@ static int elf_getphdrnum(Elf *elf, size_t *dst) | |||
54 | } | 56 | } |
55 | #endif | 57 | #endif |
56 | 58 | ||
59 | #ifndef HAVE_ELF_GETSHDRSTRNDX_SUPPORT | ||
60 | static int elf_getshdrstrndx(Elf *elf __maybe_unused, size_t *dst __maybe_unused) | ||
61 | { | ||
62 | pr_err("%s: update your libelf to > 0.140, this one lacks elf_getshdrstrndx().\n", __func__); | ||
63 | return -1; | ||
64 | } | ||
65 | #endif | ||
66 | |||
57 | #ifndef NT_GNU_BUILD_ID | 67 | #ifndef NT_GNU_BUILD_ID |
58 | #define NT_GNU_BUILD_ID 3 | 68 | #define NT_GNU_BUILD_ID 3 |
59 | #endif | 69 | #endif |
@@ -1072,6 +1082,13 @@ new_symbol: | |||
1072 | demangled = bfd_demangle(NULL, elf_name, demangle_flags); | 1082 | demangled = bfd_demangle(NULL, elf_name, demangle_flags); |
1073 | if (demangled == NULL) | 1083 | if (demangled == NULL) |
1074 | demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET); | 1084 | demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET); |
1085 | else if (rust_is_mangled(demangled)) | ||
1086 | /* | ||
1087 | * Input to Rust demangling is the BFD-demangled | ||
1088 | * name which it Rust-demangles in place. | ||
1089 | */ | ||
1090 | rust_demangle_sym(demangled); | ||
1091 | |||
1075 | if (demangled != NULL) | 1092 | if (demangled != NULL) |
1076 | elf_name = demangled; | 1093 | elf_name = demangled; |
1077 | } | 1094 | } |
@@ -1781,6 +1798,260 @@ void kcore_extract__delete(struct kcore_extract *kce) | |||
1781 | unlink(kce->extract_filename); | 1798 | unlink(kce->extract_filename); |
1782 | } | 1799 | } |
1783 | 1800 | ||
1801 | #ifdef HAVE_GELF_GETNOTE_SUPPORT | ||
1802 | /** | ||
1803 | * populate_sdt_note : Parse raw data and identify SDT note | ||
1804 | * @elf: elf of the opened file | ||
1805 | * @data: raw data of a section with description offset applied | ||
1806 | * @len: note description size | ||
1807 | * @type: type of the note | ||
1808 | * @sdt_notes: List to add the SDT note | ||
1809 | * | ||
1810 | * Responsible for parsing the @data in section .note.stapsdt in @elf and | ||
1811 | * if its an SDT note, it appends to @sdt_notes list. | ||
1812 | */ | ||
1813 | static int populate_sdt_note(Elf **elf, const char *data, size_t len, | ||
1814 | struct list_head *sdt_notes) | ||
1815 | { | ||
1816 | const char *provider, *name; | ||
1817 | struct sdt_note *tmp = NULL; | ||
1818 | GElf_Ehdr ehdr; | ||
1819 | GElf_Addr base_off = 0; | ||
1820 | GElf_Shdr shdr; | ||
1821 | int ret = -EINVAL; | ||
1822 | |||
1823 | union { | ||
1824 | Elf64_Addr a64[NR_ADDR]; | ||
1825 | Elf32_Addr a32[NR_ADDR]; | ||
1826 | } buf; | ||
1827 | |||
1828 | Elf_Data dst = { | ||
1829 | .d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT, | ||
1830 | .d_size = gelf_fsize((*elf), ELF_T_ADDR, NR_ADDR, EV_CURRENT), | ||
1831 | .d_off = 0, .d_align = 0 | ||
1832 | }; | ||
1833 | Elf_Data src = { | ||
1834 | .d_buf = (void *) data, .d_type = ELF_T_ADDR, | ||
1835 | .d_version = EV_CURRENT, .d_size = dst.d_size, .d_off = 0, | ||
1836 | .d_align = 0 | ||
1837 | }; | ||
1838 | |||
1839 | tmp = (struct sdt_note *)calloc(1, sizeof(struct sdt_note)); | ||
1840 | if (!tmp) { | ||
1841 | ret = -ENOMEM; | ||
1842 | goto out_err; | ||
1843 | } | ||
1844 | |||
1845 | INIT_LIST_HEAD(&tmp->note_list); | ||
1846 | |||
1847 | if (len < dst.d_size + 3) | ||
1848 | goto out_free_note; | ||
1849 | |||
1850 | /* Translation from file representation to memory representation */ | ||
1851 | if (gelf_xlatetom(*elf, &dst, &src, | ||
1852 | elf_getident(*elf, NULL)[EI_DATA]) == NULL) { | ||
1853 | pr_err("gelf_xlatetom : %s\n", elf_errmsg(-1)); | ||
1854 | goto out_free_note; | ||
1855 | } | ||
1856 | |||
1857 | /* Populate the fields of sdt_note */ | ||
1858 | provider = data + dst.d_size; | ||
1859 | |||
1860 | name = (const char *)memchr(provider, '\0', data + len - provider); | ||
1861 | if (name++ == NULL) | ||
1862 | goto out_free_note; | ||
1863 | |||
1864 | tmp->provider = strdup(provider); | ||
1865 | if (!tmp->provider) { | ||
1866 | ret = -ENOMEM; | ||
1867 | goto out_free_note; | ||
1868 | } | ||
1869 | tmp->name = strdup(name); | ||
1870 | if (!tmp->name) { | ||
1871 | ret = -ENOMEM; | ||
1872 | goto out_free_prov; | ||
1873 | } | ||
1874 | |||
1875 | if (gelf_getclass(*elf) == ELFCLASS32) { | ||
1876 | memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr)); | ||
1877 | tmp->bit32 = true; | ||
1878 | } else { | ||
1879 | memcpy(&tmp->addr, &buf, 3 * sizeof(Elf64_Addr)); | ||
1880 | tmp->bit32 = false; | ||
1881 | } | ||
1882 | |||
1883 | if (!gelf_getehdr(*elf, &ehdr)) { | ||
1884 | pr_debug("%s : cannot get elf header.\n", __func__); | ||
1885 | ret = -EBADF; | ||
1886 | goto out_free_name; | ||
1887 | } | ||
1888 | |||
1889 | /* Adjust the prelink effect : | ||
1890 | * Find out the .stapsdt.base section. | ||
1891 | * This scn will help us to handle prelinking (if present). | ||
1892 | * Compare the retrieved file offset of the base section with the | ||
1893 | * base address in the description of the SDT note. If its different, | ||
1894 | * then accordingly, adjust the note location. | ||
1895 | */ | ||
1896 | if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL)) { | ||
1897 | base_off = shdr.sh_offset; | ||
1898 | if (base_off) { | ||
1899 | if (tmp->bit32) | ||
1900 | tmp->addr.a32[0] = tmp->addr.a32[0] + base_off - | ||
1901 | tmp->addr.a32[1]; | ||
1902 | else | ||
1903 | tmp->addr.a64[0] = tmp->addr.a64[0] + base_off - | ||
1904 | tmp->addr.a64[1]; | ||
1905 | } | ||
1906 | } | ||
1907 | |||
1908 | list_add_tail(&tmp->note_list, sdt_notes); | ||
1909 | return 0; | ||
1910 | |||
1911 | out_free_name: | ||
1912 | free(tmp->name); | ||
1913 | out_free_prov: | ||
1914 | free(tmp->provider); | ||
1915 | out_free_note: | ||
1916 | free(tmp); | ||
1917 | out_err: | ||
1918 | return ret; | ||
1919 | } | ||
1920 | |||
1921 | /** | ||
1922 | * construct_sdt_notes_list : constructs a list of SDT notes | ||
1923 | * @elf : elf to look into | ||
1924 | * @sdt_notes : empty list_head | ||
1925 | * | ||
1926 | * Scans the sections in 'elf' for the section | ||
1927 | * .note.stapsdt. It, then calls populate_sdt_note to find | ||
1928 | * out the SDT events and populates the 'sdt_notes'. | ||
1929 | */ | ||
1930 | static int construct_sdt_notes_list(Elf *elf, struct list_head *sdt_notes) | ||
1931 | { | ||
1932 | GElf_Ehdr ehdr; | ||
1933 | Elf_Scn *scn = NULL; | ||
1934 | Elf_Data *data; | ||
1935 | GElf_Shdr shdr; | ||
1936 | size_t shstrndx, next; | ||
1937 | GElf_Nhdr nhdr; | ||
1938 | size_t name_off, desc_off, offset; | ||
1939 | int ret = 0; | ||
1940 | |||
1941 | if (gelf_getehdr(elf, &ehdr) == NULL) { | ||
1942 | ret = -EBADF; | ||
1943 | goto out_ret; | ||
1944 | } | ||
1945 | if (elf_getshdrstrndx(elf, &shstrndx) != 0) { | ||
1946 | ret = -EBADF; | ||
1947 | goto out_ret; | ||
1948 | } | ||
1949 | |||
1950 | /* Look for the required section */ | ||
1951 | scn = elf_section_by_name(elf, &ehdr, &shdr, SDT_NOTE_SCN, NULL); | ||
1952 | if (!scn) { | ||
1953 | ret = -ENOENT; | ||
1954 | goto out_ret; | ||
1955 | } | ||
1956 | |||
1957 | if ((shdr.sh_type != SHT_NOTE) || (shdr.sh_flags & SHF_ALLOC)) { | ||
1958 | ret = -ENOENT; | ||
1959 | goto out_ret; | ||
1960 | } | ||
1961 | |||
1962 | data = elf_getdata(scn, NULL); | ||
1963 | |||
1964 | /* Get the SDT notes */ | ||
1965 | for (offset = 0; (next = gelf_getnote(data, offset, &nhdr, &name_off, | ||
1966 | &desc_off)) > 0; offset = next) { | ||
1967 | if (nhdr.n_namesz == sizeof(SDT_NOTE_NAME) && | ||
1968 | !memcmp(data->d_buf + name_off, SDT_NOTE_NAME, | ||
1969 | sizeof(SDT_NOTE_NAME))) { | ||
1970 | /* Check the type of the note */ | ||
1971 | if (nhdr.n_type != SDT_NOTE_TYPE) | ||
1972 | goto out_ret; | ||
1973 | |||
1974 | ret = populate_sdt_note(&elf, ((data->d_buf) + desc_off), | ||
1975 | nhdr.n_descsz, sdt_notes); | ||
1976 | if (ret < 0) | ||
1977 | goto out_ret; | ||
1978 | } | ||
1979 | } | ||
1980 | if (list_empty(sdt_notes)) | ||
1981 | ret = -ENOENT; | ||
1982 | |||
1983 | out_ret: | ||
1984 | return ret; | ||
1985 | } | ||
1986 | |||
1987 | /** | ||
1988 | * get_sdt_note_list : Wrapper to construct a list of sdt notes | ||
1989 | * @head : empty list_head | ||
1990 | * @target : file to find SDT notes from | ||
1991 | * | ||
1992 | * This opens the file, initializes | ||
1993 | * the ELF and then calls construct_sdt_notes_list. | ||
1994 | */ | ||
1995 | int get_sdt_note_list(struct list_head *head, const char *target) | ||
1996 | { | ||
1997 | Elf *elf; | ||
1998 | int fd, ret; | ||
1999 | |||
2000 | fd = open(target, O_RDONLY); | ||
2001 | if (fd < 0) | ||
2002 | return -EBADF; | ||
2003 | |||
2004 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
2005 | if (!elf) { | ||
2006 | ret = -EBADF; | ||
2007 | goto out_close; | ||
2008 | } | ||
2009 | ret = construct_sdt_notes_list(elf, head); | ||
2010 | elf_end(elf); | ||
2011 | out_close: | ||
2012 | close(fd); | ||
2013 | return ret; | ||
2014 | } | ||
2015 | |||
2016 | /** | ||
2017 | * cleanup_sdt_note_list : free the sdt notes' list | ||
2018 | * @sdt_notes: sdt notes' list | ||
2019 | * | ||
2020 | * Free up the SDT notes in @sdt_notes. | ||
2021 | * Returns the number of SDT notes free'd. | ||
2022 | */ | ||
2023 | int cleanup_sdt_note_list(struct list_head *sdt_notes) | ||
2024 | { | ||
2025 | struct sdt_note *tmp, *pos; | ||
2026 | int nr_free = 0; | ||
2027 | |||
2028 | list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) { | ||
2029 | list_del(&pos->note_list); | ||
2030 | free(pos->name); | ||
2031 | free(pos->provider); | ||
2032 | free(pos); | ||
2033 | nr_free++; | ||
2034 | } | ||
2035 | return nr_free; | ||
2036 | } | ||
2037 | |||
2038 | /** | ||
2039 | * sdt_notes__get_count: Counts the number of sdt events | ||
2040 | * @start: list_head to sdt_notes list | ||
2041 | * | ||
2042 | * Returns the number of SDT notes in a list | ||
2043 | */ | ||
2044 | int sdt_notes__get_count(struct list_head *start) | ||
2045 | { | ||
2046 | struct sdt_note *sdt_ptr; | ||
2047 | int count = 0; | ||
2048 | |||
2049 | list_for_each_entry(sdt_ptr, start, note_list) | ||
2050 | count++; | ||
2051 | return count; | ||
2052 | } | ||
2053 | #endif | ||
2054 | |||
1784 | void symbol__elf_init(void) | 2055 | void symbol__elf_init(void) |
1785 | { | 2056 | { |
1786 | elf_version(EV_CURRENT); | 2057 | elf_version(EV_CURRENT); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 54c4ff2b1cee..37e8d20ae03e 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1430,7 +1430,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1430 | * Read the build id if possible. This is required for | 1430 | * Read the build id if possible. This is required for |
1431 | * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work | 1431 | * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work |
1432 | */ | 1432 | */ |
1433 | if (is_regular_file(name) && | 1433 | if (is_regular_file(dso->long_name) && |
1434 | filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) | 1434 | filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) |
1435 | dso__set_build_id(dso, build_id); | 1435 | dso__set_build_id(dso, build_id); |
1436 | 1436 | ||
@@ -1626,7 +1626,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz) | |||
1626 | if (!dirs) | 1626 | if (!dirs) |
1627 | return -1; | 1627 | return -1; |
1628 | 1628 | ||
1629 | strlist__for_each(nd, dirs) { | 1629 | strlist__for_each_entry(nd, dirs) { |
1630 | scnprintf(kallsyms_filename, sizeof(kallsyms_filename), | 1630 | scnprintf(kallsyms_filename, sizeof(kallsyms_filename), |
1631 | "%s/%s/kallsyms", dir, nd->s); | 1631 | "%s/%s/kallsyms", dir, nd->s); |
1632 | if (!validate_kcore_addresses(kallsyms_filename, map)) { | 1632 | if (!validate_kcore_addresses(kallsyms_filename, map)) { |
@@ -1641,6 +1641,20 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz) | |||
1641 | return ret; | 1641 | return ret; |
1642 | } | 1642 | } |
1643 | 1643 | ||
1644 | /* | ||
1645 | * Use open(O_RDONLY) to check readability directly instead of access(R_OK) | ||
1646 | * since access(R_OK) only checks with real UID/GID but open() use effective | ||
1647 | * UID/GID and actual capabilities (e.g. /proc/kcore requires CAP_SYS_RAWIO). | ||
1648 | */ | ||
1649 | static bool filename__readable(const char *file) | ||
1650 | { | ||
1651 | int fd = open(file, O_RDONLY); | ||
1652 | if (fd < 0) | ||
1653 | return false; | ||
1654 | close(fd); | ||
1655 | return true; | ||
1656 | } | ||
1657 | |||
1644 | static char *dso__find_kallsyms(struct dso *dso, struct map *map) | 1658 | static char *dso__find_kallsyms(struct dso *dso, struct map *map) |
1645 | { | 1659 | { |
1646 | u8 host_build_id[BUILD_ID_SIZE]; | 1660 | u8 host_build_id[BUILD_ID_SIZE]; |
@@ -1660,58 +1674,43 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) | |||
1660 | sizeof(host_build_id)) == 0) | 1674 | sizeof(host_build_id)) == 0) |
1661 | is_host = dso__build_id_equal(dso, host_build_id); | 1675 | is_host = dso__build_id_equal(dso, host_build_id); |
1662 | 1676 | ||
1663 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | 1677 | /* Try a fast path for /proc/kallsyms if possible */ |
1664 | |||
1665 | scnprintf(path, sizeof(path), "%s/%s/%s", buildid_dir, | ||
1666 | DSO__NAME_KCORE, sbuild_id); | ||
1667 | |||
1668 | /* Use /proc/kallsyms if possible */ | ||
1669 | if (is_host) { | 1678 | if (is_host) { |
1670 | DIR *d; | ||
1671 | int fd; | ||
1672 | |||
1673 | /* If no cached kcore go with /proc/kallsyms */ | ||
1674 | d = opendir(path); | ||
1675 | if (!d) | ||
1676 | goto proc_kallsyms; | ||
1677 | closedir(d); | ||
1678 | |||
1679 | /* | 1679 | /* |
1680 | * Do not check the build-id cache, until we know we cannot use | 1680 | * Do not check the build-id cache, unless we know we cannot use |
1681 | * /proc/kcore. | 1681 | * /proc/kcore or module maps don't match to /proc/kallsyms. |
1682 | * To check readability of /proc/kcore, do not use access(R_OK) | ||
1683 | * since /proc/kcore requires CAP_SYS_RAWIO to read and access | ||
1684 | * can't check it. | ||
1682 | */ | 1685 | */ |
1683 | fd = open("/proc/kcore", O_RDONLY); | 1686 | if (filename__readable("/proc/kcore") && |
1684 | if (fd != -1) { | 1687 | !validate_kcore_addresses("/proc/kallsyms", map)) |
1685 | close(fd); | 1688 | goto proc_kallsyms; |
1686 | /* If module maps match go with /proc/kallsyms */ | ||
1687 | if (!validate_kcore_addresses("/proc/kallsyms", map)) | ||
1688 | goto proc_kallsyms; | ||
1689 | } | ||
1690 | |||
1691 | /* Find kallsyms in build-id cache with kcore */ | ||
1692 | if (!find_matching_kcore(map, path, sizeof(path))) | ||
1693 | return strdup(path); | ||
1694 | |||
1695 | goto proc_kallsyms; | ||
1696 | } | 1689 | } |
1697 | 1690 | ||
1691 | build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | ||
1692 | |||
1698 | /* Find kallsyms in build-id cache with kcore */ | 1693 | /* Find kallsyms in build-id cache with kcore */ |
1694 | scnprintf(path, sizeof(path), "%s/%s/%s", | ||
1695 | buildid_dir, DSO__NAME_KCORE, sbuild_id); | ||
1696 | |||
1699 | if (!find_matching_kcore(map, path, sizeof(path))) | 1697 | if (!find_matching_kcore(map, path, sizeof(path))) |
1700 | return strdup(path); | 1698 | return strdup(path); |
1701 | 1699 | ||
1702 | scnprintf(path, sizeof(path), "%s/%s/%s", | 1700 | /* Use current /proc/kallsyms if possible */ |
1703 | buildid_dir, DSO__NAME_KALLSYMS, sbuild_id); | 1701 | if (is_host) { |
1702 | proc_kallsyms: | ||
1703 | return strdup("/proc/kallsyms"); | ||
1704 | } | ||
1704 | 1705 | ||
1705 | if (access(path, F_OK)) { | 1706 | /* Finally, find a cache of kallsyms */ |
1707 | if (!build_id_cache__kallsyms_path(sbuild_id, path, sizeof(path))) { | ||
1706 | pr_err("No kallsyms or vmlinux with build-id %s was found\n", | 1708 | pr_err("No kallsyms or vmlinux with build-id %s was found\n", |
1707 | sbuild_id); | 1709 | sbuild_id); |
1708 | return NULL; | 1710 | return NULL; |
1709 | } | 1711 | } |
1710 | 1712 | ||
1711 | return strdup(path); | 1713 | return strdup(path); |
1712 | |||
1713 | proc_kallsyms: | ||
1714 | return strdup("/proc/kallsyms"); | ||
1715 | } | 1714 | } |
1716 | 1715 | ||
1717 | static int dso__load_kernel_sym(struct dso *dso, struct map *map, | 1716 | static int dso__load_kernel_sym(struct dso *dso, struct map *map, |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index b10d558a8803..699f7cbcfe72 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -342,4 +342,26 @@ void arch__sym_update(struct symbol *s, GElf_Sym *sym); | |||
342 | 342 | ||
343 | int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb); | 343 | int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb); |
344 | 344 | ||
345 | /* structure containing an SDT note's info */ | ||
346 | struct sdt_note { | ||
347 | char *name; /* name of the note*/ | ||
348 | char *provider; /* provider name */ | ||
349 | bool bit32; /* whether the location is 32 bits? */ | ||
350 | union { /* location, base and semaphore addrs */ | ||
351 | Elf64_Addr a64[3]; | ||
352 | Elf32_Addr a32[3]; | ||
353 | } addr; | ||
354 | struct list_head note_list; /* SDT notes' list */ | ||
355 | }; | ||
356 | |||
357 | int get_sdt_note_list(struct list_head *head, const char *target); | ||
358 | int cleanup_sdt_note_list(struct list_head *sdt_notes); | ||
359 | int sdt_notes__get_count(struct list_head *start); | ||
360 | |||
361 | #define SDT_BASE_SCN ".stapsdt.base" | ||
362 | #define SDT_NOTE_SCN ".note.stapsdt" | ||
363 | #define SDT_NOTE_TYPE 3 | ||
364 | #define SDT_NOTE_NAME "stapsdt" | ||
365 | #define NR_ADDR 3 | ||
366 | |||
345 | #endif /* __PERF_SYMBOL */ | 367 | #endif /* __PERF_SYMBOL */ |
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c index a53603b27e52..21c4d9b23c24 100644 --- a/tools/perf/util/target.c +++ b/tools/perf/util/target.c | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "target.h" | 9 | #include "target.h" |
10 | #include "util.h" | ||
10 | #include "debug.h" | 11 | #include "debug.h" |
11 | 12 | ||
12 | #include <pwd.h> | 13 | #include <pwd.h> |
@@ -121,11 +122,7 @@ int target__strerror(struct target *target, int errnum, | |||
121 | BUG_ON(buflen == 0); | 122 | BUG_ON(buflen == 0); |
122 | 123 | ||
123 | if (errnum >= 0) { | 124 | if (errnum >= 0) { |
124 | const char *err = strerror_r(errnum, buf, buflen); | 125 | str_error_r(errnum, buf, buflen); |
125 | |||
126 | if (err != buf) | ||
127 | scnprintf(buf, buflen, "%s", err); | ||
128 | |||
129 | return 0; | 126 | return 0; |
130 | } | 127 | } |
131 | 128 | ||
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c index 825086aa9a08..d3301529f6a7 100644 --- a/tools/perf/util/thread-stack.c +++ b/tools/perf/util/thread-stack.c | |||
@@ -616,3 +616,10 @@ int thread_stack__process(struct thread *thread, struct comm *comm, | |||
616 | 616 | ||
617 | return err; | 617 | return err; |
618 | } | 618 | } |
619 | |||
620 | size_t thread_stack__depth(struct thread *thread) | ||
621 | { | ||
622 | if (!thread->ts) | ||
623 | return 0; | ||
624 | return thread->ts->cnt; | ||
625 | } | ||
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h index ad44c7944b8e..b7e41c4ebfdd 100644 --- a/tools/perf/util/thread-stack.h +++ b/tools/perf/util/thread-stack.h | |||
@@ -87,6 +87,7 @@ void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, | |||
87 | size_t sz, u64 ip); | 87 | size_t sz, u64 ip); |
88 | int thread_stack__flush(struct thread *thread); | 88 | int thread_stack__flush(struct thread *thread); |
89 | void thread_stack__free(struct thread *thread); | 89 | void thread_stack__free(struct thread *thread); |
90 | size_t thread_stack__depth(struct thread *thread); | ||
90 | 91 | ||
91 | struct call_return_processor * | 92 | struct call_return_processor * |
92 | call_return_processor__new(int (*process)(struct call_return *cr, void *data), | 93 | call_return_processor__new(int (*process)(struct call_return *cr, void *data), |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 45fcb715a36b..8b10a55410a2 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -43,9 +43,6 @@ struct thread *thread__new(pid_t pid, pid_t tid) | |||
43 | thread->cpu = -1; | 43 | thread->cpu = -1; |
44 | INIT_LIST_HEAD(&thread->comm_list); | 44 | INIT_LIST_HEAD(&thread->comm_list); |
45 | 45 | ||
46 | if (unwind__prepare_access(thread) < 0) | ||
47 | goto err_thread; | ||
48 | |||
49 | comm_str = malloc(32); | 46 | comm_str = malloc(32); |
50 | if (!comm_str) | 47 | if (!comm_str) |
51 | goto err_thread; | 48 | goto err_thread; |
@@ -201,10 +198,51 @@ size_t thread__fprintf(struct thread *thread, FILE *fp) | |||
201 | map_groups__fprintf(thread->mg, fp); | 198 | map_groups__fprintf(thread->mg, fp); |
202 | } | 199 | } |
203 | 200 | ||
204 | void thread__insert_map(struct thread *thread, struct map *map) | 201 | int thread__insert_map(struct thread *thread, struct map *map) |
205 | { | 202 | { |
203 | int ret; | ||
204 | |||
205 | ret = unwind__prepare_access(thread, map, NULL); | ||
206 | if (ret) | ||
207 | return ret; | ||
208 | |||
206 | map_groups__fixup_overlappings(thread->mg, map, stderr); | 209 | map_groups__fixup_overlappings(thread->mg, map, stderr); |
207 | map_groups__insert(thread->mg, map); | 210 | map_groups__insert(thread->mg, map); |
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int __thread__prepare_access(struct thread *thread) | ||
216 | { | ||
217 | bool initialized = false; | ||
218 | int i, err = 0; | ||
219 | |||
220 | for (i = 0; i < MAP__NR_TYPES; ++i) { | ||
221 | struct maps *maps = &thread->mg->maps[i]; | ||
222 | struct map *map; | ||
223 | |||
224 | pthread_rwlock_rdlock(&maps->lock); | ||
225 | |||
226 | for (map = maps__first(maps); map; map = map__next(map)) { | ||
227 | err = unwind__prepare_access(thread, map, &initialized); | ||
228 | if (err || initialized) | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | pthread_rwlock_unlock(&maps->lock); | ||
233 | } | ||
234 | |||
235 | return err; | ||
236 | } | ||
237 | |||
238 | static int thread__prepare_access(struct thread *thread) | ||
239 | { | ||
240 | int err = 0; | ||
241 | |||
242 | if (symbol_conf.use_callchain) | ||
243 | err = __thread__prepare_access(thread); | ||
244 | |||
245 | return err; | ||
208 | } | 246 | } |
209 | 247 | ||
210 | static int thread__clone_map_groups(struct thread *thread, | 248 | static int thread__clone_map_groups(struct thread *thread, |
@@ -214,7 +252,7 @@ static int thread__clone_map_groups(struct thread *thread, | |||
214 | 252 | ||
215 | /* This is new thread, we share map groups for process. */ | 253 | /* This is new thread, we share map groups for process. */ |
216 | if (thread->pid_ == parent->pid_) | 254 | if (thread->pid_ == parent->pid_) |
217 | return 0; | 255 | return thread__prepare_access(thread); |
218 | 256 | ||
219 | if (thread->mg == parent->mg) { | 257 | if (thread->mg == parent->mg) { |
220 | pr_debug("broken map groups on thread %d/%d parent %d/%d\n", | 258 | pr_debug("broken map groups on thread %d/%d parent %d/%d\n", |
@@ -224,7 +262,7 @@ static int thread__clone_map_groups(struct thread *thread, | |||
224 | 262 | ||
225 | /* But this one is new process, copy maps. */ | 263 | /* But this one is new process, copy maps. */ |
226 | for (i = 0; i < MAP__NR_TYPES; ++i) | 264 | for (i = 0; i < MAP__NR_TYPES; ++i) |
227 | if (map_groups__clone(thread->mg, parent->mg, i) < 0) | 265 | if (map_groups__clone(thread, parent->mg, i) < 0) |
228 | return -ENOMEM; | 266 | return -ENOMEM; |
229 | 267 | ||
230 | return 0; | 268 | return 0; |
@@ -265,3 +303,14 @@ void thread__find_cpumode_addr_location(struct thread *thread, | |||
265 | break; | 303 | break; |
266 | } | 304 | } |
267 | } | 305 | } |
306 | |||
307 | struct thread *thread__main_thread(struct machine *machine, struct thread *thread) | ||
308 | { | ||
309 | if (thread->pid_ == thread->tid) | ||
310 | return thread__get(thread); | ||
311 | |||
312 | if (thread->pid_ == -1) | ||
313 | return NULL; | ||
314 | |||
315 | return machine__find_thread(machine, thread->pid_, thread->pid_); | ||
316 | } | ||
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 45fba13c800b..99263cb6e6b6 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -9,11 +9,9 @@ | |||
9 | #include "symbol.h" | 9 | #include "symbol.h" |
10 | #include <strlist.h> | 10 | #include <strlist.h> |
11 | #include <intlist.h> | 11 | #include <intlist.h> |
12 | #ifdef HAVE_LIBUNWIND_SUPPORT | ||
13 | #include <libunwind.h> | ||
14 | #endif | ||
15 | 12 | ||
16 | struct thread_stack; | 13 | struct thread_stack; |
14 | struct unwind_libunwind_ops; | ||
17 | 15 | ||
18 | struct thread { | 16 | struct thread { |
19 | union { | 17 | union { |
@@ -36,7 +34,8 @@ struct thread { | |||
36 | void *priv; | 34 | void *priv; |
37 | struct thread_stack *ts; | 35 | struct thread_stack *ts; |
38 | #ifdef HAVE_LIBUNWIND_SUPPORT | 36 | #ifdef HAVE_LIBUNWIND_SUPPORT |
39 | unw_addr_space_t addr_space; | 37 | void *addr_space; |
38 | struct unwind_libunwind_ops *unwind_libunwind_ops; | ||
40 | #endif | 39 | #endif |
41 | }; | 40 | }; |
42 | 41 | ||
@@ -77,10 +76,12 @@ int thread__comm_len(struct thread *thread); | |||
77 | struct comm *thread__comm(const struct thread *thread); | 76 | struct comm *thread__comm(const struct thread *thread); |
78 | struct comm *thread__exec_comm(const struct thread *thread); | 77 | struct comm *thread__exec_comm(const struct thread *thread); |
79 | const char *thread__comm_str(const struct thread *thread); | 78 | const char *thread__comm_str(const struct thread *thread); |
80 | void thread__insert_map(struct thread *thread, struct map *map); | 79 | int thread__insert_map(struct thread *thread, struct map *map); |
81 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); | 80 | int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); |
82 | size_t thread__fprintf(struct thread *thread, FILE *fp); | 81 | size_t thread__fprintf(struct thread *thread, FILE *fp); |
83 | 82 | ||
83 | struct thread *thread__main_thread(struct machine *machine, struct thread *thread); | ||
84 | |||
84 | void thread__find_addr_map(struct thread *thread, | 85 | void thread__find_addr_map(struct thread *thread, |
85 | u8 cpumode, enum map_type type, u64 addr, | 86 | u8 cpumode, enum map_type type, u64 addr, |
86 | struct addr_location *al); | 87 | struct addr_location *al); |
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 5654fe15e036..40585f5b7027 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c | |||
@@ -202,7 +202,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) | |||
202 | if (!slist) | 202 | if (!slist) |
203 | return NULL; | 203 | return NULL; |
204 | 204 | ||
205 | strlist__for_each(pos, slist) { | 205 | strlist__for_each_entry(pos, slist) { |
206 | pid = strtol(pos->s, &end_ptr, 10); | 206 | pid = strtol(pos->s, &end_ptr, 10); |
207 | 207 | ||
208 | if (pid == INT_MIN || pid == INT_MAX || | 208 | if (pid == INT_MIN || pid == INT_MAX || |
@@ -278,7 +278,7 @@ struct thread_map *thread_map__new_by_tid_str(const char *tid_str) | |||
278 | if (!slist) | 278 | if (!slist) |
279 | return NULL; | 279 | return NULL; |
280 | 280 | ||
281 | strlist__for_each(pos, slist) { | 281 | strlist__for_each_entry(pos, slist) { |
282 | tid = strtol(pos->s, &end_ptr, 10); | 282 | tid = strtol(pos->s, &end_ptr, 10); |
283 | 283 | ||
284 | if (tid == INT_MIN || tid == INT_MAX || | 284 | if (tid == INT_MIN || tid == INT_MAX || |
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c index 8ae051e0ec79..c330780674fc 100644 --- a/tools/perf/util/trace-event.c +++ b/tools/perf/util/trace-event.c | |||
@@ -105,3 +105,11 @@ trace_event__tp_format(const char *sys, const char *name) | |||
105 | 105 | ||
106 | return tp_format(sys, name); | 106 | return tp_format(sys, name); |
107 | } | 107 | } |
108 | |||
109 | struct event_format *trace_event__tp_format_id(int id) | ||
110 | { | ||
111 | if (!tevent_initialized && trace_event__init2()) | ||
112 | return ERR_PTR(-ENOMEM); | ||
113 | |||
114 | return pevent_find_event(tevent.pevent, id); | ||
115 | } | ||
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index bce5b1dac268..b0af9c81bb0d 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h | |||
@@ -23,6 +23,8 @@ int trace_event__register_resolver(struct machine *machine, | |||
23 | struct event_format* | 23 | struct event_format* |
24 | trace_event__tp_format(const char *sys, const char *name); | 24 | trace_event__tp_format(const char *sys, const char *name); |
25 | 25 | ||
26 | struct event_format *trace_event__tp_format_id(int id); | ||
27 | |||
26 | int bigendian(void); | 28 | int bigendian(void); |
27 | 29 | ||
28 | void event_format__fprintf(struct event_format *event, | 30 | void event_format__fprintf(struct event_format *event, |
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c new file mode 100644 index 000000000000..97c0f8fc5561 --- /dev/null +++ b/tools/perf/util/unwind-libunwind-local.c | |||
@@ -0,0 +1,699 @@ | |||
1 | /* | ||
2 | * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps. | ||
3 | * | ||
4 | * Lots of this code have been borrowed or heavily inspired from parts of | ||
5 | * the libunwind 0.99 code which are (amongst other contributors I may have | ||
6 | * forgotten): | ||
7 | * | ||
8 | * Copyright (C) 2002-2007 Hewlett-Packard Co | ||
9 | * Contributed by David Mosberger-Tang <davidm@hpl.hp.com> | ||
10 | * | ||
11 | * And the bugs have been added by: | ||
12 | * | ||
13 | * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com> | ||
14 | * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com> | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <elf.h> | ||
19 | #include <gelf.h> | ||
20 | #include <fcntl.h> | ||
21 | #include <string.h> | ||
22 | #include <unistd.h> | ||
23 | #include <sys/mman.h> | ||
24 | #include <linux/list.h> | ||
25 | #ifndef REMOTE_UNWIND_LIBUNWIND | ||
26 | #include <libunwind.h> | ||
27 | #include <libunwind-ptrace.h> | ||
28 | #endif | ||
29 | #include "callchain.h" | ||
30 | #include "thread.h" | ||
31 | #include "session.h" | ||
32 | #include "perf_regs.h" | ||
33 | #include "unwind.h" | ||
34 | #include "symbol.h" | ||
35 | #include "util.h" | ||
36 | #include "debug.h" | ||
37 | #include "asm/bug.h" | ||
38 | |||
39 | extern int | ||
40 | UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, | ||
41 | unw_word_t ip, | ||
42 | unw_dyn_info_t *di, | ||
43 | unw_proc_info_t *pi, | ||
44 | int need_unwind_info, void *arg); | ||
45 | |||
46 | #define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) | ||
47 | |||
48 | extern int | ||
49 | UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, | ||
50 | unw_word_t ip, | ||
51 | unw_word_t segbase, | ||
52 | const char *obj_name, unw_word_t start, | ||
53 | unw_word_t end); | ||
54 | |||
55 | #define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) | ||
56 | |||
57 | #define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ | ||
58 | #define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ | ||
59 | |||
60 | /* Pointer-encoding formats: */ | ||
61 | #define DW_EH_PE_omit 0xff | ||
62 | #define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */ | ||
63 | #define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */ | ||
64 | #define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */ | ||
65 | #define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */ | ||
66 | #define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */ | ||
67 | |||
68 | /* Pointer-encoding application: */ | ||
69 | #define DW_EH_PE_absptr 0x00 /* absolute value */ | ||
70 | #define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */ | ||
71 | |||
72 | /* | ||
73 | * The following are not documented by LSB v1.3, yet they are used by | ||
74 | * GCC, presumably they aren't documented by LSB since they aren't | ||
75 | * used on Linux: | ||
76 | */ | ||
77 | #define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */ | ||
78 | #define DW_EH_PE_aligned 0x50 /* aligned pointer */ | ||
79 | |||
80 | /* Flags intentionaly not handled, since they're not needed: | ||
81 | * #define DW_EH_PE_indirect 0x80 | ||
82 | * #define DW_EH_PE_uleb128 0x01 | ||
83 | * #define DW_EH_PE_udata2 0x02 | ||
84 | * #define DW_EH_PE_sleb128 0x09 | ||
85 | * #define DW_EH_PE_sdata2 0x0a | ||
86 | * #define DW_EH_PE_textrel 0x20 | ||
87 | * #define DW_EH_PE_datarel 0x30 | ||
88 | */ | ||
89 | |||
90 | struct unwind_info { | ||
91 | struct perf_sample *sample; | ||
92 | struct machine *machine; | ||
93 | struct thread *thread; | ||
94 | }; | ||
95 | |||
96 | #define dw_read(ptr, type, end) ({ \ | ||
97 | type *__p = (type *) ptr; \ | ||
98 | type __v; \ | ||
99 | if ((__p + 1) > (type *) end) \ | ||
100 | return -EINVAL; \ | ||
101 | __v = *__p++; \ | ||
102 | ptr = (typeof(ptr)) __p; \ | ||
103 | __v; \ | ||
104 | }) | ||
105 | |||
106 | static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, | ||
107 | u8 encoding) | ||
108 | { | ||
109 | u8 *cur = *p; | ||
110 | *val = 0; | ||
111 | |||
112 | switch (encoding) { | ||
113 | case DW_EH_PE_omit: | ||
114 | *val = 0; | ||
115 | goto out; | ||
116 | case DW_EH_PE_ptr: | ||
117 | *val = dw_read(cur, unsigned long, end); | ||
118 | goto out; | ||
119 | default: | ||
120 | break; | ||
121 | } | ||
122 | |||
123 | switch (encoding & DW_EH_PE_APPL_MASK) { | ||
124 | case DW_EH_PE_absptr: | ||
125 | break; | ||
126 | case DW_EH_PE_pcrel: | ||
127 | *val = (unsigned long) cur; | ||
128 | break; | ||
129 | default: | ||
130 | return -EINVAL; | ||
131 | } | ||
132 | |||
133 | if ((encoding & 0x07) == 0x00) | ||
134 | encoding |= DW_EH_PE_udata4; | ||
135 | |||
136 | switch (encoding & DW_EH_PE_FORMAT_MASK) { | ||
137 | case DW_EH_PE_sdata4: | ||
138 | *val += dw_read(cur, s32, end); | ||
139 | break; | ||
140 | case DW_EH_PE_udata4: | ||
141 | *val += dw_read(cur, u32, end); | ||
142 | break; | ||
143 | case DW_EH_PE_sdata8: | ||
144 | *val += dw_read(cur, s64, end); | ||
145 | break; | ||
146 | case DW_EH_PE_udata8: | ||
147 | *val += dw_read(cur, u64, end); | ||
148 | break; | ||
149 | default: | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | |||
153 | out: | ||
154 | *p = cur; | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | #define dw_read_encoded_value(ptr, end, enc) ({ \ | ||
159 | u64 __v; \ | ||
160 | if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \ | ||
161 | return -EINVAL; \ | ||
162 | } \ | ||
163 | __v; \ | ||
164 | }) | ||
165 | |||
166 | static u64 elf_section_offset(int fd, const char *name) | ||
167 | { | ||
168 | Elf *elf; | ||
169 | GElf_Ehdr ehdr; | ||
170 | GElf_Shdr shdr; | ||
171 | u64 offset = 0; | ||
172 | |||
173 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
174 | if (elf == NULL) | ||
175 | return 0; | ||
176 | |||
177 | do { | ||
178 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
179 | break; | ||
180 | |||
181 | if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL)) | ||
182 | break; | ||
183 | |||
184 | offset = shdr.sh_offset; | ||
185 | } while (0); | ||
186 | |||
187 | elf_end(elf); | ||
188 | return offset; | ||
189 | } | ||
190 | |||
191 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | ||
192 | static int elf_is_exec(int fd, const char *name) | ||
193 | { | ||
194 | Elf *elf; | ||
195 | GElf_Ehdr ehdr; | ||
196 | int retval = 0; | ||
197 | |||
198 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
199 | if (elf == NULL) | ||
200 | return 0; | ||
201 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
202 | goto out; | ||
203 | |||
204 | retval = (ehdr.e_type == ET_EXEC); | ||
205 | |||
206 | out: | ||
207 | elf_end(elf); | ||
208 | pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval); | ||
209 | return retval; | ||
210 | } | ||
211 | #endif | ||
212 | |||
213 | struct table_entry { | ||
214 | u32 start_ip_offset; | ||
215 | u32 fde_offset; | ||
216 | }; | ||
217 | |||
218 | struct eh_frame_hdr { | ||
219 | unsigned char version; | ||
220 | unsigned char eh_frame_ptr_enc; | ||
221 | unsigned char fde_count_enc; | ||
222 | unsigned char table_enc; | ||
223 | |||
224 | /* | ||
225 | * The rest of the header is variable-length and consists of the | ||
226 | * following members: | ||
227 | * | ||
228 | * encoded_t eh_frame_ptr; | ||
229 | * encoded_t fde_count; | ||
230 | */ | ||
231 | |||
232 | /* A single encoded pointer should not be more than 8 bytes. */ | ||
233 | u64 enc[2]; | ||
234 | |||
235 | /* | ||
236 | * struct { | ||
237 | * encoded_t start_ip; | ||
238 | * encoded_t fde_addr; | ||
239 | * } binary_search_table[fde_count]; | ||
240 | */ | ||
241 | char data[0]; | ||
242 | } __packed; | ||
243 | |||
244 | static int unwind_spec_ehframe(struct dso *dso, struct machine *machine, | ||
245 | u64 offset, u64 *table_data, u64 *segbase, | ||
246 | u64 *fde_count) | ||
247 | { | ||
248 | struct eh_frame_hdr hdr; | ||
249 | u8 *enc = (u8 *) &hdr.enc; | ||
250 | u8 *end = (u8 *) &hdr.data; | ||
251 | ssize_t r; | ||
252 | |||
253 | r = dso__data_read_offset(dso, machine, offset, | ||
254 | (u8 *) &hdr, sizeof(hdr)); | ||
255 | if (r != sizeof(hdr)) | ||
256 | return -EINVAL; | ||
257 | |||
258 | /* We dont need eh_frame_ptr, just skip it. */ | ||
259 | dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc); | ||
260 | |||
261 | *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc); | ||
262 | *segbase = offset; | ||
263 | *table_data = (enc - (u8 *) &hdr) + offset; | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine, | ||
268 | u64 *table_data, u64 *segbase, | ||
269 | u64 *fde_count) | ||
270 | { | ||
271 | int ret = -EINVAL, fd; | ||
272 | u64 offset = dso->data.eh_frame_hdr_offset; | ||
273 | |||
274 | if (offset == 0) { | ||
275 | fd = dso__data_get_fd(dso, machine); | ||
276 | if (fd < 0) | ||
277 | return -EINVAL; | ||
278 | |||
279 | /* Check the .eh_frame section for unwinding info */ | ||
280 | offset = elf_section_offset(fd, ".eh_frame_hdr"); | ||
281 | dso->data.eh_frame_hdr_offset = offset; | ||
282 | dso__data_put_fd(dso); | ||
283 | } | ||
284 | |||
285 | if (offset) | ||
286 | ret = unwind_spec_ehframe(dso, machine, offset, | ||
287 | table_data, segbase, | ||
288 | fde_count); | ||
289 | |||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | ||
294 | static int read_unwind_spec_debug_frame(struct dso *dso, | ||
295 | struct machine *machine, u64 *offset) | ||
296 | { | ||
297 | int fd; | ||
298 | u64 ofs = dso->data.debug_frame_offset; | ||
299 | |||
300 | if (ofs == 0) { | ||
301 | fd = dso__data_get_fd(dso, machine); | ||
302 | if (fd < 0) | ||
303 | return -EINVAL; | ||
304 | |||
305 | /* Check the .debug_frame section for unwinding info */ | ||
306 | ofs = elf_section_offset(fd, ".debug_frame"); | ||
307 | dso->data.debug_frame_offset = ofs; | ||
308 | dso__data_put_fd(dso); | ||
309 | } | ||
310 | |||
311 | *offset = ofs; | ||
312 | if (*offset) | ||
313 | return 0; | ||
314 | |||
315 | return -EINVAL; | ||
316 | } | ||
317 | #endif | ||
318 | |||
319 | static struct map *find_map(unw_word_t ip, struct unwind_info *ui) | ||
320 | { | ||
321 | struct addr_location al; | ||
322 | |||
323 | thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, | ||
324 | MAP__FUNCTION, ip, &al); | ||
325 | if (!al.map) { | ||
326 | /* | ||
327 | * We've seen cases (softice) where DWARF unwinder went | ||
328 | * through non executable mmaps, which we need to lookup | ||
329 | * in MAP__VARIABLE tree. | ||
330 | */ | ||
331 | thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, | ||
332 | MAP__VARIABLE, ip, &al); | ||
333 | } | ||
334 | return al.map; | ||
335 | } | ||
336 | |||
337 | static int | ||
338 | find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | ||
339 | int need_unwind_info, void *arg) | ||
340 | { | ||
341 | struct unwind_info *ui = arg; | ||
342 | struct map *map; | ||
343 | unw_dyn_info_t di; | ||
344 | u64 table_data, segbase, fde_count; | ||
345 | int ret = -EINVAL; | ||
346 | |||
347 | map = find_map(ip, ui); | ||
348 | if (!map || !map->dso) | ||
349 | return -EINVAL; | ||
350 | |||
351 | pr_debug("unwind: find_proc_info dso %s\n", map->dso->name); | ||
352 | |||
353 | /* Check the .eh_frame section for unwinding info */ | ||
354 | if (!read_unwind_spec_eh_frame(map->dso, ui->machine, | ||
355 | &table_data, &segbase, &fde_count)) { | ||
356 | memset(&di, 0, sizeof(di)); | ||
357 | di.format = UNW_INFO_FORMAT_REMOTE_TABLE; | ||
358 | di.start_ip = map->start; | ||
359 | di.end_ip = map->end; | ||
360 | di.u.rti.segbase = map->start + segbase; | ||
361 | di.u.rti.table_data = map->start + table_data; | ||
362 | di.u.rti.table_len = fde_count * sizeof(struct table_entry) | ||
363 | / sizeof(unw_word_t); | ||
364 | ret = dwarf_search_unwind_table(as, ip, &di, pi, | ||
365 | need_unwind_info, arg); | ||
366 | } | ||
367 | |||
368 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | ||
369 | /* Check the .debug_frame section for unwinding info */ | ||
370 | if (ret < 0 && | ||
371 | !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { | ||
372 | int fd = dso__data_get_fd(map->dso, ui->machine); | ||
373 | int is_exec = elf_is_exec(fd, map->dso->name); | ||
374 | unw_word_t base = is_exec ? 0 : map->start; | ||
375 | const char *symfile; | ||
376 | |||
377 | if (fd >= 0) | ||
378 | dso__data_put_fd(map->dso); | ||
379 | |||
380 | symfile = map->dso->symsrc_filename ?: map->dso->name; | ||
381 | |||
382 | memset(&di, 0, sizeof(di)); | ||
383 | if (dwarf_find_debug_frame(0, &di, ip, base, symfile, | ||
384 | map->start, map->end)) | ||
385 | return dwarf_search_unwind_table(as, ip, &di, pi, | ||
386 | need_unwind_info, arg); | ||
387 | } | ||
388 | #endif | ||
389 | |||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | static int access_fpreg(unw_addr_space_t __maybe_unused as, | ||
394 | unw_regnum_t __maybe_unused num, | ||
395 | unw_fpreg_t __maybe_unused *val, | ||
396 | int __maybe_unused __write, | ||
397 | void __maybe_unused *arg) | ||
398 | { | ||
399 | pr_err("unwind: access_fpreg unsupported\n"); | ||
400 | return -UNW_EINVAL; | ||
401 | } | ||
402 | |||
403 | static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, | ||
404 | unw_word_t __maybe_unused *dil_addr, | ||
405 | void __maybe_unused *arg) | ||
406 | { | ||
407 | return -UNW_ENOINFO; | ||
408 | } | ||
409 | |||
410 | static int resume(unw_addr_space_t __maybe_unused as, | ||
411 | unw_cursor_t __maybe_unused *cu, | ||
412 | void __maybe_unused *arg) | ||
413 | { | ||
414 | pr_err("unwind: resume unsupported\n"); | ||
415 | return -UNW_EINVAL; | ||
416 | } | ||
417 | |||
418 | static int | ||
419 | get_proc_name(unw_addr_space_t __maybe_unused as, | ||
420 | unw_word_t __maybe_unused addr, | ||
421 | char __maybe_unused *bufp, size_t __maybe_unused buf_len, | ||
422 | unw_word_t __maybe_unused *offp, void __maybe_unused *arg) | ||
423 | { | ||
424 | pr_err("unwind: get_proc_name unsupported\n"); | ||
425 | return -UNW_EINVAL; | ||
426 | } | ||
427 | |||
428 | static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, | ||
429 | unw_word_t *data) | ||
430 | { | ||
431 | struct map *map; | ||
432 | ssize_t size; | ||
433 | |||
434 | map = find_map(addr, ui); | ||
435 | if (!map) { | ||
436 | pr_debug("unwind: no map for %lx\n", (unsigned long)addr); | ||
437 | return -1; | ||
438 | } | ||
439 | |||
440 | if (!map->dso) | ||
441 | return -1; | ||
442 | |||
443 | size = dso__data_read_addr(map->dso, map, ui->machine, | ||
444 | addr, (u8 *) data, sizeof(*data)); | ||
445 | |||
446 | return !(size == sizeof(*data)); | ||
447 | } | ||
448 | |||
449 | static int access_mem(unw_addr_space_t __maybe_unused as, | ||
450 | unw_word_t addr, unw_word_t *valp, | ||
451 | int __write, void *arg) | ||
452 | { | ||
453 | struct unwind_info *ui = arg; | ||
454 | struct stack_dump *stack = &ui->sample->user_stack; | ||
455 | u64 start, end; | ||
456 | int offset; | ||
457 | int ret; | ||
458 | |||
459 | /* Don't support write, probably not needed. */ | ||
460 | if (__write || !stack || !ui->sample->user_regs.regs) { | ||
461 | *valp = 0; | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | ret = perf_reg_value(&start, &ui->sample->user_regs, | ||
466 | LIBUNWIND__ARCH_REG_SP); | ||
467 | if (ret) | ||
468 | return ret; | ||
469 | |||
470 | end = start + stack->size; | ||
471 | |||
472 | /* Check overflow. */ | ||
473 | if (addr + sizeof(unw_word_t) < addr) | ||
474 | return -EINVAL; | ||
475 | |||
476 | if (addr < start || addr + sizeof(unw_word_t) >= end) { | ||
477 | ret = access_dso_mem(ui, addr, valp); | ||
478 | if (ret) { | ||
479 | pr_debug("unwind: access_mem %p not inside range" | ||
480 | " 0x%" PRIx64 "-0x%" PRIx64 "\n", | ||
481 | (void *) (uintptr_t) addr, start, end); | ||
482 | *valp = 0; | ||
483 | return ret; | ||
484 | } | ||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | offset = addr - start; | ||
489 | *valp = *(unw_word_t *)&stack->data[offset]; | ||
490 | pr_debug("unwind: access_mem addr %p val %lx, offset %d\n", | ||
491 | (void *) (uintptr_t) addr, (unsigned long)*valp, offset); | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static int access_reg(unw_addr_space_t __maybe_unused as, | ||
496 | unw_regnum_t regnum, unw_word_t *valp, | ||
497 | int __write, void *arg) | ||
498 | { | ||
499 | struct unwind_info *ui = arg; | ||
500 | int id, ret; | ||
501 | u64 val; | ||
502 | |||
503 | /* Don't support write, I suspect we don't need it. */ | ||
504 | if (__write) { | ||
505 | pr_err("unwind: access_reg w %d\n", regnum); | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | if (!ui->sample->user_regs.regs) { | ||
510 | *valp = 0; | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | id = LIBUNWIND__ARCH_REG_ID(regnum); | ||
515 | if (id < 0) | ||
516 | return -EINVAL; | ||
517 | |||
518 | ret = perf_reg_value(&val, &ui->sample->user_regs, id); | ||
519 | if (ret) { | ||
520 | pr_err("unwind: can't read reg %d\n", regnum); | ||
521 | return ret; | ||
522 | } | ||
523 | |||
524 | *valp = (unw_word_t) val; | ||
525 | pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp); | ||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | static void put_unwind_info(unw_addr_space_t __maybe_unused as, | ||
530 | unw_proc_info_t *pi __maybe_unused, | ||
531 | void *arg __maybe_unused) | ||
532 | { | ||
533 | pr_debug("unwind: put_unwind_info called\n"); | ||
534 | } | ||
535 | |||
536 | static int entry(u64 ip, struct thread *thread, | ||
537 | unwind_entry_cb_t cb, void *arg) | ||
538 | { | ||
539 | struct unwind_entry e; | ||
540 | struct addr_location al; | ||
541 | |||
542 | thread__find_addr_location(thread, PERF_RECORD_MISC_USER, | ||
543 | MAP__FUNCTION, ip, &al); | ||
544 | |||
545 | e.ip = ip; | ||
546 | e.map = al.map; | ||
547 | e.sym = al.sym; | ||
548 | |||
549 | pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", | ||
550 | al.sym ? al.sym->name : "''", | ||
551 | ip, | ||
552 | al.map ? al.map->map_ip(al.map, ip) : (u64) 0); | ||
553 | |||
554 | return cb(&e, arg); | ||
555 | } | ||
556 | |||
557 | static void display_error(int err) | ||
558 | { | ||
559 | switch (err) { | ||
560 | case UNW_EINVAL: | ||
561 | pr_err("unwind: Only supports local.\n"); | ||
562 | break; | ||
563 | case UNW_EUNSPEC: | ||
564 | pr_err("unwind: Unspecified error.\n"); | ||
565 | break; | ||
566 | case UNW_EBADREG: | ||
567 | pr_err("unwind: Register unavailable.\n"); | ||
568 | break; | ||
569 | default: | ||
570 | break; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | static unw_accessors_t accessors = { | ||
575 | .find_proc_info = find_proc_info, | ||
576 | .put_unwind_info = put_unwind_info, | ||
577 | .get_dyn_info_list_addr = get_dyn_info_list_addr, | ||
578 | .access_mem = access_mem, | ||
579 | .access_reg = access_reg, | ||
580 | .access_fpreg = access_fpreg, | ||
581 | .resume = resume, | ||
582 | .get_proc_name = get_proc_name, | ||
583 | }; | ||
584 | |||
585 | static int _unwind__prepare_access(struct thread *thread) | ||
586 | { | ||
587 | if (callchain_param.record_mode != CALLCHAIN_DWARF) | ||
588 | return 0; | ||
589 | |||
590 | thread->addr_space = unw_create_addr_space(&accessors, 0); | ||
591 | if (!thread->addr_space) { | ||
592 | pr_err("unwind: Can't create unwind address space.\n"); | ||
593 | return -ENOMEM; | ||
594 | } | ||
595 | |||
596 | unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL); | ||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static void _unwind__flush_access(struct thread *thread) | ||
601 | { | ||
602 | if (callchain_param.record_mode != CALLCHAIN_DWARF) | ||
603 | return; | ||
604 | |||
605 | unw_flush_cache(thread->addr_space, 0, 0); | ||
606 | } | ||
607 | |||
608 | static void _unwind__finish_access(struct thread *thread) | ||
609 | { | ||
610 | if (callchain_param.record_mode != CALLCHAIN_DWARF) | ||
611 | return; | ||
612 | |||
613 | unw_destroy_addr_space(thread->addr_space); | ||
614 | } | ||
615 | |||
616 | static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, | ||
617 | void *arg, int max_stack) | ||
618 | { | ||
619 | u64 val; | ||
620 | unw_word_t ips[max_stack]; | ||
621 | unw_addr_space_t addr_space; | ||
622 | unw_cursor_t c; | ||
623 | int ret, i = 0; | ||
624 | |||
625 | ret = perf_reg_value(&val, &ui->sample->user_regs, | ||
626 | LIBUNWIND__ARCH_REG_IP); | ||
627 | if (ret) | ||
628 | return ret; | ||
629 | |||
630 | ips[i++] = (unw_word_t) val; | ||
631 | |||
632 | /* | ||
633 | * If we need more than one entry, do the DWARF | ||
634 | * unwind itself. | ||
635 | */ | ||
636 | if (max_stack - 1 > 0) { | ||
637 | WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL"); | ||
638 | addr_space = ui->thread->addr_space; | ||
639 | |||
640 | if (addr_space == NULL) | ||
641 | return -1; | ||
642 | |||
643 | ret = unw_init_remote(&c, addr_space, ui); | ||
644 | if (ret) | ||
645 | display_error(ret); | ||
646 | |||
647 | while (!ret && (unw_step(&c) > 0) && i < max_stack) { | ||
648 | unw_get_reg(&c, UNW_REG_IP, &ips[i]); | ||
649 | ++i; | ||
650 | } | ||
651 | |||
652 | max_stack = i; | ||
653 | } | ||
654 | |||
655 | /* | ||
656 | * Display what we got based on the order setup. | ||
657 | */ | ||
658 | for (i = 0; i < max_stack && !ret; i++) { | ||
659 | int j = i; | ||
660 | |||
661 | if (callchain_param.order == ORDER_CALLER) | ||
662 | j = max_stack - i - 1; | ||
663 | ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0; | ||
664 | } | ||
665 | |||
666 | return ret; | ||
667 | } | ||
668 | |||
669 | static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg, | ||
670 | struct thread *thread, | ||
671 | struct perf_sample *data, int max_stack) | ||
672 | { | ||
673 | struct unwind_info ui = { | ||
674 | .sample = data, | ||
675 | .thread = thread, | ||
676 | .machine = thread->mg->machine, | ||
677 | }; | ||
678 | |||
679 | if (!data->user_regs.regs) | ||
680 | return -EINVAL; | ||
681 | |||
682 | if (max_stack <= 0) | ||
683 | return -EINVAL; | ||
684 | |||
685 | return get_entries(&ui, cb, arg, max_stack); | ||
686 | } | ||
687 | |||
688 | static struct unwind_libunwind_ops | ||
689 | _unwind_libunwind_ops = { | ||
690 | .prepare_access = _unwind__prepare_access, | ||
691 | .flush_access = _unwind__flush_access, | ||
692 | .finish_access = _unwind__finish_access, | ||
693 | .get_entries = _unwind__get_entries, | ||
694 | }; | ||
695 | |||
696 | #ifndef REMOTE_UNWIND_LIBUNWIND | ||
697 | struct unwind_libunwind_ops * | ||
698 | local_unwind_libunwind_ops = &_unwind_libunwind_ops; | ||
699 | #endif | ||
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 63687d3a344e..6d542a4e0648 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
@@ -1,682 +1,83 @@ | |||
1 | /* | 1 | #include "unwind.h" |
2 | * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps. | ||
3 | * | ||
4 | * Lots of this code have been borrowed or heavily inspired from parts of | ||
5 | * the libunwind 0.99 code which are (amongst other contributors I may have | ||
6 | * forgotten): | ||
7 | * | ||
8 | * Copyright (C) 2002-2007 Hewlett-Packard Co | ||
9 | * Contributed by David Mosberger-Tang <davidm@hpl.hp.com> | ||
10 | * | ||
11 | * And the bugs have been added by: | ||
12 | * | ||
13 | * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com> | ||
14 | * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com> | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <elf.h> | ||
19 | #include <gelf.h> | ||
20 | #include <fcntl.h> | ||
21 | #include <string.h> | ||
22 | #include <unistd.h> | ||
23 | #include <sys/mman.h> | ||
24 | #include <linux/list.h> | ||
25 | #include <libunwind.h> | ||
26 | #include <libunwind-ptrace.h> | ||
27 | #include "callchain.h" | ||
28 | #include "thread.h" | 2 | #include "thread.h" |
29 | #include "session.h" | 3 | #include "session.h" |
30 | #include "perf_regs.h" | ||
31 | #include "unwind.h" | ||
32 | #include "symbol.h" | ||
33 | #include "util.h" | ||
34 | #include "debug.h" | 4 | #include "debug.h" |
35 | #include "asm/bug.h" | 5 | #include "arch/common.h" |
36 | |||
37 | extern int | ||
38 | UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, | ||
39 | unw_word_t ip, | ||
40 | unw_dyn_info_t *di, | ||
41 | unw_proc_info_t *pi, | ||
42 | int need_unwind_info, void *arg); | ||
43 | |||
44 | #define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) | ||
45 | |||
46 | extern int | ||
47 | UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, | ||
48 | unw_word_t ip, | ||
49 | unw_word_t segbase, | ||
50 | const char *obj_name, unw_word_t start, | ||
51 | unw_word_t end); | ||
52 | |||
53 | #define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) | ||
54 | |||
55 | #define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */ | ||
56 | #define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */ | ||
57 | |||
58 | /* Pointer-encoding formats: */ | ||
59 | #define DW_EH_PE_omit 0xff | ||
60 | #define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */ | ||
61 | #define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */ | ||
62 | #define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */ | ||
63 | #define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */ | ||
64 | #define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */ | ||
65 | |||
66 | /* Pointer-encoding application: */ | ||
67 | #define DW_EH_PE_absptr 0x00 /* absolute value */ | ||
68 | #define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */ | ||
69 | |||
70 | /* | ||
71 | * The following are not documented by LSB v1.3, yet they are used by | ||
72 | * GCC, presumably they aren't documented by LSB since they aren't | ||
73 | * used on Linux: | ||
74 | */ | ||
75 | #define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */ | ||
76 | #define DW_EH_PE_aligned 0x50 /* aligned pointer */ | ||
77 | 6 | ||
78 | /* Flags intentionaly not handled, since they're not needed: | 7 | struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops; |
79 | * #define DW_EH_PE_indirect 0x80 | 8 | struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops; |
80 | * #define DW_EH_PE_uleb128 0x01 | 9 | struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops; |
81 | * #define DW_EH_PE_udata2 0x02 | ||
82 | * #define DW_EH_PE_sleb128 0x09 | ||
83 | * #define DW_EH_PE_sdata2 0x0a | ||
84 | * #define DW_EH_PE_textrel 0x20 | ||
85 | * #define DW_EH_PE_datarel 0x30 | ||
86 | */ | ||
87 | 10 | ||
88 | struct unwind_info { | 11 | static void unwind__register_ops(struct thread *thread, |
89 | struct perf_sample *sample; | 12 | struct unwind_libunwind_ops *ops) |
90 | struct machine *machine; | ||
91 | struct thread *thread; | ||
92 | }; | ||
93 | |||
94 | #define dw_read(ptr, type, end) ({ \ | ||
95 | type *__p = (type *) ptr; \ | ||
96 | type __v; \ | ||
97 | if ((__p + 1) > (type *) end) \ | ||
98 | return -EINVAL; \ | ||
99 | __v = *__p++; \ | ||
100 | ptr = (typeof(ptr)) __p; \ | ||
101 | __v; \ | ||
102 | }) | ||
103 | |||
104 | static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, | ||
105 | u8 encoding) | ||
106 | { | 13 | { |
107 | u8 *cur = *p; | 14 | thread->unwind_libunwind_ops = ops; |
108 | *val = 0; | ||
109 | |||
110 | switch (encoding) { | ||
111 | case DW_EH_PE_omit: | ||
112 | *val = 0; | ||
113 | goto out; | ||
114 | case DW_EH_PE_ptr: | ||
115 | *val = dw_read(cur, unsigned long, end); | ||
116 | goto out; | ||
117 | default: | ||
118 | break; | ||
119 | } | ||
120 | |||
121 | switch (encoding & DW_EH_PE_APPL_MASK) { | ||
122 | case DW_EH_PE_absptr: | ||
123 | break; | ||
124 | case DW_EH_PE_pcrel: | ||
125 | *val = (unsigned long) cur; | ||
126 | break; | ||
127 | default: | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | if ((encoding & 0x07) == 0x00) | ||
132 | encoding |= DW_EH_PE_udata4; | ||
133 | |||
134 | switch (encoding & DW_EH_PE_FORMAT_MASK) { | ||
135 | case DW_EH_PE_sdata4: | ||
136 | *val += dw_read(cur, s32, end); | ||
137 | break; | ||
138 | case DW_EH_PE_udata4: | ||
139 | *val += dw_read(cur, u32, end); | ||
140 | break; | ||
141 | case DW_EH_PE_sdata8: | ||
142 | *val += dw_read(cur, s64, end); | ||
143 | break; | ||
144 | case DW_EH_PE_udata8: | ||
145 | *val += dw_read(cur, u64, end); | ||
146 | break; | ||
147 | default: | ||
148 | return -EINVAL; | ||
149 | } | ||
150 | |||
151 | out: | ||
152 | *p = cur; | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | #define dw_read_encoded_value(ptr, end, enc) ({ \ | ||
157 | u64 __v; \ | ||
158 | if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \ | ||
159 | return -EINVAL; \ | ||
160 | } \ | ||
161 | __v; \ | ||
162 | }) | ||
163 | |||
164 | static u64 elf_section_offset(int fd, const char *name) | ||
165 | { | ||
166 | Elf *elf; | ||
167 | GElf_Ehdr ehdr; | ||
168 | GElf_Shdr shdr; | ||
169 | u64 offset = 0; | ||
170 | |||
171 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
172 | if (elf == NULL) | ||
173 | return 0; | ||
174 | |||
175 | do { | ||
176 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
177 | break; | ||
178 | |||
179 | if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL)) | ||
180 | break; | ||
181 | |||
182 | offset = shdr.sh_offset; | ||
183 | } while (0); | ||
184 | |||
185 | elf_end(elf); | ||
186 | return offset; | ||
187 | } | 15 | } |
188 | 16 | ||
189 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | 17 | int unwind__prepare_access(struct thread *thread, struct map *map, |
190 | static int elf_is_exec(int fd, const char *name) | 18 | bool *initialized) |
191 | { | 19 | { |
192 | Elf *elf; | 20 | const char *arch; |
193 | GElf_Ehdr ehdr; | 21 | enum dso_type dso_type; |
194 | int retval = 0; | 22 | struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops; |
23 | int err; | ||
195 | 24 | ||
196 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | 25 | if (thread->addr_space) { |
197 | if (elf == NULL) | 26 | pr_debug("unwind: thread map already set, dso=%s\n", |
27 | map->dso->name); | ||
28 | if (initialized) | ||
29 | *initialized = true; | ||
198 | return 0; | 30 | return 0; |
199 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
200 | goto out; | ||
201 | |||
202 | retval = (ehdr.e_type == ET_EXEC); | ||
203 | |||
204 | out: | ||
205 | elf_end(elf); | ||
206 | pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval); | ||
207 | return retval; | ||
208 | } | ||
209 | #endif | ||
210 | |||
211 | struct table_entry { | ||
212 | u32 start_ip_offset; | ||
213 | u32 fde_offset; | ||
214 | }; | ||
215 | |||
216 | struct eh_frame_hdr { | ||
217 | unsigned char version; | ||
218 | unsigned char eh_frame_ptr_enc; | ||
219 | unsigned char fde_count_enc; | ||
220 | unsigned char table_enc; | ||
221 | |||
222 | /* | ||
223 | * The rest of the header is variable-length and consists of the | ||
224 | * following members: | ||
225 | * | ||
226 | * encoded_t eh_frame_ptr; | ||
227 | * encoded_t fde_count; | ||
228 | */ | ||
229 | |||
230 | /* A single encoded pointer should not be more than 8 bytes. */ | ||
231 | u64 enc[2]; | ||
232 | |||
233 | /* | ||
234 | * struct { | ||
235 | * encoded_t start_ip; | ||
236 | * encoded_t fde_addr; | ||
237 | * } binary_search_table[fde_count]; | ||
238 | */ | ||
239 | char data[0]; | ||
240 | } __packed; | ||
241 | |||
242 | static int unwind_spec_ehframe(struct dso *dso, struct machine *machine, | ||
243 | u64 offset, u64 *table_data, u64 *segbase, | ||
244 | u64 *fde_count) | ||
245 | { | ||
246 | struct eh_frame_hdr hdr; | ||
247 | u8 *enc = (u8 *) &hdr.enc; | ||
248 | u8 *end = (u8 *) &hdr.data; | ||
249 | ssize_t r; | ||
250 | |||
251 | r = dso__data_read_offset(dso, machine, offset, | ||
252 | (u8 *) &hdr, sizeof(hdr)); | ||
253 | if (r != sizeof(hdr)) | ||
254 | return -EINVAL; | ||
255 | |||
256 | /* We dont need eh_frame_ptr, just skip it. */ | ||
257 | dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc); | ||
258 | |||
259 | *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc); | ||
260 | *segbase = offset; | ||
261 | *table_data = (enc - (u8 *) &hdr) + offset; | ||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine, | ||
266 | u64 *table_data, u64 *segbase, | ||
267 | u64 *fde_count) | ||
268 | { | ||
269 | int ret = -EINVAL, fd; | ||
270 | u64 offset = dso->data.eh_frame_hdr_offset; | ||
271 | |||
272 | if (offset == 0) { | ||
273 | fd = dso__data_get_fd(dso, machine); | ||
274 | if (fd < 0) | ||
275 | return -EINVAL; | ||
276 | |||
277 | /* Check the .eh_frame section for unwinding info */ | ||
278 | offset = elf_section_offset(fd, ".eh_frame_hdr"); | ||
279 | dso->data.eh_frame_hdr_offset = offset; | ||
280 | dso__data_put_fd(dso); | ||
281 | } | 31 | } |
282 | 32 | ||
283 | if (offset) | 33 | /* env->arch is NULL for live-mode (i.e. perf top) */ |
284 | ret = unwind_spec_ehframe(dso, machine, offset, | 34 | if (!thread->mg->machine->env || !thread->mg->machine->env->arch) |
285 | table_data, segbase, | 35 | goto out_register; |
286 | fde_count); | ||
287 | 36 | ||
288 | return ret; | 37 | dso_type = dso__type(map->dso, thread->mg->machine); |
289 | } | 38 | if (dso_type == DSO__TYPE_UNKNOWN) |
290 | |||
291 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | ||
292 | static int read_unwind_spec_debug_frame(struct dso *dso, | ||
293 | struct machine *machine, u64 *offset) | ||
294 | { | ||
295 | int fd; | ||
296 | u64 ofs = dso->data.debug_frame_offset; | ||
297 | |||
298 | if (ofs == 0) { | ||
299 | fd = dso__data_get_fd(dso, machine); | ||
300 | if (fd < 0) | ||
301 | return -EINVAL; | ||
302 | |||
303 | /* Check the .debug_frame section for unwinding info */ | ||
304 | ofs = elf_section_offset(fd, ".debug_frame"); | ||
305 | dso->data.debug_frame_offset = ofs; | ||
306 | dso__data_put_fd(dso); | ||
307 | } | ||
308 | |||
309 | *offset = ofs; | ||
310 | if (*offset) | ||
311 | return 0; | 39 | return 0; |
312 | 40 | ||
313 | return -EINVAL; | 41 | arch = normalize_arch(thread->mg->machine->env->arch); |
314 | } | ||
315 | #endif | ||
316 | |||
317 | static struct map *find_map(unw_word_t ip, struct unwind_info *ui) | ||
318 | { | ||
319 | struct addr_location al; | ||
320 | |||
321 | thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, | ||
322 | MAP__FUNCTION, ip, &al); | ||
323 | if (!al.map) { | ||
324 | /* | ||
325 | * We've seen cases (softice) where DWARF unwinder went | ||
326 | * through non executable mmaps, which we need to lookup | ||
327 | * in MAP__VARIABLE tree. | ||
328 | */ | ||
329 | thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, | ||
330 | MAP__VARIABLE, ip, &al); | ||
331 | } | ||
332 | return al.map; | ||
333 | } | ||
334 | |||
335 | static int | ||
336 | find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | ||
337 | int need_unwind_info, void *arg) | ||
338 | { | ||
339 | struct unwind_info *ui = arg; | ||
340 | struct map *map; | ||
341 | unw_dyn_info_t di; | ||
342 | u64 table_data, segbase, fde_count; | ||
343 | int ret = -EINVAL; | ||
344 | |||
345 | map = find_map(ip, ui); | ||
346 | if (!map || !map->dso) | ||
347 | return -EINVAL; | ||
348 | |||
349 | pr_debug("unwind: find_proc_info dso %s\n", map->dso->name); | ||
350 | |||
351 | /* Check the .eh_frame section for unwinding info */ | ||
352 | if (!read_unwind_spec_eh_frame(map->dso, ui->machine, | ||
353 | &table_data, &segbase, &fde_count)) { | ||
354 | memset(&di, 0, sizeof(di)); | ||
355 | di.format = UNW_INFO_FORMAT_REMOTE_TABLE; | ||
356 | di.start_ip = map->start; | ||
357 | di.end_ip = map->end; | ||
358 | di.u.rti.segbase = map->start + segbase; | ||
359 | di.u.rti.table_data = map->start + table_data; | ||
360 | di.u.rti.table_len = fde_count * sizeof(struct table_entry) | ||
361 | / sizeof(unw_word_t); | ||
362 | ret = dwarf_search_unwind_table(as, ip, &di, pi, | ||
363 | need_unwind_info, arg); | ||
364 | } | ||
365 | |||
366 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | ||
367 | /* Check the .debug_frame section for unwinding info */ | ||
368 | if (ret < 0 && | ||
369 | !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { | ||
370 | int fd = dso__data_get_fd(map->dso, ui->machine); | ||
371 | int is_exec = elf_is_exec(fd, map->dso->name); | ||
372 | unw_word_t base = is_exec ? 0 : map->start; | ||
373 | const char *symfile; | ||
374 | |||
375 | if (fd >= 0) | ||
376 | dso__data_put_fd(map->dso); | ||
377 | |||
378 | symfile = map->dso->symsrc_filename ?: map->dso->name; | ||
379 | |||
380 | memset(&di, 0, sizeof(di)); | ||
381 | if (dwarf_find_debug_frame(0, &di, ip, base, symfile, | ||
382 | map->start, map->end)) | ||
383 | return dwarf_search_unwind_table(as, ip, &di, pi, | ||
384 | need_unwind_info, arg); | ||
385 | } | ||
386 | #endif | ||
387 | |||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | static int access_fpreg(unw_addr_space_t __maybe_unused as, | ||
392 | unw_regnum_t __maybe_unused num, | ||
393 | unw_fpreg_t __maybe_unused *val, | ||
394 | int __maybe_unused __write, | ||
395 | void __maybe_unused *arg) | ||
396 | { | ||
397 | pr_err("unwind: access_fpreg unsupported\n"); | ||
398 | return -UNW_EINVAL; | ||
399 | } | ||
400 | |||
401 | static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as, | ||
402 | unw_word_t __maybe_unused *dil_addr, | ||
403 | void __maybe_unused *arg) | ||
404 | { | ||
405 | return -UNW_ENOINFO; | ||
406 | } | ||
407 | |||
408 | static int resume(unw_addr_space_t __maybe_unused as, | ||
409 | unw_cursor_t __maybe_unused *cu, | ||
410 | void __maybe_unused *arg) | ||
411 | { | ||
412 | pr_err("unwind: resume unsupported\n"); | ||
413 | return -UNW_EINVAL; | ||
414 | } | ||
415 | 42 | ||
416 | static int | 43 | if (!strcmp(arch, "x86")) { |
417 | get_proc_name(unw_addr_space_t __maybe_unused as, | 44 | if (dso_type != DSO__TYPE_64BIT) |
418 | unw_word_t __maybe_unused addr, | 45 | ops = x86_32_unwind_libunwind_ops; |
419 | char __maybe_unused *bufp, size_t __maybe_unused buf_len, | 46 | } else if (!strcmp(arch, "arm64") || !strcmp(arch, "arm")) { |
420 | unw_word_t __maybe_unused *offp, void __maybe_unused *arg) | 47 | if (dso_type == DSO__TYPE_64BIT) |
421 | { | 48 | ops = arm64_unwind_libunwind_ops; |
422 | pr_err("unwind: get_proc_name unsupported\n"); | ||
423 | return -UNW_EINVAL; | ||
424 | } | ||
425 | |||
426 | static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, | ||
427 | unw_word_t *data) | ||
428 | { | ||
429 | struct map *map; | ||
430 | ssize_t size; | ||
431 | |||
432 | map = find_map(addr, ui); | ||
433 | if (!map) { | ||
434 | pr_debug("unwind: no map for %lx\n", (unsigned long)addr); | ||
435 | return -1; | ||
436 | } | 49 | } |
437 | 50 | ||
438 | if (!map->dso) | 51 | if (!ops) { |
52 | pr_err("unwind: target platform=%s is not supported\n", arch); | ||
439 | return -1; | 53 | return -1; |
440 | |||
441 | size = dso__data_read_addr(map->dso, map, ui->machine, | ||
442 | addr, (u8 *) data, sizeof(*data)); | ||
443 | |||
444 | return !(size == sizeof(*data)); | ||
445 | } | ||
446 | |||
447 | static int access_mem(unw_addr_space_t __maybe_unused as, | ||
448 | unw_word_t addr, unw_word_t *valp, | ||
449 | int __write, void *arg) | ||
450 | { | ||
451 | struct unwind_info *ui = arg; | ||
452 | struct stack_dump *stack = &ui->sample->user_stack; | ||
453 | u64 start, end; | ||
454 | int offset; | ||
455 | int ret; | ||
456 | |||
457 | /* Don't support write, probably not needed. */ | ||
458 | if (__write || !stack || !ui->sample->user_regs.regs) { | ||
459 | *valp = 0; | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP); | ||
464 | if (ret) | ||
465 | return ret; | ||
466 | |||
467 | end = start + stack->size; | ||
468 | |||
469 | /* Check overflow. */ | ||
470 | if (addr + sizeof(unw_word_t) < addr) | ||
471 | return -EINVAL; | ||
472 | |||
473 | if (addr < start || addr + sizeof(unw_word_t) >= end) { | ||
474 | ret = access_dso_mem(ui, addr, valp); | ||
475 | if (ret) { | ||
476 | pr_debug("unwind: access_mem %p not inside range" | ||
477 | " 0x%" PRIx64 "-0x%" PRIx64 "\n", | ||
478 | (void *) (uintptr_t) addr, start, end); | ||
479 | *valp = 0; | ||
480 | return ret; | ||
481 | } | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | offset = addr - start; | ||
486 | *valp = *(unw_word_t *)&stack->data[offset]; | ||
487 | pr_debug("unwind: access_mem addr %p val %lx, offset %d\n", | ||
488 | (void *) (uintptr_t) addr, (unsigned long)*valp, offset); | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int access_reg(unw_addr_space_t __maybe_unused as, | ||
493 | unw_regnum_t regnum, unw_word_t *valp, | ||
494 | int __write, void *arg) | ||
495 | { | ||
496 | struct unwind_info *ui = arg; | ||
497 | int id, ret; | ||
498 | u64 val; | ||
499 | |||
500 | /* Don't support write, I suspect we don't need it. */ | ||
501 | if (__write) { | ||
502 | pr_err("unwind: access_reg w %d\n", regnum); | ||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | if (!ui->sample->user_regs.regs) { | ||
507 | *valp = 0; | ||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | id = libunwind__arch_reg_id(regnum); | ||
512 | if (id < 0) | ||
513 | return -EINVAL; | ||
514 | |||
515 | ret = perf_reg_value(&val, &ui->sample->user_regs, id); | ||
516 | if (ret) { | ||
517 | pr_err("unwind: can't read reg %d\n", regnum); | ||
518 | return ret; | ||
519 | } | ||
520 | |||
521 | *valp = (unw_word_t) val; | ||
522 | pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp); | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static void put_unwind_info(unw_addr_space_t __maybe_unused as, | ||
527 | unw_proc_info_t *pi __maybe_unused, | ||
528 | void *arg __maybe_unused) | ||
529 | { | ||
530 | pr_debug("unwind: put_unwind_info called\n"); | ||
531 | } | ||
532 | |||
533 | static int entry(u64 ip, struct thread *thread, | ||
534 | unwind_entry_cb_t cb, void *arg) | ||
535 | { | ||
536 | struct unwind_entry e; | ||
537 | struct addr_location al; | ||
538 | |||
539 | thread__find_addr_location(thread, PERF_RECORD_MISC_USER, | ||
540 | MAP__FUNCTION, ip, &al); | ||
541 | |||
542 | e.ip = ip; | ||
543 | e.map = al.map; | ||
544 | e.sym = al.sym; | ||
545 | |||
546 | pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", | ||
547 | al.sym ? al.sym->name : "''", | ||
548 | ip, | ||
549 | al.map ? al.map->map_ip(al.map, ip) : (u64) 0); | ||
550 | |||
551 | return cb(&e, arg); | ||
552 | } | ||
553 | |||
554 | static void display_error(int err) | ||
555 | { | ||
556 | switch (err) { | ||
557 | case UNW_EINVAL: | ||
558 | pr_err("unwind: Only supports local.\n"); | ||
559 | break; | ||
560 | case UNW_EUNSPEC: | ||
561 | pr_err("unwind: Unspecified error.\n"); | ||
562 | break; | ||
563 | case UNW_EBADREG: | ||
564 | pr_err("unwind: Register unavailable.\n"); | ||
565 | break; | ||
566 | default: | ||
567 | break; | ||
568 | } | ||
569 | } | ||
570 | |||
571 | static unw_accessors_t accessors = { | ||
572 | .find_proc_info = find_proc_info, | ||
573 | .put_unwind_info = put_unwind_info, | ||
574 | .get_dyn_info_list_addr = get_dyn_info_list_addr, | ||
575 | .access_mem = access_mem, | ||
576 | .access_reg = access_reg, | ||
577 | .access_fpreg = access_fpreg, | ||
578 | .resume = resume, | ||
579 | .get_proc_name = get_proc_name, | ||
580 | }; | ||
581 | |||
582 | int unwind__prepare_access(struct thread *thread) | ||
583 | { | ||
584 | if (callchain_param.record_mode != CALLCHAIN_DWARF) | ||
585 | return 0; | ||
586 | |||
587 | thread->addr_space = unw_create_addr_space(&accessors, 0); | ||
588 | if (!thread->addr_space) { | ||
589 | pr_err("unwind: Can't create unwind address space.\n"); | ||
590 | return -ENOMEM; | ||
591 | } | 54 | } |
55 | out_register: | ||
56 | unwind__register_ops(thread, ops); | ||
592 | 57 | ||
593 | unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL); | 58 | err = thread->unwind_libunwind_ops->prepare_access(thread); |
594 | return 0; | 59 | if (initialized) |
60 | *initialized = err ? false : true; | ||
61 | return err; | ||
595 | } | 62 | } |
596 | 63 | ||
597 | void unwind__flush_access(struct thread *thread) | 64 | void unwind__flush_access(struct thread *thread) |
598 | { | 65 | { |
599 | if (callchain_param.record_mode != CALLCHAIN_DWARF) | 66 | if (thread->unwind_libunwind_ops) |
600 | return; | 67 | thread->unwind_libunwind_ops->flush_access(thread); |
601 | |||
602 | unw_flush_cache(thread->addr_space, 0, 0); | ||
603 | } | 68 | } |
604 | 69 | ||
605 | void unwind__finish_access(struct thread *thread) | 70 | void unwind__finish_access(struct thread *thread) |
606 | { | 71 | { |
607 | if (callchain_param.record_mode != CALLCHAIN_DWARF) | 72 | if (thread->unwind_libunwind_ops) |
608 | return; | 73 | thread->unwind_libunwind_ops->finish_access(thread); |
609 | |||
610 | unw_destroy_addr_space(thread->addr_space); | ||
611 | } | ||
612 | |||
613 | static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, | ||
614 | void *arg, int max_stack) | ||
615 | { | ||
616 | u64 val; | ||
617 | unw_word_t ips[max_stack]; | ||
618 | unw_addr_space_t addr_space; | ||
619 | unw_cursor_t c; | ||
620 | int ret, i = 0; | ||
621 | |||
622 | ret = perf_reg_value(&val, &ui->sample->user_regs, PERF_REG_IP); | ||
623 | if (ret) | ||
624 | return ret; | ||
625 | |||
626 | ips[i++] = (unw_word_t) val; | ||
627 | |||
628 | /* | ||
629 | * If we need more than one entry, do the DWARF | ||
630 | * unwind itself. | ||
631 | */ | ||
632 | if (max_stack - 1 > 0) { | ||
633 | WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL"); | ||
634 | addr_space = ui->thread->addr_space; | ||
635 | |||
636 | if (addr_space == NULL) | ||
637 | return -1; | ||
638 | |||
639 | ret = unw_init_remote(&c, addr_space, ui); | ||
640 | if (ret) | ||
641 | display_error(ret); | ||
642 | |||
643 | while (!ret && (unw_step(&c) > 0) && i < max_stack) { | ||
644 | unw_get_reg(&c, UNW_REG_IP, &ips[i]); | ||
645 | ++i; | ||
646 | } | ||
647 | |||
648 | max_stack = i; | ||
649 | } | ||
650 | |||
651 | /* | ||
652 | * Display what we got based on the order setup. | ||
653 | */ | ||
654 | for (i = 0; i < max_stack && !ret; i++) { | ||
655 | int j = i; | ||
656 | |||
657 | if (callchain_param.order == ORDER_CALLER) | ||
658 | j = max_stack - i - 1; | ||
659 | ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0; | ||
660 | } | ||
661 | |||
662 | return ret; | ||
663 | } | 74 | } |
664 | 75 | ||
665 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | 76 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, |
666 | struct thread *thread, | 77 | struct thread *thread, |
667 | struct perf_sample *data, int max_stack) | 78 | struct perf_sample *data, int max_stack) |
668 | { | 79 | { |
669 | struct unwind_info ui = { | 80 | if (thread->unwind_libunwind_ops) |
670 | .sample = data, | 81 | return thread->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack); |
671 | .thread = thread, | 82 | return 0; |
672 | .machine = thread->mg->machine, | ||
673 | }; | ||
674 | |||
675 | if (!data->user_regs.regs) | ||
676 | return -EINVAL; | ||
677 | |||
678 | if (max_stack <= 0) | ||
679 | return -EINVAL; | ||
680 | |||
681 | return get_entries(&ui, cb, arg, max_stack); | ||
682 | } | 83 | } |
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index 12790cf94618..61fb1e90ff51 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h | |||
@@ -14,18 +14,42 @@ struct unwind_entry { | |||
14 | 14 | ||
15 | typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); | 15 | typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); |
16 | 16 | ||
17 | struct unwind_libunwind_ops { | ||
18 | int (*prepare_access)(struct thread *thread); | ||
19 | void (*flush_access)(struct thread *thread); | ||
20 | void (*finish_access)(struct thread *thread); | ||
21 | int (*get_entries)(unwind_entry_cb_t cb, void *arg, | ||
22 | struct thread *thread, | ||
23 | struct perf_sample *data, int max_stack); | ||
24 | }; | ||
25 | |||
17 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 26 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
18 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | 27 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, |
19 | struct thread *thread, | 28 | struct thread *thread, |
20 | struct perf_sample *data, int max_stack); | 29 | struct perf_sample *data, int max_stack); |
21 | /* libunwind specific */ | 30 | /* libunwind specific */ |
22 | #ifdef HAVE_LIBUNWIND_SUPPORT | 31 | #ifdef HAVE_LIBUNWIND_SUPPORT |
23 | int libunwind__arch_reg_id(int regnum); | 32 | #ifndef LIBUNWIND__ARCH_REG_ID |
24 | int unwind__prepare_access(struct thread *thread); | 33 | #define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arch_reg_id(regnum) |
34 | #endif | ||
35 | |||
36 | #ifndef LIBUNWIND__ARCH_REG_SP | ||
37 | #define LIBUNWIND__ARCH_REG_SP PERF_REG_SP | ||
38 | #endif | ||
39 | |||
40 | #ifndef LIBUNWIND__ARCH_REG_IP | ||
41 | #define LIBUNWIND__ARCH_REG_IP PERF_REG_IP | ||
42 | #endif | ||
43 | |||
44 | int LIBUNWIND__ARCH_REG_ID(int regnum); | ||
45 | int unwind__prepare_access(struct thread *thread, struct map *map, | ||
46 | bool *initialized); | ||
25 | void unwind__flush_access(struct thread *thread); | 47 | void unwind__flush_access(struct thread *thread); |
26 | void unwind__finish_access(struct thread *thread); | 48 | void unwind__finish_access(struct thread *thread); |
27 | #else | 49 | #else |
28 | static inline int unwind__prepare_access(struct thread *thread __maybe_unused) | 50 | static inline int unwind__prepare_access(struct thread *thread __maybe_unused, |
51 | struct map *map __maybe_unused, | ||
52 | bool *initialized __maybe_unused) | ||
29 | { | 53 | { |
30 | return 0; | 54 | return 0; |
31 | } | 55 | } |
@@ -44,7 +68,9 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, | |||
44 | return 0; | 68 | return 0; |
45 | } | 69 | } |
46 | 70 | ||
47 | static inline int unwind__prepare_access(struct thread *thread __maybe_unused) | 71 | static inline int unwind__prepare_access(struct thread *thread __maybe_unused, |
72 | struct map *map __maybe_unused, | ||
73 | bool *initialized __maybe_unused) | ||
48 | { | 74 | { |
49 | return 0; | 75 | return 0; |
50 | } | 76 | } |
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 23504ad5d6dd..cee559d8c9e8 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -19,12 +19,19 @@ | |||
19 | #include "callchain.h" | 19 | #include "callchain.h" |
20 | #include "strlist.h" | 20 | #include "strlist.h" |
21 | 21 | ||
22 | struct callchain_param callchain_param = { | 22 | #define CALLCHAIN_PARAM_DEFAULT \ |
23 | .mode = CHAIN_GRAPH_ABS, | 23 | .mode = CHAIN_GRAPH_ABS, \ |
24 | .min_percent = 0.5, | 24 | .min_percent = 0.5, \ |
25 | .order = ORDER_CALLEE, | 25 | .order = ORDER_CALLEE, \ |
26 | .key = CCKEY_FUNCTION, | 26 | .key = CCKEY_FUNCTION, \ |
27 | .value = CCVAL_PERCENT, | 27 | .value = CCVAL_PERCENT, \ |
28 | |||
29 | struct callchain_param callchain_param = { | ||
30 | CALLCHAIN_PARAM_DEFAULT | ||
31 | }; | ||
32 | |||
33 | struct callchain_param callchain_param_default = { | ||
34 | CALLCHAIN_PARAM_DEFAULT | ||
28 | }; | 35 | }; |
29 | 36 | ||
30 | /* | 37 | /* |
@@ -97,20 +104,17 @@ int rm_rf(char *path) | |||
97 | scnprintf(namebuf, sizeof(namebuf), "%s/%s", | 104 | scnprintf(namebuf, sizeof(namebuf), "%s/%s", |
98 | path, d->d_name); | 105 | path, d->d_name); |
99 | 106 | ||
100 | ret = stat(namebuf, &statbuf); | 107 | /* We have to check symbolic link itself */ |
108 | ret = lstat(namebuf, &statbuf); | ||
101 | if (ret < 0) { | 109 | if (ret < 0) { |
102 | pr_debug("stat failed: %s\n", namebuf); | 110 | pr_debug("stat failed: %s\n", namebuf); |
103 | break; | 111 | break; |
104 | } | 112 | } |
105 | 113 | ||
106 | if (S_ISREG(statbuf.st_mode)) | 114 | if (S_ISDIR(statbuf.st_mode)) |
107 | ret = unlink(namebuf); | ||
108 | else if (S_ISDIR(statbuf.st_mode)) | ||
109 | ret = rm_rf(namebuf); | 115 | ret = rm_rf(namebuf); |
110 | else { | 116 | else |
111 | pr_debug("unknown file: %s\n", namebuf); | 117 | ret = unlink(namebuf); |
112 | ret = -1; | ||
113 | } | ||
114 | } | 118 | } |
115 | closedir(dir); | 119 | closedir(dir); |
116 | 120 | ||
@@ -742,3 +746,19 @@ void print_binary(unsigned char *data, size_t len, | |||
742 | } | 746 | } |
743 | printer(BINARY_PRINT_DATA_END, -1, extra); | 747 | printer(BINARY_PRINT_DATA_END, -1, extra); |
744 | } | 748 | } |
749 | |||
750 | int is_printable_array(char *p, unsigned int len) | ||
751 | { | ||
752 | unsigned int i; | ||
753 | |||
754 | if (!p || !len || p[len - 1] != 0) | ||
755 | return 0; | ||
756 | |||
757 | len--; | ||
758 | |||
759 | for (i = 0; i < len; i++) { | ||
760 | if (!isprint(p[i]) && !isspace(p[i])) | ||
761 | return 0; | ||
762 | } | ||
763 | return 1; | ||
764 | } | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 1e8c3167b9fb..e5f55477491d 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -72,7 +72,6 @@ | |||
72 | #include <sys/ioctl.h> | 72 | #include <sys/ioctl.h> |
73 | #include <inttypes.h> | 73 | #include <inttypes.h> |
74 | #include <linux/kernel.h> | 74 | #include <linux/kernel.h> |
75 | #include <linux/magic.h> | ||
76 | #include <linux/types.h> | 75 | #include <linux/types.h> |
77 | #include <sys/ttydefaults.h> | 76 | #include <sys/ttydefaults.h> |
78 | #include <api/fs/tracing_path.h> | 77 | #include <api/fs/tracing_path.h> |
@@ -360,4 +359,10 @@ typedef void (*print_binary_t)(enum binary_printer_ops, | |||
360 | void print_binary(unsigned char *data, size_t len, | 359 | void print_binary(unsigned char *data, size_t len, |
361 | size_t bytes_per_line, print_binary_t printer, | 360 | size_t bytes_per_line, print_binary_t printer, |
362 | void *extra); | 361 | void *extra); |
362 | |||
363 | #if !defined(__GLIBC__) && !defined(__ANDROID__) | ||
364 | extern int sched_getcpu(void); | ||
365 | #endif | ||
366 | |||
367 | int is_printable_array(char *p, unsigned int len); | ||
363 | #endif /* GIT_COMPAT_UTIL_H */ | 368 | #endif /* GIT_COMPAT_UTIL_H */ |
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index 44d440da15dc..7bdcad484225 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c | |||
@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *s | |||
134 | return dso; | 134 | return dso; |
135 | } | 135 | } |
136 | 136 | ||
137 | #if BITS_PER_LONG == 64 | ||
138 | |||
139 | static enum dso_type machine__thread_dso_type(struct machine *machine, | 137 | static enum dso_type machine__thread_dso_type(struct machine *machine, |
140 | struct thread *thread) | 138 | struct thread *thread) |
141 | { | 139 | { |
@@ -156,6 +154,8 @@ static enum dso_type machine__thread_dso_type(struct machine *machine, | |||
156 | return dso_type; | 154 | return dso_type; |
157 | } | 155 | } |
158 | 156 | ||
157 | #if BITS_PER_LONG == 64 | ||
158 | |||
159 | static int vdso__do_copy_compat(FILE *f, int fd) | 159 | static int vdso__do_copy_compat(FILE *f, int fd) |
160 | { | 160 | { |
161 | char buf[4096]; | 161 | char buf[4096]; |
@@ -283,8 +283,38 @@ static int __machine__findnew_vdso_compat(struct machine *machine, | |||
283 | 283 | ||
284 | #endif | 284 | #endif |
285 | 285 | ||
286 | static struct dso *machine__find_vdso(struct machine *machine, | ||
287 | struct thread *thread) | ||
288 | { | ||
289 | struct dso *dso = NULL; | ||
290 | enum dso_type dso_type; | ||
291 | |||
292 | dso_type = machine__thread_dso_type(machine, thread); | ||
293 | switch (dso_type) { | ||
294 | case DSO__TYPE_32BIT: | ||
295 | dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO32, true); | ||
296 | if (!dso) { | ||
297 | dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, | ||
298 | true); | ||
299 | if (dso && dso_type != dso__type(dso, machine)) | ||
300 | dso = NULL; | ||
301 | } | ||
302 | break; | ||
303 | case DSO__TYPE_X32BIT: | ||
304 | dso = __dsos__find(&machine->dsos, DSO__NAME_VDSOX32, true); | ||
305 | break; | ||
306 | case DSO__TYPE_64BIT: | ||
307 | case DSO__TYPE_UNKNOWN: | ||
308 | default: | ||
309 | dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true); | ||
310 | break; | ||
311 | } | ||
312 | |||
313 | return dso; | ||
314 | } | ||
315 | |||
286 | struct dso *machine__findnew_vdso(struct machine *machine, | 316 | struct dso *machine__findnew_vdso(struct machine *machine, |
287 | struct thread *thread __maybe_unused) | 317 | struct thread *thread) |
288 | { | 318 | { |
289 | struct vdso_info *vdso_info; | 319 | struct vdso_info *vdso_info; |
290 | struct dso *dso = NULL; | 320 | struct dso *dso = NULL; |
@@ -297,6 +327,10 @@ struct dso *machine__findnew_vdso(struct machine *machine, | |||
297 | if (!vdso_info) | 327 | if (!vdso_info) |
298 | goto out_unlock; | 328 | goto out_unlock; |
299 | 329 | ||
330 | dso = machine__find_vdso(machine, thread); | ||
331 | if (dso) | ||
332 | goto out_unlock; | ||
333 | |||
300 | #if BITS_PER_LONG == 64 | 334 | #if BITS_PER_LONG == 64 |
301 | if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso)) | 335 | if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso)) |
302 | goto out_unlock; | 336 | goto out_unlock; |