aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-10-05 04:04:33 -0400
committerIngo Molnar <mingo@kernel.org>2012-10-05 04:04:33 -0400
commitc942ee2e62dff1a7bc6f809965e93e46808d554c (patch)
tree430d4730be24416f03fd992017e47605342d9b61 /tools
parente717bf4e4fe8adc519f25c4ff93ee50ed0a36710 (diff)
parent139c0815903de1a7865fe1d6beac5e995fefdf46 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: * Remove several cases of needless global variables, on most builtins. * Look up thread using tid instead of pid in 'perf sched'. * Move global variables into a perf_kvm struct, from David Ahern. * Hists refactorings, preparatory for improved 'diff' command, from Jiri Olsa. * Hists refactorings, preparatory for event group viewieng work, from Namhyung Kim. * Remove double negation on optional feature macro definitions, from Namhyung Kim. * Bash auto completion improvements, now we can auto complete the tools long options, tracepoint event names, etc, from Namhyung Kim. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Makefile83
-rw-r--r--tools/perf/bash_completion50
-rw-r--r--tools/perf/builtin-buildid-cache.c58
-rw-r--r--tools/perf/builtin-buildid-list.c55
-rw-r--r--tools/perf/builtin-diff.c68
-rw-r--r--tools/perf/builtin-evlist.c21
-rw-r--r--tools/perf/builtin-help.c40
-rw-r--r--tools/perf/builtin-inject.c88
-rw-r--r--tools/perf/builtin-kmem.c66
-rw-r--r--tools/perf/builtin-kvm.c460
-rw-r--r--tools/perf/builtin-lock.c90
-rw-r--r--tools/perf/builtin-probe.c26
-rw-r--r--tools/perf/builtin-record.c27
-rw-r--r--tools/perf/builtin-report.c4
-rw-r--r--tools/perf/builtin-sched.c2
-rw-r--r--tools/perf/builtin-script.c90
-rw-r--r--tools/perf/builtin-stat.c328
-rw-r--r--tools/perf/builtin-timechart.c100
-rw-r--r--tools/perf/builtin-top.c11
-rw-r--r--tools/perf/builtin-trace.c134
-rw-r--r--tools/perf/perf.c4
-rw-r--r--tools/perf/ui/browsers/hists.c12
-rw-r--r--tools/perf/ui/gtk/browser.c6
-rw-r--r--tools/perf/ui/gtk/util.c2
-rw-r--r--tools/perf/ui/helpline.h18
-rw-r--r--tools/perf/ui/hist.c145
-rw-r--r--tools/perf/ui/setup.c2
-rw-r--r--tools/perf/ui/stdio/hist.c45
-rw-r--r--tools/perf/util/annotate.h8
-rw-r--r--tools/perf/util/cache.h38
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/debug.h17
-rw-r--r--tools/perf/util/evlist.c88
-rw-r--r--tools/perf/util/evlist.h18
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh4
-rw-r--r--tools/perf/util/hist.c66
-rw-r--r--tools/perf/util/hist.h38
-rw-r--r--tools/perf/util/map.c2
-rw-r--r--tools/perf/util/parse-options.c8
-rw-r--r--tools/perf/util/parse-options.h1
-rw-r--r--tools/perf/util/path.c2
-rw-r--r--tools/perf/util/perf_regs.h4
-rw-r--r--tools/perf/util/sort.h19
-rw-r--r--tools/perf/util/symbol.h10
-rw-r--r--tools/perf/util/unwind.h4
-rw-r--r--tools/perf/util/util.c4
46 files changed, 1193 insertions, 1175 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e5e71e7d95a0..f9126f89efef 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -45,6 +45,8 @@ include config/utilities.mak
45# 45#
46# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf 46# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
47# backtrace post unwind. 47# backtrace post unwind.
48#
49# Define NO_BACKTRACE if you do not want stack backtrace debug feature
48 50
49$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE 51$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
50 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) 52 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
@@ -185,7 +187,7 @@ strip-libs = $(filter-out -l%,$(1))
185PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 187PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
186PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py 188PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
187 189
188$(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 190$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
189 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 191 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
190 --quiet build_ext; \ 192 --quiet build_ext; \
191 mkdir -p $(OUTPUT)python && \ 193 mkdir -p $(OUTPUT)python && \
@@ -446,20 +448,6 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
446 448
447PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT) 449PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
448 450
449# Files needed for the python binding, perf.so
450# pyrf is just an internal name needed for all those wrappers.
451# This has to be in sync with what is in the 'sources' variable in
452# tools/perf/util/setup.py
453
454PYRF_OBJS += $(OUTPUT)util/cpumap.o
455PYRF_OBJS += $(OUTPUT)util/ctype.o
456PYRF_OBJS += $(OUTPUT)util/evlist.o
457PYRF_OBJS += $(OUTPUT)util/evsel.o
458PYRF_OBJS += $(OUTPUT)util/python.o
459PYRF_OBJS += $(OUTPUT)util/thread_map.o
460PYRF_OBJS += $(OUTPUT)util/util.o
461PYRF_OBJS += $(OUTPUT)util/xyarray.o
462
463# 451#
464# Platform specific tweaks 452# Platform specific tweaks
465# 453#
@@ -486,7 +474,13 @@ ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
486 NO_DWARF := 1 474 NO_DWARF := 1
487 NO_DEMANGLE := 1 475 NO_DEMANGLE := 1
488 endif 476 endif
489endif 477else
478 FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
479 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
480 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);
481 NO_DWARF := 1
482 endif # Dwarf support
483endif # SOURCE_LIBELF
490endif # NO_LIBELF 484endif # NO_LIBELF
491 485
492ifndef NO_LIBUNWIND 486ifndef NO_LIBUNWIND
@@ -511,8 +505,6 @@ ifneq ($(OUTPUT),)
511endif 505endif
512 506
513ifdef NO_LIBELF 507ifdef NO_LIBELF
514BASIC_CFLAGS += -DNO_LIBELF_SUPPORT
515
516EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) 508EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
517 509
518# Remove ELF/DWARF dependent codes 510# Remove ELF/DWARF dependent codes
@@ -527,17 +519,12 @@ BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
527LIB_OBJS += $(OUTPUT)util/symbol-minimal.o 519LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
528 520
529else # NO_LIBELF 521else # NO_LIBELF
522BASIC_CFLAGS += -DLIBELF_SUPPORT
530 523
531ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y) 524ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
532 BASIC_CFLAGS += -DLIBELF_NO_MMAP 525 BASIC_CFLAGS += -DLIBELF_MMAP
533endif 526endif
534 527
535FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
536ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
537 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);
538 NO_DWARF := 1
539endif # Dwarf support
540
541ifndef NO_DWARF 528ifndef NO_DWARF
542ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 529ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
543 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 530 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
@@ -550,38 +537,33 @@ endif # PERF_HAVE_DWARF_REGS
550endif # NO_DWARF 537endif # NO_DWARF
551endif # NO_LIBELF 538endif # NO_LIBELF
552 539
553ifdef NO_LIBUNWIND 540ifndef NO_LIBUNWIND
554 BASIC_CFLAGS += -DNO_LIBUNWIND_SUPPORT 541 BASIC_CFLAGS += -DLIBUNWIND_SUPPORT
555else
556 EXTLIBS += $(LIBUNWIND_LIBS) 542 EXTLIBS += $(LIBUNWIND_LIBS)
557 BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS) 543 BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS)
558 BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS) 544 BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS)
559 LIB_OBJS += $(OUTPUT)util/unwind.o 545 LIB_OBJS += $(OUTPUT)util/unwind.o
560endif 546endif
561 547
562ifdef NO_LIBAUDIT 548ifndef NO_LIBAUDIT
563 BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
564else
565 FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit 549 FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
566 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y) 550 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y)
567 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev); 551 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
568 BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
569 else 552 else
553 BASIC_CFLAGS += -DLIBAUDIT_SUPPORT
570 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o 554 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
571 EXTLIBS += -laudit 555 EXTLIBS += -laudit
572 endif 556 endif
573endif 557endif
574 558
575ifdef NO_NEWT 559ifndef NO_NEWT
576 BASIC_CFLAGS += -DNO_NEWT_SUPPORT
577else
578 FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt 560 FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt
579 ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y) 561 ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y)
580 msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); 562 msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
581 BASIC_CFLAGS += -DNO_NEWT_SUPPORT
582 else 563 else
583 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h 564 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
584 BASIC_CFLAGS += -I/usr/include/slang 565 BASIC_CFLAGS += -I/usr/include/slang
566 BASIC_CFLAGS += -DNEWT_SUPPORT
585 EXTLIBS += -lnewt -lslang 567 EXTLIBS += -lnewt -lslang
586 LIB_OBJS += $(OUTPUT)ui/setup.o 568 LIB_OBJS += $(OUTPUT)ui/setup.o
587 LIB_OBJS += $(OUTPUT)ui/browser.o 569 LIB_OBJS += $(OUTPUT)ui/browser.o
@@ -603,17 +585,15 @@ else
603 endif 585 endif
604endif 586endif
605 587
606ifdef NO_GTK2 588ifndef NO_GTK2
607 BASIC_CFLAGS += -DNO_GTK2_SUPPORT
608else
609 FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) 589 FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
610 ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y) 590 ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
611 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); 591 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
612 BASIC_CFLAGS += -DNO_GTK2_SUPPORT
613 else 592 else
614 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y) 593 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
615 BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR 594 BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
616 endif 595 endif
596 BASIC_CFLAGS += -DGTK2_SUPPORT
617 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) 597 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
618 EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null) 598 EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
619 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o 599 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
@@ -621,7 +601,7 @@ else
621 LIB_OBJS += $(OUTPUT)ui/gtk/util.o 601 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
622 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o 602 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
623 # Make sure that it'd be included only once. 603 # Make sure that it'd be included only once.
624 ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),) 604 ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
625 LIB_OBJS += $(OUTPUT)ui/setup.o 605 LIB_OBJS += $(OUTPUT)ui/setup.o
626 LIB_OBJS += $(OUTPUT)ui/util.o 606 LIB_OBJS += $(OUTPUT)ui/util.o
627 endif 607 endif
@@ -762,23 +742,18 @@ ifeq ($(NO_PERF_REGS),0)
762 ifeq ($(ARCH),x86) 742 ifeq ($(ARCH),x86)
763 LIB_H += arch/x86/include/perf_regs.h 743 LIB_H += arch/x86/include/perf_regs.h
764 endif 744 endif
765else 745 BASIC_CFLAGS += -DHAVE_PERF_REGS
766 BASIC_CFLAGS += -DNO_PERF_REGS
767endif 746endif
768 747
769ifdef NO_STRLCPY 748ifndef NO_STRLCPY
770 BASIC_CFLAGS += -DNO_STRLCPY 749 ifeq ($(call try-cc,$(SOURCE_STRLCPY),),y)
771else 750 BASIC_CFLAGS += -DHAVE_STRLCPY
772 ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y)
773 BASIC_CFLAGS += -DNO_STRLCPY
774 endif 751 endif
775endif 752endif
776 753
777ifdef NO_BACKTRACE 754ifndef NO_BACKTRACE
778 BASIC_CFLAGS += -DNO_BACKTRACE 755 ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
779else 756 BASIC_CFLAGS += -DBACKTRACE_SUPPORT
780 ifneq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
781 BASIC_CFLAGS += -DNO_BACKTRACE
782 endif 757 endif
783endif 758endif
784 759
diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index 1958fa539d0f..56e6a12aab59 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -1,23 +1,59 @@
1# perf completion 1# perf completion
2 2
3function_exists()
4{
5 declare -F $1 > /dev/null
6 return $?
7}
8
9function_exists __ltrim_colon_completions ||
10__ltrim_colon_completions()
11{
12 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
13 # Remove colon-word prefix from COMPREPLY items
14 local colon_word=${1%${1##*:}}
15 local i=${#COMPREPLY[*]}
16 while [[ $((--i)) -ge 0 ]]; do
17 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
18 done
19 fi
20}
21
3have perf && 22have perf &&
4_perf() 23_perf()
5{ 24{
6 local cur cmd 25 local cur prev cmd
7 26
8 COMPREPLY=() 27 COMPREPLY=()
9 _get_comp_words_by_ref cur prev 28 if function_exists _get_comp_words_by_ref; then
29 _get_comp_words_by_ref -n : cur prev
30 else
31 cur=$(_get_cword :)
32 prev=${COMP_WORDS[COMP_CWORD-1]}
33 fi
10 34
11 cmd=${COMP_WORDS[0]} 35 cmd=${COMP_WORDS[0]}
12 36
13 # List perf subcommands 37 # List perf subcommands or long options
14 if [ $COMP_CWORD -eq 1 ]; then 38 if [ $COMP_CWORD -eq 1 ]; then
15 cmds=$($cmd --list-cmds) 39 if [[ $cur == --* ]]; then
16 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) 40 COMPREPLY=( $( compgen -W '--help --version \
41 --exec-path --html-path --paginate --no-pager \
42 --perf-dir --work-tree --debugfs-dir' -- "$cur" ) )
43 else
44 cmds=$($cmd --list-cmds)
45 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
46 fi
17 # List possible events for -e option 47 # List possible events for -e option
18 elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then 48 elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
19 cmds=$($cmd list --raw-dump) 49 evts=$($cmd list --raw-dump)
20 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) 50 COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
51 __ltrim_colon_completions $cur
52 # List long option names
53 elif [[ $cur == --* ]]; then
54 subcmd=${COMP_WORDS[1]}
55 opts=$($cmd $subcmd --list-opts)
56 COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
21 # Fall down to list regular files 57 # Fall down to list regular files
22 else 58 else
23 _filedir 59 _filedir
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 83654557e108..d37e077f4b14 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -15,22 +15,6 @@
15#include "util/strlist.h" 15#include "util/strlist.h"
16#include "util/symbol.h" 16#include "util/symbol.h"
17 17
18static char const *add_name_list_str, *remove_name_list_str;
19
20static const char * const buildid_cache_usage[] = {
21 "perf buildid-cache [<options>]",
22 NULL
23};
24
25static const struct option buildid_cache_options[] = {
26 OPT_STRING('a', "add", &add_name_list_str,
27 "file list", "file(s) to add"),
28 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
29 "file(s) to remove"),
30 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
31 OPT_END()
32};
33
34static int build_id_cache__add_file(const char *filename, const char *debugdir) 18static int build_id_cache__add_file(const char *filename, const char *debugdir)
35{ 19{
36 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 20 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -51,8 +35,8 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
51 return err; 35 return err;
52} 36}
53 37
54static int build_id_cache__remove_file(const char *filename __maybe_unused, 38static int build_id_cache__remove_file(const char *filename,
55 const char *debugdir __maybe_unused) 39 const char *debugdir)
56{ 40{
57 u8 build_id[BUILD_ID_SIZE]; 41 u8 build_id[BUILD_ID_SIZE];
58 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 42 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -73,11 +57,34 @@ static int build_id_cache__remove_file(const char *filename __maybe_unused,
73 return err; 57 return err;
74} 58}
75 59
76static int __cmd_buildid_cache(void) 60int cmd_buildid_cache(int argc, const char **argv,
61 const char *prefix __maybe_unused)
77{ 62{
78 struct strlist *list; 63 struct strlist *list;
79 struct str_node *pos; 64 struct str_node *pos;
80 char debugdir[PATH_MAX]; 65 char debugdir[PATH_MAX];
66 char const *add_name_list_str = NULL,
67 *remove_name_list_str = NULL;
68 const struct option buildid_cache_options[] = {
69 OPT_STRING('a', "add", &add_name_list_str,
70 "file list", "file(s) to add"),
71 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
72 "file(s) to remove"),
73 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
74 OPT_END()
75 };
76 const char * const buildid_cache_usage[] = {
77 "perf buildid-cache [<options>]",
78 NULL
79 };
80
81 argc = parse_options(argc, argv, buildid_cache_options,
82 buildid_cache_usage, 0);
83
84 if (symbol__init() < 0)
85 return -1;
86
87 setup_pager();
81 88
82 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); 89 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
83 90
@@ -119,16 +126,3 @@ static int __cmd_buildid_cache(void)
119 126
120 return 0; 127 return 0;
121} 128}
122
123int cmd_buildid_cache(int argc, const char **argv,
124 const char *prefix __maybe_unused)
125{
126 argc = parse_options(argc, argv, buildid_cache_options,
127 buildid_cache_usage, 0);
128
129 if (symbol__init() < 0)
130 return -1;
131
132 setup_pager();
133 return __cmd_buildid_cache();
134}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 1159feeebb19..a0e94fffa03e 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -16,27 +16,6 @@
16#include "util/session.h" 16#include "util/session.h"
17#include "util/symbol.h" 17#include "util/symbol.h"
18 18
19static const char *input_name;
20static bool force;
21static bool show_kernel;
22static bool with_hits;
23
24static const char * const buildid_list_usage[] = {
25 "perf buildid-list [<options>]",
26 NULL
27};
28
29static const struct option options[] = {
30 OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
31 OPT_STRING('i', "input", &input_name, "file",
32 "input file name"),
33 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
34 OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
35 OPT_INCR('v', "verbose", &verbose,
36 "be more verbose"),
37 OPT_END()
38};
39
40static int sysfs__fprintf_build_id(FILE *fp) 19static int sysfs__fprintf_build_id(FILE *fp)
41{ 20{
42 u8 kallsyms_build_id[BUILD_ID_SIZE]; 21 u8 kallsyms_build_id[BUILD_ID_SIZE];
@@ -65,7 +44,8 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
65 return fprintf(fp, "%s\n", sbuild_id); 44 return fprintf(fp, "%s\n", sbuild_id);
66} 45}
67 46
68static int perf_session__list_build_ids(void) 47static int perf_session__list_build_ids(const char *input_name,
48 bool force, bool with_hits)
69{ 49{
70 struct perf_session *session; 50 struct perf_session *session;
71 51
@@ -95,18 +75,31 @@ out:
95 return 0; 75 return 0;
96} 76}
97 77
98static int __cmd_buildid_list(void)
99{
100 if (show_kernel)
101 return sysfs__fprintf_build_id(stdout);
102
103 return perf_session__list_build_ids();
104}
105
106int cmd_buildid_list(int argc, const char **argv, 78int cmd_buildid_list(int argc, const char **argv,
107 const char *prefix __maybe_unused) 79 const char *prefix __maybe_unused)
108{ 80{
81 bool show_kernel = false;
82 bool with_hits = false;
83 bool force = false;
84 const char *input_name = NULL;
85 const struct option options[] = {
86 OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
87 OPT_STRING('i', "input", &input_name, "file", "input file name"),
88 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
89 OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
90 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
91 OPT_END()
92 };
93 const char * const buildid_list_usage[] = {
94 "perf buildid-list [<options>]",
95 NULL
96 };
97
109 argc = parse_options(argc, argv, options, buildid_list_usage, 0); 98 argc = parse_options(argc, argv, options, buildid_list_usage, 0);
110 setup_pager(); 99 setup_pager();
111 return __cmd_buildid_list(); 100
101 if (show_kernel)
102 return sysfs__fprintf_build_id(stdout);
103
104 return perf_session__list_build_ids(input_name, force, with_hits);
112} 105}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 761f4197a9e2..a0b531c14b97 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -70,8 +70,8 @@ static struct perf_tool tool = {
70 .ordering_requires_timestamps = true, 70 .ordering_requires_timestamps = true,
71}; 71};
72 72
73static void perf_session__insert_hist_entry_by_name(struct rb_root *root, 73static void insert_hist_entry_by_name(struct rb_root *root,
74 struct hist_entry *he) 74 struct hist_entry *he)
75{ 75{
76 struct rb_node **p = &root->rb_node; 76 struct rb_node **p = &root->rb_node;
77 struct rb_node *parent = NULL; 77 struct rb_node *parent = NULL;
@@ -90,7 +90,7 @@ static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
90 rb_insert_color(&he->rb_node, root); 90 rb_insert_color(&he->rb_node, root);
91} 91}
92 92
93static void hists__resort_entries(struct hists *self) 93static void hists__name_resort(struct hists *self, bool sort)
94{ 94{
95 unsigned long position = 1; 95 unsigned long position = 1;
96 struct rb_root tmp = RB_ROOT; 96 struct rb_root tmp = RB_ROOT;
@@ -100,12 +100,16 @@ static void hists__resort_entries(struct hists *self)
100 struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); 100 struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);
101 101
102 next = rb_next(&n->rb_node); 102 next = rb_next(&n->rb_node);
103 rb_erase(&n->rb_node, &self->entries);
104 n->position = position++; 103 n->position = position++;
105 perf_session__insert_hist_entry_by_name(&tmp, n); 104
105 if (sort) {
106 rb_erase(&n->rb_node, &self->entries);
107 insert_hist_entry_by_name(&tmp, n);
108 }
106 } 109 }
107 110
108 self->entries = tmp; 111 if (sort)
112 self->entries = tmp;
109} 113}
110 114
111static struct hist_entry *hists__find_entry(struct hists *self, 115static struct hist_entry *hists__find_entry(struct hists *self,
@@ -121,7 +125,7 @@ static struct hist_entry *hists__find_entry(struct hists *self,
121 n = n->rb_left; 125 n = n->rb_left;
122 else if (cmp > 0) 126 else if (cmp > 0)
123 n = n->rb_right; 127 n = n->rb_right;
124 else 128 else
125 return iter; 129 return iter;
126 } 130 }
127 131
@@ -150,6 +154,24 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
150 return NULL; 154 return NULL;
151} 155}
152 156
157static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
158{
159 struct perf_evsel *evsel;
160
161 list_for_each_entry(evsel, &evlist->entries, node) {
162 struct hists *hists = &evsel->hists;
163
164 hists__output_resort(hists);
165
166 /*
167 * The hists__name_resort only sets possition
168 * if name is false.
169 */
170 if (name || ((!name) && show_displacement))
171 hists__name_resort(hists, name);
172 }
173}
174
153static int __cmd_diff(void) 175static int __cmd_diff(void)
154{ 176{
155 int ret, i; 177 int ret, i;
@@ -176,15 +198,8 @@ static int __cmd_diff(void)
176 evlist_old = older->evlist; 198 evlist_old = older->evlist;
177 evlist_new = newer->evlist; 199 evlist_new = newer->evlist;
178 200
179 list_for_each_entry(evsel, &evlist_new->entries, node) 201 perf_evlist__resort_hists(evlist_old, true);
180 hists__output_resort(&evsel->hists); 202 perf_evlist__resort_hists(evlist_new, false);
181
182 list_for_each_entry(evsel, &evlist_old->entries, node) {
183 hists__output_resort(&evsel->hists);
184
185 if (show_displacement)
186 hists__resort_entries(&evsel->hists);
187 }
188 203
189 list_for_each_entry(evsel, &evlist_new->entries, node) { 204 list_for_each_entry(evsel, &evlist_new->entries, node) {
190 struct perf_evsel *evsel_old; 205 struct perf_evsel *evsel_old;
@@ -199,8 +214,7 @@ static int __cmd_diff(void)
199 first = false; 214 first = false;
200 215
201 hists__match(&evsel_old->hists, &evsel->hists); 216 hists__match(&evsel_old->hists, &evsel->hists);
202 hists__fprintf(&evsel->hists, &evsel_old->hists, 217 hists__fprintf(&evsel->hists, true, 0, 0, stdout);
203 show_displacement, true, 0, 0, stdout);
204 } 218 }
205 219
206out_delete: 220out_delete:
@@ -242,6 +256,21 @@ static const struct option options[] = {
242 OPT_END() 256 OPT_END()
243}; 257};
244 258
259static void ui_init(void)
260{
261 perf_hpp__init();
262
263 /* No overhead column. */
264 perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
265
266 /* Display baseline/delta/displacement columns. */
267 perf_hpp__column_enable(PERF_HPP__BASELINE, true);
268 perf_hpp__column_enable(PERF_HPP__DELTA, true);
269
270 if (show_displacement)
271 perf_hpp__column_enable(PERF_HPP__DISPL, true);
272}
273
245int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) 274int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
246{ 275{
247 sort_order = diff__default_sort_order; 276 sort_order = diff__default_sort_order;
@@ -264,7 +293,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
264 if (symbol__init() < 0) 293 if (symbol__init() < 0)
265 return -1; 294 return -1;
266 295
267 perf_hpp__init(true, show_displacement); 296 ui_init();
297
268 setup_sorting(diff_usage, options); 298 setup_sorting(diff_usage, options);
269 setup_pager(); 299 setup_pager();
270 300
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 1fb164164fd0..997afb82691b 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -108,23 +108,20 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
108 return 0; 108 return 0;
109} 109}
110 110
111static const char * const evlist_usage[] = {
112 "perf evlist [<options>]",
113 NULL
114};
115
116int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) 111int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
117{ 112{
118 struct perf_attr_details details = { .verbose = false, }; 113 struct perf_attr_details details = { .verbose = false, };
119 const char *input_name = NULL; 114 const char *input_name = NULL;
120 const struct option options[] = { 115 const struct option options[] = {
121 OPT_STRING('i', "input", &input_name, "file", 116 OPT_STRING('i', "input", &input_name, "file", "Input file name"),
122 "Input file name"), 117 OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"),
123 OPT_BOOLEAN('F', "freq", &details.freq, 118 OPT_BOOLEAN('v', "verbose", &details.verbose,
124 "Show the sample frequency"), 119 "Show all event attr details"),
125 OPT_BOOLEAN('v', "verbose", &details.verbose, 120 OPT_END()
126 "Show all event attr details"), 121 };
127 OPT_END() 122 const char * const evlist_usage[] = {
123 "perf evlist [<options>]",
124 NULL
128 }; 125 };
129 126
130 argc = parse_options(argc, argv, options, evlist_usage, 0); 127 argc = parse_options(argc, argv, options, evlist_usage, 0);
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 25c8b942ff85..411ee5664e98 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -30,23 +30,6 @@ enum help_format {
30 HELP_FORMAT_WEB, 30 HELP_FORMAT_WEB,
31}; 31};
32 32
33static bool show_all = false;
34static enum help_format help_format = HELP_FORMAT_NONE;
35static struct option builtin_help_options[] = {
36 OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
37 OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
38 OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
39 HELP_FORMAT_WEB),
40 OPT_SET_UINT('i', "info", &help_format, "show info page",
41 HELP_FORMAT_INFO),
42 OPT_END(),
43};
44
45static const char * const builtin_help_usage[] = {
46 "perf help [--all] [--man|--web|--info] [command]",
47 NULL
48};
49
50static enum help_format parse_help_format(const char *format) 33static enum help_format parse_help_format(const char *format)
51{ 34{
52 if (!strcmp(format, "man")) 35 if (!strcmp(format, "man"))
@@ -258,11 +241,13 @@ static int add_man_viewer_info(const char *var, const char *value)
258 241
259static int perf_help_config(const char *var, const char *value, void *cb) 242static int perf_help_config(const char *var, const char *value, void *cb)
260{ 243{
244 enum help_format *help_formatp = cb;
245
261 if (!strcmp(var, "help.format")) { 246 if (!strcmp(var, "help.format")) {
262 if (!value) 247 if (!value)
263 return config_error_nonbool(var); 248 return config_error_nonbool(var);
264 help_format = parse_help_format(value); 249 *help_formatp = parse_help_format(value);
265 if (help_format == HELP_FORMAT_NONE) 250 if (*help_formatp == HELP_FORMAT_NONE)
266 return -1; 251 return -1;
267 return 0; 252 return 0;
268 } 253 }
@@ -428,12 +413,27 @@ static int show_html_page(const char *perf_cmd)
428 413
429int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) 414int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
430{ 415{
416 bool show_all = false;
417 enum help_format help_format = HELP_FORMAT_NONE;
418 struct option builtin_help_options[] = {
419 OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
420 OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
421 OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
422 HELP_FORMAT_WEB),
423 OPT_SET_UINT('i', "info", &help_format, "show info page",
424 HELP_FORMAT_INFO),
425 OPT_END(),
426 };
427 const char * const builtin_help_usage[] = {
428 "perf help [--all] [--man|--web|--info] [command]",
429 NULL
430 };
431 const char *alias; 431 const char *alias;
432 int rc = 0; 432 int rc = 0;
433 433
434 load_command_list("perf-", &main_cmds, &other_cmds); 434 load_command_list("perf-", &main_cmds, &other_cmds);
435 435
436 perf_config(perf_help_config, NULL); 436 perf_config(perf_help_config, &help_format);
437 437
438 argc = parse_options(argc, argv, builtin_help_options, 438 argc = parse_options(argc, argv, builtin_help_options,
439 builtin_help_usage, 0); 439 builtin_help_usage, 0);
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 1eaa6617c814..4688bea95c12 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -14,8 +14,10 @@
14 14
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16 16
17static char const *input_name = "-"; 17struct perf_inject {
18static bool inject_build_ids; 18 struct perf_tool tool;
19 bool build_ids;
20};
19 21
20static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused, 22static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused,
21 union perf_event *event, 23 union perf_event *event,
@@ -194,7 +196,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
194 * account this as unresolved. 196 * account this as unresolved.
195 */ 197 */
196 } else { 198 } else {
197#ifndef NO_LIBELF_SUPPORT 199#ifdef LIBELF_SUPPORT
198 pr_warning("no symbols found in %s, maybe " 200 pr_warning("no symbols found in %s, maybe "
199 "install a debug package?\n", 201 "install a debug package?\n",
200 al.map->dso->long_name); 202 al.map->dso->long_name);
@@ -208,22 +210,6 @@ repipe:
208 return 0; 210 return 0;
209} 211}
210 212
211struct perf_tool perf_inject = {
212 .sample = perf_event__repipe_sample,
213 .mmap = perf_event__repipe,
214 .comm = perf_event__repipe,
215 .fork = perf_event__repipe,
216 .exit = perf_event__repipe,
217 .lost = perf_event__repipe,
218 .read = perf_event__repipe_sample,
219 .throttle = perf_event__repipe,
220 .unthrottle = perf_event__repipe,
221 .attr = perf_event__repipe_attr,
222 .event_type = perf_event__repipe_event_type_synth,
223 .tracing_data = perf_event__repipe_tracing_data_synth,
224 .build_id = perf_event__repipe_op2_synth,
225};
226
227extern volatile int session_done; 213extern volatile int session_done;
228 214
229static void sig_handler(int sig __maybe_unused) 215static void sig_handler(int sig __maybe_unused)
@@ -231,56 +217,72 @@ static void sig_handler(int sig __maybe_unused)
231 session_done = 1; 217 session_done = 1;
232} 218}
233 219
234static int __cmd_inject(void) 220static int __cmd_inject(struct perf_inject *inject)
235{ 221{
236 struct perf_session *session; 222 struct perf_session *session;
237 int ret = -EINVAL; 223 int ret = -EINVAL;
238 224
239 signal(SIGINT, sig_handler); 225 signal(SIGINT, sig_handler);
240 226
241 if (inject_build_ids) { 227 if (inject->build_ids) {
242 perf_inject.sample = perf_event__inject_buildid; 228 inject->tool.sample = perf_event__inject_buildid;
243 perf_inject.mmap = perf_event__repipe_mmap; 229 inject->tool.mmap = perf_event__repipe_mmap;
244 perf_inject.fork = perf_event__repipe_task; 230 inject->tool.fork = perf_event__repipe_task;
245 perf_inject.tracing_data = perf_event__repipe_tracing_data; 231 inject->tool.tracing_data = perf_event__repipe_tracing_data;
246 } 232 }
247 233
248 session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject); 234 session = perf_session__new("-", O_RDONLY, false, true, &inject->tool);
249 if (session == NULL) 235 if (session == NULL)
250 return -ENOMEM; 236 return -ENOMEM;
251 237
252 ret = perf_session__process_events(session, &perf_inject); 238 ret = perf_session__process_events(session, &inject->tool);
253 239
254 perf_session__delete(session); 240 perf_session__delete(session);
255 241
256 return ret; 242 return ret;
257} 243}
258 244
259static const char * const report_usage[] = {
260 "perf inject [<options>]",
261 NULL
262};
263
264static const struct option options[] = {
265 OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
266 "Inject build-ids into the output stream"),
267 OPT_INCR('v', "verbose", &verbose,
268 "be more verbose (show build ids, etc)"),
269 OPT_END()
270};
271
272int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) 245int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
273{ 246{
274 argc = parse_options(argc, argv, options, report_usage, 0); 247 struct perf_inject inject = {
248 .tool = {
249 .sample = perf_event__repipe_sample,
250 .mmap = perf_event__repipe,
251 .comm = perf_event__repipe,
252 .fork = perf_event__repipe,
253 .exit = perf_event__repipe,
254 .lost = perf_event__repipe,
255 .read = perf_event__repipe_sample,
256 .throttle = perf_event__repipe,
257 .unthrottle = perf_event__repipe,
258 .attr = perf_event__repipe_attr,
259 .event_type = perf_event__repipe_event_type_synth,
260 .tracing_data = perf_event__repipe_tracing_data_synth,
261 .build_id = perf_event__repipe_op2_synth,
262 },
263 };
264 const struct option options[] = {
265 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
266 "Inject build-ids into the output stream"),
267 OPT_INCR('v', "verbose", &verbose,
268 "be more verbose (show build ids, etc)"),
269 OPT_END()
270 };
271 const char * const inject_usage[] = {
272 "perf inject [<options>]",
273 NULL
274 };
275
276 argc = parse_options(argc, argv, options, inject_usage, 0);
275 277
276 /* 278 /*
277 * Any (unrecognized) arguments left? 279 * Any (unrecognized) arguments left?
278 */ 280 */
279 if (argc) 281 if (argc)
280 usage_with_options(report_usage, options); 282 usage_with_options(inject_usage, options);
281 283
282 if (symbol__init() < 0) 284 if (symbol__init() < 0)
283 return -1; 285 return -1;
284 286
285 return __cmd_inject(); 287 return __cmd_inject(&inject);
286} 288}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index bc912c68f49a..14bf82f63659 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -21,8 +21,6 @@
21struct alloc_stat; 21struct alloc_stat;
22typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 22typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
23 23
24static const char *input_name;
25
26static int alloc_flag; 24static int alloc_flag;
27static int caller_flag; 25static int caller_flag;
28 26
@@ -31,8 +29,6 @@ static int caller_lines = -1;
31 29
32static bool raw_ip; 30static bool raw_ip;
33 31
34static char default_sort_order[] = "frag,hit,bytes";
35
36static int *cpunode_map; 32static int *cpunode_map;
37static int max_cpu_num; 33static int max_cpu_num;
38 34
@@ -481,7 +477,7 @@ static void sort_result(void)
481 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 477 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
482} 478}
483 479
484static int __cmd_kmem(void) 480static int __cmd_kmem(const char *input_name)
485{ 481{
486 int err = -EINVAL; 482 int err = -EINVAL;
487 struct perf_session *session; 483 struct perf_session *session;
@@ -520,11 +516,6 @@ out_delete:
520 return err; 516 return err;
521} 517}
522 518
523static const char * const kmem_usage[] = {
524 "perf kmem [<options>] {record|stat}",
525 NULL
526};
527
528static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r) 519static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r)
529{ 520{
530 if (l->ptr < r->ptr) 521 if (l->ptr < r->ptr)
@@ -720,41 +711,17 @@ static int parse_line_opt(const struct option *opt __maybe_unused,
720 return 0; 711 return 0;
721} 712}
722 713
723static const struct option kmem_options[] = { 714static int __cmd_record(int argc, const char **argv)
724 OPT_STRING('i', "input", &input_name, "file", 715{
725 "input file name"), 716 const char * const record_args[] = {
726 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL, 717 "record", "-a", "-R", "-f", "-c", "1",
727 "show per-callsite statistics",
728 parse_caller_opt),
729 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
730 "show per-allocation statistics",
731 parse_alloc_opt),
732 OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
733 "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
734 parse_sort_opt),
735 OPT_CALLBACK('l', "line", NULL, "num",
736 "show n lines",
737 parse_line_opt),
738 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
739 OPT_END()
740};
741
742static const char *record_args[] = {
743 "record",
744 "-a",
745 "-R",
746 "-f",
747 "-c", "1",
748 "-e", "kmem:kmalloc", 718 "-e", "kmem:kmalloc",
749 "-e", "kmem:kmalloc_node", 719 "-e", "kmem:kmalloc_node",
750 "-e", "kmem:kfree", 720 "-e", "kmem:kfree",
751 "-e", "kmem:kmem_cache_alloc", 721 "-e", "kmem:kmem_cache_alloc",
752 "-e", "kmem:kmem_cache_alloc_node", 722 "-e", "kmem:kmem_cache_alloc_node",
753 "-e", "kmem:kmem_cache_free", 723 "-e", "kmem:kmem_cache_free",
754}; 724 };
755
756static int __cmd_record(int argc, const char **argv)
757{
758 unsigned int rec_argc, i, j; 725 unsigned int rec_argc, i, j;
759 const char **rec_argv; 726 const char **rec_argv;
760 727
@@ -775,6 +742,25 @@ static int __cmd_record(int argc, const char **argv)
775 742
776int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) 743int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
777{ 744{
745 const char * const default_sort_order = "frag,hit,bytes";
746 const char *input_name = NULL;
747 const struct option kmem_options[] = {
748 OPT_STRING('i', "input", &input_name, "file", "input file name"),
749 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
750 "show per-callsite statistics", parse_caller_opt),
751 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
752 "show per-allocation statistics", parse_alloc_opt),
753 OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
754 "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
755 parse_sort_opt),
756 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
757 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
758 OPT_END()
759 };
760 const char * const kmem_usage[] = {
761 "perf kmem [<options>] {record|stat}",
762 NULL
763 };
778 argc = parse_options(argc, argv, kmem_options, kmem_usage, 0); 764 argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);
779 765
780 if (!argc) 766 if (!argc)
@@ -793,7 +779,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
793 if (list_empty(&alloc_sort)) 779 if (list_empty(&alloc_sort))
794 setup_sorting(&alloc_sort, default_sort_order); 780 setup_sorting(&alloc_sort, default_sort_order);
795 781
796 return __cmd_kmem(); 782 return __cmd_kmem(input_name);
797 } else 783 } else
798 usage_with_options(kmem_usage, kmem_options); 784 usage_with_options(kmem_usage, kmem_options);
799 785
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index a28c9cad9048..260abc535b5b 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -32,16 +32,76 @@ struct event_key {
32 int info; 32 int info;
33}; 33};
34 34
35struct kvm_event_stats {
36 u64 time;
37 struct stats stats;
38};
39
40struct kvm_event {
41 struct list_head hash_entry;
42 struct rb_node rb;
43
44 struct event_key key;
45
46 struct kvm_event_stats total;
47
48 #define DEFAULT_VCPU_NUM 8
49 int max_vcpu;
50 struct kvm_event_stats *vcpu;
51};
52
53typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
54
55struct kvm_event_key {
56 const char *name;
57 key_cmp_fun key;
58};
59
60
61struct perf_kvm;
62
35struct kvm_events_ops { 63struct kvm_events_ops {
36 bool (*is_begin_event)(struct perf_evsel *evsel, 64 bool (*is_begin_event)(struct perf_evsel *evsel,
37 struct perf_sample *sample, 65 struct perf_sample *sample,
38 struct event_key *key); 66 struct event_key *key);
39 bool (*is_end_event)(struct perf_evsel *evsel, 67 bool (*is_end_event)(struct perf_evsel *evsel,
40 struct perf_sample *sample, struct event_key *key); 68 struct perf_sample *sample, struct event_key *key);
41 void (*decode_key)(struct event_key *key, char decode[20]); 69 void (*decode_key)(struct perf_kvm *kvm, struct event_key *key,
70 char decode[20]);
42 const char *name; 71 const char *name;
43}; 72};
44 73
74struct exit_reasons_table {
75 unsigned long exit_code;
76 const char *reason;
77};
78
79#define EVENTS_BITS 12
80#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
81
82struct perf_kvm {
83 struct perf_tool tool;
84 struct perf_session *session;
85
86 const char *file_name;
87 const char *report_event;
88 const char *sort_key;
89 int trace_vcpu;
90
91 struct exit_reasons_table *exit_reasons;
92 int exit_reasons_size;
93 const char *exit_reasons_isa;
94
95 struct kvm_events_ops *events_ops;
96 key_cmp_fun compare;
97 struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
98 u64 total_time;
99 u64 total_count;
100
101 struct rb_root result;
102};
103
104
45static void exit_event_get_key(struct perf_evsel *evsel, 105static void exit_event_get_key(struct perf_evsel *evsel,
46 struct perf_sample *sample, 106 struct perf_sample *sample,
47 struct event_key *key) 107 struct event_key *key)
@@ -78,45 +138,35 @@ static bool exit_event_end(struct perf_evsel *evsel,
78 return kvm_entry_event(evsel); 138 return kvm_entry_event(evsel);
79} 139}
80 140
81struct exit_reasons_table { 141static struct exit_reasons_table vmx_exit_reasons[] = {
82 unsigned long exit_code;
83 const char *reason;
84};
85
86struct exit_reasons_table vmx_exit_reasons[] = {
87 VMX_EXIT_REASONS 142 VMX_EXIT_REASONS
88}; 143};
89 144
90struct exit_reasons_table svm_exit_reasons[] = { 145static struct exit_reasons_table svm_exit_reasons[] = {
91 SVM_EXIT_REASONS 146 SVM_EXIT_REASONS
92}; 147};
93 148
94static int cpu_isa; 149static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
95
96static const char *get_exit_reason(u64 exit_code)
97{ 150{
98 int table_size = ARRAY_SIZE(svm_exit_reasons); 151 int i = kvm->exit_reasons_size;
99 struct exit_reasons_table *table = svm_exit_reasons; 152 struct exit_reasons_table *tbl = kvm->exit_reasons;
100
101 if (cpu_isa == 1) {
102 table = vmx_exit_reasons;
103 table_size = ARRAY_SIZE(vmx_exit_reasons);
104 }
105 153
106 while (table_size--) { 154 while (i--) {
107 if (table->exit_code == exit_code) 155 if (tbl->exit_code == exit_code)
108 return table->reason; 156 return tbl->reason;
109 table++; 157 tbl++;
110 } 158 }
111 159
112 pr_err("unknown kvm exit code:%lld on %s\n", 160 pr_err("unknown kvm exit code:%lld on %s\n",
113 (unsigned long long)exit_code, cpu_isa ? "VMX" : "SVM"); 161 (unsigned long long)exit_code, kvm->exit_reasons_isa);
114 return "UNKNOWN"; 162 return "UNKNOWN";
115} 163}
116 164
117static void exit_event_decode_key(struct event_key *key, char decode[20]) 165static void exit_event_decode_key(struct perf_kvm *kvm,
166 struct event_key *key,
167 char decode[20])
118{ 168{
119 const char *exit_reason = get_exit_reason(key->key); 169 const char *exit_reason = get_exit_reason(kvm, key->key);
120 170
121 scnprintf(decode, 20, "%s", exit_reason); 171 scnprintf(decode, 20, "%s", exit_reason);
122} 172}
@@ -128,11 +178,11 @@ static struct kvm_events_ops exit_events = {
128 .name = "VM-EXIT" 178 .name = "VM-EXIT"
129}; 179};
130 180
131 /* 181/*
132 * For the mmio events, we treat: 182 * For the mmio events, we treat:
133 * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry 183 * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
134 * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...). 184 * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
135 */ 185 */
136static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample, 186static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample,
137 struct event_key *key) 187 struct event_key *key)
138{ 188{
@@ -178,7 +228,9 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
178 return false; 228 return false;
179} 229}
180 230
181static void mmio_event_decode_key(struct event_key *key, char decode[20]) 231static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused,
232 struct event_key *key,
233 char decode[20])
182{ 234{
183 scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key, 235 scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
184 key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R"); 236 key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
@@ -219,7 +271,9 @@ static bool ioport_event_end(struct perf_evsel *evsel,
219 return kvm_entry_event(evsel); 271 return kvm_entry_event(evsel);
220} 272}
221 273
222static void ioport_event_decode_key(struct event_key *key, char decode[20]) 274static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused,
275 struct event_key *key,
276 char decode[20])
223{ 277{
224 scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key, 278 scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
225 key->info ? "POUT" : "PIN"); 279 key->info ? "POUT" : "PIN");
@@ -232,64 +286,37 @@ static struct kvm_events_ops ioport_events = {
232 .name = "IO Port Access" 286 .name = "IO Port Access"
233}; 287};
234 288
235static const char *report_event = "vmexit"; 289static bool register_kvm_events_ops(struct perf_kvm *kvm)
236struct kvm_events_ops *events_ops;
237
238static bool register_kvm_events_ops(void)
239{ 290{
240 bool ret = true; 291 bool ret = true;
241 292
242 if (!strcmp(report_event, "vmexit")) 293 if (!strcmp(kvm->report_event, "vmexit"))
243 events_ops = &exit_events; 294 kvm->events_ops = &exit_events;
244 else if (!strcmp(report_event, "mmio")) 295 else if (!strcmp(kvm->report_event, "mmio"))
245 events_ops = &mmio_events; 296 kvm->events_ops = &mmio_events;
246 else if (!strcmp(report_event, "ioport")) 297 else if (!strcmp(kvm->report_event, "ioport"))
247 events_ops = &ioport_events; 298 kvm->events_ops = &ioport_events;
248 else { 299 else {
249 pr_err("Unknown report event:%s\n", report_event); 300 pr_err("Unknown report event:%s\n", kvm->report_event);
250 ret = false; 301 ret = false;
251 } 302 }
252 303
253 return ret; 304 return ret;
254} 305}
255 306
256struct kvm_event_stats {
257 u64 time;
258 struct stats stats;
259};
260
261struct kvm_event {
262 struct list_head hash_entry;
263 struct rb_node rb;
264
265 struct event_key key;
266
267 struct kvm_event_stats total;
268
269 #define DEFAULT_VCPU_NUM 8
270 int max_vcpu;
271 struct kvm_event_stats *vcpu;
272};
273
274struct vcpu_event_record { 307struct vcpu_event_record {
275 int vcpu_id; 308 int vcpu_id;
276 u64 start_time; 309 u64 start_time;
277 struct kvm_event *last_event; 310 struct kvm_event *last_event;
278}; 311};
279 312
280#define EVENTS_BITS 12
281#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
282
283static u64 total_time;
284static u64 total_count;
285static struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
286 313
287static void init_kvm_event_record(void) 314static void init_kvm_event_record(struct perf_kvm *kvm)
288{ 315{
289 int i; 316 int i;
290 317
291 for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++) 318 for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
292 INIT_LIST_HEAD(&kvm_events_cache[i]); 319 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
293} 320}
294 321
295static int kvm_events_hash_fn(u64 key) 322static int kvm_events_hash_fn(u64 key)
@@ -333,14 +360,15 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
333 return event; 360 return event;
334} 361}
335 362
336static struct kvm_event *find_create_kvm_event(struct event_key *key) 363static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
364 struct event_key *key)
337{ 365{
338 struct kvm_event *event; 366 struct kvm_event *event;
339 struct list_head *head; 367 struct list_head *head;
340 368
341 BUG_ON(key->key == INVALID_KEY); 369 BUG_ON(key->key == INVALID_KEY);
342 370
343 head = &kvm_events_cache[kvm_events_hash_fn(key->key)]; 371 head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
344 list_for_each_entry(event, head, hash_entry) 372 list_for_each_entry(event, head, hash_entry)
345 if (event->key.key == key->key && event->key.info == key->info) 373 if (event->key.key == key->key && event->key.info == key->info)
346 return event; 374 return event;
@@ -353,13 +381,14 @@ static struct kvm_event *find_create_kvm_event(struct event_key *key)
353 return event; 381 return event;
354} 382}
355 383
356static bool handle_begin_event(struct vcpu_event_record *vcpu_record, 384static bool handle_begin_event(struct perf_kvm *kvm,
385 struct vcpu_event_record *vcpu_record,
357 struct event_key *key, u64 timestamp) 386 struct event_key *key, u64 timestamp)
358{ 387{
359 struct kvm_event *event = NULL; 388 struct kvm_event *event = NULL;
360 389
361 if (key->key != INVALID_KEY) 390 if (key->key != INVALID_KEY)
362 event = find_create_kvm_event(key); 391 event = find_create_kvm_event(kvm, key);
363 392
364 vcpu_record->last_event = event; 393 vcpu_record->last_event = event;
365 vcpu_record->start_time = timestamp; 394 vcpu_record->start_time = timestamp;
@@ -396,8 +425,10 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
396 return true; 425 return true;
397} 426}
398 427
399static bool handle_end_event(struct vcpu_event_record *vcpu_record, 428static bool handle_end_event(struct perf_kvm *kvm,
400 struct event_key *key, u64 timestamp) 429 struct vcpu_event_record *vcpu_record,
430 struct event_key *key,
431 u64 timestamp)
401{ 432{
402 struct kvm_event *event; 433 struct kvm_event *event;
403 u64 time_begin, time_diff; 434 u64 time_begin, time_diff;
@@ -419,7 +450,7 @@ static bool handle_end_event(struct vcpu_event_record *vcpu_record,
419 return true; 450 return true;
420 451
421 if (!event) 452 if (!event)
422 event = find_create_kvm_event(key); 453 event = find_create_kvm_event(kvm, key);
423 454
424 if (!event) 455 if (!event)
425 return false; 456 return false;
@@ -455,7 +486,9 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
455 return thread->priv; 486 return thread->priv;
456} 487}
457 488
458static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel, 489static bool handle_kvm_event(struct perf_kvm *kvm,
490 struct thread *thread,
491 struct perf_evsel *evsel,
459 struct perf_sample *sample) 492 struct perf_sample *sample)
460{ 493{
461 struct vcpu_event_record *vcpu_record; 494 struct vcpu_event_record *vcpu_record;
@@ -465,22 +498,15 @@ static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel,
465 if (!vcpu_record) 498 if (!vcpu_record)
466 return true; 499 return true;
467 500
468 if (events_ops->is_begin_event(evsel, sample, &key)) 501 if (kvm->events_ops->is_begin_event(evsel, sample, &key))
469 return handle_begin_event(vcpu_record, &key, sample->time); 502 return handle_begin_event(kvm, vcpu_record, &key, sample->time);
470 503
471 if (events_ops->is_end_event(evsel, sample, &key)) 504 if (kvm->events_ops->is_end_event(evsel, sample, &key))
472 return handle_end_event(vcpu_record, &key, sample->time); 505 return handle_end_event(kvm, vcpu_record, &key, sample->time);
473 506
474 return true; 507 return true;
475} 508}
476 509
477typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
478struct kvm_event_key {
479 const char *name;
480 key_cmp_fun key;
481};
482
483static int trace_vcpu = -1;
484#define GET_EVENT_KEY(func, field) \ 510#define GET_EVENT_KEY(func, field) \
485static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \ 511static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \
486{ \ 512{ \
@@ -515,29 +541,25 @@ static struct kvm_event_key keys[] = {
515 { NULL, NULL } 541 { NULL, NULL }
516}; 542};
517 543
518static const char *sort_key = "sample"; 544static bool select_key(struct perf_kvm *kvm)
519static key_cmp_fun compare;
520
521static bool select_key(void)
522{ 545{
523 int i; 546 int i;
524 547
525 for (i = 0; keys[i].name; i++) { 548 for (i = 0; keys[i].name; i++) {
526 if (!strcmp(keys[i].name, sort_key)) { 549 if (!strcmp(keys[i].name, kvm->sort_key)) {
527 compare = keys[i].key; 550 kvm->compare = keys[i].key;
528 return true; 551 return true;
529 } 552 }
530 } 553 }
531 554
532 pr_err("Unknown compare key:%s\n", sort_key); 555 pr_err("Unknown compare key:%s\n", kvm->sort_key);
533 return false; 556 return false;
534} 557}
535 558
536static struct rb_root result; 559static void insert_to_result(struct rb_root *result, struct kvm_event *event,
537static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger, 560 key_cmp_fun bigger, int vcpu)
538 int vcpu)
539{ 561{
540 struct rb_node **rb = &result.rb_node; 562 struct rb_node **rb = &result->rb_node;
541 struct rb_node *parent = NULL; 563 struct rb_node *parent = NULL;
542 struct kvm_event *p; 564 struct kvm_event *p;
543 565
@@ -552,13 +574,15 @@ static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
552 } 574 }
553 575
554 rb_link_node(&event->rb, parent, rb); 576 rb_link_node(&event->rb, parent, rb);
555 rb_insert_color(&event->rb, &result); 577 rb_insert_color(&event->rb, result);
556} 578}
557 579
558static void update_total_count(struct kvm_event *event, int vcpu) 580static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event)
559{ 581{
560 total_count += get_event_count(event, vcpu); 582 int vcpu = kvm->trace_vcpu;
561 total_time += get_event_time(event, vcpu); 583
584 kvm->total_count += get_event_count(event, vcpu);
585 kvm->total_time += get_event_time(event, vcpu);
562} 586}
563 587
564static bool event_is_valid(struct kvm_event *event, int vcpu) 588static bool event_is_valid(struct kvm_event *event, int vcpu)
@@ -566,28 +590,30 @@ static bool event_is_valid(struct kvm_event *event, int vcpu)
566 return !!get_event_count(event, vcpu); 590 return !!get_event_count(event, vcpu);
567} 591}
568 592
569static void sort_result(int vcpu) 593static void sort_result(struct perf_kvm *kvm)
570{ 594{
571 unsigned int i; 595 unsigned int i;
596 int vcpu = kvm->trace_vcpu;
572 struct kvm_event *event; 597 struct kvm_event *event;
573 598
574 for (i = 0; i < EVENTS_CACHE_SIZE; i++) 599 for (i = 0; i < EVENTS_CACHE_SIZE; i++)
575 list_for_each_entry(event, &kvm_events_cache[i], hash_entry) 600 list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
576 if (event_is_valid(event, vcpu)) { 601 if (event_is_valid(event, vcpu)) {
577 update_total_count(event, vcpu); 602 update_total_count(kvm, event);
578 insert_to_result(event, compare, vcpu); 603 insert_to_result(&kvm->result, event,
604 kvm->compare, vcpu);
579 } 605 }
580} 606}
581 607
582/* returns left most element of result, and erase it */ 608/* returns left most element of result, and erase it */
583static struct kvm_event *pop_from_result(void) 609static struct kvm_event *pop_from_result(struct rb_root *result)
584{ 610{
585 struct rb_node *node = rb_first(&result); 611 struct rb_node *node = rb_first(result);
586 612
587 if (!node) 613 if (!node)
588 return NULL; 614 return NULL;
589 615
590 rb_erase(node, &result); 616 rb_erase(node, result);
591 return container_of(node, struct kvm_event, rb); 617 return container_of(node, struct kvm_event, rb);
592} 618}
593 619
@@ -601,14 +627,15 @@ static void print_vcpu_info(int vcpu)
601 pr_info("VCPU %d:\n\n", vcpu); 627 pr_info("VCPU %d:\n\n", vcpu);
602} 628}
603 629
604static void print_result(int vcpu) 630static void print_result(struct perf_kvm *kvm)
605{ 631{
606 char decode[20]; 632 char decode[20];
607 struct kvm_event *event; 633 struct kvm_event *event;
634 int vcpu = kvm->trace_vcpu;
608 635
609 pr_info("\n\n"); 636 pr_info("\n\n");
610 print_vcpu_info(vcpu); 637 print_vcpu_info(vcpu);
611 pr_info("%20s ", events_ops->name); 638 pr_info("%20s ", kvm->events_ops->name);
612 pr_info("%10s ", "Samples"); 639 pr_info("%10s ", "Samples");
613 pr_info("%9s ", "Samples%"); 640 pr_info("%9s ", "Samples%");
614 641
@@ -616,33 +643,34 @@ static void print_result(int vcpu)
616 pr_info("%16s ", "Avg time"); 643 pr_info("%16s ", "Avg time");
617 pr_info("\n\n"); 644 pr_info("\n\n");
618 645
619 while ((event = pop_from_result())) { 646 while ((event = pop_from_result(&kvm->result))) {
620 u64 ecount, etime; 647 u64 ecount, etime;
621 648
622 ecount = get_event_count(event, vcpu); 649 ecount = get_event_count(event, vcpu);
623 etime = get_event_time(event, vcpu); 650 etime = get_event_time(event, vcpu);
624 651
625 events_ops->decode_key(&event->key, decode); 652 kvm->events_ops->decode_key(kvm, &event->key, decode);
626 pr_info("%20s ", decode); 653 pr_info("%20s ", decode);
627 pr_info("%10llu ", (unsigned long long)ecount); 654 pr_info("%10llu ", (unsigned long long)ecount);
628 pr_info("%8.2f%% ", (double)ecount / total_count * 100); 655 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
629 pr_info("%8.2f%% ", (double)etime / total_time * 100); 656 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
630 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, 657 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
631 kvm_event_rel_stddev(vcpu, event)); 658 kvm_event_rel_stddev(vcpu, event));
632 pr_info("\n"); 659 pr_info("\n");
633 } 660 }
634 661
635 pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n", 662 pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
636 (unsigned long long)total_count, total_time / 1e3); 663 (unsigned long long)kvm->total_count, kvm->total_time / 1e3);
637} 664}
638 665
639static int process_sample_event(struct perf_tool *tool __maybe_unused, 666static int process_sample_event(struct perf_tool *tool,
640 union perf_event *event, 667 union perf_event *event,
641 struct perf_sample *sample, 668 struct perf_sample *sample,
642 struct perf_evsel *evsel, 669 struct perf_evsel *evsel,
643 struct machine *machine) 670 struct machine *machine)
644{ 671{
645 struct thread *thread = machine__findnew_thread(machine, sample->tid); 672 struct thread *thread = machine__findnew_thread(machine, sample->tid);
673 struct perf_kvm *kvm = container_of(tool, struct perf_kvm, tool);
646 674
647 if (thread == NULL) { 675 if (thread == NULL) {
648 pr_debug("problem processing %d event, skipping it.\n", 676 pr_debug("problem processing %d event, skipping it.\n",
@@ -650,18 +678,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
650 return -1; 678 return -1;
651 } 679 }
652 680
653 if (!handle_kvm_event(thread, evsel, sample)) 681 if (!handle_kvm_event(kvm, thread, evsel, sample))
654 return -1; 682 return -1;
655 683
656 return 0; 684 return 0;
657} 685}
658 686
659static struct perf_tool eops = {
660 .sample = process_sample_event,
661 .comm = perf_event__process_comm,
662 .ordered_samples = true,
663};
664
665static int get_cpu_isa(struct perf_session *session) 687static int get_cpu_isa(struct perf_session *session)
666{ 688{
667 char *cpuid = session->header.env.cpuid; 689 char *cpuid = session->header.env.cpuid;
@@ -679,34 +701,43 @@ static int get_cpu_isa(struct perf_session *session)
679 return isa; 701 return isa;
680} 702}
681 703
682static const char *file_name; 704static int read_events(struct perf_kvm *kvm)
683
684static int read_events(void)
685{ 705{
686 struct perf_session *kvm_session;
687 int ret; 706 int ret;
688 707
689 kvm_session = perf_session__new(file_name, O_RDONLY, 0, false, &eops); 708 struct perf_tool eops = {
690 if (!kvm_session) { 709 .sample = process_sample_event,
710 .comm = perf_event__process_comm,
711 .ordered_samples = true,
712 };
713
714 kvm->tool = eops;
715 kvm->session = perf_session__new(kvm->file_name, O_RDONLY, 0, false,
716 &kvm->tool);
717 if (!kvm->session) {
691 pr_err("Initializing perf session failed\n"); 718 pr_err("Initializing perf session failed\n");
692 return -EINVAL; 719 return -EINVAL;
693 } 720 }
694 721
695 if (!perf_session__has_traces(kvm_session, "kvm record")) 722 if (!perf_session__has_traces(kvm->session, "kvm record"))
696 return -EINVAL; 723 return -EINVAL;
697 724
698 /* 725 /*
699 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not 726 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
700 * traced in the old kernel. 727 * traced in the old kernel.
701 */ 728 */
702 ret = get_cpu_isa(kvm_session); 729 ret = get_cpu_isa(kvm->session);
703 730
704 if (ret < 0) 731 if (ret < 0)
705 return ret; 732 return ret;
706 733
707 cpu_isa = ret; 734 if (ret == 1) {
735 kvm->exit_reasons = vmx_exit_reasons;
736 kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
737 kvm->exit_reasons_isa = "VMX";
738 }
708 739
709 return perf_session__process_events(kvm_session, &eops); 740 return perf_session__process_events(kvm->session, &kvm->tool);
710} 741}
711 742
712static bool verify_vcpu(int vcpu) 743static bool verify_vcpu(int vcpu)
@@ -719,28 +750,30 @@ static bool verify_vcpu(int vcpu)
719 return true; 750 return true;
720} 751}
721 752
722static int kvm_events_report_vcpu(int vcpu) 753static int kvm_events_report_vcpu(struct perf_kvm *kvm)
723{ 754{
724 int ret = -EINVAL; 755 int ret = -EINVAL;
756 int vcpu = kvm->trace_vcpu;
725 757
726 if (!verify_vcpu(vcpu)) 758 if (!verify_vcpu(vcpu))
727 goto exit; 759 goto exit;
728 760
729 if (!select_key()) 761 if (!select_key(kvm))
730 goto exit; 762 goto exit;
731 763
732 if (!register_kvm_events_ops()) 764 if (!register_kvm_events_ops(kvm))
733 goto exit; 765 goto exit;
734 766
735 init_kvm_event_record(); 767 init_kvm_event_record(kvm);
736 setup_pager(); 768 setup_pager();
737 769
738 ret = read_events(); 770 ret = read_events(kvm);
739 if (ret) 771 if (ret)
740 goto exit; 772 goto exit;
741 773
742 sort_result(vcpu); 774 sort_result(kvm);
743 print_result(vcpu); 775 print_result(kvm);
776
744exit: 777exit:
745 return ret; 778 return ret;
746} 779}
@@ -765,7 +798,7 @@ static const char * const record_args[] = {
765 _p; \ 798 _p; \
766 }) 799 })
767 800
768static int kvm_events_record(int argc, const char **argv) 801static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
769{ 802{
770 unsigned int rec_argc, i, j; 803 unsigned int rec_argc, i, j;
771 const char **rec_argv; 804 const char **rec_argv;
@@ -780,7 +813,7 @@ static int kvm_events_record(int argc, const char **argv)
780 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]); 813 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
781 814
782 rec_argv[i++] = STRDUP_FAIL_EXIT("-o"); 815 rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
783 rec_argv[i++] = STRDUP_FAIL_EXIT(file_name); 816 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);
784 817
785 for (j = 1; j < (unsigned int)argc; j++, i++) 818 for (j = 1; j < (unsigned int)argc; j++, i++)
786 rec_argv[i] = argv[j]; 819 rec_argv[i] = argv[j];
@@ -788,24 +821,24 @@ static int kvm_events_record(int argc, const char **argv)
788 return cmd_record(i, rec_argv, NULL); 821 return cmd_record(i, rec_argv, NULL);
789} 822}
790 823
791static const char * const kvm_events_report_usage[] = { 824static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv)
792 "perf kvm stat report [<options>]", 825{
793 NULL 826 const struct option kvm_events_report_options[] = {
794}; 827 OPT_STRING(0, "event", &kvm->report_event, "report event",
828 "event for reporting: vmexit, mmio, ioport"),
829 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
830 "vcpu id to report"),
831 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
832 "key for sorting: sample(sort by samples number)"
833 " time (sort by avg time)"),
834 OPT_END()
835 };
795 836
796static const struct option kvm_events_report_options[] = { 837 const char * const kvm_events_report_usage[] = {
797 OPT_STRING(0, "event", &report_event, "report event", 838 "perf kvm stat report [<options>]",
798 "event for reporting: vmexit, mmio, ioport"), 839 NULL
799 OPT_INTEGER(0, "vcpu", &trace_vcpu, 840 };
800 "vcpu id to report"),
801 OPT_STRING('k', "key", &sort_key, "sort-key",
802 "key for sorting: sample(sort by samples number)"
803 " time (sort by avg time)"),
804 OPT_END()
805};
806 841
807static int kvm_events_report(int argc, const char **argv)
808{
809 symbol__init(); 842 symbol__init();
810 843
811 if (argc) { 844 if (argc) {
@@ -817,7 +850,7 @@ static int kvm_events_report(int argc, const char **argv)
817 kvm_events_report_options); 850 kvm_events_report_options);
818 } 851 }
819 852
820 return kvm_events_report_vcpu(trace_vcpu); 853 return kvm_events_report_vcpu(kvm);
821} 854}
822 855
823static void print_kvm_stat_usage(void) 856static void print_kvm_stat_usage(void)
@@ -831,7 +864,7 @@ static void print_kvm_stat_usage(void)
831 printf("\nOtherwise, it is the alias of 'perf stat':\n"); 864 printf("\nOtherwise, it is the alias of 'perf stat':\n");
832} 865}
833 866
834static int kvm_cmd_stat(int argc, const char **argv) 867static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv)
835{ 868{
836 if (argc == 1) { 869 if (argc == 1) {
837 print_kvm_stat_usage(); 870 print_kvm_stat_usage();
@@ -839,44 +872,16 @@ static int kvm_cmd_stat(int argc, const char **argv)
839 } 872 }
840 873
841 if (!strncmp(argv[1], "rec", 3)) 874 if (!strncmp(argv[1], "rec", 3))
842 return kvm_events_record(argc - 1, argv + 1); 875 return kvm_events_record(kvm, argc - 1, argv + 1);
843 876
844 if (!strncmp(argv[1], "rep", 3)) 877 if (!strncmp(argv[1], "rep", 3))
845 return kvm_events_report(argc - 1 , argv + 1); 878 return kvm_events_report(kvm, argc - 1 , argv + 1);
846 879
847perf_stat: 880perf_stat:
848 return cmd_stat(argc, argv, NULL); 881 return cmd_stat(argc, argv, NULL);
849} 882}
850 883
851static char name_buffer[256]; 884static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
852
853static const char * const kvm_usage[] = {
854 "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
855 NULL
856};
857
858static const struct option kvm_options[] = {
859 OPT_STRING('i', "input", &file_name, "file",
860 "Input file name"),
861 OPT_STRING('o', "output", &file_name, "file",
862 "Output file name"),
863 OPT_BOOLEAN(0, "guest", &perf_guest,
864 "Collect guest os data"),
865 OPT_BOOLEAN(0, "host", &perf_host,
866 "Collect host os data"),
867 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
868 "guest mount directory under which every guest os"
869 " instance has a subdir"),
870 OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
871 "file", "file saving guest os vmlinux"),
872 OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
873 "file", "file saving guest os /proc/kallsyms"),
874 OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
875 "file", "file saving guest os /proc/modules"),
876 OPT_END()
877};
878
879static int __cmd_record(int argc, const char **argv)
880{ 885{
881 int rec_argc, i = 0, j; 886 int rec_argc, i = 0, j;
882 const char **rec_argv; 887 const char **rec_argv;
@@ -885,7 +890,7 @@ static int __cmd_record(int argc, const char **argv)
885 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 890 rec_argv = calloc(rec_argc + 1, sizeof(char *));
886 rec_argv[i++] = strdup("record"); 891 rec_argv[i++] = strdup("record");
887 rec_argv[i++] = strdup("-o"); 892 rec_argv[i++] = strdup("-o");
888 rec_argv[i++] = strdup(file_name); 893 rec_argv[i++] = strdup(kvm->file_name);
889 for (j = 1; j < argc; j++, i++) 894 for (j = 1; j < argc; j++, i++)
890 rec_argv[i] = argv[j]; 895 rec_argv[i] = argv[j];
891 896
@@ -894,7 +899,7 @@ static int __cmd_record(int argc, const char **argv)
894 return cmd_record(i, rec_argv, NULL); 899 return cmd_record(i, rec_argv, NULL);
895} 900}
896 901
897static int __cmd_report(int argc, const char **argv) 902static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
898{ 903{
899 int rec_argc, i = 0, j; 904 int rec_argc, i = 0, j;
900 const char **rec_argv; 905 const char **rec_argv;
@@ -903,7 +908,7 @@ static int __cmd_report(int argc, const char **argv)
903 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 908 rec_argv = calloc(rec_argc + 1, sizeof(char *));
904 rec_argv[i++] = strdup("report"); 909 rec_argv[i++] = strdup("report");
905 rec_argv[i++] = strdup("-i"); 910 rec_argv[i++] = strdup("-i");
906 rec_argv[i++] = strdup(file_name); 911 rec_argv[i++] = strdup(kvm->file_name);
907 for (j = 1; j < argc; j++, i++) 912 for (j = 1; j < argc; j++, i++)
908 rec_argv[i] = argv[j]; 913 rec_argv[i] = argv[j];
909 914
@@ -912,7 +917,7 @@ static int __cmd_report(int argc, const char **argv)
912 return cmd_report(i, rec_argv, NULL); 917 return cmd_report(i, rec_argv, NULL);
913} 918}
914 919
915static int __cmd_buildid_list(int argc, const char **argv) 920static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
916{ 921{
917 int rec_argc, i = 0, j; 922 int rec_argc, i = 0, j;
918 const char **rec_argv; 923 const char **rec_argv;
@@ -921,7 +926,7 @@ static int __cmd_buildid_list(int argc, const char **argv)
921 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 926 rec_argv = calloc(rec_argc + 1, sizeof(char *));
922 rec_argv[i++] = strdup("buildid-list"); 927 rec_argv[i++] = strdup("buildid-list");
923 rec_argv[i++] = strdup("-i"); 928 rec_argv[i++] = strdup("-i");
924 rec_argv[i++] = strdup(file_name); 929 rec_argv[i++] = strdup(kvm->file_name);
925 for (j = 1; j < argc; j++, i++) 930 for (j = 1; j < argc; j++, i++)
926 rec_argv[i] = argv[j]; 931 rec_argv[i] = argv[j];
927 932
@@ -932,6 +937,43 @@ static int __cmd_buildid_list(int argc, const char **argv)
932 937
933int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) 938int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
934{ 939{
940 struct perf_kvm kvm = {
941 .trace_vcpu = -1,
942 .report_event = "vmexit",
943 .sort_key = "sample",
944
945 .exit_reasons = svm_exit_reasons,
946 .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
947 .exit_reasons_isa = "SVM",
948 };
949
950 const struct option kvm_options[] = {
951 OPT_STRING('i', "input", &kvm.file_name, "file",
952 "Input file name"),
953 OPT_STRING('o', "output", &kvm.file_name, "file",
954 "Output file name"),
955 OPT_BOOLEAN(0, "guest", &perf_guest,
956 "Collect guest os data"),
957 OPT_BOOLEAN(0, "host", &perf_host,
958 "Collect host os data"),
959 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
960 "guest mount directory under which every guest os"
961 " instance has a subdir"),
962 OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
963 "file", "file saving guest os vmlinux"),
964 OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
965 "file", "file saving guest os /proc/kallsyms"),
966 OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
967 "file", "file saving guest os /proc/modules"),
968 OPT_END()
969 };
970
971
972 const char * const kvm_usage[] = {
973 "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
974 NULL
975 };
976
935 perf_host = 0; 977 perf_host = 0;
936 perf_guest = 1; 978 perf_guest = 1;
937 979
@@ -943,28 +985,32 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
943 if (!perf_host) 985 if (!perf_host)
944 perf_guest = 1; 986 perf_guest = 1;
945 987
946 if (!file_name) { 988 if (!kvm.file_name) {
947 if (perf_host && !perf_guest) 989 if (perf_host && !perf_guest)
948 sprintf(name_buffer, "perf.data.host"); 990 kvm.file_name = strdup("perf.data.host");
949 else if (!perf_host && perf_guest) 991 else if (!perf_host && perf_guest)
950 sprintf(name_buffer, "perf.data.guest"); 992 kvm.file_name = strdup("perf.data.guest");
951 else 993 else
952 sprintf(name_buffer, "perf.data.kvm"); 994 kvm.file_name = strdup("perf.data.kvm");
953 file_name = name_buffer; 995
996 if (!kvm.file_name) {
997 pr_err("Failed to allocate memory for filename\n");
998 return -ENOMEM;
999 }
954 } 1000 }
955 1001
956 if (!strncmp(argv[0], "rec", 3)) 1002 if (!strncmp(argv[0], "rec", 3))
957 return __cmd_record(argc, argv); 1003 return __cmd_record(&kvm, argc, argv);
958 else if (!strncmp(argv[0], "rep", 3)) 1004 else if (!strncmp(argv[0], "rep", 3))
959 return __cmd_report(argc, argv); 1005 return __cmd_report(&kvm, argc, argv);
960 else if (!strncmp(argv[0], "diff", 4)) 1006 else if (!strncmp(argv[0], "diff", 4))
961 return cmd_diff(argc, argv, NULL); 1007 return cmd_diff(argc, argv, NULL);
962 else if (!strncmp(argv[0], "top", 3)) 1008 else if (!strncmp(argv[0], "top", 3))
963 return cmd_top(argc, argv, NULL); 1009 return cmd_top(argc, argv, NULL);
964 else if (!strncmp(argv[0], "buildid-list", 12)) 1010 else if (!strncmp(argv[0], "buildid-list", 12))
965 return __cmd_buildid_list(argc, argv); 1011 return __cmd_buildid_list(&kvm, argc, argv);
966 else if (!strncmp(argv[0], "stat", 4)) 1012 else if (!strncmp(argv[0], "stat", 4))
967 return kvm_cmd_stat(argc, argv); 1013 return kvm_cmd_stat(&kvm, argc, argv);
968 else 1014 else
969 usage_with_options(kvm_usage, kvm_options); 1015 usage_with_options(kvm_usage, kvm_options);
970 1016
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 7d6e09949880..6f5f328157aa 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -823,12 +823,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
823 return 0; 823 return 0;
824} 824}
825 825
826static struct perf_tool eops = {
827 .sample = process_sample_event,
828 .comm = perf_event__process_comm,
829 .ordered_samples = true,
830};
831
832static const struct perf_evsel_str_handler lock_tracepoints[] = { 826static const struct perf_evsel_str_handler lock_tracepoints[] = {
833 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */ 827 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */
834 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ 828 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
@@ -838,6 +832,11 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
838 832
839static int read_events(void) 833static int read_events(void)
840{ 834{
835 struct perf_tool eops = {
836 .sample = process_sample_event,
837 .comm = perf_event__process_comm,
838 .ordered_samples = true,
839 };
841 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); 840 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
842 if (!session) { 841 if (!session) {
843 pr_err("Initializing perf session failed\n"); 842 pr_err("Initializing perf session failed\n");
@@ -878,53 +877,11 @@ static int __cmd_report(void)
878 return 0; 877 return 0;
879} 878}
880 879
881static const char * const report_usage[] = {
882 "perf lock report [<options>]",
883 NULL
884};
885
886static const struct option report_options[] = {
887 OPT_STRING('k', "key", &sort_key, "acquired",
888 "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
889 /* TODO: type */
890 OPT_END()
891};
892
893static const char * const info_usage[] = {
894 "perf lock info [<options>]",
895 NULL
896};
897
898static const struct option info_options[] = {
899 OPT_BOOLEAN('t', "threads", &info_threads,
900 "dump thread list in perf.data"),
901 OPT_BOOLEAN('m', "map", &info_map,
902 "map of lock instances (address:name table)"),
903 OPT_END()
904};
905
906static const char * const lock_usage[] = {
907 "perf lock [<options>] {record|report|script|info}",
908 NULL
909};
910
911static const struct option lock_options[] = {
912 OPT_STRING('i', "input", &input_name, "file", "input file name"),
913 OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
914 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
915 OPT_END()
916};
917
918static const char *record_args[] = {
919 "record",
920 "-R",
921 "-f",
922 "-m", "1024",
923 "-c", "1",
924};
925
926static int __cmd_record(int argc, const char **argv) 880static int __cmd_record(int argc, const char **argv)
927{ 881{
882 const char *record_args[] = {
883 "record", "-R", "-f", "-m", "1024", "-c", "1",
884 };
928 unsigned int rec_argc, i, j; 885 unsigned int rec_argc, i, j;
929 const char **rec_argv; 886 const char **rec_argv;
930 887
@@ -963,6 +920,37 @@ static int __cmd_record(int argc, const char **argv)
963 920
964int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) 921int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
965{ 922{
923 const struct option info_options[] = {
924 OPT_BOOLEAN('t', "threads", &info_threads,
925 "dump thread list in perf.data"),
926 OPT_BOOLEAN('m', "map", &info_map,
927 "map of lock instances (address:name table)"),
928 OPT_END()
929 };
930 const struct option lock_options[] = {
931 OPT_STRING('i', "input", &input_name, "file", "input file name"),
932 OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
933 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
934 OPT_END()
935 };
936 const struct option report_options[] = {
937 OPT_STRING('k', "key", &sort_key, "acquired",
938 "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
939 /* TODO: type */
940 OPT_END()
941 };
942 const char * const info_usage[] = {
943 "perf lock info [<options>]",
944 NULL
945 };
946 const char * const lock_usage[] = {
947 "perf lock [<options>] {record|report|script|info}",
948 NULL
949 };
950 const char * const report_usage[] = {
951 "perf lock report [<options>]",
952 NULL
953 };
966 unsigned int i; 954 unsigned int i;
967 int rc = 0; 955 int rc = 0;
968 956
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 118aa8946573..de38a034b129 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -250,19 +250,20 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
250 return 0; 250 return 0;
251} 251}
252 252
253static const char * const probe_usage[] = { 253int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
254 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 254{
255 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 255 const char * const probe_usage[] = {
256 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 256 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
257 "perf probe --list", 257 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
258 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
259 "perf probe --list",
258#ifdef DWARF_SUPPORT 260#ifdef DWARF_SUPPORT
259 "perf probe [<options>] --line 'LINEDESC'", 261 "perf probe [<options>] --line 'LINEDESC'",
260 "perf probe [<options>] --vars 'PROBEPOINT'", 262 "perf probe [<options>] --vars 'PROBEPOINT'",
261#endif 263#endif
262 NULL 264 NULL
263}; 265};
264 266 const struct option options[] = {
265static const struct option options[] = {
266 OPT_INCR('v', "verbose", &verbose, 267 OPT_INCR('v', "verbose", &verbose,
267 "be more verbose (show parsed arguments, etc)"), 268 "be more verbose (show parsed arguments, etc)"),
268 OPT_BOOLEAN('l', "list", &params.list_events, 269 OPT_BOOLEAN('l', "list", &params.list_events,
@@ -325,10 +326,7 @@ static const struct option options[] = {
325 OPT_CALLBACK('x', "exec", NULL, "executable|path", 326 OPT_CALLBACK('x', "exec", NULL, "executable|path",
326 "target executable name or path", opt_set_target), 327 "target executable name or path", opt_set_target),
327 OPT_END() 328 OPT_END()
328}; 329 };
329
330int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
331{
332 int ret; 330 int ret;
333 331
334 argc = parse_options(argc, argv, options, probe_usage, 332 argc = parse_options(argc, argv, options, probe_usage,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f14cb5fdb91f..e9231659754d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,15 +31,6 @@
31#include <sched.h> 31#include <sched.h>
32#include <sys/mman.h> 32#include <sys/mman.h>
33 33
34#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
35
36#ifdef NO_LIBUNWIND_SUPPORT
37static char callchain_help[] = CALLCHAIN_HELP "[fp]";
38#else
39static unsigned long default_stack_dump_size = 8192;
40static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
41#endif
42
43enum write_mode_t { 34enum write_mode_t {
44 WRITE_FORCE, 35 WRITE_FORCE,
45 WRITE_APPEND 36 WRITE_APPEND
@@ -800,7 +791,7 @@ error:
800 return ret; 791 return ret;
801} 792}
802 793
803#ifndef NO_LIBUNWIND_SUPPORT 794#ifdef LIBUNWIND_SUPPORT
804static int get_stack_size(char *str, unsigned long *_size) 795static int get_stack_size(char *str, unsigned long *_size)
805{ 796{
806 char *endptr; 797 char *endptr;
@@ -826,7 +817,7 @@ static int get_stack_size(char *str, unsigned long *_size)
826 max_size, str); 817 max_size, str);
827 return -1; 818 return -1;
828} 819}
829#endif /* !NO_LIBUNWIND_SUPPORT */ 820#endif /* LIBUNWIND_SUPPORT */
830 821
831static int 822static int
832parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, 823parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
@@ -865,9 +856,11 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
865 "needed for -g fp\n"); 856 "needed for -g fp\n");
866 break; 857 break;
867 858
868#ifndef NO_LIBUNWIND_SUPPORT 859#ifdef LIBUNWIND_SUPPORT
869 /* Dwarf style */ 860 /* Dwarf style */
870 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 861 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
862 const unsigned long default_stack_dump_size = 8192;
863
871 ret = 0; 864 ret = 0;
872 rec->opts.call_graph = CALLCHAIN_DWARF; 865 rec->opts.call_graph = CALLCHAIN_DWARF;
873 rec->opts.stack_dump_size = default_stack_dump_size; 866 rec->opts.stack_dump_size = default_stack_dump_size;
@@ -883,7 +876,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
883 if (!ret) 876 if (!ret)
884 pr_debug("callchain: stack dump size %d\n", 877 pr_debug("callchain: stack dump size %d\n",
885 rec->opts.stack_dump_size); 878 rec->opts.stack_dump_size);
886#endif /* !NO_LIBUNWIND_SUPPORT */ 879#endif /* LIBUNWIND_SUPPORT */
887 } else { 880 } else {
888 pr_err("callchain: Unknown -g option " 881 pr_err("callchain: Unknown -g option "
889 "value: %s\n", arg); 882 "value: %s\n", arg);
@@ -930,6 +923,14 @@ static struct perf_record record = {
930 .file_new = true, 923 .file_new = true,
931}; 924};
932 925
926#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
927
928#ifdef LIBUNWIND_SUPPORT
929static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
930#else
931static const char callchain_help[] = CALLCHAIN_HELP "[fp]";
932#endif
933
933/* 934/*
934 * XXX Will stay a global variable till we fix builtin-script.c to stop messing 935 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
935 * with it and switch to use the library functions in perf_evlist that came 936 * with it and switch to use the library functions in perf_evlist that came
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 1da243dfbc3e..a61725d89d3e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
320 const char *evname = perf_evsel__name(pos); 320 const char *evname = perf_evsel__name(pos);
321 321
322 hists__fprintf_nr_sample_events(hists, evname, stdout); 322 hists__fprintf_nr_sample_events(hists, evname, stdout);
323 hists__fprintf(hists, NULL, false, true, 0, 0, stdout); 323 hists__fprintf(hists, true, 0, 0, stdout);
324 fprintf(stdout, "\n\n"); 324 fprintf(stdout, "\n\n");
325 } 325 }
326 326
@@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
691 setup_browser(true); 691 setup_browser(true);
692 else { 692 else {
693 use_browser = 0; 693 use_browser = 0;
694 perf_hpp__init(false, false); 694 perf_hpp__init();
695 } 695 }
696 696
697 setup_sorting(report_usage, options); 697 setup_sorting(report_usage, options);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 9b9e32eaa805..3488ead3b60c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1426,7 +1426,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1426 struct perf_evsel *evsel, 1426 struct perf_evsel *evsel,
1427 struct machine *machine) 1427 struct machine *machine)
1428{ 1428{
1429 struct thread *thread = machine__findnew_thread(machine, sample->pid); 1429 struct thread *thread = machine__findnew_thread(machine, sample->tid);
1430 int err = 0; 1430 int err = 0;
1431 1431
1432 if (thread == NULL) { 1432 if (thread == NULL) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 1be843aa1546..fb9625083a2e 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -24,7 +24,6 @@ static u64 last_timestamp;
24static u64 nr_unordered; 24static u64 nr_unordered;
25extern const struct option record_options[]; 25extern const struct option record_options[];
26static bool no_callchain; 26static bool no_callchain;
27static bool show_full_info;
28static bool system_wide; 27static bool system_wide;
29static const char *cpu_list; 28static const char *cpu_list;
30static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 29static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -473,8 +472,6 @@ static int cleanup_scripting(void)
473 return scripting_ops->stop_script(); 472 return scripting_ops->stop_script();
474} 473}
475 474
476static const char *input_name;
477
478static int process_sample_event(struct perf_tool *tool __maybe_unused, 475static int process_sample_event(struct perf_tool *tool __maybe_unused,
479 union perf_event *event, 476 union perf_event *event,
480 struct perf_sample *sample, 477 struct perf_sample *sample,
@@ -1156,20 +1153,40 @@ out:
1156 return n_args; 1153 return n_args;
1157} 1154}
1158 1155
1159static const char * const script_usage[] = { 1156static int have_cmd(int argc, const char **argv)
1160 "perf script [<options>]", 1157{
1161 "perf script [<options>] record <script> [<record-options>] <command>", 1158 char **__argv = malloc(sizeof(const char *) * argc);
1162 "perf script [<options>] report <script> [script-args]", 1159
1163 "perf script [<options>] <script> [<record-options>] <command>", 1160 if (!__argv) {
1164 "perf script [<options>] <top-script> [script-args]", 1161 pr_err("malloc failed\n");
1165 NULL 1162 return -1;
1166}; 1163 }
1164
1165 memcpy(__argv, argv, sizeof(const char *) * argc);
1166 argc = parse_options(argc, (const char **)__argv, record_options,
1167 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
1168 free(__argv);
1167 1169
1168static const struct option options[] = { 1170 system_wide = (argc == 0);
1171
1172 return 0;
1173}
1174
1175int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1176{
1177 bool show_full_info = false;
1178 const char *input_name = NULL;
1179 char *rec_script_path = NULL;
1180 char *rep_script_path = NULL;
1181 struct perf_session *session;
1182 char *script_path = NULL;
1183 const char **__argv;
1184 int i, j, err;
1185 const struct option options[] = {
1169 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1186 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1170 "dump raw trace in ASCII"), 1187 "dump raw trace in ASCII"),
1171 OPT_INCR('v', "verbose", &verbose, 1188 OPT_INCR('v', "verbose", &verbose,
1172 "be more verbose (show symbol address, etc)"), 1189 "be more verbose (show symbol address, etc)"),
1173 OPT_BOOLEAN('L', "Latency", &latency_format, 1190 OPT_BOOLEAN('L', "Latency", &latency_format,
1174 "show latency attributes (irqs/preemption disabled, etc)"), 1191 "show latency attributes (irqs/preemption disabled, etc)"),
1175 OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts", 1192 OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
@@ -1179,8 +1196,7 @@ static const struct option options[] = {
1179 parse_scriptname), 1196 parse_scriptname),
1180 OPT_STRING('g', "gen-script", &generate_script_lang, "lang", 1197 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
1181 "generate perf-script.xx script in specified language"), 1198 "generate perf-script.xx script in specified language"),
1182 OPT_STRING('i', "input", &input_name, "file", 1199 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1183 "input file name"),
1184 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 1200 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
1185 "do various checks like samples ordering and lost events"), 1201 "do various checks like samples ordering and lost events"),
1186 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1202 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
@@ -1195,10 +1211,9 @@ static const struct option options[] = {
1195 "comma separated output fields prepend with 'type:'. " 1211 "comma separated output fields prepend with 'type:'. "
1196 "Valid types: hw,sw,trace,raw. " 1212 "Valid types: hw,sw,trace,raw. "
1197 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1213 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1198 "addr,symoff", 1214 "addr,symoff", parse_output_fields),
1199 parse_output_fields),
1200 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1215 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1201 "system-wide collection from all CPUs"), 1216 "system-wide collection from all CPUs"),
1202 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1217 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
1203 "only consider these symbols"), 1218 "only consider these symbols"),
1204 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 1219 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
@@ -1208,37 +1223,16 @@ static const struct option options[] = {
1208 "display extended information from perf.data file"), 1223 "display extended information from perf.data file"),
1209 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 1224 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
1210 "Show the path of [kernel.kallsyms]"), 1225 "Show the path of [kernel.kallsyms]"),
1211
1212 OPT_END() 1226 OPT_END()
1213}; 1227 };
1214 1228 const char * const script_usage[] = {
1215static int have_cmd(int argc, const char **argv) 1229 "perf script [<options>]",
1216{ 1230 "perf script [<options>] record <script> [<record-options>] <command>",
1217 char **__argv = malloc(sizeof(const char *) * argc); 1231 "perf script [<options>] report <script> [script-args]",
1218 1232 "perf script [<options>] <script> [<record-options>] <command>",
1219 if (!__argv) { 1233 "perf script [<options>] <top-script> [script-args]",
1220 pr_err("malloc failed\n"); 1234 NULL
1221 return -1; 1235 };
1222 }
1223
1224 memcpy(__argv, argv, sizeof(const char *) * argc);
1225 argc = parse_options(argc, (const char **)__argv, record_options,
1226 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
1227 free(__argv);
1228
1229 system_wide = (argc == 0);
1230
1231 return 0;
1232}
1233
1234int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1235{
1236 char *rec_script_path = NULL;
1237 char *rep_script_path = NULL;
1238 struct perf_session *session;
1239 char *script_path = NULL;
1240 const char **__argv;
1241 int i, j, err;
1242 1236
1243 setup_scripting(); 1237 setup_scripting();
1244 1238
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e8cd4d81b06e..93b9011fa3e2 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -64,122 +64,12 @@
64#define CNTR_NOT_SUPPORTED "<not supported>" 64#define CNTR_NOT_SUPPORTED "<not supported>"
65#define CNTR_NOT_COUNTED "<not counted>" 65#define CNTR_NOT_COUNTED "<not counted>"
66 66
67static struct perf_event_attr default_attrs[] = {
68
69 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
70 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES },
71 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS },
72 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS },
73
74 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES },
75 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
76 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
77 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS },
78 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
79 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES },
80
81};
82
83/*
84 * Detailed stats (-d), covering the L1 and last level data caches:
85 */
86static struct perf_event_attr detailed_attrs[] = {
87
88 { .type = PERF_TYPE_HW_CACHE,
89 .config =
90 PERF_COUNT_HW_CACHE_L1D << 0 |
91 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
92 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
93
94 { .type = PERF_TYPE_HW_CACHE,
95 .config =
96 PERF_COUNT_HW_CACHE_L1D << 0 |
97 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
98 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
99
100 { .type = PERF_TYPE_HW_CACHE,
101 .config =
102 PERF_COUNT_HW_CACHE_LL << 0 |
103 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
104 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
105
106 { .type = PERF_TYPE_HW_CACHE,
107 .config =
108 PERF_COUNT_HW_CACHE_LL << 0 |
109 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
110 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
111};
112
113/*
114 * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
115 */
116static struct perf_event_attr very_detailed_attrs[] = {
117
118 { .type = PERF_TYPE_HW_CACHE,
119 .config =
120 PERF_COUNT_HW_CACHE_L1I << 0 |
121 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
122 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
123
124 { .type = PERF_TYPE_HW_CACHE,
125 .config =
126 PERF_COUNT_HW_CACHE_L1I << 0 |
127 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
128 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
129
130 { .type = PERF_TYPE_HW_CACHE,
131 .config =
132 PERF_COUNT_HW_CACHE_DTLB << 0 |
133 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
134 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
135
136 { .type = PERF_TYPE_HW_CACHE,
137 .config =
138 PERF_COUNT_HW_CACHE_DTLB << 0 |
139 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
140 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
141
142 { .type = PERF_TYPE_HW_CACHE,
143 .config =
144 PERF_COUNT_HW_CACHE_ITLB << 0 |
145 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
146 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
147
148 { .type = PERF_TYPE_HW_CACHE,
149 .config =
150 PERF_COUNT_HW_CACHE_ITLB << 0 |
151 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
152 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
153
154};
155
156/*
157 * Very, very detailed stats (-d -d -d), adding prefetch events:
158 */
159static struct perf_event_attr very_very_detailed_attrs[] = {
160
161 { .type = PERF_TYPE_HW_CACHE,
162 .config =
163 PERF_COUNT_HW_CACHE_L1D << 0 |
164 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
165 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
166
167 { .type = PERF_TYPE_HW_CACHE,
168 .config =
169 PERF_COUNT_HW_CACHE_L1D << 0 |
170 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
171 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
172};
173
174
175
176static struct perf_evlist *evsel_list; 67static struct perf_evlist *evsel_list;
177 68
178static struct perf_target target = { 69static struct perf_target target = {
179 .uid = UINT_MAX, 70 .uid = UINT_MAX,
180}; 71};
181 72
182static int run_idx = 0;
183static int run_count = 1; 73static int run_count = 1;
184static bool no_inherit = false; 74static bool no_inherit = false;
185static bool scale = true; 75static bool scale = true;
@@ -187,15 +77,12 @@ static bool no_aggr = false;
187static pid_t child_pid = -1; 77static pid_t child_pid = -1;
188static bool null_run = false; 78static bool null_run = false;
189static int detailed_run = 0; 79static int detailed_run = 0;
190static bool sync_run = false;
191static bool big_num = true; 80static bool big_num = true;
192static int big_num_opt = -1; 81static int big_num_opt = -1;
193static const char *csv_sep = NULL; 82static const char *csv_sep = NULL;
194static bool csv_output = false; 83static bool csv_output = false;
195static bool group = false; 84static bool group = false;
196static const char *output_name = NULL;
197static FILE *output = NULL; 85static FILE *output = NULL;
198static int output_fd;
199 86
200static volatile int done = 0; 87static volatile int done = 0;
201 88
@@ -1028,11 +915,6 @@ static void sig_atexit(void)
1028 kill(getpid(), signr); 915 kill(getpid(), signr);
1029} 916}
1030 917
1031static const char * const stat_usage[] = {
1032 "perf stat [<options>] [<command>]",
1033 NULL
1034};
1035
1036static int stat__set_big_num(const struct option *opt __maybe_unused, 918static int stat__set_big_num(const struct option *opt __maybe_unused,
1037 const char *s __maybe_unused, int unset) 919 const char *s __maybe_unused, int unset)
1038{ 920{
@@ -1040,62 +922,119 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
1040 return 0; 922 return 0;
1041} 923}
1042 924
1043static bool append_file;
1044
1045static const struct option options[] = {
1046 OPT_CALLBACK('e', "event", &evsel_list, "event",
1047 "event selector. use 'perf list' to list available events",
1048 parse_events_option),
1049 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1050 "event filter", parse_filter),
1051 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1052 "child tasks do not inherit counters"),
1053 OPT_STRING('p', "pid", &target.pid, "pid",
1054 "stat events on existing process id"),
1055 OPT_STRING('t', "tid", &target.tid, "tid",
1056 "stat events on existing thread id"),
1057 OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
1058 "system-wide collection from all CPUs"),
1059 OPT_BOOLEAN('g', "group", &group,
1060 "put the counters into a counter group"),
1061 OPT_BOOLEAN('c', "scale", &scale,
1062 "scale/normalize counters"),
1063 OPT_INCR('v', "verbose", &verbose,
1064 "be more verbose (show counter open errors, etc)"),
1065 OPT_INTEGER('r', "repeat", &run_count,
1066 "repeat command and print average + stddev (max: 100)"),
1067 OPT_BOOLEAN('n', "null", &null_run,
1068 "null run - dont start any counters"),
1069 OPT_INCR('d', "detailed", &detailed_run,
1070 "detailed run - start a lot of events"),
1071 OPT_BOOLEAN('S', "sync", &sync_run,
1072 "call sync() before starting a run"),
1073 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1074 "print large numbers with thousands\' separators",
1075 stat__set_big_num),
1076 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
1077 "list of cpus to monitor in system-wide"),
1078 OPT_BOOLEAN('A', "no-aggr", &no_aggr,
1079 "disable CPU count aggregation"),
1080 OPT_STRING('x', "field-separator", &csv_sep, "separator",
1081 "print counts with custom separator"),
1082 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1083 "monitor event in cgroup name only",
1084 parse_cgroups),
1085 OPT_STRING('o', "output", &output_name, "file",
1086 "output file name"),
1087 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1088 OPT_INTEGER(0, "log-fd", &output_fd,
1089 "log output to fd, instead of stderr"),
1090 OPT_END()
1091};
1092
1093/* 925/*
1094 * Add default attributes, if there were no attributes specified or 926 * Add default attributes, if there were no attributes specified or
1095 * if -d/--detailed, -d -d or -d -d -d is used: 927 * if -d/--detailed, -d -d or -d -d -d is used:
1096 */ 928 */
1097static int add_default_attributes(void) 929static int add_default_attributes(void)
1098{ 930{
931 struct perf_event_attr default_attrs[] = {
932
933 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
934 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES },
935 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS },
936 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS },
937
938 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES },
939 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
940 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
941 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS },
942 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
943 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES },
944
945};
946
947/*
948 * Detailed stats (-d), covering the L1 and last level data caches:
949 */
950 struct perf_event_attr detailed_attrs[] = {
951
952 { .type = PERF_TYPE_HW_CACHE,
953 .config =
954 PERF_COUNT_HW_CACHE_L1D << 0 |
955 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
956 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
957
958 { .type = PERF_TYPE_HW_CACHE,
959 .config =
960 PERF_COUNT_HW_CACHE_L1D << 0 |
961 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
962 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
963
964 { .type = PERF_TYPE_HW_CACHE,
965 .config =
966 PERF_COUNT_HW_CACHE_LL << 0 |
967 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
968 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
969
970 { .type = PERF_TYPE_HW_CACHE,
971 .config =
972 PERF_COUNT_HW_CACHE_LL << 0 |
973 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
974 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
975};
976
977/*
978 * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
979 */
980 struct perf_event_attr very_detailed_attrs[] = {
981
982 { .type = PERF_TYPE_HW_CACHE,
983 .config =
984 PERF_COUNT_HW_CACHE_L1I << 0 |
985 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
986 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
987
988 { .type = PERF_TYPE_HW_CACHE,
989 .config =
990 PERF_COUNT_HW_CACHE_L1I << 0 |
991 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
992 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
993
994 { .type = PERF_TYPE_HW_CACHE,
995 .config =
996 PERF_COUNT_HW_CACHE_DTLB << 0 |
997 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
998 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
999
1000 { .type = PERF_TYPE_HW_CACHE,
1001 .config =
1002 PERF_COUNT_HW_CACHE_DTLB << 0 |
1003 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1004 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1005
1006 { .type = PERF_TYPE_HW_CACHE,
1007 .config =
1008 PERF_COUNT_HW_CACHE_ITLB << 0 |
1009 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1010 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1011
1012 { .type = PERF_TYPE_HW_CACHE,
1013 .config =
1014 PERF_COUNT_HW_CACHE_ITLB << 0 |
1015 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1016 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1017
1018};
1019
1020/*
1021 * Very, very detailed stats (-d -d -d), adding prefetch events:
1022 */
1023 struct perf_event_attr very_very_detailed_attrs[] = {
1024
1025 { .type = PERF_TYPE_HW_CACHE,
1026 .config =
1027 PERF_COUNT_HW_CACHE_L1D << 0 |
1028 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
1029 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1030
1031 { .type = PERF_TYPE_HW_CACHE,
1032 .config =
1033 PERF_COUNT_HW_CACHE_L1D << 0 |
1034 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
1035 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1036};
1037
1099 /* Set attrs if no event is selected and !null_run: */ 1038 /* Set attrs if no event is selected and !null_run: */
1100 if (null_run) 1039 if (null_run)
1101 return 0; 1040 return 0;
@@ -1130,8 +1069,59 @@ static int add_default_attributes(void)
1130 1069
1131int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) 1070int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1132{ 1071{
1072 bool append_file = false,
1073 sync_run = false;
1074 int output_fd = 0;
1075 const char *output_name = NULL;
1076 const struct option options[] = {
1077 OPT_CALLBACK('e', "event", &evsel_list, "event",
1078 "event selector. use 'perf list' to list available events",
1079 parse_events_option),
1080 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1081 "event filter", parse_filter),
1082 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1083 "child tasks do not inherit counters"),
1084 OPT_STRING('p', "pid", &target.pid, "pid",
1085 "stat events on existing process id"),
1086 OPT_STRING('t', "tid", &target.tid, "tid",
1087 "stat events on existing thread id"),
1088 OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
1089 "system-wide collection from all CPUs"),
1090 OPT_BOOLEAN('g', "group", &group,
1091 "put the counters into a counter group"),
1092 OPT_BOOLEAN('c', "scale", &scale, "scale/normalize counters"),
1093 OPT_INCR('v', "verbose", &verbose,
1094 "be more verbose (show counter open errors, etc)"),
1095 OPT_INTEGER('r', "repeat", &run_count,
1096 "repeat command and print average + stddev (max: 100)"),
1097 OPT_BOOLEAN('n', "null", &null_run,
1098 "null run - dont start any counters"),
1099 OPT_INCR('d', "detailed", &detailed_run,
1100 "detailed run - start a lot of events"),
1101 OPT_BOOLEAN('S', "sync", &sync_run,
1102 "call sync() before starting a run"),
1103 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1104 "print large numbers with thousands\' separators",
1105 stat__set_big_num),
1106 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
1107 "list of cpus to monitor in system-wide"),
1108 OPT_BOOLEAN('A', "no-aggr", &no_aggr, "disable CPU count aggregation"),
1109 OPT_STRING('x', "field-separator", &csv_sep, "separator",
1110 "print counts with custom separator"),
1111 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1112 "monitor event in cgroup name only", parse_cgroups),
1113 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1114 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1115 OPT_INTEGER(0, "log-fd", &output_fd,
1116 "log output to fd, instead of stderr"),
1117 OPT_END()
1118 };
1119 const char * const stat_usage[] = {
1120 "perf stat [<options>] [<command>]",
1121 NULL
1122 };
1133 struct perf_evsel *pos; 1123 struct perf_evsel *pos;
1134 int status = -ENOMEM; 1124 int status = -ENOMEM, run_idx;
1135 const char *mode; 1125 const char *mode;
1136 1126
1137 setlocale(LC_ALL, ""); 1127 setlocale(LC_ALL, "");
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index b1a8a3b841cc..f251b613b2f3 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -38,9 +38,6 @@
38#define PWR_EVENT_EXIT -1 38#define PWR_EVENT_EXIT -1
39 39
40 40
41static const char *input_name;
42static const char *output_name = "output.svg";
43
44static unsigned int numcpus; 41static unsigned int numcpus;
45static u64 min_freq; /* Lowest CPU frequency seen */ 42static u64 min_freq; /* Lowest CPU frequency seen */
46static u64 max_freq; /* Highest CPU frequency seen */ 43static u64 max_freq; /* Highest CPU frequency seen */
@@ -968,16 +965,15 @@ static void write_svg_file(const char *filename)
968 svg_close(); 965 svg_close();
969} 966}
970 967
971static struct perf_tool perf_timechart = { 968static int __cmd_timechart(const char *input_name, const char *output_name)
972 .comm = process_comm_event,
973 .fork = process_fork_event,
974 .exit = process_exit_event,
975 .sample = process_sample_event,
976 .ordered_samples = true,
977};
978
979static int __cmd_timechart(void)
980{ 969{
970 struct perf_tool perf_timechart = {
971 .comm = process_comm_event,
972 .fork = process_fork_event,
973 .exit = process_exit_event,
974 .sample = process_sample_event,
975 .ordered_samples = true,
976 };
981 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 977 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
982 0, false, &perf_timechart); 978 0, false, &perf_timechart);
983 int ret = -EINVAL; 979 int ret = -EINVAL;
@@ -1005,40 +1001,25 @@ out_delete:
1005 return ret; 1001 return ret;
1006} 1002}
1007 1003
1008static const char * const timechart_usage[] = {
1009 "perf timechart [<options>] {record}",
1010 NULL
1011};
1012
1013#ifdef SUPPORT_OLD_POWER_EVENTS
1014static const char * const record_old_args[] = {
1015 "record",
1016 "-a",
1017 "-R",
1018 "-f",
1019 "-c", "1",
1020 "-e", "power:power_start",
1021 "-e", "power:power_end",
1022 "-e", "power:power_frequency",
1023 "-e", "sched:sched_wakeup",
1024 "-e", "sched:sched_switch",
1025};
1026#endif
1027
1028static const char * const record_new_args[] = {
1029 "record",
1030 "-a",
1031 "-R",
1032 "-f",
1033 "-c", "1",
1034 "-e", "power:cpu_frequency",
1035 "-e", "power:cpu_idle",
1036 "-e", "sched:sched_wakeup",
1037 "-e", "sched:sched_switch",
1038};
1039
1040static int __cmd_record(int argc, const char **argv) 1004static int __cmd_record(int argc, const char **argv)
1041{ 1005{
1006#ifdef SUPPORT_OLD_POWER_EVENTS
1007 const char * const record_old_args[] = {
1008 "record", "-a", "-R", "-f", "-c", "1",
1009 "-e", "power:power_start",
1010 "-e", "power:power_end",
1011 "-e", "power:power_frequency",
1012 "-e", "sched:sched_wakeup",
1013 "-e", "sched:sched_switch",
1014 };
1015#endif
1016 const char * const record_new_args[] = {
1017 "record", "-a", "-R", "-f", "-c", "1",
1018 "-e", "power:cpu_frequency",
1019 "-e", "power:cpu_idle",
1020 "-e", "sched:sched_wakeup",
1021 "-e", "sched:sched_switch",
1022 };
1042 unsigned int rec_argc, i, j; 1023 unsigned int rec_argc, i, j;
1043 const char **rec_argv; 1024 const char **rec_argv;
1044 const char * const *record_args = record_new_args; 1025 const char * const *record_args = record_new_args;
@@ -1077,27 +1058,28 @@ parse_process(const struct option *opt __maybe_unused, const char *arg,
1077 return 0; 1058 return 0;
1078} 1059}
1079 1060
1080static const struct option options[] = { 1061int cmd_timechart(int argc, const char **argv,
1081 OPT_STRING('i', "input", &input_name, "file", 1062 const char *prefix __maybe_unused)
1082 "input file name"), 1063{
1083 OPT_STRING('o', "output", &output_name, "file", 1064 const char *input_name;
1084 "output file name"), 1065 const char *output_name = "output.svg";
1085 OPT_INTEGER('w', "width", &svg_page_width, 1066 const struct option options[] = {
1086 "page width"), 1067 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1087 OPT_BOOLEAN('P', "power-only", &power_only, 1068 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1088 "output power data only"), 1069 OPT_INTEGER('w', "width", &svg_page_width, "page width"),
1070 OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
1089 OPT_CALLBACK('p', "process", NULL, "process", 1071 OPT_CALLBACK('p', "process", NULL, "process",
1090 "process selector. Pass a pid or process name.", 1072 "process selector. Pass a pid or process name.",
1091 parse_process), 1073 parse_process),
1092 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1074 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1093 "Look for files with symbols relative to this directory"), 1075 "Look for files with symbols relative to this directory"),
1094 OPT_END() 1076 OPT_END()
1095}; 1077 };
1096 1078 const char * const timechart_usage[] = {
1079 "perf timechart [<options>] {record}",
1080 NULL
1081 };
1097 1082
1098int cmd_timechart(int argc, const char **argv,
1099 const char *prefix __maybe_unused)
1100{
1101 argc = parse_options(argc, argv, options, timechart_usage, 1083 argc = parse_options(argc, argv, options, timechart_usage,
1102 PARSE_OPT_STOP_AT_NON_OPTION); 1084 PARSE_OPT_STOP_AT_NON_OPTION);
1103 1085
@@ -1110,5 +1092,5 @@ int cmd_timechart(int argc, const char **argv,
1110 1092
1111 setup_pager(); 1093 setup_pager();
1112 1094
1113 return __cmd_timechart(); 1095 return __cmd_timechart(input_name, output_name);
1114} 1096}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e434a16bb5ac..ff6db8086805 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -316,7 +316,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
316 hists__output_recalc_col_len(&top->sym_evsel->hists, 316 hists__output_recalc_col_len(&top->sym_evsel->hists,
317 top->winsize.ws_row - 3); 317 top->winsize.ws_row - 3);
318 putchar('\n'); 318 putchar('\n');
319 hists__fprintf(&top->sym_evsel->hists, NULL, false, false, 319 hists__fprintf(&top->sym_evsel->hists, false,
320 top->winsize.ws_row - 4 - printed, win_width, stdout); 320 top->winsize.ws_row - 4 - printed, win_width, stdout);
321} 321}
322 322
@@ -1159,11 +1159,6 @@ setup:
1159 return 0; 1159 return 0;
1160} 1160}
1161 1161
1162static const char * const top_usage[] = {
1163 "perf top [<options>]",
1164 NULL
1165};
1166
1167int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1162int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1168{ 1163{
1169 struct perf_evsel *pos; 1164 struct perf_evsel *pos;
@@ -1250,6 +1245,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1250 OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"), 1245 OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
1251 OPT_END() 1246 OPT_END()
1252 }; 1247 };
1248 const char * const top_usage[] = {
1249 "perf top [<options>]",
1250 NULL
1251 };
1253 1252
1254 top.evlist = perf_evlist__new(NULL, NULL); 1253 top.evlist = perf_evlist__new(NULL, NULL);
1255 if (top.evlist == NULL) 1254 if (top.evlist == NULL)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 8f113dab8bf1..dec8ced61fb0 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -114,10 +114,85 @@ static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FIL
114 return printed; 114 return printed;
115} 115}
116 116
117typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
118 struct perf_sample *sample);
119
120static struct syscall *trace__syscall_info(struct trace *trace,
121 struct perf_evsel *evsel,
122 struct perf_sample *sample)
123{
124 int id = perf_evsel__intval(evsel, sample, "id");
125
126 if (id < 0) {
127 printf("Invalid syscall %d id, skipping...\n", id);
128 return NULL;
129 }
130
131 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
132 trace__read_syscall_info(trace, id))
133 goto out_cant_read;
134
135 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
136 goto out_cant_read;
137
138 return &trace->syscalls.table[id];
139
140out_cant_read:
141 printf("Problems reading syscall %d information\n", id);
142 return NULL;
143}
144
145static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
146 struct perf_sample *sample)
147{
148 void *args;
149 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
150
151 if (sc == NULL)
152 return -1;
153
154 args = perf_evsel__rawptr(evsel, sample, "args");
155 if (args == NULL) {
156 printf("Problems reading syscall arguments\n");
157 return -1;
158 }
159
160 printf("%s(", sc->name);
161 syscall__fprintf_args(sc, args, stdout);
162
163 return 0;
164}
165
166static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
167 struct perf_sample *sample)
168{
169 int ret;
170 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
171
172 if (sc == NULL)
173 return -1;
174
175 ret = perf_evsel__intval(evsel, sample, "ret");
176
177 if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
178 char bf[256];
179 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
180 *e = audit_errno_to_name(-ret);
181
182 printf(") = -1 %s %s", e, emsg);
183 } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
184 printf(") = 0 Timeout");
185 else
186 printf(") = %d", ret);
187
188 putchar('\n');
189 return 0;
190}
191
117static int trace__run(struct trace *trace) 192static int trace__run(struct trace *trace)
118{ 193{
119 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); 194 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
120 struct perf_evsel *evsel, *evsel_enter, *evsel_exit; 195 struct perf_evsel *evsel;
121 int err = -1, i, nr_events = 0, before; 196 int err = -1, i, nr_events = 0, before;
122 197
123 if (evlist == NULL) { 198 if (evlist == NULL) {
@@ -125,22 +200,12 @@ static int trace__run(struct trace *trace)
125 goto out; 200 goto out;
126 } 201 }
127 202
128 evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0); 203 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
129 if (evsel_enter == NULL) { 204 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
130 printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n"); 205 printf("Couldn't read the raw_syscalls tracepoints information!\n");
131 goto out_delete_evlist;
132 }
133
134 perf_evlist__add(evlist, evsel_enter);
135
136 evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
137 if (evsel_exit == NULL) {
138 printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
139 goto out_delete_evlist; 206 goto out_delete_evlist;
140 } 207 }
141 208
142 perf_evlist__add(evlist, evsel_exit);
143
144 err = perf_evlist__create_maps(evlist, &trace->opts.target); 209 err = perf_evlist__create_maps(evlist, &trace->opts.target);
145 if (err < 0) { 210 if (err < 0) {
146 printf("Problems parsing the target to trace, check your options!\n"); 211 printf("Problems parsing the target to trace, check your options!\n");
@@ -170,9 +235,8 @@ again:
170 235
171 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 236 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
172 const u32 type = event->header.type; 237 const u32 type = event->header.type;
173 struct syscall *sc; 238 tracepoint_handler handler;
174 struct perf_sample sample; 239 struct perf_sample sample;
175 int id;
176 240
177 ++nr_events; 241 ++nr_events;
178 242
@@ -200,45 +264,11 @@ again:
200 continue; 264 continue;
201 } 265 }
202 266
203 id = perf_evsel__intval(evsel, &sample, "id");
204 if (id < 0) {
205 printf("Invalid syscall %d id, skipping...\n", id);
206 continue;
207 }
208
209 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
210 trace__read_syscall_info(trace, id))
211 continue;
212
213 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
214 continue;
215
216 sc = &trace->syscalls.table[id];
217
218 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1) 267 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
219 printf("%d ", sample.tid); 268 printf("%d ", sample.tid);
220 269
221 if (evsel == evsel_enter) { 270 handler = evsel->handler.func;
222 void *args = perf_evsel__rawptr(evsel, &sample, "args"); 271 handler(trace, evsel, &sample);
223
224 printf("%s(", sc->name);
225 syscall__fprintf_args(sc, args, stdout);
226 } else if (evsel == evsel_exit) {
227 int ret = perf_evsel__intval(evsel, &sample, "ret");
228
229 if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
230 char bf[256];
231 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
232 *e = audit_errno_to_name(-ret);
233
234 printf(") = -1 %s %s", e, emsg);
235 } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
236 printf(") = 0 Timeout");
237 else
238 printf(") = %d", ret);
239
240 putchar('\n');
241 }
242 } 272 }
243 } 273 }
244 274
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index fc2f770e3027..6d50eb0b4251 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -48,14 +48,14 @@ static struct cmd_struct commands[] = {
48 { "version", cmd_version, 0 }, 48 { "version", cmd_version, 0 },
49 { "script", cmd_script, 0 }, 49 { "script", cmd_script, 0 },
50 { "sched", cmd_sched, 0 }, 50 { "sched", cmd_sched, 0 },
51#ifndef NO_LIBELF_SUPPORT 51#ifdef LIBELF_SUPPORT
52 { "probe", cmd_probe, 0 }, 52 { "probe", cmd_probe, 0 },
53#endif 53#endif
54 { "kmem", cmd_kmem, 0 }, 54 { "kmem", cmd_kmem, 0 },
55 { "lock", cmd_lock, 0 }, 55 { "lock", cmd_lock, 0 },
56 { "kvm", cmd_kvm, 0 }, 56 { "kvm", cmd_kvm, 0 },
57 { "test", cmd_test, 0 }, 57 { "test", cmd_test, 0 },
58#ifndef NO_LIBAUDIT_SUPPORT 58#ifdef LIBAUDIT_SUPPORT
59 { "trace", cmd_trace, 0 }, 59 { "trace", cmd_trace, 0 },
60#endif 60#endif
61 { "inject", cmd_inject, 0 }, 61 { "inject", cmd_inject, 0 },
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a21f40bebbac..0568536ecf67 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -569,7 +569,8 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
569static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ 569static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \
570 struct hist_entry *he) \ 570 struct hist_entry *he) \
571{ \ 571{ \
572 double percent = 100.0 * he->_field / hpp->total_period; \ 572 struct hists *hists = he->hists; \
573 double percent = 100.0 * he->stat._field / hists->stats.total_period; \
573 *(double *)hpp->ptr = percent; \ 574 *(double *)hpp->ptr = percent; \
574 return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \ 575 return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \
575} 576}
@@ -584,7 +585,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
584 585
585void hist_browser__init_hpp(void) 586void hist_browser__init_hpp(void)
586{ 587{
587 perf_hpp__init(false, false); 588 perf_hpp__init();
588 589
589 perf_hpp__format[PERF_HPP__OVERHEAD].color = 590 perf_hpp__format[PERF_HPP__OVERHEAD].color =
590 hist_browser__hpp_color_overhead; 591 hist_browser__hpp_color_overhead;
@@ -624,7 +625,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
624 struct perf_hpp hpp = { 625 struct perf_hpp hpp = {
625 .buf = s, 626 .buf = s,
626 .size = sizeof(s), 627 .size = sizeof(s),
627 .total_period = browser->hists->stats.total_period,
628 }; 628 };
629 629
630 ui_browser__gotorc(&browser->b, row, 0); 630 ui_browser__gotorc(&browser->b, row, 0);
@@ -982,7 +982,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
982 folded_sign = hist_entry__folded(he); 982 folded_sign = hist_entry__folded(he);
983 983
984 hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists); 984 hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists);
985 percent = (he->period * 100.0) / browser->hists->stats.total_period; 985 percent = (he->stat.period * 100.0) / browser->hists->stats.total_period;
986 986
987 if (symbol_conf.use_callchain) 987 if (symbol_conf.use_callchain)
988 printed += fprintf(fp, "%c ", folded_sign); 988 printed += fprintf(fp, "%c ", folded_sign);
@@ -990,10 +990,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
990 printed += fprintf(fp, " %5.2f%%", percent); 990 printed += fprintf(fp, " %5.2f%%", percent);
991 991
992 if (symbol_conf.show_nr_samples) 992 if (symbol_conf.show_nr_samples)
993 printed += fprintf(fp, " %11u", he->nr_events); 993 printed += fprintf(fp, " %11u", he->stat.nr_events);
994 994
995 if (symbol_conf.show_total_period) 995 if (symbol_conf.show_total_period)
996 printed += fprintf(fp, " %12" PRIu64, he->period); 996 printed += fprintf(fp, " %12" PRIu64, he->stat.period);
997 997
998 printed += fprintf(fp, "%s\n", rtrim(s)); 998 printed += fprintf(fp, "%s\n", rtrim(s));
999 999
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 7ff99ec1d95e..4125c6284114 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -49,7 +49,8 @@ static const char *perf_gtk__get_percent_color(double percent)
49static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ 49static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \
50 struct hist_entry *he) \ 50 struct hist_entry *he) \
51{ \ 51{ \
52 double percent = 100.0 * he->_field / hpp->total_period; \ 52 struct hists *hists = he->hists; \
53 double percent = 100.0 * he->stat._field / hists->stats.total_period; \
53 const char *markup; \ 54 const char *markup; \
54 int ret = 0; \ 55 int ret = 0; \
55 \ 56 \
@@ -73,7 +74,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
73 74
74void perf_gtk__init_hpp(void) 75void perf_gtk__init_hpp(void)
75{ 76{
76 perf_hpp__init(false, false); 77 perf_hpp__init();
77 78
78 perf_hpp__format[PERF_HPP__OVERHEAD].color = 79 perf_hpp__format[PERF_HPP__OVERHEAD].color =
79 perf_gtk__hpp_color_overhead; 80 perf_gtk__hpp_color_overhead;
@@ -102,7 +103,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
102 struct perf_hpp hpp = { 103 struct perf_hpp hpp = {
103 .buf = s, 104 .buf = s,
104 .size = sizeof(s), 105 .size = sizeof(s),
105 .total_period = hists->stats.total_period,
106 }; 106 };
107 107
108 nr_cols = 0; 108 nr_cols = 0;
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index 8aada5b3c04c..ccb046aac98b 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -116,7 +116,7 @@ struct perf_error_ops perf_gtk_eops = {
116 * FIXME: Functions below should be implemented properly. 116 * FIXME: Functions below should be implemented properly.
117 * For now, just add stubs for NO_NEWT=1 build. 117 * For now, just add stubs for NO_NEWT=1 build.
118 */ 118 */
119#ifdef NO_NEWT_SUPPORT 119#ifndef NEWT_SUPPORT
120void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused, 120void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused,
121 const char *title __maybe_unused) 121 const char *title __maybe_unused)
122{ 122{
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index 2b667ee454c3..baa28a4d16b9 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -23,25 +23,25 @@ void ui_helpline__puts(const char *msg);
23 23
24extern char ui_helpline__current[512]; 24extern char ui_helpline__current[512];
25 25
26#ifdef NO_NEWT_SUPPORT 26#ifdef NEWT_SUPPORT
27extern char ui_helpline__last_msg[];
28int ui_helpline__show_help(const char *format, va_list ap);
29#else
27static inline int ui_helpline__show_help(const char *format __maybe_unused, 30static inline int ui_helpline__show_help(const char *format __maybe_unused,
28 va_list ap __maybe_unused) 31 va_list ap __maybe_unused)
29{ 32{
30 return 0; 33 return 0;
31} 34}
32#else 35#endif /* NEWT_SUPPORT */
33extern char ui_helpline__last_msg[];
34int ui_helpline__show_help(const char *format, va_list ap);
35#endif /* NO_NEWT_SUPPORT */
36 36
37#ifdef NO_GTK2_SUPPORT 37#ifdef GTK2_SUPPORT
38int perf_gtk__show_helpline(const char *format, va_list ap);
39#else
38static inline int perf_gtk__show_helpline(const char *format __maybe_unused, 40static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
39 va_list ap __maybe_unused) 41 va_list ap __maybe_unused)
40{ 42{
41 return 0; 43 return 0;
42} 44}
43#else 45#endif /* GTK2_SUPPORT */
44int perf_gtk__show_helpline(const char *format, va_list ap);
45#endif /* NO_GTK2_SUPPORT */
46 46
47#endif /* _PERF_UI_HELPLINE_H_ */ 47#endif /* _PERF_UI_HELPLINE_H_ */
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index e3f8cd46e7d7..f5a1e4f65263 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -8,9 +8,7 @@
8/* hist period print (hpp) functions */ 8/* hist period print (hpp) functions */
9static int hpp__header_overhead(struct perf_hpp *hpp) 9static int hpp__header_overhead(struct perf_hpp *hpp)
10{ 10{
11 const char *fmt = hpp->ptr ? "Baseline" : "Overhead"; 11 return scnprintf(hpp->buf, hpp->size, "Overhead");
12
13 return scnprintf(hpp->buf, hpp->size, fmt);
14} 12}
15 13
16static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) 14static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
@@ -20,38 +18,18 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
20 18
21static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) 19static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
22{ 20{
23 double percent = 100.0 * he->period / hpp->total_period; 21 struct hists *hists = he->hists;
24 22 double percent = 100.0 * he->stat.period / hists->stats.total_period;
25 if (hpp->ptr) {
26 struct hists *old_hists = hpp->ptr;
27 u64 total_period = old_hists->stats.total_period;
28 u64 base_period = he->pair ? he->pair->period : 0;
29
30 if (total_period)
31 percent = 100.0 * base_period / total_period;
32 else
33 percent = 0.0;
34 }
35 23
36 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); 24 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
37} 25}
38 26
39static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) 27static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
40{ 28{
41 double percent = 100.0 * he->period / hpp->total_period; 29 struct hists *hists = he->hists;
30 double percent = 100.0 * he->stat.period / hists->stats.total_period;
42 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; 31 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
43 32
44 if (hpp->ptr) {
45 struct hists *old_hists = hpp->ptr;
46 u64 total_period = old_hists->stats.total_period;
47 u64 base_period = he->pair ? he->pair->period : 0;
48
49 if (total_period)
50 percent = 100.0 * base_period / total_period;
51 else
52 percent = 0.0;
53 }
54
55 return scnprintf(hpp->buf, hpp->size, fmt, percent); 33 return scnprintf(hpp->buf, hpp->size, fmt, percent);
56} 34}
57 35
@@ -69,13 +47,16 @@ static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
69 47
70static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) 48static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
71{ 49{
72 double percent = 100.0 * he->period_sys / hpp->total_period; 50 struct hists *hists = he->hists;
51 double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
52
73 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); 53 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
74} 54}
75 55
76static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) 56static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
77{ 57{
78 double percent = 100.0 * he->period_sys / hpp->total_period; 58 struct hists *hists = he->hists;
59 double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
79 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; 60 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
80 61
81 return scnprintf(hpp->buf, hpp->size, fmt, percent); 62 return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -95,13 +76,16 @@ static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
95 76
96static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) 77static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
97{ 78{
98 double percent = 100.0 * he->period_us / hpp->total_period; 79 struct hists *hists = he->hists;
80 double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
81
99 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); 82 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
100} 83}
101 84
102static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) 85static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
103{ 86{
104 double percent = 100.0 * he->period_us / hpp->total_period; 87 struct hists *hists = he->hists;
88 double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
105 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; 89 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
106 90
107 return scnprintf(hpp->buf, hpp->size, fmt, percent); 91 return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -120,14 +104,17 @@ static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
120static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, 104static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
121 struct hist_entry *he) 105 struct hist_entry *he)
122{ 106{
123 double percent = 100.0 * he->period_guest_sys / hpp->total_period; 107 struct hists *hists = he->hists;
108 double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
109
124 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); 110 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
125} 111}
126 112
127static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, 113static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
128 struct hist_entry *he) 114 struct hist_entry *he)
129{ 115{
130 double percent = 100.0 * he->period_guest_sys / hpp->total_period; 116 struct hists *hists = he->hists;
117 double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
131 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; 118 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
132 119
133 return scnprintf(hpp->buf, hpp->size, fmt, percent); 120 return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -146,19 +133,63 @@ static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
146static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, 133static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
147 struct hist_entry *he) 134 struct hist_entry *he)
148{ 135{
149 double percent = 100.0 * he->period_guest_us / hpp->total_period; 136 struct hists *hists = he->hists;
137 double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
138
150 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); 139 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
151} 140}
152 141
153static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, 142static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
154 struct hist_entry *he) 143 struct hist_entry *he)
155{ 144{
156 double percent = 100.0 * he->period_guest_us / hpp->total_period; 145 struct hists *hists = he->hists;
146 double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
157 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; 147 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
158 148
159 return scnprintf(hpp->buf, hpp->size, fmt, percent); 149 return scnprintf(hpp->buf, hpp->size, fmt, percent);
160} 150}
161 151
152static int hpp__header_baseline(struct perf_hpp *hpp)
153{
154 return scnprintf(hpp->buf, hpp->size, "Baseline");
155}
156
157static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
158{
159 return 8;
160}
161
162static double baseline_percent(struct hist_entry *he)
163{
164 struct hist_entry *pair = he->pair;
165 struct hists *pair_hists = pair ? pair->hists : NULL;
166 double percent = 0.0;
167
168 if (pair) {
169 u64 total_period = pair_hists->stats.total_period;
170 u64 base_period = pair->stat.period;
171
172 percent = 100.0 * base_period / total_period;
173 }
174
175 return percent;
176}
177
178static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
179{
180 double percent = baseline_percent(he);
181
182 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
183}
184
185static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
186{
187 double percent = baseline_percent(he);
188 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
189
190 return scnprintf(hpp->buf, hpp->size, fmt, percent);
191}
192
162static int hpp__header_samples(struct perf_hpp *hpp) 193static int hpp__header_samples(struct perf_hpp *hpp)
163{ 194{
164 const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; 195 const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
@@ -175,7 +206,7 @@ static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
175{ 206{
176 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; 207 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
177 208
178 return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events); 209 return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
179} 210}
180 211
181static int hpp__header_period(struct perf_hpp *hpp) 212static int hpp__header_period(struct perf_hpp *hpp)
@@ -194,7 +225,7 @@ static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
194{ 225{
195 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; 226 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
196 227
197 return scnprintf(hpp->buf, hpp->size, fmt, he->period); 228 return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
198} 229}
199 230
200static int hpp__header_delta(struct perf_hpp *hpp) 231static int hpp__header_delta(struct perf_hpp *hpp)
@@ -211,20 +242,22 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
211 242
212static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) 243static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
213{ 244{
214 struct hists *pair_hists = hpp->ptr; 245 struct hist_entry *pair = he->pair;
246 struct hists *pair_hists = pair ? pair->hists : NULL;
247 struct hists *hists = he->hists;
215 u64 old_total, new_total; 248 u64 old_total, new_total;
216 double old_percent = 0, new_percent = 0; 249 double old_percent = 0, new_percent = 0;
217 double diff; 250 double diff;
218 const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; 251 const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
219 char buf[32] = " "; 252 char buf[32] = " ";
220 253
221 old_total = pair_hists->stats.total_period; 254 old_total = pair_hists ? pair_hists->stats.total_period : 0;
222 if (old_total > 0 && he->pair) 255 if (old_total > 0 && pair)
223 old_percent = 100.0 * he->pair->period / old_total; 256 old_percent = 100.0 * pair->stat.period / old_total;
224 257
225 new_total = hpp->total_period; 258 new_total = hists->stats.total_period;
226 if (new_total > 0) 259 if (new_total > 0)
227 new_percent = 100.0 * he->period / new_total; 260 new_percent = 100.0 * he->stat.period / new_total;
228 261
229 diff = new_percent - old_percent; 262 diff = new_percent - old_percent;
230 if (fabs(diff) >= 0.01) 263 if (fabs(diff) >= 0.01)
@@ -244,13 +277,15 @@ static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
244} 277}
245 278
246static int hpp__entry_displ(struct perf_hpp *hpp, 279static int hpp__entry_displ(struct perf_hpp *hpp,
247 struct hist_entry *he __maybe_unused) 280 struct hist_entry *he)
248{ 281{
282 struct hist_entry *pair = he->pair;
283 long displacement = pair ? pair->position - he->position : 0;
249 const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; 284 const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
250 char buf[32] = " "; 285 char buf[32] = " ";
251 286
252 if (hpp->displacement) 287 if (displacement)
253 scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement); 288 scnprintf(buf, sizeof(buf), "%+4ld", displacement);
254 289
255 return scnprintf(hpp->buf, hpp->size, fmt, buf); 290 return scnprintf(hpp->buf, hpp->size, fmt, buf);
256} 291}
@@ -267,6 +302,7 @@ static int hpp__entry_displ(struct perf_hpp *hpp,
267 .entry = hpp__entry_ ## _name 302 .entry = hpp__entry_ ## _name
268 303
269struct perf_hpp_fmt perf_hpp__format[] = { 304struct perf_hpp_fmt perf_hpp__format[] = {
305 { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
270 { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, 306 { .cond = true, HPP__COLOR_PRINT_FNS(overhead) },
271 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, 307 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
272 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, 308 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
@@ -281,7 +317,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
281#undef HPP__COLOR_PRINT_FNS 317#undef HPP__COLOR_PRINT_FNS
282#undef HPP__PRINT_FNS 318#undef HPP__PRINT_FNS
283 319
284void perf_hpp__init(bool need_pair, bool show_displacement) 320void perf_hpp__init(void)
285{ 321{
286 if (symbol_conf.show_cpu_utilization) { 322 if (symbol_conf.show_cpu_utilization) {
287 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; 323 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
@@ -298,13 +334,12 @@ void perf_hpp__init(bool need_pair, bool show_displacement)
298 334
299 if (symbol_conf.show_total_period) 335 if (symbol_conf.show_total_period)
300 perf_hpp__format[PERF_HPP__PERIOD].cond = true; 336 perf_hpp__format[PERF_HPP__PERIOD].cond = true;
337}
301 338
302 if (need_pair) { 339void perf_hpp__column_enable(unsigned col, bool enable)
303 perf_hpp__format[PERF_HPP__DELTA].cond = true; 340{
304 341 BUG_ON(col >= PERF_HPP__MAX_INDEX);
305 if (show_displacement) 342 perf_hpp__format[col].cond = enable;
306 perf_hpp__format[PERF_HPP__DISPL].cond = true;
307 }
308} 343}
309 344
310static inline void advance_hpp(struct perf_hpp *hpp, int inc) 345static inline void advance_hpp(struct perf_hpp *hpp, int inc)
@@ -319,6 +354,7 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
319 const char *sep = symbol_conf.field_sep; 354 const char *sep = symbol_conf.field_sep;
320 char *start = hpp->buf; 355 char *start = hpp->buf;
321 int i, ret; 356 int i, ret;
357 bool first = true;
322 358
323 if (symbol_conf.exclude_other && !he->parent) 359 if (symbol_conf.exclude_other && !he->parent)
324 return 0; 360 return 0;
@@ -327,9 +363,10 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
327 if (!perf_hpp__format[i].cond) 363 if (!perf_hpp__format[i].cond)
328 continue; 364 continue;
329 365
330 if (!sep || i > 0) { 366 if (!sep || !first) {
331 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); 367 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
332 advance_hpp(hpp, ret); 368 advance_hpp(hpp, ret);
369 first = false;
333 } 370 }
334 371
335 if (color && perf_hpp__format[i].color) 372 if (color && perf_hpp__format[i].color)
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index bd7d460f844c..ebb4cc107876 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -30,7 +30,7 @@ void setup_browser(bool fallback_to_pager)
30 if (fallback_to_pager) 30 if (fallback_to_pager)
31 setup_pager(); 31 setup_pager();
32 32
33 perf_hpp__init(false, false); 33 perf_hpp__init();
34 break; 34 break;
35 } 35 }
36} 36}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 882461a42830..fbd4e32d0743 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -271,7 +271,7 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
271{ 271{
272 switch (callchain_param.mode) { 272 switch (callchain_param.mode) {
273 case CHAIN_GRAPH_REL: 273 case CHAIN_GRAPH_REL:
274 return callchain__fprintf_graph(fp, &he->sorted_chain, he->period, 274 return callchain__fprintf_graph(fp, &he->sorted_chain, he->stat.period,
275 left_margin); 275 left_margin);
276 break; 276 break;
277 case CHAIN_GRAPH_ABS: 277 case CHAIN_GRAPH_ABS:
@@ -292,9 +292,10 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
292 292
293static size_t hist_entry__callchain_fprintf(struct hist_entry *he, 293static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
294 struct hists *hists, 294 struct hists *hists,
295 u64 total_period, FILE *fp) 295 FILE *fp)
296{ 296{
297 int left_margin = 0; 297 int left_margin = 0;
298 u64 total_period = hists->stats.total_period;
298 299
299 if (sort__first_dimension == SORT_COMM) { 300 if (sort__first_dimension == SORT_COMM) {
300 struct sort_entry *se = list_first_entry(&hist_entry__sort_list, 301 struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
@@ -307,17 +308,13 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
307} 308}
308 309
309static int hist_entry__fprintf(struct hist_entry *he, size_t size, 310static int hist_entry__fprintf(struct hist_entry *he, size_t size,
310 struct hists *hists, struct hists *pair_hists, 311 struct hists *hists, FILE *fp)
311 long displacement, u64 total_period, FILE *fp)
312{ 312{
313 char bf[512]; 313 char bf[512];
314 int ret; 314 int ret;
315 struct perf_hpp hpp = { 315 struct perf_hpp hpp = {
316 .buf = bf, 316 .buf = bf,
317 .size = size, 317 .size = size,
318 .total_period = total_period,
319 .displacement = displacement,
320 .ptr = pair_hists,
321 }; 318 };
322 bool color = !symbol_conf.field_sep; 319 bool color = !symbol_conf.field_sep;
323 320
@@ -330,22 +327,17 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
330 ret = fprintf(fp, "%s\n", bf); 327 ret = fprintf(fp, "%s\n", bf);
331 328
332 if (symbol_conf.use_callchain) 329 if (symbol_conf.use_callchain)
333 ret += hist_entry__callchain_fprintf(he, hists, 330 ret += hist_entry__callchain_fprintf(he, hists, fp);
334 total_period, fp);
335 331
336 return ret; 332 return ret;
337} 333}
338 334
339size_t hists__fprintf(struct hists *hists, struct hists *pair, 335size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
340 bool show_displacement, bool show_header, int max_rows,
341 int max_cols, FILE *fp) 336 int max_cols, FILE *fp)
342{ 337{
343 struct sort_entry *se; 338 struct sort_entry *se;
344 struct rb_node *nd; 339 struct rb_node *nd;
345 size_t ret = 0; 340 size_t ret = 0;
346 u64 total_period;
347 unsigned long position = 1;
348 long displacement = 0;
349 unsigned int width; 341 unsigned int width;
350 const char *sep = symbol_conf.field_sep; 342 const char *sep = symbol_conf.field_sep;
351 const char *col_width = symbol_conf.col_width_list_str; 343 const char *col_width = symbol_conf.col_width_list_str;
@@ -354,8 +346,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
354 struct perf_hpp dummy_hpp = { 346 struct perf_hpp dummy_hpp = {
355 .buf = bf, 347 .buf = bf,
356 .size = sizeof(bf), 348 .size = sizeof(bf),
357 .ptr = pair,
358 }; 349 };
350 bool first = true;
359 351
360 init_rem_hits(); 352 init_rem_hits();
361 353
@@ -367,8 +359,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
367 if (!perf_hpp__format[idx].cond) 359 if (!perf_hpp__format[idx].cond)
368 continue; 360 continue;
369 361
370 if (idx) 362 if (!first)
371 fprintf(fp, "%s", sep ?: " "); 363 fprintf(fp, "%s", sep ?: " ");
364 else
365 first = false;
372 366
373 perf_hpp__format[idx].header(&dummy_hpp); 367 perf_hpp__format[idx].header(&dummy_hpp);
374 fprintf(fp, "%s", bf); 368 fprintf(fp, "%s", bf);
@@ -403,6 +397,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
403 if (sep) 397 if (sep)
404 goto print_entries; 398 goto print_entries;
405 399
400 first = true;
401
406 fprintf(fp, "# "); 402 fprintf(fp, "# ");
407 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { 403 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
408 unsigned int i; 404 unsigned int i;
@@ -410,8 +406,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
410 if (!perf_hpp__format[idx].cond) 406 if (!perf_hpp__format[idx].cond)
411 continue; 407 continue;
412 408
413 if (idx) 409 if (!first)
414 fprintf(fp, "%s", sep ?: " "); 410 fprintf(fp, "%s", sep ?: " ");
411 else
412 first = false;
415 413
416 width = perf_hpp__format[idx].width(&dummy_hpp); 414 width = perf_hpp__format[idx].width(&dummy_hpp);
417 for (i = 0; i < width; i++) 415 for (i = 0; i < width; i++)
@@ -441,24 +439,13 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
441 goto out; 439 goto out;
442 440
443print_entries: 441print_entries:
444 total_period = hists->stats.total_period;
445
446 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 442 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
447 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 443 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
448 444
449 if (h->filtered) 445 if (h->filtered)
450 continue; 446 continue;
451 447
452 if (show_displacement) { 448 ret += hist_entry__fprintf(h, max_cols, hists, fp);
453 if (h->pair != NULL)
454 displacement = ((long)h->pair->position -
455 (long)position);
456 else
457 displacement = 0;
458 ++position;
459 }
460 ret += hist_entry__fprintf(h, max_cols, hists, pair, displacement,
461 total_period, fp);
462 449
463 if (max_rows && ++nr_rows >= max_rows) 450 if (max_rows && ++nr_rows >= max_rows)
464 goto out; 451 goto out;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 9b5b21e7b032..39242dcee8f2 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -138,7 +138,10 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
138 bool print_lines, bool full_paths, int min_pcnt, 138 bool print_lines, bool full_paths, int min_pcnt,
139 int max_lines); 139 int max_lines);
140 140
141#ifdef NO_NEWT_SUPPORT 141#ifdef NEWT_SUPPORT
142int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
143 void(*timer)(void *arg), void *arg, int delay_secs);
144#else
142static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, 145static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
143 struct map *map __maybe_unused, 146 struct map *map __maybe_unused,
144 int evidx __maybe_unused, 147 int evidx __maybe_unused,
@@ -148,9 +151,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
148{ 151{
149 return 0; 152 return 0;
150} 153}
151#else
152int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
153 void(*timer)(void *arg), void *arg, int delay_secs);
154#endif 154#endif
155 155
156extern const char *disassembler_style; 156extern const char *disassembler_style;
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index ab1769426541..2bd51370ad28 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -33,39 +33,41 @@ extern int pager_use_color;
33 33
34extern int use_browser; 34extern int use_browser;
35 35
36#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) 36#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
37static inline void setup_browser(bool fallback_to_pager)
38{
39 if (fallback_to_pager)
40 setup_pager();
41}
42static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
43#else
44void setup_browser(bool fallback_to_pager); 37void setup_browser(bool fallback_to_pager);
45void exit_browser(bool wait_for_ok); 38void exit_browser(bool wait_for_ok);
46 39
47#ifdef NO_NEWT_SUPPORT 40#ifdef NEWT_SUPPORT
41int ui__init(void);
42void ui__exit(bool wait_for_ok);
43#else
48static inline int ui__init(void) 44static inline int ui__init(void)
49{ 45{
50 return -1; 46 return -1;
51} 47}
52static inline void ui__exit(bool wait_for_ok __maybe_unused) {} 48static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
53#else
54int ui__init(void);
55void ui__exit(bool wait_for_ok);
56#endif 49#endif
57 50
58#ifdef NO_GTK2_SUPPORT 51#ifdef GTK2_SUPPORT
52int perf_gtk__init(void);
53void perf_gtk__exit(bool wait_for_ok);
54#else
59static inline int perf_gtk__init(void) 55static inline int perf_gtk__init(void)
60{ 56{
61 return -1; 57 return -1;
62} 58}
63static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {} 59static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
64#else
65int perf_gtk__init(void);
66void perf_gtk__exit(bool wait_for_ok);
67#endif 60#endif
68#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */ 61
62#else /* NEWT_SUPPORT || GTK2_SUPPORT */
63
64static inline void setup_browser(bool fallback_to_pager)
65{
66 if (fallback_to_pager)
67 setup_pager();
68}
69static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
70#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
69 71
70char *alias_lookup(const char *alias); 72char *alias_lookup(const char *alias);
71int split_cmdline(char *cmdline, const char ***argv); 73int split_cmdline(char *cmdline, const char ***argv);
@@ -105,7 +107,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
105extern char *perf_pathdup(const char *fmt, ...) 107extern char *perf_pathdup(const char *fmt, ...)
106 __attribute__((format (printf, 1, 2))); 108 __attribute__((format (printf, 1, 2)));
107 109
108#ifdef NO_STRLCPY 110#ifndef HAVE_STRLCPY
109extern size_t strlcpy(char *dest, const char *src, size_t size); 111extern size_t strlcpy(char *dest, const char *src, size_t size);
110#endif 112#endif
111 113
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 66eb3828ceb5..03f830b48148 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -49,7 +49,7 @@ int dump_printf(const char *fmt, ...)
49 return ret; 49 return ret;
50} 50}
51 51
52#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) 52#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
53int ui__warning(const char *format, ...) 53int ui__warning(const char *format, ...)
54{ 54{
55 va_list args; 55 va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index bb2e7d1007ab..dec98750b484 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -15,7 +15,14 @@ void trace_event(union perf_event *event);
15struct ui_progress; 15struct ui_progress;
16struct perf_error_ops; 16struct perf_error_ops;
17 17
18#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) 18#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
19
20#include "../ui/progress.h"
21int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
22#include "../ui/util.h"
23
24#else
25
19static inline void ui_progress__update(u64 curr __maybe_unused, 26static inline void ui_progress__update(u64 curr __maybe_unused,
20 u64 total __maybe_unused, 27 u64 total __maybe_unused,
21 const char *title __maybe_unused) {} 28 const char *title __maybe_unused) {}
@@ -34,13 +41,7 @@ perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
34 return 0; 41 return 0;
35} 42}
36 43
37#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */ 44#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
38
39#include "../ui/progress.h"
40int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
41#include "../ui/util.h"
42
43#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
44 45
45int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 46int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
46int ui__error_paranoid(void); 47int ui__error_paranoid(void);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index ae89686102f4..186b87730396 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -154,8 +154,8 @@ error:
154 return -ENOMEM; 154 return -ENOMEM;
155} 155}
156 156
157int perf_evlist__add_attrs(struct perf_evlist *evlist, 157static int perf_evlist__add_attrs(struct perf_evlist *evlist,
158 struct perf_event_attr *attrs, size_t nr_attrs) 158 struct perf_event_attr *attrs, size_t nr_attrs)
159{ 159{
160 struct perf_evsel *evsel, *n; 160 struct perf_evsel *evsel, *n;
161 LIST_HEAD(head); 161 LIST_HEAD(head);
@@ -189,60 +189,6 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
189 return perf_evlist__add_attrs(evlist, attrs, nr_attrs); 189 return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
190} 190}
191 191
192static int trace_event__id(const char *evname)
193{
194 char *filename, *colon;
195 int err = -1, fd;
196
197 if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
198 return -1;
199
200 colon = strrchr(filename, ':');
201 if (colon != NULL)
202 *colon = '/';
203
204 fd = open(filename, O_RDONLY);
205 if (fd >= 0) {
206 char id[16];
207 if (read(fd, id, sizeof(id)) > 0)
208 err = atoi(id);
209 close(fd);
210 }
211
212 free(filename);
213 return err;
214}
215
216int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
217 const char *tracepoints[],
218 size_t nr_tracepoints)
219{
220 int err;
221 size_t i;
222 struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
223
224 if (attrs == NULL)
225 return -1;
226
227 for (i = 0; i < nr_tracepoints; i++) {
228 err = trace_event__id(tracepoints[i]);
229
230 if (err < 0)
231 goto out_free_attrs;
232
233 attrs[i].type = PERF_TYPE_TRACEPOINT;
234 attrs[i].config = err;
235 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
236 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
237 attrs[i].sample_period = 1;
238 }
239
240 err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
241out_free_attrs:
242 free(attrs);
243 return err;
244}
245
246struct perf_evsel * 192struct perf_evsel *
247perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 193perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
248{ 194{
@@ -257,32 +203,18 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
257 return NULL; 203 return NULL;
258} 204}
259 205
260int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, 206int perf_evlist__add_newtp(struct perf_evlist *evlist,
261 const struct perf_evsel_str_handler *assocs, 207 const char *sys, const char *name, void *handler)
262 size_t nr_assocs)
263{ 208{
264 struct perf_evsel *evsel; 209 struct perf_evsel *evsel;
265 int err;
266 size_t i;
267
268 for (i = 0; i < nr_assocs; i++) {
269 err = trace_event__id(assocs[i].name);
270 if (err < 0)
271 goto out;
272
273 evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
274 if (evsel == NULL)
275 continue;
276 210
277 err = -EEXIST; 211 evsel = perf_evsel__newtp(sys, name, evlist->nr_entries);
278 if (evsel->handler.func != NULL) 212 if (evsel == NULL)
279 goto out; 213 return -1;
280 evsel->handler.func = assocs[i].handler;
281 }
282 214
283 err = 0; 215 evsel->handler.func = handler;
284out: 216 perf_evlist__add(evlist, evsel);
285 return err; 217 return 0;
286} 218}
287 219
288void perf_evlist__disable(struct perf_evlist *evlist) 220void perf_evlist__disable(struct perf_evlist *evlist)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 3f1fb66be022..56003f779e60 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -51,26 +51,14 @@ void perf_evlist__delete(struct perf_evlist *evlist);
51 51
52void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 52void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
53int perf_evlist__add_default(struct perf_evlist *evlist); 53int perf_evlist__add_default(struct perf_evlist *evlist);
54int perf_evlist__add_attrs(struct perf_evlist *evlist,
55 struct perf_event_attr *attrs, size_t nr_attrs);
56int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 54int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
57 struct perf_event_attr *attrs, size_t nr_attrs); 55 struct perf_event_attr *attrs, size_t nr_attrs);
58int perf_evlist__add_tracepoints(struct perf_evlist *evlist, 56
59 const char *tracepoints[], size_t nr_tracepoints);
60int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
61 const struct perf_evsel_str_handler *assocs,
62 size_t nr_assocs);
63
64#define perf_evlist__add_attrs_array(evlist, array) \
65 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
66#define perf_evlist__add_default_attrs(evlist, array) \ 57#define perf_evlist__add_default_attrs(evlist, array) \
67 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) 58 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
68 59
69#define perf_evlist__add_tracepoints_array(evlist, array) \ 60int perf_evlist__add_newtp(struct perf_evlist *evlist,
70 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array)) 61 const char *sys, const char *name, void *handler);
71
72#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
73 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
74 62
75int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); 63int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
76 64
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 389590c1ad21..3ac38031d534 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -22,7 +22,7 @@ do
22 }' "Documentation/perf-$cmd.txt" 22 }' "Documentation/perf-$cmd.txt"
23done 23done
24 24
25echo "#ifndef NO_LIBELF_SUPPORT" 25echo "#ifdef LIBELF_SUPPORT"
26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt | 26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt |
27sort | 27sort |
28while read cmd 28while read cmd
@@ -35,5 +35,5 @@ do
35 p 35 p
36 }' "Documentation/perf-$cmd.txt" 36 }' "Documentation/perf-$cmd.txt"
37done 37done
38echo "#endif /* NO_LIBELF_SUPPORT */" 38echo "#endif /* LIBELF_SUPPORT */"
39echo "};" 39echo "};"
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 236bc9d98ff2..277947a669b2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -135,31 +135,47 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he,
135{ 135{
136 switch (cpumode) { 136 switch (cpumode) {
137 case PERF_RECORD_MISC_KERNEL: 137 case PERF_RECORD_MISC_KERNEL:
138 he->period_sys += period; 138 he->stat.period_sys += period;
139 break; 139 break;
140 case PERF_RECORD_MISC_USER: 140 case PERF_RECORD_MISC_USER:
141 he->period_us += period; 141 he->stat.period_us += period;
142 break; 142 break;
143 case PERF_RECORD_MISC_GUEST_KERNEL: 143 case PERF_RECORD_MISC_GUEST_KERNEL:
144 he->period_guest_sys += period; 144 he->stat.period_guest_sys += period;
145 break; 145 break;
146 case PERF_RECORD_MISC_GUEST_USER: 146 case PERF_RECORD_MISC_GUEST_USER:
147 he->period_guest_us += period; 147 he->stat.period_guest_us += period;
148 break; 148 break;
149 default: 149 default:
150 break; 150 break;
151 } 151 }
152} 152}
153 153
154static void he_stat__add_period(struct he_stat *he_stat, u64 period)
155{
156 he_stat->period += period;
157 he_stat->nr_events += 1;
158}
159
160static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
161{
162 dest->period += src->period;
163 dest->period_sys += src->period_sys;
164 dest->period_us += src->period_us;
165 dest->period_guest_sys += src->period_guest_sys;
166 dest->period_guest_us += src->period_guest_us;
167 dest->nr_events += src->nr_events;
168}
169
154static void hist_entry__decay(struct hist_entry *he) 170static void hist_entry__decay(struct hist_entry *he)
155{ 171{
156 he->period = (he->period * 7) / 8; 172 he->stat.period = (he->stat.period * 7) / 8;
157 he->nr_events = (he->nr_events * 7) / 8; 173 he->stat.nr_events = (he->stat.nr_events * 7) / 8;
158} 174}
159 175
160static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) 176static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
161{ 177{
162 u64 prev_period = he->period; 178 u64 prev_period = he->stat.period;
163 179
164 if (prev_period == 0) 180 if (prev_period == 0)
165 return true; 181 return true;
@@ -167,9 +183,9 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
167 hist_entry__decay(he); 183 hist_entry__decay(he);
168 184
169 if (!he->filtered) 185 if (!he->filtered)
170 hists->stats.total_period -= prev_period - he->period; 186 hists->stats.total_period -= prev_period - he->stat.period;
171 187
172 return he->period == 0; 188 return he->stat.period == 0;
173} 189}
174 190
175static void __hists__decay_entries(struct hists *hists, bool zap_user, 191static void __hists__decay_entries(struct hists *hists, bool zap_user,
@@ -223,7 +239,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
223 239
224 if (he != NULL) { 240 if (he != NULL) {
225 *he = *template; 241 *he = *template;
226 he->nr_events = 1; 242
227 if (he->ms.map) 243 if (he->ms.map)
228 he->ms.map->referenced = true; 244 he->ms.map->referenced = true;
229 if (symbol_conf.use_callchain) 245 if (symbol_conf.use_callchain)
@@ -238,7 +254,7 @@ static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
238 if (!h->filtered) { 254 if (!h->filtered) {
239 hists__calc_col_len(hists, h); 255 hists__calc_col_len(hists, h);
240 ++hists->nr_entries; 256 ++hists->nr_entries;
241 hists->stats.total_period += h->period; 257 hists->stats.total_period += h->stat.period;
242 } 258 }
243} 259}
244 260
@@ -270,8 +286,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
270 cmp = hist_entry__cmp(entry, he); 286 cmp = hist_entry__cmp(entry, he);
271 287
272 if (!cmp) { 288 if (!cmp) {
273 he->period += period; 289 he_stat__add_period(&he->stat, period);
274 ++he->nr_events;
275 290
276 /* If the map of an existing hist_entry has 291 /* If the map of an existing hist_entry has
277 * become out-of-date due to an exec() or 292 * become out-of-date due to an exec() or
@@ -321,10 +336,14 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
321 .cpu = al->cpu, 336 .cpu = al->cpu,
322 .ip = bi->to.addr, 337 .ip = bi->to.addr,
323 .level = al->level, 338 .level = al->level,
324 .period = period, 339 .stat = {
340 .period = period,
341 .nr_events = 1,
342 },
325 .parent = sym_parent, 343 .parent = sym_parent,
326 .filtered = symbol__parent_filter(sym_parent), 344 .filtered = symbol__parent_filter(sym_parent),
327 .branch_info = bi, 345 .branch_info = bi,
346 .hists = self,
328 }; 347 };
329 348
330 return add_hist_entry(self, &entry, al, period); 349 return add_hist_entry(self, &entry, al, period);
@@ -343,9 +362,13 @@ struct hist_entry *__hists__add_entry(struct hists *self,
343 .cpu = al->cpu, 362 .cpu = al->cpu,
344 .ip = al->addr, 363 .ip = al->addr,
345 .level = al->level, 364 .level = al->level,
346 .period = period, 365 .stat = {
366 .period = period,
367 .nr_events = 1,
368 },
347 .parent = sym_parent, 369 .parent = sym_parent,
348 .filtered = symbol__parent_filter(sym_parent), 370 .filtered = symbol__parent_filter(sym_parent),
371 .hists = self,
349 }; 372 };
350 373
351 return add_hist_entry(self, &entry, al, period); 374 return add_hist_entry(self, &entry, al, period);
@@ -410,12 +433,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
410 cmp = hist_entry__collapse(iter, he); 433 cmp = hist_entry__collapse(iter, he);
411 434
412 if (!cmp) { 435 if (!cmp) {
413 iter->period += he->period; 436 he_stat__add_stat(&iter->stat, &he->stat);
414 iter->period_sys += he->period_sys;
415 iter->period_us += he->period_us;
416 iter->period_guest_sys += he->period_guest_sys;
417 iter->period_guest_us += he->period_guest_us;
418 iter->nr_events += he->nr_events;
419 437
420 if (symbol_conf.use_callchain) { 438 if (symbol_conf.use_callchain) {
421 callchain_cursor_reset(&callchain_cursor); 439 callchain_cursor_reset(&callchain_cursor);
@@ -518,7 +536,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
518 parent = *p; 536 parent = *p;
519 iter = rb_entry(parent, struct hist_entry, rb_node); 537 iter = rb_entry(parent, struct hist_entry, rb_node);
520 538
521 if (he->period > iter->period) 539 if (he->stat.period > iter->stat.period)
522 p = &(*p)->rb_left; 540 p = &(*p)->rb_left;
523 else 541 else
524 p = &(*p)->rb_right; 542 p = &(*p)->rb_right;
@@ -579,8 +597,8 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
579 if (h->ms.unfolded) 597 if (h->ms.unfolded)
580 hists->nr_entries += h->nr_rows; 598 hists->nr_entries += h->nr_rows;
581 h->row_offset = 0; 599 h->row_offset = 0;
582 hists->stats.total_period += h->period; 600 hists->stats.total_period += h->stat.period;
583 hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events; 601 hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;
584 602
585 hists__calc_col_len(hists, h); 603 hists__calc_col_len(hists, h);
586} 604}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index f011ad4756e8..66cb31fe81d2 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -98,9 +98,8 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows);
98void hists__inc_nr_events(struct hists *self, u32 type); 98void hists__inc_nr_events(struct hists *self, u32 type);
99size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); 99size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
100 100
101size_t hists__fprintf(struct hists *self, struct hists *pair, 101size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
102 bool show_displacement, bool show_header, 102 int max_cols, FILE *fp);
103 int max_rows, int max_cols, FILE *fp);
104 103
105int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); 104int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
106int hist_entry__annotate(struct hist_entry *self, size_t privsize); 105int hist_entry__annotate(struct hist_entry *self, size_t privsize);
@@ -118,9 +117,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
118struct perf_hpp { 117struct perf_hpp {
119 char *buf; 118 char *buf;
120 size_t size; 119 size_t size;
121 u64 total_period;
122 const char *sep; 120 const char *sep;
123 long displacement;
124 void *ptr; 121 void *ptr;
125}; 122};
126 123
@@ -135,6 +132,7 @@ struct perf_hpp_fmt {
135extern struct perf_hpp_fmt perf_hpp__format[]; 132extern struct perf_hpp_fmt perf_hpp__format[];
136 133
137enum { 134enum {
135 PERF_HPP__BASELINE,
138 PERF_HPP__OVERHEAD, 136 PERF_HPP__OVERHEAD,
139 PERF_HPP__OVERHEAD_SYS, 137 PERF_HPP__OVERHEAD_SYS,
140 PERF_HPP__OVERHEAD_US, 138 PERF_HPP__OVERHEAD_US,
@@ -148,13 +146,22 @@ enum {
148 PERF_HPP__MAX_INDEX 146 PERF_HPP__MAX_INDEX
149}; 147};
150 148
151void perf_hpp__init(bool need_pair, bool show_displacement); 149void perf_hpp__init(void);
150void perf_hpp__column_enable(unsigned col, bool enable);
152int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, 151int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
153 bool color); 152 bool color);
154 153
155struct perf_evlist; 154struct perf_evlist;
156 155
157#ifdef NO_NEWT_SUPPORT 156#ifdef NEWT_SUPPORT
157#include "../ui/keysyms.h"
158int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
159 void(*timer)(void *arg), void *arg, int delay_secs);
160
161int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
162 void(*timer)(void *arg), void *arg,
163 int refresh);
164#else
158static inline 165static inline
159int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, 166int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
160 const char *help __maybe_unused, 167 const char *help __maybe_unused,
@@ -177,17 +184,13 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self
177} 184}
178#define K_LEFT -1 185#define K_LEFT -1
179#define K_RIGHT -2 186#define K_RIGHT -2
180#else 187#endif
181#include "../ui/keysyms.h"
182int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
183 void(*timer)(void *arg), void *arg, int delay_secs);
184 188
185int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 189#ifdef GTK2_SUPPORT
190int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
186 void(*timer)(void *arg), void *arg, 191 void(*timer)(void *arg), void *arg,
187 int refresh); 192 int refresh);
188#endif 193#else
189
190#ifdef NO_GTK2_SUPPORT
191static inline 194static inline
192int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, 195int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
193 const char *help __maybe_unused, 196 const char *help __maybe_unused,
@@ -197,11 +200,6 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
197{ 200{
198 return 0; 201 return 0;
199} 202}
200
201#else
202int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
203 void(*timer)(void *arg), void *arg,
204 int refresh);
205#endif 203#endif
206 204
207unsigned int hists__sort_list_width(struct hists *self); 205unsigned int hists__sort_list_width(struct hists *self);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index ead5316b3f89..6109fa4d14cd 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -162,7 +162,7 @@ int map__load(struct map *self, symbol_filter_t filter)
162 pr_warning(", continuing without symbols\n"); 162 pr_warning(", continuing without symbols\n");
163 return -1; 163 return -1;
164 } else if (nr == 0) { 164 } else if (nr == 0) {
165#ifndef NO_LIBELF_SUPPORT 165#ifdef LIBELF_SUPPORT
166 const size_t len = strlen(name); 166 const size_t len = strlen(name);
167 const size_t real_len = len - sizeof(DSO__DELETED); 167 const size_t real_len = len - sizeof(DSO__DELETED);
168 168
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 443fc116512b..2bc9e70df7e2 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -384,6 +384,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
384 return usage_with_options_internal(usagestr, options, 1); 384 return usage_with_options_internal(usagestr, options, 1);
385 if (internal_help && !strcmp(arg + 2, "help")) 385 if (internal_help && !strcmp(arg + 2, "help"))
386 return parse_options_usage(usagestr, options); 386 return parse_options_usage(usagestr, options);
387 if (!strcmp(arg + 2, "list-opts"))
388 return PARSE_OPT_LIST;
387 switch (parse_long_opt(ctx, arg + 2, options)) { 389 switch (parse_long_opt(ctx, arg + 2, options)) {
388 case -1: 390 case -1:
389 return parse_options_usage(usagestr, options); 391 return parse_options_usage(usagestr, options);
@@ -422,6 +424,12 @@ int parse_options(int argc, const char **argv, const struct option *options,
422 exit(129); 424 exit(129);
423 case PARSE_OPT_DONE: 425 case PARSE_OPT_DONE:
424 break; 426 break;
427 case PARSE_OPT_LIST:
428 while (options->type != OPTION_END) {
429 printf("--%s ", options->long_name);
430 options++;
431 }
432 exit(130);
425 default: /* PARSE_OPT_UNKNOWN */ 433 default: /* PARSE_OPT_UNKNOWN */
426 if (ctx.argv[0][1] == '-') { 434 if (ctx.argv[0][1] == '-') {
427 error("unknown option `%s'", ctx.argv[0] + 2); 435 error("unknown option `%s'", ctx.argv[0] + 2);
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index abc31a1dac1a..7bb5999940ca 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -140,6 +140,7 @@ extern NORETURN void usage_with_options(const char * const *usagestr,
140enum { 140enum {
141 PARSE_OPT_HELP = -1, 141 PARSE_OPT_HELP = -1,
142 PARSE_OPT_DONE, 142 PARSE_OPT_DONE,
143 PARSE_OPT_LIST,
143 PARSE_OPT_UNKNOWN, 144 PARSE_OPT_UNKNOWN,
144}; 145};
145 146
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index bd7497711424..a8c49548ca48 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,7 +22,7 @@ static const char *get_perf_dir(void)
22 return "."; 22 return ".";
23} 23}
24 24
25#ifdef NO_STRLCPY 25#ifndef HAVE_STRLCPY
26size_t strlcpy(char *dest, const char *src, size_t size) 26size_t strlcpy(char *dest, const char *src, size_t size)
27{ 27{
28 size_t ret = strlen(src); 28 size_t ret = strlen(src);
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 316dbe7f86ed..5a4f2b6f3738 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_REGS_H 1#ifndef __PERF_REGS_H
2#define __PERF_REGS_H 2#define __PERF_REGS_H
3 3
4#ifndef NO_PERF_REGS 4#ifdef HAVE_PERF_REGS
5#include <perf_regs.h> 5#include <perf_regs.h>
6#else 6#else
7#define PERF_REGS_MASK 0 7#define PERF_REGS_MASK 0
@@ -10,5 +10,5 @@ static inline const char *perf_reg_name(int id __maybe_unused)
10{ 10{
11 return NULL; 11 return NULL;
12} 12}
13#endif /* NO_PERF_REGS */ 13#endif /* HAVE_PERF_REGS */
14#endif /* __PERF_REGS_H */ 14#endif /* __PERF_REGS_H */
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 12d634792de5..5786f323b597 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -43,6 +43,15 @@ extern struct sort_entry sort_sym_from;
43extern struct sort_entry sort_sym_to; 43extern struct sort_entry sort_sym_to;
44extern enum sort_type sort__first_dimension; 44extern enum sort_type sort__first_dimension;
45 45
46struct he_stat {
47 u64 period;
48 u64 period_sys;
49 u64 period_us;
50 u64 period_guest_sys;
51 u64 period_guest_us;
52 u32 nr_events;
53};
54
46/** 55/**
47 * struct hist_entry - histogram entry 56 * struct hist_entry - histogram entry
48 * 57 *
@@ -52,16 +61,11 @@ extern enum sort_type sort__first_dimension;
52struct hist_entry { 61struct hist_entry {
53 struct rb_node rb_node_in; 62 struct rb_node rb_node_in;
54 struct rb_node rb_node; 63 struct rb_node rb_node;
55 u64 period; 64 struct he_stat stat;
56 u64 period_sys;
57 u64 period_us;
58 u64 period_guest_sys;
59 u64 period_guest_us;
60 struct map_symbol ms; 65 struct map_symbol ms;
61 struct thread *thread; 66 struct thread *thread;
62 u64 ip; 67 u64 ip;
63 s32 cpu; 68 s32 cpu;
64 u32 nr_events;
65 69
66 /* XXX These two should move to some tree widget lib */ 70 /* XXX These two should move to some tree widget lib */
67 u16 row_offset; 71 u16 row_offset;
@@ -73,12 +77,13 @@ struct hist_entry {
73 u8 filtered; 77 u8 filtered;
74 char *srcline; 78 char *srcline;
75 struct symbol *parent; 79 struct symbol *parent;
80 unsigned long position;
76 union { 81 union {
77 unsigned long position;
78 struct hist_entry *pair; 82 struct hist_entry *pair;
79 struct rb_root sorted_chain; 83 struct rb_root sorted_chain;
80 }; 84 };
81 struct branch_info *branch_info; 85 struct branch_info *branch_info;
86 struct hists *hists;
82 struct callchain_root callchain[0]; 87 struct callchain_root callchain[0];
83}; 88};
84 89
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index b441b07172b7..8b6ef7fac745 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -12,7 +12,7 @@
12#include <byteswap.h> 12#include <byteswap.h>
13#include <libgen.h> 13#include <libgen.h>
14 14
15#ifndef NO_LIBELF_SUPPORT 15#ifdef LIBELF_SUPPORT
16#include <libelf.h> 16#include <libelf.h>
17#include <gelf.h> 17#include <gelf.h>
18#include <elf.h> 18#include <elf.h>
@@ -46,10 +46,10 @@ char *strxfrchar(char *s, char from, char to);
46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; 46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
47 * for newer versions we can use mmap to reduce memory usage: 47 * for newer versions we can use mmap to reduce memory usage:
48 */ 48 */
49#ifdef LIBELF_NO_MMAP 49#ifdef LIBELF_MMAP
50# define PERF_ELF_C_READ_MMAP ELF_C_READ
51#else
52# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP 50# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
51#else
52# define PERF_ELF_C_READ_MMAP ELF_C_READ
53#endif 53#endif
54 54
55#ifndef DMGL_PARAMS 55#ifndef DMGL_PARAMS
@@ -233,7 +233,7 @@ struct symsrc {
233 int fd; 233 int fd;
234 enum dso_binary_type type; 234 enum dso_binary_type type;
235 235
236#ifndef NO_LIBELF_SUPPORT 236#ifdef LIBELF_SUPPORT
237 Elf *elf; 237 Elf *elf;
238 GElf_Ehdr ehdr; 238 GElf_Ehdr ehdr;
239 239
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index a78c8b303bb5..cb6bc503a792 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -13,7 +13,7 @@ struct unwind_entry {
13 13
14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); 14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
15 15
16#ifndef NO_LIBUNWIND_SUPPORT 16#ifdef LIBUNWIND_SUPPORT
17int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 17int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
18 struct machine *machine, 18 struct machine *machine,
19 struct thread *thread, 19 struct thread *thread,
@@ -31,5 +31,5 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
31{ 31{
32 return 0; 32 return 0;
33} 33}
34#endif /* NO_LIBUNWIND_SUPPORT */ 34#endif /* LIBUNWIND_SUPPORT */
35#endif /* __UNWIND_H */ 35#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 2055cf38041c..99664598bc1a 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,7 +1,7 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include <sys/mman.h> 3#include <sys/mman.h>
4#ifndef NO_BACKTRACE 4#ifdef BACKTRACE_SUPPORT
5#include <execinfo.h> 5#include <execinfo.h>
6#endif 6#endif
7#include <stdio.h> 7#include <stdio.h>
@@ -165,7 +165,7 @@ size_t hex_width(u64 v)
165} 165}
166 166
167/* Obtain a backtrace and print it to stdout. */ 167/* Obtain a backtrace and print it to stdout. */
168#ifndef NO_BACKTRACE 168#ifdef BACKTRACE_SUPPORT
169void dump_stack(void) 169void dump_stack(void)
170{ 170{
171 void *array[16]; 171 void *array[16];