aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-11-13 13:05:09 -0500
committerIngo Molnar <mingo@kernel.org>2012-11-13 13:13:41 -0500
commitccf59d8da119ab03dcbdf95fb5e5adcef6ba51f2 (patch)
treed390f9230edac3d9c42a8ad8b030182890b6e609
parent95d18aa2b6c05351181934b3bc34ce038cc7b637 (diff)
parent27f94d52394003d444a383eaf8d4824daf32432e (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: * Don't show scripts menu for 'perf top', fix from Feng Tang * Add framework for automated perf_event_attr tests, where tools with different command line options will be run from a 'perf test', via python glue, and the perf syscall will be intercepted to verify that the perf_event_attr fields set by the tool are those expected, from Jiri Olsa * Use normalized arch name for searching objdump path. This fixes cases where the system's objdump (e.g. x86_64) supports the architecture in the perf.data file (e.g. i686), but is not the same, fix from Namhyung Kim. * Postpone objdump check until annotation requested, from Namhyung Kim. * Add a 'link' method for hists, so that we can have the leader with buckets for all the entries in all the hists. This new method is now used in the default 'diff' output, making the sum of the 'baseline' column be 100%, eliminating blind spots. Now we need to use this for 'diff' with > 2 perf.data files and for multi event 'report' and 'annotate'. * libtraceevent fixes for compiler warnings trying to make perf it build on some distros, like fedora 14, 32-bit, some of the warnings really pointed to real bugs. * Remove temp dir on failure in 'perf test', fix from Jiri Olsa. * Fixes for handling data, stack mmaps, from Namhyung Kim. * Fix live annotation bug related to recent objdump lookup patches, from Namhyung Kim * Don't try to follow jump target on PLT symbols in the annotation browser, fix from Namhyung Kim. * Fix leak on hist_entry delete, from Namhyung Kim. * Fix a CPU_ALLOC related build error on builtin-test, from Zheng Liu. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/lib/traceevent/event-parse.c22
-rw-r--r--tools/perf/Documentation/android.txt5
-rw-r--r--tools/perf/Makefile34
-rw-r--r--tools/perf/arch/common.c47
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-diff.c48
-rw-r--r--tools/perf/builtin-report.c11
-rw-r--r--tools/perf/builtin-top.c10
-rw-r--r--tools/perf/perf.c2
-rw-r--r--tools/perf/perf.h17
-rw-r--r--tools/perf/tests/attr.c174
-rw-r--r--tools/perf/tests/attr.py322
-rw-r--r--tools/perf/tests/attr/README64
-rw-r--r--tools/perf/tests/attr/base-record39
-rw-r--r--tools/perf/tests/attr/base-stat39
-rw-r--r--tools/perf/tests/attr/test-record-basic5
-rw-r--r--tools/perf/tests/attr/test-record-branch-any8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any_call8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any_ret8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-hv8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-ind_call8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-k8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-u8
-rw-r--r--tools/perf/tests/attr/test-record-count8
-rw-r--r--tools/perf/tests/attr/test-record-data8
-rw-r--r--tools/perf/tests/attr/test-record-freq6
-rw-r--r--tools/perf/tests/attr/test-record-graph-default6
-rw-r--r--tools/perf/tests/attr/test-record-graph-dwarf10
-rw-r--r--tools/perf/tests/attr/test-record-graph-fp6
-rw-r--r--tools/perf/tests/attr/test-record-group17
-rw-r--r--tools/perf/tests/attr/test-record-group120
-rw-r--r--tools/perf/tests/attr/test-record-no-delay9
-rw-r--r--tools/perf/tests/attr/test-record-no-inherit7
-rw-r--r--tools/perf/tests/attr/test-record-no-samples6
-rw-r--r--tools/perf/tests/attr/test-record-period7
-rw-r--r--tools/perf/tests/attr/test-record-raw7
-rw-r--r--tools/perf/tests/attr/test-stat-basic6
-rw-r--r--tools/perf/tests/attr/test-stat-default64
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-1101
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-2155
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-3173
-rw-r--r--tools/perf/tests/attr/test-stat-group15
-rw-r--r--tools/perf/tests/attr/test-stat-group117
-rw-r--r--tools/perf/tests/attr/test-stat-no-inherit7
-rw-r--r--tools/perf/tests/builtin-test.c (renamed from tools/perf/builtin-test.c)51
-rw-r--r--tools/perf/tests/dso-data.c (renamed from tools/perf/util/dso-test-data.c)1
-rw-r--r--tools/perf/tests/parse-events.c (renamed from tools/perf/util/parse-events-test.c)0
-rw-r--r--tools/perf/ui/browsers/annotate.c39
-rw-r--r--tools/perf/ui/browsers/hists.c63
-rw-r--r--tools/perf/ui/gtk/browser.c4
-rw-r--r--tools/perf/ui/hist.c10
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN14
-rw-r--r--tools/perf/util/annotate.c71
-rw-r--r--tools/perf/util/annotate.h9
-rw-r--r--tools/perf/util/dso.c1
-rw-r--r--tools/perf/util/hist.c100
-rw-r--r--tools/perf/util/hist.h34
-rw-r--r--tools/perf/util/machine.c205
-rw-r--r--tools/perf/util/machine.h131
-rw-r--r--tools/perf/util/map.c181
-rw-r--r--tools/perf/util/map.h93
-rw-r--r--tools/perf/util/parse-events.l2
-rw-r--r--tools/perf/util/session.h5
-rw-r--r--tools/perf/util/sort.h27
-rw-r--r--tools/perf/util/symbol.c1
-rw-r--r--tools/perf/util/symbol.h20
67 files changed, 2118 insertions, 504 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index f2989c525e48..5a824e355d04 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -174,7 +174,7 @@ static int cmdline_init(struct pevent *pevent)
174 return 0; 174 return 0;
175} 175}
176 176
177static char *find_cmdline(struct pevent *pevent, int pid) 177static const char *find_cmdline(struct pevent *pevent, int pid)
178{ 178{
179 const struct cmdline *comm; 179 const struct cmdline *comm;
180 struct cmdline key; 180 struct cmdline key;
@@ -2637,7 +2637,7 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
2637 struct print_arg *farg; 2637 struct print_arg *farg;
2638 enum event_type type; 2638 enum event_type type;
2639 char *token; 2639 char *token;
2640 char *test; 2640 const char *test;
2641 int i; 2641 int i;
2642 2642
2643 arg->type = PRINT_FUNC; 2643 arg->type = PRINT_FUNC;
@@ -3889,7 +3889,7 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
3889 struct event_format *event, struct print_arg *arg) 3889 struct event_format *event, struct print_arg *arg)
3890{ 3890{
3891 unsigned char *buf; 3891 unsigned char *buf;
3892 char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"; 3892 const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
3893 3893
3894 if (arg->type == PRINT_FUNC) { 3894 if (arg->type == PRINT_FUNC) {
3895 process_defined_func(s, data, size, event, arg); 3895 process_defined_func(s, data, size, event, arg);
@@ -3931,7 +3931,8 @@ static int is_printable_array(char *p, unsigned int len)
3931 return 1; 3931 return 1;
3932} 3932}
3933 3933
3934static void print_event_fields(struct trace_seq *s, void *data, int size, 3934static void print_event_fields(struct trace_seq *s, void *data,
3935 int size __maybe_unused,
3935 struct event_format *event) 3936 struct event_format *event)
3936{ 3937{
3937 struct format_field *field; 3938 struct format_field *field;
@@ -4408,7 +4409,7 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
4408void pevent_print_event(struct pevent *pevent, struct trace_seq *s, 4409void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4409 struct pevent_record *record) 4410 struct pevent_record *record)
4410{ 4411{
4411 static char *spaces = " "; /* 20 spaces */ 4412 static const char *spaces = " "; /* 20 spaces */
4412 struct event_format *event; 4413 struct event_format *event;
4413 unsigned long secs; 4414 unsigned long secs;
4414 unsigned long usecs; 4415 unsigned long usecs;
@@ -5070,8 +5071,8 @@ static const char * const pevent_error_str[] = {
5070}; 5071};
5071#undef _PE 5072#undef _PE
5072 5073
5073int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, 5074int pevent_strerror(struct pevent *pevent __maybe_unused,
5074 char *buf, size_t buflen) 5075 enum pevent_errno errnum, char *buf, size_t buflen)
5075{ 5076{
5076 int idx; 5077 int idx;
5077 const char *msg; 5078 const char *msg;
@@ -5100,6 +5101,7 @@ int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
5100 case PEVENT_ERRNO__READ_FORMAT_FAILED: 5101 case PEVENT_ERRNO__READ_FORMAT_FAILED:
5101 case PEVENT_ERRNO__READ_PRINT_FAILED: 5102 case PEVENT_ERRNO__READ_PRINT_FAILED:
5102 case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED: 5103 case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED:
5104 case PEVENT_ERRNO__INVALID_ARG_TYPE:
5103 snprintf(buf, buflen, "%s", msg); 5105 snprintf(buf, buflen, "%s", msg);
5104 break; 5106 break;
5105 5107
@@ -5362,7 +5364,7 @@ int pevent_register_print_function(struct pevent *pevent,
5362 if (type == PEVENT_FUNC_ARG_VOID) 5364 if (type == PEVENT_FUNC_ARG_VOID)
5363 break; 5365 break;
5364 5366
5365 if (type < 0 || type >= PEVENT_FUNC_ARG_MAX_TYPES) { 5367 if (type >= PEVENT_FUNC_ARG_MAX_TYPES) {
5366 do_warning("Invalid argument type %d", type); 5368 do_warning("Invalid argument type %d", type);
5367 ret = PEVENT_ERRNO__INVALID_ARG_TYPE; 5369 ret = PEVENT_ERRNO__INVALID_ARG_TYPE;
5368 goto out_free; 5370 goto out_free;
@@ -5560,7 +5562,7 @@ void pevent_free(struct pevent *pevent)
5560 } 5562 }
5561 5563
5562 if (pevent->func_map) { 5564 if (pevent->func_map) {
5563 for (i = 0; i < pevent->func_count; i++) { 5565 for (i = 0; i < (int)pevent->func_count; i++) {
5564 free(pevent->func_map[i].func); 5566 free(pevent->func_map[i].func);
5565 free(pevent->func_map[i].mod); 5567 free(pevent->func_map[i].mod);
5566 } 5568 }
@@ -5582,7 +5584,7 @@ void pevent_free(struct pevent *pevent)
5582 } 5584 }
5583 5585
5584 if (pevent->printk_map) { 5586 if (pevent->printk_map) {
5585 for (i = 0; i < pevent->printk_count; i++) 5587 for (i = 0; i < (int)pevent->printk_count; i++)
5586 free(pevent->printk_map[i].printk); 5588 free(pevent->printk_map[i].printk);
5587 free(pevent->printk_map); 5589 free(pevent->printk_map);
5588 } 5590 }
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
index a39dbbb44c4c..8484c3a04a6a 100644
--- a/tools/perf/Documentation/android.txt
+++ b/tools/perf/Documentation/android.txt
@@ -48,7 +48,10 @@ For x86:
48II. Compile perf for Android 48II. Compile perf for Android
49------------------------------------------------ 49------------------------------------------------
50You need to run make with the NDK toolchain and sysroot defined above: 50You need to run make with the NDK toolchain and sysroot defined above:
51 make CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}" 51For arm:
52 make ARCH=arm CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}"
53For x86:
54 make ARCH=x86 CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}"
52 55
53III. Install perf 56III. Install perf
54----------------------------------------------- 57-----------------------------------------------
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 7e25f59e5e89..cca5bb8334ad 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -169,7 +169,7 @@ endif
169 169
170### --- END CONFIGURATION SECTION --- 170### --- END CONFIGURATION SECTION ---
171 171
172BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 172BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -Iutil -I. -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
173BASIC_LDFLAGS = 173BASIC_LDFLAGS =
174 174
175ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) 175ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y)
@@ -371,7 +371,6 @@ LIB_OBJS += $(OUTPUT)util/help.o
371LIB_OBJS += $(OUTPUT)util/levenshtein.o 371LIB_OBJS += $(OUTPUT)util/levenshtein.o
372LIB_OBJS += $(OUTPUT)util/parse-options.o 372LIB_OBJS += $(OUTPUT)util/parse-options.o
373LIB_OBJS += $(OUTPUT)util/parse-events.o 373LIB_OBJS += $(OUTPUT)util/parse-events.o
374LIB_OBJS += $(OUTPUT)util/parse-events-test.o
375LIB_OBJS += $(OUTPUT)util/path.o 374LIB_OBJS += $(OUTPUT)util/path.o
376LIB_OBJS += $(OUTPUT)util/rbtree.o 375LIB_OBJS += $(OUTPUT)util/rbtree.o
377LIB_OBJS += $(OUTPUT)util/bitmap.o 376LIB_OBJS += $(OUTPUT)util/bitmap.o
@@ -389,7 +388,6 @@ LIB_OBJS += $(OUTPUT)util/sigchain.o
389LIB_OBJS += $(OUTPUT)util/dso.o 388LIB_OBJS += $(OUTPUT)util/dso.o
390LIB_OBJS += $(OUTPUT)util/symbol.o 389LIB_OBJS += $(OUTPUT)util/symbol.o
391LIB_OBJS += $(OUTPUT)util/symbol-elf.o 390LIB_OBJS += $(OUTPUT)util/symbol-elf.o
392LIB_OBJS += $(OUTPUT)util/dso-test-data.o
393LIB_OBJS += $(OUTPUT)util/color.o 391LIB_OBJS += $(OUTPUT)util/color.o
394LIB_OBJS += $(OUTPUT)util/pager.o 392LIB_OBJS += $(OUTPUT)util/pager.o
395LIB_OBJS += $(OUTPUT)util/header.o 393LIB_OBJS += $(OUTPUT)util/header.o
@@ -430,6 +428,10 @@ LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
430 428
431LIB_OBJS += $(OUTPUT)arch/common.o 429LIB_OBJS += $(OUTPUT)arch/common.o
432 430
431LIB_OBJS += $(OUTPUT)tests/parse-events.o
432LIB_OBJS += $(OUTPUT)tests/dso-data.o
433LIB_OBJS += $(OUTPUT)tests/attr.o
434
433BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 435BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
434BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 436BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
435# Benchmark modules 437# Benchmark modules
@@ -459,8 +461,8 @@ BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
459BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o 461BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
460BUILTIN_OBJS += $(OUTPUT)builtin-lock.o 462BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
461BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o 463BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
462BUILTIN_OBJS += $(OUTPUT)builtin-test.o
463BUILTIN_OBJS += $(OUTPUT)builtin-inject.o 464BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
465BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
464 466
465PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT) 467PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
466 468
@@ -490,6 +492,8 @@ ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y)
490 LIBC_SUPPORT := 1 492 LIBC_SUPPORT := 1
491 endif 493 endif
492 ifeq ($(LIBC_SUPPORT),1) 494 ifeq ($(LIBC_SUPPORT),1)
495 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
496
493 NO_LIBELF := 1 497 NO_LIBELF := 1
494 NO_DWARF := 1 498 NO_DWARF := 1
495 NO_DEMANGLE := 1 499 NO_DEMANGLE := 1
@@ -497,7 +501,14 @@ ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y)
497 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); 501 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
498 endif 502 endif
499else 503else
500 FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) 504 # for linking with debug library, run like:
505 # make DEBUG=1 LIBDW_DIR=/opt/libdw/
506 ifdef LIBDW_DIR
507 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
508 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
509 endif
510
511 FLAGS_DWARF=$(ALL_CFLAGS) $(LIBDW_CFLAGS) -ldw -lelf $(LIBDW_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
501 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y) 512 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y)
502 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); 513 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
503 NO_DWARF := 1 514 NO_DWARF := 1
@@ -552,7 +563,8 @@ ifndef NO_DWARF
552ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 563ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
553 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 564 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
554else 565else
555 BASIC_CFLAGS += -DDWARF_SUPPORT 566 BASIC_CFLAGS := -DDWARF_SUPPORT $(LIBDW_CFLAGS) $(BASIC_CFLAGS)
567 BASIC_LDFLAGS := $(LIBDW_LDFLAGS) $(BASIC_LDFLAGS)
556 EXTLIBS += -lelf -ldw 568 EXTLIBS += -lelf -ldw
557 LIB_OBJS += $(OUTPUT)util/probe-finder.o 569 LIB_OBJS += $(OUTPUT)util/probe-finder.o
558 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o 570 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
@@ -891,10 +903,14 @@ $(OUTPUT)%.s: %.S
891$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS 903$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
892 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ 904 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
893 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \ 905 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
894 '-DBINDIR="$(bindir_relative_SQ)"' \
895 '-DPREFIX="$(prefix_SQ)"' \ 906 '-DPREFIX="$(prefix_SQ)"' \
896 $< 907 $<
897 908
909$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
910 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
911 '-DBINDIR="$(bindir_SQ)"' \
912 $<
913
898$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS 914$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
899 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 915 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
900 916
@@ -1059,6 +1075,10 @@ install: all try-install-man
1059 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 1075 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
1060 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d' 1076 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'
1061 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' 1077 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
1078 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
1079 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
1080 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
1081 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
1062 1082
1063install-python_ext: 1083install-python_ext:
1064 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' 1084 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 2367b253f039..3e975cb6232e 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -93,16 +93,46 @@ static int lookup_triplets(const char *const *triplets, const char *name)
93 return -1; 93 return -1;
94} 94}
95 95
96/*
97 * Return architecture name in a normalized form.
98 * The conversion logic comes from the Makefile.
99 */
100static const char *normalize_arch(char *arch)
101{
102 if (!strcmp(arch, "x86_64"))
103 return "x86";
104 if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6')
105 return "x86";
106 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5))
107 return "sparc";
108 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110"))
109 return "arm";
110 if (!strncmp(arch, "s390", 4))
111 return "s390";
112 if (!strncmp(arch, "parisc", 6))
113 return "parisc";
114 if (!strncmp(arch, "powerpc", 7) || !strncmp(arch, "ppc", 3))
115 return "powerpc";
116 if (!strncmp(arch, "mips", 4))
117 return "mips";
118 if (!strncmp(arch, "sh", 2) && isdigit(arch[2]))
119 return "sh";
120
121 return arch;
122}
123
96static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, 124static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
97 const char *name, 125 const char *name,
98 const char **path) 126 const char **path)
99{ 127{
100 int idx; 128 int idx;
101 char *arch, *cross_env; 129 const char *arch, *cross_env;
102 struct utsname uts; 130 struct utsname uts;
103 const char *const *path_list; 131 const char *const *path_list;
104 char *buf = NULL; 132 char *buf = NULL;
105 133
134 arch = normalize_arch(env->arch);
135
106 if (uname(&uts) < 0) 136 if (uname(&uts) < 0)
107 goto out; 137 goto out;
108 138
@@ -110,7 +140,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
110 * We don't need to try to find objdump path for native system. 140 * We don't need to try to find objdump path for native system.
111 * Just use default binutils path (e.g.: "objdump"). 141 * Just use default binutils path (e.g.: "objdump").
112 */ 142 */
113 if (!strcmp(uts.machine, env->arch)) 143 if (!strcmp(normalize_arch(uts.machine), arch))
114 goto out; 144 goto out;
115 145
116 cross_env = getenv("CROSS_COMPILE"); 146 cross_env = getenv("CROSS_COMPILE");
@@ -127,8 +157,6 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
127 free(buf); 157 free(buf);
128 } 158 }
129 159
130 arch = env->arch;
131
132 if (!strcmp(arch, "arm")) 160 if (!strcmp(arch, "arm"))
133 path_list = arm_triplets; 161 path_list = arm_triplets;
134 else if (!strcmp(arch, "powerpc")) 162 else if (!strcmp(arch, "powerpc"))
@@ -139,9 +167,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
139 path_list = s390_triplets; 167 path_list = s390_triplets;
140 else if (!strcmp(arch, "sparc")) 168 else if (!strcmp(arch, "sparc"))
141 path_list = sparc_triplets; 169 path_list = sparc_triplets;
142 else if (!strcmp(arch, "x86") || !strcmp(arch, "i386") || 170 else if (!strcmp(arch, "x86"))
143 !strcmp(arch, "i486") || !strcmp(arch, "i586") ||
144 !strcmp(arch, "i686"))
145 path_list = x86_triplets; 171 path_list = x86_triplets;
146 else if (!strcmp(arch, "mips")) 172 else if (!strcmp(arch, "mips"))
147 path_list = mips_triplets; 173 path_list = mips_triplets;
@@ -173,6 +199,13 @@ out_error:
173 199
174int perf_session_env__lookup_objdump(struct perf_session_env *env) 200int perf_session_env__lookup_objdump(struct perf_session_env *env)
175{ 201{
202 /*
203 * For live mode, env->arch will be NULL and we can use
204 * the native objdump tool.
205 */
206 if (env->arch == NULL)
207 return 0;
208
176 return perf_session_env__lookup_binutils_path(env, "objdump", 209 return perf_session_env__lookup_binutils_path(env, "objdump",
177 &objdump_path); 210 &objdump_path);
178} 211}
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index cb234765ce3d..dc870cf31b79 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -139,7 +139,7 @@ find_next:
139 } 139 }
140 140
141 if (use_browser > 0) { 141 if (use_browser > 0) {
142 key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0); 142 key = hist_entry__tui_annotate(he, evidx, NULL);
143 switch (key) { 143 switch (key) {
144 case K_RIGHT: 144 case K_RIGHT:
145 next = rb_next(nd); 145 next = rb_next(nd);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 380683de1df3..93b852f8a5d5 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -154,7 +154,7 @@ static double get_period_percent(struct hist_entry *he, u64 period)
154 154
155double perf_diff__compute_delta(struct hist_entry *he) 155double perf_diff__compute_delta(struct hist_entry *he)
156{ 156{
157 struct hist_entry *pair = he->pair; 157 struct hist_entry *pair = hist_entry__next_pair(he);
158 double new_percent = get_period_percent(he, he->stat.period); 158 double new_percent = get_period_percent(he, he->stat.period);
159 double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0; 159 double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
160 160
@@ -165,7 +165,7 @@ double perf_diff__compute_delta(struct hist_entry *he)
165 165
166double perf_diff__compute_ratio(struct hist_entry *he) 166double perf_diff__compute_ratio(struct hist_entry *he)
167{ 167{
168 struct hist_entry *pair = he->pair; 168 struct hist_entry *pair = hist_entry__next_pair(he);
169 double new_period = he->stat.period; 169 double new_period = he->stat.period;
170 double old_period = pair ? pair->stat.period : 0; 170 double old_period = pair ? pair->stat.period : 0;
171 171
@@ -176,7 +176,7 @@ double perf_diff__compute_ratio(struct hist_entry *he)
176 176
177s64 perf_diff__compute_wdiff(struct hist_entry *he) 177s64 perf_diff__compute_wdiff(struct hist_entry *he)
178{ 178{
179 struct hist_entry *pair = he->pair; 179 struct hist_entry *pair = hist_entry__next_pair(he);
180 u64 new_period = he->stat.period; 180 u64 new_period = he->stat.period;
181 u64 old_period = pair ? pair->stat.period : 0; 181 u64 old_period = pair ? pair->stat.period : 0;
182 182
@@ -193,7 +193,7 @@ s64 perf_diff__compute_wdiff(struct hist_entry *he)
193 193
194static int formula_delta(struct hist_entry *he, char *buf, size_t size) 194static int formula_delta(struct hist_entry *he, char *buf, size_t size)
195{ 195{
196 struct hist_entry *pair = he->pair; 196 struct hist_entry *pair = hist_entry__next_pair(he);
197 197
198 if (!pair) 198 if (!pair)
199 return -1; 199 return -1;
@@ -207,7 +207,7 @@ static int formula_delta(struct hist_entry *he, char *buf, size_t size)
207 207
208static int formula_ratio(struct hist_entry *he, char *buf, size_t size) 208static int formula_ratio(struct hist_entry *he, char *buf, size_t size)
209{ 209{
210 struct hist_entry *pair = he->pair; 210 struct hist_entry *pair = hist_entry__next_pair(he);
211 double new_period = he->stat.period; 211 double new_period = he->stat.period;
212 double old_period = pair ? pair->stat.period : 0; 212 double old_period = pair ? pair->stat.period : 0;
213 213
@@ -219,7 +219,7 @@ static int formula_ratio(struct hist_entry *he, char *buf, size_t size)
219 219
220static int formula_wdiff(struct hist_entry *he, char *buf, size_t size) 220static int formula_wdiff(struct hist_entry *he, char *buf, size_t size)
221{ 221{
222 struct hist_entry *pair = he->pair; 222 struct hist_entry *pair = hist_entry__next_pair(he);
223 u64 new_period = he->stat.period; 223 u64 new_period = he->stat.period;
224 u64 old_period = pair ? pair->stat.period : 0; 224 u64 old_period = pair ? pair->stat.period : 0;
225 225
@@ -334,36 +334,6 @@ static void hists__name_resort(struct hists *self, bool sort)
334 self->entries = tmp; 334 self->entries = tmp;
335} 335}
336 336
337static struct hist_entry *hists__find_entry(struct hists *self,
338 struct hist_entry *he)
339{
340 struct rb_node *n = self->entries.rb_node;
341
342 while (n) {
343 struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node);
344 int64_t cmp = hist_entry__cmp(he, iter);
345
346 if (cmp < 0)
347 n = n->rb_left;
348 else if (cmp > 0)
349 n = n->rb_right;
350 else
351 return iter;
352 }
353
354 return NULL;
355}
356
357static void hists__match(struct hists *older, struct hists *newer)
358{
359 struct rb_node *nd;
360
361 for (nd = rb_first(&newer->entries); nd; nd = rb_next(nd)) {
362 struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node);
363 pos->pair = hists__find_entry(older, pos);
364 }
365}
366
367static struct perf_evsel *evsel_match(struct perf_evsel *evsel, 337static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
368 struct perf_evlist *evlist) 338 struct perf_evlist *evlist)
369{ 339{
@@ -402,7 +372,7 @@ static void hists__baseline_only(struct hists *hists)
402 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); 372 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
403 373
404 next = rb_next(&he->rb_node); 374 next = rb_next(&he->rb_node);
405 if (!he->pair) { 375 if (!hist_entry__next_pair(he)) {
406 rb_erase(&he->rb_node, &hists->entries); 376 rb_erase(&he->rb_node, &hists->entries);
407 hist_entry__free(he); 377 hist_entry__free(he);
408 } 378 }
@@ -517,10 +487,12 @@ static void hists__compute_resort(struct hists *hists)
517 487
518static void hists__process(struct hists *old, struct hists *new) 488static void hists__process(struct hists *old, struct hists *new)
519{ 489{
520 hists__match(old, new); 490 hists__match(new, old);
521 491
522 if (show_baseline_only) 492 if (show_baseline_only)
523 hists__baseline_only(new); 493 hists__baseline_only(new);
494 else
495 hists__link(new, old);
524 496
525 if (sort_compute) { 497 if (sort_compute) {
526 hists__precompute(new); 498 hists__precompute(new);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f07eae73e692..fc251005dd3d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -428,10 +428,11 @@ static int __cmd_report(struct perf_report *rep)
428 if (use_browser > 0) { 428 if (use_browser > 0) {
429 if (use_browser == 1) { 429 if (use_browser == 1) {
430 perf_evlist__tui_browse_hists(session->evlist, help, 430 perf_evlist__tui_browse_hists(session->evlist, help,
431 NULL, NULL, 0); 431 NULL,
432 &session->header.env);
432 } else if (use_browser == 2) { 433 } else if (use_browser == 2) {
433 perf_evlist__gtk_browse_hists(session->evlist, help, 434 perf_evlist__gtk_browse_hists(session->evlist, help,
434 NULL, NULL, 0); 435 NULL);
435 } 436 }
436 } else 437 } else
437 perf_evlist__tty_browse_hists(session->evlist, rep, help); 438 perf_evlist__tty_browse_hists(session->evlist, rep, help);
@@ -672,12 +673,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
672 has_br_stack = perf_header__has_feat(&session->header, 673 has_br_stack = perf_header__has_feat(&session->header,
673 HEADER_BRANCH_STACK); 674 HEADER_BRANCH_STACK);
674 675
675 if (!objdump_path) {
676 ret = perf_session_env__lookup_objdump(&session->header.env);
677 if (ret)
678 goto error;
679 }
680
681 if (sort__branch_mode == -1 && has_br_stack) 676 if (sort__branch_mode == -1 && has_br_stack)
682 sort__branch_mode = 1; 677 sort__branch_mode = 1;
683 678
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index f2ecd498c72d..c9ff3950cd4b 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -582,6 +582,11 @@ static void *display_thread_tui(void *arg)
582 struct perf_evsel *pos; 582 struct perf_evsel *pos;
583 struct perf_top *top = arg; 583 struct perf_top *top = arg;
584 const char *help = "For a higher level overview, try: perf top --sort comm,dso"; 584 const char *help = "For a higher level overview, try: perf top --sort comm,dso";
585 struct hist_browser_timer hbt = {
586 .timer = perf_top__sort_new_samples,
587 .arg = top,
588 .refresh = top->delay_secs,
589 };
585 590
586 perf_top__sort_new_samples(top); 591 perf_top__sort_new_samples(top);
587 592
@@ -593,9 +598,8 @@ static void *display_thread_tui(void *arg)
593 list_for_each_entry(pos, &top->evlist->entries, node) 598 list_for_each_entry(pos, &top->evlist->entries, node)
594 pos->hists.uid_filter_str = top->target.uid_str; 599 pos->hists.uid_filter_str = top->target.uid_str;
595 600
596 perf_evlist__tui_browse_hists(top->evlist, help, 601 perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
597 perf_top__sort_new_samples, 602 &top->session->header.env);
598 top, top->delay_secs);
599 603
600 exit_browser(0); 604 exit_browser(0);
601 exit(0); 605 exit(0);
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index e9683738d89f..a0ae2902f9c9 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -484,6 +484,8 @@ int main(int argc, const char **argv)
484 } 484 }
485 cmd = argv[0]; 485 cmd = argv[0];
486 486
487 test_attr__init();
488
487 /* 489 /*
488 * We use PATH to find perf commands, but we prepend some higher 490 * We use PATH to find perf commands, but we prepend some higher
489 * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH 491 * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 469fbf2daea4..054182e41dca 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -174,13 +174,26 @@ static inline unsigned long long rdclock(void)
174 (void) (&_min1 == &_min2); \ 174 (void) (&_min1 == &_min2); \
175 _min1 < _min2 ? _min1 : _min2; }) 175 _min1 < _min2 ? _min1 : _min2; })
176 176
177extern bool test_attr__enabled;
178void test_attr__init(void);
179void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
180 int fd, int group_fd, unsigned long flags);
181int test_attr__run(void);
182
177static inline int 183static inline int
178sys_perf_event_open(struct perf_event_attr *attr, 184sys_perf_event_open(struct perf_event_attr *attr,
179 pid_t pid, int cpu, int group_fd, 185 pid_t pid, int cpu, int group_fd,
180 unsigned long flags) 186 unsigned long flags)
181{ 187{
182 return syscall(__NR_perf_event_open, attr, pid, cpu, 188 int fd;
183 group_fd, flags); 189
190 fd = syscall(__NR_perf_event_open, attr, pid, cpu,
191 group_fd, flags);
192
193 if (unlikely(test_attr__enabled))
194 test_attr__open(attr, pid, cpu, fd, group_fd, flags);
195
196 return fd;
184} 197}
185 198
186#define MAX_COUNTERS 256 199#define MAX_COUNTERS 256
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c
new file mode 100644
index 000000000000..6e2feee8db2a
--- /dev/null
+++ b/tools/perf/tests/attr.c
@@ -0,0 +1,174 @@
1
2/*
3 * The struct perf_event_attr test support.
4 *
5 * This test is embedded inside into perf directly and is governed
6 * by the PERF_TEST_ATTR environment variable and hook inside
7 * sys_perf_event_open function.
8 *
9 * The general idea is to store 'struct perf_event_attr' details for
10 * each event created within single perf command. Each event details
11 * are stored into separate text file. Once perf command is finished
12 * these files can be checked for values we expect for command.
13 *
14 * Besides 'struct perf_event_attr' values we also store 'fd' and
15 * 'group_fd' values to allow checking for groups created.
16 *
17 * This all is triggered by setting PERF_TEST_ATTR environment variable.
18 * It must contain name of existing directory with access and write
19 * permissions. All the event text files are stored there.
20 */
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <inttypes.h>
25#include <linux/types.h>
26#include <linux/kernel.h>
27#include "../perf.h"
28#include "util.h"
29#include "exec_cmd.h"
30
31#define ENV "PERF_TEST_ATTR"
32
33extern int verbose;
34
35bool test_attr__enabled;
36
37static char *dir;
38
39void test_attr__init(void)
40{
41 dir = getenv(ENV);
42 test_attr__enabled = (dir != NULL);
43}
44
45#define BUFSIZE 1024
46
47#define __WRITE_ASS(str, fmt, data) \
48do { \
49 char buf[BUFSIZE]; \
50 size_t size; \
51 \
52 size = snprintf(buf, BUFSIZE, #str "=%"fmt "\n", data); \
53 if (1 != fwrite(buf, size, 1, file)) { \
54 perror("test attr - failed to write event file"); \
55 fclose(file); \
56 return -1; \
57 } \
58 \
59} while (0)
60
61#define WRITE_ASS(field, fmt) __WRITE_ASS(field, fmt, attr->field)
62
63static int store_event(struct perf_event_attr *attr, pid_t pid, int cpu,
64 int fd, int group_fd, unsigned long flags)
65{
66 FILE *file;
67 char path[PATH_MAX];
68
69 snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir,
70 attr->type, attr->config, fd);
71
72 file = fopen(path, "w+");
73 if (!file) {
74 perror("test attr - failed to open event file");
75 return -1;
76 }
77
78 if (fprintf(file, "[event-%d-%llu-%d]\n",
79 attr->type, attr->config, fd) < 0) {
80 perror("test attr - failed to write event file");
81 fclose(file);
82 return -1;
83 }
84
85 /* syscall arguments */
86 __WRITE_ASS(fd, "d", fd);
87 __WRITE_ASS(group_fd, "d", group_fd);
88 __WRITE_ASS(cpu, "d", cpu);
89 __WRITE_ASS(pid, "d", pid);
90 __WRITE_ASS(flags, "lu", flags);
91
92 /* struct perf_event_attr */
93 WRITE_ASS(type, PRIu32);
94 WRITE_ASS(size, PRIu32);
95 WRITE_ASS(config, "llu");
96 WRITE_ASS(sample_period, "llu");
97 WRITE_ASS(sample_type, "llu");
98 WRITE_ASS(read_format, "llu");
99 WRITE_ASS(disabled, "d");
100 WRITE_ASS(inherit, "d");
101 WRITE_ASS(pinned, "d");
102 WRITE_ASS(exclusive, "d");
103 WRITE_ASS(exclude_user, "d");
104 WRITE_ASS(exclude_kernel, "d");
105 WRITE_ASS(exclude_hv, "d");
106 WRITE_ASS(exclude_idle, "d");
107 WRITE_ASS(mmap, "d");
108 WRITE_ASS(comm, "d");
109 WRITE_ASS(freq, "d");
110 WRITE_ASS(inherit_stat, "d");
111 WRITE_ASS(enable_on_exec, "d");
112 WRITE_ASS(task, "d");
113 WRITE_ASS(watermark, "d");
114 WRITE_ASS(precise_ip, "d");
115 WRITE_ASS(mmap_data, "d");
116 WRITE_ASS(sample_id_all, "d");
117 WRITE_ASS(exclude_host, "d");
118 WRITE_ASS(exclude_guest, "d");
119 WRITE_ASS(exclude_callchain_kernel, "d");
120 WRITE_ASS(exclude_callchain_user, "d");
121 WRITE_ASS(wakeup_events, PRIu32);
122 WRITE_ASS(bp_type, PRIu32);
123 WRITE_ASS(config1, "llu");
124 WRITE_ASS(config2, "llu");
125 WRITE_ASS(branch_sample_type, "llu");
126 WRITE_ASS(sample_regs_user, "llu");
127 WRITE_ASS(sample_stack_user, PRIu32);
128
129 fclose(file);
130 return 0;
131}
132
133void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
134 int fd, int group_fd, unsigned long flags)
135{
136 int errno_saved = errno;
137
138 if (store_event(attr, pid, cpu, fd, group_fd, flags))
139 die("test attr FAILED");
140
141 errno = errno_saved;
142}
143
144static int run_dir(const char *d, const char *perf)
145{
146 char cmd[3*PATH_MAX];
147
148 snprintf(cmd, 3*PATH_MAX, "python %s/attr.py -d %s/attr/ -p %s %s",
149 d, d, perf, verbose ? "-v" : "");
150
151 return system(cmd);
152}
153
154int test_attr__run(void)
155{
156 struct stat st;
157 char path_perf[PATH_MAX];
158 char path_dir[PATH_MAX];
159
160 /* First try developement tree tests. */
161 if (!lstat("./tests", &st))
162 return run_dir("./tests", "./perf");
163
164 /* Then installed path. */
165 snprintf(path_dir, PATH_MAX, "%s/tests", perf_exec_path());
166 snprintf(path_perf, PATH_MAX, "%s/perf", BINDIR);
167
168 if (!lstat(path_dir, &st) &&
169 !lstat(path_perf, &st))
170 return run_dir(path_dir, path_perf);
171
172 fprintf(stderr, " (ommitted)");
173 return 0;
174}
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py
new file mode 100644
index 000000000000..e702b82dcb86
--- /dev/null
+++ b/tools/perf/tests/attr.py
@@ -0,0 +1,322 @@
1#! /usr/bin/python
2
3import os
4import sys
5import glob
6import optparse
7import tempfile
8import logging
9import shutil
10import ConfigParser
11
12class Fail(Exception):
13 def __init__(self, test, msg):
14 self.msg = msg
15 self.test = test
16 def getMsg(self):
17 return '\'%s\' - %s' % (self.test.path, self.msg)
18
19class Unsup(Exception):
20 def __init__(self, test):
21 self.test = test
22 def getMsg(self):
23 return '\'%s\'' % self.test.path
24
25class Event(dict):
26 terms = [
27 'flags',
28 'type',
29 'size',
30 'config',
31 'sample_period',
32 'sample_type',
33 'read_format',
34 'disabled',
35 'inherit',
36 'pinned',
37 'exclusive',
38 'exclude_user',
39 'exclude_kernel',
40 'exclude_hv',
41 'exclude_idle',
42 'mmap',
43 'comm',
44 'freq',
45 'inherit_stat',
46 'enable_on_exec',
47 'task',
48 'watermark',
49 'precise_ip',
50 'mmap_data',
51 'sample_id_all',
52 'exclude_host',
53 'exclude_guest',
54 'exclude_callchain_kernel',
55 'exclude_callchain_user',
56 'wakeup_events',
57 'bp_type',
58 'config1',
59 'config2',
60 'branch_sample_type',
61 'sample_regs_user',
62 'sample_stack_user',
63 ]
64
65 def add(self, data):
66 for key, val in data:
67 log.debug(" %s = %s" % (key, val))
68 self[key] = val
69
70 def __init__(self, name, data, base):
71 log.info(" Event %s" % name);
72 self.name = name;
73 self.group = ''
74 self.add(base)
75 self.add(data)
76
77 def compare_data(self, a, b):
78 # Allow multiple values in assignment separated by '|'
79 a_list = a.split('|')
80 b_list = b.split('|')
81
82 for a_item in a_list:
83 for b_item in b_list:
84 if (a_item == b_item):
85 return True
86 elif (a_item == '*') or (b_item == '*'):
87 return True
88
89 return False
90
91 def equal(self, other):
92 for t in Event.terms:
93 log.debug(" [%s] %s %s" % (t, self[t], other[t]));
94 if not self.has_key(t) or not other.has_key(t):
95 return False
96 if not self.compare_data(self[t], other[t]):
97 return False
98 return True
99
100# Test file description needs to have following sections:
101# [config]
102# - just single instance in file
103# - needs to specify:
104# 'command' - perf command name
105# 'args' - special command arguments
106# 'ret' - expected command return value (0 by default)
107#
108# [eventX:base]
109# - one or multiple instances in file
110# - expected values assignments
111class Test(object):
112 def __init__(self, path, options):
113 parser = ConfigParser.SafeConfigParser()
114 parser.read(path)
115
116 log.warning("running '%s'" % path)
117
118 self.path = path
119 self.test_dir = options.test_dir
120 self.perf = options.perf
121 self.command = parser.get('config', 'command')
122 self.args = parser.get('config', 'args')
123
124 try:
125 self.ret = parser.get('config', 'ret')
126 except:
127 self.ret = 0
128
129 self.expect = {}
130 self.result = {}
131 log.info(" loading expected events");
132 self.load_events(path, self.expect)
133
134 def is_event(self, name):
135 if name.find("event") == -1:
136 return False
137 else:
138 return True
139
140 def load_events(self, path, events):
141 parser_event = ConfigParser.SafeConfigParser()
142 parser_event.read(path)
143
144 # The event record section header contains 'event' word,
145 # optionaly followed by ':' allowing to load 'parent
146 # event' first as a base
147 for section in filter(self.is_event, parser_event.sections()):
148
149 parser_items = parser_event.items(section);
150 base_items = {}
151
152 # Read parent event if there's any
153 if (':' in section):
154 base = section[section.index(':') + 1:]
155 parser_base = ConfigParser.SafeConfigParser()
156 parser_base.read(self.test_dir + '/' + base)
157 base_items = parser_base.items('event')
158
159 e = Event(section, parser_items, base_items)
160 events[section] = e
161
162 def run_cmd(self, tempdir):
163 cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir,
164 self.perf, self.command, tempdir, self.args)
165 ret = os.WEXITSTATUS(os.system(cmd))
166
167 log.info(" running '%s' ret %d " % (cmd, ret))
168
169 if ret != int(self.ret):
170 raise Unsup(self)
171
172 def compare(self, expect, result):
173 match = {}
174
175 log.info(" compare");
176
177 # For each expected event find all matching
178 # events in result. Fail if there's not any.
179 for exp_name, exp_event in expect.items():
180 exp_list = []
181 log.debug(" matching [%s]" % exp_name)
182 for res_name, res_event in result.items():
183 log.debug(" to [%s]" % res_name)
184 if (exp_event.equal(res_event)):
185 exp_list.append(res_name)
186 log.debug(" ->OK")
187 else:
188 log.debug(" ->FAIL");
189
190 log.info(" match: [%s] matches %s" % (exp_name, str(exp_list)))
191
192 # we did not any matching event - fail
193 if (not exp_list):
194 raise Fail(self, 'match failure');
195
196 match[exp_name] = exp_list
197
198 # For each defined group in the expected events
199 # check we match the same group in the result.
200 for exp_name, exp_event in expect.items():
201 group = exp_event.group
202
203 if (group == ''):
204 continue
205
206 for res_name in match[exp_name]:
207 res_group = result[res_name].group
208 if res_group not in match[group]:
209 raise Fail(self, 'group failure')
210
211 log.info(" group: [%s] matches group leader %s" %
212 (exp_name, str(match[group])))
213
214 log.info(" matched")
215
216 def resolve_groups(self, events):
217 for name, event in events.items():
218 group_fd = event['group_fd'];
219 if group_fd == '-1':
220 continue;
221
222 for iname, ievent in events.items():
223 if (ievent['fd'] == group_fd):
224 event.group = iname
225 log.debug('[%s] has group leader [%s]' % (name, iname))
226 break;
227
228 def run(self):
229 tempdir = tempfile.mkdtemp();
230
231 try:
232 # run the test script
233 self.run_cmd(tempdir);
234
235 # load events expectation for the test
236 log.info(" loading result events");
237 for f in glob.glob(tempdir + '/event*'):
238 self.load_events(f, self.result);
239
240 # resolve group_fd to event names
241 self.resolve_groups(self.expect);
242 self.resolve_groups(self.result);
243
244 # do the expectation - results matching - both ways
245 self.compare(self.expect, self.result)
246 self.compare(self.result, self.expect)
247
248 finally:
249 # cleanup
250 shutil.rmtree(tempdir)
251
252
253def run_tests(options):
254 for f in glob.glob(options.test_dir + '/' + options.test):
255 try:
256 Test(f, options).run()
257 except Unsup, obj:
258 log.warning("unsupp %s" % obj.getMsg())
259
260def setup_log(verbose):
261 global log
262 level = logging.CRITICAL
263
264 if verbose == 1:
265 level = logging.WARNING
266 if verbose == 2:
267 level = logging.INFO
268 if verbose >= 3:
269 level = logging.DEBUG
270
271 log = logging.getLogger('test')
272 log.setLevel(level)
273 ch = logging.StreamHandler()
274 ch.setLevel(level)
275 formatter = logging.Formatter('%(message)s')
276 ch.setFormatter(formatter)
277 log.addHandler(ch)
278
279USAGE = '''%s [OPTIONS]
280 -d dir # tests dir
281 -p path # perf binary
282 -t test # single test
283 -v # verbose level
284''' % sys.argv[0]
285
286def main():
287 parser = optparse.OptionParser(usage=USAGE)
288
289 parser.add_option("-t", "--test",
290 action="store", type="string", dest="test")
291 parser.add_option("-d", "--test-dir",
292 action="store", type="string", dest="test_dir")
293 parser.add_option("-p", "--perf",
294 action="store", type="string", dest="perf")
295 parser.add_option("-v", "--verbose",
296 action="count", dest="verbose")
297
298 options, args = parser.parse_args()
299 if args:
300 parser.error('FAILED wrong arguments %s' % ' '.join(args))
301 return -1
302
303 setup_log(options.verbose)
304
305 if not options.test_dir:
306 print 'FAILED no -d option specified'
307 sys.exit(-1)
308
309 if not options.test:
310 options.test = 'test*'
311
312 try:
313 run_tests(options)
314
315 except Fail, obj:
316 print "FAILED %s" % obj.getMsg();
317 sys.exit(-1)
318
319 sys.exit(0)
320
321if __name__ == '__main__':
322 main()
diff --git a/tools/perf/tests/attr/README b/tools/perf/tests/attr/README
new file mode 100644
index 000000000000..d102957cd59a
--- /dev/null
+++ b/tools/perf/tests/attr/README
@@ -0,0 +1,64 @@
1The struct perf_event_attr test (attr tests) support
2====================================================
3This testing support is embedded into perf directly and is governed
4by the PERF_TEST_ATTR environment variable and hook inside the
5sys_perf_event_open function.
6
7The general idea is to store 'struct perf_event_attr' details for
8each event created within single perf command. Each event details
9are stored into separate text file. Once perf command is finished
10these files are checked for values we expect for command.
11
12The attr tests consist of following parts:
13
14tests/attr.c
15------------
16This is the sys_perf_event_open hook implementation. The hook
17is triggered when the PERF_TEST_ATTR environment variable is
18defined. It must contain name of existing directory with access
19and write permissions.
20
21For each sys_perf_event_open call event details are stored in
22separate file. Besides 'struct perf_event_attr' values we also
23store 'fd' and 'group_fd' values to allow checking for groups.
24
25tests/attr.py
26-------------
27This is the python script that does all the hard work. It reads
28the test definition, executes it and checks results.
29
30tests/attr/
31-----------
32Directory containing all attr test definitions.
33Following tests are defined (with perf commands):
34
35 perf record kill (test-record-basic)
36 perf record -b kill (test-record-branch-any)
37 perf record -j any kill (test-record-branch-filter-any)
38 perf record -j any_call kill (test-record-branch-filter-any_call)
39 perf record -j any_ret kill (test-record-branch-filter-any_ret)
40 perf record -j hv kill (test-record-branch-filter-hv)
41 perf record -j ind_call kill (test-record-branch-filter-ind_call)
42 perf record -j k kill (test-record-branch-filter-k)
43 perf record -j u kill (test-record-branch-filter-u)
44 perf record -c 123 kill (test-record-count)
45 perf record -d kill (test-record-data)
46 perf record -F 100 kill (test-record-freq)
47 perf record -g -- kill (test-record-graph-default)
48 perf record -g dwarf -- kill (test-record-graph-dwarf)
49 perf record -g fp kill (test-record-graph-fp)
50 perf record --group -e cycles,instructions kill (test-record-group)
51 perf record -e '{cycles,instructions}' kill (test-record-group1)
52 perf record -D kill (test-record-no-delay)
53 perf record -i kill (test-record-no-inherit)
54 perf record -n kill (test-record-no-samples)
55 perf record -c 100 -P kill (test-record-period)
56 perf record -R kill (test-record-raw)
57 perf stat -e cycles kill (test-stat-basic)
58 perf stat kill (test-stat-default)
59 perf stat -d kill (test-stat-detailed-1)
60 perf stat -dd kill (test-stat-detailed-2)
61 perf stat -ddd kill (test-stat-detailed-3)
62 perf stat --group -e cycles,instructions kill (test-stat-group)
63 perf stat -e '{cycles,instructions}' kill (test-stat-group1)
64 perf stat -i -e cycles kill (test-stat-no-inherit)
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
new file mode 100644
index 000000000000..f1485d8e6a0b
--- /dev/null
+++ b/tools/perf/tests/attr/base-record
@@ -0,0 +1,39 @@
1[event]
2fd=1
3group_fd=-1
4flags=0
5type=0|1
6size=96
7config=0
8sample_period=4000
9sample_type=263
10read_format=7
11disabled=1
12inherit=1
13pinned=0
14exclusive=0
15exclude_user=0
16exclude_kernel=0
17exclude_hv=0
18exclude_idle=0
19mmap=1
20comm=1
21freq=1
22inherit_stat=0
23enable_on_exec=1
24task=0
25watermark=0
26precise_ip=0
27mmap_data=0
28sample_id_all=1
29exclude_host=0
30exclude_guest=1
31exclude_callchain_kernel=0
32exclude_callchain_user=0
33wakeup_events=0
34bp_type=0
35config1=0
36config2=0
37branch_sample_type=0
38sample_regs_user=0
39sample_stack_user=0
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat
new file mode 100644
index 000000000000..4bd79a82784f
--- /dev/null
+++ b/tools/perf/tests/attr/base-stat
@@ -0,0 +1,39 @@
1[event]
2fd=1
3group_fd=-1
4flags=0
5type=0
6size=96
7config=0
8sample_period=0
9sample_type=0
10read_format=3
11disabled=1
12inherit=1
13pinned=0
14exclusive=0
15exclude_user=0
16exclude_kernel=0
17exclude_hv=0
18exclude_idle=0
19mmap=0
20comm=0
21freq=0
22inherit_stat=0
23enable_on_exec=1
24task=0
25watermark=0
26precise_ip=0
27mmap_data=0
28sample_id_all=0
29exclude_host=0
30exclude_guest=1
31exclude_callchain_kernel=0
32exclude_callchain_user=0
33wakeup_events=0
34bp_type=0
35config1=0
36config2=0
37branch_sample_type=0
38sample_regs_user=0
39sample_stack_user=0
diff --git a/tools/perf/tests/attr/test-record-basic b/tools/perf/tests/attr/test-record-basic
new file mode 100644
index 000000000000..55c0428370ca
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-basic
@@ -0,0 +1,5 @@
1[config]
2command = record
3args = kill >/dev/null 2>&1
4
5[event:base-record]
diff --git a/tools/perf/tests/attr/test-record-branch-any b/tools/perf/tests/attr/test-record-branch-any
new file mode 100644
index 000000000000..1421960ed4e9
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-branch-any
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -b kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=2311
8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any b/tools/perf/tests/attr/test-record-branch-filter-any
new file mode 100644
index 000000000000..915c4df0e0c2
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-branch-filter-any
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -j any kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=2311
8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_call b/tools/perf/tests/attr/test-record-branch-filter-any_call
new file mode 100644
index 000000000000..8708dbd4f373
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-branch-filter-any_call
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -j any_call kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=2311
8branch_sample_type=16
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_ret b/tools/perf/tests/attr/test-record-branch-filter-any_ret
new file mode 100644
index 000000000000..0d3607a6dcbe
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-branch-filter-any_ret
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -j any_ret kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=2311
8branch_sample_type=32
diff --git a/tools/perf/tests/attr/test-record-branch-filter-hv b/tools/perf/tests/attr/test-record-branch-filter-hv
new file mode 100644
index 000000000000..f25526740cec
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-branch-filter-hv
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -j hv kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=2311
8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-ind_call b/tools/perf/tests/attr/test-record-branch-filter-ind_call
new file mode 100644
index 000000000000..e862dd179128
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-branch-filter-ind_call
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -j ind_call kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=2311
8branch_sample_type=64
diff --git a/tools/perf/tests/attr/test-record-branch-filter-k b/tools/perf/tests/attr/test-record-branch-filter-k
new file mode 100644
index 000000000000..182971e898f5
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-branch-filter-k
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -j k kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=2311
8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-branch-filter-u b/tools/perf/tests/attr/test-record-branch-filter-u
new file mode 100644
index 000000000000..83449ef9e687
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-branch-filter-u
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -j u kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=2311
8branch_sample_type=8
diff --git a/tools/perf/tests/attr/test-record-count b/tools/perf/tests/attr/test-record-count
new file mode 100644
index 000000000000..2f841de56f6b
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-count
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -c 123 kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=123
7sample_type=7
8freq=0
diff --git a/tools/perf/tests/attr/test-record-data b/tools/perf/tests/attr/test-record-data
new file mode 100644
index 000000000000..6627c3e7534a
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-data
@@ -0,0 +1,8 @@
1[config]
2command = record
3args = -d kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=271
8mmap_data=1
diff --git a/tools/perf/tests/attr/test-record-freq b/tools/perf/tests/attr/test-record-freq
new file mode 100644
index 000000000000..600d0f8f2583
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-freq
@@ -0,0 +1,6 @@
1[config]
2command = record
3args = -F 100 kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=100
diff --git a/tools/perf/tests/attr/test-record-graph-default b/tools/perf/tests/attr/test-record-graph-default
new file mode 100644
index 000000000000..833d1849d767
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-graph-default
@@ -0,0 +1,6 @@
1[config]
2command = record
3args = -g -- kill >/dev/null 2>&1
4
5[event:base-record]
6sample_type=295
diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf
new file mode 100644
index 000000000000..e93e082f5208
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-graph-dwarf
@@ -0,0 +1,10 @@
1[config]
2command = record
3args = -g dwarf -- kill >/dev/null 2>&1
4
5[event:base-record]
6sample_type=12583
7exclude_callchain_user=1
8sample_stack_user=8192
9# TODO different for each arch, no support for that now
10sample_regs_user=*
diff --git a/tools/perf/tests/attr/test-record-graph-fp b/tools/perf/tests/attr/test-record-graph-fp
new file mode 100644
index 000000000000..7cef3743f03f
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-graph-fp
@@ -0,0 +1,6 @@
1[config]
2command = record
3args = -g fp kill >/dev/null 2>&1
4
5[event:base-record]
6sample_type=295
diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group
new file mode 100644
index 000000000000..b945f770dc9e
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-group
@@ -0,0 +1,17 @@
1[config]
2command = record
3args = --group -e cycles,instructions kill >/dev/null 2>&1
4
5[event-1:base-record]
6fd=1
7group_fd=-1
8sample_type=327
9
10[event-2:base-record]
11fd=2
12group_fd=1
13config=1
14sample_type=327
15mmap=0
16comm=0
17enable_on_exec=0
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1
new file mode 100644
index 000000000000..39bf8609538c
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-group1
@@ -0,0 +1,20 @@
1[config]
2command = record
3args = -e '{cycles,instructions}' kill >/tmp/krava 2>&1
4
5[event-1:base-record]
6fd=1
7group_fd=-1
8sample_type=327
9
10[event-2:base-record]
11fd=2
12group_fd=1
13type=0
14config=1
15sample_type=327
16mmap=0
17comm=0
18# TODO this is disabled for --group option, enabled otherwise
19# check why..
20enable_on_exec=1
diff --git a/tools/perf/tests/attr/test-record-no-delay b/tools/perf/tests/attr/test-record-no-delay
new file mode 100644
index 000000000000..f253b78cdbf2
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-no-delay
@@ -0,0 +1,9 @@
1[config]
2command = record
3args = -D kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=263
8watermark=0
9wakeup_events=1
diff --git a/tools/perf/tests/attr/test-record-no-inherit b/tools/perf/tests/attr/test-record-no-inherit
new file mode 100644
index 000000000000..9079a25cd643
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-no-inherit
@@ -0,0 +1,7 @@
1[config]
2command = record
3args = -i kill >/dev/null 2>&1
4
5[event:base-record]
6sample_type=259
7inherit=0
diff --git a/tools/perf/tests/attr/test-record-no-samples b/tools/perf/tests/attr/test-record-no-samples
new file mode 100644
index 000000000000..d0141b2418b5
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-no-samples
@@ -0,0 +1,6 @@
1[config]
2command = record
3args = -n kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=0
diff --git a/tools/perf/tests/attr/test-record-period b/tools/perf/tests/attr/test-record-period
new file mode 100644
index 000000000000..8abc5314fc52
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-period
@@ -0,0 +1,7 @@
1[config]
2command = record
3args = -c 100 -P kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=100
7freq=0
diff --git a/tools/perf/tests/attr/test-record-raw b/tools/perf/tests/attr/test-record-raw
new file mode 100644
index 000000000000..4a8ef25b5f49
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-raw
@@ -0,0 +1,7 @@
1[config]
2command = record
3args = -R kill >/dev/null 2>&1
4
5[event:base-record]
6sample_period=4000
7sample_type=1415
diff --git a/tools/perf/tests/attr/test-stat-basic b/tools/perf/tests/attr/test-stat-basic
new file mode 100644
index 000000000000..74e17881f2ba
--- /dev/null
+++ b/tools/perf/tests/attr/test-stat-basic
@@ -0,0 +1,6 @@
1[config]
2command = stat
3args = -e cycles kill >/dev/null 2>&1
4ret = 1
5
6[event:base-stat]
diff --git a/tools/perf/tests/attr/test-stat-default b/tools/perf/tests/attr/test-stat-default
new file mode 100644
index 000000000000..19270f54c96e
--- /dev/null
+++ b/tools/perf/tests/attr/test-stat-default
@@ -0,0 +1,64 @@
1[config]
2command = stat
3args = kill >/dev/null 2>&1
4ret = 1
5
6# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK
7[event1:base-stat]
8fd=1
9type=1
10config=1
11
12# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES
13[event2:base-stat]
14fd=2
15type=1
16config=3
17
18# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS
19[event3:base-stat]
20fd=3
21type=1
22config=4
23
24# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS
25[event4:base-stat]
26fd=4
27type=1
28config=2
29
30# PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES
31[event5:base-stat]
32fd=5
33type=0
34config=0
35
36# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
37[event6:base-stat]
38fd=6
39type=0
40config=7
41
42# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
43[event7:base-stat]
44fd=7
45type=0
46config=8
47
48# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
49[event8:base-stat]
50fd=8
51type=0
52config=1
53
54# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
55[event9:base-stat]
56fd=9
57type=0
58config=4
59
60# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
61[event10:base-stat]
62fd=10
63type=0
64config=5
diff --git a/tools/perf/tests/attr/test-stat-detailed-1 b/tools/perf/tests/attr/test-stat-detailed-1
new file mode 100644
index 000000000000..51426b87153b
--- /dev/null
+++ b/tools/perf/tests/attr/test-stat-detailed-1
@@ -0,0 +1,101 @@
1[config]
2command = stat
3args = -d kill >/dev/null 2>&1
4ret = 1
5
6
7# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK
8[event1:base-stat]
9fd=1
10type=1
11config=1
12
13# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES
14[event2:base-stat]
15fd=2
16type=1
17config=3
18
19# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS
20[event3:base-stat]
21fd=3
22type=1
23config=4
24
25# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS
26[event4:base-stat]
27fd=4
28type=1
29config=2
30
31# PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES
32[event5:base-stat]
33fd=5
34type=0
35config=0
36
37# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
38[event6:base-stat]
39fd=6
40type=0
41config=7
42
43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
44[event7:base-stat]
45fd=7
46type=0
47config=8
48
49# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
50[event8:base-stat]
51fd=8
52type=0
53config=1
54
55# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
56[event9:base-stat]
57fd=9
58type=0
59config=4
60
61# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
62[event10:base-stat]
63fd=10
64type=0
65config=5
66
67# PERF_TYPE_HW_CACHE /
68# PERF_COUNT_HW_CACHE_L1D << 0 |
69# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
70# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
71[event11:base-stat]
72fd=11
73type=3
74config=0
75
76# PERF_TYPE_HW_CACHE /
77# PERF_COUNT_HW_CACHE_L1D << 0 |
78# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
79# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
80[event12:base-stat]
81fd=12
82type=3
83config=65536
84
85# PERF_TYPE_HW_CACHE /
86# PERF_COUNT_HW_CACHE_LL << 0 |
87# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
88# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
89[event13:base-stat]
90fd=13
91type=3
92config=2
93
94# PERF_TYPE_HW_CACHE,
95# PERF_COUNT_HW_CACHE_LL << 0 |
96# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
97# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
98[event14:base-stat]
99fd=14
100type=3
101config=65538
diff --git a/tools/perf/tests/attr/test-stat-detailed-2 b/tools/perf/tests/attr/test-stat-detailed-2
new file mode 100644
index 000000000000..8de5acc31c27
--- /dev/null
+++ b/tools/perf/tests/attr/test-stat-detailed-2
@@ -0,0 +1,155 @@
1[config]
2command = stat
3args = -dd kill >/dev/null 2>&1
4ret = 1
5
6
7# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK
8[event1:base-stat]
9fd=1
10type=1
11config=1
12
13# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES
14[event2:base-stat]
15fd=2
16type=1
17config=3
18
19# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS
20[event3:base-stat]
21fd=3
22type=1
23config=4
24
25# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS
26[event4:base-stat]
27fd=4
28type=1
29config=2
30
31# PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES
32[event5:base-stat]
33fd=5
34type=0
35config=0
36
37# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
38[event6:base-stat]
39fd=6
40type=0
41config=7
42
43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
44[event7:base-stat]
45fd=7
46type=0
47config=8
48
49# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
50[event8:base-stat]
51fd=8
52type=0
53config=1
54
55# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
56[event9:base-stat]
57fd=9
58type=0
59config=4
60
61# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
62[event10:base-stat]
63fd=10
64type=0
65config=5
66
67# PERF_TYPE_HW_CACHE /
68# PERF_COUNT_HW_CACHE_L1D << 0 |
69# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
70# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
71[event11:base-stat]
72fd=11
73type=3
74config=0
75
76# PERF_TYPE_HW_CACHE /
77# PERF_COUNT_HW_CACHE_L1D << 0 |
78# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
79# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
80[event12:base-stat]
81fd=12
82type=3
83config=65536
84
85# PERF_TYPE_HW_CACHE /
86# PERF_COUNT_HW_CACHE_LL << 0 |
87# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
88# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
89[event13:base-stat]
90fd=13
91type=3
92config=2
93
94# PERF_TYPE_HW_CACHE,
95# PERF_COUNT_HW_CACHE_LL << 0 |
96# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
97# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
98[event14:base-stat]
99fd=14
100type=3
101config=65538
102
103# PERF_TYPE_HW_CACHE,
104# PERF_COUNT_HW_CACHE_L1I << 0 |
105# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
106# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
107[event15:base-stat]
108fd=15
109type=3
110config=1
111
112# PERF_TYPE_HW_CACHE,
113# PERF_COUNT_HW_CACHE_L1I << 0 |
114# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
115# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
116[event16:base-stat]
117fd=16
118type=3
119config=65537
120
121# PERF_TYPE_HW_CACHE,
122# PERF_COUNT_HW_CACHE_DTLB << 0 |
123# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
124# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
125[event17:base-stat]
126fd=17
127type=3
128config=3
129
130# PERF_TYPE_HW_CACHE,
131# PERF_COUNT_HW_CACHE_DTLB << 0 |
132# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
133# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
134[event18:base-stat]
135fd=18
136type=3
137config=65539
138
139# PERF_TYPE_HW_CACHE,
140# PERF_COUNT_HW_CACHE_ITLB << 0 |
141# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
142# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
143[event19:base-stat]
144fd=19
145type=3
146config=4
147
148# PERF_TYPE_HW_CACHE,
149# PERF_COUNT_HW_CACHE_ITLB << 0 |
150# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
151# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
152[event20:base-stat]
153fd=20
154type=3
155config=65540
diff --git a/tools/perf/tests/attr/test-stat-detailed-3 b/tools/perf/tests/attr/test-stat-detailed-3
new file mode 100644
index 000000000000..0a1f45bf7d79
--- /dev/null
+++ b/tools/perf/tests/attr/test-stat-detailed-3
@@ -0,0 +1,173 @@
1[config]
2command = stat
3args = -ddd kill >/dev/null 2>&1
4ret = 1
5
6
7# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK
8[event1:base-stat]
9fd=1
10type=1
11config=1
12
13# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES
14[event2:base-stat]
15fd=2
16type=1
17config=3
18
19# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS
20[event3:base-stat]
21fd=3
22type=1
23config=4
24
25# PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS
26[event4:base-stat]
27fd=4
28type=1
29config=2
30
31# PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES
32[event5:base-stat]
33fd=5
34type=0
35config=0
36
37# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND
38[event6:base-stat]
39fd=6
40type=0
41config=7
42
43# PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND
44[event7:base-stat]
45fd=7
46type=0
47config=8
48
49# PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS
50[event8:base-stat]
51fd=8
52type=0
53config=1
54
55# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS
56[event9:base-stat]
57fd=9
58type=0
59config=4
60
61# PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES
62[event10:base-stat]
63fd=10
64type=0
65config=5
66
67# PERF_TYPE_HW_CACHE /
68# PERF_COUNT_HW_CACHE_L1D << 0 |
69# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
70# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
71[event11:base-stat]
72fd=11
73type=3
74config=0
75
76# PERF_TYPE_HW_CACHE /
77# PERF_COUNT_HW_CACHE_L1D << 0 |
78# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
79# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
80[event12:base-stat]
81fd=12
82type=3
83config=65536
84
85# PERF_TYPE_HW_CACHE /
86# PERF_COUNT_HW_CACHE_LL << 0 |
87# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
88# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
89[event13:base-stat]
90fd=13
91type=3
92config=2
93
94# PERF_TYPE_HW_CACHE,
95# PERF_COUNT_HW_CACHE_LL << 0 |
96# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
97# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
98[event14:base-stat]
99fd=14
100type=3
101config=65538
102
103# PERF_TYPE_HW_CACHE,
104# PERF_COUNT_HW_CACHE_L1I << 0 |
105# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
106# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
107[event15:base-stat]
108fd=15
109type=3
110config=1
111
112# PERF_TYPE_HW_CACHE,
113# PERF_COUNT_HW_CACHE_L1I << 0 |
114# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
115# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
116[event16:base-stat]
117fd=16
118type=3
119config=65537
120
121# PERF_TYPE_HW_CACHE,
122# PERF_COUNT_HW_CACHE_DTLB << 0 |
123# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
124# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
125[event17:base-stat]
126fd=17
127type=3
128config=3
129
130# PERF_TYPE_HW_CACHE,
131# PERF_COUNT_HW_CACHE_DTLB << 0 |
132# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
133# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
134[event18:base-stat]
135fd=18
136type=3
137config=65539
138
139# PERF_TYPE_HW_CACHE,
140# PERF_COUNT_HW_CACHE_ITLB << 0 |
141# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
142# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
143[event19:base-stat]
144fd=19
145type=3
146config=4
147
148# PERF_TYPE_HW_CACHE,
149# PERF_COUNT_HW_CACHE_ITLB << 0 |
150# (PERF_COUNT_HW_CACHE_OP_READ << 8) |
151# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
152[event20:base-stat]
153fd=20
154type=3
155config=65540
156
157# PERF_TYPE_HW_CACHE,
158# PERF_COUNT_HW_CACHE_L1D << 0 |
159# (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
160# (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16)
161[event21:base-stat]
162fd=21
163type=3
164config=512
165
166# PERF_TYPE_HW_CACHE,
167# PERF_COUNT_HW_CACHE_L1D << 0 |
168# (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
169# (PERF_COUNT_HW_CACHE_RESULT_MISS << 16)
170[event22:base-stat]
171fd=22
172type=3
173config=66048
diff --git a/tools/perf/tests/attr/test-stat-group b/tools/perf/tests/attr/test-stat-group
new file mode 100644
index 000000000000..fdc1596a8862
--- /dev/null
+++ b/tools/perf/tests/attr/test-stat-group
@@ -0,0 +1,15 @@
1[config]
2command = stat
3args = --group -e cycles,instructions kill >/dev/null 2>&1
4ret = 1
5
6[event-1:base-stat]
7fd=1
8group_fd=-1
9
10[event-2:base-stat]
11fd=2
12group_fd=1
13config=1
14disabled=0
15enable_on_exec=0
diff --git a/tools/perf/tests/attr/test-stat-group1 b/tools/perf/tests/attr/test-stat-group1
new file mode 100644
index 000000000000..5ae2718de864
--- /dev/null
+++ b/tools/perf/tests/attr/test-stat-group1
@@ -0,0 +1,17 @@
1[config]
2command = stat
3args = -e '{cycles,instructions}' kill >/dev/null 2>&1
4ret = 1
5
6[event-1:base-stat]
7fd=1
8group_fd=-1
9
10[event-2:base-stat]
11fd=2
12group_fd=1
13config=1
14# TODO both disabled and enable_on_exec are disabled for --group option,
15# enabled otherwise, check why..
16disabled=1
17enable_on_exec=1
diff --git a/tools/perf/tests/attr/test-stat-no-inherit b/tools/perf/tests/attr/test-stat-no-inherit
new file mode 100644
index 000000000000..d54b2a1e3e28
--- /dev/null
+++ b/tools/perf/tests/attr/test-stat-no-inherit
@@ -0,0 +1,7 @@
1[config]
2command = stat
3args = -i -e cycles kill >/dev/null 2>&1
4ret = 1
5
6[event:base-stat]
7inherit=0
diff --git a/tools/perf/builtin-test.c b/tools/perf/tests/builtin-test.c
index a04276e81f40..5d4354e24457 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -10,6 +10,7 @@
10#include "util/debug.h" 10#include "util/debug.h"
11#include "util/debugfs.h" 11#include "util/debugfs.h"
12#include "util/evlist.h" 12#include "util/evlist.h"
13#include "util/machine.h"
13#include "util/parse-options.h" 14#include "util/parse-options.h"
14#include "util/parse-events.h" 15#include "util/parse-events.h"
15#include "util/symbol.h" 16#include "util/symbol.h"
@@ -318,7 +319,7 @@ static int test__open_syscall_event(void)
318 nr_open_calls, evsel->counts->cpu[0].val); 319 nr_open_calls, evsel->counts->cpu[0].val);
319 goto out_close_fd; 320 goto out_close_fd;
320 } 321 }
321 322
322 err = 0; 323 err = 0;
323out_close_fd: 324out_close_fd:
324 perf_evsel__close_fd(evsel, 1, threads->nr); 325 perf_evsel__close_fd(evsel, 1, threads->nr);
@@ -604,19 +605,13 @@ out_free_threads:
604#undef nsyscalls 605#undef nsyscalls
605} 606}
606 607
607static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp, 608static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp)
608 size_t *sizep)
609{ 609{
610 cpu_set_t *mask;
611 size_t size;
612 int i, cpu = -1, nrcpus = 1024; 610 int i, cpu = -1, nrcpus = 1024;
613realloc: 611realloc:
614 mask = CPU_ALLOC(nrcpus); 612 CPU_ZERO(maskp);
615 size = CPU_ALLOC_SIZE(nrcpus);
616 CPU_ZERO_S(size, mask);
617 613
618 if (sched_getaffinity(pid, size, mask) == -1) { 614 if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) {
619 CPU_FREE(mask);
620 if (errno == EINVAL && nrcpus < (1024 << 8)) { 615 if (errno == EINVAL && nrcpus < (1024 << 8)) {
621 nrcpus = nrcpus << 2; 616 nrcpus = nrcpus << 2;
622 goto realloc; 617 goto realloc;
@@ -626,19 +621,14 @@ realloc:
626 } 621 }
627 622
628 for (i = 0; i < nrcpus; i++) { 623 for (i = 0; i < nrcpus; i++) {
629 if (CPU_ISSET_S(i, size, mask)) { 624 if (CPU_ISSET(i, maskp)) {
630 if (cpu == -1) { 625 if (cpu == -1)
631 cpu = i; 626 cpu = i;
632 *maskp = mask; 627 else
633 *sizep = size; 628 CPU_CLR(i, maskp);
634 } else
635 CPU_CLR_S(i, size, mask);
636 } 629 }
637 } 630 }
638 631
639 if (cpu == -1)
640 CPU_FREE(mask);
641
642 return cpu; 632 return cpu;
643} 633}
644 634
@@ -653,8 +643,8 @@ static int test__PERF_RECORD(void)
653 .freq = 10, 643 .freq = 10,
654 .mmap_pages = 256, 644 .mmap_pages = 256,
655 }; 645 };
656 cpu_set_t *cpu_mask = NULL; 646 cpu_set_t cpu_mask;
657 size_t cpu_mask_size = 0; 647 size_t cpu_mask_size = sizeof(cpu_mask);
658 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); 648 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
659 struct perf_evsel *evsel; 649 struct perf_evsel *evsel;
660 struct perf_sample sample; 650 struct perf_sample sample;
@@ -718,8 +708,7 @@ static int test__PERF_RECORD(void)
718 evsel->attr.sample_type |= PERF_SAMPLE_TIME; 708 evsel->attr.sample_type |= PERF_SAMPLE_TIME;
719 perf_evlist__config_attrs(evlist, &opts); 709 perf_evlist__config_attrs(evlist, &opts);
720 710
721 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask, 711 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
722 &cpu_mask_size);
723 if (err < 0) { 712 if (err < 0) {
724 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); 713 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
725 goto out_delete_evlist; 714 goto out_delete_evlist;
@@ -730,9 +719,9 @@ static int test__PERF_RECORD(void)
730 /* 719 /*
731 * So that we can check perf_sample.cpu on all the samples. 720 * So that we can check perf_sample.cpu on all the samples.
732 */ 721 */
733 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, cpu_mask) < 0) { 722 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
734 pr_debug("sched_setaffinity: %s\n", strerror(errno)); 723 pr_debug("sched_setaffinity: %s\n", strerror(errno));
735 goto out_free_cpu_mask; 724 goto out_delete_evlist;
736 } 725 }
737 726
738 /* 727 /*
@@ -916,8 +905,6 @@ found_exit:
916 } 905 }
917out_err: 906out_err:
918 perf_evlist__munmap(evlist); 907 perf_evlist__munmap(evlist);
919out_free_cpu_mask:
920 CPU_FREE(cpu_mask);
921out_delete_evlist: 908out_delete_evlist:
922 perf_evlist__delete(evlist); 909 perf_evlist__delete(evlist);
923out: 910out:
@@ -1344,8 +1331,8 @@ static int test__syscall_open_tp_fields(void)
1344 perf_evlist__enable(evlist); 1331 perf_evlist__enable(evlist);
1345 1332
1346 /* 1333 /*
1347 * Generate the event: 1334 * Generate the event:
1348 */ 1335 */
1349 open(filename, flags); 1336 open(filename, flags);
1350 1337
1351 while (1) { 1338 while (1) {
@@ -1455,6 +1442,10 @@ static struct test {
1455 .func = test__syscall_open_tp_fields, 1442 .func = test__syscall_open_tp_fields,
1456 }, 1443 },
1457 { 1444 {
1445 .desc = "struct perf_event_attr setup",
1446 .func = test_attr__run,
1447 },
1448 {
1458 .func = NULL, 1449 .func = NULL,
1459 }, 1450 },
1460}; 1451};
@@ -1495,7 +1486,7 @@ static int __cmd_test(int argc, const char *argv[])
1495 width = len; 1486 width = len;
1496 ++i; 1487 ++i;
1497 } 1488 }
1498 1489
1499 i = 0; 1490 i = 0;
1500 while (tests[i].func) { 1491 while (tests[i].func) {
1501 int curr = i++, err; 1492 int curr = i++, err;
diff --git a/tools/perf/util/dso-test-data.c b/tools/perf/tests/dso-data.c
index c6caedeb1d6b..0cd42fc9bc13 100644
--- a/tools/perf/util/dso-test-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -6,6 +6,7 @@
6#include <fcntl.h> 6#include <fcntl.h>
7#include <string.h> 7#include <string.h>
8 8
9#include "machine.h"
9#include "symbol.h" 10#include "symbol.h"
10 11
11#define TEST_ASSERT_VAL(text, cond) \ 12#define TEST_ASSERT_VAL(text, cond) \
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/tests/parse-events.c
index b49c2eebff33..b49c2eebff33 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/tests/parse-events.c
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 28f8aab73aee..5dab3ca96980 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -188,6 +188,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
188 struct disasm_line *cursor = ab->selection, *target; 188 struct disasm_line *cursor = ab->selection, *target;
189 struct browser_disasm_line *btarget, *bcursor; 189 struct browser_disasm_line *btarget, *bcursor;
190 unsigned int from, to; 190 unsigned int from, to;
191 struct map_symbol *ms = ab->b.priv;
192 struct symbol *sym = ms->sym;
193
194 /* PLT symbols contain external offsets */
195 if (strstr(sym->name, "@plt"))
196 return;
191 197
192 if (!cursor || !cursor->ins || !ins__is_jump(cursor->ins) || 198 if (!cursor || !cursor->ins || !ins__is_jump(cursor->ins) ||
193 !disasm_line__has_offset(cursor)) 199 !disasm_line__has_offset(cursor))
@@ -386,9 +392,8 @@ static void annotate_browser__init_asm_mode(struct annotate_browser *browser)
386 browser->b.nr_entries = browser->nr_asm_entries; 392 browser->b.nr_entries = browser->nr_asm_entries;
387} 393}
388 394
389static bool annotate_browser__callq(struct annotate_browser *browser, 395static bool annotate_browser__callq(struct annotate_browser *browser, int evidx,
390 int evidx, void (*timer)(void *arg), 396 struct hist_browser_timer *hbt)
391 void *arg, int delay_secs)
392{ 397{
393 struct map_symbol *ms = browser->b.priv; 398 struct map_symbol *ms = browser->b.priv;
394 struct disasm_line *dl = browser->selection; 399 struct disasm_line *dl = browser->selection;
@@ -418,7 +423,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
418 } 423 }
419 424
420 pthread_mutex_unlock(&notes->lock); 425 pthread_mutex_unlock(&notes->lock);
421 symbol__tui_annotate(target, ms->map, evidx, timer, arg, delay_secs); 426 symbol__tui_annotate(target, ms->map, evidx, hbt);
422 ui_browser__show_title(&browser->b, sym->name); 427 ui_browser__show_title(&browser->b, sym->name);
423 return true; 428 return true;
424} 429}
@@ -602,13 +607,13 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser
602} 607}
603 608
604static int annotate_browser__run(struct annotate_browser *browser, int evidx, 609static int annotate_browser__run(struct annotate_browser *browser, int evidx,
605 void(*timer)(void *arg), 610 struct hist_browser_timer *hbt)
606 void *arg, int delay_secs)
607{ 611{
608 struct rb_node *nd = NULL; 612 struct rb_node *nd = NULL;
609 struct map_symbol *ms = browser->b.priv; 613 struct map_symbol *ms = browser->b.priv;
610 struct symbol *sym = ms->sym; 614 struct symbol *sym = ms->sym;
611 const char *help = "Press 'h' for help on key bindings"; 615 const char *help = "Press 'h' for help on key bindings";
616 int delay_secs = hbt ? hbt->refresh : 0;
612 int key; 617 int key;
613 618
614 if (ui_browser__show(&browser->b, sym->name, help) < 0) 619 if (ui_browser__show(&browser->b, sym->name, help) < 0)
@@ -639,8 +644,8 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
639 644
640 switch (key) { 645 switch (key) {
641 case K_TIMER: 646 case K_TIMER:
642 if (timer != NULL) 647 if (hbt)
643 timer(arg); 648 hbt->timer(hbt->arg);
644 649
645 if (delay_secs != 0) 650 if (delay_secs != 0)
646 symbol__annotate_decay_histogram(sym, evidx); 651 symbol__annotate_decay_histogram(sym, evidx);
@@ -740,7 +745,7 @@ show_help:
740 goto show_sup_ins; 745 goto show_sup_ins;
741 goto out; 746 goto out;
742 } else if (!(annotate_browser__jump(browser) || 747 } else if (!(annotate_browser__jump(browser) ||
743 annotate_browser__callq(browser, evidx, timer, arg, delay_secs))) { 748 annotate_browser__callq(browser, evidx, hbt))) {
744show_sup_ins: 749show_sup_ins:
745 ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); 750 ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions.");
746 } 751 }
@@ -763,16 +768,21 @@ out:
763} 768}
764 769
765int hist_entry__tui_annotate(struct hist_entry *he, int evidx, 770int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
766 void(*timer)(void *arg), void *arg, int delay_secs) 771 struct hist_browser_timer *hbt)
767{ 772{
768 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, 773 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, hbt);
769 timer, arg, delay_secs);
770} 774}
771 775
772static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 776static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
773 size_t size) 777 size_t size)
774{ 778{
775 u64 offset; 779 u64 offset;
780 struct map_symbol *ms = browser->b.priv;
781 struct symbol *sym = ms->sym;
782
783 /* PLT symbols contain external offsets */
784 if (strstr(sym->name, "@plt"))
785 return;
776 786
777 for (offset = 0; offset < size; ++offset) { 787 for (offset = 0; offset < size; ++offset) {
778 struct disasm_line *dl = browser->offsets[offset], *dlt; 788 struct disasm_line *dl = browser->offsets[offset], *dlt;
@@ -816,8 +826,7 @@ static inline int width_jumps(int n)
816} 826}
817 827
818int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 828int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
819 void(*timer)(void *arg), void *arg, 829 struct hist_browser_timer *hbt)
820 int delay_secs)
821{ 830{
822 struct disasm_line *pos, *n; 831 struct disasm_line *pos, *n;
823 struct annotation *notes; 832 struct annotation *notes;
@@ -899,7 +908,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
899 908
900 annotate_browser__update_addr_width(&browser); 909 annotate_browser__update_addr_width(&browser);
901 910
902 ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs); 911 ret = annotate_browser__run(&browser, evidx, hbt);
903 list_for_each_entry_safe(pos, n, &notes->src->source, node) { 912 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
904 list_del(&pos->node); 913 list_del(&pos->node);
905 disasm_line__free(pos); 914 disasm_line__free(pos);
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index fe622845872e..ccc4bd161420 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -11,6 +11,7 @@
11#include "../../util/pstack.h" 11#include "../../util/pstack.h"
12#include "../../util/sort.h" 12#include "../../util/sort.h"
13#include "../../util/util.h" 13#include "../../util/util.h"
14#include "../../arch/common.h"
14 15
15#include "../browser.h" 16#include "../browser.h"
16#include "../helpline.h" 17#include "../helpline.h"
@@ -310,10 +311,11 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
310} 311}
311 312
312static int hist_browser__run(struct hist_browser *browser, const char *ev_name, 313static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
313 void(*timer)(void *arg), void *arg, int delay_secs) 314 struct hist_browser_timer *hbt)
314{ 315{
315 int key; 316 int key;
316 char title[160]; 317 char title[160];
318 int delay_secs = hbt ? hbt->refresh : 0;
317 319
318 browser->b.entries = &browser->hists->entries; 320 browser->b.entries = &browser->hists->entries;
319 browser->b.nr_entries = browser->hists->nr_entries; 321 browser->b.nr_entries = browser->hists->nr_entries;
@@ -330,7 +332,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name,
330 332
331 switch (key) { 333 switch (key) {
332 case K_TIMER: 334 case K_TIMER:
333 timer(arg); 335 hbt->timer(hbt->arg);
334 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); 336 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
335 337
336 if (browser->hists->stats.nr_lost_warned != 338 if (browser->hists->stats.nr_lost_warned !=
@@ -1127,11 +1129,17 @@ static inline void free_popup_options(char **options, int n)
1127 } 1129 }
1128} 1130}
1129 1131
1132/* Check whether the browser is for 'top' or 'report' */
1133static inline bool is_report_browser(void *timer)
1134{
1135 return timer == NULL;
1136}
1137
1130static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, 1138static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1131 const char *helpline, const char *ev_name, 1139 const char *helpline, const char *ev_name,
1132 bool left_exits, 1140 bool left_exits,
1133 void(*timer)(void *arg), void *arg, 1141 struct hist_browser_timer *hbt,
1134 int delay_secs) 1142 struct perf_session_env *env)
1135{ 1143{
1136 struct hists *hists = &evsel->hists; 1144 struct hists *hists = &evsel->hists;
1137 struct hist_browser *browser = hist_browser__new(hists); 1145 struct hist_browser *browser = hist_browser__new(hists);
@@ -1142,6 +1150,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1142 int key = -1; 1150 int key = -1;
1143 char buf[64]; 1151 char buf[64];
1144 char script_opt[64]; 1152 char script_opt[64];
1153 int delay_secs = hbt ? hbt->refresh : 0;
1145 1154
1146 if (browser == NULL) 1155 if (browser == NULL)
1147 return -1; 1156 return -1;
@@ -1164,7 +1173,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1164 1173
1165 nr_options = 0; 1174 nr_options = 0;
1166 1175
1167 key = hist_browser__run(browser, ev_name, timer, arg, delay_secs); 1176 key = hist_browser__run(browser, ev_name, hbt);
1168 1177
1169 if (browser->he_selection != NULL) { 1178 if (browser->he_selection != NULL) {
1170 thread = hist_browser__selected_thread(browser); 1179 thread = hist_browser__selected_thread(browser);
@@ -1214,7 +1223,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1214 } 1223 }
1215 continue; 1224 continue;
1216 case 'r': 1225 case 'r':
1217 goto do_scripts; 1226 if (is_report_browser(hbt))
1227 goto do_scripts;
1228 continue;
1218 case K_F1: 1229 case K_F1:
1219 case 'h': 1230 case 'h':
1220 case '?': 1231 case '?':
@@ -1233,7 +1244,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1233 "E Expand all callchains\n" 1244 "E Expand all callchains\n"
1234 "d Zoom into current DSO\n" 1245 "d Zoom into current DSO\n"
1235 "t Zoom into current Thread\n" 1246 "t Zoom into current Thread\n"
1236 "r Run available scripts\n" 1247 "r Run available scripts('perf report' only)\n"
1237 "P Print histograms to perf.hist.N\n" 1248 "P Print histograms to perf.hist.N\n"
1238 "V Verbose (DSO names in callchains, etc)\n" 1249 "V Verbose (DSO names in callchains, etc)\n"
1239 "/ Filter symbol by name"); 1250 "/ Filter symbol by name");
@@ -1358,6 +1369,9 @@ retry_popup_menu:
1358 struct hist_entry *he; 1369 struct hist_entry *he;
1359 int err; 1370 int err;
1360do_annotate: 1371do_annotate:
1372 if (!objdump_path && perf_session_env__lookup_objdump(env))
1373 continue;
1374
1361 he = hist_browser__selected_entry(browser); 1375 he = hist_browser__selected_entry(browser);
1362 if (he == NULL) 1376 if (he == NULL)
1363 continue; 1377 continue;
@@ -1380,8 +1394,7 @@ do_annotate:
1380 * Don't let this be freed, say, by hists__decay_entry. 1394 * Don't let this be freed, say, by hists__decay_entry.
1381 */ 1395 */
1382 he->used = true; 1396 he->used = true;
1383 err = hist_entry__tui_annotate(he, evsel->idx, 1397 err = hist_entry__tui_annotate(he, evsel->idx, hbt);
1384 timer, arg, delay_secs);
1385 he->used = false; 1398 he->used = false;
1386 /* 1399 /*
1387 * offer option to annotate the other branch source or target 1400 * offer option to annotate the other branch source or target
@@ -1462,6 +1475,7 @@ struct perf_evsel_menu {
1462 struct ui_browser b; 1475 struct ui_browser b;
1463 struct perf_evsel *selection; 1476 struct perf_evsel *selection;
1464 bool lost_events, lost_events_warned; 1477 bool lost_events, lost_events_warned;
1478 struct perf_session_env *env;
1465}; 1479};
1466 1480
1467static void perf_evsel_menu__write(struct ui_browser *browser, 1481static void perf_evsel_menu__write(struct ui_browser *browser,
@@ -1504,11 +1518,12 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1504 1518
1505static int perf_evsel_menu__run(struct perf_evsel_menu *menu, 1519static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
1506 int nr_events, const char *help, 1520 int nr_events, const char *help,
1507 void(*timer)(void *arg), void *arg, int delay_secs) 1521 struct hist_browser_timer *hbt)
1508{ 1522{
1509 struct perf_evlist *evlist = menu->b.priv; 1523 struct perf_evlist *evlist = menu->b.priv;
1510 struct perf_evsel *pos; 1524 struct perf_evsel *pos;
1511 const char *ev_name, *title = "Available samples"; 1525 const char *ev_name, *title = "Available samples";
1526 int delay_secs = hbt ? hbt->refresh : 0;
1512 int key; 1527 int key;
1513 1528
1514 if (ui_browser__show(&menu->b, title, 1529 if (ui_browser__show(&menu->b, title,
@@ -1520,7 +1535,7 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
1520 1535
1521 switch (key) { 1536 switch (key) {
1522 case K_TIMER: 1537 case K_TIMER:
1523 timer(arg); 1538 hbt->timer(hbt->arg);
1524 1539
1525 if (!menu->lost_events_warned && menu->lost_events) { 1540 if (!menu->lost_events_warned && menu->lost_events) {
1526 ui_browser__warn_lost_events(&menu->b); 1541 ui_browser__warn_lost_events(&menu->b);
@@ -1538,12 +1553,12 @@ browse_hists:
1538 * Give the calling tool a chance to populate the non 1553 * Give the calling tool a chance to populate the non
1539 * default evsel resorted hists tree. 1554 * default evsel resorted hists tree.
1540 */ 1555 */
1541 if (timer) 1556 if (hbt)
1542 timer(arg); 1557 hbt->timer(hbt->arg);
1543 ev_name = perf_evsel__name(pos); 1558 ev_name = perf_evsel__name(pos);
1544 key = perf_evsel__hists_browse(pos, nr_events, help, 1559 key = perf_evsel__hists_browse(pos, nr_events, help,
1545 ev_name, true, timer, 1560 ev_name, true, hbt,
1546 arg, delay_secs); 1561 menu->env);
1547 ui_browser__show_title(&menu->b, title); 1562 ui_browser__show_title(&menu->b, title);
1548 switch (key) { 1563 switch (key) {
1549 case K_TAB: 1564 case K_TAB:
@@ -1591,8 +1606,8 @@ out:
1591 1606
1592static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, 1607static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1593 const char *help, 1608 const char *help,
1594 void(*timer)(void *arg), void *arg, 1609 struct hist_browser_timer *hbt,
1595 int delay_secs) 1610 struct perf_session_env *env)
1596{ 1611{
1597 struct perf_evsel *pos; 1612 struct perf_evsel *pos;
1598 struct perf_evsel_menu menu = { 1613 struct perf_evsel_menu menu = {
@@ -1604,6 +1619,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1604 .nr_entries = evlist->nr_entries, 1619 .nr_entries = evlist->nr_entries,
1605 .priv = evlist, 1620 .priv = evlist,
1606 }, 1621 },
1622 .env = env,
1607 }; 1623 };
1608 1624
1609 ui_helpline__push("Press ESC to exit"); 1625 ui_helpline__push("Press ESC to exit");
@@ -1616,23 +1632,20 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1616 menu.b.width = line_len; 1632 menu.b.width = line_len;
1617 } 1633 }
1618 1634
1619 return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer, 1635 return perf_evsel_menu__run(&menu, evlist->nr_entries, help, hbt);
1620 arg, delay_secs);
1621} 1636}
1622 1637
1623int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 1638int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
1624 void(*timer)(void *arg), void *arg, 1639 struct hist_browser_timer *hbt,
1625 int delay_secs) 1640 struct perf_session_env *env)
1626{ 1641{
1627 if (evlist->nr_entries == 1) { 1642 if (evlist->nr_entries == 1) {
1628 struct perf_evsel *first = list_entry(evlist->entries.next, 1643 struct perf_evsel *first = list_entry(evlist->entries.next,
1629 struct perf_evsel, node); 1644 struct perf_evsel, node);
1630 const char *ev_name = perf_evsel__name(first); 1645 const char *ev_name = perf_evsel__name(first);
1631 return perf_evsel__hists_browse(first, evlist->nr_entries, help, 1646 return perf_evsel__hists_browse(first, evlist->nr_entries, help,
1632 ev_name, false, timer, arg, 1647 ev_name, false, hbt, env);
1633 delay_secs);
1634 } 1648 }
1635 1649
1636 return __perf_evlist__tui_browse_hists(evlist, help, 1650 return __perf_evlist__tui_browse_hists(evlist, help, hbt, env);
1637 timer, arg, delay_secs);
1638} 1651}
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 4125c6284114..253b6219a39e 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -237,9 +237,7 @@ static GtkWidget *perf_gtk__setup_statusbar(void)
237 237
238int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, 238int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
239 const char *help, 239 const char *help,
240 void (*timer) (void *arg)__maybe_unused, 240 struct hist_browser_timer *hbt __maybe_unused)
241 void *arg __maybe_unused,
242 int delay_secs __maybe_unused)
243{ 241{
244 struct perf_evsel *pos; 242 struct perf_evsel *pos;
245 GtkWidget *vbox; 243 GtkWidget *vbox;
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 4f5f4756faac..aa84130024d5 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -161,7 +161,7 @@ static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
161 161
162static double baseline_percent(struct hist_entry *he) 162static double baseline_percent(struct hist_entry *he)
163{ 163{
164 struct hist_entry *pair = he->pair; 164 struct hist_entry *pair = hist_entry__next_pair(he);
165 struct hists *pair_hists = pair ? pair->hists : NULL; 165 struct hists *pair_hists = pair ? pair->hists : NULL;
166 double percent = 0.0; 166 double percent = 0.0;
167 167
@@ -179,7 +179,7 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
179{ 179{
180 double percent = baseline_percent(he); 180 double percent = baseline_percent(he);
181 181
182 if (he->pair) 182 if (hist_entry__has_pairs(he))
183 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); 183 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
184 else 184 else
185 return scnprintf(hpp->buf, hpp->size, " "); 185 return scnprintf(hpp->buf, hpp->size, " ");
@@ -190,7 +190,7 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
190 double percent = baseline_percent(he); 190 double percent = baseline_percent(he);
191 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; 191 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
192 192
193 if (he->pair || symbol_conf.field_sep) 193 if (hist_entry__has_pairs(he) || symbol_conf.field_sep)
194 return scnprintf(hpp->buf, hpp->size, fmt, percent); 194 return scnprintf(hpp->buf, hpp->size, fmt, percent);
195 else 195 else
196 return scnprintf(hpp->buf, hpp->size, " "); 196 return scnprintf(hpp->buf, hpp->size, " ");
@@ -248,7 +248,7 @@ static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused)
248 248
249static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he) 249static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he)
250{ 250{
251 struct hist_entry *pair = he->pair; 251 struct hist_entry *pair = hist_entry__next_pair(he);
252 u64 period = pair ? pair->stat.period : 0; 252 u64 period = pair ? pair->stat.period : 0;
253 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; 253 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
254 254
@@ -354,7 +354,7 @@ static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
354static int hpp__entry_displ(struct perf_hpp *hpp, 354static int hpp__entry_displ(struct perf_hpp *hpp,
355 struct hist_entry *he) 355 struct hist_entry *he)
356{ 356{
357 struct hist_entry *pair = he->pair; 357 struct hist_entry *pair = hist_entry__next_pair(he);
358 long displacement = pair ? pair->position - he->position : 0; 358 long displacement = pair ? pair->position - he->position : 0;
359 const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; 359 const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
360 char buf[32] = " "; 360 char buf[32] = " ";
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 95264f304179..6aa34e5afdcf 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -9,18 +9,14 @@ GVF=${OUTPUT}PERF-VERSION-FILE
9LF=' 9LF='
10' 10'
11 11
12#
12# First check if there is a .git to get the version from git describe 13# First check if there is a .git to get the version from git describe
13# otherwise try to get the version from the kernel makefile 14# otherwise try to get the version from the kernel Makefile
15#
14if test -d ../../.git -o -f ../../.git && 16if test -d ../../.git -o -f ../../.git &&
15 VN=$(git describe --match 'v[0-9].[0-9]*' --abbrev=4 HEAD 2>/dev/null) && 17 VN=$(git tag 2>/dev/null | tail -1 | grep -E "v[0-9].[0-9]*")
16 case "$VN" in
17 *$LF*) (exit 1) ;;
18 v[0-9]*)
19 git update-index -q --refresh
20 test -z "$(git diff-index --name-only HEAD --)" ||
21 VN="$VN-dirty" ;;
22 esac
23then 18then
19 VN=$(echo $VN"-g"$(git log -1 --abbrev=4 --pretty=format:"%h" HEAD))
24 VN=$(echo "$VN" | sed -e 's/-/./g'); 20 VN=$(echo "$VN" | sed -e 's/-/./g');
25else 21else
26 VN=$(MAKEFLAGS= make -sC ../.. kernelversion) 22 VN=$(MAKEFLAGS= make -sC ../.. kernelversion)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7a34dd18b74c..07aaeea60000 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -171,15 +171,15 @@ static int lock__parse(struct ins_operands *ops)
171 if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0) 171 if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
172 goto out_free_ops; 172 goto out_free_ops;
173 173
174 ops->locked.ins = ins__find(name); 174 ops->locked.ins = ins__find(name);
175 if (ops->locked.ins == NULL) 175 if (ops->locked.ins == NULL)
176 goto out_free_ops; 176 goto out_free_ops;
177 177
178 if (!ops->locked.ins->ops) 178 if (!ops->locked.ins->ops)
179 return 0; 179 return 0;
180 180
181 if (ops->locked.ins->ops->parse) 181 if (ops->locked.ins->ops->parse)
182 ops->locked.ins->ops->parse(ops->locked.ops); 182 ops->locked.ins->ops->parse(ops->locked.ops);
183 183
184 return 0; 184 return 0;
185 185
@@ -401,6 +401,8 @@ static struct ins instructions[] = {
401 { .name = "testb", .ops = &mov_ops, }, 401 { .name = "testb", .ops = &mov_ops, },
402 { .name = "testl", .ops = &mov_ops, }, 402 { .name = "testl", .ops = &mov_ops, },
403 { .name = "xadd", .ops = &mov_ops, }, 403 { .name = "xadd", .ops = &mov_ops, },
404 { .name = "xbeginl", .ops = &jump_ops, },
405 { .name = "xbeginq", .ops = &jump_ops, },
404}; 406};
405 407
406static int ins__cmp(const void *name, const void *insp) 408static int ins__cmp(const void *name, const void *insp)
@@ -856,21 +858,68 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
856 struct source_line *iter; 858 struct source_line *iter;
857 struct rb_node **p = &root->rb_node; 859 struct rb_node **p = &root->rb_node;
858 struct rb_node *parent = NULL; 860 struct rb_node *parent = NULL;
861 int ret;
859 862
860 while (*p != NULL) { 863 while (*p != NULL) {
861 parent = *p; 864 parent = *p;
862 iter = rb_entry(parent, struct source_line, node); 865 iter = rb_entry(parent, struct source_line, node);
863 866
864 if (src_line->percent > iter->percent) 867 ret = strcmp(iter->path, src_line->path);
868 if (ret == 0) {
869 iter->percent_sum += src_line->percent;
870 return;
871 }
872
873 if (ret < 0)
865 p = &(*p)->rb_left; 874 p = &(*p)->rb_left;
866 else 875 else
867 p = &(*p)->rb_right; 876 p = &(*p)->rb_right;
868 } 877 }
869 878
879 src_line->percent_sum = src_line->percent;
880
870 rb_link_node(&src_line->node, parent, p); 881 rb_link_node(&src_line->node, parent, p);
871 rb_insert_color(&src_line->node, root); 882 rb_insert_color(&src_line->node, root);
872} 883}
873 884
885static void __resort_source_line(struct rb_root *root, struct source_line *src_line)
886{
887 struct source_line *iter;
888 struct rb_node **p = &root->rb_node;
889 struct rb_node *parent = NULL;
890
891 while (*p != NULL) {
892 parent = *p;
893 iter = rb_entry(parent, struct source_line, node);
894
895 if (src_line->percent_sum > iter->percent_sum)
896 p = &(*p)->rb_left;
897 else
898 p = &(*p)->rb_right;
899 }
900
901 rb_link_node(&src_line->node, parent, p);
902 rb_insert_color(&src_line->node, root);
903}
904
905static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root)
906{
907 struct source_line *src_line;
908 struct rb_node *node;
909
910 node = rb_first(src_root);
911 while (node) {
912 struct rb_node *next;
913
914 src_line = rb_entry(node, struct source_line, node);
915 next = rb_next(node);
916 rb_erase(node, src_root);
917
918 __resort_source_line(dest_root, src_line);
919 node = next;
920 }
921}
922
874static void symbol__free_source_line(struct symbol *sym, int len) 923static void symbol__free_source_line(struct symbol *sym, int len)
875{ 924{
876 struct annotation *notes = symbol__annotation(sym); 925 struct annotation *notes = symbol__annotation(sym);
@@ -895,6 +944,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
895 struct source_line *src_line; 944 struct source_line *src_line;
896 struct annotation *notes = symbol__annotation(sym); 945 struct annotation *notes = symbol__annotation(sym);
897 struct sym_hist *h = annotation__histogram(notes, evidx); 946 struct sym_hist *h = annotation__histogram(notes, evidx);
947 struct rb_root tmp_root = RB_ROOT;
898 948
899 if (!h->sum) 949 if (!h->sum)
900 return 0; 950 return 0;
@@ -929,12 +979,13 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
929 goto next; 979 goto next;
930 980
931 strcpy(src_line[i].path, path); 981 strcpy(src_line[i].path, path);
932 insert_source_line(root, &src_line[i]); 982 insert_source_line(&tmp_root, &src_line[i]);
933 983
934 next: 984 next:
935 pclose(fp); 985 pclose(fp);
936 } 986 }
937 987
988 resort_source_line(root, &tmp_root);
938 return 0; 989 return 0;
939} 990}
940 991
@@ -958,7 +1009,7 @@ static void print_summary(struct rb_root *root, const char *filename)
958 char *path; 1009 char *path;
959 1010
960 src_line = rb_entry(node, struct source_line, node); 1011 src_line = rb_entry(node, struct source_line, node);
961 percent = src_line->percent; 1012 percent = src_line->percent_sum;
962 color = get_percent_color(percent); 1013 color = get_percent_color(percent);
963 path = src_line->path; 1014 path = src_line->path;
964 1015
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index a4dd25a61a07..8eec94358a4a 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -5,6 +5,7 @@
5#include <stdint.h> 5#include <stdint.h>
6#include "types.h" 6#include "types.h"
7#include "symbol.h" 7#include "symbol.h"
8#include "hist.h"
8#include <linux/list.h> 9#include <linux/list.h>
9#include <linux/rbtree.h> 10#include <linux/rbtree.h>
10#include <pthread.h> 11#include <pthread.h>
@@ -75,6 +76,7 @@ struct sym_hist {
75struct source_line { 76struct source_line {
76 struct rb_node node; 77 struct rb_node node;
77 double percent; 78 double percent;
79 double percent_sum;
78 char *path; 80 char *path;
79}; 81};
80 82
@@ -140,14 +142,13 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
140 142
141#ifdef NEWT_SUPPORT 143#ifdef NEWT_SUPPORT
142int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 144int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
143 void(*timer)(void *arg), void *arg, int delay_secs); 145 struct hist_browser_timer *hbt);
144#else 146#else
145static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, 147static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
146 struct map *map __maybe_unused, 148 struct map *map __maybe_unused,
147 int evidx __maybe_unused, 149 int evidx __maybe_unused,
148 void(*timer)(void *arg) __maybe_unused, 150 struct hist_browser_timer *hbt
149 void *arg __maybe_unused, 151 __maybe_unused)
150 int delay_secs __maybe_unused)
151{ 152{
152 return 0; 153 return 0;
153} 154}
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index db24a3f0c820..d6d9a465acdb 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1,5 +1,6 @@
1#include "symbol.h" 1#include "symbol.h"
2#include "dso.h" 2#include "dso.h"
3#include "machine.h"
3#include "util.h" 4#include "util.h"
4#include "debug.h" 5#include "debug.h"
5 6
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 277947a669b2..7c6e73b1b7ea 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -244,6 +244,8 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
244 he->ms.map->referenced = true; 244 he->ms.map->referenced = true;
245 if (symbol_conf.use_callchain) 245 if (symbol_conf.use_callchain)
246 callchain_init(he->callchain); 246 callchain_init(he->callchain);
247
248 INIT_LIST_HEAD(&he->pairs.node);
247 } 249 }
248 250
249 return he; 251 return he;
@@ -410,6 +412,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
410 412
411void hist_entry__free(struct hist_entry *he) 413void hist_entry__free(struct hist_entry *he)
412{ 414{
415 free(he->branch_info);
413 free(he); 416 free(he);
414} 417}
415 418
@@ -713,3 +716,100 @@ void hists__inc_nr_events(struct hists *hists, u32 type)
713 ++hists->stats.nr_events[0]; 716 ++hists->stats.nr_events[0];
714 ++hists->stats.nr_events[type]; 717 ++hists->stats.nr_events[type];
715} 718}
719
720static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
721 struct hist_entry *pair)
722{
723 struct rb_node **p = &hists->entries.rb_node;
724 struct rb_node *parent = NULL;
725 struct hist_entry *he;
726 int cmp;
727
728 while (*p != NULL) {
729 parent = *p;
730 he = rb_entry(parent, struct hist_entry, rb_node);
731
732 cmp = hist_entry__cmp(pair, he);
733
734 if (!cmp)
735 goto out;
736
737 if (cmp < 0)
738 p = &(*p)->rb_left;
739 else
740 p = &(*p)->rb_right;
741 }
742
743 he = hist_entry__new(pair);
744 if (he) {
745 he->stat.nr_events = 0;
746 he->stat.period = 0;
747 he->hists = hists;
748 rb_link_node(&he->rb_node, parent, p);
749 rb_insert_color(&he->rb_node, &hists->entries);
750 hists__inc_nr_entries(hists, he);
751 }
752out:
753 return he;
754}
755
756static struct hist_entry *hists__find_entry(struct hists *hists,
757 struct hist_entry *he)
758{
759 struct rb_node *n = hists->entries.rb_node;
760
761 while (n) {
762 struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node);
763 int64_t cmp = hist_entry__cmp(he, iter);
764
765 if (cmp < 0)
766 n = n->rb_left;
767 else if (cmp > 0)
768 n = n->rb_right;
769 else
770 return iter;
771 }
772
773 return NULL;
774}
775
776/*
777 * Look for pairs to link to the leader buckets (hist_entries):
778 */
779void hists__match(struct hists *leader, struct hists *other)
780{
781 struct rb_node *nd;
782 struct hist_entry *pos, *pair;
783
784 for (nd = rb_first(&leader->entries); nd; nd = rb_next(nd)) {
785 pos = rb_entry(nd, struct hist_entry, rb_node);
786 pair = hists__find_entry(other, pos);
787
788 if (pair)
789 hist__entry_add_pair(pos, pair);
790 }
791}
792
793/*
794 * Look for entries in the other hists that are not present in the leader, if
795 * we find them, just add a dummy entry on the leader hists, with period=0,
796 * nr_events=0, to serve as the list header.
797 */
798int hists__link(struct hists *leader, struct hists *other)
799{
800 struct rb_node *nd;
801 struct hist_entry *pos, *pair;
802
803 for (nd = rb_first(&other->entries); nd; nd = rb_next(nd)) {
804 pos = rb_entry(nd, struct hist_entry, rb_node);
805
806 if (!hist_entry__has_pairs(pos)) {
807 pair = hists__add_dummy_entry(leader, pos);
808 if (pair == NULL)
809 return -1;
810 hist__entry_add_pair(pair, pos);
811 }
812 }
813
814 return 0;
815}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index b87460971736..1278c2c72a96 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -4,6 +4,7 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include <pthread.h> 5#include <pthread.h>
6#include "callchain.h" 6#include "callchain.h"
7#include "header.h"
7 8
8extern struct callchain_param callchain_param; 9extern struct callchain_param callchain_param;
9 10
@@ -114,6 +115,9 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
114void hists__reset_col_len(struct hists *hists); 115void hists__reset_col_len(struct hists *hists);
115void hists__calc_col_len(struct hists *hists, struct hist_entry *he); 116void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
116 117
118void hists__match(struct hists *leader, struct hists *other);
119int hists__link(struct hists *leader, struct hists *other);
120
117struct perf_hpp { 121struct perf_hpp {
118 char *buf; 122 char *buf;
119 size_t size; 123 size_t size;
@@ -157,22 +161,27 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
157 161
158struct perf_evlist; 162struct perf_evlist;
159 163
164struct hist_browser_timer {
165 void (*timer)(void *arg);
166 void *arg;
167 int refresh;
168};
169
160#ifdef NEWT_SUPPORT 170#ifdef NEWT_SUPPORT
161#include "../ui/keysyms.h" 171#include "../ui/keysyms.h"
162int hist_entry__tui_annotate(struct hist_entry *he, int evidx, 172int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
163 void(*timer)(void *arg), void *arg, int delay_secs); 173 struct hist_browser_timer *hbt);
164 174
165int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 175int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
166 void(*timer)(void *arg), void *arg, 176 struct hist_browser_timer *hbt,
167 int refresh); 177 struct perf_session_env *env);
168int script_browse(const char *script_opt); 178int script_browse(const char *script_opt);
169#else 179#else
170static inline 180static inline
171int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, 181int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
172 const char *help __maybe_unused, 182 const char *help __maybe_unused,
173 void(*timer)(void *arg) __maybe_unused, 183 struct hist_browser_timer *hbt __maybe_unused,
174 void *arg __maybe_unused, 184 struct perf_session_env *env __maybe_unused)
175 int refresh __maybe_unused)
176{ 185{
177 return 0; 186 return 0;
178} 187}
@@ -180,10 +189,8 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
180static inline int hist_entry__tui_annotate(struct hist_entry *self 189static inline int hist_entry__tui_annotate(struct hist_entry *self
181 __maybe_unused, 190 __maybe_unused,
182 int evidx __maybe_unused, 191 int evidx __maybe_unused,
183 void(*timer)(void *arg) 192 struct hist_browser_timer *hbt
184 __maybe_unused, 193 __maybe_unused)
185 void *arg __maybe_unused,
186 int delay_secs __maybe_unused)
187{ 194{
188 return 0; 195 return 0;
189} 196}
@@ -199,15 +206,12 @@ static inline int script_browse(const char *script_opt)
199 206
200#ifdef GTK2_SUPPORT 207#ifdef GTK2_SUPPORT
201int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, 208int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
202 void(*timer)(void *arg), void *arg, 209 struct hist_browser_timer *hbt __maybe_unused);
203 int refresh);
204#else 210#else
205static inline 211static inline
206int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, 212int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
207 const char *help __maybe_unused, 213 const char *help __maybe_unused,
208 void(*timer)(void *arg) __maybe_unused, 214 struct hist_browser_timer *hbt __maybe_unused)
209 void *arg __maybe_unused,
210 int refresh __maybe_unused)
211{ 215{
212 return 0; 216 return 0;
213} 217}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 502eec0d4773..1f09d0581e6b 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -2,9 +2,192 @@
2#include "event.h" 2#include "event.h"
3#include "machine.h" 3#include "machine.h"
4#include "map.h" 4#include "map.h"
5#include "strlist.h"
5#include "thread.h" 6#include "thread.h"
6#include <stdbool.h> 7#include <stdbool.h>
7 8
9int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
10{
11 map_groups__init(&machine->kmaps);
12 RB_CLEAR_NODE(&machine->rb_node);
13 INIT_LIST_HEAD(&machine->user_dsos);
14 INIT_LIST_HEAD(&machine->kernel_dsos);
15
16 machine->threads = RB_ROOT;
17 INIT_LIST_HEAD(&machine->dead_threads);
18 machine->last_match = NULL;
19
20 machine->kmaps.machine = machine;
21 machine->pid = pid;
22
23 machine->root_dir = strdup(root_dir);
24 if (machine->root_dir == NULL)
25 return -ENOMEM;
26
27 if (pid != HOST_KERNEL_ID) {
28 struct thread *thread = machine__findnew_thread(machine, pid);
29 char comm[64];
30
31 if (thread == NULL)
32 return -ENOMEM;
33
34 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
35 thread__set_comm(thread, comm);
36 }
37
38 return 0;
39}
40
41static void dsos__delete(struct list_head *dsos)
42{
43 struct dso *pos, *n;
44
45 list_for_each_entry_safe(pos, n, dsos, node) {
46 list_del(&pos->node);
47 dso__delete(pos);
48 }
49}
50
51void machine__exit(struct machine *machine)
52{
53 map_groups__exit(&machine->kmaps);
54 dsos__delete(&machine->user_dsos);
55 dsos__delete(&machine->kernel_dsos);
56 free(machine->root_dir);
57 machine->root_dir = NULL;
58}
59
60void machine__delete(struct machine *machine)
61{
62 machine__exit(machine);
63 free(machine);
64}
65
66struct machine *machines__add(struct rb_root *machines, pid_t pid,
67 const char *root_dir)
68{
69 struct rb_node **p = &machines->rb_node;
70 struct rb_node *parent = NULL;
71 struct machine *pos, *machine = malloc(sizeof(*machine));
72
73 if (machine == NULL)
74 return NULL;
75
76 if (machine__init(machine, root_dir, pid) != 0) {
77 free(machine);
78 return NULL;
79 }
80
81 while (*p != NULL) {
82 parent = *p;
83 pos = rb_entry(parent, struct machine, rb_node);
84 if (pid < pos->pid)
85 p = &(*p)->rb_left;
86 else
87 p = &(*p)->rb_right;
88 }
89
90 rb_link_node(&machine->rb_node, parent, p);
91 rb_insert_color(&machine->rb_node, machines);
92
93 return machine;
94}
95
96struct machine *machines__find(struct rb_root *machines, pid_t pid)
97{
98 struct rb_node **p = &machines->rb_node;
99 struct rb_node *parent = NULL;
100 struct machine *machine;
101 struct machine *default_machine = NULL;
102
103 while (*p != NULL) {
104 parent = *p;
105 machine = rb_entry(parent, struct machine, rb_node);
106 if (pid < machine->pid)
107 p = &(*p)->rb_left;
108 else if (pid > machine->pid)
109 p = &(*p)->rb_right;
110 else
111 return machine;
112 if (!machine->pid)
113 default_machine = machine;
114 }
115
116 return default_machine;
117}
118
119struct machine *machines__findnew(struct rb_root *machines, pid_t pid)
120{
121 char path[PATH_MAX];
122 const char *root_dir = "";
123 struct machine *machine = machines__find(machines, pid);
124
125 if (machine && (machine->pid == pid))
126 goto out;
127
128 if ((pid != HOST_KERNEL_ID) &&
129 (pid != DEFAULT_GUEST_KERNEL_ID) &&
130 (symbol_conf.guestmount)) {
131 sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
132 if (access(path, R_OK)) {
133 static struct strlist *seen;
134
135 if (!seen)
136 seen = strlist__new(true, NULL);
137
138 if (!strlist__has_entry(seen, path)) {
139 pr_err("Can't access file %s\n", path);
140 strlist__add(seen, path);
141 }
142 machine = NULL;
143 goto out;
144 }
145 root_dir = path;
146 }
147
148 machine = machines__add(machines, pid, root_dir);
149out:
150 return machine;
151}
152
153void machines__process(struct rb_root *machines,
154 machine__process_t process, void *data)
155{
156 struct rb_node *nd;
157
158 for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
159 struct machine *pos = rb_entry(nd, struct machine, rb_node);
160 process(pos, data);
161 }
162}
163
164char *machine__mmap_name(struct machine *machine, char *bf, size_t size)
165{
166 if (machine__is_host(machine))
167 snprintf(bf, size, "[%s]", "kernel.kallsyms");
168 else if (machine__is_default_guest(machine))
169 snprintf(bf, size, "[%s]", "guest.kernel.kallsyms");
170 else {
171 snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms",
172 machine->pid);
173 }
174
175 return bf;
176}
177
178void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size)
179{
180 struct rb_node *node;
181 struct machine *machine;
182
183 for (node = rb_first(machines); node; node = rb_next(node)) {
184 machine = rb_entry(node, struct machine, rb_node);
185 machine->id_hdr_size = id_hdr_size;
186 }
187
188 return;
189}
190
8static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, 191static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid,
9 bool create) 192 bool create)
10{ 193{
@@ -84,15 +267,19 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
84static void machine__set_kernel_mmap_len(struct machine *machine, 267static void machine__set_kernel_mmap_len(struct machine *machine,
85 union perf_event *event) 268 union perf_event *event)
86{ 269{
87 machine->vmlinux_maps[MAP__FUNCTION]->start = event->mmap.start; 270 int i;
88 machine->vmlinux_maps[MAP__FUNCTION]->end = (event->mmap.start + 271
89 event->mmap.len); 272 for (i = 0; i < MAP__NR_TYPES; i++) {
90 /* 273 machine->vmlinux_maps[i]->start = event->mmap.start;
91 * Be a bit paranoid here, some perf.data file came with 274 machine->vmlinux_maps[i]->end = (event->mmap.start +
92 * a zero sized synthesized MMAP event for the kernel. 275 event->mmap.len);
93 */ 276 /*
94 if (machine->vmlinux_maps[MAP__FUNCTION]->end == 0) 277 * Be a bit paranoid here, some perf.data file came with
95 machine->vmlinux_maps[MAP__FUNCTION]->end = ~0ULL; 278 * a zero sized synthesized MMAP event for the kernel.
279 */
280 if (machine->vmlinux_maps[i]->end == 0)
281 machine->vmlinux_maps[i]->end = ~0ULL;
282 }
96} 283}
97 284
98static int machine__process_kernel_mmap_event(struct machine *machine, 285static int machine__process_kernel_mmap_event(struct machine *machine,
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index df152f1768be..b7cde7467d55 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -2,11 +2,40 @@
2#define __PERF_MACHINE_H 2#define __PERF_MACHINE_H
3 3
4#include <sys/types.h> 4#include <sys/types.h>
5#include <linux/rbtree.h>
6#include "map.h"
5 7
8struct branch_stack;
9struct perf_evsel;
10struct perf_sample;
11struct symbol;
6struct thread; 12struct thread;
7struct machine;
8union perf_event; 13union perf_event;
9 14
15/* Native host kernel uses -1 as pid index in machine */
16#define HOST_KERNEL_ID (-1)
17#define DEFAULT_GUEST_KERNEL_ID (0)
18
19struct machine {
20 struct rb_node rb_node;
21 pid_t pid;
22 u16 id_hdr_size;
23 char *root_dir;
24 struct rb_root threads;
25 struct list_head dead_threads;
26 struct thread *last_match;
27 struct list_head user_dsos;
28 struct list_head kernel_dsos;
29 struct map_groups kmaps;
30 struct map *vmlinux_maps[MAP__NR_TYPES];
31};
32
33static inline
34struct map *machine__kernel_map(struct machine *machine, enum map_type type)
35{
36 return machine->vmlinux_maps[type];
37}
38
10struct thread *machine__find_thread(struct machine *machine, pid_t pid); 39struct thread *machine__find_thread(struct machine *machine, pid_t pid);
11 40
12int machine__process_comm_event(struct machine *machine, union perf_event *event); 41int machine__process_comm_event(struct machine *machine, union perf_event *event);
@@ -16,4 +45,104 @@ int machine__process_lost_event(struct machine *machine, union perf_event *event
16int machine__process_mmap_event(struct machine *machine, union perf_event *event); 45int machine__process_mmap_event(struct machine *machine, union perf_event *event);
17int machine__process_event(struct machine *machine, union perf_event *event); 46int machine__process_event(struct machine *machine, union perf_event *event);
18 47
48typedef void (*machine__process_t)(struct machine *machine, void *data);
49
50void machines__process(struct rb_root *machines,
51 machine__process_t process, void *data);
52
53struct machine *machines__add(struct rb_root *machines, pid_t pid,
54 const char *root_dir);
55struct machine *machines__find_host(struct rb_root *machines);
56struct machine *machines__find(struct rb_root *machines, pid_t pid);
57struct machine *machines__findnew(struct rb_root *machines, pid_t pid);
58
59void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size);
60char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
61
62int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
63void machine__exit(struct machine *machine);
64void machine__delete(struct machine *machine);
65
66
67struct branch_info *machine__resolve_bstack(struct machine *machine,
68 struct thread *thread,
69 struct branch_stack *bs);
70int machine__resolve_callchain(struct machine *machine,
71 struct perf_evsel *evsel,
72 struct thread *thread,
73 struct perf_sample *sample,
74 struct symbol **parent);
75
76/*
77 * Default guest kernel is defined by parameter --guestkallsyms
78 * and --guestmodules
79 */
80static inline bool machine__is_default_guest(struct machine *machine)
81{
82 return machine ? machine->pid == DEFAULT_GUEST_KERNEL_ID : false;
83}
84
85static inline bool machine__is_host(struct machine *machine)
86{
87 return machine ? machine->pid == HOST_KERNEL_ID : false;
88}
89
90struct thread *machine__findnew_thread(struct machine *machine, pid_t pid);
91void machine__remove_thread(struct machine *machine, struct thread *th);
92
93size_t machine__fprintf(struct machine *machine, FILE *fp);
94
95static inline
96struct symbol *machine__find_kernel_symbol(struct machine *machine,
97 enum map_type type, u64 addr,
98 struct map **mapp,
99 symbol_filter_t filter)
100{
101 return map_groups__find_symbol(&machine->kmaps, type, addr,
102 mapp, filter);
103}
104
105static inline
106struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr,
107 struct map **mapp,
108 symbol_filter_t filter)
109{
110 return machine__find_kernel_symbol(machine, MAP__FUNCTION, addr,
111 mapp, filter);
112}
113
114static inline
115struct symbol *machine__find_kernel_function_by_name(struct machine *machine,
116 const char *name,
117 struct map **mapp,
118 symbol_filter_t filter)
119{
120 return map_groups__find_function_by_name(&machine->kmaps, name, mapp,
121 filter);
122}
123
124struct map *machine__new_module(struct machine *machine, u64 start,
125 const char *filename);
126
127int machine__load_kallsyms(struct machine *machine, const char *filename,
128 enum map_type type, symbol_filter_t filter);
129int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
130 symbol_filter_t filter);
131
132size_t machine__fprintf_dsos_buildid(struct machine *machine,
133 FILE *fp, bool with_hits);
134size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
135size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
136 FILE *fp, bool with_hits);
137
138void machine__destroy_kernel_maps(struct machine *machine);
139int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
140int machine__create_kernel_maps(struct machine *machine);
141
142int machines__create_kernel_maps(struct rb_root *machines, pid_t pid);
143int machines__create_guest_kernel_maps(struct rb_root *machines);
144void machines__destroy_guest_kernel_maps(struct rb_root *machines);
145
146size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
147
19#endif /* __PERF_MACHINE_H */ 148#endif /* __PERF_MACHINE_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 9b40c444039c..0328d45c4f2a 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -24,7 +24,7 @@ static inline int is_anon_memory(const char *filename)
24 24
25static inline int is_no_dso_memory(const char *filename) 25static inline int is_no_dso_memory(const char *filename)
26{ 26{
27 return !strcmp(filename, "[stack]") || 27 return !strncmp(filename, "[stack", 6) ||
28 !strcmp(filename, "[heap]"); 28 !strcmp(filename, "[heap]");
29} 29}
30 30
@@ -590,182 +590,3 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
590 590
591 return NULL; 591 return NULL;
592} 592}
593
594int machine__init(struct machine *self, const char *root_dir, pid_t pid)
595{
596 map_groups__init(&self->kmaps);
597 RB_CLEAR_NODE(&self->rb_node);
598 INIT_LIST_HEAD(&self->user_dsos);
599 INIT_LIST_HEAD(&self->kernel_dsos);
600
601 self->threads = RB_ROOT;
602 INIT_LIST_HEAD(&self->dead_threads);
603 self->last_match = NULL;
604
605 self->kmaps.machine = self;
606 self->pid = pid;
607 self->root_dir = strdup(root_dir);
608 if (self->root_dir == NULL)
609 return -ENOMEM;
610
611 if (pid != HOST_KERNEL_ID) {
612 struct thread *thread = machine__findnew_thread(self, pid);
613 char comm[64];
614
615 if (thread == NULL)
616 return -ENOMEM;
617
618 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
619 thread__set_comm(thread, comm);
620 }
621
622 return 0;
623}
624
625static void dsos__delete(struct list_head *self)
626{
627 struct dso *pos, *n;
628
629 list_for_each_entry_safe(pos, n, self, node) {
630 list_del(&pos->node);
631 dso__delete(pos);
632 }
633}
634
635void machine__exit(struct machine *self)
636{
637 map_groups__exit(&self->kmaps);
638 dsos__delete(&self->user_dsos);
639 dsos__delete(&self->kernel_dsos);
640 free(self->root_dir);
641 self->root_dir = NULL;
642}
643
644void machine__delete(struct machine *self)
645{
646 machine__exit(self);
647 free(self);
648}
649
650struct machine *machines__add(struct rb_root *self, pid_t pid,
651 const char *root_dir)
652{
653 struct rb_node **p = &self->rb_node;
654 struct rb_node *parent = NULL;
655 struct machine *pos, *machine = malloc(sizeof(*machine));
656
657 if (!machine)
658 return NULL;
659
660 if (machine__init(machine, root_dir, pid) != 0) {
661 free(machine);
662 return NULL;
663 }
664
665 while (*p != NULL) {
666 parent = *p;
667 pos = rb_entry(parent, struct machine, rb_node);
668 if (pid < pos->pid)
669 p = &(*p)->rb_left;
670 else
671 p = &(*p)->rb_right;
672 }
673
674 rb_link_node(&machine->rb_node, parent, p);
675 rb_insert_color(&machine->rb_node, self);
676
677 return machine;
678}
679
680struct machine *machines__find(struct rb_root *self, pid_t pid)
681{
682 struct rb_node **p = &self->rb_node;
683 struct rb_node *parent = NULL;
684 struct machine *machine;
685 struct machine *default_machine = NULL;
686
687 while (*p != NULL) {
688 parent = *p;
689 machine = rb_entry(parent, struct machine, rb_node);
690 if (pid < machine->pid)
691 p = &(*p)->rb_left;
692 else if (pid > machine->pid)
693 p = &(*p)->rb_right;
694 else
695 return machine;
696 if (!machine->pid)
697 default_machine = machine;
698 }
699
700 return default_machine;
701}
702
703struct machine *machines__findnew(struct rb_root *self, pid_t pid)
704{
705 char path[PATH_MAX];
706 const char *root_dir = "";
707 struct machine *machine = machines__find(self, pid);
708
709 if (machine && (machine->pid == pid))
710 goto out;
711
712 if ((pid != HOST_KERNEL_ID) &&
713 (pid != DEFAULT_GUEST_KERNEL_ID) &&
714 (symbol_conf.guestmount)) {
715 sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
716 if (access(path, R_OK)) {
717 static struct strlist *seen;
718
719 if (!seen)
720 seen = strlist__new(true, NULL);
721
722 if (!strlist__has_entry(seen, path)) {
723 pr_err("Can't access file %s\n", path);
724 strlist__add(seen, path);
725 }
726 machine = NULL;
727 goto out;
728 }
729 root_dir = path;
730 }
731
732 machine = machines__add(self, pid, root_dir);
733
734out:
735 return machine;
736}
737
738void machines__process(struct rb_root *self, machine__process_t process, void *data)
739{
740 struct rb_node *nd;
741
742 for (nd = rb_first(self); nd; nd = rb_next(nd)) {
743 struct machine *pos = rb_entry(nd, struct machine, rb_node);
744 process(pos, data);
745 }
746}
747
748char *machine__mmap_name(struct machine *self, char *bf, size_t size)
749{
750 if (machine__is_host(self))
751 snprintf(bf, size, "[%s]", "kernel.kallsyms");
752 else if (machine__is_default_guest(self))
753 snprintf(bf, size, "[%s]", "guest.kernel.kallsyms");
754 else
755 snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", self->pid);
756
757 return bf;
758}
759
760void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size)
761{
762 struct rb_node *node;
763 struct machine *machine;
764
765 for (node = rb_first(machines); node; node = rb_next(node)) {
766 machine = rb_entry(node, struct machine, rb_node);
767 machine->id_hdr_size = id_hdr_size;
768 }
769
770 return;
771}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index d2250fc97e25..bcb39e2a6965 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -57,30 +57,6 @@ struct map_groups {
57 struct machine *machine; 57 struct machine *machine;
58}; 58};
59 59
60/* Native host kernel uses -1 as pid index in machine */
61#define HOST_KERNEL_ID (-1)
62#define DEFAULT_GUEST_KERNEL_ID (0)
63
64struct machine {
65 struct rb_node rb_node;
66 pid_t pid;
67 u16 id_hdr_size;
68 char *root_dir;
69 struct rb_root threads;
70 struct list_head dead_threads;
71 struct thread *last_match;
72 struct list_head user_dsos;
73 struct list_head kernel_dsos;
74 struct map_groups kmaps;
75 struct map *vmlinux_maps[MAP__NR_TYPES];
76};
77
78static inline
79struct map *machine__kernel_map(struct machine *self, enum map_type type)
80{
81 return self->vmlinux_maps[type];
82}
83
84static inline struct kmap *map__kmap(struct map *self) 60static inline struct kmap *map__kmap(struct map *self)
85{ 61{
86 return (struct kmap *)(self + 1); 62 return (struct kmap *)(self + 1);
@@ -143,44 +119,9 @@ int map_groups__clone(struct map_groups *mg,
143size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp); 119size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp);
144size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp); 120size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp);
145 121
146typedef void (*machine__process_t)(struct machine *self, void *data);
147
148void machines__process(struct rb_root *self, machine__process_t process, void *data);
149struct machine *machines__add(struct rb_root *self, pid_t pid,
150 const char *root_dir);
151struct machine *machines__find_host(struct rb_root *self);
152struct machine *machines__find(struct rb_root *self, pid_t pid);
153struct machine *machines__findnew(struct rb_root *self, pid_t pid);
154void machines__set_id_hdr_size(struct rb_root *self, u16 id_hdr_size);
155char *machine__mmap_name(struct machine *self, char *bf, size_t size);
156int machine__init(struct machine *self, const char *root_dir, pid_t pid);
157void machine__exit(struct machine *self);
158void machine__delete(struct machine *self);
159
160struct perf_evsel;
161struct perf_sample;
162int machine__resolve_callchain(struct machine *machine,
163 struct perf_evsel *evsel,
164 struct thread *thread,
165 struct perf_sample *sample,
166 struct symbol **parent);
167int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, 122int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
168 u64 addr); 123 u64 addr);
169 124
170/*
171 * Default guest kernel is defined by parameter --guestkallsyms
172 * and --guestmodules
173 */
174static inline bool machine__is_default_guest(struct machine *self)
175{
176 return self ? self->pid == DEFAULT_GUEST_KERNEL_ID : false;
177}
178
179static inline bool machine__is_host(struct machine *self)
180{
181 return self ? self->pid == HOST_KERNEL_ID : false;
182}
183
184static inline void map_groups__insert(struct map_groups *mg, struct map *map) 125static inline void map_groups__insert(struct map_groups *mg, struct map *map)
185{ 126{
186 maps__insert(&mg->maps[map->type], map); 127 maps__insert(&mg->maps[map->type], map);
@@ -209,29 +150,6 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
209 struct map **mapp, 150 struct map **mapp,
210 symbol_filter_t filter); 151 symbol_filter_t filter);
211 152
212
213struct thread *machine__findnew_thread(struct machine *machine, pid_t pid);
214void machine__remove_thread(struct machine *machine, struct thread *th);
215
216size_t machine__fprintf(struct machine *machine, FILE *fp);
217
218static inline
219struct symbol *machine__find_kernel_symbol(struct machine *self,
220 enum map_type type, u64 addr,
221 struct map **mapp,
222 symbol_filter_t filter)
223{
224 return map_groups__find_symbol(&self->kmaps, type, addr, mapp, filter);
225}
226
227static inline
228struct symbol *machine__find_kernel_function(struct machine *self, u64 addr,
229 struct map **mapp,
230 symbol_filter_t filter)
231{
232 return machine__find_kernel_symbol(self, MAP__FUNCTION, addr, mapp, filter);
233}
234
235static inline 153static inline
236struct symbol *map_groups__find_function_by_name(struct map_groups *mg, 154struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
237 const char *name, struct map **mapp, 155 const char *name, struct map **mapp,
@@ -240,22 +158,11 @@ struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
240 return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp, filter); 158 return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp, filter);
241} 159}
242 160
243static inline
244struct symbol *machine__find_kernel_function_by_name(struct machine *self,
245 const char *name,
246 struct map **mapp,
247 symbol_filter_t filter)
248{
249 return map_groups__find_function_by_name(&self->kmaps, name, mapp,
250 filter);
251}
252
253int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 161int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
254 int verbose, FILE *fp); 162 int verbose, FILE *fp);
255 163
256struct map *map_groups__find_by_name(struct map_groups *mg, 164struct map *map_groups__find_by_name(struct map_groups *mg,
257 enum map_type type, const char *name); 165 enum map_type type, const char *name);
258struct map *machine__new_module(struct machine *self, u64 start, const char *filename);
259 166
260void map_groups__flush(struct map_groups *mg); 167void map_groups__flush(struct map_groups *mg);
261 168
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index c87efc12579d..66959fab6634 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -81,6 +81,7 @@ num_dec [0-9]+
81num_hex 0x[a-fA-F0-9]+ 81num_hex 0x[a-fA-F0-9]+
82num_raw_hex [a-fA-F0-9]+ 82num_raw_hex [a-fA-F0-9]+
83name [a-zA-Z_*?][a-zA-Z0-9_*?]* 83name [a-zA-Z_*?][a-zA-Z0-9_*?]*
84name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]*
84modifier_event [ukhpGH]{1,8} 85modifier_event [ukhpGH]{1,8}
85modifier_bp [rwx]{1,3} 86modifier_bp [rwx]{1,3}
86 87
@@ -168,6 +169,7 @@ period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
168branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } 169branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
169, { return ','; } 170, { return ','; }
170"/" { BEGIN(INITIAL); return '/'; } 171"/" { BEGIN(INITIAL); return '/'; }
172{name_minus} { return str(yyscanner, PE_NAME); }
171} 173}
172 174
173mem: { BEGIN(mem); return PE_PREFIX_MEM; } 175mem: { BEGIN(mem); return PE_PREFIX_MEM; }
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index dd6426163ba6..18d1222b05a2 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -4,6 +4,7 @@
4#include "hist.h" 4#include "hist.h"
5#include "event.h" 5#include "event.h"
6#include "header.h" 6#include "header.h"
7#include "machine.h"
7#include "symbol.h" 8#include "symbol.h"
8#include "thread.h" 9#include "thread.h"
9#include <linux/rbtree.h> 10#include <linux/rbtree.h>
@@ -68,10 +69,6 @@ int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel
68 struct ip_callchain *chain, 69 struct ip_callchain *chain,
69 struct symbol **parent); 70 struct symbol **parent);
70 71
71struct branch_info *machine__resolve_bstack(struct machine *self,
72 struct thread *thread,
73 struct branch_stack *bs);
74
75bool perf_session__has_traces(struct perf_session *self, const char *msg); 72bool perf_session__has_traces(struct perf_session *self, const char *msg);
76 73
77void mem_bswap_64(void *src, int byte_size); 74void mem_bswap_64(void *src, int byte_size);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 13761d83a5a0..b4e8c3ba559d 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -77,6 +77,10 @@ struct hist_entry_diff {
77struct hist_entry { 77struct hist_entry {
78 struct rb_node rb_node_in; 78 struct rb_node rb_node_in;
79 struct rb_node rb_node; 79 struct rb_node rb_node;
80 union {
81 struct list_head node;
82 struct list_head head;
83 } pairs;
80 struct he_stat stat; 84 struct he_stat stat;
81 struct map_symbol ms; 85 struct map_symbol ms;
82 struct thread *thread; 86 struct thread *thread;
@@ -96,15 +100,30 @@ struct hist_entry {
96 char *srcline; 100 char *srcline;
97 struct symbol *parent; 101 struct symbol *parent;
98 unsigned long position; 102 unsigned long position;
99 union { 103 struct rb_root sorted_chain;
100 struct hist_entry *pair;
101 struct rb_root sorted_chain;
102 };
103 struct branch_info *branch_info; 104 struct branch_info *branch_info;
104 struct hists *hists; 105 struct hists *hists;
105 struct callchain_root callchain[0]; 106 struct callchain_root callchain[0];
106}; 107};
107 108
109static inline bool hist_entry__has_pairs(struct hist_entry *he)
110{
111 return !list_empty(&he->pairs.node);
112}
113
114static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he)
115{
116 if (hist_entry__has_pairs(he))
117 return list_entry(he->pairs.node.next, struct hist_entry, pairs.node);
118 return NULL;
119}
120
121static inline void hist__entry_add_pair(struct hist_entry *he,
122 struct hist_entry *pair)
123{
124 list_add_tail(&he->pairs.head, &pair->pairs.node);
125}
126
108enum sort_type { 127enum sort_type {
109 SORT_PID, 128 SORT_PID,
110 SORT_COMM, 129 SORT_COMM,
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 624c65e6ab98..295f8d4feedf 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -12,6 +12,7 @@
12#include "build-id.h" 12#include "build-id.h"
13#include "util.h" 13#include "util.h"
14#include "debug.h" 14#include "debug.h"
15#include "machine.h"
15#include "symbol.h" 16#include "symbol.h"
16#include "strlist.h" 17#include "strlist.h"
17 18
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 863b05bea5ff..04ccf2962080 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -200,16 +200,6 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
200 symbol_filter_t filter); 200 symbol_filter_t filter);
201int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 201int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
202 symbol_filter_t filter); 202 symbol_filter_t filter);
203int machine__load_kallsyms(struct machine *machine, const char *filename,
204 enum map_type type, symbol_filter_t filter);
205int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
206 symbol_filter_t filter);
207
208size_t machine__fprintf_dsos_buildid(struct machine *machine,
209 FILE *fp, bool with_hits);
210size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
211size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
212 FILE *fp, bool with_hits);
213 203
214struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, 204struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
215 u64 addr); 205 u64 addr);
@@ -224,14 +214,6 @@ int kallsyms__parse(const char *filename, void *arg,
224int filename__read_debuglink(const char *filename, char *debuglink, 214int filename__read_debuglink(const char *filename, char *debuglink,
225 size_t size); 215 size_t size);
226 216
227void machine__destroy_kernel_maps(struct machine *machine);
228int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel);
229int machine__create_kernel_maps(struct machine *machine);
230
231int machines__create_kernel_maps(struct rb_root *machines, pid_t pid);
232int machines__create_guest_kernel_maps(struct rb_root *machines);
233void machines__destroy_guest_kernel_maps(struct rb_root *machines);
234
235int symbol__init(void); 217int symbol__init(void);
236void symbol__exit(void); 218void symbol__exit(void);
237void symbol__elf_init(void); 219void symbol__elf_init(void);
@@ -242,8 +224,6 @@ size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
242size_t symbol__fprintf(struct symbol *sym, FILE *fp); 224size_t symbol__fprintf(struct symbol *sym, FILE *fp);
243bool symbol_type__is_a(char symbol_type, enum map_type map_type); 225bool symbol_type__is_a(char symbol_type, enum map_type map_type);
244 226
245size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
246
247int dso__test_data(void); 227int dso__test_data(void);
248int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 228int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
249 struct symsrc *runtime_ss, symbol_filter_t filter, 229 struct symsrc *runtime_ss, symbol_filter_t filter,