aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/lguest/lguest.c1
-rw-r--r--tools/lib/traceevent/event-parse.c9
-rw-r--r--tools/lib/traceevent/parse-filter.c15
-rw-r--r--tools/perf/Makefile116
-rw-r--r--tools/perf/bash_completion50
-rw-r--r--tools/perf/builtin-buildid-cache.c58
-rw-r--r--tools/perf/builtin-buildid-list.c55
-rw-r--r--tools/perf/builtin-diff.c68
-rw-r--r--tools/perf/builtin-evlist.c21
-rw-r--r--tools/perf/builtin-help.c40
-rw-r--r--tools/perf/builtin-inject.c88
-rw-r--r--tools/perf/builtin-kmem.c66
-rw-r--r--tools/perf/builtin-kvm.c460
-rw-r--r--tools/perf/builtin-lock.c90
-rw-r--r--tools/perf/builtin-probe.c26
-rw-r--r--tools/perf/builtin-record.c27
-rw-r--r--tools/perf/builtin-report.c4
-rw-r--r--tools/perf/builtin-sched.c2
-rw-r--r--tools/perf/builtin-script.c90
-rw-r--r--tools/perf/builtin-stat.c328
-rw-r--r--tools/perf/builtin-timechart.c100
-rw-r--r--tools/perf/builtin-top.c11
-rw-r--r--tools/perf/builtin-trace.c150
-rw-r--r--tools/perf/perf.c4
-rw-r--r--tools/perf/perf.h4
-rw-r--r--tools/perf/ui/browsers/hists.c18
-rw-r--r--tools/perf/ui/gtk/browser.c6
-rw-r--r--tools/perf/ui/gtk/util.c2
-rw-r--r--tools/perf/ui/helpline.h18
-rw-r--r--tools/perf/ui/hist.c145
-rw-r--r--tools/perf/ui/setup.c2
-rw-r--r--tools/perf/ui/stdio/hist.c45
-rw-r--r--tools/perf/util/annotate.h8
-rw-r--r--tools/perf/util/cache.h38
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/debug.h17
-rw-r--r--tools/perf/util/evlist.c88
-rw-r--r--tools/perf/util/evlist.h18
-rw-r--r--tools/perf/util/evsel.c2
-rw-r--r--tools/perf/util/evsel.h2
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh4
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/hist.c66
-rw-r--r--tools/perf/util/hist.h38
-rw-r--r--tools/perf/util/include/asm/byteorder.h2
-rw-r--r--tools/perf/util/include/linux/const.h2
-rw-r--r--tools/perf/util/include/linux/rbtree_augmented.h2
-rw-r--r--tools/perf/util/map.c2
-rw-r--r--tools/perf/util/parse-events-test.c12
-rw-r--r--tools/perf/util/parse-events.c3
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/parse-options.c8
-rw-r--r--tools/perf/util/parse-options.h1
-rw-r--r--tools/perf/util/path.c2
-rw-r--r--tools/perf/util/perf_regs.h4
-rw-r--r--tools/perf/util/pmu.h2
-rw-r--r--tools/perf/util/session.h2
-rw-r--r--tools/perf/util/setup.py2
-rw-r--r--tools/perf/util/sort.c6
-rw-r--r--tools/perf/util/sort.h19
-rw-r--r--tools/perf/util/symbol.h10
-rw-r--r--tools/perf/util/thread.c1
-rw-r--r--tools/perf/util/unwind.h4
-rw-r--r--tools/perf/util/util.c4
-rw-r--r--tools/power/acpi/Makefile18
-rw-r--r--tools/power/acpi/acpidump.859
-rw-r--r--tools/power/acpi/acpidump.c559
-rw-r--r--tools/power/cpupower/Makefile2
-rw-r--r--tools/power/x86/turbostat/turbostat.855
-rw-r--r--tools/power/x86/turbostat/turbostat.c214
-rwxr-xr-xtools/testing/ktest/ktest.pl21
-rw-r--r--tools/testing/selftests/Makefile2
-rw-r--r--tools/testing/selftests/epoll/Makefile11
-rw-r--r--tools/testing/selftests/epoll/test_epoll.c344
-rw-r--r--tools/usb/testusb.c25
-rw-r--r--tools/virtio/virtio-trace/Makefile13
-rw-r--r--tools/virtio/virtio-trace/README118
-rw-r--r--tools/virtio/virtio-trace/trace-agent-ctl.c137
-rw-r--r--tools/virtio/virtio-trace/trace-agent-rw.c192
-rw-r--r--tools/virtio/virtio-trace/trace-agent.c270
-rw-r--r--tools/virtio/virtio-trace/trace-agent.h75
-rw-r--r--tools/vm/page-types.c4
82 files changed, 3325 insertions, 1288 deletions
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index f759f4f097c7..fd2f9221b241 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -1299,6 +1299,7 @@ static struct device *new_device(const char *name, u16 type)
1299 dev->feature_len = 0; 1299 dev->feature_len = 0;
1300 dev->num_vq = 0; 1300 dev->num_vq = 0;
1301 dev->running = false; 1301 dev->running = false;
1302 dev->next = NULL;
1302 1303
1303 /* 1304 /*
1304 * Append to device list. Prepending to a single-linked list is 1305 * Append to device list. Prepending to a single-linked list is
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 47264b4652b9..f2989c525e48 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -2602,6 +2602,9 @@ find_func_handler(struct pevent *pevent, char *func_name)
2602{ 2602{
2603 struct pevent_function_handler *func; 2603 struct pevent_function_handler *func;
2604 2604
2605 if (!pevent)
2606 return NULL;
2607
2605 for (func = pevent->func_handlers; func; func = func->next) { 2608 for (func = pevent->func_handlers; func; func = func->next) {
2606 if (strcmp(func->name, func_name) == 0) 2609 if (strcmp(func->name, func_name) == 0)
2607 break; 2610 break;
@@ -4938,6 +4941,9 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
4938 goto event_alloc_failed; 4941 goto event_alloc_failed;
4939 } 4942 }
4940 4943
4944 /* Add pevent to event so that it can be referenced */
4945 event->pevent = pevent;
4946
4941 ret = event_read_format(event); 4947 ret = event_read_format(event);
4942 if (ret < 0) { 4948 if (ret < 0) {
4943 ret = PEVENT_ERRNO__READ_FORMAT_FAILED; 4949 ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
@@ -5041,9 +5047,6 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
5041 if (event == NULL) 5047 if (event == NULL)
5042 return ret; 5048 return ret;
5043 5049
5044 /* Add pevent to event so that it can be referenced */
5045 event->pevent = pevent;
5046
5047 if (add_event(pevent, event)) { 5050 if (add_event(pevent, event)) {
5048 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; 5051 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5049 goto event_add_failed; 5052 goto event_add_failed;
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index ad17855528f9..5ea4326ad11f 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -209,7 +209,16 @@ static void free_arg(struct filter_arg *arg)
209 switch (arg->type) { 209 switch (arg->type) {
210 case FILTER_ARG_NONE: 210 case FILTER_ARG_NONE:
211 case FILTER_ARG_BOOLEAN: 211 case FILTER_ARG_BOOLEAN:
212 break;
213
212 case FILTER_ARG_NUM: 214 case FILTER_ARG_NUM:
215 free_arg(arg->num.left);
216 free_arg(arg->num.right);
217 break;
218
219 case FILTER_ARG_EXP:
220 free_arg(arg->exp.left);
221 free_arg(arg->exp.right);
213 break; 222 break;
214 223
215 case FILTER_ARG_STR: 224 case FILTER_ARG_STR:
@@ -218,6 +227,12 @@ static void free_arg(struct filter_arg *arg)
218 free(arg->str.buffer); 227 free(arg->str.buffer);
219 break; 228 break;
220 229
230 case FILTER_ARG_VALUE:
231 if (arg->value.type == FILTER_STRING ||
232 arg->value.type == FILTER_CHAR)
233 free(arg->value.str);
234 break;
235
221 case FILTER_ARG_OP: 236 case FILTER_ARG_OP:
222 free_arg(arg->op.left); 237 free_arg(arg->op.left);
223 free_arg(arg->op.right); 238 free_arg(arg->op.right);
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e5e71e7d95a0..00deed4d6159 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)
@@ -72,7 +74,7 @@ ifeq ($(ARCH),x86_64)
72 override ARCH := x86 74 override ARCH := x86
73 IS_X86_64 := 0 75 IS_X86_64 := 0
74 ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) 76 ifeq (, $(findstring m32,$(EXTRA_CFLAGS)))
75 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) 77 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1)
76 endif 78 endif
77 ifeq (${IS_X86_64}, 1) 79 ifeq (${IS_X86_64}, 1)
78 RAW_ARCH := x86_64 80 RAW_ARCH := x86_64
@@ -182,10 +184,23 @@ SCRIPT_SH += perf-archive.sh
182grep-libs = $(filter -l%,$(1)) 184grep-libs = $(filter -l%,$(1))
183strip-libs = $(filter-out -l%,$(1)) 185strip-libs = $(filter-out -l%,$(1))
184 186
187TRACE_EVENT_DIR = ../lib/traceevent/
188
189ifneq ($(OUTPUT),)
190 TE_PATH=$(OUTPUT)
191else
192 TE_PATH=$(TRACE_EVENT_DIR)
193endif
194
195LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
196TE_LIB := -L$(TE_PATH) -ltraceevent
197
185PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 198PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
186PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py 199PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
187 200
188$(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 201export LIBTRACEEVENT
202
203$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
189 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 204 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
190 --quiet build_ext; \ 205 --quiet build_ext; \
191 mkdir -p $(OUTPUT)python && \ 206 mkdir -p $(OUTPUT)python && \
@@ -196,17 +211,6 @@ $(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
196 211
197SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 212SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
198 213
199TRACE_EVENT_DIR = ../lib/traceevent/
200
201ifneq ($(OUTPUT),)
202 TE_PATH=$(OUTPUT)
203else
204 TE_PATH=$(TRACE_EVENT_DIR)
205endif
206
207LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
208TE_LIB := -L$(TE_PATH) -ltraceevent
209
210# 214#
211# Single 'perf' binary right now: 215# Single 'perf' binary right now:
212# 216#
@@ -250,10 +254,10 @@ $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
250 254
251LIB_FILE=$(OUTPUT)libperf.a 255LIB_FILE=$(OUTPUT)libperf.a
252 256
253LIB_H += ../../include/linux/perf_event.h 257LIB_H += ../../include/uapi/linux/perf_event.h
254LIB_H += ../../include/linux/rbtree.h 258LIB_H += ../../include/linux/rbtree.h
255LIB_H += ../../include/linux/list.h 259LIB_H += ../../include/linux/list.h
256LIB_H += ../../include/linux/const.h 260LIB_H += ../../include/uapi/linux/const.h
257LIB_H += ../../include/linux/hash.h 261LIB_H += ../../include/linux/hash.h
258LIB_H += ../../include/linux/stringify.h 262LIB_H += ../../include/linux/stringify.h
259LIB_H += util/include/linux/bitmap.h 263LIB_H += util/include/linux/bitmap.h
@@ -268,6 +272,7 @@ LIB_H += util/include/linux/magic.h
268LIB_H += util/include/linux/poison.h 272LIB_H += util/include/linux/poison.h
269LIB_H += util/include/linux/prefetch.h 273LIB_H += util/include/linux/prefetch.h
270LIB_H += util/include/linux/rbtree.h 274LIB_H += util/include/linux/rbtree.h
275LIB_H += util/include/linux/rbtree_augmented.h
271LIB_H += util/include/linux/string.h 276LIB_H += util/include/linux/string.h
272LIB_H += util/include/linux/types.h 277LIB_H += util/include/linux/types.h
273LIB_H += util/include/linux/linkage.h 278LIB_H += util/include/linux/linkage.h
@@ -446,20 +451,6 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
446 451
447PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT) 452PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
448 453
449# Files needed for the python binding, perf.so
450# pyrf is just an internal name needed for all those wrappers.
451# This has to be in sync with what is in the 'sources' variable in
452# tools/perf/util/setup.py
453
454PYRF_OBJS += $(OUTPUT)util/cpumap.o
455PYRF_OBJS += $(OUTPUT)util/ctype.o
456PYRF_OBJS += $(OUTPUT)util/evlist.o
457PYRF_OBJS += $(OUTPUT)util/evsel.o
458PYRF_OBJS += $(OUTPUT)util/python.o
459PYRF_OBJS += $(OUTPUT)util/thread_map.o
460PYRF_OBJS += $(OUTPUT)util/util.o
461PYRF_OBJS += $(OUTPUT)util/xyarray.o
462
463# 454#
464# Platform specific tweaks 455# Platform specific tweaks
465# 456#
@@ -486,7 +477,13 @@ ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
486 NO_DWARF := 1 477 NO_DWARF := 1
487 NO_DEMANGLE := 1 478 NO_DEMANGLE := 1
488 endif 479 endif
489endif 480else
481 FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
482 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
483 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);
484 NO_DWARF := 1
485 endif # Dwarf support
486endif # SOURCE_LIBELF
490endif # NO_LIBELF 487endif # NO_LIBELF
491 488
492ifndef NO_LIBUNWIND 489ifndef NO_LIBUNWIND
@@ -511,8 +508,6 @@ ifneq ($(OUTPUT),)
511endif 508endif
512 509
513ifdef NO_LIBELF 510ifdef NO_LIBELF
514BASIC_CFLAGS += -DNO_LIBELF_SUPPORT
515
516EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) 511EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
517 512
518# Remove ELF/DWARF dependent codes 513# Remove ELF/DWARF dependent codes
@@ -527,17 +522,12 @@ BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
527LIB_OBJS += $(OUTPUT)util/symbol-minimal.o 522LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
528 523
529else # NO_LIBELF 524else # NO_LIBELF
525BASIC_CFLAGS += -DLIBELF_SUPPORT
530 526
531ifneq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y) 527ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y)
532 BASIC_CFLAGS += -DLIBELF_NO_MMAP 528 BASIC_CFLAGS += -DLIBELF_MMAP
533endif 529endif
534 530
535FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
536ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
537 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
538 NO_DWARF := 1
539endif # Dwarf support
540
541ifndef NO_DWARF 531ifndef NO_DWARF
542ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 532ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
543 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 533 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
@@ -550,38 +540,33 @@ endif # PERF_HAVE_DWARF_REGS
550endif # NO_DWARF 540endif # NO_DWARF
551endif # NO_LIBELF 541endif # NO_LIBELF
552 542
553ifdef NO_LIBUNWIND 543ifndef NO_LIBUNWIND
554 BASIC_CFLAGS += -DNO_LIBUNWIND_SUPPORT 544 BASIC_CFLAGS += -DLIBUNWIND_SUPPORT
555else
556 EXTLIBS += $(LIBUNWIND_LIBS) 545 EXTLIBS += $(LIBUNWIND_LIBS)
557 BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS) 546 BASIC_CFLAGS := $(LIBUNWIND_CFLAGS) $(BASIC_CFLAGS)
558 BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS) 547 BASIC_LDFLAGS := $(LIBUNWIND_LDFLAGS) $(BASIC_LDFLAGS)
559 LIB_OBJS += $(OUTPUT)util/unwind.o 548 LIB_OBJS += $(OUTPUT)util/unwind.o
560endif 549endif
561 550
562ifdef NO_LIBAUDIT 551ifndef NO_LIBAUDIT
563 BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
564else
565 FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit 552 FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
566 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y) 553 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); 554 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 555 else
556 BASIC_CFLAGS += -DLIBAUDIT_SUPPORT
570 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o 557 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
571 EXTLIBS += -laudit 558 EXTLIBS += -laudit
572 endif 559 endif
573endif 560endif
574 561
575ifdef NO_NEWT 562ifndef NO_NEWT
576 BASIC_CFLAGS += -DNO_NEWT_SUPPORT
577else
578 FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt 563 FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt
579 ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y) 564 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); 565 msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
581 BASIC_CFLAGS += -DNO_NEWT_SUPPORT
582 else 566 else
583 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h 567 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
584 BASIC_CFLAGS += -I/usr/include/slang 568 BASIC_CFLAGS += -I/usr/include/slang
569 BASIC_CFLAGS += -DNEWT_SUPPORT
585 EXTLIBS += -lnewt -lslang 570 EXTLIBS += -lnewt -lslang
586 LIB_OBJS += $(OUTPUT)ui/setup.o 571 LIB_OBJS += $(OUTPUT)ui/setup.o
587 LIB_OBJS += $(OUTPUT)ui/browser.o 572 LIB_OBJS += $(OUTPUT)ui/browser.o
@@ -603,17 +588,15 @@ else
603 endif 588 endif
604endif 589endif
605 590
606ifdef NO_GTK2 591ifndef NO_GTK2
607 BASIC_CFLAGS += -DNO_GTK2_SUPPORT
608else
609 FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) 592 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) 593 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); 594 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
612 BASIC_CFLAGS += -DNO_GTK2_SUPPORT
613 else 595 else
614 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y) 596 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
615 BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR 597 BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
616 endif 598 endif
599 BASIC_CFLAGS += -DGTK2_SUPPORT
617 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) 600 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
618 EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null) 601 EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
619 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o 602 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
@@ -621,7 +604,7 @@ else
621 LIB_OBJS += $(OUTPUT)ui/gtk/util.o 604 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
622 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o 605 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
623 # Make sure that it'd be included only once. 606 # Make sure that it'd be included only once.
624 ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),) 607 ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
625 LIB_OBJS += $(OUTPUT)ui/setup.o 608 LIB_OBJS += $(OUTPUT)ui/setup.o
626 LIB_OBJS += $(OUTPUT)ui/util.o 609 LIB_OBJS += $(OUTPUT)ui/util.o
627 endif 610 endif
@@ -762,23 +745,18 @@ ifeq ($(NO_PERF_REGS),0)
762 ifeq ($(ARCH),x86) 745 ifeq ($(ARCH),x86)
763 LIB_H += arch/x86/include/perf_regs.h 746 LIB_H += arch/x86/include/perf_regs.h
764 endif 747 endif
765else 748 BASIC_CFLAGS += -DHAVE_PERF_REGS
766 BASIC_CFLAGS += -DNO_PERF_REGS
767endif 749endif
768 750
769ifdef NO_STRLCPY 751ifndef NO_STRLCPY
770 BASIC_CFLAGS += -DNO_STRLCPY 752 ifeq ($(call try-cc,$(SOURCE_STRLCPY),),y)
771else 753 BASIC_CFLAGS += -DHAVE_STRLCPY
772 ifneq ($(call try-cc,$(SOURCE_STRLCPY),),y)
773 BASIC_CFLAGS += -DNO_STRLCPY
774 endif 754 endif
775endif 755endif
776 756
777ifdef NO_BACKTRACE 757ifndef NO_BACKTRACE
778 BASIC_CFLAGS += -DNO_BACKTRACE 758 ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
779else 759 BASIC_CFLAGS += -DBACKTRACE_SUPPORT
780 ifneq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
781 BASIC_CFLAGS += -DNO_BACKTRACE
782 endif 760 endif
783endif 761endif
784 762
@@ -906,7 +884,7 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
906 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 884 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
907 885
908$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 886$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
909 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 887 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
910 888
911$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS 889$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
912 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls $< 890 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls $<
diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index 1958fa539d0f..56e6a12aab59 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -1,23 +1,59 @@
1# perf completion 1# perf completion
2 2
3function_exists()
4{
5 declare -F $1 > /dev/null
6 return $?
7}
8
9function_exists __ltrim_colon_completions ||
10__ltrim_colon_completions()
11{
12 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
13 # Remove colon-word prefix from COMPREPLY items
14 local colon_word=${1%${1##*:}}
15 local i=${#COMPREPLY[*]}
16 while [[ $((--i)) -ge 0 ]]; do
17 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
18 done
19 fi
20}
21
3have perf && 22have perf &&
4_perf() 23_perf()
5{ 24{
6 local cur cmd 25 local cur prev cmd
7 26
8 COMPREPLY=() 27 COMPREPLY=()
9 _get_comp_words_by_ref cur prev 28 if function_exists _get_comp_words_by_ref; then
29 _get_comp_words_by_ref -n : cur prev
30 else
31 cur=$(_get_cword :)
32 prev=${COMP_WORDS[COMP_CWORD-1]}
33 fi
10 34
11 cmd=${COMP_WORDS[0]} 35 cmd=${COMP_WORDS[0]}
12 36
13 # List perf subcommands 37 # List perf subcommands or long options
14 if [ $COMP_CWORD -eq 1 ]; then 38 if [ $COMP_CWORD -eq 1 ]; then
15 cmds=$($cmd --list-cmds) 39 if [[ $cur == --* ]]; then
16 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) 40 COMPREPLY=( $( compgen -W '--help --version \
41 --exec-path --html-path --paginate --no-pager \
42 --perf-dir --work-tree --debugfs-dir' -- "$cur" ) )
43 else
44 cmds=$($cmd --list-cmds)
45 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
46 fi
17 # List possible events for -e option 47 # List possible events for -e option
18 elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then 48 elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then
19 cmds=$($cmd list --raw-dump) 49 evts=$($cmd list --raw-dump)
20 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) 50 COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
51 __ltrim_colon_completions $cur
52 # List long option names
53 elif [[ $cur == --* ]]; then
54 subcmd=${COMP_WORDS[1]}
55 opts=$($cmd $subcmd --list-opts)
56 COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
21 # Fall down to list regular files 57 # Fall down to list regular files
22 else 58 else
23 _filedir 59 _filedir
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 83654557e108..d37e077f4b14 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -15,22 +15,6 @@
15#include "util/strlist.h" 15#include "util/strlist.h"
16#include "util/symbol.h" 16#include "util/symbol.h"
17 17
18static char const *add_name_list_str, *remove_name_list_str;
19
20static const char * const buildid_cache_usage[] = {
21 "perf buildid-cache [<options>]",
22 NULL
23};
24
25static const struct option buildid_cache_options[] = {
26 OPT_STRING('a', "add", &add_name_list_str,
27 "file list", "file(s) to add"),
28 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
29 "file(s) to remove"),
30 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
31 OPT_END()
32};
33
34static int build_id_cache__add_file(const char *filename, const char *debugdir) 18static int build_id_cache__add_file(const char *filename, const char *debugdir)
35{ 19{
36 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 20 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -51,8 +35,8 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
51 return err; 35 return err;
52} 36}
53 37
54static int build_id_cache__remove_file(const char *filename __maybe_unused, 38static int build_id_cache__remove_file(const char *filename,
55 const char *debugdir __maybe_unused) 39 const char *debugdir)
56{ 40{
57 u8 build_id[BUILD_ID_SIZE]; 41 u8 build_id[BUILD_ID_SIZE];
58 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 42 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -73,11 +57,34 @@ static int build_id_cache__remove_file(const char *filename __maybe_unused,
73 return err; 57 return err;
74} 58}
75 59
76static int __cmd_buildid_cache(void) 60int cmd_buildid_cache(int argc, const char **argv,
61 const char *prefix __maybe_unused)
77{ 62{
78 struct strlist *list; 63 struct strlist *list;
79 struct str_node *pos; 64 struct str_node *pos;
80 char debugdir[PATH_MAX]; 65 char debugdir[PATH_MAX];
66 char const *add_name_list_str = NULL,
67 *remove_name_list_str = NULL;
68 const struct option buildid_cache_options[] = {
69 OPT_STRING('a', "add", &add_name_list_str,
70 "file list", "file(s) to add"),
71 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
72 "file(s) to remove"),
73 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
74 OPT_END()
75 };
76 const char * const buildid_cache_usage[] = {
77 "perf buildid-cache [<options>]",
78 NULL
79 };
80
81 argc = parse_options(argc, argv, buildid_cache_options,
82 buildid_cache_usage, 0);
83
84 if (symbol__init() < 0)
85 return -1;
86
87 setup_pager();
81 88
82 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); 89 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
83 90
@@ -119,16 +126,3 @@ static int __cmd_buildid_cache(void)
119 126
120 return 0; 127 return 0;
121} 128}
122
123int cmd_buildid_cache(int argc, const char **argv,
124 const char *prefix __maybe_unused)
125{
126 argc = parse_options(argc, argv, buildid_cache_options,
127 buildid_cache_usage, 0);
128
129 if (symbol__init() < 0)
130 return -1;
131
132 setup_pager();
133 return __cmd_buildid_cache();
134}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 1159feeebb19..a0e94fffa03e 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -16,27 +16,6 @@
16#include "util/session.h" 16#include "util/session.h"
17#include "util/symbol.h" 17#include "util/symbol.h"
18 18
19static const char *input_name;
20static bool force;
21static bool show_kernel;
22static bool with_hits;
23
24static const char * const buildid_list_usage[] = {
25 "perf buildid-list [<options>]",
26 NULL
27};
28
29static const struct option options[] = {
30 OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
31 OPT_STRING('i', "input", &input_name, "file",
32 "input file name"),
33 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
34 OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
35 OPT_INCR('v', "verbose", &verbose,
36 "be more verbose"),
37 OPT_END()
38};
39
40static int sysfs__fprintf_build_id(FILE *fp) 19static int sysfs__fprintf_build_id(FILE *fp)
41{ 20{
42 u8 kallsyms_build_id[BUILD_ID_SIZE]; 21 u8 kallsyms_build_id[BUILD_ID_SIZE];
@@ -65,7 +44,8 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
65 return fprintf(fp, "%s\n", sbuild_id); 44 return fprintf(fp, "%s\n", sbuild_id);
66} 45}
67 46
68static int perf_session__list_build_ids(void) 47static int perf_session__list_build_ids(const char *input_name,
48 bool force, bool with_hits)
69{ 49{
70 struct perf_session *session; 50 struct perf_session *session;
71 51
@@ -95,18 +75,31 @@ out:
95 return 0; 75 return 0;
96} 76}
97 77
98static int __cmd_buildid_list(void)
99{
100 if (show_kernel)
101 return sysfs__fprintf_build_id(stdout);
102
103 return perf_session__list_build_ids();
104}
105
106int cmd_buildid_list(int argc, const char **argv, 78int cmd_buildid_list(int argc, const char **argv,
107 const char *prefix __maybe_unused) 79 const char *prefix __maybe_unused)
108{ 80{
81 bool show_kernel = false;
82 bool with_hits = false;
83 bool force = false;
84 const char *input_name = NULL;
85 const struct option options[] = {
86 OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
87 OPT_STRING('i', "input", &input_name, "file", "input file name"),
88 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
89 OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
90 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
91 OPT_END()
92 };
93 const char * const buildid_list_usage[] = {
94 "perf buildid-list [<options>]",
95 NULL
96 };
97
109 argc = parse_options(argc, argv, options, buildid_list_usage, 0); 98 argc = parse_options(argc, argv, options, buildid_list_usage, 0);
110 setup_pager(); 99 setup_pager();
111 return __cmd_buildid_list(); 100
101 if (show_kernel)
102 return sysfs__fprintf_build_id(stdout);
103
104 return perf_session__list_build_ids(input_name, force, with_hits);
112} 105}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 761f4197a9e2..a0b531c14b97 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -70,8 +70,8 @@ static struct perf_tool tool = {
70 .ordering_requires_timestamps = true, 70 .ordering_requires_timestamps = true,
71}; 71};
72 72
73static void perf_session__insert_hist_entry_by_name(struct rb_root *root, 73static void insert_hist_entry_by_name(struct rb_root *root,
74 struct hist_entry *he) 74 struct hist_entry *he)
75{ 75{
76 struct rb_node **p = &root->rb_node; 76 struct rb_node **p = &root->rb_node;
77 struct rb_node *parent = NULL; 77 struct rb_node *parent = NULL;
@@ -90,7 +90,7 @@ static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
90 rb_insert_color(&he->rb_node, root); 90 rb_insert_color(&he->rb_node, root);
91} 91}
92 92
93static void hists__resort_entries(struct hists *self) 93static void hists__name_resort(struct hists *self, bool sort)
94{ 94{
95 unsigned long position = 1; 95 unsigned long position = 1;
96 struct rb_root tmp = RB_ROOT; 96 struct rb_root tmp = RB_ROOT;
@@ -100,12 +100,16 @@ static void hists__resort_entries(struct hists *self)
100 struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); 100 struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node);
101 101
102 next = rb_next(&n->rb_node); 102 next = rb_next(&n->rb_node);
103 rb_erase(&n->rb_node, &self->entries);
104 n->position = position++; 103 n->position = position++;
105 perf_session__insert_hist_entry_by_name(&tmp, n); 104
105 if (sort) {
106 rb_erase(&n->rb_node, &self->entries);
107 insert_hist_entry_by_name(&tmp, n);
108 }
106 } 109 }
107 110
108 self->entries = tmp; 111 if (sort)
112 self->entries = tmp;
109} 113}
110 114
111static struct hist_entry *hists__find_entry(struct hists *self, 115static struct hist_entry *hists__find_entry(struct hists *self,
@@ -121,7 +125,7 @@ static struct hist_entry *hists__find_entry(struct hists *self,
121 n = n->rb_left; 125 n = n->rb_left;
122 else if (cmp > 0) 126 else if (cmp > 0)
123 n = n->rb_right; 127 n = n->rb_right;
124 else 128 else
125 return iter; 129 return iter;
126 } 130 }
127 131
@@ -150,6 +154,24 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
150 return NULL; 154 return NULL;
151} 155}
152 156
157static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
158{
159 struct perf_evsel *evsel;
160
161 list_for_each_entry(evsel, &evlist->entries, node) {
162 struct hists *hists = &evsel->hists;
163
164 hists__output_resort(hists);
165
166 /*
167 * The hists__name_resort only sets possition
168 * if name is false.
169 */
170 if (name || ((!name) && show_displacement))
171 hists__name_resort(hists, name);
172 }
173}
174
153static int __cmd_diff(void) 175static int __cmd_diff(void)
154{ 176{
155 int ret, i; 177 int ret, i;
@@ -176,15 +198,8 @@ static int __cmd_diff(void)
176 evlist_old = older->evlist; 198 evlist_old = older->evlist;
177 evlist_new = newer->evlist; 199 evlist_new = newer->evlist;
178 200
179 list_for_each_entry(evsel, &evlist_new->entries, node) 201 perf_evlist__resort_hists(evlist_old, true);
180 hists__output_resort(&evsel->hists); 202 perf_evlist__resort_hists(evlist_new, false);
181
182 list_for_each_entry(evsel, &evlist_old->entries, node) {
183 hists__output_resort(&evsel->hists);
184
185 if (show_displacement)
186 hists__resort_entries(&evsel->hists);
187 }
188 203
189 list_for_each_entry(evsel, &evlist_new->entries, node) { 204 list_for_each_entry(evsel, &evlist_new->entries, node) {
190 struct perf_evsel *evsel_old; 205 struct perf_evsel *evsel_old;
@@ -199,8 +214,7 @@ static int __cmd_diff(void)
199 first = false; 214 first = false;
200 215
201 hists__match(&evsel_old->hists, &evsel->hists); 216 hists__match(&evsel_old->hists, &evsel->hists);
202 hists__fprintf(&evsel->hists, &evsel_old->hists, 217 hists__fprintf(&evsel->hists, true, 0, 0, stdout);
203 show_displacement, true, 0, 0, stdout);
204 } 218 }
205 219
206out_delete: 220out_delete:
@@ -242,6 +256,21 @@ static const struct option options[] = {
242 OPT_END() 256 OPT_END()
243}; 257};
244 258
259static void ui_init(void)
260{
261 perf_hpp__init();
262
263 /* No overhead column. */
264 perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
265
266 /* Display baseline/delta/displacement columns. */
267 perf_hpp__column_enable(PERF_HPP__BASELINE, true);
268 perf_hpp__column_enable(PERF_HPP__DELTA, true);
269
270 if (show_displacement)
271 perf_hpp__column_enable(PERF_HPP__DISPL, true);
272}
273
245int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) 274int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
246{ 275{
247 sort_order = diff__default_sort_order; 276 sort_order = diff__default_sort_order;
@@ -264,7 +293,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
264 if (symbol__init() < 0) 293 if (symbol__init() < 0)
265 return -1; 294 return -1;
266 295
267 perf_hpp__init(true, show_displacement); 296 ui_init();
297
268 setup_sorting(diff_usage, options); 298 setup_sorting(diff_usage, options);
269 setup_pager(); 299 setup_pager();
270 300
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 1fb164164fd0..997afb82691b 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -108,23 +108,20 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
108 return 0; 108 return 0;
109} 109}
110 110
111static const char * const evlist_usage[] = {
112 "perf evlist [<options>]",
113 NULL
114};
115
116int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) 111int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
117{ 112{
118 struct perf_attr_details details = { .verbose = false, }; 113 struct perf_attr_details details = { .verbose = false, };
119 const char *input_name = NULL; 114 const char *input_name = NULL;
120 const struct option options[] = { 115 const struct option options[] = {
121 OPT_STRING('i', "input", &input_name, "file", 116 OPT_STRING('i', "input", &input_name, "file", "Input file name"),
122 "Input file name"), 117 OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"),
123 OPT_BOOLEAN('F', "freq", &details.freq, 118 OPT_BOOLEAN('v', "verbose", &details.verbose,
124 "Show the sample frequency"), 119 "Show all event attr details"),
125 OPT_BOOLEAN('v', "verbose", &details.verbose, 120 OPT_END()
126 "Show all event attr details"), 121 };
127 OPT_END() 122 const char * const evlist_usage[] = {
123 "perf evlist [<options>]",
124 NULL
128 }; 125 };
129 126
130 argc = parse_options(argc, argv, options, evlist_usage, 0); 127 argc = parse_options(argc, argv, options, evlist_usage, 0);
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 25c8b942ff85..178b88ae3d2f 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -30,23 +30,6 @@ enum help_format {
30 HELP_FORMAT_WEB, 30 HELP_FORMAT_WEB,
31}; 31};
32 32
33static bool show_all = false;
34static enum help_format help_format = HELP_FORMAT_NONE;
35static struct option builtin_help_options[] = {
36 OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
37 OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
38 OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
39 HELP_FORMAT_WEB),
40 OPT_SET_UINT('i', "info", &help_format, "show info page",
41 HELP_FORMAT_INFO),
42 OPT_END(),
43};
44
45static const char * const builtin_help_usage[] = {
46 "perf help [--all] [--man|--web|--info] [command]",
47 NULL
48};
49
50static enum help_format parse_help_format(const char *format) 33static enum help_format parse_help_format(const char *format)
51{ 34{
52 if (!strcmp(format, "man")) 35 if (!strcmp(format, "man"))
@@ -258,11 +241,13 @@ static int add_man_viewer_info(const char *var, const char *value)
258 241
259static int perf_help_config(const char *var, const char *value, void *cb) 242static int perf_help_config(const char *var, const char *value, void *cb)
260{ 243{
244 enum help_format *help_formatp = cb;
245
261 if (!strcmp(var, "help.format")) { 246 if (!strcmp(var, "help.format")) {
262 if (!value) 247 if (!value)
263 return config_error_nonbool(var); 248 return config_error_nonbool(var);
264 help_format = parse_help_format(value); 249 *help_formatp = parse_help_format(value);
265 if (help_format == HELP_FORMAT_NONE) 250 if (*help_formatp == HELP_FORMAT_NONE)
266 return -1; 251 return -1;
267 return 0; 252 return 0;
268 } 253 }
@@ -428,12 +413,27 @@ static int show_html_page(const char *perf_cmd)
428 413
429int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused) 414int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
430{ 415{
416 bool show_all = false;
417 enum help_format help_format = HELP_FORMAT_MAN;
418 struct option builtin_help_options[] = {
419 OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
420 OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
421 OPT_SET_UINT('w', "web", &help_format, "show manual in web browser",
422 HELP_FORMAT_WEB),
423 OPT_SET_UINT('i', "info", &help_format, "show info page",
424 HELP_FORMAT_INFO),
425 OPT_END(),
426 };
427 const char * const builtin_help_usage[] = {
428 "perf help [--all] [--man|--web|--info] [command]",
429 NULL
430 };
431 const char *alias; 431 const char *alias;
432 int rc = 0; 432 int rc = 0;
433 433
434 load_command_list("perf-", &main_cmds, &other_cmds); 434 load_command_list("perf-", &main_cmds, &other_cmds);
435 435
436 perf_config(perf_help_config, NULL); 436 perf_config(perf_help_config, &help_format);
437 437
438 argc = parse_options(argc, argv, builtin_help_options, 438 argc = parse_options(argc, argv, builtin_help_options,
439 builtin_help_usage, 0); 439 builtin_help_usage, 0);
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 1eaa6617c814..4688bea95c12 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -14,8 +14,10 @@
14 14
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16 16
17static char const *input_name = "-"; 17struct perf_inject {
18static bool inject_build_ids; 18 struct perf_tool tool;
19 bool build_ids;
20};
19 21
20static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused, 22static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused,
21 union perf_event *event, 23 union perf_event *event,
@@ -194,7 +196,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
194 * account this as unresolved. 196 * account this as unresolved.
195 */ 197 */
196 } else { 198 } else {
197#ifndef NO_LIBELF_SUPPORT 199#ifdef LIBELF_SUPPORT
198 pr_warning("no symbols found in %s, maybe " 200 pr_warning("no symbols found in %s, maybe "
199 "install a debug package?\n", 201 "install a debug package?\n",
200 al.map->dso->long_name); 202 al.map->dso->long_name);
@@ -208,22 +210,6 @@ repipe:
208 return 0; 210 return 0;
209} 211}
210 212
211struct perf_tool perf_inject = {
212 .sample = perf_event__repipe_sample,
213 .mmap = perf_event__repipe,
214 .comm = perf_event__repipe,
215 .fork = perf_event__repipe,
216 .exit = perf_event__repipe,
217 .lost = perf_event__repipe,
218 .read = perf_event__repipe_sample,
219 .throttle = perf_event__repipe,
220 .unthrottle = perf_event__repipe,
221 .attr = perf_event__repipe_attr,
222 .event_type = perf_event__repipe_event_type_synth,
223 .tracing_data = perf_event__repipe_tracing_data_synth,
224 .build_id = perf_event__repipe_op2_synth,
225};
226
227extern volatile int session_done; 213extern volatile int session_done;
228 214
229static void sig_handler(int sig __maybe_unused) 215static void sig_handler(int sig __maybe_unused)
@@ -231,56 +217,72 @@ static void sig_handler(int sig __maybe_unused)
231 session_done = 1; 217 session_done = 1;
232} 218}
233 219
234static int __cmd_inject(void) 220static int __cmd_inject(struct perf_inject *inject)
235{ 221{
236 struct perf_session *session; 222 struct perf_session *session;
237 int ret = -EINVAL; 223 int ret = -EINVAL;
238 224
239 signal(SIGINT, sig_handler); 225 signal(SIGINT, sig_handler);
240 226
241 if (inject_build_ids) { 227 if (inject->build_ids) {
242 perf_inject.sample = perf_event__inject_buildid; 228 inject->tool.sample = perf_event__inject_buildid;
243 perf_inject.mmap = perf_event__repipe_mmap; 229 inject->tool.mmap = perf_event__repipe_mmap;
244 perf_inject.fork = perf_event__repipe_task; 230 inject->tool.fork = perf_event__repipe_task;
245 perf_inject.tracing_data = perf_event__repipe_tracing_data; 231 inject->tool.tracing_data = perf_event__repipe_tracing_data;
246 } 232 }
247 233
248 session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject); 234 session = perf_session__new("-", O_RDONLY, false, true, &inject->tool);
249 if (session == NULL) 235 if (session == NULL)
250 return -ENOMEM; 236 return -ENOMEM;
251 237
252 ret = perf_session__process_events(session, &perf_inject); 238 ret = perf_session__process_events(session, &inject->tool);
253 239
254 perf_session__delete(session); 240 perf_session__delete(session);
255 241
256 return ret; 242 return ret;
257} 243}
258 244
259static const char * const report_usage[] = {
260 "perf inject [<options>]",
261 NULL
262};
263
264static const struct option options[] = {
265 OPT_BOOLEAN('b', "build-ids", &inject_build_ids,
266 "Inject build-ids into the output stream"),
267 OPT_INCR('v', "verbose", &verbose,
268 "be more verbose (show build ids, etc)"),
269 OPT_END()
270};
271
272int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) 245int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
273{ 246{
274 argc = parse_options(argc, argv, options, report_usage, 0); 247 struct perf_inject inject = {
248 .tool = {
249 .sample = perf_event__repipe_sample,
250 .mmap = perf_event__repipe,
251 .comm = perf_event__repipe,
252 .fork = perf_event__repipe,
253 .exit = perf_event__repipe,
254 .lost = perf_event__repipe,
255 .read = perf_event__repipe_sample,
256 .throttle = perf_event__repipe,
257 .unthrottle = perf_event__repipe,
258 .attr = perf_event__repipe_attr,
259 .event_type = perf_event__repipe_event_type_synth,
260 .tracing_data = perf_event__repipe_tracing_data_synth,
261 .build_id = perf_event__repipe_op2_synth,
262 },
263 };
264 const struct option options[] = {
265 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
266 "Inject build-ids into the output stream"),
267 OPT_INCR('v', "verbose", &verbose,
268 "be more verbose (show build ids, etc)"),
269 OPT_END()
270 };
271 const char * const inject_usage[] = {
272 "perf inject [<options>]",
273 NULL
274 };
275
276 argc = parse_options(argc, argv, options, inject_usage, 0);
275 277
276 /* 278 /*
277 * Any (unrecognized) arguments left? 279 * Any (unrecognized) arguments left?
278 */ 280 */
279 if (argc) 281 if (argc)
280 usage_with_options(report_usage, options); 282 usage_with_options(inject_usage, options);
281 283
282 if (symbol__init() < 0) 284 if (symbol__init() < 0)
283 return -1; 285 return -1;
284 286
285 return __cmd_inject(); 287 return __cmd_inject(&inject);
286} 288}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index bc912c68f49a..14bf82f63659 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -21,8 +21,6 @@
21struct alloc_stat; 21struct alloc_stat;
22typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 22typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
23 23
24static const char *input_name;
25
26static int alloc_flag; 24static int alloc_flag;
27static int caller_flag; 25static int caller_flag;
28 26
@@ -31,8 +29,6 @@ static int caller_lines = -1;
31 29
32static bool raw_ip; 30static bool raw_ip;
33 31
34static char default_sort_order[] = "frag,hit,bytes";
35
36static int *cpunode_map; 32static int *cpunode_map;
37static int max_cpu_num; 33static int max_cpu_num;
38 34
@@ -481,7 +477,7 @@ static void sort_result(void)
481 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 477 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
482} 478}
483 479
484static int __cmd_kmem(void) 480static int __cmd_kmem(const char *input_name)
485{ 481{
486 int err = -EINVAL; 482 int err = -EINVAL;
487 struct perf_session *session; 483 struct perf_session *session;
@@ -520,11 +516,6 @@ out_delete:
520 return err; 516 return err;
521} 517}
522 518
523static const char * const kmem_usage[] = {
524 "perf kmem [<options>] {record|stat}",
525 NULL
526};
527
528static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r) 519static int ptr_cmp(struct alloc_stat *l, struct alloc_stat *r)
529{ 520{
530 if (l->ptr < r->ptr) 521 if (l->ptr < r->ptr)
@@ -720,41 +711,17 @@ static int parse_line_opt(const struct option *opt __maybe_unused,
720 return 0; 711 return 0;
721} 712}
722 713
723static const struct option kmem_options[] = { 714static int __cmd_record(int argc, const char **argv)
724 OPT_STRING('i', "input", &input_name, "file", 715{
725 "input file name"), 716 const char * const record_args[] = {
726 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL, 717 "record", "-a", "-R", "-f", "-c", "1",
727 "show per-callsite statistics",
728 parse_caller_opt),
729 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
730 "show per-allocation statistics",
731 parse_alloc_opt),
732 OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
733 "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
734 parse_sort_opt),
735 OPT_CALLBACK('l', "line", NULL, "num",
736 "show n lines",
737 parse_line_opt),
738 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
739 OPT_END()
740};
741
742static const char *record_args[] = {
743 "record",
744 "-a",
745 "-R",
746 "-f",
747 "-c", "1",
748 "-e", "kmem:kmalloc", 718 "-e", "kmem:kmalloc",
749 "-e", "kmem:kmalloc_node", 719 "-e", "kmem:kmalloc_node",
750 "-e", "kmem:kfree", 720 "-e", "kmem:kfree",
751 "-e", "kmem:kmem_cache_alloc", 721 "-e", "kmem:kmem_cache_alloc",
752 "-e", "kmem:kmem_cache_alloc_node", 722 "-e", "kmem:kmem_cache_alloc_node",
753 "-e", "kmem:kmem_cache_free", 723 "-e", "kmem:kmem_cache_free",
754}; 724 };
755
756static int __cmd_record(int argc, const char **argv)
757{
758 unsigned int rec_argc, i, j; 725 unsigned int rec_argc, i, j;
759 const char **rec_argv; 726 const char **rec_argv;
760 727
@@ -775,6 +742,25 @@ static int __cmd_record(int argc, const char **argv)
775 742
776int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) 743int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
777{ 744{
745 const char * const default_sort_order = "frag,hit,bytes";
746 const char *input_name = NULL;
747 const struct option kmem_options[] = {
748 OPT_STRING('i', "input", &input_name, "file", "input file name"),
749 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
750 "show per-callsite statistics", parse_caller_opt),
751 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
752 "show per-allocation statistics", parse_alloc_opt),
753 OPT_CALLBACK('s', "sort", NULL, "key[,key2...]",
754 "sort by keys: ptr, call_site, bytes, hit, pingpong, frag",
755 parse_sort_opt),
756 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
757 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
758 OPT_END()
759 };
760 const char * const kmem_usage[] = {
761 "perf kmem [<options>] {record|stat}",
762 NULL
763 };
778 argc = parse_options(argc, argv, kmem_options, kmem_usage, 0); 764 argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);
779 765
780 if (!argc) 766 if (!argc)
@@ -793,7 +779,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
793 if (list_empty(&alloc_sort)) 779 if (list_empty(&alloc_sort))
794 setup_sorting(&alloc_sort, default_sort_order); 780 setup_sorting(&alloc_sort, default_sort_order);
795 781
796 return __cmd_kmem(); 782 return __cmd_kmem(input_name);
797 } else 783 } else
798 usage_with_options(kmem_usage, kmem_options); 784 usage_with_options(kmem_usage, kmem_options);
799 785
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index a28c9cad9048..260abc535b5b 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -32,16 +32,76 @@ struct event_key {
32 int info; 32 int info;
33}; 33};
34 34
35struct kvm_event_stats {
36 u64 time;
37 struct stats stats;
38};
39
40struct kvm_event {
41 struct list_head hash_entry;
42 struct rb_node rb;
43
44 struct event_key key;
45
46 struct kvm_event_stats total;
47
48 #define DEFAULT_VCPU_NUM 8
49 int max_vcpu;
50 struct kvm_event_stats *vcpu;
51};
52
53typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
54
55struct kvm_event_key {
56 const char *name;
57 key_cmp_fun key;
58};
59
60
61struct perf_kvm;
62
35struct kvm_events_ops { 63struct kvm_events_ops {
36 bool (*is_begin_event)(struct perf_evsel *evsel, 64 bool (*is_begin_event)(struct perf_evsel *evsel,
37 struct perf_sample *sample, 65 struct perf_sample *sample,
38 struct event_key *key); 66 struct event_key *key);
39 bool (*is_end_event)(struct perf_evsel *evsel, 67 bool (*is_end_event)(struct perf_evsel *evsel,
40 struct perf_sample *sample, struct event_key *key); 68 struct perf_sample *sample, struct event_key *key);
41 void (*decode_key)(struct event_key *key, char decode[20]); 69 void (*decode_key)(struct perf_kvm *kvm, struct event_key *key,
70 char decode[20]);
42 const char *name; 71 const char *name;
43}; 72};
44 73
74struct exit_reasons_table {
75 unsigned long exit_code;
76 const char *reason;
77};
78
79#define EVENTS_BITS 12
80#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
81
82struct perf_kvm {
83 struct perf_tool tool;
84 struct perf_session *session;
85
86 const char *file_name;
87 const char *report_event;
88 const char *sort_key;
89 int trace_vcpu;
90
91 struct exit_reasons_table *exit_reasons;
92 int exit_reasons_size;
93 const char *exit_reasons_isa;
94
95 struct kvm_events_ops *events_ops;
96 key_cmp_fun compare;
97 struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
98 u64 total_time;
99 u64 total_count;
100
101 struct rb_root result;
102};
103
104
45static void exit_event_get_key(struct perf_evsel *evsel, 105static void exit_event_get_key(struct perf_evsel *evsel,
46 struct perf_sample *sample, 106 struct perf_sample *sample,
47 struct event_key *key) 107 struct event_key *key)
@@ -78,45 +138,35 @@ static bool exit_event_end(struct perf_evsel *evsel,
78 return kvm_entry_event(evsel); 138 return kvm_entry_event(evsel);
79} 139}
80 140
81struct exit_reasons_table { 141static struct exit_reasons_table vmx_exit_reasons[] = {
82 unsigned long exit_code;
83 const char *reason;
84};
85
86struct exit_reasons_table vmx_exit_reasons[] = {
87 VMX_EXIT_REASONS 142 VMX_EXIT_REASONS
88}; 143};
89 144
90struct exit_reasons_table svm_exit_reasons[] = { 145static struct exit_reasons_table svm_exit_reasons[] = {
91 SVM_EXIT_REASONS 146 SVM_EXIT_REASONS
92}; 147};
93 148
94static int cpu_isa; 149static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
95
96static const char *get_exit_reason(u64 exit_code)
97{ 150{
98 int table_size = ARRAY_SIZE(svm_exit_reasons); 151 int i = kvm->exit_reasons_size;
99 struct exit_reasons_table *table = svm_exit_reasons; 152 struct exit_reasons_table *tbl = kvm->exit_reasons;
100
101 if (cpu_isa == 1) {
102 table = vmx_exit_reasons;
103 table_size = ARRAY_SIZE(vmx_exit_reasons);
104 }
105 153
106 while (table_size--) { 154 while (i--) {
107 if (table->exit_code == exit_code) 155 if (tbl->exit_code == exit_code)
108 return table->reason; 156 return tbl->reason;
109 table++; 157 tbl++;
110 } 158 }
111 159
112 pr_err("unknown kvm exit code:%lld on %s\n", 160 pr_err("unknown kvm exit code:%lld on %s\n",
113 (unsigned long long)exit_code, cpu_isa ? "VMX" : "SVM"); 161 (unsigned long long)exit_code, kvm->exit_reasons_isa);
114 return "UNKNOWN"; 162 return "UNKNOWN";
115} 163}
116 164
117static void exit_event_decode_key(struct event_key *key, char decode[20]) 165static void exit_event_decode_key(struct perf_kvm *kvm,
166 struct event_key *key,
167 char decode[20])
118{ 168{
119 const char *exit_reason = get_exit_reason(key->key); 169 const char *exit_reason = get_exit_reason(kvm, key->key);
120 170
121 scnprintf(decode, 20, "%s", exit_reason); 171 scnprintf(decode, 20, "%s", exit_reason);
122} 172}
@@ -128,11 +178,11 @@ static struct kvm_events_ops exit_events = {
128 .name = "VM-EXIT" 178 .name = "VM-EXIT"
129}; 179};
130 180
131 /* 181/*
132 * For the mmio events, we treat: 182 * For the mmio events, we treat:
133 * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry 183 * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
134 * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...). 184 * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...).
135 */ 185 */
136static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample, 186static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample,
137 struct event_key *key) 187 struct event_key *key)
138{ 188{
@@ -178,7 +228,9 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
178 return false; 228 return false;
179} 229}
180 230
181static void mmio_event_decode_key(struct event_key *key, char decode[20]) 231static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused,
232 struct event_key *key,
233 char decode[20])
182{ 234{
183 scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key, 235 scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key,
184 key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R"); 236 key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
@@ -219,7 +271,9 @@ static bool ioport_event_end(struct perf_evsel *evsel,
219 return kvm_entry_event(evsel); 271 return kvm_entry_event(evsel);
220} 272}
221 273
222static void ioport_event_decode_key(struct event_key *key, char decode[20]) 274static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused,
275 struct event_key *key,
276 char decode[20])
223{ 277{
224 scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key, 278 scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key,
225 key->info ? "POUT" : "PIN"); 279 key->info ? "POUT" : "PIN");
@@ -232,64 +286,37 @@ static struct kvm_events_ops ioport_events = {
232 .name = "IO Port Access" 286 .name = "IO Port Access"
233}; 287};
234 288
235static const char *report_event = "vmexit"; 289static bool register_kvm_events_ops(struct perf_kvm *kvm)
236struct kvm_events_ops *events_ops;
237
238static bool register_kvm_events_ops(void)
239{ 290{
240 bool ret = true; 291 bool ret = true;
241 292
242 if (!strcmp(report_event, "vmexit")) 293 if (!strcmp(kvm->report_event, "vmexit"))
243 events_ops = &exit_events; 294 kvm->events_ops = &exit_events;
244 else if (!strcmp(report_event, "mmio")) 295 else if (!strcmp(kvm->report_event, "mmio"))
245 events_ops = &mmio_events; 296 kvm->events_ops = &mmio_events;
246 else if (!strcmp(report_event, "ioport")) 297 else if (!strcmp(kvm->report_event, "ioport"))
247 events_ops = &ioport_events; 298 kvm->events_ops = &ioport_events;
248 else { 299 else {
249 pr_err("Unknown report event:%s\n", report_event); 300 pr_err("Unknown report event:%s\n", kvm->report_event);
250 ret = false; 301 ret = false;
251 } 302 }
252 303
253 return ret; 304 return ret;
254} 305}
255 306
256struct kvm_event_stats {
257 u64 time;
258 struct stats stats;
259};
260
261struct kvm_event {
262 struct list_head hash_entry;
263 struct rb_node rb;
264
265 struct event_key key;
266
267 struct kvm_event_stats total;
268
269 #define DEFAULT_VCPU_NUM 8
270 int max_vcpu;
271 struct kvm_event_stats *vcpu;
272};
273
274struct vcpu_event_record { 307struct vcpu_event_record {
275 int vcpu_id; 308 int vcpu_id;
276 u64 start_time; 309 u64 start_time;
277 struct kvm_event *last_event; 310 struct kvm_event *last_event;
278}; 311};
279 312
280#define EVENTS_BITS 12
281#define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS)
282
283static u64 total_time;
284static u64 total_count;
285static struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
286 313
287static void init_kvm_event_record(void) 314static void init_kvm_event_record(struct perf_kvm *kvm)
288{ 315{
289 int i; 316 int i;
290 317
291 for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++) 318 for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
292 INIT_LIST_HEAD(&kvm_events_cache[i]); 319 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
293} 320}
294 321
295static int kvm_events_hash_fn(u64 key) 322static int kvm_events_hash_fn(u64 key)
@@ -333,14 +360,15 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
333 return event; 360 return event;
334} 361}
335 362
336static struct kvm_event *find_create_kvm_event(struct event_key *key) 363static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
364 struct event_key *key)
337{ 365{
338 struct kvm_event *event; 366 struct kvm_event *event;
339 struct list_head *head; 367 struct list_head *head;
340 368
341 BUG_ON(key->key == INVALID_KEY); 369 BUG_ON(key->key == INVALID_KEY);
342 370
343 head = &kvm_events_cache[kvm_events_hash_fn(key->key)]; 371 head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
344 list_for_each_entry(event, head, hash_entry) 372 list_for_each_entry(event, head, hash_entry)
345 if (event->key.key == key->key && event->key.info == key->info) 373 if (event->key.key == key->key && event->key.info == key->info)
346 return event; 374 return event;
@@ -353,13 +381,14 @@ static struct kvm_event *find_create_kvm_event(struct event_key *key)
353 return event; 381 return event;
354} 382}
355 383
356static bool handle_begin_event(struct vcpu_event_record *vcpu_record, 384static bool handle_begin_event(struct perf_kvm *kvm,
385 struct vcpu_event_record *vcpu_record,
357 struct event_key *key, u64 timestamp) 386 struct event_key *key, u64 timestamp)
358{ 387{
359 struct kvm_event *event = NULL; 388 struct kvm_event *event = NULL;
360 389
361 if (key->key != INVALID_KEY) 390 if (key->key != INVALID_KEY)
362 event = find_create_kvm_event(key); 391 event = find_create_kvm_event(kvm, key);
363 392
364 vcpu_record->last_event = event; 393 vcpu_record->last_event = event;
365 vcpu_record->start_time = timestamp; 394 vcpu_record->start_time = timestamp;
@@ -396,8 +425,10 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
396 return true; 425 return true;
397} 426}
398 427
399static bool handle_end_event(struct vcpu_event_record *vcpu_record, 428static bool handle_end_event(struct perf_kvm *kvm,
400 struct event_key *key, u64 timestamp) 429 struct vcpu_event_record *vcpu_record,
430 struct event_key *key,
431 u64 timestamp)
401{ 432{
402 struct kvm_event *event; 433 struct kvm_event *event;
403 u64 time_begin, time_diff; 434 u64 time_begin, time_diff;
@@ -419,7 +450,7 @@ static bool handle_end_event(struct vcpu_event_record *vcpu_record,
419 return true; 450 return true;
420 451
421 if (!event) 452 if (!event)
422 event = find_create_kvm_event(key); 453 event = find_create_kvm_event(kvm, key);
423 454
424 if (!event) 455 if (!event)
425 return false; 456 return false;
@@ -455,7 +486,9 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
455 return thread->priv; 486 return thread->priv;
456} 487}
457 488
458static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel, 489static bool handle_kvm_event(struct perf_kvm *kvm,
490 struct thread *thread,
491 struct perf_evsel *evsel,
459 struct perf_sample *sample) 492 struct perf_sample *sample)
460{ 493{
461 struct vcpu_event_record *vcpu_record; 494 struct vcpu_event_record *vcpu_record;
@@ -465,22 +498,15 @@ static bool handle_kvm_event(struct thread *thread, struct perf_evsel *evsel,
465 if (!vcpu_record) 498 if (!vcpu_record)
466 return true; 499 return true;
467 500
468 if (events_ops->is_begin_event(evsel, sample, &key)) 501 if (kvm->events_ops->is_begin_event(evsel, sample, &key))
469 return handle_begin_event(vcpu_record, &key, sample->time); 502 return handle_begin_event(kvm, vcpu_record, &key, sample->time);
470 503
471 if (events_ops->is_end_event(evsel, sample, &key)) 504 if (kvm->events_ops->is_end_event(evsel, sample, &key))
472 return handle_end_event(vcpu_record, &key, sample->time); 505 return handle_end_event(kvm, vcpu_record, &key, sample->time);
473 506
474 return true; 507 return true;
475} 508}
476 509
477typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int);
478struct kvm_event_key {
479 const char *name;
480 key_cmp_fun key;
481};
482
483static int trace_vcpu = -1;
484#define GET_EVENT_KEY(func, field) \ 510#define GET_EVENT_KEY(func, field) \
485static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \ 511static u64 get_event_ ##func(struct kvm_event *event, int vcpu) \
486{ \ 512{ \
@@ -515,29 +541,25 @@ static struct kvm_event_key keys[] = {
515 { NULL, NULL } 541 { NULL, NULL }
516}; 542};
517 543
518static const char *sort_key = "sample"; 544static bool select_key(struct perf_kvm *kvm)
519static key_cmp_fun compare;
520
521static bool select_key(void)
522{ 545{
523 int i; 546 int i;
524 547
525 for (i = 0; keys[i].name; i++) { 548 for (i = 0; keys[i].name; i++) {
526 if (!strcmp(keys[i].name, sort_key)) { 549 if (!strcmp(keys[i].name, kvm->sort_key)) {
527 compare = keys[i].key; 550 kvm->compare = keys[i].key;
528 return true; 551 return true;
529 } 552 }
530 } 553 }
531 554
532 pr_err("Unknown compare key:%s\n", sort_key); 555 pr_err("Unknown compare key:%s\n", kvm->sort_key);
533 return false; 556 return false;
534} 557}
535 558
536static struct rb_root result; 559static void insert_to_result(struct rb_root *result, struct kvm_event *event,
537static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger, 560 key_cmp_fun bigger, int vcpu)
538 int vcpu)
539{ 561{
540 struct rb_node **rb = &result.rb_node; 562 struct rb_node **rb = &result->rb_node;
541 struct rb_node *parent = NULL; 563 struct rb_node *parent = NULL;
542 struct kvm_event *p; 564 struct kvm_event *p;
543 565
@@ -552,13 +574,15 @@ static void insert_to_result(struct kvm_event *event, key_cmp_fun bigger,
552 } 574 }
553 575
554 rb_link_node(&event->rb, parent, rb); 576 rb_link_node(&event->rb, parent, rb);
555 rb_insert_color(&event->rb, &result); 577 rb_insert_color(&event->rb, result);
556} 578}
557 579
558static void update_total_count(struct kvm_event *event, int vcpu) 580static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event)
559{ 581{
560 total_count += get_event_count(event, vcpu); 582 int vcpu = kvm->trace_vcpu;
561 total_time += get_event_time(event, vcpu); 583
584 kvm->total_count += get_event_count(event, vcpu);
585 kvm->total_time += get_event_time(event, vcpu);
562} 586}
563 587
564static bool event_is_valid(struct kvm_event *event, int vcpu) 588static bool event_is_valid(struct kvm_event *event, int vcpu)
@@ -566,28 +590,30 @@ static bool event_is_valid(struct kvm_event *event, int vcpu)
566 return !!get_event_count(event, vcpu); 590 return !!get_event_count(event, vcpu);
567} 591}
568 592
569static void sort_result(int vcpu) 593static void sort_result(struct perf_kvm *kvm)
570{ 594{
571 unsigned int i; 595 unsigned int i;
596 int vcpu = kvm->trace_vcpu;
572 struct kvm_event *event; 597 struct kvm_event *event;
573 598
574 for (i = 0; i < EVENTS_CACHE_SIZE; i++) 599 for (i = 0; i < EVENTS_CACHE_SIZE; i++)
575 list_for_each_entry(event, &kvm_events_cache[i], hash_entry) 600 list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
576 if (event_is_valid(event, vcpu)) { 601 if (event_is_valid(event, vcpu)) {
577 update_total_count(event, vcpu); 602 update_total_count(kvm, event);
578 insert_to_result(event, compare, vcpu); 603 insert_to_result(&kvm->result, event,
604 kvm->compare, vcpu);
579 } 605 }
580} 606}
581 607
582/* returns left most element of result, and erase it */ 608/* returns left most element of result, and erase it */
583static struct kvm_event *pop_from_result(void) 609static struct kvm_event *pop_from_result(struct rb_root *result)
584{ 610{
585 struct rb_node *node = rb_first(&result); 611 struct rb_node *node = rb_first(result);
586 612
587 if (!node) 613 if (!node)
588 return NULL; 614 return NULL;
589 615
590 rb_erase(node, &result); 616 rb_erase(node, result);
591 return container_of(node, struct kvm_event, rb); 617 return container_of(node, struct kvm_event, rb);
592} 618}
593 619
@@ -601,14 +627,15 @@ static void print_vcpu_info(int vcpu)
601 pr_info("VCPU %d:\n\n", vcpu); 627 pr_info("VCPU %d:\n\n", vcpu);
602} 628}
603 629
604static void print_result(int vcpu) 630static void print_result(struct perf_kvm *kvm)
605{ 631{
606 char decode[20]; 632 char decode[20];
607 struct kvm_event *event; 633 struct kvm_event *event;
634 int vcpu = kvm->trace_vcpu;
608 635
609 pr_info("\n\n"); 636 pr_info("\n\n");
610 print_vcpu_info(vcpu); 637 print_vcpu_info(vcpu);
611 pr_info("%20s ", events_ops->name); 638 pr_info("%20s ", kvm->events_ops->name);
612 pr_info("%10s ", "Samples"); 639 pr_info("%10s ", "Samples");
613 pr_info("%9s ", "Samples%"); 640 pr_info("%9s ", "Samples%");
614 641
@@ -616,33 +643,34 @@ static void print_result(int vcpu)
616 pr_info("%16s ", "Avg time"); 643 pr_info("%16s ", "Avg time");
617 pr_info("\n\n"); 644 pr_info("\n\n");
618 645
619 while ((event = pop_from_result())) { 646 while ((event = pop_from_result(&kvm->result))) {
620 u64 ecount, etime; 647 u64 ecount, etime;
621 648
622 ecount = get_event_count(event, vcpu); 649 ecount = get_event_count(event, vcpu);
623 etime = get_event_time(event, vcpu); 650 etime = get_event_time(event, vcpu);
624 651
625 events_ops->decode_key(&event->key, decode); 652 kvm->events_ops->decode_key(kvm, &event->key, decode);
626 pr_info("%20s ", decode); 653 pr_info("%20s ", decode);
627 pr_info("%10llu ", (unsigned long long)ecount); 654 pr_info("%10llu ", (unsigned long long)ecount);
628 pr_info("%8.2f%% ", (double)ecount / total_count * 100); 655 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
629 pr_info("%8.2f%% ", (double)etime / total_time * 100); 656 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
630 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, 657 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
631 kvm_event_rel_stddev(vcpu, event)); 658 kvm_event_rel_stddev(vcpu, event));
632 pr_info("\n"); 659 pr_info("\n");
633 } 660 }
634 661
635 pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n", 662 pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
636 (unsigned long long)total_count, total_time / 1e3); 663 (unsigned long long)kvm->total_count, kvm->total_time / 1e3);
637} 664}
638 665
639static int process_sample_event(struct perf_tool *tool __maybe_unused, 666static int process_sample_event(struct perf_tool *tool,
640 union perf_event *event, 667 union perf_event *event,
641 struct perf_sample *sample, 668 struct perf_sample *sample,
642 struct perf_evsel *evsel, 669 struct perf_evsel *evsel,
643 struct machine *machine) 670 struct machine *machine)
644{ 671{
645 struct thread *thread = machine__findnew_thread(machine, sample->tid); 672 struct thread *thread = machine__findnew_thread(machine, sample->tid);
673 struct perf_kvm *kvm = container_of(tool, struct perf_kvm, tool);
646 674
647 if (thread == NULL) { 675 if (thread == NULL) {
648 pr_debug("problem processing %d event, skipping it.\n", 676 pr_debug("problem processing %d event, skipping it.\n",
@@ -650,18 +678,12 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
650 return -1; 678 return -1;
651 } 679 }
652 680
653 if (!handle_kvm_event(thread, evsel, sample)) 681 if (!handle_kvm_event(kvm, thread, evsel, sample))
654 return -1; 682 return -1;
655 683
656 return 0; 684 return 0;
657} 685}
658 686
659static struct perf_tool eops = {
660 .sample = process_sample_event,
661 .comm = perf_event__process_comm,
662 .ordered_samples = true,
663};
664
665static int get_cpu_isa(struct perf_session *session) 687static int get_cpu_isa(struct perf_session *session)
666{ 688{
667 char *cpuid = session->header.env.cpuid; 689 char *cpuid = session->header.env.cpuid;
@@ -679,34 +701,43 @@ static int get_cpu_isa(struct perf_session *session)
679 return isa; 701 return isa;
680} 702}
681 703
682static const char *file_name; 704static int read_events(struct perf_kvm *kvm)
683
684static int read_events(void)
685{ 705{
686 struct perf_session *kvm_session;
687 int ret; 706 int ret;
688 707
689 kvm_session = perf_session__new(file_name, O_RDONLY, 0, false, &eops); 708 struct perf_tool eops = {
690 if (!kvm_session) { 709 .sample = process_sample_event,
710 .comm = perf_event__process_comm,
711 .ordered_samples = true,
712 };
713
714 kvm->tool = eops;
715 kvm->session = perf_session__new(kvm->file_name, O_RDONLY, 0, false,
716 &kvm->tool);
717 if (!kvm->session) {
691 pr_err("Initializing perf session failed\n"); 718 pr_err("Initializing perf session failed\n");
692 return -EINVAL; 719 return -EINVAL;
693 } 720 }
694 721
695 if (!perf_session__has_traces(kvm_session, "kvm record")) 722 if (!perf_session__has_traces(kvm->session, "kvm record"))
696 return -EINVAL; 723 return -EINVAL;
697 724
698 /* 725 /*
699 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not 726 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
700 * traced in the old kernel. 727 * traced in the old kernel.
701 */ 728 */
702 ret = get_cpu_isa(kvm_session); 729 ret = get_cpu_isa(kvm->session);
703 730
704 if (ret < 0) 731 if (ret < 0)
705 return ret; 732 return ret;
706 733
707 cpu_isa = ret; 734 if (ret == 1) {
735 kvm->exit_reasons = vmx_exit_reasons;
736 kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
737 kvm->exit_reasons_isa = "VMX";
738 }
708 739
709 return perf_session__process_events(kvm_session, &eops); 740 return perf_session__process_events(kvm->session, &kvm->tool);
710} 741}
711 742
712static bool verify_vcpu(int vcpu) 743static bool verify_vcpu(int vcpu)
@@ -719,28 +750,30 @@ static bool verify_vcpu(int vcpu)
719 return true; 750 return true;
720} 751}
721 752
722static int kvm_events_report_vcpu(int vcpu) 753static int kvm_events_report_vcpu(struct perf_kvm *kvm)
723{ 754{
724 int ret = -EINVAL; 755 int ret = -EINVAL;
756 int vcpu = kvm->trace_vcpu;
725 757
726 if (!verify_vcpu(vcpu)) 758 if (!verify_vcpu(vcpu))
727 goto exit; 759 goto exit;
728 760
729 if (!select_key()) 761 if (!select_key(kvm))
730 goto exit; 762 goto exit;
731 763
732 if (!register_kvm_events_ops()) 764 if (!register_kvm_events_ops(kvm))
733 goto exit; 765 goto exit;
734 766
735 init_kvm_event_record(); 767 init_kvm_event_record(kvm);
736 setup_pager(); 768 setup_pager();
737 769
738 ret = read_events(); 770 ret = read_events(kvm);
739 if (ret) 771 if (ret)
740 goto exit; 772 goto exit;
741 773
742 sort_result(vcpu); 774 sort_result(kvm);
743 print_result(vcpu); 775 print_result(kvm);
776
744exit: 777exit:
745 return ret; 778 return ret;
746} 779}
@@ -765,7 +798,7 @@ static const char * const record_args[] = {
765 _p; \ 798 _p; \
766 }) 799 })
767 800
768static int kvm_events_record(int argc, const char **argv) 801static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
769{ 802{
770 unsigned int rec_argc, i, j; 803 unsigned int rec_argc, i, j;
771 const char **rec_argv; 804 const char **rec_argv;
@@ -780,7 +813,7 @@ static int kvm_events_record(int argc, const char **argv)
780 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]); 813 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
781 814
782 rec_argv[i++] = STRDUP_FAIL_EXIT("-o"); 815 rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
783 rec_argv[i++] = STRDUP_FAIL_EXIT(file_name); 816 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);
784 817
785 for (j = 1; j < (unsigned int)argc; j++, i++) 818 for (j = 1; j < (unsigned int)argc; j++, i++)
786 rec_argv[i] = argv[j]; 819 rec_argv[i] = argv[j];
@@ -788,24 +821,24 @@ static int kvm_events_record(int argc, const char **argv)
788 return cmd_record(i, rec_argv, NULL); 821 return cmd_record(i, rec_argv, NULL);
789} 822}
790 823
791static const char * const kvm_events_report_usage[] = { 824static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv)
792 "perf kvm stat report [<options>]", 825{
793 NULL 826 const struct option kvm_events_report_options[] = {
794}; 827 OPT_STRING(0, "event", &kvm->report_event, "report event",
828 "event for reporting: vmexit, mmio, ioport"),
829 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
830 "vcpu id to report"),
831 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
832 "key for sorting: sample(sort by samples number)"
833 " time (sort by avg time)"),
834 OPT_END()
835 };
795 836
796static const struct option kvm_events_report_options[] = { 837 const char * const kvm_events_report_usage[] = {
797 OPT_STRING(0, "event", &report_event, "report event", 838 "perf kvm stat report [<options>]",
798 "event for reporting: vmexit, mmio, ioport"), 839 NULL
799 OPT_INTEGER(0, "vcpu", &trace_vcpu, 840 };
800 "vcpu id to report"),
801 OPT_STRING('k', "key", &sort_key, "sort-key",
802 "key for sorting: sample(sort by samples number)"
803 " time (sort by avg time)"),
804 OPT_END()
805};
806 841
807static int kvm_events_report(int argc, const char **argv)
808{
809 symbol__init(); 842 symbol__init();
810 843
811 if (argc) { 844 if (argc) {
@@ -817,7 +850,7 @@ static int kvm_events_report(int argc, const char **argv)
817 kvm_events_report_options); 850 kvm_events_report_options);
818 } 851 }
819 852
820 return kvm_events_report_vcpu(trace_vcpu); 853 return kvm_events_report_vcpu(kvm);
821} 854}
822 855
823static void print_kvm_stat_usage(void) 856static void print_kvm_stat_usage(void)
@@ -831,7 +864,7 @@ static void print_kvm_stat_usage(void)
831 printf("\nOtherwise, it is the alias of 'perf stat':\n"); 864 printf("\nOtherwise, it is the alias of 'perf stat':\n");
832} 865}
833 866
834static int kvm_cmd_stat(int argc, const char **argv) 867static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv)
835{ 868{
836 if (argc == 1) { 869 if (argc == 1) {
837 print_kvm_stat_usage(); 870 print_kvm_stat_usage();
@@ -839,44 +872,16 @@ static int kvm_cmd_stat(int argc, const char **argv)
839 } 872 }
840 873
841 if (!strncmp(argv[1], "rec", 3)) 874 if (!strncmp(argv[1], "rec", 3))
842 return kvm_events_record(argc - 1, argv + 1); 875 return kvm_events_record(kvm, argc - 1, argv + 1);
843 876
844 if (!strncmp(argv[1], "rep", 3)) 877 if (!strncmp(argv[1], "rep", 3))
845 return kvm_events_report(argc - 1 , argv + 1); 878 return kvm_events_report(kvm, argc - 1 , argv + 1);
846 879
847perf_stat: 880perf_stat:
848 return cmd_stat(argc, argv, NULL); 881 return cmd_stat(argc, argv, NULL);
849} 882}
850 883
851static char name_buffer[256]; 884static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
852
853static const char * const kvm_usage[] = {
854 "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
855 NULL
856};
857
858static const struct option kvm_options[] = {
859 OPT_STRING('i', "input", &file_name, "file",
860 "Input file name"),
861 OPT_STRING('o', "output", &file_name, "file",
862 "Output file name"),
863 OPT_BOOLEAN(0, "guest", &perf_guest,
864 "Collect guest os data"),
865 OPT_BOOLEAN(0, "host", &perf_host,
866 "Collect host os data"),
867 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
868 "guest mount directory under which every guest os"
869 " instance has a subdir"),
870 OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
871 "file", "file saving guest os vmlinux"),
872 OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
873 "file", "file saving guest os /proc/kallsyms"),
874 OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
875 "file", "file saving guest os /proc/modules"),
876 OPT_END()
877};
878
879static int __cmd_record(int argc, const char **argv)
880{ 885{
881 int rec_argc, i = 0, j; 886 int rec_argc, i = 0, j;
882 const char **rec_argv; 887 const char **rec_argv;
@@ -885,7 +890,7 @@ static int __cmd_record(int argc, const char **argv)
885 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 890 rec_argv = calloc(rec_argc + 1, sizeof(char *));
886 rec_argv[i++] = strdup("record"); 891 rec_argv[i++] = strdup("record");
887 rec_argv[i++] = strdup("-o"); 892 rec_argv[i++] = strdup("-o");
888 rec_argv[i++] = strdup(file_name); 893 rec_argv[i++] = strdup(kvm->file_name);
889 for (j = 1; j < argc; j++, i++) 894 for (j = 1; j < argc; j++, i++)
890 rec_argv[i] = argv[j]; 895 rec_argv[i] = argv[j];
891 896
@@ -894,7 +899,7 @@ static int __cmd_record(int argc, const char **argv)
894 return cmd_record(i, rec_argv, NULL); 899 return cmd_record(i, rec_argv, NULL);
895} 900}
896 901
897static int __cmd_report(int argc, const char **argv) 902static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
898{ 903{
899 int rec_argc, i = 0, j; 904 int rec_argc, i = 0, j;
900 const char **rec_argv; 905 const char **rec_argv;
@@ -903,7 +908,7 @@ static int __cmd_report(int argc, const char **argv)
903 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 908 rec_argv = calloc(rec_argc + 1, sizeof(char *));
904 rec_argv[i++] = strdup("report"); 909 rec_argv[i++] = strdup("report");
905 rec_argv[i++] = strdup("-i"); 910 rec_argv[i++] = strdup("-i");
906 rec_argv[i++] = strdup(file_name); 911 rec_argv[i++] = strdup(kvm->file_name);
907 for (j = 1; j < argc; j++, i++) 912 for (j = 1; j < argc; j++, i++)
908 rec_argv[i] = argv[j]; 913 rec_argv[i] = argv[j];
909 914
@@ -912,7 +917,7 @@ static int __cmd_report(int argc, const char **argv)
912 return cmd_report(i, rec_argv, NULL); 917 return cmd_report(i, rec_argv, NULL);
913} 918}
914 919
915static int __cmd_buildid_list(int argc, const char **argv) 920static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
916{ 921{
917 int rec_argc, i = 0, j; 922 int rec_argc, i = 0, j;
918 const char **rec_argv; 923 const char **rec_argv;
@@ -921,7 +926,7 @@ static int __cmd_buildid_list(int argc, const char **argv)
921 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 926 rec_argv = calloc(rec_argc + 1, sizeof(char *));
922 rec_argv[i++] = strdup("buildid-list"); 927 rec_argv[i++] = strdup("buildid-list");
923 rec_argv[i++] = strdup("-i"); 928 rec_argv[i++] = strdup("-i");
924 rec_argv[i++] = strdup(file_name); 929 rec_argv[i++] = strdup(kvm->file_name);
925 for (j = 1; j < argc; j++, i++) 930 for (j = 1; j < argc; j++, i++)
926 rec_argv[i] = argv[j]; 931 rec_argv[i] = argv[j];
927 932
@@ -932,6 +937,43 @@ static int __cmd_buildid_list(int argc, const char **argv)
932 937
933int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused) 938int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
934{ 939{
940 struct perf_kvm kvm = {
941 .trace_vcpu = -1,
942 .report_event = "vmexit",
943 .sort_key = "sample",
944
945 .exit_reasons = svm_exit_reasons,
946 .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
947 .exit_reasons_isa = "SVM",
948 };
949
950 const struct option kvm_options[] = {
951 OPT_STRING('i', "input", &kvm.file_name, "file",
952 "Input file name"),
953 OPT_STRING('o', "output", &kvm.file_name, "file",
954 "Output file name"),
955 OPT_BOOLEAN(0, "guest", &perf_guest,
956 "Collect guest os data"),
957 OPT_BOOLEAN(0, "host", &perf_host,
958 "Collect host os data"),
959 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
960 "guest mount directory under which every guest os"
961 " instance has a subdir"),
962 OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
963 "file", "file saving guest os vmlinux"),
964 OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
965 "file", "file saving guest os /proc/kallsyms"),
966 OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
967 "file", "file saving guest os /proc/modules"),
968 OPT_END()
969 };
970
971
972 const char * const kvm_usage[] = {
973 "perf kvm [<options>] {top|record|report|diff|buildid-list|stat}",
974 NULL
975 };
976
935 perf_host = 0; 977 perf_host = 0;
936 perf_guest = 1; 978 perf_guest = 1;
937 979
@@ -943,28 +985,32 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
943 if (!perf_host) 985 if (!perf_host)
944 perf_guest = 1; 986 perf_guest = 1;
945 987
946 if (!file_name) { 988 if (!kvm.file_name) {
947 if (perf_host && !perf_guest) 989 if (perf_host && !perf_guest)
948 sprintf(name_buffer, "perf.data.host"); 990 kvm.file_name = strdup("perf.data.host");
949 else if (!perf_host && perf_guest) 991 else if (!perf_host && perf_guest)
950 sprintf(name_buffer, "perf.data.guest"); 992 kvm.file_name = strdup("perf.data.guest");
951 else 993 else
952 sprintf(name_buffer, "perf.data.kvm"); 994 kvm.file_name = strdup("perf.data.kvm");
953 file_name = name_buffer; 995
996 if (!kvm.file_name) {
997 pr_err("Failed to allocate memory for filename\n");
998 return -ENOMEM;
999 }
954 } 1000 }
955 1001
956 if (!strncmp(argv[0], "rec", 3)) 1002 if (!strncmp(argv[0], "rec", 3))
957 return __cmd_record(argc, argv); 1003 return __cmd_record(&kvm, argc, argv);
958 else if (!strncmp(argv[0], "rep", 3)) 1004 else if (!strncmp(argv[0], "rep", 3))
959 return __cmd_report(argc, argv); 1005 return __cmd_report(&kvm, argc, argv);
960 else if (!strncmp(argv[0], "diff", 4)) 1006 else if (!strncmp(argv[0], "diff", 4))
961 return cmd_diff(argc, argv, NULL); 1007 return cmd_diff(argc, argv, NULL);
962 else if (!strncmp(argv[0], "top", 3)) 1008 else if (!strncmp(argv[0], "top", 3))
963 return cmd_top(argc, argv, NULL); 1009 return cmd_top(argc, argv, NULL);
964 else if (!strncmp(argv[0], "buildid-list", 12)) 1010 else if (!strncmp(argv[0], "buildid-list", 12))
965 return __cmd_buildid_list(argc, argv); 1011 return __cmd_buildid_list(&kvm, argc, argv);
966 else if (!strncmp(argv[0], "stat", 4)) 1012 else if (!strncmp(argv[0], "stat", 4))
967 return kvm_cmd_stat(argc, argv); 1013 return kvm_cmd_stat(&kvm, argc, argv);
968 else 1014 else
969 usage_with_options(kvm_usage, kvm_options); 1015 usage_with_options(kvm_usage, kvm_options);
970 1016
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 7d6e09949880..6f5f328157aa 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -823,12 +823,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
823 return 0; 823 return 0;
824} 824}
825 825
826static struct perf_tool eops = {
827 .sample = process_sample_event,
828 .comm = perf_event__process_comm,
829 .ordered_samples = true,
830};
831
832static const struct perf_evsel_str_handler lock_tracepoints[] = { 826static const struct perf_evsel_str_handler lock_tracepoints[] = {
833 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */ 827 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */
834 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ 828 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
@@ -838,6 +832,11 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
838 832
839static int read_events(void) 833static int read_events(void)
840{ 834{
835 struct perf_tool eops = {
836 .sample = process_sample_event,
837 .comm = perf_event__process_comm,
838 .ordered_samples = true,
839 };
841 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); 840 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
842 if (!session) { 841 if (!session) {
843 pr_err("Initializing perf session failed\n"); 842 pr_err("Initializing perf session failed\n");
@@ -878,53 +877,11 @@ static int __cmd_report(void)
878 return 0; 877 return 0;
879} 878}
880 879
881static const char * const report_usage[] = {
882 "perf lock report [<options>]",
883 NULL
884};
885
886static const struct option report_options[] = {
887 OPT_STRING('k', "key", &sort_key, "acquired",
888 "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
889 /* TODO: type */
890 OPT_END()
891};
892
893static const char * const info_usage[] = {
894 "perf lock info [<options>]",
895 NULL
896};
897
898static const struct option info_options[] = {
899 OPT_BOOLEAN('t', "threads", &info_threads,
900 "dump thread list in perf.data"),
901 OPT_BOOLEAN('m', "map", &info_map,
902 "map of lock instances (address:name table)"),
903 OPT_END()
904};
905
906static const char * const lock_usage[] = {
907 "perf lock [<options>] {record|report|script|info}",
908 NULL
909};
910
911static const struct option lock_options[] = {
912 OPT_STRING('i', "input", &input_name, "file", "input file name"),
913 OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
914 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
915 OPT_END()
916};
917
918static const char *record_args[] = {
919 "record",
920 "-R",
921 "-f",
922 "-m", "1024",
923 "-c", "1",
924};
925
926static int __cmd_record(int argc, const char **argv) 880static int __cmd_record(int argc, const char **argv)
927{ 881{
882 const char *record_args[] = {
883 "record", "-R", "-f", "-m", "1024", "-c", "1",
884 };
928 unsigned int rec_argc, i, j; 885 unsigned int rec_argc, i, j;
929 const char **rec_argv; 886 const char **rec_argv;
930 887
@@ -963,6 +920,37 @@ static int __cmd_record(int argc, const char **argv)
963 920
964int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) 921int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
965{ 922{
923 const struct option info_options[] = {
924 OPT_BOOLEAN('t', "threads", &info_threads,
925 "dump thread list in perf.data"),
926 OPT_BOOLEAN('m', "map", &info_map,
927 "map of lock instances (address:name table)"),
928 OPT_END()
929 };
930 const struct option lock_options[] = {
931 OPT_STRING('i', "input", &input_name, "file", "input file name"),
932 OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
933 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
934 OPT_END()
935 };
936 const struct option report_options[] = {
937 OPT_STRING('k', "key", &sort_key, "acquired",
938 "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
939 /* TODO: type */
940 OPT_END()
941 };
942 const char * const info_usage[] = {
943 "perf lock info [<options>]",
944 NULL
945 };
946 const char * const lock_usage[] = {
947 "perf lock [<options>] {record|report|script|info}",
948 NULL
949 };
950 const char * const report_usage[] = {
951 "perf lock report [<options>]",
952 NULL
953 };
966 unsigned int i; 954 unsigned int i;
967 int rc = 0; 955 int rc = 0;
968 956
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 118aa8946573..de38a034b129 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -250,19 +250,20 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
250 return 0; 250 return 0;
251} 251}
252 252
253static const char * const probe_usage[] = { 253int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
254 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 254{
255 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 255 const char * const probe_usage[] = {
256 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 256 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
257 "perf probe --list", 257 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
258 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
259 "perf probe --list",
258#ifdef DWARF_SUPPORT 260#ifdef DWARF_SUPPORT
259 "perf probe [<options>] --line 'LINEDESC'", 261 "perf probe [<options>] --line 'LINEDESC'",
260 "perf probe [<options>] --vars 'PROBEPOINT'", 262 "perf probe [<options>] --vars 'PROBEPOINT'",
261#endif 263#endif
262 NULL 264 NULL
263}; 265};
264 266 const struct option options[] = {
265static const struct option options[] = {
266 OPT_INCR('v', "verbose", &verbose, 267 OPT_INCR('v', "verbose", &verbose,
267 "be more verbose (show parsed arguments, etc)"), 268 "be more verbose (show parsed arguments, etc)"),
268 OPT_BOOLEAN('l', "list", &params.list_events, 269 OPT_BOOLEAN('l', "list", &params.list_events,
@@ -325,10 +326,7 @@ static const struct option options[] = {
325 OPT_CALLBACK('x', "exec", NULL, "executable|path", 326 OPT_CALLBACK('x', "exec", NULL, "executable|path",
326 "target executable name or path", opt_set_target), 327 "target executable name or path", opt_set_target),
327 OPT_END() 328 OPT_END()
328}; 329 };
329
330int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
331{
332 int ret; 330 int ret;
333 331
334 argc = parse_options(argc, argv, options, probe_usage, 332 argc = parse_options(argc, argv, options, probe_usage,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f14cb5fdb91f..e9231659754d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,15 +31,6 @@
31#include <sched.h> 31#include <sched.h>
32#include <sys/mman.h> 32#include <sys/mman.h>
33 33
34#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
35
36#ifdef NO_LIBUNWIND_SUPPORT
37static char callchain_help[] = CALLCHAIN_HELP "[fp]";
38#else
39static unsigned long default_stack_dump_size = 8192;
40static char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
41#endif
42
43enum write_mode_t { 34enum write_mode_t {
44 WRITE_FORCE, 35 WRITE_FORCE,
45 WRITE_APPEND 36 WRITE_APPEND
@@ -800,7 +791,7 @@ error:
800 return ret; 791 return ret;
801} 792}
802 793
803#ifndef NO_LIBUNWIND_SUPPORT 794#ifdef LIBUNWIND_SUPPORT
804static int get_stack_size(char *str, unsigned long *_size) 795static int get_stack_size(char *str, unsigned long *_size)
805{ 796{
806 char *endptr; 797 char *endptr;
@@ -826,7 +817,7 @@ static int get_stack_size(char *str, unsigned long *_size)
826 max_size, str); 817 max_size, str);
827 return -1; 818 return -1;
828} 819}
829#endif /* !NO_LIBUNWIND_SUPPORT */ 820#endif /* LIBUNWIND_SUPPORT */
830 821
831static int 822static int
832parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg, 823parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
@@ -865,9 +856,11 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
865 "needed for -g fp\n"); 856 "needed for -g fp\n");
866 break; 857 break;
867 858
868#ifndef NO_LIBUNWIND_SUPPORT 859#ifdef LIBUNWIND_SUPPORT
869 /* Dwarf style */ 860 /* Dwarf style */
870 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 861 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
862 const unsigned long default_stack_dump_size = 8192;
863
871 ret = 0; 864 ret = 0;
872 rec->opts.call_graph = CALLCHAIN_DWARF; 865 rec->opts.call_graph = CALLCHAIN_DWARF;
873 rec->opts.stack_dump_size = default_stack_dump_size; 866 rec->opts.stack_dump_size = default_stack_dump_size;
@@ -883,7 +876,7 @@ parse_callchain_opt(const struct option *opt __maybe_unused, const char *arg,
883 if (!ret) 876 if (!ret)
884 pr_debug("callchain: stack dump size %d\n", 877 pr_debug("callchain: stack dump size %d\n",
885 rec->opts.stack_dump_size); 878 rec->opts.stack_dump_size);
886#endif /* !NO_LIBUNWIND_SUPPORT */ 879#endif /* LIBUNWIND_SUPPORT */
887 } else { 880 } else {
888 pr_err("callchain: Unknown -g option " 881 pr_err("callchain: Unknown -g option "
889 "value: %s\n", arg); 882 "value: %s\n", arg);
@@ -930,6 +923,14 @@ static struct perf_record record = {
930 .file_new = true, 923 .file_new = true,
931}; 924};
932 925
926#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
927
928#ifdef LIBUNWIND_SUPPORT
929static const char callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
930#else
931static const char callchain_help[] = CALLCHAIN_HELP "[fp]";
932#endif
933
933/* 934/*
934 * XXX Will stay a global variable till we fix builtin-script.c to stop messing 935 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
935 * with it and switch to use the library functions in perf_evlist that came 936 * with it and switch to use the library functions in perf_evlist that came
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 1da243dfbc3e..a61725d89d3e 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
320 const char *evname = perf_evsel__name(pos); 320 const char *evname = perf_evsel__name(pos);
321 321
322 hists__fprintf_nr_sample_events(hists, evname, stdout); 322 hists__fprintf_nr_sample_events(hists, evname, stdout);
323 hists__fprintf(hists, NULL, false, true, 0, 0, stdout); 323 hists__fprintf(hists, true, 0, 0, stdout);
324 fprintf(stdout, "\n\n"); 324 fprintf(stdout, "\n\n");
325 } 325 }
326 326
@@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
691 setup_browser(true); 691 setup_browser(true);
692 else { 692 else {
693 use_browser = 0; 693 use_browser = 0;
694 perf_hpp__init(false, false); 694 perf_hpp__init();
695 } 695 }
696 696
697 setup_sorting(report_usage, options); 697 setup_sorting(report_usage, options);
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 9b9e32eaa805..3488ead3b60c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1426,7 +1426,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1426 struct perf_evsel *evsel, 1426 struct perf_evsel *evsel,
1427 struct machine *machine) 1427 struct machine *machine)
1428{ 1428{
1429 struct thread *thread = machine__findnew_thread(machine, sample->pid); 1429 struct thread *thread = machine__findnew_thread(machine, sample->tid);
1430 int err = 0; 1430 int err = 0;
1431 1431
1432 if (thread == NULL) { 1432 if (thread == NULL) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 1be843aa1546..fb9625083a2e 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -24,7 +24,6 @@ static u64 last_timestamp;
24static u64 nr_unordered; 24static u64 nr_unordered;
25extern const struct option record_options[]; 25extern const struct option record_options[];
26static bool no_callchain; 26static bool no_callchain;
27static bool show_full_info;
28static bool system_wide; 27static bool system_wide;
29static const char *cpu_list; 28static const char *cpu_list;
30static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 29static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -473,8 +472,6 @@ static int cleanup_scripting(void)
473 return scripting_ops->stop_script(); 472 return scripting_ops->stop_script();
474} 473}
475 474
476static const char *input_name;
477
478static int process_sample_event(struct perf_tool *tool __maybe_unused, 475static int process_sample_event(struct perf_tool *tool __maybe_unused,
479 union perf_event *event, 476 union perf_event *event,
480 struct perf_sample *sample, 477 struct perf_sample *sample,
@@ -1156,20 +1153,40 @@ out:
1156 return n_args; 1153 return n_args;
1157} 1154}
1158 1155
1159static const char * const script_usage[] = { 1156static int have_cmd(int argc, const char **argv)
1160 "perf script [<options>]", 1157{
1161 "perf script [<options>] record <script> [<record-options>] <command>", 1158 char **__argv = malloc(sizeof(const char *) * argc);
1162 "perf script [<options>] report <script> [script-args]", 1159
1163 "perf script [<options>] <script> [<record-options>] <command>", 1160 if (!__argv) {
1164 "perf script [<options>] <top-script> [script-args]", 1161 pr_err("malloc failed\n");
1165 NULL 1162 return -1;
1166}; 1163 }
1164
1165 memcpy(__argv, argv, sizeof(const char *) * argc);
1166 argc = parse_options(argc, (const char **)__argv, record_options,
1167 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
1168 free(__argv);
1167 1169
1168static const struct option options[] = { 1170 system_wide = (argc == 0);
1171
1172 return 0;
1173}
1174
1175int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1176{
1177 bool show_full_info = false;
1178 const char *input_name = NULL;
1179 char *rec_script_path = NULL;
1180 char *rep_script_path = NULL;
1181 struct perf_session *session;
1182 char *script_path = NULL;
1183 const char **__argv;
1184 int i, j, err;
1185 const struct option options[] = {
1169 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1186 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1170 "dump raw trace in ASCII"), 1187 "dump raw trace in ASCII"),
1171 OPT_INCR('v', "verbose", &verbose, 1188 OPT_INCR('v', "verbose", &verbose,
1172 "be more verbose (show symbol address, etc)"), 1189 "be more verbose (show symbol address, etc)"),
1173 OPT_BOOLEAN('L', "Latency", &latency_format, 1190 OPT_BOOLEAN('L', "Latency", &latency_format,
1174 "show latency attributes (irqs/preemption disabled, etc)"), 1191 "show latency attributes (irqs/preemption disabled, etc)"),
1175 OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts", 1192 OPT_CALLBACK_NOOPT('l', "list", NULL, NULL, "list available scripts",
@@ -1179,8 +1196,7 @@ static const struct option options[] = {
1179 parse_scriptname), 1196 parse_scriptname),
1180 OPT_STRING('g', "gen-script", &generate_script_lang, "lang", 1197 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
1181 "generate perf-script.xx script in specified language"), 1198 "generate perf-script.xx script in specified language"),
1182 OPT_STRING('i', "input", &input_name, "file", 1199 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1183 "input file name"),
1184 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 1200 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
1185 "do various checks like samples ordering and lost events"), 1201 "do various checks like samples ordering and lost events"),
1186 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1202 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
@@ -1195,10 +1211,9 @@ static const struct option options[] = {
1195 "comma separated output fields prepend with 'type:'. " 1211 "comma separated output fields prepend with 'type:'. "
1196 "Valid types: hw,sw,trace,raw. " 1212 "Valid types: hw,sw,trace,raw. "
1197 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1213 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1198 "addr,symoff", 1214 "addr,symoff", parse_output_fields),
1199 parse_output_fields),
1200 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1215 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1201 "system-wide collection from all CPUs"), 1216 "system-wide collection from all CPUs"),
1202 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1217 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
1203 "only consider these symbols"), 1218 "only consider these symbols"),
1204 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 1219 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
@@ -1208,37 +1223,16 @@ static const struct option options[] = {
1208 "display extended information from perf.data file"), 1223 "display extended information from perf.data file"),
1209 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 1224 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
1210 "Show the path of [kernel.kallsyms]"), 1225 "Show the path of [kernel.kallsyms]"),
1211
1212 OPT_END() 1226 OPT_END()
1213}; 1227 };
1214 1228 const char * const script_usage[] = {
1215static int have_cmd(int argc, const char **argv) 1229 "perf script [<options>]",
1216{ 1230 "perf script [<options>] record <script> [<record-options>] <command>",
1217 char **__argv = malloc(sizeof(const char *) * argc); 1231 "perf script [<options>] report <script> [script-args]",
1218 1232 "perf script [<options>] <script> [<record-options>] <command>",
1219 if (!__argv) { 1233 "perf script [<options>] <top-script> [script-args]",
1220 pr_err("malloc failed\n"); 1234 NULL
1221 return -1; 1235 };
1222 }
1223
1224 memcpy(__argv, argv, sizeof(const char *) * argc);
1225 argc = parse_options(argc, (const char **)__argv, record_options,
1226 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
1227 free(__argv);
1228
1229 system_wide = (argc == 0);
1230
1231 return 0;
1232}
1233
1234int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1235{
1236 char *rec_script_path = NULL;
1237 char *rep_script_path = NULL;
1238 struct perf_session *session;
1239 char *script_path = NULL;
1240 const char **__argv;
1241 int i, j, err;
1242 1236
1243 setup_scripting(); 1237 setup_scripting();
1244 1238
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e8cd4d81b06e..93b9011fa3e2 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -64,122 +64,12 @@
64#define CNTR_NOT_SUPPORTED "<not supported>" 64#define CNTR_NOT_SUPPORTED "<not supported>"
65#define CNTR_NOT_COUNTED "<not counted>" 65#define CNTR_NOT_COUNTED "<not counted>"
66 66
67static struct perf_event_attr default_attrs[] = {
68
69 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
70 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES },
71 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS },
72 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS },
73
74 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES },
75 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
76 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
77 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS },
78 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
79 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES },
80
81};
82
83/*
84 * Detailed stats (-d), covering the L1 and last level data caches:
85 */
86static struct perf_event_attr detailed_attrs[] = {
87
88 { .type = PERF_TYPE_HW_CACHE,
89 .config =
90 PERF_COUNT_HW_CACHE_L1D << 0 |
91 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
92 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
93
94 { .type = PERF_TYPE_HW_CACHE,
95 .config =
96 PERF_COUNT_HW_CACHE_L1D << 0 |
97 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
98 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
99
100 { .type = PERF_TYPE_HW_CACHE,
101 .config =
102 PERF_COUNT_HW_CACHE_LL << 0 |
103 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
104 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
105
106 { .type = PERF_TYPE_HW_CACHE,
107 .config =
108 PERF_COUNT_HW_CACHE_LL << 0 |
109 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
110 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
111};
112
113/*
114 * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
115 */
116static struct perf_event_attr very_detailed_attrs[] = {
117
118 { .type = PERF_TYPE_HW_CACHE,
119 .config =
120 PERF_COUNT_HW_CACHE_L1I << 0 |
121 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
122 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
123
124 { .type = PERF_TYPE_HW_CACHE,
125 .config =
126 PERF_COUNT_HW_CACHE_L1I << 0 |
127 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
128 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
129
130 { .type = PERF_TYPE_HW_CACHE,
131 .config =
132 PERF_COUNT_HW_CACHE_DTLB << 0 |
133 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
134 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
135
136 { .type = PERF_TYPE_HW_CACHE,
137 .config =
138 PERF_COUNT_HW_CACHE_DTLB << 0 |
139 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
140 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
141
142 { .type = PERF_TYPE_HW_CACHE,
143 .config =
144 PERF_COUNT_HW_CACHE_ITLB << 0 |
145 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
146 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
147
148 { .type = PERF_TYPE_HW_CACHE,
149 .config =
150 PERF_COUNT_HW_CACHE_ITLB << 0 |
151 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
152 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
153
154};
155
156/*
157 * Very, very detailed stats (-d -d -d), adding prefetch events:
158 */
159static struct perf_event_attr very_very_detailed_attrs[] = {
160
161 { .type = PERF_TYPE_HW_CACHE,
162 .config =
163 PERF_COUNT_HW_CACHE_L1D << 0 |
164 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
165 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
166
167 { .type = PERF_TYPE_HW_CACHE,
168 .config =
169 PERF_COUNT_HW_CACHE_L1D << 0 |
170 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
171 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
172};
173
174
175
176static struct perf_evlist *evsel_list; 67static struct perf_evlist *evsel_list;
177 68
178static struct perf_target target = { 69static struct perf_target target = {
179 .uid = UINT_MAX, 70 .uid = UINT_MAX,
180}; 71};
181 72
182static int run_idx = 0;
183static int run_count = 1; 73static int run_count = 1;
184static bool no_inherit = false; 74static bool no_inherit = false;
185static bool scale = true; 75static bool scale = true;
@@ -187,15 +77,12 @@ static bool no_aggr = false;
187static pid_t child_pid = -1; 77static pid_t child_pid = -1;
188static bool null_run = false; 78static bool null_run = false;
189static int detailed_run = 0; 79static int detailed_run = 0;
190static bool sync_run = false;
191static bool big_num = true; 80static bool big_num = true;
192static int big_num_opt = -1; 81static int big_num_opt = -1;
193static const char *csv_sep = NULL; 82static const char *csv_sep = NULL;
194static bool csv_output = false; 83static bool csv_output = false;
195static bool group = false; 84static bool group = false;
196static const char *output_name = NULL;
197static FILE *output = NULL; 85static FILE *output = NULL;
198static int output_fd;
199 86
200static volatile int done = 0; 87static volatile int done = 0;
201 88
@@ -1028,11 +915,6 @@ static void sig_atexit(void)
1028 kill(getpid(), signr); 915 kill(getpid(), signr);
1029} 916}
1030 917
1031static const char * const stat_usage[] = {
1032 "perf stat [<options>] [<command>]",
1033 NULL
1034};
1035
1036static int stat__set_big_num(const struct option *opt __maybe_unused, 918static int stat__set_big_num(const struct option *opt __maybe_unused,
1037 const char *s __maybe_unused, int unset) 919 const char *s __maybe_unused, int unset)
1038{ 920{
@@ -1040,62 +922,119 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
1040 return 0; 922 return 0;
1041} 923}
1042 924
1043static bool append_file;
1044
1045static const struct option options[] = {
1046 OPT_CALLBACK('e', "event", &evsel_list, "event",
1047 "event selector. use 'perf list' to list available events",
1048 parse_events_option),
1049 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1050 "event filter", parse_filter),
1051 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1052 "child tasks do not inherit counters"),
1053 OPT_STRING('p', "pid", &target.pid, "pid",
1054 "stat events on existing process id"),
1055 OPT_STRING('t', "tid", &target.tid, "tid",
1056 "stat events on existing thread id"),
1057 OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
1058 "system-wide collection from all CPUs"),
1059 OPT_BOOLEAN('g', "group", &group,
1060 "put the counters into a counter group"),
1061 OPT_BOOLEAN('c', "scale", &scale,
1062 "scale/normalize counters"),
1063 OPT_INCR('v', "verbose", &verbose,
1064 "be more verbose (show counter open errors, etc)"),
1065 OPT_INTEGER('r', "repeat", &run_count,
1066 "repeat command and print average + stddev (max: 100)"),
1067 OPT_BOOLEAN('n', "null", &null_run,
1068 "null run - dont start any counters"),
1069 OPT_INCR('d', "detailed", &detailed_run,
1070 "detailed run - start a lot of events"),
1071 OPT_BOOLEAN('S', "sync", &sync_run,
1072 "call sync() before starting a run"),
1073 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1074 "print large numbers with thousands\' separators",
1075 stat__set_big_num),
1076 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
1077 "list of cpus to monitor in system-wide"),
1078 OPT_BOOLEAN('A', "no-aggr", &no_aggr,
1079 "disable CPU count aggregation"),
1080 OPT_STRING('x', "field-separator", &csv_sep, "separator",
1081 "print counts with custom separator"),
1082 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1083 "monitor event in cgroup name only",
1084 parse_cgroups),
1085 OPT_STRING('o', "output", &output_name, "file",
1086 "output file name"),
1087 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1088 OPT_INTEGER(0, "log-fd", &output_fd,
1089 "log output to fd, instead of stderr"),
1090 OPT_END()
1091};
1092
1093/* 925/*
1094 * Add default attributes, if there were no attributes specified or 926 * Add default attributes, if there were no attributes specified or
1095 * if -d/--detailed, -d -d or -d -d -d is used: 927 * if -d/--detailed, -d -d or -d -d -d is used:
1096 */ 928 */
1097static int add_default_attributes(void) 929static int add_default_attributes(void)
1098{ 930{
931 struct perf_event_attr default_attrs[] = {
932
933 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
934 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES },
935 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS },
936 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS },
937
938 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES },
939 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
940 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
941 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS },
942 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
943 { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES },
944
945};
946
947/*
948 * Detailed stats (-d), covering the L1 and last level data caches:
949 */
950 struct perf_event_attr detailed_attrs[] = {
951
952 { .type = PERF_TYPE_HW_CACHE,
953 .config =
954 PERF_COUNT_HW_CACHE_L1D << 0 |
955 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
956 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
957
958 { .type = PERF_TYPE_HW_CACHE,
959 .config =
960 PERF_COUNT_HW_CACHE_L1D << 0 |
961 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
962 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
963
964 { .type = PERF_TYPE_HW_CACHE,
965 .config =
966 PERF_COUNT_HW_CACHE_LL << 0 |
967 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
968 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
969
970 { .type = PERF_TYPE_HW_CACHE,
971 .config =
972 PERF_COUNT_HW_CACHE_LL << 0 |
973 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
974 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
975};
976
977/*
978 * Very detailed stats (-d -d), covering the instruction cache and the TLB caches:
979 */
980 struct perf_event_attr very_detailed_attrs[] = {
981
982 { .type = PERF_TYPE_HW_CACHE,
983 .config =
984 PERF_COUNT_HW_CACHE_L1I << 0 |
985 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
986 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
987
988 { .type = PERF_TYPE_HW_CACHE,
989 .config =
990 PERF_COUNT_HW_CACHE_L1I << 0 |
991 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
992 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
993
994 { .type = PERF_TYPE_HW_CACHE,
995 .config =
996 PERF_COUNT_HW_CACHE_DTLB << 0 |
997 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
998 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
999
1000 { .type = PERF_TYPE_HW_CACHE,
1001 .config =
1002 PERF_COUNT_HW_CACHE_DTLB << 0 |
1003 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1004 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1005
1006 { .type = PERF_TYPE_HW_CACHE,
1007 .config =
1008 PERF_COUNT_HW_CACHE_ITLB << 0 |
1009 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1010 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1011
1012 { .type = PERF_TYPE_HW_CACHE,
1013 .config =
1014 PERF_COUNT_HW_CACHE_ITLB << 0 |
1015 (PERF_COUNT_HW_CACHE_OP_READ << 8) |
1016 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1017
1018};
1019
1020/*
1021 * Very, very detailed stats (-d -d -d), adding prefetch events:
1022 */
1023 struct perf_event_attr very_very_detailed_attrs[] = {
1024
1025 { .type = PERF_TYPE_HW_CACHE,
1026 .config =
1027 PERF_COUNT_HW_CACHE_L1D << 0 |
1028 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
1029 (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) },
1030
1031 { .type = PERF_TYPE_HW_CACHE,
1032 .config =
1033 PERF_COUNT_HW_CACHE_L1D << 0 |
1034 (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) |
1035 (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) },
1036};
1037
1099 /* Set attrs if no event is selected and !null_run: */ 1038 /* Set attrs if no event is selected and !null_run: */
1100 if (null_run) 1039 if (null_run)
1101 return 0; 1040 return 0;
@@ -1130,8 +1069,59 @@ static int add_default_attributes(void)
1130 1069
1131int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) 1070int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1132{ 1071{
1072 bool append_file = false,
1073 sync_run = false;
1074 int output_fd = 0;
1075 const char *output_name = NULL;
1076 const struct option options[] = {
1077 OPT_CALLBACK('e', "event", &evsel_list, "event",
1078 "event selector. use 'perf list' to list available events",
1079 parse_events_option),
1080 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1081 "event filter", parse_filter),
1082 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1083 "child tasks do not inherit counters"),
1084 OPT_STRING('p', "pid", &target.pid, "pid",
1085 "stat events on existing process id"),
1086 OPT_STRING('t', "tid", &target.tid, "tid",
1087 "stat events on existing thread id"),
1088 OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
1089 "system-wide collection from all CPUs"),
1090 OPT_BOOLEAN('g', "group", &group,
1091 "put the counters into a counter group"),
1092 OPT_BOOLEAN('c', "scale", &scale, "scale/normalize counters"),
1093 OPT_INCR('v', "verbose", &verbose,
1094 "be more verbose (show counter open errors, etc)"),
1095 OPT_INTEGER('r', "repeat", &run_count,
1096 "repeat command and print average + stddev (max: 100)"),
1097 OPT_BOOLEAN('n', "null", &null_run,
1098 "null run - dont start any counters"),
1099 OPT_INCR('d', "detailed", &detailed_run,
1100 "detailed run - start a lot of events"),
1101 OPT_BOOLEAN('S', "sync", &sync_run,
1102 "call sync() before starting a run"),
1103 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1104 "print large numbers with thousands\' separators",
1105 stat__set_big_num),
1106 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
1107 "list of cpus to monitor in system-wide"),
1108 OPT_BOOLEAN('A', "no-aggr", &no_aggr, "disable CPU count aggregation"),
1109 OPT_STRING('x', "field-separator", &csv_sep, "separator",
1110 "print counts with custom separator"),
1111 OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
1112 "monitor event in cgroup name only", parse_cgroups),
1113 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1114 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1115 OPT_INTEGER(0, "log-fd", &output_fd,
1116 "log output to fd, instead of stderr"),
1117 OPT_END()
1118 };
1119 const char * const stat_usage[] = {
1120 "perf stat [<options>] [<command>]",
1121 NULL
1122 };
1133 struct perf_evsel *pos; 1123 struct perf_evsel *pos;
1134 int status = -ENOMEM; 1124 int status = -ENOMEM, run_idx;
1135 const char *mode; 1125 const char *mode;
1136 1126
1137 setlocale(LC_ALL, ""); 1127 setlocale(LC_ALL, "");
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index b1a8a3b841cc..f251b613b2f3 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -38,9 +38,6 @@
38#define PWR_EVENT_EXIT -1 38#define PWR_EVENT_EXIT -1
39 39
40 40
41static const char *input_name;
42static const char *output_name = "output.svg";
43
44static unsigned int numcpus; 41static unsigned int numcpus;
45static u64 min_freq; /* Lowest CPU frequency seen */ 42static u64 min_freq; /* Lowest CPU frequency seen */
46static u64 max_freq; /* Highest CPU frequency seen */ 43static u64 max_freq; /* Highest CPU frequency seen */
@@ -968,16 +965,15 @@ static void write_svg_file(const char *filename)
968 svg_close(); 965 svg_close();
969} 966}
970 967
971static struct perf_tool perf_timechart = { 968static int __cmd_timechart(const char *input_name, const char *output_name)
972 .comm = process_comm_event,
973 .fork = process_fork_event,
974 .exit = process_exit_event,
975 .sample = process_sample_event,
976 .ordered_samples = true,
977};
978
979static int __cmd_timechart(void)
980{ 969{
970 struct perf_tool perf_timechart = {
971 .comm = process_comm_event,
972 .fork = process_fork_event,
973 .exit = process_exit_event,
974 .sample = process_sample_event,
975 .ordered_samples = true,
976 };
981 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 977 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
982 0, false, &perf_timechart); 978 0, false, &perf_timechart);
983 int ret = -EINVAL; 979 int ret = -EINVAL;
@@ -1005,40 +1001,25 @@ out_delete:
1005 return ret; 1001 return ret;
1006} 1002}
1007 1003
1008static const char * const timechart_usage[] = {
1009 "perf timechart [<options>] {record}",
1010 NULL
1011};
1012
1013#ifdef SUPPORT_OLD_POWER_EVENTS
1014static const char * const record_old_args[] = {
1015 "record",
1016 "-a",
1017 "-R",
1018 "-f",
1019 "-c", "1",
1020 "-e", "power:power_start",
1021 "-e", "power:power_end",
1022 "-e", "power:power_frequency",
1023 "-e", "sched:sched_wakeup",
1024 "-e", "sched:sched_switch",
1025};
1026#endif
1027
1028static const char * const record_new_args[] = {
1029 "record",
1030 "-a",
1031 "-R",
1032 "-f",
1033 "-c", "1",
1034 "-e", "power:cpu_frequency",
1035 "-e", "power:cpu_idle",
1036 "-e", "sched:sched_wakeup",
1037 "-e", "sched:sched_switch",
1038};
1039
1040static int __cmd_record(int argc, const char **argv) 1004static int __cmd_record(int argc, const char **argv)
1041{ 1005{
1006#ifdef SUPPORT_OLD_POWER_EVENTS
1007 const char * const record_old_args[] = {
1008 "record", "-a", "-R", "-f", "-c", "1",
1009 "-e", "power:power_start",
1010 "-e", "power:power_end",
1011 "-e", "power:power_frequency",
1012 "-e", "sched:sched_wakeup",
1013 "-e", "sched:sched_switch",
1014 };
1015#endif
1016 const char * const record_new_args[] = {
1017 "record", "-a", "-R", "-f", "-c", "1",
1018 "-e", "power:cpu_frequency",
1019 "-e", "power:cpu_idle",
1020 "-e", "sched:sched_wakeup",
1021 "-e", "sched:sched_switch",
1022 };
1042 unsigned int rec_argc, i, j; 1023 unsigned int rec_argc, i, j;
1043 const char **rec_argv; 1024 const char **rec_argv;
1044 const char * const *record_args = record_new_args; 1025 const char * const *record_args = record_new_args;
@@ -1077,27 +1058,28 @@ parse_process(const struct option *opt __maybe_unused, const char *arg,
1077 return 0; 1058 return 0;
1078} 1059}
1079 1060
1080static const struct option options[] = { 1061int cmd_timechart(int argc, const char **argv,
1081 OPT_STRING('i', "input", &input_name, "file", 1062 const char *prefix __maybe_unused)
1082 "input file name"), 1063{
1083 OPT_STRING('o', "output", &output_name, "file", 1064 const char *input_name;
1084 "output file name"), 1065 const char *output_name = "output.svg";
1085 OPT_INTEGER('w', "width", &svg_page_width, 1066 const struct option options[] = {
1086 "page width"), 1067 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1087 OPT_BOOLEAN('P', "power-only", &power_only, 1068 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1088 "output power data only"), 1069 OPT_INTEGER('w', "width", &svg_page_width, "page width"),
1070 OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
1089 OPT_CALLBACK('p', "process", NULL, "process", 1071 OPT_CALLBACK('p', "process", NULL, "process",
1090 "process selector. Pass a pid or process name.", 1072 "process selector. Pass a pid or process name.",
1091 parse_process), 1073 parse_process),
1092 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1074 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1093 "Look for files with symbols relative to this directory"), 1075 "Look for files with symbols relative to this directory"),
1094 OPT_END() 1076 OPT_END()
1095}; 1077 };
1096 1078 const char * const timechart_usage[] = {
1079 "perf timechart [<options>] {record}",
1080 NULL
1081 };
1097 1082
1098int cmd_timechart(int argc, const char **argv,
1099 const char *prefix __maybe_unused)
1100{
1101 argc = parse_options(argc, argv, options, timechart_usage, 1083 argc = parse_options(argc, argv, options, timechart_usage,
1102 PARSE_OPT_STOP_AT_NON_OPTION); 1084 PARSE_OPT_STOP_AT_NON_OPTION);
1103 1085
@@ -1110,5 +1092,5 @@ int cmd_timechart(int argc, const char **argv,
1110 1092
1111 setup_pager(); 1093 setup_pager();
1112 1094
1113 return __cmd_timechart(); 1095 return __cmd_timechart(input_name, output_name);
1114} 1096}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e434a16bb5ac..ff6db8086805 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -316,7 +316,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
316 hists__output_recalc_col_len(&top->sym_evsel->hists, 316 hists__output_recalc_col_len(&top->sym_evsel->hists,
317 top->winsize.ws_row - 3); 317 top->winsize.ws_row - 3);
318 putchar('\n'); 318 putchar('\n');
319 hists__fprintf(&top->sym_evsel->hists, NULL, false, false, 319 hists__fprintf(&top->sym_evsel->hists, false,
320 top->winsize.ws_row - 4 - printed, win_width, stdout); 320 top->winsize.ws_row - 4 - printed, win_width, stdout);
321} 321}
322 322
@@ -1159,11 +1159,6 @@ setup:
1159 return 0; 1159 return 0;
1160} 1160}
1161 1161
1162static const char * const top_usage[] = {
1163 "perf top [<options>]",
1164 NULL
1165};
1166
1167int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1162int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1168{ 1163{
1169 struct perf_evsel *pos; 1164 struct perf_evsel *pos;
@@ -1250,6 +1245,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1250 OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"), 1245 OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
1251 OPT_END() 1246 OPT_END()
1252 }; 1247 };
1248 const char * const top_usage[] = {
1249 "perf top [<options>]",
1250 NULL
1251 };
1253 1252
1254 top.evlist = perf_evlist__new(NULL, NULL); 1253 top.evlist = perf_evlist__new(NULL, NULL);
1255 if (top.evlist == NULL) 1254 if (top.evlist == NULL)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 8f113dab8bf1..7aaee39f6774 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -56,6 +56,10 @@ static int trace__read_syscall_info(struct trace *trace, int id)
56{ 56{
57 char tp_name[128]; 57 char tp_name[128];
58 struct syscall *sc; 58 struct syscall *sc;
59 const char *name = audit_syscall_to_name(id, trace->audit_machine);
60
61 if (name == NULL)
62 return -1;
59 63
60 if (id > trace->syscalls.max) { 64 if (id > trace->syscalls.max) {
61 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); 65 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
@@ -75,11 +79,8 @@ static int trace__read_syscall_info(struct trace *trace, int id)
75 } 79 }
76 80
77 sc = trace->syscalls.table + id; 81 sc = trace->syscalls.table + id;
78 sc->name = audit_syscall_to_name(id, trace->audit_machine); 82 sc->name = name;
79 if (sc->name == NULL) 83 sc->fmt = syscall_fmt__find(sc->name);
80 return -1;
81
82 sc->fmt = syscall_fmt__find(sc->name);
83 84
84 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); 85 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
85 sc->tp_format = event_format__new("syscalls", tp_name); 86 sc->tp_format = event_format__new("syscalls", tp_name);
@@ -114,10 +115,85 @@ static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FIL
114 return printed; 115 return printed;
115} 116}
116 117
118typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
119 struct perf_sample *sample);
120
121static struct syscall *trace__syscall_info(struct trace *trace,
122 struct perf_evsel *evsel,
123 struct perf_sample *sample)
124{
125 int id = perf_evsel__intval(evsel, sample, "id");
126
127 if (id < 0) {
128 printf("Invalid syscall %d id, skipping...\n", id);
129 return NULL;
130 }
131
132 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
133 trace__read_syscall_info(trace, id))
134 goto out_cant_read;
135
136 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
137 goto out_cant_read;
138
139 return &trace->syscalls.table[id];
140
141out_cant_read:
142 printf("Problems reading syscall %d information\n", id);
143 return NULL;
144}
145
146static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
147 struct perf_sample *sample)
148{
149 void *args;
150 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
151
152 if (sc == NULL)
153 return -1;
154
155 args = perf_evsel__rawptr(evsel, sample, "args");
156 if (args == NULL) {
157 printf("Problems reading syscall arguments\n");
158 return -1;
159 }
160
161 printf("%s(", sc->name);
162 syscall__fprintf_args(sc, args, stdout);
163
164 return 0;
165}
166
167static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
168 struct perf_sample *sample)
169{
170 int ret;
171 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
172
173 if (sc == NULL)
174 return -1;
175
176 ret = perf_evsel__intval(evsel, sample, "ret");
177
178 if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
179 char bf[256];
180 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
181 *e = audit_errno_to_name(-ret);
182
183 printf(") = -1 %s %s", e, emsg);
184 } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
185 printf(") = 0 Timeout");
186 else
187 printf(") = %d", ret);
188
189 putchar('\n');
190 return 0;
191}
192
117static int trace__run(struct trace *trace) 193static int trace__run(struct trace *trace)
118{ 194{
119 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); 195 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
120 struct perf_evsel *evsel, *evsel_enter, *evsel_exit; 196 struct perf_evsel *evsel;
121 int err = -1, i, nr_events = 0, before; 197 int err = -1, i, nr_events = 0, before;
122 198
123 if (evlist == NULL) { 199 if (evlist == NULL) {
@@ -125,22 +201,12 @@ static int trace__run(struct trace *trace)
125 goto out; 201 goto out;
126 } 202 }
127 203
128 evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0); 204 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
129 if (evsel_enter == NULL) { 205 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"); 206 printf("Couldn't read the raw_syscalls tracepoints information!\n");
131 goto out_delete_evlist; 207 goto out_delete_evlist;
132 } 208 }
133 209
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;
140 }
141
142 perf_evlist__add(evlist, evsel_exit);
143
144 err = perf_evlist__create_maps(evlist, &trace->opts.target); 210 err = perf_evlist__create_maps(evlist, &trace->opts.target);
145 if (err < 0) { 211 if (err < 0) {
146 printf("Problems parsing the target to trace, check your options!\n"); 212 printf("Problems parsing the target to trace, check your options!\n");
@@ -170,9 +236,8 @@ again:
170 236
171 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 237 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
172 const u32 type = event->header.type; 238 const u32 type = event->header.type;
173 struct syscall *sc; 239 tracepoint_handler handler;
174 struct perf_sample sample; 240 struct perf_sample sample;
175 int id;
176 241
177 ++nr_events; 242 ++nr_events;
178 243
@@ -200,45 +265,18 @@ again:
200 continue; 265 continue;
201 } 266 }
202 267
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) 268 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
219 printf("%d ", sample.tid); 269 printf("%d ", sample.tid);
220 270
221 if (evsel == evsel_enter) { 271 if (sample.raw_data == NULL) {
222 void *args = perf_evsel__rawptr(evsel, &sample, "args"); 272 printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
223 273 perf_evsel__name(evsel), sample.tid,
224 printf("%s(", sc->name); 274 sample.cpu, sample.raw_size);
225 syscall__fprintf_args(sc, args, stdout); 275 continue;
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 } 276 }
277
278 handler = evsel->handler.func;
279 handler(trace, evsel, &sample);
242 } 280 }
243 } 281 }
244 282
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/perf.h b/tools/perf/perf.h
index a89cbbb61801..c50985eaec41 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -57,7 +57,7 @@ void get_term_dimensions(struct winsize *ws);
57#endif 57#endif
58 58
59#ifdef __sparc__ 59#ifdef __sparc__
60#include "../../arch/sparc/include/asm/unistd.h" 60#include "../../arch/sparc/include/uapi/asm/unistd.h"
61#define rmb() asm volatile("":::"memory") 61#define rmb() asm volatile("":::"memory")
62#define cpu_relax() asm volatile("":::"memory") 62#define cpu_relax() asm volatile("":::"memory")
63#define CPUINFO_PROC "cpu" 63#define CPUINFO_PROC "cpu"
@@ -112,7 +112,7 @@ void get_term_dimensions(struct winsize *ws);
112#include <sys/types.h> 112#include <sys/types.h>
113#include <sys/syscall.h> 113#include <sys/syscall.h>
114 114
115#include "../../include/linux/perf_event.h" 115#include "../../include/uapi/linux/perf_event.h"
116#include "util/types.h" 116#include "util/types.h"
117#include <stdbool.h> 117#include <stdbool.h>
118 118
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a21f40bebbac..ef2f93ca7496 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -569,7 +569,8 @@ static int hist_browser__show_callchain(struct hist_browser *browser,
569static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ 569static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \
570 struct hist_entry *he) \ 570 struct hist_entry *he) \
571{ \ 571{ \
572 double percent = 100.0 * he->_field / hpp->total_period; \ 572 struct hists *hists = he->hists; \
573 double percent = 100.0 * he->stat._field / hists->stats.total_period; \
573 *(double *)hpp->ptr = percent; \ 574 *(double *)hpp->ptr = percent; \
574 return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \ 575 return scnprintf(hpp->buf, hpp->size, "%6.2f%%", percent); \
575} 576}
@@ -584,7 +585,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
584 585
585void hist_browser__init_hpp(void) 586void hist_browser__init_hpp(void)
586{ 587{
587 perf_hpp__init(false, false); 588 perf_hpp__init();
588 589
589 perf_hpp__format[PERF_HPP__OVERHEAD].color = 590 perf_hpp__format[PERF_HPP__OVERHEAD].color =
590 hist_browser__hpp_color_overhead; 591 hist_browser__hpp_color_overhead;
@@ -609,6 +610,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
609 char folded_sign = ' '; 610 char folded_sign = ' ';
610 bool current_entry = ui_browser__is_current_entry(&browser->b, row); 611 bool current_entry = ui_browser__is_current_entry(&browser->b, row);
611 off_t row_offset = entry->row_offset; 612 off_t row_offset = entry->row_offset;
613 bool first = true;
612 614
613 if (current_entry) { 615 if (current_entry) {
614 browser->he_selection = entry; 616 browser->he_selection = entry;
@@ -624,7 +626,6 @@ static int hist_browser__show_entry(struct hist_browser *browser,
624 struct perf_hpp hpp = { 626 struct perf_hpp hpp = {
625 .buf = s, 627 .buf = s,
626 .size = sizeof(s), 628 .size = sizeof(s),
627 .total_period = browser->hists->stats.total_period,
628 }; 629 };
629 630
630 ui_browser__gotorc(&browser->b, row, 0); 631 ui_browser__gotorc(&browser->b, row, 0);
@@ -633,10 +634,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
633 if (!perf_hpp__format[i].cond) 634 if (!perf_hpp__format[i].cond)
634 continue; 635 continue;
635 636
636 if (i) { 637 if (!first) {
637 slsmg_printf(" "); 638 slsmg_printf(" ");
638 width -= 2; 639 width -= 2;
639 } 640 }
641 first = false;
640 642
641 if (perf_hpp__format[i].color) { 643 if (perf_hpp__format[i].color) {
642 hpp.ptr = &percent; 644 hpp.ptr = &percent;
@@ -645,7 +647,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
645 647
646 ui_browser__set_percent_color(&browser->b, percent, current_entry); 648 ui_browser__set_percent_color(&browser->b, percent, current_entry);
647 649
648 if (i == 0 && symbol_conf.use_callchain) { 650 if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) {
649 slsmg_printf("%c ", folded_sign); 651 slsmg_printf("%c ", folded_sign);
650 width -= 2; 652 width -= 2;
651 } 653 }
@@ -982,7 +984,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
982 folded_sign = hist_entry__folded(he); 984 folded_sign = hist_entry__folded(he);
983 985
984 hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists); 986 hist_entry__sort_snprintf(he, s, sizeof(s), browser->hists);
985 percent = (he->period * 100.0) / browser->hists->stats.total_period; 987 percent = (he->stat.period * 100.0) / browser->hists->stats.total_period;
986 988
987 if (symbol_conf.use_callchain) 989 if (symbol_conf.use_callchain)
988 printed += fprintf(fp, "%c ", folded_sign); 990 printed += fprintf(fp, "%c ", folded_sign);
@@ -990,10 +992,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
990 printed += fprintf(fp, " %5.2f%%", percent); 992 printed += fprintf(fp, " %5.2f%%", percent);
991 993
992 if (symbol_conf.show_nr_samples) 994 if (symbol_conf.show_nr_samples)
993 printed += fprintf(fp, " %11u", he->nr_events); 995 printed += fprintf(fp, " %11u", he->stat.nr_events);
994 996
995 if (symbol_conf.show_total_period) 997 if (symbol_conf.show_total_period)
996 printed += fprintf(fp, " %12" PRIu64, he->period); 998 printed += fprintf(fp, " %12" PRIu64, he->stat.period);
997 999
998 printed += fprintf(fp, "%s\n", rtrim(s)); 1000 printed += fprintf(fp, "%s\n", rtrim(s));
999 1001
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 7ff99ec1d95e..4125c6284114 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -49,7 +49,8 @@ static const char *perf_gtk__get_percent_color(double percent)
49static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ 49static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \
50 struct hist_entry *he) \ 50 struct hist_entry *he) \
51{ \ 51{ \
52 double percent = 100.0 * he->_field / hpp->total_period; \ 52 struct hists *hists = he->hists; \
53 double percent = 100.0 * he->stat._field / hists->stats.total_period; \
53 const char *markup; \ 54 const char *markup; \
54 int ret = 0; \ 55 int ret = 0; \
55 \ 56 \
@@ -73,7 +74,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us)
73 74
74void perf_gtk__init_hpp(void) 75void perf_gtk__init_hpp(void)
75{ 76{
76 perf_hpp__init(false, false); 77 perf_hpp__init();
77 78
78 perf_hpp__format[PERF_HPP__OVERHEAD].color = 79 perf_hpp__format[PERF_HPP__OVERHEAD].color =
79 perf_gtk__hpp_color_overhead; 80 perf_gtk__hpp_color_overhead;
@@ -102,7 +103,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
102 struct perf_hpp hpp = { 103 struct perf_hpp hpp = {
103 .buf = s, 104 .buf = s,
104 .size = sizeof(s), 105 .size = sizeof(s),
105 .total_period = hists->stats.total_period,
106 }; 106 };
107 107
108 nr_cols = 0; 108 nr_cols = 0;
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index 8aada5b3c04c..ccb046aac98b 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -116,7 +116,7 @@ struct perf_error_ops perf_gtk_eops = {
116 * FIXME: Functions below should be implemented properly. 116 * FIXME: Functions below should be implemented properly.
117 * For now, just add stubs for NO_NEWT=1 build. 117 * For now, just add stubs for NO_NEWT=1 build.
118 */ 118 */
119#ifdef NO_NEWT_SUPPORT 119#ifndef NEWT_SUPPORT
120void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused, 120void ui_progress__update(u64 curr __maybe_unused, u64 total __maybe_unused,
121 const char *title __maybe_unused) 121 const char *title __maybe_unused)
122{ 122{
diff --git a/tools/perf/ui/helpline.h b/tools/perf/ui/helpline.h
index 2b667ee454c3..baa28a4d16b9 100644
--- a/tools/perf/ui/helpline.h
+++ b/tools/perf/ui/helpline.h
@@ -23,25 +23,25 @@ void ui_helpline__puts(const char *msg);
23 23
24extern char ui_helpline__current[512]; 24extern char ui_helpline__current[512];
25 25
26#ifdef NO_NEWT_SUPPORT 26#ifdef NEWT_SUPPORT
27extern char ui_helpline__last_msg[];
28int ui_helpline__show_help(const char *format, va_list ap);
29#else
27static inline int ui_helpline__show_help(const char *format __maybe_unused, 30static inline int ui_helpline__show_help(const char *format __maybe_unused,
28 va_list ap __maybe_unused) 31 va_list ap __maybe_unused)
29{ 32{
30 return 0; 33 return 0;
31} 34}
32#else 35#endif /* NEWT_SUPPORT */
33extern char ui_helpline__last_msg[];
34int ui_helpline__show_help(const char *format, va_list ap);
35#endif /* NO_NEWT_SUPPORT */
36 36
37#ifdef NO_GTK2_SUPPORT 37#ifdef GTK2_SUPPORT
38int perf_gtk__show_helpline(const char *format, va_list ap);
39#else
38static inline int perf_gtk__show_helpline(const char *format __maybe_unused, 40static inline int perf_gtk__show_helpline(const char *format __maybe_unused,
39 va_list ap __maybe_unused) 41 va_list ap __maybe_unused)
40{ 42{
41 return 0; 43 return 0;
42} 44}
43#else 45#endif /* GTK2_SUPPORT */
44int perf_gtk__show_helpline(const char *format, va_list ap);
45#endif /* NO_GTK2_SUPPORT */
46 46
47#endif /* _PERF_UI_HELPLINE_H_ */ 47#endif /* _PERF_UI_HELPLINE_H_ */
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index e3f8cd46e7d7..f5a1e4f65263 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -8,9 +8,7 @@
8/* hist period print (hpp) functions */ 8/* hist period print (hpp) functions */
9static int hpp__header_overhead(struct perf_hpp *hpp) 9static int hpp__header_overhead(struct perf_hpp *hpp)
10{ 10{
11 const char *fmt = hpp->ptr ? "Baseline" : "Overhead"; 11 return scnprintf(hpp->buf, hpp->size, "Overhead");
12
13 return scnprintf(hpp->buf, hpp->size, fmt);
14} 12}
15 13
16static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) 14static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
@@ -20,38 +18,18 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
20 18
21static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) 19static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
22{ 20{
23 double percent = 100.0 * he->period / hpp->total_period; 21 struct hists *hists = he->hists;
24 22 double percent = 100.0 * he->stat.period / hists->stats.total_period;
25 if (hpp->ptr) {
26 struct hists *old_hists = hpp->ptr;
27 u64 total_period = old_hists->stats.total_period;
28 u64 base_period = he->pair ? he->pair->period : 0;
29
30 if (total_period)
31 percent = 100.0 * base_period / total_period;
32 else
33 percent = 0.0;
34 }
35 23
36 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); 24 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
37} 25}
38 26
39static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) 27static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
40{ 28{
41 double percent = 100.0 * he->period / hpp->total_period; 29 struct hists *hists = he->hists;
30 double percent = 100.0 * he->stat.period / hists->stats.total_period;
42 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; 31 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
43 32
44 if (hpp->ptr) {
45 struct hists *old_hists = hpp->ptr;
46 u64 total_period = old_hists->stats.total_period;
47 u64 base_period = he->pair ? he->pair->period : 0;
48
49 if (total_period)
50 percent = 100.0 * base_period / total_period;
51 else
52 percent = 0.0;
53 }
54
55 return scnprintf(hpp->buf, hpp->size, fmt, percent); 33 return scnprintf(hpp->buf, hpp->size, fmt, percent);
56} 34}
57 35
@@ -69,13 +47,16 @@ static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
69 47
70static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) 48static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
71{ 49{
72 double percent = 100.0 * he->period_sys / hpp->total_period; 50 struct hists *hists = he->hists;
51 double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
52
73 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); 53 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
74} 54}
75 55
76static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) 56static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
77{ 57{
78 double percent = 100.0 * he->period_sys / hpp->total_period; 58 struct hists *hists = he->hists;
59 double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
79 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; 60 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
80 61
81 return scnprintf(hpp->buf, hpp->size, fmt, percent); 62 return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -95,13 +76,16 @@ static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
95 76
96static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) 77static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
97{ 78{
98 double percent = 100.0 * he->period_us / hpp->total_period; 79 struct hists *hists = he->hists;
80 double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
81
99 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent); 82 return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
100} 83}
101 84
102static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he) 85static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
103{ 86{
104 double percent = 100.0 * he->period_us / hpp->total_period; 87 struct hists *hists = he->hists;
88 double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
105 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; 89 const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
106 90
107 return scnprintf(hpp->buf, hpp->size, fmt, percent); 91 return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -120,14 +104,17 @@ static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
120static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp, 104static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
121 struct hist_entry *he) 105 struct hist_entry *he)
122{ 106{
123 double percent = 100.0 * he->period_guest_sys / hpp->total_period; 107 struct hists *hists = he->hists;
108 double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
109
124 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); 110 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
125} 111}
126 112
127static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp, 113static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
128 struct hist_entry *he) 114 struct hist_entry *he)
129{ 115{
130 double percent = 100.0 * he->period_guest_sys / hpp->total_period; 116 struct hists *hists = he->hists;
117 double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
131 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; 118 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
132 119
133 return scnprintf(hpp->buf, hpp->size, fmt, percent); 120 return scnprintf(hpp->buf, hpp->size, fmt, percent);
@@ -146,19 +133,63 @@ static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
146static int hpp__color_overhead_guest_us(struct perf_hpp *hpp, 133static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
147 struct hist_entry *he) 134 struct hist_entry *he)
148{ 135{
149 double percent = 100.0 * he->period_guest_us / hpp->total_period; 136 struct hists *hists = he->hists;
137 double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
138
150 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent); 139 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
151} 140}
152 141
153static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, 142static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
154 struct hist_entry *he) 143 struct hist_entry *he)
155{ 144{
156 double percent = 100.0 * he->period_guest_us / hpp->total_period; 145 struct hists *hists = he->hists;
146 double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
157 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% "; 147 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
158 148
159 return scnprintf(hpp->buf, hpp->size, fmt, percent); 149 return scnprintf(hpp->buf, hpp->size, fmt, percent);
160} 150}
161 151
152static int hpp__header_baseline(struct perf_hpp *hpp)
153{
154 return scnprintf(hpp->buf, hpp->size, "Baseline");
155}
156
157static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
158{
159 return 8;
160}
161
162static double baseline_percent(struct hist_entry *he)
163{
164 struct hist_entry *pair = he->pair;
165 struct hists *pair_hists = pair ? pair->hists : NULL;
166 double percent = 0.0;
167
168 if (pair) {
169 u64 total_period = pair_hists->stats.total_period;
170 u64 base_period = pair->stat.period;
171
172 percent = 100.0 * base_period / total_period;
173 }
174
175 return percent;
176}
177
178static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
179{
180 double percent = baseline_percent(he);
181
182 return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
183}
184
185static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
186{
187 double percent = baseline_percent(he);
188 const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
189
190 return scnprintf(hpp->buf, hpp->size, fmt, percent);
191}
192
162static int hpp__header_samples(struct perf_hpp *hpp) 193static int hpp__header_samples(struct perf_hpp *hpp)
163{ 194{
164 const char *fmt = symbol_conf.field_sep ? "%s" : "%11s"; 195 const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
@@ -175,7 +206,7 @@ static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
175{ 206{
176 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64; 207 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
177 208
178 return scnprintf(hpp->buf, hpp->size, fmt, he->nr_events); 209 return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
179} 210}
180 211
181static int hpp__header_period(struct perf_hpp *hpp) 212static int hpp__header_period(struct perf_hpp *hpp)
@@ -194,7 +225,7 @@ static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
194{ 225{
195 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; 226 const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
196 227
197 return scnprintf(hpp->buf, hpp->size, fmt, he->period); 228 return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
198} 229}
199 230
200static int hpp__header_delta(struct perf_hpp *hpp) 231static int hpp__header_delta(struct perf_hpp *hpp)
@@ -211,20 +242,22 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
211 242
212static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) 243static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
213{ 244{
214 struct hists *pair_hists = hpp->ptr; 245 struct hist_entry *pair = he->pair;
246 struct hists *pair_hists = pair ? pair->hists : NULL;
247 struct hists *hists = he->hists;
215 u64 old_total, new_total; 248 u64 old_total, new_total;
216 double old_percent = 0, new_percent = 0; 249 double old_percent = 0, new_percent = 0;
217 double diff; 250 double diff;
218 const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; 251 const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
219 char buf[32] = " "; 252 char buf[32] = " ";
220 253
221 old_total = pair_hists->stats.total_period; 254 old_total = pair_hists ? pair_hists->stats.total_period : 0;
222 if (old_total > 0 && he->pair) 255 if (old_total > 0 && pair)
223 old_percent = 100.0 * he->pair->period / old_total; 256 old_percent = 100.0 * pair->stat.period / old_total;
224 257
225 new_total = hpp->total_period; 258 new_total = hists->stats.total_period;
226 if (new_total > 0) 259 if (new_total > 0)
227 new_percent = 100.0 * he->period / new_total; 260 new_percent = 100.0 * he->stat.period / new_total;
228 261
229 diff = new_percent - old_percent; 262 diff = new_percent - old_percent;
230 if (fabs(diff) >= 0.01) 263 if (fabs(diff) >= 0.01)
@@ -244,13 +277,15 @@ static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
244} 277}
245 278
246static int hpp__entry_displ(struct perf_hpp *hpp, 279static int hpp__entry_displ(struct perf_hpp *hpp,
247 struct hist_entry *he __maybe_unused) 280 struct hist_entry *he)
248{ 281{
282 struct hist_entry *pair = he->pair;
283 long displacement = pair ? pair->position - he->position : 0;
249 const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; 284 const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
250 char buf[32] = " "; 285 char buf[32] = " ";
251 286
252 if (hpp->displacement) 287 if (displacement)
253 scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement); 288 scnprintf(buf, sizeof(buf), "%+4ld", displacement);
254 289
255 return scnprintf(hpp->buf, hpp->size, fmt, buf); 290 return scnprintf(hpp->buf, hpp->size, fmt, buf);
256} 291}
@@ -267,6 +302,7 @@ static int hpp__entry_displ(struct perf_hpp *hpp,
267 .entry = hpp__entry_ ## _name 302 .entry = hpp__entry_ ## _name
268 303
269struct perf_hpp_fmt perf_hpp__format[] = { 304struct perf_hpp_fmt perf_hpp__format[] = {
305 { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
270 { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, 306 { .cond = true, HPP__COLOR_PRINT_FNS(overhead) },
271 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, 307 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
272 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, 308 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
@@ -281,7 +317,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
281#undef HPP__COLOR_PRINT_FNS 317#undef HPP__COLOR_PRINT_FNS
282#undef HPP__PRINT_FNS 318#undef HPP__PRINT_FNS
283 319
284void perf_hpp__init(bool need_pair, bool show_displacement) 320void perf_hpp__init(void)
285{ 321{
286 if (symbol_conf.show_cpu_utilization) { 322 if (symbol_conf.show_cpu_utilization) {
287 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; 323 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
@@ -298,13 +334,12 @@ void perf_hpp__init(bool need_pair, bool show_displacement)
298 334
299 if (symbol_conf.show_total_period) 335 if (symbol_conf.show_total_period)
300 perf_hpp__format[PERF_HPP__PERIOD].cond = true; 336 perf_hpp__format[PERF_HPP__PERIOD].cond = true;
337}
301 338
302 if (need_pair) { 339void perf_hpp__column_enable(unsigned col, bool enable)
303 perf_hpp__format[PERF_HPP__DELTA].cond = true; 340{
304 341 BUG_ON(col >= PERF_HPP__MAX_INDEX);
305 if (show_displacement) 342 perf_hpp__format[col].cond = enable;
306 perf_hpp__format[PERF_HPP__DISPL].cond = true;
307 }
308} 343}
309 344
310static inline void advance_hpp(struct perf_hpp *hpp, int inc) 345static inline void advance_hpp(struct perf_hpp *hpp, int inc)
@@ -319,6 +354,7 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
319 const char *sep = symbol_conf.field_sep; 354 const char *sep = symbol_conf.field_sep;
320 char *start = hpp->buf; 355 char *start = hpp->buf;
321 int i, ret; 356 int i, ret;
357 bool first = true;
322 358
323 if (symbol_conf.exclude_other && !he->parent) 359 if (symbol_conf.exclude_other && !he->parent)
324 return 0; 360 return 0;
@@ -327,9 +363,10 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
327 if (!perf_hpp__format[i].cond) 363 if (!perf_hpp__format[i].cond)
328 continue; 364 continue;
329 365
330 if (!sep || i > 0) { 366 if (!sep || !first) {
331 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); 367 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
332 advance_hpp(hpp, ret); 368 advance_hpp(hpp, ret);
369 first = false;
333 } 370 }
334 371
335 if (color && perf_hpp__format[i].color) 372 if (color && perf_hpp__format[i].color)
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index bd7d460f844c..ebb4cc107876 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -30,7 +30,7 @@ void setup_browser(bool fallback_to_pager)
30 if (fallback_to_pager) 30 if (fallback_to_pager)
31 setup_pager(); 31 setup_pager();
32 32
33 perf_hpp__init(false, false); 33 perf_hpp__init();
34 break; 34 break;
35 } 35 }
36} 36}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 882461a42830..fbd4e32d0743 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -271,7 +271,7 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
271{ 271{
272 switch (callchain_param.mode) { 272 switch (callchain_param.mode) {
273 case CHAIN_GRAPH_REL: 273 case CHAIN_GRAPH_REL:
274 return callchain__fprintf_graph(fp, &he->sorted_chain, he->period, 274 return callchain__fprintf_graph(fp, &he->sorted_chain, he->stat.period,
275 left_margin); 275 left_margin);
276 break; 276 break;
277 case CHAIN_GRAPH_ABS: 277 case CHAIN_GRAPH_ABS:
@@ -292,9 +292,10 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
292 292
293static size_t hist_entry__callchain_fprintf(struct hist_entry *he, 293static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
294 struct hists *hists, 294 struct hists *hists,
295 u64 total_period, FILE *fp) 295 FILE *fp)
296{ 296{
297 int left_margin = 0; 297 int left_margin = 0;
298 u64 total_period = hists->stats.total_period;
298 299
299 if (sort__first_dimension == SORT_COMM) { 300 if (sort__first_dimension == SORT_COMM) {
300 struct sort_entry *se = list_first_entry(&hist_entry__sort_list, 301 struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
@@ -307,17 +308,13 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he,
307} 308}
308 309
309static int hist_entry__fprintf(struct hist_entry *he, size_t size, 310static int hist_entry__fprintf(struct hist_entry *he, size_t size,
310 struct hists *hists, struct hists *pair_hists, 311 struct hists *hists, FILE *fp)
311 long displacement, u64 total_period, FILE *fp)
312{ 312{
313 char bf[512]; 313 char bf[512];
314 int ret; 314 int ret;
315 struct perf_hpp hpp = { 315 struct perf_hpp hpp = {
316 .buf = bf, 316 .buf = bf,
317 .size = size, 317 .size = size,
318 .total_period = total_period,
319 .displacement = displacement,
320 .ptr = pair_hists,
321 }; 318 };
322 bool color = !symbol_conf.field_sep; 319 bool color = !symbol_conf.field_sep;
323 320
@@ -330,22 +327,17 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
330 ret = fprintf(fp, "%s\n", bf); 327 ret = fprintf(fp, "%s\n", bf);
331 328
332 if (symbol_conf.use_callchain) 329 if (symbol_conf.use_callchain)
333 ret += hist_entry__callchain_fprintf(he, hists, 330 ret += hist_entry__callchain_fprintf(he, hists, fp);
334 total_period, fp);
335 331
336 return ret; 332 return ret;
337} 333}
338 334
339size_t hists__fprintf(struct hists *hists, struct hists *pair, 335size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
340 bool show_displacement, bool show_header, int max_rows,
341 int max_cols, FILE *fp) 336 int max_cols, FILE *fp)
342{ 337{
343 struct sort_entry *se; 338 struct sort_entry *se;
344 struct rb_node *nd; 339 struct rb_node *nd;
345 size_t ret = 0; 340 size_t ret = 0;
346 u64 total_period;
347 unsigned long position = 1;
348 long displacement = 0;
349 unsigned int width; 341 unsigned int width;
350 const char *sep = symbol_conf.field_sep; 342 const char *sep = symbol_conf.field_sep;
351 const char *col_width = symbol_conf.col_width_list_str; 343 const char *col_width = symbol_conf.col_width_list_str;
@@ -354,8 +346,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
354 struct perf_hpp dummy_hpp = { 346 struct perf_hpp dummy_hpp = {
355 .buf = bf, 347 .buf = bf,
356 .size = sizeof(bf), 348 .size = sizeof(bf),
357 .ptr = pair,
358 }; 349 };
350 bool first = true;
359 351
360 init_rem_hits(); 352 init_rem_hits();
361 353
@@ -367,8 +359,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
367 if (!perf_hpp__format[idx].cond) 359 if (!perf_hpp__format[idx].cond)
368 continue; 360 continue;
369 361
370 if (idx) 362 if (!first)
371 fprintf(fp, "%s", sep ?: " "); 363 fprintf(fp, "%s", sep ?: " ");
364 else
365 first = false;
372 366
373 perf_hpp__format[idx].header(&dummy_hpp); 367 perf_hpp__format[idx].header(&dummy_hpp);
374 fprintf(fp, "%s", bf); 368 fprintf(fp, "%s", bf);
@@ -403,6 +397,8 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
403 if (sep) 397 if (sep)
404 goto print_entries; 398 goto print_entries;
405 399
400 first = true;
401
406 fprintf(fp, "# "); 402 fprintf(fp, "# ");
407 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { 403 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
408 unsigned int i; 404 unsigned int i;
@@ -410,8 +406,10 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
410 if (!perf_hpp__format[idx].cond) 406 if (!perf_hpp__format[idx].cond)
411 continue; 407 continue;
412 408
413 if (idx) 409 if (!first)
414 fprintf(fp, "%s", sep ?: " "); 410 fprintf(fp, "%s", sep ?: " ");
411 else
412 first = false;
415 413
416 width = perf_hpp__format[idx].width(&dummy_hpp); 414 width = perf_hpp__format[idx].width(&dummy_hpp);
417 for (i = 0; i < width; i++) 415 for (i = 0; i < width; i++)
@@ -441,24 +439,13 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair,
441 goto out; 439 goto out;
442 440
443print_entries: 441print_entries:
444 total_period = hists->stats.total_period;
445
446 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 442 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
447 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 443 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
448 444
449 if (h->filtered) 445 if (h->filtered)
450 continue; 446 continue;
451 447
452 if (show_displacement) { 448 ret += hist_entry__fprintf(h, max_cols, hists, fp);
453 if (h->pair != NULL)
454 displacement = ((long)h->pair->position -
455 (long)position);
456 else
457 displacement = 0;
458 ++position;
459 }
460 ret += hist_entry__fprintf(h, max_cols, hists, pair, displacement,
461 total_period, fp);
462 449
463 if (max_rows && ++nr_rows >= max_rows) 450 if (max_rows && ++nr_rows >= max_rows)
464 goto out; 451 goto out;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 9b5b21e7b032..39242dcee8f2 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -138,7 +138,10 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
138 bool print_lines, bool full_paths, int min_pcnt, 138 bool print_lines, bool full_paths, int min_pcnt,
139 int max_lines); 139 int max_lines);
140 140
141#ifdef NO_NEWT_SUPPORT 141#ifdef NEWT_SUPPORT
142int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
143 void(*timer)(void *arg), void *arg, int delay_secs);
144#else
142static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, 145static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
143 struct map *map __maybe_unused, 146 struct map *map __maybe_unused,
144 int evidx __maybe_unused, 147 int evidx __maybe_unused,
@@ -148,9 +151,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
148{ 151{
149 return 0; 152 return 0;
150} 153}
151#else
152int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
153 void(*timer)(void *arg), void *arg, int delay_secs);
154#endif 154#endif
155 155
156extern const char *disassembler_style; 156extern const char *disassembler_style;
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index ab1769426541..2bd51370ad28 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -33,39 +33,41 @@ extern int pager_use_color;
33 33
34extern int use_browser; 34extern int use_browser;
35 35
36#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) 36#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
37static inline void setup_browser(bool fallback_to_pager)
38{
39 if (fallback_to_pager)
40 setup_pager();
41}
42static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
43#else
44void setup_browser(bool fallback_to_pager); 37void setup_browser(bool fallback_to_pager);
45void exit_browser(bool wait_for_ok); 38void exit_browser(bool wait_for_ok);
46 39
47#ifdef NO_NEWT_SUPPORT 40#ifdef NEWT_SUPPORT
41int ui__init(void);
42void ui__exit(bool wait_for_ok);
43#else
48static inline int ui__init(void) 44static inline int ui__init(void)
49{ 45{
50 return -1; 46 return -1;
51} 47}
52static inline void ui__exit(bool wait_for_ok __maybe_unused) {} 48static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
53#else
54int ui__init(void);
55void ui__exit(bool wait_for_ok);
56#endif 49#endif
57 50
58#ifdef NO_GTK2_SUPPORT 51#ifdef GTK2_SUPPORT
52int perf_gtk__init(void);
53void perf_gtk__exit(bool wait_for_ok);
54#else
59static inline int perf_gtk__init(void) 55static inline int perf_gtk__init(void)
60{ 56{
61 return -1; 57 return -1;
62} 58}
63static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {} 59static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
64#else
65int perf_gtk__init(void);
66void perf_gtk__exit(bool wait_for_ok);
67#endif 60#endif
68#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */ 61
62#else /* NEWT_SUPPORT || GTK2_SUPPORT */
63
64static inline void setup_browser(bool fallback_to_pager)
65{
66 if (fallback_to_pager)
67 setup_pager();
68}
69static inline void exit_browser(bool wait_for_ok __maybe_unused) {}
70#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
69 71
70char *alias_lookup(const char *alias); 72char *alias_lookup(const char *alias);
71int split_cmdline(char *cmdline, const char ***argv); 73int split_cmdline(char *cmdline, const char ***argv);
@@ -105,7 +107,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
105extern char *perf_pathdup(const char *fmt, ...) 107extern char *perf_pathdup(const char *fmt, ...)
106 __attribute__((format (printf, 1, 2))); 108 __attribute__((format (printf, 1, 2)));
107 109
108#ifdef NO_STRLCPY 110#ifndef HAVE_STRLCPY
109extern size_t strlcpy(char *dest, const char *src, size_t size); 111extern size_t strlcpy(char *dest, const char *src, size_t size);
110#endif 112#endif
111 113
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 66eb3828ceb5..03f830b48148 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -49,7 +49,7 @@ int dump_printf(const char *fmt, ...)
49 return ret; 49 return ret;
50} 50}
51 51
52#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) 52#if !defined(NEWT_SUPPORT) && !defined(GTK2_SUPPORT)
53int ui__warning(const char *format, ...) 53int ui__warning(const char *format, ...)
54{ 54{
55 va_list args; 55 va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index bb2e7d1007ab..dec98750b484 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -15,7 +15,14 @@ void trace_event(union perf_event *event);
15struct ui_progress; 15struct ui_progress;
16struct perf_error_ops; 16struct perf_error_ops;
17 17
18#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT) 18#if defined(NEWT_SUPPORT) || defined(GTK2_SUPPORT)
19
20#include "../ui/progress.h"
21int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
22#include "../ui/util.h"
23
24#else
25
19static inline void ui_progress__update(u64 curr __maybe_unused, 26static inline void ui_progress__update(u64 curr __maybe_unused,
20 u64 total __maybe_unused, 27 u64 total __maybe_unused,
21 const char *title __maybe_unused) {} 28 const char *title __maybe_unused) {}
@@ -34,13 +41,7 @@ perf_error__unregister(struct perf_error_ops *eops __maybe_unused)
34 return 0; 41 return 0;
35} 42}
36 43
37#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */ 44#endif /* NEWT_SUPPORT || GTK2_SUPPORT */
38
39#include "../ui/progress.h"
40int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
41#include "../ui/util.h"
42
43#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
44 45
45int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 46int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
46int ui__error_paranoid(void); 47int ui__error_paranoid(void);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index ae89686102f4..186b87730396 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -154,8 +154,8 @@ error:
154 return -ENOMEM; 154 return -ENOMEM;
155} 155}
156 156
157int perf_evlist__add_attrs(struct perf_evlist *evlist, 157static int perf_evlist__add_attrs(struct perf_evlist *evlist,
158 struct perf_event_attr *attrs, size_t nr_attrs) 158 struct perf_event_attr *attrs, size_t nr_attrs)
159{ 159{
160 struct perf_evsel *evsel, *n; 160 struct perf_evsel *evsel, *n;
161 LIST_HEAD(head); 161 LIST_HEAD(head);
@@ -189,60 +189,6 @@ int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
189 return perf_evlist__add_attrs(evlist, attrs, nr_attrs); 189 return perf_evlist__add_attrs(evlist, attrs, nr_attrs);
190} 190}
191 191
192static int trace_event__id(const char *evname)
193{
194 char *filename, *colon;
195 int err = -1, fd;
196
197 if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
198 return -1;
199
200 colon = strrchr(filename, ':');
201 if (colon != NULL)
202 *colon = '/';
203
204 fd = open(filename, O_RDONLY);
205 if (fd >= 0) {
206 char id[16];
207 if (read(fd, id, sizeof(id)) > 0)
208 err = atoi(id);
209 close(fd);
210 }
211
212 free(filename);
213 return err;
214}
215
216int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
217 const char *tracepoints[],
218 size_t nr_tracepoints)
219{
220 int err;
221 size_t i;
222 struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
223
224 if (attrs == NULL)
225 return -1;
226
227 for (i = 0; i < nr_tracepoints; i++) {
228 err = trace_event__id(tracepoints[i]);
229
230 if (err < 0)
231 goto out_free_attrs;
232
233 attrs[i].type = PERF_TYPE_TRACEPOINT;
234 attrs[i].config = err;
235 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
236 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
237 attrs[i].sample_period = 1;
238 }
239
240 err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
241out_free_attrs:
242 free(attrs);
243 return err;
244}
245
246struct perf_evsel * 192struct perf_evsel *
247perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id) 193perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
248{ 194{
@@ -257,32 +203,18 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
257 return NULL; 203 return NULL;
258} 204}
259 205
260int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, 206int perf_evlist__add_newtp(struct perf_evlist *evlist,
261 const struct perf_evsel_str_handler *assocs, 207 const char *sys, const char *name, void *handler)
262 size_t nr_assocs)
263{ 208{
264 struct perf_evsel *evsel; 209 struct perf_evsel *evsel;
265 int err;
266 size_t i;
267
268 for (i = 0; i < nr_assocs; i++) {
269 err = trace_event__id(assocs[i].name);
270 if (err < 0)
271 goto out;
272
273 evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
274 if (evsel == NULL)
275 continue;
276 210
277 err = -EEXIST; 211 evsel = perf_evsel__newtp(sys, name, evlist->nr_entries);
278 if (evsel->handler.func != NULL) 212 if (evsel == NULL)
279 goto out; 213 return -1;
280 evsel->handler.func = assocs[i].handler;
281 }
282 214
283 err = 0; 215 evsel->handler.func = handler;
284out: 216 perf_evlist__add(evlist, evsel);
285 return err; 217 return 0;
286} 218}
287 219
288void perf_evlist__disable(struct perf_evlist *evlist) 220void perf_evlist__disable(struct perf_evlist *evlist)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 3f1fb66be022..56003f779e60 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -51,26 +51,14 @@ void perf_evlist__delete(struct perf_evlist *evlist);
51 51
52void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 52void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
53int perf_evlist__add_default(struct perf_evlist *evlist); 53int perf_evlist__add_default(struct perf_evlist *evlist);
54int perf_evlist__add_attrs(struct perf_evlist *evlist,
55 struct perf_event_attr *attrs, size_t nr_attrs);
56int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 54int __perf_evlist__add_default_attrs(struct perf_evlist *evlist,
57 struct perf_event_attr *attrs, size_t nr_attrs); 55 struct perf_event_attr *attrs, size_t nr_attrs);
58int perf_evlist__add_tracepoints(struct perf_evlist *evlist, 56
59 const char *tracepoints[], size_t nr_tracepoints);
60int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
61 const struct perf_evsel_str_handler *assocs,
62 size_t nr_assocs);
63
64#define perf_evlist__add_attrs_array(evlist, array) \
65 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
66#define perf_evlist__add_default_attrs(evlist, array) \ 57#define perf_evlist__add_default_attrs(evlist, array) \
67 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) 58 __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array))
68 59
69#define perf_evlist__add_tracepoints_array(evlist, array) \ 60int perf_evlist__add_newtp(struct perf_evlist *evlist,
70 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array)) 61 const char *sys, const char *name, void *handler);
71
72#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
73 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
74 62
75int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); 63int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
76 64
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ffdd94e9c9c3..618d41140abd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -19,7 +19,7 @@
19#include "thread_map.h" 19#include "thread_map.h"
20#include "target.h" 20#include "target.h"
21#include "../../../include/linux/hw_breakpoint.h" 21#include "../../../include/linux/hw_breakpoint.h"
22#include "../../include/linux/perf_event.h" 22#include "../../../include/uapi/linux/perf_event.h"
23#include "perf_regs.h" 23#include "perf_regs.h"
24 24
25#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 25#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 3ead0d59c03d..6f94d6dea00f 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -3,7 +3,7 @@
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <stdbool.h> 5#include <stdbool.h>
6#include "../../../include/linux/perf_event.h" 6#include "../../../include/uapi/linux/perf_event.h"
7#include "types.h" 7#include "types.h"
8#include "xyarray.h" 8#include "xyarray.h"
9#include "cgroup.h" 9#include "cgroup.h"
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 389590c1ad21..3ac38031d534 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -22,7 +22,7 @@ do
22 }' "Documentation/perf-$cmd.txt" 22 }' "Documentation/perf-$cmd.txt"
23done 23done
24 24
25echo "#ifndef NO_LIBELF_SUPPORT" 25echo "#ifdef LIBELF_SUPPORT"
26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt | 26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt |
27sort | 27sort |
28while read cmd 28while read cmd
@@ -35,5 +35,5 @@ do
35 p 35 p
36 }' "Documentation/perf-$cmd.txt" 36 }' "Documentation/perf-$cmd.txt"
37done 37done
38echo "#endif /* NO_LIBELF_SUPPORT */" 38echo "#endif /* LIBELF_SUPPORT */"
39echo "};" 39echo "};"
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 99bdd3abce59..879d215cdac9 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_HEADER_H 1#ifndef __PERF_HEADER_H
2#define __PERF_HEADER_H 2#define __PERF_HEADER_H
3 3
4#include "../../../include/linux/perf_event.h" 4#include "../../../include/uapi/linux/perf_event.h"
5#include <sys/types.h> 5#include <sys/types.h>
6#include <stdbool.h> 6#include <stdbool.h>
7#include "types.h" 7#include "types.h"
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 236bc9d98ff2..277947a669b2 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -135,31 +135,47 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he,
135{ 135{
136 switch (cpumode) { 136 switch (cpumode) {
137 case PERF_RECORD_MISC_KERNEL: 137 case PERF_RECORD_MISC_KERNEL:
138 he->period_sys += period; 138 he->stat.period_sys += period;
139 break; 139 break;
140 case PERF_RECORD_MISC_USER: 140 case PERF_RECORD_MISC_USER:
141 he->period_us += period; 141 he->stat.period_us += period;
142 break; 142 break;
143 case PERF_RECORD_MISC_GUEST_KERNEL: 143 case PERF_RECORD_MISC_GUEST_KERNEL:
144 he->period_guest_sys += period; 144 he->stat.period_guest_sys += period;
145 break; 145 break;
146 case PERF_RECORD_MISC_GUEST_USER: 146 case PERF_RECORD_MISC_GUEST_USER:
147 he->period_guest_us += period; 147 he->stat.period_guest_us += period;
148 break; 148 break;
149 default: 149 default:
150 break; 150 break;
151 } 151 }
152} 152}
153 153
154static void he_stat__add_period(struct he_stat *he_stat, u64 period)
155{
156 he_stat->period += period;
157 he_stat->nr_events += 1;
158}
159
160static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
161{
162 dest->period += src->period;
163 dest->period_sys += src->period_sys;
164 dest->period_us += src->period_us;
165 dest->period_guest_sys += src->period_guest_sys;
166 dest->period_guest_us += src->period_guest_us;
167 dest->nr_events += src->nr_events;
168}
169
154static void hist_entry__decay(struct hist_entry *he) 170static void hist_entry__decay(struct hist_entry *he)
155{ 171{
156 he->period = (he->period * 7) / 8; 172 he->stat.period = (he->stat.period * 7) / 8;
157 he->nr_events = (he->nr_events * 7) / 8; 173 he->stat.nr_events = (he->stat.nr_events * 7) / 8;
158} 174}
159 175
160static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) 176static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
161{ 177{
162 u64 prev_period = he->period; 178 u64 prev_period = he->stat.period;
163 179
164 if (prev_period == 0) 180 if (prev_period == 0)
165 return true; 181 return true;
@@ -167,9 +183,9 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
167 hist_entry__decay(he); 183 hist_entry__decay(he);
168 184
169 if (!he->filtered) 185 if (!he->filtered)
170 hists->stats.total_period -= prev_period - he->period; 186 hists->stats.total_period -= prev_period - he->stat.period;
171 187
172 return he->period == 0; 188 return he->stat.period == 0;
173} 189}
174 190
175static void __hists__decay_entries(struct hists *hists, bool zap_user, 191static void __hists__decay_entries(struct hists *hists, bool zap_user,
@@ -223,7 +239,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
223 239
224 if (he != NULL) { 240 if (he != NULL) {
225 *he = *template; 241 *he = *template;
226 he->nr_events = 1; 242
227 if (he->ms.map) 243 if (he->ms.map)
228 he->ms.map->referenced = true; 244 he->ms.map->referenced = true;
229 if (symbol_conf.use_callchain) 245 if (symbol_conf.use_callchain)
@@ -238,7 +254,7 @@ static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
238 if (!h->filtered) { 254 if (!h->filtered) {
239 hists__calc_col_len(hists, h); 255 hists__calc_col_len(hists, h);
240 ++hists->nr_entries; 256 ++hists->nr_entries;
241 hists->stats.total_period += h->period; 257 hists->stats.total_period += h->stat.period;
242 } 258 }
243} 259}
244 260
@@ -270,8 +286,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
270 cmp = hist_entry__cmp(entry, he); 286 cmp = hist_entry__cmp(entry, he);
271 287
272 if (!cmp) { 288 if (!cmp) {
273 he->period += period; 289 he_stat__add_period(&he->stat, period);
274 ++he->nr_events;
275 290
276 /* If the map of an existing hist_entry has 291 /* If the map of an existing hist_entry has
277 * become out-of-date due to an exec() or 292 * become out-of-date due to an exec() or
@@ -321,10 +336,14 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self,
321 .cpu = al->cpu, 336 .cpu = al->cpu,
322 .ip = bi->to.addr, 337 .ip = bi->to.addr,
323 .level = al->level, 338 .level = al->level,
324 .period = period, 339 .stat = {
340 .period = period,
341 .nr_events = 1,
342 },
325 .parent = sym_parent, 343 .parent = sym_parent,
326 .filtered = symbol__parent_filter(sym_parent), 344 .filtered = symbol__parent_filter(sym_parent),
327 .branch_info = bi, 345 .branch_info = bi,
346 .hists = self,
328 }; 347 };
329 348
330 return add_hist_entry(self, &entry, al, period); 349 return add_hist_entry(self, &entry, al, period);
@@ -343,9 +362,13 @@ struct hist_entry *__hists__add_entry(struct hists *self,
343 .cpu = al->cpu, 362 .cpu = al->cpu,
344 .ip = al->addr, 363 .ip = al->addr,
345 .level = al->level, 364 .level = al->level,
346 .period = period, 365 .stat = {
366 .period = period,
367 .nr_events = 1,
368 },
347 .parent = sym_parent, 369 .parent = sym_parent,
348 .filtered = symbol__parent_filter(sym_parent), 370 .filtered = symbol__parent_filter(sym_parent),
371 .hists = self,
349 }; 372 };
350 373
351 return add_hist_entry(self, &entry, al, period); 374 return add_hist_entry(self, &entry, al, period);
@@ -410,12 +433,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
410 cmp = hist_entry__collapse(iter, he); 433 cmp = hist_entry__collapse(iter, he);
411 434
412 if (!cmp) { 435 if (!cmp) {
413 iter->period += he->period; 436 he_stat__add_stat(&iter->stat, &he->stat);
414 iter->period_sys += he->period_sys;
415 iter->period_us += he->period_us;
416 iter->period_guest_sys += he->period_guest_sys;
417 iter->period_guest_us += he->period_guest_us;
418 iter->nr_events += he->nr_events;
419 437
420 if (symbol_conf.use_callchain) { 438 if (symbol_conf.use_callchain) {
421 callchain_cursor_reset(&callchain_cursor); 439 callchain_cursor_reset(&callchain_cursor);
@@ -518,7 +536,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
518 parent = *p; 536 parent = *p;
519 iter = rb_entry(parent, struct hist_entry, rb_node); 537 iter = rb_entry(parent, struct hist_entry, rb_node);
520 538
521 if (he->period > iter->period) 539 if (he->stat.period > iter->stat.period)
522 p = &(*p)->rb_left; 540 p = &(*p)->rb_left;
523 else 541 else
524 p = &(*p)->rb_right; 542 p = &(*p)->rb_right;
@@ -579,8 +597,8 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
579 if (h->ms.unfolded) 597 if (h->ms.unfolded)
580 hists->nr_entries += h->nr_rows; 598 hists->nr_entries += h->nr_rows;
581 h->row_offset = 0; 599 h->row_offset = 0;
582 hists->stats.total_period += h->period; 600 hists->stats.total_period += h->stat.period;
583 hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events; 601 hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;
584 602
585 hists__calc_col_len(hists, h); 603 hists__calc_col_len(hists, h);
586} 604}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index f011ad4756e8..66cb31fe81d2 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -98,9 +98,8 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows);
98void hists__inc_nr_events(struct hists *self, u32 type); 98void hists__inc_nr_events(struct hists *self, u32 type);
99size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); 99size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
100 100
101size_t hists__fprintf(struct hists *self, struct hists *pair, 101size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
102 bool show_displacement, bool show_header, 102 int max_cols, FILE *fp);
103 int max_rows, int max_cols, FILE *fp);
104 103
105int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); 104int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
106int hist_entry__annotate(struct hist_entry *self, size_t privsize); 105int hist_entry__annotate(struct hist_entry *self, size_t privsize);
@@ -118,9 +117,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
118struct perf_hpp { 117struct perf_hpp {
119 char *buf; 118 char *buf;
120 size_t size; 119 size_t size;
121 u64 total_period;
122 const char *sep; 120 const char *sep;
123 long displacement;
124 void *ptr; 121 void *ptr;
125}; 122};
126 123
@@ -135,6 +132,7 @@ struct perf_hpp_fmt {
135extern struct perf_hpp_fmt perf_hpp__format[]; 132extern struct perf_hpp_fmt perf_hpp__format[];
136 133
137enum { 134enum {
135 PERF_HPP__BASELINE,
138 PERF_HPP__OVERHEAD, 136 PERF_HPP__OVERHEAD,
139 PERF_HPP__OVERHEAD_SYS, 137 PERF_HPP__OVERHEAD_SYS,
140 PERF_HPP__OVERHEAD_US, 138 PERF_HPP__OVERHEAD_US,
@@ -148,13 +146,22 @@ enum {
148 PERF_HPP__MAX_INDEX 146 PERF_HPP__MAX_INDEX
149}; 147};
150 148
151void perf_hpp__init(bool need_pair, bool show_displacement); 149void perf_hpp__init(void);
150void perf_hpp__column_enable(unsigned col, bool enable);
152int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, 151int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
153 bool color); 152 bool color);
154 153
155struct perf_evlist; 154struct perf_evlist;
156 155
157#ifdef NO_NEWT_SUPPORT 156#ifdef NEWT_SUPPORT
157#include "../ui/keysyms.h"
158int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
159 void(*timer)(void *arg), void *arg, int delay_secs);
160
161int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
162 void(*timer)(void *arg), void *arg,
163 int refresh);
164#else
158static inline 165static inline
159int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, 166int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
160 const char *help __maybe_unused, 167 const char *help __maybe_unused,
@@ -177,17 +184,13 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self
177} 184}
178#define K_LEFT -1 185#define K_LEFT -1
179#define K_RIGHT -2 186#define K_RIGHT -2
180#else 187#endif
181#include "../ui/keysyms.h"
182int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
183 void(*timer)(void *arg), void *arg, int delay_secs);
184 188
185int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 189#ifdef GTK2_SUPPORT
190int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
186 void(*timer)(void *arg), void *arg, 191 void(*timer)(void *arg), void *arg,
187 int refresh); 192 int refresh);
188#endif 193#else
189
190#ifdef NO_GTK2_SUPPORT
191static inline 194static inline
192int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, 195int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
193 const char *help __maybe_unused, 196 const char *help __maybe_unused,
@@ -197,11 +200,6 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
197{ 200{
198 return 0; 201 return 0;
199} 202}
200
201#else
202int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
203 void(*timer)(void *arg), void *arg,
204 int refresh);
205#endif 203#endif
206 204
207unsigned int hists__sort_list_width(struct hists *self); 205unsigned int hists__sort_list_width(struct hists *self);
diff --git a/tools/perf/util/include/asm/byteorder.h b/tools/perf/util/include/asm/byteorder.h
index b722abe3a626..2a9bdc066307 100644
--- a/tools/perf/util/include/asm/byteorder.h
+++ b/tools/perf/util/include/asm/byteorder.h
@@ -1,2 +1,2 @@
1#include <asm/types.h> 1#include <asm/types.h>
2#include "../../../../include/linux/swab.h" 2#include "../../../../include/uapi/linux/swab.h"
diff --git a/tools/perf/util/include/linux/const.h b/tools/perf/util/include/linux/const.h
index 1b476c9ae649..c10a35e1afb8 100644
--- a/tools/perf/util/include/linux/const.h
+++ b/tools/perf/util/include/linux/const.h
@@ -1 +1 @@
#include "../../../../include/linux/const.h" #include "../../../../include/uapi/linux/const.h"
diff --git a/tools/perf/util/include/linux/rbtree_augmented.h b/tools/perf/util/include/linux/rbtree_augmented.h
new file mode 100644
index 000000000000..9d6fcdf1788b
--- /dev/null
+++ b/tools/perf/util/include/linux/rbtree_augmented.h
@@ -0,0 +1,2 @@
1#include <stdbool.h>
2#include "../../../../include/linux/rbtree_augmented.h"
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-events-test.c b/tools/perf/util/parse-events-test.c
index 28c18d1d52c3..516ecd9ddd6e 100644
--- a/tools/perf/util/parse-events-test.c
+++ b/tools/perf/util/parse-events-test.c
@@ -513,7 +513,8 @@ static int test__group1(struct perf_evlist *evlist)
513 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); 513 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
514 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 514 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
515 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 515 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
516 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 516 /* use of precise requires exclude_guest */
517 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
517 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 518 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
518 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); 519 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
519 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 520 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -599,7 +600,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
599 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 600 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
600 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 601 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
601 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 602 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
602 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 603 /* use of precise requires exclude_guest */
604 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
603 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 605 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
604 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3); 606 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
605 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 607 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -662,7 +664,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
662 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user); 664 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
663 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel); 665 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
664 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 666 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
665 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 667 /* use of precise requires exclude_guest */
668 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
666 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 669 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
667 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1); 670 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
668 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 671 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
@@ -676,7 +679,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
676 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user); 679 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
677 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel); 680 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
678 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 681 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
679 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest); 682 /* use of precise requires exclude_guest */
683 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
680 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 684 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
681 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); 685 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
682 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 686 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index aed38e4b9dfa..75c7b0fca6d9 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -690,6 +690,9 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
690 eH = 0; 690 eH = 0;
691 } else if (*str == 'p') { 691 } else if (*str == 'p') {
692 precise++; 692 precise++;
693 /* use of precise requires exclude_guest */
694 if (!exclude_GH)
695 eG = 1;
693 } else 696 } else
694 break; 697 break;
695 698
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index c356e443448d..839230ceb18b 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -7,7 +7,7 @@
7#include <linux/list.h> 7#include <linux/list.h>
8#include <stdbool.h> 8#include <stdbool.h>
9#include "types.h" 9#include "types.h"
10#include "../../../include/linux/perf_event.h" 10#include "../../../include/uapi/linux/perf_event.h"
11#include "types.h" 11#include "types.h"
12 12
13struct list_head; 13struct list_head;
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 443fc116512b..2bc9e70df7e2 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -384,6 +384,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
384 return usage_with_options_internal(usagestr, options, 1); 384 return usage_with_options_internal(usagestr, options, 1);
385 if (internal_help && !strcmp(arg + 2, "help")) 385 if (internal_help && !strcmp(arg + 2, "help"))
386 return parse_options_usage(usagestr, options); 386 return parse_options_usage(usagestr, options);
387 if (!strcmp(arg + 2, "list-opts"))
388 return PARSE_OPT_LIST;
387 switch (parse_long_opt(ctx, arg + 2, options)) { 389 switch (parse_long_opt(ctx, arg + 2, options)) {
388 case -1: 390 case -1:
389 return parse_options_usage(usagestr, options); 391 return parse_options_usage(usagestr, options);
@@ -422,6 +424,12 @@ int parse_options(int argc, const char **argv, const struct option *options,
422 exit(129); 424 exit(129);
423 case PARSE_OPT_DONE: 425 case PARSE_OPT_DONE:
424 break; 426 break;
427 case PARSE_OPT_LIST:
428 while (options->type != OPTION_END) {
429 printf("--%s ", options->long_name);
430 options++;
431 }
432 exit(130);
425 default: /* PARSE_OPT_UNKNOWN */ 433 default: /* PARSE_OPT_UNKNOWN */
426 if (ctx.argv[0][1] == '-') { 434 if (ctx.argv[0][1] == '-') {
427 error("unknown option `%s'", ctx.argv[0] + 2); 435 error("unknown option `%s'", ctx.argv[0] + 2);
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index abc31a1dac1a..7bb5999940ca 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -140,6 +140,7 @@ extern NORETURN void usage_with_options(const char * const *usagestr,
140enum { 140enum {
141 PARSE_OPT_HELP = -1, 141 PARSE_OPT_HELP = -1,
142 PARSE_OPT_DONE, 142 PARSE_OPT_DONE,
143 PARSE_OPT_LIST,
143 PARSE_OPT_UNKNOWN, 144 PARSE_OPT_UNKNOWN,
144}; 145};
145 146
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index bd7497711424..a8c49548ca48 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,7 +22,7 @@ static const char *get_perf_dir(void)
22 return "."; 22 return ".";
23} 23}
24 24
25#ifdef NO_STRLCPY 25#ifndef HAVE_STRLCPY
26size_t strlcpy(char *dest, const char *src, size_t size) 26size_t strlcpy(char *dest, const char *src, size_t size)
27{ 27{
28 size_t ret = strlen(src); 28 size_t ret = strlen(src);
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 316dbe7f86ed..5a4f2b6f3738 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_REGS_H 1#ifndef __PERF_REGS_H
2#define __PERF_REGS_H 2#define __PERF_REGS_H
3 3
4#ifndef NO_PERF_REGS 4#ifdef HAVE_PERF_REGS
5#include <perf_regs.h> 5#include <perf_regs.h>
6#else 6#else
7#define PERF_REGS_MASK 0 7#define PERF_REGS_MASK 0
@@ -10,5 +10,5 @@ static inline const char *perf_reg_name(int id __maybe_unused)
10{ 10{
11 return NULL; 11 return NULL;
12} 12}
13#endif /* NO_PERF_REGS */ 13#endif /* HAVE_PERF_REGS */
14#endif /* __PERF_REGS_H */ 14#endif /* __PERF_REGS_H */
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 53c7794fc4be..39f3abac7744 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -2,7 +2,7 @@
2#define __PMU_H 2#define __PMU_H
3 3
4#include <linux/bitops.h> 4#include <linux/bitops.h>
5#include "../../../include/linux/perf_event.h" 5#include "../../../include/uapi/linux/perf_event.h"
6 6
7enum { 7enum {
8 PERF_PMU_FORMAT_VALUE_CONFIG, 8 PERF_PMU_FORMAT_VALUE_CONFIG,
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index aab414fbb64b..dd6426163ba6 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -7,7 +7,7 @@
7#include "symbol.h" 7#include "symbol.h"
8#include "thread.h" 8#include "thread.h"
9#include <linux/rbtree.h> 9#include <linux/rbtree.h>
10#include "../../../include/linux/perf_event.h" 10#include "../../../include/uapi/linux/perf_event.h"
11 11
12struct sample_queue; 12struct sample_queue;
13struct ip_callchain; 13struct ip_callchain;
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index d0f9f29cf181..73d510269784 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -23,6 +23,7 @@ cflags += getenv('CFLAGS', '').split()
23 23
24build_lib = getenv('PYTHON_EXTBUILD_LIB') 24build_lib = getenv('PYTHON_EXTBUILD_LIB')
25build_tmp = getenv('PYTHON_EXTBUILD_TMP') 25build_tmp = getenv('PYTHON_EXTBUILD_TMP')
26libtraceevent = getenv('LIBTRACEEVENT')
26 27
27ext_sources = [f.strip() for f in file('util/python-ext-sources') 28ext_sources = [f.strip() for f in file('util/python-ext-sources')
28 if len(f.strip()) > 0 and f[0] != '#'] 29 if len(f.strip()) > 0 and f[0] != '#']
@@ -31,6 +32,7 @@ perf = Extension('perf',
31 sources = ext_sources, 32 sources = ext_sources,
32 include_dirs = ['util/include'], 33 include_dirs = ['util/include'],
33 extra_compile_args = cflags, 34 extra_compile_args = cflags,
35 extra_objects = [libtraceevent],
34 ) 36 )
35 37
36setup(name='perf', 38setup(name='perf',
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b5b1b9211960..cfd1c0feb32d 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -260,6 +260,12 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
260 if (path != NULL) 260 if (path != NULL)
261 goto out_path; 261 goto out_path;
262 262
263 if (!self->ms.map)
264 goto out_ip;
265
266 if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10))
267 goto out_ip;
268
263 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64, 269 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
264 self->ms.map->dso->long_name, self->ip); 270 self->ms.map->dso->long_name, self->ip);
265 fp = popen(cmd, "r"); 271 fp = popen(cmd, "r");
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 12d634792de5..5786f323b597 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -43,6 +43,15 @@ extern struct sort_entry sort_sym_from;
43extern struct sort_entry sort_sym_to; 43extern struct sort_entry sort_sym_to;
44extern enum sort_type sort__first_dimension; 44extern enum sort_type sort__first_dimension;
45 45
46struct he_stat {
47 u64 period;
48 u64 period_sys;
49 u64 period_us;
50 u64 period_guest_sys;
51 u64 period_guest_us;
52 u32 nr_events;
53};
54
46/** 55/**
47 * struct hist_entry - histogram entry 56 * struct hist_entry - histogram entry
48 * 57 *
@@ -52,16 +61,11 @@ extern enum sort_type sort__first_dimension;
52struct hist_entry { 61struct hist_entry {
53 struct rb_node rb_node_in; 62 struct rb_node rb_node_in;
54 struct rb_node rb_node; 63 struct rb_node rb_node;
55 u64 period; 64 struct he_stat stat;
56 u64 period_sys;
57 u64 period_us;
58 u64 period_guest_sys;
59 u64 period_guest_us;
60 struct map_symbol ms; 65 struct map_symbol ms;
61 struct thread *thread; 66 struct thread *thread;
62 u64 ip; 67 u64 ip;
63 s32 cpu; 68 s32 cpu;
64 u32 nr_events;
65 69
66 /* XXX These two should move to some tree widget lib */ 70 /* XXX These two should move to some tree widget lib */
67 u16 row_offset; 71 u16 row_offset;
@@ -73,12 +77,13 @@ struct hist_entry {
73 u8 filtered; 77 u8 filtered;
74 char *srcline; 78 char *srcline;
75 struct symbol *parent; 79 struct symbol *parent;
80 unsigned long position;
76 union { 81 union {
77 unsigned long position;
78 struct hist_entry *pair; 82 struct hist_entry *pair;
79 struct rb_root sorted_chain; 83 struct rb_root sorted_chain;
80 }; 84 };
81 struct branch_info *branch_info; 85 struct branch_info *branch_info;
86 struct hists *hists;
82 struct callchain_root callchain[0]; 87 struct callchain_root callchain[0];
83}; 88};
84 89
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index b441b07172b7..8b6ef7fac745 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -12,7 +12,7 @@
12#include <byteswap.h> 12#include <byteswap.h>
13#include <libgen.h> 13#include <libgen.h>
14 14
15#ifndef NO_LIBELF_SUPPORT 15#ifdef LIBELF_SUPPORT
16#include <libelf.h> 16#include <libelf.h>
17#include <gelf.h> 17#include <gelf.h>
18#include <elf.h> 18#include <elf.h>
@@ -46,10 +46,10 @@ char *strxfrchar(char *s, char from, char to);
46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; 46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
47 * for newer versions we can use mmap to reduce memory usage: 47 * for newer versions we can use mmap to reduce memory usage:
48 */ 48 */
49#ifdef LIBELF_NO_MMAP 49#ifdef LIBELF_MMAP
50# define PERF_ELF_C_READ_MMAP ELF_C_READ
51#else
52# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP 50# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
51#else
52# define PERF_ELF_C_READ_MMAP ELF_C_READ
53#endif 53#endif
54 54
55#ifndef DMGL_PARAMS 55#ifndef DMGL_PARAMS
@@ -233,7 +233,7 @@ struct symsrc {
233 int fd; 233 int fd;
234 enum dso_binary_type type; 234 enum dso_binary_type type;
235 235
236#ifndef NO_LIBELF_SUPPORT 236#ifdef LIBELF_SUPPORT
237 Elf *elf; 237 Elf *elf;
238 GElf_Ehdr ehdr; 238 GElf_Ehdr ehdr;
239 239
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index fb4b7ea6752f..8b3e5939afb6 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm)
39 err = self->comm == NULL ? -ENOMEM : 0; 39 err = self->comm == NULL ? -ENOMEM : 0;
40 if (!err) { 40 if (!err) {
41 self->comm_set = true; 41 self->comm_set = true;
42 map_groups__flush(&self->mg);
43 } 42 }
44 return err; 43 return err;
45} 44}
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index a78c8b303bb5..cb6bc503a792 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -13,7 +13,7 @@ struct unwind_entry {
13 13
14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); 14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
15 15
16#ifndef NO_LIBUNWIND_SUPPORT 16#ifdef LIBUNWIND_SUPPORT
17int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 17int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
18 struct machine *machine, 18 struct machine *machine,
19 struct thread *thread, 19 struct thread *thread,
@@ -31,5 +31,5 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
31{ 31{
32 return 0; 32 return 0;
33} 33}
34#endif /* NO_LIBUNWIND_SUPPORT */ 34#endif /* LIBUNWIND_SUPPORT */
35#endif /* __UNWIND_H */ 35#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 2055cf38041c..99664598bc1a 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,7 +1,7 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include <sys/mman.h> 3#include <sys/mman.h>
4#ifndef NO_BACKTRACE 4#ifdef BACKTRACE_SUPPORT
5#include <execinfo.h> 5#include <execinfo.h>
6#endif 6#endif
7#include <stdio.h> 7#include <stdio.h>
@@ -165,7 +165,7 @@ size_t hex_width(u64 v)
165} 165}
166 166
167/* Obtain a backtrace and print it to stdout. */ 167/* Obtain a backtrace and print it to stdout. */
168#ifndef NO_BACKTRACE 168#ifdef BACKTRACE_SUPPORT
169void dump_stack(void) 169void dump_stack(void)
170{ 170{
171 void *array[16]; 171 void *array[16];
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile
new file mode 100644
index 000000000000..6b9cf7a987c7
--- /dev/null
+++ b/tools/power/acpi/Makefile
@@ -0,0 +1,18 @@
1PROG= acpidump
2SRCS= acpidump.c
3KERNEL_INCLUDE := ../../../include
4CFLAGS += -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Os -s -D_LINUX -DDEFINE_ALTERNATE_TYPES -I$(KERNEL_INCLUDE)
5
6all: acpidump
7$(PROG) : $(SRCS)
8 $(CC) $(CFLAGS) $(SRCS) -o $(PROG)
9
10CLEANFILES= $(PROG)
11
12clean :
13 rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~
14
15install :
16 install acpidump /usr/bin/acpidump
17 install acpidump.8 /usr/share/man/man8
18
diff --git a/tools/power/acpi/acpidump.8 b/tools/power/acpi/acpidump.8
new file mode 100644
index 000000000000..adfa99166e5e
--- /dev/null
+++ b/tools/power/acpi/acpidump.8
@@ -0,0 +1,59 @@
1.TH ACPIDUMP 8
2.SH NAME
3acpidump \- Dump system's ACPI tables to an ASCII file.
4.SH SYNOPSIS
5.ft B
6.B acpidump > acpidump.out
7.SH DESCRIPTION
8\fBacpidump \fP dumps the systems ACPI tables to an ASCII file
9appropriate for attaching to a bug report.
10
11Subsequently, they can be processed by utilities in the ACPICA package.
12.SS Options
13no options worth worrying about.
14.PP
15.SH EXAMPLE
16
17.nf
18# acpidump > acpidump.out
19
20$ acpixtract -a acpidump.out
21 Acpi table [DSDT] - 15974 bytes written to DSDT.dat
22 Acpi table [FACS] - 64 bytes written to FACS.dat
23 Acpi table [FACP] - 116 bytes written to FACP.dat
24 Acpi table [APIC] - 120 bytes written to APIC.dat
25 Acpi table [MCFG] - 60 bytes written to MCFG.dat
26 Acpi table [SSDT] - 444 bytes written to SSDT1.dat
27 Acpi table [SSDT] - 439 bytes written to SSDT2.dat
28 Acpi table [SSDT] - 439 bytes written to SSDT3.dat
29 Acpi table [SSDT] - 439 bytes written to SSDT4.dat
30 Acpi table [SSDT] - 439 bytes written to SSDT5.dat
31 Acpi table [RSDT] - 76 bytes written to RSDT.dat
32 Acpi table [RSDP] - 20 bytes written to RSDP.dat
33
34$ iasl -d *.dat
35...
36.fi
37creates *.dsl, a human readable form which can be edited
38and compiled using iasl.
39
40
41.SH NOTES
42
43.B "acpidump "
44must be run as root.
45
46.SH REFERENCES
47ACPICA: https://acpica.org/
48
49.SH FILES
50.ta
51.nf
52/dev/mem
53/sys/firmware/acpi/tables/dynamic/*
54.fi
55
56.PP
57.SH AUTHOR
58.nf
59Written by Len Brown <len.brown@intel.com>
diff --git a/tools/power/acpi/acpidump.c b/tools/power/acpi/acpidump.c
new file mode 100644
index 000000000000..a84553a0e0df
--- /dev/null
+++ b/tools/power/acpi/acpidump.c
@@ -0,0 +1,559 @@
1/*
2 * (c) Alexey Starikovskiy, Intel, 2005-2006.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * substantially similar to the "NO WARRANTY" disclaimer below
13 * ("Disclaimer") and any redistribution must be conditioned upon
14 * including a substantially similar Disclaimer requirement for further
15 * binary redistribution.
16 * 3. Neither the names of the above-listed copyright holders nor the names
17 * of any contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * NO WARRANTY
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
34 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGES.
36 */
37
38#ifdef DEFINE_ALTERNATE_TYPES
39/* hack to enable building old application with new headers -lenb */
40#define acpi_fadt_descriptor acpi_table_fadt
41#define acpi_rsdp_descriptor acpi_table_rsdp
42#define DSDT_SIG ACPI_SIG_DSDT
43#define FACS_SIG ACPI_SIG_FACS
44#define FADT_SIG ACPI_SIG_FADT
45#define xfirmware_ctrl Xfacs
46#define firmware_ctrl facs
47
48typedef int s32;
49typedef unsigned char u8;
50typedef unsigned short u16;
51typedef unsigned int u32;
52typedef unsigned long long u64;
53typedef long long s64;
54#endif
55
56#include <sys/mman.h>
57#include <sys/types.h>
58#include <sys/stat.h>
59#include <fcntl.h>
60#include <stdio.h>
61#include <string.h>
62#include <unistd.h>
63#include <getopt.h>
64
65#include <dirent.h>
66
67#include <acpi/acconfig.h>
68#include <acpi/platform/acenv.h>
69#include <acpi/actypes.h>
70#include <acpi/actbl.h>
71
72static inline u8 checksum(u8 * buffer, u32 length)
73{
74 u8 sum = 0, *i = buffer;
75 buffer += length;
76 for (; i < buffer; sum += *(i++));
77 return sum;
78}
79
80static unsigned long psz, addr, length;
81static int print, connect, skip;
82static u8 select_sig[4];
83
84static unsigned long read_efi_systab( void )
85{
86 char buffer[80];
87 unsigned long addr;
88 FILE *f = fopen("/sys/firmware/efi/systab", "r");
89 if (f) {
90 while (fgets(buffer, 80, f)) {
91 if (sscanf(buffer, "ACPI20=0x%lx", &addr) == 1)
92 return addr;
93 }
94 fclose(f);
95 }
96 return 0;
97}
98
99static u8 *acpi_map_memory(unsigned long where, unsigned length)
100{
101 unsigned long offset;
102 u8 *there;
103 int fd = open("/dev/mem", O_RDONLY);
104 if (fd < 0) {
105 fprintf(stderr, "acpi_os_map_memory: cannot open /dev/mem\n");
106 exit(1);
107 }
108 offset = where % psz;
109 there = mmap(NULL, length + offset, PROT_READ, MAP_PRIVATE,
110 fd, where - offset);
111 close(fd);
112 if (there == MAP_FAILED) return 0;
113 return (there + offset);
114}
115
116static void acpi_unmap_memory(u8 * there, unsigned length)
117{
118 unsigned long offset = (unsigned long)there % psz;
119 munmap(there - offset, length + offset);
120}
121
122static struct acpi_table_header *acpi_map_table(unsigned long where, char *sig)
123{
124 unsigned size;
125 struct acpi_table_header *tbl = (struct acpi_table_header *)
126 acpi_map_memory(where, sizeof(struct acpi_table_header));
127 if (!tbl || (sig && memcmp(sig, tbl->signature, 4))) return 0;
128 size = tbl->length;
129 acpi_unmap_memory((u8 *) tbl, sizeof(struct acpi_table_header));
130 return (struct acpi_table_header *)acpi_map_memory(where, size);
131}
132
133static void acpi_unmap_table(struct acpi_table_header *tbl)
134{
135 acpi_unmap_memory((u8 *)tbl, tbl->length);
136}
137
138static struct acpi_rsdp_descriptor *acpi_scan_for_rsdp(u8 *begin, u32 length)
139{
140 struct acpi_rsdp_descriptor *rsdp;
141 u8 *i, *end = begin + length;
142 /* Search from given start address for the requested length */
143 for (i = begin; i < end; i += ACPI_RSDP_SCAN_STEP) {
144 /* The signature and checksum must both be correct */
145 if (memcmp((char *)i, "RSD PTR ", 8)) continue;
146 rsdp = (struct acpi_rsdp_descriptor *)i;
147 /* Signature matches, check the appropriate checksum */
148 if (!checksum((u8 *) rsdp, (rsdp->revision < 2) ?
149 ACPI_RSDP_CHECKSUM_LENGTH :
150 ACPI_RSDP_XCHECKSUM_LENGTH))
151 /* Checksum valid, we have found a valid RSDP */
152 return rsdp;
153 }
154 /* Searched entire block, no RSDP was found */
155 return 0;
156}
157
158/*
159 * Output data
160 */
161static void acpi_show_data(int fd, u8 * data, int size)
162{
163 char buffer[256];
164 int len;
165 int i, remain = size;
166 while (remain > 0) {
167 len = snprintf(buffer, 256, " %04x:", size - remain);
168 for (i = 0; i < 16 && i < remain; i++) {
169 len +=
170 snprintf(&buffer[len], 256 - len, " %02x", data[i]);
171 }
172 for (; i < 16; i++) {
173 len += snprintf(&buffer[len], 256 - len, " ");
174 }
175 len += snprintf(&buffer[len], 256 - len, " ");
176 for (i = 0; i < 16 && i < remain; i++) {
177 buffer[len++] = (isprint(data[i])) ? data[i] : '.';
178 }
179 buffer[len++] = '\n';
180 write(fd, buffer, len);
181 data += 16;
182 remain -= 16;
183 }
184}
185
186/*
187 * Output ACPI table
188 */
189static void acpi_show_table(int fd, struct acpi_table_header *table, unsigned long addr)
190{
191 char buff[80];
192 int len = snprintf(buff, 80, "%.4s @ %p\n", table->signature, (void *)addr);
193 write(fd, buff, len);
194 acpi_show_data(fd, (u8 *) table, table->length);
195 buff[0] = '\n';
196 write(fd, buff, 1);
197}
198
199static void write_table(int fd, struct acpi_table_header *tbl, unsigned long addr)
200{
201 static int select_done = 0;
202 if (!select_sig[0]) {
203 if (print) {
204 acpi_show_table(fd, tbl, addr);
205 } else {
206 write(fd, tbl, tbl->length);
207 }
208 } else if (!select_done && !memcmp(select_sig, tbl->signature, 4)) {
209 if (skip > 0) {
210 --skip;
211 return;
212 }
213 if (print) {
214 acpi_show_table(fd, tbl, addr);
215 } else {
216 write(fd, tbl, tbl->length);
217 }
218 select_done = 1;
219 }
220}
221
222static void acpi_dump_FADT(int fd, struct acpi_table_header *tbl, unsigned long xaddr) {
223 struct acpi_fadt_descriptor x;
224 unsigned long addr;
225 size_t len = sizeof(struct acpi_fadt_descriptor);
226 if (len > tbl->length) len = tbl->length;
227 memcpy(&x, tbl, len);
228 x.header.length = len;
229 if (checksum((u8 *)tbl, len)) {
230 fprintf(stderr, "Wrong checksum for FADT!\n");
231 }
232 if (x.header.length >= 148 && x.Xdsdt) {
233 addr = (unsigned long)x.Xdsdt;
234 if (connect) {
235 x.Xdsdt = lseek(fd, 0, SEEK_CUR);
236 }
237 } else if (x.header.length >= 44 && x.dsdt) {
238 addr = (unsigned long)x.dsdt;
239 if (connect) {
240 x.dsdt = lseek(fd, 0, SEEK_CUR);
241 }
242 } else {
243 fprintf(stderr, "No DSDT in FADT!\n");
244 goto no_dsdt;
245 }
246 tbl = acpi_map_table(addr, DSDT_SIG);
247 if (!tbl) goto no_dsdt;
248 if (checksum((u8 *)tbl, tbl->length))
249 fprintf(stderr, "Wrong checksum for DSDT!\n");
250 write_table(fd, tbl, addr);
251 acpi_unmap_table(tbl);
252no_dsdt:
253 if (x.header.length >= 140 && x.xfirmware_ctrl) {
254 addr = (unsigned long)x.xfirmware_ctrl;
255 if (connect) {
256 x.xfirmware_ctrl = lseek(fd, 0, SEEK_CUR);
257 }
258 } else if (x.header.length >= 40 && x.firmware_ctrl) {
259 addr = (unsigned long)x.firmware_ctrl;
260 if (connect) {
261 x.firmware_ctrl = lseek(fd, 0, SEEK_CUR);
262 }
263 } else {
264 fprintf(stderr, "No FACS in FADT!\n");
265 goto no_facs;
266 }
267 tbl = acpi_map_table(addr, FACS_SIG);
268 if (!tbl) goto no_facs;
269 /* do not checksum FACS */
270 write_table(fd, tbl, addr);
271 acpi_unmap_table(tbl);
272no_facs:
273 write_table(fd, (struct acpi_table_header *)&x, xaddr);
274}
275
276static int acpi_dump_SDT(int fd, struct acpi_rsdp_descriptor *rsdp)
277{
278 struct acpi_table_header *sdt, *tbl = 0;
279 int xsdt = 1, i, num;
280 char *offset;
281 unsigned long addr;
282 if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
283 tbl = acpi_map_table(rsdp->xsdt_physical_address, "XSDT");
284 }
285 if (!tbl && rsdp->rsdt_physical_address) {
286 xsdt = 0;
287 tbl = acpi_map_table(rsdp->rsdt_physical_address, "RSDT");
288 }
289 if (!tbl) return 0;
290 sdt = malloc(tbl->length);
291 memcpy(sdt, tbl, tbl->length);
292 acpi_unmap_table(tbl);
293 if (checksum((u8 *)sdt, sdt->length))
294 fprintf(stderr, "Wrong checksum for %s!\n", (xsdt)?"XSDT":"RSDT");
295 num = (sdt->length - sizeof(struct acpi_table_header))/((xsdt)?sizeof(u64):sizeof(u32));
296 offset = (char *)sdt + sizeof(struct acpi_table_header);
297 for (i = 0; i < num; ++i, offset += ((xsdt) ? sizeof(u64) : sizeof(u32))) {
298 addr = (xsdt) ? (unsigned long)(*(u64 *)offset):
299 (unsigned long)(*(u32 *)offset);
300 if (!addr) continue;
301 tbl = acpi_map_table(addr, 0);
302 if (!tbl) continue;
303 if (!memcmp(tbl->signature, FADT_SIG, 4)) {
304 acpi_dump_FADT(fd, tbl, addr);
305 } else {
306 if (checksum((u8 *)tbl, tbl->length))
307 fprintf(stderr, "Wrong checksum for generic table!\n");
308 write_table(fd, tbl, addr);
309 }
310 acpi_unmap_table(tbl);
311 if (connect) {
312 if (xsdt)
313 (*(u64*)offset) = lseek(fd, 0, SEEK_CUR);
314 else
315 (*(u32*)offset) = lseek(fd, 0, SEEK_CUR);
316 }
317 }
318 if (xsdt) {
319 addr = (unsigned long)rsdp->xsdt_physical_address;
320 if (connect) {
321 rsdp->xsdt_physical_address = lseek(fd, 0, SEEK_CUR);
322 }
323 } else {
324 addr = (unsigned long)rsdp->rsdt_physical_address;
325 if (connect) {
326 rsdp->rsdt_physical_address = lseek(fd, 0, SEEK_CUR);
327 }
328 }
329 write_table(fd, sdt, addr);
330 free (sdt);
331 return 1;
332}
333
334#define DYNAMIC_SSDT "/sys/firmware/acpi/tables/dynamic"
335
336static void acpi_dump_dynamic_SSDT(int fd)
337{
338 struct stat file_stat;
339 char filename[256], *ptr;
340 DIR *tabledir;
341 struct dirent *entry;
342 FILE *fp;
343 int count, readcount, length;
344 struct acpi_table_header table_header, *ptable;
345
346 if (stat(DYNAMIC_SSDT, &file_stat) == -1) {
347 /* The directory doesn't exist */
348 return;
349 }
350 tabledir = opendir(DYNAMIC_SSDT);
351 if(!tabledir){
352 /*can't open the directory */
353 return;
354 }
355
356 while ((entry = readdir(tabledir)) != 0){
357 /* skip the file of . /.. */
358 if (entry->d_name[0] == '.')
359 continue;
360
361 sprintf(filename, "%s/%s", DYNAMIC_SSDT, entry->d_name);
362 fp = fopen(filename, "r");
363 if (fp == NULL) {
364 fprintf(stderr, "Can't open the file of %s\n",
365 filename);
366 continue;
367 }
368 /* Read the Table header to parse the table length */
369 count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
370 if (count < sizeof(table_header)) {
371 /* the length is lessn than ACPI table header. skip it */
372 fclose(fp);
373 continue;
374 }
375 length = table_header.length;
376 ptr = malloc(table_header.length);
377 fseek(fp, 0, SEEK_SET);
378 readcount = 0;
379 while(!feof(fp) && readcount < length) {
380 count = fread(ptr + readcount, 1, 256, fp);
381 readcount += count;
382 }
383 fclose(fp);
384 ptable = (struct acpi_table_header *) ptr;
385 if (checksum((u8 *) ptable, ptable->length))
386 fprintf(stderr, "Wrong checksum "
387 "for dynamic SSDT table!\n");
388 write_table(fd, ptable, 0);
389 free(ptr);
390 }
391 closedir(tabledir);
392 return;
393}
394
395static void usage(const char *progname)
396{
397 puts("Usage:");
398 printf("%s [--addr 0x1234][--table DSDT][--output filename]"
399 "[--binary][--length 0x456][--help]\n", progname);
400 puts("\t--addr 0x1234 or -a 0x1234 -- look for tables at this physical address");
401 puts("\t--table DSDT or -t DSDT -- only dump table with DSDT signature");
402 puts("\t--output filename or -o filename -- redirect output from stdin to filename");
403 puts("\t--binary or -b -- dump data in binary form rather than in hex-dump format");
404 puts("\t--length 0x456 or -l 0x456 -- works only with --addr, dump physical memory"
405 "\n\t\tregion without trying to understand it's contents");
406 puts("\t--skip 2 or -s 2 -- skip 2 tables of the given name and output only 3rd one");
407 puts("\t--help or -h -- this help message");
408 exit(0);
409}
410
411static struct option long_options[] = {
412 {"addr", 1, 0, 0},
413 {"table", 1, 0, 0},
414 {"output", 1, 0, 0},
415 {"binary", 0, 0, 0},
416 {"length", 1, 0, 0},
417 {"skip", 1, 0, 0},
418 {"help", 0, 0, 0},
419 {0, 0, 0, 0}
420};
421int main(int argc, char **argv)
422{
423 int option_index, c, fd;
424 u8 *raw;
425 struct acpi_rsdp_descriptor rsdpx, *x = 0;
426 char *filename = 0;
427 char buff[80];
428 memset(select_sig, 0, 4);
429 print = 1;
430 connect = 0;
431 addr = length = 0;
432 skip = 0;
433 while (1) {
434 option_index = 0;
435 c = getopt_long(argc, argv, "a:t:o:bl:s:h",
436 long_options, &option_index);
437 if (c == -1)
438 break;
439
440 switch (c) {
441 case 0:
442 switch (option_index) {
443 case 0:
444 addr = strtoul(optarg, (char **)NULL, 16);
445 break;
446 case 1:
447 memcpy(select_sig, optarg, 4);
448 break;
449 case 2:
450 filename = optarg;
451 break;
452 case 3:
453 print = 0;
454 break;
455 case 4:
456 length = strtoul(optarg, (char **)NULL, 16);
457 break;
458 case 5:
459 skip = strtoul(optarg, (char **)NULL, 10);
460 break;
461 case 6:
462 usage(argv[0]);
463 exit(0);
464 }
465 break;
466 case 'a':
467 addr = strtoul(optarg, (char **)NULL, 16);
468 break;
469 case 't':
470 memcpy(select_sig, optarg, 4);
471 break;
472 case 'o':
473 filename = optarg;
474 break;
475 case 'b':
476 print = 0;
477 break;
478 case 'l':
479 length = strtoul(optarg, (char **)NULL, 16);
480 break;
481 case 's':
482 skip = strtoul(optarg, (char **)NULL, 10);
483 break;
484 case 'h':
485 usage(argv[0]);
486 exit(0);
487 default:
488 printf("Unknown option!\n");
489 usage(argv[0]);
490 exit(0);
491 }
492 }
493
494 fd = STDOUT_FILENO;
495 if (filename) {
496 fd = creat(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
497 if (fd < 0)
498 return fd;
499 }
500
501 if (!select_sig[0] && !print) {
502 connect = 1;
503 }
504
505 psz = sysconf(_SC_PAGESIZE);
506 if (length && addr) {
507 /* We know length and address, it means we just want a memory dump */
508 if (!(raw = acpi_map_memory(addr, length)))
509 goto not_found;
510 write(fd, raw, length);
511 acpi_unmap_memory(raw, length);
512 close(fd);
513 return 0;
514 }
515
516 length = sizeof(struct acpi_rsdp_descriptor);
517 if (!addr) {
518 addr = read_efi_systab();
519 if (!addr) {
520 addr = ACPI_HI_RSDP_WINDOW_BASE;
521 length = ACPI_HI_RSDP_WINDOW_SIZE;
522 }
523 }
524
525 if (!(raw = acpi_map_memory(addr, length)) ||
526 !(x = acpi_scan_for_rsdp(raw, length)))
527 goto not_found;
528
529 /* Find RSDP and print all found tables */
530 memcpy(&rsdpx, x, sizeof(struct acpi_rsdp_descriptor));
531 acpi_unmap_memory(raw, length);
532 if (connect) {
533 lseek(fd, sizeof(struct acpi_rsdp_descriptor), SEEK_SET);
534 }
535 if (!acpi_dump_SDT(fd, &rsdpx))
536 goto not_found;
537 if (connect) {
538 lseek(fd, 0, SEEK_SET);
539 write(fd, x, (rsdpx.revision < 2) ?
540 ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
541 } else if (!select_sig[0] || !memcmp("RSD PTR ", select_sig, 4)) {
542 addr += (long)x - (long)raw;
543 length = snprintf(buff, 80, "RSD PTR @ %p\n", (void *)addr);
544 write(fd, buff, length);
545 acpi_show_data(fd, (u8 *) & rsdpx, (rsdpx.revision < 2) ?
546 ACPI_RSDP_CHECKSUM_LENGTH : ACPI_RSDP_XCHECKSUM_LENGTH);
547 buff[0] = '\n';
548 write(fd, buff, 1);
549 }
550 acpi_dump_dynamic_SSDT(fd);
551 close(fd);
552 return 0;
553not_found:
554 close(fd);
555 fprintf(stderr, "ACPI tables were not found. If you know location "
556 "of RSD PTR table (from dmesg, etc), "
557 "supply it with either --addr or -a option\n");
558 return 1;
559}
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index a93e06cfcc2a..cf397bd26d0c 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -111,7 +111,7 @@ GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo;
111export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS 111export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS
112 112
113# check if compiler option is supported 113# check if compiler option is supported
114cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} 114cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -x c /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;}
115 115
116# use '-Os' optimization if available, else use -O2 116# use '-Os' optimization if available, else use -O2
117OPTIMIZATION := $(call cc-supports,-Os,-O2) 117OPTIMIZATION := $(call cc-supports,-Os,-O2)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 74e44507dfe9..e4d0690cccf9 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -4,15 +4,11 @@ turbostat \- Report processor frequency and idle statistics
4.SH SYNOPSIS 4.SH SYNOPSIS
5.ft B 5.ft B
6.B turbostat 6.B turbostat
7.RB [ "\-s" ] 7.RB [ Options ]
8.RB [ "\-v" ]
9.RB [ "\-M MSR#" ]
10.RB command 8.RB command
11.br 9.br
12.B turbostat 10.B turbostat
13.RB [ "\-s" ] 11.RB [ Options ]
14.RB [ "\-v" ]
15.RB [ "\-M MSR#" ]
16.RB [ "\-i interval_sec" ] 12.RB [ "\-i interval_sec" ]
17.SH DESCRIPTION 13.SH DESCRIPTION
18\fBturbostat \fP reports processor topology, frequency 14\fBturbostat \fP reports processor topology, frequency
@@ -27,16 +23,23 @@ supports an "invariant" TSC, plus the APERF and MPERF MSRs.
27on processors that additionally support C-state residency counters. 23on processors that additionally support C-state residency counters.
28 24
29.SS Options 25.SS Options
30The \fB-s\fP option limits output to a 1-line system summary for each interval. 26The \fB-p\fP option limits output to the 1st thread in 1st core of each package.
31.PP 27.PP
32The \fB-c\fP option limits output to the 1st thread in each core. 28The \fB-P\fP option limits output to the 1st thread in each Package.
33.PP 29.PP
34The \fB-p\fP option limits output to the 1st thread in each package. 30The \fB-S\fP option limits output to a 1-line System Summary for each interval.
35.PP 31.PP
36The \fB-v\fP option increases verbosity. 32The \fB-v\fP option increases verbosity.
37.PP 33.PP
38The \fB-M MSR#\fP option dumps the specified MSR, 34The \fB-s\fP option prints the SMI counter, equivalent to "-c 0x34"
39in addition to the usual frequency and idle statistics. 35.PP
36The \fB-c MSR#\fP option includes the delta of the specified 32-bit MSR counter.
37.PP
38The \fB-C MSR#\fP option includes the delta of the specified 64-bit MSR counter.
39.PP
40The \fB-m MSR#\fP option includes the the specified 32-bit MSR value.
41.PP
42The \fB-M MSR#\fP option includes the the specified 64-bit MSR value.
40.PP 43.PP
41The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds. 44The \fB-i interval_sec\fP option prints statistics every \fiinterval_sec\fP seconds.
42The default is 5 seconds. 45The default is 5 seconds.
@@ -150,6 +153,29 @@ Note that turbostat reports average GHz of 3.63, while
150the arithmetic average of the GHz column above is lower. 153the arithmetic average of the GHz column above is lower.
151This is a weighted average, where the weight is %c0. ie. it is the total number of 154This is a weighted average, where the weight is %c0. ie. it is the total number of
152un-halted cycles elapsed per time divided by the number of CPUs. 155un-halted cycles elapsed per time divided by the number of CPUs.
156.SH SMI COUNTING EXAMPLE
157On Intel Nehalem and newer processors, MSR 0x34 is a System Management Mode Interrupt (SMI) counter.
158Using the -m option, you can display how many SMIs have fired since reset, or if there
159are SMIs during the measurement interval, you can display the delta using the -d option.
160.nf
161[root@x980 ~]# turbostat -m 0x34
162cor CPU %c0 GHz TSC MSR 0x034 %c1 %c3 %c6 %pc3 %pc6
163 1.41 1.82 3.38 0x00000000 8.92 37.82 51.85 17.37 0.55
164 0 0 3.73 2.03 3.38 0x00000055 1.72 48.25 46.31 17.38 0.55
165 0 6 0.14 1.63 3.38 0x00000056 5.30
166 1 2 2.51 1.80 3.38 0x00000056 15.65 29.33 52.52
167 1 8 0.10 1.65 3.38 0x00000056 18.05
168 2 4 1.16 1.68 3.38 0x00000056 5.87 24.47 68.50
169 2 10 0.10 1.63 3.38 0x00000056 6.93
170 8 1 3.84 1.91 3.38 0x00000056 1.36 50.65 44.16
171 8 7 0.08 1.64 3.38 0x00000056 5.12
172 9 3 1.82 1.73 3.38 0x00000056 7.59 24.21 66.38
173 9 9 0.09 1.68 3.38 0x00000056 9.32
174 10 5 1.66 1.65 3.38 0x00000056 15.10 50.00 33.23
175 10 11 1.72 1.65 3.38 0x00000056 15.05
176^C
177[root@x980 ~]#
178.fi
153.SH NOTES 179.SH NOTES
154 180
155.B "turbostat " 181.B "turbostat "
@@ -165,6 +191,13 @@ may work poorly on Linux-2.6.20 through 2.6.29,
165as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF 191as \fBacpi-cpufreq \fPperiodically cleared the APERF and MPERF
166in those kernels. 192in those kernels.
167 193
194If the TSC column does not make sense, then
195the other numbers will also make no sense.
196Turbostat is lightweight, and its data collection is not atomic.
197These issues are usually caused by an extremely short measurement
198interval (much less than 1 second), or system activity that prevents
199turbostat from being able to run on all CPUS to quickly collect data.
200
168The APERF, MPERF MSRs are defined to count non-halted cycles. 201The APERF, MPERF MSRs are defined to count non-halted cycles.
169Although it is not guaranteed by the architecture, turbostat assumes 202Although it is not guaranteed by the architecture, turbostat assumes
170that they count at TSC rate, which is true on all processors tested to date. 203that they count at TSC rate, which is true on all processors tested to date.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 861d77190206..2655ae9a3ad8 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -35,9 +35,9 @@
35#include <ctype.h> 35#include <ctype.h>
36#include <sched.h> 36#include <sched.h>
37 37
38#define MSR_TSC 0x10
39#define MSR_NEHALEM_PLATFORM_INFO 0xCE 38#define MSR_NEHALEM_PLATFORM_INFO 0xCE
40#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD 39#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1AD
40#define MSR_IVT_TURBO_RATIO_LIMIT 0x1AE
41#define MSR_APERF 0xE8 41#define MSR_APERF 0xE8
42#define MSR_MPERF 0xE7 42#define MSR_MPERF 0xE7
43#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */ 43#define MSR_PKG_C2_RESIDENCY 0x60D /* SNB only */
@@ -62,7 +62,11 @@ unsigned int genuine_intel;
62unsigned int has_invariant_tsc; 62unsigned int has_invariant_tsc;
63unsigned int do_nehalem_platform_info; 63unsigned int do_nehalem_platform_info;
64unsigned int do_nehalem_turbo_ratio_limit; 64unsigned int do_nehalem_turbo_ratio_limit;
65unsigned int extra_msr_offset; 65unsigned int do_ivt_turbo_ratio_limit;
66unsigned int extra_msr_offset32;
67unsigned int extra_msr_offset64;
68unsigned int extra_delta_offset32;
69unsigned int extra_delta_offset64;
66double bclk; 70double bclk;
67unsigned int show_pkg; 71unsigned int show_pkg;
68unsigned int show_core; 72unsigned int show_core;
@@ -83,7 +87,10 @@ struct thread_data {
83 unsigned long long aperf; 87 unsigned long long aperf;
84 unsigned long long mperf; 88 unsigned long long mperf;
85 unsigned long long c1; /* derived */ 89 unsigned long long c1; /* derived */
86 unsigned long long extra_msr; 90 unsigned long long extra_msr64;
91 unsigned long long extra_delta64;
92 unsigned long long extra_msr32;
93 unsigned long long extra_delta32;
87 unsigned int cpu_id; 94 unsigned int cpu_id;
88 unsigned int flags; 95 unsigned int flags;
89#define CPU_IS_FIRST_THREAD_IN_CORE 0x2 96#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
@@ -222,6 +229,14 @@ void print_header(void)
222 if (has_aperf) 229 if (has_aperf)
223 outp += sprintf(outp, " GHz"); 230 outp += sprintf(outp, " GHz");
224 outp += sprintf(outp, " TSC"); 231 outp += sprintf(outp, " TSC");
232 if (extra_delta_offset32)
233 outp += sprintf(outp, " count 0x%03X", extra_delta_offset32);
234 if (extra_delta_offset64)
235 outp += sprintf(outp, " COUNT 0x%03X", extra_delta_offset64);
236 if (extra_msr_offset32)
237 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset32);
238 if (extra_msr_offset64)
239 outp += sprintf(outp, " MSR 0x%03X", extra_msr_offset64);
225 if (do_nhm_cstates) 240 if (do_nhm_cstates)
226 outp += sprintf(outp, " %%c1"); 241 outp += sprintf(outp, " %%c1");
227 if (do_nhm_cstates) 242 if (do_nhm_cstates)
@@ -238,8 +253,6 @@ void print_header(void)
238 outp += sprintf(outp, " %%pc6"); 253 outp += sprintf(outp, " %%pc6");
239 if (do_snb_cstates) 254 if (do_snb_cstates)
240 outp += sprintf(outp, " %%pc7"); 255 outp += sprintf(outp, " %%pc7");
241 if (extra_msr_offset)
242 outp += sprintf(outp, " MSR 0x%x ", extra_msr_offset);
243 256
244 outp += sprintf(outp, "\n"); 257 outp += sprintf(outp, "\n");
245} 258}
@@ -255,8 +268,14 @@ int dump_counters(struct thread_data *t, struct core_data *c,
255 fprintf(stderr, "aperf: %016llX\n", t->aperf); 268 fprintf(stderr, "aperf: %016llX\n", t->aperf);
256 fprintf(stderr, "mperf: %016llX\n", t->mperf); 269 fprintf(stderr, "mperf: %016llX\n", t->mperf);
257 fprintf(stderr, "c1: %016llX\n", t->c1); 270 fprintf(stderr, "c1: %016llX\n", t->c1);
271 fprintf(stderr, "msr0x%x: %08llX\n",
272 extra_delta_offset32, t->extra_delta32);
258 fprintf(stderr, "msr0x%x: %016llX\n", 273 fprintf(stderr, "msr0x%x: %016llX\n",
259 extra_msr_offset, t->extra_msr); 274 extra_delta_offset64, t->extra_delta64);
275 fprintf(stderr, "msr0x%x: %08llX\n",
276 extra_msr_offset32, t->extra_msr32);
277 fprintf(stderr, "msr0x%x: %016llX\n",
278 extra_msr_offset64, t->extra_msr64);
260 } 279 }
261 280
262 if (c) { 281 if (c) {
@@ -360,6 +379,21 @@ int format_counters(struct thread_data *t, struct core_data *c,
360 /* TSC */ 379 /* TSC */
361 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float); 380 outp += sprintf(outp, "%5.2f", 1.0 * t->tsc/units/interval_float);
362 381
382 /* delta */
383 if (extra_delta_offset32)
384 outp += sprintf(outp, " %11llu", t->extra_delta32);
385
386 /* DELTA */
387 if (extra_delta_offset64)
388 outp += sprintf(outp, " %11llu", t->extra_delta64);
389 /* msr */
390 if (extra_msr_offset32)
391 outp += sprintf(outp, " 0x%08llx", t->extra_msr32);
392
393 /* MSR */
394 if (extra_msr_offset64)
395 outp += sprintf(outp, " 0x%016llx", t->extra_msr64);
396
363 if (do_nhm_cstates) { 397 if (do_nhm_cstates) {
364 if (!skip_c1) 398 if (!skip_c1)
365 outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc); 399 outp += sprintf(outp, " %6.2f", 100.0 * t->c1/t->tsc);
@@ -391,8 +425,6 @@ int format_counters(struct thread_data *t, struct core_data *c,
391 if (do_snb_cstates) 425 if (do_snb_cstates)
392 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); 426 outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc);
393done: 427done:
394 if (extra_msr_offset)
395 outp += sprintf(outp, " 0x%016llx", t->extra_msr);
396 outp += sprintf(outp, "\n"); 428 outp += sprintf(outp, "\n");
397 429
398 return 0; 430 return 0;
@@ -502,10 +534,16 @@ delta_thread(struct thread_data *new, struct thread_data *old,
502 old->mperf = 1; /* divide by 0 protection */ 534 old->mperf = 1; /* divide by 0 protection */
503 } 535 }
504 536
537 old->extra_delta32 = new->extra_delta32 - old->extra_delta32;
538 old->extra_delta32 &= 0xFFFFFFFF;
539
540 old->extra_delta64 = new->extra_delta64 - old->extra_delta64;
541
505 /* 542 /*
506 * for "extra msr", just copy the latest w/o subtracting 543 * Extra MSR is just a snapshot, simply copy latest w/o subtracting
507 */ 544 */
508 old->extra_msr = new->extra_msr; 545 old->extra_msr32 = new->extra_msr32;
546 old->extra_msr64 = new->extra_msr64;
509} 547}
510 548
511int delta_cpu(struct thread_data *t, struct core_data *c, 549int delta_cpu(struct thread_data *t, struct core_data *c,
@@ -533,6 +571,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
533 t->mperf = 0; 571 t->mperf = 0;
534 t->c1 = 0; 572 t->c1 = 0;
535 573
574 t->extra_delta32 = 0;
575 t->extra_delta64 = 0;
576
536 /* tells format_counters to dump all fields from this set */ 577 /* tells format_counters to dump all fields from this set */
537 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE; 578 t->flags = CPU_IS_FIRST_THREAD_IN_CORE | CPU_IS_FIRST_CORE_IN_PACKAGE;
538 579
@@ -553,6 +594,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
553 average.threads.mperf += t->mperf; 594 average.threads.mperf += t->mperf;
554 average.threads.c1 += t->c1; 595 average.threads.c1 += t->c1;
555 596
597 average.threads.extra_delta32 += t->extra_delta32;
598 average.threads.extra_delta64 += t->extra_delta64;
599
556 /* sum per-core values only for 1st thread in core */ 600 /* sum per-core values only for 1st thread in core */
557 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) 601 if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
558 return 0; 602 return 0;
@@ -588,6 +632,11 @@ void compute_average(struct thread_data *t, struct core_data *c,
588 average.threads.mperf /= topo.num_cpus; 632 average.threads.mperf /= topo.num_cpus;
589 average.threads.c1 /= topo.num_cpus; 633 average.threads.c1 /= topo.num_cpus;
590 634
635 average.threads.extra_delta32 /= topo.num_cpus;
636 average.threads.extra_delta32 &= 0xFFFFFFFF;
637
638 average.threads.extra_delta64 /= topo.num_cpus;
639
591 average.cores.c3 /= topo.num_cores; 640 average.cores.c3 /= topo.num_cores;
592 average.cores.c6 /= topo.num_cores; 641 average.cores.c6 /= topo.num_cores;
593 average.cores.c7 /= topo.num_cores; 642 average.cores.c7 /= topo.num_cores;
@@ -629,8 +678,24 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
629 return -4; 678 return -4;
630 } 679 }
631 680
632 if (extra_msr_offset) 681 if (extra_delta_offset32) {
633 if (get_msr(cpu, extra_msr_offset, &t->extra_msr)) 682 if (get_msr(cpu, extra_delta_offset32, &t->extra_delta32))
683 return -5;
684 t->extra_delta32 &= 0xFFFFFFFF;
685 }
686
687 if (extra_delta_offset64)
688 if (get_msr(cpu, extra_delta_offset64, &t->extra_delta64))
689 return -5;
690
691 if (extra_msr_offset32) {
692 if (get_msr(cpu, extra_msr_offset32, &t->extra_msr32))
693 return -5;
694 t->extra_msr32 &= 0xFFFFFFFF;
695 }
696
697 if (extra_msr_offset64)
698 if (get_msr(cpu, extra_msr_offset64, &t->extra_msr64))
634 return -5; 699 return -5;
635 700
636 /* collect core counters only for 1st thread in core */ 701 /* collect core counters only for 1st thread in core */
@@ -677,6 +742,9 @@ void print_verbose_header(void)
677 742
678 get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr); 743 get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr);
679 744
745 if (verbose > 1)
746 fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr);
747
680 ratio = (msr >> 40) & 0xFF; 748 ratio = (msr >> 40) & 0xFF;
681 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", 749 fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n",
682 ratio, bclk, ratio * bclk); 750 ratio, bclk, ratio * bclk);
@@ -685,14 +753,84 @@ void print_verbose_header(void)
685 fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n", 753 fprintf(stderr, "%d * %.0f = %.0f MHz TSC frequency\n",
686 ratio, bclk, ratio * bclk); 754 ratio, bclk, ratio * bclk);
687 755
756 if (!do_ivt_turbo_ratio_limit)
757 goto print_nhm_turbo_ratio_limits;
758
759 get_msr(0, MSR_IVT_TURBO_RATIO_LIMIT, &msr);
760
688 if (verbose > 1) 761 if (verbose > 1)
689 fprintf(stderr, "MSR_NEHALEM_PLATFORM_INFO: 0x%llx\n", msr); 762 fprintf(stderr, "MSR_IVT_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
763
764 ratio = (msr >> 56) & 0xFF;
765 if (ratio)
766 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 16 active cores\n",
767 ratio, bclk, ratio * bclk);
768
769 ratio = (msr >> 48) & 0xFF;
770 if (ratio)
771 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 15 active cores\n",
772 ratio, bclk, ratio * bclk);
773
774 ratio = (msr >> 40) & 0xFF;
775 if (ratio)
776 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 14 active cores\n",
777 ratio, bclk, ratio * bclk);
778
779 ratio = (msr >> 32) & 0xFF;
780 if (ratio)
781 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 13 active cores\n",
782 ratio, bclk, ratio * bclk);
783
784 ratio = (msr >> 24) & 0xFF;
785 if (ratio)
786 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 12 active cores\n",
787 ratio, bclk, ratio * bclk);
788
789 ratio = (msr >> 16) & 0xFF;
790 if (ratio)
791 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 11 active cores\n",
792 ratio, bclk, ratio * bclk);
793
794 ratio = (msr >> 8) & 0xFF;
795 if (ratio)
796 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 10 active cores\n",
797 ratio, bclk, ratio * bclk);
798
799 ratio = (msr >> 0) & 0xFF;
800 if (ratio)
801 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 9 active cores\n",
802 ratio, bclk, ratio * bclk);
803
804print_nhm_turbo_ratio_limits:
690 805
691 if (!do_nehalem_turbo_ratio_limit) 806 if (!do_nehalem_turbo_ratio_limit)
692 return; 807 return;
693 808
694 get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr); 809 get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr);
695 810
811 if (verbose > 1)
812 fprintf(stderr, "MSR_NEHALEM_TURBO_RATIO_LIMIT: 0x%llx\n", msr);
813
814 ratio = (msr >> 56) & 0xFF;
815 if (ratio)
816 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 8 active cores\n",
817 ratio, bclk, ratio * bclk);
818
819 ratio = (msr >> 48) & 0xFF;
820 if (ratio)
821 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 7 active cores\n",
822 ratio, bclk, ratio * bclk);
823
824 ratio = (msr >> 40) & 0xFF;
825 if (ratio)
826 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 6 active cores\n",
827 ratio, bclk, ratio * bclk);
828
829 ratio = (msr >> 32) & 0xFF;
830 if (ratio)
831 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 5 active cores\n",
832 ratio, bclk, ratio * bclk);
833
696 ratio = (msr >> 24) & 0xFF; 834 ratio = (msr >> 24) & 0xFF;
697 if (ratio) 835 if (ratio)
698 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n", 836 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 4 active cores\n",
@@ -712,7 +850,6 @@ void print_verbose_header(void)
712 if (ratio) 850 if (ratio)
713 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n", 851 fprintf(stderr, "%d * %.0f = %.0f MHz max turbo 1 active cores\n",
714 ratio, bclk, ratio * bclk); 852 ratio, bclk, ratio * bclk);
715
716} 853}
717 854
718void free_all_buffers(void) 855void free_all_buffers(void)
@@ -1038,7 +1175,7 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1038 case 0x2A: /* SNB */ 1175 case 0x2A: /* SNB */
1039 case 0x2D: /* SNB Xeon */ 1176 case 0x2D: /* SNB Xeon */
1040 case 0x3A: /* IVB */ 1177 case 0x3A: /* IVB */
1041 case 0x3D: /* IVB Xeon */ 1178 case 0x3E: /* IVB Xeon */
1042 return 1; 1179 return 1;
1043 case 0x2E: /* Nehalem-EX Xeon - Beckton */ 1180 case 0x2E: /* Nehalem-EX Xeon - Beckton */
1044 case 0x2F: /* Westmere-EX Xeon - Eagleton */ 1181 case 0x2F: /* Westmere-EX Xeon - Eagleton */
@@ -1046,6 +1183,22 @@ int has_nehalem_turbo_ratio_limit(unsigned int family, unsigned int model)
1046 return 0; 1183 return 0;
1047 } 1184 }
1048} 1185}
1186int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
1187{
1188 if (!genuine_intel)
1189 return 0;
1190
1191 if (family != 6)
1192 return 0;
1193
1194 switch (model) {
1195 case 0x3E: /* IVB Xeon */
1196 return 1;
1197 default:
1198 return 0;
1199 }
1200}
1201
1049 1202
1050int is_snb(unsigned int family, unsigned int model) 1203int is_snb(unsigned int family, unsigned int model)
1051{ 1204{
@@ -1056,7 +1209,7 @@ int is_snb(unsigned int family, unsigned int model)
1056 case 0x2A: 1209 case 0x2A:
1057 case 0x2D: 1210 case 0x2D:
1058 case 0x3A: /* IVB */ 1211 case 0x3A: /* IVB */
1059 case 0x3D: /* IVB Xeon */ 1212 case 0x3E: /* IVB Xeon */
1060 return 1; 1213 return 1;
1061 } 1214 }
1062 return 0; 1215 return 0;
@@ -1145,12 +1298,13 @@ void check_cpuid()
1145 bclk = discover_bclk(family, model); 1298 bclk = discover_bclk(family, model);
1146 1299
1147 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); 1300 do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model);
1301 do_ivt_turbo_ratio_limit = has_ivt_turbo_ratio_limit(family, model);
1148} 1302}
1149 1303
1150 1304
1151void usage() 1305void usage()
1152{ 1306{
1153 fprintf(stderr, "%s: [-v] [-M MSR#] [-i interval_sec | command ...]\n", 1307 fprintf(stderr, "%s: [-v][-p|-P|-S][-c MSR# | -s]][-C MSR#][-m MSR#][-M MSR#][-i interval_sec | command ...]\n",
1154 progname); 1308 progname);
1155 exit(1); 1309 exit(1);
1156} 1310}
@@ -1440,15 +1594,15 @@ void cmdline(int argc, char **argv)
1440 1594
1441 progname = argv[0]; 1595 progname = argv[0];
1442 1596
1443 while ((opt = getopt(argc, argv, "+cpsvi:M:")) != -1) { 1597 while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) {
1444 switch (opt) { 1598 switch (opt) {
1445 case 'c': 1599 case 'p':
1446 show_core_only++; 1600 show_core_only++;
1447 break; 1601 break;
1448 case 'p': 1602 case 'P':
1449 show_pkg_only++; 1603 show_pkg_only++;
1450 break; 1604 break;
1451 case 's': 1605 case 'S':
1452 summary_only++; 1606 summary_only++;
1453 break; 1607 break;
1454 case 'v': 1608 case 'v':
@@ -1457,10 +1611,20 @@ void cmdline(int argc, char **argv)
1457 case 'i': 1611 case 'i':
1458 interval_sec = atoi(optarg); 1612 interval_sec = atoi(optarg);
1459 break; 1613 break;
1614 case 'c':
1615 sscanf(optarg, "%x", &extra_delta_offset32);
1616 break;
1617 case 's':
1618 extra_delta_offset32 = 0x34; /* SMI counter */
1619 break;
1620 case 'C':
1621 sscanf(optarg, "%x", &extra_delta_offset64);
1622 break;
1623 case 'm':
1624 sscanf(optarg, "%x", &extra_msr_offset32);
1625 break;
1460 case 'M': 1626 case 'M':
1461 sscanf(optarg, "%x", &extra_msr_offset); 1627 sscanf(optarg, "%x", &extra_msr_offset64);
1462 if (verbose > 1)
1463 fprintf(stderr, "MSR 0x%X\n", extra_msr_offset);
1464 break; 1628 break;
1465 default: 1629 default:
1466 usage(); 1630 usage();
@@ -1473,7 +1637,7 @@ int main(int argc, char **argv)
1473 cmdline(argc, argv); 1637 cmdline(argc, argv);
1474 1638
1475 if (verbose > 1) 1639 if (verbose > 1)
1476 fprintf(stderr, "turbostat v2.0 May 16, 2012" 1640 fprintf(stderr, "turbostat v2.1 October 6, 2012"
1477 " - Len Brown <lenb@kernel.org>\n"); 1641 " - Len Brown <lenb@kernel.org>\n");
1478 1642
1479 turbostat_init(); 1643 turbostat_init();
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index c05bcd293d8c..c7ba7614061b 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -1740,8 +1740,10 @@ sub install {
1740 open(IN, "$output_config") or dodie("Can't read config file"); 1740 open(IN, "$output_config") or dodie("Can't read config file");
1741 while (<IN>) { 1741 while (<IN>) {
1742 if (/CONFIG_MODULES(=y)?/) { 1742 if (/CONFIG_MODULES(=y)?/) {
1743 $install_mods = 1 if (defined($1)); 1743 if (defined($1)) {
1744 last; 1744 $install_mods = 1;
1745 last;
1746 }
1745 } 1747 }
1746 } 1748 }
1747 close(IN); 1749 close(IN);
@@ -1873,10 +1875,10 @@ sub make_oldconfig {
1873 apply_min_config; 1875 apply_min_config;
1874 } 1876 }
1875 1877
1876 if (!run_command "$make oldnoconfig") { 1878 if (!run_command "$make olddefconfig") {
1877 # Perhaps oldnoconfig doesn't exist in this version of the kernel 1879 # Perhaps olddefconfig doesn't exist in this version of the kernel
1878 # try a yes '' | oldconfig 1880 # try a yes '' | oldconfig
1879 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1881 doprint "olddefconfig failed, trying yes '' | make oldconfig\n";
1880 run_command "yes '' | $make oldconfig" or 1882 run_command "yes '' | $make oldconfig" or
1881 dodie "failed make config oldconfig"; 1883 dodie "failed make config oldconfig";
1882 } 1884 }
@@ -1929,7 +1931,7 @@ sub build {
1929 1931
1930 # old config can ask questions 1932 # old config can ask questions
1931 if ($type eq "oldconfig") { 1933 if ($type eq "oldconfig") {
1932 $type = "oldnoconfig"; 1934 $type = "olddefconfig";
1933 1935
1934 # allow for empty configs 1936 # allow for empty configs
1935 run_command "touch $output_config"; 1937 run_command "touch $output_config";
@@ -1959,7 +1961,7 @@ sub build {
1959 load_force_config($minconfig); 1961 load_force_config($minconfig);
1960 } 1962 }
1961 1963
1962 if ($type ne "oldnoconfig") { 1964 if ($type ne "olddefconfig") {
1963 run_command "$make $type" or 1965 run_command "$make $type" or
1964 dodie "failed make config"; 1966 dodie "failed make config";
1965 } 1967 }
@@ -2458,8 +2460,7 @@ my %config_set;
2458 2460
2459# config_off holds the set of configs that the bad config had disabled. 2461# config_off holds the set of configs that the bad config had disabled.
2460# We need to record them and set them in the .config when running 2462# We need to record them and set them in the .config when running
2461# oldnoconfig, because oldnoconfig does not turn off new symbols, but 2463# olddefconfig, because olddefconfig keeps the defaults.
2462# instead just keeps the defaults.
2463my %config_off; 2464my %config_off;
2464 2465
2465# config_off_tmp holds a set of configs to turn off for now 2466# config_off_tmp holds a set of configs to turn off for now
@@ -3250,7 +3251,7 @@ sub test_this_config {
3250 } 3251 }
3251 3252
3252 # Remove this config from the list of configs 3253 # Remove this config from the list of configs
3253 # do a make oldnoconfig and then read the resulting 3254 # do a make olddefconfig and then read the resulting
3254 # .config to make sure it is missing the config that 3255 # .config to make sure it is missing the config that
3255 # we had before 3256 # we had before
3256 my %configs = %min_configs; 3257 my %configs = %min_configs;
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 85baf11e2acd..43480149119e 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -1,4 +1,4 @@
1TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug 1TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll
2 2
3all: 3all:
4 for TARGET in $(TARGETS); do \ 4 for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile
new file mode 100644
index 000000000000..19806ed62f50
--- /dev/null
+++ b/tools/testing/selftests/epoll/Makefile
@@ -0,0 +1,11 @@
1# Makefile for epoll selftests
2
3all: test_epoll
4%: %.c
5 gcc -pthread -g -o $@ $^
6
7run_tests: all
8 ./test_epoll
9
10clean:
11 $(RM) test_epoll
diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c
new file mode 100644
index 000000000000..f7525392ce84
--- /dev/null
+++ b/tools/testing/selftests/epoll/test_epoll.c
@@ -0,0 +1,344 @@
1/*
2 * tools/testing/selftests/epoll/test_epoll.c
3 *
4 * Copyright 2012 Adobe Systems Incorporated
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Paton J. Lewis <palewis@adobe.com>
12 *
13 */
14
15#include <errno.h>
16#include <fcntl.h>
17#include <pthread.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <unistd.h>
21#include <sys/epoll.h>
22#include <sys/socket.h>
23
24/*
25 * A pointer to an epoll_item_private structure will be stored in the epoll
26 * item's event structure so that we can get access to the epoll_item_private
27 * data after calling epoll_wait:
28 */
29struct epoll_item_private {
30 int index; /* Position of this struct within the epoll_items array. */
31 int fd;
32 uint32_t events;
33 pthread_mutex_t mutex; /* Guards the following variables... */
34 int stop;
35 int status; /* Stores any error encountered while handling item. */
36 /* The following variable allows us to test whether we have encountered
37 a problem while attempting to cancel and delete the associated
38 event. When the test program exits, 'deleted' should be exactly
39 one. If it is greater than one, then the failed test reflects a real
40 world situation where we would have tried to access the epoll item's
41 private data after deleting it: */
42 int deleted;
43};
44
45struct epoll_item_private *epoll_items;
46
47/*
48 * Delete the specified item from the epoll set. In a real-world secneario this
49 * is where we would free the associated data structure, but in this testing
50 * environment we retain the structure so that we can test for double-deletion:
51 */
52void delete_item(int index)
53{
54 __sync_fetch_and_add(&epoll_items[index].deleted, 1);
55}
56
57/*
58 * A pointer to a read_thread_data structure will be passed as the argument to
59 * each read thread:
60 */
61struct read_thread_data {
62 int stop;
63 int status; /* Indicates any error encountered by the read thread. */
64 int epoll_set;
65};
66
67/*
68 * The function executed by the read threads:
69 */
70void *read_thread_function(void *function_data)
71{
72 struct read_thread_data *thread_data =
73 (struct read_thread_data *)function_data;
74 struct epoll_event event_data;
75 struct epoll_item_private *item_data;
76 char socket_data;
77
78 /* Handle events until we encounter an error or this thread's 'stop'
79 condition is set: */
80 while (1) {
81 int result = epoll_wait(thread_data->epoll_set,
82 &event_data,
83 1, /* Number of desired events */
84 1000); /* Timeout in ms */
85 if (result < 0) {
86 /* Breakpoints signal all threads. Ignore that while
87 debugging: */
88 if (errno == EINTR)
89 continue;
90 thread_data->status = errno;
91 return 0;
92 } else if (thread_data->stop)
93 return 0;
94 else if (result == 0) /* Timeout */
95 continue;
96
97 /* We need the mutex here because checking for the stop
98 condition and re-enabling the epoll item need to be done
99 together as one atomic operation when EPOLL_CTL_DISABLE is
100 available: */
101 item_data = (struct epoll_item_private *)event_data.data.ptr;
102 pthread_mutex_lock(&item_data->mutex);
103
104 /* Remove the item from the epoll set if we want to stop
105 handling that event: */
106 if (item_data->stop)
107 delete_item(item_data->index);
108 else {
109 /* Clear the data that was written to the other end of
110 our non-blocking socket: */
111 do {
112 if (read(item_data->fd, &socket_data, 1) < 1) {
113 if ((errno == EAGAIN) ||
114 (errno == EWOULDBLOCK))
115 break;
116 else
117 goto error_unlock;
118 }
119 } while (item_data->events & EPOLLET);
120
121 /* The item was one-shot, so re-enable it: */
122 event_data.events = item_data->events;
123 if (epoll_ctl(thread_data->epoll_set,
124 EPOLL_CTL_MOD,
125 item_data->fd,
126 &event_data) < 0)
127 goto error_unlock;
128 }
129
130 pthread_mutex_unlock(&item_data->mutex);
131 }
132
133error_unlock:
134 thread_data->status = item_data->status = errno;
135 pthread_mutex_unlock(&item_data->mutex);
136 return 0;
137}
138
139/*
140 * A pointer to a write_thread_data structure will be passed as the argument to
141 * the write thread:
142 */
143struct write_thread_data {
144 int stop;
145 int status; /* Indicates any error encountered by the write thread. */
146 int n_fds;
147 int *fds;
148};
149
150/*
151 * The function executed by the write thread. It writes a single byte to each
152 * socket in turn until the stop condition for this thread is set. If writing to
153 * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for
154 * the moment and just move on to the next socket in the list. We don't care
155 * about the order in which we deliver events to the epoll set. In fact we don't
156 * care about the data we're writing to the pipes at all; we just want to
157 * trigger epoll events:
158 */
159void *write_thread_function(void *function_data)
160{
161 const char data = 'X';
162 int index;
163 struct write_thread_data *thread_data =
164 (struct write_thread_data *)function_data;
165 while (!thread_data->stop)
166 for (index = 0;
167 !thread_data->stop && (index < thread_data->n_fds);
168 ++index)
169 if ((write(thread_data->fds[index], &data, 1) < 1) &&
170 (errno != EAGAIN) &&
171 (errno != EWOULDBLOCK)) {
172 thread_data->status = errno;
173 return;
174 }
175}
176
177/*
178 * Arguments are currently ignored:
179 */
180int main(int argc, char **argv)
181{
182 const int n_read_threads = 100;
183 const int n_epoll_items = 500;
184 int index;
185 int epoll_set = epoll_create1(0);
186 struct write_thread_data write_thread_data = {
187 0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int))
188 };
189 struct read_thread_data *read_thread_data =
190 malloc(n_read_threads * sizeof(struct read_thread_data));
191 pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t));
192 pthread_t write_thread;
193
194 printf("-----------------\n");
195 printf("Runing test_epoll\n");
196 printf("-----------------\n");
197
198 epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private));
199
200 if (epoll_set < 0 || epoll_items == 0 || write_thread_data.fds == 0 ||
201 read_thread_data == 0 || read_threads == 0)
202 goto error;
203
204 if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
205 printf("Error: please run this test on a multi-core system.\n");
206 goto error;
207 }
208
209 /* Create the socket pairs and epoll items: */
210 for (index = 0; index < n_epoll_items; ++index) {
211 int socket_pair[2];
212 struct epoll_event event_data;
213 if (socketpair(AF_UNIX,
214 SOCK_STREAM | SOCK_NONBLOCK,
215 0,
216 socket_pair) < 0)
217 goto error;
218 write_thread_data.fds[index] = socket_pair[0];
219 epoll_items[index].index = index;
220 epoll_items[index].fd = socket_pair[1];
221 if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0)
222 goto error;
223 /* We always use EPOLLONESHOT because this test is currently
224 structured to demonstrate the need for EPOLL_CTL_DISABLE,
225 which only produces useful information in the EPOLLONESHOT
226 case (without EPOLLONESHOT, calling epoll_ctl with
227 EPOLL_CTL_DISABLE will never return EBUSY). If support for
228 testing events without EPOLLONESHOT is desired, it should
229 probably be implemented in a separate unit test. */
230 epoll_items[index].events = EPOLLIN | EPOLLONESHOT;
231 if (index < n_epoll_items / 2)
232 epoll_items[index].events |= EPOLLET;
233 epoll_items[index].stop = 0;
234 epoll_items[index].status = 0;
235 epoll_items[index].deleted = 0;
236 event_data.events = epoll_items[index].events;
237 event_data.data.ptr = &epoll_items[index];
238 if (epoll_ctl(epoll_set,
239 EPOLL_CTL_ADD,
240 epoll_items[index].fd,
241 &event_data) < 0)
242 goto error;
243 }
244
245 /* Create and start the read threads: */
246 for (index = 0; index < n_read_threads; ++index) {
247 read_thread_data[index].stop = 0;
248 read_thread_data[index].status = 0;
249 read_thread_data[index].epoll_set = epoll_set;
250 if (pthread_create(&read_threads[index],
251 NULL,
252 read_thread_function,
253 &read_thread_data[index]) != 0)
254 goto error;
255 }
256
257 if (pthread_create(&write_thread,
258 NULL,
259 write_thread_function,
260 &write_thread_data) != 0)
261 goto error;
262
263 /* Cancel all event pollers: */
264#ifdef EPOLL_CTL_DISABLE
265 for (index = 0; index < n_epoll_items; ++index) {
266 pthread_mutex_lock(&epoll_items[index].mutex);
267 ++epoll_items[index].stop;
268 if (epoll_ctl(epoll_set,
269 EPOLL_CTL_DISABLE,
270 epoll_items[index].fd,
271 NULL) == 0)
272 delete_item(index);
273 else if (errno != EBUSY) {
274 pthread_mutex_unlock(&epoll_items[index].mutex);
275 goto error;
276 }
277 /* EBUSY means events were being handled; allow the other thread
278 to delete the item. */
279 pthread_mutex_unlock(&epoll_items[index].mutex);
280 }
281#else
282 for (index = 0; index < n_epoll_items; ++index) {
283 pthread_mutex_lock(&epoll_items[index].mutex);
284 ++epoll_items[index].stop;
285 pthread_mutex_unlock(&epoll_items[index].mutex);
286 /* Wait in case a thread running read_thread_function is
287 currently executing code between epoll_wait and
288 pthread_mutex_lock with this item. Note that a longer delay
289 would make double-deletion less likely (at the expense of
290 performance), but there is no guarantee that any delay would
291 ever be sufficient. Note also that we delete all event
292 pollers at once for testing purposes, but in a real-world
293 environment we are likely to want to be able to cancel event
294 pollers at arbitrary times. Therefore we can't improve this
295 situation by just splitting this loop into two loops
296 (i.e. signal 'stop' for all items, sleep, and then delete all
297 items). We also can't fix the problem via EPOLL_CTL_DEL
298 because that command can't prevent the case where some other
299 thread is executing read_thread_function within the region
300 mentioned above: */
301 usleep(1);
302 pthread_mutex_lock(&epoll_items[index].mutex);
303 if (!epoll_items[index].deleted)
304 delete_item(index);
305 pthread_mutex_unlock(&epoll_items[index].mutex);
306 }
307#endif
308
309 /* Shut down the read threads: */
310 for (index = 0; index < n_read_threads; ++index)
311 __sync_fetch_and_add(&read_thread_data[index].stop, 1);
312 for (index = 0; index < n_read_threads; ++index) {
313 if (pthread_join(read_threads[index], NULL) != 0)
314 goto error;
315 if (read_thread_data[index].status)
316 goto error;
317 }
318
319 /* Shut down the write thread: */
320 __sync_fetch_and_add(&write_thread_data.stop, 1);
321 if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status)
322 goto error;
323
324 /* Check for final error conditions: */
325 for (index = 0; index < n_epoll_items; ++index) {
326 if (epoll_items[index].status != 0)
327 goto error;
328 if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0)
329 goto error;
330 }
331 for (index = 0; index < n_epoll_items; ++index)
332 if (epoll_items[index].deleted != 1) {
333 printf("Error: item data deleted %1d times.\n",
334 epoll_items[index].deleted);
335 goto error;
336 }
337
338 printf("[PASS]\n");
339 return 0;
340
341 error:
342 printf("[FAIL]\n");
343 return errno;
344}
diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c
index b0adb2710c02..68d0734b2081 100644
--- a/tools/usb/testusb.c
+++ b/tools/usb/testusb.c
@@ -253,9 +253,6 @@ static int find_testdev(const char *name, const struct stat *sb, int flag)
253 253
254 if (flag != FTW_F) 254 if (flag != FTW_F)
255 return 0; 255 return 0;
256 /* ignore /proc/bus/usb/{devices,drivers} */
257 if (strrchr(name, '/')[1] == 'd')
258 return 0;
259 256
260 fd = fopen(name, "rb"); 257 fd = fopen(name, "rb");
261 if (!fd) { 258 if (!fd) {
@@ -356,28 +353,8 @@ restart:
356 353
357static const char *usbfs_dir_find(void) 354static const char *usbfs_dir_find(void)
358{ 355{
359 static char usbfs_path_0[] = "/dev/usb/devices";
360 static char usbfs_path_1[] = "/proc/bus/usb/devices";
361 static char udev_usb_path[] = "/dev/bus/usb"; 356 static char udev_usb_path[] = "/dev/bus/usb";
362 357
363 static char *const usbfs_paths[] = {
364 usbfs_path_0, usbfs_path_1
365 };
366
367 static char *const *
368 end = usbfs_paths + sizeof usbfs_paths / sizeof *usbfs_paths;
369
370 char *const *it = usbfs_paths;
371 do {
372 int fd = open(*it, O_RDONLY);
373 close(fd);
374 if (fd >= 0) {
375 strrchr(*it, '/')[0] = '\0';
376 return *it;
377 }
378 } while (++it != end);
379
380 /* real device-nodes managed by udev */
381 if (access(udev_usb_path, F_OK) == 0) 358 if (access(udev_usb_path, F_OK) == 0)
382 return udev_usb_path; 359 return udev_usb_path;
383 360
@@ -489,7 +466,7 @@ usage:
489 goto usage; 466 goto usage;
490 if (!all && !device) { 467 if (!all && !device) {
491 fprintf (stderr, "must specify '-a' or '-D dev', " 468 fprintf (stderr, "must specify '-a' or '-D dev', "
492 "or DEVICE=/proc/bus/usb/BBB/DDD in env\n"); 469 "or DEVICE=/dev/bus/usb/BBB/DDD in env\n");
493 goto usage; 470 goto usage;
494 } 471 }
495 472
diff --git a/tools/virtio/virtio-trace/Makefile b/tools/virtio/virtio-trace/Makefile
new file mode 100644
index 000000000000..0d2381633475
--- /dev/null
+++ b/tools/virtio/virtio-trace/Makefile
@@ -0,0 +1,13 @@
1CC = gcc
2CFLAGS = -O2 -Wall -pthread
3
4all: trace-agent
5
6.c.o:
7 $(CC) $(CFLAGS) -c $^ -o $@
8
9trace-agent: trace-agent.o trace-agent-ctl.o trace-agent-rw.o
10 $(CC) $(CFLAGS) -o $@ $^
11
12clean:
13 rm -f *.o trace-agent
diff --git a/tools/virtio/virtio-trace/README b/tools/virtio/virtio-trace/README
new file mode 100644
index 000000000000..b64845b823ab
--- /dev/null
+++ b/tools/virtio/virtio-trace/README
@@ -0,0 +1,118 @@
1Trace Agent for virtio-trace
2============================
3
4Trace agent is a user tool for sending trace data of a guest to a Host in low
5overhead. Trace agent has the following functions:
6 - splice a page of ring-buffer to read_pipe without memory copying
7 - splice the page from write_pipe to virtio-console without memory copying
8 - write trace data to stdout by using -o option
9 - controlled by start/stop orders from a Host
10
11The trace agent operates as follows:
12 1) Initialize all structures.
13 2) Create a read/write thread per CPU. Each thread is bound to a CPU.
14 The read/write threads hold it.
15 3) A controller thread does poll() for a start order of a host.
16 4) After the controller of the trace agent receives a start order from a host,
17 the controller wake read/write threads.
18 5) The read/write threads start to read trace data from ring-buffers and
19 write the data to virtio-serial.
20 6) If the controller receives a stop order from a host, the read/write threads
21 stop to read trace data.
22
23
24Files
25=====
26
27README: this file
28Makefile: Makefile of trace agent for virtio-trace
29trace-agent.c: includes main function, sets up for operating trace agent
30trace-agent.h: includes all structures and some macros
31trace-agent-ctl.c: includes controller function for read/write threads
32trace-agent-rw.c: includes read/write threads function
33
34
35Setup
36=====
37
38To use this trace agent for virtio-trace, we need to prepare some virtio-serial
39I/Fs.
40
411) Make FIFO in a host
42 virtio-trace uses virtio-serial pipe as trace data paths as to the number
43of CPUs and a control path, so FIFO (named pipe) should be created as follows:
44 # mkdir /tmp/virtio-trace/
45 # mkfifo /tmp/virtio-trace/trace-path-cpu{0,1,2,...,X}.{in,out}
46 # mkfifo /tmp/virtio-trace/agent-ctl-path.{in,out}
47
48For example, if a guest use three CPUs, the names are
49 trace-path-cpu{0,1,2}.{in.out}
50and
51 agent-ctl-path.{in,out}.
52
532) Set up of virtio-serial pipe in a host
54 Add qemu option to use virtio-serial pipe.
55
56 ##virtio-serial device##
57 -device virtio-serial-pci,id=virtio-serial0\
58 ##control path##
59 -chardev pipe,id=charchannel0,path=/tmp/virtio-trace/agent-ctl-path\
60 -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,\
61 id=channel0,name=agent-ctl-path\
62 ##data path##
63 -chardev pipe,id=charchannel1,path=/tmp/virtio-trace/trace-path-cpu0\
64 -device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel0,\
65 id=channel1,name=trace-path-cpu0\
66 ...
67
68If you manage guests with libvirt, add the following tags to domain XML files.
69Then, libvirt passes the same command option to qemu.
70
71 <channel type='pipe'>
72 <source path='/tmp/virtio-trace/agent-ctl-path'/>
73 <target type='virtio' name='agent-ctl-path'/>
74 <address type='virtio-serial' controller='0' bus='0' port='0'/>
75 </channel>
76 <channel type='pipe'>
77 <source path='/tmp/virtio-trace/trace-path-cpu0'/>
78 <target type='virtio' name='trace-path-cpu0'/>
79 <address type='virtio-serial' controller='0' bus='0' port='1'/>
80 </channel>
81 ...
82Here, chardev names are restricted to trace-path-cpuX and agent-ctl-path. For
83example, if a guest use three CPUs, chardev names should be trace-path-cpu0,
84trace-path-cpu1, trace-path-cpu2, and agent-ctl-path.
85
863) Boot the guest
87 You can find some chardev in /dev/virtio-ports/ in the guest.
88
89
90Run
91===
92
930) Build trace agent in a guest
94 $ make
95
961) Enable ftrace in the guest
97 <Example>
98 # echo 1 > /sys/kernel/debug/tracing/events/sched/enable
99
1002) Run trace agent in the guest
101 This agent must be operated as root.
102 # ./trace-agent
103read/write threads in the agent wait for start order from host. If you add -o
104option, trace data are output via stdout in the guest.
105
1063) Open FIFO in a host
107 # cat /tmp/virtio-trace/trace-path-cpu0.out
108If a host does not open these, trace data get stuck in buffers of virtio. Then,
109the guest will stop by specification of chardev in QEMU. This blocking mode may
110be solved in the future.
111
1124) Start to read trace data by ordering from a host
113 A host injects read start order to the guest via virtio-serial.
114 # echo 1 > /tmp/virtio-trace/agent-ctl-path.in
115
1165) Stop to read trace data by ordering from a host
117 A host injects read stop order to the guest via virtio-serial.
118 # echo 0 > /tmp/virtio-trace/agent-ctl-path.in
diff --git a/tools/virtio/virtio-trace/trace-agent-ctl.c b/tools/virtio/virtio-trace/trace-agent-ctl.c
new file mode 100644
index 000000000000..a2d0403c4f94
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent-ctl.c
@@ -0,0 +1,137 @@
1/*
2 * Controller of read/write threads for virtio-trace
3 *
4 * Copyright (C) 2012 Hitachi, Ltd.
5 * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
6 * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
7 *
8 * Licensed under GPL version 2 only.
9 *
10 */
11
12#define _GNU_SOURCE
13#include <fcntl.h>
14#include <poll.h>
15#include <signal.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
19#include "trace-agent.h"
20
21#define HOST_MSG_SIZE 256
22#define EVENT_WAIT_MSEC 100
23
24static volatile sig_atomic_t global_signal_val;
25bool global_sig_receive; /* default false */
26bool global_run_operation; /* default false*/
27
28/* Handle SIGTERM/SIGINT/SIGQUIT to exit */
29static void signal_handler(int sig)
30{
31 global_signal_val = sig;
32}
33
34int rw_ctl_init(const char *ctl_path)
35{
36 int ctl_fd;
37
38 ctl_fd = open(ctl_path, O_RDONLY);
39 if (ctl_fd == -1) {
40 pr_err("Cannot open ctl_fd\n");
41 goto error;
42 }
43
44 return ctl_fd;
45
46error:
47 exit(EXIT_FAILURE);
48}
49
50static int wait_order(int ctl_fd)
51{
52 struct pollfd poll_fd;
53 int ret = 0;
54
55 while (!global_sig_receive) {
56 poll_fd.fd = ctl_fd;
57 poll_fd.events = POLLIN;
58
59 ret = poll(&poll_fd, 1, EVENT_WAIT_MSEC);
60
61 if (global_signal_val) {
62 global_sig_receive = true;
63 pr_info("Receive interrupt %d\n", global_signal_val);
64
65 /* Wakes rw-threads when they are sleeping */
66 if (!global_run_operation)
67 pthread_cond_broadcast(&cond_wakeup);
68
69 ret = -1;
70 break;
71 }
72
73 if (ret < 0) {
74 pr_err("Polling error\n");
75 goto error;
76 }
77
78 if (ret)
79 break;
80 };
81
82 return ret;
83
84error:
85 exit(EXIT_FAILURE);
86}
87
88/*
89 * contol read/write threads by handling global_run_operation
90 */
91void *rw_ctl_loop(int ctl_fd)
92{
93 ssize_t rlen;
94 char buf[HOST_MSG_SIZE];
95 int ret;
96
97 /* Setup signal handlers */
98 signal(SIGTERM, signal_handler);
99 signal(SIGINT, signal_handler);
100 signal(SIGQUIT, signal_handler);
101
102 while (!global_sig_receive) {
103
104 ret = wait_order(ctl_fd);
105 if (ret < 0)
106 break;
107
108 rlen = read(ctl_fd, buf, sizeof(buf));
109 if (rlen < 0) {
110 pr_err("read data error in ctl thread\n");
111 goto error;
112 }
113
114 if (rlen == 2 && buf[0] == '1') {
115 /*
116 * If host writes '1' to a control path,
117 * this controller wakes all read/write threads.
118 */
119 global_run_operation = true;
120 pthread_cond_broadcast(&cond_wakeup);
121 pr_debug("Wake up all read/write threads\n");
122 } else if (rlen == 2 && buf[0] == '0') {
123 /*
124 * If host writes '0' to a control path, read/write
125 * threads will wait for notification from Host.
126 */
127 global_run_operation = false;
128 pr_debug("Stop all read/write threads\n");
129 } else
130 pr_info("Invalid host notification: %s\n", buf);
131 }
132
133 return NULL;
134
135error:
136 exit(EXIT_FAILURE);
137}
diff --git a/tools/virtio/virtio-trace/trace-agent-rw.c b/tools/virtio/virtio-trace/trace-agent-rw.c
new file mode 100644
index 000000000000..3aace5ea4842
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent-rw.c
@@ -0,0 +1,192 @@
1/*
2 * Read/write thread of a guest agent for virtio-trace
3 *
4 * Copyright (C) 2012 Hitachi, Ltd.
5 * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
6 * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
7 *
8 * Licensed under GPL version 2 only.
9 *
10 */
11
12#define _GNU_SOURCE
13#include <fcntl.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include <sys/syscall.h>
18#include "trace-agent.h"
19
20#define READ_WAIT_USEC 100000
21
22void *rw_thread_info_new(void)
23{
24 struct rw_thread_info *rw_ti;
25
26 rw_ti = zalloc(sizeof(struct rw_thread_info));
27 if (rw_ti == NULL) {
28 pr_err("rw_thread_info zalloc error\n");
29 exit(EXIT_FAILURE);
30 }
31
32 rw_ti->cpu_num = -1;
33 rw_ti->in_fd = -1;
34 rw_ti->out_fd = -1;
35 rw_ti->read_pipe = -1;
36 rw_ti->write_pipe = -1;
37 rw_ti->pipe_size = PIPE_INIT;
38
39 return rw_ti;
40}
41
42void *rw_thread_init(int cpu, const char *in_path, const char *out_path,
43 bool stdout_flag, unsigned long pipe_size,
44 struct rw_thread_info *rw_ti)
45{
46 int data_pipe[2];
47
48 rw_ti->cpu_num = cpu;
49
50 /* set read(input) fd */
51 rw_ti->in_fd = open(in_path, O_RDONLY);
52 if (rw_ti->in_fd == -1) {
53 pr_err("Could not open in_fd (CPU:%d)\n", cpu);
54 goto error;
55 }
56
57 /* set write(output) fd */
58 if (!stdout_flag) {
59 /* virtio-serial output mode */
60 rw_ti->out_fd = open(out_path, O_WRONLY);
61 if (rw_ti->out_fd == -1) {
62 pr_err("Could not open out_fd (CPU:%d)\n", cpu);
63 goto error;
64 }
65 } else
66 /* stdout mode */
67 rw_ti->out_fd = STDOUT_FILENO;
68
69 if (pipe2(data_pipe, O_NONBLOCK) < 0) {
70 pr_err("Could not create pipe in rw-thread(%d)\n", cpu);
71 goto error;
72 }
73
74 /*
75 * Size of pipe is 64kB in default based on fs/pipe.c.
76 * To read/write trace data speedy, pipe size is changed.
77 */
78 if (fcntl(*data_pipe, F_SETPIPE_SZ, pipe_size) < 0) {
79 pr_err("Could not change pipe size in rw-thread(%d)\n", cpu);
80 goto error;
81 }
82
83 rw_ti->read_pipe = data_pipe[1];
84 rw_ti->write_pipe = data_pipe[0];
85 rw_ti->pipe_size = pipe_size;
86
87 return NULL;
88
89error:
90 exit(EXIT_FAILURE);
91}
92
93/* Bind a thread to a cpu */
94static void bind_cpu(int cpu_num)
95{
96 cpu_set_t mask;
97
98 CPU_ZERO(&mask);
99 CPU_SET(cpu_num, &mask);
100
101 /* bind my thread to cpu_num by assigning zero to the first argument */
102 if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
103 pr_err("Could not set CPU#%d affinity\n", (int)cpu_num);
104}
105
106static void *rw_thread_main(void *thread_info)
107{
108 ssize_t rlen, wlen;
109 ssize_t ret;
110 struct rw_thread_info *ts = (struct rw_thread_info *)thread_info;
111
112 bind_cpu(ts->cpu_num);
113
114 while (1) {
115 /* Wait for a read order of trace data by Host OS */
116 if (!global_run_operation) {
117 pthread_mutex_lock(&mutex_notify);
118 pthread_cond_wait(&cond_wakeup, &mutex_notify);
119 pthread_mutex_unlock(&mutex_notify);
120 }
121
122 if (global_sig_receive)
123 break;
124
125 /*
126 * Each thread read trace_pipe_raw of each cpu bounding the
127 * thread, so contention of multi-threads does not occur.
128 */
129 rlen = splice(ts->in_fd, NULL, ts->read_pipe, NULL,
130 ts->pipe_size, SPLICE_F_MOVE | SPLICE_F_MORE);
131
132 if (rlen < 0) {
133 pr_err("Splice_read in rw-thread(%d)\n", ts->cpu_num);
134 goto error;
135 } else if (rlen == 0) {
136 /*
137 * If trace data do not exist or are unreadable not
138 * for exceeding the page size, splice_read returns
139 * NULL. Then, this waits for being filled the data in a
140 * ring-buffer.
141 */
142 usleep(READ_WAIT_USEC);
143 pr_debug("Read retry(cpu:%d)\n", ts->cpu_num);
144 continue;
145 }
146
147 wlen = 0;
148
149 do {
150 ret = splice(ts->write_pipe, NULL, ts->out_fd, NULL,
151 rlen - wlen,
152 SPLICE_F_MOVE | SPLICE_F_MORE);
153
154 if (ret < 0) {
155 pr_err("Splice_write in rw-thread(%d)\n",
156 ts->cpu_num);
157 goto error;
158 } else if (ret == 0)
159 /*
160 * When host reader is not in time for reading
161 * trace data, guest will be stopped. This is
162 * because char dev in QEMU is not supported
163 * non-blocking mode. Then, writer might be
164 * sleep in that case.
165 * This sleep will be removed by supporting
166 * non-blocking mode.
167 */
168 sleep(1);
169 wlen += ret;
170 } while (wlen < rlen);
171 }
172
173 return NULL;
174
175error:
176 exit(EXIT_FAILURE);
177}
178
179
180pthread_t rw_thread_run(struct rw_thread_info *rw_ti)
181{
182 int ret;
183 pthread_t rw_thread_per_cpu;
184
185 ret = pthread_create(&rw_thread_per_cpu, NULL, rw_thread_main, rw_ti);
186 if (ret != 0) {
187 pr_err("Could not create a rw thread(%d)\n", rw_ti->cpu_num);
188 exit(EXIT_FAILURE);
189 }
190
191 return rw_thread_per_cpu;
192}
diff --git a/tools/virtio/virtio-trace/trace-agent.c b/tools/virtio/virtio-trace/trace-agent.c
new file mode 100644
index 000000000000..0a0a7dd4eff7
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent.c
@@ -0,0 +1,270 @@
1/*
2 * Guest agent for virtio-trace
3 *
4 * Copyright (C) 2012 Hitachi, Ltd.
5 * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
6 * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
7 *
8 * Licensed under GPL version 2 only.
9 *
10 */
11
12#define _GNU_SOURCE
13#include <limits.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include "trace-agent.h"
18
19#define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
20#define PIPE_DEF_BUFS 16
21#define PIPE_MIN_SIZE (PAGE_SIZE*PIPE_DEF_BUFS)
22#define PIPE_MAX_SIZE (1024*1024)
23#define READ_PATH_FMT \
24 "/sys/kernel/debug/tracing/per_cpu/cpu%d/trace_pipe_raw"
25#define WRITE_PATH_FMT "/dev/virtio-ports/trace-path-cpu%d"
26#define CTL_PATH "/dev/virtio-ports/agent-ctl-path"
27
28pthread_mutex_t mutex_notify = PTHREAD_MUTEX_INITIALIZER;
29pthread_cond_t cond_wakeup = PTHREAD_COND_INITIALIZER;
30
31static int get_total_cpus(void)
32{
33 int nr_cpus = (int)sysconf(_SC_NPROCESSORS_CONF);
34
35 if (nr_cpus <= 0) {
36 pr_err("Could not read cpus\n");
37 goto error;
38 } else if (nr_cpus > MAX_CPUS) {
39 pr_err("Exceed max cpus(%d)\n", (int)MAX_CPUS);
40 goto error;
41 }
42
43 return nr_cpus;
44
45error:
46 exit(EXIT_FAILURE);
47}
48
49static void *agent_info_new(void)
50{
51 struct agent_info *s;
52 int i;
53
54 s = zalloc(sizeof(struct agent_info));
55 if (s == NULL) {
56 pr_err("agent_info zalloc error\n");
57 exit(EXIT_FAILURE);
58 }
59
60 s->pipe_size = PIPE_INIT;
61 s->use_stdout = false;
62 s->cpus = get_total_cpus();
63 s->ctl_fd = -1;
64
65 /* read/write threads init */
66 for (i = 0; i < s->cpus; i++)
67 s->rw_ti[i] = rw_thread_info_new();
68
69 return s;
70}
71
72static unsigned long parse_size(const char *arg)
73{
74 unsigned long value, round;
75 char *ptr;
76
77 value = strtoul(arg, &ptr, 10);
78 switch (*ptr) {
79 case 'K': case 'k':
80 value <<= 10;
81 break;
82 case 'M': case 'm':
83 value <<= 20;
84 break;
85 default:
86 break;
87 }
88
89 if (value > PIPE_MAX_SIZE) {
90 pr_err("Pipe size must be less than 1MB\n");
91 goto error;
92 } else if (value < PIPE_MIN_SIZE) {
93 pr_err("Pipe size must be over 64KB\n");
94 goto error;
95 }
96
97 /* Align buffer size with page unit */
98 round = value & (PAGE_SIZE - 1);
99 value = value - round;
100
101 return value;
102error:
103 return 0;
104}
105
106static void usage(char const *prg)
107{
108 pr_err("usage: %s [-h] [-o] [-s <size of pipe>]\n", prg);
109}
110
111static const char *make_path(int cpu_num, bool this_is_write_path)
112{
113 int ret;
114 char *buf;
115
116 buf = zalloc(PATH_MAX);
117 if (buf == NULL) {
118 pr_err("Could not allocate buffer\n");
119 goto error;
120 }
121
122 if (this_is_write_path)
123 /* write(output) path */
124 ret = snprintf(buf, PATH_MAX, WRITE_PATH_FMT, cpu_num);
125 else
126 /* read(input) path */
127 ret = snprintf(buf, PATH_MAX, READ_PATH_FMT, cpu_num);
128
129 if (ret <= 0) {
130 pr_err("Failed to generate %s path(CPU#%d):%d\n",
131 this_is_write_path ? "read" : "write", cpu_num, ret);
132 goto error;
133 }
134
135 return buf;
136
137error:
138 free(buf);
139 return NULL;
140}
141
142static const char *make_input_path(int cpu_num)
143{
144 return make_path(cpu_num, false);
145}
146
147static const char *make_output_path(int cpu_num)
148{
149 return make_path(cpu_num, true);
150}
151
152static void *agent_info_init(struct agent_info *s)
153{
154 int cpu;
155 const char *in_path = NULL;
156 const char *out_path = NULL;
157
158 /* init read/write threads */
159 for (cpu = 0; cpu < s->cpus; cpu++) {
160 /* set read(input) path per read/write thread */
161 in_path = make_input_path(cpu);
162 if (in_path == NULL)
163 goto error;
164
165 /* set write(output) path per read/write thread*/
166 if (!s->use_stdout) {
167 out_path = make_output_path(cpu);
168 if (out_path == NULL)
169 goto error;
170 } else
171 /* stdout mode */
172 pr_debug("stdout mode\n");
173
174 rw_thread_init(cpu, in_path, out_path, s->use_stdout,
175 s->pipe_size, s->rw_ti[cpu]);
176 }
177
178 /* init controller of read/write threads */
179 s->ctl_fd = rw_ctl_init((const char *)CTL_PATH);
180
181 return NULL;
182
183error:
184 exit(EXIT_FAILURE);
185}
186
187static void *parse_args(int argc, char *argv[], struct agent_info *s)
188{
189 int cmd;
190 unsigned long size;
191
192 while ((cmd = getopt(argc, argv, "hos:")) != -1) {
193 switch (cmd) {
194 /* stdout mode */
195 case 'o':
196 s->use_stdout = true;
197 break;
198 /* size of pipe */
199 case 's':
200 size = parse_size(optarg);
201 if (size == 0)
202 goto error;
203 s->pipe_size = size;
204 break;
205 case 'h':
206 default:
207 usage(argv[0]);
208 goto error;
209 }
210 }
211
212 agent_info_init(s);
213
214 return NULL;
215
216error:
217 exit(EXIT_FAILURE);
218}
219
220static void agent_main_loop(struct agent_info *s)
221{
222 int cpu;
223 pthread_t rw_thread_per_cpu[MAX_CPUS];
224
225 /* Start all read/write threads */
226 for (cpu = 0; cpu < s->cpus; cpu++)
227 rw_thread_per_cpu[cpu] = rw_thread_run(s->rw_ti[cpu]);
228
229 rw_ctl_loop(s->ctl_fd);
230
231 /* Finish all read/write threads */
232 for (cpu = 0; cpu < s->cpus; cpu++) {
233 int ret;
234
235 ret = pthread_join(rw_thread_per_cpu[cpu], NULL);
236 if (ret != 0) {
237 pr_err("pthread_join() error:%d (cpu %d)\n", ret, cpu);
238 exit(EXIT_FAILURE);
239 }
240 }
241}
242
243static void agent_info_free(struct agent_info *s)
244{
245 int i;
246
247 close(s->ctl_fd);
248 for (i = 0; i < s->cpus; i++) {
249 close(s->rw_ti[i]->in_fd);
250 close(s->rw_ti[i]->out_fd);
251 close(s->rw_ti[i]->read_pipe);
252 close(s->rw_ti[i]->write_pipe);
253 free(s->rw_ti[i]);
254 }
255 free(s);
256}
257
258int main(int argc, char *argv[])
259{
260 struct agent_info *s = NULL;
261
262 s = agent_info_new();
263 parse_args(argc, argv, s);
264
265 agent_main_loop(s);
266
267 agent_info_free(s);
268
269 return 0;
270}
diff --git a/tools/virtio/virtio-trace/trace-agent.h b/tools/virtio/virtio-trace/trace-agent.h
new file mode 100644
index 000000000000..8de79bfeaa73
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent.h
@@ -0,0 +1,75 @@
1#ifndef __TRACE_AGENT_H__
2#define __TRACE_AGENT_H__
3#include <pthread.h>
4#include <stdbool.h>
5
6#define MAX_CPUS 256
7#define PIPE_INIT (1024*1024)
8
9/*
10 * agent_info - structure managing total information of guest agent
11 * @pipe_size: size of pipe (default 1MB)
12 * @use_stdout: set to true when o option is added (default false)
13 * @cpus: total number of CPUs
14 * @ctl_fd: fd of control path, /dev/virtio-ports/agent-ctl-path
15 * @rw_ti: structure managing information of read/write threads
16 */
17struct agent_info {
18 unsigned long pipe_size;
19 bool use_stdout;
20 int cpus;
21 int ctl_fd;
22 struct rw_thread_info *rw_ti[MAX_CPUS];
23};
24
25/*
26 * rw_thread_info - structure managing a read/write thread a cpu
27 * @cpu_num: cpu number operating this read/write thread
28 * @in_fd: fd of reading trace data path in cpu_num
29 * @out_fd: fd of writing trace data path in cpu_num
30 * @read_pipe: fd of read pipe
31 * @write_pipe: fd of write pipe
32 * @pipe_size: size of pipe (default 1MB)
33 */
34struct rw_thread_info {
35 int cpu_num;
36 int in_fd;
37 int out_fd;
38 int read_pipe;
39 int write_pipe;
40 unsigned long pipe_size;
41};
42
43/* use for stopping rw threads */
44extern bool global_sig_receive;
45
46/* use for notification */
47extern bool global_run_operation;
48extern pthread_mutex_t mutex_notify;
49extern pthread_cond_t cond_wakeup;
50
51/* for controller of read/write threads */
52extern int rw_ctl_init(const char *ctl_path);
53extern void *rw_ctl_loop(int ctl_fd);
54
55/* for trace read/write thread */
56extern void *rw_thread_info_new(void);
57extern void *rw_thread_init(int cpu, const char *in_path, const char *out_path,
58 bool stdout_flag, unsigned long pipe_size,
59 struct rw_thread_info *rw_ti);
60extern pthread_t rw_thread_run(struct rw_thread_info *rw_ti);
61
62static inline void *zalloc(size_t size)
63{
64 return calloc(1, size);
65}
66
67#define pr_err(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
68#define pr_info(format, ...) fprintf(stdout, format, ## __VA_ARGS__)
69#ifdef DEBUG
70#define pr_debug(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
71#else
72#define pr_debug(format, ...) do {} while (0)
73#endif
74
75#endif /*__TRACE_AGENT_H__*/
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index f576971f6556..b76edf2f8333 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -34,8 +34,8 @@
34#include <sys/fcntl.h> 34#include <sys/fcntl.h>
35#include <sys/mount.h> 35#include <sys/mount.h>
36#include <sys/statfs.h> 36#include <sys/statfs.h>
37#include "../../include/linux/magic.h" 37#include "../../include/uapi/linux/magic.h"
38#include "../../include/linux/kernel-page-flags.h" 38#include "../../include/uapi/linux/kernel-page-flags.h"
39 39
40 40
41#ifndef MAX_PATH 41#ifndef MAX_PATH