diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-10-05 04:04:33 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-10-05 04:04:33 -0400 |
commit | c942ee2e62dff1a7bc6f809965e93e46808d554c (patch) | |
tree | 430d4730be24416f03fd992017e47605342d9b61 /tools | |
parent | e717bf4e4fe8adc519f25c4ff93ee50ed0a36710 (diff) | |
parent | 139c0815903de1a7865fe1d6beac5e995fefdf46 (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')
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)) | |||
185 | PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) | 187 | PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) |
186 | PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py | 188 | PYTHON_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 | ||
447 | PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT) | 449 | PERFLIBS = $(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 | |||
454 | PYRF_OBJS += $(OUTPUT)util/cpumap.o | ||
455 | PYRF_OBJS += $(OUTPUT)util/ctype.o | ||
456 | PYRF_OBJS += $(OUTPUT)util/evlist.o | ||
457 | PYRF_OBJS += $(OUTPUT)util/evsel.o | ||
458 | PYRF_OBJS += $(OUTPUT)util/python.o | ||
459 | PYRF_OBJS += $(OUTPUT)util/thread_map.o | ||
460 | PYRF_OBJS += $(OUTPUT)util/util.o | ||
461 | PYRF_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 |
489 | endif | 477 | else |
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 | ||
483 | endif # SOURCE_LIBELF | ||
490 | endif # NO_LIBELF | 484 | endif # NO_LIBELF |
491 | 485 | ||
492 | ifndef NO_LIBUNWIND | 486 | ifndef NO_LIBUNWIND |
@@ -511,8 +505,6 @@ ifneq ($(OUTPUT),) | |||
511 | endif | 505 | endif |
512 | 506 | ||
513 | ifdef NO_LIBELF | 507 | ifdef NO_LIBELF |
514 | BASIC_CFLAGS += -DNO_LIBELF_SUPPORT | ||
515 | |||
516 | EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) | 508 | EXTLIBS := $(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)) | |||
527 | LIB_OBJS += $(OUTPUT)util/symbol-minimal.o | 519 | LIB_OBJS += $(OUTPUT)util/symbol-minimal.o |
528 | 520 | ||
529 | else # NO_LIBELF | 521 | else # NO_LIBELF |
522 | BASIC_CFLAGS += -DLIBELF_SUPPORT | ||
530 | 523 | ||
531 | ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y) | 524 | ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y) |
532 | BASIC_CFLAGS += -DLIBELF_NO_MMAP | 525 | BASIC_CFLAGS += -DLIBELF_MMAP |
533 | endif | 526 | endif |
534 | 527 | ||
535 | FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) | ||
536 | ifneq ($(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 | ||
539 | endif # Dwarf support | ||
540 | |||
541 | ifndef NO_DWARF | 528 | ifndef NO_DWARF |
542 | ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) | 529 | ifeq ($(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 | |||
550 | endif # NO_DWARF | 537 | endif # NO_DWARF |
551 | endif # NO_LIBELF | 538 | endif # NO_LIBELF |
552 | 539 | ||
553 | ifdef NO_LIBUNWIND | 540 | ifndef NO_LIBUNWIND |
554 | BASIC_CFLAGS += -DNO_LIBUNWIND_SUPPORT | 541 | BASIC_CFLAGS += -DLIBUNWIND_SUPPORT |
555 | else | ||
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 |
560 | endif | 546 | endif |
561 | 547 | ||
562 | ifdef NO_LIBAUDIT | 548 | ifndef NO_LIBAUDIT |
563 | BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT | ||
564 | else | ||
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 |
573 | endif | 557 | endif |
574 | 558 | ||
575 | ifdef NO_NEWT | 559 | ifndef NO_NEWT |
576 | BASIC_CFLAGS += -DNO_NEWT_SUPPORT | ||
577 | else | ||
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 |
604 | endif | 586 | endif |
605 | 587 | ||
606 | ifdef NO_GTK2 | 588 | ifndef NO_GTK2 |
607 | BASIC_CFLAGS += -DNO_GTK2_SUPPORT | ||
608 | else | ||
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 |
765 | else | 745 | BASIC_CFLAGS += -DHAVE_PERF_REGS |
766 | BASIC_CFLAGS += -DNO_PERF_REGS | ||
767 | endif | 746 | endif |
768 | 747 | ||
769 | ifdef NO_STRLCPY | 748 | ifndef NO_STRLCPY |
770 | BASIC_CFLAGS += -DNO_STRLCPY | 749 | ifeq ($(call try-cc,$(SOURCE_STRLCPY),),y) |
771 | else | 750 | BASIC_CFLAGS += -DHAVE_STRLCPY |
772 | ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y) | ||
773 | BASIC_CFLAGS += -DNO_STRLCPY | ||
774 | endif | 751 | endif |
775 | endif | 752 | endif |
776 | 753 | ||
777 | ifdef NO_BACKTRACE | 754 | ifndef NO_BACKTRACE |
778 | BASIC_CFLAGS += -DNO_BACKTRACE | 755 | ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y) |
779 | else | 756 | BASIC_CFLAGS += -DBACKTRACE_SUPPORT |
780 | ifneq ($(call try-cc,$(SOURCE_BACKTRACE),),y) | ||
781 | BASIC_CFLAGS += -DNO_BACKTRACE | ||
782 | endif | 757 | endif |
783 | endif | 758 | endif |
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 | ||
3 | function_exists() | ||
4 | { | ||
5 | declare -F $1 > /dev/null | ||
6 | return $? | ||
7 | } | ||
8 | |||
9 | function_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 | |||
3 | have perf && | 22 | have 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 | ||
18 | static char const *add_name_list_str, *remove_name_list_str; | ||
19 | |||
20 | static const char * const buildid_cache_usage[] = { | ||
21 | "perf buildid-cache [<options>]", | ||
22 | NULL | ||
23 | }; | ||
24 | |||
25 | static 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 | |||
34 | static int build_id_cache__add_file(const char *filename, const char *debugdir) | 18 | static 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 | ||
54 | static int build_id_cache__remove_file(const char *filename __maybe_unused, | 38 | static 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 | ||
76 | static int __cmd_buildid_cache(void) | 60 | int 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 | |||
123 | int 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 | ||
19 | static const char *input_name; | ||
20 | static bool force; | ||
21 | static bool show_kernel; | ||
22 | static bool with_hits; | ||
23 | |||
24 | static const char * const buildid_list_usage[] = { | ||
25 | "perf buildid-list [<options>]", | ||
26 | NULL | ||
27 | }; | ||
28 | |||
29 | static 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 | |||
40 | static int sysfs__fprintf_build_id(FILE *fp) | 19 | static 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 | ||
68 | static int perf_session__list_build_ids(void) | 47 | static 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 | ||
98 | static 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 | |||
106 | int cmd_buildid_list(int argc, const char **argv, | 78 | int 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 | ||
73 | static void perf_session__insert_hist_entry_by_name(struct rb_root *root, | 73 | static 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 | ||
93 | static void hists__resort_entries(struct hists *self) | 93 | static 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 | ||
111 | static struct hist_entry *hists__find_entry(struct hists *self, | 115 | static 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 | ||
157 | static 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 | |||
153 | static int __cmd_diff(void) | 175 | static 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 | ||
206 | out_delete: | 220 | out_delete: |
@@ -242,6 +256,21 @@ static const struct option options[] = { | |||
242 | OPT_END() | 256 | OPT_END() |
243 | }; | 257 | }; |
244 | 258 | ||
259 | static 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 | |||
245 | int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) | 274 | int 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 | ||
111 | static const char * const evlist_usage[] = { | ||
112 | "perf evlist [<options>]", | ||
113 | NULL | ||
114 | }; | ||
115 | |||
116 | int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) | 111 | int 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 | ||
33 | static bool show_all = false; | ||
34 | static enum help_format help_format = HELP_FORMAT_NONE; | ||
35 | static 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 | |||
45 | static const char * const builtin_help_usage[] = { | ||
46 | "perf help [--all] [--man|--web|--info] [command]", | ||
47 | NULL | ||
48 | }; | ||
49 | |||
50 | static enum help_format parse_help_format(const char *format) | 33 | static 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 | ||
259 | static int perf_help_config(const char *var, const char *value, void *cb) | 242 | static 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 | ||
429 | int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) | 414 | int 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 | ||
17 | static char const *input_name = "-"; | 17 | struct perf_inject { |
18 | static bool inject_build_ids; | 18 | struct perf_tool tool; |
19 | bool build_ids; | ||
20 | }; | ||
19 | 21 | ||
20 | static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused, | 22 | static 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 | ||
211 | struct 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 | |||
227 | extern volatile int session_done; | 213 | extern volatile int session_done; |
228 | 214 | ||
229 | static void sig_handler(int sig __maybe_unused) | 215 | static 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 | ||
234 | static int __cmd_inject(void) | 220 | static 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 | ||
259 | static const char * const report_usage[] = { | ||
260 | "perf inject [<options>]", | ||
261 | NULL | ||
262 | }; | ||
263 | |||
264 | static 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 | |||
272 | int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | 245 | int 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 @@ | |||
21 | struct alloc_stat; | 21 | struct alloc_stat; |
22 | typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); | 22 | typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); |
23 | 23 | ||
24 | static const char *input_name; | ||
25 | |||
26 | static int alloc_flag; | 24 | static int alloc_flag; |
27 | static int caller_flag; | 25 | static int caller_flag; |
28 | 26 | ||
@@ -31,8 +29,6 @@ static int caller_lines = -1; | |||
31 | 29 | ||
32 | static bool raw_ip; | 30 | static bool raw_ip; |
33 | 31 | ||
34 | static char default_sort_order[] = "frag,hit,bytes"; | ||
35 | |||
36 | static int *cpunode_map; | 32 | static int *cpunode_map; |
37 | static int max_cpu_num; | 33 | static 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 | ||
484 | static int __cmd_kmem(void) | 480 | static 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 | ||
523 | static const char * const kmem_usage[] = { | ||
524 | "perf kmem [<options>] {record|stat}", | ||
525 | NULL | ||
526 | }; | ||
527 | |||
528 | static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r) | 519 | static 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 | ||
723 | static const struct option kmem_options[] = { | 714 | static 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 | |||
742 | static 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 | |||
756 | static 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 | ||
776 | int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) | 743 | int 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 | ||
35 | struct kvm_event_stats { | ||
36 | u64 time; | ||
37 | struct stats stats; | ||
38 | }; | ||
39 | |||
40 | struct 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 | |||
53 | typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int); | ||
54 | |||
55 | struct kvm_event_key { | ||
56 | const char *name; | ||
57 | key_cmp_fun key; | ||
58 | }; | ||
59 | |||
60 | |||
61 | struct perf_kvm; | ||
62 | |||
35 | struct kvm_events_ops { | 63 | struct 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 | ||
74 | struct 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 | |||
82 | struct 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 | |||
45 | static void exit_event_get_key(struct perf_evsel *evsel, | 105 | static 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 | ||
81 | struct exit_reasons_table { | 141 | static struct exit_reasons_table vmx_exit_reasons[] = { |
82 | unsigned long exit_code; | ||
83 | const char *reason; | ||
84 | }; | ||
85 | |||
86 | struct exit_reasons_table vmx_exit_reasons[] = { | ||
87 | VMX_EXIT_REASONS | 142 | VMX_EXIT_REASONS |
88 | }; | 143 | }; |
89 | 144 | ||
90 | struct exit_reasons_table svm_exit_reasons[] = { | 145 | static struct exit_reasons_table svm_exit_reasons[] = { |
91 | SVM_EXIT_REASONS | 146 | SVM_EXIT_REASONS |
92 | }; | 147 | }; |
93 | 148 | ||
94 | static int cpu_isa; | 149 | static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code) |
95 | |||
96 | static 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 | ||
117 | static void exit_event_decode_key(struct event_key *key, char decode[20]) | 165 | static 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 | */ |
136 | static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample, | 186 | static 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 | ||
181 | static void mmio_event_decode_key(struct event_key *key, char decode[20]) | 231 | static 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 | ||
222 | static void ioport_event_decode_key(struct event_key *key, char decode[20]) | 274 | static 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 | ||
235 | static const char *report_event = "vmexit"; | 289 | static bool register_kvm_events_ops(struct perf_kvm *kvm) |
236 | struct kvm_events_ops *events_ops; | ||
237 | |||
238 | static 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 | ||
256 | struct kvm_event_stats { | ||
257 | u64 time; | ||
258 | struct stats stats; | ||
259 | }; | ||
260 | |||
261 | struct 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 | |||
274 | struct vcpu_event_record { | 307 | struct 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 | |||
283 | static u64 total_time; | ||
284 | static u64 total_count; | ||
285 | static struct list_head kvm_events_cache[EVENTS_CACHE_SIZE]; | ||
286 | 313 | ||
287 | static void init_kvm_event_record(void) | 314 | static 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 | ||
295 | static int kvm_events_hash_fn(u64 key) | 322 | static 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 | ||
336 | static struct kvm_event *find_create_kvm_event(struct event_key *key) | 363 | static 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 | ||
356 | static bool handle_begin_event(struct vcpu_event_record *vcpu_record, | 384 | static 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 | ||
399 | static bool handle_end_event(struct vcpu_event_record *vcpu_record, | 428 | static 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 | ||
458 | static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel, | 489 | static 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 | ||
477 | typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int); | ||
478 | struct kvm_event_key { | ||
479 | const char *name; | ||
480 | key_cmp_fun key; | ||
481 | }; | ||
482 | |||
483 | static int trace_vcpu = -1; | ||
484 | #define GET_EVENT_KEY(func, field) \ | 510 | #define GET_EVENT_KEY(func, field) \ |
485 | static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \ | 511 | static 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 | ||
518 | static const char *sort_key = "sample"; | 544 | static bool select_key(struct perf_kvm *kvm) |
519 | static key_cmp_fun compare; | ||
520 | |||
521 | static 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 | ||
536 | static struct rb_root result; | 559 | static void insert_to_result(struct rb_root *result, struct kvm_event *event, |
537 | static 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 | ||
558 | static void update_total_count(struct kvm_event *event, int vcpu) | 580 | static 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 | ||
564 | static bool event_is_valid(struct kvm_event *event, int vcpu) | 588 | static 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 | ||
569 | static void sort_result(int vcpu) | 593 | static 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 */ |
583 | static struct kvm_event *pop_from_result(void) | 609 | static 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 | ||
604 | static void print_result(int vcpu) | 630 | static 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 | ||
639 | static int process_sample_event(struct perf_tool *tool __maybe_unused, | 666 | static 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 | ||
659 | static struct perf_tool eops = { | ||
660 | .sample = process_sample_event, | ||
661 | .comm = perf_event__process_comm, | ||
662 | .ordered_samples = true, | ||
663 | }; | ||
664 | |||
665 | static int get_cpu_isa(struct perf_session *session) | 687 | static 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 | ||
682 | static const char *file_name; | 704 | static int read_events(struct perf_kvm *kvm) |
683 | |||
684 | static 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 | ||
712 | static bool verify_vcpu(int vcpu) | 743 | static 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 | ||
722 | static int kvm_events_report_vcpu(int vcpu) | 753 | static 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 | |||
744 | exit: | 777 | exit: |
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 | ||
768 | static int kvm_events_record(int argc, const char **argv) | 801 | static 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 | ||
791 | static const char * const kvm_events_report_usage[] = { | 824 | static 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 | ||
796 | static 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 | ||
807 | static 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 | ||
823 | static void print_kvm_stat_usage(void) | 856 | static 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 | ||
834 | static int kvm_cmd_stat(int argc, const char **argv) | 867 | static 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 | ||
847 | perf_stat: | 880 | perf_stat: |
848 | return cmd_stat(argc, argv, NULL); | 881 | return cmd_stat(argc, argv, NULL); |
849 | } | 882 | } |
850 | 883 | ||
851 | static char name_buffer[256]; | 884 | static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv) |
852 | |||
853 | static const char * const kvm_usage[] = { | ||
854 | "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}", | ||
855 | NULL | ||
856 | }; | ||
857 | |||
858 | static 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 | |||
879 | static 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 | ||
897 | static int __cmd_report(int argc, const char **argv) | 902 | static 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 | ||
915 | static int __cmd_buildid_list(int argc, const char **argv) | 920 | static 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 | ||
933 | int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) | 938 | int 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 | ||
826 | static struct perf_tool eops = { | ||
827 | .sample = process_sample_event, | ||
828 | .comm = perf_event__process_comm, | ||
829 | .ordered_samples = true, | ||
830 | }; | ||
831 | |||
832 | static const struct perf_evsel_str_handler lock_tracepoints[] = { | 826 | static 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 | ||
839 | static int read_events(void) | 833 | static 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 | ||
881 | static const char * const report_usage[] = { | ||
882 | "perf lock report [<options>]", | ||
883 | NULL | ||
884 | }; | ||
885 | |||
886 | static 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 | |||
893 | static const char * const info_usage[] = { | ||
894 | "perf lock info [<options>]", | ||
895 | NULL | ||
896 | }; | ||
897 | |||
898 | static 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 | |||
906 | static const char * const lock_usage[] = { | ||
907 | "perf lock [<options>] {record|report|script|info}", | ||
908 | NULL | ||
909 | }; | ||
910 | |||
911 | static 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 | |||
918 | static const char *record_args[] = { | ||
919 | "record", | ||
920 | "-R", | ||
921 | "-f", | ||
922 | "-m", "1024", | ||
923 | "-c", "1", | ||
924 | }; | ||
925 | |||
926 | static int __cmd_record(int argc, const char **argv) | 880 | static 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 | ||
964 | int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) | 921 | int 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 | ||
253 | static const char * const probe_usage[] = { | 253 | int 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[] = { | |
265 | static 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", ¶ms.list_events, | 269 | OPT_BOOLEAN('l', "list", ¶ms.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 | |||
330 | int 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 | ||
37 | static char callchain_help[] = CALLCHAIN_HELP "[fp]"; | ||
38 | #else | ||
39 | static unsigned long default_stack_dump_size = 8192; | ||
40 | static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; | ||
41 | #endif | ||
42 | |||
43 | enum write_mode_t { | 34 | enum 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 |
804 | static int get_stack_size(char *str, unsigned long *_size) | 795 | static 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 | ||
831 | static int | 822 | static int |
832 | parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, | 823 | parse_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 | ||
929 | static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; | ||
930 | #else | ||
931 | static 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; | |||
24 | static u64 nr_unordered; | 24 | static u64 nr_unordered; |
25 | extern const struct option record_options[]; | 25 | extern const struct option record_options[]; |
26 | static bool no_callchain; | 26 | static bool no_callchain; |
27 | static bool show_full_info; | ||
28 | static bool system_wide; | 27 | static bool system_wide; |
29 | static const char *cpu_list; | 28 | static const char *cpu_list; |
30 | static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | 29 | static 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 | ||
476 | static const char *input_name; | ||
477 | |||
478 | static int process_sample_event(struct perf_tool *tool __maybe_unused, | 475 | static 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 | ||
1159 | static const char * const script_usage[] = { | 1156 | static 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 | ||
1168 | static const struct option options[] = { | 1170 | system_wide = (argc == 0); |
1171 | |||
1172 | return 0; | ||
1173 | } | ||
1174 | |||
1175 | int 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[] = { | |
1215 | static 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 | |||
1234 | int 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 | ||
67 | static 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 | */ | ||
86 | static 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 | */ | ||
116 | static 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 | */ | ||
159 | static 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 | |||
176 | static struct perf_evlist *evsel_list; | 67 | static struct perf_evlist *evsel_list; |
177 | 68 | ||
178 | static struct perf_target target = { | 69 | static struct perf_target target = { |
179 | .uid = UINT_MAX, | 70 | .uid = UINT_MAX, |
180 | }; | 71 | }; |
181 | 72 | ||
182 | static int run_idx = 0; | ||
183 | static int run_count = 1; | 73 | static int run_count = 1; |
184 | static bool no_inherit = false; | 74 | static bool no_inherit = false; |
185 | static bool scale = true; | 75 | static bool scale = true; |
@@ -187,15 +77,12 @@ static bool no_aggr = false; | |||
187 | static pid_t child_pid = -1; | 77 | static pid_t child_pid = -1; |
188 | static bool null_run = false; | 78 | static bool null_run = false; |
189 | static int detailed_run = 0; | 79 | static int detailed_run = 0; |
190 | static bool sync_run = false; | ||
191 | static bool big_num = true; | 80 | static bool big_num = true; |
192 | static int big_num_opt = -1; | 81 | static int big_num_opt = -1; |
193 | static const char *csv_sep = NULL; | 82 | static const char *csv_sep = NULL; |
194 | static bool csv_output = false; | 83 | static bool csv_output = false; |
195 | static bool group = false; | 84 | static bool group = false; |
196 | static const char *output_name = NULL; | ||
197 | static FILE *output = NULL; | 85 | static FILE *output = NULL; |
198 | static int output_fd; | ||
199 | 86 | ||
200 | static volatile int done = 0; | 87 | static 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 | ||
1031 | static const char * const stat_usage[] = { | ||
1032 | "perf stat [<options>] [<command>]", | ||
1033 | NULL | ||
1034 | }; | ||
1035 | |||
1036 | static int stat__set_big_num(const struct option *opt __maybe_unused, | 918 | static 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 | ||
1043 | static bool append_file; | ||
1044 | |||
1045 | static 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 | */ |
1097 | static int add_default_attributes(void) | 929 | static 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 | ||
1131 | int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | 1070 | int 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 | ||
41 | static const char *input_name; | ||
42 | static const char *output_name = "output.svg"; | ||
43 | |||
44 | static unsigned int numcpus; | 41 | static unsigned int numcpus; |
45 | static u64 min_freq; /* Lowest CPU frequency seen */ | 42 | static u64 min_freq; /* Lowest CPU frequency seen */ |
46 | static u64 max_freq; /* Highest CPU frequency seen */ | 43 | static 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 | ||
971 | static struct perf_tool perf_timechart = { | 968 | static 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 | |||
979 | static 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 | ||
1008 | static const char * const timechart_usage[] = { | ||
1009 | "perf timechart [<options>] {record}", | ||
1010 | NULL | ||
1011 | }; | ||
1012 | |||
1013 | #ifdef SUPPORT_OLD_POWER_EVENTS | ||
1014 | static 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 | |||
1028 | static 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 | |||
1040 | static int __cmd_record(int argc, const char **argv) | 1004 | static 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 | ||
1080 | static const struct option options[] = { | 1061 | int 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 | ||
1098 | int 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 | ||
1162 | static const char * const top_usage[] = { | ||
1163 | "perf top [<options>]", | ||
1164 | NULL | ||
1165 | }; | ||
1166 | |||
1167 | int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | 1162 | int 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 | ||
117 | typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel, | ||
118 | struct perf_sample *sample); | ||
119 | |||
120 | static 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 | |||
140 | out_cant_read: | ||
141 | printf("Problems reading syscall %d information\n", id); | ||
142 | return NULL; | ||
143 | } | ||
144 | |||
145 | static 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 | |||
166 | static 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 | |||
117 | static int trace__run(struct trace *trace) | 192 | static 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, | |||
569 | static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ | 569 | static 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 | ||
585 | void hist_browser__init_hpp(void) | 586 | void 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) | |||
49 | static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ | 49 | static 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 | ||
74 | void perf_gtk__init_hpp(void) | 75 | void 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 |
120 | void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused, | 120 | void 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 | ||
24 | extern char ui_helpline__current[512]; | 24 | extern char ui_helpline__current[512]; |
25 | 25 | ||
26 | #ifdef NO_NEWT_SUPPORT | 26 | #ifdef NEWT_SUPPORT |
27 | extern char ui_helpline__last_msg[]; | ||
28 | int ui_helpline__show_help(const char *format, va_list ap); | ||
29 | #else | ||
27 | static inline int ui_helpline__show_help(const char *format __maybe_unused, | 30 | static 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 */ |
33 | extern char ui_helpline__last_msg[]; | ||
34 | int 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 |
38 | int perf_gtk__show_helpline(const char *format, va_list ap); | ||
39 | #else | ||
38 | static inline int perf_gtk__show_helpline(const char *format __maybe_unused, | 40 | static 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 */ |
44 | int 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 */ |
9 | static int hpp__header_overhead(struct perf_hpp *hpp) | 9 | static 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 | ||
16 | static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) | 14 | static 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 | ||
21 | static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) | 19 | static 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 | ||
39 | static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) | 27 | static 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 | ||
70 | static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) | 48 | static 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 | ||
76 | static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) | 56 | static 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 | ||
96 | static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) | 77 | static 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 | ||
102 | static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) | 85 | static 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) | |||
120 | static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, | 104 | static 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 | ||
127 | static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, | 113 | static 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) | |||
146 | static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, | 133 | static 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 | ||
153 | static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, | 142 | static 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 | ||
152 | static int hpp__header_baseline(struct perf_hpp *hpp) | ||
153 | { | ||
154 | return scnprintf(hpp->buf, hpp->size, "Baseline"); | ||
155 | } | ||
156 | |||
157 | static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused) | ||
158 | { | ||
159 | return 8; | ||
160 | } | ||
161 | |||
162 | static 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 | |||
178 | static 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 | |||
185 | static 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 | |||
162 | static int hpp__header_samples(struct perf_hpp *hpp) | 193 | static 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 | ||
181 | static int hpp__header_period(struct perf_hpp *hpp) | 212 | static 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 | ||
200 | static int hpp__header_delta(struct perf_hpp *hpp) | 231 | static 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 | ||
212 | static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) | 243 | static 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 | ||
246 | static int hpp__entry_displ(struct perf_hpp *hpp, | 279 | static 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 | ||
269 | struct perf_hpp_fmt perf_hpp__format[] = { | 304 | struct 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 | ||
284 | void perf_hpp__init(bool need_pair, bool show_displacement) | 320 | void 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) { | 339 | void 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 | ||
310 | static inline void advance_hpp(struct perf_hpp *hpp, int inc) | 345 | static 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 | ||
293 | static size_t hist_entry__callchain_fprintf(struct hist_entry *he, | 293 | static 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 | ||
309 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, | 310 | static 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 | ||
339 | size_t hists__fprintf(struct hists *hists, struct hists *pair, | 335 | size_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 | ||
443 | print_entries: | 441 | print_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 |
142 | int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, | ||
143 | void(*timer)(void *arg), void *arg, int delay_secs); | ||
144 | #else | ||
142 | static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, | 145 | static 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 | ||
152 | int 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 | ||
156 | extern const char *disassembler_style; | 156 | extern 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 | ||
34 | extern int use_browser; | 34 | extern int use_browser; |
35 | 35 | ||
36 | #if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) | 36 | #if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT) |
37 | static inline void setup_browser(bool fallback_to_pager) | ||
38 | { | ||
39 | if (fallback_to_pager) | ||
40 | setup_pager(); | ||
41 | } | ||
42 | static inline void exit_browser(bool wait_for_ok __maybe_unused) {} | ||
43 | #else | ||
44 | void setup_browser(bool fallback_to_pager); | 37 | void setup_browser(bool fallback_to_pager); |
45 | void exit_browser(bool wait_for_ok); | 38 | void exit_browser(bool wait_for_ok); |
46 | 39 | ||
47 | #ifdef NO_NEWT_SUPPORT | 40 | #ifdef NEWT_SUPPORT |
41 | int ui__init(void); | ||
42 | void ui__exit(bool wait_for_ok); | ||
43 | #else | ||
48 | static inline int ui__init(void) | 44 | static inline int ui__init(void) |
49 | { | 45 | { |
50 | return -1; | 46 | return -1; |
51 | } | 47 | } |
52 | static inline void ui__exit(bool wait_for_ok __maybe_unused) {} | 48 | static inline void ui__exit(bool wait_for_ok __maybe_unused) {} |
53 | #else | ||
54 | int ui__init(void); | ||
55 | void ui__exit(bool wait_for_ok); | ||
56 | #endif | 49 | #endif |
57 | 50 | ||
58 | #ifdef NO_GTK2_SUPPORT | 51 | #ifdef GTK2_SUPPORT |
52 | int perf_gtk__init(void); | ||
53 | void perf_gtk__exit(bool wait_for_ok); | ||
54 | #else | ||
59 | static inline int perf_gtk__init(void) | 55 | static inline int perf_gtk__init(void) |
60 | { | 56 | { |
61 | return -1; | 57 | return -1; |
62 | } | 58 | } |
63 | static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {} | 59 | static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {} |
64 | #else | ||
65 | int perf_gtk__init(void); | ||
66 | void 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 | |||
64 | static inline void setup_browser(bool fallback_to_pager) | ||
65 | { | ||
66 | if (fallback_to_pager) | ||
67 | setup_pager(); | ||
68 | } | ||
69 | static inline void exit_browser(bool wait_for_ok __maybe_unused) {} | ||
70 | #endif /* NEWT_SUPPORT || GTK2_SUPPORT */ | ||
69 | 71 | ||
70 | char *alias_lookup(const char *alias); | 72 | char *alias_lookup(const char *alias); |
71 | int split_cmdline(char *cmdline, const char ***argv); | 73 | int split_cmdline(char *cmdline, const char ***argv); |
@@ -105,7 +107,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2 | |||
105 | extern char *perf_pathdup(const char *fmt, ...) | 107 | extern 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 |
109 | extern size_t strlcpy(char *dest, const char *src, size_t size); | 111 | extern 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) |
53 | int ui__warning(const char *format, ...) | 53 | int 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); | |||
15 | struct ui_progress; | 15 | struct ui_progress; |
16 | struct perf_error_ops; | 16 | struct 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" | ||
21 | int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); | ||
22 | #include "../ui/util.h" | ||
23 | |||
24 | #else | ||
25 | |||
19 | static inline void ui_progress__update(u64 curr __maybe_unused, | 26 | static 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" | ||
40 | int 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 | ||
45 | int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); | 46 | int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); |
46 | int ui__error_paranoid(void); | 47 | int 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 | ||
157 | int perf_evlist__add_attrs(struct perf_evlist *evlist, | 157 | static 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 | ||
192 | static 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 | |||
216 | int 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); | ||
241 | out_free_attrs: | ||
242 | free(attrs); | ||
243 | return err; | ||
244 | } | ||
245 | |||
246 | struct perf_evsel * | 192 | struct perf_evsel * |
247 | perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) | 193 | perf_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 | ||
260 | int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, | 206 | int 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; |
284 | out: | 216 | perf_evlist__add(evlist, evsel); |
285 | return err; | 217 | return 0; |
286 | } | 218 | } |
287 | 219 | ||
288 | void perf_evlist__disable(struct perf_evlist *evlist) | 220 | void 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 | ||
52 | void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); | 52 | void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); |
53 | int perf_evlist__add_default(struct perf_evlist *evlist); | 53 | int perf_evlist__add_default(struct perf_evlist *evlist); |
54 | int perf_evlist__add_attrs(struct perf_evlist *evlist, | ||
55 | struct perf_event_attr *attrs, size_t nr_attrs); | ||
56 | int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, | 54 | int __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); |
58 | int perf_evlist__add_tracepoints(struct perf_evlist *evlist, | 56 | |
59 | const char *tracepoints[], size_t nr_tracepoints); | ||
60 | int 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) \ | 60 | int 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 | ||
75 | int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); | 63 | int 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" |
23 | done | 23 | done |
24 | 24 | ||
25 | echo "#ifndef NO_LIBELF_SUPPORT" | 25 | echo "#ifdef LIBELF_SUPPORT" |
26 | sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt | | 26 | sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt | |
27 | sort | | 27 | sort | |
28 | while read cmd | 28 | while read cmd |
@@ -35,5 +35,5 @@ do | |||
35 | p | 35 | p |
36 | }' "Documentation/perf-$cmd.txt" | 36 | }' "Documentation/perf-$cmd.txt" |
37 | done | 37 | done |
38 | echo "#endif /* NO_LIBELF_SUPPORT */" | 38 | echo "#endif /* LIBELF_SUPPORT */" |
39 | echo "};" | 39 | echo "};" |
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 | ||
154 | static 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 | |||
160 | static 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 | |||
154 | static void hist_entry__decay(struct hist_entry *he) | 170 | static 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 | ||
160 | static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) | 176 | static 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 | ||
175 | static void __hists__decay_entries(struct hists *hists, bool zap_user, | 191 | static 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); | |||
98 | void hists__inc_nr_events(struct hists *self, u32 type); | 98 | void hists__inc_nr_events(struct hists *self, u32 type); |
99 | size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); | 99 | size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); |
100 | 100 | ||
101 | size_t hists__fprintf(struct hists *self, struct hists *pair, | 101 | size_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 | ||
105 | int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); | 104 | int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); |
106 | int hist_entry__annotate(struct hist_entry *self, size_t privsize); | 105 | int 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); | |||
118 | struct perf_hpp { | 117 | struct 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 { | |||
135 | extern struct perf_hpp_fmt perf_hpp__format[]; | 132 | extern struct perf_hpp_fmt perf_hpp__format[]; |
136 | 133 | ||
137 | enum { | 134 | enum { |
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 | ||
151 | void perf_hpp__init(bool need_pair, bool show_displacement); | 149 | void perf_hpp__init(void); |
150 | void perf_hpp__column_enable(unsigned col, bool enable); | ||
152 | int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, | 151 | int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, |
153 | bool color); | 152 | bool color); |
154 | 153 | ||
155 | struct perf_evlist; | 154 | struct perf_evlist; |
156 | 155 | ||
157 | #ifdef NO_NEWT_SUPPORT | 156 | #ifdef NEWT_SUPPORT |
157 | #include "../ui/keysyms.h" | ||
158 | int hist_entry__tui_annotate(struct hist_entry *he, int evidx, | ||
159 | void(*timer)(void *arg), void *arg, int delay_secs); | ||
160 | |||
161 | int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, | ||
162 | void(*timer)(void *arg), void *arg, | ||
163 | int refresh); | ||
164 | #else | ||
158 | static inline | 165 | static inline |
159 | int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, | 166 | int 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" | ||
182 | int hist_entry__tui_annotate(struct hist_entry *he, int evidx, | ||
183 | void(*timer)(void *arg), void *arg, int delay_secs); | ||
184 | 188 | ||
185 | int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, | 189 | #ifdef GTK2_SUPPORT |
190 | int 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 | ||
191 | static inline | 194 | static inline |
192 | int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, | 195 | int 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 | ||
202 | int 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 | ||
207 | unsigned int hists__sort_list_width(struct hists *self); | 205 | unsigned 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, | |||
140 | enum { | 140 | enum { |
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 |
26 | size_t strlcpy(char *dest, const char *src, size_t size) | 26 | size_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; | |||
43 | extern struct sort_entry sort_sym_to; | 43 | extern struct sort_entry sort_sym_to; |
44 | extern enum sort_type sort__first_dimension; | 44 | extern enum sort_type sort__first_dimension; |
45 | 45 | ||
46 | struct 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; | |||
52 | struct hist_entry { | 61 | struct 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 | ||
14 | typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); | 14 | typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); |
15 | 15 | ||
16 | #ifndef NO_LIBUNWIND_SUPPORT | 16 | #ifdef LIBUNWIND_SUPPORT |
17 | int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | 17 | int 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 |
169 | void dump_stack(void) | 169 | void dump_stack(void) |
170 | { | 170 | { |
171 | void *array[16]; | 171 | void *array[16]; |