aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-01-09 11:17:33 -0500
committerIngo Molnar <mingo@kernel.org>2016-01-09 11:17:33 -0500
commit3eb9ede23bdd96e9ba60e2b4d4d17a7c35d58448 (patch)
tree2bed2ab8e7fa6e6202154992433bb24ecdb9a24d
parent9cc2617de5b9222abb39cd02e90d57dfea99c6d7 (diff)
parent775d8a1b0d75211cc6123915c6b5b688f2002478 (diff)
Merge tag 'perf-core-for-mingo' 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: New features: - Allow using trace events fields as sort order keys, making 'perf evlist --trace_fields' show those, and then the user can select a subset and use like: perf top -e sched:sched_switch -s prev_comm,next_comm That works as well in 'perf report' when handling files containing tracepoints. The default when just tracepoint events are found in a perf.data file is to format it like ftrace, using the libtraceevent formatters, plugins, etc (Namhyung Kim) - Add support in 'perf script' to process 'perf stat record' generated files, culminating in a python perf script that calculates CPI (Cycles per Instruction) (Jiri Olsa) - Show random perf tool tips in the 'perf report' bottom line (Namhyung Kim) - perf report now defaults to --group if the perf.data file has grouped events, try it with: # perf record -e '{cycles,instructions}' -a sleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 1.093 MB perf.data (1247 samples) ] # perf report # Samples: 1K of event 'anon group { cycles, instructions }' # Event count (approx.): 1955219195 # # Overhead Command Shared Object Symbol 2.86% 0.22% swapper [kernel.kallsyms] [k] intel_idle 1.05% 0.33% firefox libxul.so [.] js::SetObjectElement 1.05% 0.00% kworker/0:3 [kernel.kallsyms] [k] gen6_ring_get_seqno 0.88% 0.17% chrome chrome [.] 0x0000000000ee27ab 0.65% 0.86% firefox libxul.so [.] js::ValueToId<(js::AllowGC)1> 0.64% 0.23% JS Helper libxul.so [.] js::SplayTree<js::jit::LiveRange*, js::jit::LiveRange>::splay 0.62% 1.27% firefox libxul.so [.] js::GetIterator 0.61% 1.74% firefox libxul.so [.] js::NativeSetProperty 0.61% 0.31% firefox libxul.so [.] js::SetPropertyByDefining User visible fixes: - Coect data mmaps so that the DWARF unwinder can handle usecases needing them, like softice (Jiri Olsa) - Decay callchains in fractal mode, fixing up cases where 'perf top -g' would show entries with more than 100% (Namhyung Kim) Infrastructure changes: - Sync tools/lib with the lib/ in the kernel sources for find_bit.c and move bitmap.[ch] from tools/perf/util/ to tools/lib/ (Arnaldo Carvalho de Melo) - No need to set attr.sample_freq in some 'perf test' entries that only want to deal with PERF_RECORD_ meta-events, improve a bit error output for CQM test (Arnaldo Carvalho de Melo) - Fix python binding build, adding some missing object files now required due to cpumap using find_bit stuff (Arnaldo Carvalho de Melo) - tools/build improvemnts (Jiri Olsa) - Add more files to cscope/ctags databases (Jiri Olsa) - Do not show 'trace' in 'perf help' if it is not compiled in (Jiri Olsa) - Make perf_evlist__open() open evsels with their cpus and threads, like perf record does, making them consistent (Adrian Hunter) - Fix pmu snapshot initialization bug (Stephane Eranian) - Add missing headers in perf's MANIFEST (Wang Nan) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/build/Makefile.feature41
-rw-r--r--tools/include/linux/bitmap.h (renamed from tools/perf/util/include/linux/bitmap.h)2
-rw-r--r--tools/lib/bitmap.c (renamed from tools/perf/util/bitmap.c)0
-rw-r--r--tools/lib/bpf/Makefile4
-rw-r--r--tools/lib/find_bit.c84
-rw-r--r--tools/lib/traceevent/event-parse.c129
-rw-r--r--tools/lib/traceevent/event-parse.h4
-rw-r--r--tools/lib/util/find_next_bit.c89
-rw-r--r--tools/perf/Build1
-rw-r--r--tools/perf/Documentation/perf-evlist.txt3
-rw-r--r--tools/perf/Documentation/perf-report.txt27
-rw-r--r--tools/perf/Documentation/perf-top.txt3
-rw-r--r--tools/perf/Documentation/tips.txt14
-rw-r--r--tools/perf/MANIFEST4
-rw-r--r--tools/perf/Makefile.perf7
-rw-r--r--tools/perf/arch/x86/tests/intel-cqm.c2
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c1
-rw-r--r--tools/perf/arch/x86/util/intel-bts.c4
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c4
-rw-r--r--tools/perf/builtin-annotate.c9
-rw-r--r--tools/perf/builtin-diff.c15
-rw-r--r--tools/perf/builtin-evlist.c11
-rw-r--r--tools/perf/builtin-record.c6
-rw-r--r--tools/perf/builtin-report.c6
-rw-r--r--tools/perf/builtin-script.c170
-rw-r--r--tools/perf/builtin-stat.c9
-rw-r--r--tools/perf/builtin-top.c16
-rw-r--r--tools/perf/command-list.txt2
-rw-r--r--tools/perf/config/Makefile10
-rw-r--r--tools/perf/perf.c4
-rw-r--r--tools/perf/scripts/python/stat-cpi.py77
-rw-r--r--tools/perf/tests/hists_cumulate.c8
-rw-r--r--tools/perf/tests/hists_filter.c2
-rw-r--r--tools/perf/tests/hists_link.c8
-rw-r--r--tools/perf/tests/hists_output.c10
-rw-r--r--tools/perf/tests/keep-tracking.c3
-rw-r--r--tools/perf/tests/perf-record.c6
-rw-r--r--tools/perf/tests/switch-tracking.c6
-rw-r--r--tools/perf/ui/browsers/hists.c7
-rw-r--r--tools/perf/ui/gtk/hists.c4
-rw-r--r--tools/perf/ui/hist.c14
-rw-r--r--tools/perf/ui/stdio/hist.c6
-rw-r--r--tools/perf/util/Build11
-rw-r--r--tools/perf/util/callchain.c28
-rw-r--r--tools/perf/util/callchain.h1
-rw-r--r--tools/perf/util/cpumap.c13
-rw-r--r--tools/perf/util/evlist.c72
-rw-r--r--tools/perf/util/evlist.h7
-rw-r--r--tools/perf/util/evsel.c23
-rw-r--r--tools/perf/util/evsel.h1
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh15
-rw-r--r--tools/perf/util/hist.c78
-rw-r--r--tools/perf/util/hist.h24
-rw-r--r--tools/perf/util/pmu.c1
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c115
-rw-r--r--tools/perf/util/sort.c601
-rw-r--r--tools/perf/util/sort.h12
-rw-r--r--tools/perf/util/symbol.c1
-rw-r--r--tools/perf/util/symbol.h3
-rw-r--r--tools/perf/util/trace-event.h4
-rw-r--r--tools/perf/util/unwind-libdw.c10
-rw-r--r--tools/perf/util/unwind-libunwind.c20
-rw-r--r--tools/perf/util/util.c27
-rw-r--r--tools/perf/util/util.h2
65 files changed, 1556 insertions, 347 deletions
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 6c0519de765d..02db3cdff20f 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -122,13 +122,31 @@ define feature_print_text_code
122 MSG = $(shell printf '...%30s: %s' $(1) $(2)) 122 MSG = $(shell printf '...%30s: %s' $(1) $(2))
123endef 123endef
124 124
125#
126# generates feature value assignment for name, like:
127# $(call feature_assign,dwarf) == feature-dwarf=1
128#
129feature_assign = feature-$(1)=$(feature-$(1))
130
125FEATURE_DUMP_FILENAME = $(OUTPUT)FEATURE-DUMP$(FEATURE_USER) 131FEATURE_DUMP_FILENAME = $(OUTPUT)FEATURE-DUMP$(FEATURE_USER)
126FEATURE_DUMP := $(foreach feat,$(FEATURE_DISPLAY),feature-$(feat)($(feature-$(feat)))) 132FEATURE_DUMP := $(shell touch $(FEATURE_DUMP_FILENAME); cat $(FEATURE_DUMP_FILENAME))
127FEATURE_DUMP_FILE := $(shell touch $(FEATURE_DUMP_FILENAME); cat $(FEATURE_DUMP_FILENAME))
128 133
129ifeq ($(dwarf-post-unwind),1) 134feature_dump_check = $(eval $(feature_dump_check_code))
130 FEATURE_DUMP += dwarf-post-unwind($(dwarf-post-unwind-text)) 135define feature_dump_check_code
131endif 136 ifeq ($(findstring $(1),$(FEATURE_DUMP)),)
137 $(2) := 1
138 endif
139endef
140
141#
142# First check if any test from FEATURE_DISPLAY
143# and set feature_display := 1 if it does
144$(foreach feat,$(FEATURE_DISPLAY),$(call feature_dump_check,$(call feature_assign,$(feat)),feature_display))
145
146#
147# Now also check if any other test changed,
148# so we force FEATURE-DUMP generation
149$(foreach feat,$(FEATURE_TESTS),$(call feature_dump_check,$(call feature_assign,$(feat)),feature_dump_changed))
132 150
133# The $(feature_display) controls the default detection message 151# The $(feature_display) controls the default detection message
134# output. It's set if: 152# output. It's set if:
@@ -137,13 +155,13 @@ endif
137# - one of the $(FEATURE_DISPLAY) is not detected 155# - one of the $(FEATURE_DISPLAY) is not detected
138# - VF is enabled 156# - VF is enabled
139 157
140ifneq ("$(FEATURE_DUMP)","$(FEATURE_DUMP_FILE)") 158ifeq ($(feature_dump_changed),1)
141 $(shell echo "$(FEATURE_DUMP)" > $(FEATURE_DUMP_FILENAME)) 159 $(shell rm -f $(FEATURE_DUMP_FILENAME))
142 feature_display := 1 160 $(foreach feat,$(FEATURE_TESTS),$(shell echo "$(call feature_assign,$(feat))" >> $(FEATURE_DUMP_FILENAME)))
143endif 161endif
144 162
145feature_display_check = $(eval $(feature_check_display_code)) 163feature_display_check = $(eval $(feature_check_display_code))
146define feature_display_check_code 164define feature_check_display_code
147 ifneq ($(feature-$(1)), 1) 165 ifneq ($(feature-$(1)), 1)
148 feature_display := 1 166 feature_display := 1
149 endif 167 endif
@@ -160,11 +178,6 @@ ifeq ($(feature_display),1)
160 $(info ) 178 $(info )
161 $(info Auto-detecting system features:) 179 $(info Auto-detecting system features:)
162 $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),)) 180 $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),))
163
164 ifeq ($(dwarf-post-unwind),1)
165 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
166 endif
167
168 ifneq ($(feature_verbose),1) 181 ifneq ($(feature_verbose),1)
169 $(info ) 182 $(info )
170 endif 183 endif
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 40bd21488032..28f5493da491 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -11,6 +11,8 @@ int __bitmap_weight(const unsigned long *bitmap, int bits);
11void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, 11void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
12 const unsigned long *bitmap2, int bits); 12 const unsigned long *bitmap2, int bits);
13 13
14#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
15
14#define BITMAP_LAST_WORD_MASK(nbits) \ 16#define BITMAP_LAST_WORD_MASK(nbits) \
15( \ 17( \
16 ((nbits) % BITS_PER_LONG) ? \ 18 ((nbits) % BITS_PER_LONG) ? \
diff --git a/tools/perf/util/bitmap.c b/tools/lib/bitmap.c
index 0a1adc1111fd..0a1adc1111fd 100644
--- a/tools/perf/util/bitmap.c
+++ b/tools/lib/bitmap.c
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 636e3ddb93a1..919b71780710 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -80,7 +80,11 @@ endif
80endif 80endif
81 81
82ifeq ($(check_feat),1) 82ifeq ($(check_feat),1)
83ifeq ($(FEATURES_DUMP),)
83include $(srctree)/tools/build/Makefile.feature 84include $(srctree)/tools/build/Makefile.feature
85else
86include $(FEATURES_DUMP)
87endif
84endif 88endif
85 89
86export prefix libdir src obj 90export prefix libdir src obj
diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c
new file mode 100644
index 000000000000..9122a9e80046
--- /dev/null
+++ b/tools/lib/find_bit.c
@@ -0,0 +1,84 @@
1/* bit search implementation
2 *
3 * Copied from lib/find_bit.c to tools/lib/find_bit.c
4 *
5 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
7 *
8 * Copyright (C) 2008 IBM Corporation
9 * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au>
10 * (Inspired by David Howell's find_next_bit implementation)
11 *
12 * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
13 * size and improve performance, 2015.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version
18 * 2 of the License, or (at your option) any later version.
19 */
20
21#include <linux/bitops.h>
22#include <linux/bitmap.h>
23#include <linux/kernel.h>
24
25#if !defined(find_next_bit)
26
27/*
28 * This is a common helper function for find_next_bit and
29 * find_next_zero_bit. The difference is the "invert" argument, which
30 * is XORed with each fetched word before searching it for one bits.
31 */
32static unsigned long _find_next_bit(const unsigned long *addr,
33 unsigned long nbits, unsigned long start, unsigned long invert)
34{
35 unsigned long tmp;
36
37 if (!nbits || start >= nbits)
38 return nbits;
39
40 tmp = addr[start / BITS_PER_LONG] ^ invert;
41
42 /* Handle 1st word. */
43 tmp &= BITMAP_FIRST_WORD_MASK(start);
44 start = round_down(start, BITS_PER_LONG);
45
46 while (!tmp) {
47 start += BITS_PER_LONG;
48 if (start >= nbits)
49 return nbits;
50
51 tmp = addr[start / BITS_PER_LONG] ^ invert;
52 }
53
54 return min(start + __ffs(tmp), nbits);
55}
56#endif
57
58#ifndef find_next_bit
59/*
60 * Find the next set bit in a memory region.
61 */
62unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
63 unsigned long offset)
64{
65 return _find_next_bit(addr, size, offset, 0UL);
66}
67#endif
68
69#ifndef find_first_bit
70/*
71 * Find the first set bit in a memory region.
72 */
73unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
74{
75 unsigned long idx;
76
77 for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
78 if (addr[idx])
79 return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
80 }
81
82 return size;
83}
84#endif
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 68276f35e323..ea69ce35e902 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -4735,73 +4735,80 @@ static int is_printable_array(char *p, unsigned int len)
4735 return 1; 4735 return 1;
4736} 4736}
4737 4737
4738static void print_event_fields(struct trace_seq *s, void *data, 4738void pevent_print_field(struct trace_seq *s, void *data,
4739 int size __maybe_unused, 4739 struct format_field *field)
4740 struct event_format *event)
4741{ 4740{
4742 struct format_field *field;
4743 unsigned long long val; 4741 unsigned long long val;
4744 unsigned int offset, len, i; 4742 unsigned int offset, len, i;
4745 4743 struct pevent *pevent = field->event->pevent;
4746 field = event->format.fields; 4744
4747 while (field) { 4745 if (field->flags & FIELD_IS_ARRAY) {
4748 trace_seq_printf(s, " %s=", field->name); 4746 offset = field->offset;
4749 if (field->flags & FIELD_IS_ARRAY) { 4747 len = field->size;
4750 offset = field->offset; 4748 if (field->flags & FIELD_IS_DYNAMIC) {
4751 len = field->size; 4749 val = pevent_read_number(pevent, data + offset, len);
4752 if (field->flags & FIELD_IS_DYNAMIC) { 4750 offset = val;
4753 val = pevent_read_number(event->pevent, data + offset, len); 4751 len = offset >> 16;
4754 offset = val; 4752 offset &= 0xffff;
4755 len = offset >> 16; 4753 }
4756 offset &= 0xffff; 4754 if (field->flags & FIELD_IS_STRING &&
4757 } 4755 is_printable_array(data + offset, len)) {
4758 if (field->flags & FIELD_IS_STRING && 4756 trace_seq_printf(s, "%s", (char *)data + offset);
4759 is_printable_array(data + offset, len)) {
4760 trace_seq_printf(s, "%s", (char *)data + offset);
4761 } else {
4762 trace_seq_puts(s, "ARRAY[");
4763 for (i = 0; i < len; i++) {
4764 if (i)
4765 trace_seq_puts(s, ", ");
4766 trace_seq_printf(s, "%02x",
4767 *((unsigned char *)data + offset + i));
4768 }
4769 trace_seq_putc(s, ']');
4770 field->flags &= ~FIELD_IS_STRING;
4771 }
4772 } else { 4757 } else {
4773 val = pevent_read_number(event->pevent, data + field->offset, 4758 trace_seq_puts(s, "ARRAY[");
4774 field->size); 4759 for (i = 0; i < len; i++) {
4775 if (field->flags & FIELD_IS_POINTER) { 4760 if (i)
4776 trace_seq_printf(s, "0x%llx", val); 4761 trace_seq_puts(s, ", ");
4777 } else if (field->flags & FIELD_IS_SIGNED) { 4762 trace_seq_printf(s, "%02x",
4778 switch (field->size) { 4763 *((unsigned char *)data + offset + i));
4779 case 4: 4764 }
4780 /* 4765 trace_seq_putc(s, ']');
4781 * If field is long then print it in hex. 4766 field->flags &= ~FIELD_IS_STRING;
4782 * A long usually stores pointers. 4767 }
4783 */ 4768 } else {
4784 if (field->flags & FIELD_IS_LONG) 4769 val = pevent_read_number(pevent, data + field->offset,
4785 trace_seq_printf(s, "0x%x", (int)val); 4770 field->size);
4786 else 4771 if (field->flags & FIELD_IS_POINTER) {
4787 trace_seq_printf(s, "%d", (int)val); 4772 trace_seq_printf(s, "0x%llx", val);
4788 break; 4773 } else if (field->flags & FIELD_IS_SIGNED) {
4789 case 2: 4774 switch (field->size) {
4790 trace_seq_printf(s, "%2d", (short)val); 4775 case 4:
4791 break; 4776 /*
4792 case 1: 4777 * If field is long then print it in hex.
4793 trace_seq_printf(s, "%1d", (char)val); 4778 * A long usually stores pointers.
4794 break; 4779 */
4795 default:
4796 trace_seq_printf(s, "%lld", val);
4797 }
4798 } else {
4799 if (field->flags & FIELD_IS_LONG) 4780 if (field->flags & FIELD_IS_LONG)
4800 trace_seq_printf(s, "0x%llx", val); 4781 trace_seq_printf(s, "0x%x", (int)val);
4801 else 4782 else
4802 trace_seq_printf(s, "%llu", val); 4783 trace_seq_printf(s, "%d", (int)val);
4784 break;
4785 case 2:
4786 trace_seq_printf(s, "%2d", (short)val);
4787 break;
4788 case 1:
4789 trace_seq_printf(s, "%1d", (char)val);
4790 break;
4791 default:
4792 trace_seq_printf(s, "%lld", val);
4803 } 4793 }
4794 } else {
4795 if (field->flags & FIELD_IS_LONG)
4796 trace_seq_printf(s, "0x%llx", val);
4797 else
4798 trace_seq_printf(s, "%llu", val);
4804 } 4799 }
4800 }
4801}
4802
4803void pevent_print_fields(struct trace_seq *s, void *data,
4804 int size __maybe_unused, struct event_format *event)
4805{
4806 struct format_field *field;
4807
4808 field = event->format.fields;
4809 while (field) {
4810 trace_seq_printf(s, " %s=", field->name);
4811 pevent_print_field(s, data, field);
4805 field = field->next; 4812 field = field->next;
4806 } 4813 }
4807} 4814}
@@ -4827,7 +4834,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4827 4834
4828 if (event->flags & EVENT_FL_FAILED) { 4835 if (event->flags & EVENT_FL_FAILED) {
4829 trace_seq_printf(s, "[FAILED TO PARSE]"); 4836 trace_seq_printf(s, "[FAILED TO PARSE]");
4830 print_event_fields(s, data, size, event); 4837 pevent_print_fields(s, data, size, event);
4831 return; 4838 return;
4832 } 4839 }
4833 4840
@@ -5301,7 +5308,7 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
5301 int print_pretty = 1; 5308 int print_pretty = 1;
5302 5309
5303 if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW)) 5310 if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
5304 print_event_fields(s, record->data, record->size, event); 5311 pevent_print_fields(s, record->data, record->size, event);
5305 else { 5312 else {
5306 5313
5307 if (event->handler && !(event->flags & EVENT_FL_NOHANDLE)) 5314 if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 6fc83c7edbe9..706d9bc24066 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -705,6 +705,10 @@ struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *com
705 struct cmdline *next); 705 struct cmdline *next);
706int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline); 706int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline);
707 707
708void pevent_print_field(struct trace_seq *s, void *data,
709 struct format_field *field);
710void pevent_print_fields(struct trace_seq *s, void *data,
711 int size __maybe_unused, struct event_format *event);
708void pevent_event_info(struct trace_seq *s, struct event_format *event, 712void pevent_event_info(struct trace_seq *s, struct event_format *event,
709 struct pevent_record *record); 713 struct pevent_record *record);
710int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, 714int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
diff --git a/tools/lib/util/find_next_bit.c b/tools/lib/util/find_next_bit.c
deleted file mode 100644
index 41b44f65a79e..000000000000
--- a/tools/lib/util/find_next_bit.c
+++ /dev/null
@@ -1,89 +0,0 @@
1/* find_next_bit.c: fallback find next bit implementation
2 *
3 * Copied from lib/find_next_bit.c to tools/lib/next_bit.c
4 *
5 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <linux/bitops.h>
15#include <asm/types.h>
16#include <asm/byteorder.h>
17
18#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
19
20#ifndef find_next_bit
21/*
22 * Find the next set bit in a memory region.
23 */
24unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
25 unsigned long offset)
26{
27 const unsigned long *p = addr + BITOP_WORD(offset);
28 unsigned long result = offset & ~(BITS_PER_LONG-1);
29 unsigned long tmp;
30
31 if (offset >= size)
32 return size;
33 size -= result;
34 offset %= BITS_PER_LONG;
35 if (offset) {
36 tmp = *(p++);
37 tmp &= (~0UL << offset);
38 if (size < BITS_PER_LONG)
39 goto found_first;
40 if (tmp)
41 goto found_middle;
42 size -= BITS_PER_LONG;
43 result += BITS_PER_LONG;
44 }
45 while (size & ~(BITS_PER_LONG-1)) {
46 if ((tmp = *(p++)))
47 goto found_middle;
48 result += BITS_PER_LONG;
49 size -= BITS_PER_LONG;
50 }
51 if (!size)
52 return result;
53 tmp = *p;
54
55found_first:
56 tmp &= (~0UL >> (BITS_PER_LONG - size));
57 if (tmp == 0UL) /* Are any bits set? */
58 return result + size; /* Nope. */
59found_middle:
60 return result + __ffs(tmp);
61}
62#endif
63
64#ifndef find_first_bit
65/*
66 * Find the first set bit in a memory region.
67 */
68unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
69{
70 const unsigned long *p = addr;
71 unsigned long result = 0;
72 unsigned long tmp;
73
74 while (size & ~(BITS_PER_LONG-1)) {
75 if ((tmp = *(p++)))
76 goto found;
77 result += BITS_PER_LONG;
78 size -= BITS_PER_LONG;
79 }
80 if (!size)
81 return result;
82
83 tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
84 if (tmp == 0UL) /* Are any bits set? */
85 return result + size; /* Nope. */
86found:
87 return result + __ffs(tmp);
88}
89#endif
diff --git a/tools/perf/Build b/tools/perf/Build
index 00c4b8c3d8ca..6b67e6f4179f 100644
--- a/tools/perf/Build
+++ b/tools/perf/Build
@@ -41,6 +41,7 @@ CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" \
41 -DPREFIX="BUILD_STR($(prefix_SQ))" \ 41 -DPREFIX="BUILD_STR($(prefix_SQ))" \
42 -include $(OUTPUT)PERF-VERSION-FILE 42 -include $(OUTPUT)PERF-VERSION-FILE
43CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))" 43CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))"
44CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))"
44 45
45libperf-y += util/ 46libperf-y += util/
46libperf-y += arch/ 47libperf-y += arch/
diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
index 1ceb3700ffbb..6f7200fb85cf 100644
--- a/tools/perf/Documentation/perf-evlist.txt
+++ b/tools/perf/Documentation/perf-evlist.txt
@@ -32,6 +32,9 @@ OPTIONS
32--group:: 32--group::
33 Show event group information. 33 Show event group information.
34 34
35--trace-fields::
36 Show tracepoint field names.
37
35SEE ALSO 38SEE ALSO
36-------- 39--------
37linkperf:perf-record[1], linkperf:perf-list[1], 40linkperf:perf-record[1], linkperf:perf-list[1],
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index dab99ed2b339..8a301f6afb37 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -117,6 +117,30 @@ OPTIONS
117 And default sort keys are changed to comm, dso_from, symbol_from, dso_to 117 And default sort keys are changed to comm, dso_from, symbol_from, dso_to
118 and symbol_to, see '--branch-stack'. 118 and symbol_to, see '--branch-stack'.
119 119
120 If the data file has tracepoint event(s), following (dynamic) sort keys
121 are also available:
122 trace, trace_fields, [<event>.]<field>[/raw]
123
124 - trace: pretty printed trace output in a single column
125 - trace_fields: fields in tracepoints in separate columns
126 - <field name>: optional event and field name for a specific field
127
128 The last form consists of event and field names. If event name is
129 omitted, it searches all events for matching field name. The matched
130 field will be shown only for the event has the field. The event name
131 supports substring match so user doesn't need to specify full subsystem
132 and event name everytime. For example, 'sched:sched_switch' event can
133 be shortened to 'switch' as long as it's not ambiguous. Also event can
134 be specified by its index (starting from 1) preceded by the '%'.
135 So '%1' is the first event, '%2' is the second, and so on.
136
137 The field name can have '/raw' suffix which disables pretty printing
138 and shows raw field value like hex numbers. The --raw-trace option
139 has the same effect for all dynamic sort keys.
140
141 The default sort keys are changed to 'trace' if all events in the data
142 file are tracepoint.
143
120-F:: 144-F::
121--fields=:: 145--fields=::
122 Specify output field - multiple keys can be specified in CSV format. 146 Specify output field - multiple keys can be specified in CSV format.
@@ -371,6 +395,9 @@ include::itrace.txt[]
371--socket-filter:: 395--socket-filter::
372 Only report the samples on the processor socket that match with this filter 396 Only report the samples on the processor socket that match with this filter
373 397
398--raw-trace::
399 When displaying traceevent output, do not use print fmt or plugins.
400
374include::callchain-overhead-calculation.txt[] 401include::callchain-overhead-calculation.txt[]
375 402
376SEE ALSO 403SEE ALSO
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 556cec09bf50..b0e60e17db38 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -230,6 +230,9 @@ Default is to monitor all CPUS.
230 The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k 230 The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
231 Note that this feature may not be available on all processors. 231 Note that this feature may not be available on all processors.
232 232
233--raw-trace::
234 When displaying traceevent output, do not use print fmt or plugins.
235
233INTERACTIVE PROMPTING KEYS 236INTERACTIVE PROMPTING KEYS
234-------------------------- 237--------------------------
235 238
diff --git a/tools/perf/Documentation/tips.txt b/tools/perf/Documentation/tips.txt
new file mode 100644
index 000000000000..a1c10e360db5
--- /dev/null
+++ b/tools/perf/Documentation/tips.txt
@@ -0,0 +1,14 @@
1For a higher level overview, try: perf report --sort comm,dso
2Sample related events with: perf record -e '{cycles,instructions}:S'
3Compare performance results with: perf diff [<old file> <new file>]
4Boolean options have negative forms, e.g.: perf report --no-children
5Customize output of perf script with: perf script -F event,ip,sym
6Generate a script for your data: perf script -g <lang>
7Save output of perf stat using: perf stat record <target workload>
8Create an archive with symtabs to analyse on other machine: perf archive
9Search options using a keyword: perf report -h <keyword>
10Use parent filter to see specific call path: perf report -p <regex>
11List events using substring match: perf list <keyword>
12To see list of saved events and attributes: perf evlist -v
13Use --symfs <dir> if your symbol files are in non-standard locations
14To see callchains in a more compact form: perf report -g folded
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index ce3932ee4893..ddf922f93aa1 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,6 +1,7 @@
1tools/perf 1tools/perf
2tools/arch/alpha/include/asm/barrier.h 2tools/arch/alpha/include/asm/barrier.h
3tools/arch/arm/include/asm/barrier.h 3tools/arch/arm/include/asm/barrier.h
4tools/arch/arm64/include/asm/barrier.h
4tools/arch/ia64/include/asm/barrier.h 5tools/arch/ia64/include/asm/barrier.h
5tools/arch/mips/include/asm/barrier.h 6tools/arch/mips/include/asm/barrier.h
6tools/arch/powerpc/include/asm/barrier.h 7tools/arch/powerpc/include/asm/barrier.h
@@ -26,10 +27,11 @@ tools/lib/rbtree.c
26tools/lib/string.c 27tools/lib/string.c
27tools/lib/symbol/kallsyms.c 28tools/lib/symbol/kallsyms.c
28tools/lib/symbol/kallsyms.h 29tools/lib/symbol/kallsyms.h
29tools/lib/util/find_next_bit.c 30tools/lib/find_bit.c
30tools/include/asm/atomic.h 31tools/include/asm/atomic.h
31tools/include/asm/barrier.h 32tools/include/asm/barrier.h
32tools/include/asm/bug.h 33tools/include/asm/bug.h
34tools/include/asm-generic/atomic-gcc.h
33tools/include/asm-generic/barrier.h 35tools/include/asm-generic/barrier.h
34tools/include/asm-generic/bitops/arch_hweight.h 36tools/include/asm-generic/bitops/arch_hweight.h
35tools/include/asm-generic/bitops/atomic.h 37tools/include/asm-generic/bitops/atomic.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 569fcf022531..0a22407e1d7d 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -436,7 +436,7 @@ $(LIBAPI)-clean:
436 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null 436 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
437 437
438$(LIBBPF): fixdep FORCE 438$(LIBBPF): fixdep FORCE
439 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a 439 $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a FEATURES_DUMP=$(realpath $(OUTPUT)FEATURE-DUMP)
440 440
441$(LIBBPF)-clean: 441$(LIBBPF)-clean:
442 $(call QUIET_CLEAN, libbpf) 442 $(call QUIET_CLEAN, libbpf)
@@ -488,7 +488,7 @@ INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
488$(DOC_TARGETS): 488$(DOC_TARGETS):
489 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all) 489 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
490 490
491TAG_FOLDERS= . ../lib/traceevent ../lib/api ../lib/symbol ../include ../lib/bpf 491TAG_FOLDERS= . ../lib ../include
492TAG_FILES= ../../include/uapi/linux/perf_event.h 492TAG_FILES= ../../include/uapi/linux/perf_event.h
493 493
494TAGS: 494TAGS:
@@ -567,6 +567,9 @@ endif
567 $(call QUIET_INSTALL, perf_completion-script) \ 567 $(call QUIET_INSTALL, perf_completion-script) \
568 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \ 568 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
569 $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' 569 $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
570 $(call QUIET_INSTALL, perf-tip) \
571 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(tip_instdir_SQ)'; \
572 $(INSTALL) Documentation/tips.txt -t '$(DESTDIR_SQ)$(tip_instdir_SQ)'
570 573
571install-tests: all install-gtk 574install-tests: all install-gtk
572 $(call QUIET_INSTALL, tests) \ 575 $(call QUIET_INSTALL, tests) \
diff --git a/tools/perf/arch/x86/tests/intel-cqm.c b/tools/perf/arch/x86/tests/intel-cqm.c
index 94e0cb7462f9..3e89ba825f6b 100644
--- a/tools/perf/arch/x86/tests/intel-cqm.c
+++ b/tools/perf/arch/x86/tests/intel-cqm.c
@@ -54,7 +54,7 @@ int test__intel_cqm_count_nmi_context(int subtest __maybe_unused)
54 54
55 ret = parse_events(evlist, "intel_cqm/llc_occupancy/", NULL); 55 ret = parse_events(evlist, "intel_cqm/llc_occupancy/", NULL);
56 if (ret) { 56 if (ret) {
57 pr_debug("parse_events failed\n"); 57 pr_debug("parse_events failed, is \"intel_cqm/llc_occupancy/\" available?\n");
58 err = TEST_SKIP; 58 err = TEST_SKIP;
59 goto out; 59 goto out;
60 } 60 }
diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index a289aa8a083a..9d29ee283ac5 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -41,7 +41,6 @@ int test__perf_time_to_tsc(int subtest __maybe_unused)
41 .mmap_pages = UINT_MAX, 41 .mmap_pages = UINT_MAX,
42 .user_freq = UINT_MAX, 42 .user_freq = UINT_MAX,
43 .user_interval = ULLONG_MAX, 43 .user_interval = ULLONG_MAX,
44 .freq = 4000,
45 .target = { 44 .target = {
46 .uses_mmap = true, 45 .uses_mmap = true,
47 }, 46 },
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c
index 9b94ce520917..8d8150f1cf9b 100644
--- a/tools/perf/arch/x86/util/intel-bts.c
+++ b/tools/perf/arch/x86/util/intel-bts.c
@@ -327,7 +327,7 @@ static int intel_bts_snapshot_start(struct auxtrace_record *itr)
327 327
328 evlist__for_each(btsr->evlist, evsel) { 328 evlist__for_each(btsr->evlist, evsel) {
329 if (evsel->attr.type == btsr->intel_bts_pmu->type) 329 if (evsel->attr.type == btsr->intel_bts_pmu->type)
330 return perf_evlist__disable_event(btsr->evlist, evsel); 330 return perf_evsel__disable(evsel);
331 } 331 }
332 return -EINVAL; 332 return -EINVAL;
333} 333}
@@ -340,7 +340,7 @@ static int intel_bts_snapshot_finish(struct auxtrace_record *itr)
340 340
341 evlist__for_each(btsr->evlist, evsel) { 341 evlist__for_each(btsr->evlist, evsel) {
342 if (evsel->attr.type == btsr->intel_bts_pmu->type) 342 if (evsel->attr.type == btsr->intel_bts_pmu->type)
343 return perf_evlist__enable_event(btsr->evlist, evsel); 343 return perf_evsel__enable(evsel);
344 } 344 }
345 return -EINVAL; 345 return -EINVAL;
346} 346}
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index b64d46285ebb..f05daacc9e78 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -725,7 +725,7 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr)
725 725
726 evlist__for_each(ptr->evlist, evsel) { 726 evlist__for_each(ptr->evlist, evsel) {
727 if (evsel->attr.type == ptr->intel_pt_pmu->type) 727 if (evsel->attr.type == ptr->intel_pt_pmu->type)
728 return perf_evlist__disable_event(ptr->evlist, evsel); 728 return perf_evsel__disable(evsel);
729 } 729 }
730 return -EINVAL; 730 return -EINVAL;
731} 731}
@@ -738,7 +738,7 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr)
738 738
739 evlist__for_each(ptr->evlist, evsel) { 739 evlist__for_each(ptr->evlist, evsel) {
740 if (evsel->attr.type == ptr->intel_pt_pmu->type) 740 if (evsel->attr.type == ptr->intel_pt_pmu->type)
741 return perf_evlist__enable_event(ptr->evlist, evsel); 741 return perf_evsel__enable(evsel);
742 } 742 }
743 return -EINVAL; 743 return -EINVAL;
744} 744}
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index e18f1b995ffd..cc5c1267c738 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -47,7 +47,7 @@ struct perf_annotate {
47}; 47};
48 48
49static int perf_evsel__add_sample(struct perf_evsel *evsel, 49static int perf_evsel__add_sample(struct perf_evsel *evsel,
50 struct perf_sample *sample __maybe_unused, 50 struct perf_sample *sample,
51 struct addr_location *al, 51 struct addr_location *al,
52 struct perf_annotate *ann) 52 struct perf_annotate *ann)
53{ 53{
@@ -72,7 +72,10 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
72 return 0; 72 return 0;
73 } 73 }
74 74
75 he = __hists__add_entry(hists, al, NULL, NULL, NULL, 1, 1, 0, true); 75 sample->period = 1;
76 sample->weight = 1;
77
78 he = __hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
76 if (he == NULL) 79 if (he == NULL)
77 return -ENOMEM; 80 return -ENOMEM;
78 81
@@ -367,7 +370,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
367 if (ret < 0) 370 if (ret < 0)
368 goto out_delete; 371 goto out_delete;
369 372
370 if (setup_sorting() < 0) 373 if (setup_sorting(NULL) < 0)
371 usage_with_options(annotate_usage, options); 374 usage_with_options(annotate_usage, options);
372 375
373 if (annotate.use_stdio) 376 if (annotate.use_stdio)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 0b180a885ba3..36ccc2b8827f 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -311,11 +311,11 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
311} 311}
312 312
313static int hists__add_entry(struct hists *hists, 313static int hists__add_entry(struct hists *hists,
314 struct addr_location *al, u64 period, 314 struct addr_location *al,
315 u64 weight, u64 transaction) 315 struct perf_sample *sample)
316{ 316{
317 if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight, 317 if (__hists__add_entry(hists, al, NULL, NULL, NULL,
318 transaction, true) != NULL) 318 sample, true) != NULL)
319 return 0; 319 return 0;
320 return -ENOMEM; 320 return -ENOMEM;
321} 321}
@@ -336,8 +336,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
336 return -1; 336 return -1;
337 } 337 }
338 338
339 if (hists__add_entry(hists, &al, sample->period, 339 if (hists__add_entry(hists, &al, sample)) {
340 sample->weight, sample->transaction)) {
341 pr_warning("problem incrementing symbol period, skipping event\n"); 340 pr_warning("problem incrementing symbol period, skipping event\n");
342 goto out_put; 341 goto out_put;
343 } 342 }
@@ -1208,7 +1207,7 @@ static int ui_init(void)
1208 BUG_ON(1); 1207 BUG_ON(1);
1209 } 1208 }
1210 1209
1211 list_add(&fmt->sort_list, &perf_hpp__sort_list); 1210 perf_hpp__register_sort_field(fmt);
1212 return 0; 1211 return 0;
1213} 1212}
1214 1213
@@ -1280,7 +1279,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1280 1279
1281 sort__mode = SORT_MODE__DIFF; 1280 sort__mode = SORT_MODE__DIFF;
1282 1281
1283 if (setup_sorting() < 0) 1282 if (setup_sorting(NULL) < 0)
1284 usage_with_options(diff_usage, options); 1283 usage_with_options(diff_usage, options);
1285 1284
1286 setup_pager(); 1285 setup_pager();
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 08a7d36a2cf8..8a31f511e1a0 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -26,14 +26,22 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
26 .mode = PERF_DATA_MODE_READ, 26 .mode = PERF_DATA_MODE_READ,
27 .force = details->force, 27 .force = details->force,
28 }; 28 };
29 bool has_tracepoint = false;
29 30
30 session = perf_session__new(&file, 0, NULL); 31 session = perf_session__new(&file, 0, NULL);
31 if (session == NULL) 32 if (session == NULL)
32 return -1; 33 return -1;
33 34
34 evlist__for_each(session->evlist, pos) 35 evlist__for_each(session->evlist, pos) {
35 perf_evsel__fprintf(pos, details, stdout); 36 perf_evsel__fprintf(pos, details, stdout);
36 37
38 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
39 has_tracepoint = true;
40 }
41
42 if (has_tracepoint && !details->trace_fields)
43 printf("# Tip: use 'perf evlist --trace-fields' to show fields for tracepoint events\n");
44
37 perf_session__delete(session); 45 perf_session__delete(session);
38 return 0; 46 return 0;
39} 47}
@@ -49,6 +57,7 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
49 OPT_BOOLEAN('g', "group", &details.event_group, 57 OPT_BOOLEAN('g', "group", &details.event_group,
50 "Show event group information"), 58 "Show event group information"),
51 OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"), 59 OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"),
60 OPT_BOOLEAN(0, "trace-fields", &details.trace_fields, "Show tracepoint fields"),
52 OPT_END() 61 OPT_END()
53 }; 62 };
54 const char * const evlist_usage[] = { 63 const char * const evlist_usage[] = {
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 9c5cdc2c4471..dc4e0adf5c5b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -815,8 +815,12 @@ int record_parse_callchain_opt(const struct option *opt,
815 } 815 }
816 816
817 ret = parse_callchain_record_opt(arg, &callchain_param); 817 ret = parse_callchain_record_opt(arg, &callchain_param);
818 if (!ret) 818 if (!ret) {
819 /* Enable data address sampling for DWARF unwind. */
820 if (callchain_param.record_mode == CALLCHAIN_DWARF)
821 record->sample_address = true;
819 callchain_debug(); 822 callchain_debug();
823 }
820 824
821 return ret; 825 return ret;
822} 826}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2a7330b99b82..d5a42ee12529 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -433,7 +433,7 @@ static int report__browse_hists(struct report *rep)
433 int ret; 433 int ret;
434 struct perf_session *session = rep->session; 434 struct perf_session *session = rep->session;
435 struct perf_evlist *evlist = session->evlist; 435 struct perf_evlist *evlist = session->evlist;
436 const char *help = "For a higher level overview, try: perf report --sort comm,dso"; 436 const char *help = perf_tip(TIPDIR);
437 437
438 switch (use_browser) { 438 switch (use_browser) {
439 case 1: 439 case 1:
@@ -788,6 +788,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
788 "Show callgraph from reference event"), 788 "Show callgraph from reference event"),
789 OPT_INTEGER(0, "socket-filter", &report.socket_filter, 789 OPT_INTEGER(0, "socket-filter", &report.socket_filter,
790 "only show processor socket that match with this filter"), 790 "only show processor socket that match with this filter"),
791 OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
792 "Show raw trace event output (do not use print fmt or plugins)"),
791 OPT_END() 793 OPT_END()
792 }; 794 };
793 struct perf_data_file file = { 795 struct perf_data_file file = {
@@ -897,7 +899,7 @@ repeat:
897 symbol_conf.cumulate_callchain = false; 899 symbol_conf.cumulate_callchain = false;
898 } 900 }
899 901
900 if (setup_sorting() < 0) { 902 if (setup_sorting(session->evlist) < 0) {
901 if (sort_order) 903 if (sort_order)
902 parse_options_usage(report_usage, options, "s", 1); 904 parse_options_usage(report_usage, options, "s", 1);
903 if (field_order) 905 if (field_order)
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index bcc3542d9df5..c691214d820f 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -18,7 +18,11 @@
18#include "util/sort.h" 18#include "util/sort.h"
19#include "util/data.h" 19#include "util/data.h"
20#include "util/auxtrace.h" 20#include "util/auxtrace.h"
21#include "util/cpumap.h"
22#include "util/thread_map.h"
23#include "util/stat.h"
21#include <linux/bitmap.h> 24#include <linux/bitmap.h>
25#include "asm/bug.h"
22 26
23static char const *script_name; 27static char const *script_name;
24static char const *generate_script_lang; 28static char const *generate_script_lang;
@@ -32,6 +36,7 @@ static bool print_flags;
32static bool nanosecs; 36static bool nanosecs;
33static const char *cpu_list; 37static const char *cpu_list;
34static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 38static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
39static struct perf_stat_config stat_config;
35 40
36unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; 41unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
37 42
@@ -216,6 +221,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
216 struct perf_event_attr *attr = &evsel->attr; 221 struct perf_event_attr *attr = &evsel->attr;
217 bool allow_user_set; 222 bool allow_user_set;
218 223
224 if (perf_header__has_feat(&session->header, HEADER_STAT))
225 return 0;
226
219 allow_user_set = perf_header__has_feat(&session->header, 227 allow_user_set = perf_header__has_feat(&session->header,
220 HEADER_AUXTRACE); 228 HEADER_AUXTRACE);
221 229
@@ -606,9 +614,27 @@ struct perf_script {
606 bool show_task_events; 614 bool show_task_events;
607 bool show_mmap_events; 615 bool show_mmap_events;
608 bool show_switch_events; 616 bool show_switch_events;
617 bool allocated;
618 struct cpu_map *cpus;
619 struct thread_map *threads;
620 int name_width;
609}; 621};
610 622
611static void process_event(struct perf_script *script __maybe_unused, union perf_event *event, 623static int perf_evlist__max_name_len(struct perf_evlist *evlist)
624{
625 struct perf_evsel *evsel;
626 int max = 0;
627
628 evlist__for_each(evlist, evsel) {
629 int len = strlen(perf_evsel__name(evsel));
630
631 max = MAX(len, max);
632 }
633
634 return max;
635}
636
637static void process_event(struct perf_script *script, union perf_event *event,
612 struct perf_sample *sample, struct perf_evsel *evsel, 638 struct perf_sample *sample, struct perf_evsel *evsel,
613 struct addr_location *al) 639 struct addr_location *al)
614{ 640{
@@ -625,7 +651,12 @@ static void process_event(struct perf_script *script __maybe_unused, union perf_
625 651
626 if (PRINT_FIELD(EVNAME)) { 652 if (PRINT_FIELD(EVNAME)) {
627 const char *evname = perf_evsel__name(evsel); 653 const char *evname = perf_evsel__name(evsel);
628 printf("%s: ", evname ? evname : "[unknown]"); 654
655 if (!script->name_width)
656 script->name_width = perf_evlist__max_name_len(script->session->evlist);
657
658 printf("%*s: ", script->name_width,
659 evname ? evname : "[unknown]");
629 } 660 }
630 661
631 if (print_flags) 662 if (print_flags)
@@ -666,6 +697,54 @@ static void process_event(struct perf_script *script __maybe_unused, union perf_
666 697
667static struct scripting_ops *scripting_ops; 698static struct scripting_ops *scripting_ops;
668 699
700static void __process_stat(struct perf_evsel *counter, u64 tstamp)
701{
702 int nthreads = thread_map__nr(counter->threads);
703 int ncpus = perf_evsel__nr_cpus(counter);
704 int cpu, thread;
705 static int header_printed;
706
707 if (counter->system_wide)
708 nthreads = 1;
709
710 if (!header_printed) {
711 printf("%3s %8s %15s %15s %15s %15s %s\n",
712 "CPU", "THREAD", "VAL", "ENA", "RUN", "TIME", "EVENT");
713 header_printed = 1;
714 }
715
716 for (thread = 0; thread < nthreads; thread++) {
717 for (cpu = 0; cpu < ncpus; cpu++) {
718 struct perf_counts_values *counts;
719
720 counts = perf_counts(counter->counts, cpu, thread);
721
722 printf("%3d %8d %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %15" PRIu64 " %s\n",
723 counter->cpus->map[cpu],
724 thread_map__pid(counter->threads, thread),
725 counts->val,
726 counts->ena,
727 counts->run,
728 tstamp,
729 perf_evsel__name(counter));
730 }
731 }
732}
733
734static void process_stat(struct perf_evsel *counter, u64 tstamp)
735{
736 if (scripting_ops && scripting_ops->process_stat)
737 scripting_ops->process_stat(&stat_config, counter, tstamp);
738 else
739 __process_stat(counter, tstamp);
740}
741
742static void process_stat_interval(u64 tstamp)
743{
744 if (scripting_ops && scripting_ops->process_stat_interval)
745 scripting_ops->process_stat_interval(tstamp);
746}
747
669static void setup_scripting(void) 748static void setup_scripting(void)
670{ 749{
671 setup_perl_scripting(); 750 setup_perl_scripting();
@@ -1682,6 +1761,87 @@ static void script__setup_sample_type(struct perf_script *script)
1682 } 1761 }
1683} 1762}
1684 1763
1764static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
1765 union perf_event *event,
1766 struct perf_session *session)
1767{
1768 struct stat_round_event *round = &event->stat_round;
1769 struct perf_evsel *counter;
1770
1771 evlist__for_each(session->evlist, counter) {
1772 perf_stat_process_counter(&stat_config, counter);
1773 process_stat(counter, round->time);
1774 }
1775
1776 process_stat_interval(round->time);
1777 return 0;
1778}
1779
1780static int process_stat_config_event(struct perf_tool *tool __maybe_unused,
1781 union perf_event *event,
1782 struct perf_session *session __maybe_unused)
1783{
1784 perf_event__read_stat_config(&stat_config, &event->stat_config);
1785 return 0;
1786}
1787
1788static int set_maps(struct perf_script *script)
1789{
1790 struct perf_evlist *evlist = script->session->evlist;
1791
1792 if (!script->cpus || !script->threads)
1793 return 0;
1794
1795 if (WARN_ONCE(script->allocated, "stats double allocation\n"))
1796 return -EINVAL;
1797
1798 perf_evlist__set_maps(evlist, script->cpus, script->threads);
1799
1800 if (perf_evlist__alloc_stats(evlist, true))
1801 return -ENOMEM;
1802
1803 script->allocated = true;
1804 return 0;
1805}
1806
1807static
1808int process_thread_map_event(struct perf_tool *tool,
1809 union perf_event *event,
1810 struct perf_session *session __maybe_unused)
1811{
1812 struct perf_script *script = container_of(tool, struct perf_script, tool);
1813
1814 if (script->threads) {
1815 pr_warning("Extra thread map event, ignoring.\n");
1816 return 0;
1817 }
1818
1819 script->threads = thread_map__new_event(&event->thread_map);
1820 if (!script->threads)
1821 return -ENOMEM;
1822
1823 return set_maps(script);
1824}
1825
1826static
1827int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
1828 union perf_event *event,
1829 struct perf_session *session __maybe_unused)
1830{
1831 struct perf_script *script = container_of(tool, struct perf_script, tool);
1832
1833 if (script->cpus) {
1834 pr_warning("Extra cpu map event, ignoring.\n");
1835 return 0;
1836 }
1837
1838 script->cpus = cpu_map__new_data(&event->cpu_map.data);
1839 if (!script->cpus)
1840 return -ENOMEM;
1841
1842 return set_maps(script);
1843}
1844
1685int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) 1845int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1686{ 1846{
1687 bool show_full_info = false; 1847 bool show_full_info = false;
@@ -1710,6 +1870,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1710 .auxtrace_info = perf_event__process_auxtrace_info, 1870 .auxtrace_info = perf_event__process_auxtrace_info,
1711 .auxtrace = perf_event__process_auxtrace, 1871 .auxtrace = perf_event__process_auxtrace,
1712 .auxtrace_error = perf_event__process_auxtrace_error, 1872 .auxtrace_error = perf_event__process_auxtrace_error,
1873 .stat = perf_event__process_stat_event,
1874 .stat_round = process_stat_round_event,
1875 .stat_config = process_stat_config_event,
1876 .thread_map = process_thread_map_event,
1877 .cpu_map = process_cpu_map_event,
1713 .ordered_events = true, 1878 .ordered_events = true,
1714 .ordering_requires_timestamps = true, 1879 .ordering_requires_timestamps = true,
1715 }, 1880 },
@@ -2063,6 +2228,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2063 flush_scripting(); 2228 flush_scripting();
2064 2229
2065out_delete: 2230out_delete:
2231 perf_evlist__free_stats(session->evlist);
2066 perf_session__delete(session); 2232 perf_session__delete(session);
2067 2233
2068 if (script_started) 2234 if (script_started)
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 9805e03ab163..7f568244662b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -184,11 +184,18 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
184 * like tracepoints. Clear it up for counting. 184 * like tracepoints. Clear it up for counting.
185 */ 185 */
186 attr->sample_period = 0; 186 attr->sample_period = 0;
187
187 /* 188 /*
188 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless 189 * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless
189 * while avoiding that older tools show confusing messages. 190 * while avoiding that older tools show confusing messages.
191 *
192 * However for pipe sessions we need to keep it zero,
193 * because script's perf_evsel__check_attr is triggered
194 * by attr->sample_type != 0, and we can't run it on
195 * stat sessions.
190 */ 196 */
191 attr->sample_type = PERF_SAMPLE_IDENTIFIER; 197 if (!(STAT_RECORD && perf_stat.file.is_pipe))
198 attr->sample_type = PERF_SAMPLE_IDENTIFIER;
192 199
193 /* 200 /*
194 * Disabling all counters initially, they will be enabled 201 * Disabling all counters initially, they will be enabled
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 9ebd67a42ede..bf01cbb0ef23 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1210,6 +1210,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1210 OPT_CALLBACK('j', "branch-filter", &opts->branch_stack, 1210 OPT_CALLBACK('j', "branch-filter", &opts->branch_stack,
1211 "branch filter mask", "branch stack filter modes", 1211 "branch filter mask", "branch stack filter modes",
1212 parse_branch_stack), 1212 parse_branch_stack),
1213 OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
1214 "Show raw trace event output (do not use print fmt or plugins)"),
1213 OPT_END() 1215 OPT_END()
1214 }; 1216 };
1215 const char * const top_usage[] = { 1217 const char * const top_usage[] = {
@@ -1231,11 +1233,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1231 if (argc) 1233 if (argc)
1232 usage_with_options(top_usage, options); 1234 usage_with_options(top_usage, options);
1233 1235
1236 if (!top.evlist->nr_entries &&
1237 perf_evlist__add_default(top.evlist) < 0) {
1238 pr_err("Not enough memory for event selector list\n");
1239 goto out_delete_evlist;
1240 }
1241
1234 sort__mode = SORT_MODE__TOP; 1242 sort__mode = SORT_MODE__TOP;
1235 /* display thread wants entries to be collapsed in a different tree */ 1243 /* display thread wants entries to be collapsed in a different tree */
1236 sort__need_collapse = 1; 1244 sort__need_collapse = 1;
1237 1245
1238 if (setup_sorting() < 0) { 1246 if (setup_sorting(top.evlist) < 0) {
1239 if (sort_order) 1247 if (sort_order)
1240 parse_options_usage(top_usage, options, "s", 1); 1248 parse_options_usage(top_usage, options, "s", 1);
1241 if (field_order) 1249 if (field_order)
@@ -1277,12 +1285,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1277 goto out_delete_evlist; 1285 goto out_delete_evlist;
1278 } 1286 }
1279 1287
1280 if (!top.evlist->nr_entries &&
1281 perf_evlist__add_default(top.evlist) < 0) {
1282 ui__error("Not enough memory for event selector list\n");
1283 goto out_delete_evlist;
1284 }
1285
1286 symbol_conf.nr_events = top.evlist->nr_entries; 1288 symbol_conf.nr_events = top.evlist->nr_entries;
1287 1289
1288 if (top.delay_secs < 1) 1290 if (top.delay_secs < 1)
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index acc3ea7d90b7..ab5cbaa170d0 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -26,4 +26,4 @@ perf-stat mainporcelain common
26perf-test mainporcelain common 26perf-test mainporcelain common
27perf-timechart mainporcelain common 27perf-timechart mainporcelain common
28perf-top mainporcelain common 28perf-top mainporcelain common
29perf-trace mainporcelain common 29perf-trace mainporcelain audit
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index a5524179d26e..254d06e39bea 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -691,6 +691,7 @@ sharedir = $(prefix)/share
691template_dir = share/perf-core/templates 691template_dir = share/perf-core/templates
692STRACE_GROUPS_DIR = share/perf-core/strace/groups 692STRACE_GROUPS_DIR = share/perf-core/strace/groups
693htmldir = share/doc/perf-doc 693htmldir = share/doc/perf-doc
694tipdir = share/doc/perf-tip
694ifeq ($(prefix),/usr) 695ifeq ($(prefix),/usr)
695sysconfdir = /etc 696sysconfdir = /etc
696ETC_PERFCONFIG = $(sysconfdir)/perfconfig 697ETC_PERFCONFIG = $(sysconfdir)/perfconfig
@@ -717,6 +718,7 @@ infodir_SQ = $(subst ','\'',$(infodir))
717perfexecdir_SQ = $(subst ','\'',$(perfexecdir)) 718perfexecdir_SQ = $(subst ','\'',$(perfexecdir))
718template_dir_SQ = $(subst ','\'',$(template_dir)) 719template_dir_SQ = $(subst ','\'',$(template_dir))
719htmldir_SQ = $(subst ','\'',$(htmldir)) 720htmldir_SQ = $(subst ','\'',$(htmldir))
721tipdir_SQ = $(subst ','\'',$(tipdir))
720prefix_SQ = $(subst ','\'',$(prefix)) 722prefix_SQ = $(subst ','\'',$(prefix))
721sysconfdir_SQ = $(subst ','\'',$(sysconfdir)) 723sysconfdir_SQ = $(subst ','\'',$(sysconfdir))
722libdir_SQ = $(subst ','\'',$(libdir)) 724libdir_SQ = $(subst ','\'',$(libdir))
@@ -724,12 +726,15 @@ libdir_SQ = $(subst ','\'',$(libdir))
724ifneq ($(filter /%,$(firstword $(perfexecdir))),) 726ifneq ($(filter /%,$(firstword $(perfexecdir))),)
725perfexec_instdir = $(perfexecdir) 727perfexec_instdir = $(perfexecdir)
726STRACE_GROUPS_INSTDIR = $(STRACE_GROUPS_DIR) 728STRACE_GROUPS_INSTDIR = $(STRACE_GROUPS_DIR)
729tip_instdir = $(tipdir)
727else 730else
728perfexec_instdir = $(prefix)/$(perfexecdir) 731perfexec_instdir = $(prefix)/$(perfexecdir)
729STRACE_GROUPS_INSTDIR = $(prefix)/$(STRACE_GROUPS_DIR) 732STRACE_GROUPS_INSTDIR = $(prefix)/$(STRACE_GROUPS_DIR)
733tip_instdir = $(prefix)/$(tipdir)
730endif 734endif
731perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) 735perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
732STRACE_GROUPS_INSTDIR_SQ = $(subst ','\'',$(STRACE_GROUPS_INSTDIR)) 736STRACE_GROUPS_INSTDIR_SQ = $(subst ','\'',$(STRACE_GROUPS_INSTDIR))
737tip_instdir_SQ = $(subst ','\'',$(tip_instdir))
733 738
734# If we install to $(HOME) we keep the traceevent default: 739# If we install to $(HOME) we keep the traceevent default:
735# $(HOME)/.traceevent/plugins 740# $(HOME)/.traceevent/plugins
@@ -751,6 +756,10 @@ ifeq ($(VF),1)
751 $(call print_var,sysconfdir) 756 $(call print_var,sysconfdir)
752 $(call print_var,LIBUNWIND_DIR) 757 $(call print_var,LIBUNWIND_DIR)
753 $(call print_var,LIBDW_DIR) 758 $(call print_var,LIBDW_DIR)
759
760 ifeq ($(dwarf-post-unwind),1)
761 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
762 endif
754 $(info ) 763 $(info )
755endif 764endif
756 765
@@ -766,6 +775,7 @@ $(call detected_var,ETC_PERFCONFIG_SQ)
766$(call detected_var,STRACE_GROUPS_DIR_SQ) 775$(call detected_var,STRACE_GROUPS_DIR_SQ)
767$(call detected_var,prefix_SQ) 776$(call detected_var,prefix_SQ)
768$(call detected_var,perfexecdir_SQ) 777$(call detected_var,perfexecdir_SQ)
778$(call detected_var,tipdir_SQ)
769$(call detected_var,LIBDIR) 779$(call detected_var,LIBDIR)
770$(call detected_var,GTK_CFLAGS) 780$(call detected_var,GTK_CFLAGS)
771$(call detected_var,PERL_EMBED_CCOPTS) 781$(call detected_var,PERL_EMBED_CCOPTS)
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index cb1d2499c45c..a929618b8eb6 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -19,6 +19,8 @@
19#include "util/debug.h" 19#include "util/debug.h"
20#include <api/fs/tracing_path.h> 20#include <api/fs/tracing_path.h>
21#include <pthread.h> 21#include <pthread.h>
22#include <stdlib.h>
23#include <time.h>
22 24
23const char perf_usage_string[] = 25const char perf_usage_string[] =
24 "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]"; 26 "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]";
@@ -542,6 +544,8 @@ int main(int argc, const char **argv)
542 if (!cmd) 544 if (!cmd)
543 cmd = "perf-help"; 545 cmd = "perf-help";
544 546
547 srandom(time(NULL));
548
545 /* get debugfs/tracefs mount point from /proc/mounts */ 549 /* get debugfs/tracefs mount point from /proc/mounts */
546 tracing_path_mount(); 550 tracing_path_mount();
547 551
diff --git a/tools/perf/scripts/python/stat-cpi.py b/tools/perf/scripts/python/stat-cpi.py
new file mode 100644
index 000000000000..8b60f343dd07
--- /dev/null
+++ b/tools/perf/scripts/python/stat-cpi.py
@@ -0,0 +1,77 @@
1#!/usr/bin/env python
2
3data = {}
4times = []
5threads = []
6cpus = []
7
8def get_key(time, event, cpu, thread):
9 return "%d-%s-%d-%d" % (time, event, cpu, thread)
10
11def store_key(time, cpu, thread):
12 if (time not in times):
13 times.append(time)
14
15 if (cpu not in cpus):
16 cpus.append(cpu)
17
18 if (thread not in threads):
19 threads.append(thread)
20
21def store(time, event, cpu, thread, val, ena, run):
22 #print "event %s cpu %d, thread %d, time %d, val %d, ena %d, run %d" % \
23 # (event, cpu, thread, time, val, ena, run)
24
25 store_key(time, cpu, thread)
26 key = get_key(time, event, cpu, thread)
27 data[key] = [ val, ena, run]
28
29def get(time, event, cpu, thread):
30 key = get_key(time, event, cpu, thread)
31 return data[key][0]
32
33def stat__cycles_k(cpu, thread, time, val, ena, run):
34 store(time, "cycles", cpu, thread, val, ena, run);
35
36def stat__instructions_k(cpu, thread, time, val, ena, run):
37 store(time, "instructions", cpu, thread, val, ena, run);
38
39def stat__cycles_u(cpu, thread, time, val, ena, run):
40 store(time, "cycles", cpu, thread, val, ena, run);
41
42def stat__instructions_u(cpu, thread, time, val, ena, run):
43 store(time, "instructions", cpu, thread, val, ena, run);
44
45def stat__cycles(cpu, thread, time, val, ena, run):
46 store(time, "cycles", cpu, thread, val, ena, run);
47
48def stat__instructions(cpu, thread, time, val, ena, run):
49 store(time, "instructions", cpu, thread, val, ena, run);
50
51def stat__interval(time):
52 for cpu in cpus:
53 for thread in threads:
54 cyc = get(time, "cycles", cpu, thread)
55 ins = get(time, "instructions", cpu, thread)
56 cpi = 0
57
58 if ins != 0:
59 cpi = cyc/float(ins)
60
61 print "%15f: cpu %d, thread %d -> cpi %f (%d/%d)" % (time/(float(1000000000)), cpu, thread, cpi, cyc, ins)
62
63def trace_end():
64 pass
65# XXX trace_end callback could be used as an alternative place
66# to compute same values as in the script above:
67#
68# for time in times:
69# for cpu in cpus:
70# for thread in threads:
71# cyc = get(time, "cycles", cpu, thread)
72# ins = get(time, "instructions", cpu, thread)
73#
74# if ins != 0:
75# cpi = cyc/float(ins)
76#
77# print "time %.9f, cpu %d, thread %d -> cpi %f" % (time/(float(1000000000)), cpu, thread, cpi)
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 8292948bc5f9..e36089212061 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -281,7 +281,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
281 symbol_conf.cumulate_callchain = false; 281 symbol_conf.cumulate_callchain = false;
282 perf_evsel__reset_sample_bit(evsel, CALLCHAIN); 282 perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
283 283
284 setup_sorting(); 284 setup_sorting(NULL);
285 callchain_register_param(&callchain_param); 285 callchain_register_param(&callchain_param);
286 286
287 err = add_hist_entries(hists, machine); 287 err = add_hist_entries(hists, machine);
@@ -428,7 +428,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
428 symbol_conf.cumulate_callchain = false; 428 symbol_conf.cumulate_callchain = false;
429 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 429 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
430 430
431 setup_sorting(); 431 setup_sorting(NULL);
432 callchain_register_param(&callchain_param); 432 callchain_register_param(&callchain_param);
433 433
434 err = add_hist_entries(hists, machine); 434 err = add_hist_entries(hists, machine);
@@ -486,7 +486,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
486 symbol_conf.cumulate_callchain = true; 486 symbol_conf.cumulate_callchain = true;
487 perf_evsel__reset_sample_bit(evsel, CALLCHAIN); 487 perf_evsel__reset_sample_bit(evsel, CALLCHAIN);
488 488
489 setup_sorting(); 489 setup_sorting(NULL);
490 callchain_register_param(&callchain_param); 490 callchain_register_param(&callchain_param);
491 491
492 err = add_hist_entries(hists, machine); 492 err = add_hist_entries(hists, machine);
@@ -670,7 +670,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
670 symbol_conf.cumulate_callchain = true; 670 symbol_conf.cumulate_callchain = true;
671 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 671 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
672 672
673 setup_sorting(); 673 setup_sorting(NULL);
674 callchain_register_param(&callchain_param); 674 callchain_register_param(&callchain_param);
675 675
676 err = add_hist_entries(hists, machine); 676 err = add_hist_entries(hists, machine);
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index ccb5b4921f25..2a784befd9ce 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -122,7 +122,7 @@ int test__hists_filter(int subtest __maybe_unused)
122 goto out; 122 goto out;
123 123
124 /* default sort order (comm,dso,sym) will be used */ 124 /* default sort order (comm,dso,sym) will be used */
125 if (setup_sorting() < 0) 125 if (setup_sorting(NULL) < 0)
126 goto out; 126 goto out;
127 127
128 machines__init(&machines); 128 machines__init(&machines);
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 6243e2b2a245..c764d69ac6ef 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -64,7 +64,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
64 struct perf_evsel *evsel; 64 struct perf_evsel *evsel;
65 struct addr_location al; 65 struct addr_location al;
66 struct hist_entry *he; 66 struct hist_entry *he;
67 struct perf_sample sample = { .period = 1, }; 67 struct perf_sample sample = { .period = 1, .weight = 1, };
68 size_t i = 0, k; 68 size_t i = 0, k;
69 69
70 /* 70 /*
@@ -90,7 +90,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
90 goto out; 90 goto out;
91 91
92 he = __hists__add_entry(hists, &al, NULL, 92 he = __hists__add_entry(hists, &al, NULL,
93 NULL, NULL, 1, 1, 0, true); 93 NULL, NULL, &sample, true);
94 if (he == NULL) { 94 if (he == NULL) {
95 addr_location__put(&al); 95 addr_location__put(&al);
96 goto out; 96 goto out;
@@ -116,7 +116,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
116 goto out; 116 goto out;
117 117
118 he = __hists__add_entry(hists, &al, NULL, 118 he = __hists__add_entry(hists, &al, NULL,
119 NULL, NULL, 1, 1, 0, true); 119 NULL, NULL, &sample, true);
120 if (he == NULL) { 120 if (he == NULL) {
121 addr_location__put(&al); 121 addr_location__put(&al);
122 goto out; 122 goto out;
@@ -294,7 +294,7 @@ int test__hists_link(int subtest __maybe_unused)
294 goto out; 294 goto out;
295 295
296 /* default sort order (comm,dso,sym) will be used */ 296 /* default sort order (comm,dso,sym) will be used */
297 if (setup_sorting() < 0) 297 if (setup_sorting(NULL) < 0)
298 goto out; 298 goto out;
299 299
300 machines__init(&machines); 300 machines__init(&machines);
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index 248beec1d917..ebe6cd485b5d 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -134,7 +134,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
134 field_order = NULL; 134 field_order = NULL;
135 sort_order = NULL; /* equivalent to sort_order = "comm,dso,sym" */ 135 sort_order = NULL; /* equivalent to sort_order = "comm,dso,sym" */
136 136
137 setup_sorting(); 137 setup_sorting(NULL);
138 138
139 /* 139 /*
140 * expected output: 140 * expected output:
@@ -236,7 +236,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
236 field_order = "overhead,cpu"; 236 field_order = "overhead,cpu";
237 sort_order = "pid"; 237 sort_order = "pid";
238 238
239 setup_sorting(); 239 setup_sorting(NULL);
240 240
241 /* 241 /*
242 * expected output: 242 * expected output:
@@ -292,7 +292,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
292 field_order = "comm,overhead,dso"; 292 field_order = "comm,overhead,dso";
293 sort_order = NULL; 293 sort_order = NULL;
294 294
295 setup_sorting(); 295 setup_sorting(NULL);
296 296
297 /* 297 /*
298 * expected output: 298 * expected output:
@@ -366,7 +366,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
366 field_order = "dso,sym,comm,overhead,dso"; 366 field_order = "dso,sym,comm,overhead,dso";
367 sort_order = "sym"; 367 sort_order = "sym";
368 368
369 setup_sorting(); 369 setup_sorting(NULL);
370 370
371 /* 371 /*
372 * expected output: 372 * expected output:
@@ -468,7 +468,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)
468 field_order = "cpu,pid,comm,dso,sym"; 468 field_order = "cpu,pid,comm,dso,sym";
469 sort_order = "dso,pid"; 469 sort_order = "dso,pid";
470 470
471 setup_sorting(); 471 setup_sorting(NULL);
472 472
473 /* 473 /*
474 * expected output: 474 * expected output:
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index a337a6da1f39..ddb78fae064a 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -55,7 +55,6 @@ int test__keep_tracking(int subtest __maybe_unused)
55 .mmap_pages = UINT_MAX, 55 .mmap_pages = UINT_MAX,
56 .user_freq = UINT_MAX, 56 .user_freq = UINT_MAX,
57 .user_interval = ULLONG_MAX, 57 .user_interval = ULLONG_MAX,
58 .freq = 4000,
59 .target = { 58 .target = {
60 .uses_mmap = true, 59 .uses_mmap = true,
61 }, 60 },
@@ -124,7 +123,7 @@ int test__keep_tracking(int subtest __maybe_unused)
124 123
125 evsel = perf_evlist__last(evlist); 124 evsel = perf_evlist__last(evlist);
126 125
127 CHECK__(perf_evlist__disable_event(evlist, evsel)); 126 CHECK__(perf_evsel__disable(evsel));
128 127
129 comm = "Test COMM 2"; 128 comm = "Test COMM 2";
130 CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0)); 129 CHECK__(prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0));
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 9d5f0b57c4c1..1cc78cefe399 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -40,12 +40,11 @@ int test__PERF_RECORD(int subtest __maybe_unused)
40 .uses_mmap = true, 40 .uses_mmap = true,
41 }, 41 },
42 .no_buffering = true, 42 .no_buffering = true,
43 .freq = 10,
44 .mmap_pages = 256, 43 .mmap_pages = 256,
45 }; 44 };
46 cpu_set_t cpu_mask; 45 cpu_set_t cpu_mask;
47 size_t cpu_mask_size = sizeof(cpu_mask); 46 size_t cpu_mask_size = sizeof(cpu_mask);
48 struct perf_evlist *evlist = perf_evlist__new_default(); 47 struct perf_evlist *evlist = perf_evlist__new_dummy();
49 struct perf_evsel *evsel; 48 struct perf_evsel *evsel;
50 struct perf_sample sample; 49 struct perf_sample sample;
51 const char *cmd = "sleep"; 50 const char *cmd = "sleep";
@@ -61,6 +60,9 @@ int test__PERF_RECORD(int subtest __maybe_unused)
61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; 60 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
62 char sbuf[STRERR_BUFSIZE]; 61 char sbuf[STRERR_BUFSIZE];
63 62
63 if (evlist == NULL) /* Fallback for kernels lacking PERF_COUNT_SW_DUMMY */
64 evlist = perf_evlist__new_default();
65
64 if (evlist == NULL || argv == NULL) { 66 if (evlist == NULL || argv == NULL) {
65 pr_debug("Not enough memory to create evlist\n"); 67 pr_debug("Not enough memory to create evlist\n");
66 goto out; 68 goto out;
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index dfbd8d69ce89..ebd80168d51e 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -455,7 +455,7 @@ int test__switch_tracking(int subtest __maybe_unused)
455 455
456 perf_evlist__enable(evlist); 456 perf_evlist__enable(evlist);
457 457
458 err = perf_evlist__disable_event(evlist, cpu_clocks_evsel); 458 err = perf_evsel__disable(cpu_clocks_evsel);
459 if (err) { 459 if (err) {
460 pr_debug("perf_evlist__disable_event failed!\n"); 460 pr_debug("perf_evlist__disable_event failed!\n");
461 goto out_err; 461 goto out_err;
@@ -474,7 +474,7 @@ int test__switch_tracking(int subtest __maybe_unused)
474 goto out_err; 474 goto out_err;
475 } 475 }
476 476
477 err = perf_evlist__disable_event(evlist, cycles_evsel); 477 err = perf_evsel__disable(cycles_evsel);
478 if (err) { 478 if (err) {
479 pr_debug("perf_evlist__disable_event failed!\n"); 479 pr_debug("perf_evlist__disable_event failed!\n");
480 goto out_err; 480 goto out_err;
@@ -500,7 +500,7 @@ int test__switch_tracking(int subtest __maybe_unused)
500 goto out_err; 500 goto out_err;
501 } 501 }
502 502
503 err = perf_evlist__enable_event(evlist, cycles_evsel); 503 err = perf_evsel__enable(cycles_evsel);
504 if (err) { 504 if (err) {
505 pr_debug("perf_evlist__disable_event failed!\n"); 505 pr_debug("perf_evlist__disable_event failed!\n");
506 goto out_err; 506 goto out_err;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index ec331969b7d7..901d481e6cea 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1041,7 +1041,8 @@ static int hist_browser__show_entry(struct hist_browser *browser,
1041 hist_browser__gotorc(browser, row, 0); 1041 hist_browser__gotorc(browser, row, 0);
1042 1042
1043 perf_hpp__for_each_format(fmt) { 1043 perf_hpp__for_each_format(fmt) {
1044 if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll) 1044 if (perf_hpp__should_skip(fmt, entry->hists) ||
1045 column++ < browser->b.horiz_scroll)
1045 continue; 1046 continue;
1046 1047
1047 if (current_entry && browser->b.navkeypressed) { 1048 if (current_entry && browser->b.navkeypressed) {
@@ -1144,7 +1145,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
1144 } 1145 }
1145 1146
1146 perf_hpp__for_each_format(fmt) { 1147 perf_hpp__for_each_format(fmt) {
1147 if (perf_hpp__should_skip(fmt) || column++ < browser->b.horiz_scroll) 1148 if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll)
1148 continue; 1149 continue;
1149 1150
1150 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 1151 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
@@ -1414,7 +1415,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1414 printed += fprintf(fp, "%c ", folded_sign); 1415 printed += fprintf(fp, "%c ", folded_sign);
1415 1416
1416 perf_hpp__for_each_format(fmt) { 1417 perf_hpp__for_each_format(fmt) {
1417 if (perf_hpp__should_skip(fmt)) 1418 if (perf_hpp__should_skip(fmt, he->hists))
1418 continue; 1419 continue;
1419 1420
1420 if (!first) { 1421 if (!first) {
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 467717276ab6..0f8dcfdfb10f 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -318,7 +318,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
318 col_idx = 0; 318 col_idx = 0;
319 319
320 perf_hpp__for_each_format(fmt) { 320 perf_hpp__for_each_format(fmt) {
321 if (perf_hpp__should_skip(fmt)) 321 if (perf_hpp__should_skip(fmt, hists))
322 continue; 322 continue;
323 323
324 /* 324 /*
@@ -368,7 +368,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
368 col_idx = 0; 368 col_idx = 0;
369 369
370 perf_hpp__for_each_format(fmt) { 370 perf_hpp__for_each_format(fmt) {
371 if (perf_hpp__should_skip(fmt)) 371 if (perf_hpp__should_skip(fmt, h->hists))
372 continue; 372 continue;
373 373
374 if (fmt->color) 374 if (fmt->color)
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 5029ba2b55af..bf2a66e254ea 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -443,7 +443,6 @@ LIST_HEAD(perf_hpp__sort_list);
443 443
444void perf_hpp__init(void) 444void perf_hpp__init(void)
445{ 445{
446 struct list_head *list;
447 int i; 446 int i;
448 447
449 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) { 448 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
@@ -484,17 +483,6 @@ void perf_hpp__init(void)
484 483
485 if (symbol_conf.show_total_period) 484 if (symbol_conf.show_total_period)
486 hpp_dimension__add_output(PERF_HPP__PERIOD); 485 hpp_dimension__add_output(PERF_HPP__PERIOD);
487
488 /* prepend overhead field for backward compatiblity. */
489 list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list;
490 if (list_empty(list))
491 list_add(list, &perf_hpp__sort_list);
492
493 if (symbol_conf.cumulate_callchain) {
494 list = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC].sort_list;
495 if (list_empty(list))
496 list_add(list, &perf_hpp__sort_list);
497 }
498} 486}
499 487
500void perf_hpp__column_register(struct perf_hpp_fmt *format) 488void perf_hpp__column_register(struct perf_hpp_fmt *format)
@@ -619,7 +607,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
619 struct perf_hpp dummy_hpp; 607 struct perf_hpp dummy_hpp;
620 608
621 perf_hpp__for_each_format(fmt) { 609 perf_hpp__for_each_format(fmt) {
622 if (perf_hpp__should_skip(fmt)) 610 if (perf_hpp__should_skip(fmt, hists))
623 continue; 611 continue;
624 612
625 if (first) 613 if (first)
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 7ebc661be267..387110d50b00 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -385,7 +385,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
385 return 0; 385 return 0;
386 386
387 perf_hpp__for_each_format(fmt) { 387 perf_hpp__for_each_format(fmt) {
388 if (perf_hpp__should_skip(fmt)) 388 if (perf_hpp__should_skip(fmt, he->hists))
389 continue; 389 continue;
390 390
391 /* 391 /*
@@ -464,7 +464,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
464 fprintf(fp, "# "); 464 fprintf(fp, "# ");
465 465
466 perf_hpp__for_each_format(fmt) { 466 perf_hpp__for_each_format(fmt) {
467 if (perf_hpp__should_skip(fmt)) 467 if (perf_hpp__should_skip(fmt, hists))
468 continue; 468 continue;
469 469
470 if (!first) 470 if (!first)
@@ -490,7 +490,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
490 perf_hpp__for_each_format(fmt) { 490 perf_hpp__for_each_format(fmt) {
491 unsigned int i; 491 unsigned int i;
492 492
493 if (perf_hpp__should_skip(fmt)) 493 if (perf_hpp__should_skip(fmt, hists))
494 continue; 494 continue;
495 495
496 if (!first) 496 if (!first)
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 94b1099f2c22..5eec53a3f4ac 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -9,7 +9,7 @@ libperf-y += env.o
9libperf-y += event.o 9libperf-y += event.o
10libperf-y += evlist.o 10libperf-y += evlist.o
11libperf-y += evsel.o 11libperf-y += evsel.o
12libperf-y += find_next_bit.o 12libperf-y += find_bit.o
13libperf-y += kallsyms.o 13libperf-y += kallsyms.o
14libperf-y += levenshtein.o 14libperf-y += levenshtein.o
15libperf-y += llvm-utils.o 15libperf-y += llvm-utils.o
@@ -132,7 +132,8 @@ CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
132$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c 132$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
133$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c 133$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
134 134
135CFLAGS_find_next_bit.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 135CFLAGS_bitmap.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
136CFLAGS_find_bit.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
136CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 137CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
137CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 138CFLAGS_libstring.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
138CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 139CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
@@ -142,7 +143,11 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
142 $(call rule_mkdir) 143 $(call rule_mkdir)
143 $(call if_changed_dep,cc_o_c) 144 $(call if_changed_dep,cc_o_c)
144 145
145$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c FORCE 146$(OUTPUT)util/bitmap.o: ../lib/bitmap.c FORCE
147 $(call rule_mkdir)
148 $(call if_changed_dep,cc_o_c)
149
150$(OUTPUT)util/find_bit.o: ../lib/find_bit.c FORCE
146 $(call rule_mkdir) 151 $(call rule_mkdir)
147 $(call if_changed_dep,cc_o_c) 152 $(call if_changed_dep,cc_o_c)
148 153
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 564377d2bebf..53c43eb9489e 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -925,6 +925,34 @@ void free_callchain(struct callchain_root *root)
925 free_callchain_node(&root->node); 925 free_callchain_node(&root->node);
926} 926}
927 927
928static u64 decay_callchain_node(struct callchain_node *node)
929{
930 struct callchain_node *child;
931 struct rb_node *n;
932 u64 child_hits = 0;
933
934 n = rb_first(&node->rb_root_in);
935 while (n) {
936 child = container_of(n, struct callchain_node, rb_node_in);
937
938 child_hits += decay_callchain_node(child);
939 n = rb_next(n);
940 }
941
942 node->hit = (node->hit * 7) / 8;
943 node->children_hit = child_hits;
944
945 return node->hit;
946}
947
948void decay_callchain(struct callchain_root *root)
949{
950 if (!symbol_conf.use_callchain)
951 return;
952
953 decay_callchain_node(&root->node);
954}
955
928int callchain_node__make_parent_list(struct callchain_node *node) 956int callchain_node__make_parent_list(struct callchain_node *node)
929{ 957{
930 struct callchain_node *parent = node->parent; 958 struct callchain_node *parent = node->parent;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 8ac8f043004c..18dd22269764 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -253,6 +253,7 @@ int callchain_node__fprintf_value(struct callchain_node *node,
253 FILE *fp, u64 total); 253 FILE *fp, u64 total);
254 254
255void free_callchain(struct callchain_root *root); 255void free_callchain(struct callchain_root *root);
256void decay_callchain(struct callchain_root *root);
256int callchain_node__make_parent_list(struct callchain_node *node); 257int callchain_node__make_parent_list(struct callchain_node *node);
257 258
258#endif /* __PERF_CALLCHAIN_H */ 259#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index a0717b93d8f5..fa935093a599 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -188,8 +188,17 @@ static struct cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus)
188 if (map) { 188 if (map) {
189 unsigned i; 189 unsigned i;
190 190
191 for (i = 0; i < cpus->nr; i++) 191 for (i = 0; i < cpus->nr; i++) {
192 map->map[i] = (int)cpus->cpu[i]; 192 /*
193 * Special treatment for -1, which is not real cpu number,
194 * and we need to use (int) -1 to initialize map[i],
195 * otherwise it would become 65535.
196 */
197 if (cpus->cpu[i] == (u16) -1)
198 map->map[i] = -1;
199 else
200 map->map[i] = (int) cpus->cpu[i];
201 }
193 } 202 }
194 203
195 return map; 204 return map;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b9eac0daa0b9..d81f13de2476 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -68,6 +68,18 @@ struct perf_evlist *perf_evlist__new_default(void)
68 return evlist; 68 return evlist;
69} 69}
70 70
71struct perf_evlist *perf_evlist__new_dummy(void)
72{
73 struct perf_evlist *evlist = perf_evlist__new();
74
75 if (evlist && perf_evlist__add_dummy(evlist)) {
76 perf_evlist__delete(evlist);
77 evlist = NULL;
78 }
79
80 return evlist;
81}
82
71/** 83/**
72 * perf_evlist__set_id_pos - set the positions of event ids. 84 * perf_evlist__set_id_pos - set the positions of event ids.
73 * @evlist: selected event list 85 * @evlist: selected event list
@@ -248,6 +260,22 @@ error:
248 return -ENOMEM; 260 return -ENOMEM;
249} 261}
250 262
263int perf_evlist__add_dummy(struct perf_evlist *evlist)
264{
265 struct perf_event_attr attr = {
266 .type = PERF_TYPE_SOFTWARE,
267 .config = PERF_COUNT_SW_DUMMY,
268 .size = sizeof(attr), /* to capture ABI version */
269 };
270 struct perf_evsel *evsel = perf_evsel__new(&attr);
271
272 if (evsel == NULL)
273 return -ENOMEM;
274
275 perf_evlist__add(evlist, evsel);
276 return 0;
277}
278
251static int perf_evlist__add_attrs(struct perf_evlist *evlist, 279static int perf_evlist__add_attrs(struct perf_evlist *evlist,
252 struct perf_event_attr *attrs, size_t nr_attrs) 280 struct perf_event_attr *attrs, size_t nr_attrs)
253{ 281{
@@ -365,48 +393,6 @@ void perf_evlist__toggle_enable(struct perf_evlist *evlist)
365 (evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist); 393 (evlist->enabled ? perf_evlist__disable : perf_evlist__enable)(evlist);
366} 394}
367 395
368int perf_evlist__disable_event(struct perf_evlist *evlist,
369 struct perf_evsel *evsel)
370{
371 int cpu, thread, err;
372 int nr_cpus = cpu_map__nr(evlist->cpus);
373 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
374
375 if (!evsel->fd)
376 return 0;
377
378 for (cpu = 0; cpu < nr_cpus; cpu++) {
379 for (thread = 0; thread < nr_threads; thread++) {
380 err = ioctl(FD(evsel, cpu, thread),
381 PERF_EVENT_IOC_DISABLE, 0);
382 if (err)
383 return err;
384 }
385 }
386 return 0;
387}
388
389int perf_evlist__enable_event(struct perf_evlist *evlist,
390 struct perf_evsel *evsel)
391{
392 int cpu, thread, err;
393 int nr_cpus = cpu_map__nr(evlist->cpus);
394 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
395
396 if (!evsel->fd)
397 return -EINVAL;
398
399 for (cpu = 0; cpu < nr_cpus; cpu++) {
400 for (thread = 0; thread < nr_threads; thread++) {
401 err = ioctl(FD(evsel, cpu, thread),
402 PERF_EVENT_IOC_ENABLE, 0);
403 if (err)
404 return err;
405 }
406 }
407 return 0;
408}
409
410static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist, 396static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
411 struct perf_evsel *evsel, int cpu) 397 struct perf_evsel *evsel, int cpu)
412{ 398{
@@ -1470,7 +1456,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
1470 perf_evlist__update_id_pos(evlist); 1456 perf_evlist__update_id_pos(evlist);
1471 1457
1472 evlist__for_each(evlist, evsel) { 1458 evlist__for_each(evlist, evsel) {
1473 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); 1459 err = perf_evsel__open(evsel, evsel->cpus, evsel->threads);
1474 if (err < 0) 1460 if (err < 0)
1475 goto out_err; 1461 goto out_err;
1476 } 1462 }
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 139a50038097..7c4d9a206776 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -67,6 +67,7 @@ struct perf_evsel_str_handler {
67 67
68struct perf_evlist *perf_evlist__new(void); 68struct perf_evlist *perf_evlist__new(void);
69struct perf_evlist *perf_evlist__new_default(void); 69struct perf_evlist *perf_evlist__new_default(void);
70struct perf_evlist *perf_evlist__new_dummy(void);
70void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 71void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
71 struct thread_map *threads); 72 struct thread_map *threads);
72void perf_evlist__exit(struct perf_evlist *evlist); 73void perf_evlist__exit(struct perf_evlist *evlist);
@@ -81,6 +82,8 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
81#define perf_evlist__add_default_attrs(evlist, array) \ 82#define perf_evlist__add_default_attrs(evlist, array) \
82 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) 83 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
83 84
85int perf_evlist__add_dummy(struct perf_evlist *evlist);
86
84int perf_evlist__add_newtp(struct perf_evlist *evlist, 87int perf_evlist__add_newtp(struct perf_evlist *evlist,
85 const char *sys, const char *name, void *handler); 88 const char *sys, const char *name, void *handler);
86 89
@@ -152,10 +155,6 @@ void perf_evlist__disable(struct perf_evlist *evlist);
152void perf_evlist__enable(struct perf_evlist *evlist); 155void perf_evlist__enable(struct perf_evlist *evlist);
153void perf_evlist__toggle_enable(struct perf_evlist *evlist); 156void perf_evlist__toggle_enable(struct perf_evlist *evlist);
154 157
155int perf_evlist__disable_event(struct perf_evlist *evlist,
156 struct perf_evsel *evsel);
157int perf_evlist__enable_event(struct perf_evlist *evlist,
158 struct perf_evsel *evsel);
159int perf_evlist__enable_event_idx(struct perf_evlist *evlist, 158int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
160 struct perf_evsel *evsel, int idx); 159 struct perf_evsel *evsel, int idx);
161 160
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 544e4400de13..cdbaf9b51e42 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2298,6 +2298,29 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
2298 printed += comma_fprintf(fp, &first, " %s=%" PRIu64, 2298 printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
2299 term, (u64)evsel->attr.sample_freq); 2299 term, (u64)evsel->attr.sample_freq);
2300 } 2300 }
2301
2302 if (details->trace_fields) {
2303 struct format_field *field;
2304
2305 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2306 printed += comma_fprintf(fp, &first, " (not a tracepoint)");
2307 goto out;
2308 }
2309
2310 field = evsel->tp_format->format.fields;
2311 if (field == NULL) {
2312 printed += comma_fprintf(fp, &first, " (no trace field)");
2313 goto out;
2314 }
2315
2316 printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
2317
2318 field = field->next;
2319 while (field) {
2320 printed += comma_fprintf(fp, &first, "%s", field->name);
2321 field = field->next;
2322 }
2323 }
2301out: 2324out:
2302 fputc('\n', fp); 2325 fputc('\n', fp);
2303 return ++printed; 2326 return ++printed;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 5ded1fc0341e..8e75434bd01c 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -369,6 +369,7 @@ struct perf_attr_details {
369 bool verbose; 369 bool verbose;
370 bool event_group; 370 bool event_group;
371 bool force; 371 bool force;
372 bool trace_fields;
372}; 373};
373 374
374int perf_evsel__fprintf(struct perf_evsel *evsel, 375int perf_evsel__fprintf(struct perf_evsel *evsel,
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 36a885d2cd22..0ac2037c970c 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -36,4 +36,19 @@ do
36 }' "Documentation/perf-$cmd.txt" 36 }' "Documentation/perf-$cmd.txt"
37done 37done
38echo "#endif /* HAVE_LIBELF_SUPPORT */" 38echo "#endif /* HAVE_LIBELF_SUPPORT */"
39
40echo "#ifdef HAVE_LIBAUDIT_SUPPORT"
41sed -n -e 's/^perf-\([^ ]*\)[ ].* audit*/\1/p' command-list.txt |
42sort |
43while read cmd
44do
45 sed -n '
46 /^NAME/,/perf-'"$cmd"'/H
47 ${
48 x
49 s/.*perf-'"$cmd"' - \(.*\)/ {"'"$cmd"'", "\1"},/
50 p
51 }' "Documentation/perf-$cmd.txt"
52done
53echo "#endif /* HAVE_LIBELF_SUPPORT */"
39echo "};" 54echo "};"
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 56e97f5af598..c226303e3da0 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -254,6 +254,7 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
254 he_stat__decay(&he->stat); 254 he_stat__decay(&he->stat);
255 if (symbol_conf.cumulate_callchain) 255 if (symbol_conf.cumulate_callchain)
256 he_stat__decay(he->stat_acc); 256 he_stat__decay(he->stat_acc);
257 decay_callchain(he->callchain);
257 258
258 diff = prev_period - he->stat.period; 259 diff = prev_period - he->stat.period;
259 260
@@ -369,6 +370,25 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
369 if (symbol_conf.use_callchain) 370 if (symbol_conf.use_callchain)
370 callchain_init(he->callchain); 371 callchain_init(he->callchain);
371 372
373 if (he->raw_data) {
374 he->raw_data = memdup(he->raw_data, he->raw_size);
375
376 if (he->raw_data == NULL) {
377 map__put(he->ms.map);
378 if (he->branch_info) {
379 map__put(he->branch_info->from.map);
380 map__put(he->branch_info->to.map);
381 free(he->branch_info);
382 }
383 if (he->mem_info) {
384 map__put(he->mem_info->iaddr.map);
385 map__put(he->mem_info->daddr.map);
386 }
387 free(he->stat_acc);
388 free(he);
389 return NULL;
390 }
391 }
372 INIT_LIST_HEAD(&he->pairs.node); 392 INIT_LIST_HEAD(&he->pairs.node);
373 thread__get(he->thread); 393 thread__get(he->thread);
374 } 394 }
@@ -461,7 +481,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
461 struct symbol *sym_parent, 481 struct symbol *sym_parent,
462 struct branch_info *bi, 482 struct branch_info *bi,
463 struct mem_info *mi, 483 struct mem_info *mi,
464 u64 period, u64 weight, u64 transaction, 484 struct perf_sample *sample,
465 bool sample_self) 485 bool sample_self)
466{ 486{
467 struct hist_entry entry = { 487 struct hist_entry entry = {
@@ -478,15 +498,17 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
478 .level = al->level, 498 .level = al->level,
479 .stat = { 499 .stat = {
480 .nr_events = 1, 500 .nr_events = 1,
481 .period = period, 501 .period = sample->period,
482 .weight = weight, 502 .weight = sample->weight,
483 }, 503 },
484 .parent = sym_parent, 504 .parent = sym_parent,
485 .filtered = symbol__parent_filter(sym_parent) | al->filtered, 505 .filtered = symbol__parent_filter(sym_parent) | al->filtered,
486 .hists = hists, 506 .hists = hists,
487 .branch_info = bi, 507 .branch_info = bi,
488 .mem_info = mi, 508 .mem_info = mi,
489 .transaction = transaction, 509 .transaction = sample->transaction,
510 .raw_data = sample->raw_data,
511 .raw_size = sample->raw_size,
490 }; 512 };
491 513
492 return hists__findnew_entry(hists, &entry, al, sample_self); 514 return hists__findnew_entry(hists, &entry, al, sample_self);
@@ -526,12 +548,13 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
526 u64 cost; 548 u64 cost;
527 struct mem_info *mi = iter->priv; 549 struct mem_info *mi = iter->priv;
528 struct hists *hists = evsel__hists(iter->evsel); 550 struct hists *hists = evsel__hists(iter->evsel);
551 struct perf_sample *sample = iter->sample;
529 struct hist_entry *he; 552 struct hist_entry *he;
530 553
531 if (mi == NULL) 554 if (mi == NULL)
532 return -EINVAL; 555 return -EINVAL;
533 556
534 cost = iter->sample->weight; 557 cost = sample->weight;
535 if (!cost) 558 if (!cost)
536 cost = 1; 559 cost = 1;
537 560
@@ -542,8 +565,10 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
542 * and this is indirectly achieved by passing period=weight here 565 * and this is indirectly achieved by passing period=weight here
543 * and the he_stat__add_period() function. 566 * and the he_stat__add_period() function.
544 */ 567 */
568 sample->period = cost;
569
545 he = __hists__add_entry(hists, al, iter->parent, NULL, mi, 570 he = __hists__add_entry(hists, al, iter->parent, NULL, mi,
546 cost, cost, 0, true); 571 sample, true);
547 if (!he) 572 if (!he)
548 return -ENOMEM; 573 return -ENOMEM;
549 574
@@ -630,6 +655,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
630 struct branch_info *bi; 655 struct branch_info *bi;
631 struct perf_evsel *evsel = iter->evsel; 656 struct perf_evsel *evsel = iter->evsel;
632 struct hists *hists = evsel__hists(evsel); 657 struct hists *hists = evsel__hists(evsel);
658 struct perf_sample *sample = iter->sample;
633 struct hist_entry *he = NULL; 659 struct hist_entry *he = NULL;
634 int i = iter->curr; 660 int i = iter->curr;
635 int err = 0; 661 int err = 0;
@@ -643,9 +669,11 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
643 * The report shows the percentage of total branches captured 669 * The report shows the percentage of total branches captured
644 * and not events sampled. Thus we use a pseudo period of 1. 670 * and not events sampled. Thus we use a pseudo period of 1.
645 */ 671 */
672 sample->period = 1;
673 sample->weight = bi->flags.cycles ? bi->flags.cycles : 1;
674
646 he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL, 675 he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
647 1, bi->flags.cycles ? bi->flags.cycles : 1, 676 sample, true);
648 0, true);
649 if (he == NULL) 677 if (he == NULL)
650 return -ENOMEM; 678 return -ENOMEM;
651 679
@@ -682,8 +710,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
682 struct hist_entry *he; 710 struct hist_entry *he;
683 711
684 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 712 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
685 sample->period, sample->weight, 713 sample, true);
686 sample->transaction, true);
687 if (he == NULL) 714 if (he == NULL)
688 return -ENOMEM; 715 return -ENOMEM;
689 716
@@ -744,8 +771,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
744 int err = 0; 771 int err = 0;
745 772
746 he = __hists__add_entry(hists, al, iter->parent, NULL, NULL, 773 he = __hists__add_entry(hists, al, iter->parent, NULL, NULL,
747 sample->period, sample->weight, 774 sample, true);
748 sample->transaction, true);
749 if (he == NULL) 775 if (he == NULL)
750 return -ENOMEM; 776 return -ENOMEM;
751 777
@@ -797,6 +823,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
797 .sym = al->sym, 823 .sym = al->sym,
798 }, 824 },
799 .parent = iter->parent, 825 .parent = iter->parent,
826 .raw_data = sample->raw_data,
827 .raw_size = sample->raw_size,
800 }; 828 };
801 int i; 829 int i;
802 struct callchain_cursor cursor; 830 struct callchain_cursor cursor;
@@ -818,8 +846,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
818 } 846 }
819 847
820 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 848 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
821 sample->period, sample->weight, 849 sample, false);
822 sample->transaction, false);
823 if (he == NULL) 850 if (he == NULL)
824 return -ENOMEM; 851 return -ENOMEM;
825 852
@@ -971,6 +998,8 @@ void hist_entry__delete(struct hist_entry *he)
971 if (he->srcfile && he->srcfile[0]) 998 if (he->srcfile && he->srcfile[0])
972 free(he->srcfile); 999 free(he->srcfile);
973 free_callchain(he->callchain); 1000 free_callchain(he->callchain);
1001 free(he->trace_output);
1002 free(he->raw_data);
974 free(he); 1003 free(he);
975} 1004}
976 1005
@@ -978,9 +1007,8 @@ void hist_entry__delete(struct hist_entry *he)
978 * collapse the histogram 1007 * collapse the histogram
979 */ 1008 */
980 1009
981static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, 1010bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
982 struct rb_root *root, 1011 struct rb_root *root, struct hist_entry *he)
983 struct hist_entry *he)
984{ 1012{
985 struct rb_node **p = &root->rb_node; 1013 struct rb_node **p = &root->rb_node;
986 struct rb_node *parent = NULL; 1014 struct rb_node *parent = NULL;
@@ -1020,7 +1048,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
1020 return true; 1048 return true;
1021} 1049}
1022 1050
1023static struct rb_root *hists__get_rotate_entries_in(struct hists *hists) 1051struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
1024{ 1052{
1025 struct rb_root *root; 1053 struct rb_root *root;
1026 1054
@@ -1084,7 +1112,7 @@ static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
1084 int64_t cmp = 0; 1112 int64_t cmp = 0;
1085 1113
1086 perf_hpp__for_each_sort_list(fmt) { 1114 perf_hpp__for_each_sort_list(fmt) {
1087 if (perf_hpp__should_skip(fmt)) 1115 if (perf_hpp__should_skip(fmt, a->hists))
1088 continue; 1116 continue;
1089 1117
1090 cmp = fmt->sort(fmt, a, b); 1118 cmp = fmt->sort(fmt, a, b);
@@ -1555,10 +1583,8 @@ int perf_hist_config(const char *var, const char *value)
1555 return 0; 1583 return 0;
1556} 1584}
1557 1585
1558static int hists_evsel__init(struct perf_evsel *evsel) 1586int __hists__init(struct hists *hists)
1559{ 1587{
1560 struct hists *hists = evsel__hists(evsel);
1561
1562 memset(hists, 0, sizeof(*hists)); 1588 memset(hists, 0, sizeof(*hists));
1563 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; 1589 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
1564 hists->entries_in = &hists->entries_in_array[0]; 1590 hists->entries_in = &hists->entries_in_array[0];
@@ -1598,6 +1624,14 @@ static void hists_evsel__exit(struct perf_evsel *evsel)
1598 hists__delete_all_entries(hists); 1624 hists__delete_all_entries(hists);
1599} 1625}
1600 1626
1627static int hists_evsel__init(struct perf_evsel *evsel)
1628{
1629 struct hists *hists = evsel__hists(evsel);
1630
1631 __hists__init(hists);
1632 return 0;
1633}
1634
1601/* 1635/*
1602 * XXX We probably need a hists_evsel__exit() to free the hist_entries 1636 * XXX We probably need a hists_evsel__exit() to free the hist_entries
1603 * stored in the rbtree... 1637 * stored in the rbtree...
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index a48a2078d288..d4ec4822a103 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,6 +52,7 @@ enum hist_column {
52 HISTC_MEM_IADDR_SYMBOL, 52 HISTC_MEM_IADDR_SYMBOL,
53 HISTC_TRANSACTION, 53 HISTC_TRANSACTION,
54 HISTC_CYCLES, 54 HISTC_CYCLES,
55 HISTC_TRACE,
55 HISTC_NR_COLS, /* Last entry */ 56 HISTC_NR_COLS, /* Last entry */
56}; 57};
57 58
@@ -114,8 +115,8 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
114 struct addr_location *al, 115 struct addr_location *al,
115 struct symbol *parent, 116 struct symbol *parent,
116 struct branch_info *bi, 117 struct branch_info *bi,
117 struct mem_info *mi, u64 period, 118 struct mem_info *mi,
118 u64 weight, u64 transaction, 119 struct perf_sample *sample,
119 bool sample_self); 120 bool sample_self);
120int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, 121int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
121 int max_stack_depth, void *arg); 122 int max_stack_depth, void *arg);
@@ -184,6 +185,11 @@ static inline struct hists *evsel__hists(struct perf_evsel *evsel)
184} 185}
185 186
186int hists__init(void); 187int hists__init(void);
188int __hists__init(struct hists *hists);
189
190struct rb_root *hists__get_rotate_entries_in(struct hists *hists);
191bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
192 struct rb_root *root, struct hist_entry *he);
187 193
188struct perf_hpp { 194struct perf_hpp {
189 char *buf; 195 char *buf;
@@ -261,10 +267,20 @@ void perf_hpp__append_sort_keys(void);
261 267
262bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); 268bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format);
263bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); 269bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b);
270bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format);
271bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists);
264 272
265static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format) 273static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format,
274 struct hists *hists)
266{ 275{
267 return format->elide; 276 if (format->elide)
277 return true;
278
279 if (perf_hpp__is_dynamic_entry(format) &&
280 !perf_hpp__defined_dynamic_entry(format, hists))
281 return true;
282
283 return false;
268} 284}
269 285
270void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 286void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index e4b173dec4b9..b597bcc8fc78 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -220,6 +220,7 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
220 alias->scale = 1.0; 220 alias->scale = 1.0;
221 alias->unit[0] = '\0'; 221 alias->unit[0] = '\0';
222 alias->per_pkg = false; 222 alias->per_pkg = false;
223 alias->snapshot = false;
223 224
224 ret = parse_events_terms(&alias->terms, val); 225 ret = parse_events_terms(&alias->terms, val);
225 if (ret) { 226 if (ret) {
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 51be28b1bca2..8162ba0e2e57 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -10,6 +10,8 @@ util/ctype.c
10util/evlist.c 10util/evlist.c
11util/evsel.c 11util/evsel.c
12util/cpumap.c 12util/cpumap.c
13../lib/bitmap.c
14../lib/find_bit.c
13../lib/hweight.c 15../lib/hweight.c
14util/thread_map.c 16util/thread_map.c
15util/util.c 17util/util.c
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index a8e825fca42a..d72fafc1c800 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -41,6 +41,9 @@
41#include "../thread-stack.h" 41#include "../thread-stack.h"
42#include "../trace-event.h" 42#include "../trace-event.h"
43#include "../machine.h" 43#include "../machine.h"
44#include "thread_map.h"
45#include "cpumap.h"
46#include "stat.h"
44 47
45PyMODINIT_FUNC initperf_trace_context(void); 48PyMODINIT_FUNC initperf_trace_context(void);
46 49
@@ -859,6 +862,104 @@ static void python_process_event(union perf_event *event,
859 } 862 }
860} 863}
861 864
865static void get_handler_name(char *str, size_t size,
866 struct perf_evsel *evsel)
867{
868 char *p = str;
869
870 scnprintf(str, size, "stat__%s", perf_evsel__name(evsel));
871
872 while ((p = strchr(p, ':'))) {
873 *p = '_';
874 p++;
875 }
876}
877
878static void
879process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp,
880 struct perf_counts_values *count)
881{
882 PyObject *handler, *t;
883 static char handler_name[256];
884 int n = 0;
885
886 t = PyTuple_New(MAX_FIELDS);
887 if (!t)
888 Py_FatalError("couldn't create Python tuple");
889
890 get_handler_name(handler_name, sizeof(handler_name),
891 counter);
892
893 handler = get_handler(handler_name);
894 if (!handler) {
895 pr_debug("can't find python handler %s\n", handler_name);
896 return;
897 }
898
899 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
900 PyTuple_SetItem(t, n++, PyInt_FromLong(thread));
901
902 tuple_set_u64(t, n++, tstamp);
903 tuple_set_u64(t, n++, count->val);
904 tuple_set_u64(t, n++, count->ena);
905 tuple_set_u64(t, n++, count->run);
906
907 if (_PyTuple_Resize(&t, n) == -1)
908 Py_FatalError("error resizing Python tuple");
909
910 call_object(handler, t, handler_name);
911
912 Py_DECREF(t);
913}
914
915static void python_process_stat(struct perf_stat_config *config,
916 struct perf_evsel *counter, u64 tstamp)
917{
918 struct thread_map *threads = counter->threads;
919 struct cpu_map *cpus = counter->cpus;
920 int cpu, thread;
921
922 if (config->aggr_mode == AGGR_GLOBAL) {
923 process_stat(counter, -1, -1, tstamp,
924 &counter->counts->aggr);
925 return;
926 }
927
928 for (thread = 0; thread < threads->nr; thread++) {
929 for (cpu = 0; cpu < cpus->nr; cpu++) {
930 process_stat(counter, cpus->map[cpu],
931 thread_map__pid(threads, thread), tstamp,
932 perf_counts(counter->counts, cpu, thread));
933 }
934 }
935}
936
937static void python_process_stat_interval(u64 tstamp)
938{
939 PyObject *handler, *t;
940 static const char handler_name[] = "stat__interval";
941 int n = 0;
942
943 t = PyTuple_New(MAX_FIELDS);
944 if (!t)
945 Py_FatalError("couldn't create Python tuple");
946
947 handler = get_handler(handler_name);
948 if (!handler) {
949 pr_debug("can't find python handler %s\n", handler_name);
950 return;
951 }
952
953 tuple_set_u64(t, n++, tstamp);
954
955 if (_PyTuple_Resize(&t, n) == -1)
956 Py_FatalError("error resizing Python tuple");
957
958 call_object(handler, t, handler_name);
959
960 Py_DECREF(t);
961}
962
862static int run_start_sub(void) 963static int run_start_sub(void)
863{ 964{
864 main_module = PyImport_AddModule("__main__"); 965 main_module = PyImport_AddModule("__main__");
@@ -1201,10 +1302,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1201} 1302}
1202 1303
1203struct scripting_ops python_scripting_ops = { 1304struct scripting_ops python_scripting_ops = {
1204 .name = "Python", 1305 .name = "Python",
1205 .start_script = python_start_script, 1306 .start_script = python_start_script,
1206 .flush_script = python_flush_script, 1307 .flush_script = python_flush_script,
1207 .stop_script = python_stop_script, 1308 .stop_script = python_stop_script,
1208 .process_event = python_process_event, 1309 .process_event = python_process_event,
1209 .generate_script = python_generate_script, 1310 .process_stat = python_process_stat,
1311 .process_stat_interval = python_process_stat_interval,
1312 .generate_script = python_generate_script,
1210}; 1313};
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 2d8ccd4d9e1b..ec722346e6ff 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -4,6 +4,8 @@
4#include "comm.h" 4#include "comm.h"
5#include "symbol.h" 5#include "symbol.h"
6#include "evsel.h" 6#include "evsel.h"
7#include "evlist.h"
8#include <traceevent/event-parse.h>
7 9
8regex_t parent_regex; 10regex_t parent_regex;
9const char default_parent_pattern[] = "^sys_|^do_page_fault"; 11const char default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -13,6 +15,7 @@ const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cy
13const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked"; 15const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
14const char default_top_sort_order[] = "dso,symbol"; 16const char default_top_sort_order[] = "dso,symbol";
15const char default_diff_sort_order[] = "dso,symbol"; 17const char default_diff_sort_order[] = "dso,symbol";
18const char default_tracepoint_sort_order[] = "trace";
16const char *sort_order; 19const char *sort_order;
17const char *field_order; 20const char *field_order;
18regex_t ignore_callees_regex; 21regex_t ignore_callees_regex;
@@ -443,6 +446,70 @@ struct sort_entry sort_socket = {
443 .se_width_idx = HISTC_SOCKET, 446 .se_width_idx = HISTC_SOCKET,
444}; 447};
445 448
449/* --sort trace */
450
451static char *get_trace_output(struct hist_entry *he)
452{
453 struct trace_seq seq;
454 struct perf_evsel *evsel;
455 struct pevent_record rec = {
456 .data = he->raw_data,
457 .size = he->raw_size,
458 };
459
460 evsel = hists_to_evsel(he->hists);
461
462 trace_seq_init(&seq);
463 if (symbol_conf.raw_trace) {
464 pevent_print_fields(&seq, he->raw_data, he->raw_size,
465 evsel->tp_format);
466 } else {
467 pevent_event_info(&seq, evsel->tp_format, &rec);
468 }
469 return seq.buffer;
470}
471
472static int64_t
473sort__trace_cmp(struct hist_entry *left, struct hist_entry *right)
474{
475 struct perf_evsel *evsel;
476
477 evsel = hists_to_evsel(left->hists);
478 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
479 return 0;
480
481 if (left->trace_output == NULL)
482 left->trace_output = get_trace_output(left);
483 if (right->trace_output == NULL)
484 right->trace_output = get_trace_output(right);
485
486 hists__new_col_len(left->hists, HISTC_TRACE, strlen(left->trace_output));
487 hists__new_col_len(right->hists, HISTC_TRACE, strlen(right->trace_output));
488
489 return strcmp(right->trace_output, left->trace_output);
490}
491
492static int hist_entry__trace_snprintf(struct hist_entry *he, char *bf,
493 size_t size, unsigned int width)
494{
495 struct perf_evsel *evsel;
496
497 evsel = hists_to_evsel(he->hists);
498 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
499 return scnprintf(bf, size, "%-*.*s", width, width, "N/A");
500
501 if (he->trace_output == NULL)
502 he->trace_output = get_trace_output(he);
503 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->trace_output);
504}
505
506struct sort_entry sort_trace = {
507 .se_header = "Trace output",
508 .se_cmp = sort__trace_cmp,
509 .se_snprintf = hist_entry__trace_snprintf,
510 .se_width_idx = HISTC_TRACE,
511};
512
446/* sort keys for branch stacks */ 513/* sort keys for branch stacks */
447 514
448static int64_t 515static int64_t
@@ -1312,6 +1379,7 @@ static struct sort_dimension common_sort_dimensions[] = {
1312 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), 1379 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
1313 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), 1380 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
1314 DIM(SORT_TRANSACTION, "transaction", sort_transaction), 1381 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
1382 DIM(SORT_TRACE, "trace", sort_trace),
1315}; 1383};
1316 1384
1317#undef DIM 1385#undef DIM
@@ -1529,6 +1597,455 @@ static int __sort_dimension__add_hpp_output(struct sort_dimension *sd)
1529 return 0; 1597 return 0;
1530} 1598}
1531 1599
1600struct hpp_dynamic_entry {
1601 struct perf_hpp_fmt hpp;
1602 struct perf_evsel *evsel;
1603 struct format_field *field;
1604 unsigned dynamic_len;
1605 bool raw_trace;
1606};
1607
1608static int hde_width(struct hpp_dynamic_entry *hde)
1609{
1610 if (!hde->hpp.len) {
1611 int len = hde->dynamic_len;
1612 int namelen = strlen(hde->field->name);
1613 int fieldlen = hde->field->size;
1614
1615 if (namelen > len)
1616 len = namelen;
1617
1618 if (!(hde->field->flags & FIELD_IS_STRING)) {
1619 /* length for print hex numbers */
1620 fieldlen = hde->field->size * 2 + 2;
1621 }
1622 if (fieldlen > len)
1623 len = fieldlen;
1624
1625 hde->hpp.len = len;
1626 }
1627 return hde->hpp.len;
1628}
1629
1630static void update_dynamic_len(struct hpp_dynamic_entry *hde,
1631 struct hist_entry *he)
1632{
1633 char *str, *pos;
1634 struct format_field *field = hde->field;
1635 size_t namelen;
1636 bool last = false;
1637
1638 if (hde->raw_trace)
1639 return;
1640
1641 /* parse pretty print result and update max length */
1642 if (!he->trace_output)
1643 he->trace_output = get_trace_output(he);
1644
1645 namelen = strlen(field->name);
1646 str = he->trace_output;
1647
1648 while (str) {
1649 pos = strchr(str, ' ');
1650 if (pos == NULL) {
1651 last = true;
1652 pos = str + strlen(str);
1653 }
1654
1655 if (!strncmp(str, field->name, namelen)) {
1656 size_t len;
1657
1658 str += namelen + 1;
1659 len = pos - str;
1660
1661 if (len > hde->dynamic_len)
1662 hde->dynamic_len = len;
1663 break;
1664 }
1665
1666 if (last)
1667 str = NULL;
1668 else
1669 str = pos + 1;
1670 }
1671}
1672
1673static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1674 struct perf_evsel *evsel __maybe_unused)
1675{
1676 struct hpp_dynamic_entry *hde;
1677 size_t len = fmt->user_len;
1678
1679 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1680
1681 if (!len)
1682 len = hde_width(hde);
1683
1684 return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, hde->field->name);
1685}
1686
1687static int __sort__hde_width(struct perf_hpp_fmt *fmt,
1688 struct perf_hpp *hpp __maybe_unused,
1689 struct perf_evsel *evsel __maybe_unused)
1690{
1691 struct hpp_dynamic_entry *hde;
1692 size_t len = fmt->user_len;
1693
1694 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1695
1696 if (!len)
1697 len = hde_width(hde);
1698
1699 return len;
1700}
1701
1702bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists)
1703{
1704 struct hpp_dynamic_entry *hde;
1705
1706 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1707
1708 return hists_to_evsel(hists) == hde->evsel;
1709}
1710
1711static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1712 struct hist_entry *he)
1713{
1714 struct hpp_dynamic_entry *hde;
1715 size_t len = fmt->user_len;
1716 char *str, *pos;
1717 struct format_field *field;
1718 size_t namelen;
1719 bool last = false;
1720 int ret;
1721
1722 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1723
1724 if (!len)
1725 len = hde_width(hde);
1726
1727 if (hde->raw_trace)
1728 goto raw_field;
1729
1730 field = hde->field;
1731 namelen = strlen(field->name);
1732 str = he->trace_output;
1733
1734 while (str) {
1735 pos = strchr(str, ' ');
1736 if (pos == NULL) {
1737 last = true;
1738 pos = str + strlen(str);
1739 }
1740
1741 if (!strncmp(str, field->name, namelen)) {
1742 str += namelen + 1;
1743 str = strndup(str, pos - str);
1744
1745 if (str == NULL)
1746 return scnprintf(hpp->buf, hpp->size,
1747 "%*.*s", len, len, "ERROR");
1748 break;
1749 }
1750
1751 if (last)
1752 str = NULL;
1753 else
1754 str = pos + 1;
1755 }
1756
1757 if (str == NULL) {
1758 struct trace_seq seq;
1759raw_field:
1760 trace_seq_init(&seq);
1761 pevent_print_field(&seq, he->raw_data, hde->field);
1762 str = seq.buffer;
1763 }
1764
1765 ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, str);
1766 free(str);
1767 return ret;
1768}
1769
1770static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
1771 struct hist_entry *a, struct hist_entry *b)
1772{
1773 struct hpp_dynamic_entry *hde;
1774 struct format_field *field;
1775 unsigned offset, size;
1776
1777 hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
1778
1779 field = hde->field;
1780 if (field->flags & FIELD_IS_DYNAMIC) {
1781 unsigned long long dyn;
1782
1783 pevent_read_number_field(field, a->raw_data, &dyn);
1784 offset = dyn & 0xffff;
1785 size = (dyn >> 16) & 0xffff;
1786
1787 /* record max width for output */
1788 if (size > hde->dynamic_len)
1789 hde->dynamic_len = size;
1790 } else {
1791 offset = field->offset;
1792 size = field->size;
1793
1794 update_dynamic_len(hde, a);
1795 update_dynamic_len(hde, b);
1796 }
1797
1798 return memcmp(a->raw_data + offset, b->raw_data + offset, size);
1799}
1800
1801bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt)
1802{
1803 return fmt->cmp == __sort__hde_cmp;
1804}
1805
1806static struct hpp_dynamic_entry *
1807__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
1808{
1809 struct hpp_dynamic_entry *hde;
1810
1811 hde = malloc(sizeof(*hde));
1812 if (hde == NULL) {
1813 pr_debug("Memory allocation failed\n");
1814 return NULL;
1815 }
1816
1817 hde->evsel = evsel;
1818 hde->field = field;
1819 hde->dynamic_len = 0;
1820
1821 hde->hpp.name = field->name;
1822 hde->hpp.header = __sort__hde_header;
1823 hde->hpp.width = __sort__hde_width;
1824 hde->hpp.entry = __sort__hde_entry;
1825 hde->hpp.color = NULL;
1826
1827 hde->hpp.cmp = __sort__hde_cmp;
1828 hde->hpp.collapse = __sort__hde_cmp;
1829 hde->hpp.sort = __sort__hde_cmp;
1830
1831 INIT_LIST_HEAD(&hde->hpp.list);
1832 INIT_LIST_HEAD(&hde->hpp.sort_list);
1833 hde->hpp.elide = false;
1834 hde->hpp.len = 0;
1835 hde->hpp.user_len = 0;
1836
1837 return hde;
1838}
1839
1840static int parse_field_name(char *str, char **event, char **field, char **opt)
1841{
1842 char *event_name, *field_name, *opt_name;
1843
1844 event_name = str;
1845 field_name = strchr(str, '.');
1846
1847 if (field_name) {
1848 *field_name++ = '\0';
1849 } else {
1850 event_name = NULL;
1851 field_name = str;
1852 }
1853
1854 opt_name = strchr(field_name, '/');
1855 if (opt_name)
1856 *opt_name++ = '\0';
1857
1858 *event = event_name;
1859 *field = field_name;
1860 *opt = opt_name;
1861
1862 return 0;
1863}
1864
1865/* find match evsel using a given event name. The event name can be:
1866 * 1. '%' + event index (e.g. '%1' for first event)
1867 * 2. full event name (e.g. sched:sched_switch)
1868 * 3. partial event name (should not contain ':')
1869 */
1870static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_name)
1871{
1872 struct perf_evsel *evsel = NULL;
1873 struct perf_evsel *pos;
1874 bool full_name;
1875
1876 /* case 1 */
1877 if (event_name[0] == '%') {
1878 int nr = strtol(event_name+1, NULL, 0);
1879
1880 if (nr > evlist->nr_entries)
1881 return NULL;
1882
1883 evsel = perf_evlist__first(evlist);
1884 while (--nr > 0)
1885 evsel = perf_evsel__next(evsel);
1886
1887 return evsel;
1888 }
1889
1890 full_name = !!strchr(event_name, ':');
1891 evlist__for_each(evlist, pos) {
1892 /* case 2 */
1893 if (full_name && !strcmp(pos->name, event_name))
1894 return pos;
1895 /* case 3 */
1896 if (!full_name && strstr(pos->name, event_name)) {
1897 if (evsel) {
1898 pr_debug("'%s' event is ambiguous: it can be %s or %s\n",
1899 event_name, evsel->name, pos->name);
1900 return NULL;
1901 }
1902 evsel = pos;
1903 }
1904 }
1905
1906 return evsel;
1907}
1908
1909static int __dynamic_dimension__add(struct perf_evsel *evsel,
1910 struct format_field *field,
1911 bool raw_trace)
1912{
1913 struct hpp_dynamic_entry *hde;
1914
1915 hde = __alloc_dynamic_entry(evsel, field);
1916 if (hde == NULL)
1917 return -ENOMEM;
1918
1919 hde->raw_trace = raw_trace;
1920
1921 perf_hpp__register_sort_field(&hde->hpp);
1922 return 0;
1923}
1924
1925static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace)
1926{
1927 int ret;
1928 struct format_field *field;
1929
1930 field = evsel->tp_format->format.fields;
1931 while (field) {
1932 ret = __dynamic_dimension__add(evsel, field, raw_trace);
1933 if (ret < 0)
1934 return ret;
1935
1936 field = field->next;
1937 }
1938 return 0;
1939}
1940
1941static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace)
1942{
1943 int ret;
1944 struct perf_evsel *evsel;
1945
1946 evlist__for_each(evlist, evsel) {
1947 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
1948 continue;
1949
1950 ret = add_evsel_fields(evsel, raw_trace);
1951 if (ret < 0)
1952 return ret;
1953 }
1954 return 0;
1955}
1956
1957static int add_all_matching_fields(struct perf_evlist *evlist,
1958 char *field_name, bool raw_trace)
1959{
1960 int ret = -ESRCH;
1961 struct perf_evsel *evsel;
1962 struct format_field *field;
1963
1964 evlist__for_each(evlist, evsel) {
1965 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
1966 continue;
1967
1968 field = pevent_find_any_field(evsel->tp_format, field_name);
1969 if (field == NULL)
1970 continue;
1971
1972 ret = __dynamic_dimension__add(evsel, field, raw_trace);
1973 if (ret < 0)
1974 break;
1975 }
1976 return ret;
1977}
1978
1979static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
1980{
1981 char *str, *event_name, *field_name, *opt_name;
1982 struct perf_evsel *evsel;
1983 struct format_field *field;
1984 bool raw_trace = symbol_conf.raw_trace;
1985 int ret = 0;
1986
1987 if (evlist == NULL)
1988 return -ENOENT;
1989
1990 str = strdup(tok);
1991 if (str == NULL)
1992 return -ENOMEM;
1993
1994 if (parse_field_name(str, &event_name, &field_name, &opt_name) < 0) {
1995 ret = -EINVAL;
1996 goto out;
1997 }
1998
1999 if (opt_name) {
2000 if (strcmp(opt_name, "raw")) {
2001 pr_debug("unsupported field option %s\n", opt_name);
2002 ret = -EINVAL;
2003 goto out;
2004 }
2005 raw_trace = true;
2006 }
2007
2008 if (!strcmp(field_name, "trace_fields")) {
2009 ret = add_all_dynamic_fields(evlist, raw_trace);
2010 goto out;
2011 }
2012
2013 if (event_name == NULL) {
2014 ret = add_all_matching_fields(evlist, field_name, raw_trace);
2015 goto out;
2016 }
2017
2018 evsel = find_evsel(evlist, event_name);
2019 if (evsel == NULL) {
2020 pr_debug("Cannot find event: %s\n", event_name);
2021 ret = -ENOENT;
2022 goto out;
2023 }
2024
2025 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2026 pr_debug("%s is not a tracepoint event\n", event_name);
2027 ret = -EINVAL;
2028 goto out;
2029 }
2030
2031 if (!strcmp(field_name, "*")) {
2032 ret = add_evsel_fields(evsel, raw_trace);
2033 } else {
2034 field = pevent_find_any_field(evsel->tp_format, field_name);
2035 if (field == NULL) {
2036 pr_debug("Cannot find event field for %s.%s\n",
2037 event_name, field_name);
2038 return -ENOENT;
2039 }
2040
2041 ret = __dynamic_dimension__add(evsel, field, raw_trace);
2042 }
2043
2044out:
2045 free(str);
2046 return ret;
2047}
2048
1532static int __sort_dimension__add(struct sort_dimension *sd) 2049static int __sort_dimension__add(struct sort_dimension *sd)
1533{ 2050{
1534 if (sd->taken) 2051 if (sd->taken)
@@ -1583,7 +2100,8 @@ int hpp_dimension__add_output(unsigned col)
1583 return __hpp_dimension__add_output(&hpp_sort_dimensions[col]); 2100 return __hpp_dimension__add_output(&hpp_sort_dimensions[col]);
1584} 2101}
1585 2102
1586int sort_dimension__add(const char *tok) 2103static int sort_dimension__add(const char *tok,
2104 struct perf_evlist *evlist __maybe_unused)
1587{ 2105{
1588 unsigned int i; 2106 unsigned int i;
1589 2107
@@ -1664,10 +2182,13 @@ int sort_dimension__add(const char *tok)
1664 return 0; 2182 return 0;
1665 } 2183 }
1666 2184
2185 if (!add_dynamic_entry(evlist, tok))
2186 return 0;
2187
1667 return -ESRCH; 2188 return -ESRCH;
1668} 2189}
1669 2190
1670static const char *get_default_sort_order(void) 2191static const char *get_default_sort_order(struct perf_evlist *evlist)
1671{ 2192{
1672 const char *default_sort_orders[] = { 2193 const char *default_sort_orders[] = {
1673 default_sort_order, 2194 default_sort_order,
@@ -1675,14 +2196,33 @@ static const char *get_default_sort_order(void)
1675 default_mem_sort_order, 2196 default_mem_sort_order,
1676 default_top_sort_order, 2197 default_top_sort_order,
1677 default_diff_sort_order, 2198 default_diff_sort_order,
2199 default_tracepoint_sort_order,
1678 }; 2200 };
2201 bool use_trace = true;
2202 struct perf_evsel *evsel;
1679 2203
1680 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); 2204 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
1681 2205
2206 if (evlist == NULL)
2207 goto out_no_evlist;
2208
2209 evlist__for_each(evlist, evsel) {
2210 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2211 use_trace = false;
2212 break;
2213 }
2214 }
2215
2216 if (use_trace) {
2217 sort__mode = SORT_MODE__TRACEPOINT;
2218 if (symbol_conf.raw_trace)
2219 return "trace_fields";
2220 }
2221out_no_evlist:
1682 return default_sort_orders[sort__mode]; 2222 return default_sort_orders[sort__mode];
1683} 2223}
1684 2224
1685static int setup_sort_order(void) 2225static int setup_sort_order(struct perf_evlist *evlist)
1686{ 2226{
1687 char *new_sort_order; 2227 char *new_sort_order;
1688 2228
@@ -1703,7 +2243,7 @@ static int setup_sort_order(void)
1703 * because it's checked over the rest of the code. 2243 * because it's checked over the rest of the code.
1704 */ 2244 */
1705 if (asprintf(&new_sort_order, "%s,%s", 2245 if (asprintf(&new_sort_order, "%s,%s",
1706 get_default_sort_order(), sort_order + 1) < 0) { 2246 get_default_sort_order(evlist), sort_order + 1) < 0) {
1707 error("Not enough memory to set up --sort"); 2247 error("Not enough memory to set up --sort");
1708 return -ENOMEM; 2248 return -ENOMEM;
1709 } 2249 }
@@ -1712,13 +2252,41 @@ static int setup_sort_order(void)
1712 return 0; 2252 return 0;
1713} 2253}
1714 2254
1715static int __setup_sorting(void) 2255/*
2256 * Adds 'pre,' prefix into 'str' is 'pre' is
2257 * not already part of 'str'.
2258 */
2259static char *prefix_if_not_in(const char *pre, char *str)
2260{
2261 char *n;
2262
2263 if (!str || strstr(str, pre))
2264 return str;
2265
2266 if (asprintf(&n, "%s,%s", pre, str) < 0)
2267 return NULL;
2268
2269 free(str);
2270 return n;
2271}
2272
2273static char *setup_overhead(char *keys)
2274{
2275 keys = prefix_if_not_in("overhead", keys);
2276
2277 if (symbol_conf.cumulate_callchain)
2278 keys = prefix_if_not_in("overhead_children", keys);
2279
2280 return keys;
2281}
2282
2283static int __setup_sorting(struct perf_evlist *evlist)
1716{ 2284{
1717 char *tmp, *tok, *str; 2285 char *tmp, *tok, *str;
1718 const char *sort_keys; 2286 const char *sort_keys;
1719 int ret = 0; 2287 int ret = 0;
1720 2288
1721 ret = setup_sort_order(); 2289 ret = setup_sort_order(evlist);
1722 if (ret) 2290 if (ret)
1723 return ret; 2291 return ret;
1724 2292
@@ -1732,7 +2300,7 @@ static int __setup_sorting(void)
1732 return 0; 2300 return 0;
1733 } 2301 }
1734 2302
1735 sort_keys = get_default_sort_order(); 2303 sort_keys = get_default_sort_order(evlist);
1736 } 2304 }
1737 2305
1738 str = strdup(sort_keys); 2306 str = strdup(sort_keys);
@@ -1741,9 +2309,20 @@ static int __setup_sorting(void)
1741 return -ENOMEM; 2309 return -ENOMEM;
1742 } 2310 }
1743 2311
2312 /*
2313 * Prepend overhead fields for backward compatibility.
2314 */
2315 if (!is_strict_order(field_order)) {
2316 str = setup_overhead(str);
2317 if (str == NULL) {
2318 error("Not enough memory to setup overhead keys");
2319 return -ENOMEM;
2320 }
2321 }
2322
1744 for (tok = strtok_r(str, ", ", &tmp); 2323 for (tok = strtok_r(str, ", ", &tmp);
1745 tok; tok = strtok_r(NULL, ", ", &tmp)) { 2324 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1746 ret = sort_dimension__add(tok); 2325 ret = sort_dimension__add(tok, evlist);
1747 if (ret == -EINVAL) { 2326 if (ret == -EINVAL) {
1748 error("Invalid --sort key: `%s'", tok); 2327 error("Invalid --sort key: `%s'", tok);
1749 break; 2328 break;
@@ -1954,16 +2533,16 @@ out:
1954 return ret; 2533 return ret;
1955} 2534}
1956 2535
1957int setup_sorting(void) 2536int setup_sorting(struct perf_evlist *evlist)
1958{ 2537{
1959 int err; 2538 int err;
1960 2539
1961 err = __setup_sorting(); 2540 err = __setup_sorting(evlist);
1962 if (err < 0) 2541 if (err < 0)
1963 return err; 2542 return err;
1964 2543
1965 if (parent_pattern != default_parent_pattern) { 2544 if (parent_pattern != default_parent_pattern) {
1966 err = sort_dimension__add("parent"); 2545 err = sort_dimension__add("parent", evlist);
1967 if (err < 0) 2546 if (err < 0)
1968 return err; 2547 return err;
1969 } 2548 }
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 86f05e7a5566..687bbb124428 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -122,6 +122,9 @@ struct hist_entry {
122 struct branch_info *branch_info; 122 struct branch_info *branch_info;
123 struct hists *hists; 123 struct hists *hists;
124 struct mem_info *mem_info; 124 struct mem_info *mem_info;
125 void *raw_data;
126 u32 raw_size;
127 void *trace_output;
125 struct callchain_root callchain[0]; /* must be last member */ 128 struct callchain_root callchain[0]; /* must be last member */
126}; 129};
127 130
@@ -164,6 +167,7 @@ enum sort_mode {
164 SORT_MODE__MEMORY, 167 SORT_MODE__MEMORY,
165 SORT_MODE__TOP, 168 SORT_MODE__TOP,
166 SORT_MODE__DIFF, 169 SORT_MODE__DIFF,
170 SORT_MODE__TRACEPOINT,
167}; 171};
168 172
169enum sort_type { 173enum sort_type {
@@ -180,6 +184,7 @@ enum sort_type {
180 SORT_LOCAL_WEIGHT, 184 SORT_LOCAL_WEIGHT,
181 SORT_GLOBAL_WEIGHT, 185 SORT_GLOBAL_WEIGHT,
182 SORT_TRANSACTION, 186 SORT_TRANSACTION,
187 SORT_TRACE,
183 188
184 /* branch stack specific sort keys */ 189 /* branch stack specific sort keys */
185 __SORT_BRANCH_STACK, 190 __SORT_BRANCH_STACK,
@@ -209,8 +214,6 @@ enum sort_type {
209 */ 214 */
210 215
211struct sort_entry { 216struct sort_entry {
212 struct list_head list;
213
214 const char *se_header; 217 const char *se_header;
215 218
216 int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *); 219 int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *);
@@ -224,10 +227,11 @@ struct sort_entry {
224extern struct sort_entry sort_thread; 227extern struct sort_entry sort_thread;
225extern struct list_head hist_entry__sort_list; 228extern struct list_head hist_entry__sort_list;
226 229
227int setup_sorting(void); 230struct perf_evlist;
231struct pevent;
232int setup_sorting(struct perf_evlist *evlist);
228int setup_output_field(void); 233int setup_output_field(void);
229void reset_output_field(void); 234void reset_output_field(void);
230extern int sort_dimension__add(const char *);
231void sort__setup_elide(FILE *fp); 235void sort__setup_elide(FILE *fp);
232void perf_hpp__set_elide(int idx, bool elide); 236void perf_hpp__set_elide(int idx, bool elide);
233 237
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index d51abd2e7865..3b2de6eb3376 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -39,6 +39,7 @@ struct symbol_conf symbol_conf = {
39 .cumulate_callchain = true, 39 .cumulate_callchain = true,
40 .show_hist_headers = true, 40 .show_hist_headers = true,
41 .symfs = "", 41 .symfs = "",
42 .event_group = true,
42}; 43};
43 44
44static enum dso_binary_type binary_type_symtab[] = { 45static enum dso_binary_type binary_type_symtab[] = {
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 857f707ac12b..ccd1caa40e11 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -109,7 +109,8 @@ struct symbol_conf {
109 branch_callstack, 109 branch_callstack,
110 has_filter, 110 has_filter,
111 show_ref_callgraph, 111 show_ref_callgraph,
112 hide_unresolved; 112 hide_unresolved,
113 raw_trace;
113 const char *vmlinux_name, 114 const char *vmlinux_name,
114 *kallsyms_name, 115 *kallsyms_name,
115 *source_prefix, 116 *source_prefix,
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b85ee55cca0c..bce5b1dac268 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -65,6 +65,7 @@ int tracing_data_put(struct tracing_data *tdata);
65struct addr_location; 65struct addr_location;
66 66
67struct perf_session; 67struct perf_session;
68struct perf_stat_config;
68 69
69struct scripting_ops { 70struct scripting_ops {
70 const char *name; 71 const char *name;
@@ -75,6 +76,9 @@ struct scripting_ops {
75 struct perf_sample *sample, 76 struct perf_sample *sample,
76 struct perf_evsel *evsel, 77 struct perf_evsel *evsel,
77 struct addr_location *al); 78 struct addr_location *al);
79 void (*process_stat)(struct perf_stat_config *config,
80 struct perf_evsel *evsel, u64 tstamp);
81 void (*process_stat_interval)(u64 tstamp);
78 int (*generate_script) (struct pevent *pevent, const char *outfile); 82 int (*generate_script) (struct pevent *pevent, const char *outfile);
79}; 83};
80 84
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index db8142ba7cb9..cf5e250bc78e 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -96,6 +96,16 @@ static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
96 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, 96 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
97 MAP__FUNCTION, addr, &al); 97 MAP__FUNCTION, addr, &al);
98 if (!al.map) { 98 if (!al.map) {
99 /*
100 * We've seen cases (softice) where DWARF unwinder went
101 * through non executable mmaps, which we need to lookup
102 * in MAP__VARIABLE tree.
103 */
104 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
105 MAP__VARIABLE, addr, &al);
106 }
107
108 if (!al.map) {
99 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 109 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
100 return -1; 110 return -1;
101 } 111 }
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 3c258a0e4092..ee7e372297e5 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -319,6 +319,15 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
319 319
320 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, 320 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
321 MAP__FUNCTION, ip, &al); 321 MAP__FUNCTION, ip, &al);
322 if (!al.map) {
323 /*
324 * We've seen cases (softice) where DWARF unwinder went
325 * through non executable mmaps, which we need to lookup
326 * in MAP__VARIABLE tree.
327 */
328 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
329 MAP__VARIABLE, ip, &al);
330 }
322 return al.map; 331 return al.map;
323} 332}
324 333
@@ -416,20 +425,19 @@ get_proc_name(unw_addr_space_t __maybe_unused as,
416static int access_dso_mem(struct unwind_info *ui, unw_word_t addr, 425static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
417 unw_word_t *data) 426 unw_word_t *data)
418{ 427{
419 struct addr_location al; 428 struct map *map;
420 ssize_t size; 429 ssize_t size;
421 430
422 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, 431 map = find_map(addr, ui);
423 MAP__FUNCTION, addr, &al); 432 if (!map) {
424 if (!al.map) {
425 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 433 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
426 return -1; 434 return -1;
427 } 435 }
428 436
429 if (!al.map->dso) 437 if (!map->dso)
430 return -1; 438 return -1;
431 439
432 size = dso__data_read_addr(al.map->dso, al.map, ui->machine, 440 size = dso__data_read_addr(map->dso, map, ui->machine,
433 addr, (u8 *) data, sizeof(*data)); 441 addr, (u8 *) data, sizeof(*data));
434 442
435 return !(size == sizeof(*data)); 443 return !(size == sizeof(*data));
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index aff0cfd83662..88b8f8d21f58 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -16,6 +16,8 @@
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <unistd.h> 17#include <unistd.h>
18#include "callchain.h" 18#include "callchain.h"
19#include "strlist.h"
20#include <subcmd/exec-cmd.h>
19 21
20struct callchain_param callchain_param = { 22struct callchain_param callchain_param = {
21 .mode = CHAIN_GRAPH_ABS, 23 .mode = CHAIN_GRAPH_ABS,
@@ -663,3 +665,28 @@ fetch_kernel_version(unsigned int *puint, char *str,
663 *puint = (version << 16) + (patchlevel << 8) + sublevel; 665 *puint = (version << 16) + (patchlevel << 8) + sublevel;
664 return 0; 666 return 0;
665} 667}
668
669const char *perf_tip(const char *dirpath)
670{
671 struct strlist *tips;
672 struct str_node *node;
673 char *tip = NULL;
674 struct strlist_config conf = {
675 .dirname = system_path(dirpath) ,
676 };
677
678 tips = strlist__new("tips.txt", &conf);
679 if (tips == NULL || strlist__nr_entries(tips) == 1) {
680 tip = (char *)"Cannot find tips.txt file";
681 goto out;
682 }
683
684 node = strlist__entry(tips, random() % strlist__nr_entries(tips));
685 if (asprintf(&tip, "Tip: %s", node->s) < 0)
686 tip = (char *)"Tip: get more memory! ;-)";
687
688out:
689 strlist__delete(tips);
690
691 return tip;
692}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 4b519c59bdc3..fe915e616f9b 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -342,4 +342,6 @@ int fetch_kernel_version(unsigned int *puint,
342#define KVER_FMT "%d.%d.%d" 342#define KVER_FMT "%d.%d.%d"
343#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) 343#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
344 344
345const char *perf_tip(const char *dirpath);
346
345#endif /* GIT_COMPAT_UTIL_H */ 347#endif /* GIT_COMPAT_UTIL_H */