diff options
Diffstat (limited to 'tools/perf')
157 files changed, 7581 insertions, 1593 deletions
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt index 4a0501d7a3b4..be764f9ec769 100644 --- a/tools/perf/Documentation/intel-pt.txt +++ b/tools/perf/Documentation/intel-pt.txt | |||
@@ -364,21 +364,6 @@ cyc_thresh Specifies how frequently CYC packets are produced - see cyc | |||
364 | 364 | ||
365 | CYC packets are not requested by default. | 365 | CYC packets are not requested by default. |
366 | 366 | ||
367 | no_force_psb This is a driver option and is not in the IA32_RTIT_CTL MSR. | ||
368 | |||
369 | It stops the driver resetting the byte count to zero whenever | ||
370 | enabling the trace (for example on context switches) which in | ||
371 | turn results in no PSB being forced. However some processors | ||
372 | will produce a PSB anyway. | ||
373 | |||
374 | In any case, there is still a PSB when the trace is enabled for | ||
375 | the first time. | ||
376 | |||
377 | no_force_psb can be used to slightly decrease the trace size but | ||
378 | may make it harder for the decoder to recover from errors. | ||
379 | |||
380 | no_force_psb is not selected by default. | ||
381 | |||
382 | 367 | ||
383 | new snapshot option | 368 | new snapshot option |
384 | ------------------- | 369 | ------------------- |
@@ -686,6 +671,7 @@ The letters are: | |||
686 | e synthesize tracing error events | 671 | e synthesize tracing error events |
687 | d create a debug log | 672 | d create a debug log |
688 | g synthesize a call chain (use with i or x) | 673 | g synthesize a call chain (use with i or x) |
674 | l synthesize last branch entries (use with i or x) | ||
689 | 675 | ||
690 | "Instructions" events look like they were recorded by "perf record -e | 676 | "Instructions" events look like they were recorded by "perf record -e |
691 | instructions". | 677 | instructions". |
@@ -722,12 +708,26 @@ on the sample is *not* adjusted and reflects the last known value of TSC. | |||
722 | 708 | ||
723 | For Intel PT, the default period is 100us. | 709 | For Intel PT, the default period is 100us. |
724 | 710 | ||
711 | Setting it to a zero period means "as often as possible". | ||
712 | |||
713 | In the case of Intel PT that is the same as a period of 1 and a unit of | ||
714 | 'instructions' (i.e. --itrace=i1i). | ||
715 | |||
725 | Also the call chain size (default 16, max. 1024) for instructions or | 716 | Also the call chain size (default 16, max. 1024) for instructions or |
726 | transactions events can be specified. e.g. | 717 | transactions events can be specified. e.g. |
727 | 718 | ||
728 | --itrace=ig32 | 719 | --itrace=ig32 |
729 | --itrace=xg32 | 720 | --itrace=xg32 |
730 | 721 | ||
722 | Also the number of last branch entries (default 64, max. 1024) for instructions or | ||
723 | transactions events can be specified. e.g. | ||
724 | |||
725 | --itrace=il10 | ||
726 | --itrace=xl10 | ||
727 | |||
728 | Note that last branch entries are cleared for each sample, so there is no overlap | ||
729 | from one sample to the next. | ||
730 | |||
731 | To disable trace decoding entirely, use the option --no-itrace. | 731 | To disable trace decoding entirely, use the option --no-itrace. |
732 | 732 | ||
733 | 733 | ||
@@ -764,3 +764,32 @@ perf inject also accepts the --itrace option in which case tracing data is | |||
764 | removed and replaced with the synthesized events. e.g. | 764 | removed and replaced with the synthesized events. e.g. |
765 | 765 | ||
766 | perf inject --itrace -i perf.data -o perf.data.new | 766 | perf inject --itrace -i perf.data -o perf.data.new |
767 | |||
768 | Below is an example of using Intel PT with autofdo. It requires autofdo | ||
769 | (https://github.com/google/autofdo) and gcc version 5. The bubble | ||
770 | sort example is from the AutoFDO tutorial (https://gcc.gnu.org/wiki/AutoFDO/Tutorial) | ||
771 | amended to take the number of elements as a parameter. | ||
772 | |||
773 | $ gcc-5 -O3 sort.c -o sort_optimized | ||
774 | $ ./sort_optimized 30000 | ||
775 | Bubble sorting array of 30000 elements | ||
776 | 2254 ms | ||
777 | |||
778 | $ cat ~/.perfconfig | ||
779 | [intel-pt] | ||
780 | mispred-all | ||
781 | |||
782 | $ perf record -e intel_pt//u ./sort 3000 | ||
783 | Bubble sorting array of 3000 elements | ||
784 | 58 ms | ||
785 | [ perf record: Woken up 2 times to write data ] | ||
786 | [ perf record: Captured and wrote 3.939 MB perf.data ] | ||
787 | $ perf inject -i perf.data -o inj --itrace=i100usle --strip | ||
788 | $ ./create_gcov --binary=./sort --profile=inj --gcov=sort.gcov -gcov_version=1 | ||
789 | $ gcc-5 -O3 -fauto-profile=sort.gcov sort.c -o sort_autofdo | ||
790 | $ ./sort_autofdo 30000 | ||
791 | Bubble sorting array of 30000 elements | ||
792 | 2155 ms | ||
793 | |||
794 | Note there is currently no advantage to using Intel PT instead of LBR, but | ||
795 | that may change in the future if greater use is made of the data. | ||
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt index 2ff946677e3b..65453f4c7006 100644 --- a/tools/perf/Documentation/itrace.txt +++ b/tools/perf/Documentation/itrace.txt | |||
@@ -6,6 +6,7 @@ | |||
6 | e synthesize error events | 6 | e synthesize error events |
7 | d create a debug log | 7 | d create a debug log |
8 | g synthesize a call chain (use with i or x) | 8 | g synthesize a call chain (use with i or x) |
9 | l synthesize last branch entries (use with i or x) | ||
9 | 10 | ||
10 | The default is all events i.e. the same as --itrace=ibxe | 11 | The default is all events i.e. the same as --itrace=ibxe |
11 | 12 | ||
@@ -20,3 +21,6 @@ | |||
20 | 21 | ||
21 | Also the call chain size (default 16, max. 1024) for instructions or | 22 | Also the call chain size (default 16, max. 1024) for instructions or |
22 | transactions events can be specified. | 23 | transactions events can be specified. |
24 | |||
25 | Also the number of last branch entries (default 64, max. 1024) for | ||
26 | instructions or transactions events can be specified. | ||
diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt index ab632d9fbd7d..34750fc32714 100644 --- a/tools/perf/Documentation/perf-bench.txt +++ b/tools/perf/Documentation/perf-bench.txt | |||
@@ -82,7 +82,7 @@ Be multi thread instead of multi process | |||
82 | Specify number of groups | 82 | Specify number of groups |
83 | 83 | ||
84 | -l:: | 84 | -l:: |
85 | --loop=:: | 85 | --nr_loops=:: |
86 | Specify number of loops | 86 | Specify number of loops |
87 | 87 | ||
88 | Example of *messaging* | 88 | Example of *messaging* |
@@ -139,64 +139,48 @@ Suite for evaluating performance of simple memory copy in various ways. | |||
139 | Options of *memcpy* | 139 | Options of *memcpy* |
140 | ^^^^^^^^^^^^^^^^^^^ | 140 | ^^^^^^^^^^^^^^^^^^^ |
141 | -l:: | 141 | -l:: |
142 | --length:: | 142 | --size:: |
143 | Specify length of memory to copy (default: 1MB). | 143 | Specify size of memory to copy (default: 1MB). |
144 | Available units are B, KB, MB, GB and TB (case insensitive). | 144 | Available units are B, KB, MB, GB and TB (case insensitive). |
145 | 145 | ||
146 | -r:: | 146 | -f:: |
147 | --routine:: | 147 | --function:: |
148 | Specify routine to copy (default: default). | 148 | Specify function to copy (default: default). |
149 | Available routines are depend on the architecture. | 149 | Available functions are depend on the architecture. |
150 | On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported. | 150 | On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported. |
151 | 151 | ||
152 | -i:: | 152 | -l:: |
153 | --iterations:: | 153 | --nr_loops:: |
154 | Repeat memcpy invocation this number of times. | 154 | Repeat memcpy invocation this number of times. |
155 | 155 | ||
156 | -c:: | 156 | -c:: |
157 | --cycle:: | 157 | --cycles:: |
158 | Use perf's cpu-cycles event instead of gettimeofday syscall. | 158 | Use perf's cpu-cycles event instead of gettimeofday syscall. |
159 | 159 | ||
160 | -o:: | ||
161 | --only-prefault:: | ||
162 | Show only the result with page faults before memcpy. | ||
163 | |||
164 | -n:: | ||
165 | --no-prefault:: | ||
166 | Show only the result without page faults before memcpy. | ||
167 | |||
168 | *memset*:: | 160 | *memset*:: |
169 | Suite for evaluating performance of simple memory set in various ways. | 161 | Suite for evaluating performance of simple memory set in various ways. |
170 | 162 | ||
171 | Options of *memset* | 163 | Options of *memset* |
172 | ^^^^^^^^^^^^^^^^^^^ | 164 | ^^^^^^^^^^^^^^^^^^^ |
173 | -l:: | 165 | -l:: |
174 | --length:: | 166 | --size:: |
175 | Specify length of memory to set (default: 1MB). | 167 | Specify size of memory to set (default: 1MB). |
176 | Available units are B, KB, MB, GB and TB (case insensitive). | 168 | Available units are B, KB, MB, GB and TB (case insensitive). |
177 | 169 | ||
178 | -r:: | 170 | -f:: |
179 | --routine:: | 171 | --function:: |
180 | Specify routine to set (default: default). | 172 | Specify function to set (default: default). |
181 | Available routines are depend on the architecture. | 173 | Available functions are depend on the architecture. |
182 | On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported. | 174 | On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported. |
183 | 175 | ||
184 | -i:: | 176 | -l:: |
185 | --iterations:: | 177 | --nr_loops:: |
186 | Repeat memset invocation this number of times. | 178 | Repeat memset invocation this number of times. |
187 | 179 | ||
188 | -c:: | 180 | -c:: |
189 | --cycle:: | 181 | --cycles:: |
190 | Use perf's cpu-cycles event instead of gettimeofday syscall. | 182 | Use perf's cpu-cycles event instead of gettimeofday syscall. |
191 | 183 | ||
192 | -o:: | ||
193 | --only-prefault:: | ||
194 | Show only the result with page faults before memset. | ||
195 | |||
196 | -n:: | ||
197 | --no-prefault:: | ||
198 | Show only the result without page faults before memset. | ||
199 | |||
200 | SUITES FOR 'numa' | 184 | SUITES FOR 'numa' |
201 | ~~~~~~~~~~~~~~~~~ | 185 | ~~~~~~~~~~~~~~~~~ |
202 | *mem*:: | 186 | *mem*:: |
diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt index 0c721c3e37e1..0b1cedeef895 100644 --- a/tools/perf/Documentation/perf-inject.txt +++ b/tools/perf/Documentation/perf-inject.txt | |||
@@ -50,6 +50,9 @@ OPTIONS | |||
50 | 50 | ||
51 | include::itrace.txt[] | 51 | include::itrace.txt[] |
52 | 52 | ||
53 | --strip:: | ||
54 | Use with --itrace to strip out non-synthesized events. | ||
55 | |||
53 | SEE ALSO | 56 | SEE ALSO |
54 | -------- | 57 | -------- |
55 | linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1] | 58 | linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1] |
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index bada8933fdd4..79483f40e991 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt | |||
@@ -30,6 +30,7 @@ counted. The following modifiers exist: | |||
30 | G - guest counting (in KVM guests) | 30 | G - guest counting (in KVM guests) |
31 | H - host counting (not in KVM guests) | 31 | H - host counting (not in KVM guests) |
32 | p - precise level | 32 | p - precise level |
33 | P - use maximum detected precise level | ||
33 | S - read sample value (PERF_SAMPLE_READ) | 34 | S - read sample value (PERF_SAMPLE_READ) |
34 | D - pin the event to the PMU | 35 | D - pin the event to the PMU |
35 | 36 | ||
@@ -125,6 +126,8 @@ To limit the list use: | |||
125 | . If none of the above is matched, it will apply the supplied glob to all | 126 | . If none of the above is matched, it will apply the supplied glob to all |
126 | events, printing the ones that match. | 127 | events, printing the ones that match. |
127 | 128 | ||
129 | . As a last resort, it will do a substring search in all event names. | ||
130 | |||
128 | One or more types can be used at the same time, listing the events for the | 131 | One or more types can be used at the same time, listing the events for the |
129 | types specified. | 132 | types specified. |
130 | 133 | ||
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 2e9ce77b5e14..e630a7d2c348 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -144,7 +144,7 @@ OPTIONS | |||
144 | 144 | ||
145 | --call-graph:: | 145 | --call-graph:: |
146 | Setup and enable call-graph (stack chain/backtrace) recording, | 146 | Setup and enable call-graph (stack chain/backtrace) recording, |
147 | implies -g. | 147 | implies -g. Default is "fp". |
148 | 148 | ||
149 | Allows specifying "fp" (frame pointer) or "dwarf" | 149 | Allows specifying "fp" (frame pointer) or "dwarf" |
150 | (DWARF's CFI - Call Frame Information) or "lbr" | 150 | (DWARF's CFI - Call Frame Information) or "lbr" |
@@ -154,13 +154,18 @@ OPTIONS | |||
154 | In some systems, where binaries are build with gcc | 154 | In some systems, where binaries are build with gcc |
155 | --fomit-frame-pointer, using the "fp" method will produce bogus | 155 | --fomit-frame-pointer, using the "fp" method will produce bogus |
156 | call graphs, using "dwarf", if available (perf tools linked to | 156 | call graphs, using "dwarf", if available (perf tools linked to |
157 | the libunwind library) should be used instead. | 157 | the libunwind or libdw library) should be used instead. |
158 | Using the "lbr" method doesn't require any compiler options. It | 158 | Using the "lbr" method doesn't require any compiler options. It |
159 | will produce call graphs from the hardware LBR registers. The | 159 | will produce call graphs from the hardware LBR registers. The |
160 | main limition is that it is only available on new Intel | 160 | main limition is that it is only available on new Intel |
161 | platforms, such as Haswell. It can only get user call chain. It | 161 | platforms, such as Haswell. It can only get user call chain. It |
162 | doesn't work with branch stack sampling at the same time. | 162 | doesn't work with branch stack sampling at the same time. |
163 | 163 | ||
164 | When "dwarf" recording is used, perf also records (user) stack dump | ||
165 | when sampled. Default size of the stack dump is 8192 (bytes). | ||
166 | User can change the size by passing the size after comma like | ||
167 | "--call-graph dwarf,4096". | ||
168 | |||
164 | -q:: | 169 | -q:: |
165 | --quiet:: | 170 | --quiet:: |
166 | Don't print any message, useful for scripting. | 171 | Don't print any message, useful for scripting. |
@@ -236,6 +241,7 @@ following filters are defined: | |||
236 | - any_call: any function call or system call | 241 | - any_call: any function call or system call |
237 | - any_ret: any function return or system call return | 242 | - any_ret: any function return or system call return |
238 | - ind_call: any indirect branch | 243 | - ind_call: any indirect branch |
244 | - call: direct calls, including far (to/from kernel) calls | ||
239 | - u: only when the branch target is at the user level | 245 | - u: only when the branch target is at the user level |
240 | - k: only when the branch target is in the kernel | 246 | - k: only when the branch target is in the kernel |
241 | - hv: only when the target is at the hypervisor level | 247 | - hv: only when the target is at the hypervisor level |
@@ -308,6 +314,12 @@ This option sets the time out limit. The default value is 500 ms. | |||
308 | Record context switch events i.e. events of type PERF_RECORD_SWITCH or | 314 | Record context switch events i.e. events of type PERF_RECORD_SWITCH or |
309 | PERF_RECORD_SWITCH_CPU_WIDE. | 315 | PERF_RECORD_SWITCH_CPU_WIDE. |
310 | 316 | ||
317 | --clang-path:: | ||
318 | Path to clang binary to use for compiling BPF scriptlets. | ||
319 | |||
320 | --clang-opt:: | ||
321 | Options passed to clang when compiling BPF scriptlets. | ||
322 | |||
311 | SEE ALSO | 323 | SEE ALSO |
312 | -------- | 324 | -------- |
313 | linkperf:perf-stat[1], linkperf:perf-list[1] | 325 | 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 9c7981bfddad..5ce8da1e1256 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -29,7 +29,7 @@ OPTIONS | |||
29 | --show-nr-samples:: | 29 | --show-nr-samples:: |
30 | Show the number of samples for each symbol | 30 | Show the number of samples for each symbol |
31 | 31 | ||
32 | --showcpuutilization:: | 32 | --show-cpu-utilization:: |
33 | Show sample percentage for different cpu modes. | 33 | Show sample percentage for different cpu modes. |
34 | 34 | ||
35 | -T:: | 35 | -T:: |
@@ -68,7 +68,7 @@ OPTIONS | |||
68 | --sort=:: | 68 | --sort=:: |
69 | Sort histogram entries by given key(s) - multiple keys can be specified | 69 | Sort histogram entries by given key(s) - multiple keys can be specified |
70 | in CSV format. Following sort keys are available: | 70 | in CSV format. Following sort keys are available: |
71 | pid, comm, dso, symbol, parent, cpu, srcline, weight, local_weight. | 71 | pid, comm, dso, symbol, parent, cpu, socket, srcline, weight, local_weight. |
72 | 72 | ||
73 | Each key has following meaning: | 73 | Each key has following meaning: |
74 | 74 | ||
@@ -79,6 +79,7 @@ OPTIONS | |||
79 | - parent: name of function matched to the parent regex filter. Unmatched | 79 | - parent: name of function matched to the parent regex filter. Unmatched |
80 | entries are displayed as "[other]". | 80 | entries are displayed as "[other]". |
81 | - cpu: cpu number the task ran at the time of sample | 81 | - cpu: cpu number the task ran at the time of sample |
82 | - socket: processor socket number the task ran at the time of sample | ||
82 | - srcline: filename and line number executed at the time of sample. The | 83 | - srcline: filename and line number executed at the time of sample. The |
83 | DWARF debugging info must be provided. | 84 | DWARF debugging info must be provided. |
84 | - srcfile: file name of the source file of the same. Requires dwarf | 85 | - srcfile: file name of the source file of the same. Requires dwarf |
@@ -168,30 +169,40 @@ OPTIONS | |||
168 | --dump-raw-trace:: | 169 | --dump-raw-trace:: |
169 | Dump raw trace in ASCII. | 170 | Dump raw trace in ASCII. |
170 | 171 | ||
171 | -g [type,min[,limit],order[,key][,branch]]:: | 172 | -g:: |
172 | --call-graph:: | 173 | --call-graph=<print_type,threshold[,print_limit],order,sort_key,branch>:: |
173 | Display call chains using type, min percent threshold, optional print | 174 | Display call chains using type, min percent threshold, print limit, |
174 | limit and order. | 175 | call order, sort key and branch. Note that ordering of parameters is not |
175 | type can be either: | 176 | fixed so any parement can be given in an arbitraty order. One exception |
177 | is the print_limit which should be preceded by threshold. | ||
178 | |||
179 | print_type can be either: | ||
176 | - flat: single column, linear exposure of call chains. | 180 | - flat: single column, linear exposure of call chains. |
177 | - graph: use a graph tree, displaying absolute overhead rates. | 181 | - graph: use a graph tree, displaying absolute overhead rates. (default) |
178 | - fractal: like graph, but displays relative rates. Each branch of | 182 | - fractal: like graph, but displays relative rates. Each branch of |
179 | the tree is considered as a new profiled object. + | 183 | the tree is considered as a new profiled object. |
184 | - none: disable call chain display. | ||
185 | |||
186 | threshold is a percentage value which specifies a minimum percent to be | ||
187 | included in the output call graph. Default is 0.5 (%). | ||
188 | |||
189 | print_limit is only applied when stdio interface is used. It's to limit | ||
190 | number of call graph entries in a single hist entry. Note that it needs | ||
191 | to be given after threshold (but not necessarily consecutive). | ||
192 | Default is 0 (unlimited). | ||
180 | 193 | ||
181 | order can be either: | 194 | order can be either: |
182 | - callee: callee based call graph. | 195 | - callee: callee based call graph. |
183 | - caller: inverted caller based call graph. | 196 | - caller: inverted caller based call graph. |
197 | Default is 'caller' when --children is used, otherwise 'callee'. | ||
184 | 198 | ||
185 | key can be: | 199 | sort_key can be: |
186 | - function: compare on functions | 200 | - function: compare on functions (default) |
187 | - address: compare on individual code addresses | 201 | - address: compare on individual code addresses |
188 | 202 | ||
189 | branch can be: | 203 | branch can be: |
190 | - branch: include last branch information in callgraph | 204 | - branch: include last branch information in callgraph when available. |
191 | when available. Usually more convenient to use --branch-history | 205 | Usually more convenient to use --branch-history for this. |
192 | for this. | ||
193 | |||
194 | Default: fractal,0.5,callee,function. | ||
195 | 206 | ||
196 | --children:: | 207 | --children:: |
197 | Accumulate callchain of children to parent entry so that then can | 208 | Accumulate callchain of children to parent entry so that then can |
@@ -204,6 +215,8 @@ OPTIONS | |||
204 | beyond the specified depth will be ignored. This is a trade-off | 215 | beyond the specified depth will be ignored. This is a trade-off |
205 | between information loss and faster processing especially for | 216 | between information loss and faster processing especially for |
206 | workloads that can have a very long callchain stack. | 217 | workloads that can have a very long callchain stack. |
218 | Note that when using the --itrace option the synthesized callchain size | ||
219 | will override this value if the synthesized callchain size is bigger. | ||
207 | 220 | ||
208 | Default: 127 | 221 | Default: 127 |
209 | 222 | ||
@@ -349,6 +362,9 @@ include::itrace.txt[] | |||
349 | This option extends the perf report to show reference callgraphs, | 362 | This option extends the perf report to show reference callgraphs, |
350 | which collected by reference event, in no callgraph event. | 363 | which collected by reference event, in no callgraph event. |
351 | 364 | ||
365 | --socket-filter:: | ||
366 | Only report the samples on the processor socket that match with this filter | ||
367 | |||
352 | include::callchain-overhead-calculation.txt[] | 368 | include::callchain-overhead-calculation.txt[] |
353 | 369 | ||
354 | SEE ALSO | 370 | SEE ALSO |
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index dc3ec783b7bd..382ddfb45d1d 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt | |||
@@ -112,11 +112,11 @@ OPTIONS | |||
112 | --debug-mode:: | 112 | --debug-mode:: |
113 | Do various checks like samples ordering and lost events. | 113 | Do various checks like samples ordering and lost events. |
114 | 114 | ||
115 | -f:: | 115 | -F:: |
116 | --fields:: | 116 | --fields:: |
117 | Comma separated list of fields to print. Options are: | 117 | Comma separated list of fields to print. Options are: |
118 | comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, | 118 | comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, |
119 | srcline, period, iregs, flags. | 119 | srcline, period, iregs, brstack, brstacksym, flags. |
120 | Field list can be prepended with the type, trace, sw or hw, | 120 | Field list can be prepended with the type, trace, sw or hw, |
121 | to indicate to which event type the field list applies. | 121 | to indicate to which event type the field list applies. |
122 | e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace | 122 | e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace |
@@ -175,6 +175,16 @@ OPTIONS | |||
175 | Finally, a user may not set fields to none for all event types. | 175 | Finally, a user may not set fields to none for all event types. |
176 | i.e., -f "" is not allowed. | 176 | i.e., -f "" is not allowed. |
177 | 177 | ||
178 | The brstack output includes branch related information with raw addresses using the | ||
179 | /v/v/v/v/ syntax in the following order: | ||
180 | FROM: branch source instruction | ||
181 | TO : branch target instruction | ||
182 | M/P/-: M=branch target mispredicted or branch direction was mispredicted, P=target predicted or direction predicted, -=not supported | ||
183 | X/- : X=branch inside a transactional region, -=not in transaction region or not supported | ||
184 | A/- : A=TSX abort entry, -=not aborted region or not supported | ||
185 | |||
186 | The brstacksym is identical to brstack, except that the FROM and TO addresses are printed in a symbolic form if possible. | ||
187 | |||
178 | -k:: | 188 | -k:: |
179 | --vmlinux=<file>:: | 189 | --vmlinux=<file>:: |
180 | vmlinux pathname | 190 | vmlinux pathname |
@@ -249,6 +259,9 @@ include::itrace.txt[] | |||
249 | --full-source-path:: | 259 | --full-source-path:: |
250 | Show the full path for source files for srcline output. | 260 | Show the full path for source files for srcline output. |
251 | 261 | ||
262 | --ns:: | ||
263 | Use 9 decimal places when displaying time (i.e. show the nanoseconds) | ||
264 | |||
252 | SEE ALSO | 265 | SEE ALSO |
253 | -------- | 266 | -------- |
254 | linkperf:perf-record[1], linkperf:perf-script-perl[1], | 267 | linkperf:perf-record[1], linkperf:perf-script-perl[1], |
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 47469abdcc1c..4e074a660826 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt | |||
@@ -128,8 +128,9 @@ perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' -- m | |||
128 | 128 | ||
129 | -I msecs:: | 129 | -I msecs:: |
130 | --interval-print msecs:: | 130 | --interval-print msecs:: |
131 | Print count deltas every N milliseconds (minimum: 100ms) | 131 | Print count deltas every N milliseconds (minimum: 10ms) |
132 | example: perf stat -I 1000 -e cycles -a sleep 5 | 132 | The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution. |
133 | example: 'perf stat -I 1000 -e cycles -a sleep 5' | ||
133 | 134 | ||
134 | --per-socket:: | 135 | --per-socket:: |
135 | Aggregate counts per processor socket for system-wide mode measurements. This | 136 | Aggregate counts per processor socket for system-wide mode measurements. This |
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index f6a23eb294e7..556cec09bf50 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
@@ -160,9 +160,10 @@ Default is to monitor all CPUS. | |||
160 | -g:: | 160 | -g:: |
161 | Enables call-graph (stack chain/backtrace) recording. | 161 | Enables call-graph (stack chain/backtrace) recording. |
162 | 162 | ||
163 | --call-graph:: | 163 | --call-graph [mode,type,min[,limit],order[,key][,branch]]:: |
164 | Setup and enable call-graph (stack chain/backtrace) recording, | 164 | Setup and enable call-graph (stack chain/backtrace) recording, |
165 | implies -g. | 165 | implies -g. See `--call-graph` section in perf-record and |
166 | perf-report man pages for details. | ||
166 | 167 | ||
167 | --children:: | 168 | --children:: |
168 | Accumulate callchain of children to parent entry so that then can | 169 | Accumulate callchain of children to parent entry so that then can |
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt index 2b131776363e..864e37597252 100644 --- a/tools/perf/Documentation/perf.txt +++ b/tools/perf/Documentation/perf.txt | |||
@@ -27,6 +27,14 @@ OPTIONS | |||
27 | Setup buildid cache directory. It has higher priority than | 27 | Setup buildid cache directory. It has higher priority than |
28 | buildid.dir config file option. | 28 | buildid.dir config file option. |
29 | 29 | ||
30 | -v:: | ||
31 | --version:: | ||
32 | Display perf version. | ||
33 | |||
34 | -h:: | ||
35 | --help:: | ||
36 | Run perf help command. | ||
37 | |||
30 | DESCRIPTION | 38 | DESCRIPTION |
31 | ----------- | 39 | ----------- |
32 | Performance counters for Linux are a new kernel-based subsystem | 40 | Performance counters for Linux are a new kernel-based subsystem |
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index af009bd6e6b7..39c38cb45b00 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
@@ -17,6 +17,7 @@ tools/build | |||
17 | tools/arch/x86/include/asm/atomic.h | 17 | tools/arch/x86/include/asm/atomic.h |
18 | tools/arch/x86/include/asm/rmwcc.h | 18 | tools/arch/x86/include/asm/rmwcc.h |
19 | tools/lib/traceevent | 19 | tools/lib/traceevent |
20 | tools/lib/bpf | ||
20 | tools/lib/api | 21 | tools/lib/api |
21 | tools/lib/bpf | 22 | tools/lib/bpf |
22 | tools/lib/hweight.c | 23 | tools/lib/hweight.c |
@@ -41,6 +42,7 @@ tools/include/asm-generic/bitops.h | |||
41 | tools/include/linux/atomic.h | 42 | tools/include/linux/atomic.h |
42 | tools/include/linux/bitops.h | 43 | tools/include/linux/bitops.h |
43 | tools/include/linux/compiler.h | 44 | tools/include/linux/compiler.h |
45 | tools/include/linux/filter.h | ||
44 | tools/include/linux/hash.h | 46 | tools/include/linux/hash.h |
45 | tools/include/linux/kernel.h | 47 | tools/include/linux/kernel.h |
46 | tools/include/linux/list.h | 48 | tools/include/linux/list.h |
@@ -49,6 +51,7 @@ tools/include/linux/poison.h | |||
49 | tools/include/linux/rbtree.h | 51 | tools/include/linux/rbtree.h |
50 | tools/include/linux/rbtree_augmented.h | 52 | tools/include/linux/rbtree_augmented.h |
51 | tools/include/linux/types.h | 53 | tools/include/linux/types.h |
54 | tools/include/linux/err.h | ||
52 | include/asm-generic/bitops/arch_hweight.h | 55 | include/asm-generic/bitops/arch_hweight.h |
53 | include/asm-generic/bitops/const_hweight.h | 56 | include/asm-generic/bitops/const_hweight.h |
54 | include/asm-generic/bitops/fls64.h | 57 | include/asm-generic/bitops/fls64.h |
@@ -67,6 +70,8 @@ arch/*/lib/memset*.S | |||
67 | include/linux/poison.h | 70 | include/linux/poison.h |
68 | include/linux/hw_breakpoint.h | 71 | include/linux/hw_breakpoint.h |
69 | include/uapi/linux/perf_event.h | 72 | include/uapi/linux/perf_event.h |
73 | include/uapi/linux/bpf.h | ||
74 | include/uapi/linux/bpf_common.h | ||
70 | include/uapi/linux/const.h | 75 | include/uapi/linux/const.h |
71 | include/uapi/linux/swab.h | 76 | include/uapi/linux/swab.h |
72 | include/uapi/linux/hw_breakpoint.h | 77 | include/uapi/linux/hw_breakpoint.h |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index d9863cb96f59..0d19d5447d6c 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -75,6 +75,8 @@ include config/utilities.mak | |||
75 | # Define NO_LZMA if you do not want to support compressed (xz) kernel modules | 75 | # Define NO_LZMA if you do not want to support compressed (xz) kernel modules |
76 | # | 76 | # |
77 | # Define NO_AUXTRACE if you do not want AUX area tracing support | 77 | # Define NO_AUXTRACE if you do not want AUX area tracing support |
78 | # | ||
79 | # Define NO_LIBBPF if you do not want BPF support | ||
78 | 80 | ||
79 | # As per kernel Makefile, avoid funny character set dependencies | 81 | # As per kernel Makefile, avoid funny character set dependencies |
80 | unexport LC_ALL | 82 | unexport LC_ALL |
@@ -145,6 +147,7 @@ AWK = awk | |||
145 | 147 | ||
146 | LIB_DIR = $(srctree)/tools/lib/api/ | 148 | LIB_DIR = $(srctree)/tools/lib/api/ |
147 | TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ | 149 | TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ |
150 | BPF_DIR = $(srctree)/tools/lib/bpf/ | ||
148 | 151 | ||
149 | # include config/Makefile by default and rule out | 152 | # include config/Makefile by default and rule out |
150 | # non-config cases | 153 | # non-config cases |
@@ -180,6 +183,7 @@ strip-libs = $(filter-out -l%,$(1)) | |||
180 | 183 | ||
181 | ifneq ($(OUTPUT),) | 184 | ifneq ($(OUTPUT),) |
182 | TE_PATH=$(OUTPUT) | 185 | TE_PATH=$(OUTPUT) |
186 | BPF_PATH=$(OUTPUT) | ||
183 | ifneq ($(subdir),) | 187 | ifneq ($(subdir),) |
184 | LIB_PATH=$(OUTPUT)/../lib/api/ | 188 | LIB_PATH=$(OUTPUT)/../lib/api/ |
185 | else | 189 | else |
@@ -188,6 +192,7 @@ endif | |||
188 | else | 192 | else |
189 | TE_PATH=$(TRACE_EVENT_DIR) | 193 | TE_PATH=$(TRACE_EVENT_DIR) |
190 | LIB_PATH=$(LIB_DIR) | 194 | LIB_PATH=$(LIB_DIR) |
195 | BPF_PATH=$(BPF_DIR) | ||
191 | endif | 196 | endif |
192 | 197 | ||
193 | LIBTRACEEVENT = $(TE_PATH)libtraceevent.a | 198 | LIBTRACEEVENT = $(TE_PATH)libtraceevent.a |
@@ -199,6 +204,8 @@ LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYN | |||
199 | LIBAPI = $(LIB_PATH)libapi.a | 204 | LIBAPI = $(LIB_PATH)libapi.a |
200 | export LIBAPI | 205 | export LIBAPI |
201 | 206 | ||
207 | LIBBPF = $(BPF_PATH)libbpf.a | ||
208 | |||
202 | # python extension build directories | 209 | # python extension build directories |
203 | PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ | 210 | PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ |
204 | PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ | 211 | PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ |
@@ -251,6 +258,9 @@ export PERL_PATH | |||
251 | LIB_FILE=$(OUTPUT)libperf.a | 258 | LIB_FILE=$(OUTPUT)libperf.a |
252 | 259 | ||
253 | PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT) | 260 | PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT) |
261 | ifndef NO_LIBBPF | ||
262 | PERFLIBS += $(LIBBPF) | ||
263 | endif | ||
254 | 264 | ||
255 | # We choose to avoid "if .. else if .. else .. endif endif" | 265 | # We choose to avoid "if .. else if .. else .. endif endif" |
256 | # because maintaining the nesting to match is a pain. If | 266 | # because maintaining the nesting to match is a pain. If |
@@ -297,16 +307,16 @@ strip: $(PROGRAMS) $(OUTPUT)perf | |||
297 | PERF_IN := $(OUTPUT)perf-in.o | 307 | PERF_IN := $(OUTPUT)perf-in.o |
298 | 308 | ||
299 | export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK | 309 | export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK |
300 | build := -f $(srctree)/tools/build/Makefile.build dir=. obj | 310 | include $(srctree)/tools/build/Makefile.include |
301 | 311 | ||
302 | $(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE | 312 | $(PERF_IN): prepare FORCE |
303 | $(Q)$(MAKE) $(build)=perf | 313 | $(Q)$(MAKE) $(build)=perf |
304 | 314 | ||
305 | $(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) | 315 | $(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) |
306 | $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \ | 316 | $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \ |
307 | $(PERF_IN) $(LIBS) -o $@ | 317 | $(PERF_IN) $(LIBS) -o $@ |
308 | 318 | ||
309 | $(GTK_IN): FORCE | 319 | $(GTK_IN): fixdep FORCE |
310 | $(Q)$(MAKE) $(build)=gtk | 320 | $(Q)$(MAKE) $(build)=gtk |
311 | 321 | ||
312 | $(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS) | 322 | $(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS) |
@@ -349,27 +359,27 @@ endif | |||
349 | __build-dir = $(subst $(OUTPUT),,$(dir $@)) | 359 | __build-dir = $(subst $(OUTPUT),,$(dir $@)) |
350 | build-dir = $(if $(__build-dir),$(__build-dir),.) | 360 | build-dir = $(if $(__build-dir),$(__build-dir),.) |
351 | 361 | ||
352 | single_dep: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h | 362 | prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep |
353 | 363 | ||
354 | $(OUTPUT)%.o: %.c single_dep FORCE | 364 | $(OUTPUT)%.o: %.c prepare FORCE |
355 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ | 365 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ |
356 | 366 | ||
357 | $(OUTPUT)%.i: %.c single_dep FORCE | 367 | $(OUTPUT)%.i: %.c prepare FORCE |
358 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ | 368 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ |
359 | 369 | ||
360 | $(OUTPUT)%.s: %.c single_dep FORCE | 370 | $(OUTPUT)%.s: %.c prepare FORCE |
361 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ | 371 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ |
362 | 372 | ||
363 | $(OUTPUT)%-bison.o: %.c single_dep FORCE | 373 | $(OUTPUT)%-bison.o: %.c prepare FORCE |
364 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ | 374 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ |
365 | 375 | ||
366 | $(OUTPUT)%-flex.o: %.c single_dep FORCE | 376 | $(OUTPUT)%-flex.o: %.c prepare FORCE |
367 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ | 377 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ |
368 | 378 | ||
369 | $(OUTPUT)%.o: %.S single_dep FORCE | 379 | $(OUTPUT)%.o: %.S prepare FORCE |
370 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ | 380 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ |
371 | 381 | ||
372 | $(OUTPUT)%.i: %.S single_dep FORCE | 382 | $(OUTPUT)%.i: %.S prepare FORCE |
373 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ | 383 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ |
374 | 384 | ||
375 | $(OUTPUT)perf-%: %.o $(PERFLIBS) | 385 | $(OUTPUT)perf-%: %.o $(PERFLIBS) |
@@ -389,7 +399,7 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h) | |||
389 | 399 | ||
390 | LIBPERF_IN := $(OUTPUT)libperf-in.o | 400 | LIBPERF_IN := $(OUTPUT)libperf-in.o |
391 | 401 | ||
392 | $(LIBPERF_IN): FORCE | 402 | $(LIBPERF_IN): fixdep FORCE |
393 | $(Q)$(MAKE) $(build)=libperf | 403 | $(Q)$(MAKE) $(build)=libperf |
394 | 404 | ||
395 | $(LIB_FILE): $(LIBPERF_IN) | 405 | $(LIB_FILE): $(LIBPERF_IN) |
@@ -397,10 +407,10 @@ $(LIB_FILE): $(LIBPERF_IN) | |||
397 | 407 | ||
398 | LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) | 408 | LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) |
399 | 409 | ||
400 | $(LIBTRACEEVENT): FORCE | 410 | $(LIBTRACEEVENT): fixdep FORCE |
401 | $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a | 411 | $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a |
402 | 412 | ||
403 | libtraceevent_plugins: FORCE | 413 | libtraceevent_plugins: fixdep FORCE |
404 | $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins | 414 | $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) plugins |
405 | 415 | ||
406 | $(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins | 416 | $(LIBTRACEEVENT_DYNAMIC_LIST): libtraceevent_plugins |
@@ -413,13 +423,20 @@ $(LIBTRACEEVENT)-clean: | |||
413 | install-traceevent-plugins: $(LIBTRACEEVENT) | 423 | install-traceevent-plugins: $(LIBTRACEEVENT) |
414 | $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins | 424 | $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins |
415 | 425 | ||
416 | $(LIBAPI): FORCE | 426 | $(LIBAPI): fixdep FORCE |
417 | $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a | 427 | $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a |
418 | 428 | ||
419 | $(LIBAPI)-clean: | 429 | $(LIBAPI)-clean: |
420 | $(call QUIET_CLEAN, libapi) | 430 | $(call QUIET_CLEAN, libapi) |
421 | $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null | 431 | $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null |
422 | 432 | ||
433 | $(LIBBPF): fixdep FORCE | ||
434 | $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a | ||
435 | |||
436 | $(LIBBPF)-clean: | ||
437 | $(call QUIET_CLEAN, libbpf) | ||
438 | $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) clean >/dev/null | ||
439 | |||
423 | help: | 440 | help: |
424 | @echo 'Perf make targets:' | 441 | @echo 'Perf make targets:' |
425 | @echo ' doc - make *all* documentation (see below)' | 442 | @echo ' doc - make *all* documentation (see below)' |
@@ -459,7 +476,7 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html | |||
459 | $(DOC_TARGETS): | 476 | $(DOC_TARGETS): |
460 | $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all) | 477 | $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all) |
461 | 478 | ||
462 | TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol | 479 | TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include ../lib/bpf |
463 | TAG_FILES= ../../include/uapi/linux/perf_event.h | 480 | TAG_FILES= ../../include/uapi/linux/perf_event.h |
464 | 481 | ||
465 | TAGS: | 482 | TAGS: |
@@ -567,7 +584,7 @@ config-clean: | |||
567 | $(call QUIET_CLEAN, config) | 584 | $(call QUIET_CLEAN, config) |
568 | $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null | 585 | $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null |
569 | 586 | ||
570 | clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean | 587 | clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean config-clean |
571 | $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) | 588 | $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) |
572 | $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete | 589 | $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete |
573 | $(Q)$(RM) $(OUTPUT).config-detected | 590 | $(Q)$(RM) $(OUTPUT).config-detected |
@@ -591,6 +608,6 @@ FORCE: | |||
591 | 608 | ||
592 | .PHONY: all install clean config-clean strip install-gtk | 609 | .PHONY: all install clean config-clean strip install-gtk |
593 | .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell | 610 | .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell |
594 | .PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep | 611 | .PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare |
595 | .PHONY: libtraceevent_plugins | 612 | .PHONY: libtraceevent_plugins |
596 | 613 | ||
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index b00dfd92ea73..e83c8ce24303 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c | |||
@@ -128,9 +128,8 @@ static const char *normalize_arch(char *arch) | |||
128 | return arch; | 128 | return arch; |
129 | } | 129 | } |
130 | 130 | ||
131 | static int perf_session_env__lookup_binutils_path(struct perf_env *env, | 131 | static int perf_env__lookup_binutils_path(struct perf_env *env, |
132 | const char *name, | 132 | const char *name, const char **path) |
133 | const char **path) | ||
134 | { | 133 | { |
135 | int idx; | 134 | int idx; |
136 | const char *arch, *cross_env; | 135 | const char *arch, *cross_env; |
@@ -206,7 +205,7 @@ out_error: | |||
206 | return -1; | 205 | return -1; |
207 | } | 206 | } |
208 | 207 | ||
209 | int perf_session_env__lookup_objdump(struct perf_env *env) | 208 | int perf_env__lookup_objdump(struct perf_env *env) |
210 | { | 209 | { |
211 | /* | 210 | /* |
212 | * For live mode, env->arch will be NULL and we can use | 211 | * For live mode, env->arch will be NULL and we can use |
@@ -215,6 +214,5 @@ int perf_session_env__lookup_objdump(struct perf_env *env) | |||
215 | if (env->arch == NULL) | 214 | if (env->arch == NULL) |
216 | return 0; | 215 | return 0; |
217 | 216 | ||
218 | return perf_session_env__lookup_binutils_path(env, "objdump", | 217 | return perf_env__lookup_binutils_path(env, "objdump", &objdump_path); |
219 | &objdump_path); | ||
220 | } | 218 | } |
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h index 20176df69fc8..7529cfb143ce 100644 --- a/tools/perf/arch/common.h +++ b/tools/perf/arch/common.h | |||
@@ -1,10 +1,10 @@ | |||
1 | #ifndef ARCH_PERF_COMMON_H | 1 | #ifndef ARCH_PERF_COMMON_H |
2 | #define ARCH_PERF_COMMON_H | 2 | #define ARCH_PERF_COMMON_H |
3 | 3 | ||
4 | #include "../util/session.h" | 4 | #include "../util/env.h" |
5 | 5 | ||
6 | extern const char *objdump_path; | 6 | extern const char *objdump_path; |
7 | 7 | ||
8 | int perf_session_env__lookup_objdump(struct perf_env *env); | 8 | int perf_env__lookup_objdump(struct perf_env *env); |
9 | 9 | ||
10 | #endif /* ARCH_PERF_COMMON_H */ | 10 | #endif /* ARCH_PERF_COMMON_H */ |
diff --git a/tools/perf/arch/x86/Build b/tools/perf/arch/x86/Build index 41bf61da476a..db52fa22d3a1 100644 --- a/tools/perf/arch/x86/Build +++ b/tools/perf/arch/x86/Build | |||
@@ -1,2 +1,2 @@ | |||
1 | libperf-y += util/ | 1 | libperf-y += util/ |
2 | libperf-$(CONFIG_DWARF_UNWIND) += tests/ | 2 | libperf-y += tests/ |
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index 21322e0385b8..09ba923debe8 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile | |||
@@ -2,3 +2,4 @@ ifndef NO_DWARF | |||
2 | PERF_HAVE_DWARF_REGS := 1 | 2 | PERF_HAVE_DWARF_REGS := 1 |
3 | endif | 3 | endif |
4 | HAVE_KVM_STAT_SUPPORT := 1 | 4 | HAVE_KVM_STAT_SUPPORT := 1 |
5 | PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 | ||
diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h new file mode 100644 index 000000000000..7ed00f4b0908 --- /dev/null +++ b/tools/perf/arch/x86/include/arch-tests.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #ifndef ARCH_TESTS_H | ||
2 | #define ARCH_TESTS_H | ||
3 | |||
4 | /* Tests */ | ||
5 | int test__rdpmc(void); | ||
6 | int test__perf_time_to_tsc(void); | ||
7 | int test__insn_x86(void); | ||
8 | int test__intel_cqm_count_nmi_context(void); | ||
9 | |||
10 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
11 | struct thread; | ||
12 | struct perf_sample; | ||
13 | int test__arch_unwind_sample(struct perf_sample *sample, | ||
14 | struct thread *thread); | ||
15 | #endif | ||
16 | |||
17 | extern struct test arch_tests[]; | ||
18 | |||
19 | #endif | ||
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build index b30eff9bcc83..cbb7e978166b 100644 --- a/tools/perf/arch/x86/tests/Build +++ b/tools/perf/arch/x86/tests/Build | |||
@@ -1,2 +1,8 @@ | |||
1 | libperf-y += regs_load.o | 1 | libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o |
2 | libperf-y += dwarf-unwind.o | 2 | libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o |
3 | |||
4 | libperf-y += arch-tests.o | ||
5 | libperf-y += rdpmc.o | ||
6 | libperf-y += perf-time-to-tsc.o | ||
7 | libperf-$(CONFIG_AUXTRACE) += insn-x86.o | ||
8 | libperf-y += intel-cqm.o | ||
diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c new file mode 100644 index 000000000000..2218cb64f840 --- /dev/null +++ b/tools/perf/arch/x86/tests/arch-tests.c | |||
@@ -0,0 +1,34 @@ | |||
1 | #include <string.h> | ||
2 | #include "tests/tests.h" | ||
3 | #include "arch-tests.h" | ||
4 | |||
5 | struct test arch_tests[] = { | ||
6 | { | ||
7 | .desc = "x86 rdpmc test", | ||
8 | .func = test__rdpmc, | ||
9 | }, | ||
10 | { | ||
11 | .desc = "Test converting perf time to TSC", | ||
12 | .func = test__perf_time_to_tsc, | ||
13 | }, | ||
14 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
15 | { | ||
16 | .desc = "Test dwarf unwind", | ||
17 | .func = test__dwarf_unwind, | ||
18 | }, | ||
19 | #endif | ||
20 | #ifdef HAVE_AUXTRACE_SUPPORT | ||
21 | { | ||
22 | .desc = "Test x86 instruction decoder - new instructions", | ||
23 | .func = test__insn_x86, | ||
24 | }, | ||
25 | #endif | ||
26 | { | ||
27 | .desc = "Test intel cqm nmi context read", | ||
28 | .func = test__intel_cqm_count_nmi_context, | ||
29 | }, | ||
30 | { | ||
31 | .func = NULL, | ||
32 | }, | ||
33 | |||
34 | }; | ||
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c index d8bbf7ad1681..7f209ce827bf 100644 --- a/tools/perf/arch/x86/tests/dwarf-unwind.c +++ b/tools/perf/arch/x86/tests/dwarf-unwind.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "event.h" | 5 | #include "event.h" |
6 | #include "debug.h" | 6 | #include "debug.h" |
7 | #include "tests/tests.h" | 7 | #include "tests/tests.h" |
8 | #include "arch-tests.h" | ||
8 | 9 | ||
9 | #define STACK_SIZE 8192 | 10 | #define STACK_SIZE 8192 |
10 | 11 | ||
diff --git a/tools/perf/arch/x86/tests/gen-insn-x86-dat.awk b/tools/perf/arch/x86/tests/gen-insn-x86-dat.awk new file mode 100644 index 000000000000..a21454835cd4 --- /dev/null +++ b/tools/perf/arch/x86/tests/gen-insn-x86-dat.awk | |||
@@ -0,0 +1,75 @@ | |||
1 | #!/bin/awk -f | ||
2 | # gen-insn-x86-dat.awk: script to convert data for the insn-x86 test | ||
3 | # Copyright (c) 2015, Intel Corporation. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify it | ||
6 | # under the terms and conditions of the GNU General Public License, | ||
7 | # version 2, as published by the Free Software Foundation. | ||
8 | # | ||
9 | # This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | # more details. | ||
13 | |||
14 | BEGIN { | ||
15 | print "/*" | ||
16 | print " * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk" | ||
17 | print " * from insn-x86-dat-src.c for inclusion by insn-x86.c" | ||
18 | print " * Do not change this code." | ||
19 | print "*/\n" | ||
20 | op = "" | ||
21 | branch = "" | ||
22 | rel = 0 | ||
23 | going = 0 | ||
24 | } | ||
25 | |||
26 | / Start here / { | ||
27 | going = 1 | ||
28 | } | ||
29 | |||
30 | / Stop here / { | ||
31 | going = 0 | ||
32 | } | ||
33 | |||
34 | /^\s*[0-9a-fA-F]+\:/ { | ||
35 | if (going) { | ||
36 | colon_pos = index($0, ":") | ||
37 | useful_line = substr($0, colon_pos + 1) | ||
38 | first_pos = match(useful_line, "[0-9a-fA-F]") | ||
39 | useful_line = substr(useful_line, first_pos) | ||
40 | gsub("\t", "\\t", useful_line) | ||
41 | printf "{{" | ||
42 | len = 0 | ||
43 | for (i = 2; i <= NF; i++) { | ||
44 | if (match($i, "^[0-9a-fA-F][0-9a-fA-F]$")) { | ||
45 | printf "0x%s, ", $i | ||
46 | len += 1 | ||
47 | } else { | ||
48 | break | ||
49 | } | ||
50 | } | ||
51 | printf "}, %d, %s, \"%s\", \"%s\",", len, rel, op, branch | ||
52 | printf "\n\"%s\",},\n", useful_line | ||
53 | op = "" | ||
54 | branch = "" | ||
55 | rel = 0 | ||
56 | } | ||
57 | } | ||
58 | |||
59 | / Expecting: / { | ||
60 | expecting_str = " Expecting: " | ||
61 | expecting_len = length(expecting_str) | ||
62 | expecting_pos = index($0, expecting_str) | ||
63 | useful_line = substr($0, expecting_pos + expecting_len) | ||
64 | for (i = 1; i <= NF; i++) { | ||
65 | if ($i == "Expecting:") { | ||
66 | i++ | ||
67 | op = $i | ||
68 | i++ | ||
69 | branch = $i | ||
70 | i++ | ||
71 | rel = $i | ||
72 | break | ||
73 | } | ||
74 | } | ||
75 | } | ||
diff --git a/tools/perf/arch/x86/tests/gen-insn-x86-dat.sh b/tools/perf/arch/x86/tests/gen-insn-x86-dat.sh new file mode 100755 index 000000000000..2d4ef94cff98 --- /dev/null +++ b/tools/perf/arch/x86/tests/gen-insn-x86-dat.sh | |||
@@ -0,0 +1,43 @@ | |||
1 | #!/bin/sh | ||
2 | # gen-insn-x86-dat: generate data for the insn-x86 test | ||
3 | # Copyright (c) 2015, Intel Corporation. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify it | ||
6 | # under the terms and conditions of the GNU General Public License, | ||
7 | # version 2, as published by the Free Software Foundation. | ||
8 | # | ||
9 | # This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | # more details. | ||
13 | |||
14 | set -e | ||
15 | |||
16 | if [ "$(uname -m)" != "x86_64" ]; then | ||
17 | echo "ERROR: This script only works on x86_64" | ||
18 | exit 1 | ||
19 | fi | ||
20 | |||
21 | cd $(dirname $0) | ||
22 | |||
23 | trap 'echo "Might need a more recent version of binutils"' EXIT | ||
24 | |||
25 | echo "Compiling insn-x86-dat-src.c to 64-bit object" | ||
26 | |||
27 | gcc -g -c insn-x86-dat-src.c | ||
28 | |||
29 | objdump -dSw insn-x86-dat-src.o | awk -f gen-insn-x86-dat.awk > insn-x86-dat-64.c | ||
30 | |||
31 | rm -f insn-x86-dat-src.o | ||
32 | |||
33 | echo "Compiling insn-x86-dat-src.c to 32-bit object" | ||
34 | |||
35 | gcc -g -c -m32 insn-x86-dat-src.c | ||
36 | |||
37 | objdump -dSw insn-x86-dat-src.o | awk -f gen-insn-x86-dat.awk > insn-x86-dat-32.c | ||
38 | |||
39 | rm -f insn-x86-dat-src.o | ||
40 | |||
41 | trap - EXIT | ||
42 | |||
43 | echo "Done (use git diff to see the changes)" | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-32.c b/tools/perf/arch/x86/tests/insn-x86-dat-32.c new file mode 100644 index 000000000000..3b491cfe204e --- /dev/null +++ b/tools/perf/arch/x86/tests/insn-x86-dat-32.c | |||
@@ -0,0 +1,658 @@ | |||
1 | /* | ||
2 | * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk | ||
3 | * from insn-x86-dat-src.c for inclusion by insn-x86.c | ||
4 | * Do not change this code. | ||
5 | */ | ||
6 | |||
7 | {{0x0f, 0x31, }, 2, 0, "", "", | ||
8 | "0f 31 \trdtsc ",}, | ||
9 | {{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", | ||
10 | "f3 0f 1b 00 \tbndmk (%eax),%bnd0",}, | ||
11 | {{0xf3, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
12 | "f3 0f 1b 05 78 56 34 12 \tbndmk 0x12345678,%bnd0",}, | ||
13 | {{0xf3, 0x0f, 0x1b, 0x18, }, 4, 0, "", "", | ||
14 | "f3 0f 1b 18 \tbndmk (%eax),%bnd3",}, | ||
15 | {{0xf3, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "", | ||
16 | "f3 0f 1b 04 01 \tbndmk (%ecx,%eax,1),%bnd0",}, | ||
17 | {{0xf3, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
18 | "f3 0f 1b 04 05 78 56 34 12 \tbndmk 0x12345678(,%eax,1),%bnd0",}, | ||
19 | {{0xf3, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "", | ||
20 | "f3 0f 1b 04 08 \tbndmk (%eax,%ecx,1),%bnd0",}, | ||
21 | {{0xf3, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "", | ||
22 | "f3 0f 1b 04 c8 \tbndmk (%eax,%ecx,8),%bnd0",}, | ||
23 | {{0xf3, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "", | ||
24 | "f3 0f 1b 40 12 \tbndmk 0x12(%eax),%bnd0",}, | ||
25 | {{0xf3, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "", | ||
26 | "f3 0f 1b 45 12 \tbndmk 0x12(%ebp),%bnd0",}, | ||
27 | {{0xf3, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
28 | "f3 0f 1b 44 01 12 \tbndmk 0x12(%ecx,%eax,1),%bnd0",}, | ||
29 | {{0xf3, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
30 | "f3 0f 1b 44 05 12 \tbndmk 0x12(%ebp,%eax,1),%bnd0",}, | ||
31 | {{0xf3, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
32 | "f3 0f 1b 44 08 12 \tbndmk 0x12(%eax,%ecx,1),%bnd0",}, | ||
33 | {{0xf3, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
34 | "f3 0f 1b 44 c8 12 \tbndmk 0x12(%eax,%ecx,8),%bnd0",}, | ||
35 | {{0xf3, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
36 | "f3 0f 1b 80 78 56 34 12 \tbndmk 0x12345678(%eax),%bnd0",}, | ||
37 | {{0xf3, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
38 | "f3 0f 1b 85 78 56 34 12 \tbndmk 0x12345678(%ebp),%bnd0",}, | ||
39 | {{0xf3, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
40 | "f3 0f 1b 84 01 78 56 34 12 \tbndmk 0x12345678(%ecx,%eax,1),%bnd0",}, | ||
41 | {{0xf3, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
42 | "f3 0f 1b 84 05 78 56 34 12 \tbndmk 0x12345678(%ebp,%eax,1),%bnd0",}, | ||
43 | {{0xf3, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
44 | "f3 0f 1b 84 08 78 56 34 12 \tbndmk 0x12345678(%eax,%ecx,1),%bnd0",}, | ||
45 | {{0xf3, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
46 | "f3 0f 1b 84 c8 78 56 34 12 \tbndmk 0x12345678(%eax,%ecx,8),%bnd0",}, | ||
47 | {{0xf3, 0x0f, 0x1a, 0x00, }, 4, 0, "", "", | ||
48 | "f3 0f 1a 00 \tbndcl (%eax),%bnd0",}, | ||
49 | {{0xf3, 0x0f, 0x1a, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
50 | "f3 0f 1a 05 78 56 34 12 \tbndcl 0x12345678,%bnd0",}, | ||
51 | {{0xf3, 0x0f, 0x1a, 0x18, }, 4, 0, "", "", | ||
52 | "f3 0f 1a 18 \tbndcl (%eax),%bnd3",}, | ||
53 | {{0xf3, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "", | ||
54 | "f3 0f 1a 04 01 \tbndcl (%ecx,%eax,1),%bnd0",}, | ||
55 | {{0xf3, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
56 | "f3 0f 1a 04 05 78 56 34 12 \tbndcl 0x12345678(,%eax,1),%bnd0",}, | ||
57 | {{0xf3, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "", | ||
58 | "f3 0f 1a 04 08 \tbndcl (%eax,%ecx,1),%bnd0",}, | ||
59 | {{0xf3, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "", | ||
60 | "f3 0f 1a 04 c8 \tbndcl (%eax,%ecx,8),%bnd0",}, | ||
61 | {{0xf3, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "", | ||
62 | "f3 0f 1a 40 12 \tbndcl 0x12(%eax),%bnd0",}, | ||
63 | {{0xf3, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "", | ||
64 | "f3 0f 1a 45 12 \tbndcl 0x12(%ebp),%bnd0",}, | ||
65 | {{0xf3, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
66 | "f3 0f 1a 44 01 12 \tbndcl 0x12(%ecx,%eax,1),%bnd0",}, | ||
67 | {{0xf3, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
68 | "f3 0f 1a 44 05 12 \tbndcl 0x12(%ebp,%eax,1),%bnd0",}, | ||
69 | {{0xf3, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
70 | "f3 0f 1a 44 08 12 \tbndcl 0x12(%eax,%ecx,1),%bnd0",}, | ||
71 | {{0xf3, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
72 | "f3 0f 1a 44 c8 12 \tbndcl 0x12(%eax,%ecx,8),%bnd0",}, | ||
73 | {{0xf3, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
74 | "f3 0f 1a 80 78 56 34 12 \tbndcl 0x12345678(%eax),%bnd0",}, | ||
75 | {{0xf3, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
76 | "f3 0f 1a 85 78 56 34 12 \tbndcl 0x12345678(%ebp),%bnd0",}, | ||
77 | {{0xf3, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
78 | "f3 0f 1a 84 01 78 56 34 12 \tbndcl 0x12345678(%ecx,%eax,1),%bnd0",}, | ||
79 | {{0xf3, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
80 | "f3 0f 1a 84 05 78 56 34 12 \tbndcl 0x12345678(%ebp,%eax,1),%bnd0",}, | ||
81 | {{0xf3, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
82 | "f3 0f 1a 84 08 78 56 34 12 \tbndcl 0x12345678(%eax,%ecx,1),%bnd0",}, | ||
83 | {{0xf3, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
84 | "f3 0f 1a 84 c8 78 56 34 12 \tbndcl 0x12345678(%eax,%ecx,8),%bnd0",}, | ||
85 | {{0xf3, 0x0f, 0x1a, 0xc0, }, 4, 0, "", "", | ||
86 | "f3 0f 1a c0 \tbndcl %eax,%bnd0",}, | ||
87 | {{0xf2, 0x0f, 0x1a, 0x00, }, 4, 0, "", "", | ||
88 | "f2 0f 1a 00 \tbndcu (%eax),%bnd0",}, | ||
89 | {{0xf2, 0x0f, 0x1a, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
90 | "f2 0f 1a 05 78 56 34 12 \tbndcu 0x12345678,%bnd0",}, | ||
91 | {{0xf2, 0x0f, 0x1a, 0x18, }, 4, 0, "", "", | ||
92 | "f2 0f 1a 18 \tbndcu (%eax),%bnd3",}, | ||
93 | {{0xf2, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "", | ||
94 | "f2 0f 1a 04 01 \tbndcu (%ecx,%eax,1),%bnd0",}, | ||
95 | {{0xf2, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
96 | "f2 0f 1a 04 05 78 56 34 12 \tbndcu 0x12345678(,%eax,1),%bnd0",}, | ||
97 | {{0xf2, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "", | ||
98 | "f2 0f 1a 04 08 \tbndcu (%eax,%ecx,1),%bnd0",}, | ||
99 | {{0xf2, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "", | ||
100 | "f2 0f 1a 04 c8 \tbndcu (%eax,%ecx,8),%bnd0",}, | ||
101 | {{0xf2, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "", | ||
102 | "f2 0f 1a 40 12 \tbndcu 0x12(%eax),%bnd0",}, | ||
103 | {{0xf2, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "", | ||
104 | "f2 0f 1a 45 12 \tbndcu 0x12(%ebp),%bnd0",}, | ||
105 | {{0xf2, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
106 | "f2 0f 1a 44 01 12 \tbndcu 0x12(%ecx,%eax,1),%bnd0",}, | ||
107 | {{0xf2, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
108 | "f2 0f 1a 44 05 12 \tbndcu 0x12(%ebp,%eax,1),%bnd0",}, | ||
109 | {{0xf2, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
110 | "f2 0f 1a 44 08 12 \tbndcu 0x12(%eax,%ecx,1),%bnd0",}, | ||
111 | {{0xf2, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
112 | "f2 0f 1a 44 c8 12 \tbndcu 0x12(%eax,%ecx,8),%bnd0",}, | ||
113 | {{0xf2, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
114 | "f2 0f 1a 80 78 56 34 12 \tbndcu 0x12345678(%eax),%bnd0",}, | ||
115 | {{0xf2, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
116 | "f2 0f 1a 85 78 56 34 12 \tbndcu 0x12345678(%ebp),%bnd0",}, | ||
117 | {{0xf2, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
118 | "f2 0f 1a 84 01 78 56 34 12 \tbndcu 0x12345678(%ecx,%eax,1),%bnd0",}, | ||
119 | {{0xf2, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
120 | "f2 0f 1a 84 05 78 56 34 12 \tbndcu 0x12345678(%ebp,%eax,1),%bnd0",}, | ||
121 | {{0xf2, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
122 | "f2 0f 1a 84 08 78 56 34 12 \tbndcu 0x12345678(%eax,%ecx,1),%bnd0",}, | ||
123 | {{0xf2, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
124 | "f2 0f 1a 84 c8 78 56 34 12 \tbndcu 0x12345678(%eax,%ecx,8),%bnd0",}, | ||
125 | {{0xf2, 0x0f, 0x1a, 0xc0, }, 4, 0, "", "", | ||
126 | "f2 0f 1a c0 \tbndcu %eax,%bnd0",}, | ||
127 | {{0xf2, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", | ||
128 | "f2 0f 1b 00 \tbndcn (%eax),%bnd0",}, | ||
129 | {{0xf2, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
130 | "f2 0f 1b 05 78 56 34 12 \tbndcn 0x12345678,%bnd0",}, | ||
131 | {{0xf2, 0x0f, 0x1b, 0x18, }, 4, 0, "", "", | ||
132 | "f2 0f 1b 18 \tbndcn (%eax),%bnd3",}, | ||
133 | {{0xf2, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "", | ||
134 | "f2 0f 1b 04 01 \tbndcn (%ecx,%eax,1),%bnd0",}, | ||
135 | {{0xf2, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
136 | "f2 0f 1b 04 05 78 56 34 12 \tbndcn 0x12345678(,%eax,1),%bnd0",}, | ||
137 | {{0xf2, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "", | ||
138 | "f2 0f 1b 04 08 \tbndcn (%eax,%ecx,1),%bnd0",}, | ||
139 | {{0xf2, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "", | ||
140 | "f2 0f 1b 04 c8 \tbndcn (%eax,%ecx,8),%bnd0",}, | ||
141 | {{0xf2, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "", | ||
142 | "f2 0f 1b 40 12 \tbndcn 0x12(%eax),%bnd0",}, | ||
143 | {{0xf2, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "", | ||
144 | "f2 0f 1b 45 12 \tbndcn 0x12(%ebp),%bnd0",}, | ||
145 | {{0xf2, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
146 | "f2 0f 1b 44 01 12 \tbndcn 0x12(%ecx,%eax,1),%bnd0",}, | ||
147 | {{0xf2, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
148 | "f2 0f 1b 44 05 12 \tbndcn 0x12(%ebp,%eax,1),%bnd0",}, | ||
149 | {{0xf2, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
150 | "f2 0f 1b 44 08 12 \tbndcn 0x12(%eax,%ecx,1),%bnd0",}, | ||
151 | {{0xf2, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
152 | "f2 0f 1b 44 c8 12 \tbndcn 0x12(%eax,%ecx,8),%bnd0",}, | ||
153 | {{0xf2, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
154 | "f2 0f 1b 80 78 56 34 12 \tbndcn 0x12345678(%eax),%bnd0",}, | ||
155 | {{0xf2, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
156 | "f2 0f 1b 85 78 56 34 12 \tbndcn 0x12345678(%ebp),%bnd0",}, | ||
157 | {{0xf2, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
158 | "f2 0f 1b 84 01 78 56 34 12 \tbndcn 0x12345678(%ecx,%eax,1),%bnd0",}, | ||
159 | {{0xf2, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
160 | "f2 0f 1b 84 05 78 56 34 12 \tbndcn 0x12345678(%ebp,%eax,1),%bnd0",}, | ||
161 | {{0xf2, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
162 | "f2 0f 1b 84 08 78 56 34 12 \tbndcn 0x12345678(%eax,%ecx,1),%bnd0",}, | ||
163 | {{0xf2, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
164 | "f2 0f 1b 84 c8 78 56 34 12 \tbndcn 0x12345678(%eax,%ecx,8),%bnd0",}, | ||
165 | {{0xf2, 0x0f, 0x1b, 0xc0, }, 4, 0, "", "", | ||
166 | "f2 0f 1b c0 \tbndcn %eax,%bnd0",}, | ||
167 | {{0x66, 0x0f, 0x1a, 0x00, }, 4, 0, "", "", | ||
168 | "66 0f 1a 00 \tbndmov (%eax),%bnd0",}, | ||
169 | {{0x66, 0x0f, 0x1a, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
170 | "66 0f 1a 05 78 56 34 12 \tbndmov 0x12345678,%bnd0",}, | ||
171 | {{0x66, 0x0f, 0x1a, 0x18, }, 4, 0, "", "", | ||
172 | "66 0f 1a 18 \tbndmov (%eax),%bnd3",}, | ||
173 | {{0x66, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "", | ||
174 | "66 0f 1a 04 01 \tbndmov (%ecx,%eax,1),%bnd0",}, | ||
175 | {{0x66, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
176 | "66 0f 1a 04 05 78 56 34 12 \tbndmov 0x12345678(,%eax,1),%bnd0",}, | ||
177 | {{0x66, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "", | ||
178 | "66 0f 1a 04 08 \tbndmov (%eax,%ecx,1),%bnd0",}, | ||
179 | {{0x66, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "", | ||
180 | "66 0f 1a 04 c8 \tbndmov (%eax,%ecx,8),%bnd0",}, | ||
181 | {{0x66, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "", | ||
182 | "66 0f 1a 40 12 \tbndmov 0x12(%eax),%bnd0",}, | ||
183 | {{0x66, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "", | ||
184 | "66 0f 1a 45 12 \tbndmov 0x12(%ebp),%bnd0",}, | ||
185 | {{0x66, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
186 | "66 0f 1a 44 01 12 \tbndmov 0x12(%ecx,%eax,1),%bnd0",}, | ||
187 | {{0x66, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
188 | "66 0f 1a 44 05 12 \tbndmov 0x12(%ebp,%eax,1),%bnd0",}, | ||
189 | {{0x66, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
190 | "66 0f 1a 44 08 12 \tbndmov 0x12(%eax,%ecx,1),%bnd0",}, | ||
191 | {{0x66, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
192 | "66 0f 1a 44 c8 12 \tbndmov 0x12(%eax,%ecx,8),%bnd0",}, | ||
193 | {{0x66, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
194 | "66 0f 1a 80 78 56 34 12 \tbndmov 0x12345678(%eax),%bnd0",}, | ||
195 | {{0x66, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
196 | "66 0f 1a 85 78 56 34 12 \tbndmov 0x12345678(%ebp),%bnd0",}, | ||
197 | {{0x66, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
198 | "66 0f 1a 84 01 78 56 34 12 \tbndmov 0x12345678(%ecx,%eax,1),%bnd0",}, | ||
199 | {{0x66, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
200 | "66 0f 1a 84 05 78 56 34 12 \tbndmov 0x12345678(%ebp,%eax,1),%bnd0",}, | ||
201 | {{0x66, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
202 | "66 0f 1a 84 08 78 56 34 12 \tbndmov 0x12345678(%eax,%ecx,1),%bnd0",}, | ||
203 | {{0x66, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
204 | "66 0f 1a 84 c8 78 56 34 12 \tbndmov 0x12345678(%eax,%ecx,8),%bnd0",}, | ||
205 | {{0x66, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", | ||
206 | "66 0f 1b 00 \tbndmov %bnd0,(%eax)",}, | ||
207 | {{0x66, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
208 | "66 0f 1b 05 78 56 34 12 \tbndmov %bnd0,0x12345678",}, | ||
209 | {{0x66, 0x0f, 0x1b, 0x18, }, 4, 0, "", "", | ||
210 | "66 0f 1b 18 \tbndmov %bnd3,(%eax)",}, | ||
211 | {{0x66, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "", | ||
212 | "66 0f 1b 04 01 \tbndmov %bnd0,(%ecx,%eax,1)",}, | ||
213 | {{0x66, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
214 | "66 0f 1b 04 05 78 56 34 12 \tbndmov %bnd0,0x12345678(,%eax,1)",}, | ||
215 | {{0x66, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "", | ||
216 | "66 0f 1b 04 08 \tbndmov %bnd0,(%eax,%ecx,1)",}, | ||
217 | {{0x66, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "", | ||
218 | "66 0f 1b 04 c8 \tbndmov %bnd0,(%eax,%ecx,8)",}, | ||
219 | {{0x66, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "", | ||
220 | "66 0f 1b 40 12 \tbndmov %bnd0,0x12(%eax)",}, | ||
221 | {{0x66, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "", | ||
222 | "66 0f 1b 45 12 \tbndmov %bnd0,0x12(%ebp)",}, | ||
223 | {{0x66, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
224 | "66 0f 1b 44 01 12 \tbndmov %bnd0,0x12(%ecx,%eax,1)",}, | ||
225 | {{0x66, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
226 | "66 0f 1b 44 05 12 \tbndmov %bnd0,0x12(%ebp,%eax,1)",}, | ||
227 | {{0x66, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
228 | "66 0f 1b 44 08 12 \tbndmov %bnd0,0x12(%eax,%ecx,1)",}, | ||
229 | {{0x66, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
230 | "66 0f 1b 44 c8 12 \tbndmov %bnd0,0x12(%eax,%ecx,8)",}, | ||
231 | {{0x66, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
232 | "66 0f 1b 80 78 56 34 12 \tbndmov %bnd0,0x12345678(%eax)",}, | ||
233 | {{0x66, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
234 | "66 0f 1b 85 78 56 34 12 \tbndmov %bnd0,0x12345678(%ebp)",}, | ||
235 | {{0x66, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
236 | "66 0f 1b 84 01 78 56 34 12 \tbndmov %bnd0,0x12345678(%ecx,%eax,1)",}, | ||
237 | {{0x66, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
238 | "66 0f 1b 84 05 78 56 34 12 \tbndmov %bnd0,0x12345678(%ebp,%eax,1)",}, | ||
239 | {{0x66, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
240 | "66 0f 1b 84 08 78 56 34 12 \tbndmov %bnd0,0x12345678(%eax,%ecx,1)",}, | ||
241 | {{0x66, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
242 | "66 0f 1b 84 c8 78 56 34 12 \tbndmov %bnd0,0x12345678(%eax,%ecx,8)",}, | ||
243 | {{0x66, 0x0f, 0x1a, 0xc8, }, 4, 0, "", "", | ||
244 | "66 0f 1a c8 \tbndmov %bnd0,%bnd1",}, | ||
245 | {{0x66, 0x0f, 0x1a, 0xc1, }, 4, 0, "", "", | ||
246 | "66 0f 1a c1 \tbndmov %bnd1,%bnd0",}, | ||
247 | {{0x0f, 0x1a, 0x00, }, 3, 0, "", "", | ||
248 | "0f 1a 00 \tbndldx (%eax),%bnd0",}, | ||
249 | {{0x0f, 0x1a, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
250 | "0f 1a 05 78 56 34 12 \tbndldx 0x12345678,%bnd0",}, | ||
251 | {{0x0f, 0x1a, 0x18, }, 3, 0, "", "", | ||
252 | "0f 1a 18 \tbndldx (%eax),%bnd3",}, | ||
253 | {{0x0f, 0x1a, 0x04, 0x01, }, 4, 0, "", "", | ||
254 | "0f 1a 04 01 \tbndldx (%ecx,%eax,1),%bnd0",}, | ||
255 | {{0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
256 | "0f 1a 04 05 78 56 34 12 \tbndldx 0x12345678(,%eax,1),%bnd0",}, | ||
257 | {{0x0f, 0x1a, 0x04, 0x08, }, 4, 0, "", "", | ||
258 | "0f 1a 04 08 \tbndldx (%eax,%ecx,1),%bnd0",}, | ||
259 | {{0x0f, 0x1a, 0x40, 0x12, }, 4, 0, "", "", | ||
260 | "0f 1a 40 12 \tbndldx 0x12(%eax),%bnd0",}, | ||
261 | {{0x0f, 0x1a, 0x45, 0x12, }, 4, 0, "", "", | ||
262 | "0f 1a 45 12 \tbndldx 0x12(%ebp),%bnd0",}, | ||
263 | {{0x0f, 0x1a, 0x44, 0x01, 0x12, }, 5, 0, "", "", | ||
264 | "0f 1a 44 01 12 \tbndldx 0x12(%ecx,%eax,1),%bnd0",}, | ||
265 | {{0x0f, 0x1a, 0x44, 0x05, 0x12, }, 5, 0, "", "", | ||
266 | "0f 1a 44 05 12 \tbndldx 0x12(%ebp,%eax,1),%bnd0",}, | ||
267 | {{0x0f, 0x1a, 0x44, 0x08, 0x12, }, 5, 0, "", "", | ||
268 | "0f 1a 44 08 12 \tbndldx 0x12(%eax,%ecx,1),%bnd0",}, | ||
269 | {{0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
270 | "0f 1a 80 78 56 34 12 \tbndldx 0x12345678(%eax),%bnd0",}, | ||
271 | {{0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
272 | "0f 1a 85 78 56 34 12 \tbndldx 0x12345678(%ebp),%bnd0",}, | ||
273 | {{0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
274 | "0f 1a 84 01 78 56 34 12 \tbndldx 0x12345678(%ecx,%eax,1),%bnd0",}, | ||
275 | {{0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
276 | "0f 1a 84 05 78 56 34 12 \tbndldx 0x12345678(%ebp,%eax,1),%bnd0",}, | ||
277 | {{0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
278 | "0f 1a 84 08 78 56 34 12 \tbndldx 0x12345678(%eax,%ecx,1),%bnd0",}, | ||
279 | {{0x0f, 0x1b, 0x00, }, 3, 0, "", "", | ||
280 | "0f 1b 00 \tbndstx %bnd0,(%eax)",}, | ||
281 | {{0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
282 | "0f 1b 05 78 56 34 12 \tbndstx %bnd0,0x12345678",}, | ||
283 | {{0x0f, 0x1b, 0x18, }, 3, 0, "", "", | ||
284 | "0f 1b 18 \tbndstx %bnd3,(%eax)",}, | ||
285 | {{0x0f, 0x1b, 0x04, 0x01, }, 4, 0, "", "", | ||
286 | "0f 1b 04 01 \tbndstx %bnd0,(%ecx,%eax,1)",}, | ||
287 | {{0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
288 | "0f 1b 04 05 78 56 34 12 \tbndstx %bnd0,0x12345678(,%eax,1)",}, | ||
289 | {{0x0f, 0x1b, 0x04, 0x08, }, 4, 0, "", "", | ||
290 | "0f 1b 04 08 \tbndstx %bnd0,(%eax,%ecx,1)",}, | ||
291 | {{0x0f, 0x1b, 0x40, 0x12, }, 4, 0, "", "", | ||
292 | "0f 1b 40 12 \tbndstx %bnd0,0x12(%eax)",}, | ||
293 | {{0x0f, 0x1b, 0x45, 0x12, }, 4, 0, "", "", | ||
294 | "0f 1b 45 12 \tbndstx %bnd0,0x12(%ebp)",}, | ||
295 | {{0x0f, 0x1b, 0x44, 0x01, 0x12, }, 5, 0, "", "", | ||
296 | "0f 1b 44 01 12 \tbndstx %bnd0,0x12(%ecx,%eax,1)",}, | ||
297 | {{0x0f, 0x1b, 0x44, 0x05, 0x12, }, 5, 0, "", "", | ||
298 | "0f 1b 44 05 12 \tbndstx %bnd0,0x12(%ebp,%eax,1)",}, | ||
299 | {{0x0f, 0x1b, 0x44, 0x08, 0x12, }, 5, 0, "", "", | ||
300 | "0f 1b 44 08 12 \tbndstx %bnd0,0x12(%eax,%ecx,1)",}, | ||
301 | {{0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
302 | "0f 1b 80 78 56 34 12 \tbndstx %bnd0,0x12345678(%eax)",}, | ||
303 | {{0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
304 | "0f 1b 85 78 56 34 12 \tbndstx %bnd0,0x12345678(%ebp)",}, | ||
305 | {{0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
306 | "0f 1b 84 01 78 56 34 12 \tbndstx %bnd0,0x12345678(%ecx,%eax,1)",}, | ||
307 | {{0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
308 | "0f 1b 84 05 78 56 34 12 \tbndstx %bnd0,0x12345678(%ebp,%eax,1)",}, | ||
309 | {{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
310 | "0f 1b 84 08 78 56 34 12 \tbndstx %bnd0,0x12345678(%eax,%ecx,1)",}, | ||
311 | {{0xf2, 0xe8, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "call", "unconditional", | ||
312 | "f2 e8 fc ff ff ff \tbnd call 3c3 <main+0x3c3>",}, | ||
313 | {{0xf2, 0xff, 0x10, }, 3, 0, "call", "indirect", | ||
314 | "f2 ff 10 \tbnd call *(%eax)",}, | ||
315 | {{0xf2, 0xc3, }, 2, 0, "ret", "indirect", | ||
316 | "f2 c3 \tbnd ret ",}, | ||
317 | {{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional", | ||
318 | "f2 e9 fc ff ff ff \tbnd jmp 3ce <main+0x3ce>",}, | ||
319 | {{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional", | ||
320 | "f2 e9 fc ff ff ff \tbnd jmp 3d4 <main+0x3d4>",}, | ||
321 | {{0xf2, 0xff, 0x21, }, 3, 0, "jmp", "indirect", | ||
322 | "f2 ff 21 \tbnd jmp *(%ecx)",}, | ||
323 | {{0xf2, 0x0f, 0x85, 0xfc, 0xff, 0xff, 0xff, }, 7, 0xfffffffc, "jcc", "conditional", | ||
324 | "f2 0f 85 fc ff ff ff \tbnd jne 3de <main+0x3de>",}, | ||
325 | {{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "", | ||
326 | "0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",}, | ||
327 | {{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "", | ||
328 | "0f 3a cc d7 91 \tsha1rnds4 $0x91,%xmm7,%xmm2",}, | ||
329 | {{0x0f, 0x3a, 0xcc, 0x00, 0x91, }, 5, 0, "", "", | ||
330 | "0f 3a cc 00 91 \tsha1rnds4 $0x91,(%eax),%xmm0",}, | ||
331 | {{0x0f, 0x3a, 0xcc, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "", | ||
332 | "0f 3a cc 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678,%xmm0",}, | ||
333 | {{0x0f, 0x3a, 0xcc, 0x18, 0x91, }, 5, 0, "", "", | ||
334 | "0f 3a cc 18 91 \tsha1rnds4 $0x91,(%eax),%xmm3",}, | ||
335 | {{0x0f, 0x3a, 0xcc, 0x04, 0x01, 0x91, }, 6, 0, "", "", | ||
336 | "0f 3a cc 04 01 91 \tsha1rnds4 $0x91,(%ecx,%eax,1),%xmm0",}, | ||
337 | {{0x0f, 0x3a, 0xcc, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
338 | "0f 3a cc 04 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(,%eax,1),%xmm0",}, | ||
339 | {{0x0f, 0x3a, 0xcc, 0x04, 0x08, 0x91, }, 6, 0, "", "", | ||
340 | "0f 3a cc 04 08 91 \tsha1rnds4 $0x91,(%eax,%ecx,1),%xmm0",}, | ||
341 | {{0x0f, 0x3a, 0xcc, 0x04, 0xc8, 0x91, }, 6, 0, "", "", | ||
342 | "0f 3a cc 04 c8 91 \tsha1rnds4 $0x91,(%eax,%ecx,8),%xmm0",}, | ||
343 | {{0x0f, 0x3a, 0xcc, 0x40, 0x12, 0x91, }, 6, 0, "", "", | ||
344 | "0f 3a cc 40 12 91 \tsha1rnds4 $0x91,0x12(%eax),%xmm0",}, | ||
345 | {{0x0f, 0x3a, 0xcc, 0x45, 0x12, 0x91, }, 6, 0, "", "", | ||
346 | "0f 3a cc 45 12 91 \tsha1rnds4 $0x91,0x12(%ebp),%xmm0",}, | ||
347 | {{0x0f, 0x3a, 0xcc, 0x44, 0x01, 0x12, 0x91, }, 7, 0, "", "", | ||
348 | "0f 3a cc 44 01 12 91 \tsha1rnds4 $0x91,0x12(%ecx,%eax,1),%xmm0",}, | ||
349 | {{0x0f, 0x3a, 0xcc, 0x44, 0x05, 0x12, 0x91, }, 7, 0, "", "", | ||
350 | "0f 3a cc 44 05 12 91 \tsha1rnds4 $0x91,0x12(%ebp,%eax,1),%xmm0",}, | ||
351 | {{0x0f, 0x3a, 0xcc, 0x44, 0x08, 0x12, 0x91, }, 7, 0, "", "", | ||
352 | "0f 3a cc 44 08 12 91 \tsha1rnds4 $0x91,0x12(%eax,%ecx,1),%xmm0",}, | ||
353 | {{0x0f, 0x3a, 0xcc, 0x44, 0xc8, 0x12, 0x91, }, 7, 0, "", "", | ||
354 | "0f 3a cc 44 c8 12 91 \tsha1rnds4 $0x91,0x12(%eax,%ecx,8),%xmm0",}, | ||
355 | {{0x0f, 0x3a, 0xcc, 0x80, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "", | ||
356 | "0f 3a cc 80 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%eax),%xmm0",}, | ||
357 | {{0x0f, 0x3a, 0xcc, 0x85, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "", | ||
358 | "0f 3a cc 85 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%ebp),%xmm0",}, | ||
359 | {{0x0f, 0x3a, 0xcc, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
360 | "0f 3a cc 84 01 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%ecx,%eax,1),%xmm0",}, | ||
361 | {{0x0f, 0x3a, 0xcc, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
362 | "0f 3a cc 84 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%ebp,%eax,1),%xmm0",}, | ||
363 | {{0x0f, 0x3a, 0xcc, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
364 | "0f 3a cc 84 08 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%eax,%ecx,1),%xmm0",}, | ||
365 | {{0x0f, 0x3a, 0xcc, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
366 | "0f 3a cc 84 c8 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%eax,%ecx,8),%xmm0",}, | ||
367 | {{0x0f, 0x38, 0xc8, 0xc1, }, 4, 0, "", "", | ||
368 | "0f 38 c8 c1 \tsha1nexte %xmm1,%xmm0",}, | ||
369 | {{0x0f, 0x38, 0xc8, 0xd7, }, 4, 0, "", "", | ||
370 | "0f 38 c8 d7 \tsha1nexte %xmm7,%xmm2",}, | ||
371 | {{0x0f, 0x38, 0xc8, 0x00, }, 4, 0, "", "", | ||
372 | "0f 38 c8 00 \tsha1nexte (%eax),%xmm0",}, | ||
373 | {{0x0f, 0x38, 0xc8, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
374 | "0f 38 c8 05 78 56 34 12 \tsha1nexte 0x12345678,%xmm0",}, | ||
375 | {{0x0f, 0x38, 0xc8, 0x18, }, 4, 0, "", "", | ||
376 | "0f 38 c8 18 \tsha1nexte (%eax),%xmm3",}, | ||
377 | {{0x0f, 0x38, 0xc8, 0x04, 0x01, }, 5, 0, "", "", | ||
378 | "0f 38 c8 04 01 \tsha1nexte (%ecx,%eax,1),%xmm0",}, | ||
379 | {{0x0f, 0x38, 0xc8, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
380 | "0f 38 c8 04 05 78 56 34 12 \tsha1nexte 0x12345678(,%eax,1),%xmm0",}, | ||
381 | {{0x0f, 0x38, 0xc8, 0x04, 0x08, }, 5, 0, "", "", | ||
382 | "0f 38 c8 04 08 \tsha1nexte (%eax,%ecx,1),%xmm0",}, | ||
383 | {{0x0f, 0x38, 0xc8, 0x04, 0xc8, }, 5, 0, "", "", | ||
384 | "0f 38 c8 04 c8 \tsha1nexte (%eax,%ecx,8),%xmm0",}, | ||
385 | {{0x0f, 0x38, 0xc8, 0x40, 0x12, }, 5, 0, "", "", | ||
386 | "0f 38 c8 40 12 \tsha1nexte 0x12(%eax),%xmm0",}, | ||
387 | {{0x0f, 0x38, 0xc8, 0x45, 0x12, }, 5, 0, "", "", | ||
388 | "0f 38 c8 45 12 \tsha1nexte 0x12(%ebp),%xmm0",}, | ||
389 | {{0x0f, 0x38, 0xc8, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
390 | "0f 38 c8 44 01 12 \tsha1nexte 0x12(%ecx,%eax,1),%xmm0",}, | ||
391 | {{0x0f, 0x38, 0xc8, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
392 | "0f 38 c8 44 05 12 \tsha1nexte 0x12(%ebp,%eax,1),%xmm0",}, | ||
393 | {{0x0f, 0x38, 0xc8, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
394 | "0f 38 c8 44 08 12 \tsha1nexte 0x12(%eax,%ecx,1),%xmm0",}, | ||
395 | {{0x0f, 0x38, 0xc8, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
396 | "0f 38 c8 44 c8 12 \tsha1nexte 0x12(%eax,%ecx,8),%xmm0",}, | ||
397 | {{0x0f, 0x38, 0xc8, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
398 | "0f 38 c8 80 78 56 34 12 \tsha1nexte 0x12345678(%eax),%xmm0",}, | ||
399 | {{0x0f, 0x38, 0xc8, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
400 | "0f 38 c8 85 78 56 34 12 \tsha1nexte 0x12345678(%ebp),%xmm0",}, | ||
401 | {{0x0f, 0x38, 0xc8, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
402 | "0f 38 c8 84 01 78 56 34 12 \tsha1nexte 0x12345678(%ecx,%eax,1),%xmm0",}, | ||
403 | {{0x0f, 0x38, 0xc8, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
404 | "0f 38 c8 84 05 78 56 34 12 \tsha1nexte 0x12345678(%ebp,%eax,1),%xmm0",}, | ||
405 | {{0x0f, 0x38, 0xc8, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
406 | "0f 38 c8 84 08 78 56 34 12 \tsha1nexte 0x12345678(%eax,%ecx,1),%xmm0",}, | ||
407 | {{0x0f, 0x38, 0xc8, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
408 | "0f 38 c8 84 c8 78 56 34 12 \tsha1nexte 0x12345678(%eax,%ecx,8),%xmm0",}, | ||
409 | {{0x0f, 0x38, 0xc9, 0xc1, }, 4, 0, "", "", | ||
410 | "0f 38 c9 c1 \tsha1msg1 %xmm1,%xmm0",}, | ||
411 | {{0x0f, 0x38, 0xc9, 0xd7, }, 4, 0, "", "", | ||
412 | "0f 38 c9 d7 \tsha1msg1 %xmm7,%xmm2",}, | ||
413 | {{0x0f, 0x38, 0xc9, 0x00, }, 4, 0, "", "", | ||
414 | "0f 38 c9 00 \tsha1msg1 (%eax),%xmm0",}, | ||
415 | {{0x0f, 0x38, 0xc9, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
416 | "0f 38 c9 05 78 56 34 12 \tsha1msg1 0x12345678,%xmm0",}, | ||
417 | {{0x0f, 0x38, 0xc9, 0x18, }, 4, 0, "", "", | ||
418 | "0f 38 c9 18 \tsha1msg1 (%eax),%xmm3",}, | ||
419 | {{0x0f, 0x38, 0xc9, 0x04, 0x01, }, 5, 0, "", "", | ||
420 | "0f 38 c9 04 01 \tsha1msg1 (%ecx,%eax,1),%xmm0",}, | ||
421 | {{0x0f, 0x38, 0xc9, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
422 | "0f 38 c9 04 05 78 56 34 12 \tsha1msg1 0x12345678(,%eax,1),%xmm0",}, | ||
423 | {{0x0f, 0x38, 0xc9, 0x04, 0x08, }, 5, 0, "", "", | ||
424 | "0f 38 c9 04 08 \tsha1msg1 (%eax,%ecx,1),%xmm0",}, | ||
425 | {{0x0f, 0x38, 0xc9, 0x04, 0xc8, }, 5, 0, "", "", | ||
426 | "0f 38 c9 04 c8 \tsha1msg1 (%eax,%ecx,8),%xmm0",}, | ||
427 | {{0x0f, 0x38, 0xc9, 0x40, 0x12, }, 5, 0, "", "", | ||
428 | "0f 38 c9 40 12 \tsha1msg1 0x12(%eax),%xmm0",}, | ||
429 | {{0x0f, 0x38, 0xc9, 0x45, 0x12, }, 5, 0, "", "", | ||
430 | "0f 38 c9 45 12 \tsha1msg1 0x12(%ebp),%xmm0",}, | ||
431 | {{0x0f, 0x38, 0xc9, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
432 | "0f 38 c9 44 01 12 \tsha1msg1 0x12(%ecx,%eax,1),%xmm0",}, | ||
433 | {{0x0f, 0x38, 0xc9, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
434 | "0f 38 c9 44 05 12 \tsha1msg1 0x12(%ebp,%eax,1),%xmm0",}, | ||
435 | {{0x0f, 0x38, 0xc9, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
436 | "0f 38 c9 44 08 12 \tsha1msg1 0x12(%eax,%ecx,1),%xmm0",}, | ||
437 | {{0x0f, 0x38, 0xc9, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
438 | "0f 38 c9 44 c8 12 \tsha1msg1 0x12(%eax,%ecx,8),%xmm0",}, | ||
439 | {{0x0f, 0x38, 0xc9, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
440 | "0f 38 c9 80 78 56 34 12 \tsha1msg1 0x12345678(%eax),%xmm0",}, | ||
441 | {{0x0f, 0x38, 0xc9, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
442 | "0f 38 c9 85 78 56 34 12 \tsha1msg1 0x12345678(%ebp),%xmm0",}, | ||
443 | {{0x0f, 0x38, 0xc9, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
444 | "0f 38 c9 84 01 78 56 34 12 \tsha1msg1 0x12345678(%ecx,%eax,1),%xmm0",}, | ||
445 | {{0x0f, 0x38, 0xc9, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
446 | "0f 38 c9 84 05 78 56 34 12 \tsha1msg1 0x12345678(%ebp,%eax,1),%xmm0",}, | ||
447 | {{0x0f, 0x38, 0xc9, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
448 | "0f 38 c9 84 08 78 56 34 12 \tsha1msg1 0x12345678(%eax,%ecx,1),%xmm0",}, | ||
449 | {{0x0f, 0x38, 0xc9, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
450 | "0f 38 c9 84 c8 78 56 34 12 \tsha1msg1 0x12345678(%eax,%ecx,8),%xmm0",}, | ||
451 | {{0x0f, 0x38, 0xca, 0xc1, }, 4, 0, "", "", | ||
452 | "0f 38 ca c1 \tsha1msg2 %xmm1,%xmm0",}, | ||
453 | {{0x0f, 0x38, 0xca, 0xd7, }, 4, 0, "", "", | ||
454 | "0f 38 ca d7 \tsha1msg2 %xmm7,%xmm2",}, | ||
455 | {{0x0f, 0x38, 0xca, 0x00, }, 4, 0, "", "", | ||
456 | "0f 38 ca 00 \tsha1msg2 (%eax),%xmm0",}, | ||
457 | {{0x0f, 0x38, 0xca, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
458 | "0f 38 ca 05 78 56 34 12 \tsha1msg2 0x12345678,%xmm0",}, | ||
459 | {{0x0f, 0x38, 0xca, 0x18, }, 4, 0, "", "", | ||
460 | "0f 38 ca 18 \tsha1msg2 (%eax),%xmm3",}, | ||
461 | {{0x0f, 0x38, 0xca, 0x04, 0x01, }, 5, 0, "", "", | ||
462 | "0f 38 ca 04 01 \tsha1msg2 (%ecx,%eax,1),%xmm0",}, | ||
463 | {{0x0f, 0x38, 0xca, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
464 | "0f 38 ca 04 05 78 56 34 12 \tsha1msg2 0x12345678(,%eax,1),%xmm0",}, | ||
465 | {{0x0f, 0x38, 0xca, 0x04, 0x08, }, 5, 0, "", "", | ||
466 | "0f 38 ca 04 08 \tsha1msg2 (%eax,%ecx,1),%xmm0",}, | ||
467 | {{0x0f, 0x38, 0xca, 0x04, 0xc8, }, 5, 0, "", "", | ||
468 | "0f 38 ca 04 c8 \tsha1msg2 (%eax,%ecx,8),%xmm0",}, | ||
469 | {{0x0f, 0x38, 0xca, 0x40, 0x12, }, 5, 0, "", "", | ||
470 | "0f 38 ca 40 12 \tsha1msg2 0x12(%eax),%xmm0",}, | ||
471 | {{0x0f, 0x38, 0xca, 0x45, 0x12, }, 5, 0, "", "", | ||
472 | "0f 38 ca 45 12 \tsha1msg2 0x12(%ebp),%xmm0",}, | ||
473 | {{0x0f, 0x38, 0xca, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
474 | "0f 38 ca 44 01 12 \tsha1msg2 0x12(%ecx,%eax,1),%xmm0",}, | ||
475 | {{0x0f, 0x38, 0xca, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
476 | "0f 38 ca 44 05 12 \tsha1msg2 0x12(%ebp,%eax,1),%xmm0",}, | ||
477 | {{0x0f, 0x38, 0xca, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
478 | "0f 38 ca 44 08 12 \tsha1msg2 0x12(%eax,%ecx,1),%xmm0",}, | ||
479 | {{0x0f, 0x38, 0xca, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
480 | "0f 38 ca 44 c8 12 \tsha1msg2 0x12(%eax,%ecx,8),%xmm0",}, | ||
481 | {{0x0f, 0x38, 0xca, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
482 | "0f 38 ca 80 78 56 34 12 \tsha1msg2 0x12345678(%eax),%xmm0",}, | ||
483 | {{0x0f, 0x38, 0xca, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
484 | "0f 38 ca 85 78 56 34 12 \tsha1msg2 0x12345678(%ebp),%xmm0",}, | ||
485 | {{0x0f, 0x38, 0xca, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
486 | "0f 38 ca 84 01 78 56 34 12 \tsha1msg2 0x12345678(%ecx,%eax,1),%xmm0",}, | ||
487 | {{0x0f, 0x38, 0xca, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
488 | "0f 38 ca 84 05 78 56 34 12 \tsha1msg2 0x12345678(%ebp,%eax,1),%xmm0",}, | ||
489 | {{0x0f, 0x38, 0xca, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
490 | "0f 38 ca 84 08 78 56 34 12 \tsha1msg2 0x12345678(%eax,%ecx,1),%xmm0",}, | ||
491 | {{0x0f, 0x38, 0xca, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
492 | "0f 38 ca 84 c8 78 56 34 12 \tsha1msg2 0x12345678(%eax,%ecx,8),%xmm0",}, | ||
493 | {{0x0f, 0x38, 0xcb, 0xcc, }, 4, 0, "", "", | ||
494 | "0f 38 cb cc \tsha256rnds2 %xmm0,%xmm4,%xmm1",}, | ||
495 | {{0x0f, 0x38, 0xcb, 0xd7, }, 4, 0, "", "", | ||
496 | "0f 38 cb d7 \tsha256rnds2 %xmm0,%xmm7,%xmm2",}, | ||
497 | {{0x0f, 0x38, 0xcb, 0x08, }, 4, 0, "", "", | ||
498 | "0f 38 cb 08 \tsha256rnds2 %xmm0,(%eax),%xmm1",}, | ||
499 | {{0x0f, 0x38, 0xcb, 0x0d, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
500 | "0f 38 cb 0d 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678,%xmm1",}, | ||
501 | {{0x0f, 0x38, 0xcb, 0x18, }, 4, 0, "", "", | ||
502 | "0f 38 cb 18 \tsha256rnds2 %xmm0,(%eax),%xmm3",}, | ||
503 | {{0x0f, 0x38, 0xcb, 0x0c, 0x01, }, 5, 0, "", "", | ||
504 | "0f 38 cb 0c 01 \tsha256rnds2 %xmm0,(%ecx,%eax,1),%xmm1",}, | ||
505 | {{0x0f, 0x38, 0xcb, 0x0c, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
506 | "0f 38 cb 0c 05 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(,%eax,1),%xmm1",}, | ||
507 | {{0x0f, 0x38, 0xcb, 0x0c, 0x08, }, 5, 0, "", "", | ||
508 | "0f 38 cb 0c 08 \tsha256rnds2 %xmm0,(%eax,%ecx,1),%xmm1",}, | ||
509 | {{0x0f, 0x38, 0xcb, 0x0c, 0xc8, }, 5, 0, "", "", | ||
510 | "0f 38 cb 0c c8 \tsha256rnds2 %xmm0,(%eax,%ecx,8),%xmm1",}, | ||
511 | {{0x0f, 0x38, 0xcb, 0x48, 0x12, }, 5, 0, "", "", | ||
512 | "0f 38 cb 48 12 \tsha256rnds2 %xmm0,0x12(%eax),%xmm1",}, | ||
513 | {{0x0f, 0x38, 0xcb, 0x4d, 0x12, }, 5, 0, "", "", | ||
514 | "0f 38 cb 4d 12 \tsha256rnds2 %xmm0,0x12(%ebp),%xmm1",}, | ||
515 | {{0x0f, 0x38, 0xcb, 0x4c, 0x01, 0x12, }, 6, 0, "", "", | ||
516 | "0f 38 cb 4c 01 12 \tsha256rnds2 %xmm0,0x12(%ecx,%eax,1),%xmm1",}, | ||
517 | {{0x0f, 0x38, 0xcb, 0x4c, 0x05, 0x12, }, 6, 0, "", "", | ||
518 | "0f 38 cb 4c 05 12 \tsha256rnds2 %xmm0,0x12(%ebp,%eax,1),%xmm1",}, | ||
519 | {{0x0f, 0x38, 0xcb, 0x4c, 0x08, 0x12, }, 6, 0, "", "", | ||
520 | "0f 38 cb 4c 08 12 \tsha256rnds2 %xmm0,0x12(%eax,%ecx,1),%xmm1",}, | ||
521 | {{0x0f, 0x38, 0xcb, 0x4c, 0xc8, 0x12, }, 6, 0, "", "", | ||
522 | "0f 38 cb 4c c8 12 \tsha256rnds2 %xmm0,0x12(%eax,%ecx,8),%xmm1",}, | ||
523 | {{0x0f, 0x38, 0xcb, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
524 | "0f 38 cb 88 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%eax),%xmm1",}, | ||
525 | {{0x0f, 0x38, 0xcb, 0x8d, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
526 | "0f 38 cb 8d 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%ebp),%xmm1",}, | ||
527 | {{0x0f, 0x38, 0xcb, 0x8c, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
528 | "0f 38 cb 8c 01 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%ecx,%eax,1),%xmm1",}, | ||
529 | {{0x0f, 0x38, 0xcb, 0x8c, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
530 | "0f 38 cb 8c 05 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%ebp,%eax,1),%xmm1",}, | ||
531 | {{0x0f, 0x38, 0xcb, 0x8c, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
532 | "0f 38 cb 8c 08 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%eax,%ecx,1),%xmm1",}, | ||
533 | {{0x0f, 0x38, 0xcb, 0x8c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
534 | "0f 38 cb 8c c8 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%eax,%ecx,8),%xmm1",}, | ||
535 | {{0x0f, 0x38, 0xcc, 0xc1, }, 4, 0, "", "", | ||
536 | "0f 38 cc c1 \tsha256msg1 %xmm1,%xmm0",}, | ||
537 | {{0x0f, 0x38, 0xcc, 0xd7, }, 4, 0, "", "", | ||
538 | "0f 38 cc d7 \tsha256msg1 %xmm7,%xmm2",}, | ||
539 | {{0x0f, 0x38, 0xcc, 0x00, }, 4, 0, "", "", | ||
540 | "0f 38 cc 00 \tsha256msg1 (%eax),%xmm0",}, | ||
541 | {{0x0f, 0x38, 0xcc, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
542 | "0f 38 cc 05 78 56 34 12 \tsha256msg1 0x12345678,%xmm0",}, | ||
543 | {{0x0f, 0x38, 0xcc, 0x18, }, 4, 0, "", "", | ||
544 | "0f 38 cc 18 \tsha256msg1 (%eax),%xmm3",}, | ||
545 | {{0x0f, 0x38, 0xcc, 0x04, 0x01, }, 5, 0, "", "", | ||
546 | "0f 38 cc 04 01 \tsha256msg1 (%ecx,%eax,1),%xmm0",}, | ||
547 | {{0x0f, 0x38, 0xcc, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
548 | "0f 38 cc 04 05 78 56 34 12 \tsha256msg1 0x12345678(,%eax,1),%xmm0",}, | ||
549 | {{0x0f, 0x38, 0xcc, 0x04, 0x08, }, 5, 0, "", "", | ||
550 | "0f 38 cc 04 08 \tsha256msg1 (%eax,%ecx,1),%xmm0",}, | ||
551 | {{0x0f, 0x38, 0xcc, 0x04, 0xc8, }, 5, 0, "", "", | ||
552 | "0f 38 cc 04 c8 \tsha256msg1 (%eax,%ecx,8),%xmm0",}, | ||
553 | {{0x0f, 0x38, 0xcc, 0x40, 0x12, }, 5, 0, "", "", | ||
554 | "0f 38 cc 40 12 \tsha256msg1 0x12(%eax),%xmm0",}, | ||
555 | {{0x0f, 0x38, 0xcc, 0x45, 0x12, }, 5, 0, "", "", | ||
556 | "0f 38 cc 45 12 \tsha256msg1 0x12(%ebp),%xmm0",}, | ||
557 | {{0x0f, 0x38, 0xcc, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
558 | "0f 38 cc 44 01 12 \tsha256msg1 0x12(%ecx,%eax,1),%xmm0",}, | ||
559 | {{0x0f, 0x38, 0xcc, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
560 | "0f 38 cc 44 05 12 \tsha256msg1 0x12(%ebp,%eax,1),%xmm0",}, | ||
561 | {{0x0f, 0x38, 0xcc, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
562 | "0f 38 cc 44 08 12 \tsha256msg1 0x12(%eax,%ecx,1),%xmm0",}, | ||
563 | {{0x0f, 0x38, 0xcc, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
564 | "0f 38 cc 44 c8 12 \tsha256msg1 0x12(%eax,%ecx,8),%xmm0",}, | ||
565 | {{0x0f, 0x38, 0xcc, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
566 | "0f 38 cc 80 78 56 34 12 \tsha256msg1 0x12345678(%eax),%xmm0",}, | ||
567 | {{0x0f, 0x38, 0xcc, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
568 | "0f 38 cc 85 78 56 34 12 \tsha256msg1 0x12345678(%ebp),%xmm0",}, | ||
569 | {{0x0f, 0x38, 0xcc, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
570 | "0f 38 cc 84 01 78 56 34 12 \tsha256msg1 0x12345678(%ecx,%eax,1),%xmm0",}, | ||
571 | {{0x0f, 0x38, 0xcc, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
572 | "0f 38 cc 84 05 78 56 34 12 \tsha256msg1 0x12345678(%ebp,%eax,1),%xmm0",}, | ||
573 | {{0x0f, 0x38, 0xcc, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
574 | "0f 38 cc 84 08 78 56 34 12 \tsha256msg1 0x12345678(%eax,%ecx,1),%xmm0",}, | ||
575 | {{0x0f, 0x38, 0xcc, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
576 | "0f 38 cc 84 c8 78 56 34 12 \tsha256msg1 0x12345678(%eax,%ecx,8),%xmm0",}, | ||
577 | {{0x0f, 0x38, 0xcd, 0xc1, }, 4, 0, "", "", | ||
578 | "0f 38 cd c1 \tsha256msg2 %xmm1,%xmm0",}, | ||
579 | {{0x0f, 0x38, 0xcd, 0xd7, }, 4, 0, "", "", | ||
580 | "0f 38 cd d7 \tsha256msg2 %xmm7,%xmm2",}, | ||
581 | {{0x0f, 0x38, 0xcd, 0x00, }, 4, 0, "", "", | ||
582 | "0f 38 cd 00 \tsha256msg2 (%eax),%xmm0",}, | ||
583 | {{0x0f, 0x38, 0xcd, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
584 | "0f 38 cd 05 78 56 34 12 \tsha256msg2 0x12345678,%xmm0",}, | ||
585 | {{0x0f, 0x38, 0xcd, 0x18, }, 4, 0, "", "", | ||
586 | "0f 38 cd 18 \tsha256msg2 (%eax),%xmm3",}, | ||
587 | {{0x0f, 0x38, 0xcd, 0x04, 0x01, }, 5, 0, "", "", | ||
588 | "0f 38 cd 04 01 \tsha256msg2 (%ecx,%eax,1),%xmm0",}, | ||
589 | {{0x0f, 0x38, 0xcd, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
590 | "0f 38 cd 04 05 78 56 34 12 \tsha256msg2 0x12345678(,%eax,1),%xmm0",}, | ||
591 | {{0x0f, 0x38, 0xcd, 0x04, 0x08, }, 5, 0, "", "", | ||
592 | "0f 38 cd 04 08 \tsha256msg2 (%eax,%ecx,1),%xmm0",}, | ||
593 | {{0x0f, 0x38, 0xcd, 0x04, 0xc8, }, 5, 0, "", "", | ||
594 | "0f 38 cd 04 c8 \tsha256msg2 (%eax,%ecx,8),%xmm0",}, | ||
595 | {{0x0f, 0x38, 0xcd, 0x40, 0x12, }, 5, 0, "", "", | ||
596 | "0f 38 cd 40 12 \tsha256msg2 0x12(%eax),%xmm0",}, | ||
597 | {{0x0f, 0x38, 0xcd, 0x45, 0x12, }, 5, 0, "", "", | ||
598 | "0f 38 cd 45 12 \tsha256msg2 0x12(%ebp),%xmm0",}, | ||
599 | {{0x0f, 0x38, 0xcd, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
600 | "0f 38 cd 44 01 12 \tsha256msg2 0x12(%ecx,%eax,1),%xmm0",}, | ||
601 | {{0x0f, 0x38, 0xcd, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
602 | "0f 38 cd 44 05 12 \tsha256msg2 0x12(%ebp,%eax,1),%xmm0",}, | ||
603 | {{0x0f, 0x38, 0xcd, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
604 | "0f 38 cd 44 08 12 \tsha256msg2 0x12(%eax,%ecx,1),%xmm0",}, | ||
605 | {{0x0f, 0x38, 0xcd, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
606 | "0f 38 cd 44 c8 12 \tsha256msg2 0x12(%eax,%ecx,8),%xmm0",}, | ||
607 | {{0x0f, 0x38, 0xcd, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
608 | "0f 38 cd 80 78 56 34 12 \tsha256msg2 0x12345678(%eax),%xmm0",}, | ||
609 | {{0x0f, 0x38, 0xcd, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
610 | "0f 38 cd 85 78 56 34 12 \tsha256msg2 0x12345678(%ebp),%xmm0",}, | ||
611 | {{0x0f, 0x38, 0xcd, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
612 | "0f 38 cd 84 01 78 56 34 12 \tsha256msg2 0x12345678(%ecx,%eax,1),%xmm0",}, | ||
613 | {{0x0f, 0x38, 0xcd, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
614 | "0f 38 cd 84 05 78 56 34 12 \tsha256msg2 0x12345678(%ebp,%eax,1),%xmm0",}, | ||
615 | {{0x0f, 0x38, 0xcd, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
616 | "0f 38 cd 84 08 78 56 34 12 \tsha256msg2 0x12345678(%eax,%ecx,1),%xmm0",}, | ||
617 | {{0x0f, 0x38, 0xcd, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
618 | "0f 38 cd 84 c8 78 56 34 12 \tsha256msg2 0x12345678(%eax,%ecx,8),%xmm0",}, | ||
619 | {{0x66, 0x0f, 0xae, 0x38, }, 4, 0, "", "", | ||
620 | "66 0f ae 38 \tclflushopt (%eax)",}, | ||
621 | {{0x66, 0x0f, 0xae, 0x3d, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
622 | "66 0f ae 3d 78 56 34 12 \tclflushopt 0x12345678",}, | ||
623 | {{0x66, 0x0f, 0xae, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
624 | "66 0f ae bc c8 78 56 34 12 \tclflushopt 0x12345678(%eax,%ecx,8)",}, | ||
625 | {{0x0f, 0xae, 0x38, }, 3, 0, "", "", | ||
626 | "0f ae 38 \tclflush (%eax)",}, | ||
627 | {{0x0f, 0xae, 0xf8, }, 3, 0, "", "", | ||
628 | "0f ae f8 \tsfence ",}, | ||
629 | {{0x66, 0x0f, 0xae, 0x30, }, 4, 0, "", "", | ||
630 | "66 0f ae 30 \tclwb (%eax)",}, | ||
631 | {{0x66, 0x0f, 0xae, 0x35, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
632 | "66 0f ae 35 78 56 34 12 \tclwb 0x12345678",}, | ||
633 | {{0x66, 0x0f, 0xae, 0xb4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
634 | "66 0f ae b4 c8 78 56 34 12 \tclwb 0x12345678(%eax,%ecx,8)",}, | ||
635 | {{0x0f, 0xae, 0x30, }, 3, 0, "", "", | ||
636 | "0f ae 30 \txsaveopt (%eax)",}, | ||
637 | {{0x0f, 0xae, 0xf0, }, 3, 0, "", "", | ||
638 | "0f ae f0 \tmfence ",}, | ||
639 | {{0x0f, 0xc7, 0x20, }, 3, 0, "", "", | ||
640 | "0f c7 20 \txsavec (%eax)",}, | ||
641 | {{0x0f, 0xc7, 0x25, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
642 | "0f c7 25 78 56 34 12 \txsavec 0x12345678",}, | ||
643 | {{0x0f, 0xc7, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
644 | "0f c7 a4 c8 78 56 34 12 \txsavec 0x12345678(%eax,%ecx,8)",}, | ||
645 | {{0x0f, 0xc7, 0x28, }, 3, 0, "", "", | ||
646 | "0f c7 28 \txsaves (%eax)",}, | ||
647 | {{0x0f, 0xc7, 0x2d, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
648 | "0f c7 2d 78 56 34 12 \txsaves 0x12345678",}, | ||
649 | {{0x0f, 0xc7, 0xac, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
650 | "0f c7 ac c8 78 56 34 12 \txsaves 0x12345678(%eax,%ecx,8)",}, | ||
651 | {{0x0f, 0xc7, 0x18, }, 3, 0, "", "", | ||
652 | "0f c7 18 \txrstors (%eax)",}, | ||
653 | {{0x0f, 0xc7, 0x1d, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
654 | "0f c7 1d 78 56 34 12 \txrstors 0x12345678",}, | ||
655 | {{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
656 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",}, | ||
657 | {{0x66, 0x0f, 0xae, 0xf8, }, 4, 0, "", "", | ||
658 | "66 0f ae f8 \tpcommit ",}, | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-64.c b/tools/perf/arch/x86/tests/insn-x86-dat-64.c new file mode 100644 index 000000000000..4fe7cce179c4 --- /dev/null +++ b/tools/perf/arch/x86/tests/insn-x86-dat-64.c | |||
@@ -0,0 +1,768 @@ | |||
1 | /* | ||
2 | * Generated by gen-insn-x86-dat.sh and gen-insn-x86-dat.awk | ||
3 | * from insn-x86-dat-src.c for inclusion by insn-x86.c | ||
4 | * Do not change this code. | ||
5 | */ | ||
6 | |||
7 | {{0x0f, 0x31, }, 2, 0, "", "", | ||
8 | "0f 31 \trdtsc ",}, | ||
9 | {{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", | ||
10 | "f3 0f 1b 00 \tbndmk (%rax),%bnd0",}, | ||
11 | {{0xf3, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "", | ||
12 | "f3 41 0f 1b 00 \tbndmk (%r8),%bnd0",}, | ||
13 | {{0xf3, 0x0f, 0x1b, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
14 | "f3 0f 1b 04 25 78 56 34 12 \tbndmk 0x12345678,%bnd0",}, | ||
15 | {{0xf3, 0x0f, 0x1b, 0x18, }, 4, 0, "", "", | ||
16 | "f3 0f 1b 18 \tbndmk (%rax),%bnd3",}, | ||
17 | {{0xf3, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "", | ||
18 | "f3 0f 1b 04 01 \tbndmk (%rcx,%rax,1),%bnd0",}, | ||
19 | {{0xf3, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
20 | "f3 0f 1b 04 05 78 56 34 12 \tbndmk 0x12345678(,%rax,1),%bnd0",}, | ||
21 | {{0xf3, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "", | ||
22 | "f3 0f 1b 04 08 \tbndmk (%rax,%rcx,1),%bnd0",}, | ||
23 | {{0xf3, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "", | ||
24 | "f3 0f 1b 04 c8 \tbndmk (%rax,%rcx,8),%bnd0",}, | ||
25 | {{0xf3, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "", | ||
26 | "f3 0f 1b 40 12 \tbndmk 0x12(%rax),%bnd0",}, | ||
27 | {{0xf3, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "", | ||
28 | "f3 0f 1b 45 12 \tbndmk 0x12(%rbp),%bnd0",}, | ||
29 | {{0xf3, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
30 | "f3 0f 1b 44 01 12 \tbndmk 0x12(%rcx,%rax,1),%bnd0",}, | ||
31 | {{0xf3, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
32 | "f3 0f 1b 44 05 12 \tbndmk 0x12(%rbp,%rax,1),%bnd0",}, | ||
33 | {{0xf3, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
34 | "f3 0f 1b 44 08 12 \tbndmk 0x12(%rax,%rcx,1),%bnd0",}, | ||
35 | {{0xf3, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
36 | "f3 0f 1b 44 c8 12 \tbndmk 0x12(%rax,%rcx,8),%bnd0",}, | ||
37 | {{0xf3, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
38 | "f3 0f 1b 80 78 56 34 12 \tbndmk 0x12345678(%rax),%bnd0",}, | ||
39 | {{0xf3, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
40 | "f3 0f 1b 85 78 56 34 12 \tbndmk 0x12345678(%rbp),%bnd0",}, | ||
41 | {{0xf3, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
42 | "f3 0f 1b 84 01 78 56 34 12 \tbndmk 0x12345678(%rcx,%rax,1),%bnd0",}, | ||
43 | {{0xf3, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
44 | "f3 0f 1b 84 05 78 56 34 12 \tbndmk 0x12345678(%rbp,%rax,1),%bnd0",}, | ||
45 | {{0xf3, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
46 | "f3 0f 1b 84 08 78 56 34 12 \tbndmk 0x12345678(%rax,%rcx,1),%bnd0",}, | ||
47 | {{0xf3, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
48 | "f3 0f 1b 84 c8 78 56 34 12 \tbndmk 0x12345678(%rax,%rcx,8),%bnd0",}, | ||
49 | {{0xf3, 0x0f, 0x1a, 0x00, }, 4, 0, "", "", | ||
50 | "f3 0f 1a 00 \tbndcl (%rax),%bnd0",}, | ||
51 | {{0xf3, 0x41, 0x0f, 0x1a, 0x00, }, 5, 0, "", "", | ||
52 | "f3 41 0f 1a 00 \tbndcl (%r8),%bnd0",}, | ||
53 | {{0xf3, 0x0f, 0x1a, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
54 | "f3 0f 1a 04 25 78 56 34 12 \tbndcl 0x12345678,%bnd0",}, | ||
55 | {{0xf3, 0x0f, 0x1a, 0x18, }, 4, 0, "", "", | ||
56 | "f3 0f 1a 18 \tbndcl (%rax),%bnd3",}, | ||
57 | {{0xf3, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "", | ||
58 | "f3 0f 1a 04 01 \tbndcl (%rcx,%rax,1),%bnd0",}, | ||
59 | {{0xf3, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
60 | "f3 0f 1a 04 05 78 56 34 12 \tbndcl 0x12345678(,%rax,1),%bnd0",}, | ||
61 | {{0xf3, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "", | ||
62 | "f3 0f 1a 04 08 \tbndcl (%rax,%rcx,1),%bnd0",}, | ||
63 | {{0xf3, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "", | ||
64 | "f3 0f 1a 04 c8 \tbndcl (%rax,%rcx,8),%bnd0",}, | ||
65 | {{0xf3, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "", | ||
66 | "f3 0f 1a 40 12 \tbndcl 0x12(%rax),%bnd0",}, | ||
67 | {{0xf3, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "", | ||
68 | "f3 0f 1a 45 12 \tbndcl 0x12(%rbp),%bnd0",}, | ||
69 | {{0xf3, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
70 | "f3 0f 1a 44 01 12 \tbndcl 0x12(%rcx,%rax,1),%bnd0",}, | ||
71 | {{0xf3, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
72 | "f3 0f 1a 44 05 12 \tbndcl 0x12(%rbp,%rax,1),%bnd0",}, | ||
73 | {{0xf3, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
74 | "f3 0f 1a 44 08 12 \tbndcl 0x12(%rax,%rcx,1),%bnd0",}, | ||
75 | {{0xf3, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
76 | "f3 0f 1a 44 c8 12 \tbndcl 0x12(%rax,%rcx,8),%bnd0",}, | ||
77 | {{0xf3, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
78 | "f3 0f 1a 80 78 56 34 12 \tbndcl 0x12345678(%rax),%bnd0",}, | ||
79 | {{0xf3, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
80 | "f3 0f 1a 85 78 56 34 12 \tbndcl 0x12345678(%rbp),%bnd0",}, | ||
81 | {{0xf3, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
82 | "f3 0f 1a 84 01 78 56 34 12 \tbndcl 0x12345678(%rcx,%rax,1),%bnd0",}, | ||
83 | {{0xf3, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
84 | "f3 0f 1a 84 05 78 56 34 12 \tbndcl 0x12345678(%rbp,%rax,1),%bnd0",}, | ||
85 | {{0xf3, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
86 | "f3 0f 1a 84 08 78 56 34 12 \tbndcl 0x12345678(%rax,%rcx,1),%bnd0",}, | ||
87 | {{0xf3, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
88 | "f3 0f 1a 84 c8 78 56 34 12 \tbndcl 0x12345678(%rax,%rcx,8),%bnd0",}, | ||
89 | {{0xf3, 0x0f, 0x1a, 0xc0, }, 4, 0, "", "", | ||
90 | "f3 0f 1a c0 \tbndcl %rax,%bnd0",}, | ||
91 | {{0xf2, 0x0f, 0x1a, 0x00, }, 4, 0, "", "", | ||
92 | "f2 0f 1a 00 \tbndcu (%rax),%bnd0",}, | ||
93 | {{0xf2, 0x41, 0x0f, 0x1a, 0x00, }, 5, 0, "", "", | ||
94 | "f2 41 0f 1a 00 \tbndcu (%r8),%bnd0",}, | ||
95 | {{0xf2, 0x0f, 0x1a, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
96 | "f2 0f 1a 04 25 78 56 34 12 \tbndcu 0x12345678,%bnd0",}, | ||
97 | {{0xf2, 0x0f, 0x1a, 0x18, }, 4, 0, "", "", | ||
98 | "f2 0f 1a 18 \tbndcu (%rax),%bnd3",}, | ||
99 | {{0xf2, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "", | ||
100 | "f2 0f 1a 04 01 \tbndcu (%rcx,%rax,1),%bnd0",}, | ||
101 | {{0xf2, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
102 | "f2 0f 1a 04 05 78 56 34 12 \tbndcu 0x12345678(,%rax,1),%bnd0",}, | ||
103 | {{0xf2, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "", | ||
104 | "f2 0f 1a 04 08 \tbndcu (%rax,%rcx,1),%bnd0",}, | ||
105 | {{0xf2, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "", | ||
106 | "f2 0f 1a 04 c8 \tbndcu (%rax,%rcx,8),%bnd0",}, | ||
107 | {{0xf2, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "", | ||
108 | "f2 0f 1a 40 12 \tbndcu 0x12(%rax),%bnd0",}, | ||
109 | {{0xf2, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "", | ||
110 | "f2 0f 1a 45 12 \tbndcu 0x12(%rbp),%bnd0",}, | ||
111 | {{0xf2, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
112 | "f2 0f 1a 44 01 12 \tbndcu 0x12(%rcx,%rax,1),%bnd0",}, | ||
113 | {{0xf2, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
114 | "f2 0f 1a 44 05 12 \tbndcu 0x12(%rbp,%rax,1),%bnd0",}, | ||
115 | {{0xf2, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
116 | "f2 0f 1a 44 08 12 \tbndcu 0x12(%rax,%rcx,1),%bnd0",}, | ||
117 | {{0xf2, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
118 | "f2 0f 1a 44 c8 12 \tbndcu 0x12(%rax,%rcx,8),%bnd0",}, | ||
119 | {{0xf2, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
120 | "f2 0f 1a 80 78 56 34 12 \tbndcu 0x12345678(%rax),%bnd0",}, | ||
121 | {{0xf2, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
122 | "f2 0f 1a 85 78 56 34 12 \tbndcu 0x12345678(%rbp),%bnd0",}, | ||
123 | {{0xf2, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
124 | "f2 0f 1a 84 01 78 56 34 12 \tbndcu 0x12345678(%rcx,%rax,1),%bnd0",}, | ||
125 | {{0xf2, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
126 | "f2 0f 1a 84 05 78 56 34 12 \tbndcu 0x12345678(%rbp,%rax,1),%bnd0",}, | ||
127 | {{0xf2, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
128 | "f2 0f 1a 84 08 78 56 34 12 \tbndcu 0x12345678(%rax,%rcx,1),%bnd0",}, | ||
129 | {{0xf2, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
130 | "f2 0f 1a 84 c8 78 56 34 12 \tbndcu 0x12345678(%rax,%rcx,8),%bnd0",}, | ||
131 | {{0xf2, 0x0f, 0x1a, 0xc0, }, 4, 0, "", "", | ||
132 | "f2 0f 1a c0 \tbndcu %rax,%bnd0",}, | ||
133 | {{0xf2, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", | ||
134 | "f2 0f 1b 00 \tbndcn (%rax),%bnd0",}, | ||
135 | {{0xf2, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "", | ||
136 | "f2 41 0f 1b 00 \tbndcn (%r8),%bnd0",}, | ||
137 | {{0xf2, 0x0f, 0x1b, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
138 | "f2 0f 1b 04 25 78 56 34 12 \tbndcn 0x12345678,%bnd0",}, | ||
139 | {{0xf2, 0x0f, 0x1b, 0x18, }, 4, 0, "", "", | ||
140 | "f2 0f 1b 18 \tbndcn (%rax),%bnd3",}, | ||
141 | {{0xf2, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "", | ||
142 | "f2 0f 1b 04 01 \tbndcn (%rcx,%rax,1),%bnd0",}, | ||
143 | {{0xf2, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
144 | "f2 0f 1b 04 05 78 56 34 12 \tbndcn 0x12345678(,%rax,1),%bnd0",}, | ||
145 | {{0xf2, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "", | ||
146 | "f2 0f 1b 04 08 \tbndcn (%rax,%rcx,1),%bnd0",}, | ||
147 | {{0xf2, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "", | ||
148 | "f2 0f 1b 04 c8 \tbndcn (%rax,%rcx,8),%bnd0",}, | ||
149 | {{0xf2, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "", | ||
150 | "f2 0f 1b 40 12 \tbndcn 0x12(%rax),%bnd0",}, | ||
151 | {{0xf2, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "", | ||
152 | "f2 0f 1b 45 12 \tbndcn 0x12(%rbp),%bnd0",}, | ||
153 | {{0xf2, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
154 | "f2 0f 1b 44 01 12 \tbndcn 0x12(%rcx,%rax,1),%bnd0",}, | ||
155 | {{0xf2, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
156 | "f2 0f 1b 44 05 12 \tbndcn 0x12(%rbp,%rax,1),%bnd0",}, | ||
157 | {{0xf2, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
158 | "f2 0f 1b 44 08 12 \tbndcn 0x12(%rax,%rcx,1),%bnd0",}, | ||
159 | {{0xf2, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
160 | "f2 0f 1b 44 c8 12 \tbndcn 0x12(%rax,%rcx,8),%bnd0",}, | ||
161 | {{0xf2, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
162 | "f2 0f 1b 80 78 56 34 12 \tbndcn 0x12345678(%rax),%bnd0",}, | ||
163 | {{0xf2, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
164 | "f2 0f 1b 85 78 56 34 12 \tbndcn 0x12345678(%rbp),%bnd0",}, | ||
165 | {{0xf2, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
166 | "f2 0f 1b 84 01 78 56 34 12 \tbndcn 0x12345678(%rcx,%rax,1),%bnd0",}, | ||
167 | {{0xf2, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
168 | "f2 0f 1b 84 05 78 56 34 12 \tbndcn 0x12345678(%rbp,%rax,1),%bnd0",}, | ||
169 | {{0xf2, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
170 | "f2 0f 1b 84 08 78 56 34 12 \tbndcn 0x12345678(%rax,%rcx,1),%bnd0",}, | ||
171 | {{0xf2, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
172 | "f2 0f 1b 84 c8 78 56 34 12 \tbndcn 0x12345678(%rax,%rcx,8),%bnd0",}, | ||
173 | {{0xf2, 0x0f, 0x1b, 0xc0, }, 4, 0, "", "", | ||
174 | "f2 0f 1b c0 \tbndcn %rax,%bnd0",}, | ||
175 | {{0x66, 0x0f, 0x1a, 0x00, }, 4, 0, "", "", | ||
176 | "66 0f 1a 00 \tbndmov (%rax),%bnd0",}, | ||
177 | {{0x66, 0x41, 0x0f, 0x1a, 0x00, }, 5, 0, "", "", | ||
178 | "66 41 0f 1a 00 \tbndmov (%r8),%bnd0",}, | ||
179 | {{0x66, 0x0f, 0x1a, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
180 | "66 0f 1a 04 25 78 56 34 12 \tbndmov 0x12345678,%bnd0",}, | ||
181 | {{0x66, 0x0f, 0x1a, 0x18, }, 4, 0, "", "", | ||
182 | "66 0f 1a 18 \tbndmov (%rax),%bnd3",}, | ||
183 | {{0x66, 0x0f, 0x1a, 0x04, 0x01, }, 5, 0, "", "", | ||
184 | "66 0f 1a 04 01 \tbndmov (%rcx,%rax,1),%bnd0",}, | ||
185 | {{0x66, 0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
186 | "66 0f 1a 04 05 78 56 34 12 \tbndmov 0x12345678(,%rax,1),%bnd0",}, | ||
187 | {{0x66, 0x0f, 0x1a, 0x04, 0x08, }, 5, 0, "", "", | ||
188 | "66 0f 1a 04 08 \tbndmov (%rax,%rcx,1),%bnd0",}, | ||
189 | {{0x66, 0x0f, 0x1a, 0x04, 0xc8, }, 5, 0, "", "", | ||
190 | "66 0f 1a 04 c8 \tbndmov (%rax,%rcx,8),%bnd0",}, | ||
191 | {{0x66, 0x0f, 0x1a, 0x40, 0x12, }, 5, 0, "", "", | ||
192 | "66 0f 1a 40 12 \tbndmov 0x12(%rax),%bnd0",}, | ||
193 | {{0x66, 0x0f, 0x1a, 0x45, 0x12, }, 5, 0, "", "", | ||
194 | "66 0f 1a 45 12 \tbndmov 0x12(%rbp),%bnd0",}, | ||
195 | {{0x66, 0x0f, 0x1a, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
196 | "66 0f 1a 44 01 12 \tbndmov 0x12(%rcx,%rax,1),%bnd0",}, | ||
197 | {{0x66, 0x0f, 0x1a, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
198 | "66 0f 1a 44 05 12 \tbndmov 0x12(%rbp,%rax,1),%bnd0",}, | ||
199 | {{0x66, 0x0f, 0x1a, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
200 | "66 0f 1a 44 08 12 \tbndmov 0x12(%rax,%rcx,1),%bnd0",}, | ||
201 | {{0x66, 0x0f, 0x1a, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
202 | "66 0f 1a 44 c8 12 \tbndmov 0x12(%rax,%rcx,8),%bnd0",}, | ||
203 | {{0x66, 0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
204 | "66 0f 1a 80 78 56 34 12 \tbndmov 0x12345678(%rax),%bnd0",}, | ||
205 | {{0x66, 0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
206 | "66 0f 1a 85 78 56 34 12 \tbndmov 0x12345678(%rbp),%bnd0",}, | ||
207 | {{0x66, 0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
208 | "66 0f 1a 84 01 78 56 34 12 \tbndmov 0x12345678(%rcx,%rax,1),%bnd0",}, | ||
209 | {{0x66, 0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
210 | "66 0f 1a 84 05 78 56 34 12 \tbndmov 0x12345678(%rbp,%rax,1),%bnd0",}, | ||
211 | {{0x66, 0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
212 | "66 0f 1a 84 08 78 56 34 12 \tbndmov 0x12345678(%rax,%rcx,1),%bnd0",}, | ||
213 | {{0x66, 0x0f, 0x1a, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
214 | "66 0f 1a 84 c8 78 56 34 12 \tbndmov 0x12345678(%rax,%rcx,8),%bnd0",}, | ||
215 | {{0x66, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", | ||
216 | "66 0f 1b 00 \tbndmov %bnd0,(%rax)",}, | ||
217 | {{0x66, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "", | ||
218 | "66 41 0f 1b 00 \tbndmov %bnd0,(%r8)",}, | ||
219 | {{0x66, 0x0f, 0x1b, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
220 | "66 0f 1b 04 25 78 56 34 12 \tbndmov %bnd0,0x12345678",}, | ||
221 | {{0x66, 0x0f, 0x1b, 0x18, }, 4, 0, "", "", | ||
222 | "66 0f 1b 18 \tbndmov %bnd3,(%rax)",}, | ||
223 | {{0x66, 0x0f, 0x1b, 0x04, 0x01, }, 5, 0, "", "", | ||
224 | "66 0f 1b 04 01 \tbndmov %bnd0,(%rcx,%rax,1)",}, | ||
225 | {{0x66, 0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
226 | "66 0f 1b 04 05 78 56 34 12 \tbndmov %bnd0,0x12345678(,%rax,1)",}, | ||
227 | {{0x66, 0x0f, 0x1b, 0x04, 0x08, }, 5, 0, "", "", | ||
228 | "66 0f 1b 04 08 \tbndmov %bnd0,(%rax,%rcx,1)",}, | ||
229 | {{0x66, 0x0f, 0x1b, 0x04, 0xc8, }, 5, 0, "", "", | ||
230 | "66 0f 1b 04 c8 \tbndmov %bnd0,(%rax,%rcx,8)",}, | ||
231 | {{0x66, 0x0f, 0x1b, 0x40, 0x12, }, 5, 0, "", "", | ||
232 | "66 0f 1b 40 12 \tbndmov %bnd0,0x12(%rax)",}, | ||
233 | {{0x66, 0x0f, 0x1b, 0x45, 0x12, }, 5, 0, "", "", | ||
234 | "66 0f 1b 45 12 \tbndmov %bnd0,0x12(%rbp)",}, | ||
235 | {{0x66, 0x0f, 0x1b, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
236 | "66 0f 1b 44 01 12 \tbndmov %bnd0,0x12(%rcx,%rax,1)",}, | ||
237 | {{0x66, 0x0f, 0x1b, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
238 | "66 0f 1b 44 05 12 \tbndmov %bnd0,0x12(%rbp,%rax,1)",}, | ||
239 | {{0x66, 0x0f, 0x1b, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
240 | "66 0f 1b 44 08 12 \tbndmov %bnd0,0x12(%rax,%rcx,1)",}, | ||
241 | {{0x66, 0x0f, 0x1b, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
242 | "66 0f 1b 44 c8 12 \tbndmov %bnd0,0x12(%rax,%rcx,8)",}, | ||
243 | {{0x66, 0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
244 | "66 0f 1b 80 78 56 34 12 \tbndmov %bnd0,0x12345678(%rax)",}, | ||
245 | {{0x66, 0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
246 | "66 0f 1b 85 78 56 34 12 \tbndmov %bnd0,0x12345678(%rbp)",}, | ||
247 | {{0x66, 0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
248 | "66 0f 1b 84 01 78 56 34 12 \tbndmov %bnd0,0x12345678(%rcx,%rax,1)",}, | ||
249 | {{0x66, 0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
250 | "66 0f 1b 84 05 78 56 34 12 \tbndmov %bnd0,0x12345678(%rbp,%rax,1)",}, | ||
251 | {{0x66, 0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
252 | "66 0f 1b 84 08 78 56 34 12 \tbndmov %bnd0,0x12345678(%rax,%rcx,1)",}, | ||
253 | {{0x66, 0x0f, 0x1b, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
254 | "66 0f 1b 84 c8 78 56 34 12 \tbndmov %bnd0,0x12345678(%rax,%rcx,8)",}, | ||
255 | {{0x66, 0x0f, 0x1a, 0xc8, }, 4, 0, "", "", | ||
256 | "66 0f 1a c8 \tbndmov %bnd0,%bnd1",}, | ||
257 | {{0x66, 0x0f, 0x1a, 0xc1, }, 4, 0, "", "", | ||
258 | "66 0f 1a c1 \tbndmov %bnd1,%bnd0",}, | ||
259 | {{0x0f, 0x1a, 0x00, }, 3, 0, "", "", | ||
260 | "0f 1a 00 \tbndldx (%rax),%bnd0",}, | ||
261 | {{0x41, 0x0f, 0x1a, 0x00, }, 4, 0, "", "", | ||
262 | "41 0f 1a 00 \tbndldx (%r8),%bnd0",}, | ||
263 | {{0x0f, 0x1a, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
264 | "0f 1a 04 25 78 56 34 12 \tbndldx 0x12345678,%bnd0",}, | ||
265 | {{0x0f, 0x1a, 0x18, }, 3, 0, "", "", | ||
266 | "0f 1a 18 \tbndldx (%rax),%bnd3",}, | ||
267 | {{0x0f, 0x1a, 0x04, 0x01, }, 4, 0, "", "", | ||
268 | "0f 1a 04 01 \tbndldx (%rcx,%rax,1),%bnd0",}, | ||
269 | {{0x0f, 0x1a, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
270 | "0f 1a 04 05 78 56 34 12 \tbndldx 0x12345678(,%rax,1),%bnd0",}, | ||
271 | {{0x0f, 0x1a, 0x04, 0x08, }, 4, 0, "", "", | ||
272 | "0f 1a 04 08 \tbndldx (%rax,%rcx,1),%bnd0",}, | ||
273 | {{0x0f, 0x1a, 0x40, 0x12, }, 4, 0, "", "", | ||
274 | "0f 1a 40 12 \tbndldx 0x12(%rax),%bnd0",}, | ||
275 | {{0x0f, 0x1a, 0x45, 0x12, }, 4, 0, "", "", | ||
276 | "0f 1a 45 12 \tbndldx 0x12(%rbp),%bnd0",}, | ||
277 | {{0x0f, 0x1a, 0x44, 0x01, 0x12, }, 5, 0, "", "", | ||
278 | "0f 1a 44 01 12 \tbndldx 0x12(%rcx,%rax,1),%bnd0",}, | ||
279 | {{0x0f, 0x1a, 0x44, 0x05, 0x12, }, 5, 0, "", "", | ||
280 | "0f 1a 44 05 12 \tbndldx 0x12(%rbp,%rax,1),%bnd0",}, | ||
281 | {{0x0f, 0x1a, 0x44, 0x08, 0x12, }, 5, 0, "", "", | ||
282 | "0f 1a 44 08 12 \tbndldx 0x12(%rax,%rcx,1),%bnd0",}, | ||
283 | {{0x0f, 0x1a, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
284 | "0f 1a 80 78 56 34 12 \tbndldx 0x12345678(%rax),%bnd0",}, | ||
285 | {{0x0f, 0x1a, 0x85, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
286 | "0f 1a 85 78 56 34 12 \tbndldx 0x12345678(%rbp),%bnd0",}, | ||
287 | {{0x0f, 0x1a, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
288 | "0f 1a 84 01 78 56 34 12 \tbndldx 0x12345678(%rcx,%rax,1),%bnd0",}, | ||
289 | {{0x0f, 0x1a, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
290 | "0f 1a 84 05 78 56 34 12 \tbndldx 0x12345678(%rbp,%rax,1),%bnd0",}, | ||
291 | {{0x0f, 0x1a, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
292 | "0f 1a 84 08 78 56 34 12 \tbndldx 0x12345678(%rax,%rcx,1),%bnd0",}, | ||
293 | {{0x0f, 0x1b, 0x00, }, 3, 0, "", "", | ||
294 | "0f 1b 00 \tbndstx %bnd0,(%rax)",}, | ||
295 | {{0x41, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", | ||
296 | "41 0f 1b 00 \tbndstx %bnd0,(%r8)",}, | ||
297 | {{0x0f, 0x1b, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
298 | "0f 1b 04 25 78 56 34 12 \tbndstx %bnd0,0x12345678",}, | ||
299 | {{0x0f, 0x1b, 0x18, }, 3, 0, "", "", | ||
300 | "0f 1b 18 \tbndstx %bnd3,(%rax)",}, | ||
301 | {{0x0f, 0x1b, 0x04, 0x01, }, 4, 0, "", "", | ||
302 | "0f 1b 04 01 \tbndstx %bnd0,(%rcx,%rax,1)",}, | ||
303 | {{0x0f, 0x1b, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
304 | "0f 1b 04 05 78 56 34 12 \tbndstx %bnd0,0x12345678(,%rax,1)",}, | ||
305 | {{0x0f, 0x1b, 0x04, 0x08, }, 4, 0, "", "", | ||
306 | "0f 1b 04 08 \tbndstx %bnd0,(%rax,%rcx,1)",}, | ||
307 | {{0x0f, 0x1b, 0x40, 0x12, }, 4, 0, "", "", | ||
308 | "0f 1b 40 12 \tbndstx %bnd0,0x12(%rax)",}, | ||
309 | {{0x0f, 0x1b, 0x45, 0x12, }, 4, 0, "", "", | ||
310 | "0f 1b 45 12 \tbndstx %bnd0,0x12(%rbp)",}, | ||
311 | {{0x0f, 0x1b, 0x44, 0x01, 0x12, }, 5, 0, "", "", | ||
312 | "0f 1b 44 01 12 \tbndstx %bnd0,0x12(%rcx,%rax,1)",}, | ||
313 | {{0x0f, 0x1b, 0x44, 0x05, 0x12, }, 5, 0, "", "", | ||
314 | "0f 1b 44 05 12 \tbndstx %bnd0,0x12(%rbp,%rax,1)",}, | ||
315 | {{0x0f, 0x1b, 0x44, 0x08, 0x12, }, 5, 0, "", "", | ||
316 | "0f 1b 44 08 12 \tbndstx %bnd0,0x12(%rax,%rcx,1)",}, | ||
317 | {{0x0f, 0x1b, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
318 | "0f 1b 80 78 56 34 12 \tbndstx %bnd0,0x12345678(%rax)",}, | ||
319 | {{0x0f, 0x1b, 0x85, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "", | ||
320 | "0f 1b 85 78 56 34 12 \tbndstx %bnd0,0x12345678(%rbp)",}, | ||
321 | {{0x0f, 0x1b, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
322 | "0f 1b 84 01 78 56 34 12 \tbndstx %bnd0,0x12345678(%rcx,%rax,1)",}, | ||
323 | {{0x0f, 0x1b, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
324 | "0f 1b 84 05 78 56 34 12 \tbndstx %bnd0,0x12345678(%rbp,%rax,1)",}, | ||
325 | {{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
326 | "0f 1b 84 08 78 56 34 12 \tbndstx %bnd0,0x12345678(%rax,%rcx,1)",}, | ||
327 | {{0xf2, 0xe8, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "call", "unconditional", | ||
328 | "f2 e8 00 00 00 00 \tbnd callq 3f6 <main+0x3f6>",}, | ||
329 | {{0x67, 0xf2, 0xff, 0x10, }, 4, 0, "call", "indirect", | ||
330 | "67 f2 ff 10 \tbnd callq *(%eax)",}, | ||
331 | {{0xf2, 0xc3, }, 2, 0, "ret", "indirect", | ||
332 | "f2 c3 \tbnd retq ",}, | ||
333 | {{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional", | ||
334 | "f2 e9 00 00 00 00 \tbnd jmpq 402 <main+0x402>",}, | ||
335 | {{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional", | ||
336 | "f2 e9 00 00 00 00 \tbnd jmpq 408 <main+0x408>",}, | ||
337 | {{0x67, 0xf2, 0xff, 0x21, }, 4, 0, "jmp", "indirect", | ||
338 | "67 f2 ff 21 \tbnd jmpq *(%ecx)",}, | ||
339 | {{0xf2, 0x0f, 0x85, 0x00, 0x00, 0x00, 0x00, }, 7, 0, "jcc", "conditional", | ||
340 | "f2 0f 85 00 00 00 00 \tbnd jne 413 <main+0x413>",}, | ||
341 | {{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "", | ||
342 | "0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",}, | ||
343 | {{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "", | ||
344 | "0f 3a cc d7 91 \tsha1rnds4 $0x91,%xmm7,%xmm2",}, | ||
345 | {{0x41, 0x0f, 0x3a, 0xcc, 0xc0, 0x91, }, 6, 0, "", "", | ||
346 | "41 0f 3a cc c0 91 \tsha1rnds4 $0x91,%xmm8,%xmm0",}, | ||
347 | {{0x44, 0x0f, 0x3a, 0xcc, 0xc7, 0x91, }, 6, 0, "", "", | ||
348 | "44 0f 3a cc c7 91 \tsha1rnds4 $0x91,%xmm7,%xmm8",}, | ||
349 | {{0x45, 0x0f, 0x3a, 0xcc, 0xc7, 0x91, }, 6, 0, "", "", | ||
350 | "45 0f 3a cc c7 91 \tsha1rnds4 $0x91,%xmm15,%xmm8",}, | ||
351 | {{0x0f, 0x3a, 0xcc, 0x00, 0x91, }, 5, 0, "", "", | ||
352 | "0f 3a cc 00 91 \tsha1rnds4 $0x91,(%rax),%xmm0",}, | ||
353 | {{0x41, 0x0f, 0x3a, 0xcc, 0x00, 0x91, }, 6, 0, "", "", | ||
354 | "41 0f 3a cc 00 91 \tsha1rnds4 $0x91,(%r8),%xmm0",}, | ||
355 | {{0x0f, 0x3a, 0xcc, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
356 | "0f 3a cc 04 25 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678,%xmm0",}, | ||
357 | {{0x0f, 0x3a, 0xcc, 0x18, 0x91, }, 5, 0, "", "", | ||
358 | "0f 3a cc 18 91 \tsha1rnds4 $0x91,(%rax),%xmm3",}, | ||
359 | {{0x0f, 0x3a, 0xcc, 0x04, 0x01, 0x91, }, 6, 0, "", "", | ||
360 | "0f 3a cc 04 01 91 \tsha1rnds4 $0x91,(%rcx,%rax,1),%xmm0",}, | ||
361 | {{0x0f, 0x3a, 0xcc, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
362 | "0f 3a cc 04 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(,%rax,1),%xmm0",}, | ||
363 | {{0x0f, 0x3a, 0xcc, 0x04, 0x08, 0x91, }, 6, 0, "", "", | ||
364 | "0f 3a cc 04 08 91 \tsha1rnds4 $0x91,(%rax,%rcx,1),%xmm0",}, | ||
365 | {{0x0f, 0x3a, 0xcc, 0x04, 0xc8, 0x91, }, 6, 0, "", "", | ||
366 | "0f 3a cc 04 c8 91 \tsha1rnds4 $0x91,(%rax,%rcx,8),%xmm0",}, | ||
367 | {{0x0f, 0x3a, 0xcc, 0x40, 0x12, 0x91, }, 6, 0, "", "", | ||
368 | "0f 3a cc 40 12 91 \tsha1rnds4 $0x91,0x12(%rax),%xmm0",}, | ||
369 | {{0x0f, 0x3a, 0xcc, 0x45, 0x12, 0x91, }, 6, 0, "", "", | ||
370 | "0f 3a cc 45 12 91 \tsha1rnds4 $0x91,0x12(%rbp),%xmm0",}, | ||
371 | {{0x0f, 0x3a, 0xcc, 0x44, 0x01, 0x12, 0x91, }, 7, 0, "", "", | ||
372 | "0f 3a cc 44 01 12 91 \tsha1rnds4 $0x91,0x12(%rcx,%rax,1),%xmm0",}, | ||
373 | {{0x0f, 0x3a, 0xcc, 0x44, 0x05, 0x12, 0x91, }, 7, 0, "", "", | ||
374 | "0f 3a cc 44 05 12 91 \tsha1rnds4 $0x91,0x12(%rbp,%rax,1),%xmm0",}, | ||
375 | {{0x0f, 0x3a, 0xcc, 0x44, 0x08, 0x12, 0x91, }, 7, 0, "", "", | ||
376 | "0f 3a cc 44 08 12 91 \tsha1rnds4 $0x91,0x12(%rax,%rcx,1),%xmm0",}, | ||
377 | {{0x0f, 0x3a, 0xcc, 0x44, 0xc8, 0x12, 0x91, }, 7, 0, "", "", | ||
378 | "0f 3a cc 44 c8 12 91 \tsha1rnds4 $0x91,0x12(%rax,%rcx,8),%xmm0",}, | ||
379 | {{0x0f, 0x3a, 0xcc, 0x80, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "", | ||
380 | "0f 3a cc 80 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rax),%xmm0",}, | ||
381 | {{0x0f, 0x3a, 0xcc, 0x85, 0x78, 0x56, 0x34, 0x12, 0x91, }, 9, 0, "", "", | ||
382 | "0f 3a cc 85 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rbp),%xmm0",}, | ||
383 | {{0x0f, 0x3a, 0xcc, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
384 | "0f 3a cc 84 01 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rcx,%rax,1),%xmm0",}, | ||
385 | {{0x0f, 0x3a, 0xcc, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
386 | "0f 3a cc 84 05 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rbp,%rax,1),%xmm0",}, | ||
387 | {{0x0f, 0x3a, 0xcc, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
388 | "0f 3a cc 84 08 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rax,%rcx,1),%xmm0",}, | ||
389 | {{0x0f, 0x3a, 0xcc, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, 0x91, }, 10, 0, "", "", | ||
390 | "0f 3a cc 84 c8 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rax,%rcx,8),%xmm0",}, | ||
391 | {{0x44, 0x0f, 0x3a, 0xcc, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, 0x91, }, 11, 0, "", "", | ||
392 | "44 0f 3a cc bc c8 78 56 34 12 91 \tsha1rnds4 $0x91,0x12345678(%rax,%rcx,8),%xmm15",}, | ||
393 | {{0x0f, 0x38, 0xc8, 0xc1, }, 4, 0, "", "", | ||
394 | "0f 38 c8 c1 \tsha1nexte %xmm1,%xmm0",}, | ||
395 | {{0x0f, 0x38, 0xc8, 0xd7, }, 4, 0, "", "", | ||
396 | "0f 38 c8 d7 \tsha1nexte %xmm7,%xmm2",}, | ||
397 | {{0x41, 0x0f, 0x38, 0xc8, 0xc0, }, 5, 0, "", "", | ||
398 | "41 0f 38 c8 c0 \tsha1nexte %xmm8,%xmm0",}, | ||
399 | {{0x44, 0x0f, 0x38, 0xc8, 0xc7, }, 5, 0, "", "", | ||
400 | "44 0f 38 c8 c7 \tsha1nexte %xmm7,%xmm8",}, | ||
401 | {{0x45, 0x0f, 0x38, 0xc8, 0xc7, }, 5, 0, "", "", | ||
402 | "45 0f 38 c8 c7 \tsha1nexte %xmm15,%xmm8",}, | ||
403 | {{0x0f, 0x38, 0xc8, 0x00, }, 4, 0, "", "", | ||
404 | "0f 38 c8 00 \tsha1nexte (%rax),%xmm0",}, | ||
405 | {{0x41, 0x0f, 0x38, 0xc8, 0x00, }, 5, 0, "", "", | ||
406 | "41 0f 38 c8 00 \tsha1nexte (%r8),%xmm0",}, | ||
407 | {{0x0f, 0x38, 0xc8, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
408 | "0f 38 c8 04 25 78 56 34 12 \tsha1nexte 0x12345678,%xmm0",}, | ||
409 | {{0x0f, 0x38, 0xc8, 0x18, }, 4, 0, "", "", | ||
410 | "0f 38 c8 18 \tsha1nexte (%rax),%xmm3",}, | ||
411 | {{0x0f, 0x38, 0xc8, 0x04, 0x01, }, 5, 0, "", "", | ||
412 | "0f 38 c8 04 01 \tsha1nexte (%rcx,%rax,1),%xmm0",}, | ||
413 | {{0x0f, 0x38, 0xc8, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
414 | "0f 38 c8 04 05 78 56 34 12 \tsha1nexte 0x12345678(,%rax,1),%xmm0",}, | ||
415 | {{0x0f, 0x38, 0xc8, 0x04, 0x08, }, 5, 0, "", "", | ||
416 | "0f 38 c8 04 08 \tsha1nexte (%rax,%rcx,1),%xmm0",}, | ||
417 | {{0x0f, 0x38, 0xc8, 0x04, 0xc8, }, 5, 0, "", "", | ||
418 | "0f 38 c8 04 c8 \tsha1nexte (%rax,%rcx,8),%xmm0",}, | ||
419 | {{0x0f, 0x38, 0xc8, 0x40, 0x12, }, 5, 0, "", "", | ||
420 | "0f 38 c8 40 12 \tsha1nexte 0x12(%rax),%xmm0",}, | ||
421 | {{0x0f, 0x38, 0xc8, 0x45, 0x12, }, 5, 0, "", "", | ||
422 | "0f 38 c8 45 12 \tsha1nexte 0x12(%rbp),%xmm0",}, | ||
423 | {{0x0f, 0x38, 0xc8, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
424 | "0f 38 c8 44 01 12 \tsha1nexte 0x12(%rcx,%rax,1),%xmm0",}, | ||
425 | {{0x0f, 0x38, 0xc8, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
426 | "0f 38 c8 44 05 12 \tsha1nexte 0x12(%rbp,%rax,1),%xmm0",}, | ||
427 | {{0x0f, 0x38, 0xc8, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
428 | "0f 38 c8 44 08 12 \tsha1nexte 0x12(%rax,%rcx,1),%xmm0",}, | ||
429 | {{0x0f, 0x38, 0xc8, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
430 | "0f 38 c8 44 c8 12 \tsha1nexte 0x12(%rax,%rcx,8),%xmm0",}, | ||
431 | {{0x0f, 0x38, 0xc8, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
432 | "0f 38 c8 80 78 56 34 12 \tsha1nexte 0x12345678(%rax),%xmm0",}, | ||
433 | {{0x0f, 0x38, 0xc8, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
434 | "0f 38 c8 85 78 56 34 12 \tsha1nexte 0x12345678(%rbp),%xmm0",}, | ||
435 | {{0x0f, 0x38, 0xc8, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
436 | "0f 38 c8 84 01 78 56 34 12 \tsha1nexte 0x12345678(%rcx,%rax,1),%xmm0",}, | ||
437 | {{0x0f, 0x38, 0xc8, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
438 | "0f 38 c8 84 05 78 56 34 12 \tsha1nexte 0x12345678(%rbp,%rax,1),%xmm0",}, | ||
439 | {{0x0f, 0x38, 0xc8, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
440 | "0f 38 c8 84 08 78 56 34 12 \tsha1nexte 0x12345678(%rax,%rcx,1),%xmm0",}, | ||
441 | {{0x0f, 0x38, 0xc8, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
442 | "0f 38 c8 84 c8 78 56 34 12 \tsha1nexte 0x12345678(%rax,%rcx,8),%xmm0",}, | ||
443 | {{0x44, 0x0f, 0x38, 0xc8, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
444 | "44 0f 38 c8 bc c8 78 56 34 12 \tsha1nexte 0x12345678(%rax,%rcx,8),%xmm15",}, | ||
445 | {{0x0f, 0x38, 0xc9, 0xc1, }, 4, 0, "", "", | ||
446 | "0f 38 c9 c1 \tsha1msg1 %xmm1,%xmm0",}, | ||
447 | {{0x0f, 0x38, 0xc9, 0xd7, }, 4, 0, "", "", | ||
448 | "0f 38 c9 d7 \tsha1msg1 %xmm7,%xmm2",}, | ||
449 | {{0x41, 0x0f, 0x38, 0xc9, 0xc0, }, 5, 0, "", "", | ||
450 | "41 0f 38 c9 c0 \tsha1msg1 %xmm8,%xmm0",}, | ||
451 | {{0x44, 0x0f, 0x38, 0xc9, 0xc7, }, 5, 0, "", "", | ||
452 | "44 0f 38 c9 c7 \tsha1msg1 %xmm7,%xmm8",}, | ||
453 | {{0x45, 0x0f, 0x38, 0xc9, 0xc7, }, 5, 0, "", "", | ||
454 | "45 0f 38 c9 c7 \tsha1msg1 %xmm15,%xmm8",}, | ||
455 | {{0x0f, 0x38, 0xc9, 0x00, }, 4, 0, "", "", | ||
456 | "0f 38 c9 00 \tsha1msg1 (%rax),%xmm0",}, | ||
457 | {{0x41, 0x0f, 0x38, 0xc9, 0x00, }, 5, 0, "", "", | ||
458 | "41 0f 38 c9 00 \tsha1msg1 (%r8),%xmm0",}, | ||
459 | {{0x0f, 0x38, 0xc9, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
460 | "0f 38 c9 04 25 78 56 34 12 \tsha1msg1 0x12345678,%xmm0",}, | ||
461 | {{0x0f, 0x38, 0xc9, 0x18, }, 4, 0, "", "", | ||
462 | "0f 38 c9 18 \tsha1msg1 (%rax),%xmm3",}, | ||
463 | {{0x0f, 0x38, 0xc9, 0x04, 0x01, }, 5, 0, "", "", | ||
464 | "0f 38 c9 04 01 \tsha1msg1 (%rcx,%rax,1),%xmm0",}, | ||
465 | {{0x0f, 0x38, 0xc9, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
466 | "0f 38 c9 04 05 78 56 34 12 \tsha1msg1 0x12345678(,%rax,1),%xmm0",}, | ||
467 | {{0x0f, 0x38, 0xc9, 0x04, 0x08, }, 5, 0, "", "", | ||
468 | "0f 38 c9 04 08 \tsha1msg1 (%rax,%rcx,1),%xmm0",}, | ||
469 | {{0x0f, 0x38, 0xc9, 0x04, 0xc8, }, 5, 0, "", "", | ||
470 | "0f 38 c9 04 c8 \tsha1msg1 (%rax,%rcx,8),%xmm0",}, | ||
471 | {{0x0f, 0x38, 0xc9, 0x40, 0x12, }, 5, 0, "", "", | ||
472 | "0f 38 c9 40 12 \tsha1msg1 0x12(%rax),%xmm0",}, | ||
473 | {{0x0f, 0x38, 0xc9, 0x45, 0x12, }, 5, 0, "", "", | ||
474 | "0f 38 c9 45 12 \tsha1msg1 0x12(%rbp),%xmm0",}, | ||
475 | {{0x0f, 0x38, 0xc9, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
476 | "0f 38 c9 44 01 12 \tsha1msg1 0x12(%rcx,%rax,1),%xmm0",}, | ||
477 | {{0x0f, 0x38, 0xc9, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
478 | "0f 38 c9 44 05 12 \tsha1msg1 0x12(%rbp,%rax,1),%xmm0",}, | ||
479 | {{0x0f, 0x38, 0xc9, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
480 | "0f 38 c9 44 08 12 \tsha1msg1 0x12(%rax,%rcx,1),%xmm0",}, | ||
481 | {{0x0f, 0x38, 0xc9, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
482 | "0f 38 c9 44 c8 12 \tsha1msg1 0x12(%rax,%rcx,8),%xmm0",}, | ||
483 | {{0x0f, 0x38, 0xc9, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
484 | "0f 38 c9 80 78 56 34 12 \tsha1msg1 0x12345678(%rax),%xmm0",}, | ||
485 | {{0x0f, 0x38, 0xc9, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
486 | "0f 38 c9 85 78 56 34 12 \tsha1msg1 0x12345678(%rbp),%xmm0",}, | ||
487 | {{0x0f, 0x38, 0xc9, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
488 | "0f 38 c9 84 01 78 56 34 12 \tsha1msg1 0x12345678(%rcx,%rax,1),%xmm0",}, | ||
489 | {{0x0f, 0x38, 0xc9, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
490 | "0f 38 c9 84 05 78 56 34 12 \tsha1msg1 0x12345678(%rbp,%rax,1),%xmm0",}, | ||
491 | {{0x0f, 0x38, 0xc9, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
492 | "0f 38 c9 84 08 78 56 34 12 \tsha1msg1 0x12345678(%rax,%rcx,1),%xmm0",}, | ||
493 | {{0x0f, 0x38, 0xc9, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
494 | "0f 38 c9 84 c8 78 56 34 12 \tsha1msg1 0x12345678(%rax,%rcx,8),%xmm0",}, | ||
495 | {{0x44, 0x0f, 0x38, 0xc9, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
496 | "44 0f 38 c9 bc c8 78 56 34 12 \tsha1msg1 0x12345678(%rax,%rcx,8),%xmm15",}, | ||
497 | {{0x0f, 0x38, 0xca, 0xc1, }, 4, 0, "", "", | ||
498 | "0f 38 ca c1 \tsha1msg2 %xmm1,%xmm0",}, | ||
499 | {{0x0f, 0x38, 0xca, 0xd7, }, 4, 0, "", "", | ||
500 | "0f 38 ca d7 \tsha1msg2 %xmm7,%xmm2",}, | ||
501 | {{0x41, 0x0f, 0x38, 0xca, 0xc0, }, 5, 0, "", "", | ||
502 | "41 0f 38 ca c0 \tsha1msg2 %xmm8,%xmm0",}, | ||
503 | {{0x44, 0x0f, 0x38, 0xca, 0xc7, }, 5, 0, "", "", | ||
504 | "44 0f 38 ca c7 \tsha1msg2 %xmm7,%xmm8",}, | ||
505 | {{0x45, 0x0f, 0x38, 0xca, 0xc7, }, 5, 0, "", "", | ||
506 | "45 0f 38 ca c7 \tsha1msg2 %xmm15,%xmm8",}, | ||
507 | {{0x0f, 0x38, 0xca, 0x00, }, 4, 0, "", "", | ||
508 | "0f 38 ca 00 \tsha1msg2 (%rax),%xmm0",}, | ||
509 | {{0x41, 0x0f, 0x38, 0xca, 0x00, }, 5, 0, "", "", | ||
510 | "41 0f 38 ca 00 \tsha1msg2 (%r8),%xmm0",}, | ||
511 | {{0x0f, 0x38, 0xca, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
512 | "0f 38 ca 04 25 78 56 34 12 \tsha1msg2 0x12345678,%xmm0",}, | ||
513 | {{0x0f, 0x38, 0xca, 0x18, }, 4, 0, "", "", | ||
514 | "0f 38 ca 18 \tsha1msg2 (%rax),%xmm3",}, | ||
515 | {{0x0f, 0x38, 0xca, 0x04, 0x01, }, 5, 0, "", "", | ||
516 | "0f 38 ca 04 01 \tsha1msg2 (%rcx,%rax,1),%xmm0",}, | ||
517 | {{0x0f, 0x38, 0xca, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
518 | "0f 38 ca 04 05 78 56 34 12 \tsha1msg2 0x12345678(,%rax,1),%xmm0",}, | ||
519 | {{0x0f, 0x38, 0xca, 0x04, 0x08, }, 5, 0, "", "", | ||
520 | "0f 38 ca 04 08 \tsha1msg2 (%rax,%rcx,1),%xmm0",}, | ||
521 | {{0x0f, 0x38, 0xca, 0x04, 0xc8, }, 5, 0, "", "", | ||
522 | "0f 38 ca 04 c8 \tsha1msg2 (%rax,%rcx,8),%xmm0",}, | ||
523 | {{0x0f, 0x38, 0xca, 0x40, 0x12, }, 5, 0, "", "", | ||
524 | "0f 38 ca 40 12 \tsha1msg2 0x12(%rax),%xmm0",}, | ||
525 | {{0x0f, 0x38, 0xca, 0x45, 0x12, }, 5, 0, "", "", | ||
526 | "0f 38 ca 45 12 \tsha1msg2 0x12(%rbp),%xmm0",}, | ||
527 | {{0x0f, 0x38, 0xca, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
528 | "0f 38 ca 44 01 12 \tsha1msg2 0x12(%rcx,%rax,1),%xmm0",}, | ||
529 | {{0x0f, 0x38, 0xca, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
530 | "0f 38 ca 44 05 12 \tsha1msg2 0x12(%rbp,%rax,1),%xmm0",}, | ||
531 | {{0x0f, 0x38, 0xca, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
532 | "0f 38 ca 44 08 12 \tsha1msg2 0x12(%rax,%rcx,1),%xmm0",}, | ||
533 | {{0x0f, 0x38, 0xca, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
534 | "0f 38 ca 44 c8 12 \tsha1msg2 0x12(%rax,%rcx,8),%xmm0",}, | ||
535 | {{0x0f, 0x38, 0xca, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
536 | "0f 38 ca 80 78 56 34 12 \tsha1msg2 0x12345678(%rax),%xmm0",}, | ||
537 | {{0x0f, 0x38, 0xca, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
538 | "0f 38 ca 85 78 56 34 12 \tsha1msg2 0x12345678(%rbp),%xmm0",}, | ||
539 | {{0x0f, 0x38, 0xca, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
540 | "0f 38 ca 84 01 78 56 34 12 \tsha1msg2 0x12345678(%rcx,%rax,1),%xmm0",}, | ||
541 | {{0x0f, 0x38, 0xca, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
542 | "0f 38 ca 84 05 78 56 34 12 \tsha1msg2 0x12345678(%rbp,%rax,1),%xmm0",}, | ||
543 | {{0x0f, 0x38, 0xca, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
544 | "0f 38 ca 84 08 78 56 34 12 \tsha1msg2 0x12345678(%rax,%rcx,1),%xmm0",}, | ||
545 | {{0x0f, 0x38, 0xca, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
546 | "0f 38 ca 84 c8 78 56 34 12 \tsha1msg2 0x12345678(%rax,%rcx,8),%xmm0",}, | ||
547 | {{0x44, 0x0f, 0x38, 0xca, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
548 | "44 0f 38 ca bc c8 78 56 34 12 \tsha1msg2 0x12345678(%rax,%rcx,8),%xmm15",}, | ||
549 | {{0x0f, 0x38, 0xcb, 0xcc, }, 4, 0, "", "", | ||
550 | "0f 38 cb cc \tsha256rnds2 %xmm0,%xmm4,%xmm1",}, | ||
551 | {{0x0f, 0x38, 0xcb, 0xd7, }, 4, 0, "", "", | ||
552 | "0f 38 cb d7 \tsha256rnds2 %xmm0,%xmm7,%xmm2",}, | ||
553 | {{0x41, 0x0f, 0x38, 0xcb, 0xc8, }, 5, 0, "", "", | ||
554 | "41 0f 38 cb c8 \tsha256rnds2 %xmm0,%xmm8,%xmm1",}, | ||
555 | {{0x44, 0x0f, 0x38, 0xcb, 0xc7, }, 5, 0, "", "", | ||
556 | "44 0f 38 cb c7 \tsha256rnds2 %xmm0,%xmm7,%xmm8",}, | ||
557 | {{0x45, 0x0f, 0x38, 0xcb, 0xc7, }, 5, 0, "", "", | ||
558 | "45 0f 38 cb c7 \tsha256rnds2 %xmm0,%xmm15,%xmm8",}, | ||
559 | {{0x0f, 0x38, 0xcb, 0x08, }, 4, 0, "", "", | ||
560 | "0f 38 cb 08 \tsha256rnds2 %xmm0,(%rax),%xmm1",}, | ||
561 | {{0x41, 0x0f, 0x38, 0xcb, 0x08, }, 5, 0, "", "", | ||
562 | "41 0f 38 cb 08 \tsha256rnds2 %xmm0,(%r8),%xmm1",}, | ||
563 | {{0x0f, 0x38, 0xcb, 0x0c, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
564 | "0f 38 cb 0c 25 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678,%xmm1",}, | ||
565 | {{0x0f, 0x38, 0xcb, 0x18, }, 4, 0, "", "", | ||
566 | "0f 38 cb 18 \tsha256rnds2 %xmm0,(%rax),%xmm3",}, | ||
567 | {{0x0f, 0x38, 0xcb, 0x0c, 0x01, }, 5, 0, "", "", | ||
568 | "0f 38 cb 0c 01 \tsha256rnds2 %xmm0,(%rcx,%rax,1),%xmm1",}, | ||
569 | {{0x0f, 0x38, 0xcb, 0x0c, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
570 | "0f 38 cb 0c 05 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(,%rax,1),%xmm1",}, | ||
571 | {{0x0f, 0x38, 0xcb, 0x0c, 0x08, }, 5, 0, "", "", | ||
572 | "0f 38 cb 0c 08 \tsha256rnds2 %xmm0,(%rax,%rcx,1),%xmm1",}, | ||
573 | {{0x0f, 0x38, 0xcb, 0x0c, 0xc8, }, 5, 0, "", "", | ||
574 | "0f 38 cb 0c c8 \tsha256rnds2 %xmm0,(%rax,%rcx,8),%xmm1",}, | ||
575 | {{0x0f, 0x38, 0xcb, 0x48, 0x12, }, 5, 0, "", "", | ||
576 | "0f 38 cb 48 12 \tsha256rnds2 %xmm0,0x12(%rax),%xmm1",}, | ||
577 | {{0x0f, 0x38, 0xcb, 0x4d, 0x12, }, 5, 0, "", "", | ||
578 | "0f 38 cb 4d 12 \tsha256rnds2 %xmm0,0x12(%rbp),%xmm1",}, | ||
579 | {{0x0f, 0x38, 0xcb, 0x4c, 0x01, 0x12, }, 6, 0, "", "", | ||
580 | "0f 38 cb 4c 01 12 \tsha256rnds2 %xmm0,0x12(%rcx,%rax,1),%xmm1",}, | ||
581 | {{0x0f, 0x38, 0xcb, 0x4c, 0x05, 0x12, }, 6, 0, "", "", | ||
582 | "0f 38 cb 4c 05 12 \tsha256rnds2 %xmm0,0x12(%rbp,%rax,1),%xmm1",}, | ||
583 | {{0x0f, 0x38, 0xcb, 0x4c, 0x08, 0x12, }, 6, 0, "", "", | ||
584 | "0f 38 cb 4c 08 12 \tsha256rnds2 %xmm0,0x12(%rax,%rcx,1),%xmm1",}, | ||
585 | {{0x0f, 0x38, 0xcb, 0x4c, 0xc8, 0x12, }, 6, 0, "", "", | ||
586 | "0f 38 cb 4c c8 12 \tsha256rnds2 %xmm0,0x12(%rax,%rcx,8),%xmm1",}, | ||
587 | {{0x0f, 0x38, 0xcb, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
588 | "0f 38 cb 88 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rax),%xmm1",}, | ||
589 | {{0x0f, 0x38, 0xcb, 0x8d, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
590 | "0f 38 cb 8d 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rbp),%xmm1",}, | ||
591 | {{0x0f, 0x38, 0xcb, 0x8c, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
592 | "0f 38 cb 8c 01 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rcx,%rax,1),%xmm1",}, | ||
593 | {{0x0f, 0x38, 0xcb, 0x8c, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
594 | "0f 38 cb 8c 05 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rbp,%rax,1),%xmm1",}, | ||
595 | {{0x0f, 0x38, 0xcb, 0x8c, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
596 | "0f 38 cb 8c 08 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rax,%rcx,1),%xmm1",}, | ||
597 | {{0x0f, 0x38, 0xcb, 0x8c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
598 | "0f 38 cb 8c c8 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rax,%rcx,8),%xmm1",}, | ||
599 | {{0x44, 0x0f, 0x38, 0xcb, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
600 | "44 0f 38 cb bc c8 78 56 34 12 \tsha256rnds2 %xmm0,0x12345678(%rax,%rcx,8),%xmm15",}, | ||
601 | {{0x0f, 0x38, 0xcc, 0xc1, }, 4, 0, "", "", | ||
602 | "0f 38 cc c1 \tsha256msg1 %xmm1,%xmm0",}, | ||
603 | {{0x0f, 0x38, 0xcc, 0xd7, }, 4, 0, "", "", | ||
604 | "0f 38 cc d7 \tsha256msg1 %xmm7,%xmm2",}, | ||
605 | {{0x41, 0x0f, 0x38, 0xcc, 0xc0, }, 5, 0, "", "", | ||
606 | "41 0f 38 cc c0 \tsha256msg1 %xmm8,%xmm0",}, | ||
607 | {{0x44, 0x0f, 0x38, 0xcc, 0xc7, }, 5, 0, "", "", | ||
608 | "44 0f 38 cc c7 \tsha256msg1 %xmm7,%xmm8",}, | ||
609 | {{0x45, 0x0f, 0x38, 0xcc, 0xc7, }, 5, 0, "", "", | ||
610 | "45 0f 38 cc c7 \tsha256msg1 %xmm15,%xmm8",}, | ||
611 | {{0x0f, 0x38, 0xcc, 0x00, }, 4, 0, "", "", | ||
612 | "0f 38 cc 00 \tsha256msg1 (%rax),%xmm0",}, | ||
613 | {{0x41, 0x0f, 0x38, 0xcc, 0x00, }, 5, 0, "", "", | ||
614 | "41 0f 38 cc 00 \tsha256msg1 (%r8),%xmm0",}, | ||
615 | {{0x0f, 0x38, 0xcc, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
616 | "0f 38 cc 04 25 78 56 34 12 \tsha256msg1 0x12345678,%xmm0",}, | ||
617 | {{0x0f, 0x38, 0xcc, 0x18, }, 4, 0, "", "", | ||
618 | "0f 38 cc 18 \tsha256msg1 (%rax),%xmm3",}, | ||
619 | {{0x0f, 0x38, 0xcc, 0x04, 0x01, }, 5, 0, "", "", | ||
620 | "0f 38 cc 04 01 \tsha256msg1 (%rcx,%rax,1),%xmm0",}, | ||
621 | {{0x0f, 0x38, 0xcc, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
622 | "0f 38 cc 04 05 78 56 34 12 \tsha256msg1 0x12345678(,%rax,1),%xmm0",}, | ||
623 | {{0x0f, 0x38, 0xcc, 0x04, 0x08, }, 5, 0, "", "", | ||
624 | "0f 38 cc 04 08 \tsha256msg1 (%rax,%rcx,1),%xmm0",}, | ||
625 | {{0x0f, 0x38, 0xcc, 0x04, 0xc8, }, 5, 0, "", "", | ||
626 | "0f 38 cc 04 c8 \tsha256msg1 (%rax,%rcx,8),%xmm0",}, | ||
627 | {{0x0f, 0x38, 0xcc, 0x40, 0x12, }, 5, 0, "", "", | ||
628 | "0f 38 cc 40 12 \tsha256msg1 0x12(%rax),%xmm0",}, | ||
629 | {{0x0f, 0x38, 0xcc, 0x45, 0x12, }, 5, 0, "", "", | ||
630 | "0f 38 cc 45 12 \tsha256msg1 0x12(%rbp),%xmm0",}, | ||
631 | {{0x0f, 0x38, 0xcc, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
632 | "0f 38 cc 44 01 12 \tsha256msg1 0x12(%rcx,%rax,1),%xmm0",}, | ||
633 | {{0x0f, 0x38, 0xcc, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
634 | "0f 38 cc 44 05 12 \tsha256msg1 0x12(%rbp,%rax,1),%xmm0",}, | ||
635 | {{0x0f, 0x38, 0xcc, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
636 | "0f 38 cc 44 08 12 \tsha256msg1 0x12(%rax,%rcx,1),%xmm0",}, | ||
637 | {{0x0f, 0x38, 0xcc, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
638 | "0f 38 cc 44 c8 12 \tsha256msg1 0x12(%rax,%rcx,8),%xmm0",}, | ||
639 | {{0x0f, 0x38, 0xcc, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
640 | "0f 38 cc 80 78 56 34 12 \tsha256msg1 0x12345678(%rax),%xmm0",}, | ||
641 | {{0x0f, 0x38, 0xcc, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
642 | "0f 38 cc 85 78 56 34 12 \tsha256msg1 0x12345678(%rbp),%xmm0",}, | ||
643 | {{0x0f, 0x38, 0xcc, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
644 | "0f 38 cc 84 01 78 56 34 12 \tsha256msg1 0x12345678(%rcx,%rax,1),%xmm0",}, | ||
645 | {{0x0f, 0x38, 0xcc, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
646 | "0f 38 cc 84 05 78 56 34 12 \tsha256msg1 0x12345678(%rbp,%rax,1),%xmm0",}, | ||
647 | {{0x0f, 0x38, 0xcc, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
648 | "0f 38 cc 84 08 78 56 34 12 \tsha256msg1 0x12345678(%rax,%rcx,1),%xmm0",}, | ||
649 | {{0x0f, 0x38, 0xcc, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
650 | "0f 38 cc 84 c8 78 56 34 12 \tsha256msg1 0x12345678(%rax,%rcx,8),%xmm0",}, | ||
651 | {{0x44, 0x0f, 0x38, 0xcc, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
652 | "44 0f 38 cc bc c8 78 56 34 12 \tsha256msg1 0x12345678(%rax,%rcx,8),%xmm15",}, | ||
653 | {{0x0f, 0x38, 0xcd, 0xc1, }, 4, 0, "", "", | ||
654 | "0f 38 cd c1 \tsha256msg2 %xmm1,%xmm0",}, | ||
655 | {{0x0f, 0x38, 0xcd, 0xd7, }, 4, 0, "", "", | ||
656 | "0f 38 cd d7 \tsha256msg2 %xmm7,%xmm2",}, | ||
657 | {{0x41, 0x0f, 0x38, 0xcd, 0xc0, }, 5, 0, "", "", | ||
658 | "41 0f 38 cd c0 \tsha256msg2 %xmm8,%xmm0",}, | ||
659 | {{0x44, 0x0f, 0x38, 0xcd, 0xc7, }, 5, 0, "", "", | ||
660 | "44 0f 38 cd c7 \tsha256msg2 %xmm7,%xmm8",}, | ||
661 | {{0x45, 0x0f, 0x38, 0xcd, 0xc7, }, 5, 0, "", "", | ||
662 | "45 0f 38 cd c7 \tsha256msg2 %xmm15,%xmm8",}, | ||
663 | {{0x0f, 0x38, 0xcd, 0x00, }, 4, 0, "", "", | ||
664 | "0f 38 cd 00 \tsha256msg2 (%rax),%xmm0",}, | ||
665 | {{0x41, 0x0f, 0x38, 0xcd, 0x00, }, 5, 0, "", "", | ||
666 | "41 0f 38 cd 00 \tsha256msg2 (%r8),%xmm0",}, | ||
667 | {{0x0f, 0x38, 0xcd, 0x04, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
668 | "0f 38 cd 04 25 78 56 34 12 \tsha256msg2 0x12345678,%xmm0",}, | ||
669 | {{0x0f, 0x38, 0xcd, 0x18, }, 4, 0, "", "", | ||
670 | "0f 38 cd 18 \tsha256msg2 (%rax),%xmm3",}, | ||
671 | {{0x0f, 0x38, 0xcd, 0x04, 0x01, }, 5, 0, "", "", | ||
672 | "0f 38 cd 04 01 \tsha256msg2 (%rcx,%rax,1),%xmm0",}, | ||
673 | {{0x0f, 0x38, 0xcd, 0x04, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
674 | "0f 38 cd 04 05 78 56 34 12 \tsha256msg2 0x12345678(,%rax,1),%xmm0",}, | ||
675 | {{0x0f, 0x38, 0xcd, 0x04, 0x08, }, 5, 0, "", "", | ||
676 | "0f 38 cd 04 08 \tsha256msg2 (%rax,%rcx,1),%xmm0",}, | ||
677 | {{0x0f, 0x38, 0xcd, 0x04, 0xc8, }, 5, 0, "", "", | ||
678 | "0f 38 cd 04 c8 \tsha256msg2 (%rax,%rcx,8),%xmm0",}, | ||
679 | {{0x0f, 0x38, 0xcd, 0x40, 0x12, }, 5, 0, "", "", | ||
680 | "0f 38 cd 40 12 \tsha256msg2 0x12(%rax),%xmm0",}, | ||
681 | {{0x0f, 0x38, 0xcd, 0x45, 0x12, }, 5, 0, "", "", | ||
682 | "0f 38 cd 45 12 \tsha256msg2 0x12(%rbp),%xmm0",}, | ||
683 | {{0x0f, 0x38, 0xcd, 0x44, 0x01, 0x12, }, 6, 0, "", "", | ||
684 | "0f 38 cd 44 01 12 \tsha256msg2 0x12(%rcx,%rax,1),%xmm0",}, | ||
685 | {{0x0f, 0x38, 0xcd, 0x44, 0x05, 0x12, }, 6, 0, "", "", | ||
686 | "0f 38 cd 44 05 12 \tsha256msg2 0x12(%rbp,%rax,1),%xmm0",}, | ||
687 | {{0x0f, 0x38, 0xcd, 0x44, 0x08, 0x12, }, 6, 0, "", "", | ||
688 | "0f 38 cd 44 08 12 \tsha256msg2 0x12(%rax,%rcx,1),%xmm0",}, | ||
689 | {{0x0f, 0x38, 0xcd, 0x44, 0xc8, 0x12, }, 6, 0, "", "", | ||
690 | "0f 38 cd 44 c8 12 \tsha256msg2 0x12(%rax,%rcx,8),%xmm0",}, | ||
691 | {{0x0f, 0x38, 0xcd, 0x80, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
692 | "0f 38 cd 80 78 56 34 12 \tsha256msg2 0x12345678(%rax),%xmm0",}, | ||
693 | {{0x0f, 0x38, 0xcd, 0x85, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
694 | "0f 38 cd 85 78 56 34 12 \tsha256msg2 0x12345678(%rbp),%xmm0",}, | ||
695 | {{0x0f, 0x38, 0xcd, 0x84, 0x01, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
696 | "0f 38 cd 84 01 78 56 34 12 \tsha256msg2 0x12345678(%rcx,%rax,1),%xmm0",}, | ||
697 | {{0x0f, 0x38, 0xcd, 0x84, 0x05, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
698 | "0f 38 cd 84 05 78 56 34 12 \tsha256msg2 0x12345678(%rbp,%rax,1),%xmm0",}, | ||
699 | {{0x0f, 0x38, 0xcd, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
700 | "0f 38 cd 84 08 78 56 34 12 \tsha256msg2 0x12345678(%rax,%rcx,1),%xmm0",}, | ||
701 | {{0x0f, 0x38, 0xcd, 0x84, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
702 | "0f 38 cd 84 c8 78 56 34 12 \tsha256msg2 0x12345678(%rax,%rcx,8),%xmm0",}, | ||
703 | {{0x44, 0x0f, 0x38, 0xcd, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
704 | "44 0f 38 cd bc c8 78 56 34 12 \tsha256msg2 0x12345678(%rax,%rcx,8),%xmm15",}, | ||
705 | {{0x66, 0x0f, 0xae, 0x38, }, 4, 0, "", "", | ||
706 | "66 0f ae 38 \tclflushopt (%rax)",}, | ||
707 | {{0x66, 0x41, 0x0f, 0xae, 0x38, }, 5, 0, "", "", | ||
708 | "66 41 0f ae 38 \tclflushopt (%r8)",}, | ||
709 | {{0x66, 0x0f, 0xae, 0x3c, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
710 | "66 0f ae 3c 25 78 56 34 12 \tclflushopt 0x12345678",}, | ||
711 | {{0x66, 0x0f, 0xae, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
712 | "66 0f ae bc c8 78 56 34 12 \tclflushopt 0x12345678(%rax,%rcx,8)",}, | ||
713 | {{0x66, 0x41, 0x0f, 0xae, 0xbc, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
714 | "66 41 0f ae bc c8 78 56 34 12 \tclflushopt 0x12345678(%r8,%rcx,8)",}, | ||
715 | {{0x0f, 0xae, 0x38, }, 3, 0, "", "", | ||
716 | "0f ae 38 \tclflush (%rax)",}, | ||
717 | {{0x41, 0x0f, 0xae, 0x38, }, 4, 0, "", "", | ||
718 | "41 0f ae 38 \tclflush (%r8)",}, | ||
719 | {{0x0f, 0xae, 0xf8, }, 3, 0, "", "", | ||
720 | "0f ae f8 \tsfence ",}, | ||
721 | {{0x66, 0x0f, 0xae, 0x30, }, 4, 0, "", "", | ||
722 | "66 0f ae 30 \tclwb (%rax)",}, | ||
723 | {{0x66, 0x41, 0x0f, 0xae, 0x30, }, 5, 0, "", "", | ||
724 | "66 41 0f ae 30 \tclwb (%r8)",}, | ||
725 | {{0x66, 0x0f, 0xae, 0x34, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
726 | "66 0f ae 34 25 78 56 34 12 \tclwb 0x12345678",}, | ||
727 | {{0x66, 0x0f, 0xae, 0xb4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
728 | "66 0f ae b4 c8 78 56 34 12 \tclwb 0x12345678(%rax,%rcx,8)",}, | ||
729 | {{0x66, 0x41, 0x0f, 0xae, 0xb4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
730 | "66 41 0f ae b4 c8 78 56 34 12 \tclwb 0x12345678(%r8,%rcx,8)",}, | ||
731 | {{0x0f, 0xae, 0x30, }, 3, 0, "", "", | ||
732 | "0f ae 30 \txsaveopt (%rax)",}, | ||
733 | {{0x41, 0x0f, 0xae, 0x30, }, 4, 0, "", "", | ||
734 | "41 0f ae 30 \txsaveopt (%r8)",}, | ||
735 | {{0x0f, 0xae, 0xf0, }, 3, 0, "", "", | ||
736 | "0f ae f0 \tmfence ",}, | ||
737 | {{0x0f, 0xc7, 0x20, }, 3, 0, "", "", | ||
738 | "0f c7 20 \txsavec (%rax)",}, | ||
739 | {{0x41, 0x0f, 0xc7, 0x20, }, 4, 0, "", "", | ||
740 | "41 0f c7 20 \txsavec (%r8)",}, | ||
741 | {{0x0f, 0xc7, 0x24, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
742 | "0f c7 24 25 78 56 34 12 \txsavec 0x12345678",}, | ||
743 | {{0x0f, 0xc7, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
744 | "0f c7 a4 c8 78 56 34 12 \txsavec 0x12345678(%rax,%rcx,8)",}, | ||
745 | {{0x41, 0x0f, 0xc7, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
746 | "41 0f c7 a4 c8 78 56 34 12 \txsavec 0x12345678(%r8,%rcx,8)",}, | ||
747 | {{0x0f, 0xc7, 0x28, }, 3, 0, "", "", | ||
748 | "0f c7 28 \txsaves (%rax)",}, | ||
749 | {{0x41, 0x0f, 0xc7, 0x28, }, 4, 0, "", "", | ||
750 | "41 0f c7 28 \txsaves (%r8)",}, | ||
751 | {{0x0f, 0xc7, 0x2c, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
752 | "0f c7 2c 25 78 56 34 12 \txsaves 0x12345678",}, | ||
753 | {{0x0f, 0xc7, 0xac, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
754 | "0f c7 ac c8 78 56 34 12 \txsaves 0x12345678(%rax,%rcx,8)",}, | ||
755 | {{0x41, 0x0f, 0xc7, 0xac, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
756 | "41 0f c7 ac c8 78 56 34 12 \txsaves 0x12345678(%r8,%rcx,8)",}, | ||
757 | {{0x0f, 0xc7, 0x18, }, 3, 0, "", "", | ||
758 | "0f c7 18 \txrstors (%rax)",}, | ||
759 | {{0x41, 0x0f, 0xc7, 0x18, }, 4, 0, "", "", | ||
760 | "41 0f c7 18 \txrstors (%r8)",}, | ||
761 | {{0x0f, 0xc7, 0x1c, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
762 | "0f c7 1c 25 78 56 34 12 \txrstors 0x12345678",}, | ||
763 | {{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
764 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",}, | ||
765 | {{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
766 | "41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",}, | ||
767 | {{0x66, 0x0f, 0xae, 0xf8, }, 4, 0, "", "", | ||
768 | "66 0f ae f8 \tpcommit ",}, | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-src.c b/tools/perf/arch/x86/tests/insn-x86-dat-src.c new file mode 100644 index 000000000000..41b1b1c62660 --- /dev/null +++ b/tools/perf/arch/x86/tests/insn-x86-dat-src.c | |||
@@ -0,0 +1,877 @@ | |||
1 | /* | ||
2 | * This file contains instructions for testing by the test titled: | ||
3 | * | ||
4 | * "Test x86 instruction decoder - new instructions" | ||
5 | * | ||
6 | * Note that the 'Expecting' comment lines are consumed by the | ||
7 | * gen-insn-x86-dat.awk script and have the format: | ||
8 | * | ||
9 | * Expecting: <op> <branch> <rel> | ||
10 | * | ||
11 | * If this file is changed, remember to run the gen-insn-x86-dat.sh | ||
12 | * script and commit the result. | ||
13 | * | ||
14 | * Refer to insn-x86.c for more details. | ||
15 | */ | ||
16 | |||
17 | int main(void) | ||
18 | { | ||
19 | /* Following line is a marker for the awk script - do not change */ | ||
20 | asm volatile("rdtsc"); /* Start here */ | ||
21 | |||
22 | #ifdef __x86_64__ | ||
23 | |||
24 | /* bndmk m64, bnd */ | ||
25 | |||
26 | asm volatile("bndmk (%rax), %bnd0"); | ||
27 | asm volatile("bndmk (%r8), %bnd0"); | ||
28 | asm volatile("bndmk (0x12345678), %bnd0"); | ||
29 | asm volatile("bndmk (%rax), %bnd3"); | ||
30 | asm volatile("bndmk (%rcx,%rax,1), %bnd0"); | ||
31 | asm volatile("bndmk 0x12345678(,%rax,1), %bnd0"); | ||
32 | asm volatile("bndmk (%rax,%rcx,1), %bnd0"); | ||
33 | asm volatile("bndmk (%rax,%rcx,8), %bnd0"); | ||
34 | asm volatile("bndmk 0x12(%rax), %bnd0"); | ||
35 | asm volatile("bndmk 0x12(%rbp), %bnd0"); | ||
36 | asm volatile("bndmk 0x12(%rcx,%rax,1), %bnd0"); | ||
37 | asm volatile("bndmk 0x12(%rbp,%rax,1), %bnd0"); | ||
38 | asm volatile("bndmk 0x12(%rax,%rcx,1), %bnd0"); | ||
39 | asm volatile("bndmk 0x12(%rax,%rcx,8), %bnd0"); | ||
40 | asm volatile("bndmk 0x12345678(%rax), %bnd0"); | ||
41 | asm volatile("bndmk 0x12345678(%rbp), %bnd0"); | ||
42 | asm volatile("bndmk 0x12345678(%rcx,%rax,1), %bnd0"); | ||
43 | asm volatile("bndmk 0x12345678(%rbp,%rax,1), %bnd0"); | ||
44 | asm volatile("bndmk 0x12345678(%rax,%rcx,1), %bnd0"); | ||
45 | asm volatile("bndmk 0x12345678(%rax,%rcx,8), %bnd0"); | ||
46 | |||
47 | /* bndcl r/m64, bnd */ | ||
48 | |||
49 | asm volatile("bndcl (%rax), %bnd0"); | ||
50 | asm volatile("bndcl (%r8), %bnd0"); | ||
51 | asm volatile("bndcl (0x12345678), %bnd0"); | ||
52 | asm volatile("bndcl (%rax), %bnd3"); | ||
53 | asm volatile("bndcl (%rcx,%rax,1), %bnd0"); | ||
54 | asm volatile("bndcl 0x12345678(,%rax,1), %bnd0"); | ||
55 | asm volatile("bndcl (%rax,%rcx,1), %bnd0"); | ||
56 | asm volatile("bndcl (%rax,%rcx,8), %bnd0"); | ||
57 | asm volatile("bndcl 0x12(%rax), %bnd0"); | ||
58 | asm volatile("bndcl 0x12(%rbp), %bnd0"); | ||
59 | asm volatile("bndcl 0x12(%rcx,%rax,1), %bnd0"); | ||
60 | asm volatile("bndcl 0x12(%rbp,%rax,1), %bnd0"); | ||
61 | asm volatile("bndcl 0x12(%rax,%rcx,1), %bnd0"); | ||
62 | asm volatile("bndcl 0x12(%rax,%rcx,8), %bnd0"); | ||
63 | asm volatile("bndcl 0x12345678(%rax), %bnd0"); | ||
64 | asm volatile("bndcl 0x12345678(%rbp), %bnd0"); | ||
65 | asm volatile("bndcl 0x12345678(%rcx,%rax,1), %bnd0"); | ||
66 | asm volatile("bndcl 0x12345678(%rbp,%rax,1), %bnd0"); | ||
67 | asm volatile("bndcl 0x12345678(%rax,%rcx,1), %bnd0"); | ||
68 | asm volatile("bndcl 0x12345678(%rax,%rcx,8), %bnd0"); | ||
69 | asm volatile("bndcl %rax, %bnd0"); | ||
70 | |||
71 | /* bndcu r/m64, bnd */ | ||
72 | |||
73 | asm volatile("bndcu (%rax), %bnd0"); | ||
74 | asm volatile("bndcu (%r8), %bnd0"); | ||
75 | asm volatile("bndcu (0x12345678), %bnd0"); | ||
76 | asm volatile("bndcu (%rax), %bnd3"); | ||
77 | asm volatile("bndcu (%rcx,%rax,1), %bnd0"); | ||
78 | asm volatile("bndcu 0x12345678(,%rax,1), %bnd0"); | ||
79 | asm volatile("bndcu (%rax,%rcx,1), %bnd0"); | ||
80 | asm volatile("bndcu (%rax,%rcx,8), %bnd0"); | ||
81 | asm volatile("bndcu 0x12(%rax), %bnd0"); | ||
82 | asm volatile("bndcu 0x12(%rbp), %bnd0"); | ||
83 | asm volatile("bndcu 0x12(%rcx,%rax,1), %bnd0"); | ||
84 | asm volatile("bndcu 0x12(%rbp,%rax,1), %bnd0"); | ||
85 | asm volatile("bndcu 0x12(%rax,%rcx,1), %bnd0"); | ||
86 | asm volatile("bndcu 0x12(%rax,%rcx,8), %bnd0"); | ||
87 | asm volatile("bndcu 0x12345678(%rax), %bnd0"); | ||
88 | asm volatile("bndcu 0x12345678(%rbp), %bnd0"); | ||
89 | asm volatile("bndcu 0x12345678(%rcx,%rax,1), %bnd0"); | ||
90 | asm volatile("bndcu 0x12345678(%rbp,%rax,1), %bnd0"); | ||
91 | asm volatile("bndcu 0x12345678(%rax,%rcx,1), %bnd0"); | ||
92 | asm volatile("bndcu 0x12345678(%rax,%rcx,8), %bnd0"); | ||
93 | asm volatile("bndcu %rax, %bnd0"); | ||
94 | |||
95 | /* bndcn r/m64, bnd */ | ||
96 | |||
97 | asm volatile("bndcn (%rax), %bnd0"); | ||
98 | asm volatile("bndcn (%r8), %bnd0"); | ||
99 | asm volatile("bndcn (0x12345678), %bnd0"); | ||
100 | asm volatile("bndcn (%rax), %bnd3"); | ||
101 | asm volatile("bndcn (%rcx,%rax,1), %bnd0"); | ||
102 | asm volatile("bndcn 0x12345678(,%rax,1), %bnd0"); | ||
103 | asm volatile("bndcn (%rax,%rcx,1), %bnd0"); | ||
104 | asm volatile("bndcn (%rax,%rcx,8), %bnd0"); | ||
105 | asm volatile("bndcn 0x12(%rax), %bnd0"); | ||
106 | asm volatile("bndcn 0x12(%rbp), %bnd0"); | ||
107 | asm volatile("bndcn 0x12(%rcx,%rax,1), %bnd0"); | ||
108 | asm volatile("bndcn 0x12(%rbp,%rax,1), %bnd0"); | ||
109 | asm volatile("bndcn 0x12(%rax,%rcx,1), %bnd0"); | ||
110 | asm volatile("bndcn 0x12(%rax,%rcx,8), %bnd0"); | ||
111 | asm volatile("bndcn 0x12345678(%rax), %bnd0"); | ||
112 | asm volatile("bndcn 0x12345678(%rbp), %bnd0"); | ||
113 | asm volatile("bndcn 0x12345678(%rcx,%rax,1), %bnd0"); | ||
114 | asm volatile("bndcn 0x12345678(%rbp,%rax,1), %bnd0"); | ||
115 | asm volatile("bndcn 0x12345678(%rax,%rcx,1), %bnd0"); | ||
116 | asm volatile("bndcn 0x12345678(%rax,%rcx,8), %bnd0"); | ||
117 | asm volatile("bndcn %rax, %bnd0"); | ||
118 | |||
119 | /* bndmov m128, bnd */ | ||
120 | |||
121 | asm volatile("bndmov (%rax), %bnd0"); | ||
122 | asm volatile("bndmov (%r8), %bnd0"); | ||
123 | asm volatile("bndmov (0x12345678), %bnd0"); | ||
124 | asm volatile("bndmov (%rax), %bnd3"); | ||
125 | asm volatile("bndmov (%rcx,%rax,1), %bnd0"); | ||
126 | asm volatile("bndmov 0x12345678(,%rax,1), %bnd0"); | ||
127 | asm volatile("bndmov (%rax,%rcx,1), %bnd0"); | ||
128 | asm volatile("bndmov (%rax,%rcx,8), %bnd0"); | ||
129 | asm volatile("bndmov 0x12(%rax), %bnd0"); | ||
130 | asm volatile("bndmov 0x12(%rbp), %bnd0"); | ||
131 | asm volatile("bndmov 0x12(%rcx,%rax,1), %bnd0"); | ||
132 | asm volatile("bndmov 0x12(%rbp,%rax,1), %bnd0"); | ||
133 | asm volatile("bndmov 0x12(%rax,%rcx,1), %bnd0"); | ||
134 | asm volatile("bndmov 0x12(%rax,%rcx,8), %bnd0"); | ||
135 | asm volatile("bndmov 0x12345678(%rax), %bnd0"); | ||
136 | asm volatile("bndmov 0x12345678(%rbp), %bnd0"); | ||
137 | asm volatile("bndmov 0x12345678(%rcx,%rax,1), %bnd0"); | ||
138 | asm volatile("bndmov 0x12345678(%rbp,%rax,1), %bnd0"); | ||
139 | asm volatile("bndmov 0x12345678(%rax,%rcx,1), %bnd0"); | ||
140 | asm volatile("bndmov 0x12345678(%rax,%rcx,8), %bnd0"); | ||
141 | |||
142 | /* bndmov bnd, m128 */ | ||
143 | |||
144 | asm volatile("bndmov %bnd0, (%rax)"); | ||
145 | asm volatile("bndmov %bnd0, (%r8)"); | ||
146 | asm volatile("bndmov %bnd0, (0x12345678)"); | ||
147 | asm volatile("bndmov %bnd3, (%rax)"); | ||
148 | asm volatile("bndmov %bnd0, (%rcx,%rax,1)"); | ||
149 | asm volatile("bndmov %bnd0, 0x12345678(,%rax,1)"); | ||
150 | asm volatile("bndmov %bnd0, (%rax,%rcx,1)"); | ||
151 | asm volatile("bndmov %bnd0, (%rax,%rcx,8)"); | ||
152 | asm volatile("bndmov %bnd0, 0x12(%rax)"); | ||
153 | asm volatile("bndmov %bnd0, 0x12(%rbp)"); | ||
154 | asm volatile("bndmov %bnd0, 0x12(%rcx,%rax,1)"); | ||
155 | asm volatile("bndmov %bnd0, 0x12(%rbp,%rax,1)"); | ||
156 | asm volatile("bndmov %bnd0, 0x12(%rax,%rcx,1)"); | ||
157 | asm volatile("bndmov %bnd0, 0x12(%rax,%rcx,8)"); | ||
158 | asm volatile("bndmov %bnd0, 0x12345678(%rax)"); | ||
159 | asm volatile("bndmov %bnd0, 0x12345678(%rbp)"); | ||
160 | asm volatile("bndmov %bnd0, 0x12345678(%rcx,%rax,1)"); | ||
161 | asm volatile("bndmov %bnd0, 0x12345678(%rbp,%rax,1)"); | ||
162 | asm volatile("bndmov %bnd0, 0x12345678(%rax,%rcx,1)"); | ||
163 | asm volatile("bndmov %bnd0, 0x12345678(%rax,%rcx,8)"); | ||
164 | |||
165 | /* bndmov bnd2, bnd1 */ | ||
166 | |||
167 | asm volatile("bndmov %bnd0, %bnd1"); | ||
168 | asm volatile("bndmov %bnd1, %bnd0"); | ||
169 | |||
170 | /* bndldx mib, bnd */ | ||
171 | |||
172 | asm volatile("bndldx (%rax), %bnd0"); | ||
173 | asm volatile("bndldx (%r8), %bnd0"); | ||
174 | asm volatile("bndldx (0x12345678), %bnd0"); | ||
175 | asm volatile("bndldx (%rax), %bnd3"); | ||
176 | asm volatile("bndldx (%rcx,%rax,1), %bnd0"); | ||
177 | asm volatile("bndldx 0x12345678(,%rax,1), %bnd0"); | ||
178 | asm volatile("bndldx (%rax,%rcx,1), %bnd0"); | ||
179 | asm volatile("bndldx 0x12(%rax), %bnd0"); | ||
180 | asm volatile("bndldx 0x12(%rbp), %bnd0"); | ||
181 | asm volatile("bndldx 0x12(%rcx,%rax,1), %bnd0"); | ||
182 | asm volatile("bndldx 0x12(%rbp,%rax,1), %bnd0"); | ||
183 | asm volatile("bndldx 0x12(%rax,%rcx,1), %bnd0"); | ||
184 | asm volatile("bndldx 0x12345678(%rax), %bnd0"); | ||
185 | asm volatile("bndldx 0x12345678(%rbp), %bnd0"); | ||
186 | asm volatile("bndldx 0x12345678(%rcx,%rax,1), %bnd0"); | ||
187 | asm volatile("bndldx 0x12345678(%rbp,%rax,1), %bnd0"); | ||
188 | asm volatile("bndldx 0x12345678(%rax,%rcx,1), %bnd0"); | ||
189 | |||
190 | /* bndstx bnd, mib */ | ||
191 | |||
192 | asm volatile("bndstx %bnd0, (%rax)"); | ||
193 | asm volatile("bndstx %bnd0, (%r8)"); | ||
194 | asm volatile("bndstx %bnd0, (0x12345678)"); | ||
195 | asm volatile("bndstx %bnd3, (%rax)"); | ||
196 | asm volatile("bndstx %bnd0, (%rcx,%rax,1)"); | ||
197 | asm volatile("bndstx %bnd0, 0x12345678(,%rax,1)"); | ||
198 | asm volatile("bndstx %bnd0, (%rax,%rcx,1)"); | ||
199 | asm volatile("bndstx %bnd0, 0x12(%rax)"); | ||
200 | asm volatile("bndstx %bnd0, 0x12(%rbp)"); | ||
201 | asm volatile("bndstx %bnd0, 0x12(%rcx,%rax,1)"); | ||
202 | asm volatile("bndstx %bnd0, 0x12(%rbp,%rax,1)"); | ||
203 | asm volatile("bndstx %bnd0, 0x12(%rax,%rcx,1)"); | ||
204 | asm volatile("bndstx %bnd0, 0x12345678(%rax)"); | ||
205 | asm volatile("bndstx %bnd0, 0x12345678(%rbp)"); | ||
206 | asm volatile("bndstx %bnd0, 0x12345678(%rcx,%rax,1)"); | ||
207 | asm volatile("bndstx %bnd0, 0x12345678(%rbp,%rax,1)"); | ||
208 | asm volatile("bndstx %bnd0, 0x12345678(%rax,%rcx,1)"); | ||
209 | |||
210 | /* bnd prefix on call, ret, jmp and all jcc */ | ||
211 | |||
212 | asm volatile("bnd call label1"); /* Expecting: call unconditional 0 */ | ||
213 | asm volatile("bnd call *(%eax)"); /* Expecting: call indirect 0 */ | ||
214 | asm volatile("bnd ret"); /* Expecting: ret indirect 0 */ | ||
215 | asm volatile("bnd jmp label1"); /* Expecting: jmp unconditional 0 */ | ||
216 | asm volatile("bnd jmp label1"); /* Expecting: jmp unconditional 0 */ | ||
217 | asm volatile("bnd jmp *(%ecx)"); /* Expecting: jmp indirect 0 */ | ||
218 | asm volatile("bnd jne label1"); /* Expecting: jcc conditional 0 */ | ||
219 | |||
220 | /* sha1rnds4 imm8, xmm2/m128, xmm1 */ | ||
221 | |||
222 | asm volatile("sha1rnds4 $0x0, %xmm1, %xmm0"); | ||
223 | asm volatile("sha1rnds4 $0x91, %xmm7, %xmm2"); | ||
224 | asm volatile("sha1rnds4 $0x91, %xmm8, %xmm0"); | ||
225 | asm volatile("sha1rnds4 $0x91, %xmm7, %xmm8"); | ||
226 | asm volatile("sha1rnds4 $0x91, %xmm15, %xmm8"); | ||
227 | asm volatile("sha1rnds4 $0x91, (%rax), %xmm0"); | ||
228 | asm volatile("sha1rnds4 $0x91, (%r8), %xmm0"); | ||
229 | asm volatile("sha1rnds4 $0x91, (0x12345678), %xmm0"); | ||
230 | asm volatile("sha1rnds4 $0x91, (%rax), %xmm3"); | ||
231 | asm volatile("sha1rnds4 $0x91, (%rcx,%rax,1), %xmm0"); | ||
232 | asm volatile("sha1rnds4 $0x91, 0x12345678(,%rax,1), %xmm0"); | ||
233 | asm volatile("sha1rnds4 $0x91, (%rax,%rcx,1), %xmm0"); | ||
234 | asm volatile("sha1rnds4 $0x91, (%rax,%rcx,8), %xmm0"); | ||
235 | asm volatile("sha1rnds4 $0x91, 0x12(%rax), %xmm0"); | ||
236 | asm volatile("sha1rnds4 $0x91, 0x12(%rbp), %xmm0"); | ||
237 | asm volatile("sha1rnds4 $0x91, 0x12(%rcx,%rax,1), %xmm0"); | ||
238 | asm volatile("sha1rnds4 $0x91, 0x12(%rbp,%rax,1), %xmm0"); | ||
239 | asm volatile("sha1rnds4 $0x91, 0x12(%rax,%rcx,1), %xmm0"); | ||
240 | asm volatile("sha1rnds4 $0x91, 0x12(%rax,%rcx,8), %xmm0"); | ||
241 | asm volatile("sha1rnds4 $0x91, 0x12345678(%rax), %xmm0"); | ||
242 | asm volatile("sha1rnds4 $0x91, 0x12345678(%rbp), %xmm0"); | ||
243 | asm volatile("sha1rnds4 $0x91, 0x12345678(%rcx,%rax,1), %xmm0"); | ||
244 | asm volatile("sha1rnds4 $0x91, 0x12345678(%rbp,%rax,1), %xmm0"); | ||
245 | asm volatile("sha1rnds4 $0x91, 0x12345678(%rax,%rcx,1), %xmm0"); | ||
246 | asm volatile("sha1rnds4 $0x91, 0x12345678(%rax,%rcx,8), %xmm0"); | ||
247 | asm volatile("sha1rnds4 $0x91, 0x12345678(%rax,%rcx,8), %xmm15"); | ||
248 | |||
249 | /* sha1nexte xmm2/m128, xmm1 */ | ||
250 | |||
251 | asm volatile("sha1nexte %xmm1, %xmm0"); | ||
252 | asm volatile("sha1nexte %xmm7, %xmm2"); | ||
253 | asm volatile("sha1nexte %xmm8, %xmm0"); | ||
254 | asm volatile("sha1nexte %xmm7, %xmm8"); | ||
255 | asm volatile("sha1nexte %xmm15, %xmm8"); | ||
256 | asm volatile("sha1nexte (%rax), %xmm0"); | ||
257 | asm volatile("sha1nexte (%r8), %xmm0"); | ||
258 | asm volatile("sha1nexte (0x12345678), %xmm0"); | ||
259 | asm volatile("sha1nexte (%rax), %xmm3"); | ||
260 | asm volatile("sha1nexte (%rcx,%rax,1), %xmm0"); | ||
261 | asm volatile("sha1nexte 0x12345678(,%rax,1), %xmm0"); | ||
262 | asm volatile("sha1nexte (%rax,%rcx,1), %xmm0"); | ||
263 | asm volatile("sha1nexte (%rax,%rcx,8), %xmm0"); | ||
264 | asm volatile("sha1nexte 0x12(%rax), %xmm0"); | ||
265 | asm volatile("sha1nexte 0x12(%rbp), %xmm0"); | ||
266 | asm volatile("sha1nexte 0x12(%rcx,%rax,1), %xmm0"); | ||
267 | asm volatile("sha1nexte 0x12(%rbp,%rax,1), %xmm0"); | ||
268 | asm volatile("sha1nexte 0x12(%rax,%rcx,1), %xmm0"); | ||
269 | asm volatile("sha1nexte 0x12(%rax,%rcx,8), %xmm0"); | ||
270 | asm volatile("sha1nexte 0x12345678(%rax), %xmm0"); | ||
271 | asm volatile("sha1nexte 0x12345678(%rbp), %xmm0"); | ||
272 | asm volatile("sha1nexte 0x12345678(%rcx,%rax,1), %xmm0"); | ||
273 | asm volatile("sha1nexte 0x12345678(%rbp,%rax,1), %xmm0"); | ||
274 | asm volatile("sha1nexte 0x12345678(%rax,%rcx,1), %xmm0"); | ||
275 | asm volatile("sha1nexte 0x12345678(%rax,%rcx,8), %xmm0"); | ||
276 | asm volatile("sha1nexte 0x12345678(%rax,%rcx,8), %xmm15"); | ||
277 | |||
278 | /* sha1msg1 xmm2/m128, xmm1 */ | ||
279 | |||
280 | asm volatile("sha1msg1 %xmm1, %xmm0"); | ||
281 | asm volatile("sha1msg1 %xmm7, %xmm2"); | ||
282 | asm volatile("sha1msg1 %xmm8, %xmm0"); | ||
283 | asm volatile("sha1msg1 %xmm7, %xmm8"); | ||
284 | asm volatile("sha1msg1 %xmm15, %xmm8"); | ||
285 | asm volatile("sha1msg1 (%rax), %xmm0"); | ||
286 | asm volatile("sha1msg1 (%r8), %xmm0"); | ||
287 | asm volatile("sha1msg1 (0x12345678), %xmm0"); | ||
288 | asm volatile("sha1msg1 (%rax), %xmm3"); | ||
289 | asm volatile("sha1msg1 (%rcx,%rax,1), %xmm0"); | ||
290 | asm volatile("sha1msg1 0x12345678(,%rax,1), %xmm0"); | ||
291 | asm volatile("sha1msg1 (%rax,%rcx,1), %xmm0"); | ||
292 | asm volatile("sha1msg1 (%rax,%rcx,8), %xmm0"); | ||
293 | asm volatile("sha1msg1 0x12(%rax), %xmm0"); | ||
294 | asm volatile("sha1msg1 0x12(%rbp), %xmm0"); | ||
295 | asm volatile("sha1msg1 0x12(%rcx,%rax,1), %xmm0"); | ||
296 | asm volatile("sha1msg1 0x12(%rbp,%rax,1), %xmm0"); | ||
297 | asm volatile("sha1msg1 0x12(%rax,%rcx,1), %xmm0"); | ||
298 | asm volatile("sha1msg1 0x12(%rax,%rcx,8), %xmm0"); | ||
299 | asm volatile("sha1msg1 0x12345678(%rax), %xmm0"); | ||
300 | asm volatile("sha1msg1 0x12345678(%rbp), %xmm0"); | ||
301 | asm volatile("sha1msg1 0x12345678(%rcx,%rax,1), %xmm0"); | ||
302 | asm volatile("sha1msg1 0x12345678(%rbp,%rax,1), %xmm0"); | ||
303 | asm volatile("sha1msg1 0x12345678(%rax,%rcx,1), %xmm0"); | ||
304 | asm volatile("sha1msg1 0x12345678(%rax,%rcx,8), %xmm0"); | ||
305 | asm volatile("sha1msg1 0x12345678(%rax,%rcx,8), %xmm15"); | ||
306 | |||
307 | /* sha1msg2 xmm2/m128, xmm1 */ | ||
308 | |||
309 | asm volatile("sha1msg2 %xmm1, %xmm0"); | ||
310 | asm volatile("sha1msg2 %xmm7, %xmm2"); | ||
311 | asm volatile("sha1msg2 %xmm8, %xmm0"); | ||
312 | asm volatile("sha1msg2 %xmm7, %xmm8"); | ||
313 | asm volatile("sha1msg2 %xmm15, %xmm8"); | ||
314 | asm volatile("sha1msg2 (%rax), %xmm0"); | ||
315 | asm volatile("sha1msg2 (%r8), %xmm0"); | ||
316 | asm volatile("sha1msg2 (0x12345678), %xmm0"); | ||
317 | asm volatile("sha1msg2 (%rax), %xmm3"); | ||
318 | asm volatile("sha1msg2 (%rcx,%rax,1), %xmm0"); | ||
319 | asm volatile("sha1msg2 0x12345678(,%rax,1), %xmm0"); | ||
320 | asm volatile("sha1msg2 (%rax,%rcx,1), %xmm0"); | ||
321 | asm volatile("sha1msg2 (%rax,%rcx,8), %xmm0"); | ||
322 | asm volatile("sha1msg2 0x12(%rax), %xmm0"); | ||
323 | asm volatile("sha1msg2 0x12(%rbp), %xmm0"); | ||
324 | asm volatile("sha1msg2 0x12(%rcx,%rax,1), %xmm0"); | ||
325 | asm volatile("sha1msg2 0x12(%rbp,%rax,1), %xmm0"); | ||
326 | asm volatile("sha1msg2 0x12(%rax,%rcx,1), %xmm0"); | ||
327 | asm volatile("sha1msg2 0x12(%rax,%rcx,8), %xmm0"); | ||
328 | asm volatile("sha1msg2 0x12345678(%rax), %xmm0"); | ||
329 | asm volatile("sha1msg2 0x12345678(%rbp), %xmm0"); | ||
330 | asm volatile("sha1msg2 0x12345678(%rcx,%rax,1), %xmm0"); | ||
331 | asm volatile("sha1msg2 0x12345678(%rbp,%rax,1), %xmm0"); | ||
332 | asm volatile("sha1msg2 0x12345678(%rax,%rcx,1), %xmm0"); | ||
333 | asm volatile("sha1msg2 0x12345678(%rax,%rcx,8), %xmm0"); | ||
334 | asm volatile("sha1msg2 0x12345678(%rax,%rcx,8), %xmm15"); | ||
335 | |||
336 | /* sha256rnds2 <XMM0>, xmm2/m128, xmm1 */ | ||
337 | /* Note sha256rnds2 has an implicit operand 'xmm0' */ | ||
338 | |||
339 | asm volatile("sha256rnds2 %xmm4, %xmm1"); | ||
340 | asm volatile("sha256rnds2 %xmm7, %xmm2"); | ||
341 | asm volatile("sha256rnds2 %xmm8, %xmm1"); | ||
342 | asm volatile("sha256rnds2 %xmm7, %xmm8"); | ||
343 | asm volatile("sha256rnds2 %xmm15, %xmm8"); | ||
344 | asm volatile("sha256rnds2 (%rax), %xmm1"); | ||
345 | asm volatile("sha256rnds2 (%r8), %xmm1"); | ||
346 | asm volatile("sha256rnds2 (0x12345678), %xmm1"); | ||
347 | asm volatile("sha256rnds2 (%rax), %xmm3"); | ||
348 | asm volatile("sha256rnds2 (%rcx,%rax,1), %xmm1"); | ||
349 | asm volatile("sha256rnds2 0x12345678(,%rax,1), %xmm1"); | ||
350 | asm volatile("sha256rnds2 (%rax,%rcx,1), %xmm1"); | ||
351 | asm volatile("sha256rnds2 (%rax,%rcx,8), %xmm1"); | ||
352 | asm volatile("sha256rnds2 0x12(%rax), %xmm1"); | ||
353 | asm volatile("sha256rnds2 0x12(%rbp), %xmm1"); | ||
354 | asm volatile("sha256rnds2 0x12(%rcx,%rax,1), %xmm1"); | ||
355 | asm volatile("sha256rnds2 0x12(%rbp,%rax,1), %xmm1"); | ||
356 | asm volatile("sha256rnds2 0x12(%rax,%rcx,1), %xmm1"); | ||
357 | asm volatile("sha256rnds2 0x12(%rax,%rcx,8), %xmm1"); | ||
358 | asm volatile("sha256rnds2 0x12345678(%rax), %xmm1"); | ||
359 | asm volatile("sha256rnds2 0x12345678(%rbp), %xmm1"); | ||
360 | asm volatile("sha256rnds2 0x12345678(%rcx,%rax,1), %xmm1"); | ||
361 | asm volatile("sha256rnds2 0x12345678(%rbp,%rax,1), %xmm1"); | ||
362 | asm volatile("sha256rnds2 0x12345678(%rax,%rcx,1), %xmm1"); | ||
363 | asm volatile("sha256rnds2 0x12345678(%rax,%rcx,8), %xmm1"); | ||
364 | asm volatile("sha256rnds2 0x12345678(%rax,%rcx,8), %xmm15"); | ||
365 | |||
366 | /* sha256msg1 xmm2/m128, xmm1 */ | ||
367 | |||
368 | asm volatile("sha256msg1 %xmm1, %xmm0"); | ||
369 | asm volatile("sha256msg1 %xmm7, %xmm2"); | ||
370 | asm volatile("sha256msg1 %xmm8, %xmm0"); | ||
371 | asm volatile("sha256msg1 %xmm7, %xmm8"); | ||
372 | asm volatile("sha256msg1 %xmm15, %xmm8"); | ||
373 | asm volatile("sha256msg1 (%rax), %xmm0"); | ||
374 | asm volatile("sha256msg1 (%r8), %xmm0"); | ||
375 | asm volatile("sha256msg1 (0x12345678), %xmm0"); | ||
376 | asm volatile("sha256msg1 (%rax), %xmm3"); | ||
377 | asm volatile("sha256msg1 (%rcx,%rax,1), %xmm0"); | ||
378 | asm volatile("sha256msg1 0x12345678(,%rax,1), %xmm0"); | ||
379 | asm volatile("sha256msg1 (%rax,%rcx,1), %xmm0"); | ||
380 | asm volatile("sha256msg1 (%rax,%rcx,8), %xmm0"); | ||
381 | asm volatile("sha256msg1 0x12(%rax), %xmm0"); | ||
382 | asm volatile("sha256msg1 0x12(%rbp), %xmm0"); | ||
383 | asm volatile("sha256msg1 0x12(%rcx,%rax,1), %xmm0"); | ||
384 | asm volatile("sha256msg1 0x12(%rbp,%rax,1), %xmm0"); | ||
385 | asm volatile("sha256msg1 0x12(%rax,%rcx,1), %xmm0"); | ||
386 | asm volatile("sha256msg1 0x12(%rax,%rcx,8), %xmm0"); | ||
387 | asm volatile("sha256msg1 0x12345678(%rax), %xmm0"); | ||
388 | asm volatile("sha256msg1 0x12345678(%rbp), %xmm0"); | ||
389 | asm volatile("sha256msg1 0x12345678(%rcx,%rax,1), %xmm0"); | ||
390 | asm volatile("sha256msg1 0x12345678(%rbp,%rax,1), %xmm0"); | ||
391 | asm volatile("sha256msg1 0x12345678(%rax,%rcx,1), %xmm0"); | ||
392 | asm volatile("sha256msg1 0x12345678(%rax,%rcx,8), %xmm0"); | ||
393 | asm volatile("sha256msg1 0x12345678(%rax,%rcx,8), %xmm15"); | ||
394 | |||
395 | /* sha256msg2 xmm2/m128, xmm1 */ | ||
396 | |||
397 | asm volatile("sha256msg2 %xmm1, %xmm0"); | ||
398 | asm volatile("sha256msg2 %xmm7, %xmm2"); | ||
399 | asm volatile("sha256msg2 %xmm8, %xmm0"); | ||
400 | asm volatile("sha256msg2 %xmm7, %xmm8"); | ||
401 | asm volatile("sha256msg2 %xmm15, %xmm8"); | ||
402 | asm volatile("sha256msg2 (%rax), %xmm0"); | ||
403 | asm volatile("sha256msg2 (%r8), %xmm0"); | ||
404 | asm volatile("sha256msg2 (0x12345678), %xmm0"); | ||
405 | asm volatile("sha256msg2 (%rax), %xmm3"); | ||
406 | asm volatile("sha256msg2 (%rcx,%rax,1), %xmm0"); | ||
407 | asm volatile("sha256msg2 0x12345678(,%rax,1), %xmm0"); | ||
408 | asm volatile("sha256msg2 (%rax,%rcx,1), %xmm0"); | ||
409 | asm volatile("sha256msg2 (%rax,%rcx,8), %xmm0"); | ||
410 | asm volatile("sha256msg2 0x12(%rax), %xmm0"); | ||
411 | asm volatile("sha256msg2 0x12(%rbp), %xmm0"); | ||
412 | asm volatile("sha256msg2 0x12(%rcx,%rax,1), %xmm0"); | ||
413 | asm volatile("sha256msg2 0x12(%rbp,%rax,1), %xmm0"); | ||
414 | asm volatile("sha256msg2 0x12(%rax,%rcx,1), %xmm0"); | ||
415 | asm volatile("sha256msg2 0x12(%rax,%rcx,8), %xmm0"); | ||
416 | asm volatile("sha256msg2 0x12345678(%rax), %xmm0"); | ||
417 | asm volatile("sha256msg2 0x12345678(%rbp), %xmm0"); | ||
418 | asm volatile("sha256msg2 0x12345678(%rcx,%rax,1), %xmm0"); | ||
419 | asm volatile("sha256msg2 0x12345678(%rbp,%rax,1), %xmm0"); | ||
420 | asm volatile("sha256msg2 0x12345678(%rax,%rcx,1), %xmm0"); | ||
421 | asm volatile("sha256msg2 0x12345678(%rax,%rcx,8), %xmm0"); | ||
422 | asm volatile("sha256msg2 0x12345678(%rax,%rcx,8), %xmm15"); | ||
423 | |||
424 | /* clflushopt m8 */ | ||
425 | |||
426 | asm volatile("clflushopt (%rax)"); | ||
427 | asm volatile("clflushopt (%r8)"); | ||
428 | asm volatile("clflushopt (0x12345678)"); | ||
429 | asm volatile("clflushopt 0x12345678(%rax,%rcx,8)"); | ||
430 | asm volatile("clflushopt 0x12345678(%r8,%rcx,8)"); | ||
431 | /* Also check instructions in the same group encoding as clflushopt */ | ||
432 | asm volatile("clflush (%rax)"); | ||
433 | asm volatile("clflush (%r8)"); | ||
434 | asm volatile("sfence"); | ||
435 | |||
436 | /* clwb m8 */ | ||
437 | |||
438 | asm volatile("clwb (%rax)"); | ||
439 | asm volatile("clwb (%r8)"); | ||
440 | asm volatile("clwb (0x12345678)"); | ||
441 | asm volatile("clwb 0x12345678(%rax,%rcx,8)"); | ||
442 | asm volatile("clwb 0x12345678(%r8,%rcx,8)"); | ||
443 | /* Also check instructions in the same group encoding as clwb */ | ||
444 | asm volatile("xsaveopt (%rax)"); | ||
445 | asm volatile("xsaveopt (%r8)"); | ||
446 | asm volatile("mfence"); | ||
447 | |||
448 | /* xsavec mem */ | ||
449 | |||
450 | asm volatile("xsavec (%rax)"); | ||
451 | asm volatile("xsavec (%r8)"); | ||
452 | asm volatile("xsavec (0x12345678)"); | ||
453 | asm volatile("xsavec 0x12345678(%rax,%rcx,8)"); | ||
454 | asm volatile("xsavec 0x12345678(%r8,%rcx,8)"); | ||
455 | |||
456 | /* xsaves mem */ | ||
457 | |||
458 | asm volatile("xsaves (%rax)"); | ||
459 | asm volatile("xsaves (%r8)"); | ||
460 | asm volatile("xsaves (0x12345678)"); | ||
461 | asm volatile("xsaves 0x12345678(%rax,%rcx,8)"); | ||
462 | asm volatile("xsaves 0x12345678(%r8,%rcx,8)"); | ||
463 | |||
464 | /* xrstors mem */ | ||
465 | |||
466 | asm volatile("xrstors (%rax)"); | ||
467 | asm volatile("xrstors (%r8)"); | ||
468 | asm volatile("xrstors (0x12345678)"); | ||
469 | asm volatile("xrstors 0x12345678(%rax,%rcx,8)"); | ||
470 | asm volatile("xrstors 0x12345678(%r8,%rcx,8)"); | ||
471 | |||
472 | #else /* #ifdef __x86_64__ */ | ||
473 | |||
474 | /* bndmk m32, bnd */ | ||
475 | |||
476 | asm volatile("bndmk (%eax), %bnd0"); | ||
477 | asm volatile("bndmk (0x12345678), %bnd0"); | ||
478 | asm volatile("bndmk (%eax), %bnd3"); | ||
479 | asm volatile("bndmk (%ecx,%eax,1), %bnd0"); | ||
480 | asm volatile("bndmk 0x12345678(,%eax,1), %bnd0"); | ||
481 | asm volatile("bndmk (%eax,%ecx,1), %bnd0"); | ||
482 | asm volatile("bndmk (%eax,%ecx,8), %bnd0"); | ||
483 | asm volatile("bndmk 0x12(%eax), %bnd0"); | ||
484 | asm volatile("bndmk 0x12(%ebp), %bnd0"); | ||
485 | asm volatile("bndmk 0x12(%ecx,%eax,1), %bnd0"); | ||
486 | asm volatile("bndmk 0x12(%ebp,%eax,1), %bnd0"); | ||
487 | asm volatile("bndmk 0x12(%eax,%ecx,1), %bnd0"); | ||
488 | asm volatile("bndmk 0x12(%eax,%ecx,8), %bnd0"); | ||
489 | asm volatile("bndmk 0x12345678(%eax), %bnd0"); | ||
490 | asm volatile("bndmk 0x12345678(%ebp), %bnd0"); | ||
491 | asm volatile("bndmk 0x12345678(%ecx,%eax,1), %bnd0"); | ||
492 | asm volatile("bndmk 0x12345678(%ebp,%eax,1), %bnd0"); | ||
493 | asm volatile("bndmk 0x12345678(%eax,%ecx,1), %bnd0"); | ||
494 | asm volatile("bndmk 0x12345678(%eax,%ecx,8), %bnd0"); | ||
495 | |||
496 | /* bndcl r/m32, bnd */ | ||
497 | |||
498 | asm volatile("bndcl (%eax), %bnd0"); | ||
499 | asm volatile("bndcl (0x12345678), %bnd0"); | ||
500 | asm volatile("bndcl (%eax), %bnd3"); | ||
501 | asm volatile("bndcl (%ecx,%eax,1), %bnd0"); | ||
502 | asm volatile("bndcl 0x12345678(,%eax,1), %bnd0"); | ||
503 | asm volatile("bndcl (%eax,%ecx,1), %bnd0"); | ||
504 | asm volatile("bndcl (%eax,%ecx,8), %bnd0"); | ||
505 | asm volatile("bndcl 0x12(%eax), %bnd0"); | ||
506 | asm volatile("bndcl 0x12(%ebp), %bnd0"); | ||
507 | asm volatile("bndcl 0x12(%ecx,%eax,1), %bnd0"); | ||
508 | asm volatile("bndcl 0x12(%ebp,%eax,1), %bnd0"); | ||
509 | asm volatile("bndcl 0x12(%eax,%ecx,1), %bnd0"); | ||
510 | asm volatile("bndcl 0x12(%eax,%ecx,8), %bnd0"); | ||
511 | asm volatile("bndcl 0x12345678(%eax), %bnd0"); | ||
512 | asm volatile("bndcl 0x12345678(%ebp), %bnd0"); | ||
513 | asm volatile("bndcl 0x12345678(%ecx,%eax,1), %bnd0"); | ||
514 | asm volatile("bndcl 0x12345678(%ebp,%eax,1), %bnd0"); | ||
515 | asm volatile("bndcl 0x12345678(%eax,%ecx,1), %bnd0"); | ||
516 | asm volatile("bndcl 0x12345678(%eax,%ecx,8), %bnd0"); | ||
517 | asm volatile("bndcl %eax, %bnd0"); | ||
518 | |||
519 | /* bndcu r/m32, bnd */ | ||
520 | |||
521 | asm volatile("bndcu (%eax), %bnd0"); | ||
522 | asm volatile("bndcu (0x12345678), %bnd0"); | ||
523 | asm volatile("bndcu (%eax), %bnd3"); | ||
524 | asm volatile("bndcu (%ecx,%eax,1), %bnd0"); | ||
525 | asm volatile("bndcu 0x12345678(,%eax,1), %bnd0"); | ||
526 | asm volatile("bndcu (%eax,%ecx,1), %bnd0"); | ||
527 | asm volatile("bndcu (%eax,%ecx,8), %bnd0"); | ||
528 | asm volatile("bndcu 0x12(%eax), %bnd0"); | ||
529 | asm volatile("bndcu 0x12(%ebp), %bnd0"); | ||
530 | asm volatile("bndcu 0x12(%ecx,%eax,1), %bnd0"); | ||
531 | asm volatile("bndcu 0x12(%ebp,%eax,1), %bnd0"); | ||
532 | asm volatile("bndcu 0x12(%eax,%ecx,1), %bnd0"); | ||
533 | asm volatile("bndcu 0x12(%eax,%ecx,8), %bnd0"); | ||
534 | asm volatile("bndcu 0x12345678(%eax), %bnd0"); | ||
535 | asm volatile("bndcu 0x12345678(%ebp), %bnd0"); | ||
536 | asm volatile("bndcu 0x12345678(%ecx,%eax,1), %bnd0"); | ||
537 | asm volatile("bndcu 0x12345678(%ebp,%eax,1), %bnd0"); | ||
538 | asm volatile("bndcu 0x12345678(%eax,%ecx,1), %bnd0"); | ||
539 | asm volatile("bndcu 0x12345678(%eax,%ecx,8), %bnd0"); | ||
540 | asm volatile("bndcu %eax, %bnd0"); | ||
541 | |||
542 | /* bndcn r/m32, bnd */ | ||
543 | |||
544 | asm volatile("bndcn (%eax), %bnd0"); | ||
545 | asm volatile("bndcn (0x12345678), %bnd0"); | ||
546 | asm volatile("bndcn (%eax), %bnd3"); | ||
547 | asm volatile("bndcn (%ecx,%eax,1), %bnd0"); | ||
548 | asm volatile("bndcn 0x12345678(,%eax,1), %bnd0"); | ||
549 | asm volatile("bndcn (%eax,%ecx,1), %bnd0"); | ||
550 | asm volatile("bndcn (%eax,%ecx,8), %bnd0"); | ||
551 | asm volatile("bndcn 0x12(%eax), %bnd0"); | ||
552 | asm volatile("bndcn 0x12(%ebp), %bnd0"); | ||
553 | asm volatile("bndcn 0x12(%ecx,%eax,1), %bnd0"); | ||
554 | asm volatile("bndcn 0x12(%ebp,%eax,1), %bnd0"); | ||
555 | asm volatile("bndcn 0x12(%eax,%ecx,1), %bnd0"); | ||
556 | asm volatile("bndcn 0x12(%eax,%ecx,8), %bnd0"); | ||
557 | asm volatile("bndcn 0x12345678(%eax), %bnd0"); | ||
558 | asm volatile("bndcn 0x12345678(%ebp), %bnd0"); | ||
559 | asm volatile("bndcn 0x12345678(%ecx,%eax,1), %bnd0"); | ||
560 | asm volatile("bndcn 0x12345678(%ebp,%eax,1), %bnd0"); | ||
561 | asm volatile("bndcn 0x12345678(%eax,%ecx,1), %bnd0"); | ||
562 | asm volatile("bndcn 0x12345678(%eax,%ecx,8), %bnd0"); | ||
563 | asm volatile("bndcn %eax, %bnd0"); | ||
564 | |||
565 | /* bndmov m64, bnd */ | ||
566 | |||
567 | asm volatile("bndmov (%eax), %bnd0"); | ||
568 | asm volatile("bndmov (0x12345678), %bnd0"); | ||
569 | asm volatile("bndmov (%eax), %bnd3"); | ||
570 | asm volatile("bndmov (%ecx,%eax,1), %bnd0"); | ||
571 | asm volatile("bndmov 0x12345678(,%eax,1), %bnd0"); | ||
572 | asm volatile("bndmov (%eax,%ecx,1), %bnd0"); | ||
573 | asm volatile("bndmov (%eax,%ecx,8), %bnd0"); | ||
574 | asm volatile("bndmov 0x12(%eax), %bnd0"); | ||
575 | asm volatile("bndmov 0x12(%ebp), %bnd0"); | ||
576 | asm volatile("bndmov 0x12(%ecx,%eax,1), %bnd0"); | ||
577 | asm volatile("bndmov 0x12(%ebp,%eax,1), %bnd0"); | ||
578 | asm volatile("bndmov 0x12(%eax,%ecx,1), %bnd0"); | ||
579 | asm volatile("bndmov 0x12(%eax,%ecx,8), %bnd0"); | ||
580 | asm volatile("bndmov 0x12345678(%eax), %bnd0"); | ||
581 | asm volatile("bndmov 0x12345678(%ebp), %bnd0"); | ||
582 | asm volatile("bndmov 0x12345678(%ecx,%eax,1), %bnd0"); | ||
583 | asm volatile("bndmov 0x12345678(%ebp,%eax,1), %bnd0"); | ||
584 | asm volatile("bndmov 0x12345678(%eax,%ecx,1), %bnd0"); | ||
585 | asm volatile("bndmov 0x12345678(%eax,%ecx,8), %bnd0"); | ||
586 | |||
587 | /* bndmov bnd, m64 */ | ||
588 | |||
589 | asm volatile("bndmov %bnd0, (%eax)"); | ||
590 | asm volatile("bndmov %bnd0, (0x12345678)"); | ||
591 | asm volatile("bndmov %bnd3, (%eax)"); | ||
592 | asm volatile("bndmov %bnd0, (%ecx,%eax,1)"); | ||
593 | asm volatile("bndmov %bnd0, 0x12345678(,%eax,1)"); | ||
594 | asm volatile("bndmov %bnd0, (%eax,%ecx,1)"); | ||
595 | asm volatile("bndmov %bnd0, (%eax,%ecx,8)"); | ||
596 | asm volatile("bndmov %bnd0, 0x12(%eax)"); | ||
597 | asm volatile("bndmov %bnd0, 0x12(%ebp)"); | ||
598 | asm volatile("bndmov %bnd0, 0x12(%ecx,%eax,1)"); | ||
599 | asm volatile("bndmov %bnd0, 0x12(%ebp,%eax,1)"); | ||
600 | asm volatile("bndmov %bnd0, 0x12(%eax,%ecx,1)"); | ||
601 | asm volatile("bndmov %bnd0, 0x12(%eax,%ecx,8)"); | ||
602 | asm volatile("bndmov %bnd0, 0x12345678(%eax)"); | ||
603 | asm volatile("bndmov %bnd0, 0x12345678(%ebp)"); | ||
604 | asm volatile("bndmov %bnd0, 0x12345678(%ecx,%eax,1)"); | ||
605 | asm volatile("bndmov %bnd0, 0x12345678(%ebp,%eax,1)"); | ||
606 | asm volatile("bndmov %bnd0, 0x12345678(%eax,%ecx,1)"); | ||
607 | asm volatile("bndmov %bnd0, 0x12345678(%eax,%ecx,8)"); | ||
608 | |||
609 | /* bndmov bnd2, bnd1 */ | ||
610 | |||
611 | asm volatile("bndmov %bnd0, %bnd1"); | ||
612 | asm volatile("bndmov %bnd1, %bnd0"); | ||
613 | |||
614 | /* bndldx mib, bnd */ | ||
615 | |||
616 | asm volatile("bndldx (%eax), %bnd0"); | ||
617 | asm volatile("bndldx (0x12345678), %bnd0"); | ||
618 | asm volatile("bndldx (%eax), %bnd3"); | ||
619 | asm volatile("bndldx (%ecx,%eax,1), %bnd0"); | ||
620 | asm volatile("bndldx 0x12345678(,%eax,1), %bnd0"); | ||
621 | asm volatile("bndldx (%eax,%ecx,1), %bnd0"); | ||
622 | asm volatile("bndldx 0x12(%eax), %bnd0"); | ||
623 | asm volatile("bndldx 0x12(%ebp), %bnd0"); | ||
624 | asm volatile("bndldx 0x12(%ecx,%eax,1), %bnd0"); | ||
625 | asm volatile("bndldx 0x12(%ebp,%eax,1), %bnd0"); | ||
626 | asm volatile("bndldx 0x12(%eax,%ecx,1), %bnd0"); | ||
627 | asm volatile("bndldx 0x12345678(%eax), %bnd0"); | ||
628 | asm volatile("bndldx 0x12345678(%ebp), %bnd0"); | ||
629 | asm volatile("bndldx 0x12345678(%ecx,%eax,1), %bnd0"); | ||
630 | asm volatile("bndldx 0x12345678(%ebp,%eax,1), %bnd0"); | ||
631 | asm volatile("bndldx 0x12345678(%eax,%ecx,1), %bnd0"); | ||
632 | |||
633 | /* bndstx bnd, mib */ | ||
634 | |||
635 | asm volatile("bndstx %bnd0, (%eax)"); | ||
636 | asm volatile("bndstx %bnd0, (0x12345678)"); | ||
637 | asm volatile("bndstx %bnd3, (%eax)"); | ||
638 | asm volatile("bndstx %bnd0, (%ecx,%eax,1)"); | ||
639 | asm volatile("bndstx %bnd0, 0x12345678(,%eax,1)"); | ||
640 | asm volatile("bndstx %bnd0, (%eax,%ecx,1)"); | ||
641 | asm volatile("bndstx %bnd0, 0x12(%eax)"); | ||
642 | asm volatile("bndstx %bnd0, 0x12(%ebp)"); | ||
643 | asm volatile("bndstx %bnd0, 0x12(%ecx,%eax,1)"); | ||
644 | asm volatile("bndstx %bnd0, 0x12(%ebp,%eax,1)"); | ||
645 | asm volatile("bndstx %bnd0, 0x12(%eax,%ecx,1)"); | ||
646 | asm volatile("bndstx %bnd0, 0x12345678(%eax)"); | ||
647 | asm volatile("bndstx %bnd0, 0x12345678(%ebp)"); | ||
648 | asm volatile("bndstx %bnd0, 0x12345678(%ecx,%eax,1)"); | ||
649 | asm volatile("bndstx %bnd0, 0x12345678(%ebp,%eax,1)"); | ||
650 | asm volatile("bndstx %bnd0, 0x12345678(%eax,%ecx,1)"); | ||
651 | |||
652 | /* bnd prefix on call, ret, jmp and all jcc */ | ||
653 | |||
654 | asm volatile("bnd call label1"); /* Expecting: call unconditional 0xfffffffc */ | ||
655 | asm volatile("bnd call *(%eax)"); /* Expecting: call indirect 0 */ | ||
656 | asm volatile("bnd ret"); /* Expecting: ret indirect 0 */ | ||
657 | asm volatile("bnd jmp label1"); /* Expecting: jmp unconditional 0xfffffffc */ | ||
658 | asm volatile("bnd jmp label1"); /* Expecting: jmp unconditional 0xfffffffc */ | ||
659 | asm volatile("bnd jmp *(%ecx)"); /* Expecting: jmp indirect 0 */ | ||
660 | asm volatile("bnd jne label1"); /* Expecting: jcc conditional 0xfffffffc */ | ||
661 | |||
662 | /* sha1rnds4 imm8, xmm2/m128, xmm1 */ | ||
663 | |||
664 | asm volatile("sha1rnds4 $0x0, %xmm1, %xmm0"); | ||
665 | asm volatile("sha1rnds4 $0x91, %xmm7, %xmm2"); | ||
666 | asm volatile("sha1rnds4 $0x91, (%eax), %xmm0"); | ||
667 | asm volatile("sha1rnds4 $0x91, (0x12345678), %xmm0"); | ||
668 | asm volatile("sha1rnds4 $0x91, (%eax), %xmm3"); | ||
669 | asm volatile("sha1rnds4 $0x91, (%ecx,%eax,1), %xmm0"); | ||
670 | asm volatile("sha1rnds4 $0x91, 0x12345678(,%eax,1), %xmm0"); | ||
671 | asm volatile("sha1rnds4 $0x91, (%eax,%ecx,1), %xmm0"); | ||
672 | asm volatile("sha1rnds4 $0x91, (%eax,%ecx,8), %xmm0"); | ||
673 | asm volatile("sha1rnds4 $0x91, 0x12(%eax), %xmm0"); | ||
674 | asm volatile("sha1rnds4 $0x91, 0x12(%ebp), %xmm0"); | ||
675 | asm volatile("sha1rnds4 $0x91, 0x12(%ecx,%eax,1), %xmm0"); | ||
676 | asm volatile("sha1rnds4 $0x91, 0x12(%ebp,%eax,1), %xmm0"); | ||
677 | asm volatile("sha1rnds4 $0x91, 0x12(%eax,%ecx,1), %xmm0"); | ||
678 | asm volatile("sha1rnds4 $0x91, 0x12(%eax,%ecx,8), %xmm0"); | ||
679 | asm volatile("sha1rnds4 $0x91, 0x12345678(%eax), %xmm0"); | ||
680 | asm volatile("sha1rnds4 $0x91, 0x12345678(%ebp), %xmm0"); | ||
681 | asm volatile("sha1rnds4 $0x91, 0x12345678(%ecx,%eax,1), %xmm0"); | ||
682 | asm volatile("sha1rnds4 $0x91, 0x12345678(%ebp,%eax,1), %xmm0"); | ||
683 | asm volatile("sha1rnds4 $0x91, 0x12345678(%eax,%ecx,1), %xmm0"); | ||
684 | asm volatile("sha1rnds4 $0x91, 0x12345678(%eax,%ecx,8), %xmm0"); | ||
685 | |||
686 | /* sha1nexte xmm2/m128, xmm1 */ | ||
687 | |||
688 | asm volatile("sha1nexte %xmm1, %xmm0"); | ||
689 | asm volatile("sha1nexte %xmm7, %xmm2"); | ||
690 | asm volatile("sha1nexte (%eax), %xmm0"); | ||
691 | asm volatile("sha1nexte (0x12345678), %xmm0"); | ||
692 | asm volatile("sha1nexte (%eax), %xmm3"); | ||
693 | asm volatile("sha1nexte (%ecx,%eax,1), %xmm0"); | ||
694 | asm volatile("sha1nexte 0x12345678(,%eax,1), %xmm0"); | ||
695 | asm volatile("sha1nexte (%eax,%ecx,1), %xmm0"); | ||
696 | asm volatile("sha1nexte (%eax,%ecx,8), %xmm0"); | ||
697 | asm volatile("sha1nexte 0x12(%eax), %xmm0"); | ||
698 | asm volatile("sha1nexte 0x12(%ebp), %xmm0"); | ||
699 | asm volatile("sha1nexte 0x12(%ecx,%eax,1), %xmm0"); | ||
700 | asm volatile("sha1nexte 0x12(%ebp,%eax,1), %xmm0"); | ||
701 | asm volatile("sha1nexte 0x12(%eax,%ecx,1), %xmm0"); | ||
702 | asm volatile("sha1nexte 0x12(%eax,%ecx,8), %xmm0"); | ||
703 | asm volatile("sha1nexte 0x12345678(%eax), %xmm0"); | ||
704 | asm volatile("sha1nexte 0x12345678(%ebp), %xmm0"); | ||
705 | asm volatile("sha1nexte 0x12345678(%ecx,%eax,1), %xmm0"); | ||
706 | asm volatile("sha1nexte 0x12345678(%ebp,%eax,1), %xmm0"); | ||
707 | asm volatile("sha1nexte 0x12345678(%eax,%ecx,1), %xmm0"); | ||
708 | asm volatile("sha1nexte 0x12345678(%eax,%ecx,8), %xmm0"); | ||
709 | |||
710 | /* sha1msg1 xmm2/m128, xmm1 */ | ||
711 | |||
712 | asm volatile("sha1msg1 %xmm1, %xmm0"); | ||
713 | asm volatile("sha1msg1 %xmm7, %xmm2"); | ||
714 | asm volatile("sha1msg1 (%eax), %xmm0"); | ||
715 | asm volatile("sha1msg1 (0x12345678), %xmm0"); | ||
716 | asm volatile("sha1msg1 (%eax), %xmm3"); | ||
717 | asm volatile("sha1msg1 (%ecx,%eax,1), %xmm0"); | ||
718 | asm volatile("sha1msg1 0x12345678(,%eax,1), %xmm0"); | ||
719 | asm volatile("sha1msg1 (%eax,%ecx,1), %xmm0"); | ||
720 | asm volatile("sha1msg1 (%eax,%ecx,8), %xmm0"); | ||
721 | asm volatile("sha1msg1 0x12(%eax), %xmm0"); | ||
722 | asm volatile("sha1msg1 0x12(%ebp), %xmm0"); | ||
723 | asm volatile("sha1msg1 0x12(%ecx,%eax,1), %xmm0"); | ||
724 | asm volatile("sha1msg1 0x12(%ebp,%eax,1), %xmm0"); | ||
725 | asm volatile("sha1msg1 0x12(%eax,%ecx,1), %xmm0"); | ||
726 | asm volatile("sha1msg1 0x12(%eax,%ecx,8), %xmm0"); | ||
727 | asm volatile("sha1msg1 0x12345678(%eax), %xmm0"); | ||
728 | asm volatile("sha1msg1 0x12345678(%ebp), %xmm0"); | ||
729 | asm volatile("sha1msg1 0x12345678(%ecx,%eax,1), %xmm0"); | ||
730 | asm volatile("sha1msg1 0x12345678(%ebp,%eax,1), %xmm0"); | ||
731 | asm volatile("sha1msg1 0x12345678(%eax,%ecx,1), %xmm0"); | ||
732 | asm volatile("sha1msg1 0x12345678(%eax,%ecx,8), %xmm0"); | ||
733 | |||
734 | /* sha1msg2 xmm2/m128, xmm1 */ | ||
735 | |||
736 | asm volatile("sha1msg2 %xmm1, %xmm0"); | ||
737 | asm volatile("sha1msg2 %xmm7, %xmm2"); | ||
738 | asm volatile("sha1msg2 (%eax), %xmm0"); | ||
739 | asm volatile("sha1msg2 (0x12345678), %xmm0"); | ||
740 | asm volatile("sha1msg2 (%eax), %xmm3"); | ||
741 | asm volatile("sha1msg2 (%ecx,%eax,1), %xmm0"); | ||
742 | asm volatile("sha1msg2 0x12345678(,%eax,1), %xmm0"); | ||
743 | asm volatile("sha1msg2 (%eax,%ecx,1), %xmm0"); | ||
744 | asm volatile("sha1msg2 (%eax,%ecx,8), %xmm0"); | ||
745 | asm volatile("sha1msg2 0x12(%eax), %xmm0"); | ||
746 | asm volatile("sha1msg2 0x12(%ebp), %xmm0"); | ||
747 | asm volatile("sha1msg2 0x12(%ecx,%eax,1), %xmm0"); | ||
748 | asm volatile("sha1msg2 0x12(%ebp,%eax,1), %xmm0"); | ||
749 | asm volatile("sha1msg2 0x12(%eax,%ecx,1), %xmm0"); | ||
750 | asm volatile("sha1msg2 0x12(%eax,%ecx,8), %xmm0"); | ||
751 | asm volatile("sha1msg2 0x12345678(%eax), %xmm0"); | ||
752 | asm volatile("sha1msg2 0x12345678(%ebp), %xmm0"); | ||
753 | asm volatile("sha1msg2 0x12345678(%ecx,%eax,1), %xmm0"); | ||
754 | asm volatile("sha1msg2 0x12345678(%ebp,%eax,1), %xmm0"); | ||
755 | asm volatile("sha1msg2 0x12345678(%eax,%ecx,1), %xmm0"); | ||
756 | asm volatile("sha1msg2 0x12345678(%eax,%ecx,8), %xmm0"); | ||
757 | |||
758 | /* sha256rnds2 <XMM0>, xmm2/m128, xmm1 */ | ||
759 | /* Note sha256rnds2 has an implicit operand 'xmm0' */ | ||
760 | |||
761 | asm volatile("sha256rnds2 %xmm4, %xmm1"); | ||
762 | asm volatile("sha256rnds2 %xmm7, %xmm2"); | ||
763 | asm volatile("sha256rnds2 (%eax), %xmm1"); | ||
764 | asm volatile("sha256rnds2 (0x12345678), %xmm1"); | ||
765 | asm volatile("sha256rnds2 (%eax), %xmm3"); | ||
766 | asm volatile("sha256rnds2 (%ecx,%eax,1), %xmm1"); | ||
767 | asm volatile("sha256rnds2 0x12345678(,%eax,1), %xmm1"); | ||
768 | asm volatile("sha256rnds2 (%eax,%ecx,1), %xmm1"); | ||
769 | asm volatile("sha256rnds2 (%eax,%ecx,8), %xmm1"); | ||
770 | asm volatile("sha256rnds2 0x12(%eax), %xmm1"); | ||
771 | asm volatile("sha256rnds2 0x12(%ebp), %xmm1"); | ||
772 | asm volatile("sha256rnds2 0x12(%ecx,%eax,1), %xmm1"); | ||
773 | asm volatile("sha256rnds2 0x12(%ebp,%eax,1), %xmm1"); | ||
774 | asm volatile("sha256rnds2 0x12(%eax,%ecx,1), %xmm1"); | ||
775 | asm volatile("sha256rnds2 0x12(%eax,%ecx,8), %xmm1"); | ||
776 | asm volatile("sha256rnds2 0x12345678(%eax), %xmm1"); | ||
777 | asm volatile("sha256rnds2 0x12345678(%ebp), %xmm1"); | ||
778 | asm volatile("sha256rnds2 0x12345678(%ecx,%eax,1), %xmm1"); | ||
779 | asm volatile("sha256rnds2 0x12345678(%ebp,%eax,1), %xmm1"); | ||
780 | asm volatile("sha256rnds2 0x12345678(%eax,%ecx,1), %xmm1"); | ||
781 | asm volatile("sha256rnds2 0x12345678(%eax,%ecx,8), %xmm1"); | ||
782 | |||
783 | /* sha256msg1 xmm2/m128, xmm1 */ | ||
784 | |||
785 | asm volatile("sha256msg1 %xmm1, %xmm0"); | ||
786 | asm volatile("sha256msg1 %xmm7, %xmm2"); | ||
787 | asm volatile("sha256msg1 (%eax), %xmm0"); | ||
788 | asm volatile("sha256msg1 (0x12345678), %xmm0"); | ||
789 | asm volatile("sha256msg1 (%eax), %xmm3"); | ||
790 | asm volatile("sha256msg1 (%ecx,%eax,1), %xmm0"); | ||
791 | asm volatile("sha256msg1 0x12345678(,%eax,1), %xmm0"); | ||
792 | asm volatile("sha256msg1 (%eax,%ecx,1), %xmm0"); | ||
793 | asm volatile("sha256msg1 (%eax,%ecx,8), %xmm0"); | ||
794 | asm volatile("sha256msg1 0x12(%eax), %xmm0"); | ||
795 | asm volatile("sha256msg1 0x12(%ebp), %xmm0"); | ||
796 | asm volatile("sha256msg1 0x12(%ecx,%eax,1), %xmm0"); | ||
797 | asm volatile("sha256msg1 0x12(%ebp,%eax,1), %xmm0"); | ||
798 | asm volatile("sha256msg1 0x12(%eax,%ecx,1), %xmm0"); | ||
799 | asm volatile("sha256msg1 0x12(%eax,%ecx,8), %xmm0"); | ||
800 | asm volatile("sha256msg1 0x12345678(%eax), %xmm0"); | ||
801 | asm volatile("sha256msg1 0x12345678(%ebp), %xmm0"); | ||
802 | asm volatile("sha256msg1 0x12345678(%ecx,%eax,1), %xmm0"); | ||
803 | asm volatile("sha256msg1 0x12345678(%ebp,%eax,1), %xmm0"); | ||
804 | asm volatile("sha256msg1 0x12345678(%eax,%ecx,1), %xmm0"); | ||
805 | asm volatile("sha256msg1 0x12345678(%eax,%ecx,8), %xmm0"); | ||
806 | |||
807 | /* sha256msg2 xmm2/m128, xmm1 */ | ||
808 | |||
809 | asm volatile("sha256msg2 %xmm1, %xmm0"); | ||
810 | asm volatile("sha256msg2 %xmm7, %xmm2"); | ||
811 | asm volatile("sha256msg2 (%eax), %xmm0"); | ||
812 | asm volatile("sha256msg2 (0x12345678), %xmm0"); | ||
813 | asm volatile("sha256msg2 (%eax), %xmm3"); | ||
814 | asm volatile("sha256msg2 (%ecx,%eax,1), %xmm0"); | ||
815 | asm volatile("sha256msg2 0x12345678(,%eax,1), %xmm0"); | ||
816 | asm volatile("sha256msg2 (%eax,%ecx,1), %xmm0"); | ||
817 | asm volatile("sha256msg2 (%eax,%ecx,8), %xmm0"); | ||
818 | asm volatile("sha256msg2 0x12(%eax), %xmm0"); | ||
819 | asm volatile("sha256msg2 0x12(%ebp), %xmm0"); | ||
820 | asm volatile("sha256msg2 0x12(%ecx,%eax,1), %xmm0"); | ||
821 | asm volatile("sha256msg2 0x12(%ebp,%eax,1), %xmm0"); | ||
822 | asm volatile("sha256msg2 0x12(%eax,%ecx,1), %xmm0"); | ||
823 | asm volatile("sha256msg2 0x12(%eax,%ecx,8), %xmm0"); | ||
824 | asm volatile("sha256msg2 0x12345678(%eax), %xmm0"); | ||
825 | asm volatile("sha256msg2 0x12345678(%ebp), %xmm0"); | ||
826 | asm volatile("sha256msg2 0x12345678(%ecx,%eax,1), %xmm0"); | ||
827 | asm volatile("sha256msg2 0x12345678(%ebp,%eax,1), %xmm0"); | ||
828 | asm volatile("sha256msg2 0x12345678(%eax,%ecx,1), %xmm0"); | ||
829 | asm volatile("sha256msg2 0x12345678(%eax,%ecx,8), %xmm0"); | ||
830 | |||
831 | /* clflushopt m8 */ | ||
832 | |||
833 | asm volatile("clflushopt (%eax)"); | ||
834 | asm volatile("clflushopt (0x12345678)"); | ||
835 | asm volatile("clflushopt 0x12345678(%eax,%ecx,8)"); | ||
836 | /* Also check instructions in the same group encoding as clflushopt */ | ||
837 | asm volatile("clflush (%eax)"); | ||
838 | asm volatile("sfence"); | ||
839 | |||
840 | /* clwb m8 */ | ||
841 | |||
842 | asm volatile("clwb (%eax)"); | ||
843 | asm volatile("clwb (0x12345678)"); | ||
844 | asm volatile("clwb 0x12345678(%eax,%ecx,8)"); | ||
845 | /* Also check instructions in the same group encoding as clwb */ | ||
846 | asm volatile("xsaveopt (%eax)"); | ||
847 | asm volatile("mfence"); | ||
848 | |||
849 | /* xsavec mem */ | ||
850 | |||
851 | asm volatile("xsavec (%eax)"); | ||
852 | asm volatile("xsavec (0x12345678)"); | ||
853 | asm volatile("xsavec 0x12345678(%eax,%ecx,8)"); | ||
854 | |||
855 | /* xsaves mem */ | ||
856 | |||
857 | asm volatile("xsaves (%eax)"); | ||
858 | asm volatile("xsaves (0x12345678)"); | ||
859 | asm volatile("xsaves 0x12345678(%eax,%ecx,8)"); | ||
860 | |||
861 | /* xrstors mem */ | ||
862 | |||
863 | asm volatile("xrstors (%eax)"); | ||
864 | asm volatile("xrstors (0x12345678)"); | ||
865 | asm volatile("xrstors 0x12345678(%eax,%ecx,8)"); | ||
866 | |||
867 | #endif /* #ifndef __x86_64__ */ | ||
868 | |||
869 | /* pcommit */ | ||
870 | |||
871 | asm volatile("pcommit"); | ||
872 | |||
873 | /* Following line is a marker for the awk script - do not change */ | ||
874 | asm volatile("rdtsc"); /* Stop here */ | ||
875 | |||
876 | return 0; | ||
877 | } | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86.c b/tools/perf/arch/x86/tests/insn-x86.c new file mode 100644 index 000000000000..b6115dfd28f0 --- /dev/null +++ b/tools/perf/arch/x86/tests/insn-x86.c | |||
@@ -0,0 +1,185 @@ | |||
1 | #include <linux/types.h> | ||
2 | |||
3 | #include "debug.h" | ||
4 | #include "tests/tests.h" | ||
5 | #include "arch-tests.h" | ||
6 | |||
7 | #include "intel-pt-decoder/insn.h" | ||
8 | #include "intel-pt-decoder/intel-pt-insn-decoder.h" | ||
9 | |||
10 | struct test_data { | ||
11 | u8 data[MAX_INSN_SIZE]; | ||
12 | int expected_length; | ||
13 | int expected_rel; | ||
14 | const char *expected_op_str; | ||
15 | const char *expected_branch_str; | ||
16 | const char *asm_rep; | ||
17 | }; | ||
18 | |||
19 | struct test_data test_data_32[] = { | ||
20 | #include "insn-x86-dat-32.c" | ||
21 | {{0x0f, 0x01, 0xee}, 3, 0, NULL, NULL, "0f 01 ee \trdpkru"}, | ||
22 | {{0x0f, 0x01, 0xef}, 3, 0, NULL, NULL, "0f 01 ef \twrpkru"}, | ||
23 | {{0}, 0, 0, NULL, NULL, NULL}, | ||
24 | }; | ||
25 | |||
26 | struct test_data test_data_64[] = { | ||
27 | #include "insn-x86-dat-64.c" | ||
28 | {{0x0f, 0x01, 0xee}, 3, 0, NULL, NULL, "0f 01 ee \trdpkru"}, | ||
29 | {{0x0f, 0x01, 0xef}, 3, 0, NULL, NULL, "0f 01 ef \twrpkru"}, | ||
30 | {{0}, 0, 0, NULL, NULL, NULL}, | ||
31 | }; | ||
32 | |||
33 | static int get_op(const char *op_str) | ||
34 | { | ||
35 | struct val_data { | ||
36 | const char *name; | ||
37 | int val; | ||
38 | } vals[] = { | ||
39 | {"other", INTEL_PT_OP_OTHER}, | ||
40 | {"call", INTEL_PT_OP_CALL}, | ||
41 | {"ret", INTEL_PT_OP_RET}, | ||
42 | {"jcc", INTEL_PT_OP_JCC}, | ||
43 | {"jmp", INTEL_PT_OP_JMP}, | ||
44 | {"loop", INTEL_PT_OP_LOOP}, | ||
45 | {"iret", INTEL_PT_OP_IRET}, | ||
46 | {"int", INTEL_PT_OP_INT}, | ||
47 | {"syscall", INTEL_PT_OP_SYSCALL}, | ||
48 | {"sysret", INTEL_PT_OP_SYSRET}, | ||
49 | {NULL, 0}, | ||
50 | }; | ||
51 | struct val_data *val; | ||
52 | |||
53 | if (!op_str || !strlen(op_str)) | ||
54 | return 0; | ||
55 | |||
56 | for (val = vals; val->name; val++) { | ||
57 | if (!strcmp(val->name, op_str)) | ||
58 | return val->val; | ||
59 | } | ||
60 | |||
61 | pr_debug("Failed to get op\n"); | ||
62 | |||
63 | return -1; | ||
64 | } | ||
65 | |||
66 | static int get_branch(const char *branch_str) | ||
67 | { | ||
68 | struct val_data { | ||
69 | const char *name; | ||
70 | int val; | ||
71 | } vals[] = { | ||
72 | {"no_branch", INTEL_PT_BR_NO_BRANCH}, | ||
73 | {"indirect", INTEL_PT_BR_INDIRECT}, | ||
74 | {"conditional", INTEL_PT_BR_CONDITIONAL}, | ||
75 | {"unconditional", INTEL_PT_BR_UNCONDITIONAL}, | ||
76 | {NULL, 0}, | ||
77 | }; | ||
78 | struct val_data *val; | ||
79 | |||
80 | if (!branch_str || !strlen(branch_str)) | ||
81 | return 0; | ||
82 | |||
83 | for (val = vals; val->name; val++) { | ||
84 | if (!strcmp(val->name, branch_str)) | ||
85 | return val->val; | ||
86 | } | ||
87 | |||
88 | pr_debug("Failed to get branch\n"); | ||
89 | |||
90 | return -1; | ||
91 | } | ||
92 | |||
93 | static int test_data_item(struct test_data *dat, int x86_64) | ||
94 | { | ||
95 | struct intel_pt_insn intel_pt_insn; | ||
96 | struct insn insn; | ||
97 | int op, branch; | ||
98 | |||
99 | insn_init(&insn, dat->data, MAX_INSN_SIZE, x86_64); | ||
100 | insn_get_length(&insn); | ||
101 | |||
102 | if (!insn_complete(&insn)) { | ||
103 | pr_debug("Failed to decode: %s\n", dat->asm_rep); | ||
104 | return -1; | ||
105 | } | ||
106 | |||
107 | if (insn.length != dat->expected_length) { | ||
108 | pr_debug("Failed to decode length (%d vs expected %d): %s\n", | ||
109 | insn.length, dat->expected_length, dat->asm_rep); | ||
110 | return -1; | ||
111 | } | ||
112 | |||
113 | op = get_op(dat->expected_op_str); | ||
114 | branch = get_branch(dat->expected_branch_str); | ||
115 | |||
116 | if (intel_pt_get_insn(dat->data, MAX_INSN_SIZE, x86_64, &intel_pt_insn)) { | ||
117 | pr_debug("Intel PT failed to decode: %s\n", dat->asm_rep); | ||
118 | return -1; | ||
119 | } | ||
120 | |||
121 | if ((int)intel_pt_insn.op != op) { | ||
122 | pr_debug("Failed to decode 'op' value (%d vs expected %d): %s\n", | ||
123 | intel_pt_insn.op, op, dat->asm_rep); | ||
124 | return -1; | ||
125 | } | ||
126 | |||
127 | if ((int)intel_pt_insn.branch != branch) { | ||
128 | pr_debug("Failed to decode 'branch' value (%d vs expected %d): %s\n", | ||
129 | intel_pt_insn.branch, branch, dat->asm_rep); | ||
130 | return -1; | ||
131 | } | ||
132 | |||
133 | if (intel_pt_insn.rel != dat->expected_rel) { | ||
134 | pr_debug("Failed to decode 'rel' value (%#x vs expected %#x): %s\n", | ||
135 | intel_pt_insn.rel, dat->expected_rel, dat->asm_rep); | ||
136 | return -1; | ||
137 | } | ||
138 | |||
139 | pr_debug("Decoded ok: %s\n", dat->asm_rep); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int test_data_set(struct test_data *dat_set, int x86_64) | ||
145 | { | ||
146 | struct test_data *dat; | ||
147 | int ret = 0; | ||
148 | |||
149 | for (dat = dat_set; dat->expected_length; dat++) { | ||
150 | if (test_data_item(dat, x86_64)) | ||
151 | ret = -1; | ||
152 | } | ||
153 | |||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * test__insn_x86 - test x86 instruction decoder - new instructions. | ||
159 | * | ||
160 | * This function implements a test that decodes a selection of instructions and | ||
161 | * checks the results. The Intel PT function that further categorizes | ||
162 | * instructions (i.e. intel_pt_get_insn()) is also checked. | ||
163 | * | ||
164 | * The instructions are originally in insn-x86-dat-src.c which has been | ||
165 | * processed by scripts gen-insn-x86-dat.sh and gen-insn-x86-dat.awk to produce | ||
166 | * insn-x86-dat-32.c and insn-x86-dat-64.c which are included into this program. | ||
167 | * i.e. to add new instructions to the test, edit insn-x86-dat-src.c, run the | ||
168 | * gen-insn-x86-dat.sh script, make perf, and then run the test. | ||
169 | * | ||
170 | * If the test passes %0 is returned, otherwise %-1 is returned. Use the | ||
171 | * verbose (-v) option to see all the instructions and whether or not they | ||
172 | * decoded successfuly. | ||
173 | */ | ||
174 | int test__insn_x86(void) | ||
175 | { | ||
176 | int ret = 0; | ||
177 | |||
178 | if (test_data_set(test_data_32, 0)) | ||
179 | ret = -1; | ||
180 | |||
181 | if (test_data_set(test_data_64, 1)) | ||
182 | ret = -1; | ||
183 | |||
184 | return ret; | ||
185 | } | ||
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c new file mode 100644 index 000000000000..d28c1b6a3b54 --- /dev/null +++ b/tools/perf/arch/x86/tests/intel-cqm.c | |||
@@ -0,0 +1,124 @@ | |||
1 | #include "tests/tests.h" | ||
2 | #include "perf.h" | ||
3 | #include "cloexec.h" | ||
4 | #include "debug.h" | ||
5 | #include "evlist.h" | ||
6 | #include "evsel.h" | ||
7 | #include "arch-tests.h" | ||
8 | |||
9 | #include <sys/mman.h> | ||
10 | #include <string.h> | ||
11 | |||
12 | static pid_t spawn(void) | ||
13 | { | ||
14 | pid_t pid; | ||
15 | |||
16 | pid = fork(); | ||
17 | if (pid) | ||
18 | return pid; | ||
19 | |||
20 | while(1); | ||
21 | sleep(5); | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | /* | ||
26 | * Create an event group that contains both a sampled hardware | ||
27 | * (cpu-cycles) and software (intel_cqm/llc_occupancy/) event. We then | ||
28 | * wait for the hardware perf counter to overflow and generate a PMI, | ||
29 | * which triggers an event read for both of the events in the group. | ||
30 | * | ||
31 | * Since reading Intel CQM event counters requires sending SMP IPIs, the | ||
32 | * CQM pmu needs to handle the above situation gracefully, and return | ||
33 | * the last read counter value to avoid triggering a WARN_ON_ONCE() in | ||
34 | * smp_call_function_many() caused by sending IPIs from NMI context. | ||
35 | */ | ||
36 | int test__intel_cqm_count_nmi_context(void) | ||
37 | { | ||
38 | struct perf_evlist *evlist = NULL; | ||
39 | struct perf_evsel *evsel = NULL; | ||
40 | struct perf_event_attr pe; | ||
41 | int i, fd[2], flag, ret; | ||
42 | size_t mmap_len; | ||
43 | void *event; | ||
44 | pid_t pid; | ||
45 | int err = TEST_FAIL; | ||
46 | |||
47 | flag = perf_event_open_cloexec_flag(); | ||
48 | |||
49 | evlist = perf_evlist__new(); | ||
50 | if (!evlist) { | ||
51 | pr_debug("perf_evlist__new failed\n"); | ||
52 | return TEST_FAIL; | ||
53 | } | ||
54 | |||
55 | ret = parse_events(evlist, "intel_cqm/llc_occupancy/", NULL); | ||
56 | if (ret) { | ||
57 | pr_debug("parse_events failed\n"); | ||
58 | err = TEST_SKIP; | ||
59 | goto out; | ||
60 | } | ||
61 | |||
62 | evsel = perf_evlist__first(evlist); | ||
63 | if (!evsel) { | ||
64 | pr_debug("perf_evlist__first failed\n"); | ||
65 | goto out; | ||
66 | } | ||
67 | |||
68 | memset(&pe, 0, sizeof(pe)); | ||
69 | pe.size = sizeof(pe); | ||
70 | |||
71 | pe.type = PERF_TYPE_HARDWARE; | ||
72 | pe.config = PERF_COUNT_HW_CPU_CYCLES; | ||
73 | pe.read_format = PERF_FORMAT_GROUP; | ||
74 | |||
75 | pe.sample_period = 128; | ||
76 | pe.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_READ; | ||
77 | |||
78 | pid = spawn(); | ||
79 | |||
80 | fd[0] = sys_perf_event_open(&pe, pid, -1, -1, flag); | ||
81 | if (fd[0] < 0) { | ||
82 | pr_debug("failed to open event\n"); | ||
83 | goto out; | ||
84 | } | ||
85 | |||
86 | memset(&pe, 0, sizeof(pe)); | ||
87 | pe.size = sizeof(pe); | ||
88 | |||
89 | pe.type = evsel->attr.type; | ||
90 | pe.config = evsel->attr.config; | ||
91 | |||
92 | fd[1] = sys_perf_event_open(&pe, pid, -1, fd[0], flag); | ||
93 | if (fd[1] < 0) { | ||
94 | pr_debug("failed to open event\n"); | ||
95 | goto out; | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * Pick a power-of-two number of pages + 1 for the meta-data | ||
100 | * page (struct perf_event_mmap_page). See tools/perf/design.txt. | ||
101 | */ | ||
102 | mmap_len = page_size * 65; | ||
103 | |||
104 | event = mmap(NULL, mmap_len, PROT_READ, MAP_SHARED, fd[0], 0); | ||
105 | if (event == (void *)(-1)) { | ||
106 | pr_debug("failed to mmap %d\n", errno); | ||
107 | goto out; | ||
108 | } | ||
109 | |||
110 | sleep(1); | ||
111 | |||
112 | err = TEST_OK; | ||
113 | |||
114 | munmap(event, mmap_len); | ||
115 | |||
116 | for (i = 0; i < 2; i++) | ||
117 | close(fd[i]); | ||
118 | |||
119 | kill(pid, SIGKILL); | ||
120 | wait(NULL); | ||
121 | out: | ||
122 | perf_evlist__delete(evlist); | ||
123 | return err; | ||
124 | } | ||
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c index 5f49484f1abc..658cd200af74 100644 --- a/tools/perf/tests/perf-time-to-tsc.c +++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c | |||
@@ -9,7 +9,9 @@ | |||
9 | #include "thread_map.h" | 9 | #include "thread_map.h" |
10 | #include "cpumap.h" | 10 | #include "cpumap.h" |
11 | #include "tsc.h" | 11 | #include "tsc.h" |
12 | #include "tests.h" | 12 | #include "tests/tests.h" |
13 | |||
14 | #include "arch-tests.h" | ||
13 | 15 | ||
14 | #define CHECK__(x) { \ | 16 | #define CHECK__(x) { \ |
15 | while ((x) < 0) { \ | 17 | while ((x) < 0) { \ |
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/arch/x86/tests/rdpmc.c index d31f2c4d9f64..e7688214c7cf 100644 --- a/tools/perf/tests/rdpmc.c +++ b/tools/perf/arch/x86/tests/rdpmc.c | |||
@@ -5,10 +5,9 @@ | |||
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include "perf.h" | 6 | #include "perf.h" |
7 | #include "debug.h" | 7 | #include "debug.h" |
8 | #include "tests.h" | 8 | #include "tests/tests.h" |
9 | #include "cloexec.h" | 9 | #include "cloexec.h" |
10 | 10 | #include "arch-tests.h" | |
11 | #if defined(__x86_64__) || defined(__i386__) | ||
12 | 11 | ||
13 | static u64 rdpmc(unsigned int counter) | 12 | static u64 rdpmc(unsigned int counter) |
14 | { | 13 | { |
@@ -173,5 +172,3 @@ int test__rdpmc(void) | |||
173 | 172 | ||
174 | return 0; | 173 | return 0; |
175 | } | 174 | } |
176 | |||
177 | #endif | ||
diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c index a08de0a35b83..9223c164e545 100644 --- a/tools/perf/arch/x86/util/dwarf-regs.c +++ b/tools/perf/arch/x86/util/dwarf-regs.c | |||
@@ -21,55 +21,109 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <stddef.h> | 23 | #include <stddef.h> |
24 | #include <errno.h> /* for EINVAL */ | ||
25 | #include <string.h> /* for strcmp */ | ||
26 | #include <linux/ptrace.h> /* for struct pt_regs */ | ||
27 | #include <linux/kernel.h> /* for offsetof */ | ||
24 | #include <dwarf-regs.h> | 28 | #include <dwarf-regs.h> |
25 | 29 | ||
26 | /* | 30 | /* |
27 | * Generic dwarf analysis helpers | 31 | * See arch/x86/kernel/ptrace.c. |
32 | * Different from it: | ||
33 | * | ||
34 | * - Since struct pt_regs is defined differently for user and kernel, | ||
35 | * but we want to use 'ax, bx' instead of 'rax, rbx' (which is struct | ||
36 | * field name of user's pt_regs), we make REG_OFFSET_NAME to accept | ||
37 | * both string name and reg field name. | ||
38 | * | ||
39 | * - Since accessing x86_32's pt_regs from x86_64 building is difficult | ||
40 | * and vise versa, we simply fill offset with -1, so | ||
41 | * get_arch_regstr() still works but regs_query_register_offset() | ||
42 | * returns error. | ||
43 | * The only inconvenience caused by it now is that we are not allowed | ||
44 | * to generate BPF prologue for a x86_64 kernel if perf is built for | ||
45 | * x86_32. This is really a rare usecase. | ||
46 | * | ||
47 | * - Order is different from kernel's ptrace.c for get_arch_regstr(). Use | ||
48 | * the order defined by dwarf. | ||
28 | */ | 49 | */ |
29 | 50 | ||
30 | #define X86_32_MAX_REGS 8 | 51 | struct pt_regs_offset { |
31 | const char *x86_32_regs_table[X86_32_MAX_REGS] = { | 52 | const char *name; |
32 | "%ax", | 53 | int offset; |
33 | "%cx", | 54 | }; |
34 | "%dx", | 55 | |
35 | "%bx", | 56 | #define REG_OFFSET_END {.name = NULL, .offset = 0} |
36 | "$stack", /* Stack address instead of %sp */ | 57 | |
37 | "%bp", | 58 | #ifdef __x86_64__ |
38 | "%si", | 59 | # define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)} |
39 | "%di", | 60 | # define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = -1} |
61 | #else | ||
62 | # define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = -1} | ||
63 | # define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)} | ||
64 | #endif | ||
65 | |||
66 | static const struct pt_regs_offset x86_32_regoffset_table[] = { | ||
67 | REG_OFFSET_NAME_32("%ax", eax), | ||
68 | REG_OFFSET_NAME_32("%cx", ecx), | ||
69 | REG_OFFSET_NAME_32("%dx", edx), | ||
70 | REG_OFFSET_NAME_32("%bx", ebx), | ||
71 | REG_OFFSET_NAME_32("$stack", esp), /* Stack address instead of %sp */ | ||
72 | REG_OFFSET_NAME_32("%bp", ebp), | ||
73 | REG_OFFSET_NAME_32("%si", esi), | ||
74 | REG_OFFSET_NAME_32("%di", edi), | ||
75 | REG_OFFSET_END, | ||
40 | }; | 76 | }; |
41 | 77 | ||
42 | #define X86_64_MAX_REGS 16 | 78 | static const struct pt_regs_offset x86_64_regoffset_table[] = { |
43 | const char *x86_64_regs_table[X86_64_MAX_REGS] = { | 79 | REG_OFFSET_NAME_64("%ax", rax), |
44 | "%ax", | 80 | REG_OFFSET_NAME_64("%dx", rdx), |
45 | "%dx", | 81 | REG_OFFSET_NAME_64("%cx", rcx), |
46 | "%cx", | 82 | REG_OFFSET_NAME_64("%bx", rbx), |
47 | "%bx", | 83 | REG_OFFSET_NAME_64("%si", rsi), |
48 | "%si", | 84 | REG_OFFSET_NAME_64("%di", rdi), |
49 | "%di", | 85 | REG_OFFSET_NAME_64("%bp", rbp), |
50 | "%bp", | 86 | REG_OFFSET_NAME_64("%sp", rsp), |
51 | "%sp", | 87 | REG_OFFSET_NAME_64("%r8", r8), |
52 | "%r8", | 88 | REG_OFFSET_NAME_64("%r9", r9), |
53 | "%r9", | 89 | REG_OFFSET_NAME_64("%r10", r10), |
54 | "%r10", | 90 | REG_OFFSET_NAME_64("%r11", r11), |
55 | "%r11", | 91 | REG_OFFSET_NAME_64("%r12", r12), |
56 | "%r12", | 92 | REG_OFFSET_NAME_64("%r13", r13), |
57 | "%r13", | 93 | REG_OFFSET_NAME_64("%r14", r14), |
58 | "%r14", | 94 | REG_OFFSET_NAME_64("%r15", r15), |
59 | "%r15", | 95 | REG_OFFSET_END, |
60 | }; | 96 | }; |
61 | 97 | ||
62 | /* TODO: switching by dwarf address size */ | 98 | /* TODO: switching by dwarf address size */ |
63 | #ifdef __x86_64__ | 99 | #ifdef __x86_64__ |
64 | #define ARCH_MAX_REGS X86_64_MAX_REGS | 100 | #define regoffset_table x86_64_regoffset_table |
65 | #define arch_regs_table x86_64_regs_table | ||
66 | #else | 101 | #else |
67 | #define ARCH_MAX_REGS X86_32_MAX_REGS | 102 | #define regoffset_table x86_32_regoffset_table |
68 | #define arch_regs_table x86_32_regs_table | ||
69 | #endif | 103 | #endif |
70 | 104 | ||
105 | /* Minus 1 for the ending REG_OFFSET_END */ | ||
106 | #define ARCH_MAX_REGS ((sizeof(regoffset_table) / sizeof(regoffset_table[0])) - 1) | ||
107 | |||
71 | /* Return architecture dependent register string (for kprobe-tracer) */ | 108 | /* Return architecture dependent register string (for kprobe-tracer) */ |
72 | const char *get_arch_regstr(unsigned int n) | 109 | const char *get_arch_regstr(unsigned int n) |
73 | { | 110 | { |
74 | return (n < ARCH_MAX_REGS) ? arch_regs_table[n] : NULL; | 111 | return (n < ARCH_MAX_REGS) ? regoffset_table[n].name : NULL; |
112 | } | ||
113 | |||
114 | /* Reuse code from arch/x86/kernel/ptrace.c */ | ||
115 | /** | ||
116 | * regs_query_register_offset() - query register offset from its name | ||
117 | * @name: the name of a register | ||
118 | * | ||
119 | * regs_query_register_offset() returns the offset of a register in struct | ||
120 | * pt_regs from its name. If the name is invalid, this returns -EINVAL; | ||
121 | */ | ||
122 | int regs_query_register_offset(const char *name) | ||
123 | { | ||
124 | const struct pt_regs_offset *roff; | ||
125 | for (roff = regoffset_table; roff->name != NULL; roff++) | ||
126 | if (!strcmp(roff->name, name)) | ||
127 | return roff->offset; | ||
128 | return -EINVAL; | ||
75 | } | 129 | } |
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 2ca10d796c0b..b02af064f0f9 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c | |||
@@ -624,13 +624,49 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
624 | * threads. | 624 | * threads. |
625 | */ | 625 | */ |
626 | if (have_timing_info && !cpu_map__empty(cpus)) { | 626 | if (have_timing_info && !cpu_map__empty(cpus)) { |
627 | err = intel_pt_track_switches(evlist); | 627 | if (perf_can_record_switch_events()) { |
628 | if (err == -EPERM) | 628 | bool cpu_wide = !target__none(&opts->target) && |
629 | pr_debug2("Unable to select sched:sched_switch\n"); | 629 | !target__has_task(&opts->target); |
630 | else if (err) | 630 | |
631 | return err; | 631 | if (!cpu_wide && perf_can_record_cpu_wide()) { |
632 | else | 632 | struct perf_evsel *switch_evsel; |
633 | ptr->have_sched_switch = 1; | 633 | |
634 | err = parse_events(evlist, "dummy:u", NULL); | ||
635 | if (err) | ||
636 | return err; | ||
637 | |||
638 | switch_evsel = perf_evlist__last(evlist); | ||
639 | |||
640 | switch_evsel->attr.freq = 0; | ||
641 | switch_evsel->attr.sample_period = 1; | ||
642 | switch_evsel->attr.context_switch = 1; | ||
643 | |||
644 | switch_evsel->system_wide = true; | ||
645 | switch_evsel->no_aux_samples = true; | ||
646 | switch_evsel->immediate = true; | ||
647 | |||
648 | perf_evsel__set_sample_bit(switch_evsel, TID); | ||
649 | perf_evsel__set_sample_bit(switch_evsel, TIME); | ||
650 | perf_evsel__set_sample_bit(switch_evsel, CPU); | ||
651 | |||
652 | opts->record_switch_events = false; | ||
653 | ptr->have_sched_switch = 3; | ||
654 | } else { | ||
655 | opts->record_switch_events = true; | ||
656 | if (cpu_wide) | ||
657 | ptr->have_sched_switch = 3; | ||
658 | else | ||
659 | ptr->have_sched_switch = 2; | ||
660 | } | ||
661 | } else { | ||
662 | err = intel_pt_track_switches(evlist); | ||
663 | if (err == -EPERM) | ||
664 | pr_debug2("Unable to select sched:sched_switch\n"); | ||
665 | else if (err) | ||
666 | return err; | ||
667 | else | ||
668 | ptr->have_sched_switch = 1; | ||
669 | } | ||
634 | } | 670 | } |
635 | 671 | ||
636 | if (intel_pt_evsel) { | 672 | if (intel_pt_evsel) { |
@@ -663,8 +699,11 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
663 | tracking_evsel->attr.sample_period = 1; | 699 | tracking_evsel->attr.sample_period = 1; |
664 | 700 | ||
665 | /* In per-cpu case, always need the time of mmap events etc */ | 701 | /* In per-cpu case, always need the time of mmap events etc */ |
666 | if (!cpu_map__empty(cpus)) | 702 | if (!cpu_map__empty(cpus)) { |
667 | perf_evsel__set_sample_bit(tracking_evsel, TIME); | 703 | perf_evsel__set_sample_bit(tracking_evsel, TIME); |
704 | /* And the CPU for switch events */ | ||
705 | perf_evsel__set_sample_bit(tracking_evsel, CPU); | ||
706 | } | ||
668 | } | 707 | } |
669 | 708 | ||
670 | /* | 709 | /* |
diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build index 573e28896038..60bf11943047 100644 --- a/tools/perf/bench/Build +++ b/tools/perf/bench/Build | |||
@@ -1,6 +1,6 @@ | |||
1 | perf-y += sched-messaging.o | 1 | perf-y += sched-messaging.o |
2 | perf-y += sched-pipe.o | 2 | perf-y += sched-pipe.o |
3 | perf-y += mem-memcpy.o | 3 | perf-y += mem-functions.o |
4 | perf-y += futex-hash.o | 4 | perf-y += futex-hash.o |
5 | perf-y += futex-wake.o | 5 | perf-y += futex-wake.o |
6 | perf-y += futex-wake-parallel.o | 6 | perf-y += futex-wake-parallel.o |
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c new file mode 100644 index 000000000000..9419b944220f --- /dev/null +++ b/tools/perf/bench/mem-functions.c | |||
@@ -0,0 +1,379 @@ | |||
1 | /* | ||
2 | * mem-memcpy.c | ||
3 | * | ||
4 | * Simple memcpy() and memset() benchmarks | ||
5 | * | ||
6 | * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> | ||
7 | */ | ||
8 | |||
9 | #include "../perf.h" | ||
10 | #include "../util/util.h" | ||
11 | #include "../util/parse-options.h" | ||
12 | #include "../util/header.h" | ||
13 | #include "../util/cloexec.h" | ||
14 | #include "bench.h" | ||
15 | #include "mem-memcpy-arch.h" | ||
16 | #include "mem-memset-arch.h" | ||
17 | |||
18 | #include <stdio.h> | ||
19 | #include <stdlib.h> | ||
20 | #include <string.h> | ||
21 | #include <sys/time.h> | ||
22 | #include <errno.h> | ||
23 | |||
24 | #define K 1024 | ||
25 | |||
26 | static const char *size_str = "1MB"; | ||
27 | static const char *function_str = "all"; | ||
28 | static int nr_loops = 1; | ||
29 | static bool use_cycles; | ||
30 | static int cycles_fd; | ||
31 | |||
32 | static const struct option options[] = { | ||
33 | OPT_STRING('s', "size", &size_str, "1MB", | ||
34 | "Specify the size of the memory buffers. " | ||
35 | "Available units: B, KB, MB, GB and TB (case insensitive)"), | ||
36 | |||
37 | OPT_STRING('f', "function", &function_str, "all", | ||
38 | "Specify the function to run, \"all\" runs all available functions, \"help\" lists them"), | ||
39 | |||
40 | OPT_INTEGER('l', "nr_loops", &nr_loops, | ||
41 | "Specify the number of loops to run. (default: 1)"), | ||
42 | |||
43 | OPT_BOOLEAN('c', "cycles", &use_cycles, | ||
44 | "Use a cycles event instead of gettimeofday() to measure performance"), | ||
45 | |||
46 | OPT_END() | ||
47 | }; | ||
48 | |||
49 | typedef void *(*memcpy_t)(void *, const void *, size_t); | ||
50 | typedef void *(*memset_t)(void *, int, size_t); | ||
51 | |||
52 | struct function { | ||
53 | const char *name; | ||
54 | const char *desc; | ||
55 | union { | ||
56 | memcpy_t memcpy; | ||
57 | memset_t memset; | ||
58 | } fn; | ||
59 | }; | ||
60 | |||
61 | static struct perf_event_attr cycle_attr = { | ||
62 | .type = PERF_TYPE_HARDWARE, | ||
63 | .config = PERF_COUNT_HW_CPU_CYCLES | ||
64 | }; | ||
65 | |||
66 | static void init_cycles(void) | ||
67 | { | ||
68 | cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag()); | ||
69 | |||
70 | if (cycles_fd < 0 && errno == ENOSYS) | ||
71 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | ||
72 | else | ||
73 | BUG_ON(cycles_fd < 0); | ||
74 | } | ||
75 | |||
76 | static u64 get_cycles(void) | ||
77 | { | ||
78 | int ret; | ||
79 | u64 clk; | ||
80 | |||
81 | ret = read(cycles_fd, &clk, sizeof(u64)); | ||
82 | BUG_ON(ret != sizeof(u64)); | ||
83 | |||
84 | return clk; | ||
85 | } | ||
86 | |||
87 | static double timeval2double(struct timeval *ts) | ||
88 | { | ||
89 | return (double)ts->tv_sec + (double)ts->tv_usec / (double)1000000; | ||
90 | } | ||
91 | |||
92 | #define print_bps(x) do { \ | ||
93 | if (x < K) \ | ||
94 | printf(" %14lf bytes/sec\n", x); \ | ||
95 | else if (x < K * K) \ | ||
96 | printf(" %14lfd KB/sec\n", x / K); \ | ||
97 | else if (x < K * K * K) \ | ||
98 | printf(" %14lf MB/sec\n", x / K / K); \ | ||
99 | else \ | ||
100 | printf(" %14lf GB/sec\n", x / K / K / K); \ | ||
101 | } while (0) | ||
102 | |||
103 | struct bench_mem_info { | ||
104 | const struct function *functions; | ||
105 | u64 (*do_cycles)(const struct function *r, size_t size); | ||
106 | double (*do_gettimeofday)(const struct function *r, size_t size); | ||
107 | const char *const *usage; | ||
108 | }; | ||
109 | |||
110 | static void __bench_mem_function(struct bench_mem_info *info, int r_idx, size_t size, double size_total) | ||
111 | { | ||
112 | const struct function *r = &info->functions[r_idx]; | ||
113 | double result_bps = 0.0; | ||
114 | u64 result_cycles = 0; | ||
115 | |||
116 | printf("# function '%s' (%s)\n", r->name, r->desc); | ||
117 | |||
118 | if (bench_format == BENCH_FORMAT_DEFAULT) | ||
119 | printf("# Copying %s bytes ...\n\n", size_str); | ||
120 | |||
121 | if (use_cycles) { | ||
122 | result_cycles = info->do_cycles(r, size); | ||
123 | } else { | ||
124 | result_bps = info->do_gettimeofday(r, size); | ||
125 | } | ||
126 | |||
127 | switch (bench_format) { | ||
128 | case BENCH_FORMAT_DEFAULT: | ||
129 | if (use_cycles) { | ||
130 | printf(" %14lf cycles/byte\n", (double)result_cycles/size_total); | ||
131 | } else { | ||
132 | print_bps(result_bps); | ||
133 | } | ||
134 | break; | ||
135 | |||
136 | case BENCH_FORMAT_SIMPLE: | ||
137 | if (use_cycles) { | ||
138 | printf("%lf\n", (double)result_cycles/size_total); | ||
139 | } else { | ||
140 | printf("%lf\n", result_bps); | ||
141 | } | ||
142 | break; | ||
143 | |||
144 | default: | ||
145 | BUG_ON(1); | ||
146 | break; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *info) | ||
151 | { | ||
152 | int i; | ||
153 | size_t size; | ||
154 | double size_total; | ||
155 | |||
156 | argc = parse_options(argc, argv, options, info->usage, 0); | ||
157 | |||
158 | if (use_cycles) | ||
159 | init_cycles(); | ||
160 | |||
161 | size = (size_t)perf_atoll((char *)size_str); | ||
162 | size_total = (double)size * nr_loops; | ||
163 | |||
164 | if ((s64)size <= 0) { | ||
165 | fprintf(stderr, "Invalid size:%s\n", size_str); | ||
166 | return 1; | ||
167 | } | ||
168 | |||
169 | if (!strncmp(function_str, "all", 3)) { | ||
170 | for (i = 0; info->functions[i].name; i++) | ||
171 | __bench_mem_function(info, i, size, size_total); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | for (i = 0; info->functions[i].name; i++) { | ||
176 | if (!strcmp(info->functions[i].name, function_str)) | ||
177 | break; | ||
178 | } | ||
179 | if (!info->functions[i].name) { | ||
180 | if (strcmp(function_str, "help") && strcmp(function_str, "h")) | ||
181 | printf("Unknown function: %s\n", function_str); | ||
182 | printf("Available functions:\n"); | ||
183 | for (i = 0; info->functions[i].name; i++) { | ||
184 | printf("\t%s ... %s\n", | ||
185 | info->functions[i].name, info->functions[i].desc); | ||
186 | } | ||
187 | return 1; | ||
188 | } | ||
189 | |||
190 | __bench_mem_function(info, i, size, size_total); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static void memcpy_alloc_mem(void **dst, void **src, size_t size) | ||
196 | { | ||
197 | *dst = zalloc(size); | ||
198 | if (!*dst) | ||
199 | die("memory allocation failed - maybe size is too large?\n"); | ||
200 | |||
201 | *src = zalloc(size); | ||
202 | if (!*src) | ||
203 | die("memory allocation failed - maybe size is too large?\n"); | ||
204 | |||
205 | /* Make sure to always prefault zero pages even if MMAP_THRESH is crossed: */ | ||
206 | memset(*src, 0, size); | ||
207 | } | ||
208 | |||
209 | static u64 do_memcpy_cycles(const struct function *r, size_t size) | ||
210 | { | ||
211 | u64 cycle_start = 0ULL, cycle_end = 0ULL; | ||
212 | void *src = NULL, *dst = NULL; | ||
213 | memcpy_t fn = r->fn.memcpy; | ||
214 | int i; | ||
215 | |||
216 | memcpy_alloc_mem(&dst, &src, size); | ||
217 | |||
218 | /* | ||
219 | * We prefault the freshly allocated memory range here, | ||
220 | * to not measure page fault overhead: | ||
221 | */ | ||
222 | fn(dst, src, size); | ||
223 | |||
224 | cycle_start = get_cycles(); | ||
225 | for (i = 0; i < nr_loops; ++i) | ||
226 | fn(dst, src, size); | ||
227 | cycle_end = get_cycles(); | ||
228 | |||
229 | free(src); | ||
230 | free(dst); | ||
231 | return cycle_end - cycle_start; | ||
232 | } | ||
233 | |||
234 | static double do_memcpy_gettimeofday(const struct function *r, size_t size) | ||
235 | { | ||
236 | struct timeval tv_start, tv_end, tv_diff; | ||
237 | memcpy_t fn = r->fn.memcpy; | ||
238 | void *src = NULL, *dst = NULL; | ||
239 | int i; | ||
240 | |||
241 | memcpy_alloc_mem(&dst, &src, size); | ||
242 | |||
243 | /* | ||
244 | * We prefault the freshly allocated memory range here, | ||
245 | * to not measure page fault overhead: | ||
246 | */ | ||
247 | fn(dst, src, size); | ||
248 | |||
249 | BUG_ON(gettimeofday(&tv_start, NULL)); | ||
250 | for (i = 0; i < nr_loops; ++i) | ||
251 | fn(dst, src, size); | ||
252 | BUG_ON(gettimeofday(&tv_end, NULL)); | ||
253 | |||
254 | timersub(&tv_end, &tv_start, &tv_diff); | ||
255 | |||
256 | free(src); | ||
257 | free(dst); | ||
258 | |||
259 | return (double)(((double)size * nr_loops) / timeval2double(&tv_diff)); | ||
260 | } | ||
261 | |||
262 | struct function memcpy_functions[] = { | ||
263 | { .name = "default", | ||
264 | .desc = "Default memcpy() provided by glibc", | ||
265 | .fn.memcpy = memcpy }, | ||
266 | |||
267 | #ifdef HAVE_ARCH_X86_64_SUPPORT | ||
268 | # define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn}, | ||
269 | # include "mem-memcpy-x86-64-asm-def.h" | ||
270 | # undef MEMCPY_FN | ||
271 | #endif | ||
272 | |||
273 | { .name = NULL, } | ||
274 | }; | ||
275 | |||
276 | static const char * const bench_mem_memcpy_usage[] = { | ||
277 | "perf bench mem memcpy <options>", | ||
278 | NULL | ||
279 | }; | ||
280 | |||
281 | int bench_mem_memcpy(int argc, const char **argv, const char *prefix __maybe_unused) | ||
282 | { | ||
283 | struct bench_mem_info info = { | ||
284 | .functions = memcpy_functions, | ||
285 | .do_cycles = do_memcpy_cycles, | ||
286 | .do_gettimeofday = do_memcpy_gettimeofday, | ||
287 | .usage = bench_mem_memcpy_usage, | ||
288 | }; | ||
289 | |||
290 | return bench_mem_common(argc, argv, &info); | ||
291 | } | ||
292 | |||
293 | static void memset_alloc_mem(void **dst, size_t size) | ||
294 | { | ||
295 | *dst = zalloc(size); | ||
296 | if (!*dst) | ||
297 | die("memory allocation failed - maybe size is too large?\n"); | ||
298 | } | ||
299 | |||
300 | static u64 do_memset_cycles(const struct function *r, size_t size) | ||
301 | { | ||
302 | u64 cycle_start = 0ULL, cycle_end = 0ULL; | ||
303 | memset_t fn = r->fn.memset; | ||
304 | void *dst = NULL; | ||
305 | int i; | ||
306 | |||
307 | memset_alloc_mem(&dst, size); | ||
308 | |||
309 | /* | ||
310 | * We prefault the freshly allocated memory range here, | ||
311 | * to not measure page fault overhead: | ||
312 | */ | ||
313 | fn(dst, -1, size); | ||
314 | |||
315 | cycle_start = get_cycles(); | ||
316 | for (i = 0; i < nr_loops; ++i) | ||
317 | fn(dst, i, size); | ||
318 | cycle_end = get_cycles(); | ||
319 | |||
320 | free(dst); | ||
321 | return cycle_end - cycle_start; | ||
322 | } | ||
323 | |||
324 | static double do_memset_gettimeofday(const struct function *r, size_t size) | ||
325 | { | ||
326 | struct timeval tv_start, tv_end, tv_diff; | ||
327 | memset_t fn = r->fn.memset; | ||
328 | void *dst = NULL; | ||
329 | int i; | ||
330 | |||
331 | memset_alloc_mem(&dst, size); | ||
332 | |||
333 | /* | ||
334 | * We prefault the freshly allocated memory range here, | ||
335 | * to not measure page fault overhead: | ||
336 | */ | ||
337 | fn(dst, -1, size); | ||
338 | |||
339 | BUG_ON(gettimeofday(&tv_start, NULL)); | ||
340 | for (i = 0; i < nr_loops; ++i) | ||
341 | fn(dst, i, size); | ||
342 | BUG_ON(gettimeofday(&tv_end, NULL)); | ||
343 | |||
344 | timersub(&tv_end, &tv_start, &tv_diff); | ||
345 | |||
346 | free(dst); | ||
347 | return (double)(((double)size * nr_loops) / timeval2double(&tv_diff)); | ||
348 | } | ||
349 | |||
350 | static const char * const bench_mem_memset_usage[] = { | ||
351 | "perf bench mem memset <options>", | ||
352 | NULL | ||
353 | }; | ||
354 | |||
355 | static const struct function memset_functions[] = { | ||
356 | { .name = "default", | ||
357 | .desc = "Default memset() provided by glibc", | ||
358 | .fn.memset = memset }, | ||
359 | |||
360 | #ifdef HAVE_ARCH_X86_64_SUPPORT | ||
361 | # define MEMSET_FN(_fn, _name, _desc) { .name = _name, .desc = _desc, .fn.memset = _fn }, | ||
362 | # include "mem-memset-x86-64-asm-def.h" | ||
363 | # undef MEMSET_FN | ||
364 | #endif | ||
365 | |||
366 | { .name = NULL, } | ||
367 | }; | ||
368 | |||
369 | int bench_mem_memset(int argc, const char **argv, const char *prefix __maybe_unused) | ||
370 | { | ||
371 | struct bench_mem_info info = { | ||
372 | .functions = memset_functions, | ||
373 | .do_cycles = do_memset_cycles, | ||
374 | .do_gettimeofday = do_memset_gettimeofday, | ||
375 | .usage = bench_mem_memset_usage, | ||
376 | }; | ||
377 | |||
378 | return bench_mem_common(argc, argv, &info); | ||
379 | } | ||
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c deleted file mode 100644 index d3dfb7936dcd..000000000000 --- a/tools/perf/bench/mem-memcpy.c +++ /dev/null | |||
@@ -1,434 +0,0 @@ | |||
1 | /* | ||
2 | * mem-memcpy.c | ||
3 | * | ||
4 | * memcpy: Simple memory copy in various ways | ||
5 | * | ||
6 | * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> | ||
7 | */ | ||
8 | |||
9 | #include "../perf.h" | ||
10 | #include "../util/util.h" | ||
11 | #include "../util/parse-options.h" | ||
12 | #include "../util/header.h" | ||
13 | #include "../util/cloexec.h" | ||
14 | #include "bench.h" | ||
15 | #include "mem-memcpy-arch.h" | ||
16 | #include "mem-memset-arch.h" | ||
17 | |||
18 | #include <stdio.h> | ||
19 | #include <stdlib.h> | ||
20 | #include <string.h> | ||
21 | #include <sys/time.h> | ||
22 | #include <errno.h> | ||
23 | |||
24 | #define K 1024 | ||
25 | |||
26 | static const char *length_str = "1MB"; | ||
27 | static const char *routine = "default"; | ||
28 | static int iterations = 1; | ||
29 | static bool use_cycle; | ||
30 | static int cycle_fd; | ||
31 | static bool only_prefault; | ||
32 | static bool no_prefault; | ||
33 | |||
34 | static const struct option options[] = { | ||
35 | OPT_STRING('l', "length", &length_str, "1MB", | ||
36 | "Specify length of memory to copy. " | ||
37 | "Available units: B, KB, MB, GB and TB (upper and lower)"), | ||
38 | OPT_STRING('r', "routine", &routine, "default", | ||
39 | "Specify routine to copy, \"all\" runs all available routines"), | ||
40 | OPT_INTEGER('i', "iterations", &iterations, | ||
41 | "repeat memcpy() invocation this number of times"), | ||
42 | OPT_BOOLEAN('c', "cycle", &use_cycle, | ||
43 | "Use cycles event instead of gettimeofday() for measuring"), | ||
44 | OPT_BOOLEAN('o', "only-prefault", &only_prefault, | ||
45 | "Show only the result with page faults before memcpy()"), | ||
46 | OPT_BOOLEAN('n', "no-prefault", &no_prefault, | ||
47 | "Show only the result without page faults before memcpy()"), | ||
48 | OPT_END() | ||
49 | }; | ||
50 | |||
51 | typedef void *(*memcpy_t)(void *, const void *, size_t); | ||
52 | typedef void *(*memset_t)(void *, int, size_t); | ||
53 | |||
54 | struct routine { | ||
55 | const char *name; | ||
56 | const char *desc; | ||
57 | union { | ||
58 | memcpy_t memcpy; | ||
59 | memset_t memset; | ||
60 | } fn; | ||
61 | }; | ||
62 | |||
63 | struct routine memcpy_routines[] = { | ||
64 | { .name = "default", | ||
65 | .desc = "Default memcpy() provided by glibc", | ||
66 | .fn.memcpy = memcpy }, | ||
67 | #ifdef HAVE_ARCH_X86_64_SUPPORT | ||
68 | |||
69 | #define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn}, | ||
70 | #include "mem-memcpy-x86-64-asm-def.h" | ||
71 | #undef MEMCPY_FN | ||
72 | |||
73 | #endif | ||
74 | |||
75 | { NULL, | ||
76 | NULL, | ||
77 | {NULL} } | ||
78 | }; | ||
79 | |||
80 | static const char * const bench_mem_memcpy_usage[] = { | ||
81 | "perf bench mem memcpy <options>", | ||
82 | NULL | ||
83 | }; | ||
84 | |||
85 | static struct perf_event_attr cycle_attr = { | ||
86 | .type = PERF_TYPE_HARDWARE, | ||
87 | .config = PERF_COUNT_HW_CPU_CYCLES | ||
88 | }; | ||
89 | |||
90 | static void init_cycle(void) | ||
91 | { | ||
92 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, | ||
93 | perf_event_open_cloexec_flag()); | ||
94 | |||
95 | if (cycle_fd < 0 && errno == ENOSYS) | ||
96 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | ||
97 | else | ||
98 | BUG_ON(cycle_fd < 0); | ||
99 | } | ||
100 | |||
101 | static u64 get_cycle(void) | ||
102 | { | ||
103 | int ret; | ||
104 | u64 clk; | ||
105 | |||
106 | ret = read(cycle_fd, &clk, sizeof(u64)); | ||
107 | BUG_ON(ret != sizeof(u64)); | ||
108 | |||
109 | return clk; | ||
110 | } | ||
111 | |||
112 | static double timeval2double(struct timeval *ts) | ||
113 | { | ||
114 | return (double)ts->tv_sec + | ||
115 | (double)ts->tv_usec / (double)1000000; | ||
116 | } | ||
117 | |||
118 | #define pf (no_prefault ? 0 : 1) | ||
119 | |||
120 | #define print_bps(x) do { \ | ||
121 | if (x < K) \ | ||
122 | printf(" %14lf B/Sec", x); \ | ||
123 | else if (x < K * K) \ | ||
124 | printf(" %14lfd KB/Sec", x / K); \ | ||
125 | else if (x < K * K * K) \ | ||
126 | printf(" %14lf MB/Sec", x / K / K); \ | ||
127 | else \ | ||
128 | printf(" %14lf GB/Sec", x / K / K / K); \ | ||
129 | } while (0) | ||
130 | |||
131 | struct bench_mem_info { | ||
132 | const struct routine *routines; | ||
133 | u64 (*do_cycle)(const struct routine *r, size_t len, bool prefault); | ||
134 | double (*do_gettimeofday)(const struct routine *r, size_t len, bool prefault); | ||
135 | const char *const *usage; | ||
136 | }; | ||
137 | |||
138 | static void __bench_mem_routine(struct bench_mem_info *info, int r_idx, size_t len, double totallen) | ||
139 | { | ||
140 | const struct routine *r = &info->routines[r_idx]; | ||
141 | double result_bps[2]; | ||
142 | u64 result_cycle[2]; | ||
143 | |||
144 | result_cycle[0] = result_cycle[1] = 0ULL; | ||
145 | result_bps[0] = result_bps[1] = 0.0; | ||
146 | |||
147 | printf("Routine %s (%s)\n", r->name, r->desc); | ||
148 | |||
149 | if (bench_format == BENCH_FORMAT_DEFAULT) | ||
150 | printf("# Copying %s Bytes ...\n\n", length_str); | ||
151 | |||
152 | if (!only_prefault && !no_prefault) { | ||
153 | /* show both of results */ | ||
154 | if (use_cycle) { | ||
155 | result_cycle[0] = info->do_cycle(r, len, false); | ||
156 | result_cycle[1] = info->do_cycle(r, len, true); | ||
157 | } else { | ||
158 | result_bps[0] = info->do_gettimeofday(r, len, false); | ||
159 | result_bps[1] = info->do_gettimeofday(r, len, true); | ||
160 | } | ||
161 | } else { | ||
162 | if (use_cycle) | ||
163 | result_cycle[pf] = info->do_cycle(r, len, only_prefault); | ||
164 | else | ||
165 | result_bps[pf] = info->do_gettimeofday(r, len, only_prefault); | ||
166 | } | ||
167 | |||
168 | switch (bench_format) { | ||
169 | case BENCH_FORMAT_DEFAULT: | ||
170 | if (!only_prefault && !no_prefault) { | ||
171 | if (use_cycle) { | ||
172 | printf(" %14lf Cycle/Byte\n", | ||
173 | (double)result_cycle[0] | ||
174 | / totallen); | ||
175 | printf(" %14lf Cycle/Byte (with prefault)\n", | ||
176 | (double)result_cycle[1] | ||
177 | / totallen); | ||
178 | } else { | ||
179 | print_bps(result_bps[0]); | ||
180 | printf("\n"); | ||
181 | print_bps(result_bps[1]); | ||
182 | printf(" (with prefault)\n"); | ||
183 | } | ||
184 | } else { | ||
185 | if (use_cycle) { | ||
186 | printf(" %14lf Cycle/Byte", | ||
187 | (double)result_cycle[pf] | ||
188 | / totallen); | ||
189 | } else | ||
190 | print_bps(result_bps[pf]); | ||
191 | |||
192 | printf("%s\n", only_prefault ? " (with prefault)" : ""); | ||
193 | } | ||
194 | break; | ||
195 | case BENCH_FORMAT_SIMPLE: | ||
196 | if (!only_prefault && !no_prefault) { | ||
197 | if (use_cycle) { | ||
198 | printf("%lf %lf\n", | ||
199 | (double)result_cycle[0] / totallen, | ||
200 | (double)result_cycle[1] / totallen); | ||
201 | } else { | ||
202 | printf("%lf %lf\n", | ||
203 | result_bps[0], result_bps[1]); | ||
204 | } | ||
205 | } else { | ||
206 | if (use_cycle) { | ||
207 | printf("%lf\n", (double)result_cycle[pf] | ||
208 | / totallen); | ||
209 | } else | ||
210 | printf("%lf\n", result_bps[pf]); | ||
211 | } | ||
212 | break; | ||
213 | default: | ||
214 | /* reaching this means there's some disaster: */ | ||
215 | die("unknown format: %d\n", bench_format); | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | static int bench_mem_common(int argc, const char **argv, | ||
221 | const char *prefix __maybe_unused, | ||
222 | struct bench_mem_info *info) | ||
223 | { | ||
224 | int i; | ||
225 | size_t len; | ||
226 | double totallen; | ||
227 | |||
228 | argc = parse_options(argc, argv, options, | ||
229 | info->usage, 0); | ||
230 | |||
231 | if (no_prefault && only_prefault) { | ||
232 | fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n"); | ||
233 | return 1; | ||
234 | } | ||
235 | |||
236 | if (use_cycle) | ||
237 | init_cycle(); | ||
238 | |||
239 | len = (size_t)perf_atoll((char *)length_str); | ||
240 | totallen = (double)len * iterations; | ||
241 | |||
242 | if ((s64)len <= 0) { | ||
243 | fprintf(stderr, "Invalid length:%s\n", length_str); | ||
244 | return 1; | ||
245 | } | ||
246 | |||
247 | /* same to without specifying either of prefault and no-prefault */ | ||
248 | if (only_prefault && no_prefault) | ||
249 | only_prefault = no_prefault = false; | ||
250 | |||
251 | if (!strncmp(routine, "all", 3)) { | ||
252 | for (i = 0; info->routines[i].name; i++) | ||
253 | __bench_mem_routine(info, i, len, totallen); | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | for (i = 0; info->routines[i].name; i++) { | ||
258 | if (!strcmp(info->routines[i].name, routine)) | ||
259 | break; | ||
260 | } | ||
261 | if (!info->routines[i].name) { | ||
262 | printf("Unknown routine:%s\n", routine); | ||
263 | printf("Available routines...\n"); | ||
264 | for (i = 0; info->routines[i].name; i++) { | ||
265 | printf("\t%s ... %s\n", | ||
266 | info->routines[i].name, info->routines[i].desc); | ||
267 | } | ||
268 | return 1; | ||
269 | } | ||
270 | |||
271 | __bench_mem_routine(info, i, len, totallen); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static void memcpy_alloc_mem(void **dst, void **src, size_t length) | ||
277 | { | ||
278 | *dst = zalloc(length); | ||
279 | if (!*dst) | ||
280 | die("memory allocation failed - maybe length is too large?\n"); | ||
281 | |||
282 | *src = zalloc(length); | ||
283 | if (!*src) | ||
284 | die("memory allocation failed - maybe length is too large?\n"); | ||
285 | /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ | ||
286 | memset(*src, 0, length); | ||
287 | } | ||
288 | |||
289 | static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault) | ||
290 | { | ||
291 | u64 cycle_start = 0ULL, cycle_end = 0ULL; | ||
292 | void *src = NULL, *dst = NULL; | ||
293 | memcpy_t fn = r->fn.memcpy; | ||
294 | int i; | ||
295 | |||
296 | memcpy_alloc_mem(&dst, &src, len); | ||
297 | |||
298 | if (prefault) | ||
299 | fn(dst, src, len); | ||
300 | |||
301 | cycle_start = get_cycle(); | ||
302 | for (i = 0; i < iterations; ++i) | ||
303 | fn(dst, src, len); | ||
304 | cycle_end = get_cycle(); | ||
305 | |||
306 | free(src); | ||
307 | free(dst); | ||
308 | return cycle_end - cycle_start; | ||
309 | } | ||
310 | |||
311 | static double do_memcpy_gettimeofday(const struct routine *r, size_t len, | ||
312 | bool prefault) | ||
313 | { | ||
314 | struct timeval tv_start, tv_end, tv_diff; | ||
315 | memcpy_t fn = r->fn.memcpy; | ||
316 | void *src = NULL, *dst = NULL; | ||
317 | int i; | ||
318 | |||
319 | memcpy_alloc_mem(&dst, &src, len); | ||
320 | |||
321 | if (prefault) | ||
322 | fn(dst, src, len); | ||
323 | |||
324 | BUG_ON(gettimeofday(&tv_start, NULL)); | ||
325 | for (i = 0; i < iterations; ++i) | ||
326 | fn(dst, src, len); | ||
327 | BUG_ON(gettimeofday(&tv_end, NULL)); | ||
328 | |||
329 | timersub(&tv_end, &tv_start, &tv_diff); | ||
330 | |||
331 | free(src); | ||
332 | free(dst); | ||
333 | return (double)(((double)len * iterations) / timeval2double(&tv_diff)); | ||
334 | } | ||
335 | |||
336 | int bench_mem_memcpy(int argc, const char **argv, | ||
337 | const char *prefix __maybe_unused) | ||
338 | { | ||
339 | struct bench_mem_info info = { | ||
340 | .routines = memcpy_routines, | ||
341 | .do_cycle = do_memcpy_cycle, | ||
342 | .do_gettimeofday = do_memcpy_gettimeofday, | ||
343 | .usage = bench_mem_memcpy_usage, | ||
344 | }; | ||
345 | |||
346 | return bench_mem_common(argc, argv, prefix, &info); | ||
347 | } | ||
348 | |||
349 | static void memset_alloc_mem(void **dst, size_t length) | ||
350 | { | ||
351 | *dst = zalloc(length); | ||
352 | if (!*dst) | ||
353 | die("memory allocation failed - maybe length is too large?\n"); | ||
354 | } | ||
355 | |||
356 | static u64 do_memset_cycle(const struct routine *r, size_t len, bool prefault) | ||
357 | { | ||
358 | u64 cycle_start = 0ULL, cycle_end = 0ULL; | ||
359 | memset_t fn = r->fn.memset; | ||
360 | void *dst = NULL; | ||
361 | int i; | ||
362 | |||
363 | memset_alloc_mem(&dst, len); | ||
364 | |||
365 | if (prefault) | ||
366 | fn(dst, -1, len); | ||
367 | |||
368 | cycle_start = get_cycle(); | ||
369 | for (i = 0; i < iterations; ++i) | ||
370 | fn(dst, i, len); | ||
371 | cycle_end = get_cycle(); | ||
372 | |||
373 | free(dst); | ||
374 | return cycle_end - cycle_start; | ||
375 | } | ||
376 | |||
377 | static double do_memset_gettimeofday(const struct routine *r, size_t len, | ||
378 | bool prefault) | ||
379 | { | ||
380 | struct timeval tv_start, tv_end, tv_diff; | ||
381 | memset_t fn = r->fn.memset; | ||
382 | void *dst = NULL; | ||
383 | int i; | ||
384 | |||
385 | memset_alloc_mem(&dst, len); | ||
386 | |||
387 | if (prefault) | ||
388 | fn(dst, -1, len); | ||
389 | |||
390 | BUG_ON(gettimeofday(&tv_start, NULL)); | ||
391 | for (i = 0; i < iterations; ++i) | ||
392 | fn(dst, i, len); | ||
393 | BUG_ON(gettimeofday(&tv_end, NULL)); | ||
394 | |||
395 | timersub(&tv_end, &tv_start, &tv_diff); | ||
396 | |||
397 | free(dst); | ||
398 | return (double)(((double)len * iterations) / timeval2double(&tv_diff)); | ||
399 | } | ||
400 | |||
401 | static const char * const bench_mem_memset_usage[] = { | ||
402 | "perf bench mem memset <options>", | ||
403 | NULL | ||
404 | }; | ||
405 | |||
406 | static const struct routine memset_routines[] = { | ||
407 | { .name ="default", | ||
408 | .desc = "Default memset() provided by glibc", | ||
409 | .fn.memset = memset }, | ||
410 | #ifdef HAVE_ARCH_X86_64_SUPPORT | ||
411 | |||
412 | #define MEMSET_FN(_fn, _name, _desc) { .name = _name, .desc = _desc, .fn.memset = _fn }, | ||
413 | #include "mem-memset-x86-64-asm-def.h" | ||
414 | #undef MEMSET_FN | ||
415 | |||
416 | #endif | ||
417 | |||
418 | { .name = NULL, | ||
419 | .desc = NULL, | ||
420 | .fn.memset = NULL } | ||
421 | }; | ||
422 | |||
423 | int bench_mem_memset(int argc, const char **argv, | ||
424 | const char *prefix __maybe_unused) | ||
425 | { | ||
426 | struct bench_mem_info info = { | ||
427 | .routines = memset_routines, | ||
428 | .do_cycle = do_memset_cycle, | ||
429 | .do_gettimeofday = do_memset_gettimeofday, | ||
430 | .usage = bench_mem_memset_usage, | ||
431 | }; | ||
432 | |||
433 | return bench_mem_common(argc, argv, prefix, &info); | ||
434 | } | ||
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c index 870b7e665a20..492df2752a2d 100644 --- a/tools/perf/bench/numa.c +++ b/tools/perf/bench/numa.c | |||
@@ -164,8 +164,8 @@ static const struct option options[] = { | |||
164 | OPT_STRING('L', "mb_proc_locked", &p0.mb_proc_locked_str,"MB", "process serialized/locked memory access (MBs), <= process_memory"), | 164 | OPT_STRING('L', "mb_proc_locked", &p0.mb_proc_locked_str,"MB", "process serialized/locked memory access (MBs), <= process_memory"), |
165 | OPT_STRING('T', "mb_thread" , &p0.mb_thread_str, "MB", "thread memory (MBs)"), | 165 | OPT_STRING('T', "mb_thread" , &p0.mb_thread_str, "MB", "thread memory (MBs)"), |
166 | 166 | ||
167 | OPT_UINTEGER('l', "nr_loops" , &p0.nr_loops, "max number of loops to run"), | 167 | OPT_UINTEGER('l', "nr_loops" , &p0.nr_loops, "max number of loops to run (default: unlimited)"), |
168 | OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run"), | 168 | OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run (default: 5 secs)"), |
169 | OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"), | 169 | OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"), |
170 | 170 | ||
171 | OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via writes (can be mixed with -W)"), | 171 | OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via writes (can be mixed with -W)"), |
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c index d7f281c2828d..d4ff1b539cfd 100644 --- a/tools/perf/bench/sched-messaging.c +++ b/tools/perf/bench/sched-messaging.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #define DATASIZE 100 | 33 | #define DATASIZE 100 |
34 | 34 | ||
35 | static bool use_pipes = false; | 35 | static bool use_pipes = false; |
36 | static unsigned int loops = 100; | 36 | static unsigned int nr_loops = 100; |
37 | static bool thread_mode = false; | 37 | static bool thread_mode = false; |
38 | static unsigned int num_groups = 10; | 38 | static unsigned int num_groups = 10; |
39 | 39 | ||
@@ -79,7 +79,7 @@ static void ready(int ready_out, int wakefd) | |||
79 | err(EXIT_FAILURE, "poll"); | 79 | err(EXIT_FAILURE, "poll"); |
80 | } | 80 | } |
81 | 81 | ||
82 | /* Sender sprays loops messages down each file descriptor */ | 82 | /* Sender sprays nr_loops messages down each file descriptor */ |
83 | static void *sender(struct sender_context *ctx) | 83 | static void *sender(struct sender_context *ctx) |
84 | { | 84 | { |
85 | char data[DATASIZE]; | 85 | char data[DATASIZE]; |
@@ -88,7 +88,7 @@ static void *sender(struct sender_context *ctx) | |||
88 | ready(ctx->ready_out, ctx->wakefd); | 88 | ready(ctx->ready_out, ctx->wakefd); |
89 | 89 | ||
90 | /* Now pump to every receiver. */ | 90 | /* Now pump to every receiver. */ |
91 | for (i = 0; i < loops; i++) { | 91 | for (i = 0; i < nr_loops; i++) { |
92 | for (j = 0; j < ctx->num_fds; j++) { | 92 | for (j = 0; j < ctx->num_fds; j++) { |
93 | int ret, done = 0; | 93 | int ret, done = 0; |
94 | 94 | ||
@@ -213,7 +213,7 @@ static unsigned int group(pthread_t *pth, | |||
213 | /* Create the pipe between client and server */ | 213 | /* Create the pipe between client and server */ |
214 | fdpair(fds); | 214 | fdpair(fds); |
215 | 215 | ||
216 | ctx->num_packets = num_fds * loops; | 216 | ctx->num_packets = num_fds * nr_loops; |
217 | ctx->in_fds[0] = fds[0]; | 217 | ctx->in_fds[0] = fds[0]; |
218 | ctx->in_fds[1] = fds[1]; | 218 | ctx->in_fds[1] = fds[1]; |
219 | ctx->ready_out = ready_out; | 219 | ctx->ready_out = ready_out; |
@@ -250,7 +250,7 @@ static const struct option options[] = { | |||
250 | OPT_BOOLEAN('t', "thread", &thread_mode, | 250 | OPT_BOOLEAN('t', "thread", &thread_mode, |
251 | "Be multi thread instead of multi process"), | 251 | "Be multi thread instead of multi process"), |
252 | OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"), | 252 | OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"), |
253 | OPT_UINTEGER('l', "loop", &loops, "Specify number of loops"), | 253 | OPT_UINTEGER('l', "nr_loops", &nr_loops, "Specify the number of loops to run (default: 100)"), |
254 | OPT_END() | 254 | OPT_END() |
255 | }; | 255 | }; |
256 | 256 | ||
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 8edc205ff9a7..2bf9b3fd9e61 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -211,7 +211,7 @@ static int __cmd_annotate(struct perf_annotate *ann) | |||
211 | } | 211 | } |
212 | 212 | ||
213 | if (!objdump_path) { | 213 | if (!objdump_path) { |
214 | ret = perf_session_env__lookup_objdump(&session->header.env); | 214 | ret = perf_env__lookup_objdump(&session->header.env); |
215 | if (ret) | 215 | if (ret) |
216 | goto out; | 216 | goto out; |
217 | } | 217 | } |
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c index f67934d46d40..b17aed36ca16 100644 --- a/tools/perf/builtin-bench.c +++ b/tools/perf/builtin-bench.c | |||
@@ -36,7 +36,7 @@ struct bench { | |||
36 | #ifdef HAVE_LIBNUMA_SUPPORT | 36 | #ifdef HAVE_LIBNUMA_SUPPORT |
37 | static struct bench numa_benchmarks[] = { | 37 | static struct bench numa_benchmarks[] = { |
38 | { "mem", "Benchmark for NUMA workloads", bench_numa }, | 38 | { "mem", "Benchmark for NUMA workloads", bench_numa }, |
39 | { "all", "Test all NUMA benchmarks", NULL }, | 39 | { "all", "Run all NUMA benchmarks", NULL }, |
40 | { NULL, NULL, NULL } | 40 | { NULL, NULL, NULL } |
41 | }; | 41 | }; |
42 | #endif | 42 | #endif |
@@ -44,14 +44,14 @@ static struct bench numa_benchmarks[] = { | |||
44 | static struct bench sched_benchmarks[] = { | 44 | static struct bench sched_benchmarks[] = { |
45 | { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging }, | 45 | { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging }, |
46 | { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe }, | 46 | { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe }, |
47 | { "all", "Test all scheduler benchmarks", NULL }, | 47 | { "all", "Run all scheduler benchmarks", NULL }, |
48 | { NULL, NULL, NULL } | 48 | { NULL, NULL, NULL } |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static struct bench mem_benchmarks[] = { | 51 | static struct bench mem_benchmarks[] = { |
52 | { "memcpy", "Benchmark for memcpy()", bench_mem_memcpy }, | 52 | { "memcpy", "Benchmark for memcpy() functions", bench_mem_memcpy }, |
53 | { "memset", "Benchmark for memset() tests", bench_mem_memset }, | 53 | { "memset", "Benchmark for memset() functions", bench_mem_memset }, |
54 | { "all", "Test all memory benchmarks", NULL }, | 54 | { "all", "Run all memory access benchmarks", NULL }, |
55 | { NULL, NULL, NULL } | 55 | { NULL, NULL, NULL } |
56 | }; | 56 | }; |
57 | 57 | ||
@@ -62,7 +62,7 @@ static struct bench futex_benchmarks[] = { | |||
62 | { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue }, | 62 | { "requeue", "Benchmark for futex requeue calls", bench_futex_requeue }, |
63 | /* pi-futexes */ | 63 | /* pi-futexes */ |
64 | { "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi }, | 64 | { "lock-pi", "Benchmark for futex lock_pi calls", bench_futex_lock_pi }, |
65 | { "all", "Test all futex benchmarks", NULL }, | 65 | { "all", "Run all futex benchmarks", NULL }, |
66 | { NULL, NULL, NULL } | 66 | { NULL, NULL, NULL } |
67 | }; | 67 | }; |
68 | 68 | ||
@@ -110,7 +110,7 @@ int bench_format = BENCH_FORMAT_DEFAULT; | |||
110 | unsigned int bench_repeat = 10; /* default number of times to repeat the run */ | 110 | unsigned int bench_repeat = 10; /* default number of times to repeat the run */ |
111 | 111 | ||
112 | static const struct option bench_options[] = { | 112 | static const struct option bench_options[] = { |
113 | OPT_STRING('f', "format", &bench_format_str, "default", "Specify format style"), | 113 | OPT_STRING('f', "format", &bench_format_str, "default|simple", "Specify the output formatting style"), |
114 | OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify amount of times to repeat the run"), | 114 | OPT_UINTEGER('r', "repeat", &bench_repeat, "Specify amount of times to repeat the run"), |
115 | OPT_END() | 115 | OPT_END() |
116 | }; | 116 | }; |
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index 695ec5a50cf2..f4d62510acbb 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c | |||
@@ -61,8 +61,8 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) | |||
61 | usage_with_options(evlist_usage, options); | 61 | usage_with_options(evlist_usage, options); |
62 | 62 | ||
63 | if (details.event_group && (details.verbose || details.freq)) { | 63 | if (details.event_group && (details.verbose || details.freq)) { |
64 | pr_err("--group option is not compatible with other options\n"); | 64 | usage_with_options_msg(evlist_usage, options, |
65 | usage_with_options(evlist_usage, options); | 65 | "--group option is not compatible with other options\n"); |
66 | } | 66 | } |
67 | 67 | ||
68 | return __cmd_evlist(input_name, &details); | 68 | return __cmd_evlist(input_name, &details); |
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 36486eade1ef..a7d588bf3cdd 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c | |||
@@ -463,7 +463,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) | |||
463 | builtin_help_subcommands, builtin_help_usage, 0); | 463 | builtin_help_subcommands, builtin_help_usage, 0); |
464 | 464 | ||
465 | if (show_all) { | 465 | if (show_all) { |
466 | printf("\n usage: %s\n\n", perf_usage_string); | 466 | printf("\n Usage: %s\n\n", perf_usage_string); |
467 | list_commands("perf commands", &main_cmds, &other_cmds); | 467 | list_commands("perf commands", &main_cmds, &other_cmds); |
468 | printf(" %s\n\n", perf_more_info_string); | 468 | printf(" %s\n\n", perf_more_info_string); |
469 | return 0; | 469 | return 0; |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index f62c49b35be0..0a945d2e8ca5 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -28,9 +28,11 @@ struct perf_inject { | |||
28 | bool build_ids; | 28 | bool build_ids; |
29 | bool sched_stat; | 29 | bool sched_stat; |
30 | bool have_auxtrace; | 30 | bool have_auxtrace; |
31 | bool strip; | ||
31 | const char *input_name; | 32 | const char *input_name; |
32 | struct perf_data_file output; | 33 | struct perf_data_file output; |
33 | u64 bytes_written; | 34 | u64 bytes_written; |
35 | u64 aux_id; | ||
34 | struct list_head samples; | 36 | struct list_head samples; |
35 | struct itrace_synth_opts itrace_synth_opts; | 37 | struct itrace_synth_opts itrace_synth_opts; |
36 | }; | 38 | }; |
@@ -176,6 +178,27 @@ static int perf_event__repipe(struct perf_tool *tool, | |||
176 | return perf_event__repipe_synth(tool, event); | 178 | return perf_event__repipe_synth(tool, event); |
177 | } | 179 | } |
178 | 180 | ||
181 | static int perf_event__drop(struct perf_tool *tool __maybe_unused, | ||
182 | union perf_event *event __maybe_unused, | ||
183 | struct perf_sample *sample __maybe_unused, | ||
184 | struct machine *machine __maybe_unused) | ||
185 | { | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int perf_event__drop_aux(struct perf_tool *tool, | ||
190 | union perf_event *event __maybe_unused, | ||
191 | struct perf_sample *sample, | ||
192 | struct machine *machine __maybe_unused) | ||
193 | { | ||
194 | struct perf_inject *inject = container_of(tool, struct perf_inject, tool); | ||
195 | |||
196 | if (!inject->aux_id) | ||
197 | inject->aux_id = sample->id; | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
179 | typedef int (*inject_handler)(struct perf_tool *tool, | 202 | typedef int (*inject_handler)(struct perf_tool *tool, |
180 | union perf_event *event, | 203 | union perf_event *event, |
181 | struct perf_sample *sample, | 204 | struct perf_sample *sample, |
@@ -466,6 +489,78 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel, | |||
466 | return 0; | 489 | return 0; |
467 | } | 490 | } |
468 | 491 | ||
492 | static int drop_sample(struct perf_tool *tool __maybe_unused, | ||
493 | union perf_event *event __maybe_unused, | ||
494 | struct perf_sample *sample __maybe_unused, | ||
495 | struct perf_evsel *evsel __maybe_unused, | ||
496 | struct machine *machine __maybe_unused) | ||
497 | { | ||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | static void strip_init(struct perf_inject *inject) | ||
502 | { | ||
503 | struct perf_evlist *evlist = inject->session->evlist; | ||
504 | struct perf_evsel *evsel; | ||
505 | |||
506 | inject->tool.context_switch = perf_event__drop; | ||
507 | |||
508 | evlist__for_each(evlist, evsel) | ||
509 | evsel->handler = drop_sample; | ||
510 | } | ||
511 | |||
512 | static bool has_tracking(struct perf_evsel *evsel) | ||
513 | { | ||
514 | return evsel->attr.mmap || evsel->attr.mmap2 || evsel->attr.comm || | ||
515 | evsel->attr.task; | ||
516 | } | ||
517 | |||
518 | #define COMPAT_MASK (PERF_SAMPLE_ID | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | \ | ||
519 | PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER) | ||
520 | |||
521 | /* | ||
522 | * In order that the perf.data file is parsable, tracking events like MMAP need | ||
523 | * their selected event to exist, except if there is only 1 selected event left | ||
524 | * and it has a compatible sample type. | ||
525 | */ | ||
526 | static bool ok_to_remove(struct perf_evlist *evlist, | ||
527 | struct perf_evsel *evsel_to_remove) | ||
528 | { | ||
529 | struct perf_evsel *evsel; | ||
530 | int cnt = 0; | ||
531 | bool ok = false; | ||
532 | |||
533 | if (!has_tracking(evsel_to_remove)) | ||
534 | return true; | ||
535 | |||
536 | evlist__for_each(evlist, evsel) { | ||
537 | if (evsel->handler != drop_sample) { | ||
538 | cnt += 1; | ||
539 | if ((evsel->attr.sample_type & COMPAT_MASK) == | ||
540 | (evsel_to_remove->attr.sample_type & COMPAT_MASK)) | ||
541 | ok = true; | ||
542 | } | ||
543 | } | ||
544 | |||
545 | return ok && cnt == 1; | ||
546 | } | ||
547 | |||
548 | static void strip_fini(struct perf_inject *inject) | ||
549 | { | ||
550 | struct perf_evlist *evlist = inject->session->evlist; | ||
551 | struct perf_evsel *evsel, *tmp; | ||
552 | |||
553 | /* Remove non-synthesized evsels if possible */ | ||
554 | evlist__for_each_safe(evlist, tmp, evsel) { | ||
555 | if (evsel->handler == drop_sample && | ||
556 | ok_to_remove(evlist, evsel)) { | ||
557 | pr_debug("Deleting %s\n", perf_evsel__name(evsel)); | ||
558 | perf_evlist__remove(evlist, evsel); | ||
559 | perf_evsel__delete(evsel); | ||
560 | } | ||
561 | } | ||
562 | } | ||
563 | |||
469 | static int __cmd_inject(struct perf_inject *inject) | 564 | static int __cmd_inject(struct perf_inject *inject) |
470 | { | 565 | { |
471 | int ret = -EINVAL; | 566 | int ret = -EINVAL; |
@@ -512,10 +607,14 @@ static int __cmd_inject(struct perf_inject *inject) | |||
512 | inject->tool.id_index = perf_event__repipe_id_index; | 607 | inject->tool.id_index = perf_event__repipe_id_index; |
513 | inject->tool.auxtrace_info = perf_event__process_auxtrace_info; | 608 | inject->tool.auxtrace_info = perf_event__process_auxtrace_info; |
514 | inject->tool.auxtrace = perf_event__process_auxtrace; | 609 | inject->tool.auxtrace = perf_event__process_auxtrace; |
610 | inject->tool.aux = perf_event__drop_aux; | ||
611 | inject->tool.itrace_start = perf_event__drop_aux, | ||
515 | inject->tool.ordered_events = true; | 612 | inject->tool.ordered_events = true; |
516 | inject->tool.ordering_requires_timestamps = true; | 613 | inject->tool.ordering_requires_timestamps = true; |
517 | /* Allow space in the header for new attributes */ | 614 | /* Allow space in the header for new attributes */ |
518 | output_data_offset = 4096; | 615 | output_data_offset = 4096; |
616 | if (inject->strip) | ||
617 | strip_init(inject); | ||
519 | } | 618 | } |
520 | 619 | ||
521 | if (!inject->itrace_synth_opts.set) | 620 | if (!inject->itrace_synth_opts.set) |
@@ -535,11 +634,28 @@ static int __cmd_inject(struct perf_inject *inject) | |||
535 | } | 634 | } |
536 | /* | 635 | /* |
537 | * The AUX areas have been removed and replaced with | 636 | * The AUX areas have been removed and replaced with |
538 | * synthesized hardware events, so clear the feature flag. | 637 | * synthesized hardware events, so clear the feature flag and |
638 | * remove the evsel. | ||
539 | */ | 639 | */ |
540 | if (inject->itrace_synth_opts.set) | 640 | if (inject->itrace_synth_opts.set) { |
641 | struct perf_evsel *evsel; | ||
642 | |||
541 | perf_header__clear_feat(&session->header, | 643 | perf_header__clear_feat(&session->header, |
542 | HEADER_AUXTRACE); | 644 | HEADER_AUXTRACE); |
645 | if (inject->itrace_synth_opts.last_branch) | ||
646 | perf_header__set_feat(&session->header, | ||
647 | HEADER_BRANCH_STACK); | ||
648 | evsel = perf_evlist__id2evsel_strict(session->evlist, | ||
649 | inject->aux_id); | ||
650 | if (evsel) { | ||
651 | pr_debug("Deleting %s\n", | ||
652 | perf_evsel__name(evsel)); | ||
653 | perf_evlist__remove(session->evlist, evsel); | ||
654 | perf_evsel__delete(evsel); | ||
655 | } | ||
656 | if (inject->strip) | ||
657 | strip_fini(inject); | ||
658 | } | ||
543 | session->header.data_offset = output_data_offset; | 659 | session->header.data_offset = output_data_offset; |
544 | session->header.data_size = inject->bytes_written; | 660 | session->header.data_size = inject->bytes_written; |
545 | perf_session__write_header(session, session->evlist, fd, true); | 661 | perf_session__write_header(session, session->evlist, fd, true); |
@@ -604,6 +720,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
604 | OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, | 720 | OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, |
605 | NULL, "opts", "Instruction Tracing options", | 721 | NULL, "opts", "Instruction Tracing options", |
606 | itrace_parse_synth_opts), | 722 | itrace_parse_synth_opts), |
723 | OPT_BOOLEAN(0, "strip", &inject.strip, | ||
724 | "strip non-synthesized events (use with --itrace)"), | ||
607 | OPT_END() | 725 | OPT_END() |
608 | }; | 726 | }; |
609 | const char * const inject_usage[] = { | 727 | const char * const inject_usage[] = { |
@@ -619,6 +737,11 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
619 | if (argc) | 737 | if (argc) |
620 | usage_with_options(inject_usage, options); | 738 | usage_with_options(inject_usage, options); |
621 | 739 | ||
740 | if (inject.strip && !inject.itrace_synth_opts.set) { | ||
741 | pr_err("--strip option requires --itrace option\n"); | ||
742 | return -1; | ||
743 | } | ||
744 | |||
622 | if (perf_data_file__open(&inject.output)) { | 745 | if (perf_data_file__open(&inject.output)) { |
623 | perror("failed to create output file"); | 746 | perror("failed to create output file"); |
624 | return -1; | 747 | return -1; |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 23b1faaaa4cc..93ce665f976f 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -329,7 +329,7 @@ static int build_alloc_func_list(void) | |||
329 | return -EINVAL; | 329 | return -EINVAL; |
330 | } | 330 | } |
331 | 331 | ||
332 | kernel_map = machine->vmlinux_maps[MAP__FUNCTION]; | 332 | kernel_map = machine__kernel_map(machine); |
333 | if (map__load(kernel_map, NULL) < 0) { | 333 | if (map__load(kernel_map, NULL) < 0) { |
334 | pr_err("cannot load kernel map\n"); | 334 | pr_err("cannot load kernel map\n"); |
335 | return -ENOENT; | 335 | return -ENOENT; |
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index fc1cffb1b7a2..dd94b4ca2213 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include "util/parse-options.h" | 13 | #include "util/parse-options.h" |
14 | #include "util/trace-event.h" | 14 | #include "util/trace-event.h" |
15 | #include "util/debug.h" | 15 | #include "util/debug.h" |
16 | #include <api/fs/debugfs.h> | ||
17 | #include "util/tool.h" | 16 | #include "util/tool.h" |
18 | #include "util/stat.h" | 17 | #include "util/stat.h" |
19 | #include "util/top.h" | 18 | #include "util/top.h" |
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index af5bd0514108..bf679e2c978b 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c | |||
@@ -36,7 +36,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
36 | 36 | ||
37 | setup_pager(); | 37 | setup_pager(); |
38 | 38 | ||
39 | if (!raw_dump) | 39 | if (!raw_dump && pager_in_use()) |
40 | printf("\nList of pre-defined events (to be used in -e):\n\n"); | 40 | printf("\nList of pre-defined events (to be used in -e):\n\n"); |
41 | 41 | ||
42 | if (argc == 0) { | 42 | if (argc == 0) { |
@@ -45,6 +45,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
45 | } | 45 | } |
46 | 46 | ||
47 | for (i = 0; i < argc; ++i) { | 47 | for (i = 0; i < argc; ++i) { |
48 | char *sep, *s; | ||
49 | |||
48 | if (strcmp(argv[i], "tracepoint") == 0) | 50 | if (strcmp(argv[i], "tracepoint") == 0) |
49 | print_tracepoint_events(NULL, NULL, raw_dump); | 51 | print_tracepoint_events(NULL, NULL, raw_dump); |
50 | else if (strcmp(argv[i], "hw") == 0 || | 52 | else if (strcmp(argv[i], "hw") == 0 || |
@@ -60,8 +62,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
60 | print_hwcache_events(NULL, raw_dump); | 62 | print_hwcache_events(NULL, raw_dump); |
61 | else if (strcmp(argv[i], "pmu") == 0) | 63 | else if (strcmp(argv[i], "pmu") == 0) |
62 | print_pmu_events(NULL, raw_dump); | 64 | print_pmu_events(NULL, raw_dump); |
63 | else { | 65 | else if ((sep = strchr(argv[i], ':')) != NULL) { |
64 | char *sep = strchr(argv[i], ':'), *s; | ||
65 | int sep_idx; | 66 | int sep_idx; |
66 | 67 | ||
67 | if (sep == NULL) { | 68 | if (sep == NULL) { |
@@ -76,6 +77,19 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) | |||
76 | s[sep_idx] = '\0'; | 77 | s[sep_idx] = '\0'; |
77 | print_tracepoint_events(s, s + sep_idx + 1, raw_dump); | 78 | print_tracepoint_events(s, s + sep_idx + 1, raw_dump); |
78 | free(s); | 79 | free(s); |
80 | } else { | ||
81 | if (asprintf(&s, "*%s*", argv[i]) < 0) { | ||
82 | printf("Critical: Not enough memory! Trying to continue...\n"); | ||
83 | continue; | ||
84 | } | ||
85 | print_symbol_events(s, PERF_TYPE_HARDWARE, | ||
86 | event_symbols_hw, PERF_COUNT_HW_MAX, raw_dump); | ||
87 | print_symbol_events(s, PERF_TYPE_SOFTWARE, | ||
88 | event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump); | ||
89 | print_hwcache_events(s, raw_dump); | ||
90 | print_pmu_events(s, raw_dump); | ||
91 | print_tracepoint_events(NULL, s, raw_dump); | ||
92 | free(s); | ||
79 | } | 93 | } |
80 | } | 94 | } |
81 | return 0; | 95 | return 0; |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index b81cec33b4b2..132afc97676c 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -37,10 +37,10 @@ | |||
37 | #include "util/strfilter.h" | 37 | #include "util/strfilter.h" |
38 | #include "util/symbol.h" | 38 | #include "util/symbol.h" |
39 | #include "util/debug.h" | 39 | #include "util/debug.h" |
40 | #include <api/fs/debugfs.h> | ||
41 | #include "util/parse-options.h" | 40 | #include "util/parse-options.h" |
42 | #include "util/probe-finder.h" | 41 | #include "util/probe-finder.h" |
43 | #include "util/probe-event.h" | 42 | #include "util/probe-event.h" |
43 | #include "util/probe-file.h" | ||
44 | 44 | ||
45 | #define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" | 45 | #define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" |
46 | #define DEFAULT_FUNC_FILTER "!_*" | 46 | #define DEFAULT_FUNC_FILTER "!_*" |
@@ -182,10 +182,8 @@ static int opt_set_target(const struct option *opt, const char *str, | |||
182 | if (str) { | 182 | if (str) { |
183 | if (!strcmp(opt->long_name, "exec")) | 183 | if (!strcmp(opt->long_name, "exec")) |
184 | params.uprobes = true; | 184 | params.uprobes = true; |
185 | #ifdef HAVE_DWARF_SUPPORT | ||
186 | else if (!strcmp(opt->long_name, "module")) | 185 | else if (!strcmp(opt->long_name, "module")) |
187 | params.uprobes = false; | 186 | params.uprobes = false; |
188 | #endif | ||
189 | else | 187 | else |
190 | return ret; | 188 | return ret; |
191 | 189 | ||
@@ -311,6 +309,119 @@ static void pr_err_with_code(const char *msg, int err) | |||
311 | pr_err("\n"); | 309 | pr_err("\n"); |
312 | } | 310 | } |
313 | 311 | ||
312 | static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs) | ||
313 | { | ||
314 | int ret; | ||
315 | int i, k; | ||
316 | const char *event = NULL, *group = NULL; | ||
317 | |||
318 | ret = init_probe_symbol_maps(pevs->uprobes); | ||
319 | if (ret < 0) | ||
320 | return ret; | ||
321 | |||
322 | ret = convert_perf_probe_events(pevs, npevs); | ||
323 | if (ret < 0) | ||
324 | goto out_cleanup; | ||
325 | |||
326 | ret = apply_perf_probe_events(pevs, npevs); | ||
327 | if (ret < 0) | ||
328 | goto out_cleanup; | ||
329 | |||
330 | for (i = k = 0; i < npevs; i++) | ||
331 | k += pevs[i].ntevs; | ||
332 | |||
333 | pr_info("Added new event%s\n", (k > 1) ? "s:" : ":"); | ||
334 | for (i = 0; i < npevs; i++) { | ||
335 | struct perf_probe_event *pev = &pevs[i]; | ||
336 | |||
337 | for (k = 0; k < pev->ntevs; k++) { | ||
338 | struct probe_trace_event *tev = &pev->tevs[k]; | ||
339 | |||
340 | /* We use tev's name for showing new events */ | ||
341 | show_perf_probe_event(tev->group, tev->event, pev, | ||
342 | tev->point.module, false); | ||
343 | |||
344 | /* Save the last valid name */ | ||
345 | event = tev->event; | ||
346 | group = tev->group; | ||
347 | } | ||
348 | } | ||
349 | |||
350 | /* Note that it is possible to skip all events because of blacklist */ | ||
351 | if (event) { | ||
352 | /* Show how to use the event. */ | ||
353 | pr_info("\nYou can now use it in all perf tools, such as:\n\n"); | ||
354 | pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event); | ||
355 | } | ||
356 | |||
357 | out_cleanup: | ||
358 | cleanup_perf_probe_events(pevs, npevs); | ||
359 | exit_probe_symbol_maps(); | ||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | static int perf_del_probe_events(struct strfilter *filter) | ||
364 | { | ||
365 | int ret, ret2, ufd = -1, kfd = -1; | ||
366 | char *str = strfilter__string(filter); | ||
367 | struct strlist *klist = NULL, *ulist = NULL; | ||
368 | struct str_node *ent; | ||
369 | |||
370 | if (!str) | ||
371 | return -EINVAL; | ||
372 | |||
373 | pr_debug("Delete filter: \'%s\'\n", str); | ||
374 | |||
375 | /* Get current event names */ | ||
376 | ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); | ||
377 | if (ret < 0) | ||
378 | goto out; | ||
379 | |||
380 | klist = strlist__new(NULL, NULL); | ||
381 | ulist = strlist__new(NULL, NULL); | ||
382 | if (!klist || !ulist) { | ||
383 | ret = -ENOMEM; | ||
384 | goto out; | ||
385 | } | ||
386 | |||
387 | ret = probe_file__get_events(kfd, filter, klist); | ||
388 | if (ret == 0) { | ||
389 | strlist__for_each(ent, klist) | ||
390 | pr_info("Removed event: %s\n", ent->s); | ||
391 | |||
392 | ret = probe_file__del_strlist(kfd, klist); | ||
393 | if (ret < 0) | ||
394 | goto error; | ||
395 | } | ||
396 | |||
397 | ret2 = probe_file__get_events(ufd, filter, ulist); | ||
398 | if (ret2 == 0) { | ||
399 | strlist__for_each(ent, ulist) | ||
400 | pr_info("Removed event: %s\n", ent->s); | ||
401 | |||
402 | ret2 = probe_file__del_strlist(ufd, ulist); | ||
403 | if (ret2 < 0) | ||
404 | goto error; | ||
405 | } | ||
406 | |||
407 | if (ret == -ENOENT && ret2 == -ENOENT) | ||
408 | pr_debug("\"%s\" does not hit any event.\n", str); | ||
409 | /* Note that this is silently ignored */ | ||
410 | ret = 0; | ||
411 | |||
412 | error: | ||
413 | if (kfd >= 0) | ||
414 | close(kfd); | ||
415 | if (ufd >= 0) | ||
416 | close(ufd); | ||
417 | out: | ||
418 | strlist__delete(klist); | ||
419 | strlist__delete(ulist); | ||
420 | free(str); | ||
421 | |||
422 | return ret; | ||
423 | } | ||
424 | |||
314 | static int | 425 | static int |
315 | __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | 426 | __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) |
316 | { | 427 | { |
@@ -377,9 +488,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
377 | "file", "vmlinux pathname"), | 488 | "file", "vmlinux pathname"), |
378 | OPT_STRING('s', "source", &symbol_conf.source_prefix, | 489 | OPT_STRING('s', "source", &symbol_conf.source_prefix, |
379 | "directory", "path to kernel source"), | 490 | "directory", "path to kernel source"), |
380 | OPT_CALLBACK('m', "module", NULL, "modname|path", | ||
381 | "target module name (for online) or path (for offline)", | ||
382 | opt_set_target), | ||
383 | OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines, | 491 | OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines, |
384 | "Don't search inlined functions"), | 492 | "Don't search inlined functions"), |
385 | #endif | 493 | #endif |
@@ -396,6 +504,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
396 | opt_set_filter), | 504 | opt_set_filter), |
397 | OPT_CALLBACK('x', "exec", NULL, "executable|path", | 505 | OPT_CALLBACK('x', "exec", NULL, "executable|path", |
398 | "target executable name or path", opt_set_target), | 506 | "target executable name or path", opt_set_target), |
507 | OPT_CALLBACK('m', "module", NULL, "modname|path", | ||
508 | "target module name (for online) or path (for offline)", | ||
509 | opt_set_target), | ||
399 | OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, | 510 | OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, |
400 | "Enable symbol demangling"), | 511 | "Enable symbol demangling"), |
401 | OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, | 512 | OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, |
@@ -417,12 +528,12 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
417 | PARSE_OPT_STOP_AT_NON_OPTION); | 528 | PARSE_OPT_STOP_AT_NON_OPTION); |
418 | if (argc > 0) { | 529 | if (argc > 0) { |
419 | if (strcmp(argv[0], "-") == 0) { | 530 | if (strcmp(argv[0], "-") == 0) { |
420 | pr_warning(" Error: '-' is not supported.\n"); | 531 | usage_with_options_msg(probe_usage, options, |
421 | usage_with_options(probe_usage, options); | 532 | "'-' is not supported.\n"); |
422 | } | 533 | } |
423 | if (params.command && params.command != 'a') { | 534 | if (params.command && params.command != 'a') { |
424 | pr_warning(" Error: another command except --add is set.\n"); | 535 | usage_with_options_msg(probe_usage, options, |
425 | usage_with_options(probe_usage, options); | 536 | "another command except --add is set.\n"); |
426 | } | 537 | } |
427 | ret = parse_probe_event_argv(argc, argv); | 538 | ret = parse_probe_event_argv(argc, argv); |
428 | if (ret < 0) { | 539 | if (ret < 0) { |
@@ -451,8 +562,10 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
451 | switch (params.command) { | 562 | switch (params.command) { |
452 | case 'l': | 563 | case 'l': |
453 | if (params.uprobes) { | 564 | if (params.uprobes) { |
454 | pr_warning(" Error: Don't use --list with --exec.\n"); | 565 | pr_err(" Error: Don't use --list with --exec.\n"); |
455 | usage_with_options(probe_usage, options); | 566 | parse_options_usage(probe_usage, options, "l", true); |
567 | parse_options_usage(NULL, options, "x", true); | ||
568 | return -EINVAL; | ||
456 | } | 569 | } |
457 | ret = show_perf_probe_events(params.filter); | 570 | ret = show_perf_probe_events(params.filter); |
458 | if (ret < 0) | 571 | if (ret < 0) |
@@ -483,7 +596,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
483 | return ret; | 596 | return ret; |
484 | #endif | 597 | #endif |
485 | case 'd': | 598 | case 'd': |
486 | ret = del_perf_probe_events(params.filter); | 599 | ret = perf_del_probe_events(params.filter); |
487 | if (ret < 0) { | 600 | if (ret < 0) { |
488 | pr_err_with_code(" Error: Failed to delete events.", ret); | 601 | pr_err_with_code(" Error: Failed to delete events.", ret); |
489 | return ret; | 602 | return ret; |
@@ -492,11 +605,13 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
492 | case 'a': | 605 | case 'a': |
493 | /* Ensure the last given target is used */ | 606 | /* Ensure the last given target is used */ |
494 | if (params.target && !params.target_used) { | 607 | if (params.target && !params.target_used) { |
495 | pr_warning(" Error: -x/-m must follow the probe definitions.\n"); | 608 | pr_err(" Error: -x/-m must follow the probe definitions.\n"); |
496 | usage_with_options(probe_usage, options); | 609 | parse_options_usage(probe_usage, options, "m", true); |
610 | parse_options_usage(NULL, options, "x", true); | ||
611 | return -EINVAL; | ||
497 | } | 612 | } |
498 | 613 | ||
499 | ret = add_perf_probe_events(params.events, params.nevents); | 614 | ret = perf_add_probe_events(params.events, params.nevents); |
500 | if (ret < 0) { | 615 | if (ret < 0) { |
501 | pr_err_with_code(" Error: Failed to add events.", ret); | 616 | pr_err_with_code(" Error: Failed to add events.", ret); |
502 | return ret; | 617 | return ret; |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 142eeb341b29..199fc31e3919 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "util/auxtrace.h" | 31 | #include "util/auxtrace.h" |
32 | #include "util/parse-branch-options.h" | 32 | #include "util/parse-branch-options.h" |
33 | #include "util/parse-regs-options.h" | 33 | #include "util/parse-regs-options.h" |
34 | #include "util/llvm-utils.h" | ||
34 | 35 | ||
35 | #include <unistd.h> | 36 | #include <unistd.h> |
36 | #include <sched.h> | 37 | #include <sched.h> |
@@ -49,7 +50,7 @@ struct record { | |||
49 | int realtime_prio; | 50 | int realtime_prio; |
50 | bool no_buildid; | 51 | bool no_buildid; |
51 | bool no_buildid_cache; | 52 | bool no_buildid_cache; |
52 | long samples; | 53 | unsigned long long samples; |
53 | }; | 54 | }; |
54 | 55 | ||
55 | static int record__write(struct record *rec, void *bf, size_t size) | 56 | static int record__write(struct record *rec, void *bf, size_t size) |
@@ -636,8 +637,29 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
636 | /* | 637 | /* |
637 | * Let the child rip | 638 | * Let the child rip |
638 | */ | 639 | */ |
639 | if (forks) | 640 | if (forks) { |
641 | union perf_event *event; | ||
642 | |||
643 | event = malloc(sizeof(event->comm) + machine->id_hdr_size); | ||
644 | if (event == NULL) { | ||
645 | err = -ENOMEM; | ||
646 | goto out_child; | ||
647 | } | ||
648 | |||
649 | /* | ||
650 | * Some H/W events are generated before COMM event | ||
651 | * which is emitted during exec(), so perf script | ||
652 | * cannot see a correct process name for those events. | ||
653 | * Synthesize COMM event to prevent it. | ||
654 | */ | ||
655 | perf_event__synthesize_comm(tool, event, | ||
656 | rec->evlist->workload.pid, | ||
657 | process_synthesized_event, | ||
658 | machine); | ||
659 | free(event); | ||
660 | |||
640 | perf_evlist__start_workload(rec->evlist); | 661 | perf_evlist__start_workload(rec->evlist); |
662 | } | ||
641 | 663 | ||
642 | if (opts->initial_delay) { | 664 | if (opts->initial_delay) { |
643 | usleep(opts->initial_delay * 1000); | 665 | usleep(opts->initial_delay * 1000); |
@@ -646,7 +668,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
646 | 668 | ||
647 | auxtrace_snapshot_enabled = 1; | 669 | auxtrace_snapshot_enabled = 1; |
648 | for (;;) { | 670 | for (;;) { |
649 | int hits = rec->samples; | 671 | unsigned long long hits = rec->samples; |
650 | 672 | ||
651 | if (record__mmap_read_all(rec) < 0) { | 673 | if (record__mmap_read_all(rec) < 0) { |
652 | auxtrace_snapshot_enabled = 0; | 674 | auxtrace_snapshot_enabled = 0; |
@@ -989,13 +1011,8 @@ static struct record record = { | |||
989 | }, | 1011 | }, |
990 | }; | 1012 | }; |
991 | 1013 | ||
992 | #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " | 1014 | const char record_callchain_help[] = CALLCHAIN_RECORD_HELP |
993 | 1015 | "\n\t\t\t\tDefault: fp"; | |
994 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
995 | const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr"; | ||
996 | #else | ||
997 | const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr"; | ||
998 | #endif | ||
999 | 1016 | ||
1000 | /* | 1017 | /* |
1001 | * XXX Will stay a global variable till we fix builtin-script.c to stop messing | 1018 | * XXX Will stay a global variable till we fix builtin-script.c to stop messing |
@@ -1043,7 +1060,7 @@ struct option __record_options[] = { | |||
1043 | NULL, "enables call-graph recording" , | 1060 | NULL, "enables call-graph recording" , |
1044 | &record_callchain_opt), | 1061 | &record_callchain_opt), |
1045 | OPT_CALLBACK(0, "call-graph", &record.opts, | 1062 | OPT_CALLBACK(0, "call-graph", &record.opts, |
1046 | "mode[,dump_size]", record_callchain_help, | 1063 | "record_mode[,record_size]", record_callchain_help, |
1047 | &record_parse_callchain_opt), | 1064 | &record_parse_callchain_opt), |
1048 | OPT_INCR('v', "verbose", &verbose, | 1065 | OPT_INCR('v', "verbose", &verbose, |
1049 | "be more verbose (show counter open errors, etc)"), | 1066 | "be more verbose (show counter open errors, etc)"), |
@@ -1096,6 +1113,12 @@ struct option __record_options[] = { | |||
1096 | "per thread proc mmap processing timeout in ms"), | 1113 | "per thread proc mmap processing timeout in ms"), |
1097 | OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, | 1114 | OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, |
1098 | "Record context switch events"), | 1115 | "Record context switch events"), |
1116 | #ifdef HAVE_LIBBPF_SUPPORT | ||
1117 | OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path", | ||
1118 | "clang binary to use for compiling BPF scriptlets"), | ||
1119 | OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options", | ||
1120 | "options passed to clang when compiling BPF scriptlets"), | ||
1121 | #endif | ||
1099 | OPT_END() | 1122 | OPT_END() |
1100 | }; | 1123 | }; |
1101 | 1124 | ||
@@ -1119,14 +1142,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1119 | usage_with_options(record_usage, record_options); | 1142 | usage_with_options(record_usage, record_options); |
1120 | 1143 | ||
1121 | if (nr_cgroups && !rec->opts.target.system_wide) { | 1144 | if (nr_cgroups && !rec->opts.target.system_wide) { |
1122 | ui__error("cgroup monitoring only available in" | 1145 | usage_with_options_msg(record_usage, record_options, |
1123 | " system-wide mode\n"); | 1146 | "cgroup monitoring only available in system-wide mode"); |
1124 | usage_with_options(record_usage, record_options); | 1147 | |
1125 | } | 1148 | } |
1126 | if (rec->opts.record_switch_events && | 1149 | if (rec->opts.record_switch_events && |
1127 | !perf_can_record_switch_events()) { | 1150 | !perf_can_record_switch_events()) { |
1128 | ui__error("kernel does not support recording context switch events (--switch-events option)\n"); | 1151 | ui__error("kernel does not support recording context switch events\n"); |
1129 | usage_with_options(record_usage, record_options); | 1152 | parse_options_usage(record_usage, record_options, "switch-events", 0); |
1153 | return -EINVAL; | ||
1130 | } | 1154 | } |
1131 | 1155 | ||
1132 | if (!rec->itr) { | 1156 | if (!rec->itr) { |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 62b285e32aa5..2853ad2bd435 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -62,6 +62,7 @@ struct report { | |||
62 | float min_percent; | 62 | float min_percent; |
63 | u64 nr_entries; | 63 | u64 nr_entries; |
64 | u64 queue_size; | 64 | u64 queue_size; |
65 | int socket_filter; | ||
65 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 66 | DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); |
66 | }; | 67 | }; |
67 | 68 | ||
@@ -162,14 +163,21 @@ static int process_sample_event(struct perf_tool *tool, | |||
162 | if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) | 163 | if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap)) |
163 | goto out_put; | 164 | goto out_put; |
164 | 165 | ||
165 | if (sort__mode == SORT_MODE__BRANCH) | 166 | if (sort__mode == SORT_MODE__BRANCH) { |
167 | /* | ||
168 | * A non-synthesized event might not have a branch stack if | ||
169 | * branch stacks have been synthesized (using itrace options). | ||
170 | */ | ||
171 | if (!sample->branch_stack) | ||
172 | goto out_put; | ||
166 | iter.ops = &hist_iter_branch; | 173 | iter.ops = &hist_iter_branch; |
167 | else if (rep->mem_mode) | 174 | } else if (rep->mem_mode) { |
168 | iter.ops = &hist_iter_mem; | 175 | iter.ops = &hist_iter_mem; |
169 | else if (symbol_conf.cumulate_callchain) | 176 | } else if (symbol_conf.cumulate_callchain) { |
170 | iter.ops = &hist_iter_cumulative; | 177 | iter.ops = &hist_iter_cumulative; |
171 | else | 178 | } else { |
172 | iter.ops = &hist_iter_normal; | 179 | iter.ops = &hist_iter_normal; |
180 | } | ||
173 | 181 | ||
174 | if (al.map != NULL) | 182 | if (al.map != NULL) |
175 | al.map->dso->hit = 1; | 183 | al.map->dso->hit = 1; |
@@ -213,6 +221,15 @@ static int report__setup_sample_type(struct report *rep) | |||
213 | u64 sample_type = perf_evlist__combined_sample_type(session->evlist); | 221 | u64 sample_type = perf_evlist__combined_sample_type(session->evlist); |
214 | bool is_pipe = perf_data_file__is_pipe(session->file); | 222 | bool is_pipe = perf_data_file__is_pipe(session->file); |
215 | 223 | ||
224 | if (session->itrace_synth_opts->callchain || | ||
225 | (!is_pipe && | ||
226 | perf_header__has_feat(&session->header, HEADER_AUXTRACE) && | ||
227 | !session->itrace_synth_opts->set)) | ||
228 | sample_type |= PERF_SAMPLE_CALLCHAIN; | ||
229 | |||
230 | if (session->itrace_synth_opts->last_branch) | ||
231 | sample_type |= PERF_SAMPLE_BRANCH_STACK; | ||
232 | |||
216 | if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { | 233 | if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { |
217 | if (sort__has_parent) { | 234 | if (sort__has_parent) { |
218 | ui__error("Selected --sort parent, but no " | 235 | ui__error("Selected --sort parent, but no " |
@@ -286,6 +303,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report | |||
286 | struct perf_evsel *evsel = hists_to_evsel(hists); | 303 | struct perf_evsel *evsel = hists_to_evsel(hists); |
287 | char buf[512]; | 304 | char buf[512]; |
288 | size_t size = sizeof(buf); | 305 | size_t size = sizeof(buf); |
306 | int socked_id = hists->socket_filter; | ||
289 | 307 | ||
290 | if (symbol_conf.filter_relative) { | 308 | if (symbol_conf.filter_relative) { |
291 | nr_samples = hists->stats.nr_non_filtered_samples; | 309 | nr_samples = hists->stats.nr_non_filtered_samples; |
@@ -326,6 +344,10 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report | |||
326 | ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order); | 344 | ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order); |
327 | } else | 345 | } else |
328 | ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events); | 346 | ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events); |
347 | |||
348 | if (socked_id > -1) | ||
349 | ret += fprintf(fp, "\n# Processor Socket: %d", socked_id); | ||
350 | |||
329 | return ret + fprintf(fp, "\n#\n"); | 351 | return ret + fprintf(fp, "\n#\n"); |
330 | } | 352 | } |
331 | 353 | ||
@@ -365,7 +387,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, | |||
365 | 387 | ||
366 | static void report__warn_kptr_restrict(const struct report *rep) | 388 | static void report__warn_kptr_restrict(const struct report *rep) |
367 | { | 389 | { |
368 | struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION]; | 390 | struct map *kernel_map = machine__kernel_map(&rep->session->machines.host); |
369 | struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL; | 391 | struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL; |
370 | 392 | ||
371 | if (kernel_map == NULL || | 393 | if (kernel_map == NULL || |
@@ -450,6 +472,8 @@ static void report__collapse_hists(struct report *rep) | |||
450 | if (pos->idx == 0) | 472 | if (pos->idx == 0) |
451 | hists->symbol_filter_str = rep->symbol_filter_str; | 473 | hists->symbol_filter_str = rep->symbol_filter_str; |
452 | 474 | ||
475 | hists->socket_filter = rep->socket_filter; | ||
476 | |||
453 | hists__collapse_resort(hists, &prog); | 477 | hists__collapse_resort(hists, &prog); |
454 | 478 | ||
455 | /* Non-group events are considered as leader */ | 479 | /* Non-group events are considered as leader */ |
@@ -601,6 +625,12 @@ parse_percent_limit(const struct option *opt, const char *str, | |||
601 | return 0; | 625 | return 0; |
602 | } | 626 | } |
603 | 627 | ||
628 | #define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function" | ||
629 | |||
630 | const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n" | ||
631 | CALLCHAIN_REPORT_HELP | ||
632 | "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT; | ||
633 | |||
604 | int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | 634 | int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) |
605 | { | 635 | { |
606 | struct perf_session *session; | 636 | struct perf_session *session; |
@@ -609,7 +639,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
609 | bool has_br_stack = false; | 639 | bool has_br_stack = false; |
610 | int branch_mode = -1; | 640 | int branch_mode = -1; |
611 | bool branch_call_mode = false; | 641 | bool branch_call_mode = false; |
612 | char callchain_default_opt[] = "fractal,0.5,callee"; | 642 | char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; |
613 | const char * const report_usage[] = { | 643 | const char * const report_usage[] = { |
614 | "perf report [<options>]", | 644 | "perf report [<options>]", |
615 | NULL | 645 | NULL |
@@ -635,6 +665,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
635 | }, | 665 | }, |
636 | .max_stack = PERF_MAX_STACK_DEPTH, | 666 | .max_stack = PERF_MAX_STACK_DEPTH, |
637 | .pretty_printing_style = "normal", | 667 | .pretty_printing_style = "normal", |
668 | .socket_filter = -1, | ||
638 | }; | 669 | }; |
639 | const struct option options[] = { | 670 | const struct option options[] = { |
640 | OPT_STRING('i', "input", &input_name, "file", | 671 | OPT_STRING('i', "input", &input_name, "file", |
@@ -668,15 +699,18 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
668 | " Please refer the man page for the complete list."), | 699 | " Please refer the man page for the complete list."), |
669 | OPT_STRING('F', "fields", &field_order, "key[,keys...]", | 700 | OPT_STRING('F', "fields", &field_order, "key[,keys...]", |
670 | "output field(s): overhead, period, sample plus all of sort keys"), | 701 | "output field(s): overhead, period, sample plus all of sort keys"), |
671 | OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, | 702 | OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization, |
672 | "Show sample percentage for different cpu modes"), | 703 | "Show sample percentage for different cpu modes"), |
704 | OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, | ||
705 | "Show sample percentage for different cpu modes", PARSE_OPT_HIDDEN), | ||
673 | OPT_STRING('p', "parent", &parent_pattern, "regex", | 706 | OPT_STRING('p', "parent", &parent_pattern, "regex", |
674 | "regex filter to identify parent, see: '--sort parent'"), | 707 | "regex filter to identify parent, see: '--sort parent'"), |
675 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, | 708 | OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, |
676 | "Only display entries with parent-match"), | 709 | "Only display entries with parent-match"), |
677 | OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]", | 710 | OPT_CALLBACK_DEFAULT('g', "call-graph", &report, |
678 | "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. " | 711 | "print_type,threshold[,print_limit],order,sort_key[,branch]", |
679 | "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt), | 712 | report_callchain_help, &report_parse_callchain_opt, |
713 | callchain_default_opt), | ||
680 | OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, | 714 | OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, |
681 | "Accumulate callchains of children and show total overhead as well"), | 715 | "Accumulate callchains of children and show total overhead as well"), |
682 | OPT_INTEGER(0, "max-stack", &report.max_stack, | 716 | OPT_INTEGER(0, "max-stack", &report.max_stack, |
@@ -747,6 +781,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
747 | "Show full source file name path for source lines"), | 781 | "Show full source file name path for source lines"), |
748 | OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph, | 782 | OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph, |
749 | "Show callgraph from reference event"), | 783 | "Show callgraph from reference event"), |
784 | OPT_INTEGER(0, "socket-filter", &report.socket_filter, | ||
785 | "only show processor socket that match with this filter"), | ||
750 | OPT_END() | 786 | OPT_END() |
751 | }; | 787 | }; |
752 | struct perf_data_file file = { | 788 | struct perf_data_file file = { |
@@ -781,6 +817,12 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
781 | 817 | ||
782 | if (report.inverted_callchain) | 818 | if (report.inverted_callchain) |
783 | callchain_param.order = ORDER_CALLER; | 819 | callchain_param.order = ORDER_CALLER; |
820 | if (symbol_conf.cumulate_callchain && !callchain_param.order_set) | ||
821 | callchain_param.order = ORDER_CALLER; | ||
822 | |||
823 | if (itrace_synth_opts.callchain && | ||
824 | (int)itrace_synth_opts.callchain_sz > report.max_stack) | ||
825 | report.max_stack = itrace_synth_opts.callchain_sz; | ||
784 | 826 | ||
785 | if (!input_name || !strlen(input_name)) { | 827 | if (!input_name || !strlen(input_name)) { |
786 | if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) | 828 | if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) |
@@ -809,6 +851,9 @@ repeat: | |||
809 | has_br_stack = perf_header__has_feat(&session->header, | 851 | has_br_stack = perf_header__has_feat(&session->header, |
810 | HEADER_BRANCH_STACK); | 852 | HEADER_BRANCH_STACK); |
811 | 853 | ||
854 | if (itrace_synth_opts.last_branch) | ||
855 | has_br_stack = true; | ||
856 | |||
812 | /* | 857 | /* |
813 | * Branch mode is a tristate: | 858 | * Branch mode is a tristate: |
814 | * -1 means default, so decide based on the file having branch data. | 859 | * -1 means default, so decide based on the file having branch data. |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 33962612a5e9..0ee6d900e100 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -1728,8 +1728,8 @@ static void setup_sorting(struct perf_sched *sched, const struct option *options | |||
1728 | for (tok = strtok_r(str, ", ", &tmp); | 1728 | for (tok = strtok_r(str, ", ", &tmp); |
1729 | tok; tok = strtok_r(NULL, ", ", &tmp)) { | 1729 | tok; tok = strtok_r(NULL, ", ", &tmp)) { |
1730 | if (sort_dimension__add(tok, &sched->sort_list) < 0) { | 1730 | if (sort_dimension__add(tok, &sched->sort_list) < 0) { |
1731 | error("Unknown --sort key: `%s'", tok); | 1731 | usage_with_options_msg(usage_msg, options, |
1732 | usage_with_options(usage_msg, options); | 1732 | "Unknown --sort key: `%s'", tok); |
1733 | } | 1733 | } |
1734 | } | 1734 | } |
1735 | 1735 | ||
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index eb51325e8ad9..72b5deb4bd79 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -29,9 +29,12 @@ static bool no_callchain; | |||
29 | static bool latency_format; | 29 | static bool latency_format; |
30 | static bool system_wide; | 30 | static bool system_wide; |
31 | static bool print_flags; | 31 | static bool print_flags; |
32 | static bool nanosecs; | ||
32 | static const char *cpu_list; | 33 | static const char *cpu_list; |
33 | static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 34 | static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); |
34 | 35 | ||
36 | unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; | ||
37 | |||
35 | enum perf_output_field { | 38 | enum perf_output_field { |
36 | PERF_OUTPUT_COMM = 1U << 0, | 39 | PERF_OUTPUT_COMM = 1U << 0, |
37 | PERF_OUTPUT_TID = 1U << 1, | 40 | PERF_OUTPUT_TID = 1U << 1, |
@@ -48,6 +51,8 @@ enum perf_output_field { | |||
48 | PERF_OUTPUT_SRCLINE = 1U << 12, | 51 | PERF_OUTPUT_SRCLINE = 1U << 12, |
49 | PERF_OUTPUT_PERIOD = 1U << 13, | 52 | PERF_OUTPUT_PERIOD = 1U << 13, |
50 | PERF_OUTPUT_IREGS = 1U << 14, | 53 | PERF_OUTPUT_IREGS = 1U << 14, |
54 | PERF_OUTPUT_BRSTACK = 1U << 15, | ||
55 | PERF_OUTPUT_BRSTACKSYM = 1U << 16, | ||
51 | }; | 56 | }; |
52 | 57 | ||
53 | struct output_option { | 58 | struct output_option { |
@@ -69,6 +74,8 @@ struct output_option { | |||
69 | {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, | 74 | {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, |
70 | {.str = "period", .field = PERF_OUTPUT_PERIOD}, | 75 | {.str = "period", .field = PERF_OUTPUT_PERIOD}, |
71 | {.str = "iregs", .field = PERF_OUTPUT_IREGS}, | 76 | {.str = "iregs", .field = PERF_OUTPUT_IREGS}, |
77 | {.str = "brstack", .field = PERF_OUTPUT_BRSTACK}, | ||
78 | {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM}, | ||
72 | }; | 79 | }; |
73 | 80 | ||
74 | /* default set to maintain compatibility with current format */ | 81 | /* default set to maintain compatibility with current format */ |
@@ -415,10 +422,84 @@ static void print_sample_start(struct perf_sample *sample, | |||
415 | secs = nsecs / NSECS_PER_SEC; | 422 | secs = nsecs / NSECS_PER_SEC; |
416 | nsecs -= secs * NSECS_PER_SEC; | 423 | nsecs -= secs * NSECS_PER_SEC; |
417 | usecs = nsecs / NSECS_PER_USEC; | 424 | usecs = nsecs / NSECS_PER_USEC; |
418 | printf("%5lu.%06lu: ", secs, usecs); | 425 | if (nanosecs) |
426 | printf("%5lu.%09llu: ", secs, nsecs); | ||
427 | else | ||
428 | printf("%5lu.%06lu: ", secs, usecs); | ||
419 | } | 429 | } |
420 | } | 430 | } |
421 | 431 | ||
432 | static inline char | ||
433 | mispred_str(struct branch_entry *br) | ||
434 | { | ||
435 | if (!(br->flags.mispred || br->flags.predicted)) | ||
436 | return '-'; | ||
437 | |||
438 | return br->flags.predicted ? 'P' : 'M'; | ||
439 | } | ||
440 | |||
441 | static void print_sample_brstack(union perf_event *event __maybe_unused, | ||
442 | struct perf_sample *sample, | ||
443 | struct thread *thread __maybe_unused, | ||
444 | struct perf_event_attr *attr __maybe_unused) | ||
445 | { | ||
446 | struct branch_stack *br = sample->branch_stack; | ||
447 | u64 i; | ||
448 | |||
449 | if (!(br && br->nr)) | ||
450 | return; | ||
451 | |||
452 | for (i = 0; i < br->nr; i++) { | ||
453 | printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ", | ||
454 | br->entries[i].from, | ||
455 | br->entries[i].to, | ||
456 | mispred_str( br->entries + i), | ||
457 | br->entries[i].flags.in_tx? 'X' : '-', | ||
458 | br->entries[i].flags.abort? 'A' : '-', | ||
459 | br->entries[i].flags.cycles); | ||
460 | } | ||
461 | } | ||
462 | |||
463 | static void print_sample_brstacksym(union perf_event *event __maybe_unused, | ||
464 | struct perf_sample *sample, | ||
465 | struct thread *thread __maybe_unused, | ||
466 | struct perf_event_attr *attr __maybe_unused) | ||
467 | { | ||
468 | struct branch_stack *br = sample->branch_stack; | ||
469 | struct addr_location alf, alt; | ||
470 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
471 | u64 i, from, to; | ||
472 | |||
473 | if (!(br && br->nr)) | ||
474 | return; | ||
475 | |||
476 | for (i = 0; i < br->nr; i++) { | ||
477 | |||
478 | memset(&alf, 0, sizeof(alf)); | ||
479 | memset(&alt, 0, sizeof(alt)); | ||
480 | from = br->entries[i].from; | ||
481 | to = br->entries[i].to; | ||
482 | |||
483 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, from, &alf); | ||
484 | if (alf.map) | ||
485 | alf.sym = map__find_symbol(alf.map, alf.addr, NULL); | ||
486 | |||
487 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, to, &alt); | ||
488 | if (alt.map) | ||
489 | alt.sym = map__find_symbol(alt.map, alt.addr, NULL); | ||
490 | |||
491 | symbol__fprintf_symname_offs(alf.sym, &alf, stdout); | ||
492 | putchar('/'); | ||
493 | symbol__fprintf_symname_offs(alt.sym, &alt, stdout); | ||
494 | printf("/%c/%c/%c/%d ", | ||
495 | mispred_str( br->entries + i), | ||
496 | br->entries[i].flags.in_tx? 'X' : '-', | ||
497 | br->entries[i].flags.abort? 'A' : '-', | ||
498 | br->entries[i].flags.cycles); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | |||
422 | static void print_sample_addr(union perf_event *event, | 503 | static void print_sample_addr(union perf_event *event, |
423 | struct perf_sample *sample, | 504 | struct perf_sample *sample, |
424 | struct thread *thread, | 505 | struct thread *thread, |
@@ -471,7 +552,7 @@ static void print_sample_bts(union perf_event *event, | |||
471 | } | 552 | } |
472 | } | 553 | } |
473 | perf_evsel__print_ip(evsel, sample, al, print_opts, | 554 | perf_evsel__print_ip(evsel, sample, al, print_opts, |
474 | PERF_MAX_STACK_DEPTH); | 555 | scripting_max_stack); |
475 | } | 556 | } |
476 | 557 | ||
477 | /* print branch_to information */ | 558 | /* print branch_to information */ |
@@ -548,12 +629,17 @@ static void process_event(union perf_event *event, struct perf_sample *sample, | |||
548 | 629 | ||
549 | perf_evsel__print_ip(evsel, sample, al, | 630 | perf_evsel__print_ip(evsel, sample, al, |
550 | output[attr->type].print_ip_opts, | 631 | output[attr->type].print_ip_opts, |
551 | PERF_MAX_STACK_DEPTH); | 632 | scripting_max_stack); |
552 | } | 633 | } |
553 | 634 | ||
554 | if (PRINT_FIELD(IREGS)) | 635 | if (PRINT_FIELD(IREGS)) |
555 | print_sample_iregs(event, sample, thread, attr); | 636 | print_sample_iregs(event, sample, thread, attr); |
556 | 637 | ||
638 | if (PRINT_FIELD(BRSTACK)) | ||
639 | print_sample_brstack(event, sample, thread, attr); | ||
640 | else if (PRINT_FIELD(BRSTACKSYM)) | ||
641 | print_sample_brstacksym(event, sample, thread, attr); | ||
642 | |||
557 | printf("\n"); | 643 | printf("\n"); |
558 | } | 644 | } |
559 | 645 | ||
@@ -680,7 +766,10 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, | |||
680 | 766 | ||
681 | set_print_ip_opts(&evsel->attr); | 767 | set_print_ip_opts(&evsel->attr); |
682 | 768 | ||
683 | return perf_evsel__check_attr(evsel, scr->session); | 769 | if (evsel->attr.sample_type) |
770 | err = perf_evsel__check_attr(evsel, scr->session); | ||
771 | |||
772 | return err; | ||
684 | } | 773 | } |
685 | 774 | ||
686 | static int process_comm_event(struct perf_tool *tool, | 775 | static int process_comm_event(struct perf_tool *tool, |
@@ -768,8 +857,8 @@ static int process_exit_event(struct perf_tool *tool, | |||
768 | if (!evsel->attr.sample_id_all) { | 857 | if (!evsel->attr.sample_id_all) { |
769 | sample->cpu = 0; | 858 | sample->cpu = 0; |
770 | sample->time = 0; | 859 | sample->time = 0; |
771 | sample->tid = event->comm.tid; | 860 | sample->tid = event->fork.tid; |
772 | sample->pid = event->comm.pid; | 861 | sample->pid = event->fork.pid; |
773 | } | 862 | } |
774 | print_sample_start(sample, thread, evsel); | 863 | print_sample_start(sample, thread, evsel); |
775 | perf_event__fprintf(event, stdout); | 864 | perf_event__fprintf(event, stdout); |
@@ -1672,7 +1761,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1672 | "comma separated output fields prepend with 'type:'. " | 1761 | "comma separated output fields prepend with 'type:'. " |
1673 | "Valid types: hw,sw,trace,raw. " | 1762 | "Valid types: hw,sw,trace,raw. " |
1674 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," | 1763 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," |
1675 | "addr,symoff,period,iregs,flags", parse_output_fields), | 1764 | "addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields), |
1676 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 1765 | OPT_BOOLEAN('a', "all-cpus", &system_wide, |
1677 | "system-wide collection from all CPUs"), | 1766 | "system-wide collection from all CPUs"), |
1678 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", | 1767 | OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", |
@@ -1695,6 +1784,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1695 | OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events, | 1784 | OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events, |
1696 | "Show context switch events (if recorded)"), | 1785 | "Show context switch events (if recorded)"), |
1697 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), | 1786 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), |
1787 | OPT_BOOLEAN(0, "ns", &nanosecs, | ||
1788 | "Use 9 decimal places when displaying time"), | ||
1698 | OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", | 1789 | OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts", |
1699 | "Instruction Tracing options", | 1790 | "Instruction Tracing options", |
1700 | itrace_parse_synth_opts), | 1791 | itrace_parse_synth_opts), |
@@ -1740,6 +1831,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1740 | } | 1831 | } |
1741 | } | 1832 | } |
1742 | 1833 | ||
1834 | if (itrace_synth_opts.callchain && | ||
1835 | itrace_synth_opts.callchain_sz > scripting_max_stack) | ||
1836 | scripting_max_stack = itrace_synth_opts.callchain_sz; | ||
1837 | |||
1743 | /* make sure PERF_EXEC_PATH is set for scripts */ | 1838 | /* make sure PERF_EXEC_PATH is set for scripts */ |
1744 | perf_set_argv_exec_path(perf_exec_path()); | 1839 | perf_set_argv_exec_path(perf_exec_path()); |
1745 | 1840 | ||
@@ -1752,9 +1847,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1752 | rep_script_path = get_script_path(argv[0], REPORT_SUFFIX); | 1847 | rep_script_path = get_script_path(argv[0], REPORT_SUFFIX); |
1753 | 1848 | ||
1754 | if (!rec_script_path && !rep_script_path) { | 1849 | if (!rec_script_path && !rep_script_path) { |
1755 | fprintf(stderr, " Couldn't find script %s\n\n See perf" | 1850 | usage_with_options_msg(script_usage, options, |
1851 | "Couldn't find script `%s'\n\n See perf" | ||
1756 | " script -l for available scripts.\n", argv[0]); | 1852 | " script -l for available scripts.\n", argv[0]); |
1757 | usage_with_options(script_usage, options); | ||
1758 | } | 1853 | } |
1759 | 1854 | ||
1760 | if (is_top_script(argv[0])) { | 1855 | if (is_top_script(argv[0])) { |
@@ -1765,10 +1860,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1765 | rep_args = has_required_arg(rep_script_path); | 1860 | rep_args = has_required_arg(rep_script_path); |
1766 | rec_args = (argc - 1) - rep_args; | 1861 | rec_args = (argc - 1) - rep_args; |
1767 | if (rec_args < 0) { | 1862 | if (rec_args < 0) { |
1768 | fprintf(stderr, " %s script requires options." | 1863 | usage_with_options_msg(script_usage, options, |
1864 | "`%s' script requires options." | ||
1769 | "\n\n See perf script -l for available " | 1865 | "\n\n See perf script -l for available " |
1770 | "scripts and options.\n", argv[0]); | 1866 | "scripts and options.\n", argv[0]); |
1771 | usage_with_options(script_usage, options); | ||
1772 | } | 1867 | } |
1773 | } | 1868 | } |
1774 | 1869 | ||
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index d46dbb1bc65d..2f438f76cceb 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -100,6 +100,8 @@ static struct target target = { | |||
100 | .uid = UINT_MAX, | 100 | .uid = UINT_MAX, |
101 | }; | 101 | }; |
102 | 102 | ||
103 | typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu); | ||
104 | |||
103 | static int run_count = 1; | 105 | static int run_count = 1; |
104 | static bool no_inherit = false; | 106 | static bool no_inherit = false; |
105 | static volatile pid_t child_pid = -1; | 107 | static volatile pid_t child_pid = -1; |
@@ -119,7 +121,7 @@ static unsigned int unit_width = 4; /* strlen("unit") */ | |||
119 | static bool forever = false; | 121 | static bool forever = false; |
120 | static struct timespec ref_time; | 122 | static struct timespec ref_time; |
121 | static struct cpu_map *aggr_map; | 123 | static struct cpu_map *aggr_map; |
122 | static int (*aggr_get_id)(struct cpu_map *m, int cpu); | 124 | static aggr_get_id_t aggr_get_id; |
123 | 125 | ||
124 | static volatile int done = 0; | 126 | static volatile int done = 0; |
125 | 127 | ||
@@ -215,7 +217,7 @@ static void read_counters(bool close_counters) | |||
215 | 217 | ||
216 | evlist__for_each(evsel_list, counter) { | 218 | evlist__for_each(evsel_list, counter) { |
217 | if (read_counter(counter)) | 219 | if (read_counter(counter)) |
218 | pr_warning("failed to read counter %s\n", counter->name); | 220 | pr_debug("failed to read counter %s\n", counter->name); |
219 | 221 | ||
220 | if (perf_stat_process_counter(&stat_config, counter)) | 222 | if (perf_stat_process_counter(&stat_config, counter)) |
221 | pr_warning("failed to process counter %s\n", counter->name); | 223 | pr_warning("failed to process counter %s\n", counter->name); |
@@ -434,7 +436,7 @@ static void print_noise_pct(double total, double avg) | |||
434 | 436 | ||
435 | static void print_noise(struct perf_evsel *evsel, double avg) | 437 | static void print_noise(struct perf_evsel *evsel, double avg) |
436 | { | 438 | { |
437 | struct perf_stat *ps; | 439 | struct perf_stat_evsel *ps; |
438 | 440 | ||
439 | if (run_count == 1) | 441 | if (run_count == 1) |
440 | return; | 442 | return; |
@@ -479,6 +481,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr) | |||
479 | csv_sep); | 481 | csv_sep); |
480 | break; | 482 | break; |
481 | case AGGR_GLOBAL: | 483 | case AGGR_GLOBAL: |
484 | case AGGR_UNSET: | ||
482 | default: | 485 | default: |
483 | break; | 486 | break; |
484 | } | 487 | } |
@@ -671,7 +674,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix) | |||
671 | static void print_counter_aggr(struct perf_evsel *counter, char *prefix) | 674 | static void print_counter_aggr(struct perf_evsel *counter, char *prefix) |
672 | { | 675 | { |
673 | FILE *output = stat_config.output; | 676 | FILE *output = stat_config.output; |
674 | struct perf_stat *ps = counter->priv; | 677 | struct perf_stat_evsel *ps = counter->priv; |
675 | double avg = avg_stats(&ps->res_stats[0]); | 678 | double avg = avg_stats(&ps->res_stats[0]); |
676 | int scaled = counter->counts->scaled; | 679 | int scaled = counter->counts->scaled; |
677 | double uval; | 680 | double uval; |
@@ -799,6 +802,8 @@ static void print_interval(char *prefix, struct timespec *ts) | |||
799 | case AGGR_GLOBAL: | 802 | case AGGR_GLOBAL: |
800 | default: | 803 | default: |
801 | fprintf(output, "# time counts %*s events\n", unit_width, "unit"); | 804 | fprintf(output, "# time counts %*s events\n", unit_width, "unit"); |
805 | case AGGR_UNSET: | ||
806 | break; | ||
802 | } | 807 | } |
803 | } | 808 | } |
804 | 809 | ||
@@ -880,6 +885,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) | |||
880 | evlist__for_each(evsel_list, counter) | 885 | evlist__for_each(evsel_list, counter) |
881 | print_counter(counter, prefix); | 886 | print_counter(counter, prefix); |
882 | break; | 887 | break; |
888 | case AGGR_UNSET: | ||
883 | default: | 889 | default: |
884 | break; | 890 | break; |
885 | } | 891 | } |
@@ -940,30 +946,90 @@ static int stat__set_big_num(const struct option *opt __maybe_unused, | |||
940 | return 0; | 946 | return 0; |
941 | } | 947 | } |
942 | 948 | ||
949 | static int perf_stat__get_socket(struct cpu_map *map, int cpu) | ||
950 | { | ||
951 | return cpu_map__get_socket(map, cpu, NULL); | ||
952 | } | ||
953 | |||
954 | static int perf_stat__get_core(struct cpu_map *map, int cpu) | ||
955 | { | ||
956 | return cpu_map__get_core(map, cpu, NULL); | ||
957 | } | ||
958 | |||
959 | static int cpu_map__get_max(struct cpu_map *map) | ||
960 | { | ||
961 | int i, max = -1; | ||
962 | |||
963 | for (i = 0; i < map->nr; i++) { | ||
964 | if (map->map[i] > max) | ||
965 | max = map->map[i]; | ||
966 | } | ||
967 | |||
968 | return max; | ||
969 | } | ||
970 | |||
971 | static struct cpu_map *cpus_aggr_map; | ||
972 | |||
973 | static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx) | ||
974 | { | ||
975 | int cpu; | ||
976 | |||
977 | if (idx >= map->nr) | ||
978 | return -1; | ||
979 | |||
980 | cpu = map->map[idx]; | ||
981 | |||
982 | if (cpus_aggr_map->map[cpu] == -1) | ||
983 | cpus_aggr_map->map[cpu] = get_id(map, idx); | ||
984 | |||
985 | return cpus_aggr_map->map[cpu]; | ||
986 | } | ||
987 | |||
988 | static int perf_stat__get_socket_cached(struct cpu_map *map, int idx) | ||
989 | { | ||
990 | return perf_stat__get_aggr(perf_stat__get_socket, map, idx); | ||
991 | } | ||
992 | |||
993 | static int perf_stat__get_core_cached(struct cpu_map *map, int idx) | ||
994 | { | ||
995 | return perf_stat__get_aggr(perf_stat__get_core, map, idx); | ||
996 | } | ||
997 | |||
943 | static int perf_stat_init_aggr_mode(void) | 998 | static int perf_stat_init_aggr_mode(void) |
944 | { | 999 | { |
1000 | int nr; | ||
1001 | |||
945 | switch (stat_config.aggr_mode) { | 1002 | switch (stat_config.aggr_mode) { |
946 | case AGGR_SOCKET: | 1003 | case AGGR_SOCKET: |
947 | if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { | 1004 | if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { |
948 | perror("cannot build socket map"); | 1005 | perror("cannot build socket map"); |
949 | return -1; | 1006 | return -1; |
950 | } | 1007 | } |
951 | aggr_get_id = cpu_map__get_socket; | 1008 | aggr_get_id = perf_stat__get_socket_cached; |
952 | break; | 1009 | break; |
953 | case AGGR_CORE: | 1010 | case AGGR_CORE: |
954 | if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { | 1011 | if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { |
955 | perror("cannot build core map"); | 1012 | perror("cannot build core map"); |
956 | return -1; | 1013 | return -1; |
957 | } | 1014 | } |
958 | aggr_get_id = cpu_map__get_core; | 1015 | aggr_get_id = perf_stat__get_core_cached; |
959 | break; | 1016 | break; |
960 | case AGGR_NONE: | 1017 | case AGGR_NONE: |
961 | case AGGR_GLOBAL: | 1018 | case AGGR_GLOBAL: |
962 | case AGGR_THREAD: | 1019 | case AGGR_THREAD: |
1020 | case AGGR_UNSET: | ||
963 | default: | 1021 | default: |
964 | break; | 1022 | break; |
965 | } | 1023 | } |
966 | return 0; | 1024 | |
1025 | /* | ||
1026 | * The evsel_list->cpus is the base we operate on, | ||
1027 | * taking the highest cpu number to be the size of | ||
1028 | * the aggregation translate cpumap. | ||
1029 | */ | ||
1030 | nr = cpu_map__get_max(evsel_list->cpus); | ||
1031 | cpus_aggr_map = cpu_map__empty_new(nr + 1); | ||
1032 | return cpus_aggr_map ? 0 : -ENOMEM; | ||
967 | } | 1033 | } |
968 | 1034 | ||
969 | /* | 1035 | /* |
@@ -1179,7 +1245,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1179 | OPT_STRING(0, "post", &post_cmd, "command", | 1245 | OPT_STRING(0, "post", &post_cmd, "command", |
1180 | "command to run after to the measured command"), | 1246 | "command to run after to the measured command"), |
1181 | OPT_UINTEGER('I', "interval-print", &stat_config.interval, | 1247 | OPT_UINTEGER('I', "interval-print", &stat_config.interval, |
1182 | "print counts at regular interval in ms (>= 100)"), | 1248 | "print counts at regular interval in ms (>= 10)"), |
1183 | OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode, | 1249 | OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode, |
1184 | "aggregate counts per processor socket", AGGR_SOCKET), | 1250 | "aggregate counts per processor socket", AGGR_SOCKET), |
1185 | OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode, | 1251 | OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode, |
@@ -1332,9 +1398,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1332 | thread_map__read_comms(evsel_list->threads); | 1398 | thread_map__read_comms(evsel_list->threads); |
1333 | 1399 | ||
1334 | if (interval && interval < 100) { | 1400 | if (interval && interval < 100) { |
1335 | pr_err("print interval must be >= 100ms\n"); | 1401 | if (interval < 10) { |
1336 | parse_options_usage(stat_usage, options, "I", 1); | 1402 | pr_err("print interval must be >= 10ms\n"); |
1337 | goto out; | 1403 | parse_options_usage(stat_usage, options, "I", 1); |
1404 | goto out; | ||
1405 | } else | ||
1406 | pr_warning("print interval < 100ms. " | ||
1407 | "The overhead percentage could be high in some cases. " | ||
1408 | "Please proceed with caution.\n"); | ||
1338 | } | 1409 | } |
1339 | 1410 | ||
1340 | if (perf_evlist__alloc_stats(evsel_list, interval)) | 1411 | if (perf_evlist__alloc_stats(evsel_list, interval)) |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 8c465c83aabf..7e2e72e6d9d1 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -655,7 +655,7 @@ static int symbol_filter(struct map *map, struct symbol *sym) | |||
655 | { | 655 | { |
656 | const char *name = sym->name; | 656 | const char *name = sym->name; |
657 | 657 | ||
658 | if (!map->dso->kernel) | 658 | if (!__map__is_kernel(map)) |
659 | return 0; | 659 | return 0; |
660 | /* | 660 | /* |
661 | * ppc64 uses function descriptors and appends a '.' to the | 661 | * ppc64 uses function descriptors and appends a '.' to the |
@@ -857,9 +857,12 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) | |||
857 | * TODO: we don't process guest user from host side | 857 | * TODO: we don't process guest user from host side |
858 | * except simple counting. | 858 | * except simple counting. |
859 | */ | 859 | */ |
860 | /* Fall thru */ | ||
861 | default: | ||
862 | goto next_event; | 860 | goto next_event; |
861 | default: | ||
862 | if (event->header.type == PERF_RECORD_SAMPLE) | ||
863 | goto next_event; | ||
864 | machine = &session->machines.host; | ||
865 | break; | ||
863 | } | 866 | } |
864 | 867 | ||
865 | 868 | ||
@@ -952,7 +955,7 @@ static int __cmd_top(struct perf_top *top) | |||
952 | machines__set_symbol_filter(&top->session->machines, symbol_filter); | 955 | machines__set_symbol_filter(&top->session->machines, symbol_filter); |
953 | 956 | ||
954 | if (!objdump_path) { | 957 | if (!objdump_path) { |
955 | ret = perf_session_env__lookup_objdump(&top->session->header.env); | 958 | ret = perf_env__lookup_objdump(&top->session->header.env); |
956 | if (ret) | 959 | if (ret) |
957 | goto out_delete; | 960 | goto out_delete; |
958 | } | 961 | } |
@@ -961,8 +964,18 @@ static int __cmd_top(struct perf_top *top) | |||
961 | if (ret) | 964 | if (ret) |
962 | goto out_delete; | 965 | goto out_delete; |
963 | 966 | ||
967 | if (perf_session__register_idle_thread(top->session) == NULL) | ||
968 | goto out_delete; | ||
969 | |||
964 | machine__synthesize_threads(&top->session->machines.host, &opts->target, | 970 | machine__synthesize_threads(&top->session->machines.host, &opts->target, |
965 | top->evlist->threads, false, opts->proc_map_timeout); | 971 | top->evlist->threads, false, opts->proc_map_timeout); |
972 | |||
973 | if (sort__has_socket) { | ||
974 | ret = perf_env__read_cpu_topology_map(&perf_env); | ||
975 | if (ret < 0) | ||
976 | goto out_err_cpu_topo; | ||
977 | } | ||
978 | |||
966 | ret = perf_top__start_counters(top); | 979 | ret = perf_top__start_counters(top); |
967 | if (ret) | 980 | if (ret) |
968 | goto out_delete; | 981 | goto out_delete; |
@@ -1020,6 +1033,14 @@ out_delete: | |||
1020 | top->session = NULL; | 1033 | top->session = NULL; |
1021 | 1034 | ||
1022 | return ret; | 1035 | return ret; |
1036 | |||
1037 | out_err_cpu_topo: { | ||
1038 | char errbuf[BUFSIZ]; | ||
1039 | const char *err = strerror_r(-ret, errbuf, sizeof(errbuf)); | ||
1040 | |||
1041 | ui__error("Could not read the CPU topology map: %s\n", err); | ||
1042 | goto out_delete; | ||
1043 | } | ||
1023 | } | 1044 | } |
1024 | 1045 | ||
1025 | static int | 1046 | static int |
@@ -1032,8 +1053,22 @@ callchain_opt(const struct option *opt, const char *arg, int unset) | |||
1032 | static int | 1053 | static int |
1033 | parse_callchain_opt(const struct option *opt, const char *arg, int unset) | 1054 | parse_callchain_opt(const struct option *opt, const char *arg, int unset) |
1034 | { | 1055 | { |
1035 | symbol_conf.use_callchain = true; | 1056 | struct record_opts *record = (struct record_opts *)opt->value; |
1036 | return record_parse_callchain_opt(opt, arg, unset); | 1057 | |
1058 | record->callgraph_set = true; | ||
1059 | callchain_param.enabled = !unset; | ||
1060 | callchain_param.record_mode = CALLCHAIN_FP; | ||
1061 | |||
1062 | /* | ||
1063 | * --no-call-graph | ||
1064 | */ | ||
1065 | if (unset) { | ||
1066 | symbol_conf.use_callchain = false; | ||
1067 | callchain_param.record_mode = CALLCHAIN_NONE; | ||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | return parse_callchain_top_opt(arg); | ||
1037 | } | 1072 | } |
1038 | 1073 | ||
1039 | static int perf_top_config(const char *var, const char *value, void *cb) | 1074 | static int perf_top_config(const char *var, const char *value, void *cb) |
@@ -1058,6 +1093,9 @@ parse_percent_limit(const struct option *opt, const char *arg, | |||
1058 | return 0; | 1093 | return 0; |
1059 | } | 1094 | } |
1060 | 1095 | ||
1096 | const char top_callchain_help[] = CALLCHAIN_RECORD_HELP CALLCHAIN_REPORT_HELP | ||
1097 | "\n\t\t\t\tDefault: fp,graph,0.5,caller,function"; | ||
1098 | |||
1061 | int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | 1099 | int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) |
1062 | { | 1100 | { |
1063 | char errbuf[BUFSIZ]; | 1101 | char errbuf[BUFSIZ]; |
@@ -1133,11 +1171,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1133 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, | 1171 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, |
1134 | "Show a column with the number of samples"), | 1172 | "Show a column with the number of samples"), |
1135 | OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts, | 1173 | OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts, |
1136 | NULL, "enables call-graph recording", | 1174 | NULL, "enables call-graph recording and display", |
1137 | &callchain_opt), | 1175 | &callchain_opt), |
1138 | OPT_CALLBACK(0, "call-graph", &top.record_opts, | 1176 | OPT_CALLBACK(0, "call-graph", &top.record_opts, |
1139 | "mode[,dump_size]", record_callchain_help, | 1177 | "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]", |
1140 | &parse_callchain_opt), | 1178 | top_callchain_help, &parse_callchain_opt), |
1141 | OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, | 1179 | OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, |
1142 | "Accumulate callchains of children and show total overhead as well"), | 1180 | "Accumulate callchains of children and show total overhead as well"), |
1143 | OPT_INTEGER(0, "max-stack", &top.max_stack, | 1181 | OPT_INTEGER(0, "max-stack", &top.max_stack, |
@@ -1267,6 +1305,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1267 | perf_hpp__cancel_cumulate(); | 1305 | perf_hpp__cancel_cumulate(); |
1268 | } | 1306 | } |
1269 | 1307 | ||
1308 | if (symbol_conf.cumulate_callchain && !callchain_param.order_set) | ||
1309 | callchain_param.order = ORDER_CALLER; | ||
1310 | |||
1270 | symbol_conf.priv_size = sizeof(struct annotation); | 1311 | symbol_conf.priv_size = sizeof(struct annotation); |
1271 | 1312 | ||
1272 | symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); | 1313 | symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 4e3abba03062..c783d8fd3a80 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <traceevent/event-parse.h> | 19 | #include <traceevent/event-parse.h> |
20 | #include <api/fs/tracing_path.h> | ||
20 | #include "builtin.h" | 21 | #include "builtin.h" |
21 | #include "util/color.h" | 22 | #include "util/color.h" |
22 | #include "util/debug.h" | 23 | #include "util/debug.h" |
@@ -37,6 +38,7 @@ | |||
37 | #include <stdlib.h> | 38 | #include <stdlib.h> |
38 | #include <sys/mman.h> | 39 | #include <sys/mman.h> |
39 | #include <linux/futex.h> | 40 | #include <linux/futex.h> |
41 | #include <linux/err.h> | ||
40 | 42 | ||
41 | /* For older distros: */ | 43 | /* For older distros: */ |
42 | #ifndef MAP_STACK | 44 | #ifndef MAP_STACK |
@@ -244,13 +246,14 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void | |||
244 | struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); | 246 | struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); |
245 | 247 | ||
246 | /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */ | 248 | /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */ |
247 | if (evsel == NULL) | 249 | if (IS_ERR(evsel)) |
248 | evsel = perf_evsel__newtp("syscalls", direction); | 250 | evsel = perf_evsel__newtp("syscalls", direction); |
249 | 251 | ||
250 | if (evsel) { | 252 | if (IS_ERR(evsel)) |
251 | if (perf_evsel__init_syscall_tp(evsel, handler)) | 253 | return NULL; |
252 | goto out_delete; | 254 | |
253 | } | 255 | if (perf_evsel__init_syscall_tp(evsel, handler)) |
256 | goto out_delete; | ||
254 | 257 | ||
255 | return evsel; | 258 | return evsel; |
256 | 259 | ||
@@ -582,6 +585,12 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct sysc | |||
582 | 585 | ||
583 | #define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op | 586 | #define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op |
584 | 587 | ||
588 | static const char *bpf_cmd[] = { | ||
589 | "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM", | ||
590 | "MAP_GET_NEXT_KEY", "PROG_LOAD", | ||
591 | }; | ||
592 | static DEFINE_STRARRAY(bpf_cmd); | ||
593 | |||
585 | static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", }; | 594 | static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", }; |
586 | static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1); | 595 | static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1); |
587 | 596 | ||
@@ -1008,6 +1017,7 @@ static struct syscall_fmt { | |||
1008 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ | 1017 | .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ |
1009 | [1] = SCA_ACCMODE, /* mode */ }, }, | 1018 | [1] = SCA_ACCMODE, /* mode */ }, }, |
1010 | { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, | 1019 | { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, |
1020 | { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, | ||
1011 | { .name = "brk", .hexret = true, | 1021 | { .name = "brk", .hexret = true, |
1012 | .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, | 1022 | .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, |
1013 | { .name = "chdir", .errmsg = true, | 1023 | { .name = "chdir", .errmsg = true, |
@@ -1704,12 +1714,12 @@ static int trace__read_syscall_info(struct trace *trace, int id) | |||
1704 | snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); | 1714 | snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); |
1705 | sc->tp_format = trace_event__tp_format("syscalls", tp_name); | 1715 | sc->tp_format = trace_event__tp_format("syscalls", tp_name); |
1706 | 1716 | ||
1707 | if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) { | 1717 | if (IS_ERR(sc->tp_format) && sc->fmt && sc->fmt->alias) { |
1708 | snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias); | 1718 | snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias); |
1709 | sc->tp_format = trace_event__tp_format("syscalls", tp_name); | 1719 | sc->tp_format = trace_event__tp_format("syscalls", tp_name); |
1710 | } | 1720 | } |
1711 | 1721 | ||
1712 | if (sc->tp_format == NULL) | 1722 | if (IS_ERR(sc->tp_format)) |
1713 | return -1; | 1723 | return -1; |
1714 | 1724 | ||
1715 | sc->args = sc->tp_format->format.fields; | 1725 | sc->args = sc->tp_format->format.fields; |
@@ -2389,7 +2399,8 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp); | |||
2389 | static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) | 2399 | static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) |
2390 | { | 2400 | { |
2391 | struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname"); | 2401 | struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname"); |
2392 | if (evsel == NULL) | 2402 | |
2403 | if (IS_ERR(evsel)) | ||
2393 | return false; | 2404 | return false; |
2394 | 2405 | ||
2395 | if (perf_evsel__field(evsel, "pathname") == NULL) { | 2406 | if (perf_evsel__field(evsel, "pathname") == NULL) { |
@@ -2686,11 +2697,11 @@ out_delete_evlist: | |||
2686 | char errbuf[BUFSIZ]; | 2697 | char errbuf[BUFSIZ]; |
2687 | 2698 | ||
2688 | out_error_sched_stat_runtime: | 2699 | out_error_sched_stat_runtime: |
2689 | debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime"); | 2700 | tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "sched", "sched_stat_runtime"); |
2690 | goto out_error; | 2701 | goto out_error; |
2691 | 2702 | ||
2692 | out_error_raw_syscalls: | 2703 | out_error_raw_syscalls: |
2693 | debugfs__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)"); | 2704 | tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "raw_syscalls", "sys_(enter|exit)"); |
2694 | goto out_error; | 2705 | goto out_error; |
2695 | 2706 | ||
2696 | out_error_mmap: | 2707 | out_error_mmap: |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 827557fc7511..de89ec574361 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -106,9 +106,14 @@ ifdef LIBBABELTRACE | |||
106 | FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf | 106 | FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf |
107 | endif | 107 | endif |
108 | 108 | ||
109 | FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi | ||
109 | # include ARCH specific config | 110 | # include ARCH specific config |
110 | -include $(src-perf)/arch/$(ARCH)/Makefile | 111 | -include $(src-perf)/arch/$(ARCH)/Makefile |
111 | 112 | ||
113 | ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET | ||
114 | CFLAGS += -DHAVE_ARCH_REGS_QUERY_REGISTER_OFFSET | ||
115 | endif | ||
116 | |||
112 | include $(src-perf)/config/utilities.mak | 117 | include $(src-perf)/config/utilities.mak |
113 | 118 | ||
114 | ifeq ($(call get-executable,$(FLEX)),) | 119 | ifeq ($(call get-executable,$(FLEX)),) |
@@ -233,6 +238,7 @@ ifdef NO_LIBELF | |||
233 | NO_DEMANGLE := 1 | 238 | NO_DEMANGLE := 1 |
234 | NO_LIBUNWIND := 1 | 239 | NO_LIBUNWIND := 1 |
235 | NO_LIBDW_DWARF_UNWIND := 1 | 240 | NO_LIBDW_DWARF_UNWIND := 1 |
241 | NO_LIBBPF := 1 | ||
236 | else | 242 | else |
237 | ifeq ($(feature-libelf), 0) | 243 | ifeq ($(feature-libelf), 0) |
238 | ifeq ($(feature-glibc), 1) | 244 | ifeq ($(feature-glibc), 1) |
@@ -242,13 +248,14 @@ else | |||
242 | LIBC_SUPPORT := 1 | 248 | LIBC_SUPPORT := 1 |
243 | endif | 249 | endif |
244 | ifeq ($(LIBC_SUPPORT),1) | 250 | ifeq ($(LIBC_SUPPORT),1) |
245 | msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev); | 251 | msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install elfutils-libelf-devel/libelf-dev); |
246 | 252 | ||
247 | NO_LIBELF := 1 | 253 | NO_LIBELF := 1 |
248 | NO_DWARF := 1 | 254 | NO_DWARF := 1 |
249 | NO_DEMANGLE := 1 | 255 | NO_DEMANGLE := 1 |
250 | NO_LIBUNWIND := 1 | 256 | NO_LIBUNWIND := 1 |
251 | NO_LIBDW_DWARF_UNWIND := 1 | 257 | NO_LIBDW_DWARF_UNWIND := 1 |
258 | NO_LIBBPF := 1 | ||
252 | else | 259 | else |
253 | ifneq ($(filter s% -static%,$(LDFLAGS),),) | 260 | ifneq ($(filter s% -static%,$(LDFLAGS),),) |
254 | msg := $(error No static glibc found, please install glibc-static); | 261 | msg := $(error No static glibc found, please install glibc-static); |
@@ -305,6 +312,13 @@ ifndef NO_LIBELF | |||
305 | $(call detected,CONFIG_DWARF) | 312 | $(call detected,CONFIG_DWARF) |
306 | endif # PERF_HAVE_DWARF_REGS | 313 | endif # PERF_HAVE_DWARF_REGS |
307 | endif # NO_DWARF | 314 | endif # NO_DWARF |
315 | |||
316 | ifndef NO_LIBBPF | ||
317 | ifeq ($(feature-bpf), 1) | ||
318 | CFLAGS += -DHAVE_LIBBPF_SUPPORT | ||
319 | $(call detected,CONFIG_LIBBPF) | ||
320 | endif | ||
321 | endif # NO_LIBBPF | ||
308 | endif # NO_LIBELF | 322 | endif # NO_LIBELF |
309 | 323 | ||
310 | ifeq ($(ARCH),powerpc) | 324 | ifeq ($(ARCH),powerpc) |
@@ -320,6 +334,13 @@ ifndef NO_LIBUNWIND | |||
320 | endif | 334 | endif |
321 | endif | 335 | endif |
322 | 336 | ||
337 | ifndef NO_LIBBPF | ||
338 | ifneq ($(feature-bpf), 1) | ||
339 | msg := $(warning BPF API too old. Please install recent kernel headers. BPF support in 'perf record' is disabled.) | ||
340 | NO_LIBBPF := 1 | ||
341 | endif | ||
342 | endif | ||
343 | |||
323 | dwarf-post-unwind := 1 | 344 | dwarf-post-unwind := 1 |
324 | dwarf-post-unwind-text := BUG | 345 | dwarf-post-unwind-text := BUG |
325 | 346 | ||
@@ -573,9 +594,14 @@ ifndef NO_LIBNUMA | |||
573 | msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numactl-devel/libnuma-devel/libnuma-dev); | 594 | msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numactl-devel/libnuma-devel/libnuma-dev); |
574 | NO_LIBNUMA := 1 | 595 | NO_LIBNUMA := 1 |
575 | else | 596 | else |
576 | CFLAGS += -DHAVE_LIBNUMA_SUPPORT | 597 | ifeq ($(feature-numa_num_possible_cpus), 0) |
577 | EXTLIBS += -lnuma | 598 | msg := $(warning Old numa library found, disables 'perf bench numa mem' benchmark, please install numactl-devel/libnuma-devel/libnuma-dev >= 2.0.8); |
578 | $(call detected,CONFIG_NUMA) | 599 | NO_LIBNUMA := 1 |
600 | else | ||
601 | CFLAGS += -DHAVE_LIBNUMA_SUPPORT | ||
602 | EXTLIBS += -lnuma | ||
603 | $(call detected,CONFIG_NUMA) | ||
604 | endif | ||
579 | endif | 605 | endif |
580 | endif | 606 | endif |
581 | 607 | ||
@@ -621,8 +647,13 @@ ifdef LIBBABELTRACE | |||
621 | endif | 647 | endif |
622 | 648 | ||
623 | ifndef NO_AUXTRACE | 649 | ifndef NO_AUXTRACE |
624 | $(call detected,CONFIG_AUXTRACE) | 650 | ifeq ($(feature-get_cpuid), 0) |
625 | CFLAGS += -DHAVE_AUXTRACE_SUPPORT | 651 | msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); |
652 | NO_AUXTRACE := 1 | ||
653 | else | ||
654 | $(call detected,CONFIG_AUXTRACE) | ||
655 | CFLAGS += -DHAVE_AUXTRACE_SUPPORT | ||
656 | endif | ||
626 | endif | 657 | endif |
627 | 658 | ||
628 | # Among the variables below, these: | 659 | # Among the variables below, these: |
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 07dbff5c0e60..3d4c7c09adea 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -8,14 +8,16 @@ | |||
8 | */ | 8 | */ |
9 | #include "builtin.h" | 9 | #include "builtin.h" |
10 | 10 | ||
11 | #include "util/env.h" | ||
11 | #include "util/exec_cmd.h" | 12 | #include "util/exec_cmd.h" |
12 | #include "util/cache.h" | 13 | #include "util/cache.h" |
13 | #include "util/quote.h" | 14 | #include "util/quote.h" |
14 | #include "util/run-command.h" | 15 | #include "util/run-command.h" |
15 | #include "util/parse-events.h" | 16 | #include "util/parse-events.h" |
16 | #include "util/parse-options.h" | 17 | #include "util/parse-options.h" |
18 | #include "util/bpf-loader.h" | ||
17 | #include "util/debug.h" | 19 | #include "util/debug.h" |
18 | #include <api/fs/debugfs.h> | 20 | #include <api/fs/tracing_path.h> |
19 | #include <pthread.h> | 21 | #include <pthread.h> |
20 | 22 | ||
21 | const char perf_usage_string[] = | 23 | const char perf_usage_string[] = |
@@ -161,6 +163,20 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) | |||
161 | break; | 163 | break; |
162 | 164 | ||
163 | /* | 165 | /* |
166 | * Shortcut for '-h' and '-v' options to invoke help | ||
167 | * and version command. | ||
168 | */ | ||
169 | if (!strcmp(cmd, "-h")) { | ||
170 | (*argv)[0] = "--help"; | ||
171 | break; | ||
172 | } | ||
173 | |||
174 | if (!strcmp(cmd, "-v")) { | ||
175 | (*argv)[0] = "--version"; | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | /* | ||
164 | * Check remaining flags. | 180 | * Check remaining flags. |
165 | */ | 181 | */ |
166 | if (!prefixcmp(cmd, CMD_EXEC_PATH)) { | 182 | if (!prefixcmp(cmd, CMD_EXEC_PATH)) { |
@@ -214,7 +230,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) | |||
214 | fprintf(stderr, "No directory given for --debugfs-dir.\n"); | 230 | fprintf(stderr, "No directory given for --debugfs-dir.\n"); |
215 | usage(perf_usage_string); | 231 | usage(perf_usage_string); |
216 | } | 232 | } |
217 | perf_debugfs_set_path((*argv)[1]); | 233 | tracing_path_set((*argv)[1]); |
218 | if (envchanged) | 234 | if (envchanged) |
219 | *envchanged = 1; | 235 | *envchanged = 1; |
220 | (*argv)++; | 236 | (*argv)++; |
@@ -230,7 +246,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) | |||
230 | (*argv)++; | 246 | (*argv)++; |
231 | (*argc)--; | 247 | (*argc)--; |
232 | } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { | 248 | } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { |
233 | perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR)); | 249 | tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR)); |
234 | fprintf(stderr, "dir: %s\n", tracing_path); | 250 | fprintf(stderr, "dir: %s\n", tracing_path); |
235 | if (envchanged) | 251 | if (envchanged) |
236 | *envchanged = 1; | 252 | *envchanged = 1; |
@@ -369,6 +385,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) | |||
369 | 385 | ||
370 | status = p->fn(argc, argv, prefix); | 386 | status = p->fn(argc, argv, prefix); |
371 | exit_browser(status); | 387 | exit_browser(status); |
388 | perf_env__exit(&perf_env); | ||
389 | bpf__clear(); | ||
372 | 390 | ||
373 | if (status) | 391 | if (status) |
374 | return status & 0xff; | 392 | return status & 0xff; |
@@ -517,8 +535,10 @@ int main(int argc, const char **argv) | |||
517 | cmd = perf_extract_argv0_path(argv[0]); | 535 | cmd = perf_extract_argv0_path(argv[0]); |
518 | if (!cmd) | 536 | if (!cmd) |
519 | cmd = "perf-help"; | 537 | cmd = "perf-help"; |
520 | /* get debugfs mount point from /proc/mounts */ | 538 | |
521 | perf_debugfs_mount(NULL); | 539 | /* get debugfs/tracefs mount point from /proc/mounts */ |
540 | tracing_path_mount(); | ||
541 | |||
522 | /* | 542 | /* |
523 | * "perf-xxxx" is the same as "perf xxxx", but we obviously: | 543 | * "perf-xxxx" is the same as "perf xxxx", but we obviously: |
524 | * | 544 | * |
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py index b9d508336ae6..c235c22b107a 100755 --- a/tools/perf/python/twatch.py +++ b/tools/perf/python/twatch.py | |||
@@ -15,14 +15,14 @@ | |||
15 | 15 | ||
16 | import perf | 16 | import perf |
17 | 17 | ||
18 | def main(): | 18 | def main(context_switch = 0, thread = -1): |
19 | cpus = perf.cpu_map() | 19 | cpus = perf.cpu_map() |
20 | threads = perf.thread_map() | 20 | threads = perf.thread_map(thread) |
21 | evsel = perf.evsel(type = perf.TYPE_SOFTWARE, | 21 | evsel = perf.evsel(type = perf.TYPE_SOFTWARE, |
22 | config = perf.COUNT_SW_DUMMY, | 22 | config = perf.COUNT_SW_DUMMY, |
23 | task = 1, comm = 1, mmap = 0, freq = 0, | 23 | task = 1, comm = 1, mmap = 0, freq = 0, |
24 | wakeup_events = 1, watermark = 1, | 24 | wakeup_events = 1, watermark = 1, |
25 | sample_id_all = 1, | 25 | sample_id_all = 1, context_switch = context_switch, |
26 | sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU) | 26 | sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU) |
27 | 27 | ||
28 | """What we want are just the PERF_RECORD_ lifetime events for threads, | 28 | """What we want are just the PERF_RECORD_ lifetime events for threads, |
@@ -48,4 +48,21 @@ def main(): | |||
48 | print event | 48 | print event |
49 | 49 | ||
50 | if __name__ == '__main__': | 50 | if __name__ == '__main__': |
51 | """ | ||
52 | To test the PERF_RECORD_SWITCH record, pick a pid and replace | ||
53 | in the following line. | ||
54 | |||
55 | Example output: | ||
56 | |||
57 | cpu: 3, pid: 31463, tid: 31593 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31593, switch_out: 1 } | ||
58 | cpu: 1, pid: 31463, tid: 31489 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31489, switch_out: 1 } | ||
59 | cpu: 2, pid: 31463, tid: 31496 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31496, switch_out: 1 } | ||
60 | cpu: 3, pid: 31463, tid: 31491 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31491, switch_out: 0 } | ||
61 | |||
62 | It is possible as well to use event.misc & perf.PERF_RECORD_MISC_SWITCH_OUT | ||
63 | to figure out if this is a context switch in or out of the monitored threads. | ||
64 | |||
65 | If bored, please add command line option parsing support for these options :-) | ||
66 | """ | ||
67 | # main(context_switch = 1, thread = 31463) | ||
51 | main() | 68 | main() |
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py index 84a32037a80f..1b02cdc0cab6 100644 --- a/tools/perf/scripts/python/export-to-postgresql.py +++ b/tools/perf/scripts/python/export-to-postgresql.py | |||
@@ -61,6 +61,142 @@ import datetime | |||
61 | # | 61 | # |
62 | # An example of using the database is provided by the script | 62 | # An example of using the database is provided by the script |
63 | # call-graph-from-postgresql.py. Refer to that script for details. | 63 | # call-graph-from-postgresql.py. Refer to that script for details. |
64 | # | ||
65 | # Tables: | ||
66 | # | ||
67 | # The tables largely correspond to perf tools' data structures. They are largely self-explanatory. | ||
68 | # | ||
69 | # samples | ||
70 | # | ||
71 | # 'samples' is the main table. It represents what instruction was executing at a point in time | ||
72 | # when something (a selected event) happened. The memory address is the instruction pointer or 'ip'. | ||
73 | # | ||
74 | # calls | ||
75 | # | ||
76 | # 'calls' represents function calls and is related to 'samples' by 'call_id' and 'return_id'. | ||
77 | # 'calls' is only created when the 'calls' option to this script is specified. | ||
78 | # | ||
79 | # call_paths | ||
80 | # | ||
81 | # 'call_paths' represents all the call stacks. Each 'call' has an associated record in 'call_paths'. | ||
82 | # 'calls_paths' is only created when the 'calls' option to this script is specified. | ||
83 | # | ||
84 | # branch_types | ||
85 | # | ||
86 | # 'branch_types' provides descriptions for each type of branch. | ||
87 | # | ||
88 | # comm_threads | ||
89 | # | ||
90 | # 'comm_threads' shows how 'comms' relates to 'threads'. | ||
91 | # | ||
92 | # comms | ||
93 | # | ||
94 | # 'comms' contains a record for each 'comm' - the name given to the executable that is running. | ||
95 | # | ||
96 | # dsos | ||
97 | # | ||
98 | # 'dsos' contains a record for each executable file or library. | ||
99 | # | ||
100 | # machines | ||
101 | # | ||
102 | # 'machines' can be used to distinguish virtual machines if virtualization is supported. | ||
103 | # | ||
104 | # selected_events | ||
105 | # | ||
106 | # 'selected_events' contains a record for each kind of event that has been sampled. | ||
107 | # | ||
108 | # symbols | ||
109 | # | ||
110 | # 'symbols' contains a record for each symbol. Only symbols that have samples are present. | ||
111 | # | ||
112 | # threads | ||
113 | # | ||
114 | # 'threads' contains a record for each thread. | ||
115 | # | ||
116 | # Views: | ||
117 | # | ||
118 | # Most of the tables have views for more friendly display. The views are: | ||
119 | # | ||
120 | # calls_view | ||
121 | # call_paths_view | ||
122 | # comm_threads_view | ||
123 | # dsos_view | ||
124 | # machines_view | ||
125 | # samples_view | ||
126 | # symbols_view | ||
127 | # threads_view | ||
128 | # | ||
129 | # More examples of browsing the database with psql: | ||
130 | # Note that some of the examples are not the most optimal SQL query. | ||
131 | # Note that call information is only available if the script's 'calls' option has been used. | ||
132 | # | ||
133 | # Top 10 function calls (not aggregated by symbol): | ||
134 | # | ||
135 | # SELECT * FROM calls_view ORDER BY elapsed_time DESC LIMIT 10; | ||
136 | # | ||
137 | # Top 10 function calls (aggregated by symbol): | ||
138 | # | ||
139 | # SELECT symbol_id,(SELECT name FROM symbols WHERE id = symbol_id) AS symbol, | ||
140 | # SUM(elapsed_time) AS tot_elapsed_time,SUM(branch_count) AS tot_branch_count | ||
141 | # FROM calls_view GROUP BY symbol_id ORDER BY tot_elapsed_time DESC LIMIT 10; | ||
142 | # | ||
143 | # Note that the branch count gives a rough estimation of cpu usage, so functions | ||
144 | # that took a long time but have a relatively low branch count must have spent time | ||
145 | # waiting. | ||
146 | # | ||
147 | # Find symbols by pattern matching on part of the name (e.g. names containing 'alloc'): | ||
148 | # | ||
149 | # SELECT * FROM symbols_view WHERE name LIKE '%alloc%'; | ||
150 | # | ||
151 | # Top 10 function calls for a specific symbol (e.g. whose symbol_id is 187): | ||
152 | # | ||
153 | # SELECT * FROM calls_view WHERE symbol_id = 187 ORDER BY elapsed_time DESC LIMIT 10; | ||
154 | # | ||
155 | # Show function calls made by function in the same context (i.e. same call path) (e.g. one with call_path_id 254): | ||
156 | # | ||
157 | # SELECT * FROM calls_view WHERE parent_call_path_id = 254; | ||
158 | # | ||
159 | # Show branches made during a function call (e.g. where call_id is 29357 and return_id is 29370 and tid is 29670) | ||
160 | # | ||
161 | # SELECT * FROM samples_view WHERE id >= 29357 AND id <= 29370 AND tid = 29670 AND event LIKE 'branches%'; | ||
162 | # | ||
163 | # Show transactions: | ||
164 | # | ||
165 | # SELECT * FROM samples_view WHERE event = 'transactions'; | ||
166 | # | ||
167 | # Note transaction start has 'in_tx' true whereas, transaction end has 'in_tx' false. | ||
168 | # Transaction aborts have branch_type_name 'transaction abort' | ||
169 | # | ||
170 | # Show transaction aborts: | ||
171 | # | ||
172 | # SELECT * FROM samples_view WHERE event = 'transactions' AND branch_type_name = 'transaction abort'; | ||
173 | # | ||
174 | # To print a call stack requires walking the call_paths table. For example this python script: | ||
175 | # #!/usr/bin/python2 | ||
176 | # | ||
177 | # import sys | ||
178 | # from PySide.QtSql import * | ||
179 | # | ||
180 | # if __name__ == '__main__': | ||
181 | # if (len(sys.argv) < 3): | ||
182 | # print >> sys.stderr, "Usage is: printcallstack.py <database name> <call_path_id>" | ||
183 | # raise Exception("Too few arguments") | ||
184 | # dbname = sys.argv[1] | ||
185 | # call_path_id = sys.argv[2] | ||
186 | # db = QSqlDatabase.addDatabase('QPSQL') | ||
187 | # db.setDatabaseName(dbname) | ||
188 | # if not db.open(): | ||
189 | # raise Exception("Failed to open database " + dbname + " error: " + db.lastError().text()) | ||
190 | # query = QSqlQuery(db) | ||
191 | # print " id ip symbol_id symbol dso_id dso_short_name" | ||
192 | # while call_path_id != 0 and call_path_id != 1: | ||
193 | # ret = query.exec_('SELECT * FROM call_paths_view WHERE id = ' + str(call_path_id)) | ||
194 | # if not ret: | ||
195 | # raise Exception("Query failed: " + query.lastError().text()) | ||
196 | # if not query.next(): | ||
197 | # raise Exception("Query failed") | ||
198 | # print "{0:>6} {1:>10} {2:>9} {3:<30} {4:>6} {5:<30}".format(query.value(0), query.value(1), query.value(2), query.value(3), query.value(4), query.value(5)) | ||
199 | # call_path_id = query.value(6) | ||
64 | 200 | ||
65 | from PySide.QtSql import * | 201 | from PySide.QtSql import * |
66 | 202 | ||
@@ -244,6 +380,91 @@ if perf_db_export_calls: | |||
244 | 'parent_call_path_id bigint,' | 380 | 'parent_call_path_id bigint,' |
245 | 'flags integer)') | 381 | 'flags integer)') |
246 | 382 | ||
383 | do_query(query, 'CREATE VIEW machines_view AS ' | ||
384 | 'SELECT ' | ||
385 | 'id,' | ||
386 | 'pid,' | ||
387 | 'root_dir,' | ||
388 | 'CASE WHEN id=0 THEN \'unknown\' WHEN pid=-1 THEN \'host\' ELSE \'guest\' END AS host_or_guest' | ||
389 | ' FROM machines') | ||
390 | |||
391 | do_query(query, 'CREATE VIEW dsos_view AS ' | ||
392 | 'SELECT ' | ||
393 | 'id,' | ||
394 | 'machine_id,' | ||
395 | '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,' | ||
396 | 'short_name,' | ||
397 | 'long_name,' | ||
398 | 'build_id' | ||
399 | ' FROM dsos') | ||
400 | |||
401 | do_query(query, 'CREATE VIEW symbols_view AS ' | ||
402 | 'SELECT ' | ||
403 | 'id,' | ||
404 | 'name,' | ||
405 | '(SELECT short_name FROM dsos WHERE id=dso_id) AS dso,' | ||
406 | 'dso_id,' | ||
407 | 'sym_start,' | ||
408 | 'sym_end,' | ||
409 | 'CASE WHEN binding=0 THEN \'local\' WHEN binding=1 THEN \'global\' ELSE \'weak\' END AS binding' | ||
410 | ' FROM symbols') | ||
411 | |||
412 | do_query(query, 'CREATE VIEW threads_view AS ' | ||
413 | 'SELECT ' | ||
414 | 'id,' | ||
415 | 'machine_id,' | ||
416 | '(SELECT host_or_guest FROM machines_view WHERE id = machine_id) AS host_or_guest,' | ||
417 | 'process_id,' | ||
418 | 'pid,' | ||
419 | 'tid' | ||
420 | ' FROM threads') | ||
421 | |||
422 | do_query(query, 'CREATE VIEW comm_threads_view AS ' | ||
423 | 'SELECT ' | ||
424 | 'comm_id,' | ||
425 | '(SELECT comm FROM comms WHERE id = comm_id) AS command,' | ||
426 | 'thread_id,' | ||
427 | '(SELECT pid FROM threads WHERE id = thread_id) AS pid,' | ||
428 | '(SELECT tid FROM threads WHERE id = thread_id) AS tid' | ||
429 | ' FROM comm_threads') | ||
430 | |||
431 | if perf_db_export_calls: | ||
432 | do_query(query, 'CREATE VIEW call_paths_view AS ' | ||
433 | 'SELECT ' | ||
434 | 'c.id,' | ||
435 | 'to_hex(c.ip) AS ip,' | ||
436 | 'c.symbol_id,' | ||
437 | '(SELECT name FROM symbols WHERE id = c.symbol_id) AS symbol,' | ||
438 | '(SELECT dso_id FROM symbols WHERE id = c.symbol_id) AS dso_id,' | ||
439 | '(SELECT dso FROM symbols_view WHERE id = c.symbol_id) AS dso_short_name,' | ||
440 | 'c.parent_id,' | ||
441 | 'to_hex(p.ip) AS parent_ip,' | ||
442 | 'p.symbol_id AS parent_symbol_id,' | ||
443 | '(SELECT name FROM symbols WHERE id = p.symbol_id) AS parent_symbol,' | ||
444 | '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,' | ||
445 | '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name' | ||
446 | ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id') | ||
447 | do_query(query, 'CREATE VIEW calls_view AS ' | ||
448 | 'SELECT ' | ||
449 | 'calls.id,' | ||
450 | 'thread_id,' | ||
451 | '(SELECT pid FROM threads WHERE id = thread_id) AS pid,' | ||
452 | '(SELECT tid FROM threads WHERE id = thread_id) AS tid,' | ||
453 | '(SELECT comm FROM comms WHERE id = comm_id) AS command,' | ||
454 | 'call_path_id,' | ||
455 | 'to_hex(ip) AS ip,' | ||
456 | 'symbol_id,' | ||
457 | '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,' | ||
458 | 'call_time,' | ||
459 | 'return_time,' | ||
460 | 'return_time - call_time AS elapsed_time,' | ||
461 | 'branch_count,' | ||
462 | 'call_id,' | ||
463 | 'return_id,' | ||
464 | 'CASE WHEN flags=1 THEN \'no call\' WHEN flags=2 THEN \'no return\' WHEN flags=3 THEN \'no call/return\' ELSE \'\' END AS flags,' | ||
465 | 'parent_call_path_id' | ||
466 | ' FROM calls INNER JOIN call_paths ON call_paths.id = call_path_id') | ||
467 | |||
247 | do_query(query, 'CREATE VIEW samples_view AS ' | 468 | do_query(query, 'CREATE VIEW samples_view AS ' |
248 | 'SELECT ' | 469 | 'SELECT ' |
249 | 'id,' | 470 | 'id,' |
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index c1518bdd0f1b..50de2253cff6 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build | |||
@@ -8,7 +8,6 @@ perf-y += openat-syscall-all-cpus.o | |||
8 | perf-y += openat-syscall-tp-fields.o | 8 | perf-y += openat-syscall-tp-fields.o |
9 | perf-y += mmap-basic.o | 9 | perf-y += mmap-basic.o |
10 | perf-y += perf-record.o | 10 | perf-y += perf-record.o |
11 | perf-y += rdpmc.o | ||
12 | perf-y += evsel-roundtrip-name.o | 11 | perf-y += evsel-roundtrip-name.o |
13 | perf-y += evsel-tp-sched.o | 12 | perf-y += evsel-tp-sched.o |
14 | perf-y += fdarray.o | 13 | perf-y += fdarray.o |
@@ -33,8 +32,7 @@ perf-y += parse-no-sample-id-all.o | |||
33 | perf-y += kmod-path.o | 32 | perf-y += kmod-path.o |
34 | perf-y += thread-map.o | 33 | perf-y += thread-map.o |
35 | perf-y += llvm.o | 34 | perf-y += llvm.o |
36 | 35 | perf-y += topology.o | |
37 | perf-$(CONFIG_X86) += perf-time-to-tsc.o | ||
38 | 36 | ||
39 | ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) | 37 | ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) |
40 | perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o | 38 | perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o |
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c new file mode 100644 index 000000000000..410a70b93b93 --- /dev/null +++ b/tools/perf/tests/bpf-script-example.c | |||
@@ -0,0 +1,44 @@ | |||
1 | #ifndef LINUX_VERSION_CODE | ||
2 | # error Need LINUX_VERSION_CODE | ||
3 | # error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig' | ||
4 | #endif | ||
5 | #define BPF_ANY 0 | ||
6 | #define BPF_MAP_TYPE_ARRAY 2 | ||
7 | #define BPF_FUNC_map_lookup_elem 1 | ||
8 | #define BPF_FUNC_map_update_elem 2 | ||
9 | |||
10 | static void *(*bpf_map_lookup_elem)(void *map, void *key) = | ||
11 | (void *) BPF_FUNC_map_lookup_elem; | ||
12 | static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) = | ||
13 | (void *) BPF_FUNC_map_update_elem; | ||
14 | |||
15 | struct bpf_map_def { | ||
16 | unsigned int type; | ||
17 | unsigned int key_size; | ||
18 | unsigned int value_size; | ||
19 | unsigned int max_entries; | ||
20 | }; | ||
21 | |||
22 | #define SEC(NAME) __attribute__((section(NAME), used)) | ||
23 | struct bpf_map_def SEC("maps") flip_table = { | ||
24 | .type = BPF_MAP_TYPE_ARRAY, | ||
25 | .key_size = sizeof(int), | ||
26 | .value_size = sizeof(int), | ||
27 | .max_entries = 1, | ||
28 | }; | ||
29 | |||
30 | SEC("func=sys_epoll_pwait") | ||
31 | int bpf_func__sys_epoll_pwait(void *ctx) | ||
32 | { | ||
33 | int ind =0; | ||
34 | int *flag = bpf_map_lookup_elem(&flip_table, &ind); | ||
35 | int new_flag; | ||
36 | if (!flag) | ||
37 | return 0; | ||
38 | /* flip flag and store back */ | ||
39 | new_flag = !*flag; | ||
40 | bpf_map_update_elem(&flip_table, &ind, &new_flag, BPF_ANY); | ||
41 | return new_flag; | ||
42 | } | ||
43 | char _license[] SEC("license") = "GPL"; | ||
44 | int _version SEC("version") = LINUX_VERSION_CODE; | ||
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 136cd934be66..66f72d3d6677 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -14,10 +14,13 @@ | |||
14 | #include "parse-options.h" | 14 | #include "parse-options.h" |
15 | #include "symbol.h" | 15 | #include "symbol.h" |
16 | 16 | ||
17 | static struct test { | 17 | struct test __weak arch_tests[] = { |
18 | const char *desc; | 18 | { |
19 | int (*func)(void); | 19 | .func = NULL, |
20 | } tests[] = { | 20 | }, |
21 | }; | ||
22 | |||
23 | static struct test generic_tests[] = { | ||
21 | { | 24 | { |
22 | .desc = "vmlinux symtab matches kallsyms", | 25 | .desc = "vmlinux symtab matches kallsyms", |
23 | .func = test__vmlinux_matches_kallsyms, | 26 | .func = test__vmlinux_matches_kallsyms, |
@@ -38,12 +41,6 @@ static struct test { | |||
38 | .desc = "parse events tests", | 41 | .desc = "parse events tests", |
39 | .func = test__parse_events, | 42 | .func = test__parse_events, |
40 | }, | 43 | }, |
41 | #if defined(__x86_64__) || defined(__i386__) | ||
42 | { | ||
43 | .desc = "x86 rdpmc test", | ||
44 | .func = test__rdpmc, | ||
45 | }, | ||
46 | #endif | ||
47 | { | 44 | { |
48 | .desc = "Validate PERF_RECORD_* events & perf_sample fields", | 45 | .desc = "Validate PERF_RECORD_* events & perf_sample fields", |
49 | .func = test__PERF_RECORD, | 46 | .func = test__PERF_RECORD, |
@@ -104,12 +101,6 @@ static struct test { | |||
104 | .desc = "Test software clock events have valid period values", | 101 | .desc = "Test software clock events have valid period values", |
105 | .func = test__sw_clock_freq, | 102 | .func = test__sw_clock_freq, |
106 | }, | 103 | }, |
107 | #if defined(__x86_64__) || defined(__i386__) | ||
108 | { | ||
109 | .desc = "Test converting perf time to TSC", | ||
110 | .func = test__perf_time_to_tsc, | ||
111 | }, | ||
112 | #endif | ||
113 | { | 104 | { |
114 | .desc = "Test object code reading", | 105 | .desc = "Test object code reading", |
115 | .func = test__code_reading, | 106 | .func = test__code_reading, |
@@ -126,14 +117,6 @@ static struct test { | |||
126 | .desc = "Test parsing with no sample_id_all bit set", | 117 | .desc = "Test parsing with no sample_id_all bit set", |
127 | .func = test__parse_no_sample_id_all, | 118 | .func = test__parse_no_sample_id_all, |
128 | }, | 119 | }, |
129 | #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__) | ||
130 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
131 | { | ||
132 | .desc = "Test dwarf unwind", | ||
133 | .func = test__dwarf_unwind, | ||
134 | }, | ||
135 | #endif | ||
136 | #endif | ||
137 | { | 120 | { |
138 | .desc = "Test filtering hist entries", | 121 | .desc = "Test filtering hist entries", |
139 | .func = test__hists_filter, | 122 | .func = test__hists_filter, |
@@ -179,11 +162,20 @@ static struct test { | |||
179 | .func = test__llvm, | 162 | .func = test__llvm, |
180 | }, | 163 | }, |
181 | { | 164 | { |
165 | .desc = "Test topology in session", | ||
166 | .func = test_session_topology, | ||
167 | }, | ||
168 | { | ||
182 | .func = NULL, | 169 | .func = NULL, |
183 | }, | 170 | }, |
184 | }; | 171 | }; |
185 | 172 | ||
186 | static bool perf_test__matches(int curr, int argc, const char *argv[]) | 173 | static struct test *tests[] = { |
174 | generic_tests, | ||
175 | arch_tests, | ||
176 | }; | ||
177 | |||
178 | static bool perf_test__matches(struct test *test, int curr, int argc, const char *argv[]) | ||
187 | { | 179 | { |
188 | int i; | 180 | int i; |
189 | 181 | ||
@@ -200,7 +192,7 @@ static bool perf_test__matches(int curr, int argc, const char *argv[]) | |||
200 | continue; | 192 | continue; |
201 | } | 193 | } |
202 | 194 | ||
203 | if (strstr(tests[curr].desc, argv[i])) | 195 | if (strstr(test->desc, argv[i])) |
204 | return true; | 196 | return true; |
205 | } | 197 | } |
206 | 198 | ||
@@ -237,27 +229,31 @@ static int run_test(struct test *test) | |||
237 | return err; | 229 | return err; |
238 | } | 230 | } |
239 | 231 | ||
232 | #define for_each_test(j, t) \ | ||
233 | for (j = 0; j < ARRAY_SIZE(tests); j++) \ | ||
234 | for (t = &tests[j][0]; t->func; t++) | ||
235 | |||
240 | static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) | 236 | static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) |
241 | { | 237 | { |
238 | struct test *t; | ||
239 | unsigned int j; | ||
242 | int i = 0; | 240 | int i = 0; |
243 | int width = 0; | 241 | int width = 0; |
244 | 242 | ||
245 | while (tests[i].func) { | 243 | for_each_test(j, t) { |
246 | int len = strlen(tests[i].desc); | 244 | int len = strlen(t->desc); |
247 | 245 | ||
248 | if (width < len) | 246 | if (width < len) |
249 | width = len; | 247 | width = len; |
250 | ++i; | ||
251 | } | 248 | } |
252 | 249 | ||
253 | i = 0; | 250 | for_each_test(j, t) { |
254 | while (tests[i].func) { | ||
255 | int curr = i++, err; | 251 | int curr = i++, err; |
256 | 252 | ||
257 | if (!perf_test__matches(curr, argc, argv)) | 253 | if (!perf_test__matches(t, curr, argc, argv)) |
258 | continue; | 254 | continue; |
259 | 255 | ||
260 | pr_info("%2d: %-*s:", i, width, tests[curr].desc); | 256 | pr_info("%2d: %-*s:", i, width, t->desc); |
261 | 257 | ||
262 | if (intlist__find(skiplist, i)) { | 258 | if (intlist__find(skiplist, i)) { |
263 | color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); | 259 | color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); |
@@ -265,8 +261,8 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) | |||
265 | } | 261 | } |
266 | 262 | ||
267 | pr_debug("\n--- start ---\n"); | 263 | pr_debug("\n--- start ---\n"); |
268 | err = run_test(&tests[curr]); | 264 | err = run_test(t); |
269 | pr_debug("---- end ----\n%s:", tests[curr].desc); | 265 | pr_debug("---- end ----\n%s:", t->desc); |
270 | 266 | ||
271 | switch (err) { | 267 | switch (err) { |
272 | case TEST_OK: | 268 | case TEST_OK: |
@@ -287,15 +283,15 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) | |||
287 | 283 | ||
288 | static int perf_test__list(int argc, const char **argv) | 284 | static int perf_test__list(int argc, const char **argv) |
289 | { | 285 | { |
286 | unsigned int j; | ||
287 | struct test *t; | ||
290 | int i = 0; | 288 | int i = 0; |
291 | 289 | ||
292 | while (tests[i].func) { | 290 | for_each_test(j, t) { |
293 | int curr = i++; | 291 | if (argc > 1 && !strstr(t->desc, argv[1])) |
294 | |||
295 | if (argc > 1 && !strstr(tests[curr].desc, argv[1])) | ||
296 | continue; | 292 | continue; |
297 | 293 | ||
298 | pr_info("%2d: %s\n", i, tests[curr].desc); | 294 | pr_info("%2d: %s\n", ++i, t->desc); |
299 | } | 295 | } |
300 | 296 | ||
301 | return 0; | 297 | return 0; |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 39c784a100a9..49b1959dda41 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -33,20 +33,20 @@ static unsigned int hex(char c) | |||
33 | return c - 'A' + 10; | 33 | return c - 'A' + 10; |
34 | } | 34 | } |
35 | 35 | ||
36 | static void read_objdump_line(const char *line, size_t line_len, void **buf, | 36 | static size_t read_objdump_line(const char *line, size_t line_len, void *buf, |
37 | size_t *len) | 37 | size_t len) |
38 | { | 38 | { |
39 | const char *p; | 39 | const char *p; |
40 | size_t i; | 40 | size_t i, j = 0; |
41 | 41 | ||
42 | /* Skip to a colon */ | 42 | /* Skip to a colon */ |
43 | p = strchr(line, ':'); | 43 | p = strchr(line, ':'); |
44 | if (!p) | 44 | if (!p) |
45 | return; | 45 | return 0; |
46 | i = p + 1 - line; | 46 | i = p + 1 - line; |
47 | 47 | ||
48 | /* Read bytes */ | 48 | /* Read bytes */ |
49 | while (*len) { | 49 | while (j < len) { |
50 | char c1, c2; | 50 | char c1, c2; |
51 | 51 | ||
52 | /* Skip spaces */ | 52 | /* Skip spaces */ |
@@ -65,20 +65,26 @@ static void read_objdump_line(const char *line, size_t line_len, void **buf, | |||
65 | if (i < line_len && line[i] && !isspace(line[i])) | 65 | if (i < line_len && line[i] && !isspace(line[i])) |
66 | break; | 66 | break; |
67 | /* Store byte */ | 67 | /* Store byte */ |
68 | *(unsigned char *)*buf = (hex(c1) << 4) | hex(c2); | 68 | *(unsigned char *)buf = (hex(c1) << 4) | hex(c2); |
69 | *buf += 1; | 69 | buf += 1; |
70 | *len -= 1; | 70 | j++; |
71 | } | 71 | } |
72 | /* return number of successfully read bytes */ | ||
73 | return j; | ||
72 | } | 74 | } |
73 | 75 | ||
74 | static int read_objdump_output(FILE *f, void **buf, size_t *len) | 76 | static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr) |
75 | { | 77 | { |
76 | char *line = NULL; | 78 | char *line = NULL; |
77 | size_t line_len; | 79 | size_t line_len, off_last = 0; |
78 | ssize_t ret; | 80 | ssize_t ret; |
79 | int err = 0; | 81 | int err = 0; |
82 | u64 addr, last_addr = start_addr; | ||
83 | |||
84 | while (off_last < *len) { | ||
85 | size_t off, read_bytes, written_bytes; | ||
86 | unsigned char tmp[BUFSZ]; | ||
80 | 87 | ||
81 | while (1) { | ||
82 | ret = getline(&line, &line_len, f); | 88 | ret = getline(&line, &line_len, f); |
83 | if (feof(f)) | 89 | if (feof(f)) |
84 | break; | 90 | break; |
@@ -87,9 +93,33 @@ static int read_objdump_output(FILE *f, void **buf, size_t *len) | |||
87 | err = -1; | 93 | err = -1; |
88 | break; | 94 | break; |
89 | } | 95 | } |
90 | read_objdump_line(line, ret, buf, len); | 96 | |
97 | /* read objdump data into temporary buffer */ | ||
98 | read_bytes = read_objdump_line(line, ret, tmp, sizeof(tmp)); | ||
99 | if (!read_bytes) | ||
100 | continue; | ||
101 | |||
102 | if (sscanf(line, "%"PRIx64, &addr) != 1) | ||
103 | continue; | ||
104 | if (addr < last_addr) { | ||
105 | pr_debug("addr going backwards, read beyond section?\n"); | ||
106 | break; | ||
107 | } | ||
108 | last_addr = addr; | ||
109 | |||
110 | /* copy it from temporary buffer to 'buf' according | ||
111 | * to address on current objdump line */ | ||
112 | off = addr - start_addr; | ||
113 | if (off >= *len) | ||
114 | break; | ||
115 | written_bytes = MIN(read_bytes, *len - off); | ||
116 | memcpy(buf + off, tmp, written_bytes); | ||
117 | off_last = off + written_bytes; | ||
91 | } | 118 | } |
92 | 119 | ||
120 | /* len returns number of bytes that could not be read */ | ||
121 | *len -= off_last; | ||
122 | |||
93 | free(line); | 123 | free(line); |
94 | 124 | ||
95 | return err; | 125 | return err; |
@@ -103,7 +133,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf, | |||
103 | FILE *f; | 133 | FILE *f; |
104 | int ret; | 134 | int ret; |
105 | 135 | ||
106 | fmt = "%s -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s"; | 136 | fmt = "%s -z -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s"; |
107 | ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len, | 137 | ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len, |
108 | filename); | 138 | filename); |
109 | if (ret <= 0 || (size_t)ret >= sizeof(cmd)) | 139 | if (ret <= 0 || (size_t)ret >= sizeof(cmd)) |
@@ -120,7 +150,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf, | |||
120 | return -1; | 150 | return -1; |
121 | } | 151 | } |
122 | 152 | ||
123 | ret = read_objdump_output(f, &buf, &len); | 153 | ret = read_objdump_output(f, buf, &len, addr); |
124 | if (len) { | 154 | if (len) { |
125 | pr_debug("objdump read too few bytes\n"); | 155 | pr_debug("objdump read too few bytes\n"); |
126 | if (!ret) | 156 | if (!ret) |
@@ -132,6 +162,18 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf, | |||
132 | return ret; | 162 | return ret; |
133 | } | 163 | } |
134 | 164 | ||
165 | static void dump_buf(unsigned char *buf, size_t len) | ||
166 | { | ||
167 | size_t i; | ||
168 | |||
169 | for (i = 0; i < len; i++) { | ||
170 | pr_debug("0x%02x ", buf[i]); | ||
171 | if (i % 16 == 15) | ||
172 | pr_debug("\n"); | ||
173 | } | ||
174 | pr_debug("\n"); | ||
175 | } | ||
176 | |||
135 | static int read_object_code(u64 addr, size_t len, u8 cpumode, | 177 | static int read_object_code(u64 addr, size_t len, u8 cpumode, |
136 | struct thread *thread, struct state *state) | 178 | struct thread *thread, struct state *state) |
137 | { | 179 | { |
@@ -234,6 +276,10 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, | |||
234 | /* The results should be identical */ | 276 | /* The results should be identical */ |
235 | if (memcmp(buf1, buf2, len)) { | 277 | if (memcmp(buf1, buf2, len)) { |
236 | pr_debug("Bytes read differ from those read by objdump\n"); | 278 | pr_debug("Bytes read differ from those read by objdump\n"); |
279 | pr_debug("buf1 (dso):\n"); | ||
280 | dump_buf(buf1, len); | ||
281 | pr_debug("buf2 (objdump):\n"); | ||
282 | dump_buf(buf2, len); | ||
237 | return -1; | 283 | return -1; |
238 | } | 284 | } |
239 | pr_debug("Bytes read match those read by objdump\n"); | 285 | pr_debug("Bytes read match those read by objdump\n"); |
@@ -427,7 +473,7 @@ static int do_test_code_reading(bool try_kcore) | |||
427 | symbol_conf.kallsyms_name = "/proc/kallsyms"; | 473 | symbol_conf.kallsyms_name = "/proc/kallsyms"; |
428 | 474 | ||
429 | /* Load kernel map */ | 475 | /* Load kernel map */ |
430 | map = machine->vmlinux_maps[MAP__FUNCTION]; | 476 | map = machine__kernel_map(machine); |
431 | ret = map__load(map, NULL); | 477 | ret = map__load(map, NULL); |
432 | if (ret < 0) { | 478 | if (ret < 0) { |
433 | pr_debug("map__load failed\n"); | 479 | pr_debug("map__load failed\n"); |
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c index 40b36c462427..07221793a3ac 100644 --- a/tools/perf/tests/dwarf-unwind.c +++ b/tools/perf/tests/dwarf-unwind.c | |||
@@ -11,6 +11,10 @@ | |||
11 | #include "thread.h" | 11 | #include "thread.h" |
12 | #include "callchain.h" | 12 | #include "callchain.h" |
13 | 13 | ||
14 | #if defined (__x86_64__) || defined (__i386__) | ||
15 | #include "arch-tests.h" | ||
16 | #endif | ||
17 | |||
14 | /* For bsearch. We try to unwind functions in shared object. */ | 18 | /* For bsearch. We try to unwind functions in shared object. */ |
15 | #include <stdlib.h> | 19 | #include <stdlib.h> |
16 | 20 | ||
diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index 52162425c969..790e413d9a1f 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <linux/err.h> | ||
1 | #include <traceevent/event-parse.h> | 2 | #include <traceevent/event-parse.h> |
2 | #include "evsel.h" | 3 | #include "evsel.h" |
3 | #include "tests.h" | 4 | #include "tests.h" |
@@ -36,8 +37,8 @@ int test__perf_evsel__tp_sched_test(void) | |||
36 | struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); | 37 | struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch"); |
37 | int ret = 0; | 38 | int ret = 0; |
38 | 39 | ||
39 | if (evsel == NULL) { | 40 | if (IS_ERR(evsel)) { |
40 | pr_debug("perf_evsel__new\n"); | 41 | pr_debug("perf_evsel__newtp failed with %ld\n", PTR_ERR(evsel)); |
41 | return -1; | 42 | return -1; |
42 | } | 43 | } |
43 | 44 | ||
@@ -66,6 +67,11 @@ int test__perf_evsel__tp_sched_test(void) | |||
66 | 67 | ||
67 | evsel = perf_evsel__newtp("sched", "sched_wakeup"); | 68 | evsel = perf_evsel__newtp("sched", "sched_wakeup"); |
68 | 69 | ||
70 | if (IS_ERR(evsel)) { | ||
71 | pr_debug("perf_evsel__newtp failed with %ld\n", PTR_ERR(evsel)); | ||
72 | return -1; | ||
73 | } | ||
74 | |||
69 | if (perf_evsel__test_field(evsel, "comm", 16, true)) | 75 | if (perf_evsel__test_field(evsel, "comm", 16, true)) |
70 | ret = -1; | 76 | ret = -1; |
71 | 77 | ||
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index ce48775e6ada..818acf875dd0 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c | |||
@@ -16,30 +16,31 @@ struct sample { | |||
16 | struct thread *thread; | 16 | struct thread *thread; |
17 | struct map *map; | 17 | struct map *map; |
18 | struct symbol *sym; | 18 | struct symbol *sym; |
19 | int socket; | ||
19 | }; | 20 | }; |
20 | 21 | ||
21 | /* For the numbers, see hists_common.c */ | 22 | /* For the numbers, see hists_common.c */ |
22 | static struct sample fake_samples[] = { | 23 | static struct sample fake_samples[] = { |
23 | /* perf [kernel] schedule() */ | 24 | /* perf [kernel] schedule() */ |
24 | { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, }, | 25 | { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, .socket = 0 }, |
25 | /* perf [perf] main() */ | 26 | /* perf [perf] main() */ |
26 | { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, }, | 27 | { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, .socket = 0 }, |
27 | /* perf [libc] malloc() */ | 28 | /* perf [libc] malloc() */ |
28 | { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, }, | 29 | { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, .socket = 0 }, |
29 | /* perf [perf] main() */ | 30 | /* perf [perf] main() */ |
30 | { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, }, /* will be merged */ | 31 | { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, .socket = 0 }, /* will be merged */ |
31 | /* perf [perf] cmd_record() */ | 32 | /* perf [perf] cmd_record() */ |
32 | { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, }, | 33 | { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, .socket = 1 }, |
33 | /* perf [kernel] page_fault() */ | 34 | /* perf [kernel] page_fault() */ |
34 | { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, | 35 | { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 1 }, |
35 | /* bash [bash] main() */ | 36 | /* bash [bash] main() */ |
36 | { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, }, | 37 | { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, .socket = 2 }, |
37 | /* bash [bash] xmalloc() */ | 38 | /* bash [bash] xmalloc() */ |
38 | { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, }, | 39 | { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, .socket = 2 }, |
39 | /* bash [libc] malloc() */ | 40 | /* bash [libc] malloc() */ |
40 | { .pid = FAKE_PID_BASH, .ip = FAKE_IP_LIBC_MALLOC, }, | 41 | { .pid = FAKE_PID_BASH, .ip = FAKE_IP_LIBC_MALLOC, .socket = 3 }, |
41 | /* bash [kernel] page_fault() */ | 42 | /* bash [kernel] page_fault() */ |
42 | { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, }, | 43 | { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 3 }, |
43 | }; | 44 | }; |
44 | 45 | ||
45 | static int add_hist_entries(struct perf_evlist *evlist, | 46 | static int add_hist_entries(struct perf_evlist *evlist, |
@@ -83,6 +84,7 @@ static int add_hist_entries(struct perf_evlist *evlist, | |||
83 | &sample) < 0) | 84 | &sample) < 0) |
84 | goto out; | 85 | goto out; |
85 | 86 | ||
87 | al.socket = fake_samples[i].socket; | ||
86 | if (hist_entry_iter__add(&iter, &al, | 88 | if (hist_entry_iter__add(&iter, &al, |
87 | PERF_MAX_STACK_DEPTH, NULL) < 0) { | 89 | PERF_MAX_STACK_DEPTH, NULL) < 0) { |
88 | addr_location__put(&al); | 90 | addr_location__put(&al); |
@@ -253,6 +255,39 @@ int test__hists_filter(void) | |||
253 | TEST_ASSERT_VAL("Unmatched total period for symbol filter", | 255 | TEST_ASSERT_VAL("Unmatched total period for symbol filter", |
254 | hists->stats.total_non_filtered_period == 300); | 256 | hists->stats.total_non_filtered_period == 300); |
255 | 257 | ||
258 | /* remove symbol filter first */ | ||
259 | hists->symbol_filter_str = NULL; | ||
260 | hists__filter_by_symbol(hists); | ||
261 | |||
262 | /* now applying socket filters */ | ||
263 | hists->socket_filter = 2; | ||
264 | hists__filter_by_socket(hists); | ||
265 | |||
266 | if (verbose > 2) { | ||
267 | pr_info("Histogram for socket filters\n"); | ||
268 | print_hists_out(hists); | ||
269 | } | ||
270 | |||
271 | /* normal stats should be invariant */ | ||
272 | TEST_ASSERT_VAL("Invalid nr samples", | ||
273 | hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10); | ||
274 | TEST_ASSERT_VAL("Invalid nr hist entries", | ||
275 | hists->nr_entries == 9); | ||
276 | TEST_ASSERT_VAL("Invalid total period", | ||
277 | hists->stats.total_period == 1000); | ||
278 | |||
279 | /* but filter stats are changed */ | ||
280 | TEST_ASSERT_VAL("Unmatched nr samples for socket filter", | ||
281 | hists->stats.nr_non_filtered_samples == 2); | ||
282 | TEST_ASSERT_VAL("Unmatched nr hist entries for socket filter", | ||
283 | hists->nr_non_filtered_entries == 2); | ||
284 | TEST_ASSERT_VAL("Unmatched total period for socket filter", | ||
285 | hists->stats.total_non_filtered_period == 200); | ||
286 | |||
287 | /* remove socket filter first */ | ||
288 | hists->socket_filter = -1; | ||
289 | hists__filter_by_socket(hists); | ||
290 | |||
256 | /* now applying all filters at once. */ | 291 | /* now applying all filters at once. */ |
257 | hists->thread_filter = fake_samples[1].thread; | 292 | hists->thread_filter = fake_samples[1].thread; |
258 | hists->dso_filter = fake_samples[1].map->dso; | 293 | hists->dso_filter = fake_samples[1].map->dso; |
diff --git a/tools/perf/tests/make b/tools/perf/tests/make index ba31c4bd441d..2cbd0c6901e3 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make | |||
@@ -44,6 +44,7 @@ make_no_libnuma := NO_LIBNUMA=1 | |||
44 | make_no_libaudit := NO_LIBAUDIT=1 | 44 | make_no_libaudit := NO_LIBAUDIT=1 |
45 | make_no_libbionic := NO_LIBBIONIC=1 | 45 | make_no_libbionic := NO_LIBBIONIC=1 |
46 | make_no_auxtrace := NO_AUXTRACE=1 | 46 | make_no_auxtrace := NO_AUXTRACE=1 |
47 | make_no_libbpf := NO_LIBBPF=1 | ||
47 | make_tags := tags | 48 | make_tags := tags |
48 | make_cscope := cscope | 49 | make_cscope := cscope |
49 | make_help := help | 50 | make_help := help |
@@ -66,7 +67,7 @@ make_static := LDFLAGS=-static | |||
66 | make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 | 67 | make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 |
67 | make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 | 68 | make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 |
68 | make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 | 69 | make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 |
69 | make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 | 70 | make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 |
70 | 71 | ||
71 | # $(run) contains all available tests | 72 | # $(run) contains all available tests |
72 | run := make_pure | 73 | run := make_pure |
@@ -94,6 +95,7 @@ run += make_no_libnuma | |||
94 | run += make_no_libaudit | 95 | run += make_no_libaudit |
95 | run += make_no_libbionic | 96 | run += make_no_libbionic |
96 | run += make_no_auxtrace | 97 | run += make_no_auxtrace |
98 | run += make_no_libbpf | ||
97 | run += make_help | 99 | run += make_help |
98 | run += make_doc | 100 | run += make_doc |
99 | run += make_perf_o | 101 | run += make_perf_o |
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 666b67a4df9d..4495493c9431 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "thread_map.h" | 3 | #include "thread_map.h" |
4 | #include "cpumap.h" | 4 | #include "cpumap.h" |
5 | #include "tests.h" | 5 | #include "tests.h" |
6 | #include <linux/err.h> | ||
6 | 7 | ||
7 | /* | 8 | /* |
8 | * This test will generate random numbers of calls to some getpid syscalls, | 9 | * This test will generate random numbers of calls to some getpid syscalls, |
@@ -65,7 +66,7 @@ int test__basic_mmap(void) | |||
65 | 66 | ||
66 | snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); | 67 | snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]); |
67 | evsels[i] = perf_evsel__newtp("syscalls", name); | 68 | evsels[i] = perf_evsel__newtp("syscalls", name); |
68 | if (evsels[i] == NULL) { | 69 | if (IS_ERR(evsels[i])) { |
69 | pr_debug("perf_evsel__new\n"); | 70 | pr_debug("perf_evsel__new\n"); |
70 | goto out_delete_evlist; | 71 | goto out_delete_evlist; |
71 | } | 72 | } |
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index a572f87e9c8d..2006485a2859 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c | |||
@@ -1,3 +1,5 @@ | |||
1 | #include <api/fs/fs.h> | ||
2 | #include <linux/err.h> | ||
1 | #include "evsel.h" | 3 | #include "evsel.h" |
2 | #include "tests.h" | 4 | #include "tests.h" |
3 | #include "thread_map.h" | 5 | #include "thread_map.h" |
@@ -14,6 +16,7 @@ int test__openat_syscall_event_on_all_cpus(void) | |||
14 | cpu_set_t cpu_set; | 16 | cpu_set_t cpu_set; |
15 | struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); | 17 | struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); |
16 | char sbuf[STRERR_BUFSIZE]; | 18 | char sbuf[STRERR_BUFSIZE]; |
19 | char errbuf[BUFSIZ]; | ||
17 | 20 | ||
18 | if (threads == NULL) { | 21 | if (threads == NULL) { |
19 | pr_debug("thread_map__new\n"); | 22 | pr_debug("thread_map__new\n"); |
@@ -29,13 +32,9 @@ int test__openat_syscall_event_on_all_cpus(void) | |||
29 | CPU_ZERO(&cpu_set); | 32 | CPU_ZERO(&cpu_set); |
30 | 33 | ||
31 | evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); | 34 | evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); |
32 | if (evsel == NULL) { | 35 | if (IS_ERR(evsel)) { |
33 | if (tracefs_configured()) | 36 | tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat"); |
34 | pr_debug("is tracefs mounted on /sys/kernel/tracing?\n"); | 37 | pr_debug("%s\n", errbuf); |
35 | else if (debugfs_configured()) | ||
36 | pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); | ||
37 | else | ||
38 | pr_debug("Neither tracefs or debugfs is enabled in this kernel\n"); | ||
39 | goto out_thread_map_delete; | 38 | goto out_thread_map_delete; |
40 | } | 39 | } |
41 | 40 | ||
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 01a19626c846..5e811cd8f1c3 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <linux/err.h> | ||
1 | #include "perf.h" | 2 | #include "perf.h" |
2 | #include "evlist.h" | 3 | #include "evlist.h" |
3 | #include "evsel.h" | 4 | #include "evsel.h" |
@@ -30,7 +31,7 @@ int test__syscall_openat_tp_fields(void) | |||
30 | } | 31 | } |
31 | 32 | ||
32 | evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); | 33 | evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); |
33 | if (evsel == NULL) { | 34 | if (IS_ERR(evsel)) { |
34 | pr_debug("%s: perf_evsel__newtp\n", __func__); | 35 | pr_debug("%s: perf_evsel__newtp\n", __func__); |
35 | goto out_delete_evlist; | 36 | goto out_delete_evlist; |
36 | } | 37 | } |
@@ -88,7 +89,7 @@ int test__syscall_openat_tp_fields(void) | |||
88 | 89 | ||
89 | err = perf_evsel__parse_sample(evsel, event, &sample); | 90 | err = perf_evsel__parse_sample(evsel, event, &sample); |
90 | if (err) { | 91 | if (err) { |
91 | pr_err("Can't parse sample, err = %d\n", err); | 92 | pr_debug("Can't parse sample, err = %d\n", err); |
92 | goto out_delete_evlist; | 93 | goto out_delete_evlist; |
93 | } | 94 | } |
94 | 95 | ||
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index c9a37bc6b33a..033b54797b8a 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c | |||
@@ -1,3 +1,5 @@ | |||
1 | #include <api/fs/tracing_path.h> | ||
2 | #include <linux/err.h> | ||
1 | #include "thread_map.h" | 3 | #include "thread_map.h" |
2 | #include "evsel.h" | 4 | #include "evsel.h" |
3 | #include "debug.h" | 5 | #include "debug.h" |
@@ -10,6 +12,7 @@ int test__openat_syscall_event(void) | |||
10 | unsigned int nr_openat_calls = 111, i; | 12 | unsigned int nr_openat_calls = 111, i; |
11 | struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); | 13 | struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); |
12 | char sbuf[STRERR_BUFSIZE]; | 14 | char sbuf[STRERR_BUFSIZE]; |
15 | char errbuf[BUFSIZ]; | ||
13 | 16 | ||
14 | if (threads == NULL) { | 17 | if (threads == NULL) { |
15 | pr_debug("thread_map__new\n"); | 18 | pr_debug("thread_map__new\n"); |
@@ -17,13 +20,9 @@ int test__openat_syscall_event(void) | |||
17 | } | 20 | } |
18 | 21 | ||
19 | evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); | 22 | evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); |
20 | if (evsel == NULL) { | 23 | if (IS_ERR(evsel)) { |
21 | if (tracefs_configured()) | 24 | tracing_path__strerror_open_tp(errno, errbuf, sizeof(errbuf), "syscalls", "sys_enter_openat"); |
22 | pr_debug("is tracefs mounted on /sys/kernel/tracing?\n"); | 25 | pr_debug("%s\n", errbuf); |
23 | else if (debugfs_configured()) | ||
24 | pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); | ||
25 | else | ||
26 | pr_debug("Neither tracefs or debugfs is enabled in this kernel\n"); | ||
27 | goto out_thread_map_delete; | 26 | goto out_thread_map_delete; |
28 | } | 27 | } |
29 | 28 | ||
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 9b6b2b6324a1..636d7b42d844 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c | |||
@@ -3,11 +3,11 @@ | |||
3 | #include "evsel.h" | 3 | #include "evsel.h" |
4 | #include "evlist.h" | 4 | #include "evlist.h" |
5 | #include <api/fs/fs.h> | 5 | #include <api/fs/fs.h> |
6 | #include <api/fs/tracefs.h> | ||
7 | #include <api/fs/debugfs.h> | ||
8 | #include "tests.h" | 6 | #include "tests.h" |
9 | #include "debug.h" | 7 | #include "debug.h" |
8 | #include "util.h" | ||
10 | #include <linux/hw_breakpoint.h> | 9 | #include <linux/hw_breakpoint.h> |
10 | #include <api/fs/fs.h> | ||
11 | 11 | ||
12 | #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ | 12 | #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ |
13 | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) | 13 | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) |
@@ -1260,25 +1260,24 @@ test__checkevent_breakpoint_len_rw_modifier(struct perf_evlist *evlist) | |||
1260 | return test__checkevent_breakpoint_rw(evlist); | 1260 | return test__checkevent_breakpoint_rw(evlist); |
1261 | } | 1261 | } |
1262 | 1262 | ||
1263 | static int test__checkevent_precise_max_modifier(struct perf_evlist *evlist) | ||
1264 | { | ||
1265 | struct perf_evsel *evsel = perf_evlist__first(evlist); | ||
1266 | |||
1267 | TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries); | ||
1268 | TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); | ||
1269 | TEST_ASSERT_VAL("wrong config", | ||
1270 | PERF_COUNT_SW_TASK_CLOCK == evsel->attr.config); | ||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1263 | static int count_tracepoints(void) | 1274 | static int count_tracepoints(void) |
1264 | { | 1275 | { |
1265 | char events_path[PATH_MAX]; | ||
1266 | struct dirent *events_ent; | 1276 | struct dirent *events_ent; |
1267 | const char *mountpoint; | ||
1268 | DIR *events_dir; | 1277 | DIR *events_dir; |
1269 | int cnt = 0; | 1278 | int cnt = 0; |
1270 | 1279 | ||
1271 | mountpoint = tracefs_find_mountpoint(); | 1280 | events_dir = opendir(tracing_events_path); |
1272 | if (mountpoint) { | ||
1273 | scnprintf(events_path, PATH_MAX, "%s/events", | ||
1274 | mountpoint); | ||
1275 | } else { | ||
1276 | mountpoint = debugfs_find_mountpoint(); | ||
1277 | scnprintf(events_path, PATH_MAX, "%s/tracing/events", | ||
1278 | mountpoint); | ||
1279 | } | ||
1280 | |||
1281 | events_dir = opendir(events_path); | ||
1282 | 1281 | ||
1283 | TEST_ASSERT_VAL("Can't open events dir", events_dir); | 1282 | TEST_ASSERT_VAL("Can't open events dir", events_dir); |
1284 | 1283 | ||
@@ -1295,7 +1294,7 @@ static int count_tracepoints(void) | |||
1295 | continue; | 1294 | continue; |
1296 | 1295 | ||
1297 | scnprintf(sys_path, PATH_MAX, "%s/%s", | 1296 | scnprintf(sys_path, PATH_MAX, "%s/%s", |
1298 | events_path, events_ent->d_name); | 1297 | tracing_events_path, events_ent->d_name); |
1299 | 1298 | ||
1300 | sys_dir = opendir(sys_path); | 1299 | sys_dir = opendir(sys_path); |
1301 | TEST_ASSERT_VAL("Can't open sys dir", sys_dir); | 1300 | TEST_ASSERT_VAL("Can't open sys dir", sys_dir); |
@@ -1575,6 +1574,11 @@ static struct evlist_test test__events[] = { | |||
1575 | .check = test__checkevent_exclude_idle_modifier_1, | 1574 | .check = test__checkevent_exclude_idle_modifier_1, |
1576 | .id = 46, | 1575 | .id = 46, |
1577 | }, | 1576 | }, |
1577 | { | ||
1578 | .name = "task-clock:P,cycles", | ||
1579 | .check = test__checkevent_precise_max_modifier, | ||
1580 | .id = 47, | ||
1581 | }, | ||
1578 | }; | 1582 | }; |
1579 | 1583 | ||
1580 | static struct evlist_test test__events_pmu[] = { | 1584 | static struct evlist_test test__events_pmu[] = { |
@@ -1750,6 +1754,17 @@ static int test_pmu_events(void) | |||
1750 | return ret; | 1754 | return ret; |
1751 | } | 1755 | } |
1752 | 1756 | ||
1757 | static void debug_warn(const char *warn, va_list params) | ||
1758 | { | ||
1759 | char msg[1024]; | ||
1760 | |||
1761 | if (!verbose) | ||
1762 | return; | ||
1763 | |||
1764 | vsnprintf(msg, sizeof(msg), warn, params); | ||
1765 | fprintf(stderr, " Warning: %s\n", msg); | ||
1766 | } | ||
1767 | |||
1753 | int test__parse_events(void) | 1768 | int test__parse_events(void) |
1754 | { | 1769 | { |
1755 | int ret1, ret2 = 0; | 1770 | int ret1, ret2 = 0; |
@@ -1761,6 +1776,8 @@ do { \ | |||
1761 | ret2 = ret1; \ | 1776 | ret2 = ret1; \ |
1762 | } while (0) | 1777 | } while (0) |
1763 | 1778 | ||
1779 | set_warning_routine(debug_warn); | ||
1780 | |||
1764 | TEST_EVENTS(test__events); | 1781 | TEST_EVENTS(test__events); |
1765 | 1782 | ||
1766 | if (test_pmu()) | 1783 | if (test_pmu()) |
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 1aa21c90731b..5b83f56a3b6f 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c | |||
@@ -34,6 +34,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
34 | .disabled = 1, | 34 | .disabled = 1, |
35 | .freq = 1, | 35 | .freq = 1, |
36 | }; | 36 | }; |
37 | struct cpu_map *cpus; | ||
38 | struct thread_map *threads; | ||
37 | 39 | ||
38 | attr.sample_freq = 500; | 40 | attr.sample_freq = 500; |
39 | 41 | ||
@@ -50,14 +52,19 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
50 | } | 52 | } |
51 | perf_evlist__add(evlist, evsel); | 53 | perf_evlist__add(evlist, evsel); |
52 | 54 | ||
53 | evlist->cpus = cpu_map__dummy_new(); | 55 | cpus = cpu_map__dummy_new(); |
54 | evlist->threads = thread_map__new_by_tid(getpid()); | 56 | threads = thread_map__new_by_tid(getpid()); |
55 | if (!evlist->cpus || !evlist->threads) { | 57 | if (!cpus || !threads) { |
56 | err = -ENOMEM; | 58 | err = -ENOMEM; |
57 | pr_debug("Not enough memory to create thread/cpu maps\n"); | 59 | pr_debug("Not enough memory to create thread/cpu maps\n"); |
58 | goto out_delete_evlist; | 60 | goto out_free_maps; |
59 | } | 61 | } |
60 | 62 | ||
63 | perf_evlist__set_maps(evlist, cpus, threads); | ||
64 | |||
65 | cpus = NULL; | ||
66 | threads = NULL; | ||
67 | |||
61 | if (perf_evlist__open(evlist)) { | 68 | if (perf_evlist__open(evlist)) { |
62 | const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate"; | 69 | const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate"; |
63 | 70 | ||
@@ -107,6 +114,9 @@ next_event: | |||
107 | err = -1; | 114 | err = -1; |
108 | } | 115 | } |
109 | 116 | ||
117 | out_free_maps: | ||
118 | cpu_map__put(cpus); | ||
119 | thread_map__put(threads); | ||
110 | out_delete_evlist: | 120 | out_delete_evlist: |
111 | perf_evlist__delete(evlist); | 121 | perf_evlist__delete(evlist); |
112 | return err; | 122 | return err; |
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index 3a8fedef83bc..add16385f13e 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c | |||
@@ -43,6 +43,8 @@ int test__task_exit(void) | |||
43 | }; | 43 | }; |
44 | const char *argv[] = { "true", NULL }; | 44 | const char *argv[] = { "true", NULL }; |
45 | char sbuf[STRERR_BUFSIZE]; | 45 | char sbuf[STRERR_BUFSIZE]; |
46 | struct cpu_map *cpus; | ||
47 | struct thread_map *threads; | ||
46 | 48 | ||
47 | signal(SIGCHLD, sig_handler); | 49 | signal(SIGCHLD, sig_handler); |
48 | 50 | ||
@@ -58,14 +60,19 @@ int test__task_exit(void) | |||
58 | * perf_evlist__prepare_workload we'll fill in the only thread | 60 | * perf_evlist__prepare_workload we'll fill in the only thread |
59 | * we're monitoring, the one forked there. | 61 | * we're monitoring, the one forked there. |
60 | */ | 62 | */ |
61 | evlist->cpus = cpu_map__dummy_new(); | 63 | cpus = cpu_map__dummy_new(); |
62 | evlist->threads = thread_map__new_by_tid(-1); | 64 | threads = thread_map__new_by_tid(-1); |
63 | if (!evlist->cpus || !evlist->threads) { | 65 | if (!cpus || !threads) { |
64 | err = -ENOMEM; | 66 | err = -ENOMEM; |
65 | pr_debug("Not enough memory to create thread/cpu maps\n"); | 67 | pr_debug("Not enough memory to create thread/cpu maps\n"); |
66 | goto out_delete_evlist; | 68 | goto out_free_maps; |
67 | } | 69 | } |
68 | 70 | ||
71 | perf_evlist__set_maps(evlist, cpus, threads); | ||
72 | |||
73 | cpus = NULL; | ||
74 | threads = NULL; | ||
75 | |||
69 | err = perf_evlist__prepare_workload(evlist, &target, argv, false, | 76 | err = perf_evlist__prepare_workload(evlist, &target, argv, false, |
70 | workload_exec_failed_signal); | 77 | workload_exec_failed_signal); |
71 | if (err < 0) { | 78 | if (err < 0) { |
@@ -114,6 +121,9 @@ retry: | |||
114 | err = -1; | 121 | err = -1; |
115 | } | 122 | } |
116 | 123 | ||
124 | out_free_maps: | ||
125 | cpu_map__put(cpus); | ||
126 | thread_map__put(threads); | ||
117 | out_delete_evlist: | 127 | out_delete_evlist: |
118 | perf_evlist__delete(evlist); | 128 | perf_evlist__delete(evlist); |
119 | return err; | 129 | return err; |
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index bf113a247987..c80486969f83 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
@@ -24,13 +24,17 @@ enum { | |||
24 | TEST_SKIP = -2, | 24 | TEST_SKIP = -2, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | struct test { | ||
28 | const char *desc; | ||
29 | int (*func)(void); | ||
30 | }; | ||
31 | |||
27 | /* Tests */ | 32 | /* Tests */ |
28 | int test__vmlinux_matches_kallsyms(void); | 33 | int test__vmlinux_matches_kallsyms(void); |
29 | int test__openat_syscall_event(void); | 34 | int test__openat_syscall_event(void); |
30 | int test__openat_syscall_event_on_all_cpus(void); | 35 | int test__openat_syscall_event_on_all_cpus(void); |
31 | int test__basic_mmap(void); | 36 | int test__basic_mmap(void); |
32 | int test__PERF_RECORD(void); | 37 | int test__PERF_RECORD(void); |
33 | int test__rdpmc(void); | ||
34 | int test__perf_evsel__roundtrip_name_test(void); | 38 | int test__perf_evsel__roundtrip_name_test(void); |
35 | int test__perf_evsel__tp_sched_test(void); | 39 | int test__perf_evsel__tp_sched_test(void); |
36 | int test__syscall_openat_tp_fields(void); | 40 | int test__syscall_openat_tp_fields(void); |
@@ -46,7 +50,6 @@ int test__bp_signal(void); | |||
46 | int test__bp_signal_overflow(void); | 50 | int test__bp_signal_overflow(void); |
47 | int test__task_exit(void); | 51 | int test__task_exit(void); |
48 | int test__sw_clock_freq(void); | 52 | int test__sw_clock_freq(void); |
49 | int test__perf_time_to_tsc(void); | ||
50 | int test__code_reading(void); | 53 | int test__code_reading(void); |
51 | int test__sample_parsing(void); | 54 | int test__sample_parsing(void); |
52 | int test__keep_tracking(void); | 55 | int test__keep_tracking(void); |
@@ -63,8 +66,9 @@ int test__fdarray__add(void); | |||
63 | int test__kmod_path__parse(void); | 66 | int test__kmod_path__parse(void); |
64 | int test__thread_map(void); | 67 | int test__thread_map(void); |
65 | int test__llvm(void); | 68 | int test__llvm(void); |
69 | int test_session_topology(void); | ||
66 | 70 | ||
67 | #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__) | 71 | #if defined(__arm__) || defined(__aarch64__) |
68 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 72 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
69 | struct thread; | 73 | struct thread; |
70 | struct perf_sample; | 74 | struct perf_sample; |
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c new file mode 100644 index 000000000000..f5bb096c3bd9 --- /dev/null +++ b/tools/perf/tests/topology.c | |||
@@ -0,0 +1,115 @@ | |||
1 | #include <string.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <stdio.h> | ||
4 | #include "tests.h" | ||
5 | #include "util.h" | ||
6 | #include "session.h" | ||
7 | #include "evlist.h" | ||
8 | #include "debug.h" | ||
9 | |||
10 | #define TEMPL "/tmp/perf-test-XXXXXX" | ||
11 | #define DATA_SIZE 10 | ||
12 | |||
13 | static int get_temp(char *path) | ||
14 | { | ||
15 | int fd; | ||
16 | |||
17 | strcpy(path, TEMPL); | ||
18 | |||
19 | fd = mkstemp(path); | ||
20 | if (fd < 0) { | ||
21 | perror("mkstemp failed"); | ||
22 | return -1; | ||
23 | } | ||
24 | |||
25 | close(fd); | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | static int session_write_header(char *path) | ||
30 | { | ||
31 | struct perf_session *session; | ||
32 | struct perf_data_file file = { | ||
33 | .path = path, | ||
34 | .mode = PERF_DATA_MODE_WRITE, | ||
35 | }; | ||
36 | |||
37 | session = perf_session__new(&file, false, NULL); | ||
38 | TEST_ASSERT_VAL("can't get session", session); | ||
39 | |||
40 | session->evlist = perf_evlist__new_default(); | ||
41 | TEST_ASSERT_VAL("can't get evlist", session->evlist); | ||
42 | |||
43 | perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); | ||
44 | perf_header__set_feat(&session->header, HEADER_NRCPUS); | ||
45 | |||
46 | session->header.data_size += DATA_SIZE; | ||
47 | |||
48 | TEST_ASSERT_VAL("failed to write header", | ||
49 | !perf_session__write_header(session, session->evlist, file.fd, true)); | ||
50 | |||
51 | perf_session__delete(session); | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int check_cpu_topology(char *path, struct cpu_map *map) | ||
57 | { | ||
58 | struct perf_session *session; | ||
59 | struct perf_data_file file = { | ||
60 | .path = path, | ||
61 | .mode = PERF_DATA_MODE_READ, | ||
62 | }; | ||
63 | int i; | ||
64 | |||
65 | session = perf_session__new(&file, false, NULL); | ||
66 | TEST_ASSERT_VAL("can't get session", session); | ||
67 | |||
68 | for (i = 0; i < session->header.env.nr_cpus_online; i++) { | ||
69 | pr_debug("CPU %d, core %d, socket %d\n", i, | ||
70 | session->header.env.cpu[i].core_id, | ||
71 | session->header.env.cpu[i].socket_id); | ||
72 | } | ||
73 | |||
74 | for (i = 0; i < map->nr; i++) { | ||
75 | TEST_ASSERT_VAL("Core ID doesn't match", | ||
76 | (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i, NULL) & 0xffff))); | ||
77 | |||
78 | TEST_ASSERT_VAL("Socket ID doesn't match", | ||
79 | (session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i, NULL))); | ||
80 | } | ||
81 | |||
82 | perf_session__delete(session); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | int test_session_topology(void) | ||
88 | { | ||
89 | char path[PATH_MAX]; | ||
90 | struct cpu_map *map; | ||
91 | int ret = -1; | ||
92 | |||
93 | TEST_ASSERT_VAL("can't get templ file", !get_temp(path)); | ||
94 | |||
95 | pr_debug("templ file: %s\n", path); | ||
96 | |||
97 | if (session_write_header(path)) | ||
98 | goto free_path; | ||
99 | |||
100 | map = cpu_map__new(NULL); | ||
101 | if (map == NULL) { | ||
102 | pr_debug("failed to get system cpumap\n"); | ||
103 | goto free_path; | ||
104 | } | ||
105 | |||
106 | if (check_cpu_topology(path, map)) | ||
107 | goto free_map; | ||
108 | ret = 0; | ||
109 | |||
110 | free_map: | ||
111 | cpu_map__put(map); | ||
112 | free_path: | ||
113 | unlink(path); | ||
114 | return ret; | ||
115 | } | ||
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c index b34c5fc829ae..d677e018e504 100644 --- a/tools/perf/tests/vmlinux-kallsyms.c +++ b/tools/perf/tests/vmlinux-kallsyms.c | |||
@@ -68,7 +68,7 @@ int test__vmlinux_matches_kallsyms(void) | |||
68 | * to see if the running kernel was relocated by checking if it has the | 68 | * to see if the running kernel was relocated by checking if it has the |
69 | * same value in the vmlinux file we load. | 69 | * same value in the vmlinux file we load. |
70 | */ | 70 | */ |
71 | kallsyms_map = machine__kernel_map(&kallsyms, type); | 71 | kallsyms_map = machine__kernel_map(&kallsyms); |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * Step 5: | 74 | * Step 5: |
@@ -80,7 +80,7 @@ int test__vmlinux_matches_kallsyms(void) | |||
80 | goto out; | 80 | goto out; |
81 | } | 81 | } |
82 | 82 | ||
83 | vmlinux_map = machine__kernel_map(&vmlinux, type); | 83 | vmlinux_map = machine__kernel_map(&vmlinux); |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Step 6: | 86 | * Step 6: |
diff --git a/tools/perf/trace/strace/groups/file b/tools/perf/trace/strace/groups/file index 62378a899d79..722e25d200bf 100644 --- a/tools/perf/trace/strace/groups/file +++ b/tools/perf/trace/strace/groups/file | |||
@@ -9,6 +9,7 @@ mkdir | |||
9 | open | 9 | open |
10 | openat | 10 | openat |
11 | quotactl | 11 | quotactl |
12 | read | ||
12 | readlink | 13 | readlink |
13 | rename | 14 | rename |
14 | rmdir | 15 | rmdir |
@@ -16,3 +17,4 @@ stat | |||
16 | statfs | 17 | statfs |
17 | symlink | 18 | symlink |
18 | unlink | 19 | unlink |
20 | write | ||
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index c6c7e5189214..e9703c0829f1 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c | |||
@@ -393,6 +393,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) | |||
393 | 393 | ||
394 | if (browser->use_navkeypressed && !browser->navkeypressed) { | 394 | if (browser->use_navkeypressed && !browser->navkeypressed) { |
395 | if (key == K_DOWN || key == K_UP || | 395 | if (key == K_DOWN || key == K_UP || |
396 | (browser->columns && (key == K_LEFT || key == K_RIGHT)) || | ||
396 | key == K_PGDN || key == K_PGUP || | 397 | key == K_PGDN || key == K_PGUP || |
397 | key == K_HOME || key == K_END || | 398 | key == K_HOME || key == K_END || |
398 | key == ' ') { | 399 | key == ' ') { |
@@ -421,6 +422,18 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) | |||
421 | browser->seek(browser, -1, SEEK_CUR); | 422 | browser->seek(browser, -1, SEEK_CUR); |
422 | } | 423 | } |
423 | break; | 424 | break; |
425 | case K_RIGHT: | ||
426 | if (!browser->columns) | ||
427 | goto out; | ||
428 | if (browser->horiz_scroll < browser->columns - 1) | ||
429 | ++browser->horiz_scroll; | ||
430 | break; | ||
431 | case K_LEFT: | ||
432 | if (!browser->columns) | ||
433 | goto out; | ||
434 | if (browser->horiz_scroll != 0) | ||
435 | --browser->horiz_scroll; | ||
436 | break; | ||
424 | case K_PGDN: | 437 | case K_PGDN: |
425 | case ' ': | 438 | case ' ': |
426 | if (browser->top_idx + browser->rows > browser->nr_entries - 1) | 439 | if (browser->top_idx + browser->rows > browser->nr_entries - 1) |
@@ -459,6 +472,7 @@ int ui_browser__run(struct ui_browser *browser, int delay_secs) | |||
459 | browser->seek(browser, -offset, SEEK_END); | 472 | browser->seek(browser, -offset, SEEK_END); |
460 | break; | 473 | break; |
461 | default: | 474 | default: |
475 | out: | ||
462 | return key; | 476 | return key; |
463 | } | 477 | } |
464 | } | 478 | } |
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index f3cef564de02..01781de59532 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h | |||
@@ -14,7 +14,7 @@ | |||
14 | struct ui_browser { | 14 | struct ui_browser { |
15 | u64 index, top_idx; | 15 | u64 index, top_idx; |
16 | void *top, *entries; | 16 | void *top, *entries; |
17 | u16 y, x, width, height, rows; | 17 | u16 y, x, width, height, rows, columns, horiz_scroll; |
18 | int current_color; | 18 | int current_color; |
19 | void *priv; | 19 | void *priv; |
20 | const char *title; | 20 | const char *title; |
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 29739b347599..d4d7cc27252f 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c | |||
@@ -768,8 +768,8 @@ static int annotate_browser__run(struct annotate_browser *browser, | |||
768 | "UP/DOWN/PGUP\n" | 768 | "UP/DOWN/PGUP\n" |
769 | "PGDN/SPACE Navigate\n" | 769 | "PGDN/SPACE Navigate\n" |
770 | "q/ESC/CTRL+C Exit\n\n" | 770 | "q/ESC/CTRL+C Exit\n\n" |
771 | "-> Go to target\n" | 771 | "ENTER Go to target\n" |
772 | "<- Exit\n" | 772 | "ESC Exit\n" |
773 | "H Cycle thru hottest instructions\n" | 773 | "H Cycle thru hottest instructions\n" |
774 | "j Toggle showing jump to target arrows\n" | 774 | "j Toggle showing jump to target arrows\n" |
775 | "J Toggle showing number of jump sources on targets\n" | 775 | "J Toggle showing number of jump sources on targets\n" |
@@ -1056,7 +1056,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, | |||
1056 | goto out_free_offsets; | 1056 | goto out_free_offsets; |
1057 | } | 1057 | } |
1058 | 1058 | ||
1059 | ui_helpline__push("Press <- or ESC to exit"); | 1059 | ui_helpline__push("Press ESC to exit"); |
1060 | 1060 | ||
1061 | notes = symbol__annotation(sym); | 1061 | notes = symbol__annotation(sym); |
1062 | browser.start = map__rip_2objdump(map, sym->start); | 1062 | browser.start = map__rip_2objdump(map, sym->start); |
@@ -1125,8 +1125,8 @@ static struct annotate_config { | |||
1125 | ANNOTATE_CFG(jump_arrows), | 1125 | ANNOTATE_CFG(jump_arrows), |
1126 | ANNOTATE_CFG(show_linenr), | 1126 | ANNOTATE_CFG(show_linenr), |
1127 | ANNOTATE_CFG(show_nr_jumps), | 1127 | ANNOTATE_CFG(show_nr_jumps), |
1128 | ANNOTATE_CFG(use_offset), | ||
1129 | ANNOTATE_CFG(show_total_period), | 1128 | ANNOTATE_CFG(show_total_period), |
1129 | ANNOTATE_CFG(use_offset), | ||
1130 | }; | 1130 | }; |
1131 | 1131 | ||
1132 | #undef ANNOTATE_CFG | 1132 | #undef ANNOTATE_CFG |
@@ -1152,9 +1152,9 @@ static int annotate__config(const char *var, const char *value, | |||
1152 | sizeof(struct annotate_config), annotate_config__cmp); | 1152 | sizeof(struct annotate_config), annotate_config__cmp); |
1153 | 1153 | ||
1154 | if (cfg == NULL) | 1154 | if (cfg == NULL) |
1155 | return -1; | 1155 | ui__warning("%s variable unknown, ignoring...", var); |
1156 | 1156 | else | |
1157 | *cfg->value = perf_config_bool(name, value); | 1157 | *cfg->value = perf_config_bool(name, value); |
1158 | return 0; | 1158 | return 0; |
1159 | } | 1159 | } |
1160 | 1160 | ||
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index cf86f2d3a5e7..e5afb8936040 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -784,11 +784,12 @@ static int hist_browser__show_entry(struct hist_browser *browser, | |||
784 | .size = sizeof(s), | 784 | .size = sizeof(s), |
785 | .ptr = &arg, | 785 | .ptr = &arg, |
786 | }; | 786 | }; |
787 | int column = 0; | ||
787 | 788 | ||
788 | hist_browser__gotorc(browser, row, 0); | 789 | hist_browser__gotorc(browser, row, 0); |
789 | 790 | ||
790 | perf_hpp__for_each_format(fmt) { | 791 | perf_hpp__for_each_format(fmt) { |
791 | if (perf_hpp__should_skip(fmt)) | 792 | if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll) |
792 | continue; | 793 | continue; |
793 | 794 | ||
794 | if (current_entry && browser->b.navkeypressed) { | 795 | if (current_entry && browser->b.navkeypressed) { |
@@ -861,14 +862,16 @@ static int advance_hpp_check(struct perf_hpp *hpp, int inc) | |||
861 | return hpp->size <= 0; | 862 | return hpp->size <= 0; |
862 | } | 863 | } |
863 | 864 | ||
864 | static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists) | 865 | static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf, size_t size) |
865 | { | 866 | { |
867 | struct hists *hists = browser->hists; | ||
866 | struct perf_hpp dummy_hpp = { | 868 | struct perf_hpp dummy_hpp = { |
867 | .buf = buf, | 869 | .buf = buf, |
868 | .size = size, | 870 | .size = size, |
869 | }; | 871 | }; |
870 | struct perf_hpp_fmt *fmt; | 872 | struct perf_hpp_fmt *fmt; |
871 | size_t ret = 0; | 873 | size_t ret = 0; |
874 | int column = 0; | ||
872 | 875 | ||
873 | if (symbol_conf.use_callchain) { | 876 | if (symbol_conf.use_callchain) { |
874 | ret = scnprintf(buf, size, " "); | 877 | ret = scnprintf(buf, size, " "); |
@@ -877,7 +880,7 @@ static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists) | |||
877 | } | 880 | } |
878 | 881 | ||
879 | perf_hpp__for_each_format(fmt) { | 882 | perf_hpp__for_each_format(fmt) { |
880 | if (perf_hpp__should_skip(fmt)) | 883 | if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll) |
881 | continue; | 884 | continue; |
882 | 885 | ||
883 | ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); | 886 | ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); |
@@ -896,7 +899,7 @@ static void hist_browser__show_headers(struct hist_browser *browser) | |||
896 | { | 899 | { |
897 | char headers[1024]; | 900 | char headers[1024]; |
898 | 901 | ||
899 | hists__scnprintf_headers(headers, sizeof(headers), browser->hists); | 902 | hists_browser__scnprintf_headers(browser, headers, sizeof(headers)); |
900 | ui_browser__gotorc(&browser->b, 0, 0); | 903 | ui_browser__gotorc(&browser->b, 0, 0); |
901 | ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); | 904 | ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); |
902 | ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); | 905 | ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); |
@@ -1261,6 +1264,7 @@ static int hists__browser_title(struct hists *hists, | |||
1261 | int printed; | 1264 | int printed; |
1262 | const struct dso *dso = hists->dso_filter; | 1265 | const struct dso *dso = hists->dso_filter; |
1263 | const struct thread *thread = hists->thread_filter; | 1266 | const struct thread *thread = hists->thread_filter; |
1267 | int socket_id = hists->socket_filter; | ||
1264 | unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; | 1268 | unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; |
1265 | u64 nr_events = hists->stats.total_period; | 1269 | u64 nr_events = hists->stats.total_period; |
1266 | struct perf_evsel *evsel = hists_to_evsel(hists); | 1270 | struct perf_evsel *evsel = hists_to_evsel(hists); |
@@ -1314,6 +1318,9 @@ static int hists__browser_title(struct hists *hists, | |||
1314 | if (dso) | 1318 | if (dso) |
1315 | printed += scnprintf(bf + printed, size - printed, | 1319 | printed += scnprintf(bf + printed, size - printed, |
1316 | ", DSO: %s", dso->short_name); | 1320 | ", DSO: %s", dso->short_name); |
1321 | if (socket_id > -1) | ||
1322 | printed += scnprintf(bf + printed, size - printed, | ||
1323 | ", Processor Socket: %d", socket_id); | ||
1317 | if (!is_report_browser(hbt)) { | 1324 | if (!is_report_browser(hbt)) { |
1318 | struct perf_top *top = hbt->arg; | 1325 | struct perf_top *top = hbt->arg; |
1319 | 1326 | ||
@@ -1425,6 +1432,7 @@ struct popup_action { | |||
1425 | struct thread *thread; | 1432 | struct thread *thread; |
1426 | struct dso *dso; | 1433 | struct dso *dso; |
1427 | struct map_symbol ms; | 1434 | struct map_symbol ms; |
1435 | int socket; | ||
1428 | 1436 | ||
1429 | int (*fn)(struct hist_browser *browser, struct popup_action *act); | 1437 | int (*fn)(struct hist_browser *browser, struct popup_action *act); |
1430 | }; | 1438 | }; |
@@ -1437,7 +1445,7 @@ do_annotate(struct hist_browser *browser, struct popup_action *act) | |||
1437 | struct hist_entry *he; | 1445 | struct hist_entry *he; |
1438 | int err; | 1446 | int err; |
1439 | 1447 | ||
1440 | if (!objdump_path && perf_session_env__lookup_objdump(browser->env)) | 1448 | if (!objdump_path && perf_env__lookup_objdump(browser->env)) |
1441 | return 0; | 1449 | return 0; |
1442 | 1450 | ||
1443 | notes = symbol__annotation(act->ms.sym); | 1451 | notes = symbol__annotation(act->ms.sym); |
@@ -1488,7 +1496,7 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act) | |||
1488 | thread__zput(browser->hists->thread_filter); | 1496 | thread__zput(browser->hists->thread_filter); |
1489 | ui_helpline__pop(); | 1497 | ui_helpline__pop(); |
1490 | } else { | 1498 | } else { |
1491 | ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", | 1499 | ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"", |
1492 | thread->comm_set ? thread__comm_str(thread) : "", | 1500 | thread->comm_set ? thread__comm_str(thread) : "", |
1493 | thread->tid); | 1501 | thread->tid); |
1494 | browser->hists->thread_filter = thread__get(thread); | 1502 | browser->hists->thread_filter = thread__get(thread); |
@@ -1522,7 +1530,7 @@ add_thread_opt(struct hist_browser *browser, struct popup_action *act, | |||
1522 | static int | 1530 | static int |
1523 | do_zoom_dso(struct hist_browser *browser, struct popup_action *act) | 1531 | do_zoom_dso(struct hist_browser *browser, struct popup_action *act) |
1524 | { | 1532 | { |
1525 | struct dso *dso = act->dso; | 1533 | struct map *map = act->ms.map; |
1526 | 1534 | ||
1527 | if (browser->hists->dso_filter) { | 1535 | if (browser->hists->dso_filter) { |
1528 | pstack__remove(browser->pstack, &browser->hists->dso_filter); | 1536 | pstack__remove(browser->pstack, &browser->hists->dso_filter); |
@@ -1530,11 +1538,11 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act) | |||
1530 | browser->hists->dso_filter = NULL; | 1538 | browser->hists->dso_filter = NULL; |
1531 | ui_helpline__pop(); | 1539 | ui_helpline__pop(); |
1532 | } else { | 1540 | } else { |
1533 | if (dso == NULL) | 1541 | if (map == NULL) |
1534 | return 0; | 1542 | return 0; |
1535 | ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", | 1543 | ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s DSO\"", |
1536 | dso->kernel ? "the Kernel" : dso->short_name); | 1544 | __map__is_kernel(map) ? "the Kernel" : map->dso->short_name); |
1537 | browser->hists->dso_filter = dso; | 1545 | browser->hists->dso_filter = map->dso; |
1538 | perf_hpp__set_elide(HISTC_DSO, true); | 1546 | perf_hpp__set_elide(HISTC_DSO, true); |
1539 | pstack__push(browser->pstack, &browser->hists->dso_filter); | 1547 | pstack__push(browser->pstack, &browser->hists->dso_filter); |
1540 | } | 1548 | } |
@@ -1546,17 +1554,18 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act) | |||
1546 | 1554 | ||
1547 | static int | 1555 | static int |
1548 | add_dso_opt(struct hist_browser *browser, struct popup_action *act, | 1556 | add_dso_opt(struct hist_browser *browser, struct popup_action *act, |
1549 | char **optstr, struct dso *dso) | 1557 | char **optstr, struct map *map) |
1550 | { | 1558 | { |
1551 | if (dso == NULL) | 1559 | if (map == NULL) |
1552 | return 0; | 1560 | return 0; |
1553 | 1561 | ||
1554 | if (asprintf(optstr, "Zoom %s %s DSO", | 1562 | if (asprintf(optstr, "Zoom %s %s DSO", |
1555 | browser->hists->dso_filter ? "out of" : "into", | 1563 | browser->hists->dso_filter ? "out of" : "into", |
1556 | dso->kernel ? "the Kernel" : dso->short_name) < 0) | 1564 | __map__is_kernel(map) ? "the Kernel" : map->dso->short_name) < 0) |
1557 | return 0; | 1565 | return 0; |
1558 | 1566 | ||
1559 | act->dso = dso; | 1567 | act->ms.map = map; |
1568 | act->dso = map->dso; | ||
1560 | act->fn = do_zoom_dso; | 1569 | act->fn = do_zoom_dso; |
1561 | return 1; | 1570 | return 1; |
1562 | } | 1571 | } |
@@ -1672,6 +1681,41 @@ add_exit_opt(struct hist_browser *browser __maybe_unused, | |||
1672 | return 1; | 1681 | return 1; |
1673 | } | 1682 | } |
1674 | 1683 | ||
1684 | static int | ||
1685 | do_zoom_socket(struct hist_browser *browser, struct popup_action *act) | ||
1686 | { | ||
1687 | if (browser->hists->socket_filter > -1) { | ||
1688 | pstack__remove(browser->pstack, &browser->hists->socket_filter); | ||
1689 | browser->hists->socket_filter = -1; | ||
1690 | perf_hpp__set_elide(HISTC_SOCKET, false); | ||
1691 | } else { | ||
1692 | browser->hists->socket_filter = act->socket; | ||
1693 | perf_hpp__set_elide(HISTC_SOCKET, true); | ||
1694 | pstack__push(browser->pstack, &browser->hists->socket_filter); | ||
1695 | } | ||
1696 | |||
1697 | hists__filter_by_socket(browser->hists); | ||
1698 | hist_browser__reset(browser); | ||
1699 | return 0; | ||
1700 | } | ||
1701 | |||
1702 | static int | ||
1703 | add_socket_opt(struct hist_browser *browser, struct popup_action *act, | ||
1704 | char **optstr, int socket_id) | ||
1705 | { | ||
1706 | if (socket_id < 0) | ||
1707 | return 0; | ||
1708 | |||
1709 | if (asprintf(optstr, "Zoom %s Processor Socket %d", | ||
1710 | (browser->hists->socket_filter > -1) ? "out of" : "into", | ||
1711 | socket_id) < 0) | ||
1712 | return 0; | ||
1713 | |||
1714 | act->socket = socket_id; | ||
1715 | act->fn = do_zoom_socket; | ||
1716 | return 1; | ||
1717 | } | ||
1718 | |||
1675 | static void hist_browser__update_nr_entries(struct hist_browser *hb) | 1719 | static void hist_browser__update_nr_entries(struct hist_browser *hb) |
1676 | { | 1720 | { |
1677 | u64 nr_entries = 0; | 1721 | u64 nr_entries = 0; |
@@ -1717,14 +1761,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1717 | "For multiple event sessions:\n\n" \ | 1761 | "For multiple event sessions:\n\n" \ |
1718 | "TAB/UNTAB Switch events\n\n" \ | 1762 | "TAB/UNTAB Switch events\n\n" \ |
1719 | "For symbolic views (--sort has sym):\n\n" \ | 1763 | "For symbolic views (--sort has sym):\n\n" \ |
1720 | "-> Zoom into DSO/Threads & Annotate current symbol\n" \ | 1764 | "ENTER Zoom into DSO/Threads & Annotate current symbol\n" \ |
1721 | "<- Zoom out\n" \ | 1765 | "ESC Zoom out\n" \ |
1722 | "a Annotate current symbol\n" \ | 1766 | "a Annotate current symbol\n" \ |
1723 | "C Collapse all callchains\n" \ | 1767 | "C Collapse all callchains\n" \ |
1724 | "d Zoom into current DSO\n" \ | 1768 | "d Zoom into current DSO\n" \ |
1725 | "E Expand all callchains\n" \ | 1769 | "E Expand all callchains\n" \ |
1726 | "F Toggle percentage of filtered entries\n" \ | 1770 | "F Toggle percentage of filtered entries\n" \ |
1727 | "H Display column headers\n" \ | 1771 | "H Display column headers\n" \ |
1772 | "m Display context menu\n" \ | ||
1773 | "S Zoom into current Processor Socket\n" \ | ||
1728 | 1774 | ||
1729 | /* help messages are sorted by lexical order of the hotkey */ | 1775 | /* help messages are sorted by lexical order of the hotkey */ |
1730 | const char report_help[] = HIST_BROWSER_HELP_COMMON | 1776 | const char report_help[] = HIST_BROWSER_HELP_COMMON |
@@ -1755,7 +1801,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1755 | hist_browser__update_nr_entries(browser); | 1801 | hist_browser__update_nr_entries(browser); |
1756 | } | 1802 | } |
1757 | 1803 | ||
1758 | browser->pstack = pstack__new(2); | 1804 | browser->pstack = pstack__new(3); |
1759 | if (browser->pstack == NULL) | 1805 | if (browser->pstack == NULL) |
1760 | goto out; | 1806 | goto out; |
1761 | 1807 | ||
@@ -1764,8 +1810,17 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1764 | memset(options, 0, sizeof(options)); | 1810 | memset(options, 0, sizeof(options)); |
1765 | memset(actions, 0, sizeof(actions)); | 1811 | memset(actions, 0, sizeof(actions)); |
1766 | 1812 | ||
1767 | perf_hpp__for_each_format(fmt) | 1813 | perf_hpp__for_each_format(fmt) { |
1768 | perf_hpp__reset_width(fmt, hists); | 1814 | perf_hpp__reset_width(fmt, hists); |
1815 | /* | ||
1816 | * This is done just once, and activates the horizontal scrolling | ||
1817 | * code in the ui_browser code, it would be better to have a the | ||
1818 | * counter in the perf_hpp code, but I couldn't find doing it here | ||
1819 | * works, FIXME by setting this in hist_browser__new, for now, be | ||
1820 | * clever 8-) | ||
1821 | */ | ||
1822 | ++browser->b.columns; | ||
1823 | } | ||
1769 | 1824 | ||
1770 | if (symbol_conf.col_width_list_str) | 1825 | if (symbol_conf.col_width_list_str) |
1771 | perf_hpp__set_user_width(symbol_conf.col_width_list_str); | 1826 | perf_hpp__set_user_width(symbol_conf.col_width_list_str); |
@@ -1773,7 +1828,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1773 | while (1) { | 1828 | while (1) { |
1774 | struct thread *thread = NULL; | 1829 | struct thread *thread = NULL; |
1775 | struct dso *dso = NULL; | 1830 | struct dso *dso = NULL; |
1831 | struct map *map = NULL; | ||
1776 | int choice = 0; | 1832 | int choice = 0; |
1833 | int socked_id = -1; | ||
1777 | 1834 | ||
1778 | nr_options = 0; | 1835 | nr_options = 0; |
1779 | 1836 | ||
@@ -1781,7 +1838,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1781 | 1838 | ||
1782 | if (browser->he_selection != NULL) { | 1839 | if (browser->he_selection != NULL) { |
1783 | thread = hist_browser__selected_thread(browser); | 1840 | thread = hist_browser__selected_thread(browser); |
1784 | dso = browser->selection->map ? browser->selection->map->dso : NULL; | 1841 | map = browser->selection->map; |
1842 | if (map) | ||
1843 | dso = map->dso; | ||
1844 | socked_id = browser->he_selection->socket; | ||
1785 | } | 1845 | } |
1786 | switch (key) { | 1846 | switch (key) { |
1787 | case K_TAB: | 1847 | case K_TAB: |
@@ -1824,9 +1884,14 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1824 | actions->thread = thread; | 1884 | actions->thread = thread; |
1825 | do_zoom_thread(browser, actions); | 1885 | do_zoom_thread(browser, actions); |
1826 | continue; | 1886 | continue; |
1887 | case 'S': | ||
1888 | actions->socket = socked_id; | ||
1889 | do_zoom_socket(browser, actions); | ||
1890 | continue; | ||
1827 | case '/': | 1891 | case '/': |
1828 | if (ui_browser__input_window("Symbol to show", | 1892 | if (ui_browser__input_window("Symbol to show", |
1829 | "Please enter the name of symbol you want to see", | 1893 | "Please enter the name of symbol you want to see.\n" |
1894 | "To remove the filter later, press / + ENTER.", | ||
1830 | buf, "ENTER: OK, ESC: Cancel", | 1895 | buf, "ENTER: OK, ESC: Cancel", |
1831 | delay_secs * 2) == K_ENTER) { | 1896 | delay_secs * 2) == K_ENTER) { |
1832 | hists->symbol_filter_str = *buf ? buf : NULL; | 1897 | hists->symbol_filter_str = *buf ? buf : NULL; |
@@ -1871,6 +1936,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1871 | continue; | 1936 | continue; |
1872 | case K_ENTER: | 1937 | case K_ENTER: |
1873 | case K_RIGHT: | 1938 | case K_RIGHT: |
1939 | case 'm': | ||
1874 | /* menu */ | 1940 | /* menu */ |
1875 | break; | 1941 | break; |
1876 | case K_ESC: | 1942 | case K_ESC: |
@@ -1899,9 +1965,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1899 | * Ditto for thread below. | 1965 | * Ditto for thread below. |
1900 | */ | 1966 | */ |
1901 | do_zoom_dso(browser, actions); | 1967 | do_zoom_dso(browser, actions); |
1902 | } | 1968 | } else if (top == &browser->hists->thread_filter) { |
1903 | if (top == &browser->hists->thread_filter) | ||
1904 | do_zoom_thread(browser, actions); | 1969 | do_zoom_thread(browser, actions); |
1970 | } else if (top == &browser->hists->socket_filter) { | ||
1971 | do_zoom_socket(browser, actions); | ||
1972 | } | ||
1905 | continue; | 1973 | continue; |
1906 | } | 1974 | } |
1907 | case 'q': | 1975 | case 'q': |
@@ -1965,17 +2033,29 @@ skip_annotation: | |||
1965 | nr_options += add_thread_opt(browser, &actions[nr_options], | 2033 | nr_options += add_thread_opt(browser, &actions[nr_options], |
1966 | &options[nr_options], thread); | 2034 | &options[nr_options], thread); |
1967 | nr_options += add_dso_opt(browser, &actions[nr_options], | 2035 | nr_options += add_dso_opt(browser, &actions[nr_options], |
1968 | &options[nr_options], dso); | 2036 | &options[nr_options], map); |
1969 | nr_options += add_map_opt(browser, &actions[nr_options], | 2037 | nr_options += add_map_opt(browser, &actions[nr_options], |
1970 | &options[nr_options], | 2038 | &options[nr_options], |
1971 | browser->selection->map); | 2039 | browser->selection ? |
1972 | 2040 | browser->selection->map : NULL); | |
2041 | nr_options += add_socket_opt(browser, &actions[nr_options], | ||
2042 | &options[nr_options], | ||
2043 | socked_id); | ||
1973 | /* perf script support */ | 2044 | /* perf script support */ |
1974 | if (browser->he_selection) { | 2045 | if (browser->he_selection) { |
1975 | nr_options += add_script_opt(browser, | 2046 | nr_options += add_script_opt(browser, |
1976 | &actions[nr_options], | 2047 | &actions[nr_options], |
1977 | &options[nr_options], | 2048 | &options[nr_options], |
1978 | thread, NULL); | 2049 | thread, NULL); |
2050 | /* | ||
2051 | * Note that browser->selection != NULL | ||
2052 | * when browser->he_selection is not NULL, | ||
2053 | * so we don't need to check browser->selection | ||
2054 | * before fetching browser->selection->sym like what | ||
2055 | * we do before fetching browser->selection->map. | ||
2056 | * | ||
2057 | * See hist_browser__show_entry. | ||
2058 | */ | ||
1979 | nr_options += add_script_opt(browser, | 2059 | nr_options += add_script_opt(browser, |
1980 | &actions[nr_options], | 2060 | &actions[nr_options], |
1981 | &options[nr_options], | 2061 | &options[nr_options], |
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c index 8c154c7d4669..80912778bb6d 100644 --- a/tools/perf/ui/browsers/map.c +++ b/tools/perf/ui/browsers/map.c | |||
@@ -72,7 +72,7 @@ static int map_browser__run(struct map_browser *browser) | |||
72 | int key; | 72 | int key; |
73 | 73 | ||
74 | if (ui_browser__show(&browser->b, browser->map->dso->long_name, | 74 | if (ui_browser__show(&browser->b, browser->map->dso->long_name, |
75 | "Press <- or ESC to exit, %s / to search", | 75 | "Press ESC to exit, %s / to search", |
76 | verbose ? "" : "restart with -v to use") < 0) | 76 | verbose ? "" : "restart with -v to use") < 0) |
77 | return -1; | 77 | return -1; |
78 | 78 | ||
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c index e13b48d705ef..ad6b6ee3770e 100644 --- a/tools/perf/ui/browsers/scripts.c +++ b/tools/perf/ui/browsers/scripts.c | |||
@@ -89,7 +89,7 @@ static int script_browser__run(struct perf_script_browser *browser) | |||
89 | int key; | 89 | int key; |
90 | 90 | ||
91 | if (ui_browser__show(&browser->b, browser->script_name, | 91 | if (ui_browser__show(&browser->b, browser->script_name, |
92 | "Press <- or ESC to exit") < 0) | 92 | "Press ESC to exit") < 0) |
93 | return -1; | 93 | return -1; |
94 | 94 | ||
95 | while (1) { | 95 | while (1) { |
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 25d608394d74..5029ba2b55af 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
@@ -463,27 +463,27 @@ void perf_hpp__init(void) | |||
463 | return; | 463 | return; |
464 | 464 | ||
465 | if (symbol_conf.cumulate_callchain) { | 465 | if (symbol_conf.cumulate_callchain) { |
466 | perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC); | 466 | hpp_dimension__add_output(PERF_HPP__OVERHEAD_ACC); |
467 | perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self"; | 467 | perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self"; |
468 | } | 468 | } |
469 | 469 | ||
470 | perf_hpp__column_enable(PERF_HPP__OVERHEAD); | 470 | hpp_dimension__add_output(PERF_HPP__OVERHEAD); |
471 | 471 | ||
472 | if (symbol_conf.show_cpu_utilization) { | 472 | if (symbol_conf.show_cpu_utilization) { |
473 | perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS); | 473 | hpp_dimension__add_output(PERF_HPP__OVERHEAD_SYS); |
474 | perf_hpp__column_enable(PERF_HPP__OVERHEAD_US); | 474 | hpp_dimension__add_output(PERF_HPP__OVERHEAD_US); |
475 | 475 | ||
476 | if (perf_guest) { | 476 | if (perf_guest) { |
477 | perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_SYS); | 477 | hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_SYS); |
478 | perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_US); | 478 | hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_US); |
479 | } | 479 | } |
480 | } | 480 | } |
481 | 481 | ||
482 | if (symbol_conf.show_nr_samples) | 482 | if (symbol_conf.show_nr_samples) |
483 | perf_hpp__column_enable(PERF_HPP__SAMPLES); | 483 | hpp_dimension__add_output(PERF_HPP__SAMPLES); |
484 | 484 | ||
485 | if (symbol_conf.show_total_period) | 485 | if (symbol_conf.show_total_period) |
486 | perf_hpp__column_enable(PERF_HPP__PERIOD); | 486 | hpp_dimension__add_output(PERF_HPP__PERIOD); |
487 | 487 | ||
488 | /* prepend overhead field for backward compatiblity. */ | 488 | /* prepend overhead field for backward compatiblity. */ |
489 | list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list; | 489 | list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list; |
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c index 60d1f29b4b50..7dfeba0a91f3 100644 --- a/tools/perf/ui/tui/setup.c +++ b/tools/perf/ui/tui/setup.c | |||
@@ -141,10 +141,6 @@ int ui__init(void) | |||
141 | 141 | ||
142 | SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB); | 142 | SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB); |
143 | 143 | ||
144 | ui_helpline__init(); | ||
145 | ui_browser__init(); | ||
146 | tui_progress__init(); | ||
147 | |||
148 | signal(SIGSEGV, ui__signal_backtrace); | 144 | signal(SIGSEGV, ui__signal_backtrace); |
149 | signal(SIGFPE, ui__signal_backtrace); | 145 | signal(SIGFPE, ui__signal_backtrace); |
150 | signal(SIGINT, ui__signal); | 146 | signal(SIGINT, ui__signal); |
@@ -153,6 +149,10 @@ int ui__init(void) | |||
153 | 149 | ||
154 | perf_error__register(&perf_tui_eops); | 150 | perf_error__register(&perf_tui_eops); |
155 | 151 | ||
152 | ui_helpline__init(); | ||
153 | ui_browser__init(); | ||
154 | tui_progress__init(); | ||
155 | |||
156 | hist_browser__init_hpp(); | 156 | hist_browser__init_hpp(); |
157 | out: | 157 | out: |
158 | return err; | 158 | return err; |
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 349bc96ca1fe..591b3fe3ed49 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
@@ -5,6 +5,7 @@ libperf-y += build-id.o | |||
5 | libperf-y += config.o | 5 | libperf-y += config.o |
6 | libperf-y += ctype.o | 6 | libperf-y += ctype.o |
7 | libperf-y += db-export.o | 7 | libperf-y += db-export.o |
8 | libperf-y += env.o | ||
8 | libperf-y += environment.o | 9 | libperf-y += environment.o |
9 | libperf-y += event.o | 10 | libperf-y += event.o |
10 | libperf-y += evlist.o | 11 | libperf-y += evlist.o |
@@ -17,6 +18,7 @@ libperf-y += levenshtein.o | |||
17 | libperf-y += llvm-utils.o | 18 | libperf-y += llvm-utils.o |
18 | libperf-y += parse-options.o | 19 | libperf-y += parse-options.o |
19 | libperf-y += parse-events.o | 20 | libperf-y += parse-events.o |
21 | libperf-y += perf_regs.o | ||
20 | libperf-y += path.o | 22 | libperf-y += path.o |
21 | libperf-y += rbtree.o | 23 | libperf-y += rbtree.o |
22 | libperf-y += bitmap.o | 24 | libperf-y += bitmap.o |
@@ -85,6 +87,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-bts.o | |||
85 | libperf-y += parse-branch-options.o | 87 | libperf-y += parse-branch-options.o |
86 | libperf-y += parse-regs-options.o | 88 | libperf-y += parse-regs-options.o |
87 | 89 | ||
90 | libperf-$(CONFIG_LIBBPF) += bpf-loader.o | ||
88 | libperf-$(CONFIG_LIBELF) += symbol-elf.o | 91 | libperf-$(CONFIG_LIBELF) += symbol-elf.o |
89 | libperf-$(CONFIG_LIBELF) += probe-file.o | 92 | libperf-$(CONFIG_LIBELF) += probe-file.o |
90 | libperf-$(CONFIG_LIBELF) += probe-event.o | 93 | libperf-$(CONFIG_LIBELF) += probe-event.o |
@@ -103,7 +106,6 @@ libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o | |||
103 | 106 | ||
104 | libperf-y += scripting-engines/ | 107 | libperf-y += scripting-engines/ |
105 | 108 | ||
106 | libperf-$(CONFIG_PERF_REGS) += perf_regs.o | ||
107 | libperf-$(CONFIG_ZLIB) += zlib.o | 109 | libperf-$(CONFIG_ZLIB) += zlib.o |
108 | libperf-$(CONFIG_LZMA) += lzma.o | 110 | libperf-$(CONFIG_LZMA) += lzma.o |
109 | 111 | ||
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index d1eece70b84d..0fc8d7a2fea5 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -548,8 +548,11 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map, | |||
548 | 548 | ||
549 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); | 549 | pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); |
550 | 550 | ||
551 | if (addr < sym->start || addr >= sym->end) | 551 | if (addr < sym->start || addr >= sym->end) { |
552 | pr_debug("%s(%d): ERANGE! sym->name=%s, start=%#" PRIx64 ", addr=%#" PRIx64 ", end=%#" PRIx64 "\n", | ||
553 | __func__, __LINE__, sym->name, sym->start, addr, sym->end); | ||
552 | return -ERANGE; | 554 | return -ERANGE; |
555 | } | ||
553 | 556 | ||
554 | offset = addr - sym->start; | 557 | offset = addr - sym->start; |
555 | h = annotation__histogram(notes, evidx); | 558 | h = annotation__histogram(notes, evidx); |
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index e9996092a093..cea323d9ee7e 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
@@ -122,7 +122,7 @@ struct annotated_source { | |||
122 | struct list_head source; | 122 | struct list_head source; |
123 | struct source_line *lines; | 123 | struct source_line *lines; |
124 | int nr_histograms; | 124 | int nr_histograms; |
125 | int sizeof_sym_hist; | 125 | size_t sizeof_sym_hist; |
126 | struct cyc_hist *cycles_hist; | 126 | struct cyc_hist *cycles_hist; |
127 | struct sym_hist histograms[0]; | 127 | struct sym_hist histograms[0]; |
128 | }; | 128 | }; |
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index a980e7c50ee0..7f10430af39c 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c | |||
@@ -926,6 +926,8 @@ s64 perf_event__process_auxtrace(struct perf_tool *tool, | |||
926 | #define PERF_ITRACE_DEFAULT_PERIOD 100000 | 926 | #define PERF_ITRACE_DEFAULT_PERIOD 100000 |
927 | #define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16 | 927 | #define PERF_ITRACE_DEFAULT_CALLCHAIN_SZ 16 |
928 | #define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024 | 928 | #define PERF_ITRACE_MAX_CALLCHAIN_SZ 1024 |
929 | #define PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ 64 | ||
930 | #define PERF_ITRACE_MAX_LAST_BRANCH_SZ 1024 | ||
929 | 931 | ||
930 | void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) | 932 | void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) |
931 | { | 933 | { |
@@ -936,6 +938,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) | |||
936 | synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; | 938 | synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; |
937 | synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; | 939 | synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; |
938 | synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; | 940 | synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; |
941 | synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ; | ||
939 | } | 942 | } |
940 | 943 | ||
941 | /* | 944 | /* |
@@ -950,6 +953,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str, | |||
950 | const char *p; | 953 | const char *p; |
951 | char *endptr; | 954 | char *endptr; |
952 | bool period_type_set = false; | 955 | bool period_type_set = false; |
956 | bool period_set = false; | ||
953 | 957 | ||
954 | synth_opts->set = true; | 958 | synth_opts->set = true; |
955 | 959 | ||
@@ -971,6 +975,7 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str, | |||
971 | p += 1; | 975 | p += 1; |
972 | if (isdigit(*p)) { | 976 | if (isdigit(*p)) { |
973 | synth_opts->period = strtoull(p, &endptr, 10); | 977 | synth_opts->period = strtoull(p, &endptr, 10); |
978 | period_set = true; | ||
974 | p = endptr; | 979 | p = endptr; |
975 | while (*p == ' ' || *p == ',') | 980 | while (*p == ' ' || *p == ',') |
976 | p += 1; | 981 | p += 1; |
@@ -1041,6 +1046,23 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str, | |||
1041 | synth_opts->callchain_sz = val; | 1046 | synth_opts->callchain_sz = val; |
1042 | } | 1047 | } |
1043 | break; | 1048 | break; |
1049 | case 'l': | ||
1050 | synth_opts->last_branch = true; | ||
1051 | synth_opts->last_branch_sz = | ||
1052 | PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ; | ||
1053 | while (*p == ' ' || *p == ',') | ||
1054 | p += 1; | ||
1055 | if (isdigit(*p)) { | ||
1056 | unsigned int val; | ||
1057 | |||
1058 | val = strtoul(p, &endptr, 10); | ||
1059 | p = endptr; | ||
1060 | if (!val || | ||
1061 | val > PERF_ITRACE_MAX_LAST_BRANCH_SZ) | ||
1062 | goto out_err; | ||
1063 | synth_opts->last_branch_sz = val; | ||
1064 | } | ||
1065 | break; | ||
1044 | case ' ': | 1066 | case ' ': |
1045 | case ',': | 1067 | case ',': |
1046 | break; | 1068 | break; |
@@ -1053,7 +1075,7 @@ out: | |||
1053 | if (!period_type_set) | 1075 | if (!period_type_set) |
1054 | synth_opts->period_type = | 1076 | synth_opts->period_type = |
1055 | PERF_ITRACE_DEFAULT_PERIOD_TYPE; | 1077 | PERF_ITRACE_DEFAULT_PERIOD_TYPE; |
1056 | if (!synth_opts->period) | 1078 | if (!period_set) |
1057 | synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; | 1079 | synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; |
1058 | } | 1080 | } |
1059 | 1081 | ||
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index bf72b77a588a..b86f90db1352 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h | |||
@@ -63,7 +63,9 @@ enum itrace_period_type { | |||
63 | * @calls: limit branch samples to calls (can be combined with @returns) | 63 | * @calls: limit branch samples to calls (can be combined with @returns) |
64 | * @returns: limit branch samples to returns (can be combined with @calls) | 64 | * @returns: limit branch samples to returns (can be combined with @calls) |
65 | * @callchain: add callchain to 'instructions' events | 65 | * @callchain: add callchain to 'instructions' events |
66 | * @last_branch: add branch context to 'instruction' events | ||
66 | * @callchain_sz: maximum callchain size | 67 | * @callchain_sz: maximum callchain size |
68 | * @last_branch_sz: branch context size | ||
67 | * @period: 'instructions' events period | 69 | * @period: 'instructions' events period |
68 | * @period_type: 'instructions' events period type | 70 | * @period_type: 'instructions' events period type |
69 | */ | 71 | */ |
@@ -79,7 +81,9 @@ struct itrace_synth_opts { | |||
79 | bool calls; | 81 | bool calls; |
80 | bool returns; | 82 | bool returns; |
81 | bool callchain; | 83 | bool callchain; |
84 | bool last_branch; | ||
82 | unsigned int callchain_sz; | 85 | unsigned int callchain_sz; |
86 | unsigned int last_branch_sz; | ||
83 | unsigned long long period; | 87 | unsigned long long period; |
84 | enum itrace_period_type period_type; | 88 | enum itrace_period_type period_type; |
85 | }; | 89 | }; |
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c new file mode 100644 index 000000000000..ba6f7526b282 --- /dev/null +++ b/tools/perf/util/bpf-loader.c | |||
@@ -0,0 +1,352 @@ | |||
1 | /* | ||
2 | * bpf-loader.c | ||
3 | * | ||
4 | * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> | ||
5 | * Copyright (C) 2015 Huawei Inc. | ||
6 | */ | ||
7 | |||
8 | #include <bpf/libbpf.h> | ||
9 | #include <linux/err.h> | ||
10 | #include "perf.h" | ||
11 | #include "debug.h" | ||
12 | #include "bpf-loader.h" | ||
13 | #include "probe-event.h" | ||
14 | #include "probe-finder.h" // for MAX_PROBES | ||
15 | #include "llvm-utils.h" | ||
16 | |||
17 | #define DEFINE_PRINT_FN(name, level) \ | ||
18 | static int libbpf_##name(const char *fmt, ...) \ | ||
19 | { \ | ||
20 | va_list args; \ | ||
21 | int ret; \ | ||
22 | \ | ||
23 | va_start(args, fmt); \ | ||
24 | ret = veprintf(level, verbose, pr_fmt(fmt), args);\ | ||
25 | va_end(args); \ | ||
26 | return ret; \ | ||
27 | } | ||
28 | |||
29 | DEFINE_PRINT_FN(warning, 0) | ||
30 | DEFINE_PRINT_FN(info, 0) | ||
31 | DEFINE_PRINT_FN(debug, 1) | ||
32 | |||
33 | struct bpf_prog_priv { | ||
34 | struct perf_probe_event pev; | ||
35 | }; | ||
36 | |||
37 | struct bpf_object *bpf__prepare_load(const char *filename, bool source) | ||
38 | { | ||
39 | struct bpf_object *obj; | ||
40 | static bool libbpf_initialized; | ||
41 | |||
42 | if (!libbpf_initialized) { | ||
43 | libbpf_set_print(libbpf_warning, | ||
44 | libbpf_info, | ||
45 | libbpf_debug); | ||
46 | libbpf_initialized = true; | ||
47 | } | ||
48 | |||
49 | if (source) { | ||
50 | int err; | ||
51 | void *obj_buf; | ||
52 | size_t obj_buf_sz; | ||
53 | |||
54 | err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz); | ||
55 | if (err) | ||
56 | return ERR_PTR(err); | ||
57 | obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); | ||
58 | free(obj_buf); | ||
59 | } else | ||
60 | obj = bpf_object__open(filename); | ||
61 | |||
62 | if (!obj) { | ||
63 | pr_debug("bpf: failed to load %s\n", filename); | ||
64 | return ERR_PTR(-EINVAL); | ||
65 | } | ||
66 | |||
67 | return obj; | ||
68 | } | ||
69 | |||
70 | void bpf__clear(void) | ||
71 | { | ||
72 | struct bpf_object *obj, *tmp; | ||
73 | |||
74 | bpf_object__for_each_safe(obj, tmp) { | ||
75 | bpf__unprobe(obj); | ||
76 | bpf_object__close(obj); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static void | ||
81 | bpf_prog_priv__clear(struct bpf_program *prog __maybe_unused, | ||
82 | void *_priv) | ||
83 | { | ||
84 | struct bpf_prog_priv *priv = _priv; | ||
85 | |||
86 | cleanup_perf_probe_events(&priv->pev, 1); | ||
87 | free(priv); | ||
88 | } | ||
89 | |||
90 | static int | ||
91 | config_bpf_program(struct bpf_program *prog) | ||
92 | { | ||
93 | struct perf_probe_event *pev = NULL; | ||
94 | struct bpf_prog_priv *priv = NULL; | ||
95 | const char *config_str; | ||
96 | int err; | ||
97 | |||
98 | config_str = bpf_program__title(prog, false); | ||
99 | if (!config_str) { | ||
100 | pr_debug("bpf: unable to get title for program\n"); | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | priv = calloc(sizeof(*priv), 1); | ||
105 | if (!priv) { | ||
106 | pr_debug("bpf: failed to alloc priv\n"); | ||
107 | return -ENOMEM; | ||
108 | } | ||
109 | pev = &priv->pev; | ||
110 | |||
111 | pr_debug("bpf: config program '%s'\n", config_str); | ||
112 | err = parse_perf_probe_command(config_str, pev); | ||
113 | if (err < 0) { | ||
114 | pr_debug("bpf: '%s' is not a valid config string\n", | ||
115 | config_str); | ||
116 | err = -EINVAL; | ||
117 | goto errout; | ||
118 | } | ||
119 | |||
120 | if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { | ||
121 | pr_debug("bpf: '%s': group for event is set and not '%s'.\n", | ||
122 | config_str, PERF_BPF_PROBE_GROUP); | ||
123 | err = -EINVAL; | ||
124 | goto errout; | ||
125 | } else if (!pev->group) | ||
126 | pev->group = strdup(PERF_BPF_PROBE_GROUP); | ||
127 | |||
128 | if (!pev->group) { | ||
129 | pr_debug("bpf: strdup failed\n"); | ||
130 | err = -ENOMEM; | ||
131 | goto errout; | ||
132 | } | ||
133 | |||
134 | if (!pev->event) { | ||
135 | pr_debug("bpf: '%s': event name is missing\n", | ||
136 | config_str); | ||
137 | err = -EINVAL; | ||
138 | goto errout; | ||
139 | } | ||
140 | pr_debug("bpf: config '%s' is ok\n", config_str); | ||
141 | |||
142 | err = bpf_program__set_private(prog, priv, bpf_prog_priv__clear); | ||
143 | if (err) { | ||
144 | pr_debug("Failed to set priv for program '%s'\n", config_str); | ||
145 | goto errout; | ||
146 | } | ||
147 | |||
148 | return 0; | ||
149 | |||
150 | errout: | ||
151 | if (pev) | ||
152 | clear_perf_probe_event(pev); | ||
153 | free(priv); | ||
154 | return err; | ||
155 | } | ||
156 | |||
157 | static int bpf__prepare_probe(void) | ||
158 | { | ||
159 | static int err = 0; | ||
160 | static bool initialized = false; | ||
161 | |||
162 | /* | ||
163 | * Make err static, so if init failed the first, bpf__prepare_probe() | ||
164 | * fails each time without calling init_probe_symbol_maps multiple | ||
165 | * times. | ||
166 | */ | ||
167 | if (initialized) | ||
168 | return err; | ||
169 | |||
170 | initialized = true; | ||
171 | err = init_probe_symbol_maps(false); | ||
172 | if (err < 0) | ||
173 | pr_debug("Failed to init_probe_symbol_maps\n"); | ||
174 | probe_conf.max_probes = MAX_PROBES; | ||
175 | return err; | ||
176 | } | ||
177 | |||
178 | int bpf__probe(struct bpf_object *obj) | ||
179 | { | ||
180 | int err = 0; | ||
181 | struct bpf_program *prog; | ||
182 | struct bpf_prog_priv *priv; | ||
183 | struct perf_probe_event *pev; | ||
184 | |||
185 | err = bpf__prepare_probe(); | ||
186 | if (err) { | ||
187 | pr_debug("bpf__prepare_probe failed\n"); | ||
188 | return err; | ||
189 | } | ||
190 | |||
191 | bpf_object__for_each_program(prog, obj) { | ||
192 | err = config_bpf_program(prog); | ||
193 | if (err) | ||
194 | goto out; | ||
195 | |||
196 | err = bpf_program__get_private(prog, (void **)&priv); | ||
197 | if (err || !priv) | ||
198 | goto out; | ||
199 | pev = &priv->pev; | ||
200 | |||
201 | err = convert_perf_probe_events(pev, 1); | ||
202 | if (err < 0) { | ||
203 | pr_debug("bpf_probe: failed to convert perf probe events"); | ||
204 | goto out; | ||
205 | } | ||
206 | |||
207 | err = apply_perf_probe_events(pev, 1); | ||
208 | if (err < 0) { | ||
209 | pr_debug("bpf_probe: failed to apply perf probe events"); | ||
210 | goto out; | ||
211 | } | ||
212 | } | ||
213 | out: | ||
214 | return err < 0 ? err : 0; | ||
215 | } | ||
216 | |||
217 | #define EVENTS_WRITE_BUFSIZE 4096 | ||
218 | int bpf__unprobe(struct bpf_object *obj) | ||
219 | { | ||
220 | int err, ret = 0; | ||
221 | struct bpf_program *prog; | ||
222 | struct bpf_prog_priv *priv; | ||
223 | |||
224 | bpf_object__for_each_program(prog, obj) { | ||
225 | int i; | ||
226 | |||
227 | err = bpf_program__get_private(prog, (void **)&priv); | ||
228 | if (err || !priv) | ||
229 | continue; | ||
230 | |||
231 | for (i = 0; i < priv->pev.ntevs; i++) { | ||
232 | struct probe_trace_event *tev = &priv->pev.tevs[i]; | ||
233 | char name_buf[EVENTS_WRITE_BUFSIZE]; | ||
234 | struct strfilter *delfilter; | ||
235 | |||
236 | snprintf(name_buf, EVENTS_WRITE_BUFSIZE, | ||
237 | "%s:%s", tev->group, tev->event); | ||
238 | name_buf[EVENTS_WRITE_BUFSIZE - 1] = '\0'; | ||
239 | |||
240 | delfilter = strfilter__new(name_buf, NULL); | ||
241 | if (!delfilter) { | ||
242 | pr_debug("Failed to create filter for unprobing\n"); | ||
243 | ret = -ENOMEM; | ||
244 | continue; | ||
245 | } | ||
246 | |||
247 | err = del_perf_probe_events(delfilter); | ||
248 | strfilter__delete(delfilter); | ||
249 | if (err) { | ||
250 | pr_debug("Failed to delete %s\n", name_buf); | ||
251 | ret = err; | ||
252 | continue; | ||
253 | } | ||
254 | } | ||
255 | } | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | int bpf__load(struct bpf_object *obj) | ||
260 | { | ||
261 | int err; | ||
262 | |||
263 | err = bpf_object__load(obj); | ||
264 | if (err) { | ||
265 | pr_debug("bpf: load objects failed\n"); | ||
266 | return err; | ||
267 | } | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | int bpf__foreach_tev(struct bpf_object *obj, | ||
272 | bpf_prog_iter_callback_t func, | ||
273 | void *arg) | ||
274 | { | ||
275 | struct bpf_program *prog; | ||
276 | int err; | ||
277 | |||
278 | bpf_object__for_each_program(prog, obj) { | ||
279 | struct probe_trace_event *tev; | ||
280 | struct perf_probe_event *pev; | ||
281 | struct bpf_prog_priv *priv; | ||
282 | int i, fd; | ||
283 | |||
284 | err = bpf_program__get_private(prog, | ||
285 | (void **)&priv); | ||
286 | if (err || !priv) { | ||
287 | pr_debug("bpf: failed to get private field\n"); | ||
288 | return -EINVAL; | ||
289 | } | ||
290 | |||
291 | pev = &priv->pev; | ||
292 | for (i = 0; i < pev->ntevs; i++) { | ||
293 | tev = &pev->tevs[i]; | ||
294 | |||
295 | fd = bpf_program__fd(prog); | ||
296 | if (fd < 0) { | ||
297 | pr_debug("bpf: failed to get file descriptor\n"); | ||
298 | return fd; | ||
299 | } | ||
300 | |||
301 | err = (*func)(tev, fd, arg); | ||
302 | if (err) { | ||
303 | pr_debug("bpf: call back failed, stop iterate\n"); | ||
304 | return err; | ||
305 | } | ||
306 | } | ||
307 | } | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | #define bpf__strerror_head(err, buf, size) \ | ||
312 | char sbuf[STRERR_BUFSIZE], *emsg;\ | ||
313 | if (!size)\ | ||
314 | return 0;\ | ||
315 | if (err < 0)\ | ||
316 | err = -err;\ | ||
317 | emsg = strerror_r(err, sbuf, sizeof(sbuf));\ | ||
318 | switch (err) {\ | ||
319 | default:\ | ||
320 | scnprintf(buf, size, "%s", emsg);\ | ||
321 | break; | ||
322 | |||
323 | #define bpf__strerror_entry(val, fmt...)\ | ||
324 | case val: {\ | ||
325 | scnprintf(buf, size, fmt);\ | ||
326 | break;\ | ||
327 | } | ||
328 | |||
329 | #define bpf__strerror_end(buf, size)\ | ||
330 | }\ | ||
331 | buf[size - 1] = '\0'; | ||
332 | |||
333 | int bpf__strerror_probe(struct bpf_object *obj __maybe_unused, | ||
334 | int err, char *buf, size_t size) | ||
335 | { | ||
336 | bpf__strerror_head(err, buf, size); | ||
337 | bpf__strerror_entry(EEXIST, "Probe point exist. Try use 'perf probe -d \"*\"'"); | ||
338 | bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0\n"); | ||
339 | bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file\n"); | ||
340 | bpf__strerror_end(buf, size); | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | int bpf__strerror_load(struct bpf_object *obj __maybe_unused, | ||
345 | int err, char *buf, size_t size) | ||
346 | { | ||
347 | bpf__strerror_head(err, buf, size); | ||
348 | bpf__strerror_entry(EINVAL, "%s: Are you root and runing a CONFIG_BPF_SYSCALL kernel?", | ||
349 | emsg) | ||
350 | bpf__strerror_end(buf, size); | ||
351 | return 0; | ||
352 | } | ||
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h new file mode 100644 index 000000000000..ccd8d7fd79d3 --- /dev/null +++ b/tools/perf/util/bpf-loader.h | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015, Wang Nan <wangnan0@huawei.com> | ||
3 | * Copyright (C) 2015, Huawei Inc. | ||
4 | */ | ||
5 | #ifndef __BPF_LOADER_H | ||
6 | #define __BPF_LOADER_H | ||
7 | |||
8 | #include <linux/compiler.h> | ||
9 | #include <linux/err.h> | ||
10 | #include <string.h> | ||
11 | #include "probe-event.h" | ||
12 | #include "debug.h" | ||
13 | |||
14 | struct bpf_object; | ||
15 | #define PERF_BPF_PROBE_GROUP "perf_bpf_probe" | ||
16 | |||
17 | typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev, | ||
18 | int fd, void *arg); | ||
19 | |||
20 | #ifdef HAVE_LIBBPF_SUPPORT | ||
21 | struct bpf_object *bpf__prepare_load(const char *filename, bool source); | ||
22 | |||
23 | void bpf__clear(void); | ||
24 | |||
25 | int bpf__probe(struct bpf_object *obj); | ||
26 | int bpf__unprobe(struct bpf_object *obj); | ||
27 | int bpf__strerror_probe(struct bpf_object *obj, int err, | ||
28 | char *buf, size_t size); | ||
29 | |||
30 | int bpf__load(struct bpf_object *obj); | ||
31 | int bpf__strerror_load(struct bpf_object *obj, int err, | ||
32 | char *buf, size_t size); | ||
33 | int bpf__foreach_tev(struct bpf_object *obj, | ||
34 | bpf_prog_iter_callback_t func, void *arg); | ||
35 | #else | ||
36 | static inline struct bpf_object * | ||
37 | bpf__prepare_load(const char *filename __maybe_unused, | ||
38 | bool source __maybe_unused) | ||
39 | { | ||
40 | pr_debug("ERROR: eBPF object loading is disabled during compiling.\n"); | ||
41 | return ERR_PTR(-ENOTSUP); | ||
42 | } | ||
43 | |||
44 | static inline void bpf__clear(void) { } | ||
45 | |||
46 | static inline int bpf__probe(struct bpf_object *obj __maybe_unused) { return 0;} | ||
47 | static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0;} | ||
48 | static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; } | ||
49 | |||
50 | static inline int | ||
51 | bpf__foreach_tev(struct bpf_object *obj __maybe_unused, | ||
52 | bpf_prog_iter_callback_t func __maybe_unused, | ||
53 | void *arg __maybe_unused) | ||
54 | { | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static inline int | ||
59 | __bpf_strerror(char *buf, size_t size) | ||
60 | { | ||
61 | if (!size) | ||
62 | return 0; | ||
63 | strncpy(buf, | ||
64 | "ERROR: eBPF object loading is disabled during compiling.\n", | ||
65 | size); | ||
66 | buf[size - 1] = '\0'; | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static inline int | ||
71 | bpf__strerror_probe(struct bpf_object *obj __maybe_unused, | ||
72 | int err __maybe_unused, | ||
73 | char *buf, size_t size) | ||
74 | { | ||
75 | return __bpf_strerror(buf, size); | ||
76 | } | ||
77 | |||
78 | static inline int bpf__strerror_load(struct bpf_object *obj __maybe_unused, | ||
79 | int err __maybe_unused, | ||
80 | char *buf, size_t size) | ||
81 | { | ||
82 | return __bpf_strerror(buf, size); | ||
83 | } | ||
84 | #endif | ||
85 | #endif | ||
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 773fe13ce627..735ad48e1858 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -51,10 +51,12 @@ static int parse_callchain_order(const char *value) | |||
51 | { | 51 | { |
52 | if (!strncmp(value, "caller", strlen(value))) { | 52 | if (!strncmp(value, "caller", strlen(value))) { |
53 | callchain_param.order = ORDER_CALLER; | 53 | callchain_param.order = ORDER_CALLER; |
54 | callchain_param.order_set = true; | ||
54 | return 0; | 55 | return 0; |
55 | } | 56 | } |
56 | if (!strncmp(value, "callee", strlen(value))) { | 57 | if (!strncmp(value, "callee", strlen(value))) { |
57 | callchain_param.order = ORDER_CALLEE; | 58 | callchain_param.order = ORDER_CALLEE; |
59 | callchain_param.order_set = true; | ||
58 | return 0; | 60 | return 0; |
59 | } | 61 | } |
60 | return -1; | 62 | return -1; |
@@ -77,12 +79,14 @@ static int parse_callchain_sort_key(const char *value) | |||
77 | return -1; | 79 | return -1; |
78 | } | 80 | } |
79 | 81 | ||
80 | int | 82 | static int |
81 | parse_callchain_report_opt(const char *arg) | 83 | __parse_callchain_report_opt(const char *arg, bool allow_record_opt) |
82 | { | 84 | { |
83 | char *tok; | 85 | char *tok; |
84 | char *endptr; | 86 | char *endptr; |
85 | bool minpcnt_set = false; | 87 | bool minpcnt_set = false; |
88 | bool record_opt_set = false; | ||
89 | bool try_stack_size = false; | ||
86 | 90 | ||
87 | symbol_conf.use_callchain = true; | 91 | symbol_conf.use_callchain = true; |
88 | 92 | ||
@@ -100,6 +104,28 @@ parse_callchain_report_opt(const char *arg) | |||
100 | !parse_callchain_order(tok) || | 104 | !parse_callchain_order(tok) || |
101 | !parse_callchain_sort_key(tok)) { | 105 | !parse_callchain_sort_key(tok)) { |
102 | /* parsing ok - move on to the next */ | 106 | /* parsing ok - move on to the next */ |
107 | try_stack_size = false; | ||
108 | goto next; | ||
109 | } else if (allow_record_opt && !record_opt_set) { | ||
110 | if (parse_callchain_record(tok, &callchain_param)) | ||
111 | goto try_numbers; | ||
112 | |||
113 | /* assume that number followed by 'dwarf' is stack size */ | ||
114 | if (callchain_param.record_mode == CALLCHAIN_DWARF) | ||
115 | try_stack_size = true; | ||
116 | |||
117 | record_opt_set = true; | ||
118 | goto next; | ||
119 | } | ||
120 | |||
121 | try_numbers: | ||
122 | if (try_stack_size) { | ||
123 | unsigned long size = 0; | ||
124 | |||
125 | if (get_stack_size(tok, &size) < 0) | ||
126 | return -1; | ||
127 | callchain_param.dump_size = size; | ||
128 | try_stack_size = false; | ||
103 | } else if (!minpcnt_set) { | 129 | } else if (!minpcnt_set) { |
104 | /* try to get the min percent */ | 130 | /* try to get the min percent */ |
105 | callchain_param.min_percent = strtod(tok, &endptr); | 131 | callchain_param.min_percent = strtod(tok, &endptr); |
@@ -112,7 +138,7 @@ parse_callchain_report_opt(const char *arg) | |||
112 | if (tok == endptr) | 138 | if (tok == endptr) |
113 | return -1; | 139 | return -1; |
114 | } | 140 | } |
115 | 141 | next: | |
116 | arg = NULL; | 142 | arg = NULL; |
117 | } | 143 | } |
118 | 144 | ||
@@ -123,6 +149,16 @@ parse_callchain_report_opt(const char *arg) | |||
123 | return 0; | 149 | return 0; |
124 | } | 150 | } |
125 | 151 | ||
152 | int parse_callchain_report_opt(const char *arg) | ||
153 | { | ||
154 | return __parse_callchain_report_opt(arg, false); | ||
155 | } | ||
156 | |||
157 | int parse_callchain_top_opt(const char *arg) | ||
158 | { | ||
159 | return __parse_callchain_report_opt(arg, true); | ||
160 | } | ||
161 | |||
126 | int perf_callchain_config(const char *var, const char *value) | 162 | int perf_callchain_config(const char *var, const char *value) |
127 | { | 163 | { |
128 | char *endptr; | 164 | char *endptr; |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index acee2b3cd801..fce8161e54db 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -7,6 +7,30 @@ | |||
7 | #include "event.h" | 7 | #include "event.h" |
8 | #include "symbol.h" | 8 | #include "symbol.h" |
9 | 9 | ||
10 | #define HELP_PAD "\t\t\t\t" | ||
11 | |||
12 | #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace):\n\n" | ||
13 | |||
14 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | ||
15 | # define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|dwarf|lbr)\n" | ||
16 | #else | ||
17 | # define RECORD_MODE_HELP HELP_PAD "record_mode:\tcall graph recording mode (fp|lbr)\n" | ||
18 | #endif | ||
19 | |||
20 | #define RECORD_SIZE_HELP \ | ||
21 | HELP_PAD "record_size:\tif record_mode is 'dwarf', max size of stack recording (<bytes>)\n" \ | ||
22 | HELP_PAD "\t\tdefault: 8192 (bytes)\n" | ||
23 | |||
24 | #define CALLCHAIN_RECORD_HELP CALLCHAIN_HELP RECORD_MODE_HELP RECORD_SIZE_HELP | ||
25 | |||
26 | #define CALLCHAIN_REPORT_HELP \ | ||
27 | HELP_PAD "print_type:\tcall graph printing style (graph|flat|fractal|none)\n" \ | ||
28 | HELP_PAD "threshold:\tminimum call graph inclusion threshold (<percent>)\n" \ | ||
29 | HELP_PAD "print_limit:\tmaximum number of call graph entry (<number>)\n" \ | ||
30 | HELP_PAD "order:\t\tcall graph order (caller|callee)\n" \ | ||
31 | HELP_PAD "sort_key:\tcall graph sort key (function|address)\n" \ | ||
32 | HELP_PAD "branch:\t\tinclude last branch info to call graph (branch)\n" | ||
33 | |||
10 | enum perf_call_graph_mode { | 34 | enum perf_call_graph_mode { |
11 | CALLCHAIN_NONE, | 35 | CALLCHAIN_NONE, |
12 | CALLCHAIN_FP, | 36 | CALLCHAIN_FP, |
@@ -63,6 +87,7 @@ struct callchain_param { | |||
63 | double min_percent; | 87 | double min_percent; |
64 | sort_chain_func_t sort; | 88 | sort_chain_func_t sort; |
65 | enum chain_order order; | 89 | enum chain_order order; |
90 | bool order_set; | ||
66 | enum chain_key key; | 91 | enum chain_key key; |
67 | bool branch_callstack; | 92 | bool branch_callstack; |
68 | }; | 93 | }; |
@@ -180,6 +205,7 @@ extern const char record_callchain_help[]; | |||
180 | extern int parse_callchain_record(const char *arg, struct callchain_param *param); | 205 | extern int parse_callchain_record(const char *arg, struct callchain_param *param); |
181 | int parse_callchain_record_opt(const char *arg, struct callchain_param *param); | 206 | int parse_callchain_record_opt(const char *arg, struct callchain_param *param); |
182 | int parse_callchain_report_opt(const char *arg); | 207 | int parse_callchain_report_opt(const char *arg); |
208 | int parse_callchain_top_opt(const char *arg); | ||
183 | int perf_callchain_config(const char *var, const char *value); | 209 | int perf_callchain_config(const char *var, const char *value); |
184 | 210 | ||
185 | static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, | 211 | static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, |
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 3667e2123e5b..10af1e7524fb 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c | |||
@@ -203,6 +203,23 @@ struct cpu_map *cpu_map__dummy_new(void) | |||
203 | return cpus; | 203 | return cpus; |
204 | } | 204 | } |
205 | 205 | ||
206 | struct cpu_map *cpu_map__empty_new(int nr) | ||
207 | { | ||
208 | struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int) * nr); | ||
209 | |||
210 | if (cpus != NULL) { | ||
211 | int i; | ||
212 | |||
213 | cpus->nr = nr; | ||
214 | for (i = 0; i < nr; i++) | ||
215 | cpus->map[i] = -1; | ||
216 | |||
217 | atomic_set(&cpus->refcnt, 1); | ||
218 | } | ||
219 | |||
220 | return cpus; | ||
221 | } | ||
222 | |||
206 | static void cpu_map__delete(struct cpu_map *map) | 223 | static void cpu_map__delete(struct cpu_map *map) |
207 | { | 224 | { |
208 | if (map) { | 225 | if (map) { |
@@ -225,32 +242,32 @@ void cpu_map__put(struct cpu_map *map) | |||
225 | cpu_map__delete(map); | 242 | cpu_map__delete(map); |
226 | } | 243 | } |
227 | 244 | ||
228 | int cpu_map__get_socket(struct cpu_map *map, int idx) | 245 | static int cpu__get_topology_int(int cpu, const char *name, int *value) |
229 | { | 246 | { |
230 | FILE *fp; | ||
231 | const char *mnt; | ||
232 | char path[PATH_MAX]; | 247 | char path[PATH_MAX]; |
233 | int cpu, ret; | ||
234 | 248 | ||
235 | if (idx > map->nr) | 249 | snprintf(path, PATH_MAX, |
236 | return -1; | 250 | "devices/system/cpu/cpu%d/topology/%s", cpu, name); |
237 | 251 | ||
238 | cpu = map->map[idx]; | 252 | return sysfs__read_int(path, value); |
253 | } | ||
239 | 254 | ||
240 | mnt = sysfs__mountpoint(); | 255 | int cpu_map__get_socket_id(int cpu) |
241 | if (!mnt) | 256 | { |
242 | return -1; | 257 | int value, ret = cpu__get_topology_int(cpu, "physical_package_id", &value); |
258 | return ret ?: value; | ||
259 | } | ||
243 | 260 | ||
244 | snprintf(path, PATH_MAX, | 261 | int cpu_map__get_socket(struct cpu_map *map, int idx, void *data __maybe_unused) |
245 | "%s/devices/system/cpu/cpu%d/topology/physical_package_id", | 262 | { |
246 | mnt, cpu); | 263 | int cpu; |
247 | 264 | ||
248 | fp = fopen(path, "r"); | 265 | if (idx > map->nr) |
249 | if (!fp) | ||
250 | return -1; | 266 | return -1; |
251 | ret = fscanf(fp, "%d", &cpu); | 267 | |
252 | fclose(fp); | 268 | cpu = map->map[idx]; |
253 | return ret == 1 ? cpu : -1; | 269 | |
270 | return cpu_map__get_socket_id(cpu); | ||
254 | } | 271 | } |
255 | 272 | ||
256 | static int cmp_ids(const void *a, const void *b) | 273 | static int cmp_ids(const void *a, const void *b) |
@@ -258,8 +275,9 @@ static int cmp_ids(const void *a, const void *b) | |||
258 | return *(int *)a - *(int *)b; | 275 | return *(int *)a - *(int *)b; |
259 | } | 276 | } |
260 | 277 | ||
261 | static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, | 278 | int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, |
262 | int (*f)(struct cpu_map *map, int cpu)) | 279 | int (*f)(struct cpu_map *map, int cpu, void *data), |
280 | void *data) | ||
263 | { | 281 | { |
264 | struct cpu_map *c; | 282 | struct cpu_map *c; |
265 | int nr = cpus->nr; | 283 | int nr = cpus->nr; |
@@ -271,7 +289,7 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, | |||
271 | return -1; | 289 | return -1; |
272 | 290 | ||
273 | for (cpu = 0; cpu < nr; cpu++) { | 291 | for (cpu = 0; cpu < nr; cpu++) { |
274 | s1 = f(cpus, cpu); | 292 | s1 = f(cpus, cpu, data); |
275 | for (s2 = 0; s2 < c->nr; s2++) { | 293 | for (s2 = 0; s2 < c->nr; s2++) { |
276 | if (s1 == c->map[s2]) | 294 | if (s1 == c->map[s2]) |
277 | break; | 295 | break; |
@@ -284,40 +302,29 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, | |||
284 | /* ensure we process id in increasing order */ | 302 | /* ensure we process id in increasing order */ |
285 | qsort(c->map, c->nr, sizeof(int), cmp_ids); | 303 | qsort(c->map, c->nr, sizeof(int), cmp_ids); |
286 | 304 | ||
287 | atomic_set(&cpus->refcnt, 1); | 305 | atomic_set(&c->refcnt, 1); |
288 | *res = c; | 306 | *res = c; |
289 | return 0; | 307 | return 0; |
290 | } | 308 | } |
291 | 309 | ||
292 | int cpu_map__get_core(struct cpu_map *map, int idx) | 310 | int cpu_map__get_core_id(int cpu) |
293 | { | 311 | { |
294 | FILE *fp; | 312 | int value, ret = cpu__get_topology_int(cpu, "core_id", &value); |
295 | const char *mnt; | 313 | return ret ?: value; |
296 | char path[PATH_MAX]; | 314 | } |
297 | int cpu, ret, s; | 315 | |
316 | int cpu_map__get_core(struct cpu_map *map, int idx, void *data) | ||
317 | { | ||
318 | int cpu, s; | ||
298 | 319 | ||
299 | if (idx > map->nr) | 320 | if (idx > map->nr) |
300 | return -1; | 321 | return -1; |
301 | 322 | ||
302 | cpu = map->map[idx]; | 323 | cpu = map->map[idx]; |
303 | 324 | ||
304 | mnt = sysfs__mountpoint(); | 325 | cpu = cpu_map__get_core_id(cpu); |
305 | if (!mnt) | ||
306 | return -1; | ||
307 | |||
308 | snprintf(path, PATH_MAX, | ||
309 | "%s/devices/system/cpu/cpu%d/topology/core_id", | ||
310 | mnt, cpu); | ||
311 | |||
312 | fp = fopen(path, "r"); | ||
313 | if (!fp) | ||
314 | return -1; | ||
315 | ret = fscanf(fp, "%d", &cpu); | ||
316 | fclose(fp); | ||
317 | if (ret != 1) | ||
318 | return -1; | ||
319 | 326 | ||
320 | s = cpu_map__get_socket(map, idx); | 327 | s = cpu_map__get_socket(map, idx, data); |
321 | if (s == -1) | 328 | if (s == -1) |
322 | return -1; | 329 | return -1; |
323 | 330 | ||
@@ -332,12 +339,12 @@ int cpu_map__get_core(struct cpu_map *map, int idx) | |||
332 | 339 | ||
333 | int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp) | 340 | int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp) |
334 | { | 341 | { |
335 | return cpu_map__build_map(cpus, sockp, cpu_map__get_socket); | 342 | return cpu_map__build_map(cpus, sockp, cpu_map__get_socket, NULL); |
336 | } | 343 | } |
337 | 344 | ||
338 | int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep) | 345 | int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep) |
339 | { | 346 | { |
340 | return cpu_map__build_map(cpus, corep, cpu_map__get_core); | 347 | return cpu_map__build_map(cpus, corep, cpu_map__get_core, NULL); |
341 | } | 348 | } |
342 | 349 | ||
343 | /* setup simple routines to easily access node numbers given a cpu number */ | 350 | /* setup simple routines to easily access node numbers given a cpu number */ |
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 0af9cecb4c51..85f7772457fa 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h | |||
@@ -15,11 +15,14 @@ struct cpu_map { | |||
15 | }; | 15 | }; |
16 | 16 | ||
17 | struct cpu_map *cpu_map__new(const char *cpu_list); | 17 | struct cpu_map *cpu_map__new(const char *cpu_list); |
18 | struct cpu_map *cpu_map__empty_new(int nr); | ||
18 | struct cpu_map *cpu_map__dummy_new(void); | 19 | struct cpu_map *cpu_map__dummy_new(void); |
19 | struct cpu_map *cpu_map__read(FILE *file); | 20 | struct cpu_map *cpu_map__read(FILE *file); |
20 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); | 21 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); |
21 | int cpu_map__get_socket(struct cpu_map *map, int idx); | 22 | int cpu_map__get_socket_id(int cpu); |
22 | int cpu_map__get_core(struct cpu_map *map, int idx); | 23 | int cpu_map__get_socket(struct cpu_map *map, int idx, void *data); |
24 | int cpu_map__get_core_id(int cpu); | ||
25 | int cpu_map__get_core(struct cpu_map *map, int idx, void *data); | ||
23 | int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp); | 26 | int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp); |
24 | int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep); | 27 | int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep); |
25 | 28 | ||
@@ -85,4 +88,7 @@ static inline int cpu__get_node(int cpu) | |||
85 | return cpunode_map[cpu]; | 88 | return cpunode_map[cpu]; |
86 | } | 89 | } |
87 | 90 | ||
91 | int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, | ||
92 | int (*f)(struct cpu_map *map, int cpu, void *data), | ||
93 | void *data); | ||
88 | #endif /* __PERF_CPUMAP_H */ | 94 | #endif /* __PERF_CPUMAP_H */ |
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c new file mode 100644 index 000000000000..6af4f7c36820 --- /dev/null +++ b/tools/perf/util/env.c | |||
@@ -0,0 +1,86 @@ | |||
1 | #include "cpumap.h" | ||
2 | #include "env.h" | ||
3 | #include "util.h" | ||
4 | |||
5 | struct perf_env perf_env; | ||
6 | |||
7 | void perf_env__exit(struct perf_env *env) | ||
8 | { | ||
9 | zfree(&env->hostname); | ||
10 | zfree(&env->os_release); | ||
11 | zfree(&env->version); | ||
12 | zfree(&env->arch); | ||
13 | zfree(&env->cpu_desc); | ||
14 | zfree(&env->cpuid); | ||
15 | zfree(&env->cmdline); | ||
16 | zfree(&env->cmdline_argv); | ||
17 | zfree(&env->sibling_cores); | ||
18 | zfree(&env->sibling_threads); | ||
19 | zfree(&env->numa_nodes); | ||
20 | zfree(&env->pmu_mappings); | ||
21 | zfree(&env->cpu); | ||
22 | } | ||
23 | |||
24 | int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) | ||
25 | { | ||
26 | int i; | ||
27 | |||
28 | /* | ||
29 | * If env->cmdline_argv has already been set, do not override it. This allows | ||
30 | * a command to set the cmdline, parse args and then call another | ||
31 | * builtin function that implements a command -- e.g, cmd_kvm calling | ||
32 | * cmd_record. | ||
33 | */ | ||
34 | if (env->cmdline_argv != NULL) | ||
35 | return 0; | ||
36 | |||
37 | /* do not include NULL termination */ | ||
38 | env->cmdline_argv = calloc(argc, sizeof(char *)); | ||
39 | if (env->cmdline_argv == NULL) | ||
40 | goto out_enomem; | ||
41 | |||
42 | /* | ||
43 | * Must copy argv contents because it gets moved around during option | ||
44 | * parsing: | ||
45 | */ | ||
46 | for (i = 0; i < argc ; i++) { | ||
47 | env->cmdline_argv[i] = argv[i]; | ||
48 | if (env->cmdline_argv[i] == NULL) | ||
49 | goto out_free; | ||
50 | } | ||
51 | |||
52 | env->nr_cmdline = argc; | ||
53 | |||
54 | return 0; | ||
55 | out_free: | ||
56 | zfree(&env->cmdline_argv); | ||
57 | out_enomem: | ||
58 | return -ENOMEM; | ||
59 | } | ||
60 | |||
61 | int perf_env__read_cpu_topology_map(struct perf_env *env) | ||
62 | { | ||
63 | int cpu, nr_cpus; | ||
64 | |||
65 | if (env->cpu != NULL) | ||
66 | return 0; | ||
67 | |||
68 | if (env->nr_cpus_avail == 0) | ||
69 | env->nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF); | ||
70 | |||
71 | nr_cpus = env->nr_cpus_avail; | ||
72 | if (nr_cpus == -1) | ||
73 | return -EINVAL; | ||
74 | |||
75 | env->cpu = calloc(nr_cpus, sizeof(env->cpu[0])); | ||
76 | if (env->cpu == NULL) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | for (cpu = 0; cpu < nr_cpus; ++cpu) { | ||
80 | env->cpu[cpu].core_id = cpu_map__get_core_id(cpu); | ||
81 | env->cpu[cpu].socket_id = cpu_map__get_socket_id(cpu); | ||
82 | } | ||
83 | |||
84 | env->nr_cpus_avail = nr_cpus; | ||
85 | return 0; | ||
86 | } | ||
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h new file mode 100644 index 000000000000..0132b9557c02 --- /dev/null +++ b/tools/perf/util/env.h | |||
@@ -0,0 +1,44 @@ | |||
1 | #ifndef __PERF_ENV_H | ||
2 | #define __PERF_ENV_H | ||
3 | |||
4 | struct cpu_topology_map { | ||
5 | int socket_id; | ||
6 | int core_id; | ||
7 | }; | ||
8 | |||
9 | struct perf_env { | ||
10 | char *hostname; | ||
11 | char *os_release; | ||
12 | char *version; | ||
13 | char *arch; | ||
14 | int nr_cpus_online; | ||
15 | int nr_cpus_avail; | ||
16 | char *cpu_desc; | ||
17 | char *cpuid; | ||
18 | unsigned long long total_mem; | ||
19 | unsigned int msr_pmu_type; | ||
20 | |||
21 | int nr_cmdline; | ||
22 | int nr_sibling_cores; | ||
23 | int nr_sibling_threads; | ||
24 | int nr_numa_nodes; | ||
25 | int nr_pmu_mappings; | ||
26 | int nr_groups; | ||
27 | char *cmdline; | ||
28 | const char **cmdline_argv; | ||
29 | char *sibling_cores; | ||
30 | char *sibling_threads; | ||
31 | char *numa_nodes; | ||
32 | char *pmu_mappings; | ||
33 | struct cpu_topology_map *cpu; | ||
34 | }; | ||
35 | |||
36 | extern struct perf_env perf_env; | ||
37 | |||
38 | void perf_env__exit(struct perf_env *env); | ||
39 | |||
40 | int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]); | ||
41 | |||
42 | int perf_env__read_cpu_topology_map(struct perf_env *env); | ||
43 | |||
44 | #endif /* __PERF_ENV_H */ | ||
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 7ff61274ed57..8b10621b415c 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -67,7 +67,8 @@ static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len, | |||
67 | char filename[PATH_MAX]; | 67 | char filename[PATH_MAX]; |
68 | char bf[4096]; | 68 | char bf[4096]; |
69 | int fd; | 69 | int fd; |
70 | size_t size = 0, n; | 70 | size_t size = 0; |
71 | ssize_t n; | ||
71 | char *nl, *name, *tgids, *ppids; | 72 | char *nl, *name, *tgids, *ppids; |
72 | 73 | ||
73 | *tgid = -1; | 74 | *tgid = -1; |
@@ -167,7 +168,7 @@ static int perf_event__prepare_comm(union perf_event *event, pid_t pid, | |||
167 | return 0; | 168 | return 0; |
168 | } | 169 | } |
169 | 170 | ||
170 | static pid_t perf_event__synthesize_comm(struct perf_tool *tool, | 171 | pid_t perf_event__synthesize_comm(struct perf_tool *tool, |
171 | union perf_event *event, pid_t pid, | 172 | union perf_event *event, pid_t pid, |
172 | perf_event__handler_t process, | 173 | perf_event__handler_t process, |
173 | struct machine *machine) | 174 | struct machine *machine) |
@@ -378,7 +379,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool, | |||
378 | for (pos = maps__first(maps); pos; pos = map__next(pos)) { | 379 | for (pos = maps__first(maps); pos; pos = map__next(pos)) { |
379 | size_t size; | 380 | size_t size; |
380 | 381 | ||
381 | if (pos->dso->kernel) | 382 | if (__map__is_kernel(pos)) |
382 | continue; | 383 | continue; |
383 | 384 | ||
384 | size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); | 385 | size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); |
@@ -649,12 +650,12 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, | |||
649 | size_t size; | 650 | size_t size; |
650 | const char *mmap_name; | 651 | const char *mmap_name; |
651 | char name_buff[PATH_MAX]; | 652 | char name_buff[PATH_MAX]; |
652 | struct map *map; | 653 | struct map *map = machine__kernel_map(machine); |
653 | struct kmap *kmap; | 654 | struct kmap *kmap; |
654 | int err; | 655 | int err; |
655 | union perf_event *event; | 656 | union perf_event *event; |
656 | 657 | ||
657 | if (machine->vmlinux_maps[0] == NULL) | 658 | if (map == NULL) |
658 | return -1; | 659 | return -1; |
659 | 660 | ||
660 | /* | 661 | /* |
@@ -680,7 +681,6 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, | |||
680 | event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; | 681 | event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; |
681 | } | 682 | } |
682 | 683 | ||
683 | map = machine->vmlinux_maps[MAP__FUNCTION]; | ||
684 | kmap = map__kmap(map); | 684 | kmap = map__kmap(map); |
685 | size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), | 685 | size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), |
686 | "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; | 686 | "%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1; |
@@ -1008,7 +1008,7 @@ int perf_event__preprocess_sample(const union perf_event *event, | |||
1008 | * it now. | 1008 | * it now. |
1009 | */ | 1009 | */ |
1010 | if (cpumode == PERF_RECORD_MISC_KERNEL && | 1010 | if (cpumode == PERF_RECORD_MISC_KERNEL && |
1011 | machine->vmlinux_maps[MAP__FUNCTION] == NULL) | 1011 | machine__kernel_map(machine) == NULL) |
1012 | machine__create_kernel_maps(machine); | 1012 | machine__create_kernel_maps(machine); |
1013 | 1013 | ||
1014 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al); | 1014 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al); |
@@ -1021,6 +1021,14 @@ int perf_event__preprocess_sample(const union perf_event *event, | |||
1021 | 1021 | ||
1022 | al->sym = NULL; | 1022 | al->sym = NULL; |
1023 | al->cpu = sample->cpu; | 1023 | al->cpu = sample->cpu; |
1024 | al->socket = -1; | ||
1025 | |||
1026 | if (al->cpu >= 0) { | ||
1027 | struct perf_env *env = machine->env; | ||
1028 | |||
1029 | if (env && env->cpu) | ||
1030 | al->socket = env->cpu[al->cpu].socket_id; | ||
1031 | } | ||
1024 | 1032 | ||
1025 | if (al->map) { | 1033 | if (al->map) { |
1026 | struct dso *dso = al->map->dso; | 1034 | struct dso *dso = al->map->dso; |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index f729df5e25e6..a0dbcbd4f6d8 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -257,6 +257,7 @@ struct events_stats { | |||
257 | u64 total_non_filtered_period; | 257 | u64 total_non_filtered_period; |
258 | u64 total_lost; | 258 | u64 total_lost; |
259 | u64 total_lost_samples; | 259 | u64 total_lost_samples; |
260 | u64 total_aux_lost; | ||
260 | u64 total_invalid_chains; | 261 | u64 total_invalid_chains; |
261 | u32 nr_events[PERF_RECORD_HEADER_MAX]; | 262 | u32 nr_events[PERF_RECORD_HEADER_MAX]; |
262 | u32 nr_non_filtered_samples; | 263 | u32 nr_non_filtered_samples; |
@@ -478,6 +479,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
478 | const struct perf_sample *sample, | 479 | const struct perf_sample *sample, |
479 | bool swapped); | 480 | bool swapped); |
480 | 481 | ||
482 | pid_t perf_event__synthesize_comm(struct perf_tool *tool, | ||
483 | union perf_event *event, pid_t pid, | ||
484 | perf_event__handler_t process, | ||
485 | struct machine *machine); | ||
486 | |||
481 | int perf_event__synthesize_mmap_events(struct perf_tool *tool, | 487 | int perf_event__synthesize_mmap_events(struct perf_tool *tool, |
482 | union perf_event *event, | 488 | union perf_event *event, |
483 | pid_t pid, pid_t tgid, | 489 | pid_t pid, pid_t tgid, |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d51a5200c8af..d1392194a9a9 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/bitops.h> | 25 | #include <linux/bitops.h> |
26 | #include <linux/hash.h> | 26 | #include <linux/hash.h> |
27 | #include <linux/log2.h> | 27 | #include <linux/log2.h> |
28 | #include <linux/err.h> | ||
28 | 29 | ||
29 | static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); | 30 | static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); |
30 | static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); | 31 | static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); |
@@ -124,6 +125,33 @@ void perf_evlist__delete(struct perf_evlist *evlist) | |||
124 | free(evlist); | 125 | free(evlist); |
125 | } | 126 | } |
126 | 127 | ||
128 | static void __perf_evlist__propagate_maps(struct perf_evlist *evlist, | ||
129 | struct perf_evsel *evsel) | ||
130 | { | ||
131 | /* | ||
132 | * We already have cpus for evsel (via PMU sysfs) so | ||
133 | * keep it, if there's no target cpu list defined. | ||
134 | */ | ||
135 | if (!evsel->own_cpus || evlist->has_user_cpus) { | ||
136 | cpu_map__put(evsel->cpus); | ||
137 | evsel->cpus = cpu_map__get(evlist->cpus); | ||
138 | } else if (evsel->cpus != evsel->own_cpus) { | ||
139 | cpu_map__put(evsel->cpus); | ||
140 | evsel->cpus = cpu_map__get(evsel->own_cpus); | ||
141 | } | ||
142 | |||
143 | thread_map__put(evsel->threads); | ||
144 | evsel->threads = thread_map__get(evlist->threads); | ||
145 | } | ||
146 | |||
147 | static void perf_evlist__propagate_maps(struct perf_evlist *evlist) | ||
148 | { | ||
149 | struct perf_evsel *evsel; | ||
150 | |||
151 | evlist__for_each(evlist, evsel) | ||
152 | __perf_evlist__propagate_maps(evlist, evsel); | ||
153 | } | ||
154 | |||
127 | void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) | 155 | void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) |
128 | { | 156 | { |
129 | entry->evlist = evlist; | 157 | entry->evlist = evlist; |
@@ -133,18 +161,26 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) | |||
133 | 161 | ||
134 | if (!evlist->nr_entries++) | 162 | if (!evlist->nr_entries++) |
135 | perf_evlist__set_id_pos(evlist); | 163 | perf_evlist__set_id_pos(evlist); |
164 | |||
165 | __perf_evlist__propagate_maps(evlist, entry); | ||
166 | } | ||
167 | |||
168 | void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel) | ||
169 | { | ||
170 | evsel->evlist = NULL; | ||
171 | list_del_init(&evsel->node); | ||
172 | evlist->nr_entries -= 1; | ||
136 | } | 173 | } |
137 | 174 | ||
138 | void perf_evlist__splice_list_tail(struct perf_evlist *evlist, | 175 | void perf_evlist__splice_list_tail(struct perf_evlist *evlist, |
139 | struct list_head *list, | 176 | struct list_head *list) |
140 | int nr_entries) | ||
141 | { | 177 | { |
142 | bool set_id_pos = !evlist->nr_entries; | 178 | struct perf_evsel *evsel, *temp; |
143 | 179 | ||
144 | list_splice_tail(list, &evlist->entries); | 180 | __evlist__for_each_safe(list, temp, evsel) { |
145 | evlist->nr_entries += nr_entries; | 181 | list_del_init(&evsel->node); |
146 | if (set_id_pos) | 182 | perf_evlist__add(evlist, evsel); |
147 | perf_evlist__set_id_pos(evlist); | 183 | } |
148 | } | 184 | } |
149 | 185 | ||
150 | void __perf_evlist__set_leader(struct list_head *list) | 186 | void __perf_evlist__set_leader(struct list_head *list) |
@@ -169,6 +205,20 @@ void perf_evlist__set_leader(struct perf_evlist *evlist) | |||
169 | } | 205 | } |
170 | } | 206 | } |
171 | 207 | ||
208 | void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr) | ||
209 | { | ||
210 | attr->precise_ip = 3; | ||
211 | |||
212 | while (attr->precise_ip != 0) { | ||
213 | int fd = sys_perf_event_open(attr, 0, -1, -1, 0); | ||
214 | if (fd != -1) { | ||
215 | close(fd); | ||
216 | break; | ||
217 | } | ||
218 | --attr->precise_ip; | ||
219 | } | ||
220 | } | ||
221 | |||
172 | int perf_evlist__add_default(struct perf_evlist *evlist) | 222 | int perf_evlist__add_default(struct perf_evlist *evlist) |
173 | { | 223 | { |
174 | struct perf_event_attr attr = { | 224 | struct perf_event_attr attr = { |
@@ -179,13 +229,15 @@ int perf_evlist__add_default(struct perf_evlist *evlist) | |||
179 | 229 | ||
180 | event_attr_init(&attr); | 230 | event_attr_init(&attr); |
181 | 231 | ||
232 | perf_event_attr__set_max_precise_ip(&attr); | ||
233 | |||
182 | evsel = perf_evsel__new(&attr); | 234 | evsel = perf_evsel__new(&attr); |
183 | if (evsel == NULL) | 235 | if (evsel == NULL) |
184 | goto error; | 236 | goto error; |
185 | 237 | ||
186 | /* use strdup() because free(evsel) assumes name is allocated */ | 238 | /* use asprintf() because free(evsel) assumes name is allocated */ |
187 | evsel->name = strdup("cycles"); | 239 | if (asprintf(&evsel->name, "cycles%.*s", |
188 | if (!evsel->name) | 240 | attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0) |
189 | goto error_free; | 241 | goto error_free; |
190 | 242 | ||
191 | perf_evlist__add(evlist, evsel); | 243 | perf_evlist__add(evlist, evsel); |
@@ -210,7 +262,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist, | |||
210 | list_add_tail(&evsel->node, &head); | 262 | list_add_tail(&evsel->node, &head); |
211 | } | 263 | } |
212 | 264 | ||
213 | perf_evlist__splice_list_tail(evlist, &head, nr_attrs); | 265 | perf_evlist__splice_list_tail(evlist, &head); |
214 | 266 | ||
215 | return 0; | 267 | return 0; |
216 | 268 | ||
@@ -265,7 +317,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist, | |||
265 | { | 317 | { |
266 | struct perf_evsel *evsel = perf_evsel__newtp(sys, name); | 318 | struct perf_evsel *evsel = perf_evsel__newtp(sys, name); |
267 | 319 | ||
268 | if (evsel == NULL) | 320 | if (IS_ERR(evsel)) |
269 | return -1; | 321 | return -1; |
270 | 322 | ||
271 | evsel->handler = handler; | 323 | evsel->handler = handler; |
@@ -588,6 +640,21 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) | |||
588 | return NULL; | 640 | return NULL; |
589 | } | 641 | } |
590 | 642 | ||
643 | struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, | ||
644 | u64 id) | ||
645 | { | ||
646 | struct perf_sample_id *sid; | ||
647 | |||
648 | if (!id) | ||
649 | return NULL; | ||
650 | |||
651 | sid = perf_evlist__id2sid(evlist, id); | ||
652 | if (sid) | ||
653 | return sid->evsel; | ||
654 | |||
655 | return NULL; | ||
656 | } | ||
657 | |||
591 | static int perf_evlist__event2id(struct perf_evlist *evlist, | 658 | static int perf_evlist__event2id(struct perf_evlist *evlist, |
592 | union perf_event *event, u64 *id) | 659 | union perf_event *event, u64 *id) |
593 | { | 660 | { |
@@ -1103,71 +1170,56 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, | |||
1103 | return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false); | 1170 | return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false); |
1104 | } | 1171 | } |
1105 | 1172 | ||
1106 | static int perf_evlist__propagate_maps(struct perf_evlist *evlist, | ||
1107 | bool has_user_cpus) | ||
1108 | { | ||
1109 | struct perf_evsel *evsel; | ||
1110 | |||
1111 | evlist__for_each(evlist, evsel) { | ||
1112 | /* | ||
1113 | * We already have cpus for evsel (via PMU sysfs) so | ||
1114 | * keep it, if there's no target cpu list defined. | ||
1115 | */ | ||
1116 | if (evsel->cpus && has_user_cpus) | ||
1117 | cpu_map__put(evsel->cpus); | ||
1118 | |||
1119 | if (!evsel->cpus || has_user_cpus) | ||
1120 | evsel->cpus = cpu_map__get(evlist->cpus); | ||
1121 | |||
1122 | evsel->threads = thread_map__get(evlist->threads); | ||
1123 | |||
1124 | if ((evlist->cpus && !evsel->cpus) || | ||
1125 | (evlist->threads && !evsel->threads)) | ||
1126 | return -ENOMEM; | ||
1127 | } | ||
1128 | |||
1129 | return 0; | ||
1130 | } | ||
1131 | |||
1132 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) | 1173 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) |
1133 | { | 1174 | { |
1134 | evlist->threads = thread_map__new_str(target->pid, target->tid, | 1175 | struct cpu_map *cpus; |
1135 | target->uid); | 1176 | struct thread_map *threads; |
1177 | |||
1178 | threads = thread_map__new_str(target->pid, target->tid, target->uid); | ||
1136 | 1179 | ||
1137 | if (evlist->threads == NULL) | 1180 | if (!threads) |
1138 | return -1; | 1181 | return -1; |
1139 | 1182 | ||
1140 | if (target__uses_dummy_map(target)) | 1183 | if (target__uses_dummy_map(target)) |
1141 | evlist->cpus = cpu_map__dummy_new(); | 1184 | cpus = cpu_map__dummy_new(); |
1142 | else | 1185 | else |
1143 | evlist->cpus = cpu_map__new(target->cpu_list); | 1186 | cpus = cpu_map__new(target->cpu_list); |
1144 | 1187 | ||
1145 | if (evlist->cpus == NULL) | 1188 | if (!cpus) |
1146 | goto out_delete_threads; | 1189 | goto out_delete_threads; |
1147 | 1190 | ||
1148 | return perf_evlist__propagate_maps(evlist, !!target->cpu_list); | 1191 | evlist->has_user_cpus = !!target->cpu_list; |
1192 | |||
1193 | perf_evlist__set_maps(evlist, cpus, threads); | ||
1194 | |||
1195 | return 0; | ||
1149 | 1196 | ||
1150 | out_delete_threads: | 1197 | out_delete_threads: |
1151 | thread_map__put(evlist->threads); | 1198 | thread_map__put(threads); |
1152 | evlist->threads = NULL; | ||
1153 | return -1; | 1199 | return -1; |
1154 | } | 1200 | } |
1155 | 1201 | ||
1156 | int perf_evlist__set_maps(struct perf_evlist *evlist, | 1202 | void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, |
1157 | struct cpu_map *cpus, | 1203 | struct thread_map *threads) |
1158 | struct thread_map *threads) | ||
1159 | { | 1204 | { |
1160 | if (evlist->cpus) | 1205 | /* |
1206 | * Allow for the possibility that one or another of the maps isn't being | ||
1207 | * changed i.e. don't put it. Note we are assuming the maps that are | ||
1208 | * being applied are brand new and evlist is taking ownership of the | ||
1209 | * original reference count of 1. If that is not the case it is up to | ||
1210 | * the caller to increase the reference count. | ||
1211 | */ | ||
1212 | if (cpus != evlist->cpus) { | ||
1161 | cpu_map__put(evlist->cpus); | 1213 | cpu_map__put(evlist->cpus); |
1214 | evlist->cpus = cpus; | ||
1215 | } | ||
1162 | 1216 | ||
1163 | evlist->cpus = cpus; | 1217 | if (threads != evlist->threads) { |
1164 | |||
1165 | if (evlist->threads) | ||
1166 | thread_map__put(evlist->threads); | 1218 | thread_map__put(evlist->threads); |
1219 | evlist->threads = threads; | ||
1220 | } | ||
1167 | 1221 | ||
1168 | evlist->threads = threads; | 1222 | perf_evlist__propagate_maps(evlist); |
1169 | |||
1170 | return perf_evlist__propagate_maps(evlist, false); | ||
1171 | } | 1223 | } |
1172 | 1224 | ||
1173 | int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel) | 1225 | int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel) |
@@ -1387,6 +1439,8 @@ void perf_evlist__close(struct perf_evlist *evlist) | |||
1387 | 1439 | ||
1388 | static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) | 1440 | static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) |
1389 | { | 1441 | { |
1442 | struct cpu_map *cpus; | ||
1443 | struct thread_map *threads; | ||
1390 | int err = -ENOMEM; | 1444 | int err = -ENOMEM; |
1391 | 1445 | ||
1392 | /* | 1446 | /* |
@@ -1398,20 +1452,19 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) | |||
1398 | * error, and we may not want to do that fallback to a | 1452 | * error, and we may not want to do that fallback to a |
1399 | * default cpu identity map :-\ | 1453 | * default cpu identity map :-\ |
1400 | */ | 1454 | */ |
1401 | evlist->cpus = cpu_map__new(NULL); | 1455 | cpus = cpu_map__new(NULL); |
1402 | if (evlist->cpus == NULL) | 1456 | if (!cpus) |
1403 | goto out; | 1457 | goto out; |
1404 | 1458 | ||
1405 | evlist->threads = thread_map__new_dummy(); | 1459 | threads = thread_map__new_dummy(); |
1406 | if (evlist->threads == NULL) | 1460 | if (!threads) |
1407 | goto out_free_cpus; | 1461 | goto out_put; |
1408 | 1462 | ||
1409 | err = 0; | 1463 | perf_evlist__set_maps(evlist, cpus, threads); |
1410 | out: | 1464 | out: |
1411 | return err; | 1465 | return err; |
1412 | out_free_cpus: | 1466 | out_put: |
1413 | cpu_map__put(evlist->cpus); | 1467 | cpu_map__put(cpus); |
1414 | evlist->cpus = NULL; | ||
1415 | goto out; | 1468 | goto out; |
1416 | } | 1469 | } |
1417 | 1470 | ||
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index b39a6198f4ac..a459fe71b452 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -42,6 +42,7 @@ struct perf_evlist { | |||
42 | int nr_mmaps; | 42 | int nr_mmaps; |
43 | bool overwrite; | 43 | bool overwrite; |
44 | bool enabled; | 44 | bool enabled; |
45 | bool has_user_cpus; | ||
45 | size_t mmap_len; | 46 | size_t mmap_len; |
46 | int id_pos; | 47 | int id_pos; |
47 | int is_pos; | 48 | int is_pos; |
@@ -72,6 +73,7 @@ void perf_evlist__exit(struct perf_evlist *evlist); | |||
72 | void perf_evlist__delete(struct perf_evlist *evlist); | 73 | void perf_evlist__delete(struct perf_evlist *evlist); |
73 | 74 | ||
74 | void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); | 75 | void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); |
76 | void perf_evlist__remove(struct perf_evlist *evlist, struct perf_evsel *evsel); | ||
75 | int perf_evlist__add_default(struct perf_evlist *evlist); | 77 | int perf_evlist__add_default(struct perf_evlist *evlist); |
76 | int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, | 78 | int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, |
77 | struct perf_event_attr *attrs, size_t nr_attrs); | 79 | struct perf_event_attr *attrs, size_t nr_attrs); |
@@ -103,6 +105,8 @@ int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mas | |||
103 | int perf_evlist__poll(struct perf_evlist *evlist, int timeout); | 105 | int perf_evlist__poll(struct perf_evlist *evlist, int timeout); |
104 | 106 | ||
105 | struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); | 107 | struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); |
108 | struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist, | ||
109 | u64 id); | ||
106 | 110 | ||
107 | struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); | 111 | struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); |
108 | 112 | ||
@@ -155,9 +159,8 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist, | |||
155 | void perf_evlist__set_selected(struct perf_evlist *evlist, | 159 | void perf_evlist__set_selected(struct perf_evlist *evlist, |
156 | struct perf_evsel *evsel); | 160 | struct perf_evsel *evsel); |
157 | 161 | ||
158 | int perf_evlist__set_maps(struct perf_evlist *evlist, | 162 | void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, |
159 | struct cpu_map *cpus, | 163 | struct thread_map *threads); |
160 | struct thread_map *threads); | ||
161 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); | 164 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); |
162 | int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel); | 165 | int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel); |
163 | 166 | ||
@@ -179,8 +182,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist); | |||
179 | bool perf_evlist__valid_read_format(struct perf_evlist *evlist); | 182 | bool perf_evlist__valid_read_format(struct perf_evlist *evlist); |
180 | 183 | ||
181 | void perf_evlist__splice_list_tail(struct perf_evlist *evlist, | 184 | void perf_evlist__splice_list_tail(struct perf_evlist *evlist, |
182 | struct list_head *list, | 185 | struct list_head *list); |
183 | int nr_entries); | ||
184 | 186 | ||
185 | static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist) | 187 | static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist) |
186 | { | 188 | { |
@@ -288,4 +290,6 @@ void perf_evlist__to_front(struct perf_evlist *evlist, | |||
288 | 290 | ||
289 | void perf_evlist__set_tracking_event(struct perf_evlist *evlist, | 291 | void perf_evlist__set_tracking_event(struct perf_evlist *evlist, |
290 | struct perf_evsel *tracking_evsel); | 292 | struct perf_evsel *tracking_evsel); |
293 | |||
294 | void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr); | ||
291 | #endif /* __PERF_EVLIST_H */ | 295 | #endif /* __PERF_EVLIST_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index c53f79123b37..397fb4ed3c97 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -9,10 +9,11 @@ | |||
9 | 9 | ||
10 | #include <byteswap.h> | 10 | #include <byteswap.h> |
11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
12 | #include <api/fs/debugfs.h> | 12 | #include <api/fs/tracing_path.h> |
13 | #include <traceevent/event-parse.h> | 13 | #include <traceevent/event-parse.h> |
14 | #include <linux/hw_breakpoint.h> | 14 | #include <linux/hw_breakpoint.h> |
15 | #include <linux/perf_event.h> | 15 | #include <linux/perf_event.h> |
16 | #include <linux/err.h> | ||
16 | #include <sys/resource.h> | 17 | #include <sys/resource.h> |
17 | #include "asm/bug.h" | 18 | #include "asm/bug.h" |
18 | #include "callchain.h" | 19 | #include "callchain.h" |
@@ -207,6 +208,7 @@ void perf_evsel__init(struct perf_evsel *evsel, | |||
207 | evsel->unit = ""; | 208 | evsel->unit = ""; |
208 | evsel->scale = 1.0; | 209 | evsel->scale = 1.0; |
209 | evsel->evlist = NULL; | 210 | evsel->evlist = NULL; |
211 | evsel->bpf_fd = -1; | ||
210 | INIT_LIST_HEAD(&evsel->node); | 212 | INIT_LIST_HEAD(&evsel->node); |
211 | INIT_LIST_HEAD(&evsel->config_terms); | 213 | INIT_LIST_HEAD(&evsel->config_terms); |
212 | perf_evsel__object.init(evsel); | 214 | perf_evsel__object.init(evsel); |
@@ -225,11 +227,17 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) | |||
225 | return evsel; | 227 | return evsel; |
226 | } | 228 | } |
227 | 229 | ||
230 | /* | ||
231 | * Returns pointer with encoded error via <linux/err.h> interface. | ||
232 | */ | ||
228 | struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) | 233 | struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) |
229 | { | 234 | { |
230 | struct perf_evsel *evsel = zalloc(perf_evsel__object.size); | 235 | struct perf_evsel *evsel = zalloc(perf_evsel__object.size); |
236 | int err = -ENOMEM; | ||
231 | 237 | ||
232 | if (evsel != NULL) { | 238 | if (evsel == NULL) { |
239 | goto out_err; | ||
240 | } else { | ||
233 | struct perf_event_attr attr = { | 241 | struct perf_event_attr attr = { |
234 | .type = PERF_TYPE_TRACEPOINT, | 242 | .type = PERF_TYPE_TRACEPOINT, |
235 | .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | | 243 | .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | |
@@ -240,8 +248,10 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int | |||
240 | goto out_free; | 248 | goto out_free; |
241 | 249 | ||
242 | evsel->tp_format = trace_event__tp_format(sys, name); | 250 | evsel->tp_format = trace_event__tp_format(sys, name); |
243 | if (evsel->tp_format == NULL) | 251 | if (IS_ERR(evsel->tp_format)) { |
252 | err = PTR_ERR(evsel->tp_format); | ||
244 | goto out_free; | 253 | goto out_free; |
254 | } | ||
245 | 255 | ||
246 | event_attr_init(&attr); | 256 | event_attr_init(&attr); |
247 | attr.config = evsel->tp_format->id; | 257 | attr.config = evsel->tp_format->id; |
@@ -254,7 +264,8 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int | |||
254 | out_free: | 264 | out_free: |
255 | zfree(&evsel->name); | 265 | zfree(&evsel->name); |
256 | free(evsel); | 266 | free(evsel); |
257 | return NULL; | 267 | out_err: |
268 | return ERR_PTR(err); | ||
258 | } | 269 | } |
259 | 270 | ||
260 | const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { | 271 | const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { |
@@ -642,6 +653,15 @@ static void apply_config_terms(struct perf_evsel *evsel, | |||
642 | case PERF_EVSEL__CONFIG_TERM_STACK_USER: | 653 | case PERF_EVSEL__CONFIG_TERM_STACK_USER: |
643 | dump_size = term->val.stack_user; | 654 | dump_size = term->val.stack_user; |
644 | break; | 655 | break; |
656 | case PERF_EVSEL__CONFIG_TERM_INHERIT: | ||
657 | /* | ||
658 | * attr->inherit should has already been set by | ||
659 | * perf_evsel__config. If user explicitly set | ||
660 | * inherit using config terms, override global | ||
661 | * opt->no_inherit setting. | ||
662 | */ | ||
663 | attr->inherit = term->val.inherit ? 1 : 0; | ||
664 | break; | ||
645 | default: | 665 | default: |
646 | break; | 666 | break; |
647 | } | 667 | } |
@@ -872,6 +892,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
872 | attr->clockid = opts->clockid; | 892 | attr->clockid = opts->clockid; |
873 | } | 893 | } |
874 | 894 | ||
895 | if (evsel->precise_max) | ||
896 | perf_event_attr__set_max_precise_ip(attr); | ||
897 | |||
875 | /* | 898 | /* |
876 | * Apply event specific term settings, | 899 | * Apply event specific term settings, |
877 | * it overloads any global configuration. | 900 | * it overloads any global configuration. |
@@ -1033,6 +1056,7 @@ void perf_evsel__exit(struct perf_evsel *evsel) | |||
1033 | perf_evsel__free_config_terms(evsel); | 1056 | perf_evsel__free_config_terms(evsel); |
1034 | close_cgroup(evsel->cgrp); | 1057 | close_cgroup(evsel->cgrp); |
1035 | cpu_map__put(evsel->cpus); | 1058 | cpu_map__put(evsel->cpus); |
1059 | cpu_map__put(evsel->own_cpus); | ||
1036 | thread_map__put(evsel->threads); | 1060 | thread_map__put(evsel->threads); |
1037 | zfree(&evsel->group_name); | 1061 | zfree(&evsel->group_name); |
1038 | zfree(&evsel->name); | 1062 | zfree(&evsel->name); |
@@ -1167,7 +1191,7 @@ static void __p_sample_type(char *buf, size_t size, u64 value) | |||
1167 | bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), | 1191 | bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), |
1168 | bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), | 1192 | bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), |
1169 | bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), | 1193 | bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), |
1170 | bit_name(IDENTIFIER), bit_name(REGS_INTR), | 1194 | bit_name(IDENTIFIER), bit_name(REGS_INTR), bit_name(DATA_SRC), |
1171 | { .name = NULL, } | 1195 | { .name = NULL, } |
1172 | }; | 1196 | }; |
1173 | #undef bit_name | 1197 | #undef bit_name |
@@ -1248,6 +1272,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, | |||
1248 | PRINT_ATTRf(bp_type, p_unsigned); | 1272 | PRINT_ATTRf(bp_type, p_unsigned); |
1249 | PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); | 1273 | PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); |
1250 | PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); | 1274 | PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); |
1275 | PRINT_ATTRf(branch_sample_type, p_unsigned); | ||
1251 | PRINT_ATTRf(sample_regs_user, p_hex); | 1276 | PRINT_ATTRf(sample_regs_user, p_hex); |
1252 | PRINT_ATTRf(sample_stack_user, p_unsigned); | 1277 | PRINT_ATTRf(sample_stack_user, p_unsigned); |
1253 | PRINT_ATTRf(clockid, p_signed); | 1278 | PRINT_ATTRf(clockid, p_signed); |
@@ -1332,6 +1357,22 @@ retry_open: | |||
1332 | err); | 1357 | err); |
1333 | goto try_fallback; | 1358 | goto try_fallback; |
1334 | } | 1359 | } |
1360 | |||
1361 | if (evsel->bpf_fd >= 0) { | ||
1362 | int evt_fd = FD(evsel, cpu, thread); | ||
1363 | int bpf_fd = evsel->bpf_fd; | ||
1364 | |||
1365 | err = ioctl(evt_fd, | ||
1366 | PERF_EVENT_IOC_SET_BPF, | ||
1367 | bpf_fd); | ||
1368 | if (err && errno != EEXIST) { | ||
1369 | pr_err("failed to attach bpf fd %d: %s\n", | ||
1370 | bpf_fd, strerror(errno)); | ||
1371 | err = -EINVAL; | ||
1372 | goto out_close; | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1335 | set_rlimit = NO_CHANGE; | 1376 | set_rlimit = NO_CHANGE; |
1336 | 1377 | ||
1337 | /* | 1378 | /* |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 298e6bbca200..0e49bd742c63 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -43,6 +43,7 @@ enum { | |||
43 | PERF_EVSEL__CONFIG_TERM_TIME, | 43 | PERF_EVSEL__CONFIG_TERM_TIME, |
44 | PERF_EVSEL__CONFIG_TERM_CALLGRAPH, | 44 | PERF_EVSEL__CONFIG_TERM_CALLGRAPH, |
45 | PERF_EVSEL__CONFIG_TERM_STACK_USER, | 45 | PERF_EVSEL__CONFIG_TERM_STACK_USER, |
46 | PERF_EVSEL__CONFIG_TERM_INHERIT, | ||
46 | PERF_EVSEL__CONFIG_TERM_MAX, | 47 | PERF_EVSEL__CONFIG_TERM_MAX, |
47 | }; | 48 | }; |
48 | 49 | ||
@@ -55,6 +56,7 @@ struct perf_evsel_config_term { | |||
55 | bool time; | 56 | bool time; |
56 | char *callgraph; | 57 | char *callgraph; |
57 | u64 stack_user; | 58 | u64 stack_user; |
59 | bool inherit; | ||
58 | } val; | 60 | } val; |
59 | }; | 61 | }; |
60 | 62 | ||
@@ -90,14 +92,15 @@ struct perf_evsel { | |||
90 | double scale; | 92 | double scale; |
91 | const char *unit; | 93 | const char *unit; |
92 | struct event_format *tp_format; | 94 | struct event_format *tp_format; |
95 | off_t id_offset; | ||
93 | union { | 96 | union { |
94 | void *priv; | 97 | void *priv; |
95 | off_t id_offset; | ||
96 | u64 db_id; | 98 | u64 db_id; |
97 | }; | 99 | }; |
98 | struct cgroup_sel *cgrp; | 100 | struct cgroup_sel *cgrp; |
99 | void *handler; | 101 | void *handler; |
100 | struct cpu_map *cpus; | 102 | struct cpu_map *cpus; |
103 | struct cpu_map *own_cpus; | ||
101 | struct thread_map *threads; | 104 | struct thread_map *threads; |
102 | unsigned int sample_size; | 105 | unsigned int sample_size; |
103 | int id_pos; | 106 | int id_pos; |
@@ -110,6 +113,7 @@ struct perf_evsel { | |||
110 | bool system_wide; | 113 | bool system_wide; |
111 | bool tracking; | 114 | bool tracking; |
112 | bool per_pkg; | 115 | bool per_pkg; |
116 | bool precise_max; | ||
113 | /* parse modifier helper */ | 117 | /* parse modifier helper */ |
114 | int exclude_GH; | 118 | int exclude_GH; |
115 | int nr_members; | 119 | int nr_members; |
@@ -119,6 +123,7 @@ struct perf_evsel { | |||
119 | char *group_name; | 123 | char *group_name; |
120 | bool cmdline_group_boundary; | 124 | bool cmdline_group_boundary; |
121 | struct list_head config_terms; | 125 | struct list_head config_terms; |
126 | int bpf_fd; | ||
122 | }; | 127 | }; |
123 | 128 | ||
124 | union u64_swap { | 129 | union u64_swap { |
@@ -129,7 +134,6 @@ union u64_swap { | |||
129 | struct cpu_map; | 134 | struct cpu_map; |
130 | struct target; | 135 | struct target; |
131 | struct thread_map; | 136 | struct thread_map; |
132 | struct perf_evlist; | ||
133 | struct record_opts; | 137 | struct record_opts; |
134 | 138 | ||
135 | static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) | 139 | static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) |
@@ -161,6 +165,9 @@ static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) | |||
161 | 165 | ||
162 | struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx); | 166 | struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx); |
163 | 167 | ||
168 | /* | ||
169 | * Returns pointer with encoded error via <linux/err.h> interface. | ||
170 | */ | ||
164 | static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name) | 171 | static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name) |
165 | { | 172 | { |
166 | return perf_evsel__newtp_idx(sys, name, 0); | 173 | return perf_evsel__newtp_idx(sys, name, 0); |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 41814547da15..43838003c1a1 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -24,9 +24,6 @@ | |||
24 | #include "build-id.h" | 24 | #include "build-id.h" |
25 | #include "data.h" | 25 | #include "data.h" |
26 | 26 | ||
27 | static u32 header_argc; | ||
28 | static const char **header_argv; | ||
29 | |||
30 | /* | 27 | /* |
31 | * magic2 = "PERFILE2" | 28 | * magic2 = "PERFILE2" |
32 | * must be a numerical value to let the endianness | 29 | * must be a numerical value to let the endianness |
@@ -88,6 +85,9 @@ int write_padded(int fd, const void *bf, size_t count, size_t count_aligned) | |||
88 | return err; | 85 | return err; |
89 | } | 86 | } |
90 | 87 | ||
88 | #define string_size(str) \ | ||
89 | (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32)) | ||
90 | |||
91 | static int do_write_string(int fd, const char *str) | 91 | static int do_write_string(int fd, const char *str) |
92 | { | 92 | { |
93 | u32 len, olen; | 93 | u32 len, olen; |
@@ -135,37 +135,6 @@ static char *do_read_string(int fd, struct perf_header *ph) | |||
135 | return NULL; | 135 | return NULL; |
136 | } | 136 | } |
137 | 137 | ||
138 | int | ||
139 | perf_header__set_cmdline(int argc, const char **argv) | ||
140 | { | ||
141 | int i; | ||
142 | |||
143 | /* | ||
144 | * If header_argv has already been set, do not override it. | ||
145 | * This allows a command to set the cmdline, parse args and | ||
146 | * then call another builtin function that implements a | ||
147 | * command -- e.g, cmd_kvm calling cmd_record. | ||
148 | */ | ||
149 | if (header_argv) | ||
150 | return 0; | ||
151 | |||
152 | header_argc = (u32)argc; | ||
153 | |||
154 | /* do not include NULL termination */ | ||
155 | header_argv = calloc(argc, sizeof(char *)); | ||
156 | if (!header_argv) | ||
157 | return -ENOMEM; | ||
158 | |||
159 | /* | ||
160 | * must copy argv contents because it gets moved | ||
161 | * around during option parsing | ||
162 | */ | ||
163 | for (i = 0; i < argc ; i++) | ||
164 | header_argv[i] = argv[i]; | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, | 138 | static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, |
170 | struct perf_evlist *evlist) | 139 | struct perf_evlist *evlist) |
171 | { | 140 | { |
@@ -402,8 +371,8 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused, | |||
402 | { | 371 | { |
403 | char buf[MAXPATHLEN]; | 372 | char buf[MAXPATHLEN]; |
404 | char proc[32]; | 373 | char proc[32]; |
405 | u32 i, n; | 374 | u32 n; |
406 | int ret; | 375 | int i, ret; |
407 | 376 | ||
408 | /* | 377 | /* |
409 | * actual atual path to perf binary | 378 | * actual atual path to perf binary |
@@ -417,7 +386,7 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused, | |||
417 | buf[ret] = '\0'; | 386 | buf[ret] = '\0'; |
418 | 387 | ||
419 | /* account for binary path */ | 388 | /* account for binary path */ |
420 | n = header_argc + 1; | 389 | n = perf_env.nr_cmdline + 1; |
421 | 390 | ||
422 | ret = do_write(fd, &n, sizeof(n)); | 391 | ret = do_write(fd, &n, sizeof(n)); |
423 | if (ret < 0) | 392 | if (ret < 0) |
@@ -427,8 +396,8 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused, | |||
427 | if (ret < 0) | 396 | if (ret < 0) |
428 | return ret; | 397 | return ret; |
429 | 398 | ||
430 | for (i = 0 ; i < header_argc; i++) { | 399 | for (i = 0 ; i < perf_env.nr_cmdline; i++) { |
431 | ret = do_write_string(fd, header_argv[i]); | 400 | ret = do_write_string(fd, perf_env.cmdline_argv[i]); |
432 | if (ret < 0) | 401 | if (ret < 0) |
433 | return ret; | 402 | return ret; |
434 | } | 403 | } |
@@ -441,6 +410,7 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused, | |||
441 | "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list" | 410 | "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list" |
442 | 411 | ||
443 | struct cpu_topo { | 412 | struct cpu_topo { |
413 | u32 cpu_nr; | ||
444 | u32 core_sib; | 414 | u32 core_sib; |
445 | u32 thread_sib; | 415 | u32 thread_sib; |
446 | char **core_siblings; | 416 | char **core_siblings; |
@@ -551,7 +521,7 @@ static struct cpu_topo *build_cpu_topology(void) | |||
551 | return NULL; | 521 | return NULL; |
552 | 522 | ||
553 | tp = addr; | 523 | tp = addr; |
554 | 524 | tp->cpu_nr = nr; | |
555 | addr += sizeof(*tp); | 525 | addr += sizeof(*tp); |
556 | tp->core_siblings = addr; | 526 | tp->core_siblings = addr; |
557 | addr += sz; | 527 | addr += sz; |
@@ -574,7 +544,7 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, | |||
574 | { | 544 | { |
575 | struct cpu_topo *tp; | 545 | struct cpu_topo *tp; |
576 | u32 i; | 546 | u32 i; |
577 | int ret; | 547 | int ret, j; |
578 | 548 | ||
579 | tp = build_cpu_topology(); | 549 | tp = build_cpu_topology(); |
580 | if (!tp) | 550 | if (!tp) |
@@ -598,6 +568,21 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, | |||
598 | if (ret < 0) | 568 | if (ret < 0) |
599 | break; | 569 | break; |
600 | } | 570 | } |
571 | |||
572 | ret = perf_env__read_cpu_topology_map(&perf_env); | ||
573 | if (ret < 0) | ||
574 | goto done; | ||
575 | |||
576 | for (j = 0; j < perf_env.nr_cpus_avail; j++) { | ||
577 | ret = do_write(fd, &perf_env.cpu[j].core_id, | ||
578 | sizeof(perf_env.cpu[j].core_id)); | ||
579 | if (ret < 0) | ||
580 | return ret; | ||
581 | ret = do_write(fd, &perf_env.cpu[j].socket_id, | ||
582 | sizeof(perf_env.cpu[j].socket_id)); | ||
583 | if (ret < 0) | ||
584 | return ret; | ||
585 | } | ||
601 | done: | 586 | done: |
602 | free_cpu_topo(tp); | 587 | free_cpu_topo(tp); |
603 | return ret; | 588 | return ret; |
@@ -938,6 +923,7 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused, | |||
938 | { | 923 | { |
939 | int nr, i; | 924 | int nr, i; |
940 | char *str; | 925 | char *str; |
926 | int cpu_nr = ph->env.nr_cpus_online; | ||
941 | 927 | ||
942 | nr = ph->env.nr_sibling_cores; | 928 | nr = ph->env.nr_sibling_cores; |
943 | str = ph->env.sibling_cores; | 929 | str = ph->env.sibling_cores; |
@@ -954,6 +940,13 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused, | |||
954 | fprintf(fp, "# sibling threads : %s\n", str); | 940 | fprintf(fp, "# sibling threads : %s\n", str); |
955 | str += strlen(str) + 1; | 941 | str += strlen(str) + 1; |
956 | } | 942 | } |
943 | |||
944 | if (ph->env.cpu != NULL) { | ||
945 | for (i = 0; i < cpu_nr; i++) | ||
946 | fprintf(fp, "# CPU %d: Core ID %d, Socket ID %d\n", i, | ||
947 | ph->env.cpu[i].core_id, ph->env.cpu[i].socket_id); | ||
948 | } else | ||
949 | fprintf(fp, "# Core ID and Socket ID information is not available\n"); | ||
957 | } | 950 | } |
958 | 951 | ||
959 | static void free_event_desc(struct perf_evsel *events) | 952 | static void free_event_desc(struct perf_evsel *events) |
@@ -1438,7 +1431,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, | |||
1438 | if (ph->needs_swap) | 1431 | if (ph->needs_swap) |
1439 | nr = bswap_32(nr); | 1432 | nr = bswap_32(nr); |
1440 | 1433 | ||
1441 | ph->env.nr_cpus_online = nr; | 1434 | ph->env.nr_cpus_avail = nr; |
1442 | 1435 | ||
1443 | ret = readn(fd, &nr, sizeof(nr)); | 1436 | ret = readn(fd, &nr, sizeof(nr)); |
1444 | if (ret != sizeof(nr)) | 1437 | if (ret != sizeof(nr)) |
@@ -1447,7 +1440,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, | |||
1447 | if (ph->needs_swap) | 1440 | if (ph->needs_swap) |
1448 | nr = bswap_32(nr); | 1441 | nr = bswap_32(nr); |
1449 | 1442 | ||
1450 | ph->env.nr_cpus_avail = nr; | 1443 | ph->env.nr_cpus_online = nr; |
1451 | return 0; | 1444 | return 0; |
1452 | } | 1445 | } |
1453 | 1446 | ||
@@ -1582,7 +1575,7 @@ error: | |||
1582 | return -1; | 1575 | return -1; |
1583 | } | 1576 | } |
1584 | 1577 | ||
1585 | static int process_cpu_topology(struct perf_file_section *section __maybe_unused, | 1578 | static int process_cpu_topology(struct perf_file_section *section, |
1586 | struct perf_header *ph, int fd, | 1579 | struct perf_header *ph, int fd, |
1587 | void *data __maybe_unused) | 1580 | void *data __maybe_unused) |
1588 | { | 1581 | { |
@@ -1590,15 +1583,22 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused | |||
1590 | u32 nr, i; | 1583 | u32 nr, i; |
1591 | char *str; | 1584 | char *str; |
1592 | struct strbuf sb; | 1585 | struct strbuf sb; |
1586 | int cpu_nr = ph->env.nr_cpus_online; | ||
1587 | u64 size = 0; | ||
1588 | |||
1589 | ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu)); | ||
1590 | if (!ph->env.cpu) | ||
1591 | return -1; | ||
1593 | 1592 | ||
1594 | ret = readn(fd, &nr, sizeof(nr)); | 1593 | ret = readn(fd, &nr, sizeof(nr)); |
1595 | if (ret != sizeof(nr)) | 1594 | if (ret != sizeof(nr)) |
1596 | return -1; | 1595 | goto free_cpu; |
1597 | 1596 | ||
1598 | if (ph->needs_swap) | 1597 | if (ph->needs_swap) |
1599 | nr = bswap_32(nr); | 1598 | nr = bswap_32(nr); |
1600 | 1599 | ||
1601 | ph->env.nr_sibling_cores = nr; | 1600 | ph->env.nr_sibling_cores = nr; |
1601 | size += sizeof(u32); | ||
1602 | strbuf_init(&sb, 128); | 1602 | strbuf_init(&sb, 128); |
1603 | 1603 | ||
1604 | for (i = 0; i < nr; i++) { | 1604 | for (i = 0; i < nr; i++) { |
@@ -1608,6 +1608,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused | |||
1608 | 1608 | ||
1609 | /* include a NULL character at the end */ | 1609 | /* include a NULL character at the end */ |
1610 | strbuf_add(&sb, str, strlen(str) + 1); | 1610 | strbuf_add(&sb, str, strlen(str) + 1); |
1611 | size += string_size(str); | ||
1611 | free(str); | 1612 | free(str); |
1612 | } | 1613 | } |
1613 | ph->env.sibling_cores = strbuf_detach(&sb, NULL); | 1614 | ph->env.sibling_cores = strbuf_detach(&sb, NULL); |
@@ -1620,6 +1621,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused | |||
1620 | nr = bswap_32(nr); | 1621 | nr = bswap_32(nr); |
1621 | 1622 | ||
1622 | ph->env.nr_sibling_threads = nr; | 1623 | ph->env.nr_sibling_threads = nr; |
1624 | size += sizeof(u32); | ||
1623 | 1625 | ||
1624 | for (i = 0; i < nr; i++) { | 1626 | for (i = 0; i < nr; i++) { |
1625 | str = do_read_string(fd, ph); | 1627 | str = do_read_string(fd, ph); |
@@ -1628,13 +1630,57 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused | |||
1628 | 1630 | ||
1629 | /* include a NULL character at the end */ | 1631 | /* include a NULL character at the end */ |
1630 | strbuf_add(&sb, str, strlen(str) + 1); | 1632 | strbuf_add(&sb, str, strlen(str) + 1); |
1633 | size += string_size(str); | ||
1631 | free(str); | 1634 | free(str); |
1632 | } | 1635 | } |
1633 | ph->env.sibling_threads = strbuf_detach(&sb, NULL); | 1636 | ph->env.sibling_threads = strbuf_detach(&sb, NULL); |
1637 | |||
1638 | /* | ||
1639 | * The header may be from old perf, | ||
1640 | * which doesn't include core id and socket id information. | ||
1641 | */ | ||
1642 | if (section->size <= size) { | ||
1643 | zfree(&ph->env.cpu); | ||
1644 | return 0; | ||
1645 | } | ||
1646 | |||
1647 | for (i = 0; i < (u32)cpu_nr; i++) { | ||
1648 | ret = readn(fd, &nr, sizeof(nr)); | ||
1649 | if (ret != sizeof(nr)) | ||
1650 | goto free_cpu; | ||
1651 | |||
1652 | if (ph->needs_swap) | ||
1653 | nr = bswap_32(nr); | ||
1654 | |||
1655 | if (nr > (u32)cpu_nr) { | ||
1656 | pr_debug("core_id number is too big." | ||
1657 | "You may need to upgrade the perf tool.\n"); | ||
1658 | goto free_cpu; | ||
1659 | } | ||
1660 | ph->env.cpu[i].core_id = nr; | ||
1661 | |||
1662 | ret = readn(fd, &nr, sizeof(nr)); | ||
1663 | if (ret != sizeof(nr)) | ||
1664 | goto free_cpu; | ||
1665 | |||
1666 | if (ph->needs_swap) | ||
1667 | nr = bswap_32(nr); | ||
1668 | |||
1669 | if (nr > (u32)cpu_nr) { | ||
1670 | pr_debug("socket_id number is too big." | ||
1671 | "You may need to upgrade the perf tool.\n"); | ||
1672 | goto free_cpu; | ||
1673 | } | ||
1674 | |||
1675 | ph->env.cpu[i].socket_id = nr; | ||
1676 | } | ||
1677 | |||
1634 | return 0; | 1678 | return 0; |
1635 | 1679 | ||
1636 | error: | 1680 | error: |
1637 | strbuf_release(&sb); | 1681 | strbuf_release(&sb); |
1682 | free_cpu: | ||
1683 | zfree(&ph->env.cpu); | ||
1638 | return -1; | 1684 | return -1; |
1639 | } | 1685 | } |
1640 | 1686 | ||
@@ -1737,6 +1783,9 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused | |||
1737 | /* include a NULL character at the end */ | 1783 | /* include a NULL character at the end */ |
1738 | strbuf_add(&sb, "", 1); | 1784 | strbuf_add(&sb, "", 1); |
1739 | 1785 | ||
1786 | if (!strcmp(name, "msr")) | ||
1787 | ph->env.msr_pmu_type = type; | ||
1788 | |||
1740 | free(name); | 1789 | free(name); |
1741 | pmu_num--; | 1790 | pmu_num--; |
1742 | } | 1791 | } |
@@ -2515,6 +2564,7 @@ int perf_session__read_header(struct perf_session *session) | |||
2515 | return -ENOMEM; | 2564 | return -ENOMEM; |
2516 | 2565 | ||
2517 | session->evlist->env = &header->env; | 2566 | session->evlist->env = &header->env; |
2567 | session->machines.host.env = &header->env; | ||
2518 | if (perf_data_file__is_pipe(file)) | 2568 | if (perf_data_file__is_pipe(file)) |
2519 | return perf_header__read_pipe(session); | 2569 | return perf_header__read_pipe(session); |
2520 | 2570 | ||
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 396e4965f0c9..05f27cb6b7e3 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #include <linux/bitmap.h> | 7 | #include <linux/bitmap.h> |
8 | #include <linux/types.h> | 8 | #include <linux/types.h> |
9 | #include "event.h" | 9 | #include "event.h" |
10 | 10 | #include "env.h" | |
11 | 11 | ||
12 | enum { | 12 | enum { |
13 | HEADER_RESERVED = 0, /* always cleared */ | 13 | HEADER_RESERVED = 0, /* always cleared */ |
@@ -66,31 +66,6 @@ struct perf_header; | |||
66 | int perf_file_header__read(struct perf_file_header *header, | 66 | int perf_file_header__read(struct perf_file_header *header, |
67 | struct perf_header *ph, int fd); | 67 | struct perf_header *ph, int fd); |
68 | 68 | ||
69 | struct perf_env { | ||
70 | char *hostname; | ||
71 | char *os_release; | ||
72 | char *version; | ||
73 | char *arch; | ||
74 | int nr_cpus_online; | ||
75 | int nr_cpus_avail; | ||
76 | char *cpu_desc; | ||
77 | char *cpuid; | ||
78 | unsigned long long total_mem; | ||
79 | |||
80 | int nr_cmdline; | ||
81 | int nr_sibling_cores; | ||
82 | int nr_sibling_threads; | ||
83 | int nr_numa_nodes; | ||
84 | int nr_pmu_mappings; | ||
85 | int nr_groups; | ||
86 | char *cmdline; | ||
87 | const char **cmdline_argv; | ||
88 | char *sibling_cores; | ||
89 | char *sibling_threads; | ||
90 | char *numa_nodes; | ||
91 | char *pmu_mappings; | ||
92 | }; | ||
93 | |||
94 | struct perf_header { | 69 | struct perf_header { |
95 | enum perf_header_version version; | 70 | enum perf_header_version version; |
96 | bool needs_swap; | 71 | bool needs_swap; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 08b6cd945f1e..4fd37d6708cb 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -15,6 +15,8 @@ static bool hists__filter_entry_by_thread(struct hists *hists, | |||
15 | struct hist_entry *he); | 15 | struct hist_entry *he); |
16 | static bool hists__filter_entry_by_symbol(struct hists *hists, | 16 | static bool hists__filter_entry_by_symbol(struct hists *hists, |
17 | struct hist_entry *he); | 17 | struct hist_entry *he); |
18 | static bool hists__filter_entry_by_socket(struct hists *hists, | ||
19 | struct hist_entry *he); | ||
18 | 20 | ||
19 | u16 hists__col_len(struct hists *hists, enum hist_column col) | 21 | u16 hists__col_len(struct hists *hists, enum hist_column col) |
20 | { | 22 | { |
@@ -130,6 +132,18 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) | |||
130 | hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, | 132 | hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, |
131 | symlen); | 133 | symlen); |
132 | } | 134 | } |
135 | |||
136 | if (h->mem_info->iaddr.sym) { | ||
137 | symlen = (int)h->mem_info->iaddr.sym->namelen + 4 | ||
138 | + unresolved_col_width + 2; | ||
139 | hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL, | ||
140 | symlen); | ||
141 | } else { | ||
142 | symlen = unresolved_col_width + 4 + 2; | ||
143 | hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL, | ||
144 | symlen); | ||
145 | } | ||
146 | |||
133 | if (h->mem_info->daddr.map) { | 147 | if (h->mem_info->daddr.map) { |
134 | symlen = dso__name_len(h->mem_info->daddr.map->dso); | 148 | symlen = dso__name_len(h->mem_info->daddr.map->dso); |
135 | hists__new_col_len(hists, HISTC_MEM_DADDR_DSO, | 149 | hists__new_col_len(hists, HISTC_MEM_DADDR_DSO, |
@@ -141,9 +155,12 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) | |||
141 | } else { | 155 | } else { |
142 | symlen = unresolved_col_width + 4 + 2; | 156 | symlen = unresolved_col_width + 4 + 2; |
143 | hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen); | 157 | hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen); |
158 | hists__new_col_len(hists, HISTC_MEM_IADDR_SYMBOL, symlen); | ||
144 | hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); | 159 | hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); |
145 | } | 160 | } |
146 | 161 | ||
162 | hists__new_col_len(hists, HISTC_CPU, 3); | ||
163 | hists__new_col_len(hists, HISTC_SOCKET, 6); | ||
147 | hists__new_col_len(hists, HISTC_MEM_LOCKED, 6); | 164 | hists__new_col_len(hists, HISTC_MEM_LOCKED, 6); |
148 | hists__new_col_len(hists, HISTC_MEM_TLB, 22); | 165 | hists__new_col_len(hists, HISTC_MEM_TLB, 22); |
149 | hists__new_col_len(hists, HISTC_MEM_SNOOP, 12); | 166 | hists__new_col_len(hists, HISTC_MEM_SNOOP, 12); |
@@ -452,6 +469,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists, | |||
452 | .map = al->map, | 469 | .map = al->map, |
453 | .sym = al->sym, | 470 | .sym = al->sym, |
454 | }, | 471 | }, |
472 | .socket = al->socket, | ||
455 | .cpu = al->cpu, | 473 | .cpu = al->cpu, |
456 | .cpumode = al->cpumode, | 474 | .cpumode = al->cpumode, |
457 | .ip = al->addr, | 475 | .ip = al->addr, |
@@ -690,7 +708,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter, | |||
690 | } | 708 | } |
691 | 709 | ||
692 | static int | 710 | static int |
693 | iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused, | 711 | iter_prepare_cumulative_entry(struct hist_entry_iter *iter, |
694 | struct addr_location *al __maybe_unused) | 712 | struct addr_location *al __maybe_unused) |
695 | { | 713 | { |
696 | struct hist_entry **he_cache; | 714 | struct hist_entry **he_cache; |
@@ -702,7 +720,7 @@ iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused, | |||
702 | * cumulated only one time to prevent entries more than 100% | 720 | * cumulated only one time to prevent entries more than 100% |
703 | * overhead. | 721 | * overhead. |
704 | */ | 722 | */ |
705 | he_cache = malloc(sizeof(*he_cache) * (PERF_MAX_STACK_DEPTH + 1)); | 723 | he_cache = malloc(sizeof(*he_cache) * (iter->max_stack + 1)); |
706 | if (he_cache == NULL) | 724 | if (he_cache == NULL) |
707 | return -ENOMEM; | 725 | return -ENOMEM; |
708 | 726 | ||
@@ -863,6 +881,8 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, | |||
863 | if (err) | 881 | if (err) |
864 | return err; | 882 | return err; |
865 | 883 | ||
884 | iter->max_stack = max_stack_depth; | ||
885 | |||
866 | err = iter->ops->prepare_entry(iter, al); | 886 | err = iter->ops->prepare_entry(iter, al); |
867 | if (err) | 887 | if (err) |
868 | goto out; | 888 | goto out; |
@@ -1024,6 +1044,7 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he) | |||
1024 | hists__filter_entry_by_dso(hists, he); | 1044 | hists__filter_entry_by_dso(hists, he); |
1025 | hists__filter_entry_by_thread(hists, he); | 1045 | hists__filter_entry_by_thread(hists, he); |
1026 | hists__filter_entry_by_symbol(hists, he); | 1046 | hists__filter_entry_by_symbol(hists, he); |
1047 | hists__filter_entry_by_socket(hists, he); | ||
1027 | } | 1048 | } |
1028 | 1049 | ||
1029 | void hists__collapse_resort(struct hists *hists, struct ui_progress *prog) | 1050 | void hists__collapse_resort(struct hists *hists, struct ui_progress *prog) |
@@ -1143,7 +1164,7 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog) | |||
1143 | struct perf_evsel *evsel = hists_to_evsel(hists); | 1164 | struct perf_evsel *evsel = hists_to_evsel(hists); |
1144 | bool use_callchain; | 1165 | bool use_callchain; |
1145 | 1166 | ||
1146 | if (evsel && !symbol_conf.show_ref_callgraph) | 1167 | if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) |
1147 | use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN; | 1168 | use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN; |
1148 | else | 1169 | else |
1149 | use_callchain = symbol_conf.use_callchain; | 1170 | use_callchain = symbol_conf.use_callchain; |
@@ -1292,6 +1313,37 @@ void hists__filter_by_symbol(struct hists *hists) | |||
1292 | } | 1313 | } |
1293 | } | 1314 | } |
1294 | 1315 | ||
1316 | static bool hists__filter_entry_by_socket(struct hists *hists, | ||
1317 | struct hist_entry *he) | ||
1318 | { | ||
1319 | if ((hists->socket_filter > -1) && | ||
1320 | (he->socket != hists->socket_filter)) { | ||
1321 | he->filtered |= (1 << HIST_FILTER__SOCKET); | ||
1322 | return true; | ||
1323 | } | ||
1324 | |||
1325 | return false; | ||
1326 | } | ||
1327 | |||
1328 | void hists__filter_by_socket(struct hists *hists) | ||
1329 | { | ||
1330 | struct rb_node *nd; | ||
1331 | |||
1332 | hists->stats.nr_non_filtered_samples = 0; | ||
1333 | |||
1334 | hists__reset_filter_stats(hists); | ||
1335 | hists__reset_col_len(hists); | ||
1336 | |||
1337 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { | ||
1338 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | ||
1339 | |||
1340 | if (hists__filter_entry_by_socket(hists, h)) | ||
1341 | continue; | ||
1342 | |||
1343 | hists__remove_entry_filter(hists, h, HIST_FILTER__SOCKET); | ||
1344 | } | ||
1345 | } | ||
1346 | |||
1295 | void events_stats__inc(struct events_stats *stats, u32 type) | 1347 | void events_stats__inc(struct events_stats *stats, u32 type) |
1296 | { | 1348 | { |
1297 | ++stats->nr_events[0]; | 1349 | ++stats->nr_events[0]; |
@@ -1517,6 +1569,7 @@ static int hists_evsel__init(struct perf_evsel *evsel) | |||
1517 | hists->entries_collapsed = RB_ROOT; | 1569 | hists->entries_collapsed = RB_ROOT; |
1518 | hists->entries = RB_ROOT; | 1570 | hists->entries = RB_ROOT; |
1519 | pthread_mutex_init(&hists->lock, NULL); | 1571 | pthread_mutex_init(&hists->lock, NULL); |
1572 | hists->socket_filter = -1; | ||
1520 | return 0; | 1573 | return 0; |
1521 | } | 1574 | } |
1522 | 1575 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index de6d58e7f0d5..a48a2078d288 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -20,6 +20,7 @@ enum hist_filter { | |||
20 | HIST_FILTER__SYMBOL, | 20 | HIST_FILTER__SYMBOL, |
21 | HIST_FILTER__GUEST, | 21 | HIST_FILTER__GUEST, |
22 | HIST_FILTER__HOST, | 22 | HIST_FILTER__HOST, |
23 | HIST_FILTER__SOCKET, | ||
23 | }; | 24 | }; |
24 | 25 | ||
25 | enum hist_column { | 26 | enum hist_column { |
@@ -29,6 +30,7 @@ enum hist_column { | |||
29 | HISTC_COMM, | 30 | HISTC_COMM, |
30 | HISTC_PARENT, | 31 | HISTC_PARENT, |
31 | HISTC_CPU, | 32 | HISTC_CPU, |
33 | HISTC_SOCKET, | ||
32 | HISTC_SRCLINE, | 34 | HISTC_SRCLINE, |
33 | HISTC_SRCFILE, | 35 | HISTC_SRCFILE, |
34 | HISTC_MISPREDICT, | 36 | HISTC_MISPREDICT, |
@@ -47,6 +49,7 @@ enum hist_column { | |||
47 | HISTC_MEM_LVL, | 49 | HISTC_MEM_LVL, |
48 | HISTC_MEM_SNOOP, | 50 | HISTC_MEM_SNOOP, |
49 | HISTC_MEM_DCACHELINE, | 51 | HISTC_MEM_DCACHELINE, |
52 | HISTC_MEM_IADDR_SYMBOL, | ||
50 | HISTC_TRANSACTION, | 53 | HISTC_TRANSACTION, |
51 | HISTC_CYCLES, | 54 | HISTC_CYCLES, |
52 | HISTC_NR_COLS, /* Last entry */ | 55 | HISTC_NR_COLS, /* Last entry */ |
@@ -70,6 +73,7 @@ struct hists { | |||
70 | struct events_stats stats; | 73 | struct events_stats stats; |
71 | u64 event_stream; | 74 | u64 event_stream; |
72 | u16 col_len[HISTC_NR_COLS]; | 75 | u16 col_len[HISTC_NR_COLS]; |
76 | int socket_filter; | ||
73 | }; | 77 | }; |
74 | 78 | ||
75 | struct hist_entry_iter; | 79 | struct hist_entry_iter; |
@@ -87,6 +91,7 @@ struct hist_entry_iter { | |||
87 | int curr; | 91 | int curr; |
88 | 92 | ||
89 | bool hide_unresolved; | 93 | bool hide_unresolved; |
94 | int max_stack; | ||
90 | 95 | ||
91 | struct perf_evsel *evsel; | 96 | struct perf_evsel *evsel; |
92 | struct perf_sample *sample; | 97 | struct perf_sample *sample; |
@@ -144,11 +149,12 @@ size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp); | |||
144 | void hists__filter_by_dso(struct hists *hists); | 149 | void hists__filter_by_dso(struct hists *hists); |
145 | void hists__filter_by_thread(struct hists *hists); | 150 | void hists__filter_by_thread(struct hists *hists); |
146 | void hists__filter_by_symbol(struct hists *hists); | 151 | void hists__filter_by_symbol(struct hists *hists); |
152 | void hists__filter_by_socket(struct hists *hists); | ||
147 | 153 | ||
148 | static inline bool hists__has_filter(struct hists *hists) | 154 | static inline bool hists__has_filter(struct hists *hists) |
149 | { | 155 | { |
150 | return hists->thread_filter || hists->dso_filter || | 156 | return hists->thread_filter || hists->dso_filter || |
151 | hists->symbol_filter_str; | 157 | hists->symbol_filter_str || (hists->socket_filter > -1); |
152 | } | 158 | } |
153 | 159 | ||
154 | u16 hists__col_len(struct hists *hists, enum hist_column col); | 160 | u16 hists__col_len(struct hists *hists, enum hist_column col); |
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h index 8f149655f497..07c644ed64c4 100644 --- a/tools/perf/util/include/dwarf-regs.h +++ b/tools/perf/util/include/dwarf-regs.h | |||
@@ -5,4 +5,12 @@ | |||
5 | const char *get_arch_regstr(unsigned int n); | 5 | const char *get_arch_regstr(unsigned int n); |
6 | #endif | 6 | #endif |
7 | 7 | ||
8 | #ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET | ||
9 | /* | ||
10 | * Arch should support fetching the offset of a register in pt_regs | ||
11 | * by its name. See kernel's regs_query_register_offset in | ||
12 | * arch/xxx/kernel/ptrace.c. | ||
13 | */ | ||
14 | int regs_query_register_offset(const char *name); | ||
15 | #endif | ||
8 | #endif | 16 | #endif |
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index ea768625ab5b..eb0e7f8bf515 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c | |||
@@ -623,7 +623,7 @@ static int intel_bts_process_event(struct perf_session *session, | |||
623 | if (err) | 623 | if (err) |
624 | return err; | 624 | return err; |
625 | if (event->header.type == PERF_RECORD_EXIT) { | 625 | if (event->header.type == PERF_RECORD_EXIT) { |
626 | err = intel_bts_process_tid_exit(bts, event->comm.tid); | 626 | err = intel_bts_process_tid_exit(bts, event->fork.tid); |
627 | if (err) | 627 | if (err) |
628 | return err; | 628 | return err; |
629 | } | 629 | } |
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build index 2386322ece4f..0611d619a42e 100644 --- a/tools/perf/util/intel-pt-decoder/Build +++ b/tools/perf/util/intel-pt-decoder/Build | |||
@@ -7,6 +7,17 @@ $(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_table | |||
7 | $(call rule_mkdir) | 7 | $(call rule_mkdir) |
8 | @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@ | 8 | @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@ |
9 | 9 | ||
10 | $(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c | 10 | $(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/intel-pt-insn-decoder.c util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c |
11 | @(test -d ../../kernel -a -d ../../tools -a -d ../perf && (( \ | ||
12 | diff -B -I'^#include' util/intel-pt-decoder/insn.c ../../arch/x86/lib/insn.c >/dev/null && \ | ||
13 | diff -B -I'^#include' util/intel-pt-decoder/inat.c ../../arch/x86/lib/inat.c >/dev/null && \ | ||
14 | diff -B util/intel-pt-decoder/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \ | ||
15 | diff -B util/intel-pt-decoder/gen-insn-attr-x86.awk ../../arch/x86/tools/gen-insn-attr-x86.awk >/dev/null && \ | ||
16 | diff -B -I'^#include' util/intel-pt-decoder/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \ | ||
17 | diff -B -I'^#include' util/intel-pt-decoder/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \ | ||
18 | diff -B -I'^#include' util/intel-pt-decoder/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \ | ||
19 | || echo "Warning: Intel PT: x86 instruction decoder differs from kernel" >&2 )) || true | ||
20 | $(call rule_mkdir) | ||
21 | $(call if_changed_dep,cc_o_c) | ||
11 | 22 | ||
12 | CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder -Wno-override-init | 23 | CFLAGS_intel-pt-insn-decoder.o += -I$(OUTPUT)util/intel-pt-decoder -Wno-override-init |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 22ba50224319..9409d014b46c 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | |||
@@ -650,7 +650,7 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info) | |||
650 | if (data->from_mtc && timestamp < data->timestamp && | 650 | if (data->from_mtc && timestamp < data->timestamp && |
651 | data->timestamp - timestamp < decoder->tsc_slip) | 651 | data->timestamp - timestamp < decoder->tsc_slip) |
652 | return 1; | 652 | return 1; |
653 | while (timestamp < data->timestamp) | 653 | if (timestamp < data->timestamp) |
654 | timestamp += (1ULL << 56); | 654 | timestamp += (1ULL << 56); |
655 | if (pkt_info->last_packet_type != INTEL_PT_CYC) { | 655 | if (pkt_info->last_packet_type != INTEL_PT_CYC) { |
656 | if (data->from_mtc) | 656 | if (data->from_mtc) |
@@ -1191,7 +1191,7 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder) | |||
1191 | timestamp); | 1191 | timestamp); |
1192 | timestamp = decoder->timestamp; | 1192 | timestamp = decoder->timestamp; |
1193 | } | 1193 | } |
1194 | while (timestamp < decoder->timestamp) { | 1194 | if (timestamp < decoder->timestamp) { |
1195 | intel_pt_log_to("Wraparound timestamp", timestamp); | 1195 | intel_pt_log_to("Wraparound timestamp", timestamp); |
1196 | timestamp += (1ULL << 56); | 1196 | timestamp += (1ULL << 56); |
1197 | decoder->tsc_timestamp = timestamp; | 1197 | decoder->tsc_timestamp = timestamp; |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.c b/tools/perf/util/intel-pt-decoder/intel-pt-log.c index d09c7d9f9050..319bef33a64b 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-log.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.c | |||
@@ -29,18 +29,18 @@ | |||
29 | 29 | ||
30 | static FILE *f; | 30 | static FILE *f; |
31 | static char log_name[MAX_LOG_NAME]; | 31 | static char log_name[MAX_LOG_NAME]; |
32 | static bool enable_logging; | 32 | bool intel_pt_enable_logging; |
33 | 33 | ||
34 | void intel_pt_log_enable(void) | 34 | void intel_pt_log_enable(void) |
35 | { | 35 | { |
36 | enable_logging = true; | 36 | intel_pt_enable_logging = true; |
37 | } | 37 | } |
38 | 38 | ||
39 | void intel_pt_log_disable(void) | 39 | void intel_pt_log_disable(void) |
40 | { | 40 | { |
41 | if (f) | 41 | if (f) |
42 | fflush(f); | 42 | fflush(f); |
43 | enable_logging = false; | 43 | intel_pt_enable_logging = false; |
44 | } | 44 | } |
45 | 45 | ||
46 | void intel_pt_log_set_name(const char *name) | 46 | void intel_pt_log_set_name(const char *name) |
@@ -80,7 +80,7 @@ static void intel_pt_print_no_data(uint64_t pos, int indent) | |||
80 | 80 | ||
81 | static int intel_pt_log_open(void) | 81 | static int intel_pt_log_open(void) |
82 | { | 82 | { |
83 | if (!enable_logging) | 83 | if (!intel_pt_enable_logging) |
84 | return -1; | 84 | return -1; |
85 | 85 | ||
86 | if (f) | 86 | if (f) |
@@ -91,15 +91,15 @@ static int intel_pt_log_open(void) | |||
91 | 91 | ||
92 | f = fopen(log_name, "w+"); | 92 | f = fopen(log_name, "w+"); |
93 | if (!f) { | 93 | if (!f) { |
94 | enable_logging = false; | 94 | intel_pt_enable_logging = false; |
95 | return -1; | 95 | return -1; |
96 | } | 96 | } |
97 | 97 | ||
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, | 101 | void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, |
102 | uint64_t pos, const unsigned char *buf) | 102 | uint64_t pos, const unsigned char *buf) |
103 | { | 103 | { |
104 | char desc[INTEL_PT_PKT_DESC_MAX]; | 104 | char desc[INTEL_PT_PKT_DESC_MAX]; |
105 | 105 | ||
@@ -111,7 +111,7 @@ void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, | |||
111 | fprintf(f, "%s\n", desc); | 111 | fprintf(f, "%s\n", desc); |
112 | } | 112 | } |
113 | 113 | ||
114 | void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip) | 114 | void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip) |
115 | { | 115 | { |
116 | char desc[INTEL_PT_INSN_DESC_MAX]; | 116 | char desc[INTEL_PT_INSN_DESC_MAX]; |
117 | size_t len = intel_pt_insn->length; | 117 | size_t len = intel_pt_insn->length; |
@@ -128,7 +128,8 @@ void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip) | |||
128 | fprintf(f, "Bad instruction!\n"); | 128 | fprintf(f, "Bad instruction!\n"); |
129 | } | 129 | } |
130 | 130 | ||
131 | void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip) | 131 | void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, |
132 | uint64_t ip) | ||
132 | { | 133 | { |
133 | char desc[INTEL_PT_INSN_DESC_MAX]; | 134 | char desc[INTEL_PT_INSN_DESC_MAX]; |
134 | 135 | ||
@@ -142,7 +143,7 @@ void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, uint64_t ip) | |||
142 | fprintf(f, "Bad instruction!\n"); | 143 | fprintf(f, "Bad instruction!\n"); |
143 | } | 144 | } |
144 | 145 | ||
145 | void intel_pt_log(const char *fmt, ...) | 146 | void __intel_pt_log(const char *fmt, ...) |
146 | { | 147 | { |
147 | va_list args; | 148 | va_list args; |
148 | 149 | ||
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-log.h b/tools/perf/util/intel-pt-decoder/intel-pt-log.h index db3942f83677..debe751dc3d6 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-log.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-log.h | |||
@@ -25,20 +25,46 @@ void intel_pt_log_enable(void); | |||
25 | void intel_pt_log_disable(void); | 25 | void intel_pt_log_disable(void); |
26 | void intel_pt_log_set_name(const char *name); | 26 | void intel_pt_log_set_name(const char *name); |
27 | 27 | ||
28 | void intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, | 28 | void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, |
29 | uint64_t pos, const unsigned char *buf); | 29 | uint64_t pos, const unsigned char *buf); |
30 | 30 | ||
31 | struct intel_pt_insn; | 31 | struct intel_pt_insn; |
32 | 32 | ||
33 | void intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip); | 33 | void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip); |
34 | void intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, | 34 | void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, |
35 | uint64_t ip); | 35 | uint64_t ip); |
36 | 36 | ||
37 | __attribute__((format(printf, 1, 2))) | 37 | __attribute__((format(printf, 1, 2))) |
38 | void intel_pt_log(const char *fmt, ...); | 38 | void __intel_pt_log(const char *fmt, ...); |
39 | |||
40 | #define intel_pt_log(fmt, ...) \ | ||
41 | do { \ | ||
42 | if (intel_pt_enable_logging) \ | ||
43 | __intel_pt_log(fmt, ##__VA_ARGS__); \ | ||
44 | } while (0) | ||
45 | |||
46 | #define intel_pt_log_packet(arg, ...) \ | ||
47 | do { \ | ||
48 | if (intel_pt_enable_logging) \ | ||
49 | __intel_pt_log_packet(arg, ##__VA_ARGS__); \ | ||
50 | } while (0) | ||
51 | |||
52 | #define intel_pt_log_insn(arg, ...) \ | ||
53 | do { \ | ||
54 | if (intel_pt_enable_logging) \ | ||
55 | __intel_pt_log_insn(arg, ##__VA_ARGS__); \ | ||
56 | } while (0) | ||
57 | |||
58 | #define intel_pt_log_insn_no_data(arg, ...) \ | ||
59 | do { \ | ||
60 | if (intel_pt_enable_logging) \ | ||
61 | __intel_pt_log_insn_no_data(arg, ##__VA_ARGS__); \ | ||
62 | } while (0) | ||
39 | 63 | ||
40 | #define x64_fmt "0x%" PRIx64 | 64 | #define x64_fmt "0x%" PRIx64 |
41 | 65 | ||
66 | extern bool intel_pt_enable_logging; | ||
67 | |||
42 | static inline void intel_pt_log_at(const char *msg, uint64_t u) | 68 | static inline void intel_pt_log_at(const char *msg, uint64_t u) |
43 | { | 69 | { |
44 | intel_pt_log("%s at " x64_fmt "\n", msg, u); | 70 | intel_pt_log("%s at " x64_fmt "\n", msg, u); |
diff --git a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt index 816488c0b97e..d388de72eaca 100644 --- a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt +++ b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt | |||
@@ -353,8 +353,12 @@ AVXcode: 1 | |||
353 | 17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1) | 353 | 17: vmovhps Mq,Vq (v1) | vmovhpd Mq,Vq (66),(v1) |
354 | 18: Grp16 (1A) | 354 | 18: Grp16 (1A) |
355 | 19: | 355 | 19: |
356 | 1a: BNDCL Ev,Gv | BNDCU Ev,Gv | BNDMOV Gv,Ev | BNDLDX Gv,Ev,Gv | 356 | # Intel SDM opcode map does not list MPX instructions. For now using Gv for |
357 | 1b: BNDCN Ev,Gv | BNDMOV Ev,Gv | BNDMK Gv,Ev | BNDSTX Ev,GV,Gv | 357 | # bnd registers and Ev for everything else is OK because the instruction |
358 | # decoder does not use the information except as an indication that there is | ||
359 | # a ModR/M byte. | ||
360 | 1a: BNDCL Gv,Ev (F3) | BNDCU Gv,Ev (F2) | BNDMOV Gv,Ev (66) | BNDLDX Gv,Ev | ||
361 | 1b: BNDCN Gv,Ev (F2) | BNDMOV Ev,Gv (66) | BNDMK Gv,Ev (F3) | BNDSTX Ev,Gv | ||
358 | 1c: | 362 | 1c: |
359 | 1d: | 363 | 1d: |
360 | 1e: | 364 | 1e: |
@@ -732,6 +736,12 @@ bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1) | |||
732 | be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) | 736 | be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) |
733 | bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) | 737 | bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) |
734 | # 0x0f 0x38 0xc0-0xff | 738 | # 0x0f 0x38 0xc0-0xff |
739 | c8: sha1nexte Vdq,Wdq | ||
740 | c9: sha1msg1 Vdq,Wdq | ||
741 | ca: sha1msg2 Vdq,Wdq | ||
742 | cb: sha256rnds2 Vdq,Wdq | ||
743 | cc: sha256msg1 Vdq,Wdq | ||
744 | cd: sha256msg2 Vdq,Wdq | ||
735 | db: VAESIMC Vdq,Wdq (66),(v1) | 745 | db: VAESIMC Vdq,Wdq (66),(v1) |
736 | dc: VAESENC Vdq,Hdq,Wdq (66),(v1) | 746 | dc: VAESENC Vdq,Hdq,Wdq (66),(v1) |
737 | dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) | 747 | dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) |
@@ -790,6 +800,7 @@ AVXcode: 3 | |||
790 | 61: vpcmpestri Vdq,Wdq,Ib (66),(v1) | 800 | 61: vpcmpestri Vdq,Wdq,Ib (66),(v1) |
791 | 62: vpcmpistrm Vdq,Wdq,Ib (66),(v1) | 801 | 62: vpcmpistrm Vdq,Wdq,Ib (66),(v1) |
792 | 63: vpcmpistri Vdq,Wdq,Ib (66),(v1) | 802 | 63: vpcmpistri Vdq,Wdq,Ib (66),(v1) |
803 | cc: sha1rnds4 Vdq,Wdq,Ib | ||
793 | df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) | 804 | df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) |
794 | f0: RORX Gy,Ey,Ib (F2),(v) | 805 | f0: RORX Gy,Ey,Ib (F2),(v) |
795 | EndTable | 806 | EndTable |
@@ -874,7 +885,7 @@ GrpTable: Grp7 | |||
874 | 2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B) | 885 | 2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B) |
875 | 3: LIDT Ms | 886 | 3: LIDT Ms |
876 | 4: SMSW Mw/Rv | 887 | 4: SMSW Mw/Rv |
877 | 5: | 888 | 5: rdpkru (110),(11B) | wrpkru (111),(11B) |
878 | 6: LMSW Ew | 889 | 6: LMSW Ew |
879 | 7: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B) | 890 | 7: INVLPG Mb | SWAPGS (o64),(000),(11B) | RDTSCP (001),(11B) |
880 | EndTable | 891 | EndTable |
@@ -888,6 +899,9 @@ EndTable | |||
888 | 899 | ||
889 | GrpTable: Grp9 | 900 | GrpTable: Grp9 |
890 | 1: CMPXCHG8B/16B Mq/Mdq | 901 | 1: CMPXCHG8B/16B Mq/Mdq |
902 | 3: xrstors | ||
903 | 4: xsavec | ||
904 | 5: xsaves | ||
891 | 6: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B) | 905 | 6: VMPTRLD Mq | VMCLEAR Mq (66) | VMXON Mq (F3) | RDRAND Rv (11B) |
892 | 7: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B) | 906 | 7: VMPTRST Mq | VMPTRST Mq (F3) | RDSEED Rv (11B) |
893 | EndTable | 907 | EndTable |
@@ -932,8 +946,8 @@ GrpTable: Grp15 | |||
932 | 3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) | 946 | 3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) |
933 | 4: XSAVE | 947 | 4: XSAVE |
934 | 5: XRSTOR | lfence (11B) | 948 | 5: XRSTOR | lfence (11B) |
935 | 6: XSAVEOPT | mfence (11B) | 949 | 6: XSAVEOPT | clwb (66) | mfence (11B) |
936 | 7: clflush | sfence (11B) | 950 | 7: clflush | clflushopt (66) | sfence (11B) | pcommit (66),(11B) |
937 | EndTable | 951 | EndTable |
938 | 952 | ||
939 | GrpTable: Grp16 | 953 | GrpTable: Grp16 |
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index bb41c20e6005..97f963a3dcb9 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "../perf.h" | 22 | #include "../perf.h" |
23 | #include "session.h" | 23 | #include "session.h" |
24 | #include "machine.h" | 24 | #include "machine.h" |
25 | #include "sort.h" | ||
25 | #include "tool.h" | 26 | #include "tool.h" |
26 | #include "event.h" | 27 | #include "event.h" |
27 | #include "evlist.h" | 28 | #include "evlist.h" |
@@ -63,6 +64,7 @@ struct intel_pt { | |||
63 | bool data_queued; | 64 | bool data_queued; |
64 | bool est_tsc; | 65 | bool est_tsc; |
65 | bool sync_switch; | 66 | bool sync_switch; |
67 | bool mispred_all; | ||
66 | int have_sched_switch; | 68 | int have_sched_switch; |
67 | u32 pmu_type; | 69 | u32 pmu_type; |
68 | u64 kernel_start; | 70 | u64 kernel_start; |
@@ -115,6 +117,9 @@ struct intel_pt_queue { | |||
115 | void *decoder; | 117 | void *decoder; |
116 | const struct intel_pt_state *state; | 118 | const struct intel_pt_state *state; |
117 | struct ip_callchain *chain; | 119 | struct ip_callchain *chain; |
120 | struct branch_stack *last_branch; | ||
121 | struct branch_stack *last_branch_rb; | ||
122 | size_t last_branch_pos; | ||
118 | union perf_event *event_buf; | 123 | union perf_event *event_buf; |
119 | bool on_heap; | 124 | bool on_heap; |
120 | bool stop; | 125 | bool stop; |
@@ -675,6 +680,19 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, | |||
675 | goto out_free; | 680 | goto out_free; |
676 | } | 681 | } |
677 | 682 | ||
683 | if (pt->synth_opts.last_branch) { | ||
684 | size_t sz = sizeof(struct branch_stack); | ||
685 | |||
686 | sz += pt->synth_opts.last_branch_sz * | ||
687 | sizeof(struct branch_entry); | ||
688 | ptq->last_branch = zalloc(sz); | ||
689 | if (!ptq->last_branch) | ||
690 | goto out_free; | ||
691 | ptq->last_branch_rb = zalloc(sz); | ||
692 | if (!ptq->last_branch_rb) | ||
693 | goto out_free; | ||
694 | } | ||
695 | |||
678 | ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE); | 696 | ptq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE); |
679 | if (!ptq->event_buf) | 697 | if (!ptq->event_buf) |
680 | goto out_free; | 698 | goto out_free; |
@@ -720,7 +738,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, | |||
720 | 738 | ||
721 | if (!params.period) { | 739 | if (!params.period) { |
722 | params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS; | 740 | params.period_type = INTEL_PT_PERIOD_INSTRUCTIONS; |
723 | params.period = 1000; | 741 | params.period = 1; |
724 | } | 742 | } |
725 | } | 743 | } |
726 | 744 | ||
@@ -732,6 +750,8 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt, | |||
732 | 750 | ||
733 | out_free: | 751 | out_free: |
734 | zfree(&ptq->event_buf); | 752 | zfree(&ptq->event_buf); |
753 | zfree(&ptq->last_branch); | ||
754 | zfree(&ptq->last_branch_rb); | ||
735 | zfree(&ptq->chain); | 755 | zfree(&ptq->chain); |
736 | free(ptq); | 756 | free(ptq); |
737 | return NULL; | 757 | return NULL; |
@@ -746,6 +766,8 @@ static void intel_pt_free_queue(void *priv) | |||
746 | thread__zput(ptq->thread); | 766 | thread__zput(ptq->thread); |
747 | intel_pt_decoder_free(ptq->decoder); | 767 | intel_pt_decoder_free(ptq->decoder); |
748 | zfree(&ptq->event_buf); | 768 | zfree(&ptq->event_buf); |
769 | zfree(&ptq->last_branch); | ||
770 | zfree(&ptq->last_branch_rb); | ||
749 | zfree(&ptq->chain); | 771 | zfree(&ptq->chain); |
750 | free(ptq); | 772 | free(ptq); |
751 | } | 773 | } |
@@ -876,6 +898,58 @@ static int intel_pt_setup_queues(struct intel_pt *pt) | |||
876 | return 0; | 898 | return 0; |
877 | } | 899 | } |
878 | 900 | ||
901 | static inline void intel_pt_copy_last_branch_rb(struct intel_pt_queue *ptq) | ||
902 | { | ||
903 | struct branch_stack *bs_src = ptq->last_branch_rb; | ||
904 | struct branch_stack *bs_dst = ptq->last_branch; | ||
905 | size_t nr = 0; | ||
906 | |||
907 | bs_dst->nr = bs_src->nr; | ||
908 | |||
909 | if (!bs_src->nr) | ||
910 | return; | ||
911 | |||
912 | nr = ptq->pt->synth_opts.last_branch_sz - ptq->last_branch_pos; | ||
913 | memcpy(&bs_dst->entries[0], | ||
914 | &bs_src->entries[ptq->last_branch_pos], | ||
915 | sizeof(struct branch_entry) * nr); | ||
916 | |||
917 | if (bs_src->nr >= ptq->pt->synth_opts.last_branch_sz) { | ||
918 | memcpy(&bs_dst->entries[nr], | ||
919 | &bs_src->entries[0], | ||
920 | sizeof(struct branch_entry) * ptq->last_branch_pos); | ||
921 | } | ||
922 | } | ||
923 | |||
924 | static inline void intel_pt_reset_last_branch_rb(struct intel_pt_queue *ptq) | ||
925 | { | ||
926 | ptq->last_branch_pos = 0; | ||
927 | ptq->last_branch_rb->nr = 0; | ||
928 | } | ||
929 | |||
930 | static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq) | ||
931 | { | ||
932 | const struct intel_pt_state *state = ptq->state; | ||
933 | struct branch_stack *bs = ptq->last_branch_rb; | ||
934 | struct branch_entry *be; | ||
935 | |||
936 | if (!ptq->last_branch_pos) | ||
937 | ptq->last_branch_pos = ptq->pt->synth_opts.last_branch_sz; | ||
938 | |||
939 | ptq->last_branch_pos -= 1; | ||
940 | |||
941 | be = &bs->entries[ptq->last_branch_pos]; | ||
942 | be->from = state->from_ip; | ||
943 | be->to = state->to_ip; | ||
944 | be->flags.abort = !!(state->flags & INTEL_PT_ABORT_TX); | ||
945 | be->flags.in_tx = !!(state->flags & INTEL_PT_IN_TX); | ||
946 | /* No support for mispredict */ | ||
947 | be->flags.mispred = ptq->pt->mispred_all; | ||
948 | |||
949 | if (bs->nr < ptq->pt->synth_opts.last_branch_sz) | ||
950 | bs->nr += 1; | ||
951 | } | ||
952 | |||
879 | static int intel_pt_inject_event(union perf_event *event, | 953 | static int intel_pt_inject_event(union perf_event *event, |
880 | struct perf_sample *sample, u64 type, | 954 | struct perf_sample *sample, u64 type, |
881 | bool swapped) | 955 | bool swapped) |
@@ -890,6 +964,13 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | |||
890 | struct intel_pt *pt = ptq->pt; | 964 | struct intel_pt *pt = ptq->pt; |
891 | union perf_event *event = ptq->event_buf; | 965 | union perf_event *event = ptq->event_buf; |
892 | struct perf_sample sample = { .ip = 0, }; | 966 | struct perf_sample sample = { .ip = 0, }; |
967 | struct dummy_branch_stack { | ||
968 | u64 nr; | ||
969 | struct branch_entry entries; | ||
970 | } dummy_bs; | ||
971 | |||
972 | if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) | ||
973 | return 0; | ||
893 | 974 | ||
894 | event->sample.header.type = PERF_RECORD_SAMPLE; | 975 | event->sample.header.type = PERF_RECORD_SAMPLE; |
895 | event->sample.header.misc = PERF_RECORD_MISC_USER; | 976 | event->sample.header.misc = PERF_RECORD_MISC_USER; |
@@ -909,8 +990,20 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | |||
909 | sample.flags = ptq->flags; | 990 | sample.flags = ptq->flags; |
910 | sample.insn_len = ptq->insn_len; | 991 | sample.insn_len = ptq->insn_len; |
911 | 992 | ||
912 | if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) | 993 | /* |
913 | return 0; | 994 | * perf report cannot handle events without a branch stack when using |
995 | * SORT_MODE__BRANCH so make a dummy one. | ||
996 | */ | ||
997 | if (pt->synth_opts.last_branch && sort__mode == SORT_MODE__BRANCH) { | ||
998 | dummy_bs = (struct dummy_branch_stack){ | ||
999 | .nr = 1, | ||
1000 | .entries = { | ||
1001 | .from = sample.ip, | ||
1002 | .to = sample.addr, | ||
1003 | }, | ||
1004 | }; | ||
1005 | sample.branch_stack = (struct branch_stack *)&dummy_bs; | ||
1006 | } | ||
914 | 1007 | ||
915 | if (pt->synth_opts.inject) { | 1008 | if (pt->synth_opts.inject) { |
916 | ret = intel_pt_inject_event(event, &sample, | 1009 | ret = intel_pt_inject_event(event, &sample, |
@@ -961,6 +1054,11 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) | |||
961 | sample.callchain = ptq->chain; | 1054 | sample.callchain = ptq->chain; |
962 | } | 1055 | } |
963 | 1056 | ||
1057 | if (pt->synth_opts.last_branch) { | ||
1058 | intel_pt_copy_last_branch_rb(ptq); | ||
1059 | sample.branch_stack = ptq->last_branch; | ||
1060 | } | ||
1061 | |||
964 | if (pt->synth_opts.inject) { | 1062 | if (pt->synth_opts.inject) { |
965 | ret = intel_pt_inject_event(event, &sample, | 1063 | ret = intel_pt_inject_event(event, &sample, |
966 | pt->instructions_sample_type, | 1064 | pt->instructions_sample_type, |
@@ -974,6 +1072,9 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) | |||
974 | pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n", | 1072 | pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n", |
975 | ret); | 1073 | ret); |
976 | 1074 | ||
1075 | if (pt->synth_opts.last_branch) | ||
1076 | intel_pt_reset_last_branch_rb(ptq); | ||
1077 | |||
977 | return ret; | 1078 | return ret; |
978 | } | 1079 | } |
979 | 1080 | ||
@@ -1008,6 +1109,11 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq) | |||
1008 | sample.callchain = ptq->chain; | 1109 | sample.callchain = ptq->chain; |
1009 | } | 1110 | } |
1010 | 1111 | ||
1112 | if (pt->synth_opts.last_branch) { | ||
1113 | intel_pt_copy_last_branch_rb(ptq); | ||
1114 | sample.branch_stack = ptq->last_branch; | ||
1115 | } | ||
1116 | |||
1011 | if (pt->synth_opts.inject) { | 1117 | if (pt->synth_opts.inject) { |
1012 | ret = intel_pt_inject_event(event, &sample, | 1118 | ret = intel_pt_inject_event(event, &sample, |
1013 | pt->transactions_sample_type, | 1119 | pt->transactions_sample_type, |
@@ -1021,6 +1127,9 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq) | |||
1021 | pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n", | 1127 | pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n", |
1022 | ret); | 1128 | ret); |
1023 | 1129 | ||
1130 | if (pt->synth_opts.callchain) | ||
1131 | intel_pt_reset_last_branch_rb(ptq); | ||
1132 | |||
1024 | return ret; | 1133 | return ret; |
1025 | } | 1134 | } |
1026 | 1135 | ||
@@ -1116,6 +1225,9 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) | |||
1116 | return err; | 1225 | return err; |
1117 | } | 1226 | } |
1118 | 1227 | ||
1228 | if (pt->synth_opts.last_branch) | ||
1229 | intel_pt_update_last_branch_rb(ptq); | ||
1230 | |||
1119 | if (!pt->sync_switch) | 1231 | if (!pt->sync_switch) |
1120 | return 0; | 1232 | return 0; |
1121 | 1233 | ||
@@ -1145,16 +1257,18 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) | |||
1145 | return 0; | 1257 | return 0; |
1146 | } | 1258 | } |
1147 | 1259 | ||
1148 | static u64 intel_pt_switch_ip(struct machine *machine, u64 *ptss_ip) | 1260 | static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip) |
1149 | { | 1261 | { |
1262 | struct machine *machine = pt->machine; | ||
1150 | struct map *map; | 1263 | struct map *map; |
1151 | struct symbol *sym, *start; | 1264 | struct symbol *sym, *start; |
1152 | u64 ip, switch_ip = 0; | 1265 | u64 ip, switch_ip = 0; |
1266 | const char *ptss; | ||
1153 | 1267 | ||
1154 | if (ptss_ip) | 1268 | if (ptss_ip) |
1155 | *ptss_ip = 0; | 1269 | *ptss_ip = 0; |
1156 | 1270 | ||
1157 | map = machine__kernel_map(machine, MAP__FUNCTION); | 1271 | map = machine__kernel_map(machine); |
1158 | if (!map) | 1272 | if (!map) |
1159 | return 0; | 1273 | return 0; |
1160 | 1274 | ||
@@ -1177,8 +1291,13 @@ static u64 intel_pt_switch_ip(struct machine *machine, u64 *ptss_ip) | |||
1177 | if (!switch_ip || !ptss_ip) | 1291 | if (!switch_ip || !ptss_ip) |
1178 | return 0; | 1292 | return 0; |
1179 | 1293 | ||
1294 | if (pt->have_sched_switch == 1) | ||
1295 | ptss = "perf_trace_sched_switch"; | ||
1296 | else | ||
1297 | ptss = "__perf_event_task_sched_out"; | ||
1298 | |||
1180 | for (sym = start; sym; sym = dso__next_symbol(sym)) { | 1299 | for (sym = start; sym; sym = dso__next_symbol(sym)) { |
1181 | if (!strcmp(sym->name, "perf_trace_sched_switch")) { | 1300 | if (!strcmp(sym->name, ptss)) { |
1182 | ip = map->unmap_ip(map, sym->start); | 1301 | ip = map->unmap_ip(map, sym->start); |
1183 | if (ip >= map->start && ip < map->end) { | 1302 | if (ip >= map->start && ip < map->end) { |
1184 | *ptss_ip = ip; | 1303 | *ptss_ip = ip; |
@@ -1198,11 +1317,11 @@ static int intel_pt_run_decoder(struct intel_pt_queue *ptq, u64 *timestamp) | |||
1198 | 1317 | ||
1199 | if (!pt->kernel_start) { | 1318 | if (!pt->kernel_start) { |
1200 | pt->kernel_start = machine__kernel_start(pt->machine); | 1319 | pt->kernel_start = machine__kernel_start(pt->machine); |
1201 | if (pt->per_cpu_mmaps && pt->have_sched_switch && | 1320 | if (pt->per_cpu_mmaps && |
1321 | (pt->have_sched_switch == 1 || pt->have_sched_switch == 3) && | ||
1202 | !pt->timeless_decoding && intel_pt_tracing_kernel(pt) && | 1322 | !pt->timeless_decoding && intel_pt_tracing_kernel(pt) && |
1203 | !pt->sampling_mode) { | 1323 | !pt->sampling_mode) { |
1204 | pt->switch_ip = intel_pt_switch_ip(pt->machine, | 1324 | pt->switch_ip = intel_pt_switch_ip(pt, &pt->ptss_ip); |
1205 | &pt->ptss_ip); | ||
1206 | if (pt->switch_ip) { | 1325 | if (pt->switch_ip) { |
1207 | intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n", | 1326 | intel_pt_log("switch_ip: %"PRIx64" ptss_ip: %"PRIx64"\n", |
1208 | pt->switch_ip, pt->ptss_ip); | 1327 | pt->switch_ip, pt->ptss_ip); |
@@ -1387,31 +1506,18 @@ static struct intel_pt_queue *intel_pt_cpu_to_ptq(struct intel_pt *pt, int cpu) | |||
1387 | return NULL; | 1506 | return NULL; |
1388 | } | 1507 | } |
1389 | 1508 | ||
1390 | static int intel_pt_process_switch(struct intel_pt *pt, | 1509 | static int intel_pt_sync_switch(struct intel_pt *pt, int cpu, pid_t tid, |
1391 | struct perf_sample *sample) | 1510 | u64 timestamp) |
1392 | { | 1511 | { |
1393 | struct intel_pt_queue *ptq; | 1512 | struct intel_pt_queue *ptq; |
1394 | struct perf_evsel *evsel; | 1513 | int err; |
1395 | pid_t tid; | ||
1396 | int cpu, err; | ||
1397 | |||
1398 | evsel = perf_evlist__id2evsel(pt->session->evlist, sample->id); | ||
1399 | if (evsel != pt->switch_evsel) | ||
1400 | return 0; | ||
1401 | |||
1402 | tid = perf_evsel__intval(evsel, sample, "next_pid"); | ||
1403 | cpu = sample->cpu; | ||
1404 | |||
1405 | intel_pt_log("sched_switch: cpu %d tid %d time %"PRIu64" tsc %#"PRIx64"\n", | ||
1406 | cpu, tid, sample->time, perf_time_to_tsc(sample->time, | ||
1407 | &pt->tc)); | ||
1408 | 1514 | ||
1409 | if (!pt->sync_switch) | 1515 | if (!pt->sync_switch) |
1410 | goto out; | 1516 | return 1; |
1411 | 1517 | ||
1412 | ptq = intel_pt_cpu_to_ptq(pt, cpu); | 1518 | ptq = intel_pt_cpu_to_ptq(pt, cpu); |
1413 | if (!ptq) | 1519 | if (!ptq) |
1414 | goto out; | 1520 | return 1; |
1415 | 1521 | ||
1416 | switch (ptq->switch_state) { | 1522 | switch (ptq->switch_state) { |
1417 | case INTEL_PT_SS_NOT_TRACING: | 1523 | case INTEL_PT_SS_NOT_TRACING: |
@@ -1424,7 +1530,7 @@ static int intel_pt_process_switch(struct intel_pt *pt, | |||
1424 | return 0; | 1530 | return 0; |
1425 | case INTEL_PT_SS_EXPECTING_SWITCH_EVENT: | 1531 | case INTEL_PT_SS_EXPECTING_SWITCH_EVENT: |
1426 | if (!ptq->on_heap) { | 1532 | if (!ptq->on_heap) { |
1427 | ptq->timestamp = perf_time_to_tsc(sample->time, | 1533 | ptq->timestamp = perf_time_to_tsc(timestamp, |
1428 | &pt->tc); | 1534 | &pt->tc); |
1429 | err = auxtrace_heap__add(&pt->heap, ptq->queue_nr, | 1535 | err = auxtrace_heap__add(&pt->heap, ptq->queue_nr, |
1430 | ptq->timestamp); | 1536 | ptq->timestamp); |
@@ -1441,10 +1547,76 @@ static int intel_pt_process_switch(struct intel_pt *pt, | |||
1441 | default: | 1547 | default: |
1442 | break; | 1548 | break; |
1443 | } | 1549 | } |
1444 | out: | 1550 | |
1551 | return 1; | ||
1552 | } | ||
1553 | |||
1554 | static int intel_pt_process_switch(struct intel_pt *pt, | ||
1555 | struct perf_sample *sample) | ||
1556 | { | ||
1557 | struct perf_evsel *evsel; | ||
1558 | pid_t tid; | ||
1559 | int cpu, ret; | ||
1560 | |||
1561 | evsel = perf_evlist__id2evsel(pt->session->evlist, sample->id); | ||
1562 | if (evsel != pt->switch_evsel) | ||
1563 | return 0; | ||
1564 | |||
1565 | tid = perf_evsel__intval(evsel, sample, "next_pid"); | ||
1566 | cpu = sample->cpu; | ||
1567 | |||
1568 | intel_pt_log("sched_switch: cpu %d tid %d time %"PRIu64" tsc %#"PRIx64"\n", | ||
1569 | cpu, tid, sample->time, perf_time_to_tsc(sample->time, | ||
1570 | &pt->tc)); | ||
1571 | |||
1572 | ret = intel_pt_sync_switch(pt, cpu, tid, sample->time); | ||
1573 | if (ret <= 0) | ||
1574 | return ret; | ||
1575 | |||
1445 | return machine__set_current_tid(pt->machine, cpu, -1, tid); | 1576 | return machine__set_current_tid(pt->machine, cpu, -1, tid); |
1446 | } | 1577 | } |
1447 | 1578 | ||
1579 | static int intel_pt_context_switch(struct intel_pt *pt, union perf_event *event, | ||
1580 | struct perf_sample *sample) | ||
1581 | { | ||
1582 | bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT; | ||
1583 | pid_t pid, tid; | ||
1584 | int cpu, ret; | ||
1585 | |||
1586 | cpu = sample->cpu; | ||
1587 | |||
1588 | if (pt->have_sched_switch == 3) { | ||
1589 | if (!out) | ||
1590 | return 0; | ||
1591 | if (event->header.type != PERF_RECORD_SWITCH_CPU_WIDE) { | ||
1592 | pr_err("Expecting CPU-wide context switch event\n"); | ||
1593 | return -EINVAL; | ||
1594 | } | ||
1595 | pid = event->context_switch.next_prev_pid; | ||
1596 | tid = event->context_switch.next_prev_tid; | ||
1597 | } else { | ||
1598 | if (out) | ||
1599 | return 0; | ||
1600 | pid = sample->pid; | ||
1601 | tid = sample->tid; | ||
1602 | } | ||
1603 | |||
1604 | if (tid == -1) { | ||
1605 | pr_err("context_switch event has no tid\n"); | ||
1606 | return -EINVAL; | ||
1607 | } | ||
1608 | |||
1609 | intel_pt_log("context_switch: cpu %d pid %d tid %d time %"PRIu64" tsc %#"PRIx64"\n", | ||
1610 | cpu, pid, tid, sample->time, perf_time_to_tsc(sample->time, | ||
1611 | &pt->tc)); | ||
1612 | |||
1613 | ret = intel_pt_sync_switch(pt, cpu, tid, sample->time); | ||
1614 | if (ret <= 0) | ||
1615 | return ret; | ||
1616 | |||
1617 | return machine__set_current_tid(pt->machine, cpu, pid, tid); | ||
1618 | } | ||
1619 | |||
1448 | static int intel_pt_process_itrace_start(struct intel_pt *pt, | 1620 | static int intel_pt_process_itrace_start(struct intel_pt *pt, |
1449 | union perf_event *event, | 1621 | union perf_event *event, |
1450 | struct perf_sample *sample) | 1622 | struct perf_sample *sample) |
@@ -1494,7 +1666,7 @@ static int intel_pt_process_event(struct perf_session *session, | |||
1494 | if (pt->timeless_decoding) { | 1666 | if (pt->timeless_decoding) { |
1495 | if (event->header.type == PERF_RECORD_EXIT) { | 1667 | if (event->header.type == PERF_RECORD_EXIT) { |
1496 | err = intel_pt_process_timeless_queues(pt, | 1668 | err = intel_pt_process_timeless_queues(pt, |
1497 | event->comm.tid, | 1669 | event->fork.tid, |
1498 | sample->time); | 1670 | sample->time); |
1499 | } | 1671 | } |
1500 | } else if (timestamp) { | 1672 | } else if (timestamp) { |
@@ -1515,6 +1687,9 @@ static int intel_pt_process_event(struct perf_session *session, | |||
1515 | err = intel_pt_process_switch(pt, sample); | 1687 | err = intel_pt_process_switch(pt, sample); |
1516 | else if (event->header.type == PERF_RECORD_ITRACE_START) | 1688 | else if (event->header.type == PERF_RECORD_ITRACE_START) |
1517 | err = intel_pt_process_itrace_start(pt, event, sample); | 1689 | err = intel_pt_process_itrace_start(pt, event, sample); |
1690 | else if (event->header.type == PERF_RECORD_SWITCH || | ||
1691 | event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) | ||
1692 | err = intel_pt_context_switch(pt, event, sample); | ||
1518 | 1693 | ||
1519 | intel_pt_log("event %s (%u): cpu %d time %"PRIu64" tsc %#"PRIx64"\n", | 1694 | intel_pt_log("event %s (%u): cpu %d time %"PRIu64" tsc %#"PRIx64"\n", |
1520 | perf_event__name(event->header.type), event->header.type, | 1695 | perf_event__name(event->header.type), event->header.type, |
@@ -1700,6 +1875,8 @@ static int intel_pt_synth_events(struct intel_pt *pt, | |||
1700 | pt->instructions_sample_period = attr.sample_period; | 1875 | pt->instructions_sample_period = attr.sample_period; |
1701 | if (pt->synth_opts.callchain) | 1876 | if (pt->synth_opts.callchain) |
1702 | attr.sample_type |= PERF_SAMPLE_CALLCHAIN; | 1877 | attr.sample_type |= PERF_SAMPLE_CALLCHAIN; |
1878 | if (pt->synth_opts.last_branch) | ||
1879 | attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; | ||
1703 | pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", | 1880 | pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", |
1704 | id, (u64)attr.sample_type); | 1881 | id, (u64)attr.sample_type); |
1705 | err = intel_pt_synth_event(session, &attr, id); | 1882 | err = intel_pt_synth_event(session, &attr, id); |
@@ -1719,6 +1896,8 @@ static int intel_pt_synth_events(struct intel_pt *pt, | |||
1719 | attr.sample_period = 1; | 1896 | attr.sample_period = 1; |
1720 | if (pt->synth_opts.callchain) | 1897 | if (pt->synth_opts.callchain) |
1721 | attr.sample_type |= PERF_SAMPLE_CALLCHAIN; | 1898 | attr.sample_type |= PERF_SAMPLE_CALLCHAIN; |
1899 | if (pt->synth_opts.last_branch) | ||
1900 | attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; | ||
1722 | pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", | 1901 | pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", |
1723 | id, (u64)attr.sample_type); | 1902 | id, (u64)attr.sample_type); |
1724 | err = intel_pt_synth_event(session, &attr, id); | 1903 | err = intel_pt_synth_event(session, &attr, id); |
@@ -1745,6 +1924,7 @@ static int intel_pt_synth_events(struct intel_pt *pt, | |||
1745 | attr.sample_period = 1; | 1924 | attr.sample_period = 1; |
1746 | attr.sample_type |= PERF_SAMPLE_ADDR; | 1925 | attr.sample_type |= PERF_SAMPLE_ADDR; |
1747 | attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN; | 1926 | attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN; |
1927 | attr.sample_type &= ~(u64)PERF_SAMPLE_BRANCH_STACK; | ||
1748 | pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n", | 1928 | pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n", |
1749 | id, (u64)attr.sample_type); | 1929 | id, (u64)attr.sample_type); |
1750 | err = intel_pt_synth_event(session, &attr, id); | 1930 | err = intel_pt_synth_event(session, &attr, id); |
@@ -1777,6 +1957,28 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist) | |||
1777 | return NULL; | 1957 | return NULL; |
1778 | } | 1958 | } |
1779 | 1959 | ||
1960 | static bool intel_pt_find_switch(struct perf_evlist *evlist) | ||
1961 | { | ||
1962 | struct perf_evsel *evsel; | ||
1963 | |||
1964 | evlist__for_each(evlist, evsel) { | ||
1965 | if (evsel->attr.context_switch) | ||
1966 | return true; | ||
1967 | } | ||
1968 | |||
1969 | return false; | ||
1970 | } | ||
1971 | |||
1972 | static int intel_pt_perf_config(const char *var, const char *value, void *data) | ||
1973 | { | ||
1974 | struct intel_pt *pt = data; | ||
1975 | |||
1976 | if (!strcmp(var, "intel-pt.mispred-all")) | ||
1977 | pt->mispred_all = perf_config_bool(var, value); | ||
1978 | |||
1979 | return 0; | ||
1980 | } | ||
1981 | |||
1780 | static const char * const intel_pt_info_fmts[] = { | 1982 | static const char * const intel_pt_info_fmts[] = { |
1781 | [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", | 1983 | [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", |
1782 | [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", | 1984 | [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", |
@@ -1821,6 +2023,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event, | |||
1821 | if (!pt) | 2023 | if (!pt) |
1822 | return -ENOMEM; | 2024 | return -ENOMEM; |
1823 | 2025 | ||
2026 | perf_config(intel_pt_perf_config, pt); | ||
2027 | |||
1824 | err = auxtrace_queues__init(&pt->queues); | 2028 | err = auxtrace_queues__init(&pt->queues); |
1825 | if (err) | 2029 | if (err) |
1826 | goto err_free; | 2030 | goto err_free; |
@@ -1888,6 +2092,10 @@ int intel_pt_process_auxtrace_info(union perf_event *event, | |||
1888 | pr_err("%s: missing sched_switch event\n", __func__); | 2092 | pr_err("%s: missing sched_switch event\n", __func__); |
1889 | goto err_delete_thread; | 2093 | goto err_delete_thread; |
1890 | } | 2094 | } |
2095 | } else if (pt->have_sched_switch == 2 && | ||
2096 | !intel_pt_find_switch(session->evlist)) { | ||
2097 | pr_err("%s: missing context_switch attribute flag\n", __func__); | ||
2098 | goto err_delete_thread; | ||
1891 | } | 2099 | } |
1892 | 2100 | ||
1893 | if (session->itrace_synth_opts && session->itrace_synth_opts->set) { | 2101 | if (session->itrace_synth_opts && session->itrace_synth_opts->set) { |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 6309f7ceb08f..5ef90be2a249 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -35,6 +35,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | |||
35 | machine->last_match = NULL; | 35 | machine->last_match = NULL; |
36 | 36 | ||
37 | machine->vdso_info = NULL; | 37 | machine->vdso_info = NULL; |
38 | machine->env = NULL; | ||
38 | 39 | ||
39 | machine->pid = pid; | 40 | machine->pid = pid; |
40 | 41 | ||
@@ -624,7 +625,7 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp) | |||
624 | { | 625 | { |
625 | int i; | 626 | int i; |
626 | size_t printed = 0; | 627 | size_t printed = 0; |
627 | struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso; | 628 | struct dso *kdso = machine__kernel_map(machine)->dso; |
628 | 629 | ||
629 | if (kdso->has_build_id) { | 630 | if (kdso->has_build_id) { |
630 | char filename[PATH_MAX]; | 631 | char filename[PATH_MAX]; |
@@ -740,6 +741,7 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) | |||
740 | 741 | ||
741 | for (type = 0; type < MAP__NR_TYPES; ++type) { | 742 | for (type = 0; type < MAP__NR_TYPES; ++type) { |
742 | struct kmap *kmap; | 743 | struct kmap *kmap; |
744 | struct map *map; | ||
743 | 745 | ||
744 | machine->vmlinux_maps[type] = map__new2(start, kernel, type); | 746 | machine->vmlinux_maps[type] = map__new2(start, kernel, type); |
745 | if (machine->vmlinux_maps[type] == NULL) | 747 | if (machine->vmlinux_maps[type] == NULL) |
@@ -748,13 +750,13 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) | |||
748 | machine->vmlinux_maps[type]->map_ip = | 750 | machine->vmlinux_maps[type]->map_ip = |
749 | machine->vmlinux_maps[type]->unmap_ip = | 751 | machine->vmlinux_maps[type]->unmap_ip = |
750 | identity__map_ip; | 752 | identity__map_ip; |
751 | kmap = map__kmap(machine->vmlinux_maps[type]); | 753 | map = __machine__kernel_map(machine, type); |
754 | kmap = map__kmap(map); | ||
752 | if (!kmap) | 755 | if (!kmap) |
753 | return -1; | 756 | return -1; |
754 | 757 | ||
755 | kmap->kmaps = &machine->kmaps; | 758 | kmap->kmaps = &machine->kmaps; |
756 | map_groups__insert(&machine->kmaps, | 759 | map_groups__insert(&machine->kmaps, map); |
757 | machine->vmlinux_maps[type]); | ||
758 | } | 760 | } |
759 | 761 | ||
760 | return 0; | 762 | return 0; |
@@ -766,13 +768,13 @@ void machine__destroy_kernel_maps(struct machine *machine) | |||
766 | 768 | ||
767 | for (type = 0; type < MAP__NR_TYPES; ++type) { | 769 | for (type = 0; type < MAP__NR_TYPES; ++type) { |
768 | struct kmap *kmap; | 770 | struct kmap *kmap; |
771 | struct map *map = __machine__kernel_map(machine, type); | ||
769 | 772 | ||
770 | if (machine->vmlinux_maps[type] == NULL) | 773 | if (map == NULL) |
771 | continue; | 774 | continue; |
772 | 775 | ||
773 | kmap = map__kmap(machine->vmlinux_maps[type]); | 776 | kmap = map__kmap(map); |
774 | map_groups__remove(&machine->kmaps, | 777 | map_groups__remove(&machine->kmaps, map); |
775 | machine->vmlinux_maps[type]); | ||
776 | if (kmap && kmap->ref_reloc_sym) { | 778 | if (kmap && kmap->ref_reloc_sym) { |
777 | /* | 779 | /* |
778 | * ref_reloc_sym is shared among all maps, so free just | 780 | * ref_reloc_sym is shared among all maps, so free just |
@@ -866,7 +868,7 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid) | |||
866 | int machine__load_kallsyms(struct machine *machine, const char *filename, | 868 | int machine__load_kallsyms(struct machine *machine, const char *filename, |
867 | enum map_type type, symbol_filter_t filter) | 869 | enum map_type type, symbol_filter_t filter) |
868 | { | 870 | { |
869 | struct map *map = machine->vmlinux_maps[type]; | 871 | struct map *map = machine__kernel_map(machine); |
870 | int ret = dso__load_kallsyms(map->dso, filename, map, filter); | 872 | int ret = dso__load_kallsyms(map->dso, filename, map, filter); |
871 | 873 | ||
872 | if (ret > 0) { | 874 | if (ret > 0) { |
@@ -885,7 +887,7 @@ int machine__load_kallsyms(struct machine *machine, const char *filename, | |||
885 | int machine__load_vmlinux_path(struct machine *machine, enum map_type type, | 887 | int machine__load_vmlinux_path(struct machine *machine, enum map_type type, |
886 | symbol_filter_t filter) | 888 | symbol_filter_t filter) |
887 | { | 889 | { |
888 | struct map *map = machine->vmlinux_maps[type]; | 890 | struct map *map = machine__kernel_map(machine); |
889 | int ret = dso__load_vmlinux_path(map->dso, map, filter); | 891 | int ret = dso__load_vmlinux_path(map->dso, map, filter); |
890 | 892 | ||
891 | if (ret > 0) | 893 | if (ret > 0) |
@@ -1243,8 +1245,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
1243 | /* | 1245 | /* |
1244 | * preload dso of guest kernel and modules | 1246 | * preload dso of guest kernel and modules |
1245 | */ | 1247 | */ |
1246 | dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], | 1248 | dso__load(kernel, machine__kernel_map(machine), NULL); |
1247 | NULL); | ||
1248 | } | 1249 | } |
1249 | } | 1250 | } |
1250 | return 0; | 1251 | return 0; |
@@ -1830,7 +1831,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, | |||
1830 | } | 1831 | } |
1831 | 1832 | ||
1832 | check_calls: | 1833 | check_calls: |
1833 | if (chain->nr > PERF_MAX_STACK_DEPTH) { | 1834 | if (chain->nr > PERF_MAX_STACK_DEPTH && (int)chain->nr > max_stack) { |
1834 | pr_warning("corrupted callchain. skipping...\n"); | 1835 | pr_warning("corrupted callchain. skipping...\n"); |
1835 | return 0; | 1836 | return 0; |
1836 | } | 1837 | } |
@@ -1996,7 +1997,7 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid, | |||
1996 | 1997 | ||
1997 | int machine__get_kernel_start(struct machine *machine) | 1998 | int machine__get_kernel_start(struct machine *machine) |
1998 | { | 1999 | { |
1999 | struct map *map = machine__kernel_map(machine, MAP__FUNCTION); | 2000 | struct map *map = machine__kernel_map(machine); |
2000 | int err = 0; | 2001 | int err = 0; |
2001 | 2002 | ||
2002 | /* | 2003 | /* |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index ea5cb4a621db..2c2b443df5ba 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -34,6 +34,7 @@ struct machine { | |||
34 | struct list_head dead_threads; | 34 | struct list_head dead_threads; |
35 | struct thread *last_match; | 35 | struct thread *last_match; |
36 | struct vdso_info *vdso_info; | 36 | struct vdso_info *vdso_info; |
37 | struct perf_env *env; | ||
37 | struct dsos dsos; | 38 | struct dsos dsos; |
38 | struct map_groups kmaps; | 39 | struct map_groups kmaps; |
39 | struct map *vmlinux_maps[MAP__NR_TYPES]; | 40 | struct map *vmlinux_maps[MAP__NR_TYPES]; |
@@ -47,11 +48,17 @@ struct machine { | |||
47 | }; | 48 | }; |
48 | 49 | ||
49 | static inline | 50 | static inline |
50 | struct map *machine__kernel_map(struct machine *machine, enum map_type type) | 51 | struct map *__machine__kernel_map(struct machine *machine, enum map_type type) |
51 | { | 52 | { |
52 | return machine->vmlinux_maps[type]; | 53 | return machine->vmlinux_maps[type]; |
53 | } | 54 | } |
54 | 55 | ||
56 | static inline | ||
57 | struct map *machine__kernel_map(struct machine *machine) | ||
58 | { | ||
59 | return __machine__kernel_map(machine, MAP__FUNCTION); | ||
60 | } | ||
61 | |||
55 | int machine__get_kernel_start(struct machine *machine); | 62 | int machine__get_kernel_start(struct machine *machine); |
56 | 63 | ||
57 | static inline u64 machine__kernel_start(struct machine *machine) | 64 | static inline u64 machine__kernel_start(struct machine *machine) |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index b1c475d9b240..4e38c396a897 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -235,7 +235,7 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | |||
235 | */ | 235 | */ |
236 | bool __map__is_kernel(const struct map *map) | 236 | bool __map__is_kernel(const struct map *map) |
237 | { | 237 | { |
238 | return map->groups->machine->vmlinux_maps[map->type] == map; | 238 | return __machine__kernel_map(map->groups->machine, map->type) == map; |
239 | } | 239 | } |
240 | 240 | ||
241 | static void map__exit(struct map *map) | 241 | static void map__exit(struct map *map) |
@@ -553,13 +553,9 @@ struct symbol *map_groups__find_symbol(struct map_groups *mg, | |||
553 | return NULL; | 553 | return NULL; |
554 | } | 554 | } |
555 | 555 | ||
556 | struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, | 556 | struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, |
557 | enum map_type type, | 557 | struct map **mapp, symbol_filter_t filter) |
558 | const char *name, | ||
559 | struct map **mapp, | ||
560 | symbol_filter_t filter) | ||
561 | { | 558 | { |
562 | struct maps *maps = &mg->maps[type]; | ||
563 | struct symbol *sym; | 559 | struct symbol *sym; |
564 | struct rb_node *nd; | 560 | struct rb_node *nd; |
565 | 561 | ||
@@ -583,6 +579,17 @@ out: | |||
583 | return sym; | 579 | return sym; |
584 | } | 580 | } |
585 | 581 | ||
582 | struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, | ||
583 | enum map_type type, | ||
584 | const char *name, | ||
585 | struct map **mapp, | ||
586 | symbol_filter_t filter) | ||
587 | { | ||
588 | struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp, filter); | ||
589 | |||
590 | return sym; | ||
591 | } | ||
592 | |||
586 | int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) | 593 | int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) |
587 | { | 594 | { |
588 | if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { | 595 | if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 57829e89b78b..7309d64ce39e 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -190,6 +190,8 @@ void maps__remove(struct maps *maps, struct map *map); | |||
190 | struct map *maps__find(struct maps *maps, u64 addr); | 190 | struct map *maps__find(struct maps *maps, u64 addr); |
191 | struct map *maps__first(struct maps *maps); | 191 | struct map *maps__first(struct maps *maps); |
192 | struct map *map__next(struct map *map); | 192 | struct map *map__next(struct map *map); |
193 | struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, | ||
194 | struct map **mapp, symbol_filter_t filter); | ||
193 | void map_groups__init(struct map_groups *mg, struct machine *machine); | 195 | void map_groups__init(struct map_groups *mg, struct machine *machine); |
194 | void map_groups__exit(struct map_groups *mg); | 196 | void map_groups__exit(struct map_groups *mg); |
195 | int map_groups__clone(struct map_groups *mg, | 197 | int map_groups__clone(struct map_groups *mg, |
diff --git a/tools/perf/util/parse-branch-options.c b/tools/perf/util/parse-branch-options.c index a3b1e13a05c0..355eecf6bf59 100644 --- a/tools/perf/util/parse-branch-options.c +++ b/tools/perf/util/parse-branch-options.c | |||
@@ -27,6 +27,7 @@ static const struct branch_mode branch_modes[] = { | |||
27 | BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), | 27 | BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX), |
28 | BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND), | 28 | BRANCH_OPT("cond", PERF_SAMPLE_BRANCH_COND), |
29 | BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP), | 29 | BRANCH_OPT("ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP), |
30 | BRANCH_OPT("call", PERF_SAMPLE_BRANCH_CALL), | ||
30 | BRANCH_END | 31 | BRANCH_END |
31 | }; | 32 | }; |
32 | 33 | ||
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index d826e6f515db..bee60583839a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <linux/hw_breakpoint.h> | 1 | #include <linux/hw_breakpoint.h> |
2 | #include <linux/err.h> | ||
2 | #include "util.h" | 3 | #include "util.h" |
3 | #include "../perf.h" | 4 | #include "../perf.h" |
4 | #include "evlist.h" | 5 | #include "evlist.h" |
@@ -10,8 +11,9 @@ | |||
10 | #include "symbol.h" | 11 | #include "symbol.h" |
11 | #include "cache.h" | 12 | #include "cache.h" |
12 | #include "header.h" | 13 | #include "header.h" |
14 | #include "bpf-loader.h" | ||
13 | #include "debug.h" | 15 | #include "debug.h" |
14 | #include <api/fs/debugfs.h> | 16 | #include <api/fs/tracing_path.h> |
15 | #include "parse-events-bison.h" | 17 | #include "parse-events-bison.h" |
16 | #define YY_EXTRA_TYPE int | 18 | #define YY_EXTRA_TYPE int |
17 | #include "parse-events-flex.h" | 19 | #include "parse-events-flex.h" |
@@ -26,6 +28,8 @@ | |||
26 | extern int parse_events_debug; | 28 | extern int parse_events_debug; |
27 | #endif | 29 | #endif |
28 | int parse_events_parse(void *data, void *scanner); | 30 | int parse_events_parse(void *data, void *scanner); |
31 | static int get_config_terms(struct list_head *head_config, | ||
32 | struct list_head *head_terms __maybe_unused); | ||
29 | 33 | ||
30 | static struct perf_pmu_event_symbol *perf_pmu_events_list; | 34 | static struct perf_pmu_event_symbol *perf_pmu_events_list; |
31 | /* | 35 | /* |
@@ -287,8 +291,8 @@ __add_event(struct list_head *list, int *idx, | |||
287 | if (!evsel) | 291 | if (!evsel) |
288 | return NULL; | 292 | return NULL; |
289 | 293 | ||
290 | if (cpus) | 294 | evsel->cpus = cpu_map__get(cpus); |
291 | evsel->cpus = cpu_map__get(cpus); | 295 | evsel->own_cpus = cpu_map__get(cpus); |
292 | 296 | ||
293 | if (name) | 297 | if (name) |
294 | evsel->name = strdup(name); | 298 | evsel->name = strdup(name); |
@@ -386,32 +390,72 @@ int parse_events_add_cache(struct list_head *list, int *idx, | |||
386 | return add_event(list, idx, &attr, name, NULL); | 390 | return add_event(list, idx, &attr, name, NULL); |
387 | } | 391 | } |
388 | 392 | ||
393 | static void tracepoint_error(struct parse_events_error *e, int err, | ||
394 | char *sys, char *name) | ||
395 | { | ||
396 | char help[BUFSIZ]; | ||
397 | |||
398 | /* | ||
399 | * We get error directly from syscall errno ( > 0), | ||
400 | * or from encoded pointer's error ( < 0). | ||
401 | */ | ||
402 | err = abs(err); | ||
403 | |||
404 | switch (err) { | ||
405 | case EACCES: | ||
406 | e->str = strdup("can't access trace events"); | ||
407 | break; | ||
408 | case ENOENT: | ||
409 | e->str = strdup("unknown tracepoint"); | ||
410 | break; | ||
411 | default: | ||
412 | e->str = strdup("failed to add tracepoint"); | ||
413 | break; | ||
414 | } | ||
415 | |||
416 | tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name); | ||
417 | e->help = strdup(help); | ||
418 | } | ||
419 | |||
389 | static int add_tracepoint(struct list_head *list, int *idx, | 420 | static int add_tracepoint(struct list_head *list, int *idx, |
390 | char *sys_name, char *evt_name) | 421 | char *sys_name, char *evt_name, |
422 | struct parse_events_error *err, | ||
423 | struct list_head *head_config) | ||
391 | { | 424 | { |
392 | struct perf_evsel *evsel; | 425 | struct perf_evsel *evsel; |
393 | 426 | ||
394 | evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); | 427 | evsel = perf_evsel__newtp_idx(sys_name, evt_name, (*idx)++); |
395 | if (!evsel) | 428 | if (IS_ERR(evsel)) { |
396 | return -ENOMEM; | 429 | tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name); |
430 | return PTR_ERR(evsel); | ||
431 | } | ||
397 | 432 | ||
398 | list_add_tail(&evsel->node, list); | 433 | if (head_config) { |
434 | LIST_HEAD(config_terms); | ||
399 | 435 | ||
436 | if (get_config_terms(head_config, &config_terms)) | ||
437 | return -ENOMEM; | ||
438 | list_splice(&config_terms, &evsel->config_terms); | ||
439 | } | ||
440 | |||
441 | list_add_tail(&evsel->node, list); | ||
400 | return 0; | 442 | return 0; |
401 | } | 443 | } |
402 | 444 | ||
403 | static int add_tracepoint_multi_event(struct list_head *list, int *idx, | 445 | static int add_tracepoint_multi_event(struct list_head *list, int *idx, |
404 | char *sys_name, char *evt_name) | 446 | char *sys_name, char *evt_name, |
447 | struct parse_events_error *err, | ||
448 | struct list_head *head_config) | ||
405 | { | 449 | { |
406 | char evt_path[MAXPATHLEN]; | 450 | char evt_path[MAXPATHLEN]; |
407 | struct dirent *evt_ent; | 451 | struct dirent *evt_ent; |
408 | DIR *evt_dir; | 452 | DIR *evt_dir; |
409 | int ret = 0; | 453 | int ret = 0, found = 0; |
410 | 454 | ||
411 | snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); | 455 | snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); |
412 | evt_dir = opendir(evt_path); | 456 | evt_dir = opendir(evt_path); |
413 | if (!evt_dir) { | 457 | if (!evt_dir) { |
414 | perror("Can't open event dir"); | 458 | tracepoint_error(err, errno, sys_name, evt_name); |
415 | return -1; | 459 | return -1; |
416 | } | 460 | } |
417 | 461 | ||
@@ -425,7 +469,15 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, | |||
425 | if (!strglobmatch(evt_ent->d_name, evt_name)) | 469 | if (!strglobmatch(evt_ent->d_name, evt_name)) |
426 | continue; | 470 | continue; |
427 | 471 | ||
428 | ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name); | 472 | found++; |
473 | |||
474 | ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, | ||
475 | err, head_config); | ||
476 | } | ||
477 | |||
478 | if (!found) { | ||
479 | tracepoint_error(err, ENOENT, sys_name, evt_name); | ||
480 | ret = -1; | ||
429 | } | 481 | } |
430 | 482 | ||
431 | closedir(evt_dir); | 483 | closedir(evt_dir); |
@@ -433,15 +485,21 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, | |||
433 | } | 485 | } |
434 | 486 | ||
435 | static int add_tracepoint_event(struct list_head *list, int *idx, | 487 | static int add_tracepoint_event(struct list_head *list, int *idx, |
436 | char *sys_name, char *evt_name) | 488 | char *sys_name, char *evt_name, |
489 | struct parse_events_error *err, | ||
490 | struct list_head *head_config) | ||
437 | { | 491 | { |
438 | return strpbrk(evt_name, "*?") ? | 492 | return strpbrk(evt_name, "*?") ? |
439 | add_tracepoint_multi_event(list, idx, sys_name, evt_name) : | 493 | add_tracepoint_multi_event(list, idx, sys_name, evt_name, |
440 | add_tracepoint(list, idx, sys_name, evt_name); | 494 | err, head_config) : |
495 | add_tracepoint(list, idx, sys_name, evt_name, | ||
496 | err, head_config); | ||
441 | } | 497 | } |
442 | 498 | ||
443 | static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | 499 | static int add_tracepoint_multi_sys(struct list_head *list, int *idx, |
444 | char *sys_name, char *evt_name) | 500 | char *sys_name, char *evt_name, |
501 | struct parse_events_error *err, | ||
502 | struct list_head *head_config) | ||
445 | { | 503 | { |
446 | struct dirent *events_ent; | 504 | struct dirent *events_ent; |
447 | DIR *events_dir; | 505 | DIR *events_dir; |
@@ -449,7 +507,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | |||
449 | 507 | ||
450 | events_dir = opendir(tracing_events_path); | 508 | events_dir = opendir(tracing_events_path); |
451 | if (!events_dir) { | 509 | if (!events_dir) { |
452 | perror("Can't open event dir"); | 510 | tracepoint_error(err, errno, sys_name, evt_name); |
453 | return -1; | 511 | return -1; |
454 | } | 512 | } |
455 | 513 | ||
@@ -465,20 +523,135 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx, | |||
465 | continue; | 523 | continue; |
466 | 524 | ||
467 | ret = add_tracepoint_event(list, idx, events_ent->d_name, | 525 | ret = add_tracepoint_event(list, idx, events_ent->d_name, |
468 | evt_name); | 526 | evt_name, err, head_config); |
469 | } | 527 | } |
470 | 528 | ||
471 | closedir(events_dir); | 529 | closedir(events_dir); |
472 | return ret; | 530 | return ret; |
473 | } | 531 | } |
474 | 532 | ||
475 | int parse_events_add_tracepoint(struct list_head *list, int *idx, | 533 | struct __add_bpf_event_param { |
476 | char *sys, char *event) | 534 | struct parse_events_evlist *data; |
535 | struct list_head *list; | ||
536 | }; | ||
537 | |||
538 | static int add_bpf_event(struct probe_trace_event *tev, int fd, | ||
539 | void *_param) | ||
477 | { | 540 | { |
478 | if (strpbrk(sys, "*?")) | 541 | LIST_HEAD(new_evsels); |
479 | return add_tracepoint_multi_sys(list, idx, sys, event); | 542 | struct __add_bpf_event_param *param = _param; |
480 | else | 543 | struct parse_events_evlist *evlist = param->data; |
481 | return add_tracepoint_event(list, idx, sys, event); | 544 | struct list_head *list = param->list; |
545 | struct perf_evsel *pos; | ||
546 | int err; | ||
547 | |||
548 | pr_debug("add bpf event %s:%s and attach bpf program %d\n", | ||
549 | tev->group, tev->event, fd); | ||
550 | |||
551 | err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group, | ||
552 | tev->event, evlist->error, NULL); | ||
553 | if (err) { | ||
554 | struct perf_evsel *evsel, *tmp; | ||
555 | |||
556 | pr_debug("Failed to add BPF event %s:%s\n", | ||
557 | tev->group, tev->event); | ||
558 | list_for_each_entry_safe(evsel, tmp, &new_evsels, node) { | ||
559 | list_del(&evsel->node); | ||
560 | perf_evsel__delete(evsel); | ||
561 | } | ||
562 | return err; | ||
563 | } | ||
564 | pr_debug("adding %s:%s\n", tev->group, tev->event); | ||
565 | |||
566 | list_for_each_entry(pos, &new_evsels, node) { | ||
567 | pr_debug("adding %s:%s to %p\n", | ||
568 | tev->group, tev->event, pos); | ||
569 | pos->bpf_fd = fd; | ||
570 | } | ||
571 | list_splice(&new_evsels, list); | ||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | int parse_events_load_bpf_obj(struct parse_events_evlist *data, | ||
576 | struct list_head *list, | ||
577 | struct bpf_object *obj) | ||
578 | { | ||
579 | int err; | ||
580 | char errbuf[BUFSIZ]; | ||
581 | struct __add_bpf_event_param param = {data, list}; | ||
582 | static bool registered_unprobe_atexit = false; | ||
583 | |||
584 | if (IS_ERR(obj) || !obj) { | ||
585 | snprintf(errbuf, sizeof(errbuf), | ||
586 | "Internal error: load bpf obj with NULL"); | ||
587 | err = -EINVAL; | ||
588 | goto errout; | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * Register atexit handler before calling bpf__probe() so | ||
593 | * bpf__probe() don't need to unprobe probe points its already | ||
594 | * created when failure. | ||
595 | */ | ||
596 | if (!registered_unprobe_atexit) { | ||
597 | atexit(bpf__clear); | ||
598 | registered_unprobe_atexit = true; | ||
599 | } | ||
600 | |||
601 | err = bpf__probe(obj); | ||
602 | if (err) { | ||
603 | bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf)); | ||
604 | goto errout; | ||
605 | } | ||
606 | |||
607 | err = bpf__load(obj); | ||
608 | if (err) { | ||
609 | bpf__strerror_load(obj, err, errbuf, sizeof(errbuf)); | ||
610 | goto errout; | ||
611 | } | ||
612 | |||
613 | err = bpf__foreach_tev(obj, add_bpf_event, ¶m); | ||
614 | if (err) { | ||
615 | snprintf(errbuf, sizeof(errbuf), | ||
616 | "Attach events in BPF object failed"); | ||
617 | goto errout; | ||
618 | } | ||
619 | |||
620 | return 0; | ||
621 | errout: | ||
622 | data->error->help = strdup("(add -v to see detail)"); | ||
623 | data->error->str = strdup(errbuf); | ||
624 | return err; | ||
625 | } | ||
626 | |||
627 | int parse_events_load_bpf(struct parse_events_evlist *data, | ||
628 | struct list_head *list, | ||
629 | char *bpf_file_name, | ||
630 | bool source) | ||
631 | { | ||
632 | struct bpf_object *obj; | ||
633 | |||
634 | obj = bpf__prepare_load(bpf_file_name, source); | ||
635 | if (IS_ERR(obj) || !obj) { | ||
636 | char errbuf[BUFSIZ]; | ||
637 | int err; | ||
638 | |||
639 | err = obj ? PTR_ERR(obj) : -EINVAL; | ||
640 | |||
641 | if (err == -ENOTSUP) | ||
642 | snprintf(errbuf, sizeof(errbuf), | ||
643 | "BPF support is not compiled"); | ||
644 | else | ||
645 | snprintf(errbuf, sizeof(errbuf), | ||
646 | "BPF object file '%s' is invalid", | ||
647 | bpf_file_name); | ||
648 | |||
649 | data->error->help = strdup("(add -v to see detail)"); | ||
650 | data->error->str = strdup(errbuf); | ||
651 | return err; | ||
652 | } | ||
653 | |||
654 | return parse_events_load_bpf_obj(data, list, obj); | ||
482 | } | 655 | } |
483 | 656 | ||
484 | static int | 657 | static int |
@@ -565,9 +738,13 @@ static int check_type_val(struct parse_events_term *term, | |||
565 | return -EINVAL; | 738 | return -EINVAL; |
566 | } | 739 | } |
567 | 740 | ||
568 | static int config_term(struct perf_event_attr *attr, | 741 | typedef int config_term_func_t(struct perf_event_attr *attr, |
569 | struct parse_events_term *term, | 742 | struct parse_events_term *term, |
570 | struct parse_events_error *err) | 743 | struct parse_events_error *err); |
744 | |||
745 | static int config_term_common(struct perf_event_attr *attr, | ||
746 | struct parse_events_term *term, | ||
747 | struct parse_events_error *err) | ||
571 | { | 748 | { |
572 | #define CHECK_TYPE_VAL(type) \ | 749 | #define CHECK_TYPE_VAL(type) \ |
573 | do { \ | 750 | do { \ |
@@ -576,12 +753,6 @@ do { \ | |||
576 | } while (0) | 753 | } while (0) |
577 | 754 | ||
578 | switch (term->type_term) { | 755 | switch (term->type_term) { |
579 | case PARSE_EVENTS__TERM_TYPE_USER: | ||
580 | /* | ||
581 | * Always succeed for sysfs terms, as we dont know | ||
582 | * at this point what type they need to have. | ||
583 | */ | ||
584 | return 0; | ||
585 | case PARSE_EVENTS__TERM_TYPE_CONFIG: | 756 | case PARSE_EVENTS__TERM_TYPE_CONFIG: |
586 | CHECK_TYPE_VAL(NUM); | 757 | CHECK_TYPE_VAL(NUM); |
587 | attr->config = term->val.num; | 758 | attr->config = term->val.num; |
@@ -620,10 +791,19 @@ do { \ | |||
620 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: | 791 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: |
621 | CHECK_TYPE_VAL(NUM); | 792 | CHECK_TYPE_VAL(NUM); |
622 | break; | 793 | break; |
794 | case PARSE_EVENTS__TERM_TYPE_INHERIT: | ||
795 | CHECK_TYPE_VAL(NUM); | ||
796 | break; | ||
797 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: | ||
798 | CHECK_TYPE_VAL(NUM); | ||
799 | break; | ||
623 | case PARSE_EVENTS__TERM_TYPE_NAME: | 800 | case PARSE_EVENTS__TERM_TYPE_NAME: |
624 | CHECK_TYPE_VAL(STR); | 801 | CHECK_TYPE_VAL(STR); |
625 | break; | 802 | break; |
626 | default: | 803 | default: |
804 | err->str = strdup("unknown term"); | ||
805 | err->idx = term->err_term; | ||
806 | err->help = parse_events_formats_error_string(NULL); | ||
627 | return -EINVAL; | 807 | return -EINVAL; |
628 | } | 808 | } |
629 | 809 | ||
@@ -631,9 +811,46 @@ do { \ | |||
631 | #undef CHECK_TYPE_VAL | 811 | #undef CHECK_TYPE_VAL |
632 | } | 812 | } |
633 | 813 | ||
814 | static int config_term_pmu(struct perf_event_attr *attr, | ||
815 | struct parse_events_term *term, | ||
816 | struct parse_events_error *err) | ||
817 | { | ||
818 | if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) | ||
819 | /* | ||
820 | * Always succeed for sysfs terms, as we dont know | ||
821 | * at this point what type they need to have. | ||
822 | */ | ||
823 | return 0; | ||
824 | else | ||
825 | return config_term_common(attr, term, err); | ||
826 | } | ||
827 | |||
828 | static int config_term_tracepoint(struct perf_event_attr *attr, | ||
829 | struct parse_events_term *term, | ||
830 | struct parse_events_error *err) | ||
831 | { | ||
832 | switch (term->type_term) { | ||
833 | case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: | ||
834 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: | ||
835 | case PARSE_EVENTS__TERM_TYPE_INHERIT: | ||
836 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: | ||
837 | return config_term_common(attr, term, err); | ||
838 | default: | ||
839 | if (err) { | ||
840 | err->idx = term->err_term; | ||
841 | err->str = strdup("unknown term"); | ||
842 | err->help = strdup("valid terms: call-graph,stack-size\n"); | ||
843 | } | ||
844 | return -EINVAL; | ||
845 | } | ||
846 | |||
847 | return 0; | ||
848 | } | ||
849 | |||
634 | static int config_attr(struct perf_event_attr *attr, | 850 | static int config_attr(struct perf_event_attr *attr, |
635 | struct list_head *head, | 851 | struct list_head *head, |
636 | struct parse_events_error *err) | 852 | struct parse_events_error *err, |
853 | config_term_func_t config_term) | ||
637 | { | 854 | { |
638 | struct parse_events_term *term; | 855 | struct parse_events_term *term; |
639 | 856 | ||
@@ -680,6 +897,12 @@ do { \ | |||
680 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: | 897 | case PARSE_EVENTS__TERM_TYPE_STACKSIZE: |
681 | ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); | 898 | ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num); |
682 | break; | 899 | break; |
900 | case PARSE_EVENTS__TERM_TYPE_INHERIT: | ||
901 | ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 1 : 0); | ||
902 | break; | ||
903 | case PARSE_EVENTS__TERM_TYPE_NOINHERIT: | ||
904 | ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1); | ||
905 | break; | ||
683 | default: | 906 | default: |
684 | break; | 907 | break; |
685 | } | 908 | } |
@@ -688,6 +911,27 @@ do { \ | |||
688 | return 0; | 911 | return 0; |
689 | } | 912 | } |
690 | 913 | ||
914 | int parse_events_add_tracepoint(struct list_head *list, int *idx, | ||
915 | char *sys, char *event, | ||
916 | struct parse_events_error *err, | ||
917 | struct list_head *head_config) | ||
918 | { | ||
919 | if (head_config) { | ||
920 | struct perf_event_attr attr; | ||
921 | |||
922 | if (config_attr(&attr, head_config, err, | ||
923 | config_term_tracepoint)) | ||
924 | return -EINVAL; | ||
925 | } | ||
926 | |||
927 | if (strpbrk(sys, "*?")) | ||
928 | return add_tracepoint_multi_sys(list, idx, sys, event, | ||
929 | err, head_config); | ||
930 | else | ||
931 | return add_tracepoint_event(list, idx, sys, event, | ||
932 | err, head_config); | ||
933 | } | ||
934 | |||
691 | int parse_events_add_numeric(struct parse_events_evlist *data, | 935 | int parse_events_add_numeric(struct parse_events_evlist *data, |
692 | struct list_head *list, | 936 | struct list_head *list, |
693 | u32 type, u64 config, | 937 | u32 type, u64 config, |
@@ -701,7 +945,8 @@ int parse_events_add_numeric(struct parse_events_evlist *data, | |||
701 | attr.config = config; | 945 | attr.config = config; |
702 | 946 | ||
703 | if (head_config) { | 947 | if (head_config) { |
704 | if (config_attr(&attr, head_config, data->error)) | 948 | if (config_attr(&attr, head_config, data->error, |
949 | config_term_common)) | ||
705 | return -EINVAL; | 950 | return -EINVAL; |
706 | 951 | ||
707 | if (get_config_terms(head_config, &config_terms)) | 952 | if (get_config_terms(head_config, &config_terms)) |
@@ -761,7 +1006,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data, | |||
761 | * Configure hardcoded terms first, no need to check | 1006 | * Configure hardcoded terms first, no need to check |
762 | * return value when called with fail == 0 ;) | 1007 | * return value when called with fail == 0 ;) |
763 | */ | 1008 | */ |
764 | if (config_attr(&attr, head_config, data->error)) | 1009 | if (config_attr(&attr, head_config, data->error, config_term_pmu)) |
765 | return -EINVAL; | 1010 | return -EINVAL; |
766 | 1011 | ||
767 | if (get_config_terms(head_config, &config_terms)) | 1012 | if (get_config_terms(head_config, &config_terms)) |
@@ -793,6 +1038,11 @@ void parse_events__set_leader(char *name, struct list_head *list) | |||
793 | { | 1038 | { |
794 | struct perf_evsel *leader; | 1039 | struct perf_evsel *leader; |
795 | 1040 | ||
1041 | if (list_empty(list)) { | ||
1042 | WARN_ONCE(true, "WARNING: failed to set leader: empty list"); | ||
1043 | return; | ||
1044 | } | ||
1045 | |||
796 | __perf_evlist__set_leader(list); | 1046 | __perf_evlist__set_leader(list); |
797 | leader = list_entry(list->next, struct perf_evsel, node); | 1047 | leader = list_entry(list->next, struct perf_evsel, node); |
798 | leader->group_name = name ? strdup(name) : NULL; | 1048 | leader->group_name = name ? strdup(name) : NULL; |
@@ -819,6 +1069,7 @@ struct event_modifier { | |||
819 | int eG; | 1069 | int eG; |
820 | int eI; | 1070 | int eI; |
821 | int precise; | 1071 | int precise; |
1072 | int precise_max; | ||
822 | int exclude_GH; | 1073 | int exclude_GH; |
823 | int sample_read; | 1074 | int sample_read; |
824 | int pinned; | 1075 | int pinned; |
@@ -834,6 +1085,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str, | |||
834 | int eG = evsel ? evsel->attr.exclude_guest : 0; | 1085 | int eG = evsel ? evsel->attr.exclude_guest : 0; |
835 | int eI = evsel ? evsel->attr.exclude_idle : 0; | 1086 | int eI = evsel ? evsel->attr.exclude_idle : 0; |
836 | int precise = evsel ? evsel->attr.precise_ip : 0; | 1087 | int precise = evsel ? evsel->attr.precise_ip : 0; |
1088 | int precise_max = 0; | ||
837 | int sample_read = 0; | 1089 | int sample_read = 0; |
838 | int pinned = evsel ? evsel->attr.pinned : 0; | 1090 | int pinned = evsel ? evsel->attr.pinned : 0; |
839 | 1091 | ||
@@ -870,6 +1122,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str, | |||
870 | /* use of precise requires exclude_guest */ | 1122 | /* use of precise requires exclude_guest */ |
871 | if (!exclude_GH) | 1123 | if (!exclude_GH) |
872 | eG = 1; | 1124 | eG = 1; |
1125 | } else if (*str == 'P') { | ||
1126 | precise_max = 1; | ||
873 | } else if (*str == 'S') { | 1127 | } else if (*str == 'S') { |
874 | sample_read = 1; | 1128 | sample_read = 1; |
875 | } else if (*str == 'D') { | 1129 | } else if (*str == 'D') { |
@@ -900,6 +1154,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str, | |||
900 | mod->eG = eG; | 1154 | mod->eG = eG; |
901 | mod->eI = eI; | 1155 | mod->eI = eI; |
902 | mod->precise = precise; | 1156 | mod->precise = precise; |
1157 | mod->precise_max = precise_max; | ||
903 | mod->exclude_GH = exclude_GH; | 1158 | mod->exclude_GH = exclude_GH; |
904 | mod->sample_read = sample_read; | 1159 | mod->sample_read = sample_read; |
905 | mod->pinned = pinned; | 1160 | mod->pinned = pinned; |
@@ -916,7 +1171,7 @@ static int check_modifier(char *str) | |||
916 | char *p = str; | 1171 | char *p = str; |
917 | 1172 | ||
918 | /* The sizeof includes 0 byte as well. */ | 1173 | /* The sizeof includes 0 byte as well. */ |
919 | if (strlen(str) > (sizeof("ukhGHpppSDI") - 1)) | 1174 | if (strlen(str) > (sizeof("ukhGHpppPSDI") - 1)) |
920 | return -1; | 1175 | return -1; |
921 | 1176 | ||
922 | while (*p) { | 1177 | while (*p) { |
@@ -955,6 +1210,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) | |||
955 | evsel->attr.exclude_idle = mod.eI; | 1210 | evsel->attr.exclude_idle = mod.eI; |
956 | evsel->exclude_GH = mod.exclude_GH; | 1211 | evsel->exclude_GH = mod.exclude_GH; |
957 | evsel->sample_read = mod.sample_read; | 1212 | evsel->sample_read = mod.sample_read; |
1213 | evsel->precise_max = mod.precise_max; | ||
958 | 1214 | ||
959 | if (perf_evsel__is_group_leader(evsel)) | 1215 | if (perf_evsel__is_group_leader(evsel)) |
960 | evsel->attr.pinned = mod.pinned; | 1216 | evsel->attr.pinned = mod.pinned; |
@@ -1140,10 +1396,14 @@ int parse_events(struct perf_evlist *evlist, const char *str, | |||
1140 | ret = parse_events__scanner(str, &data, PE_START_EVENTS); | 1396 | ret = parse_events__scanner(str, &data, PE_START_EVENTS); |
1141 | perf_pmu__parse_cleanup(); | 1397 | perf_pmu__parse_cleanup(); |
1142 | if (!ret) { | 1398 | if (!ret) { |
1143 | int entries = data.idx - evlist->nr_entries; | ||
1144 | struct perf_evsel *last; | 1399 | struct perf_evsel *last; |
1145 | 1400 | ||
1146 | perf_evlist__splice_list_tail(evlist, &data.list, entries); | 1401 | if (list_empty(&data.list)) { |
1402 | WARN_ONCE(true, "WARNING: event parser found nothing"); | ||
1403 | return -1; | ||
1404 | } | ||
1405 | |||
1406 | perf_evlist__splice_list_tail(evlist, &data.list); | ||
1147 | evlist->nr_groups += data.nr_groups; | 1407 | evlist->nr_groups += data.nr_groups; |
1148 | last = perf_evlist__last(evlist); | 1408 | last = perf_evlist__last(evlist); |
1149 | last->cmdline_group_boundary = true; | 1409 | last->cmdline_group_boundary = true; |
@@ -1252,6 +1512,12 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist, | |||
1252 | struct perf_evsel *last = NULL; | 1512 | struct perf_evsel *last = NULL; |
1253 | int err; | 1513 | int err; |
1254 | 1514 | ||
1515 | /* | ||
1516 | * Don't return when list_empty, give func a chance to report | ||
1517 | * error when it found last == NULL. | ||
1518 | * | ||
1519 | * So no need to WARN here, let *func do this. | ||
1520 | */ | ||
1255 | if (evlist->nr_entries > 0) | 1521 | if (evlist->nr_entries > 0) |
1256 | last = perf_evlist__last(evlist); | 1522 | last = perf_evlist__last(evlist); |
1257 | 1523 | ||
@@ -1420,7 +1686,7 @@ restart: | |||
1420 | printf(" %-50s [%s]\n", evt_list[evt_i++], | 1686 | printf(" %-50s [%s]\n", evt_list[evt_i++], |
1421 | event_type_descriptors[PERF_TYPE_TRACEPOINT]); | 1687 | event_type_descriptors[PERF_TYPE_TRACEPOINT]); |
1422 | } | 1688 | } |
1423 | if (evt_num) | 1689 | if (evt_num && pager_in_use()) |
1424 | printf("\n"); | 1690 | printf("\n"); |
1425 | 1691 | ||
1426 | out_free: | 1692 | out_free: |
@@ -1576,7 +1842,7 @@ restart: | |||
1576 | printf(" %-50s [%s]\n", evt_list[evt_i++], | 1842 | printf(" %-50s [%s]\n", evt_list[evt_i++], |
1577 | event_type_descriptors[PERF_TYPE_HW_CACHE]); | 1843 | event_type_descriptors[PERF_TYPE_HW_CACHE]); |
1578 | } | 1844 | } |
1579 | if (evt_num) | 1845 | if (evt_num && pager_in_use()) |
1580 | printf("\n"); | 1846 | printf("\n"); |
1581 | 1847 | ||
1582 | out_free: | 1848 | out_free: |
@@ -1649,7 +1915,7 @@ restart: | |||
1649 | } | 1915 | } |
1650 | printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); | 1916 | printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); |
1651 | } | 1917 | } |
1652 | if (evt_num) | 1918 | if (evt_num && pager_in_use()) |
1653 | printf("\n"); | 1919 | printf("\n"); |
1654 | 1920 | ||
1655 | out_free: | 1921 | out_free: |
@@ -1690,13 +1956,14 @@ void print_events(const char *event_glob, bool name_only) | |||
1690 | printf(" %-50s [%s]\n", | 1956 | printf(" %-50s [%s]\n", |
1691 | "cpu/t1=v1[,t2=v2,t3 ...]/modifier", | 1957 | "cpu/t1=v1[,t2=v2,t3 ...]/modifier", |
1692 | event_type_descriptors[PERF_TYPE_RAW]); | 1958 | event_type_descriptors[PERF_TYPE_RAW]); |
1693 | printf(" (see 'man perf-list' on how to encode it)\n"); | 1959 | if (pager_in_use()) |
1694 | printf("\n"); | 1960 | printf(" (see 'man perf-list' on how to encode it)\n\n"); |
1695 | 1961 | ||
1696 | printf(" %-50s [%s]\n", | 1962 | printf(" %-50s [%s]\n", |
1697 | "mem:<addr>[/len][:access]", | 1963 | "mem:<addr>[/len][:access]", |
1698 | event_type_descriptors[PERF_TYPE_BREAKPOINT]); | 1964 | event_type_descriptors[PERF_TYPE_BREAKPOINT]); |
1699 | printf("\n"); | 1965 | if (pager_in_use()) |
1966 | printf("\n"); | ||
1700 | } | 1967 | } |
1701 | 1968 | ||
1702 | print_tracepoint_events(NULL, NULL, name_only); | 1969 | print_tracepoint_events(NULL, NULL, name_only); |
@@ -1812,3 +2079,29 @@ void parse_events_evlist_error(struct parse_events_evlist *data, | |||
1812 | err->str = strdup(str); | 2079 | err->str = strdup(str); |
1813 | WARN_ONCE(!err->str, "WARNING: failed to allocate error string"); | 2080 | WARN_ONCE(!err->str, "WARNING: failed to allocate error string"); |
1814 | } | 2081 | } |
2082 | |||
2083 | /* | ||
2084 | * Return string contains valid config terms of an event. | ||
2085 | * @additional_terms: For terms such as PMU sysfs terms. | ||
2086 | */ | ||
2087 | char *parse_events_formats_error_string(char *additional_terms) | ||
2088 | { | ||
2089 | char *str; | ||
2090 | static const char *static_terms = "config,config1,config2,name," | ||
2091 | "period,freq,branch_type,time," | ||
2092 | "call-graph,stack-size\n"; | ||
2093 | |||
2094 | /* valid terms */ | ||
2095 | if (additional_terms) { | ||
2096 | if (!asprintf(&str, "valid terms: %s,%s", | ||
2097 | additional_terms, static_terms)) | ||
2098 | goto fail; | ||
2099 | } else { | ||
2100 | if (!asprintf(&str, "valid terms: %s", static_terms)) | ||
2101 | goto fail; | ||
2102 | } | ||
2103 | return str; | ||
2104 | |||
2105 | fail: | ||
2106 | return NULL; | ||
2107 | } | ||
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index a09b0e210997..f1a6db107241 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -67,6 +67,8 @@ enum { | |||
67 | PARSE_EVENTS__TERM_TYPE_TIME, | 67 | PARSE_EVENTS__TERM_TYPE_TIME, |
68 | PARSE_EVENTS__TERM_TYPE_CALLGRAPH, | 68 | PARSE_EVENTS__TERM_TYPE_CALLGRAPH, |
69 | PARSE_EVENTS__TERM_TYPE_STACKSIZE, | 69 | PARSE_EVENTS__TERM_TYPE_STACKSIZE, |
70 | PARSE_EVENTS__TERM_TYPE_NOINHERIT, | ||
71 | PARSE_EVENTS__TERM_TYPE_INHERIT | ||
70 | }; | 72 | }; |
71 | 73 | ||
72 | struct parse_events_term { | 74 | struct parse_events_term { |
@@ -118,7 +120,18 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add); | |||
118 | int parse_events__modifier_group(struct list_head *list, char *event_mod); | 120 | int parse_events__modifier_group(struct list_head *list, char *event_mod); |
119 | int parse_events_name(struct list_head *list, char *name); | 121 | int parse_events_name(struct list_head *list, char *name); |
120 | int parse_events_add_tracepoint(struct list_head *list, int *idx, | 122 | int parse_events_add_tracepoint(struct list_head *list, int *idx, |
121 | char *sys, char *event); | 123 | char *sys, char *event, |
124 | struct parse_events_error *error, | ||
125 | struct list_head *head_config); | ||
126 | int parse_events_load_bpf(struct parse_events_evlist *data, | ||
127 | struct list_head *list, | ||
128 | char *bpf_file_name, | ||
129 | bool source); | ||
130 | /* Provide this function for perf test */ | ||
131 | struct bpf_object; | ||
132 | int parse_events_load_bpf_obj(struct parse_events_evlist *data, | ||
133 | struct list_head *list, | ||
134 | struct bpf_object *obj); | ||
122 | int parse_events_add_numeric(struct parse_events_evlist *data, | 135 | int parse_events_add_numeric(struct parse_events_evlist *data, |
123 | struct list_head *list, | 136 | struct list_head *list, |
124 | u32 type, u64 config, | 137 | u32 type, u64 config, |
@@ -155,5 +168,6 @@ int print_hwcache_events(const char *event_glob, bool name_only); | |||
155 | extern int is_valid_tracepoint(const char *event_string); | 168 | extern int is_valid_tracepoint(const char *event_string); |
156 | 169 | ||
157 | int valid_event_mount(const char *eventfs); | 170 | int valid_event_mount(const char *eventfs); |
171 | char *parse_events_formats_error_string(char *additional_terms); | ||
158 | 172 | ||
159 | #endif /* __PERF_PARSE_EVENTS_H */ | 173 | #endif /* __PERF_PARSE_EVENTS_H */ |
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 936d566f48d8..58c5831ffd5c 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
@@ -115,6 +115,8 @@ do { \ | |||
115 | group [^,{}/]*[{][^}]*[}][^,{}/]* | 115 | group [^,{}/]*[{][^}]*[}][^,{}/]* |
116 | event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* | 116 | event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* |
117 | event [^,{}/]+ | 117 | event [^,{}/]+ |
118 | bpf_object .*\.(o|bpf) | ||
119 | bpf_source .*\.c | ||
118 | 120 | ||
119 | num_dec [0-9]+ | 121 | num_dec [0-9]+ |
120 | num_hex 0x[a-fA-F0-9]+ | 122 | num_hex 0x[a-fA-F0-9]+ |
@@ -122,7 +124,7 @@ num_raw_hex [a-fA-F0-9]+ | |||
122 | name [a-zA-Z_*?][a-zA-Z0-9_*?.]* | 124 | name [a-zA-Z_*?][a-zA-Z0-9_*?.]* |
123 | name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]* | 125 | name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]* |
124 | /* If you add a modifier you need to update check_modifier() */ | 126 | /* If you add a modifier you need to update check_modifier() */ |
125 | modifier_event [ukhpGHSDI]+ | 127 | modifier_event [ukhpPGHSDI]+ |
126 | modifier_bp [rwx]{1,3} | 128 | modifier_bp [rwx]{1,3} |
127 | 129 | ||
128 | %% | 130 | %% |
@@ -159,6 +161,8 @@ modifier_bp [rwx]{1,3} | |||
159 | } | 161 | } |
160 | 162 | ||
161 | {event_pmu} | | 163 | {event_pmu} | |
164 | {bpf_object} | | ||
165 | {bpf_source} | | ||
162 | {event} { | 166 | {event} { |
163 | BEGIN(INITIAL); | 167 | BEGIN(INITIAL); |
164 | REWIND(1); | 168 | REWIND(1); |
@@ -174,7 +178,7 @@ modifier_bp [rwx]{1,3} | |||
174 | 178 | ||
175 | <config>{ | 179 | <config>{ |
176 | /* | 180 | /* |
177 | * Please update formats_error_string any time | 181 | * Please update parse_events_formats_error_string any time |
178 | * new static term is added. | 182 | * new static term is added. |
179 | */ | 183 | */ |
180 | config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } | 184 | config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); } |
@@ -187,6 +191,8 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE | |||
187 | time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } | 191 | time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } |
188 | call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } | 192 | call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } |
189 | stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } | 193 | stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } |
194 | inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } | ||
195 | no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } | ||
190 | , { return ','; } | 196 | , { return ','; } |
191 | "/" { BEGIN(INITIAL); return '/'; } | 197 | "/" { BEGIN(INITIAL); return '/'; } |
192 | {name_minus} { return str(yyscanner, PE_NAME); } | 198 | {name_minus} { return str(yyscanner, PE_NAME); } |
@@ -264,6 +270,8 @@ r{num_raw_hex} { return raw(yyscanner); } | |||
264 | {num_hex} { return value(yyscanner, 16); } | 270 | {num_hex} { return value(yyscanner, 16); } |
265 | 271 | ||
266 | {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } | 272 | {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } |
273 | {bpf_object} { return str(yyscanner, PE_BPF_OBJECT); } | ||
274 | {bpf_source} { return str(yyscanner, PE_BPF_SOURCE); } | ||
267 | {name} { return pmu_str_check(yyscanner); } | 275 | {name} { return pmu_str_check(yyscanner); } |
268 | "/" { BEGIN(config); return '/'; } | 276 | "/" { BEGIN(config); return '/'; } |
269 | - { return '-'; } | 277 | - { return '-'; } |
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 591905a02b92..ad379968d4c1 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y | |||
@@ -42,6 +42,7 @@ static inc_group_count(struct list_head *list, | |||
42 | %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM | 42 | %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM |
43 | %token PE_EVENT_NAME | 43 | %token PE_EVENT_NAME |
44 | %token PE_NAME | 44 | %token PE_NAME |
45 | %token PE_BPF_OBJECT PE_BPF_SOURCE | ||
45 | %token PE_MODIFIER_EVENT PE_MODIFIER_BP | 46 | %token PE_MODIFIER_EVENT PE_MODIFIER_BP |
46 | %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT | 47 | %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT |
47 | %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP | 48 | %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP |
@@ -53,6 +54,8 @@ static inc_group_count(struct list_head *list, | |||
53 | %type <num> PE_RAW | 54 | %type <num> PE_RAW |
54 | %type <num> PE_TERM | 55 | %type <num> PE_TERM |
55 | %type <str> PE_NAME | 56 | %type <str> PE_NAME |
57 | %type <str> PE_BPF_OBJECT | ||
58 | %type <str> PE_BPF_SOURCE | ||
56 | %type <str> PE_NAME_CACHE_TYPE | 59 | %type <str> PE_NAME_CACHE_TYPE |
57 | %type <str> PE_NAME_CACHE_OP_RESULT | 60 | %type <str> PE_NAME_CACHE_OP_RESULT |
58 | %type <str> PE_MODIFIER_EVENT | 61 | %type <str> PE_MODIFIER_EVENT |
@@ -67,8 +70,10 @@ static inc_group_count(struct list_head *list, | |||
67 | %type <head> event_legacy_cache | 70 | %type <head> event_legacy_cache |
68 | %type <head> event_legacy_mem | 71 | %type <head> event_legacy_mem |
69 | %type <head> event_legacy_tracepoint | 72 | %type <head> event_legacy_tracepoint |
73 | %type <tracepoint_name> tracepoint_name | ||
70 | %type <head> event_legacy_numeric | 74 | %type <head> event_legacy_numeric |
71 | %type <head> event_legacy_raw | 75 | %type <head> event_legacy_raw |
76 | %type <head> event_bpf_file | ||
72 | %type <head> event_def | 77 | %type <head> event_def |
73 | %type <head> event_mod | 78 | %type <head> event_mod |
74 | %type <head> event_name | 79 | %type <head> event_name |
@@ -84,6 +89,10 @@ static inc_group_count(struct list_head *list, | |||
84 | u64 num; | 89 | u64 num; |
85 | struct list_head *head; | 90 | struct list_head *head; |
86 | struct parse_events_term *term; | 91 | struct parse_events_term *term; |
92 | struct tracepoint_name { | ||
93 | char *sys; | ||
94 | char *event; | ||
95 | } tracepoint_name; | ||
87 | } | 96 | } |
88 | %% | 97 | %% |
89 | 98 | ||
@@ -198,7 +207,8 @@ event_def: event_pmu | | |||
198 | event_legacy_mem | | 207 | event_legacy_mem | |
199 | event_legacy_tracepoint sep_dc | | 208 | event_legacy_tracepoint sep_dc | |
200 | event_legacy_numeric sep_dc | | 209 | event_legacy_numeric sep_dc | |
201 | event_legacy_raw sep_dc | 210 | event_legacy_raw sep_dc | |
211 | event_bpf_file | ||
202 | 212 | ||
203 | event_pmu: | 213 | event_pmu: |
204 | PE_NAME '/' event_config '/' | 214 | PE_NAME '/' event_config '/' |
@@ -255,7 +265,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc | |||
255 | list_add_tail(&term->list, head); | 265 | list_add_tail(&term->list, head); |
256 | 266 | ||
257 | ALLOC_LIST(list); | 267 | ALLOC_LIST(list); |
258 | ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head)); | 268 | ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); |
259 | parse_events__free_terms(head); | 269 | parse_events__free_terms(head); |
260 | $$ = list; | 270 | $$ = list; |
261 | } | 271 | } |
@@ -368,36 +378,60 @@ PE_PREFIX_MEM PE_VALUE sep_dc | |||
368 | } | 378 | } |
369 | 379 | ||
370 | event_legacy_tracepoint: | 380 | event_legacy_tracepoint: |
371 | PE_NAME '-' PE_NAME ':' PE_NAME | 381 | tracepoint_name |
372 | { | 382 | { |
373 | struct parse_events_evlist *data = _data; | 383 | struct parse_events_evlist *data = _data; |
384 | struct parse_events_error *error = data->error; | ||
374 | struct list_head *list; | 385 | struct list_head *list; |
375 | char sys_name[128]; | ||
376 | snprintf(&sys_name, 128, "%s-%s", $1, $3); | ||
377 | 386 | ||
378 | ALLOC_LIST(list); | 387 | ALLOC_LIST(list); |
379 | ABORT_ON(parse_events_add_tracepoint(list, &data->idx, &sys_name, $5)); | 388 | if (error) |
389 | error->idx = @1.first_column; | ||
390 | |||
391 | if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event, | ||
392 | error, NULL)) | ||
393 | return -1; | ||
394 | |||
380 | $$ = list; | 395 | $$ = list; |
381 | } | 396 | } |
382 | | | 397 | | |
383 | PE_NAME ':' PE_NAME | 398 | tracepoint_name '/' event_config '/' |
384 | { | 399 | { |
385 | struct parse_events_evlist *data = _data; | 400 | struct parse_events_evlist *data = _data; |
401 | struct parse_events_error *error = data->error; | ||
386 | struct list_head *list; | 402 | struct list_head *list; |
387 | 403 | ||
388 | ALLOC_LIST(list); | 404 | ALLOC_LIST(list); |
389 | if (parse_events_add_tracepoint(list, &data->idx, $1, $3)) { | 405 | if (error) |
390 | struct parse_events_error *error = data->error; | 406 | error->idx = @1.first_column; |
391 | 407 | ||
392 | if (error) { | 408 | if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event, |
393 | error->idx = @1.first_column; | 409 | error, $3)) |
394 | error->str = strdup("unknown tracepoint"); | ||
395 | } | ||
396 | return -1; | 410 | return -1; |
397 | } | 411 | |
398 | $$ = list; | 412 | $$ = list; |
399 | } | 413 | } |
400 | 414 | ||
415 | tracepoint_name: | ||
416 | PE_NAME '-' PE_NAME ':' PE_NAME | ||
417 | { | ||
418 | char sys_name[128]; | ||
419 | struct tracepoint_name tracepoint; | ||
420 | |||
421 | snprintf(&sys_name, 128, "%s-%s", $1, $3); | ||
422 | tracepoint.sys = &sys_name; | ||
423 | tracepoint.event = $5; | ||
424 | |||
425 | $$ = tracepoint; | ||
426 | } | ||
427 | | | ||
428 | PE_NAME ':' PE_NAME | ||
429 | { | ||
430 | struct tracepoint_name tracepoint = {$1, $3}; | ||
431 | |||
432 | $$ = tracepoint; | ||
433 | } | ||
434 | |||
401 | event_legacy_numeric: | 435 | event_legacy_numeric: |
402 | PE_VALUE ':' PE_VALUE | 436 | PE_VALUE ':' PE_VALUE |
403 | { | 437 | { |
@@ -420,6 +454,28 @@ PE_RAW | |||
420 | $$ = list; | 454 | $$ = list; |
421 | } | 455 | } |
422 | 456 | ||
457 | event_bpf_file: | ||
458 | PE_BPF_OBJECT | ||
459 | { | ||
460 | struct parse_events_evlist *data = _data; | ||
461 | struct parse_events_error *error = data->error; | ||
462 | struct list_head *list; | ||
463 | |||
464 | ALLOC_LIST(list); | ||
465 | ABORT_ON(parse_events_load_bpf(data, list, $1, false)); | ||
466 | $$ = list; | ||
467 | } | ||
468 | | | ||
469 | PE_BPF_SOURCE | ||
470 | { | ||
471 | struct parse_events_evlist *data = _data; | ||
472 | struct list_head *list; | ||
473 | |||
474 | ALLOC_LIST(list); | ||
475 | ABORT_ON(parse_events_load_bpf(data, list, $1, true)); | ||
476 | $$ = list; | ||
477 | } | ||
478 | |||
423 | start_terms: event_config | 479 | start_terms: event_config |
424 | { | 480 | { |
425 | struct parse_events_terms *data = _data; | 481 | struct parse_events_terms *data = _data; |
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 01626be2a8eb..9fca09296eb3 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c | |||
@@ -2,10 +2,13 @@ | |||
2 | #include "parse-options.h" | 2 | #include "parse-options.h" |
3 | #include "cache.h" | 3 | #include "cache.h" |
4 | #include "header.h" | 4 | #include "header.h" |
5 | #include <linux/string.h> | ||
5 | 6 | ||
6 | #define OPT_SHORT 1 | 7 | #define OPT_SHORT 1 |
7 | #define OPT_UNSET 2 | 8 | #define OPT_UNSET 2 |
8 | 9 | ||
10 | static struct strbuf error_buf = STRBUF_INIT; | ||
11 | |||
9 | static int opterror(const struct option *opt, const char *reason, int flags) | 12 | static int opterror(const struct option *opt, const char *reason, int flags) |
10 | { | 13 | { |
11 | if (flags & OPT_SHORT) | 14 | if (flags & OPT_SHORT) |
@@ -372,7 +375,8 @@ void parse_options_start(struct parse_opt_ctx_t *ctx, | |||
372 | } | 375 | } |
373 | 376 | ||
374 | static int usage_with_options_internal(const char * const *, | 377 | static int usage_with_options_internal(const char * const *, |
375 | const struct option *, int); | 378 | const struct option *, int, |
379 | struct parse_opt_ctx_t *); | ||
376 | 380 | ||
377 | int parse_options_step(struct parse_opt_ctx_t *ctx, | 381 | int parse_options_step(struct parse_opt_ctx_t *ctx, |
378 | const struct option *options, | 382 | const struct option *options, |
@@ -396,8 +400,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
396 | 400 | ||
397 | if (arg[1] != '-') { | 401 | if (arg[1] != '-') { |
398 | ctx->opt = ++arg; | 402 | ctx->opt = ++arg; |
399 | if (internal_help && *ctx->opt == 'h') | 403 | if (internal_help && *ctx->opt == 'h') { |
400 | return usage_with_options_internal(usagestr, options, 0); | 404 | return usage_with_options_internal(usagestr, options, 0, ctx); |
405 | } | ||
401 | switch (parse_short_opt(ctx, options)) { | 406 | switch (parse_short_opt(ctx, options)) { |
402 | case -1: | 407 | case -1: |
403 | return parse_options_usage(usagestr, options, arg, 1); | 408 | return parse_options_usage(usagestr, options, arg, 1); |
@@ -412,7 +417,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
412 | check_typos(arg, options); | 417 | check_typos(arg, options); |
413 | while (ctx->opt) { | 418 | while (ctx->opt) { |
414 | if (internal_help && *ctx->opt == 'h') | 419 | if (internal_help && *ctx->opt == 'h') |
415 | return usage_with_options_internal(usagestr, options, 0); | 420 | return usage_with_options_internal(usagestr, options, 0, ctx); |
416 | arg = ctx->opt; | 421 | arg = ctx->opt; |
417 | switch (parse_short_opt(ctx, options)) { | 422 | switch (parse_short_opt(ctx, options)) { |
418 | case -1: | 423 | case -1: |
@@ -445,9 +450,9 @@ int parse_options_step(struct parse_opt_ctx_t *ctx, | |||
445 | 450 | ||
446 | arg += 2; | 451 | arg += 2; |
447 | if (internal_help && !strcmp(arg, "help-all")) | 452 | if (internal_help && !strcmp(arg, "help-all")) |
448 | return usage_with_options_internal(usagestr, options, 1); | 453 | return usage_with_options_internal(usagestr, options, 1, ctx); |
449 | if (internal_help && !strcmp(arg, "help")) | 454 | if (internal_help && !strcmp(arg, "help")) |
450 | return usage_with_options_internal(usagestr, options, 0); | 455 | return usage_with_options_internal(usagestr, options, 0, ctx); |
451 | if (!strcmp(arg, "list-opts")) | 456 | if (!strcmp(arg, "list-opts")) |
452 | return PARSE_OPT_LIST_OPTS; | 457 | return PARSE_OPT_LIST_OPTS; |
453 | if (!strcmp(arg, "list-cmds")) | 458 | if (!strcmp(arg, "list-cmds")) |
@@ -496,7 +501,7 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o | |||
496 | { | 501 | { |
497 | struct parse_opt_ctx_t ctx; | 502 | struct parse_opt_ctx_t ctx; |
498 | 503 | ||
499 | perf_header__set_cmdline(argc, argv); | 504 | perf_env__set_cmdline(&perf_env, argc, argv); |
500 | 505 | ||
501 | /* build usage string if it's not provided */ | 506 | /* build usage string if it's not provided */ |
502 | if (subcommands && !usagestr[0]) { | 507 | if (subcommands && !usagestr[0]) { |
@@ -537,9 +542,11 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o | |||
537 | exit(130); | 542 | exit(130); |
538 | default: /* PARSE_OPT_UNKNOWN */ | 543 | default: /* PARSE_OPT_UNKNOWN */ |
539 | if (ctx.argv[0][1] == '-') { | 544 | if (ctx.argv[0][1] == '-') { |
540 | error("unknown option `%s'", ctx.argv[0] + 2); | 545 | strbuf_addf(&error_buf, "unknown option `%s'", |
546 | ctx.argv[0] + 2); | ||
541 | } else { | 547 | } else { |
542 | error("unknown switch `%c'", *ctx.opt); | 548 | strbuf_addf(&error_buf, "unknown switch `%c'", |
549 | *ctx.opt); | ||
543 | } | 550 | } |
544 | usage_with_options(usagestr, options); | 551 | usage_with_options(usagestr, options); |
545 | } | 552 | } |
@@ -642,13 +649,93 @@ static void print_option_help(const struct option *opts, int full) | |||
642 | fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); | 649 | fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help); |
643 | } | 650 | } |
644 | 651 | ||
652 | static int option__cmp(const void *va, const void *vb) | ||
653 | { | ||
654 | const struct option *a = va, *b = vb; | ||
655 | int sa = tolower(a->short_name), sb = tolower(b->short_name), ret; | ||
656 | |||
657 | if (sa == 0) | ||
658 | sa = 'z' + 1; | ||
659 | if (sb == 0) | ||
660 | sb = 'z' + 1; | ||
661 | |||
662 | ret = sa - sb; | ||
663 | |||
664 | if (ret == 0) { | ||
665 | const char *la = a->long_name ?: "", | ||
666 | *lb = b->long_name ?: ""; | ||
667 | ret = strcmp(la, lb); | ||
668 | } | ||
669 | |||
670 | return ret; | ||
671 | } | ||
672 | |||
673 | static struct option *options__order(const struct option *opts) | ||
674 | { | ||
675 | int nr_opts = 0; | ||
676 | const struct option *o = opts; | ||
677 | struct option *ordered; | ||
678 | |||
679 | for (o = opts; o->type != OPTION_END; o++) | ||
680 | ++nr_opts; | ||
681 | |||
682 | ordered = memdup(opts, sizeof(*o) * (nr_opts + 1)); | ||
683 | if (ordered == NULL) | ||
684 | goto out; | ||
685 | |||
686 | qsort(ordered, nr_opts, sizeof(*o), option__cmp); | ||
687 | out: | ||
688 | return ordered; | ||
689 | } | ||
690 | |||
691 | static bool option__in_argv(const struct option *opt, const struct parse_opt_ctx_t *ctx) | ||
692 | { | ||
693 | int i; | ||
694 | |||
695 | for (i = 1; i < ctx->argc; ++i) { | ||
696 | const char *arg = ctx->argv[i]; | ||
697 | |||
698 | if (arg[0] != '-') { | ||
699 | if (arg[1] == '\0') { | ||
700 | if (arg[0] == opt->short_name) | ||
701 | return true; | ||
702 | continue; | ||
703 | } | ||
704 | |||
705 | if (opt->long_name && strcmp(opt->long_name, arg) == 0) | ||
706 | return true; | ||
707 | |||
708 | if (opt->help && strcasestr(opt->help, arg) != NULL) | ||
709 | return true; | ||
710 | |||
711 | continue; | ||
712 | } | ||
713 | |||
714 | if (arg[1] == opt->short_name || | ||
715 | (arg[1] == '-' && opt->long_name && strcmp(opt->long_name, arg + 2) == 0)) | ||
716 | return true; | ||
717 | } | ||
718 | |||
719 | return false; | ||
720 | } | ||
721 | |||
645 | int usage_with_options_internal(const char * const *usagestr, | 722 | int usage_with_options_internal(const char * const *usagestr, |
646 | const struct option *opts, int full) | 723 | const struct option *opts, int full, |
724 | struct parse_opt_ctx_t *ctx) | ||
647 | { | 725 | { |
726 | struct option *ordered; | ||
727 | |||
648 | if (!usagestr) | 728 | if (!usagestr) |
649 | return PARSE_OPT_HELP; | 729 | return PARSE_OPT_HELP; |
650 | 730 | ||
651 | fprintf(stderr, "\n usage: %s\n", *usagestr++); | 731 | setup_pager(); |
732 | |||
733 | if (strbuf_avail(&error_buf)) { | ||
734 | fprintf(stderr, " Error: %s\n", error_buf.buf); | ||
735 | strbuf_release(&error_buf); | ||
736 | } | ||
737 | |||
738 | fprintf(stderr, "\n Usage: %s\n", *usagestr++); | ||
652 | while (*usagestr && **usagestr) | 739 | while (*usagestr && **usagestr) |
653 | fprintf(stderr, " or: %s\n", *usagestr++); | 740 | fprintf(stderr, " or: %s\n", *usagestr++); |
654 | while (*usagestr) { | 741 | while (*usagestr) { |
@@ -661,11 +748,20 @@ int usage_with_options_internal(const char * const *usagestr, | |||
661 | if (opts->type != OPTION_GROUP) | 748 | if (opts->type != OPTION_GROUP) |
662 | fputc('\n', stderr); | 749 | fputc('\n', stderr); |
663 | 750 | ||
664 | for ( ; opts->type != OPTION_END; opts++) | 751 | ordered = options__order(opts); |
752 | if (ordered) | ||
753 | opts = ordered; | ||
754 | |||
755 | for ( ; opts->type != OPTION_END; opts++) { | ||
756 | if (ctx && ctx->argc > 1 && !option__in_argv(opts, ctx)) | ||
757 | continue; | ||
665 | print_option_help(opts, full); | 758 | print_option_help(opts, full); |
759 | } | ||
666 | 760 | ||
667 | fputc('\n', stderr); | 761 | fputc('\n', stderr); |
668 | 762 | ||
763 | free(ordered); | ||
764 | |||
669 | return PARSE_OPT_HELP; | 765 | return PARSE_OPT_HELP; |
670 | } | 766 | } |
671 | 767 | ||
@@ -673,7 +769,22 @@ void usage_with_options(const char * const *usagestr, | |||
673 | const struct option *opts) | 769 | const struct option *opts) |
674 | { | 770 | { |
675 | exit_browser(false); | 771 | exit_browser(false); |
676 | usage_with_options_internal(usagestr, opts, 0); | 772 | usage_with_options_internal(usagestr, opts, 0, NULL); |
773 | exit(129); | ||
774 | } | ||
775 | |||
776 | void usage_with_options_msg(const char * const *usagestr, | ||
777 | const struct option *opts, const char *fmt, ...) | ||
778 | { | ||
779 | va_list ap; | ||
780 | |||
781 | exit_browser(false); | ||
782 | |||
783 | va_start(ap, fmt); | ||
784 | strbuf_addv(&error_buf, fmt, ap); | ||
785 | va_end(ap); | ||
786 | |||
787 | usage_with_options_internal(usagestr, opts, 0, NULL); | ||
677 | exit(129); | 788 | exit(129); |
678 | } | 789 | } |
679 | 790 | ||
@@ -684,7 +795,7 @@ int parse_options_usage(const char * const *usagestr, | |||
684 | if (!usagestr) | 795 | if (!usagestr) |
685 | goto opt; | 796 | goto opt; |
686 | 797 | ||
687 | fprintf(stderr, "\n usage: %s\n", *usagestr++); | 798 | fprintf(stderr, "\n Usage: %s\n", *usagestr++); |
688 | while (*usagestr && **usagestr) | 799 | while (*usagestr && **usagestr) |
689 | fprintf(stderr, " or: %s\n", *usagestr++); | 800 | fprintf(stderr, " or: %s\n", *usagestr++); |
690 | while (*usagestr) { | 801 | while (*usagestr) { |
@@ -698,24 +809,23 @@ int parse_options_usage(const char * const *usagestr, | |||
698 | opt: | 809 | opt: |
699 | for ( ; opts->type != OPTION_END; opts++) { | 810 | for ( ; opts->type != OPTION_END; opts++) { |
700 | if (short_opt) { | 811 | if (short_opt) { |
701 | if (opts->short_name == *optstr) | 812 | if (opts->short_name == *optstr) { |
813 | print_option_help(opts, 0); | ||
702 | break; | 814 | break; |
815 | } | ||
703 | continue; | 816 | continue; |
704 | } | 817 | } |
705 | 818 | ||
706 | if (opts->long_name == NULL) | 819 | if (opts->long_name == NULL) |
707 | continue; | 820 | continue; |
708 | 821 | ||
709 | if (!prefixcmp(optstr, opts->long_name)) | 822 | if (!prefixcmp(opts->long_name, optstr)) |
710 | break; | 823 | print_option_help(opts, 0); |
711 | if (!prefixcmp(optstr, "no-") && | 824 | if (!prefixcmp("no-", optstr) && |
712 | !prefixcmp(optstr + 3, opts->long_name)) | 825 | !prefixcmp(opts->long_name, optstr + 3)) |
713 | break; | 826 | print_option_help(opts, 0); |
714 | } | 827 | } |
715 | 828 | ||
716 | if (opts->type != OPTION_END) | ||
717 | print_option_help(opts, 0); | ||
718 | |||
719 | return PARSE_OPT_HELP; | 829 | return PARSE_OPT_HELP; |
720 | } | 830 | } |
721 | 831 | ||
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index 367d8b816cc7..a8e407bc251e 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h | |||
@@ -111,6 +111,7 @@ struct option { | |||
111 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } | 111 | #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } |
112 | #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } | 112 | #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } |
113 | #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } | 113 | #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } |
114 | #define OPT_BOOLEAN_FLAG(s, l, v, h, f) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h), .flags = (f) } | ||
114 | #define OPT_BOOLEAN_SET(s, l, v, os, h) \ | 115 | #define OPT_BOOLEAN_SET(s, l, v, os, h) \ |
115 | { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ | 116 | { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \ |
116 | .value = check_vtype(v, bool *), .help = (h), \ | 117 | .value = check_vtype(v, bool *), .help = (h), \ |
@@ -160,6 +161,10 @@ extern int parse_options_subcommand(int argc, const char **argv, | |||
160 | 161 | ||
161 | extern NORETURN void usage_with_options(const char * const *usagestr, | 162 | extern NORETURN void usage_with_options(const char * const *usagestr, |
162 | const struct option *options); | 163 | const struct option *options); |
164 | extern NORETURN __attribute__((format(printf,3,4))) | ||
165 | void usage_with_options_msg(const char * const *usagestr, | ||
166 | const struct option *options, | ||
167 | const char *fmt, ...); | ||
163 | 168 | ||
164 | /*----- incremantal advanced APIs -----*/ | 169 | /*----- incremantal advanced APIs -----*/ |
165 | 170 | ||
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c index 885e8ac83997..6b8eb13e14e4 100644 --- a/tools/perf/util/perf_regs.c +++ b/tools/perf/util/perf_regs.c | |||
@@ -6,6 +6,7 @@ const struct sample_reg __weak sample_reg_masks[] = { | |||
6 | SMPL_REG_END | 6 | SMPL_REG_END |
7 | }; | 7 | }; |
8 | 8 | ||
9 | #ifdef HAVE_PERF_REGS_SUPPORT | ||
9 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) | 10 | int perf_reg_value(u64 *valp, struct regs_dump *regs, int id) |
10 | { | 11 | { |
11 | int i, idx = 0; | 12 | int i, idx = 0; |
@@ -29,3 +30,4 @@ out: | |||
29 | *valp = regs->cache_regs[id]; | 30 | *valp = regs->cache_regs[id]; |
30 | return 0; | 31 | return 0; |
31 | } | 32 | } |
33 | #endif | ||
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index 2984dcc54d67..679d6e493962 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __PERF_REGS_H | 2 | #define __PERF_REGS_H |
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <linux/compiler.h> | ||
5 | 6 | ||
6 | struct regs_dump; | 7 | struct regs_dump; |
7 | 8 | ||
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 89c91a1a67e7..e4b173dec4b9 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -626,38 +626,26 @@ static int pmu_resolve_param_term(struct parse_events_term *term, | |||
626 | return -1; | 626 | return -1; |
627 | } | 627 | } |
628 | 628 | ||
629 | static char *formats_error_string(struct list_head *formats) | 629 | static char *pmu_formats_string(struct list_head *formats) |
630 | { | 630 | { |
631 | struct perf_pmu_format *format; | 631 | struct perf_pmu_format *format; |
632 | char *err, *str; | 632 | char *str; |
633 | static const char *static_terms = "config,config1,config2,name," | 633 | struct strbuf buf; |
634 | "period,freq,branch_type,time," | ||
635 | "call-graph,stack-size\n"; | ||
636 | unsigned i = 0; | 634 | unsigned i = 0; |
637 | 635 | ||
638 | if (!asprintf(&str, "valid terms:")) | 636 | if (!formats) |
639 | return NULL; | 637 | return NULL; |
640 | 638 | ||
639 | strbuf_init(&buf, 0); | ||
641 | /* sysfs exported terms */ | 640 | /* sysfs exported terms */ |
642 | list_for_each_entry(format, formats, list) { | 641 | list_for_each_entry(format, formats, list) |
643 | char c = i++ ? ',' : ' '; | 642 | strbuf_addf(&buf, i++ ? ",%s" : "%s", |
644 | 643 | format->name); | |
645 | err = str; | ||
646 | if (!asprintf(&str, "%s%c%s", err, c, format->name)) | ||
647 | goto fail; | ||
648 | free(err); | ||
649 | } | ||
650 | 644 | ||
651 | /* static terms */ | 645 | str = strbuf_detach(&buf, NULL); |
652 | err = str; | 646 | strbuf_release(&buf); |
653 | if (!asprintf(&str, "%s,%s", err, static_terms)) | ||
654 | goto fail; | ||
655 | 647 | ||
656 | free(err); | ||
657 | return str; | 648 | return str; |
658 | fail: | ||
659 | free(err); | ||
660 | return NULL; | ||
661 | } | 649 | } |
662 | 650 | ||
663 | /* | 651 | /* |
@@ -693,9 +681,12 @@ static int pmu_config_term(struct list_head *formats, | |||
693 | if (verbose) | 681 | if (verbose) |
694 | printf("Invalid event/parameter '%s'\n", term->config); | 682 | printf("Invalid event/parameter '%s'\n", term->config); |
695 | if (err) { | 683 | if (err) { |
684 | char *pmu_term = pmu_formats_string(formats); | ||
685 | |||
696 | err->idx = term->err_term; | 686 | err->idx = term->err_term; |
697 | err->str = strdup("unknown term"); | 687 | err->str = strdup("unknown term"); |
698 | err->help = formats_error_string(formats); | 688 | err->help = parse_events_formats_error_string(pmu_term); |
689 | free(pmu_term); | ||
699 | } | 690 | } |
700 | return -EINVAL; | 691 | return -EINVAL; |
701 | } | 692 | } |
@@ -1017,7 +1008,8 @@ void print_pmu_events(const char *event_glob, bool name_only) | |||
1017 | goto out_enomem; | 1008 | goto out_enomem; |
1018 | j++; | 1009 | j++; |
1019 | } | 1010 | } |
1020 | if (pmu->selectable) { | 1011 | if (pmu->selectable && |
1012 | (event_glob == NULL || strglobmatch(pmu->name, event_glob))) { | ||
1021 | char *s; | 1013 | char *s; |
1022 | if (asprintf(&s, "%s//", pmu->name) < 0) | 1014 | if (asprintf(&s, "%s//", pmu->name) < 0) |
1023 | goto out_enomem; | 1015 | goto out_enomem; |
@@ -1035,7 +1027,7 @@ void print_pmu_events(const char *event_glob, bool name_only) | |||
1035 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); | 1027 | printf(" %-50s [Kernel PMU event]\n", aliases[j]); |
1036 | printed++; | 1028 | printed++; |
1037 | } | 1029 | } |
1038 | if (printed) | 1030 | if (printed && pager_in_use()) |
1039 | printf("\n"); | 1031 | printf("\n"); |
1040 | out_free: | 1032 | out_free: |
1041 | for (j = 0; j < len; j++) | 1033 | for (j = 0; j < len; j++) |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index eb5f18b75402..b51a8bfb40f9 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -40,8 +40,7 @@ | |||
40 | #include "color.h" | 40 | #include "color.h" |
41 | #include "symbol.h" | 41 | #include "symbol.h" |
42 | #include "thread.h" | 42 | #include "thread.h" |
43 | #include <api/fs/debugfs.h> | 43 | #include <api/fs/fs.h> |
44 | #include <api/fs/tracefs.h> | ||
45 | #include "trace-event.h" /* For __maybe_unused */ | 44 | #include "trace-event.h" /* For __maybe_unused */ |
46 | #include "probe-event.h" | 45 | #include "probe-event.h" |
47 | #include "probe-finder.h" | 46 | #include "probe-finder.h" |
@@ -72,7 +71,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp); | |||
72 | static struct machine *host_machine; | 71 | static struct machine *host_machine; |
73 | 72 | ||
74 | /* Initialize symbol maps and path of vmlinux/modules */ | 73 | /* Initialize symbol maps and path of vmlinux/modules */ |
75 | static int init_symbol_maps(bool user_only) | 74 | int init_probe_symbol_maps(bool user_only) |
76 | { | 75 | { |
77 | int ret; | 76 | int ret; |
78 | 77 | ||
@@ -102,7 +101,7 @@ out: | |||
102 | return ret; | 101 | return ret; |
103 | } | 102 | } |
104 | 103 | ||
105 | static void exit_symbol_maps(void) | 104 | void exit_probe_symbol_maps(void) |
106 | { | 105 | { |
107 | if (host_machine) { | 106 | if (host_machine) { |
108 | machine__delete(host_machine); | 107 | machine__delete(host_machine); |
@@ -127,17 +126,19 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) | |||
127 | { | 126 | { |
128 | /* kmap->ref_reloc_sym should be set if host_machine is initialized */ | 127 | /* kmap->ref_reloc_sym should be set if host_machine is initialized */ |
129 | struct kmap *kmap; | 128 | struct kmap *kmap; |
129 | struct map *map = machine__kernel_map(host_machine); | ||
130 | 130 | ||
131 | if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0) | 131 | if (map__load(map, NULL) < 0) |
132 | return NULL; | 132 | return NULL; |
133 | 133 | ||
134 | kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); | 134 | kmap = map__kmap(map); |
135 | if (!kmap) | 135 | if (!kmap) |
136 | return NULL; | 136 | return NULL; |
137 | return kmap->ref_reloc_sym; | 137 | return kmap->ref_reloc_sym; |
138 | } | 138 | } |
139 | 139 | ||
140 | static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc) | 140 | static int kernel_get_symbol_address_by_name(const char *name, u64 *addr, |
141 | bool reloc, bool reladdr) | ||
141 | { | 142 | { |
142 | struct ref_reloc_sym *reloc_sym; | 143 | struct ref_reloc_sym *reloc_sym; |
143 | struct symbol *sym; | 144 | struct symbol *sym; |
@@ -146,12 +147,14 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc) | |||
146 | /* ref_reloc_sym is just a label. Need a special fix*/ | 147 | /* ref_reloc_sym is just a label. Need a special fix*/ |
147 | reloc_sym = kernel_get_ref_reloc_sym(); | 148 | reloc_sym = kernel_get_ref_reloc_sym(); |
148 | if (reloc_sym && strcmp(name, reloc_sym->name) == 0) | 149 | if (reloc_sym && strcmp(name, reloc_sym->name) == 0) |
149 | return (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr; | 150 | *addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr; |
150 | else { | 151 | else { |
151 | sym = __find_kernel_function_by_name(name, &map); | 152 | sym = __find_kernel_function_by_name(name, &map); |
152 | if (sym) | 153 | if (!sym) |
153 | return map->unmap_ip(map, sym->start) - | 154 | return -ENOENT; |
154 | ((reloc) ? 0 : map->reloc); | 155 | *addr = map->unmap_ip(map, sym->start) - |
156 | ((reloc) ? 0 : map->reloc) - | ||
157 | ((reladdr) ? map->start : 0); | ||
155 | } | 158 | } |
156 | return 0; | 159 | return 0; |
157 | } | 160 | } |
@@ -245,12 +248,14 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) | |||
245 | static bool kprobe_blacklist__listed(unsigned long address); | 248 | static bool kprobe_blacklist__listed(unsigned long address); |
246 | static bool kprobe_warn_out_range(const char *symbol, unsigned long address) | 249 | static bool kprobe_warn_out_range(const char *symbol, unsigned long address) |
247 | { | 250 | { |
248 | u64 etext_addr; | 251 | u64 etext_addr = 0; |
252 | int ret; | ||
249 | 253 | ||
250 | /* Get the address of _etext for checking non-probable text symbol */ | 254 | /* Get the address of _etext for checking non-probable text symbol */ |
251 | etext_addr = kernel_get_symbol_address_by_name("_etext", false); | 255 | ret = kernel_get_symbol_address_by_name("_etext", &etext_addr, |
256 | false, false); | ||
252 | 257 | ||
253 | if (etext_addr != 0 && etext_addr < address) | 258 | if (ret == 0 && etext_addr < address) |
254 | pr_warning("%s is out of .text, skip it.\n", symbol); | 259 | pr_warning("%s is out of .text, skip it.\n", symbol); |
255 | else if (kprobe_blacklist__listed(address)) | 260 | else if (kprobe_blacklist__listed(address)) |
256 | pr_warning("%s is blacklisted function, skip it.\n", symbol); | 261 | pr_warning("%s is blacklisted function, skip it.\n", symbol); |
@@ -270,18 +275,19 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso) | |||
270 | int ret = 0; | 275 | int ret = 0; |
271 | 276 | ||
272 | if (module) { | 277 | if (module) { |
273 | list_for_each_entry(dso, &host_machine->dsos.head, node) { | 278 | char module_name[128]; |
274 | if (!dso->kernel) | 279 | |
275 | continue; | 280 | snprintf(module_name, sizeof(module_name), "[%s]", module); |
276 | if (strncmp(dso->short_name + 1, module, | 281 | map = map_groups__find_by_name(&host_machine->kmaps, MAP__FUNCTION, module_name); |
277 | dso->short_name_len - 2) == 0) | 282 | if (map) { |
278 | goto found; | 283 | dso = map->dso; |
284 | goto found; | ||
279 | } | 285 | } |
280 | pr_debug("Failed to find module %s.\n", module); | 286 | pr_debug("Failed to find module %s.\n", module); |
281 | return -ENOENT; | 287 | return -ENOENT; |
282 | } | 288 | } |
283 | 289 | ||
284 | map = host_machine->vmlinux_maps[MAP__FUNCTION]; | 290 | map = machine__kernel_map(host_machine); |
285 | dso = map->dso; | 291 | dso = map->dso; |
286 | 292 | ||
287 | vmlinux_name = symbol_conf.vmlinux_name; | 293 | vmlinux_name = symbol_conf.vmlinux_name; |
@@ -435,19 +441,22 @@ static char *debuginfo_cache_path; | |||
435 | 441 | ||
436 | static struct debuginfo *debuginfo_cache__open(const char *module, bool silent) | 442 | static struct debuginfo *debuginfo_cache__open(const char *module, bool silent) |
437 | { | 443 | { |
438 | if ((debuginfo_cache_path && !strcmp(debuginfo_cache_path, module)) || | 444 | const char *path = module; |
439 | (!debuginfo_cache_path && !module && debuginfo_cache)) | 445 | |
446 | /* If the module is NULL, it should be the kernel. */ | ||
447 | if (!module) | ||
448 | path = "kernel"; | ||
449 | |||
450 | if (debuginfo_cache_path && !strcmp(debuginfo_cache_path, path)) | ||
440 | goto out; | 451 | goto out; |
441 | 452 | ||
442 | /* Copy module path */ | 453 | /* Copy module path */ |
443 | free(debuginfo_cache_path); | 454 | free(debuginfo_cache_path); |
444 | if (module) { | 455 | debuginfo_cache_path = strdup(path); |
445 | debuginfo_cache_path = strdup(module); | 456 | if (!debuginfo_cache_path) { |
446 | if (!debuginfo_cache_path) { | 457 | debuginfo__delete(debuginfo_cache); |
447 | debuginfo__delete(debuginfo_cache); | 458 | debuginfo_cache = NULL; |
448 | debuginfo_cache = NULL; | 459 | goto out; |
449 | goto out; | ||
450 | } | ||
451 | } | 460 | } |
452 | 461 | ||
453 | debuginfo_cache = open_debuginfo(module, silent); | 462 | debuginfo_cache = open_debuginfo(module, silent); |
@@ -516,8 +525,10 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp, | |||
516 | goto error; | 525 | goto error; |
517 | addr += stext; | 526 | addr += stext; |
518 | } else if (tp->symbol) { | 527 | } else if (tp->symbol) { |
519 | addr = kernel_get_symbol_address_by_name(tp->symbol, false); | 528 | /* If the module is given, this returns relative address */ |
520 | if (addr == 0) | 529 | ret = kernel_get_symbol_address_by_name(tp->symbol, &addr, |
530 | false, !!tp->module); | ||
531 | if (ret != 0) | ||
521 | goto error; | 532 | goto error; |
522 | addr += tp->offset; | 533 | addr += tp->offset; |
523 | } | 534 | } |
@@ -860,11 +871,11 @@ int show_line_range(struct line_range *lr, const char *module, bool user) | |||
860 | { | 871 | { |
861 | int ret; | 872 | int ret; |
862 | 873 | ||
863 | ret = init_symbol_maps(user); | 874 | ret = init_probe_symbol_maps(user); |
864 | if (ret < 0) | 875 | if (ret < 0) |
865 | return ret; | 876 | return ret; |
866 | ret = __show_line_range(lr, module, user); | 877 | ret = __show_line_range(lr, module, user); |
867 | exit_symbol_maps(); | 878 | exit_probe_symbol_maps(); |
868 | 879 | ||
869 | return ret; | 880 | return ret; |
870 | } | 881 | } |
@@ -942,7 +953,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, | |||
942 | int i, ret = 0; | 953 | int i, ret = 0; |
943 | struct debuginfo *dinfo; | 954 | struct debuginfo *dinfo; |
944 | 955 | ||
945 | ret = init_symbol_maps(pevs->uprobes); | 956 | ret = init_probe_symbol_maps(pevs->uprobes); |
946 | if (ret < 0) | 957 | if (ret < 0) |
947 | return ret; | 958 | return ret; |
948 | 959 | ||
@@ -959,7 +970,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, | |||
959 | 970 | ||
960 | debuginfo__delete(dinfo); | 971 | debuginfo__delete(dinfo); |
961 | out: | 972 | out: |
962 | exit_symbol_maps(); | 973 | exit_probe_symbol_maps(); |
963 | return ret; | 974 | return ret; |
964 | } | 975 | } |
965 | 976 | ||
@@ -1883,8 +1894,12 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp, | |||
1883 | goto out; | 1894 | goto out; |
1884 | sym = map__find_symbol(map, addr, NULL); | 1895 | sym = map__find_symbol(map, addr, NULL); |
1885 | } else { | 1896 | } else { |
1886 | if (tp->symbol) | 1897 | if (tp->symbol && !addr) { |
1887 | addr = kernel_get_symbol_address_by_name(tp->symbol, true); | 1898 | ret = kernel_get_symbol_address_by_name(tp->symbol, |
1899 | &addr, true, false); | ||
1900 | if (ret < 0) | ||
1901 | goto out; | ||
1902 | } | ||
1888 | if (addr) { | 1903 | if (addr) { |
1889 | addr += tp->offset; | 1904 | addr += tp->offset; |
1890 | sym = __find_kernel_function(addr, &map); | 1905 | sym = __find_kernel_function(addr, &map); |
@@ -2054,7 +2069,7 @@ static void kprobe_blacklist__delete(struct list_head *blacklist) | |||
2054 | static int kprobe_blacklist__load(struct list_head *blacklist) | 2069 | static int kprobe_blacklist__load(struct list_head *blacklist) |
2055 | { | 2070 | { |
2056 | struct kprobe_blacklist_node *node; | 2071 | struct kprobe_blacklist_node *node; |
2057 | const char *__debugfs = debugfs_find_mountpoint(); | 2072 | const char *__debugfs = debugfs__mountpoint(); |
2058 | char buf[PATH_MAX], *p; | 2073 | char buf[PATH_MAX], *p; |
2059 | FILE *fp; | 2074 | FILE *fp; |
2060 | int ret; | 2075 | int ret; |
@@ -2180,9 +2195,9 @@ out: | |||
2180 | } | 2195 | } |
2181 | 2196 | ||
2182 | /* Show an event */ | 2197 | /* Show an event */ |
2183 | static int show_perf_probe_event(const char *group, const char *event, | 2198 | int show_perf_probe_event(const char *group, const char *event, |
2184 | struct perf_probe_event *pev, | 2199 | struct perf_probe_event *pev, |
2185 | const char *module, bool use_stdout) | 2200 | const char *module, bool use_stdout) |
2186 | { | 2201 | { |
2187 | struct strbuf buf = STRBUF_INIT; | 2202 | struct strbuf buf = STRBUF_INIT; |
2188 | int ret; | 2203 | int ret; |
@@ -2263,7 +2278,7 @@ int show_perf_probe_events(struct strfilter *filter) | |||
2263 | 2278 | ||
2264 | setup_pager(); | 2279 | setup_pager(); |
2265 | 2280 | ||
2266 | ret = init_symbol_maps(false); | 2281 | ret = init_probe_symbol_maps(false); |
2267 | if (ret < 0) | 2282 | if (ret < 0) |
2268 | return ret; | 2283 | return ret; |
2269 | 2284 | ||
@@ -2279,7 +2294,7 @@ int show_perf_probe_events(struct strfilter *filter) | |||
2279 | close(kp_fd); | 2294 | close(kp_fd); |
2280 | if (up_fd > 0) | 2295 | if (up_fd > 0) |
2281 | close(up_fd); | 2296 | close(up_fd); |
2282 | exit_symbol_maps(); | 2297 | exit_probe_symbol_maps(); |
2283 | 2298 | ||
2284 | return ret; | 2299 | return ret; |
2285 | } | 2300 | } |
@@ -2288,36 +2303,41 @@ static int get_new_event_name(char *buf, size_t len, const char *base, | |||
2288 | struct strlist *namelist, bool allow_suffix) | 2303 | struct strlist *namelist, bool allow_suffix) |
2289 | { | 2304 | { |
2290 | int i, ret; | 2305 | int i, ret; |
2291 | char *p; | 2306 | char *p, *nbase; |
2292 | 2307 | ||
2293 | if (*base == '.') | 2308 | if (*base == '.') |
2294 | base++; | 2309 | base++; |
2310 | nbase = strdup(base); | ||
2311 | if (!nbase) | ||
2312 | return -ENOMEM; | ||
2295 | 2313 | ||
2296 | /* Try no suffix */ | 2314 | /* Cut off the dot suffixes (e.g. .const, .isra)*/ |
2297 | ret = e_snprintf(buf, len, "%s", base); | 2315 | p = strchr(nbase, '.'); |
2316 | if (p && p != nbase) | ||
2317 | *p = '\0'; | ||
2318 | |||
2319 | /* Try no suffix number */ | ||
2320 | ret = e_snprintf(buf, len, "%s", nbase); | ||
2298 | if (ret < 0) { | 2321 | if (ret < 0) { |
2299 | pr_debug("snprintf() failed: %d\n", ret); | 2322 | pr_debug("snprintf() failed: %d\n", ret); |
2300 | return ret; | 2323 | goto out; |
2301 | } | 2324 | } |
2302 | /* Cut off the postfixes (e.g. .const, .isra)*/ | ||
2303 | p = strchr(buf, '.'); | ||
2304 | if (p && p != buf) | ||
2305 | *p = '\0'; | ||
2306 | if (!strlist__has_entry(namelist, buf)) | 2325 | if (!strlist__has_entry(namelist, buf)) |
2307 | return 0; | 2326 | goto out; |
2308 | 2327 | ||
2309 | if (!allow_suffix) { | 2328 | if (!allow_suffix) { |
2310 | pr_warning("Error: event \"%s\" already exists. " | 2329 | pr_warning("Error: event \"%s\" already exists. " |
2311 | "(Use -f to force duplicates.)\n", base); | 2330 | "(Use -f to force duplicates.)\n", buf); |
2312 | return -EEXIST; | 2331 | ret = -EEXIST; |
2332 | goto out; | ||
2313 | } | 2333 | } |
2314 | 2334 | ||
2315 | /* Try to add suffix */ | 2335 | /* Try to add suffix */ |
2316 | for (i = 1; i < MAX_EVENT_INDEX; i++) { | 2336 | for (i = 1; i < MAX_EVENT_INDEX; i++) { |
2317 | ret = e_snprintf(buf, len, "%s_%d", base, i); | 2337 | ret = e_snprintf(buf, len, "%s_%d", nbase, i); |
2318 | if (ret < 0) { | 2338 | if (ret < 0) { |
2319 | pr_debug("snprintf() failed: %d\n", ret); | 2339 | pr_debug("snprintf() failed: %d\n", ret); |
2320 | return ret; | 2340 | goto out; |
2321 | } | 2341 | } |
2322 | if (!strlist__has_entry(namelist, buf)) | 2342 | if (!strlist__has_entry(namelist, buf)) |
2323 | break; | 2343 | break; |
@@ -2327,6 +2347,8 @@ static int get_new_event_name(char *buf, size_t len, const char *base, | |||
2327 | ret = -ERANGE; | 2347 | ret = -ERANGE; |
2328 | } | 2348 | } |
2329 | 2349 | ||
2350 | out: | ||
2351 | free(nbase); | ||
2330 | return ret; | 2352 | return ret; |
2331 | } | 2353 | } |
2332 | 2354 | ||
@@ -2399,7 +2421,6 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
2399 | { | 2421 | { |
2400 | int i, fd, ret; | 2422 | int i, fd, ret; |
2401 | struct probe_trace_event *tev = NULL; | 2423 | struct probe_trace_event *tev = NULL; |
2402 | const char *event = NULL, *group = NULL; | ||
2403 | struct strlist *namelist; | 2424 | struct strlist *namelist; |
2404 | 2425 | ||
2405 | fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0)); | 2426 | fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0)); |
@@ -2415,7 +2436,6 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
2415 | } | 2436 | } |
2416 | 2437 | ||
2417 | ret = 0; | 2438 | ret = 0; |
2418 | pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); | ||
2419 | for (i = 0; i < ntevs; i++) { | 2439 | for (i = 0; i < ntevs; i++) { |
2420 | tev = &tevs[i]; | 2440 | tev = &tevs[i]; |
2421 | /* Skip if the symbol is out of .text or blacklisted */ | 2441 | /* Skip if the symbol is out of .text or blacklisted */ |
@@ -2432,13 +2452,6 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
2432 | if (ret < 0) | 2452 | if (ret < 0) |
2433 | break; | 2453 | break; |
2434 | 2454 | ||
2435 | /* We use tev's name for showing new events */ | ||
2436 | show_perf_probe_event(tev->group, tev->event, pev, | ||
2437 | tev->point.module, false); | ||
2438 | /* Save the last valid name */ | ||
2439 | event = tev->event; | ||
2440 | group = tev->group; | ||
2441 | |||
2442 | /* | 2455 | /* |
2443 | * Probes after the first probe which comes from same | 2456 | * Probes after the first probe which comes from same |
2444 | * user input are always allowed to add suffix, because | 2457 | * user input are always allowed to add suffix, because |
@@ -2450,13 +2463,6 @@ static int __add_probe_trace_events(struct perf_probe_event *pev, | |||
2450 | if (ret == -EINVAL && pev->uprobes) | 2463 | if (ret == -EINVAL && pev->uprobes) |
2451 | warn_uprobe_event_compat(tev); | 2464 | warn_uprobe_event_compat(tev); |
2452 | 2465 | ||
2453 | /* Note that it is possible to skip all events because of blacklist */ | ||
2454 | if (ret >= 0 && event) { | ||
2455 | /* Show how to use the event. */ | ||
2456 | pr_info("\nYou can now use it in all perf tools, such as:\n\n"); | ||
2457 | pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", group, event); | ||
2458 | } | ||
2459 | |||
2460 | strlist__delete(namelist); | 2466 | strlist__delete(namelist); |
2461 | close_out: | 2467 | close_out: |
2462 | close(fd); | 2468 | close(fd); |
@@ -2537,7 +2543,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
2537 | goto out; | 2543 | goto out; |
2538 | } | 2544 | } |
2539 | 2545 | ||
2540 | if (!pev->uprobes && !pp->retprobe) { | 2546 | /* Note that the symbols in the kmodule are not relocated */ |
2547 | if (!pev->uprobes && !pp->retprobe && !pev->target) { | ||
2541 | reloc_sym = kernel_get_ref_reloc_sym(); | 2548 | reloc_sym = kernel_get_ref_reloc_sym(); |
2542 | if (!reloc_sym) { | 2549 | if (!reloc_sym) { |
2543 | pr_warning("Relocated base symbol is not found!\n"); | 2550 | pr_warning("Relocated base symbol is not found!\n"); |
@@ -2574,8 +2581,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
2574 | } | 2581 | } |
2575 | /* Add one probe point */ | 2582 | /* Add one probe point */ |
2576 | tp->address = map->unmap_ip(map, sym->start) + pp->offset; | 2583 | tp->address = map->unmap_ip(map, sym->start) + pp->offset; |
2577 | /* If we found a wrong one, mark it by NULL symbol */ | 2584 | |
2578 | if (!pev->uprobes && | 2585 | /* Check the kprobe (not in module) is within .text */ |
2586 | if (!pev->uprobes && !pev->target && | ||
2579 | kprobe_warn_out_range(sym->name, tp->address)) { | 2587 | kprobe_warn_out_range(sym->name, tp->address)) { |
2580 | tp->symbol = NULL; /* Skip it */ | 2588 | tp->symbol = NULL; /* Skip it */ |
2581 | skipped++; | 2589 | skipped++; |
@@ -2759,63 +2767,71 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, | |||
2759 | return find_probe_trace_events_from_map(pev, tevs); | 2767 | return find_probe_trace_events_from_map(pev, tevs); |
2760 | } | 2768 | } |
2761 | 2769 | ||
2762 | struct __event_package { | 2770 | int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs) |
2763 | struct perf_probe_event *pev; | ||
2764 | struct probe_trace_event *tevs; | ||
2765 | int ntevs; | ||
2766 | }; | ||
2767 | |||
2768 | int add_perf_probe_events(struct perf_probe_event *pevs, int npevs) | ||
2769 | { | 2771 | { |
2770 | int i, j, ret; | 2772 | int i, ret; |
2771 | struct __event_package *pkgs; | ||
2772 | |||
2773 | ret = 0; | ||
2774 | pkgs = zalloc(sizeof(struct __event_package) * npevs); | ||
2775 | |||
2776 | if (pkgs == NULL) | ||
2777 | return -ENOMEM; | ||
2778 | |||
2779 | ret = init_symbol_maps(pevs->uprobes); | ||
2780 | if (ret < 0) { | ||
2781 | free(pkgs); | ||
2782 | return ret; | ||
2783 | } | ||
2784 | 2773 | ||
2785 | /* Loop 1: convert all events */ | 2774 | /* Loop 1: convert all events */ |
2786 | for (i = 0; i < npevs; i++) { | 2775 | for (i = 0; i < npevs; i++) { |
2787 | pkgs[i].pev = &pevs[i]; | ||
2788 | /* Init kprobe blacklist if needed */ | 2776 | /* Init kprobe blacklist if needed */ |
2789 | if (!pkgs[i].pev->uprobes) | 2777 | if (!pevs[i].uprobes) |
2790 | kprobe_blacklist__init(); | 2778 | kprobe_blacklist__init(); |
2791 | /* Convert with or without debuginfo */ | 2779 | /* Convert with or without debuginfo */ |
2792 | ret = convert_to_probe_trace_events(pkgs[i].pev, | 2780 | ret = convert_to_probe_trace_events(&pevs[i], &pevs[i].tevs); |
2793 | &pkgs[i].tevs); | ||
2794 | if (ret < 0) | 2781 | if (ret < 0) |
2795 | goto end; | 2782 | return ret; |
2796 | pkgs[i].ntevs = ret; | 2783 | pevs[i].ntevs = ret; |
2797 | } | 2784 | } |
2798 | /* This just release blacklist only if allocated */ | 2785 | /* This just release blacklist only if allocated */ |
2799 | kprobe_blacklist__release(); | 2786 | kprobe_blacklist__release(); |
2800 | 2787 | ||
2788 | return 0; | ||
2789 | } | ||
2790 | |||
2791 | int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs) | ||
2792 | { | ||
2793 | int i, ret = 0; | ||
2794 | |||
2801 | /* Loop 2: add all events */ | 2795 | /* Loop 2: add all events */ |
2802 | for (i = 0; i < npevs; i++) { | 2796 | for (i = 0; i < npevs; i++) { |
2803 | ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, | 2797 | ret = __add_probe_trace_events(&pevs[i], pevs[i].tevs, |
2804 | pkgs[i].ntevs, | 2798 | pevs[i].ntevs, |
2805 | probe_conf.force_add); | 2799 | probe_conf.force_add); |
2806 | if (ret < 0) | 2800 | if (ret < 0) |
2807 | break; | 2801 | break; |
2808 | } | 2802 | } |
2809 | end: | 2803 | return ret; |
2804 | } | ||
2805 | |||
2806 | void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs) | ||
2807 | { | ||
2808 | int i, j; | ||
2809 | |||
2810 | /* Loop 3: cleanup and free trace events */ | 2810 | /* Loop 3: cleanup and free trace events */ |
2811 | for (i = 0; i < npevs; i++) { | 2811 | for (i = 0; i < npevs; i++) { |
2812 | for (j = 0; j < pkgs[i].ntevs; j++) | 2812 | for (j = 0; j < pevs[i].ntevs; j++) |
2813 | clear_probe_trace_event(&pkgs[i].tevs[j]); | 2813 | clear_probe_trace_event(&pevs[i].tevs[j]); |
2814 | zfree(&pkgs[i].tevs); | 2814 | zfree(&pevs[i].tevs); |
2815 | pevs[i].ntevs = 0; | ||
2816 | clear_perf_probe_event(&pevs[i]); | ||
2815 | } | 2817 | } |
2816 | free(pkgs); | 2818 | } |
2817 | exit_symbol_maps(); | ||
2818 | 2819 | ||
2820 | int add_perf_probe_events(struct perf_probe_event *pevs, int npevs) | ||
2821 | { | ||
2822 | int ret; | ||
2823 | |||
2824 | ret = init_probe_symbol_maps(pevs->uprobes); | ||
2825 | if (ret < 0) | ||
2826 | return ret; | ||
2827 | |||
2828 | ret = convert_perf_probe_events(pevs, npevs); | ||
2829 | if (ret == 0) | ||
2830 | ret = apply_perf_probe_events(pevs, npevs); | ||
2831 | |||
2832 | cleanup_perf_probe_events(pevs, npevs); | ||
2833 | |||
2834 | exit_probe_symbol_maps(); | ||
2819 | return ret; | 2835 | return ret; |
2820 | } | 2836 | } |
2821 | 2837 | ||
@@ -2827,8 +2843,6 @@ int del_perf_probe_events(struct strfilter *filter) | |||
2827 | if (!str) | 2843 | if (!str) |
2828 | return -EINVAL; | 2844 | return -EINVAL; |
2829 | 2845 | ||
2830 | pr_debug("Delete filter: \'%s\'\n", str); | ||
2831 | |||
2832 | /* Get current event names */ | 2846 | /* Get current event names */ |
2833 | ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); | 2847 | ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); |
2834 | if (ret < 0) | 2848 | if (ret < 0) |
@@ -2843,9 +2857,6 @@ int del_perf_probe_events(struct strfilter *filter) | |||
2843 | ret = ret2; | 2857 | ret = ret2; |
2844 | goto error; | 2858 | goto error; |
2845 | } | 2859 | } |
2846 | if (ret == -ENOENT && ret2 == -ENOENT) | ||
2847 | pr_debug("\"%s\" does not hit any event.\n", str); | ||
2848 | /* Note that this is silently ignored */ | ||
2849 | ret = 0; | 2860 | ret = 0; |
2850 | 2861 | ||
2851 | error: | 2862 | error: |
@@ -2880,7 +2891,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter, | |||
2880 | struct map *map; | 2891 | struct map *map; |
2881 | int ret; | 2892 | int ret; |
2882 | 2893 | ||
2883 | ret = init_symbol_maps(user); | 2894 | ret = init_probe_symbol_maps(user); |
2884 | if (ret < 0) | 2895 | if (ret < 0) |
2885 | return ret; | 2896 | return ret; |
2886 | 2897 | ||
@@ -2910,7 +2921,7 @@ end: | |||
2910 | if (user) { | 2921 | if (user) { |
2911 | map__put(map); | 2922 | map__put(map); |
2912 | } | 2923 | } |
2913 | exit_symbol_maps(); | 2924 | exit_probe_symbol_maps(); |
2914 | 2925 | ||
2915 | return ret; | 2926 | return ret; |
2916 | } | 2927 | } |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 6e7ec68a4aa8..ba926c30f8cd 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -87,6 +87,8 @@ struct perf_probe_event { | |||
87 | bool uprobes; /* Uprobe event flag */ | 87 | bool uprobes; /* Uprobe event flag */ |
88 | char *target; /* Target binary */ | 88 | char *target; /* Target binary */ |
89 | struct perf_probe_arg *args; /* Arguments */ | 89 | struct perf_probe_arg *args; /* Arguments */ |
90 | struct probe_trace_event *tevs; | ||
91 | int ntevs; | ||
90 | }; | 92 | }; |
91 | 93 | ||
92 | /* Line range */ | 94 | /* Line range */ |
@@ -108,6 +110,8 @@ struct variable_list { | |||
108 | }; | 110 | }; |
109 | 111 | ||
110 | struct map; | 112 | struct map; |
113 | int init_probe_symbol_maps(bool user_only); | ||
114 | void exit_probe_symbol_maps(void); | ||
111 | 115 | ||
112 | /* Command string to events */ | 116 | /* Command string to events */ |
113 | extern int parse_perf_probe_command(const char *cmd, | 117 | extern int parse_perf_probe_command(const char *cmd, |
@@ -138,7 +142,14 @@ extern void line_range__clear(struct line_range *lr); | |||
138 | extern int line_range__init(struct line_range *lr); | 142 | extern int line_range__init(struct line_range *lr); |
139 | 143 | ||
140 | extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs); | 144 | extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs); |
145 | extern int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs); | ||
146 | extern int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs); | ||
147 | extern void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs); | ||
141 | extern int del_perf_probe_events(struct strfilter *filter); | 148 | extern int del_perf_probe_events(struct strfilter *filter); |
149 | |||
150 | extern int show_perf_probe_event(const char *group, const char *event, | ||
151 | struct perf_probe_event *pev, | ||
152 | const char *module, bool use_stdout); | ||
142 | extern int show_perf_probe_events(struct strfilter *filter); | 153 | extern int show_perf_probe_events(struct strfilter *filter); |
143 | extern int show_line_range(struct line_range *lr, const char *module, | 154 | extern int show_line_range(struct line_range *lr, const char *module, |
144 | bool user); | 155 | bool user); |
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c index bbb243717ec8..89dbeb92c68e 100644 --- a/tools/perf/util/probe-file.c +++ b/tools/perf/util/probe-file.c | |||
@@ -22,8 +22,7 @@ | |||
22 | #include "color.h" | 22 | #include "color.h" |
23 | #include "symbol.h" | 23 | #include "symbol.h" |
24 | #include "thread.h" | 24 | #include "thread.h" |
25 | #include <api/fs/debugfs.h> | 25 | #include <api/fs/tracing_path.h> |
26 | #include <api/fs/tracefs.h> | ||
27 | #include "probe-event.h" | 26 | #include "probe-event.h" |
28 | #include "probe-file.h" | 27 | #include "probe-file.h" |
29 | #include "session.h" | 28 | #include "session.h" |
@@ -73,21 +72,11 @@ static void print_both_open_warning(int kerr, int uerr) | |||
73 | static int open_probe_events(const char *trace_file, bool readwrite) | 72 | static int open_probe_events(const char *trace_file, bool readwrite) |
74 | { | 73 | { |
75 | char buf[PATH_MAX]; | 74 | char buf[PATH_MAX]; |
76 | const char *__debugfs; | ||
77 | const char *tracing_dir = ""; | 75 | const char *tracing_dir = ""; |
78 | int ret; | 76 | int ret; |
79 | 77 | ||
80 | __debugfs = tracefs_find_mountpoint(); | ||
81 | if (__debugfs == NULL) { | ||
82 | tracing_dir = "tracing/"; | ||
83 | |||
84 | __debugfs = debugfs_find_mountpoint(); | ||
85 | if (__debugfs == NULL) | ||
86 | return -ENOTSUP; | ||
87 | } | ||
88 | |||
89 | ret = e_snprintf(buf, PATH_MAX, "%s/%s%s", | 78 | ret = e_snprintf(buf, PATH_MAX, "%s/%s%s", |
90 | __debugfs, tracing_dir, trace_file); | 79 | tracing_path, tracing_dir, trace_file); |
91 | if (ret >= 0) { | 80 | if (ret >= 0) { |
92 | pr_debug("Opening %s write=%d\n", buf, readwrite); | 81 | pr_debug("Opening %s write=%d\n", buf, readwrite); |
93 | if (readwrite && !probe_event_dry_run) | 82 | if (readwrite && !probe_event_dry_run) |
@@ -267,7 +256,6 @@ static int __del_trace_probe_event(int fd, struct str_node *ent) | |||
267 | goto error; | 256 | goto error; |
268 | } | 257 | } |
269 | 258 | ||
270 | pr_info("Removed event: %s\n", ent->s); | ||
271 | return 0; | 259 | return 0; |
272 | error: | 260 | error: |
273 | pr_warning("Failed to delete event: %s\n", | 261 | pr_warning("Failed to delete event: %s\n", |
@@ -275,7 +263,8 @@ error: | |||
275 | return ret; | 263 | return ret; |
276 | } | 264 | } |
277 | 265 | ||
278 | int probe_file__del_events(int fd, struct strfilter *filter) | 266 | int probe_file__get_events(int fd, struct strfilter *filter, |
267 | struct strlist *plist) | ||
279 | { | 268 | { |
280 | struct strlist *namelist; | 269 | struct strlist *namelist; |
281 | struct str_node *ent; | 270 | struct str_node *ent; |
@@ -290,12 +279,43 @@ int probe_file__del_events(int fd, struct strfilter *filter) | |||
290 | p = strchr(ent->s, ':'); | 279 | p = strchr(ent->s, ':'); |
291 | if ((p && strfilter__compare(filter, p + 1)) || | 280 | if ((p && strfilter__compare(filter, p + 1)) || |
292 | strfilter__compare(filter, ent->s)) { | 281 | strfilter__compare(filter, ent->s)) { |
293 | ret = __del_trace_probe_event(fd, ent); | 282 | strlist__add(plist, ent->s); |
294 | if (ret < 0) | 283 | ret = 0; |
295 | break; | ||
296 | } | 284 | } |
297 | } | 285 | } |
298 | strlist__delete(namelist); | 286 | strlist__delete(namelist); |
299 | 287 | ||
300 | return ret; | 288 | return ret; |
301 | } | 289 | } |
290 | |||
291 | int probe_file__del_strlist(int fd, struct strlist *namelist) | ||
292 | { | ||
293 | int ret = 0; | ||
294 | struct str_node *ent; | ||
295 | |||
296 | strlist__for_each(ent, namelist) { | ||
297 | ret = __del_trace_probe_event(fd, ent); | ||
298 | if (ret < 0) | ||
299 | break; | ||
300 | } | ||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | int probe_file__del_events(int fd, struct strfilter *filter) | ||
305 | { | ||
306 | struct strlist *namelist; | ||
307 | int ret; | ||
308 | |||
309 | namelist = strlist__new(NULL, NULL); | ||
310 | if (!namelist) | ||
311 | return -ENOMEM; | ||
312 | |||
313 | ret = probe_file__get_events(fd, filter, namelist); | ||
314 | if (ret < 0) | ||
315 | return ret; | ||
316 | |||
317 | ret = probe_file__del_strlist(fd, namelist); | ||
318 | strlist__delete(namelist); | ||
319 | |||
320 | return ret; | ||
321 | } | ||
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h index ada94a242a17..18ac9cf51c34 100644 --- a/tools/perf/util/probe-file.h +++ b/tools/perf/util/probe-file.h | |||
@@ -14,5 +14,9 @@ struct strlist *probe_file__get_namelist(int fd); | |||
14 | struct strlist *probe_file__get_rawlist(int fd); | 14 | struct strlist *probe_file__get_rawlist(int fd); |
15 | int probe_file__add_event(int fd, struct probe_trace_event *tev); | 15 | int probe_file__add_event(int fd, struct probe_trace_event *tev); |
16 | int probe_file__del_events(int fd, struct strfilter *filter); | 16 | int probe_file__del_events(int fd, struct strfilter *filter); |
17 | int probe_file__get_events(int fd, struct strfilter *filter, | ||
18 | struct strlist *plist); | ||
19 | int probe_file__del_strlist(int fd, struct strlist *namelist); | ||
20 | |||
17 | 21 | ||
18 | #endif | 22 | #endif |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 29c43c0680a8..bd8f03de5e40 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -70,6 +70,7 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, | |||
70 | if (!dbg->dwfl) | 70 | if (!dbg->dwfl) |
71 | goto error; | 71 | goto error; |
72 | 72 | ||
73 | dwfl_report_begin(dbg->dwfl); | ||
73 | dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); | 74 | dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); |
74 | if (!dbg->mod) | 75 | if (!dbg->mod) |
75 | goto error; | 76 | goto error; |
@@ -78,6 +79,8 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, | |||
78 | if (!dbg->dbg) | 79 | if (!dbg->dbg) |
79 | goto error; | 80 | goto error; |
80 | 81 | ||
82 | dwfl_report_end(dbg->dwfl, NULL, NULL); | ||
83 | |||
81 | return 0; | 84 | return 0; |
82 | error: | 85 | error: |
83 | if (dbg->dwfl) | 86 | if (dbg->dwfl) |
@@ -591,6 +594,7 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
591 | /* Convert subprogram DIE to trace point */ | 594 | /* Convert subprogram DIE to trace point */ |
592 | static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, | 595 | static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, |
593 | Dwarf_Addr paddr, bool retprobe, | 596 | Dwarf_Addr paddr, bool retprobe, |
597 | const char *function, | ||
594 | struct probe_trace_point *tp) | 598 | struct probe_trace_point *tp) |
595 | { | 599 | { |
596 | Dwarf_Addr eaddr, highaddr; | 600 | Dwarf_Addr eaddr, highaddr; |
@@ -634,8 +638,10 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, | |||
634 | /* Return probe must be on the head of a subprogram */ | 638 | /* Return probe must be on the head of a subprogram */ |
635 | if (retprobe) { | 639 | if (retprobe) { |
636 | if (eaddr != paddr) { | 640 | if (eaddr != paddr) { |
637 | pr_warning("Return probe must be on the head of" | 641 | pr_warning("Failed to find \"%s%%return\",\n" |
638 | " a real function.\n"); | 642 | " because %s is an inlined function and" |
643 | " has no return point.\n", function, | ||
644 | function); | ||
639 | return -EINVAL; | 645 | return -EINVAL; |
640 | } | 646 | } |
641 | tp->retprobe = true; | 647 | tp->retprobe = true; |
@@ -1175,6 +1181,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1175 | { | 1181 | { |
1176 | struct trace_event_finder *tf = | 1182 | struct trace_event_finder *tf = |
1177 | container_of(pf, struct trace_event_finder, pf); | 1183 | container_of(pf, struct trace_event_finder, pf); |
1184 | struct perf_probe_point *pp = &pf->pev->point; | ||
1178 | struct probe_trace_event *tev; | 1185 | struct probe_trace_event *tev; |
1179 | struct perf_probe_arg *args; | 1186 | struct perf_probe_arg *args; |
1180 | int ret, i; | 1187 | int ret, i; |
@@ -1189,7 +1196,7 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1189 | 1196 | ||
1190 | /* Trace point should be converted from subprogram DIE */ | 1197 | /* Trace point should be converted from subprogram DIE */ |
1191 | ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, | 1198 | ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, |
1192 | pf->pev->point.retprobe, &tev->point); | 1199 | pp->retprobe, pp->function, &tev->point); |
1193 | if (ret < 0) | 1200 | if (ret < 0) |
1194 | return ret; | 1201 | return ret; |
1195 | 1202 | ||
@@ -1319,6 +1326,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1319 | { | 1326 | { |
1320 | struct available_var_finder *af = | 1327 | struct available_var_finder *af = |
1321 | container_of(pf, struct available_var_finder, pf); | 1328 | container_of(pf, struct available_var_finder, pf); |
1329 | struct perf_probe_point *pp = &pf->pev->point; | ||
1322 | struct variable_list *vl; | 1330 | struct variable_list *vl; |
1323 | Dwarf_Die die_mem; | 1331 | Dwarf_Die die_mem; |
1324 | int ret; | 1332 | int ret; |
@@ -1332,7 +1340,7 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
1332 | 1340 | ||
1333 | /* Trace point should be converted from subprogram DIE */ | 1341 | /* Trace point should be converted from subprogram DIE */ |
1334 | ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr, | 1342 | ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr, |
1335 | pf->pev->point.retprobe, &vl->point); | 1343 | pp->retprobe, pp->function, &vl->point); |
1336 | if (ret < 0) | 1344 | if (ret < 0) |
1337 | return ret; | 1345 | return ret; |
1338 | 1346 | ||
@@ -1399,6 +1407,41 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, | |||
1399 | return (ret < 0) ? ret : af.nvls; | 1407 | return (ret < 0) ? ret : af.nvls; |
1400 | } | 1408 | } |
1401 | 1409 | ||
1410 | /* For the kernel module, we need a special code to get a DIE */ | ||
1411 | static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs) | ||
1412 | { | ||
1413 | int n, i; | ||
1414 | Elf32_Word shndx; | ||
1415 | Elf_Scn *scn; | ||
1416 | Elf *elf; | ||
1417 | GElf_Shdr mem, *shdr; | ||
1418 | const char *p; | ||
1419 | |||
1420 | elf = dwfl_module_getelf(dbg->mod, &dbg->bias); | ||
1421 | if (!elf) | ||
1422 | return -EINVAL; | ||
1423 | |||
1424 | /* Get the number of relocations */ | ||
1425 | n = dwfl_module_relocations(dbg->mod); | ||
1426 | if (n < 0) | ||
1427 | return -ENOENT; | ||
1428 | /* Search the relocation related .text section */ | ||
1429 | for (i = 0; i < n; i++) { | ||
1430 | p = dwfl_module_relocation_info(dbg->mod, i, &shndx); | ||
1431 | if (strcmp(p, ".text") == 0) { | ||
1432 | /* OK, get the section header */ | ||
1433 | scn = elf_getscn(elf, shndx); | ||
1434 | if (!scn) | ||
1435 | return -ENOENT; | ||
1436 | shdr = gelf_getshdr(scn, &mem); | ||
1437 | if (!shdr) | ||
1438 | return -ENOENT; | ||
1439 | *offs = shdr->sh_addr; | ||
1440 | } | ||
1441 | } | ||
1442 | return 0; | ||
1443 | } | ||
1444 | |||
1402 | /* Reverse search */ | 1445 | /* Reverse search */ |
1403 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, | 1446 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, |
1404 | struct perf_probe_point *ppt) | 1447 | struct perf_probe_point *ppt) |
@@ -1407,9 +1450,16 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, | |||
1407 | Dwarf_Addr _addr = 0, baseaddr = 0; | 1450 | Dwarf_Addr _addr = 0, baseaddr = 0; |
1408 | const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; | 1451 | const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; |
1409 | int baseline = 0, lineno = 0, ret = 0; | 1452 | int baseline = 0, lineno = 0, ret = 0; |
1453 | bool reloc = false; | ||
1410 | 1454 | ||
1455 | retry: | ||
1411 | /* Find cu die */ | 1456 | /* Find cu die */ |
1412 | if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { | 1457 | if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { |
1458 | if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) { | ||
1459 | addr += baseaddr; | ||
1460 | reloc = true; | ||
1461 | goto retry; | ||
1462 | } | ||
1413 | pr_warning("Failed to find debug information for address %lx\n", | 1463 | pr_warning("Failed to find debug information for address %lx\n", |
1414 | addr); | 1464 | addr); |
1415 | ret = -EINVAL; | 1465 | ret = -EINVAL; |
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 6324fe6b161e..98f127abfa42 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
@@ -67,6 +67,7 @@ static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object."); | |||
67 | static PyMemberDef pyrf_mmap_event__members[] = { | 67 | static PyMemberDef pyrf_mmap_event__members[] = { |
68 | sample_members | 68 | sample_members |
69 | member_def(perf_event_header, type, T_UINT, "event type"), | 69 | member_def(perf_event_header, type, T_UINT, "event type"), |
70 | member_def(perf_event_header, misc, T_UINT, "event misc"), | ||
70 | member_def(mmap_event, pid, T_UINT, "event pid"), | 71 | member_def(mmap_event, pid, T_UINT, "event pid"), |
71 | member_def(mmap_event, tid, T_UINT, "event tid"), | 72 | member_def(mmap_event, tid, T_UINT, "event tid"), |
72 | member_def(mmap_event, start, T_ULONGLONG, "start of the map"), | 73 | member_def(mmap_event, start, T_ULONGLONG, "start of the map"), |
@@ -297,6 +298,43 @@ static PyTypeObject pyrf_sample_event__type = { | |||
297 | .tp_repr = (reprfunc)pyrf_sample_event__repr, | 298 | .tp_repr = (reprfunc)pyrf_sample_event__repr, |
298 | }; | 299 | }; |
299 | 300 | ||
301 | static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); | ||
302 | |||
303 | static PyMemberDef pyrf_context_switch_event__members[] = { | ||
304 | sample_members | ||
305 | member_def(perf_event_header, type, T_UINT, "event type"), | ||
306 | member_def(context_switch_event, next_prev_pid, T_UINT, "next/prev pid"), | ||
307 | member_def(context_switch_event, next_prev_tid, T_UINT, "next/prev tid"), | ||
308 | { .name = NULL, }, | ||
309 | }; | ||
310 | |||
311 | static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent) | ||
312 | { | ||
313 | PyObject *ret; | ||
314 | char *s; | ||
315 | |||
316 | if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }", | ||
317 | pevent->event.context_switch.next_prev_pid, | ||
318 | pevent->event.context_switch.next_prev_tid, | ||
319 | !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { | ||
320 | ret = PyErr_NoMemory(); | ||
321 | } else { | ||
322 | ret = PyString_FromString(s); | ||
323 | free(s); | ||
324 | } | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | static PyTypeObject pyrf_context_switch_event__type = { | ||
329 | PyVarObject_HEAD_INIT(NULL, 0) | ||
330 | .tp_name = "perf.context_switch_event", | ||
331 | .tp_basicsize = sizeof(struct pyrf_event), | ||
332 | .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, | ||
333 | .tp_doc = pyrf_context_switch_event__doc, | ||
334 | .tp_members = pyrf_context_switch_event__members, | ||
335 | .tp_repr = (reprfunc)pyrf_context_switch_event__repr, | ||
336 | }; | ||
337 | |||
300 | static int pyrf_event__setup_types(void) | 338 | static int pyrf_event__setup_types(void) |
301 | { | 339 | { |
302 | int err; | 340 | int err; |
@@ -306,6 +344,7 @@ static int pyrf_event__setup_types(void) | |||
306 | pyrf_lost_event__type.tp_new = | 344 | pyrf_lost_event__type.tp_new = |
307 | pyrf_read_event__type.tp_new = | 345 | pyrf_read_event__type.tp_new = |
308 | pyrf_sample_event__type.tp_new = | 346 | pyrf_sample_event__type.tp_new = |
347 | pyrf_context_switch_event__type.tp_new = | ||
309 | pyrf_throttle_event__type.tp_new = PyType_GenericNew; | 348 | pyrf_throttle_event__type.tp_new = PyType_GenericNew; |
310 | err = PyType_Ready(&pyrf_mmap_event__type); | 349 | err = PyType_Ready(&pyrf_mmap_event__type); |
311 | if (err < 0) | 350 | if (err < 0) |
@@ -328,6 +367,9 @@ static int pyrf_event__setup_types(void) | |||
328 | err = PyType_Ready(&pyrf_sample_event__type); | 367 | err = PyType_Ready(&pyrf_sample_event__type); |
329 | if (err < 0) | 368 | if (err < 0) |
330 | goto out; | 369 | goto out; |
370 | err = PyType_Ready(&pyrf_context_switch_event__type); | ||
371 | if (err < 0) | ||
372 | goto out; | ||
331 | out: | 373 | out: |
332 | return err; | 374 | return err; |
333 | } | 375 | } |
@@ -342,6 +384,8 @@ static PyTypeObject *pyrf_event__type[] = { | |||
342 | [PERF_RECORD_FORK] = &pyrf_task_event__type, | 384 | [PERF_RECORD_FORK] = &pyrf_task_event__type, |
343 | [PERF_RECORD_READ] = &pyrf_read_event__type, | 385 | [PERF_RECORD_READ] = &pyrf_read_event__type, |
344 | [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type, | 386 | [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type, |
387 | [PERF_RECORD_SWITCH] = &pyrf_context_switch_event__type, | ||
388 | [PERF_RECORD_SWITCH_CPU_WIDE] = &pyrf_context_switch_event__type, | ||
345 | }; | 389 | }; |
346 | 390 | ||
347 | static PyObject *pyrf_event__new(union perf_event *event) | 391 | static PyObject *pyrf_event__new(union perf_event *event) |
@@ -349,8 +393,10 @@ static PyObject *pyrf_event__new(union perf_event *event) | |||
349 | struct pyrf_event *pevent; | 393 | struct pyrf_event *pevent; |
350 | PyTypeObject *ptype; | 394 | PyTypeObject *ptype; |
351 | 395 | ||
352 | if (event->header.type < PERF_RECORD_MMAP || | 396 | if ((event->header.type < PERF_RECORD_MMAP || |
353 | event->header.type > PERF_RECORD_SAMPLE) | 397 | event->header.type > PERF_RECORD_SAMPLE) && |
398 | !(event->header.type == PERF_RECORD_SWITCH || | ||
399 | event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)) | ||
354 | return NULL; | 400 | return NULL; |
355 | 401 | ||
356 | ptype = pyrf_event__type[event->header.type]; | 402 | ptype = pyrf_event__type[event->header.type]; |
@@ -528,6 +574,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, | |||
528 | "exclude_hv", | 574 | "exclude_hv", |
529 | "exclude_idle", | 575 | "exclude_idle", |
530 | "mmap", | 576 | "mmap", |
577 | "context_switch", | ||
531 | "comm", | 578 | "comm", |
532 | "freq", | 579 | "freq", |
533 | "inherit_stat", | 580 | "inherit_stat", |
@@ -553,6 +600,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, | |||
553 | exclude_hv = 0, | 600 | exclude_hv = 0, |
554 | exclude_idle = 0, | 601 | exclude_idle = 0, |
555 | mmap = 0, | 602 | mmap = 0, |
603 | context_switch = 0, | ||
556 | comm = 0, | 604 | comm = 0, |
557 | freq = 1, | 605 | freq = 1, |
558 | inherit_stat = 0, | 606 | inherit_stat = 0, |
@@ -565,13 +613,13 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, | |||
565 | int idx = 0; | 613 | int idx = 0; |
566 | 614 | ||
567 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, | 615 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, |
568 | "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist, | 616 | "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKK", kwlist, |
569 | &attr.type, &attr.config, &attr.sample_freq, | 617 | &attr.type, &attr.config, &attr.sample_freq, |
570 | &sample_period, &attr.sample_type, | 618 | &sample_period, &attr.sample_type, |
571 | &attr.read_format, &disabled, &inherit, | 619 | &attr.read_format, &disabled, &inherit, |
572 | &pinned, &exclusive, &exclude_user, | 620 | &pinned, &exclusive, &exclude_user, |
573 | &exclude_kernel, &exclude_hv, &exclude_idle, | 621 | &exclude_kernel, &exclude_hv, &exclude_idle, |
574 | &mmap, &comm, &freq, &inherit_stat, | 622 | &mmap, &context_switch, &comm, &freq, &inherit_stat, |
575 | &enable_on_exec, &task, &watermark, | 623 | &enable_on_exec, &task, &watermark, |
576 | &precise_ip, &mmap_data, &sample_id_all, | 624 | &precise_ip, &mmap_data, &sample_id_all, |
577 | &attr.wakeup_events, &attr.bp_type, | 625 | &attr.wakeup_events, &attr.bp_type, |
@@ -595,6 +643,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, | |||
595 | attr.exclude_hv = exclude_hv; | 643 | attr.exclude_hv = exclude_hv; |
596 | attr.exclude_idle = exclude_idle; | 644 | attr.exclude_idle = exclude_idle; |
597 | attr.mmap = mmap; | 645 | attr.mmap = mmap; |
646 | attr.context_switch = context_switch; | ||
598 | attr.comm = comm; | 647 | attr.comm = comm; |
599 | attr.freq = freq; | 648 | attr.freq = freq; |
600 | attr.inherit_stat = inherit_stat; | 649 | attr.inherit_stat = inherit_stat; |
@@ -1019,6 +1068,8 @@ static struct { | |||
1019 | PERF_CONST(RECORD_LOST_SAMPLES), | 1068 | PERF_CONST(RECORD_LOST_SAMPLES), |
1020 | PERF_CONST(RECORD_SWITCH), | 1069 | PERF_CONST(RECORD_SWITCH), |
1021 | PERF_CONST(RECORD_SWITCH_CPU_WIDE), | 1070 | PERF_CONST(RECORD_SWITCH_CPU_WIDE), |
1071 | |||
1072 | PERF_CONST(RECORD_MISC_SWITCH_OUT), | ||
1022 | { .name = NULL, }, | 1073 | { .name = NULL, }, |
1023 | }; | 1074 | }; |
1024 | 1075 | ||
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 1bd593bbf7a5..544509c159ce 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
@@ -221,6 +221,7 @@ static void define_event_symbols(struct event_format *event, | |||
221 | break; | 221 | break; |
222 | case PRINT_BSTRING: | 222 | case PRINT_BSTRING: |
223 | case PRINT_DYNAMIC_ARRAY: | 223 | case PRINT_DYNAMIC_ARRAY: |
224 | case PRINT_DYNAMIC_ARRAY_LEN: | ||
224 | case PRINT_STRING: | 225 | case PRINT_STRING: |
225 | case PRINT_BITMASK: | 226 | case PRINT_BITMASK: |
226 | break; | 227 | break; |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index ace2484985cb..a8e825fca42a 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -251,6 +251,7 @@ static void define_event_symbols(struct event_format *event, | |||
251 | /* gcc warns for these? */ | 251 | /* gcc warns for these? */ |
252 | case PRINT_BSTRING: | 252 | case PRINT_BSTRING: |
253 | case PRINT_DYNAMIC_ARRAY: | 253 | case PRINT_DYNAMIC_ARRAY: |
254 | case PRINT_DYNAMIC_ARRAY_LEN: | ||
254 | case PRINT_FUNC: | 255 | case PRINT_FUNC: |
255 | case PRINT_BITMASK: | 256 | case PRINT_BITMASK: |
256 | /* we should warn... */ | 257 | /* we should warn... */ |
@@ -318,7 +319,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, | |||
318 | 319 | ||
319 | if (thread__resolve_callchain(al->thread, evsel, | 320 | if (thread__resolve_callchain(al->thread, evsel, |
320 | sample, NULL, NULL, | 321 | sample, NULL, NULL, |
321 | PERF_MAX_STACK_DEPTH) != 0) { | 322 | scripting_max_stack) != 0) { |
322 | pr_err("Failed to resolve callchain. Skipping\n"); | 323 | pr_err("Failed to resolve callchain. Skipping\n"); |
323 | goto exit; | 324 | goto exit; |
324 | } | 325 | } |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 8a4537ee9bc3..428149bc64d2 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -138,6 +138,8 @@ struct perf_session *perf_session__new(struct perf_data_file *file, | |||
138 | perf_session__set_id_hdr_size(session); | 138 | perf_session__set_id_hdr_size(session); |
139 | perf_session__set_comm_exec(session); | 139 | perf_session__set_comm_exec(session); |
140 | } | 140 | } |
141 | } else { | ||
142 | session->machines.host.env = &perf_env; | ||
141 | } | 143 | } |
142 | 144 | ||
143 | if (!file || perf_data_file__is_write(file)) { | 145 | if (!file || perf_data_file__is_write(file)) { |
@@ -170,30 +172,13 @@ static void perf_session__delete_threads(struct perf_session *session) | |||
170 | machine__delete_threads(&session->machines.host); | 172 | machine__delete_threads(&session->machines.host); |
171 | } | 173 | } |
172 | 174 | ||
173 | static void perf_session_env__exit(struct perf_env *env) | ||
174 | { | ||
175 | zfree(&env->hostname); | ||
176 | zfree(&env->os_release); | ||
177 | zfree(&env->version); | ||
178 | zfree(&env->arch); | ||
179 | zfree(&env->cpu_desc); | ||
180 | zfree(&env->cpuid); | ||
181 | |||
182 | zfree(&env->cmdline); | ||
183 | zfree(&env->cmdline_argv); | ||
184 | zfree(&env->sibling_cores); | ||
185 | zfree(&env->sibling_threads); | ||
186 | zfree(&env->numa_nodes); | ||
187 | zfree(&env->pmu_mappings); | ||
188 | } | ||
189 | |||
190 | void perf_session__delete(struct perf_session *session) | 175 | void perf_session__delete(struct perf_session *session) |
191 | { | 176 | { |
192 | auxtrace__free(session); | 177 | auxtrace__free(session); |
193 | auxtrace_index__free(&session->auxtrace_index); | 178 | auxtrace_index__free(&session->auxtrace_index); |
194 | perf_session__destroy_kernel_maps(session); | 179 | perf_session__destroy_kernel_maps(session); |
195 | perf_session__delete_threads(session); | 180 | perf_session__delete_threads(session); |
196 | perf_session_env__exit(&session->header.env); | 181 | perf_env__exit(&session->header.env); |
197 | machines__exit(&session->machines); | 182 | machines__exit(&session->machines); |
198 | if (session->file) | 183 | if (session->file) |
199 | perf_data_file__close(session->file); | 184 | perf_data_file__close(session->file); |
@@ -1079,11 +1064,11 @@ static int machines__deliver_event(struct machines *machines, | |||
1079 | 1064 | ||
1080 | switch (event->header.type) { | 1065 | switch (event->header.type) { |
1081 | case PERF_RECORD_SAMPLE: | 1066 | case PERF_RECORD_SAMPLE: |
1082 | dump_sample(evsel, event, sample); | ||
1083 | if (evsel == NULL) { | 1067 | if (evsel == NULL) { |
1084 | ++evlist->stats.nr_unknown_id; | 1068 | ++evlist->stats.nr_unknown_id; |
1085 | return 0; | 1069 | return 0; |
1086 | } | 1070 | } |
1071 | dump_sample(evsel, event, sample); | ||
1087 | if (machine == NULL) { | 1072 | if (machine == NULL) { |
1088 | ++evlist->stats.nr_unprocessable_samples; | 1073 | ++evlist->stats.nr_unprocessable_samples; |
1089 | return 0; | 1074 | return 0; |
@@ -1116,6 +1101,9 @@ static int machines__deliver_event(struct machines *machines, | |||
1116 | case PERF_RECORD_UNTHROTTLE: | 1101 | case PERF_RECORD_UNTHROTTLE: |
1117 | return tool->unthrottle(tool, event, sample, machine); | 1102 | return tool->unthrottle(tool, event, sample, machine); |
1118 | case PERF_RECORD_AUX: | 1103 | case PERF_RECORD_AUX: |
1104 | if (tool->aux == perf_event__process_aux && | ||
1105 | (event->aux.flags & PERF_AUX_FLAG_TRUNCATED)) | ||
1106 | evlist->stats.total_aux_lost += 1; | ||
1119 | return tool->aux(tool, event, sample, machine); | 1107 | return tool->aux(tool, event, sample, machine); |
1120 | case PERF_RECORD_ITRACE_START: | 1108 | case PERF_RECORD_ITRACE_START: |
1121 | return tool->itrace_start(tool, event, sample, machine); | 1109 | return tool->itrace_start(tool, event, sample, machine); |
@@ -1323,7 +1311,7 @@ struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) | |||
1323 | return machine__findnew_thread(&session->machines.host, -1, pid); | 1311 | return machine__findnew_thread(&session->machines.host, -1, pid); |
1324 | } | 1312 | } |
1325 | 1313 | ||
1326 | static struct thread *perf_session__register_idle_thread(struct perf_session *session) | 1314 | struct thread *perf_session__register_idle_thread(struct perf_session *session) |
1327 | { | 1315 | { |
1328 | struct thread *thread; | 1316 | struct thread *thread; |
1329 | 1317 | ||
@@ -1361,6 +1349,13 @@ static void perf_session__warn_about_errors(const struct perf_session *session) | |||
1361 | } | 1349 | } |
1362 | } | 1350 | } |
1363 | 1351 | ||
1352 | if (session->tool->aux == perf_event__process_aux && | ||
1353 | stats->total_aux_lost != 0) { | ||
1354 | ui__warning("AUX data lost %" PRIu64 " times out of %u!\n\n", | ||
1355 | stats->total_aux_lost, | ||
1356 | stats->nr_events[PERF_RECORD_AUX]); | ||
1357 | } | ||
1358 | |||
1364 | if (stats->nr_unknown_events != 0) { | 1359 | if (stats->nr_unknown_events != 0) { |
1365 | ui__warning("Found %u unknown events!\n\n" | 1360 | ui__warning("Found %u unknown events!\n\n" |
1366 | "Is this an older tool processing a perf.data " | 1361 | "Is this an older tool processing a perf.data " |
@@ -1580,7 +1575,10 @@ static int __perf_session__process_events(struct perf_session *session, | |||
1580 | file_offset = page_offset; | 1575 | file_offset = page_offset; |
1581 | head = data_offset - page_offset; | 1576 | head = data_offset - page_offset; |
1582 | 1577 | ||
1583 | if (data_size && (data_offset + data_size < file_size)) | 1578 | if (data_size == 0) |
1579 | goto out; | ||
1580 | |||
1581 | if (data_offset + data_size < file_size) | ||
1584 | file_size = data_offset + data_size; | 1582 | file_size = data_offset + data_size; |
1585 | 1583 | ||
1586 | ui_progress__init(&prog, file_size, "Processing events..."); | 1584 | ui_progress__init(&prog, file_size, "Processing events..."); |
@@ -1802,7 +1800,7 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample, | |||
1802 | 1800 | ||
1803 | if (thread__resolve_callchain(al->thread, evsel, | 1801 | if (thread__resolve_callchain(al->thread, evsel, |
1804 | sample, NULL, NULL, | 1802 | sample, NULL, NULL, |
1805 | PERF_MAX_STACK_DEPTH) != 0) { | 1803 | stack_depth) != 0) { |
1806 | if (verbose) | 1804 | if (verbose) |
1807 | error("Failed to resolve callchain. Skipping\n"); | 1805 | error("Failed to resolve callchain. Skipping\n"); |
1808 | return; | 1806 | return; |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index b44afc75d1cc..3e900c0efc73 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -89,6 +89,8 @@ struct machine *perf_session__findnew_machine(struct perf_session *session, pid_ | |||
89 | } | 89 | } |
90 | 90 | ||
91 | struct thread *perf_session__findnew(struct perf_session *session, pid_t pid); | 91 | struct thread *perf_session__findnew(struct perf_session *session, pid_t pid); |
92 | struct thread *perf_session__register_idle_thread(struct perf_session *session); | ||
93 | |||
92 | size_t perf_session__fprintf(struct perf_session *session, FILE *fp); | 94 | size_t perf_session__fprintf(struct perf_session *session, FILE *fp); |
93 | 95 | ||
94 | size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp); | 96 | size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp); |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 7e3871606df3..2d8ccd4d9e1b 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -21,6 +21,7 @@ int sort__need_collapse = 0; | |||
21 | int sort__has_parent = 0; | 21 | int sort__has_parent = 0; |
22 | int sort__has_sym = 0; | 22 | int sort__has_sym = 0; |
23 | int sort__has_dso = 0; | 23 | int sort__has_dso = 0; |
24 | int sort__has_socket = 0; | ||
24 | enum sort_mode sort__mode = SORT_MODE__NORMAL; | 25 | enum sort_mode sort__mode = SORT_MODE__NORMAL; |
25 | 26 | ||
26 | 27 | ||
@@ -328,8 +329,8 @@ static char *get_srcfile(struct hist_entry *e) | |||
328 | char *sf, *p; | 329 | char *sf, *p; |
329 | struct map *map = e->ms.map; | 330 | struct map *map = e->ms.map; |
330 | 331 | ||
331 | sf = get_srcline(map->dso, map__rip_2objdump(map, e->ip), | 332 | sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip), |
332 | e->ms.sym, true); | 333 | e->ms.sym, false, true); |
333 | if (!strcmp(sf, SRCLINE_UNKNOWN)) | 334 | if (!strcmp(sf, SRCLINE_UNKNOWN)) |
334 | return no_srcfile; | 335 | return no_srcfile; |
335 | p = strchr(sf, ':'); | 336 | p = strchr(sf, ':'); |
@@ -421,6 +422,27 @@ struct sort_entry sort_cpu = { | |||
421 | .se_width_idx = HISTC_CPU, | 422 | .se_width_idx = HISTC_CPU, |
422 | }; | 423 | }; |
423 | 424 | ||
425 | /* --sort socket */ | ||
426 | |||
427 | static int64_t | ||
428 | sort__socket_cmp(struct hist_entry *left, struct hist_entry *right) | ||
429 | { | ||
430 | return right->socket - left->socket; | ||
431 | } | ||
432 | |||
433 | static int hist_entry__socket_snprintf(struct hist_entry *he, char *bf, | ||
434 | size_t size, unsigned int width) | ||
435 | { | ||
436 | return repsep_snprintf(bf, size, "%*.*d", width, width-3, he->socket); | ||
437 | } | ||
438 | |||
439 | struct sort_entry sort_socket = { | ||
440 | .se_header = "Socket", | ||
441 | .se_cmp = sort__socket_cmp, | ||
442 | .se_snprintf = hist_entry__socket_snprintf, | ||
443 | .se_width_idx = HISTC_SOCKET, | ||
444 | }; | ||
445 | |||
424 | /* sort keys for branch stacks */ | 446 | /* sort keys for branch stacks */ |
425 | 447 | ||
426 | static int64_t | 448 | static int64_t |
@@ -633,6 +655,35 @@ static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf, | |||
633 | } | 655 | } |
634 | 656 | ||
635 | static int64_t | 657 | static int64_t |
658 | sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right) | ||
659 | { | ||
660 | uint64_t l = 0, r = 0; | ||
661 | |||
662 | if (left->mem_info) | ||
663 | l = left->mem_info->iaddr.addr; | ||
664 | if (right->mem_info) | ||
665 | r = right->mem_info->iaddr.addr; | ||
666 | |||
667 | return (int64_t)(r - l); | ||
668 | } | ||
669 | |||
670 | static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf, | ||
671 | size_t size, unsigned int width) | ||
672 | { | ||
673 | uint64_t addr = 0; | ||
674 | struct map *map = NULL; | ||
675 | struct symbol *sym = NULL; | ||
676 | |||
677 | if (he->mem_info) { | ||
678 | addr = he->mem_info->iaddr.addr; | ||
679 | map = he->mem_info->iaddr.map; | ||
680 | sym = he->mem_info->iaddr.sym; | ||
681 | } | ||
682 | return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size, | ||
683 | width); | ||
684 | } | ||
685 | |||
686 | static int64_t | ||
636 | sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) | 687 | sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right) |
637 | { | 688 | { |
638 | struct map *map_l = NULL; | 689 | struct map *map_l = NULL; |
@@ -1055,6 +1106,13 @@ struct sort_entry sort_mem_daddr_sym = { | |||
1055 | .se_width_idx = HISTC_MEM_DADDR_SYMBOL, | 1106 | .se_width_idx = HISTC_MEM_DADDR_SYMBOL, |
1056 | }; | 1107 | }; |
1057 | 1108 | ||
1109 | struct sort_entry sort_mem_iaddr_sym = { | ||
1110 | .se_header = "Code Symbol", | ||
1111 | .se_cmp = sort__iaddr_cmp, | ||
1112 | .se_snprintf = hist_entry__iaddr_snprintf, | ||
1113 | .se_width_idx = HISTC_MEM_IADDR_SYMBOL, | ||
1114 | }; | ||
1115 | |||
1058 | struct sort_entry sort_mem_daddr_dso = { | 1116 | struct sort_entry sort_mem_daddr_dso = { |
1059 | .se_header = "Data Object", | 1117 | .se_header = "Data Object", |
1060 | .se_cmp = sort__dso_daddr_cmp, | 1118 | .se_cmp = sort__dso_daddr_cmp, |
@@ -1248,6 +1306,7 @@ static struct sort_dimension common_sort_dimensions[] = { | |||
1248 | DIM(SORT_SYM, "symbol", sort_sym), | 1306 | DIM(SORT_SYM, "symbol", sort_sym), |
1249 | DIM(SORT_PARENT, "parent", sort_parent), | 1307 | DIM(SORT_PARENT, "parent", sort_parent), |
1250 | DIM(SORT_CPU, "cpu", sort_cpu), | 1308 | DIM(SORT_CPU, "cpu", sort_cpu), |
1309 | DIM(SORT_SOCKET, "socket", sort_socket), | ||
1251 | DIM(SORT_SRCLINE, "srcline", sort_srcline), | 1310 | DIM(SORT_SRCLINE, "srcline", sort_srcline), |
1252 | DIM(SORT_SRCFILE, "srcfile", sort_srcfile), | 1311 | DIM(SORT_SRCFILE, "srcfile", sort_srcfile), |
1253 | DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), | 1312 | DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), |
@@ -1276,6 +1335,7 @@ static struct sort_dimension bstack_sort_dimensions[] = { | |||
1276 | 1335 | ||
1277 | static struct sort_dimension memory_sort_dimensions[] = { | 1336 | static struct sort_dimension memory_sort_dimensions[] = { |
1278 | DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym), | 1337 | DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym), |
1338 | DIM(SORT_MEM_IADDR_SYMBOL, "symbol_iaddr", sort_mem_iaddr_sym), | ||
1279 | DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso), | 1339 | DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso), |
1280 | DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked), | 1340 | DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked), |
1281 | DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb), | 1341 | DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb), |
@@ -1517,6 +1577,12 @@ static int __hpp_dimension__add_output(struct hpp_dimension *hd) | |||
1517 | return 0; | 1577 | return 0; |
1518 | } | 1578 | } |
1519 | 1579 | ||
1580 | int hpp_dimension__add_output(unsigned col) | ||
1581 | { | ||
1582 | BUG_ON(col >= PERF_HPP__MAX_INDEX); | ||
1583 | return __hpp_dimension__add_output(&hpp_sort_dimensions[col]); | ||
1584 | } | ||
1585 | |||
1520 | int sort_dimension__add(const char *tok) | 1586 | int sort_dimension__add(const char *tok) |
1521 | { | 1587 | { |
1522 | unsigned int i; | 1588 | unsigned int i; |
@@ -1550,6 +1616,8 @@ int sort_dimension__add(const char *tok) | |||
1550 | 1616 | ||
1551 | } else if (sd->entry == &sort_dso) { | 1617 | } else if (sd->entry == &sort_dso) { |
1552 | sort__has_dso = 1; | 1618 | sort__has_dso = 1; |
1619 | } else if (sd->entry == &sort_socket) { | ||
1620 | sort__has_socket = 1; | ||
1553 | } | 1621 | } |
1554 | 1622 | ||
1555 | return __sort_dimension__add(sd); | 1623 | return __sort_dimension__add(sd); |
@@ -1855,8 +1923,6 @@ static int __setup_output_field(void) | |||
1855 | if (field_order == NULL) | 1923 | if (field_order == NULL) |
1856 | return 0; | 1924 | return 0; |
1857 | 1925 | ||
1858 | reset_dimensions(); | ||
1859 | |||
1860 | strp = str = strdup(field_order); | 1926 | strp = str = strdup(field_order); |
1861 | if (str == NULL) { | 1927 | if (str == NULL) { |
1862 | error("Not enough memory to setup output fields"); | 1928 | error("Not enough memory to setup output fields"); |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 3c2a399f8f5b..31228851e397 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -34,6 +34,7 @@ extern int have_ignore_callees; | |||
34 | extern int sort__need_collapse; | 34 | extern int sort__need_collapse; |
35 | extern int sort__has_parent; | 35 | extern int sort__has_parent; |
36 | extern int sort__has_sym; | 36 | extern int sort__has_sym; |
37 | extern int sort__has_socket; | ||
37 | extern enum sort_mode sort__mode; | 38 | extern enum sort_mode sort__mode; |
38 | extern struct sort_entry sort_comm; | 39 | extern struct sort_entry sort_comm; |
39 | extern struct sort_entry sort_dso; | 40 | extern struct sort_entry sort_dso; |
@@ -90,6 +91,7 @@ struct hist_entry { | |||
90 | struct comm *comm; | 91 | struct comm *comm; |
91 | u64 ip; | 92 | u64 ip; |
92 | u64 transaction; | 93 | u64 transaction; |
94 | s32 socket; | ||
93 | s32 cpu; | 95 | s32 cpu; |
94 | u8 cpumode; | 96 | u8 cpumode; |
95 | 97 | ||
@@ -172,6 +174,7 @@ enum sort_type { | |||
172 | SORT_SYM, | 174 | SORT_SYM, |
173 | SORT_PARENT, | 175 | SORT_PARENT, |
174 | SORT_CPU, | 176 | SORT_CPU, |
177 | SORT_SOCKET, | ||
175 | SORT_SRCLINE, | 178 | SORT_SRCLINE, |
176 | SORT_SRCFILE, | 179 | SORT_SRCFILE, |
177 | SORT_LOCAL_WEIGHT, | 180 | SORT_LOCAL_WEIGHT, |
@@ -198,6 +201,7 @@ enum sort_type { | |||
198 | SORT_MEM_LVL, | 201 | SORT_MEM_LVL, |
199 | SORT_MEM_SNOOP, | 202 | SORT_MEM_SNOOP, |
200 | SORT_MEM_DCACHELINE, | 203 | SORT_MEM_DCACHELINE, |
204 | SORT_MEM_IADDR_SYMBOL, | ||
201 | }; | 205 | }; |
202 | 206 | ||
203 | /* | 207 | /* |
@@ -230,4 +234,6 @@ void perf_hpp__set_elide(int idx, bool elide); | |||
230 | int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); | 234 | int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); |
231 | 235 | ||
232 | bool is_strict_order(const char *order); | 236 | bool is_strict_order(const char *order); |
237 | |||
238 | int hpp_dimension__add_output(unsigned col); | ||
233 | #endif /* __PERF_SORT_H */ | 239 | #endif /* __PERF_SORT_H */ |
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index fc08248f08ca..b4db3f48e3b0 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c | |||
@@ -149,8 +149,11 @@ static void addr2line_cleanup(struct a2l_data *a2l) | |||
149 | free(a2l); | 149 | free(a2l); |
150 | } | 150 | } |
151 | 151 | ||
152 | #define MAX_INLINE_NEST 1024 | ||
153 | |||
152 | static int addr2line(const char *dso_name, u64 addr, | 154 | static int addr2line(const char *dso_name, u64 addr, |
153 | char **file, unsigned int *line, struct dso *dso) | 155 | char **file, unsigned int *line, struct dso *dso, |
156 | bool unwind_inlines) | ||
154 | { | 157 | { |
155 | int ret = 0; | 158 | int ret = 0; |
156 | struct a2l_data *a2l = dso->a2l; | 159 | struct a2l_data *a2l = dso->a2l; |
@@ -170,6 +173,15 @@ static int addr2line(const char *dso_name, u64 addr, | |||
170 | 173 | ||
171 | bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); | 174 | bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); |
172 | 175 | ||
176 | if (a2l->found && unwind_inlines) { | ||
177 | int cnt = 0; | ||
178 | |||
179 | while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, | ||
180 | &a2l->funcname, &a2l->line) && | ||
181 | cnt++ < MAX_INLINE_NEST) | ||
182 | ; | ||
183 | } | ||
184 | |||
173 | if (a2l->found && a2l->filename) { | 185 | if (a2l->found && a2l->filename) { |
174 | *file = strdup(a2l->filename); | 186 | *file = strdup(a2l->filename); |
175 | *line = a2l->line; | 187 | *line = a2l->line; |
@@ -197,7 +209,8 @@ void dso__free_a2l(struct dso *dso) | |||
197 | 209 | ||
198 | static int addr2line(const char *dso_name, u64 addr, | 210 | static int addr2line(const char *dso_name, u64 addr, |
199 | char **file, unsigned int *line_nr, | 211 | char **file, unsigned int *line_nr, |
200 | struct dso *dso __maybe_unused) | 212 | struct dso *dso __maybe_unused, |
213 | bool unwind_inlines __maybe_unused) | ||
201 | { | 214 | { |
202 | FILE *fp; | 215 | FILE *fp; |
203 | char cmd[PATH_MAX]; | 216 | char cmd[PATH_MAX]; |
@@ -254,8 +267,8 @@ void dso__free_a2l(struct dso *dso __maybe_unused) | |||
254 | */ | 267 | */ |
255 | #define A2L_FAIL_LIMIT 123 | 268 | #define A2L_FAIL_LIMIT 123 |
256 | 269 | ||
257 | char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, | 270 | char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, |
258 | bool show_sym) | 271 | bool show_sym, bool unwind_inlines) |
259 | { | 272 | { |
260 | char *file = NULL; | 273 | char *file = NULL; |
261 | unsigned line = 0; | 274 | unsigned line = 0; |
@@ -276,7 +289,7 @@ char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, | |||
276 | if (!strncmp(dso_name, "/tmp/perf-", 10)) | 289 | if (!strncmp(dso_name, "/tmp/perf-", 10)) |
277 | goto out; | 290 | goto out; |
278 | 291 | ||
279 | if (!addr2line(dso_name, addr, &file, &line, dso)) | 292 | if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines)) |
280 | goto out; | 293 | goto out; |
281 | 294 | ||
282 | if (asprintf(&srcline, "%s:%u", | 295 | if (asprintf(&srcline, "%s:%u", |
@@ -310,3 +323,9 @@ void free_srcline(char *srcline) | |||
310 | if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0) | 323 | if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0) |
311 | free(srcline); | 324 | free(srcline); |
312 | } | 325 | } |
326 | |||
327 | char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, | ||
328 | bool show_sym) | ||
329 | { | ||
330 | return __get_srcline(dso, addr, sym, show_sym, false); | ||
331 | } | ||
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 415c359de465..2d9d8306dbd3 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c | |||
@@ -67,7 +67,7 @@ double rel_stddev_stats(double stddev, double avg) | |||
67 | bool __perf_evsel_stat__is(struct perf_evsel *evsel, | 67 | bool __perf_evsel_stat__is(struct perf_evsel *evsel, |
68 | enum perf_stat_evsel_id id) | 68 | enum perf_stat_evsel_id id) |
69 | { | 69 | { |
70 | struct perf_stat *ps = evsel->priv; | 70 | struct perf_stat_evsel *ps = evsel->priv; |
71 | 71 | ||
72 | return ps->id == id; | 72 | return ps->id == id; |
73 | } | 73 | } |
@@ -84,7 +84,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = { | |||
84 | 84 | ||
85 | void perf_stat_evsel_id_init(struct perf_evsel *evsel) | 85 | void perf_stat_evsel_id_init(struct perf_evsel *evsel) |
86 | { | 86 | { |
87 | struct perf_stat *ps = evsel->priv; | 87 | struct perf_stat_evsel *ps = evsel->priv; |
88 | int i; | 88 | int i; |
89 | 89 | ||
90 | /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */ | 90 | /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */ |
@@ -100,7 +100,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) | |||
100 | void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) | 100 | void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) |
101 | { | 101 | { |
102 | int i; | 102 | int i; |
103 | struct perf_stat *ps = evsel->priv; | 103 | struct perf_stat_evsel *ps = evsel->priv; |
104 | 104 | ||
105 | for (i = 0; i < 3; i++) | 105 | for (i = 0; i < 3; i++) |
106 | init_stats(&ps->res_stats[i]); | 106 | init_stats(&ps->res_stats[i]); |
@@ -110,7 +110,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) | |||
110 | 110 | ||
111 | int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) | 111 | int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) |
112 | { | 112 | { |
113 | evsel->priv = zalloc(sizeof(struct perf_stat)); | 113 | evsel->priv = zalloc(sizeof(struct perf_stat_evsel)); |
114 | if (evsel->priv == NULL) | 114 | if (evsel->priv == NULL) |
115 | return -ENOMEM; | 115 | return -ENOMEM; |
116 | perf_evsel__reset_stat_priv(evsel); | 116 | perf_evsel__reset_stat_priv(evsel); |
@@ -196,7 +196,8 @@ static void zero_per_pkg(struct perf_evsel *counter) | |||
196 | memset(counter->per_pkg_mask, 0, MAX_NR_CPUS); | 196 | memset(counter->per_pkg_mask, 0, MAX_NR_CPUS); |
197 | } | 197 | } |
198 | 198 | ||
199 | static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) | 199 | static int check_per_pkg(struct perf_evsel *counter, |
200 | struct perf_counts_values *vals, int cpu, bool *skip) | ||
200 | { | 201 | { |
201 | unsigned long *mask = counter->per_pkg_mask; | 202 | unsigned long *mask = counter->per_pkg_mask; |
202 | struct cpu_map *cpus = perf_evsel__cpus(counter); | 203 | struct cpu_map *cpus = perf_evsel__cpus(counter); |
@@ -218,7 +219,18 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip) | |||
218 | counter->per_pkg_mask = mask; | 219 | counter->per_pkg_mask = mask; |
219 | } | 220 | } |
220 | 221 | ||
221 | s = cpu_map__get_socket(cpus, cpu); | 222 | /* |
223 | * we do not consider an event that has not run as a good | ||
224 | * instance to mark a package as used (skip=1). Otherwise | ||
225 | * we may run into a situation where the first CPU in a package | ||
226 | * is not running anything, yet the second is, and this function | ||
227 | * would mark the package as used after the first CPU and would | ||
228 | * not read the values from the second CPU. | ||
229 | */ | ||
230 | if (!(vals->run && vals->ena)) | ||
231 | return 0; | ||
232 | |||
233 | s = cpu_map__get_socket(cpus, cpu, NULL); | ||
222 | if (s < 0) | 234 | if (s < 0) |
223 | return -1; | 235 | return -1; |
224 | 236 | ||
@@ -235,7 +247,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel | |||
235 | static struct perf_counts_values zero; | 247 | static struct perf_counts_values zero; |
236 | bool skip = false; | 248 | bool skip = false; |
237 | 249 | ||
238 | if (check_per_pkg(evsel, cpu, &skip)) { | 250 | if (check_per_pkg(evsel, count, cpu, &skip)) { |
239 | pr_err("failed to read per-pkg counter\n"); | 251 | pr_err("failed to read per-pkg counter\n"); |
240 | return -1; | 252 | return -1; |
241 | } | 253 | } |
@@ -260,6 +272,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel | |||
260 | aggr->ena += count->ena; | 272 | aggr->ena += count->ena; |
261 | aggr->run += count->run; | 273 | aggr->run += count->run; |
262 | } | 274 | } |
275 | case AGGR_UNSET: | ||
263 | default: | 276 | default: |
264 | break; | 277 | break; |
265 | } | 278 | } |
@@ -292,7 +305,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, | |||
292 | struct perf_evsel *counter) | 305 | struct perf_evsel *counter) |
293 | { | 306 | { |
294 | struct perf_counts_values *aggr = &counter->counts->aggr; | 307 | struct perf_counts_values *aggr = &counter->counts->aggr; |
295 | struct perf_stat *ps = counter->priv; | 308 | struct perf_stat_evsel *ps = counter->priv; |
296 | u64 *count = counter->counts->aggr.values; | 309 | u64 *count = counter->counts->aggr.values; |
297 | int i, ret; | 310 | int i, ret; |
298 | 311 | ||
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 62448c8175d3..da1d11c4f8c1 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h | |||
@@ -20,7 +20,7 @@ enum perf_stat_evsel_id { | |||
20 | PERF_STAT_EVSEL_ID__MAX, | 20 | PERF_STAT_EVSEL_ID__MAX, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | struct perf_stat { | 23 | struct perf_stat_evsel { |
24 | struct stats res_stats[3]; | 24 | struct stats res_stats[3]; |
25 | enum perf_stat_evsel_id id; | 25 | enum perf_stat_evsel_id id; |
26 | }; | 26 | }; |
@@ -31,6 +31,7 @@ enum aggr_mode { | |||
31 | AGGR_SOCKET, | 31 | AGGR_SOCKET, |
32 | AGGR_CORE, | 32 | AGGR_CORE, |
33 | AGGR_THREAD, | 33 | AGGR_THREAD, |
34 | AGGR_UNSET, | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | struct perf_stat_config { | 37 | struct perf_stat_config { |
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index 4abe23550c73..25671fa16618 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c | |||
@@ -82,23 +82,22 @@ void strbuf_add(struct strbuf *sb, const void *data, size_t len) | |||
82 | strbuf_setlen(sb, sb->len + len); | 82 | strbuf_setlen(sb, sb->len + len); |
83 | } | 83 | } |
84 | 84 | ||
85 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...) | 85 | void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) |
86 | { | 86 | { |
87 | int len; | 87 | int len; |
88 | va_list ap; | 88 | va_list ap_saved; |
89 | 89 | ||
90 | if (!strbuf_avail(sb)) | 90 | if (!strbuf_avail(sb)) |
91 | strbuf_grow(sb, 64); | 91 | strbuf_grow(sb, 64); |
92 | va_start(ap, fmt); | 92 | |
93 | va_copy(ap_saved, ap); | ||
93 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); | 94 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); |
94 | va_end(ap); | ||
95 | if (len < 0) | 95 | if (len < 0) |
96 | die("your vsnprintf is broken"); | 96 | die("your vsnprintf is broken"); |
97 | if (len > strbuf_avail(sb)) { | 97 | if (len > strbuf_avail(sb)) { |
98 | strbuf_grow(sb, len); | 98 | strbuf_grow(sb, len); |
99 | va_start(ap, fmt); | 99 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); |
100 | len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); | 100 | va_end(ap_saved); |
101 | va_end(ap); | ||
102 | if (len > strbuf_avail(sb)) { | 101 | if (len > strbuf_avail(sb)) { |
103 | die("this should not happen, your vsnprintf is broken"); | 102 | die("this should not happen, your vsnprintf is broken"); |
104 | } | 103 | } |
@@ -106,6 +105,15 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...) | |||
106 | strbuf_setlen(sb, sb->len + len); | 105 | strbuf_setlen(sb, sb->len + len); |
107 | } | 106 | } |
108 | 107 | ||
108 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...) | ||
109 | { | ||
110 | va_list ap; | ||
111 | |||
112 | va_start(ap, fmt); | ||
113 | strbuf_addv(sb, fmt, ap); | ||
114 | va_end(ap); | ||
115 | } | ||
116 | |||
109 | ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) | 117 | ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) |
110 | { | 118 | { |
111 | size_t oldlen = sb->len; | 119 | size_t oldlen = sb->len; |
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index 436ac319f6c7..529f2f035249 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h | |||
@@ -39,6 +39,7 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include <assert.h> | 41 | #include <assert.h> |
42 | #include <stdarg.h> | ||
42 | 43 | ||
43 | extern char strbuf_slopbuf[]; | 44 | extern char strbuf_slopbuf[]; |
44 | struct strbuf { | 45 | struct strbuf { |
@@ -85,6 +86,7 @@ static inline void strbuf_addstr(struct strbuf *sb, const char *s) { | |||
85 | 86 | ||
86 | __attribute__((format(printf,2,3))) | 87 | __attribute__((format(printf,2,3))) |
87 | extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); | 88 | extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); |
89 | extern void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap); | ||
88 | 90 | ||
89 | /* XXX: if read fails, any partial read is undone */ | 91 | /* XXX: if read fails, any partial read is undone */ |
90 | extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); | 92 | extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 53bb5f59ec58..475d88d0a1c9 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -38,7 +38,7 @@ static inline char *bfd_demangle(void __maybe_unused *v, | |||
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT | 40 | #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT |
41 | int elf_getphdrnum(Elf *elf, size_t *dst) | 41 | static int elf_getphdrnum(Elf *elf, size_t *dst) |
42 | { | 42 | { |
43 | GElf_Ehdr gehdr; | 43 | GElf_Ehdr gehdr; |
44 | GElf_Ehdr *ehdr; | 44 | GElf_Ehdr *ehdr; |
@@ -1271,8 +1271,6 @@ out_close: | |||
1271 | static int kcore__init(struct kcore *kcore, char *filename, int elfclass, | 1271 | static int kcore__init(struct kcore *kcore, char *filename, int elfclass, |
1272 | bool temp) | 1272 | bool temp) |
1273 | { | 1273 | { |
1274 | GElf_Ehdr *ehdr; | ||
1275 | |||
1276 | kcore->elfclass = elfclass; | 1274 | kcore->elfclass = elfclass; |
1277 | 1275 | ||
1278 | if (temp) | 1276 | if (temp) |
@@ -1289,9 +1287,7 @@ static int kcore__init(struct kcore *kcore, char *filename, int elfclass, | |||
1289 | if (!gelf_newehdr(kcore->elf, elfclass)) | 1287 | if (!gelf_newehdr(kcore->elf, elfclass)) |
1290 | goto out_end; | 1288 | goto out_end; |
1291 | 1289 | ||
1292 | ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr); | 1290 | memset(&kcore->ehdr, 0, sizeof(GElf_Ehdr)); |
1293 | if (!ehdr) | ||
1294 | goto out_end; | ||
1295 | 1291 | ||
1296 | return 0; | 1292 | return 0; |
1297 | 1293 | ||
@@ -1348,23 +1344,18 @@ static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count) | |||
1348 | static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset, | 1344 | static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset, |
1349 | u64 addr, u64 len) | 1345 | u64 addr, u64 len) |
1350 | { | 1346 | { |
1351 | GElf_Phdr gphdr; | 1347 | GElf_Phdr phdr = { |
1352 | GElf_Phdr *phdr; | 1348 | .p_type = PT_LOAD, |
1353 | 1349 | .p_flags = PF_R | PF_W | PF_X, | |
1354 | phdr = gelf_getphdr(kcore->elf, idx, &gphdr); | 1350 | .p_offset = offset, |
1355 | if (!phdr) | 1351 | .p_vaddr = addr, |
1356 | return -1; | 1352 | .p_paddr = 0, |
1357 | 1353 | .p_filesz = len, | |
1358 | phdr->p_type = PT_LOAD; | 1354 | .p_memsz = len, |
1359 | phdr->p_flags = PF_R | PF_W | PF_X; | 1355 | .p_align = page_size, |
1360 | phdr->p_offset = offset; | 1356 | }; |
1361 | phdr->p_vaddr = addr; | 1357 | |
1362 | phdr->p_paddr = 0; | 1358 | if (!gelf_update_phdr(kcore->elf, idx, &phdr)) |
1363 | phdr->p_filesz = len; | ||
1364 | phdr->p_memsz = len; | ||
1365 | phdr->p_align = page_size; | ||
1366 | |||
1367 | if (!gelf_update_phdr(kcore->elf, idx, phdr)) | ||
1368 | return -1; | 1359 | return -1; |
1369 | 1360 | ||
1370 | return 0; | 1361 | return 0; |
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index fd8477cacf88..48906333a858 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
@@ -337,7 +337,7 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, | |||
337 | symbol_filter_t filter __maybe_unused, | 337 | symbol_filter_t filter __maybe_unused, |
338 | int kmodule __maybe_unused) | 338 | int kmodule __maybe_unused) |
339 | { | 339 | { |
340 | unsigned char *build_id[BUILD_ID_SIZE]; | 340 | unsigned char build_id[BUILD_ID_SIZE]; |
341 | int ret; | 341 | int ret; |
342 | 342 | ||
343 | ret = fd__is_64_bit(ss->fd); | 343 | ret = fd__is_64_bit(ss->fd); |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 1f97ffb158a6..b4cc7662677e 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -624,7 +624,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name, | |||
624 | * symbols, setting length to 0, and rely on | 624 | * symbols, setting length to 0, and rely on |
625 | * symbols__fixup_end() to fix it up. | 625 | * symbols__fixup_end() to fix it up. |
626 | */ | 626 | */ |
627 | sym = symbol__new(start, 0, kallsyms2elf_type(type), name); | 627 | sym = symbol__new(start, 0, kallsyms2elf_binding(type), name); |
628 | if (sym == NULL) | 628 | if (sym == NULL) |
629 | return -ENOMEM; | 629 | return -ENOMEM; |
630 | /* | 630 | /* |
@@ -680,7 +680,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, | |||
680 | pos->start -= curr_map->start - curr_map->pgoff; | 680 | pos->start -= curr_map->start - curr_map->pgoff; |
681 | if (pos->end) | 681 | if (pos->end) |
682 | pos->end -= curr_map->start - curr_map->pgoff; | 682 | pos->end -= curr_map->start - curr_map->pgoff; |
683 | if (curr_map != map) { | 683 | if (curr_map->dso != map->dso) { |
684 | rb_erase_init(&pos->rb_node, root); | 684 | rb_erase_init(&pos->rb_node, root); |
685 | symbols__insert( | 685 | symbols__insert( |
686 | &curr_map->dso->symbols[curr_map->type], | 686 | &curr_map->dso->symbols[curr_map->type], |
@@ -1406,6 +1406,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1406 | struct symsrc ss_[2]; | 1406 | struct symsrc ss_[2]; |
1407 | struct symsrc *syms_ss = NULL, *runtime_ss = NULL; | 1407 | struct symsrc *syms_ss = NULL, *runtime_ss = NULL; |
1408 | bool kmod; | 1408 | bool kmod; |
1409 | unsigned char build_id[BUILD_ID_SIZE]; | ||
1409 | 1410 | ||
1410 | pthread_mutex_lock(&dso->lock); | 1411 | pthread_mutex_lock(&dso->lock); |
1411 | 1412 | ||
@@ -1461,6 +1462,14 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1461 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || | 1462 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE || |
1462 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; | 1463 | dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; |
1463 | 1464 | ||
1465 | |||
1466 | /* | ||
1467 | * Read the build id if possible. This is required for | ||
1468 | * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work | ||
1469 | */ | ||
1470 | if (filename__read_build_id(dso->name, build_id, BUILD_ID_SIZE) > 0) | ||
1471 | dso__set_build_id(dso, build_id); | ||
1472 | |||
1464 | /* | 1473 | /* |
1465 | * Iterate over candidate debug images. | 1474 | * Iterate over candidate debug images. |
1466 | * Keep track of "interesting" ones (those which have a symtab, dynsym, | 1475 | * Keep track of "interesting" ones (those which have a symtab, dynsym, |
@@ -1607,6 +1616,15 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, | |||
1607 | int i, err = 0; | 1616 | int i, err = 0; |
1608 | char *filename = NULL; | 1617 | char *filename = NULL; |
1609 | 1618 | ||
1619 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", | ||
1620 | vmlinux_path__nr_entries + 1); | ||
1621 | |||
1622 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { | ||
1623 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); | ||
1624 | if (err > 0) | ||
1625 | goto out; | ||
1626 | } | ||
1627 | |||
1610 | if (!symbol_conf.ignore_vmlinux_buildid) | 1628 | if (!symbol_conf.ignore_vmlinux_buildid) |
1611 | filename = dso__build_id_filename(dso, NULL, 0); | 1629 | filename = dso__build_id_filename(dso, NULL, 0); |
1612 | if (filename != NULL) { | 1630 | if (filename != NULL) { |
@@ -1615,15 +1633,6 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, | |||
1615 | goto out; | 1633 | goto out; |
1616 | free(filename); | 1634 | free(filename); |
1617 | } | 1635 | } |
1618 | |||
1619 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", | ||
1620 | vmlinux_path__nr_entries + 1); | ||
1621 | |||
1622 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { | ||
1623 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); | ||
1624 | if (err > 0) | ||
1625 | break; | ||
1626 | } | ||
1627 | out: | 1636 | out: |
1628 | return err; | 1637 | return err; |
1629 | } | 1638 | } |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 440ba8ae888f..40073c60b83d 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -191,6 +191,7 @@ struct addr_location { | |||
191 | u8 filtered; | 191 | u8 filtered; |
192 | u8 cpumode; | 192 | u8 cpumode; |
193 | s32 cpu; | 193 | s32 cpu; |
194 | s32 socket; | ||
194 | }; | 195 | }; |
195 | 196 | ||
196 | struct symsrc { | 197 | struct symsrc { |
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 22245986e59e..d995743cb673 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | #include "../perf.h" | 39 | #include "../perf.h" |
40 | #include "trace-event.h" | 40 | #include "trace-event.h" |
41 | #include <api/fs/debugfs.h> | 41 | #include <api/fs/tracing_path.h> |
42 | #include "evsel.h" | 42 | #include "evsel.h" |
43 | #include "debug.h" | 43 | #include "debug.h" |
44 | 44 | ||
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c index b90e646c7a91..802bb868d446 100644 --- a/tools/perf/util/trace-event.c +++ b/tools/perf/util/trace-event.c | |||
@@ -7,7 +7,9 @@ | |||
7 | #include <sys/stat.h> | 7 | #include <sys/stat.h> |
8 | #include <fcntl.h> | 8 | #include <fcntl.h> |
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/err.h> | ||
10 | #include <traceevent/event-parse.h> | 11 | #include <traceevent/event-parse.h> |
12 | #include <api/fs/tracing_path.h> | ||
11 | #include "trace-event.h" | 13 | #include "trace-event.h" |
12 | #include "machine.h" | 14 | #include "machine.h" |
13 | #include "util.h" | 15 | #include "util.h" |
@@ -65,6 +67,9 @@ void trace_event__cleanup(struct trace_event *t) | |||
65 | pevent_free(t->pevent); | 67 | pevent_free(t->pevent); |
66 | } | 68 | } |
67 | 69 | ||
70 | /* | ||
71 | * Returns pointer with encoded error via <linux/err.h> interface. | ||
72 | */ | ||
68 | static struct event_format* | 73 | static struct event_format* |
69 | tp_format(const char *sys, const char *name) | 74 | tp_format(const char *sys, const char *name) |
70 | { | 75 | { |
@@ -73,12 +78,14 @@ tp_format(const char *sys, const char *name) | |||
73 | char path[PATH_MAX]; | 78 | char path[PATH_MAX]; |
74 | size_t size; | 79 | size_t size; |
75 | char *data; | 80 | char *data; |
81 | int err; | ||
76 | 82 | ||
77 | scnprintf(path, PATH_MAX, "%s/%s/%s/format", | 83 | scnprintf(path, PATH_MAX, "%s/%s/%s/format", |
78 | tracing_events_path, sys, name); | 84 | tracing_events_path, sys, name); |
79 | 85 | ||
80 | if (filename__read_str(path, &data, &size)) | 86 | err = filename__read_str(path, &data, &size); |
81 | return NULL; | 87 | if (err) |
88 | return ERR_PTR(err); | ||
82 | 89 | ||
83 | pevent_parse_format(pevent, &event, data, size, sys); | 90 | pevent_parse_format(pevent, &event, data, size, sys); |
84 | 91 | ||
@@ -86,11 +93,14 @@ tp_format(const char *sys, const char *name) | |||
86 | return event; | 93 | return event; |
87 | } | 94 | } |
88 | 95 | ||
96 | /* | ||
97 | * Returns pointer with encoded error via <linux/err.h> interface. | ||
98 | */ | ||
89 | struct event_format* | 99 | struct event_format* |
90 | trace_event__tp_format(const char *sys, const char *name) | 100 | trace_event__tp_format(const char *sys, const char *name) |
91 | { | 101 | { |
92 | if (!tevent_initialized && trace_event__init2()) | 102 | if (!tevent_initialized && trace_event__init2()) |
93 | return NULL; | 103 | return ERR_PTR(-ENOMEM); |
94 | 104 | ||
95 | return tp_format(sys, name); | 105 | return tp_format(sys, name); |
96 | } | 106 | } |
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index da6cc4cc2a4f..b85ee55cca0c 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h | |||
@@ -78,6 +78,8 @@ struct scripting_ops { | |||
78 | int (*generate_script) (struct pevent *pevent, const char *outfile); | 78 | int (*generate_script) (struct pevent *pevent, const char *outfile); |
79 | }; | 79 | }; |
80 | 80 | ||
81 | extern unsigned int scripting_max_stack; | ||
82 | |||
81 | int script_spec_register(const char *spec, struct scripting_ops *ops); | 83 | int script_spec_register(const char *spec, struct scripting_ops *ops); |
82 | 84 | ||
83 | void setup_perl_scripting(void); | 85 | void setup_perl_scripting(void); |
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 4c00507ee3fd..c83832b555e5 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
@@ -330,6 +330,7 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | |||
330 | struct map *map; | 330 | struct map *map; |
331 | unw_dyn_info_t di; | 331 | unw_dyn_info_t di; |
332 | u64 table_data, segbase, fde_count; | 332 | u64 table_data, segbase, fde_count; |
333 | int ret = -EINVAL; | ||
333 | 334 | ||
334 | map = find_map(ip, ui); | 335 | map = find_map(ip, ui); |
335 | if (!map || !map->dso) | 336 | if (!map || !map->dso) |
@@ -348,29 +349,33 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, | |||
348 | di.u.rti.table_data = map->start + table_data; | 349 | di.u.rti.table_data = map->start + table_data; |
349 | di.u.rti.table_len = fde_count * sizeof(struct table_entry) | 350 | di.u.rti.table_len = fde_count * sizeof(struct table_entry) |
350 | / sizeof(unw_word_t); | 351 | / sizeof(unw_word_t); |
351 | return dwarf_search_unwind_table(as, ip, &di, pi, | 352 | ret = dwarf_search_unwind_table(as, ip, &di, pi, |
352 | need_unwind_info, arg); | 353 | need_unwind_info, arg); |
353 | } | 354 | } |
354 | 355 | ||
355 | #ifndef NO_LIBUNWIND_DEBUG_FRAME | 356 | #ifndef NO_LIBUNWIND_DEBUG_FRAME |
356 | /* Check the .debug_frame section for unwinding info */ | 357 | /* Check the .debug_frame section for unwinding info */ |
357 | if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { | 358 | if (ret < 0 && |
359 | !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { | ||
358 | int fd = dso__data_get_fd(map->dso, ui->machine); | 360 | int fd = dso__data_get_fd(map->dso, ui->machine); |
359 | int is_exec = elf_is_exec(fd, map->dso->name); | 361 | int is_exec = elf_is_exec(fd, map->dso->name); |
360 | unw_word_t base = is_exec ? 0 : map->start; | 362 | unw_word_t base = is_exec ? 0 : map->start; |
363 | const char *symfile; | ||
361 | 364 | ||
362 | if (fd >= 0) | 365 | if (fd >= 0) |
363 | dso__data_put_fd(map->dso); | 366 | dso__data_put_fd(map->dso); |
364 | 367 | ||
368 | symfile = map->dso->symsrc_filename ?: map->dso->name; | ||
369 | |||
365 | memset(&di, 0, sizeof(di)); | 370 | memset(&di, 0, sizeof(di)); |
366 | if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, | 371 | if (dwarf_find_debug_frame(0, &di, ip, base, symfile, |
367 | map->start, map->end)) | 372 | map->start, map->end)) |
368 | return dwarf_search_unwind_table(as, ip, &di, pi, | 373 | return dwarf_search_unwind_table(as, ip, &di, pi, |
369 | need_unwind_info, arg); | 374 | need_unwind_info, arg); |
370 | } | 375 | } |
371 | #endif | 376 | #endif |
372 | 377 | ||
373 | return -EINVAL; | 378 | return ret; |
374 | } | 379 | } |
375 | 380 | ||
376 | static int access_fpreg(unw_addr_space_t __maybe_unused as, | 381 | static int access_fpreg(unw_addr_space_t __maybe_unused as, |
@@ -461,7 +466,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as, | |||
461 | if (ret) { | 466 | if (ret) { |
462 | pr_debug("unwind: access_mem %p not inside range" | 467 | pr_debug("unwind: access_mem %p not inside range" |
463 | " 0x%" PRIx64 "-0x%" PRIx64 "\n", | 468 | " 0x%" PRIx64 "-0x%" PRIx64 "\n", |
464 | (void *) addr, start, end); | 469 | (void *) (uintptr_t) addr, start, end); |
465 | *valp = 0; | 470 | *valp = 0; |
466 | return ret; | 471 | return ret; |
467 | } | 472 | } |
@@ -471,7 +476,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as, | |||
471 | offset = addr - start; | 476 | offset = addr - start; |
472 | *valp = *(unw_word_t *)&stack->data[offset]; | 477 | *valp = *(unw_word_t *)&stack->data[offset]; |
473 | pr_debug("unwind: access_mem addr %p val %lx, offset %d\n", | 478 | pr_debug("unwind: access_mem addr %p val %lx, offset %d\n", |
474 | (void *) addr, (unsigned long)*valp, offset); | 479 | (void *) (uintptr_t) addr, (unsigned long)*valp, offset); |
475 | return 0; | 480 | return 0; |
476 | } | 481 | } |
477 | 482 | ||
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c index 4007aca8e0ca..6adfa18cdd4e 100644 --- a/tools/perf/util/usage.c +++ b/tools/perf/util/usage.c | |||
@@ -50,6 +50,11 @@ void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN) | |||
50 | die_routine = routine; | 50 | die_routine = routine; |
51 | } | 51 | } |
52 | 52 | ||
53 | void set_warning_routine(void (*routine)(const char *err, va_list params)) | ||
54 | { | ||
55 | warn_routine = routine; | ||
56 | } | ||
57 | |||
53 | void usage(const char *err) | 58 | void usage(const char *err) |
54 | { | 59 | { |
55 | usage_routine(err); | 60 | usage_routine(err); |
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 7acafb3c5592..cd12c25e4ea4 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include "callchain.h" | 17 | #include "callchain.h" |
18 | 18 | ||
19 | struct callchain_param callchain_param = { | 19 | struct callchain_param callchain_param = { |
20 | .mode = CHAIN_GRAPH_REL, | 20 | .mode = CHAIN_GRAPH_ABS, |
21 | .min_percent = 0.5, | 21 | .min_percent = 0.5, |
22 | .order = ORDER_CALLEE, | 22 | .order = ORDER_CALLEE, |
23 | .key = CCKEY_FUNCTION | 23 | .key = CCKEY_FUNCTION |
@@ -34,9 +34,6 @@ bool test_attr__enabled; | |||
34 | bool perf_host = true; | 34 | bool perf_host = true; |
35 | bool perf_guest = false; | 35 | bool perf_guest = false; |
36 | 36 | ||
37 | char tracing_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing"; | ||
38 | char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events"; | ||
39 | |||
40 | void event_attr_init(struct perf_event_attr *attr) | 37 | void event_attr_init(struct perf_event_attr *attr) |
41 | { | 38 | { |
42 | if (!perf_host) | 39 | if (!perf_host) |
@@ -390,73 +387,6 @@ void set_term_quiet_input(struct termios *old) | |||
390 | tcsetattr(0, TCSANOW, &tc); | 387 | tcsetattr(0, TCSANOW, &tc); |
391 | } | 388 | } |
392 | 389 | ||
393 | static void set_tracing_events_path(const char *tracing, const char *mountpoint) | ||
394 | { | ||
395 | snprintf(tracing_path, sizeof(tracing_path), "%s/%s", | ||
396 | mountpoint, tracing); | ||
397 | snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s", | ||
398 | mountpoint, tracing, "events"); | ||
399 | } | ||
400 | |||
401 | static const char *__perf_tracefs_mount(const char *mountpoint) | ||
402 | { | ||
403 | const char *mnt; | ||
404 | |||
405 | mnt = tracefs_mount(mountpoint); | ||
406 | if (!mnt) | ||
407 | return NULL; | ||
408 | |||
409 | set_tracing_events_path("", mnt); | ||
410 | |||
411 | return mnt; | ||
412 | } | ||
413 | |||
414 | static const char *__perf_debugfs_mount(const char *mountpoint) | ||
415 | { | ||
416 | const char *mnt; | ||
417 | |||
418 | mnt = debugfs_mount(mountpoint); | ||
419 | if (!mnt) | ||
420 | return NULL; | ||
421 | |||
422 | set_tracing_events_path("tracing/", mnt); | ||
423 | |||
424 | return mnt; | ||
425 | } | ||
426 | |||
427 | const char *perf_debugfs_mount(const char *mountpoint) | ||
428 | { | ||
429 | const char *mnt; | ||
430 | |||
431 | mnt = __perf_tracefs_mount(mountpoint); | ||
432 | if (mnt) | ||
433 | return mnt; | ||
434 | |||
435 | mnt = __perf_debugfs_mount(mountpoint); | ||
436 | |||
437 | return mnt; | ||
438 | } | ||
439 | |||
440 | void perf_debugfs_set_path(const char *mntpt) | ||
441 | { | ||
442 | set_tracing_events_path("tracing/", mntpt); | ||
443 | } | ||
444 | |||
445 | char *get_tracing_file(const char *name) | ||
446 | { | ||
447 | char *file; | ||
448 | |||
449 | if (asprintf(&file, "%s/%s", tracing_path, name) < 0) | ||
450 | return NULL; | ||
451 | |||
452 | return file; | ||
453 | } | ||
454 | |||
455 | void put_tracing_file(char *file) | ||
456 | { | ||
457 | free(file); | ||
458 | } | ||
459 | |||
460 | int parse_nsec_time(const char *str, u64 *ptime) | 390 | int parse_nsec_time(const char *str, u64 *ptime) |
461 | { | 391 | { |
462 | u64 time_sec, time_nsec; | 392 | u64 time_sec, time_nsec; |
@@ -709,7 +639,7 @@ bool find_process(const char *name) | |||
709 | 639 | ||
710 | dir = opendir(procfs__mountpoint()); | 640 | dir = opendir(procfs__mountpoint()); |
711 | if (!dir) | 641 | if (!dir) |
712 | return -1; | 642 | return false; |
713 | 643 | ||
714 | /* Walk through the directory. */ | 644 | /* Walk through the directory. */ |
715 | while (ret && (d = readdir(dir)) != NULL) { | 645 | while (ret && (d = readdir(dir)) != NULL) { |
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 291be1d84bc3..4cfb913aa9e0 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -74,8 +74,7 @@ | |||
74 | #include <linux/magic.h> | 74 | #include <linux/magic.h> |
75 | #include <linux/types.h> | 75 | #include <linux/types.h> |
76 | #include <sys/ttydefaults.h> | 76 | #include <sys/ttydefaults.h> |
77 | #include <api/fs/debugfs.h> | 77 | #include <api/fs/tracing_path.h> |
78 | #include <api/fs/tracefs.h> | ||
79 | #include <termios.h> | 78 | #include <termios.h> |
80 | #include <linux/bitops.h> | 79 | #include <linux/bitops.h> |
81 | #include <termios.h> | 80 | #include <termios.h> |
@@ -83,12 +82,6 @@ | |||
83 | extern const char *graph_line; | 82 | extern const char *graph_line; |
84 | extern const char *graph_dotted_line; | 83 | extern const char *graph_dotted_line; |
85 | extern char buildid_dir[]; | 84 | extern char buildid_dir[]; |
86 | extern char tracing_path[]; | ||
87 | extern char tracing_events_path[]; | ||
88 | extern void perf_debugfs_set_path(const char *mountpoint); | ||
89 | const char *perf_debugfs_mount(const char *mountpoint); | ||
90 | char *get_tracing_file(const char *name); | ||
91 | void put_tracing_file(char *file); | ||
92 | 85 | ||
93 | /* On most systems <limits.h> would have given us this, but | 86 | /* On most systems <limits.h> would have given us this, but |
94 | * not on some systems (e.g. GNU/Hurd). | 87 | * not on some systems (e.g. GNU/Hurd). |
@@ -152,6 +145,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))) | |||
152 | 145 | ||
153 | 146 | ||
154 | extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); | 147 | extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); |
148 | extern void set_warning_routine(void (*routine)(const char *err, va_list params)); | ||
155 | 149 | ||
156 | extern int prefixcmp(const char *str, const char *prefix); | 150 | extern int prefixcmp(const char *str, const char *prefix); |
157 | extern void set_buildid_dir(const char *dir); | 151 | extern void set_buildid_dir(const char *dir); |
@@ -321,6 +315,8 @@ struct symbol; | |||
321 | extern bool srcline_full_filename; | 315 | extern bool srcline_full_filename; |
322 | char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, | 316 | char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, |
323 | bool show_sym); | 317 | bool show_sym); |
318 | char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, | ||
319 | bool show_sym, bool unwind_inlines); | ||
324 | void free_srcline(char *srcline); | 320 | void free_srcline(char *srcline); |
325 | 321 | ||
326 | int filename__read_str(const char *filename, char **buf, size_t *sizep); | 322 | int filename__read_str(const char *filename, char **buf, size_t *sizep); |