aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile3
-rw-r--r--tools/build/Makefile.feature10
-rw-r--r--tools/build/feature/Makefile27
-rw-r--r--tools/build/feature/test-all.c5
-rw-r--r--tools/build/feature/test-bpf.c3
-rw-r--r--tools/build/feature/test-dwarf_getlocations.c12
-rw-r--r--tools/build/feature/test-libunwind-aarch64.c26
-rw-r--r--tools/build/feature/test-libunwind-arm.c27
-rw-r--r--tools/build/feature/test-libunwind-debug-frame-aarch64.c16
-rw-r--r--tools/build/feature/test-libunwind-debug-frame-arm.c16
-rw-r--r--tools/build/feature/test-libunwind-x86.c27
-rw-r--r--tools/build/feature/test-libunwind-x86_64.c27
-rw-r--r--tools/gpio/Makefile2
-rw-r--r--tools/gpio/lsgpio.c2
-rw-r--r--tools/lguest/lguest.c10
-rw-r--r--tools/lib/api/fs/fs.c13
-rw-r--r--tools/lib/api/fs/fs.h2
-rw-r--r--tools/lib/traceevent/parse-filter.c4
-rw-r--r--tools/net/bpf_jit_disasm.c3
-rw-r--r--tools/objtool/Documentation/stack-validation.txt38
-rw-r--r--tools/objtool/builtin-check.c97
-rw-r--r--tools/perf/Documentation/intel-pt.txt7
-rw-r--r--tools/perf/Documentation/itrace.txt8
-rw-r--r--tools/perf/Documentation/perf-annotate.txt2
-rw-r--r--tools/perf/Documentation/perf-diff.txt2
-rw-r--r--tools/perf/Documentation/perf-list.txt107
-rw-r--r--tools/perf/Documentation/perf-mem.txt8
-rw-r--r--tools/perf/Documentation/perf-record.txt13
-rw-r--r--tools/perf/Documentation/perf-report.txt4
-rw-r--r--tools/perf/Documentation/perf-sched.txt16
-rw-r--r--tools/perf/Documentation/perf-script.txt14
-rw-r--r--tools/perf/Documentation/perf-top.txt2
-rw-r--r--tools/perf/Documentation/perf-trace.txt32
-rw-r--r--tools/perf/Makefile.perf15
-rw-r--r--tools/perf/arch/powerpc/Makefile1
-rw-r--r--tools/perf/arch/powerpc/util/dwarf-regs.c40
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c43
-rw-r--r--tools/perf/arch/x86/Makefile23
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl376
-rwxr-xr-xtools/perf/arch/x86/entry/syscalls/syscalltbl.sh39
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c2
-rw-r--r--tools/perf/arch/x86/util/dwarf-regs.c8
-rw-r--r--tools/perf/arch/x86/util/intel-bts.c5
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c5
-rw-r--r--tools/perf/arch/x86/util/tsc.c32
-rw-r--r--tools/perf/arch/x86/util/tsc.h17
-rw-r--r--tools/perf/bench/futex-lock-pi.c2
-rw-r--r--tools/perf/bench/futex.h6
-rw-r--r--tools/perf/bench/mem-functions.c22
-rw-r--r--tools/perf/builtin-config.c39
-rw-r--r--tools/perf/builtin-diff.c4
-rw-r--r--tools/perf/builtin-help.c18
-rw-r--r--tools/perf/builtin-inject.c1
-rw-r--r--tools/perf/builtin-kmem.c2
-rw-r--r--tools/perf/builtin-kvm.c2
-rw-r--r--tools/perf/builtin-mem.c11
-rw-r--r--tools/perf/builtin-record.c267
-rw-r--r--tools/perf/builtin-report.c19
-rw-r--r--tools/perf/builtin-sched.c198
-rw-r--r--tools/perf/builtin-script.c124
-rw-r--r--tools/perf/builtin-stat.c15
-rw-r--r--tools/perf/builtin-top.c39
-rw-r--r--tools/perf/builtin-trace.c1085
-rw-r--r--tools/perf/config/Makefile11
-rw-r--r--tools/perf/jvmti/jvmti_agent.c43
-rw-r--r--tools/perf/perf.c16
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py52
-rw-r--r--tools/perf/tests/Build2
-rw-r--r--tools/perf/tests/backward-ring-buffer.c151
-rw-r--r--tools/perf/tests/bpf.c2
-rw-r--r--tools/perf/tests/builtin-test.c8
-rw-r--r--tools/perf/tests/code-reading.c2
-rw-r--r--tools/perf/tests/dso-data.c2
-rw-r--r--tools/perf/tests/event-times.c236
-rw-r--r--tools/perf/tests/event_update.c2
-rw-r--r--tools/perf/tests/hists_common.c2
-rw-r--r--tools/perf/tests/hists_cumulate.c4
-rw-r--r--tools/perf/tests/hists_filter.c2
-rw-r--r--tools/perf/tests/hists_link.c4
-rw-r--r--tools/perf/tests/hists_output.c4
-rw-r--r--tools/perf/tests/keep-tracking.c2
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c2
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c2
-rw-r--r--tools/perf/tests/perf-record.c2
-rw-r--r--tools/perf/tests/switch-tracking.c2
-rw-r--r--tools/perf/tests/tests.h2
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c11
-rw-r--r--tools/perf/trace/beauty/eventfd.c38
-rw-r--r--tools/perf/trace/beauty/flock.c31
-rw-r--r--tools/perf/trace/beauty/futex_op.c44
-rw-r--r--tools/perf/trace/beauty/mmap.c158
-rw-r--r--tools/perf/trace/beauty/mode_t.c68
-rw-r--r--tools/perf/trace/beauty/msg_flags.c62
-rw-r--r--tools/perf/trace/beauty/open_flags.c56
-rw-r--r--tools/perf/trace/beauty/perf_event_open.c43
-rw-r--r--tools/perf/trace/beauty/pid.c21
-rw-r--r--tools/perf/trace/beauty/sched_policy.c44
-rw-r--r--tools/perf/trace/beauty/seccomp.c52
-rw-r--r--tools/perf/trace/beauty/signum.c53
-rw-r--r--tools/perf/trace/beauty/socket_type.c60
-rw-r--r--tools/perf/trace/beauty/waitid_options.c26
-rw-r--r--tools/perf/ui/browsers/hists.c40
-rw-r--r--tools/perf/ui/gtk/hists.c2
-rw-r--r--tools/perf/ui/hist.c2
-rw-r--r--tools/perf/ui/stdio/hist.c3
-rw-r--r--tools/perf/util/Build8
-rw-r--r--tools/perf/util/annotate.c4
-rw-r--r--tools/perf/util/auxtrace.c7
-rw-r--r--tools/perf/util/auxtrace.h2
-rw-r--r--tools/perf/util/bpf-loader.c143
-rw-r--r--tools/perf/util/bpf-loader.h19
-rw-r--r--tools/perf/util/build-id.c36
-rw-r--r--tools/perf/util/cache.h19
-rw-r--r--tools/perf/util/call-path.c122
-rw-r--r--tools/perf/util/call-path.h77
-rw-r--r--tools/perf/util/callchain.c9
-rw-r--r--tools/perf/util/callchain.h9
-rw-r--r--tools/perf/util/config.c222
-rw-r--r--tools/perf/util/config.h26
-rw-r--r--tools/perf/util/cpumap.c12
-rw-r--r--tools/perf/util/cpumap.h2
-rw-r--r--tools/perf/util/data.c41
-rw-r--r--tools/perf/util/data.h11
-rw-r--r--tools/perf/util/db-export.c89
-rw-r--r--tools/perf/util/db-export.h3
-rw-r--r--tools/perf/util/dso.c4
-rw-r--r--tools/perf/util/dwarf-aux.c61
-rw-r--r--tools/perf/util/event.c13
-rw-r--r--tools/perf/util/event.h9
-rw-r--r--tools/perf/util/evlist.c174
-rw-r--r--tools/perf/util/evlist.h22
-rw-r--r--tools/perf/util/evsel.c164
-rw-r--r--tools/perf/util/evsel.h28
-rw-r--r--tools/perf/util/evsel_fprintf.c212
-rw-r--r--tools/perf/util/header.c33
-rw-r--r--tools/perf/util/help-unknown-cmd.c30
-rw-r--r--tools/perf/util/hist.c23
-rw-r--r--tools/perf/util/hist.h12
-rw-r--r--tools/perf/util/intel-bts.c5
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c2
-rw-r--r--tools/perf/util/intel-pt.c24
-rw-r--r--tools/perf/util/jitdump.c41
-rw-r--r--tools/perf/util/jitdump.h3
-rw-r--r--tools/perf/util/machine.c107
-rw-r--r--tools/perf/util/machine.h7
-rw-r--r--tools/perf/util/map.c16
-rw-r--r--tools/perf/util/ordered-events.c9
-rw-r--r--tools/perf/util/ordered-events.h1
-rw-r--r--tools/perf/util/parse-events.c62
-rw-r--r--tools/perf/util/pmu.c23
-rw-r--r--tools/perf/util/probe-event.c406
-rw-r--r--tools/perf/util/probe-event.h5
-rw-r--r--tools/perf/util/probe-file.c3
-rw-r--r--tools/perf/util/probe-finder.c36
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/quote.c36
-rw-r--r--tools/perf/util/quote.h2
-rw-r--r--tools/perf/util/rb_resort.h149
-rw-r--r--tools/perf/util/record.c5
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c126
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c47
-rw-r--r--tools/perf/util/session.c117
-rw-r--r--tools/perf/util/session.h12
-rw-r--r--tools/perf/util/sort.c38
-rw-r--r--tools/perf/util/sort.h7
-rw-r--r--tools/perf/util/stat.c4
-rw-r--r--tools/perf/util/strbuf.c93
-rw-r--r--tools/perf/util/strbuf.h25
-rw-r--r--tools/perf/util/symbol-elf.c20
-rw-r--r--tools/perf/util/symbol.c108
-rw-r--r--tools/perf/util/symbol.h19
-rw-r--r--tools/perf/util/symbol_fprintf.c71
-rw-r--r--tools/perf/util/syscalltbl.c134
-rw-r--r--tools/perf/util/syscalltbl.h20
-rw-r--r--tools/perf/util/thread-stack.c139
-rw-r--r--tools/perf/util/thread-stack.h31
-rw-r--r--tools/perf/util/thread.c21
-rw-r--r--tools/perf/util/thread.h8
-rw-r--r--tools/perf/util/thread_map.c22
-rw-r--r--tools/perf/util/thread_map.h3
-rw-r--r--tools/perf/util/tool.h1
-rw-r--r--tools/perf/util/trigger.h94
-rw-r--r--tools/perf/util/tsc.h21
-rw-r--r--tools/perf/util/unwind-libunwind.c25
-rw-r--r--tools/perf/util/util.c38
-rw-r--r--tools/perf/util/util.h15
-rw-r--r--tools/perf/util/wrapper.c29
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c47
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixmap.c2
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c24
-rw-r--r--tools/power/acpi/tools/acpidbg/acpidbg.c4
-rw-r--r--tools/power/acpi/tools/acpidump/Makefile1
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c13
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c3
-rw-r--r--tools/power/cpupower/Makefile12
-rw-r--r--tools/power/cpupower/bench/Makefile2
-rw-r--r--tools/power/cpupower/bench/README-BENCH2
-rw-r--r--tools/power/cpupower/bench/benchmark.c4
-rw-r--r--tools/power/cpupower/bench/parse.c20
-rw-r--r--tools/power/cpupower/bench/system.c3
-rw-r--r--tools/power/cpupower/lib/cpufreq.c550
-rw-r--r--tools/power/cpupower/lib/cpufreq.h59
-rw-r--r--tools/power/cpupower/lib/cpuidle.c380
-rw-r--r--tools/power/cpupower/lib/cpuidle.h23
-rw-r--r--tools/power/cpupower/lib/cpupower.c192
-rw-r--r--tools/power/cpupower/lib/cpupower.h35
-rw-r--r--tools/power/cpupower/lib/cpupower_intern.h5
-rw-r--r--tools/power/cpupower/lib/sysfs.c672
-rw-r--r--tools/power/cpupower/lib/sysfs.h31
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-info.12
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-set.12
-rw-r--r--tools/power/cpupower/man/cpupower-idle-info.12
-rw-r--r--tools/power/cpupower/man/cpupower-idle-set.12
-rw-r--r--tools/power/cpupower/utils/cpufreq-set.c8
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c32
-rw-r--r--tools/power/cpupower/utils/cpuidle-set.c26
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h26
-rw-r--r--tools/power/cpupower/utils/helpers/topology.c107
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c12
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/net/.gitignore1
-rw-r--r--tools/testing/selftests/net/Makefile2
-rw-r--r--tools/testing/selftests/net/reuseport_dualstack.c208
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/jitter.sh90
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh121
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh96
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck.sh5
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh59
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh24
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE042
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST1
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon2
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/TREE20
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/TREE5423
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh52
-rw-r--r--tools/testing/selftests/sigaltstack/Makefile8
-rw-r--r--tools/testing/selftests/sigaltstack/sas.c176
-rw-r--r--tools/testing/selftests/x86/Makefile1
-rw-r--r--tools/testing/selftests/x86/fsgsbase.c398
-rw-r--r--tools/testing/selftests/x86/ldt_gdt.c250
242 files changed, 8986 insertions, 3151 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 60c7e6c8ff17..6bf68fe7dd29 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -137,7 +137,8 @@ libsubcmd_clean:
137 $(call descend,lib/subcmd,clean) 137 $(call descend,lib/subcmd,clean)
138 138
139perf_clean: 139perf_clean:
140 $(call descend,$(@:_clean=),clean) 140 $(Q)mkdir -p $(PERF_O) .
141 $(Q)$(MAKE) --no-print-directory -C perf O=$(PERF_O) subdir= clean
141 142
142selftests_clean: 143selftests_clean:
143 $(call descend,testing/$(@:_clean=),clean) 144 $(call descend,testing/$(@:_clean=),clean)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 6b7707270aa3..57c8f98874e8 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -30,6 +30,7 @@ endef
30FEATURE_TESTS_BASIC := \ 30FEATURE_TESTS_BASIC := \
31 backtrace \ 31 backtrace \
32 dwarf \ 32 dwarf \
33 dwarf_getlocations \
33 fortify-source \ 34 fortify-source \
34 sync-compare-and-swap \ 35 sync-compare-and-swap \
35 glibc \ 36 glibc \
@@ -48,6 +49,10 @@ FEATURE_TESTS_BASIC := \
48 libslang \ 49 libslang \
49 libcrypto \ 50 libcrypto \
50 libunwind \ 51 libunwind \
52 libunwind-x86 \
53 libunwind-x86_64 \
54 libunwind-arm \
55 libunwind-aarch64 \
51 pthread-attr-setaffinity-np \ 56 pthread-attr-setaffinity-np \
52 stackprotector-all \ 57 stackprotector-all \
53 timerfd \ 58 timerfd \
@@ -68,7 +73,9 @@ FEATURE_TESTS_EXTRA := \
68 libbabeltrace \ 73 libbabeltrace \
69 liberty \ 74 liberty \
70 liberty-z \ 75 liberty-z \
71 libunwind-debug-frame 76 libunwind-debug-frame \
77 libunwind-debug-frame-arm \
78 libunwind-debug-frame-aarch64
72 79
73FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC) 80FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
74 81
@@ -78,6 +85,7 @@ endif
78 85
79FEATURE_DISPLAY ?= \ 86FEATURE_DISPLAY ?= \
80 dwarf \ 87 dwarf \
88 dwarf_getlocations \
81 glibc \ 89 glibc \
82 gtk2 \ 90 gtk2 \
83 libaudit \ 91 libaudit \
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index c5f4c417428d..3d88f09e188b 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -3,6 +3,7 @@ FILES= \
3 test-backtrace.bin \ 3 test-backtrace.bin \
4 test-bionic.bin \ 4 test-bionic.bin \
5 test-dwarf.bin \ 5 test-dwarf.bin \
6 test-dwarf_getlocations.bin \
6 test-fortify-source.bin \ 7 test-fortify-source.bin \
7 test-sync-compare-and-swap.bin \ 8 test-sync-compare-and-swap.bin \
8 test-glibc.bin \ 9 test-glibc.bin \
@@ -26,6 +27,12 @@ FILES= \
26 test-libcrypto.bin \ 27 test-libcrypto.bin \
27 test-libunwind.bin \ 28 test-libunwind.bin \
28 test-libunwind-debug-frame.bin \ 29 test-libunwind-debug-frame.bin \
30 test-libunwind-x86.bin \
31 test-libunwind-x86_64.bin \
32 test-libunwind-arm.bin \
33 test-libunwind-aarch64.bin \
34 test-libunwind-debug-frame-arm.bin \
35 test-libunwind-debug-frame-aarch64.bin \
29 test-pthread-attr-setaffinity-np.bin \ 36 test-pthread-attr-setaffinity-np.bin \
30 test-stackprotector-all.bin \ 37 test-stackprotector-all.bin \
31 test-timerfd.bin \ 38 test-timerfd.bin \
@@ -82,6 +89,9 @@ endif
82$(OUTPUT)test-dwarf.bin: 89$(OUTPUT)test-dwarf.bin:
83 $(BUILD) $(DWARFLIBS) 90 $(BUILD) $(DWARFLIBS)
84 91
92$(OUTPUT)test-dwarf_getlocations.bin:
93 $(BUILD) $(DWARFLIBS)
94
85$(OUTPUT)test-libelf-mmap.bin: 95$(OUTPUT)test-libelf-mmap.bin:
86 $(BUILD) -lelf 96 $(BUILD) -lelf
87 97
@@ -99,6 +109,23 @@ $(OUTPUT)test-libunwind.bin:
99 109
100$(OUTPUT)test-libunwind-debug-frame.bin: 110$(OUTPUT)test-libunwind-debug-frame.bin:
101 $(BUILD) -lelf 111 $(BUILD) -lelf
112$(OUTPUT)test-libunwind-x86.bin:
113 $(BUILD) -lelf -lunwind-x86
114
115$(OUTPUT)test-libunwind-x86_64.bin:
116 $(BUILD) -lelf -lunwind-x86_64
117
118$(OUTPUT)test-libunwind-arm.bin:
119 $(BUILD) -lelf -lunwind-arm
120
121$(OUTPUT)test-libunwind-aarch64.bin:
122 $(BUILD) -lelf -lunwind-aarch64
123
124$(OUTPUT)test-libunwind-debug-frame-arm.bin:
125 $(BUILD) -lelf -lunwind-arm
126
127$(OUTPUT)test-libunwind-debug-frame-aarch64.bin:
128 $(BUILD) -lelf -lunwind-aarch64
102 129
103$(OUTPUT)test-libaudit.bin: 130$(OUTPUT)test-libaudit.bin:
104 $(BUILD) -laudit 131 $(BUILD) -laudit
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index e499a36c1e4a..a282e8cb84f3 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -41,6 +41,10 @@
41# include "test-dwarf.c" 41# include "test-dwarf.c"
42#undef main 42#undef main
43 43
44#define main main_test_dwarf_getlocations
45# include "test-dwarf_getlocations.c"
46#undef main
47
44#define main main_test_libelf_getphdrnum 48#define main main_test_libelf_getphdrnum
45# include "test-libelf-getphdrnum.c" 49# include "test-libelf-getphdrnum.c"
46#undef main 50#undef main
@@ -143,6 +147,7 @@ int main(int argc, char *argv[])
143 main_test_libelf_mmap(); 147 main_test_libelf_mmap();
144 main_test_glibc(); 148 main_test_glibc();
145 main_test_dwarf(); 149 main_test_dwarf();
150 main_test_dwarf_getlocations();
146 main_test_libelf_getphdrnum(); 151 main_test_libelf_getphdrnum();
147 main_test_libunwind(); 152 main_test_libunwind();
148 main_test_libaudit(); 153 main_test_libaudit();
diff --git a/tools/build/feature/test-bpf.c b/tools/build/feature/test-bpf.c
index b389026839b9..e04ab89a1013 100644
--- a/tools/build/feature/test-bpf.c
+++ b/tools/build/feature/test-bpf.c
@@ -27,10 +27,9 @@ int main(void)
27 attr.log_level = 0; 27 attr.log_level = 0;
28 attr.kern_version = 0; 28 attr.kern_version = 0;
29 29
30 attr = attr;
31 /* 30 /*
32 * Test existence of __NR_bpf and BPF_PROG_LOAD. 31 * Test existence of __NR_bpf and BPF_PROG_LOAD.
33 * This call should fail if we run the testcase. 32 * This call should fail if we run the testcase.
34 */ 33 */
35 return syscall(__NR_bpf, BPF_PROG_LOAD, attr, sizeof(attr)); 34 return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
36} 35}
diff --git a/tools/build/feature/test-dwarf_getlocations.c b/tools/build/feature/test-dwarf_getlocations.c
new file mode 100644
index 000000000000..70162699dd43
--- /dev/null
+++ b/tools/build/feature/test-dwarf_getlocations.c
@@ -0,0 +1,12 @@
1#include <stdlib.h>
2#include <elfutils/libdw.h>
3
4int main(void)
5{
6 Dwarf_Addr base, start, end;
7 Dwarf_Attribute attr;
8 Dwarf_Op *op;
9 size_t nops;
10 ptrdiff_t offset = 0;
11 return (int)dwarf_getlocations(&attr, offset, &base, &start, &end, &op, &nops);
12}
diff --git a/tools/build/feature/test-libunwind-aarch64.c b/tools/build/feature/test-libunwind-aarch64.c
new file mode 100644
index 000000000000..fc03fb64e8c1
--- /dev/null
+++ b/tools/build/feature/test-libunwind-aarch64.c
@@ -0,0 +1,26 @@
1#include <libunwind-aarch64.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
11
12static unw_accessors_t accessors;
13
14int main(void)
15{
16 unw_addr_space_t addr_space;
17
18 addr_space = unw_create_addr_space(&accessors, 0);
19 if (addr_space)
20 return 0;
21
22 unw_init_remote(NULL, addr_space, NULL);
23 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
24
25 return 0;
26}
diff --git a/tools/build/feature/test-libunwind-arm.c b/tools/build/feature/test-libunwind-arm.c
new file mode 100644
index 000000000000..632d95ec641f
--- /dev/null
+++ b/tools/build/feature/test-libunwind-arm.c
@@ -0,0 +1,27 @@
1#include <libunwind-arm.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
diff --git a/tools/build/feature/test-libunwind-debug-frame-aarch64.c b/tools/build/feature/test-libunwind-debug-frame-aarch64.c
new file mode 100644
index 000000000000..22844673fc26
--- /dev/null
+++ b/tools/build/feature/test-libunwind-debug-frame-aarch64.c
@@ -0,0 +1,16 @@
1#include <libunwind-aarch64.h>
2#include <stdlib.h>
3
4extern int
5UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
6 unw_word_t ip, unw_word_t segbase,
7 const char *obj_name, unw_word_t start,
8 unw_word_t end);
9
10#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
11
12int main(void)
13{
14 dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
15 return 0;
16}
diff --git a/tools/build/feature/test-libunwind-debug-frame-arm.c b/tools/build/feature/test-libunwind-debug-frame-arm.c
new file mode 100644
index 000000000000..f98859684fee
--- /dev/null
+++ b/tools/build/feature/test-libunwind-debug-frame-arm.c
@@ -0,0 +1,16 @@
1#include <libunwind-arm.h>
2#include <stdlib.h>
3
4extern int
5UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
6 unw_word_t ip, unw_word_t segbase,
7 const char *obj_name, unw_word_t start,
8 unw_word_t end);
9
10#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
11
12int main(void)
13{
14 dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
15 return 0;
16}
diff --git a/tools/build/feature/test-libunwind-x86.c b/tools/build/feature/test-libunwind-x86.c
new file mode 100644
index 000000000000..3561edce305e
--- /dev/null
+++ b/tools/build/feature/test-libunwind-x86.c
@@ -0,0 +1,27 @@
1#include <libunwind-x86.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
diff --git a/tools/build/feature/test-libunwind-x86_64.c b/tools/build/feature/test-libunwind-x86_64.c
new file mode 100644
index 000000000000..5add2517b2a1
--- /dev/null
+++ b/tools/build/feature/test-libunwind-x86_64.c
@@ -0,0 +1,27 @@
1#include <libunwind-x86_64.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile
index 4d198d5c4203..c155d6bc47a7 100644
--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -1,5 +1,5 @@
1CC = $(CROSS_COMPILE)gcc 1CC = $(CROSS_COMPILE)gcc
2CFLAGS += -Wall -g -D_GNU_SOURCE 2CFLAGS += -O2 -Wall -g -D_GNU_SOURCE
3 3
4all: lsgpio 4all: lsgpio
5 5
diff --git a/tools/gpio/lsgpio.c b/tools/gpio/lsgpio.c
index 1124da375942..eb3f56efd215 100644
--- a/tools/gpio/lsgpio.c
+++ b/tools/gpio/lsgpio.c
@@ -147,7 +147,7 @@ void print_usage(void)
147 147
148int main(int argc, char **argv) 148int main(int argc, char **argv)
149{ 149{
150 const char *device_name; 150 const char *device_name = NULL;
151 int ret; 151 int ret;
152 int c; 152 int c;
153 153
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index 80159e6811c2..d9836c5eb694 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -3351,12 +3351,18 @@ int main(int argc, char *argv[])
3351 /* Boot protocol version: 2.07 supports the fields for lguest. */ 3351 /* Boot protocol version: 2.07 supports the fields for lguest. */
3352 boot->hdr.version = 0x207; 3352 boot->hdr.version = 0x207;
3353 3353
3354 /* The hardware_subarch value of "1" tells the Guest it's an lguest. */ 3354 /* X86_SUBARCH_LGUEST tells the Guest it's an lguest. */
3355 boot->hdr.hardware_subarch = 1; 3355 boot->hdr.hardware_subarch = X86_SUBARCH_LGUEST;
3356 3356
3357 /* Tell the entry path not to try to reload segment registers. */ 3357 /* Tell the entry path not to try to reload segment registers. */
3358 boot->hdr.loadflags |= KEEP_SEGMENTS; 3358 boot->hdr.loadflags |= KEEP_SEGMENTS;
3359 3359
3360 /* We don't support tboot: */
3361 boot->tboot_addr = 0;
3362
3363 /* Ensure this is 0 to prevent APM from loading: */
3364 boot->apm_bios_info.version = 0;
3365
3360 /* We tell the kernel to initialize the Guest. */ 3366 /* We tell the kernel to initialize the Guest. */
3361 tell_kernel(start); 3367 tell_kernel(start);
3362 3368
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index ef78c22ff44d..08556cf2c70d 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -351,6 +351,19 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
351 return err; 351 return err;
352} 352}
353 353
354int procfs__read_str(const char *entry, char **buf, size_t *sizep)
355{
356 char path[PATH_MAX];
357 const char *procfs = procfs__mountpoint();
358
359 if (!procfs)
360 return -1;
361
362 snprintf(path, sizeof(path), "%s/%s", procfs, entry);
363
364 return filename__read_str(path, buf, sizep);
365}
366
354int sysfs__read_ull(const char *entry, unsigned long long *value) 367int sysfs__read_ull(const char *entry, unsigned long long *value)
355{ 368{
356 char path[PATH_MAX]; 369 char path[PATH_MAX];
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index 9f6598098dc5..16c9c2ed7c5b 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -29,6 +29,8 @@ int filename__read_int(const char *filename, int *value);
29int filename__read_ull(const char *filename, unsigned long long *value); 29int filename__read_ull(const char *filename, unsigned long long *value);
30int filename__read_str(const char *filename, char **buf, size_t *sizep); 30int filename__read_str(const char *filename, char **buf, size_t *sizep);
31 31
32int procfs__read_str(const char *entry, char **buf, size_t *sizep);
33
32int sysctl__read_int(const char *sysctl, int *value); 34int sysctl__read_int(const char *sysctl, int *value);
33int sysfs__read_int(const char *entry, int *value); 35int sysfs__read_int(const char *entry, int *value);
34int sysfs__read_ull(const char *entry, unsigned long long *value); 36int sysfs__read_ull(const char *entry, unsigned long long *value);
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index 0144b3d1bb77..88cccea3ca99 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -1164,11 +1164,11 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1164 current_op = current_exp; 1164 current_op = current_exp;
1165 1165
1166 ret = collapse_tree(current_op, parg, error_str); 1166 ret = collapse_tree(current_op, parg, error_str);
1167 /* collapse_tree() may free current_op, and updates parg accordingly */
1168 current_op = NULL;
1167 if (ret < 0) 1169 if (ret < 0)
1168 goto fail; 1170 goto fail;
1169 1171
1170 *parg = current_op;
1171
1172 free(token); 1172 free(token);
1173 return 0; 1173 return 0;
1174 1174
diff --git a/tools/net/bpf_jit_disasm.c b/tools/net/bpf_jit_disasm.c
index 5b3241340945..544b05a53b70 100644
--- a/tools/net/bpf_jit_disasm.c
+++ b/tools/net/bpf_jit_disasm.c
@@ -98,6 +98,9 @@ static char *get_klog_buff(unsigned int *klen)
98 char *buff; 98 char *buff;
99 99
100 len = klogctl(CMD_ACTION_SIZE_BUFFER, NULL, 0); 100 len = klogctl(CMD_ACTION_SIZE_BUFFER, NULL, 0);
101 if (len < 0)
102 return NULL;
103
101 buff = malloc(len); 104 buff = malloc(len);
102 if (!buff) 105 if (!buff)
103 return NULL; 106 return NULL;
diff --git a/tools/objtool/Documentation/stack-validation.txt b/tools/objtool/Documentation/stack-validation.txt
index 5a95896105bc..55a60d331f47 100644
--- a/tools/objtool/Documentation/stack-validation.txt
+++ b/tools/objtool/Documentation/stack-validation.txt
@@ -299,18 +299,38 @@ they mean, and suggestions for how to fix them.
299Errors in .c files 299Errors in .c files
300------------------ 300------------------
301 301
302If you're getting an objtool error in a compiled .c file, chances are 3021. c_file.o: warning: objtool: funcA() falls through to next function funcB()
303the file uses an asm() statement which has a "call" instruction. An
304asm() statement with a call instruction must declare the use of the
305stack pointer in its output operand. For example, on x86_64:
306 303
307 register void *__sp asm("rsp"); 304 This means that funcA() doesn't end with a return instruction or an
308 asm volatile("call func" : "+r" (__sp)); 305 unconditional jump, and that objtool has determined that the function
306 can fall through into the next function. There could be different
307 reasons for this:
309 308
310Otherwise the stack frame may not get created before the call. 309 1) funcA()'s last instruction is a call to a "noreturn" function like
310 panic(). In this case the noreturn function needs to be added to
311 objtool's hard-coded global_noreturns array. Feel free to bug the
312 objtool maintainer, or you can submit a patch.
311 313
312Another possible cause for errors in C code is if the Makefile removes 314 2) funcA() uses the unreachable() annotation in a section of code
313-fno-omit-frame-pointer or adds -fomit-frame-pointer to the gcc options. 315 that is actually reachable.
316
317 3) If funcA() calls an inline function, the object code for funcA()
318 might be corrupt due to a gcc bug. For more details, see:
319 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70646
320
3212. If you're getting any other objtool error in a compiled .c file, it
322 may be because the file uses an asm() statement which has a "call"
323 instruction. An asm() statement with a call instruction must declare
324 the use of the stack pointer in its output operand. For example, on
325 x86_64:
326
327 register void *__sp asm("rsp");
328 asm volatile("call func" : "+r" (__sp));
329
330 Otherwise the stack frame may not get created before the call.
331
3323. Another possible cause for errors in C code is if the Makefile removes
333 -fno-omit-frame-pointer or adds -fomit-frame-pointer to the gcc options.
314 334
315Also see the above section for .S file errors for more information what 335Also see the above section for .S file errors for more information what
316the individual error messages mean. 336the individual error messages mean.
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 7515cb2e879a..e8a1e69eb92c 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -54,6 +54,7 @@ struct instruction {
54 struct symbol *call_dest; 54 struct symbol *call_dest;
55 struct instruction *jump_dest; 55 struct instruction *jump_dest;
56 struct list_head alts; 56 struct list_head alts;
57 struct symbol *func;
57}; 58};
58 59
59struct alternative { 60struct alternative {
@@ -66,6 +67,7 @@ struct objtool_file {
66 struct list_head insn_list; 67 struct list_head insn_list;
67 DECLARE_HASHTABLE(insn_hash, 16); 68 DECLARE_HASHTABLE(insn_hash, 16);
68 struct section *rodata, *whitelist; 69 struct section *rodata, *whitelist;
70 bool ignore_unreachables, c_file;
69}; 71};
70 72
71const char *objname; 73const char *objname;
@@ -228,7 +230,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
228 } 230 }
229 } 231 }
230 232
231 if (insn->type == INSN_JUMP_DYNAMIC) 233 if (insn->type == INSN_JUMP_DYNAMIC && list_empty(&insn->alts))
232 /* sibling call */ 234 /* sibling call */
233 return 0; 235 return 0;
234 } 236 }
@@ -248,6 +250,7 @@ static int dead_end_function(struct objtool_file *file, struct symbol *func)
248static int decode_instructions(struct objtool_file *file) 250static int decode_instructions(struct objtool_file *file)
249{ 251{
250 struct section *sec; 252 struct section *sec;
253 struct symbol *func;
251 unsigned long offset; 254 unsigned long offset;
252 struct instruction *insn; 255 struct instruction *insn;
253 int ret; 256 int ret;
@@ -281,6 +284,21 @@ static int decode_instructions(struct objtool_file *file)
281 hash_add(file->insn_hash, &insn->hash, insn->offset); 284 hash_add(file->insn_hash, &insn->hash, insn->offset);
282 list_add_tail(&insn->list, &file->insn_list); 285 list_add_tail(&insn->list, &file->insn_list);
283 } 286 }
287
288 list_for_each_entry(func, &sec->symbol_list, list) {
289 if (func->type != STT_FUNC)
290 continue;
291
292 if (!find_insn(file, sec, func->offset)) {
293 WARN("%s(): can't find starting instruction",
294 func->name);
295 return -1;
296 }
297
298 func_for_each_insn(file, func, insn)
299 if (!insn->func)
300 insn->func = func;
301 }
284 } 302 }
285 303
286 return 0; 304 return 0;
@@ -664,13 +682,40 @@ static int add_func_switch_tables(struct objtool_file *file,
664 text_rela->addend); 682 text_rela->addend);
665 683
666 /* 684 /*
667 * TODO: Document where this is needed, or get rid of it.
668 *
669 * rare case: jmpq *[addr](%rip) 685 * rare case: jmpq *[addr](%rip)
686 *
687 * This check is for a rare gcc quirk, currently only seen in
688 * three driver functions in the kernel, only with certain
689 * obscure non-distro configs.
690 *
691 * As part of an optimization, gcc makes a copy of an existing
692 * switch jump table, modifies it, and then hard-codes the jump
693 * (albeit with an indirect jump) to use a single entry in the
694 * table. The rest of the jump table and some of its jump
695 * targets remain as dead code.
696 *
697 * In such a case we can just crudely ignore all unreachable
698 * instruction warnings for the entire object file. Ideally we
699 * would just ignore them for the function, but that would
700 * require redesigning the code quite a bit. And honestly
701 * that's just not worth doing: unreachable instruction
702 * warnings are of questionable value anyway, and this is such
703 * a rare issue.
704 *
705 * kbuild reports:
706 * - https://lkml.kernel.org/r/201603231906.LWcVUpxm%25fengguang.wu@intel.com
707 * - https://lkml.kernel.org/r/201603271114.K9i45biy%25fengguang.wu@intel.com
708 * - https://lkml.kernel.org/r/201603291058.zuJ6ben1%25fengguang.wu@intel.com
709 *
710 * gcc bug:
711 * - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70604
670 */ 712 */
671 if (!rodata_rela) 713 if (!rodata_rela) {
672 rodata_rela = find_rela_by_dest(file->rodata, 714 rodata_rela = find_rela_by_dest(file->rodata,
673 text_rela->addend + 4); 715 text_rela->addend + 4);
716 if (rodata_rela)
717 file->ignore_unreachables = true;
718 }
674 719
675 if (!rodata_rela) 720 if (!rodata_rela)
676 continue; 721 continue;
@@ -732,9 +777,6 @@ static int decode_sections(struct objtool_file *file)
732{ 777{
733 int ret; 778 int ret;
734 779
735 file->whitelist = find_section_by_name(file->elf, "__func_stack_frame_non_standard");
736 file->rodata = find_section_by_name(file->elf, ".rodata");
737
738 ret = decode_instructions(file); 780 ret = decode_instructions(file);
739 if (ret) 781 if (ret)
740 return ret; 782 return ret;
@@ -799,6 +841,7 @@ static int validate_branch(struct objtool_file *file,
799 struct alternative *alt; 841 struct alternative *alt;
800 struct instruction *insn; 842 struct instruction *insn;
801 struct section *sec; 843 struct section *sec;
844 struct symbol *func = NULL;
802 unsigned char state; 845 unsigned char state;
803 int ret; 846 int ret;
804 847
@@ -813,6 +856,16 @@ static int validate_branch(struct objtool_file *file,
813 } 856 }
814 857
815 while (1) { 858 while (1) {
859 if (file->c_file && insn->func) {
860 if (func && func != insn->func) {
861 WARN("%s() falls through to next function %s()",
862 func->name, insn->func->name);
863 return 1;
864 }
865
866 func = insn->func;
867 }
868
816 if (insn->visited) { 869 if (insn->visited) {
817 if (frame_state(insn->state) != frame_state(state)) { 870 if (frame_state(insn->state) != frame_state(state)) {
818 WARN_FUNC("frame pointer state mismatch", 871 WARN_FUNC("frame pointer state mismatch",
@@ -823,13 +876,6 @@ static int validate_branch(struct objtool_file *file,
823 return 0; 876 return 0;
824 } 877 }
825 878
826 /*
827 * Catch a rare case where a noreturn function falls through to
828 * the next function.
829 */
830 if (is_fentry_call(insn) && (state & STATE_FENTRY))
831 return 0;
832
833 insn->visited = true; 879 insn->visited = true;
834 insn->state = state; 880 insn->state = state;
835 881
@@ -1035,12 +1081,8 @@ static int validate_functions(struct objtool_file *file)
1035 continue; 1081 continue;
1036 1082
1037 insn = find_insn(file, sec, func->offset); 1083 insn = find_insn(file, sec, func->offset);
1038 if (!insn) { 1084 if (!insn)
1039 WARN("%s(): can't find starting instruction",
1040 func->name);
1041 warnings++;
1042 continue; 1085 continue;
1043 }
1044 1086
1045 ret = validate_branch(file, insn, 0); 1087 ret = validate_branch(file, insn, 0);
1046 warnings += ret; 1088 warnings += ret;
@@ -1056,13 +1098,14 @@ static int validate_functions(struct objtool_file *file)
1056 if (insn->visited) 1098 if (insn->visited)
1057 continue; 1099 continue;
1058 1100
1059 if (!ignore_unreachable_insn(func, insn) &&
1060 !warnings) {
1061 WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
1062 warnings++;
1063 }
1064
1065 insn->visited = true; 1101 insn->visited = true;
1102
1103 if (file->ignore_unreachables || warnings ||
1104 ignore_unreachable_insn(func, insn))
1105 continue;
1106
1107 WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
1108 warnings++;
1066 } 1109 }
1067 } 1110 }
1068 } 1111 }
@@ -1133,6 +1176,10 @@ int cmd_check(int argc, const char **argv)
1133 1176
1134 INIT_LIST_HEAD(&file.insn_list); 1177 INIT_LIST_HEAD(&file.insn_list);
1135 hash_init(file.insn_hash); 1178 hash_init(file.insn_hash);
1179 file.whitelist = find_section_by_name(file.elf, "__func_stack_frame_non_standard");
1180 file.rodata = find_section_by_name(file.elf, ".rodata");
1181 file.ignore_unreachables = false;
1182 file.c_file = find_section_by_name(file.elf, ".comment");
1136 1183
1137 ret = decode_sections(&file); 1184 ret = decode_sections(&file);
1138 if (ret < 0) 1185 if (ret < 0)
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index be764f9ec769..c6c8318e38a2 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -672,6 +672,7 @@ The letters are:
672 d create a debug log 672 d create a debug log
673 g synthesize a call chain (use with i or x) 673 g synthesize a call chain (use with i or x)
674 l synthesize last branch entries (use with i or x) 674 l synthesize last branch entries (use with i or x)
675 s skip initial number of events
675 676
676"Instructions" events look like they were recorded by "perf record -e 677"Instructions" events look like they were recorded by "perf record -e
677instructions". 678instructions".
@@ -730,6 +731,12 @@ from one sample to the next.
730 731
731To disable trace decoding entirely, use the option --no-itrace. 732To disable trace decoding entirely, use the option --no-itrace.
732 733
734It is also possible to skip events generated (instructions, branches, transactions)
735at the beginning. This is useful to ignore initialization code.
736
737 --itrace=i0nss1000000
738
739skips the first million instructions.
733 740
734dump option 741dump option
735----------- 742-----------
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt
index 65453f4c7006..e2a4c5e0dbe5 100644
--- a/tools/perf/Documentation/itrace.txt
+++ b/tools/perf/Documentation/itrace.txt
@@ -7,6 +7,7 @@
7 d create a debug log 7 d create a debug log
8 g synthesize a call chain (use with i or x) 8 g synthesize a call chain (use with i or x)
9 l synthesize last branch entries (use with i or x) 9 l synthesize last branch entries (use with i or x)
10 s skip initial number of events
10 11
11 The default is all events i.e. the same as --itrace=ibxe 12 The default is all events i.e. the same as --itrace=ibxe
12 13
@@ -24,3 +25,10 @@
24 25
25 Also the number of last branch entries (default 64, max. 1024) for 26 Also the number of last branch entries (default 64, max. 1024) for
26 instructions or transactions events can be specified. 27 instructions or transactions events can be specified.
28
29 It is also possible to skip events generated (instructions, branches, transactions)
30 at the beginning. This is useful to ignore initialization code.
31
32 --itrace=i0nss1000000
33
34 skips the first million instructions.
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index e9cd39a92dc2..778f54d4d0bd 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -33,7 +33,7 @@ OPTIONS
33 33
34-f:: 34-f::
35--force:: 35--force::
36 Don't complain, do it. 36 Don't do ownership validation.
37 37
38-v:: 38-v::
39--verbose:: 39--verbose::
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index d1deb573877f..3e9490b9c533 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -75,7 +75,7 @@ OPTIONS
75 75
76-f:: 76-f::
77--force:: 77--force::
78 Don't complain, do it. 78 Don't do ownership validation.
79 79
80--symfs=<directory>:: 80--symfs=<directory>::
81 Look for files with symbols relative to this directory. 81 Look for files with symbols relative to this directory.
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index ec723d0a5bb3..a126e97a8114 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -93,6 +93,67 @@ raw encoding of 0x1A8 can be used:
93You should refer to the processor specific documentation for getting these 93You should refer to the processor specific documentation for getting these
94details. Some of them are referenced in the SEE ALSO section below. 94details. Some of them are referenced in the SEE ALSO section below.
95 95
96ARBITRARY PMUS
97--------------
98
99perf also supports an extended syntax for specifying raw parameters
100to PMUs. Using this typically requires looking up the specific event
101in the CPU vendor specific documentation.
102
103The available PMUs and their raw parameters can be listed with
104
105 ls /sys/devices/*/format
106
107For example the raw event "LSD.UOPS" core pmu event above could
108be specified as
109
110 perf stat -e cpu/event=0xa8,umask=0x1,name=LSD.UOPS_CYCLES,cmask=1/ ...
111
112PER SOCKET PMUS
113---------------
114
115Some PMUs are not associated with a core, but with a whole CPU socket.
116Events on these PMUs generally cannot be sampled, but only counted globally
117with perf stat -a. They can be bound to one logical CPU, but will measure
118all the CPUs in the same socket.
119
120This example measures memory bandwidth every second
121on the first memory controller on socket 0 of a Intel Xeon system
122
123 perf stat -C 0 -a uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/ -I 1000 ...
124
125Each memory controller has its own PMU. Measuring the complete system
126bandwidth would require specifying all imc PMUs (see perf list output),
127and adding the values together.
128
129This example measures the combined core power every second
130
131 perf stat -I 1000 -e power/energy-cores/ -a
132
133ACCESS RESTRICTIONS
134-------------------
135
136For non root users generally only context switched PMU events are available.
137This is normally only the events in the cpu PMU, the predefined events
138like cycles and instructions and some software events.
139
140Other PMUs and global measurements are normally root only.
141Some event qualifiers, such as "any", are also root only.
142
143This can be overriden by setting the kernel.perf_event_paranoid
144sysctl to -1, which allows non root to use these events.
145
146For accessing trace point events perf needs to have read access to
147/sys/kernel/debug/tracing, even when perf_event_paranoid is in a relaxed
148setting.
149
150TRACING
151-------
152
153Some PMUs control advanced hardware tracing capabilities, such as Intel PT,
154that allows low overhead execution tracing. These are described in a separate
155intel-pt.txt document.
156
96PARAMETERIZED EVENTS 157PARAMETERIZED EVENTS
97-------------------- 158--------------------
98 159
@@ -106,6 +167,50 @@ also be supplied. For example:
106 167
107 perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ... 168 perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ...
108 169
170EVENT GROUPS
171------------
172
173Perf supports time based multiplexing of events, when the number of events
174active exceeds the number of hardware performance counters. Multiplexing
175can cause measurement errors when the workload changes its execution
176profile.
177
178When metrics are computed using formulas from event counts, it is useful to
179ensure some events are always measured together as a group to minimize multiplexing
180errors. Event groups can be specified using { }.
181
182 perf stat -e '{instructions,cycles}' ...
183
184The number of available performance counters depend on the CPU. A group
185cannot contain more events than available counters.
186For example Intel Core CPUs typically have four generic performance counters
187for the core, plus three fixed counters for instructions, cycles and
188ref-cycles. Some special events have restrictions on which counter they
189can schedule, and may not support multiple instances in a single group.
190When too many events are specified in the group none of them will not
191be measured.
192
193Globally pinned events can limit the number of counters available for
194other groups. On x86 systems, the NMI watchdog pins a counter by default.
195The nmi watchdog can be disabled as root with
196
197 echo 0 > /proc/sys/kernel/nmi_watchdog
198
199Events from multiple different PMUs cannot be mixed in a group, with
200some exceptions for software events.
201
202LEADER SAMPLING
203---------------
204
205perf also supports group leader sampling using the :S specifier.
206
207 perf record -e '{cycles,instructions}:S' ...
208 perf report --group
209
210Normally all events in a event group sample, but with :S only
211the first event (the leader) samples, and it only reads the values of the
212other events in the group.
213
109OPTIONS 214OPTIONS
110------- 215-------
111 216
@@ -143,5 +248,5 @@ SEE ALSO
143-------- 248--------
144linkperf:perf-stat[1], linkperf:perf-top[1], 249linkperf:perf-stat[1], linkperf:perf-top[1],
145linkperf:perf-record[1], 250linkperf:perf-record[1],
146http://www.intel.com/Assets/PDF/manual/253669.pdf[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide], 251http://www.intel.com/sdm/[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide],
147http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming] 252http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming]
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 43310d8661fe..1d6092c460dd 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -48,6 +48,14 @@ OPTIONS
48 option can be passed in record mode. It will be interpreted the same way as perf 48 option can be passed in record mode. It will be interpreted the same way as perf
49 record. 49 record.
50 50
51-K::
52--all-kernel::
53 Configure all used events to run in kernel space.
54
55-U::
56--all-user::
57 Configure all used events to run in user space.
58
51SEE ALSO 59SEE ALSO
52-------- 60--------
53linkperf:perf-record[1], linkperf:perf-report[1] 61linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 19aa17532a16..8dbee832abd9 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -347,6 +347,19 @@ Configure all used events to run in kernel space.
347--all-user:: 347--all-user::
348Configure all used events to run in user space. 348Configure all used events to run in user space.
349 349
350--timestamp-filename
351Append timestamp to output file name.
352
353--switch-output::
354Generate multiple perf.data files, timestamp prefixed, switching to a new one
355when receiving a SIGUSR2.
356
357A possible use case is to, given an external event, slice the perf.data file
358that gets then processed, possibly via a perf script, to decide if that
359particular perf.data snapshot should be kept or not.
360
361Implies --timestamp-filename, --no-buildid and --no-buildid-cache.
362
350SEE ALSO 363SEE ALSO
351-------- 364--------
352linkperf:perf-stat[1], linkperf:perf-list[1] 365linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 12113992ac9d..ebaf849e30ef 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -248,7 +248,7 @@ OPTIONS
248 Note that when using the --itrace option the synthesized callchain size 248 Note that when using the --itrace option the synthesized callchain size
249 will override this value if the synthesized callchain size is bigger. 249 will override this value if the synthesized callchain size is bigger.
250 250
251 Default: 127 251 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
252 252
253-G:: 253-G::
254--inverted:: 254--inverted::
@@ -285,7 +285,7 @@ OPTIONS
285 285
286-f:: 286-f::
287--force:: 287--force::
288 Don't complain, do it. 288 Don't do ownership validation.
289 289
290--symfs=<directory>:: 290--symfs=<directory>::
291 Look for files with symbols relative to this directory. 291 Look for files with symbols relative to this directory.
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 8ff4df956951..1cc08cc47ac5 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -50,6 +50,22 @@ OPTIONS
50--dump-raw-trace=:: 50--dump-raw-trace=::
51 Display verbose dump of the sched data. 51 Display verbose dump of the sched data.
52 52
53OPTIONS for 'perf sched map'
54----------------------------
55
56--compact::
57 Show only CPUs with activity. Helps visualizing on high core
58 count systems.
59
60--cpus::
61 Show just entries with activities for the given CPUs.
62
63--color-cpus::
64 Highlight the given cpus.
65
66--color-pids::
67 Highlight the given pids.
68
53SEE ALSO 69SEE ALSO
54-------- 70--------
55linkperf:perf-record[1] 71linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 382ddfb45d1d..a856a1095893 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -259,9 +259,23 @@ include::itrace.txt[]
259--full-source-path:: 259--full-source-path::
260 Show the full path for source files for srcline output. 260 Show the full path for source files for srcline output.
261 261
262--max-stack::
263 Set the stack depth limit when parsing the callchain, anything
264 beyond the specified depth will be ignored. This is a trade-off
265 between information loss and faster processing especially for
266 workloads that can have a very long callchain stack.
267 Note that when using the --itrace option the synthesized callchain size
268 will override this value if the synthesized callchain size is bigger.
269
270 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
271
262--ns:: 272--ns::
263 Use 9 decimal places when displaying time (i.e. show the nanoseconds) 273 Use 9 decimal places when displaying time (i.e. show the nanoseconds)
264 274
275-f::
276--force::
277 Don't do ownership validation.
278
265SEE ALSO 279SEE ALSO
266-------- 280--------
267linkperf:perf-record[1], linkperf:perf-script-perl[1], 281linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 19f046f027cd..91d638df3a6b 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -177,7 +177,7 @@ Default is to monitor all CPUS.
177 between information loss and faster processing especially for 177 between information loss and faster processing especially for
178 workloads that can have a very long callchain stack. 178 workloads that can have a very long callchain stack.
179 179
180 Default: 127 180 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
181 181
182--ignore-callees=<regex>:: 182--ignore-callees=<regex>::
183 Ignore callees of the function(s) matching the given regex. 183 Ignore callees of the function(s) matching the given regex.
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 13293de8869f..6afe20121bc0 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -117,9 +117,41 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
117--syscalls:: 117--syscalls::
118 Trace system calls. This options is enabled by default. 118 Trace system calls. This options is enabled by default.
119 119
120--call-graph [mode,type,min[,limit],order[,key][,branch]]::
121 Setup and enable call-graph (stack chain/backtrace) recording.
122 See `--call-graph` section in perf-record and perf-report
123 man pages for details. The ones that are most useful in 'perf trace'
124 are 'dwarf' and 'lbr', where available, try: 'perf trace --call-graph dwarf'.
125
126 Using this will, for the root user, bump the value of --mmap-pages to 4
127 times the maximum for non-root users, based on the kernel.perf_event_mlock_kb
128 sysctl. This is done only if the user doesn't specify a --mmap-pages value.
129
130--kernel-syscall-graph::
131 Show the kernel callchains on the syscall exit path.
132
120--event:: 133--event::
121 Trace other events, see 'perf list' for a complete list. 134 Trace other events, see 'perf list' for a complete list.
122 135
136--max-stack::
137 Set the stack depth limit when parsing the callchain, anything
138 beyond the specified depth will be ignored. Note that at this point
139 this is just about the presentation part, i.e. the kernel is still
140 not limiting, the overhead of callchains needs to be set via the
141 knobs in --call-graph dwarf.
142
143 Implies '--call-graph dwarf' when --call-graph not present on the
144 command line, on systems where DWARF unwinding was built in.
145
146 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
147
148--min-stack::
149 Set the stack depth limit when parsing the callchain, anything
150 below the specified depth will be ignored. Disabled by default.
151
152 Implies '--call-graph dwarf' when --call-graph not present on the
153 command line, on systems where DWARF unwinding was built in.
154
123--proc-map-timeout:: 155--proc-map-timeout::
124 When processing pre-existing threads /proc/XXX/mmap, it may take a long time, 156 When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
125 because the file may be huge. A time out is needed in such cases. 157 because the file may be huge. A time out is needed in such cases.
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 000ea210389d..bde8cbae7dd9 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -183,6 +183,11 @@ endif
183include config/Makefile 183include config/Makefile
184endif 184endif
185 185
186ifeq ($(config),0)
187include $(srctree)/tools/scripts/Makefile.arch
188-include arch/$(ARCH)/Makefile
189endif
190
186# The FEATURE_DUMP_EXPORT holds location of the actual 191# The FEATURE_DUMP_EXPORT holds location of the actual
187# FEATURE_DUMP file to be used to bypass feature detection 192# FEATURE_DUMP file to be used to bypass feature detection
188# (for bpf or any other subproject) 193# (for bpf or any other subproject)
@@ -297,8 +302,6 @@ endif
297# because maintaining the nesting to match is a pain. If 302# because maintaining the nesting to match is a pain. If
298# we had "elif" things would have been much nicer... 303# we had "elif" things would have been much nicer...
299 304
300-include arch/$(ARCH)/Makefile
301
302ifneq ($(OUTPUT),) 305ifneq ($(OUTPUT),)
303 CFLAGS += -I$(OUTPUT) 306 CFLAGS += -I$(OUTPUT)
304endif 307endif
@@ -390,7 +393,7 @@ endif
390__build-dir = $(subst $(OUTPUT),,$(dir $@)) 393__build-dir = $(subst $(OUTPUT),,$(dir $@))
391build-dir = $(if $(__build-dir),$(__build-dir),.) 394build-dir = $(if $(__build-dir),$(__build-dir),.)
392 395
393prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep 396prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep archheaders
394 397
395$(OUTPUT)%.o: %.c prepare FORCE 398$(OUTPUT)%.o: %.c prepare FORCE
396 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 399 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -430,7 +433,7 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
430 433
431LIBPERF_IN := $(OUTPUT)libperf-in.o 434LIBPERF_IN := $(OUTPUT)libperf-in.o
432 435
433$(LIBPERF_IN): fixdep FORCE 436$(LIBPERF_IN): prepare fixdep FORCE
434 $(Q)$(MAKE) $(build)=libperf 437 $(Q)$(MAKE) $(build)=libperf
435 438
436$(LIB_FILE): $(LIBPERF_IN) 439$(LIB_FILE): $(LIBPERF_IN)
@@ -625,7 +628,7 @@ config-clean:
625 $(call QUIET_CLEAN, config) 628 $(call QUIET_CLEAN, config)
626 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null 629 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null
627 630
628clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean 631clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean
629 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) 632 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
630 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 633 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
631 $(Q)$(RM) $(OUTPUT).config-detected 634 $(Q)$(RM) $(OUTPUT).config-detected
@@ -662,5 +665,5 @@ FORCE:
662.PHONY: all install clean config-clean strip install-gtk 665.PHONY: all install clean config-clean strip install-gtk
663.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 666.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
664.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare 667.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare
665.PHONY: libtraceevent_plugins 668.PHONY: libtraceevent_plugins archheaders
666 669
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 56e05f126ad8..cc3930904d68 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -3,4 +3,5 @@ PERF_HAVE_DWARF_REGS := 1
3endif 3endif
4 4
5HAVE_KVM_STAT_SUPPORT := 1 5HAVE_KVM_STAT_SUPPORT := 1
6PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
6PERF_HAVE_JITDUMP := 1 7PERF_HAVE_JITDUMP := 1
diff --git a/tools/perf/arch/powerpc/util/dwarf-regs.c b/tools/perf/arch/powerpc/util/dwarf-regs.c
index 733151cdf46e..41bdf9530d82 100644
--- a/tools/perf/arch/powerpc/util/dwarf-regs.c
+++ b/tools/perf/arch/powerpc/util/dwarf-regs.c
@@ -10,19 +10,26 @@
10 */ 10 */
11 11
12#include <stddef.h> 12#include <stddef.h>
13#include <errno.h>
14#include <string.h>
13#include <dwarf-regs.h> 15#include <dwarf-regs.h>
14 16#include <linux/ptrace.h>
17#include <linux/kernel.h>
18#include "util.h"
15 19
16struct pt_regs_dwarfnum { 20struct pt_regs_dwarfnum {
17 const char *name; 21 const char *name;
18 unsigned int dwarfnum; 22 unsigned int dwarfnum;
23 unsigned int ptregs_offset;
19}; 24};
20 25
21#define STR(s) #s 26#define REG_DWARFNUM_NAME(r, num) \
22#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} 27 {.name = STR(%)STR(r), .dwarfnum = num, \
23#define GPR_DWARFNUM_NAME(num) \ 28 .ptregs_offset = offsetof(struct pt_regs, r)}
24 {.name = STR(%gpr##num), .dwarfnum = num} 29#define GPR_DWARFNUM_NAME(num) \
25#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} 30 {.name = STR(%gpr##num), .dwarfnum = num, \
31 .ptregs_offset = offsetof(struct pt_regs, gpr[num])}
32#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0, .ptregs_offset = 0}
26 33
27/* 34/*
28 * Reference: 35 * Reference:
@@ -61,12 +68,12 @@ static const struct pt_regs_dwarfnum regdwarfnum_table[] = {
61 GPR_DWARFNUM_NAME(29), 68 GPR_DWARFNUM_NAME(29),
62 GPR_DWARFNUM_NAME(30), 69 GPR_DWARFNUM_NAME(30),
63 GPR_DWARFNUM_NAME(31), 70 GPR_DWARFNUM_NAME(31),
64 REG_DWARFNUM_NAME("%msr", 66), 71 REG_DWARFNUM_NAME(msr, 66),
65 REG_DWARFNUM_NAME("%ctr", 109), 72 REG_DWARFNUM_NAME(ctr, 109),
66 REG_DWARFNUM_NAME("%link", 108), 73 REG_DWARFNUM_NAME(link, 108),
67 REG_DWARFNUM_NAME("%xer", 101), 74 REG_DWARFNUM_NAME(xer, 101),
68 REG_DWARFNUM_NAME("%dar", 119), 75 REG_DWARFNUM_NAME(dar, 119),
69 REG_DWARFNUM_NAME("%dsisr", 118), 76 REG_DWARFNUM_NAME(dsisr, 118),
70 REG_DWARFNUM_END, 77 REG_DWARFNUM_END,
71}; 78};
72 79
@@ -86,3 +93,12 @@ const char *get_arch_regstr(unsigned int n)
86 return roff->name; 93 return roff->name;
87 return NULL; 94 return NULL;
88} 95}
96
97int regs_query_register_offset(const char *name)
98{
99 const struct pt_regs_dwarfnum *roff;
100 for (roff = regdwarfnum_table; roff->name != NULL; roff++)
101 if (!strcmp(roff->name, name))
102 return roff->ptregs_offset;
103 return -EINVAL;
104}
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index bbc1a50768dd..c6d0f91731a1 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -19,12 +19,6 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
19 ehdr.e_type == ET_DYN; 19 ehdr.e_type == ET_DYN;
20} 20}
21 21
22#if defined(_CALL_ELF) && _CALL_ELF == 2
23void arch__elf_sym_adjust(GElf_Sym *sym)
24{
25 sym->st_value += PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
26}
27#endif
28#endif 22#endif
29 23
30#if !defined(_CALL_ELF) || _CALL_ELF != 2 24#if !defined(_CALL_ELF) || _CALL_ELF != 2
@@ -65,18 +59,45 @@ bool arch__prefers_symtab(void)
65 return true; 59 return true;
66} 60}
67 61
62#ifdef HAVE_LIBELF_SUPPORT
63void arch__sym_update(struct symbol *s, GElf_Sym *sym)
64{
65 s->arch_sym = sym->st_other;
66}
67#endif
68
68#define PPC64LE_LEP_OFFSET 8 69#define PPC64LE_LEP_OFFSET 8
69 70
70void arch__fix_tev_from_maps(struct perf_probe_event *pev, 71void arch__fix_tev_from_maps(struct perf_probe_event *pev,
71 struct probe_trace_event *tev, struct map *map) 72 struct probe_trace_event *tev, struct map *map,
73 struct symbol *sym)
72{ 74{
75 int lep_offset;
76
73 /* 77 /*
74 * ppc64 ABIv2 local entry point is currently always 2 instructions 78 * When probing at a function entry point, we normally always want the
75 * (8 bytes) after the global entry point. 79 * LEP since that catches calls to the function through both the GEP and
80 * the LEP. Hence, we would like to probe at an offset of 8 bytes if
81 * the user only specified the function entry.
82 *
83 * However, if the user specifies an offset, we fall back to using the
84 * GEP since all userspace applications (objdump/readelf) show function
85 * disassembly with offsets from the GEP.
86 *
87 * In addition, we shouldn't specify an offset for kretprobes.
76 */ 88 */
77 if (!pev->uprobes && map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) { 89 if (pev->point.offset || pev->point.retprobe || !map || !sym)
78 tev->point.address += PPC64LE_LEP_OFFSET; 90 return;
91
92 lep_offset = PPC64_LOCAL_ENTRY_OFFSET(sym->arch_sym);
93
94 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS)
79 tev->point.offset += PPC64LE_LEP_OFFSET; 95 tev->point.offset += PPC64LE_LEP_OFFSET;
96 else if (lep_offset) {
97 if (pev->uprobes)
98 tev->point.address += lep_offset;
99 else
100 tev->point.offset += lep_offset;
80 } 101 }
81} 102}
82#endif 103#endif
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 269af2143735..6c9211b18ec0 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -4,3 +4,26 @@ endif
4HAVE_KVM_STAT_SUPPORT := 1 4HAVE_KVM_STAT_SUPPORT := 1
5PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 5PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
6PERF_HAVE_JITDUMP := 1 6PERF_HAVE_JITDUMP := 1
7
8###
9# Syscall table generation
10#
11
12out := $(OUTPUT)arch/x86/include/generated/asm
13header := $(out)/syscalls_64.c
14sys := $(srctree)/tools/perf/arch/x86/entry/syscalls
15systbl := $(sys)/syscalltbl.sh
16
17# Create output directory if not already present
18_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
19
20$(header): $(sys)/syscall_64.tbl $(systbl)
21 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
22 (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \
23 || echo "Warning: x86_64's syscall_64.tbl differs from kernel" >&2 )) || true
24 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
25
26clean::
27 $(call QUIET_CLEAN, x86) $(RM) $(header)
28
29archheaders: $(header)
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
new file mode 100644
index 000000000000..cac6d17ce5db
--- /dev/null
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -0,0 +1,376 @@
1#
2# 64-bit system call numbers and entry vectors
3#
4# The format is:
5# <number> <abi> <name> <entry point>
6#
7# The abi is "common", "64" or "x32" for this file.
8#
90 common read sys_read
101 common write sys_write
112 common open sys_open
123 common close sys_close
134 common stat sys_newstat
145 common fstat sys_newfstat
156 common lstat sys_newlstat
167 common poll sys_poll
178 common lseek sys_lseek
189 common mmap sys_mmap
1910 common mprotect sys_mprotect
2011 common munmap sys_munmap
2112 common brk sys_brk
2213 64 rt_sigaction sys_rt_sigaction
2314 common rt_sigprocmask sys_rt_sigprocmask
2415 64 rt_sigreturn sys_rt_sigreturn/ptregs
2516 64 ioctl sys_ioctl
2617 common pread64 sys_pread64
2718 common pwrite64 sys_pwrite64
2819 64 readv sys_readv
2920 64 writev sys_writev
3021 common access sys_access
3122 common pipe sys_pipe
3223 common select sys_select
3324 common sched_yield sys_sched_yield
3425 common mremap sys_mremap
3526 common msync sys_msync
3627 common mincore sys_mincore
3728 common madvise sys_madvise
3829 common shmget sys_shmget
3930 common shmat sys_shmat
4031 common shmctl sys_shmctl
4132 common dup sys_dup
4233 common dup2 sys_dup2
4334 common pause sys_pause
4435 common nanosleep sys_nanosleep
4536 common getitimer sys_getitimer
4637 common alarm sys_alarm
4738 common setitimer sys_setitimer
4839 common getpid sys_getpid
4940 common sendfile sys_sendfile64
5041 common socket sys_socket
5142 common connect sys_connect
5243 common accept sys_accept
5344 common sendto sys_sendto
5445 64 recvfrom sys_recvfrom
5546 64 sendmsg sys_sendmsg
5647 64 recvmsg sys_recvmsg
5748 common shutdown sys_shutdown
5849 common bind sys_bind
5950 common listen sys_listen
6051 common getsockname sys_getsockname
6152 common getpeername sys_getpeername
6253 common socketpair sys_socketpair
6354 64 setsockopt sys_setsockopt
6455 64 getsockopt sys_getsockopt
6556 common clone sys_clone/ptregs
6657 common fork sys_fork/ptregs
6758 common vfork sys_vfork/ptregs
6859 64 execve sys_execve/ptregs
6960 common exit sys_exit
7061 common wait4 sys_wait4
7162 common kill sys_kill
7263 common uname sys_newuname
7364 common semget sys_semget
7465 common semop sys_semop
7566 common semctl sys_semctl
7667 common shmdt sys_shmdt
7768 common msgget sys_msgget
7869 common msgsnd sys_msgsnd
7970 common msgrcv sys_msgrcv
8071 common msgctl sys_msgctl
8172 common fcntl sys_fcntl
8273 common flock sys_flock
8374 common fsync sys_fsync
8475 common fdatasync sys_fdatasync
8576 common truncate sys_truncate
8677 common ftruncate sys_ftruncate
8778 common getdents sys_getdents
8879 common getcwd sys_getcwd
8980 common chdir sys_chdir
9081 common fchdir sys_fchdir
9182 common rename sys_rename
9283 common mkdir sys_mkdir
9384 common rmdir sys_rmdir
9485 common creat sys_creat
9586 common link sys_link
9687 common unlink sys_unlink
9788 common symlink sys_symlink
9889 common readlink sys_readlink
9990 common chmod sys_chmod
10091 common fchmod sys_fchmod
10192 common chown sys_chown
10293 common fchown sys_fchown
10394 common lchown sys_lchown
10495 common umask sys_umask
10596 common gettimeofday sys_gettimeofday
10697 common getrlimit sys_getrlimit
10798 common getrusage sys_getrusage
10899 common sysinfo sys_sysinfo
109100 common times sys_times
110101 64 ptrace sys_ptrace
111102 common getuid sys_getuid
112103 common syslog sys_syslog
113104 common getgid sys_getgid
114105 common setuid sys_setuid
115106 common setgid sys_setgid
116107 common geteuid sys_geteuid
117108 common getegid sys_getegid
118109 common setpgid sys_setpgid
119110 common getppid sys_getppid
120111 common getpgrp sys_getpgrp
121112 common setsid sys_setsid
122113 common setreuid sys_setreuid
123114 common setregid sys_setregid
124115 common getgroups sys_getgroups
125116 common setgroups sys_setgroups
126117 common setresuid sys_setresuid
127118 common getresuid sys_getresuid
128119 common setresgid sys_setresgid
129120 common getresgid sys_getresgid
130121 common getpgid sys_getpgid
131122 common setfsuid sys_setfsuid
132123 common setfsgid sys_setfsgid
133124 common getsid sys_getsid
134125 common capget sys_capget
135126 common capset sys_capset
136127 64 rt_sigpending sys_rt_sigpending
137128 64 rt_sigtimedwait sys_rt_sigtimedwait
138129 64 rt_sigqueueinfo sys_rt_sigqueueinfo
139130 common rt_sigsuspend sys_rt_sigsuspend
140131 64 sigaltstack sys_sigaltstack
141132 common utime sys_utime
142133 common mknod sys_mknod
143134 64 uselib
144135 common personality sys_personality
145136 common ustat sys_ustat
146137 common statfs sys_statfs
147138 common fstatfs sys_fstatfs
148139 common sysfs sys_sysfs
149140 common getpriority sys_getpriority
150141 common setpriority sys_setpriority
151142 common sched_setparam sys_sched_setparam
152143 common sched_getparam sys_sched_getparam
153144 common sched_setscheduler sys_sched_setscheduler
154145 common sched_getscheduler sys_sched_getscheduler
155146 common sched_get_priority_max sys_sched_get_priority_max
156147 common sched_get_priority_min sys_sched_get_priority_min
157148 common sched_rr_get_interval sys_sched_rr_get_interval
158149 common mlock sys_mlock
159150 common munlock sys_munlock
160151 common mlockall sys_mlockall
161152 common munlockall sys_munlockall
162153 common vhangup sys_vhangup
163154 common modify_ldt sys_modify_ldt
164155 common pivot_root sys_pivot_root
165156 64 _sysctl sys_sysctl
166157 common prctl sys_prctl
167158 common arch_prctl sys_arch_prctl
168159 common adjtimex sys_adjtimex
169160 common setrlimit sys_setrlimit
170161 common chroot sys_chroot
171162 common sync sys_sync
172163 common acct sys_acct
173164 common settimeofday sys_settimeofday
174165 common mount sys_mount
175166 common umount2 sys_umount
176167 common swapon sys_swapon
177168 common swapoff sys_swapoff
178169 common reboot sys_reboot
179170 common sethostname sys_sethostname
180171 common setdomainname sys_setdomainname
181172 common iopl sys_iopl/ptregs
182173 common ioperm sys_ioperm
183174 64 create_module
184175 common init_module sys_init_module
185176 common delete_module sys_delete_module
186177 64 get_kernel_syms
187178 64 query_module
188179 common quotactl sys_quotactl
189180 64 nfsservctl
190181 common getpmsg
191182 common putpmsg
192183 common afs_syscall
193184 common tuxcall
194185 common security
195186 common gettid sys_gettid
196187 common readahead sys_readahead
197188 common setxattr sys_setxattr
198189 common lsetxattr sys_lsetxattr
199190 common fsetxattr sys_fsetxattr
200191 common getxattr sys_getxattr
201192 common lgetxattr sys_lgetxattr
202193 common fgetxattr sys_fgetxattr
203194 common listxattr sys_listxattr
204195 common llistxattr sys_llistxattr
205196 common flistxattr sys_flistxattr
206197 common removexattr sys_removexattr
207198 common lremovexattr sys_lremovexattr
208199 common fremovexattr sys_fremovexattr
209200 common tkill sys_tkill
210201 common time sys_time
211202 common futex sys_futex
212203 common sched_setaffinity sys_sched_setaffinity
213204 common sched_getaffinity sys_sched_getaffinity
214205 64 set_thread_area
215206 64 io_setup sys_io_setup
216207 common io_destroy sys_io_destroy
217208 common io_getevents sys_io_getevents
218209 64 io_submit sys_io_submit
219210 common io_cancel sys_io_cancel
220211 64 get_thread_area
221212 common lookup_dcookie sys_lookup_dcookie
222213 common epoll_create sys_epoll_create
223214 64 epoll_ctl_old
224215 64 epoll_wait_old
225216 common remap_file_pages sys_remap_file_pages
226217 common getdents64 sys_getdents64
227218 common set_tid_address sys_set_tid_address
228219 common restart_syscall sys_restart_syscall
229220 common semtimedop sys_semtimedop
230221 common fadvise64 sys_fadvise64
231222 64 timer_create sys_timer_create
232223 common timer_settime sys_timer_settime
233224 common timer_gettime sys_timer_gettime
234225 common timer_getoverrun sys_timer_getoverrun
235226 common timer_delete sys_timer_delete
236227 common clock_settime sys_clock_settime
237228 common clock_gettime sys_clock_gettime
238229 common clock_getres sys_clock_getres
239230 common clock_nanosleep sys_clock_nanosleep
240231 common exit_group sys_exit_group
241232 common epoll_wait sys_epoll_wait
242233 common epoll_ctl sys_epoll_ctl
243234 common tgkill sys_tgkill
244235 common utimes sys_utimes
245236 64 vserver
246237 common mbind sys_mbind
247238 common set_mempolicy sys_set_mempolicy
248239 common get_mempolicy sys_get_mempolicy
249240 common mq_open sys_mq_open
250241 common mq_unlink sys_mq_unlink
251242 common mq_timedsend sys_mq_timedsend
252243 common mq_timedreceive sys_mq_timedreceive
253244 64 mq_notify sys_mq_notify
254245 common mq_getsetattr sys_mq_getsetattr
255246 64 kexec_load sys_kexec_load
256247 64 waitid sys_waitid
257248 common add_key sys_add_key
258249 common request_key sys_request_key
259250 common keyctl sys_keyctl
260251 common ioprio_set sys_ioprio_set
261252 common ioprio_get sys_ioprio_get
262253 common inotify_init sys_inotify_init
263254 common inotify_add_watch sys_inotify_add_watch
264255 common inotify_rm_watch sys_inotify_rm_watch
265256 common migrate_pages sys_migrate_pages
266257 common openat sys_openat
267258 common mkdirat sys_mkdirat
268259 common mknodat sys_mknodat
269260 common fchownat sys_fchownat
270261 common futimesat sys_futimesat
271262 common newfstatat sys_newfstatat
272263 common unlinkat sys_unlinkat
273264 common renameat sys_renameat
274265 common linkat sys_linkat
275266 common symlinkat sys_symlinkat
276267 common readlinkat sys_readlinkat
277268 common fchmodat sys_fchmodat
278269 common faccessat sys_faccessat
279270 common pselect6 sys_pselect6
280271 common ppoll sys_ppoll
281272 common unshare sys_unshare
282273 64 set_robust_list sys_set_robust_list
283274 64 get_robust_list sys_get_robust_list
284275 common splice sys_splice
285276 common tee sys_tee
286277 common sync_file_range sys_sync_file_range
287278 64 vmsplice sys_vmsplice
288279 64 move_pages sys_move_pages
289280 common utimensat sys_utimensat
290281 common epoll_pwait sys_epoll_pwait
291282 common signalfd sys_signalfd
292283 common timerfd_create sys_timerfd_create
293284 common eventfd sys_eventfd
294285 common fallocate sys_fallocate
295286 common timerfd_settime sys_timerfd_settime
296287 common timerfd_gettime sys_timerfd_gettime
297288 common accept4 sys_accept4
298289 common signalfd4 sys_signalfd4
299290 common eventfd2 sys_eventfd2
300291 common epoll_create1 sys_epoll_create1
301292 common dup3 sys_dup3
302293 common pipe2 sys_pipe2
303294 common inotify_init1 sys_inotify_init1
304295 64 preadv sys_preadv
305296 64 pwritev sys_pwritev
306297 64 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo
307298 common perf_event_open sys_perf_event_open
308299 64 recvmmsg sys_recvmmsg
309300 common fanotify_init sys_fanotify_init
310301 common fanotify_mark sys_fanotify_mark
311302 common prlimit64 sys_prlimit64
312303 common name_to_handle_at sys_name_to_handle_at
313304 common open_by_handle_at sys_open_by_handle_at
314305 common clock_adjtime sys_clock_adjtime
315306 common syncfs sys_syncfs
316307 64 sendmmsg sys_sendmmsg
317308 common setns sys_setns
318309 common getcpu sys_getcpu
319310 64 process_vm_readv sys_process_vm_readv
320311 64 process_vm_writev sys_process_vm_writev
321312 common kcmp sys_kcmp
322313 common finit_module sys_finit_module
323314 common sched_setattr sys_sched_setattr
324315 common sched_getattr sys_sched_getattr
325316 common renameat2 sys_renameat2
326317 common seccomp sys_seccomp
327318 common getrandom sys_getrandom
328319 common memfd_create sys_memfd_create
329320 common kexec_file_load sys_kexec_file_load
330321 common bpf sys_bpf
331322 64 execveat sys_execveat/ptregs
332323 common userfaultfd sys_userfaultfd
333324 common membarrier sys_membarrier
334325 common mlock2 sys_mlock2
335326 common copy_file_range sys_copy_file_range
336327 64 preadv2 sys_preadv2
337328 64 pwritev2 sys_pwritev2
338
339#
340# x32-specific system call numbers start at 512 to avoid cache impact
341# for native 64-bit operation.
342#
343512 x32 rt_sigaction compat_sys_rt_sigaction
344513 x32 rt_sigreturn sys32_x32_rt_sigreturn
345514 x32 ioctl compat_sys_ioctl
346515 x32 readv compat_sys_readv
347516 x32 writev compat_sys_writev
348517 x32 recvfrom compat_sys_recvfrom
349518 x32 sendmsg compat_sys_sendmsg
350519 x32 recvmsg compat_sys_recvmsg
351520 x32 execve compat_sys_execve/ptregs
352521 x32 ptrace compat_sys_ptrace
353522 x32 rt_sigpending compat_sys_rt_sigpending
354523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait
355524 x32 rt_sigqueueinfo compat_sys_rt_sigqueueinfo
356525 x32 sigaltstack compat_sys_sigaltstack
357526 x32 timer_create compat_sys_timer_create
358527 x32 mq_notify compat_sys_mq_notify
359528 x32 kexec_load compat_sys_kexec_load
360529 x32 waitid compat_sys_waitid
361530 x32 set_robust_list compat_sys_set_robust_list
362531 x32 get_robust_list compat_sys_get_robust_list
363532 x32 vmsplice compat_sys_vmsplice
364533 x32 move_pages compat_sys_move_pages
365534 x32 preadv compat_sys_preadv64
366535 x32 pwritev compat_sys_pwritev64
367536 x32 rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
368537 x32 recvmmsg compat_sys_recvmmsg
369538 x32 sendmmsg compat_sys_sendmmsg
370539 x32 process_vm_readv compat_sys_process_vm_readv
371540 x32 process_vm_writev compat_sys_process_vm_writev
372541 x32 setsockopt compat_sys_setsockopt
373542 x32 getsockopt compat_sys_getsockopt
374543 x32 io_setup compat_sys_io_setup
375544 x32 io_submit compat_sys_io_submit
376545 x32 execveat compat_sys_execveat/ptregs
diff --git a/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh b/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh
new file mode 100755
index 000000000000..49a18b9ad9cf
--- /dev/null
+++ b/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh
@@ -0,0 +1,39 @@
1#!/bin/sh
2
3in="$1"
4arch="$2"
5
6syscall_macro() {
7 nr="$1"
8 name="$2"
9
10 echo " [$nr] = \"$name\","
11}
12
13emit() {
14 nr="$1"
15 entry="$2"
16
17 syscall_macro "$nr" "$entry"
18}
19
20echo "static const char *syscalltbl_${arch}[] = {"
21
22sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
23grep '^[0-9]' "$in" | sort -n > $sorted_table
24
25max_nr=0
26while read nr abi name entry compat; do
27 if [ $nr -ge 512 ] ; then # discard compat sycalls
28 break
29 fi
30
31 emit "$nr" "$name"
32 max_nr=$nr
33done < $sorted_table
34
35rm -f $sorted_table
36
37echo "};"
38
39echo "#define SYSCALLTBL_${arch}_MAX_ID ${max_nr}"
diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index 9d29ee283ac5..d4aa567a29c4 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -71,7 +71,7 @@ int test__perf_time_to_tsc(int subtest __maybe_unused)
71 71
72 CHECK__(parse_events(evlist, "cycles:u", NULL)); 72 CHECK__(parse_events(evlist, "cycles:u", NULL));
73 73
74 perf_evlist__config(evlist, &opts); 74 perf_evlist__config(evlist, &opts, NULL);
75 75
76 evsel = perf_evlist__first(evlist); 76 evsel = perf_evlist__first(evlist);
77 77
diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c
index 9223c164e545..1f86ee8fb831 100644
--- a/tools/perf/arch/x86/util/dwarf-regs.c
+++ b/tools/perf/arch/x86/util/dwarf-regs.c
@@ -63,6 +63,8 @@ struct pt_regs_offset {
63# define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)} 63# define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)}
64#endif 64#endif
65 65
66/* TODO: switching by dwarf address size */
67#ifndef __x86_64__
66static const struct pt_regs_offset x86_32_regoffset_table[] = { 68static const struct pt_regs_offset x86_32_regoffset_table[] = {
67 REG_OFFSET_NAME_32("%ax", eax), 69 REG_OFFSET_NAME_32("%ax", eax),
68 REG_OFFSET_NAME_32("%cx", ecx), 70 REG_OFFSET_NAME_32("%cx", ecx),
@@ -75,6 +77,8 @@ static const struct pt_regs_offset x86_32_regoffset_table[] = {
75 REG_OFFSET_END, 77 REG_OFFSET_END,
76}; 78};
77 79
80#define regoffset_table x86_32_regoffset_table
81#else
78static const struct pt_regs_offset x86_64_regoffset_table[] = { 82static const struct pt_regs_offset x86_64_regoffset_table[] = {
79 REG_OFFSET_NAME_64("%ax", rax), 83 REG_OFFSET_NAME_64("%ax", rax),
80 REG_OFFSET_NAME_64("%dx", rdx), 84 REG_OFFSET_NAME_64("%dx", rdx),
@@ -95,11 +99,7 @@ static const struct pt_regs_offset x86_64_regoffset_table[] = {
95 REG_OFFSET_END, 99 REG_OFFSET_END,
96}; 100};
97 101
98/* TODO: switching by dwarf address size */
99#ifdef __x86_64__
100#define regoffset_table x86_64_regoffset_table 102#define regoffset_table x86_64_regoffset_table
101#else
102#define regoffset_table x86_32_regoffset_table
103#endif 103#endif
104 104
105/* Minus 1 for the ending REG_OFFSET_END */ 105/* Minus 1 for the ending REG_OFFSET_END */
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c
index d66f9ad4df2e..7dc30637cf66 100644
--- a/tools/perf/arch/x86/util/intel-bts.c
+++ b/tools/perf/arch/x86/util/intel-bts.c
@@ -438,6 +438,11 @@ struct auxtrace_record *intel_bts_recording_init(int *err)
438 if (!intel_bts_pmu) 438 if (!intel_bts_pmu)
439 return NULL; 439 return NULL;
440 440
441 if (setenv("JITDUMP_USE_ARCH_TIMESTAMP", "1", 1)) {
442 *err = -errno;
443 return NULL;
444 }
445
441 btsr = zalloc(sizeof(struct intel_bts_recording)); 446 btsr = zalloc(sizeof(struct intel_bts_recording));
442 if (!btsr) { 447 if (!btsr) {
443 *err = -ENOMEM; 448 *err = -ENOMEM;
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index a3395179c9ee..a07b9605e93b 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -1027,6 +1027,11 @@ struct auxtrace_record *intel_pt_recording_init(int *err)
1027 if (!intel_pt_pmu) 1027 if (!intel_pt_pmu)
1028 return NULL; 1028 return NULL;
1029 1029
1030 if (setenv("JITDUMP_USE_ARCH_TIMESTAMP", "1", 1)) {
1031 *err = -errno;
1032 return NULL;
1033 }
1034
1030 ptr = zalloc(sizeof(struct intel_pt_recording)); 1035 ptr = zalloc(sizeof(struct intel_pt_recording));
1031 if (!ptr) { 1036 if (!ptr) {
1032 *err = -ENOMEM; 1037 *err = -ENOMEM;
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
index fd2868490d00..357f1b13b5ae 100644
--- a/tools/perf/arch/x86/util/tsc.c
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -7,7 +7,6 @@
7#include <linux/types.h> 7#include <linux/types.h>
8#include "../../util/debug.h" 8#include "../../util/debug.h"
9#include "../../util/tsc.h" 9#include "../../util/tsc.h"
10#include "tsc.h"
11 10
12int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, 11int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
13 struct perf_tsc_conversion *tc) 12 struct perf_tsc_conversion *tc)
@@ -46,3 +45,34 @@ u64 rdtsc(void)
46 45
47 return low | ((u64)high) << 32; 46 return low | ((u64)high) << 32;
48} 47}
48
49int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc,
50 struct perf_tool *tool,
51 perf_event__handler_t process,
52 struct machine *machine)
53{
54 union perf_event event = {
55 .time_conv = {
56 .header = {
57 .type = PERF_RECORD_TIME_CONV,
58 .size = sizeof(struct time_conv_event),
59 },
60 },
61 };
62 struct perf_tsc_conversion tc;
63 int err;
64
65 err = perf_read_tsc_conversion(pc, &tc);
66 if (err == -EOPNOTSUPP)
67 return 0;
68 if (err)
69 return err;
70
71 pr_debug2("Synthesizing TSC conversion information\n");
72
73 event.time_conv.time_mult = tc.time_mult;
74 event.time_conv.time_shift = tc.time_shift;
75 event.time_conv.time_zero = tc.time_zero;
76
77 return process(tool, &event, NULL, machine);
78}
diff --git a/tools/perf/arch/x86/util/tsc.h b/tools/perf/arch/x86/util/tsc.h
deleted file mode 100644
index 2edc4d31065c..000000000000
--- a/tools/perf/arch/x86/util/tsc.h
+++ /dev/null
@@ -1,17 +0,0 @@
1#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__
2#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__
3
4#include <linux/types.h>
5
6struct perf_tsc_conversion {
7 u16 time_shift;
8 u32 time_mult;
9 u64 time_zero;
10};
11
12struct perf_event_mmap_page;
13
14int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
15 struct perf_tsc_conversion *tc);
16
17#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 6a18ce21f865..6952db65508a 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -83,7 +83,7 @@ static void *workerfn(void *arg)
83 do { 83 do {
84 int ret; 84 int ret;
85 again: 85 again:
86 ret = futex_lock_pi(w->futex, NULL, 0, futex_flag); 86 ret = futex_lock_pi(w->futex, NULL, futex_flag);
87 87
88 if (ret) { /* handle lock acquisition */ 88 if (ret) { /* handle lock acquisition */
89 if (!silent) 89 if (!silent)
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index d44de9f44281..b2e06d1190d0 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -57,13 +57,11 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
57 57
58/** 58/**
59 * futex_lock_pi() - block on uaddr as a PI mutex 59 * futex_lock_pi() - block on uaddr as a PI mutex
60 * @detect: whether (1) or not (0) to perform deadlock detection
61 */ 60 */
62static inline int 61static inline int
63futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int detect, 62futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
64 int opflags)
65{ 63{
66 return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags); 64 return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
67} 65}
68 66
69/** 67/**
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index a91aa85d80ff..2b54d0f2672a 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -6,6 +6,7 @@
6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
7 */ 7 */
8 8
9#include "debug.h"
9#include "../perf.h" 10#include "../perf.h"
10#include "../util/util.h" 11#include "../util/util.h"
11#include <subcmd/parse-options.h> 12#include <subcmd/parse-options.h>
@@ -63,14 +64,16 @@ static struct perf_event_attr cycle_attr = {
63 .config = PERF_COUNT_HW_CPU_CYCLES 64 .config = PERF_COUNT_HW_CPU_CYCLES
64}; 65};
65 66
66static void init_cycles(void) 67static int init_cycles(void)
67{ 68{
68 cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag()); 69 cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag());
69 70
70 if (cycles_fd < 0 && errno == ENOSYS) 71 if (cycles_fd < 0 && errno == ENOSYS) {
71 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 72 pr_debug("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
72 else 73 return -1;
73 BUG_ON(cycles_fd < 0); 74 }
75
76 return cycles_fd;
74} 77}
75 78
76static u64 get_cycles(void) 79static u64 get_cycles(void)
@@ -155,8 +158,13 @@ static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *
155 158
156 argc = parse_options(argc, argv, options, info->usage, 0); 159 argc = parse_options(argc, argv, options, info->usage, 0);
157 160
158 if (use_cycles) 161 if (use_cycles) {
159 init_cycles(); 162 i = init_cycles();
163 if (i < 0) {
164 fprintf(stderr, "Failed to open cycles counter\n");
165 return i;
166 }
167 }
160 168
161 size = (size_t)perf_atoll((char *)size_str); 169 size = (size_t)perf_atoll((char *)size_str);
162 size_total = (double)size * nr_loops; 170 size_total = (double)size * nr_loops;
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index c42448ed5dfe..fe1b77fa21f9 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -12,6 +12,7 @@
12#include <subcmd/parse-options.h> 12#include <subcmd/parse-options.h>
13#include "util/util.h" 13#include "util/util.h"
14#include "util/debug.h" 14#include "util/debug.h"
15#include "util/config.h"
15 16
16static bool use_system_config, use_user_config; 17static bool use_system_config, use_user_config;
17 18
@@ -32,13 +33,28 @@ static struct option config_options[] = {
32 OPT_END() 33 OPT_END()
33}; 34};
34 35
35static int show_config(const char *key, const char *value, 36static int show_config(struct perf_config_set *set)
36 void *cb __maybe_unused)
37{ 37{
38 if (value) 38 struct perf_config_section *section;
39 printf("%s=%s\n", key, value); 39 struct perf_config_item *item;
40 else 40 struct list_head *sections;
41 printf("%s\n", key); 41
42 if (set == NULL)
43 return -1;
44
45 sections = &set->sections;
46 if (list_empty(sections))
47 return -1;
48
49 list_for_each_entry(section, sections, node) {
50 list_for_each_entry(item, &section->items, node) {
51 char *value = item->value;
52
53 if (value)
54 printf("%s.%s=%s\n", section->name,
55 item->name, value);
56 }
57 }
42 58
43 return 0; 59 return 0;
44} 60}
@@ -46,6 +62,7 @@ static int show_config(const char *key, const char *value,
46int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) 62int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
47{ 63{
48 int ret = 0; 64 int ret = 0;
65 struct perf_config_set *set;
49 char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); 66 char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
50 67
51 argc = parse_options(argc, argv, config_options, config_usage, 68 argc = parse_options(argc, argv, config_options, config_usage,
@@ -63,13 +80,19 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
63 else if (use_user_config) 80 else if (use_user_config)
64 config_exclusive_filename = user_config; 81 config_exclusive_filename = user_config;
65 82
83 set = perf_config_set__new();
84 if (!set) {
85 ret = -1;
86 goto out_err;
87 }
88
66 switch (actions) { 89 switch (actions) {
67 case ACTION_LIST: 90 case ACTION_LIST:
68 if (argc) { 91 if (argc) {
69 pr_err("Error: takes no arguments\n"); 92 pr_err("Error: takes no arguments\n");
70 parse_options_usage(config_usage, config_options, "l", 1); 93 parse_options_usage(config_usage, config_options, "l", 1);
71 } else { 94 } else {
72 ret = perf_config(show_config, NULL); 95 ret = show_config(set);
73 if (ret < 0) { 96 if (ret < 0) {
74 const char * config_filename = config_exclusive_filename; 97 const char * config_filename = config_exclusive_filename;
75 if (!config_exclusive_filename) 98 if (!config_exclusive_filename)
@@ -83,5 +106,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
83 usage_with_options(config_usage, config_options); 106 usage_with_options(config_usage, config_options);
84 } 107 }
85 108
109 perf_config_set__delete(set);
110out_err:
86 return ret; 111 return ret;
87} 112}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 8053a8ceefda..9ce354f469dc 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -428,7 +428,7 @@ static void hists__baseline_only(struct hists *hists)
428 struct rb_root *root; 428 struct rb_root *root;
429 struct rb_node *next; 429 struct rb_node *next;
430 430
431 if (sort__need_collapse) 431 if (hists__has(hists, need_collapse))
432 root = &hists->entries_collapsed; 432 root = &hists->entries_collapsed;
433 else 433 else
434 root = hists->entries_in; 434 root = hists->entries_in;
@@ -450,7 +450,7 @@ static void hists__precompute(struct hists *hists)
450 struct rb_root *root; 450 struct rb_root *root;
451 struct rb_node *next; 451 struct rb_node *next;
452 452
453 if (sort__need_collapse) 453 if (hists__has(hists, need_collapse))
454 root = &hists->entries_collapsed; 454 root = &hists->entries_collapsed;
455 else 455 else
456 root = hists->entries_in; 456 root = hists->entries_in;
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index bc1de9b8fd67..f9830c902b78 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -61,6 +61,7 @@ static int check_emacsclient_version(void)
61 struct child_process ec_process; 61 struct child_process ec_process;
62 const char *argv_ec[] = { "emacsclient", "--version", NULL }; 62 const char *argv_ec[] = { "emacsclient", "--version", NULL };
63 int version; 63 int version;
64 int ret = -1;
64 65
65 /* emacsclient prints its version number on stderr */ 66 /* emacsclient prints its version number on stderr */
66 memset(&ec_process, 0, sizeof(ec_process)); 67 memset(&ec_process, 0, sizeof(ec_process));
@@ -71,7 +72,10 @@ static int check_emacsclient_version(void)
71 fprintf(stderr, "Failed to start emacsclient.\n"); 72 fprintf(stderr, "Failed to start emacsclient.\n");
72 return -1; 73 return -1;
73 } 74 }
74 strbuf_read(&buffer, ec_process.err, 20); 75 if (strbuf_read(&buffer, ec_process.err, 20) < 0) {
76 fprintf(stderr, "Failed to read emacsclient version\n");
77 goto out;
78 }
75 close(ec_process.err); 79 close(ec_process.err);
76 80
77 /* 81 /*
@@ -82,8 +86,7 @@ static int check_emacsclient_version(void)
82 86
83 if (prefixcmp(buffer.buf, "emacsclient")) { 87 if (prefixcmp(buffer.buf, "emacsclient")) {
84 fprintf(stderr, "Failed to parse emacsclient version.\n"); 88 fprintf(stderr, "Failed to parse emacsclient version.\n");
85 strbuf_release(&buffer); 89 goto out;
86 return -1;
87 } 90 }
88 91
89 version = atoi(buffer.buf + strlen("emacsclient")); 92 version = atoi(buffer.buf + strlen("emacsclient"));
@@ -92,12 +95,11 @@ static int check_emacsclient_version(void)
92 fprintf(stderr, 95 fprintf(stderr,
93 "emacsclient version '%d' too old (< 22).\n", 96 "emacsclient version '%d' too old (< 22).\n",
94 version); 97 version);
95 strbuf_release(&buffer); 98 } else
96 return -1; 99 ret = 0;
97 } 100out:
98
99 strbuf_release(&buffer); 101 strbuf_release(&buffer);
100 return 0; 102 return ret;
101} 103}
102 104
103static void exec_woman_emacs(const char *path, const char *page) 105static void exec_woman_emacs(const char *path, const char *page)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index d1a2d104f2bc..e5afa8fe1bf1 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -748,6 +748,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
748 .auxtrace_info = perf_event__repipe_op2_synth, 748 .auxtrace_info = perf_event__repipe_op2_synth,
749 .auxtrace = perf_event__repipe_auxtrace, 749 .auxtrace = perf_event__repipe_auxtrace,
750 .auxtrace_error = perf_event__repipe_op2_synth, 750 .auxtrace_error = perf_event__repipe_op2_synth,
751 .time_conv = perf_event__repipe_op2_synth,
751 .finished_round = perf_event__repipe_oe_synth, 752 .finished_round = perf_event__repipe_oe_synth,
752 .build_id = perf_event__repipe_op2_synth, 753 .build_id = perf_event__repipe_op2_synth,
753 .id_index = perf_event__repipe_op2_synth, 754 .id_index = perf_event__repipe_op2_synth,
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index c9cb3be47cff..58adfee230de 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -375,7 +375,7 @@ static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample)
375 } 375 }
376 376
377 al.thread = machine__findnew_thread(machine, sample->pid, sample->tid); 377 al.thread = machine__findnew_thread(machine, sample->pid, sample->tid);
378 sample__resolve_callchain(sample, NULL, evsel, &al, 16); 378 sample__resolve_callchain(sample, &callchain_cursor, NULL, evsel, &al, 16);
379 379
380 callchain_cursor_commit(&callchain_cursor); 380 callchain_cursor_commit(&callchain_cursor);
381 while (true) { 381 while (true) {
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index bff666458b28..6487c06d2708 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -982,7 +982,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
982 struct perf_evlist *evlist = kvm->evlist; 982 struct perf_evlist *evlist = kvm->evlist;
983 char sbuf[STRERR_BUFSIZE]; 983 char sbuf[STRERR_BUFSIZE];
984 984
985 perf_evlist__config(evlist, &kvm->opts); 985 perf_evlist__config(evlist, &kvm->opts, NULL);
986 986
987 /* 987 /*
988 * Note: exclude_{guest,host} do not apply here. 988 * Note: exclude_{guest,host} do not apply here.
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 85db3be4b3cb..1dc140c5481d 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -62,19 +62,22 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
62 int rec_argc, i = 0, j; 62 int rec_argc, i = 0, j;
63 const char **rec_argv; 63 const char **rec_argv;
64 int ret; 64 int ret;
65 bool all_user = false, all_kernel = false;
65 struct option options[] = { 66 struct option options[] = {
66 OPT_CALLBACK('e', "event", &mem, "event", 67 OPT_CALLBACK('e', "event", &mem, "event",
67 "event selector. use 'perf mem record -e list' to list available events", 68 "event selector. use 'perf mem record -e list' to list available events",
68 parse_record_events), 69 parse_record_events),
69 OPT_INCR('v', "verbose", &verbose, 70 OPT_INCR('v', "verbose", &verbose,
70 "be more verbose (show counter open errors, etc)"), 71 "be more verbose (show counter open errors, etc)"),
72 OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"),
73 OPT_BOOLEAN('K', "--all-kernel", &all_kernel, "collect only kernel level data"),
71 OPT_END() 74 OPT_END()
72 }; 75 };
73 76
74 argc = parse_options(argc, argv, options, record_mem_usage, 77 argc = parse_options(argc, argv, options, record_mem_usage,
75 PARSE_OPT_STOP_AT_NON_OPTION); 78 PARSE_OPT_STOP_AT_NON_OPTION);
76 79
77 rec_argc = argc + 7; /* max number of arguments */ 80 rec_argc = argc + 9; /* max number of arguments */
78 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 81 rec_argv = calloc(rec_argc + 1, sizeof(char *));
79 if (!rec_argv) 82 if (!rec_argv)
80 return -1; 83 return -1;
@@ -103,6 +106,12 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
103 rec_argv[i++] = perf_mem_events__name(j); 106 rec_argv[i++] = perf_mem_events__name(j);
104 }; 107 };
105 108
109 if (all_user)
110 rec_argv[i++] = "--all-user";
111
112 if (all_kernel)
113 rec_argv[i++] = "--all-kernel";
114
106 for (j = 0; j < argc; j++, i++) 115 for (j = 0; j < argc; j++, i++)
107 rec_argv[i] = argv[j]; 116 rec_argv[i] = argv[j];
108 117
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 515510ecc76a..f3679c44d3f3 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -29,10 +29,12 @@
29#include "util/data.h" 29#include "util/data.h"
30#include "util/perf_regs.h" 30#include "util/perf_regs.h"
31#include "util/auxtrace.h" 31#include "util/auxtrace.h"
32#include "util/tsc.h"
32#include "util/parse-branch-options.h" 33#include "util/parse-branch-options.h"
33#include "util/parse-regs-options.h" 34#include "util/parse-regs-options.h"
34#include "util/llvm-utils.h" 35#include "util/llvm-utils.h"
35#include "util/bpf-loader.h" 36#include "util/bpf-loader.h"
37#include "util/trigger.h"
36#include "asm/bug.h" 38#include "asm/bug.h"
37 39
38#include <unistd.h> 40#include <unistd.h>
@@ -55,6 +57,8 @@ struct record {
55 bool no_buildid_cache; 57 bool no_buildid_cache;
56 bool no_buildid_cache_set; 58 bool no_buildid_cache_set;
57 bool buildid_all; 59 bool buildid_all;
60 bool timestamp_filename;
61 bool switch_output;
58 unsigned long long samples; 62 unsigned long long samples;
59}; 63};
60 64
@@ -124,9 +128,10 @@ out:
124static volatile int done; 128static volatile int done;
125static volatile int signr = -1; 129static volatile int signr = -1;
126static volatile int child_finished; 130static volatile int child_finished;
127static volatile int auxtrace_snapshot_enabled; 131
128static volatile int auxtrace_snapshot_err;
129static volatile int auxtrace_record__snapshot_started; 132static volatile int auxtrace_record__snapshot_started;
133static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
134static DEFINE_TRIGGER(switch_output_trigger);
130 135
131static void sig_handler(int sig) 136static void sig_handler(int sig)
132{ 137{
@@ -244,11 +249,12 @@ static void record__read_auxtrace_snapshot(struct record *rec)
244{ 249{
245 pr_debug("Recording AUX area tracing snapshot\n"); 250 pr_debug("Recording AUX area tracing snapshot\n");
246 if (record__auxtrace_read_snapshot_all(rec) < 0) { 251 if (record__auxtrace_read_snapshot_all(rec) < 0) {
247 auxtrace_snapshot_err = -1; 252 trigger_error(&auxtrace_snapshot_trigger);
248 } else { 253 } else {
249 auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 254 if (auxtrace_record__snapshot_finish(rec->itr))
250 if (!auxtrace_snapshot_err) 255 trigger_error(&auxtrace_snapshot_trigger);
251 auxtrace_snapshot_enabled = 1; 256 else
257 trigger_ready(&auxtrace_snapshot_trigger);
252 } 258 }
253} 259}
254 260
@@ -283,7 +289,7 @@ static int record__open(struct record *rec)
283 struct record_opts *opts = &rec->opts; 289 struct record_opts *opts = &rec->opts;
284 int rc = 0; 290 int rc = 0;
285 291
286 perf_evlist__config(evlist, opts); 292 perf_evlist__config(evlist, opts, &callchain_param);
287 293
288 evlist__for_each(evlist, pos) { 294 evlist__for_each(evlist, pos) {
289try_again: 295try_again:
@@ -494,6 +500,73 @@ record__finish_output(struct record *rec)
494 return; 500 return;
495} 501}
496 502
503static int record__synthesize_workload(struct record *rec)
504{
505 struct {
506 struct thread_map map;
507 struct thread_map_data map_data;
508 } thread_map;
509
510 thread_map.map.nr = 1;
511 thread_map.map.map[0].pid = rec->evlist->workload.pid;
512 thread_map.map.map[0].comm = NULL;
513 return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map,
514 process_synthesized_event,
515 &rec->session->machines.host,
516 rec->opts.sample_address,
517 rec->opts.proc_map_timeout);
518}
519
520static int record__synthesize(struct record *rec);
521
522static int
523record__switch_output(struct record *rec, bool at_exit)
524{
525 struct perf_data_file *file = &rec->file;
526 int fd, err;
527
528 /* Same Size: "2015122520103046"*/
529 char timestamp[] = "InvalidTimestamp";
530
531 rec->samples = 0;
532 record__finish_output(rec);
533 err = fetch_current_timestamp(timestamp, sizeof(timestamp));
534 if (err) {
535 pr_err("Failed to get current timestamp\n");
536 return -EINVAL;
537 }
538
539 fd = perf_data_file__switch(file, timestamp,
540 rec->session->header.data_offset,
541 at_exit);
542 if (fd >= 0 && !at_exit) {
543 rec->bytes_written = 0;
544 rec->session->header.data_size = 0;
545 }
546
547 if (!quiet)
548 fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
549 file->path, timestamp);
550
551 /* Output tracking events */
552 if (!at_exit) {
553 record__synthesize(rec);
554
555 /*
556 * In 'perf record --switch-output' without -a,
557 * record__synthesize() in record__switch_output() won't
558 * generate tracking events because there's no thread_map
559 * in evlist. Which causes newly created perf.data doesn't
560 * contain map and comm information.
561 * Create a fake thread_map and directly call
562 * perf_event__synthesize_thread_map() for those events.
563 */
564 if (target__none(&rec->opts.target))
565 record__synthesize_workload(rec);
566 }
567 return fd;
568}
569
497static volatile int workload_exec_errno; 570static volatile int workload_exec_errno;
498 571
499/* 572/*
@@ -512,6 +585,15 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
512 585
513static void snapshot_sig_handler(int sig); 586static void snapshot_sig_handler(int sig);
514 587
588int __weak
589perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
590 struct perf_tool *tool __maybe_unused,
591 perf_event__handler_t process __maybe_unused,
592 struct machine *machine __maybe_unused)
593{
594 return 0;
595}
596
515static int record__synthesize(struct record *rec) 597static int record__synthesize(struct record *rec)
516{ 598{
517 struct perf_session *session = rec->session; 599 struct perf_session *session = rec->session;
@@ -549,6 +631,11 @@ static int record__synthesize(struct record *rec)
549 } 631 }
550 } 632 }
551 633
634 err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool,
635 process_synthesized_event, machine);
636 if (err)
637 goto out;
638
552 if (rec->opts.full_auxtrace) { 639 if (rec->opts.full_auxtrace) {
553 err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 640 err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
554 session, process_synthesized_event); 641 session, process_synthesized_event);
@@ -600,10 +687,16 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
600 signal(SIGCHLD, sig_handler); 687 signal(SIGCHLD, sig_handler);
601 signal(SIGINT, sig_handler); 688 signal(SIGINT, sig_handler);
602 signal(SIGTERM, sig_handler); 689 signal(SIGTERM, sig_handler);
603 if (rec->opts.auxtrace_snapshot_mode) 690
691 if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
604 signal(SIGUSR2, snapshot_sig_handler); 692 signal(SIGUSR2, snapshot_sig_handler);
605 else 693 if (rec->opts.auxtrace_snapshot_mode)
694 trigger_on(&auxtrace_snapshot_trigger);
695 if (rec->switch_output)
696 trigger_on(&switch_output_trigger);
697 } else {
606 signal(SIGUSR2, SIG_IGN); 698 signal(SIGUSR2, SIG_IGN);
699 }
607 700
608 session = perf_session__new(file, false, tool); 701 session = perf_session__new(file, false, tool);
609 if (session == NULL) { 702 if (session == NULL) {
@@ -729,27 +822,45 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
729 perf_evlist__enable(rec->evlist); 822 perf_evlist__enable(rec->evlist);
730 } 823 }
731 824
732 auxtrace_snapshot_enabled = 1; 825 trigger_ready(&auxtrace_snapshot_trigger);
826 trigger_ready(&switch_output_trigger);
733 for (;;) { 827 for (;;) {
734 unsigned long long hits = rec->samples; 828 unsigned long long hits = rec->samples;
735 829
736 if (record__mmap_read_all(rec) < 0) { 830 if (record__mmap_read_all(rec) < 0) {
737 auxtrace_snapshot_enabled = 0; 831 trigger_error(&auxtrace_snapshot_trigger);
832 trigger_error(&switch_output_trigger);
738 err = -1; 833 err = -1;
739 goto out_child; 834 goto out_child;
740 } 835 }
741 836
742 if (auxtrace_record__snapshot_started) { 837 if (auxtrace_record__snapshot_started) {
743 auxtrace_record__snapshot_started = 0; 838 auxtrace_record__snapshot_started = 0;
744 if (!auxtrace_snapshot_err) 839 if (!trigger_is_error(&auxtrace_snapshot_trigger))
745 record__read_auxtrace_snapshot(rec); 840 record__read_auxtrace_snapshot(rec);
746 if (auxtrace_snapshot_err) { 841 if (trigger_is_error(&auxtrace_snapshot_trigger)) {
747 pr_err("AUX area tracing snapshot failed\n"); 842 pr_err("AUX area tracing snapshot failed\n");
748 err = -1; 843 err = -1;
749 goto out_child; 844 goto out_child;
750 } 845 }
751 } 846 }
752 847
848 if (trigger_is_hit(&switch_output_trigger)) {
849 trigger_ready(&switch_output_trigger);
850
851 if (!quiet)
852 fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
853 waking);
854 waking = 0;
855 fd = record__switch_output(rec, false);
856 if (fd < 0) {
857 pr_err("Failed to switch to new file\n");
858 trigger_error(&switch_output_trigger);
859 err = fd;
860 goto out_child;
861 }
862 }
863
753 if (hits == rec->samples) { 864 if (hits == rec->samples) {
754 if (done || draining) 865 if (done || draining)
755 break; 866 break;
@@ -772,12 +883,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
772 * disable events in this case. 883 * disable events in this case.
773 */ 884 */
774 if (done && !disabled && !target__none(&opts->target)) { 885 if (done && !disabled && !target__none(&opts->target)) {
775 auxtrace_snapshot_enabled = 0; 886 trigger_off(&auxtrace_snapshot_trigger);
776 perf_evlist__disable(rec->evlist); 887 perf_evlist__disable(rec->evlist);
777 disabled = true; 888 disabled = true;
778 } 889 }
779 } 890 }
780 auxtrace_snapshot_enabled = 0; 891 trigger_off(&auxtrace_snapshot_trigger);
892 trigger_off(&switch_output_trigger);
781 893
782 if (forks && workload_exec_errno) { 894 if (forks && workload_exec_errno) {
783 char msg[STRERR_BUFSIZE]; 895 char msg[STRERR_BUFSIZE];
@@ -811,11 +923,22 @@ out_child:
811 /* this will be recalculated during process_buildids() */ 923 /* this will be recalculated during process_buildids() */
812 rec->samples = 0; 924 rec->samples = 0;
813 925
814 if (!err) 926 if (!err) {
815 record__finish_output(rec); 927 if (!rec->timestamp_filename) {
928 record__finish_output(rec);
929 } else {
930 fd = record__switch_output(rec, true);
931 if (fd < 0) {
932 status = fd;
933 goto out_delete_session;
934 }
935 }
936 }
816 937
817 if (!err && !quiet) { 938 if (!err && !quiet) {
818 char samples[128]; 939 char samples[128];
940 const char *postfix = rec->timestamp_filename ?
941 ".<timestamp>" : "";
819 942
820 if (rec->samples && !rec->opts.full_auxtrace) 943 if (rec->samples && !rec->opts.full_auxtrace)
821 scnprintf(samples, sizeof(samples), 944 scnprintf(samples, sizeof(samples),
@@ -823,9 +946,9 @@ out_child:
823 else 946 else
824 samples[0] = '\0'; 947 samples[0] = '\0';
825 948
826 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 949 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
827 perf_data_file__size(file) / 1024.0 / 1024.0, 950 perf_data_file__size(file) / 1024.0 / 1024.0,
828 file->path, samples); 951 file->path, postfix, samples);
829 } 952 }
830 953
831out_delete_session: 954out_delete_session:
@@ -833,58 +956,61 @@ out_delete_session:
833 return status; 956 return status;
834} 957}
835 958
836static void callchain_debug(void) 959static void callchain_debug(struct callchain_param *callchain)
837{ 960{
838 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 961 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
839 962
840 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 963 pr_debug("callchain: type %s\n", str[callchain->record_mode]);
841 964
842 if (callchain_param.record_mode == CALLCHAIN_DWARF) 965 if (callchain->record_mode == CALLCHAIN_DWARF)
843 pr_debug("callchain: stack dump size %d\n", 966 pr_debug("callchain: stack dump size %d\n",
844 callchain_param.dump_size); 967 callchain->dump_size);
845} 968}
846 969
847int record_parse_callchain_opt(const struct option *opt, 970int record_opts__parse_callchain(struct record_opts *record,
848 const char *arg, 971 struct callchain_param *callchain,
849 int unset) 972 const char *arg, bool unset)
850{ 973{
851 int ret; 974 int ret;
852 struct record_opts *record = (struct record_opts *)opt->value; 975 callchain->enabled = !unset;
853
854 record->callgraph_set = true;
855 callchain_param.enabled = !unset;
856 976
857 /* --no-call-graph */ 977 /* --no-call-graph */
858 if (unset) { 978 if (unset) {
859 callchain_param.record_mode = CALLCHAIN_NONE; 979 callchain->record_mode = CALLCHAIN_NONE;
860 pr_debug("callchain: disabled\n"); 980 pr_debug("callchain: disabled\n");
861 return 0; 981 return 0;
862 } 982 }
863 983
864 ret = parse_callchain_record_opt(arg, &callchain_param); 984 ret = parse_callchain_record_opt(arg, callchain);
865 if (!ret) { 985 if (!ret) {
866 /* Enable data address sampling for DWARF unwind. */ 986 /* Enable data address sampling for DWARF unwind. */
867 if (callchain_param.record_mode == CALLCHAIN_DWARF) 987 if (callchain->record_mode == CALLCHAIN_DWARF)
868 record->sample_address = true; 988 record->sample_address = true;
869 callchain_debug(); 989 callchain_debug(callchain);
870 } 990 }
871 991
872 return ret; 992 return ret;
873} 993}
874 994
995int record_parse_callchain_opt(const struct option *opt,
996 const char *arg,
997 int unset)
998{
999 return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
1000}
1001
875int record_callchain_opt(const struct option *opt, 1002int record_callchain_opt(const struct option *opt,
876 const char *arg __maybe_unused, 1003 const char *arg __maybe_unused,
877 int unset __maybe_unused) 1004 int unset __maybe_unused)
878{ 1005{
879 struct record_opts *record = (struct record_opts *)opt->value; 1006 struct callchain_param *callchain = opt->value;
880 1007
881 record->callgraph_set = true; 1008 callchain->enabled = true;
882 callchain_param.enabled = true;
883 1009
884 if (callchain_param.record_mode == CALLCHAIN_NONE) 1010 if (callchain->record_mode == CALLCHAIN_NONE)
885 callchain_param.record_mode = CALLCHAIN_FP; 1011 callchain->record_mode = CALLCHAIN_FP;
886 1012
887 callchain_debug(); 1013 callchain_debug(callchain);
888 return 0; 1014 return 0;
889} 1015}
890 1016
@@ -1122,7 +1248,7 @@ struct option __record_options[] = {
1122 record__parse_mmap_pages), 1248 record__parse_mmap_pages),
1123 OPT_BOOLEAN(0, "group", &record.opts.group, 1249 OPT_BOOLEAN(0, "group", &record.opts.group,
1124 "put the counters into a counter group"), 1250 "put the counters into a counter group"),
1125 OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 1251 OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
1126 NULL, "enables call-graph recording" , 1252 NULL, "enables call-graph recording" ,
1127 &record_callchain_opt), 1253 &record_callchain_opt),
1128 OPT_CALLBACK(0, "call-graph", &record.opts, 1254 OPT_CALLBACK(0, "call-graph", &record.opts,
@@ -1195,6 +1321,10 @@ struct option __record_options[] = {
1195 "file", "vmlinux pathname"), 1321 "file", "vmlinux pathname"),
1196 OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 1322 OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
1197 "Record build-id of all DSOs regardless of hits"), 1323 "Record build-id of all DSOs regardless of hits"),
1324 OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1325 "append timestamp to output filename"),
1326 OPT_BOOLEAN(0, "switch-output", &record.switch_output,
1327 "Switch output when receive SIGUSR2"),
1198 OPT_END() 1328 OPT_END()
1199}; 1329};
1200 1330
@@ -1250,6 +1380,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1250 return -EINVAL; 1380 return -EINVAL;
1251 } 1381 }
1252 1382
1383 if (rec->switch_output)
1384 rec->timestamp_filename = true;
1385
1253 if (!rec->itr) { 1386 if (!rec->itr) {
1254 rec->itr = auxtrace_record__init(rec->evlist, &err); 1387 rec->itr = auxtrace_record__init(rec->evlist, &err);
1255 if (err) 1388 if (err)
@@ -1261,6 +1394,14 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1261 if (err) 1394 if (err)
1262 return err; 1395 return err;
1263 1396
1397 err = bpf__setup_stdout(rec->evlist);
1398 if (err) {
1399 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1400 pr_err("ERROR: Setup BPF stdout failed: %s\n",
1401 errbuf);
1402 return err;
1403 }
1404
1264 err = -ENOMEM; 1405 err = -ENOMEM;
1265 1406
1266 symbol__init(NULL); 1407 symbol__init(NULL);
@@ -1275,8 +1416,36 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1275"If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1416"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1276"even with a suitable vmlinux or kallsyms file.\n\n"); 1417"even with a suitable vmlinux or kallsyms file.\n\n");
1277 1418
1278 if (rec->no_buildid_cache || rec->no_buildid) 1419 if (rec->no_buildid_cache || rec->no_buildid) {
1279 disable_buildid_cache(); 1420 disable_buildid_cache();
1421 } else if (rec->switch_output) {
1422 /*
1423 * In 'perf record --switch-output', disable buildid
1424 * generation by default to reduce data file switching
1425 * overhead. Still generate buildid if they are required
1426 * explicitly using
1427 *
1428 * perf record --signal-trigger --no-no-buildid \
1429 * --no-no-buildid-cache
1430 *
1431 * Following code equals to:
1432 *
1433 * if ((rec->no_buildid || !rec->no_buildid_set) &&
1434 * (rec->no_buildid_cache || !rec->no_buildid_cache_set))
1435 * disable_buildid_cache();
1436 */
1437 bool disable = true;
1438
1439 if (rec->no_buildid_set && !rec->no_buildid)
1440 disable = false;
1441 if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
1442 disable = false;
1443 if (disable) {
1444 rec->no_buildid = true;
1445 rec->no_buildid_cache = true;
1446 disable_buildid_cache();
1447 }
1448 }
1280 1449
1281 if (rec->evlist->nr_entries == 0 && 1450 if (rec->evlist->nr_entries == 0 &&
1282 perf_evlist__add_default(rec->evlist) < 0) { 1451 perf_evlist__add_default(rec->evlist) < 0) {
@@ -1335,9 +1504,13 @@ out_symbol_exit:
1335 1504
1336static void snapshot_sig_handler(int sig __maybe_unused) 1505static void snapshot_sig_handler(int sig __maybe_unused)
1337{ 1506{
1338 if (!auxtrace_snapshot_enabled) 1507 if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
1339 return; 1508 trigger_hit(&auxtrace_snapshot_trigger);
1340 auxtrace_snapshot_enabled = 0; 1509 auxtrace_record__snapshot_started = 1;
1341 auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 1510 if (auxtrace_record__snapshot_start(record.itr))
1342 auxtrace_record__snapshot_started = 1; 1511 trigger_error(&auxtrace_snapshot_trigger);
1512 }
1513
1514 if (trigger_is_ready(&switch_output_trigger))
1515 trigger_hit(&switch_output_trigger);
1343} 1516}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 160ea23b45aa..87d40e3c4078 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -47,7 +47,6 @@ struct report {
47 struct perf_tool tool; 47 struct perf_tool tool;
48 struct perf_session *session; 48 struct perf_session *session;
49 bool use_tui, use_gtk, use_stdio; 49 bool use_tui, use_gtk, use_stdio;
50 bool dont_use_callchains;
51 bool show_full_info; 50 bool show_full_info;
52 bool show_threads; 51 bool show_threads;
53 bool inverted_callchain; 52 bool inverted_callchain;
@@ -235,7 +234,7 @@ static int report__setup_sample_type(struct report *rep)
235 sample_type |= PERF_SAMPLE_BRANCH_STACK; 234 sample_type |= PERF_SAMPLE_BRANCH_STACK;
236 235
237 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { 236 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
238 if (sort__has_parent) { 237 if (perf_hpp_list.parent) {
239 ui__error("Selected --sort parent, but no " 238 ui__error("Selected --sort parent, but no "
240 "callchain data. Did you call " 239 "callchain data. Did you call "
241 "'perf record' without -g?\n"); 240 "'perf record' without -g?\n");
@@ -247,7 +246,7 @@ static int report__setup_sample_type(struct report *rep)
247 "you call 'perf record' without -g?\n"); 246 "you call 'perf record' without -g?\n");
248 return -1; 247 return -1;
249 } 248 }
250 } else if (!rep->dont_use_callchains && 249 } else if (!callchain_param.enabled &&
251 callchain_param.mode != CHAIN_NONE && 250 callchain_param.mode != CHAIN_NONE &&
252 !symbol_conf.use_callchain) { 251 !symbol_conf.use_callchain) {
253 symbol_conf.use_callchain = true; 252 symbol_conf.use_callchain = true;
@@ -599,13 +598,15 @@ static int __cmd_report(struct report *rep)
599static int 598static int
600report_parse_callchain_opt(const struct option *opt, const char *arg, int unset) 599report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
601{ 600{
602 struct report *rep = (struct report *)opt->value; 601 struct callchain_param *callchain = opt->value;
603 602
603 callchain->enabled = !unset;
604 /* 604 /*
605 * --no-call-graph 605 * --no-call-graph
606 */ 606 */
607 if (unset) { 607 if (unset) {
608 rep->dont_use_callchains = true; 608 symbol_conf.use_callchain = false;
609 callchain->mode = CHAIN_NONE;
609 return 0; 610 return 0;
610 } 611 }
611 612
@@ -690,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
690 .ordered_events = true, 691 .ordered_events = true,
691 .ordering_requires_timestamps = true, 692 .ordering_requires_timestamps = true,
692 }, 693 },
693 .max_stack = PERF_MAX_STACK_DEPTH, 694 .max_stack = sysctl_perf_event_max_stack,
694 .pretty_printing_style = "normal", 695 .pretty_printing_style = "normal",
695 .socket_filter = -1, 696 .socket_filter = -1,
696 }; 697 };
@@ -734,7 +735,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
734 "regex filter to identify parent, see: '--sort parent'"), 735 "regex filter to identify parent, see: '--sort parent'"),
735 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 736 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
736 "Only display entries with parent-match"), 737 "Only display entries with parent-match"),
737 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, 738 OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
738 "print_type,threshold[,print_limit],order,sort_key[,branch],value", 739 "print_type,threshold[,print_limit],order,sort_key[,branch],value",
739 report_callchain_help, &report_parse_callchain_opt, 740 report_callchain_help, &report_parse_callchain_opt,
740 callchain_default_opt), 741 callchain_default_opt),
@@ -743,7 +744,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
743 OPT_INTEGER(0, "max-stack", &report.max_stack, 744 OPT_INTEGER(0, "max-stack", &report.max_stack,
744 "Set the maximum stack depth when parsing the callchain, " 745 "Set the maximum stack depth when parsing the callchain, "
745 "anything beyond the specified depth will be ignored. " 746 "anything beyond the specified depth will be ignored. "
746 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 747 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
747 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, 748 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
748 "alias for inverted call graph"), 749 "alias for inverted call graph"),
749 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 750 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
@@ -935,7 +936,7 @@ repeat:
935 goto error; 936 goto error;
936 } 937 }
937 938
938 sort__need_collapse = true; 939 perf_hpp_list.need_collapse = true;
939 } 940 }
940 941
941 /* Force tty output for header output and per-thread stat. */ 942 /* Force tty output for header output and per-thread stat. */
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 871b55ae22a4..afa057666c2a 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -11,6 +11,8 @@
11#include "util/session.h" 11#include "util/session.h"
12#include "util/tool.h" 12#include "util/tool.h"
13#include "util/cloexec.h" 13#include "util/cloexec.h"
14#include "util/thread_map.h"
15#include "util/color.h"
14 16
15#include <subcmd/parse-options.h> 17#include <subcmd/parse-options.h>
16#include "util/trace-event.h" 18#include "util/trace-event.h"
@@ -122,6 +124,21 @@ struct trace_sched_handler {
122 struct machine *machine); 124 struct machine *machine);
123}; 125};
124 126
127#define COLOR_PIDS PERF_COLOR_BLUE
128#define COLOR_CPUS PERF_COLOR_BG_RED
129
130struct perf_sched_map {
131 DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS);
132 int *comp_cpus;
133 bool comp;
134 struct thread_map *color_pids;
135 const char *color_pids_str;
136 struct cpu_map *color_cpus;
137 const char *color_cpus_str;
138 struct cpu_map *cpus;
139 const char *cpus_str;
140};
141
125struct perf_sched { 142struct perf_sched {
126 struct perf_tool tool; 143 struct perf_tool tool;
127 const char *sort_order; 144 const char *sort_order;
@@ -173,6 +190,7 @@ struct perf_sched {
173 struct list_head sort_list, cmp_pid; 190 struct list_head sort_list, cmp_pid;
174 bool force; 191 bool force;
175 bool skip_merge; 192 bool skip_merge;
193 struct perf_sched_map map;
176}; 194};
177 195
178static u64 get_nsecs(void) 196static u64 get_nsecs(void)
@@ -1339,6 +1357,38 @@ static int process_sched_wakeup_event(struct perf_tool *tool,
1339 return 0; 1357 return 0;
1340} 1358}
1341 1359
1360union map_priv {
1361 void *ptr;
1362 bool color;
1363};
1364
1365static bool thread__has_color(struct thread *thread)
1366{
1367 union map_priv priv = {
1368 .ptr = thread__priv(thread),
1369 };
1370
1371 return priv.color;
1372}
1373
1374static struct thread*
1375map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid, pid_t tid)
1376{
1377 struct thread *thread = machine__findnew_thread(machine, pid, tid);
1378 union map_priv priv = {
1379 .color = false,
1380 };
1381
1382 if (!sched->map.color_pids || !thread || thread__priv(thread))
1383 return thread;
1384
1385 if (thread_map__has(sched->map.color_pids, tid))
1386 priv.color = true;
1387
1388 thread__set_priv(thread, priv.ptr);
1389 return thread;
1390}
1391
1342static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, 1392static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1343 struct perf_sample *sample, struct machine *machine) 1393 struct perf_sample *sample, struct machine *machine)
1344{ 1394{
@@ -1347,13 +1397,25 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1347 int new_shortname; 1397 int new_shortname;
1348 u64 timestamp0, timestamp = sample->time; 1398 u64 timestamp0, timestamp = sample->time;
1349 s64 delta; 1399 s64 delta;
1350 int cpu, this_cpu = sample->cpu; 1400 int i, this_cpu = sample->cpu;
1401 int cpus_nr;
1402 bool new_cpu = false;
1403 const char *color = PERF_COLOR_NORMAL;
1351 1404
1352 BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0); 1405 BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0);
1353 1406
1354 if (this_cpu > sched->max_cpu) 1407 if (this_cpu > sched->max_cpu)
1355 sched->max_cpu = this_cpu; 1408 sched->max_cpu = this_cpu;
1356 1409
1410 if (sched->map.comp) {
1411 cpus_nr = bitmap_weight(sched->map.comp_cpus_mask, MAX_CPUS);
1412 if (!test_and_set_bit(this_cpu, sched->map.comp_cpus_mask)) {
1413 sched->map.comp_cpus[cpus_nr++] = this_cpu;
1414 new_cpu = true;
1415 }
1416 } else
1417 cpus_nr = sched->max_cpu;
1418
1357 timestamp0 = sched->cpu_last_switched[this_cpu]; 1419 timestamp0 = sched->cpu_last_switched[this_cpu];
1358 sched->cpu_last_switched[this_cpu] = timestamp; 1420 sched->cpu_last_switched[this_cpu] = timestamp;
1359 if (timestamp0) 1421 if (timestamp0)
@@ -1366,7 +1428,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1366 return -1; 1428 return -1;
1367 } 1429 }
1368 1430
1369 sched_in = machine__findnew_thread(machine, -1, next_pid); 1431 sched_in = map__findnew_thread(sched, machine, -1, next_pid);
1370 if (sched_in == NULL) 1432 if (sched_in == NULL)
1371 return -1; 1433 return -1;
1372 1434
@@ -1400,26 +1462,52 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1400 new_shortname = 1; 1462 new_shortname = 1;
1401 } 1463 }
1402 1464
1403 for (cpu = 0; cpu <= sched->max_cpu; cpu++) { 1465 for (i = 0; i < cpus_nr; i++) {
1466 int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i;
1467 struct thread *curr_thread = sched->curr_thread[cpu];
1468 const char *pid_color = color;
1469 const char *cpu_color = color;
1470
1471 if (curr_thread && thread__has_color(curr_thread))
1472 pid_color = COLOR_PIDS;
1473
1474 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, cpu))
1475 continue;
1476
1477 if (sched->map.color_cpus && cpu_map__has(sched->map.color_cpus, cpu))
1478 cpu_color = COLOR_CPUS;
1479
1404 if (cpu != this_cpu) 1480 if (cpu != this_cpu)
1405 printf(" "); 1481 color_fprintf(stdout, cpu_color, " ");
1406 else 1482 else
1407 printf("*"); 1483 color_fprintf(stdout, cpu_color, "*");
1408 1484
1409 if (sched->curr_thread[cpu]) 1485 if (sched->curr_thread[cpu])
1410 printf("%2s ", sched->curr_thread[cpu]->shortname); 1486 color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname);
1411 else 1487 else
1412 printf(" "); 1488 color_fprintf(stdout, color, " ");
1413 } 1489 }
1414 1490
1415 printf(" %12.6f secs ", (double)timestamp/1e9); 1491 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu))
1492 goto out;
1493
1494 color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9);
1416 if (new_shortname) { 1495 if (new_shortname) {
1417 printf("%s => %s:%d\n", 1496 const char *pid_color = color;
1497
1498 if (thread__has_color(sched_in))
1499 pid_color = COLOR_PIDS;
1500
1501 color_fprintf(stdout, pid_color, "%s => %s:%d",
1418 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); 1502 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid);
1419 } else {
1420 printf("\n");
1421 } 1503 }
1422 1504
1505 if (sched->map.comp && new_cpu)
1506 color_fprintf(stdout, color, " (CPU %d)", this_cpu);
1507
1508out:
1509 color_fprintf(stdout, color, "\n");
1510
1423 thread__put(sched_in); 1511 thread__put(sched_in);
1424 1512
1425 return 0; 1513 return 0;
@@ -1675,9 +1763,75 @@ static int perf_sched__lat(struct perf_sched *sched)
1675 return 0; 1763 return 0;
1676} 1764}
1677 1765
1766static int setup_map_cpus(struct perf_sched *sched)
1767{
1768 struct cpu_map *map;
1769
1770 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1771
1772 if (sched->map.comp) {
1773 sched->map.comp_cpus = zalloc(sched->max_cpu * sizeof(int));
1774 if (!sched->map.comp_cpus)
1775 return -1;
1776 }
1777
1778 if (!sched->map.cpus_str)
1779 return 0;
1780
1781 map = cpu_map__new(sched->map.cpus_str);
1782 if (!map) {
1783 pr_err("failed to get cpus map from %s\n", sched->map.cpus_str);
1784 return -1;
1785 }
1786
1787 sched->map.cpus = map;
1788 return 0;
1789}
1790
1791static int setup_color_pids(struct perf_sched *sched)
1792{
1793 struct thread_map *map;
1794
1795 if (!sched->map.color_pids_str)
1796 return 0;
1797
1798 map = thread_map__new_by_tid_str(sched->map.color_pids_str);
1799 if (!map) {
1800 pr_err("failed to get thread map from %s\n", sched->map.color_pids_str);
1801 return -1;
1802 }
1803
1804 sched->map.color_pids = map;
1805 return 0;
1806}
1807
1808static int setup_color_cpus(struct perf_sched *sched)
1809{
1810 struct cpu_map *map;
1811
1812 if (!sched->map.color_cpus_str)
1813 return 0;
1814
1815 map = cpu_map__new(sched->map.color_cpus_str);
1816 if (!map) {
1817 pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str);
1818 return -1;
1819 }
1820
1821 sched->map.color_cpus = map;
1822 return 0;
1823}
1824
1678static int perf_sched__map(struct perf_sched *sched) 1825static int perf_sched__map(struct perf_sched *sched)
1679{ 1826{
1680 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1827 if (setup_map_cpus(sched))
1828 return -1;
1829
1830 if (setup_color_pids(sched))
1831 return -1;
1832
1833 if (setup_color_cpus(sched))
1834 return -1;
1681 1835
1682 setup_pager(); 1836 setup_pager();
1683 if (perf_sched__read_events(sched)) 1837 if (perf_sched__read_events(sched))
@@ -1831,6 +1985,17 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1831 "dump raw trace in ASCII"), 1985 "dump raw trace in ASCII"),
1832 OPT_END() 1986 OPT_END()
1833 }; 1987 };
1988 const struct option map_options[] = {
1989 OPT_BOOLEAN(0, "compact", &sched.map.comp,
1990 "map output in compact mode"),
1991 OPT_STRING(0, "color-pids", &sched.map.color_pids_str, "pids",
1992 "highlight given pids in map"),
1993 OPT_STRING(0, "color-cpus", &sched.map.color_cpus_str, "cpus",
1994 "highlight given CPUs in map"),
1995 OPT_STRING(0, "cpus", &sched.map.cpus_str, "cpus",
1996 "display given CPUs in map"),
1997 OPT_END()
1998 };
1834 const char * const latency_usage[] = { 1999 const char * const latency_usage[] = {
1835 "perf sched latency [<options>]", 2000 "perf sched latency [<options>]",
1836 NULL 2001 NULL
@@ -1839,6 +2004,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1839 "perf sched replay [<options>]", 2004 "perf sched replay [<options>]",
1840 NULL 2005 NULL
1841 }; 2006 };
2007 const char * const map_usage[] = {
2008 "perf sched map [<options>]",
2009 NULL
2010 };
1842 const char *const sched_subcommands[] = { "record", "latency", "map", 2011 const char *const sched_subcommands[] = { "record", "latency", "map",
1843 "replay", "script", NULL }; 2012 "replay", "script", NULL };
1844 const char *sched_usage[] = { 2013 const char *sched_usage[] = {
@@ -1887,6 +2056,11 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1887 setup_sorting(&sched, latency_options, latency_usage); 2056 setup_sorting(&sched, latency_options, latency_usage);
1888 return perf_sched__lat(&sched); 2057 return perf_sched__lat(&sched);
1889 } else if (!strcmp(argv[0], "map")) { 2058 } else if (!strcmp(argv[0], "map")) {
2059 if (argc) {
2060 argc = parse_options(argc, argv, map_options, map_usage, 0);
2061 if (argc)
2062 usage_with_options(map_usage, map_options);
2063 }
1890 sched.tp_handler = &map_ops; 2064 sched.tp_handler = &map_ops;
1891 setup_sorting(&sched, latency_options, latency_usage); 2065 setup_sorting(&sched, latency_options, latency_usage);
1892 return perf_sched__map(&sched); 2066 return perf_sched__map(&sched);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 3770c3dffe5e..efca81679bb3 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -22,6 +22,7 @@
22#include "util/thread_map.h" 22#include "util/thread_map.h"
23#include "util/stat.h" 23#include "util/stat.h"
24#include <linux/bitmap.h> 24#include <linux/bitmap.h>
25#include <linux/stringify.h>
25#include "asm/bug.h" 26#include "asm/bug.h"
26#include "util/mem-events.h" 27#include "util/mem-events.h"
27 28
@@ -317,19 +318,19 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
317 318
318 output[type].print_ip_opts = 0; 319 output[type].print_ip_opts = 0;
319 if (PRINT_FIELD(IP)) 320 if (PRINT_FIELD(IP))
320 output[type].print_ip_opts |= PRINT_IP_OPT_IP; 321 output[type].print_ip_opts |= EVSEL__PRINT_IP;
321 322
322 if (PRINT_FIELD(SYM)) 323 if (PRINT_FIELD(SYM))
323 output[type].print_ip_opts |= PRINT_IP_OPT_SYM; 324 output[type].print_ip_opts |= EVSEL__PRINT_SYM;
324 325
325 if (PRINT_FIELD(DSO)) 326 if (PRINT_FIELD(DSO))
326 output[type].print_ip_opts |= PRINT_IP_OPT_DSO; 327 output[type].print_ip_opts |= EVSEL__PRINT_DSO;
327 328
328 if (PRINT_FIELD(SYMOFFSET)) 329 if (PRINT_FIELD(SYMOFFSET))
329 output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; 330 output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET;
330 331
331 if (PRINT_FIELD(SRCLINE)) 332 if (PRINT_FIELD(SRCLINE))
332 output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE; 333 output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;
333} 334}
334 335
335/* 336/*
@@ -569,18 +570,23 @@ static void print_sample_bts(struct perf_sample *sample,
569 /* print branch_from information */ 570 /* print branch_from information */
570 if (PRINT_FIELD(IP)) { 571 if (PRINT_FIELD(IP)) {
571 unsigned int print_opts = output[attr->type].print_ip_opts; 572 unsigned int print_opts = output[attr->type].print_ip_opts;
573 struct callchain_cursor *cursor = NULL;
572 574
573 if (symbol_conf.use_callchain && sample->callchain) { 575 if (symbol_conf.use_callchain && sample->callchain &&
574 printf("\n"); 576 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
575 } else { 577 sample, NULL, NULL, scripting_max_stack) == 0)
576 printf(" "); 578 cursor = &callchain_cursor;
577 if (print_opts & PRINT_IP_OPT_SRCLINE) { 579
580 if (cursor == NULL) {
581 putchar(' ');
582 if (print_opts & EVSEL__PRINT_SRCLINE) {
578 print_srcline_last = true; 583 print_srcline_last = true;
579 print_opts &= ~PRINT_IP_OPT_SRCLINE; 584 print_opts &= ~EVSEL__PRINT_SRCLINE;
580 } 585 }
581 } 586 } else
582 perf_evsel__print_ip(evsel, sample, al, print_opts, 587 putchar('\n');
583 scripting_max_stack); 588
589 sample__fprintf_sym(sample, al, 0, print_opts, cursor, stdout);
584 } 590 }
585 591
586 /* print branch_to information */ 592 /* print branch_to information */
@@ -783,14 +789,15 @@ static void process_event(struct perf_script *script,
783 printf("%16" PRIu64, sample->weight); 789 printf("%16" PRIu64, sample->weight);
784 790
785 if (PRINT_FIELD(IP)) { 791 if (PRINT_FIELD(IP)) {
786 if (!symbol_conf.use_callchain) 792 struct callchain_cursor *cursor = NULL;
787 printf(" "); 793
788 else 794 if (symbol_conf.use_callchain && sample->callchain &&
789 printf("\n"); 795 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
796 sample, NULL, NULL, scripting_max_stack) == 0)
797 cursor = &callchain_cursor;
790 798
791 perf_evsel__print_ip(evsel, sample, al, 799 putchar(cursor ? '\n' : ' ');
792 output[attr->type].print_ip_opts, 800 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout);
793 scripting_max_stack);
794 } 801 }
795 802
796 if (PRINT_FIELD(IREGS)) 803 if (PRINT_FIELD(IREGS))
@@ -1415,21 +1422,19 @@ static int is_directory(const char *base_path, const struct dirent *dent)
1415 return S_ISDIR(st.st_mode); 1422 return S_ISDIR(st.st_mode);
1416} 1423}
1417 1424
1418#define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\ 1425#define for_each_lang(scripts_path, scripts_dir, lang_dirent) \
1419 while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \ 1426 while ((lang_dirent = readdir(scripts_dir)) != NULL) \
1420 lang_next) \ 1427 if ((lang_dirent->d_type == DT_DIR || \
1421 if ((lang_dirent.d_type == DT_DIR || \ 1428 (lang_dirent->d_type == DT_UNKNOWN && \
1422 (lang_dirent.d_type == DT_UNKNOWN && \ 1429 is_directory(scripts_path, lang_dirent))) && \
1423 is_directory(scripts_path, &lang_dirent))) && \ 1430 (strcmp(lang_dirent->d_name, ".")) && \
1424 (strcmp(lang_dirent.d_name, ".")) && \ 1431 (strcmp(lang_dirent->d_name, "..")))
1425 (strcmp(lang_dirent.d_name, "..")))
1426 1432
1427#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\ 1433#define for_each_script(lang_path, lang_dir, script_dirent) \
1428 while (!readdir_r(lang_dir, &script_dirent, &script_next) && \ 1434 while ((script_dirent = readdir(lang_dir)) != NULL) \
1429 script_next) \ 1435 if (script_dirent->d_type != DT_DIR && \
1430 if (script_dirent.d_type != DT_DIR && \ 1436 (script_dirent->d_type != DT_UNKNOWN || \
1431 (script_dirent.d_type != DT_UNKNOWN || \ 1437 !is_directory(lang_path, script_dirent)))
1432 !is_directory(lang_path, &script_dirent)))
1433 1438
1434 1439
1435#define RECORD_SUFFIX "-record" 1440#define RECORD_SUFFIX "-record"
@@ -1575,7 +1580,7 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
1575 const char *s __maybe_unused, 1580 const char *s __maybe_unused,
1576 int unset __maybe_unused) 1581 int unset __maybe_unused)
1577{ 1582{
1578 struct dirent *script_next, *lang_next, script_dirent, lang_dirent; 1583 struct dirent *script_dirent, *lang_dirent;
1579 char scripts_path[MAXPATHLEN]; 1584 char scripts_path[MAXPATHLEN];
1580 DIR *scripts_dir, *lang_dir; 1585 DIR *scripts_dir, *lang_dir;
1581 char script_path[MAXPATHLEN]; 1586 char script_path[MAXPATHLEN];
@@ -1590,19 +1595,19 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
1590 if (!scripts_dir) 1595 if (!scripts_dir)
1591 return -1; 1596 return -1;
1592 1597
1593 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { 1598 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
1594 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 1599 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
1595 lang_dirent.d_name); 1600 lang_dirent->d_name);
1596 lang_dir = opendir(lang_path); 1601 lang_dir = opendir(lang_path);
1597 if (!lang_dir) 1602 if (!lang_dir)
1598 continue; 1603 continue;
1599 1604
1600 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 1605 for_each_script(lang_path, lang_dir, script_dirent) {
1601 script_root = get_script_root(&script_dirent, REPORT_SUFFIX); 1606 script_root = get_script_root(script_dirent, REPORT_SUFFIX);
1602 if (script_root) { 1607 if (script_root) {
1603 desc = script_desc__findnew(script_root); 1608 desc = script_desc__findnew(script_root);
1604 snprintf(script_path, MAXPATHLEN, "%s/%s", 1609 snprintf(script_path, MAXPATHLEN, "%s/%s",
1605 lang_path, script_dirent.d_name); 1610 lang_path, script_dirent->d_name);
1606 read_script_info(desc, script_path); 1611 read_script_info(desc, script_path);
1607 free(script_root); 1612 free(script_root);
1608 } 1613 }
@@ -1690,7 +1695,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
1690 */ 1695 */
1691int find_scripts(char **scripts_array, char **scripts_path_array) 1696int find_scripts(char **scripts_array, char **scripts_path_array)
1692{ 1697{
1693 struct dirent *script_next, *lang_next, script_dirent, lang_dirent; 1698 struct dirent *script_dirent, *lang_dirent;
1694 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; 1699 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
1695 DIR *scripts_dir, *lang_dir; 1700 DIR *scripts_dir, *lang_dir;
1696 struct perf_session *session; 1701 struct perf_session *session;
@@ -1713,9 +1718,9 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
1713 return -1; 1718 return -1;
1714 } 1719 }
1715 1720
1716 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { 1721 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
1717 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, 1722 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
1718 lang_dirent.d_name); 1723 lang_dirent->d_name);
1719#ifdef NO_LIBPERL 1724#ifdef NO_LIBPERL
1720 if (strstr(lang_path, "perl")) 1725 if (strstr(lang_path, "perl"))
1721 continue; 1726 continue;
@@ -1729,16 +1734,16 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
1729 if (!lang_dir) 1734 if (!lang_dir)
1730 continue; 1735 continue;
1731 1736
1732 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 1737 for_each_script(lang_path, lang_dir, script_dirent) {
1733 /* Skip those real time scripts: xxxtop.p[yl] */ 1738 /* Skip those real time scripts: xxxtop.p[yl] */
1734 if (strstr(script_dirent.d_name, "top.")) 1739 if (strstr(script_dirent->d_name, "top."))
1735 continue; 1740 continue;
1736 sprintf(scripts_path_array[i], "%s/%s", lang_path, 1741 sprintf(scripts_path_array[i], "%s/%s", lang_path,
1737 script_dirent.d_name); 1742 script_dirent->d_name);
1738 temp = strchr(script_dirent.d_name, '.'); 1743 temp = strchr(script_dirent->d_name, '.');
1739 snprintf(scripts_array[i], 1744 snprintf(scripts_array[i],
1740 (temp - script_dirent.d_name) + 1, 1745 (temp - script_dirent->d_name) + 1,
1741 "%s", script_dirent.d_name); 1746 "%s", script_dirent->d_name);
1742 1747
1743 if (check_ev_match(lang_path, 1748 if (check_ev_match(lang_path,
1744 scripts_array[i], session)) 1749 scripts_array[i], session))
@@ -1756,7 +1761,7 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
1756 1761
1757static char *get_script_path(const char *script_root, const char *suffix) 1762static char *get_script_path(const char *script_root, const char *suffix)
1758{ 1763{
1759 struct dirent *script_next, *lang_next, script_dirent, lang_dirent; 1764 struct dirent *script_dirent, *lang_dirent;
1760 char scripts_path[MAXPATHLEN]; 1765 char scripts_path[MAXPATHLEN];
1761 char script_path[MAXPATHLEN]; 1766 char script_path[MAXPATHLEN];
1762 DIR *scripts_dir, *lang_dir; 1767 DIR *scripts_dir, *lang_dir;
@@ -1769,21 +1774,21 @@ static char *get_script_path(const char *script_root, const char *suffix)
1769 if (!scripts_dir) 1774 if (!scripts_dir)
1770 return NULL; 1775 return NULL;
1771 1776
1772 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { 1777 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
1773 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 1778 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
1774 lang_dirent.d_name); 1779 lang_dirent->d_name);
1775 lang_dir = opendir(lang_path); 1780 lang_dir = opendir(lang_path);
1776 if (!lang_dir) 1781 if (!lang_dir)
1777 continue; 1782 continue;
1778 1783
1779 for_each_script(lang_path, lang_dir, script_dirent, script_next) { 1784 for_each_script(lang_path, lang_dir, script_dirent) {
1780 __script_root = get_script_root(&script_dirent, suffix); 1785 __script_root = get_script_root(script_dirent, suffix);
1781 if (__script_root && !strcmp(script_root, __script_root)) { 1786 if (__script_root && !strcmp(script_root, __script_root)) {
1782 free(__script_root); 1787 free(__script_root);
1783 closedir(lang_dir); 1788 closedir(lang_dir);
1784 closedir(scripts_dir); 1789 closedir(scripts_dir);
1785 snprintf(script_path, MAXPATHLEN, "%s/%s", 1790 snprintf(script_path, MAXPATHLEN, "%s/%s",
1786 lang_path, script_dirent.d_name); 1791 lang_path, script_dirent->d_name);
1787 return strdup(script_path); 1792 return strdup(script_path);
1788 } 1793 }
1789 free(__script_root); 1794 free(__script_root);
@@ -1961,6 +1966,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1961 .exit = perf_event__process_exit, 1966 .exit = perf_event__process_exit,
1962 .fork = perf_event__process_fork, 1967 .fork = perf_event__process_fork,
1963 .attr = process_attr, 1968 .attr = process_attr,
1969 .event_update = perf_event__process_event_update,
1964 .tracing_data = perf_event__process_tracing_data, 1970 .tracing_data = perf_event__process_tracing_data,
1965 .build_id = perf_event__process_build_id, 1971 .build_id = perf_event__process_build_id,
1966 .id_index = perf_event__process_id_index, 1972 .id_index = perf_event__process_id_index,
@@ -2022,6 +2028,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2022 "only consider symbols in these pids"), 2028 "only consider symbols in these pids"),
2023 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]", 2029 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
2024 "only consider symbols in these tids"), 2030 "only consider symbols in these tids"),
2031 OPT_UINTEGER(0, "max-stack", &scripting_max_stack,
2032 "Set the maximum stack depth when parsing the callchain, "
2033 "anything beyond the specified depth will be ignored. "
2034 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
2025 OPT_BOOLEAN('I', "show-info", &show_full_info, 2035 OPT_BOOLEAN('I', "show-info", &show_full_info,
2026 "display extended information from perf.data file"), 2036 "display extended information from perf.data file"),
2027 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 2037 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -2057,6 +2067,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2057 NULL 2067 NULL
2058 }; 2068 };
2059 2069
2070 scripting_max_stack = sysctl_perf_event_max_stack;
2071
2060 setup_scripting(); 2072 setup_scripting();
2061 2073
2062 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, 2074 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1f19f2f999c8..e459b685a4e9 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -298,6 +298,14 @@ static int read_counter(struct perf_evsel *counter)
298 return -1; 298 return -1;
299 } 299 }
300 } 300 }
301
302 if (verbose > 1) {
303 fprintf(stat_config.output,
304 "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
305 perf_evsel__name(counter),
306 cpu,
307 count->val, count->ena, count->run);
308 }
301 } 309 }
302 } 310 }
303 311
@@ -528,6 +536,7 @@ static int __run_perf_stat(int argc, const char **argv)
528 perf_evlist__set_leader(evsel_list); 536 perf_evlist__set_leader(evsel_list);
529 537
530 evlist__for_each(evsel_list, counter) { 538 evlist__for_each(evsel_list, counter) {
539try_again:
531 if (create_perf_stat_counter(counter) < 0) { 540 if (create_perf_stat_counter(counter) < 0) {
532 /* 541 /*
533 * PPC returns ENXIO for HW counters until 2.6.37 542 * PPC returns ENXIO for HW counters until 2.6.37
@@ -544,7 +553,11 @@ static int __run_perf_stat(int argc, const char **argv)
544 if ((counter->leader != counter) || 553 if ((counter->leader != counter) ||
545 !(counter->leader->nr_members > 1)) 554 !(counter->leader->nr_members > 1))
546 continue; 555 continue;
547 } 556 } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
557 if (verbose)
558 ui__warning("%s\n", msg);
559 goto try_again;
560 }
548 561
549 perf_evsel__open_strerror(counter, &target, 562 perf_evsel__open_strerror(counter, &target,
550 errno, msg, sizeof(msg)); 563 errno, msg, sizeof(msg));
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 833214979c4f..1793da585676 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -688,7 +688,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
688 struct hist_entry *he = iter->he; 688 struct hist_entry *he = iter->he;
689 struct perf_evsel *evsel = iter->evsel; 689 struct perf_evsel *evsel = iter->evsel;
690 690
691 if (sort__has_sym && single) 691 if (perf_hpp_list.sym && single)
692 perf_top__record_precise_ip(top, he, evsel->idx, al->addr); 692 perf_top__record_precise_ip(top, he, evsel->idx, al->addr);
693 693
694 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 694 hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
@@ -886,7 +886,7 @@ static int perf_top__start_counters(struct perf_top *top)
886 struct perf_evlist *evlist = top->evlist; 886 struct perf_evlist *evlist = top->evlist;
887 struct record_opts *opts = &top->record_opts; 887 struct record_opts *opts = &top->record_opts;
888 888
889 perf_evlist__config(evlist, opts); 889 perf_evlist__config(evlist, opts, &callchain_param);
890 890
891 evlist__for_each(evlist, counter) { 891 evlist__for_each(evlist, counter) {
892try_again: 892try_again:
@@ -917,15 +917,15 @@ out_err:
917 return -1; 917 return -1;
918} 918}
919 919
920static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused) 920static int callchain_param__setup_sample_type(struct callchain_param *callchain)
921{ 921{
922 if (!sort__has_sym) { 922 if (!perf_hpp_list.sym) {
923 if (symbol_conf.use_callchain) { 923 if (callchain->enabled) {
924 ui__error("Selected -g but \"sym\" not present in --sort/-s."); 924 ui__error("Selected -g but \"sym\" not present in --sort/-s.");
925 return -EINVAL; 925 return -EINVAL;
926 } 926 }
927 } else if (callchain_param.mode != CHAIN_NONE) { 927 } else if (callchain->mode != CHAIN_NONE) {
928 if (callchain_register_param(&callchain_param) < 0) { 928 if (callchain_register_param(callchain) < 0) {
929 ui__error("Can't register callchain params.\n"); 929 ui__error("Can't register callchain params.\n");
930 return -EINVAL; 930 return -EINVAL;
931 } 931 }
@@ -952,7 +952,7 @@ static int __cmd_top(struct perf_top *top)
952 goto out_delete; 952 goto out_delete;
953 } 953 }
954 954
955 ret = perf_top__setup_sample_type(top); 955 ret = callchain_param__setup_sample_type(&callchain_param);
956 if (ret) 956 if (ret)
957 goto out_delete; 957 goto out_delete;
958 958
@@ -962,7 +962,7 @@ static int __cmd_top(struct perf_top *top)
962 machine__synthesize_threads(&top->session->machines.host, &opts->target, 962 machine__synthesize_threads(&top->session->machines.host, &opts->target,
963 top->evlist->threads, false, opts->proc_map_timeout); 963 top->evlist->threads, false, opts->proc_map_timeout);
964 964
965 if (sort__has_socket) { 965 if (perf_hpp_list.socket) {
966 ret = perf_env__read_cpu_topology_map(&perf_env); 966 ret = perf_env__read_cpu_topology_map(&perf_env);
967 if (ret < 0) 967 if (ret < 0)
968 goto out_err_cpu_topo; 968 goto out_err_cpu_topo;
@@ -1045,18 +1045,17 @@ callchain_opt(const struct option *opt, const char *arg, int unset)
1045static int 1045static int
1046parse_callchain_opt(const struct option *opt, const char *arg, int unset) 1046parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1047{ 1047{
1048 struct record_opts *record = (struct record_opts *)opt->value; 1048 struct callchain_param *callchain = opt->value;
1049 1049
1050 record->callgraph_set = true; 1050 callchain->enabled = !unset;
1051 callchain_param.enabled = !unset; 1051 callchain->record_mode = CALLCHAIN_FP;
1052 callchain_param.record_mode = CALLCHAIN_FP;
1053 1052
1054 /* 1053 /*
1055 * --no-call-graph 1054 * --no-call-graph
1056 */ 1055 */
1057 if (unset) { 1056 if (unset) {
1058 symbol_conf.use_callchain = false; 1057 symbol_conf.use_callchain = false;
1059 callchain_param.record_mode = CALLCHAIN_NONE; 1058 callchain->record_mode = CALLCHAIN_NONE;
1060 return 0; 1059 return 0;
1061 } 1060 }
1062 1061
@@ -1104,7 +1103,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1104 }, 1103 },
1105 .proc_map_timeout = 500, 1104 .proc_map_timeout = 500,
1106 }, 1105 },
1107 .max_stack = PERF_MAX_STACK_DEPTH, 1106 .max_stack = sysctl_perf_event_max_stack,
1108 .sym_pcnt_filter = 5, 1107 .sym_pcnt_filter = 5,
1109 }; 1108 };
1110 struct record_opts *opts = &top.record_opts; 1109 struct record_opts *opts = &top.record_opts;
@@ -1162,17 +1161,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1162 "output field(s): overhead, period, sample plus all of sort keys"), 1161 "output field(s): overhead, period, sample plus all of sort keys"),
1163 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1162 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1164 "Show a column with the number of samples"), 1163 "Show a column with the number of samples"),
1165 OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts, 1164 OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
1166 NULL, "enables call-graph recording and display", 1165 NULL, "enables call-graph recording and display",
1167 &callchain_opt), 1166 &callchain_opt),
1168 OPT_CALLBACK(0, "call-graph", &top.record_opts, 1167 OPT_CALLBACK(0, "call-graph", &callchain_param,
1169 "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]", 1168 "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]",
1170 top_callchain_help, &parse_callchain_opt), 1169 top_callchain_help, &parse_callchain_opt),
1171 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 1170 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
1172 "Accumulate callchains of children and show total overhead as well"), 1171 "Accumulate callchains of children and show total overhead as well"),
1173 OPT_INTEGER(0, "max-stack", &top.max_stack, 1172 OPT_INTEGER(0, "max-stack", &top.max_stack,
1174 "Set the maximum stack depth when parsing the callchain. " 1173 "Set the maximum stack depth when parsing the callchain. "
1175 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 1174 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
1176 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 1175 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
1177 "ignore callees of these functions in call graphs", 1176 "ignore callees of these functions in call graphs",
1178 report_parse_ignore_callees_opt), 1177 report_parse_ignore_callees_opt),
@@ -1256,7 +1255,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1256 1255
1257 sort__mode = SORT_MODE__TOP; 1256 sort__mode = SORT_MODE__TOP;
1258 /* display thread wants entries to be collapsed in a different tree */ 1257 /* display thread wants entries to be collapsed in a different tree */
1259 sort__need_collapse = 1; 1258 perf_hpp_list.need_collapse = 1;
1260 1259
1261 if (top.use_stdio) 1260 if (top.use_stdio)
1262 use_browser = 0; 1261 use_browser = 0;
@@ -1312,7 +1311,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1312 1311
1313 top.sym_evsel = perf_evlist__first(top.evlist); 1312 top.sym_evsel = perf_evlist__first(top.evlist);
1314 1313
1315 if (!symbol_conf.use_callchain) { 1314 if (!callchain_param.enabled) {
1316 symbol_conf.cumulate_callchain = false; 1315 symbol_conf.cumulate_callchain = false;
1317 perf_hpp__cancel_cumulate(); 1316 perf_hpp__cancel_cumulate();
1318 } 1317 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 93ac724fb635..6e5c325148e4 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -34,79 +34,76 @@
34#include "trace-event.h" 34#include "trace-event.h"
35#include "util/parse-events.h" 35#include "util/parse-events.h"
36#include "util/bpf-loader.h" 36#include "util/bpf-loader.h"
37#include "callchain.h"
38#include "syscalltbl.h"
39#include "rb_resort.h"
37 40
38#include <libaudit.h> 41#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
39#include <stdlib.h> 42#include <stdlib.h>
40#include <sys/mman.h>
41#include <linux/futex.h>
42#include <linux/err.h> 43#include <linux/err.h>
43 44#include <linux/filter.h>
44/* For older distros: */ 45#include <linux/audit.h>
45#ifndef MAP_STACK 46#include <sys/ptrace.h>
46# define MAP_STACK 0x20000 47#include <linux/random.h>
47#endif 48#include <linux/stringify.h>
48
49#ifndef MADV_HWPOISON
50# define MADV_HWPOISON 100
51
52#endif
53
54#ifndef MADV_MERGEABLE
55# define MADV_MERGEABLE 12
56#endif
57
58#ifndef MADV_UNMERGEABLE
59# define MADV_UNMERGEABLE 13
60#endif
61
62#ifndef EFD_SEMAPHORE
63# define EFD_SEMAPHORE 1
64#endif
65
66#ifndef EFD_NONBLOCK
67# define EFD_NONBLOCK 00004000
68#endif
69
70#ifndef EFD_CLOEXEC
71# define EFD_CLOEXEC 02000000
72#endif
73 49
74#ifndef O_CLOEXEC 50#ifndef O_CLOEXEC
75# define O_CLOEXEC 02000000 51# define O_CLOEXEC 02000000
76#endif 52#endif
77 53
78#ifndef SOCK_DCCP 54struct trace {
79# define SOCK_DCCP 6 55 struct perf_tool tool;
80#endif 56 struct syscalltbl *sctbl;
81 57 struct {
82#ifndef SOCK_CLOEXEC 58 int max;
83# define SOCK_CLOEXEC 02000000 59 struct syscall *table;
84#endif 60 struct {
85 61 struct perf_evsel *sys_enter,
86#ifndef SOCK_NONBLOCK 62 *sys_exit;
87# define SOCK_NONBLOCK 00004000 63 } events;
88#endif 64 } syscalls;
89 65 struct record_opts opts;
90#ifndef MSG_CMSG_CLOEXEC 66 struct perf_evlist *evlist;
91# define MSG_CMSG_CLOEXEC 0x40000000 67 struct machine *host;
92#endif 68 struct thread *current;
93 69 u64 base_time;
94#ifndef PERF_FLAG_FD_NO_GROUP 70 FILE *output;
95# define PERF_FLAG_FD_NO_GROUP (1UL << 0) 71 unsigned long nr_events;
96#endif 72 struct strlist *ev_qualifier;
97 73 struct {
98#ifndef PERF_FLAG_FD_OUTPUT 74 size_t nr;
99# define PERF_FLAG_FD_OUTPUT (1UL << 1) 75 int *entries;
100#endif 76 } ev_qualifier_ids;
101 77 struct intlist *tid_list;
102#ifndef PERF_FLAG_PID_CGROUP 78 struct intlist *pid_list;
103# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */ 79 struct {
104#endif 80 size_t nr;
105 81 pid_t *entries;
106#ifndef PERF_FLAG_FD_CLOEXEC 82 } filter_pids;
107# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */ 83 double duration_filter;
108#endif 84 double runtime_ms;
109 85 struct {
86 u64 vfs_getname,
87 proc_getname;
88 } stats;
89 unsigned int max_stack;
90 unsigned int min_stack;
91 bool not_ev_qualifier;
92 bool live;
93 bool full_time;
94 bool sched;
95 bool multiple_threads;
96 bool summary;
97 bool summary_only;
98 bool show_comm;
99 bool show_tool_stats;
100 bool trace_syscalls;
101 bool kernel_syscallchains;
102 bool force;
103 bool vfs_getname;
104 int trace_pgfaults;
105 int open_id;
106};
110 107
111struct tp_field { 108struct tp_field {
112 int offset; 109 int offset;
@@ -371,221 +368,6 @@ static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
371 368
372#define SCA_INT syscall_arg__scnprintf_int 369#define SCA_INT syscall_arg__scnprintf_int
373 370
374static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
375 struct syscall_arg *arg)
376{
377 int printed = 0, prot = arg->val;
378
379 if (prot == PROT_NONE)
380 return scnprintf(bf, size, "NONE");
381#define P_MMAP_PROT(n) \
382 if (prot & PROT_##n) { \
383 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
384 prot &= ~PROT_##n; \
385 }
386
387 P_MMAP_PROT(EXEC);
388 P_MMAP_PROT(READ);
389 P_MMAP_PROT(WRITE);
390#ifdef PROT_SEM
391 P_MMAP_PROT(SEM);
392#endif
393 P_MMAP_PROT(GROWSDOWN);
394 P_MMAP_PROT(GROWSUP);
395#undef P_MMAP_PROT
396
397 if (prot)
398 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
399
400 return printed;
401}
402
403#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
404
405static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
406 struct syscall_arg *arg)
407{
408 int printed = 0, flags = arg->val;
409
410#define P_MMAP_FLAG(n) \
411 if (flags & MAP_##n) { \
412 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
413 flags &= ~MAP_##n; \
414 }
415
416 P_MMAP_FLAG(SHARED);
417 P_MMAP_FLAG(PRIVATE);
418#ifdef MAP_32BIT
419 P_MMAP_FLAG(32BIT);
420#endif
421 P_MMAP_FLAG(ANONYMOUS);
422 P_MMAP_FLAG(DENYWRITE);
423 P_MMAP_FLAG(EXECUTABLE);
424 P_MMAP_FLAG(FILE);
425 P_MMAP_FLAG(FIXED);
426 P_MMAP_FLAG(GROWSDOWN);
427#ifdef MAP_HUGETLB
428 P_MMAP_FLAG(HUGETLB);
429#endif
430 P_MMAP_FLAG(LOCKED);
431 P_MMAP_FLAG(NONBLOCK);
432 P_MMAP_FLAG(NORESERVE);
433 P_MMAP_FLAG(POPULATE);
434 P_MMAP_FLAG(STACK);
435#ifdef MAP_UNINITIALIZED
436 P_MMAP_FLAG(UNINITIALIZED);
437#endif
438#undef P_MMAP_FLAG
439
440 if (flags)
441 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
442
443 return printed;
444}
445
446#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
447
448static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
449 struct syscall_arg *arg)
450{
451 int printed = 0, flags = arg->val;
452
453#define P_MREMAP_FLAG(n) \
454 if (flags & MREMAP_##n) { \
455 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
456 flags &= ~MREMAP_##n; \
457 }
458
459 P_MREMAP_FLAG(MAYMOVE);
460#ifdef MREMAP_FIXED
461 P_MREMAP_FLAG(FIXED);
462#endif
463#undef P_MREMAP_FLAG
464
465 if (flags)
466 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
467
468 return printed;
469}
470
471#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
472
473static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
474 struct syscall_arg *arg)
475{
476 int behavior = arg->val;
477
478 switch (behavior) {
479#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
480 P_MADV_BHV(NORMAL);
481 P_MADV_BHV(RANDOM);
482 P_MADV_BHV(SEQUENTIAL);
483 P_MADV_BHV(WILLNEED);
484 P_MADV_BHV(DONTNEED);
485 P_MADV_BHV(REMOVE);
486 P_MADV_BHV(DONTFORK);
487 P_MADV_BHV(DOFORK);
488 P_MADV_BHV(HWPOISON);
489#ifdef MADV_SOFT_OFFLINE
490 P_MADV_BHV(SOFT_OFFLINE);
491#endif
492 P_MADV_BHV(MERGEABLE);
493 P_MADV_BHV(UNMERGEABLE);
494#ifdef MADV_HUGEPAGE
495 P_MADV_BHV(HUGEPAGE);
496#endif
497#ifdef MADV_NOHUGEPAGE
498 P_MADV_BHV(NOHUGEPAGE);
499#endif
500#ifdef MADV_DONTDUMP
501 P_MADV_BHV(DONTDUMP);
502#endif
503#ifdef MADV_DODUMP
504 P_MADV_BHV(DODUMP);
505#endif
506#undef P_MADV_PHV
507 default: break;
508 }
509
510 return scnprintf(bf, size, "%#x", behavior);
511}
512
513#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
514
515static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
516 struct syscall_arg *arg)
517{
518 int printed = 0, op = arg->val;
519
520 if (op == 0)
521 return scnprintf(bf, size, "NONE");
522#define P_CMD(cmd) \
523 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
524 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
525 op &= ~LOCK_##cmd; \
526 }
527
528 P_CMD(SH);
529 P_CMD(EX);
530 P_CMD(NB);
531 P_CMD(UN);
532 P_CMD(MAND);
533 P_CMD(RW);
534 P_CMD(READ);
535 P_CMD(WRITE);
536#undef P_OP
537
538 if (op)
539 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
540
541 return printed;
542}
543
544#define SCA_FLOCK syscall_arg__scnprintf_flock
545
546static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
547{
548 enum syscall_futex_args {
549 SCF_UADDR = (1 << 0),
550 SCF_OP = (1 << 1),
551 SCF_VAL = (1 << 2),
552 SCF_TIMEOUT = (1 << 3),
553 SCF_UADDR2 = (1 << 4),
554 SCF_VAL3 = (1 << 5),
555 };
556 int op = arg->val;
557 int cmd = op & FUTEX_CMD_MASK;
558 size_t printed = 0;
559
560 switch (cmd) {
561#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
562 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
563 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
564 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
565 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
566 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
567 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
568 P_FUTEX_OP(WAKE_OP); break;
569 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
570 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
571 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
572 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
573 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
574 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
575 default: printed = scnprintf(bf, size, "%#x", cmd); break;
576 }
577
578 if (op & FUTEX_PRIVATE_FLAG)
579 printed += scnprintf(bf + printed, size - printed, "|PRIV");
580
581 if (op & FUTEX_CLOCK_REALTIME)
582 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
583
584 return printed;
585}
586
587#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
588
589static const char *bpf_cmd[] = { 371static const char *bpf_cmd[] = {
590 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM", 372 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
591 "MAP_GET_NEXT_KEY", "PROG_LOAD", 373 "MAP_GET_NEXT_KEY", "PROG_LOAD",
@@ -652,110 +434,6 @@ static const char *socket_families[] = {
652}; 434};
653static DEFINE_STRARRAY(socket_families); 435static DEFINE_STRARRAY(socket_families);
654 436
655#ifndef SOCK_TYPE_MASK
656#define SOCK_TYPE_MASK 0xf
657#endif
658
659static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
660 struct syscall_arg *arg)
661{
662 size_t printed;
663 int type = arg->val,
664 flags = type & ~SOCK_TYPE_MASK;
665
666 type &= SOCK_TYPE_MASK;
667 /*
668 * Can't use a strarray, MIPS may override for ABI reasons.
669 */
670 switch (type) {
671#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
672 P_SK_TYPE(STREAM);
673 P_SK_TYPE(DGRAM);
674 P_SK_TYPE(RAW);
675 P_SK_TYPE(RDM);
676 P_SK_TYPE(SEQPACKET);
677 P_SK_TYPE(DCCP);
678 P_SK_TYPE(PACKET);
679#undef P_SK_TYPE
680 default:
681 printed = scnprintf(bf, size, "%#x", type);
682 }
683
684#define P_SK_FLAG(n) \
685 if (flags & SOCK_##n) { \
686 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
687 flags &= ~SOCK_##n; \
688 }
689
690 P_SK_FLAG(CLOEXEC);
691 P_SK_FLAG(NONBLOCK);
692#undef P_SK_FLAG
693
694 if (flags)
695 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
696
697 return printed;
698}
699
700#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
701
702#ifndef MSG_PROBE
703#define MSG_PROBE 0x10
704#endif
705#ifndef MSG_WAITFORONE
706#define MSG_WAITFORONE 0x10000
707#endif
708#ifndef MSG_SENDPAGE_NOTLAST
709#define MSG_SENDPAGE_NOTLAST 0x20000
710#endif
711#ifndef MSG_FASTOPEN
712#define MSG_FASTOPEN 0x20000000
713#endif
714
715static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
716 struct syscall_arg *arg)
717{
718 int printed = 0, flags = arg->val;
719
720 if (flags == 0)
721 return scnprintf(bf, size, "NONE");
722#define P_MSG_FLAG(n) \
723 if (flags & MSG_##n) { \
724 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
725 flags &= ~MSG_##n; \
726 }
727
728 P_MSG_FLAG(OOB);
729 P_MSG_FLAG(PEEK);
730 P_MSG_FLAG(DONTROUTE);
731 P_MSG_FLAG(TRYHARD);
732 P_MSG_FLAG(CTRUNC);
733 P_MSG_FLAG(PROBE);
734 P_MSG_FLAG(TRUNC);
735 P_MSG_FLAG(DONTWAIT);
736 P_MSG_FLAG(EOR);
737 P_MSG_FLAG(WAITALL);
738 P_MSG_FLAG(FIN);
739 P_MSG_FLAG(SYN);
740 P_MSG_FLAG(CONFIRM);
741 P_MSG_FLAG(RST);
742 P_MSG_FLAG(ERRQUEUE);
743 P_MSG_FLAG(NOSIGNAL);
744 P_MSG_FLAG(MORE);
745 P_MSG_FLAG(WAITFORONE);
746 P_MSG_FLAG(SENDPAGE_NOTLAST);
747 P_MSG_FLAG(FASTOPEN);
748 P_MSG_FLAG(CMSG_CLOEXEC);
749#undef P_MSG_FLAG
750
751 if (flags)
752 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
753
754 return printed;
755}
756
757#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
758
759static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size, 437static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
760 struct syscall_arg *arg) 438 struct syscall_arg *arg)
761{ 439{
@@ -788,116 +466,6 @@ static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
788 466
789#define SCA_FILENAME syscall_arg__scnprintf_filename 467#define SCA_FILENAME syscall_arg__scnprintf_filename
790 468
791static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
792 struct syscall_arg *arg)
793{
794 int printed = 0, flags = arg->val;
795
796 if (!(flags & O_CREAT))
797 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
798
799 if (flags == 0)
800 return scnprintf(bf, size, "RDONLY");
801#define P_FLAG(n) \
802 if (flags & O_##n) { \
803 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
804 flags &= ~O_##n; \
805 }
806
807 P_FLAG(APPEND);
808 P_FLAG(ASYNC);
809 P_FLAG(CLOEXEC);
810 P_FLAG(CREAT);
811 P_FLAG(DIRECT);
812 P_FLAG(DIRECTORY);
813 P_FLAG(EXCL);
814 P_FLAG(LARGEFILE);
815 P_FLAG(NOATIME);
816 P_FLAG(NOCTTY);
817#ifdef O_NONBLOCK
818 P_FLAG(NONBLOCK);
819#elif O_NDELAY
820 P_FLAG(NDELAY);
821#endif
822#ifdef O_PATH
823 P_FLAG(PATH);
824#endif
825 P_FLAG(RDWR);
826#ifdef O_DSYNC
827 if ((flags & O_SYNC) == O_SYNC)
828 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
829 else {
830 P_FLAG(DSYNC);
831 }
832#else
833 P_FLAG(SYNC);
834#endif
835 P_FLAG(TRUNC);
836 P_FLAG(WRONLY);
837#undef P_FLAG
838
839 if (flags)
840 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
841
842 return printed;
843}
844
845#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
846
847static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
848 struct syscall_arg *arg)
849{
850 int printed = 0, flags = arg->val;
851
852 if (flags == 0)
853 return 0;
854
855#define P_FLAG(n) \
856 if (flags & PERF_FLAG_##n) { \
857 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
858 flags &= ~PERF_FLAG_##n; \
859 }
860
861 P_FLAG(FD_NO_GROUP);
862 P_FLAG(FD_OUTPUT);
863 P_FLAG(PID_CGROUP);
864 P_FLAG(FD_CLOEXEC);
865#undef P_FLAG
866
867 if (flags)
868 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
869
870 return printed;
871}
872
873#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
874
875static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
876 struct syscall_arg *arg)
877{
878 int printed = 0, flags = arg->val;
879
880 if (flags == 0)
881 return scnprintf(bf, size, "NONE");
882#define P_FLAG(n) \
883 if (flags & EFD_##n) { \
884 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
885 flags &= ~EFD_##n; \
886 }
887
888 P_FLAG(SEMAPHORE);
889 P_FLAG(CLOEXEC);
890 P_FLAG(NONBLOCK);
891#undef P_FLAG
892
893 if (flags)
894 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
895
896 return printed;
897}
898
899#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
900
901static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, 469static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
902 struct syscall_arg *arg) 470 struct syscall_arg *arg)
903{ 471{
@@ -921,59 +489,6 @@ static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
921 489
922#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags 490#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
923 491
924static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
925{
926 int sig = arg->val;
927
928 switch (sig) {
929#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
930 P_SIGNUM(HUP);
931 P_SIGNUM(INT);
932 P_SIGNUM(QUIT);
933 P_SIGNUM(ILL);
934 P_SIGNUM(TRAP);
935 P_SIGNUM(ABRT);
936 P_SIGNUM(BUS);
937 P_SIGNUM(FPE);
938 P_SIGNUM(KILL);
939 P_SIGNUM(USR1);
940 P_SIGNUM(SEGV);
941 P_SIGNUM(USR2);
942 P_SIGNUM(PIPE);
943 P_SIGNUM(ALRM);
944 P_SIGNUM(TERM);
945 P_SIGNUM(CHLD);
946 P_SIGNUM(CONT);
947 P_SIGNUM(STOP);
948 P_SIGNUM(TSTP);
949 P_SIGNUM(TTIN);
950 P_SIGNUM(TTOU);
951 P_SIGNUM(URG);
952 P_SIGNUM(XCPU);
953 P_SIGNUM(XFSZ);
954 P_SIGNUM(VTALRM);
955 P_SIGNUM(PROF);
956 P_SIGNUM(WINCH);
957 P_SIGNUM(IO);
958 P_SIGNUM(PWR);
959 P_SIGNUM(SYS);
960#ifdef SIGEMT
961 P_SIGNUM(EMT);
962#endif
963#ifdef SIGSTKFLT
964 P_SIGNUM(STKFLT);
965#endif
966#ifdef SIGSWI
967 P_SIGNUM(SWI);
968#endif
969 default: break;
970 }
971
972 return scnprintf(bf, size, "%#x", sig);
973}
974
975#define SCA_SIGNUM syscall_arg__scnprintf_signum
976
977#if defined(__i386__) || defined(__x86_64__) 492#if defined(__i386__) || defined(__x86_64__)
978/* 493/*
979 * FIXME: Make this available to all arches. 494 * FIXME: Make this available to all arches.
@@ -1001,16 +516,62 @@ static const char *tioctls[] = {
1001static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401); 516static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
1002#endif /* defined(__i386__) || defined(__x86_64__) */ 517#endif /* defined(__i386__) || defined(__x86_64__) */
1003 518
519#ifndef GRND_NONBLOCK
520#define GRND_NONBLOCK 0x0001
521#endif
522#ifndef GRND_RANDOM
523#define GRND_RANDOM 0x0002
524#endif
525
526static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
527 struct syscall_arg *arg)
528{
529 int printed = 0, flags = arg->val;
530
531#define P_FLAG(n) \
532 if (flags & GRND_##n) { \
533 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
534 flags &= ~GRND_##n; \
535 }
536
537 P_FLAG(RANDOM);
538 P_FLAG(NONBLOCK);
539#undef P_FLAG
540
541 if (flags)
542 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
543
544 return printed;
545}
546
547#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
548
1004#define STRARRAY(arg, name, array) \ 549#define STRARRAY(arg, name, array) \
1005 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ 550 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
1006 .arg_parm = { [arg] = &strarray__##array, } 551 .arg_parm = { [arg] = &strarray__##array, }
1007 552
553#include "trace/beauty/eventfd.c"
554#include "trace/beauty/flock.c"
555#include "trace/beauty/futex_op.c"
556#include "trace/beauty/mmap.c"
557#include "trace/beauty/mode_t.c"
558#include "trace/beauty/msg_flags.c"
559#include "trace/beauty/open_flags.c"
560#include "trace/beauty/perf_event_open.c"
561#include "trace/beauty/pid.c"
562#include "trace/beauty/sched_policy.c"
563#include "trace/beauty/seccomp.c"
564#include "trace/beauty/signum.c"
565#include "trace/beauty/socket_type.c"
566#include "trace/beauty/waitid_options.c"
567
1008static struct syscall_fmt { 568static struct syscall_fmt {
1009 const char *name; 569 const char *name;
1010 const char *alias; 570 const char *alias;
1011 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg); 571 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
1012 void *arg_parm[6]; 572 void *arg_parm[6];
1013 bool errmsg; 573 bool errmsg;
574 bool errpid;
1014 bool timeout; 575 bool timeout;
1015 bool hexret; 576 bool hexret;
1016} syscall_fmts[] = { 577} syscall_fmts[] = {
@@ -1028,6 +589,7 @@ static struct syscall_fmt {
1028 { .name = "chroot", .errmsg = true, 589 { .name = "chroot", .errmsg = true,
1029 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 590 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1030 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, 591 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
592 { .name = "clone", .errpid = true, },
1031 { .name = "close", .errmsg = true, 593 { .name = "close", .errmsg = true,
1032 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 594 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
1033 { .name = "connect", .errmsg = true, }, 595 { .name = "connect", .errmsg = true, },
@@ -1093,6 +655,11 @@ static struct syscall_fmt {
1093 { .name = "getdents64", .errmsg = true, 655 { .name = "getdents64", .errmsg = true,
1094 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 656 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1095 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 657 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
658 { .name = "getpid", .errpid = true, },
659 { .name = "getpgid", .errpid = true, },
660 { .name = "getppid", .errpid = true, },
661 { .name = "getrandom", .errmsg = true,
662 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
1096 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 663 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1097 { .name = "getxattr", .errmsg = true, 664 { .name = "getxattr", .errmsg = true,
1098 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 665 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
@@ -1186,8 +753,7 @@ static struct syscall_fmt {
1186 [1] = SCA_FILENAME, /* filename */ 753 [1] = SCA_FILENAME, /* filename */
1187 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 754 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
1188 { .name = "perf_event_open", .errmsg = true, 755 { .name = "perf_event_open", .errmsg = true,
1189 .arg_scnprintf = { [1] = SCA_INT, /* pid */ 756 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
1190 [2] = SCA_INT, /* cpu */
1191 [3] = SCA_FD, /* group_fd */ 757 [3] = SCA_FD, /* group_fd */
1192 [4] = SCA_PERF_FLAGS, /* flags */ }, }, 758 [4] = SCA_PERF_FLAGS, /* flags */ }, },
1193 { .name = "pipe2", .errmsg = true, 759 { .name = "pipe2", .errmsg = true,
@@ -1234,6 +800,11 @@ static struct syscall_fmt {
1234 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 800 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1235 { .name = "rt_tgsigqueueinfo", .errmsg = true, 801 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1236 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 802 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
803 { .name = "sched_setscheduler", .errmsg = true,
804 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
805 { .name = "seccomp", .errmsg = true,
806 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
807 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
1237 { .name = "select", .errmsg = true, .timeout = true, }, 808 { .name = "select", .errmsg = true, .timeout = true, },
1238 { .name = "sendmmsg", .errmsg = true, 809 { .name = "sendmmsg", .errmsg = true,
1239 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 810 .arg_scnprintf = { [0] = SCA_FD, /* fd */
@@ -1244,7 +815,9 @@ static struct syscall_fmt {
1244 { .name = "sendto", .errmsg = true, 815 { .name = "sendto", .errmsg = true,
1245 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 816 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1246 [3] = SCA_MSG_FLAGS, /* flags */ }, }, 817 [3] = SCA_MSG_FLAGS, /* flags */ }, },
818 { .name = "set_tid_address", .errpid = true, },
1247 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 819 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
820 { .name = "setpgid", .errmsg = true, },
1248 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 821 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1249 { .name = "setxattr", .errmsg = true, 822 { .name = "setxattr", .errmsg = true,
1250 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 823 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
@@ -1287,6 +860,10 @@ static struct syscall_fmt {
1287 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 860 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1288 { .name = "vmsplice", .errmsg = true, 861 { .name = "vmsplice", .errmsg = true,
1289 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 862 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
863 { .name = "wait4", .errpid = true,
864 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
865 { .name = "waitid", .errpid = true,
866 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
1290 { .name = "write", .errmsg = true, 867 { .name = "write", .errmsg = true,
1291 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 868 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1292 { .name = "writev", .errmsg = true, 869 { .name = "writev", .errmsg = true,
@@ -1398,59 +975,6 @@ fail:
1398 975
1399static const size_t trace__entry_str_size = 2048; 976static const size_t trace__entry_str_size = 2048;
1400 977
1401struct trace {
1402 struct perf_tool tool;
1403 struct {
1404 int machine;
1405 int open_id;
1406 } audit;
1407 struct {
1408 int max;
1409 struct syscall *table;
1410 struct {
1411 struct perf_evsel *sys_enter,
1412 *sys_exit;
1413 } events;
1414 } syscalls;
1415 struct record_opts opts;
1416 struct perf_evlist *evlist;
1417 struct machine *host;
1418 struct thread *current;
1419 u64 base_time;
1420 FILE *output;
1421 unsigned long nr_events;
1422 struct strlist *ev_qualifier;
1423 struct {
1424 size_t nr;
1425 int *entries;
1426 } ev_qualifier_ids;
1427 struct intlist *tid_list;
1428 struct intlist *pid_list;
1429 struct {
1430 size_t nr;
1431 pid_t *entries;
1432 } filter_pids;
1433 double duration_filter;
1434 double runtime_ms;
1435 struct {
1436 u64 vfs_getname,
1437 proc_getname;
1438 } stats;
1439 bool not_ev_qualifier;
1440 bool live;
1441 bool full_time;
1442 bool sched;
1443 bool multiple_threads;
1444 bool summary;
1445 bool summary_only;
1446 bool show_comm;
1447 bool show_tool_stats;
1448 bool trace_syscalls;
1449 bool force;
1450 bool vfs_getname;
1451 int trace_pgfaults;
1452};
1453
1454static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) 978static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1455{ 979{
1456 struct thread_trace *ttrace = thread__priv(thread); 980 struct thread_trace *ttrace = thread__priv(thread);
@@ -1618,6 +1142,7 @@ static int trace__process_event(struct trace *trace, struct machine *machine,
1618 color_fprintf(trace->output, PERF_COLOR_RED, 1142 color_fprintf(trace->output, PERF_COLOR_RED,
1619 "LOST %" PRIu64 " events!\n", event->lost.lost); 1143 "LOST %" PRIu64 " events!\n", event->lost.lost);
1620 ret = machine__process_lost_event(machine, event, sample); 1144 ret = machine__process_lost_event(machine, event, sample);
1145 break;
1621 default: 1146 default:
1622 ret = machine__process_event(machine, event, sample); 1147 ret = machine__process_event(machine, event, sample);
1623 break; 1148 break;
@@ -1675,6 +1200,10 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1675 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; 1200 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1676 else if (field->flags & FIELD_IS_POINTER) 1201 else if (field->flags & FIELD_IS_POINTER)
1677 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; 1202 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1203 else if (strcmp(field->type, "pid_t") == 0)
1204 sc->arg_scnprintf[idx] = SCA_PID;
1205 else if (strcmp(field->type, "umode_t") == 0)
1206 sc->arg_scnprintf[idx] = SCA_MODE_T;
1678 ++idx; 1207 ++idx;
1679 } 1208 }
1680 1209
@@ -1685,7 +1214,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1685{ 1214{
1686 char tp_name[128]; 1215 char tp_name[128];
1687 struct syscall *sc; 1216 struct syscall *sc;
1688 const char *name = audit_syscall_to_name(id, trace->audit.machine); 1217 const char *name = syscalltbl__name(trace->sctbl, id);
1689 1218
1690 if (name == NULL) 1219 if (name == NULL)
1691 return -1; 1220 return -1;
@@ -1760,7 +1289,7 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1760 1289
1761 strlist__for_each(pos, trace->ev_qualifier) { 1290 strlist__for_each(pos, trace->ev_qualifier) {
1762 const char *sc = pos->s; 1291 const char *sc = pos->s;
1763 int id = audit_name_to_syscall(sc, trace->audit.machine); 1292 int id = syscalltbl__id(trace->sctbl, sc);
1764 1293
1765 if (id < 0) { 1294 if (id < 0) {
1766 if (err == 0) { 1295 if (err == 0) {
@@ -1846,7 +1375,12 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1846 "%ld", val); 1375 "%ld", val);
1847 } 1376 }
1848 } 1377 }
1849 } else { 1378 } else if (IS_ERR(sc->tp_format)) {
1379 /*
1380 * If we managed to read the tracepoint /format file, then we
1381 * may end up not having any args, like with gettid(), so only
1382 * print the raw args when we didn't manage to read it.
1383 */
1850 int i = 0; 1384 int i = 0;
1851 1385
1852 while (i < 6) { 1386 while (i < 6) {
@@ -1987,7 +1521,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1987 goto out_put; 1521 goto out_put;
1988 } 1522 }
1989 1523
1990 if (!trace->summary_only) 1524 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
1991 trace__printf_interrupted_entry(trace, sample); 1525 trace__printf_interrupted_entry(trace, sample);
1992 1526
1993 ttrace->entry_time = sample->time; 1527 ttrace->entry_time = sample->time;
@@ -1998,7 +1532,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1998 args, trace, thread); 1532 args, trace, thread);
1999 1533
2000 if (sc->is_exit) { 1534 if (sc->is_exit) {
2001 if (!trace->duration_filter && !trace->summary_only) { 1535 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
2002 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); 1536 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
2003 fprintf(trace->output, "%-70s\n", ttrace->entry_str); 1537 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
2004 } 1538 }
@@ -2018,6 +1552,29 @@ out_put:
2018 return err; 1552 return err;
2019} 1553}
2020 1554
1555static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1556 struct perf_sample *sample,
1557 struct callchain_cursor *cursor)
1558{
1559 struct addr_location al;
1560
1561 if (machine__resolve(trace->host, &al, sample) < 0 ||
1562 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1563 return -1;
1564
1565 return 0;
1566}
1567
1568static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1569{
1570 /* TODO: user-configurable print_opts */
1571 const unsigned int print_opts = EVSEL__PRINT_SYM |
1572 EVSEL__PRINT_DSO |
1573 EVSEL__PRINT_UNKNOWN_AS_ADDR;
1574
1575 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
1576}
1577
2021static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, 1578static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2022 union perf_event *event __maybe_unused, 1579 union perf_event *event __maybe_unused,
2023 struct perf_sample *sample) 1580 struct perf_sample *sample)
@@ -2025,7 +1582,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2025 long ret; 1582 long ret;
2026 u64 duration = 0; 1583 u64 duration = 0;
2027 struct thread *thread; 1584 struct thread *thread;
2028 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; 1585 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
2029 struct syscall *sc = trace__syscall_info(trace, evsel, id); 1586 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2030 struct thread_trace *ttrace; 1587 struct thread_trace *ttrace;
2031 1588
@@ -2042,7 +1599,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2042 1599
2043 ret = perf_evsel__sc_tp_uint(evsel, ret, sample); 1600 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
2044 1601
2045 if (id == trace->audit.open_id && ret >= 0 && ttrace->filename.pending_open) { 1602 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
2046 trace__set_fd_pathname(thread, ret, ttrace->filename.name); 1603 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
2047 ttrace->filename.pending_open = false; 1604 ttrace->filename.pending_open = false;
2048 ++trace->stats.vfs_getname; 1605 ++trace->stats.vfs_getname;
@@ -2057,6 +1614,15 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2057 } else if (trace->duration_filter) 1614 } else if (trace->duration_filter)
2058 goto out; 1615 goto out;
2059 1616
1617 if (sample->callchain) {
1618 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1619 if (callchain_ret == 0) {
1620 if (callchain_cursor.nr < trace->min_stack)
1621 goto out;
1622 callchain_ret = 1;
1623 }
1624 }
1625
2060 if (trace->summary_only) 1626 if (trace->summary_only)
2061 goto out; 1627 goto out;
2062 1628
@@ -2073,7 +1639,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2073 if (sc->fmt == NULL) { 1639 if (sc->fmt == NULL) {
2074signed_print: 1640signed_print:
2075 fprintf(trace->output, ") = %ld", ret); 1641 fprintf(trace->output, ") = %ld", ret);
2076 } else if (ret < 0 && sc->fmt->errmsg) { 1642 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
2077 char bf[STRERR_BUFSIZE]; 1643 char bf[STRERR_BUFSIZE];
2078 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 1644 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
2079 *e = audit_errno_to_name(-ret); 1645 *e = audit_errno_to_name(-ret);
@@ -2083,10 +1649,24 @@ signed_print:
2083 fprintf(trace->output, ") = 0 Timeout"); 1649 fprintf(trace->output, ") = 0 Timeout");
2084 else if (sc->fmt->hexret) 1650 else if (sc->fmt->hexret)
2085 fprintf(trace->output, ") = %#lx", ret); 1651 fprintf(trace->output, ") = %#lx", ret);
2086 else 1652 else if (sc->fmt->errpid) {
1653 struct thread *child = machine__find_thread(trace->host, ret, ret);
1654
1655 if (child != NULL) {
1656 fprintf(trace->output, ") = %ld", ret);
1657 if (child->comm_set)
1658 fprintf(trace->output, " (%s)", thread__comm_str(child));
1659 thread__put(child);
1660 }
1661 } else
2087 goto signed_print; 1662 goto signed_print;
2088 1663
2089 fputc('\n', trace->output); 1664 fputc('\n', trace->output);
1665
1666 if (callchain_ret > 0)
1667 trace__fprintf_callchain(trace, sample);
1668 else if (callchain_ret < 0)
1669 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2090out: 1670out:
2091 ttrace->entry_pending = false; 1671 ttrace->entry_pending = false;
2092 err = 0; 1672 err = 0;
@@ -2217,6 +1797,17 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2217 union perf_event *event __maybe_unused, 1797 union perf_event *event __maybe_unused,
2218 struct perf_sample *sample) 1798 struct perf_sample *sample)
2219{ 1799{
1800 int callchain_ret = 0;
1801
1802 if (sample->callchain) {
1803 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1804 if (callchain_ret == 0) {
1805 if (callchain_cursor.nr < trace->min_stack)
1806 goto out;
1807 callchain_ret = 1;
1808 }
1809 }
1810
2220 trace__printf_interrupted_entry(trace, sample); 1811 trace__printf_interrupted_entry(trace, sample);
2221 trace__fprintf_tstamp(trace, sample->time, trace->output); 1812 trace__fprintf_tstamp(trace, sample->time, trace->output);
2222 1813
@@ -2234,6 +1825,12 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2234 } 1825 }
2235 1826
2236 fprintf(trace->output, ")\n"); 1827 fprintf(trace->output, ")\n");
1828
1829 if (callchain_ret > 0)
1830 trace__fprintf_callchain(trace, sample);
1831 else if (callchain_ret < 0)
1832 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
1833out:
2237 return 0; 1834 return 0;
2238} 1835}
2239 1836
@@ -2264,8 +1861,19 @@ static int trace__pgfault(struct trace *trace,
2264 char map_type = 'd'; 1861 char map_type = 'd';
2265 struct thread_trace *ttrace; 1862 struct thread_trace *ttrace;
2266 int err = -1; 1863 int err = -1;
1864 int callchain_ret = 0;
2267 1865
2268 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 1866 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1867
1868 if (sample->callchain) {
1869 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1870 if (callchain_ret == 0) {
1871 if (callchain_cursor.nr < trace->min_stack)
1872 goto out_put;
1873 callchain_ret = 1;
1874 }
1875 }
1876
2269 ttrace = thread__trace(thread, trace->output); 1877 ttrace = thread__trace(thread, trace->output);
2270 if (ttrace == NULL) 1878 if (ttrace == NULL)
2271 goto out_put; 1879 goto out_put;
@@ -2307,6 +1915,11 @@ static int trace__pgfault(struct trace *trace,
2307 print_location(trace->output, sample, &al, true, false); 1915 print_location(trace->output, sample, &al, true, false);
2308 1916
2309 fprintf(trace->output, " (%c%c)\n", map_type, al.level); 1917 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
1918
1919 if (callchain_ret > 0)
1920 trace__fprintf_callchain(trace, sample);
1921 else if (callchain_ret < 0)
1922 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2310out: 1923out:
2311 err = 0; 1924 err = 0;
2312out_put: 1925out_put:
@@ -2326,6 +1939,23 @@ static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2326 return false; 1939 return false;
2327} 1940}
2328 1941
1942static void trace__set_base_time(struct trace *trace,
1943 struct perf_evsel *evsel,
1944 struct perf_sample *sample)
1945{
1946 /*
1947 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
1948 * and don't use sample->time unconditionally, we may end up having
1949 * some other event in the future without PERF_SAMPLE_TIME for good
1950 * reason, i.e. we may not be interested in its timestamps, just in
1951 * it taking place, picking some piece of information when it
1952 * appears in our event stream (vfs_getname comes to mind).
1953 */
1954 if (trace->base_time == 0 && !trace->full_time &&
1955 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
1956 trace->base_time = sample->time;
1957}
1958
2329static int trace__process_sample(struct perf_tool *tool, 1959static int trace__process_sample(struct perf_tool *tool,
2330 union perf_event *event, 1960 union perf_event *event,
2331 struct perf_sample *sample, 1961 struct perf_sample *sample,
@@ -2340,8 +1970,7 @@ static int trace__process_sample(struct perf_tool *tool,
2340 if (skip_sample(trace, sample)) 1970 if (skip_sample(trace, sample))
2341 return 0; 1971 return 0;
2342 1972
2343 if (!trace->full_time && trace->base_time == 0) 1973 trace__set_base_time(trace, evsel, sample);
2344 trace->base_time = sample->time;
2345 1974
2346 if (handler) { 1975 if (handler) {
2347 ++trace->nr_events; 1976 ++trace->nr_events;
@@ -2450,8 +2079,7 @@ static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
2450 return true; 2079 return true;
2451} 2080}
2452 2081
2453static int perf_evlist__add_pgfault(struct perf_evlist *evlist, 2082static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
2454 u64 config)
2455{ 2083{
2456 struct perf_evsel *evsel; 2084 struct perf_evsel *evsel;
2457 struct perf_event_attr attr = { 2085 struct perf_event_attr attr = {
@@ -2465,13 +2093,10 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2465 event_attr_init(&attr); 2093 event_attr_init(&attr);
2466 2094
2467 evsel = perf_evsel__new(&attr); 2095 evsel = perf_evsel__new(&attr);
2468 if (!evsel) 2096 if (evsel)
2469 return -ENOMEM; 2097 evsel->handler = trace__pgfault;
2470
2471 evsel->handler = trace__pgfault;
2472 perf_evlist__add(evlist, evsel);
2473 2098
2474 return 0; 2099 return evsel;
2475} 2100}
2476 2101
2477static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) 2102static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
@@ -2479,9 +2104,6 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
2479 const u32 type = event->header.type; 2104 const u32 type = event->header.type;
2480 struct perf_evsel *evsel; 2105 struct perf_evsel *evsel;
2481 2106
2482 if (!trace->full_time && trace->base_time == 0)
2483 trace->base_time = sample->time;
2484
2485 if (type != PERF_RECORD_SAMPLE) { 2107 if (type != PERF_RECORD_SAMPLE) {
2486 trace__process_event(trace, trace->host, event, sample); 2108 trace__process_event(trace, trace->host, event, sample);
2487 return; 2109 return;
@@ -2493,6 +2115,8 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
2493 return; 2115 return;
2494 } 2116 }
2495 2117
2118 trace__set_base_time(trace, evsel, sample);
2119
2496 if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 2120 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2497 sample->raw_data == NULL) { 2121 sample->raw_data == NULL) {
2498 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", 2122 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
@@ -2527,6 +2151,15 @@ static int trace__add_syscall_newtp(struct trace *trace)
2527 perf_evlist__add(evlist, sys_enter); 2151 perf_evlist__add(evlist, sys_enter);
2528 perf_evlist__add(evlist, sys_exit); 2152 perf_evlist__add(evlist, sys_exit);
2529 2153
2154 if (callchain_param.enabled && !trace->kernel_syscallchains) {
2155 /*
2156 * We're interested only in the user space callchain
2157 * leading to the syscall, allow overriding that for
2158 * debugging reasons using --kernel_syscall_callchains
2159 */
2160 sys_exit->attr.exclude_callchain_kernel = 1;
2161 }
2162
2530 trace->syscalls.events.sys_enter = sys_enter; 2163 trace->syscalls.events.sys_enter = sys_enter;
2531 trace->syscalls.events.sys_exit = sys_exit; 2164 trace->syscalls.events.sys_exit = sys_exit;
2532 2165
@@ -2565,7 +2198,7 @@ out_enomem:
2565static int trace__run(struct trace *trace, int argc, const char **argv) 2198static int trace__run(struct trace *trace, int argc, const char **argv)
2566{ 2199{
2567 struct perf_evlist *evlist = trace->evlist; 2200 struct perf_evlist *evlist = trace->evlist;
2568 struct perf_evsel *evsel; 2201 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
2569 int err = -1, i; 2202 int err = -1, i;
2570 unsigned long before; 2203 unsigned long before;
2571 const bool forks = argc > 0; 2204 const bool forks = argc > 0;
@@ -2579,14 +2212,19 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2579 if (trace->trace_syscalls) 2212 if (trace->trace_syscalls)
2580 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist); 2213 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
2581 2214
2582 if ((trace->trace_pgfaults & TRACE_PFMAJ) && 2215 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2583 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) { 2216 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2584 goto out_error_mem; 2217 if (pgfault_maj == NULL)
2218 goto out_error_mem;
2219 perf_evlist__add(evlist, pgfault_maj);
2585 } 2220 }
2586 2221
2587 if ((trace->trace_pgfaults & TRACE_PFMIN) && 2222 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2588 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN)) 2223 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2589 goto out_error_mem; 2224 if (pgfault_min == NULL)
2225 goto out_error_mem;
2226 perf_evlist__add(evlist, pgfault_min);
2227 }
2590 2228
2591 if (trace->sched && 2229 if (trace->sched &&
2592 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 2230 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
@@ -2605,7 +2243,45 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2605 goto out_delete_evlist; 2243 goto out_delete_evlist;
2606 } 2244 }
2607 2245
2608 perf_evlist__config(evlist, &trace->opts); 2246 perf_evlist__config(evlist, &trace->opts, NULL);
2247
2248 if (callchain_param.enabled) {
2249 bool use_identifier = false;
2250
2251 if (trace->syscalls.events.sys_exit) {
2252 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2253 &trace->opts, &callchain_param);
2254 use_identifier = true;
2255 }
2256
2257 if (pgfault_maj) {
2258 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2259 use_identifier = true;
2260 }
2261
2262 if (pgfault_min) {
2263 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2264 use_identifier = true;
2265 }
2266
2267 if (use_identifier) {
2268 /*
2269 * Now we have evsels with different sample_ids, use
2270 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2271 * from a fixed position in each ring buffer record.
2272 *
2273 * As of this the changeset introducing this comment, this
2274 * isn't strictly needed, as the fields that can come before
2275 * PERF_SAMPLE_ID are all used, but we'll probably disable
2276 * some of those for things like copying the payload of
2277 * pointer syscall arguments, and for vfs_getname we don't
2278 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2279 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2280 */
2281 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2282 perf_evlist__reset_sample_bit(evlist, ID);
2283 }
2284 }
2609 2285
2610 signal(SIGCHLD, sig_handler); 2286 signal(SIGCHLD, sig_handler);
2611 signal(SIGINT, sig_handler); 2287 signal(SIGINT, sig_handler);
@@ -2883,15 +2559,29 @@ static size_t trace__fprintf_threads_header(FILE *fp)
2883 return printed; 2559 return printed;
2884} 2560}
2885 2561
2562DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
2563 struct stats *stats;
2564 double msecs;
2565 int syscall;
2566)
2567{
2568 struct int_node *source = rb_entry(nd, struct int_node, rb_node);
2569 struct stats *stats = source->priv;
2570
2571 entry->syscall = source->i;
2572 entry->stats = stats;
2573 entry->msecs = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
2574}
2575
2886static size_t thread__dump_stats(struct thread_trace *ttrace, 2576static size_t thread__dump_stats(struct thread_trace *ttrace,
2887 struct trace *trace, FILE *fp) 2577 struct trace *trace, FILE *fp)
2888{ 2578{
2889 struct stats *stats;
2890 size_t printed = 0; 2579 size_t printed = 0;
2891 struct syscall *sc; 2580 struct syscall *sc;
2892 struct int_node *inode = intlist__first(ttrace->syscall_stats); 2581 struct rb_node *nd;
2582 DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
2893 2583
2894 if (inode == NULL) 2584 if (syscall_stats == NULL)
2895 return 0; 2585 return 0;
2896 2586
2897 printed += fprintf(fp, "\n"); 2587 printed += fprintf(fp, "\n");
@@ -2900,9 +2590,8 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
2900 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n"); 2590 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2901 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n"); 2591 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
2902 2592
2903 /* each int_node is a syscall */ 2593 resort_rb__for_each(nd, syscall_stats) {
2904 while (inode) { 2594 struct stats *stats = syscall_stats_entry->stats;
2905 stats = inode->priv;
2906 if (stats) { 2595 if (stats) {
2907 double min = (double)(stats->min) / NSEC_PER_MSEC; 2596 double min = (double)(stats->min) / NSEC_PER_MSEC;
2908 double max = (double)(stats->max) / NSEC_PER_MSEC; 2597 double max = (double)(stats->max) / NSEC_PER_MSEC;
@@ -2913,34 +2602,23 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
2913 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0; 2602 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2914 avg /= NSEC_PER_MSEC; 2603 avg /= NSEC_PER_MSEC;
2915 2604
2916 sc = &trace->syscalls.table[inode->i]; 2605 sc = &trace->syscalls.table[syscall_stats_entry->syscall];
2917 printed += fprintf(fp, " %-15s", sc->name); 2606 printed += fprintf(fp, " %-15s", sc->name);
2918 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f", 2607 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2919 n, avg * n, min, avg); 2608 n, syscall_stats_entry->msecs, min, avg);
2920 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct); 2609 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
2921 } 2610 }
2922
2923 inode = intlist__next(inode);
2924 } 2611 }
2925 2612
2613 resort_rb__delete(syscall_stats);
2926 printed += fprintf(fp, "\n\n"); 2614 printed += fprintf(fp, "\n\n");
2927 2615
2928 return printed; 2616 return printed;
2929} 2617}
2930 2618
2931/* struct used to pass data to per-thread function */ 2619static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
2932struct summary_data {
2933 FILE *fp;
2934 struct trace *trace;
2935 size_t printed;
2936};
2937
2938static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2939{ 2620{
2940 struct summary_data *data = priv; 2621 size_t printed = 0;
2941 FILE *fp = data->fp;
2942 size_t printed = data->printed;
2943 struct trace *trace = data->trace;
2944 struct thread_trace *ttrace = thread__priv(thread); 2622 struct thread_trace *ttrace = thread__priv(thread);
2945 double ratio; 2623 double ratio;
2946 2624
@@ -2956,25 +2634,45 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2956 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj); 2634 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2957 if (ttrace->pfmin) 2635 if (ttrace->pfmin)
2958 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin); 2636 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
2959 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); 2637 if (trace->sched)
2638 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2639 else if (fputc('\n', fp) != EOF)
2640 ++printed;
2641
2960 printed += thread__dump_stats(ttrace, trace, fp); 2642 printed += thread__dump_stats(ttrace, trace, fp);
2961 2643
2962 data->printed += printed; 2644 return printed;
2645}
2963 2646
2964 return 0; 2647static unsigned long thread__nr_events(struct thread_trace *ttrace)
2648{
2649 return ttrace ? ttrace->nr_events : 0;
2650}
2651
2652DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
2653 struct thread *thread;
2654)
2655{
2656 entry->thread = rb_entry(nd, struct thread, rb_node);
2965} 2657}
2966 2658
2967static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) 2659static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2968{ 2660{
2969 struct summary_data data = { 2661 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
2970 .fp = fp, 2662 size_t printed = trace__fprintf_threads_header(fp);
2971 .trace = trace 2663 struct rb_node *nd;
2972 }; 2664
2973 data.printed = trace__fprintf_threads_header(fp); 2665 if (threads == NULL) {
2666 fprintf(fp, "%s", "Error sorting output by nr_events!\n");
2667 return 0;
2668 }
2974 2669
2975 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data); 2670 resort_rb__for_each(nd, threads)
2671 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2976 2672
2977 return data.printed; 2673 resort_rb__delete(threads);
2674
2675 return printed;
2978} 2676}
2979 2677
2980static int trace__set_duration(const struct option *opt, const char *str, 2678static int trace__set_duration(const struct option *opt, const char *str,
@@ -3070,10 +2768,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3070 NULL 2768 NULL
3071 }; 2769 };
3072 struct trace trace = { 2770 struct trace trace = {
3073 .audit = {
3074 .machine = audit_detect_machine(),
3075 .open_id = audit_name_to_syscall("open", trace.audit.machine),
3076 },
3077 .syscalls = { 2771 .syscalls = {
3078 . max = -1, 2772 . max = -1,
3079 }, 2773 },
@@ -3091,6 +2785,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3091 .output = stderr, 2785 .output = stderr,
3092 .show_comm = true, 2786 .show_comm = true,
3093 .trace_syscalls = true, 2787 .trace_syscalls = true,
2788 .kernel_syscallchains = false,
2789 .max_stack = UINT_MAX,
3094 }; 2790 };
3095 const char *output_name = NULL; 2791 const char *output_name = NULL;
3096 const char *ev_qualifier_str = NULL; 2792 const char *ev_qualifier_str = NULL;
@@ -3136,10 +2832,24 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3136 "Trace pagefaults", parse_pagefaults, "maj"), 2832 "Trace pagefaults", parse_pagefaults, "maj"),
3137 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"), 2833 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
3138 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"), 2834 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
2835 OPT_CALLBACK(0, "call-graph", &trace.opts,
2836 "record_mode[,record_size]", record_callchain_help,
2837 &record_parse_callchain_opt),
2838 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
2839 "Show the kernel callchains on the syscall exit path"),
2840 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
2841 "Set the minimum stack depth when parsing the callchain, "
2842 "anything below the specified depth will be ignored."),
2843 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
2844 "Set the maximum stack depth when parsing the callchain, "
2845 "anything beyond the specified depth will be ignored. "
2846 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
3139 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, 2847 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3140 "per thread proc mmap processing timeout in ms"), 2848 "per thread proc mmap processing timeout in ms"),
3141 OPT_END() 2849 OPT_END()
3142 }; 2850 };
2851 bool __maybe_unused max_stack_user_set = true;
2852 bool mmap_pages_user_set = true;
3143 const char * const trace_subcommands[] = { "record", NULL }; 2853 const char * const trace_subcommands[] = { "record", NULL };
3144 int err; 2854 int err;
3145 char bf[BUFSIZ]; 2855 char bf[BUFSIZ];
@@ -3148,8 +2858,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3148 signal(SIGFPE, sighandler_dump_stack); 2858 signal(SIGFPE, sighandler_dump_stack);
3149 2859
3150 trace.evlist = perf_evlist__new(); 2860 trace.evlist = perf_evlist__new();
2861 trace.sctbl = syscalltbl__new();
3151 2862
3152 if (trace.evlist == NULL) { 2863 if (trace.evlist == NULL || trace.sctbl == NULL) {
3153 pr_err("Not enough memory to run!\n"); 2864 pr_err("Not enough memory to run!\n");
3154 err = -ENOMEM; 2865 err = -ENOMEM;
3155 goto out; 2866 goto out;
@@ -3158,11 +2869,40 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3158 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands, 2869 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3159 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION); 2870 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
3160 2871
2872 err = bpf__setup_stdout(trace.evlist);
2873 if (err) {
2874 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
2875 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
2876 goto out;
2877 }
2878
2879 err = -1;
2880
3161 if (trace.trace_pgfaults) { 2881 if (trace.trace_pgfaults) {
3162 trace.opts.sample_address = true; 2882 trace.opts.sample_address = true;
3163 trace.opts.sample_time = true; 2883 trace.opts.sample_time = true;
3164 } 2884 }
3165 2885
2886 if (trace.opts.mmap_pages == UINT_MAX)
2887 mmap_pages_user_set = false;
2888
2889 if (trace.max_stack == UINT_MAX) {
2890 trace.max_stack = sysctl_perf_event_max_stack;
2891 max_stack_user_set = false;
2892 }
2893
2894#ifdef HAVE_DWARF_UNWIND_SUPPORT
2895 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled)
2896 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
2897#endif
2898
2899 if (callchain_param.enabled) {
2900 if (!mmap_pages_user_set && geteuid() == 0)
2901 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
2902
2903 symbol_conf.use_callchain = true;
2904 }
2905
3166 if (trace.evlist->nr_entries > 0) 2906 if (trace.evlist->nr_entries > 0)
3167 evlist__set_evsel_handler(trace.evlist, trace__event_handler); 2907 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3168 2908
@@ -3179,6 +2919,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3179 return -1; 2919 return -1;
3180 } 2920 }
3181 2921
2922 if (!trace.trace_syscalls && ev_qualifier_str) {
2923 pr_err("The -e option can't be used with --no-syscalls.\n");
2924 goto out;
2925 }
2926
3182 if (output_name != NULL) { 2927 if (output_name != NULL) {
3183 err = trace__open_output(&trace, output_name); 2928 err = trace__open_output(&trace, output_name);
3184 if (err < 0) { 2929 if (err < 0) {
@@ -3187,6 +2932,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3187 } 2932 }
3188 } 2933 }
3189 2934
2935 trace.open_id = syscalltbl__id(trace.sctbl, "open");
2936
3190 if (ev_qualifier_str != NULL) { 2937 if (ev_qualifier_str != NULL) {
3191 const char *s = ev_qualifier_str; 2938 const char *s = ev_qualifier_str;
3192 struct strlist_config slist_config = { 2939 struct strlist_config slist_config = {
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index f7d7f5a1cad5..1e46277286c2 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -27,7 +27,7 @@ NO_PERF_REGS := 1
27ifeq ($(ARCH),x86) 27ifeq ($(ARCH),x86)
28 $(call detected,CONFIG_X86) 28 $(call detected,CONFIG_X86)
29 ifeq (${IS_64_BIT}, 1) 29 ifeq (${IS_64_BIT}, 1)
30 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT 30 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated
31 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S 31 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
33 $(call detected,CONFIG_X86_64) 33 $(call detected,CONFIG_X86_64)
@@ -268,6 +268,12 @@ else
268 ifneq ($(feature-dwarf), 1) 268 ifneq ($(feature-dwarf), 1)
269 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); 269 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);
270 NO_DWARF := 1 270 NO_DWARF := 1
271 else
272 ifneq ($(feature-dwarf_getlocations), 1)
273 msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
274 else
275 CFLAGS += -DHAVE_DWARF_GETLOCATIONS
276 endif # dwarf_getlocations
271 endif # Dwarf support 277 endif # Dwarf support
272 endif # libelf support 278 endif # libelf support
273endif # NO_LIBELF 279endif # NO_LIBELF
@@ -289,9 +295,6 @@ ifndef NO_LIBELF
289 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT 295 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
290 endif 296 endif
291 297
292 # include ARCH specific config
293 -include $(src-perf)/arch/$(ARCH)/Makefile
294
295 ifndef NO_DWARF 298 ifndef NO_DWARF
296 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 299 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
297 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 300 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c
index 6461e02ab940..3573f315f955 100644
--- a/tools/perf/jvmti/jvmti_agent.c
+++ b/tools/perf/jvmti/jvmti_agent.c
@@ -92,6 +92,22 @@ error:
92 return ret; 92 return ret;
93} 93}
94 94
95static int use_arch_timestamp;
96
97static inline uint64_t
98get_arch_timestamp(void)
99{
100#if defined(__i386__) || defined(__x86_64__)
101 unsigned int low, high;
102
103 asm volatile("rdtsc" : "=a" (low), "=d" (high));
104
105 return low | ((uint64_t)high) << 32;
106#else
107 return 0;
108#endif
109}
110
95#define NSEC_PER_SEC 1000000000 111#define NSEC_PER_SEC 1000000000
96static int perf_clk_id = CLOCK_MONOTONIC; 112static int perf_clk_id = CLOCK_MONOTONIC;
97 113
@@ -107,6 +123,9 @@ perf_get_timestamp(void)
107 struct timespec ts; 123 struct timespec ts;
108 int ret; 124 int ret;
109 125
126 if (use_arch_timestamp)
127 return get_arch_timestamp();
128
110 ret = clock_gettime(perf_clk_id, &ts); 129 ret = clock_gettime(perf_clk_id, &ts);
111 if (ret) 130 if (ret)
112 return 0; 131 return 0;
@@ -203,6 +222,17 @@ perf_close_marker_file(void)
203 munmap(marker_addr, pgsz); 222 munmap(marker_addr, pgsz);
204} 223}
205 224
225static void
226init_arch_timestamp(void)
227{
228 char *str = getenv("JITDUMP_USE_ARCH_TIMESTAMP");
229
230 if (!str || !*str || !strcmp(str, "0"))
231 return;
232
233 use_arch_timestamp = 1;
234}
235
206void *jvmti_open(void) 236void *jvmti_open(void)
207{ 237{
208 int pad_cnt; 238 int pad_cnt;
@@ -211,11 +241,17 @@ void *jvmti_open(void)
211 int fd; 241 int fd;
212 FILE *fp; 242 FILE *fp;
213 243
244 init_arch_timestamp();
245
214 /* 246 /*
215 * check if clockid is supported 247 * check if clockid is supported
216 */ 248 */
217 if (!perf_get_timestamp()) 249 if (!perf_get_timestamp()) {
218 warnx("jvmti: kernel does not support %d clock id", perf_clk_id); 250 if (use_arch_timestamp)
251 warnx("jvmti: arch timestamp not supported");
252 else
253 warnx("jvmti: kernel does not support %d clock id", perf_clk_id);
254 }
219 255
220 memset(&header, 0, sizeof(header)); 256 memset(&header, 0, sizeof(header));
221 257
@@ -263,6 +299,9 @@ void *jvmti_open(void)
263 299
264 header.timestamp = perf_get_timestamp(); 300 header.timestamp = perf_get_timestamp();
265 301
302 if (use_arch_timestamp)
303 header.flags |= JITDUMP_FLAGS_ARCH_TIMESTAMP;
304
266 if (!fwrite(&header, sizeof(header), 1, fp)) { 305 if (!fwrite(&header, sizeof(header), 1, fp)) {
267 warn("jvmti: cannot write dumpfile header"); 306 warn("jvmti: cannot write dumpfile header");
268 goto error; 307 goto error;
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index aaee0a782747..797000842d40 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -17,6 +17,7 @@
17#include <subcmd/parse-options.h> 17#include <subcmd/parse-options.h>
18#include "util/bpf-loader.h" 18#include "util/bpf-loader.h"
19#include "util/debug.h" 19#include "util/debug.h"
20#include <api/fs/fs.h>
20#include <api/fs/tracing_path.h> 21#include <api/fs/tracing_path.h>
21#include <pthread.h> 22#include <pthread.h>
22#include <stdlib.h> 23#include <stdlib.h>
@@ -308,9 +309,11 @@ static int handle_alias(int *argcp, const char ***argv)
308 if (*argcp > 1) { 309 if (*argcp > 1) {
309 struct strbuf buf; 310 struct strbuf buf;
310 311
311 strbuf_init(&buf, PATH_MAX); 312 if (strbuf_init(&buf, PATH_MAX) < 0 ||
312 strbuf_addstr(&buf, alias_string); 313 strbuf_addstr(&buf, alias_string) < 0 ||
313 sq_quote_argv(&buf, (*argv) + 1, PATH_MAX); 314 sq_quote_argv(&buf, (*argv) + 1,
315 PATH_MAX) < 0)
316 die("Failed to allocate memory.");
314 free(alias_string); 317 free(alias_string);
315 alias_string = buf.buf; 318 alias_string = buf.buf;
316 } 319 }
@@ -533,6 +536,7 @@ int main(int argc, const char **argv)
533{ 536{
534 const char *cmd; 537 const char *cmd;
535 char sbuf[STRERR_BUFSIZE]; 538 char sbuf[STRERR_BUFSIZE];
539 int value;
536 540
537 /* libsubcmd init */ 541 /* libsubcmd init */
538 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT); 542 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
@@ -542,6 +546,9 @@ int main(int argc, const char **argv)
542 page_size = sysconf(_SC_PAGE_SIZE); 546 page_size = sysconf(_SC_PAGE_SIZE);
543 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); 547 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
544 548
549 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
550 sysctl_perf_event_max_stack = value;
551
545 cmd = extract_argv0_path(argv[0]); 552 cmd = extract_argv0_path(argv[0]);
546 if (!cmd) 553 if (!cmd)
547 cmd = "perf-help"; 554 cmd = "perf-help";
@@ -549,6 +556,7 @@ int main(int argc, const char **argv)
549 srandom(time(NULL)); 556 srandom(time(NULL));
550 557
551 perf_config(perf_default_config, NULL); 558 perf_config(perf_default_config, NULL);
559 set_buildid_dir(NULL);
552 560
553 /* get debugfs/tracefs mount point from /proc/mounts */ 561 /* get debugfs/tracefs mount point from /proc/mounts */
554 tracing_path_mount(); 562 tracing_path_mount();
@@ -572,7 +580,6 @@ int main(int argc, const char **argv)
572 } 580 }
573 if (!prefixcmp(cmd, "trace")) { 581 if (!prefixcmp(cmd, "trace")) {
574#ifdef HAVE_LIBAUDIT_SUPPORT 582#ifdef HAVE_LIBAUDIT_SUPPORT
575 set_buildid_dir(NULL);
576 setup_path(); 583 setup_path();
577 argv[0] = "trace"; 584 argv[0] = "trace";
578 return cmd_trace(argc, argv, NULL); 585 return cmd_trace(argc, argv, NULL);
@@ -587,7 +594,6 @@ int main(int argc, const char **argv)
587 argc--; 594 argc--;
588 handle_options(&argv, &argc, NULL); 595 handle_options(&argv, &argc, NULL);
589 commit_pager_choice(); 596 commit_pager_choice();
590 set_buildid_dir(NULL);
591 597
592 if (argc > 0) { 598 if (argc > 0) {
593 if (!prefixcmp(argv[0], "--")) 599 if (!prefixcmp(argv[0], "--"))
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 5381a01c0610..cd8f1b150f9e 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -52,7 +52,6 @@ struct record_opts {
52 bool sample_weight; 52 bool sample_weight;
53 bool sample_time; 53 bool sample_time;
54 bool sample_time_set; 54 bool sample_time_set;
55 bool callgraph_set;
56 bool period; 55 bool period;
57 bool running_time; 56 bool running_time;
58 bool full_auxtrace; 57 bool full_auxtrace;
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 1b02cdc0cab6..7656ff8aa066 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -34,10 +34,9 @@ import datetime
34# 34#
35# ubuntu: 35# ubuntu:
36# 36#
37# $ sudo apt-get install postgresql 37# $ sudo apt-get install postgresql python-pyside.qtsql libqt4-sql-psql
38# $ sudo su - postgres 38# $ sudo su - postgres
39# $ createuser <your user id here> 39# $ createuser -s <your user id here>
40# Shall the new role be a superuser? (y/n) y
41# 40#
42# An example of using this script with Intel PT: 41# An example of using this script with Intel PT:
43# 42#
@@ -224,11 +223,14 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \
224 223
225perf_db_export_mode = True 224perf_db_export_mode = True
226perf_db_export_calls = False 225perf_db_export_calls = False
226perf_db_export_callchains = False
227
227 228
228def usage(): 229def usage():
229 print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>]" 230 print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]"
230 print >> sys.stderr, "where: columns 'all' or 'branches'" 231 print >> sys.stderr, "where: columns 'all' or 'branches'"
231 print >> sys.stderr, " calls 'calls' => create calls table" 232 print >> sys.stderr, " calls 'calls' => create calls and call_paths table"
233 print >> sys.stderr, " callchains 'callchains' => create call_paths table"
232 raise Exception("Too few arguments") 234 raise Exception("Too few arguments")
233 235
234if (len(sys.argv) < 2): 236if (len(sys.argv) < 2):
@@ -246,9 +248,11 @@ if columns not in ("all", "branches"):
246 248
247branches = (columns == "branches") 249branches = (columns == "branches")
248 250
249if (len(sys.argv) >= 4): 251for i in range(3,len(sys.argv)):
250 if (sys.argv[3] == "calls"): 252 if (sys.argv[i] == "calls"):
251 perf_db_export_calls = True 253 perf_db_export_calls = True
254 elif (sys.argv[i] == "callchains"):
255 perf_db_export_callchains = True
252 else: 256 else:
253 usage() 257 usage()
254 258
@@ -359,14 +363,16 @@ else:
359 'transaction bigint,' 363 'transaction bigint,'
360 'data_src bigint,' 364 'data_src bigint,'
361 'branch_type integer,' 365 'branch_type integer,'
362 'in_tx boolean)') 366 'in_tx boolean,'
367 'call_path_id bigint)')
363 368
364if perf_db_export_calls: 369if perf_db_export_calls or perf_db_export_callchains:
365 do_query(query, 'CREATE TABLE call_paths (' 370 do_query(query, 'CREATE TABLE call_paths ('
366 'id bigint NOT NULL,' 371 'id bigint NOT NULL,'
367 'parent_id bigint,' 372 'parent_id bigint,'
368 'symbol_id bigint,' 373 'symbol_id bigint,'
369 'ip bigint)') 374 'ip bigint)')
375if perf_db_export_calls:
370 do_query(query, 'CREATE TABLE calls (' 376 do_query(query, 'CREATE TABLE calls ('
371 'id bigint NOT NULL,' 377 'id bigint NOT NULL,'
372 'thread_id bigint,' 378 'thread_id bigint,'
@@ -428,7 +434,7 @@ do_query(query, 'CREATE VIEW comm_threads_view AS '
428 '(SELECT tid FROM threads WHERE id = thread_id) AS tid' 434 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
429 ' FROM comm_threads') 435 ' FROM comm_threads')
430 436
431if perf_db_export_calls: 437if perf_db_export_calls or perf_db_export_callchains:
432 do_query(query, 'CREATE VIEW call_paths_view AS ' 438 do_query(query, 'CREATE VIEW call_paths_view AS '
433 'SELECT ' 439 'SELECT '
434 'c.id,' 440 'c.id,'
@@ -444,6 +450,7 @@ if perf_db_export_calls:
444 '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,' 450 '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
445 '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name' 451 '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
446 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id') 452 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
453if perf_db_export_calls:
447 do_query(query, 'CREATE VIEW calls_view AS ' 454 do_query(query, 'CREATE VIEW calls_view AS '
448 'SELECT ' 455 'SELECT '
449 'calls.id,' 456 'calls.id,'
@@ -541,8 +548,9 @@ dso_file = open_output_file("dso_table.bin")
541symbol_file = open_output_file("symbol_table.bin") 548symbol_file = open_output_file("symbol_table.bin")
542branch_type_file = open_output_file("branch_type_table.bin") 549branch_type_file = open_output_file("branch_type_table.bin")
543sample_file = open_output_file("sample_table.bin") 550sample_file = open_output_file("sample_table.bin")
544if perf_db_export_calls: 551if perf_db_export_calls or perf_db_export_callchains:
545 call_path_file = open_output_file("call_path_table.bin") 552 call_path_file = open_output_file("call_path_table.bin")
553if perf_db_export_calls:
546 call_file = open_output_file("call_table.bin") 554 call_file = open_output_file("call_table.bin")
547 555
548def trace_begin(): 556def trace_begin():
@@ -554,8 +562,8 @@ def trace_begin():
554 comm_table(0, "unknown") 562 comm_table(0, "unknown")
555 dso_table(0, 0, "unknown", "unknown", "") 563 dso_table(0, 0, "unknown", "unknown", "")
556 symbol_table(0, 0, 0, 0, 0, "unknown") 564 symbol_table(0, 0, 0, 0, 0, "unknown")
557 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 565 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
558 if perf_db_export_calls: 566 if perf_db_export_calls or perf_db_export_callchains:
559 call_path_table(0, 0, 0, 0) 567 call_path_table(0, 0, 0, 0)
560 568
561unhandled_count = 0 569unhandled_count = 0
@@ -571,8 +579,9 @@ def trace_end():
571 copy_output_file(symbol_file, "symbols") 579 copy_output_file(symbol_file, "symbols")
572 copy_output_file(branch_type_file, "branch_types") 580 copy_output_file(branch_type_file, "branch_types")
573 copy_output_file(sample_file, "samples") 581 copy_output_file(sample_file, "samples")
574 if perf_db_export_calls: 582 if perf_db_export_calls or perf_db_export_callchains:
575 copy_output_file(call_path_file, "call_paths") 583 copy_output_file(call_path_file, "call_paths")
584 if perf_db_export_calls:
576 copy_output_file(call_file, "calls") 585 copy_output_file(call_file, "calls")
577 586
578 print datetime.datetime.today(), "Removing intermediate files..." 587 print datetime.datetime.today(), "Removing intermediate files..."
@@ -585,8 +594,9 @@ def trace_end():
585 remove_output_file(symbol_file) 594 remove_output_file(symbol_file)
586 remove_output_file(branch_type_file) 595 remove_output_file(branch_type_file)
587 remove_output_file(sample_file) 596 remove_output_file(sample_file)
588 if perf_db_export_calls: 597 if perf_db_export_calls or perf_db_export_callchains:
589 remove_output_file(call_path_file) 598 remove_output_file(call_path_file)
599 if perf_db_export_calls:
590 remove_output_file(call_file) 600 remove_output_file(call_file)
591 os.rmdir(output_dir_name) 601 os.rmdir(output_dir_name)
592 print datetime.datetime.today(), "Adding primary keys" 602 print datetime.datetime.today(), "Adding primary keys"
@@ -599,8 +609,9 @@ def trace_end():
599 do_query(query, 'ALTER TABLE symbols ADD PRIMARY KEY (id)') 609 do_query(query, 'ALTER TABLE symbols ADD PRIMARY KEY (id)')
600 do_query(query, 'ALTER TABLE branch_types ADD PRIMARY KEY (id)') 610 do_query(query, 'ALTER TABLE branch_types ADD PRIMARY KEY (id)')
601 do_query(query, 'ALTER TABLE samples ADD PRIMARY KEY (id)') 611 do_query(query, 'ALTER TABLE samples ADD PRIMARY KEY (id)')
602 if perf_db_export_calls: 612 if perf_db_export_calls or perf_db_export_callchains:
603 do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)') 613 do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)')
614 if perf_db_export_calls:
604 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)') 615 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)')
605 616
606 print datetime.datetime.today(), "Adding foreign keys" 617 print datetime.datetime.today(), "Adding foreign keys"
@@ -623,10 +634,11 @@ def trace_end():
623 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id),' 634 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id),'
624 'ADD CONSTRAINT todsofk FOREIGN KEY (to_dso_id) REFERENCES dsos (id),' 635 'ADD CONSTRAINT todsofk FOREIGN KEY (to_dso_id) REFERENCES dsos (id),'
625 'ADD CONSTRAINT tosymbolfk FOREIGN KEY (to_symbol_id) REFERENCES symbols (id)') 636 'ADD CONSTRAINT tosymbolfk FOREIGN KEY (to_symbol_id) REFERENCES symbols (id)')
626 if perf_db_export_calls: 637 if perf_db_export_calls or perf_db_export_callchains:
627 do_query(query, 'ALTER TABLE call_paths ' 638 do_query(query, 'ALTER TABLE call_paths '
628 'ADD CONSTRAINT parentfk FOREIGN KEY (parent_id) REFERENCES call_paths (id),' 639 'ADD CONSTRAINT parentfk FOREIGN KEY (parent_id) REFERENCES call_paths (id),'
629 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id)') 640 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id)')
641 if perf_db_export_calls:
630 do_query(query, 'ALTER TABLE calls ' 642 do_query(query, 'ALTER TABLE calls '
631 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),' 643 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),'
632 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),' 644 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
@@ -694,11 +706,11 @@ def branch_type_table(branch_type, name, *x):
694 value = struct.pack(fmt, 2, 4, branch_type, n, name) 706 value = struct.pack(fmt, 2, 4, branch_type, n, name)
695 branch_type_file.write(value) 707 branch_type_file.write(value)
696 708
697def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, *x): 709def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, call_path_id, *x):
698 if branches: 710 if branches:
699 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiB", 17, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx) 711 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiBiq", 18, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx, 8, call_path_id)
700 else: 712 else:
701 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiB", 21, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx) 713 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiBiq", 22, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx, 8, call_path_id)
702 sample_file.write(value) 714 sample_file.write(value)
703 715
704def call_path_table(cp_id, parent_id, symbol_id, ip, *x): 716def call_path_table(cp_id, parent_id, symbol_id, ip, *x):
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 1ba628ed049a..66a28982547b 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -37,6 +37,8 @@ perf-y += topology.o
37perf-y += cpumap.o 37perf-y += cpumap.o
38perf-y += stat.o 38perf-y += stat.o
39perf-y += event_update.o 39perf-y += event_update.o
40perf-y += event-times.o
41perf-y += backward-ring-buffer.o
40 42
41$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 43$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
42 $(call rule_mkdir) 44 $(call rule_mkdir)
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
new file mode 100644
index 000000000000..d9ba991a9a30
--- /dev/null
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -0,0 +1,151 @@
1/*
2 * Test backward bit in event attribute, read ring buffer from end to
3 * beginning
4 */
5
6#include <perf.h>
7#include <evlist.h>
8#include <sys/prctl.h>
9#include "tests.h"
10#include "debug.h"
11
12#define NR_ITERS 111
13
14static void testcase(void)
15{
16 int i;
17
18 for (i = 0; i < NR_ITERS; i++) {
19 char proc_name[10];
20
21 snprintf(proc_name, sizeof(proc_name), "p:%d\n", i);
22 prctl(PR_SET_NAME, proc_name);
23 }
24}
25
26static int count_samples(struct perf_evlist *evlist, int *sample_count,
27 int *comm_count)
28{
29 int i;
30
31 for (i = 0; i < evlist->nr_mmaps; i++) {
32 union perf_event *event;
33
34 perf_evlist__mmap_read_catchup(evlist, i);
35 while ((event = perf_evlist__mmap_read_backward(evlist, i)) != NULL) {
36 const u32 type = event->header.type;
37
38 switch (type) {
39 case PERF_RECORD_SAMPLE:
40 (*sample_count)++;
41 break;
42 case PERF_RECORD_COMM:
43 (*comm_count)++;
44 break;
45 default:
46 pr_err("Unexpected record of type %d\n", type);
47 return TEST_FAIL;
48 }
49 }
50 }
51 return TEST_OK;
52}
53
54static int do_test(struct perf_evlist *evlist, int mmap_pages,
55 int *sample_count, int *comm_count)
56{
57 int err;
58 char sbuf[STRERR_BUFSIZE];
59
60 err = perf_evlist__mmap(evlist, mmap_pages, true);
61 if (err < 0) {
62 pr_debug("perf_evlist__mmap: %s\n",
63 strerror_r(errno, sbuf, sizeof(sbuf)));
64 return TEST_FAIL;
65 }
66
67 perf_evlist__enable(evlist);
68 testcase();
69 perf_evlist__disable(evlist);
70
71 err = count_samples(evlist, sample_count, comm_count);
72 perf_evlist__munmap(evlist);
73 return err;
74}
75
76
77int test__backward_ring_buffer(int subtest __maybe_unused)
78{
79 int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0;
80 char pid[16], sbuf[STRERR_BUFSIZE];
81 struct perf_evlist *evlist;
82 struct perf_evsel *evsel __maybe_unused;
83 struct parse_events_error parse_error;
84 struct record_opts opts = {
85 .target = {
86 .uid = UINT_MAX,
87 .uses_mmap = true,
88 },
89 .freq = 0,
90 .mmap_pages = 256,
91 .default_interval = 1,
92 };
93
94 snprintf(pid, sizeof(pid), "%d", getpid());
95 pid[sizeof(pid) - 1] = '\0';
96 opts.target.tid = opts.target.pid = pid;
97
98 evlist = perf_evlist__new();
99 if (!evlist) {
100 pr_debug("No ehough memory to create evlist\n");
101 return TEST_FAIL;
102 }
103
104 err = perf_evlist__create_maps(evlist, &opts.target);
105 if (err < 0) {
106 pr_debug("Not enough memory to create thread/cpu maps\n");
107 goto out_delete_evlist;
108 }
109
110 bzero(&parse_error, sizeof(parse_error));
111 err = parse_events(evlist, "syscalls:sys_enter_prctl", &parse_error);
112 if (err) {
113 pr_debug("Failed to parse tracepoint event, try use root\n");
114 ret = TEST_SKIP;
115 goto out_delete_evlist;
116 }
117
118 perf_evlist__config(evlist, &opts, NULL);
119
120 /* Set backward bit, ring buffer should be writing from end */
121 evlist__for_each(evlist, evsel)
122 evsel->attr.write_backward = 1;
123
124 err = perf_evlist__open(evlist);
125 if (err < 0) {
126 pr_debug("perf_evlist__open: %s\n",
127 strerror_r(errno, sbuf, sizeof(sbuf)));
128 goto out_delete_evlist;
129 }
130
131 ret = TEST_FAIL;
132 err = do_test(evlist, opts.mmap_pages, &sample_count,
133 &comm_count);
134 if (err != TEST_OK)
135 goto out_delete_evlist;
136
137 if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) {
138 pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n",
139 sample_count, comm_count);
140 goto out_delete_evlist;
141 }
142
143 err = do_test(evlist, 1, &sample_count, &comm_count);
144 if (err != TEST_OK)
145 goto out_delete_evlist;
146
147 ret = TEST_OK;
148out_delete_evlist:
149 perf_evlist__delete(evlist);
150 return ret;
151}
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 199501c71e27..f31eed31c1a9 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -138,7 +138,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
138 perf_evlist__splice_list_tail(evlist, &parse_evlist.list); 138 perf_evlist__splice_list_tail(evlist, &parse_evlist.list);
139 evlist->nr_groups = parse_evlist.nr_groups; 139 evlist->nr_groups = parse_evlist.nr_groups;
140 140
141 perf_evlist__config(evlist, &opts); 141 perf_evlist__config(evlist, &opts, NULL);
142 142
143 err = perf_evlist__open(evlist); 143 err = perf_evlist__open(evlist);
144 if (err < 0) { 144 if (err < 0) {
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index f2b1dcac45d3..0e95c20ecf6e 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -204,6 +204,14 @@ static struct test generic_tests[] = {
204 .func = test__event_update, 204 .func = test__event_update,
205 }, 205 },
206 { 206 {
207 .desc = "Test events times",
208 .func = test__event_times,
209 },
210 {
211 .desc = "Test backward reading from ring buffer",
212 .func = test__backward_ring_buffer,
213 },
214 {
207 .func = NULL, 215 .func = NULL,
208 }, 216 },
209}; 217};
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index abd3f0ec0c0b..68a69a195545 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -532,7 +532,7 @@ static int do_test_code_reading(bool try_kcore)
532 goto out_put; 532 goto out_put;
533 } 533 }
534 534
535 perf_evlist__config(evlist, &opts); 535 perf_evlist__config(evlist, &opts, NULL);
536 536
537 evsel = perf_evlist__first(evlist); 537 evsel = perf_evlist__first(evlist);
538 538
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index dc673ff7c437..8cf0d9e189a8 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -202,7 +202,7 @@ static int dsos__create(int cnt, int size)
202{ 202{
203 int i; 203 int i;
204 204
205 dsos = malloc(sizeof(dsos) * cnt); 205 dsos = malloc(sizeof(*dsos) * cnt);
206 TEST_ASSERT_VAL("failed to alloc dsos array", dsos); 206 TEST_ASSERT_VAL("failed to alloc dsos array", dsos);
207 207
208 for (i = 0; i < cnt; i++) { 208 for (i = 0; i < cnt; i++) {
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c
new file mode 100644
index 000000000000..95fb744f6628
--- /dev/null
+++ b/tools/perf/tests/event-times.c
@@ -0,0 +1,236 @@
1#include <linux/compiler.h>
2#include <string.h>
3#include "tests.h"
4#include "evlist.h"
5#include "evsel.h"
6#include "util.h"
7#include "debug.h"
8#include "thread_map.h"
9#include "target.h"
10
11static int attach__enable_on_exec(struct perf_evlist *evlist)
12{
13 struct perf_evsel *evsel = perf_evlist__last(evlist);
14 struct target target = {
15 .uid = UINT_MAX,
16 };
17 const char *argv[] = { "true", NULL, };
18 char sbuf[STRERR_BUFSIZE];
19 int err;
20
21 pr_debug("attaching to spawned child, enable on exec\n");
22
23 err = perf_evlist__create_maps(evlist, &target);
24 if (err < 0) {
25 pr_debug("Not enough memory to create thread/cpu maps\n");
26 return err;
27 }
28
29 err = perf_evlist__prepare_workload(evlist, &target, argv, false, NULL);
30 if (err < 0) {
31 pr_debug("Couldn't run the workload!\n");
32 return err;
33 }
34
35 evsel->attr.enable_on_exec = 1;
36
37 err = perf_evlist__open(evlist);
38 if (err < 0) {
39 pr_debug("perf_evlist__open: %s\n",
40 strerror_r(errno, sbuf, sizeof(sbuf)));
41 return err;
42 }
43
44 return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
45}
46
47static int detach__enable_on_exec(struct perf_evlist *evlist)
48{
49 waitpid(evlist->workload.pid, NULL, 0);
50 return 0;
51}
52
53static int attach__current_disabled(struct perf_evlist *evlist)
54{
55 struct perf_evsel *evsel = perf_evlist__last(evlist);
56 struct thread_map *threads;
57 int err;
58
59 pr_debug("attaching to current thread as disabled\n");
60
61 threads = thread_map__new(-1, getpid(), UINT_MAX);
62 if (threads == NULL) {
63 pr_debug("thread_map__new\n");
64 return -1;
65 }
66
67 evsel->attr.disabled = 1;
68
69 err = perf_evsel__open_per_thread(evsel, threads);
70 if (err) {
71 pr_debug("Failed to open event cpu-clock:u\n");
72 return err;
73 }
74
75 thread_map__put(threads);
76 return perf_evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
77}
78
79static int attach__current_enabled(struct perf_evlist *evlist)
80{
81 struct perf_evsel *evsel = perf_evlist__last(evlist);
82 struct thread_map *threads;
83 int err;
84
85 pr_debug("attaching to current thread as enabled\n");
86
87 threads = thread_map__new(-1, getpid(), UINT_MAX);
88 if (threads == NULL) {
89 pr_debug("failed to call thread_map__new\n");
90 return -1;
91 }
92
93 err = perf_evsel__open_per_thread(evsel, threads);
94
95 thread_map__put(threads);
96 return err == 0 ? TEST_OK : TEST_FAIL;
97}
98
99static int detach__disable(struct perf_evlist *evlist)
100{
101 struct perf_evsel *evsel = perf_evlist__last(evlist);
102
103 return perf_evsel__enable(evsel);
104}
105
106static int attach__cpu_disabled(struct perf_evlist *evlist)
107{
108 struct perf_evsel *evsel = perf_evlist__last(evlist);
109 struct cpu_map *cpus;
110 int err;
111
112 pr_debug("attaching to CPU 0 as enabled\n");
113
114 cpus = cpu_map__new("0");
115 if (cpus == NULL) {
116 pr_debug("failed to call cpu_map__new\n");
117 return -1;
118 }
119
120 evsel->attr.disabled = 1;
121
122 err = perf_evsel__open_per_cpu(evsel, cpus);
123 if (err) {
124 if (err == -EACCES)
125 return TEST_SKIP;
126
127 pr_debug("Failed to open event cpu-clock:u\n");
128 return err;
129 }
130
131 cpu_map__put(cpus);
132 return perf_evsel__enable(evsel);
133}
134
135static int attach__cpu_enabled(struct perf_evlist *evlist)
136{
137 struct perf_evsel *evsel = perf_evlist__last(evlist);
138 struct cpu_map *cpus;
139 int err;
140
141 pr_debug("attaching to CPU 0 as enabled\n");
142
143 cpus = cpu_map__new("0");
144 if (cpus == NULL) {
145 pr_debug("failed to call cpu_map__new\n");
146 return -1;
147 }
148
149 err = perf_evsel__open_per_cpu(evsel, cpus);
150 if (err == -EACCES)
151 return TEST_SKIP;
152
153 cpu_map__put(cpus);
154 return err ? TEST_FAIL : TEST_OK;
155}
156
157static int test_times(int (attach)(struct perf_evlist *),
158 int (detach)(struct perf_evlist *))
159{
160 struct perf_counts_values count;
161 struct perf_evlist *evlist = NULL;
162 struct perf_evsel *evsel;
163 int err = -1, i;
164
165 evlist = perf_evlist__new();
166 if (!evlist) {
167 pr_debug("failed to create event list\n");
168 goto out_err;
169 }
170
171 err = parse_events(evlist, "cpu-clock:u", NULL);
172 if (err) {
173 pr_debug("failed to parse event cpu-clock:u\n");
174 goto out_err;
175 }
176
177 evsel = perf_evlist__last(evlist);
178 evsel->attr.read_format |=
179 PERF_FORMAT_TOTAL_TIME_ENABLED |
180 PERF_FORMAT_TOTAL_TIME_RUNNING;
181
182 err = attach(evlist);
183 if (err == TEST_SKIP) {
184 pr_debug(" SKIP : not enough rights\n");
185 return err;
186 }
187
188 TEST_ASSERT_VAL("failed to attach", !err);
189
190 for (i = 0; i < 100000000; i++) { }
191
192 TEST_ASSERT_VAL("failed to detach", !detach(evlist));
193
194 perf_evsel__read(evsel, 0, 0, &count);
195
196 err = !(count.ena == count.run);
197
198 pr_debug(" %s: ena %" PRIu64", run %" PRIu64"\n",
199 !err ? "OK " : "FAILED",
200 count.ena, count.run);
201
202out_err:
203 if (evlist)
204 perf_evlist__delete(evlist);
205 return !err ? TEST_OK : TEST_FAIL;
206}
207
208/*
209 * This test creates software event 'cpu-clock'
210 * attaches it in several ways (explained below)
211 * and checks that enabled and running times
212 * match.
213 */
214int test__event_times(int subtest __maybe_unused)
215{
216 int err, ret = 0;
217
218#define _T(attach, detach) \
219 err = test_times(attach, detach); \
220 if (err && (ret == TEST_OK || ret == TEST_SKIP)) \
221 ret = err;
222
223 /* attach on newly spawned process after exec */
224 _T(attach__enable_on_exec, detach__enable_on_exec)
225 /* attach on current process as enabled */
226 _T(attach__current_enabled, detach__disable)
227 /* attach on current process as disabled */
228 _T(attach__current_disabled, detach__disable)
229 /* attach on cpu as disabled */
230 _T(attach__cpu_disabled, detach__disable)
231 /* attach on cpu as enabled */
232 _T(attach__cpu_enabled, detach__disable)
233
234#undef _T
235 return ret;
236}
diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index 012eab5d1df1..63ecf21750eb 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -30,7 +30,7 @@ static int process_event_scale(struct perf_tool *tool __maybe_unused,
30 30
31 TEST_ASSERT_VAL("wrong id", ev->id == 123); 31 TEST_ASSERT_VAL("wrong id", ev->id == 123);
32 TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE); 32 TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE);
33 TEST_ASSERT_VAL("wrong scale", ev_data->scale = 0.123); 33 TEST_ASSERT_VAL("wrong scale", ev_data->scale == 0.123);
34 return 0; 34 return 0;
35} 35}
36 36
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index f55f4bd47932..6b21746d6eec 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -161,7 +161,7 @@ void print_hists_in(struct hists *hists)
161 struct rb_root *root; 161 struct rb_root *root;
162 struct rb_node *node; 162 struct rb_node *node;
163 163
164 if (sort__need_collapse) 164 if (hists__has(hists, need_collapse))
165 root = &hists->entries_collapsed; 165 root = &hists->entries_collapsed;
166 else 166 else
167 root = hists->entries_in; 167 root = hists->entries_in;
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index ed5aa9eaeb6c..a9e3db3afac4 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -101,7 +101,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
101 if (machine__resolve(machine, &al, &sample) < 0) 101 if (machine__resolve(machine, &al, &sample) < 0)
102 goto out; 102 goto out;
103 103
104 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, 104 if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
105 NULL) < 0) { 105 NULL) < 0) {
106 addr_location__put(&al); 106 addr_location__put(&al);
107 goto out; 107 goto out;
@@ -126,7 +126,7 @@ static void del_hist_entries(struct hists *hists)
126 struct rb_root *root_out; 126 struct rb_root *root_out;
127 struct rb_node *node; 127 struct rb_node *node;
128 128
129 if (sort__need_collapse) 129 if (hists__has(hists, need_collapse))
130 root_in = &hists->entries_collapsed; 130 root_in = &hists->entries_collapsed;
131 else 131 else
132 root_in = hists->entries_in; 132 root_in = hists->entries_in;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index b825d24f8186..e846f8c42013 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -81,7 +81,7 @@ static int add_hist_entries(struct perf_evlist *evlist,
81 81
82 al.socket = fake_samples[i].socket; 82 al.socket = fake_samples[i].socket;
83 if (hist_entry_iter__add(&iter, &al, 83 if (hist_entry_iter__add(&iter, &al,
84 PERF_MAX_STACK_DEPTH, NULL) < 0) { 84 sysctl_perf_event_max_stack, NULL) < 0) {
85 addr_location__put(&al); 85 addr_location__put(&al);
86 goto out; 86 goto out;
87 } 87 }
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 358324e47805..acf5a1301c07 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -145,7 +145,7 @@ static int __validate_match(struct hists *hists)
145 /* 145 /*
146 * Only entries from fake_common_samples should have a pair. 146 * Only entries from fake_common_samples should have a pair.
147 */ 147 */
148 if (sort__need_collapse) 148 if (hists__has(hists, need_collapse))
149 root = &hists->entries_collapsed; 149 root = &hists->entries_collapsed;
150 else 150 else
151 root = hists->entries_in; 151 root = hists->entries_in;
@@ -197,7 +197,7 @@ static int __validate_link(struct hists *hists, int idx)
197 * and some entries will have no pair. However every entry 197 * and some entries will have no pair. However every entry
198 * in other hists should have (dummy) pair. 198 * in other hists should have (dummy) pair.
199 */ 199 */
200 if (sort__need_collapse) 200 if (hists__has(hists, need_collapse))
201 root = &hists->entries_collapsed; 201 root = &hists->entries_collapsed;
202 else 202 else
203 root = hists->entries_in; 203 root = hists->entries_in;
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index d3556fbe8c5c..63c5efaba1b5 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -67,7 +67,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
67 if (machine__resolve(machine, &al, &sample) < 0) 67 if (machine__resolve(machine, &al, &sample) < 0)
68 goto out; 68 goto out;
69 69
70 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, 70 if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
71 NULL) < 0) { 71 NULL) < 0) {
72 addr_location__put(&al); 72 addr_location__put(&al);
73 goto out; 73 goto out;
@@ -92,7 +92,7 @@ static void del_hist_entries(struct hists *hists)
92 struct rb_root *root_out; 92 struct rb_root *root_out;
93 struct rb_node *node; 93 struct rb_node *node;
94 94
95 if (sort__need_collapse) 95 if (hists__has(hists, need_collapse))
96 root_in = &hists->entries_collapsed; 96 root_in = &hists->entries_collapsed;
97 else 97 else
98 root_in = hists->entries_in; 98 root_in = hists->entries_in;
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index ddb78fae064a..614e45a3c603 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -80,7 +80,7 @@ int test__keep_tracking(int subtest __maybe_unused)
80 CHECK__(parse_events(evlist, "dummy:u", NULL)); 80 CHECK__(parse_events(evlist, "dummy:u", NULL));
81 CHECK__(parse_events(evlist, "cycles:u", NULL)); 81 CHECK__(parse_events(evlist, "cycles:u", NULL));
82 82
83 perf_evlist__config(evlist, &opts); 83 perf_evlist__config(evlist, &opts, NULL);
84 84
85 evsel = perf_evlist__first(evlist); 85 evsel = perf_evlist__first(evlist);
86 86
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 53c2273e8859..ad1cb63139a7 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -73,7 +73,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused)
73 } 73 }
74 74
75 /* 75 /*
76 * Here we need to explicitely preallocate the counts, as if 76 * Here we need to explicitly preallocate the counts, as if
77 * we use the auto allocation it will allocate just for 1 cpu, 77 * we use the auto allocation it will allocate just for 1 cpu,
78 * as we start by cpu 0. 78 * as we start by cpu 0.
79 */ 79 */
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index eb99a105f31c..4344fe482c1d 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -44,7 +44,7 @@ int test__syscall_openat_tp_fields(int subtest __maybe_unused)
44 goto out_delete_evlist; 44 goto out_delete_evlist;
45 } 45 }
46 46
47 perf_evsel__config(evsel, &opts); 47 perf_evsel__config(evsel, &opts, NULL);
48 48
49 thread_map__set_pid(evlist->threads, 0, getpid()); 49 thread_map__set_pid(evlist->threads, 0, getpid());
50 50
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 1cc78cefe399..b836ee6a8d9b 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -99,7 +99,7 @@ int test__PERF_RECORD(int subtest __maybe_unused)
99 perf_evsel__set_sample_bit(evsel, CPU); 99 perf_evsel__set_sample_bit(evsel, CPU);
100 perf_evsel__set_sample_bit(evsel, TID); 100 perf_evsel__set_sample_bit(evsel, TID);
101 perf_evsel__set_sample_bit(evsel, TIME); 101 perf_evsel__set_sample_bit(evsel, TIME);
102 perf_evlist__config(evlist, &opts); 102 perf_evlist__config(evlist, &opts, NULL);
103 103
104 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); 104 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
105 if (err < 0) { 105 if (err < 0) {
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index ebd80168d51e..39a689bf7574 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -417,7 +417,7 @@ int test__switch_tracking(int subtest __maybe_unused)
417 perf_evsel__set_sample_bit(tracking_evsel, TIME); 417 perf_evsel__set_sample_bit(tracking_evsel, TIME);
418 418
419 /* Config events */ 419 /* Config events */
420 perf_evlist__config(evlist, &opts); 420 perf_evlist__config(evlist, &opts, NULL);
421 421
422 /* Check moved event is still at the front */ 422 /* Check moved event is still at the front */
423 if (cycles_evsel != perf_evlist__first(evlist)) { 423 if (cycles_evsel != perf_evlist__first(evlist)) {
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 82b2b5e6ba7c..c57e72c826d2 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -85,6 +85,8 @@ int test__synthesize_stat_config(int subtest);
85int test__synthesize_stat(int subtest); 85int test__synthesize_stat(int subtest);
86int test__synthesize_stat_round(int subtest); 86int test__synthesize_stat_round(int subtest);
87int test__event_update(int subtest); 87int test__event_update(int subtest);
88int test__event_times(int subtest);
89int test__backward_ring_buffer(int subtest);
88 90
89#if defined(__arm__) || defined(__aarch64__) 91#if defined(__arm__) || defined(__aarch64__)
90#ifdef HAVE_DWARF_UNWIND_SUPPORT 92#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 630b0b409b97..e63abab7d5a1 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -54,8 +54,14 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
54 * Step 3: 54 * Step 3:
55 * 55 *
56 * Load and split /proc/kallsyms into multiple maps, one per module. 56 * Load and split /proc/kallsyms into multiple maps, one per module.
57 * Do not use kcore, as this test was designed before kcore support
58 * and has parts that only make sense if using the non-kcore code.
59 * XXX: extend it to stress the kcorre code as well, hint: the list
60 * of modules extracted from /proc/kcore, in its current form, can't
61 * be compacted against the list of modules found in the "vmlinux"
62 * code and with the one got from /proc/modules from the "kallsyms" code.
57 */ 63 */
58 if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) { 64 if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true, NULL) <= 0) {
59 pr_debug("dso__load_kallsyms "); 65 pr_debug("dso__load_kallsyms ");
60 goto out; 66 goto out;
61 } 67 }
@@ -157,6 +163,9 @@ next_pair:
157 163
158 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", 164 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
159 mem_start, sym->name, pair->name); 165 mem_start, sym->name, pair->name);
166 } else {
167 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
168 mem_start, sym->name, first_pair->name);
160 } 169 }
161 } 170 }
162 } else 171 } else
diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c
new file mode 100644
index 000000000000..d64f4a9128a1
--- /dev/null
+++ b/tools/perf/trace/beauty/eventfd.c
@@ -0,0 +1,38 @@
1#include <sys/eventfd.h>
2
3#ifndef EFD_SEMAPHORE
4#define EFD_SEMAPHORE 1
5#endif
6
7#ifndef EFD_NONBLOCK
8#define EFD_NONBLOCK 00004000
9#endif
10
11#ifndef EFD_CLOEXEC
12#define EFD_CLOEXEC 02000000
13#endif
14
15static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, struct syscall_arg *arg)
16{
17 int printed = 0, flags = arg->val;
18
19 if (flags == 0)
20 return scnprintf(bf, size, "NONE");
21#define P_FLAG(n) \
22 if (flags & EFD_##n) { \
23 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
24 flags &= ~EFD_##n; \
25 }
26
27 P_FLAG(SEMAPHORE);
28 P_FLAG(CLOEXEC);
29 P_FLAG(NONBLOCK);
30#undef P_FLAG
31
32 if (flags)
33 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
34
35 return printed;
36}
37
38#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
diff --git a/tools/perf/trace/beauty/flock.c b/tools/perf/trace/beauty/flock.c
new file mode 100644
index 000000000000..021bb48c6336
--- /dev/null
+++ b/tools/perf/trace/beauty/flock.c
@@ -0,0 +1,31 @@
1
2static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
3 struct syscall_arg *arg)
4{
5 int printed = 0, op = arg->val;
6
7 if (op == 0)
8 return scnprintf(bf, size, "NONE");
9#define P_CMD(cmd) \
10 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
11 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
12 op &= ~LOCK_##cmd; \
13 }
14
15 P_CMD(SH);
16 P_CMD(EX);
17 P_CMD(NB);
18 P_CMD(UN);
19 P_CMD(MAND);
20 P_CMD(RW);
21 P_CMD(READ);
22 P_CMD(WRITE);
23#undef P_OP
24
25 if (op)
26 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
27
28 return printed;
29}
30
31#define SCA_FLOCK syscall_arg__scnprintf_flock
diff --git a/tools/perf/trace/beauty/futex_op.c b/tools/perf/trace/beauty/futex_op.c
new file mode 100644
index 000000000000..e2476211f22d
--- /dev/null
+++ b/tools/perf/trace/beauty/futex_op.c
@@ -0,0 +1,44 @@
1#include <linux/futex.h>
2
3static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
4{
5 enum syscall_futex_args {
6 SCF_UADDR = (1 << 0),
7 SCF_OP = (1 << 1),
8 SCF_VAL = (1 << 2),
9 SCF_TIMEOUT = (1 << 3),
10 SCF_UADDR2 = (1 << 4),
11 SCF_VAL3 = (1 << 5),
12 };
13 int op = arg->val;
14 int cmd = op & FUTEX_CMD_MASK;
15 size_t printed = 0;
16
17 switch (cmd) {
18#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
19 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
20 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
21 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
22 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
23 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
24 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
25 P_FUTEX_OP(WAKE_OP); break;
26 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
27 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
28 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
29 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
30 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
31 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
32 default: printed = scnprintf(bf, size, "%#x", cmd); break;
33 }
34
35 if (op & FUTEX_PRIVATE_FLAG)
36 printed += scnprintf(bf + printed, size - printed, "|PRIV");
37
38 if (op & FUTEX_CLOCK_REALTIME)
39 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
40
41 return printed;
42}
43
44#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
new file mode 100644
index 000000000000..3444a4d5382d
--- /dev/null
+++ b/tools/perf/trace/beauty/mmap.c
@@ -0,0 +1,158 @@
1#include <sys/mman.h>
2
3static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
4 struct syscall_arg *arg)
5{
6 int printed = 0, prot = arg->val;
7
8 if (prot == PROT_NONE)
9 return scnprintf(bf, size, "NONE");
10#define P_MMAP_PROT(n) \
11 if (prot & PROT_##n) { \
12 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
13 prot &= ~PROT_##n; \
14 }
15
16 P_MMAP_PROT(EXEC);
17 P_MMAP_PROT(READ);
18 P_MMAP_PROT(WRITE);
19#ifdef PROT_SEM
20 P_MMAP_PROT(SEM);
21#endif
22 P_MMAP_PROT(GROWSDOWN);
23 P_MMAP_PROT(GROWSUP);
24#undef P_MMAP_PROT
25
26 if (prot)
27 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
28
29 return printed;
30}
31
32#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
33
34#ifndef MAP_STACK
35# define MAP_STACK 0x20000
36#endif
37
38static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
39 struct syscall_arg *arg)
40{
41 int printed = 0, flags = arg->val;
42
43#define P_MMAP_FLAG(n) \
44 if (flags & MAP_##n) { \
45 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
46 flags &= ~MAP_##n; \
47 }
48
49 P_MMAP_FLAG(SHARED);
50 P_MMAP_FLAG(PRIVATE);
51#ifdef MAP_32BIT
52 P_MMAP_FLAG(32BIT);
53#endif
54 P_MMAP_FLAG(ANONYMOUS);
55 P_MMAP_FLAG(DENYWRITE);
56 P_MMAP_FLAG(EXECUTABLE);
57 P_MMAP_FLAG(FILE);
58 P_MMAP_FLAG(FIXED);
59 P_MMAP_FLAG(GROWSDOWN);
60#ifdef MAP_HUGETLB
61 P_MMAP_FLAG(HUGETLB);
62#endif
63 P_MMAP_FLAG(LOCKED);
64 P_MMAP_FLAG(NONBLOCK);
65 P_MMAP_FLAG(NORESERVE);
66 P_MMAP_FLAG(POPULATE);
67 P_MMAP_FLAG(STACK);
68#ifdef MAP_UNINITIALIZED
69 P_MMAP_FLAG(UNINITIALIZED);
70#endif
71#undef P_MMAP_FLAG
72
73 if (flags)
74 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
75
76 return printed;
77}
78
79#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
80
81static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
82 struct syscall_arg *arg)
83{
84 int printed = 0, flags = arg->val;
85
86#define P_MREMAP_FLAG(n) \
87 if (flags & MREMAP_##n) { \
88 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
89 flags &= ~MREMAP_##n; \
90 }
91
92 P_MREMAP_FLAG(MAYMOVE);
93#ifdef MREMAP_FIXED
94 P_MREMAP_FLAG(FIXED);
95#endif
96#undef P_MREMAP_FLAG
97
98 if (flags)
99 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
100
101 return printed;
102}
103
104#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
105
106#ifndef MADV_HWPOISON
107#define MADV_HWPOISON 100
108#endif
109
110#ifndef MADV_MERGEABLE
111#define MADV_MERGEABLE 12
112#endif
113
114#ifndef MADV_UNMERGEABLE
115#define MADV_UNMERGEABLE 13
116#endif
117
118static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
119 struct syscall_arg *arg)
120{
121 int behavior = arg->val;
122
123 switch (behavior) {
124#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
125 P_MADV_BHV(NORMAL);
126 P_MADV_BHV(RANDOM);
127 P_MADV_BHV(SEQUENTIAL);
128 P_MADV_BHV(WILLNEED);
129 P_MADV_BHV(DONTNEED);
130 P_MADV_BHV(REMOVE);
131 P_MADV_BHV(DONTFORK);
132 P_MADV_BHV(DOFORK);
133 P_MADV_BHV(HWPOISON);
134#ifdef MADV_SOFT_OFFLINE
135 P_MADV_BHV(SOFT_OFFLINE);
136#endif
137 P_MADV_BHV(MERGEABLE);
138 P_MADV_BHV(UNMERGEABLE);
139#ifdef MADV_HUGEPAGE
140 P_MADV_BHV(HUGEPAGE);
141#endif
142#ifdef MADV_NOHUGEPAGE
143 P_MADV_BHV(NOHUGEPAGE);
144#endif
145#ifdef MADV_DONTDUMP
146 P_MADV_BHV(DONTDUMP);
147#endif
148#ifdef MADV_DODUMP
149 P_MADV_BHV(DODUMP);
150#endif
151#undef P_MADV_PHV
152 default: break;
153 }
154
155 return scnprintf(bf, size, "%#x", behavior);
156}
157
158#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
diff --git a/tools/perf/trace/beauty/mode_t.c b/tools/perf/trace/beauty/mode_t.c
new file mode 100644
index 000000000000..930d8fef2400
--- /dev/null
+++ b/tools/perf/trace/beauty/mode_t.c
@@ -0,0 +1,68 @@
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <unistd.h>
4
5/* From include/linux/stat.h */
6#ifndef S_IRWXUGO
7#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
8#endif
9#ifndef S_IALLUGO
10#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
11#endif
12#ifndef S_IRUGO
13#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
14#endif
15#ifndef S_IWUGO
16#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
17#endif
18#ifndef S_IXUGO
19#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
20#endif
21
22static size_t syscall_arg__scnprintf_mode_t(char *bf, size_t size, struct syscall_arg *arg)
23{
24 int printed = 0, mode = arg->val;
25
26#define P_MODE(n) \
27 if ((mode & S_##n) == S_##n) { \
28 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
29 mode &= ~S_##n; \
30 }
31
32 P_MODE(IALLUGO);
33 P_MODE(IRWXUGO);
34 P_MODE(IRUGO);
35 P_MODE(IWUGO);
36 P_MODE(IXUGO);
37 P_MODE(IFMT);
38 P_MODE(IFSOCK);
39 P_MODE(IFLNK);
40 P_MODE(IFREG);
41 P_MODE(IFBLK);
42 P_MODE(IFDIR);
43 P_MODE(IFCHR);
44 P_MODE(IFIFO);
45 P_MODE(ISUID);
46 P_MODE(ISGID);
47 P_MODE(ISVTX);
48 P_MODE(IRWXU);
49 P_MODE(IRUSR);
50 P_MODE(IWUSR);
51 P_MODE(IXUSR);
52 P_MODE(IRWXG);
53 P_MODE(IRGRP);
54 P_MODE(IWGRP);
55 P_MODE(IXGRP);
56 P_MODE(IRWXO);
57 P_MODE(IROTH);
58 P_MODE(IWOTH);
59 P_MODE(IXOTH);
60#undef P_MODE
61
62 if (mode)
63 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", mode);
64
65 return printed;
66}
67
68#define SCA_MODE_T syscall_arg__scnprintf_mode_t
diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c
new file mode 100644
index 000000000000..07fa8a0acad6
--- /dev/null
+++ b/tools/perf/trace/beauty/msg_flags.c
@@ -0,0 +1,62 @@
1#include <sys/types.h>
2#include <sys/socket.h>
3
4#ifndef MSG_PROBE
5#define MSG_PROBE 0x10
6#endif
7#ifndef MSG_WAITFORONE
8#define MSG_WAITFORONE 0x10000
9#endif
10#ifndef MSG_SENDPAGE_NOTLAST
11#define MSG_SENDPAGE_NOTLAST 0x20000
12#endif
13#ifndef MSG_FASTOPEN
14#define MSG_FASTOPEN 0x20000000
15#endif
16#ifndef MSG_CMSG_CLOEXEC
17# define MSG_CMSG_CLOEXEC 0x40000000
18#endif
19
20static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
21 struct syscall_arg *arg)
22{
23 int printed = 0, flags = arg->val;
24
25 if (flags == 0)
26 return scnprintf(bf, size, "NONE");
27#define P_MSG_FLAG(n) \
28 if (flags & MSG_##n) { \
29 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
30 flags &= ~MSG_##n; \
31 }
32
33 P_MSG_FLAG(OOB);
34 P_MSG_FLAG(PEEK);
35 P_MSG_FLAG(DONTROUTE);
36 P_MSG_FLAG(TRYHARD);
37 P_MSG_FLAG(CTRUNC);
38 P_MSG_FLAG(PROBE);
39 P_MSG_FLAG(TRUNC);
40 P_MSG_FLAG(DONTWAIT);
41 P_MSG_FLAG(EOR);
42 P_MSG_FLAG(WAITALL);
43 P_MSG_FLAG(FIN);
44 P_MSG_FLAG(SYN);
45 P_MSG_FLAG(CONFIRM);
46 P_MSG_FLAG(RST);
47 P_MSG_FLAG(ERRQUEUE);
48 P_MSG_FLAG(NOSIGNAL);
49 P_MSG_FLAG(MORE);
50 P_MSG_FLAG(WAITFORONE);
51 P_MSG_FLAG(SENDPAGE_NOTLAST);
52 P_MSG_FLAG(FASTOPEN);
53 P_MSG_FLAG(CMSG_CLOEXEC);
54#undef P_MSG_FLAG
55
56 if (flags)
57 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
58
59 return printed;
60}
61
62#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
new file mode 100644
index 000000000000..0f3679e0cdcf
--- /dev/null
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -0,0 +1,56 @@
1
2static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
3 struct syscall_arg *arg)
4{
5 int printed = 0, flags = arg->val;
6
7 if (!(flags & O_CREAT))
8 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
9
10 if (flags == 0)
11 return scnprintf(bf, size, "RDONLY");
12#define P_FLAG(n) \
13 if (flags & O_##n) { \
14 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
15 flags &= ~O_##n; \
16 }
17
18 P_FLAG(APPEND);
19 P_FLAG(ASYNC);
20 P_FLAG(CLOEXEC);
21 P_FLAG(CREAT);
22 P_FLAG(DIRECT);
23 P_FLAG(DIRECTORY);
24 P_FLAG(EXCL);
25 P_FLAG(LARGEFILE);
26 P_FLAG(NOATIME);
27 P_FLAG(NOCTTY);
28#ifdef O_NONBLOCK
29 P_FLAG(NONBLOCK);
30#elif O_NDELAY
31 P_FLAG(NDELAY);
32#endif
33#ifdef O_PATH
34 P_FLAG(PATH);
35#endif
36 P_FLAG(RDWR);
37#ifdef O_DSYNC
38 if ((flags & O_SYNC) == O_SYNC)
39 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
40 else {
41 P_FLAG(DSYNC);
42 }
43#else
44 P_FLAG(SYNC);
45#endif
46 P_FLAG(TRUNC);
47 P_FLAG(WRONLY);
48#undef P_FLAG
49
50 if (flags)
51 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
52
53 return printed;
54}
55
56#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c
new file mode 100644
index 000000000000..311f09dd718d
--- /dev/null
+++ b/tools/perf/trace/beauty/perf_event_open.c
@@ -0,0 +1,43 @@
1#ifndef PERF_FLAG_FD_NO_GROUP
2# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
3#endif
4
5#ifndef PERF_FLAG_FD_OUTPUT
6# define PERF_FLAG_FD_OUTPUT (1UL << 1)
7#endif
8
9#ifndef PERF_FLAG_PID_CGROUP
10# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
11#endif
12
13#ifndef PERF_FLAG_FD_CLOEXEC
14# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
15#endif
16
17static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
18 struct syscall_arg *arg)
19{
20 int printed = 0, flags = arg->val;
21
22 if (flags == 0)
23 return 0;
24
25#define P_FLAG(n) \
26 if (flags & PERF_FLAG_##n) { \
27 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
28 flags &= ~PERF_FLAG_##n; \
29 }
30
31 P_FLAG(FD_NO_GROUP);
32 P_FLAG(FD_OUTPUT);
33 P_FLAG(PID_CGROUP);
34 P_FLAG(FD_CLOEXEC);
35#undef P_FLAG
36
37 if (flags)
38 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
39
40 return printed;
41}
42
43#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c
new file mode 100644
index 000000000000..07486ea65ae3
--- /dev/null
+++ b/tools/perf/trace/beauty/pid.c
@@ -0,0 +1,21 @@
1static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
2{
3 int pid = arg->val;
4 struct trace *trace = arg->trace;
5 size_t printed = scnprintf(bf, size, "%d", pid);
6 struct thread *thread = machine__findnew_thread(trace->host, pid, pid);
7
8 if (thread != NULL) {
9 if (!thread->comm_set)
10 thread__set_comm_from_proc(thread);
11
12 if (thread->comm_set)
13 printed += scnprintf(bf + printed, size - printed,
14 " (%s)", thread__comm_str(thread));
15 thread__put(thread);
16 }
17
18 return printed;
19}
20
21#define SCA_PID syscall_arg__scnprintf_pid
diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c
new file mode 100644
index 000000000000..c205bc608b3c
--- /dev/null
+++ b/tools/perf/trace/beauty/sched_policy.c
@@ -0,0 +1,44 @@
1#include <sched.h>
2
3/*
4 * Not defined anywhere else, probably, just to make sure we
5 * catch future flags
6 */
7#define SCHED_POLICY_MASK 0xff
8
9#ifndef SCHED_DEADLINE
10#define SCHED_DEADLINE 6
11#endif
12
13static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size,
14 struct syscall_arg *arg)
15{
16 const char *policies[] = {
17 "NORMAL", "FIFO", "RR", "BATCH", "ISO", "IDLE", "DEADLINE",
18 };
19 size_t printed;
20 int policy = arg->val,
21 flags = policy & ~SCHED_POLICY_MASK;
22
23 policy &= SCHED_POLICY_MASK;
24 if (policy <= SCHED_DEADLINE)
25 printed = scnprintf(bf, size, "%s", policies[policy]);
26 else
27 printed = scnprintf(bf, size, "%#x", policy);
28
29#define P_POLICY_FLAG(n) \
30 if (flags & SCHED_##n) { \
31 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
32 flags &= ~SCHED_##n; \
33 }
34
35 P_POLICY_FLAG(RESET_ON_FORK);
36#undef P_POLICY_FLAG
37
38 if (flags)
39 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
40
41 return printed;
42}
43
44#define SCA_SCHED_POLICY syscall_arg__scnprintf_sched_policy
diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c
new file mode 100644
index 000000000000..213c5a7e3e92
--- /dev/null
+++ b/tools/perf/trace/beauty/seccomp.c
@@ -0,0 +1,52 @@
1#include <linux/seccomp.h>
2
3#ifndef SECCOMP_SET_MODE_STRICT
4#define SECCOMP_SET_MODE_STRICT 0
5#endif
6#ifndef SECCOMP_SET_MODE_FILTER
7#define SECCOMP_SET_MODE_FILTER 1
8#endif
9
10static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
11{
12 int op = arg->val;
13 size_t printed = 0;
14
15 switch (op) {
16#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
17 P_SECCOMP_SET_MODE_OP(STRICT);
18 P_SECCOMP_SET_MODE_OP(FILTER);
19#undef P_SECCOMP_SET_MODE_OP
20 default: printed = scnprintf(bf, size, "%#x", op); break;
21 }
22
23 return printed;
24}
25
26#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
27
28#ifndef SECCOMP_FILTER_FLAG_TSYNC
29#define SECCOMP_FILTER_FLAG_TSYNC 1
30#endif
31
32static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
33 struct syscall_arg *arg)
34{
35 int printed = 0, flags = arg->val;
36
37#define P_FLAG(n) \
38 if (flags & SECCOMP_FILTER_FLAG_##n) { \
39 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
40 flags &= ~SECCOMP_FILTER_FLAG_##n; \
41 }
42
43 P_FLAG(TSYNC);
44#undef P_FLAG
45
46 if (flags)
47 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
48
49 return printed;
50}
51
52#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
diff --git a/tools/perf/trace/beauty/signum.c b/tools/perf/trace/beauty/signum.c
new file mode 100644
index 000000000000..d3b0b1fab077
--- /dev/null
+++ b/tools/perf/trace/beauty/signum.c
@@ -0,0 +1,53 @@
1
2static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
3{
4 int sig = arg->val;
5
6 switch (sig) {
7#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
8 P_SIGNUM(HUP);
9 P_SIGNUM(INT);
10 P_SIGNUM(QUIT);
11 P_SIGNUM(ILL);
12 P_SIGNUM(TRAP);
13 P_SIGNUM(ABRT);
14 P_SIGNUM(BUS);
15 P_SIGNUM(FPE);
16 P_SIGNUM(KILL);
17 P_SIGNUM(USR1);
18 P_SIGNUM(SEGV);
19 P_SIGNUM(USR2);
20 P_SIGNUM(PIPE);
21 P_SIGNUM(ALRM);
22 P_SIGNUM(TERM);
23 P_SIGNUM(CHLD);
24 P_SIGNUM(CONT);
25 P_SIGNUM(STOP);
26 P_SIGNUM(TSTP);
27 P_SIGNUM(TTIN);
28 P_SIGNUM(TTOU);
29 P_SIGNUM(URG);
30 P_SIGNUM(XCPU);
31 P_SIGNUM(XFSZ);
32 P_SIGNUM(VTALRM);
33 P_SIGNUM(PROF);
34 P_SIGNUM(WINCH);
35 P_SIGNUM(IO);
36 P_SIGNUM(PWR);
37 P_SIGNUM(SYS);
38#ifdef SIGEMT
39 P_SIGNUM(EMT);
40#endif
41#ifdef SIGSTKFLT
42 P_SIGNUM(STKFLT);
43#endif
44#ifdef SIGSWI
45 P_SIGNUM(SWI);
46#endif
47 default: break;
48 }
49
50 return scnprintf(bf, size, "%#x", sig);
51}
52
53#define SCA_SIGNUM syscall_arg__scnprintf_signum
diff --git a/tools/perf/trace/beauty/socket_type.c b/tools/perf/trace/beauty/socket_type.c
new file mode 100644
index 000000000000..0a5ce818131c
--- /dev/null
+++ b/tools/perf/trace/beauty/socket_type.c
@@ -0,0 +1,60 @@
1#include <sys/types.h>
2#include <sys/socket.h>
3
4#ifndef SOCK_DCCP
5# define SOCK_DCCP 6
6#endif
7
8#ifndef SOCK_CLOEXEC
9# define SOCK_CLOEXEC 02000000
10#endif
11
12#ifndef SOCK_NONBLOCK
13# define SOCK_NONBLOCK 00004000
14#endif
15
16#ifndef SOCK_TYPE_MASK
17#define SOCK_TYPE_MASK 0xf
18#endif
19
20static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, struct syscall_arg *arg)
21{
22 size_t printed;
23 int type = arg->val,
24 flags = type & ~SOCK_TYPE_MASK;
25
26 type &= SOCK_TYPE_MASK;
27 /*
28 * Can't use a strarray, MIPS may override for ABI reasons.
29 */
30 switch (type) {
31#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
32 P_SK_TYPE(STREAM);
33 P_SK_TYPE(DGRAM);
34 P_SK_TYPE(RAW);
35 P_SK_TYPE(RDM);
36 P_SK_TYPE(SEQPACKET);
37 P_SK_TYPE(DCCP);
38 P_SK_TYPE(PACKET);
39#undef P_SK_TYPE
40 default:
41 printed = scnprintf(bf, size, "%#x", type);
42 }
43
44#define P_SK_FLAG(n) \
45 if (flags & SOCK_##n) { \
46 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
47 flags &= ~SOCK_##n; \
48 }
49
50 P_SK_FLAG(CLOEXEC);
51 P_SK_FLAG(NONBLOCK);
52#undef P_SK_FLAG
53
54 if (flags)
55 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
56
57 return printed;
58}
59
60#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
diff --git a/tools/perf/trace/beauty/waitid_options.c b/tools/perf/trace/beauty/waitid_options.c
new file mode 100644
index 000000000000..7942724adec8
--- /dev/null
+++ b/tools/perf/trace/beauty/waitid_options.c
@@ -0,0 +1,26 @@
1#include <sys/types.h>
2#include <sys/wait.h>
3
4static size_t syscall_arg__scnprintf_waitid_options(char *bf, size_t size,
5 struct syscall_arg *arg)
6{
7 int printed = 0, options = arg->val;
8
9#define P_OPTION(n) \
10 if (options & W##n) { \
11 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
12 options &= ~W##n; \
13 }
14
15 P_OPTION(NOHANG);
16 P_OPTION(UNTRACED);
17 P_OPTION(CONTINUED);
18#undef P_OPTION
19
20 if (options)
21 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", options);
22
23 return printed;
24}
25
26#define SCA_WAITID_OPTIONS syscall_arg__scnprintf_waitid_options
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 2a83414159a6..538bae880bfe 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1607,9 +1607,8 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
1607 1607
1608 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 1608 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
1609 dummy_hpp.buf[ret] = '\0'; 1609 dummy_hpp.buf[ret] = '\0';
1610 rtrim(dummy_hpp.buf);
1611 1610
1612 start = ltrim(dummy_hpp.buf); 1611 start = trim(dummy_hpp.buf);
1613 ret = strlen(start); 1612 ret = strlen(start);
1614 1613
1615 if (start != dummy_hpp.buf) 1614 if (start != dummy_hpp.buf)
@@ -1897,11 +1896,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1897 bool first = true; 1896 bool first = true;
1898 int ret; 1897 int ret;
1899 1898
1900 if (symbol_conf.use_callchain) 1899 if (symbol_conf.use_callchain) {
1901 folded_sign = hist_entry__folded(he); 1900 folded_sign = hist_entry__folded(he);
1902
1903 if (symbol_conf.use_callchain)
1904 printed += fprintf(fp, "%c ", folded_sign); 1901 printed += fprintf(fp, "%c ", folded_sign);
1902 }
1905 1903
1906 hists__for_each_format(browser->hists, fmt) { 1904 hists__for_each_format(browser->hists, fmt) {
1907 if (perf_hpp__should_skip(fmt, he->hists)) 1905 if (perf_hpp__should_skip(fmt, he->hists))
@@ -2137,7 +2135,7 @@ static int hists__browser_title(struct hists *hists,
2137 printed += snprintf(bf + printed, size - printed, 2135 printed += snprintf(bf + printed, size - printed,
2138 ", UID: %s", hists->uid_filter_str); 2136 ", UID: %s", hists->uid_filter_str);
2139 if (thread) { 2137 if (thread) {
2140 if (sort__has_thread) { 2138 if (hists__has(hists, thread)) {
2141 printed += scnprintf(bf + printed, size - printed, 2139 printed += scnprintf(bf + printed, size - printed,
2142 ", Thread: %s(%d)", 2140 ", Thread: %s(%d)",
2143 (thread->comm_set ? thread__comm_str(thread) : ""), 2141 (thread->comm_set ? thread__comm_str(thread) : ""),
@@ -2322,7 +2320,8 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act)
2322{ 2320{
2323 struct thread *thread = act->thread; 2321 struct thread *thread = act->thread;
2324 2322
2325 if ((!sort__has_thread && !sort__has_comm) || thread == NULL) 2323 if ((!hists__has(browser->hists, thread) &&
2324 !hists__has(browser->hists, comm)) || thread == NULL)
2326 return 0; 2325 return 0;
2327 2326
2328 if (browser->hists->thread_filter) { 2327 if (browser->hists->thread_filter) {
@@ -2331,7 +2330,7 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act)
2331 thread__zput(browser->hists->thread_filter); 2330 thread__zput(browser->hists->thread_filter);
2332 ui_helpline__pop(); 2331 ui_helpline__pop();
2333 } else { 2332 } else {
2334 if (sort__has_thread) { 2333 if (hists__has(browser->hists, thread)) {
2335 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"", 2334 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"",
2336 thread->comm_set ? thread__comm_str(thread) : "", 2335 thread->comm_set ? thread__comm_str(thread) : "",
2337 thread->tid); 2336 thread->tid);
@@ -2356,10 +2355,11 @@ add_thread_opt(struct hist_browser *browser, struct popup_action *act,
2356{ 2355{
2357 int ret; 2356 int ret;
2358 2357
2359 if ((!sort__has_thread && !sort__has_comm) || thread == NULL) 2358 if ((!hists__has(browser->hists, thread) &&
2359 !hists__has(browser->hists, comm)) || thread == NULL)
2360 return 0; 2360 return 0;
2361 2361
2362 if (sort__has_thread) { 2362 if (hists__has(browser->hists, thread)) {
2363 ret = asprintf(optstr, "Zoom %s %s(%d) thread", 2363 ret = asprintf(optstr, "Zoom %s %s(%d) thread",
2364 browser->hists->thread_filter ? "out of" : "into", 2364 browser->hists->thread_filter ? "out of" : "into",
2365 thread->comm_set ? thread__comm_str(thread) : "", 2365 thread->comm_set ? thread__comm_str(thread) : "",
@@ -2382,7 +2382,7 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
2382{ 2382{
2383 struct map *map = act->ms.map; 2383 struct map *map = act->ms.map;
2384 2384
2385 if (!sort__has_dso || map == NULL) 2385 if (!hists__has(browser->hists, dso) || map == NULL)
2386 return 0; 2386 return 0;
2387 2387
2388 if (browser->hists->dso_filter) { 2388 if (browser->hists->dso_filter) {
@@ -2409,7 +2409,7 @@ static int
2409add_dso_opt(struct hist_browser *browser, struct popup_action *act, 2409add_dso_opt(struct hist_browser *browser, struct popup_action *act,
2410 char **optstr, struct map *map) 2410 char **optstr, struct map *map)
2411{ 2411{
2412 if (!sort__has_dso || map == NULL) 2412 if (!hists__has(browser->hists, dso) || map == NULL)
2413 return 0; 2413 return 0;
2414 2414
2415 if (asprintf(optstr, "Zoom %s %s DSO", 2415 if (asprintf(optstr, "Zoom %s %s DSO",
@@ -2431,10 +2431,10 @@ do_browse_map(struct hist_browser *browser __maybe_unused,
2431} 2431}
2432 2432
2433static int 2433static int
2434add_map_opt(struct hist_browser *browser __maybe_unused, 2434add_map_opt(struct hist_browser *browser,
2435 struct popup_action *act, char **optstr, struct map *map) 2435 struct popup_action *act, char **optstr, struct map *map)
2436{ 2436{
2437 if (!sort__has_dso || map == NULL) 2437 if (!hists__has(browser->hists, dso) || map == NULL)
2438 return 0; 2438 return 0;
2439 2439
2440 if (asprintf(optstr, "Browse map details") < 0) 2440 if (asprintf(optstr, "Browse map details") < 0)
@@ -2536,7 +2536,7 @@ add_exit_opt(struct hist_browser *browser __maybe_unused,
2536static int 2536static int
2537do_zoom_socket(struct hist_browser *browser, struct popup_action *act) 2537do_zoom_socket(struct hist_browser *browser, struct popup_action *act)
2538{ 2538{
2539 if (!sort__has_socket || act->socket < 0) 2539 if (!hists__has(browser->hists, socket) || act->socket < 0)
2540 return 0; 2540 return 0;
2541 2541
2542 if (browser->hists->socket_filter > -1) { 2542 if (browser->hists->socket_filter > -1) {
@@ -2558,7 +2558,7 @@ static int
2558add_socket_opt(struct hist_browser *browser, struct popup_action *act, 2558add_socket_opt(struct hist_browser *browser, struct popup_action *act,
2559 char **optstr, int socket_id) 2559 char **optstr, int socket_id)
2560{ 2560{
2561 if (!sort__has_socket || socket_id < 0) 2561 if (!hists__has(browser->hists, socket) || socket_id < 0)
2562 return 0; 2562 return 0;
2563 2563
2564 if (asprintf(optstr, "Zoom %s Processor Socket %d", 2564 if (asprintf(optstr, "Zoom %s Processor Socket %d",
@@ -2749,7 +2749,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2749 */ 2749 */
2750 goto out_free_stack; 2750 goto out_free_stack;
2751 case 'a': 2751 case 'a':
2752 if (!sort__has_sym) { 2752 if (!hists__has(hists, sym)) {
2753 ui_browser__warning(&browser->b, delay_secs * 2, 2753 ui_browser__warning(&browser->b, delay_secs * 2,
2754 "Annotation is only available for symbolic views, " 2754 "Annotation is only available for symbolic views, "
2755 "include \"sym*\" in --sort to use it."); 2755 "include \"sym*\" in --sort to use it.");
@@ -2912,7 +2912,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2912 continue; 2912 continue;
2913 } 2913 }
2914 2914
2915 if (!sort__has_sym || browser->selection == NULL) 2915 if (!hists__has(hists, sym) || browser->selection == NULL)
2916 goto skip_annotation; 2916 goto skip_annotation;
2917 2917
2918 if (sort__mode == SORT_MODE__BRANCH) { 2918 if (sort__mode == SORT_MODE__BRANCH) {
@@ -2956,7 +2956,7 @@ skip_annotation:
2956 goto skip_scripting; 2956 goto skip_scripting;
2957 2957
2958 if (browser->he_selection) { 2958 if (browser->he_selection) {
2959 if (sort__has_thread && thread) { 2959 if (hists__has(hists, thread) && thread) {
2960 nr_options += add_script_opt(browser, 2960 nr_options += add_script_opt(browser,
2961 &actions[nr_options], 2961 &actions[nr_options],
2962 &options[nr_options], 2962 &options[nr_options],
@@ -2971,7 +2971,7 @@ skip_annotation:
2971 * 2971 *
2972 * See hist_browser__show_entry. 2972 * See hist_browser__show_entry.
2973 */ 2973 */
2974 if (sort__has_sym && browser->selection->sym) { 2974 if (hists__has(hists, sym) && browser->selection->sym) {
2975 nr_options += add_script_opt(browser, 2975 nr_options += add_script_opt(browser,
2976 &actions[nr_options], 2976 &actions[nr_options],
2977 &options[nr_options], 2977 &options[nr_options],
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 2aa45b606fa4..932adfaa05af 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -379,7 +379,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
379 gtk_tree_store_set(store, &iter, col_idx++, s, -1); 379 gtk_tree_store_set(store, &iter, col_idx++, s, -1);
380 } 380 }
381 381
382 if (symbol_conf.use_callchain && sort__has_sym) { 382 if (symbol_conf.use_callchain && hists__has(hists, sym)) {
383 if (callchain_param.mode == CHAIN_GRAPH_REL) 383 if (callchain_param.mode == CHAIN_GRAPH_REL)
384 total = symbol_conf.cumulate_callchain ? 384 total = symbol_conf.cumulate_callchain ?
385 h->stat_acc->period : h->stat.period; 385 h->stat_acc->period : h->stat.period;
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 3baeaa6e71b5..af07ffb129ca 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -635,7 +635,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
635 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); 635 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists));
636 } 636 }
637 637
638 if (verbose && sort__has_sym) /* Addr + origin */ 638 if (verbose && hists__has(hists, sym)) /* Addr + origin */
639 ret += 3 + BITS_PER_LONG / 4; 639 ret += 3 + BITS_PER_LONG / 4;
640 640
641 return ret; 641 return ret;
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 7aff5acf3265..560eb47d56f9 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -569,9 +569,8 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
569 first_col = false; 569 first_col = false;
570 570
571 fmt->header(fmt, hpp, hists_to_evsel(hists)); 571 fmt->header(fmt, hpp, hists_to_evsel(hists));
572 rtrim(hpp->buf);
573 572
574 header_width += fprintf(fp, "%s", ltrim(hpp->buf)); 573 header_width += fprintf(fp, "%s", trim(hpp->buf));
575 } 574 }
576 } 575 }
577 576
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index da48fd843438..8c6c8a0ca642 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -8,6 +8,7 @@ libperf-y += env.o
8libperf-y += event.o 8libperf-y += event.o
9libperf-y += evlist.o 9libperf-y += evlist.o
10libperf-y += evsel.o 10libperf-y += evsel.o
11libperf-y += evsel_fprintf.o
11libperf-y += find_bit.o 12libperf-y += find_bit.o
12libperf-y += kallsyms.o 13libperf-y += kallsyms.o
13libperf-y += levenshtein.o 14libperf-y += levenshtein.o
@@ -26,9 +27,9 @@ libperf-y += strlist.o
26libperf-y += strfilter.o 27libperf-y += strfilter.o
27libperf-y += top.o 28libperf-y += top.o
28libperf-y += usage.o 29libperf-y += usage.o
29libperf-y += wrapper.o
30libperf-y += dso.o 30libperf-y += dso.o
31libperf-y += symbol.o 31libperf-y += symbol.o
32libperf-y += symbol_fprintf.o
32libperf-y += color.o 33libperf-y += color.o
33libperf-y += header.o 34libperf-y += header.o
34libperf-y += callchain.o 35libperf-y += callchain.o
@@ -38,6 +39,7 @@ libperf-y += machine.o
38libperf-y += map.o 39libperf-y += map.o
39libperf-y += pstack.o 40libperf-y += pstack.o
40libperf-y += session.o 41libperf-y += session.o
42libperf-$(CONFIG_AUDIT) += syscalltbl.o
41libperf-y += ordered-events.o 43libperf-y += ordered-events.o
42libperf-y += comm.o 44libperf-y += comm.o
43libperf-y += thread.o 45libperf-y += thread.o
@@ -69,9 +71,9 @@ libperf-y += stat-shadow.o
69libperf-y += record.o 71libperf-y += record.o
70libperf-y += srcline.o 72libperf-y += srcline.o
71libperf-y += data.o 73libperf-y += data.o
72libperf-$(CONFIG_X86) += tsc.o 74libperf-y += tsc.o
73libperf-$(CONFIG_AUXTRACE) += tsc.o
74libperf-y += cloexec.o 75libperf-y += cloexec.o
76libperf-y += call-path.o
75libperf-y += thread-stack.o 77libperf-y += thread-stack.o
76libperf-$(CONFIG_AUXTRACE) += auxtrace.o 78libperf-$(CONFIG_AUXTRACE) += auxtrace.o
77libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/ 79libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index b795b6994144..4db73d5a0dbc 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1138,7 +1138,7 @@ fallback:
1138 1138
1139 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1139 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1140 !dso__is_kcore(dso)) { 1140 !dso__is_kcore(dso)) {
1141 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id "; 1141 char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1142 char *build_id_msg = NULL; 1142 char *build_id_msg = NULL;
1143 1143
1144 if (dso->annotate_warned) 1144 if (dso->annotate_warned)
@@ -1665,5 +1665,5 @@ int hist_entry__annotate(struct hist_entry *he, size_t privsize)
1665 1665
1666bool ui__has_annotation(void) 1666bool ui__has_annotation(void)
1667{ 1667{
1668 return use_browser == 1 && sort__has_sym; 1668 return use_browser == 1 && perf_hpp_list.sym;
1669} 1669}
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index ec164fe70718..c9169011e55e 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -940,6 +940,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
940 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD; 940 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
941 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ; 941 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
942 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ; 942 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
943 synth_opts->initial_skip = 0;
943} 944}
944 945
945/* 946/*
@@ -1064,6 +1065,12 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str,
1064 synth_opts->last_branch_sz = val; 1065 synth_opts->last_branch_sz = val;
1065 } 1066 }
1066 break; 1067 break;
1068 case 's':
1069 synth_opts->initial_skip = strtoul(p, &endptr, 10);
1070 if (p == endptr)
1071 goto out_err;
1072 p = endptr;
1073 break;
1067 case ' ': 1074 case ' ':
1068 case ',': 1075 case ',':
1069 break; 1076 break;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 57ff31ecb8e4..767989e0e312 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -68,6 +68,7 @@ enum itrace_period_type {
68 * @last_branch_sz: branch context size 68 * @last_branch_sz: branch context size
69 * @period: 'instructions' events period 69 * @period: 'instructions' events period
70 * @period_type: 'instructions' events period type 70 * @period_type: 'instructions' events period type
71 * @initial_skip: skip N events at the beginning.
71 */ 72 */
72struct itrace_synth_opts { 73struct itrace_synth_opts {
73 bool set; 74 bool set;
@@ -86,6 +87,7 @@ struct itrace_synth_opts {
86 unsigned int last_branch_sz; 87 unsigned int last_branch_sz;
87 unsigned long long period; 88 unsigned long long period;
88 enum itrace_period_type period_type; 89 enum itrace_period_type period_type;
90 unsigned long initial_skip;
89}; 91};
90 92
91/** 93/**
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 0967ce601931..493307d1414c 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -842,6 +842,58 @@ bpf_map_op__new(struct parse_events_term *term)
842 return op; 842 return op;
843} 843}
844 844
845static struct bpf_map_op *
846bpf_map_op__clone(struct bpf_map_op *op)
847{
848 struct bpf_map_op *newop;
849
850 newop = memdup(op, sizeof(*op));
851 if (!newop) {
852 pr_debug("Failed to alloc bpf_map_op\n");
853 return NULL;
854 }
855
856 INIT_LIST_HEAD(&newop->list);
857 if (op->key_type == BPF_MAP_KEY_RANGES) {
858 size_t memsz = op->k.array.nr_ranges *
859 sizeof(op->k.array.ranges[0]);
860
861 newop->k.array.ranges = memdup(op->k.array.ranges, memsz);
862 if (!newop->k.array.ranges) {
863 pr_debug("Failed to alloc indices for map\n");
864 free(newop);
865 return NULL;
866 }
867 }
868
869 return newop;
870}
871
872static struct bpf_map_priv *
873bpf_map_priv__clone(struct bpf_map_priv *priv)
874{
875 struct bpf_map_priv *newpriv;
876 struct bpf_map_op *pos, *newop;
877
878 newpriv = zalloc(sizeof(*newpriv));
879 if (!newpriv) {
880 pr_debug("No enough memory to alloc map private\n");
881 return NULL;
882 }
883 INIT_LIST_HEAD(&newpriv->ops_list);
884
885 list_for_each_entry(pos, &priv->ops_list, list) {
886 newop = bpf_map_op__clone(pos);
887 if (!newop) {
888 bpf_map_priv__purge(newpriv);
889 return NULL;
890 }
891 list_add_tail(&newop->list, &newpriv->ops_list);
892 }
893
894 return newpriv;
895}
896
845static int 897static int
846bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op) 898bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
847{ 899{
@@ -1417,6 +1469,89 @@ int bpf__apply_obj_config(void)
1417 return 0; 1469 return 0;
1418} 1470}
1419 1471
1472#define bpf__for_each_map(pos, obj, objtmp) \
1473 bpf_object__for_each_safe(obj, objtmp) \
1474 bpf_map__for_each(pos, obj)
1475
1476#define bpf__for_each_stdout_map(pos, obj, objtmp) \
1477 bpf__for_each_map(pos, obj, objtmp) \
1478 if (bpf_map__get_name(pos) && \
1479 (strcmp("__bpf_stdout__", \
1480 bpf_map__get_name(pos)) == 0))
1481
1482int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
1483{
1484 struct bpf_map_priv *tmpl_priv = NULL;
1485 struct bpf_object *obj, *tmp;
1486 struct perf_evsel *evsel = NULL;
1487 struct bpf_map *map;
1488 int err;
1489 bool need_init = false;
1490
1491 bpf__for_each_stdout_map(map, obj, tmp) {
1492 struct bpf_map_priv *priv;
1493
1494 err = bpf_map__get_private(map, (void **)&priv);
1495 if (err)
1496 return -BPF_LOADER_ERRNO__INTERNAL;
1497
1498 /*
1499 * No need to check map type: type should have been
1500 * verified by kernel.
1501 */
1502 if (!need_init && !priv)
1503 need_init = !priv;
1504 if (!tmpl_priv && priv)
1505 tmpl_priv = priv;
1506 }
1507
1508 if (!need_init)
1509 return 0;
1510
1511 if (!tmpl_priv) {
1512 err = parse_events(evlist, "bpf-output/no-inherit=1,name=__bpf_stdout__/",
1513 NULL);
1514 if (err) {
1515 pr_debug("ERROR: failed to create bpf-output event\n");
1516 return -err;
1517 }
1518
1519 evsel = perf_evlist__last(evlist);
1520 }
1521
1522 bpf__for_each_stdout_map(map, obj, tmp) {
1523 struct bpf_map_priv *priv;
1524
1525 err = bpf_map__get_private(map, (void **)&priv);
1526 if (err)
1527 return -BPF_LOADER_ERRNO__INTERNAL;
1528 if (priv)
1529 continue;
1530
1531 if (tmpl_priv) {
1532 priv = bpf_map_priv__clone(tmpl_priv);
1533 if (!priv)
1534 return -ENOMEM;
1535
1536 err = bpf_map__set_private(map, priv, bpf_map_priv__clear);
1537 if (err) {
1538 bpf_map_priv__clear(map, priv);
1539 return err;
1540 }
1541 } else if (evsel) {
1542 struct bpf_map_op *op;
1543
1544 op = bpf_map__add_newop(map, NULL);
1545 if (IS_ERR(op))
1546 return PTR_ERR(op);
1547 op->op_type = BPF_MAP_OP_SET_EVSEL;
1548 op->v.evsel = evsel;
1549 }
1550 }
1551
1552 return 0;
1553}
1554
1420#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) 1555#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)
1421#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c) 1556#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
1422#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START) 1557#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
@@ -1590,3 +1725,11 @@ int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
1590 bpf__strerror_end(buf, size); 1725 bpf__strerror_end(buf, size);
1591 return 0; 1726 return 0;
1592} 1727}
1728
1729int bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused,
1730 int err, char *buf, size_t size)
1731{
1732 bpf__strerror_head(err, buf, size);
1733 bpf__strerror_end(buf, size);
1734 return 0;
1735}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index be4311944e3d..941e17275aa7 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -79,6 +79,11 @@ int bpf__strerror_config_obj(struct bpf_object *obj,
79 size_t size); 79 size_t size);
80int bpf__apply_obj_config(void); 80int bpf__apply_obj_config(void);
81int bpf__strerror_apply_obj_config(int err, char *buf, size_t size); 81int bpf__strerror_apply_obj_config(int err, char *buf, size_t size);
82
83int bpf__setup_stdout(struct perf_evlist *evlist);
84int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err,
85 char *buf, size_t size);
86
82#else 87#else
83static inline struct bpf_object * 88static inline struct bpf_object *
84bpf__prepare_load(const char *filename __maybe_unused, 89bpf__prepare_load(const char *filename __maybe_unused,
@@ -125,6 +130,12 @@ bpf__apply_obj_config(void)
125} 130}
126 131
127static inline int 132static inline int
133bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
134{
135 return 0;
136}
137
138static inline int
128__bpf_strerror(char *buf, size_t size) 139__bpf_strerror(char *buf, size_t size)
129{ 140{
130 if (!size) 141 if (!size)
@@ -177,5 +188,13 @@ bpf__strerror_apply_obj_config(int err __maybe_unused,
177{ 188{
178 return __bpf_strerror(buf, size); 189 return __bpf_strerror(buf, size);
179} 190}
191
192static inline int
193bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused,
194 int err __maybe_unused, char *buf,
195 size_t size)
196{
197 return __bpf_strerror(buf, size);
198}
180#endif 199#endif
181#endif 200#endif
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0573c2ec861d..bff425e1232c 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -261,14 +261,14 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
261 261
262 if (dso__is_vdso(pos)) { 262 if (dso__is_vdso(pos)) {
263 name = pos->short_name; 263 name = pos->short_name;
264 name_len = pos->short_name_len + 1; 264 name_len = pos->short_name_len;
265 } else if (dso__is_kcore(pos)) { 265 } else if (dso__is_kcore(pos)) {
266 machine__mmap_name(machine, nm, sizeof(nm)); 266 machine__mmap_name(machine, nm, sizeof(nm));
267 name = nm; 267 name = nm;
268 name_len = strlen(nm) + 1; 268 name_len = strlen(nm);
269 } else { 269 } else {
270 name = pos->long_name; 270 name = pos->long_name;
271 name_len = pos->long_name_len + 1; 271 name_len = pos->long_name_len;
272 } 272 }
273 273
274 in_kernel = pos->kernel || 274 in_kernel = pos->kernel ||
@@ -365,39 +365,17 @@ static char *build_id_cache__dirname_from_path(const char *name,
365int build_id_cache__list_build_ids(const char *pathname, 365int build_id_cache__list_build_ids(const char *pathname,
366 struct strlist **result) 366 struct strlist **result)
367{ 367{
368 struct strlist *list;
369 char *dir_name; 368 char *dir_name;
370 DIR *dir;
371 struct dirent *d;
372 int ret = 0; 369 int ret = 0;
373 370
374 list = strlist__new(NULL, NULL);
375 dir_name = build_id_cache__dirname_from_path(pathname, false, false); 371 dir_name = build_id_cache__dirname_from_path(pathname, false, false);
376 if (!list || !dir_name) { 372 if (!dir_name)
377 ret = -ENOMEM; 373 return -ENOMEM;
378 goto out;
379 }
380 374
381 /* List up all dirents */ 375 *result = lsdir(dir_name, lsdir_no_dot_filter);
382 dir = opendir(dir_name); 376 if (!*result)
383 if (!dir) {
384 ret = -errno; 377 ret = -errno;
385 goto out;
386 }
387
388 while ((d = readdir(dir)) != NULL) {
389 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
390 continue;
391 strlist__add(list, d->d_name);
392 }
393 closedir(dir);
394
395out:
396 free(dir_name); 378 free(dir_name);
397 if (ret)
398 strlist__delete(list);
399 else
400 *result = list;
401 379
402 return ret; 380 return ret;
403} 381}
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 1f5a93c2c9a2..0d814bb74661 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -40,25 +40,6 @@ int split_cmdline(char *cmdline, const char ***argv);
40 40
41#define alloc_nr(x) (((x)+16)*3/2) 41#define alloc_nr(x) (((x)+16)*3/2)
42 42
43/*
44 * Realloc the buffer pointed at by variable 'x' so that it can hold
45 * at least 'nr' entries; the number of entries currently allocated
46 * is 'alloc', using the standard growing factor alloc_nr() macro.
47 *
48 * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
49 */
50#define ALLOC_GROW(x, nr, alloc) \
51 do { \
52 if ((nr) > alloc) { \
53 if (alloc_nr(alloc) < (nr)) \
54 alloc = (nr); \
55 else \
56 alloc = alloc_nr(alloc); \
57 x = xrealloc((x), alloc * sizeof(*(x))); \
58 } \
59 } while(0)
60
61
62static inline int is_absolute_path(const char *path) 43static inline int is_absolute_path(const char *path)
63{ 44{
64 return path[0] == '/'; 45 return path[0] == '/';
diff --git a/tools/perf/util/call-path.c b/tools/perf/util/call-path.c
new file mode 100644
index 000000000000..904a17052e38
--- /dev/null
+++ b/tools/perf/util/call-path.c
@@ -0,0 +1,122 @@
1/*
2 * call-path.h: Manipulate a tree data structure containing function call paths
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <linux/rbtree.h>
17#include <linux/list.h>
18
19#include "util.h"
20#include "call-path.h"
21
22static void call_path__init(struct call_path *cp, struct call_path *parent,
23 struct symbol *sym, u64 ip, bool in_kernel)
24{
25 cp->parent = parent;
26 cp->sym = sym;
27 cp->ip = sym ? 0 : ip;
28 cp->db_id = 0;
29 cp->in_kernel = in_kernel;
30 RB_CLEAR_NODE(&cp->rb_node);
31 cp->children = RB_ROOT;
32}
33
34struct call_path_root *call_path_root__new(void)
35{
36 struct call_path_root *cpr;
37
38 cpr = zalloc(sizeof(struct call_path_root));
39 if (!cpr)
40 return NULL;
41 call_path__init(&cpr->call_path, NULL, NULL, 0, false);
42 INIT_LIST_HEAD(&cpr->blocks);
43 return cpr;
44}
45
46void call_path_root__free(struct call_path_root *cpr)
47{
48 struct call_path_block *pos, *n;
49
50 list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
51 list_del(&pos->node);
52 free(pos);
53 }
54 free(cpr);
55}
56
57static struct call_path *call_path__new(struct call_path_root *cpr,
58 struct call_path *parent,
59 struct symbol *sym, u64 ip,
60 bool in_kernel)
61{
62 struct call_path_block *cpb;
63 struct call_path *cp;
64 size_t n;
65
66 if (cpr->next < cpr->sz) {
67 cpb = list_last_entry(&cpr->blocks, struct call_path_block,
68 node);
69 } else {
70 cpb = zalloc(sizeof(struct call_path_block));
71 if (!cpb)
72 return NULL;
73 list_add_tail(&cpb->node, &cpr->blocks);
74 cpr->sz += CALL_PATH_BLOCK_SIZE;
75 }
76
77 n = cpr->next++ & CALL_PATH_BLOCK_MASK;
78 cp = &cpb->cp[n];
79
80 call_path__init(cp, parent, sym, ip, in_kernel);
81
82 return cp;
83}
84
85struct call_path *call_path__findnew(struct call_path_root *cpr,
86 struct call_path *parent,
87 struct symbol *sym, u64 ip, u64 ks)
88{
89 struct rb_node **p;
90 struct rb_node *node_parent = NULL;
91 struct call_path *cp;
92 bool in_kernel = ip >= ks;
93
94 if (sym)
95 ip = 0;
96
97 if (!parent)
98 return call_path__new(cpr, parent, sym, ip, in_kernel);
99
100 p = &parent->children.rb_node;
101 while (*p != NULL) {
102 node_parent = *p;
103 cp = rb_entry(node_parent, struct call_path, rb_node);
104
105 if (cp->sym == sym && cp->ip == ip)
106 return cp;
107
108 if (sym < cp->sym || (sym == cp->sym && ip < cp->ip))
109 p = &(*p)->rb_left;
110 else
111 p = &(*p)->rb_right;
112 }
113
114 cp = call_path__new(cpr, parent, sym, ip, in_kernel);
115 if (!cp)
116 return NULL;
117
118 rb_link_node(&cp->rb_node, node_parent, p);
119 rb_insert_color(&cp->rb_node, &parent->children);
120
121 return cp;
122}
diff --git a/tools/perf/util/call-path.h b/tools/perf/util/call-path.h
new file mode 100644
index 000000000000..477f6d03b659
--- /dev/null
+++ b/tools/perf/util/call-path.h
@@ -0,0 +1,77 @@
1/*
2 * call-path.h: Manipulate a tree data structure containing function call paths
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_CALL_PATH_H
17#define __PERF_CALL_PATH_H
18
19#include <sys/types.h>
20
21#include <linux/types.h>
22#include <linux/rbtree.h>
23
24/**
25 * struct call_path - node in list of calls leading to a function call.
26 * @parent: call path to the parent function call
27 * @sym: symbol of function called
28 * @ip: only if sym is null, the ip of the function
29 * @db_id: id used for db-export
30 * @in_kernel: whether function is a in the kernel
31 * @rb_node: node in parent's tree of called functions
32 * @children: tree of call paths of functions called
33 *
34 * In combination with the call_return structure, the call_path structure
35 * defines a context-sensitve call-graph.
36 */
37struct call_path {
38 struct call_path *parent;
39 struct symbol *sym;
40 u64 ip;
41 u64 db_id;
42 bool in_kernel;
43 struct rb_node rb_node;
44 struct rb_root children;
45};
46
47#define CALL_PATH_BLOCK_SHIFT 8
48#define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT)
49#define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1)
50
51struct call_path_block {
52 struct call_path cp[CALL_PATH_BLOCK_SIZE];
53 struct list_head node;
54};
55
56/**
57 * struct call_path_root - root of all call paths.
58 * @call_path: root call path
59 * @blocks: list of blocks to store call paths
60 * @next: next free space
61 * @sz: number of spaces
62 */
63struct call_path_root {
64 struct call_path call_path;
65 struct list_head blocks;
66 size_t next;
67 size_t sz;
68};
69
70struct call_path_root *call_path_root__new(void);
71void call_path_root__free(struct call_path_root *cpr);
72
73struct call_path *call_path__findnew(struct call_path_root *cpr,
74 struct call_path *parent,
75 struct symbol *sym, u64 ip, u64 ks);
76
77#endif
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 24b4bd0d7754..07fd30bc2f81 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -109,6 +109,7 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
109 bool record_opt_set = false; 109 bool record_opt_set = false;
110 bool try_stack_size = false; 110 bool try_stack_size = false;
111 111
112 callchain_param.enabled = true;
112 symbol_conf.use_callchain = true; 113 symbol_conf.use_callchain = true;
113 114
114 if (!arg) 115 if (!arg)
@@ -117,6 +118,7 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
117 while ((tok = strtok((char *)arg, ",")) != NULL) { 118 while ((tok = strtok((char *)arg, ",")) != NULL) {
118 if (!strncmp(tok, "none", strlen(tok))) { 119 if (!strncmp(tok, "none", strlen(tok))) {
119 callchain_param.mode = CHAIN_NONE; 120 callchain_param.mode = CHAIN_NONE;
121 callchain_param.enabled = false;
120 symbol_conf.use_callchain = false; 122 symbol_conf.use_callchain = false;
121 return 0; 123 return 0;
122 } 124 }
@@ -788,7 +790,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
788 return 0; 790 return 0;
789} 791}
790 792
791int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, 793int sample__resolve_callchain(struct perf_sample *sample,
794 struct callchain_cursor *cursor, struct symbol **parent,
792 struct perf_evsel *evsel, struct addr_location *al, 795 struct perf_evsel *evsel, struct addr_location *al,
793 int max_stack) 796 int max_stack)
794{ 797{
@@ -796,8 +799,8 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
796 return 0; 799 return 0;
797 800
798 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || 801 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
799 sort__has_parent) { 802 perf_hpp_list.parent) {
800 return thread__resolve_callchain(al->thread, evsel, sample, 803 return thread__resolve_callchain(al->thread, cursor, evsel, sample,
801 parent, al, max_stack); 804 parent, al, max_stack);
802 } 805 }
803 return 0; 806 return 0;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index d2a9e694810c..65e2a4f7cb4e 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -212,7 +212,14 @@ struct hist_entry;
212int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 212int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
213int record_callchain_opt(const struct option *opt, const char *arg, int unset); 213int record_callchain_opt(const struct option *opt, const char *arg, int unset);
214 214
215int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, 215struct record_opts;
216
217int record_opts__parse_callchain(struct record_opts *record,
218 struct callchain_param *callchain,
219 const char *arg, bool unset);
220
221int sample__resolve_callchain(struct perf_sample *sample,
222 struct callchain_cursor *cursor, struct symbol **parent,
216 struct perf_evsel *evsel, struct addr_location *al, 223 struct perf_evsel *evsel, struct addr_location *al,
217 int max_stack); 224 int max_stack);
218int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample); 225int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 4e727635476e..dad7d8272168 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -13,6 +13,7 @@
13#include <subcmd/exec-cmd.h> 13#include <subcmd/exec-cmd.h>
14#include "util/hist.h" /* perf_hist_config */ 14#include "util/hist.h" /* perf_hist_config */
15#include "util/llvm-utils.h" /* perf_llvm_config */ 15#include "util/llvm-utils.h" /* perf_llvm_config */
16#include "config.h"
16 17
17#define MAXNAME (256) 18#define MAXNAME (256)
18 19
@@ -377,6 +378,21 @@ const char *perf_config_dirname(const char *name, const char *value)
377 return value; 378 return value;
378} 379}
379 380
381static int perf_buildid_config(const char *var, const char *value)
382{
383 /* same dir for all commands */
384 if (!strcmp(var, "buildid.dir")) {
385 const char *dir = perf_config_dirname(var, value);
386
387 if (!dir)
388 return -1;
389 strncpy(buildid_dir, dir, MAXPATHLEN-1);
390 buildid_dir[MAXPATHLEN-1] = '\0';
391 }
392
393 return 0;
394}
395
380static int perf_default_core_config(const char *var __maybe_unused, 396static int perf_default_core_config(const char *var __maybe_unused,
381 const char *value __maybe_unused) 397 const char *value __maybe_unused)
382{ 398{
@@ -412,6 +428,9 @@ int perf_default_config(const char *var, const char *value,
412 if (!prefixcmp(var, "llvm.")) 428 if (!prefixcmp(var, "llvm."))
413 return perf_llvm_config(var, value); 429 return perf_llvm_config(var, value);
414 430
431 if (!prefixcmp(var, "buildid."))
432 return perf_buildid_config(var, value);
433
415 /* Add other config variables here. */ 434 /* Add other config variables here. */
416 return 0; 435 return 0;
417} 436}
@@ -506,41 +525,185 @@ out:
506 return ret; 525 return ret;
507} 526}
508 527
509/* 528static struct perf_config_section *find_section(struct list_head *sections,
510 * Call this to report error for your variable that should not 529 const char *section_name)
511 * get a boolean value (i.e. "[my] var" means "true").
512 */
513int config_error_nonbool(const char *var)
514{ 530{
515 return error("Missing value for '%s'", var); 531 struct perf_config_section *section;
532
533 list_for_each_entry(section, sections, node)
534 if (!strcmp(section->name, section_name))
535 return section;
536
537 return NULL;
538}
539
540static struct perf_config_item *find_config_item(const char *name,
541 struct perf_config_section *section)
542{
543 struct perf_config_item *item;
544
545 list_for_each_entry(item, &section->items, node)
546 if (!strcmp(item->name, name))
547 return item;
548
549 return NULL;
516} 550}
517 551
518struct buildid_dir_config { 552static struct perf_config_section *add_section(struct list_head *sections,
519 char *dir; 553 const char *section_name)
520}; 554{
555 struct perf_config_section *section = zalloc(sizeof(*section));
556
557 if (!section)
558 return NULL;
559
560 INIT_LIST_HEAD(&section->items);
561 section->name = strdup(section_name);
562 if (!section->name) {
563 pr_debug("%s: strdup failed\n", __func__);
564 free(section);
565 return NULL;
566 }
567
568 list_add_tail(&section->node, sections);
569 return section;
570}
521 571
522static int buildid_dir_command_config(const char *var, const char *value, 572static struct perf_config_item *add_config_item(struct perf_config_section *section,
523 void *data) 573 const char *name)
524{ 574{
525 struct buildid_dir_config *c = data; 575 struct perf_config_item *item = zalloc(sizeof(*item));
526 const char *v;
527 576
528 /* same dir for all commands */ 577 if (!item)
529 if (!strcmp(var, "buildid.dir")) { 578 return NULL;
530 v = perf_config_dirname(var, value); 579
531 if (!v) 580 item->name = strdup(name);
532 return -1; 581 if (!item->name) {
533 strncpy(c->dir, v, MAXPATHLEN-1); 582 pr_debug("%s: strdup failed\n", __func__);
534 c->dir[MAXPATHLEN-1] = '\0'; 583 free(item);
584 return NULL;
535 } 585 }
586
587 list_add_tail(&item->node, &section->items);
588 return item;
589}
590
591static int set_value(struct perf_config_item *item, const char *value)
592{
593 char *val = strdup(value);
594
595 if (!val)
596 return -1;
597
598 zfree(&item->value);
599 item->value = val;
536 return 0; 600 return 0;
537} 601}
538 602
539static void check_buildid_dir_config(void) 603static int collect_config(const char *var, const char *value,
604 void *perf_config_set)
540{ 605{
541 struct buildid_dir_config c; 606 int ret = -1;
542 c.dir = buildid_dir; 607 char *ptr, *key;
543 perf_config(buildid_dir_command_config, &c); 608 char *section_name, *name;
609 struct perf_config_section *section = NULL;
610 struct perf_config_item *item = NULL;
611 struct perf_config_set *set = perf_config_set;
612 struct list_head *sections = &set->sections;
613
614 key = ptr = strdup(var);
615 if (!key) {
616 pr_debug("%s: strdup failed\n", __func__);
617 return -1;
618 }
619
620 section_name = strsep(&ptr, ".");
621 name = ptr;
622 if (name == NULL || value == NULL)
623 goto out_free;
624
625 section = find_section(sections, section_name);
626 if (!section) {
627 section = add_section(sections, section_name);
628 if (!section)
629 goto out_free;
630 }
631
632 item = find_config_item(name, section);
633 if (!item) {
634 item = add_config_item(section, name);
635 if (!item)
636 goto out_free;
637 }
638
639 ret = set_value(item, value);
640 return ret;
641
642out_free:
643 free(key);
644 perf_config_set__delete(set);
645 return -1;
646}
647
648struct perf_config_set *perf_config_set__new(void)
649{
650 struct perf_config_set *set = zalloc(sizeof(*set));
651
652 if (set) {
653 INIT_LIST_HEAD(&set->sections);
654 perf_config(collect_config, set);
655 }
656
657 return set;
658}
659
660static void perf_config_item__delete(struct perf_config_item *item)
661{
662 zfree(&item->name);
663 zfree(&item->value);
664 free(item);
665}
666
667static void perf_config_section__purge(struct perf_config_section *section)
668{
669 struct perf_config_item *item, *tmp;
670
671 list_for_each_entry_safe(item, tmp, &section->items, node) {
672 list_del_init(&item->node);
673 perf_config_item__delete(item);
674 }
675}
676
677static void perf_config_section__delete(struct perf_config_section *section)
678{
679 perf_config_section__purge(section);
680 zfree(&section->name);
681 free(section);
682}
683
684static void perf_config_set__purge(struct perf_config_set *set)
685{
686 struct perf_config_section *section, *tmp;
687
688 list_for_each_entry_safe(section, tmp, &set->sections, node) {
689 list_del_init(&section->node);
690 perf_config_section__delete(section);
691 }
692}
693
694void perf_config_set__delete(struct perf_config_set *set)
695{
696 perf_config_set__purge(set);
697 free(set);
698}
699
700/*
701 * Call this to report error for your variable that should not
702 * get a boolean value (i.e. "[my] var" means "true").
703 */
704int config_error_nonbool(const char *var)
705{
706 return error("Missing value for '%s'", var);
544} 707}
545 708
546void set_buildid_dir(const char *dir) 709void set_buildid_dir(const char *dir)
@@ -548,16 +711,13 @@ void set_buildid_dir(const char *dir)
548 if (dir) 711 if (dir)
549 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); 712 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir);
550 713
551 /* try config file */
552 if (buildid_dir[0] == '\0')
553 check_buildid_dir_config();
554
555 /* default to $HOME/.debug */ 714 /* default to $HOME/.debug */
556 if (buildid_dir[0] == '\0') { 715 if (buildid_dir[0] == '\0') {
557 char *v = getenv("HOME"); 716 char *home = getenv("HOME");
558 if (v) { 717
718 if (home) {
559 snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s", 719 snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s",
560 v, DEBUG_CACHE_DIR); 720 home, DEBUG_CACHE_DIR);
561 } else { 721 } else {
562 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); 722 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1);
563 } 723 }
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
new file mode 100644
index 000000000000..22ec626ac718
--- /dev/null
+++ b/tools/perf/util/config.h
@@ -0,0 +1,26 @@
1#ifndef __PERF_CONFIG_H
2#define __PERF_CONFIG_H
3
4#include <stdbool.h>
5#include <linux/list.h>
6
7struct perf_config_item {
8 char *name;
9 char *value;
10 struct list_head node;
11};
12
13struct perf_config_section {
14 char *name;
15 struct list_head items;
16 struct list_head node;
17};
18
19struct perf_config_set {
20 struct list_head sections;
21};
22
23struct perf_config_set *perf_config_set__new(void);
24void perf_config_set__delete(struct perf_config_set *set);
25
26#endif /* __PERF_CONFIG_H */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 9bcf2bed3a6d..02d801670f30 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -587,3 +587,15 @@ int cpu__setup_cpunode_map(void)
587 closedir(dir1); 587 closedir(dir1);
588 return 0; 588 return 0;
589} 589}
590
591bool cpu_map__has(struct cpu_map *cpus, int cpu)
592{
593 int i;
594
595 for (i = 0; i < cpus->nr; ++i) {
596 if (cpus->map[i] == cpu)
597 return true;
598 }
599
600 return false;
601}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 81a2562aaa2b..1a0a35073ce1 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -66,4 +66,6 @@ int cpu__get_node(int cpu);
66int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, 66int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
67 int (*f)(struct cpu_map *map, int cpu, void *data), 67 int (*f)(struct cpu_map *map, int cpu, void *data),
68 void *data); 68 void *data);
69
70bool cpu_map__has(struct cpu_map *cpus, int cpu);
69#endif /* __PERF_CPUMAP_H */ 71#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 1921942fc2e0..be83516155ee 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -136,3 +136,44 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
136{ 136{
137 return writen(file->fd, buf, size); 137 return writen(file->fd, buf, size);
138} 138}
139
140int perf_data_file__switch(struct perf_data_file *file,
141 const char *postfix,
142 size_t pos, bool at_exit)
143{
144 char *new_filepath;
145 int ret;
146
147 if (check_pipe(file))
148 return -EINVAL;
149 if (perf_data_file__is_read(file))
150 return -EINVAL;
151
152 if (asprintf(&new_filepath, "%s.%s", file->path, postfix) < 0)
153 return -ENOMEM;
154
155 /*
156 * Only fire a warning, don't return error, continue fill
157 * original file.
158 */
159 if (rename(file->path, new_filepath))
160 pr_warning("Failed to rename %s to %s\n", file->path, new_filepath);
161
162 if (!at_exit) {
163 close(file->fd);
164 ret = perf_data_file__open(file);
165 if (ret < 0)
166 goto out;
167
168 if (lseek(file->fd, pos, SEEK_SET) == (off_t)-1) {
169 ret = -errno;
170 pr_debug("Failed to lseek to %zu: %s",
171 pos, strerror(errno));
172 goto out;
173 }
174 }
175 ret = file->fd;
176out:
177 free(new_filepath);
178 return ret;
179}
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 2b15d0c95c7f..ae510ce16cb1 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -46,5 +46,14 @@ int perf_data_file__open(struct perf_data_file *file);
46void perf_data_file__close(struct perf_data_file *file); 46void perf_data_file__close(struct perf_data_file *file);
47ssize_t perf_data_file__write(struct perf_data_file *file, 47ssize_t perf_data_file__write(struct perf_data_file *file,
48 void *buf, size_t size); 48 void *buf, size_t size);
49 49/*
50 * If at_exit is set, only rename current perf.data to
51 * perf.data.<postfix>, continue write on original file.
52 * Set at_exit when flushing the last output.
53 *
54 * Return value is fd of new output.
55 */
56int perf_data_file__switch(struct perf_data_file *file,
57 const char *postfix,
58 size_t pos, bool at_exit);
50#endif /* __PERF_DATA_H */ 59#endif /* __PERF_DATA_H */
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index 049438d51b9a..8d96c80cc67e 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -23,6 +23,8 @@
23#include "event.h" 23#include "event.h"
24#include "util.h" 24#include "util.h"
25#include "thread-stack.h" 25#include "thread-stack.h"
26#include "callchain.h"
27#include "call-path.h"
26#include "db-export.h" 28#include "db-export.h"
27 29
28struct deferred_export { 30struct deferred_export {
@@ -258,8 +260,7 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
258 if (!al->sym) { 260 if (!al->sym) {
259 al->sym = symbol__new(al->addr, 0, 0, "unknown"); 261 al->sym = symbol__new(al->addr, 0, 0, "unknown");
260 if (al->sym) 262 if (al->sym)
261 symbols__insert(&dso->symbols[al->map->type], 263 dso__insert_symbol(dso, al->map->type, al->sym);
262 al->sym);
263 } 264 }
264 265
265 if (al->sym) { 266 if (al->sym) {
@@ -276,6 +277,80 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
276 return 0; 277 return 0;
277} 278}
278 279
280static struct call_path *call_path_from_sample(struct db_export *dbe,
281 struct machine *machine,
282 struct thread *thread,
283 struct perf_sample *sample,
284 struct perf_evsel *evsel)
285{
286 u64 kernel_start = machine__kernel_start(machine);
287 struct call_path *current = &dbe->cpr->call_path;
288 enum chain_order saved_order = callchain_param.order;
289 int err;
290
291 if (!symbol_conf.use_callchain || !sample->callchain)
292 return NULL;
293
294 /*
295 * Since the call path tree must be built starting with the root, we
296 * must use ORDER_CALL for call chain resolution, in order to process
297 * the callchain starting with the root node and ending with the leaf.
298 */
299 callchain_param.order = ORDER_CALLER;
300 err = thread__resolve_callchain(thread, &callchain_cursor, evsel,
301 sample, NULL, NULL,
302 sysctl_perf_event_max_stack);
303 if (err) {
304 callchain_param.order = saved_order;
305 return NULL;
306 }
307 callchain_cursor_commit(&callchain_cursor);
308
309 while (1) {
310 struct callchain_cursor_node *node;
311 struct addr_location al;
312 u64 dso_db_id = 0, sym_db_id = 0, offset = 0;
313
314 memset(&al, 0, sizeof(al));
315
316 node = callchain_cursor_current(&callchain_cursor);
317 if (!node)
318 break;
319 /*
320 * Handle export of symbol and dso for this node by
321 * constructing an addr_location struct and then passing it to
322 * db_ids_from_al() to perform the export.
323 */
324 al.sym = node->sym;
325 al.map = node->map;
326 al.machine = machine;
327 al.addr = node->ip;
328
329 if (al.map && !al.sym)
330 al.sym = dso__find_symbol(al.map->dso, MAP__FUNCTION,
331 al.addr);
332
333 db_ids_from_al(dbe, &al, &dso_db_id, &sym_db_id, &offset);
334
335 /* add node to the call path tree if it doesn't exist */
336 current = call_path__findnew(dbe->cpr, current,
337 al.sym, node->ip,
338 kernel_start);
339
340 callchain_cursor_advance(&callchain_cursor);
341 }
342
343 /* Reset the callchain order to its prior value. */
344 callchain_param.order = saved_order;
345
346 if (current == &dbe->cpr->call_path) {
347 /* Bail because the callchain was empty. */
348 return NULL;
349 }
350
351 return current;
352}
353
279int db_export__branch_type(struct db_export *dbe, u32 branch_type, 354int db_export__branch_type(struct db_export *dbe, u32 branch_type,
280 const char *name) 355 const char *name)
281{ 356{
@@ -329,6 +404,16 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
329 if (err) 404 if (err)
330 goto out_put; 405 goto out_put;
331 406
407 if (dbe->cpr) {
408 struct call_path *cp = call_path_from_sample(dbe, al->machine,
409 thread, sample,
410 evsel);
411 if (cp) {
412 db_export__call_path(dbe, cp);
413 es.call_path_id = cp->db_id;
414 }
415 }
416
332 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 417 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
333 sample_addr_correlates_sym(&evsel->attr)) { 418 sample_addr_correlates_sym(&evsel->attr)) {
334 struct addr_location addr_al; 419 struct addr_location addr_al;
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
index 25e22fd76aca..67bc6b8ad2d6 100644
--- a/tools/perf/util/db-export.h
+++ b/tools/perf/util/db-export.h
@@ -27,6 +27,7 @@ struct dso;
27struct perf_sample; 27struct perf_sample;
28struct addr_location; 28struct addr_location;
29struct call_return_processor; 29struct call_return_processor;
30struct call_path_root;
30struct call_path; 31struct call_path;
31struct call_return; 32struct call_return;
32 33
@@ -43,6 +44,7 @@ struct export_sample {
43 u64 addr_dso_db_id; 44 u64 addr_dso_db_id;
44 u64 addr_sym_db_id; 45 u64 addr_sym_db_id;
45 u64 addr_offset; /* addr offset from symbol start */ 46 u64 addr_offset; /* addr offset from symbol start */
47 u64 call_path_id;
46}; 48};
47 49
48struct db_export { 50struct db_export {
@@ -64,6 +66,7 @@ struct db_export {
64 int (*export_call_return)(struct db_export *dbe, 66 int (*export_call_return)(struct db_export *dbe,
65 struct call_return *cr); 67 struct call_return *cr);
66 struct call_return_processor *crp; 68 struct call_return_processor *crp;
69 struct call_path_root *cpr;
67 u64 evsel_last_db_id; 70 u64 evsel_last_db_id;
68 u64 machine_last_db_id; 71 u64 machine_last_db_id;
69 u64 thread_last_db_id; 72 u64 thread_last_db_id;
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 8e6395439ca0..3357479082ca 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -38,7 +38,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
38 enum dso_binary_type type, 38 enum dso_binary_type type,
39 char *root_dir, char *filename, size_t size) 39 char *root_dir, char *filename, size_t size)
40{ 40{
41 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 41 char build_id_hex[SBUILD_ID_SIZE];
42 int ret = 0; 42 int ret = 0;
43 size_t len; 43 size_t len;
44 44
@@ -1301,7 +1301,7 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp)
1301 1301
1302size_t dso__fprintf_buildid(struct dso *dso, FILE *fp) 1302size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
1303{ 1303{
1304 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1304 char sbuild_id[SBUILD_ID_SIZE];
1305 1305
1306 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 1306 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1307 return fprintf(fp, "%s", sbuild_id); 1307 return fprintf(fp, "%s", sbuild_id);
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index 577e600c8eb1..a347b19c961a 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -915,8 +915,7 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
915 tmp = "*"; 915 tmp = "*";
916 else if (tag == DW_TAG_subroutine_type) { 916 else if (tag == DW_TAG_subroutine_type) {
917 /* Function pointer */ 917 /* Function pointer */
918 strbuf_add(buf, "(function_type)", 15); 918 return strbuf_add(buf, "(function_type)", 15);
919 return 0;
920 } else { 919 } else {
921 if (!dwarf_diename(&type)) 920 if (!dwarf_diename(&type))
922 return -ENOENT; 921 return -ENOENT;
@@ -927,14 +926,10 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
927 else if (tag == DW_TAG_enumeration_type) 926 else if (tag == DW_TAG_enumeration_type)
928 tmp = "enum "; 927 tmp = "enum ";
929 /* Write a base name */ 928 /* Write a base name */
930 strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type)); 929 return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
931 return 0;
932 } 930 }
933 ret = die_get_typename(&type, buf); 931 ret = die_get_typename(&type, buf);
934 if (ret == 0) 932 return ret ? ret : strbuf_addstr(buf, tmp);
935 strbuf_addstr(buf, tmp);
936
937 return ret;
938} 933}
939 934
940/** 935/**
@@ -951,14 +946,13 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
951 ret = die_get_typename(vr_die, buf); 946 ret = die_get_typename(vr_die, buf);
952 if (ret < 0) { 947 if (ret < 0) {
953 pr_debug("Failed to get type, make it unknown.\n"); 948 pr_debug("Failed to get type, make it unknown.\n");
954 strbuf_add(buf, " (unknown_type)", 14); 949 ret = strbuf_add(buf, " (unknown_type)", 14);
955 } 950 }
956 951
957 strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); 952 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
958
959 return 0;
960} 953}
961 954
955#ifdef HAVE_DWARF_GETLOCATIONS
962/** 956/**
963 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE 957 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
964 * @sp_die: a subprogram DIE 958 * @sp_die: a subprogram DIE
@@ -998,22 +992,24 @@ static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
998 } 992 }
999 993
1000 while ((offset = dwarf_ranges(&scopes[1], offset, &base, 994 while ((offset = dwarf_ranges(&scopes[1], offset, &base,
1001 &start, &end)) > 0) { 995 &start, &end)) > 0) {
1002 start -= entry; 996 start -= entry;
1003 end -= entry; 997 end -= entry;
1004 998
1005 if (first) { 999 if (first) {
1006 strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, 1000 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1007 name, start, end); 1001 name, start, end);
1008 first = false; 1002 first = false;
1009 } else { 1003 } else {
1010 strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, 1004 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1011 start, end); 1005 start, end);
1012 } 1006 }
1007 if (ret < 0)
1008 goto out;
1013 } 1009 }
1014 1010
1015 if (!first) 1011 if (!first)
1016 strbuf_add(buf, "]>", 2); 1012 ret = strbuf_add(buf, "]>", 2);
1017 1013
1018out: 1014out:
1019 free(scopes); 1015 free(scopes);
@@ -1053,30 +1049,39 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
1053 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) 1049 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
1054 return -EINVAL; 1050 return -EINVAL;
1055 1051
1056 while ((offset = dwarf_getlocations( 1052 while ((offset = dwarf_getlocations(&attr, offset, &base,
1057 &attr, offset, &base, 1053 &start, &end, &op, &nops)) > 0) {
1058 &start, &end, &op, &nops)) > 0) {
1059 if (start == 0) { 1054 if (start == 0) {
1060 /* Single Location Descriptions */ 1055 /* Single Location Descriptions */
1061 ret = die_get_var_innermost_scope(sp_die, vr_die, buf); 1056 ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
1062 return ret; 1057 goto out;
1063 } 1058 }
1064 1059
1065 /* Location Lists */ 1060 /* Location Lists */
1066 start -= entry; 1061 start -= entry;
1067 end -= entry; 1062 end -= entry;
1068 if (first) { 1063 if (first) {
1069 strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, 1064 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1070 name, start, end); 1065 name, start, end);
1071 first = false; 1066 first = false;
1072 } else { 1067 } else {
1073 strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, 1068 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1074 start, end); 1069 start, end);
1075 } 1070 }
1071 if (ret < 0)
1072 goto out;
1076 } 1073 }
1077 1074
1078 if (!first) 1075 if (!first)
1079 strbuf_add(buf, "]>", 2); 1076 ret = strbuf_add(buf, "]>", 2);
1080 1077out:
1081 return ret; 1078 return ret;
1082} 1079}
1080#else
1081int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
1082 Dwarf_Die *vr_die __maybe_unused,
1083 struct strbuf *buf __maybe_unused)
1084{
1085 return -ENOTSUP;
1086}
1087#endif
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index dad55d04ffdd..f6fcc6832949 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -45,6 +45,7 @@ static const char *perf_event__names[] = {
45 [PERF_RECORD_STAT] = "STAT", 45 [PERF_RECORD_STAT] = "STAT",
46 [PERF_RECORD_STAT_ROUND] = "STAT_ROUND", 46 [PERF_RECORD_STAT_ROUND] = "STAT_ROUND",
47 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE", 47 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE",
48 [PERF_RECORD_TIME_CONV] = "TIME_CONV",
48}; 49};
49 50
50const char *perf_event__name(unsigned int id) 51const char *perf_event__name(unsigned int id)
@@ -433,7 +434,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
433{ 434{
434 char filename[PATH_MAX]; 435 char filename[PATH_MAX];
435 DIR *tasks; 436 DIR *tasks;
436 struct dirent dirent, *next; 437 struct dirent *dirent;
437 pid_t tgid, ppid; 438 pid_t tgid, ppid;
438 int rc = 0; 439 int rc = 0;
439 440
@@ -462,11 +463,11 @@ static int __event__synthesize_thread(union perf_event *comm_event,
462 return 0; 463 return 0;
463 } 464 }
464 465
465 while (!readdir_r(tasks, &dirent, &next) && next) { 466 while ((dirent = readdir(tasks)) != NULL) {
466 char *end; 467 char *end;
467 pid_t _pid; 468 pid_t _pid;
468 469
469 _pid = strtol(dirent.d_name, &end, 10); 470 _pid = strtol(dirent->d_name, &end, 10);
470 if (*end) 471 if (*end)
471 continue; 472 continue;
472 473
@@ -575,7 +576,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
575{ 576{
576 DIR *proc; 577 DIR *proc;
577 char proc_path[PATH_MAX]; 578 char proc_path[PATH_MAX];
578 struct dirent dirent, *next; 579 struct dirent *dirent;
579 union perf_event *comm_event, *mmap_event, *fork_event; 580 union perf_event *comm_event, *mmap_event, *fork_event;
580 int err = -1; 581 int err = -1;
581 582
@@ -600,9 +601,9 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
600 if (proc == NULL) 601 if (proc == NULL)
601 goto out_free_fork; 602 goto out_free_fork;
602 603
603 while (!readdir_r(proc, &dirent, &next) && next) { 604 while ((dirent = readdir(proc)) != NULL) {
604 char *end; 605 char *end;
605 pid_t pid = strtol(dirent.d_name, &end, 10); 606 pid_t pid = strtol(dirent->d_name, &end, 10);
606 607
607 if (*end) /* only interested in proper numerical dirents */ 608 if (*end) /* only interested in proper numerical dirents */
608 continue; 609 continue;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 6bb1c928350d..8d363d5e65a2 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -233,6 +233,7 @@ enum perf_user_event_type { /* above any possible kernel type */
233 PERF_RECORD_STAT = 76, 233 PERF_RECORD_STAT = 76,
234 PERF_RECORD_STAT_ROUND = 77, 234 PERF_RECORD_STAT_ROUND = 77,
235 PERF_RECORD_EVENT_UPDATE = 78, 235 PERF_RECORD_EVENT_UPDATE = 78,
236 PERF_RECORD_TIME_CONV = 79,
236 PERF_RECORD_HEADER_MAX 237 PERF_RECORD_HEADER_MAX
237}; 238};
238 239
@@ -469,6 +470,13 @@ struct stat_round_event {
469 u64 time; 470 u64 time;
470}; 471};
471 472
473struct time_conv_event {
474 struct perf_event_header header;
475 u64 time_shift;
476 u64 time_mult;
477 u64 time_zero;
478};
479
472union perf_event { 480union perf_event {
473 struct perf_event_header header; 481 struct perf_event_header header;
474 struct mmap_event mmap; 482 struct mmap_event mmap;
@@ -497,6 +505,7 @@ union perf_event {
497 struct stat_config_event stat_config; 505 struct stat_config_event stat_config;
498 struct stat_event stat; 506 struct stat_event stat;
499 struct stat_round_event stat_round; 507 struct stat_round_event stat_round;
508 struct time_conv_event time_conv;
500}; 509};
501 510
502void perf_event__print_totals(void); 511void perf_event__print_totals(void);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 86a03836a83f..c4bfe11479a0 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -679,53 +679,52 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
679 return NULL; 679 return NULL;
680} 680}
681 681
682union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 682/* When check_messup is true, 'end' must points to a good entry */
683static union perf_event *
684perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
685 u64 end, u64 *prev)
683{ 686{
684 struct perf_mmap *md = &evlist->mmap[idx];
685 u64 head;
686 u64 old = md->prev;
687 unsigned char *data = md->base + page_size; 687 unsigned char *data = md->base + page_size;
688 union perf_event *event = NULL; 688 union perf_event *event = NULL;
689 int diff = end - start;
689 690
690 /* 691 if (check_messup) {
691 * Check if event was unmapped due to a POLLHUP/POLLERR.
692 */
693 if (!atomic_read(&md->refcnt))
694 return NULL;
695
696 head = perf_mmap__read_head(md);
697 if (evlist->overwrite) {
698 /* 692 /*
699 * If we're further behind than half the buffer, there's a chance 693 * If we're further behind than half the buffer, there's a chance
700 * the writer will bite our tail and mess up the samples under us. 694 * the writer will bite our tail and mess up the samples under us.
701 * 695 *
702 * If we somehow ended up ahead of the head, we got messed up. 696 * If we somehow ended up ahead of the 'end', we got messed up.
703 * 697 *
704 * In either case, truncate and restart at head. 698 * In either case, truncate and restart at 'end'.
705 */ 699 */
706 int diff = head - old;
707 if (diff > md->mask / 2 || diff < 0) { 700 if (diff > md->mask / 2 || diff < 0) {
708 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); 701 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
709 702
710 /* 703 /*
711 * head points to a known good entry, start there. 704 * 'end' points to a known good entry, start there.
712 */ 705 */
713 old = head; 706 start = end;
707 diff = 0;
714 } 708 }
715 } 709 }
716 710
717 if (old != head) { 711 if (diff >= (int)sizeof(event->header)) {
718 size_t size; 712 size_t size;
719 713
720 event = (union perf_event *)&data[old & md->mask]; 714 event = (union perf_event *)&data[start & md->mask];
721 size = event->header.size; 715 size = event->header.size;
722 716
717 if (size < sizeof(event->header) || diff < (int)size) {
718 event = NULL;
719 goto broken_event;
720 }
721
723 /* 722 /*
724 * Event straddles the mmap boundary -- header should always 723 * Event straddles the mmap boundary -- header should always
725 * be inside due to u64 alignment of output. 724 * be inside due to u64 alignment of output.
726 */ 725 */
727 if ((old & md->mask) + size != ((old + size) & md->mask)) { 726 if ((start & md->mask) + size != ((start + size) & md->mask)) {
728 unsigned int offset = old; 727 unsigned int offset = start;
729 unsigned int len = min(sizeof(*event), size), cpy; 728 unsigned int len = min(sizeof(*event), size), cpy;
730 void *dst = md->event_copy; 729 void *dst = md->event_copy;
731 730
@@ -740,14 +739,83 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
740 event = (union perf_event *) md->event_copy; 739 event = (union perf_event *) md->event_copy;
741 } 740 }
742 741
743 old += size; 742 start += size;
744 } 743 }
745 744
746 md->prev = old; 745broken_event:
746 if (prev)
747 *prev = start;
747 748
748 return event; 749 return event;
749} 750}
750 751
752union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
753{
754 struct perf_mmap *md = &evlist->mmap[idx];
755 u64 head;
756 u64 old = md->prev;
757
758 /*
759 * Check if event was unmapped due to a POLLHUP/POLLERR.
760 */
761 if (!atomic_read(&md->refcnt))
762 return NULL;
763
764 head = perf_mmap__read_head(md);
765
766 return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev);
767}
768
769union perf_event *
770perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
771{
772 struct perf_mmap *md = &evlist->mmap[idx];
773 u64 head, end;
774 u64 start = md->prev;
775
776 /*
777 * Check if event was unmapped due to a POLLHUP/POLLERR.
778 */
779 if (!atomic_read(&md->refcnt))
780 return NULL;
781
782 head = perf_mmap__read_head(md);
783 if (!head)
784 return NULL;
785
786 /*
787 * 'head' pointer starts from 0. Kernel minus sizeof(record) form
788 * it each time when kernel writes to it, so in fact 'head' is
789 * negative. 'end' pointer is made manually by adding the size of
790 * the ring buffer to 'head' pointer, means the validate data can
791 * read is the whole ring buffer. If 'end' is positive, the ring
792 * buffer has not fully filled, so we must adjust 'end' to 0.
793 *
794 * However, since both 'head' and 'end' is unsigned, we can't
795 * simply compare 'end' against 0. Here we compare '-head' and
796 * the size of the ring buffer, where -head is the number of bytes
797 * kernel write to the ring buffer.
798 */
799 if (-head < (u64)(md->mask + 1))
800 end = 0;
801 else
802 end = head + md->mask + 1;
803
804 return perf_mmap__read(md, false, start, end, &md->prev);
805}
806
807void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
808{
809 struct perf_mmap *md = &evlist->mmap[idx];
810 u64 head;
811
812 if (!atomic_read(&md->refcnt))
813 return;
814
815 head = perf_mmap__read_head(md);
816 md->prev = head;
817}
818
751static bool perf_mmap__empty(struct perf_mmap *md) 819static bool perf_mmap__empty(struct perf_mmap *md)
752{ 820{
753 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; 821 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
@@ -986,26 +1054,34 @@ out_unmap:
986 return -1; 1054 return -1;
987} 1055}
988 1056
989static size_t perf_evlist__mmap_size(unsigned long pages) 1057unsigned long perf_event_mlock_kb_in_pages(void)
990{ 1058{
991 if (pages == UINT_MAX) { 1059 unsigned long pages;
992 int max; 1060 int max;
993 1061
994 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) { 1062 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
995 /* 1063 /*
996 * Pick a once upon a time good value, i.e. things look 1064 * Pick a once upon a time good value, i.e. things look
997 * strange since we can't read a sysctl value, but lets not 1065 * strange since we can't read a sysctl value, but lets not
998 * die yet... 1066 * die yet...
999 */ 1067 */
1000 max = 512; 1068 max = 512;
1001 } else { 1069 } else {
1002 max -= (page_size / 1024); 1070 max -= (page_size / 1024);
1003 } 1071 }
1004 1072
1005 pages = (max * 1024) / page_size; 1073 pages = (max * 1024) / page_size;
1006 if (!is_power_of_2(pages)) 1074 if (!is_power_of_2(pages))
1007 pages = rounddown_pow_of_two(pages); 1075 pages = rounddown_pow_of_two(pages);
1008 } else if (!is_power_of_2(pages)) 1076
1077 return pages;
1078}
1079
1080static size_t perf_evlist__mmap_size(unsigned long pages)
1081{
1082 if (pages == UINT_MAX)
1083 pages = perf_event_mlock_kb_in_pages();
1084 else if (!is_power_of_2(pages))
1009 return 0; 1085 return 0;
1010 1086
1011 return (pages + 1) * page_size; 1087 return (pages + 1) * page_size;
@@ -1192,6 +1268,24 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
1192 perf_evlist__propagate_maps(evlist); 1268 perf_evlist__propagate_maps(evlist);
1193} 1269}
1194 1270
1271void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
1272 enum perf_event_sample_format bit)
1273{
1274 struct perf_evsel *evsel;
1275
1276 evlist__for_each(evlist, evsel)
1277 __perf_evsel__set_sample_bit(evsel, bit);
1278}
1279
1280void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
1281 enum perf_event_sample_format bit)
1282{
1283 struct perf_evsel *evsel;
1284
1285 evlist__for_each(evlist, evsel)
1286 __perf_evsel__reset_sample_bit(evsel, bit);
1287}
1288
1195int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel) 1289int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
1196{ 1290{
1197 struct perf_evsel *evsel; 1291 struct perf_evsel *evsel;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a0d15221db6e..85d1b59802e8 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -87,6 +87,17 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist);
87int perf_evlist__add_newtp(struct perf_evlist *evlist, 87int perf_evlist__add_newtp(struct perf_evlist *evlist,
88 const char *sys, const char *name, void *handler); 88 const char *sys, const char *name, void *handler);
89 89
90void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
91 enum perf_event_sample_format bit);
92void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
93 enum perf_event_sample_format bit);
94
95#define perf_evlist__set_sample_bit(evlist, bit) \
96 __perf_evlist__set_sample_bit(evlist, PERF_SAMPLE_##bit)
97
98#define perf_evlist__reset_sample_bit(evlist, bit) \
99 __perf_evlist__reset_sample_bit(evlist, PERF_SAMPLE_##bit)
100
90int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); 101int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
91int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid); 102int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid);
92int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids); 103int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);
@@ -118,16 +129,23 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
118 129
119union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); 130union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
120 131
132union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
133 int idx);
134void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
135
121void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 136void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
122 137
123int perf_evlist__open(struct perf_evlist *evlist); 138int perf_evlist__open(struct perf_evlist *evlist);
124void perf_evlist__close(struct perf_evlist *evlist); 139void perf_evlist__close(struct perf_evlist *evlist);
125 140
141struct callchain_param;
142
126void perf_evlist__set_id_pos(struct perf_evlist *evlist); 143void perf_evlist__set_id_pos(struct perf_evlist *evlist);
127bool perf_can_sample_identifier(void); 144bool perf_can_sample_identifier(void);
128bool perf_can_record_switch_events(void); 145bool perf_can_record_switch_events(void);
129bool perf_can_record_cpu_wide(void); 146bool perf_can_record_cpu_wide(void);
130void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts); 147void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
148 struct callchain_param *callchain);
131int record_opts__config(struct record_opts *opts); 149int record_opts__config(struct record_opts *opts);
132 150
133int perf_evlist__prepare_workload(struct perf_evlist *evlist, 151int perf_evlist__prepare_workload(struct perf_evlist *evlist,
@@ -144,6 +162,8 @@ int perf_evlist__parse_mmap_pages(const struct option *opt,
144 const char *str, 162 const char *str,
145 int unset); 163 int unset);
146 164
165unsigned long perf_event_mlock_kb_in_pages(void);
166
147int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, 167int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
148 bool overwrite, unsigned int auxtrace_pages, 168 bool overwrite, unsigned int auxtrace_pages,
149 bool auxtrace_overwrite); 169 bool auxtrace_overwrite);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 738ce226002b..52c7d8884741 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -226,7 +226,8 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
226 perf_evsel__init(evsel, attr, idx); 226 perf_evsel__init(evsel, attr, idx);
227 227
228 if (perf_evsel__is_bpf_output(evsel)) { 228 if (perf_evsel__is_bpf_output(evsel)) {
229 evsel->attr.sample_type |= PERF_SAMPLE_RAW; 229 evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
230 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
230 evsel->attr.sample_period = 1; 231 evsel->attr.sample_period = 1;
231 } 232 }
232 233
@@ -561,10 +562,9 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
561 return ret; 562 return ret;
562} 563}
563 564
564static void 565void perf_evsel__config_callchain(struct perf_evsel *evsel,
565perf_evsel__config_callgraph(struct perf_evsel *evsel, 566 struct record_opts *opts,
566 struct record_opts *opts, 567 struct callchain_param *param)
567 struct callchain_param *param)
568{ 568{
569 bool function = perf_evsel__is_function_event(evsel); 569 bool function = perf_evsel__is_function_event(evsel);
570 struct perf_event_attr *attr = &evsel->attr; 570 struct perf_event_attr *attr = &evsel->attr;
@@ -704,7 +704,7 @@ static void apply_config_terms(struct perf_evsel *evsel,
704 704
705 /* set perf-event callgraph */ 705 /* set perf-event callgraph */
706 if (param.enabled) 706 if (param.enabled)
707 perf_evsel__config_callgraph(evsel, opts, &param); 707 perf_evsel__config_callchain(evsel, opts, &param);
708 } 708 }
709} 709}
710 710
@@ -736,7 +736,8 @@ static void apply_config_terms(struct perf_evsel *evsel,
736 * enable/disable events specifically, as there's no 736 * enable/disable events specifically, as there's no
737 * initial traced exec call. 737 * initial traced exec call.
738 */ 738 */
739void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) 739void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
740 struct callchain_param *callchain)
740{ 741{
741 struct perf_evsel *leader = evsel->leader; 742 struct perf_evsel *leader = evsel->leader;
742 struct perf_event_attr *attr = &evsel->attr; 743 struct perf_event_attr *attr = &evsel->attr;
@@ -811,8 +812,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
811 if (perf_evsel__is_function_event(evsel)) 812 if (perf_evsel__is_function_event(evsel))
812 evsel->attr.exclude_callchain_user = 1; 813 evsel->attr.exclude_callchain_user = 1;
813 814
814 if (callchain_param.enabled && !evsel->no_aux_samples) 815 if (callchain && callchain->enabled && !evsel->no_aux_samples)
815 perf_evsel__config_callgraph(evsel, opts, &callchain_param); 816 perf_evsel__config_callchain(evsel, opts, callchain);
816 817
817 if (opts->sample_intr_regs) { 818 if (opts->sample_intr_regs) {
818 attr->sample_regs_intr = opts->sample_intr_regs; 819 attr->sample_regs_intr = opts->sample_intr_regs;
@@ -826,7 +827,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
826 perf_evsel__set_sample_bit(evsel, PERIOD); 827 perf_evsel__set_sample_bit(evsel, PERIOD);
827 828
828 /* 829 /*
829 * When the user explicitely disabled time don't force it here. 830 * When the user explicitly disabled time don't force it here.
830 */ 831 */
831 if (opts->sample_time && 832 if (opts->sample_time &&
832 (!perf_missing_features.sample_id_all && 833 (!perf_missing_features.sample_id_all &&
@@ -1230,6 +1231,21 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1230 __p_bits(buf, size, value, bits); 1231 __p_bits(buf, size, value, bits);
1231} 1232}
1232 1233
1234static void __p_branch_sample_type(char *buf, size_t size, u64 value)
1235{
1236#define bit_name(n) { PERF_SAMPLE_BRANCH_##n, #n }
1237 struct bit_names bits[] = {
1238 bit_name(USER), bit_name(KERNEL), bit_name(HV), bit_name(ANY),
1239 bit_name(ANY_CALL), bit_name(ANY_RETURN), bit_name(IND_CALL),
1240 bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX),
1241 bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP),
1242 bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES),
1243 { .name = NULL, }
1244 };
1245#undef bit_name
1246 __p_bits(buf, size, value, bits);
1247}
1248
1233static void __p_read_format(char *buf, size_t size, u64 value) 1249static void __p_read_format(char *buf, size_t size, u64 value)
1234{ 1250{
1235#define bit_name(n) { PERF_FORMAT_##n, #n } 1251#define bit_name(n) { PERF_FORMAT_##n, #n }
@@ -1248,6 +1264,7 @@ static void __p_read_format(char *buf, size_t size, u64 value)
1248#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val)) 1264#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))
1249#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val)) 1265#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))
1250#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val) 1266#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)
1267#define p_branch_sample_type(val) __p_branch_sample_type(buf, BUF_SIZE, val)
1251#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val) 1268#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val)
1252 1269
1253#define PRINT_ATTRn(_n, _f, _p) \ 1270#define PRINT_ATTRn(_n, _f, _p) \
@@ -1299,12 +1316,13 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1299 PRINT_ATTRf(comm_exec, p_unsigned); 1316 PRINT_ATTRf(comm_exec, p_unsigned);
1300 PRINT_ATTRf(use_clockid, p_unsigned); 1317 PRINT_ATTRf(use_clockid, p_unsigned);
1301 PRINT_ATTRf(context_switch, p_unsigned); 1318 PRINT_ATTRf(context_switch, p_unsigned);
1319 PRINT_ATTRf(write_backward, p_unsigned);
1302 1320
1303 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); 1321 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
1304 PRINT_ATTRf(bp_type, p_unsigned); 1322 PRINT_ATTRf(bp_type, p_unsigned);
1305 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); 1323 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
1306 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); 1324 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
1307 PRINT_ATTRf(branch_sample_type, p_unsigned); 1325 PRINT_ATTRf(branch_sample_type, p_branch_sample_type);
1308 PRINT_ATTRf(sample_regs_user, p_hex); 1326 PRINT_ATTRf(sample_regs_user, p_hex);
1309 PRINT_ATTRf(sample_stack_user, p_unsigned); 1327 PRINT_ATTRf(sample_stack_user, p_unsigned);
1310 PRINT_ATTRf(clockid, p_signed); 1328 PRINT_ATTRf(clockid, p_signed);
@@ -2253,98 +2271,11 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2253 return 0; 2271 return 0;
2254} 2272}
2255 2273
2256static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
2257{
2258 va_list args;
2259 int ret = 0;
2260
2261 if (!*first) {
2262 ret += fprintf(fp, ",");
2263 } else {
2264 ret += fprintf(fp, ":");
2265 *first = false;
2266 }
2267
2268 va_start(args, fmt);
2269 ret += vfprintf(fp, fmt, args);
2270 va_end(args);
2271 return ret;
2272}
2273
2274static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
2275{
2276 return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
2277}
2278
2279int perf_evsel__fprintf(struct perf_evsel *evsel,
2280 struct perf_attr_details *details, FILE *fp)
2281{
2282 bool first = true;
2283 int printed = 0;
2284
2285 if (details->event_group) {
2286 struct perf_evsel *pos;
2287
2288 if (!perf_evsel__is_group_leader(evsel))
2289 return 0;
2290
2291 if (evsel->nr_members > 1)
2292 printed += fprintf(fp, "%s{", evsel->group_name ?: "");
2293
2294 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
2295 for_each_group_member(pos, evsel)
2296 printed += fprintf(fp, ",%s", perf_evsel__name(pos));
2297
2298 if (evsel->nr_members > 1)
2299 printed += fprintf(fp, "}");
2300 goto out;
2301 }
2302
2303 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
2304
2305 if (details->verbose) {
2306 printed += perf_event_attr__fprintf(fp, &evsel->attr,
2307 __print_attr__fprintf, &first);
2308 } else if (details->freq) {
2309 const char *term = "sample_freq";
2310
2311 if (!evsel->attr.freq)
2312 term = "sample_period";
2313
2314 printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
2315 term, (u64)evsel->attr.sample_freq);
2316 }
2317
2318 if (details->trace_fields) {
2319 struct format_field *field;
2320
2321 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2322 printed += comma_fprintf(fp, &first, " (not a tracepoint)");
2323 goto out;
2324 }
2325
2326 field = evsel->tp_format->format.fields;
2327 if (field == NULL) {
2328 printed += comma_fprintf(fp, &first, " (no trace field)");
2329 goto out;
2330 }
2331
2332 printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
2333
2334 field = field->next;
2335 while (field) {
2336 printed += comma_fprintf(fp, &first, "%s", field->name);
2337 field = field->next;
2338 }
2339 }
2340out:
2341 fputc('\n', fp);
2342 return ++printed;
2343}
2344
2345bool perf_evsel__fallback(struct perf_evsel *evsel, int err, 2274bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2346 char *msg, size_t msgsize) 2275 char *msg, size_t msgsize)
2347{ 2276{
2277 int paranoid;
2278
2348 if ((err == ENOENT || err == ENXIO || err == ENODEV) && 2279 if ((err == ENOENT || err == ENXIO || err == ENODEV) &&
2349 evsel->attr.type == PERF_TYPE_HARDWARE && 2280 evsel->attr.type == PERF_TYPE_HARDWARE &&
2350 evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) { 2281 evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) {
@@ -2364,6 +2295,22 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2364 2295
2365 zfree(&evsel->name); 2296 zfree(&evsel->name);
2366 return true; 2297 return true;
2298 } else if (err == EACCES && !evsel->attr.exclude_kernel &&
2299 (paranoid = perf_event_paranoid()) > 1) {
2300 const char *name = perf_evsel__name(evsel);
2301 char *new_name;
2302
2303 if (asprintf(&new_name, "%s%su", name, strchr(name, ':') ? "" : ":") < 0)
2304 return false;
2305
2306 if (evsel->name)
2307 free(evsel->name);
2308 evsel->name = new_name;
2309 scnprintf(msg, msgsize,
2310"kernel.perf_event_paranoid=%d, trying to fall back to excluding kernel samples", paranoid);
2311 evsel->attr.exclude_kernel = 1;
2312
2313 return true;
2367 } 2314 }
2368 2315
2369 return false; 2316 return false;
@@ -2382,12 +2329,13 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2382 "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n" 2329 "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n"
2383 "which controls use of the performance events system by\n" 2330 "which controls use of the performance events system by\n"
2384 "unprivileged users (without CAP_SYS_ADMIN).\n\n" 2331 "unprivileged users (without CAP_SYS_ADMIN).\n\n"
2385 "The default value is 1:\n\n" 2332 "The current value is %d:\n\n"
2386 " -1: Allow use of (almost) all events by all users\n" 2333 " -1: Allow use of (almost) all events by all users\n"
2387 ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n" 2334 ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n"
2388 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n" 2335 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n"
2389 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN", 2336 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN",
2390 target->system_wide ? "system-wide " : ""); 2337 target->system_wide ? "system-wide " : "",
2338 perf_event_paranoid());
2391 case ENOENT: 2339 case ENOENT:
2392 return scnprintf(msg, size, "The %s event is not supported.", 2340 return scnprintf(msg, size, "The %s event is not supported.",
2393 perf_evsel__name(evsel)); 2341 perf_evsel__name(evsel));
@@ -2397,10 +2345,18 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2397 "Probably the maximum number of open file descriptors has been reached.\n" 2345 "Probably the maximum number of open file descriptors has been reached.\n"
2398 "Hint: Try again after reducing the number of events.\n" 2346 "Hint: Try again after reducing the number of events.\n"
2399 "Hint: Try increasing the limit with 'ulimit -n <limit>'"); 2347 "Hint: Try increasing the limit with 'ulimit -n <limit>'");
2348 case ENOMEM:
2349 if ((evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0 &&
2350 access("/proc/sys/kernel/perf_event_max_stack", F_OK) == 0)
2351 return scnprintf(msg, size,
2352 "Not enough memory to setup event with callchain.\n"
2353 "Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n"
2354 "Hint: Current value: %d", sysctl_perf_event_max_stack);
2355 break;
2400 case ENODEV: 2356 case ENODEV:
2401 if (target->cpu_list) 2357 if (target->cpu_list)
2402 return scnprintf(msg, size, "%s", 2358 return scnprintf(msg, size, "%s",
2403 "No such device - did you specify an out-of-range profile CPU?\n"); 2359 "No such device - did you specify an out-of-range profile CPU?");
2404 break; 2360 break;
2405 case EOPNOTSUPP: 2361 case EOPNOTSUPP:
2406 if (evsel->attr.precise_ip) 2362 if (evsel->attr.precise_ip)
@@ -2432,7 +2388,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2432 return scnprintf(msg, size, 2388 return scnprintf(msg, size,
2433 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" 2389 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2434 "/bin/dmesg may provide additional information.\n" 2390 "/bin/dmesg may provide additional information.\n"
2435 "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 2391 "No CONFIG_PERF_EVENTS=y kernel support configured?",
2436 err, strerror_r(err, sbuf, sizeof(sbuf)), 2392 err, strerror_r(err, sbuf, sizeof(sbuf)),
2437 perf_evsel__name(evsel)); 2393 perf_evsel__name(evsel));
2438} 2394}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 501ea6e565f1..8a644fef452c 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -178,8 +178,14 @@ void perf_evsel__init(struct perf_evsel *evsel,
178void perf_evsel__exit(struct perf_evsel *evsel); 178void perf_evsel__exit(struct perf_evsel *evsel);
179void perf_evsel__delete(struct perf_evsel *evsel); 179void perf_evsel__delete(struct perf_evsel *evsel);
180 180
181struct callchain_param;
182
181void perf_evsel__config(struct perf_evsel *evsel, 183void perf_evsel__config(struct perf_evsel *evsel,
182 struct record_opts *opts); 184 struct record_opts *opts,
185 struct callchain_param *callchain);
186void perf_evsel__config_callchain(struct perf_evsel *evsel,
187 struct record_opts *opts,
188 struct callchain_param *callchain);
183 189
184int __perf_evsel__sample_size(u64 sample_type); 190int __perf_evsel__sample_size(u64 sample_type);
185void perf_evsel__calc_id_pos(struct perf_evsel *evsel); 191void perf_evsel__calc_id_pos(struct perf_evsel *evsel);
@@ -381,6 +387,24 @@ struct perf_attr_details {
381int perf_evsel__fprintf(struct perf_evsel *evsel, 387int perf_evsel__fprintf(struct perf_evsel *evsel,
382 struct perf_attr_details *details, FILE *fp); 388 struct perf_attr_details *details, FILE *fp);
383 389
390#define EVSEL__PRINT_IP (1<<0)
391#define EVSEL__PRINT_SYM (1<<1)
392#define EVSEL__PRINT_DSO (1<<2)
393#define EVSEL__PRINT_SYMOFFSET (1<<3)
394#define EVSEL__PRINT_ONELINE (1<<4)
395#define EVSEL__PRINT_SRCLINE (1<<5)
396#define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6)
397
398struct callchain_cursor;
399
400int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
401 unsigned int print_opts,
402 struct callchain_cursor *cursor, FILE *fp);
403
404int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
405 int left_alignment, unsigned int print_opts,
406 struct callchain_cursor *cursor, FILE *fp);
407
384bool perf_evsel__fallback(struct perf_evsel *evsel, int err, 408bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
385 char *msg, size_t msgsize); 409 char *msg, size_t msgsize);
386int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 410int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
@@ -396,7 +420,7 @@ for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \
396 (_evsel) && (_evsel)->leader == (_leader); \ 420 (_evsel) && (_evsel)->leader == (_leader); \
397 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) 421 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
398 422
399static inline bool has_branch_callstack(struct perf_evsel *evsel) 423static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel)
400{ 424{
401 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; 425 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
402} 426}
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
new file mode 100644
index 000000000000..3674e77ad640
--- /dev/null
+++ b/tools/perf/util/evsel_fprintf.c
@@ -0,0 +1,212 @@
1#include <stdio.h>
2#include <stdbool.h>
3#include <traceevent/event-parse.h>
4#include "evsel.h"
5#include "callchain.h"
6#include "map.h"
7#include "symbol.h"
8
9static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
10{
11 va_list args;
12 int ret = 0;
13
14 if (!*first) {
15 ret += fprintf(fp, ",");
16 } else {
17 ret += fprintf(fp, ":");
18 *first = false;
19 }
20
21 va_start(args, fmt);
22 ret += vfprintf(fp, fmt, args);
23 va_end(args);
24 return ret;
25}
26
27static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
28{
29 return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
30}
31
32int perf_evsel__fprintf(struct perf_evsel *evsel,
33 struct perf_attr_details *details, FILE *fp)
34{
35 bool first = true;
36 int printed = 0;
37
38 if (details->event_group) {
39 struct perf_evsel *pos;
40
41 if (!perf_evsel__is_group_leader(evsel))
42 return 0;
43
44 if (evsel->nr_members > 1)
45 printed += fprintf(fp, "%s{", evsel->group_name ?: "");
46
47 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
48 for_each_group_member(pos, evsel)
49 printed += fprintf(fp, ",%s", perf_evsel__name(pos));
50
51 if (evsel->nr_members > 1)
52 printed += fprintf(fp, "}");
53 goto out;
54 }
55
56 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
57
58 if (details->verbose) {
59 printed += perf_event_attr__fprintf(fp, &evsel->attr,
60 __print_attr__fprintf, &first);
61 } else if (details->freq) {
62 const char *term = "sample_freq";
63
64 if (!evsel->attr.freq)
65 term = "sample_period";
66
67 printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
68 term, (u64)evsel->attr.sample_freq);
69 }
70
71 if (details->trace_fields) {
72 struct format_field *field;
73
74 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
75 printed += comma_fprintf(fp, &first, " (not a tracepoint)");
76 goto out;
77 }
78
79 field = evsel->tp_format->format.fields;
80 if (field == NULL) {
81 printed += comma_fprintf(fp, &first, " (no trace field)");
82 goto out;
83 }
84
85 printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
86
87 field = field->next;
88 while (field) {
89 printed += comma_fprintf(fp, &first, "%s", field->name);
90 field = field->next;
91 }
92 }
93out:
94 fputc('\n', fp);
95 return ++printed;
96}
97
98int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
99 unsigned int print_opts, struct callchain_cursor *cursor,
100 FILE *fp)
101{
102 int printed = 0;
103 struct callchain_cursor_node *node;
104 int print_ip = print_opts & EVSEL__PRINT_IP;
105 int print_sym = print_opts & EVSEL__PRINT_SYM;
106 int print_dso = print_opts & EVSEL__PRINT_DSO;
107 int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
108 int print_oneline = print_opts & EVSEL__PRINT_ONELINE;
109 int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
110 int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
111 char s = print_oneline ? ' ' : '\t';
112
113 if (sample->callchain) {
114 struct addr_location node_al;
115
116 callchain_cursor_commit(cursor);
117
118 while (1) {
119 u64 addr = 0;
120
121 node = callchain_cursor_current(cursor);
122 if (!node)
123 break;
124
125 if (node->sym && node->sym->ignore)
126 goto next;
127
128 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
129
130 if (print_ip)
131 printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
132
133 if (node->map)
134 addr = node->map->map_ip(node->map, node->ip);
135
136 if (print_sym) {
137 printed += fprintf(fp, " ");
138 node_al.addr = addr;
139 node_al.map = node->map;
140
141 if (print_symoffset) {
142 printed += __symbol__fprintf_symname_offs(node->sym, &node_al,
143 print_unknown_as_addr, fp);
144 } else {
145 printed += __symbol__fprintf_symname(node->sym, &node_al,
146 print_unknown_as_addr, fp);
147 }
148 }
149
150 if (print_dso) {
151 printed += fprintf(fp, " (");
152 printed += map__fprintf_dsoname(node->map, fp);
153 printed += fprintf(fp, ")");
154 }
155
156 if (print_srcline)
157 printed += map__fprintf_srcline(node->map, addr, "\n ", fp);
158
159 if (!print_oneline)
160 printed += fprintf(fp, "\n");
161next:
162 callchain_cursor_advance(cursor);
163 }
164 }
165
166 return printed;
167}
168
169int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
170 int left_alignment, unsigned int print_opts,
171 struct callchain_cursor *cursor, FILE *fp)
172{
173 int printed = 0;
174 int print_ip = print_opts & EVSEL__PRINT_IP;
175 int print_sym = print_opts & EVSEL__PRINT_SYM;
176 int print_dso = print_opts & EVSEL__PRINT_DSO;
177 int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
178 int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
179 int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
180
181 if (cursor != NULL) {
182 printed += sample__fprintf_callchain(sample, left_alignment,
183 print_opts, cursor, fp);
184 } else if (!(al->sym && al->sym->ignore)) {
185 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
186
187 if (print_ip)
188 printed += fprintf(fp, "%16" PRIx64, sample->ip);
189
190 if (print_sym) {
191 printed += fprintf(fp, " ");
192 if (print_symoffset) {
193 printed += __symbol__fprintf_symname_offs(al->sym, al,
194 print_unknown_as_addr, fp);
195 } else {
196 printed += __symbol__fprintf_symname(al->sym, al,
197 print_unknown_as_addr, fp);
198 }
199 }
200
201 if (print_dso) {
202 printed += fprintf(fp, " (");
203 printed += map__fprintf_dsoname(al->map, fp);
204 printed += fprintf(fp, ")");
205 }
206
207 if (print_srcline)
208 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
209 }
210
211 return printed;
212}
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 90680ec9f8b8..08852dde1378 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1474,7 +1474,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1474 1474
1475 dso = machine__findnew_dso(machine, filename); 1475 dso = machine__findnew_dso(machine, filename);
1476 if (dso != NULL) { 1476 if (dso != NULL) {
1477 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1477 char sbuild_id[SBUILD_ID_SIZE];
1478 1478
1479 dso__set_build_id(dso, &bev->build_id); 1479 dso__set_build_id(dso, &bev->build_id);
1480 1480
@@ -1819,7 +1819,8 @@ static int process_cpu_topology(struct perf_file_section *section,
1819 1819
1820 ph->env.nr_sibling_cores = nr; 1820 ph->env.nr_sibling_cores = nr;
1821 size += sizeof(u32); 1821 size += sizeof(u32);
1822 strbuf_init(&sb, 128); 1822 if (strbuf_init(&sb, 128) < 0)
1823 goto free_cpu;
1823 1824
1824 for (i = 0; i < nr; i++) { 1825 for (i = 0; i < nr; i++) {
1825 str = do_read_string(fd, ph); 1826 str = do_read_string(fd, ph);
@@ -1827,7 +1828,8 @@ static int process_cpu_topology(struct perf_file_section *section,
1827 goto error; 1828 goto error;
1828 1829
1829 /* include a NULL character at the end */ 1830 /* include a NULL character at the end */
1830 strbuf_add(&sb, str, strlen(str) + 1); 1831 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1832 goto error;
1831 size += string_size(str); 1833 size += string_size(str);
1832 free(str); 1834 free(str);
1833 } 1835 }
@@ -1849,7 +1851,8 @@ static int process_cpu_topology(struct perf_file_section *section,
1849 goto error; 1851 goto error;
1850 1852
1851 /* include a NULL character at the end */ 1853 /* include a NULL character at the end */
1852 strbuf_add(&sb, str, strlen(str) + 1); 1854 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1855 goto error;
1853 size += string_size(str); 1856 size += string_size(str);
1854 free(str); 1857 free(str);
1855 } 1858 }
@@ -1912,13 +1915,14 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1912 /* nr nodes */ 1915 /* nr nodes */
1913 ret = readn(fd, &nr, sizeof(nr)); 1916 ret = readn(fd, &nr, sizeof(nr));
1914 if (ret != sizeof(nr)) 1917 if (ret != sizeof(nr))
1915 goto error; 1918 return -1;
1916 1919
1917 if (ph->needs_swap) 1920 if (ph->needs_swap)
1918 nr = bswap_32(nr); 1921 nr = bswap_32(nr);
1919 1922
1920 ph->env.nr_numa_nodes = nr; 1923 ph->env.nr_numa_nodes = nr;
1921 strbuf_init(&sb, 256); 1924 if (strbuf_init(&sb, 256) < 0)
1925 return -1;
1922 1926
1923 for (i = 0; i < nr; i++) { 1927 for (i = 0; i < nr; i++) {
1924 /* node number */ 1928 /* node number */
@@ -1940,15 +1944,17 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1940 mem_free = bswap_64(mem_free); 1944 mem_free = bswap_64(mem_free);
1941 } 1945 }
1942 1946
1943 strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":", 1947 if (strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",
1944 node, mem_total, mem_free); 1948 node, mem_total, mem_free) < 0)
1949 goto error;
1945 1950
1946 str = do_read_string(fd, ph); 1951 str = do_read_string(fd, ph);
1947 if (!str) 1952 if (!str)
1948 goto error; 1953 goto error;
1949 1954
1950 /* include a NULL character at the end */ 1955 /* include a NULL character at the end */
1951 strbuf_add(&sb, str, strlen(str) + 1); 1956 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1957 goto error;
1952 free(str); 1958 free(str);
1953 } 1959 }
1954 ph->env.numa_nodes = strbuf_detach(&sb, NULL); 1960 ph->env.numa_nodes = strbuf_detach(&sb, NULL);
@@ -1982,7 +1988,8 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
1982 } 1988 }
1983 1989
1984 ph->env.nr_pmu_mappings = pmu_num; 1990 ph->env.nr_pmu_mappings = pmu_num;
1985 strbuf_init(&sb, 128); 1991 if (strbuf_init(&sb, 128) < 0)
1992 return -1;
1986 1993
1987 while (pmu_num) { 1994 while (pmu_num) {
1988 if (readn(fd, &type, sizeof(type)) != sizeof(type)) 1995 if (readn(fd, &type, sizeof(type)) != sizeof(type))
@@ -1994,9 +2001,11 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
1994 if (!name) 2001 if (!name)
1995 goto error; 2002 goto error;
1996 2003
1997 strbuf_addf(&sb, "%u:%s", type, name); 2004 if (strbuf_addf(&sb, "%u:%s", type, name) < 0)
2005 goto error;
1998 /* include a NULL character at the end */ 2006 /* include a NULL character at the end */
1999 strbuf_add(&sb, "", 1); 2007 if (strbuf_add(&sb, "", 1) < 0)
2008 goto error;
2000 2009
2001 if (!strcmp(name, "msr")) 2010 if (!strcmp(name, "msr"))
2002 ph->env.msr_pmu_type = type; 2011 ph->env.msr_pmu_type = type;
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c
index 43a98a4dc1e1..d62ccaeeadd6 100644
--- a/tools/perf/util/help-unknown-cmd.c
+++ b/tools/perf/util/help-unknown-cmd.c
@@ -27,16 +27,27 @@ static int levenshtein_compare(const void *p1, const void *p2)
27 return l1 != l2 ? l1 - l2 : strcmp(s1, s2); 27 return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
28} 28}
29 29
30static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) 30static int add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
31{ 31{
32 unsigned int i; 32 unsigned int i, nr = cmds->cnt + old->cnt;
33 33 void *tmp;
34 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); 34
35 35 if (nr > cmds->alloc) {
36 /* Choose bigger one to alloc */
37 if (alloc_nr(cmds->alloc) < nr)
38 cmds->alloc = nr;
39 else
40 cmds->alloc = alloc_nr(cmds->alloc);
41 tmp = realloc(cmds->names, cmds->alloc * sizeof(*cmds->names));
42 if (!tmp)
43 return -1;
44 cmds->names = tmp;
45 }
36 for (i = 0; i < old->cnt; i++) 46 for (i = 0; i < old->cnt; i++)
37 cmds->names[cmds->cnt++] = old->names[i]; 47 cmds->names[cmds->cnt++] = old->names[i];
38 zfree(&old->names); 48 zfree(&old->names);
39 old->cnt = 0; 49 old->cnt = 0;
50 return 0;
40} 51}
41 52
42const char *help_unknown_cmd(const char *cmd) 53const char *help_unknown_cmd(const char *cmd)
@@ -52,8 +63,11 @@ const char *help_unknown_cmd(const char *cmd)
52 63
53 load_command_list("perf-", &main_cmds, &other_cmds); 64 load_command_list("perf-", &main_cmds, &other_cmds);
54 65
55 add_cmd_list(&main_cmds, &aliases); 66 if (add_cmd_list(&main_cmds, &aliases) < 0 ||
56 add_cmd_list(&main_cmds, &other_cmds); 67 add_cmd_list(&main_cmds, &other_cmds) < 0) {
68 fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n");
69 goto end;
70 }
57 qsort(main_cmds.names, main_cmds.cnt, 71 qsort(main_cmds.names, main_cmds.cnt,
58 sizeof(main_cmds.names), cmdname_compare); 72 sizeof(main_cmds.names), cmdname_compare);
59 uniq(&main_cmds); 73 uniq(&main_cmds);
@@ -99,6 +113,6 @@ const char *help_unknown_cmd(const char *cmd)
99 for (i = 0; i < n; i++) 113 for (i = 0; i < n; i++)
100 fprintf(stderr, "\t%s\n", main_cmds.names[i]->name); 114 fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
101 } 115 }
102 116end:
103 exit(1); 117 exit(1);
104} 118}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 31c4641fe5ff..cfab531437c7 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -295,7 +295,7 @@ static void hists__delete_entry(struct hists *hists, struct hist_entry *he)
295 root_in = &he->parent_he->hroot_in; 295 root_in = &he->parent_he->hroot_in;
296 root_out = &he->parent_he->hroot_out; 296 root_out = &he->parent_he->hroot_out;
297 } else { 297 } else {
298 if (sort__need_collapse) 298 if (hists__has(hists, need_collapse))
299 root_in = &hists->entries_collapsed; 299 root_in = &hists->entries_collapsed;
300 else 300 else
301 root_in = hists->entries_in; 301 root_in = hists->entries_in;
@@ -953,7 +953,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
953{ 953{
954 int err, err2; 954 int err, err2;
955 955
956 err = sample__resolve_callchain(iter->sample, &iter->parent, 956 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
957 iter->evsel, al, max_stack_depth); 957 iter->evsel, al, max_stack_depth);
958 if (err) 958 if (err)
959 return err; 959 return err;
@@ -1295,8 +1295,9 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
1295 return ret; 1295 return ret;
1296} 1296}
1297 1297
1298int hists__collapse_insert_entry(struct hists *hists, struct rb_root *root, 1298static int hists__collapse_insert_entry(struct hists *hists,
1299 struct hist_entry *he) 1299 struct rb_root *root,
1300 struct hist_entry *he)
1300{ 1301{
1301 struct rb_node **p = &root->rb_node; 1302 struct rb_node **p = &root->rb_node;
1302 struct rb_node *parent = NULL; 1303 struct rb_node *parent = NULL;
@@ -1372,7 +1373,7 @@ int hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
1372 struct hist_entry *n; 1373 struct hist_entry *n;
1373 int ret; 1374 int ret;
1374 1375
1375 if (!sort__need_collapse) 1376 if (!hists__has(hists, need_collapse))
1376 return 0; 1377 return 0;
1377 1378
1378 hists->nr_entries = 0; 1379 hists->nr_entries = 0;
@@ -1631,7 +1632,7 @@ static void output_resort(struct hists *hists, struct ui_progress *prog,
1631 return; 1632 return;
1632 } 1633 }
1633 1634
1634 if (sort__need_collapse) 1635 if (hists__has(hists, need_collapse))
1635 root = &hists->entries_collapsed; 1636 root = &hists->entries_collapsed;
1636 else 1637 else
1637 root = hists->entries_in; 1638 root = hists->entries_in;
@@ -2035,7 +2036,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
2035 struct hist_entry *he; 2036 struct hist_entry *he;
2036 int64_t cmp; 2037 int64_t cmp;
2037 2038
2038 if (sort__need_collapse) 2039 if (hists__has(hists, need_collapse))
2039 root = &hists->entries_collapsed; 2040 root = &hists->entries_collapsed;
2040 else 2041 else
2041 root = hists->entries_in; 2042 root = hists->entries_in;
@@ -2061,6 +2062,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
2061 if (he) { 2062 if (he) {
2062 memset(&he->stat, 0, sizeof(he->stat)); 2063 memset(&he->stat, 0, sizeof(he->stat));
2063 he->hists = hists; 2064 he->hists = hists;
2065 if (symbol_conf.cumulate_callchain)
2066 memset(he->stat_acc, 0, sizeof(he->stat));
2064 rb_link_node(&he->rb_node_in, parent, p); 2067 rb_link_node(&he->rb_node_in, parent, p);
2065 rb_insert_color(&he->rb_node_in, root); 2068 rb_insert_color(&he->rb_node_in, root);
2066 hists__inc_stats(hists, he); 2069 hists__inc_stats(hists, he);
@@ -2075,7 +2078,7 @@ static struct hist_entry *hists__find_entry(struct hists *hists,
2075{ 2078{
2076 struct rb_node *n; 2079 struct rb_node *n;
2077 2080
2078 if (sort__need_collapse) 2081 if (hists__has(hists, need_collapse))
2079 n = hists->entries_collapsed.rb_node; 2082 n = hists->entries_collapsed.rb_node;
2080 else 2083 else
2081 n = hists->entries_in->rb_node; 2084 n = hists->entries_in->rb_node;
@@ -2104,7 +2107,7 @@ void hists__match(struct hists *leader, struct hists *other)
2104 struct rb_node *nd; 2107 struct rb_node *nd;
2105 struct hist_entry *pos, *pair; 2108 struct hist_entry *pos, *pair;
2106 2109
2107 if (sort__need_collapse) 2110 if (hists__has(leader, need_collapse))
2108 root = &leader->entries_collapsed; 2111 root = &leader->entries_collapsed;
2109 else 2112 else
2110 root = leader->entries_in; 2113 root = leader->entries_in;
@@ -2129,7 +2132,7 @@ int hists__link(struct hists *leader, struct hists *other)
2129 struct rb_node *nd; 2132 struct rb_node *nd;
2130 struct hist_entry *pos, *pair; 2133 struct hist_entry *pos, *pair;
2131 2134
2132 if (sort__need_collapse) 2135 if (hists__has(other, need_collapse))
2133 root = &other->entries_collapsed; 2136 root = &other->entries_collapsed;
2134 else 2137 else
2135 root = other->entries_in; 2138 root = other->entries_in;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index bec0cd660fbd..0f84bfb42bb1 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -82,6 +82,8 @@ struct hists {
82 int nr_hpp_node; 82 int nr_hpp_node;
83}; 83};
84 84
85#define hists__has(__h, __f) (__h)->hpp_list->__f
86
85struct hist_entry_iter; 87struct hist_entry_iter;
86 88
87struct hist_iter_ops { 89struct hist_iter_ops {
@@ -199,8 +201,6 @@ int hists__init(void);
199int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list); 201int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list);
200 202
201struct rb_root *hists__get_rotate_entries_in(struct hists *hists); 203struct rb_root *hists__get_rotate_entries_in(struct hists *hists);
202int hists__collapse_insert_entry(struct hists *hists,
203 struct rb_root *root, struct hist_entry *he);
204 204
205struct perf_hpp { 205struct perf_hpp {
206 char *buf; 206 char *buf;
@@ -240,6 +240,14 @@ struct perf_hpp_fmt {
240struct perf_hpp_list { 240struct perf_hpp_list {
241 struct list_head fields; 241 struct list_head fields;
242 struct list_head sorts; 242 struct list_head sorts;
243
244 int need_collapse;
245 int parent;
246 int sym;
247 int dso;
248 int socket;
249 int thread;
250 int comm;
243}; 251};
244 252
245extern struct perf_hpp_list perf_hpp_list; 253extern struct perf_hpp_list perf_hpp_list;
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index abf1366e2a24..9df996085563 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -66,6 +66,7 @@ struct intel_bts {
66 u64 branches_id; 66 u64 branches_id;
67 size_t branches_event_size; 67 size_t branches_event_size;
68 bool synth_needs_swap; 68 bool synth_needs_swap;
69 unsigned long num_events;
69}; 70};
70 71
71struct intel_bts_queue { 72struct intel_bts_queue {
@@ -275,6 +276,10 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq,
275 union perf_event event; 276 union perf_event event;
276 struct perf_sample sample = { .ip = 0, }; 277 struct perf_sample sample = { .ip = 0, };
277 278
279 if (bts->synth_opts.initial_skip &&
280 bts->num_events++ <= bts->synth_opts.initial_skip)
281 return 0;
282
278 event.sample.header.type = PERF_RECORD_SAMPLE; 283 event.sample.header.type = PERF_RECORD_SAMPLE;
279 event.sample.header.misc = PERF_RECORD_MISC_USER; 284 event.sample.header.misc = PERF_RECORD_MISC_USER;
280 event.sample.header.size = sizeof(struct perf_event_header); 285 event.sample.header.size = sizeof(struct perf_event_header);
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 9409d014b46c..9c8f15da86ce 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -356,7 +356,7 @@ static const char *intel_pt_err_msgs[] = {
356 356
357int intel_pt__strerror(int code, char *buf, size_t buflen) 357int intel_pt__strerror(int code, char *buf, size_t buflen)
358{ 358{
359 if (code < 1 || code > INTEL_PT_ERR_MAX) 359 if (code < 1 || code >= INTEL_PT_ERR_MAX)
360 code = INTEL_PT_ERR_UNK; 360 code = INTEL_PT_ERR_UNK;
361 strlcpy(buf, intel_pt_err_msgs[code], buflen); 361 strlcpy(buf, intel_pt_err_msgs[code], buflen);
362 return 0; 362 return 0;
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 407f11b97c8d..137196990012 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -100,6 +100,8 @@ struct intel_pt {
100 u64 cyc_bit; 100 u64 cyc_bit;
101 u64 noretcomp_bit; 101 u64 noretcomp_bit;
102 unsigned max_non_turbo_ratio; 102 unsigned max_non_turbo_ratio;
103
104 unsigned long num_events;
103}; 105};
104 106
105enum switch_state { 107enum switch_state {
@@ -972,6 +974,10 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
972 if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) 974 if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
973 return 0; 975 return 0;
974 976
977 if (pt->synth_opts.initial_skip &&
978 pt->num_events++ < pt->synth_opts.initial_skip)
979 return 0;
980
975 event->sample.header.type = PERF_RECORD_SAMPLE; 981 event->sample.header.type = PERF_RECORD_SAMPLE;
976 event->sample.header.misc = PERF_RECORD_MISC_USER; 982 event->sample.header.misc = PERF_RECORD_MISC_USER;
977 event->sample.header.size = sizeof(struct perf_event_header); 983 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1029,6 +1035,10 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
1029 union perf_event *event = ptq->event_buf; 1035 union perf_event *event = ptq->event_buf;
1030 struct perf_sample sample = { .ip = 0, }; 1036 struct perf_sample sample = { .ip = 0, };
1031 1037
1038 if (pt->synth_opts.initial_skip &&
1039 pt->num_events++ < pt->synth_opts.initial_skip)
1040 return 0;
1041
1032 event->sample.header.type = PERF_RECORD_SAMPLE; 1042 event->sample.header.type = PERF_RECORD_SAMPLE;
1033 event->sample.header.misc = PERF_RECORD_MISC_USER; 1043 event->sample.header.misc = PERF_RECORD_MISC_USER;
1034 event->sample.header.size = sizeof(struct perf_event_header); 1044 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1087,6 +1097,10 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1087 union perf_event *event = ptq->event_buf; 1097 union perf_event *event = ptq->event_buf;
1088 struct perf_sample sample = { .ip = 0, }; 1098 struct perf_sample sample = { .ip = 0, };
1089 1099
1100 if (pt->synth_opts.initial_skip &&
1101 pt->num_events++ < pt->synth_opts.initial_skip)
1102 return 0;
1103
1090 event->sample.header.type = PERF_RECORD_SAMPLE; 1104 event->sample.header.type = PERF_RECORD_SAMPLE;
1091 event->sample.header.misc = PERF_RECORD_MISC_USER; 1105 event->sample.header.misc = PERF_RECORD_MISC_USER;
1092 event->sample.header.size = sizeof(struct perf_event_header); 1106 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1130,7 +1144,7 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1130 pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n", 1144 pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n",
1131 ret); 1145 ret);
1132 1146
1133 if (pt->synth_opts.callchain) 1147 if (pt->synth_opts.last_branch)
1134 intel_pt_reset_last_branch_rb(ptq); 1148 intel_pt_reset_last_branch_rb(ptq);
1135 1149
1136 return ret; 1150 return ret;
@@ -1199,14 +1213,18 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1199 ptq->have_sample = false; 1213 ptq->have_sample = false;
1200 1214
1201 if (pt->sample_instructions && 1215 if (pt->sample_instructions &&
1202 (state->type & INTEL_PT_INSTRUCTION)) { 1216 (state->type & INTEL_PT_INSTRUCTION) &&
1217 (!pt->synth_opts.initial_skip ||
1218 pt->num_events++ >= pt->synth_opts.initial_skip)) {
1203 err = intel_pt_synth_instruction_sample(ptq); 1219 err = intel_pt_synth_instruction_sample(ptq);
1204 if (err) 1220 if (err)
1205 return err; 1221 return err;
1206 } 1222 }
1207 1223
1208 if (pt->sample_transactions && 1224 if (pt->sample_transactions &&
1209 (state->type & INTEL_PT_TRANSACTION)) { 1225 (state->type & INTEL_PT_TRANSACTION) &&
1226 (!pt->synth_opts.initial_skip ||
1227 pt->num_events++ >= pt->synth_opts.initial_skip)) {
1210 err = intel_pt_synth_transaction_sample(ptq); 1228 err = intel_pt_synth_transaction_sample(ptq);
1211 if (err) 1229 if (err)
1212 return err; 1230 return err;
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index ad0c0bb1fbc7..86afe9618bb0 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -17,6 +17,7 @@
17#include "strlist.h" 17#include "strlist.h"
18#include <elf.h> 18#include <elf.h>
19 19
20#include "tsc.h"
20#include "session.h" 21#include "session.h"
21#include "jit.h" 22#include "jit.h"
22#include "jitdump.h" 23#include "jitdump.h"
@@ -33,6 +34,7 @@ struct jit_buf_desc {
33 size_t bufsize; 34 size_t bufsize;
34 FILE *in; 35 FILE *in;
35 bool needs_bswap; /* handles cross-endianess */ 36 bool needs_bswap; /* handles cross-endianess */
37 bool use_arch_timestamp;
36 void *debug_data; 38 void *debug_data;
37 size_t nr_debug_entries; 39 size_t nr_debug_entries;
38 uint32_t code_load_count; 40 uint32_t code_load_count;
@@ -158,13 +160,16 @@ jit_open(struct jit_buf_desc *jd, const char *name)
158 header.flags = bswap_64(header.flags); 160 header.flags = bswap_64(header.flags);
159 } 161 }
160 162
163 jd->use_arch_timestamp = header.flags & JITDUMP_FLAGS_ARCH_TIMESTAMP;
164
161 if (verbose > 2) 165 if (verbose > 2)
162 pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n", 166 pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n",
163 header.version, 167 header.version,
164 header.total_size, 168 header.total_size,
165 (unsigned long long)header.timestamp, 169 (unsigned long long)header.timestamp,
166 header.pid, 170 header.pid,
167 header.elf_mach); 171 header.elf_mach,
172 jd->use_arch_timestamp);
168 173
169 if (header.flags & JITDUMP_FLAGS_RESERVED) { 174 if (header.flags & JITDUMP_FLAGS_RESERVED) {
170 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n", 175 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
@@ -172,10 +177,15 @@ jit_open(struct jit_buf_desc *jd, const char *name)
172 goto error; 177 goto error;
173 } 178 }
174 179
180 if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) {
181 pr_err("jitdump file uses arch timestamps but there is no timestamp conversion\n");
182 goto error;
183 }
184
175 /* 185 /*
176 * validate event is using the correct clockid 186 * validate event is using the correct clockid
177 */ 187 */
178 if (jit_validate_events(jd->session)) { 188 if (!jd->use_arch_timestamp && jit_validate_events(jd->session)) {
179 pr_err("error, jitted code must be sampled with perf record -k 1\n"); 189 pr_err("error, jitted code must be sampled with perf record -k 1\n");
180 goto error; 190 goto error;
181 } 191 }
@@ -329,6 +339,23 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)
329 return 0; 339 return 0;
330} 340}
331 341
342static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp)
343{
344 struct perf_tsc_conversion tc;
345
346 if (!jd->use_arch_timestamp)
347 return timestamp;
348
349 tc.time_shift = jd->session->time_conv.time_shift;
350 tc.time_mult = jd->session->time_conv.time_mult;
351 tc.time_zero = jd->session->time_conv.time_zero;
352
353 if (!tc.time_mult)
354 return 0;
355
356 return tsc_to_perf_time(timestamp, &tc);
357}
358
332static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) 359static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
333{ 360{
334 struct perf_sample sample; 361 struct perf_sample sample;
@@ -385,7 +412,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
385 return -1; 412 return -1;
386 } 413 }
387 if (stat(filename, &st)) 414 if (stat(filename, &st))
388 memset(&st, 0, sizeof(stat)); 415 memset(&st, 0, sizeof(st));
389 416
390 event->mmap2.header.type = PERF_RECORD_MMAP2; 417 event->mmap2.header.type = PERF_RECORD_MMAP2;
391 event->mmap2.header.misc = PERF_RECORD_MISC_USER; 418 event->mmap2.header.misc = PERF_RECORD_MISC_USER;
@@ -410,7 +437,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
410 id->tid = tid; 437 id->tid = tid;
411 } 438 }
412 if (jd->sample_type & PERF_SAMPLE_TIME) 439 if (jd->sample_type & PERF_SAMPLE_TIME)
413 id->time = jr->load.p.timestamp; 440 id->time = convert_timestamp(jd, jr->load.p.timestamp);
414 441
415 /* 442 /*
416 * create pseudo sample to induce dso hit increment 443 * create pseudo sample to induce dso hit increment
@@ -473,7 +500,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
473 size++; /* for \0 */ 500 size++; /* for \0 */
474 501
475 if (stat(filename, &st)) 502 if (stat(filename, &st))
476 memset(&st, 0, sizeof(stat)); 503 memset(&st, 0, sizeof(st));
477 504
478 size = PERF_ALIGN(size, sizeof(u64)); 505 size = PERF_ALIGN(size, sizeof(u64));
479 506
@@ -499,7 +526,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
499 id->tid = tid; 526 id->tid = tid;
500 } 527 }
501 if (jd->sample_type & PERF_SAMPLE_TIME) 528 if (jd->sample_type & PERF_SAMPLE_TIME)
502 id->time = jr->load.p.timestamp; 529 id->time = convert_timestamp(jd, jr->load.p.timestamp);
503 530
504 /* 531 /*
505 * create pseudo sample to induce dso hit increment 532 * create pseudo sample to induce dso hit increment
diff --git a/tools/perf/util/jitdump.h b/tools/perf/util/jitdump.h
index b66c1f503d9e..bcacd20d0c1c 100644
--- a/tools/perf/util/jitdump.h
+++ b/tools/perf/util/jitdump.h
@@ -23,9 +23,12 @@
23#define JITHEADER_VERSION 1 23#define JITHEADER_VERSION 1
24 24
25enum jitdump_flags_bits { 25enum jitdump_flags_bits {
26 JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT,
26 JITDUMP_FLAGS_MAX_BIT, 27 JITDUMP_FLAGS_MAX_BIT,
27}; 28};
28 29
30#define JITDUMP_FLAGS_ARCH_TIMESTAMP (1ULL << JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT)
31
29#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \ 32#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \
30 (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0) 33 (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0)
31 34
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 80b9b6a87990..f9644f79686c 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -32,6 +32,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
32 32
33 machine->threads = RB_ROOT; 33 machine->threads = RB_ROOT;
34 pthread_rwlock_init(&machine->threads_lock, NULL); 34 pthread_rwlock_init(&machine->threads_lock, NULL);
35 machine->nr_threads = 0;
35 INIT_LIST_HEAD(&machine->dead_threads); 36 INIT_LIST_HEAD(&machine->dead_threads);
36 machine->last_match = NULL; 37 machine->last_match = NULL;
37 38
@@ -361,7 +362,7 @@ out_err:
361} 362}
362 363
363/* 364/*
364 * Caller must eventually drop thread->refcnt returned with a successfull 365 * Caller must eventually drop thread->refcnt returned with a successful
365 * lookup/new thread inserted. 366 * lookup/new thread inserted.
366 */ 367 */
367static struct thread *____machine__findnew_thread(struct machine *machine, 368static struct thread *____machine__findnew_thread(struct machine *machine,
@@ -430,6 +431,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
430 */ 431 */
431 thread__get(th); 432 thread__get(th);
432 machine->last_match = th; 433 machine->last_match = th;
434 ++machine->nr_threads;
433 } 435 }
434 436
435 return th; 437 return th;
@@ -681,11 +683,13 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
681 683
682size_t machine__fprintf(struct machine *machine, FILE *fp) 684size_t machine__fprintf(struct machine *machine, FILE *fp)
683{ 685{
684 size_t ret = 0; 686 size_t ret;
685 struct rb_node *nd; 687 struct rb_node *nd;
686 688
687 pthread_rwlock_rdlock(&machine->threads_lock); 689 pthread_rwlock_rdlock(&machine->threads_lock);
688 690
691 ret = fprintf(fp, "Threads: %u\n", machine->nr_threads);
692
689 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) { 693 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
690 struct thread *pos = rb_entry(nd, struct thread, rb_node); 694 struct thread *pos = rb_entry(nd, struct thread, rb_node);
691 695
@@ -908,11 +912,11 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
908 return machine__create_kernel_maps(machine); 912 return machine__create_kernel_maps(machine);
909} 913}
910 914
911int machine__load_kallsyms(struct machine *machine, const char *filename, 915int __machine__load_kallsyms(struct machine *machine, const char *filename,
912 enum map_type type, symbol_filter_t filter) 916 enum map_type type, bool no_kcore, symbol_filter_t filter)
913{ 917{
914 struct map *map = machine__kernel_map(machine); 918 struct map *map = machine__kernel_map(machine);
915 int ret = dso__load_kallsyms(map->dso, filename, map, filter); 919 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore, filter);
916 920
917 if (ret > 0) { 921 if (ret > 0) {
918 dso__set_loaded(map->dso, type); 922 dso__set_loaded(map->dso, type);
@@ -927,6 +931,12 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
927 return ret; 931 return ret;
928} 932}
929 933
934int machine__load_kallsyms(struct machine *machine, const char *filename,
935 enum map_type type, symbol_filter_t filter)
936{
937 return __machine__load_kallsyms(machine, filename, type, false, filter);
938}
939
930int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 940int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
931 symbol_filter_t filter) 941 symbol_filter_t filter)
932{ 942{
@@ -1413,6 +1423,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
1413 pthread_rwlock_wrlock(&machine->threads_lock); 1423 pthread_rwlock_wrlock(&machine->threads_lock);
1414 rb_erase_init(&th->rb_node, &machine->threads); 1424 rb_erase_init(&th->rb_node, &machine->threads);
1415 RB_CLEAR_NODE(&th->rb_node); 1425 RB_CLEAR_NODE(&th->rb_node);
1426 --machine->nr_threads;
1416 /* 1427 /*
1417 * Move it first to the dead_threads list, then drop the reference, 1428 * Move it first to the dead_threads list, then drop the reference,
1418 * if this is the last reference, then the thread__delete destructor 1429 * if this is the last reference, then the thread__delete destructor
@@ -1599,6 +1610,7 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1599} 1610}
1600 1611
1601static int add_callchain_ip(struct thread *thread, 1612static int add_callchain_ip(struct thread *thread,
1613 struct callchain_cursor *cursor,
1602 struct symbol **parent, 1614 struct symbol **parent,
1603 struct addr_location *root_al, 1615 struct addr_location *root_al,
1604 u8 *cpumode, 1616 u8 *cpumode,
@@ -1630,7 +1642,7 @@ static int add_callchain_ip(struct thread *thread,
1630 * It seems the callchain is corrupted. 1642 * It seems the callchain is corrupted.
1631 * Discard all. 1643 * Discard all.
1632 */ 1644 */
1633 callchain_cursor_reset(&callchain_cursor); 1645 callchain_cursor_reset(cursor);
1634 return 1; 1646 return 1;
1635 } 1647 }
1636 return 0; 1648 return 0;
@@ -1640,7 +1652,7 @@ static int add_callchain_ip(struct thread *thread,
1640 } 1652 }
1641 1653
1642 if (al.sym != NULL) { 1654 if (al.sym != NULL) {
1643 if (sort__has_parent && !*parent && 1655 if (perf_hpp_list.parent && !*parent &&
1644 symbol__match_regex(al.sym, &parent_regex)) 1656 symbol__match_regex(al.sym, &parent_regex))
1645 *parent = al.sym; 1657 *parent = al.sym;
1646 else if (have_ignore_callees && root_al && 1658 else if (have_ignore_callees && root_al &&
@@ -1648,13 +1660,13 @@ static int add_callchain_ip(struct thread *thread,
1648 /* Treat this symbol as the root, 1660 /* Treat this symbol as the root,
1649 forgetting its callees. */ 1661 forgetting its callees. */
1650 *root_al = al; 1662 *root_al = al;
1651 callchain_cursor_reset(&callchain_cursor); 1663 callchain_cursor_reset(cursor);
1652 } 1664 }
1653 } 1665 }
1654 1666
1655 if (symbol_conf.hide_unresolved && al.sym == NULL) 1667 if (symbol_conf.hide_unresolved && al.sym == NULL)
1656 return 0; 1668 return 0;
1657 return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym); 1669 return callchain_cursor_append(cursor, al.addr, al.map, al.sym);
1658} 1670}
1659 1671
1660struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1672struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1724,6 +1736,7 @@ static int remove_loops(struct branch_entry *l, int nr)
1724 * negative error code on other errors. 1736 * negative error code on other errors.
1725 */ 1737 */
1726static int resolve_lbr_callchain_sample(struct thread *thread, 1738static int resolve_lbr_callchain_sample(struct thread *thread,
1739 struct callchain_cursor *cursor,
1727 struct perf_sample *sample, 1740 struct perf_sample *sample,
1728 struct symbol **parent, 1741 struct symbol **parent,
1729 struct addr_location *root_al, 1742 struct addr_location *root_al,
@@ -1756,7 +1769,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1756 */ 1769 */
1757 int mix_chain_nr = i + 1 + lbr_nr + 1; 1770 int mix_chain_nr = i + 1 + lbr_nr + 1;
1758 1771
1759 if (mix_chain_nr > PERF_MAX_STACK_DEPTH + PERF_MAX_BRANCH_DEPTH) { 1772 if (mix_chain_nr > (int)sysctl_perf_event_max_stack + PERF_MAX_BRANCH_DEPTH) {
1760 pr_warning("corrupted callchain. skipping...\n"); 1773 pr_warning("corrupted callchain. skipping...\n");
1761 return 0; 1774 return 0;
1762 } 1775 }
@@ -1778,7 +1791,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1778 ip = lbr_stack->entries[0].to; 1791 ip = lbr_stack->entries[0].to;
1779 } 1792 }
1780 1793
1781 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); 1794 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
1782 if (err) 1795 if (err)
1783 return (err < 0) ? err : 0; 1796 return (err < 0) ? err : 0;
1784 } 1797 }
@@ -1789,6 +1802,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1789} 1802}
1790 1803
1791static int thread__resolve_callchain_sample(struct thread *thread, 1804static int thread__resolve_callchain_sample(struct thread *thread,
1805 struct callchain_cursor *cursor,
1792 struct perf_evsel *evsel, 1806 struct perf_evsel *evsel,
1793 struct perf_sample *sample, 1807 struct perf_sample *sample,
1794 struct symbol **parent, 1808 struct symbol **parent,
@@ -1803,10 +1817,8 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1803 int skip_idx = -1; 1817 int skip_idx = -1;
1804 int first_call = 0; 1818 int first_call = 0;
1805 1819
1806 callchain_cursor_reset(&callchain_cursor); 1820 if (perf_evsel__has_branch_callstack(evsel)) {
1807 1821 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent,
1808 if (has_branch_callstack(evsel)) {
1809 err = resolve_lbr_callchain_sample(thread, sample, parent,
1810 root_al, max_stack); 1822 root_al, max_stack);
1811 if (err) 1823 if (err)
1812 return (err < 0) ? err : 0; 1824 return (err < 0) ? err : 0;
@@ -1816,7 +1828,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1816 * Based on DWARF debug information, some architectures skip 1828 * Based on DWARF debug information, some architectures skip
1817 * a callchain entry saved by the kernel. 1829 * a callchain entry saved by the kernel.
1818 */ 1830 */
1819 if (chain->nr < PERF_MAX_STACK_DEPTH) 1831 if (chain->nr < sysctl_perf_event_max_stack)
1820 skip_idx = arch_skip_callchain_idx(thread, chain); 1832 skip_idx = arch_skip_callchain_idx(thread, chain);
1821 1833
1822 /* 1834 /*
@@ -1863,10 +1875,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1863 nr = remove_loops(be, nr); 1875 nr = remove_loops(be, nr);
1864 1876
1865 for (i = 0; i < nr; i++) { 1877 for (i = 0; i < nr; i++) {
1866 err = add_callchain_ip(thread, parent, root_al, 1878 err = add_callchain_ip(thread, cursor, parent, root_al,
1867 NULL, be[i].to); 1879 NULL, be[i].to);
1868 if (!err) 1880 if (!err)
1869 err = add_callchain_ip(thread, parent, root_al, 1881 err = add_callchain_ip(thread, cursor, parent, root_al,
1870 NULL, be[i].from); 1882 NULL, be[i].from);
1871 if (err == -EINVAL) 1883 if (err == -EINVAL)
1872 break; 1884 break;
@@ -1877,7 +1889,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1877 } 1889 }
1878 1890
1879check_calls: 1891check_calls:
1880 if (chain->nr > PERF_MAX_STACK_DEPTH && (int)chain->nr > max_stack) { 1892 if (chain->nr > sysctl_perf_event_max_stack && (int)chain->nr > max_stack) {
1881 pr_warning("corrupted callchain. skipping...\n"); 1893 pr_warning("corrupted callchain. skipping...\n");
1882 return 0; 1894 return 0;
1883 } 1895 }
@@ -1896,7 +1908,7 @@ check_calls:
1896#endif 1908#endif
1897 ip = chain->ips[j]; 1909 ip = chain->ips[j];
1898 1910
1899 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); 1911 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
1900 1912
1901 if (err) 1913 if (err)
1902 return (err < 0) ? err : 0; 1914 return (err < 0) ? err : 0;
@@ -1915,19 +1927,12 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
1915 entry->map, entry->sym); 1927 entry->map, entry->sym);
1916} 1928}
1917 1929
1918int thread__resolve_callchain(struct thread *thread, 1930static int thread__resolve_callchain_unwind(struct thread *thread,
1919 struct perf_evsel *evsel, 1931 struct callchain_cursor *cursor,
1920 struct perf_sample *sample, 1932 struct perf_evsel *evsel,
1921 struct symbol **parent, 1933 struct perf_sample *sample,
1922 struct addr_location *root_al, 1934 int max_stack)
1923 int max_stack)
1924{ 1935{
1925 int ret = thread__resolve_callchain_sample(thread, evsel,
1926 sample, parent,
1927 root_al, max_stack);
1928 if (ret)
1929 return ret;
1930
1931 /* Can we do dwarf post unwind? */ 1936 /* Can we do dwarf post unwind? */
1932 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) && 1937 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
1933 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER))) 1938 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
@@ -1938,9 +1943,45 @@ int thread__resolve_callchain(struct thread *thread,
1938 (!sample->user_stack.size)) 1943 (!sample->user_stack.size))
1939 return 0; 1944 return 0;
1940 1945
1941 return unwind__get_entries(unwind_entry, &callchain_cursor, 1946 return unwind__get_entries(unwind_entry, cursor,
1942 thread, sample, max_stack); 1947 thread, sample, max_stack);
1948}
1949
1950int thread__resolve_callchain(struct thread *thread,
1951 struct callchain_cursor *cursor,
1952 struct perf_evsel *evsel,
1953 struct perf_sample *sample,
1954 struct symbol **parent,
1955 struct addr_location *root_al,
1956 int max_stack)
1957{
1958 int ret = 0;
1959
1960 callchain_cursor_reset(&callchain_cursor);
1943 1961
1962 if (callchain_param.order == ORDER_CALLEE) {
1963 ret = thread__resolve_callchain_sample(thread, cursor,
1964 evsel, sample,
1965 parent, root_al,
1966 max_stack);
1967 if (ret)
1968 return ret;
1969 ret = thread__resolve_callchain_unwind(thread, cursor,
1970 evsel, sample,
1971 max_stack);
1972 } else {
1973 ret = thread__resolve_callchain_unwind(thread, cursor,
1974 evsel, sample,
1975 max_stack);
1976 if (ret)
1977 return ret;
1978 ret = thread__resolve_callchain_sample(thread, cursor,
1979 evsel, sample,
1980 parent, root_al,
1981 max_stack);
1982 }
1983
1984 return ret;
1944} 1985}
1945 1986
1946int machine__for_each_thread(struct machine *machine, 1987int machine__for_each_thread(struct machine *machine,
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 8499db281158..83f46790c52f 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -31,6 +31,7 @@ struct machine {
31 char *root_dir; 31 char *root_dir;
32 struct rb_root threads; 32 struct rb_root threads;
33 pthread_rwlock_t threads_lock; 33 pthread_rwlock_t threads_lock;
34 unsigned int nr_threads;
34 struct list_head dead_threads; 35 struct list_head dead_threads;
35 struct thread *last_match; 36 struct thread *last_match;
36 struct vdso_info *vdso_info; 37 struct vdso_info *vdso_info;
@@ -141,7 +142,11 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
141 struct addr_location *al); 142 struct addr_location *al);
142struct mem_info *sample__resolve_mem(struct perf_sample *sample, 143struct mem_info *sample__resolve_mem(struct perf_sample *sample,
143 struct addr_location *al); 144 struct addr_location *al);
145
146struct callchain_cursor;
147
144int thread__resolve_callchain(struct thread *thread, 148int thread__resolve_callchain(struct thread *thread,
149 struct callchain_cursor *cursor,
145 struct perf_evsel *evsel, 150 struct perf_evsel *evsel,
146 struct perf_sample *sample, 151 struct perf_sample *sample,
147 struct symbol **parent, 152 struct symbol **parent,
@@ -211,6 +216,8 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *machine,
211struct map *machine__findnew_module_map(struct machine *machine, u64 start, 216struct map *machine__findnew_module_map(struct machine *machine, u64 start,
212 const char *filename); 217 const char *filename);
213 218
219int __machine__load_kallsyms(struct machine *machine, const char *filename,
220 enum map_type type, bool no_kcore, symbol_filter_t filter);
214int machine__load_kallsyms(struct machine *machine, const char *filename, 221int machine__load_kallsyms(struct machine *machine, const char *filename,
215 enum map_type type, symbol_filter_t filter); 222 enum map_type type, symbol_filter_t filter);
216int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 223int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 171b6d10a04b..b19bcd3b7128 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -289,7 +289,7 @@ int map__load(struct map *map, symbol_filter_t filter)
289 nr = dso__load(map->dso, map, filter); 289 nr = dso__load(map->dso, map, filter);
290 if (nr < 0) { 290 if (nr < 0) {
291 if (map->dso->has_build_id) { 291 if (map->dso->has_build_id) {
292 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 292 char sbuild_id[SBUILD_ID_SIZE];
293 293
294 build_id__sprintf(map->dso->build_id, 294 build_id__sprintf(map->dso->build_id,
295 sizeof(map->dso->build_id), 295 sizeof(map->dso->build_id),
@@ -431,6 +431,13 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
431 if (map->dso->rel) 431 if (map->dso->rel)
432 return rip - map->pgoff; 432 return rip - map->pgoff;
433 433
434 /*
435 * kernel modules also have DSO_TYPE_USER in dso->kernel,
436 * but all kernel modules are ET_REL, so won't get here.
437 */
438 if (map->dso->kernel == DSO_TYPE_USER)
439 return rip + map->dso->text_offset;
440
434 return map->unmap_ip(map, rip) - map->reloc; 441 return map->unmap_ip(map, rip) - map->reloc;
435} 442}
436 443
@@ -454,6 +461,13 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
454 if (map->dso->rel) 461 if (map->dso->rel)
455 return map->unmap_ip(map, ip + map->pgoff); 462 return map->unmap_ip(map, ip + map->pgoff);
456 463
464 /*
465 * kernel modules also have DSO_TYPE_USER in dso->kernel,
466 * but all kernel modules are ET_REL, so won't get here.
467 */
468 if (map->dso->kernel == DSO_TYPE_USER)
469 return map->unmap_ip(map, ip - map->dso->text_offset);
470
457 return ip + map->reloc; 471 return ip + map->reloc;
458} 472}
459 473
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index b1b9e2385f4b..fe84df1875aa 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -308,3 +308,12 @@ void ordered_events__free(struct ordered_events *oe)
308 free(event); 308 free(event);
309 } 309 }
310} 310}
311
312void ordered_events__reinit(struct ordered_events *oe)
313{
314 ordered_events__deliver_t old_deliver = oe->deliver;
315
316 ordered_events__free(oe);
317 memset(oe, '\0', sizeof(*oe));
318 ordered_events__init(oe, old_deliver);
319}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index f403991e3bfd..e11468a9a6e4 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -49,6 +49,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
49int ordered_events__flush(struct ordered_events *oe, enum oe_flush how); 49int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
50void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver); 50void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver);
51void ordered_events__free(struct ordered_events *oe); 51void ordered_events__free(struct ordered_events *oe);
52void ordered_events__reinit(struct ordered_events *oe);
52 53
53static inline 54static inline
54void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size) 55void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4c19d5e79d8c..c6fd0479f4cd 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -138,11 +138,11 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
138#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 138#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
139#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 139#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
140 140
141#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ 141#define for_each_subsystem(sys_dir, sys_dirent) \
142 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \ 142 while ((sys_dirent = readdir(sys_dir)) != NULL) \
143 if (sys_dirent.d_type == DT_DIR && \ 143 if (sys_dirent->d_type == DT_DIR && \
144 (strcmp(sys_dirent.d_name, ".")) && \ 144 (strcmp(sys_dirent->d_name, ".")) && \
145 (strcmp(sys_dirent.d_name, ".."))) 145 (strcmp(sys_dirent->d_name, "..")))
146 146
147static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) 147static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
148{ 148{
@@ -159,12 +159,12 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
159 return 0; 159 return 0;
160} 160}
161 161
162#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) \ 162#define for_each_event(sys_dirent, evt_dir, evt_dirent) \
163 while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \ 163 while ((evt_dirent = readdir(evt_dir)) != NULL) \
164 if (evt_dirent.d_type == DT_DIR && \ 164 if (evt_dirent->d_type == DT_DIR && \
165 (strcmp(evt_dirent.d_name, ".")) && \ 165 (strcmp(evt_dirent->d_name, ".")) && \
166 (strcmp(evt_dirent.d_name, "..")) && \ 166 (strcmp(evt_dirent->d_name, "..")) && \
167 (!tp_event_has_id(&sys_dirent, &evt_dirent))) 167 (!tp_event_has_id(sys_dirent, evt_dirent)))
168 168
169#define MAX_EVENT_LENGTH 512 169#define MAX_EVENT_LENGTH 512
170 170
@@ -173,7 +173,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
173{ 173{
174 struct tracepoint_path *path = NULL; 174 struct tracepoint_path *path = NULL;
175 DIR *sys_dir, *evt_dir; 175 DIR *sys_dir, *evt_dir;
176 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 176 struct dirent *sys_dirent, *evt_dirent;
177 char id_buf[24]; 177 char id_buf[24];
178 int fd; 178 int fd;
179 u64 id; 179 u64 id;
@@ -184,18 +184,18 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
184 if (!sys_dir) 184 if (!sys_dir)
185 return NULL; 185 return NULL;
186 186
187 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 187 for_each_subsystem(sys_dir, sys_dirent) {
188 188
189 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, 189 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
190 sys_dirent.d_name); 190 sys_dirent->d_name);
191 evt_dir = opendir(dir_path); 191 evt_dir = opendir(dir_path);
192 if (!evt_dir) 192 if (!evt_dir)
193 continue; 193 continue;
194 194
195 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 195 for_each_event(sys_dirent, evt_dir, evt_dirent) {
196 196
197 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 197 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
198 evt_dirent.d_name); 198 evt_dirent->d_name);
199 fd = open(evt_path, O_RDONLY); 199 fd = open(evt_path, O_RDONLY);
200 if (fd < 0) 200 if (fd < 0)
201 continue; 201 continue;
@@ -220,9 +220,9 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
220 free(path); 220 free(path);
221 return NULL; 221 return NULL;
222 } 222 }
223 strncpy(path->system, sys_dirent.d_name, 223 strncpy(path->system, sys_dirent->d_name,
224 MAX_EVENT_LENGTH); 224 MAX_EVENT_LENGTH);
225 strncpy(path->name, evt_dirent.d_name, 225 strncpy(path->name, evt_dirent->d_name,
226 MAX_EVENT_LENGTH); 226 MAX_EVENT_LENGTH);
227 return path; 227 return path;
228 } 228 }
@@ -1649,7 +1649,7 @@ static void parse_events_print_error(struct parse_events_error *err,
1649 1649
1650 buf = _buf; 1650 buf = _buf;
1651 1651
1652 /* We're cutting from the beggining. */ 1652 /* We're cutting from the beginning. */
1653 if (err->idx > max_err_idx) 1653 if (err->idx > max_err_idx)
1654 cut = err->idx - max_err_idx; 1654 cut = err->idx - max_err_idx;
1655 1655
@@ -1812,7 +1812,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1812 bool name_only) 1812 bool name_only)
1813{ 1813{
1814 DIR *sys_dir, *evt_dir; 1814 DIR *sys_dir, *evt_dir;
1815 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1815 struct dirent *sys_dirent, *evt_dirent;
1816 char evt_path[MAXPATHLEN]; 1816 char evt_path[MAXPATHLEN];
1817 char dir_path[MAXPATHLEN]; 1817 char dir_path[MAXPATHLEN];
1818 char **evt_list = NULL; 1818 char **evt_list = NULL;
@@ -1830,20 +1830,20 @@ restart:
1830 goto out_close_sys_dir; 1830 goto out_close_sys_dir;
1831 } 1831 }
1832 1832
1833 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 1833 for_each_subsystem(sys_dir, sys_dirent) {
1834 if (subsys_glob != NULL && 1834 if (subsys_glob != NULL &&
1835 !strglobmatch(sys_dirent.d_name, subsys_glob)) 1835 !strglobmatch(sys_dirent->d_name, subsys_glob))
1836 continue; 1836 continue;
1837 1837
1838 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, 1838 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
1839 sys_dirent.d_name); 1839 sys_dirent->d_name);
1840 evt_dir = opendir(dir_path); 1840 evt_dir = opendir(dir_path);
1841 if (!evt_dir) 1841 if (!evt_dir)
1842 continue; 1842 continue;
1843 1843
1844 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 1844 for_each_event(sys_dirent, evt_dir, evt_dirent) {
1845 if (event_glob != NULL && 1845 if (event_glob != NULL &&
1846 !strglobmatch(evt_dirent.d_name, event_glob)) 1846 !strglobmatch(evt_dirent->d_name, event_glob))
1847 continue; 1847 continue;
1848 1848
1849 if (!evt_num_known) { 1849 if (!evt_num_known) {
@@ -1852,7 +1852,7 @@ restart:
1852 } 1852 }
1853 1853
1854 snprintf(evt_path, MAXPATHLEN, "%s:%s", 1854 snprintf(evt_path, MAXPATHLEN, "%s:%s",
1855 sys_dirent.d_name, evt_dirent.d_name); 1855 sys_dirent->d_name, evt_dirent->d_name);
1856 1856
1857 evt_list[evt_i] = strdup(evt_path); 1857 evt_list[evt_i] = strdup(evt_path);
1858 if (evt_list[evt_i] == NULL) 1858 if (evt_list[evt_i] == NULL)
@@ -1905,7 +1905,7 @@ out_close_sys_dir:
1905int is_valid_tracepoint(const char *event_string) 1905int is_valid_tracepoint(const char *event_string)
1906{ 1906{
1907 DIR *sys_dir, *evt_dir; 1907 DIR *sys_dir, *evt_dir;
1908 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1908 struct dirent *sys_dirent, *evt_dirent;
1909 char evt_path[MAXPATHLEN]; 1909 char evt_path[MAXPATHLEN];
1910 char dir_path[MAXPATHLEN]; 1910 char dir_path[MAXPATHLEN];
1911 1911
@@ -1913,17 +1913,17 @@ int is_valid_tracepoint(const char *event_string)
1913 if (!sys_dir) 1913 if (!sys_dir)
1914 return 0; 1914 return 0;
1915 1915
1916 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 1916 for_each_subsystem(sys_dir, sys_dirent) {
1917 1917
1918 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, 1918 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
1919 sys_dirent.d_name); 1919 sys_dirent->d_name);
1920 evt_dir = opendir(dir_path); 1920 evt_dir = opendir(dir_path);
1921 if (!evt_dir) 1921 if (!evt_dir)
1922 continue; 1922 continue;
1923 1923
1924 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 1924 for_each_event(sys_dirent, evt_dir, evt_dirent) {
1925 snprintf(evt_path, MAXPATHLEN, "%s:%s", 1925 snprintf(evt_path, MAXPATHLEN, "%s:%s",
1926 sys_dirent.d_name, evt_dirent.d_name); 1926 sys_dirent->d_name, evt_dirent->d_name);
1927 if (!strcmp(evt_path, event_string)) { 1927 if (!strcmp(evt_path, event_string)) {
1928 closedir(evt_dir); 1928 closedir(evt_dir);
1929 closedir(sys_dir); 1929 closedir(sys_dir);
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index adef23b1352e..ddb0261b2577 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -602,14 +602,13 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
602 602
603static __u64 pmu_format_max_value(const unsigned long *format) 603static __u64 pmu_format_max_value(const unsigned long *format)
604{ 604{
605 int w; 605 __u64 w = 0;
606 int fbit;
606 607
607 w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); 608 for_each_set_bit(fbit, format, PERF_PMU_FORMAT_BITS)
608 if (!w) 609 w |= (1ULL << fbit);
609 return 0; 610
610 if (w < 64) 611 return w;
611 return (1ULL << w) - 1;
612 return -1;
613} 612}
614 613
615/* 614/*
@@ -644,20 +643,20 @@ static int pmu_resolve_param_term(struct parse_events_term *term,
644static char *pmu_formats_string(struct list_head *formats) 643static char *pmu_formats_string(struct list_head *formats)
645{ 644{
646 struct perf_pmu_format *format; 645 struct perf_pmu_format *format;
647 char *str; 646 char *str = NULL;
648 struct strbuf buf; 647 struct strbuf buf = STRBUF_INIT;
649 unsigned i = 0; 648 unsigned i = 0;
650 649
651 if (!formats) 650 if (!formats)
652 return NULL; 651 return NULL;
653 652
654 strbuf_init(&buf, 0);
655 /* sysfs exported terms */ 653 /* sysfs exported terms */
656 list_for_each_entry(format, formats, list) 654 list_for_each_entry(format, formats, list)
657 strbuf_addf(&buf, i++ ? ",%s" : "%s", 655 if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0)
658 format->name); 656 goto error;
659 657
660 str = strbuf_detach(&buf, NULL); 658 str = strbuf_detach(&buf, NULL);
659error:
661 strbuf_release(&buf); 660 strbuf_release(&buf);
662 661
663 return str; 662 return str;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 8319fbb08636..74401a20106d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -265,6 +265,65 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
265 return true; 265 return true;
266} 266}
267 267
268/*
269 * NOTE:
270 * '.gnu.linkonce.this_module' section of kernel module elf directly
271 * maps to 'struct module' from linux/module.h. This section contains
272 * actual module name which will be used by kernel after loading it.
273 * But, we cannot use 'struct module' here since linux/module.h is not
274 * exposed to user-space. Offset of 'name' has remained same from long
275 * time, so hardcoding it here.
276 */
277#ifdef __LP64__
278#define MOD_NAME_OFFSET 24
279#else
280#define MOD_NAME_OFFSET 12
281#endif
282
283/*
284 * @module can be module name of module file path. In case of path,
285 * inspect elf and find out what is actual module name.
286 * Caller has to free mod_name after using it.
287 */
288static char *find_module_name(const char *module)
289{
290 int fd;
291 Elf *elf;
292 GElf_Ehdr ehdr;
293 GElf_Shdr shdr;
294 Elf_Data *data;
295 Elf_Scn *sec;
296 char *mod_name = NULL;
297
298 fd = open(module, O_RDONLY);
299 if (fd < 0)
300 return NULL;
301
302 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
303 if (elf == NULL)
304 goto elf_err;
305
306 if (gelf_getehdr(elf, &ehdr) == NULL)
307 goto ret_err;
308
309 sec = elf_section_by_name(elf, &ehdr, &shdr,
310 ".gnu.linkonce.this_module", NULL);
311 if (!sec)
312 goto ret_err;
313
314 data = elf_getdata(sec, NULL);
315 if (!data || !data->d_buf)
316 goto ret_err;
317
318 mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET);
319
320ret_err:
321 elf_end(elf);
322elf_err:
323 close(fd);
324 return mod_name;
325}
326
268#ifdef HAVE_DWARF_SUPPORT 327#ifdef HAVE_DWARF_SUPPORT
269 328
270static int kernel_get_module_dso(const char *module, struct dso **pdso) 329static int kernel_get_module_dso(const char *module, struct dso **pdso)
@@ -486,8 +545,10 @@ static int get_text_start_address(const char *exec, unsigned long *address)
486 return -errno; 545 return -errno;
487 546
488 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 547 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
489 if (elf == NULL) 548 if (elf == NULL) {
490 return -EINVAL; 549 ret = -EINVAL;
550 goto out_close;
551 }
491 552
492 if (gelf_getehdr(elf, &ehdr) == NULL) 553 if (gelf_getehdr(elf, &ehdr) == NULL)
493 goto out; 554 goto out;
@@ -499,6 +560,9 @@ static int get_text_start_address(const char *exec, unsigned long *address)
499 ret = 0; 560 ret = 0;
500out: 561out:
501 elf_end(elf); 562 elf_end(elf);
563out_close:
564 close(fd);
565
502 return ret; 566 return ret;
503} 567}
504 568
@@ -583,32 +647,23 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
583 int ntevs, const char *module) 647 int ntevs, const char *module)
584{ 648{
585 int i, ret = 0; 649 int i, ret = 0;
586 char *tmp; 650 char *mod_name = NULL;
587 651
588 if (!module) 652 if (!module)
589 return 0; 653 return 0;
590 654
591 tmp = strrchr(module, '/'); 655 mod_name = find_module_name(module);
592 if (tmp) {
593 /* This is a module path -- get the module name */
594 module = strdup(tmp + 1);
595 if (!module)
596 return -ENOMEM;
597 tmp = strchr(module, '.');
598 if (tmp)
599 *tmp = '\0';
600 tmp = (char *)module; /* For free() */
601 }
602 656
603 for (i = 0; i < ntevs; i++) { 657 for (i = 0; i < ntevs; i++) {
604 tevs[i].point.module = strdup(module); 658 tevs[i].point.module =
659 strdup(mod_name ? mod_name : module);
605 if (!tevs[i].point.module) { 660 if (!tevs[i].point.module) {
606 ret = -ENOMEM; 661 ret = -ENOMEM;
607 break; 662 break;
608 } 663 }
609 } 664 }
610 665
611 free(tmp); 666 free(mod_name);
612 return ret; 667 return ret;
613} 668}
614 669
@@ -1618,69 +1673,65 @@ out:
1618} 1673}
1619 1674
1620/* Compose only probe arg */ 1675/* Compose only probe arg */
1621int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 1676char *synthesize_perf_probe_arg(struct perf_probe_arg *pa)
1622{ 1677{
1623 struct perf_probe_arg_field *field = pa->field; 1678 struct perf_probe_arg_field *field = pa->field;
1624 int ret; 1679 struct strbuf buf;
1625 char *tmp = buf; 1680 char *ret = NULL;
1681 int err;
1682
1683 if (strbuf_init(&buf, 64) < 0)
1684 return NULL;
1626 1685
1627 if (pa->name && pa->var) 1686 if (pa->name && pa->var)
1628 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); 1687 err = strbuf_addf(&buf, "%s=%s", pa->name, pa->var);
1629 else 1688 else
1630 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); 1689 err = strbuf_addstr(&buf, pa->name ?: pa->var);
1631 if (ret <= 0) 1690 if (err)
1632 goto error; 1691 goto out;
1633 tmp += ret;
1634 len -= ret;
1635 1692
1636 while (field) { 1693 while (field) {
1637 if (field->name[0] == '[') 1694 if (field->name[0] == '[')
1638 ret = e_snprintf(tmp, len, "%s", field->name); 1695 err = strbuf_addstr(&buf, field->name);
1639 else 1696 else
1640 ret = e_snprintf(tmp, len, "%s%s", 1697 err = strbuf_addf(&buf, "%s%s", field->ref ? "->" : ".",
1641 field->ref ? "->" : ".", field->name); 1698 field->name);
1642 if (ret <= 0)
1643 goto error;
1644 tmp += ret;
1645 len -= ret;
1646 field = field->next; 1699 field = field->next;
1700 if (err)
1701 goto out;
1647 } 1702 }
1648 1703
1649 if (pa->type) { 1704 if (pa->type)
1650 ret = e_snprintf(tmp, len, ":%s", pa->type); 1705 if (strbuf_addf(&buf, ":%s", pa->type) < 0)
1651 if (ret <= 0) 1706 goto out;
1652 goto error;
1653 tmp += ret;
1654 len -= ret;
1655 }
1656 1707
1657 return tmp - buf; 1708 ret = strbuf_detach(&buf, NULL);
1658error: 1709out:
1659 pr_debug("Failed to synthesize perf probe argument: %d\n", ret); 1710 strbuf_release(&buf);
1660 return ret; 1711 return ret;
1661} 1712}
1662 1713
1663/* Compose only probe point (not argument) */ 1714/* Compose only probe point (not argument) */
1664static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 1715static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1665{ 1716{
1666 char *buf, *tmp; 1717 struct strbuf buf;
1667 char offs[32] = "", line[32] = "", file[32] = ""; 1718 char *tmp, *ret = NULL;
1668 int ret, len; 1719 int len, err = 0;
1669 1720
1670 buf = zalloc(MAX_CMDLEN); 1721 if (strbuf_init(&buf, 64) < 0)
1671 if (buf == NULL) { 1722 return NULL;
1672 ret = -ENOMEM; 1723
1673 goto error; 1724 if (pp->function) {
1674 } 1725 if (strbuf_addstr(&buf, pp->function) < 0)
1675 if (pp->offset) { 1726 goto out;
1676 ret = e_snprintf(offs, 32, "+%lu", pp->offset); 1727 if (pp->offset)
1677 if (ret <= 0) 1728 err = strbuf_addf(&buf, "+%lu", pp->offset);
1678 goto error; 1729 else if (pp->line)
1679 } 1730 err = strbuf_addf(&buf, ":%d", pp->line);
1680 if (pp->line) { 1731 else if (pp->retprobe)
1681 ret = e_snprintf(line, 32, ":%d", pp->line); 1732 err = strbuf_addstr(&buf, "%return");
1682 if (ret <= 0) 1733 if (err)
1683 goto error; 1734 goto out;
1684 } 1735 }
1685 if (pp->file) { 1736 if (pp->file) {
1686 tmp = pp->file; 1737 tmp = pp->file;
@@ -1689,25 +1740,15 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1689 tmp = strchr(pp->file + len - 30, '/'); 1740 tmp = strchr(pp->file + len - 30, '/');
1690 tmp = tmp ? tmp + 1 : pp->file + len - 30; 1741 tmp = tmp ? tmp + 1 : pp->file + len - 30;
1691 } 1742 }
1692 ret = e_snprintf(file, 32, "@%s", tmp); 1743 err = strbuf_addf(&buf, "@%s", tmp);
1693 if (ret <= 0) 1744 if (!err && !pp->function && pp->line)
1694 goto error; 1745 err = strbuf_addf(&buf, ":%d", pp->line);
1695 } 1746 }
1696 1747 if (!err)
1697 if (pp->function) 1748 ret = strbuf_detach(&buf, NULL);
1698 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, 1749out:
1699 offs, pp->retprobe ? "%return" : "", line, 1750 strbuf_release(&buf);
1700 file); 1751 return ret;
1701 else
1702 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
1703 if (ret <= 0)
1704 goto error;
1705
1706 return buf;
1707error:
1708 pr_debug("Failed to synthesize perf probe point: %d\n", ret);
1709 free(buf);
1710 return NULL;
1711} 1752}
1712 1753
1713#if 0 1754#if 0
@@ -1736,45 +1777,32 @@ char *synthesize_perf_probe_command(struct perf_probe_event *pev)
1736#endif 1777#endif
1737 1778
1738static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 1779static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
1739 char **buf, size_t *buflen, 1780 struct strbuf *buf, int depth)
1740 int depth)
1741{ 1781{
1742 int ret; 1782 int err;
1743 if (ref->next) { 1783 if (ref->next) {
1744 depth = __synthesize_probe_trace_arg_ref(ref->next, buf, 1784 depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
1745 buflen, depth + 1); 1785 depth + 1);
1746 if (depth < 0) 1786 if (depth < 0)
1747 goto out; 1787 return depth;
1748 }
1749
1750 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
1751 if (ret < 0)
1752 depth = ret;
1753 else {
1754 *buf += ret;
1755 *buflen -= ret;
1756 } 1788 }
1757out: 1789 err = strbuf_addf(buf, "%+ld(", ref->offset);
1758 return depth; 1790 return (err < 0) ? err : depth;
1759
1760} 1791}
1761 1792
1762static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, 1793static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
1763 char *buf, size_t buflen) 1794 struct strbuf *buf)
1764{ 1795{
1765 struct probe_trace_arg_ref *ref = arg->ref; 1796 struct probe_trace_arg_ref *ref = arg->ref;
1766 int ret, depth = 0; 1797 int depth = 0, err;
1767 char *tmp = buf;
1768 1798
1769 /* Argument name or separator */ 1799 /* Argument name or separator */
1770 if (arg->name) 1800 if (arg->name)
1771 ret = e_snprintf(buf, buflen, " %s=", arg->name); 1801 err = strbuf_addf(buf, " %s=", arg->name);
1772 else 1802 else
1773 ret = e_snprintf(buf, buflen, " "); 1803 err = strbuf_addch(buf, ' ');
1774 if (ret < 0) 1804 if (err)
1775 return ret; 1805 return err;
1776 buf += ret;
1777 buflen -= ret;
1778 1806
1779 /* Special case: @XXX */ 1807 /* Special case: @XXX */
1780 if (arg->value[0] == '@' && arg->ref) 1808 if (arg->value[0] == '@' && arg->ref)
@@ -1782,59 +1810,44 @@ static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
1782 1810
1783 /* Dereferencing arguments */ 1811 /* Dereferencing arguments */
1784 if (ref) { 1812 if (ref) {
1785 depth = __synthesize_probe_trace_arg_ref(ref, &buf, 1813 depth = __synthesize_probe_trace_arg_ref(ref, buf, 1);
1786 &buflen, 1);
1787 if (depth < 0) 1814 if (depth < 0)
1788 return depth; 1815 return depth;
1789 } 1816 }
1790 1817
1791 /* Print argument value */ 1818 /* Print argument value */
1792 if (arg->value[0] == '@' && arg->ref) 1819 if (arg->value[0] == '@' && arg->ref)
1793 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value, 1820 err = strbuf_addf(buf, "%s%+ld", arg->value, arg->ref->offset);
1794 arg->ref->offset);
1795 else 1821 else
1796 ret = e_snprintf(buf, buflen, "%s", arg->value); 1822 err = strbuf_addstr(buf, arg->value);
1797 if (ret < 0)
1798 return ret;
1799 buf += ret;
1800 buflen -= ret;
1801 1823
1802 /* Closing */ 1824 /* Closing */
1803 while (depth--) { 1825 while (!err && depth--)
1804 ret = e_snprintf(buf, buflen, ")"); 1826 err = strbuf_addch(buf, ')');
1805 if (ret < 0) 1827
1806 return ret;
1807 buf += ret;
1808 buflen -= ret;
1809 }
1810 /* Print argument type */ 1828 /* Print argument type */
1811 if (arg->type) { 1829 if (!err && arg->type)
1812 ret = e_snprintf(buf, buflen, ":%s", arg->type); 1830 err = strbuf_addf(buf, ":%s", arg->type);
1813 if (ret <= 0)
1814 return ret;
1815 buf += ret;
1816 }
1817 1831
1818 return buf - tmp; 1832 return err;
1819} 1833}
1820 1834
1821char *synthesize_probe_trace_command(struct probe_trace_event *tev) 1835char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1822{ 1836{
1823 struct probe_trace_point *tp = &tev->point; 1837 struct probe_trace_point *tp = &tev->point;
1824 char *buf; 1838 struct strbuf buf;
1825 int i, len, ret; 1839 char *ret = NULL;
1840 int i, err;
1826 1841
1827 buf = zalloc(MAX_CMDLEN); 1842 /* Uprobes must have tp->module */
1828 if (buf == NULL) 1843 if (tev->uprobes && !tp->module)
1829 return NULL; 1844 return NULL;
1830 1845
1831 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p', 1846 if (strbuf_init(&buf, 32) < 0)
1832 tev->group, tev->event); 1847 return NULL;
1833 if (len <= 0)
1834 goto error;
1835 1848
1836 /* Uprobes must have tp->module */ 1849 if (strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
1837 if (tev->uprobes && !tp->module) 1850 tev->group, tev->event) < 0)
1838 goto error; 1851 goto error;
1839 /* 1852 /*
1840 * If tp->address == 0, then this point must be a 1853 * If tp->address == 0, then this point must be a
@@ -1849,34 +1862,25 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1849 1862
1850 /* Use the tp->address for uprobes */ 1863 /* Use the tp->address for uprobes */
1851 if (tev->uprobes) 1864 if (tev->uprobes)
1852 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx", 1865 err = strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address);
1853 tp->module, tp->address);
1854 else if (!strncmp(tp->symbol, "0x", 2)) 1866 else if (!strncmp(tp->symbol, "0x", 2))
1855 /* Absolute address. See try_to_find_absolute_address() */ 1867 /* Absolute address. See try_to_find_absolute_address() */
1856 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx", 1868 err = strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "",
1857 tp->module ?: "", tp->module ? ":" : "", 1869 tp->module ? ":" : "", tp->address);
1858 tp->address);
1859 else 1870 else
1860 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu", 1871 err = strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
1861 tp->module ?: "", tp->module ? ":" : "", 1872 tp->module ? ":" : "", tp->symbol, tp->offset);
1862 tp->symbol, tp->offset); 1873 if (err)
1863
1864 if (ret <= 0)
1865 goto error; 1874 goto error;
1866 len += ret;
1867 1875
1868 for (i = 0; i < tev->nargs; i++) { 1876 for (i = 0; i < tev->nargs; i++)
1869 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len, 1877 if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0)
1870 MAX_CMDLEN - len);
1871 if (ret <= 0)
1872 goto error; 1878 goto error;
1873 len += ret;
1874 }
1875 1879
1876 return buf; 1880 ret = strbuf_detach(&buf, NULL);
1877error: 1881error:
1878 free(buf); 1882 strbuf_release(&buf);
1879 return NULL; 1883 return ret;
1880} 1884}
1881 1885
1882static int find_perf_probe_point_from_map(struct probe_trace_point *tp, 1886static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
@@ -1958,7 +1962,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
1958static int convert_to_perf_probe_event(struct probe_trace_event *tev, 1962static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1959 struct perf_probe_event *pev, bool is_kprobe) 1963 struct perf_probe_event *pev, bool is_kprobe)
1960{ 1964{
1961 char buf[64] = ""; 1965 struct strbuf buf = STRBUF_INIT;
1962 int i, ret; 1966 int i, ret;
1963 1967
1964 /* Convert event/group name */ 1968 /* Convert event/group name */
@@ -1981,14 +1985,15 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1981 if (tev->args[i].name) 1985 if (tev->args[i].name)
1982 pev->args[i].name = strdup(tev->args[i].name); 1986 pev->args[i].name = strdup(tev->args[i].name);
1983 else { 1987 else {
1984 ret = synthesize_probe_trace_arg(&tev->args[i], 1988 if ((ret = strbuf_init(&buf, 32)) < 0)
1985 buf, 64); 1989 goto error;
1986 pev->args[i].name = strdup(buf); 1990 ret = synthesize_probe_trace_arg(&tev->args[i], &buf);
1991 pev->args[i].name = strbuf_detach(&buf, NULL);
1987 } 1992 }
1988 if (pev->args[i].name == NULL && ret >= 0) 1993 if (pev->args[i].name == NULL && ret >= 0)
1989 ret = -ENOMEM; 1994 ret = -ENOMEM;
1990 } 1995 }
1991 1996error:
1992 if (ret < 0) 1997 if (ret < 0)
1993 clear_perf_probe_event(pev); 1998 clear_perf_probe_event(pev);
1994 1999
@@ -2162,35 +2167,38 @@ static int perf_probe_event__sprintf(const char *group, const char *event,
2162 struct strbuf *result) 2167 struct strbuf *result)
2163{ 2168{
2164 int i, ret; 2169 int i, ret;
2165 char buf[128]; 2170 char *buf;
2166 char *place;
2167 2171
2168 /* Synthesize only event probe point */ 2172 if (asprintf(&buf, "%s:%s", group, event) < 0)
2169 place = synthesize_perf_probe_point(&pev->point); 2173 return -errno;
2170 if (!place) 2174 ret = strbuf_addf(result, " %-20s (on ", buf);
2171 return -EINVAL; 2175 free(buf);
2176 if (ret)
2177 return ret;
2172 2178
2173 ret = e_snprintf(buf, 128, "%s:%s", group, event); 2179 /* Synthesize only event probe point */
2174 if (ret < 0) 2180 buf = synthesize_perf_probe_point(&pev->point);
2175 goto out; 2181 if (!buf)
2182 return -ENOMEM;
2183 ret = strbuf_addstr(result, buf);
2184 free(buf);
2176 2185
2177 strbuf_addf(result, " %-20s (on %s", buf, place); 2186 if (!ret && module)
2178 if (module) 2187 ret = strbuf_addf(result, " in %s", module);
2179 strbuf_addf(result, " in %s", module);
2180 2188
2181 if (pev->nargs > 0) { 2189 if (!ret && pev->nargs > 0) {
2182 strbuf_add(result, " with", 5); 2190 ret = strbuf_add(result, " with", 5);
2183 for (i = 0; i < pev->nargs; i++) { 2191 for (i = 0; !ret && i < pev->nargs; i++) {
2184 ret = synthesize_perf_probe_arg(&pev->args[i], 2192 buf = synthesize_perf_probe_arg(&pev->args[i]);
2185 buf, 128); 2193 if (!buf)
2186 if (ret < 0) 2194 return -ENOMEM;
2187 goto out; 2195 ret = strbuf_addf(result, " %s", buf);
2188 strbuf_addf(result, " %s", buf); 2196 free(buf);
2189 } 2197 }
2190 } 2198 }
2191 strbuf_addch(result, ')'); 2199 if (!ret)
2192out: 2200 ret = strbuf_addch(result, ')');
2193 free(place); 2201
2194 return ret; 2202 return ret;
2195} 2203}
2196 2204
@@ -2498,7 +2506,8 @@ static int find_probe_functions(struct map *map, char *name,
2498 2506
2499void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused, 2507void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
2500 struct probe_trace_event *tev __maybe_unused, 2508 struct probe_trace_event *tev __maybe_unused,
2501 struct map *map __maybe_unused) { } 2509 struct map *map __maybe_unused,
2510 struct symbol *sym __maybe_unused) { }
2502 2511
2503/* 2512/*
2504 * Find probe function addresses from map. 2513 * Find probe function addresses from map.
@@ -2516,6 +2525,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2516 struct probe_trace_point *tp; 2525 struct probe_trace_point *tp;
2517 int num_matched_functions; 2526 int num_matched_functions;
2518 int ret, i, j, skipped = 0; 2527 int ret, i, j, skipped = 0;
2528 char *mod_name;
2519 2529
2520 map = get_target_map(pev->target, pev->uprobes); 2530 map = get_target_map(pev->target, pev->uprobes);
2521 if (!map) { 2531 if (!map) {
@@ -2600,9 +2610,19 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2600 tp->realname = strdup_or_goto(sym->name, nomem_out); 2610 tp->realname = strdup_or_goto(sym->name, nomem_out);
2601 2611
2602 tp->retprobe = pp->retprobe; 2612 tp->retprobe = pp->retprobe;
2603 if (pev->target) 2613 if (pev->target) {
2604 tev->point.module = strdup_or_goto(pev->target, 2614 if (pev->uprobes) {
2605 nomem_out); 2615 tev->point.module = strdup_or_goto(pev->target,
2616 nomem_out);
2617 } else {
2618 mod_name = find_module_name(pev->target);
2619 tev->point.module =
2620 strdup(mod_name ? mod_name : pev->target);
2621 free(mod_name);
2622 if (!tev->point.module)
2623 goto nomem_out;
2624 }
2625 }
2606 tev->uprobes = pev->uprobes; 2626 tev->uprobes = pev->uprobes;
2607 tev->nargs = pev->nargs; 2627 tev->nargs = pev->nargs;
2608 if (tev->nargs) { 2628 if (tev->nargs) {
@@ -2624,7 +2644,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2624 strdup_or_goto(pev->args[i].type, 2644 strdup_or_goto(pev->args[i].type,
2625 nomem_out); 2645 nomem_out);
2626 } 2646 }
2627 arch__fix_tev_from_maps(pev, tev, map); 2647 arch__fix_tev_from_maps(pev, tev, map, sym);
2628 } 2648 }
2629 if (ret == skipped) { 2649 if (ret == skipped) {
2630 ret = -ENOENT; 2650 ret = -ENOENT;
@@ -2743,9 +2763,13 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2743{ 2763{
2744 int ret; 2764 int ret;
2745 2765
2746 if (pev->uprobes && !pev->group) { 2766 if (!pev->group) {
2747 /* Replace group name if not given */ 2767 /* Set group name if not given */
2748 ret = convert_exec_to_group(pev->target, &pev->group); 2768 if (!pev->uprobes) {
2769 pev->group = strdup(PERFPROBE_GROUP);
2770 ret = pev->group ? 0 : -ENOMEM;
2771 } else
2772 ret = convert_exec_to_group(pev->target, &pev->group);
2749 if (ret != 0) { 2773 if (ret != 0) {
2750 pr_warning("Failed to make a group name.\n"); 2774 pr_warning("Failed to make a group name.\n");
2751 return ret; 2775 return ret;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e54e7b011577..5a27eb4fad05 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -120,7 +120,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev);
120/* Events to command string */ 120/* Events to command string */
121char *synthesize_perf_probe_command(struct perf_probe_event *pev); 121char *synthesize_perf_probe_command(struct perf_probe_event *pev);
122char *synthesize_probe_trace_command(struct probe_trace_event *tev); 122char *synthesize_probe_trace_command(struct probe_trace_event *tev);
123int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len); 123char *synthesize_perf_probe_arg(struct perf_probe_arg *pa);
124 124
125/* Check the perf_probe_event needs debuginfo */ 125/* Check the perf_probe_event needs debuginfo */
126bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); 126bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
@@ -154,7 +154,8 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
154int show_available_funcs(const char *module, struct strfilter *filter, bool user); 154int show_available_funcs(const char *module, struct strfilter *filter, bool user);
155bool arch__prefers_symtab(void); 155bool arch__prefers_symtab(void);
156void arch__fix_tev_from_maps(struct perf_probe_event *pev, 156void arch__fix_tev_from_maps(struct perf_probe_event *pev,
157 struct probe_trace_event *tev, struct map *map); 157 struct probe_trace_event *tev, struct map *map,
158 struct symbol *sym);
158 159
159/* If there is no space to write, returns -E2BIG. */ 160/* If there is no space to write, returns -E2BIG. */
160int e_snprintf(char *str, size_t size, const char *format, ...) 161int e_snprintf(char *str, size_t size, const char *format, ...)
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index e3b3b92e4458..3fe6214970e6 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -220,8 +220,7 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev)
220 220
221 pr_debug("Writing event: %s\n", buf); 221 pr_debug("Writing event: %s\n", buf);
222 if (!probe_event_dry_run) { 222 if (!probe_event_dry_run) {
223 ret = write(fd, buf, strlen(buf)); 223 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
224 if (ret <= 0) {
225 ret = -errno; 224 ret = -errno;
226 pr_warning("Failed to write event: %s\n", 225 pr_warning("Failed to write event: %s\n",
227 strerror_r(errno, sbuf, sizeof(sbuf))); 226 strerror_r(errno, sbuf, sizeof(sbuf)));
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index b3bd0fba0237..1259839dbf6d 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -553,7 +553,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
553static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) 553static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
554{ 554{
555 Dwarf_Die vr_die; 555 Dwarf_Die vr_die;
556 char buf[32], *ptr; 556 char *buf, *ptr;
557 int ret = 0; 557 int ret = 0;
558 558
559 /* Copy raw parameters */ 559 /* Copy raw parameters */
@@ -563,13 +563,13 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
563 if (pf->pvar->name) 563 if (pf->pvar->name)
564 pf->tvar->name = strdup(pf->pvar->name); 564 pf->tvar->name = strdup(pf->pvar->name);
565 else { 565 else {
566 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32); 566 buf = synthesize_perf_probe_arg(pf->pvar);
567 if (ret < 0) 567 if (!buf)
568 return ret; 568 return -ENOMEM;
569 ptr = strchr(buf, ':'); /* Change type separator to _ */ 569 ptr = strchr(buf, ':'); /* Change type separator to _ */
570 if (ptr) 570 if (ptr)
571 *ptr = '_'; 571 *ptr = '_';
572 pf->tvar->name = strdup(buf); 572 pf->tvar->name = buf;
573 } 573 }
574 if (pf->tvar->name == NULL) 574 if (pf->tvar->name == NULL)
575 return -ENOMEM; 575 return -ENOMEM;
@@ -1294,6 +1294,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1294{ 1294{
1295 struct available_var_finder *af = data; 1295 struct available_var_finder *af = data;
1296 struct variable_list *vl; 1296 struct variable_list *vl;
1297 struct strbuf buf = STRBUF_INIT;
1297 int tag, ret; 1298 int tag, ret;
1298 1299
1299 vl = &af->vls[af->nvls - 1]; 1300 vl = &af->vls[af->nvls - 1];
@@ -1307,25 +1308,26 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1307 if (ret == 0 || ret == -ERANGE) { 1308 if (ret == 0 || ret == -ERANGE) {
1308 int ret2; 1309 int ret2;
1309 bool externs = !af->child; 1310 bool externs = !af->child;
1310 struct strbuf buf;
1311 1311
1312 strbuf_init(&buf, 64); 1312 if (strbuf_init(&buf, 64) < 0)
1313 goto error;
1313 1314
1314 if (probe_conf.show_location_range) { 1315 if (probe_conf.show_location_range) {
1315 if (!externs) { 1316 if (!externs)
1316 if (ret) 1317 ret2 = strbuf_add(&buf,
1317 strbuf_add(&buf, "[INV]\t", 6); 1318 ret ? "[INV]\t" : "[VAL]\t", 6);
1318 else 1319 else
1319 strbuf_add(&buf, "[VAL]\t", 6); 1320 ret2 = strbuf_add(&buf, "[EXT]\t", 6);
1320 } else 1321 if (ret2)
1321 strbuf_add(&buf, "[EXT]\t", 6); 1322 goto error;
1322 } 1323 }
1323 1324
1324 ret2 = die_get_varname(die_mem, &buf); 1325 ret2 = die_get_varname(die_mem, &buf);
1325 1326
1326 if (!ret2 && probe_conf.show_location_range && 1327 if (!ret2 && probe_conf.show_location_range &&
1327 !externs) { 1328 !externs) {
1328 strbuf_addch(&buf, '\t'); 1329 if (strbuf_addch(&buf, '\t') < 0)
1330 goto error;
1329 ret2 = die_get_var_range(&af->pf.sp_die, 1331 ret2 = die_get_var_range(&af->pf.sp_die,
1330 die_mem, &buf); 1332 die_mem, &buf);
1331 } 1333 }
@@ -1343,6 +1345,10 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1343 return DIE_FIND_CB_CONTINUE; 1345 return DIE_FIND_CB_CONTINUE;
1344 else 1346 else
1345 return DIE_FIND_CB_SIBLING; 1347 return DIE_FIND_CB_SIBLING;
1348error:
1349 strbuf_release(&buf);
1350 pr_debug("Error in strbuf\n");
1351 return DIE_FIND_CB_END;
1346} 1352}
1347 1353
1348/* Add a found vars into available variables list */ 1354/* Add a found vars into available variables list */
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 8162ba0e2e57..36c6862119e3 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -23,3 +23,4 @@ util/strlist.c
23util/trace-event.c 23util/trace-event.c
24../lib/rbtree.c 24../lib/rbtree.c
25util/string.c 25util/string.c
26util/symbol_fprintf.c
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index 01f03242b86a..c6d4ee2de752 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -17,38 +17,42 @@ static inline int need_bs_quote(char c)
17 return (c == '\'' || c == '!'); 17 return (c == '\'' || c == '!');
18} 18}
19 19
20static void sq_quote_buf(struct strbuf *dst, const char *src) 20static int sq_quote_buf(struct strbuf *dst, const char *src)
21{ 21{
22 char *to_free = NULL; 22 char *to_free = NULL;
23 int ret;
23 24
24 if (dst->buf == src) 25 if (dst->buf == src)
25 to_free = strbuf_detach(dst, NULL); 26 to_free = strbuf_detach(dst, NULL);
26 27
27 strbuf_addch(dst, '\''); 28 ret = strbuf_addch(dst, '\'');
28 while (*src) { 29 while (!ret && *src) {
29 size_t len = strcspn(src, "'!"); 30 size_t len = strcspn(src, "'!");
30 strbuf_add(dst, src, len); 31 ret = strbuf_add(dst, src, len);
31 src += len; 32 src += len;
32 while (need_bs_quote(*src)) { 33 while (!ret && need_bs_quote(*src))
33 strbuf_addstr(dst, "'\\"); 34 ret = strbuf_addf(dst, "'\\%c\'", *src++);
34 strbuf_addch(dst, *src++);
35 strbuf_addch(dst, '\'');
36 }
37 } 35 }
38 strbuf_addch(dst, '\''); 36 if (!ret)
37 ret = strbuf_addch(dst, '\'');
39 free(to_free); 38 free(to_free);
39
40 return ret;
40} 41}
41 42
42void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) 43int sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
43{ 44{
44 int i; 45 int i, ret;
45 46
46 /* Copy into destination buffer. */ 47 /* Copy into destination buffer. */
47 strbuf_grow(dst, 255); 48 ret = strbuf_grow(dst, 255);
48 for (i = 0; argv[i]; ++i) { 49 for (i = 0; !ret && argv[i]; ++i) {
49 strbuf_addch(dst, ' '); 50 ret = strbuf_addch(dst, ' ');
50 sq_quote_buf(dst, argv[i]); 51 if (ret)
52 break;
53 ret = sq_quote_buf(dst, argv[i]);
51 if (maxlen && dst->len > maxlen) 54 if (maxlen && dst->len > maxlen)
52 die("Too many or long arguments"); 55 die("Too many or long arguments");
53 } 56 }
57 return ret;
54} 58}
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index 3340c9c4a6ca..e1ec19146fb0 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -24,6 +24,6 @@
24 * sq_quote() in a real application. 24 * sq_quote() in a real application.
25 */ 25 */
26 26
27void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); 27int sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);
28 28
29#endif /* __PERF_QUOTE_H */ 29#endif /* __PERF_QUOTE_H */
diff --git a/tools/perf/util/rb_resort.h b/tools/perf/util/rb_resort.h
new file mode 100644
index 000000000000..abc76e3d3098
--- /dev/null
+++ b/tools/perf/util/rb_resort.h
@@ -0,0 +1,149 @@
1#ifndef _PERF_RESORT_RB_H_
2#define _PERF_RESORT_RB_H_
3/*
4 * Template for creating a class to resort an existing rb_tree according to
5 * a new sort criteria, that must be present in the entries of the source
6 * rb_tree.
7 *
8 * (c) 2016 Arnaldo Carvalho de Melo <acme@redhat.com>
9 *
10 * Quick example, resorting threads by its shortname:
11 *
12 * First define the prefix (threads) to be used for the functions and data
13 * structures created, and provide an expression for the sorting, then the
14 * fields to be present in each of the entries in the new, sorted, rb_tree.
15 *
16 * The body of the init function should collect the fields, maybe
17 * pre-calculating them from multiple entries in the original 'entry' from
18 * the rb_tree used as a source for the entries to be sorted:
19
20DEFINE_RB_RESORT_RB(threads, strcmp(a->thread->shortname,
21 b->thread->shortname) < 0,
22 struct thread *thread;
23)
24{
25 entry->thread = rb_entry(nd, struct thread, rb_node);
26}
27
28 * After this it is just a matter of instantiating it and iterating it,
29 * for a few data structures with existing rb_trees, such as 'struct machine',
30 * helpers are available to get the rb_root and the nr_entries:
31
32 DECLARE_RESORT_RB_MACHINE_THREADS(threads, machine_ptr);
33
34 * This will instantiate the new rb_tree and a cursor for it, that can be used as:
35
36 struct rb_node *nd;
37
38 resort_rb__for_each(nd, threads) {
39 struct thread *t = threads_entry;
40 printf("%s: %d\n", t->shortname, t->tid);
41 }
42
43 * Then delete it:
44
45 resort_rb__delete(threads);
46
47 * The name of the data structures and functions will have a _sorted suffix
48 * right before the method names, i.e. will look like:
49 *
50 * struct threads_sorted_entry {}
51 * threads_sorted__insert()
52 */
53
54#define DEFINE_RESORT_RB(__name, __comp, ...) \
55struct __name##_sorted_entry { \
56 struct rb_node rb_node; \
57 __VA_ARGS__ \
58}; \
59static void __name##_sorted__init_entry(struct rb_node *nd, \
60 struct __name##_sorted_entry *entry); \
61 \
62static int __name##_sorted__cmp(struct rb_node *nda, struct rb_node *ndb) \
63{ \
64 struct __name##_sorted_entry *a, *b; \
65 a = rb_entry(nda, struct __name##_sorted_entry, rb_node); \
66 b = rb_entry(ndb, struct __name##_sorted_entry, rb_node); \
67 return __comp; \
68} \
69 \
70struct __name##_sorted { \
71 struct rb_root entries; \
72 struct __name##_sorted_entry nd[0]; \
73}; \
74 \
75static void __name##_sorted__insert(struct __name##_sorted *sorted, \
76 struct rb_node *sorted_nd) \
77{ \
78 struct rb_node **p = &sorted->entries.rb_node, *parent = NULL; \
79 while (*p != NULL) { \
80 parent = *p; \
81 if (__name##_sorted__cmp(sorted_nd, parent)) \
82 p = &(*p)->rb_left; \
83 else \
84 p = &(*p)->rb_right; \
85 } \
86 rb_link_node(sorted_nd, parent, p); \
87 rb_insert_color(sorted_nd, &sorted->entries); \
88} \
89 \
90static void __name##_sorted__sort(struct __name##_sorted *sorted, \
91 struct rb_root *entries) \
92{ \
93 struct rb_node *nd; \
94 unsigned int i = 0; \
95 for (nd = rb_first(entries); nd; nd = rb_next(nd)) { \
96 struct __name##_sorted_entry *snd = &sorted->nd[i++]; \
97 __name##_sorted__init_entry(nd, snd); \
98 __name##_sorted__insert(sorted, &snd->rb_node); \
99 } \
100} \
101 \
102static struct __name##_sorted *__name##_sorted__new(struct rb_root *entries, \
103 int nr_entries) \
104{ \
105 struct __name##_sorted *sorted; \
106 sorted = malloc(sizeof(*sorted) + sizeof(sorted->nd[0]) * nr_entries); \
107 if (sorted) { \
108 sorted->entries = RB_ROOT; \
109 __name##_sorted__sort(sorted, entries); \
110 } \
111 return sorted; \
112} \
113 \
114static void __name##_sorted__delete(struct __name##_sorted *sorted) \
115{ \
116 free(sorted); \
117} \
118 \
119static void __name##_sorted__init_entry(struct rb_node *nd, \
120 struct __name##_sorted_entry *entry)
121
122#define DECLARE_RESORT_RB(__name) \
123struct __name##_sorted_entry *__name##_entry; \
124struct __name##_sorted *__name = __name##_sorted__new
125
126#define resort_rb__for_each(__nd, __name) \
127 for (__nd = rb_first(&__name->entries); \
128 __name##_entry = rb_entry(__nd, struct __name##_sorted_entry, \
129 rb_node), __nd; \
130 __nd = rb_next(__nd))
131
132#define resort_rb__delete(__name) \
133 __name##_sorted__delete(__name), __name = NULL
134
135/*
136 * Helpers for other classes that contains both an rbtree and the
137 * number of entries in it:
138 */
139
140/* For 'struct intlist' */
141#define DECLARE_RESORT_RB_INTLIST(__name, __ilist) \
142 DECLARE_RESORT_RB(__name)(&__ilist->rblist.entries, \
143 __ilist->rblist.nr_entries)
144
145/* For 'struct machine->threads' */
146#define DECLARE_RESORT_RB_MACHINE_THREADS(__name, __machine) \
147 DECLARE_RESORT_RB(__name)(&__machine->threads, __machine->nr_threads)
148
149#endif /* _PERF_RESORT_RB_H_ */
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 0467367dc315..481792c7484b 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -129,7 +129,8 @@ bool perf_can_record_cpu_wide(void)
129 return true; 129 return true;
130} 130}
131 131
132void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) 132void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
133 struct callchain_param *callchain)
133{ 134{
134 struct perf_evsel *evsel; 135 struct perf_evsel *evsel;
135 bool use_sample_identifier = false; 136 bool use_sample_identifier = false;
@@ -148,7 +149,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
148 use_comm_exec = perf_can_comm_exec(); 149 use_comm_exec = perf_can_comm_exec();
149 150
150 evlist__for_each(evlist, evsel) { 151 evlist__for_each(evlist, evsel) {
151 perf_evsel__config(evsel, opts); 152 perf_evsel__config(evsel, opts, callchain);
152 if (evsel->tracking && use_comm_exec) 153 if (evsel->tracking && use_comm_exec)
153 evsel->attr.comm_exec = 1; 154 evsel->attr.comm_exec = 1;
154 } 155 }
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b3aabc0d4eb0..62c7f6988e0e 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -31,6 +31,8 @@
31#include <perl.h> 31#include <perl.h>
32 32
33#include "../../perf.h" 33#include "../../perf.h"
34#include "../callchain.h"
35#include "../machine.h"
34#include "../thread.h" 36#include "../thread.h"
35#include "../event.h" 37#include "../event.h"
36#include "../trace-event.h" 38#include "../trace-event.h"
@@ -248,10 +250,90 @@ static void define_event_symbols(struct event_format *event,
248 define_event_symbols(event, ev_name, args->next); 250 define_event_symbols(event, ev_name, args->next);
249} 251}
250 252
253static SV *perl_process_callchain(struct perf_sample *sample,
254 struct perf_evsel *evsel,
255 struct addr_location *al)
256{
257 AV *list;
258
259 list = newAV();
260 if (!list)
261 goto exit;
262
263 if (!symbol_conf.use_callchain || !sample->callchain)
264 goto exit;
265
266 if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
267 sample, NULL, NULL,
268 sysctl_perf_event_max_stack) != 0) {
269 pr_err("Failed to resolve callchain. Skipping\n");
270 goto exit;
271 }
272 callchain_cursor_commit(&callchain_cursor);
273
274
275 while (1) {
276 HV *elem;
277 struct callchain_cursor_node *node;
278 node = callchain_cursor_current(&callchain_cursor);
279 if (!node)
280 break;
281
282 elem = newHV();
283 if (!elem)
284 goto exit;
285
286 if (!hv_stores(elem, "ip", newSVuv(node->ip))) {
287 hv_undef(elem);
288 goto exit;
289 }
290
291 if (node->sym) {
292 HV *sym = newHV();
293 if (!sym) {
294 hv_undef(elem);
295 goto exit;
296 }
297 if (!hv_stores(sym, "start", newSVuv(node->sym->start)) ||
298 !hv_stores(sym, "end", newSVuv(node->sym->end)) ||
299 !hv_stores(sym, "binding", newSVuv(node->sym->binding)) ||
300 !hv_stores(sym, "name", newSVpvn(node->sym->name,
301 node->sym->namelen)) ||
302 !hv_stores(elem, "sym", newRV_noinc((SV*)sym))) {
303 hv_undef(sym);
304 hv_undef(elem);
305 goto exit;
306 }
307 }
308
309 if (node->map) {
310 struct map *map = node->map;
311 const char *dsoname = "[unknown]";
312 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
313 if (symbol_conf.show_kernel_path && map->dso->long_name)
314 dsoname = map->dso->long_name;
315 else if (map->dso->name)
316 dsoname = map->dso->name;
317 }
318 if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) {
319 hv_undef(elem);
320 goto exit;
321 }
322 }
323
324 callchain_cursor_advance(&callchain_cursor);
325 av_push(list, newRV_noinc((SV*)elem));
326 }
327
328exit:
329 return newRV_noinc((SV*)list);
330}
331
251static void perl_process_tracepoint(struct perf_sample *sample, 332static void perl_process_tracepoint(struct perf_sample *sample,
252 struct perf_evsel *evsel, 333 struct perf_evsel *evsel,
253 struct thread *thread) 334 struct addr_location *al)
254{ 335{
336 struct thread *thread = al->thread;
255 struct event_format *event = evsel->tp_format; 337 struct event_format *event = evsel->tp_format;
256 struct format_field *field; 338 struct format_field *field;
257 static char handler[256]; 339 static char handler[256];
@@ -295,6 +377,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
295 XPUSHs(sv_2mortal(newSVuv(ns))); 377 XPUSHs(sv_2mortal(newSVuv(ns)));
296 XPUSHs(sv_2mortal(newSViv(pid))); 378 XPUSHs(sv_2mortal(newSViv(pid)));
297 XPUSHs(sv_2mortal(newSVpv(comm, 0))); 379 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
380 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
298 381
299 /* common fields other than pid can be accessed via xsub fns */ 382 /* common fields other than pid can be accessed via xsub fns */
300 383
@@ -329,6 +412,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
329 XPUSHs(sv_2mortal(newSVuv(nsecs))); 412 XPUSHs(sv_2mortal(newSVuv(nsecs)));
330 XPUSHs(sv_2mortal(newSViv(pid))); 413 XPUSHs(sv_2mortal(newSViv(pid)));
331 XPUSHs(sv_2mortal(newSVpv(comm, 0))); 414 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
415 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
332 call_pv("main::trace_unhandled", G_SCALAR); 416 call_pv("main::trace_unhandled", G_SCALAR);
333 } 417 }
334 SPAGAIN; 418 SPAGAIN;
@@ -366,7 +450,7 @@ static void perl_process_event(union perf_event *event,
366 struct perf_evsel *evsel, 450 struct perf_evsel *evsel,
367 struct addr_location *al) 451 struct addr_location *al)
368{ 452{
369 perl_process_tracepoint(sample, evsel, al->thread); 453 perl_process_tracepoint(sample, evsel, al);
370 perl_process_event_generic(event, sample, evsel); 454 perl_process_event_generic(event, sample, evsel);
371} 455}
372 456
@@ -490,7 +574,27 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
490 fprintf(ofp, "use Perf::Trace::Util;\n\n"); 574 fprintf(ofp, "use Perf::Trace::Util;\n\n");
491 575
492 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n"); 576 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
493 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n"); 577 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n");
578
579
580 fprintf(ofp, "\n\
581sub print_backtrace\n\
582{\n\
583 my $callchain = shift;\n\
584 for my $node (@$callchain)\n\
585 {\n\
586 if(exists $node->{sym})\n\
587 {\n\
588 printf( \"\\t[\\%%x] \\%%s\\n\", $node->{ip}, $node->{sym}{name});\n\
589 }\n\
590 else\n\
591 {\n\
592 printf( \"\\t[\\%%x]\\n\", $node{ip});\n\
593 }\n\
594 }\n\
595}\n\n\
596");
597
494 598
495 while ((event = trace_find_next_event(pevent, event))) { 599 while ((event = trace_find_next_event(pevent, event))) {
496 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name); 600 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
@@ -502,7 +606,8 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
502 fprintf(ofp, "$common_secs, "); 606 fprintf(ofp, "$common_secs, ");
503 fprintf(ofp, "$common_nsecs,\n"); 607 fprintf(ofp, "$common_nsecs,\n");
504 fprintf(ofp, "\t $common_pid, "); 608 fprintf(ofp, "\t $common_pid, ");
505 fprintf(ofp, "$common_comm,\n\t "); 609 fprintf(ofp, "$common_comm, ");
610 fprintf(ofp, "$common_callchain,\n\t ");
506 611
507 not_first = 0; 612 not_first = 0;
508 count = 0; 613 count = 0;
@@ -519,7 +624,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
519 624
520 fprintf(ofp, "\tprint_header($event_name, $common_cpu, " 625 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
521 "$common_secs, $common_nsecs,\n\t " 626 "$common_secs, $common_nsecs,\n\t "
522 "$common_pid, $common_comm);\n\n"); 627 "$common_pid, $common_comm, $common_callchain);\n\n");
523 628
524 fprintf(ofp, "\tprintf(\""); 629 fprintf(ofp, "\tprintf(\"");
525 630
@@ -581,17 +686,22 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
581 fprintf(ofp, "$%s", f->name); 686 fprintf(ofp, "$%s", f->name);
582 } 687 }
583 688
584 fprintf(ofp, ");\n"); 689 fprintf(ofp, ");\n\n");
690
691 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
692
585 fprintf(ofp, "}\n\n"); 693 fprintf(ofp, "}\n\n");
586 } 694 }
587 695
588 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, " 696 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "
589 "$common_cpu, $common_secs, $common_nsecs,\n\t " 697 "$common_cpu, $common_secs, $common_nsecs,\n\t "
590 "$common_pid, $common_comm) = @_;\n\n"); 698 "$common_pid, $common_comm, $common_callchain) = @_;\n\n");
591 699
592 fprintf(ofp, "\tprint_header($event_name, $common_cpu, " 700 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
593 "$common_secs, $common_nsecs,\n\t $common_pid, " 701 "$common_secs, $common_nsecs,\n\t $common_pid, "
594 "$common_comm);\n}\n\n"); 702 "$common_comm, $common_callchain);\n");
703 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
704 fprintf(ofp, "}\n\n");
595 705
596 fprintf(ofp, "sub print_header\n{\n" 706 fprintf(ofp, "sub print_header\n{\n"
597 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n" 707 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index fbd05242b4e5..ff134700bf30 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -41,6 +41,7 @@
41#include "../thread-stack.h" 41#include "../thread-stack.h"
42#include "../trace-event.h" 42#include "../trace-event.h"
43#include "../machine.h" 43#include "../machine.h"
44#include "../call-path.h"
44#include "thread_map.h" 45#include "thread_map.h"
45#include "cpumap.h" 46#include "cpumap.h"
46#include "stat.h" 47#include "stat.h"
@@ -323,7 +324,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
323 if (!symbol_conf.use_callchain || !sample->callchain) 324 if (!symbol_conf.use_callchain || !sample->callchain)
324 goto exit; 325 goto exit;
325 326
326 if (thread__resolve_callchain(al->thread, evsel, 327 if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
327 sample, NULL, NULL, 328 sample, NULL, NULL,
328 scripting_max_stack) != 0) { 329 scripting_max_stack) != 0) {
329 pr_err("Failed to resolve callchain. Skipping\n"); 330 pr_err("Failed to resolve callchain. Skipping\n");
@@ -407,8 +408,11 @@ static void python_process_tracepoint(struct perf_sample *sample,
407 if (!t) 408 if (!t)
408 Py_FatalError("couldn't create Python tuple"); 409 Py_FatalError("couldn't create Python tuple");
409 410
410 if (!event) 411 if (!event) {
411 die("ug! no event found for type %d", (int)evsel->attr.config); 412 snprintf(handler_name, sizeof(handler_name),
413 "ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
414 Py_FatalError(handler_name);
415 }
412 416
413 pid = raw_field_value(event, "common_pid", data); 417 pid = raw_field_value(event, "common_pid", data);
414 418
@@ -614,7 +618,7 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso,
614 struct machine *machine) 618 struct machine *machine)
615{ 619{
616 struct tables *tables = container_of(dbe, struct tables, dbe); 620 struct tables *tables = container_of(dbe, struct tables, dbe);
617 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 621 char sbuild_id[SBUILD_ID_SIZE];
618 PyObject *t; 622 PyObject *t;
619 623
620 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 624 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
@@ -681,7 +685,7 @@ static int python_export_sample(struct db_export *dbe,
681 struct tables *tables = container_of(dbe, struct tables, dbe); 685 struct tables *tables = container_of(dbe, struct tables, dbe);
682 PyObject *t; 686 PyObject *t;
683 687
684 t = tuple_new(21); 688 t = tuple_new(22);
685 689
686 tuple_set_u64(t, 0, es->db_id); 690 tuple_set_u64(t, 0, es->db_id);
687 tuple_set_u64(t, 1, es->evsel->db_id); 691 tuple_set_u64(t, 1, es->evsel->db_id);
@@ -704,6 +708,7 @@ static int python_export_sample(struct db_export *dbe,
704 tuple_set_u64(t, 18, es->sample->data_src); 708 tuple_set_u64(t, 18, es->sample->data_src);
705 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); 709 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);
706 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); 710 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));
711 tuple_set_u64(t, 21, es->call_path_id);
707 712
708 call_object(tables->sample_handler, t, "sample_table"); 713 call_object(tables->sample_handler, t, "sample_table");
709 714
@@ -998,8 +1003,10 @@ static void set_table_handlers(struct tables *tables)
998{ 1003{
999 const char *perf_db_export_mode = "perf_db_export_mode"; 1004 const char *perf_db_export_mode = "perf_db_export_mode";
1000 const char *perf_db_export_calls = "perf_db_export_calls"; 1005 const char *perf_db_export_calls = "perf_db_export_calls";
1001 PyObject *db_export_mode, *db_export_calls; 1006 const char *perf_db_export_callchains = "perf_db_export_callchains";
1007 PyObject *db_export_mode, *db_export_calls, *db_export_callchains;
1002 bool export_calls = false; 1008 bool export_calls = false;
1009 bool export_callchains = false;
1003 int ret; 1010 int ret;
1004 1011
1005 memset(tables, 0, sizeof(struct tables)); 1012 memset(tables, 0, sizeof(struct tables));
@@ -1016,6 +1023,7 @@ static void set_table_handlers(struct tables *tables)
1016 if (!ret) 1023 if (!ret)
1017 return; 1024 return;
1018 1025
1026 /* handle export calls */
1019 tables->dbe.crp = NULL; 1027 tables->dbe.crp = NULL;
1020 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); 1028 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);
1021 if (db_export_calls) { 1029 if (db_export_calls) {
@@ -1033,6 +1041,33 @@ static void set_table_handlers(struct tables *tables)
1033 Py_FatalError("failed to create calls processor"); 1041 Py_FatalError("failed to create calls processor");
1034 } 1042 }
1035 1043
1044 /* handle export callchains */
1045 tables->dbe.cpr = NULL;
1046 db_export_callchains = PyDict_GetItemString(main_dict,
1047 perf_db_export_callchains);
1048 if (db_export_callchains) {
1049 ret = PyObject_IsTrue(db_export_callchains);
1050 if (ret == -1)
1051 handler_call_die(perf_db_export_callchains);
1052 export_callchains = !!ret;
1053 }
1054
1055 if (export_callchains) {
1056 /*
1057 * Attempt to use the call path root from the call return
1058 * processor, if the call return processor is in use. Otherwise,
1059 * we allocate a new call path root. This prevents exporting
1060 * duplicate call path ids when both are in use simultaniously.
1061 */
1062 if (tables->dbe.crp)
1063 tables->dbe.cpr = tables->dbe.crp->cpr;
1064 else
1065 tables->dbe.cpr = call_path_root__new();
1066
1067 if (!tables->dbe.cpr)
1068 Py_FatalError("failed to create call path root");
1069 }
1070
1036 tables->db_export_mode = true; 1071 tables->db_export_mode = true;
1037 /* 1072 /*
1038 * Reserve per symbol space for symbol->db_id via symbol__priv() 1073 * Reserve per symbol space for symbol->db_id via symbol__priv()
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 4abd85c6346d..5214974e841a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -409,6 +409,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
409 tool->stat = process_stat_stub; 409 tool->stat = process_stat_stub;
410 if (tool->stat_round == NULL) 410 if (tool->stat_round == NULL)
411 tool->stat_round = process_stat_round_stub; 411 tool->stat_round = process_stat_round_stub;
412 if (tool->time_conv == NULL)
413 tool->time_conv = process_event_op2_stub;
412} 414}
413 415
414static void swap_sample_id_all(union perf_event *event, void *data) 416static void swap_sample_id_all(union perf_event *event, void *data)
@@ -555,7 +557,7 @@ static u8 revbyte(u8 b)
555 557
556/* 558/*
557 * XXX this is hack in attempt to carry flags bitfield 559 * XXX this is hack in attempt to carry flags bitfield
558 * throught endian village. ABI says: 560 * through endian village. ABI says:
559 * 561 *
560 * Bit-fields are allocated from right to left (least to most significant) 562 * Bit-fields are allocated from right to left (least to most significant)
561 * on little-endian implementations and from left to right (most to least 563 * on little-endian implementations and from left to right (most to least
@@ -794,6 +796,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
794 [PERF_RECORD_STAT] = perf_event__stat_swap, 796 [PERF_RECORD_STAT] = perf_event__stat_swap,
795 [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, 797 [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap,
796 [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, 798 [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap,
799 [PERF_RECORD_TIME_CONV] = perf_event__all64_swap,
797 [PERF_RECORD_HEADER_MAX] = NULL, 800 [PERF_RECORD_HEADER_MAX] = NULL,
798}; 801};
799 802
@@ -904,7 +907,7 @@ static void callchain__printf(struct perf_evsel *evsel,
904 unsigned int i; 907 unsigned int i;
905 struct ip_callchain *callchain = sample->callchain; 908 struct ip_callchain *callchain = sample->callchain;
906 909
907 if (has_branch_callstack(evsel)) 910 if (perf_evsel__has_branch_callstack(evsel))
908 callchain__lbr_callstack_printf(sample); 911 callchain__lbr_callstack_printf(sample);
909 912
910 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr); 913 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);
@@ -1078,7 +1081,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1078 if (sample_type & PERF_SAMPLE_CALLCHAIN) 1081 if (sample_type & PERF_SAMPLE_CALLCHAIN)
1079 callchain__printf(evsel, sample); 1082 callchain__printf(evsel, sample);
1080 1083
1081 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !has_branch_callstack(evsel)) 1084 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !perf_evsel__has_branch_callstack(evsel))
1082 branch_stack__printf(sample); 1085 branch_stack__printf(sample);
1083 1086
1084 if (sample_type & PERF_SAMPLE_REGS_USER) 1087 if (sample_type & PERF_SAMPLE_REGS_USER)
@@ -1341,6 +1344,9 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1341 return tool->stat(tool, event, session); 1344 return tool->stat(tool, event, session);
1342 case PERF_RECORD_STAT_ROUND: 1345 case PERF_RECORD_STAT_ROUND:
1343 return tool->stat_round(tool, event, session); 1346 return tool->stat_round(tool, event, session);
1347 case PERF_RECORD_TIME_CONV:
1348 session->time_conv = event->time_conv;
1349 return tool->time_conv(tool, event, session);
1344 default: 1350 default:
1345 return -EINVAL; 1351 return -EINVAL;
1346 } 1352 }
@@ -1830,7 +1836,11 @@ out:
1830out_err: 1836out_err:
1831 ui_progress__finish(); 1837 ui_progress__finish();
1832 perf_session__warn_about_errors(session); 1838 perf_session__warn_about_errors(session);
1833 ordered_events__free(&session->ordered_events); 1839 /*
1840 * We may switching perf.data output, make ordered_events
1841 * reusable.
1842 */
1843 ordered_events__reinit(&session->ordered_events);
1834 auxtrace__free_events(session); 1844 auxtrace__free_events(session);
1835 session->one_mmap = false; 1845 session->one_mmap = false;
1836 return err; 1846 return err;
@@ -1947,105 +1957,6 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1947 return NULL; 1957 return NULL;
1948} 1958}
1949 1959
1950void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1951 struct addr_location *al,
1952 unsigned int print_opts, unsigned int stack_depth)
1953{
1954 struct callchain_cursor_node *node;
1955 int print_ip = print_opts & PRINT_IP_OPT_IP;
1956 int print_sym = print_opts & PRINT_IP_OPT_SYM;
1957 int print_dso = print_opts & PRINT_IP_OPT_DSO;
1958 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
1959 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
1960 int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
1961 char s = print_oneline ? ' ' : '\t';
1962
1963 if (symbol_conf.use_callchain && sample->callchain) {
1964 struct addr_location node_al;
1965
1966 if (thread__resolve_callchain(al->thread, evsel,
1967 sample, NULL, NULL,
1968 stack_depth) != 0) {
1969 if (verbose)
1970 error("Failed to resolve callchain. Skipping\n");
1971 return;
1972 }
1973 callchain_cursor_commit(&callchain_cursor);
1974
1975 if (print_symoffset)
1976 node_al = *al;
1977
1978 while (stack_depth) {
1979 u64 addr = 0;
1980
1981 node = callchain_cursor_current(&callchain_cursor);
1982 if (!node)
1983 break;
1984
1985 if (node->sym && node->sym->ignore)
1986 goto next;
1987
1988 if (print_ip)
1989 printf("%c%16" PRIx64, s, node->ip);
1990
1991 if (node->map)
1992 addr = node->map->map_ip(node->map, node->ip);
1993
1994 if (print_sym) {
1995 printf(" ");
1996 if (print_symoffset) {
1997 node_al.addr = addr;
1998 node_al.map = node->map;
1999 symbol__fprintf_symname_offs(node->sym, &node_al, stdout);
2000 } else
2001 symbol__fprintf_symname(node->sym, stdout);
2002 }
2003
2004 if (print_dso) {
2005 printf(" (");
2006 map__fprintf_dsoname(node->map, stdout);
2007 printf(")");
2008 }
2009
2010 if (print_srcline)
2011 map__fprintf_srcline(node->map, addr, "\n ",
2012 stdout);
2013
2014 if (!print_oneline)
2015 printf("\n");
2016
2017 stack_depth--;
2018next:
2019 callchain_cursor_advance(&callchain_cursor);
2020 }
2021
2022 } else {
2023 if (al->sym && al->sym->ignore)
2024 return;
2025
2026 if (print_ip)
2027 printf("%16" PRIx64, sample->ip);
2028
2029 if (print_sym) {
2030 printf(" ");
2031 if (print_symoffset)
2032 symbol__fprintf_symname_offs(al->sym, al,
2033 stdout);
2034 else
2035 symbol__fprintf_symname(al->sym, stdout);
2036 }
2037
2038 if (print_dso) {
2039 printf(" (");
2040 map__fprintf_dsoname(al->map, stdout);
2041 printf(")");
2042 }
2043
2044 if (print_srcline)
2045 map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
2046 }
2047}
2048
2049int perf_session__cpu_bitmap(struct perf_session *session, 1960int perf_session__cpu_bitmap(struct perf_session *session,
2050 const char *cpu_list, unsigned long *cpu_bitmap) 1961 const char *cpu_list, unsigned long *cpu_bitmap)
2051{ 1962{
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 5f792e35d4c1..4bd758553450 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -26,6 +26,7 @@ struct perf_session {
26 struct itrace_synth_opts *itrace_synth_opts; 26 struct itrace_synth_opts *itrace_synth_opts;
27 struct list_head auxtrace_index; 27 struct list_head auxtrace_index;
28 struct trace_event tevent; 28 struct trace_event tevent;
29 struct time_conv_event time_conv;
29 bool repipe; 30 bool repipe;
30 bool one_mmap; 31 bool one_mmap;
31 void *one_mmap_addr; 32 void *one_mmap_addr;
@@ -35,13 +36,6 @@ struct perf_session {
35 struct perf_tool *tool; 36 struct perf_tool *tool;
36}; 37};
37 38
38#define PRINT_IP_OPT_IP (1<<0)
39#define PRINT_IP_OPT_SYM (1<<1)
40#define PRINT_IP_OPT_DSO (1<<2)
41#define PRINT_IP_OPT_SYMOFFSET (1<<3)
42#define PRINT_IP_OPT_ONELINE (1<<4)
43#define PRINT_IP_OPT_SRCLINE (1<<5)
44
45struct perf_tool; 39struct perf_tool;
46 40
47struct perf_session *perf_session__new(struct perf_data_file *file, 41struct perf_session *perf_session__new(struct perf_data_file *file,
@@ -103,10 +97,6 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
103struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 97struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
104 unsigned int type); 98 unsigned int type);
105 99
106void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
107 struct addr_location *al,
108 unsigned int print_opts, unsigned int stack_depth);
109
110int perf_session__cpu_bitmap(struct perf_session *session, 100int perf_session__cpu_bitmap(struct perf_session *session,
111 const char *cpu_list, unsigned long *cpu_bitmap); 101 const char *cpu_list, unsigned long *cpu_bitmap);
112 102
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 47966a1618c7..20e69edd5006 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -21,13 +21,6 @@ const char *sort_order;
21const char *field_order; 21const char *field_order;
22regex_t ignore_callees_regex; 22regex_t ignore_callees_regex;
23int have_ignore_callees = 0; 23int have_ignore_callees = 0;
24int sort__need_collapse = 0;
25int sort__has_parent = 0;
26int sort__has_sym = 0;
27int sort__has_dso = 0;
28int sort__has_socket = 0;
29int sort__has_thread = 0;
30int sort__has_comm = 0;
31enum sort_mode sort__mode = SORT_MODE__NORMAL; 24enum sort_mode sort__mode = SORT_MODE__NORMAL;
32 25
33/* 26/*
@@ -244,7 +237,7 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
244 * comparing symbol address alone is not enough since it's a 237 * comparing symbol address alone is not enough since it's a
245 * relative address within a dso. 238 * relative address within a dso.
246 */ 239 */
247 if (!sort__has_dso) { 240 if (!hists__has(left->hists, dso) || hists__has(right->hists, dso)) {
248 ret = sort__dso_cmp(left, right); 241 ret = sort__dso_cmp(left, right);
249 if (ret != 0) 242 if (ret != 0)
250 return ret; 243 return ret;
@@ -2163,7 +2156,7 @@ static int __sort_dimension__add(struct sort_dimension *sd,
2163 return -1; 2156 return -1;
2164 2157
2165 if (sd->entry->se_collapse) 2158 if (sd->entry->se_collapse)
2166 sort__need_collapse = 1; 2159 list->need_collapse = 1;
2167 2160
2168 sd->taken = 1; 2161 sd->taken = 1;
2169 2162
@@ -2245,9 +2238,9 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2245 pr_err("Invalid regex: %s\n%s", parent_pattern, err); 2238 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
2246 return -EINVAL; 2239 return -EINVAL;
2247 } 2240 }
2248 sort__has_parent = 1; 2241 list->parent = 1;
2249 } else if (sd->entry == &sort_sym) { 2242 } else if (sd->entry == &sort_sym) {
2250 sort__has_sym = 1; 2243 list->sym = 1;
2251 /* 2244 /*
2252 * perf diff displays the performance difference amongst 2245 * perf diff displays the performance difference amongst
2253 * two or more perf.data files. Those files could come 2246 * two or more perf.data files. Those files could come
@@ -2258,13 +2251,13 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2258 sd->entry->se_collapse = sort__sym_sort; 2251 sd->entry->se_collapse = sort__sym_sort;
2259 2252
2260 } else if (sd->entry == &sort_dso) { 2253 } else if (sd->entry == &sort_dso) {
2261 sort__has_dso = 1; 2254 list->dso = 1;
2262 } else if (sd->entry == &sort_socket) { 2255 } else if (sd->entry == &sort_socket) {
2263 sort__has_socket = 1; 2256 list->socket = 1;
2264 } else if (sd->entry == &sort_thread) { 2257 } else if (sd->entry == &sort_thread) {
2265 sort__has_thread = 1; 2258 list->thread = 1;
2266 } else if (sd->entry == &sort_comm) { 2259 } else if (sd->entry == &sort_comm) {
2267 sort__has_comm = 1; 2260 list->comm = 1;
2268 } 2261 }
2269 2262
2270 return __sort_dimension__add(sd, list, level); 2263 return __sort_dimension__add(sd, list, level);
@@ -2289,7 +2282,7 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2289 return -EINVAL; 2282 return -EINVAL;
2290 2283
2291 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) 2284 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
2292 sort__has_sym = 1; 2285 list->sym = 1;
2293 2286
2294 __sort_dimension__add(sd, list, level); 2287 __sort_dimension__add(sd, list, level);
2295 return 0; 2288 return 0;
@@ -2305,7 +2298,7 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2305 return -EINVAL; 2298 return -EINVAL;
2306 2299
2307 if (sd->entry == &sort_mem_daddr_sym) 2300 if (sd->entry == &sort_mem_daddr_sym)
2308 sort__has_sym = 1; 2301 list->sym = 1;
2309 2302
2310 __sort_dimension__add(sd, list, level); 2303 __sort_dimension__add(sd, list, level);
2311 return 0; 2304 return 0;
@@ -2445,6 +2438,9 @@ static char *prefix_if_not_in(const char *pre, char *str)
2445 2438
2446static char *setup_overhead(char *keys) 2439static char *setup_overhead(char *keys)
2447{ 2440{
2441 if (sort__mode == SORT_MODE__DIFF)
2442 return keys;
2443
2448 keys = prefix_if_not_in("overhead", keys); 2444 keys = prefix_if_not_in("overhead", keys);
2449 2445
2450 if (symbol_conf.cumulate_callchain) 2446 if (symbol_conf.cumulate_callchain)
@@ -2746,10 +2742,10 @@ int setup_sorting(struct perf_evlist *evlist)
2746 2742
2747void reset_output_field(void) 2743void reset_output_field(void)
2748{ 2744{
2749 sort__need_collapse = 0; 2745 perf_hpp_list.need_collapse = 0;
2750 sort__has_parent = 0; 2746 perf_hpp_list.parent = 0;
2751 sort__has_sym = 0; 2747 perf_hpp_list.sym = 0;
2752 sort__has_dso = 0; 2748 perf_hpp_list.dso = 0;
2753 2749
2754 field_order = NULL; 2750 field_order = NULL;
2755 sort_order = NULL; 2751 sort_order = NULL;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 3f4e35998119..42927f448bcb 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -31,13 +31,6 @@ extern const char *parent_pattern;
31extern const char default_sort_order[]; 31extern const char default_sort_order[];
32extern regex_t ignore_callees_regex; 32extern regex_t ignore_callees_regex;
33extern int have_ignore_callees; 33extern int have_ignore_callees;
34extern int sort__need_collapse;
35extern int sort__has_dso;
36extern int sort__has_parent;
37extern int sort__has_sym;
38extern int sort__has_socket;
39extern int sort__has_thread;
40extern int sort__has_comm;
41extern enum sort_mode sort__mode; 34extern enum sort_mode sort__mode;
42extern struct sort_entry sort_comm; 35extern struct sort_entry sort_comm;
43extern struct sort_entry sort_dso; 36extern struct sort_entry sort_dso;
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 4d9b481cf3b6..ffa1d0653861 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -307,6 +307,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
307 struct perf_counts_values *aggr = &counter->counts->aggr; 307 struct perf_counts_values *aggr = &counter->counts->aggr;
308 struct perf_stat_evsel *ps = counter->priv; 308 struct perf_stat_evsel *ps = counter->priv;
309 u64 *count = counter->counts->aggr.values; 309 u64 *count = counter->counts->aggr.values;
310 u64 val;
310 int i, ret; 311 int i, ret;
311 312
312 aggr->val = aggr->ena = aggr->run = 0; 313 aggr->val = aggr->ena = aggr->run = 0;
@@ -346,7 +347,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
346 /* 347 /*
347 * Save the full runtime - to allow normalization during printout: 348 * Save the full runtime - to allow normalization during printout:
348 */ 349 */
349 perf_stat__update_shadow_stats(counter, count, 0); 350 val = counter->scale * *count;
351 perf_stat__update_shadow_stats(counter, &val, 0);
350 352
351 return 0; 353 return 0;
352} 354}
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 8fb73295ec34..f95f682aa2b2 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -1,3 +1,4 @@
1#include "debug.h"
1#include "cache.h" 2#include "cache.h"
2#include <linux/kernel.h> 3#include <linux/kernel.h>
3 4
@@ -17,12 +18,13 @@ int prefixcmp(const char *str, const char *prefix)
17 */ 18 */
18char strbuf_slopbuf[1]; 19char strbuf_slopbuf[1];
19 20
20void strbuf_init(struct strbuf *sb, ssize_t hint) 21int strbuf_init(struct strbuf *sb, ssize_t hint)
21{ 22{
22 sb->alloc = sb->len = 0; 23 sb->alloc = sb->len = 0;
23 sb->buf = strbuf_slopbuf; 24 sb->buf = strbuf_slopbuf;
24 if (hint) 25 if (hint)
25 strbuf_grow(sb, hint); 26 return strbuf_grow(sb, hint);
27 return 0;
26} 28}
27 29
28void strbuf_release(struct strbuf *sb) 30void strbuf_release(struct strbuf *sb)
@@ -42,67 +44,104 @@ char *strbuf_detach(struct strbuf *sb, size_t *sz)
42 return res; 44 return res;
43} 45}
44 46
45void strbuf_grow(struct strbuf *sb, size_t extra) 47int strbuf_grow(struct strbuf *sb, size_t extra)
46{ 48{
47 if (sb->len + extra + 1 <= sb->len) 49 char *buf;
48 die("you want to use way too much memory"); 50 size_t nr = sb->len + extra + 1;
49 if (!sb->alloc) 51
50 sb->buf = NULL; 52 if (nr < sb->alloc)
51 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); 53 return 0;
54
55 if (nr <= sb->len)
56 return -E2BIG;
57
58 if (alloc_nr(sb->alloc) > nr)
59 nr = alloc_nr(sb->alloc);
60
61 /*
62 * Note that sb->buf == strbuf_slopbuf if sb->alloc == 0, and it is
63 * a static variable. Thus we have to avoid passing it to realloc.
64 */
65 buf = realloc(sb->alloc ? sb->buf : NULL, nr * sizeof(*buf));
66 if (!buf)
67 return -ENOMEM;
68
69 sb->buf = buf;
70 sb->alloc = nr;
71 return 0;
52} 72}
53 73
54void strbuf_addch(struct strbuf *sb, int c) 74int strbuf_addch(struct strbuf *sb, int c)
55{ 75{
56 strbuf_grow(sb, 1); 76 int ret = strbuf_grow(sb, 1);
77 if (ret)
78 return ret;
79
57 sb->buf[sb->len++] = c; 80 sb->buf[sb->len++] = c;
58 sb->buf[sb->len] = '\0'; 81 sb->buf[sb->len] = '\0';
82 return 0;
59} 83}
60 84
61void strbuf_add(struct strbuf *sb, const void *data, size_t len) 85int strbuf_add(struct strbuf *sb, const void *data, size_t len)
62{ 86{
63 strbuf_grow(sb, len); 87 int ret = strbuf_grow(sb, len);
88 if (ret)
89 return ret;
90
64 memcpy(sb->buf + sb->len, data, len); 91 memcpy(sb->buf + sb->len, data, len);
65 strbuf_setlen(sb, sb->len + len); 92 return strbuf_setlen(sb, sb->len + len);
66} 93}
67 94
68static void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) 95static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
69{ 96{
70 int len; 97 int len, ret;
71 va_list ap_saved; 98 va_list ap_saved;
72 99
73 if (!strbuf_avail(sb)) 100 if (!strbuf_avail(sb)) {
74 strbuf_grow(sb, 64); 101 ret = strbuf_grow(sb, 64);
102 if (ret)
103 return ret;
104 }
75 105
76 va_copy(ap_saved, ap); 106 va_copy(ap_saved, ap);
77 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap); 107 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
78 if (len < 0) 108 if (len < 0)
79 die("your vsnprintf is broken"); 109 return len;
80 if (len > strbuf_avail(sb)) { 110 if (len > strbuf_avail(sb)) {
81 strbuf_grow(sb, len); 111 ret = strbuf_grow(sb, len);
112 if (ret)
113 return ret;
82 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); 114 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
83 va_end(ap_saved); 115 va_end(ap_saved);
84 if (len > strbuf_avail(sb)) { 116 if (len > strbuf_avail(sb)) {
85 die("this should not happen, your vsnprintf is broken"); 117 pr_debug("this should not happen, your vsnprintf is broken");
118 return -EINVAL;
86 } 119 }
87 } 120 }
88 strbuf_setlen(sb, sb->len + len); 121 return strbuf_setlen(sb, sb->len + len);
89} 122}
90 123
91void strbuf_addf(struct strbuf *sb, const char *fmt, ...) 124int strbuf_addf(struct strbuf *sb, const char *fmt, ...)
92{ 125{
93 va_list ap; 126 va_list ap;
127 int ret;
94 128
95 va_start(ap, fmt); 129 va_start(ap, fmt);
96 strbuf_addv(sb, fmt, ap); 130 ret = strbuf_addv(sb, fmt, ap);
97 va_end(ap); 131 va_end(ap);
132 return ret;
98} 133}
99 134
100ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) 135ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
101{ 136{
102 size_t oldlen = sb->len; 137 size_t oldlen = sb->len;
103 size_t oldalloc = sb->alloc; 138 size_t oldalloc = sb->alloc;
139 int ret;
140
141 ret = strbuf_grow(sb, hint ? hint : 8192);
142 if (ret)
143 return ret;
104 144
105 strbuf_grow(sb, hint ? hint : 8192);
106 for (;;) { 145 for (;;) {
107 ssize_t cnt; 146 ssize_t cnt;
108 147
@@ -112,12 +151,14 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
112 strbuf_release(sb); 151 strbuf_release(sb);
113 else 152 else
114 strbuf_setlen(sb, oldlen); 153 strbuf_setlen(sb, oldlen);
115 return -1; 154 return cnt;
116 } 155 }
117 if (!cnt) 156 if (!cnt)
118 break; 157 break;
119 sb->len += cnt; 158 sb->len += cnt;
120 strbuf_grow(sb, 8192); 159 ret = strbuf_grow(sb, 8192);
160 if (ret)
161 return ret;
121 } 162 }
122 163
123 sb->buf[sb->len] = '\0'; 164 sb->buf[sb->len] = '\0';
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index ab9be0fbbd40..54b409297d4a 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -51,7 +51,7 @@ struct strbuf {
51#define STRBUF_INIT { 0, 0, strbuf_slopbuf } 51#define STRBUF_INIT { 0, 0, strbuf_slopbuf }
52 52
53/*----- strbuf life cycle -----*/ 53/*----- strbuf life cycle -----*/
54void strbuf_init(struct strbuf *buf, ssize_t hint); 54int strbuf_init(struct strbuf *buf, ssize_t hint);
55void strbuf_release(struct strbuf *buf); 55void strbuf_release(struct strbuf *buf);
56char *strbuf_detach(struct strbuf *buf, size_t *); 56char *strbuf_detach(struct strbuf *buf, size_t *);
57 57
@@ -60,26 +60,31 @@ static inline ssize_t strbuf_avail(const struct strbuf *sb) {
60 return sb->alloc ? sb->alloc - sb->len - 1 : 0; 60 return sb->alloc ? sb->alloc - sb->len - 1 : 0;
61} 61}
62 62
63void strbuf_grow(struct strbuf *buf, size_t); 63int strbuf_grow(struct strbuf *buf, size_t);
64 64
65static inline void strbuf_setlen(struct strbuf *sb, size_t len) { 65static inline int strbuf_setlen(struct strbuf *sb, size_t len) {
66 if (!sb->alloc) 66 int ret;
67 strbuf_grow(sb, 0); 67 if (!sb->alloc) {
68 ret = strbuf_grow(sb, 0);
69 if (ret)
70 return ret;
71 }
68 assert(len < sb->alloc); 72 assert(len < sb->alloc);
69 sb->len = len; 73 sb->len = len;
70 sb->buf[len] = '\0'; 74 sb->buf[len] = '\0';
75 return 0;
71} 76}
72 77
73/*----- add data in your buffer -----*/ 78/*----- add data in your buffer -----*/
74void strbuf_addch(struct strbuf *sb, int c); 79int strbuf_addch(struct strbuf *sb, int c);
75 80
76void strbuf_add(struct strbuf *buf, const void *, size_t); 81int strbuf_add(struct strbuf *buf, const void *, size_t);
77static inline void strbuf_addstr(struct strbuf *sb, const char *s) { 82static inline int strbuf_addstr(struct strbuf *sb, const char *s) {
78 strbuf_add(sb, s, strlen(s)); 83 return strbuf_add(sb, s, strlen(s));
79} 84}
80 85
81__attribute__((format(printf,2,3))) 86__attribute__((format(printf,2,3)))
82void strbuf_addf(struct strbuf *sb, const char *fmt, ...); 87int strbuf_addf(struct strbuf *sb, const char *fmt, ...);
83 88
84/* XXX: if read fails, any partial read is undone */ 89/* XXX: if read fails, any partial read is undone */
85ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); 90ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index bc229a74c6a9..87a297dd8901 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -709,17 +709,10 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
709 if (ss->opdshdr.sh_type != SHT_PROGBITS) 709 if (ss->opdshdr.sh_type != SHT_PROGBITS)
710 ss->opdsec = NULL; 710 ss->opdsec = NULL;
711 711
712 if (dso->kernel == DSO_TYPE_USER) { 712 if (dso->kernel == DSO_TYPE_USER)
713 GElf_Shdr shdr; 713 ss->adjust_symbols = true;
714 ss->adjust_symbols = (ehdr.e_type == ET_EXEC || 714 else
715 ehdr.e_type == ET_REL ||
716 dso__is_vdso(dso) ||
717 elf_section_by_name(elf, &ehdr, &shdr,
718 ".gnu.prelink_undo",
719 NULL) != NULL);
720 } else {
721 ss->adjust_symbols = elf__needs_adjust_symbols(ehdr); 715 ss->adjust_symbols = elf__needs_adjust_symbols(ehdr);
722 }
723 716
724 ss->name = strdup(name); 717 ss->name = strdup(name);
725 if (!ss->name) { 718 if (!ss->name) {
@@ -777,7 +770,8 @@ static bool want_demangle(bool is_kernel_sym)
777 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle; 770 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
778} 771}
779 772
780void __weak arch__elf_sym_adjust(GElf_Sym *sym __maybe_unused) { } 773void __weak arch__sym_update(struct symbol *s __maybe_unused,
774 GElf_Sym *sym __maybe_unused) { }
781 775
782int dso__load_sym(struct dso *dso, struct map *map, 776int dso__load_sym(struct dso *dso, struct map *map,
783 struct symsrc *syms_ss, struct symsrc *runtime_ss, 777 struct symsrc *syms_ss, struct symsrc *runtime_ss,
@@ -954,8 +948,6 @@ int dso__load_sym(struct dso *dso, struct map *map,
954 (sym.st_value & 1)) 948 (sym.st_value & 1))
955 --sym.st_value; 949 --sym.st_value;
956 950
957 arch__elf_sym_adjust(&sym);
958
959 if (dso->kernel || kmodule) { 951 if (dso->kernel || kmodule) {
960 char dso_name[PATH_MAX]; 952 char dso_name[PATH_MAX];
961 953
@@ -1089,6 +1081,8 @@ new_symbol:
1089 if (!f) 1081 if (!f)
1090 goto out_elf_end; 1082 goto out_elf_end;
1091 1083
1084 arch__sym_update(f, &sym);
1085
1092 if (filter && filter(curr_map, f)) 1086 if (filter && filter(curr_map, f))
1093 symbol__delete(f); 1087 symbol__delete(f);
1094 else { 1088 else {
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e7588dc91518..7fb33304fb4e 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -255,40 +255,6 @@ void symbol__delete(struct symbol *sym)
255 free(((void *)sym) - symbol_conf.priv_size); 255 free(((void *)sym) - symbol_conf.priv_size);
256} 256}
257 257
258size_t symbol__fprintf(struct symbol *sym, FILE *fp)
259{
260 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
261 sym->start, sym->end,
262 sym->binding == STB_GLOBAL ? 'g' :
263 sym->binding == STB_LOCAL ? 'l' : 'w',
264 sym->name);
265}
266
267size_t symbol__fprintf_symname_offs(const struct symbol *sym,
268 const struct addr_location *al, FILE *fp)
269{
270 unsigned long offset;
271 size_t length;
272
273 if (sym && sym->name) {
274 length = fprintf(fp, "%s", sym->name);
275 if (al) {
276 if (al->addr < sym->end)
277 offset = al->addr - sym->start;
278 else
279 offset = al->addr - al->map->start - sym->start;
280 length += fprintf(fp, "+0x%lx", offset);
281 }
282 return length;
283 } else
284 return fprintf(fp, "[unknown]");
285}
286
287size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
288{
289 return symbol__fprintf_symname_offs(sym, NULL, fp);
290}
291
292void symbols__delete(struct rb_root *symbols) 258void symbols__delete(struct rb_root *symbols)
293{ 259{
294 struct symbol *pos; 260 struct symbol *pos;
@@ -335,7 +301,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
335 301
336 if (ip < s->start) 302 if (ip < s->start)
337 n = n->rb_left; 303 n = n->rb_left;
338 else if (ip >= s->end) 304 else if (ip > s->end || (ip == s->end && ip != s->start))
339 n = n->rb_right; 305 n = n->rb_right;
340 else 306 else
341 return s; 307 return s;
@@ -364,11 +330,6 @@ static struct symbol *symbols__next(struct symbol *sym)
364 return NULL; 330 return NULL;
365} 331}
366 332
367struct symbol_name_rb_node {
368 struct rb_node rb_node;
369 struct symbol sym;
370};
371
372static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym) 333static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym)
373{ 334{
374 struct rb_node **p = &symbols->rb_node; 335 struct rb_node **p = &symbols->rb_node;
@@ -452,6 +413,18 @@ void dso__reset_find_symbol_cache(struct dso *dso)
452 } 413 }
453} 414}
454 415
416void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym)
417{
418 symbols__insert(&dso->symbols[type], sym);
419
420 /* update the symbol cache if necessary */
421 if (dso->last_find_result[type].addr >= sym->start &&
422 (dso->last_find_result[type].addr < sym->end ||
423 sym->start == sym->end)) {
424 dso->last_find_result[type].symbol = sym;
425 }
426}
427
455struct symbol *dso__find_symbol(struct dso *dso, 428struct symbol *dso__find_symbol(struct dso *dso,
456 enum map_type type, u64 addr) 429 enum map_type type, u64 addr)
457{ 430{
@@ -497,21 +470,6 @@ void dso__sort_by_name(struct dso *dso, enum map_type type)
497 &dso->symbols[type]); 470 &dso->symbols[type]);
498} 471}
499 472
500size_t dso__fprintf_symbols_by_name(struct dso *dso,
501 enum map_type type, FILE *fp)
502{
503 size_t ret = 0;
504 struct rb_node *nd;
505 struct symbol_name_rb_node *pos;
506
507 for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) {
508 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
509 fprintf(fp, "%s\n", pos->sym.name);
510 }
511
512 return ret;
513}
514
515int modules__parse(const char *filename, void *arg, 473int modules__parse(const char *filename, void *arg,
516 int (*process_module)(void *arg, const char *name, 474 int (*process_module)(void *arg, const char *name,
517 u64 start)) 475 u64 start))
@@ -1262,8 +1220,8 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1262 return 0; 1220 return 0;
1263} 1221}
1264 1222
1265int dso__load_kallsyms(struct dso *dso, const char *filename, 1223int __dso__load_kallsyms(struct dso *dso, const char *filename,
1266 struct map *map, symbol_filter_t filter) 1224 struct map *map, bool no_kcore, symbol_filter_t filter)
1267{ 1225{
1268 u64 delta = 0; 1226 u64 delta = 0;
1269 1227
@@ -1284,12 +1242,18 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
1284 else 1242 else
1285 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; 1243 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
1286 1244
1287 if (!dso__load_kcore(dso, map, filename)) 1245 if (!no_kcore && !dso__load_kcore(dso, map, filename))
1288 return dso__split_kallsyms_for_kcore(dso, map, filter); 1246 return dso__split_kallsyms_for_kcore(dso, map, filter);
1289 else 1247 else
1290 return dso__split_kallsyms(dso, map, delta, filter); 1248 return dso__split_kallsyms(dso, map, delta, filter);
1291} 1249}
1292 1250
1251int dso__load_kallsyms(struct dso *dso, const char *filename,
1252 struct map *map, symbol_filter_t filter)
1253{
1254 return __dso__load_kallsyms(dso, filename, map, false, filter);
1255}
1256
1293static int dso__load_perf_map(struct dso *dso, struct map *map, 1257static int dso__load_perf_map(struct dso *dso, struct map *map,
1294 symbol_filter_t filter) 1258 symbol_filter_t filter)
1295{ 1259{
@@ -1644,25 +1608,27 @@ out:
1644 return err; 1608 return err;
1645} 1609}
1646 1610
1611static bool visible_dir_filter(const char *name, struct dirent *d)
1612{
1613 if (d->d_type != DT_DIR)
1614 return false;
1615 return lsdir_no_dot_filter(name, d);
1616}
1617
1647static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz) 1618static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1648{ 1619{
1649 char kallsyms_filename[PATH_MAX]; 1620 char kallsyms_filename[PATH_MAX];
1650 struct dirent *dent;
1651 int ret = -1; 1621 int ret = -1;
1652 DIR *d; 1622 struct strlist *dirs;
1623 struct str_node *nd;
1653 1624
1654 d = opendir(dir); 1625 dirs = lsdir(dir, visible_dir_filter);
1655 if (!d) 1626 if (!dirs)
1656 return -1; 1627 return -1;
1657 1628
1658 while (1) { 1629 strlist__for_each(nd, dirs) {
1659 dent = readdir(d);
1660 if (!dent)
1661 break;
1662 if (dent->d_type != DT_DIR)
1663 continue;
1664 scnprintf(kallsyms_filename, sizeof(kallsyms_filename), 1630 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
1665 "%s/%s/kallsyms", dir, dent->d_name); 1631 "%s/%s/kallsyms", dir, nd->s);
1666 if (!validate_kcore_addresses(kallsyms_filename, map)) { 1632 if (!validate_kcore_addresses(kallsyms_filename, map)) {
1667 strlcpy(dir, kallsyms_filename, dir_sz); 1633 strlcpy(dir, kallsyms_filename, dir_sz);
1668 ret = 0; 1634 ret = 0;
@@ -1670,7 +1636,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1670 } 1636 }
1671 } 1637 }
1672 1638
1673 closedir(d); 1639 strlist__delete(dirs);
1674 1640
1675 return ret; 1641 return ret;
1676} 1642}
@@ -1678,7 +1644,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1678static char *dso__find_kallsyms(struct dso *dso, struct map *map) 1644static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1679{ 1645{
1680 u8 host_build_id[BUILD_ID_SIZE]; 1646 u8 host_build_id[BUILD_ID_SIZE];
1681 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1647 char sbuild_id[SBUILD_ID_SIZE];
1682 bool is_host = false; 1648 bool is_host = false;
1683 char path[PATH_MAX]; 1649 char path[PATH_MAX];
1684 1650
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index c8b7544d9267..2b5e4ed76fcb 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -55,6 +55,7 @@ struct symbol {
55 u16 namelen; 55 u16 namelen;
56 u8 binding; 56 u8 binding;
57 bool ignore; 57 bool ignore;
58 u8 arch_sym;
58 char name[0]; 59 char name[0];
59}; 60};
60 61
@@ -140,6 +141,11 @@ struct symbol_conf {
140 141
141extern struct symbol_conf symbol_conf; 142extern struct symbol_conf symbol_conf;
142 143
144struct symbol_name_rb_node {
145 struct rb_node rb_node;
146 struct symbol sym;
147};
148
143static inline int __symbol__join_symfs(char *bf, size_t size, const char *path) 149static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)
144{ 150{
145 return path__join(bf, size, symbol_conf.symfs, path); 151 return path__join(bf, size, symbol_conf.symfs, path);
@@ -235,9 +241,14 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
235 symbol_filter_t filter); 241 symbol_filter_t filter);
236int dso__load_vmlinux_path(struct dso *dso, struct map *map, 242int dso__load_vmlinux_path(struct dso *dso, struct map *map,
237 symbol_filter_t filter); 243 symbol_filter_t filter);
244int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
245 bool no_kcore, symbol_filter_t filter);
238int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 246int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
239 symbol_filter_t filter); 247 symbol_filter_t filter);
240 248
249void dso__insert_symbol(struct dso *dso, enum map_type type,
250 struct symbol *sym);
251
241struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, 252struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
242 u64 addr); 253 u64 addr);
243struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 254struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
@@ -262,8 +273,14 @@ int symbol__init(struct perf_env *env);
262void symbol__exit(void); 273void symbol__exit(void);
263void symbol__elf_init(void); 274void symbol__elf_init(void);
264struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 275struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
276size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
277 const struct addr_location *al,
278 bool unknown_as_addr, FILE *fp);
265size_t symbol__fprintf_symname_offs(const struct symbol *sym, 279size_t symbol__fprintf_symname_offs(const struct symbol *sym,
266 const struct addr_location *al, FILE *fp); 280 const struct addr_location *al, FILE *fp);
281size_t __symbol__fprintf_symname(const struct symbol *sym,
282 const struct addr_location *al,
283 bool unknown_as_addr, FILE *fp);
267size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 284size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
268size_t symbol__fprintf(struct symbol *sym, FILE *fp); 285size_t symbol__fprintf(struct symbol *sym, FILE *fp);
269bool symbol_type__is_a(char symbol_type, enum map_type map_type); 286bool symbol_type__is_a(char symbol_type, enum map_type map_type);
@@ -310,7 +327,7 @@ int setup_intlist(struct intlist **list, const char *list_str,
310 327
311#ifdef HAVE_LIBELF_SUPPORT 328#ifdef HAVE_LIBELF_SUPPORT
312bool elf__needs_adjust_symbols(GElf_Ehdr ehdr); 329bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
313void arch__elf_sym_adjust(GElf_Sym *sym); 330void arch__sym_update(struct symbol *s, GElf_Sym *sym);
314#endif 331#endif
315 332
316#define SYMBOL_A 0 333#define SYMBOL_A 0
diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c
new file mode 100644
index 000000000000..a680bdaa65dc
--- /dev/null
+++ b/tools/perf/util/symbol_fprintf.c
@@ -0,0 +1,71 @@
1#include <elf.h>
2#include <inttypes.h>
3#include <stdio.h>
4
5#include "symbol.h"
6
7size_t symbol__fprintf(struct symbol *sym, FILE *fp)
8{
9 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
10 sym->start, sym->end,
11 sym->binding == STB_GLOBAL ? 'g' :
12 sym->binding == STB_LOCAL ? 'l' : 'w',
13 sym->name);
14}
15
16size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
17 const struct addr_location *al,
18 bool unknown_as_addr, FILE *fp)
19{
20 unsigned long offset;
21 size_t length;
22
23 if (sym && sym->name) {
24 length = fprintf(fp, "%s", sym->name);
25 if (al) {
26 if (al->addr < sym->end)
27 offset = al->addr - sym->start;
28 else
29 offset = al->addr - al->map->start - sym->start;
30 length += fprintf(fp, "+0x%lx", offset);
31 }
32 return length;
33 } else if (al && unknown_as_addr)
34 return fprintf(fp, "[%#" PRIx64 "]", al->addr);
35 else
36 return fprintf(fp, "[unknown]");
37}
38
39size_t symbol__fprintf_symname_offs(const struct symbol *sym,
40 const struct addr_location *al,
41 FILE *fp)
42{
43 return __symbol__fprintf_symname_offs(sym, al, false, fp);
44}
45
46size_t __symbol__fprintf_symname(const struct symbol *sym,
47 const struct addr_location *al,
48 bool unknown_as_addr, FILE *fp)
49{
50 return __symbol__fprintf_symname_offs(sym, al, unknown_as_addr, fp);
51}
52
53size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
54{
55 return __symbol__fprintf_symname_offs(sym, NULL, false, fp);
56}
57
58size_t dso__fprintf_symbols_by_name(struct dso *dso,
59 enum map_type type, FILE *fp)
60{
61 size_t ret = 0;
62 struct rb_node *nd;
63 struct symbol_name_rb_node *pos;
64
65 for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) {
66 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
67 fprintf(fp, "%s\n", pos->sym.name);
68 }
69
70 return ret;
71}
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
new file mode 100644
index 000000000000..bbb4c1957578
--- /dev/null
+++ b/tools/perf/util/syscalltbl.c
@@ -0,0 +1,134 @@
1/*
2 * System call table mapper
3 *
4 * (C) 2016 Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15
16#include "syscalltbl.h"
17#include <stdlib.h>
18
19#ifdef HAVE_SYSCALL_TABLE
20#include <linux/compiler.h>
21#include <string.h>
22#include "util.h"
23
24#if defined(__x86_64__)
25#include <asm/syscalls_64.c>
26const int syscalltbl_native_max_id = SYSCALLTBL_x86_64_MAX_ID;
27static const char **syscalltbl_native = syscalltbl_x86_64;
28#endif
29
30struct syscall {
31 int id;
32 const char *name;
33};
34
35static int syscallcmpname(const void *vkey, const void *ventry)
36{
37 const char *key = vkey;
38 const struct syscall *entry = ventry;
39
40 return strcmp(key, entry->name);
41}
42
43static int syscallcmp(const void *va, const void *vb)
44{
45 const struct syscall *a = va, *b = vb;
46
47 return strcmp(a->name, b->name);
48}
49
50static int syscalltbl__init_native(struct syscalltbl *tbl)
51{
52 int nr_entries = 0, i, j;
53 struct syscall *entries;
54
55 for (i = 0; i <= syscalltbl_native_max_id; ++i)
56 if (syscalltbl_native[i])
57 ++nr_entries;
58
59 entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries);
60 if (tbl->syscalls.entries == NULL)
61 return -1;
62
63 for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) {
64 if (syscalltbl_native[i]) {
65 entries[j].name = syscalltbl_native[i];
66 entries[j].id = i;
67 ++j;
68 }
69 }
70
71 qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp);
72 tbl->syscalls.nr_entries = nr_entries;
73 return 0;
74}
75
76struct syscalltbl *syscalltbl__new(void)
77{
78 struct syscalltbl *tbl = malloc(sizeof(*tbl));
79 if (tbl) {
80 if (syscalltbl__init_native(tbl)) {
81 free(tbl);
82 return NULL;
83 }
84 }
85 return tbl;
86}
87
88void syscalltbl__delete(struct syscalltbl *tbl)
89{
90 zfree(&tbl->syscalls.entries);
91 free(tbl);
92}
93
94const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id)
95{
96 return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL;
97}
98
99int syscalltbl__id(struct syscalltbl *tbl, const char *name)
100{
101 struct syscall *sc = bsearch(name, tbl->syscalls.entries,
102 tbl->syscalls.nr_entries, sizeof(*sc),
103 syscallcmpname);
104
105 return sc ? sc->id : -1;
106}
107
108#else /* HAVE_SYSCALL_TABLE */
109
110#include <libaudit.h>
111
112struct syscalltbl *syscalltbl__new(void)
113{
114 struct syscalltbl *tbl = malloc(sizeof(*tbl));
115 if (tbl)
116 tbl->audit_machine = audit_detect_machine();
117 return tbl;
118}
119
120void syscalltbl__delete(struct syscalltbl *tbl)
121{
122 free(tbl);
123}
124
125const char *syscalltbl__name(const struct syscalltbl *tbl, int id)
126{
127 return audit_syscall_to_name(id, tbl->audit_machine);
128}
129
130int syscalltbl__id(struct syscalltbl *tbl, const char *name)
131{
132 return audit_name_to_syscall(name, tbl->audit_machine);
133}
134#endif /* HAVE_SYSCALL_TABLE */
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
new file mode 100644
index 000000000000..e2951510484f
--- /dev/null
+++ b/tools/perf/util/syscalltbl.h
@@ -0,0 +1,20 @@
1#ifndef __PERF_SYSCALLTBL_H
2#define __PERF_SYSCALLTBL_H
3
4struct syscalltbl {
5 union {
6 int audit_machine;
7 struct {
8 int nr_entries;
9 void *entries;
10 } syscalls;
11 };
12};
13
14struct syscalltbl *syscalltbl__new(void);
15void syscalltbl__delete(struct syscalltbl *tbl);
16
17const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
18int syscalltbl__id(struct syscalltbl *tbl, const char *name);
19
20#endif /* __PERF_SYSCALLTBL_H */
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index 679688e70ae7..825086aa9a08 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -22,44 +22,9 @@
22#include "debug.h" 22#include "debug.h"
23#include "symbol.h" 23#include "symbol.h"
24#include "comm.h" 24#include "comm.h"
25#include "call-path.h"
25#include "thread-stack.h" 26#include "thread-stack.h"
26 27
27#define CALL_PATH_BLOCK_SHIFT 8
28#define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT)
29#define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1)
30
31struct call_path_block {
32 struct call_path cp[CALL_PATH_BLOCK_SIZE];
33 struct list_head node;
34};
35
36/**
37 * struct call_path_root - root of all call paths.
38 * @call_path: root call path
39 * @blocks: list of blocks to store call paths
40 * @next: next free space
41 * @sz: number of spaces
42 */
43struct call_path_root {
44 struct call_path call_path;
45 struct list_head blocks;
46 size_t next;
47 size_t sz;
48};
49
50/**
51 * struct call_return_processor - provides a call-back to consume call-return
52 * information.
53 * @cpr: call path root
54 * @process: call-back that accepts call/return information
55 * @data: anonymous data for call-back
56 */
57struct call_return_processor {
58 struct call_path_root *cpr;
59 int (*process)(struct call_return *cr, void *data);
60 void *data;
61};
62
63#define STACK_GROWTH 2048 28#define STACK_GROWTH 2048
64 29
65/** 30/**
@@ -335,108 +300,6 @@ void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
335 chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr; 300 chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr;
336} 301}
337 302
338static void call_path__init(struct call_path *cp, struct call_path *parent,
339 struct symbol *sym, u64 ip, bool in_kernel)
340{
341 cp->parent = parent;
342 cp->sym = sym;
343 cp->ip = sym ? 0 : ip;
344 cp->db_id = 0;
345 cp->in_kernel = in_kernel;
346 RB_CLEAR_NODE(&cp->rb_node);
347 cp->children = RB_ROOT;
348}
349
350static struct call_path_root *call_path_root__new(void)
351{
352 struct call_path_root *cpr;
353
354 cpr = zalloc(sizeof(struct call_path_root));
355 if (!cpr)
356 return NULL;
357 call_path__init(&cpr->call_path, NULL, NULL, 0, false);
358 INIT_LIST_HEAD(&cpr->blocks);
359 return cpr;
360}
361
362static void call_path_root__free(struct call_path_root *cpr)
363{
364 struct call_path_block *pos, *n;
365
366 list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
367 list_del(&pos->node);
368 free(pos);
369 }
370 free(cpr);
371}
372
373static struct call_path *call_path__new(struct call_path_root *cpr,
374 struct call_path *parent,
375 struct symbol *sym, u64 ip,
376 bool in_kernel)
377{
378 struct call_path_block *cpb;
379 struct call_path *cp;
380 size_t n;
381
382 if (cpr->next < cpr->sz) {
383 cpb = list_last_entry(&cpr->blocks, struct call_path_block,
384 node);
385 } else {
386 cpb = zalloc(sizeof(struct call_path_block));
387 if (!cpb)
388 return NULL;
389 list_add_tail(&cpb->node, &cpr->blocks);
390 cpr->sz += CALL_PATH_BLOCK_SIZE;
391 }
392
393 n = cpr->next++ & CALL_PATH_BLOCK_MASK;
394 cp = &cpb->cp[n];
395
396 call_path__init(cp, parent, sym, ip, in_kernel);
397
398 return cp;
399}
400
401static struct call_path *call_path__findnew(struct call_path_root *cpr,
402 struct call_path *parent,
403 struct symbol *sym, u64 ip, u64 ks)
404{
405 struct rb_node **p;
406 struct rb_node *node_parent = NULL;
407 struct call_path *cp;
408 bool in_kernel = ip >= ks;
409
410 if (sym)
411 ip = 0;
412
413 if (!parent)
414 return call_path__new(cpr, parent, sym, ip, in_kernel);
415
416 p = &parent->children.rb_node;
417 while (*p != NULL) {
418 node_parent = *p;
419 cp = rb_entry(node_parent, struct call_path, rb_node);
420
421 if (cp->sym == sym && cp->ip == ip)
422 return cp;
423
424 if (sym < cp->sym || (sym == cp->sym && ip < cp->ip))
425 p = &(*p)->rb_left;
426 else
427 p = &(*p)->rb_right;
428 }
429
430 cp = call_path__new(cpr, parent, sym, ip, in_kernel);
431 if (!cp)
432 return NULL;
433
434 rb_link_node(&cp->rb_node, node_parent, p);
435 rb_insert_color(&cp->rb_node, &parent->children);
436
437 return cp;
438}
439
440struct call_return_processor * 303struct call_return_processor *
441call_return_processor__new(int (*process)(struct call_return *cr, void *data), 304call_return_processor__new(int (*process)(struct call_return *cr, void *data),
442 void *data) 305 void *data)
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
index e1528f1374c3..ad44c7944b8e 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -19,17 +19,16 @@
19#include <sys/types.h> 19#include <sys/types.h>
20 20
21#include <linux/types.h> 21#include <linux/types.h>
22#include <linux/rbtree.h>
23 22
24struct thread; 23struct thread;
25struct comm; 24struct comm;
26struct ip_callchain; 25struct ip_callchain;
27struct symbol; 26struct symbol;
28struct dso; 27struct dso;
29struct call_return_processor;
30struct comm; 28struct comm;
31struct perf_sample; 29struct perf_sample;
32struct addr_location; 30struct addr_location;
31struct call_path;
33 32
34/* 33/*
35 * Call/Return flags. 34 * Call/Return flags.
@@ -69,26 +68,16 @@ struct call_return {
69}; 68};
70 69
71/** 70/**
72 * struct call_path - node in list of calls leading to a function call. 71 * struct call_return_processor - provides a call-back to consume call-return
73 * @parent: call path to the parent function call 72 * information.
74 * @sym: symbol of function called 73 * @cpr: call path root
75 * @ip: only if sym is null, the ip of the function 74 * @process: call-back that accepts call/return information
76 * @db_id: id used for db-export 75 * @data: anonymous data for call-back
77 * @in_kernel: whether function is a in the kernel
78 * @rb_node: node in parent's tree of called functions
79 * @children: tree of call paths of functions called
80 *
81 * In combination with the call_return structure, the call_path structure
82 * defines a context-sensitve call-graph.
83 */ 76 */
84struct call_path { 77struct call_return_processor {
85 struct call_path *parent; 78 struct call_path_root *cpr;
86 struct symbol *sym; 79 int (*process)(struct call_return *cr, void *data);
87 u64 ip; 80 void *data;
88 u64 db_id;
89 bool in_kernel;
90 struct rb_node rb_node;
91 struct rb_root children;
92}; 81};
93 82
94int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, 83int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index dfd00c6dad6e..45fcb715a36b 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -10,6 +10,8 @@
10#include "comm.h" 10#include "comm.h"
11#include "unwind.h" 11#include "unwind.h"
12 12
13#include <api/fs/fs.h>
14
13int thread__init_map_groups(struct thread *thread, struct machine *machine) 15int thread__init_map_groups(struct thread *thread, struct machine *machine)
14{ 16{
15 struct thread *leader; 17 struct thread *leader;
@@ -153,6 +155,23 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
153 return 0; 155 return 0;
154} 156}
155 157
158int thread__set_comm_from_proc(struct thread *thread)
159{
160 char path[64];
161 char *comm = NULL;
162 size_t sz;
163 int err = -1;
164
165 if (!(snprintf(path, sizeof(path), "%d/task/%d/comm",
166 thread->pid_, thread->tid) >= (int)sizeof(path)) &&
167 procfs__read_str(path, &comm, &sz) == 0) {
168 comm[sz - 1] = '\0';
169 err = thread__set_comm(thread, comm, 0);
170 }
171
172 return err;
173}
174
156const char *thread__comm_str(const struct thread *thread) 175const char *thread__comm_str(const struct thread *thread)
157{ 176{
158 const struct comm *comm = thread__comm(thread); 177 const struct comm *comm = thread__comm(thread);
@@ -233,7 +252,7 @@ void thread__find_cpumode_addr_location(struct thread *thread,
233 struct addr_location *al) 252 struct addr_location *al)
234{ 253{
235 size_t i; 254 size_t i;
236 const u8 const cpumodes[] = { 255 const u8 cpumodes[] = {
237 PERF_RECORD_MISC_USER, 256 PERF_RECORD_MISC_USER,
238 PERF_RECORD_MISC_KERNEL, 257 PERF_RECORD_MISC_KERNEL,
239 PERF_RECORD_MISC_GUEST_USER, 258 PERF_RECORD_MISC_GUEST_USER,
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index a0ac0317affb..45fba13c800b 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -9,6 +9,9 @@
9#include "symbol.h" 9#include "symbol.h"
10#include <strlist.h> 10#include <strlist.h>
11#include <intlist.h> 11#include <intlist.h>
12#ifdef HAVE_LIBUNWIND_SUPPORT
13#include <libunwind.h>
14#endif
12 15
13struct thread_stack; 16struct thread_stack;
14 17
@@ -32,6 +35,9 @@ struct thread {
32 35
33 void *priv; 36 void *priv;
34 struct thread_stack *ts; 37 struct thread_stack *ts;
38#ifdef HAVE_LIBUNWIND_SUPPORT
39 unw_addr_space_t addr_space;
40#endif
35}; 41};
36 42
37struct machine; 43struct machine;
@@ -65,6 +71,8 @@ static inline int thread__set_comm(struct thread *thread, const char *comm,
65 return __thread__set_comm(thread, comm, timestamp, false); 71 return __thread__set_comm(thread, comm, timestamp, false);
66} 72}
67 73
74int thread__set_comm_from_proc(struct thread *thread);
75
68int thread__comm_len(struct thread *thread); 76int thread__comm_len(struct thread *thread);
69struct comm *thread__comm(const struct thread *thread); 77struct comm *thread__comm(const struct thread *thread);
70struct comm *thread__exec_comm(const struct thread *thread); 78struct comm *thread__exec_comm(const struct thread *thread);
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 08afc6909953..5654fe15e036 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -94,7 +94,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
94 DIR *proc; 94 DIR *proc;
95 int max_threads = 32, items, i; 95 int max_threads = 32, items, i;
96 char path[256]; 96 char path[256];
97 struct dirent dirent, *next, **namelist = NULL; 97 struct dirent *dirent, **namelist = NULL;
98 struct thread_map *threads = thread_map__alloc(max_threads); 98 struct thread_map *threads = thread_map__alloc(max_threads);
99 99
100 if (threads == NULL) 100 if (threads == NULL)
@@ -107,16 +107,16 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
107 threads->nr = 0; 107 threads->nr = 0;
108 atomic_set(&threads->refcnt, 1); 108 atomic_set(&threads->refcnt, 1);
109 109
110 while (!readdir_r(proc, &dirent, &next) && next) { 110 while ((dirent = readdir(proc)) != NULL) {
111 char *end; 111 char *end;
112 bool grow = false; 112 bool grow = false;
113 struct stat st; 113 struct stat st;
114 pid_t pid = strtol(dirent.d_name, &end, 10); 114 pid_t pid = strtol(dirent->d_name, &end, 10);
115 115
116 if (*end) /* only interested in proper numerical dirents */ 116 if (*end) /* only interested in proper numerical dirents */
117 continue; 117 continue;
118 118
119 snprintf(path, sizeof(path), "/proc/%s", dirent.d_name); 119 snprintf(path, sizeof(path), "/proc/%s", dirent->d_name);
120 120
121 if (stat(path, &st) != 0) 121 if (stat(path, &st) != 0)
122 continue; 122 continue;
@@ -260,7 +260,7 @@ struct thread_map *thread_map__new_dummy(void)
260 return threads; 260 return threads;
261} 261}
262 262
263static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) 263struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
264{ 264{
265 struct thread_map *threads = NULL, *nt; 265 struct thread_map *threads = NULL, *nt;
266 int ntasks = 0; 266 int ntasks = 0;
@@ -436,3 +436,15 @@ struct thread_map *thread_map__new_event(struct thread_map_event *event)
436 436
437 return threads; 437 return threads;
438} 438}
439
440bool thread_map__has(struct thread_map *threads, pid_t pid)
441{
442 int i;
443
444 for (i = 0; i < threads->nr; ++i) {
445 if (threads->map[i].pid == pid)
446 return true;
447 }
448
449 return false;
450}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 85e4c7c4fbde..bd3b971588da 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -31,6 +31,8 @@ void thread_map__put(struct thread_map *map);
31struct thread_map *thread_map__new_str(const char *pid, 31struct thread_map *thread_map__new_str(const char *pid,
32 const char *tid, uid_t uid); 32 const char *tid, uid_t uid);
33 33
34struct thread_map *thread_map__new_by_tid_str(const char *tid_str);
35
34size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); 36size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
35 37
36static inline int thread_map__nr(struct thread_map *threads) 38static inline int thread_map__nr(struct thread_map *threads)
@@ -55,4 +57,5 @@ static inline char *thread_map__comm(struct thread_map *map, int thread)
55} 57}
56 58
57void thread_map__read_comms(struct thread_map *threads); 59void thread_map__read_comms(struct thread_map *threads);
60bool thread_map__has(struct thread_map *threads, pid_t pid);
58#endif /* __PERF_THREAD_MAP_H */ 61#endif /* __PERF_THREAD_MAP_H */
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 55de4cffcd4e..ac2590a3de2d 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -57,6 +57,7 @@ struct perf_tool {
57 id_index, 57 id_index,
58 auxtrace_info, 58 auxtrace_info,
59 auxtrace_error, 59 auxtrace_error,
60 time_conv,
60 thread_map, 61 thread_map,
61 cpu_map, 62 cpu_map,
62 stat_config, 63 stat_config,
diff --git a/tools/perf/util/trigger.h b/tools/perf/util/trigger.h
new file mode 100644
index 000000000000..e97d7016d771
--- /dev/null
+++ b/tools/perf/util/trigger.h
@@ -0,0 +1,94 @@
1#ifndef __TRIGGER_H_
2#define __TRIGGER_H_ 1
3
4#include "util/debug.h"
5#include "asm/bug.h"
6
7/*
8 * Use trigger to model operations which need to be executed when
9 * an event (a signal, for example) is observed.
10 *
11 * States and transits:
12 *
13 *
14 * OFF--(on)--> READY --(hit)--> HIT
15 * ^ |
16 * | (ready)
17 * | |
18 * \_____________/
19 *
20 * is_hit and is_ready are two key functions to query the state of
21 * a trigger. is_hit means the event already happen; is_ready means the
22 * trigger is waiting for the event.
23 */
24
25struct trigger {
26 volatile enum {
27 TRIGGER_ERROR = -2,
28 TRIGGER_OFF = -1,
29 TRIGGER_READY = 0,
30 TRIGGER_HIT = 1,
31 } state;
32 const char *name;
33};
34
35#define TRIGGER_WARN_ONCE(t, exp) \
36 WARN_ONCE(t->state != exp, "trigger '%s' state transist error: %d in %s()\n", \
37 t->name, t->state, __func__)
38
39static inline bool trigger_is_available(struct trigger *t)
40{
41 return t->state >= 0;
42}
43
44static inline bool trigger_is_error(struct trigger *t)
45{
46 return t->state <= TRIGGER_ERROR;
47}
48
49static inline void trigger_on(struct trigger *t)
50{
51 TRIGGER_WARN_ONCE(t, TRIGGER_OFF);
52 t->state = TRIGGER_READY;
53}
54
55static inline void trigger_ready(struct trigger *t)
56{
57 if (!trigger_is_available(t))
58 return;
59 t->state = TRIGGER_READY;
60}
61
62static inline void trigger_hit(struct trigger *t)
63{
64 if (!trigger_is_available(t))
65 return;
66 TRIGGER_WARN_ONCE(t, TRIGGER_READY);
67 t->state = TRIGGER_HIT;
68}
69
70static inline void trigger_off(struct trigger *t)
71{
72 if (!trigger_is_available(t))
73 return;
74 t->state = TRIGGER_OFF;
75}
76
77static inline void trigger_error(struct trigger *t)
78{
79 t->state = TRIGGER_ERROR;
80}
81
82static inline bool trigger_is_ready(struct trigger *t)
83{
84 return t->state == TRIGGER_READY;
85}
86
87static inline bool trigger_is_hit(struct trigger *t)
88{
89 return t->state == TRIGGER_HIT;
90}
91
92#define DEFINE_TRIGGER(n) \
93struct trigger n = {.state = TRIGGER_OFF, .name = #n}
94#endif
diff --git a/tools/perf/util/tsc.h b/tools/perf/util/tsc.h
index a8b78f1b3243..d5b11e2b85e0 100644
--- a/tools/perf/util/tsc.h
+++ b/tools/perf/util/tsc.h
@@ -3,10 +3,29 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6#include "../arch/x86/util/tsc.h" 6#include "event.h"
7
8struct perf_tsc_conversion {
9 u16 time_shift;
10 u32 time_mult;
11 u64 time_zero;
12};
13struct perf_event_mmap_page;
14
15int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
16 struct perf_tsc_conversion *tc);
7 17
8u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); 18u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc);
9u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); 19u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc);
10u64 rdtsc(void); 20u64 rdtsc(void);
11 21
22struct perf_event_mmap_page;
23struct perf_tool;
24struct machine;
25
26int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc,
27 struct perf_tool *tool,
28 perf_event__handler_t process,
29 struct machine *machine);
30
12#endif 31#endif
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index ee7e372297e5..63687d3a344e 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -32,6 +32,7 @@
32#include "symbol.h" 32#include "symbol.h"
33#include "util.h" 33#include "util.h"
34#include "debug.h" 34#include "debug.h"
35#include "asm/bug.h"
35 36
36extern int 37extern int
37UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, 38UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
@@ -580,43 +581,33 @@ static unw_accessors_t accessors = {
580 581
581int unwind__prepare_access(struct thread *thread) 582int unwind__prepare_access(struct thread *thread)
582{ 583{
583 unw_addr_space_t addr_space;
584
585 if (callchain_param.record_mode != CALLCHAIN_DWARF) 584 if (callchain_param.record_mode != CALLCHAIN_DWARF)
586 return 0; 585 return 0;
587 586
588 addr_space = unw_create_addr_space(&accessors, 0); 587 thread->addr_space = unw_create_addr_space(&accessors, 0);
589 if (!addr_space) { 588 if (!thread->addr_space) {
590 pr_err("unwind: Can't create unwind address space.\n"); 589 pr_err("unwind: Can't create unwind address space.\n");
591 return -ENOMEM; 590 return -ENOMEM;
592 } 591 }
593 592
594 unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); 593 unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL);
595 thread__set_priv(thread, addr_space);
596
597 return 0; 594 return 0;
598} 595}
599 596
600void unwind__flush_access(struct thread *thread) 597void unwind__flush_access(struct thread *thread)
601{ 598{
602 unw_addr_space_t addr_space;
603
604 if (callchain_param.record_mode != CALLCHAIN_DWARF) 599 if (callchain_param.record_mode != CALLCHAIN_DWARF)
605 return; 600 return;
606 601
607 addr_space = thread__priv(thread); 602 unw_flush_cache(thread->addr_space, 0, 0);
608 unw_flush_cache(addr_space, 0, 0);
609} 603}
610 604
611void unwind__finish_access(struct thread *thread) 605void unwind__finish_access(struct thread *thread)
612{ 606{
613 unw_addr_space_t addr_space;
614
615 if (callchain_param.record_mode != CALLCHAIN_DWARF) 607 if (callchain_param.record_mode != CALLCHAIN_DWARF)
616 return; 608 return;
617 609
618 addr_space = thread__priv(thread); 610 unw_destroy_addr_space(thread->addr_space);
619 unw_destroy_addr_space(addr_space);
620} 611}
621 612
622static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, 613static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
@@ -639,7 +630,9 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
639 * unwind itself. 630 * unwind itself.
640 */ 631 */
641 if (max_stack - 1 > 0) { 632 if (max_stack - 1 > 0) {
642 addr_space = thread__priv(ui->thread); 633 WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
634 addr_space = ui->thread->addr_space;
635
643 if (addr_space == NULL) 636 if (addr_space == NULL)
644 return -1; 637 return -1;
645 638
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index b7766c577b01..eab077ad6ca9 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -33,6 +33,8 @@ struct callchain_param callchain_param = {
33unsigned int page_size; 33unsigned int page_size;
34int cacheline_size; 34int cacheline_size;
35 35
36unsigned int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
37
36bool test_attr__enabled; 38bool test_attr__enabled;
37 39
38bool perf_host = true; 40bool perf_host = true;
@@ -117,6 +119,40 @@ int rm_rf(char *path)
117 return rmdir(path); 119 return rmdir(path);
118} 120}
119 121
122/* A filter which removes dot files */
123bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
124{
125 return d->d_name[0] != '.';
126}
127
128/* lsdir reads a directory and store it in strlist */
129struct strlist *lsdir(const char *name,
130 bool (*filter)(const char *, struct dirent *))
131{
132 struct strlist *list = NULL;
133 DIR *dir;
134 struct dirent *d;
135
136 dir = opendir(name);
137 if (!dir)
138 return NULL;
139
140 list = strlist__new(NULL, NULL);
141 if (!list) {
142 errno = ENOMEM;
143 goto out;
144 }
145
146 while ((d = readdir(dir)) != NULL) {
147 if (!filter || filter(name, d))
148 strlist__add(list, d->d_name);
149 }
150
151out:
152 closedir(dir);
153 return list;
154}
155
120static int slow_copyfile(const char *from, const char *to) 156static int slow_copyfile(const char *from, const char *to)
121{ 157{
122 int err = -1; 158 int err = -1;
@@ -471,7 +507,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param)
471 "needed for --call-graph fp\n"); 507 "needed for --call-graph fp\n");
472 break; 508 break;
473 509
474#ifdef HAVE_DWARF_UNWIND_SUPPORT
475 /* Dwarf style */ 510 /* Dwarf style */
476 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 511 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
477 const unsigned long default_stack_dump_size = 8192; 512 const unsigned long default_stack_dump_size = 8192;
@@ -487,7 +522,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param)
487 ret = get_stack_size(tok, &size); 522 ret = get_stack_size(tok, &size);
488 param->dump_size = size; 523 param->dump_size = size;
489 } 524 }
490#endif /* HAVE_DWARF_UNWIND_SUPPORT */
491 } else if (!strncmp(name, "lbr", sizeof("lbr"))) { 525 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
492 if (!strtok_r(NULL, ",", &saveptr)) { 526 if (!strtok_r(NULL, ",", &saveptr)) {
493 param->record_mode = CALLCHAIN_LBR; 527 param->record_mode = CALLCHAIN_LBR;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 8298d607c738..7651633a8dc7 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -79,6 +79,7 @@
79#include <termios.h> 79#include <termios.h>
80#include <linux/bitops.h> 80#include <linux/bitops.h>
81#include <termios.h> 81#include <termios.h>
82#include "strlist.h"
82 83
83extern const char *graph_line; 84extern const char *graph_line;
84extern const char *graph_dotted_line; 85extern const char *graph_dotted_line;
@@ -159,12 +160,6 @@ static inline char *gitstrchrnul(const char *s, int c)
159} 160}
160#endif 161#endif
161 162
162/*
163 * Wrappers:
164 */
165void *xrealloc(void *ptr, size_t size) __attribute__((weak));
166
167
168static inline void *zalloc(size_t size) 163static inline void *zalloc(size_t size)
169{ 164{
170 return calloc(1, size); 165 return calloc(1, size);
@@ -222,6 +217,8 @@ static inline int sane_case(int x, int high)
222 217
223int mkdir_p(char *path, mode_t mode); 218int mkdir_p(char *path, mode_t mode);
224int rm_rf(char *path); 219int rm_rf(char *path);
220struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *));
221bool lsdir_no_dot_filter(const char *name, struct dirent *d);
225int copyfile(const char *from, const char *to); 222int copyfile(const char *from, const char *to);
226int copyfile_mode(const char *from, const char *to, mode_t mode); 223int copyfile_mode(const char *from, const char *to, mode_t mode);
227int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size); 224int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);
@@ -254,11 +251,17 @@ int hex2u64(const char *ptr, u64 *val);
254char *ltrim(char *s); 251char *ltrim(char *s);
255char *rtrim(char *s); 252char *rtrim(char *s);
256 253
254static inline char *trim(char *s)
255{
256 return ltrim(rtrim(s));
257}
258
257void dump_stack(void); 259void dump_stack(void);
258void sighandler_dump_stack(int sig); 260void sighandler_dump_stack(int sig);
259 261
260extern unsigned int page_size; 262extern unsigned int page_size;
261extern int cacheline_size; 263extern int cacheline_size;
264extern unsigned int sysctl_perf_event_max_stack;
262 265
263struct parse_tag { 266struct parse_tag {
264 char tag; 267 char tag;
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c
deleted file mode 100644
index 5f1a07c4b87b..000000000000
--- a/tools/perf/util/wrapper.c
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2 * Various trivial helper wrappers around standard functions
3 */
4#include "cache.h"
5
6/*
7 * There's no pack memory to release - but stay close to the Git
8 * version so wrap this away:
9 */
10static inline void release_pack_memory(size_t size __maybe_unused,
11 int flag __maybe_unused)
12{
13}
14
15void *xrealloc(void *ptr, size_t size)
16{
17 void *ret = realloc(ptr, size);
18 if (!ret && !size)
19 ret = realloc(ptr, 1);
20 if (!ret) {
21 release_pack_memory(size, -1);
22 ret = realloc(ptr, size);
23 if (!ret && !size)
24 ret = realloc(ptr, 1);
25 if (!ret)
26 die("Out of memory, realloc failed");
27 }
28 return ret;
29}
diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
index d0e6b857d8d1..546cf4a503b7 100644
--- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
+++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
@@ -91,7 +91,7 @@ osl_get_customized_table(char *pathname,
91 char *signature, 91 char *signature,
92 u32 instance, 92 u32 instance,
93 struct acpi_table_header **table, 93 struct acpi_table_header **table,
94 acpi_physical_address * address); 94 acpi_physical_address *address);
95 95
96static acpi_status osl_list_bios_tables(void); 96static acpi_status osl_list_bios_tables(void);
97 97
@@ -99,7 +99,7 @@ static acpi_status
99osl_get_bios_table(char *signature, 99osl_get_bios_table(char *signature,
100 u32 instance, 100 u32 instance,
101 struct acpi_table_header **table, 101 struct acpi_table_header **table,
102 acpi_physical_address * address); 102 acpi_physical_address *address);
103 103
104static acpi_status osl_get_last_status(acpi_status default_status); 104static acpi_status osl_get_last_status(acpi_status default_status);
105 105
@@ -187,7 +187,7 @@ static acpi_status osl_get_last_status(acpi_status default_status)
187 187
188acpi_status 188acpi_status
189acpi_os_get_table_by_address(acpi_physical_address address, 189acpi_os_get_table_by_address(acpi_physical_address address,
190 struct acpi_table_header ** table) 190 struct acpi_table_header **table)
191{ 191{
192 u32 table_length; 192 u32 table_length;
193 struct acpi_table_header *mapped_table; 193 struct acpi_table_header *mapped_table;
@@ -252,8 +252,8 @@ exit:
252acpi_status 252acpi_status
253acpi_os_get_table_by_name(char *signature, 253acpi_os_get_table_by_name(char *signature,
254 u32 instance, 254 u32 instance,
255 struct acpi_table_header ** table, 255 struct acpi_table_header **table,
256 acpi_physical_address * address) 256 acpi_physical_address *address)
257{ 257{
258 acpi_status status; 258 acpi_status status;
259 259
@@ -380,8 +380,8 @@ static acpi_status osl_add_table_to_list(char *signature, u32 instance)
380 380
381acpi_status 381acpi_status
382acpi_os_get_table_by_index(u32 index, 382acpi_os_get_table_by_index(u32 index,
383 struct acpi_table_header ** table, 383 struct acpi_table_header **table,
384 u32 *instance, acpi_physical_address * address) 384 u32 *instance, acpi_physical_address *address)
385{ 385{
386 struct osl_table_info *info; 386 struct osl_table_info *info;
387 acpi_status status; 387 acpi_status status;
@@ -447,7 +447,7 @@ osl_find_rsdp_via_efi_by_keyword(FILE * file, const char *keyword)
447 } 447 }
448 } 448 }
449 449
450 return ((acpi_physical_address) (address)); 450 return ((acpi_physical_address)(address));
451} 451}
452 452
453/****************************************************************************** 453/******************************************************************************
@@ -751,10 +751,10 @@ static acpi_status osl_list_bios_tables(void)
751 for (i = 0; i < number_of_tables; ++i, table_data += item_size) { 751 for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
752 if (osl_can_use_xsdt()) { 752 if (osl_can_use_xsdt()) {
753 table_address = 753 table_address =
754 (acpi_physical_address) (*ACPI_CAST64(table_data)); 754 (acpi_physical_address)(*ACPI_CAST64(table_data));
755 } else { 755 } else {
756 table_address = 756 table_address =
757 (acpi_physical_address) (*ACPI_CAST32(table_data)); 757 (acpi_physical_address)(*ACPI_CAST32(table_data));
758 } 758 }
759 759
760 /* Skip NULL entries in RSDT/XSDT */ 760 /* Skip NULL entries in RSDT/XSDT */
@@ -800,7 +800,7 @@ static acpi_status
800osl_get_bios_table(char *signature, 800osl_get_bios_table(char *signature,
801 u32 instance, 801 u32 instance,
802 struct acpi_table_header **table, 802 struct acpi_table_header **table,
803 acpi_physical_address * address) 803 acpi_physical_address *address)
804{ 804{
805 struct acpi_table_header *local_table = NULL; 805 struct acpi_table_header *local_table = NULL;
806 struct acpi_table_header *mapped_table = NULL; 806 struct acpi_table_header *mapped_table = NULL;
@@ -833,38 +833,37 @@ osl_get_bios_table(char *signature,
833 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) && 833 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) &&
834 gbl_fadt->Xdsdt) { 834 gbl_fadt->Xdsdt) {
835 table_address = 835 table_address =
836 (acpi_physical_address) gbl_fadt->Xdsdt; 836 (acpi_physical_address)gbl_fadt->Xdsdt;
837 } else 837 } else
838 if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT) 838 if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT)
839 && gbl_fadt->dsdt) { 839 && gbl_fadt->dsdt) {
840 table_address = 840 table_address =
841 (acpi_physical_address) gbl_fadt->dsdt; 841 (acpi_physical_address)gbl_fadt->dsdt;
842 } 842 }
843 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { 843 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
844 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) && 844 if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) &&
845 gbl_fadt->Xfacs) { 845 gbl_fadt->Xfacs) {
846 table_address = 846 table_address =
847 (acpi_physical_address) gbl_fadt->Xfacs; 847 (acpi_physical_address)gbl_fadt->Xfacs;
848 } else 848 } else
849 if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS) 849 if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS)
850 && gbl_fadt->facs) { 850 && gbl_fadt->facs) {
851 table_address = 851 table_address =
852 (acpi_physical_address) gbl_fadt->facs; 852 (acpi_physical_address)gbl_fadt->facs;
853 } 853 }
854 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) { 854 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
855 if (!gbl_revision) { 855 if (!gbl_revision) {
856 return (AE_BAD_SIGNATURE); 856 return (AE_BAD_SIGNATURE);
857 } 857 }
858 table_address = 858 table_address =
859 (acpi_physical_address) gbl_rsdp. 859 (acpi_physical_address)gbl_rsdp.
860 xsdt_physical_address; 860 xsdt_physical_address;
861 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) { 861 } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
862 table_address = 862 table_address =
863 (acpi_physical_address) gbl_rsdp. 863 (acpi_physical_address)gbl_rsdp.
864 rsdt_physical_address; 864 rsdt_physical_address;
865 } else { 865 } else {
866 table_address = 866 table_address = (acpi_physical_address)gbl_rsdp_address;
867 (acpi_physical_address) gbl_rsdp_address;
868 signature = ACPI_SIG_RSDP; 867 signature = ACPI_SIG_RSDP;
869 } 868 }
870 869
@@ -904,12 +903,12 @@ osl_get_bios_table(char *signature,
904 for (i = 0; i < number_of_tables; ++i, table_data += item_size) { 903 for (i = 0; i < number_of_tables; ++i, table_data += item_size) {
905 if (osl_can_use_xsdt()) { 904 if (osl_can_use_xsdt()) {
906 table_address = 905 table_address =
907 (acpi_physical_address) (*ACPI_CAST64 906 (acpi_physical_address)(*ACPI_CAST64
908 (table_data)); 907 (table_data));
909 } else { 908 } else {
910 table_address = 909 table_address =
911 (acpi_physical_address) (*ACPI_CAST32 910 (acpi_physical_address)(*ACPI_CAST32
912 (table_data)); 911 (table_data));
913 } 912 }
914 913
915 /* Skip NULL entries in RSDT/XSDT */ 914 /* Skip NULL entries in RSDT/XSDT */
@@ -1301,7 +1300,7 @@ osl_get_customized_table(char *pathname,
1301 char *signature, 1300 char *signature,
1302 u32 instance, 1301 u32 instance,
1303 struct acpi_table_header **table, 1302 struct acpi_table_header **table,
1304 acpi_physical_address * address) 1303 acpi_physical_address *address)
1305{ 1304{
1306 void *table_dir; 1305 void *table_dir;
1307 u32 current_instance = 0; 1306 u32 current_instance = 0;
diff --git a/tools/power/acpi/os_specific/service_layers/osunixmap.c b/tools/power/acpi/os_specific/service_layers/osunixmap.c
index 3818fd07e50f..cbfbce18783d 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixmap.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixmap.c
@@ -54,7 +54,7 @@ ACPI_MODULE_NAME("osunixmap")
54#ifndef O_BINARY 54#ifndef O_BINARY
55#define O_BINARY 0 55#define O_BINARY 0
56#endif 56#endif
57#if defined(_dragon_fly) || defined(_free_BSD) 57#if defined(_dragon_fly) || defined(_free_BSD) || defined(_QNX)
58#define MMAP_FLAGS MAP_SHARED 58#define MMAP_FLAGS MAP_SHARED
59#else 59#else
60#define MMAP_FLAGS MAP_PRIVATE 60#define MMAP_FLAGS MAP_PRIVATE
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index 08cb8b2035f2..88aa66ef4ad5 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -246,8 +246,8 @@ acpi_physical_address acpi_os_get_root_pointer(void)
246 *****************************************************************************/ 246 *****************************************************************************/
247 247
248acpi_status 248acpi_status
249acpi_os_predefined_override(const struct acpi_predefined_names * init_val, 249acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
250 acpi_string * new_val) 250 acpi_string *new_val)
251{ 251{
252 252
253 if (!init_val || !new_val) { 253 if (!init_val || !new_val) {
@@ -274,8 +274,8 @@ acpi_os_predefined_override(const struct acpi_predefined_names * init_val,
274 *****************************************************************************/ 274 *****************************************************************************/
275 275
276acpi_status 276acpi_status
277acpi_os_table_override(struct acpi_table_header * existing_table, 277acpi_os_table_override(struct acpi_table_header *existing_table,
278 struct acpi_table_header ** new_table) 278 struct acpi_table_header **new_table)
279{ 279{
280 280
281 if (!existing_table || !new_table) { 281 if (!existing_table || !new_table) {
@@ -311,8 +311,8 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
311 *****************************************************************************/ 311 *****************************************************************************/
312 312
313acpi_status 313acpi_status
314acpi_os_physical_table_override(struct acpi_table_header * existing_table, 314acpi_os_physical_table_override(struct acpi_table_header *existing_table,
315 acpi_physical_address * new_address, 315 acpi_physical_address *new_address,
316 u32 *new_table_length) 316 u32 *new_table_length)
317{ 317{
318 318
@@ -506,7 +506,7 @@ acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read)
506void *acpi_os_map_memory(acpi_physical_address where, acpi_size length) 506void *acpi_os_map_memory(acpi_physical_address where, acpi_size length)
507{ 507{
508 508
509 return (ACPI_TO_POINTER((acpi_size) where)); 509 return (ACPI_TO_POINTER((acpi_size)where));
510} 510}
511 511
512/****************************************************************************** 512/******************************************************************************
@@ -603,9 +603,9 @@ void acpi_os_free(void *mem)
603 603
604acpi_status 604acpi_status
605acpi_os_create_semaphore(u32 max_units, 605acpi_os_create_semaphore(u32 max_units,
606 u32 initial_units, acpi_handle * out_handle) 606 u32 initial_units, acpi_handle *out_handle)
607{ 607{
608 *out_handle = (acpi_handle) 1; 608 *out_handle = (acpi_handle)1;
609 return (AE_OK); 609 return (AE_OK);
610} 610}
611 611
@@ -640,7 +640,7 @@ acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
640 640
641acpi_status 641acpi_status
642acpi_os_create_semaphore(u32 max_units, 642acpi_os_create_semaphore(u32 max_units,
643 u32 initial_units, acpi_handle * out_handle) 643 u32 initial_units, acpi_handle *out_handle)
644{ 644{
645 sem_t *sem; 645 sem_t *sem;
646 646
@@ -672,7 +672,7 @@ acpi_os_create_semaphore(u32 max_units,
672 } 672 }
673#endif 673#endif
674 674
675 *out_handle = (acpi_handle) sem; 675 *out_handle = (acpi_handle)sem;
676 return (AE_OK); 676 return (AE_OK);
677} 677}
678 678
@@ -1035,7 +1035,7 @@ acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id,
1035 *****************************************************************************/ 1035 *****************************************************************************/
1036 1036
1037acpi_status 1037acpi_status
1038acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, 1038acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id,
1039 u32 pci_register, u64 value, u32 width) 1039 u32 pci_register, u64 value, u32 width)
1040{ 1040{
1041 1041
diff --git a/tools/power/acpi/tools/acpidbg/acpidbg.c b/tools/power/acpi/tools/acpidbg/acpidbg.c
index d070fccdba6d..a88ac45b7756 100644
--- a/tools/power/acpi/tools/acpidbg/acpidbg.c
+++ b/tools/power/acpi/tools/acpidbg/acpidbg.c
@@ -375,7 +375,7 @@ void usage(FILE *file, char *progname)
375 375
376int main(int argc, char **argv) 376int main(int argc, char **argv)
377{ 377{
378 int fd = 0; 378 int fd = -1;
379 int ch; 379 int ch;
380 int len; 380 int len;
381 int ret = EXIT_SUCCESS; 381 int ret = EXIT_SUCCESS;
@@ -430,7 +430,7 @@ int main(int argc, char **argv)
430 acpi_aml_loop(fd); 430 acpi_aml_loop(fd);
431 431
432exit: 432exit:
433 if (fd < 0) 433 if (fd >= 0)
434 close(fd); 434 close(fd);
435 if (acpi_aml_batch_cmd) 435 if (acpi_aml_batch_cmd)
436 free(acpi_aml_batch_cmd); 436 free(acpi_aml_batch_cmd);
diff --git a/tools/power/acpi/tools/acpidump/Makefile b/tools/power/acpi/tools/acpidump/Makefile
index 8d761576e91b..2942cdced2ad 100644
--- a/tools/power/acpi/tools/acpidump/Makefile
+++ b/tools/power/acpi/tools/acpidump/Makefile
@@ -31,6 +31,7 @@ TOOL_OBJS = \
31 osunixxf.o\ 31 osunixxf.o\
32 tbprint.o\ 32 tbprint.o\
33 tbxfroot.o\ 33 tbxfroot.o\
34 utascii.o\
34 utbuffer.o\ 35 utbuffer.o\
35 utdebug.o\ 36 utdebug.o\
36 utexcep.o\ 37 utexcep.o\
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c
index da44458d3b6c..fb8f1d9e3b1b 100644
--- a/tools/power/acpi/tools/acpidump/apdump.c
+++ b/tools/power/acpi/tools/acpidump/apdump.c
@@ -68,7 +68,7 @@ u8 ap_is_valid_header(struct acpi_table_header *table)
68 68
69 /* Make sure signature is all ASCII and a valid ACPI name */ 69 /* Make sure signature is all ASCII and a valid ACPI name */
70 70
71 if (!acpi_ut_valid_acpi_name(table->signature)) { 71 if (!acpi_ut_valid_nameseg(table->signature)) {
72 acpi_log_error("Table signature (0x%8.8X) is invalid\n", 72 acpi_log_error("Table signature (0x%8.8X) is invalid\n",
73 *(u32 *)table->signature); 73 *(u32 *)table->signature);
74 return (FALSE); 74 return (FALSE);
@@ -286,14 +286,15 @@ int ap_dump_table_by_address(char *ascii_address)
286 286
287 /* Convert argument to an integer physical address */ 287 /* Convert argument to an integer physical address */
288 288
289 status = acpi_ut_strtoul64(ascii_address, 0, &long_address); 289 status = acpi_ut_strtoul64(ascii_address, ACPI_ANY_BASE,
290 ACPI_MAX64_BYTE_WIDTH, &long_address);
290 if (ACPI_FAILURE(status)) { 291 if (ACPI_FAILURE(status)) {
291 acpi_log_error("%s: Could not convert to a physical address\n", 292 acpi_log_error("%s: Could not convert to a physical address\n",
292 ascii_address); 293 ascii_address);
293 return (-1); 294 return (-1);
294 } 295 }
295 296
296 address = (acpi_physical_address) long_address; 297 address = (acpi_physical_address)long_address;
297 status = acpi_os_get_table_by_address(address, &table); 298 status = acpi_os_get_table_by_address(address, &table);
298 if (ACPI_FAILURE(status)) { 299 if (ACPI_FAILURE(status)) {
299 acpi_log_error("Could not get table at 0x%8.8X%8.8X, %s\n", 300 acpi_log_error("Could not get table at 0x%8.8X%8.8X, %s\n",
@@ -406,6 +407,12 @@ int ap_dump_table_from_file(char *pathname)
406 return (-1); 407 return (-1);
407 } 408 }
408 409
410 if (!acpi_ut_valid_nameseg(table->signature)) {
411 acpi_log_error
412 ("No valid ACPI signature was found in input file %s\n",
413 pathname);
414 }
415
409 /* File must be at least as long as the table length */ 416 /* File must be at least as long as the table length */
410 417
411 if (table->length > file_size) { 418 if (table->length > file_size) {
diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c
index c3c09152fac6..7692e6b887e1 100644
--- a/tools/power/acpi/tools/acpidump/apmain.c
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -209,7 +209,8 @@ static int ap_do_options(int argc, char **argv)
209 case 'r': /* Dump tables from specified RSDP */ 209 case 'r': /* Dump tables from specified RSDP */
210 210
211 status = 211 status =
212 acpi_ut_strtoul64(acpi_gbl_optarg, 0, 212 acpi_ut_strtoul64(acpi_gbl_optarg, ACPI_ANY_BASE,
213 ACPI_MAX64_BYTE_WIDTH,
213 &gbl_rsdp_base); 214 &gbl_rsdp_base);
214 if (ACPI_FAILURE(status)) { 215 if (ACPI_FAILURE(status)) {
215 acpi_log_error 216 acpi_log_error
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index 0adaf0c7c03a..8358863259c5 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -63,7 +63,7 @@ DESTDIR ?=
63# and _should_ modify the PACKAGE_BUGREPORT definition 63# and _should_ modify the PACKAGE_BUGREPORT definition
64 64
65VERSION= $(shell ./utils/version-gen.sh) 65VERSION= $(shell ./utils/version-gen.sh)
66LIB_MAJ= 0.0.0 66LIB_MAJ= 0.0.1
67LIB_MIN= 0 67LIB_MIN= 0
68 68
69PACKAGE = cpupower 69PACKAGE = cpupower
@@ -129,7 +129,7 @@ WARNINGS += -Wshadow
129CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \ 129CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
130 -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE 130 -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE
131 131
132UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \ 132UTIL_OBJS = utils/helpers/amd.o utils/helpers/msr.o \
133 utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \ 133 utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \
134 utils/helpers/pci.o utils/helpers/bitmask.o \ 134 utils/helpers/pci.o utils/helpers/bitmask.o \
135 utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \ 135 utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \
@@ -148,9 +148,9 @@ UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
148 utils/helpers/bitmask.h \ 148 utils/helpers/bitmask.h \
149 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def 149 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
150 150
151LIB_HEADERS = lib/cpufreq.h lib/sysfs.h 151LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h
152LIB_SRC = lib/cpufreq.c lib/sysfs.c 152LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c
153LIB_OBJS = lib/cpufreq.o lib/sysfs.o 153LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o
154LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS)) 154LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS))
155 155
156CFLAGS += -pipe 156CFLAGS += -pipe
@@ -280,6 +280,7 @@ install-lib:
280 $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/ 280 $(CP) $(OUTPUT)libcpupower.so* $(DESTDIR)${libdir}/
281 $(INSTALL) -d $(DESTDIR)${includedir} 281 $(INSTALL) -d $(DESTDIR)${includedir}
282 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h 282 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
283 $(INSTALL_DATA) lib/cpuidle.h $(DESTDIR)${includedir}/cpuidle.h
283 284
284install-tools: 285install-tools:
285 $(INSTALL) -d $(DESTDIR)${bindir} 286 $(INSTALL) -d $(DESTDIR)${bindir}
@@ -315,6 +316,7 @@ endif
315uninstall: 316uninstall:
316 - rm -f $(DESTDIR)${libdir}/libcpupower.* 317 - rm -f $(DESTDIR)${libdir}/libcpupower.*
317 - rm -f $(DESTDIR)${includedir}/cpufreq.h 318 - rm -f $(DESTDIR)${includedir}/cpufreq.h
319 - rm -f $(DESTDIR)${includedir}/cpuidle.h
318 - rm -f $(DESTDIR)${bindir}/utils/cpupower 320 - rm -f $(DESTDIR)${bindir}/utils/cpupower
319 - rm -f $(DESTDIR)${mandir}/man1/cpupower.1 321 - rm -f $(DESTDIR)${mandir}/man1/cpupower.1
320 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 322 - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1
diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile
index d0f879b223fc..3e59f1aa3947 100644
--- a/tools/power/cpupower/bench/Makefile
+++ b/tools/power/cpupower/bench/Makefile
@@ -22,7 +22,7 @@ $(OUTPUT)%.o : %.c
22 22
23$(OUTPUT)cpufreq-bench: $(OBJS) 23$(OUTPUT)cpufreq-bench: $(OBJS)
24 $(ECHO) " CC " $@ 24 $(ECHO) " CC " $@
25 $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS) 25 $(QUIET) $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(OBJS) $(LIBS)
26 26
27all: $(OUTPUT)cpufreq-bench 27all: $(OUTPUT)cpufreq-bench
28 28
diff --git a/tools/power/cpupower/bench/README-BENCH b/tools/power/cpupower/bench/README-BENCH
index 8093ec738170..97727aed61cc 100644
--- a/tools/power/cpupower/bench/README-BENCH
+++ b/tools/power/cpupower/bench/README-BENCH
@@ -113,7 +113,7 @@ cpufreq-bench Command Usage
113-c, --cpu=<unsigned int> CPU Number to use, starting at 0 113-c, --cpu=<unsigned int> CPU Number to use, starting at 0
114-p, --prio=<priority> scheduler priority, HIGH, LOW or DEFAULT 114-p, --prio=<priority> scheduler priority, HIGH, LOW or DEFAULT
115-g, --governor=<governor> cpufreq governor to test 115-g, --governor=<governor> cpufreq governor to test
116-n, --cycles=<int> load/sleep cycles to get an avarage value to compare 116-n, --cycles=<int> load/sleep cycles to get an average value to compare
117-r, --rounds<int> load/sleep rounds 117-r, --rounds<int> load/sleep rounds
118-f, --file=<configfile> config file to use 118-f, --file=<configfile> config file to use
119-o, --output=<dir> output dir, must exist 119-o, --output=<dir> output dir, must exist
diff --git a/tools/power/cpupower/bench/benchmark.c b/tools/power/cpupower/bench/benchmark.c
index 81b1c48607d9..429d51ab8031 100644
--- a/tools/power/cpupower/bench/benchmark.c
+++ b/tools/power/cpupower/bench/benchmark.c
@@ -130,7 +130,7 @@ void start_benchmark(struct config *config)
130 _round, load_time, sleep_time); 130 _round, load_time, sleep_time);
131 131
132 if (config->verbose) 132 if (config->verbose)
133 printf("avarage: %lius, rps:%li\n", 133 printf("average: %lius, rps:%li\n",
134 load_time / calculations, 134 load_time / calculations,
135 1000000 * calculations / load_time); 135 1000000 * calculations / load_time);
136 136
@@ -177,7 +177,7 @@ void start_benchmark(struct config *config)
177 177
178 progress_time += sleep_time + load_time; 178 progress_time += sleep_time + load_time;
179 179
180 /* compare the avarage sleep/load cycles */ 180 /* compare the average sleep/load cycles */
181 fprintf(config->output, "%li ", 181 fprintf(config->output, "%li ",
182 powersave_time / config->cycles); 182 powersave_time / config->cycles);
183 fprintf(config->output, "%.3f\n", 183 fprintf(config->output, "%.3f\n",
diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c
index f503fb53824e..9b65f052081f 100644
--- a/tools/power/cpupower/bench/parse.c
+++ b/tools/power/cpupower/bench/parse.c
@@ -65,7 +65,7 @@ FILE *prepare_output(const char *dirname)
65{ 65{
66 FILE *output = NULL; 66 FILE *output = NULL;
67 int len; 67 int len;
68 char *filename; 68 char *filename, *filename_tmp;
69 struct utsname sysdata; 69 struct utsname sysdata;
70 DIR *dir; 70 DIR *dir;
71 71
@@ -81,16 +81,22 @@ FILE *prepare_output(const char *dirname)
81 81
82 len = strlen(dirname) + 30; 82 len = strlen(dirname) + 30;
83 filename = malloc(sizeof(char) * len); 83 filename = malloc(sizeof(char) * len);
84 if (!filename) {
85 perror("malloc");
86 goto out_dir;
87 }
84 88
85 if (uname(&sysdata) == 0) { 89 if (uname(&sysdata) == 0) {
86 len += strlen(sysdata.nodename) + strlen(sysdata.release); 90 len += strlen(sysdata.nodename) + strlen(sysdata.release);
87 filename = realloc(filename, sizeof(char) * len); 91 filename_tmp = realloc(filename, sizeof(*filename) * len);
88 92
89 if (filename == NULL) { 93 if (filename_tmp == NULL) {
94 free(filename);
90 perror("realloc"); 95 perror("realloc");
91 return NULL; 96 goto out_dir;
92 } 97 }
93 98
99 filename = filename_tmp;
94 snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log", 100 snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log",
95 dirname, sysdata.nodename, sysdata.release, time(NULL)); 101 dirname, sysdata.nodename, sysdata.release, time(NULL));
96 } else { 102 } else {
@@ -104,12 +110,16 @@ FILE *prepare_output(const char *dirname)
104 if (output == NULL) { 110 if (output == NULL) {
105 perror("fopen"); 111 perror("fopen");
106 fprintf(stderr, "error: unable to open logfile\n"); 112 fprintf(stderr, "error: unable to open logfile\n");
113 goto out;
107 } 114 }
108 115
109 fprintf(stdout, "Logfile: %s\n", filename); 116 fprintf(stdout, "Logfile: %s\n", filename);
110 117
111 free(filename);
112 fprintf(output, "#round load sleep performance powersave percentage\n"); 118 fprintf(output, "#round load sleep performance powersave percentage\n");
119out:
120 free(filename);
121out_dir:
122 closedir(dir);
113 return output; 123 return output;
114} 124}
115 125
diff --git a/tools/power/cpupower/bench/system.c b/tools/power/cpupower/bench/system.c
index f01e3f4be84c..c25a74ae51ba 100644
--- a/tools/power/cpupower/bench/system.c
+++ b/tools/power/cpupower/bench/system.c
@@ -26,6 +26,7 @@
26#include <sched.h> 26#include <sched.h>
27 27
28#include <cpufreq.h> 28#include <cpufreq.h>
29#include <cpupower.h>
29 30
30#include "config.h" 31#include "config.h"
31#include "system.h" 32#include "system.h"
@@ -60,7 +61,7 @@ int set_cpufreq_governor(char *governor, unsigned int cpu)
60 61
61 dprintf("set %s as cpufreq governor\n", governor); 62 dprintf("set %s as cpufreq governor\n", governor);
62 63
63 if (cpufreq_cpu_exists(cpu) != 0) { 64 if (cpupower_is_cpu_online(cpu) != 0) {
64 perror("cpufreq_cpu_exists"); 65 perror("cpufreq_cpu_exists");
65 fprintf(stderr, "error: cpu %u does not exist\n", cpu); 66 fprintf(stderr, "error: cpu %u does not exist\n", cpu);
66 return -1; 67 return -1;
diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
index d961101d1cea..1b993fe1ce23 100644
--- a/tools/power/cpupower/lib/cpufreq.c
+++ b/tools/power/cpupower/lib/cpufreq.c
@@ -9,28 +9,190 @@
9#include <errno.h> 9#include <errno.h>
10#include <stdlib.h> 10#include <stdlib.h>
11#include <string.h> 11#include <string.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
12 16
13#include "cpufreq.h" 17#include "cpufreq.h"
14#include "sysfs.h" 18#include "cpupower_intern.h"
15 19
16int cpufreq_cpu_exists(unsigned int cpu) 20/* CPUFREQ sysfs access **************************************************/
21
22/* helper function to read file from /sys into given buffer */
23/* fname is a relative path under "cpuX/cpufreq" dir */
24static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
25 char *buf, size_t buflen)
17{ 26{
18 return sysfs_cpu_exists(cpu); 27 char path[SYSFS_PATH_MAX];
28
29 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
30 cpu, fname);
31 return sysfs_read_file(path, buf, buflen);
19} 32}
20 33
34/* helper function to write a new value to a /sys file */
35/* fname is a relative path under "cpuX/cpufreq" dir */
36static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
37 const char *fname,
38 const char *value, size_t len)
39{
40 char path[SYSFS_PATH_MAX];
41 int fd;
42 ssize_t numwrite;
43
44 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
45 cpu, fname);
46
47 fd = open(path, O_WRONLY);
48 if (fd == -1)
49 return 0;
50
51 numwrite = write(fd, value, len);
52 if (numwrite < 1) {
53 close(fd);
54 return 0;
55 }
56
57 close(fd);
58
59 return (unsigned int) numwrite;
60}
61
62/* read access to files which contain one numeric value */
63
64enum cpufreq_value {
65 CPUINFO_CUR_FREQ,
66 CPUINFO_MIN_FREQ,
67 CPUINFO_MAX_FREQ,
68 CPUINFO_LATENCY,
69 SCALING_CUR_FREQ,
70 SCALING_MIN_FREQ,
71 SCALING_MAX_FREQ,
72 STATS_NUM_TRANSITIONS,
73 MAX_CPUFREQ_VALUE_READ_FILES
74};
75
76static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
77 [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
78 [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
79 [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
80 [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
81 [SCALING_CUR_FREQ] = "scaling_cur_freq",
82 [SCALING_MIN_FREQ] = "scaling_min_freq",
83 [SCALING_MAX_FREQ] = "scaling_max_freq",
84 [STATS_NUM_TRANSITIONS] = "stats/total_trans"
85};
86
87
88static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
89 enum cpufreq_value which)
90{
91 unsigned long value;
92 unsigned int len;
93 char linebuf[MAX_LINE_LEN];
94 char *endp;
95
96 if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
97 return 0;
98
99 len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
100 linebuf, sizeof(linebuf));
101
102 if (len == 0)
103 return 0;
104
105 value = strtoul(linebuf, &endp, 0);
106
107 if (endp == linebuf || errno == ERANGE)
108 return 0;
109
110 return value;
111}
112
113/* read access to files which contain one string */
114
115enum cpufreq_string {
116 SCALING_DRIVER,
117 SCALING_GOVERNOR,
118 MAX_CPUFREQ_STRING_FILES
119};
120
121static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
122 [SCALING_DRIVER] = "scaling_driver",
123 [SCALING_GOVERNOR] = "scaling_governor",
124};
125
126
127static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
128 enum cpufreq_string which)
129{
130 char linebuf[MAX_LINE_LEN];
131 char *result;
132 unsigned int len;
133
134 if (which >= MAX_CPUFREQ_STRING_FILES)
135 return NULL;
136
137 len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
138 linebuf, sizeof(linebuf));
139 if (len == 0)
140 return NULL;
141
142 result = strdup(linebuf);
143 if (result == NULL)
144 return NULL;
145
146 if (result[strlen(result) - 1] == '\n')
147 result[strlen(result) - 1] = '\0';
148
149 return result;
150}
151
152/* write access */
153
154enum cpufreq_write {
155 WRITE_SCALING_MIN_FREQ,
156 WRITE_SCALING_MAX_FREQ,
157 WRITE_SCALING_GOVERNOR,
158 WRITE_SCALING_SET_SPEED,
159 MAX_CPUFREQ_WRITE_FILES
160};
161
162static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
163 [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
164 [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
165 [WRITE_SCALING_GOVERNOR] = "scaling_governor",
166 [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
167};
168
169static int sysfs_cpufreq_write_one_value(unsigned int cpu,
170 enum cpufreq_write which,
171 const char *new_value, size_t len)
172{
173 if (which >= MAX_CPUFREQ_WRITE_FILES)
174 return 0;
175
176 if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
177 new_value, len) != len)
178 return -ENODEV;
179
180 return 0;
181};
182
21unsigned long cpufreq_get_freq_kernel(unsigned int cpu) 183unsigned long cpufreq_get_freq_kernel(unsigned int cpu)
22{ 184{
23 return sysfs_get_freq_kernel(cpu); 185 return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
24} 186}
25 187
26unsigned long cpufreq_get_freq_hardware(unsigned int cpu) 188unsigned long cpufreq_get_freq_hardware(unsigned int cpu)
27{ 189{
28 return sysfs_get_freq_hardware(cpu); 190 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
29} 191}
30 192
31unsigned long cpufreq_get_transition_latency(unsigned int cpu) 193unsigned long cpufreq_get_transition_latency(unsigned int cpu)
32{ 194{
33 return sysfs_get_freq_transition_latency(cpu); 195 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
34} 196}
35 197
36int cpufreq_get_hardware_limits(unsigned int cpu, 198int cpufreq_get_hardware_limits(unsigned int cpu,
@@ -39,12 +201,21 @@ int cpufreq_get_hardware_limits(unsigned int cpu,
39{ 201{
40 if ((!min) || (!max)) 202 if ((!min) || (!max))
41 return -EINVAL; 203 return -EINVAL;
42 return sysfs_get_freq_hardware_limits(cpu, min, max); 204
205 *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
206 if (!*min)
207 return -ENODEV;
208
209 *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
210 if (!*max)
211 return -ENODEV;
212
213 return 0;
43} 214}
44 215
45char *cpufreq_get_driver(unsigned int cpu) 216char *cpufreq_get_driver(unsigned int cpu)
46{ 217{
47 return sysfs_get_freq_driver(cpu); 218 return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
48} 219}
49 220
50void cpufreq_put_driver(char *ptr) 221void cpufreq_put_driver(char *ptr)
@@ -56,7 +227,26 @@ void cpufreq_put_driver(char *ptr)
56 227
57struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu) 228struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu)
58{ 229{
59 return sysfs_get_freq_policy(cpu); 230 struct cpufreq_policy *policy;
231
232 policy = malloc(sizeof(struct cpufreq_policy));
233 if (!policy)
234 return NULL;
235
236 policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
237 if (!policy->governor) {
238 free(policy);
239 return NULL;
240 }
241 policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
242 policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
243 if ((!policy->min) || (!policy->max)) {
244 free(policy->governor);
245 free(policy);
246 return NULL;
247 }
248
249 return policy;
60} 250}
61 251
62void cpufreq_put_policy(struct cpufreq_policy *policy) 252void cpufreq_put_policy(struct cpufreq_policy *policy)
@@ -72,7 +262,57 @@ void cpufreq_put_policy(struct cpufreq_policy *policy)
72struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned 262struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned
73 int cpu) 263 int cpu)
74{ 264{
75 return sysfs_get_freq_available_governors(cpu); 265 struct cpufreq_available_governors *first = NULL;
266 struct cpufreq_available_governors *current = NULL;
267 char linebuf[MAX_LINE_LEN];
268 unsigned int pos, i;
269 unsigned int len;
270
271 len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
272 linebuf, sizeof(linebuf));
273 if (len == 0)
274 return NULL;
275
276 pos = 0;
277 for (i = 0; i < len; i++) {
278 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
279 if (i - pos < 2)
280 continue;
281 if (current) {
282 current->next = malloc(sizeof(*current));
283 if (!current->next)
284 goto error_out;
285 current = current->next;
286 } else {
287 first = malloc(sizeof(*first));
288 if (!first)
289 goto error_out;
290 current = first;
291 }
292 current->first = first;
293 current->next = NULL;
294
295 current->governor = malloc(i - pos + 1);
296 if (!current->governor)
297 goto error_out;
298
299 memcpy(current->governor, linebuf + pos, i - pos);
300 current->governor[i - pos] = '\0';
301 pos = i + 1;
302 }
303 }
304
305 return first;
306
307 error_out:
308 while (first) {
309 current = first->next;
310 if (first->governor)
311 free(first->governor);
312 free(first);
313 first = current;
314 }
315 return NULL;
76} 316}
77 317
78void cpufreq_put_available_governors(struct cpufreq_available_governors *any) 318void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
@@ -96,7 +336,57 @@ void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
96struct cpufreq_available_frequencies 336struct cpufreq_available_frequencies
97*cpufreq_get_available_frequencies(unsigned int cpu) 337*cpufreq_get_available_frequencies(unsigned int cpu)
98{ 338{
99 return sysfs_get_available_frequencies(cpu); 339 struct cpufreq_available_frequencies *first = NULL;
340 struct cpufreq_available_frequencies *current = NULL;
341 char one_value[SYSFS_PATH_MAX];
342 char linebuf[MAX_LINE_LEN];
343 unsigned int pos, i;
344 unsigned int len;
345
346 len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
347 linebuf, sizeof(linebuf));
348 if (len == 0)
349 return NULL;
350
351 pos = 0;
352 for (i = 0; i < len; i++) {
353 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
354 if (i - pos < 2)
355 continue;
356 if (i - pos >= SYSFS_PATH_MAX)
357 goto error_out;
358 if (current) {
359 current->next = malloc(sizeof(*current));
360 if (!current->next)
361 goto error_out;
362 current = current->next;
363 } else {
364 first = malloc(sizeof(*first));
365 if (!first)
366 goto error_out;
367 current = first;
368 }
369 current->first = first;
370 current->next = NULL;
371
372 memcpy(one_value, linebuf + pos, i - pos);
373 one_value[i - pos] = '\0';
374 if (sscanf(one_value, "%lu", &current->frequency) != 1)
375 goto error_out;
376
377 pos = i + 1;
378 }
379 }
380
381 return first;
382
383 error_out:
384 while (first) {
385 current = first->next;
386 free(first);
387 first = current;
388 }
389 return NULL;
100} 390}
101 391
102void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies 392void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies
@@ -114,10 +404,65 @@ void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies
114 } 404 }
115} 405}
116 406
407static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
408 const char *file)
409{
410 struct cpufreq_affected_cpus *first = NULL;
411 struct cpufreq_affected_cpus *current = NULL;
412 char one_value[SYSFS_PATH_MAX];
413 char linebuf[MAX_LINE_LEN];
414 unsigned int pos, i;
415 unsigned int len;
416
417 len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
418 if (len == 0)
419 return NULL;
420
421 pos = 0;
422 for (i = 0; i < len; i++) {
423 if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
424 if (i - pos < 1)
425 continue;
426 if (i - pos >= SYSFS_PATH_MAX)
427 goto error_out;
428 if (current) {
429 current->next = malloc(sizeof(*current));
430 if (!current->next)
431 goto error_out;
432 current = current->next;
433 } else {
434 first = malloc(sizeof(*first));
435 if (!first)
436 goto error_out;
437 current = first;
438 }
439 current->first = first;
440 current->next = NULL;
441
442 memcpy(one_value, linebuf + pos, i - pos);
443 one_value[i - pos] = '\0';
444
445 if (sscanf(one_value, "%u", &current->cpu) != 1)
446 goto error_out;
447
448 pos = i + 1;
449 }
450 }
451
452 return first;
453
454 error_out:
455 while (first) {
456 current = first->next;
457 free(first);
458 first = current;
459 }
460 return NULL;
461}
117 462
118struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu) 463struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu)
119{ 464{
120 return sysfs_get_freq_affected_cpus(cpu); 465 return sysfs_get_cpu_list(cpu, "affected_cpus");
121} 466}
122 467
123void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any) 468void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
@@ -138,7 +483,7 @@ void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
138 483
139struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu) 484struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu)
140{ 485{
141 return sysfs_get_freq_related_cpus(cpu); 486 return sysfs_get_cpu_list(cpu, "related_cpus");
142} 487}
143 488
144void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any) 489void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
@@ -146,45 +491,208 @@ void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
146 cpufreq_put_affected_cpus(any); 491 cpufreq_put_affected_cpus(any);
147} 492}
148 493
494static int verify_gov(char *new_gov, char *passed_gov)
495{
496 unsigned int i, j = 0;
497
498 if (!passed_gov || (strlen(passed_gov) > 19))
499 return -EINVAL;
500
501 strncpy(new_gov, passed_gov, 20);
502 for (i = 0; i < 20; i++) {
503 if (j) {
504 new_gov[i] = '\0';
505 continue;
506 }
507 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
508 continue;
509
510 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
511 continue;
512
513 if (new_gov[i] == '-')
514 continue;
515
516 if (new_gov[i] == '_')
517 continue;
518
519 if (new_gov[i] == '\0') {
520 j = 1;
521 continue;
522 }
523 return -EINVAL;
524 }
525 new_gov[19] = '\0';
526 return 0;
527}
149 528
150int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) 529int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
151{ 530{
531 char min[SYSFS_PATH_MAX];
532 char max[SYSFS_PATH_MAX];
533 char gov[SYSFS_PATH_MAX];
534 int ret;
535 unsigned long old_min;
536 int write_max_first;
537
152 if (!policy || !(policy->governor)) 538 if (!policy || !(policy->governor))
153 return -EINVAL; 539 return -EINVAL;
154 540
155 return sysfs_set_freq_policy(cpu, policy); 541 if (policy->max < policy->min)
542 return -EINVAL;
543
544 if (verify_gov(gov, policy->governor))
545 return -EINVAL;
546
547 snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
548 snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
549
550 old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
551 write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
552
553 if (write_max_first) {
554 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
555 max, strlen(max));
556 if (ret)
557 return ret;
558 }
559
560 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
561 strlen(min));
562 if (ret)
563 return ret;
564
565 if (!write_max_first) {
566 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
567 max, strlen(max));
568 if (ret)
569 return ret;
570 }
571
572 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
573 gov, strlen(gov));
156} 574}
157 575
158 576
159int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq) 577int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq)
160{ 578{
161 return sysfs_modify_freq_policy_min(cpu, min_freq); 579 char value[SYSFS_PATH_MAX];
580
581 snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
582
583 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
584 value, strlen(value));
162} 585}
163 586
164 587
165int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq) 588int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq)
166{ 589{
167 return sysfs_modify_freq_policy_max(cpu, max_freq); 590 char value[SYSFS_PATH_MAX];
168} 591
592 snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
169 593
594 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
595 value, strlen(value));
596}
170 597
171int cpufreq_modify_policy_governor(unsigned int cpu, char *governor) 598int cpufreq_modify_policy_governor(unsigned int cpu, char *governor)
172{ 599{
600 char new_gov[SYSFS_PATH_MAX];
601
173 if ((!governor) || (strlen(governor) > 19)) 602 if ((!governor) || (strlen(governor) > 19))
174 return -EINVAL; 603 return -EINVAL;
175 604
176 return sysfs_modify_freq_policy_governor(cpu, governor); 605 if (verify_gov(new_gov, governor))
606 return -EINVAL;
607
608 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
609 new_gov, strlen(new_gov));
177} 610}
178 611
179int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency) 612int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency)
180{ 613{
181 return sysfs_set_frequency(cpu, target_frequency); 614 struct cpufreq_policy *pol = cpufreq_get_policy(cpu);
615 char userspace_gov[] = "userspace";
616 char freq[SYSFS_PATH_MAX];
617 int ret;
618
619 if (!pol)
620 return -ENODEV;
621
622 if (strncmp(pol->governor, userspace_gov, 9) != 0) {
623 ret = cpufreq_modify_policy_governor(cpu, userspace_gov);
624 if (ret) {
625 cpufreq_put_policy(pol);
626 return ret;
627 }
628 }
629
630 cpufreq_put_policy(pol);
631
632 snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
633
634 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
635 freq, strlen(freq));
182} 636}
183 637
184struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu, 638struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
185 unsigned long long *total_time) 639 unsigned long long *total_time)
186{ 640{
187 return sysfs_get_freq_stats(cpu, total_time); 641 struct cpufreq_stats *first = NULL;
642 struct cpufreq_stats *current = NULL;
643 char one_value[SYSFS_PATH_MAX];
644 char linebuf[MAX_LINE_LEN];
645 unsigned int pos, i;
646 unsigned int len;
647
648 len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
649 linebuf, sizeof(linebuf));
650 if (len == 0)
651 return NULL;
652
653 *total_time = 0;
654 pos = 0;
655 for (i = 0; i < len; i++) {
656 if (i == strlen(linebuf) || linebuf[i] == '\n') {
657 if (i - pos < 2)
658 continue;
659 if ((i - pos) >= SYSFS_PATH_MAX)
660 goto error_out;
661 if (current) {
662 current->next = malloc(sizeof(*current));
663 if (!current->next)
664 goto error_out;
665 current = current->next;
666 } else {
667 first = malloc(sizeof(*first));
668 if (!first)
669 goto error_out;
670 current = first;
671 }
672 current->first = first;
673 current->next = NULL;
674
675 memcpy(one_value, linebuf + pos, i - pos);
676 one_value[i - pos] = '\0';
677 if (sscanf(one_value, "%lu %llu",
678 &current->frequency,
679 &current->time_in_state) != 2)
680 goto error_out;
681
682 *total_time = *total_time + current->time_in_state;
683 pos = i + 1;
684 }
685 }
686
687 return first;
688
689 error_out:
690 while (first) {
691 current = first->next;
692 free(first);
693 first = current;
694 }
695 return NULL;
188} 696}
189 697
190void cpufreq_put_stats(struct cpufreq_stats *any) 698void cpufreq_put_stats(struct cpufreq_stats *any)
@@ -204,5 +712,5 @@ void cpufreq_put_stats(struct cpufreq_stats *any)
204 712
205unsigned long cpufreq_get_transitions(unsigned int cpu) 713unsigned long cpufreq_get_transitions(unsigned int cpu)
206{ 714{
207 return sysfs_get_freq_transitions(cpu); 715 return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
208} 716}
diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
index 3aae8e7a0839..3b005c39f068 100644
--- a/tools/power/cpupower/lib/cpufreq.h
+++ b/tools/power/cpupower/lib/cpufreq.h
@@ -17,8 +17,8 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20#ifndef _CPUFREQ_H 20#ifndef __CPUPOWER_CPUFREQ_H__
21#define _CPUFREQ_H 1 21#define __CPUPOWER_CPUFREQ_H__
22 22
23struct cpufreq_policy { 23struct cpufreq_policy {
24 unsigned long min; 24 unsigned long min;
@@ -58,13 +58,6 @@ struct cpufreq_stats {
58extern "C" { 58extern "C" {
59#endif 59#endif
60 60
61/*
62 * returns 0 if the specified CPU is present (it doesn't say
63 * whether it is online!), and an error value if not.
64 */
65
66extern int cpufreq_cpu_exists(unsigned int cpu);
67
68/* determine current CPU frequency 61/* determine current CPU frequency
69 * - _kernel variant means kernel's opinion of CPU frequency 62 * - _kernel variant means kernel's opinion of CPU frequency
70 * - _hardware variant means actual hardware CPU frequency, 63 * - _hardware variant means actual hardware CPU frequency,
@@ -73,9 +66,9 @@ extern int cpufreq_cpu_exists(unsigned int cpu);
73 * returns 0 on failure, else frequency in kHz. 66 * returns 0 on failure, else frequency in kHz.
74 */ 67 */
75 68
76extern unsigned long cpufreq_get_freq_kernel(unsigned int cpu); 69unsigned long cpufreq_get_freq_kernel(unsigned int cpu);
77 70
78extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu); 71unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
79 72
80#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu); 73#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu);
81 74
@@ -84,7 +77,7 @@ extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
84 * 77 *
85 * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds 78 * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds
86 */ 79 */
87extern unsigned long cpufreq_get_transition_latency(unsigned int cpu); 80unsigned long cpufreq_get_transition_latency(unsigned int cpu);
88 81
89 82
90/* determine hardware CPU frequency limits 83/* determine hardware CPU frequency limits
@@ -93,7 +86,7 @@ extern unsigned long cpufreq_get_transition_latency(unsigned int cpu);
93 * considerations by cpufreq policy notifiers in the kernel. 86 * considerations by cpufreq policy notifiers in the kernel.
94 */ 87 */
95 88
96extern int cpufreq_get_hardware_limits(unsigned int cpu, 89int cpufreq_get_hardware_limits(unsigned int cpu,
97 unsigned long *min, 90 unsigned long *min,
98 unsigned long *max); 91 unsigned long *max);
99 92
@@ -104,9 +97,9 @@ extern int cpufreq_get_hardware_limits(unsigned int cpu,
104 * to avoid memory leakage, please. 97 * to avoid memory leakage, please.
105 */ 98 */
106 99
107extern char *cpufreq_get_driver(unsigned int cpu); 100char *cpufreq_get_driver(unsigned int cpu);
108 101
109extern void cpufreq_put_driver(char *ptr); 102void cpufreq_put_driver(char *ptr);
110 103
111 104
112/* determine CPUfreq policy currently used 105/* determine CPUfreq policy currently used
@@ -116,9 +109,9 @@ extern void cpufreq_put_driver(char *ptr);
116 */ 109 */
117 110
118 111
119extern struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu); 112struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu);
120 113
121extern void cpufreq_put_policy(struct cpufreq_policy *policy); 114void cpufreq_put_policy(struct cpufreq_policy *policy);
122 115
123 116
124/* determine CPUfreq governors currently available 117/* determine CPUfreq governors currently available
@@ -129,10 +122,10 @@ extern void cpufreq_put_policy(struct cpufreq_policy *policy);
129 */ 122 */
130 123
131 124
132extern struct cpufreq_available_governors 125struct cpufreq_available_governors
133*cpufreq_get_available_governors(unsigned int cpu); 126*cpufreq_get_available_governors(unsigned int cpu);
134 127
135extern void cpufreq_put_available_governors( 128void cpufreq_put_available_governors(
136 struct cpufreq_available_governors *first); 129 struct cpufreq_available_governors *first);
137 130
138 131
@@ -143,10 +136,10 @@ extern void cpufreq_put_available_governors(
143 * cpufreq_put_available_frequencies after use. 136 * cpufreq_put_available_frequencies after use.
144 */ 137 */
145 138
146extern struct cpufreq_available_frequencies 139struct cpufreq_available_frequencies
147*cpufreq_get_available_frequencies(unsigned int cpu); 140*cpufreq_get_available_frequencies(unsigned int cpu);
148 141
149extern void cpufreq_put_available_frequencies( 142void cpufreq_put_available_frequencies(
150 struct cpufreq_available_frequencies *first); 143 struct cpufreq_available_frequencies *first);
151 144
152 145
@@ -156,10 +149,10 @@ extern void cpufreq_put_available_frequencies(
156 * to avoid memory leakage, please. 149 * to avoid memory leakage, please.
157 */ 150 */
158 151
159extern struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned 152struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned
160 int cpu); 153 int cpu);
161 154
162extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first); 155void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first);
163 156
164 157
165/* determine related CPUs 158/* determine related CPUs
@@ -168,10 +161,10 @@ extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first);
168 * to avoid memory leakage, please. 161 * to avoid memory leakage, please.
169 */ 162 */
170 163
171extern struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned 164struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned
172 int cpu); 165 int cpu);
173 166
174extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first); 167void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first);
175 168
176 169
177/* determine stats for cpufreq subsystem 170/* determine stats for cpufreq subsystem
@@ -179,12 +172,12 @@ extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first);
179 * This is not available in all kernel versions or configurations. 172 * This is not available in all kernel versions or configurations.
180 */ 173 */
181 174
182extern struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu, 175struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
183 unsigned long long *total_time); 176 unsigned long long *total_time);
184 177
185extern void cpufreq_put_stats(struct cpufreq_stats *stats); 178void cpufreq_put_stats(struct cpufreq_stats *stats);
186 179
187extern unsigned long cpufreq_get_transitions(unsigned int cpu); 180unsigned long cpufreq_get_transitions(unsigned int cpu);
188 181
189 182
190/* set new cpufreq policy 183/* set new cpufreq policy
@@ -193,7 +186,7 @@ extern unsigned long cpufreq_get_transitions(unsigned int cpu);
193 * but results may differ depending e.g. on governors being available. 186 * but results may differ depending e.g. on governors being available.
194 */ 187 */
195 188
196extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy); 189int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
197 190
198 191
199/* modify a policy by only changing min/max freq or governor 192/* modify a policy by only changing min/max freq or governor
@@ -201,9 +194,9 @@ extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
201 * Does not check whether result is what was intended. 194 * Does not check whether result is what was intended.
202 */ 195 */
203 196
204extern int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq); 197int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq);
205extern int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq); 198int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq);
206extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor); 199int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
207 200
208 201
209/* set a specific frequency 202/* set a specific frequency
@@ -213,7 +206,7 @@ extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
213 * occurs. Also does not work on ->range() cpufreq drivers. 206 * occurs. Also does not work on ->range() cpufreq drivers.
214 */ 207 */
215 208
216extern int cpufreq_set_frequency(unsigned int cpu, 209int cpufreq_set_frequency(unsigned int cpu,
217 unsigned long target_frequency); 210 unsigned long target_frequency);
218 211
219#ifdef __cplusplus 212#ifdef __cplusplus
diff --git a/tools/power/cpupower/lib/cpuidle.c b/tools/power/cpupower/lib/cpuidle.c
new file mode 100644
index 000000000000..9bd4c7655fdb
--- /dev/null
+++ b/tools/power/cpupower/lib/cpuidle.c
@@ -0,0 +1,380 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 * (C) 2011 Thomas Renninger <trenn@novell.com> Novell Inc.
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 */
7
8#include <stdio.h>
9#include <errno.h>
10#include <stdlib.h>
11#include <string.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include "cpuidle.h"
18#include "cpupower_intern.h"
19
20/*
21 * helper function to check whether a file under "../cpuX/cpuidle/stateX/" dir
22 * exists.
23 * For example the functionality to disable c-states was introduced in later
24 * kernel versions, this function can be used to explicitly check for this
25 * feature.
26 *
27 * returns 1 if the file exists, 0 otherwise.
28 */
29static
30unsigned int cpuidle_state_file_exists(unsigned int cpu,
31 unsigned int idlestate,
32 const char *fname)
33{
34 char path[SYSFS_PATH_MAX];
35 struct stat statbuf;
36
37
38 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
39 cpu, idlestate, fname);
40 if (stat(path, &statbuf) != 0)
41 return 0;
42 return 1;
43}
44
45/*
46 * helper function to read file from /sys into given buffer
47 * fname is a relative path under "cpuX/cpuidle/stateX/" dir
48 * cstates starting with 0, C0 is not counted as cstate.
49 * This means if you want C1 info, pass 0 as idlestate param
50 */
51static
52unsigned int cpuidle_state_read_file(unsigned int cpu,
53 unsigned int idlestate,
54 const char *fname, char *buf,
55 size_t buflen)
56{
57 char path[SYSFS_PATH_MAX];
58 int fd;
59 ssize_t numread;
60
61 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
62 cpu, idlestate, fname);
63
64 fd = open(path, O_RDONLY);
65 if (fd == -1)
66 return 0;
67
68 numread = read(fd, buf, buflen - 1);
69 if (numread < 1) {
70 close(fd);
71 return 0;
72 }
73
74 buf[numread] = '\0';
75 close(fd);
76
77 return (unsigned int) numread;
78}
79
80/*
81 * helper function to write a new value to a /sys file
82 * fname is a relative path under "../cpuX/cpuidle/cstateY/" dir
83 *
84 * Returns the number of bytes written or 0 on error
85 */
86static
87unsigned int cpuidle_state_write_file(unsigned int cpu,
88 unsigned int idlestate,
89 const char *fname,
90 const char *value, size_t len)
91{
92 char path[SYSFS_PATH_MAX];
93 int fd;
94 ssize_t numwrite;
95
96 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
97 cpu, idlestate, fname);
98
99 fd = open(path, O_WRONLY);
100 if (fd == -1)
101 return 0;
102
103 numwrite = write(fd, value, len);
104 if (numwrite < 1) {
105 close(fd);
106 return 0;
107 }
108
109 close(fd);
110
111 return (unsigned int) numwrite;
112}
113
114/* read access to files which contain one numeric value */
115
116enum idlestate_value {
117 IDLESTATE_USAGE,
118 IDLESTATE_POWER,
119 IDLESTATE_LATENCY,
120 IDLESTATE_TIME,
121 IDLESTATE_DISABLE,
122 MAX_IDLESTATE_VALUE_FILES
123};
124
125static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
126 [IDLESTATE_USAGE] = "usage",
127 [IDLESTATE_POWER] = "power",
128 [IDLESTATE_LATENCY] = "latency",
129 [IDLESTATE_TIME] = "time",
130 [IDLESTATE_DISABLE] = "disable",
131};
132
133static
134unsigned long long cpuidle_state_get_one_value(unsigned int cpu,
135 unsigned int idlestate,
136 enum idlestate_value which)
137{
138 unsigned long long value;
139 unsigned int len;
140 char linebuf[MAX_LINE_LEN];
141 char *endp;
142
143 if (which >= MAX_IDLESTATE_VALUE_FILES)
144 return 0;
145
146 len = cpuidle_state_read_file(cpu, idlestate,
147 idlestate_value_files[which],
148 linebuf, sizeof(linebuf));
149 if (len == 0)
150 return 0;
151
152 value = strtoull(linebuf, &endp, 0);
153
154 if (endp == linebuf || errno == ERANGE)
155 return 0;
156
157 return value;
158}
159
160/* read access to files which contain one string */
161
162enum idlestate_string {
163 IDLESTATE_DESC,
164 IDLESTATE_NAME,
165 MAX_IDLESTATE_STRING_FILES
166};
167
168static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = {
169 [IDLESTATE_DESC] = "desc",
170 [IDLESTATE_NAME] = "name",
171};
172
173
174static char *cpuidle_state_get_one_string(unsigned int cpu,
175 unsigned int idlestate,
176 enum idlestate_string which)
177{
178 char linebuf[MAX_LINE_LEN];
179 char *result;
180 unsigned int len;
181
182 if (which >= MAX_IDLESTATE_STRING_FILES)
183 return NULL;
184
185 len = cpuidle_state_read_file(cpu, idlestate,
186 idlestate_string_files[which],
187 linebuf, sizeof(linebuf));
188 if (len == 0)
189 return NULL;
190
191 result = strdup(linebuf);
192 if (result == NULL)
193 return NULL;
194
195 if (result[strlen(result) - 1] == '\n')
196 result[strlen(result) - 1] = '\0';
197
198 return result;
199}
200
201/*
202 * Returns:
203 * 1 if disabled
204 * 0 if enabled
205 * -1 if idlestate is not available
206 * -2 if disabling is not supported by the kernel
207 */
208int cpuidle_is_state_disabled(unsigned int cpu,
209 unsigned int idlestate)
210{
211 if (cpuidle_state_count(cpu) <= idlestate)
212 return -1;
213
214 if (!cpuidle_state_file_exists(cpu, idlestate,
215 idlestate_value_files[IDLESTATE_DISABLE]))
216 return -2;
217 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_DISABLE);
218}
219
220/*
221 * Pass 1 as last argument to disable or 0 to enable the state
222 * Returns:
223 * 0 on success
224 * negative values on error, for example:
225 * -1 if idlestate is not available
226 * -2 if disabling is not supported by the kernel
227 * -3 No write access to disable/enable C-states
228 */
229int cpuidle_state_disable(unsigned int cpu,
230 unsigned int idlestate,
231 unsigned int disable)
232{
233 char value[SYSFS_PATH_MAX];
234 int bytes_written;
235
236 if (cpuidle_state_count(cpu) <= idlestate)
237 return -1;
238
239 if (!cpuidle_state_file_exists(cpu, idlestate,
240 idlestate_value_files[IDLESTATE_DISABLE]))
241 return -2;
242
243 snprintf(value, SYSFS_PATH_MAX, "%u", disable);
244
245 bytes_written = cpuidle_state_write_file(cpu, idlestate, "disable",
246 value, sizeof(disable));
247 if (bytes_written)
248 return 0;
249 return -3;
250}
251
252unsigned long cpuidle_state_latency(unsigned int cpu,
253 unsigned int idlestate)
254{
255 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
256}
257
258unsigned long cpuidle_state_usage(unsigned int cpu,
259 unsigned int idlestate)
260{
261 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_USAGE);
262}
263
264unsigned long long cpuidle_state_time(unsigned int cpu,
265 unsigned int idlestate)
266{
267 return cpuidle_state_get_one_value(cpu, idlestate, IDLESTATE_TIME);
268}
269
270char *cpuidle_state_name(unsigned int cpu, unsigned int idlestate)
271{
272 return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_NAME);
273}
274
275char *cpuidle_state_desc(unsigned int cpu, unsigned int idlestate)
276{
277 return cpuidle_state_get_one_string(cpu, idlestate, IDLESTATE_DESC);
278}
279
280/*
281 * Returns number of supported C-states of CPU core cpu
282 * Negativ in error case
283 * Zero if cpuidle does not export any C-states
284 */
285unsigned int cpuidle_state_count(unsigned int cpu)
286{
287 char file[SYSFS_PATH_MAX];
288 struct stat statbuf;
289 int idlestates = 1;
290
291
292 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
293 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
294 return 0;
295
296 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
297 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
298 return 0;
299
300 while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
301 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
302 "cpu%u/cpuidle/state%d", cpu, idlestates);
303 idlestates++;
304 }
305 idlestates--;
306 return idlestates;
307}
308
309/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
310
311/*
312 * helper function to read file from /sys into given buffer
313 * fname is a relative path under "cpu/cpuidle/" dir
314 */
315static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
316 size_t buflen)
317{
318 char path[SYSFS_PATH_MAX];
319
320 snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
321
322 return sysfs_read_file(path, buf, buflen);
323}
324
325
326
327/* read access to files which contain one string */
328
329enum cpuidle_string {
330 CPUIDLE_GOVERNOR,
331 CPUIDLE_GOVERNOR_RO,
332 CPUIDLE_DRIVER,
333 MAX_CPUIDLE_STRING_FILES
334};
335
336static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
337 [CPUIDLE_GOVERNOR] = "current_governor",
338 [CPUIDLE_GOVERNOR_RO] = "current_governor_ro",
339 [CPUIDLE_DRIVER] = "current_driver",
340};
341
342
343static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which)
344{
345 char linebuf[MAX_LINE_LEN];
346 char *result;
347 unsigned int len;
348
349 if (which >= MAX_CPUIDLE_STRING_FILES)
350 return NULL;
351
352 len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
353 linebuf, sizeof(linebuf));
354 if (len == 0)
355 return NULL;
356
357 result = strdup(linebuf);
358 if (result == NULL)
359 return NULL;
360
361 if (result[strlen(result) - 1] == '\n')
362 result[strlen(result) - 1] = '\0';
363
364 return result;
365}
366
367char *cpuidle_get_governor(void)
368{
369 char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
370 if (!tmp)
371 return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
372 else
373 return tmp;
374}
375
376char *cpuidle_get_driver(void)
377{
378 return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
379}
380/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
diff --git a/tools/power/cpupower/lib/cpuidle.h b/tools/power/cpupower/lib/cpuidle.h
new file mode 100644
index 000000000000..04eb3cfa6e42
--- /dev/null
+++ b/tools/power/cpupower/lib/cpuidle.h
@@ -0,0 +1,23 @@
1#ifndef __CPUPOWER_CPUIDLE_H__
2#define __CPUPOWER_CPUIDLE_H__
3
4int cpuidle_is_state_disabled(unsigned int cpu,
5 unsigned int idlestate);
6int cpuidle_state_disable(unsigned int cpu, unsigned int idlestate,
7 unsigned int disable);
8unsigned long cpuidle_state_latency(unsigned int cpu,
9 unsigned int idlestate);
10unsigned long cpuidle_state_usage(unsigned int cpu,
11 unsigned int idlestate);
12unsigned long long cpuidle_state_time(unsigned int cpu,
13 unsigned int idlestate);
14char *cpuidle_state_name(unsigned int cpu,
15 unsigned int idlestate);
16char *cpuidle_state_desc(unsigned int cpu,
17 unsigned int idlestate);
18unsigned int cpuidle_state_count(unsigned int cpu);
19
20char *cpuidle_get_governor(void);
21char *cpuidle_get_driver(void);
22
23#endif /* __CPUPOWER_HELPERS_SYSFS_H__ */
diff --git a/tools/power/cpupower/lib/cpupower.c b/tools/power/cpupower/lib/cpupower.c
new file mode 100644
index 000000000000..9c395ec924de
--- /dev/null
+++ b/tools/power/cpupower/lib/cpupower.c
@@ -0,0 +1,192 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10#include <unistd.h>
11#include <stdio.h>
12#include <errno.h>
13#include <stdlib.h>
14
15#include "cpupower.h"
16#include "cpupower_intern.h"
17
18unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
19{
20 int fd;
21 ssize_t numread;
22
23 fd = open(path, O_RDONLY);
24 if (fd == -1)
25 return 0;
26
27 numread = read(fd, buf, buflen - 1);
28 if (numread < 1) {
29 close(fd);
30 return 0;
31 }
32
33 buf[numread] = '\0';
34 close(fd);
35
36 return (unsigned int) numread;
37}
38
39/*
40 * Detect whether a CPU is online
41 *
42 * Returns:
43 * 1 -> if CPU is online
44 * 0 -> if CPU is offline
45 * negative errno values in error case
46 */
47int cpupower_is_cpu_online(unsigned int cpu)
48{
49 char path[SYSFS_PATH_MAX];
50 int fd;
51 ssize_t numread;
52 unsigned long long value;
53 char linebuf[MAX_LINE_LEN];
54 char *endp;
55 struct stat statbuf;
56
57 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u", cpu);
58
59 if (stat(path, &statbuf) != 0)
60 return 0;
61
62 /*
63 * kernel without CONFIG_HOTPLUG_CPU
64 * -> cpuX directory exists, but not cpuX/online file
65 */
66 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/online", cpu);
67 if (stat(path, &statbuf) != 0)
68 return 1;
69
70 fd = open(path, O_RDONLY);
71 if (fd == -1)
72 return -errno;
73
74 numread = read(fd, linebuf, MAX_LINE_LEN - 1);
75 if (numread < 1) {
76 close(fd);
77 return -EIO;
78 }
79 linebuf[numread] = '\0';
80 close(fd);
81
82 value = strtoull(linebuf, &endp, 0);
83 if (value > 1)
84 return -EINVAL;
85
86 return value;
87}
88
89/* returns -1 on failure, 0 on success */
90static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
91{
92 char linebuf[MAX_LINE_LEN];
93 char *endp;
94 char path[SYSFS_PATH_MAX];
95
96 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
97 cpu, fname);
98 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
99 return -1;
100 *result = strtol(linebuf, &endp, 0);
101 if (endp == linebuf || errno == ERANGE)
102 return -1;
103 return 0;
104}
105
106static int __compare(const void *t1, const void *t2)
107{
108 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
109 struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
110 if (top1->pkg < top2->pkg)
111 return -1;
112 else if (top1->pkg > top2->pkg)
113 return 1;
114 else if (top1->core < top2->core)
115 return -1;
116 else if (top1->core > top2->core)
117 return 1;
118 else if (top1->cpu < top2->cpu)
119 return -1;
120 else if (top1->cpu > top2->cpu)
121 return 1;
122 else
123 return 0;
124}
125
126/*
127 * Returns amount of cpus, negative on error, cpu_top must be
128 * passed to cpu_topology_release to free resources
129 *
130 * Array is sorted after ->pkg, ->core, then ->cpu
131 */
132int get_cpu_topology(struct cpupower_topology *cpu_top)
133{
134 int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
135
136 cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
137 if (cpu_top->core_info == NULL)
138 return -ENOMEM;
139 cpu_top->pkgs = cpu_top->cores = 0;
140 for (cpu = 0; cpu < cpus; cpu++) {
141 cpu_top->core_info[cpu].cpu = cpu;
142 cpu_top->core_info[cpu].is_online = cpupower_is_cpu_online(cpu);
143 if(sysfs_topology_read_file(
144 cpu,
145 "physical_package_id",
146 &(cpu_top->core_info[cpu].pkg)) < 0) {
147 cpu_top->core_info[cpu].pkg = -1;
148 cpu_top->core_info[cpu].core = -1;
149 continue;
150 }
151 if(sysfs_topology_read_file(
152 cpu,
153 "core_id",
154 &(cpu_top->core_info[cpu].core)) < 0) {
155 cpu_top->core_info[cpu].pkg = -1;
156 cpu_top->core_info[cpu].core = -1;
157 continue;
158 }
159 }
160
161 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
162 __compare);
163
164 /* Count the number of distinct pkgs values. This works
165 because the primary sort of the core_info struct was just
166 done by pkg value. */
167 last_pkg = cpu_top->core_info[0].pkg;
168 for(cpu = 1; cpu < cpus; cpu++) {
169 if (cpu_top->core_info[cpu].pkg != last_pkg &&
170 cpu_top->core_info[cpu].pkg != -1) {
171
172 last_pkg = cpu_top->core_info[cpu].pkg;
173 cpu_top->pkgs++;
174 }
175 }
176 if (!(cpu_top->core_info[0].pkg == -1))
177 cpu_top->pkgs++;
178
179 /* Intel's cores count is not consecutively numbered, there may
180 * be a core_id of 3, but none of 2. Assume there always is 0
181 * Get amount of cores by counting duplicates in a package
182 for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
183 if (cpu_top->core_info[cpu].core == 0)
184 cpu_top->cores++;
185 */
186 return cpus;
187}
188
189void cpu_topology_release(struct cpupower_topology cpu_top)
190{
191 free(cpu_top.core_info);
192}
diff --git a/tools/power/cpupower/lib/cpupower.h b/tools/power/cpupower/lib/cpupower.h
new file mode 100644
index 000000000000..fa031fcc7710
--- /dev/null
+++ b/tools/power/cpupower/lib/cpupower.h
@@ -0,0 +1,35 @@
1#ifndef __CPUPOWER_CPUPOWER_H__
2#define __CPUPOWER_CPUPOWER_H__
3
4struct cpupower_topology {
5 /* Amount of CPU cores, packages and threads per core in the system */
6 unsigned int cores;
7 unsigned int pkgs;
8 unsigned int threads; /* per core */
9
10 /* Array gets mallocated with cores entries, holding per core info */
11 struct cpuid_core_info *core_info;
12};
13
14struct cpuid_core_info {
15 int pkg;
16 int core;
17 int cpu;
18
19 /* flags */
20 unsigned int is_online:1;
21};
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27int get_cpu_topology(struct cpupower_topology *cpu_top);
28void cpu_topology_release(struct cpupower_topology cpu_top);
29int cpupower_is_cpu_online(unsigned int cpu);
30
31#ifdef __cplusplus
32}
33#endif
34
35#endif
diff --git a/tools/power/cpupower/lib/cpupower_intern.h b/tools/power/cpupower/lib/cpupower_intern.h
new file mode 100644
index 000000000000..f8ec4009621c
--- /dev/null
+++ b/tools/power/cpupower/lib/cpupower_intern.h
@@ -0,0 +1,5 @@
1#define PATH_TO_CPU "/sys/devices/system/cpu/"
2#define MAX_LINE_LEN 4096
3#define SYSFS_PATH_MAX 255
4
5unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
diff --git a/tools/power/cpupower/lib/sysfs.c b/tools/power/cpupower/lib/sysfs.c
deleted file mode 100644
index 870713a75a81..000000000000
--- a/tools/power/cpupower/lib/sysfs.c
+++ /dev/null
@@ -1,672 +0,0 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#include <stdio.h>
8#include <errno.h>
9#include <stdlib.h>
10#include <string.h>
11#include <limits.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include "cpufreq.h"
18
19#define PATH_TO_CPU "/sys/devices/system/cpu/"
20#define MAX_LINE_LEN 4096
21#define SYSFS_PATH_MAX 255
22
23
24static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
25{
26 int fd;
27 ssize_t numread;
28
29 fd = open(path, O_RDONLY);
30 if (fd == -1)
31 return 0;
32
33 numread = read(fd, buf, buflen - 1);
34 if (numread < 1) {
35 close(fd);
36 return 0;
37 }
38
39 buf[numread] = '\0';
40 close(fd);
41
42 return (unsigned int) numread;
43}
44
45
46/* CPUFREQ sysfs access **************************************************/
47
48/* helper function to read file from /sys into given buffer */
49/* fname is a relative path under "cpuX/cpufreq" dir */
50static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
51 char *buf, size_t buflen)
52{
53 char path[SYSFS_PATH_MAX];
54
55 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
56 cpu, fname);
57 return sysfs_read_file(path, buf, buflen);
58}
59
60/* helper function to write a new value to a /sys file */
61/* fname is a relative path under "cpuX/cpufreq" dir */
62static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
63 const char *fname,
64 const char *value, size_t len)
65{
66 char path[SYSFS_PATH_MAX];
67 int fd;
68 ssize_t numwrite;
69
70 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
71 cpu, fname);
72
73 fd = open(path, O_WRONLY);
74 if (fd == -1)
75 return 0;
76
77 numwrite = write(fd, value, len);
78 if (numwrite < 1) {
79 close(fd);
80 return 0;
81 }
82
83 close(fd);
84
85 return (unsigned int) numwrite;
86}
87
88/* read access to files which contain one numeric value */
89
90enum cpufreq_value {
91 CPUINFO_CUR_FREQ,
92 CPUINFO_MIN_FREQ,
93 CPUINFO_MAX_FREQ,
94 CPUINFO_LATENCY,
95 SCALING_CUR_FREQ,
96 SCALING_MIN_FREQ,
97 SCALING_MAX_FREQ,
98 STATS_NUM_TRANSITIONS,
99 MAX_CPUFREQ_VALUE_READ_FILES
100};
101
102static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
103 [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
104 [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
105 [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
106 [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
107 [SCALING_CUR_FREQ] = "scaling_cur_freq",
108 [SCALING_MIN_FREQ] = "scaling_min_freq",
109 [SCALING_MAX_FREQ] = "scaling_max_freq",
110 [STATS_NUM_TRANSITIONS] = "stats/total_trans"
111};
112
113
114static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
115 enum cpufreq_value which)
116{
117 unsigned long value;
118 unsigned int len;
119 char linebuf[MAX_LINE_LEN];
120 char *endp;
121
122 if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
123 return 0;
124
125 len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
126 linebuf, sizeof(linebuf));
127
128 if (len == 0)
129 return 0;
130
131 value = strtoul(linebuf, &endp, 0);
132
133 if (endp == linebuf || errno == ERANGE)
134 return 0;
135
136 return value;
137}
138
139/* read access to files which contain one string */
140
141enum cpufreq_string {
142 SCALING_DRIVER,
143 SCALING_GOVERNOR,
144 MAX_CPUFREQ_STRING_FILES
145};
146
147static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
148 [SCALING_DRIVER] = "scaling_driver",
149 [SCALING_GOVERNOR] = "scaling_governor",
150};
151
152
153static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
154 enum cpufreq_string which)
155{
156 char linebuf[MAX_LINE_LEN];
157 char *result;
158 unsigned int len;
159
160 if (which >= MAX_CPUFREQ_STRING_FILES)
161 return NULL;
162
163 len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
164 linebuf, sizeof(linebuf));
165 if (len == 0)
166 return NULL;
167
168 result = strdup(linebuf);
169 if (result == NULL)
170 return NULL;
171
172 if (result[strlen(result) - 1] == '\n')
173 result[strlen(result) - 1] = '\0';
174
175 return result;
176}
177
178/* write access */
179
180enum cpufreq_write {
181 WRITE_SCALING_MIN_FREQ,
182 WRITE_SCALING_MAX_FREQ,
183 WRITE_SCALING_GOVERNOR,
184 WRITE_SCALING_SET_SPEED,
185 MAX_CPUFREQ_WRITE_FILES
186};
187
188static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
189 [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
190 [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
191 [WRITE_SCALING_GOVERNOR] = "scaling_governor",
192 [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
193};
194
195static int sysfs_cpufreq_write_one_value(unsigned int cpu,
196 enum cpufreq_write which,
197 const char *new_value, size_t len)
198{
199 if (which >= MAX_CPUFREQ_WRITE_FILES)
200 return 0;
201
202 if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
203 new_value, len) != len)
204 return -ENODEV;
205
206 return 0;
207};
208
209unsigned long sysfs_get_freq_kernel(unsigned int cpu)
210{
211 return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
212}
213
214unsigned long sysfs_get_freq_hardware(unsigned int cpu)
215{
216 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
217}
218
219unsigned long sysfs_get_freq_transition_latency(unsigned int cpu)
220{
221 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
222}
223
224int sysfs_get_freq_hardware_limits(unsigned int cpu,
225 unsigned long *min,
226 unsigned long *max)
227{
228 if ((!min) || (!max))
229 return -EINVAL;
230
231 *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
232 if (!*min)
233 return -ENODEV;
234
235 *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
236 if (!*max)
237 return -ENODEV;
238
239 return 0;
240}
241
242char *sysfs_get_freq_driver(unsigned int cpu)
243{
244 return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
245}
246
247struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu)
248{
249 struct cpufreq_policy *policy;
250
251 policy = malloc(sizeof(struct cpufreq_policy));
252 if (!policy)
253 return NULL;
254
255 policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
256 if (!policy->governor) {
257 free(policy);
258 return NULL;
259 }
260 policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
261 policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
262 if ((!policy->min) || (!policy->max)) {
263 free(policy->governor);
264 free(policy);
265 return NULL;
266 }
267
268 return policy;
269}
270
271struct cpufreq_available_governors *
272sysfs_get_freq_available_governors(unsigned int cpu) {
273 struct cpufreq_available_governors *first = NULL;
274 struct cpufreq_available_governors *current = NULL;
275 char linebuf[MAX_LINE_LEN];
276 unsigned int pos, i;
277 unsigned int len;
278
279 len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
280 linebuf, sizeof(linebuf));
281 if (len == 0)
282 return NULL;
283
284 pos = 0;
285 for (i = 0; i < len; i++) {
286 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
287 if (i - pos < 2)
288 continue;
289 if (current) {
290 current->next = malloc(sizeof(*current));
291 if (!current->next)
292 goto error_out;
293 current = current->next;
294 } else {
295 first = malloc(sizeof(*first));
296 if (!first)
297 goto error_out;
298 current = first;
299 }
300 current->first = first;
301 current->next = NULL;
302
303 current->governor = malloc(i - pos + 1);
304 if (!current->governor)
305 goto error_out;
306
307 memcpy(current->governor, linebuf + pos, i - pos);
308 current->governor[i - pos] = '\0';
309 pos = i + 1;
310 }
311 }
312
313 return first;
314
315 error_out:
316 while (first) {
317 current = first->next;
318 if (first->governor)
319 free(first->governor);
320 free(first);
321 first = current;
322 }
323 return NULL;
324}
325
326
327struct cpufreq_available_frequencies *
328sysfs_get_available_frequencies(unsigned int cpu) {
329 struct cpufreq_available_frequencies *first = NULL;
330 struct cpufreq_available_frequencies *current = NULL;
331 char one_value[SYSFS_PATH_MAX];
332 char linebuf[MAX_LINE_LEN];
333 unsigned int pos, i;
334 unsigned int len;
335
336 len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
337 linebuf, sizeof(linebuf));
338 if (len == 0)
339 return NULL;
340
341 pos = 0;
342 for (i = 0; i < len; i++) {
343 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
344 if (i - pos < 2)
345 continue;
346 if (i - pos >= SYSFS_PATH_MAX)
347 goto error_out;
348 if (current) {
349 current->next = malloc(sizeof(*current));
350 if (!current->next)
351 goto error_out;
352 current = current->next;
353 } else {
354 first = malloc(sizeof(*first));
355 if (!first)
356 goto error_out;
357 current = first;
358 }
359 current->first = first;
360 current->next = NULL;
361
362 memcpy(one_value, linebuf + pos, i - pos);
363 one_value[i - pos] = '\0';
364 if (sscanf(one_value, "%lu", &current->frequency) != 1)
365 goto error_out;
366
367 pos = i + 1;
368 }
369 }
370
371 return first;
372
373 error_out:
374 while (first) {
375 current = first->next;
376 free(first);
377 first = current;
378 }
379 return NULL;
380}
381
382static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
383 const char *file)
384{
385 struct cpufreq_affected_cpus *first = NULL;
386 struct cpufreq_affected_cpus *current = NULL;
387 char one_value[SYSFS_PATH_MAX];
388 char linebuf[MAX_LINE_LEN];
389 unsigned int pos, i;
390 unsigned int len;
391
392 len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
393 if (len == 0)
394 return NULL;
395
396 pos = 0;
397 for (i = 0; i < len; i++) {
398 if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
399 if (i - pos < 1)
400 continue;
401 if (i - pos >= SYSFS_PATH_MAX)
402 goto error_out;
403 if (current) {
404 current->next = malloc(sizeof(*current));
405 if (!current->next)
406 goto error_out;
407 current = current->next;
408 } else {
409 first = malloc(sizeof(*first));
410 if (!first)
411 goto error_out;
412 current = first;
413 }
414 current->first = first;
415 current->next = NULL;
416
417 memcpy(one_value, linebuf + pos, i - pos);
418 one_value[i - pos] = '\0';
419
420 if (sscanf(one_value, "%u", &current->cpu) != 1)
421 goto error_out;
422
423 pos = i + 1;
424 }
425 }
426
427 return first;
428
429 error_out:
430 while (first) {
431 current = first->next;
432 free(first);
433 first = current;
434 }
435 return NULL;
436}
437
438struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(unsigned int cpu)
439{
440 return sysfs_get_cpu_list(cpu, "affected_cpus");
441}
442
443struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(unsigned int cpu)
444{
445 return sysfs_get_cpu_list(cpu, "related_cpus");
446}
447
448struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
449 unsigned long long *total_time) {
450 struct cpufreq_stats *first = NULL;
451 struct cpufreq_stats *current = NULL;
452 char one_value[SYSFS_PATH_MAX];
453 char linebuf[MAX_LINE_LEN];
454 unsigned int pos, i;
455 unsigned int len;
456
457 len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
458 linebuf, sizeof(linebuf));
459 if (len == 0)
460 return NULL;
461
462 *total_time = 0;
463 pos = 0;
464 for (i = 0; i < len; i++) {
465 if (i == strlen(linebuf) || linebuf[i] == '\n') {
466 if (i - pos < 2)
467 continue;
468 if ((i - pos) >= SYSFS_PATH_MAX)
469 goto error_out;
470 if (current) {
471 current->next = malloc(sizeof(*current));
472 if (!current->next)
473 goto error_out;
474 current = current->next;
475 } else {
476 first = malloc(sizeof(*first));
477 if (!first)
478 goto error_out;
479 current = first;
480 }
481 current->first = first;
482 current->next = NULL;
483
484 memcpy(one_value, linebuf + pos, i - pos);
485 one_value[i - pos] = '\0';
486 if (sscanf(one_value, "%lu %llu",
487 &current->frequency,
488 &current->time_in_state) != 2)
489 goto error_out;
490
491 *total_time = *total_time + current->time_in_state;
492 pos = i + 1;
493 }
494 }
495
496 return first;
497
498 error_out:
499 while (first) {
500 current = first->next;
501 free(first);
502 first = current;
503 }
504 return NULL;
505}
506
507unsigned long sysfs_get_freq_transitions(unsigned int cpu)
508{
509 return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
510}
511
512static int verify_gov(char *new_gov, char *passed_gov)
513{
514 unsigned int i, j = 0;
515
516 if (!passed_gov || (strlen(passed_gov) > 19))
517 return -EINVAL;
518
519 strncpy(new_gov, passed_gov, 20);
520 for (i = 0; i < 20; i++) {
521 if (j) {
522 new_gov[i] = '\0';
523 continue;
524 }
525 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
526 continue;
527
528 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
529 continue;
530
531 if (new_gov[i] == '-')
532 continue;
533
534 if (new_gov[i] == '_')
535 continue;
536
537 if (new_gov[i] == '\0') {
538 j = 1;
539 continue;
540 }
541 return -EINVAL;
542 }
543 new_gov[19] = '\0';
544 return 0;
545}
546
547int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor)
548{
549 char new_gov[SYSFS_PATH_MAX];
550
551 if (!governor)
552 return -EINVAL;
553
554 if (verify_gov(new_gov, governor))
555 return -EINVAL;
556
557 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
558 new_gov, strlen(new_gov));
559};
560
561int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq)
562{
563 char value[SYSFS_PATH_MAX];
564
565 snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
566
567 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
568 value, strlen(value));
569};
570
571
572int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq)
573{
574 char value[SYSFS_PATH_MAX];
575
576 snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
577
578 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
579 value, strlen(value));
580};
581
582
583int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy)
584{
585 char min[SYSFS_PATH_MAX];
586 char max[SYSFS_PATH_MAX];
587 char gov[SYSFS_PATH_MAX];
588 int ret;
589 unsigned long old_min;
590 int write_max_first;
591
592 if (!policy || !(policy->governor))
593 return -EINVAL;
594
595 if (policy->max < policy->min)
596 return -EINVAL;
597
598 if (verify_gov(gov, policy->governor))
599 return -EINVAL;
600
601 snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
602 snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
603
604 old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
605 write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
606
607 if (write_max_first) {
608 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
609 max, strlen(max));
610 if (ret)
611 return ret;
612 }
613
614 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
615 strlen(min));
616 if (ret)
617 return ret;
618
619 if (!write_max_first) {
620 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
621 max, strlen(max));
622 if (ret)
623 return ret;
624 }
625
626 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
627 gov, strlen(gov));
628}
629
630int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency)
631{
632 struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu);
633 char userspace_gov[] = "userspace";
634 char freq[SYSFS_PATH_MAX];
635 int ret;
636
637 if (!pol)
638 return -ENODEV;
639
640 if (strncmp(pol->governor, userspace_gov, 9) != 0) {
641 ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov);
642 if (ret) {
643 cpufreq_put_policy(pol);
644 return ret;
645 }
646 }
647
648 cpufreq_put_policy(pol);
649
650 snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
651
652 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
653 freq, strlen(freq));
654}
655
656/* CPUFREQ sysfs access **************************************************/
657
658/* General sysfs access **************************************************/
659int sysfs_cpu_exists(unsigned int cpu)
660{
661 char file[SYSFS_PATH_MAX];
662 struct stat statbuf;
663
664 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
665
666 if (stat(file, &statbuf) != 0)
667 return -ENOSYS;
668
669 return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
670}
671
672/* General sysfs access **************************************************/
diff --git a/tools/power/cpupower/lib/sysfs.h b/tools/power/cpupower/lib/sysfs.h
deleted file mode 100644
index c76a5e0af501..000000000000
--- a/tools/power/cpupower/lib/sysfs.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/* General */
2extern unsigned int sysfs_cpu_exists(unsigned int cpu);
3
4/* CPUfreq */
5extern unsigned long sysfs_get_freq_kernel(unsigned int cpu);
6extern unsigned long sysfs_get_freq_hardware(unsigned int cpu);
7extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu);
8extern int sysfs_get_freq_hardware_limits(unsigned int cpu,
9 unsigned long *min, unsigned long *max);
10extern char *sysfs_get_freq_driver(unsigned int cpu);
11extern struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu);
12extern struct cpufreq_available_governors *sysfs_get_freq_available_governors(
13 unsigned int cpu);
14extern struct cpufreq_available_frequencies *sysfs_get_available_frequencies(
15 unsigned int cpu);
16extern struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(
17 unsigned int cpu);
18extern struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(
19 unsigned int cpu);
20extern struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
21 unsigned long long *total_time);
22extern unsigned long sysfs_get_freq_transitions(unsigned int cpu);
23extern int sysfs_set_freq_policy(unsigned int cpu,
24 struct cpufreq_policy *policy);
25extern int sysfs_modify_freq_policy_min(unsigned int cpu,
26 unsigned long min_freq);
27extern int sysfs_modify_freq_policy_max(unsigned int cpu,
28 unsigned long max_freq);
29extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor);
30extern int sysfs_set_frequency(unsigned int cpu,
31 unsigned long target_frequency);
diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1
index 9c85a382e355..6aa8d239dff9 100644
--- a/tools/power/cpupower/man/cpupower-frequency-info.1
+++ b/tools/power/cpupower/man/cpupower-frequency-info.1
@@ -1,7 +1,7 @@
1.TH "CPUPOWER\-FREQUENCY\-INFO" "1" "0.1" "" "cpupower Manual" 1.TH "CPUPOWER\-FREQUENCY\-INFO" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower frequency\-info \- Utility to retrieve cpufreq kernel information 4cpupower\-frequency\-info \- Utility to retrieve cpufreq kernel information
5.SH "SYNTAX" 5.SH "SYNTAX"
6.LP 6.LP
7cpupower [ \-c cpulist ] frequency\-info [\fIoptions\fP] 7cpupower [ \-c cpulist ] frequency\-info [\fIoptions\fP]
diff --git a/tools/power/cpupower/man/cpupower-frequency-set.1 b/tools/power/cpupower/man/cpupower-frequency-set.1
index 3eacc8d03d1a..b50570221a5b 100644
--- a/tools/power/cpupower/man/cpupower-frequency-set.1
+++ b/tools/power/cpupower/man/cpupower-frequency-set.1
@@ -1,7 +1,7 @@
1.TH "CPUPOWER\-FREQUENCY\-SET" "1" "0.1" "" "cpupower Manual" 1.TH "CPUPOWER\-FREQUENCY\-SET" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower frequency\-set \- A small tool which allows to modify cpufreq settings. 4cpupower\-frequency\-set \- A small tool which allows to modify cpufreq settings.
5.SH "SYNTAX" 5.SH "SYNTAX"
6.LP 6.LP
7cpupower [ \-c cpu ] frequency\-set [\fIoptions\fP] 7cpupower [ \-c cpu ] frequency\-set [\fIoptions\fP]
diff --git a/tools/power/cpupower/man/cpupower-idle-info.1 b/tools/power/cpupower/man/cpupower-idle-info.1
index 7b3646adb92f..80a1311fa747 100644
--- a/tools/power/cpupower/man/cpupower-idle-info.1
+++ b/tools/power/cpupower/man/cpupower-idle-info.1
@@ -1,7 +1,7 @@
1.TH "CPUPOWER-IDLE-INFO" "1" "0.1" "" "cpupower Manual" 1.TH "CPUPOWER-IDLE-INFO" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower idle\-info \- Utility to retrieve cpu idle kernel information 4cpupower\-idle\-info \- Utility to retrieve cpu idle kernel information
5.SH "SYNTAX" 5.SH "SYNTAX"
6.LP 6.LP
7cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP] 7cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP]
diff --git a/tools/power/cpupower/man/cpupower-idle-set.1 b/tools/power/cpupower/man/cpupower-idle-set.1
index 580c4e3ea92a..21916cff7516 100644
--- a/tools/power/cpupower/man/cpupower-idle-set.1
+++ b/tools/power/cpupower/man/cpupower-idle-set.1
@@ -1,7 +1,7 @@
1.TH "CPUPOWER-IDLE-SET" "1" "0.1" "" "cpupower Manual" 1.TH "CPUPOWER-IDLE-SET" "1" "0.1" "" "cpupower Manual"
2.SH "NAME" 2.SH "NAME"
3.LP 3.LP
4cpupower idle\-set \- Utility to set cpu idle state specific kernel options 4cpupower\-idle\-set \- Utility to set cpu idle state specific kernel options
5.SH "SYNTAX" 5.SH "SYNTAX"
6.LP 6.LP
7cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP] 7cpupower [ \-c cpulist ] idle\-info [\fIoptions\fP]
diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c
index 0fbd1a22c0a9..b4bf76971dc9 100644
--- a/tools/power/cpupower/utils/cpufreq-set.c
+++ b/tools/power/cpupower/utils/cpufreq-set.c
@@ -16,8 +16,8 @@
16#include <getopt.h> 16#include <getopt.h>
17 17
18#include "cpufreq.h" 18#include "cpufreq.h"
19#include "cpuidle.h"
19#include "helpers/helpers.h" 20#include "helpers/helpers.h"
20#include "helpers/sysfs.h"
21 21
22#define NORM_FREQ_LEN 32 22#define NORM_FREQ_LEN 32
23 23
@@ -296,7 +296,7 @@ int cmd_freq_set(int argc, char **argv)
296 struct cpufreq_affected_cpus *cpus; 296 struct cpufreq_affected_cpus *cpus;
297 297
298 if (!bitmask_isbitset(cpus_chosen, cpu) || 298 if (!bitmask_isbitset(cpus_chosen, cpu) ||
299 cpufreq_cpu_exists(cpu)) 299 cpupower_is_cpu_online(cpu))
300 continue; 300 continue;
301 301
302 cpus = cpufreq_get_related_cpus(cpu); 302 cpus = cpufreq_get_related_cpus(cpu);
@@ -316,10 +316,10 @@ int cmd_freq_set(int argc, char **argv)
316 cpu <= bitmask_last(cpus_chosen); cpu++) { 316 cpu <= bitmask_last(cpus_chosen); cpu++) {
317 317
318 if (!bitmask_isbitset(cpus_chosen, cpu) || 318 if (!bitmask_isbitset(cpus_chosen, cpu) ||
319 cpufreq_cpu_exists(cpu)) 319 cpupower_is_cpu_online(cpu))
320 continue; 320 continue;
321 321
322 if (sysfs_is_cpu_online(cpu) != 1) 322 if (cpupower_is_cpu_online(cpu) != 1)
323 continue; 323 continue;
324 324
325 printf(_("Setting cpu: %d\n"), cpu); 325 printf(_("Setting cpu: %d\n"), cpu);
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
index 8bf8ab5ffa25..b59c85defa05 100644
--- a/tools/power/cpupower/utils/cpuidle-info.c
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -13,8 +13,10 @@
13#include <string.h> 13#include <string.h>
14#include <getopt.h> 14#include <getopt.h>
15 15
16#include "helpers/helpers.h" 16#include <cpuidle.h>
17
17#include "helpers/sysfs.h" 18#include "helpers/sysfs.h"
19#include "helpers/helpers.h"
18#include "helpers/bitmask.h" 20#include "helpers/bitmask.h"
19 21
20#define LINE_LEN 10 22#define LINE_LEN 10
@@ -24,7 +26,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
24 unsigned int idlestates, idlestate; 26 unsigned int idlestates, idlestate;
25 char *tmp; 27 char *tmp;
26 28
27 idlestates = sysfs_get_idlestate_count(cpu); 29 idlestates = cpuidle_state_count(cpu);
28 if (idlestates == 0) { 30 if (idlestates == 0) {
29 printf(_("CPU %u: No idle states\n"), cpu); 31 printf(_("CPU %u: No idle states\n"), cpu);
30 return; 32 return;
@@ -33,7 +35,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
33 printf(_("Number of idle states: %d\n"), idlestates); 35 printf(_("Number of idle states: %d\n"), idlestates);
34 printf(_("Available idle states:")); 36 printf(_("Available idle states:"));
35 for (idlestate = 0; idlestate < idlestates; idlestate++) { 37 for (idlestate = 0; idlestate < idlestates; idlestate++) {
36 tmp = sysfs_get_idlestate_name(cpu, idlestate); 38 tmp = cpuidle_state_name(cpu, idlestate);
37 if (!tmp) 39 if (!tmp)
38 continue; 40 continue;
39 printf(" %s", tmp); 41 printf(" %s", tmp);
@@ -45,28 +47,28 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose)
45 return; 47 return;
46 48
47 for (idlestate = 0; idlestate < idlestates; idlestate++) { 49 for (idlestate = 0; idlestate < idlestates; idlestate++) {
48 int disabled = sysfs_is_idlestate_disabled(cpu, idlestate); 50 int disabled = cpuidle_is_state_disabled(cpu, idlestate);
49 /* Disabled interface not supported on older kernels */ 51 /* Disabled interface not supported on older kernels */
50 if (disabled < 0) 52 if (disabled < 0)
51 disabled = 0; 53 disabled = 0;
52 tmp = sysfs_get_idlestate_name(cpu, idlestate); 54 tmp = cpuidle_state_name(cpu, idlestate);
53 if (!tmp) 55 if (!tmp)
54 continue; 56 continue;
55 printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : ""); 57 printf("%s%s:\n", tmp, (disabled) ? " (DISABLED) " : "");
56 free(tmp); 58 free(tmp);
57 59
58 tmp = sysfs_get_idlestate_desc(cpu, idlestate); 60 tmp = cpuidle_state_desc(cpu, idlestate);
59 if (!tmp) 61 if (!tmp)
60 continue; 62 continue;
61 printf(_("Flags/Description: %s\n"), tmp); 63 printf(_("Flags/Description: %s\n"), tmp);
62 free(tmp); 64 free(tmp);
63 65
64 printf(_("Latency: %lu\n"), 66 printf(_("Latency: %lu\n"),
65 sysfs_get_idlestate_latency(cpu, idlestate)); 67 cpuidle_state_latency(cpu, idlestate));
66 printf(_("Usage: %lu\n"), 68 printf(_("Usage: %lu\n"),
67 sysfs_get_idlestate_usage(cpu, idlestate)); 69 cpuidle_state_usage(cpu, idlestate));
68 printf(_("Duration: %llu\n"), 70 printf(_("Duration: %llu\n"),
69 sysfs_get_idlestate_time(cpu, idlestate)); 71 cpuidle_state_time(cpu, idlestate));
70 } 72 }
71} 73}
72 74
@@ -74,7 +76,7 @@ static void cpuidle_general_output(void)
74{ 76{
75 char *tmp; 77 char *tmp;
76 78
77 tmp = sysfs_get_cpuidle_driver(); 79 tmp = cpuidle_get_driver();
78 if (!tmp) { 80 if (!tmp) {
79 printf(_("Could not determine cpuidle driver\n")); 81 printf(_("Could not determine cpuidle driver\n"));
80 return; 82 return;
@@ -83,7 +85,7 @@ static void cpuidle_general_output(void)
83 printf(_("CPUidle driver: %s\n"), tmp); 85 printf(_("CPUidle driver: %s\n"), tmp);
84 free(tmp); 86 free(tmp);
85 87
86 tmp = sysfs_get_cpuidle_governor(); 88 tmp = cpuidle_get_governor();
87 if (!tmp) { 89 if (!tmp) {
88 printf(_("Could not determine cpuidle governor\n")); 90 printf(_("Could not determine cpuidle governor\n"));
89 return; 91 return;
@@ -98,7 +100,7 @@ static void proc_cpuidle_cpu_output(unsigned int cpu)
98 long max_allowed_cstate = 2000000000; 100 long max_allowed_cstate = 2000000000;
99 unsigned int cstate, cstates; 101 unsigned int cstate, cstates;
100 102
101 cstates = sysfs_get_idlestate_count(cpu); 103 cstates = cpuidle_state_count(cpu);
102 if (cstates == 0) { 104 if (cstates == 0) {
103 printf(_("CPU %u: No C-states info\n"), cpu); 105 printf(_("CPU %u: No C-states info\n"), cpu);
104 return; 106 return;
@@ -113,11 +115,11 @@ static void proc_cpuidle_cpu_output(unsigned int cpu)
113 "type[C%d] "), cstate, cstate); 115 "type[C%d] "), cstate, cstate);
114 printf(_("promotion[--] demotion[--] ")); 116 printf(_("promotion[--] demotion[--] "));
115 printf(_("latency[%03lu] "), 117 printf(_("latency[%03lu] "),
116 sysfs_get_idlestate_latency(cpu, cstate)); 118 cpuidle_state_latency(cpu, cstate));
117 printf(_("usage[%08lu] "), 119 printf(_("usage[%08lu] "),
118 sysfs_get_idlestate_usage(cpu, cstate)); 120 cpuidle_state_usage(cpu, cstate));
119 printf(_("duration[%020Lu] \n"), 121 printf(_("duration[%020Lu] \n"),
120 sysfs_get_idlestate_time(cpu, cstate)); 122 cpuidle_state_time(cpu, cstate));
121 } 123 }
122} 124}
123 125
diff --git a/tools/power/cpupower/utils/cpuidle-set.c b/tools/power/cpupower/utils/cpuidle-set.c
index d6b6ae44b8c2..691c24d50ef4 100644
--- a/tools/power/cpupower/utils/cpuidle-set.c
+++ b/tools/power/cpupower/utils/cpuidle-set.c
@@ -5,12 +5,12 @@
5#include <limits.h> 5#include <limits.h>
6#include <string.h> 6#include <string.h>
7#include <ctype.h> 7#include <ctype.h>
8
9#include <getopt.h> 8#include <getopt.h>
10 9
11#include "cpufreq.h" 10#include <cpufreq.h>
11#include <cpuidle.h>
12
12#include "helpers/helpers.h" 13#include "helpers/helpers.h"
13#include "helpers/sysfs.h"
14 14
15static struct option info_opts[] = { 15static struct option info_opts[] = {
16 {"disable", required_argument, NULL, 'd'}, 16 {"disable", required_argument, NULL, 'd'},
@@ -104,16 +104,16 @@ int cmd_idle_set(int argc, char **argv)
104 if (!bitmask_isbitset(cpus_chosen, cpu)) 104 if (!bitmask_isbitset(cpus_chosen, cpu))
105 continue; 105 continue;
106 106
107 if (sysfs_is_cpu_online(cpu) != 1) 107 if (cpupower_is_cpu_online(cpu) != 1)
108 continue; 108 continue;
109 109
110 idlestates = sysfs_get_idlestate_count(cpu); 110 idlestates = cpuidle_state_count(cpu);
111 if (idlestates <= 0) 111 if (idlestates <= 0)
112 continue; 112 continue;
113 113
114 switch (param) { 114 switch (param) {
115 case 'd': 115 case 'd':
116 ret = sysfs_idlestate_disable(cpu, idlestate, 1); 116 ret = cpuidle_state_disable(cpu, idlestate, 1);
117 if (ret == 0) 117 if (ret == 0)
118 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 118 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
119 else if (ret == -1) 119 else if (ret == -1)
@@ -126,7 +126,7 @@ int cmd_idle_set(int argc, char **argv)
126 idlestate, cpu); 126 idlestate, cpu);
127 break; 127 break;
128 case 'e': 128 case 'e':
129 ret = sysfs_idlestate_disable(cpu, idlestate, 0); 129 ret = cpuidle_state_disable(cpu, idlestate, 0);
130 if (ret == 0) 130 if (ret == 0)
131 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 131 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
132 else if (ret == -1) 132 else if (ret == -1)
@@ -140,13 +140,13 @@ int cmd_idle_set(int argc, char **argv)
140 break; 140 break;
141 case 'D': 141 case 'D':
142 for (idlestate = 0; idlestate < idlestates; idlestate++) { 142 for (idlestate = 0; idlestate < idlestates; idlestate++) {
143 disabled = sysfs_is_idlestate_disabled 143 disabled = cpuidle_is_state_disabled
144 (cpu, idlestate); 144 (cpu, idlestate);
145 state_latency = sysfs_get_idlestate_latency 145 state_latency = cpuidle_state_latency
146 (cpu, idlestate); 146 (cpu, idlestate);
147 if (disabled == 1) { 147 if (disabled == 1) {
148 if (latency > state_latency){ 148 if (latency > state_latency){
149 ret = sysfs_idlestate_disable 149 ret = cpuidle_state_disable
150 (cpu, idlestate, 0); 150 (cpu, idlestate, 0);
151 if (ret == 0) 151 if (ret == 0)
152 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 152 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
@@ -154,7 +154,7 @@ int cmd_idle_set(int argc, char **argv)
154 continue; 154 continue;
155 } 155 }
156 if (latency <= state_latency){ 156 if (latency <= state_latency){
157 ret = sysfs_idlestate_disable 157 ret = cpuidle_state_disable
158 (cpu, idlestate, 1); 158 (cpu, idlestate, 1);
159 if (ret == 0) 159 if (ret == 0)
160 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu); 160 printf(_("Idlestate %u disabled on CPU %u\n"), idlestate, cpu);
@@ -163,10 +163,10 @@ int cmd_idle_set(int argc, char **argv)
163 break; 163 break;
164 case 'E': 164 case 'E':
165 for (idlestate = 0; idlestate < idlestates; idlestate++) { 165 for (idlestate = 0; idlestate < idlestates; idlestate++) {
166 disabled = sysfs_is_idlestate_disabled 166 disabled = cpuidle_is_state_disabled
167 (cpu, idlestate); 167 (cpu, idlestate);
168 if (disabled == 1) { 168 if (disabled == 1) {
169 ret = sysfs_idlestate_disable 169 ret = cpuidle_state_disable
170 (cpu, idlestate, 0); 170 (cpu, idlestate, 0);
171 if (ret == 0) 171 if (ret == 0)
172 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu); 172 printf(_("Idlestate %u enabled on CPU %u\n"), idlestate, cpu);
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index aa9e95486a2d..afb66f80554e 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -14,6 +14,7 @@
14#include <locale.h> 14#include <locale.h>
15 15
16#include "helpers/bitmask.h" 16#include "helpers/bitmask.h"
17#include <cpupower.h>
17 18
18/* Internationalization ****************************/ 19/* Internationalization ****************************/
19#ifdef NLS 20#ifdef NLS
@@ -92,31 +93,6 @@ extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
92extern struct cpupower_cpu_info cpupower_cpu_info; 93extern struct cpupower_cpu_info cpupower_cpu_info;
93/* cpuid and cpuinfo helpers **************************/ 94/* cpuid and cpuinfo helpers **************************/
94 95
95struct cpuid_core_info {
96 int pkg;
97 int core;
98 int cpu;
99
100 /* flags */
101 unsigned int is_online:1;
102};
103
104/* CPU topology/hierarchy parsing ******************/
105struct cpupower_topology {
106 /* Amount of CPU cores, packages and threads per core in the system */
107 unsigned int cores;
108 unsigned int pkgs;
109 unsigned int threads; /* per core */
110
111 /* Array gets mallocated with cores entries, holding per core info */
112 struct cpuid_core_info *core_info;
113};
114
115extern int get_cpu_topology(struct cpupower_topology *cpu_top);
116extern void cpu_topology_release(struct cpupower_topology cpu_top);
117
118/* CPU topology/hierarchy parsing ******************/
119
120/* X86 ONLY ****************************************/ 96/* X86 ONLY ****************************************/
121#if defined(__i386__) || defined(__x86_64__) 97#if defined(__i386__) || defined(__x86_64__)
122 98
diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c
index 5f9c908f4557..a1a6c6041a1e 100644
--- a/tools/power/cpupower/utils/helpers/topology.c
+++ b/tools/power/cpupower/utils/helpers/topology.c
@@ -16,110 +16,7 @@
16#include <errno.h> 16#include <errno.h>
17#include <fcntl.h> 17#include <fcntl.h>
18 18
19#include <helpers/helpers.h> 19#include <cpuidle.h>
20#include <helpers/sysfs.h>
21 20
22/* returns -1 on failure, 0 on success */ 21/* CPU topology/hierarchy parsing ******************/
23static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
24{
25 char linebuf[MAX_LINE_LEN];
26 char *endp;
27 char path[SYSFS_PATH_MAX];
28 22
29 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
30 cpu, fname);
31 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
32 return -1;
33 *result = strtol(linebuf, &endp, 0);
34 if (endp == linebuf || errno == ERANGE)
35 return -1;
36 return 0;
37}
38
39static int __compare(const void *t1, const void *t2)
40{
41 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
42 struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
43 if (top1->pkg < top2->pkg)
44 return -1;
45 else if (top1->pkg > top2->pkg)
46 return 1;
47 else if (top1->core < top2->core)
48 return -1;
49 else if (top1->core > top2->core)
50 return 1;
51 else if (top1->cpu < top2->cpu)
52 return -1;
53 else if (top1->cpu > top2->cpu)
54 return 1;
55 else
56 return 0;
57}
58
59/*
60 * Returns amount of cpus, negative on error, cpu_top must be
61 * passed to cpu_topology_release to free resources
62 *
63 * Array is sorted after ->pkg, ->core, then ->cpu
64 */
65int get_cpu_topology(struct cpupower_topology *cpu_top)
66{
67 int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
68
69 cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
70 if (cpu_top->core_info == NULL)
71 return -ENOMEM;
72 cpu_top->pkgs = cpu_top->cores = 0;
73 for (cpu = 0; cpu < cpus; cpu++) {
74 cpu_top->core_info[cpu].cpu = cpu;
75 cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
76 if(sysfs_topology_read_file(
77 cpu,
78 "physical_package_id",
79 &(cpu_top->core_info[cpu].pkg)) < 0) {
80 cpu_top->core_info[cpu].pkg = -1;
81 cpu_top->core_info[cpu].core = -1;
82 continue;
83 }
84 if(sysfs_topology_read_file(
85 cpu,
86 "core_id",
87 &(cpu_top->core_info[cpu].core)) < 0) {
88 cpu_top->core_info[cpu].pkg = -1;
89 cpu_top->core_info[cpu].core = -1;
90 continue;
91 }
92 }
93
94 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
95 __compare);
96
97 /* Count the number of distinct pkgs values. This works
98 because the primary sort of the core_info struct was just
99 done by pkg value. */
100 last_pkg = cpu_top->core_info[0].pkg;
101 for(cpu = 1; cpu < cpus; cpu++) {
102 if (cpu_top->core_info[cpu].pkg != last_pkg &&
103 cpu_top->core_info[cpu].pkg != -1) {
104
105 last_pkg = cpu_top->core_info[cpu].pkg;
106 cpu_top->pkgs++;
107 }
108 }
109 if (!(cpu_top->core_info[0].pkg == -1))
110 cpu_top->pkgs++;
111
112 /* Intel's cores count is not consecutively numbered, there may
113 * be a core_id of 3, but none of 2. Assume there always is 0
114 * Get amount of cores by counting duplicates in a package
115 for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
116 if (cpu_top->core_info[cpu].core == 0)
117 cpu_top->cores++;
118 */
119 return cpus;
120}
121
122void cpu_topology_release(struct cpupower_topology cpu_top)
123{
124 free(cpu_top.core_info);
125}
diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
index bcd22a1a3970..1b5da0066ebf 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
@@ -10,8 +10,8 @@
10#include <stdint.h> 10#include <stdint.h>
11#include <string.h> 11#include <string.h>
12#include <limits.h> 12#include <limits.h>
13#include <cpuidle.h>
13 14
14#include "helpers/sysfs.h"
15#include "helpers/helpers.h" 15#include "helpers/helpers.h"
16#include "idle_monitor/cpupower-monitor.h" 16#include "idle_monitor/cpupower-monitor.h"
17 17
@@ -51,7 +51,7 @@ static int cpuidle_start(void)
51 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; 51 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
52 state++) { 52 state++) {
53 previous_count[cpu][state] = 53 previous_count[cpu][state] =
54 sysfs_get_idlestate_time(cpu, state); 54 cpuidle_state_time(cpu, state);
55 dprint("CPU %d - State: %d - Val: %llu\n", 55 dprint("CPU %d - State: %d - Val: %llu\n",
56 cpu, state, previous_count[cpu][state]); 56 cpu, state, previous_count[cpu][state]);
57 } 57 }
@@ -70,7 +70,7 @@ static int cpuidle_stop(void)
70 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; 70 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
71 state++) { 71 state++) {
72 current_count[cpu][state] = 72 current_count[cpu][state] =
73 sysfs_get_idlestate_time(cpu, state); 73 cpuidle_state_time(cpu, state);
74 dprint("CPU %d - State: %d - Val: %llu\n", 74 dprint("CPU %d - State: %d - Val: %llu\n",
75 cpu, state, previous_count[cpu][state]); 75 cpu, state, previous_count[cpu][state]);
76 } 76 }
@@ -132,13 +132,13 @@ static struct cpuidle_monitor *cpuidle_register(void)
132 char *tmp; 132 char *tmp;
133 133
134 /* Assume idle state count is the same for all CPUs */ 134 /* Assume idle state count is the same for all CPUs */
135 cpuidle_sysfs_monitor.hw_states_num = sysfs_get_idlestate_count(0); 135 cpuidle_sysfs_monitor.hw_states_num = cpuidle_state_count(0);
136 136
137 if (cpuidle_sysfs_monitor.hw_states_num <= 0) 137 if (cpuidle_sysfs_monitor.hw_states_num <= 0)
138 return NULL; 138 return NULL;
139 139
140 for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) { 140 for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
141 tmp = sysfs_get_idlestate_name(0, num); 141 tmp = cpuidle_state_name(0, num);
142 if (tmp == NULL) 142 if (tmp == NULL)
143 continue; 143 continue;
144 144
@@ -146,7 +146,7 @@ static struct cpuidle_monitor *cpuidle_register(void)
146 strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1); 146 strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
147 free(tmp); 147 free(tmp);
148 148
149 tmp = sysfs_get_idlestate_desc(0, num); 149 tmp = cpuidle_state_desc(0, num);
150 if (tmp == NULL) 150 if (tmp == NULL)
151 continue; 151 continue;
152 strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1); 152 strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index b04afc3295df..ff9e5f20a5a7 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -19,6 +19,7 @@ TARGETS += powerpc
19TARGETS += pstore 19TARGETS += pstore
20TARGETS += ptrace 20TARGETS += ptrace
21TARGETS += seccomp 21TARGETS += seccomp
22TARGETS += sigaltstack
22TARGETS += size 23TARGETS += size
23TARGETS += static_keys 24TARGETS += static_keys
24TARGETS += sysctl 25TARGETS += sysctl
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index 69bb3fc38fb2..0840684deb7d 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -3,3 +3,4 @@ psock_fanout
3psock_tpacket 3psock_tpacket
4reuseport_bpf 4reuseport_bpf
5reuseport_bpf_cpu 5reuseport_bpf_cpu
6reuseport_dualstack
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index c658792d47b4..0e5340742620 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -4,7 +4,7 @@ CFLAGS = -Wall -O2 -g
4 4
5CFLAGS += -I../../../../usr/include/ 5CFLAGS += -I../../../../usr/include/
6 6
7NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf reuseport_bpf_cpu 7NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf reuseport_bpf_cpu reuseport_dualstack
8 8
9all: $(NET_PROGS) 9all: $(NET_PROGS)
10%: %.c 10%: %.c
diff --git a/tools/testing/selftests/net/reuseport_dualstack.c b/tools/testing/selftests/net/reuseport_dualstack.c
new file mode 100644
index 000000000000..90958aaaafb9
--- /dev/null
+++ b/tools/testing/selftests/net/reuseport_dualstack.c
@@ -0,0 +1,208 @@
1/*
2 * It is possible to use SO_REUSEPORT to open multiple sockets bound to
3 * equivalent local addresses using AF_INET and AF_INET6 at the same time. If
4 * the AF_INET6 socket has IPV6_V6ONLY set, it's clear which socket should
5 * receive a given incoming packet. However, when it is not set, incoming v4
6 * packets should prefer the AF_INET socket(s). This behavior was defined with
7 * the original SO_REUSEPORT implementation, but broke with
8 * e32ea7e74727 ("soreuseport: fast reuseport UDP socket selection")
9 * This test creates these mixed AF_INET/AF_INET6 sockets and asserts the
10 * AF_INET preference for v4 packets.
11 */
12
13#define _GNU_SOURCE
14
15#include <arpa/inet.h>
16#include <errno.h>
17#include <error.h>
18#include <linux/in.h>
19#include <linux/unistd.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <sys/epoll.h>
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <unistd.h>
27
28static const int PORT = 8888;
29
30static void build_rcv_fd(int family, int proto, int *rcv_fds, int count)
31{
32 struct sockaddr_storage addr;
33 struct sockaddr_in *addr4;
34 struct sockaddr_in6 *addr6;
35 int opt, i;
36
37 switch (family) {
38 case AF_INET:
39 addr4 = (struct sockaddr_in *)&addr;
40 addr4->sin_family = AF_INET;
41 addr4->sin_addr.s_addr = htonl(INADDR_ANY);
42 addr4->sin_port = htons(PORT);
43 break;
44 case AF_INET6:
45 addr6 = (struct sockaddr_in6 *)&addr;
46 addr6->sin6_family = AF_INET6;
47 addr6->sin6_addr = in6addr_any;
48 addr6->sin6_port = htons(PORT);
49 break;
50 default:
51 error(1, 0, "Unsupported family %d", family);
52 }
53
54 for (i = 0; i < count; ++i) {
55 rcv_fds[i] = socket(family, proto, 0);
56 if (rcv_fds[i] < 0)
57 error(1, errno, "failed to create receive socket");
58
59 opt = 1;
60 if (setsockopt(rcv_fds[i], SOL_SOCKET, SO_REUSEPORT, &opt,
61 sizeof(opt)))
62 error(1, errno, "failed to set SO_REUSEPORT");
63
64 if (bind(rcv_fds[i], (struct sockaddr *)&addr, sizeof(addr)))
65 error(1, errno, "failed to bind receive socket");
66
67 if (proto == SOCK_STREAM && listen(rcv_fds[i], 10))
68 error(1, errno, "failed to listen on receive port");
69 }
70}
71
72static void send_from_v4(int proto)
73{
74 struct sockaddr_in saddr, daddr;
75 int fd;
76
77 saddr.sin_family = AF_INET;
78 saddr.sin_addr.s_addr = htonl(INADDR_ANY);
79 saddr.sin_port = 0;
80
81 daddr.sin_family = AF_INET;
82 daddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
83 daddr.sin_port = htons(PORT);
84
85 fd = socket(AF_INET, proto, 0);
86 if (fd < 0)
87 error(1, errno, "failed to create send socket");
88
89 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)))
90 error(1, errno, "failed to bind send socket");
91
92 if (connect(fd, (struct sockaddr *)&daddr, sizeof(daddr)))
93 error(1, errno, "failed to connect send socket");
94
95 if (send(fd, "a", 1, 0) < 0)
96 error(1, errno, "failed to send message");
97
98 close(fd);
99}
100
101static int receive_once(int epfd, int proto)
102{
103 struct epoll_event ev;
104 int i, fd;
105 char buf[8];
106
107 i = epoll_wait(epfd, &ev, 1, -1);
108 if (i < 0)
109 error(1, errno, "epoll_wait failed");
110
111 if (proto == SOCK_STREAM) {
112 fd = accept(ev.data.fd, NULL, NULL);
113 if (fd < 0)
114 error(1, errno, "failed to accept");
115 i = recv(fd, buf, sizeof(buf), 0);
116 close(fd);
117 } else {
118 i = recv(ev.data.fd, buf, sizeof(buf), 0);
119 }
120
121 if (i < 0)
122 error(1, errno, "failed to recv");
123
124 return ev.data.fd;
125}
126
127static void test(int *rcv_fds, int count, int proto)
128{
129 struct epoll_event ev;
130 int epfd, i, test_fd;
131 uint16_t test_family;
132 socklen_t len;
133
134 epfd = epoll_create(1);
135 if (epfd < 0)
136 error(1, errno, "failed to create epoll");
137
138 ev.events = EPOLLIN;
139 for (i = 0; i < count; ++i) {
140 ev.data.fd = rcv_fds[i];
141 if (epoll_ctl(epfd, EPOLL_CTL_ADD, rcv_fds[i], &ev))
142 error(1, errno, "failed to register sock epoll");
143 }
144
145 send_from_v4(proto);
146
147 test_fd = receive_once(epfd, proto);
148 if (getsockopt(test_fd, SOL_SOCKET, SO_DOMAIN, &test_family, &len))
149 error(1, errno, "failed to read socket domain");
150 if (test_family != AF_INET)
151 error(1, 0, "expected to receive on v4 socket but got v6 (%d)",
152 test_family);
153
154 close(epfd);
155}
156
157int main(void)
158{
159 int rcv_fds[32], i;
160
161 fprintf(stderr, "---- UDP IPv4 created before IPv6 ----\n");
162 build_rcv_fd(AF_INET, SOCK_DGRAM, rcv_fds, 5);
163 build_rcv_fd(AF_INET6, SOCK_DGRAM, &(rcv_fds[5]), 5);
164 test(rcv_fds, 10, SOCK_DGRAM);
165 for (i = 0; i < 10; ++i)
166 close(rcv_fds[i]);
167
168 fprintf(stderr, "---- UDP IPv6 created before IPv4 ----\n");
169 build_rcv_fd(AF_INET6, SOCK_DGRAM, rcv_fds, 5);
170 build_rcv_fd(AF_INET, SOCK_DGRAM, &(rcv_fds[5]), 5);
171 test(rcv_fds, 10, SOCK_DGRAM);
172 for (i = 0; i < 10; ++i)
173 close(rcv_fds[i]);
174
175 /* NOTE: UDP socket lookups traverse a different code path when there
176 * are > 10 sockets in a group.
177 */
178 fprintf(stderr, "---- UDP IPv4 created before IPv6 (large) ----\n");
179 build_rcv_fd(AF_INET, SOCK_DGRAM, rcv_fds, 16);
180 build_rcv_fd(AF_INET6, SOCK_DGRAM, &(rcv_fds[16]), 16);
181 test(rcv_fds, 32, SOCK_DGRAM);
182 for (i = 0; i < 32; ++i)
183 close(rcv_fds[i]);
184
185 fprintf(stderr, "---- UDP IPv6 created before IPv4 (large) ----\n");
186 build_rcv_fd(AF_INET6, SOCK_DGRAM, rcv_fds, 16);
187 build_rcv_fd(AF_INET, SOCK_DGRAM, &(rcv_fds[16]), 16);
188 test(rcv_fds, 32, SOCK_DGRAM);
189 for (i = 0; i < 32; ++i)
190 close(rcv_fds[i]);
191
192 fprintf(stderr, "---- TCP IPv4 created before IPv6 ----\n");
193 build_rcv_fd(AF_INET, SOCK_STREAM, rcv_fds, 5);
194 build_rcv_fd(AF_INET6, SOCK_STREAM, &(rcv_fds[5]), 5);
195 test(rcv_fds, 10, SOCK_STREAM);
196 for (i = 0; i < 10; ++i)
197 close(rcv_fds[i]);
198
199 fprintf(stderr, "---- TCP IPv6 created before IPv4 ----\n");
200 build_rcv_fd(AF_INET6, SOCK_STREAM, rcv_fds, 5);
201 build_rcv_fd(AF_INET, SOCK_STREAM, &(rcv_fds[5]), 5);
202 test(rcv_fds, 10, SOCK_STREAM);
203 for (i = 0; i < 10; ++i)
204 close(rcv_fds[i]);
205
206 fprintf(stderr, "SUCCESS\n");
207 return 0;
208}
diff --git a/tools/testing/selftests/rcutorture/bin/jitter.sh b/tools/testing/selftests/rcutorture/bin/jitter.sh
new file mode 100755
index 000000000000..3633828375e3
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/jitter.sh
@@ -0,0 +1,90 @@
1#!/bin/bash
2#
3# Alternate sleeping and spinning on randomly selected CPUs. The purpose
4# of this script is to inflict random OS jitter on a concurrently running
5# test.
6#
7# Usage: jitter.sh me duration [ sleepmax [ spinmax ] ]
8#
9# me: Random-number-generator seed salt.
10# duration: Time to run in seconds.
11# sleepmax: Maximum microseconds to sleep, defaults to one second.
12# spinmax: Maximum microseconds to spin, defaults to one millisecond.
13#
14# This program is free software; you can redistribute it and/or modify
15# it under the terms of the GNU General Public License as published by
16# the Free Software Foundation; either version 2 of the License, or
17# (at your option) any later version.
18#
19# This program is distributed in the hope that it will be useful,
20# but WITHOUT ANY WARRANTY; without even the implied warranty of
21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22# GNU General Public License for more details.
23#
24# You should have received a copy of the GNU General Public License
25# along with this program; if not, you can access it online at
26# http://www.gnu.org/licenses/gpl-2.0.html.
27#
28# Copyright (C) IBM Corporation, 2016
29#
30# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
31
32me=$(($1 * 1000))
33duration=$2
34sleepmax=${3-1000000}
35spinmax=${4-1000}
36
37n=1
38
39starttime=`awk 'BEGIN { print systime(); }' < /dev/null`
40
41while :
42do
43 # Check for done.
44 t=`awk -v s=$starttime 'BEGIN { print systime() - s; }' < /dev/null`
45 if test "$t" -gt "$duration"
46 then
47 exit 0;
48 fi
49
50 # Set affinity to randomly selected CPU
51 cpus=`ls /sys/devices/system/cpu/*/online |
52 sed -e 's,/[^/]*$,,' -e 's/^[^0-9]*//' |
53 grep -v '^0*$'`
54 cpumask=`awk -v cpus="$cpus" -v me=$me -v n=$n 'BEGIN {
55 srand(n + me + systime());
56 ncpus = split(cpus, ca);
57 curcpu = ca[int(rand() * ncpus + 1)];
58 mask = lshift(1, curcpu);
59 if (mask + 0 <= 0)
60 mask = 1;
61 printf("%#x\n", mask);
62 }' < /dev/null`
63 n=$(($n+1))
64 if ! taskset -p $cpumask $$ > /dev/null 2>&1
65 then
66 echo taskset failure: '"taskset -p ' $cpumask $$ '"'
67 exit 1
68 fi
69
70 # Sleep a random duration
71 sleeptime=`awk -v me=$me -v n=$n -v sleepmax=$sleepmax 'BEGIN {
72 srand(n + me + systime());
73 printf("%06d", int(rand() * sleepmax));
74 }' < /dev/null`
75 n=$(($n+1))
76 sleep .$sleeptime
77
78 # Spin a random duration
79 limit=`awk -v me=$me -v n=$n -v spinmax=$spinmax 'BEGIN {
80 srand(n + me + systime());
81 printf("%06d", int(rand() * spinmax));
82 }' < /dev/null`
83 n=$(($n+1))
84 for i in {1..$limit}
85 do
86 echo > /dev/null
87 done
88done
89
90exit 1
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh
new file mode 100755
index 000000000000..f79b0e9e84fc
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf-ftrace.sh
@@ -0,0 +1,121 @@
1#!/bin/bash
2#
3# Analyze a given results directory for rcuperf performance measurements,
4# looking for ftrace data. Exits with 0 if data was found, analyzed, and
5# printed. Intended to be invoked from kvm-recheck-rcuperf.sh after
6# argument checking.
7#
8# Usage: kvm-recheck-rcuperf-ftrace.sh resdir
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, you can access it online at
22# http://www.gnu.org/licenses/gpl-2.0.html.
23#
24# Copyright (C) IBM Corporation, 2016
25#
26# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
27
28i="$1"
29. tools/testing/selftests/rcutorture/bin/functions.sh
30
31if test "`grep -c 'rcu_exp_grace_period.*start' < $i/console.log`" -lt 100
32then
33 exit 10
34fi
35
36sed -e 's/^\[[^]]*]//' < $i/console.log |
37grep 'us : rcu_exp_grace_period' |
38sed -e 's/us : / : /' |
39tr -d '\015' |
40awk '
41$8 == "start" {
42 if (starttask != "")
43 nlost++;
44 starttask = $1;
45 starttime = $3;
46 startseq = $7;
47}
48
49$8 == "end" {
50 if (starttask == $1 && startseq == $7) {
51 curgpdur = $3 - starttime;
52 gptimes[++n] = curgpdur;
53 gptaskcnt[starttask]++;
54 sum += curgpdur;
55 if (curgpdur > 1000)
56 print "Long GP " starttime "us to " $3 "us (" curgpdur "us)";
57 starttask = "";
58 } else {
59 # Lost a message or some such, reset.
60 starttask = "";
61 nlost++;
62 }
63}
64
65$8 == "done" {
66 piggybackcnt[$1]++;
67}
68
69END {
70 newNR = asort(gptimes);
71 if (newNR <= 0) {
72 print "No ftrace records found???"
73 exit 10;
74 }
75 pct50 = int(newNR * 50 / 100);
76 if (pct50 < 1)
77 pct50 = 1;
78 pct90 = int(newNR * 90 / 100);
79 if (pct90 < 1)
80 pct90 = 1;
81 pct99 = int(newNR * 99 / 100);
82 if (pct99 < 1)
83 pct99 = 1;
84 div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100;
85 print "Histogram bucket size: " div;
86 last = gptimes[1] - 10;
87 count = 0;
88 for (i = 1; i <= newNR; i++) {
89 current = div * int(gptimes[i] / div);
90 if (last == current) {
91 count++;
92 } else {
93 if (count > 0)
94 print last, count;
95 count = 1;
96 last = current;
97 }
98 }
99 if (count > 0)
100 print last, count;
101 print "Distribution of grace periods across tasks:";
102 for (i in gptaskcnt) {
103 print "\t" i, gptaskcnt[i];
104 nbatches += gptaskcnt[i];
105 }
106 ngps = nbatches;
107 print "Distribution of piggybacking across tasks:";
108 for (i in piggybackcnt) {
109 print "\t" i, piggybackcnt[i];
110 ngps += piggybackcnt[i];
111 }
112 print "Average grace-period duration: " sum / newNR " microseconds";
113 print "Minimum grace-period duration: " gptimes[1];
114 print "50th percentile grace-period duration: " gptimes[pct50];
115 print "90th percentile grace-period duration: " gptimes[pct90];
116 print "99th percentile grace-period duration: " gptimes[pct99];
117 print "Maximum grace-period duration: " gptimes[newNR];
118 print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches " Lost: " nlost + 0;
119 print "Computed from ftrace data.";
120}'
121exit 0
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh
new file mode 100755
index 000000000000..8f3121afc716
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck-rcuperf.sh
@@ -0,0 +1,96 @@
1#!/bin/bash
2#
3# Analyze a given results directory for rcuperf performance measurements.
4#
5# Usage: kvm-recheck-rcuperf.sh resdir
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, you can access it online at
19# http://www.gnu.org/licenses/gpl-2.0.html.
20#
21# Copyright (C) IBM Corporation, 2016
22#
23# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
24
25i="$1"
26if test -d $i
27then
28 :
29else
30 echo Unreadable results directory: $i
31 exit 1
32fi
33PATH=`pwd`/tools/testing/selftests/rcutorture/bin:$PATH; export PATH
34. tools/testing/selftests/rcutorture/bin/functions.sh
35
36if kvm-recheck-rcuperf-ftrace.sh $i
37then
38 # ftrace data was successfully analyzed, call it good!
39 exit 0
40fi
41
42configfile=`echo $i | sed -e 's/^.*\///'`
43
44sed -e 's/^\[[^]]*]//' < $i/console.log |
45awk '
46/-perf: .* gps: .* batches:/ {
47 ngps = $9;
48 nbatches = $11;
49}
50
51/-perf: .*writer-duration/ {
52 gptimes[++n] = $5 / 1000.;
53 sum += $5 / 1000.;
54}
55
56END {
57 newNR = asort(gptimes);
58 if (newNR <= 0) {
59 print "No rcuperf records found???"
60 exit;
61 }
62 pct50 = int(newNR * 50 / 100);
63 if (pct50 < 1)
64 pct50 = 1;
65 pct90 = int(newNR * 90 / 100);
66 if (pct90 < 1)
67 pct90 = 1;
68 pct99 = int(newNR * 99 / 100);
69 if (pct99 < 1)
70 pct99 = 1;
71 div = 10 ** int(log(gptimes[pct90]) / log(10) + .5) / 100;
72 print "Histogram bucket size: " div;
73 last = gptimes[1] - 10;
74 count = 0;
75 for (i = 1; i <= newNR; i++) {
76 current = div * int(gptimes[i] / div);
77 if (last == current) {
78 count++;
79 } else {
80 if (count > 0)
81 print last, count;
82 count = 1;
83 last = current;
84 }
85 }
86 if (count > 0)
87 print last, count;
88 print "Average grace-period duration: " sum / newNR " microseconds";
89 print "Minimum grace-period duration: " gptimes[1];
90 print "50th percentile grace-period duration: " gptimes[pct50];
91 print "90th percentile grace-period duration: " gptimes[pct90];
92 print "99th percentile grace-period duration: " gptimes[pct99];
93 print "Maximum grace-period duration: " gptimes[newNR];
94 print "Grace periods: " ngps + 0 " Batches: " nbatches + 0 " Ratio: " ngps / nbatches;
95 print "Computed from rcuperf printk output.";
96}'
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
index d86bdd6b6cc2..f659346d3358 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-recheck.sh
@@ -48,7 +48,10 @@ do
48 cat $i/Make.oldconfig.err 48 cat $i/Make.oldconfig.err
49 fi 49 fi
50 parse-build.sh $i/Make.out $configfile 50 parse-build.sh $i/Make.out $configfile
51 parse-torture.sh $i/console.log $configfile 51 if test "$TORTURE_SUITE" != rcuperf
52 then
53 parse-torture.sh $i/console.log $configfile
54 fi
52 parse-console.sh $i/console.log $configfile 55 parse-console.sh $i/console.log $configfile
53 if test -r $i/Warnings 56 if test -r $i/Warnings
54 then 57 then
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index 0f80eefb0bfd..4109f306d855 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -6,7 +6,7 @@
6# Execute this in the source tree. Do not run it as a background task 6# Execute this in the source tree. Do not run it as a background task
7# because qemu does not seem to like that much. 7# because qemu does not seem to like that much.
8# 8#
9# Usage: kvm-test-1-run.sh config builddir resdir minutes qemu-args boot_args 9# Usage: kvm-test-1-run.sh config builddir resdir seconds qemu-args boot_args
10# 10#
11# qemu-args defaults to "-enable-kvm -soundhw pcspk -nographic", along with 11# qemu-args defaults to "-enable-kvm -soundhw pcspk -nographic", along with
12# arguments specifying the number of CPUs and other 12# arguments specifying the number of CPUs and other
@@ -91,25 +91,33 @@ fi
91# CONFIG_PCMCIA=n 91# CONFIG_PCMCIA=n
92# CONFIG_CARDBUS=n 92# CONFIG_CARDBUS=n
93# CONFIG_YENTA=n 93# CONFIG_YENTA=n
94if kvm-build.sh $config_template $builddir $T 94base_resdir=`echo $resdir | sed -e 's/\.[0-9]\+$//'`
95if test "$base_resdir" != "$resdir" -a -f $base_resdir/bzImage -a -f $base_resdir/vmlinux
95then 96then
97 # Rerunning previous test, so use that test's kernel.
98 QEMU="`identify_qemu $base_resdir/vmlinux`"
99 KERNEL=$base_resdir/bzImage
100 ln -s $base_resdir/Make*.out $resdir # for kvm-recheck.sh
101 ln -s $base_resdir/.config $resdir # for kvm-recheck.sh
102elif kvm-build.sh $config_template $builddir $T
103then
104 # Had to build a kernel for this test.
96 QEMU="`identify_qemu $builddir/vmlinux`" 105 QEMU="`identify_qemu $builddir/vmlinux`"
97 BOOT_IMAGE="`identify_boot_image $QEMU`" 106 BOOT_IMAGE="`identify_boot_image $QEMU`"
98 cp $builddir/Make*.out $resdir 107 cp $builddir/Make*.out $resdir
108 cp $builddir/vmlinux $resdir
99 cp $builddir/.config $resdir 109 cp $builddir/.config $resdir
100 if test -n "$BOOT_IMAGE" 110 if test -n "$BOOT_IMAGE"
101 then 111 then
102 cp $builddir/$BOOT_IMAGE $resdir 112 cp $builddir/$BOOT_IMAGE $resdir
113 KERNEL=$resdir/bzImage
103 else 114 else
104 echo No identifiable boot image, not running KVM, see $resdir. 115 echo No identifiable boot image, not running KVM, see $resdir.
105 echo Do the torture scripts know about your architecture? 116 echo Do the torture scripts know about your architecture?
106 fi 117 fi
107 parse-build.sh $resdir/Make.out $title 118 parse-build.sh $resdir/Make.out $title
108 if test -f $builddir.wait
109 then
110 mv $builddir.wait $builddir.ready
111 fi
112else 119else
120 # Build failed.
113 cp $builddir/Make*.out $resdir 121 cp $builddir/Make*.out $resdir
114 cp $builddir/.config $resdir || : 122 cp $builddir/.config $resdir || :
115 echo Build failed, not running KVM, see $resdir. 123 echo Build failed, not running KVM, see $resdir.
@@ -119,12 +127,15 @@ else
119 fi 127 fi
120 exit 1 128 exit 1
121fi 129fi
130if test -f $builddir.wait
131then
132 mv $builddir.wait $builddir.ready
133fi
122while test -f $builddir.ready 134while test -f $builddir.ready
123do 135do
124 sleep 1 136 sleep 1
125done 137done
126minutes=$4 138seconds=$4
127seconds=$(($minutes * 60))
128qemu_args=$5 139qemu_args=$5
129boot_args=$6 140boot_args=$6
130 141
@@ -167,15 +178,26 @@ then
167 exit 0 178 exit 0
168fi 179fi
169echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log 180echo "NOTE: $QEMU either did not run or was interactive" > $resdir/console.log
170echo $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd 181echo $QEMU $qemu_args -m 512 -kernel $KERNEL -append \"$qemu_append $boot_args\" > $resdir/qemu-cmd
171( $QEMU $qemu_args -m 512 -kernel $resdir/bzImage -append "$qemu_append $boot_args"; echo $? > $resdir/qemu-retval ) & 182( $QEMU $qemu_args -m 512 -kernel $KERNEL -append "$qemu_append $boot_args"& echo $! > $resdir/qemu_pid; wait `cat $resdir/qemu_pid`; echo $? > $resdir/qemu-retval ) &
172qemu_pid=$!
173commandcompleted=0 183commandcompleted=0
174echo Monitoring qemu job at pid $qemu_pid 184sleep 10 # Give qemu's pid a chance to reach the file
185if test -s "$resdir/qemu_pid"
186then
187 qemu_pid=`cat "$resdir/qemu_pid"`
188 echo Monitoring qemu job at pid $qemu_pid
189else
190 qemu_pid=""
191 echo Monitoring qemu job at yet-as-unknown pid
192fi
175while : 193while :
176do 194do
195 if test -z "$qemu_pid" -a -s "$resdir/qemu_pid"
196 then
197 qemu_pid=`cat "$resdir/qemu_pid"`
198 fi
177 kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` 199 kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null`
178 if kill -0 $qemu_pid > /dev/null 2>&1 200 if test -z "$qemu_pid" || kill -0 "$qemu_pid" > /dev/null 2>&1
179 then 201 then
180 if test $kruntime -ge $seconds 202 if test $kruntime -ge $seconds
181 then 203 then
@@ -195,12 +217,16 @@ do
195 ps -fp $killpid >> $resdir/Warnings 2>&1 217 ps -fp $killpid >> $resdir/Warnings 2>&1
196 fi 218 fi
197 else 219 else
198 echo ' ---' `date`: Kernel done 220 echo ' ---' `date`: "Kernel done"
199 fi 221 fi
200 break 222 break
201 fi 223 fi
202done 224done
203if test $commandcompleted -eq 0 225if test -z "$qemu_pid" -a -s "$resdir/qemu_pid"
226then
227 qemu_pid=`cat "$resdir/qemu_pid"`
228fi
229if test $commandcompleted -eq 0 -a -n "$qemu_pid"
204then 230then
205 echo Grace period for qemu job at pid $qemu_pid 231 echo Grace period for qemu job at pid $qemu_pid
206 while : 232 while :
@@ -220,6 +246,9 @@ then
220 fi 246 fi
221 sleep 1 247 sleep 1
222 done 248 done
249elif test -z "$qemu_pid"
250then
251 echo Unknown PID, cannot kill qemu command
223fi 252fi
224 253
225parse-torture.sh $resdir/console.log $title 254parse-torture.sh $resdir/console.log $title
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 4a431767f77a..0d598145873e 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -34,7 +34,7 @@ T=/tmp/kvm.sh.$$
34trap 'rm -rf $T' 0 34trap 'rm -rf $T' 0
35mkdir $T 35mkdir $T
36 36
37dur=30 37dur=$((30*60))
38dryrun="" 38dryrun=""
39KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM 39KVM="`pwd`/tools/testing/selftests/rcutorture"; export KVM
40PATH=${KVM}/bin:$PATH; export PATH 40PATH=${KVM}/bin:$PATH; export PATH
@@ -48,6 +48,7 @@ resdir=""
48configs="" 48configs=""
49cpus=0 49cpus=0
50ds=`date +%Y.%m.%d-%H:%M:%S` 50ds=`date +%Y.%m.%d-%H:%M:%S`
51jitter=0
51 52
52. functions.sh 53. functions.sh
53 54
@@ -63,6 +64,7 @@ usage () {
63 echo " --dryrun sched|script" 64 echo " --dryrun sched|script"
64 echo " --duration minutes" 65 echo " --duration minutes"
65 echo " --interactive" 66 echo " --interactive"
67 echo " --jitter N [ maxsleep (us) [ maxspin (us) ] ]"
66 echo " --kmake-arg kernel-make-arguments" 68 echo " --kmake-arg kernel-make-arguments"
67 echo " --mac nn:nn:nn:nn:nn:nn" 69 echo " --mac nn:nn:nn:nn:nn:nn"
68 echo " --no-initrd" 70 echo " --no-initrd"
@@ -116,12 +118,17 @@ do
116 ;; 118 ;;
117 --duration) 119 --duration)
118 checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error' 120 checkarg --duration "(minutes)" $# "$2" '^[0-9]*$' '^error'
119 dur=$2 121 dur=$(($2*60))
120 shift 122 shift
121 ;; 123 ;;
122 --interactive) 124 --interactive)
123 TORTURE_QEMU_INTERACTIVE=1; export TORTURE_QEMU_INTERACTIVE 125 TORTURE_QEMU_INTERACTIVE=1; export TORTURE_QEMU_INTERACTIVE
124 ;; 126 ;;
127 --jitter)
128 checkarg --jitter "(# threads [ sleep [ spin ] ])" $# "$2" '^-\{,1\}[0-9]\+\( \+[0-9]\+\)\{,2\} *$' '^error$'
129 jitter="$2"
130 shift
131 ;;
125 --kmake-arg) 132 --kmake-arg)
126 checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$' 133 checkarg --kmake-arg "(kernel make arguments)" $# "$2" '.*' '^error$'
127 TORTURE_KMAKE_ARG="$2" 134 TORTURE_KMAKE_ARG="$2"
@@ -156,7 +163,7 @@ do
156 shift 163 shift
157 ;; 164 ;;
158 --torture) 165 --torture)
159 checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\)$' '^--' 166 checkarg --torture "(suite name)" "$#" "$2" '^\(lock\|rcu\|rcuperf\)$' '^--'
160 TORTURE_SUITE=$2 167 TORTURE_SUITE=$2
161 shift 168 shift
162 ;; 169 ;;
@@ -299,6 +306,7 @@ awk < $T/cfgcpu.pack \
299 -v CONFIGDIR="$CONFIGFRAG/" \ 306 -v CONFIGDIR="$CONFIGFRAG/" \
300 -v KVM="$KVM" \ 307 -v KVM="$KVM" \
301 -v ncpus=$cpus \ 308 -v ncpus=$cpus \
309 -v jitter="$jitter" \
302 -v rd=$resdir/$ds/ \ 310 -v rd=$resdir/$ds/ \
303 -v dur=$dur \ 311 -v dur=$dur \
304 -v TORTURE_QEMU_ARG="$TORTURE_QEMU_ARG" \ 312 -v TORTURE_QEMU_ARG="$TORTURE_QEMU_ARG" \
@@ -359,6 +367,16 @@ function dump(first, pastlast, batchnum)
359 print "\techo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log"; 367 print "\techo ----", cfr[j], cpusr[j] ovf ": Starting kernel. `date` >> " rd "/log";
360 print "fi" 368 print "fi"
361 } 369 }
370 njitter = 0;
371 split(jitter, ja);
372 if (ja[1] == -1 && ncpus == 0)
373 njitter = 1;
374 else if (ja[1] == -1)
375 njitter = ncpus;
376 else
377 njitter = ja[1];
378 for (j = 0; j < njitter; j++)
379 print "jitter.sh " j " " dur " " ja[2] " " ja[3] "&"
362 print "wait" 380 print "wait"
363 print "if test -z \"$TORTURE_BUILDONLY\"" 381 print "if test -z \"$TORTURE_BUILDONLY\""
364 print "then" 382 print "then"
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
index 39a2c6d7d7ec..17cbe098b115 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
@@ -14,7 +14,7 @@ CONFIG_HOTPLUG_CPU=n
14CONFIG_SUSPEND=n 14CONFIG_SUSPEND=n
15CONFIG_HIBERNATION=n 15CONFIG_HIBERNATION=n
16CONFIG_RCU_FANOUT=4 16CONFIG_RCU_FANOUT=4
17CONFIG_RCU_FANOUT_LEAF=4 17CONFIG_RCU_FANOUT_LEAF=3
18CONFIG_RCU_NOCB_CPU=n 18CONFIG_RCU_NOCB_CPU=n
19CONFIG_DEBUG_LOCK_ALLOC=n 19CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
index 0fc8a3428938..e34c33430447 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04.boot
@@ -1 +1 @@
rcutorture.torture_type=rcu_bh rcutorture.torture_type=rcu_bh rcutree.rcu_fanout_leaf=4
diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST b/tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST
new file mode 100644
index 000000000000..c9f56cf20775
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/CFLIST
@@ -0,0 +1 @@
TREE
diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon b/tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon
new file mode 100644
index 000000000000..a09816b8c0f3
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/CFcommon
@@ -0,0 +1,2 @@
1CONFIG_RCU_PERF_TEST=y
2CONFIG_PRINTK_TIME=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE
new file mode 100644
index 000000000000..a312f671a29a
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE
@@ -0,0 +1,20 @@
1CONFIG_SMP=y
2CONFIG_PREEMPT_NONE=n
3CONFIG_PREEMPT_VOLUNTARY=n
4CONFIG_PREEMPT=y
5#CHECK#CONFIG_PREEMPT_RCU=y
6CONFIG_HZ_PERIODIC=n
7CONFIG_NO_HZ_IDLE=y
8CONFIG_NO_HZ_FULL=n
9CONFIG_RCU_FAST_NO_HZ=n
10CONFIG_RCU_TRACE=n
11CONFIG_HOTPLUG_CPU=n
12CONFIG_SUSPEND=n
13CONFIG_HIBERNATION=n
14CONFIG_RCU_NOCB_CPU=n
15CONFIG_DEBUG_LOCK_ALLOC=n
16CONFIG_PROVE_LOCKING=n
17CONFIG_RCU_BOOST=n
18CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
19CONFIG_RCU_EXPERT=y
20CONFIG_RCU_TRACE=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54 b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54
new file mode 100644
index 000000000000..985fb170d13c
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/TREE54
@@ -0,0 +1,23 @@
1CONFIG_SMP=y
2CONFIG_NR_CPUS=54
3CONFIG_PREEMPT_NONE=n
4CONFIG_PREEMPT_VOLUNTARY=n
5CONFIG_PREEMPT=y
6#CHECK#CONFIG_PREEMPT_RCU=y
7CONFIG_HZ_PERIODIC=n
8CONFIG_NO_HZ_IDLE=y
9CONFIG_NO_HZ_FULL=n
10CONFIG_RCU_FAST_NO_HZ=n
11CONFIG_RCU_TRACE=n
12CONFIG_HOTPLUG_CPU=n
13CONFIG_SUSPEND=n
14CONFIG_HIBERNATION=n
15CONFIG_RCU_FANOUT=3
16CONFIG_RCU_FANOUT_LEAF=2
17CONFIG_RCU_NOCB_CPU=n
18CONFIG_DEBUG_LOCK_ALLOC=n
19CONFIG_PROVE_LOCKING=n
20CONFIG_RCU_BOOST=n
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
22CONFIG_RCU_EXPERT=y
23CONFIG_RCU_TRACE=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh b/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh
new file mode 100644
index 000000000000..34f2a1b35ee5
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/configs/rcuperf/ver_functions.sh
@@ -0,0 +1,52 @@
1#!/bin/bash
2#
3# Torture-suite-dependent shell functions for the rest of the scripts.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, you can access it online at
17# http://www.gnu.org/licenses/gpl-2.0.html.
18#
19# Copyright (C) IBM Corporation, 2015
20#
21# Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
22
23# rcuperf_param_nreaders bootparam-string
24#
25# Adds nreaders rcuperf module parameter if not already specified.
26rcuperf_param_nreaders () {
27 if ! echo "$1" | grep -q "rcuperf.nreaders"
28 then
29 echo rcuperf.nreaders=-1
30 fi
31}
32
33# rcuperf_param_nwriters bootparam-string
34#
35# Adds nwriters rcuperf module parameter if not already specified.
36rcuperf_param_nwriters () {
37 if ! echo "$1" | grep -q "rcuperf.nwriters"
38 then
39 echo rcuperf.nwriters=-1
40 fi
41}
42
43# per_version_boot_params bootparam-string config-file seconds
44#
45# Adds per-version torture-module parameters to kernels supporting them.
46per_version_boot_params () {
47 echo $1 `rcuperf_param_nreaders "$1"` \
48 `rcuperf_param_nwriters "$1"` \
49 rcuperf.perf_runnable=1 \
50 rcuperf.shutdown=1 \
51 rcuperf.verbose=1
52}
diff --git a/tools/testing/selftests/sigaltstack/Makefile b/tools/testing/selftests/sigaltstack/Makefile
new file mode 100644
index 000000000000..56af56eda6fa
--- /dev/null
+++ b/tools/testing/selftests/sigaltstack/Makefile
@@ -0,0 +1,8 @@
1CFLAGS = -Wall
2BINARIES = sas
3all: $(BINARIES)
4
5include ../lib.mk
6
7clean:
8 rm -rf $(BINARIES)
diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c
new file mode 100644
index 000000000000..1bb01258e559
--- /dev/null
+++ b/tools/testing/selftests/sigaltstack/sas.c
@@ -0,0 +1,176 @@
1/*
2 * Stas Sergeev <stsp@users.sourceforge.net>
3 *
4 * test sigaltstack(SS_ONSTACK | SS_AUTODISARM)
5 * If that succeeds, then swapcontext() can be used inside sighandler safely.
6 *
7 */
8
9#define _GNU_SOURCE
10#include <signal.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <sys/mman.h>
14#include <ucontext.h>
15#include <alloca.h>
16#include <string.h>
17#include <assert.h>
18#include <errno.h>
19
20#ifndef SS_AUTODISARM
21#define SS_AUTODISARM (1U << 31)
22#endif
23
24static void *sstack, *ustack;
25static ucontext_t uc, sc;
26static const char *msg = "[OK]\tStack preserved";
27static const char *msg2 = "[FAIL]\tStack corrupted";
28struct stk_data {
29 char msg[128];
30 int flag;
31};
32
33void my_usr1(int sig, siginfo_t *si, void *u)
34{
35 char *aa;
36 int err;
37 stack_t stk;
38 struct stk_data *p;
39
40 register unsigned long sp asm("sp");
41
42 if (sp < (unsigned long)sstack ||
43 sp >= (unsigned long)sstack + SIGSTKSZ) {
44 printf("[FAIL]\tSP is not on sigaltstack\n");
45 exit(EXIT_FAILURE);
46 }
47 /* put some data on stack. other sighandler will try to overwrite it */
48 aa = alloca(1024);
49 assert(aa);
50 p = (struct stk_data *)(aa + 512);
51 strcpy(p->msg, msg);
52 p->flag = 1;
53 printf("[RUN]\tsignal USR1\n");
54 err = sigaltstack(NULL, &stk);
55 if (err) {
56 perror("[FAIL]\tsigaltstack()");
57 exit(EXIT_FAILURE);
58 }
59 if (stk.ss_flags != SS_DISABLE)
60 printf("[FAIL]\tss_flags=%i, should be SS_DISABLE\n",
61 stk.ss_flags);
62 else
63 printf("[OK]\tsigaltstack is disabled in sighandler\n");
64 swapcontext(&sc, &uc);
65 printf("%s\n", p->msg);
66 if (!p->flag) {
67 printf("[RUN]\tAborting\n");
68 exit(EXIT_FAILURE);
69 }
70}
71
72void my_usr2(int sig, siginfo_t *si, void *u)
73{
74 char *aa;
75 struct stk_data *p;
76
77 printf("[RUN]\tsignal USR2\n");
78 aa = alloca(1024);
79 /* dont run valgrind on this */
80 /* try to find the data stored by previous sighandler */
81 p = memmem(aa, 1024, msg, strlen(msg));
82 if (p) {
83 printf("[FAIL]\tsigaltstack re-used\n");
84 /* corrupt the data */
85 strcpy(p->msg, msg2);
86 /* tell other sighandler that his data is corrupted */
87 p->flag = 0;
88 }
89}
90
91static void switch_fn(void)
92{
93 printf("[RUN]\tswitched to user ctx\n");
94 raise(SIGUSR2);
95 setcontext(&sc);
96}
97
98int main(void)
99{
100 struct sigaction act;
101 stack_t stk;
102 int err;
103
104 sigemptyset(&act.sa_mask);
105 act.sa_flags = SA_ONSTACK | SA_SIGINFO;
106 act.sa_sigaction = my_usr1;
107 sigaction(SIGUSR1, &act, NULL);
108 act.sa_sigaction = my_usr2;
109 sigaction(SIGUSR2, &act, NULL);
110 sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
111 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
112 if (sstack == MAP_FAILED) {
113 perror("mmap()");
114 return EXIT_FAILURE;
115 }
116
117 err = sigaltstack(NULL, &stk);
118 if (err) {
119 perror("[FAIL]\tsigaltstack()");
120 exit(EXIT_FAILURE);
121 }
122 if (stk.ss_flags == SS_DISABLE) {
123 printf("[OK]\tInitial sigaltstack state was SS_DISABLE\n");
124 } else {
125 printf("[FAIL]\tInitial sigaltstack state was %i; should have been SS_DISABLE\n", stk.ss_flags);
126 return EXIT_FAILURE;
127 }
128
129 stk.ss_sp = sstack;
130 stk.ss_size = SIGSTKSZ;
131 stk.ss_flags = SS_ONSTACK | SS_AUTODISARM;
132 err = sigaltstack(&stk, NULL);
133 if (err) {
134 if (errno == EINVAL) {
135 printf("[NOTE]\tThe running kernel doesn't support SS_AUTODISARM\n");
136 /*
137 * If test cases for the !SS_AUTODISARM variant were
138 * added, we could still run them. We don't have any
139 * test cases like that yet, so just exit and report
140 * success.
141 */
142 return 0;
143 } else {
144 perror("[FAIL]\tsigaltstack(SS_ONSTACK | SS_AUTODISARM)");
145 return EXIT_FAILURE;
146 }
147 }
148
149 ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
150 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
151 if (ustack == MAP_FAILED) {
152 perror("mmap()");
153 return EXIT_FAILURE;
154 }
155 getcontext(&uc);
156 uc.uc_link = NULL;
157 uc.uc_stack.ss_sp = ustack;
158 uc.uc_stack.ss_size = SIGSTKSZ;
159 makecontext(&uc, switch_fn, 0);
160 raise(SIGUSR1);
161
162 err = sigaltstack(NULL, &stk);
163 if (err) {
164 perror("[FAIL]\tsigaltstack()");
165 exit(EXIT_FAILURE);
166 }
167 if (stk.ss_flags != SS_AUTODISARM) {
168 printf("[FAIL]\tss_flags=%i, should be SS_AUTODISARM\n",
169 stk.ss_flags);
170 exit(EXIT_FAILURE);
171 }
172 printf("[OK]\tsigaltstack is still SS_AUTODISARM after signal\n");
173
174 printf("[OK]\tTest passed\n");
175 return 0;
176}
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index b47ebd170690..c73425de3cfe 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -9,6 +9,7 @@ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_sysc
9TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ 9TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
10 test_FCMOV test_FCOMI test_FISTTP \ 10 test_FCMOV test_FCOMI test_FISTTP \
11 vdso_restorer 11 vdso_restorer
12TARGETS_C_64BIT_ONLY := fsgsbase
12 13
13TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) 14TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
14TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY) 15TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY)
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
new file mode 100644
index 000000000000..5b2b4b3c634c
--- /dev/null
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -0,0 +1,398 @@
1/*
2 * fsgsbase.c, an fsgsbase test
3 * Copyright (c) 2014-2016 Andy Lutomirski
4 * GPL v2
5 */
6
7#define _GNU_SOURCE
8#include <stdio.h>
9#include <stdlib.h>
10#include <stdbool.h>
11#include <string.h>
12#include <sys/syscall.h>
13#include <unistd.h>
14#include <err.h>
15#include <sys/user.h>
16#include <asm/prctl.h>
17#include <sys/prctl.h>
18#include <signal.h>
19#include <limits.h>
20#include <sys/ucontext.h>
21#include <sched.h>
22#include <linux/futex.h>
23#include <pthread.h>
24#include <asm/ldt.h>
25#include <sys/mman.h>
26
27#ifndef __x86_64__
28# error This test is 64-bit only
29#endif
30
31static volatile sig_atomic_t want_segv;
32static volatile unsigned long segv_addr;
33
34static int nerrs;
35
36static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
37 int flags)
38{
39 struct sigaction sa;
40 memset(&sa, 0, sizeof(sa));
41 sa.sa_sigaction = handler;
42 sa.sa_flags = SA_SIGINFO | flags;
43 sigemptyset(&sa.sa_mask);
44 if (sigaction(sig, &sa, 0))
45 err(1, "sigaction");
46}
47
48static void clearhandler(int sig)
49{
50 struct sigaction sa;
51 memset(&sa, 0, sizeof(sa));
52 sa.sa_handler = SIG_DFL;
53 sigemptyset(&sa.sa_mask);
54 if (sigaction(sig, &sa, 0))
55 err(1, "sigaction");
56}
57
58static void sigsegv(int sig, siginfo_t *si, void *ctx_void)
59{
60 ucontext_t *ctx = (ucontext_t*)ctx_void;
61
62 if (!want_segv) {
63 clearhandler(SIGSEGV);
64 return; /* Crash cleanly. */
65 }
66
67 want_segv = false;
68 segv_addr = (unsigned long)si->si_addr;
69
70 ctx->uc_mcontext.gregs[REG_RIP] += 4; /* Skip the faulting mov */
71
72}
73
74enum which_base { FS, GS };
75
76static unsigned long read_base(enum which_base which)
77{
78 unsigned long offset;
79 /*
80 * Unless we have FSGSBASE, there's no direct way to do this from
81 * user mode. We can get at it indirectly using signals, though.
82 */
83
84 want_segv = true;
85
86 offset = 0;
87 if (which == FS) {
88 /* Use a constant-length instruction here. */
89 asm volatile ("mov %%fs:(%%rcx), %%rax" : : "c" (offset) : "rax");
90 } else {
91 asm volatile ("mov %%gs:(%%rcx), %%rax" : : "c" (offset) : "rax");
92 }
93 if (!want_segv)
94 return segv_addr + offset;
95
96 /*
97 * If that didn't segfault, try the other end of the address space.
98 * Unless we get really unlucky and run into the vsyscall page, this
99 * is guaranteed to segfault.
100 */
101
102 offset = (ULONG_MAX >> 1) + 1;
103 if (which == FS) {
104 asm volatile ("mov %%fs:(%%rcx), %%rax"
105 : : "c" (offset) : "rax");
106 } else {
107 asm volatile ("mov %%gs:(%%rcx), %%rax"
108 : : "c" (offset) : "rax");
109 }
110 if (!want_segv)
111 return segv_addr + offset;
112
113 abort();
114}
115
116static void check_gs_value(unsigned long value)
117{
118 unsigned long base;
119 unsigned short sel;
120
121 printf("[RUN]\tARCH_SET_GS to 0x%lx\n", value);
122 if (syscall(SYS_arch_prctl, ARCH_SET_GS, value) != 0)
123 err(1, "ARCH_SET_GS");
124
125 asm volatile ("mov %%gs, %0" : "=rm" (sel));
126 base = read_base(GS);
127 if (base == value) {
128 printf("[OK]\tGSBASE was set as expected (selector 0x%hx)\n",
129 sel);
130 } else {
131 nerrs++;
132 printf("[FAIL]\tGSBASE was not as expected: got 0x%lx (selector 0x%hx)\n",
133 base, sel);
134 }
135
136 if (syscall(SYS_arch_prctl, ARCH_GET_GS, &base) != 0)
137 err(1, "ARCH_GET_GS");
138 if (base == value) {
139 printf("[OK]\tARCH_GET_GS worked as expected (selector 0x%hx)\n",
140 sel);
141 } else {
142 nerrs++;
143 printf("[FAIL]\tARCH_GET_GS was not as expected: got 0x%lx (selector 0x%hx)\n",
144 base, sel);
145 }
146}
147
148static void mov_0_gs(unsigned long initial_base, bool schedule)
149{
150 unsigned long base, arch_base;
151
152 printf("[RUN]\tARCH_SET_GS to 0x%lx then mov 0 to %%gs%s\n", initial_base, schedule ? " and schedule " : "");
153 if (syscall(SYS_arch_prctl, ARCH_SET_GS, initial_base) != 0)
154 err(1, "ARCH_SET_GS");
155
156 if (schedule)
157 usleep(10);
158
159 asm volatile ("mov %0, %%gs" : : "rm" (0));
160 base = read_base(GS);
161 if (syscall(SYS_arch_prctl, ARCH_GET_GS, &arch_base) != 0)
162 err(1, "ARCH_GET_GS");
163 if (base == arch_base) {
164 printf("[OK]\tGSBASE is 0x%lx\n", base);
165 } else {
166 nerrs++;
167 printf("[FAIL]\tGSBASE changed to 0x%lx but kernel reports 0x%lx\n", base, arch_base);
168 }
169}
170
171static volatile unsigned long remote_base;
172static volatile bool remote_hard_zero;
173static volatile unsigned int ftx;
174
175/*
176 * ARCH_SET_FS/GS(0) may or may not program a selector of zero. HARD_ZERO
177 * means to force the selector to zero to improve test coverage.
178 */
179#define HARD_ZERO 0xa1fa5f343cb85fa4
180
181static void do_remote_base()
182{
183 unsigned long to_set = remote_base;
184 bool hard_zero = false;
185 if (to_set == HARD_ZERO) {
186 to_set = 0;
187 hard_zero = true;
188 }
189
190 if (syscall(SYS_arch_prctl, ARCH_SET_GS, to_set) != 0)
191 err(1, "ARCH_SET_GS");
192
193 if (hard_zero)
194 asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
195
196 unsigned short sel;
197 asm volatile ("mov %%gs, %0" : "=rm" (sel));
198 printf("\tother thread: ARCH_SET_GS(0x%lx)%s -- sel is 0x%hx\n",
199 to_set, hard_zero ? " and clear gs" : "", sel);
200}
201
202void do_unexpected_base(void)
203{
204 /*
205 * The goal here is to try to arrange for GS == 0, GSBASE !=
206 * 0, and for the the kernel the think that GSBASE == 0.
207 *
208 * To make the test as reliable as possible, this uses
209 * explicit descriptorss. (This is not the only way. This
210 * could use ARCH_SET_GS with a low, nonzero base, but the
211 * relevant side effect of ARCH_SET_GS could change.)
212 */
213
214 /* Step 1: tell the kernel that we have GSBASE == 0. */
215 if (syscall(SYS_arch_prctl, ARCH_SET_GS, 0) != 0)
216 err(1, "ARCH_SET_GS");
217
218 /* Step 2: change GSBASE without telling the kernel. */
219 struct user_desc desc = {
220 .entry_number = 0,
221 .base_addr = 0xBAADF00D,
222 .limit = 0xfffff,
223 .seg_32bit = 1,
224 .contents = 0, /* Data, grow-up */
225 .read_exec_only = 0,
226 .limit_in_pages = 1,
227 .seg_not_present = 0,
228 .useable = 0
229 };
230 if (syscall(SYS_modify_ldt, 1, &desc, sizeof(desc)) == 0) {
231 printf("\tother thread: using LDT slot 0\n");
232 asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0x7));
233 } else {
234 /* No modify_ldt for us (configured out, perhaps) */
235
236 struct user_desc *low_desc = mmap(
237 NULL, sizeof(desc),
238 PROT_READ | PROT_WRITE,
239 MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
240 memcpy(low_desc, &desc, sizeof(desc));
241
242 low_desc->entry_number = -1;
243
244 /* 32-bit set_thread_area */
245 long ret;
246 asm volatile ("int $0x80"
247 : "=a" (ret) : "a" (243), "b" (low_desc)
248 : "flags");
249 memcpy(&desc, low_desc, sizeof(desc));
250 munmap(low_desc, sizeof(desc));
251
252 if (ret != 0) {
253 printf("[NOTE]\tcould not create a segment -- test won't do anything\n");
254 return;
255 }
256 printf("\tother thread: using GDT slot %d\n", desc.entry_number);
257 asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)((desc.entry_number << 3) | 0x3)));
258 }
259
260 /*
261 * Step 3: set the selector back to zero. On AMD chips, this will
262 * preserve GSBASE.
263 */
264
265 asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
266}
267
268static void *threadproc(void *ctx)
269{
270 while (1) {
271 while (ftx == 0)
272 syscall(SYS_futex, &ftx, FUTEX_WAIT, 0, NULL, NULL, 0);
273 if (ftx == 3)
274 return NULL;
275
276 if (ftx == 1)
277 do_remote_base();
278 else if (ftx == 2)
279 do_unexpected_base();
280 else
281 errx(1, "helper thread got bad command");
282
283 ftx = 0;
284 syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
285 }
286}
287
288static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
289{
290 unsigned long base;
291
292 bool hard_zero = false;
293 if (local == HARD_ZERO) {
294 hard_zero = true;
295 local = 0;
296 }
297
298 printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n",
299 local, hard_zero ? " and clear gs" : "", remote);
300 if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0)
301 err(1, "ARCH_SET_GS");
302 if (hard_zero)
303 asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
304
305 if (read_base(GS) != local) {
306 nerrs++;
307 printf("[FAIL]\tGSBASE wasn't set as expected\n");
308 }
309
310 remote_base = remote;
311 ftx = 1;
312 syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
313 while (ftx != 0)
314 syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
315
316 base = read_base(GS);
317 if (base == local) {
318 printf("[OK]\tGSBASE remained 0x%lx\n", local);
319 } else {
320 nerrs++;
321 printf("[FAIL]\tGSBASE changed to 0x%lx\n", base);
322 }
323}
324
325static void test_unexpected_base(void)
326{
327 unsigned long base;
328
329 printf("[RUN]\tARCH_SET_GS(0), clear gs, then manipulate GSBASE in a different thread\n");
330 if (syscall(SYS_arch_prctl, ARCH_SET_GS, 0) != 0)
331 err(1, "ARCH_SET_GS");
332 asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0));
333
334 ftx = 2;
335 syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
336 while (ftx != 0)
337 syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
338
339 base = read_base(GS);
340 if (base == 0) {
341 printf("[OK]\tGSBASE remained 0\n");
342 } else {
343 nerrs++;
344 printf("[FAIL]\tGSBASE changed to 0x%lx\n", base);
345 }
346}
347
348int main()
349{
350 pthread_t thread;
351
352 sethandler(SIGSEGV, sigsegv, 0);
353
354 check_gs_value(0);
355 check_gs_value(1);
356 check_gs_value(0x200000000);
357 check_gs_value(0);
358 check_gs_value(0x200000000);
359 check_gs_value(1);
360
361 for (int sched = 0; sched < 2; sched++) {
362 mov_0_gs(0, !!sched);
363 mov_0_gs(1, !!sched);
364 mov_0_gs(0x200000000, !!sched);
365 }
366
367 /* Set up for multithreading. */
368
369 cpu_set_t cpuset;
370 CPU_ZERO(&cpuset);
371 CPU_SET(0, &cpuset);
372 if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
373 err(1, "sched_setaffinity to CPU 0"); /* should never fail */
374
375 if (pthread_create(&thread, 0, threadproc, 0) != 0)
376 err(1, "pthread_create");
377
378 static unsigned long bases_with_hard_zero[] = {
379 0, HARD_ZERO, 1, 0x200000000,
380 };
381
382 for (int local = 0; local < 4; local++) {
383 for (int remote = 0; remote < 4; remote++) {
384 set_gs_and_switch_to(bases_with_hard_zero[local],
385 bases_with_hard_zero[remote]);
386 }
387 }
388
389 test_unexpected_base();
390
391 ftx = 3; /* Kill the thread. */
392 syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
393
394 if (pthread_join(thread, NULL) != 0)
395 err(1, "pthread_join");
396
397 return nerrs == 0 ? 0 : 1;
398}
diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c
index 31a3035cd4eb..4af47079cf04 100644
--- a/tools/testing/selftests/x86/ldt_gdt.c
+++ b/tools/testing/selftests/x86/ldt_gdt.c
@@ -21,6 +21,9 @@
21#include <pthread.h> 21#include <pthread.h>
22#include <sched.h> 22#include <sched.h>
23#include <linux/futex.h> 23#include <linux/futex.h>
24#include <sys/mman.h>
25#include <asm/prctl.h>
26#include <sys/prctl.h>
24 27
25#define AR_ACCESSED (1<<8) 28#define AR_ACCESSED (1<<8)
26 29
@@ -44,6 +47,12 @@
44 47
45static int nerrs; 48static int nerrs;
46 49
50/* Points to an array of 1024 ints, each holding its own index. */
51static const unsigned int *counter_page;
52static struct user_desc *low_user_desc;
53static struct user_desc *low_user_desc_clear; /* Use to delete GDT entry */
54static int gdt_entry_num;
55
47static void check_invalid_segment(uint16_t index, int ldt) 56static void check_invalid_segment(uint16_t index, int ldt)
48{ 57{
49 uint32_t has_limit = 0, has_ar = 0, limit, ar; 58 uint32_t has_limit = 0, has_ar = 0, limit, ar;
@@ -561,16 +570,257 @@ static void do_exec_test(void)
561 } 570 }
562} 571}
563 572
573static void setup_counter_page(void)
574{
575 unsigned int *page = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
576 MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1, 0);
577 if (page == MAP_FAILED)
578 err(1, "mmap");
579
580 for (int i = 0; i < 1024; i++)
581 page[i] = i;
582 counter_page = page;
583}
584
585static int invoke_set_thread_area(void)
586{
587 int ret;
588 asm volatile ("int $0x80"
589 : "=a" (ret), "+m" (low_user_desc) :
590 "a" (243), "b" (low_user_desc)
591 : "flags");
592 return ret;
593}
594
595static void setup_low_user_desc(void)
596{
597 low_user_desc = mmap(NULL, 2 * sizeof(struct user_desc),
598 PROT_READ | PROT_WRITE,
599 MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1, 0);
600 if (low_user_desc == MAP_FAILED)
601 err(1, "mmap");
602
603 low_user_desc->entry_number = -1;
604 low_user_desc->base_addr = (unsigned long)&counter_page[1];
605 low_user_desc->limit = 0xfffff;
606 low_user_desc->seg_32bit = 1;
607 low_user_desc->contents = 0; /* Data, grow-up*/
608 low_user_desc->read_exec_only = 0;
609 low_user_desc->limit_in_pages = 1;
610 low_user_desc->seg_not_present = 0;
611 low_user_desc->useable = 0;
612
613 if (invoke_set_thread_area() == 0) {
614 gdt_entry_num = low_user_desc->entry_number;
615 printf("[NOTE]\tset_thread_area is available; will use GDT index %d\n", gdt_entry_num);
616 } else {
617 printf("[NOTE]\tset_thread_area is unavailable\n");
618 }
619
620 low_user_desc_clear = low_user_desc + 1;
621 low_user_desc_clear->entry_number = gdt_entry_num;
622 low_user_desc_clear->read_exec_only = 1;
623 low_user_desc_clear->seg_not_present = 1;
624}
625
626static void test_gdt_invalidation(void)
627{
628 if (!gdt_entry_num)
629 return; /* 64-bit only system -- we can't use set_thread_area */
630
631 unsigned short prev_sel;
632 unsigned short sel;
633 unsigned int eax;
634 const char *result;
635#ifdef __x86_64__
636 unsigned long saved_base;
637 unsigned long new_base;
638#endif
639
640 /* Test DS */
641 invoke_set_thread_area();
642 eax = 243;
643 sel = (gdt_entry_num << 3) | 3;
644 asm volatile ("movw %%ds, %[prev_sel]\n\t"
645 "movw %[sel], %%ds\n\t"
646#ifdef __i386__
647 "pushl %%ebx\n\t"
648#endif
649 "movl %[arg1], %%ebx\n\t"
650 "int $0x80\n\t" /* Should invalidate ds */
651#ifdef __i386__
652 "popl %%ebx\n\t"
653#endif
654 "movw %%ds, %[sel]\n\t"
655 "movw %[prev_sel], %%ds"
656 : [prev_sel] "=&r" (prev_sel), [sel] "+r" (sel),
657 "+a" (eax)
658 : "m" (low_user_desc_clear),
659 [arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
660 : "flags");
661
662 if (sel != 0) {
663 result = "FAIL";
664 nerrs++;
665 } else {
666 result = "OK";
667 }
668 printf("[%s]\tInvalidate DS with set_thread_area: new DS = 0x%hx\n",
669 result, sel);
670
671 /* Test ES */
672 invoke_set_thread_area();
673 eax = 243;
674 sel = (gdt_entry_num << 3) | 3;
675 asm volatile ("movw %%es, %[prev_sel]\n\t"
676 "movw %[sel], %%es\n\t"
677#ifdef __i386__
678 "pushl %%ebx\n\t"
679#endif
680 "movl %[arg1], %%ebx\n\t"
681 "int $0x80\n\t" /* Should invalidate es */
682#ifdef __i386__
683 "popl %%ebx\n\t"
684#endif
685 "movw %%es, %[sel]\n\t"
686 "movw %[prev_sel], %%es"
687 : [prev_sel] "=&r" (prev_sel), [sel] "+r" (sel),
688 "+a" (eax)
689 : "m" (low_user_desc_clear),
690 [arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
691 : "flags");
692
693 if (sel != 0) {
694 result = "FAIL";
695 nerrs++;
696 } else {
697 result = "OK";
698 }
699 printf("[%s]\tInvalidate ES with set_thread_area: new ES = 0x%hx\n",
700 result, sel);
701
702 /* Test FS */
703 invoke_set_thread_area();
704 eax = 243;
705 sel = (gdt_entry_num << 3) | 3;
706#ifdef __x86_64__
707 syscall(SYS_arch_prctl, ARCH_GET_FS, &saved_base);
708#endif
709 asm volatile ("movw %%fs, %[prev_sel]\n\t"
710 "movw %[sel], %%fs\n\t"
711#ifdef __i386__
712 "pushl %%ebx\n\t"
713#endif
714 "movl %[arg1], %%ebx\n\t"
715 "int $0x80\n\t" /* Should invalidate fs */
716#ifdef __i386__
717 "popl %%ebx\n\t"
718#endif
719 "movw %%fs, %[sel]\n\t"
720 : [prev_sel] "=&r" (prev_sel), [sel] "+r" (sel),
721 "+a" (eax)
722 : "m" (low_user_desc_clear),
723 [arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
724 : "flags");
725
726#ifdef __x86_64__
727 syscall(SYS_arch_prctl, ARCH_GET_FS, &new_base);
728#endif
729
730 /* Restore FS/BASE for glibc */
731 asm volatile ("movw %[prev_sel], %%fs" : : [prev_sel] "rm" (prev_sel));
732#ifdef __x86_64__
733 if (saved_base)
734 syscall(SYS_arch_prctl, ARCH_SET_FS, saved_base);
735#endif
736
737 if (sel != 0) {
738 result = "FAIL";
739 nerrs++;
740 } else {
741 result = "OK";
742 }
743 printf("[%s]\tInvalidate FS with set_thread_area: new FS = 0x%hx\n",
744 result, sel);
745
746#ifdef __x86_64__
747 if (sel == 0 && new_base != 0) {
748 nerrs++;
749 printf("[FAIL]\tNew FSBASE was 0x%lx\n", new_base);
750 } else {
751 printf("[OK]\tNew FSBASE was zero\n");
752 }
753#endif
754
755 /* Test GS */
756 invoke_set_thread_area();
757 eax = 243;
758 sel = (gdt_entry_num << 3) | 3;
759#ifdef __x86_64__
760 syscall(SYS_arch_prctl, ARCH_GET_GS, &saved_base);
761#endif
762 asm volatile ("movw %%gs, %[prev_sel]\n\t"
763 "movw %[sel], %%gs\n\t"
764#ifdef __i386__
765 "pushl %%ebx\n\t"
766#endif
767 "movl %[arg1], %%ebx\n\t"
768 "int $0x80\n\t" /* Should invalidate gs */
769#ifdef __i386__
770 "popl %%ebx\n\t"
771#endif
772 "movw %%gs, %[sel]\n\t"
773 : [prev_sel] "=&r" (prev_sel), [sel] "+r" (sel),
774 "+a" (eax)
775 : "m" (low_user_desc_clear),
776 [arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
777 : "flags");
778
779#ifdef __x86_64__
780 syscall(SYS_arch_prctl, ARCH_GET_GS, &new_base);
781#endif
782
783 /* Restore GS/BASE for glibc */
784 asm volatile ("movw %[prev_sel], %%gs" : : [prev_sel] "rm" (prev_sel));
785#ifdef __x86_64__
786 if (saved_base)
787 syscall(SYS_arch_prctl, ARCH_SET_GS, saved_base);
788#endif
789
790 if (sel != 0) {
791 result = "FAIL";
792 nerrs++;
793 } else {
794 result = "OK";
795 }
796 printf("[%s]\tInvalidate GS with set_thread_area: new GS = 0x%hx\n",
797 result, sel);
798
799#ifdef __x86_64__
800 if (sel == 0 && new_base != 0) {
801 nerrs++;
802 printf("[FAIL]\tNew GSBASE was 0x%lx\n", new_base);
803 } else {
804 printf("[OK]\tNew GSBASE was zero\n");
805 }
806#endif
807}
808
564int main(int argc, char **argv) 809int main(int argc, char **argv)
565{ 810{
566 if (argc == 1 && !strcmp(argv[0], "ldt_gdt_test_exec")) 811 if (argc == 1 && !strcmp(argv[0], "ldt_gdt_test_exec"))
567 return finish_exec_test(); 812 return finish_exec_test();
568 813
814 setup_counter_page();
815 setup_low_user_desc();
816
569 do_simple_tests(); 817 do_simple_tests();
570 818
571 do_multicpu_tests(); 819 do_multicpu_tests();
572 820
573 do_exec_test(); 821 do_exec_test();
574 822
823 test_gdt_invalidation();
824
575 return nerrs ? 1 : 0; 825 return nerrs ? 1 : 0;
576} 826}