diff options
author | Ingo Molnar <mingo@kernel.org> | 2017-07-01 04:39:25 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-07-01 04:39:25 -0400 |
commit | 23acd3e1a0a377cf3730ccb753aa1fdc50378396 (patch) | |
tree | a80d7cfd2be43d77af659d5f309a5032be5e0662 /tools/perf | |
parent | e91c8d97eac74e603481840d950536bcb62b471b (diff) | |
parent | 644e0840ad4615e032d67adec6ee60f821b669fe (diff) |
Merge tag 'perf-core-for-mingo-4.13-20170630' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
Intel PT enhancements:
- Support "ptwrite" instruction, a way to stuff 32 or 64 bit values into
the Intel PT trace (Adrian Hunter)
- Support power events in Intel PT to report changes to C-state (Adrian
Hunter)
- Synthesize Intel PT events as PERF_RECORD_SAMPLE records with a
perf_event_attr.type (PERF_TYPE_SYNTH) just after the range used by the
kernel, i.e. right after what is allocated for PMUs, at INT_MAX + 1U,
attr.config will have the identification for the synthesized event and
the PERF_SAMPLE_RAW payload will have its fields (Adrian Hunter)
Infrastructure changes:
- Remove warning() and error(), using instead pr_warning() and
pr_error(), consolidating error reporting (Arnaldo Carvalho de Melo)
- Add platform dependency to 'perf test 15' (Thomas Richter)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
37 files changed, 1197 insertions, 361 deletions
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt index d157dee7a4ec..4b6cdbf8f935 100644 --- a/tools/perf/Documentation/intel-pt.txt +++ b/tools/perf/Documentation/intel-pt.txt | |||
@@ -108,6 +108,9 @@ approach is available to export the data to a postgresql database. Refer to | |||
108 | script export-to-postgresql.py for more details, and to script | 108 | script export-to-postgresql.py for more details, and to script |
109 | call-graph-from-postgresql.py for an example of using the database. | 109 | call-graph-from-postgresql.py for an example of using the database. |
110 | 110 | ||
111 | There is also script intel-pt-events.py which provides an example of how to | ||
112 | unpack the raw data for power events and PTWRITE. | ||
113 | |||
111 | As mentioned above, it is easy to capture too much data. One way to limit the | 114 | As mentioned above, it is easy to capture too much data. One way to limit the |
112 | data captured is to use 'snapshot' mode which is explained further below. | 115 | data captured is to use 'snapshot' mode which is explained further below. |
113 | Refer to 'new snapshot option' and 'Intel PT modes of operation' further below. | 116 | Refer to 'new snapshot option' and 'Intel PT modes of operation' further below. |
@@ -710,13 +713,15 @@ Having no option is the same as | |||
710 | 713 | ||
711 | which, in turn, is the same as | 714 | which, in turn, is the same as |
712 | 715 | ||
713 | --itrace=ibxe | 716 | --itrace=ibxwpe |
714 | 717 | ||
715 | The letters are: | 718 | The letters are: |
716 | 719 | ||
717 | i synthesize "instructions" events | 720 | i synthesize "instructions" events |
718 | b synthesize "branches" events | 721 | b synthesize "branches" events |
719 | x synthesize "transactions" events | 722 | x synthesize "transactions" events |
723 | w synthesize "ptwrite" events | ||
724 | p synthesize "power" events | ||
720 | c synthesize branches events (calls only) | 725 | c synthesize branches events (calls only) |
721 | r synthesize branches events (returns only) | 726 | r synthesize branches events (returns only) |
722 | e synthesize tracing error events | 727 | e synthesize tracing error events |
@@ -735,7 +740,40 @@ and "r" can be combined to get calls and returns. | |||
735 | 'flags' field can be used in perf script to determine whether the event is a | 740 | 'flags' field can be used in perf script to determine whether the event is a |
736 | tranasaction start, commit or abort. | 741 | tranasaction start, commit or abort. |
737 | 742 | ||
738 | Error events are new. They show where the decoder lost the trace. Error events | 743 | Note that "instructions", "branches" and "transactions" events depend on code |
744 | flow packets which can be disabled by using the config term "branch=0". Refer | ||
745 | to the config terms section above. | ||
746 | |||
747 | "ptwrite" events record the payload of the ptwrite instruction and whether | ||
748 | "fup_on_ptw" was used. "ptwrite" events depend on PTWRITE packets which are | ||
749 | recorded only if the "ptw" config term was used. Refer to the config terms | ||
750 | section above. perf script "synth" field displays "ptwrite" information like | ||
751 | this: "ip: 0 payload: 0x123456789abcdef0" where "ip" is 1 if "fup_on_ptw" was | ||
752 | used. | ||
753 | |||
754 | "Power" events correspond to power event packets and CBR (core-to-bus ratio) | ||
755 | packets. While CBR packets are always recorded when tracing is enabled, power | ||
756 | event packets are recorded only if the "pwr_evt" config term was used. Refer to | ||
757 | the config terms section above. The power events record information about | ||
758 | C-state changes, whereas CBR is indicative of CPU frequency. perf script | ||
759 | "event,synth" fields display information like this: | ||
760 | cbr: cbr: 22 freq: 2189 MHz (200%) | ||
761 | mwait: hints: 0x60 extensions: 0x1 | ||
762 | pwre: hw: 0 cstate: 2 sub-cstate: 0 | ||
763 | exstop: ip: 1 | ||
764 | pwrx: deepest cstate: 2 last cstate: 2 wake reason: 0x4 | ||
765 | Where: | ||
766 | "cbr" includes the frequency and the percentage of maximum non-turbo | ||
767 | "mwait" shows mwait hints and extensions | ||
768 | "pwre" shows C-state transitions (to a C-state deeper than C0) and | ||
769 | whether initiated by hardware | ||
770 | "exstop" indicates execution stopped and whether the IP was recorded | ||
771 | exactly, | ||
772 | "pwrx" indicates return to C0 | ||
773 | For more details refer to the Intel 64 and IA-32 Architectures Software | ||
774 | Developer Manuals. | ||
775 | |||
776 | Error events show where the decoder lost the trace. Error events | ||
739 | are quite important. Users must know if what they are seeing is a complete | 777 | are quite important. Users must know if what they are seeing is a complete |
740 | picture or not. | 778 | picture or not. |
741 | 779 | ||
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt index e2a4c5e0dbe5..a3abe04c779d 100644 --- a/tools/perf/Documentation/itrace.txt +++ b/tools/perf/Documentation/itrace.txt | |||
@@ -3,13 +3,15 @@ | |||
3 | c synthesize branches events (calls only) | 3 | c synthesize branches events (calls only) |
4 | r synthesize branches events (returns only) | 4 | r synthesize branches events (returns only) |
5 | x synthesize transactions events | 5 | x synthesize transactions events |
6 | w synthesize ptwrite events | ||
7 | p synthesize power events | ||
6 | e synthesize error events | 8 | e synthesize error events |
7 | d create a debug log | 9 | d create a debug log |
8 | g synthesize a call chain (use with i or x) | 10 | g synthesize a call chain (use with i or x) |
9 | l synthesize last branch entries (use with i or x) | 11 | l synthesize last branch entries (use with i or x) |
10 | s skip initial number of events | 12 | s skip initial number of events |
11 | 13 | ||
12 | The default is all events i.e. the same as --itrace=ibxe | 14 | The default is all events i.e. the same as --itrace=ibxwpe |
13 | 15 | ||
14 | In addition, the period (default 100000) for instructions events | 16 | In addition, the period (default 100000) for instructions events |
15 | can be specified in units of: | 17 | can be specified in units of: |
@@ -26,8 +28,8 @@ | |||
26 | Also the number of last branch entries (default 64, max. 1024) for | 28 | Also the number of last branch entries (default 64, max. 1024) for |
27 | instructions or transactions events can be specified. | 29 | instructions or transactions events can be specified. |
28 | 30 | ||
29 | It is also possible to skip events generated (instructions, branches, transactions) | 31 | It is also possible to skip events generated (instructions, branches, transactions, |
30 | at the beginning. This is useful to ignore initialization code. | 32 | ptwrite, power) at the beginning. This is useful to ignore initialization code. |
31 | 33 | ||
32 | --itrace=i0nss1000000 | 34 | --itrace=i0nss1000000 |
33 | 35 | ||
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index e2468ed6a307..5ee8796be96e 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt | |||
@@ -117,7 +117,8 @@ OPTIONS | |||
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, brstack, brstacksym, flags, bpf-output, brstackinsn, brstackoff, | 119 | srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn, brstackoff, |
120 | callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw, | 120 | callindent, insn, insnlen, synth. |
121 | Field list can be prepended with the type, trace, sw or hw, | ||
121 | to indicate to which event type the field list applies. | 122 | 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 | 123 | e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace |
123 | 124 | ||
@@ -193,6 +194,9 @@ OPTIONS | |||
193 | instruction bytes and the instruction length of the current | 194 | instruction bytes and the instruction length of the current |
194 | instruction. | 195 | instruction. |
195 | 196 | ||
197 | The synth field is used by synthesized events which may be created when | ||
198 | Instruction Trace decoding. | ||
199 | |||
196 | Finally, a user may not set fields to none for all event types. | 200 | Finally, a user may not set fields to none for all event types. |
197 | i.e., -F "" is not allowed. | 201 | i.e., -F "" is not allowed. |
198 | 202 | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-32.c b/tools/perf/arch/x86/tests/insn-x86-dat-32.c index 0f196eec9f48..3cbf6fad169f 100644 --- a/tools/perf/arch/x86/tests/insn-x86-dat-32.c +++ b/tools/perf/arch/x86/tests/insn-x86-dat-32.c | |||
@@ -1664,3 +1664,15 @@ | |||
1664 | "0f c7 1d 78 56 34 12 \txrstors 0x12345678",}, | 1664 | "0f c7 1d 78 56 34 12 \txrstors 0x12345678",}, |
1665 | {{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | 1665 | {{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", |
1666 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",}, | 1666 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",}, |
1667 | {{0xf3, 0x0f, 0xae, 0x20, }, 4, 0, "", "", | ||
1668 | "f3 0f ae 20 \tptwritel (%eax)",}, | ||
1669 | {{0xf3, 0x0f, 0xae, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
1670 | "f3 0f ae 25 78 56 34 12 \tptwritel 0x12345678",}, | ||
1671 | {{0xf3, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
1672 | "f3 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%eax,%ecx,8)",}, | ||
1673 | {{0xf3, 0x0f, 0xae, 0x20, }, 4, 0, "", "", | ||
1674 | "f3 0f ae 20 \tptwritel (%eax)",}, | ||
1675 | {{0xf3, 0x0f, 0xae, 0x25, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", | ||
1676 | "f3 0f ae 25 78 56 34 12 \tptwritel 0x12345678",}, | ||
1677 | {{0xf3, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
1678 | "f3 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%eax,%ecx,8)",}, | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-64.c b/tools/perf/arch/x86/tests/insn-x86-dat-64.c index af25bc8240d0..aa512fa944dd 100644 --- a/tools/perf/arch/x86/tests/insn-x86-dat-64.c +++ b/tools/perf/arch/x86/tests/insn-x86-dat-64.c | |||
@@ -1696,3 +1696,33 @@ | |||
1696 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",}, | 1696 | "0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",}, |
1697 | {{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | 1697 | {{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", |
1698 | "41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",}, | 1698 | "41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",}, |
1699 | {{0xf3, 0x0f, 0xae, 0x20, }, 4, 0, "", "", | ||
1700 | "f3 0f ae 20 \tptwritel (%rax)",}, | ||
1701 | {{0xf3, 0x41, 0x0f, 0xae, 0x20, }, 5, 0, "", "", | ||
1702 | "f3 41 0f ae 20 \tptwritel (%r8)",}, | ||
1703 | {{0xf3, 0x0f, 0xae, 0x24, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
1704 | "f3 0f ae 24 25 78 56 34 12 \tptwritel 0x12345678",}, | ||
1705 | {{0xf3, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
1706 | "f3 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%rax,%rcx,8)",}, | ||
1707 | {{0xf3, 0x41, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
1708 | "f3 41 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%r8,%rcx,8)",}, | ||
1709 | {{0xf3, 0x0f, 0xae, 0x20, }, 4, 0, "", "", | ||
1710 | "f3 0f ae 20 \tptwritel (%rax)",}, | ||
1711 | {{0xf3, 0x41, 0x0f, 0xae, 0x20, }, 5, 0, "", "", | ||
1712 | "f3 41 0f ae 20 \tptwritel (%r8)",}, | ||
1713 | {{0xf3, 0x0f, 0xae, 0x24, 0x25, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
1714 | "f3 0f ae 24 25 78 56 34 12 \tptwritel 0x12345678",}, | ||
1715 | {{0xf3, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", | ||
1716 | "f3 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%rax,%rcx,8)",}, | ||
1717 | {{0xf3, 0x41, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
1718 | "f3 41 0f ae a4 c8 78 56 34 12 \tptwritel 0x12345678(%r8,%rcx,8)",}, | ||
1719 | {{0xf3, 0x48, 0x0f, 0xae, 0x20, }, 5, 0, "", "", | ||
1720 | "f3 48 0f ae 20 \tptwriteq (%rax)",}, | ||
1721 | {{0xf3, 0x49, 0x0f, 0xae, 0x20, }, 5, 0, "", "", | ||
1722 | "f3 49 0f ae 20 \tptwriteq (%r8)",}, | ||
1723 | {{0xf3, 0x48, 0x0f, 0xae, 0x24, 0x25, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
1724 | "f3 48 0f ae 24 25 78 56 34 12 \tptwriteq 0x12345678",}, | ||
1725 | {{0xf3, 0x48, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
1726 | "f3 48 0f ae a4 c8 78 56 34 12 \tptwriteq 0x12345678(%rax,%rcx,8)",}, | ||
1727 | {{0xf3, 0x49, 0x0f, 0xae, 0xa4, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 10, 0, "", "", | ||
1728 | "f3 49 0f ae a4 c8 78 56 34 12 \tptwriteq 0x12345678(%r8,%rcx,8)",}, | ||
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-src.c b/tools/perf/arch/x86/tests/insn-x86-dat-src.c index 979487dae8d4..6cdb65d25b79 100644 --- a/tools/perf/arch/x86/tests/insn-x86-dat-src.c +++ b/tools/perf/arch/x86/tests/insn-x86-dat-src.c | |||
@@ -1343,6 +1343,26 @@ int main(void) | |||
1343 | asm volatile("xrstors 0x12345678(%rax,%rcx,8)"); | 1343 | asm volatile("xrstors 0x12345678(%rax,%rcx,8)"); |
1344 | asm volatile("xrstors 0x12345678(%r8,%rcx,8)"); | 1344 | asm volatile("xrstors 0x12345678(%r8,%rcx,8)"); |
1345 | 1345 | ||
1346 | /* ptwrite */ | ||
1347 | |||
1348 | asm volatile("ptwrite (%rax)"); | ||
1349 | asm volatile("ptwrite (%r8)"); | ||
1350 | asm volatile("ptwrite (0x12345678)"); | ||
1351 | asm volatile("ptwrite 0x12345678(%rax,%rcx,8)"); | ||
1352 | asm volatile("ptwrite 0x12345678(%r8,%rcx,8)"); | ||
1353 | |||
1354 | asm volatile("ptwritel (%rax)"); | ||
1355 | asm volatile("ptwritel (%r8)"); | ||
1356 | asm volatile("ptwritel (0x12345678)"); | ||
1357 | asm volatile("ptwritel 0x12345678(%rax,%rcx,8)"); | ||
1358 | asm volatile("ptwritel 0x12345678(%r8,%rcx,8)"); | ||
1359 | |||
1360 | asm volatile("ptwriteq (%rax)"); | ||
1361 | asm volatile("ptwriteq (%r8)"); | ||
1362 | asm volatile("ptwriteq (0x12345678)"); | ||
1363 | asm volatile("ptwriteq 0x12345678(%rax,%rcx,8)"); | ||
1364 | asm volatile("ptwriteq 0x12345678(%r8,%rcx,8)"); | ||
1365 | |||
1346 | #else /* #ifdef __x86_64__ */ | 1366 | #else /* #ifdef __x86_64__ */ |
1347 | 1367 | ||
1348 | /* bound r32, mem (same op code as EVEX prefix) */ | 1368 | /* bound r32, mem (same op code as EVEX prefix) */ |
@@ -2653,6 +2673,16 @@ int main(void) | |||
2653 | asm volatile("xrstors (0x12345678)"); | 2673 | asm volatile("xrstors (0x12345678)"); |
2654 | asm volatile("xrstors 0x12345678(%eax,%ecx,8)"); | 2674 | asm volatile("xrstors 0x12345678(%eax,%ecx,8)"); |
2655 | 2675 | ||
2676 | /* ptwrite */ | ||
2677 | |||
2678 | asm volatile("ptwrite (%eax)"); | ||
2679 | asm volatile("ptwrite (0x12345678)"); | ||
2680 | asm volatile("ptwrite 0x12345678(%eax,%ecx,8)"); | ||
2681 | |||
2682 | asm volatile("ptwritel (%eax)"); | ||
2683 | asm volatile("ptwritel (0x12345678)"); | ||
2684 | asm volatile("ptwritel 0x12345678(%eax,%ecx,8)"); | ||
2685 | |||
2656 | #endif /* #ifndef __x86_64__ */ | 2686 | #endif /* #ifndef __x86_64__ */ |
2657 | 2687 | ||
2658 | /* Following line is a marker for the awk script - do not change */ | 2688 | /* Following line is a marker for the awk script - do not change */ |
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 620a467ee304..475999e48f66 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c | |||
@@ -1725,10 +1725,10 @@ static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name) | |||
1725 | tok; tok = strtok_r(NULL, ", ", &tmp)) { \ | 1725 | tok; tok = strtok_r(NULL, ", ", &tmp)) { \ |
1726 | ret = _fn(hpp_list, tok); \ | 1726 | ret = _fn(hpp_list, tok); \ |
1727 | if (ret == -EINVAL) { \ | 1727 | if (ret == -EINVAL) { \ |
1728 | error("Invalid --fields key: `%s'", tok); \ | 1728 | pr_err("Invalid --fields key: `%s'", tok); \ |
1729 | break; \ | 1729 | break; \ |
1730 | } else if (ret == -ESRCH) { \ | 1730 | } else if (ret == -ESRCH) { \ |
1731 | error("Unknown --fields key: `%s'", tok); \ | 1731 | pr_err("Unknown --fields key: `%s'", tok); \ |
1732 | break; \ | 1732 | break; \ |
1733 | } \ | 1733 | } \ |
1734 | } \ | 1734 | } \ |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index eec5df80f5a3..0cd4cf6a344b 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -1302,7 +1302,10 @@ static int diff__config(const char *var, const char *value, | |||
1302 | void *cb __maybe_unused) | 1302 | void *cb __maybe_unused) |
1303 | { | 1303 | { |
1304 | if (!strcmp(var, "diff.order")) { | 1304 | if (!strcmp(var, "diff.order")) { |
1305 | sort_compute = perf_config_int(var, value); | 1305 | int ret; |
1306 | if (perf_config_int(&ret, var, value) < 0) | ||
1307 | return -1; | ||
1308 | sort_compute = ret; | ||
1306 | return 0; | 1309 | return 0; |
1307 | } | 1310 | } |
1308 | if (!strcmp(var, "diff.compute")) { | 1311 | if (!strcmp(var, "diff.compute")) { |
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 492f8e14ab09..530a7f2fa0f3 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c | |||
@@ -108,10 +108,14 @@ out: | |||
108 | return ret; | 108 | return ret; |
109 | } | 109 | } |
110 | 110 | ||
111 | static void exec_woman_emacs(const char *path, const char *page) | 111 | static void exec_failed(const char *cmd) |
112 | { | 112 | { |
113 | char sbuf[STRERR_BUFSIZE]; | 113 | char sbuf[STRERR_BUFSIZE]; |
114 | pr_warning("failed to exec '%s': %s", cmd, str_error_r(errno, sbuf, sizeof(sbuf))); | ||
115 | } | ||
114 | 116 | ||
117 | static void exec_woman_emacs(const char *path, const char *page) | ||
118 | { | ||
115 | if (!check_emacsclient_version()) { | 119 | if (!check_emacsclient_version()) { |
116 | /* This works only with emacsclient version >= 22. */ | 120 | /* This works only with emacsclient version >= 22. */ |
117 | char *man_page; | 121 | char *man_page; |
@@ -122,8 +126,7 @@ static void exec_woman_emacs(const char *path, const char *page) | |||
122 | execlp(path, "emacsclient", "-e", man_page, NULL); | 126 | execlp(path, "emacsclient", "-e", man_page, NULL); |
123 | free(man_page); | 127 | free(man_page); |
124 | } | 128 | } |
125 | warning("failed to exec '%s': %s", path, | 129 | exec_failed(path); |
126 | str_error_r(errno, sbuf, sizeof(sbuf))); | ||
127 | } | 130 | } |
128 | } | 131 | } |
129 | 132 | ||
@@ -134,7 +137,6 @@ static void exec_man_konqueror(const char *path, const char *page) | |||
134 | if (display && *display) { | 137 | if (display && *display) { |
135 | char *man_page; | 138 | char *man_page; |
136 | const char *filename = "kfmclient"; | 139 | const char *filename = "kfmclient"; |
137 | char sbuf[STRERR_BUFSIZE]; | ||
138 | 140 | ||
139 | /* It's simpler to launch konqueror using kfmclient. */ | 141 | /* It's simpler to launch konqueror using kfmclient. */ |
140 | if (path) { | 142 | if (path) { |
@@ -155,33 +157,27 @@ static void exec_man_konqueror(const char *path, const char *page) | |||
155 | execlp(path, filename, "newTab", man_page, NULL); | 157 | execlp(path, filename, "newTab", man_page, NULL); |
156 | free(man_page); | 158 | free(man_page); |
157 | } | 159 | } |
158 | warning("failed to exec '%s': %s", path, | 160 | exec_failed(path); |
159 | str_error_r(errno, sbuf, sizeof(sbuf))); | ||
160 | } | 161 | } |
161 | } | 162 | } |
162 | 163 | ||
163 | static void exec_man_man(const char *path, const char *page) | 164 | static void exec_man_man(const char *path, const char *page) |
164 | { | 165 | { |
165 | char sbuf[STRERR_BUFSIZE]; | ||
166 | |||
167 | if (!path) | 166 | if (!path) |
168 | path = "man"; | 167 | path = "man"; |
169 | execlp(path, "man", page, NULL); | 168 | execlp(path, "man", page, NULL); |
170 | warning("failed to exec '%s': %s", path, | 169 | exec_failed(path); |
171 | str_error_r(errno, sbuf, sizeof(sbuf))); | ||
172 | } | 170 | } |
173 | 171 | ||
174 | static void exec_man_cmd(const char *cmd, const char *page) | 172 | static void exec_man_cmd(const char *cmd, const char *page) |
175 | { | 173 | { |
176 | char sbuf[STRERR_BUFSIZE]; | ||
177 | char *shell_cmd; | 174 | char *shell_cmd; |
178 | 175 | ||
179 | if (asprintf(&shell_cmd, "%s %s", cmd, page) > 0) { | 176 | if (asprintf(&shell_cmd, "%s %s", cmd, page) > 0) { |
180 | execl("/bin/sh", "sh", "-c", shell_cmd, NULL); | 177 | execl("/bin/sh", "sh", "-c", shell_cmd, NULL); |
181 | free(shell_cmd); | 178 | free(shell_cmd); |
182 | } | 179 | } |
183 | warning("failed to exec '%s': %s", cmd, | 180 | exec_failed(cmd); |
184 | str_error_r(errno, sbuf, sizeof(sbuf))); | ||
185 | } | 181 | } |
186 | 182 | ||
187 | static void add_man_viewer(const char *name) | 183 | static void add_man_viewer(const char *name) |
@@ -214,6 +210,12 @@ static void do_add_man_viewer_info(const char *name, | |||
214 | man_viewer_info_list = new; | 210 | man_viewer_info_list = new; |
215 | } | 211 | } |
216 | 212 | ||
213 | static void unsupported_man_viewer(const char *name, const char *var) | ||
214 | { | ||
215 | pr_warning("'%s': path for unsupported man viewer.\n" | ||
216 | "Please consider using 'man.<tool>.%s' instead.", name, var); | ||
217 | } | ||
218 | |||
217 | static int add_man_viewer_path(const char *name, | 219 | static int add_man_viewer_path(const char *name, |
218 | size_t len, | 220 | size_t len, |
219 | const char *value) | 221 | const char *value) |
@@ -221,9 +223,7 @@ static int add_man_viewer_path(const char *name, | |||
221 | if (supported_man_viewer(name, len)) | 223 | if (supported_man_viewer(name, len)) |
222 | do_add_man_viewer_info(name, len, value); | 224 | do_add_man_viewer_info(name, len, value); |
223 | else | 225 | else |
224 | warning("'%s': path for unsupported man viewer.\n" | 226 | unsupported_man_viewer(name, "cmd"); |
225 | "Please consider using 'man.<tool>.cmd' instead.", | ||
226 | name); | ||
227 | 227 | ||
228 | return 0; | 228 | return 0; |
229 | } | 229 | } |
@@ -233,9 +233,7 @@ static int add_man_viewer_cmd(const char *name, | |||
233 | const char *value) | 233 | const char *value) |
234 | { | 234 | { |
235 | if (supported_man_viewer(name, len)) | 235 | if (supported_man_viewer(name, len)) |
236 | warning("'%s': cmd for supported man viewer.\n" | 236 | unsupported_man_viewer(name, "path"); |
237 | "Please consider using 'man.<tool>.path' instead.", | ||
238 | name); | ||
239 | else | 237 | else |
240 | do_add_man_viewer_info(name, len, value); | 238 | do_add_man_viewer_info(name, len, value); |
241 | 239 | ||
@@ -247,8 +245,10 @@ static int add_man_viewer_info(const char *var, const char *value) | |||
247 | const char *name = var + 4; | 245 | const char *name = var + 4; |
248 | const char *subkey = strrchr(name, '.'); | 246 | const char *subkey = strrchr(name, '.'); |
249 | 247 | ||
250 | if (!subkey) | 248 | if (!subkey) { |
251 | return error("Config with no key for man viewer: %s", name); | 249 | pr_err("Config with no key for man viewer: %s", name); |
250 | return -1; | ||
251 | } | ||
252 | 252 | ||
253 | if (!strcmp(subkey, ".path")) { | 253 | if (!strcmp(subkey, ".path")) { |
254 | if (!value) | 254 | if (!value) |
@@ -261,7 +261,7 @@ static int add_man_viewer_info(const char *var, const char *value) | |||
261 | return add_man_viewer_cmd(name, subkey - name, value); | 261 | return add_man_viewer_cmd(name, subkey - name, value); |
262 | } | 262 | } |
263 | 263 | ||
264 | warning("'%s': unsupported man viewer sub key.", subkey); | 264 | pr_warning("'%s': unsupported man viewer sub key.", subkey); |
265 | return 0; | 265 | return 0; |
266 | } | 266 | } |
267 | 267 | ||
@@ -332,7 +332,7 @@ static void setup_man_path(void) | |||
332 | setenv("MANPATH", new_path, 1); | 332 | setenv("MANPATH", new_path, 1); |
333 | free(new_path); | 333 | free(new_path); |
334 | } else { | 334 | } else { |
335 | error("Unable to setup man path"); | 335 | pr_err("Unable to setup man path"); |
336 | } | 336 | } |
337 | } | 337 | } |
338 | 338 | ||
@@ -349,7 +349,7 @@ static void exec_viewer(const char *name, const char *page) | |||
349 | else if (info) | 349 | else if (info) |
350 | exec_man_cmd(info, page); | 350 | exec_man_cmd(info, page); |
351 | else | 351 | else |
352 | warning("'%s': unknown man viewer.", name); | 352 | pr_warning("'%s': unknown man viewer.", name); |
353 | } | 353 | } |
354 | 354 | ||
355 | static int show_man_page(const char *perf_cmd) | 355 | static int show_man_page(const char *perf_cmd) |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 9409c9464667..0a8a1c45af87 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -1715,7 +1715,7 @@ static int setup_slab_sorting(struct list_head *sort_list, const char *arg) | |||
1715 | if (!tok) | 1715 | if (!tok) |
1716 | break; | 1716 | break; |
1717 | if (slab_sort_dimension__add(tok, sort_list) < 0) { | 1717 | if (slab_sort_dimension__add(tok, sort_list) < 0) { |
1718 | error("Unknown slab --sort key: '%s'", tok); | 1718 | pr_err("Unknown slab --sort key: '%s'", tok); |
1719 | free(str); | 1719 | free(str); |
1720 | return -1; | 1720 | return -1; |
1721 | } | 1721 | } |
@@ -1741,7 +1741,7 @@ static int setup_page_sorting(struct list_head *sort_list, const char *arg) | |||
1741 | if (!tok) | 1741 | if (!tok) |
1742 | break; | 1742 | break; |
1743 | if (page_sort_dimension__add(tok, sort_list) < 0) { | 1743 | if (page_sort_dimension__add(tok, sort_list) < 0) { |
1744 | error("Unknown page --sort key: '%s'", tok); | 1744 | pr_err("Unknown page --sort key: '%s'", tok); |
1745 | free(str); | 1745 | free(str); |
1746 | return -1; | 1746 | return -1; |
1747 | } | 1747 | } |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index ee7d0a82ccd0..17a14bcce34a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -453,7 +453,7 @@ try_again: | |||
453 | } | 453 | } |
454 | 454 | ||
455 | if (perf_evlist__apply_filters(evlist, &pos)) { | 455 | if (perf_evlist__apply_filters(evlist, &pos)) { |
456 | error("failed to set filter \"%s\" on event %s with %d (%s)\n", | 456 | pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", |
457 | pos->filter, perf_evsel__name(pos), errno, | 457 | pos->filter, perf_evsel__name(pos), errno, |
458 | str_error_r(errno, msg, sizeof(msg))); | 458 | str_error_r(errno, msg, sizeof(msg))); |
459 | rc = -1; | 459 | rc = -1; |
@@ -461,7 +461,7 @@ try_again: | |||
461 | } | 461 | } |
462 | 462 | ||
463 | if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) { | 463 | if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) { |
464 | error("failed to set config \"%s\" on event %s with %d (%s)\n", | 464 | pr_err("failed to set config \"%s\" on event %s with %d (%s)\n", |
465 | err_term->val.drv_cfg, perf_evsel__name(pos), errno, | 465 | err_term->val.drv_cfg, perf_evsel__name(pos), errno, |
466 | str_error_r(errno, msg, sizeof(msg))); | 466 | str_error_r(errno, msg, sizeof(msg))); |
467 | rc = -1; | 467 | rc = -1; |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 22478ff2b706..79a33eb1a10d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -94,10 +94,9 @@ static int report__config(const char *var, const char *value, void *cb) | |||
94 | symbol_conf.cumulate_callchain = perf_config_bool(var, value); | 94 | symbol_conf.cumulate_callchain = perf_config_bool(var, value); |
95 | return 0; | 95 | return 0; |
96 | } | 96 | } |
97 | if (!strcmp(var, "report.queue-size")) { | 97 | if (!strcmp(var, "report.queue-size")) |
98 | rep->queue_size = perf_config_u64(var, value); | 98 | return perf_config_u64(&rep->queue_size, var, value); |
99 | return 0; | 99 | |
100 | } | ||
101 | if (!strcmp(var, "report.sort_order")) { | 100 | if (!strcmp(var, "report.sort_order")) { |
102 | default_sort_order = strdup(value); | 101 | default_sort_order = strdup(value); |
103 | return 0; | 102 | return 0; |
@@ -558,6 +557,7 @@ static int __cmd_report(struct report *rep) | |||
558 | ui__error("failed to set cpu bitmap\n"); | 557 | ui__error("failed to set cpu bitmap\n"); |
559 | return ret; | 558 | return ret; |
560 | } | 559 | } |
560 | session->itrace_synth_opts->cpu_bitmap = rep->cpu_bitmap; | ||
561 | } | 561 | } |
562 | 562 | ||
563 | if (rep->show_threads) { | 563 | if (rep->show_threads) { |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 39996c53995a..322b4def8411 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -2066,7 +2066,7 @@ static void save_task_callchain(struct perf_sched *sched, | |||
2066 | if (thread__resolve_callchain(thread, cursor, evsel, sample, | 2066 | if (thread__resolve_callchain(thread, cursor, evsel, sample, |
2067 | NULL, NULL, sched->max_stack + 2) != 0) { | 2067 | NULL, NULL, sched->max_stack + 2) != 0) { |
2068 | if (verbose > 0) | 2068 | if (verbose > 0) |
2069 | error("Failed to resolve callchain. Skipping\n"); | 2069 | pr_err("Failed to resolve callchain. Skipping\n"); |
2070 | 2070 | ||
2071 | return; | 2071 | return; |
2072 | } | 2072 | } |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 4bce7d8679cb..83cdc0a61fd6 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -86,6 +86,7 @@ enum perf_output_field { | |||
86 | PERF_OUTPUT_INSNLEN = 1U << 22, | 86 | PERF_OUTPUT_INSNLEN = 1U << 22, |
87 | PERF_OUTPUT_BRSTACKINSN = 1U << 23, | 87 | PERF_OUTPUT_BRSTACKINSN = 1U << 23, |
88 | PERF_OUTPUT_BRSTACKOFF = 1U << 24, | 88 | PERF_OUTPUT_BRSTACKOFF = 1U << 24, |
89 | PERF_OUTPUT_SYNTH = 1U << 25, | ||
89 | }; | 90 | }; |
90 | 91 | ||
91 | struct output_option { | 92 | struct output_option { |
@@ -117,6 +118,12 @@ struct output_option { | |||
117 | {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN}, | 118 | {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN}, |
118 | {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, | 119 | {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN}, |
119 | {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, | 120 | {.str = "brstackoff", .field = PERF_OUTPUT_BRSTACKOFF}, |
121 | {.str = "synth", .field = PERF_OUTPUT_SYNTH}, | ||
122 | }; | ||
123 | |||
124 | enum { | ||
125 | OUTPUT_TYPE_SYNTH = PERF_TYPE_MAX, | ||
126 | OUTPUT_TYPE_MAX | ||
120 | }; | 127 | }; |
121 | 128 | ||
122 | /* default set to maintain compatibility with current format */ | 129 | /* default set to maintain compatibility with current format */ |
@@ -126,7 +133,7 @@ static struct { | |||
126 | unsigned int print_ip_opts; | 133 | unsigned int print_ip_opts; |
127 | u64 fields; | 134 | u64 fields; |
128 | u64 invalid_fields; | 135 | u64 invalid_fields; |
129 | } output[PERF_TYPE_MAX] = { | 136 | } output[OUTPUT_TYPE_MAX] = { |
130 | 137 | ||
131 | [PERF_TYPE_HARDWARE] = { | 138 | [PERF_TYPE_HARDWARE] = { |
132 | .user_set = false, | 139 | .user_set = false, |
@@ -184,12 +191,44 @@ static struct { | |||
184 | 191 | ||
185 | .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, | 192 | .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, |
186 | }, | 193 | }, |
194 | |||
195 | [OUTPUT_TYPE_SYNTH] = { | ||
196 | .user_set = false, | ||
197 | |||
198 | .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | | ||
199 | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | | ||
200 | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | | ||
201 | PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | | ||
202 | PERF_OUTPUT_SYNTH, | ||
203 | |||
204 | .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, | ||
205 | }, | ||
187 | }; | 206 | }; |
188 | 207 | ||
208 | static inline int output_type(unsigned int type) | ||
209 | { | ||
210 | switch (type) { | ||
211 | case PERF_TYPE_SYNTH: | ||
212 | return OUTPUT_TYPE_SYNTH; | ||
213 | default: | ||
214 | return type; | ||
215 | } | ||
216 | } | ||
217 | |||
218 | static inline unsigned int attr_type(unsigned int type) | ||
219 | { | ||
220 | switch (type) { | ||
221 | case OUTPUT_TYPE_SYNTH: | ||
222 | return PERF_TYPE_SYNTH; | ||
223 | default: | ||
224 | return type; | ||
225 | } | ||
226 | } | ||
227 | |||
189 | static bool output_set_by_user(void) | 228 | static bool output_set_by_user(void) |
190 | { | 229 | { |
191 | int j; | 230 | int j; |
192 | for (j = 0; j < PERF_TYPE_MAX; ++j) { | 231 | for (j = 0; j < OUTPUT_TYPE_MAX; ++j) { |
193 | if (output[j].user_set) | 232 | if (output[j].user_set) |
194 | return true; | 233 | return true; |
195 | } | 234 | } |
@@ -210,7 +249,7 @@ static const char *output_field2str(enum perf_output_field field) | |||
210 | return str; | 249 | return str; |
211 | } | 250 | } |
212 | 251 | ||
213 | #define PRINT_FIELD(x) (output[attr->type].fields & PERF_OUTPUT_##x) | 252 | #define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x) |
214 | 253 | ||
215 | static int perf_evsel__do_check_stype(struct perf_evsel *evsel, | 254 | static int perf_evsel__do_check_stype(struct perf_evsel *evsel, |
216 | u64 sample_type, const char *sample_msg, | 255 | u64 sample_type, const char *sample_msg, |
@@ -218,7 +257,7 @@ static int perf_evsel__do_check_stype(struct perf_evsel *evsel, | |||
218 | bool allow_user_set) | 257 | bool allow_user_set) |
219 | { | 258 | { |
220 | struct perf_event_attr *attr = &evsel->attr; | 259 | struct perf_event_attr *attr = &evsel->attr; |
221 | int type = attr->type; | 260 | int type = output_type(attr->type); |
222 | const char *evname; | 261 | const char *evname; |
223 | 262 | ||
224 | if (attr->sample_type & sample_type) | 263 | if (attr->sample_type & sample_type) |
@@ -348,7 +387,7 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, | |||
348 | 387 | ||
349 | static void set_print_ip_opts(struct perf_event_attr *attr) | 388 | static void set_print_ip_opts(struct perf_event_attr *attr) |
350 | { | 389 | { |
351 | unsigned int type = attr->type; | 390 | unsigned int type = output_type(attr->type); |
352 | 391 | ||
353 | output[type].print_ip_opts = 0; | 392 | output[type].print_ip_opts = 0; |
354 | if (PRINT_FIELD(IP)) | 393 | if (PRINT_FIELD(IP)) |
@@ -376,14 +415,15 @@ static int perf_session__check_output_opt(struct perf_session *session) | |||
376 | unsigned int j; | 415 | unsigned int j; |
377 | struct perf_evsel *evsel; | 416 | struct perf_evsel *evsel; |
378 | 417 | ||
379 | for (j = 0; j < PERF_TYPE_MAX; ++j) { | 418 | for (j = 0; j < OUTPUT_TYPE_MAX; ++j) { |
380 | evsel = perf_session__find_first_evtype(session, j); | 419 | evsel = perf_session__find_first_evtype(session, attr_type(j)); |
381 | 420 | ||
382 | /* | 421 | /* |
383 | * even if fields is set to 0 (ie., show nothing) event must | 422 | * even if fields is set to 0 (ie., show nothing) event must |
384 | * exist if user explicitly includes it on the command line | 423 | * exist if user explicitly includes it on the command line |
385 | */ | 424 | */ |
386 | if (!evsel && output[j].user_set && !output[j].wildcard_set) { | 425 | if (!evsel && output[j].user_set && !output[j].wildcard_set && |
426 | j != OUTPUT_TYPE_SYNTH) { | ||
387 | pr_err("%s events do not exist. " | 427 | pr_err("%s events do not exist. " |
388 | "Remove corresponding -F option to proceed.\n", | 428 | "Remove corresponding -F option to proceed.\n", |
389 | event_type(j)); | 429 | event_type(j)); |
@@ -989,6 +1029,7 @@ static void print_sample_bts(struct perf_sample *sample, | |||
989 | struct machine *machine) | 1029 | struct machine *machine) |
990 | { | 1030 | { |
991 | struct perf_event_attr *attr = &evsel->attr; | 1031 | struct perf_event_attr *attr = &evsel->attr; |
1032 | unsigned int type = output_type(attr->type); | ||
992 | bool print_srcline_last = false; | 1033 | bool print_srcline_last = false; |
993 | 1034 | ||
994 | if (PRINT_FIELD(CALLINDENT)) | 1035 | if (PRINT_FIELD(CALLINDENT)) |
@@ -996,7 +1037,7 @@ static void print_sample_bts(struct perf_sample *sample, | |||
996 | 1037 | ||
997 | /* print branch_from information */ | 1038 | /* print branch_from information */ |
998 | if (PRINT_FIELD(IP)) { | 1039 | if (PRINT_FIELD(IP)) { |
999 | unsigned int print_opts = output[attr->type].print_ip_opts; | 1040 | unsigned int print_opts = output[type].print_ip_opts; |
1000 | struct callchain_cursor *cursor = NULL; | 1041 | struct callchain_cursor *cursor = NULL; |
1001 | 1042 | ||
1002 | if (symbol_conf.use_callchain && sample->callchain && | 1043 | if (symbol_conf.use_callchain && sample->callchain && |
@@ -1019,7 +1060,7 @@ static void print_sample_bts(struct perf_sample *sample, | |||
1019 | /* print branch_to information */ | 1060 | /* print branch_to information */ |
1020 | if (PRINT_FIELD(ADDR) || | 1061 | if (PRINT_FIELD(ADDR) || |
1021 | ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && | 1062 | ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && |
1022 | !output[attr->type].user_set)) { | 1063 | !output[type].user_set)) { |
1023 | printf(" => "); | 1064 | printf(" => "); |
1024 | print_sample_addr(sample, thread, attr); | 1065 | print_sample_addr(sample, thread, attr); |
1025 | } | 1066 | } |
@@ -1162,6 +1203,127 @@ static void print_sample_bpf_output(struct perf_sample *sample) | |||
1162 | (char *)(sample->raw_data)); | 1203 | (char *)(sample->raw_data)); |
1163 | } | 1204 | } |
1164 | 1205 | ||
1206 | static void print_sample_spacing(int len, int spacing) | ||
1207 | { | ||
1208 | if (len > 0 && len < spacing) | ||
1209 | printf("%*s", spacing - len, ""); | ||
1210 | } | ||
1211 | |||
1212 | static void print_sample_pt_spacing(int len) | ||
1213 | { | ||
1214 | print_sample_spacing(len, 34); | ||
1215 | } | ||
1216 | |||
1217 | static void print_sample_synth_ptwrite(struct perf_sample *sample) | ||
1218 | { | ||
1219 | struct perf_synth_intel_ptwrite *data = perf_sample__synth_ptr(sample); | ||
1220 | int len; | ||
1221 | |||
1222 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1223 | return; | ||
1224 | |||
1225 | len = printf(" IP: %u payload: %#" PRIx64 " ", | ||
1226 | data->ip, le64_to_cpu(data->payload)); | ||
1227 | print_sample_pt_spacing(len); | ||
1228 | } | ||
1229 | |||
1230 | static void print_sample_synth_mwait(struct perf_sample *sample) | ||
1231 | { | ||
1232 | struct perf_synth_intel_mwait *data = perf_sample__synth_ptr(sample); | ||
1233 | int len; | ||
1234 | |||
1235 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1236 | return; | ||
1237 | |||
1238 | len = printf(" hints: %#x extensions: %#x ", | ||
1239 | data->hints, data->extensions); | ||
1240 | print_sample_pt_spacing(len); | ||
1241 | } | ||
1242 | |||
1243 | static void print_sample_synth_pwre(struct perf_sample *sample) | ||
1244 | { | ||
1245 | struct perf_synth_intel_pwre *data = perf_sample__synth_ptr(sample); | ||
1246 | int len; | ||
1247 | |||
1248 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1249 | return; | ||
1250 | |||
1251 | len = printf(" hw: %u cstate: %u sub-cstate: %u ", | ||
1252 | data->hw, data->cstate, data->subcstate); | ||
1253 | print_sample_pt_spacing(len); | ||
1254 | } | ||
1255 | |||
1256 | static void print_sample_synth_exstop(struct perf_sample *sample) | ||
1257 | { | ||
1258 | struct perf_synth_intel_exstop *data = perf_sample__synth_ptr(sample); | ||
1259 | int len; | ||
1260 | |||
1261 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1262 | return; | ||
1263 | |||
1264 | len = printf(" IP: %u ", data->ip); | ||
1265 | print_sample_pt_spacing(len); | ||
1266 | } | ||
1267 | |||
1268 | static void print_sample_synth_pwrx(struct perf_sample *sample) | ||
1269 | { | ||
1270 | struct perf_synth_intel_pwrx *data = perf_sample__synth_ptr(sample); | ||
1271 | int len; | ||
1272 | |||
1273 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1274 | return; | ||
1275 | |||
1276 | len = printf(" deepest cstate: %u last cstate: %u wake reason: %#x ", | ||
1277 | data->deepest_cstate, data->last_cstate, | ||
1278 | data->wake_reason); | ||
1279 | print_sample_pt_spacing(len); | ||
1280 | } | ||
1281 | |||
1282 | static void print_sample_synth_cbr(struct perf_sample *sample) | ||
1283 | { | ||
1284 | struct perf_synth_intel_cbr *data = perf_sample__synth_ptr(sample); | ||
1285 | unsigned int percent, freq; | ||
1286 | int len; | ||
1287 | |||
1288 | if (perf_sample__bad_synth_size(sample, *data)) | ||
1289 | return; | ||
1290 | |||
1291 | freq = (le32_to_cpu(data->freq) + 500) / 1000; | ||
1292 | len = printf(" cbr: %2u freq: %4u MHz ", data->cbr, freq); | ||
1293 | if (data->max_nonturbo) { | ||
1294 | percent = (5 + (1000 * data->cbr) / data->max_nonturbo) / 10; | ||
1295 | len += printf("(%3u%%) ", percent); | ||
1296 | } | ||
1297 | print_sample_pt_spacing(len); | ||
1298 | } | ||
1299 | |||
1300 | static void print_sample_synth(struct perf_sample *sample, | ||
1301 | struct perf_evsel *evsel) | ||
1302 | { | ||
1303 | switch (evsel->attr.config) { | ||
1304 | case PERF_SYNTH_INTEL_PTWRITE: | ||
1305 | print_sample_synth_ptwrite(sample); | ||
1306 | break; | ||
1307 | case PERF_SYNTH_INTEL_MWAIT: | ||
1308 | print_sample_synth_mwait(sample); | ||
1309 | break; | ||
1310 | case PERF_SYNTH_INTEL_PWRE: | ||
1311 | print_sample_synth_pwre(sample); | ||
1312 | break; | ||
1313 | case PERF_SYNTH_INTEL_EXSTOP: | ||
1314 | print_sample_synth_exstop(sample); | ||
1315 | break; | ||
1316 | case PERF_SYNTH_INTEL_PWRX: | ||
1317 | print_sample_synth_pwrx(sample); | ||
1318 | break; | ||
1319 | case PERF_SYNTH_INTEL_CBR: | ||
1320 | print_sample_synth_cbr(sample); | ||
1321 | break; | ||
1322 | default: | ||
1323 | break; | ||
1324 | } | ||
1325 | } | ||
1326 | |||
1165 | struct perf_script { | 1327 | struct perf_script { |
1166 | struct perf_tool tool; | 1328 | struct perf_tool tool; |
1167 | struct perf_session *session; | 1329 | struct perf_session *session; |
@@ -1215,8 +1377,9 @@ static void process_event(struct perf_script *script, | |||
1215 | { | 1377 | { |
1216 | struct thread *thread = al->thread; | 1378 | struct thread *thread = al->thread; |
1217 | struct perf_event_attr *attr = &evsel->attr; | 1379 | struct perf_event_attr *attr = &evsel->attr; |
1380 | unsigned int type = output_type(attr->type); | ||
1218 | 1381 | ||
1219 | if (output[attr->type].fields == 0) | 1382 | if (output[type].fields == 0) |
1220 | return; | 1383 | return; |
1221 | 1384 | ||
1222 | print_sample_start(sample, thread, evsel); | 1385 | print_sample_start(sample, thread, evsel); |
@@ -1245,6 +1408,10 @@ static void process_event(struct perf_script *script, | |||
1245 | if (PRINT_FIELD(TRACE)) | 1408 | if (PRINT_FIELD(TRACE)) |
1246 | event_format__print(evsel->tp_format, sample->cpu, | 1409 | event_format__print(evsel->tp_format, sample->cpu, |
1247 | sample->raw_data, sample->raw_size); | 1410 | sample->raw_data, sample->raw_size); |
1411 | |||
1412 | if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH)) | ||
1413 | print_sample_synth(sample, evsel); | ||
1414 | |||
1248 | if (PRINT_FIELD(ADDR)) | 1415 | if (PRINT_FIELD(ADDR)) |
1249 | print_sample_addr(sample, thread, attr); | 1416 | print_sample_addr(sample, thread, attr); |
1250 | 1417 | ||
@@ -1263,7 +1430,7 @@ static void process_event(struct perf_script *script, | |||
1263 | cursor = &callchain_cursor; | 1430 | cursor = &callchain_cursor; |
1264 | 1431 | ||
1265 | putchar(cursor ? '\n' : ' '); | 1432 | putchar(cursor ? '\n' : ' '); |
1266 | sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout); | 1433 | sample__fprintf_sym(sample, al, 0, output[type].print_ip_opts, cursor, stdout); |
1267 | } | 1434 | } |
1268 | 1435 | ||
1269 | if (PRINT_FIELD(IREGS)) | 1436 | if (PRINT_FIELD(IREGS)) |
@@ -1410,7 +1577,8 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, | |||
1410 | evlist = *pevlist; | 1577 | evlist = *pevlist; |
1411 | evsel = perf_evlist__last(*pevlist); | 1578 | evsel = perf_evlist__last(*pevlist); |
1412 | 1579 | ||
1413 | if (evsel->attr.type >= PERF_TYPE_MAX) | 1580 | if (evsel->attr.type >= PERF_TYPE_MAX && |
1581 | evsel->attr.type != PERF_TYPE_SYNTH) | ||
1414 | return 0; | 1582 | return 0; |
1415 | 1583 | ||
1416 | evlist__for_each_entry(evlist, pos) { | 1584 | evlist__for_each_entry(evlist, pos) { |
@@ -1835,6 +2003,8 @@ static int parse_output_fields(const struct option *opt __maybe_unused, | |||
1835 | type = PERF_TYPE_RAW; | 2003 | type = PERF_TYPE_RAW; |
1836 | else if (!strcmp(str, "break")) | 2004 | else if (!strcmp(str, "break")) |
1837 | type = PERF_TYPE_BREAKPOINT; | 2005 | type = PERF_TYPE_BREAKPOINT; |
2006 | else if (!strcmp(str, "synth")) | ||
2007 | type = OUTPUT_TYPE_SYNTH; | ||
1838 | else { | 2008 | else { |
1839 | fprintf(stderr, "Invalid event type in field string.\n"); | 2009 | fprintf(stderr, "Invalid event type in field string.\n"); |
1840 | rc = -EINVAL; | 2010 | rc = -EINVAL; |
@@ -1865,7 +2035,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused, | |||
1865 | if (output_set_by_user()) | 2035 | if (output_set_by_user()) |
1866 | pr_warning("Overriding previous field request for all events.\n"); | 2036 | pr_warning("Overriding previous field request for all events.\n"); |
1867 | 2037 | ||
1868 | for (j = 0; j < PERF_TYPE_MAX; ++j) { | 2038 | for (j = 0; j < OUTPUT_TYPE_MAX; ++j) { |
1869 | output[j].fields = 0; | 2039 | output[j].fields = 0; |
1870 | output[j].user_set = true; | 2040 | output[j].user_set = true; |
1871 | output[j].wildcard_set = true; | 2041 | output[j].wildcard_set = true; |
@@ -1908,7 +2078,7 @@ parse: | |||
1908 | /* add user option to all events types for | 2078 | /* add user option to all events types for |
1909 | * which it is valid | 2079 | * which it is valid |
1910 | */ | 2080 | */ |
1911 | for (j = 0; j < PERF_TYPE_MAX; ++j) { | 2081 | for (j = 0; j < OUTPUT_TYPE_MAX; ++j) { |
1912 | if (output[j].invalid_fields & all_output_options[i].field) { | 2082 | if (output[j].invalid_fields & all_output_options[i].field) { |
1913 | pr_warning("\'%s\' not valid for %s events. Ignoring.\n", | 2083 | pr_warning("\'%s\' not valid for %s events. Ignoring.\n", |
1914 | all_output_options[i].str, event_type(j)); | 2084 | all_output_options[i].str, event_type(j)); |
@@ -2560,10 +2730,10 @@ int cmd_script(int argc, const char **argv) | |||
2560 | OPT_CALLBACK('F', "fields", NULL, "str", | 2730 | OPT_CALLBACK('F', "fields", NULL, "str", |
2561 | "comma separated output fields prepend with 'type:'. " | 2731 | "comma separated output fields prepend with 'type:'. " |
2562 | "+field to add and -field to remove." | 2732 | "+field to add and -field to remove." |
2563 | "Valid types: hw,sw,trace,raw. " | 2733 | "Valid types: hw,sw,trace,raw,synth. " |
2564 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," | 2734 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," |
2565 | "addr,symoff,period,iregs,brstack,brstacksym,flags," | 2735 | "addr,symoff,period,iregs,brstack,brstacksym,flags," |
2566 | "bpf-output,callindent,insn,insnlen,brstackinsn", | 2736 | "bpf-output,callindent,insn,insnlen,brstackinsn,synth", |
2567 | parse_output_fields), | 2737 | parse_output_fields), |
2568 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 2738 | OPT_BOOLEAN('a', "all-cpus", &system_wide, |
2569 | "system-wide collection from all CPUs"), | 2739 | "system-wide collection from all CPUs"), |
@@ -2822,6 +2992,7 @@ int cmd_script(int argc, const char **argv) | |||
2822 | err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); | 2992 | err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); |
2823 | if (err < 0) | 2993 | if (err < 0) |
2824 | goto out_delete; | 2994 | goto out_delete; |
2995 | itrace_synth_opts.cpu_bitmap = cpu_bitmap; | ||
2825 | } | 2996 | } |
2826 | 2997 | ||
2827 | if (!no_callchain) | 2998 | if (!no_callchain) |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 324363054c3f..48ac53b199fc 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -636,14 +636,14 @@ try_again: | |||
636 | } | 636 | } |
637 | 637 | ||
638 | if (perf_evlist__apply_filters(evsel_list, &counter)) { | 638 | if (perf_evlist__apply_filters(evsel_list, &counter)) { |
639 | error("failed to set filter \"%s\" on event %s with %d (%s)\n", | 639 | pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", |
640 | counter->filter, perf_evsel__name(counter), errno, | 640 | counter->filter, perf_evsel__name(counter), errno, |
641 | str_error_r(errno, msg, sizeof(msg))); | 641 | str_error_r(errno, msg, sizeof(msg))); |
642 | return -1; | 642 | return -1; |
643 | } | 643 | } |
644 | 644 | ||
645 | if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) { | 645 | if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) { |
646 | error("failed to set config \"%s\" on event %s with %d (%s)\n", | 646 | pr_err("failed to set config \"%s\" on event %s with %d (%s)\n", |
647 | err_term->val.drv_cfg, perf_evsel__name(counter), errno, | 647 | err_term->val.drv_cfg, perf_evsel__name(counter), errno, |
648 | str_error_r(errno, msg, sizeof(msg))); | 648 | str_error_r(errno, msg, sizeof(msg))); |
649 | return -1; | 649 | return -1; |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 2bcfa46913c8..6052376634c0 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -958,7 +958,7 @@ static int __cmd_top(struct perf_top *top) | |||
958 | 958 | ||
959 | ret = perf_evlist__apply_drv_configs(evlist, &pos, &err_term); | 959 | ret = perf_evlist__apply_drv_configs(evlist, &pos, &err_term); |
960 | if (ret) { | 960 | if (ret) { |
961 | error("failed to set config \"%s\" on event %s with %d (%s)\n", | 961 | pr_err("failed to set config \"%s\" on event %s with %d (%s)\n", |
962 | err_term->val.drv_cfg, perf_evsel__name(pos), errno, | 962 | err_term->val.drv_cfg, perf_evsel__name(pos), errno, |
963 | str_error_r(errno, msg, sizeof(msg))); | 963 | str_error_r(errno, msg, sizeof(msg))); |
964 | goto out_delete; | 964 | goto out_delete; |
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c index e9651a9d670e..cf36de7ea255 100644 --- a/tools/perf/jvmti/jvmti_agent.c +++ b/tools/perf/jvmti/jvmti_agent.c | |||
@@ -304,7 +304,7 @@ jvmti_close(void *agent) | |||
304 | FILE *fp = agent; | 304 | FILE *fp = agent; |
305 | 305 | ||
306 | if (!fp) { | 306 | if (!fp) { |
307 | warnx("jvmti: incalid fd in close_agent"); | 307 | warnx("jvmti: invalid fd in close_agent"); |
308 | return -1; | 308 | return -1; |
309 | } | 309 | } |
310 | 310 | ||
diff --git a/tools/perf/scripts/python/bin/intel-pt-events-record b/tools/perf/scripts/python/bin/intel-pt-events-record new file mode 100644 index 000000000000..10fe2b6977d4 --- /dev/null +++ b/tools/perf/scripts/python/bin/intel-pt-events-record | |||
@@ -0,0 +1,13 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | # | ||
4 | # print Intel PT Power Events and PTWRITE. The intel_pt PMU event needs | ||
5 | # to be specified with appropriate config terms. | ||
6 | # | ||
7 | if ! echo "$@" | grep -q intel_pt ; then | ||
8 | echo "Options must include the Intel PT event e.g. -e intel_pt/pwr_evt,ptw/" | ||
9 | echo "and for power events it probably needs to be system wide i.e. -a option" | ||
10 | echo "For example: -a -e intel_pt/pwr_evt,branch=0/ sleep 1" | ||
11 | exit 1 | ||
12 | fi | ||
13 | perf record $@ | ||
diff --git a/tools/perf/scripts/python/bin/intel-pt-events-report b/tools/perf/scripts/python/bin/intel-pt-events-report new file mode 100644 index 000000000000..9a9c92fcd026 --- /dev/null +++ b/tools/perf/scripts/python/bin/intel-pt-events-report | |||
@@ -0,0 +1,3 @@ | |||
1 | #!/bin/bash | ||
2 | # description: print Intel PT Power Events and PTWRITE | ||
3 | perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/intel-pt-events.py \ No newline at end of file | ||
diff --git a/tools/perf/scripts/python/intel-pt-events.py b/tools/perf/scripts/python/intel-pt-events.py new file mode 100644 index 000000000000..b19172d673af --- /dev/null +++ b/tools/perf/scripts/python/intel-pt-events.py | |||
@@ -0,0 +1,128 @@ | |||
1 | # intel-pt-events.py: Print Intel PT Power Events and PTWRITE | ||
2 | # Copyright (c) 2017, Intel Corporation. | ||
3 | # | ||
4 | # This program is free software; you can redistribute it and/or modify it | ||
5 | # under the terms and conditions of the GNU General Public License, | ||
6 | # version 2, as published by the Free Software Foundation. | ||
7 | # | ||
8 | # This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | # more details. | ||
12 | |||
13 | import os | ||
14 | import sys | ||
15 | import struct | ||
16 | |||
17 | sys.path.append(os.environ['PERF_EXEC_PATH'] + \ | ||
18 | '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') | ||
19 | |||
20 | # These perf imports are not used at present | ||
21 | #from perf_trace_context import * | ||
22 | #from Core import * | ||
23 | |||
24 | def trace_begin(): | ||
25 | print "Intel PT Power Events and PTWRITE" | ||
26 | |||
27 | def trace_end(): | ||
28 | print "End" | ||
29 | |||
30 | def trace_unhandled(event_name, context, event_fields_dict): | ||
31 | print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())]) | ||
32 | |||
33 | def print_ptwrite(raw_buf): | ||
34 | data = struct.unpack_from("<IQ", raw_buf) | ||
35 | flags = data[0] | ||
36 | payload = data[1] | ||
37 | exact_ip = flags & 1 | ||
38 | print "IP: %u payload: %#x" % (exact_ip, payload), | ||
39 | |||
40 | def print_cbr(raw_buf): | ||
41 | data = struct.unpack_from("<BBBBII", raw_buf) | ||
42 | cbr = data[0] | ||
43 | f = (data[4] + 500) / 1000 | ||
44 | p = ((cbr * 1000 / data[2]) + 5) / 10 | ||
45 | print "%3u freq: %4u MHz (%3u%%)" % (cbr, f, p), | ||
46 | |||
47 | def print_mwait(raw_buf): | ||
48 | data = struct.unpack_from("<IQ", raw_buf) | ||
49 | payload = data[1] | ||
50 | hints = payload & 0xff | ||
51 | extensions = (payload >> 32) & 0x3 | ||
52 | print "hints: %#x extensions: %#x" % (hints, extensions), | ||
53 | |||
54 | def print_pwre(raw_buf): | ||
55 | data = struct.unpack_from("<IQ", raw_buf) | ||
56 | payload = data[1] | ||
57 | hw = (payload >> 7) & 1 | ||
58 | cstate = (payload >> 12) & 0xf | ||
59 | subcstate = (payload >> 8) & 0xf | ||
60 | print "hw: %u cstate: %u sub-cstate: %u" % (hw, cstate, subcstate), | ||
61 | |||
62 | def print_exstop(raw_buf): | ||
63 | data = struct.unpack_from("<I", raw_buf) | ||
64 | flags = data[0] | ||
65 | exact_ip = flags & 1 | ||
66 | print "IP: %u" % (exact_ip), | ||
67 | |||
68 | def print_pwrx(raw_buf): | ||
69 | data = struct.unpack_from("<IQ", raw_buf) | ||
70 | payload = data[1] | ||
71 | deepest_cstate = payload & 0xf | ||
72 | last_cstate = (payload >> 4) & 0xf | ||
73 | wake_reason = (payload >> 8) & 0xf | ||
74 | print "deepest cstate: %u last cstate: %u wake reason: %#x" % (deepest_cstate, last_cstate, wake_reason), | ||
75 | |||
76 | def print_common_start(comm, sample, name): | ||
77 | ts = sample["time"] | ||
78 | cpu = sample["cpu"] | ||
79 | pid = sample["pid"] | ||
80 | tid = sample["tid"] | ||
81 | print "%16s %5u/%-5u [%03u] %9u.%09u %7s:" % (comm, pid, tid, cpu, ts / 1000000000, ts %1000000000, name), | ||
82 | |||
83 | def print_common_ip(sample, symbol, dso): | ||
84 | ip = sample["ip"] | ||
85 | print "%16x %s (%s)" % (ip, symbol, dso) | ||
86 | |||
87 | def process_event(param_dict): | ||
88 | event_attr = param_dict["attr"] | ||
89 | sample = param_dict["sample"] | ||
90 | raw_buf = param_dict["raw_buf"] | ||
91 | comm = param_dict["comm"] | ||
92 | name = param_dict["ev_name"] | ||
93 | |||
94 | # Symbol and dso info are not always resolved | ||
95 | if (param_dict.has_key("dso")): | ||
96 | dso = param_dict["dso"] | ||
97 | else: | ||
98 | dso = "[unknown]" | ||
99 | |||
100 | if (param_dict.has_key("symbol")): | ||
101 | symbol = param_dict["symbol"] | ||
102 | else: | ||
103 | symbol = "[unknown]" | ||
104 | |||
105 | if name == "ptwrite": | ||
106 | print_common_start(comm, sample, name) | ||
107 | print_ptwrite(raw_buf) | ||
108 | print_common_ip(sample, symbol, dso) | ||
109 | elif name == "cbr": | ||
110 | print_common_start(comm, sample, name) | ||
111 | print_cbr(raw_buf) | ||
112 | print_common_ip(sample, symbol, dso) | ||
113 | elif name == "mwait": | ||
114 | print_common_start(comm, sample, name) | ||
115 | print_mwait(raw_buf) | ||
116 | print_common_ip(sample, symbol, dso) | ||
117 | elif name == "pwre": | ||
118 | print_common_start(comm, sample, name) | ||
119 | print_pwre(raw_buf) | ||
120 | print_common_ip(sample, symbol, dso) | ||
121 | elif name == "exstop": | ||
122 | print_common_start(comm, sample, name) | ||
123 | print_exstop(raw_buf) | ||
124 | print_common_ip(sample, symbol, dso) | ||
125 | elif name == "pwrx": | ||
126 | print_common_start(comm, sample, name) | ||
127 | print_pwrx(raw_buf) | ||
128 | print_common_ip(sample, symbol, dso) | ||
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c index 0dd77494bb58..0e77b2cf61ec 100644 --- a/tools/perf/tests/attr.c +++ b/tools/perf/tests/attr.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * permissions. All the event text files are stored there. | 18 | * permissions. All the event text files are stored there. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <debug.h> | ||
21 | #include <errno.h> | 22 | #include <errno.h> |
22 | #include <inttypes.h> | 23 | #include <inttypes.h> |
23 | #include <stdlib.h> | 24 | #include <stdlib.h> |
@@ -29,14 +30,11 @@ | |||
29 | #include <sys/stat.h> | 30 | #include <sys/stat.h> |
30 | #include <unistd.h> | 31 | #include <unistd.h> |
31 | #include "../perf.h" | 32 | #include "../perf.h" |
32 | #include "util.h" | ||
33 | #include <subcmd/exec-cmd.h> | 33 | #include <subcmd/exec-cmd.h> |
34 | #include "tests.h" | 34 | #include "tests.h" |
35 | 35 | ||
36 | #define ENV "PERF_TEST_ATTR" | 36 | #define ENV "PERF_TEST_ATTR" |
37 | 37 | ||
38 | extern int verbose; | ||
39 | |||
40 | static char *dir; | 38 | static char *dir; |
41 | 39 | ||
42 | void test_attr__init(void) | 40 | void test_attr__init(void) |
@@ -138,8 +136,10 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, | |||
138 | { | 136 | { |
139 | int errno_saved = errno; | 137 | int errno_saved = errno; |
140 | 138 | ||
141 | if (store_event(attr, pid, cpu, fd, group_fd, flags)) | 139 | if (store_event(attr, pid, cpu, fd, group_fd, flags)) { |
142 | die("test attr FAILED"); | 140 | pr_err("test attr FAILED"); |
141 | exit(128); | ||
142 | } | ||
143 | 143 | ||
144 | errno = errno_saved; | 144 | errno = errno_saved; |
145 | } | 145 | } |
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py index 1091bd47adfd..cdf21a9d0c35 100644 --- a/tools/perf/tests/attr.py +++ b/tools/perf/tests/attr.py | |||
@@ -16,6 +16,13 @@ class Fail(Exception): | |||
16 | def getMsg(self): | 16 | def getMsg(self): |
17 | return '\'%s\' - %s' % (self.test.path, self.msg) | 17 | return '\'%s\' - %s' % (self.test.path, self.msg) |
18 | 18 | ||
19 | class Notest(Exception): | ||
20 | def __init__(self, test, arch): | ||
21 | self.arch = arch | ||
22 | self.test = test | ||
23 | def getMsg(self): | ||
24 | return '[%s] \'%s\'' % (self.arch, self.test.path) | ||
25 | |||
19 | class Unsup(Exception): | 26 | class Unsup(Exception): |
20 | def __init__(self, test): | 27 | def __init__(self, test): |
21 | self.test = test | 28 | self.test = test |
@@ -112,6 +119,9 @@ class Event(dict): | |||
112 | # 'command' - perf command name | 119 | # 'command' - perf command name |
113 | # 'args' - special command arguments | 120 | # 'args' - special command arguments |
114 | # 'ret' - expected command return value (0 by default) | 121 | # 'ret' - expected command return value (0 by default) |
122 | # 'arch' - architecture specific test (optional) | ||
123 | # comma separated list, ! at the beginning | ||
124 | # negates it. | ||
115 | # | 125 | # |
116 | # [eventX:base] | 126 | # [eventX:base] |
117 | # - one or multiple instances in file | 127 | # - one or multiple instances in file |
@@ -134,6 +144,12 @@ class Test(object): | |||
134 | except: | 144 | except: |
135 | self.ret = 0 | 145 | self.ret = 0 |
136 | 146 | ||
147 | try: | ||
148 | self.arch = parser.get('config', 'arch') | ||
149 | log.warning("test limitation '%s'" % self.arch) | ||
150 | except: | ||
151 | self.arch = '' | ||
152 | |||
137 | self.expect = {} | 153 | self.expect = {} |
138 | self.result = {} | 154 | self.result = {} |
139 | log.debug(" loading expected events"); | 155 | log.debug(" loading expected events"); |
@@ -145,6 +161,31 @@ class Test(object): | |||
145 | else: | 161 | else: |
146 | return True | 162 | return True |
147 | 163 | ||
164 | def skip_test(self, myarch): | ||
165 | # If architecture not set always run test | ||
166 | if self.arch == '': | ||
167 | # log.warning("test for arch %s is ok" % myarch) | ||
168 | return False | ||
169 | |||
170 | # Allow multiple values in assignment separated by ',' | ||
171 | arch_list = self.arch.split(',') | ||
172 | |||
173 | # Handle negated list such as !s390x,ppc | ||
174 | if arch_list[0][0] == '!': | ||
175 | arch_list[0] = arch_list[0][1:] | ||
176 | log.warning("excluded architecture list %s" % arch_list) | ||
177 | for arch_item in arch_list: | ||
178 | # log.warning("test for %s arch is %s" % (arch_item, myarch)) | ||
179 | if arch_item == myarch: | ||
180 | return True | ||
181 | return False | ||
182 | |||
183 | for arch_item in arch_list: | ||
184 | # log.warning("test for architecture '%s' current '%s'" % (arch_item, myarch)) | ||
185 | if arch_item == myarch: | ||
186 | return False | ||
187 | return True | ||
188 | |||
148 | def load_events(self, path, events): | 189 | def load_events(self, path, events): |
149 | parser_event = ConfigParser.SafeConfigParser() | 190 | parser_event = ConfigParser.SafeConfigParser() |
150 | parser_event.read(path) | 191 | parser_event.read(path) |
@@ -168,6 +209,11 @@ class Test(object): | |||
168 | events[section] = e | 209 | events[section] = e |
169 | 210 | ||
170 | def run_cmd(self, tempdir): | 211 | def run_cmd(self, tempdir): |
212 | junk1, junk2, junk3, junk4, myarch = (os.uname()) | ||
213 | |||
214 | if self.skip_test(myarch): | ||
215 | raise Notest(self, myarch) | ||
216 | |||
171 | cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir, | 217 | cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir, |
172 | self.perf, self.command, tempdir, self.args) | 218 | self.perf, self.command, tempdir, self.args) |
173 | ret = os.WEXITSTATUS(os.system(cmd)) | 219 | ret = os.WEXITSTATUS(os.system(cmd)) |
@@ -265,6 +311,8 @@ def run_tests(options): | |||
265 | Test(f, options).run() | 311 | Test(f, options).run() |
266 | except Unsup, obj: | 312 | except Unsup, obj: |
267 | log.warning("unsupp %s" % obj.getMsg()) | 313 | log.warning("unsupp %s" % obj.getMsg()) |
314 | except Notest, obj: | ||
315 | log.warning("skipped %s" % obj.getMsg()) | ||
268 | 316 | ||
269 | def setup_log(verbose): | 317 | def setup_log(verbose): |
270 | global log | 318 | global log |
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 7fad885491c5..812a053d1941 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c | |||
@@ -1810,17 +1810,6 @@ static int test_pmu_events(void) | |||
1810 | return ret; | 1810 | return ret; |
1811 | } | 1811 | } |
1812 | 1812 | ||
1813 | static void debug_warn(const char *warn, va_list params) | ||
1814 | { | ||
1815 | char msg[1024]; | ||
1816 | |||
1817 | if (verbose <= 0) | ||
1818 | return; | ||
1819 | |||
1820 | vsnprintf(msg, sizeof(msg), warn, params); | ||
1821 | fprintf(stderr, " Warning: %s\n", msg); | ||
1822 | } | ||
1823 | |||
1824 | int test__parse_events(int subtest __maybe_unused) | 1813 | int test__parse_events(int subtest __maybe_unused) |
1825 | { | 1814 | { |
1826 | int ret1, ret2 = 0; | 1815 | int ret1, ret2 = 0; |
@@ -1832,8 +1821,6 @@ do { \ | |||
1832 | ret2 = ret1; \ | 1821 | ret2 = ret1; \ |
1833 | } while (0) | 1822 | } while (0) |
1834 | 1823 | ||
1835 | set_warning_routine(debug_warn); | ||
1836 | |||
1837 | TEST_EVENTS(test__events); | 1824 | TEST_EVENTS(test__events); |
1838 | 1825 | ||
1839 | if (test_pmu()) | 1826 | if (test_pmu()) |
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 0daf63b9ee3e..5547457566a7 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c | |||
@@ -322,6 +322,13 @@ static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues, | |||
322 | return auxtrace_queues__add_buffer(queues, idx, buffer); | 322 | return auxtrace_queues__add_buffer(queues, idx, buffer); |
323 | } | 323 | } |
324 | 324 | ||
325 | static bool filter_cpu(struct perf_session *session, int cpu) | ||
326 | { | ||
327 | unsigned long *cpu_bitmap = session->itrace_synth_opts->cpu_bitmap; | ||
328 | |||
329 | return cpu_bitmap && cpu != -1 && !test_bit(cpu, cpu_bitmap); | ||
330 | } | ||
331 | |||
325 | int auxtrace_queues__add_event(struct auxtrace_queues *queues, | 332 | int auxtrace_queues__add_event(struct auxtrace_queues *queues, |
326 | struct perf_session *session, | 333 | struct perf_session *session, |
327 | union perf_event *event, off_t data_offset, | 334 | union perf_event *event, off_t data_offset, |
@@ -331,6 +338,9 @@ int auxtrace_queues__add_event(struct auxtrace_queues *queues, | |||
331 | unsigned int idx; | 338 | unsigned int idx; |
332 | int err; | 339 | int err; |
333 | 340 | ||
341 | if (filter_cpu(session, event->auxtrace.cpu)) | ||
342 | return 0; | ||
343 | |||
334 | buffer = zalloc(sizeof(struct auxtrace_buffer)); | 344 | buffer = zalloc(sizeof(struct auxtrace_buffer)); |
335 | if (!buffer) | 345 | if (!buffer) |
336 | return -ENOMEM; | 346 | return -ENOMEM; |
@@ -947,6 +957,8 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) | |||
947 | synth_opts->instructions = true; | 957 | synth_opts->instructions = true; |
948 | synth_opts->branches = true; | 958 | synth_opts->branches = true; |
949 | synth_opts->transactions = true; | 959 | synth_opts->transactions = true; |
960 | synth_opts->ptwrites = true; | ||
961 | synth_opts->pwr_events = true; | ||
950 | synth_opts->errors = true; | 962 | synth_opts->errors = true; |
951 | synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; | 963 | synth_opts->period_type = PERF_ITRACE_DEFAULT_PERIOD_TYPE; |
952 | synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; | 964 | synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; |
@@ -1030,6 +1042,12 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str, | |||
1030 | case 'x': | 1042 | case 'x': |
1031 | synth_opts->transactions = true; | 1043 | synth_opts->transactions = true; |
1032 | break; | 1044 | break; |
1045 | case 'w': | ||
1046 | synth_opts->ptwrites = true; | ||
1047 | break; | ||
1048 | case 'p': | ||
1049 | synth_opts->pwr_events = true; | ||
1050 | break; | ||
1033 | case 'e': | 1051 | case 'e': |
1034 | synth_opts->errors = true; | 1052 | synth_opts->errors = true; |
1035 | break; | 1053 | break; |
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index 9f0de72d58e2..33b5e6cdf38c 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h | |||
@@ -59,6 +59,8 @@ enum itrace_period_type { | |||
59 | * @instructions: whether to synthesize 'instructions' events | 59 | * @instructions: whether to synthesize 'instructions' events |
60 | * @branches: whether to synthesize 'branches' events | 60 | * @branches: whether to synthesize 'branches' events |
61 | * @transactions: whether to synthesize events for transactions | 61 | * @transactions: whether to synthesize events for transactions |
62 | * @ptwrites: whether to synthesize events for ptwrites | ||
63 | * @pwr_events: whether to synthesize power events | ||
62 | * @errors: whether to synthesize decoder error events | 64 | * @errors: whether to synthesize decoder error events |
63 | * @dont_decode: whether to skip decoding entirely | 65 | * @dont_decode: whether to skip decoding entirely |
64 | * @log: write a decoding log | 66 | * @log: write a decoding log |
@@ -72,6 +74,7 @@ enum itrace_period_type { | |||
72 | * @period: 'instructions' events period | 74 | * @period: 'instructions' events period |
73 | * @period_type: 'instructions' events period type | 75 | * @period_type: 'instructions' events period type |
74 | * @initial_skip: skip N events at the beginning. | 76 | * @initial_skip: skip N events at the beginning. |
77 | * @cpu_bitmap: CPUs for which to synthesize events, or NULL for all | ||
75 | */ | 78 | */ |
76 | struct itrace_synth_opts { | 79 | struct itrace_synth_opts { |
77 | bool set; | 80 | bool set; |
@@ -79,6 +82,8 @@ struct itrace_synth_opts { | |||
79 | bool instructions; | 82 | bool instructions; |
80 | bool branches; | 83 | bool branches; |
81 | bool transactions; | 84 | bool transactions; |
85 | bool ptwrites; | ||
86 | bool pwr_events; | ||
82 | bool errors; | 87 | bool errors; |
83 | bool dont_decode; | 88 | bool dont_decode; |
84 | bool log; | 89 | bool log; |
@@ -92,6 +97,7 @@ struct itrace_synth_opts { | |||
92 | unsigned long long period; | 97 | unsigned long long period; |
93 | enum itrace_period_type period_type; | 98 | enum itrace_period_type period_type; |
94 | unsigned long initial_skip; | 99 | unsigned long initial_skip; |
100 | unsigned long *cpu_bitmap; | ||
95 | }; | 101 | }; |
96 | 102 | ||
97 | /** | 103 | /** |
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 8d724f0fa5a8..31a7dea248d0 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c | |||
@@ -335,32 +335,42 @@ static int perf_parse_long(const char *value, long *ret) | |||
335 | return 0; | 335 | return 0; |
336 | } | 336 | } |
337 | 337 | ||
338 | static void die_bad_config(const char *name) | 338 | static void bad_config(const char *name) |
339 | { | 339 | { |
340 | if (config_file_name) | 340 | if (config_file_name) |
341 | die("bad config value for '%s' in %s", name, config_file_name); | 341 | pr_warning("bad config value for '%s' in %s, ignoring...\n", name, config_file_name); |
342 | die("bad config value for '%s'", name); | 342 | else |
343 | pr_warning("bad config value for '%s', ignoring...\n", name); | ||
343 | } | 344 | } |
344 | 345 | ||
345 | u64 perf_config_u64(const char *name, const char *value) | 346 | int perf_config_u64(u64 *dest, const char *name, const char *value) |
346 | { | 347 | { |
347 | long long ret = 0; | 348 | long long ret = 0; |
348 | 349 | ||
349 | if (!perf_parse_llong(value, &ret)) | 350 | if (!perf_parse_llong(value, &ret)) { |
350 | die_bad_config(name); | 351 | bad_config(name); |
351 | return (u64) ret; | 352 | return -1; |
353 | } | ||
354 | |||
355 | *dest = ret; | ||
356 | return 0; | ||
352 | } | 357 | } |
353 | 358 | ||
354 | int perf_config_int(const char *name, const char *value) | 359 | int perf_config_int(int *dest, const char *name, const char *value) |
355 | { | 360 | { |
356 | long ret = 0; | 361 | long ret = 0; |
357 | if (!perf_parse_long(value, &ret)) | 362 | if (!perf_parse_long(value, &ret)) { |
358 | die_bad_config(name); | 363 | bad_config(name); |
359 | return ret; | 364 | return -1; |
365 | } | ||
366 | *dest = ret; | ||
367 | return 0; | ||
360 | } | 368 | } |
361 | 369 | ||
362 | static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) | 370 | static int perf_config_bool_or_int(const char *name, const char *value, int *is_bool) |
363 | { | 371 | { |
372 | int ret; | ||
373 | |||
364 | *is_bool = 1; | 374 | *is_bool = 1; |
365 | if (!value) | 375 | if (!value) |
366 | return 1; | 376 | return 1; |
@@ -371,7 +381,7 @@ static int perf_config_bool_or_int(const char *name, const char *value, int *is_ | |||
371 | if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) | 381 | if (!strcasecmp(value, "false") || !strcasecmp(value, "no") || !strcasecmp(value, "off")) |
372 | return 0; | 382 | return 0; |
373 | *is_bool = 0; | 383 | *is_bool = 0; |
374 | return perf_config_int(name, value); | 384 | return perf_config_int(&ret, name, value) < 0 ? -1 : ret; |
375 | } | 385 | } |
376 | 386 | ||
377 | int perf_config_bool(const char *name, const char *value) | 387 | int perf_config_bool(const char *name, const char *value) |
@@ -657,8 +667,7 @@ static int perf_config_set__init(struct perf_config_set *set) | |||
657 | 667 | ||
658 | user_config = strdup(mkpath("%s/.perfconfig", home)); | 668 | user_config = strdup(mkpath("%s/.perfconfig", home)); |
659 | if (user_config == NULL) { | 669 | if (user_config == NULL) { |
660 | warning("Not enough memory to process %s/.perfconfig, " | 670 | pr_warning("Not enough memory to process %s/.perfconfig, ignoring it.", home); |
661 | "ignoring it.", home); | ||
662 | goto out; | 671 | goto out; |
663 | } | 672 | } |
664 | 673 | ||
@@ -671,8 +680,7 @@ static int perf_config_set__init(struct perf_config_set *set) | |||
671 | ret = 0; | 680 | ret = 0; |
672 | 681 | ||
673 | if (st.st_uid && (st.st_uid != geteuid())) { | 682 | if (st.st_uid && (st.st_uid != geteuid())) { |
674 | warning("File %s not owned by current user or root, " | 683 | pr_warning("File %s not owned by current user or root, ignoring it.", user_config); |
675 | "ignoring it.", user_config); | ||
676 | goto out_free; | 684 | goto out_free; |
677 | } | 685 | } |
678 | 686 | ||
@@ -795,7 +803,8 @@ void perf_config_set__delete(struct perf_config_set *set) | |||
795 | */ | 803 | */ |
796 | int config_error_nonbool(const char *var) | 804 | int config_error_nonbool(const char *var) |
797 | { | 805 | { |
798 | return error("Missing value for '%s'", var); | 806 | pr_err("Missing value for '%s'", var); |
807 | return -1; | ||
799 | } | 808 | } |
800 | 809 | ||
801 | void set_buildid_dir(const char *dir) | 810 | void set_buildid_dir(const char *dir) |
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h index 1a59a6b43f8b..b6bb11f3f165 100644 --- a/tools/perf/util/config.h +++ b/tools/perf/util/config.h | |||
@@ -27,8 +27,8 @@ extern const char *config_exclusive_filename; | |||
27 | typedef int (*config_fn_t)(const char *, const char *, void *); | 27 | typedef int (*config_fn_t)(const char *, const char *, void *); |
28 | int perf_default_config(const char *, const char *, void *); | 28 | int perf_default_config(const char *, const char *, void *); |
29 | int perf_config(config_fn_t fn, void *); | 29 | int perf_config(config_fn_t fn, void *); |
30 | int perf_config_int(const char *, const char *); | 30 | int perf_config_int(int *dest, const char *, const char *); |
31 | u64 perf_config_u64(const char *, const char *); | 31 | int perf_config_u64(u64 *dest, const char *, const char *); |
32 | int perf_config_bool(const char *, const char *); | 32 | int perf_config_bool(const char *, const char *); |
33 | int config_error_nonbool(const char *); | 33 | int config_error_nonbool(const char *); |
34 | const char *perf_etc_perfconfig(void); | 34 | const char *perf_etc_perfconfig(void); |
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 89d50318833d..3149b70799fd 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c | |||
@@ -1444,10 +1444,8 @@ static int convert__config(const char *var, const char *value, void *cb) | |||
1444 | { | 1444 | { |
1445 | struct convert *c = cb; | 1445 | struct convert *c = cb; |
1446 | 1446 | ||
1447 | if (!strcmp(var, "convert.queue-size")) { | 1447 | if (!strcmp(var, "convert.queue-size")) |
1448 | c->queue_size = perf_config_u64(var, value); | 1448 | return perf_config_u64(&c->queue_size, var, value); |
1449 | return 0; | ||
1450 | } | ||
1451 | 1449 | ||
1452 | return 0; | 1450 | return 0; |
1453 | } | 1451 | } |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 7c3fa1c8cbcd..9967c87af7a6 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -252,6 +252,127 @@ enum auxtrace_error_type { | |||
252 | PERF_AUXTRACE_ERROR_MAX | 252 | PERF_AUXTRACE_ERROR_MAX |
253 | }; | 253 | }; |
254 | 254 | ||
255 | /* Attribute type for custom synthesized events */ | ||
256 | #define PERF_TYPE_SYNTH (INT_MAX + 1U) | ||
257 | |||
258 | /* Attribute config for custom synthesized events */ | ||
259 | enum perf_synth_id { | ||
260 | PERF_SYNTH_INTEL_PTWRITE, | ||
261 | PERF_SYNTH_INTEL_MWAIT, | ||
262 | PERF_SYNTH_INTEL_PWRE, | ||
263 | PERF_SYNTH_INTEL_EXSTOP, | ||
264 | PERF_SYNTH_INTEL_PWRX, | ||
265 | PERF_SYNTH_INTEL_CBR, | ||
266 | }; | ||
267 | |||
268 | /* | ||
269 | * Raw data formats for synthesized events. Note that 4 bytes of padding are | ||
270 | * present to match the 'size' member of PERF_SAMPLE_RAW data which is always | ||
271 | * 8-byte aligned. That means we must dereference raw_data with an offset of 4. | ||
272 | * Refer perf_sample__synth_ptr() and perf_synth__raw_data(). It also means the | ||
273 | * structure sizes are 4 bytes bigger than the raw_size, refer | ||
274 | * perf_synth__raw_size(). | ||
275 | */ | ||
276 | |||
277 | struct perf_synth_intel_ptwrite { | ||
278 | u32 padding; | ||
279 | union { | ||
280 | struct { | ||
281 | u32 ip : 1, | ||
282 | reserved : 31; | ||
283 | }; | ||
284 | u32 flags; | ||
285 | }; | ||
286 | u64 payload; | ||
287 | }; | ||
288 | |||
289 | struct perf_synth_intel_mwait { | ||
290 | u32 padding; | ||
291 | u32 reserved; | ||
292 | union { | ||
293 | struct { | ||
294 | u64 hints : 8, | ||
295 | reserved1 : 24, | ||
296 | extensions : 2, | ||
297 | reserved2 : 30; | ||
298 | }; | ||
299 | u64 payload; | ||
300 | }; | ||
301 | }; | ||
302 | |||
303 | struct perf_synth_intel_pwre { | ||
304 | u32 padding; | ||
305 | u32 reserved; | ||
306 | union { | ||
307 | struct { | ||
308 | u64 reserved1 : 7, | ||
309 | hw : 1, | ||
310 | subcstate : 4, | ||
311 | cstate : 4, | ||
312 | reserved2 : 48; | ||
313 | }; | ||
314 | u64 payload; | ||
315 | }; | ||
316 | }; | ||
317 | |||
318 | struct perf_synth_intel_exstop { | ||
319 | u32 padding; | ||
320 | union { | ||
321 | struct { | ||
322 | u32 ip : 1, | ||
323 | reserved : 31; | ||
324 | }; | ||
325 | u32 flags; | ||
326 | }; | ||
327 | }; | ||
328 | |||
329 | struct perf_synth_intel_pwrx { | ||
330 | u32 padding; | ||
331 | u32 reserved; | ||
332 | union { | ||
333 | struct { | ||
334 | u64 deepest_cstate : 4, | ||
335 | last_cstate : 4, | ||
336 | wake_reason : 4, | ||
337 | reserved1 : 52; | ||
338 | }; | ||
339 | u64 payload; | ||
340 | }; | ||
341 | }; | ||
342 | |||
343 | struct perf_synth_intel_cbr { | ||
344 | u32 padding; | ||
345 | union { | ||
346 | struct { | ||
347 | u32 cbr : 8, | ||
348 | reserved1 : 8, | ||
349 | max_nonturbo : 8, | ||
350 | reserved2 : 8; | ||
351 | }; | ||
352 | u32 flags; | ||
353 | }; | ||
354 | u32 freq; | ||
355 | u32 reserved3; | ||
356 | }; | ||
357 | |||
358 | /* | ||
359 | * raw_data is always 4 bytes from an 8-byte boundary, so subtract 4 to get | ||
360 | * 8-byte alignment. | ||
361 | */ | ||
362 | static inline void *perf_sample__synth_ptr(struct perf_sample *sample) | ||
363 | { | ||
364 | return sample->raw_data - 4; | ||
365 | } | ||
366 | |||
367 | static inline void *perf_synth__raw_data(void *p) | ||
368 | { | ||
369 | return p + 4; | ||
370 | } | ||
371 | |||
372 | #define perf_synth__raw_size(d) (sizeof(d) - 4) | ||
373 | |||
374 | #define perf_sample__bad_synth_size(s, d) ((s)->raw_size < sizeof(d) - 4) | ||
375 | |||
255 | /* | 376 | /* |
256 | * The kernel collects the number of events it couldn't send in a stretch and | 377 | * The kernel collects the number of events it couldn't send in a stretch and |
257 | * when possible sends this number in a PERF_RECORD_LOST event. The number of | 378 | * when possible sends this number in a PERF_RECORD_LOST event. The number of |
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c index 1c88ad6425b8..15b95300d7f3 100644 --- a/tools/perf/util/help-unknown-cmd.c +++ b/tools/perf/util/help-unknown-cmd.c | |||
@@ -12,7 +12,7 @@ static int perf_unknown_cmd_config(const char *var, const char *value, | |||
12 | void *cb __maybe_unused) | 12 | void *cb __maybe_unused) |
13 | { | 13 | { |
14 | if (!strcmp(var, "help.autocorrect")) | 14 | if (!strcmp(var, "help.autocorrect")) |
15 | autocorrect = perf_config_int(var,value); | 15 | return perf_config_int(&autocorrect, var,value); |
16 | 16 | ||
17 | return 0; | 17 | return 0; |
18 | } | 18 | } |
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 5dea06289db5..aa1593ce551d 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | |||
@@ -711,6 +711,12 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info) | |||
711 | break; | 711 | break; |
712 | 712 | ||
713 | case INTEL_PT_TSC: | 713 | case INTEL_PT_TSC: |
714 | /* | ||
715 | * For now, do not support using TSC packets - refer | ||
716 | * intel_pt_calc_cyc_to_tsc(). | ||
717 | */ | ||
718 | if (data->from_mtc) | ||
719 | return 1; | ||
714 | timestamp = pkt_info->packet.payload | | 720 | timestamp = pkt_info->packet.payload | |
715 | (data->timestamp & (0xffULL << 56)); | 721 | (data->timestamp & (0xffULL << 56)); |
716 | if (data->from_mtc && timestamp < data->timestamp && | 722 | if (data->from_mtc && timestamp < data->timestamp && |
@@ -828,6 +834,14 @@ static void intel_pt_calc_cyc_to_tsc(struct intel_pt_decoder *decoder, | |||
828 | .cbr_cyc_to_tsc = 0, | 834 | .cbr_cyc_to_tsc = 0, |
829 | }; | 835 | }; |
830 | 836 | ||
837 | /* | ||
838 | * For now, do not support using TSC packets for at least the reasons: | ||
839 | * 1) timing might have stopped | ||
840 | * 2) TSC packets within PSB+ can slip against CYC packets | ||
841 | */ | ||
842 | if (!from_mtc) | ||
843 | return; | ||
844 | |||
831 | intel_pt_pkt_lookahead(decoder, intel_pt_calc_cyc_cb, &data); | 845 | intel_pt_pkt_lookahead(decoder, intel_pt_calc_cyc_cb, &data); |
832 | } | 846 | } |
833 | 847 | ||
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 767be7c76034..12e377184ee4 100644 --- a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt +++ b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt | |||
@@ -1009,7 +1009,7 @@ GrpTable: Grp15 | |||
1009 | 1: fxstor | RDGSBASE Ry (F3),(11B) | 1009 | 1: fxstor | RDGSBASE Ry (F3),(11B) |
1010 | 2: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B) | 1010 | 2: vldmxcsr Md (v1) | WRFSBASE Ry (F3),(11B) |
1011 | 3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) | 1011 | 3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B) |
1012 | 4: XSAVE | 1012 | 4: XSAVE | ptwrite Ey (F3),(11B) |
1013 | 5: XRSTOR | lfence (11B) | 1013 | 5: XRSTOR | lfence (11B) |
1014 | 6: XSAVEOPT | clwb (66) | mfence (11B) | 1014 | 6: XSAVEOPT | clwb (66) | mfence (11B) |
1015 | 7: clflush | clflushopt (66) | sfence (11B) | 1015 | 7: clflush | clflushopt (66) | sfence (11B) |
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index 6df836469f2b..b58f9fd1e2ee 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c | |||
@@ -81,7 +81,6 @@ struct intel_pt { | |||
81 | 81 | ||
82 | bool sample_instructions; | 82 | bool sample_instructions; |
83 | u64 instructions_sample_type; | 83 | u64 instructions_sample_type; |
84 | u64 instructions_sample_period; | ||
85 | u64 instructions_id; | 84 | u64 instructions_id; |
86 | 85 | ||
87 | bool sample_branches; | 86 | bool sample_branches; |
@@ -93,6 +92,18 @@ struct intel_pt { | |||
93 | u64 transactions_sample_type; | 92 | u64 transactions_sample_type; |
94 | u64 transactions_id; | 93 | u64 transactions_id; |
95 | 94 | ||
95 | bool sample_ptwrites; | ||
96 | u64 ptwrites_sample_type; | ||
97 | u64 ptwrites_id; | ||
98 | |||
99 | bool sample_pwr_events; | ||
100 | u64 pwr_events_sample_type; | ||
101 | u64 mwait_id; | ||
102 | u64 pwre_id; | ||
103 | u64 exstop_id; | ||
104 | u64 pwrx_id; | ||
105 | u64 cbr_id; | ||
106 | |||
96 | bool synth_needs_swap; | 107 | bool synth_needs_swap; |
97 | 108 | ||
98 | u64 tsc_bit; | 109 | u64 tsc_bit; |
@@ -103,6 +114,7 @@ struct intel_pt { | |||
103 | u64 cyc_bit; | 114 | u64 cyc_bit; |
104 | u64 noretcomp_bit; | 115 | u64 noretcomp_bit; |
105 | unsigned max_non_turbo_ratio; | 116 | unsigned max_non_turbo_ratio; |
117 | unsigned cbr2khz; | ||
106 | 118 | ||
107 | unsigned long num_events; | 119 | unsigned long num_events; |
108 | 120 | ||
@@ -1058,6 +1070,36 @@ static void intel_pt_update_last_branch_rb(struct intel_pt_queue *ptq) | |||
1058 | bs->nr += 1; | 1070 | bs->nr += 1; |
1059 | } | 1071 | } |
1060 | 1072 | ||
1073 | static inline bool intel_pt_skip_event(struct intel_pt *pt) | ||
1074 | { | ||
1075 | return pt->synth_opts.initial_skip && | ||
1076 | pt->num_events++ < pt->synth_opts.initial_skip; | ||
1077 | } | ||
1078 | |||
1079 | static void intel_pt_prep_b_sample(struct intel_pt *pt, | ||
1080 | struct intel_pt_queue *ptq, | ||
1081 | union perf_event *event, | ||
1082 | struct perf_sample *sample) | ||
1083 | { | ||
1084 | event->sample.header.type = PERF_RECORD_SAMPLE; | ||
1085 | event->sample.header.misc = PERF_RECORD_MISC_USER; | ||
1086 | event->sample.header.size = sizeof(struct perf_event_header); | ||
1087 | |||
1088 | if (!pt->timeless_decoding) | ||
1089 | sample->time = tsc_to_perf_time(ptq->timestamp, &pt->tc); | ||
1090 | |||
1091 | sample->cpumode = PERF_RECORD_MISC_USER; | ||
1092 | sample->ip = ptq->state->from_ip; | ||
1093 | sample->pid = ptq->pid; | ||
1094 | sample->tid = ptq->tid; | ||
1095 | sample->addr = ptq->state->to_ip; | ||
1096 | sample->period = 1; | ||
1097 | sample->cpu = ptq->cpu; | ||
1098 | sample->flags = ptq->flags; | ||
1099 | sample->insn_len = ptq->insn_len; | ||
1100 | memcpy(sample->insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); | ||
1101 | } | ||
1102 | |||
1061 | static int intel_pt_inject_event(union perf_event *event, | 1103 | static int intel_pt_inject_event(union perf_event *event, |
1062 | struct perf_sample *sample, u64 type, | 1104 | struct perf_sample *sample, u64 type, |
1063 | bool swapped) | 1105 | bool swapped) |
@@ -1066,9 +1108,35 @@ static int intel_pt_inject_event(union perf_event *event, | |||
1066 | return perf_event__synthesize_sample(event, type, 0, sample, swapped); | 1108 | return perf_event__synthesize_sample(event, type, 0, sample, swapped); |
1067 | } | 1109 | } |
1068 | 1110 | ||
1069 | static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | 1111 | static inline int intel_pt_opt_inject(struct intel_pt *pt, |
1112 | union perf_event *event, | ||
1113 | struct perf_sample *sample, u64 type) | ||
1114 | { | ||
1115 | if (!pt->synth_opts.inject) | ||
1116 | return 0; | ||
1117 | |||
1118 | return intel_pt_inject_event(event, sample, type, pt->synth_needs_swap); | ||
1119 | } | ||
1120 | |||
1121 | static int intel_pt_deliver_synth_b_event(struct intel_pt *pt, | ||
1122 | union perf_event *event, | ||
1123 | struct perf_sample *sample, u64 type) | ||
1070 | { | 1124 | { |
1071 | int ret; | 1125 | int ret; |
1126 | |||
1127 | ret = intel_pt_opt_inject(pt, event, sample, type); | ||
1128 | if (ret) | ||
1129 | return ret; | ||
1130 | |||
1131 | ret = perf_session__deliver_synth_event(pt->session, event, sample); | ||
1132 | if (ret) | ||
1133 | pr_err("Intel PT: failed to deliver event, error %d\n", ret); | ||
1134 | |||
1135 | return ret; | ||
1136 | } | ||
1137 | |||
1138 | static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | ||
1139 | { | ||
1072 | struct intel_pt *pt = ptq->pt; | 1140 | struct intel_pt *pt = ptq->pt; |
1073 | union perf_event *event = ptq->event_buf; | 1141 | union perf_event *event = ptq->event_buf; |
1074 | struct perf_sample sample = { .ip = 0, }; | 1142 | struct perf_sample sample = { .ip = 0, }; |
@@ -1080,29 +1148,13 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | |||
1080 | if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) | 1148 | if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) |
1081 | return 0; | 1149 | return 0; |
1082 | 1150 | ||
1083 | if (pt->synth_opts.initial_skip && | 1151 | if (intel_pt_skip_event(pt)) |
1084 | pt->num_events++ < pt->synth_opts.initial_skip) | ||
1085 | return 0; | 1152 | return 0; |
1086 | 1153 | ||
1087 | event->sample.header.type = PERF_RECORD_SAMPLE; | 1154 | intel_pt_prep_b_sample(pt, ptq, event, &sample); |
1088 | event->sample.header.misc = PERF_RECORD_MISC_USER; | ||
1089 | event->sample.header.size = sizeof(struct perf_event_header); | ||
1090 | 1155 | ||
1091 | if (!pt->timeless_decoding) | ||
1092 | sample.time = tsc_to_perf_time(ptq->timestamp, &pt->tc); | ||
1093 | |||
1094 | sample.cpumode = PERF_RECORD_MISC_USER; | ||
1095 | sample.ip = ptq->state->from_ip; | ||
1096 | sample.pid = ptq->pid; | ||
1097 | sample.tid = ptq->tid; | ||
1098 | sample.addr = ptq->state->to_ip; | ||
1099 | sample.id = ptq->pt->branches_id; | 1156 | sample.id = ptq->pt->branches_id; |
1100 | sample.stream_id = ptq->pt->branches_id; | 1157 | sample.stream_id = ptq->pt->branches_id; |
1101 | sample.period = 1; | ||
1102 | sample.cpu = ptq->cpu; | ||
1103 | sample.flags = ptq->flags; | ||
1104 | sample.insn_len = ptq->insn_len; | ||
1105 | memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); | ||
1106 | 1158 | ||
1107 | /* | 1159 | /* |
1108 | * perf report cannot handle events without a branch stack when using | 1160 | * perf report cannot handle events without a branch stack when using |
@@ -1119,144 +1171,251 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) | |||
1119 | sample.branch_stack = (struct branch_stack *)&dummy_bs; | 1171 | sample.branch_stack = (struct branch_stack *)&dummy_bs; |
1120 | } | 1172 | } |
1121 | 1173 | ||
1122 | if (pt->synth_opts.inject) { | 1174 | return intel_pt_deliver_synth_b_event(pt, event, &sample, |
1123 | ret = intel_pt_inject_event(event, &sample, | 1175 | pt->branches_sample_type); |
1124 | pt->branches_sample_type, | 1176 | } |
1125 | pt->synth_needs_swap); | 1177 | |
1126 | if (ret) | 1178 | static void intel_pt_prep_sample(struct intel_pt *pt, |
1127 | return ret; | 1179 | struct intel_pt_queue *ptq, |
1180 | union perf_event *event, | ||
1181 | struct perf_sample *sample) | ||
1182 | { | ||
1183 | intel_pt_prep_b_sample(pt, ptq, event, sample); | ||
1184 | |||
1185 | if (pt->synth_opts.callchain) { | ||
1186 | thread_stack__sample(ptq->thread, ptq->chain, | ||
1187 | pt->synth_opts.callchain_sz, sample->ip); | ||
1188 | sample->callchain = ptq->chain; | ||
1128 | } | 1189 | } |
1129 | 1190 | ||
1130 | ret = perf_session__deliver_synth_event(pt->session, event, &sample); | 1191 | if (pt->synth_opts.last_branch) { |
1131 | if (ret) | 1192 | intel_pt_copy_last_branch_rb(ptq); |
1132 | pr_err("Intel Processor Trace: failed to deliver branch event, error %d\n", | 1193 | sample->branch_stack = ptq->last_branch; |
1133 | ret); | 1194 | } |
1195 | } | ||
1196 | |||
1197 | static inline int intel_pt_deliver_synth_event(struct intel_pt *pt, | ||
1198 | struct intel_pt_queue *ptq, | ||
1199 | union perf_event *event, | ||
1200 | struct perf_sample *sample, | ||
1201 | u64 type) | ||
1202 | { | ||
1203 | int ret; | ||
1204 | |||
1205 | ret = intel_pt_deliver_synth_b_event(pt, event, sample, type); | ||
1206 | |||
1207 | if (pt->synth_opts.last_branch) | ||
1208 | intel_pt_reset_last_branch_rb(ptq); | ||
1134 | 1209 | ||
1135 | return ret; | 1210 | return ret; |
1136 | } | 1211 | } |
1137 | 1212 | ||
1138 | static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) | 1213 | static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) |
1139 | { | 1214 | { |
1140 | int ret; | ||
1141 | struct intel_pt *pt = ptq->pt; | 1215 | struct intel_pt *pt = ptq->pt; |
1142 | union perf_event *event = ptq->event_buf; | 1216 | union perf_event *event = ptq->event_buf; |
1143 | struct perf_sample sample = { .ip = 0, }; | 1217 | struct perf_sample sample = { .ip = 0, }; |
1144 | 1218 | ||
1145 | if (pt->synth_opts.initial_skip && | 1219 | if (intel_pt_skip_event(pt)) |
1146 | pt->num_events++ < pt->synth_opts.initial_skip) | ||
1147 | return 0; | 1220 | return 0; |
1148 | 1221 | ||
1149 | event->sample.header.type = PERF_RECORD_SAMPLE; | 1222 | intel_pt_prep_sample(pt, ptq, event, &sample); |
1150 | event->sample.header.misc = PERF_RECORD_MISC_USER; | ||
1151 | event->sample.header.size = sizeof(struct perf_event_header); | ||
1152 | |||
1153 | if (!pt->timeless_decoding) | ||
1154 | sample.time = tsc_to_perf_time(ptq->timestamp, &pt->tc); | ||
1155 | 1223 | ||
1156 | sample.cpumode = PERF_RECORD_MISC_USER; | ||
1157 | sample.ip = ptq->state->from_ip; | ||
1158 | sample.pid = ptq->pid; | ||
1159 | sample.tid = ptq->tid; | ||
1160 | sample.addr = ptq->state->to_ip; | ||
1161 | sample.id = ptq->pt->instructions_id; | 1224 | sample.id = ptq->pt->instructions_id; |
1162 | sample.stream_id = ptq->pt->instructions_id; | 1225 | sample.stream_id = ptq->pt->instructions_id; |
1163 | sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt; | 1226 | sample.period = ptq->state->tot_insn_cnt - ptq->last_insn_cnt; |
1164 | sample.cpu = ptq->cpu; | ||
1165 | sample.flags = ptq->flags; | ||
1166 | sample.insn_len = ptq->insn_len; | ||
1167 | memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); | ||
1168 | 1227 | ||
1169 | ptq->last_insn_cnt = ptq->state->tot_insn_cnt; | 1228 | ptq->last_insn_cnt = ptq->state->tot_insn_cnt; |
1170 | 1229 | ||
1171 | if (pt->synth_opts.callchain) { | 1230 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, |
1172 | thread_stack__sample(ptq->thread, ptq->chain, | 1231 | pt->instructions_sample_type); |
1173 | pt->synth_opts.callchain_sz, sample.ip); | 1232 | } |
1174 | sample.callchain = ptq->chain; | ||
1175 | } | ||
1176 | 1233 | ||
1177 | if (pt->synth_opts.last_branch) { | 1234 | static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq) |
1178 | intel_pt_copy_last_branch_rb(ptq); | 1235 | { |
1179 | sample.branch_stack = ptq->last_branch; | 1236 | struct intel_pt *pt = ptq->pt; |
1180 | } | 1237 | union perf_event *event = ptq->event_buf; |
1238 | struct perf_sample sample = { .ip = 0, }; | ||
1181 | 1239 | ||
1182 | if (pt->synth_opts.inject) { | 1240 | if (intel_pt_skip_event(pt)) |
1183 | ret = intel_pt_inject_event(event, &sample, | 1241 | return 0; |
1184 | pt->instructions_sample_type, | ||
1185 | pt->synth_needs_swap); | ||
1186 | if (ret) | ||
1187 | return ret; | ||
1188 | } | ||
1189 | 1242 | ||
1190 | ret = perf_session__deliver_synth_event(pt->session, event, &sample); | 1243 | intel_pt_prep_sample(pt, ptq, event, &sample); |
1191 | if (ret) | ||
1192 | pr_err("Intel Processor Trace: failed to deliver instruction event, error %d\n", | ||
1193 | ret); | ||
1194 | 1244 | ||
1195 | if (pt->synth_opts.last_branch) | 1245 | sample.id = ptq->pt->transactions_id; |
1196 | intel_pt_reset_last_branch_rb(ptq); | 1246 | sample.stream_id = ptq->pt->transactions_id; |
1197 | 1247 | ||
1198 | return ret; | 1248 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, |
1249 | pt->transactions_sample_type); | ||
1199 | } | 1250 | } |
1200 | 1251 | ||
1201 | static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq) | 1252 | static void intel_pt_prep_p_sample(struct intel_pt *pt, |
1253 | struct intel_pt_queue *ptq, | ||
1254 | union perf_event *event, | ||
1255 | struct perf_sample *sample) | ||
1256 | { | ||
1257 | intel_pt_prep_sample(pt, ptq, event, sample); | ||
1258 | |||
1259 | /* | ||
1260 | * Zero IP is used to mean "trace start" but that is not the case for | ||
1261 | * power or PTWRITE events with no IP, so clear the flags. | ||
1262 | */ | ||
1263 | if (!sample->ip) | ||
1264 | sample->flags = 0; | ||
1265 | } | ||
1266 | |||
1267 | static int intel_pt_synth_ptwrite_sample(struct intel_pt_queue *ptq) | ||
1202 | { | 1268 | { |
1203 | int ret; | ||
1204 | struct intel_pt *pt = ptq->pt; | 1269 | struct intel_pt *pt = ptq->pt; |
1205 | union perf_event *event = ptq->event_buf; | 1270 | union perf_event *event = ptq->event_buf; |
1206 | struct perf_sample sample = { .ip = 0, }; | 1271 | struct perf_sample sample = { .ip = 0, }; |
1272 | struct perf_synth_intel_ptwrite raw; | ||
1207 | 1273 | ||
1208 | if (pt->synth_opts.initial_skip && | 1274 | if (intel_pt_skip_event(pt)) |
1209 | pt->num_events++ < pt->synth_opts.initial_skip) | ||
1210 | return 0; | 1275 | return 0; |
1211 | 1276 | ||
1212 | event->sample.header.type = PERF_RECORD_SAMPLE; | 1277 | intel_pt_prep_p_sample(pt, ptq, event, &sample); |
1213 | event->sample.header.misc = PERF_RECORD_MISC_USER; | ||
1214 | event->sample.header.size = sizeof(struct perf_event_header); | ||
1215 | 1278 | ||
1216 | if (!pt->timeless_decoding) | 1279 | sample.id = ptq->pt->ptwrites_id; |
1217 | sample.time = tsc_to_perf_time(ptq->timestamp, &pt->tc); | 1280 | sample.stream_id = ptq->pt->ptwrites_id; |
1218 | 1281 | ||
1219 | sample.cpumode = PERF_RECORD_MISC_USER; | 1282 | raw.flags = 0; |
1220 | sample.ip = ptq->state->from_ip; | 1283 | raw.ip = !!(ptq->state->flags & INTEL_PT_FUP_IP); |
1221 | sample.pid = ptq->pid; | 1284 | raw.payload = cpu_to_le64(ptq->state->ptw_payload); |
1222 | sample.tid = ptq->tid; | ||
1223 | sample.addr = ptq->state->to_ip; | ||
1224 | sample.id = ptq->pt->transactions_id; | ||
1225 | sample.stream_id = ptq->pt->transactions_id; | ||
1226 | sample.period = 1; | ||
1227 | sample.cpu = ptq->cpu; | ||
1228 | sample.flags = ptq->flags; | ||
1229 | sample.insn_len = ptq->insn_len; | ||
1230 | memcpy(sample.insn, ptq->insn, INTEL_PT_INSN_BUF_SZ); | ||
1231 | 1285 | ||
1232 | if (pt->synth_opts.callchain) { | 1286 | sample.raw_size = perf_synth__raw_size(raw); |
1233 | thread_stack__sample(ptq->thread, ptq->chain, | 1287 | sample.raw_data = perf_synth__raw_data(&raw); |
1234 | pt->synth_opts.callchain_sz, sample.ip); | ||
1235 | sample.callchain = ptq->chain; | ||
1236 | } | ||
1237 | 1288 | ||
1238 | if (pt->synth_opts.last_branch) { | 1289 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, |
1239 | intel_pt_copy_last_branch_rb(ptq); | 1290 | pt->ptwrites_sample_type); |
1240 | sample.branch_stack = ptq->last_branch; | 1291 | } |
1241 | } | ||
1242 | 1292 | ||
1243 | if (pt->synth_opts.inject) { | 1293 | static int intel_pt_synth_cbr_sample(struct intel_pt_queue *ptq) |
1244 | ret = intel_pt_inject_event(event, &sample, | 1294 | { |
1245 | pt->transactions_sample_type, | 1295 | struct intel_pt *pt = ptq->pt; |
1246 | pt->synth_needs_swap); | 1296 | union perf_event *event = ptq->event_buf; |
1247 | if (ret) | 1297 | struct perf_sample sample = { .ip = 0, }; |
1248 | return ret; | 1298 | struct perf_synth_intel_cbr raw; |
1249 | } | 1299 | u32 flags; |
1250 | 1300 | ||
1251 | ret = perf_session__deliver_synth_event(pt->session, event, &sample); | 1301 | if (intel_pt_skip_event(pt)) |
1252 | if (ret) | 1302 | return 0; |
1253 | pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n", | ||
1254 | ret); | ||
1255 | 1303 | ||
1256 | if (pt->synth_opts.last_branch) | 1304 | intel_pt_prep_p_sample(pt, ptq, event, &sample); |
1257 | intel_pt_reset_last_branch_rb(ptq); | ||
1258 | 1305 | ||
1259 | return ret; | 1306 | sample.id = ptq->pt->cbr_id; |
1307 | sample.stream_id = ptq->pt->cbr_id; | ||
1308 | |||
1309 | flags = (u16)ptq->state->cbr_payload | (pt->max_non_turbo_ratio << 16); | ||
1310 | raw.flags = cpu_to_le32(flags); | ||
1311 | raw.freq = cpu_to_le32(raw.cbr * pt->cbr2khz); | ||
1312 | raw.reserved3 = 0; | ||
1313 | |||
1314 | sample.raw_size = perf_synth__raw_size(raw); | ||
1315 | sample.raw_data = perf_synth__raw_data(&raw); | ||
1316 | |||
1317 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, | ||
1318 | pt->pwr_events_sample_type); | ||
1319 | } | ||
1320 | |||
1321 | static int intel_pt_synth_mwait_sample(struct intel_pt_queue *ptq) | ||
1322 | { | ||
1323 | struct intel_pt *pt = ptq->pt; | ||
1324 | union perf_event *event = ptq->event_buf; | ||
1325 | struct perf_sample sample = { .ip = 0, }; | ||
1326 | struct perf_synth_intel_mwait raw; | ||
1327 | |||
1328 | if (intel_pt_skip_event(pt)) | ||
1329 | return 0; | ||
1330 | |||
1331 | intel_pt_prep_p_sample(pt, ptq, event, &sample); | ||
1332 | |||
1333 | sample.id = ptq->pt->mwait_id; | ||
1334 | sample.stream_id = ptq->pt->mwait_id; | ||
1335 | |||
1336 | raw.reserved = 0; | ||
1337 | raw.payload = cpu_to_le64(ptq->state->mwait_payload); | ||
1338 | |||
1339 | sample.raw_size = perf_synth__raw_size(raw); | ||
1340 | sample.raw_data = perf_synth__raw_data(&raw); | ||
1341 | |||
1342 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, | ||
1343 | pt->pwr_events_sample_type); | ||
1344 | } | ||
1345 | |||
1346 | static int intel_pt_synth_pwre_sample(struct intel_pt_queue *ptq) | ||
1347 | { | ||
1348 | struct intel_pt *pt = ptq->pt; | ||
1349 | union perf_event *event = ptq->event_buf; | ||
1350 | struct perf_sample sample = { .ip = 0, }; | ||
1351 | struct perf_synth_intel_pwre raw; | ||
1352 | |||
1353 | if (intel_pt_skip_event(pt)) | ||
1354 | return 0; | ||
1355 | |||
1356 | intel_pt_prep_p_sample(pt, ptq, event, &sample); | ||
1357 | |||
1358 | sample.id = ptq->pt->pwre_id; | ||
1359 | sample.stream_id = ptq->pt->pwre_id; | ||
1360 | |||
1361 | raw.reserved = 0; | ||
1362 | raw.payload = cpu_to_le64(ptq->state->pwre_payload); | ||
1363 | |||
1364 | sample.raw_size = perf_synth__raw_size(raw); | ||
1365 | sample.raw_data = perf_synth__raw_data(&raw); | ||
1366 | |||
1367 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, | ||
1368 | pt->pwr_events_sample_type); | ||
1369 | } | ||
1370 | |||
1371 | static int intel_pt_synth_exstop_sample(struct intel_pt_queue *ptq) | ||
1372 | { | ||
1373 | struct intel_pt *pt = ptq->pt; | ||
1374 | union perf_event *event = ptq->event_buf; | ||
1375 | struct perf_sample sample = { .ip = 0, }; | ||
1376 | struct perf_synth_intel_exstop raw; | ||
1377 | |||
1378 | if (intel_pt_skip_event(pt)) | ||
1379 | return 0; | ||
1380 | |||
1381 | intel_pt_prep_p_sample(pt, ptq, event, &sample); | ||
1382 | |||
1383 | sample.id = ptq->pt->exstop_id; | ||
1384 | sample.stream_id = ptq->pt->exstop_id; | ||
1385 | |||
1386 | raw.flags = 0; | ||
1387 | raw.ip = !!(ptq->state->flags & INTEL_PT_FUP_IP); | ||
1388 | |||
1389 | sample.raw_size = perf_synth__raw_size(raw); | ||
1390 | sample.raw_data = perf_synth__raw_data(&raw); | ||
1391 | |||
1392 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, | ||
1393 | pt->pwr_events_sample_type); | ||
1394 | } | ||
1395 | |||
1396 | static int intel_pt_synth_pwrx_sample(struct intel_pt_queue *ptq) | ||
1397 | { | ||
1398 | struct intel_pt *pt = ptq->pt; | ||
1399 | union perf_event *event = ptq->event_buf; | ||
1400 | struct perf_sample sample = { .ip = 0, }; | ||
1401 | struct perf_synth_intel_pwrx raw; | ||
1402 | |||
1403 | if (intel_pt_skip_event(pt)) | ||
1404 | return 0; | ||
1405 | |||
1406 | intel_pt_prep_p_sample(pt, ptq, event, &sample); | ||
1407 | |||
1408 | sample.id = ptq->pt->pwrx_id; | ||
1409 | sample.stream_id = ptq->pt->pwrx_id; | ||
1410 | |||
1411 | raw.reserved = 0; | ||
1412 | raw.payload = cpu_to_le64(ptq->state->pwrx_payload); | ||
1413 | |||
1414 | sample.raw_size = perf_synth__raw_size(raw); | ||
1415 | sample.raw_data = perf_synth__raw_data(&raw); | ||
1416 | |||
1417 | return intel_pt_deliver_synth_event(pt, ptq, event, &sample, | ||
1418 | pt->pwr_events_sample_type); | ||
1260 | } | 1419 | } |
1261 | 1420 | ||
1262 | static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu, | 1421 | static int intel_pt_synth_error(struct intel_pt *pt, int code, int cpu, |
@@ -1310,6 +1469,10 @@ static inline bool intel_pt_is_switch_ip(struct intel_pt_queue *ptq, u64 ip) | |||
1310 | PERF_IP_FLAG_INTERRUPT | PERF_IP_FLAG_TX_ABORT)); | 1469 | PERF_IP_FLAG_INTERRUPT | PERF_IP_FLAG_TX_ABORT)); |
1311 | } | 1470 | } |
1312 | 1471 | ||
1472 | #define INTEL_PT_PWR_EVT (INTEL_PT_MWAIT_OP | INTEL_PT_PWR_ENTRY | \ | ||
1473 | INTEL_PT_EX_STOP | INTEL_PT_PWR_EXIT | \ | ||
1474 | INTEL_PT_CBR_CHG) | ||
1475 | |||
1313 | static int intel_pt_sample(struct intel_pt_queue *ptq) | 1476 | static int intel_pt_sample(struct intel_pt_queue *ptq) |
1314 | { | 1477 | { |
1315 | const struct intel_pt_state *state = ptq->state; | 1478 | const struct intel_pt_state *state = ptq->state; |
@@ -1321,20 +1484,52 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) | |||
1321 | 1484 | ||
1322 | ptq->have_sample = false; | 1485 | ptq->have_sample = false; |
1323 | 1486 | ||
1324 | if (pt->sample_instructions && | 1487 | if (pt->sample_pwr_events && (state->type & INTEL_PT_PWR_EVT)) { |
1325 | (state->type & INTEL_PT_INSTRUCTION)) { | 1488 | if (state->type & INTEL_PT_CBR_CHG) { |
1489 | err = intel_pt_synth_cbr_sample(ptq); | ||
1490 | if (err) | ||
1491 | return err; | ||
1492 | } | ||
1493 | if (state->type & INTEL_PT_MWAIT_OP) { | ||
1494 | err = intel_pt_synth_mwait_sample(ptq); | ||
1495 | if (err) | ||
1496 | return err; | ||
1497 | } | ||
1498 | if (state->type & INTEL_PT_PWR_ENTRY) { | ||
1499 | err = intel_pt_synth_pwre_sample(ptq); | ||
1500 | if (err) | ||
1501 | return err; | ||
1502 | } | ||
1503 | if (state->type & INTEL_PT_EX_STOP) { | ||
1504 | err = intel_pt_synth_exstop_sample(ptq); | ||
1505 | if (err) | ||
1506 | return err; | ||
1507 | } | ||
1508 | if (state->type & INTEL_PT_PWR_EXIT) { | ||
1509 | err = intel_pt_synth_pwrx_sample(ptq); | ||
1510 | if (err) | ||
1511 | return err; | ||
1512 | } | ||
1513 | } | ||
1514 | |||
1515 | if (pt->sample_instructions && (state->type & INTEL_PT_INSTRUCTION)) { | ||
1326 | err = intel_pt_synth_instruction_sample(ptq); | 1516 | err = intel_pt_synth_instruction_sample(ptq); |
1327 | if (err) | 1517 | if (err) |
1328 | return err; | 1518 | return err; |
1329 | } | 1519 | } |
1330 | 1520 | ||
1331 | if (pt->sample_transactions && | 1521 | if (pt->sample_transactions && (state->type & INTEL_PT_TRANSACTION)) { |
1332 | (state->type & INTEL_PT_TRANSACTION)) { | ||
1333 | err = intel_pt_synth_transaction_sample(ptq); | 1522 | err = intel_pt_synth_transaction_sample(ptq); |
1334 | if (err) | 1523 | if (err) |
1335 | return err; | 1524 | return err; |
1336 | } | 1525 | } |
1337 | 1526 | ||
1527 | if (pt->sample_ptwrites && (state->type & INTEL_PT_PTW)) { | ||
1528 | err = intel_pt_synth_ptwrite_sample(ptq); | ||
1529 | if (err) | ||
1530 | return err; | ||
1531 | } | ||
1532 | |||
1338 | if (!(state->type & INTEL_PT_BRANCH)) | 1533 | if (!(state->type & INTEL_PT_BRANCH)) |
1339 | return 0; | 1534 | return 0; |
1340 | 1535 | ||
@@ -1935,36 +2130,65 @@ static int intel_pt_event_synth(struct perf_tool *tool, | |||
1935 | NULL); | 2130 | NULL); |
1936 | } | 2131 | } |
1937 | 2132 | ||
1938 | static int intel_pt_synth_event(struct perf_session *session, | 2133 | static int intel_pt_synth_event(struct perf_session *session, const char *name, |
1939 | struct perf_event_attr *attr, u64 id) | 2134 | struct perf_event_attr *attr, u64 id) |
1940 | { | 2135 | { |
1941 | struct intel_pt_synth intel_pt_synth; | 2136 | struct intel_pt_synth intel_pt_synth; |
2137 | int err; | ||
2138 | |||
2139 | pr_debug("Synthesizing '%s' event with id %" PRIu64 " sample type %#" PRIx64 "\n", | ||
2140 | name, id, (u64)attr->sample_type); | ||
1942 | 2141 | ||
1943 | memset(&intel_pt_synth, 0, sizeof(struct intel_pt_synth)); | 2142 | memset(&intel_pt_synth, 0, sizeof(struct intel_pt_synth)); |
1944 | intel_pt_synth.session = session; | 2143 | intel_pt_synth.session = session; |
1945 | 2144 | ||
1946 | return perf_event__synthesize_attr(&intel_pt_synth.dummy_tool, attr, 1, | 2145 | err = perf_event__synthesize_attr(&intel_pt_synth.dummy_tool, attr, 1, |
1947 | &id, intel_pt_event_synth); | 2146 | &id, intel_pt_event_synth); |
2147 | if (err) | ||
2148 | pr_err("%s: failed to synthesize '%s' event type\n", | ||
2149 | __func__, name); | ||
2150 | |||
2151 | return err; | ||
1948 | } | 2152 | } |
1949 | 2153 | ||
1950 | static int intel_pt_synth_events(struct intel_pt *pt, | 2154 | static void intel_pt_set_event_name(struct perf_evlist *evlist, u64 id, |
1951 | struct perf_session *session) | 2155 | const char *name) |
1952 | { | 2156 | { |
1953 | struct perf_evlist *evlist = session->evlist; | ||
1954 | struct perf_evsel *evsel; | 2157 | struct perf_evsel *evsel; |
1955 | struct perf_event_attr attr; | ||
1956 | bool found = false; | ||
1957 | u64 id; | ||
1958 | int err; | ||
1959 | 2158 | ||
1960 | evlist__for_each_entry(evlist, evsel) { | 2159 | evlist__for_each_entry(evlist, evsel) { |
1961 | if (evsel->attr.type == pt->pmu_type && evsel->ids) { | 2160 | if (evsel->id && evsel->id[0] == id) { |
1962 | found = true; | 2161 | if (evsel->name) |
2162 | zfree(&evsel->name); | ||
2163 | evsel->name = strdup(name); | ||
1963 | break; | 2164 | break; |
1964 | } | 2165 | } |
1965 | } | 2166 | } |
2167 | } | ||
2168 | |||
2169 | static struct perf_evsel *intel_pt_evsel(struct intel_pt *pt, | ||
2170 | struct perf_evlist *evlist) | ||
2171 | { | ||
2172 | struct perf_evsel *evsel; | ||
2173 | |||
2174 | evlist__for_each_entry(evlist, evsel) { | ||
2175 | if (evsel->attr.type == pt->pmu_type && evsel->ids) | ||
2176 | return evsel; | ||
2177 | } | ||
2178 | |||
2179 | return NULL; | ||
2180 | } | ||
2181 | |||
2182 | static int intel_pt_synth_events(struct intel_pt *pt, | ||
2183 | struct perf_session *session) | ||
2184 | { | ||
2185 | struct perf_evlist *evlist = session->evlist; | ||
2186 | struct perf_evsel *evsel = intel_pt_evsel(pt, evlist); | ||
2187 | struct perf_event_attr attr; | ||
2188 | u64 id; | ||
2189 | int err; | ||
1966 | 2190 | ||
1967 | if (!found) { | 2191 | if (!evsel) { |
1968 | pr_debug("There are no selected events with Intel Processor Trace data\n"); | 2192 | pr_debug("There are no selected events with Intel Processor Trace data\n"); |
1969 | return 0; | 2193 | return 0; |
1970 | } | 2194 | } |
@@ -1993,6 +2217,25 @@ static int intel_pt_synth_events(struct intel_pt *pt, | |||
1993 | if (!id) | 2217 | if (!id) |
1994 | id = 1; | 2218 | id = 1; |
1995 | 2219 | ||
2220 | if (pt->synth_opts.branches) { | ||
2221 | attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS; | ||
2222 | attr.sample_period = 1; | ||
2223 | attr.sample_type |= PERF_SAMPLE_ADDR; | ||
2224 | err = intel_pt_synth_event(session, "branches", &attr, id); | ||
2225 | if (err) | ||
2226 | return err; | ||
2227 | pt->sample_branches = true; | ||
2228 | pt->branches_sample_type = attr.sample_type; | ||
2229 | pt->branches_id = id; | ||
2230 | id += 1; | ||
2231 | attr.sample_type &= ~(u64)PERF_SAMPLE_ADDR; | ||
2232 | } | ||
2233 | |||
2234 | if (pt->synth_opts.callchain) | ||
2235 | attr.sample_type |= PERF_SAMPLE_CALLCHAIN; | ||
2236 | if (pt->synth_opts.last_branch) | ||
2237 | attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; | ||
2238 | |||
1996 | if (pt->synth_opts.instructions) { | 2239 | if (pt->synth_opts.instructions) { |
1997 | attr.config = PERF_COUNT_HW_INSTRUCTIONS; | 2240 | attr.config = PERF_COUNT_HW_INSTRUCTIONS; |
1998 | if (pt->synth_opts.period_type == PERF_ITRACE_PERIOD_NANOSECS) | 2241 | if (pt->synth_opts.period_type == PERF_ITRACE_PERIOD_NANOSECS) |
@@ -2000,71 +2243,90 @@ static int intel_pt_synth_events(struct intel_pt *pt, | |||
2000 | intel_pt_ns_to_ticks(pt, pt->synth_opts.period); | 2243 | intel_pt_ns_to_ticks(pt, pt->synth_opts.period); |
2001 | else | 2244 | else |
2002 | attr.sample_period = pt->synth_opts.period; | 2245 | attr.sample_period = pt->synth_opts.period; |
2003 | pt->instructions_sample_period = attr.sample_period; | 2246 | err = intel_pt_synth_event(session, "instructions", &attr, id); |
2004 | if (pt->synth_opts.callchain) | 2247 | if (err) |
2005 | attr.sample_type |= PERF_SAMPLE_CALLCHAIN; | ||
2006 | if (pt->synth_opts.last_branch) | ||
2007 | attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; | ||
2008 | pr_debug("Synthesizing 'instructions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", | ||
2009 | id, (u64)attr.sample_type); | ||
2010 | err = intel_pt_synth_event(session, &attr, id); | ||
2011 | if (err) { | ||
2012 | pr_err("%s: failed to synthesize 'instructions' event type\n", | ||
2013 | __func__); | ||
2014 | return err; | 2248 | return err; |
2015 | } | ||
2016 | pt->sample_instructions = true; | 2249 | pt->sample_instructions = true; |
2017 | pt->instructions_sample_type = attr.sample_type; | 2250 | pt->instructions_sample_type = attr.sample_type; |
2018 | pt->instructions_id = id; | 2251 | pt->instructions_id = id; |
2019 | id += 1; | 2252 | id += 1; |
2020 | } | 2253 | } |
2021 | 2254 | ||
2255 | attr.sample_type &= ~(u64)PERF_SAMPLE_PERIOD; | ||
2256 | attr.sample_period = 1; | ||
2257 | |||
2022 | if (pt->synth_opts.transactions) { | 2258 | if (pt->synth_opts.transactions) { |
2023 | attr.config = PERF_COUNT_HW_INSTRUCTIONS; | 2259 | attr.config = PERF_COUNT_HW_INSTRUCTIONS; |
2024 | attr.sample_period = 1; | 2260 | err = intel_pt_synth_event(session, "transactions", &attr, id); |
2025 | if (pt->synth_opts.callchain) | 2261 | if (err) |
2026 | attr.sample_type |= PERF_SAMPLE_CALLCHAIN; | ||
2027 | if (pt->synth_opts.last_branch) | ||
2028 | attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; | ||
2029 | pr_debug("Synthesizing 'transactions' event with id %" PRIu64 " sample type %#" PRIx64 "\n", | ||
2030 | id, (u64)attr.sample_type); | ||
2031 | err = intel_pt_synth_event(session, &attr, id); | ||
2032 | if (err) { | ||
2033 | pr_err("%s: failed to synthesize 'transactions' event type\n", | ||
2034 | __func__); | ||
2035 | return err; | 2262 | return err; |
2036 | } | ||
2037 | pt->sample_transactions = true; | 2263 | pt->sample_transactions = true; |
2038 | pt->transactions_sample_type = attr.sample_type; | 2264 | pt->transactions_sample_type = attr.sample_type; |
2039 | pt->transactions_id = id; | 2265 | pt->transactions_id = id; |
2266 | intel_pt_set_event_name(evlist, id, "transactions"); | ||
2040 | id += 1; | 2267 | id += 1; |
2041 | evlist__for_each_entry(evlist, evsel) { | ||
2042 | if (evsel->id && evsel->id[0] == pt->transactions_id) { | ||
2043 | if (evsel->name) | ||
2044 | zfree(&evsel->name); | ||
2045 | evsel->name = strdup("transactions"); | ||
2046 | break; | ||
2047 | } | ||
2048 | } | ||
2049 | } | 2268 | } |
2050 | 2269 | ||
2051 | if (pt->synth_opts.branches) { | 2270 | attr.type = PERF_TYPE_SYNTH; |
2052 | attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS; | 2271 | attr.sample_type |= PERF_SAMPLE_RAW; |
2053 | attr.sample_period = 1; | 2272 | |
2054 | attr.sample_type |= PERF_SAMPLE_ADDR; | 2273 | if (pt->synth_opts.ptwrites) { |
2055 | attr.sample_type &= ~(u64)PERF_SAMPLE_CALLCHAIN; | 2274 | attr.config = PERF_SYNTH_INTEL_PTWRITE; |
2056 | attr.sample_type &= ~(u64)PERF_SAMPLE_BRANCH_STACK; | 2275 | err = intel_pt_synth_event(session, "ptwrite", &attr, id); |
2057 | pr_debug("Synthesizing 'branches' event with id %" PRIu64 " sample type %#" PRIx64 "\n", | 2276 | if (err) |
2058 | id, (u64)attr.sample_type); | ||
2059 | err = intel_pt_synth_event(session, &attr, id); | ||
2060 | if (err) { | ||
2061 | pr_err("%s: failed to synthesize 'branches' event type\n", | ||
2062 | __func__); | ||
2063 | return err; | 2277 | return err; |
2064 | } | 2278 | pt->sample_ptwrites = true; |
2065 | pt->sample_branches = true; | 2279 | pt->ptwrites_sample_type = attr.sample_type; |
2066 | pt->branches_sample_type = attr.sample_type; | 2280 | pt->ptwrites_id = id; |
2067 | pt->branches_id = id; | 2281 | intel_pt_set_event_name(evlist, id, "ptwrite"); |
2282 | id += 1; | ||
2283 | } | ||
2284 | |||
2285 | if (pt->synth_opts.pwr_events) { | ||
2286 | pt->sample_pwr_events = true; | ||
2287 | pt->pwr_events_sample_type = attr.sample_type; | ||
2288 | |||
2289 | attr.config = PERF_SYNTH_INTEL_CBR; | ||
2290 | err = intel_pt_synth_event(session, "cbr", &attr, id); | ||
2291 | if (err) | ||
2292 | return err; | ||
2293 | pt->cbr_id = id; | ||
2294 | intel_pt_set_event_name(evlist, id, "cbr"); | ||
2295 | id += 1; | ||
2296 | } | ||
2297 | |||
2298 | if (pt->synth_opts.pwr_events && (evsel->attr.config & 0x10)) { | ||
2299 | attr.config = PERF_SYNTH_INTEL_MWAIT; | ||
2300 | err = intel_pt_synth_event(session, "mwait", &attr, id); | ||
2301 | if (err) | ||
2302 | return err; | ||
2303 | pt->mwait_id = id; | ||
2304 | intel_pt_set_event_name(evlist, id, "mwait"); | ||
2305 | id += 1; | ||
2306 | |||
2307 | attr.config = PERF_SYNTH_INTEL_PWRE; | ||
2308 | err = intel_pt_synth_event(session, "pwre", &attr, id); | ||
2309 | if (err) | ||
2310 | return err; | ||
2311 | pt->pwre_id = id; | ||
2312 | intel_pt_set_event_name(evlist, id, "pwre"); | ||
2313 | id += 1; | ||
2314 | |||
2315 | attr.config = PERF_SYNTH_INTEL_EXSTOP; | ||
2316 | err = intel_pt_synth_event(session, "exstop", &attr, id); | ||
2317 | if (err) | ||
2318 | return err; | ||
2319 | pt->exstop_id = id; | ||
2320 | intel_pt_set_event_name(evlist, id, "exstop"); | ||
2321 | id += 1; | ||
2322 | |||
2323 | attr.config = PERF_SYNTH_INTEL_PWRX; | ||
2324 | err = intel_pt_synth_event(session, "pwrx", &attr, id); | ||
2325 | if (err) | ||
2326 | return err; | ||
2327 | pt->pwrx_id = id; | ||
2328 | intel_pt_set_event_name(evlist, id, "pwrx"); | ||
2329 | id += 1; | ||
2068 | } | 2330 | } |
2069 | 2331 | ||
2070 | pt->synth_needs_swap = evsel->needs_swap; | 2332 | pt->synth_needs_swap = evsel->needs_swap; |
@@ -2333,6 +2595,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event, | |||
2333 | intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq); | 2595 | intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq); |
2334 | intel_pt_log("Maximum non-turbo ratio %u\n", | 2596 | intel_pt_log("Maximum non-turbo ratio %u\n", |
2335 | pt->max_non_turbo_ratio); | 2597 | pt->max_non_turbo_ratio); |
2598 | pt->cbr2khz = tsc_freq / pt->max_non_turbo_ratio / 1000; | ||
2336 | } | 2599 | } |
2337 | 2600 | ||
2338 | if (pt->synth_opts.calls) | 2601 | if (pt->synth_opts.calls) |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 5762ae4e9e91..8b327c955a4f 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -2532,12 +2532,12 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str, | |||
2532 | ret = sort_dimension__add(list, tok, evlist, level); | 2532 | ret = sort_dimension__add(list, tok, evlist, level); |
2533 | if (ret == -EINVAL) { | 2533 | if (ret == -EINVAL) { |
2534 | if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok))) | 2534 | if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok))) |
2535 | error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system"); | 2535 | pr_err("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system"); |
2536 | else | 2536 | else |
2537 | error("Invalid --sort key: `%s'", tok); | 2537 | pr_err("Invalid --sort key: `%s'", tok); |
2538 | break; | 2538 | break; |
2539 | } else if (ret == -ESRCH) { | 2539 | } else if (ret == -ESRCH) { |
2540 | error("Unknown --sort key: `%s'", tok); | 2540 | pr_err("Unknown --sort key: `%s'", tok); |
2541 | break; | 2541 | break; |
2542 | } | 2542 | } |
2543 | } | 2543 | } |
@@ -2594,7 +2594,7 @@ static int setup_sort_order(struct perf_evlist *evlist) | |||
2594 | return 0; | 2594 | return 0; |
2595 | 2595 | ||
2596 | if (sort_order[1] == '\0') { | 2596 | if (sort_order[1] == '\0') { |
2597 | error("Invalid --sort key: `+'"); | 2597 | pr_err("Invalid --sort key: `+'"); |
2598 | return -EINVAL; | 2598 | return -EINVAL; |
2599 | } | 2599 | } |
2600 | 2600 | ||
@@ -2604,7 +2604,7 @@ static int setup_sort_order(struct perf_evlist *evlist) | |||
2604 | */ | 2604 | */ |
2605 | if (asprintf(&new_sort_order, "%s,%s", | 2605 | if (asprintf(&new_sort_order, "%s,%s", |
2606 | get_default_sort_order(evlist), sort_order + 1) < 0) { | 2606 | get_default_sort_order(evlist), sort_order + 1) < 0) { |
2607 | error("Not enough memory to set up --sort"); | 2607 | pr_err("Not enough memory to set up --sort"); |
2608 | return -ENOMEM; | 2608 | return -ENOMEM; |
2609 | } | 2609 | } |
2610 | 2610 | ||
@@ -2668,7 +2668,7 @@ static int __setup_sorting(struct perf_evlist *evlist) | |||
2668 | 2668 | ||
2669 | str = strdup(sort_keys); | 2669 | str = strdup(sort_keys); |
2670 | if (str == NULL) { | 2670 | if (str == NULL) { |
2671 | error("Not enough memory to setup sort keys"); | 2671 | pr_err("Not enough memory to setup sort keys"); |
2672 | return -ENOMEM; | 2672 | return -ENOMEM; |
2673 | } | 2673 | } |
2674 | 2674 | ||
@@ -2678,7 +2678,7 @@ static int __setup_sorting(struct perf_evlist *evlist) | |||
2678 | if (!is_strict_order(field_order)) { | 2678 | if (!is_strict_order(field_order)) { |
2679 | str = setup_overhead(str); | 2679 | str = setup_overhead(str); |
2680 | if (str == NULL) { | 2680 | if (str == NULL) { |
2681 | error("Not enough memory to setup overhead keys"); | 2681 | pr_err("Not enough memory to setup overhead keys"); |
2682 | return -ENOMEM; | 2682 | return -ENOMEM; |
2683 | } | 2683 | } |
2684 | } | 2684 | } |
@@ -2834,10 +2834,10 @@ static int setup_output_list(struct perf_hpp_list *list, char *str) | |||
2834 | tok; tok = strtok_r(NULL, ", ", &tmp)) { | 2834 | tok; tok = strtok_r(NULL, ", ", &tmp)) { |
2835 | ret = output_field_add(list, tok); | 2835 | ret = output_field_add(list, tok); |
2836 | if (ret == -EINVAL) { | 2836 | if (ret == -EINVAL) { |
2837 | error("Invalid --fields key: `%s'", tok); | 2837 | pr_err("Invalid --fields key: `%s'", tok); |
2838 | break; | 2838 | break; |
2839 | } else if (ret == -ESRCH) { | 2839 | } else if (ret == -ESRCH) { |
2840 | error("Unknown --fields key: `%s'", tok); | 2840 | pr_err("Unknown --fields key: `%s'", tok); |
2841 | break; | 2841 | break; |
2842 | } | 2842 | } |
2843 | } | 2843 | } |
@@ -2877,7 +2877,7 @@ static int __setup_output_field(void) | |||
2877 | 2877 | ||
2878 | strp = str = strdup(field_order); | 2878 | strp = str = strdup(field_order); |
2879 | if (str == NULL) { | 2879 | if (str == NULL) { |
2880 | error("Not enough memory to setup output fields"); | 2880 | pr_err("Not enough memory to setup output fields"); |
2881 | return -ENOMEM; | 2881 | return -ENOMEM; |
2882 | } | 2882 | } |
2883 | 2883 | ||
@@ -2885,7 +2885,7 @@ static int __setup_output_field(void) | |||
2885 | strp++; | 2885 | strp++; |
2886 | 2886 | ||
2887 | if (!strlen(strp)) { | 2887 | if (!strlen(strp)) { |
2888 | error("Invalid --fields key: `+'"); | 2888 | pr_err("Invalid --fields key: `+'"); |
2889 | goto out; | 2889 | goto out; |
2890 | } | 2890 | } |
2891 | 2891 | ||
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 746bbee645d9..e0a6e9a6a053 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <errno.h> | 24 | #include <errno.h> |
25 | 25 | ||
26 | #include "../perf.h" | 26 | #include "../perf.h" |
27 | #include "util.h" | 27 | #include "debug.h" |
28 | #include "trace-event.h" | 28 | #include "trace-event.h" |
29 | 29 | ||
30 | #include "sane_ctype.h" | 30 | #include "sane_ctype.h" |
@@ -150,7 +150,7 @@ void parse_ftrace_printk(struct pevent *pevent, | |||
150 | while (line) { | 150 | while (line) { |
151 | addr_str = strtok_r(line, ":", &fmt); | 151 | addr_str = strtok_r(line, ":", &fmt); |
152 | if (!addr_str) { | 152 | if (!addr_str) { |
153 | warning("printk format with empty entry"); | 153 | pr_warning("printk format with empty entry"); |
154 | break; | 154 | break; |
155 | } | 155 | } |
156 | addr = strtoull(addr_str, NULL, 16); | 156 | addr = strtoull(addr_str, NULL, 16); |
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c index aacb65e079aa..6cc9d9888ce0 100644 --- a/tools/perf/util/usage.c +++ b/tools/perf/util/usage.c | |||
@@ -9,75 +9,17 @@ | |||
9 | #include "util.h" | 9 | #include "util.h" |
10 | #include "debug.h" | 10 | #include "debug.h" |
11 | 11 | ||
12 | static void report(const char *prefix, const char *err, va_list params) | ||
13 | { | ||
14 | char msg[1024]; | ||
15 | vsnprintf(msg, sizeof(msg), err, params); | ||
16 | fprintf(stderr, " %s%s\n", prefix, msg); | ||
17 | } | ||
18 | |||
19 | static __noreturn void usage_builtin(const char *err) | 12 | static __noreturn void usage_builtin(const char *err) |
20 | { | 13 | { |
21 | fprintf(stderr, "\n Usage: %s\n", err); | 14 | fprintf(stderr, "\n Usage: %s\n", err); |
22 | exit(129); | 15 | exit(129); |
23 | } | 16 | } |
24 | 17 | ||
25 | static __noreturn void die_builtin(const char *err, va_list params) | ||
26 | { | ||
27 | report(" Fatal: ", err, params); | ||
28 | exit(128); | ||
29 | } | ||
30 | |||
31 | static void error_builtin(const char *err, va_list params) | ||
32 | { | ||
33 | report(" Error: ", err, params); | ||
34 | } | ||
35 | |||
36 | static void warn_builtin(const char *warn, va_list params) | ||
37 | { | ||
38 | report(" Warning: ", warn, params); | ||
39 | } | ||
40 | |||
41 | /* If we are in a dlopen()ed .so write to a global variable would segfault | 18 | /* If we are in a dlopen()ed .so write to a global variable would segfault |
42 | * (ugh), so keep things static. */ | 19 | * (ugh), so keep things static. */ |
43 | static void (*usage_routine)(const char *err) __noreturn = usage_builtin; | 20 | static void (*usage_routine)(const char *err) __noreturn = usage_builtin; |
44 | static void (*error_routine)(const char *err, va_list params) = error_builtin; | ||
45 | static void (*warn_routine)(const char *err, va_list params) = warn_builtin; | ||
46 | |||
47 | void set_warning_routine(void (*routine)(const char *err, va_list params)) | ||
48 | { | ||
49 | warn_routine = routine; | ||
50 | } | ||
51 | 21 | ||
52 | void usage(const char *err) | 22 | void usage(const char *err) |
53 | { | 23 | { |
54 | usage_routine(err); | 24 | usage_routine(err); |
55 | } | 25 | } |
56 | |||
57 | void die(const char *err, ...) | ||
58 | { | ||
59 | va_list params; | ||
60 | |||
61 | va_start(params, err); | ||
62 | die_builtin(err, params); | ||
63 | va_end(params); | ||
64 | } | ||
65 | |||
66 | int error(const char *err, ...) | ||
67 | { | ||
68 | va_list params; | ||
69 | |||
70 | va_start(params, err); | ||
71 | error_routine(err, params); | ||
72 | va_end(params); | ||
73 | return -1; | ||
74 | } | ||
75 | |||
76 | void warning(const char *warn, ...) | ||
77 | { | ||
78 | va_list params; | ||
79 | |||
80 | va_start(params, warn); | ||
81 | warn_routine(warn, params); | ||
82 | va_end(params); | ||
83 | } | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 978572dfeb14..2c9e58a45310 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -16,10 +16,6 @@ | |||
16 | /* General helper functions */ | 16 | /* General helper functions */ |
17 | void usage(const char *err) __noreturn; | 17 | void usage(const char *err) __noreturn; |
18 | void die(const char *err, ...) __noreturn __printf(1, 2); | 18 | void die(const char *err, ...) __noreturn __printf(1, 2); |
19 | int error(const char *err, ...) __printf(1, 2); | ||
20 | void warning(const char *err, ...) __printf(1, 2); | ||
21 | |||
22 | void set_warning_routine(void (*routine)(const char *err, va_list params)); | ||
23 | 19 | ||
24 | static inline void *zalloc(size_t size) | 20 | static inline void *zalloc(size_t size) |
25 | { | 21 | { |