diff options
Diffstat (limited to 'tools/perf')
227 files changed, 11224 insertions, 2297 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..69966abf65d1 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
| @@ -360,6 +360,35 @@ particular perf.data snapshot should be kept or not. | |||
| 360 | 360 | ||
| 361 | Implies --timestamp-filename, --no-buildid and --no-buildid-cache. | 361 | Implies --timestamp-filename, --no-buildid and --no-buildid-cache. |
| 362 | 362 | ||
| 363 | --dry-run:: | ||
| 364 | Parse options then exit. --dry-run can be used to detect errors in cmdline | ||
| 365 | options. | ||
| 366 | |||
| 367 | 'perf record --dry-run -e' can act as a BPF script compiler if llvm.dump-obj | ||
| 368 | in config file is set to true. | ||
| 369 | |||
| 370 | --tail-synthesize:: | ||
| 371 | Instead of collecting non-sample events (for example, fork, comm, mmap) at | ||
| 372 | the beginning of record, collect them during finalizing an output file. | ||
| 373 | The collected non-sample events reflects the status of the system when | ||
| 374 | record is finished. | ||
| 375 | |||
| 376 | --overwrite:: | ||
| 377 | Makes all events use an overwritable ring buffer. An overwritable ring | ||
| 378 | buffer works like a flight recorder: when it gets full, the kernel will | ||
| 379 | overwrite the oldest records, that thus will never make it to the | ||
| 380 | perf.data file. | ||
| 381 | |||
| 382 | When '--overwrite' and '--switch-output' are used perf records and drops | ||
| 383 | events until it receives a signal, meaning that something unusual was | ||
| 384 | detected that warrants taking a snapshot of the most current events, | ||
| 385 | those fitting in the ring buffer at that moment. | ||
| 386 | |||
| 387 | 'overwrite' attribute can also be set or canceled for an event using | ||
| 388 | config terms. For example: 'cycles/overwrite/' and 'instructions/no-overwrite/'. | ||
| 389 | |||
| 390 | Implies --tail-synthesize. | ||
| 391 | |||
| 363 | SEE ALSO | 392 | SEE ALSO |
| 364 | -------- | 393 | -------- |
| 365 | linkperf:perf-stat[1], linkperf:perf-list[1] | 394 | 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/Makefile.perf b/tools/perf/Makefile.perf index bde8cbae7dd9..6641abb97f0a 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 | ||
| @@ -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) |
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/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..3918dd52e903 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, "", "", |
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..9c8c61e06d5a 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, "", "", |
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..76e0ec379c8b 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"); |
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..b1d491c2e704 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" |
| @@ -1354,7 +1354,7 @@ static int __cmd_kmem(struct perf_session *session) | |||
| 1354 | goto out; | 1354 | goto out; |
| 1355 | } | 1355 | } |
| 1356 | 1356 | ||
| 1357 | evlist__for_each(session->evlist, evsel) { | 1357 | evlist__for_each_entry(session->evlist, evsel) { |
| 1358 | if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") && | 1358 | if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") && |
| 1359 | perf_evsel__field(evsel, "pfn")) { | 1359 | perf_evsel__field(evsel, "pfn")) { |
| 1360 | use_pfn = true; | 1360 | 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..8f2c16d9275f 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", |
| @@ -1386,6 +1499,8 @@ struct option __record_options[] = { | |||
| 1386 | "append timestamp to output filename"), | 1499 | "append timestamp to output filename"), |
| 1387 | OPT_BOOLEAN(0, "switch-output", &record.switch_output, | 1500 | OPT_BOOLEAN(0, "switch-output", &record.switch_output, |
| 1388 | "Switch output when receive SIGUSR2"), | 1501 | "Switch output when receive SIGUSR2"), |
| 1502 | OPT_BOOLEAN(0, "dry-run", &dry_run, | ||
| 1503 | "Parse options then exit"), | ||
| 1389 | OPT_END() | 1504 | OPT_END() |
| 1390 | }; | 1505 | }; |
| 1391 | 1506 | ||
| @@ -1455,6 +1570,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 1455 | if (err) | 1570 | if (err) |
| 1456 | return err; | 1571 | return err; |
| 1457 | 1572 | ||
| 1573 | if (dry_run) | ||
| 1574 | return 0; | ||
| 1575 | |||
| 1458 | err = bpf__setup_stdout(rec->evlist); | 1576 | err = bpf__setup_stdout(rec->evlist); |
| 1459 | if (err) { | 1577 | if (err) { |
| 1460 | bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); | 1578 | bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); |
| @@ -1508,6 +1626,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 1508 | } | 1626 | } |
| 1509 | } | 1627 | } |
| 1510 | 1628 | ||
| 1629 | if (record.opts.overwrite) | ||
| 1630 | record.opts.tail_synthesize = true; | ||
| 1631 | |||
| 1511 | if (rec->evlist->nr_entries == 0 && | 1632 | if (rec->evlist->nr_entries == 0 && |
| 1512 | perf_evlist__add_default(rec->evlist) < 0) { | 1633 | perf_evlist__add_default(rec->evlist) < 0) { |
| 1513 | pr_err("Not enough memory for event selector list\n"); | 1634 | 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..bd108683fcb8 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" |
| @@ -295,7 +295,7 @@ static void perf_top__print_sym_table(struct perf_top *top) | |||
| 295 | hists__output_recalc_col_len(hists, top->print_entries - printed); | 295 | hists__output_recalc_col_len(hists, top->print_entries - printed); |
| 296 | putchar('\n'); | 296 | putchar('\n'); |
| 297 | hists__fprintf(hists, false, top->print_entries - printed, win_width, | 297 | hists__fprintf(hists, false, top->print_entries - printed, win_width, |
| 298 | top->min_percent, stdout); | 298 | top->min_percent, stdout, symbol_conf.use_callchain); |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | static void prompt_integer(int *target, const char *msg) | 301 | static void prompt_integer(int *target, const char *msg) |
| @@ -479,7 +479,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) | |||
| 479 | 479 | ||
| 480 | fprintf(stderr, "\nAvailable events:"); | 480 | fprintf(stderr, "\nAvailable events:"); |
| 481 | 481 | ||
| 482 | evlist__for_each(top->evlist, top->sym_evsel) | 482 | 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)); | 483 | fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel)); |
| 484 | 484 | ||
| 485 | prompt_integer(&counter, "Enter details event counter"); | 485 | prompt_integer(&counter, "Enter details event counter"); |
| @@ -490,7 +490,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) | |||
| 490 | sleep(1); | 490 | sleep(1); |
| 491 | break; | 491 | break; |
| 492 | } | 492 | } |
| 493 | evlist__for_each(top->evlist, top->sym_evsel) | 493 | evlist__for_each_entry(top->evlist, top->sym_evsel) |
| 494 | if (top->sym_evsel->idx == counter) | 494 | if (top->sym_evsel->idx == counter) |
| 495 | break; | 495 | break; |
| 496 | } else | 496 | } else |
| @@ -583,7 +583,7 @@ static void *display_thread_tui(void *arg) | |||
| 583 | * Zooming in/out UIDs. For now juse use whatever the user passed | 583 | * Zooming in/out UIDs. For now juse use whatever the user passed |
| 584 | * via --uid. | 584 | * via --uid. |
| 585 | */ | 585 | */ |
| 586 | evlist__for_each(top->evlist, pos) { | 586 | evlist__for_each_entry(top->evlist, pos) { |
| 587 | struct hists *hists = evsel__hists(pos); | 587 | struct hists *hists = evsel__hists(pos); |
| 588 | hists->uid_filter_str = top->record_opts.target.uid_str; | 588 | hists->uid_filter_str = top->record_opts.target.uid_str; |
| 589 | } | 589 | } |
| @@ -888,7 +888,7 @@ static int perf_top__start_counters(struct perf_top *top) | |||
| 888 | 888 | ||
| 889 | perf_evlist__config(evlist, opts, &callchain_param); | 889 | perf_evlist__config(evlist, opts, &callchain_param); |
| 890 | 890 | ||
| 891 | evlist__for_each(evlist, counter) { | 891 | evlist__for_each_entry(evlist, counter) { |
| 892 | try_again: | 892 | try_again: |
| 893 | if (perf_evsel__open(counter, top->evlist->cpus, | 893 | if (perf_evsel__open(counter, top->evlist->cpus, |
| 894 | top->evlist->threads) < 0) { | 894 | top->evlist->threads) < 0) { |
| @@ -907,7 +907,7 @@ try_again: | |||
| 907 | 907 | ||
| 908 | if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { | 908 | if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { |
| 909 | ui__error("Failed to mmap with %d (%s)\n", | 909 | ui__error("Failed to mmap with %d (%s)\n", |
| 910 | errno, strerror_r(errno, msg, sizeof(msg))); | 910 | errno, str_error_r(errno, msg, sizeof(msg))); |
| 911 | goto out_err; | 911 | goto out_err; |
| 912 | } | 912 | } |
| 913 | 913 | ||
| @@ -1028,7 +1028,7 @@ out_delete: | |||
| 1028 | 1028 | ||
| 1029 | out_err_cpu_topo: { | 1029 | out_err_cpu_topo: { |
| 1030 | char errbuf[BUFSIZ]; | 1030 | char errbuf[BUFSIZ]; |
| 1031 | const char *err = strerror_r(-ret, errbuf, sizeof(errbuf)); | 1031 | const char *err = str_error_r(-ret, errbuf, sizeof(errbuf)); |
| 1032 | 1032 | ||
| 1033 | ui__error("Could not read the CPU topology map: %s\n", err); | 1033 | ui__error("Could not read the CPU topology map: %s\n", err); |
| 1034 | goto out_delete; | 1034 | goto out_delete; |
| @@ -1295,7 +1295,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 1295 | 1295 | ||
| 1296 | if (perf_evlist__create_maps(top.evlist, target) < 0) { | 1296 | if (perf_evlist__create_maps(top.evlist, target) < 0) { |
| 1297 | ui__error("Couldn't create thread/CPU maps: %s\n", | 1297 | ui__error("Couldn't create thread/CPU maps: %s\n", |
| 1298 | errno == ENOENT ? "No such process" : strerror_r(errno, errbuf, sizeof(errbuf))); | 1298 | errno == ENOENT ? "No such process" : str_error_r(errno, errbuf, sizeof(errbuf))); |
| 1299 | goto out_delete_evlist; | 1299 | goto out_delete_evlist; |
| 1300 | } | 1300 | } |
| 1301 | 1301 | ||
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/config/Makefile b/tools/perf/config/Makefile index 5ad0255f8756..24803c58049a 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
| @@ -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/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..a7e0f1497244 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
| @@ -59,6 +59,8 @@ struct record_opts { | |||
| 59 | bool record_switch_events; | 59 | bool record_switch_events; |
| 60 | bool all_kernel; | 60 | bool all_kernel; |
| 61 | bool all_user; | 61 | bool all_user; |
| 62 | bool tail_synthesize; | ||
| 63 | bool overwrite; | ||
| 62 | unsigned int freq; | 64 | unsigned int freq; |
| 63 | unsigned int mmap_pages; | 65 | unsigned int mmap_pages; |
| 64 | unsigned int auxtrace_mmap_pages; | 66 | 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/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/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..cb20ae1c0d35 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build | |||
| @@ -39,6 +39,8 @@ 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 | ||
| 42 | 44 | ||
| 43 | $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build | 45 | $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build |
| 44 | $(call rule_mkdir) | 46 | $(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/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c index 0ec9c2c03164..e53bc91fa260 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..10eb30686c9c 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,18 @@ 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 | { | ||
| 215 | .func = NULL, | 229 | .func = NULL, |
| 216 | }, | 230 | }, |
| 217 | }; | 231 | }; |
| @@ -247,44 +261,51 @@ static bool perf_test__matches(struct test *test, int curr, int argc, const char | |||
| 247 | 261 | ||
| 248 | static int run_test(struct test *test, int subtest) | 262 | static int run_test(struct test *test, int subtest) |
| 249 | { | 263 | { |
| 250 | int status, err = -1, child = fork(); | 264 | int status, err = -1, child = dont_fork ? 0 : fork(); |
| 251 | char sbuf[STRERR_BUFSIZE]; | 265 | char sbuf[STRERR_BUFSIZE]; |
| 252 | 266 | ||
| 253 | if (child < 0) { | 267 | if (child < 0) { |
| 254 | pr_err("failed to fork test: %s\n", | 268 | pr_err("failed to fork test: %s\n", |
| 255 | strerror_r(errno, sbuf, sizeof(sbuf))); | 269 | str_error_r(errno, sbuf, sizeof(sbuf))); |
| 256 | return -1; | 270 | return -1; |
| 257 | } | 271 | } |
| 258 | 272 | ||
| 259 | if (!child) { | 273 | if (!child) { |
| 260 | pr_debug("test child forked, pid %d\n", getpid()); | 274 | if (!dont_fork) { |
| 261 | if (!verbose) { | 275 | pr_debug("test child forked, pid %d\n", getpid()); |
| 262 | int nullfd = open("/dev/null", O_WRONLY); | 276 | |
| 263 | if (nullfd >= 0) { | 277 | if (!verbose) { |
| 264 | close(STDERR_FILENO); | 278 | int nullfd = open("/dev/null", O_WRONLY); |
| 265 | close(STDOUT_FILENO); | 279 | |
| 266 | 280 | if (nullfd >= 0) { | |
| 267 | dup2(nullfd, STDOUT_FILENO); | 281 | close(STDERR_FILENO); |
| 268 | dup2(STDOUT_FILENO, STDERR_FILENO); | 282 | close(STDOUT_FILENO); |
| 269 | close(nullfd); | 283 | |
| 284 | dup2(nullfd, STDOUT_FILENO); | ||
| 285 | dup2(STDOUT_FILENO, STDERR_FILENO); | ||
| 286 | close(nullfd); | ||
| 287 | } | ||
| 288 | } else { | ||
| 289 | signal(SIGSEGV, sighandler_dump_stack); | ||
| 290 | signal(SIGFPE, sighandler_dump_stack); | ||
| 270 | } | 291 | } |
| 271 | } else { | ||
| 272 | signal(SIGSEGV, sighandler_dump_stack); | ||
| 273 | signal(SIGFPE, sighandler_dump_stack); | ||
| 274 | } | 292 | } |
| 275 | 293 | ||
| 276 | err = test->func(subtest); | 294 | err = test->func(subtest); |
| 277 | exit(err); | 295 | if (!dont_fork) |
| 296 | exit(err); | ||
| 278 | } | 297 | } |
| 279 | 298 | ||
| 280 | wait(&status); | 299 | if (!dont_fork) { |
| 300 | wait(&status); | ||
| 281 | 301 | ||
| 282 | if (WIFEXITED(status)) { | 302 | if (WIFEXITED(status)) { |
| 283 | err = (signed char)WEXITSTATUS(status); | 303 | err = (signed char)WEXITSTATUS(status); |
| 284 | pr_debug("test child finished with %d\n", err); | 304 | pr_debug("test child finished with %d\n", err); |
| 285 | } else if (WIFSIGNALED(status)) { | 305 | } else if (WIFSIGNALED(status)) { |
| 286 | err = -1; | 306 | err = -1; |
| 287 | pr_debug("test child interrupted\n"); | 307 | pr_debug("test child interrupted\n"); |
| 308 | } | ||
| 288 | } | 309 | } |
| 289 | 310 | ||
| 290 | return err; | 311 | return err; |
| @@ -425,6 +446,8 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 425 | OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), | 446 | OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), |
| 426 | OPT_INCR('v', "verbose", &verbose, | 447 | OPT_INCR('v', "verbose", &verbose, |
| 427 | "be more verbose (show symbol address, etc)"), | 448 | "be more verbose (show symbol address, etc)"), |
| 449 | OPT_BOOLEAN('F', "dont-fork", &dont_fork, | ||
| 450 | "Do not fork for testcase"), | ||
| 428 | OPT_END() | 451 | OPT_END() |
| 429 | }; | 452 | }; |
| 430 | const char * const test_subcommands[] = { "list", NULL }; | 453 | const char * const test_subcommands[] = { "list", NULL }; |
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..9bfc0e06c61a 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
| @@ -87,6 +87,9 @@ 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); | ||
| 90 | 93 | ||
| 91 | #if defined(__arm__) || defined(__aarch64__) | 94 | #if defined(__arm__) || defined(__aarch64__) |
| 92 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 95 | #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..29dc6d20364e 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': |
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/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..2fa7d8b69873 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
| @@ -70,6 +70,7 @@ libperf-y += stat.o | |||
| 70 | libperf-y += stat-shadow.o | 70 | libperf-y += stat-shadow.o |
| 71 | libperf-y += record.o | 71 | libperf-y += record.o |
| 72 | libperf-y += srcline.o | 72 | libperf-y += srcline.o |
| 73 | libperf-y += str_error_r.o | ||
| 73 | libperf-y += data.o | 74 | libperf-y += data.o |
| 74 | libperf-y += tsc.o | 75 | libperf-y += tsc.o |
| 75 | libperf-y += cloexec.o | 76 | libperf-y += cloexec.o |
| @@ -84,6 +85,7 @@ libperf-y += parse-regs-options.o | |||
| 84 | libperf-y += term.o | 85 | libperf-y += term.o |
| 85 | libperf-y += help-unknown-cmd.o | 86 | libperf-y += help-unknown-cmd.o |
| 86 | libperf-y += mem-events.o | 87 | libperf-y += mem-events.o |
| 88 | libperf-y += vsprintf.o | ||
| 87 | 89 | ||
| 88 | libperf-$(CONFIG_LIBBPF) += bpf-loader.o | 90 | libperf-$(CONFIG_LIBBPF) += bpf-loader.o |
| 89 | libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o | 91 | libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o |
| @@ -99,7 +101,10 @@ libperf-$(CONFIG_DWARF) += probe-finder.o | |||
| 99 | libperf-$(CONFIG_DWARF) += dwarf-aux.o | 101 | libperf-$(CONFIG_DWARF) += dwarf-aux.o |
| 100 | 102 | ||
| 101 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o | 103 | libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o |
| 104 | libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o | ||
| 102 | libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o | 105 | libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o |
| 106 | libperf-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o | ||
| 107 | libperf-$(CONFIG_LIBUNWIND_AARCH64) += libunwind/arm64.o | ||
| 103 | 108 | ||
| 104 | libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o | 109 | libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o |
| 105 | 110 | ||
| @@ -108,6 +113,7 @@ libperf-y += scripting-engines/ | |||
| 108 | libperf-$(CONFIG_ZLIB) += zlib.o | 113 | libperf-$(CONFIG_ZLIB) += zlib.o |
| 109 | libperf-$(CONFIG_LZMA) += lzma.o | 114 | libperf-$(CONFIG_LZMA) += lzma.o |
| 110 | libperf-y += demangle-java.o | 115 | libperf-y += demangle-java.o |
| 116 | libperf-y += demangle-rust.o | ||
| 111 | 117 | ||
| 112 | ifdef CONFIG_JITDUMP | 118 | ifdef CONFIG_JITDUMP |
| 113 | libperf-$(CONFIG_LIBELF) += jitdump.o | 119 | libperf-$(CONFIG_LIBELF) += jitdump.o |
| @@ -170,6 +176,14 @@ $(OUTPUT)util/libstring.o: ../lib/string.c FORCE | |||
| 170 | $(call rule_mkdir) | 176 | $(call rule_mkdir) |
| 171 | $(call if_changed_dep,cc_o_c) | 177 | $(call if_changed_dep,cc_o_c) |
| 172 | 178 | ||
| 179 | $(OUTPUT)util/str_error_r.o: ../lib/str_error_r.c FORCE | ||
| 180 | $(call rule_mkdir) | ||
| 181 | $(call if_changed_dep,cc_o_c) | ||
| 182 | |||
| 173 | $(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE | 183 | $(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE |
| 174 | $(call rule_mkdir) | 184 | $(call rule_mkdir) |
| 175 | $(call if_changed_dep,cc_o_c) | 185 | $(call if_changed_dep,cc_o_c) |
| 186 | |||
| 187 | $(OUTPUT)util/vsprintf.o: ../lib/vsprintf.c FORCE | ||
| 188 | $(call rule_mkdir) | ||
| 189 | $(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..e9825fe825fd 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) |
| @@ -1512,13 +1522,14 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, | |||
| 1512 | const char *d_filename; | 1522 | const char *d_filename; |
| 1513 | const char *evsel_name = perf_evsel__name(evsel); | 1523 | const char *evsel_name = perf_evsel__name(evsel); |
| 1514 | struct annotation *notes = symbol__annotation(sym); | 1524 | struct annotation *notes = symbol__annotation(sym); |
| 1525 | struct sym_hist *h = annotation__histogram(notes, evsel->idx); | ||
| 1515 | struct disasm_line *pos, *queue = NULL; | 1526 | struct disasm_line *pos, *queue = NULL; |
| 1516 | u64 start = map__rip_2objdump(map, sym->start); | 1527 | u64 start = map__rip_2objdump(map, sym->start); |
| 1517 | int printed = 2, queue_len = 0; | 1528 | int printed = 2, queue_len = 0; |
| 1518 | int more = 0; | 1529 | int more = 0; |
| 1519 | u64 len; | 1530 | u64 len; |
| 1520 | int width = 8; | 1531 | int width = 8; |
| 1521 | int namelen, evsel_name_len, graph_dotted_len; | 1532 | int graph_dotted_len; |
| 1522 | 1533 | ||
| 1523 | filename = strdup(dso->long_name); | 1534 | filename = strdup(dso->long_name); |
| 1524 | if (!filename) | 1535 | if (!filename) |
| @@ -1530,17 +1541,14 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, | |||
| 1530 | d_filename = basename(filename); | 1541 | d_filename = basename(filename); |
| 1531 | 1542 | ||
| 1532 | len = symbol__size(sym); | 1543 | len = symbol__size(sym); |
| 1533 | namelen = strlen(d_filename); | ||
| 1534 | evsel_name_len = strlen(evsel_name); | ||
| 1535 | 1544 | ||
| 1536 | if (perf_evsel__is_group_event(evsel)) | 1545 | if (perf_evsel__is_group_event(evsel)) |
| 1537 | width *= evsel->nr_members; | 1546 | width *= evsel->nr_members; |
| 1538 | 1547 | ||
| 1539 | printf(" %-*.*s| Source code & Disassembly of %s for %s\n", | 1548 | graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", |
| 1540 | width, width, "Percent", d_filename, evsel_name); | 1549 | width, width, "Percent", d_filename, evsel_name, h->sum); |
| 1541 | 1550 | ||
| 1542 | graph_dotted_len = width + namelen + evsel_name_len; | 1551 | printf("%-*.*s----\n", |
| 1543 | printf("-%-*.*s-----------------------------------------\n", | ||
| 1544 | graph_dotted_len, graph_dotted_len, graph_dotted_line); | 1552 | graph_dotted_len, graph_dotted_len, graph_dotted_line); |
| 1545 | 1553 | ||
| 1546 | if (verbose) | 1554 | if (verbose) |
| @@ -1676,11 +1684,6 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, | |||
| 1676 | return 0; | 1684 | return 0; |
| 1677 | } | 1685 | } |
| 1678 | 1686 | ||
| 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) | 1687 | bool ui__has_annotation(void) |
| 1685 | { | 1688 | { |
| 1686 | return use_browser == 1 && perf_hpp_list.sym; | 1689 | return use_browser == 1 && perf_hpp_list.sym; |
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 9241f8c2b7e1..a23084f54128 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; |
| @@ -156,8 +157,6 @@ 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__annotate(struct symbol *sym, struct map *map, size_t privsize); |
| 158 | 159 | ||
| 159 | int hist_entry__annotate(struct hist_entry *he, size_t privsize); | ||
| 160 | |||
| 161 | int symbol__annotate_init(struct map *map, struct symbol *sym); | 160 | int symbol__annotate_init(struct map *map, struct symbol *sym); |
| 162 | int symbol__annotate_printf(struct symbol *sym, struct map *map, | 161 | int symbol__annotate_printf(struct symbol *sym, struct map *map, |
| 163 | struct perf_evsel *evsel, bool full_paths, | 162 | struct perf_evsel *evsel, bool full_paths, |
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..2a40b8e1def7 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 | } |
| @@ -296,7 +301,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist, | |||
| 296 | return 0; | 301 | return 0; |
| 297 | 302 | ||
| 298 | out_delete_partial_list: | 303 | out_delete_partial_list: |
| 299 | __evlist__for_each_safe(&head, n, evsel) | 304 | __evlist__for_each_entry_safe(&head, n, evsel) |
| 300 | perf_evsel__delete(evsel); | 305 | perf_evsel__delete(evsel); |
| 301 | return -1; | 306 | return -1; |
| 302 | } | 307 | } |
| @@ -317,7 +322,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) | |||
| 317 | { | 322 | { |
| 318 | struct perf_evsel *evsel; | 323 | struct perf_evsel *evsel; |
| 319 | 324 | ||
| 320 | evlist__for_each(evlist, evsel) { | 325 | evlist__for_each_entry(evlist, evsel) { |
| 321 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT && | 326 | if (evsel->attr.type == PERF_TYPE_TRACEPOINT && |
| 322 | (int)evsel->attr.config == id) | 327 | (int)evsel->attr.config == id) |
| 323 | return evsel; | 328 | return evsel; |
| @@ -332,7 +337,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, | |||
| 332 | { | 337 | { |
| 333 | struct perf_evsel *evsel; | 338 | struct perf_evsel *evsel; |
| 334 | 339 | ||
| 335 | evlist__for_each(evlist, evsel) { | 340 | evlist__for_each_entry(evlist, evsel) { |
| 336 | if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && | 341 | if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && |
| 337 | (strcmp(evsel->name, name) == 0)) | 342 | (strcmp(evsel->name, name) == 0)) |
| 338 | return evsel; | 343 | return evsel; |
| @@ -367,7 +372,7 @@ void perf_evlist__disable(struct perf_evlist *evlist) | |||
| 367 | { | 372 | { |
| 368 | struct perf_evsel *pos; | 373 | struct perf_evsel *pos; |
| 369 | 374 | ||
| 370 | evlist__for_each(evlist, pos) { | 375 | evlist__for_each_entry(evlist, pos) { |
| 371 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 376 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
| 372 | continue; | 377 | continue; |
| 373 | perf_evsel__disable(pos); | 378 | perf_evsel__disable(pos); |
| @@ -380,7 +385,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) | |||
| 380 | { | 385 | { |
| 381 | struct perf_evsel *pos; | 386 | struct perf_evsel *pos; |
| 382 | 387 | ||
| 383 | evlist__for_each(evlist, pos) { | 388 | evlist__for_each_entry(evlist, pos) { |
| 384 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 389 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
| 385 | continue; | 390 | continue; |
| 386 | perf_evsel__enable(pos); | 391 | perf_evsel__enable(pos); |
| @@ -448,7 +453,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) | |||
| 448 | int nfds = 0; | 453 | int nfds = 0; |
| 449 | struct perf_evsel *evsel; | 454 | struct perf_evsel *evsel; |
| 450 | 455 | ||
| 451 | evlist__for_each(evlist, evsel) { | 456 | evlist__for_each_entry(evlist, evsel) { |
| 452 | if (evsel->system_wide) | 457 | if (evsel->system_wide) |
| 453 | nfds += nr_cpus; | 458 | nfds += nr_cpus; |
| 454 | else | 459 | else |
| @@ -462,15 +467,16 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) | |||
| 462 | return 0; | 467 | return 0; |
| 463 | } | 468 | } |
| 464 | 469 | ||
| 465 | static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx) | 470 | static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, |
| 471 | struct perf_mmap *map, short revent) | ||
| 466 | { | 472 | { |
| 467 | int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP); | 473 | int pos = fdarray__add(&evlist->pollfd, fd, revent | POLLERR | POLLHUP); |
| 468 | /* | 474 | /* |
| 469 | * Save the idx so that when we filter out fds POLLHUP'ed we can | 475 | * Save the idx so that when we filter out fds POLLHUP'ed we can |
| 470 | * close the associated evlist->mmap[] entry. | 476 | * close the associated evlist->mmap[] entry. |
| 471 | */ | 477 | */ |
| 472 | if (pos >= 0) { | 478 | if (pos >= 0) { |
| 473 | evlist->pollfd.priv[pos].idx = idx; | 479 | evlist->pollfd.priv[pos].ptr = map; |
| 474 | 480 | ||
| 475 | fcntl(fd, F_SETFL, O_NONBLOCK); | 481 | fcntl(fd, F_SETFL, O_NONBLOCK); |
| 476 | } | 482 | } |
| @@ -480,20 +486,22 @@ static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx | |||
| 480 | 486 | ||
| 481 | int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) | 487 | int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) |
| 482 | { | 488 | { |
| 483 | return __perf_evlist__add_pollfd(evlist, fd, -1); | 489 | return __perf_evlist__add_pollfd(evlist, fd, NULL, POLLIN); |
| 484 | } | 490 | } |
| 485 | 491 | ||
| 486 | static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd) | 492 | static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd, |
| 493 | void *arg __maybe_unused) | ||
| 487 | { | 494 | { |
| 488 | struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd); | 495 | struct perf_mmap *map = fda->priv[fd].ptr; |
| 489 | 496 | ||
| 490 | perf_evlist__mmap_put(evlist, fda->priv[fd].idx); | 497 | if (map) |
| 498 | perf_mmap__put(map); | ||
| 491 | } | 499 | } |
| 492 | 500 | ||
| 493 | int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) | 501 | int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) |
| 494 | { | 502 | { |
| 495 | return fdarray__filter(&evlist->pollfd, revents_and_mask, | 503 | return fdarray__filter(&evlist->pollfd, revents_and_mask, |
| 496 | perf_evlist__munmap_filtered); | 504 | perf_evlist__munmap_filtered, NULL); |
| 497 | } | 505 | } |
| 498 | 506 | ||
| 499 | int perf_evlist__poll(struct perf_evlist *evlist, int timeout) | 507 | int perf_evlist__poll(struct perf_evlist *evlist, int timeout) |
| @@ -647,8 +655,8 @@ static int perf_evlist__event2id(struct perf_evlist *evlist, | |||
| 647 | return 0; | 655 | return 0; |
| 648 | } | 656 | } |
| 649 | 657 | ||
| 650 | static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, | 658 | struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, |
| 651 | union perf_event *event) | 659 | union perf_event *event) |
| 652 | { | 660 | { |
| 653 | struct perf_evsel *first = perf_evlist__first(evlist); | 661 | struct perf_evsel *first = perf_evlist__first(evlist); |
| 654 | struct hlist_head *head; | 662 | struct hlist_head *head; |
| @@ -684,8 +692,11 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value) | |||
| 684 | { | 692 | { |
| 685 | int i; | 693 | int i; |
| 686 | 694 | ||
| 695 | if (!evlist->backward_mmap) | ||
| 696 | return 0; | ||
| 697 | |||
| 687 | for (i = 0; i < evlist->nr_mmaps; i++) { | 698 | for (i = 0; i < evlist->nr_mmaps; i++) { |
| 688 | int fd = evlist->mmap[i].fd; | 699 | int fd = evlist->backward_mmap[i].fd; |
| 689 | int err; | 700 | int err; |
| 690 | 701 | ||
| 691 | if (fd < 0) | 702 | if (fd < 0) |
| @@ -697,12 +708,12 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value) | |||
| 697 | return 0; | 708 | return 0; |
| 698 | } | 709 | } |
| 699 | 710 | ||
| 700 | int perf_evlist__pause(struct perf_evlist *evlist) | 711 | static int perf_evlist__pause(struct perf_evlist *evlist) |
| 701 | { | 712 | { |
| 702 | return perf_evlist__set_paused(evlist, true); | 713 | return perf_evlist__set_paused(evlist, true); |
| 703 | } | 714 | } |
| 704 | 715 | ||
| 705 | int perf_evlist__resume(struct perf_evlist *evlist) | 716 | static int perf_evlist__resume(struct perf_evlist *evlist) |
| 706 | { | 717 | { |
| 707 | return perf_evlist__set_paused(evlist, false); | 718 | return perf_evlist__set_paused(evlist, false); |
| 708 | } | 719 | } |
| @@ -777,9 +788,8 @@ broken_event: | |||
| 777 | return event; | 788 | return event; |
| 778 | } | 789 | } |
| 779 | 790 | ||
| 780 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | 791 | union perf_event *perf_mmap__read_forward(struct perf_mmap *md, bool check_messup) |
| 781 | { | 792 | { |
| 782 | struct perf_mmap *md = &evlist->mmap[idx]; | ||
| 783 | u64 head; | 793 | u64 head; |
| 784 | u64 old = md->prev; | 794 | u64 old = md->prev; |
| 785 | 795 | ||
| @@ -791,13 +801,12 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | |||
| 791 | 801 | ||
| 792 | head = perf_mmap__read_head(md); | 802 | head = perf_mmap__read_head(md); |
| 793 | 803 | ||
| 794 | return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev); | 804 | return perf_mmap__read(md, check_messup, old, head, &md->prev); |
| 795 | } | 805 | } |
| 796 | 806 | ||
| 797 | union perf_event * | 807 | union perf_event * |
| 798 | perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx) | 808 | perf_mmap__read_backward(struct perf_mmap *md) |
| 799 | { | 809 | { |
| 800 | struct perf_mmap *md = &evlist->mmap[idx]; | ||
| 801 | u64 head, end; | 810 | u64 head, end; |
| 802 | u64 start = md->prev; | 811 | u64 start = md->prev; |
| 803 | 812 | ||
| @@ -832,9 +841,38 @@ perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx) | |||
| 832 | return perf_mmap__read(md, false, start, end, &md->prev); | 841 | return perf_mmap__read(md, false, start, end, &md->prev); |
| 833 | } | 842 | } |
| 834 | 843 | ||
| 835 | void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) | 844 | union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx) |
| 845 | { | ||
| 846 | struct perf_mmap *md = &evlist->mmap[idx]; | ||
| 847 | |||
| 848 | /* | ||
| 849 | * Check messup is required for forward overwritable ring buffer: | ||
| 850 | * memory pointed by md->prev can be overwritten in this case. | ||
| 851 | * No need for read-write ring buffer: kernel stop outputting when | ||
| 852 | * it hit md->prev (perf_mmap__consume()). | ||
| 853 | */ | ||
| 854 | return perf_mmap__read_forward(md, evlist->overwrite); | ||
| 855 | } | ||
| 856 | |||
| 857 | union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx) | ||
| 836 | { | 858 | { |
| 837 | struct perf_mmap *md = &evlist->mmap[idx]; | 859 | struct perf_mmap *md = &evlist->mmap[idx]; |
| 860 | |||
| 861 | /* | ||
| 862 | * No need to check messup for backward ring buffer: | ||
| 863 | * We can always read arbitrary long data from a backward | ||
| 864 | * ring buffer unless we forget to pause it before reading. | ||
| 865 | */ | ||
| 866 | return perf_mmap__read_backward(md); | ||
| 867 | } | ||
| 868 | |||
| 869 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | ||
| 870 | { | ||
| 871 | return perf_evlist__mmap_read_forward(evlist, idx); | ||
| 872 | } | ||
| 873 | |||
| 874 | void perf_mmap__read_catchup(struct perf_mmap *md) | ||
| 875 | { | ||
| 838 | u64 head; | 876 | u64 head; |
| 839 | 877 | ||
| 840 | if (!atomic_read(&md->refcnt)) | 878 | if (!atomic_read(&md->refcnt)) |
| @@ -844,36 +882,44 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) | |||
| 844 | md->prev = head; | 882 | md->prev = head; |
| 845 | } | 883 | } |
| 846 | 884 | ||
| 885 | void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) | ||
| 886 | { | ||
| 887 | perf_mmap__read_catchup(&evlist->mmap[idx]); | ||
| 888 | } | ||
| 889 | |||
| 847 | static bool perf_mmap__empty(struct perf_mmap *md) | 890 | static bool perf_mmap__empty(struct perf_mmap *md) |
| 848 | { | 891 | { |
| 849 | return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; | 892 | return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; |
| 850 | } | 893 | } |
| 851 | 894 | ||
| 852 | static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) | 895 | static void perf_mmap__get(struct perf_mmap *map) |
| 853 | { | 896 | { |
| 854 | atomic_inc(&evlist->mmap[idx].refcnt); | 897 | atomic_inc(&map->refcnt); |
| 855 | } | 898 | } |
| 856 | 899 | ||
| 857 | static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx) | 900 | static void perf_mmap__put(struct perf_mmap *md) |
| 858 | { | 901 | { |
| 859 | BUG_ON(atomic_read(&evlist->mmap[idx].refcnt) == 0); | 902 | BUG_ON(md->base && atomic_read(&md->refcnt) == 0); |
| 860 | 903 | ||
| 861 | if (atomic_dec_and_test(&evlist->mmap[idx].refcnt)) | 904 | if (atomic_dec_and_test(&md->refcnt)) |
| 862 | __perf_evlist__munmap(evlist, idx); | 905 | perf_mmap__munmap(md); |
| 863 | } | 906 | } |
| 864 | 907 | ||
| 865 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) | 908 | void perf_mmap__consume(struct perf_mmap *md, bool overwrite) |
| 866 | { | 909 | { |
| 867 | struct perf_mmap *md = &evlist->mmap[idx]; | 910 | if (!overwrite) { |
| 868 | |||
| 869 | if (!evlist->overwrite) { | ||
| 870 | u64 old = md->prev; | 911 | u64 old = md->prev; |
| 871 | 912 | ||
| 872 | perf_mmap__write_tail(md, old); | 913 | perf_mmap__write_tail(md, old); |
| 873 | } | 914 | } |
| 874 | 915 | ||
| 875 | if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md)) | 916 | if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md)) |
| 876 | perf_evlist__mmap_put(evlist, idx); | 917 | perf_mmap__put(md); |
| 918 | } | ||
| 919 | |||
| 920 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) | ||
| 921 | { | ||
| 922 | perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite); | ||
| 877 | } | 923 | } |
| 878 | 924 | ||
| 879 | int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused, | 925 | int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused, |
| @@ -904,41 +950,52 @@ void __weak auxtrace_mmap_params__set_idx( | |||
| 904 | { | 950 | { |
| 905 | } | 951 | } |
| 906 | 952 | ||
| 907 | static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) | 953 | static void perf_mmap__munmap(struct perf_mmap *map) |
| 908 | { | 954 | { |
| 909 | if (evlist->mmap[idx].base != NULL) { | 955 | if (map->base != NULL) { |
| 910 | munmap(evlist->mmap[idx].base, evlist->mmap_len); | 956 | munmap(map->base, perf_mmap__mmap_len(map)); |
| 911 | evlist->mmap[idx].base = NULL; | 957 | map->base = NULL; |
| 912 | evlist->mmap[idx].fd = -1; | 958 | map->fd = -1; |
| 913 | atomic_set(&evlist->mmap[idx].refcnt, 0); | 959 | atomic_set(&map->refcnt, 0); |
| 914 | } | 960 | } |
| 915 | auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); | 961 | auxtrace_mmap__munmap(&map->auxtrace_mmap); |
| 916 | } | 962 | } |
| 917 | 963 | ||
| 918 | void perf_evlist__munmap(struct perf_evlist *evlist) | 964 | static void perf_evlist__munmap_nofree(struct perf_evlist *evlist) |
| 919 | { | 965 | { |
| 920 | int i; | 966 | int i; |
| 921 | 967 | ||
| 922 | if (evlist->mmap == NULL) | 968 | if (evlist->mmap) |
| 923 | return; | 969 | for (i = 0; i < evlist->nr_mmaps; i++) |
| 970 | perf_mmap__munmap(&evlist->mmap[i]); | ||
| 924 | 971 | ||
| 925 | for (i = 0; i < evlist->nr_mmaps; i++) | 972 | if (evlist->backward_mmap) |
| 926 | __perf_evlist__munmap(evlist, i); | 973 | for (i = 0; i < evlist->nr_mmaps; i++) |
| 974 | perf_mmap__munmap(&evlist->backward_mmap[i]); | ||
| 975 | } | ||
| 927 | 976 | ||
| 977 | void perf_evlist__munmap(struct perf_evlist *evlist) | ||
| 978 | { | ||
| 979 | perf_evlist__munmap_nofree(evlist); | ||
| 928 | zfree(&evlist->mmap); | 980 | zfree(&evlist->mmap); |
| 981 | zfree(&evlist->backward_mmap); | ||
| 929 | } | 982 | } |
| 930 | 983 | ||
| 931 | static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | 984 | static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist) |
| 932 | { | 985 | { |
| 933 | int i; | 986 | int i; |
| 987 | struct perf_mmap *map; | ||
| 934 | 988 | ||
| 935 | evlist->nr_mmaps = cpu_map__nr(evlist->cpus); | 989 | evlist->nr_mmaps = cpu_map__nr(evlist->cpus); |
| 936 | if (cpu_map__empty(evlist->cpus)) | 990 | if (cpu_map__empty(evlist->cpus)) |
| 937 | evlist->nr_mmaps = thread_map__nr(evlist->threads); | 991 | evlist->nr_mmaps = thread_map__nr(evlist->threads); |
| 938 | evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); | 992 | map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); |
| 993 | if (!map) | ||
| 994 | return NULL; | ||
| 995 | |||
| 939 | for (i = 0; i < evlist->nr_mmaps; i++) | 996 | for (i = 0; i < evlist->nr_mmaps; i++) |
| 940 | evlist->mmap[i].fd = -1; | 997 | map[i].fd = -1; |
| 941 | return evlist->mmap != NULL ? 0 : -ENOMEM; | 998 | return map; |
| 942 | } | 999 | } |
| 943 | 1000 | ||
| 944 | struct mmap_params { | 1001 | struct mmap_params { |
| @@ -947,8 +1004,8 @@ struct mmap_params { | |||
| 947 | struct auxtrace_mmap_params auxtrace_mp; | 1004 | struct auxtrace_mmap_params auxtrace_mp; |
| 948 | }; | 1005 | }; |
| 949 | 1006 | ||
| 950 | static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, | 1007 | static int perf_mmap__mmap(struct perf_mmap *map, |
| 951 | struct mmap_params *mp, int fd) | 1008 | struct mmap_params *mp, int fd) |
| 952 | { | 1009 | { |
| 953 | /* | 1010 | /* |
| 954 | * The last one will be done at perf_evlist__mmap_consume(), so that we | 1011 | * The last one will be done at perf_evlist__mmap_consume(), so that we |
| @@ -963,35 +1020,61 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, | |||
| 963 | * evlist layer can't just drop it when filtering events in | 1020 | * evlist layer can't just drop it when filtering events in |
| 964 | * perf_evlist__filter_pollfd(). | 1021 | * perf_evlist__filter_pollfd(). |
| 965 | */ | 1022 | */ |
| 966 | atomic_set(&evlist->mmap[idx].refcnt, 2); | 1023 | atomic_set(&map->refcnt, 2); |
| 967 | evlist->mmap[idx].prev = 0; | 1024 | map->prev = 0; |
| 968 | evlist->mmap[idx].mask = mp->mask; | 1025 | map->mask = mp->mask; |
| 969 | evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, | 1026 | map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot, |
| 970 | MAP_SHARED, fd, 0); | 1027 | MAP_SHARED, fd, 0); |
| 971 | if (evlist->mmap[idx].base == MAP_FAILED) { | 1028 | if (map->base == MAP_FAILED) { |
| 972 | pr_debug2("failed to mmap perf event ring buffer, error %d\n", | 1029 | pr_debug2("failed to mmap perf event ring buffer, error %d\n", |
| 973 | errno); | 1030 | errno); |
| 974 | evlist->mmap[idx].base = NULL; | 1031 | map->base = NULL; |
| 975 | return -1; | 1032 | return -1; |
| 976 | } | 1033 | } |
| 977 | evlist->mmap[idx].fd = fd; | 1034 | map->fd = fd; |
| 978 | 1035 | ||
| 979 | if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, | 1036 | if (auxtrace_mmap__mmap(&map->auxtrace_mmap, |
| 980 | &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) | 1037 | &mp->auxtrace_mp, map->base, fd)) |
| 981 | return -1; | 1038 | return -1; |
| 982 | 1039 | ||
| 983 | return 0; | 1040 | return 0; |
| 984 | } | 1041 | } |
| 985 | 1042 | ||
| 1043 | static bool | ||
| 1044 | perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused, | ||
| 1045 | struct perf_evsel *evsel) | ||
| 1046 | { | ||
| 1047 | if (evsel->attr.write_backward) | ||
| 1048 | return false; | ||
| 1049 | return true; | ||
| 1050 | } | ||
| 1051 | |||
| 986 | static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | 1052 | static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, |
| 987 | struct mmap_params *mp, int cpu, | 1053 | struct mmap_params *mp, int cpu, |
| 988 | int thread, int *output) | 1054 | int thread, int *_output, int *_output_backward) |
| 989 | { | 1055 | { |
| 990 | struct perf_evsel *evsel; | 1056 | struct perf_evsel *evsel; |
| 1057 | int revent; | ||
| 991 | 1058 | ||
| 992 | evlist__for_each(evlist, evsel) { | 1059 | evlist__for_each_entry(evlist, evsel) { |
| 1060 | struct perf_mmap *maps = evlist->mmap; | ||
| 1061 | int *output = _output; | ||
| 993 | int fd; | 1062 | int fd; |
| 994 | 1063 | ||
| 1064 | if (evsel->attr.write_backward) { | ||
| 1065 | output = _output_backward; | ||
| 1066 | maps = evlist->backward_mmap; | ||
| 1067 | |||
| 1068 | if (!maps) { | ||
| 1069 | maps = perf_evlist__alloc_mmap(evlist); | ||
| 1070 | if (!maps) | ||
| 1071 | return -1; | ||
| 1072 | evlist->backward_mmap = maps; | ||
| 1073 | if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY) | ||
| 1074 | perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING); | ||
| 1075 | } | ||
| 1076 | } | ||
| 1077 | |||
| 995 | if (evsel->system_wide && thread) | 1078 | if (evsel->system_wide && thread) |
| 996 | continue; | 1079 | continue; |
| 997 | 1080 | ||
| @@ -999,15 +1082,18 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
| 999 | 1082 | ||
| 1000 | if (*output == -1) { | 1083 | if (*output == -1) { |
| 1001 | *output = fd; | 1084 | *output = fd; |
| 1002 | if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0) | 1085 | |
| 1086 | if (perf_mmap__mmap(&maps[idx], mp, *output) < 0) | ||
| 1003 | return -1; | 1087 | return -1; |
| 1004 | } else { | 1088 | } else { |
| 1005 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) | 1089 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) |
| 1006 | return -1; | 1090 | return -1; |
| 1007 | 1091 | ||
| 1008 | perf_evlist__mmap_get(evlist, idx); | 1092 | perf_mmap__get(&maps[idx]); |
| 1009 | } | 1093 | } |
| 1010 | 1094 | ||
| 1095 | revent = perf_evlist__should_poll(evlist, evsel) ? POLLIN : 0; | ||
| 1096 | |||
| 1011 | /* | 1097 | /* |
| 1012 | * The system_wide flag causes a selected event to be opened | 1098 | * The system_wide flag causes a selected event to be opened |
| 1013 | * always without a pid. Consequently it will never get a | 1099 | * always without a pid. Consequently it will never get a |
| @@ -1016,8 +1102,8 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
| 1016 | * Therefore don't add it for polling. | 1102 | * Therefore don't add it for polling. |
| 1017 | */ | 1103 | */ |
| 1018 | if (!evsel->system_wide && | 1104 | if (!evsel->system_wide && |
| 1019 | __perf_evlist__add_pollfd(evlist, fd, idx) < 0) { | 1105 | __perf_evlist__add_pollfd(evlist, fd, &maps[idx], revent) < 0) { |
| 1020 | perf_evlist__mmap_put(evlist, idx); | 1106 | perf_mmap__put(&maps[idx]); |
| 1021 | return -1; | 1107 | return -1; |
| 1022 | } | 1108 | } |
| 1023 | 1109 | ||
| @@ -1043,13 +1129,14 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, | |||
| 1043 | pr_debug2("perf event ring buffer mmapped per cpu\n"); | 1129 | pr_debug2("perf event ring buffer mmapped per cpu\n"); |
| 1044 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 1130 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
| 1045 | int output = -1; | 1131 | int output = -1; |
| 1132 | int output_backward = -1; | ||
| 1046 | 1133 | ||
| 1047 | auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu, | 1134 | auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu, |
| 1048 | true); | 1135 | true); |
| 1049 | 1136 | ||
| 1050 | for (thread = 0; thread < nr_threads; thread++) { | 1137 | for (thread = 0; thread < nr_threads; thread++) { |
| 1051 | if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, | 1138 | if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, |
| 1052 | thread, &output)) | 1139 | thread, &output, &output_backward)) |
| 1053 | goto out_unmap; | 1140 | goto out_unmap; |
| 1054 | } | 1141 | } |
| 1055 | } | 1142 | } |
| @@ -1057,8 +1144,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, | |||
| 1057 | return 0; | 1144 | return 0; |
| 1058 | 1145 | ||
| 1059 | out_unmap: | 1146 | out_unmap: |
| 1060 | for (cpu = 0; cpu < nr_cpus; cpu++) | 1147 | perf_evlist__munmap_nofree(evlist); |
| 1061 | __perf_evlist__munmap(evlist, cpu); | ||
| 1062 | return -1; | 1148 | return -1; |
| 1063 | } | 1149 | } |
| 1064 | 1150 | ||
| @@ -1071,20 +1157,20 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, | |||
| 1071 | pr_debug2("perf event ring buffer mmapped per thread\n"); | 1157 | pr_debug2("perf event ring buffer mmapped per thread\n"); |
| 1072 | for (thread = 0; thread < nr_threads; thread++) { | 1158 | for (thread = 0; thread < nr_threads; thread++) { |
| 1073 | int output = -1; | 1159 | int output = -1; |
| 1160 | int output_backward = -1; | ||
| 1074 | 1161 | ||
| 1075 | auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread, | 1162 | auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread, |
| 1076 | false); | 1163 | false); |
| 1077 | 1164 | ||
| 1078 | if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, | 1165 | if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, |
| 1079 | &output)) | 1166 | &output, &output_backward)) |
| 1080 | goto out_unmap; | 1167 | goto out_unmap; |
| 1081 | } | 1168 | } |
| 1082 | 1169 | ||
| 1083 | return 0; | 1170 | return 0; |
| 1084 | 1171 | ||
| 1085 | out_unmap: | 1172 | out_unmap: |
| 1086 | for (thread = 0; thread < nr_threads; thread++) | 1173 | perf_evlist__munmap_nofree(evlist); |
| 1087 | __perf_evlist__munmap(evlist, thread); | ||
| 1088 | return -1; | 1174 | return -1; |
| 1089 | } | 1175 | } |
| 1090 | 1176 | ||
| @@ -1217,7 +1303,9 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, | |||
| 1217 | .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), | 1303 | .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), |
| 1218 | }; | 1304 | }; |
| 1219 | 1305 | ||
| 1220 | if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) | 1306 | if (!evlist->mmap) |
| 1307 | evlist->mmap = perf_evlist__alloc_mmap(evlist); | ||
| 1308 | if (!evlist->mmap) | ||
| 1221 | return -ENOMEM; | 1309 | return -ENOMEM; |
| 1222 | 1310 | ||
| 1223 | if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) | 1311 | if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) |
| @@ -1231,7 +1319,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, | |||
| 1231 | auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len, | 1319 | auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len, |
| 1232 | auxtrace_pages, auxtrace_overwrite); | 1320 | auxtrace_pages, auxtrace_overwrite); |
| 1233 | 1321 | ||
| 1234 | evlist__for_each(evlist, evsel) { | 1322 | evlist__for_each_entry(evlist, evsel) { |
| 1235 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | 1323 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
| 1236 | evsel->sample_id == NULL && | 1324 | evsel->sample_id == NULL && |
| 1237 | perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) | 1325 | perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) |
| @@ -1307,7 +1395,7 @@ void __perf_evlist__set_sample_bit(struct perf_evlist *evlist, | |||
| 1307 | { | 1395 | { |
| 1308 | struct perf_evsel *evsel; | 1396 | struct perf_evsel *evsel; |
| 1309 | 1397 | ||
| 1310 | evlist__for_each(evlist, evsel) | 1398 | evlist__for_each_entry(evlist, evsel) |
| 1311 | __perf_evsel__set_sample_bit(evsel, bit); | 1399 | __perf_evsel__set_sample_bit(evsel, bit); |
| 1312 | } | 1400 | } |
| 1313 | 1401 | ||
| @@ -1316,7 +1404,7 @@ void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist, | |||
| 1316 | { | 1404 | { |
| 1317 | struct perf_evsel *evsel; | 1405 | struct perf_evsel *evsel; |
| 1318 | 1406 | ||
| 1319 | evlist__for_each(evlist, evsel) | 1407 | evlist__for_each_entry(evlist, evsel) |
| 1320 | __perf_evsel__reset_sample_bit(evsel, bit); | 1408 | __perf_evsel__reset_sample_bit(evsel, bit); |
| 1321 | } | 1409 | } |
| 1322 | 1410 | ||
| @@ -1327,7 +1415,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e | |||
| 1327 | const int ncpus = cpu_map__nr(evlist->cpus), | 1415 | const int ncpus = cpu_map__nr(evlist->cpus), |
| 1328 | nthreads = thread_map__nr(evlist->threads); | 1416 | nthreads = thread_map__nr(evlist->threads); |
| 1329 | 1417 | ||
| 1330 | evlist__for_each(evlist, evsel) { | 1418 | evlist__for_each_entry(evlist, evsel) { |
| 1331 | if (evsel->filter == NULL) | 1419 | if (evsel->filter == NULL) |
| 1332 | continue; | 1420 | continue; |
| 1333 | 1421 | ||
| @@ -1350,7 +1438,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) | |||
| 1350 | struct perf_evsel *evsel; | 1438 | struct perf_evsel *evsel; |
| 1351 | int err = 0; | 1439 | int err = 0; |
| 1352 | 1440 | ||
| 1353 | evlist__for_each(evlist, evsel) { | 1441 | evlist__for_each_entry(evlist, evsel) { |
| 1354 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) | 1442 | if (evsel->attr.type != PERF_TYPE_TRACEPOINT) |
| 1355 | continue; | 1443 | continue; |
| 1356 | 1444 | ||
| @@ -1404,7 +1492,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) | |||
| 1404 | if (evlist->id_pos < 0 || evlist->is_pos < 0) | 1492 | if (evlist->id_pos < 0 || evlist->is_pos < 0) |
| 1405 | return false; | 1493 | return false; |
| 1406 | 1494 | ||
| 1407 | evlist__for_each(evlist, pos) { | 1495 | evlist__for_each_entry(evlist, pos) { |
| 1408 | if (pos->id_pos != evlist->id_pos || | 1496 | if (pos->id_pos != evlist->id_pos || |
| 1409 | pos->is_pos != evlist->is_pos) | 1497 | pos->is_pos != evlist->is_pos) |
| 1410 | return false; | 1498 | return false; |
| @@ -1420,7 +1508,7 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist) | |||
| 1420 | if (evlist->combined_sample_type) | 1508 | if (evlist->combined_sample_type) |
| 1421 | return evlist->combined_sample_type; | 1509 | return evlist->combined_sample_type; |
| 1422 | 1510 | ||
| 1423 | evlist__for_each(evlist, evsel) | 1511 | evlist__for_each_entry(evlist, evsel) |
| 1424 | evlist->combined_sample_type |= evsel->attr.sample_type; | 1512 | evlist->combined_sample_type |= evsel->attr.sample_type; |
| 1425 | 1513 | ||
| 1426 | return evlist->combined_sample_type; | 1514 | return evlist->combined_sample_type; |
| @@ -1437,7 +1525,7 @@ u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist) | |||
| 1437 | struct perf_evsel *evsel; | 1525 | struct perf_evsel *evsel; |
| 1438 | u64 branch_type = 0; | 1526 | u64 branch_type = 0; |
| 1439 | 1527 | ||
| 1440 | evlist__for_each(evlist, evsel) | 1528 | evlist__for_each_entry(evlist, evsel) |
| 1441 | branch_type |= evsel->attr.branch_sample_type; | 1529 | branch_type |= evsel->attr.branch_sample_type; |
| 1442 | return branch_type; | 1530 | return branch_type; |
| 1443 | } | 1531 | } |
| @@ -1448,7 +1536,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist) | |||
| 1448 | u64 read_format = first->attr.read_format; | 1536 | u64 read_format = first->attr.read_format; |
| 1449 | u64 sample_type = first->attr.sample_type; | 1537 | u64 sample_type = first->attr.sample_type; |
| 1450 | 1538 | ||
| 1451 | evlist__for_each(evlist, pos) { | 1539 | evlist__for_each_entry(evlist, pos) { |
| 1452 | if (read_format != pos->attr.read_format) | 1540 | if (read_format != pos->attr.read_format) |
| 1453 | return false; | 1541 | return false; |
| 1454 | } | 1542 | } |
| @@ -1505,7 +1593,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist) | |||
| 1505 | { | 1593 | { |
| 1506 | struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; | 1594 | struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; |
| 1507 | 1595 | ||
| 1508 | evlist__for_each_continue(evlist, pos) { | 1596 | evlist__for_each_entry_continue(evlist, pos) { |
| 1509 | if (first->attr.sample_id_all != pos->attr.sample_id_all) | 1597 | if (first->attr.sample_id_all != pos->attr.sample_id_all) |
| 1510 | return false; | 1598 | return false; |
| 1511 | } | 1599 | } |
| @@ -1532,7 +1620,7 @@ void perf_evlist__close(struct perf_evlist *evlist) | |||
| 1532 | int nthreads = thread_map__nr(evlist->threads); | 1620 | int nthreads = thread_map__nr(evlist->threads); |
| 1533 | int n; | 1621 | int n; |
| 1534 | 1622 | ||
| 1535 | evlist__for_each_reverse(evlist, evsel) { | 1623 | evlist__for_each_entry_reverse(evlist, evsel) { |
| 1536 | n = evsel->cpus ? evsel->cpus->nr : ncpus; | 1624 | n = evsel->cpus ? evsel->cpus->nr : ncpus; |
| 1537 | perf_evsel__close(evsel, n, nthreads); | 1625 | perf_evsel__close(evsel, n, nthreads); |
| 1538 | } | 1626 | } |
| @@ -1586,7 +1674,7 @@ int perf_evlist__open(struct perf_evlist *evlist) | |||
| 1586 | 1674 | ||
| 1587 | perf_evlist__update_id_pos(evlist); | 1675 | perf_evlist__update_id_pos(evlist); |
| 1588 | 1676 | ||
| 1589 | evlist__for_each(evlist, evsel) { | 1677 | evlist__for_each_entry(evlist, evsel) { |
| 1590 | err = perf_evsel__open(evsel, evsel->cpus, evsel->threads); | 1678 | err = perf_evsel__open(evsel, evsel->cpus, evsel->threads); |
| 1591 | if (err < 0) | 1679 | if (err < 0) |
| 1592 | goto out_err; | 1680 | goto out_err; |
| @@ -1747,7 +1835,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp) | |||
| 1747 | struct perf_evsel *evsel; | 1835 | struct perf_evsel *evsel; |
| 1748 | size_t printed = 0; | 1836 | size_t printed = 0; |
| 1749 | 1837 | ||
| 1750 | evlist__for_each(evlist, evsel) { | 1838 | evlist__for_each_entry(evlist, evsel) { |
| 1751 | printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", | 1839 | printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", |
| 1752 | perf_evsel__name(evsel)); | 1840 | perf_evsel__name(evsel)); |
| 1753 | } | 1841 | } |
| @@ -1759,7 +1847,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist, | |||
| 1759 | int err, char *buf, size_t size) | 1847 | int err, char *buf, size_t size) |
| 1760 | { | 1848 | { |
| 1761 | int printed, value; | 1849 | int printed, value; |
| 1762 | char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); | 1850 | char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf)); |
| 1763 | 1851 | ||
| 1764 | switch (err) { | 1852 | switch (err) { |
| 1765 | case EACCES: | 1853 | case EACCES: |
| @@ -1811,7 +1899,7 @@ out_default: | |||
| 1811 | 1899 | ||
| 1812 | int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) | 1900 | int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) |
| 1813 | { | 1901 | { |
| 1814 | char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); | 1902 | 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; | 1903 | int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0; |
| 1816 | 1904 | ||
| 1817 | switch (err) { | 1905 | switch (err) { |
| @@ -1849,7 +1937,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist, | |||
| 1849 | if (move_evsel == perf_evlist__first(evlist)) | 1937 | if (move_evsel == perf_evlist__first(evlist)) |
| 1850 | return; | 1938 | return; |
| 1851 | 1939 | ||
| 1852 | evlist__for_each_safe(evlist, n, evsel) { | 1940 | evlist__for_each_entry_safe(evlist, n, evsel) { |
| 1853 | if (evsel->leader == move_evsel->leader) | 1941 | if (evsel->leader == move_evsel->leader) |
| 1854 | list_move_tail(&evsel->node, &move); | 1942 | list_move_tail(&evsel->node, &move); |
| 1855 | } | 1943 | } |
| @@ -1865,7 +1953,7 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist, | |||
| 1865 | if (tracking_evsel->tracking) | 1953 | if (tracking_evsel->tracking) |
| 1866 | return; | 1954 | return; |
| 1867 | 1955 | ||
| 1868 | evlist__for_each(evlist, evsel) { | 1956 | evlist__for_each_entry(evlist, evsel) { |
| 1869 | if (evsel != tracking_evsel) | 1957 | if (evsel != tracking_evsel) |
| 1870 | evsel->tracking = false; | 1958 | evsel->tracking = false; |
| 1871 | } | 1959 | } |
| @@ -1879,7 +1967,7 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, | |||
| 1879 | { | 1967 | { |
| 1880 | struct perf_evsel *evsel; | 1968 | struct perf_evsel *evsel; |
| 1881 | 1969 | ||
| 1882 | evlist__for_each(evlist, evsel) { | 1970 | evlist__for_each_entry(evlist, evsel) { |
| 1883 | if (!evsel->name) | 1971 | if (!evsel->name) |
| 1884 | continue; | 1972 | continue; |
| 1885 | if (strcmp(str, evsel->name) == 0) | 1973 | if (strcmp(str, evsel->name) == 0) |
| @@ -1888,3 +1976,61 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, | |||
| 1888 | 1976 | ||
| 1889 | return NULL; | 1977 | return NULL; |
| 1890 | } | 1978 | } |
| 1979 | |||
| 1980 | void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, | ||
| 1981 | enum bkw_mmap_state state) | ||
| 1982 | { | ||
| 1983 | enum bkw_mmap_state old_state = evlist->bkw_mmap_state; | ||
| 1984 | enum action { | ||
| 1985 | NONE, | ||
| 1986 | PAUSE, | ||
| 1987 | RESUME, | ||
| 1988 | } action = NONE; | ||
| 1989 | |||
| 1990 | if (!evlist->backward_mmap) | ||
| 1991 | return; | ||
| 1992 | |||
| 1993 | switch (old_state) { | ||
| 1994 | case BKW_MMAP_NOTREADY: { | ||
| 1995 | if (state != BKW_MMAP_RUNNING) | ||
| 1996 | goto state_err;; | ||
| 1997 | break; | ||
| 1998 | } | ||
| 1999 | case BKW_MMAP_RUNNING: { | ||
| 2000 | if (state != BKW_MMAP_DATA_PENDING) | ||
| 2001 | goto state_err; | ||
| 2002 | action = PAUSE; | ||
| 2003 | break; | ||
| 2004 | } | ||
| 2005 | case BKW_MMAP_DATA_PENDING: { | ||
| 2006 | if (state != BKW_MMAP_EMPTY) | ||
| 2007 | goto state_err; | ||
| 2008 | break; | ||
| 2009 | } | ||
| 2010 | case BKW_MMAP_EMPTY: { | ||
| 2011 | if (state != BKW_MMAP_RUNNING) | ||
| 2012 | goto state_err; | ||
| 2013 | action = RESUME; | ||
| 2014 | break; | ||
| 2015 | } | ||
| 2016 | default: | ||
| 2017 | WARN_ONCE(1, "Shouldn't get there\n"); | ||
| 2018 | } | ||
| 2019 | |||
| 2020 | evlist->bkw_mmap_state = state; | ||
| 2021 | |||
| 2022 | switch (action) { | ||
| 2023 | case PAUSE: | ||
| 2024 | perf_evlist__pause(evlist); | ||
| 2025 | break; | ||
| 2026 | case RESUME: | ||
| 2027 | perf_evlist__resume(evlist); | ||
| 2028 | break; | ||
| 2029 | case NONE: | ||
| 2030 | default: | ||
| 2031 | break; | ||
| 2032 | } | ||
| 2033 | |||
| 2034 | state_err: | ||
| 2035 | return; | ||
| 2036 | } | ||
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..8c54df61fe64 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 | { |
| @@ -572,6 +590,8 @@ void perf_evsel__config_callchain(struct perf_evsel *evsel, | |||
| 572 | 590 | ||
| 573 | perf_evsel__set_sample_bit(evsel, CALLCHAIN); | 591 | perf_evsel__set_sample_bit(evsel, CALLCHAIN); |
| 574 | 592 | ||
| 593 | attr->sample_max_stack = param->max_stack; | ||
| 594 | |||
| 575 | if (param->record_mode == CALLCHAIN_LBR) { | 595 | if (param->record_mode == CALLCHAIN_LBR) { |
| 576 | if (!opts->branch_stack) { | 596 | if (!opts->branch_stack) { |
| 577 | if (attr->exclude_user) { | 597 | if (attr->exclude_user) { |
| @@ -635,7 +655,8 @@ static void apply_config_terms(struct perf_evsel *evsel, | |||
| 635 | struct perf_event_attr *attr = &evsel->attr; | 655 | struct perf_event_attr *attr = &evsel->attr; |
| 636 | struct callchain_param param; | 656 | struct callchain_param param; |
| 637 | u32 dump_size = 0; | 657 | u32 dump_size = 0; |
| 638 | char *callgraph_buf = NULL; | 658 | int max_stack = 0; |
| 659 | const char *callgraph_buf = NULL; | ||
| 639 | 660 | ||
| 640 | /* callgraph default */ | 661 | /* callgraph default */ |
| 641 | param.record_mode = callchain_param.record_mode; | 662 | param.record_mode = callchain_param.record_mode; |
| @@ -662,6 +683,9 @@ static void apply_config_terms(struct perf_evsel *evsel, | |||
| 662 | case PERF_EVSEL__CONFIG_TERM_STACK_USER: | 683 | case PERF_EVSEL__CONFIG_TERM_STACK_USER: |
| 663 | dump_size = term->val.stack_user; | 684 | dump_size = term->val.stack_user; |
| 664 | break; | 685 | break; |
| 686 | case PERF_EVSEL__CONFIG_TERM_MAX_STACK: | ||
| 687 | max_stack = term->val.max_stack; | ||
| 688 | break; | ||
| 665 | case PERF_EVSEL__CONFIG_TERM_INHERIT: | 689 | case PERF_EVSEL__CONFIG_TERM_INHERIT: |
| 666 | /* | 690 | /* |
| 667 | * attr->inherit should has already been set by | 691 | * attr->inherit should has already been set by |
| @@ -671,13 +695,21 @@ static void apply_config_terms(struct perf_evsel *evsel, | |||
| 671 | */ | 695 | */ |
| 672 | attr->inherit = term->val.inherit ? 1 : 0; | 696 | attr->inherit = term->val.inherit ? 1 : 0; |
| 673 | break; | 697 | break; |
| 698 | case PERF_EVSEL__CONFIG_TERM_OVERWRITE: | ||
| 699 | attr->write_backward = term->val.overwrite ? 1 : 0; | ||
| 700 | break; | ||
| 674 | default: | 701 | default: |
| 675 | break; | 702 | break; |
| 676 | } | 703 | } |
| 677 | } | 704 | } |
| 678 | 705 | ||
| 679 | /* User explicitly set per-event callgraph, clear the old setting and reset. */ | 706 | /* User explicitly set per-event callgraph, clear the old setting and reset. */ |
| 680 | if ((callgraph_buf != NULL) || (dump_size > 0)) { | 707 | if ((callgraph_buf != NULL) || (dump_size > 0) || max_stack) { |
| 708 | if (max_stack) { | ||
| 709 | param.max_stack = max_stack; | ||
| 710 | if (callgraph_buf == NULL) | ||
| 711 | callgraph_buf = "fp"; | ||
| 712 | } | ||
| 681 | 713 | ||
| 682 | /* parse callgraph parameters */ | 714 | /* parse callgraph parameters */ |
| 683 | if (callgraph_buf != NULL) { | 715 | if (callgraph_buf != NULL) { |
| @@ -747,6 +779,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts, | |||
| 747 | 779 | ||
| 748 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; | 780 | attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; |
| 749 | attr->inherit = !opts->no_inherit; | 781 | attr->inherit = !opts->no_inherit; |
| 782 | attr->write_backward = opts->overwrite ? 1 : 0; | ||
| 750 | 783 | ||
| 751 | perf_evsel__set_sample_bit(evsel, IP); | 784 | perf_evsel__set_sample_bit(evsel, IP); |
| 752 | perf_evsel__set_sample_bit(evsel, TID); | 785 | perf_evsel__set_sample_bit(evsel, TID); |
| @@ -1329,6 +1362,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, | |||
| 1329 | PRINT_ATTRf(clockid, p_signed); | 1362 | PRINT_ATTRf(clockid, p_signed); |
| 1330 | PRINT_ATTRf(sample_regs_intr, p_hex); | 1363 | PRINT_ATTRf(sample_regs_intr, p_hex); |
| 1331 | PRINT_ATTRf(aux_watermark, p_unsigned); | 1364 | PRINT_ATTRf(aux_watermark, p_unsigned); |
| 1365 | PRINT_ATTRf(sample_max_stack, p_unsigned); | ||
| 1332 | 1366 | ||
| 1333 | return ret; | 1367 | return ret; |
| 1334 | } | 1368 | } |
| @@ -1347,6 +1381,9 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
| 1347 | int pid = -1, err; | 1381 | int pid = -1, err; |
| 1348 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; | 1382 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; |
| 1349 | 1383 | ||
| 1384 | if (perf_missing_features.write_backward && evsel->attr.write_backward) | ||
| 1385 | return -EINVAL; | ||
| 1386 | |||
| 1350 | if (evsel->system_wide) | 1387 | if (evsel->system_wide) |
| 1351 | nthreads = 1; | 1388 | nthreads = 1; |
| 1352 | else | 1389 | else |
| @@ -1377,8 +1414,6 @@ fallback_missing_features: | |||
| 1377 | if (perf_missing_features.lbr_flags) | 1414 | if (perf_missing_features.lbr_flags) |
| 1378 | evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | | 1415 | evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | |
| 1379 | PERF_SAMPLE_BRANCH_NO_CYCLES); | 1416 | PERF_SAMPLE_BRANCH_NO_CYCLES); |
| 1380 | if (perf_missing_features.write_backward) | ||
| 1381 | evsel->attr.write_backward = false; | ||
| 1382 | retry_sample_id: | 1417 | retry_sample_id: |
| 1383 | if (perf_missing_features.sample_id_all) | 1418 | if (perf_missing_features.sample_id_all) |
| 1384 | evsel->attr.sample_id_all = 0; | 1419 | evsel->attr.sample_id_all = 0; |
| @@ -1441,12 +1476,6 @@ retry_open: | |||
| 1441 | err = -EINVAL; | 1476 | err = -EINVAL; |
| 1442 | goto out_close; | 1477 | goto out_close; |
| 1443 | } | 1478 | } |
| 1444 | |||
| 1445 | if (evsel->overwrite && | ||
| 1446 | perf_missing_features.write_backward) { | ||
| 1447 | err = -EINVAL; | ||
| 1448 | goto out_close; | ||
| 1449 | } | ||
| 1450 | } | 1479 | } |
| 1451 | } | 1480 | } |
| 1452 | 1481 | ||
| @@ -1484,7 +1513,10 @@ try_fallback: | |||
| 1484 | * Must probe features in the order they were added to the | 1513 | * Must probe features in the order they were added to the |
| 1485 | * perf_event_attr interface. | 1514 | * perf_event_attr interface. |
| 1486 | */ | 1515 | */ |
| 1487 | if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { | 1516 | if (!perf_missing_features.write_backward && evsel->attr.write_backward) { |
| 1517 | perf_missing_features.write_backward = true; | ||
| 1518 | goto out_close; | ||
| 1519 | } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { | ||
| 1488 | perf_missing_features.clockid_wrong = true; | 1520 | perf_missing_features.clockid_wrong = true; |
| 1489 | goto fallback_missing_features; | 1521 | goto fallback_missing_features; |
| 1490 | } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { | 1522 | } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { |
| @@ -1509,12 +1541,7 @@ try_fallback: | |||
| 1509 | PERF_SAMPLE_BRANCH_NO_FLAGS))) { | 1541 | PERF_SAMPLE_BRANCH_NO_FLAGS))) { |
| 1510 | perf_missing_features.lbr_flags = true; | 1542 | perf_missing_features.lbr_flags = true; |
| 1511 | goto fallback_missing_features; | 1543 | 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 | } | 1544 | } |
| 1517 | |||
| 1518 | out_close: | 1545 | out_close: |
| 1519 | do { | 1546 | do { |
| 1520 | while (--thread >= 0) { | 1547 | while (--thread >= 0) { |
| @@ -2239,17 +2266,11 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, | |||
| 2239 | return sample->raw_data + offset; | 2266 | return sample->raw_data + offset; |
| 2240 | } | 2267 | } |
| 2241 | 2268 | ||
| 2242 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | 2269 | u64 format_field__intval(struct format_field *field, struct perf_sample *sample, |
| 2243 | const char *name) | 2270 | bool needs_swap) |
| 2244 | { | 2271 | { |
| 2245 | struct format_field *field = perf_evsel__field(evsel, name); | ||
| 2246 | void *ptr; | ||
| 2247 | u64 value; | 2272 | u64 value; |
| 2248 | 2273 | void *ptr = sample->raw_data + field->offset; | |
| 2249 | if (!field) | ||
| 2250 | return 0; | ||
| 2251 | |||
| 2252 | ptr = sample->raw_data + field->offset; | ||
| 2253 | 2274 | ||
| 2254 | switch (field->size) { | 2275 | switch (field->size) { |
| 2255 | case 1: | 2276 | case 1: |
| @@ -2267,7 +2288,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
| 2267 | return 0; | 2288 | return 0; |
| 2268 | } | 2289 | } |
| 2269 | 2290 | ||
| 2270 | if (!evsel->needs_swap) | 2291 | if (!needs_swap) |
| 2271 | return value; | 2292 | return value; |
| 2272 | 2293 | ||
| 2273 | switch (field->size) { | 2294 | switch (field->size) { |
| @@ -2284,6 +2305,17 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
| 2284 | return 0; | 2305 | return 0; |
| 2285 | } | 2306 | } |
| 2286 | 2307 | ||
| 2308 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | ||
| 2309 | const char *name) | ||
| 2310 | { | ||
| 2311 | struct format_field *field = perf_evsel__field(evsel, name); | ||
| 2312 | |||
| 2313 | if (!field) | ||
| 2314 | return 0; | ||
| 2315 | |||
| 2316 | return field ? format_field__intval(field, sample, evsel->needs_swap) : 0; | ||
| 2317 | } | ||
| 2318 | |||
| 2287 | bool perf_evsel__fallback(struct perf_evsel *evsel, int err, | 2319 | bool perf_evsel__fallback(struct perf_evsel *evsel, int err, |
| 2288 | char *msg, size_t msgsize) | 2320 | char *msg, size_t msgsize) |
| 2289 | { | 2321 | { |
| @@ -2372,6 +2404,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?"); | 2404 | "No such device - did you specify an out-of-range profile CPU?"); |
| 2373 | break; | 2405 | break; |
| 2374 | case EOPNOTSUPP: | 2406 | case EOPNOTSUPP: |
| 2407 | if (evsel->attr.sample_period != 0) | ||
| 2408 | return scnprintf(msg, size, "%s", | ||
| 2409 | "PMU Hardware doesn't support sampling/overflow-interrupts."); | ||
| 2375 | if (evsel->attr.precise_ip) | 2410 | if (evsel->attr.precise_ip) |
| 2376 | return scnprintf(msg, size, "%s", | 2411 | return scnprintf(msg, size, "%s", |
| 2377 | "\'precise\' request may not be supported. Try removing 'p' modifier."); | 2412 | "\'precise\' request may not be supported. Try removing 'p' modifier."); |
| @@ -2389,6 +2424,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."); | 2424 | "We found oprofile daemon running, please stop it and try again."); |
| 2390 | break; | 2425 | break; |
| 2391 | case EINVAL: | 2426 | case EINVAL: |
| 2427 | if (evsel->attr.write_backward && perf_missing_features.write_backward) | ||
| 2428 | return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel."); | ||
| 2392 | if (perf_missing_features.clockid) | 2429 | if (perf_missing_features.clockid) |
| 2393 | return scnprintf(msg, size, "clockid feature not supported."); | 2430 | return scnprintf(msg, size, "clockid feature not supported."); |
| 2394 | if (perf_missing_features.clockid_wrong) | 2431 | if (perf_missing_features.clockid_wrong) |
| @@ -2402,6 +2439,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" | 2439 | "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" |
| 2403 | "/bin/dmesg may provide additional information.\n" | 2440 | "/bin/dmesg may provide additional information.\n" |
| 2404 | "No CONFIG_PERF_EVENTS=y kernel support configured?", | 2441 | "No CONFIG_PERF_EVENTS=y kernel support configured?", |
| 2405 | err, strerror_r(err, sbuf, sizeof(sbuf)), | 2442 | err, str_error_r(err, sbuf, sizeof(sbuf)), |
| 2406 | perf_evsel__name(evsel)); | 2443 | perf_evsel__name(evsel)); |
| 2407 | } | 2444 | } |
| 2445 | |||
| 2446 | char *perf_evsel__env_arch(struct perf_evsel *evsel) | ||
| 2447 | { | ||
| 2448 | if (evsel && evsel->evlist && evsel->evlist->env) | ||
| 2449 | return evsel->evlist->env->arch; | ||
| 2450 | return NULL; | ||
| 2451 | } | ||
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index c1f10159804c..8a4a6c9f1480 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; |
| @@ -259,6 +262,8 @@ static inline char *perf_evsel__strval(struct perf_evsel *evsel, | |||
| 259 | 262 | ||
| 260 | struct format_field; | 263 | struct format_field; |
| 261 | 264 | ||
| 265 | u64 format_field__intval(struct format_field *field, struct perf_sample *sample, bool needs_swap); | ||
| 266 | |||
| 262 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); | 267 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); |
| 263 | 268 | ||
| 264 | #define perf_evsel__match(evsel, t, c) \ | 269 | #define perf_evsel__match(evsel, t, c) \ |
| @@ -351,23 +356,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; | 356 | return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1; |
| 352 | } | 357 | } |
| 353 | 358 | ||
| 354 | /** | 359 | 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 | 360 | ||
| 372 | static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel) | 361 | static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel) |
| 373 | { | 362 | { |
| @@ -431,4 +420,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, | 420 | int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, |
| 432 | attr__fprintf_f attr__fprintf, void *priv); | 421 | attr__fprintf_f attr__fprintf, void *priv); |
| 433 | 422 | ||
| 423 | char *perf_evsel__env_arch(struct perf_evsel *evsel); | ||
| 424 | |||
| 434 | #endif /* __PERF_EVSEL_H */ | 425 | #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..a18d142cdca3 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 | } | ||
| 363 | 369 | ||
| 364 | he = zalloc(sizeof(*he) + callchain_size); | 370 | map__get(he->ms.map); |
| 365 | 371 | ||
| 366 | if (he != NULL) { | 372 | if (he->branch_info) { |
| 367 | *he = *template; | 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 | } | ||
| 368 | 391 | ||
| 369 | if (symbol_conf.cumulate_callchain) { | 392 | if (he->mem_info) { |
| 370 | he->stat_acc = malloc(sizeof(he->stat)); | 393 | map__get(he->mem_info->iaddr.map); |
| 371 | if (he->stat_acc == NULL) { | 394 | map__get(he->mem_info->daddr.map); |
| 372 | free(he); | 395 | } |
| 373 | return NULL; | 396 | |
| 397 | if (symbol_conf.use_callchain) | ||
| 398 | callchain_init(he->callchain); | ||
| 399 | |||
| 400 | if (he->raw_data) { | ||
| 401 | he->raw_data = memdup(he->raw_data, he->raw_size); | ||
| 402 | |||
| 403 | if (he->raw_data == NULL) { | ||
| 404 | map__put(he->ms.map); | ||
| 405 | if (he->branch_info) { | ||
| 406 | map__put(he->branch_info->from.map); | ||
| 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, " "); |
| @@ -2199,7 +2257,7 @@ size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp) | |||
| 2199 | struct perf_evsel *pos; | 2257 | struct perf_evsel *pos; |
| 2200 | size_t ret = 0; | 2258 | size_t ret = 0; |
| 2201 | 2259 | ||
| 2202 | evlist__for_each(evlist, pos) { | 2260 | evlist__for_each_entry(evlist, pos) { |
| 2203 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); | 2261 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); |
| 2204 | ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp); | 2262 | ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp); |
| 2205 | } | 2263 | } |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 7b54ccf1b737..49aa4fac148f 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 | ||
| @@ -159,7 +170,8 @@ void events_stats__inc(struct events_stats *stats, u32 type); | |||
| 159 | size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); | 170 | size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); |
| 160 | 171 | ||
| 161 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | 172 | size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, |
| 162 | int max_cols, float min_pcnt, FILE *fp); | 173 | int max_cols, float min_pcnt, FILE *fp, |
| 174 | bool use_callchain); | ||
| 163 | size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp); | 175 | size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp); |
| 164 | 176 | ||
| 165 | void hists__filter_by_dso(struct hists *hists); | 177 | void hists__filter_by_dso(struct hists *hists); |
| @@ -214,9 +226,9 @@ struct perf_hpp { | |||
| 214 | struct perf_hpp_fmt { | 226 | struct perf_hpp_fmt { |
| 215 | const char *name; | 227 | const char *name; |
| 216 | int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 228 | int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
| 217 | struct perf_evsel *evsel); | 229 | struct hists *hists); |
| 218 | int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 230 | int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
| 219 | struct perf_evsel *evsel); | 231 | struct hists *hists); |
| 220 | int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 232 | int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, |
| 221 | struct hist_entry *he); | 233 | struct hist_entry *he); |
| 222 | int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, | 234 | 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..ec378cd7b71e 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 | ||
| @@ -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..bc2cdbd09a25 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) |
| @@ -1353,11 +1355,16 @@ int machine__process_mmap2_event(struct machine *machine, | |||
| 1353 | if (map == NULL) | 1355 | if (map == NULL) |
| 1354 | goto out_problem_map; | 1356 | goto out_problem_map; |
| 1355 | 1357 | ||
| 1356 | thread__insert_map(thread, map); | 1358 | ret = thread__insert_map(thread, map); |
| 1359 | if (ret) | ||
| 1360 | goto out_problem_insert; | ||
| 1361 | |||
| 1357 | thread__put(thread); | 1362 | thread__put(thread); |
| 1358 | map__put(map); | 1363 | map__put(map); |
| 1359 | return 0; | 1364 | return 0; |
| 1360 | 1365 | ||
| 1366 | out_problem_insert: | ||
| 1367 | map__put(map); | ||
| 1361 | out_problem_map: | 1368 | out_problem_map: |
| 1362 | thread__put(thread); | 1369 | thread__put(thread); |
| 1363 | out_problem: | 1370 | out_problem: |
| @@ -1403,11 +1410,16 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event | |||
| 1403 | if (map == NULL) | 1410 | if (map == NULL) |
| 1404 | goto out_problem_map; | 1411 | goto out_problem_map; |
| 1405 | 1412 | ||
| 1406 | thread__insert_map(thread, map); | 1413 | ret = thread__insert_map(thread, map); |
| 1414 | if (ret) | ||
| 1415 | goto out_problem_insert; | ||
| 1416 | |||
| 1407 | thread__put(thread); | 1417 | thread__put(thread); |
| 1408 | map__put(map); | 1418 | map__put(map); |
| 1409 | return 0; | 1419 | return 0; |
| 1410 | 1420 | ||
| 1421 | out_problem_insert: | ||
| 1422 | map__put(map); | ||
| 1411 | out_problem_map: | 1423 | out_problem_map: |
| 1412 | thread__put(thread); | 1424 | thread__put(thread); |
| 1413 | out_problem: | 1425 | out_problem: |
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..5065ec98049c 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources | |||
| @@ -13,6 +13,8 @@ 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/str_error_r.c | ||
| 17 | ../lib/vsprintf.c | ||
| 16 | util/thread_map.c | 18 | util/thread_map.c |
| 17 | util/util.c | 19 | util/util.c |
| 18 | util/xyarray.c | 20 | 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..8cdcf4641c51 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,7 +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 | const char *err = str_error_r(errnum, buf, buflen); |
| 125 | 126 | ||
| 126 | if (err != buf) | 127 | if (err != buf) |
| 127 | scnprintf(buf, buflen, "%s", err); | 128 | scnprintf(buf, buflen, "%s", err); |
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; |
