aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile9
-rw-r--r--tools/build/Makefile.build8
-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/hv/lsvmbus1
-rw-r--r--tools/iio/generic_buffer.c116
-rw-r--r--tools/iio/iio_event_monitor.c18
-rw-r--r--tools/iio/iio_utils.h7
-rw-r--r--tools/kvm/kvm_stat/Makefile41
-rwxr-xr-xtools/kvm/kvm_stat/kvm_stat1127
-rw-r--r--tools/kvm/kvm_stat/kvm_stat.txt63
-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/Makefile4
-rw-r--r--tools/objtool/elf.h5
-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.txt5
-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.txt33
-rw-r--r--tools/perf/Makefile.perf15
-rw-r--r--tools/perf/arch/powerpc/Makefile1
-rw-r--r--tools/perf/arch/powerpc/include/perf_regs.h69
-rw-r--r--tools/perf/arch/powerpc/util/Build2
-rw-r--r--tools/perf/arch/powerpc/util/dwarf-regs.c40
-rw-r--r--tools/perf/arch/powerpc/util/perf_regs.c49
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c43
-rw-r--r--tools/perf/arch/powerpc/util/unwind-libunwind.c96
-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-annotate.c5
-rw-r--r--tools/perf/builtin-buildid-cache.c8
-rw-r--r--tools/perf/builtin-config.c39
-rw-r--r--tools/perf/builtin-diff.c9
-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.c348
-rw-r--r--tools/perf/builtin-report.c22
-rw-r--r--tools/perf/builtin-sched.c198
-rw-r--r--tools/perf/builtin-script.c127
-rw-r--r--tools/perf/builtin-stat.c37
-rw-r--r--tools/perf/builtin-timechart.c5
-rw-r--r--tools/perf/builtin-top.c45
-rw-r--r--tools/perf/builtin-trace.c1355
-rw-r--r--tools/perf/config/Makefile17
-rw-r--r--tools/perf/jvmti/jvmti_agent.c43
-rw-r--r--tools/perf/perf.c19
-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.c36
-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.c38
-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.c88
-rw-r--r--tools/perf/util/db-export.h3
-rw-r--r--tools/perf/util/dso.c11
-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.c208
-rw-r--r--tools/perf/util/evlist.h26
-rw-r--r--tools/perf/util/evsel.c177
-rw-r--r--tools/perf/util/evsel.h29
-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.c32
-rw-r--r--tools/perf/util/hist.h14
-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.c22
-rw-r--r--tools/perf/util/jitdump.c41
-rw-r--r--tools/perf/util/jitdump.h3
-rw-r--r--tools/perf/util/machine.c136
-rw-r--r--tools/perf/util/machine.h8
-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/perf_regs.c8
-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.c125
-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.c122
-rw-r--r--tools/perf/util/sort.h9
-rw-r--r--tools/perf/util/stat-shadow.c8
-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.c141
-rw-r--r--tools/perf/util/symbol.h26
-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/top.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.c39
-rw-r--r--tools/perf/util/util.h16
-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/nvdimm/Kbuild11
-rw-r--r--tools/testing/nvdimm/config_check.c2
-rw-r--r--tools/testing/nvdimm/test/iomap.c27
-rw-r--r--tools/testing/nvdimm/test/nfit.c90
-rw-r--r--tools/testing/radix-tree/Makefile4
-rw-r--r--tools/testing/radix-tree/generated/autoconf.h3
-rw-r--r--tools/testing/radix-tree/linux/init.h1
-rw-r--r--tools/testing/radix-tree/linux/kernel.h15
-rw-r--r--tools/testing/radix-tree/linux/slab.h1
-rw-r--r--tools/testing/radix-tree/linux/types.h7
-rw-r--r--tools/testing/radix-tree/main.c84
-rw-r--r--tools/testing/radix-tree/multiorder.c337
-rw-r--r--tools/testing/radix-tree/regression2.c7
-rw-r--r--tools/testing/radix-tree/tag_check.c10
-rw-r--r--tools/testing/radix-tree/test.c49
-rw-r--r--tools/testing/radix-tree/test.h11
-rw-r--r--tools/testing/selftests/Makefile1
-rwxr-xr-xtools/testing/selftests/ftrace/ftracetest9
-rw-r--r--tools/testing/selftests/ftrace/test.d/event/event-pid.tc72
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions9
-rw-r--r--tools/testing/selftests/ftrace/test.d/instances/instance-event.tc138
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc64
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc59
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc75
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc83
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc73
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc56
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc53
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc58
-rwxr-xr-xtools/testing/selftests/intel_pstate/run.sh2
-rw-r--r--tools/testing/selftests/powerpc/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/context_switch/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/context_switch/Makefile10
-rw-r--r--tools/testing/selftests/powerpc/context_switch/cp_abort.c110
-rw-r--r--tools/testing/selftests/powerpc/mm/subpage_prot.c18
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb.c1
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c1
-rw-r--r--tools/testing/selftests/powerpc/reg.h (renamed from tools/testing/selftests/powerpc/pmu/ebb/reg.h)18
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore3
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile3
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-fork.c42
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-resched-dscr.c16
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-stack.c4
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tar.c90
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-tmspr.c143
-rw-r--r--tools/testing/selftests/powerpc/utils.h8
-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/seccomp/seccomp_bpf.c38
-rw-r--r--tools/testing/selftests/sigaltstack/Makefile8
-rw-r--r--tools/testing/selftests/sigaltstack/sas.c176
-rw-r--r--tools/testing/selftests/vm/thuge-gen.c2
-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
-rw-r--r--tools/usb/usbip/libsrc/Makefile.am4
-rw-r--r--tools/usb/usbip/libsrc/usbip_common.h3
-rw-r--r--tools/usb/usbip/libsrc/usbip_device_driver.c163
-rw-r--r--tools/usb/usbip/libsrc/usbip_device_driver.h34
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_common.c273
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_common.h104
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_driver.c269
-rw-r--r--tools/usb/usbip/libsrc/usbip_host_driver.h27
-rw-r--r--tools/usb/usbip/src/usbip_attach.c10
-rw-r--r--tools/usb/usbip/src/usbip_list.c96
-rw-r--r--tools/usb/usbip/src/usbip_port.c13
-rw-r--r--tools/usb/usbip/src/usbipd.c42
-rw-r--r--tools/virtio/ringtest/Makefile5
-rw-r--r--tools/virtio/ringtest/main.c2
-rw-r--r--tools/virtio/ringtest/virtio_ring_0_9.c49
-rw-r--r--tools/virtio/ringtest/virtio_ring_inorder.c2
320 files changed, 13366 insertions, 3746 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 60c7e6c8ff17..f10b64d8c674 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -16,6 +16,7 @@ help:
16 @echo ' gpio - GPIO tools' 16 @echo ' gpio - GPIO tools'
17 @echo ' hv - tools used when in Hyper-V clients' 17 @echo ' hv - tools used when in Hyper-V clients'
18 @echo ' iio - IIO tools' 18 @echo ' iio - IIO tools'
19 @echo ' kvm_stat - top-like utility for displaying kvm statistics'
19 @echo ' lguest - a minimal 32-bit x86 hypervisor' 20 @echo ' lguest - a minimal 32-bit x86 hypervisor'
20 @echo ' net - misc networking tools' 21 @echo ' net - misc networking tools'
21 @echo ' perf - Linux performance measurement and analysis tool' 22 @echo ' perf - Linux performance measurement and analysis tool'
@@ -110,10 +111,13 @@ tmon_install:
110freefall_install: 111freefall_install:
111 $(call descend,laptop/$(@:_install=),install) 112 $(call descend,laptop/$(@:_install=),install)
112 113
114kvm_stat_install:
115 $(call descend,kvm/$(@:_install=),install)
116
113install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ 117install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \
114 perf_install selftests_install turbostat_install usb_install \ 118 perf_install selftests_install turbostat_install usb_install \
115 virtio_install vm_install net_install x86_energy_perf_policy_install \ 119 virtio_install vm_install net_install x86_energy_perf_policy_install \
116 tmon_install freefall_install objtool_install 120 tmon_install freefall_install objtool_install kvm_stat_install
117 121
118acpi_clean: 122acpi_clean:
119 $(call descend,power/acpi,clean) 123 $(call descend,power/acpi,clean)
@@ -137,7 +141,8 @@ libsubcmd_clean:
137 $(call descend,lib/subcmd,clean) 141 $(call descend,lib/subcmd,clean)
138 142
139perf_clean: 143perf_clean:
140 $(call descend,$(@:_clean=),clean) 144 $(Q)mkdir -p $(PERF_O) .
145 $(Q)$(MAKE) --no-print-directory -C perf O=$(PERF_O) subdir= clean
141 146
142selftests_clean: 147selftests_clean:
143 $(call descend,testing/$(@:_clean=),clean) 148 $(call descend,testing/$(@:_clean=),clean)
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
index ee566e8bd1cf..27f3583193e6 100644
--- a/tools/build/Makefile.build
+++ b/tools/build/Makefile.build
@@ -58,8 +58,8 @@ quiet_cmd_mkdir = MKDIR $(dir $@)
58quiet_cmd_cc_o_c = CC $@ 58quiet_cmd_cc_o_c = CC $@
59 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< 59 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
60 60
61quiet_cmd_cc_i_c = CPP $@ 61quiet_cmd_cpp_i_c = CPP $@
62 cmd_cc_i_c = $(CC) $(c_flags) -E -o $@ $< 62 cmd_cpp_i_c = $(CC) $(c_flags) -E -o $@ $<
63 63
64quiet_cmd_cc_s_c = AS $@ 64quiet_cmd_cc_s_c = AS $@
65 cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $< 65 cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
@@ -83,11 +83,11 @@ $(OUTPUT)%.o: %.S FORCE
83 83
84$(OUTPUT)%.i: %.c FORCE 84$(OUTPUT)%.i: %.c FORCE
85 $(call rule_mkdir) 85 $(call rule_mkdir)
86 $(call if_changed_dep,cc_i_c) 86 $(call if_changed_dep,cpp_i_c)
87 87
88$(OUTPUT)%.s: %.S FORCE 88$(OUTPUT)%.s: %.S FORCE
89 $(call rule_mkdir) 89 $(call rule_mkdir)
90 $(call if_changed_dep,cc_i_c) 90 $(call if_changed_dep,cpp_i_c)
91 91
92$(OUTPUT)%.s: %.c FORCE 92$(OUTPUT)%.s: %.c FORCE
93 $(call rule_mkdir) 93 $(call rule_mkdir)
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/hv/lsvmbus b/tools/hv/lsvmbus
index 162a3784d80e..e8fecd61871f 100644
--- a/tools/hv/lsvmbus
+++ b/tools/hv/lsvmbus
@@ -35,6 +35,7 @@ vmbus_dev_dict = {
35 '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller', 35 '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller',
36 '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter', 36 '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter',
37 '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter', 37 '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter',
38 '{44c4f61d-4444-4400-9d52-802e27ede19f}' : 'PCI Express pass-through',
38 '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]', 39 '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]',
39 '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]', 40 '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]',
40 '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]', 41 '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]',
diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c
index 01c4f67801e0..2429c78de940 100644
--- a/tools/iio/generic_buffer.c
+++ b/tools/iio/generic_buffer.c
@@ -35,6 +35,15 @@
35#include "iio_utils.h" 35#include "iio_utils.h"
36 36
37/** 37/**
38 * enum autochan - state for the automatic channel enabling mechanism
39 */
40enum autochan {
41 AUTOCHANNELS_DISABLED,
42 AUTOCHANNELS_ENABLED,
43 AUTOCHANNELS_ACTIVE,
44};
45
46/**
38 * size_from_channelarray() - calculate the storage size of a scan 47 * size_from_channelarray() - calculate the storage size of a scan
39 * @channels: the channel info array 48 * @channels: the channel info array
40 * @num_channels: number of channels 49 * @num_channels: number of channels
@@ -191,10 +200,51 @@ void process_scan(char *data,
191 printf("\n"); 200 printf("\n");
192} 201}
193 202
203static int enable_disable_all_channels(char *dev_dir_name, int enable)
204{
205 const struct dirent *ent;
206 char scanelemdir[256];
207 DIR *dp;
208 int ret;
209
210 snprintf(scanelemdir, sizeof(scanelemdir),
211 FORMAT_SCAN_ELEMENTS_DIR, dev_dir_name);
212 scanelemdir[sizeof(scanelemdir)-1] = '\0';
213
214 dp = opendir(scanelemdir);
215 if (!dp) {
216 fprintf(stderr, "Enabling/disabling channels: can't open %s\n",
217 scanelemdir);
218 return -EIO;
219 }
220
221 ret = -ENOENT;
222 while (ent = readdir(dp), ent) {
223 if (iioutils_check_suffix(ent->d_name, "_en")) {
224 printf("%sabling: %s\n",
225 enable ? "En" : "Dis",
226 ent->d_name);
227 ret = write_sysfs_int(ent->d_name, scanelemdir,
228 enable);
229 if (ret < 0)
230 fprintf(stderr, "Failed to enable/disable %s\n",
231 ent->d_name);
232 }
233 }
234
235 if (closedir(dp) == -1) {
236 perror("Enabling/disabling channels: "
237 "Failed to close directory");
238 return -errno;
239 }
240 return 0;
241}
242
194void print_usage(void) 243void print_usage(void)
195{ 244{
196 fprintf(stderr, "Usage: generic_buffer [options]...\n" 245 fprintf(stderr, "Usage: generic_buffer [options]...\n"
197 "Capture, convert and output data from IIO device buffer\n" 246 "Capture, convert and output data from IIO device buffer\n"
247 " -a Auto-activate all available channels\n"
198 " -c <n> Do n conversions\n" 248 " -c <n> Do n conversions\n"
199 " -e Disable wait for event (new data)\n" 249 " -e Disable wait for event (new data)\n"
200 " -g Use trigger-less mode\n" 250 " -g Use trigger-less mode\n"
@@ -225,12 +275,16 @@ int main(int argc, char **argv)
225 int scan_size; 275 int scan_size;
226 int noevents = 0; 276 int noevents = 0;
227 int notrigger = 0; 277 int notrigger = 0;
278 enum autochan autochannels = AUTOCHANNELS_DISABLED;
228 char *dummy; 279 char *dummy;
229 280
230 struct iio_channel_info *channels; 281 struct iio_channel_info *channels;
231 282
232 while ((c = getopt(argc, argv, "c:egl:n:t:w:")) != -1) { 283 while ((c = getopt(argc, argv, "ac:egl:n:t:w:")) != -1) {
233 switch (c) { 284 switch (c) {
285 case 'a':
286 autochannels = AUTOCHANNELS_ENABLED;
287 break;
234 case 'c': 288 case 'c':
235 errno = 0; 289 errno = 0;
236 num_loops = strtoul(optarg, &dummy, 10); 290 num_loops = strtoul(optarg, &dummy, 10);
@@ -304,7 +358,19 @@ int main(int argc, char **argv)
304 } 358 }
305 } 359 }
306 360
307 /* Verify the trigger exists */ 361 /* Look for this "-devN" trigger */
362 trig_num = find_type_by_name(trigger_name, "trigger");
363 if (trig_num < 0) {
364 /* OK try the simpler "-trigger" suffix instead */
365 free(trigger_name);
366 ret = asprintf(&trigger_name,
367 "%s-trigger", device_name);
368 if (ret < 0) {
369 ret = -ENOMEM;
370 goto error_free_dev_dir_name;
371 }
372 }
373
308 trig_num = find_type_by_name(trigger_name, "trigger"); 374 trig_num = find_type_by_name(trigger_name, "trigger");
309 if (trig_num < 0) { 375 if (trig_num < 0) {
310 fprintf(stderr, "Failed to find the trigger %s\n", 376 fprintf(stderr, "Failed to find the trigger %s\n",
@@ -328,12 +394,47 @@ int main(int argc, char **argv)
328 "diag %s\n", dev_dir_name); 394 "diag %s\n", dev_dir_name);
329 goto error_free_triggername; 395 goto error_free_triggername;
330 } 396 }
331 if (!num_channels) { 397 if (num_channels && autochannels == AUTOCHANNELS_ENABLED) {
398 fprintf(stderr, "Auto-channels selected but some channels "
399 "are already activated in sysfs\n");
400 fprintf(stderr, "Proceeding without activating any channels\n");
401 }
402
403 if (!num_channels && autochannels == AUTOCHANNELS_ENABLED) {
404 fprintf(stderr,
405 "No channels are enabled, enabling all channels\n");
406
407 ret = enable_disable_all_channels(dev_dir_name, 1);
408 if (ret) {
409 fprintf(stderr, "Failed to enable all channels\n");
410 goto error_free_triggername;
411 }
412
413 /* This flags that we need to disable the channels again */
414 autochannels = AUTOCHANNELS_ACTIVE;
415
416 ret = build_channel_array(dev_dir_name, &channels,
417 &num_channels);
418 if (ret) {
419 fprintf(stderr, "Problem reading scan element "
420 "information\n"
421 "diag %s\n", dev_dir_name);
422 goto error_disable_channels;
423 }
424 if (!num_channels) {
425 fprintf(stderr, "Still no channels after "
426 "auto-enabling, giving up\n");
427 goto error_disable_channels;
428 }
429 }
430
431 if (!num_channels && autochannels == AUTOCHANNELS_DISABLED) {
332 fprintf(stderr, 432 fprintf(stderr,
333 "No channels are enabled, we have nothing to scan.\n"); 433 "No channels are enabled, we have nothing to scan.\n");
334 fprintf(stderr, "Enable channels manually in " 434 fprintf(stderr, "Enable channels manually in "
335 FORMAT_SCAN_ELEMENTS_DIR 435 FORMAT_SCAN_ELEMENTS_DIR
336 "/*_en and try again.\n", dev_dir_name); 436 "/*_en or pass -a to autoenable channels and "
437 "try again.\n", dev_dir_name);
337 ret = -ENOENT; 438 ret = -ENOENT;
338 goto error_free_triggername; 439 goto error_free_triggername;
339 } 440 }
@@ -467,7 +568,12 @@ error_free_channels:
467error_free_triggername: 568error_free_triggername:
468 if (datardytrigger) 569 if (datardytrigger)
469 free(trigger_name); 570 free(trigger_name);
470 571error_disable_channels:
572 if (autochannels == AUTOCHANNELS_ACTIVE) {
573 ret = enable_disable_all_channels(dev_dir_name, 0);
574 if (ret)
575 fprintf(stderr, "Failed to disable all channels\n");
576 }
471error_free_dev_dir_name: 577error_free_dev_dir_name:
472 free(dev_dir_name); 578 free(dev_dir_name);
473 579
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index d51eb04202e9..d9b7e0f306c6 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -53,6 +53,10 @@ static const char * const iio_chan_type_name_spec[] = {
53 [IIO_ENERGY] = "energy", 53 [IIO_ENERGY] = "energy",
54 [IIO_DISTANCE] = "distance", 54 [IIO_DISTANCE] = "distance",
55 [IIO_VELOCITY] = "velocity", 55 [IIO_VELOCITY] = "velocity",
56 [IIO_CONCENTRATION] = "concentration",
57 [IIO_RESISTANCE] = "resistance",
58 [IIO_PH] = "ph",
59 [IIO_UVINDEX] = "uvindex",
56}; 60};
57 61
58static const char * const iio_ev_type_text[] = { 62static const char * const iio_ev_type_text[] = {
@@ -90,6 +94,7 @@ static const char * const iio_modifier_names[] = {
90 [IIO_MOD_LIGHT_RED] = "red", 94 [IIO_MOD_LIGHT_RED] = "red",
91 [IIO_MOD_LIGHT_GREEN] = "green", 95 [IIO_MOD_LIGHT_GREEN] = "green",
92 [IIO_MOD_LIGHT_BLUE] = "blue", 96 [IIO_MOD_LIGHT_BLUE] = "blue",
97 [IIO_MOD_LIGHT_UV] = "uv",
93 [IIO_MOD_QUATERNION] = "quaternion", 98 [IIO_MOD_QUATERNION] = "quaternion",
94 [IIO_MOD_TEMP_AMBIENT] = "ambient", 99 [IIO_MOD_TEMP_AMBIENT] = "ambient",
95 [IIO_MOD_TEMP_OBJECT] = "object", 100 [IIO_MOD_TEMP_OBJECT] = "object",
@@ -102,6 +107,10 @@ static const char * const iio_modifier_names[] = {
102 [IIO_MOD_WALKING] = "walking", 107 [IIO_MOD_WALKING] = "walking",
103 [IIO_MOD_STILL] = "still", 108 [IIO_MOD_STILL] = "still",
104 [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)", 109 [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
110 [IIO_MOD_I] = "i",
111 [IIO_MOD_Q] = "q",
112 [IIO_MOD_CO2] = "co2",
113 [IIO_MOD_VOC] = "voc",
105}; 114};
106 115
107static bool event_is_known(struct iio_event_data *event) 116static bool event_is_known(struct iio_event_data *event)
@@ -136,6 +145,10 @@ static bool event_is_known(struct iio_event_data *event)
136 case IIO_ENERGY: 145 case IIO_ENERGY:
137 case IIO_DISTANCE: 146 case IIO_DISTANCE:
138 case IIO_VELOCITY: 147 case IIO_VELOCITY:
148 case IIO_CONCENTRATION:
149 case IIO_RESISTANCE:
150 case IIO_PH:
151 case IIO_UVINDEX:
139 break; 152 break;
140 default: 153 default:
141 return false; 154 return false;
@@ -162,6 +175,7 @@ static bool event_is_known(struct iio_event_data *event)
162 case IIO_MOD_LIGHT_RED: 175 case IIO_MOD_LIGHT_RED:
163 case IIO_MOD_LIGHT_GREEN: 176 case IIO_MOD_LIGHT_GREEN:
164 case IIO_MOD_LIGHT_BLUE: 177 case IIO_MOD_LIGHT_BLUE:
178 case IIO_MOD_LIGHT_UV:
165 case IIO_MOD_QUATERNION: 179 case IIO_MOD_QUATERNION:
166 case IIO_MOD_TEMP_AMBIENT: 180 case IIO_MOD_TEMP_AMBIENT:
167 case IIO_MOD_TEMP_OBJECT: 181 case IIO_MOD_TEMP_OBJECT:
@@ -174,6 +188,10 @@ static bool event_is_known(struct iio_event_data *event)
174 case IIO_MOD_WALKING: 188 case IIO_MOD_WALKING:
175 case IIO_MOD_STILL: 189 case IIO_MOD_STILL:
176 case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z: 190 case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z:
191 case IIO_MOD_I:
192 case IIO_MOD_Q:
193 case IIO_MOD_CO2:
194 case IIO_MOD_VOC:
177 break; 195 break;
178 default: 196 default:
179 return false; 197 return false;
diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
index e3503bfe538b..780f2014f8fa 100644
--- a/tools/iio/iio_utils.h
+++ b/tools/iio/iio_utils.h
@@ -52,6 +52,13 @@ struct iio_channel_info {
52 unsigned location; 52 unsigned location;
53}; 53};
54 54
55static inline int iioutils_check_suffix(const char *str, const char *suffix)
56{
57 return strlen(str) >= strlen(suffix) &&
58 strncmp(str+strlen(str)-strlen(suffix),
59 suffix, strlen(suffix)) == 0;
60}
61
55int iioutils_break_up_name(const char *full_name, char **generic_name); 62int iioutils_break_up_name(const char *full_name, char **generic_name);
56int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used, 63int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
57 unsigned *shift, uint64_t *mask, unsigned *be, 64 unsigned *shift, uint64_t *mask, unsigned *be,
diff --git a/tools/kvm/kvm_stat/Makefile b/tools/kvm/kvm_stat/Makefile
new file mode 100644
index 000000000000..5b1cba57e3b3
--- /dev/null
+++ b/tools/kvm/kvm_stat/Makefile
@@ -0,0 +1,41 @@
1include ../../scripts/Makefile.include
2include ../../scripts/utilities.mak
3BINDIR=usr/bin
4MANDIR=usr/share/man
5MAN1DIR=$(MANDIR)/man1
6
7MAN1=kvm_stat.1
8
9A2X=a2x
10a2x_path := $(call get-executable,$(A2X))
11
12all: man
13
14ifneq ($(findstring $(MAKEFLAGS),s),s)
15 ifneq ($(V),1)
16 QUIET_A2X = @echo ' A2X '$@;
17 endif
18endif
19
20%.1: %.txt
21ifeq ($(a2x_path),)
22 $(error "You need to install asciidoc for man pages")
23else
24 $(QUIET_A2X)$(A2X) --doctype manpage --format manpage $<
25endif
26
27clean:
28 rm -f $(MAN1)
29
30man: $(MAN1)
31
32install-man: man
33 install -d -m 755 $(INSTALL_ROOT)/$(MAN1DIR)
34 install -m 644 kvm_stat.1 $(INSTALL_ROOT)/$(MAN1DIR)
35
36install-tools:
37 install -d -m 755 $(INSTALL_ROOT)/$(BINDIR)
38 install -m 755 -p "kvm_stat" "$(INSTALL_ROOT)/$(BINDIR)/$(TARGET)"
39
40install: install-tools install-man
41.PHONY: all clean man install-tools install-man install
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat
new file mode 100755
index 000000000000..581278c58488
--- /dev/null
+++ b/tools/kvm/kvm_stat/kvm_stat
@@ -0,0 +1,1127 @@
1#!/usr/bin/python
2#
3# top-like utility for displaying kvm statistics
4#
5# Copyright 2006-2008 Qumranet Technologies
6# Copyright 2008-2011 Red Hat, Inc.
7#
8# Authors:
9# Avi Kivity <avi@redhat.com>
10#
11# This work is licensed under the terms of the GNU GPL, version 2. See
12# the COPYING file in the top-level directory.
13"""The kvm_stat module outputs statistics about running KVM VMs
14
15Three different ways of output formatting are available:
16- as a top-like text ui
17- in a key -> value format
18- in an all keys, all values format
19
20The data is sampled from the KVM's debugfs entries and its perf events.
21"""
22
23import curses
24import sys
25import os
26import time
27import optparse
28import ctypes
29import fcntl
30import resource
31import struct
32import re
33from collections import defaultdict
34from time import sleep
35
36VMX_EXIT_REASONS = {
37 'EXCEPTION_NMI': 0,
38 'EXTERNAL_INTERRUPT': 1,
39 'TRIPLE_FAULT': 2,
40 'PENDING_INTERRUPT': 7,
41 'NMI_WINDOW': 8,
42 'TASK_SWITCH': 9,
43 'CPUID': 10,
44 'HLT': 12,
45 'INVLPG': 14,
46 'RDPMC': 15,
47 'RDTSC': 16,
48 'VMCALL': 18,
49 'VMCLEAR': 19,
50 'VMLAUNCH': 20,
51 'VMPTRLD': 21,
52 'VMPTRST': 22,
53 'VMREAD': 23,
54 'VMRESUME': 24,
55 'VMWRITE': 25,
56 'VMOFF': 26,
57 'VMON': 27,
58 'CR_ACCESS': 28,
59 'DR_ACCESS': 29,
60 'IO_INSTRUCTION': 30,
61 'MSR_READ': 31,
62 'MSR_WRITE': 32,
63 'INVALID_STATE': 33,
64 'MWAIT_INSTRUCTION': 36,
65 'MONITOR_INSTRUCTION': 39,
66 'PAUSE_INSTRUCTION': 40,
67 'MCE_DURING_VMENTRY': 41,
68 'TPR_BELOW_THRESHOLD': 43,
69 'APIC_ACCESS': 44,
70 'EPT_VIOLATION': 48,
71 'EPT_MISCONFIG': 49,
72 'WBINVD': 54,
73 'XSETBV': 55,
74 'APIC_WRITE': 56,
75 'INVPCID': 58,
76}
77
78SVM_EXIT_REASONS = {
79 'READ_CR0': 0x000,
80 'READ_CR3': 0x003,
81 'READ_CR4': 0x004,
82 'READ_CR8': 0x008,
83 'WRITE_CR0': 0x010,
84 'WRITE_CR3': 0x013,
85 'WRITE_CR4': 0x014,
86 'WRITE_CR8': 0x018,
87 'READ_DR0': 0x020,
88 'READ_DR1': 0x021,
89 'READ_DR2': 0x022,
90 'READ_DR3': 0x023,
91 'READ_DR4': 0x024,
92 'READ_DR5': 0x025,
93 'READ_DR6': 0x026,
94 'READ_DR7': 0x027,
95 'WRITE_DR0': 0x030,
96 'WRITE_DR1': 0x031,
97 'WRITE_DR2': 0x032,
98 'WRITE_DR3': 0x033,
99 'WRITE_DR4': 0x034,
100 'WRITE_DR5': 0x035,
101 'WRITE_DR6': 0x036,
102 'WRITE_DR7': 0x037,
103 'EXCP_BASE': 0x040,
104 'INTR': 0x060,
105 'NMI': 0x061,
106 'SMI': 0x062,
107 'INIT': 0x063,
108 'VINTR': 0x064,
109 'CR0_SEL_WRITE': 0x065,
110 'IDTR_READ': 0x066,
111 'GDTR_READ': 0x067,
112 'LDTR_READ': 0x068,
113 'TR_READ': 0x069,
114 'IDTR_WRITE': 0x06a,
115 'GDTR_WRITE': 0x06b,
116 'LDTR_WRITE': 0x06c,
117 'TR_WRITE': 0x06d,
118 'RDTSC': 0x06e,
119 'RDPMC': 0x06f,
120 'PUSHF': 0x070,
121 'POPF': 0x071,
122 'CPUID': 0x072,
123 'RSM': 0x073,
124 'IRET': 0x074,
125 'SWINT': 0x075,
126 'INVD': 0x076,
127 'PAUSE': 0x077,
128 'HLT': 0x078,
129 'INVLPG': 0x079,
130 'INVLPGA': 0x07a,
131 'IOIO': 0x07b,
132 'MSR': 0x07c,
133 'TASK_SWITCH': 0x07d,
134 'FERR_FREEZE': 0x07e,
135 'SHUTDOWN': 0x07f,
136 'VMRUN': 0x080,
137 'VMMCALL': 0x081,
138 'VMLOAD': 0x082,
139 'VMSAVE': 0x083,
140 'STGI': 0x084,
141 'CLGI': 0x085,
142 'SKINIT': 0x086,
143 'RDTSCP': 0x087,
144 'ICEBP': 0x088,
145 'WBINVD': 0x089,
146 'MONITOR': 0x08a,
147 'MWAIT': 0x08b,
148 'MWAIT_COND': 0x08c,
149 'XSETBV': 0x08d,
150 'NPF': 0x400,
151}
152
153# EC definition of HSR (from arch/arm64/include/asm/kvm_arm.h)
154AARCH64_EXIT_REASONS = {
155 'UNKNOWN': 0x00,
156 'WFI': 0x01,
157 'CP15_32': 0x03,
158 'CP15_64': 0x04,
159 'CP14_MR': 0x05,
160 'CP14_LS': 0x06,
161 'FP_ASIMD': 0x07,
162 'CP10_ID': 0x08,
163 'CP14_64': 0x0C,
164 'ILL_ISS': 0x0E,
165 'SVC32': 0x11,
166 'HVC32': 0x12,
167 'SMC32': 0x13,
168 'SVC64': 0x15,
169 'HVC64': 0x16,
170 'SMC64': 0x17,
171 'SYS64': 0x18,
172 'IABT': 0x20,
173 'IABT_HYP': 0x21,
174 'PC_ALIGN': 0x22,
175 'DABT': 0x24,
176 'DABT_HYP': 0x25,
177 'SP_ALIGN': 0x26,
178 'FP_EXC32': 0x28,
179 'FP_EXC64': 0x2C,
180 'SERROR': 0x2F,
181 'BREAKPT': 0x30,
182 'BREAKPT_HYP': 0x31,
183 'SOFTSTP': 0x32,
184 'SOFTSTP_HYP': 0x33,
185 'WATCHPT': 0x34,
186 'WATCHPT_HYP': 0x35,
187 'BKPT32': 0x38,
188 'VECTOR32': 0x3A,
189 'BRK64': 0x3C,
190}
191
192# From include/uapi/linux/kvm.h, KVM_EXIT_xxx
193USERSPACE_EXIT_REASONS = {
194 'UNKNOWN': 0,
195 'EXCEPTION': 1,
196 'IO': 2,
197 'HYPERCALL': 3,
198 'DEBUG': 4,
199 'HLT': 5,
200 'MMIO': 6,
201 'IRQ_WINDOW_OPEN': 7,
202 'SHUTDOWN': 8,
203 'FAIL_ENTRY': 9,
204 'INTR': 10,
205 'SET_TPR': 11,
206 'TPR_ACCESS': 12,
207 'S390_SIEIC': 13,
208 'S390_RESET': 14,
209 'DCR': 15,
210 'NMI': 16,
211 'INTERNAL_ERROR': 17,
212 'OSI': 18,
213 'PAPR_HCALL': 19,
214 'S390_UCONTROL': 20,
215 'WATCHDOG': 21,
216 'S390_TSCH': 22,
217 'EPR': 23,
218 'SYSTEM_EVENT': 24,
219}
220
221IOCTL_NUMBERS = {
222 'SET_FILTER': 0x40082406,
223 'ENABLE': 0x00002400,
224 'DISABLE': 0x00002401,
225 'RESET': 0x00002403,
226}
227
228class Arch(object):
229 """Encapsulates global architecture specific data.
230
231 Contains the performance event open syscall and ioctl numbers, as
232 well as the VM exit reasons for the architecture it runs on.
233
234 """
235 @staticmethod
236 def get_arch():
237 machine = os.uname()[4]
238
239 if machine.startswith('ppc'):
240 return ArchPPC()
241 elif machine.startswith('aarch64'):
242 return ArchA64()
243 elif machine.startswith('s390'):
244 return ArchS390()
245 else:
246 # X86_64
247 for line in open('/proc/cpuinfo'):
248 if not line.startswith('flags'):
249 continue
250
251 flags = line.split()
252 if 'vmx' in flags:
253 return ArchX86(VMX_EXIT_REASONS)
254 if 'svm' in flags:
255 return ArchX86(SVM_EXIT_REASONS)
256 return
257
258class ArchX86(Arch):
259 def __init__(self, exit_reasons):
260 self.sc_perf_evt_open = 298
261 self.ioctl_numbers = IOCTL_NUMBERS
262 self.exit_reasons = exit_reasons
263
264class ArchPPC(Arch):
265 def __init__(self):
266 self.sc_perf_evt_open = 319
267 self.ioctl_numbers = IOCTL_NUMBERS
268 self.ioctl_numbers['ENABLE'] = 0x20002400
269 self.ioctl_numbers['DISABLE'] = 0x20002401
270 self.ioctl_numbers['RESET'] = 0x20002403
271
272 # PPC comes in 32 and 64 bit and some generated ioctl
273 # numbers depend on the wordsize.
274 char_ptr_size = ctypes.sizeof(ctypes.c_char_p)
275 self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16
276 self.exit_reasons = {}
277
278class ArchA64(Arch):
279 def __init__(self):
280 self.sc_perf_evt_open = 241
281 self.ioctl_numbers = IOCTL_NUMBERS
282 self.exit_reasons = AARCH64_EXIT_REASONS
283
284class ArchS390(Arch):
285 def __init__(self):
286 self.sc_perf_evt_open = 331
287 self.ioctl_numbers = IOCTL_NUMBERS
288 self.exit_reasons = None
289
290ARCH = Arch.get_arch()
291
292
293def walkdir(path):
294 """Returns os.walk() data for specified directory.
295
296 As it is only a wrapper it returns the same 3-tuple of (dirpath,
297 dirnames, filenames).
298 """
299 return next(os.walk(path))
300
301
302def parse_int_list(list_string):
303 """Returns an int list from a string of comma separated integers and
304 integer ranges."""
305 integers = []
306 members = list_string.split(',')
307
308 for member in members:
309 if '-' not in member:
310 integers.append(int(member))
311 else:
312 int_range = member.split('-')
313 integers.extend(range(int(int_range[0]),
314 int(int_range[1]) + 1))
315
316 return integers
317
318
319def get_online_cpus():
320 """Returns a list of cpu id integers."""
321 with open('/sys/devices/system/cpu/online') as cpu_list:
322 cpu_string = cpu_list.readline()
323 return parse_int_list(cpu_string)
324
325
326def get_filters():
327 """Returns a dict of trace events, their filter ids and
328 the values that can be filtered.
329
330 Trace events can be filtered for special values by setting a
331 filter string via an ioctl. The string normally has the format
332 identifier==value. For each filter a new event will be created, to
333 be able to distinguish the events.
334
335 """
336 filters = {}
337 filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS)
338 if ARCH.exit_reasons:
339 filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons)
340 return filters
341
342libc = ctypes.CDLL('libc.so.6', use_errno=True)
343syscall = libc.syscall
344
345class perf_event_attr(ctypes.Structure):
346 """Struct that holds the necessary data to set up a trace event.
347
348 For an extensive explanation see perf_event_open(2) and
349 include/uapi/linux/perf_event.h, struct perf_event_attr
350
351 All fields that are not initialized in the constructor are 0.
352
353 """
354 _fields_ = [('type', ctypes.c_uint32),
355 ('size', ctypes.c_uint32),
356 ('config', ctypes.c_uint64),
357 ('sample_freq', ctypes.c_uint64),
358 ('sample_type', ctypes.c_uint64),
359 ('read_format', ctypes.c_uint64),
360 ('flags', ctypes.c_uint64),
361 ('wakeup_events', ctypes.c_uint32),
362 ('bp_type', ctypes.c_uint32),
363 ('bp_addr', ctypes.c_uint64),
364 ('bp_len', ctypes.c_uint64),
365 ]
366
367 def __init__(self):
368 super(self.__class__, self).__init__()
369 self.type = PERF_TYPE_TRACEPOINT
370 self.size = ctypes.sizeof(self)
371 self.read_format = PERF_FORMAT_GROUP
372
373def perf_event_open(attr, pid, cpu, group_fd, flags):
374 """Wrapper for the sys_perf_evt_open() syscall.
375
376 Used to set up performance events, returns a file descriptor or -1
377 on error.
378
379 Attributes are:
380 - syscall number
381 - struct perf_event_attr *
382 - pid or -1 to monitor all pids
383 - cpu number or -1 to monitor all cpus
384 - The file descriptor of the group leader or -1 to create a group.
385 - flags
386
387 """
388 return syscall(ARCH.sc_perf_evt_open, ctypes.pointer(attr),
389 ctypes.c_int(pid), ctypes.c_int(cpu),
390 ctypes.c_int(group_fd), ctypes.c_long(flags))
391
392PERF_TYPE_TRACEPOINT = 2
393PERF_FORMAT_GROUP = 1 << 3
394
395PATH_DEBUGFS_TRACING = '/sys/kernel/debug/tracing'
396PATH_DEBUGFS_KVM = '/sys/kernel/debug/kvm'
397
398class Group(object):
399 """Represents a perf event group."""
400
401 def __init__(self):
402 self.events = []
403
404 def add_event(self, event):
405 self.events.append(event)
406
407 def read(self):
408 """Returns a dict with 'event name: value' for all events in the
409 group.
410
411 Values are read by reading from the file descriptor of the
412 event that is the group leader. See perf_event_open(2) for
413 details.
414
415 Read format for the used event configuration is:
416 struct read_format {
417 u64 nr; /* The number of events */
418 struct {
419 u64 value; /* The value of the event */
420 } values[nr];
421 };
422
423 """
424 length = 8 * (1 + len(self.events))
425 read_format = 'xxxxxxxx' + 'Q' * len(self.events)
426 return dict(zip([event.name for event in self.events],
427 struct.unpack(read_format,
428 os.read(self.events[0].fd, length))))
429
430class Event(object):
431 """Represents a performance event and manages its life cycle."""
432 def __init__(self, name, group, trace_cpu, trace_pid, trace_point,
433 trace_filter, trace_set='kvm'):
434 self.name = name
435 self.fd = None
436 self.setup_event(group, trace_cpu, trace_pid, trace_point,
437 trace_filter, trace_set)
438
439 def __del__(self):
440 """Closes the event's file descriptor.
441
442 As no python file object was created for the file descriptor,
443 python will not reference count the descriptor and will not
444 close it itself automatically, so we do it.
445
446 """
447 if self.fd:
448 os.close(self.fd)
449
450 def setup_event_attribute(self, trace_set, trace_point):
451 """Returns an initialized ctype perf_event_attr struct."""
452
453 id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', trace_set,
454 trace_point, 'id')
455
456 event_attr = perf_event_attr()
457 event_attr.config = int(open(id_path).read())
458 return event_attr
459
460 def setup_event(self, group, trace_cpu, trace_pid, trace_point,
461 trace_filter, trace_set):
462 """Sets up the perf event in Linux.
463
464 Issues the syscall to register the event in the kernel and
465 then sets the optional filter.
466
467 """
468
469 event_attr = self.setup_event_attribute(trace_set, trace_point)
470
471 # First event will be group leader.
472 group_leader = -1
473
474 # All others have to pass the leader's descriptor instead.
475 if group.events:
476 group_leader = group.events[0].fd
477
478 fd = perf_event_open(event_attr, trace_pid,
479 trace_cpu, group_leader, 0)
480 if fd == -1:
481 err = ctypes.get_errno()
482 raise OSError(err, os.strerror(err),
483 'while calling sys_perf_event_open().')
484
485 if trace_filter:
486 fcntl.ioctl(fd, ARCH.ioctl_numbers['SET_FILTER'],
487 trace_filter)
488
489 self.fd = fd
490
491 def enable(self):
492 """Enables the trace event in the kernel.
493
494 Enabling the group leader makes reading counters from it and the
495 events under it possible.
496
497 """
498 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['ENABLE'], 0)
499
500 def disable(self):
501 """Disables the trace event in the kernel.
502
503 Disabling the group leader makes reading all counters under it
504 impossible.
505
506 """
507 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['DISABLE'], 0)
508
509 def reset(self):
510 """Resets the count of the trace event in the kernel."""
511 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['RESET'], 0)
512
513class TracepointProvider(object):
514 """Data provider for the stats class.
515
516 Manages the events/groups from which it acquires its data.
517
518 """
519 def __init__(self):
520 self.group_leaders = []
521 self.filters = get_filters()
522 self._fields = self.get_available_fields()
523 self._pid = 0
524
525 def get_available_fields(self):
526 """Returns a list of available event's of format 'event name(filter
527 name)'.
528
529 All available events have directories under
530 /sys/kernel/debug/tracing/events/ which export information
531 about the specific event. Therefore, listing the dirs gives us
532 a list of all available events.
533
534 Some events like the vm exit reasons can be filtered for
535 specific values. To take account for that, the routine below
536 creates special fields with the following format:
537 event name(filter name)
538
539 """
540 path = os.path.join(PATH_DEBUGFS_TRACING, 'events', 'kvm')
541 fields = walkdir(path)[1]
542 extra = []
543 for field in fields:
544 if field in self.filters:
545 filter_name_, filter_dicts = self.filters[field]
546 for name in filter_dicts:
547 extra.append(field + '(' + name + ')')
548 fields += extra
549 return fields
550
551 def setup_traces(self):
552 """Creates all event and group objects needed to be able to retrieve
553 data."""
554 if self._pid > 0:
555 # Fetch list of all threads of the monitored pid, as qemu
556 # starts a thread for each vcpu.
557 path = os.path.join('/proc', str(self._pid), 'task')
558 groupids = walkdir(path)[1]
559 else:
560 groupids = get_online_cpus()
561
562 # The constant is needed as a buffer for python libs, std
563 # streams and other files that the script opens.
564 newlim = len(groupids) * len(self._fields) + 50
565 try:
566 softlim_, hardlim = resource.getrlimit(resource.RLIMIT_NOFILE)
567
568 if hardlim < newlim:
569 # Now we need CAP_SYS_RESOURCE, to increase the hard limit.
570 resource.setrlimit(resource.RLIMIT_NOFILE, (newlim, newlim))
571 else:
572 # Raising the soft limit is sufficient.
573 resource.setrlimit(resource.RLIMIT_NOFILE, (newlim, hardlim))
574
575 except ValueError:
576 sys.exit("NOFILE rlimit could not be raised to {0}".format(newlim))
577
578 for groupid in groupids:
579 group = Group()
580 for name in self._fields:
581 tracepoint = name
582 tracefilter = None
583 match = re.match(r'(.*)\((.*)\)', name)
584 if match:
585 tracepoint, sub = match.groups()
586 tracefilter = ('%s==%d\0' %
587 (self.filters[tracepoint][0],
588 self.filters[tracepoint][1][sub]))
589
590 # From perf_event_open(2):
591 # pid > 0 and cpu == -1
592 # This measures the specified process/thread on any CPU.
593 #
594 # pid == -1 and cpu >= 0
595 # This measures all processes/threads on the specified CPU.
596 trace_cpu = groupid if self._pid == 0 else -1
597 trace_pid = int(groupid) if self._pid != 0 else -1
598
599 group.add_event(Event(name=name,
600 group=group,
601 trace_cpu=trace_cpu,
602 trace_pid=trace_pid,
603 trace_point=tracepoint,
604 trace_filter=tracefilter))
605
606 self.group_leaders.append(group)
607
608 def available_fields(self):
609 return self.get_available_fields()
610
611 @property
612 def fields(self):
613 return self._fields
614
615 @fields.setter
616 def fields(self, fields):
617 """Enables/disables the (un)wanted events"""
618 self._fields = fields
619 for group in self.group_leaders:
620 for index, event in enumerate(group.events):
621 if event.name in fields:
622 event.reset()
623 event.enable()
624 else:
625 # Do not disable the group leader.
626 # It would disable all of its events.
627 if index != 0:
628 event.disable()
629
630 @property
631 def pid(self):
632 return self._pid
633
634 @pid.setter
635 def pid(self, pid):
636 """Changes the monitored pid by setting new traces."""
637 self._pid = pid
638 # The garbage collector will get rid of all Event/Group
639 # objects and open files after removing the references.
640 self.group_leaders = []
641 self.setup_traces()
642 self.fields = self._fields
643
644 def read(self):
645 """Returns 'event name: current value' for all enabled events."""
646 ret = defaultdict(int)
647 for group in self.group_leaders:
648 for name, val in group.read().iteritems():
649 if name in self._fields:
650 ret[name] += val
651 return ret
652
653class DebugfsProvider(object):
654 """Provides data from the files that KVM creates in the kvm debugfs
655 folder."""
656 def __init__(self):
657 self._fields = self.get_available_fields()
658 self._pid = 0
659 self.do_read = True
660
661 def get_available_fields(self):
662 """"Returns a list of available fields.
663
664 The fields are all available KVM debugfs files
665
666 """
667 return walkdir(PATH_DEBUGFS_KVM)[2]
668
669 @property
670 def fields(self):
671 return self._fields
672
673 @fields.setter
674 def fields(self, fields):
675 self._fields = fields
676
677 @property
678 def pid(self):
679 return self._pid
680
681 @pid.setter
682 def pid(self, pid):
683 if pid != 0:
684 self._pid = pid
685
686 vms = walkdir(PATH_DEBUGFS_KVM)[1]
687 if len(vms) == 0:
688 self.do_read = False
689
690 self.paths = filter(lambda x: "{}-".format(pid) in x, vms)
691
692 else:
693 self.paths = ['']
694 self.do_read = True
695
696 def read(self):
697 """Returns a dict with format:'file name / field -> current value'."""
698 results = {}
699
700 # If no debugfs filtering support is available, then don't read.
701 if not self.do_read:
702 return results
703
704 for path in self.paths:
705 for field in self._fields:
706 results[field] = results.get(field, 0) \
707 + self.read_field(field, path)
708
709 return results
710
711 def read_field(self, field, path):
712 """Returns the value of a single field from a specific VM."""
713 try:
714 return int(open(os.path.join(PATH_DEBUGFS_KVM,
715 path,
716 field))
717 .read())
718 except IOError:
719 return 0
720
721class Stats(object):
722 """Manages the data providers and the data they provide.
723
724 It is used to set filters on the provider's data and collect all
725 provider data.
726
727 """
728 def __init__(self, providers, pid, fields=None):
729 self.providers = providers
730 self._pid_filter = pid
731 self._fields_filter = fields
732 self.values = {}
733 self.update_provider_pid()
734 self.update_provider_filters()
735
736 def update_provider_filters(self):
737 """Propagates fields filters to providers."""
738 def wanted(key):
739 if not self._fields_filter:
740 return True
741 return re.match(self._fields_filter, key) is not None
742
743 # As we reset the counters when updating the fields we can
744 # also clear the cache of old values.
745 self.values = {}
746 for provider in self.providers:
747 provider_fields = [key for key in provider.get_available_fields()
748 if wanted(key)]
749 provider.fields = provider_fields
750
751 def update_provider_pid(self):
752 """Propagates pid filters to providers."""
753 for provider in self.providers:
754 provider.pid = self._pid_filter
755
756 @property
757 def fields_filter(self):
758 return self._fields_filter
759
760 @fields_filter.setter
761 def fields_filter(self, fields_filter):
762 self._fields_filter = fields_filter
763 self.update_provider_filters()
764
765 @property
766 def pid_filter(self):
767 return self._pid_filter
768
769 @pid_filter.setter
770 def pid_filter(self, pid):
771 self._pid_filter = pid
772 self.values = {}
773 self.update_provider_pid()
774
775 def get(self):
776 """Returns a dict with field -> (value, delta to last value) of all
777 provider data."""
778 for provider in self.providers:
779 new = provider.read()
780 for key in provider.fields:
781 oldval = self.values.get(key, (0, 0))
782 newval = new.get(key, 0)
783 newdelta = None
784 if oldval is not None:
785 newdelta = newval - oldval[0]
786 self.values[key] = (newval, newdelta)
787 return self.values
788
789LABEL_WIDTH = 40
790NUMBER_WIDTH = 10
791
792class Tui(object):
793 """Instruments curses to draw a nice text ui."""
794 def __init__(self, stats):
795 self.stats = stats
796 self.screen = None
797 self.drilldown = False
798 self.update_drilldown()
799
800 def __enter__(self):
801 """Initialises curses for later use. Based on curses.wrapper
802 implementation from the Python standard library."""
803 self.screen = curses.initscr()
804 curses.noecho()
805 curses.cbreak()
806
807 # The try/catch works around a minor bit of
808 # over-conscientiousness in the curses module, the error
809 # return from C start_color() is ignorable.
810 try:
811 curses.start_color()
812 except:
813 pass
814
815 curses.use_default_colors()
816 return self
817
818 def __exit__(self, *exception):
819 """Resets the terminal to its normal state. Based on curses.wrappre
820 implementation from the Python standard library."""
821 if self.screen:
822 self.screen.keypad(0)
823 curses.echo()
824 curses.nocbreak()
825 curses.endwin()
826
827 def update_drilldown(self):
828 """Sets or removes a filter that only allows fields without braces."""
829 if not self.stats.fields_filter:
830 self.stats.fields_filter = r'^[^\(]*$'
831
832 elif self.stats.fields_filter == r'^[^\(]*$':
833 self.stats.fields_filter = None
834
835 def update_pid(self, pid):
836 """Propagates pid selection to stats object."""
837 self.stats.pid_filter = pid
838
839 def refresh(self, sleeptime):
840 """Refreshes on-screen data."""
841 self.screen.erase()
842 if self.stats.pid_filter > 0:
843 self.screen.addstr(0, 0, 'kvm statistics - pid {0}'
844 .format(self.stats.pid_filter),
845 curses.A_BOLD)
846 else:
847 self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD)
848 self.screen.addstr(2, 1, 'Event')
849 self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH -
850 len('Total'), 'Total')
851 self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 8 -
852 len('Current'), 'Current')
853 row = 3
854 stats = self.stats.get()
855 def sortkey(x):
856 if stats[x][1]:
857 return (-stats[x][1], -stats[x][0])
858 else:
859 return (0, -stats[x][0])
860 for key in sorted(stats.keys(), key=sortkey):
861
862 if row >= self.screen.getmaxyx()[0]:
863 break
864 values = stats[key]
865 if not values[0] and not values[1]:
866 break
867 col = 1
868 self.screen.addstr(row, col, key)
869 col += LABEL_WIDTH
870 self.screen.addstr(row, col, '%10d' % (values[0],))
871 col += NUMBER_WIDTH
872 if values[1] is not None:
873 self.screen.addstr(row, col, '%8d' % (values[1] / sleeptime,))
874 row += 1
875 self.screen.refresh()
876
877 def show_filter_selection(self):
878 """Draws filter selection mask.
879
880 Asks for a valid regex and sets the fields filter accordingly.
881
882 """
883 while True:
884 self.screen.erase()
885 self.screen.addstr(0, 0,
886 "Show statistics for events matching a regex.",
887 curses.A_BOLD)
888 self.screen.addstr(2, 0,
889 "Current regex: {0}"
890 .format(self.stats.fields_filter))
891 self.screen.addstr(3, 0, "New regex: ")
892 curses.echo()
893 regex = self.screen.getstr()
894 curses.noecho()
895 if len(regex) == 0:
896 return
897 try:
898 re.compile(regex)
899 self.stats.fields_filter = regex
900 return
901 except re.error:
902 continue
903
904 def show_vm_selection(self):
905 """Draws PID selection mask.
906
907 Asks for a pid until a valid pid or 0 has been entered.
908
909 """
910 while True:
911 self.screen.erase()
912 self.screen.addstr(0, 0,
913 'Show statistics for specific pid.',
914 curses.A_BOLD)
915 self.screen.addstr(1, 0,
916 'This might limit the shown data to the trace '
917 'statistics.')
918
919 curses.echo()
920 self.screen.addstr(3, 0, "Pid [0 or pid]: ")
921 pid = self.screen.getstr()
922 curses.noecho()
923
924 try:
925 pid = int(pid)
926
927 if pid == 0:
928 self.update_pid(pid)
929 break
930 else:
931 if not os.path.isdir(os.path.join('/proc/', str(pid))):
932 continue
933 else:
934 self.update_pid(pid)
935 break
936
937 except ValueError:
938 continue
939
940 def show_stats(self):
941 """Refreshes the screen and processes user input."""
942 sleeptime = 0.25
943 while True:
944 self.refresh(sleeptime)
945 curses.halfdelay(int(sleeptime * 10))
946 sleeptime = 3
947 try:
948 char = self.screen.getkey()
949 if char == 'x':
950 self.drilldown = not self.drilldown
951 self.update_drilldown()
952 if char == 'q':
953 break
954 if char == 'f':
955 self.show_filter_selection()
956 if char == 'p':
957 self.show_vm_selection()
958 except KeyboardInterrupt:
959 break
960 except curses.error:
961 continue
962
963def batch(stats):
964 """Prints statistics in a key, value format."""
965 s = stats.get()
966 time.sleep(1)
967 s = stats.get()
968 for key in sorted(s.keys()):
969 values = s[key]
970 print '%-42s%10d%10d' % (key, values[0], values[1])
971
972def log(stats):
973 """Prints statistics as reiterating key block, multiple value blocks."""
974 keys = sorted(stats.get().iterkeys())
975 def banner():
976 for k in keys:
977 print '%s' % k,
978 print
979 def statline():
980 s = stats.get()
981 for k in keys:
982 print ' %9d' % s[k][1],
983 print
984 line = 0
985 banner_repeat = 20
986 while True:
987 time.sleep(1)
988 if line % banner_repeat == 0:
989 banner()
990 statline()
991 line += 1
992
993def get_options():
994 """Returns processed program arguments."""
995 description_text = """
996This script displays various statistics about VMs running under KVM.
997The statistics are gathered from the KVM debugfs entries and / or the
998currently available perf traces.
999
1000The monitoring takes additional cpu cycles and might affect the VM's
1001performance.
1002
1003Requirements:
1004- Access to:
1005 /sys/kernel/debug/kvm
1006 /sys/kernel/debug/trace/events/*
1007 /proc/pid/task
1008- /proc/sys/kernel/perf_event_paranoid < 1 if user has no
1009 CAP_SYS_ADMIN and perf events are used.
1010- CAP_SYS_RESOURCE if the hard limit is not high enough to allow
1011 the large number of files that are possibly opened.
1012"""
1013
1014 class PlainHelpFormatter(optparse.IndentedHelpFormatter):
1015 def format_description(self, description):
1016 if description:
1017 return description + "\n"
1018 else:
1019 return ""
1020
1021 optparser = optparse.OptionParser(description=description_text,
1022 formatter=PlainHelpFormatter())
1023 optparser.add_option('-1', '--once', '--batch',
1024 action='store_true',
1025 default=False,
1026 dest='once',
1027 help='run in batch mode for one second',
1028 )
1029 optparser.add_option('-l', '--log',
1030 action='store_true',
1031 default=False,
1032 dest='log',
1033 help='run in logging mode (like vmstat)',
1034 )
1035 optparser.add_option('-t', '--tracepoints',
1036 action='store_true',
1037 default=False,
1038 dest='tracepoints',
1039 help='retrieve statistics from tracepoints',
1040 )
1041 optparser.add_option('-d', '--debugfs',
1042 action='store_true',
1043 default=False,
1044 dest='debugfs',
1045 help='retrieve statistics from debugfs',
1046 )
1047 optparser.add_option('-f', '--fields',
1048 action='store',
1049 default=None,
1050 dest='fields',
1051 help='fields to display (regex)',
1052 )
1053 optparser.add_option('-p', '--pid',
1054 action='store',
1055 default=0,
1056 type=int,
1057 dest='pid',
1058 help='restrict statistics to pid',
1059 )
1060 (options, _) = optparser.parse_args(sys.argv)
1061 return options
1062
1063def get_providers(options):
1064 """Returns a list of data providers depending on the passed options."""
1065 providers = []
1066
1067 if options.tracepoints:
1068 providers.append(TracepointProvider())
1069 if options.debugfs:
1070 providers.append(DebugfsProvider())
1071 if len(providers) == 0:
1072 providers.append(TracepointProvider())
1073
1074 return providers
1075
1076def check_access(options):
1077 """Exits if the current user can't access all needed directories."""
1078 if not os.path.exists('/sys/kernel/debug'):
1079 sys.stderr.write('Please enable CONFIG_DEBUG_FS in your kernel.')
1080 sys.exit(1)
1081
1082 if not os.path.exists(PATH_DEBUGFS_KVM):
1083 sys.stderr.write("Please make sure, that debugfs is mounted and "
1084 "readable by the current user:\n"
1085 "('mount -t debugfs debugfs /sys/kernel/debug')\n"
1086 "Also ensure, that the kvm modules are loaded.\n")
1087 sys.exit(1)
1088
1089 if not os.path.exists(PATH_DEBUGFS_TRACING) and (options.tracepoints
1090 or not options.debugfs):
1091 sys.stderr.write("Please enable CONFIG_TRACING in your kernel "
1092 "when using the option -t (default).\n"
1093 "If it is enabled, make {0} readable by the "
1094 "current user.\n"
1095 .format(PATH_DEBUGFS_TRACING))
1096 if options.tracepoints:
1097 sys.exit(1)
1098
1099 sys.stderr.write("Falling back to debugfs statistics!\n")
1100 options.debugfs = True
1101 sleep(5)
1102
1103 return options
1104
1105def main():
1106 options = get_options()
1107 options = check_access(options)
1108
1109 if (options.pid > 0 and
1110 not os.path.isdir(os.path.join('/proc/',
1111 str(options.pid)))):
1112 sys.stderr.write('Did you use a (unsupported) tid instead of a pid?\n')
1113 sys.exit('Specified pid does not exist.')
1114
1115 providers = get_providers(options)
1116 stats = Stats(providers, options.pid, fields=options.fields)
1117
1118 if options.log:
1119 log(stats)
1120 elif not options.once:
1121 with Tui(stats) as tui:
1122 tui.show_stats()
1123 else:
1124 batch(stats)
1125
1126if __name__ == "__main__":
1127 main()
diff --git a/tools/kvm/kvm_stat/kvm_stat.txt b/tools/kvm/kvm_stat/kvm_stat.txt
new file mode 100644
index 000000000000..b92a153d7115
--- /dev/null
+++ b/tools/kvm/kvm_stat/kvm_stat.txt
@@ -0,0 +1,63 @@
1kvm_stat(1)
2===========
3
4NAME
5----
6kvm_stat - Report KVM kernel module event counters
7
8SYNOPSIS
9--------
10[verse]
11'kvm_stat' [OPTION]...
12
13DESCRIPTION
14-----------
15kvm_stat prints counts of KVM kernel module trace events. These events signify
16state transitions such as guest mode entry and exit.
17
18This tool is useful for observing guest behavior from the host perspective.
19Often conclusions about performance or buggy behavior can be drawn from the
20output.
21
22The set of KVM kernel module trace events may be specific to the kernel version
23or architecture. It is best to check the KVM kernel module source code for the
24meaning of events.
25
26OPTIONS
27-------
28-1::
29--once::
30--batch::
31 run in batch mode for one second
32
33-l::
34--log::
35 run in logging mode (like vmstat)
36
37-t::
38--tracepoints::
39 retrieve statistics from tracepoints
40
41-d::
42--debugfs::
43 retrieve statistics from debugfs
44
45-p<pid>::
46--pid=<pid>::
47 limit statistics to one virtual machine (pid)
48
49-f<fields>::
50--fields=<fields>::
51 fields to display (regex)
52
53-h::
54--help::
55 show help message
56
57SEE ALSO
58--------
59'perf'(1), 'trace-cmd'(1)
60
61AUTHOR
62------
63Stefan Hajnoczi <stefanha@redhat.com>
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/Makefile b/tools/objtool/Makefile
index 6765c7e949f3..f094f3c4ed84 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -30,6 +30,10 @@ INCLUDES := -I$(srctree)/tools/include
30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) 30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES)
31LDFLAGS += -lelf $(LIBSUBCMD) 31LDFLAGS += -lelf $(LIBSUBCMD)
32 32
33# Allow old libelf to be used:
34elfshdr := $(shell echo '\#include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | grep elf_getshdr)
35CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
36
33AWK = awk 37AWK = awk
34export srctree OUTPUT CFLAGS ARCH AWK 38export srctree OUTPUT CFLAGS ARCH AWK
35include $(srctree)/tools/build/Makefile.include 39include $(srctree)/tools/build/Makefile.include
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index 7f3e00a2f907..aa1ff6596684 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -23,6 +23,11 @@
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/hashtable.h> 24#include <linux/hashtable.h>
25 25
26#ifdef LIBELF_USE_DEPRECATED
27# define elf_getshdrnum elf_getshnum
28# define elf_getshdrstrndx elf_getshstrndx
29#endif
30
26struct section { 31struct section {
27 struct list_head list; 32 struct list_head list;
28 GElf_Shdr sh; 33 GElf_Shdr sh;
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..9cbddc290aff 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -103,12 +103,13 @@ OPTIONS
103 103
104 If --branch-stack option is used, following sort keys are also 104 If --branch-stack option is used, following sort keys are also
105 available: 105 available:
106 dso_from, dso_to, symbol_from, symbol_to, mispredict.
107 106
108 - dso_from: name of library or module branched from 107 - dso_from: name of library or module branched from
109 - dso_to: name of library or module branched to 108 - dso_to: name of library or module branched to
110 - symbol_from: name of function branched from 109 - symbol_from: name of function branched from
111 - symbol_to: name of function branched to 110 - symbol_to: name of function branched to
111 - srcline_from: source file and line branched from
112 - srcline_to: source file and line branched to
112 - mispredict: "N" for predicted branch, "Y" for mispredicted branch 113 - mispredict: "N" for predicted branch, "Y" for mispredicted branch
113 - in_tx: branch in TSX transaction 114 - in_tx: branch in TSX transaction
114 - abort: TSX transaction abort. 115 - abort: TSX transaction abort.
@@ -285,7 +286,7 @@ OPTIONS
285 286
286-f:: 287-f::
287--force:: 288--force::
288 Don't complain, do it. 289 Don't do ownership validation.
289 290
290--symfs=<directory>:: 291--symfs=<directory>::
291 Look for files with symbols relative to this directory. 292 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..4fc44c75263f 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: 127
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..1ab0782369b1 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -117,9 +117,42 @@ 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 for
147 live sessions (without --input/-i), 127 otherwise.
148
149--min-stack::
150 Set the stack depth limit when parsing the callchain, anything
151 below the specified depth will be ignored. Disabled by default.
152
153 Implies '--call-graph dwarf' when --call-graph not present on the
154 command line, on systems where DWARF unwinding was built in.
155
123--proc-map-timeout:: 156--proc-map-timeout::
124 When processing pre-existing threads /proc/XXX/mmap, it may take a long time, 157 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. 158 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/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
new file mode 100644
index 000000000000..75de0e92e71e
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -0,0 +1,69 @@
1#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H
3
4#include <stdlib.h>
5#include <linux/types.h>
6#include <asm/perf_regs.h>
7
8#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_POWERPC_MAX
10#ifdef __powerpc64__
11 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
12#else
13 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
14#endif
15
16#define PERF_REG_IP PERF_REG_POWERPC_NIP
17#define PERF_REG_SP PERF_REG_POWERPC_R1
18
19static const char *reg_names[] = {
20 [PERF_REG_POWERPC_R0] = "r0",
21 [PERF_REG_POWERPC_R1] = "r1",
22 [PERF_REG_POWERPC_R2] = "r2",
23 [PERF_REG_POWERPC_R3] = "r3",
24 [PERF_REG_POWERPC_R4] = "r4",
25 [PERF_REG_POWERPC_R5] = "r5",
26 [PERF_REG_POWERPC_R6] = "r6",
27 [PERF_REG_POWERPC_R7] = "r7",
28 [PERF_REG_POWERPC_R8] = "r8",
29 [PERF_REG_POWERPC_R9] = "r9",
30 [PERF_REG_POWERPC_R10] = "r10",
31 [PERF_REG_POWERPC_R11] = "r11",
32 [PERF_REG_POWERPC_R12] = "r12",
33 [PERF_REG_POWERPC_R13] = "r13",
34 [PERF_REG_POWERPC_R14] = "r14",
35 [PERF_REG_POWERPC_R15] = "r15",
36 [PERF_REG_POWERPC_R16] = "r16",
37 [PERF_REG_POWERPC_R17] = "r17",
38 [PERF_REG_POWERPC_R18] = "r18",
39 [PERF_REG_POWERPC_R19] = "r19",
40 [PERF_REG_POWERPC_R20] = "r20",
41 [PERF_REG_POWERPC_R21] = "r21",
42 [PERF_REG_POWERPC_R22] = "r22",
43 [PERF_REG_POWERPC_R23] = "r23",
44 [PERF_REG_POWERPC_R24] = "r24",
45 [PERF_REG_POWERPC_R25] = "r25",
46 [PERF_REG_POWERPC_R26] = "r26",
47 [PERF_REG_POWERPC_R27] = "r27",
48 [PERF_REG_POWERPC_R28] = "r28",
49 [PERF_REG_POWERPC_R29] = "r29",
50 [PERF_REG_POWERPC_R30] = "r30",
51 [PERF_REG_POWERPC_R31] = "r31",
52 [PERF_REG_POWERPC_NIP] = "nip",
53 [PERF_REG_POWERPC_MSR] = "msr",
54 [PERF_REG_POWERPC_ORIG_R3] = "orig_r3",
55 [PERF_REG_POWERPC_CTR] = "ctr",
56 [PERF_REG_POWERPC_LINK] = "link",
57 [PERF_REG_POWERPC_XER] = "xer",
58 [PERF_REG_POWERPC_CCR] = "ccr",
59 [PERF_REG_POWERPC_SOFTE] = "softe",
60 [PERF_REG_POWERPC_TRAP] = "trap",
61 [PERF_REG_POWERPC_DAR] = "dar",
62 [PERF_REG_POWERPC_DSISR] = "dsisr"
63};
64
65static inline const char *perf_reg_name(int id)
66{
67 return reg_names[id];
68}
69#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
index c8fe2074d217..90ad64b231cd 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -1,6 +1,8 @@
1libperf-y += header.o 1libperf-y += header.o
2libperf-y += sym-handling.o 2libperf-y += sym-handling.o
3libperf-y += kvm-stat.o 3libperf-y += kvm-stat.o
4libperf-y += perf_regs.o
4 5
5libperf-$(CONFIG_DWARF) += dwarf-regs.o 6libperf-$(CONFIG_DWARF) += dwarf-regs.o
6libperf-$(CONFIG_DWARF) += skip-callchain-idx.o 7libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
8libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
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/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
new file mode 100644
index 000000000000..a3c3e1ce6807
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -0,0 +1,49 @@
1#include "../../perf.h"
2#include "../../util/perf_regs.h"
3
4const struct sample_reg sample_reg_masks[] = {
5 SMPL_REG(r0, PERF_REG_POWERPC_R0),
6 SMPL_REG(r1, PERF_REG_POWERPC_R1),
7 SMPL_REG(r2, PERF_REG_POWERPC_R2),
8 SMPL_REG(r3, PERF_REG_POWERPC_R3),
9 SMPL_REG(r4, PERF_REG_POWERPC_R4),
10 SMPL_REG(r5, PERF_REG_POWERPC_R5),
11 SMPL_REG(r6, PERF_REG_POWERPC_R6),
12 SMPL_REG(r7, PERF_REG_POWERPC_R7),
13 SMPL_REG(r8, PERF_REG_POWERPC_R8),
14 SMPL_REG(r9, PERF_REG_POWERPC_R9),
15 SMPL_REG(r10, PERF_REG_POWERPC_R10),
16 SMPL_REG(r11, PERF_REG_POWERPC_R11),
17 SMPL_REG(r12, PERF_REG_POWERPC_R12),
18 SMPL_REG(r13, PERF_REG_POWERPC_R13),
19 SMPL_REG(r14, PERF_REG_POWERPC_R14),
20 SMPL_REG(r15, PERF_REG_POWERPC_R15),
21 SMPL_REG(r16, PERF_REG_POWERPC_R16),
22 SMPL_REG(r17, PERF_REG_POWERPC_R17),
23 SMPL_REG(r18, PERF_REG_POWERPC_R18),
24 SMPL_REG(r19, PERF_REG_POWERPC_R19),
25 SMPL_REG(r20, PERF_REG_POWERPC_R20),
26 SMPL_REG(r21, PERF_REG_POWERPC_R21),
27 SMPL_REG(r22, PERF_REG_POWERPC_R22),
28 SMPL_REG(r23, PERF_REG_POWERPC_R23),
29 SMPL_REG(r24, PERF_REG_POWERPC_R24),
30 SMPL_REG(r25, PERF_REG_POWERPC_R25),
31 SMPL_REG(r26, PERF_REG_POWERPC_R26),
32 SMPL_REG(r27, PERF_REG_POWERPC_R27),
33 SMPL_REG(r28, PERF_REG_POWERPC_R28),
34 SMPL_REG(r29, PERF_REG_POWERPC_R29),
35 SMPL_REG(r30, PERF_REG_POWERPC_R30),
36 SMPL_REG(r31, PERF_REG_POWERPC_R31),
37 SMPL_REG(nip, PERF_REG_POWERPC_NIP),
38 SMPL_REG(msr, PERF_REG_POWERPC_MSR),
39 SMPL_REG(orig_r3, PERF_REG_POWERPC_ORIG_R3),
40 SMPL_REG(ctr, PERF_REG_POWERPC_CTR),
41 SMPL_REG(link, PERF_REG_POWERPC_LINK),
42 SMPL_REG(xer, PERF_REG_POWERPC_XER),
43 SMPL_REG(ccr, PERF_REG_POWERPC_CCR),
44 SMPL_REG(softe, PERF_REG_POWERPC_SOFTE),
45 SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
46 SMPL_REG(dar, PERF_REG_POWERPC_DAR),
47 SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
48 SMPL_REG_END
49};
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/powerpc/util/unwind-libunwind.c b/tools/perf/arch/powerpc/util/unwind-libunwind.c
new file mode 100644
index 000000000000..9e15f92ae49f
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/unwind-libunwind.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2016 Chandan Kumar, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include <errno.h>
11#include <libunwind.h>
12#include <asm/perf_regs.h>
13#include "../../util/unwind.h"
14#include "../../util/debug.h"
15
16int libunwind__arch_reg_id(int regnum)
17{
18 switch (regnum) {
19 case UNW_PPC64_R0:
20 return PERF_REG_POWERPC_R0;
21 case UNW_PPC64_R1:
22 return PERF_REG_POWERPC_R1;
23 case UNW_PPC64_R2:
24 return PERF_REG_POWERPC_R2;
25 case UNW_PPC64_R3:
26 return PERF_REG_POWERPC_R3;
27 case UNW_PPC64_R4:
28 return PERF_REG_POWERPC_R4;
29 case UNW_PPC64_R5:
30 return PERF_REG_POWERPC_R5;
31 case UNW_PPC64_R6:
32 return PERF_REG_POWERPC_R6;
33 case UNW_PPC64_R7:
34 return PERF_REG_POWERPC_R7;
35 case UNW_PPC64_R8:
36 return PERF_REG_POWERPC_R8;
37 case UNW_PPC64_R9:
38 return PERF_REG_POWERPC_R9;
39 case UNW_PPC64_R10:
40 return PERF_REG_POWERPC_R10;
41 case UNW_PPC64_R11:
42 return PERF_REG_POWERPC_R11;
43 case UNW_PPC64_R12:
44 return PERF_REG_POWERPC_R12;
45 case UNW_PPC64_R13:
46 return PERF_REG_POWERPC_R13;
47 case UNW_PPC64_R14:
48 return PERF_REG_POWERPC_R14;
49 case UNW_PPC64_R15:
50 return PERF_REG_POWERPC_R15;
51 case UNW_PPC64_R16:
52 return PERF_REG_POWERPC_R16;
53 case UNW_PPC64_R17:
54 return PERF_REG_POWERPC_R17;
55 case UNW_PPC64_R18:
56 return PERF_REG_POWERPC_R18;
57 case UNW_PPC64_R19:
58 return PERF_REG_POWERPC_R19;
59 case UNW_PPC64_R20:
60 return PERF_REG_POWERPC_R20;
61 case UNW_PPC64_R21:
62 return PERF_REG_POWERPC_R21;
63 case UNW_PPC64_R22:
64 return PERF_REG_POWERPC_R22;
65 case UNW_PPC64_R23:
66 return PERF_REG_POWERPC_R23;
67 case UNW_PPC64_R24:
68 return PERF_REG_POWERPC_R24;
69 case UNW_PPC64_R25:
70 return PERF_REG_POWERPC_R25;
71 case UNW_PPC64_R26:
72 return PERF_REG_POWERPC_R26;
73 case UNW_PPC64_R27:
74 return PERF_REG_POWERPC_R27;
75 case UNW_PPC64_R28:
76 return PERF_REG_POWERPC_R28;
77 case UNW_PPC64_R29:
78 return PERF_REG_POWERPC_R29;
79 case UNW_PPC64_R30:
80 return PERF_REG_POWERPC_R30;
81 case UNW_PPC64_R31:
82 return PERF_REG_POWERPC_R31;
83 case UNW_PPC64_LR:
84 return PERF_REG_POWERPC_LINK;
85 case UNW_PPC64_CTR:
86 return PERF_REG_POWERPC_CTR;
87 case UNW_PPC64_XER:
88 return PERF_REG_POWERPC_XER;
89 case UNW_PPC64_NIP:
90 return PERF_REG_POWERPC_NIP;
91 default:
92 pr_err("unwind: invalid reg id %d\n", regnum);
93 return -EINVAL;
94 }
95 return -EINVAL;
96}
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-annotate.c b/tools/perf/builtin-annotate.c
index 814158393656..25c81734a950 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -324,8 +324,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
324 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing, 324 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
325 "Skip symbols that cannot be annotated"), 325 "Skip symbols that cannot be annotated"),
326 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"), 326 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
327 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 327 OPT_CALLBACK(0, "symfs", NULL, "directory",
328 "Look for files with symbols relative to this directory"), 328 "Look for files with symbols relative to this directory",
329 symbol__config_symfs),
329 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 330 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
330 "Interleave source code with assembly code (default)"), 331 "Interleave source code with assembly code (default)"),
331 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 332 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 632efc6b79a0..d75bded21fe0 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -119,8 +119,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
119 if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0) 119 if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0)
120 return -1; 120 return -1;
121 121
122 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", 122 scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s",
123 buildid_dir, sbuildid); 123 buildid_dir, DSO__NAME_KCORE, sbuildid);
124 124
125 if (!force && 125 if (!force &&
126 !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { 126 !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
@@ -131,8 +131,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
131 if (build_id_cache__kcore_dir(dir, sizeof(dir))) 131 if (build_id_cache__kcore_dir(dir, sizeof(dir)))
132 return -1; 132 return -1;
133 133
134 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s", 134 scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s/%s",
135 buildid_dir, sbuildid, dir); 135 buildid_dir, DSO__NAME_KCORE, sbuildid, dir);
136 136
137 if (mkdir_p(to_dir, 0755)) 137 if (mkdir_p(to_dir, 0755))
138 return -1; 138 return -1;
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..f7645a42708e 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;
@@ -812,8 +812,9 @@ static const struct option options[] = {
812 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator", 812 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
813 "separator for columns, no spaces will be added between " 813 "separator for columns, no spaces will be added between "
814 "columns '.' is reserved."), 814 "columns '.' is reserved."),
815 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 815 OPT_CALLBACK(0, "symfs", NULL, "directory",
816 "Look for files with symbols relative to this directory"), 816 "Look for files with symbols relative to this directory",
817 symbol__config_symfs),
817 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), 818 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
818 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 819 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
819 "How to display percentage of filtered entries", parse_filter_percentage), 820 "How to display percentage of filtered entries", parse_filter_percentage),
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..dc3fcb597e4c 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -29,15 +29,18 @@
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>
39#include <sched.h> 41#include <sched.h>
40#include <sys/mman.h> 42#include <sys/mman.h>
43#include <asm/bug.h>
41 44
42 45
43struct record { 46struct record {
@@ -55,6 +58,8 @@ struct record {
55 bool no_buildid_cache; 58 bool no_buildid_cache;
56 bool no_buildid_cache_set; 59 bool no_buildid_cache_set;
57 bool buildid_all; 60 bool buildid_all;
61 bool timestamp_filename;
62 bool switch_output;
58 unsigned long long samples; 63 unsigned long long samples;
59}; 64};
60 65
@@ -78,27 +83,87 @@ static int process_synthesized_event(struct perf_tool *tool,
78 return record__write(rec, event, event->header.size); 83 return record__write(rec, event, event->header.size);
79} 84}
80 85
86static int
87backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
88{
89 struct perf_event_header *pheader;
90 u64 evt_head = head;
91 int size = mask + 1;
92
93 pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head);
94 pheader = (struct perf_event_header *)(buf + (head & mask));
95 *start = head;
96 while (true) {
97 if (evt_head - head >= (unsigned int)size) {
98 pr_debug("Finshed reading backward ring buffer: rewind\n");
99 if (evt_head - head > (unsigned int)size)
100 evt_head -= pheader->size;
101 *end = evt_head;
102 return 0;
103 }
104
105 pheader = (struct perf_event_header *)(buf + (evt_head & mask));
106
107 if (pheader->size == 0) {
108 pr_debug("Finshed reading backward ring buffer: get start\n");
109 *end = evt_head;
110 return 0;
111 }
112
113 evt_head += pheader->size;
114 pr_debug3("move evt_head: %"PRIx64"\n", evt_head);
115 }
116 WARN_ONCE(1, "Shouldn't get here\n");
117 return -1;
118}
119
120static int
121rb_find_range(struct perf_evlist *evlist,
122 void *data, int mask, u64 head, u64 old,
123 u64 *start, u64 *end)
124{
125 if (!evlist->backward) {
126 *start = old;
127 *end = head;
128 return 0;
129 }
130
131 return backward_rb_find_range(data, mask, head, start, end);
132}
133
81static int record__mmap_read(struct record *rec, int idx) 134static int record__mmap_read(struct record *rec, int idx)
82{ 135{
83 struct perf_mmap *md = &rec->evlist->mmap[idx]; 136 struct perf_mmap *md = &rec->evlist->mmap[idx];
84 u64 head = perf_mmap__read_head(md); 137 u64 head = perf_mmap__read_head(md);
85 u64 old = md->prev; 138 u64 old = md->prev;
139 u64 end = head, start = old;
86 unsigned char *data = md->base + page_size; 140 unsigned char *data = md->base + page_size;
87 unsigned long size; 141 unsigned long size;
88 void *buf; 142 void *buf;
89 int rc = 0; 143 int rc = 0;
90 144
91 if (old == head) 145 if (rb_find_range(rec->evlist, data, md->mask, head,
146 old, &start, &end))
147 return -1;
148
149 if (start == end)
92 return 0; 150 return 0;
93 151
94 rec->samples++; 152 rec->samples++;
95 153
96 size = head - old; 154 size = end - start;
155 if (size > (unsigned long)(md->mask) + 1) {
156 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
157
158 md->prev = head;
159 perf_evlist__mmap_consume(rec->evlist, idx);
160 return 0;
161 }
97 162
98 if ((old & md->mask) + size != (head & md->mask)) { 163 if ((start & md->mask) + size != (end & md->mask)) {
99 buf = &data[old & md->mask]; 164 buf = &data[start & md->mask];
100 size = md->mask + 1 - (old & md->mask); 165 size = md->mask + 1 - (start & md->mask);
101 old += size; 166 start += size;
102 167
103 if (record__write(rec, buf, size) < 0) { 168 if (record__write(rec, buf, size) < 0) {
104 rc = -1; 169 rc = -1;
@@ -106,16 +171,16 @@ static int record__mmap_read(struct record *rec, int idx)
106 } 171 }
107 } 172 }
108 173
109 buf = &data[old & md->mask]; 174 buf = &data[start & md->mask];
110 size = head - old; 175 size = end - start;
111 old += size; 176 start += size;
112 177
113 if (record__write(rec, buf, size) < 0) { 178 if (record__write(rec, buf, size) < 0) {
114 rc = -1; 179 rc = -1;
115 goto out; 180 goto out;
116 } 181 }
117 182
118 md->prev = old; 183 md->prev = head;
119 perf_evlist__mmap_consume(rec->evlist, idx); 184 perf_evlist__mmap_consume(rec->evlist, idx);
120out: 185out:
121 return rc; 186 return rc;
@@ -124,9 +189,10 @@ out:
124static volatile int done; 189static volatile int done;
125static volatile int signr = -1; 190static volatile int signr = -1;
126static volatile int child_finished; 191static volatile int child_finished;
127static volatile int auxtrace_snapshot_enabled; 192
128static volatile int auxtrace_snapshot_err;
129static volatile int auxtrace_record__snapshot_started; 193static volatile int auxtrace_record__snapshot_started;
194static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
195static DEFINE_TRIGGER(switch_output_trigger);
130 196
131static void sig_handler(int sig) 197static void sig_handler(int sig)
132{ 198{
@@ -244,11 +310,12 @@ static void record__read_auxtrace_snapshot(struct record *rec)
244{ 310{
245 pr_debug("Recording AUX area tracing snapshot\n"); 311 pr_debug("Recording AUX area tracing snapshot\n");
246 if (record__auxtrace_read_snapshot_all(rec) < 0) { 312 if (record__auxtrace_read_snapshot_all(rec) < 0) {
247 auxtrace_snapshot_err = -1; 313 trigger_error(&auxtrace_snapshot_trigger);
248 } else { 314 } else {
249 auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 315 if (auxtrace_record__snapshot_finish(rec->itr))
250 if (!auxtrace_snapshot_err) 316 trigger_error(&auxtrace_snapshot_trigger);
251 auxtrace_snapshot_enabled = 1; 317 else
318 trigger_ready(&auxtrace_snapshot_trigger);
252 } 319 }
253} 320}
254 321
@@ -283,7 +350,7 @@ static int record__open(struct record *rec)
283 struct record_opts *opts = &rec->opts; 350 struct record_opts *opts = &rec->opts;
284 int rc = 0; 351 int rc = 0;
285 352
286 perf_evlist__config(evlist, opts); 353 perf_evlist__config(evlist, opts, &callchain_param);
287 354
288 evlist__for_each(evlist, pos) { 355 evlist__for_each(evlist, pos) {
289try_again: 356try_again:
@@ -494,6 +561,73 @@ record__finish_output(struct record *rec)
494 return; 561 return;
495} 562}
496 563
564static int record__synthesize_workload(struct record *rec)
565{
566 struct {
567 struct thread_map map;
568 struct thread_map_data map_data;
569 } thread_map;
570
571 thread_map.map.nr = 1;
572 thread_map.map.map[0].pid = rec->evlist->workload.pid;
573 thread_map.map.map[0].comm = NULL;
574 return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map,
575 process_synthesized_event,
576 &rec->session->machines.host,
577 rec->opts.sample_address,
578 rec->opts.proc_map_timeout);
579}
580
581static int record__synthesize(struct record *rec);
582
583static int
584record__switch_output(struct record *rec, bool at_exit)
585{
586 struct perf_data_file *file = &rec->file;
587 int fd, err;
588
589 /* Same Size: "2015122520103046"*/
590 char timestamp[] = "InvalidTimestamp";
591
592 rec->samples = 0;
593 record__finish_output(rec);
594 err = fetch_current_timestamp(timestamp, sizeof(timestamp));
595 if (err) {
596 pr_err("Failed to get current timestamp\n");
597 return -EINVAL;
598 }
599
600 fd = perf_data_file__switch(file, timestamp,
601 rec->session->header.data_offset,
602 at_exit);
603 if (fd >= 0 && !at_exit) {
604 rec->bytes_written = 0;
605 rec->session->header.data_size = 0;
606 }
607
608 if (!quiet)
609 fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
610 file->path, timestamp);
611
612 /* Output tracking events */
613 if (!at_exit) {
614 record__synthesize(rec);
615
616 /*
617 * In 'perf record --switch-output' without -a,
618 * record__synthesize() in record__switch_output() won't
619 * generate tracking events because there's no thread_map
620 * in evlist. Which causes newly created perf.data doesn't
621 * contain map and comm information.
622 * Create a fake thread_map and directly call
623 * perf_event__synthesize_thread_map() for those events.
624 */
625 if (target__none(&rec->opts.target))
626 record__synthesize_workload(rec);
627 }
628 return fd;
629}
630
497static volatile int workload_exec_errno; 631static volatile int workload_exec_errno;
498 632
499/* 633/*
@@ -512,6 +646,15 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
512 646
513static void snapshot_sig_handler(int sig); 647static void snapshot_sig_handler(int sig);
514 648
649int __weak
650perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
651 struct perf_tool *tool __maybe_unused,
652 perf_event__handler_t process __maybe_unused,
653 struct machine *machine __maybe_unused)
654{
655 return 0;
656}
657
515static int record__synthesize(struct record *rec) 658static int record__synthesize(struct record *rec)
516{ 659{
517 struct perf_session *session = rec->session; 660 struct perf_session *session = rec->session;
@@ -549,6 +692,11 @@ static int record__synthesize(struct record *rec)
549 } 692 }
550 } 693 }
551 694
695 err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool,
696 process_synthesized_event, machine);
697 if (err)
698 goto out;
699
552 if (rec->opts.full_auxtrace) { 700 if (rec->opts.full_auxtrace) {
553 err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 701 err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
554 session, process_synthesized_event); 702 session, process_synthesized_event);
@@ -600,10 +748,16 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
600 signal(SIGCHLD, sig_handler); 748 signal(SIGCHLD, sig_handler);
601 signal(SIGINT, sig_handler); 749 signal(SIGINT, sig_handler);
602 signal(SIGTERM, sig_handler); 750 signal(SIGTERM, sig_handler);
603 if (rec->opts.auxtrace_snapshot_mode) 751
752 if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
604 signal(SIGUSR2, snapshot_sig_handler); 753 signal(SIGUSR2, snapshot_sig_handler);
605 else 754 if (rec->opts.auxtrace_snapshot_mode)
755 trigger_on(&auxtrace_snapshot_trigger);
756 if (rec->switch_output)
757 trigger_on(&switch_output_trigger);
758 } else {
606 signal(SIGUSR2, SIG_IGN); 759 signal(SIGUSR2, SIG_IGN);
760 }
607 761
608 session = perf_session__new(file, false, tool); 762 session = perf_session__new(file, false, tool);
609 if (session == NULL) { 763 if (session == NULL) {
@@ -729,27 +883,45 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
729 perf_evlist__enable(rec->evlist); 883 perf_evlist__enable(rec->evlist);
730 } 884 }
731 885
732 auxtrace_snapshot_enabled = 1; 886 trigger_ready(&auxtrace_snapshot_trigger);
887 trigger_ready(&switch_output_trigger);
733 for (;;) { 888 for (;;) {
734 unsigned long long hits = rec->samples; 889 unsigned long long hits = rec->samples;
735 890
736 if (record__mmap_read_all(rec) < 0) { 891 if (record__mmap_read_all(rec) < 0) {
737 auxtrace_snapshot_enabled = 0; 892 trigger_error(&auxtrace_snapshot_trigger);
893 trigger_error(&switch_output_trigger);
738 err = -1; 894 err = -1;
739 goto out_child; 895 goto out_child;
740 } 896 }
741 897
742 if (auxtrace_record__snapshot_started) { 898 if (auxtrace_record__snapshot_started) {
743 auxtrace_record__snapshot_started = 0; 899 auxtrace_record__snapshot_started = 0;
744 if (!auxtrace_snapshot_err) 900 if (!trigger_is_error(&auxtrace_snapshot_trigger))
745 record__read_auxtrace_snapshot(rec); 901 record__read_auxtrace_snapshot(rec);
746 if (auxtrace_snapshot_err) { 902 if (trigger_is_error(&auxtrace_snapshot_trigger)) {
747 pr_err("AUX area tracing snapshot failed\n"); 903 pr_err("AUX area tracing snapshot failed\n");
748 err = -1; 904 err = -1;
749 goto out_child; 905 goto out_child;
750 } 906 }
751 } 907 }
752 908
909 if (trigger_is_hit(&switch_output_trigger)) {
910 trigger_ready(&switch_output_trigger);
911
912 if (!quiet)
913 fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
914 waking);
915 waking = 0;
916 fd = record__switch_output(rec, false);
917 if (fd < 0) {
918 pr_err("Failed to switch to new file\n");
919 trigger_error(&switch_output_trigger);
920 err = fd;
921 goto out_child;
922 }
923 }
924
753 if (hits == rec->samples) { 925 if (hits == rec->samples) {
754 if (done || draining) 926 if (done || draining)
755 break; 927 break;
@@ -772,12 +944,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
772 * disable events in this case. 944 * disable events in this case.
773 */ 945 */
774 if (done && !disabled && !target__none(&opts->target)) { 946 if (done && !disabled && !target__none(&opts->target)) {
775 auxtrace_snapshot_enabled = 0; 947 trigger_off(&auxtrace_snapshot_trigger);
776 perf_evlist__disable(rec->evlist); 948 perf_evlist__disable(rec->evlist);
777 disabled = true; 949 disabled = true;
778 } 950 }
779 } 951 }
780 auxtrace_snapshot_enabled = 0; 952 trigger_off(&auxtrace_snapshot_trigger);
953 trigger_off(&switch_output_trigger);
781 954
782 if (forks && workload_exec_errno) { 955 if (forks && workload_exec_errno) {
783 char msg[STRERR_BUFSIZE]; 956 char msg[STRERR_BUFSIZE];
@@ -811,11 +984,22 @@ out_child:
811 /* this will be recalculated during process_buildids() */ 984 /* this will be recalculated during process_buildids() */
812 rec->samples = 0; 985 rec->samples = 0;
813 986
814 if (!err) 987 if (!err) {
815 record__finish_output(rec); 988 if (!rec->timestamp_filename) {
989 record__finish_output(rec);
990 } else {
991 fd = record__switch_output(rec, true);
992 if (fd < 0) {
993 status = fd;
994 goto out_delete_session;
995 }
996 }
997 }
816 998
817 if (!err && !quiet) { 999 if (!err && !quiet) {
818 char samples[128]; 1000 char samples[128];
1001 const char *postfix = rec->timestamp_filename ?
1002 ".<timestamp>" : "";
819 1003
820 if (rec->samples && !rec->opts.full_auxtrace) 1004 if (rec->samples && !rec->opts.full_auxtrace)
821 scnprintf(samples, sizeof(samples), 1005 scnprintf(samples, sizeof(samples),
@@ -823,9 +1007,9 @@ out_child:
823 else 1007 else
824 samples[0] = '\0'; 1008 samples[0] = '\0';
825 1009
826 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 1010 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
827 perf_data_file__size(file) / 1024.0 / 1024.0, 1011 perf_data_file__size(file) / 1024.0 / 1024.0,
828 file->path, samples); 1012 file->path, postfix, samples);
829 } 1013 }
830 1014
831out_delete_session: 1015out_delete_session:
@@ -833,58 +1017,61 @@ out_delete_session:
833 return status; 1017 return status;
834} 1018}
835 1019
836static void callchain_debug(void) 1020static void callchain_debug(struct callchain_param *callchain)
837{ 1021{
838 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 1022 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
839 1023
840 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 1024 pr_debug("callchain: type %s\n", str[callchain->record_mode]);
841 1025
842 if (callchain_param.record_mode == CALLCHAIN_DWARF) 1026 if (callchain->record_mode == CALLCHAIN_DWARF)
843 pr_debug("callchain: stack dump size %d\n", 1027 pr_debug("callchain: stack dump size %d\n",
844 callchain_param.dump_size); 1028 callchain->dump_size);
845} 1029}
846 1030
847int record_parse_callchain_opt(const struct option *opt, 1031int record_opts__parse_callchain(struct record_opts *record,
848 const char *arg, 1032 struct callchain_param *callchain,
849 int unset) 1033 const char *arg, bool unset)
850{ 1034{
851 int ret; 1035 int ret;
852 struct record_opts *record = (struct record_opts *)opt->value; 1036 callchain->enabled = !unset;
853
854 record->callgraph_set = true;
855 callchain_param.enabled = !unset;
856 1037
857 /* --no-call-graph */ 1038 /* --no-call-graph */
858 if (unset) { 1039 if (unset) {
859 callchain_param.record_mode = CALLCHAIN_NONE; 1040 callchain->record_mode = CALLCHAIN_NONE;
860 pr_debug("callchain: disabled\n"); 1041 pr_debug("callchain: disabled\n");
861 return 0; 1042 return 0;
862 } 1043 }
863 1044
864 ret = parse_callchain_record_opt(arg, &callchain_param); 1045 ret = parse_callchain_record_opt(arg, callchain);
865 if (!ret) { 1046 if (!ret) {
866 /* Enable data address sampling for DWARF unwind. */ 1047 /* Enable data address sampling for DWARF unwind. */
867 if (callchain_param.record_mode == CALLCHAIN_DWARF) 1048 if (callchain->record_mode == CALLCHAIN_DWARF)
868 record->sample_address = true; 1049 record->sample_address = true;
869 callchain_debug(); 1050 callchain_debug(callchain);
870 } 1051 }
871 1052
872 return ret; 1053 return ret;
873} 1054}
874 1055
1056int record_parse_callchain_opt(const struct option *opt,
1057 const char *arg,
1058 int unset)
1059{
1060 return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
1061}
1062
875int record_callchain_opt(const struct option *opt, 1063int record_callchain_opt(const struct option *opt,
876 const char *arg __maybe_unused, 1064 const char *arg __maybe_unused,
877 int unset __maybe_unused) 1065 int unset __maybe_unused)
878{ 1066{
879 struct record_opts *record = (struct record_opts *)opt->value; 1067 struct callchain_param *callchain = opt->value;
880 1068
881 record->callgraph_set = true; 1069 callchain->enabled = true;
882 callchain_param.enabled = true;
883 1070
884 if (callchain_param.record_mode == CALLCHAIN_NONE) 1071 if (callchain->record_mode == CALLCHAIN_NONE)
885 callchain_param.record_mode = CALLCHAIN_FP; 1072 callchain->record_mode = CALLCHAIN_FP;
886 1073
887 callchain_debug(); 1074 callchain_debug(callchain);
888 return 0; 1075 return 0;
889} 1076}
890 1077
@@ -1122,7 +1309,7 @@ struct option __record_options[] = {
1122 record__parse_mmap_pages), 1309 record__parse_mmap_pages),
1123 OPT_BOOLEAN(0, "group", &record.opts.group, 1310 OPT_BOOLEAN(0, "group", &record.opts.group,
1124 "put the counters into a counter group"), 1311 "put the counters into a counter group"),
1125 OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 1312 OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
1126 NULL, "enables call-graph recording" , 1313 NULL, "enables call-graph recording" ,
1127 &record_callchain_opt), 1314 &record_callchain_opt),
1128 OPT_CALLBACK(0, "call-graph", &record.opts, 1315 OPT_CALLBACK(0, "call-graph", &record.opts,
@@ -1195,6 +1382,10 @@ struct option __record_options[] = {
1195 "file", "vmlinux pathname"), 1382 "file", "vmlinux pathname"),
1196 OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 1383 OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
1197 "Record build-id of all DSOs regardless of hits"), 1384 "Record build-id of all DSOs regardless of hits"),
1385 OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1386 "append timestamp to output filename"),
1387 OPT_BOOLEAN(0, "switch-output", &record.switch_output,
1388 "Switch output when receive SIGUSR2"),
1198 OPT_END() 1389 OPT_END()
1199}; 1390};
1200 1391
@@ -1250,6 +1441,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1250 return -EINVAL; 1441 return -EINVAL;
1251 } 1442 }
1252 1443
1444 if (rec->switch_output)
1445 rec->timestamp_filename = true;
1446
1253 if (!rec->itr) { 1447 if (!rec->itr) {
1254 rec->itr = auxtrace_record__init(rec->evlist, &err); 1448 rec->itr = auxtrace_record__init(rec->evlist, &err);
1255 if (err) 1449 if (err)
@@ -1261,6 +1455,14 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1261 if (err) 1455 if (err)
1262 return err; 1456 return err;
1263 1457
1458 err = bpf__setup_stdout(rec->evlist);
1459 if (err) {
1460 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1461 pr_err("ERROR: Setup BPF stdout failed: %s\n",
1462 errbuf);
1463 return err;
1464 }
1465
1264 err = -ENOMEM; 1466 err = -ENOMEM;
1265 1467
1266 symbol__init(NULL); 1468 symbol__init(NULL);
@@ -1275,8 +1477,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" 1477"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1276"even with a suitable vmlinux or kallsyms file.\n\n"); 1478"even with a suitable vmlinux or kallsyms file.\n\n");
1277 1479
1278 if (rec->no_buildid_cache || rec->no_buildid) 1480 if (rec->no_buildid_cache || rec->no_buildid) {
1279 disable_buildid_cache(); 1481 disable_buildid_cache();
1482 } else if (rec->switch_output) {
1483 /*
1484 * In 'perf record --switch-output', disable buildid
1485 * generation by default to reduce data file switching
1486 * overhead. Still generate buildid if they are required
1487 * explicitly using
1488 *
1489 * perf record --signal-trigger --no-no-buildid \
1490 * --no-no-buildid-cache
1491 *
1492 * Following code equals to:
1493 *
1494 * if ((rec->no_buildid || !rec->no_buildid_set) &&
1495 * (rec->no_buildid_cache || !rec->no_buildid_cache_set))
1496 * disable_buildid_cache();
1497 */
1498 bool disable = true;
1499
1500 if (rec->no_buildid_set && !rec->no_buildid)
1501 disable = false;
1502 if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
1503 disable = false;
1504 if (disable) {
1505 rec->no_buildid = true;
1506 rec->no_buildid_cache = true;
1507 disable_buildid_cache();
1508 }
1509 }
1280 1510
1281 if (rec->evlist->nr_entries == 0 && 1511 if (rec->evlist->nr_entries == 0 &&
1282 perf_evlist__add_default(rec->evlist) < 0) { 1512 perf_evlist__add_default(rec->evlist) < 0) {
@@ -1335,9 +1565,13 @@ out_symbol_exit:
1335 1565
1336static void snapshot_sig_handler(int sig __maybe_unused) 1566static void snapshot_sig_handler(int sig __maybe_unused)
1337{ 1567{
1338 if (!auxtrace_snapshot_enabled) 1568 if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
1339 return; 1569 trigger_hit(&auxtrace_snapshot_trigger);
1340 auxtrace_snapshot_enabled = 0; 1570 auxtrace_record__snapshot_started = 1;
1341 auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 1571 if (auxtrace_record__snapshot_start(record.itr))
1342 auxtrace_record__snapshot_started = 1; 1572 trigger_error(&auxtrace_snapshot_trigger);
1573 }
1574
1575 if (trigger_is_ready(&switch_output_trigger))
1576 trigger_hit(&switch_output_trigger);
1343} 1577}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 160ea23b45aa..a87cb338bdf1 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
@@ -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",
@@ -769,8 +770,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
769 "columns '.' is reserved."), 770 "columns '.' is reserved."),
770 OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved, 771 OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved,
771 "Only display entries resolved to a symbol"), 772 "Only display entries resolved to a symbol"),
772 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 773 OPT_CALLBACK(0, "symfs", NULL, "directory",
773 "Look for files with symbols relative to this directory"), 774 "Look for files with symbols relative to this directory",
775 symbol__config_symfs),
774 OPT_STRING('C', "cpu", &report.cpu_list, "cpu", 776 OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
775 "list of cpus to profile"), 777 "list of cpus to profile"),
776 OPT_BOOLEAN('I', "show-info", &report.show_full_info, 778 OPT_BOOLEAN('I', "show-info", &report.show_full_info,
@@ -935,7 +937,7 @@ repeat:
935 goto error; 937 goto error;
936 } 938 }
937 939
938 sort__need_collapse = true; 940 perf_hpp_list.need_collapse = true;
939 } 941 }
940 942
941 /* Force tty output for header output and per-thread stat. */ 943 /* 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..e3ce2f34d3ad 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,
@@ -2004,8 +2010,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2004 "file", "kallsyms pathname"), 2010 "file", "kallsyms pathname"),
2005 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain, 2011 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
2006 "When printing symbols do not display call chain"), 2012 "When printing symbols do not display call chain"),
2007 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 2013 OPT_CALLBACK(0, "symfs", NULL, "directory",
2008 "Look for files with symbols relative to this directory"), 2014 "Look for files with symbols relative to this directory",
2015 symbol__config_symfs),
2009 OPT_CALLBACK('F', "fields", NULL, "str", 2016 OPT_CALLBACK('F', "fields", NULL, "str",
2010 "comma separated output fields prepend with 'type:'. " 2017 "comma separated output fields prepend with 'type:'. "
2011 "Valid types: hw,sw,trace,raw. " 2018 "Valid types: hw,sw,trace,raw. "
@@ -2022,6 +2029,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2022 "only consider symbols in these pids"), 2029 "only consider symbols in these pids"),
2023 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]", 2030 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
2024 "only consider symbols in these tids"), 2031 "only consider symbols in these tids"),
2032 OPT_UINTEGER(0, "max-stack", &scripting_max_stack,
2033 "Set the maximum stack depth when parsing the callchain, "
2034 "anything beyond the specified depth will be ignored. "
2035 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
2025 OPT_BOOLEAN('I', "show-info", &show_full_info, 2036 OPT_BOOLEAN('I', "show-info", &show_full_info,
2026 "display extended information from perf.data file"), 2037 "display extended information from perf.data file"),
2027 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 2038 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 1f19f2f999c8..ee7ada78d86f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -66,6 +66,7 @@
66#include <stdlib.h> 66#include <stdlib.h>
67#include <sys/prctl.h> 67#include <sys/prctl.h>
68#include <locale.h> 68#include <locale.h>
69#include <math.h>
69 70
70#define DEFAULT_SEPARATOR " " 71#define DEFAULT_SEPARATOR " "
71#define CNTR_NOT_SUPPORTED "<not supported>" 72#define CNTR_NOT_SUPPORTED "<not supported>"
@@ -298,6 +299,14 @@ static int read_counter(struct perf_evsel *counter)
298 return -1; 299 return -1;
299 } 300 }
300 } 301 }
302
303 if (verbose > 1) {
304 fprintf(stat_config.output,
305 "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
306 perf_evsel__name(counter),
307 cpu,
308 count->val, count->ena, count->run);
309 }
301 } 310 }
302 } 311 }
303 312
@@ -528,6 +537,7 @@ static int __run_perf_stat(int argc, const char **argv)
528 perf_evlist__set_leader(evsel_list); 537 perf_evlist__set_leader(evsel_list);
529 538
530 evlist__for_each(evsel_list, counter) { 539 evlist__for_each(evsel_list, counter) {
540try_again:
531 if (create_perf_stat_counter(counter) < 0) { 541 if (create_perf_stat_counter(counter) < 0) {
532 /* 542 /*
533 * PPC returns ENXIO for HW counters until 2.6.37 543 * PPC returns ENXIO for HW counters until 2.6.37
@@ -544,7 +554,11 @@ static int __run_perf_stat(int argc, const char **argv)
544 if ((counter->leader != counter) || 554 if ((counter->leader != counter) ||
545 !(counter->leader->nr_members > 1)) 555 !(counter->leader->nr_members > 1))
546 continue; 556 continue;
547 } 557 } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
558 if (verbose)
559 ui__warning("%s\n", msg);
560 goto try_again;
561 }
548 562
549 perf_evsel__open_strerror(counter, &target, 563 perf_evsel__open_strerror(counter, &target,
550 errno, msg, sizeof(msg)); 564 errno, msg, sizeof(msg));
@@ -978,12 +992,12 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
978 const char *fmt; 992 const char *fmt;
979 993
980 if (csv_output) { 994 if (csv_output) {
981 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s"; 995 fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
982 } else { 996 } else {
983 if (big_num) 997 if (big_num)
984 fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s"; 998 fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
985 else 999 else
986 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s"; 1000 fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
987 } 1001 }
988 1002
989 aggr_printout(evsel, id, nr); 1003 aggr_printout(evsel, id, nr);
@@ -1896,6 +1910,9 @@ static int add_default_attributes(void)
1896 } 1910 }
1897 1911
1898 if (!evsel_list->nr_entries) { 1912 if (!evsel_list->nr_entries) {
1913 if (target__has_cpu(&target))
1914 default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK;
1915
1899 if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) 1916 if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0)
1900 return -1; 1917 return -1;
1901 if (pmu_have_event("cpu", "stalled-cycles-frontend")) { 1918 if (pmu_have_event("cpu", "stalled-cycles-frontend")) {
@@ -1987,7 +2004,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
1987 union perf_event *event, 2004 union perf_event *event,
1988 struct perf_session *session) 2005 struct perf_session *session)
1989{ 2006{
1990 struct stat_round_event *round = &event->stat_round; 2007 struct stat_round_event *stat_round = &event->stat_round;
1991 struct perf_evsel *counter; 2008 struct perf_evsel *counter;
1992 struct timespec tsh, *ts = NULL; 2009 struct timespec tsh, *ts = NULL;
1993 const char **argv = session->header.env.cmdline_argv; 2010 const char **argv = session->header.env.cmdline_argv;
@@ -1996,12 +2013,12 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
1996 evlist__for_each(evsel_list, counter) 2013 evlist__for_each(evsel_list, counter)
1997 perf_stat_process_counter(&stat_config, counter); 2014 perf_stat_process_counter(&stat_config, counter);
1998 2015
1999 if (round->type == PERF_STAT_ROUND_TYPE__FINAL) 2016 if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL)
2000 update_stats(&walltime_nsecs_stats, round->time); 2017 update_stats(&walltime_nsecs_stats, stat_round->time);
2001 2018
2002 if (stat_config.interval && round->time) { 2019 if (stat_config.interval && stat_round->time) {
2003 tsh.tv_sec = round->time / NSECS_PER_SEC; 2020 tsh.tv_sec = stat_round->time / NSECS_PER_SEC;
2004 tsh.tv_nsec = round->time % NSECS_PER_SEC; 2021 tsh.tv_nsec = stat_round->time % NSECS_PER_SEC;
2005 ts = &tsh; 2022 ts = &tsh;
2006 } 2023 }
2007 2024
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 40cc9bb3506c..733a55422d03 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1945,8 +1945,9 @@ int cmd_timechart(int argc, const char **argv,
1945 OPT_CALLBACK('p', "process", NULL, "process", 1945 OPT_CALLBACK('p', "process", NULL, "process",
1946 "process selector. Pass a pid or process name.", 1946 "process selector. Pass a pid or process name.",
1947 parse_process), 1947 parse_process),
1948 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1948 OPT_CALLBACK(0, "symfs", NULL, "directory",
1949 "Look for files with symbols relative to this directory"), 1949 "Look for files with symbols relative to this directory",
1950 symbol__config_symfs),
1950 OPT_INTEGER('n', "proc-num", &tchart.proc_num, 1951 OPT_INTEGER('n', "proc-num", &tchart.proc_num,
1951 "min. number of tasks to print"), 1952 "min. number of tasks to print"),
1952 OPT_BOOLEAN('t', "topology", &tchart.topology, 1953 OPT_BOOLEAN('t', "topology", &tchart.topology,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 833214979c4f..2a6cc254ad0c 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,
@@ -732,7 +732,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
732 if (machine__resolve(machine, &al, sample) < 0) 732 if (machine__resolve(machine, &al, sample) < 0)
733 return; 733 return;
734 734
735 if (!top->kptr_restrict_warned && 735 if (!machine->kptr_restrict_warned &&
736 symbol_conf.kptr_restrict && 736 symbol_conf.kptr_restrict &&
737 al.cpumode == PERF_RECORD_MISC_KERNEL) { 737 al.cpumode == PERF_RECORD_MISC_KERNEL) {
738 ui__warning( 738 ui__warning(
@@ -743,7 +743,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
743 " modules" : ""); 743 " modules" : "");
744 if (use_browser <= 0) 744 if (use_browser <= 0)
745 sleep(5); 745 sleep(5);
746 top->kptr_restrict_warned = true; 746 machine->kptr_restrict_warned = true;
747 } 747 }
748 748
749 if (al.sym == NULL) { 749 if (al.sym == NULL) {
@@ -759,7 +759,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
759 * --hide-kernel-symbols, even if the user specifies an 759 * --hide-kernel-symbols, even if the user specifies an
760 * invalid --vmlinux ;-) 760 * invalid --vmlinux ;-)
761 */ 761 */
762 if (!top->kptr_restrict_warned && !top->vmlinux_warned && 762 if (!machine->kptr_restrict_warned && !top->vmlinux_warned &&
763 al.map == machine->vmlinux_maps[MAP__FUNCTION] && 763 al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
764 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 764 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
765 if (symbol_conf.vmlinux_name) { 765 if (symbol_conf.vmlinux_name) {
@@ -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..5c50fe70d6b3 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,105 +516,125 @@ 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[] = {
1017 { .name = "access", .errmsg = true, 578 { .name = "access", .errmsg = true,
1018 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ 579 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
1019 [1] = SCA_ACCMODE, /* mode */ }, },
1020 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 580 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
1021 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, 581 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
1022 { .name = "brk", .hexret = true, 582 { .name = "brk", .hexret = true,
1023 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 583 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
1024 { .name = "chdir", .errmsg = true, 584 { .name = "chdir", .errmsg = true, },
1025 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 585 { .name = "chmod", .errmsg = true, },
1026 { .name = "chmod", .errmsg = true, 586 { .name = "chroot", .errmsg = true, },
1027 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1028 { .name = "chroot", .errmsg = true,
1029 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1030 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, 587 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
588 { .name = "clone", .errpid = true, },
1031 { .name = "close", .errmsg = true, 589 { .name = "close", .errmsg = true,
1032 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 590 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
1033 { .name = "connect", .errmsg = true, }, 591 { .name = "connect", .errmsg = true, },
1034 { .name = "creat", .errmsg = true, 592 { .name = "creat", .errmsg = true, },
1035 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 593 { .name = "dup", .errmsg = true, },
1036 { .name = "dup", .errmsg = true, 594 { .name = "dup2", .errmsg = true, },
1037 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 595 { .name = "dup3", .errmsg = true, },
1038 { .name = "dup2", .errmsg = true,
1039 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1040 { .name = "dup3", .errmsg = true,
1041 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1042 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, 596 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
1043 { .name = "eventfd2", .errmsg = true, 597 { .name = "eventfd2", .errmsg = true,
1044 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, 598 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
1045 { .name = "faccessat", .errmsg = true, 599 { .name = "faccessat", .errmsg = true, },
1046 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 600 { .name = "fadvise64", .errmsg = true, },
1047 [1] = SCA_FILENAME, /* filename */ }, }, 601 { .name = "fallocate", .errmsg = true, },
1048 { .name = "fadvise64", .errmsg = true, 602 { .name = "fchdir", .errmsg = true, },
1049 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 603 { .name = "fchmod", .errmsg = true, },
1050 { .name = "fallocate", .errmsg = true,
1051 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1052 { .name = "fchdir", .errmsg = true,
1053 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1054 { .name = "fchmod", .errmsg = true,
1055 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1056 { .name = "fchmodat", .errmsg = true, 604 { .name = "fchmodat", .errmsg = true,
1057 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 605 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1058 [1] = SCA_FILENAME, /* filename */ }, }, 606 { .name = "fchown", .errmsg = true, },
1059 { .name = "fchown", .errmsg = true,
1060 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1061 { .name = "fchownat", .errmsg = true, 607 { .name = "fchownat", .errmsg = true,
1062 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 608 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1063 [1] = SCA_FILENAME, /* filename */ }, },
1064 { .name = "fcntl", .errmsg = true, 609 { .name = "fcntl", .errmsg = true,
1065 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 610 .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
1066 [1] = SCA_STRARRAY, /* cmd */ },
1067 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, 611 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
1068 { .name = "fdatasync", .errmsg = true, 612 { .name = "fdatasync", .errmsg = true, },
1069 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1070 { .name = "flock", .errmsg = true, 613 { .name = "flock", .errmsg = true,
1071 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 614 .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
1072 [1] = SCA_FLOCK, /* cmd */ }, }, 615 { .name = "fsetxattr", .errmsg = true, },
1073 { .name = "fsetxattr", .errmsg = true, 616 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
1074 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 617 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
1075 { .name = "fstat", .errmsg = true, .alias = "newfstat", 618 { .name = "fstatfs", .errmsg = true, },
1076 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 619 { .name = "fsync", .errmsg = true, },
1077 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", 620 { .name = "ftruncate", .errmsg = true, },
1078 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1079 [1] = SCA_FILENAME, /* filename */ }, },
1080 { .name = "fstatfs", .errmsg = true,
1081 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1082 { .name = "fsync", .errmsg = true,
1083 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1084 { .name = "ftruncate", .errmsg = true,
1085 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1086 { .name = "futex", .errmsg = true, 621 { .name = "futex", .errmsg = true,
1087 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, 622 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
1088 { .name = "futimesat", .errmsg = true, 623 { .name = "futimesat", .errmsg = true,
1089 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 624 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1090 [1] = SCA_FILENAME, /* filename */ }, }, 625 { .name = "getdents", .errmsg = true, },
1091 { .name = "getdents", .errmsg = true, 626 { .name = "getdents64", .errmsg = true, },
1092 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1093 { .name = "getdents64", .errmsg = true,
1094 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1095 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 627 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
628 { .name = "getpid", .errpid = true, },
629 { .name = "getpgid", .errpid = true, },
630 { .name = "getppid", .errpid = true, },
631 { .name = "getrandom", .errmsg = true,
632 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
1096 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 633 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1097 { .name = "getxattr", .errmsg = true, 634 { .name = "getxattr", .errmsg = true, },
1098 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 635 { .name = "inotify_add_watch", .errmsg = true, },
1099 { .name = "inotify_add_watch", .errmsg = true,
1100 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
1101 { .name = "ioctl", .errmsg = true, 636 { .name = "ioctl", .errmsg = true,
1102 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 637 .arg_scnprintf = {
1103#if defined(__i386__) || defined(__x86_64__) 638#if defined(__i386__) || defined(__x86_64__)
1104/* 639/*
1105 * FIXME: Make this available to all arches. 640 * FIXME: Make this available to all arches.
@@ -1113,41 +648,28 @@ static struct syscall_fmt {
1113 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), }, 648 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
1114 { .name = "kill", .errmsg = true, 649 { .name = "kill", .errmsg = true,
1115 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 650 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1116 { .name = "lchown", .errmsg = true, 651 { .name = "lchown", .errmsg = true, },
1117 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 652 { .name = "lgetxattr", .errmsg = true, },
1118 { .name = "lgetxattr", .errmsg = true,
1119 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1120 { .name = "linkat", .errmsg = true, 653 { .name = "linkat", .errmsg = true,
1121 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 654 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1122 { .name = "listxattr", .errmsg = true, 655 { .name = "listxattr", .errmsg = true, },
1123 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 656 { .name = "llistxattr", .errmsg = true, },
1124 { .name = "llistxattr", .errmsg = true, 657 { .name = "lremovexattr", .errmsg = true, },
1125 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1126 { .name = "lremovexattr", .errmsg = true,
1127 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1128 { .name = "lseek", .errmsg = true, 658 { .name = "lseek", .errmsg = true,
1129 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 659 .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
1130 [2] = SCA_STRARRAY, /* whence */ },
1131 .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, 660 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
1132 { .name = "lsetxattr", .errmsg = true, 661 { .name = "lsetxattr", .errmsg = true, },
1133 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 662 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
1134 { .name = "lstat", .errmsg = true, .alias = "newlstat", 663 { .name = "lsxattr", .errmsg = true, },
1135 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1136 { .name = "lsxattr", .errmsg = true,
1137 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1138 { .name = "madvise", .errmsg = true, 664 { .name = "madvise", .errmsg = true,
1139 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 665 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1140 [2] = SCA_MADV_BHV, /* behavior */ }, }, 666 [2] = SCA_MADV_BHV, /* behavior */ }, },
1141 { .name = "mkdir", .errmsg = true, 667 { .name = "mkdir", .errmsg = true, },
1142 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1143 { .name = "mkdirat", .errmsg = true, 668 { .name = "mkdirat", .errmsg = true,
1144 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 669 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1145 [1] = SCA_FILENAME, /* pathname */ }, }, 670 { .name = "mknod", .errmsg = true, },
1146 { .name = "mknod", .errmsg = true,
1147 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1148 { .name = "mknodat", .errmsg = true, 671 { .name = "mknodat", .errmsg = true,
1149 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 672 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1150 [1] = SCA_FILENAME, /* filename */ }, },
1151 { .name = "mlock", .errmsg = true, 673 { .name = "mlock", .errmsg = true,
1152 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 674 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1153 { .name = "mlockall", .errmsg = true, 675 { .name = "mlockall", .errmsg = true,
@@ -1155,8 +677,7 @@ static struct syscall_fmt {
1155 { .name = "mmap", .hexret = true, 677 { .name = "mmap", .hexret = true,
1156 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 678 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
1157 [2] = SCA_MMAP_PROT, /* prot */ 679 [2] = SCA_MMAP_PROT, /* prot */
1158 [3] = SCA_MMAP_FLAGS, /* flags */ 680 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
1159 [4] = SCA_FD, /* fd */ }, },
1160 { .name = "mprotect", .errmsg = true, 681 { .name = "mprotect", .errmsg = true,
1161 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 682 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1162 [2] = SCA_MMAP_PROT, /* prot */ }, }, 683 [2] = SCA_MMAP_PROT, /* prot */ }, },
@@ -1173,60 +694,43 @@ static struct syscall_fmt {
1173 { .name = "name_to_handle_at", .errmsg = true, 694 { .name = "name_to_handle_at", .errmsg = true,
1174 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 695 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1175 { .name = "newfstatat", .errmsg = true, 696 { .name = "newfstatat", .errmsg = true,
1176 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 697 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1177 [1] = SCA_FILENAME, /* filename */ }, },
1178 { .name = "open", .errmsg = true, 698 { .name = "open", .errmsg = true,
1179 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ 699 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
1180 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
1181 { .name = "open_by_handle_at", .errmsg = true, 700 { .name = "open_by_handle_at", .errmsg = true,
1182 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 701 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1183 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 702 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
1184 { .name = "openat", .errmsg = true, 703 { .name = "openat", .errmsg = true,
1185 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 704 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1186 [1] = SCA_FILENAME, /* filename */
1187 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 705 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
1188 { .name = "perf_event_open", .errmsg = true, 706 { .name = "perf_event_open", .errmsg = true,
1189 .arg_scnprintf = { [1] = SCA_INT, /* pid */ 707 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
1190 [2] = SCA_INT, /* cpu */
1191 [3] = SCA_FD, /* group_fd */ 708 [3] = SCA_FD, /* group_fd */
1192 [4] = SCA_PERF_FLAGS, /* flags */ }, }, 709 [4] = SCA_PERF_FLAGS, /* flags */ }, },
1193 { .name = "pipe2", .errmsg = true, 710 { .name = "pipe2", .errmsg = true,
1194 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, 711 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
1195 { .name = "poll", .errmsg = true, .timeout = true, }, 712 { .name = "poll", .errmsg = true, .timeout = true, },
1196 { .name = "ppoll", .errmsg = true, .timeout = true, }, 713 { .name = "ppoll", .errmsg = true, .timeout = true, },
1197 { .name = "pread", .errmsg = true, .alias = "pread64", 714 { .name = "pread", .errmsg = true, .alias = "pread64", },
1198 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 715 { .name = "preadv", .errmsg = true, .alias = "pread", },
1199 { .name = "preadv", .errmsg = true, .alias = "pread",
1200 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1201 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, 716 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
1202 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", 717 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
1203 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 718 { .name = "pwritev", .errmsg = true, },
1204 { .name = "pwritev", .errmsg = true, 719 { .name = "read", .errmsg = true, },
1205 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 720 { .name = "readlink", .errmsg = true, },
1206 { .name = "read", .errmsg = true,
1207 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1208 { .name = "readlink", .errmsg = true,
1209 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
1210 { .name = "readlinkat", .errmsg = true, 721 { .name = "readlinkat", .errmsg = true,
1211 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 722 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1212 [1] = SCA_FILENAME, /* pathname */ }, }, 723 { .name = "readv", .errmsg = true, },
1213 { .name = "readv", .errmsg = true,
1214 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1215 { .name = "recvfrom", .errmsg = true, 724 { .name = "recvfrom", .errmsg = true,
1216 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 725 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1217 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1218 { .name = "recvmmsg", .errmsg = true, 726 { .name = "recvmmsg", .errmsg = true,
1219 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 727 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1220 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1221 { .name = "recvmsg", .errmsg = true, 728 { .name = "recvmsg", .errmsg = true,
1222 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 729 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1223 [2] = SCA_MSG_FLAGS, /* flags */ }, }, 730 { .name = "removexattr", .errmsg = true, },
1224 { .name = "removexattr", .errmsg = true,
1225 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1226 { .name = "renameat", .errmsg = true, 731 { .name = "renameat", .errmsg = true,
1227 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 732 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1228 { .name = "rmdir", .errmsg = true, 733 { .name = "rmdir", .errmsg = true, },
1229 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1230 { .name = "rt_sigaction", .errmsg = true, 734 { .name = "rt_sigaction", .errmsg = true,
1231 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, 735 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
1232 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, 736 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
@@ -1234,22 +738,24 @@ static struct syscall_fmt {
1234 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 738 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1235 { .name = "rt_tgsigqueueinfo", .errmsg = true, 739 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1236 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 740 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
741 { .name = "sched_setscheduler", .errmsg = true,
742 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
743 { .name = "seccomp", .errmsg = true,
744 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
745 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
1237 { .name = "select", .errmsg = true, .timeout = true, }, 746 { .name = "select", .errmsg = true, .timeout = true, },
1238 { .name = "sendmmsg", .errmsg = true, 747 { .name = "sendmmsg", .errmsg = true,
1239 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 748 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1240 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1241 { .name = "sendmsg", .errmsg = true, 749 { .name = "sendmsg", .errmsg = true,
1242 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 750 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1243 [2] = SCA_MSG_FLAGS, /* flags */ }, },
1244 { .name = "sendto", .errmsg = true, 751 { .name = "sendto", .errmsg = true,
1245 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 752 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1246 [3] = SCA_MSG_FLAGS, /* flags */ }, }, 753 { .name = "set_tid_address", .errpid = true, },
1247 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 754 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
755 { .name = "setpgid", .errmsg = true, },
1248 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 756 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1249 { .name = "setxattr", .errmsg = true, 757 { .name = "setxattr", .errmsg = true, },
1250 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 758 { .name = "shutdown", .errmsg = true, },
1251 { .name = "shutdown", .errmsg = true,
1252 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1253 { .name = "socket", .errmsg = true, 759 { .name = "socket", .errmsg = true,
1254 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 760 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1255 [1] = SCA_SK_TYPE, /* type */ }, 761 [1] = SCA_SK_TYPE, /* type */ },
@@ -1258,10 +764,8 @@ static struct syscall_fmt {
1258 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 764 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1259 [1] = SCA_SK_TYPE, /* type */ }, 765 [1] = SCA_SK_TYPE, /* type */ },
1260 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 766 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1261 { .name = "stat", .errmsg = true, .alias = "newstat", 767 { .name = "stat", .errmsg = true, .alias = "newstat", },
1262 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 768 { .name = "statfs", .errmsg = true, },
1263 { .name = "statfs", .errmsg = true,
1264 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1265 { .name = "swapoff", .errmsg = true, 769 { .name = "swapoff", .errmsg = true,
1266 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, 770 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1267 { .name = "swapon", .errmsg = true, 771 { .name = "swapon", .errmsg = true,
@@ -1272,25 +776,21 @@ static struct syscall_fmt {
1272 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 776 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1273 { .name = "tkill", .errmsg = true, 777 { .name = "tkill", .errmsg = true,
1274 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 778 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1275 { .name = "truncate", .errmsg = true, 779 { .name = "truncate", .errmsg = true, },
1276 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
1277 { .name = "uname", .errmsg = true, .alias = "newuname", }, 780 { .name = "uname", .errmsg = true, .alias = "newuname", },
1278 { .name = "unlinkat", .errmsg = true, 781 { .name = "unlinkat", .errmsg = true,
1279 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 782 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1280 [1] = SCA_FILENAME, /* pathname */ }, }, 783 { .name = "utime", .errmsg = true, },
1281 { .name = "utime", .errmsg = true,
1282 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1283 { .name = "utimensat", .errmsg = true, 784 { .name = "utimensat", .errmsg = true,
1284 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ 785 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
1285 [1] = SCA_FILENAME, /* filename */ }, }, 786 { .name = "utimes", .errmsg = true, },
1286 { .name = "utimes", .errmsg = true, 787 { .name = "vmsplice", .errmsg = true, },
1287 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 788 { .name = "wait4", .errpid = true,
1288 { .name = "vmsplice", .errmsg = true, 789 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
1289 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 790 { .name = "waitid", .errpid = true,
1290 { .name = "write", .errmsg = true, 791 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
1291 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 792 { .name = "write", .errmsg = true, },
1292 { .name = "writev", .errmsg = true, 793 { .name = "writev", .errmsg = true, },
1293 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1294}; 794};
1295 795
1296static int syscall_fmt__cmp(const void *name, const void *fmtp) 796static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -1398,59 +898,6 @@ fail:
1398 898
1399static const size_t trace__entry_str_size = 2048; 899static const size_t trace__entry_str_size = 2048;
1400 900
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) 901static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1455{ 902{
1456 struct thread_trace *ttrace = thread__priv(thread); 903 struct thread_trace *ttrace = thread__priv(thread);
@@ -1618,6 +1065,7 @@ static int trace__process_event(struct trace *trace, struct machine *machine,
1618 color_fprintf(trace->output, PERF_COLOR_RED, 1065 color_fprintf(trace->output, PERF_COLOR_RED,
1619 "LOST %" PRIu64 " events!\n", event->lost.lost); 1066 "LOST %" PRIu64 " events!\n", event->lost.lost);
1620 ret = machine__process_lost_event(machine, event, sample); 1067 ret = machine__process_lost_event(machine, event, sample);
1068 break;
1621 default: 1069 default:
1622 ret = machine__process_event(machine, event, sample); 1070 ret = machine__process_event(machine, event, sample);
1623 break; 1071 break;
@@ -1635,6 +1083,24 @@ static int trace__tool_process(struct perf_tool *tool,
1635 return trace__process_event(trace, machine, event, sample); 1083 return trace__process_event(trace, machine, event, sample);
1636} 1084}
1637 1085
1086static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp)
1087{
1088 struct machine *machine = vmachine;
1089
1090 if (machine->kptr_restrict_warned)
1091 return NULL;
1092
1093 if (symbol_conf.kptr_restrict) {
1094 pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
1095 "Check /proc/sys/kernel/kptr_restrict.\n\n"
1096 "Kernel samples will not be resolved.\n");
1097 machine->kptr_restrict_warned = true;
1098 return NULL;
1099 }
1100
1101 return machine__resolve_kernel_addr(vmachine, addrp, modp);
1102}
1103
1638static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1104static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1639{ 1105{
1640 int err = symbol__init(NULL); 1106 int err = symbol__init(NULL);
@@ -1646,7 +1112,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1646 if (trace->host == NULL) 1112 if (trace->host == NULL)
1647 return -ENOMEM; 1113 return -ENOMEM;
1648 1114
1649 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0) 1115 if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0)
1650 return -errno; 1116 return -errno;
1651 1117
1652 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, 1118 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
@@ -1661,7 +1127,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1661static int syscall__set_arg_fmts(struct syscall *sc) 1127static int syscall__set_arg_fmts(struct syscall *sc)
1662{ 1128{
1663 struct format_field *field; 1129 struct format_field *field;
1664 int idx = 0; 1130 int idx = 0, len;
1665 1131
1666 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *)); 1132 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
1667 if (sc->arg_scnprintf == NULL) 1133 if (sc->arg_scnprintf == NULL)
@@ -1673,8 +1139,31 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1673 for (field = sc->args; field; field = field->next) { 1139 for (field = sc->args; field; field = field->next) {
1674 if (sc->fmt && sc->fmt->arg_scnprintf[idx]) 1140 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1675 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; 1141 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1142 else if (strcmp(field->type, "const char *") == 0 &&
1143 (strcmp(field->name, "filename") == 0 ||
1144 strcmp(field->name, "path") == 0 ||
1145 strcmp(field->name, "pathname") == 0))
1146 sc->arg_scnprintf[idx] = SCA_FILENAME;
1676 else if (field->flags & FIELD_IS_POINTER) 1147 else if (field->flags & FIELD_IS_POINTER)
1677 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; 1148 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1149 else if (strcmp(field->type, "pid_t") == 0)
1150 sc->arg_scnprintf[idx] = SCA_PID;
1151 else if (strcmp(field->type, "umode_t") == 0)
1152 sc->arg_scnprintf[idx] = SCA_MODE_T;
1153 else if ((strcmp(field->type, "int") == 0 ||
1154 strcmp(field->type, "unsigned int") == 0 ||
1155 strcmp(field->type, "long") == 0) &&
1156 (len = strlen(field->name)) >= 2 &&
1157 strcmp(field->name + len - 2, "fd") == 0) {
1158 /*
1159 * /sys/kernel/tracing/events/syscalls/sys_enter*
1160 * egrep 'field:.*fd;' .../format|sed -r 's/.*field:([a-z ]+) [a-z_]*fd.+/\1/g'|sort|uniq -c
1161 * 65 int
1162 * 23 unsigned int
1163 * 7 unsigned long
1164 */
1165 sc->arg_scnprintf[idx] = SCA_FD;
1166 }
1678 ++idx; 1167 ++idx;
1679 } 1168 }
1680 1169
@@ -1685,7 +1174,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1685{ 1174{
1686 char tp_name[128]; 1175 char tp_name[128];
1687 struct syscall *sc; 1176 struct syscall *sc;
1688 const char *name = audit_syscall_to_name(id, trace->audit.machine); 1177 const char *name = syscalltbl__name(trace->sctbl, id);
1689 1178
1690 if (name == NULL) 1179 if (name == NULL)
1691 return -1; 1180 return -1;
@@ -1760,7 +1249,7 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1760 1249
1761 strlist__for_each(pos, trace->ev_qualifier) { 1250 strlist__for_each(pos, trace->ev_qualifier) {
1762 const char *sc = pos->s; 1251 const char *sc = pos->s;
1763 int id = audit_name_to_syscall(sc, trace->audit.machine); 1252 int id = syscalltbl__id(trace->sctbl, sc);
1764 1253
1765 if (id < 0) { 1254 if (id < 0) {
1766 if (err == 0) { 1255 if (err == 0) {
@@ -1846,7 +1335,12 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1846 "%ld", val); 1335 "%ld", val);
1847 } 1336 }
1848 } 1337 }
1849 } else { 1338 } else if (IS_ERR(sc->tp_format)) {
1339 /*
1340 * If we managed to read the tracepoint /format file, then we
1341 * may end up not having any args, like with gettid(), so only
1342 * print the raw args when we didn't manage to read it.
1343 */
1850 int i = 0; 1344 int i = 0;
1851 1345
1852 while (i < 6) { 1346 while (i < 6) {
@@ -1987,7 +1481,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1987 goto out_put; 1481 goto out_put;
1988 } 1482 }
1989 1483
1990 if (!trace->summary_only) 1484 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
1991 trace__printf_interrupted_entry(trace, sample); 1485 trace__printf_interrupted_entry(trace, sample);
1992 1486
1993 ttrace->entry_time = sample->time; 1487 ttrace->entry_time = sample->time;
@@ -1998,9 +1492,9 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1998 args, trace, thread); 1492 args, trace, thread);
1999 1493
2000 if (sc->is_exit) { 1494 if (sc->is_exit) {
2001 if (!trace->duration_filter && !trace->summary_only) { 1495 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
2002 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); 1496 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
2003 fprintf(trace->output, "%-70s\n", ttrace->entry_str); 1497 fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
2004 } 1498 }
2005 } else { 1499 } else {
2006 ttrace->entry_pending = true; 1500 ttrace->entry_pending = true;
@@ -2018,6 +1512,29 @@ out_put:
2018 return err; 1512 return err;
2019} 1513}
2020 1514
1515static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1516 struct perf_sample *sample,
1517 struct callchain_cursor *cursor)
1518{
1519 struct addr_location al;
1520
1521 if (machine__resolve(trace->host, &al, sample) < 0 ||
1522 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1523 return -1;
1524
1525 return 0;
1526}
1527
1528static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1529{
1530 /* TODO: user-configurable print_opts */
1531 const unsigned int print_opts = EVSEL__PRINT_SYM |
1532 EVSEL__PRINT_DSO |
1533 EVSEL__PRINT_UNKNOWN_AS_ADDR;
1534
1535 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
1536}
1537
2021static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, 1538static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2022 union perf_event *event __maybe_unused, 1539 union perf_event *event __maybe_unused,
2023 struct perf_sample *sample) 1540 struct perf_sample *sample)
@@ -2025,7 +1542,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2025 long ret; 1542 long ret;
2026 u64 duration = 0; 1543 u64 duration = 0;
2027 struct thread *thread; 1544 struct thread *thread;
2028 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; 1545 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); 1546 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2030 struct thread_trace *ttrace; 1547 struct thread_trace *ttrace;
2031 1548
@@ -2042,7 +1559,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2042 1559
2043 ret = perf_evsel__sc_tp_uint(evsel, ret, sample); 1560 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
2044 1561
2045 if (id == trace->audit.open_id && ret >= 0 && ttrace->filename.pending_open) { 1562 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
2046 trace__set_fd_pathname(thread, ret, ttrace->filename.name); 1563 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
2047 ttrace->filename.pending_open = false; 1564 ttrace->filename.pending_open = false;
2048 ++trace->stats.vfs_getname; 1565 ++trace->stats.vfs_getname;
@@ -2057,6 +1574,15 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2057 } else if (trace->duration_filter) 1574 } else if (trace->duration_filter)
2058 goto out; 1575 goto out;
2059 1576
1577 if (sample->callchain) {
1578 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1579 if (callchain_ret == 0) {
1580 if (callchain_cursor.nr < trace->min_stack)
1581 goto out;
1582 callchain_ret = 1;
1583 }
1584 }
1585
2060 if (trace->summary_only) 1586 if (trace->summary_only)
2061 goto out; 1587 goto out;
2062 1588
@@ -2073,7 +1599,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2073 if (sc->fmt == NULL) { 1599 if (sc->fmt == NULL) {
2074signed_print: 1600signed_print:
2075 fprintf(trace->output, ") = %ld", ret); 1601 fprintf(trace->output, ") = %ld", ret);
2076 } else if (ret < 0 && sc->fmt->errmsg) { 1602 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
2077 char bf[STRERR_BUFSIZE]; 1603 char bf[STRERR_BUFSIZE];
2078 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 1604 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
2079 *e = audit_errno_to_name(-ret); 1605 *e = audit_errno_to_name(-ret);
@@ -2083,10 +1609,24 @@ signed_print:
2083 fprintf(trace->output, ") = 0 Timeout"); 1609 fprintf(trace->output, ") = 0 Timeout");
2084 else if (sc->fmt->hexret) 1610 else if (sc->fmt->hexret)
2085 fprintf(trace->output, ") = %#lx", ret); 1611 fprintf(trace->output, ") = %#lx", ret);
2086 else 1612 else if (sc->fmt->errpid) {
1613 struct thread *child = machine__find_thread(trace->host, ret, ret);
1614
1615 if (child != NULL) {
1616 fprintf(trace->output, ") = %ld", ret);
1617 if (child->comm_set)
1618 fprintf(trace->output, " (%s)", thread__comm_str(child));
1619 thread__put(child);
1620 }
1621 } else
2087 goto signed_print; 1622 goto signed_print;
2088 1623
2089 fputc('\n', trace->output); 1624 fputc('\n', trace->output);
1625
1626 if (callchain_ret > 0)
1627 trace__fprintf_callchain(trace, sample);
1628 else if (callchain_ret < 0)
1629 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2090out: 1630out:
2091 ttrace->entry_pending = false; 1631 ttrace->entry_pending = false;
2092 err = 0; 1632 err = 0;
@@ -2217,6 +1757,17 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2217 union perf_event *event __maybe_unused, 1757 union perf_event *event __maybe_unused,
2218 struct perf_sample *sample) 1758 struct perf_sample *sample)
2219{ 1759{
1760 int callchain_ret = 0;
1761
1762 if (sample->callchain) {
1763 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1764 if (callchain_ret == 0) {
1765 if (callchain_cursor.nr < trace->min_stack)
1766 goto out;
1767 callchain_ret = 1;
1768 }
1769 }
1770
2220 trace__printf_interrupted_entry(trace, sample); 1771 trace__printf_interrupted_entry(trace, sample);
2221 trace__fprintf_tstamp(trace, sample->time, trace->output); 1772 trace__fprintf_tstamp(trace, sample->time, trace->output);
2222 1773
@@ -2234,6 +1785,12 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2234 } 1785 }
2235 1786
2236 fprintf(trace->output, ")\n"); 1787 fprintf(trace->output, ")\n");
1788
1789 if (callchain_ret > 0)
1790 trace__fprintf_callchain(trace, sample);
1791 else if (callchain_ret < 0)
1792 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
1793out:
2237 return 0; 1794 return 0;
2238} 1795}
2239 1796
@@ -2264,8 +1821,19 @@ static int trace__pgfault(struct trace *trace,
2264 char map_type = 'd'; 1821 char map_type = 'd';
2265 struct thread_trace *ttrace; 1822 struct thread_trace *ttrace;
2266 int err = -1; 1823 int err = -1;
1824 int callchain_ret = 0;
2267 1825
2268 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 1826 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1827
1828 if (sample->callchain) {
1829 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1830 if (callchain_ret == 0) {
1831 if (callchain_cursor.nr < trace->min_stack)
1832 goto out_put;
1833 callchain_ret = 1;
1834 }
1835 }
1836
2269 ttrace = thread__trace(thread, trace->output); 1837 ttrace = thread__trace(thread, trace->output);
2270 if (ttrace == NULL) 1838 if (ttrace == NULL)
2271 goto out_put; 1839 goto out_put;
@@ -2307,6 +1875,11 @@ static int trace__pgfault(struct trace *trace,
2307 print_location(trace->output, sample, &al, true, false); 1875 print_location(trace->output, sample, &al, true, false);
2308 1876
2309 fprintf(trace->output, " (%c%c)\n", map_type, al.level); 1877 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
1878
1879 if (callchain_ret > 0)
1880 trace__fprintf_callchain(trace, sample);
1881 else if (callchain_ret < 0)
1882 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2310out: 1883out:
2311 err = 0; 1884 err = 0;
2312out_put: 1885out_put:
@@ -2326,6 +1899,23 @@ static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2326 return false; 1899 return false;
2327} 1900}
2328 1901
1902static void trace__set_base_time(struct trace *trace,
1903 struct perf_evsel *evsel,
1904 struct perf_sample *sample)
1905{
1906 /*
1907 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
1908 * and don't use sample->time unconditionally, we may end up having
1909 * some other event in the future without PERF_SAMPLE_TIME for good
1910 * reason, i.e. we may not be interested in its timestamps, just in
1911 * it taking place, picking some piece of information when it
1912 * appears in our event stream (vfs_getname comes to mind).
1913 */
1914 if (trace->base_time == 0 && !trace->full_time &&
1915 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
1916 trace->base_time = sample->time;
1917}
1918
2329static int trace__process_sample(struct perf_tool *tool, 1919static int trace__process_sample(struct perf_tool *tool,
2330 union perf_event *event, 1920 union perf_event *event,
2331 struct perf_sample *sample, 1921 struct perf_sample *sample,
@@ -2340,8 +1930,7 @@ static int trace__process_sample(struct perf_tool *tool,
2340 if (skip_sample(trace, sample)) 1930 if (skip_sample(trace, sample))
2341 return 0; 1931 return 0;
2342 1932
2343 if (!trace->full_time && trace->base_time == 0) 1933 trace__set_base_time(trace, evsel, sample);
2344 trace->base_time = sample->time;
2345 1934
2346 if (handler) { 1935 if (handler) {
2347 ++trace->nr_events; 1936 ++trace->nr_events;
@@ -2450,8 +2039,7 @@ static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
2450 return true; 2039 return true;
2451} 2040}
2452 2041
2453static int perf_evlist__add_pgfault(struct perf_evlist *evlist, 2042static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
2454 u64 config)
2455{ 2043{
2456 struct perf_evsel *evsel; 2044 struct perf_evsel *evsel;
2457 struct perf_event_attr attr = { 2045 struct perf_event_attr attr = {
@@ -2465,13 +2053,10 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2465 event_attr_init(&attr); 2053 event_attr_init(&attr);
2466 2054
2467 evsel = perf_evsel__new(&attr); 2055 evsel = perf_evsel__new(&attr);
2468 if (!evsel) 2056 if (evsel)
2469 return -ENOMEM; 2057 evsel->handler = trace__pgfault;
2470 2058
2471 evsel->handler = trace__pgfault; 2059 return evsel;
2472 perf_evlist__add(evlist, evsel);
2473
2474 return 0;
2475} 2060}
2476 2061
2477static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) 2062static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
@@ -2479,9 +2064,6 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
2479 const u32 type = event->header.type; 2064 const u32 type = event->header.type;
2480 struct perf_evsel *evsel; 2065 struct perf_evsel *evsel;
2481 2066
2482 if (!trace->full_time && trace->base_time == 0)
2483 trace->base_time = sample->time;
2484
2485 if (type != PERF_RECORD_SAMPLE) { 2067 if (type != PERF_RECORD_SAMPLE) {
2486 trace__process_event(trace, trace->host, event, sample); 2068 trace__process_event(trace, trace->host, event, sample);
2487 return; 2069 return;
@@ -2493,6 +2075,8 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
2493 return; 2075 return;
2494 } 2076 }
2495 2077
2078 trace__set_base_time(trace, evsel, sample);
2079
2496 if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 2080 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2497 sample->raw_data == NULL) { 2081 sample->raw_data == NULL) {
2498 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", 2082 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
@@ -2527,6 +2111,15 @@ static int trace__add_syscall_newtp(struct trace *trace)
2527 perf_evlist__add(evlist, sys_enter); 2111 perf_evlist__add(evlist, sys_enter);
2528 perf_evlist__add(evlist, sys_exit); 2112 perf_evlist__add(evlist, sys_exit);
2529 2113
2114 if (callchain_param.enabled && !trace->kernel_syscallchains) {
2115 /*
2116 * We're interested only in the user space callchain
2117 * leading to the syscall, allow overriding that for
2118 * debugging reasons using --kernel_syscall_callchains
2119 */
2120 sys_exit->attr.exclude_callchain_kernel = 1;
2121 }
2122
2530 trace->syscalls.events.sys_enter = sys_enter; 2123 trace->syscalls.events.sys_enter = sys_enter;
2531 trace->syscalls.events.sys_exit = sys_exit; 2124 trace->syscalls.events.sys_exit = sys_exit;
2532 2125
@@ -2565,7 +2158,7 @@ out_enomem:
2565static int trace__run(struct trace *trace, int argc, const char **argv) 2158static int trace__run(struct trace *trace, int argc, const char **argv)
2566{ 2159{
2567 struct perf_evlist *evlist = trace->evlist; 2160 struct perf_evlist *evlist = trace->evlist;
2568 struct perf_evsel *evsel; 2161 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
2569 int err = -1, i; 2162 int err = -1, i;
2570 unsigned long before; 2163 unsigned long before;
2571 const bool forks = argc > 0; 2164 const bool forks = argc > 0;
@@ -2579,14 +2172,19 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2579 if (trace->trace_syscalls) 2172 if (trace->trace_syscalls)
2580 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist); 2173 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
2581 2174
2582 if ((trace->trace_pgfaults & TRACE_PFMAJ) && 2175 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2583 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) { 2176 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2584 goto out_error_mem; 2177 if (pgfault_maj == NULL)
2178 goto out_error_mem;
2179 perf_evlist__add(evlist, pgfault_maj);
2585 } 2180 }
2586 2181
2587 if ((trace->trace_pgfaults & TRACE_PFMIN) && 2182 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2588 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN)) 2183 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2589 goto out_error_mem; 2184 if (pgfault_min == NULL)
2185 goto out_error_mem;
2186 perf_evlist__add(evlist, pgfault_min);
2187 }
2590 2188
2591 if (trace->sched && 2189 if (trace->sched &&
2592 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 2190 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
@@ -2605,7 +2203,45 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2605 goto out_delete_evlist; 2203 goto out_delete_evlist;
2606 } 2204 }
2607 2205
2608 perf_evlist__config(evlist, &trace->opts); 2206 perf_evlist__config(evlist, &trace->opts, NULL);
2207
2208 if (callchain_param.enabled) {
2209 bool use_identifier = false;
2210
2211 if (trace->syscalls.events.sys_exit) {
2212 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2213 &trace->opts, &callchain_param);
2214 use_identifier = true;
2215 }
2216
2217 if (pgfault_maj) {
2218 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2219 use_identifier = true;
2220 }
2221
2222 if (pgfault_min) {
2223 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2224 use_identifier = true;
2225 }
2226
2227 if (use_identifier) {
2228 /*
2229 * Now we have evsels with different sample_ids, use
2230 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2231 * from a fixed position in each ring buffer record.
2232 *
2233 * As of this the changeset introducing this comment, this
2234 * isn't strictly needed, as the fields that can come before
2235 * PERF_SAMPLE_ID are all used, but we'll probably disable
2236 * some of those for things like copying the payload of
2237 * pointer syscall arguments, and for vfs_getname we don't
2238 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2239 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2240 */
2241 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2242 perf_evlist__reset_sample_bit(evlist, ID);
2243 }
2244 }
2609 2245
2610 signal(SIGCHLD, sig_handler); 2246 signal(SIGCHLD, sig_handler);
2611 signal(SIGINT, sig_handler); 2247 signal(SIGINT, sig_handler);
@@ -2883,15 +2519,29 @@ static size_t trace__fprintf_threads_header(FILE *fp)
2883 return printed; 2519 return printed;
2884} 2520}
2885 2521
2522DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
2523 struct stats *stats;
2524 double msecs;
2525 int syscall;
2526)
2527{
2528 struct int_node *source = rb_entry(nd, struct int_node, rb_node);
2529 struct stats *stats = source->priv;
2530
2531 entry->syscall = source->i;
2532 entry->stats = stats;
2533 entry->msecs = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
2534}
2535
2886static size_t thread__dump_stats(struct thread_trace *ttrace, 2536static size_t thread__dump_stats(struct thread_trace *ttrace,
2887 struct trace *trace, FILE *fp) 2537 struct trace *trace, FILE *fp)
2888{ 2538{
2889 struct stats *stats;
2890 size_t printed = 0; 2539 size_t printed = 0;
2891 struct syscall *sc; 2540 struct syscall *sc;
2892 struct int_node *inode = intlist__first(ttrace->syscall_stats); 2541 struct rb_node *nd;
2542 DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
2893 2543
2894 if (inode == NULL) 2544 if (syscall_stats == NULL)
2895 return 0; 2545 return 0;
2896 2546
2897 printed += fprintf(fp, "\n"); 2547 printed += fprintf(fp, "\n");
@@ -2900,9 +2550,8 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
2900 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n"); 2550 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2901 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n"); 2551 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
2902 2552
2903 /* each int_node is a syscall */ 2553 resort_rb__for_each(nd, syscall_stats) {
2904 while (inode) { 2554 struct stats *stats = syscall_stats_entry->stats;
2905 stats = inode->priv;
2906 if (stats) { 2555 if (stats) {
2907 double min = (double)(stats->min) / NSEC_PER_MSEC; 2556 double min = (double)(stats->min) / NSEC_PER_MSEC;
2908 double max = (double)(stats->max) / NSEC_PER_MSEC; 2557 double max = (double)(stats->max) / NSEC_PER_MSEC;
@@ -2913,34 +2562,23 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
2913 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0; 2562 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2914 avg /= NSEC_PER_MSEC; 2563 avg /= NSEC_PER_MSEC;
2915 2564
2916 sc = &trace->syscalls.table[inode->i]; 2565 sc = &trace->syscalls.table[syscall_stats_entry->syscall];
2917 printed += fprintf(fp, " %-15s", sc->name); 2566 printed += fprintf(fp, " %-15s", sc->name);
2918 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f", 2567 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2919 n, avg * n, min, avg); 2568 n, syscall_stats_entry->msecs, min, avg);
2920 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct); 2569 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
2921 } 2570 }
2922
2923 inode = intlist__next(inode);
2924 } 2571 }
2925 2572
2573 resort_rb__delete(syscall_stats);
2926 printed += fprintf(fp, "\n\n"); 2574 printed += fprintf(fp, "\n\n");
2927 2575
2928 return printed; 2576 return printed;
2929} 2577}
2930 2578
2931/* struct used to pass data to per-thread function */ 2579static 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{ 2580{
2940 struct summary_data *data = priv; 2581 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); 2582 struct thread_trace *ttrace = thread__priv(thread);
2945 double ratio; 2583 double ratio;
2946 2584
@@ -2956,25 +2594,45 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2956 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj); 2594 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2957 if (ttrace->pfmin) 2595 if (ttrace->pfmin)
2958 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin); 2596 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
2959 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); 2597 if (trace->sched)
2598 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2599 else if (fputc('\n', fp) != EOF)
2600 ++printed;
2601
2960 printed += thread__dump_stats(ttrace, trace, fp); 2602 printed += thread__dump_stats(ttrace, trace, fp);
2961 2603
2962 data->printed += printed; 2604 return printed;
2605}
2963 2606
2964 return 0; 2607static unsigned long thread__nr_events(struct thread_trace *ttrace)
2608{
2609 return ttrace ? ttrace->nr_events : 0;
2610}
2611
2612DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
2613 struct thread *thread;
2614)
2615{
2616 entry->thread = rb_entry(nd, struct thread, rb_node);
2965} 2617}
2966 2618
2967static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) 2619static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2968{ 2620{
2969 struct summary_data data = { 2621 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
2970 .fp = fp, 2622 size_t printed = trace__fprintf_threads_header(fp);
2971 .trace = trace 2623 struct rb_node *nd;
2972 };
2973 data.printed = trace__fprintf_threads_header(fp);
2974 2624
2975 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data); 2625 if (threads == NULL) {
2626 fprintf(fp, "%s", "Error sorting output by nr_events!\n");
2627 return 0;
2628 }
2976 2629
2977 return data.printed; 2630 resort_rb__for_each(nd, threads)
2631 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2632
2633 resort_rb__delete(threads);
2634
2635 return printed;
2978} 2636}
2979 2637
2980static int trace__set_duration(const struct option *opt, const char *str, 2638static int trace__set_duration(const struct option *opt, const char *str,
@@ -3070,10 +2728,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3070 NULL 2728 NULL
3071 }; 2729 };
3072 struct trace trace = { 2730 struct trace trace = {
3073 .audit = {
3074 .machine = audit_detect_machine(),
3075 .open_id = audit_name_to_syscall("open", trace.audit.machine),
3076 },
3077 .syscalls = { 2731 .syscalls = {
3078 . max = -1, 2732 . max = -1,
3079 }, 2733 },
@@ -3091,6 +2745,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3091 .output = stderr, 2745 .output = stderr,
3092 .show_comm = true, 2746 .show_comm = true,
3093 .trace_syscalls = true, 2747 .trace_syscalls = true,
2748 .kernel_syscallchains = false,
2749 .max_stack = UINT_MAX,
3094 }; 2750 };
3095 const char *output_name = NULL; 2751 const char *output_name = NULL;
3096 const char *ev_qualifier_str = NULL; 2752 const char *ev_qualifier_str = NULL;
@@ -3136,10 +2792,24 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3136 "Trace pagefaults", parse_pagefaults, "maj"), 2792 "Trace pagefaults", parse_pagefaults, "maj"),
3137 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"), 2793 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
3138 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"), 2794 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
2795 OPT_CALLBACK(0, "call-graph", &trace.opts,
2796 "record_mode[,record_size]", record_callchain_help,
2797 &record_parse_callchain_opt),
2798 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
2799 "Show the kernel callchains on the syscall exit path"),
2800 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
2801 "Set the minimum stack depth when parsing the callchain, "
2802 "anything below the specified depth will be ignored."),
2803 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
2804 "Set the maximum stack depth when parsing the callchain, "
2805 "anything beyond the specified depth will be ignored. "
2806 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
3139 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, 2807 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3140 "per thread proc mmap processing timeout in ms"), 2808 "per thread proc mmap processing timeout in ms"),
3141 OPT_END() 2809 OPT_END()
3142 }; 2810 };
2811 bool __maybe_unused max_stack_user_set = true;
2812 bool mmap_pages_user_set = true;
3143 const char * const trace_subcommands[] = { "record", NULL }; 2813 const char * const trace_subcommands[] = { "record", NULL };
3144 int err; 2814 int err;
3145 char bf[BUFSIZ]; 2815 char bf[BUFSIZ];
@@ -3148,8 +2818,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3148 signal(SIGFPE, sighandler_dump_stack); 2818 signal(SIGFPE, sighandler_dump_stack);
3149 2819
3150 trace.evlist = perf_evlist__new(); 2820 trace.evlist = perf_evlist__new();
2821 trace.sctbl = syscalltbl__new();
3151 2822
3152 if (trace.evlist == NULL) { 2823 if (trace.evlist == NULL || trace.sctbl == NULL) {
3153 pr_err("Not enough memory to run!\n"); 2824 pr_err("Not enough memory to run!\n");
3154 err = -ENOMEM; 2825 err = -ENOMEM;
3155 goto out; 2826 goto out;
@@ -3158,11 +2829,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, 2829 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3159 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION); 2830 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
3160 2831
2832 err = bpf__setup_stdout(trace.evlist);
2833 if (err) {
2834 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
2835 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
2836 goto out;
2837 }
2838
2839 err = -1;
2840
3161 if (trace.trace_pgfaults) { 2841 if (trace.trace_pgfaults) {
3162 trace.opts.sample_address = true; 2842 trace.opts.sample_address = true;
3163 trace.opts.sample_time = true; 2843 trace.opts.sample_time = true;
3164 } 2844 }
3165 2845
2846 if (trace.opts.mmap_pages == UINT_MAX)
2847 mmap_pages_user_set = false;
2848
2849 if (trace.max_stack == UINT_MAX) {
2850 trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack;
2851 max_stack_user_set = false;
2852 }
2853
2854#ifdef HAVE_DWARF_UNWIND_SUPPORT
2855 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls)
2856 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
2857#endif
2858
2859 if (callchain_param.enabled) {
2860 if (!mmap_pages_user_set && geteuid() == 0)
2861 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
2862
2863 symbol_conf.use_callchain = true;
2864 }
2865
3166 if (trace.evlist->nr_entries > 0) 2866 if (trace.evlist->nr_entries > 0)
3167 evlist__set_evsel_handler(trace.evlist, trace__event_handler); 2867 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3168 2868
@@ -3179,6 +2879,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3179 return -1; 2879 return -1;
3180 } 2880 }
3181 2881
2882 if (!trace.trace_syscalls && ev_qualifier_str) {
2883 pr_err("The -e option can't be used with --no-syscalls.\n");
2884 goto out;
2885 }
2886
3182 if (output_name != NULL) { 2887 if (output_name != NULL) {
3183 err = trace__open_output(&trace, output_name); 2888 err = trace__open_output(&trace, output_name);
3184 if (err < 0) { 2889 if (err < 0) {
@@ -3187,6 +2892,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3187 } 2892 }
3188 } 2893 }
3189 2894
2895 trace.open_id = syscalltbl__id(trace.sctbl, "open");
2896
3190 if (ev_qualifier_str != NULL) { 2897 if (ev_qualifier_str != NULL) {
3191 const char *s = ev_qualifier_str; 2898 const char *s = ev_qualifier_str;
3192 struct strlist_config slist_config = { 2899 struct strlist_config slist_config = {
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index f7d7f5a1cad5..5ad0255f8756 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -23,11 +23,17 @@ $(call detected_var,ARCH)
23 23
24NO_PERF_REGS := 1 24NO_PERF_REGS := 1
25 25
26# Additional ARCH settings for ppc
27ifeq ($(ARCH),powerpc)
28 NO_PERF_REGS := 0
29 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
30endif
31
26# Additional ARCH settings for x86 32# Additional ARCH settings for x86
27ifeq ($(ARCH),x86) 33ifeq ($(ARCH),x86)
28 $(call detected,CONFIG_X86) 34 $(call detected,CONFIG_X86)
29 ifeq (${IS_64_BIT}, 1) 35 ifeq (${IS_64_BIT}, 1)
30 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT 36 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 37 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 38 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
33 $(call detected,CONFIG_X86_64) 39 $(call detected,CONFIG_X86_64)
@@ -268,6 +274,12 @@ else
268 ifneq ($(feature-dwarf), 1) 274 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); 275 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 276 NO_DWARF := 1
277 else
278 ifneq ($(feature-dwarf_getlocations), 1)
279 msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
280 else
281 CFLAGS += -DHAVE_DWARF_GETLOCATIONS
282 endif # dwarf_getlocations
271 endif # Dwarf support 283 endif # Dwarf support
272 endif # libelf support 284 endif # libelf support
273endif # NO_LIBELF 285endif # NO_LIBELF
@@ -289,9 +301,6 @@ ifndef NO_LIBELF
289 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT 301 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
290 endif 302 endif
291 303
292 # include ARCH specific config
293 -include $(src-perf)/arch/$(ARCH)/Makefile
294
295 ifndef NO_DWARF 304 ifndef NO_DWARF
296 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 305 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
297 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 306 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..15982cee5ef3 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,12 @@ 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
552 if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0)
553 sysctl_perf_event_max_contexts_per_stack = value;
554
545 cmd = extract_argv0_path(argv[0]); 555 cmd = extract_argv0_path(argv[0]);
546 if (!cmd) 556 if (!cmd)
547 cmd = "perf-help"; 557 cmd = "perf-help";
@@ -549,6 +559,7 @@ int main(int argc, const char **argv)
549 srandom(time(NULL)); 559 srandom(time(NULL));
550 560
551 perf_config(perf_default_config, NULL); 561 perf_config(perf_default_config, NULL);
562 set_buildid_dir(NULL);
552 563
553 /* get debugfs/tracefs mount point from /proc/mounts */ 564 /* get debugfs/tracefs mount point from /proc/mounts */
554 tracing_path_mount(); 565 tracing_path_mount();
@@ -572,7 +583,6 @@ int main(int argc, const char **argv)
572 } 583 }
573 if (!prefixcmp(cmd, "trace")) { 584 if (!prefixcmp(cmd, "trace")) {
574#ifdef HAVE_LIBAUDIT_SUPPORT 585#ifdef HAVE_LIBAUDIT_SUPPORT
575 set_buildid_dir(NULL);
576 setup_path(); 586 setup_path();
577 argv[0] = "trace"; 587 argv[0] = "trace";
578 return cmd_trace(argc, argv, NULL); 588 return cmd_trace(argc, argv, NULL);
@@ -587,7 +597,6 @@ int main(int argc, const char **argv)
587 argc--; 597 argc--;
588 handle_options(&argv, &argc, NULL); 598 handle_options(&argv, &argc, NULL);
589 commit_pager_choice(); 599 commit_pager_choice();
590 set_buildid_dir(NULL);
591 600
592 if (argc > 0) { 601 if (argc > 0) {
593 if (!prefixcmp(argv[0], "--")) 602 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..7e5a1e8874ce 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -354,9 +354,6 @@ static struct ins_ops nop_ops = {
354 .scnprintf = nop__scnprintf, 354 .scnprintf = nop__scnprintf,
355}; 355};
356 356
357/*
358 * Must be sorted by name!
359 */
360static struct ins instructions[] = { 357static struct ins instructions[] = {
361 { .name = "add", .ops = &mov_ops, }, 358 { .name = "add", .ops = &mov_ops, },
362 { .name = "addl", .ops = &mov_ops, }, 359 { .name = "addl", .ops = &mov_ops, },
@@ -372,8 +369,8 @@ static struct ins instructions[] = {
372 { .name = "bgt", .ops = &jump_ops, }, 369 { .name = "bgt", .ops = &jump_ops, },
373 { .name = "bhi", .ops = &jump_ops, }, 370 { .name = "bhi", .ops = &jump_ops, },
374 { .name = "bl", .ops = &call_ops, }, 371 { .name = "bl", .ops = &call_ops, },
375 { .name = "blt", .ops = &jump_ops, },
376 { .name = "bls", .ops = &jump_ops, }, 372 { .name = "bls", .ops = &jump_ops, },
373 { .name = "blt", .ops = &jump_ops, },
377 { .name = "blx", .ops = &call_ops, }, 374 { .name = "blx", .ops = &call_ops, },
378 { .name = "bne", .ops = &jump_ops, }, 375 { .name = "bne", .ops = &jump_ops, },
379#endif 376#endif
@@ -449,18 +446,39 @@ static struct ins instructions[] = {
449 { .name = "xbeginq", .ops = &jump_ops, }, 446 { .name = "xbeginq", .ops = &jump_ops, },
450}; 447};
451 448
452static int ins__cmp(const void *name, const void *insp) 449static int ins__key_cmp(const void *name, const void *insp)
453{ 450{
454 const struct ins *ins = insp; 451 const struct ins *ins = insp;
455 452
456 return strcmp(name, ins->name); 453 return strcmp(name, ins->name);
457} 454}
458 455
456static int ins__cmp(const void *a, const void *b)
457{
458 const struct ins *ia = a;
459 const struct ins *ib = b;
460
461 return strcmp(ia->name, ib->name);
462}
463
464static void ins__sort(void)
465{
466 const int nmemb = ARRAY_SIZE(instructions);
467
468 qsort(instructions, nmemb, sizeof(struct ins), ins__cmp);
469}
470
459static struct ins *ins__find(const char *name) 471static struct ins *ins__find(const char *name)
460{ 472{
461 const int nmemb = ARRAY_SIZE(instructions); 473 const int nmemb = ARRAY_SIZE(instructions);
474 static bool sorted;
475
476 if (!sorted) {
477 ins__sort();
478 sorted = true;
479 }
462 480
463 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp); 481 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp);
464} 482}
465 483
466int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym) 484int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
@@ -1122,7 +1140,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
1122 } else if (dso__is_kcore(dso)) { 1140 } else if (dso__is_kcore(dso)) {
1123 goto fallback; 1141 goto fallback;
1124 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || 1142 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
1125 strstr(command, "[kernel.kallsyms]") || 1143 strstr(command, DSO__NAME_KALLSYMS) ||
1126 access(symfs_filename, R_OK)) { 1144 access(symfs_filename, R_OK)) {
1127 free(filename); 1145 free(filename);
1128fallback: 1146fallback:
@@ -1138,7 +1156,7 @@ fallback:
1138 1156
1139 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1157 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1140 !dso__is_kcore(dso)) { 1158 !dso__is_kcore(dso)) {
1141 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id "; 1159 char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1142 char *build_id_msg = NULL; 1160 char *build_id_msg = NULL;
1143 1161
1144 if (dso->annotate_warned) 1162 if (dso->annotate_warned)
@@ -1665,5 +1683,5 @@ int hist_entry__annotate(struct hist_entry *he, size_t privsize)
1665 1683
1666bool ui__has_annotation(void) 1684bool ui__has_annotation(void)
1667{ 1685{
1668 return use_browser == 1 && sort__has_sym; 1686 return use_browser == 1 && perf_hpp_list.sym;
1669} 1687}
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..67e5966503b2 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -256,19 +256,19 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
256 size_t name_len; 256 size_t name_len;
257 bool in_kernel = false; 257 bool in_kernel = false;
258 258
259 if (!pos->hit) 259 if (!pos->hit && !dso__is_vdso(pos))
260 continue; 260 continue;
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..c9a6dc173e74 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,79 @@ 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, PERF_MAX_STACK_DEPTH);
302 if (err) {
303 callchain_param.order = saved_order;
304 return NULL;
305 }
306 callchain_cursor_commit(&callchain_cursor);
307
308 while (1) {
309 struct callchain_cursor_node *node;
310 struct addr_location al;
311 u64 dso_db_id = 0, sym_db_id = 0, offset = 0;
312
313 memset(&al, 0, sizeof(al));
314
315 node = callchain_cursor_current(&callchain_cursor);
316 if (!node)
317 break;
318 /*
319 * Handle export of symbol and dso for this node by
320 * constructing an addr_location struct and then passing it to
321 * db_ids_from_al() to perform the export.
322 */
323 al.sym = node->sym;
324 al.map = node->map;
325 al.machine = machine;
326 al.addr = node->ip;
327
328 if (al.map && !al.sym)
329 al.sym = dso__find_symbol(al.map->dso, MAP__FUNCTION,
330 al.addr);
331
332 db_ids_from_al(dbe, &al, &dso_db_id, &sym_db_id, &offset);
333
334 /* add node to the call path tree if it doesn't exist */
335 current = call_path__findnew(dbe->cpr, current,
336 al.sym, node->ip,
337 kernel_start);
338
339 callchain_cursor_advance(&callchain_cursor);
340 }
341
342 /* Reset the callchain order to its prior value. */
343 callchain_param.order = saved_order;
344
345 if (current == &dbe->cpr->call_path) {
346 /* Bail because the callchain was empty. */
347 return NULL;
348 }
349
350 return current;
351}
352
279int db_export__branch_type(struct db_export *dbe, u32 branch_type, 353int db_export__branch_type(struct db_export *dbe, u32 branch_type,
280 const char *name) 354 const char *name)
281{ 355{
@@ -329,6 +403,16 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
329 if (err) 403 if (err)
330 goto out_put; 404 goto out_put;
331 405
406 if (dbe->cpr) {
407 struct call_path *cp = call_path_from_sample(dbe, al->machine,
408 thread, sample,
409 evsel);
410 if (cp) {
411 db_export__call_path(dbe, cp);
412 es.call_path_id = cp->db_id;
413 }
414 }
415
332 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 416 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
333 sample_addr_correlates_sym(&evsel->attr)) { 417 sample_addr_correlates_sym(&evsel->attr)) {
334 struct addr_location addr_al; 418 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..5d286f5d7906 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -7,6 +7,7 @@
7#include "auxtrace.h" 7#include "auxtrace.h"
8#include "util.h" 8#include "util.h"
9#include "debug.h" 9#include "debug.h"
10#include "vdso.h"
10 11
11char dso__symtab_origin(const struct dso *dso) 12char dso__symtab_origin(const struct dso *dso)
12{ 13{
@@ -38,7 +39,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
38 enum dso_binary_type type, 39 enum dso_binary_type type,
39 char *root_dir, char *filename, size_t size) 40 char *root_dir, char *filename, size_t size)
40{ 41{
41 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 42 char build_id_hex[SBUILD_ID_SIZE];
42 int ret = 0; 43 int ret = 0;
43 size_t len; 44 size_t len;
44 45
@@ -62,9 +63,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
62 } 63 }
63 break; 64 break;
64 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 65 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
65 /* skip the locally configured cache if a symfs is given */ 66 if (dso__build_id_filename(dso, filename, size) == NULL)
66 if (symbol_conf.symfs[0] ||
67 (dso__build_id_filename(dso, filename, size) == NULL))
68 ret = -1; 67 ret = -1;
69 break; 68 break;
70 69
@@ -1169,7 +1168,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1169 struct dso *pos; 1168 struct dso *pos;
1170 1169
1171 list_for_each_entry(pos, head, node) { 1170 list_for_each_entry(pos, head, node) {
1172 if (with_hits && !pos->hit) 1171 if (with_hits && !pos->hit && !dso__is_vdso(pos))
1173 continue; 1172 continue;
1174 if (pos->has_build_id) { 1173 if (pos->has_build_id) {
1175 have_build_id = true; 1174 have_build_id = true;
@@ -1301,7 +1300,7 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp)
1301 1300
1302size_t dso__fprintf_buildid(struct dso *dso, FILE *fp) 1301size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
1303{ 1302{
1304 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1303 char sbuild_id[SBUILD_ID_SIZE];
1305 1304
1306 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 1305 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1307 return fprintf(fp, "%s", sbuild_id); 1306 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..e82ba90cc969 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -44,6 +44,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
44 perf_evlist__set_maps(evlist, cpus, threads); 44 perf_evlist__set_maps(evlist, cpus, threads);
45 fdarray__init(&evlist->pollfd, 64); 45 fdarray__init(&evlist->pollfd, 64);
46 evlist->workload.pid = -1; 46 evlist->workload.pid = -1;
47 evlist->backward = false;
47} 48}
48 49
49struct perf_evlist *perf_evlist__new(void) 50struct perf_evlist *perf_evlist__new(void)
@@ -679,53 +680,79 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
679 return NULL; 680 return NULL;
680} 681}
681 682
682union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 683static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value)
684{
685 int i;
686
687 for (i = 0; i < evlist->nr_mmaps; i++) {
688 int fd = evlist->mmap[i].fd;
689 int err;
690
691 if (fd < 0)
692 continue;
693 err = ioctl(fd, PERF_EVENT_IOC_PAUSE_OUTPUT, value ? 1 : 0);
694 if (err)
695 return err;
696 }
697 return 0;
698}
699
700int perf_evlist__pause(struct perf_evlist *evlist)
701{
702 return perf_evlist__set_paused(evlist, true);
703}
704
705int perf_evlist__resume(struct perf_evlist *evlist)
706{
707 return perf_evlist__set_paused(evlist, false);
708}
709
710/* When check_messup is true, 'end' must points to a good entry */
711static union perf_event *
712perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
713 u64 end, u64 *prev)
683{ 714{
684 struct perf_mmap *md = &evlist->mmap[idx];
685 u64 head;
686 u64 old = md->prev;
687 unsigned char *data = md->base + page_size; 715 unsigned char *data = md->base + page_size;
688 union perf_event *event = NULL; 716 union perf_event *event = NULL;
717 int diff = end - start;
689 718
690 /* 719 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 /* 720 /*
699 * If we're further behind than half the buffer, there's a chance 721 * 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. 722 * the writer will bite our tail and mess up the samples under us.
701 * 723 *
702 * If we somehow ended up ahead of the head, we got messed up. 724 * If we somehow ended up ahead of the 'end', we got messed up.
703 * 725 *
704 * In either case, truncate and restart at head. 726 * In either case, truncate and restart at 'end'.
705 */ 727 */
706 int diff = head - old;
707 if (diff > md->mask / 2 || diff < 0) { 728 if (diff > md->mask / 2 || diff < 0) {
708 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); 729 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
709 730
710 /* 731 /*
711 * head points to a known good entry, start there. 732 * 'end' points to a known good entry, start there.
712 */ 733 */
713 old = head; 734 start = end;
735 diff = 0;
714 } 736 }
715 } 737 }
716 738
717 if (old != head) { 739 if (diff >= (int)sizeof(event->header)) {
718 size_t size; 740 size_t size;
719 741
720 event = (union perf_event *)&data[old & md->mask]; 742 event = (union perf_event *)&data[start & md->mask];
721 size = event->header.size; 743 size = event->header.size;
722 744
745 if (size < sizeof(event->header) || diff < (int)size) {
746 event = NULL;
747 goto broken_event;
748 }
749
723 /* 750 /*
724 * Event straddles the mmap boundary -- header should always 751 * Event straddles the mmap boundary -- header should always
725 * be inside due to u64 alignment of output. 752 * be inside due to u64 alignment of output.
726 */ 753 */
727 if ((old & md->mask) + size != ((old + size) & md->mask)) { 754 if ((start & md->mask) + size != ((start + size) & md->mask)) {
728 unsigned int offset = old; 755 unsigned int offset = start;
729 unsigned int len = min(sizeof(*event), size), cpy; 756 unsigned int len = min(sizeof(*event), size), cpy;
730 void *dst = md->event_copy; 757 void *dst = md->event_copy;
731 758
@@ -740,14 +767,83 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
740 event = (union perf_event *) md->event_copy; 767 event = (union perf_event *) md->event_copy;
741 } 768 }
742 769
743 old += size; 770 start += size;
744 } 771 }
745 772
746 md->prev = old; 773broken_event:
774 if (prev)
775 *prev = start;
747 776
748 return event; 777 return event;
749} 778}
750 779
780union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
781{
782 struct perf_mmap *md = &evlist->mmap[idx];
783 u64 head;
784 u64 old = md->prev;
785
786 /*
787 * Check if event was unmapped due to a POLLHUP/POLLERR.
788 */
789 if (!atomic_read(&md->refcnt))
790 return NULL;
791
792 head = perf_mmap__read_head(md);
793
794 return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev);
795}
796
797union perf_event *
798perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
799{
800 struct perf_mmap *md = &evlist->mmap[idx];
801 u64 head, end;
802 u64 start = md->prev;
803
804 /*
805 * Check if event was unmapped due to a POLLHUP/POLLERR.
806 */
807 if (!atomic_read(&md->refcnt))
808 return NULL;
809
810 head = perf_mmap__read_head(md);
811 if (!head)
812 return NULL;
813
814 /*
815 * 'head' pointer starts from 0. Kernel minus sizeof(record) form
816 * it each time when kernel writes to it, so in fact 'head' is
817 * negative. 'end' pointer is made manually by adding the size of
818 * the ring buffer to 'head' pointer, means the validate data can
819 * read is the whole ring buffer. If 'end' is positive, the ring
820 * buffer has not fully filled, so we must adjust 'end' to 0.
821 *
822 * However, since both 'head' and 'end' is unsigned, we can't
823 * simply compare 'end' against 0. Here we compare '-head' and
824 * the size of the ring buffer, where -head is the number of bytes
825 * kernel write to the ring buffer.
826 */
827 if (-head < (u64)(md->mask + 1))
828 end = 0;
829 else
830 end = head + md->mask + 1;
831
832 return perf_mmap__read(md, false, start, end, &md->prev);
833}
834
835void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
836{
837 struct perf_mmap *md = &evlist->mmap[idx];
838 u64 head;
839
840 if (!atomic_read(&md->refcnt))
841 return;
842
843 head = perf_mmap__read_head(md);
844 md->prev = head;
845}
846
751static bool perf_mmap__empty(struct perf_mmap *md) 847static bool perf_mmap__empty(struct perf_mmap *md)
752{ 848{
753 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; 849 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
@@ -813,6 +909,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
813 if (evlist->mmap[idx].base != NULL) { 909 if (evlist->mmap[idx].base != NULL) {
814 munmap(evlist->mmap[idx].base, evlist->mmap_len); 910 munmap(evlist->mmap[idx].base, evlist->mmap_len);
815 evlist->mmap[idx].base = NULL; 911 evlist->mmap[idx].base = NULL;
912 evlist->mmap[idx].fd = -1;
816 atomic_set(&evlist->mmap[idx].refcnt, 0); 913 atomic_set(&evlist->mmap[idx].refcnt, 0);
817 } 914 }
818 auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); 915 auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap);
@@ -833,10 +930,14 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
833 930
834static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 931static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
835{ 932{
933 int i;
934
836 evlist->nr_mmaps = cpu_map__nr(evlist->cpus); 935 evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
837 if (cpu_map__empty(evlist->cpus)) 936 if (cpu_map__empty(evlist->cpus))
838 evlist->nr_mmaps = thread_map__nr(evlist->threads); 937 evlist->nr_mmaps = thread_map__nr(evlist->threads);
839 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 938 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
939 for (i = 0; i < evlist->nr_mmaps; i++)
940 evlist->mmap[i].fd = -1;
840 return evlist->mmap != NULL ? 0 : -ENOMEM; 941 return evlist->mmap != NULL ? 0 : -ENOMEM;
841} 942}
842 943
@@ -873,6 +974,7 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
873 evlist->mmap[idx].base = NULL; 974 evlist->mmap[idx].base = NULL;
874 return -1; 975 return -1;
875 } 976 }
977 evlist->mmap[idx].fd = fd;
876 978
877 if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, 979 if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap,
878 &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) 980 &mp->auxtrace_mp, evlist->mmap[idx].base, fd))
@@ -986,26 +1088,34 @@ out_unmap:
986 return -1; 1088 return -1;
987} 1089}
988 1090
989static size_t perf_evlist__mmap_size(unsigned long pages) 1091unsigned long perf_event_mlock_kb_in_pages(void)
990{ 1092{
991 if (pages == UINT_MAX) { 1093 unsigned long pages;
992 int max; 1094 int max;
993 1095
994 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) { 1096 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
995 /* 1097 /*
996 * Pick a once upon a time good value, i.e. things look 1098 * 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 1099 * strange since we can't read a sysctl value, but lets not
998 * die yet... 1100 * die yet...
999 */ 1101 */
1000 max = 512; 1102 max = 512;
1001 } else { 1103 } else {
1002 max -= (page_size / 1024); 1104 max -= (page_size / 1024);
1003 } 1105 }
1106
1107 pages = (max * 1024) / page_size;
1108 if (!is_power_of_2(pages))
1109 pages = rounddown_pow_of_two(pages);
1110
1111 return pages;
1112}
1004 1113
1005 pages = (max * 1024) / page_size; 1114static size_t perf_evlist__mmap_size(unsigned long pages)
1006 if (!is_power_of_2(pages)) 1115{
1007 pages = rounddown_pow_of_two(pages); 1116 if (pages == UINT_MAX)
1008 } else if (!is_power_of_2(pages)) 1117 pages = perf_event_mlock_kb_in_pages();
1118 else if (!is_power_of_2(pages))
1009 return 0; 1119 return 0;
1010 1120
1011 return (pages + 1) * page_size; 1121 return (pages + 1) * page_size;
@@ -1192,6 +1302,24 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
1192 perf_evlist__propagate_maps(evlist); 1302 perf_evlist__propagate_maps(evlist);
1193} 1303}
1194 1304
1305void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
1306 enum perf_event_sample_format bit)
1307{
1308 struct perf_evsel *evsel;
1309
1310 evlist__for_each(evlist, evsel)
1311 __perf_evsel__set_sample_bit(evsel, bit);
1312}
1313
1314void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
1315 enum perf_event_sample_format bit)
1316{
1317 struct perf_evsel *evsel;
1318
1319 evlist__for_each(evlist, evsel)
1320 __perf_evsel__reset_sample_bit(evsel, bit);
1321}
1322
1195int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel) 1323int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
1196{ 1324{
1197 struct perf_evsel *evsel; 1325 struct perf_evsel *evsel;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a0d15221db6e..d740fb877ab6 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -28,6 +28,7 @@ struct record_opts;
28struct perf_mmap { 28struct perf_mmap {
29 void *base; 29 void *base;
30 int mask; 30 int mask;
31 int fd;
31 atomic_t refcnt; 32 atomic_t refcnt;
32 u64 prev; 33 u64 prev;
33 struct auxtrace_mmap auxtrace_mmap; 34 struct auxtrace_mmap auxtrace_mmap;
@@ -43,6 +44,7 @@ struct perf_evlist {
43 bool overwrite; 44 bool overwrite;
44 bool enabled; 45 bool enabled;
45 bool has_user_cpus; 46 bool has_user_cpus;
47 bool backward;
46 size_t mmap_len; 48 size_t mmap_len;
47 int id_pos; 49 int id_pos;
48 int is_pos; 50 int is_pos;
@@ -87,6 +89,17 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist);
87int perf_evlist__add_newtp(struct perf_evlist *evlist, 89int perf_evlist__add_newtp(struct perf_evlist *evlist,
88 const char *sys, const char *name, void *handler); 90 const char *sys, const char *name, void *handler);
89 91
92void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
93 enum perf_event_sample_format bit);
94void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
95 enum perf_event_sample_format bit);
96
97#define perf_evlist__set_sample_bit(evlist, bit) \
98 __perf_evlist__set_sample_bit(evlist, PERF_SAMPLE_##bit)
99
100#define perf_evlist__reset_sample_bit(evlist, bit) \
101 __perf_evlist__reset_sample_bit(evlist, PERF_SAMPLE_##bit)
102
90int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); 103int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
91int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid); 104int 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); 105int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);
@@ -118,16 +131,25 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
118 131
119union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); 132union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
120 133
134union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
135 int idx);
136void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
137
121void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 138void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
122 139
140int perf_evlist__pause(struct perf_evlist *evlist);
141int perf_evlist__resume(struct perf_evlist *evlist);
123int perf_evlist__open(struct perf_evlist *evlist); 142int perf_evlist__open(struct perf_evlist *evlist);
124void perf_evlist__close(struct perf_evlist *evlist); 143void perf_evlist__close(struct perf_evlist *evlist);
125 144
145struct callchain_param;
146
126void perf_evlist__set_id_pos(struct perf_evlist *evlist); 147void perf_evlist__set_id_pos(struct perf_evlist *evlist);
127bool perf_can_sample_identifier(void); 148bool perf_can_sample_identifier(void);
128bool perf_can_record_switch_events(void); 149bool perf_can_record_switch_events(void);
129bool perf_can_record_cpu_wide(void); 150bool perf_can_record_cpu_wide(void);
130void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts); 151void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
152 struct callchain_param *callchain);
131int record_opts__config(struct record_opts *opts); 153int record_opts__config(struct record_opts *opts);
132 154
133int perf_evlist__prepare_workload(struct perf_evlist *evlist, 155int perf_evlist__prepare_workload(struct perf_evlist *evlist,
@@ -144,6 +166,8 @@ int perf_evlist__parse_mmap_pages(const struct option *opt,
144 const char *str, 166 const char *str,
145 int unset); 167 int unset);
146 168
169unsigned long perf_event_mlock_kb_in_pages(void);
170
147int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, 171int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
148 bool overwrite, unsigned int auxtrace_pages, 172 bool overwrite, unsigned int auxtrace_pages,
149 bool auxtrace_overwrite); 173 bool auxtrace_overwrite);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 738ce226002b..5d7037ef7d3b 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -37,6 +37,7 @@ static struct {
37 bool clockid; 37 bool clockid;
38 bool clockid_wrong; 38 bool clockid_wrong;
39 bool lbr_flags; 39 bool lbr_flags;
40 bool write_backward;
40} perf_missing_features; 41} perf_missing_features;
41 42
42static clockid_t clockid; 43static clockid_t clockid;
@@ -226,7 +227,8 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
226 perf_evsel__init(evsel, attr, idx); 227 perf_evsel__init(evsel, attr, idx);
227 228
228 if (perf_evsel__is_bpf_output(evsel)) { 229 if (perf_evsel__is_bpf_output(evsel)) {
229 evsel->attr.sample_type |= PERF_SAMPLE_RAW; 230 evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
231 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
230 evsel->attr.sample_period = 1; 232 evsel->attr.sample_period = 1;
231 } 233 }
232 234
@@ -561,10 +563,9 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
561 return ret; 563 return ret;
562} 564}
563 565
564static void 566void perf_evsel__config_callchain(struct perf_evsel *evsel,
565perf_evsel__config_callgraph(struct perf_evsel *evsel, 567 struct record_opts *opts,
566 struct record_opts *opts, 568 struct callchain_param *param)
567 struct callchain_param *param)
568{ 569{
569 bool function = perf_evsel__is_function_event(evsel); 570 bool function = perf_evsel__is_function_event(evsel);
570 struct perf_event_attr *attr = &evsel->attr; 571 struct perf_event_attr *attr = &evsel->attr;
@@ -704,7 +705,7 @@ static void apply_config_terms(struct perf_evsel *evsel,
704 705
705 /* set perf-event callgraph */ 706 /* set perf-event callgraph */
706 if (param.enabled) 707 if (param.enabled)
707 perf_evsel__config_callgraph(evsel, opts, &param); 708 perf_evsel__config_callchain(evsel, opts, &param);
708 } 709 }
709} 710}
710 711
@@ -736,7 +737,8 @@ static void apply_config_terms(struct perf_evsel *evsel,
736 * enable/disable events specifically, as there's no 737 * enable/disable events specifically, as there's no
737 * initial traced exec call. 738 * initial traced exec call.
738 */ 739 */
739void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) 740void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
741 struct callchain_param *callchain)
740{ 742{
741 struct perf_evsel *leader = evsel->leader; 743 struct perf_evsel *leader = evsel->leader;
742 struct perf_event_attr *attr = &evsel->attr; 744 struct perf_event_attr *attr = &evsel->attr;
@@ -811,8 +813,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
811 if (perf_evsel__is_function_event(evsel)) 813 if (perf_evsel__is_function_event(evsel))
812 evsel->attr.exclude_callchain_user = 1; 814 evsel->attr.exclude_callchain_user = 1;
813 815
814 if (callchain_param.enabled && !evsel->no_aux_samples) 816 if (callchain && callchain->enabled && !evsel->no_aux_samples)
815 perf_evsel__config_callgraph(evsel, opts, &callchain_param); 817 perf_evsel__config_callchain(evsel, opts, callchain);
816 818
817 if (opts->sample_intr_regs) { 819 if (opts->sample_intr_regs) {
818 attr->sample_regs_intr = opts->sample_intr_regs; 820 attr->sample_regs_intr = opts->sample_intr_regs;
@@ -826,7 +828,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
826 perf_evsel__set_sample_bit(evsel, PERIOD); 828 perf_evsel__set_sample_bit(evsel, PERIOD);
827 829
828 /* 830 /*
829 * When the user explicitely disabled time don't force it here. 831 * When the user explicitly disabled time don't force it here.
830 */ 832 */
831 if (opts->sample_time && 833 if (opts->sample_time &&
832 (!perf_missing_features.sample_id_all && 834 (!perf_missing_features.sample_id_all &&
@@ -1230,6 +1232,21 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1230 __p_bits(buf, size, value, bits); 1232 __p_bits(buf, size, value, bits);
1231} 1233}
1232 1234
1235static void __p_branch_sample_type(char *buf, size_t size, u64 value)
1236{
1237#define bit_name(n) { PERF_SAMPLE_BRANCH_##n, #n }
1238 struct bit_names bits[] = {
1239 bit_name(USER), bit_name(KERNEL), bit_name(HV), bit_name(ANY),
1240 bit_name(ANY_CALL), bit_name(ANY_RETURN), bit_name(IND_CALL),
1241 bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX),
1242 bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP),
1243 bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES),
1244 { .name = NULL, }
1245 };
1246#undef bit_name
1247 __p_bits(buf, size, value, bits);
1248}
1249
1233static void __p_read_format(char *buf, size_t size, u64 value) 1250static void __p_read_format(char *buf, size_t size, u64 value)
1234{ 1251{
1235#define bit_name(n) { PERF_FORMAT_##n, #n } 1252#define bit_name(n) { PERF_FORMAT_##n, #n }
@@ -1248,6 +1265,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)) 1265#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)) 1266#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) 1267#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)
1268#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) 1269#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val)
1252 1270
1253#define PRINT_ATTRn(_n, _f, _p) \ 1271#define PRINT_ATTRn(_n, _f, _p) \
@@ -1299,12 +1317,13 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1299 PRINT_ATTRf(comm_exec, p_unsigned); 1317 PRINT_ATTRf(comm_exec, p_unsigned);
1300 PRINT_ATTRf(use_clockid, p_unsigned); 1318 PRINT_ATTRf(use_clockid, p_unsigned);
1301 PRINT_ATTRf(context_switch, p_unsigned); 1319 PRINT_ATTRf(context_switch, p_unsigned);
1320 PRINT_ATTRf(write_backward, p_unsigned);
1302 1321
1303 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); 1322 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
1304 PRINT_ATTRf(bp_type, p_unsigned); 1323 PRINT_ATTRf(bp_type, p_unsigned);
1305 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); 1324 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
1306 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); 1325 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
1307 PRINT_ATTRf(branch_sample_type, p_unsigned); 1326 PRINT_ATTRf(branch_sample_type, p_branch_sample_type);
1308 PRINT_ATTRf(sample_regs_user, p_hex); 1327 PRINT_ATTRf(sample_regs_user, p_hex);
1309 PRINT_ATTRf(sample_stack_user, p_unsigned); 1328 PRINT_ATTRf(sample_stack_user, p_unsigned);
1310 PRINT_ATTRf(clockid, p_signed); 1329 PRINT_ATTRf(clockid, p_signed);
@@ -1358,6 +1377,8 @@ fallback_missing_features:
1358 if (perf_missing_features.lbr_flags) 1377 if (perf_missing_features.lbr_flags)
1359 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | 1378 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
1360 PERF_SAMPLE_BRANCH_NO_CYCLES); 1379 PERF_SAMPLE_BRANCH_NO_CYCLES);
1380 if (perf_missing_features.write_backward)
1381 evsel->attr.write_backward = false;
1361retry_sample_id: 1382retry_sample_id:
1362 if (perf_missing_features.sample_id_all) 1383 if (perf_missing_features.sample_id_all)
1363 evsel->attr.sample_id_all = 0; 1384 evsel->attr.sample_id_all = 0;
@@ -1420,6 +1441,12 @@ retry_open:
1420 err = -EINVAL; 1441 err = -EINVAL;
1421 goto out_close; 1442 goto out_close;
1422 } 1443 }
1444
1445 if (evsel->overwrite &&
1446 perf_missing_features.write_backward) {
1447 err = -EINVAL;
1448 goto out_close;
1449 }
1423 } 1450 }
1424 } 1451 }
1425 1452
@@ -1482,6 +1509,10 @@ try_fallback:
1482 PERF_SAMPLE_BRANCH_NO_FLAGS))) { 1509 PERF_SAMPLE_BRANCH_NO_FLAGS))) {
1483 perf_missing_features.lbr_flags = true; 1510 perf_missing_features.lbr_flags = true;
1484 goto fallback_missing_features; 1511 goto fallback_missing_features;
1512 } else if (!perf_missing_features.write_backward &&
1513 evsel->attr.write_backward) {
1514 perf_missing_features.write_backward = true;
1515 goto fallback_missing_features;
1485 } 1516 }
1486 1517
1487out_close: 1518out_close:
@@ -2253,98 +2284,11 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2253 return 0; 2284 return 0;
2254} 2285}
2255 2286
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, 2287bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2346 char *msg, size_t msgsize) 2288 char *msg, size_t msgsize)
2347{ 2289{
2290 int paranoid;
2291
2348 if ((err == ENOENT || err == ENXIO || err == ENODEV) && 2292 if ((err == ENOENT || err == ENXIO || err == ENODEV) &&
2349 evsel->attr.type == PERF_TYPE_HARDWARE && 2293 evsel->attr.type == PERF_TYPE_HARDWARE &&
2350 evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) { 2294 evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) {
@@ -2364,6 +2308,22 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2364 2308
2365 zfree(&evsel->name); 2309 zfree(&evsel->name);
2366 return true; 2310 return true;
2311 } else if (err == EACCES && !evsel->attr.exclude_kernel &&
2312 (paranoid = perf_event_paranoid()) > 1) {
2313 const char *name = perf_evsel__name(evsel);
2314 char *new_name;
2315
2316 if (asprintf(&new_name, "%s%su", name, strchr(name, ':') ? "" : ":") < 0)
2317 return false;
2318
2319 if (evsel->name)
2320 free(evsel->name);
2321 evsel->name = new_name;
2322 scnprintf(msg, msgsize,
2323"kernel.perf_event_paranoid=%d, trying to fall back to excluding kernel samples", paranoid);
2324 evsel->attr.exclude_kernel = 1;
2325
2326 return true;
2367 } 2327 }
2368 2328
2369 return false; 2329 return false;
@@ -2382,12 +2342,13 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2382 "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n" 2342 "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n"
2383 "which controls use of the performance events system by\n" 2343 "which controls use of the performance events system by\n"
2384 "unprivileged users (without CAP_SYS_ADMIN).\n\n" 2344 "unprivileged users (without CAP_SYS_ADMIN).\n\n"
2385 "The default value is 1:\n\n" 2345 "The current value is %d:\n\n"
2386 " -1: Allow use of (almost) all events by all users\n" 2346 " -1: Allow use of (almost) all events by all users\n"
2387 ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n" 2347 ">= 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" 2348 ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n"
2389 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN", 2349 ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN",
2390 target->system_wide ? "system-wide " : ""); 2350 target->system_wide ? "system-wide " : "",
2351 perf_event_paranoid());
2391 case ENOENT: 2352 case ENOENT:
2392 return scnprintf(msg, size, "The %s event is not supported.", 2353 return scnprintf(msg, size, "The %s event is not supported.",
2393 perf_evsel__name(evsel)); 2354 perf_evsel__name(evsel));
@@ -2397,10 +2358,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" 2358 "Probably the maximum number of open file descriptors has been reached.\n"
2398 "Hint: Try again after reducing the number of events.\n" 2359 "Hint: Try again after reducing the number of events.\n"
2399 "Hint: Try increasing the limit with 'ulimit -n <limit>'"); 2360 "Hint: Try increasing the limit with 'ulimit -n <limit>'");
2361 case ENOMEM:
2362 if ((evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0 &&
2363 access("/proc/sys/kernel/perf_event_max_stack", F_OK) == 0)
2364 return scnprintf(msg, size,
2365 "Not enough memory to setup event with callchain.\n"
2366 "Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n"
2367 "Hint: Current value: %d", sysctl_perf_event_max_stack);
2368 break;
2400 case ENODEV: 2369 case ENODEV:
2401 if (target->cpu_list) 2370 if (target->cpu_list)
2402 return scnprintf(msg, size, "%s", 2371 return scnprintf(msg, size, "%s",
2403 "No such device - did you specify an out-of-range profile CPU?\n"); 2372 "No such device - did you specify an out-of-range profile CPU?");
2404 break; 2373 break;
2405 case EOPNOTSUPP: 2374 case EOPNOTSUPP:
2406 if (evsel->attr.precise_ip) 2375 if (evsel->attr.precise_ip)
@@ -2432,7 +2401,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2432 return scnprintf(msg, size, 2401 return scnprintf(msg, size,
2433 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" 2402 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2434 "/bin/dmesg may provide additional information.\n" 2403 "/bin/dmesg may provide additional information.\n"
2435 "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 2404 "No CONFIG_PERF_EVENTS=y kernel support configured?",
2436 err, strerror_r(err, sbuf, sizeof(sbuf)), 2405 err, strerror_r(err, sbuf, sizeof(sbuf)),
2437 perf_evsel__name(evsel)); 2406 perf_evsel__name(evsel));
2438} 2407}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 501ea6e565f1..c1f10159804c 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -112,6 +112,7 @@ struct perf_evsel {
112 bool tracking; 112 bool tracking;
113 bool per_pkg; 113 bool per_pkg;
114 bool precise_max; 114 bool precise_max;
115 bool overwrite;
115 /* parse modifier helper */ 116 /* parse modifier helper */
116 int exclude_GH; 117 int exclude_GH;
117 int nr_members; 118 int nr_members;
@@ -178,8 +179,14 @@ void perf_evsel__init(struct perf_evsel *evsel,
178void perf_evsel__exit(struct perf_evsel *evsel); 179void perf_evsel__exit(struct perf_evsel *evsel);
179void perf_evsel__delete(struct perf_evsel *evsel); 180void perf_evsel__delete(struct perf_evsel *evsel);
180 181
182struct callchain_param;
183
181void perf_evsel__config(struct perf_evsel *evsel, 184void perf_evsel__config(struct perf_evsel *evsel,
182 struct record_opts *opts); 185 struct record_opts *opts,
186 struct callchain_param *callchain);
187void perf_evsel__config_callchain(struct perf_evsel *evsel,
188 struct record_opts *opts,
189 struct callchain_param *callchain);
183 190
184int __perf_evsel__sample_size(u64 sample_type); 191int __perf_evsel__sample_size(u64 sample_type);
185void perf_evsel__calc_id_pos(struct perf_evsel *evsel); 192void perf_evsel__calc_id_pos(struct perf_evsel *evsel);
@@ -381,6 +388,24 @@ struct perf_attr_details {
381int perf_evsel__fprintf(struct perf_evsel *evsel, 388int perf_evsel__fprintf(struct perf_evsel *evsel,
382 struct perf_attr_details *details, FILE *fp); 389 struct perf_attr_details *details, FILE *fp);
383 390
391#define EVSEL__PRINT_IP (1<<0)
392#define EVSEL__PRINT_SYM (1<<1)
393#define EVSEL__PRINT_DSO (1<<2)
394#define EVSEL__PRINT_SYMOFFSET (1<<3)
395#define EVSEL__PRINT_ONELINE (1<<4)
396#define EVSEL__PRINT_SRCLINE (1<<5)
397#define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6)
398
399struct callchain_cursor;
400
401int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
402 unsigned int print_opts,
403 struct callchain_cursor *cursor, FILE *fp);
404
405int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
406 int left_alignment, unsigned int print_opts,
407 struct callchain_cursor *cursor, FILE *fp);
408
384bool perf_evsel__fallback(struct perf_evsel *evsel, int err, 409bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
385 char *msg, size_t msgsize); 410 char *msg, size_t msgsize);
386int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 411int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
@@ -396,7 +421,7 @@ for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \
396 (_evsel) && (_evsel)->leader == (_leader); \ 421 (_evsel) && (_evsel)->leader == (_leader); \
397 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) 422 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
398 423
399static inline bool has_branch_callstack(struct perf_evsel *evsel) 424static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel)
400{ 425{
401 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; 426 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
402} 427}
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..d1f19e0012d4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -117,6 +117,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
117 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); 117 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
118 hists__set_unres_dso_col_len(hists, HISTC_DSO_TO); 118 hists__set_unres_dso_col_len(hists, HISTC_DSO_TO);
119 } 119 }
120
121 if (h->branch_info->srcline_from)
122 hists__new_col_len(hists, HISTC_SRCLINE_FROM,
123 strlen(h->branch_info->srcline_from));
124 if (h->branch_info->srcline_to)
125 hists__new_col_len(hists, HISTC_SRCLINE_TO,
126 strlen(h->branch_info->srcline_to));
120 } 127 }
121 128
122 if (h->mem_info) { 129 if (h->mem_info) {
@@ -295,7 +302,7 @@ static void hists__delete_entry(struct hists *hists, struct hist_entry *he)
295 root_in = &he->parent_he->hroot_in; 302 root_in = &he->parent_he->hroot_in;
296 root_out = &he->parent_he->hroot_out; 303 root_out = &he->parent_he->hroot_out;
297 } else { 304 } else {
298 if (sort__need_collapse) 305 if (hists__has(hists, need_collapse))
299 root_in = &hists->entries_collapsed; 306 root_in = &hists->entries_collapsed;
300 else 307 else
301 root_in = hists->entries_in; 308 root_in = hists->entries_in;
@@ -953,7 +960,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
953{ 960{
954 int err, err2; 961 int err, err2;
955 962
956 err = sample__resolve_callchain(iter->sample, &iter->parent, 963 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
957 iter->evsel, al, max_stack_depth); 964 iter->evsel, al, max_stack_depth);
958 if (err) 965 if (err)
959 return err; 966 return err;
@@ -1042,6 +1049,8 @@ void hist_entry__delete(struct hist_entry *he)
1042 if (he->branch_info) { 1049 if (he->branch_info) {
1043 map__zput(he->branch_info->from.map); 1050 map__zput(he->branch_info->from.map);
1044 map__zput(he->branch_info->to.map); 1051 map__zput(he->branch_info->to.map);
1052 free_srcline(he->branch_info->srcline_from);
1053 free_srcline(he->branch_info->srcline_to);
1045 zfree(&he->branch_info); 1054 zfree(&he->branch_info);
1046 } 1055 }
1047 1056
@@ -1295,8 +1304,9 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
1295 return ret; 1304 return ret;
1296} 1305}
1297 1306
1298int hists__collapse_insert_entry(struct hists *hists, struct rb_root *root, 1307static int hists__collapse_insert_entry(struct hists *hists,
1299 struct hist_entry *he) 1308 struct rb_root *root,
1309 struct hist_entry *he)
1300{ 1310{
1301 struct rb_node **p = &root->rb_node; 1311 struct rb_node **p = &root->rb_node;
1302 struct rb_node *parent = NULL; 1312 struct rb_node *parent = NULL;
@@ -1372,7 +1382,7 @@ int hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
1372 struct hist_entry *n; 1382 struct hist_entry *n;
1373 int ret; 1383 int ret;
1374 1384
1375 if (!sort__need_collapse) 1385 if (!hists__has(hists, need_collapse))
1376 return 0; 1386 return 0;
1377 1387
1378 hists->nr_entries = 0; 1388 hists->nr_entries = 0;
@@ -1631,7 +1641,7 @@ static void output_resort(struct hists *hists, struct ui_progress *prog,
1631 return; 1641 return;
1632 } 1642 }
1633 1643
1634 if (sort__need_collapse) 1644 if (hists__has(hists, need_collapse))
1635 root = &hists->entries_collapsed; 1645 root = &hists->entries_collapsed;
1636 else 1646 else
1637 root = hists->entries_in; 1647 root = hists->entries_in;
@@ -2035,7 +2045,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
2035 struct hist_entry *he; 2045 struct hist_entry *he;
2036 int64_t cmp; 2046 int64_t cmp;
2037 2047
2038 if (sort__need_collapse) 2048 if (hists__has(hists, need_collapse))
2039 root = &hists->entries_collapsed; 2049 root = &hists->entries_collapsed;
2040 else 2050 else
2041 root = hists->entries_in; 2051 root = hists->entries_in;
@@ -2061,6 +2071,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
2061 if (he) { 2071 if (he) {
2062 memset(&he->stat, 0, sizeof(he->stat)); 2072 memset(&he->stat, 0, sizeof(he->stat));
2063 he->hists = hists; 2073 he->hists = hists;
2074 if (symbol_conf.cumulate_callchain)
2075 memset(he->stat_acc, 0, sizeof(he->stat));
2064 rb_link_node(&he->rb_node_in, parent, p); 2076 rb_link_node(&he->rb_node_in, parent, p);
2065 rb_insert_color(&he->rb_node_in, root); 2077 rb_insert_color(&he->rb_node_in, root);
2066 hists__inc_stats(hists, he); 2078 hists__inc_stats(hists, he);
@@ -2075,7 +2087,7 @@ static struct hist_entry *hists__find_entry(struct hists *hists,
2075{ 2087{
2076 struct rb_node *n; 2088 struct rb_node *n;
2077 2089
2078 if (sort__need_collapse) 2090 if (hists__has(hists, need_collapse))
2079 n = hists->entries_collapsed.rb_node; 2091 n = hists->entries_collapsed.rb_node;
2080 else 2092 else
2081 n = hists->entries_in->rb_node; 2093 n = hists->entries_in->rb_node;
@@ -2104,7 +2116,7 @@ void hists__match(struct hists *leader, struct hists *other)
2104 struct rb_node *nd; 2116 struct rb_node *nd;
2105 struct hist_entry *pos, *pair; 2117 struct hist_entry *pos, *pair;
2106 2118
2107 if (sort__need_collapse) 2119 if (hists__has(leader, need_collapse))
2108 root = &leader->entries_collapsed; 2120 root = &leader->entries_collapsed;
2109 else 2121 else
2110 root = leader->entries_in; 2122 root = leader->entries_in;
@@ -2129,7 +2141,7 @@ int hists__link(struct hists *leader, struct hists *other)
2129 struct rb_node *nd; 2141 struct rb_node *nd;
2130 struct hist_entry *pos, *pair; 2142 struct hist_entry *pos, *pair;
2131 2143
2132 if (sort__need_collapse) 2144 if (hists__has(other, need_collapse))
2133 root = &other->entries_collapsed; 2145 root = &other->entries_collapsed;
2134 else 2146 else
2135 root = other->entries_in; 2147 root = other->entries_in;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index bec0cd660fbd..7b54ccf1b737 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,6 +52,8 @@ enum hist_column {
52 HISTC_MEM_IADDR_SYMBOL, 52 HISTC_MEM_IADDR_SYMBOL,
53 HISTC_TRANSACTION, 53 HISTC_TRANSACTION,
54 HISTC_CYCLES, 54 HISTC_CYCLES,
55 HISTC_SRCLINE_FROM,
56 HISTC_SRCLINE_TO,
55 HISTC_TRACE, 57 HISTC_TRACE,
56 HISTC_NR_COLS, /* Last entry */ 58 HISTC_NR_COLS, /* Last entry */
57}; 59};
@@ -82,6 +84,8 @@ struct hists {
82 int nr_hpp_node; 84 int nr_hpp_node;
83}; 85};
84 86
87#define hists__has(__h, __f) (__h)->hpp_list->__f
88
85struct hist_entry_iter; 89struct hist_entry_iter;
86 90
87struct hist_iter_ops { 91struct hist_iter_ops {
@@ -199,8 +203,6 @@ int hists__init(void);
199int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list); 203int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list);
200 204
201struct rb_root *hists__get_rotate_entries_in(struct hists *hists); 205struct 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 206
205struct perf_hpp { 207struct perf_hpp {
206 char *buf; 208 char *buf;
@@ -240,6 +242,14 @@ struct perf_hpp_fmt {
240struct perf_hpp_list { 242struct perf_hpp_list {
241 struct list_head fields; 243 struct list_head fields;
242 struct list_head sorts; 244 struct list_head sorts;
245
246 int need_collapse;
247 int parent;
248 int sym;
249 int dso;
250 int socket;
251 int thread;
252 int comm;
243}; 253};
244 254
245extern struct perf_hpp_list perf_hpp_list; 255extern 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 617578440989..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);
@@ -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..b1772180c820 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
@@ -42,6 +43,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
42 43
43 machine->symbol_filter = NULL; 44 machine->symbol_filter = NULL;
44 machine->id_hdr_size = 0; 45 machine->id_hdr_size = 0;
46 machine->kptr_restrict_warned = false;
45 machine->comm_exec = false; 47 machine->comm_exec = false;
46 machine->kernel_start = 0; 48 machine->kernel_start = 0;
47 49
@@ -361,7 +363,7 @@ out_err:
361} 363}
362 364
363/* 365/*
364 * Caller must eventually drop thread->refcnt returned with a successfull 366 * Caller must eventually drop thread->refcnt returned with a successful
365 * lookup/new thread inserted. 367 * lookup/new thread inserted.
366 */ 368 */
367static struct thread *____machine__findnew_thread(struct machine *machine, 369static struct thread *____machine__findnew_thread(struct machine *machine,
@@ -430,6 +432,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
430 */ 432 */
431 thread__get(th); 433 thread__get(th);
432 machine->last_match = th; 434 machine->last_match = th;
435 ++machine->nr_threads;
433 } 436 }
434 437
435 return th; 438 return th;
@@ -681,11 +684,13 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
681 684
682size_t machine__fprintf(struct machine *machine, FILE *fp) 685size_t machine__fprintf(struct machine *machine, FILE *fp)
683{ 686{
684 size_t ret = 0; 687 size_t ret;
685 struct rb_node *nd; 688 struct rb_node *nd;
686 689
687 pthread_rwlock_rdlock(&machine->threads_lock); 690 pthread_rwlock_rdlock(&machine->threads_lock);
688 691
692 ret = fprintf(fp, "Threads: %u\n", machine->nr_threads);
693
689 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) { 694 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
690 struct thread *pos = rb_entry(nd, struct thread, rb_node); 695 struct thread *pos = rb_entry(nd, struct thread, rb_node);
691 696
@@ -705,7 +710,7 @@ static struct dso *machine__get_kernel(struct machine *machine)
705 if (machine__is_host(machine)) { 710 if (machine__is_host(machine)) {
706 vmlinux_name = symbol_conf.vmlinux_name; 711 vmlinux_name = symbol_conf.vmlinux_name;
707 if (!vmlinux_name) 712 if (!vmlinux_name)
708 vmlinux_name = "[kernel.kallsyms]"; 713 vmlinux_name = DSO__NAME_KALLSYMS;
709 714
710 kernel = machine__findnew_kernel(machine, vmlinux_name, 715 kernel = machine__findnew_kernel(machine, vmlinux_name,
711 "[kernel]", DSO_TYPE_KERNEL); 716 "[kernel]", DSO_TYPE_KERNEL);
@@ -908,11 +913,11 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
908 return machine__create_kernel_maps(machine); 913 return machine__create_kernel_maps(machine);
909} 914}
910 915
911int machine__load_kallsyms(struct machine *machine, const char *filename, 916int __machine__load_kallsyms(struct machine *machine, const char *filename,
912 enum map_type type, symbol_filter_t filter) 917 enum map_type type, bool no_kcore, symbol_filter_t filter)
913{ 918{
914 struct map *map = machine__kernel_map(machine); 919 struct map *map = machine__kernel_map(machine);
915 int ret = dso__load_kallsyms(map->dso, filename, map, filter); 920 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore, filter);
916 921
917 if (ret > 0) { 922 if (ret > 0) {
918 dso__set_loaded(map->dso, type); 923 dso__set_loaded(map->dso, type);
@@ -927,6 +932,12 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
927 return ret; 932 return ret;
928} 933}
929 934
935int machine__load_kallsyms(struct machine *machine, const char *filename,
936 enum map_type type, symbol_filter_t filter)
937{
938 return __machine__load_kallsyms(machine, filename, type, false, filter);
939}
940
930int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 941int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
931 symbol_filter_t filter) 942 symbol_filter_t filter)
932{ 943{
@@ -1125,10 +1136,10 @@ int machine__create_kernel_maps(struct machine *machine)
1125{ 1136{
1126 struct dso *kernel = machine__get_kernel(machine); 1137 struct dso *kernel = machine__get_kernel(machine);
1127 const char *name; 1138 const char *name;
1128 u64 addr = machine__get_running_kernel_start(machine, &name); 1139 u64 addr;
1129 int ret; 1140 int ret;
1130 1141
1131 if (!addr || kernel == NULL) 1142 if (kernel == NULL)
1132 return -1; 1143 return -1;
1133 1144
1134 ret = __machine__create_kernel_maps(machine, kernel); 1145 ret = __machine__create_kernel_maps(machine, kernel);
@@ -1150,8 +1161,9 @@ int machine__create_kernel_maps(struct machine *machine)
1150 */ 1161 */
1151 map_groups__fixup_end(&machine->kmaps); 1162 map_groups__fixup_end(&machine->kmaps);
1152 1163
1153 if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, 1164 addr = machine__get_running_kernel_start(machine, &name);
1154 addr)) { 1165 if (!addr) {
1166 } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
1155 machine__destroy_kernel_maps(machine); 1167 machine__destroy_kernel_maps(machine);
1156 return -1; 1168 return -1;
1157 } 1169 }
@@ -1413,6 +1425,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
1413 pthread_rwlock_wrlock(&machine->threads_lock); 1425 pthread_rwlock_wrlock(&machine->threads_lock);
1414 rb_erase_init(&th->rb_node, &machine->threads); 1426 rb_erase_init(&th->rb_node, &machine->threads);
1415 RB_CLEAR_NODE(&th->rb_node); 1427 RB_CLEAR_NODE(&th->rb_node);
1428 --machine->nr_threads;
1416 /* 1429 /*
1417 * Move it first to the dead_threads list, then drop the reference, 1430 * Move it first to the dead_threads list, then drop the reference,
1418 * if this is the last reference, then the thread__delete destructor 1431 * if this is the last reference, then the thread__delete destructor
@@ -1599,6 +1612,7 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1599} 1612}
1600 1613
1601static int add_callchain_ip(struct thread *thread, 1614static int add_callchain_ip(struct thread *thread,
1615 struct callchain_cursor *cursor,
1602 struct symbol **parent, 1616 struct symbol **parent,
1603 struct addr_location *root_al, 1617 struct addr_location *root_al,
1604 u8 *cpumode, 1618 u8 *cpumode,
@@ -1630,7 +1644,7 @@ static int add_callchain_ip(struct thread *thread,
1630 * It seems the callchain is corrupted. 1644 * It seems the callchain is corrupted.
1631 * Discard all. 1645 * Discard all.
1632 */ 1646 */
1633 callchain_cursor_reset(&callchain_cursor); 1647 callchain_cursor_reset(cursor);
1634 return 1; 1648 return 1;
1635 } 1649 }
1636 return 0; 1650 return 0;
@@ -1640,7 +1654,7 @@ static int add_callchain_ip(struct thread *thread,
1640 } 1654 }
1641 1655
1642 if (al.sym != NULL) { 1656 if (al.sym != NULL) {
1643 if (sort__has_parent && !*parent && 1657 if (perf_hpp_list.parent && !*parent &&
1644 symbol__match_regex(al.sym, &parent_regex)) 1658 symbol__match_regex(al.sym, &parent_regex))
1645 *parent = al.sym; 1659 *parent = al.sym;
1646 else if (have_ignore_callees && root_al && 1660 else if (have_ignore_callees && root_al &&
@@ -1648,13 +1662,13 @@ static int add_callchain_ip(struct thread *thread,
1648 /* Treat this symbol as the root, 1662 /* Treat this symbol as the root,
1649 forgetting its callees. */ 1663 forgetting its callees. */
1650 *root_al = al; 1664 *root_al = al;
1651 callchain_cursor_reset(&callchain_cursor); 1665 callchain_cursor_reset(cursor);
1652 } 1666 }
1653 } 1667 }
1654 1668
1655 if (symbol_conf.hide_unresolved && al.sym == NULL) 1669 if (symbol_conf.hide_unresolved && al.sym == NULL)
1656 return 0; 1670 return 0;
1657 return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym); 1671 return callchain_cursor_append(cursor, al.addr, al.map, al.sym);
1658} 1672}
1659 1673
1660struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1674struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1724,6 +1738,7 @@ static int remove_loops(struct branch_entry *l, int nr)
1724 * negative error code on other errors. 1738 * negative error code on other errors.
1725 */ 1739 */
1726static int resolve_lbr_callchain_sample(struct thread *thread, 1740static int resolve_lbr_callchain_sample(struct thread *thread,
1741 struct callchain_cursor *cursor,
1727 struct perf_sample *sample, 1742 struct perf_sample *sample,
1728 struct symbol **parent, 1743 struct symbol **parent,
1729 struct addr_location *root_al, 1744 struct addr_location *root_al,
@@ -1756,11 +1771,6 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1756 */ 1771 */
1757 int mix_chain_nr = i + 1 + lbr_nr + 1; 1772 int mix_chain_nr = i + 1 + lbr_nr + 1;
1758 1773
1759 if (mix_chain_nr > PERF_MAX_STACK_DEPTH + PERF_MAX_BRANCH_DEPTH) {
1760 pr_warning("corrupted callchain. skipping...\n");
1761 return 0;
1762 }
1763
1764 for (j = 0; j < mix_chain_nr; j++) { 1774 for (j = 0; j < mix_chain_nr; j++) {
1765 if (callchain_param.order == ORDER_CALLEE) { 1775 if (callchain_param.order == ORDER_CALLEE) {
1766 if (j < i + 1) 1776 if (j < i + 1)
@@ -1778,7 +1788,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1778 ip = lbr_stack->entries[0].to; 1788 ip = lbr_stack->entries[0].to;
1779 } 1789 }
1780 1790
1781 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); 1791 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
1782 if (err) 1792 if (err)
1783 return (err < 0) ? err : 0; 1793 return (err < 0) ? err : 0;
1784 } 1794 }
@@ -1789,6 +1799,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1789} 1799}
1790 1800
1791static int thread__resolve_callchain_sample(struct thread *thread, 1801static int thread__resolve_callchain_sample(struct thread *thread,
1802 struct callchain_cursor *cursor,
1792 struct perf_evsel *evsel, 1803 struct perf_evsel *evsel,
1793 struct perf_sample *sample, 1804 struct perf_sample *sample,
1794 struct symbol **parent, 1805 struct symbol **parent,
@@ -1797,16 +1808,14 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1797{ 1808{
1798 struct branch_stack *branch = sample->branch_stack; 1809 struct branch_stack *branch = sample->branch_stack;
1799 struct ip_callchain *chain = sample->callchain; 1810 struct ip_callchain *chain = sample->callchain;
1800 int chain_nr = min(max_stack, (int)chain->nr); 1811 int chain_nr = chain->nr;
1801 u8 cpumode = PERF_RECORD_MISC_USER; 1812 u8 cpumode = PERF_RECORD_MISC_USER;
1802 int i, j, err; 1813 int i, j, err, nr_entries;
1803 int skip_idx = -1; 1814 int skip_idx = -1;
1804 int first_call = 0; 1815 int first_call = 0;
1805 1816
1806 callchain_cursor_reset(&callchain_cursor); 1817 if (perf_evsel__has_branch_callstack(evsel)) {
1807 1818 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); 1819 root_al, max_stack);
1811 if (err) 1820 if (err)
1812 return (err < 0) ? err : 0; 1821 return (err < 0) ? err : 0;
@@ -1816,8 +1825,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1816 * Based on DWARF debug information, some architectures skip 1825 * Based on DWARF debug information, some architectures skip
1817 * a callchain entry saved by the kernel. 1826 * a callchain entry saved by the kernel.
1818 */ 1827 */
1819 if (chain->nr < PERF_MAX_STACK_DEPTH) 1828 skip_idx = arch_skip_callchain_idx(thread, chain);
1820 skip_idx = arch_skip_callchain_idx(thread, chain);
1821 1829
1822 /* 1830 /*
1823 * Add branches to call stack for easier browsing. This gives 1831 * Add branches to call stack for easier browsing. This gives
@@ -1863,10 +1871,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1863 nr = remove_loops(be, nr); 1871 nr = remove_loops(be, nr);
1864 1872
1865 for (i = 0; i < nr; i++) { 1873 for (i = 0; i < nr; i++) {
1866 err = add_callchain_ip(thread, parent, root_al, 1874 err = add_callchain_ip(thread, cursor, parent, root_al,
1867 NULL, be[i].to); 1875 NULL, be[i].to);
1868 if (!err) 1876 if (!err)
1869 err = add_callchain_ip(thread, parent, root_al, 1877 err = add_callchain_ip(thread, cursor, parent, root_al,
1870 NULL, be[i].from); 1878 NULL, be[i].from);
1871 if (err == -EINVAL) 1879 if (err == -EINVAL)
1872 break; 1880 break;
@@ -1877,12 +1885,8 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1877 } 1885 }
1878 1886
1879check_calls: 1887check_calls:
1880 if (chain->nr > PERF_MAX_STACK_DEPTH && (int)chain->nr > max_stack) { 1888 for (i = first_call, nr_entries = 0;
1881 pr_warning("corrupted callchain. skipping...\n"); 1889 i < chain_nr && nr_entries < max_stack; i++) {
1882 return 0;
1883 }
1884
1885 for (i = first_call; i < chain_nr; i++) {
1886 u64 ip; 1890 u64 ip;
1887 1891
1888 if (callchain_param.order == ORDER_CALLEE) 1892 if (callchain_param.order == ORDER_CALLEE)
@@ -1896,7 +1900,10 @@ check_calls:
1896#endif 1900#endif
1897 ip = chain->ips[j]; 1901 ip = chain->ips[j];
1898 1902
1899 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); 1903 if (ip < PERF_CONTEXT_MAX)
1904 ++nr_entries;
1905
1906 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
1900 1907
1901 if (err) 1908 if (err)
1902 return (err < 0) ? err : 0; 1909 return (err < 0) ? err : 0;
@@ -1915,19 +1922,12 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
1915 entry->map, entry->sym); 1922 entry->map, entry->sym);
1916} 1923}
1917 1924
1918int thread__resolve_callchain(struct thread *thread, 1925static int thread__resolve_callchain_unwind(struct thread *thread,
1919 struct perf_evsel *evsel, 1926 struct callchain_cursor *cursor,
1920 struct perf_sample *sample, 1927 struct perf_evsel *evsel,
1921 struct symbol **parent, 1928 struct perf_sample *sample,
1922 struct addr_location *root_al, 1929 int max_stack)
1923 int max_stack)
1924{ 1930{
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? */ 1931 /* Can we do dwarf post unwind? */
1932 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) && 1932 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
1933 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER))) 1933 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
@@ -1938,9 +1938,45 @@ int thread__resolve_callchain(struct thread *thread,
1938 (!sample->user_stack.size)) 1938 (!sample->user_stack.size))
1939 return 0; 1939 return 0;
1940 1940
1941 return unwind__get_entries(unwind_entry, &callchain_cursor, 1941 return unwind__get_entries(unwind_entry, cursor,
1942 thread, sample, max_stack); 1942 thread, sample, max_stack);
1943}
1943 1944
1945int thread__resolve_callchain(struct thread *thread,
1946 struct callchain_cursor *cursor,
1947 struct perf_evsel *evsel,
1948 struct perf_sample *sample,
1949 struct symbol **parent,
1950 struct addr_location *root_al,
1951 int max_stack)
1952{
1953 int ret = 0;
1954
1955 callchain_cursor_reset(&callchain_cursor);
1956
1957 if (callchain_param.order == ORDER_CALLEE) {
1958 ret = thread__resolve_callchain_sample(thread, cursor,
1959 evsel, sample,
1960 parent, root_al,
1961 max_stack);
1962 if (ret)
1963 return ret;
1964 ret = thread__resolve_callchain_unwind(thread, cursor,
1965 evsel, sample,
1966 max_stack);
1967 } else {
1968 ret = thread__resolve_callchain_unwind(thread, cursor,
1969 evsel, sample,
1970 max_stack);
1971 if (ret)
1972 return ret;
1973 ret = thread__resolve_callchain_sample(thread, cursor,
1974 evsel, sample,
1975 parent, root_al,
1976 max_stack);
1977 }
1978
1979 return ret;
1944} 1980}
1945 1981
1946int machine__for_each_thread(struct machine *machine, 1982int machine__for_each_thread(struct machine *machine,
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 8499db281158..41ac9cfd416b 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -28,9 +28,11 @@ struct machine {
28 pid_t pid; 28 pid_t pid;
29 u16 id_hdr_size; 29 u16 id_hdr_size;
30 bool comm_exec; 30 bool comm_exec;
31 bool kptr_restrict_warned;
31 char *root_dir; 32 char *root_dir;
32 struct rb_root threads; 33 struct rb_root threads;
33 pthread_rwlock_t threads_lock; 34 pthread_rwlock_t threads_lock;
35 unsigned int nr_threads;
34 struct list_head dead_threads; 36 struct list_head dead_threads;
35 struct thread *last_match; 37 struct thread *last_match;
36 struct vdso_info *vdso_info; 38 struct vdso_info *vdso_info;
@@ -141,7 +143,11 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
141 struct addr_location *al); 143 struct addr_location *al);
142struct mem_info *sample__resolve_mem(struct perf_sample *sample, 144struct mem_info *sample__resolve_mem(struct perf_sample *sample,
143 struct addr_location *al); 145 struct addr_location *al);
146
147struct callchain_cursor;
148
144int thread__resolve_callchain(struct thread *thread, 149int thread__resolve_callchain(struct thread *thread,
150 struct callchain_cursor *cursor,
145 struct perf_evsel *evsel, 151 struct perf_evsel *evsel,
146 struct perf_sample *sample, 152 struct perf_sample *sample,
147 struct symbol **parent, 153 struct symbol **parent,
@@ -211,6 +217,8 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *machine,
211struct map *machine__findnew_module_map(struct machine *machine, u64 start, 217struct map *machine__findnew_module_map(struct machine *machine, u64 start,
212 const char *filename); 218 const char *filename);
213 219
220int __machine__load_kallsyms(struct machine *machine, const char *filename,
221 enum map_type type, bool no_kcore, symbol_filter_t filter);
214int machine__load_kallsyms(struct machine *machine, const char *filename, 222int machine__load_kallsyms(struct machine *machine, const char *filename,
215 enum map_type type, symbol_filter_t filter); 223 enum map_type type, symbol_filter_t filter);
216int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 224int 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/perf_regs.c b/tools/perf/util/perf_regs.c
index 6b8eb13e14e4..c4023f22f287 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -12,18 +12,18 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
12 int i, idx = 0; 12 int i, idx = 0;
13 u64 mask = regs->mask; 13 u64 mask = regs->mask;
14 14
15 if (regs->cache_mask & (1 << id)) 15 if (regs->cache_mask & (1ULL << id))
16 goto out; 16 goto out;
17 17
18 if (!(mask & (1 << id))) 18 if (!(mask & (1ULL << id)))
19 return -EINVAL; 19 return -EINVAL;
20 20
21 for (i = 0; i < id; i++) { 21 for (i = 0; i < id; i++) {
22 if (mask & (1 << i)) 22 if (mask & (1ULL << i))
23 idx++; 23 idx++;
24 } 24 }
25 25
26 regs->cache_mask |= (1 << id); 26 regs->cache_mask |= (1ULL << id);
27 regs->cache_regs[id] = regs->regs[idx]; 27 regs->cache_regs[id] = regs->regs[idx];
28 28
29out: 29out:
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..5d1eb1ccd96c 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,89 @@ 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, scripting_max_stack) != 0) {
268 pr_err("Failed to resolve callchain. Skipping\n");
269 goto exit;
270 }
271 callchain_cursor_commit(&callchain_cursor);
272
273
274 while (1) {
275 HV *elem;
276 struct callchain_cursor_node *node;
277 node = callchain_cursor_current(&callchain_cursor);
278 if (!node)
279 break;
280
281 elem = newHV();
282 if (!elem)
283 goto exit;
284
285 if (!hv_stores(elem, "ip", newSVuv(node->ip))) {
286 hv_undef(elem);
287 goto exit;
288 }
289
290 if (node->sym) {
291 HV *sym = newHV();
292 if (!sym) {
293 hv_undef(elem);
294 goto exit;
295 }
296 if (!hv_stores(sym, "start", newSVuv(node->sym->start)) ||
297 !hv_stores(sym, "end", newSVuv(node->sym->end)) ||
298 !hv_stores(sym, "binding", newSVuv(node->sym->binding)) ||
299 !hv_stores(sym, "name", newSVpvn(node->sym->name,
300 node->sym->namelen)) ||
301 !hv_stores(elem, "sym", newRV_noinc((SV*)sym))) {
302 hv_undef(sym);
303 hv_undef(elem);
304 goto exit;
305 }
306 }
307
308 if (node->map) {
309 struct map *map = node->map;
310 const char *dsoname = "[unknown]";
311 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
312 if (symbol_conf.show_kernel_path && map->dso->long_name)
313 dsoname = map->dso->long_name;
314 else if (map->dso->name)
315 dsoname = map->dso->name;
316 }
317 if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) {
318 hv_undef(elem);
319 goto exit;
320 }
321 }
322
323 callchain_cursor_advance(&callchain_cursor);
324 av_push(list, newRV_noinc((SV*)elem));
325 }
326
327exit:
328 return newRV_noinc((SV*)list);
329}
330
251static void perl_process_tracepoint(struct perf_sample *sample, 331static void perl_process_tracepoint(struct perf_sample *sample,
252 struct perf_evsel *evsel, 332 struct perf_evsel *evsel,
253 struct thread *thread) 333 struct addr_location *al)
254{ 334{
335 struct thread *thread = al->thread;
255 struct event_format *event = evsel->tp_format; 336 struct event_format *event = evsel->tp_format;
256 struct format_field *field; 337 struct format_field *field;
257 static char handler[256]; 338 static char handler[256];
@@ -295,6 +376,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
295 XPUSHs(sv_2mortal(newSVuv(ns))); 376 XPUSHs(sv_2mortal(newSVuv(ns)));
296 XPUSHs(sv_2mortal(newSViv(pid))); 377 XPUSHs(sv_2mortal(newSViv(pid)));
297 XPUSHs(sv_2mortal(newSVpv(comm, 0))); 378 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
379 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
298 380
299 /* common fields other than pid can be accessed via xsub fns */ 381 /* common fields other than pid can be accessed via xsub fns */
300 382
@@ -329,6 +411,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
329 XPUSHs(sv_2mortal(newSVuv(nsecs))); 411 XPUSHs(sv_2mortal(newSVuv(nsecs)));
330 XPUSHs(sv_2mortal(newSViv(pid))); 412 XPUSHs(sv_2mortal(newSViv(pid)));
331 XPUSHs(sv_2mortal(newSVpv(comm, 0))); 413 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
414 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
332 call_pv("main::trace_unhandled", G_SCALAR); 415 call_pv("main::trace_unhandled", G_SCALAR);
333 } 416 }
334 SPAGAIN; 417 SPAGAIN;
@@ -366,7 +449,7 @@ static void perl_process_event(union perf_event *event,
366 struct perf_evsel *evsel, 449 struct perf_evsel *evsel,
367 struct addr_location *al) 450 struct addr_location *al)
368{ 451{
369 perl_process_tracepoint(sample, evsel, al->thread); 452 perl_process_tracepoint(sample, evsel, al);
370 perl_process_event_generic(event, sample, evsel); 453 perl_process_event_generic(event, sample, evsel);
371} 454}
372 455
@@ -490,7 +573,27 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
490 fprintf(ofp, "use Perf::Trace::Util;\n\n"); 573 fprintf(ofp, "use Perf::Trace::Util;\n\n");
491 574
492 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n"); 575 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"); 576 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n");
577
578
579 fprintf(ofp, "\n\
580sub print_backtrace\n\
581{\n\
582 my $callchain = shift;\n\
583 for my $node (@$callchain)\n\
584 {\n\
585 if(exists $node->{sym})\n\
586 {\n\
587 printf( \"\\t[\\%%x] \\%%s\\n\", $node->{ip}, $node->{sym}{name});\n\
588 }\n\
589 else\n\
590 {\n\
591 printf( \"\\t[\\%%x]\\n\", $node{ip});\n\
592 }\n\
593 }\n\
594}\n\n\
595");
596
494 597
495 while ((event = trace_find_next_event(pevent, event))) { 598 while ((event = trace_find_next_event(pevent, event))) {
496 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name); 599 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
@@ -502,7 +605,8 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
502 fprintf(ofp, "$common_secs, "); 605 fprintf(ofp, "$common_secs, ");
503 fprintf(ofp, "$common_nsecs,\n"); 606 fprintf(ofp, "$common_nsecs,\n");
504 fprintf(ofp, "\t $common_pid, "); 607 fprintf(ofp, "\t $common_pid, ");
505 fprintf(ofp, "$common_comm,\n\t "); 608 fprintf(ofp, "$common_comm, ");
609 fprintf(ofp, "$common_callchain,\n\t ");
506 610
507 not_first = 0; 611 not_first = 0;
508 count = 0; 612 count = 0;
@@ -519,7 +623,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
519 623
520 fprintf(ofp, "\tprint_header($event_name, $common_cpu, " 624 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
521 "$common_secs, $common_nsecs,\n\t " 625 "$common_secs, $common_nsecs,\n\t "
522 "$common_pid, $common_comm);\n\n"); 626 "$common_pid, $common_comm, $common_callchain);\n\n");
523 627
524 fprintf(ofp, "\tprintf(\""); 628 fprintf(ofp, "\tprintf(\"");
525 629
@@ -581,17 +685,22 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
581 fprintf(ofp, "$%s", f->name); 685 fprintf(ofp, "$%s", f->name);
582 } 686 }
583 687
584 fprintf(ofp, ");\n"); 688 fprintf(ofp, ");\n\n");
689
690 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
691
585 fprintf(ofp, "}\n\n"); 692 fprintf(ofp, "}\n\n");
586 } 693 }
587 694
588 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, " 695 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "
589 "$common_cpu, $common_secs, $common_nsecs,\n\t " 696 "$common_cpu, $common_secs, $common_nsecs,\n\t "
590 "$common_pid, $common_comm) = @_;\n\n"); 697 "$common_pid, $common_comm, $common_callchain) = @_;\n\n");
591 698
592 fprintf(ofp, "\tprint_header($event_name, $common_cpu, " 699 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
593 "$common_secs, $common_nsecs,\n\t $common_pid, " 700 "$common_secs, $common_nsecs,\n\t $common_pid, "
594 "$common_comm);\n}\n\n"); 701 "$common_comm, $common_callchain);\n");
702 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
703 fprintf(ofp, "}\n\n");
595 704
596 fprintf(ofp, "sub print_header\n{\n" 705 fprintf(ofp, "sub print_header\n{\n"
597 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n" 706 "\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..c4e9bd70723c 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;
@@ -360,6 +353,88 @@ struct sort_entry sort_srcline = {
360 .se_width_idx = HISTC_SRCLINE, 353 .se_width_idx = HISTC_SRCLINE,
361}; 354};
362 355
356/* --sort srcline_from */
357
358static int64_t
359sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
360{
361 if (!left->branch_info->srcline_from) {
362 struct map *map = left->branch_info->from.map;
363 if (!map)
364 left->branch_info->srcline_from = SRCLINE_UNKNOWN;
365 else
366 left->branch_info->srcline_from = get_srcline(map->dso,
367 map__rip_2objdump(map,
368 left->branch_info->from.al_addr),
369 left->branch_info->from.sym, true);
370 }
371 if (!right->branch_info->srcline_from) {
372 struct map *map = right->branch_info->from.map;
373 if (!map)
374 right->branch_info->srcline_from = SRCLINE_UNKNOWN;
375 else
376 right->branch_info->srcline_from = get_srcline(map->dso,
377 map__rip_2objdump(map,
378 right->branch_info->from.al_addr),
379 right->branch_info->from.sym, true);
380 }
381 return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
382}
383
384static int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf,
385 size_t size, unsigned int width)
386{
387 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_from);
388}
389
390struct sort_entry sort_srcline_from = {
391 .se_header = "From Source:Line",
392 .se_cmp = sort__srcline_from_cmp,
393 .se_snprintf = hist_entry__srcline_from_snprintf,
394 .se_width_idx = HISTC_SRCLINE_FROM,
395};
396
397/* --sort srcline_to */
398
399static int64_t
400sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
401{
402 if (!left->branch_info->srcline_to) {
403 struct map *map = left->branch_info->to.map;
404 if (!map)
405 left->branch_info->srcline_to = SRCLINE_UNKNOWN;
406 else
407 left->branch_info->srcline_to = get_srcline(map->dso,
408 map__rip_2objdump(map,
409 left->branch_info->to.al_addr),
410 left->branch_info->from.sym, true);
411 }
412 if (!right->branch_info->srcline_to) {
413 struct map *map = right->branch_info->to.map;
414 if (!map)
415 right->branch_info->srcline_to = SRCLINE_UNKNOWN;
416 else
417 right->branch_info->srcline_to = get_srcline(map->dso,
418 map__rip_2objdump(map,
419 right->branch_info->to.al_addr),
420 right->branch_info->to.sym, true);
421 }
422 return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
423}
424
425static int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf,
426 size_t size, unsigned int width)
427{
428 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_to);
429}
430
431struct sort_entry sort_srcline_to = {
432 .se_header = "To Source:Line",
433 .se_cmp = sort__srcline_to_cmp,
434 .se_snprintf = hist_entry__srcline_to_snprintf,
435 .se_width_idx = HISTC_SRCLINE_TO,
436};
437
363/* --sort srcfile */ 438/* --sort srcfile */
364 439
365static char no_srcfile[1]; 440static char no_srcfile[1];
@@ -1354,6 +1429,8 @@ static struct sort_dimension bstack_sort_dimensions[] = {
1354 DIM(SORT_IN_TX, "in_tx", sort_in_tx), 1429 DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1355 DIM(SORT_ABORT, "abort", sort_abort), 1430 DIM(SORT_ABORT, "abort", sort_abort),
1356 DIM(SORT_CYCLES, "cycles", sort_cycles), 1431 DIM(SORT_CYCLES, "cycles", sort_cycles),
1432 DIM(SORT_SRCLINE_FROM, "srcline_from", sort_srcline_from),
1433 DIM(SORT_SRCLINE_TO, "srcline_to", sort_srcline_to),
1357}; 1434};
1358 1435
1359#undef DIM 1436#undef DIM
@@ -2163,7 +2240,7 @@ static int __sort_dimension__add(struct sort_dimension *sd,
2163 return -1; 2240 return -1;
2164 2241
2165 if (sd->entry->se_collapse) 2242 if (sd->entry->se_collapse)
2166 sort__need_collapse = 1; 2243 list->need_collapse = 1;
2167 2244
2168 sd->taken = 1; 2245 sd->taken = 1;
2169 2246
@@ -2245,9 +2322,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); 2322 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
2246 return -EINVAL; 2323 return -EINVAL;
2247 } 2324 }
2248 sort__has_parent = 1; 2325 list->parent = 1;
2249 } else if (sd->entry == &sort_sym) { 2326 } else if (sd->entry == &sort_sym) {
2250 sort__has_sym = 1; 2327 list->sym = 1;
2251 /* 2328 /*
2252 * perf diff displays the performance difference amongst 2329 * perf diff displays the performance difference amongst
2253 * two or more perf.data files. Those files could come 2330 * two or more perf.data files. Those files could come
@@ -2258,13 +2335,13 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2258 sd->entry->se_collapse = sort__sym_sort; 2335 sd->entry->se_collapse = sort__sym_sort;
2259 2336
2260 } else if (sd->entry == &sort_dso) { 2337 } else if (sd->entry == &sort_dso) {
2261 sort__has_dso = 1; 2338 list->dso = 1;
2262 } else if (sd->entry == &sort_socket) { 2339 } else if (sd->entry == &sort_socket) {
2263 sort__has_socket = 1; 2340 list->socket = 1;
2264 } else if (sd->entry == &sort_thread) { 2341 } else if (sd->entry == &sort_thread) {
2265 sort__has_thread = 1; 2342 list->thread = 1;
2266 } else if (sd->entry == &sort_comm) { 2343 } else if (sd->entry == &sort_comm) {
2267 sort__has_comm = 1; 2344 list->comm = 1;
2268 } 2345 }
2269 2346
2270 return __sort_dimension__add(sd, list, level); 2347 return __sort_dimension__add(sd, list, level);
@@ -2289,7 +2366,7 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2289 return -EINVAL; 2366 return -EINVAL;
2290 2367
2291 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) 2368 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
2292 sort__has_sym = 1; 2369 list->sym = 1;
2293 2370
2294 __sort_dimension__add(sd, list, level); 2371 __sort_dimension__add(sd, list, level);
2295 return 0; 2372 return 0;
@@ -2305,7 +2382,7 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2305 return -EINVAL; 2382 return -EINVAL;
2306 2383
2307 if (sd->entry == &sort_mem_daddr_sym) 2384 if (sd->entry == &sort_mem_daddr_sym)
2308 sort__has_sym = 1; 2385 list->sym = 1;
2309 2386
2310 __sort_dimension__add(sd, list, level); 2387 __sort_dimension__add(sd, list, level);
2311 return 0; 2388 return 0;
@@ -2445,6 +2522,9 @@ static char *prefix_if_not_in(const char *pre, char *str)
2445 2522
2446static char *setup_overhead(char *keys) 2523static char *setup_overhead(char *keys)
2447{ 2524{
2525 if (sort__mode == SORT_MODE__DIFF)
2526 return keys;
2527
2448 keys = prefix_if_not_in("overhead", keys); 2528 keys = prefix_if_not_in("overhead", keys);
2449 2529
2450 if (symbol_conf.cumulate_callchain) 2530 if (symbol_conf.cumulate_callchain)
@@ -2746,10 +2826,10 @@ int setup_sorting(struct perf_evlist *evlist)
2746 2826
2747void reset_output_field(void) 2827void reset_output_field(void)
2748{ 2828{
2749 sort__need_collapse = 0; 2829 perf_hpp_list.need_collapse = 0;
2750 sort__has_parent = 0; 2830 perf_hpp_list.parent = 0;
2751 sort__has_sym = 0; 2831 perf_hpp_list.sym = 0;
2752 sort__has_dso = 0; 2832 perf_hpp_list.dso = 0;
2753 2833
2754 field_order = NULL; 2834 field_order = NULL;
2755 sort_order = NULL; 2835 sort_order = NULL;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 3f4e35998119..ebb59cacd092 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;
@@ -222,6 +215,8 @@ enum sort_type {
222 SORT_ABORT, 215 SORT_ABORT,
223 SORT_IN_TX, 216 SORT_IN_TX,
224 SORT_CYCLES, 217 SORT_CYCLES,
218 SORT_SRCLINE_FROM,
219 SORT_SRCLINE_TO,
225 220
226 /* memory mode specific sort keys */ 221 /* memory mode specific sort keys */
227 __SORT_MEMORY_MODE, 222 __SORT_MEMORY_MODE,
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index fdb71961143e..aa9efe08762b 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -94,7 +94,8 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
94{ 94{
95 int ctx = evsel_context(counter); 95 int ctx = evsel_context(counter);
96 96
97 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 97 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) ||
98 perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK))
98 update_stats(&runtime_nsecs_stats[cpu], count[0]); 99 update_stats(&runtime_nsecs_stats[cpu], count[0]);
99 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 100 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
100 update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); 101 update_stats(&runtime_cycles_stats[ctx][cpu], count[0]);
@@ -188,7 +189,7 @@ static void print_stalled_cycles_backend(int cpu,
188 189
189 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); 190 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
190 191
191 out->print_metric(out->ctx, color, "%6.2f%%", "backend cycles idle", ratio); 192 out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
192} 193}
193 194
194static void print_branch_misses(int cpu, 195static void print_branch_misses(int cpu,
@@ -444,7 +445,8 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
444 ratio = total / avg; 445 ratio = total / avg;
445 446
446 print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio); 447 print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio);
447 } else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) { 448 } else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK) ||
449 perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK)) {
448 if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0) 450 if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
449 print_metric(ctxp, NULL, "%8.3f", "CPUs utilized", 451 print_metric(ctxp, NULL, "%8.3f", "CPUs utilized",
450 avg / ratio); 452 avg / ratio);
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..20f9cb32b703 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
@@ -1696,8 +1662,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1696 1662
1697 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 1663 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1698 1664
1699 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir, 1665 scnprintf(path, sizeof(path), "%s/%s/%s", buildid_dir,
1700 sbuild_id); 1666 DSO__NAME_KCORE, sbuild_id);
1701 1667
1702 /* Use /proc/kallsyms if possible */ 1668 /* Use /proc/kallsyms if possible */
1703 if (is_host) { 1669 if (is_host) {
@@ -1733,8 +1699,8 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1733 if (!find_matching_kcore(map, path, sizeof(path))) 1699 if (!find_matching_kcore(map, path, sizeof(path)))
1734 return strdup(path); 1700 return strdup(path);
1735 1701
1736 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", 1702 scnprintf(path, sizeof(path), "%s/%s/%s",
1737 buildid_dir, sbuild_id); 1703 buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
1738 1704
1739 if (access(path, F_OK)) { 1705 if (access(path, F_OK)) {
1740 pr_err("No kallsyms or vmlinux with build-id %s was found\n", 1706 pr_err("No kallsyms or vmlinux with build-id %s was found\n",
@@ -1803,7 +1769,7 @@ do_kallsyms:
1803 1769
1804 if (err > 0 && !dso__is_kcore(dso)) { 1770 if (err > 0 && !dso__is_kcore(dso)) {
1805 dso->binary_type = DSO_BINARY_TYPE__KALLSYMS; 1771 dso->binary_type = DSO_BINARY_TYPE__KALLSYMS;
1806 dso__set_long_name(dso, "[kernel.kallsyms]", false); 1772 dso__set_long_name(dso, DSO__NAME_KALLSYMS, false);
1807 map__fixup_start(map); 1773 map__fixup_start(map);
1808 map__fixup_end(map); 1774 map__fixup_end(map);
1809 } 1775 }
@@ -2067,3 +2033,26 @@ void symbol__exit(void)
2067 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 2033 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
2068 symbol_conf.initialized = false; 2034 symbol_conf.initialized = false;
2069} 2035}
2036
2037int symbol__config_symfs(const struct option *opt __maybe_unused,
2038 const char *dir, int unset __maybe_unused)
2039{
2040 char *bf = NULL;
2041 int ret;
2042
2043 symbol_conf.symfs = strdup(dir);
2044 if (symbol_conf.symfs == NULL)
2045 return -ENOMEM;
2046
2047 /* skip the locally configured cache if a symfs is given, and
2048 * config buildid dir to symfs/.debug
2049 */
2050 ret = asprintf(&bf, "%s/%s", dir, ".debug");
2051 if (ret < 0)
2052 return -ENOMEM;
2053
2054 set_buildid_dir(bf);
2055
2056 free(bf);
2057 return 0;
2058}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index c8b7544d9267..b10d558a8803 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -44,6 +44,9 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
44#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 44#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
45#endif 45#endif
46 46
47#define DSO__NAME_KALLSYMS "[kernel.kallsyms]"
48#define DSO__NAME_KCORE "[kernel.kcore]"
49
47/** struct symbol - symtab entry 50/** struct symbol - symtab entry
48 * 51 *
49 * @ignore - resolvable but tools ignore it (e.g. idle routines) 52 * @ignore - resolvable but tools ignore it (e.g. idle routines)
@@ -55,6 +58,7 @@ struct symbol {
55 u16 namelen; 58 u16 namelen;
56 u8 binding; 59 u8 binding;
57 bool ignore; 60 bool ignore;
61 u8 arch_sym;
58 char name[0]; 62 char name[0];
59}; 63};
60 64
@@ -140,6 +144,11 @@ struct symbol_conf {
140 144
141extern struct symbol_conf symbol_conf; 145extern struct symbol_conf symbol_conf;
142 146
147struct symbol_name_rb_node {
148 struct rb_node rb_node;
149 struct symbol sym;
150};
151
143static inline int __symbol__join_symfs(char *bf, size_t size, const char *path) 152static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)
144{ 153{
145 return path__join(bf, size, symbol_conf.symfs, path); 154 return path__join(bf, size, symbol_conf.symfs, path);
@@ -177,6 +186,8 @@ struct branch_info {
177 struct addr_map_symbol from; 186 struct addr_map_symbol from;
178 struct addr_map_symbol to; 187 struct addr_map_symbol to;
179 struct branch_flags flags; 188 struct branch_flags flags;
189 char *srcline_from;
190 char *srcline_to;
180}; 191};
181 192
182struct mem_info { 193struct mem_info {
@@ -235,9 +246,14 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
235 symbol_filter_t filter); 246 symbol_filter_t filter);
236int dso__load_vmlinux_path(struct dso *dso, struct map *map, 247int dso__load_vmlinux_path(struct dso *dso, struct map *map,
237 symbol_filter_t filter); 248 symbol_filter_t filter);
249int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
250 bool no_kcore, symbol_filter_t filter);
238int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 251int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
239 symbol_filter_t filter); 252 symbol_filter_t filter);
240 253
254void dso__insert_symbol(struct dso *dso, enum map_type type,
255 struct symbol *sym);
256
241struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, 257struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
242 u64 addr); 258 u64 addr);
243struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 259struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
@@ -262,14 +278,22 @@ int symbol__init(struct perf_env *env);
262void symbol__exit(void); 278void symbol__exit(void);
263void symbol__elf_init(void); 279void symbol__elf_init(void);
264struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 280struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
281size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
282 const struct addr_location *al,
283 bool unknown_as_addr, FILE *fp);
265size_t symbol__fprintf_symname_offs(const struct symbol *sym, 284size_t symbol__fprintf_symname_offs(const struct symbol *sym,
266 const struct addr_location *al, FILE *fp); 285 const struct addr_location *al, FILE *fp);
286size_t __symbol__fprintf_symname(const struct symbol *sym,
287 const struct addr_location *al,
288 bool unknown_as_addr, FILE *fp);
267size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 289size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
268size_t symbol__fprintf(struct symbol *sym, FILE *fp); 290size_t symbol__fprintf(struct symbol *sym, FILE *fp);
269bool symbol_type__is_a(char symbol_type, enum map_type map_type); 291bool symbol_type__is_a(char symbol_type, enum map_type map_type);
270bool symbol__restricted_filename(const char *filename, 292bool symbol__restricted_filename(const char *filename,
271 const char *restricted_filename); 293 const char *restricted_filename);
272bool symbol__is_idle(struct symbol *sym); 294bool symbol__is_idle(struct symbol *sym);
295int symbol__config_symfs(const struct option *opt __maybe_unused,
296 const char *dir, int unset __maybe_unused);
273 297
274int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 298int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
275 struct symsrc *runtime_ss, symbol_filter_t filter, 299 struct symsrc *runtime_ss, symbol_filter_t filter,
@@ -310,7 +334,7 @@ int setup_intlist(struct intlist **list, const char *list_str,
310 334
311#ifdef HAVE_LIBELF_SUPPORT 335#ifdef HAVE_LIBELF_SUPPORT
312bool elf__needs_adjust_symbols(GElf_Ehdr ehdr); 336bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
313void arch__elf_sym_adjust(GElf_Sym *sym); 337void arch__sym_update(struct symbol *s, GElf_Sym *sym);
314#endif 338#endif
315 339
316#define SYMBOL_A 0 340#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/top.h b/tools/perf/util/top.h
index f92c37abb0a8..b2940c88734a 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -27,7 +27,6 @@ struct perf_top {
27 int max_stack; 27 int max_stack;
28 bool hide_kernel_symbols, hide_user_symbols, zero; 28 bool hide_kernel_symbols, hide_user_symbols, zero;
29 bool use_tui, use_stdio; 29 bool use_tui, use_stdio;
30 bool kptr_restrict_warned;
31 bool vmlinux_warned; 30 bool vmlinux_warned;
32 bool dump_symtab; 31 bool dump_symtab;
33 struct hist_entry *sym_filter_entry; 32 struct hist_entry *sym_filter_entry;
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..23504ad5d6dd 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -33,6 +33,9 @@ struct callchain_param callchain_param = {
33unsigned int page_size; 33unsigned int page_size;
34int cacheline_size; 34int cacheline_size;
35 35
36int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
37int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK;
38
36bool test_attr__enabled; 39bool test_attr__enabled;
37 40
38bool perf_host = true; 41bool perf_host = true;
@@ -117,6 +120,40 @@ int rm_rf(char *path)
117 return rmdir(path); 120 return rmdir(path);
118} 121}
119 122
123/* A filter which removes dot files */
124bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
125{
126 return d->d_name[0] != '.';
127}
128
129/* lsdir reads a directory and store it in strlist */
130struct strlist *lsdir(const char *name,
131 bool (*filter)(const char *, struct dirent *))
132{
133 struct strlist *list = NULL;
134 DIR *dir;
135 struct dirent *d;
136
137 dir = opendir(name);
138 if (!dir)
139 return NULL;
140
141 list = strlist__new(NULL, NULL);
142 if (!list) {
143 errno = ENOMEM;
144 goto out;
145 }
146
147 while ((d = readdir(dir)) != NULL) {
148 if (!filter || filter(name, d))
149 strlist__add(list, d->d_name);
150 }
151
152out:
153 closedir(dir);
154 return list;
155}
156
120static int slow_copyfile(const char *from, const char *to) 157static int slow_copyfile(const char *from, const char *to)
121{ 158{
122 int err = -1; 159 int err = -1;
@@ -471,7 +508,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param)
471 "needed for --call-graph fp\n"); 508 "needed for --call-graph fp\n");
472 break; 509 break;
473 510
474#ifdef HAVE_DWARF_UNWIND_SUPPORT
475 /* Dwarf style */ 511 /* Dwarf style */
476 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 512 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
477 const unsigned long default_stack_dump_size = 8192; 513 const unsigned long default_stack_dump_size = 8192;
@@ -487,7 +523,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param)
487 ret = get_stack_size(tok, &size); 523 ret = get_stack_size(tok, &size);
488 param->dump_size = size; 524 param->dump_size = size;
489 } 525 }
490#endif /* HAVE_DWARF_UNWIND_SUPPORT */
491 } else if (!strncmp(name, "lbr", sizeof("lbr"))) { 526 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
492 if (!strtok_r(NULL, ",", &saveptr)) { 527 if (!strtok_r(NULL, ",", &saveptr)) {
493 param->record_mode = CALLCHAIN_LBR; 528 param->record_mode = CALLCHAIN_LBR;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 8298d607c738..1e8c3167b9fb 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,18 @@ 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 int sysctl_perf_event_max_stack;
265extern int sysctl_perf_event_max_contexts_per_stack;
262 266
263struct parse_tag { 267struct parse_tag {
264 char tag; 268 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/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index a34bfd0c8928..785985677159 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -7,6 +7,7 @@ ldflags-y += --wrap=ioremap_nocache
7ldflags-y += --wrap=iounmap 7ldflags-y += --wrap=iounmap
8ldflags-y += --wrap=memunmap 8ldflags-y += --wrap=memunmap
9ldflags-y += --wrap=__devm_request_region 9ldflags-y += --wrap=__devm_request_region
10ldflags-y += --wrap=__devm_release_region
10ldflags-y += --wrap=__request_region 11ldflags-y += --wrap=__request_region
11ldflags-y += --wrap=__release_region 12ldflags-y += --wrap=__release_region
12ldflags-y += --wrap=devm_memremap_pages 13ldflags-y += --wrap=devm_memremap_pages
@@ -15,6 +16,7 @@ ldflags-y += --wrap=phys_to_pfn_t
15DRIVERS := ../../../drivers 16DRIVERS := ../../../drivers
16NVDIMM_SRC := $(DRIVERS)/nvdimm 17NVDIMM_SRC := $(DRIVERS)/nvdimm
17ACPI_SRC := $(DRIVERS)/acpi 18ACPI_SRC := $(DRIVERS)/acpi
19DAX_SRC := $(DRIVERS)/dax
18 20
19obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o 21obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
20obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o 22obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
@@ -22,6 +24,8 @@ obj-$(CONFIG_ND_BTT) += nd_btt.o
22obj-$(CONFIG_ND_BLK) += nd_blk.o 24obj-$(CONFIG_ND_BLK) += nd_blk.o
23obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o 25obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
24obj-$(CONFIG_ACPI_NFIT) += nfit.o 26obj-$(CONFIG_ACPI_NFIT) += nfit.o
27obj-$(CONFIG_DEV_DAX) += dax.o
28obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
25 29
26nfit-y := $(ACPI_SRC)/nfit.o 30nfit-y := $(ACPI_SRC)/nfit.o
27nfit-y += config_check.o 31nfit-y += config_check.o
@@ -38,6 +42,12 @@ nd_blk-y += config_check.o
38nd_e820-y := $(NVDIMM_SRC)/e820.o 42nd_e820-y := $(NVDIMM_SRC)/e820.o
39nd_e820-y += config_check.o 43nd_e820-y += config_check.o
40 44
45dax-y := $(DAX_SRC)/dax.o
46dax-y += config_check.o
47
48dax_pmem-y := $(DAX_SRC)/pmem.o
49dax_pmem-y += config_check.o
50
41libnvdimm-y := $(NVDIMM_SRC)/core.o 51libnvdimm-y := $(NVDIMM_SRC)/core.o
42libnvdimm-y += $(NVDIMM_SRC)/bus.o 52libnvdimm-y += $(NVDIMM_SRC)/bus.o
43libnvdimm-y += $(NVDIMM_SRC)/dimm_devs.o 53libnvdimm-y += $(NVDIMM_SRC)/dimm_devs.o
@@ -49,6 +59,7 @@ libnvdimm-y += $(NVDIMM_SRC)/label.o
49libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o 59libnvdimm-$(CONFIG_ND_CLAIM) += $(NVDIMM_SRC)/claim.o
50libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o 60libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o
51libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o 61libnvdimm-$(CONFIG_NVDIMM_PFN) += $(NVDIMM_SRC)/pfn_devs.o
62libnvdimm-$(CONFIG_NVDIMM_DAX) += $(NVDIMM_SRC)/dax_devs.o
52libnvdimm-y += config_check.o 63libnvdimm-y += config_check.o
53 64
54obj-m += test/ 65obj-m += test/
diff --git a/tools/testing/nvdimm/config_check.c b/tools/testing/nvdimm/config_check.c
index f2c7615554eb..adf18bfeca00 100644
--- a/tools/testing/nvdimm/config_check.c
+++ b/tools/testing/nvdimm/config_check.c
@@ -12,4 +12,6 @@ void check(void)
12 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT)); 12 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT));
13 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK)); 13 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK));
14 BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT)); 14 BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT));
15 BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX));
16 BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX_PMEM));
15} 17}
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index 0c1a7e65bb81..c842095f2801 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -239,13 +239,11 @@ struct resource *__wrap___devm_request_region(struct device *dev,
239} 239}
240EXPORT_SYMBOL(__wrap___devm_request_region); 240EXPORT_SYMBOL(__wrap___devm_request_region);
241 241
242void __wrap___release_region(struct resource *parent, resource_size_t start, 242static bool nfit_test_release_region(struct resource *parent,
243 resource_size_t n) 243 resource_size_t start, resource_size_t n)
244{ 244{
245 struct nfit_test_resource *nfit_res;
246
247 if (parent == &iomem_resource) { 245 if (parent == &iomem_resource) {
248 nfit_res = get_nfit_res(start); 246 struct nfit_test_resource *nfit_res = get_nfit_res(start);
249 if (nfit_res) { 247 if (nfit_res) {
250 struct resource *res = nfit_res->res + 1; 248 struct resource *res = nfit_res->res + 1;
251 249
@@ -254,11 +252,26 @@ void __wrap___release_region(struct resource *parent, resource_size_t start,
254 __func__, start, n, res); 252 __func__, start, n, res);
255 else 253 else
256 memset(res, 0, sizeof(*res)); 254 memset(res, 0, sizeof(*res));
257 return; 255 return true;
258 } 256 }
259 } 257 }
260 __release_region(parent, start, n); 258 return false;
259}
260
261void __wrap___release_region(struct resource *parent, resource_size_t start,
262 resource_size_t n)
263{
264 if (!nfit_test_release_region(parent, start, n))
265 __release_region(parent, start, n);
261} 266}
262EXPORT_SYMBOL(__wrap___release_region); 267EXPORT_SYMBOL(__wrap___release_region);
263 268
269void __wrap___devm_release_region(struct device *dev, struct resource *parent,
270 resource_size_t start, resource_size_t n)
271{
272 if (!nfit_test_release_region(parent, start, n))
273 __devm_release_region(dev, parent, start, n);
274}
275EXPORT_SYMBOL(__wrap___devm_release_region);
276
264MODULE_LICENSE("GPL v2"); 277MODULE_LICENSE("GPL v2");
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 3187322eeed7..c919866853a0 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -330,12 +330,49 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err,
330 return 0; 330 return 0;
331} 331}
332 332
333static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len)
334{
335 static const struct nd_smart_payload smart_data = {
336 .flags = ND_SMART_HEALTH_VALID | ND_SMART_TEMP_VALID
337 | ND_SMART_SPARES_VALID | ND_SMART_ALARM_VALID
338 | ND_SMART_USED_VALID | ND_SMART_SHUTDOWN_VALID,
339 .health = ND_SMART_NON_CRITICAL_HEALTH,
340 .temperature = 23 * 16,
341 .spares = 75,
342 .alarm_flags = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
343 .life_used = 5,
344 .shutdown_state = 0,
345 .vendor_size = 0,
346 };
347
348 if (buf_len < sizeof(*smart))
349 return -EINVAL;
350 memcpy(smart->data, &smart_data, sizeof(smart_data));
351 return 0;
352}
353
354static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold *smart_t,
355 unsigned int buf_len)
356{
357 static const struct nd_smart_threshold_payload smart_t_data = {
358 .alarm_control = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
359 .temperature = 40 * 16,
360 .spares = 5,
361 };
362
363 if (buf_len < sizeof(*smart_t))
364 return -EINVAL;
365 memcpy(smart_t->data, &smart_t_data, sizeof(smart_t_data));
366 return 0;
367}
368
333static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, 369static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
334 struct nvdimm *nvdimm, unsigned int cmd, void *buf, 370 struct nvdimm *nvdimm, unsigned int cmd, void *buf,
335 unsigned int buf_len, int *cmd_rc) 371 unsigned int buf_len, int *cmd_rc)
336{ 372{
337 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); 373 struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
338 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc); 374 struct nfit_test *t = container_of(acpi_desc, typeof(*t), acpi_desc);
375 unsigned int func = cmd;
339 int i, rc = 0, __cmd_rc; 376 int i, rc = 0, __cmd_rc;
340 377
341 if (!cmd_rc) 378 if (!cmd_rc)
@@ -344,8 +381,23 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
344 381
345 if (nvdimm) { 382 if (nvdimm) {
346 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); 383 struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
384 unsigned long cmd_mask = nvdimm_cmd_mask(nvdimm);
347 385
348 if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask)) 386 if (!nfit_mem)
387 return -ENOTTY;
388
389 if (cmd == ND_CMD_CALL) {
390 struct nd_cmd_pkg *call_pkg = buf;
391
392 buf_len = call_pkg->nd_size_in + call_pkg->nd_size_out;
393 buf = (void *) call_pkg->nd_payload;
394 func = call_pkg->nd_command;
395 if (call_pkg->nd_family != nfit_mem->family)
396 return -ENOTTY;
397 }
398
399 if (!test_bit(cmd, &cmd_mask)
400 || !test_bit(func, &nfit_mem->dsm_mask))
349 return -ENOTTY; 401 return -ENOTTY;
350 402
351 /* lookup label space for the given dimm */ 403 /* lookup label space for the given dimm */
@@ -356,7 +408,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
356 if (i >= ARRAY_SIZE(handle)) 408 if (i >= ARRAY_SIZE(handle))
357 return -ENXIO; 409 return -ENXIO;
358 410
359 switch (cmd) { 411 switch (func) {
360 case ND_CMD_GET_CONFIG_SIZE: 412 case ND_CMD_GET_CONFIG_SIZE:
361 rc = nfit_test_cmd_get_config_size(buf, buf_len); 413 rc = nfit_test_cmd_get_config_size(buf, buf_len);
362 break; 414 break;
@@ -368,16 +420,22 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
368 rc = nfit_test_cmd_set_config_data(buf, buf_len, 420 rc = nfit_test_cmd_set_config_data(buf, buf_len,
369 t->label[i]); 421 t->label[i]);
370 break; 422 break;
423 case ND_CMD_SMART:
424 rc = nfit_test_cmd_smart(buf, buf_len);
425 break;
426 case ND_CMD_SMART_THRESHOLD:
427 rc = nfit_test_cmd_smart_threshold(buf, buf_len);
428 break;
371 default: 429 default:
372 return -ENOTTY; 430 return -ENOTTY;
373 } 431 }
374 } else { 432 } else {
375 struct ars_state *ars_state = &t->ars_state; 433 struct ars_state *ars_state = &t->ars_state;
376 434
377 if (!nd_desc || !test_bit(cmd, &nd_desc->dsm_mask)) 435 if (!nd_desc || !test_bit(cmd, &nd_desc->cmd_mask))
378 return -ENOTTY; 436 return -ENOTTY;
379 437
380 switch (cmd) { 438 switch (func) {
381 case ND_CMD_ARS_CAP: 439 case ND_CMD_ARS_CAP:
382 rc = nfit_test_cmd_ars_cap(buf, buf_len); 440 rc = nfit_test_cmd_ars_cap(buf, buf_len);
383 break; 441 break;
@@ -1251,13 +1309,15 @@ static void nfit_test0_setup(struct nfit_test *t)
1251 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); 1309 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE);
1252 1310
1253 acpi_desc = &t->acpi_desc; 1311 acpi_desc = &t->acpi_desc;
1254 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); 1312 set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
1255 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 1313 set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1256 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); 1314 set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
1257 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); 1315 set_bit(ND_CMD_SMART, &acpi_desc->dimm_cmd_force_en);
1258 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); 1316 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1259 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); 1317 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1260 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); 1318 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1319 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1320 set_bit(ND_CMD_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
1261} 1321}
1262 1322
1263static void nfit_test1_setup(struct nfit_test *t) 1323static void nfit_test1_setup(struct nfit_test *t)
@@ -1315,10 +1375,10 @@ static void nfit_test1_setup(struct nfit_test *t)
1315 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE); 1375 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA2_SIZE);
1316 1376
1317 acpi_desc = &t->acpi_desc; 1377 acpi_desc = &t->acpi_desc;
1318 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en); 1378 set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
1319 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en); 1379 set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
1320 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en); 1380 set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
1321 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_dsm_force_en); 1381 set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
1322} 1382}
1323 1383
1324static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, 1384static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index 604212db9d4b..3b530467148e 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -3,7 +3,7 @@ CFLAGS += -I. -g -Wall -D_LGPL_SOURCE
3LDFLAGS += -lpthread -lurcu 3LDFLAGS += -lpthread -lurcu
4TARGETS = main 4TARGETS = main
5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \ 5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \
6 regression1.o regression2.o regression3.o 6 regression1.o regression2.o regression3.o multiorder.o
7 7
8targets: $(TARGETS) 8targets: $(TARGETS)
9 9
@@ -13,7 +13,7 @@ main: $(OFILES)
13clean: 13clean:
14 $(RM) -f $(TARGETS) *.o radix-tree.c 14 $(RM) -f $(TARGETS) *.o radix-tree.c
15 15
16$(OFILES): *.h */*.h 16$(OFILES): *.h */*.h ../../../include/linux/radix-tree.h ../../include/linux/*.h
17 17
18radix-tree.c: ../../../lib/radix-tree.c 18radix-tree.c: ../../../lib/radix-tree.c
19 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@ 19 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
diff --git a/tools/testing/radix-tree/generated/autoconf.h b/tools/testing/radix-tree/generated/autoconf.h
new file mode 100644
index 000000000000..ad18cf5a2a3a
--- /dev/null
+++ b/tools/testing/radix-tree/generated/autoconf.h
@@ -0,0 +1,3 @@
1#define CONFIG_RADIX_TREE_MULTIORDER 1
2#define CONFIG_SHMEM 1
3#define CONFIG_SWAP 1
diff --git a/tools/testing/radix-tree/linux/init.h b/tools/testing/radix-tree/linux/init.h
new file mode 100644
index 000000000000..360cabb3c4e7
--- /dev/null
+++ b/tools/testing/radix-tree/linux/init.h
@@ -0,0 +1 @@
/* An empty file stub that allows radix-tree.c to compile. */
diff --git a/tools/testing/radix-tree/linux/kernel.h b/tools/testing/radix-tree/linux/kernel.h
index ae013b0160ac..be98a47b4e1b 100644
--- a/tools/testing/radix-tree/linux/kernel.h
+++ b/tools/testing/radix-tree/linux/kernel.h
@@ -7,19 +7,28 @@
7#include <stddef.h> 7#include <stddef.h>
8#include <limits.h> 8#include <limits.h>
9 9
10#include "../../include/linux/compiler.h"
11#include "../../../include/linux/kconfig.h"
12
13#define RADIX_TREE_MAP_SHIFT 3
14
10#ifndef NULL 15#ifndef NULL
11#define NULL 0 16#define NULL 0
12#endif 17#endif
13 18
14#define BUG_ON(expr) assert(!(expr)) 19#define BUG_ON(expr) assert(!(expr))
20#define WARN_ON(expr) assert(!(expr))
15#define __init 21#define __init
16#define __must_check 22#define __must_check
17#define panic(expr) 23#define panic(expr)
18#define printk printf 24#define printk printf
19#define __force 25#define __force
20#define likely(c) (c)
21#define unlikely(c) (c)
22#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 26#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
27#define pr_debug printk
28
29#define smp_rmb() barrier()
30#define smp_wmb() barrier()
31#define cpu_relax() barrier()
23 32
24#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 33#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
25 34
@@ -28,6 +37,8 @@
28 (type *)( (char *)__mptr - offsetof(type, member) );}) 37 (type *)( (char *)__mptr - offsetof(type, member) );})
29#define min(a, b) ((a) < (b) ? (a) : (b)) 38#define min(a, b) ((a) < (b) ? (a) : (b))
30 39
40#define cond_resched() sched_yield()
41
31static inline int in_interrupt(void) 42static inline int in_interrupt(void)
32{ 43{
33 return 0; 44 return 0;
diff --git a/tools/testing/radix-tree/linux/slab.h b/tools/testing/radix-tree/linux/slab.h
index 57282506c21d..6d5a34770fd4 100644
--- a/tools/testing/radix-tree/linux/slab.h
+++ b/tools/testing/radix-tree/linux/slab.h
@@ -3,7 +3,6 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6#define GFP_KERNEL 1
7#define SLAB_HWCACHE_ALIGN 1 6#define SLAB_HWCACHE_ALIGN 1
8#define SLAB_PANIC 2 7#define SLAB_PANIC 2
9#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */ 8#define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* Objects are reclaimable */
diff --git a/tools/testing/radix-tree/linux/types.h b/tools/testing/radix-tree/linux/types.h
index 72a9d85f6c76..faa0b6ff9ca8 100644
--- a/tools/testing/radix-tree/linux/types.h
+++ b/tools/testing/radix-tree/linux/types.h
@@ -1,15 +1,13 @@
1#ifndef _TYPES_H 1#ifndef _TYPES_H
2#define _TYPES_H 2#define _TYPES_H
3 3
4#include "../../include/linux/types.h"
5
4#define __rcu 6#define __rcu
5#define __read_mostly 7#define __read_mostly
6 8
7#define BITS_PER_LONG (sizeof(long) * 8) 9#define BITS_PER_LONG (sizeof(long) * 8)
8 10
9struct list_head {
10 struct list_head *next, *prev;
11};
12
13static inline void INIT_LIST_HEAD(struct list_head *list) 11static inline void INIT_LIST_HEAD(struct list_head *list)
14{ 12{
15 list->next = list; 13 list->next = list;
@@ -22,7 +20,6 @@ typedef struct {
22 20
23#define uninitialized_var(x) x = x 21#define uninitialized_var(x) x = x
24 22
25typedef unsigned gfp_t;
26#include <linux/gfp.h> 23#include <linux/gfp.h>
27 24
28#endif 25#endif
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c
index 0e83cad27a9f..b7619ff3b552 100644
--- a/tools/testing/radix-tree/main.c
+++ b/tools/testing/radix-tree/main.c
@@ -61,11 +61,11 @@ void __big_gang_check(void)
61 } while (!wrapped); 61 } while (!wrapped);
62} 62}
63 63
64void big_gang_check(void) 64void big_gang_check(bool long_run)
65{ 65{
66 int i; 66 int i;
67 67
68 for (i = 0; i < 1000; i++) { 68 for (i = 0; i < (long_run ? 1000 : 3); i++) {
69 __big_gang_check(); 69 __big_gang_check();
70 srand(time(0)); 70 srand(time(0));
71 printf("%d ", i); 71 printf("%d ", i);
@@ -232,10 +232,72 @@ void copy_tag_check(void)
232 item_kill_tree(&tree); 232 item_kill_tree(&tree);
233} 233}
234 234
235static void single_thread_tests(void) 235static void __locate_check(struct radix_tree_root *tree, unsigned long index,
236 unsigned order)
237{
238 struct item *item;
239 unsigned long index2;
240
241 item_insert_order(tree, index, order);
242 item = item_lookup(tree, index);
243 index2 = radix_tree_locate_item(tree, item);
244 if (index != index2) {
245 printf("index %ld order %d inserted; found %ld\n",
246 index, order, index2);
247 abort();
248 }
249}
250
251static void __order_0_locate_check(void)
252{
253 RADIX_TREE(tree, GFP_KERNEL);
254 int i;
255
256 for (i = 0; i < 50; i++)
257 __locate_check(&tree, rand() % INT_MAX, 0);
258
259 item_kill_tree(&tree);
260}
261
262static void locate_check(void)
263{
264 RADIX_TREE(tree, GFP_KERNEL);
265 unsigned order;
266 unsigned long offset, index;
267
268 __order_0_locate_check();
269
270 for (order = 0; order < 20; order++) {
271 for (offset = 0; offset < (1 << (order + 3));
272 offset += (1UL << order)) {
273 for (index = 0; index < (1UL << (order + 5));
274 index += (1UL << order)) {
275 __locate_check(&tree, index + offset, order);
276 }
277 if (radix_tree_locate_item(&tree, &tree) != -1)
278 abort();
279
280 item_kill_tree(&tree);
281 }
282 }
283
284 if (radix_tree_locate_item(&tree, &tree) != -1)
285 abort();
286 __locate_check(&tree, -1, 0);
287 if (radix_tree_locate_item(&tree, &tree) != -1)
288 abort();
289 item_kill_tree(&tree);
290}
291
292static void single_thread_tests(bool long_run)
236{ 293{
237 int i; 294 int i;
238 295
296 printf("starting single_thread_tests: %d allocated\n", nr_allocated);
297 multiorder_checks();
298 printf("after multiorder_check: %d allocated\n", nr_allocated);
299 locate_check();
300 printf("after locate_check: %d allocated\n", nr_allocated);
239 tag_check(); 301 tag_check();
240 printf("after tag_check: %d allocated\n", nr_allocated); 302 printf("after tag_check: %d allocated\n", nr_allocated);
241 gang_check(); 303 gang_check();
@@ -244,9 +306,9 @@ static void single_thread_tests(void)
244 printf("after add_and_check: %d allocated\n", nr_allocated); 306 printf("after add_and_check: %d allocated\n", nr_allocated);
245 dynamic_height_check(); 307 dynamic_height_check();
246 printf("after dynamic_height_check: %d allocated\n", nr_allocated); 308 printf("after dynamic_height_check: %d allocated\n", nr_allocated);
247 big_gang_check(); 309 big_gang_check(long_run);
248 printf("after big_gang_check: %d allocated\n", nr_allocated); 310 printf("after big_gang_check: %d allocated\n", nr_allocated);
249 for (i = 0; i < 2000; i++) { 311 for (i = 0; i < (long_run ? 2000 : 3); i++) {
250 copy_tag_check(); 312 copy_tag_check();
251 printf("%d ", i); 313 printf("%d ", i);
252 fflush(stdout); 314 fflush(stdout);
@@ -254,15 +316,23 @@ static void single_thread_tests(void)
254 printf("after copy_tag_check: %d allocated\n", nr_allocated); 316 printf("after copy_tag_check: %d allocated\n", nr_allocated);
255} 317}
256 318
257int main(void) 319int main(int argc, char **argv)
258{ 320{
321 bool long_run = false;
322 int opt;
323
324 while ((opt = getopt(argc, argv, "l")) != -1) {
325 if (opt == 'l')
326 long_run = true;
327 }
328
259 rcu_register_thread(); 329 rcu_register_thread();
260 radix_tree_init(); 330 radix_tree_init();
261 331
262 regression1_test(); 332 regression1_test();
263 regression2_test(); 333 regression2_test();
264 regression3_test(); 334 regression3_test();
265 single_thread_tests(); 335 single_thread_tests(long_run);
266 336
267 sleep(1); 337 sleep(1);
268 printf("after sleep(1): %d allocated\n", nr_allocated); 338 printf("after sleep(1): %d allocated\n", nr_allocated);
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
new file mode 100644
index 000000000000..39d9b9568fe2
--- /dev/null
+++ b/tools/testing/radix-tree/multiorder.c
@@ -0,0 +1,337 @@
1/*
2 * multiorder.c: Multi-order radix tree entry testing
3 * Copyright (c) 2016 Intel Corporation
4 * Author: Ross Zwisler <ross.zwisler@linux.intel.com>
5 * Author: Matthew Wilcox <matthew.r.wilcox@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 */
16#include <linux/radix-tree.h>
17#include <linux/slab.h>
18#include <linux/errno.h>
19
20#include "test.h"
21
22#define for_each_index(i, base, order) \
23 for (i = base; i < base + (1 << order); i++)
24
25static void __multiorder_tag_test(int index, int order)
26{
27 RADIX_TREE(tree, GFP_KERNEL);
28 int base, err, i;
29 unsigned long first = 0;
30
31 /* our canonical entry */
32 base = index & ~((1 << order) - 1);
33
34 printf("Multiorder tag test with index %d, canonical entry %d\n",
35 index, base);
36
37 err = item_insert_order(&tree, index, order);
38 assert(!err);
39
40 /*
41 * Verify we get collisions for covered indices. We try and fail to
42 * insert an exceptional entry so we don't leak memory via
43 * item_insert_order().
44 */
45 for_each_index(i, base, order) {
46 err = __radix_tree_insert(&tree, i, order,
47 (void *)(0xA0 | RADIX_TREE_EXCEPTIONAL_ENTRY));
48 assert(err == -EEXIST);
49 }
50
51 for_each_index(i, base, order) {
52 assert(!radix_tree_tag_get(&tree, i, 0));
53 assert(!radix_tree_tag_get(&tree, i, 1));
54 }
55
56 assert(radix_tree_tag_set(&tree, index, 0));
57
58 for_each_index(i, base, order) {
59 assert(radix_tree_tag_get(&tree, i, 0));
60 assert(!radix_tree_tag_get(&tree, i, 1));
61 }
62
63 assert(radix_tree_range_tag_if_tagged(&tree, &first, ~0UL, 10, 0, 1) == 1);
64 assert(radix_tree_tag_clear(&tree, index, 0));
65
66 for_each_index(i, base, order) {
67 assert(!radix_tree_tag_get(&tree, i, 0));
68 assert(radix_tree_tag_get(&tree, i, 1));
69 }
70
71 assert(radix_tree_tag_clear(&tree, index, 1));
72
73 assert(!radix_tree_tagged(&tree, 0));
74 assert(!radix_tree_tagged(&tree, 1));
75
76 item_kill_tree(&tree);
77}
78
79static void multiorder_tag_tests(void)
80{
81 /* test multi-order entry for indices 0-7 with no sibling pointers */
82 __multiorder_tag_test(0, 3);
83 __multiorder_tag_test(5, 3);
84
85 /* test multi-order entry for indices 8-15 with no sibling pointers */
86 __multiorder_tag_test(8, 3);
87 __multiorder_tag_test(15, 3);
88
89 /*
90 * Our order 5 entry covers indices 0-31 in a tree with height=2.
91 * This is broken up as follows:
92 * 0-7: canonical entry
93 * 8-15: sibling 1
94 * 16-23: sibling 2
95 * 24-31: sibling 3
96 */
97 __multiorder_tag_test(0, 5);
98 __multiorder_tag_test(29, 5);
99
100 /* same test, but with indices 32-63 */
101 __multiorder_tag_test(32, 5);
102 __multiorder_tag_test(44, 5);
103
104 /*
105 * Our order 8 entry covers indices 0-255 in a tree with height=3.
106 * This is broken up as follows:
107 * 0-63: canonical entry
108 * 64-127: sibling 1
109 * 128-191: sibling 2
110 * 192-255: sibling 3
111 */
112 __multiorder_tag_test(0, 8);
113 __multiorder_tag_test(190, 8);
114
115 /* same test, but with indices 256-511 */
116 __multiorder_tag_test(256, 8);
117 __multiorder_tag_test(300, 8);
118
119 __multiorder_tag_test(0x12345678UL, 8);
120}
121
122static void multiorder_check(unsigned long index, int order)
123{
124 unsigned long i;
125 unsigned long min = index & ~((1UL << order) - 1);
126 unsigned long max = min + (1UL << order);
127 RADIX_TREE(tree, GFP_KERNEL);
128
129 printf("Multiorder index %ld, order %d\n", index, order);
130
131 assert(item_insert_order(&tree, index, order) == 0);
132
133 for (i = min; i < max; i++) {
134 struct item *item = item_lookup(&tree, i);
135 assert(item != 0);
136 assert(item->index == index);
137 }
138 for (i = 0; i < min; i++)
139 item_check_absent(&tree, i);
140 for (i = max; i < 2*max; i++)
141 item_check_absent(&tree, i);
142 for (i = min; i < max; i++) {
143 static void *entry = (void *)
144 (0xA0 | RADIX_TREE_EXCEPTIONAL_ENTRY);
145 assert(radix_tree_insert(&tree, i, entry) == -EEXIST);
146 }
147
148 assert(item_delete(&tree, index) != 0);
149
150 for (i = 0; i < 2*max; i++)
151 item_check_absent(&tree, i);
152}
153
154static void multiorder_shrink(unsigned long index, int order)
155{
156 unsigned long i;
157 unsigned long max = 1 << order;
158 RADIX_TREE(tree, GFP_KERNEL);
159 struct radix_tree_node *node;
160
161 printf("Multiorder shrink index %ld, order %d\n", index, order);
162
163 assert(item_insert_order(&tree, 0, order) == 0);
164
165 node = tree.rnode;
166
167 assert(item_insert(&tree, index) == 0);
168 assert(node != tree.rnode);
169
170 assert(item_delete(&tree, index) != 0);
171 assert(node == tree.rnode);
172
173 for (i = 0; i < max; i++) {
174 struct item *item = item_lookup(&tree, i);
175 assert(item != 0);
176 assert(item->index == 0);
177 }
178 for (i = max; i < 2*max; i++)
179 item_check_absent(&tree, i);
180
181 if (!item_delete(&tree, 0)) {
182 printf("failed to delete index %ld (order %d)\n", index, order); abort();
183 }
184
185 for (i = 0; i < 2*max; i++)
186 item_check_absent(&tree, i);
187}
188
189static void multiorder_insert_bug(void)
190{
191 RADIX_TREE(tree, GFP_KERNEL);
192
193 item_insert(&tree, 0);
194 radix_tree_tag_set(&tree, 0, 0);
195 item_insert_order(&tree, 3 << 6, 6);
196
197 item_kill_tree(&tree);
198}
199
200void multiorder_iteration(void)
201{
202 RADIX_TREE(tree, GFP_KERNEL);
203 struct radix_tree_iter iter;
204 void **slot;
205 int i, j, err;
206
207 printf("Multiorder iteration test\n");
208
209#define NUM_ENTRIES 11
210 int index[NUM_ENTRIES] = {0, 2, 4, 8, 16, 32, 34, 36, 64, 72, 128};
211 int order[NUM_ENTRIES] = {1, 1, 2, 3, 4, 1, 0, 1, 3, 0, 7};
212
213 for (i = 0; i < NUM_ENTRIES; i++) {
214 err = item_insert_order(&tree, index[i], order[i]);
215 assert(!err);
216 }
217
218 for (j = 0; j < 256; j++) {
219 for (i = 0; i < NUM_ENTRIES; i++)
220 if (j <= (index[i] | ((1 << order[i]) - 1)))
221 break;
222
223 radix_tree_for_each_slot(slot, &tree, &iter, j) {
224 int height = order[i] / RADIX_TREE_MAP_SHIFT;
225 int shift = height * RADIX_TREE_MAP_SHIFT;
226 int mask = (1 << order[i]) - 1;
227
228 assert(iter.index >= (index[i] &~ mask));
229 assert(iter.index <= (index[i] | mask));
230 assert(iter.shift == shift);
231 i++;
232 }
233 }
234
235 item_kill_tree(&tree);
236}
237
238void multiorder_tagged_iteration(void)
239{
240 RADIX_TREE(tree, GFP_KERNEL);
241 struct radix_tree_iter iter;
242 void **slot;
243 unsigned long first = 0;
244 int i, j;
245
246 printf("Multiorder tagged iteration test\n");
247
248#define MT_NUM_ENTRIES 9
249 int index[MT_NUM_ENTRIES] = {0, 2, 4, 16, 32, 40, 64, 72, 128};
250 int order[MT_NUM_ENTRIES] = {1, 0, 2, 4, 3, 1, 3, 0, 7};
251
252#define TAG_ENTRIES 7
253 int tag_index[TAG_ENTRIES] = {0, 4, 16, 40, 64, 72, 128};
254
255 for (i = 0; i < MT_NUM_ENTRIES; i++)
256 assert(!item_insert_order(&tree, index[i], order[i]));
257
258 assert(!radix_tree_tagged(&tree, 1));
259
260 for (i = 0; i < TAG_ENTRIES; i++)
261 assert(radix_tree_tag_set(&tree, tag_index[i], 1));
262
263 for (j = 0; j < 256; j++) {
264 int mask, k;
265
266 for (i = 0; i < TAG_ENTRIES; i++) {
267 for (k = i; index[k] < tag_index[i]; k++)
268 ;
269 if (j <= (index[k] | ((1 << order[k]) - 1)))
270 break;
271 }
272
273 radix_tree_for_each_tagged(slot, &tree, &iter, j, 1) {
274 for (k = i; index[k] < tag_index[i]; k++)
275 ;
276 mask = (1 << order[k]) - 1;
277
278 assert(iter.index >= (tag_index[i] &~ mask));
279 assert(iter.index <= (tag_index[i] | mask));
280 i++;
281 }
282 }
283
284 radix_tree_range_tag_if_tagged(&tree, &first, ~0UL,
285 MT_NUM_ENTRIES, 1, 2);
286
287 for (j = 0; j < 256; j++) {
288 int mask, k;
289
290 for (i = 0; i < TAG_ENTRIES; i++) {
291 for (k = i; index[k] < tag_index[i]; k++)
292 ;
293 if (j <= (index[k] | ((1 << order[k]) - 1)))
294 break;
295 }
296
297 radix_tree_for_each_tagged(slot, &tree, &iter, j, 2) {
298 for (k = i; index[k] < tag_index[i]; k++)
299 ;
300 mask = (1 << order[k]) - 1;
301
302 assert(iter.index >= (tag_index[i] &~ mask));
303 assert(iter.index <= (tag_index[i] | mask));
304 i++;
305 }
306 }
307
308 first = 1;
309 radix_tree_range_tag_if_tagged(&tree, &first, ~0UL,
310 MT_NUM_ENTRIES, 1, 0);
311 i = 0;
312 radix_tree_for_each_tagged(slot, &tree, &iter, 0, 0) {
313 assert(iter.index == tag_index[i]);
314 i++;
315 }
316
317 item_kill_tree(&tree);
318}
319
320void multiorder_checks(void)
321{
322 int i;
323
324 for (i = 0; i < 20; i++) {
325 multiorder_check(200, i);
326 multiorder_check(0, i);
327 multiorder_check((1UL << i) + 1, i);
328 }
329
330 for (i = 0; i < 15; i++)
331 multiorder_shrink((1UL << (i + RADIX_TREE_MAP_SHIFT)), i);
332
333 multiorder_insert_bug();
334 multiorder_tag_tests();
335 multiorder_iteration();
336 multiorder_tagged_iteration();
337}
diff --git a/tools/testing/radix-tree/regression2.c b/tools/testing/radix-tree/regression2.c
index 5d2fa28cdca3..63bf347aaf33 100644
--- a/tools/testing/radix-tree/regression2.c
+++ b/tools/testing/radix-tree/regression2.c
@@ -51,13 +51,6 @@
51 51
52#include "regression.h" 52#include "regression.h"
53 53
54#ifdef __KERNEL__
55#define RADIX_TREE_MAP_SHIFT (CONFIG_BASE_SMALL ? 4 : 6)
56#else
57#define RADIX_TREE_MAP_SHIFT 3 /* For more stressful testing */
58#endif
59
60#define RADIX_TREE_MAP_SIZE (1UL << RADIX_TREE_MAP_SHIFT)
61#define PAGECACHE_TAG_DIRTY 0 54#define PAGECACHE_TAG_DIRTY 0
62#define PAGECACHE_TAG_WRITEBACK 1 55#define PAGECACHE_TAG_WRITEBACK 1
63#define PAGECACHE_TAG_TOWRITE 2 56#define PAGECACHE_TAG_TOWRITE 2
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c
index 83136be552a0..b7447ceb75e9 100644
--- a/tools/testing/radix-tree/tag_check.c
+++ b/tools/testing/radix-tree/tag_check.c
@@ -12,6 +12,7 @@
12static void 12static void
13__simple_checks(struct radix_tree_root *tree, unsigned long index, int tag) 13__simple_checks(struct radix_tree_root *tree, unsigned long index, int tag)
14{ 14{
15 unsigned long first = 0;
15 int ret; 16 int ret;
16 17
17 item_check_absent(tree, index); 18 item_check_absent(tree, index);
@@ -22,6 +23,10 @@ __simple_checks(struct radix_tree_root *tree, unsigned long index, int tag)
22 item_tag_set(tree, index, tag); 23 item_tag_set(tree, index, tag);
23 ret = item_tag_get(tree, index, tag); 24 ret = item_tag_get(tree, index, tag);
24 assert(ret != 0); 25 assert(ret != 0);
26 ret = radix_tree_range_tag_if_tagged(tree, &first, ~0UL, 10, tag, !tag);
27 assert(ret == 1);
28 ret = item_tag_get(tree, index, !tag);
29 assert(ret != 0);
25 ret = item_delete(tree, index); 30 ret = item_delete(tree, index);
26 assert(ret != 0); 31 assert(ret != 0);
27 item_insert(tree, index); 32 item_insert(tree, index);
@@ -304,6 +309,7 @@ static void single_check(void)
304 struct item *items[BATCH]; 309 struct item *items[BATCH];
305 RADIX_TREE(tree, GFP_KERNEL); 310 RADIX_TREE(tree, GFP_KERNEL);
306 int ret; 311 int ret;
312 unsigned long first = 0;
307 313
308 item_insert(&tree, 0); 314 item_insert(&tree, 0);
309 item_tag_set(&tree, 0, 0); 315 item_tag_set(&tree, 0, 0);
@@ -313,6 +319,10 @@ static void single_check(void)
313 assert(ret == 0); 319 assert(ret == 0);
314 verify_tag_consistency(&tree, 0); 320 verify_tag_consistency(&tree, 0);
315 verify_tag_consistency(&tree, 1); 321 verify_tag_consistency(&tree, 1);
322 ret = radix_tree_range_tag_if_tagged(&tree, &first, 10, 10, 0, 1);
323 assert(ret == 1);
324 ret = radix_tree_gang_lookup_tag(&tree, (void **)items, 0, BATCH, 1);
325 assert(ret == 1);
316 item_kill_tree(&tree); 326 item_kill_tree(&tree);
317} 327}
318 328
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c
index 2bebf34cdc27..a6e8099eaf4f 100644
--- a/tools/testing/radix-tree/test.c
+++ b/tools/testing/radix-tree/test.c
@@ -24,14 +24,21 @@ int item_tag_get(struct radix_tree_root *root, unsigned long index, int tag)
24 return radix_tree_tag_get(root, index, tag); 24 return radix_tree_tag_get(root, index, tag);
25} 25}
26 26
27int __item_insert(struct radix_tree_root *root, struct item *item) 27int __item_insert(struct radix_tree_root *root, struct item *item,
28 unsigned order)
28{ 29{
29 return radix_tree_insert(root, item->index, item); 30 return __radix_tree_insert(root, item->index, order, item);
30} 31}
31 32
32int item_insert(struct radix_tree_root *root, unsigned long index) 33int item_insert(struct radix_tree_root *root, unsigned long index)
33{ 34{
34 return __item_insert(root, item_create(index)); 35 return __item_insert(root, item_create(index), 0);
36}
37
38int item_insert_order(struct radix_tree_root *root, unsigned long index,
39 unsigned order)
40{
41 return __item_insert(root, item_create(index), order);
35} 42}
36 43
37int item_delete(struct radix_tree_root *root, unsigned long index) 44int item_delete(struct radix_tree_root *root, unsigned long index)
@@ -136,13 +143,13 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
136} 143}
137 144
138static int verify_node(struct radix_tree_node *slot, unsigned int tag, 145static int verify_node(struct radix_tree_node *slot, unsigned int tag,
139 unsigned int height, int tagged) 146 int tagged)
140{ 147{
141 int anyset = 0; 148 int anyset = 0;
142 int i; 149 int i;
143 int j; 150 int j;
144 151
145 slot = indirect_to_ptr(slot); 152 slot = entry_to_node(slot);
146 153
147 /* Verify consistency at this level */ 154 /* Verify consistency at this level */
148 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++) { 155 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++) {
@@ -152,7 +159,8 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag,
152 } 159 }
153 } 160 }
154 if (tagged != anyset) { 161 if (tagged != anyset) {
155 printf("tag: %u, height %u, tagged: %d, anyset: %d\n", tag, height, tagged, anyset); 162 printf("tag: %u, shift %u, tagged: %d, anyset: %d\n",
163 tag, slot->shift, tagged, anyset);
156 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) { 164 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) {
157 printf("tag %d: ", j); 165 printf("tag %d: ", j);
158 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++) 166 for (i = 0; i < RADIX_TREE_TAG_LONGS; i++)
@@ -164,10 +172,10 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag,
164 assert(tagged == anyset); 172 assert(tagged == anyset);
165 173
166 /* Go for next level */ 174 /* Go for next level */
167 if (height > 1) { 175 if (slot->shift > 0) {
168 for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) 176 for (i = 0; i < RADIX_TREE_MAP_SIZE; i++)
169 if (slot->slots[i]) 177 if (slot->slots[i])
170 if (verify_node(slot->slots[i], tag, height - 1, 178 if (verify_node(slot->slots[i], tag,
171 !!test_bit(i, slot->tags[tag]))) { 179 !!test_bit(i, slot->tags[tag]))) {
172 printf("Failure at off %d\n", i); 180 printf("Failure at off %d\n", i);
173 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) { 181 for (j = 0; j < RADIX_TREE_MAX_TAGS; j++) {
@@ -184,9 +192,10 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag,
184 192
185void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag) 193void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag)
186{ 194{
187 if (!root->height) 195 struct radix_tree_node *node = root->rnode;
196 if (!radix_tree_is_internal_node(node))
188 return; 197 return;
189 verify_node(root->rnode, tag, root->height, !!root_tag_get(root, tag)); 198 verify_node(node, tag, !!root_tag_get(root, tag));
190} 199}
191 200
192void item_kill_tree(struct radix_tree_root *root) 201void item_kill_tree(struct radix_tree_root *root)
@@ -211,9 +220,19 @@ void item_kill_tree(struct radix_tree_root *root)
211 220
212void tree_verify_min_height(struct radix_tree_root *root, int maxindex) 221void tree_verify_min_height(struct radix_tree_root *root, int maxindex)
213{ 222{
214 assert(radix_tree_maxindex(root->height) >= maxindex); 223 unsigned shift;
215 if (root->height > 1) 224 struct radix_tree_node *node = root->rnode;
216 assert(radix_tree_maxindex(root->height-1) < maxindex); 225 if (!radix_tree_is_internal_node(node)) {
217 else if (root->height == 1) 226 assert(maxindex == 0);
218 assert(radix_tree_maxindex(root->height-1) <= maxindex); 227 return;
228 }
229
230 node = entry_to_node(node);
231 assert(maxindex <= node_maxindex(node));
232
233 shift = node->shift;
234 if (shift > 0)
235 assert(maxindex > shift_maxindex(shift - RADIX_TREE_MAP_SHIFT));
236 else
237 assert(maxindex > 0);
219} 238}
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index 4e1d95faaa94..e85131369723 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -8,8 +8,11 @@ struct item {
8}; 8};
9 9
10struct item *item_create(unsigned long index); 10struct item *item_create(unsigned long index);
11int __item_insert(struct radix_tree_root *root, struct item *item); 11int __item_insert(struct radix_tree_root *root, struct item *item,
12 unsigned order);
12int item_insert(struct radix_tree_root *root, unsigned long index); 13int item_insert(struct radix_tree_root *root, unsigned long index);
14int item_insert_order(struct radix_tree_root *root, unsigned long index,
15 unsigned order);
13int item_delete(struct radix_tree_root *root, unsigned long index); 16int item_delete(struct radix_tree_root *root, unsigned long index);
14struct item *item_lookup(struct radix_tree_root *root, unsigned long index); 17struct item *item_lookup(struct radix_tree_root *root, unsigned long index);
15 18
@@ -23,6 +26,7 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
23void item_kill_tree(struct radix_tree_root *root); 26void item_kill_tree(struct radix_tree_root *root);
24 27
25void tag_check(void); 28void tag_check(void);
29void multiorder_checks(void);
26 30
27struct item * 31struct item *
28item_tag_set(struct radix_tree_root *root, unsigned long index, int tag); 32item_tag_set(struct radix_tree_root *root, unsigned long index, int tag);
@@ -35,6 +39,7 @@ void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag);
35extern int nr_allocated; 39extern int nr_allocated;
36 40
37/* Normally private parts of lib/radix-tree.c */ 41/* Normally private parts of lib/radix-tree.c */
38void *indirect_to_ptr(void *ptr); 42void radix_tree_dump(struct radix_tree_root *root);
39int root_tag_get(struct radix_tree_root *root, unsigned int tag); 43int root_tag_get(struct radix_tree_root *root, unsigned int tag);
40unsigned long radix_tree_maxindex(unsigned int height); 44unsigned long node_maxindex(struct radix_tree_node *);
45unsigned long shift_maxindex(unsigned int shift);
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/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
index da48812ab95e..4c6a0bf8ba79 100755
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -88,7 +88,12 @@ parse_opts() { # opts
88 88
89# Parameters 89# Parameters
90DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1` 90DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1`
91TRACING_DIR=$DEBUGFS_DIR/tracing 91if [ -z "$DEBUGFS_DIR" ]; then
92 TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1`
93else
94 TRACING_DIR=$DEBUGFS_DIR/tracing
95fi
96
92TOP_DIR=`absdir $0` 97TOP_DIR=`absdir $0`
93TEST_DIR=$TOP_DIR/test.d 98TEST_DIR=$TOP_DIR/test.d
94TEST_CASES=`find_testcases $TEST_DIR` 99TEST_CASES=`find_testcases $TEST_DIR`
@@ -102,7 +107,7 @@ parse_opts $*
102[ $DEBUG -ne 0 ] && set -x 107[ $DEBUG -ne 0 ] && set -x
103 108
104# Verify parameters 109# Verify parameters
105if [ -z "$DEBUGFS_DIR" -o ! -d "$TRACING_DIR" ]; then 110if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then
106 errexit "No ftrace directory found" 111 errexit "No ftrace directory found"
107fi 112fi
108 113
diff --git a/tools/testing/selftests/ftrace/test.d/event/event-pid.tc b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc
new file mode 100644
index 000000000000..d4ab27b522f8
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc
@@ -0,0 +1,72 @@
1#!/bin/sh
2# description: event tracing - restricts events based on pid
3
4do_reset() {
5 echo > set_event
6 echo > set_event_pid
7 echo 0 > options/event-fork
8 clear_trace
9}
10
11fail() { #msg
12 do_reset
13 echo $1
14 exit $FAIL
15}
16
17yield() {
18 ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1
19}
20
21if [ ! -f set_event -o ! -d events/sched ]; then
22 echo "event tracing is not supported"
23 exit_unsupported
24fi
25
26if [ ! -f set_event_pid ]; then
27 echo "event pid filtering is not supported"
28 exit_unsupported
29fi
30
31reset_tracer
32do_reset
33
34echo 1 > events/sched/sched_switch/enable
35
36yield
37
38count=`cat trace | grep sched_switch | wc -l`
39if [ $count -eq 0 ]; then
40 fail "sched_switch events are not recorded"
41fi
42
43do_reset
44
45read mypid rest < /proc/self/stat
46
47echo $mypid > set_event_pid
48echo 'sched:sched_switch' > set_event
49
50yield
51
52count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l`
53if [ $count -ne 0 ]; then
54 fail "sched_switch events from other task are recorded"
55fi
56
57do_reset
58
59echo $mypid > set_event_pid
60echo 1 > options/event-fork
61echo 1 > events/sched/sched_switch/enable
62
63yield
64
65count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l`
66if [ $count -eq 0 ]; then
67 fail "sched_switch events from other task are not recorded"
68fi
69
70do_reset
71
72exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions
index 5d8cd06d920f..c37262f6c269 100644
--- a/tools/testing/selftests/ftrace/test.d/functions
+++ b/tools/testing/selftests/ftrace/test.d/functions
@@ -14,3 +14,12 @@ enable_tracing() { # start trace recording
14reset_tracer() { # reset the current tracer 14reset_tracer() { # reset the current tracer
15 echo nop > current_tracer 15 echo nop > current_tracer
16} 16}
17
18reset_trigger() { # reset all current setting triggers
19 grep -v ^# events/*/*/trigger |
20 while read line; do
21 cmd=`echo $line | cut -f2- -d: | cut -f1 -d" "`
22 echo "!$cmd" > `echo $line | cut -f1 -d:`
23 done
24}
25
diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
new file mode 100644
index 000000000000..4c5a061a5b4e
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
@@ -0,0 +1,138 @@
1#!/bin/sh
2# description: Test creation and deletion of trace instances while setting an event
3
4if [ ! -d instances ] ; then
5 echo "no instance directory with this kernel"
6 exit_unsupported;
7fi
8
9fail() { # mesg
10 rmdir foo 2>/dev/null
11 echo $1
12 set -e
13 exit $FAIL
14}
15
16cd instances
17
18# we don't want to fail on error
19set +e
20
21mkdir x
22rmdir x
23result=$?
24
25if [ $result -ne 0 ]; then
26 echo "instance rmdir not supported"
27 exit_unsupported
28fi
29
30instance_slam() {
31 while :; do
32 mkdir foo 2> /dev/null
33 rmdir foo 2> /dev/null
34 done
35}
36
37instance_read() {
38 while :; do
39 cat foo/trace 1> /dev/null 2>&1
40 done
41}
42
43instance_set() {
44 while :; do
45 echo 1 > foo/events/sched/sched_switch
46 done 2> /dev/null
47}
48
49instance_slam &
50p1=$!
51echo $p1
52
53instance_set &
54p2=$!
55echo $p2
56
57instance_read &
58p3=$!
59echo $p3
60
61sleep 1
62
63kill -1 $p3
64kill -1 $p2
65kill -1 $p1
66
67echo "Wait for processes to finish"
68wait $p1 $p2 $p3
69echo "all processes finished, wait for cleanup"
70sleep 1
71
72mkdir foo
73ls foo > /dev/null
74rmdir foo
75if [ -d foo ]; then
76 fail "foo still exists"
77fi
78exit 0
79
80
81
82
83instance_slam() {
84 while :; do
85 mkdir x
86 mkdir y
87 mkdir z
88 rmdir x
89 rmdir y
90 rmdir z
91 done 2>/dev/null
92}
93
94instance_slam &
95p1=$!
96echo $p1
97
98instance_slam &
99p2=$!
100echo $p2
101
102instance_slam &
103p3=$!
104echo $p3
105
106instance_slam &
107p4=$!
108echo $p4
109
110instance_slam &
111p5=$!
112echo $p5
113
114ls -lR >/dev/null
115sleep 1
116
117kill -1 $p1
118kill -1 $p2
119kill -1 $p3
120kill -1 $p4
121kill -1 $p5
122
123echo "Wait for processes to finish"
124wait $p1 $p2 $p3 $p4 $p5
125echo "all processes finished, wait for cleanup"
126
127mkdir x y z
128ls x y z
129rmdir x y z
130for d in x y z; do
131 if [ -d $d ]; then
132 fail "instance $d still exists"
133 fi
134done
135
136set -e
137
138exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
new file mode 100644
index 000000000000..1a9445021bf1
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
@@ -0,0 +1,64 @@
1#!/bin/sh
2# description: event trigger - test event enable/disable trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep enable_event events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "event enable/disable trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test enable_event trigger"
36echo 0 > events/sched/sched_switch/enable
37echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
38( echo "forked")
39if [ `cat events/sched/sched_switch/enable` != '1*' ]; then
40 fail "enable_event trigger on sched_process_fork did not work"
41fi
42
43reset_trigger
44
45echo "Test disable_event trigger"
46echo 1 > events/sched/sched_switch/enable
47echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
48( echo "forked")
49if [ `cat events/sched/sched_switch/enable` != '0*' ]; then
50 fail "disable_event trigger on sched_process_fork did not work"
51fi
52
53reset_trigger
54
55echo "Test semantic error for event enable/disable trigger"
56! echo 'enable_event:nogroup:noevent' > events/sched/sched_process_fork/trigger
57! echo 'disable_event+1' > events/sched/sched_process_fork/trigger
58echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
59! echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
60! echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger
61
62do_reset
63
64exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
new file mode 100644
index 000000000000..514e466e198b
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
@@ -0,0 +1,59 @@
1#!/bin/sh
2# description: event trigger - test trigger filter
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29echo "Test trigger filter"
30echo 1 > tracing_on
31echo 'traceoff if child_pid == 0' > events/sched/sched_process_fork/trigger
32( echo "forked")
33if [ `cat tracing_on` -ne 1 ]; then
34 fail "traceoff trigger on sched_process_fork did not work"
35fi
36
37reset_trigger
38
39echo "Test semantic error for trigger filter"
40! echo 'traceoff if a' > events/sched/sched_process_fork/trigger
41! echo 'traceoff if common_pid=0' > events/sched/sched_process_fork/trigger
42! echo 'traceoff if common_pid==b' > events/sched/sched_process_fork/trigger
43echo 'traceoff if common_pid == 0' > events/sched/sched_process_fork/trigger
44echo '!traceoff' > events/sched/sched_process_fork/trigger
45! echo 'traceoff if common_pid == child_pid' > events/sched/sched_process_fork/trigger
46echo 'traceoff if common_pid <= 0' > events/sched/sched_process_fork/trigger
47echo '!traceoff' > events/sched/sched_process_fork/trigger
48echo 'traceoff if common_pid >= 0' > events/sched/sched_process_fork/trigger
49echo '!traceoff' > events/sched/sched_process_fork/trigger
50echo 'traceoff if parent_pid >= 0 && child_pid >= 0' > events/sched/sched_process_fork/trigger
51echo '!traceoff' > events/sched/sched_process_fork/trigger
52echo 'traceoff if parent_pid >= 0 || child_pid >= 0' > events/sched/sched_process_fork/trigger
53echo '!traceoff' > events/sched/sched_process_fork/trigger
54
55
56
57do_reset
58
59exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
new file mode 100644
index 000000000000..c2b61c4fda11
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
@@ -0,0 +1,75 @@
1#!/bin/sh
2# description: event trigger - test histogram modifiers
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test histogram with execname modifier"
36
37echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger
38for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
39COMM=`cat /proc/$$/comm`
40grep "common_pid: $COMM" events/sched/sched_process_fork/hist > /dev/null || \
41 fail "execname modifier on sched_process_fork did not work"
42
43reset_trigger
44
45echo "Test histogram with hex modifier"
46
47echo 'hist:keys=parent_pid.hex' > events/sched/sched_process_fork/trigger
48for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
49# Note that $$ is the parent pid. $PID is current PID.
50HEX=`printf %x $PID`
51grep "parent_pid: $HEX" events/sched/sched_process_fork/hist > /dev/null || \
52 fail "hex modifier on sched_process_fork did not work"
53
54reset_trigger
55
56echo "Test histogram with syscall modifier"
57
58echo 'hist:keys=id.syscall' > events/raw_syscalls/sys_exit/trigger
59for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
60grep "id: sys_" events/raw_syscalls/sys_exit/hist > /dev/null || \
61 fail "syscall modifier on raw_syscalls/sys_exit did not work"
62
63
64reset_trigger
65
66echo "Test histgram with log2 modifier"
67
68echo 'hist:keys=bytes_req.log2' > events/kmem/kmalloc/trigger
69for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
70grep 'bytes_req: ~ 2^[0-9]*' events/kmem/kmalloc/hist > /dev/null || \
71 fail "log2 modifier on kmem/kmalloc did not work"
72
73do_reset
74
75exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
new file mode 100644
index 000000000000..b2902d42a537
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
@@ -0,0 +1,83 @@
1#!/bin/sh
2# description: event trigger - test histogram trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test histogram basic tigger"
36
37echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
38for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
39grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \
40 fail "hist trigger on sched_process_fork did not work"
41grep child events/sched/sched_process_fork/hist > /dev/null || \
42 fail "hist trigger on sched_process_fork did not work"
43
44reset_trigger
45
46echo "Test histogram with compound keys"
47
48echo 'hist:keys=parent_pid,child_pid' > events/sched/sched_process_fork/trigger
49for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
50grep '^{ parent_pid:.*, child_pid:.*}' events/sched/sched_process_fork/hist > /dev/null || \
51 fail "compound keys on sched_process_fork did not work"
52
53reset_trigger
54
55echo "Test histogram with string key"
56
57echo 'hist:keys=parent_comm' > events/sched/sched_process_fork/trigger
58for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
59COMM=`cat /proc/$$/comm`
60grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \
61 fail "string key on sched_process_fork did not work"
62
63reset_trigger
64
65echo "Test histogram with sort key"
66
67echo 'hist:keys=parent_pid,child_pid:sort=child_pid.ascending' > events/sched/sched_process_fork/trigger
68for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
69
70check_inc() {
71 while [ $# -gt 1 ]; do
72 [ $1 -gt $2 ] && return 1
73 shift 1
74 done
75 return 0
76}
77check_inc `grep -o "child_pid:[[:space:]]*[[:digit:]]*" \
78 events/sched/sched_process_fork/hist | cut -d: -f2 ` ||
79 fail "sort param on sched_process_fork did not work"
80
81do_reset
82
83exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
new file mode 100644
index 000000000000..03c4a46561fc
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
@@ -0,0 +1,73 @@
1#!/bin/sh
2# description: event trigger - test multiple histogram triggers
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported"
32 exit_unsupported
33fi
34
35reset_trigger
36
37echo "Test histogram multiple tiggers"
38
39echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
40echo 'hist:keys=parent_comm:vals=child_pid' >> events/sched/sched_process_fork/trigger
41for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
42grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \
43 fail "hist trigger on sched_process_fork did not work"
44grep child events/sched/sched_process_fork/hist > /dev/null || \
45 fail "hist trigger on sched_process_fork did not work"
46COMM=`cat /proc/$$/comm`
47grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \
48 fail "string key on sched_process_fork did not work"
49
50reset_trigger
51
52echo "Test histogram with its name"
53
54echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_fork/trigger
55for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
56grep test_hist events/sched/sched_process_fork/hist > /dev/null || \
57 fail "named event on sched_process_fork did not work"
58
59echo "Test same named histogram on different events"
60
61echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_exit/trigger
62for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done
63grep test_hist events/sched/sched_process_exit/hist > /dev/null || \
64 fail "named event on sched_process_fork did not work"
65
66diffs=`diff events/sched/sched_process_exit/hist events/sched/sched_process_fork/hist | wc -l`
67test $diffs -eq 0 || fail "Same name histograms are not same"
68
69reset_trigger
70
71do_reset
72
73exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
new file mode 100644
index 000000000000..f84b80d551a2
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
@@ -0,0 +1,56 @@
1#!/bin/sh
2# description: event trigger - test snapshot-trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep snapshot events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "snapshot trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test snapshot tigger"
36echo 0 > snapshot
37echo 1 > events/sched/sched_process_fork/enable
38( echo "forked")
39echo 'snapshot:1' > events/sched/sched_process_fork/trigger
40( echo "forked")
41grep sched_process_fork snapshot > /dev/null || \
42 fail "snapshot trigger on sched_process_fork did not work"
43
44reset_trigger
45echo 0 > snapshot
46echo 0 > events/sched/sched_process_fork/enable
47
48echo "Test snapshot semantic errors"
49
50! echo "snapshot+1" > events/sched/sched_process_fork/trigger
51echo "snapshot" > events/sched/sched_process_fork/trigger
52! echo "snapshot" > events/sched/sched_process_fork/trigger
53
54do_reset
55
56exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
new file mode 100644
index 000000000000..9fa23b085def
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
@@ -0,0 +1,53 @@
1#!/bin/sh
2# description: event trigger - test stacktrace-trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29FEATURE=`grep stacktrace events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "stacktrace trigger is not supported"
32 exit_unsupported
33fi
34
35echo "Test stacktrace tigger"
36echo 0 > trace
37echo 0 > options/stacktrace
38echo 'stacktrace' > events/sched/sched_process_fork/trigger
39( echo "forked")
40grep "<stack trace>" trace > /dev/null || \
41 fail "stacktrace trigger on sched_process_fork did not work"
42
43reset_trigger
44
45echo "Test stacktrace semantic errors"
46
47! echo "stacktrace:foo" > events/sched/sched_process_fork/trigger
48echo "stacktrace" > events/sched/sched_process_fork/trigger
49! echo "stacktrace" > events/sched/sched_process_fork/trigger
50
51do_reset
52
53exit 0
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
new file mode 100644
index 000000000000..87648e5f987c
--- /dev/null
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
@@ -0,0 +1,58 @@
1#!/bin/sh
2# description: event trigger - test traceon/off trigger
3
4do_reset() {
5 reset_trigger
6 echo > set_event
7 clear_trace
8}
9
10fail() { #msg
11 do_reset
12 echo $1
13 exit $FAIL
14}
15
16if [ ! -f set_event -o ! -d events/sched ]; then
17 echo "event tracing is not supported"
18 exit_unsupported
19fi
20
21if [ ! -f events/sched/sched_process_fork/trigger ]; then
22 echo "event trigger is not supported"
23 exit_unsupported
24fi
25
26reset_tracer
27do_reset
28
29echo "Test traceoff trigger"
30echo 1 > tracing_on
31echo 'traceoff' > events/sched/sched_process_fork/trigger
32( echo "forked")
33if [ `cat tracing_on` -ne 0 ]; then
34 fail "traceoff trigger on sched_process_fork did not work"
35fi
36
37reset_trigger
38
39echo "Test traceon trigger"
40echo 0 > tracing_on
41echo 'traceon' > events/sched/sched_process_fork/trigger
42( echo "forked")
43if [ `cat tracing_on` -ne 1 ]; then
44 fail "traceoff trigger on sched_process_fork did not work"
45fi
46
47reset_trigger
48
49echo "Test semantic error for traceoff/on trigger"
50! echo 'traceoff:badparam' > events/sched/sched_process_fork/trigger
51! echo 'traceoff+0' > events/sched/sched_process_fork/trigger
52echo 'traceon' > events/sched/sched_process_fork/trigger
53! echo 'traceon' > events/sched/sched_process_fork/trigger
54! echo 'traceoff' > events/sched/sched_process_fork/trigger
55
56do_reset
57
58exit 0
diff --git a/tools/testing/selftests/intel_pstate/run.sh b/tools/testing/selftests/intel_pstate/run.sh
index bdaf37e92684..7868c106b8b1 100755
--- a/tools/testing/selftests/intel_pstate/run.sh
+++ b/tools/testing/selftests/intel_pstate/run.sh
@@ -32,7 +32,7 @@ EVALUATE_ONLY=0
32max_cpus=$(($(nproc)-1)) 32max_cpus=$(($(nproc)-1))
33 33
34# compile programs 34# compile programs
35gcc -o aperf aperf.c -lm 35gcc aperf.c -Wall -D_GNU_SOURCE -o aperf -lm
36[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1 36[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1
37gcc -o msr msr.c -lm 37gcc -o msr msr.c -lm
38[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1 38[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index b08f77cbe31b..4ca83fe80654 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -14,6 +14,7 @@ export CFLAGS
14 14
15SUB_DIRS = benchmarks \ 15SUB_DIRS = benchmarks \
16 copyloops \ 16 copyloops \
17 context_switch \
17 dscr \ 18 dscr \
18 mm \ 19 mm \
19 pmu \ 20 pmu \
diff --git a/tools/testing/selftests/powerpc/context_switch/.gitignore b/tools/testing/selftests/powerpc/context_switch/.gitignore
new file mode 100644
index 000000000000..c1431af7b51c
--- /dev/null
+++ b/tools/testing/selftests/powerpc/context_switch/.gitignore
@@ -0,0 +1 @@
cp_abort
diff --git a/tools/testing/selftests/powerpc/context_switch/Makefile b/tools/testing/selftests/powerpc/context_switch/Makefile
new file mode 100644
index 000000000000..e164d1466466
--- /dev/null
+++ b/tools/testing/selftests/powerpc/context_switch/Makefile
@@ -0,0 +1,10 @@
1TEST_PROGS := cp_abort
2
3all: $(TEST_PROGS)
4
5$(TEST_PROGS): ../harness.c ../utils.c
6
7include ../../lib.mk
8
9clean:
10 rm -f $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/context_switch/cp_abort.c b/tools/testing/selftests/powerpc/context_switch/cp_abort.c
new file mode 100644
index 000000000000..5a5b55afda0e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/context_switch/cp_abort.c
@@ -0,0 +1,110 @@
1/*
2 * Adapted from Anton Blanchard's context switch microbenchmark.
3 *
4 * Copyright 2009, Anton Blanchard, IBM Corporation.
5 * Copyright 2016, Mikey Neuling, Chris Smart, IBM Corporation.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 * This program tests the copy paste abort functionality of a P9
13 * (or later) by setting up two processes on the same CPU, one
14 * which executes the copy instruction and the other which
15 * executes paste.
16 *
17 * The paste instruction should never succeed, as the cp_abort
18 * instruction is called by the kernel during a context switch.
19 *
20 */
21
22#define _GNU_SOURCE
23
24#include <stdio.h>
25#include <unistd.h>
26#include <stdlib.h>
27#include "utils.h"
28#include <sched.h>
29
30#define READ_FD 0
31#define WRITE_FD 1
32
33#define NUM_LOOPS 1000
34
35/* This defines the "paste" instruction from Power ISA 3.0 Book II, section 4.4. */
36#define PASTE(RA, RB, L, RC) \
37 .long (0x7c00070c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10) | (RC) << (31-31))
38
39int paste(void *i)
40{
41 int cr;
42
43 asm volatile(str(PASTE(0, %1, 1, 1))";"
44 "mfcr %0;"
45 : "=r" (cr)
46 : "b" (i)
47 : "memory"
48 );
49 return cr;
50}
51
52/* This defines the "copy" instruction from Power ISA 3.0 Book II, section 4.4. */
53#define COPY(RA, RB, L) \
54 .long (0x7c00060c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10))
55
56void copy(void *i)
57{
58 asm volatile(str(COPY(0, %0, 1))";"
59 :
60 : "b" (i)
61 : "memory"
62 );
63}
64
65int test_cp_abort(void)
66{
67 /* 128 bytes for a full cache line */
68 char buf[128] __cacheline_aligned;
69 cpu_set_t cpuset;
70 int fd1[2], fd2[2], pid;
71 char c;
72
73 /* only run this test on a P9 or later */
74 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
75
76 /*
77 * Run both processes on the same CPU, so that copy is more likely
78 * to leak into a paste.
79 */
80 CPU_ZERO(&cpuset);
81 CPU_SET(pick_online_cpu(), &cpuset);
82 FAIL_IF(sched_setaffinity(0, sizeof(cpuset), &cpuset));
83
84 FAIL_IF(pipe(fd1) || pipe(fd2));
85
86 pid = fork();
87 FAIL_IF(pid < 0);
88
89 if (!pid) {
90 for (int i = 0; i < NUM_LOOPS; i++) {
91 FAIL_IF((write(fd1[WRITE_FD], &c, 1)) != 1);
92 FAIL_IF((read(fd2[READ_FD], &c, 1)) != 1);
93 /* A paste succeeds if CR0 EQ bit is set */
94 FAIL_IF(paste(buf) & 0x20000000);
95 }
96 } else {
97 for (int i = 0; i < NUM_LOOPS; i++) {
98 FAIL_IF((read(fd1[READ_FD], &c, 1)) != 1);
99 copy(buf);
100 FAIL_IF((write(fd2[WRITE_FD], &c, 1) != 1));
101 }
102 }
103 return 0;
104
105}
106
107int main(int argc, char *argv[])
108{
109 return test_harness(test_cp_abort, "cp_abort");
110}
diff --git a/tools/testing/selftests/powerpc/mm/subpage_prot.c b/tools/testing/selftests/powerpc/mm/subpage_prot.c
index 440180ff8089..35ade7406dcd 100644
--- a/tools/testing/selftests/powerpc/mm/subpage_prot.c
+++ b/tools/testing/selftests/powerpc/mm/subpage_prot.c
@@ -73,7 +73,7 @@ static inline void check_faulted(void *addr, long page, long subpage, int write)
73 want_fault |= (subpage == ((page + 1) % 16)); 73 want_fault |= (subpage == ((page + 1) % 16));
74 74
75 if (faulted != want_fault) { 75 if (faulted != want_fault) {
76 printf("Failed at 0x%p (p=%ld,sp=%ld,w=%d), want=%s, got=%s !\n", 76 printf("Failed at %p (p=%ld,sp=%ld,w=%d), want=%s, got=%s !\n",
77 addr, page, subpage, write, 77 addr, page, subpage, write,
78 want_fault ? "fault" : "pass", 78 want_fault ? "fault" : "pass",
79 faulted ? "fault" : "pass"); 79 faulted ? "fault" : "pass");
@@ -82,7 +82,7 @@ static inline void check_faulted(void *addr, long page, long subpage, int write)
82 82
83 if (faulted) { 83 if (faulted) {
84 if (dar != addr) { 84 if (dar != addr) {
85 printf("Fault expected at 0x%p and happened at 0x%p !\n", 85 printf("Fault expected at %p and happened at %p !\n",
86 addr, dar); 86 addr, dar);
87 } 87 }
88 faulted = 0; 88 faulted = 0;
@@ -162,7 +162,7 @@ int test_anon(void)
162 162
163 mallocblock = (void *)align; 163 mallocblock = (void *)align;
164 164
165 printf("allocated malloc block of 0x%lx bytes at 0x%p\n", 165 printf("allocated malloc block of 0x%lx bytes at %p\n",
166 mallocsize, mallocblock); 166 mallocsize, mallocblock);
167 167
168 printf("testing malloc block...\n"); 168 printf("testing malloc block...\n");
@@ -197,7 +197,7 @@ int test_file(void)
197 perror("failed to map file"); 197 perror("failed to map file");
198 return 1; 198 return 1;
199 } 199 }
200 printf("allocated %s for 0x%lx bytes at 0x%p\n", 200 printf("allocated %s for 0x%lx bytes at %p\n",
201 file_name, filesize, fileblock); 201 file_name, filesize, fileblock);
202 202
203 printf("testing file map...\n"); 203 printf("testing file map...\n");
@@ -207,14 +207,16 @@ int test_file(void)
207 207
208int main(int argc, char *argv[]) 208int main(int argc, char *argv[])
209{ 209{
210 test_harness(test_anon, "subpage_prot_anon"); 210 int rc;
211
212 rc = test_harness(test_anon, "subpage_prot_anon");
213 if (rc)
214 return rc;
211 215
212 if (argc > 1) 216 if (argc > 1)
213 file_name = argv[1]; 217 file_name = argv[1];
214 else 218 else
215 file_name = "tempfile"; 219 file_name = "tempfile";
216 220
217 test_harness(test_file, "subpage_prot_file"); 221 return test_harness(test_file, "subpage_prot_file");
218
219 return 0;
220} 222}
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
index e67452f1bcff..46681fec549b 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
@@ -15,7 +15,6 @@
15#include <sys/ioctl.h> 15#include <sys/ioctl.h>
16 16
17#include "trace.h" 17#include "trace.h"
18#include "reg.h"
19#include "ebb.h" 18#include "ebb.h"
20 19
21 20
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c b/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
index 5b1188f10c15..f923228bca22 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/reg_access_test.c
@@ -7,7 +7,6 @@
7#include <stdlib.h> 7#include <stdlib.h>
8 8
9#include "ebb.h" 9#include "ebb.h"
10#include "reg.h"
11 10
12 11
13/* 12/*
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/reg.h b/tools/testing/selftests/powerpc/reg.h
index 5921b0dfe2e9..65bfdeeebdee 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/reg.h
+++ b/tools/testing/selftests/powerpc/reg.h
@@ -9,12 +9,12 @@
9#define __stringify_1(x) #x 9#define __stringify_1(x) #x
10#define __stringify(x) __stringify_1(x) 10#define __stringify(x) __stringify_1(x)
11 11
12#define mfspr(rn) ({unsigned long rval; \ 12#define mfspr(rn) ({unsigned long rval; \
13 asm volatile("mfspr %0," __stringify(rn) \ 13 asm volatile("mfspr %0," _str(rn) \
14 : "=r" (rval)); rval; }) 14 : "=r" (rval)); rval; })
15#define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : \ 15#define mtspr(rn, v) asm volatile("mtspr " _str(rn) ",%0" : \
16 : "r" ((unsigned long)(v)) \ 16 : "r" ((unsigned long)(v)) \
17 : "memory") 17 : "memory")
18 18
19#define mb() asm volatile("sync" : : : "memory"); 19#define mb() asm volatile("sync" : : : "memory");
20 20
@@ -46,4 +46,10 @@
46#define SPRN_SDAR 781 46#define SPRN_SDAR 781
47#define SPRN_SIER 768 47#define SPRN_SIER 768
48 48
49#define SPRN_TEXASR 0x82
50#define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */
51#define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */
52#define TEXASR_FS 0x08000000
53#define SPRN_TAR 0x32f
54
49#endif /* _SELFTESTS_POWERPC_REG_H */ 55#endif /* _SELFTESTS_POWERPC_REG_H */
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index 7d0f14b8cb2e..bb942db845bf 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -3,3 +3,6 @@ tm-syscall
3tm-signal-msr-resv 3tm-signal-msr-resv
4tm-signal-stack 4tm-signal-stack
5tm-vmxcopy 5tm-vmxcopy
6tm-fork
7tm-tar
8tm-tmspr
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 737f72c964e6..d0505dbd22d5 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,4 +1,4 @@
1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy 1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy tm-fork tm-tar tm-tmspr
2 2
3all: $(TEST_PROGS) 3all: $(TEST_PROGS)
4 4
@@ -6,6 +6,7 @@ $(TEST_PROGS): ../harness.c ../utils.c
6 6
7tm-syscall: tm-syscall-asm.S 7tm-syscall: tm-syscall-asm.S
8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include 8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include
9tm-tmspr: CFLAGS += -pthread
9 10
10include ../../lib.mk 11include ../../lib.mk
11 12
diff --git a/tools/testing/selftests/powerpc/tm/tm-fork.c b/tools/testing/selftests/powerpc/tm/tm-fork.c
new file mode 100644
index 000000000000..8d48579b7778
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-fork.c
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Edited: Rashmica Gupta, Nov 2015
6 *
7 * This test does a fork syscall inside a transaction. Basic sniff test
8 * to see if we can enter the kernel during a transaction.
9 */
10
11#include <errno.h>
12#include <inttypes.h>
13#include <pthread.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17
18#include "utils.h"
19#include "tm.h"
20
21int test_fork(void)
22{
23 SKIP_IF(!have_htm());
24
25 asm __volatile__(
26 "tbegin.;"
27 "blt 1f; "
28 "li 0, 2;" /* fork syscall */
29 "sc ;"
30 "tend.;"
31 "1: ;"
32 : : : "memory", "r0");
33 /* If we reach here, we've passed. Otherwise we've probably crashed
34 * the kernel */
35
36 return 0;
37}
38
39int main(int argc, char *argv[])
40{
41 return test_harness(test_fork, "tm_fork");
42}
diff --git a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
index 8fde93d6021f..d9c49f41515e 100644
--- a/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
+++ b/tools/testing/selftests/powerpc/tm/tm-resched-dscr.c
@@ -31,12 +31,6 @@
31#include "utils.h" 31#include "utils.h"
32#include "tm.h" 32#include "tm.h"
33 33
34#define TBEGIN ".long 0x7C00051D ;"
35#define TEND ".long 0x7C00055D ;"
36#define TCHECK ".long 0x7C00059C ;"
37#define TSUSPEND ".long 0x7C0005DD ;"
38#define TRESUME ".long 0x7C2005DD ;"
39#define SPRN_TEXASR 0x82
40#define SPRN_DSCR 0x03 34#define SPRN_DSCR 0x03
41 35
42int test_body(void) 36int test_body(void)
@@ -55,13 +49,13 @@ int test_body(void)
55 "mtspr %[sprn_dscr], 3;" 49 "mtspr %[sprn_dscr], 3;"
56 50
57 /* start and suspend a transaction */ 51 /* start and suspend a transaction */
58 TBEGIN 52 "tbegin.;"
59 "beq 1f;" 53 "beq 1f;"
60 TSUSPEND 54 "tsuspend.;"
61 55
62 /* hard loop until the transaction becomes doomed */ 56 /* hard loop until the transaction becomes doomed */
63 "2: ;" 57 "2: ;"
64 TCHECK 58 "tcheck 0;"
65 "bc 4, 0, 2b;" 59 "bc 4, 0, 2b;"
66 60
67 /* record DSCR and TEXASR */ 61 /* record DSCR and TEXASR */
@@ -70,8 +64,8 @@ int test_body(void)
70 "mfspr 3, %[sprn_texasr];" 64 "mfspr 3, %[sprn_texasr];"
71 "std 3, %[texasr];" 65 "std 3, %[texasr];"
72 66
73 TRESUME 67 "tresume.;"
74 TEND 68 "tend.;"
75 "li %[rv], 0;" 69 "li %[rv], 0;"
76 "1: ;" 70 "1: ;"
77 : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr) 71 : [rv]"=r"(rv), [dscr2]"=m"(dscr2), [texasr]"=m"(texasr)
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
index e44a238c1d77..1f0eb567438d 100644
--- a/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-stack.c
@@ -60,9 +60,9 @@ int tm_signal_stack()
60 exit(1); 60 exit(1);
61 asm volatile("li 1, 0 ;" /* stack ptr == NULL */ 61 asm volatile("li 1, 0 ;" /* stack ptr == NULL */
62 "1:" 62 "1:"
63 ".long 0x7C00051D ;" /* tbegin */ 63 "tbegin.;"
64 "beq 1b ;" /* retry forever */ 64 "beq 1b ;" /* retry forever */
65 ".long 0x7C0005DD ; ;" /* tsuspend */ 65 "tsuspend.;"
66 "ld 2, 0(1) ;" /* trigger segv" */ 66 "ld 2, 0(1) ;" /* trigger segv" */
67 : : : "memory"); 67 : : : "memory");
68 68
diff --git a/tools/testing/selftests/powerpc/tm/tm-tar.c b/tools/testing/selftests/powerpc/tm/tm-tar.c
new file mode 100644
index 000000000000..2d2fcc2b7a60
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-tar.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 * Original: Michael Neuling 19/7/2013
5 * Edited: Rashmica Gupta 01/12/2015
6 *
7 * Do some transactions, see if the tar is corrupted.
8 * If the transaction is aborted, the TAR should be rolled back to the
9 * checkpointed value before the transaction began. The value written to
10 * TAR in suspended mode should only remain in TAR if the transaction
11 * completes.
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include <string.h>
18
19#include "tm.h"
20#include "utils.h"
21
22int num_loops = 10000;
23
24int test_tar(void)
25{
26 int i;
27
28 SKIP_IF(!have_htm());
29
30 for (i = 0; i < num_loops; i++)
31 {
32 uint64_t result = 0;
33 asm __volatile__(
34 "li 7, 1;"
35 "mtspr %[tar], 7;" /* tar = 1 */
36 "tbegin.;"
37 "beq 3f;"
38 "li 4, 0x7000;" /* Loop lots, to use time */
39 "2:;" /* Start loop */
40 "li 7, 2;"
41 "mtspr %[tar], 7;" /* tar = 2 */
42 "tsuspend.;"
43 "li 7, 3;"
44 "mtspr %[tar], 7;" /* tar = 3 */
45 "tresume.;"
46 "subi 4, 4, 1;"
47 "cmpdi 4, 0;"
48 "bne 2b;"
49 "tend.;"
50
51 /* Transaction sucess! TAR should be 3 */
52 "mfspr 7, %[tar];"
53 "ori %[res], 7, 4;" // res = 3|4 = 7
54 "b 4f;"
55
56 /* Abort handler. TAR should be rolled back to 1 */
57 "3:;"
58 "mfspr 7, %[tar];"
59 "ori %[res], 7, 8;" // res = 1|8 = 9
60 "4:;"
61
62 : [res]"=r"(result)
63 : [tar]"i"(SPRN_TAR)
64 : "memory", "r0", "r4", "r7");
65
66 /* If result is anything else other than 7 or 9, the tar
67 * value must have been corrupted. */
68 if ((result != 7) && (result != 9))
69 return 1;
70 }
71 return 0;
72}
73
74int main(int argc, char *argv[])
75{
76 /* A low number of iterations (eg 100) can cause a false pass */
77 if (argc > 1) {
78 if (strcmp(argv[1], "-h") == 0) {
79 printf("Syntax:\n\t%s [<num loops>]\n",
80 argv[0]);
81 return 1;
82 } else {
83 num_loops = atoi(argv[1]);
84 }
85 }
86
87 printf("Starting, %d loops\n", num_loops);
88
89 return test_harness(test_tar, "tm_tar");
90}
diff --git a/tools/testing/selftests/powerpc/tm/tm-tmspr.c b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
new file mode 100644
index 000000000000..2bda81c7bf23
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-tmspr.c
@@ -0,0 +1,143 @@
1/*
2 * Copyright 2015, Michael Neuling, IBM Corp.
3 * Licensed under GPLv2.
4 *
5 * Original: Michael Neuling 3/4/2014
6 * Modified: Rashmica Gupta 8/12/2015
7 *
8 * Check if any of the Transaction Memory SPRs get corrupted.
9 * - TFIAR - stores address of location of transaction failure
10 * - TFHAR - stores address of software failure handler (if transaction
11 * fails)
12 * - TEXASR - lots of info about the transacion(s)
13 *
14 * (1) create more threads than cpus
15 * (2) in each thread:
16 * (a) set TFIAR and TFHAR a unique value
17 * (b) loop for awhile, continually checking to see if
18 * either register has been corrupted.
19 *
20 * (3) Loop:
21 * (a) begin transaction
22 * (b) abort transaction
23 * (c) check TEXASR to see if FS has been corrupted
24 *
25 */
26
27#define _GNU_SOURCE
28#include <stdio.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <pthread.h>
32#include <string.h>
33
34#include "utils.h"
35#include "tm.h"
36
37int num_loops = 10000;
38int passed = 1;
39
40void tfiar_tfhar(void *in)
41{
42 int i, cpu;
43 unsigned long tfhar, tfhar_rd, tfiar, tfiar_rd;
44 cpu_set_t cpuset;
45
46 CPU_ZERO(&cpuset);
47 cpu = (unsigned long)in >> 1;
48 CPU_SET(cpu, &cpuset);
49 sched_setaffinity(0, sizeof(cpuset), &cpuset);
50
51 /* TFIAR: Last bit has to be high so userspace can read register */
52 tfiar = ((unsigned long)in) + 1;
53 tfiar += 2;
54 mtspr(SPRN_TFIAR, tfiar);
55
56 /* TFHAR: Last two bits are reserved */
57 tfhar = ((unsigned long)in);
58 tfhar &= ~0x3UL;
59 tfhar += 4;
60 mtspr(SPRN_TFHAR, tfhar);
61
62 for (i = 0; i < num_loops; i++) {
63 tfhar_rd = mfspr(SPRN_TFHAR);
64 tfiar_rd = mfspr(SPRN_TFIAR);
65 if ( (tfhar != tfhar_rd) || (tfiar != tfiar_rd) ) {
66 passed = 0;
67 return;
68 }
69 }
70 return;
71}
72
73void texasr(void *in)
74{
75 unsigned long i;
76 uint64_t result = 0;
77
78 for (i = 0; i < num_loops; i++) {
79 asm __volatile__(
80 "tbegin.;"
81 "beq 3f ;"
82 "tabort. 0 ;"
83 "tend.;"
84
85 /* Abort handler */
86 "3: ;"
87 ::: "memory");
88
89 /* Check the TEXASR */
90 result = mfspr(SPRN_TEXASR);
91 if ((result & TEXASR_FS) == 0) {
92 passed = 0;
93 return;
94 }
95 }
96 return;
97}
98
99int test_tmspr()
100{
101 pthread_t thread;
102 int thread_num;
103 unsigned long i;
104
105 SKIP_IF(!have_htm());
106
107 /* To cause some context switching */
108 thread_num = 10 * sysconf(_SC_NPROCESSORS_ONLN);
109
110 /* Test TFIAR and TFHAR */
111 for (i = 0 ; i < thread_num ; i += 2){
112 if (pthread_create(&thread, NULL, (void*)tfiar_tfhar, (void *)i))
113 return EXIT_FAILURE;
114 }
115 if (pthread_join(thread, NULL) != 0)
116 return EXIT_FAILURE;
117
118 /* Test TEXASR */
119 for (i = 0 ; i < thread_num ; i++){
120 if (pthread_create(&thread, NULL, (void*)texasr, (void *)i))
121 return EXIT_FAILURE;
122 }
123 if (pthread_join(thread, NULL) != 0)
124 return EXIT_FAILURE;
125
126 if (passed)
127 return 0;
128 else
129 return 1;
130}
131
132int main(int argc, char *argv[])
133{
134 if (argc > 1) {
135 if (strcmp(argv[1], "-h") == 0) {
136 printf("Syntax:\t [<num loops>]\n");
137 return 0;
138 } else {
139 num_loops = atoi(argv[1]);
140 }
141 }
142 return test_harness(test_tmspr, "tm_tmspr");
143}
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
index 175ac6ad10dd..a985cfaa535e 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -6,9 +6,12 @@
6#ifndef _SELFTESTS_POWERPC_UTILS_H 6#ifndef _SELFTESTS_POWERPC_UTILS_H
7#define _SELFTESTS_POWERPC_UTILS_H 7#define _SELFTESTS_POWERPC_UTILS_H
8 8
9#define __cacheline_aligned __attribute__((aligned(128)))
10
9#include <stdint.h> 11#include <stdint.h>
10#include <stdbool.h> 12#include <stdbool.h>
11#include <linux/auxvec.h> 13#include <linux/auxvec.h>
14#include "reg.h"
12 15
13/* Avoid headaches with PRI?64 - just use %ll? always */ 16/* Avoid headaches with PRI?64 - just use %ll? always */
14typedef unsigned long long u64; 17typedef unsigned long long u64;
@@ -54,4 +57,9 @@ do { \
54#define _str(s) #s 57#define _str(s) #s
55#define str(s) _str(s) 58#define str(s) _str(s)
56 59
60/* POWER9 feature */
61#ifndef PPC_FEATURE2_ARCH_3_00
62#define PPC_FEATURE2_ARCH_3_00 0x00800000
63#endif
64
57#endif /* _SELFTESTS_POWERPC_UTILS_H */ 65#endif /* _SELFTESTS_POWERPC_UTILS_H */
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/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 150829dd7998..2e58549b2f02 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -5,6 +5,7 @@
5 * Test code for seccomp bpf. 5 * Test code for seccomp bpf.
6 */ 6 */
7 7
8#include <sys/types.h>
8#include <asm/siginfo.h> 9#include <asm/siginfo.h>
9#define __have_siginfo_t 1 10#define __have_siginfo_t 1
10#define __have_sigval_t 1 11#define __have_sigval_t 1
@@ -14,7 +15,6 @@
14#include <linux/filter.h> 15#include <linux/filter.h>
15#include <sys/prctl.h> 16#include <sys/prctl.h>
16#include <sys/ptrace.h> 17#include <sys/ptrace.h>
17#include <sys/types.h>
18#include <sys/user.h> 18#include <sys/user.h>
19#include <linux/prctl.h> 19#include <linux/prctl.h>
20#include <linux/ptrace.h> 20#include <linux/ptrace.h>
@@ -1234,6 +1234,10 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1234# define ARCH_REGS struct user_pt_regs 1234# define ARCH_REGS struct user_pt_regs
1235# define SYSCALL_NUM regs[8] 1235# define SYSCALL_NUM regs[8]
1236# define SYSCALL_RET regs[0] 1236# define SYSCALL_RET regs[0]
1237#elif defined(__hppa__)
1238# define ARCH_REGS struct user_regs_struct
1239# define SYSCALL_NUM gr[20]
1240# define SYSCALL_RET gr[28]
1237#elif defined(__powerpc__) 1241#elif defined(__powerpc__)
1238# define ARCH_REGS struct pt_regs 1242# define ARCH_REGS struct pt_regs
1239# define SYSCALL_NUM gpr[0] 1243# define SYSCALL_NUM gpr[0]
@@ -1242,6 +1246,12 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1242# define ARCH_REGS s390_regs 1246# define ARCH_REGS s390_regs
1243# define SYSCALL_NUM gprs[2] 1247# define SYSCALL_NUM gprs[2]
1244# define SYSCALL_RET gprs[2] 1248# define SYSCALL_RET gprs[2]
1249#elif defined(__mips__)
1250# define ARCH_REGS struct pt_regs
1251# define SYSCALL_NUM regs[2]
1252# define SYSCALL_SYSCALL_NUM regs[4]
1253# define SYSCALL_RET regs[2]
1254# define SYSCALL_NUM_RET_SHARE_REG
1245#else 1255#else
1246# error "Do not know how to find your architecture's registers and syscalls" 1256# error "Do not know how to find your architecture's registers and syscalls"
1247#endif 1257#endif
@@ -1249,7 +1259,7 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1249/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for 1259/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
1250 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux). 1260 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
1251 */ 1261 */
1252#if defined(__x86_64__) || defined(__i386__) 1262#if defined(__x86_64__) || defined(__i386__) || defined(__mips__)
1253#define HAVE_GETREGS 1263#define HAVE_GETREGS
1254#endif 1264#endif
1255 1265
@@ -1273,6 +1283,10 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
1273 } 1283 }
1274#endif 1284#endif
1275 1285
1286#if defined(__mips__)
1287 if (regs.SYSCALL_NUM == __NR_O32_Linux)
1288 return regs.SYSCALL_SYSCALL_NUM;
1289#endif
1276 return regs.SYSCALL_NUM; 1290 return regs.SYSCALL_NUM;
1277} 1291}
1278 1292
@@ -1293,10 +1307,17 @@ void change_syscall(struct __test_metadata *_metadata,
1293 EXPECT_EQ(0, ret); 1307 EXPECT_EQ(0, ret);
1294 1308
1295#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ 1309#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \
1296 defined(__s390__) 1310 defined(__s390__) || defined(__hppa__)
1297 { 1311 {
1298 regs.SYSCALL_NUM = syscall; 1312 regs.SYSCALL_NUM = syscall;
1299 } 1313 }
1314#elif defined(__mips__)
1315 {
1316 if (regs.SYSCALL_NUM == __NR_O32_Linux)
1317 regs.SYSCALL_SYSCALL_NUM = syscall;
1318 else
1319 regs.SYSCALL_NUM = syscall;
1320 }
1300 1321
1301#elif defined(__arm__) 1322#elif defined(__arm__)
1302# ifndef PTRACE_SET_SYSCALL 1323# ifndef PTRACE_SET_SYSCALL
@@ -1327,7 +1348,11 @@ void change_syscall(struct __test_metadata *_metadata,
1327 1348
1328 /* If syscall is skipped, change return value. */ 1349 /* If syscall is skipped, change return value. */
1329 if (syscall == -1) 1350 if (syscall == -1)
1351#ifdef SYSCALL_NUM_RET_SHARE_REG
1352 TH_LOG("Can't modify syscall return on this architecture");
1353#else
1330 regs.SYSCALL_RET = 1; 1354 regs.SYSCALL_RET = 1;
1355#endif
1331 1356
1332#ifdef HAVE_GETREGS 1357#ifdef HAVE_GETREGS
1333 ret = ptrace(PTRACE_SETREGS, tracee, 0, &regs); 1358 ret = ptrace(PTRACE_SETREGS, tracee, 0, &regs);
@@ -1465,8 +1490,13 @@ TEST_F(TRACE_syscall, syscall_dropped)
1465 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0); 1490 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1466 ASSERT_EQ(0, ret); 1491 ASSERT_EQ(0, ret);
1467 1492
1493#ifdef SYSCALL_NUM_RET_SHARE_REG
1494 /* gettid has been skipped */
1495 EXPECT_EQ(-1, syscall(__NR_gettid));
1496#else
1468 /* gettid has been skipped and an altered return value stored. */ 1497 /* gettid has been skipped and an altered return value stored. */
1469 EXPECT_EQ(1, syscall(__NR_gettid)); 1498 EXPECT_EQ(1, syscall(__NR_gettid));
1499#endif
1470 EXPECT_NE(self->mytid, syscall(__NR_gettid)); 1500 EXPECT_NE(self->mytid, syscall(__NR_gettid));
1471} 1501}
1472 1502
@@ -1479,6 +1509,8 @@ TEST_F(TRACE_syscall, syscall_dropped)
1479# define __NR_seccomp 383 1509# define __NR_seccomp 383
1480# elif defined(__aarch64__) 1510# elif defined(__aarch64__)
1481# define __NR_seccomp 277 1511# define __NR_seccomp 277
1512# elif defined(__hppa__)
1513# define __NR_seccomp 338
1482# elif defined(__powerpc__) 1514# elif defined(__powerpc__)
1483# define __NR_seccomp 358 1515# define __NR_seccomp 358
1484# elif defined(__s390__) 1516# elif defined(__s390__)
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/vm/thuge-gen.c b/tools/testing/selftests/vm/thuge-gen.c
index c87957295f74..0bc737a75150 100644
--- a/tools/testing/selftests/vm/thuge-gen.c
+++ b/tools/testing/selftests/vm/thuge-gen.c
@@ -30,7 +30,9 @@
30#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT) 30#define MAP_HUGE_1GB (30 << MAP_HUGE_SHIFT)
31#define MAP_HUGE_SHIFT 26 31#define MAP_HUGE_SHIFT 26
32#define MAP_HUGE_MASK 0x3f 32#define MAP_HUGE_MASK 0x3f
33#if !defined(MAP_HUGETLB)
33#define MAP_HUGETLB 0x40000 34#define MAP_HUGETLB 0x40000
35#endif
34 36
35#define SHM_HUGETLB 04000 /* segment will use huge TLB pages */ 37#define SHM_HUGETLB 04000 /* segment will use huge TLB pages */
36#define SHM_HUGE_SHIFT 26 38#define SHM_HUGE_SHIFT 26
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}
diff --git a/tools/usb/usbip/libsrc/Makefile.am b/tools/usb/usbip/libsrc/Makefile.am
index 7c8f8a4d54e4..90daf95c0804 100644
--- a/tools/usb/usbip/libsrc/Makefile.am
+++ b/tools/usb/usbip/libsrc/Makefile.am
@@ -4,5 +4,7 @@ libusbip_la_LDFLAGS = -version-info @LIBUSBIP_VERSION@
4 4
5lib_LTLIBRARIES := libusbip.la 5lib_LTLIBRARIES := libusbip.la
6libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \ 6libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \
7 usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h \ 7 usbip_device_driver.c usbip_device_driver.h \
8 usbip_common.c usbip_common.h usbip_host_common.h \
9 usbip_host_common.c vhci_driver.c vhci_driver.h \
8 sysfs_utils.c sysfs_utils.h 10 sysfs_utils.c sysfs_utils.h
diff --git a/tools/usb/usbip/libsrc/usbip_common.h b/tools/usb/usbip/libsrc/usbip_common.h
index 15fe792e1e96..51ef5fe485dd 100644
--- a/tools/usb/usbip/libsrc/usbip_common.h
+++ b/tools/usb/usbip/libsrc/usbip_common.h
@@ -25,9 +25,12 @@
25#define VHCI_STATE_PATH "/var/run/vhci_hcd" 25#define VHCI_STATE_PATH "/var/run/vhci_hcd"
26#endif 26#endif
27 27
28#define VUDC_DEVICE_DESCR_FILE "dev_desc"
29
28/* kernel module names */ 30/* kernel module names */
29#define USBIP_CORE_MOD_NAME "usbip-core" 31#define USBIP_CORE_MOD_NAME "usbip-core"
30#define USBIP_HOST_DRV_NAME "usbip-host" 32#define USBIP_HOST_DRV_NAME "usbip-host"
33#define USBIP_DEVICE_DRV_NAME "usbip-vudc"
31#define USBIP_VHCI_DRV_NAME "vhci_hcd" 34#define USBIP_VHCI_DRV_NAME "vhci_hcd"
32 35
33/* sysfs constants */ 36/* sysfs constants */
diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.c b/tools/usb/usbip/libsrc/usbip_device_driver.c
new file mode 100644
index 000000000000..e059b7d1ec5b
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_device_driver.c
@@ -0,0 +1,163 @@
1/*
2 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
3 * 2015 Samsung Electronics
4 * Author: Igor Kotrasinski <i.kotrasinsk@samsung.com>
5 *
6 * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <fcntl.h>
25#include <string.h>
26#include <linux/usb/ch9.h>
27
28#include <unistd.h>
29
30#include "usbip_host_common.h"
31#include "usbip_device_driver.h"
32
33#undef PROGNAME
34#define PROGNAME "libusbip"
35
36#define copy_descr_attr16(dev, descr, attr) \
37 ((dev)->attr = le16toh((descr)->attr)) \
38
39#define copy_descr_attr(dev, descr, attr) \
40 ((dev)->attr = (descr)->attr) \
41
42#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
43
44static struct {
45 enum usb_device_speed speed;
46 const char *name;
47} speed_names[] = {
48 {
49 .speed = USB_SPEED_UNKNOWN,
50 .name = "UNKNOWN",
51 },
52 {
53 .speed = USB_SPEED_LOW,
54 .name = "low-speed",
55 },
56 {
57 .speed = USB_SPEED_FULL,
58 .name = "full-speed",
59 },
60 {
61 .speed = USB_SPEED_HIGH,
62 .name = "high-speed",
63 },
64 {
65 .speed = USB_SPEED_WIRELESS,
66 .name = "wireless",
67 },
68 {
69 .speed = USB_SPEED_SUPER,
70 .name = "super-speed",
71 },
72};
73
74static
75int read_usb_vudc_device(struct udev_device *sdev, struct usbip_usb_device *dev)
76{
77 const char *path, *name;
78 char filepath[SYSFS_PATH_MAX];
79 struct usb_device_descriptor descr;
80 unsigned i;
81 FILE *fd = NULL;
82 struct udev_device *plat;
83 const char *speed;
84 int ret = 0;
85
86 plat = udev_device_get_parent(sdev);
87 path = udev_device_get_syspath(plat);
88 snprintf(filepath, SYSFS_PATH_MAX, "%s/%s",
89 path, VUDC_DEVICE_DESCR_FILE);
90 fd = fopen(filepath, "r");
91 if (!fd)
92 return -1;
93 ret = fread((char *) &descr, sizeof(descr), 1, fd);
94 if (ret < 0)
95 return -1;
96 fclose(fd);
97
98 copy_descr_attr(dev, &descr, bDeviceClass);
99 copy_descr_attr(dev, &descr, bDeviceSubClass);
100 copy_descr_attr(dev, &descr, bDeviceProtocol);
101 copy_descr_attr(dev, &descr, bNumConfigurations);
102 copy_descr_attr16(dev, &descr, idVendor);
103 copy_descr_attr16(dev, &descr, idProduct);
104 copy_descr_attr16(dev, &descr, bcdDevice);
105
106 strncpy(dev->path, path, SYSFS_PATH_MAX);
107
108 dev->speed = USB_SPEED_UNKNOWN;
109 speed = udev_device_get_sysattr_value(sdev, "current_speed");
110 if (speed) {
111 for (i = 0; i < ARRAY_SIZE(speed_names); i++) {
112 if (!strcmp(speed_names[i].name, speed)) {
113 dev->speed = speed_names[i].speed;
114 break;
115 }
116 }
117 }
118
119 /* Only used for user output, little sense to output them in general */
120 dev->bNumInterfaces = 0;
121 dev->bConfigurationValue = 0;
122 dev->busnum = 0;
123
124 name = udev_device_get_sysname(plat);
125 strncpy(dev->busid, name, SYSFS_BUS_ID_SIZE);
126 return 0;
127}
128
129static int is_my_device(struct udev_device *dev)
130{
131 const char *driver;
132
133 driver = udev_device_get_property_value(dev, "USB_UDC_NAME");
134 return driver != NULL && !strcmp(driver, USBIP_DEVICE_DRV_NAME);
135}
136
137static int usbip_device_driver_open(struct usbip_host_driver *hdriver)
138{
139 int ret;
140
141 hdriver->ndevs = 0;
142 INIT_LIST_HEAD(&hdriver->edev_list);
143
144 ret = usbip_generic_driver_open(hdriver);
145 if (ret)
146 err("please load " USBIP_CORE_MOD_NAME ".ko and "
147 USBIP_DEVICE_DRV_NAME ".ko!");
148
149 return ret;
150}
151
152struct usbip_host_driver device_driver = {
153 .edev_list = LIST_HEAD_INIT(device_driver.edev_list),
154 .udev_subsystem = "udc",
155 .ops = {
156 .open = usbip_device_driver_open,
157 .close = usbip_generic_driver_close,
158 .refresh_device_list = usbip_generic_refresh_device_list,
159 .get_device = usbip_generic_get_device,
160 .read_device = read_usb_vudc_device,
161 .is_my_device = is_my_device,
162 },
163};
diff --git a/tools/usb/usbip/libsrc/usbip_device_driver.h b/tools/usb/usbip/libsrc/usbip_device_driver.h
new file mode 100644
index 000000000000..54cb658b37a3
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_device_driver.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu>
3 * 2015 Samsung Electronics
4 * Author: Igor Kotrasinski <i.kotrasinsk@samsung.com>
5 *
6 * Based on tools/usb/usbip/libsrc/usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
22 */
23
24#ifndef __USBIP_DEVICE_DRIVER_H
25#define __USBIP_DEVICE_DRIVER_H
26
27#include <stdint.h>
28#include "usbip_common.h"
29#include "usbip_host_common.h"
30#include "list.h"
31
32extern struct usbip_host_driver device_driver;
33
34#endif /* __USBIP_DEVICE_DRIVER_H */
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.c b/tools/usb/usbip/libsrc/usbip_host_common.c
new file mode 100644
index 000000000000..9d415228883d
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_host_common.c
@@ -0,0 +1,273 @@
1/*
2 * Copyright (C) 2015-2016 Samsung Electronics
3 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
4 * Krzysztof Opasiak <k.opasiak@samsung.com>
5 *
6 * Refactored from usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27
28#include <errno.h>
29#include <unistd.h>
30
31#include <libudev.h>
32
33#include "usbip_common.h"
34#include "usbip_host_common.h"
35#include "list.h"
36#include "sysfs_utils.h"
37
38struct udev *udev_context;
39
40static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
41{
42 char status_attr_path[SYSFS_PATH_MAX];
43 int fd;
44 int length;
45 char status;
46 int value = 0;
47
48 snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
49 udev->path);
50
51 fd = open(status_attr_path, O_RDONLY);
52 if (fd < 0) {
53 err("error opening attribute %s", status_attr_path);
54 return -1;
55 }
56
57 length = read(fd, &status, 1);
58 if (length < 0) {
59 err("error reading attribute %s", status_attr_path);
60 close(fd);
61 return -1;
62 }
63
64 value = atoi(&status);
65
66 return value;
67}
68
69static
70struct usbip_exported_device *usbip_exported_device_new(
71 struct usbip_host_driver *hdriver, const char *sdevpath)
72{
73 struct usbip_exported_device *edev = NULL;
74 struct usbip_exported_device *edev_old;
75 size_t size;
76 int i;
77
78 edev = calloc(1, sizeof(struct usbip_exported_device));
79
80 edev->sudev =
81 udev_device_new_from_syspath(udev_context, sdevpath);
82 if (!edev->sudev) {
83 err("udev_device_new_from_syspath: %s", sdevpath);
84 goto err;
85 }
86
87 if (hdriver->ops.read_device(edev->sudev, &edev->udev) < 0)
88 goto err;
89
90 edev->status = read_attr_usbip_status(&edev->udev);
91 if (edev->status < 0)
92 goto err;
93
94 /* reallocate buffer to include usb interface data */
95 size = sizeof(struct usbip_exported_device) +
96 edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
97
98 edev_old = edev;
99 edev = realloc(edev, size);
100 if (!edev) {
101 edev = edev_old;
102 dbg("realloc failed");
103 goto err;
104 }
105
106 for (i = 0; i < edev->udev.bNumInterfaces; i++) {
107 /* vudc does not support reading interfaces */
108 if (!hdriver->ops.read_interface)
109 break;
110 hdriver->ops.read_interface(&edev->udev, i, &edev->uinf[i]);
111 }
112
113 return edev;
114err:
115 if (edev->sudev)
116 udev_device_unref(edev->sudev);
117 if (edev)
118 free(edev);
119
120 return NULL;
121}
122
123static int refresh_exported_devices(struct usbip_host_driver *hdriver)
124{
125 struct usbip_exported_device *edev;
126 struct udev_enumerate *enumerate;
127 struct udev_list_entry *devices, *dev_list_entry;
128 struct udev_device *dev;
129 const char *path;
130
131 enumerate = udev_enumerate_new(udev_context);
132 udev_enumerate_add_match_subsystem(enumerate, hdriver->udev_subsystem);
133 udev_enumerate_scan_devices(enumerate);
134
135 devices = udev_enumerate_get_list_entry(enumerate);
136
137 udev_list_entry_foreach(dev_list_entry, devices) {
138 path = udev_list_entry_get_name(dev_list_entry);
139 dev = udev_device_new_from_syspath(udev_context,
140 path);
141 if (dev == NULL)
142 continue;
143
144 /* Check whether device uses usbip driver. */
145 if (hdriver->ops.is_my_device(dev)) {
146 edev = usbip_exported_device_new(hdriver, path);
147 if (!edev) {
148 dbg("usbip_exported_device_new failed");
149 continue;
150 }
151
152 list_add(&edev->node, &hdriver->edev_list);
153 hdriver->ndevs++;
154 }
155 }
156
157 return 0;
158}
159
160static void usbip_exported_device_destroy(struct list_head *devs)
161{
162 struct list_head *i, *tmp;
163 struct usbip_exported_device *edev;
164
165 list_for_each_safe(i, tmp, devs) {
166 edev = list_entry(i, struct usbip_exported_device, node);
167 list_del(i);
168 free(edev);
169 }
170}
171
172int usbip_generic_driver_open(struct usbip_host_driver *hdriver)
173{
174 int rc;
175
176 udev_context = udev_new();
177 if (!udev_context) {
178 err("udev_new failed");
179 return -1;
180 }
181
182 rc = refresh_exported_devices(hdriver);
183 if (rc < 0)
184 goto err;
185 return 0;
186err:
187 udev_unref(udev_context);
188 return -1;
189}
190
191void usbip_generic_driver_close(struct usbip_host_driver *hdriver)
192{
193 if (!hdriver)
194 return;
195
196 usbip_exported_device_destroy(&hdriver->edev_list);
197
198 udev_unref(udev_context);
199}
200
201int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver)
202{
203 int rc;
204
205 usbip_exported_device_destroy(&hdriver->edev_list);
206
207 hdriver->ndevs = 0;
208 INIT_LIST_HEAD(&hdriver->edev_list);
209
210 rc = refresh_exported_devices(hdriver);
211 if (rc < 0)
212 return -1;
213
214 return 0;
215}
216
217int usbip_export_device(struct usbip_exported_device *edev, int sockfd)
218{
219 char attr_name[] = "usbip_sockfd";
220 char sockfd_attr_path[SYSFS_PATH_MAX];
221 char sockfd_buff[30];
222 int ret;
223
224 if (edev->status != SDEV_ST_AVAILABLE) {
225 dbg("device not available: %s", edev->udev.busid);
226 switch (edev->status) {
227 case SDEV_ST_ERROR:
228 dbg("status SDEV_ST_ERROR");
229 break;
230 case SDEV_ST_USED:
231 dbg("status SDEV_ST_USED");
232 break;
233 default:
234 dbg("status unknown: 0x%x", edev->status);
235 }
236 return -1;
237 }
238
239 /* only the first interface is true */
240 snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
241 edev->udev.path, attr_name);
242
243 snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
244
245 ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
246 strlen(sockfd_buff));
247 if (ret < 0) {
248 err("write_sysfs_attribute failed: sockfd %s to %s",
249 sockfd_buff, sockfd_attr_path);
250 return ret;
251 }
252
253 info("connect: %s", edev->udev.busid);
254
255 return ret;
256}
257
258struct usbip_exported_device *usbip_generic_get_device(
259 struct usbip_host_driver *hdriver, int num)
260{
261 struct list_head *i;
262 struct usbip_exported_device *edev;
263 int cnt = 0;
264
265 list_for_each(i, &hdriver->edev_list) {
266 edev = list_entry(i, struct usbip_exported_device, node);
267 if (num == cnt)
268 return edev;
269 cnt++;
270 }
271
272 return NULL;
273}
diff --git a/tools/usb/usbip/libsrc/usbip_host_common.h b/tools/usb/usbip/libsrc/usbip_host_common.h
new file mode 100644
index 000000000000..a64b8033fe64
--- /dev/null
+++ b/tools/usb/usbip/libsrc/usbip_host_common.h
@@ -0,0 +1,104 @@
1/*
2 * Copyright (C) 2015-2016 Samsung Electronics
3 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
4 * Krzysztof Opasiak <k.opasiak@samsung.com>
5 *
6 * Refactored from usbip_host_driver.c, which is:
7 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
8 * 2005-2007 Takahiro Hirofuchi
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, see <http://www.gnu.org/licenses/>.
22 */
23
24#ifndef __USBIP_HOST_COMMON_H
25#define __USBIP_HOST_COMMON_H
26
27#include <stdint.h>
28#include <libudev.h>
29#include <errno.h>
30#include "list.h"
31#include "usbip_common.h"
32#include "sysfs_utils.h"
33
34struct usbip_host_driver;
35
36struct usbip_host_driver_ops {
37 int (*open)(struct usbip_host_driver *hdriver);
38 void (*close)(struct usbip_host_driver *hdriver);
39 int (*refresh_device_list)(struct usbip_host_driver *hdriver);
40 struct usbip_exported_device * (*get_device)(
41 struct usbip_host_driver *hdriver, int num);
42
43 int (*read_device)(struct udev_device *sdev,
44 struct usbip_usb_device *dev);
45 int (*read_interface)(struct usbip_usb_device *udev, int i,
46 struct usbip_usb_interface *uinf);
47 int (*is_my_device)(struct udev_device *udev);
48};
49
50struct usbip_host_driver {
51 int ndevs;
52 /* list of exported device */
53 struct list_head edev_list;
54 const char *udev_subsystem;
55 struct usbip_host_driver_ops ops;
56};
57
58struct usbip_exported_device {
59 struct udev_device *sudev;
60 int32_t status;
61 struct usbip_usb_device udev;
62 struct list_head node;
63 struct usbip_usb_interface uinf[];
64};
65
66/* External API to access the driver */
67static inline int usbip_driver_open(struct usbip_host_driver *hdriver)
68{
69 if (!hdriver->ops.open)
70 return -EOPNOTSUPP;
71 return hdriver->ops.open(hdriver);
72}
73
74static inline void usbip_driver_close(struct usbip_host_driver *hdriver)
75{
76 if (!hdriver->ops.close)
77 return;
78 hdriver->ops.close(hdriver);
79}
80
81static inline int usbip_refresh_device_list(struct usbip_host_driver *hdriver)
82{
83 if (!hdriver->ops.refresh_device_list)
84 return -EOPNOTSUPP;
85 return hdriver->ops.refresh_device_list(hdriver);
86}
87
88static inline struct usbip_exported_device *
89usbip_get_device(struct usbip_host_driver *hdriver, int num)
90{
91 if (!hdriver->ops.get_device)
92 return NULL;
93 return hdriver->ops.get_device(hdriver, num);
94}
95
96/* Helper functions for implementing driver backend */
97int usbip_generic_driver_open(struct usbip_host_driver *hdriver);
98void usbip_generic_driver_close(struct usbip_host_driver *hdriver);
99int usbip_generic_refresh_device_list(struct usbip_host_driver *hdriver);
100int usbip_export_device(struct usbip_exported_device *edev, int sockfd);
101struct usbip_exported_device *usbip_generic_get_device(
102 struct usbip_host_driver *hdriver, int num);
103
104#endif /* __USBIP_HOST_COMMON_H */
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.c b/tools/usb/usbip/libsrc/usbip_host_driver.c
index bef08d5c44e8..4de6edc54d35 100644
--- a/tools/usb/usbip/libsrc/usbip_host_driver.c
+++ b/tools/usb/usbip/libsrc/usbip_host_driver.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * 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 9 * it under the terms of the GNU General Public License as published by
@@ -16,265 +19,47 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 20 */
18 21
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22
23#include <errno.h>
24#include <unistd.h> 22#include <unistd.h>
25
26#include <libudev.h> 23#include <libudev.h>
27 24
28#include "usbip_common.h" 25#include "usbip_host_common.h"
29#include "usbip_host_driver.h" 26#include "usbip_host_driver.h"
30#include "list.h"
31#include "sysfs_utils.h"
32 27
33#undef PROGNAME 28#undef PROGNAME
34#define PROGNAME "libusbip" 29#define PROGNAME "libusbip"
35 30
36struct usbip_host_driver *host_driver; 31static int is_my_device(struct udev_device *dev)
37struct udev *udev_context;
38
39static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
40{
41 char status_attr_path[SYSFS_PATH_MAX];
42 int fd;
43 int length;
44 char status;
45 int value = 0;
46
47 snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
48 udev->path);
49
50 fd = open(status_attr_path, O_RDONLY);
51 if (fd < 0) {
52 err("error opening attribute %s", status_attr_path);
53 return -1;
54 }
55
56 length = read(fd, &status, 1);
57 if (length < 0) {
58 err("error reading attribute %s", status_attr_path);
59 close(fd);
60 return -1;
61 }
62
63 value = atoi(&status);
64
65 return value;
66}
67
68static
69struct usbip_exported_device *usbip_exported_device_new(const char *sdevpath)
70{
71 struct usbip_exported_device *edev = NULL;
72 struct usbip_exported_device *edev_old;
73 size_t size;
74 int i;
75
76 edev = calloc(1, sizeof(struct usbip_exported_device));
77
78 edev->sudev = udev_device_new_from_syspath(udev_context, sdevpath);
79 if (!edev->sudev) {
80 err("udev_device_new_from_syspath: %s", sdevpath);
81 goto err;
82 }
83
84 read_usb_device(edev->sudev, &edev->udev);
85
86 edev->status = read_attr_usbip_status(&edev->udev);
87 if (edev->status < 0)
88 goto err;
89
90 /* reallocate buffer to include usb interface data */
91 size = sizeof(struct usbip_exported_device) +
92 edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
93
94 edev_old = edev;
95 edev = realloc(edev, size);
96 if (!edev) {
97 edev = edev_old;
98 dbg("realloc failed");
99 goto err;
100 }
101
102 for (i = 0; i < edev->udev.bNumInterfaces; i++)
103 read_usb_interface(&edev->udev, i, &edev->uinf[i]);
104
105 return edev;
106err:
107 if (edev->sudev)
108 udev_device_unref(edev->sudev);
109 if (edev)
110 free(edev);
111
112 return NULL;
113}
114
115static int refresh_exported_devices(void)
116{ 32{
117 struct usbip_exported_device *edev;
118 struct udev_enumerate *enumerate;
119 struct udev_list_entry *devices, *dev_list_entry;
120 struct udev_device *dev;
121 const char *path;
122 const char *driver; 33 const char *driver;
123 34
124 enumerate = udev_enumerate_new(udev_context); 35 driver = udev_device_get_driver(dev);
125 udev_enumerate_add_match_subsystem(enumerate, "usb"); 36 return driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME);
126 udev_enumerate_scan_devices(enumerate);
127
128 devices = udev_enumerate_get_list_entry(enumerate);
129
130 udev_list_entry_foreach(dev_list_entry, devices) {
131 path = udev_list_entry_get_name(dev_list_entry);
132 dev = udev_device_new_from_syspath(udev_context, path);
133 if (dev == NULL)
134 continue;
135
136 /* Check whether device uses usbip-host driver. */
137 driver = udev_device_get_driver(dev);
138 if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) {
139 edev = usbip_exported_device_new(path);
140 if (!edev) {
141 dbg("usbip_exported_device_new failed");
142 continue;
143 }
144
145 list_add(&edev->node, &host_driver->edev_list);
146 host_driver->ndevs++;
147 }
148 }
149
150 return 0;
151}
152
153static void usbip_exported_device_destroy(void)
154{
155 struct list_head *i, *tmp;
156 struct usbip_exported_device *edev;
157
158 list_for_each_safe(i, tmp, &host_driver->edev_list) {
159 edev = list_entry(i, struct usbip_exported_device, node);
160 list_del(i);
161 free(edev);
162 }
163} 37}
164 38
165int usbip_host_driver_open(void) 39static int usbip_host_driver_open(struct usbip_host_driver *hdriver)
166{ 40{
167 int rc;
168
169 udev_context = udev_new();
170 if (!udev_context) {
171 err("udev_new failed");
172 return -1;
173 }
174
175 host_driver = calloc(1, sizeof(*host_driver));
176
177 host_driver->ndevs = 0;
178 INIT_LIST_HEAD(&host_driver->edev_list);
179
180 rc = refresh_exported_devices();
181 if (rc < 0)
182 goto err_free_host_driver;
183
184 return 0;
185
186err_free_host_driver:
187 free(host_driver);
188 host_driver = NULL;
189
190 udev_unref(udev_context);
191
192 return -1;
193}
194
195void usbip_host_driver_close(void)
196{
197 if (!host_driver)
198 return;
199
200 usbip_exported_device_destroy();
201
202 free(host_driver);
203 host_driver = NULL;
204
205 udev_unref(udev_context);
206}
207
208int usbip_host_refresh_device_list(void)
209{
210 int rc;
211
212 usbip_exported_device_destroy();
213
214 host_driver->ndevs = 0;
215 INIT_LIST_HEAD(&host_driver->edev_list);
216
217 rc = refresh_exported_devices();
218 if (rc < 0)
219 return -1;
220
221 return 0;
222}
223
224int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd)
225{
226 char attr_name[] = "usbip_sockfd";
227 char sockfd_attr_path[SYSFS_PATH_MAX];
228 char sockfd_buff[30];
229 int ret; 41 int ret;
230 42
231 if (edev->status != SDEV_ST_AVAILABLE) { 43 hdriver->ndevs = 0;
232 dbg("device not available: %s", edev->udev.busid); 44 INIT_LIST_HEAD(&hdriver->edev_list);
233 switch (edev->status) {
234 case SDEV_ST_ERROR:
235 dbg("status SDEV_ST_ERROR");
236 break;
237 case SDEV_ST_USED:
238 dbg("status SDEV_ST_USED");
239 break;
240 default:
241 dbg("status unknown: 0x%x", edev->status);
242 }
243 return -1;
244 }
245
246 /* only the first interface is true */
247 snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
248 edev->udev.path, attr_name);
249
250 snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
251
252 ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
253 strlen(sockfd_buff));
254 if (ret < 0) {
255 err("write_sysfs_attribute failed: sockfd %s to %s",
256 sockfd_buff, sockfd_attr_path);
257 return ret;
258 }
259
260 info("connect: %s", edev->udev.busid);
261 45
46 ret = usbip_generic_driver_open(hdriver);
47 if (ret)
48 err("please load " USBIP_CORE_MOD_NAME ".ko and "
49 USBIP_HOST_DRV_NAME ".ko!");
262 return ret; 50 return ret;
263} 51}
264 52
265struct usbip_exported_device *usbip_host_get_device(int num) 53struct usbip_host_driver host_driver = {
266{ 54 .edev_list = LIST_HEAD_INIT(host_driver.edev_list),
267 struct list_head *i; 55 .udev_subsystem = "usb",
268 struct usbip_exported_device *edev; 56 .ops = {
269 int cnt = 0; 57 .open = usbip_host_driver_open,
270 58 .close = usbip_generic_driver_close,
271 list_for_each(i, &host_driver->edev_list) { 59 .refresh_device_list = usbip_generic_refresh_device_list,
272 edev = list_entry(i, struct usbip_exported_device, node); 60 .get_device = usbip_generic_get_device,
273 if (num == cnt) 61 .read_device = read_usb_device,
274 return edev; 62 .read_interface = read_usb_interface,
275 else 63 .is_my_device = is_my_device,
276 cnt++; 64 },
277 } 65};
278
279 return NULL;
280}
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.h b/tools/usb/usbip/libsrc/usbip_host_driver.h
index 2a31f855c616..77f07e72a7fe 100644
--- a/tools/usb/usbip/libsrc/usbip_host_driver.h
+++ b/tools/usb/usbip/libsrc/usbip_host_driver.h
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * 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 9 * it under the terms of the GNU General Public License as published by
@@ -22,28 +25,8 @@
22#include <stdint.h> 25#include <stdint.h>
23#include "usbip_common.h" 26#include "usbip_common.h"
24#include "list.h" 27#include "list.h"
28#include "usbip_host_common.h"
25 29
26struct usbip_host_driver { 30extern struct usbip_host_driver host_driver;
27 int ndevs;
28 /* list of exported device */
29 struct list_head edev_list;
30};
31
32struct usbip_exported_device {
33 struct udev_device *sudev;
34 int32_t status;
35 struct usbip_usb_device udev;
36 struct list_head node;
37 struct usbip_usb_interface uinf[];
38};
39
40extern struct usbip_host_driver *host_driver;
41
42int usbip_host_driver_open(void);
43void usbip_host_driver_close(void);
44
45int usbip_host_refresh_device_list(void);
46int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd);
47struct usbip_exported_device *usbip_host_get_device(int num);
48 31
49#endif /* __USBIP_HOST_DRIVER_H */ 32#endif /* __USBIP_HOST_DRIVER_H */
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index d58a14dfc094..70a6b507fb62 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * 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 9 * it under the terms of the GNU General Public License as published by
@@ -36,7 +39,8 @@
36static const char usbip_attach_usage_string[] = 39static const char usbip_attach_usage_string[] =
37 "usbip attach <args>\n" 40 "usbip attach <args>\n"
38 " -r, --remote=<host> The machine with exported USB devices\n" 41 " -r, --remote=<host> The machine with exported USB devices\n"
39 " -b, --busid=<busid> Busid of the device on <host>\n"; 42 " -b, --busid=<busid> Busid of the device on <host>\n"
43 " -d, --device=<devid> Id of the virtual UDC on <host>\n";
40 44
41void usbip_attach_usage(void) 45void usbip_attach_usage(void)
42{ 46{
@@ -203,6 +207,7 @@ int usbip_attach(int argc, char *argv[])
203 static const struct option opts[] = { 207 static const struct option opts[] = {
204 { "remote", required_argument, NULL, 'r' }, 208 { "remote", required_argument, NULL, 'r' },
205 { "busid", required_argument, NULL, 'b' }, 209 { "busid", required_argument, NULL, 'b' },
210 { "device", required_argument, NULL, 'd' },
206 { NULL, 0, NULL, 0 } 211 { NULL, 0, NULL, 0 }
207 }; 212 };
208 char *host = NULL; 213 char *host = NULL;
@@ -211,7 +216,7 @@ int usbip_attach(int argc, char *argv[])
211 int ret = -1; 216 int ret = -1;
212 217
213 for (;;) { 218 for (;;) {
214 opt = getopt_long(argc, argv, "r:b:", opts, NULL); 219 opt = getopt_long(argc, argv, "d:r:b:", opts, NULL);
215 220
216 if (opt == -1) 221 if (opt == -1)
217 break; 222 break;
@@ -220,6 +225,7 @@ int usbip_attach(int argc, char *argv[])
220 case 'r': 225 case 'r':
221 host = optarg; 226 host = optarg;
222 break; 227 break;
228 case 'd':
223 case 'b': 229 case 'b':
224 busid = optarg; 230 busid = optarg;
225 break; 231 break;
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index d5ce34a410e7..f1b38e866dd7 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * 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 9 * it under the terms of the GNU General Public License as published by
@@ -30,6 +33,10 @@
30#include <netdb.h> 33#include <netdb.h>
31#include <unistd.h> 34#include <unistd.h>
32 35
36#include <dirent.h>
37
38#include <linux/usb/ch9.h>
39
33#include "usbip_common.h" 40#include "usbip_common.h"
34#include "usbip_network.h" 41#include "usbip_network.h"
35#include "usbip.h" 42#include "usbip.h"
@@ -205,8 +212,10 @@ static int list_devices(bool parsable)
205 /* Get device information. */ 212 /* Get device information. */
206 idVendor = udev_device_get_sysattr_value(dev, "idVendor"); 213 idVendor = udev_device_get_sysattr_value(dev, "idVendor");
207 idProduct = udev_device_get_sysattr_value(dev, "idProduct"); 214 idProduct = udev_device_get_sysattr_value(dev, "idProduct");
208 bConfValue = udev_device_get_sysattr_value(dev, "bConfigurationValue"); 215 bConfValue = udev_device_get_sysattr_value(dev,
209 bNumIntfs = udev_device_get_sysattr_value(dev, "bNumInterfaces"); 216 "bConfigurationValue");
217 bNumIntfs = udev_device_get_sysattr_value(dev,
218 "bNumInterfaces");
210 busid = udev_device_get_sysname(dev); 219 busid = udev_device_get_sysname(dev);
211 if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) { 220 if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
212 err("problem getting device attributes: %s", 221 err("problem getting device attributes: %s",
@@ -237,12 +246,90 @@ err_out:
237 return ret; 246 return ret;
238} 247}
239 248
249static int list_gadget_devices(bool parsable)
250{
251 int ret = -1;
252 struct udev *udev;
253 struct udev_enumerate *enumerate;
254 struct udev_list_entry *devices, *dev_list_entry;
255 struct udev_device *dev;
256 const char *path;
257 const char *driver;
258
259 const struct usb_device_descriptor *d_desc;
260 const char *descriptors;
261 char product_name[128];
262
263 uint16_t idVendor;
264 char idVendor_buf[8];
265 uint16_t idProduct;
266 char idProduct_buf[8];
267 const char *busid;
268
269 udev = udev_new();
270 enumerate = udev_enumerate_new(udev);
271
272 udev_enumerate_add_match_subsystem(enumerate, "platform");
273
274 udev_enumerate_scan_devices(enumerate);
275 devices = udev_enumerate_get_list_entry(enumerate);
276
277 udev_list_entry_foreach(dev_list_entry, devices) {
278 path = udev_list_entry_get_name(dev_list_entry);
279 dev = udev_device_new_from_syspath(udev, path);
280
281 driver = udev_device_get_driver(dev);
282 /* We only have mechanism to enumerate gadgets bound to vudc */
283 if (driver == NULL || strcmp(driver, USBIP_DEVICE_DRV_NAME))
284 continue;
285
286 /* Get device information. */
287 descriptors = udev_device_get_sysattr_value(dev,
288 VUDC_DEVICE_DESCR_FILE);
289
290 if (!descriptors) {
291 err("problem getting device attributes: %s",
292 strerror(errno));
293 goto err_out;
294 }
295
296 d_desc = (const struct usb_device_descriptor *) descriptors;
297
298 idVendor = le16toh(d_desc->idVendor);
299 sprintf(idVendor_buf, "0x%4x", idVendor);
300 idProduct = le16toh(d_desc->idProduct);
301 sprintf(idProduct_buf, "0x%4x", idVendor);
302 busid = udev_device_get_sysname(dev);
303
304 /* Get product name. */
305 usbip_names_get_product(product_name, sizeof(product_name),
306 le16toh(idVendor),
307 le16toh(idProduct));
308
309 /* Print information. */
310 print_device(busid, idVendor_buf, idProduct_buf, parsable);
311 print_product_name(product_name, parsable);
312
313 printf("\n");
314
315 udev_device_unref(dev);
316 }
317 ret = 0;
318
319err_out:
320 udev_enumerate_unref(enumerate);
321 udev_unref(udev);
322
323 return ret;
324}
325
240int usbip_list(int argc, char *argv[]) 326int usbip_list(int argc, char *argv[])
241{ 327{
242 static const struct option opts[] = { 328 static const struct option opts[] = {
243 { "parsable", no_argument, NULL, 'p' }, 329 { "parsable", no_argument, NULL, 'p' },
244 { "remote", required_argument, NULL, 'r' }, 330 { "remote", required_argument, NULL, 'r' },
245 { "local", no_argument, NULL, 'l' }, 331 { "local", no_argument, NULL, 'l' },
332 { "device", no_argument, NULL, 'd' },
246 { NULL, 0, NULL, 0 } 333 { NULL, 0, NULL, 0 }
247 }; 334 };
248 335
@@ -254,7 +341,7 @@ int usbip_list(int argc, char *argv[])
254 err("failed to open %s", USBIDS_FILE); 341 err("failed to open %s", USBIDS_FILE);
255 342
256 for (;;) { 343 for (;;) {
257 opt = getopt_long(argc, argv, "pr:l", opts, NULL); 344 opt = getopt_long(argc, argv, "pr:ld", opts, NULL);
258 345
259 if (opt == -1) 346 if (opt == -1)
260 break; 347 break;
@@ -269,6 +356,9 @@ int usbip_list(int argc, char *argv[])
269 case 'l': 356 case 'l':
270 ret = list_devices(parsable); 357 ret = list_devices(parsable);
271 goto out; 358 goto out;
359 case 'd':
360 ret = list_gadget_devices(parsable);
361 goto out;
272 default: 362 default:
273 goto err_out; 363 goto err_out;
274 } 364 }
diff --git a/tools/usb/usbip/src/usbip_port.c b/tools/usb/usbip/src/usbip_port.c
index a2e884fd9226..7bd74fb3a9cd 100644
--- a/tools/usb/usbip/src/usbip_port.c
+++ b/tools/usb/usbip/src/usbip_port.c
@@ -22,10 +22,13 @@ static int list_imported_devices(void)
22 struct usbip_imported_device *idev; 22 struct usbip_imported_device *idev;
23 int ret; 23 int ret;
24 24
25 if (usbip_names_init(USBIDS_FILE))
26 err("failed to open %s", USBIDS_FILE);
27
25 ret = usbip_vhci_driver_open(); 28 ret = usbip_vhci_driver_open();
26 if (ret < 0) { 29 if (ret < 0) {
27 err("open vhci_driver"); 30 err("open vhci_driver");
28 return -1; 31 goto err_names_free;
29 } 32 }
30 33
31 printf("Imported USB devices\n"); 34 printf("Imported USB devices\n");
@@ -35,13 +38,19 @@ static int list_imported_devices(void)
35 idev = &vhci_driver->idev[i]; 38 idev = &vhci_driver->idev[i];
36 39
37 if (usbip_vhci_imported_device_dump(idev) < 0) 40 if (usbip_vhci_imported_device_dump(idev) < 0)
38 ret = -1; 41 goto err_driver_close;
39 } 42 }
40 43
41 usbip_vhci_driver_close(); 44 usbip_vhci_driver_close();
45 usbip_names_free();
42 46
43 return ret; 47 return ret;
44 48
49err_driver_close:
50 usbip_vhci_driver_close();
51err_names_free:
52 usbip_names_free();
53 return -1;
45} 54}
46 55
47int usbip_port_show(__attribute__((unused)) int argc, 56int usbip_port_show(__attribute__((unused)) int argc,
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
index 2a7cd2b8d966..a0972dea9e6c 100644
--- a/tools/usb/usbip/src/usbipd.c
+++ b/tools/usb/usbip/src/usbipd.c
@@ -1,6 +1,9 @@
1/* 1/*
2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi 3 * 2005-2007 Takahiro Hirofuchi
4 * Copyright (C) 2015-2016 Samsung Electronics
5 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
6 * Krzysztof Opasiak <k.opasiak@samsung.com>
4 * 7 *
5 * This program is free software: you can redistribute it and/or modify 8 * 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 9 * it under the terms of the GNU General Public License as published by
@@ -41,6 +44,8 @@
41#include <poll.h> 44#include <poll.h>
42 45
43#include "usbip_host_driver.h" 46#include "usbip_host_driver.h"
47#include "usbip_host_common.h"
48#include "usbip_device_driver.h"
44#include "usbip_common.h" 49#include "usbip_common.h"
45#include "usbip_network.h" 50#include "usbip_network.h"
46#include "list.h" 51#include "list.h"
@@ -64,6 +69,11 @@ static const char usbipd_help_string[] =
64 " -6, --ipv6\n" 69 " -6, --ipv6\n"
65 " Bind to IPv6. Default is both.\n" 70 " Bind to IPv6. Default is both.\n"
66 "\n" 71 "\n"
72 " -e, --device\n"
73 " Run in device mode.\n"
74 " Rather than drive an attached device, create\n"
75 " a virtual UDC to bind gadgets to.\n"
76 "\n"
67 " -D, --daemon\n" 77 " -D, --daemon\n"
68 " Run as a daemon process.\n" 78 " Run as a daemon process.\n"
69 "\n" 79 "\n"
@@ -83,6 +93,8 @@ static const char usbipd_help_string[] =
83 " -v, --version\n" 93 " -v, --version\n"
84 " Show version.\n"; 94 " Show version.\n";
85 95
96static struct usbip_host_driver *driver;
97
86static void usbipd_help(void) 98static void usbipd_help(void)
87{ 99{
88 printf("%s\n", usbipd_help_string); 100 printf("%s\n", usbipd_help_string);
@@ -107,7 +119,7 @@ static int recv_request_import(int sockfd)
107 } 119 }
108 PACK_OP_IMPORT_REQUEST(0, &req); 120 PACK_OP_IMPORT_REQUEST(0, &req);
109 121
110 list_for_each(i, &host_driver->edev_list) { 122 list_for_each(i, &driver->edev_list) {
111 edev = list_entry(i, struct usbip_exported_device, node); 123 edev = list_entry(i, struct usbip_exported_device, node);
112 if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { 124 if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
113 info("found requested device: %s", req.busid); 125 info("found requested device: %s", req.busid);
@@ -121,7 +133,7 @@ static int recv_request_import(int sockfd)
121 usbip_net_set_nodelay(sockfd); 133 usbip_net_set_nodelay(sockfd);
122 134
123 /* export device needs a TCP/IP socket descriptor */ 135 /* export device needs a TCP/IP socket descriptor */
124 rc = usbip_host_export_device(edev, sockfd); 136 rc = usbip_export_device(edev, sockfd);
125 if (rc < 0) 137 if (rc < 0)
126 error = 1; 138 error = 1;
127 } else { 139 } else {
@@ -166,7 +178,7 @@ static int send_reply_devlist(int connfd)
166 178
167 reply.ndev = 0; 179 reply.ndev = 0;
168 /* number of exported devices */ 180 /* number of exported devices */
169 list_for_each(j, &host_driver->edev_list) { 181 list_for_each(j, &driver->edev_list) {
170 reply.ndev += 1; 182 reply.ndev += 1;
171 } 183 }
172 info("exportable devices: %d", reply.ndev); 184 info("exportable devices: %d", reply.ndev);
@@ -184,7 +196,7 @@ static int send_reply_devlist(int connfd)
184 return -1; 196 return -1;
185 } 197 }
186 198
187 list_for_each(j, &host_driver->edev_list) { 199 list_for_each(j, &driver->edev_list) {
188 edev = list_entry(j, struct usbip_exported_device, node); 200 edev = list_entry(j, struct usbip_exported_device, node);
189 dump_usb_device(&edev->udev); 201 dump_usb_device(&edev->udev);
190 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); 202 memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
@@ -246,7 +258,7 @@ static int recv_pdu(int connfd)
246 return -1; 258 return -1;
247 } 259 }
248 260
249 ret = usbip_host_refresh_device_list(); 261 ret = usbip_refresh_device_list(driver);
250 if (ret < 0) { 262 if (ret < 0) {
251 dbg("could not refresh device list: %d", ret); 263 dbg("could not refresh device list: %d", ret);
252 return -1; 264 return -1;
@@ -491,16 +503,13 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
491 struct timespec timeout; 503 struct timespec timeout;
492 sigset_t sigmask; 504 sigset_t sigmask;
493 505
494 if (usbip_host_driver_open()) { 506 if (usbip_driver_open(driver))
495 err("please load " USBIP_CORE_MOD_NAME ".ko and "
496 USBIP_HOST_DRV_NAME ".ko!");
497 return -1; 507 return -1;
498 }
499 508
500 if (daemonize) { 509 if (daemonize) {
501 if (daemon(0, 0) < 0) { 510 if (daemon(0, 0) < 0) {
502 err("daemonizing failed: %s", strerror(errno)); 511 err("daemonizing failed: %s", strerror(errno));
503 usbip_host_driver_close(); 512 usbip_driver_close(driver);
504 return -1; 513 return -1;
505 } 514 }
506 umask(0); 515 umask(0);
@@ -525,7 +534,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
525 534
526 ai_head = do_getaddrinfo(NULL, family); 535 ai_head = do_getaddrinfo(NULL, family);
527 if (!ai_head) { 536 if (!ai_head) {
528 usbip_host_driver_close(); 537 usbip_driver_close(driver);
529 return -1; 538 return -1;
530 } 539 }
531 nsockfd = listen_all_addrinfo(ai_head, sockfdlist, 540 nsockfd = listen_all_addrinfo(ai_head, sockfdlist,
@@ -533,7 +542,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
533 freeaddrinfo(ai_head); 542 freeaddrinfo(ai_head);
534 if (nsockfd <= 0) { 543 if (nsockfd <= 0) {
535 err("failed to open a listening socket"); 544 err("failed to open a listening socket");
536 usbip_host_driver_close(); 545 usbip_driver_close(driver);
537 return -1; 546 return -1;
538 } 547 }
539 548
@@ -574,7 +583,7 @@ static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
574 583
575 info("shutting down " PROGNAME); 584 info("shutting down " PROGNAME);
576 free(fds); 585 free(fds);
577 usbip_host_driver_close(); 586 usbip_driver_close(driver);
578 587
579 return 0; 588 return 0;
580} 589}
@@ -587,6 +596,7 @@ int main(int argc, char *argv[])
587 { "daemon", no_argument, NULL, 'D' }, 596 { "daemon", no_argument, NULL, 'D' },
588 { "daemon", no_argument, NULL, 'D' }, 597 { "daemon", no_argument, NULL, 'D' },
589 { "debug", no_argument, NULL, 'd' }, 598 { "debug", no_argument, NULL, 'd' },
599 { "device", no_argument, NULL, 'e' },
590 { "pid", optional_argument, NULL, 'P' }, 600 { "pid", optional_argument, NULL, 'P' },
591 { "tcp-port", required_argument, NULL, 't' }, 601 { "tcp-port", required_argument, NULL, 't' },
592 { "help", no_argument, NULL, 'h' }, 602 { "help", no_argument, NULL, 'h' },
@@ -613,8 +623,9 @@ int main(int argc, char *argv[])
613 err("not running as root?"); 623 err("not running as root?");
614 624
615 cmd = cmd_standalone_mode; 625 cmd = cmd_standalone_mode;
626 driver = &host_driver;
616 for (;;) { 627 for (;;) {
617 opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL); 628 opt = getopt_long(argc, argv, "46DdeP::t:hv", longopts, NULL);
618 629
619 if (opt == -1) 630 if (opt == -1)
620 break; 631 break;
@@ -644,6 +655,9 @@ int main(int argc, char *argv[])
644 case 'v': 655 case 'v':
645 cmd = cmd_version; 656 cmd = cmd_version;
646 break; 657 break;
658 case 'e':
659 driver = &device_driver;
660 break;
647 case '?': 661 case '?':
648 usbipd_help(); 662 usbipd_help();
649 default: 663 default:
diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile
index feaa64ac4630..6ba745529833 100644
--- a/tools/virtio/ringtest/Makefile
+++ b/tools/virtio/ringtest/Makefile
@@ -1,6 +1,6 @@
1all: 1all:
2 2
3all: ring virtio_ring_0_9 virtio_ring_poll 3all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder
4 4
5CFLAGS += -Wall 5CFLAGS += -Wall
6CFLAGS += -pthread -O2 -ggdb 6CFLAGS += -pthread -O2 -ggdb
@@ -10,13 +10,16 @@ main.o: main.c main.h
10ring.o: ring.c main.h 10ring.o: ring.c main.h
11virtio_ring_0_9.o: virtio_ring_0_9.c main.h 11virtio_ring_0_9.o: virtio_ring_0_9.c main.h
12virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h 12virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h
13virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h
13ring: ring.o main.o 14ring: ring.o main.o
14virtio_ring_0_9: virtio_ring_0_9.o main.o 15virtio_ring_0_9: virtio_ring_0_9.o main.o
15virtio_ring_poll: virtio_ring_poll.o main.o 16virtio_ring_poll: virtio_ring_poll.o main.o
17virtio_ring_inorder: virtio_ring_inorder.o main.o
16clean: 18clean:
17 -rm main.o 19 -rm main.o
18 -rm ring.o ring 20 -rm ring.o ring
19 -rm virtio_ring_0_9.o virtio_ring_0_9 21 -rm virtio_ring_0_9.o virtio_ring_0_9
20 -rm virtio_ring_poll.o virtio_ring_poll 22 -rm virtio_ring_poll.o virtio_ring_poll
23 -rm virtio_ring_inorder.o virtio_ring_inorder
21 24
22.PHONY: all clean 25.PHONY: all clean
diff --git a/tools/virtio/ringtest/main.c b/tools/virtio/ringtest/main.c
index 3a5ff438bd62..147abb452a6c 100644
--- a/tools/virtio/ringtest/main.c
+++ b/tools/virtio/ringtest/main.c
@@ -115,7 +115,7 @@ static void run_guest(void)
115 do { 115 do {
116 if (started < bufs && 116 if (started < bufs &&
117 started - completed < max_outstanding) { 117 started - completed < max_outstanding) {
118 r = add_inbuf(0, NULL, "Hello, world!"); 118 r = add_inbuf(0, "Buffer\n", "Hello, world!");
119 if (__builtin_expect(r == 0, true)) { 119 if (__builtin_expect(r == 0, true)) {
120 ++started; 120 ++started;
121 if (!--tokick) { 121 if (!--tokick) {
diff --git a/tools/virtio/ringtest/virtio_ring_0_9.c b/tools/virtio/ringtest/virtio_ring_0_9.c
index 47c9a1a18d36..761866212aac 100644
--- a/tools/virtio/ringtest/virtio_ring_0_9.c
+++ b/tools/virtio/ringtest/virtio_ring_0_9.c
@@ -26,6 +26,14 @@ struct vring ring;
26 * high bits of ring id ^ 0x8000). 26 * high bits of ring id ^ 0x8000).
27 */ 27 */
28/* #ifdef RING_POLL */ 28/* #ifdef RING_POLL */
29/* enabling the below activates experimental in-order code
30 * (which skips ring updates and reads and writes len in descriptor).
31 */
32/* #ifdef INORDER */
33
34#if defined(RING_POLL) && defined(INORDER)
35#error "RING_POLL and INORDER are mutually exclusive"
36#endif
29 37
30/* how much padding is needed to avoid false cache sharing */ 38/* how much padding is needed to avoid false cache sharing */
31#define HOST_GUEST_PADDING 0x80 39#define HOST_GUEST_PADDING 0x80
@@ -35,7 +43,11 @@ struct guest {
35 unsigned short last_used_idx; 43 unsigned short last_used_idx;
36 unsigned short num_free; 44 unsigned short num_free;
37 unsigned short kicked_avail_idx; 45 unsigned short kicked_avail_idx;
46#ifndef INORDER
38 unsigned short free_head; 47 unsigned short free_head;
48#else
49 unsigned short reserved_free_head;
50#endif
39 unsigned char reserved[HOST_GUEST_PADDING - 10]; 51 unsigned char reserved[HOST_GUEST_PADDING - 10];
40} guest; 52} guest;
41 53
@@ -66,8 +78,10 @@ void alloc_ring(void)
66 guest.avail_idx = 0; 78 guest.avail_idx = 0;
67 guest.kicked_avail_idx = -1; 79 guest.kicked_avail_idx = -1;
68 guest.last_used_idx = 0; 80 guest.last_used_idx = 0;
81#ifndef INORDER
69 /* Put everything in free lists. */ 82 /* Put everything in free lists. */
70 guest.free_head = 0; 83 guest.free_head = 0;
84#endif
71 for (i = 0; i < ring_size - 1; i++) 85 for (i = 0; i < ring_size - 1; i++)
72 ring.desc[i].next = i + 1; 86 ring.desc[i].next = i + 1;
73 host.used_idx = 0; 87 host.used_idx = 0;
@@ -84,13 +98,20 @@ void alloc_ring(void)
84/* guest side */ 98/* guest side */
85int add_inbuf(unsigned len, void *buf, void *datap) 99int add_inbuf(unsigned len, void *buf, void *datap)
86{ 100{
87 unsigned head, avail; 101 unsigned head;
102#ifndef INORDER
103 unsigned avail;
104#endif
88 struct vring_desc *desc; 105 struct vring_desc *desc;
89 106
90 if (!guest.num_free) 107 if (!guest.num_free)
91 return -1; 108 return -1;
92 109
110#ifdef INORDER
111 head = (ring_size - 1) & (guest.avail_idx++);
112#else
93 head = guest.free_head; 113 head = guest.free_head;
114#endif
94 guest.num_free--; 115 guest.num_free--;
95 116
96 desc = ring.desc; 117 desc = ring.desc;
@@ -102,7 +123,9 @@ int add_inbuf(unsigned len, void *buf, void *datap)
102 * descriptors. 123 * descriptors.
103 */ 124 */
104 desc[head].flags &= ~VRING_DESC_F_NEXT; 125 desc[head].flags &= ~VRING_DESC_F_NEXT;
126#ifndef INORDER
105 guest.free_head = desc[head].next; 127 guest.free_head = desc[head].next;
128#endif
106 129
107 data[head].data = datap; 130 data[head].data = datap;
108 131
@@ -113,8 +136,12 @@ int add_inbuf(unsigned len, void *buf, void *datap)
113 ring.avail->ring[avail & (ring_size - 1)] = 136 ring.avail->ring[avail & (ring_size - 1)] =
114 (head | (avail & ~(ring_size - 1))) ^ 0x8000; 137 (head | (avail & ~(ring_size - 1))) ^ 0x8000;
115#else 138#else
139#ifndef INORDER
140 /* Barrier A (for pairing) */
141 smp_release();
116 avail = (ring_size - 1) & (guest.avail_idx++); 142 avail = (ring_size - 1) & (guest.avail_idx++);
117 ring.avail->ring[avail] = head; 143 ring.avail->ring[avail] = head;
144#endif
118 /* Barrier A (for pairing) */ 145 /* Barrier A (for pairing) */
119 smp_release(); 146 smp_release();
120#endif 147#endif
@@ -141,15 +168,27 @@ void *get_buf(unsigned *lenp, void **bufp)
141 return NULL; 168 return NULL;
142 /* Barrier B (for pairing) */ 169 /* Barrier B (for pairing) */
143 smp_acquire(); 170 smp_acquire();
171#ifdef INORDER
172 head = (ring_size - 1) & guest.last_used_idx;
173 index = head;
174#else
144 head = (ring_size - 1) & guest.last_used_idx; 175 head = (ring_size - 1) & guest.last_used_idx;
145 index = ring.used->ring[head].id; 176 index = ring.used->ring[head].id;
146#endif 177#endif
178
179#endif
180#ifdef INORDER
181 *lenp = ring.desc[index].len;
182#else
147 *lenp = ring.used->ring[head].len; 183 *lenp = ring.used->ring[head].len;
184#endif
148 datap = data[index].data; 185 datap = data[index].data;
149 *bufp = (void*)(unsigned long)ring.desc[index].addr; 186 *bufp = (void*)(unsigned long)ring.desc[index].addr;
150 data[index].data = NULL; 187 data[index].data = NULL;
188#ifndef INORDER
151 ring.desc[index].next = guest.free_head; 189 ring.desc[index].next = guest.free_head;
152 guest.free_head = index; 190 guest.free_head = index;
191#endif
153 guest.num_free++; 192 guest.num_free++;
154 guest.last_used_idx++; 193 guest.last_used_idx++;
155 return datap; 194 return datap;
@@ -283,16 +322,24 @@ bool use_buf(unsigned *lenp, void **bufp)
283 smp_acquire(); 322 smp_acquire();
284 323
285 used_idx &= ring_size - 1; 324 used_idx &= ring_size - 1;
325#ifdef INORDER
326 head = used_idx;
327#else
286 head = ring.avail->ring[used_idx]; 328 head = ring.avail->ring[used_idx];
329#endif
287 desc = &ring.desc[head]; 330 desc = &ring.desc[head];
288#endif 331#endif
289 332
290 *lenp = desc->len; 333 *lenp = desc->len;
291 *bufp = (void *)(unsigned long)desc->addr; 334 *bufp = (void *)(unsigned long)desc->addr;
292 335
336#ifdef INORDER
337 desc->len = desc->len - 1;
338#else
293 /* now update used ring */ 339 /* now update used ring */
294 ring.used->ring[used_idx].id = head; 340 ring.used->ring[used_idx].id = head;
295 ring.used->ring[used_idx].len = desc->len - 1; 341 ring.used->ring[used_idx].len = desc->len - 1;
342#endif
296 /* Barrier B (for pairing) */ 343 /* Barrier B (for pairing) */
297 smp_release(); 344 smp_release();
298 host.used_idx++; 345 host.used_idx++;
diff --git a/tools/virtio/ringtest/virtio_ring_inorder.c b/tools/virtio/ringtest/virtio_ring_inorder.c
new file mode 100644
index 000000000000..2438ca58a2ad
--- /dev/null
+++ b/tools/virtio/ringtest/virtio_ring_inorder.c
@@ -0,0 +1,2 @@
1#define INORDER 1
2#include "virtio_ring_0_9.c"