aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/arch/alpha/include/uapi/asm/mman.h47
-rw-r--r--tools/arch/arc/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/arm/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/arm64/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/frv/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/h8300/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/hexagon/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/ia64/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/m32r/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/microblaze/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/mips/include/uapi/asm/mman.h46
-rw-r--r--tools/arch/mn10300/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/parisc/include/uapi/asm/mman.h47
-rw-r--r--tools/arch/powerpc/include/uapi/asm/mman.h15
-rw-r--r--tools/arch/s390/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/score/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/sh/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/sparc/include/uapi/asm/mman.h15
-rw-r--r--tools/arch/tile/include/uapi/asm/mman.h15
-rw-r--r--tools/arch/x86/include/uapi/asm/mman.h5
-rw-r--r--tools/arch/xtensa/include/uapi/asm/mman.h47
-rw-r--r--tools/hv/hv_kvp_daemon.c2
-rw-r--r--tools/hv/hv_vss_daemon.c3
-rw-r--r--tools/iio/iio_generic_buffer.c4
-rw-r--r--tools/iio/iio_utils.c11
-rw-r--r--tools/iio/lsiio.c3
-rw-r--r--tools/include/linux/coresight-pmu.h39
-rw-r--r--tools/include/linux/time64.h12
-rw-r--r--tools/include/uapi/asm-generic/mman-common.h75
-rw-r--r--tools/include/uapi/asm-generic/mman.h22
-rw-r--r--tools/include/uapi/linux/mman.h13
-rw-r--r--tools/lguest/lguest.c6
-rw-r--r--tools/lib/api/fs/fs.c15
-rw-r--r--tools/lib/api/fs/fs.h1
-rw-r--r--tools/objtool/builtin-check.c1
-rw-r--r--tools/perf/Documentation/perf-config.txt12
-rw-r--r--tools/perf/Documentation/perf-probe.txt14
-rw-r--r--tools/perf/Documentation/perf-record.txt73
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt6
-rw-r--r--tools/perf/Documentation/perfconfig.example9
-rw-r--r--tools/perf/MANIFEST6
-rw-r--r--tools/perf/Makefile.config11
-rw-r--r--tools/perf/Makefile.perf14
-rw-r--r--tools/perf/arch/arm/include/dwarf-regs-table.h9
-rw-r--r--tools/perf/arch/arm/util/Build2
-rw-r--r--tools/perf/arch/arm/util/auxtrace.c54
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c617
-rw-r--r--tools/perf/arch/arm/util/cs-etm.h26
-rw-r--r--tools/perf/arch/arm/util/pmu.c36
-rw-r--r--tools/perf/arch/arm64/include/dwarf-regs-table.h13
-rw-r--r--tools/perf/arch/arm64/util/Build4
-rw-r--r--tools/perf/arch/powerpc/Build1
-rw-r--r--tools/perf/arch/powerpc/include/arch-tests.h13
-rw-r--r--tools/perf/arch/powerpc/include/dwarf-regs-table.h27
-rw-r--r--tools/perf/arch/powerpc/include/perf_regs.h2
-rw-r--r--tools/perf/arch/powerpc/tests/Build4
-rw-r--r--tools/perf/arch/powerpc/tests/arch-tests.c15
-rw-r--r--tools/perf/arch/powerpc/tests/dwarf-unwind.c62
-rw-r--r--tools/perf/arch/powerpc/tests/regs_load.S94
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c2
-rw-r--r--tools/perf/arch/s390/include/dwarf-regs-table.h8
-rw-r--r--tools/perf/arch/sh/include/dwarf-regs-table.h25
-rw-r--r--tools/perf/arch/sparc/include/dwarf-regs-table.h18
-rw-r--r--tools/perf/arch/x86/include/dwarf-regs-table.h14
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c57
-rw-r--r--tools/perf/arch/xtensa/include/dwarf-regs-table.h8
-rw-r--r--tools/perf/bench/futex-requeue.c5
-rw-r--r--tools/perf/bench/futex-wake-parallel.c5
-rw-r--r--tools/perf/bench/futex-wake.c5
-rw-r--r--tools/perf/bench/mem-functions.c3
-rw-r--r--tools/perf/bench/numa.c53
-rw-r--r--tools/perf/bench/sched-messaging.c5
-rw-r--r--tools/perf/bench/sched-pipe.c9
-rw-r--r--tools/perf/builtin-annotate.c111
-rw-r--r--tools/perf/builtin-diff.c4
-rw-r--r--tools/perf/builtin-inject.c2
-rw-r--r--tools/perf/builtin-kmem.c10
-rw-r--r--tools/perf/builtin-kvm.c11
-rw-r--r--tools/perf/builtin-probe.c35
-rw-r--r--tools/perf/builtin-record.c50
-rw-r--r--tools/perf/builtin-report.c11
-rw-r--r--tools/perf/builtin-sched.c37
-rw-r--r--tools/perf/builtin-script.c11
-rw-r--r--tools/perf/builtin-stat.c28
-rw-r--r--tools/perf/builtin-timechart.c13
-rw-r--r--tools/perf/builtin-top.c52
-rw-r--r--tools/perf/builtin-trace.c11
-rw-r--r--tools/perf/perf-sys.h1
-rw-r--r--tools/perf/perf.h7
-rw-r--r--tools/perf/tests/Build2
-rw-r--r--tools/perf/tests/backward-ring-buffer.c2
-rw-r--r--tools/perf/tests/bpf.c2
-rw-r--r--tools/perf/tests/code-reading.c4
-rw-r--r--tools/perf/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c61
-rw-r--r--tools/perf/trace/beauty/mmap.c72
-rw-r--r--tools/perf/ui/browsers/annotate.c2
-rw-r--r--tools/perf/ui/browsers/hists.c59
-rw-r--r--tools/perf/ui/browsers/map.c4
-rw-r--r--tools/perf/ui/gtk/hists.c2
-rw-r--r--tools/perf/ui/hist.c21
-rw-r--r--tools/perf/ui/stdio/hist.c82
-rw-r--r--tools/perf/util/Build3
-rw-r--r--tools/perf/util/annotate.c226
-rw-r--r--tools/perf/util/annotate.h4
-rw-r--r--tools/perf/util/auxtrace.c738
-rw-r--r--tools/perf/util/auxtrace.h55
-rw-r--r--tools/perf/util/block-range.c328
-rw-r--r--tools/perf/util/block-range.h71
-rw-r--r--tools/perf/util/bpf-loader.c2
-rw-r--r--tools/perf/util/build-id.c4
-rw-r--r--tools/perf/util/cs-etm.h74
-rw-r--r--tools/perf/util/data-convert-bt.c2
-rw-r--r--tools/perf/util/debug.c10
-rw-r--r--tools/perf/util/drv_configs.c77
-rw-r--r--tools/perf/util/drv_configs.h26
-rw-r--r--tools/perf/util/dso.c3
-rw-r--r--tools/perf/util/dwarf-aux.c207
-rw-r--r--tools/perf/util/dwarf-aux.h11
-rw-r--r--tools/perf/util/dwarf-regs.c59
-rw-r--r--tools/perf/util/event.c21
-rw-r--r--tools/perf/util/evlist.c8
-rw-r--r--tools/perf/util/evsel.c18
-rw-r--r--tools/perf/util/evsel.h7
-rw-r--r--tools/perf/util/evsel_fprintf.c7
-rw-r--r--tools/perf/util/header.c3
-rw-r--r--tools/perf/util/hist.c154
-rw-r--r--tools/perf/util/hist.h9
-rw-r--r--tools/perf/util/include/dwarf-regs.h6
-rw-r--r--tools/perf/util/intel-bts.c2
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c30
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h1
-rw-r--r--tools/perf/util/intel-pt.c176
-rw-r--r--tools/perf/util/intel-pt.h4
-rw-r--r--tools/perf/util/lzma.c15
-rw-r--r--tools/perf/util/machine.c38
-rw-r--r--tools/perf/util/machine.h34
-rw-r--r--tools/perf/util/map.c45
-rw-r--r--tools/perf/util/map.h32
-rw-r--r--tools/perf/util/parse-events.c48
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/parse-events.l22
-rw-r--r--tools/perf/util/parse-events.y11
-rw-r--r--tools/perf/util/pmu.c15
-rw-r--r--tools/perf/util/pmu.h2
-rw-r--r--tools/perf/util/probe-event.c126
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/probe-file.c64
-rw-r--r--tools/perf/util/probe-file.h10
-rw-r--r--tools/perf/util/probe-finder.c96
-rw-r--r--tools/perf/util/probe-finder.h1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c5
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c5
-rw-r--r--tools/perf/util/sort.c25
-rw-r--r--tools/perf/util/sort.h14
-rw-r--r--tools/perf/util/svghelper.c11
-rw-r--r--tools/perf/util/symbol-elf.c118
-rw-r--r--tools/perf/util/symbol-minimal.c4
-rw-r--r--tools/perf/util/symbol.c179
-rw-r--r--tools/perf/util/symbol.h26
-rw-r--r--tools/perf/util/util.c1
-rw-r--r--tools/perf/util/util.h4
-rw-r--r--tools/power/acpi/common/cmfsize.c13
-rw-r--r--tools/power/acpi/common/getopt.c4
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslibcfs.c217
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c3
-rw-r--r--tools/power/acpi/tools/acpidump/Makefile3
-rw-r--r--tools/power/acpi/tools/acpidump/acpidump.h12
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c75
-rw-r--r--tools/power/acpi/tools/acpidump/apfiles.c56
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c37
-rw-r--r--tools/spi/Makefile2
-rw-r--r--tools/spi/spidev_test.c3
-rw-r--r--tools/testing/nvdimm/test/nfit.c3
-rw-r--r--tools/testing/radix-tree/Makefile2
-rw-r--r--tools/testing/radix-tree/linux/cpu.h13
-rw-r--r--tools/testing/radix-tree/multiorder.c16
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/nsfs/Makefile12
-rw-r--r--tools/testing/selftests/nsfs/owner.c91
-rw-r--r--tools/testing/selftests/nsfs/pidns.c78
-rw-r--r--tools/testing/selftests/powerpc/Makefile1
-rw-r--r--tools/testing/selftests/powerpc/fpu_asm.h80
-rw-r--r--tools/testing/selftests/powerpc/gpr_asm.h96
-rw-r--r--tools/testing/selftests/powerpc/harness.c9
-rw-r--r--tools/testing/selftests/powerpc/math/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/math/fpu_asm.S73
-rw-r--r--tools/testing/selftests/powerpc/math/vmx_asm.S85
-rw-r--r--tools/testing/selftests/powerpc/math/vsx_asm.S61
-rw-r--r--tools/testing/selftests/powerpc/math/vsx_preempt.c147
-rw-r--r--tools/testing/selftests/powerpc/signal/Makefile13
-rw-r--r--tools/testing/selftests/powerpc/signal/signal.S50
-rw-r--r--tools/testing/selftests/powerpc/signal/signal.c111
-rw-r--r--tools/testing/selftests/powerpc/signal/signal_tm.c110
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile8
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c92
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c90
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c110
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c125
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal.S114
-rw-r--r--tools/testing/selftests/powerpc/tm/tm.h27
-rw-r--r--tools/testing/selftests/powerpc/utils.h9
-rw-r--r--tools/testing/selftests/powerpc/vmx_asm.h96
-rw-r--r--tools/testing/selftests/powerpc/vsx_asm.h71
-rw-r--r--tools/testing/selftests/x86/ptrace_syscall.c4
-rw-r--r--tools/testing/selftests/x86/sigreturn.c16
206 files changed, 6787 insertions, 1330 deletions
diff --git a/tools/arch/alpha/include/uapi/asm/mman.h b/tools/arch/alpha/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..e38b64c82b97
--- /dev/null
+++ b/tools/arch/alpha/include/uapi/asm/mman.h
@@ -0,0 +1,47 @@
1#ifndef TOOLS_ARCH_ALPHA_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ALPHA_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 17
4#define MADV_DOFORK 11
5#define MADV_DONTDUMP 16
6#define MADV_DONTFORK 10
7#define MADV_DONTNEED 6
8#define MADV_FREE 8
9#define MADV_HUGEPAGE 14
10#define MADV_MERGEABLE 12
11#define MADV_NOHUGEPAGE 15
12#define MADV_NORMAL 0
13#define MADV_RANDOM 1
14#define MADV_REMOVE 9
15#define MADV_SEQUENTIAL 2
16#define MADV_UNMERGEABLE 13
17#define MADV_WILLNEED 3
18#define MAP_ANONYMOUS 0x10
19#define MAP_DENYWRITE 0x02000
20#define MAP_EXECUTABLE 0x04000
21#define MAP_FILE 0
22#define MAP_FIXED 0x100
23#define MAP_GROWSDOWN 0x01000
24#define MAP_HUGETLB 0x100000
25#define MAP_LOCKED 0x08000
26#define MAP_NONBLOCK 0x40000
27#define MAP_NORESERVE 0x10000
28#define MAP_POPULATE 0x20000
29#define MAP_PRIVATE 0x02
30#define MAP_SHARED 0x01
31#define MAP_STACK 0x80000
32#define PROT_EXEC 0x4
33#define PROT_GROWSDOWN 0x01000000
34#define PROT_GROWSUP 0x02000000
35#define PROT_NONE 0x0
36#define PROT_READ 0x1
37#define PROT_SEM 0x8
38#define PROT_WRITE 0x2
39/* MADV_HWPOISON is undefined on alpha, fix it for perf */
40#define MADV_HWPOISON 100
41/* MADV_SOFT_OFFLINE is undefined on alpha, fix it for perf */
42#define MADV_SOFT_OFFLINE 101
43/* MAP_32BIT is undefined on alpha, fix it for perf */
44#define MAP_32BIT 0
45/* MAP_UNINITIALIZED is undefined on alpha, fix it for perf */
46#define MAP_UNINITIALIZED 0
47#endif
diff --git a/tools/arch/arc/include/uapi/asm/mman.h b/tools/arch/arc/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..aa3acd2aa9af
--- /dev/null
+++ b/tools/arch/arc/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_ARC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ARC_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on arc, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/arm/include/uapi/asm/mman.h b/tools/arch/arm/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..478f699f56fd
--- /dev/null
+++ b/tools/arch/arm/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_ARM_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ARM_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on arm, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/arm64/include/uapi/asm/mman.h b/tools/arch/arm64/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..70fd3113710a
--- /dev/null
+++ b/tools/arch/arm64/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_ARM64_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ARM64_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on arm64, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/frv/include/uapi/asm/mman.h b/tools/arch/frv/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..5be78ac12464
--- /dev/null
+++ b/tools/arch/frv/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on frv, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/h8300/include/uapi/asm/mman.h b/tools/arch/h8300/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..9d9ac54d3c5a
--- /dev/null
+++ b/tools/arch/h8300/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on h8300, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/hexagon/include/uapi/asm/mman.h b/tools/arch/hexagon/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..102f3fae6085
--- /dev/null
+++ b/tools/arch/hexagon/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_HEXAGON_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_HEXAGON_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on hexagon, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/ia64/include/uapi/asm/mman.h b/tools/arch/ia64/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..1d6e5ac6442d
--- /dev/null
+++ b/tools/arch/ia64/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_IA64_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_IA64_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on ia64, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/m32r/include/uapi/asm/mman.h b/tools/arch/m32r/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..1c29635bb73b
--- /dev/null
+++ b/tools/arch/m32r/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on m32r, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/microblaze/include/uapi/asm/mman.h b/tools/arch/microblaze/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..005cd50b50e1
--- /dev/null
+++ b/tools/arch/microblaze/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_MICROBLAZE_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_MICROBLAZE_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on microblaze, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/mips/include/uapi/asm/mman.h b/tools/arch/mips/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..c02052965d50
--- /dev/null
+++ b/tools/arch/mips/include/uapi/asm/mman.h
@@ -0,0 +1,46 @@
1#ifndef TOOLS_ARCH_MIPS_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_MIPS_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 17
4#define MADV_DOFORK 11
5#define MADV_DONTDUMP 16
6#define MADV_DONTFORK 10
7#define MADV_DONTNEED 4
8#define MADV_FREE 8
9#define MADV_HUGEPAGE 14
10#define MADV_HWPOISON 100
11#define MADV_MERGEABLE 12
12#define MADV_NOHUGEPAGE 15
13#define MADV_NORMAL 0
14#define MADV_RANDOM 1
15#define MADV_REMOVE 9
16#define MADV_SEQUENTIAL 2
17#define MADV_UNMERGEABLE 13
18#define MADV_WILLNEED 3
19#define MAP_ANONYMOUS 0x0800
20#define MAP_DENYWRITE 0x2000
21#define MAP_EXECUTABLE 0x4000
22#define MAP_FILE 0
23#define MAP_FIXED 0x010
24#define MAP_GROWSDOWN 0x1000
25#define MAP_HUGETLB 0x80000
26#define MAP_LOCKED 0x8000
27#define MAP_NONBLOCK 0x20000
28#define MAP_NORESERVE 0x0400
29#define MAP_POPULATE 0x10000
30#define MAP_PRIVATE 0x002
31#define MAP_SHARED 0x001
32#define MAP_STACK 0x40000
33#define PROT_EXEC 0x04
34#define PROT_GROWSDOWN 0x01000000
35#define PROT_GROWSUP 0x02000000
36#define PROT_NONE 0x00
37#define PROT_READ 0x01
38#define PROT_SEM 0x10
39#define PROT_WRITE 0x02
40/* MADV_SOFT_OFFLINE is undefined on mips, fix it for perf */
41#define MADV_SOFT_OFFLINE 101
42/* MAP_32BIT is undefined on mips, fix it for perf */
43#define MAP_32BIT 0
44/* MAP_UNINITIALIZED is undefined on mips, fix it for perf */
45#define MAP_UNINITIALIZED 0
46#endif
diff --git a/tools/arch/mn10300/include/uapi/asm/mman.h b/tools/arch/mn10300/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..c1ea36d83acc
--- /dev/null
+++ b/tools/arch/mn10300/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on mn10300, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/parisc/include/uapi/asm/mman.h b/tools/arch/parisc/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..03d8d5b7ae7f
--- /dev/null
+++ b/tools/arch/parisc/include/uapi/asm/mman.h
@@ -0,0 +1,47 @@
1#ifndef TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 70
4#define MADV_DOFORK 11
5#define MADV_DONTDUMP 69
6#define MADV_DONTFORK 10
7#define MADV_DONTNEED 4
8#define MADV_FREE 8
9#define MADV_HUGEPAGE 67
10#define MADV_MERGEABLE 65
11#define MADV_NOHUGEPAGE 68
12#define MADV_NORMAL 0
13#define MADV_RANDOM 1
14#define MADV_REMOVE 9
15#define MADV_SEQUENTIAL 2
16#define MADV_UNMERGEABLE 66
17#define MADV_WILLNEED 3
18#define MAP_ANONYMOUS 0x10
19#define MAP_DENYWRITE 0x0800
20#define MAP_EXECUTABLE 0x1000
21#define MAP_FILE 0
22#define MAP_FIXED 0x04
23#define MAP_GROWSDOWN 0x8000
24#define MAP_HUGETLB 0x80000
25#define MAP_LOCKED 0x2000
26#define MAP_NONBLOCK 0x20000
27#define MAP_NORESERVE 0x4000
28#define MAP_POPULATE 0x10000
29#define MAP_PRIVATE 0x02
30#define MAP_SHARED 0x01
31#define MAP_STACK 0x40000
32#define PROT_EXEC 0x4
33#define PROT_GROWSDOWN 0x01000000
34#define PROT_GROWSUP 0x02000000
35#define PROT_NONE 0x0
36#define PROT_READ 0x1
37#define PROT_SEM 0x8
38#define PROT_WRITE 0x2
39/* MADV_HWPOISON is undefined on parisc, fix it for perf */
40#define MADV_HWPOISON 100
41/* MADV_SOFT_OFFLINE is undefined on parisc, fix it for perf */
42#define MADV_SOFT_OFFLINE 101
43/* MAP_32BIT is undefined on parisc, fix it for perf */
44#define MAP_32BIT 0
45/* MAP_UNINITIALIZED is undefined on parisc, fix it for perf */
46#define MAP_UNINITIALIZED 0
47#endif
diff --git a/tools/arch/powerpc/include/uapi/asm/mman.h b/tools/arch/powerpc/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..761db43172fe
--- /dev/null
+++ b/tools/arch/powerpc/include/uapi/asm/mman.h
@@ -0,0 +1,15 @@
1#ifndef TOOLS_ARCH_POWERPC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_POWERPC_UAPI_ASM_MMAN_FIX_H
3#define MAP_DENYWRITE 0x0800
4#define MAP_EXECUTABLE 0x1000
5#define MAP_GROWSDOWN 0x0100
6#define MAP_HUGETLB 0x40000
7#define MAP_LOCKED 0x80
8#define MAP_NONBLOCK 0x10000
9#define MAP_NORESERVE 0x40
10#define MAP_POPULATE 0x8000
11#define MAP_STACK 0x20000
12#include <uapi/asm-generic/mman-common.h>
13/* MAP_32BIT is undefined on powerpc, fix it for perf */
14#define MAP_32BIT 0
15#endif
diff --git a/tools/arch/s390/include/uapi/asm/mman.h b/tools/arch/s390/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..b03dea9e1f56
--- /dev/null
+++ b/tools/arch/s390/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_S390_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_S390_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on s390, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/score/include/uapi/asm/mman.h b/tools/arch/score/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..2f8fb89944fd
--- /dev/null
+++ b/tools/arch/score/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on score, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/sh/include/uapi/asm/mman.h b/tools/arch/sh/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..26504f6f060e
--- /dev/null
+++ b/tools/arch/sh/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_SH_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_SH_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on sh, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/sparc/include/uapi/asm/mman.h b/tools/arch/sparc/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..8640525de991
--- /dev/null
+++ b/tools/arch/sparc/include/uapi/asm/mman.h
@@ -0,0 +1,15 @@
1#ifndef TOOLS_ARCH_SPARC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_SPARC_UAPI_ASM_MMAN_FIX_H
3#define MAP_DENYWRITE 0x0800
4#define MAP_EXECUTABLE 0x1000
5#define MAP_GROWSDOWN 0x0200
6#define MAP_HUGETLB 0x40000
7#define MAP_LOCKED 0x100
8#define MAP_NONBLOCK 0x10000
9#define MAP_NORESERVE 0x40
10#define MAP_POPULATE 0x8000
11#define MAP_STACK 0x20000
12#include <uapi/asm-generic/mman-common.h>
13/* MAP_32BIT is undefined on sparc, fix it for perf */
14#define MAP_32BIT 0
15#endif
diff --git a/tools/arch/tile/include/uapi/asm/mman.h b/tools/arch/tile/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..7116c4b928b3
--- /dev/null
+++ b/tools/arch/tile/include/uapi/asm/mman.h
@@ -0,0 +1,15 @@
1#ifndef TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H
3#define MAP_DENYWRITE 0x0800
4#define MAP_EXECUTABLE 0x1000
5#define MAP_GROWSDOWN 0x0100
6#define MAP_HUGETLB 0x4000
7#define MAP_LOCKED 0x0200
8#define MAP_NONBLOCK 0x0080
9#define MAP_NORESERVE 0x0400
10#define MAP_POPULATE 0x0040
11#define MAP_STACK MAP_GROWSDOWN
12#include <uapi/asm-generic/mman-common.h>
13/* MAP_32BIT is undefined on tile, fix it for perf */
14#define MAP_32BIT 0
15#endif
diff --git a/tools/arch/x86/include/uapi/asm/mman.h b/tools/arch/x86/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..b73c1af8b1dd
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/mman.h
@@ -0,0 +1,5 @@
1#ifndef TOOLS_ARCH_X86_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_X86_UAPI_ASM_MMAN_FIX_H
3#define MAP_32BIT 0x40
4#include <uapi/asm-generic/mman.h>
5#endif
diff --git a/tools/arch/xtensa/include/uapi/asm/mman.h b/tools/arch/xtensa/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..4453195c450c
--- /dev/null
+++ b/tools/arch/xtensa/include/uapi/asm/mman.h
@@ -0,0 +1,47 @@
1#ifndef TOOLS_ARCH_XTENSA_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_XTENSA_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 17
4#define MADV_DOFORK 11
5#define MADV_DONTDUMP 16
6#define MADV_DONTFORK 10
7#define MADV_DONTNEED 4
8#define MADV_FREE 8
9#define MADV_HUGEPAGE 14
10#define MADV_MERGEABLE 12
11#define MADV_NOHUGEPAGE 15
12#define MADV_NORMAL 0
13#define MADV_RANDOM 1
14#define MADV_REMOVE 9
15#define MADV_SEQUENTIAL 2
16#define MADV_UNMERGEABLE 13
17#define MADV_WILLNEED 3
18#define MAP_ANONYMOUS 0x0800
19#define MAP_DENYWRITE 0x2000
20#define MAP_EXECUTABLE 0x4000
21#define MAP_FILE 0
22#define MAP_FIXED 0x010
23#define MAP_GROWSDOWN 0x1000
24#define MAP_HUGETLB 0x80000
25#define MAP_LOCKED 0x8000
26#define MAP_NONBLOCK 0x20000
27#define MAP_NORESERVE 0x0400
28#define MAP_POPULATE 0x10000
29#define MAP_PRIVATE 0x002
30#define MAP_SHARED 0x001
31#define MAP_STACK 0x40000
32#define PROT_EXEC 0x4
33#define PROT_GROWSDOWN 0x01000000
34#define PROT_GROWSUP 0x02000000
35#define PROT_NONE 0x0
36#define PROT_READ 0x1
37#define PROT_SEM 0x10
38#define PROT_WRITE 0x2
39/* MADV_HWPOISON is undefined on xtensa, fix it for perf */
40#define MADV_HWPOISON 100
41/* MADV_SOFT_OFFLINE is undefined on xtensa, fix it for perf */
42#define MADV_SOFT_OFFLINE 101
43/* MAP_32BIT is undefined on xtensa, fix it for perf */
44#define MAP_32BIT 0
45/* MAP_UNINITIALIZED is undefined on xtensa, fix it for perf */
46#define MAP_UNINITIALIZED 0
47#endif
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 0d9f48ec42bb..bc7adb84e679 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1433,7 +1433,7 @@ int main(int argc, char *argv[])
1433 openlog("KVP", 0, LOG_USER); 1433 openlog("KVP", 0, LOG_USER);
1434 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); 1434 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
1435 1435
1436 kvp_fd = open("/dev/vmbus/hv_kvp", O_RDWR); 1436 kvp_fd = open("/dev/vmbus/hv_kvp", O_RDWR | O_CLOEXEC);
1437 1437
1438 if (kvp_fd < 0) { 1438 if (kvp_fd < 0) {
1439 syslog(LOG_ERR, "open /dev/vmbus/hv_kvp failed; error: %d %s", 1439 syslog(LOG_ERR, "open /dev/vmbus/hv_kvp failed; error: %d %s",
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 5d51d6ff08e6..e0829809c897 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -250,6 +250,9 @@ int main(int argc, char *argv[])
250 syslog(LOG_ERR, "/etc/fstab and /proc/mounts"); 250 syslog(LOG_ERR, "/etc/fstab and /proc/mounts");
251 } 251 }
252 break; 252 break;
253 case VSS_OP_HOT_BACKUP:
254 syslog(LOG_INFO, "VSS: op=CHECK HOT BACKUP\n");
255 break;
253 default: 256 default:
254 syslog(LOG_ERR, "Illegal op:%d\n", op); 257 syslog(LOG_ERR, "Illegal op:%d\n", op);
255 } 258 }
diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
index 0e8a1f7a292d..f39c0e9c0d5c 100644
--- a/tools/iio/iio_generic_buffer.c
+++ b/tools/iio/iio_generic_buffer.c
@@ -348,7 +348,7 @@ int main(int argc, char **argv)
348 int notrigger = 0; 348 int notrigger = 0;
349 char *dummy; 349 char *dummy;
350 350
351 struct iio_channel_info *channels; 351 struct iio_channel_info *channels = NULL;
352 352
353 register_cleanup(); 353 register_cleanup();
354 354
@@ -456,7 +456,7 @@ int main(int argc, char **argv)
456 456
457 if (notrigger) { 457 if (notrigger) {
458 printf("trigger-less mode selected\n"); 458 printf("trigger-less mode selected\n");
459 } if (trig_num >= 0) { 459 } else if (trig_num >= 0) {
460 char *trig_dev_name; 460 char *trig_dev_name;
461 ret = asprintf(&trig_dev_name, "%strigger%d", iio_dir, trig_num); 461 ret = asprintf(&trig_dev_name, "%strigger%d", iio_dir, trig_num);
462 if (ret < 0) { 462 if (ret < 0) {
diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
index 5eb6793f3972..7a6d61c6c012 100644
--- a/tools/iio/iio_utils.c
+++ b/tools/iio/iio_utils.c
@@ -121,10 +121,6 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
121 121
122 ret = -ENOENT; 122 ret = -ENOENT;
123 while (ent = readdir(dp), ent) 123 while (ent = readdir(dp), ent)
124 /*
125 * Do we allow devices to override a generic name with
126 * a specific one?
127 */
128 if ((strcmp(builtname, ent->d_name) == 0) || 124 if ((strcmp(builtname, ent->d_name) == 0) ||
129 (strcmp(builtname_generic, ent->d_name) == 0)) { 125 (strcmp(builtname_generic, ent->d_name) == 0)) {
130 ret = asprintf(&filename, 126 ret = asprintf(&filename,
@@ -178,6 +174,13 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
178 sysfsfp = 0; 174 sysfsfp = 0;
179 free(filename); 175 free(filename);
180 filename = 0; 176 filename = 0;
177
178 /*
179 * Avoid having a more generic entry overwriting
180 * the settings.
181 */
182 if (strcmp(builtname, ent->d_name) == 0)
183 break;
181 } 184 }
182 185
183error_close_sysfsfp: 186error_close_sysfsfp:
diff --git a/tools/iio/lsiio.c b/tools/iio/lsiio.c
index 3d650e668252..ab0f5cf16025 100644
--- a/tools/iio/lsiio.c
+++ b/tools/iio/lsiio.c
@@ -51,7 +51,8 @@ static int dump_channels(const char *dev_dir_name)
51 51
52 while (ent = readdir(dp), ent) 52 while (ent = readdir(dp), ent)
53 if (check_prefix(ent->d_name, "in_") && 53 if (check_prefix(ent->d_name, "in_") &&
54 check_postfix(ent->d_name, "_raw")) 54 (check_postfix(ent->d_name, "_raw") ||
55 check_postfix(ent->d_name, "_input")))
55 printf(" %-10s\n", ent->d_name); 56 printf(" %-10s\n", ent->d_name);
56 57
57 return (closedir(dp) == -1) ? -errno : 0; 58 return (closedir(dp) == -1) ? -errno : 0;
diff --git a/tools/include/linux/coresight-pmu.h b/tools/include/linux/coresight-pmu.h
new file mode 100644
index 000000000000..7d410260661b
--- /dev/null
+++ b/tools/include/linux/coresight-pmu.h
@@ -0,0 +1,39 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef _LINUX_CORESIGHT_PMU_H
19#define _LINUX_CORESIGHT_PMU_H
20
21#define CORESIGHT_ETM_PMU_NAME "cs_etm"
22#define CORESIGHT_ETM_PMU_SEED 0x10
23
24/* ETMv3.5/PTM's ETMCR config bit */
25#define ETM_OPT_CYCACC 12
26#define ETM_OPT_TS 28
27
28static inline int coresight_get_trace_id(int cpu)
29{
30 /*
31 * A trace ID of value 0 is invalid, so let's start at some
32 * random value that fits in 7 bits and go from there. Since
33 * the common convention is to have data trace IDs be I(N) + 1,
34 * set instruction trace IDs as a function of the CPU number.
35 */
36 return (CORESIGHT_ETM_PMU_SEED + (cpu * 2));
37}
38
39#endif
diff --git a/tools/include/linux/time64.h b/tools/include/linux/time64.h
new file mode 100644
index 000000000000..df9265483d65
--- /dev/null
+++ b/tools/include/linux/time64.h
@@ -0,0 +1,12 @@
1#ifndef _TOOLS_LINUX_TIME64_H
2#define _TOOLS_LINUX_TIME64_H
3
4#define MSEC_PER_SEC 1000L
5#define USEC_PER_MSEC 1000L
6#define NSEC_PER_USEC 1000L
7#define NSEC_PER_MSEC 1000000L
8#define USEC_PER_SEC 1000000L
9#define NSEC_PER_SEC 1000000000L
10#define FSEC_PER_SEC 1000000000000000LL
11
12#endif /* _LINUX_TIME64_H */
diff --git a/tools/include/uapi/asm-generic/mman-common.h b/tools/include/uapi/asm-generic/mman-common.h
new file mode 100644
index 000000000000..58274382a616
--- /dev/null
+++ b/tools/include/uapi/asm-generic/mman-common.h
@@ -0,0 +1,75 @@
1#ifndef __ASM_GENERIC_MMAN_COMMON_H
2#define __ASM_GENERIC_MMAN_COMMON_H
3
4/*
5 Author: Michael S. Tsirkin <mst@mellanox.co.il>, Mellanox Technologies Ltd.
6 Based on: asm-xxx/mman.h
7*/
8
9#define PROT_READ 0x1 /* page can be read */
10#define PROT_WRITE 0x2 /* page can be written */
11#define PROT_EXEC 0x4 /* page can be executed */
12#define PROT_SEM 0x8 /* page may be used for atomic ops */
13#define PROT_NONE 0x0 /* page can not be accessed */
14#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
15#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
16
17#define MAP_SHARED 0x01 /* Share changes */
18#define MAP_PRIVATE 0x02 /* Changes are private */
19#define MAP_TYPE 0x0f /* Mask for type of mapping */
20#define MAP_FIXED 0x10 /* Interpret addr exactly */
21#define MAP_ANONYMOUS 0x20 /* don't use a file */
22#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
23# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be uninitialized */
24#else
25# define MAP_UNINITIALIZED 0x0 /* Don't support this flag */
26#endif
27
28/*
29 * Flags for mlock
30 */
31#define MLOCK_ONFAULT 0x01 /* Lock pages in range after they are faulted in, do not prefault */
32
33#define MS_ASYNC 1 /* sync memory asynchronously */
34#define MS_INVALIDATE 2 /* invalidate the caches */
35#define MS_SYNC 4 /* synchronous memory sync */
36
37#define MADV_NORMAL 0 /* no further special treatment */
38#define MADV_RANDOM 1 /* expect random page references */
39#define MADV_SEQUENTIAL 2 /* expect sequential page references */
40#define MADV_WILLNEED 3 /* will need these pages */
41#define MADV_DONTNEED 4 /* don't need these pages */
42
43/* common parameters: try to keep these consistent across architectures */
44#define MADV_FREE 8 /* free pages only if memory pressure */
45#define MADV_REMOVE 9 /* remove these pages & resources */
46#define MADV_DONTFORK 10 /* don't inherit across fork */
47#define MADV_DOFORK 11 /* do inherit across fork */
48#define MADV_HWPOISON 100 /* poison a page for testing */
49#define MADV_SOFT_OFFLINE 101 /* soft offline page for testing */
50
51#define MADV_MERGEABLE 12 /* KSM may merge identical pages */
52#define MADV_UNMERGEABLE 13 /* KSM may not merge identical pages */
53
54#define MADV_HUGEPAGE 14 /* Worth backing with hugepages */
55#define MADV_NOHUGEPAGE 15 /* Not worth backing with hugepages */
56
57#define MADV_DONTDUMP 16 /* Explicity exclude from the core dump,
58 overrides the coredump filter bits */
59#define MADV_DODUMP 17 /* Clear the MADV_DONTDUMP flag */
60
61/* compatibility flags */
62#define MAP_FILE 0
63
64/*
65 * When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
66 * This gives us 6 bits, which is enough until someone invents 128 bit address
67 * spaces.
68 *
69 * Assume these are all power of twos.
70 * When 0 use the default page size.
71 */
72#define MAP_HUGE_SHIFT 26
73#define MAP_HUGE_MASK 0x3f
74
75#endif /* __ASM_GENERIC_MMAN_COMMON_H */
diff --git a/tools/include/uapi/asm-generic/mman.h b/tools/include/uapi/asm-generic/mman.h
new file mode 100644
index 000000000000..10fa7857777f
--- /dev/null
+++ b/tools/include/uapi/asm-generic/mman.h
@@ -0,0 +1,22 @@
1#ifndef __ASM_GENERIC_MMAN_H
2#define __ASM_GENERIC_MMAN_H
3
4#include <uapi/asm-generic/mman-common.h>
5
6#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
7#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
8#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
9#define MAP_LOCKED 0x2000 /* pages are locked */
10#define MAP_NORESERVE 0x4000 /* don't check for reservations */
11#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
12#define MAP_NONBLOCK 0x10000 /* do not block on IO */
13#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
14#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
15
16/* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
17
18#define MCL_CURRENT 1 /* lock all current mappings */
19#define MCL_FUTURE 2 /* lock all future mappings */
20#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
21
22#endif /* __ASM_GENERIC_MMAN_H */
diff --git a/tools/include/uapi/linux/mman.h b/tools/include/uapi/linux/mman.h
new file mode 100644
index 000000000000..81d8edf11789
--- /dev/null
+++ b/tools/include/uapi/linux/mman.h
@@ -0,0 +1,13 @@
1#ifndef _UAPI_LINUX_MMAN_H
2#define _UAPI_LINUX_MMAN_H
3
4#include <uapi/asm/mman.h>
5
6#define MREMAP_MAYMOVE 1
7#define MREMAP_FIXED 2
8
9#define OVERCOMMIT_GUESS 0
10#define OVERCOMMIT_ALWAYS 1
11#define OVERCOMMIT_NEVER 2
12
13#endif /* _UAPI_LINUX_MMAN_H */
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index d9836c5eb694..11c8d9bc762e 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -3266,6 +3266,9 @@ int main(int argc, char *argv[])
3266 } 3266 }
3267 } 3267 }
3268 3268
3269 /* If we exit via err(), this kills all the threads, restores tty. */
3270 atexit(cleanup_devices);
3271
3269 /* We always have a console device, and it's always device 1. */ 3272 /* We always have a console device, and it's always device 1. */
3270 setup_console(); 3273 setup_console();
3271 3274
@@ -3369,9 +3372,6 @@ int main(int argc, char *argv[])
3369 /* Ensure that we terminate if a device-servicing child dies. */ 3372 /* Ensure that we terminate if a device-servicing child dies. */
3370 signal(SIGCHLD, kill_launcher); 3373 signal(SIGCHLD, kill_launcher);
3371 3374
3372 /* If we exit via err(), this kills all the threads, restores tty. */
3373 atexit(cleanup_devices);
3374
3375 /* If requested, chroot to a directory */ 3375 /* If requested, chroot to a directory */
3376 if (chroot_path) { 3376 if (chroot_path) {
3377 if (chroot(chroot_path) != 0) 3377 if (chroot(chroot_path) != 0)
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index ba7094b945ff..f99f49e4a31e 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -34,6 +34,10 @@
34#define TRACEFS_MAGIC 0x74726163 34#define TRACEFS_MAGIC 0x74726163
35#endif 35#endif
36 36
37#ifndef HUGETLBFS_MAGIC
38#define HUGETLBFS_MAGIC 0x958458f6
39#endif
40
37static const char * const sysfs__fs_known_mountpoints[] = { 41static const char * const sysfs__fs_known_mountpoints[] = {
38 "/sys", 42 "/sys",
39 0, 43 0,
@@ -67,6 +71,10 @@ static const char * const tracefs__known_mountpoints[] = {
67 0, 71 0,
68}; 72};
69 73
74static const char * const hugetlbfs__known_mountpoints[] = {
75 0,
76};
77
70struct fs { 78struct fs {
71 const char *name; 79 const char *name;
72 const char * const *mounts; 80 const char * const *mounts;
@@ -80,6 +88,7 @@ enum {
80 FS__PROCFS = 1, 88 FS__PROCFS = 1,
81 FS__DEBUGFS = 2, 89 FS__DEBUGFS = 2,
82 FS__TRACEFS = 3, 90 FS__TRACEFS = 3,
91 FS__HUGETLBFS = 4,
83}; 92};
84 93
85#ifndef TRACEFS_MAGIC 94#ifndef TRACEFS_MAGIC
@@ -107,6 +116,11 @@ static struct fs fs__entries[] = {
107 .mounts = tracefs__known_mountpoints, 116 .mounts = tracefs__known_mountpoints,
108 .magic = TRACEFS_MAGIC, 117 .magic = TRACEFS_MAGIC,
109 }, 118 },
119 [FS__HUGETLBFS] = {
120 .name = "hugetlbfs",
121 .mounts = hugetlbfs__known_mountpoints,
122 .magic = HUGETLBFS_MAGIC,
123 },
110}; 124};
111 125
112static bool fs__read_mounts(struct fs *fs) 126static bool fs__read_mounts(struct fs *fs)
@@ -265,6 +279,7 @@ FS(sysfs, FS__SYSFS);
265FS(procfs, FS__PROCFS); 279FS(procfs, FS__PROCFS);
266FS(debugfs, FS__DEBUGFS); 280FS(debugfs, FS__DEBUGFS);
267FS(tracefs, FS__TRACEFS); 281FS(tracefs, FS__TRACEFS);
282FS(hugetlbfs, FS__HUGETLBFS);
268 283
269int filename__read_int(const char *filename, int *value) 284int filename__read_int(const char *filename, int *value)
270{ 285{
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index 16c9c2ed7c5b..a63269f5d20c 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -21,6 +21,7 @@ FS(sysfs)
21FS(procfs) 21FS(procfs)
22FS(debugfs) 22FS(debugfs)
23FS(tracefs) 23FS(tracefs)
24FS(hugetlbfs)
24 25
25#undef FS 26#undef FS
26 27
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index bd09d0effef8..143b6cdd7f06 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -175,6 +175,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
175 "__stack_chk_fail", 175 "__stack_chk_fail",
176 "panic", 176 "panic",
177 "do_exit", 177 "do_exit",
178 "do_task_dead",
178 "__module_put_and_exit", 179 "__module_put_and_exit",
179 "complete_and_exit", 180 "complete_and_exit",
180 "kvm_spurious_fault", 181 "kvm_spurious_fault",
diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt
index 15949e2a7805..cb081ac59fd1 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -110,6 +110,14 @@ Given a $HOME/.perfconfig like this:
110 order = caller 110 order = caller
111 sort-key = function 111 sort-key = function
112 112
113 [report]
114 # Defaults
115 sort-order = comm,dso,symbol
116 percent-limit = 0
117 queue-size = 0
118 children = true
119 group = true
120
113Variables 121Variables
114~~~~~~~~~ 122~~~~~~~~~
115 123
@@ -382,6 +390,10 @@ call-graph.*::
382 histogram entry. Default is 0 which means no limitation. 390 histogram entry. Default is 0 which means no limitation.
383 391
384report.*:: 392report.*::
393 report.sort_order::
394 Allows changing the default sort order from "comm,dso,symbol" to
395 some other default, for instance "sym,dso" may be more fitting for
396 kernel developers.
385 report.percent-limit:: 397 report.percent-limit::
386 This one is mostly the same as call-graph.threshold but works for 398 This one is mostly the same as call-graph.threshold but works for
387 histogram entries. Entries having an overhead lower than this 399 histogram entries. Entries having an overhead lower than this
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index b303bcdd8ed1..e6c9902c6d82 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -21,6 +21,8 @@ or
21'perf probe' [options] --vars='PROBEPOINT' 21'perf probe' [options] --vars='PROBEPOINT'
22or 22or
23'perf probe' [options] --funcs 23'perf probe' [options] --funcs
24or
25'perf probe' [options] --definition='PROBE' [...]
24 26
25DESCRIPTION 27DESCRIPTION
26----------- 28-----------
@@ -34,6 +36,8 @@ OPTIONS
34-k:: 36-k::
35--vmlinux=PATH:: 37--vmlinux=PATH::
36 Specify vmlinux path which has debuginfo (Dwarf binary). 38 Specify vmlinux path which has debuginfo (Dwarf binary).
39 Only when using this with --definition, you can give an offline
40 vmlinux file.
37 41
38-m:: 42-m::
39--module=MODNAME|PATH:: 43--module=MODNAME|PATH::
@@ -96,6 +100,11 @@ OPTIONS
96 can also list functions in a user space executable / shared library. 100 can also list functions in a user space executable / shared library.
97 This also can accept a FILTER rule argument. 101 This also can accept a FILTER rule argument.
98 102
103-D::
104--definition=::
105 Show trace-event definition converted from given probe-event instead
106 of write it into tracing/[k,u]probe_events.
107
99--filter=FILTER:: 108--filter=FILTER::
100 (Only for --vars and --funcs) Set filter. FILTER is a combination of glob 109 (Only for --vars and --funcs) Set filter. FILTER is a combination of glob
101 pattern, see FILTER PATTERN for detail. 110 pattern, see FILTER PATTERN for detail.
@@ -176,13 +185,12 @@ Each probe argument follows below syntax.
176 185
177'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.) 186'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
178'$vars' and '$params' special arguments are also available for NAME, '$vars' is expanded to the local variables (including function parameters) which can access at given probe point. '$params' is expanded to only the function parameters. 187'$vars' and '$params' special arguments are also available for NAME, '$vars' is expanded to the local variables (including function parameters) which can access at given probe point. '$params' is expanded to only the function parameters.
179'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. Currently, basic types (u8/u16/u32/u64/s8/s16/s32/s64), signedness casting (u/s), "string" and bitfield are supported. (see TYPES for detail) 188'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo (*). Currently, basic types (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal integers (x/x8/x16/x32/x64), signedness casting (u/s), "string" and bitfield are supported. (see TYPES for detail)
180
181On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid. 189On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
182 190
183TYPES 191TYPES
184----- 192-----
185Basic types (u8/u16/u32/u64/s8/s16/s32/s64) are integer types. Prefix 's' and 'u' means those types are signed and unsigned respectively. Traced arguments are shown in decimal (signed) or hex (unsigned). You can also use 's' or 'u' to specify only signedness and leave its size auto-detected by perf probe. 193Basic types (u8/u16/u32/u64/s8/s16/s32/s64) and hexadecimal integers (x8/x16/x32/x64) are integer types. Prefix 's' and 'u' means those types are signed and unsigned respectively, and 'x' means that is shown in hexadecimal format. Traced arguments are shown in decimal (sNN/uNN) or hex (xNN). You can also use 's' or 'u' to specify only signedness and leave its size auto-detected by perf probe. Moreover, you can use 'x' to explicitly specify to be shown in hexadecimal (the size is also auto-detected).
186String type is a special type, which fetches a "null-terminated" string from kernel space. This means it will fail and store NULL if the string container has been paged out. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type. 194String type is a special type, which fetches a "null-terminated" string from kernel space. This means it will fail and store NULL if the string container has been paged out. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
187Bitfield is another special type, which takes 3 parameters, bit-width, bit-offset, and container-size (usually 32). The syntax is; 195Bitfield is another special type, which takes 3 parameters, bit-width, bit-offset, and container-size (usually 32). The syntax is;
188 196
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 379a2bed07c0..92335193dc33 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -35,15 +35,15 @@ OPTIONS
35 35
36 - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where 36 - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where
37 'param1', 'param2', etc are defined as formats for the PMU in 37 'param1', 'param2', etc are defined as formats for the PMU in
38 /sys/bus/event_sources/devices/<pmu>/format/*. 38 /sys/bus/event_source/devices/<pmu>/format/*.
39 39
40 - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/' 40 - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/'
41 41
42 where M, N, K are numbers (in decimal, hex, octal format). Acceptable 42 where M, N, K are numbers (in decimal, hex, octal format). Acceptable
43 values for each of 'config', 'config1' and 'config2' are defined by 43 values for each of 'config', 'config1' and 'config2' are defined by
44 corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/* 44 corresponding entries in /sys/bus/event_source/devices/<pmu>/format/*
45 param1 and param2 are defined as formats for the PMU in: 45 param1 and param2 are defined as formats for the PMU in:
46 /sys/bus/event_sources/devices/<pmu>/format/* 46 /sys/bus/event_source/devices/<pmu>/format/*
47 47
48 There are also some params which are not defined in .../<pmu>/format/*. 48 There are also some params which are not defined in .../<pmu>/format/*.
49 These params can be used to overload default config values per event. 49 These params can be used to overload default config values per event.
@@ -60,6 +60,18 @@ OPTIONS
60 Note: If user explicitly sets options which conflict with the params, 60 Note: If user explicitly sets options which conflict with the params,
61 the value set by the params will be overridden. 61 the value set by the params will be overridden.
62 62
63 Also not defined in .../<pmu>/format/* are PMU driver specific
64 configuration parameters. Any configuration parameter preceded by
65 the letter '@' is not interpreted in user space and sent down directly
66 to the PMU driver. For example:
67
68 perf record -e some_event/@cfg1,@cfg2=config/ ...
69
70 will see 'cfg1' and 'cfg2=config' pushed to the PMU driver associated
71 with the event for further processing. There is no restriction on
72 what the configuration parameters are, as long as their semantic is
73 understood and supported by the PMU driver.
74
63 - a hardware breakpoint event in the form of '\mem:addr[/len][:access]' 75 - a hardware breakpoint event in the form of '\mem:addr[/len][:access]'
64 where addr is the address in memory you want to break in. 76 where addr is the address in memory you want to break in.
65 Access is the memory access type (read, write, execute) it can 77 Access is the memory access type (read, write, execute) it can
@@ -77,9 +89,62 @@ OPTIONS
77 89
78--filter=<filter>:: 90--filter=<filter>::
79 Event filter. This option should follow a event selector (-e) which 91 Event filter. This option should follow a event selector (-e) which
80 selects tracepoint event(s). Multiple '--filter' options are combined 92 selects either tracepoint event(s) or a hardware trace PMU
93 (e.g. Intel PT or CoreSight).
94
95 - tracepoint filters
96
97 In the case of tracepoints, multiple '--filter' options are combined
81 using '&&'. 98 using '&&'.
82 99
100 - address filters
101
102 A hardware trace PMU advertises its ability to accept a number of
103 address filters by specifying a non-zero value in
104 /sys/bus/event_source/devices/<pmu>/nr_addr_filters.
105
106 Address filters have the format:
107
108 filter|start|stop|tracestop <start> [/ <size>] [@<file name>]
109
110 Where:
111 - 'filter': defines a region that will be traced.
112 - 'start': defines an address at which tracing will begin.
113 - 'stop': defines an address at which tracing will stop.
114 - 'tracestop': defines a region in which tracing will stop.
115
116 <file name> is the name of the object file, <start> is the offset to the
117 code to trace in that file, and <size> is the size of the region to
118 trace. 'start' and 'stop' filters need not specify a <size>.
119
120 If no object file is specified then the kernel is assumed, in which case
121 the start address must be a current kernel memory address.
122
123 <start> can also be specified by providing the name of a symbol. If the
124 symbol name is not unique, it can be disambiguated by inserting #n where
125 'n' selects the n'th symbol in address order. Alternately #0, #g or #G
126 select only a global symbol. <size> can also be specified by providing
127 the name of a symbol, in which case the size is calculated to the end
128 of that symbol. For 'filter' and 'tracestop' filters, if <size> is
129 omitted and <start> is a symbol, then the size is calculated to the end
130 of that symbol.
131
132 If <size> is omitted and <start> is '*', then the start and size will
133 be calculated from the first and last symbols, i.e. to trace the whole
134 file.
135
136 If symbol names (or '*') are provided, they must be surrounded by white
137 space.
138
139 The filter passed to the kernel is not necessarily the same as entered.
140 To see the filter that is passed, use the -v option.
141
142 The kernel may not be able to configure a trace region if it is not
143 within a single mapping. MMAP events (or /proc/<pid>/maps) can be
144 examined to determine if that is a possibility.
145
146 Multiple filters can be separated with space or comma.
147
83--exclude-perf:: 148--exclude-perf::
84 Don't record events issued by perf itself. This option should follow 149 Don't record events issued by perf itself. This option should follow
85 a event selector (-e) which selects tracepoint event(s). It adds a 150 a event selector (-e) which selects tracepoint event(s). It adds a
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index fdc99fe6bbc3..b664b18d3991 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -437,6 +437,10 @@ in pmu-tools parser. This allows to read perf.data from python and dump it.
437quipper 437quipper
438 438
439The quipper C++ parser is available at 439The quipper C++ parser is available at
440https://chromium.googlesource.com/chromiumos/platform/chromiumos-wide-profiling/ 440https://chromium.googlesource.com/chromiumos/platform2
441
442It is under the chromiumos-wide-profiling/ subdirectory. This library can
443convert a perf data file to a protobuf and vice versa.
444
441Unfortunately this parser tends to be many versions behind and may not be able 445Unfortunately this parser tends to be many versions behind and may not be able
442to parse data files generated by recent perf. 446to parse data files generated by recent perf.
diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
index 1d8d5bc4cd2d..2b477c1d1efe 100644
--- a/tools/perf/Documentation/perfconfig.example
+++ b/tools/perf/Documentation/perfconfig.example
@@ -27,3 +27,12 @@
27 use_offset = true 27 use_offset = true
28 jump_arrows = true 28 jump_arrows = true
29 show_nr_jumps = false 29 show_nr_jumps = false
30
31[report]
32
33 # Defaults
34 sort-order = comm,dso,symbol
35 percent-limit = 0
36 queue-size = 0
37 children = true
38 group = true
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index ad2534df4ba6..0bda2cca2b3a 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -60,14 +60,18 @@ tools/include/asm-generic/bitops.h
60tools/include/linux/atomic.h 60tools/include/linux/atomic.h
61tools/include/linux/bitops.h 61tools/include/linux/bitops.h
62tools/include/linux/compiler.h 62tools/include/linux/compiler.h
63tools/include/linux/coresight-pmu.h
63tools/include/linux/filter.h 64tools/include/linux/filter.h
64tools/include/linux/hash.h 65tools/include/linux/hash.h
65tools/include/linux/kernel.h 66tools/include/linux/kernel.h
66tools/include/linux/list.h 67tools/include/linux/list.h
67tools/include/linux/log2.h 68tools/include/linux/log2.h
69tools/include/uapi/asm-generic/mman-common.h
70tools/include/uapi/asm-generic/mman.h
68tools/include/uapi/linux/bpf.h 71tools/include/uapi/linux/bpf.h
69tools/include/uapi/linux/bpf_common.h 72tools/include/uapi/linux/bpf_common.h
70tools/include/uapi/linux/hw_breakpoint.h 73tools/include/uapi/linux/hw_breakpoint.h
74tools/include/uapi/linux/mman.h
71tools/include/uapi/linux/perf_event.h 75tools/include/uapi/linux/perf_event.h
72tools/include/linux/poison.h 76tools/include/linux/poison.h
73tools/include/linux/rbtree.h 77tools/include/linux/rbtree.h
@@ -77,4 +81,6 @@ tools/include/linux/stringify.h
77tools/include/linux/types.h 81tools/include/linux/types.h
78tools/include/linux/err.h 82tools/include/linux/err.h
79tools/include/linux/bitmap.h 83tools/include/linux/bitmap.h
84tools/include/linux/time64.h
85tools/arch/*/include/uapi/asm/mman.h
80tools/arch/*/include/uapi/asm/perf_regs.h 86tools/arch/*/include/uapi/asm/perf_regs.h
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 24803c58049a..72edf83d76b7 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -746,10 +746,13 @@ ifdef LIBBABELTRACE
746endif 746endif
747 747
748ifndef NO_AUXTRACE 748ifndef NO_AUXTRACE
749 ifeq ($(feature-get_cpuid), 0) 749 ifeq ($(ARCH),x86)
750 msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); 750 ifeq ($(feature-get_cpuid), 0)
751 NO_AUXTRACE := 1 751 msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc);
752 else 752 NO_AUXTRACE := 1
753 endif
754 endif
755 ifndef NO_AUXTRACE
753 $(call detected,CONFIG_AUXTRACE) 756 $(call detected,CONFIG_AUXTRACE)
754 CFLAGS += -DHAVE_AUXTRACE_SUPPORT 757 CFLAGS += -DHAVE_AUXTRACE_SUPPORT
755 endif 758 endif
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 2d9087501633..d710db16b963 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -165,7 +165,7 @@ SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
165# non-config cases 165# non-config cases
166config := 1 166config := 1
167 167
168NON_CONFIG_TARGETS := clean TAGS tags cscope help 168NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc
169 169
170ifdef MAKECMDGOALS 170ifdef MAKECMDGOALS
171ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),) 171ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
@@ -429,6 +429,18 @@ $(PERF_IN): prepare FORCE
429 @(test -f ../../include/asm-generic/bitops/fls64.h && ( \ 429 @(test -f ../../include/asm-generic/bitops/fls64.h && ( \
430 (diff -B ../include/asm-generic/bitops/fls64.h ../../include/asm-generic/bitops/fls64.h >/dev/null) \ 430 (diff -B ../include/asm-generic/bitops/fls64.h ../../include/asm-generic/bitops/fls64.h >/dev/null) \
431 || echo "Warning: tools/include/asm-generic/bitops/fls64.h differs from kernel" >&2 )) || true 431 || echo "Warning: tools/include/asm-generic/bitops/fls64.h differs from kernel" >&2 )) || true
432 @(test -f ../../include/linux/coresight-pmu.h && ( \
433 (diff -B ../include/linux/coresight-pmu.h ../../include/linux/coresight-pmu.h >/dev/null) \
434 || echo "Warning: tools/include/linux/coresight-pmu.h differs from kernel" >&2 )) || true
435 @(test -f ../../include/uapi/asm-generic/mman-common.h && ( \
436 (diff -B ../include/uapi/asm-generic/mman-common.h ../../include/uapi/asm-generic/mman-common.h >/dev/null) \
437 || echo "Warning: tools/include/uapi/asm-generic/mman-common.h differs from kernel" >&2 )) || true
438 @(test -f ../../include/uapi/asm-generic/mman.h && ( \
439 (diff -B -I "^#include <\(uapi/\)*asm-generic/mman-common.h>$$" ../include/uapi/asm-generic/mman.h ../../include/uapi/asm-generic/mman.h >/dev/null) \
440 || echo "Warning: tools/include/uapi/asm-generic/mman.h differs from kernel" >&2 )) || true
441 @(test -f ../../include/uapi/linux/mman.h && ( \
442 (diff -B -I "^#include <\(uapi/\)*asm/mman.h>$$" ../include/uapi/linux/mman.h ../../include/uapi/linux/mman.h >/dev/null) \
443 || echo "Warning: tools/include/uapi/linux/mman.h differs from kernel" >&2 )) || true
432 $(Q)$(MAKE) $(build)=perf 444 $(Q)$(MAKE) $(build)=perf
433 445
434$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) 446$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
diff --git a/tools/perf/arch/arm/include/dwarf-regs-table.h b/tools/perf/arch/arm/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..f298d034c37b
--- /dev/null
+++ b/tools/perf/arch/arm/include/dwarf-regs-table.h
@@ -0,0 +1,9 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const arm_regstr_tbl[] = {
5 "%r0", "%r1", "%r2", "%r3", "%r4",
6 "%r5", "%r6", "%r7", "%r8", "%r9", "%r10",
7 "%fp", "%ip", "%sp", "%lr", "%pc",
8};
9#endif
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build
index f98da17357c0..e64c5f216448 100644
--- a/tools/perf/arch/arm/util/Build
+++ b/tools/perf/arch/arm/util/Build
@@ -2,3 +2,5 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o
2 2
3libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o 3libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
4libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 4libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
5
6libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs-etm.o
diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
new file mode 100644
index 000000000000..8edf2cb71564
--- /dev/null
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <stdbool.h>
19#include <linux/coresight-pmu.h>
20
21#include "../../util/auxtrace.h"
22#include "../../util/evlist.h"
23#include "../../util/pmu.h"
24#include "cs-etm.h"
25
26struct auxtrace_record
27*auxtrace_record__init(struct perf_evlist *evlist, int *err)
28{
29 struct perf_pmu *cs_etm_pmu;
30 struct perf_evsel *evsel;
31 bool found_etm = false;
32
33 cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
34
35 if (evlist) {
36 evlist__for_each_entry(evlist, evsel) {
37 if (cs_etm_pmu &&
38 evsel->attr.type == cs_etm_pmu->type)
39 found_etm = true;
40 }
41 }
42
43 if (found_etm)
44 return cs_etm_record_init(err);
45
46 /*
47 * Clear 'err' even if we haven't found a cs_etm event - that way perf
48 * record can still be used even if tracers aren't present. The NULL
49 * return value will take care of telling the infrastructure HW tracing
50 * isn't available.
51 */
52 *err = 0;
53 return NULL;
54}
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
new file mode 100644
index 000000000000..47d584da5819
--- /dev/null
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -0,0 +1,617 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <api/fs/fs.h>
19#include <linux/bitops.h>
20#include <linux/coresight-pmu.h>
21#include <linux/kernel.h>
22#include <linux/log2.h>
23#include <linux/types.h>
24
25#include "cs-etm.h"
26#include "../../perf.h"
27#include "../../util/auxtrace.h"
28#include "../../util/cpumap.h"
29#include "../../util/evlist.h"
30#include "../../util/evsel.h"
31#include "../../util/pmu.h"
32#include "../../util/thread_map.h"
33#include "../../util/cs-etm.h"
34
35#include <stdlib.h>
36
37#define ENABLE_SINK_MAX 128
38#define CS_BUS_DEVICE_PATH "/bus/coresight/devices/"
39
40struct cs_etm_recording {
41 struct auxtrace_record itr;
42 struct perf_pmu *cs_etm_pmu;
43 struct perf_evlist *evlist;
44 bool snapshot_mode;
45 size_t snapshot_size;
46};
47
48static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
49
50static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
51 struct record_opts *opts,
52 const char *str)
53{
54 struct cs_etm_recording *ptr =
55 container_of(itr, struct cs_etm_recording, itr);
56 unsigned long long snapshot_size = 0;
57 char *endptr;
58
59 if (str) {
60 snapshot_size = strtoull(str, &endptr, 0);
61 if (*endptr || snapshot_size > SIZE_MAX)
62 return -1;
63 }
64
65 opts->auxtrace_snapshot_mode = true;
66 opts->auxtrace_snapshot_size = snapshot_size;
67 ptr->snapshot_size = snapshot_size;
68
69 return 0;
70}
71
72static int cs_etm_recording_options(struct auxtrace_record *itr,
73 struct perf_evlist *evlist,
74 struct record_opts *opts)
75{
76 struct cs_etm_recording *ptr =
77 container_of(itr, struct cs_etm_recording, itr);
78 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
79 struct perf_evsel *evsel, *cs_etm_evsel = NULL;
80 const struct cpu_map *cpus = evlist->cpus;
81 bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0);
82
83 ptr->evlist = evlist;
84 ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
85
86 evlist__for_each_entry(evlist, evsel) {
87 if (evsel->attr.type == cs_etm_pmu->type) {
88 if (cs_etm_evsel) {
89 pr_err("There may be only one %s event\n",
90 CORESIGHT_ETM_PMU_NAME);
91 return -EINVAL;
92 }
93 evsel->attr.freq = 0;
94 evsel->attr.sample_period = 1;
95 cs_etm_evsel = evsel;
96 opts->full_auxtrace = true;
97 }
98 }
99
100 /* no need to continue if at least one event of interest was found */
101 if (!cs_etm_evsel)
102 return 0;
103
104 if (opts->use_clockid) {
105 pr_err("Cannot use clockid (-k option) with %s\n",
106 CORESIGHT_ETM_PMU_NAME);
107 return -EINVAL;
108 }
109
110 /* we are in snapshot mode */
111 if (opts->auxtrace_snapshot_mode) {
112 /*
113 * No size were given to '-S' or '-m,', so go with
114 * the default
115 */
116 if (!opts->auxtrace_snapshot_size &&
117 !opts->auxtrace_mmap_pages) {
118 if (privileged) {
119 opts->auxtrace_mmap_pages = MiB(4) / page_size;
120 } else {
121 opts->auxtrace_mmap_pages =
122 KiB(128) / page_size;
123 if (opts->mmap_pages == UINT_MAX)
124 opts->mmap_pages = KiB(256) / page_size;
125 }
126 } else if (!opts->auxtrace_mmap_pages && !privileged &&
127 opts->mmap_pages == UINT_MAX) {
128 opts->mmap_pages = KiB(256) / page_size;
129 }
130
131 /*
132 * '-m,xyz' was specified but no snapshot size, so make the
133 * snapshot size as big as the auxtrace mmap area.
134 */
135 if (!opts->auxtrace_snapshot_size) {
136 opts->auxtrace_snapshot_size =
137 opts->auxtrace_mmap_pages * (size_t)page_size;
138 }
139
140 /*
141 * -Sxyz was specified but no auxtrace mmap area, so make the
142 * auxtrace mmap area big enough to fit the requested snapshot
143 * size.
144 */
145 if (!opts->auxtrace_mmap_pages) {
146 size_t sz = opts->auxtrace_snapshot_size;
147
148 sz = round_up(sz, page_size) / page_size;
149 opts->auxtrace_mmap_pages = roundup_pow_of_two(sz);
150 }
151
152 /* Snapshost size can't be bigger than the auxtrace area */
153 if (opts->auxtrace_snapshot_size >
154 opts->auxtrace_mmap_pages * (size_t)page_size) {
155 pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
156 opts->auxtrace_snapshot_size,
157 opts->auxtrace_mmap_pages * (size_t)page_size);
158 return -EINVAL;
159 }
160
161 /* Something went wrong somewhere - this shouldn't happen */
162 if (!opts->auxtrace_snapshot_size ||
163 !opts->auxtrace_mmap_pages) {
164 pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
165 return -EINVAL;
166 }
167 }
168
169 /* We are in full trace mode but '-m,xyz' wasn't specified */
170 if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) {
171 if (privileged) {
172 opts->auxtrace_mmap_pages = MiB(4) / page_size;
173 } else {
174 opts->auxtrace_mmap_pages = KiB(128) / page_size;
175 if (opts->mmap_pages == UINT_MAX)
176 opts->mmap_pages = KiB(256) / page_size;
177 }
178
179 }
180
181 /* Validate auxtrace_mmap_pages provided by user */
182 if (opts->auxtrace_mmap_pages) {
183 unsigned int max_page = (KiB(128) / page_size);
184 size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size;
185
186 if (!privileged &&
187 opts->auxtrace_mmap_pages > max_page) {
188 opts->auxtrace_mmap_pages = max_page;
189 pr_err("auxtrace too big, truncating to %d\n",
190 max_page);
191 }
192
193 if (!is_power_of_2(sz)) {
194 pr_err("Invalid mmap size for %s: must be a power of 2\n",
195 CORESIGHT_ETM_PMU_NAME);
196 return -EINVAL;
197 }
198 }
199
200 if (opts->auxtrace_snapshot_mode)
201 pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME,
202 opts->auxtrace_snapshot_size);
203
204 if (cs_etm_evsel) {
205 /*
206 * To obtain the auxtrace buffer file descriptor, the auxtrace
207 * event must come first.
208 */
209 perf_evlist__to_front(evlist, cs_etm_evsel);
210 /*
211 * In the case of per-cpu mmaps, we need the CPU on the
212 * AUX event.
213 */
214 if (!cpu_map__empty(cpus))
215 perf_evsel__set_sample_bit(cs_etm_evsel, CPU);
216 }
217
218 /* Add dummy event to keep tracking */
219 if (opts->full_auxtrace) {
220 struct perf_evsel *tracking_evsel;
221 int err;
222
223 err = parse_events(evlist, "dummy:u", NULL);
224 if (err)
225 return err;
226
227 tracking_evsel = perf_evlist__last(evlist);
228 perf_evlist__set_tracking_event(evlist, tracking_evsel);
229
230 tracking_evsel->attr.freq = 0;
231 tracking_evsel->attr.sample_period = 1;
232
233 /* In per-cpu case, always need the time of mmap events etc */
234 if (!cpu_map__empty(cpus))
235 perf_evsel__set_sample_bit(tracking_evsel, TIME);
236 }
237
238 return 0;
239}
240
241static u64 cs_etm_get_config(struct auxtrace_record *itr)
242{
243 u64 config = 0;
244 struct cs_etm_recording *ptr =
245 container_of(itr, struct cs_etm_recording, itr);
246 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
247 struct perf_evlist *evlist = ptr->evlist;
248 struct perf_evsel *evsel;
249
250 evlist__for_each_entry(evlist, evsel) {
251 if (evsel->attr.type == cs_etm_pmu->type) {
252 /*
253 * Variable perf_event_attr::config is assigned to
254 * ETMv3/PTM. The bit fields have been made to match
255 * the ETMv3.5 ETRMCR register specification. See the
256 * PMU_FORMAT_ATTR() declarations in
257 * drivers/hwtracing/coresight/coresight-perf.c for
258 * details.
259 */
260 config = evsel->attr.config;
261 break;
262 }
263 }
264
265 return config;
266}
267
268static size_t
269cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
270 struct perf_evlist *evlist __maybe_unused)
271{
272 int i;
273 int etmv3 = 0, etmv4 = 0;
274 const struct cpu_map *cpus = evlist->cpus;
275
276 /* cpu map is not empty, we have specific CPUs to work with */
277 if (!cpu_map__empty(cpus)) {
278 for (i = 0; i < cpu_map__nr(cpus); i++) {
279 if (cs_etm_is_etmv4(itr, cpus->map[i]))
280 etmv4++;
281 else
282 etmv3++;
283 }
284 } else {
285 /* get configuration for all CPUs in the system */
286 for (i = 0; i < cpu__max_cpu(); i++) {
287 if (cs_etm_is_etmv4(itr, i))
288 etmv4++;
289 else
290 etmv3++;
291 }
292 }
293
294 return (CS_ETM_HEADER_SIZE +
295 (etmv4 * CS_ETMV4_PRIV_SIZE) +
296 (etmv3 * CS_ETMV3_PRIV_SIZE));
297}
298
299static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = {
300 [CS_ETM_ETMCCER] = "mgmt/etmccer",
301 [CS_ETM_ETMIDR] = "mgmt/etmidr",
302};
303
304static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
305 [CS_ETMV4_TRCIDR0] = "trcidr/trcidr0",
306 [CS_ETMV4_TRCIDR1] = "trcidr/trcidr1",
307 [CS_ETMV4_TRCIDR2] = "trcidr/trcidr2",
308 [CS_ETMV4_TRCIDR8] = "trcidr/trcidr8",
309 [CS_ETMV4_TRCAUTHSTATUS] = "mgmt/trcauthstatus",
310};
311
312static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu)
313{
314 bool ret = false;
315 char path[PATH_MAX];
316 int scan;
317 unsigned int val;
318 struct cs_etm_recording *ptr =
319 container_of(itr, struct cs_etm_recording, itr);
320 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
321
322 /* Take any of the RO files for ETMv4 and see if it present */
323 snprintf(path, PATH_MAX, "cpu%d/%s",
324 cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
325 scan = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
326
327 /* The file was read successfully, we have a winner */
328 if (scan == 1)
329 ret = true;
330
331 return ret;
332}
333
334static int cs_etm_get_ro(struct perf_pmu *pmu, int cpu, const char *path)
335{
336 char pmu_path[PATH_MAX];
337 int scan;
338 unsigned int val = 0;
339
340 /* Get RO metadata from sysfs */
341 snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path);
342
343 scan = perf_pmu__scan_file(pmu, pmu_path, "%x", &val);
344 if (scan != 1)
345 pr_err("%s: error reading: %s\n", __func__, pmu_path);
346
347 return val;
348}
349
350static void cs_etm_get_metadata(int cpu, u32 *offset,
351 struct auxtrace_record *itr,
352 struct auxtrace_info_event *info)
353{
354 u32 increment;
355 u64 magic;
356 struct cs_etm_recording *ptr =
357 container_of(itr, struct cs_etm_recording, itr);
358 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
359
360 /* first see what kind of tracer this cpu is affined to */
361 if (cs_etm_is_etmv4(itr, cpu)) {
362 magic = __perf_cs_etmv4_magic;
363 /* Get trace configuration register */
364 info->priv[*offset + CS_ETMV4_TRCCONFIGR] =
365 cs_etm_get_config(itr);
366 /* Get traceID from the framework */
367 info->priv[*offset + CS_ETMV4_TRCTRACEIDR] =
368 coresight_get_trace_id(cpu);
369 /* Get read-only information from sysFS */
370 info->priv[*offset + CS_ETMV4_TRCIDR0] =
371 cs_etm_get_ro(cs_etm_pmu, cpu,
372 metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
373 info->priv[*offset + CS_ETMV4_TRCIDR1] =
374 cs_etm_get_ro(cs_etm_pmu, cpu,
375 metadata_etmv4_ro[CS_ETMV4_TRCIDR1]);
376 info->priv[*offset + CS_ETMV4_TRCIDR2] =
377 cs_etm_get_ro(cs_etm_pmu, cpu,
378 metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
379 info->priv[*offset + CS_ETMV4_TRCIDR8] =
380 cs_etm_get_ro(cs_etm_pmu, cpu,
381 metadata_etmv4_ro[CS_ETMV4_TRCIDR8]);
382 info->priv[*offset + CS_ETMV4_TRCAUTHSTATUS] =
383 cs_etm_get_ro(cs_etm_pmu, cpu,
384 metadata_etmv4_ro
385 [CS_ETMV4_TRCAUTHSTATUS]);
386
387 /* How much space was used */
388 increment = CS_ETMV4_PRIV_MAX;
389 } else {
390 magic = __perf_cs_etmv3_magic;
391 /* Get configuration register */
392 info->priv[*offset + CS_ETM_ETMCR] = cs_etm_get_config(itr);
393 /* Get traceID from the framework */
394 info->priv[*offset + CS_ETM_ETMTRACEIDR] =
395 coresight_get_trace_id(cpu);
396 /* Get read-only information from sysFS */
397 info->priv[*offset + CS_ETM_ETMCCER] =
398 cs_etm_get_ro(cs_etm_pmu, cpu,
399 metadata_etmv3_ro[CS_ETM_ETMCCER]);
400 info->priv[*offset + CS_ETM_ETMIDR] =
401 cs_etm_get_ro(cs_etm_pmu, cpu,
402 metadata_etmv3_ro[CS_ETM_ETMIDR]);
403
404 /* How much space was used */
405 increment = CS_ETM_PRIV_MAX;
406 }
407
408 /* Build generic header portion */
409 info->priv[*offset + CS_ETM_MAGIC] = magic;
410 info->priv[*offset + CS_ETM_CPU] = cpu;
411 /* Where the next CPU entry should start from */
412 *offset += increment;
413}
414
415static int cs_etm_info_fill(struct auxtrace_record *itr,
416 struct perf_session *session,
417 struct auxtrace_info_event *info,
418 size_t priv_size)
419{
420 int i;
421 u32 offset;
422 u64 nr_cpu, type;
423 const struct cpu_map *cpus = session->evlist->cpus;
424 struct cs_etm_recording *ptr =
425 container_of(itr, struct cs_etm_recording, itr);
426 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
427
428 if (priv_size != cs_etm_info_priv_size(itr, session->evlist))
429 return -EINVAL;
430
431 if (!session->evlist->nr_mmaps)
432 return -EINVAL;
433
434 /* If the cpu_map is empty all CPUs are involved */
435 nr_cpu = cpu_map__empty(cpus) ? cpu__max_cpu() : cpu_map__nr(cpus);
436 /* Get PMU type as dynamically assigned by the core */
437 type = cs_etm_pmu->type;
438
439 /* First fill out the session header */
440 info->type = PERF_AUXTRACE_CS_ETM;
441 info->priv[CS_HEADER_VERSION_0] = 0;
442 info->priv[CS_PMU_TYPE_CPUS] = type << 32;
443 info->priv[CS_PMU_TYPE_CPUS] |= nr_cpu;
444 info->priv[CS_ETM_SNAPSHOT] = ptr->snapshot_mode;
445
446 offset = CS_ETM_SNAPSHOT + 1;
447
448 /* cpu map is not empty, we have specific CPUs to work with */
449 if (!cpu_map__empty(cpus)) {
450 for (i = 0; i < cpu_map__nr(cpus) && offset < priv_size; i++)
451 cs_etm_get_metadata(cpus->map[i], &offset, itr, info);
452 } else {
453 /* get configuration for all CPUs in the system */
454 for (i = 0; i < cpu__max_cpu(); i++)
455 cs_etm_get_metadata(i, &offset, itr, info);
456 }
457
458 return 0;
459}
460
461static int cs_etm_find_snapshot(struct auxtrace_record *itr __maybe_unused,
462 int idx, struct auxtrace_mmap *mm,
463 unsigned char *data __maybe_unused,
464 u64 *head, u64 *old)
465{
466 pr_debug3("%s: mmap index %d old head %zu new head %zu size %zu\n",
467 __func__, idx, (size_t)*old, (size_t)*head, mm->len);
468
469 *old = *head;
470 *head += mm->len;
471
472 return 0;
473}
474
475static int cs_etm_snapshot_start(struct auxtrace_record *itr)
476{
477 struct cs_etm_recording *ptr =
478 container_of(itr, struct cs_etm_recording, itr);
479 struct perf_evsel *evsel;
480
481 evlist__for_each_entry(ptr->evlist, evsel) {
482 if (evsel->attr.type == ptr->cs_etm_pmu->type)
483 return perf_evsel__disable(evsel);
484 }
485 return -EINVAL;
486}
487
488static int cs_etm_snapshot_finish(struct auxtrace_record *itr)
489{
490 struct cs_etm_recording *ptr =
491 container_of(itr, struct cs_etm_recording, itr);
492 struct perf_evsel *evsel;
493
494 evlist__for_each_entry(ptr->evlist, evsel) {
495 if (evsel->attr.type == ptr->cs_etm_pmu->type)
496 return perf_evsel__enable(evsel);
497 }
498 return -EINVAL;
499}
500
501static u64 cs_etm_reference(struct auxtrace_record *itr __maybe_unused)
502{
503 return (((u64) rand() << 0) & 0x00000000FFFFFFFFull) |
504 (((u64) rand() << 32) & 0xFFFFFFFF00000000ull);
505}
506
507static void cs_etm_recording_free(struct auxtrace_record *itr)
508{
509 struct cs_etm_recording *ptr =
510 container_of(itr, struct cs_etm_recording, itr);
511 free(ptr);
512}
513
514static int cs_etm_read_finish(struct auxtrace_record *itr, int idx)
515{
516 struct cs_etm_recording *ptr =
517 container_of(itr, struct cs_etm_recording, itr);
518 struct perf_evsel *evsel;
519
520 evlist__for_each_entry(ptr->evlist, evsel) {
521 if (evsel->attr.type == ptr->cs_etm_pmu->type)
522 return perf_evlist__enable_event_idx(ptr->evlist,
523 evsel, idx);
524 }
525
526 return -EINVAL;
527}
528
529struct auxtrace_record *cs_etm_record_init(int *err)
530{
531 struct perf_pmu *cs_etm_pmu;
532 struct cs_etm_recording *ptr;
533
534 cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
535
536 if (!cs_etm_pmu) {
537 *err = -EINVAL;
538 goto out;
539 }
540
541 ptr = zalloc(sizeof(struct cs_etm_recording));
542 if (!ptr) {
543 *err = -ENOMEM;
544 goto out;
545 }
546
547 ptr->cs_etm_pmu = cs_etm_pmu;
548 ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options;
549 ptr->itr.recording_options = cs_etm_recording_options;
550 ptr->itr.info_priv_size = cs_etm_info_priv_size;
551 ptr->itr.info_fill = cs_etm_info_fill;
552 ptr->itr.find_snapshot = cs_etm_find_snapshot;
553 ptr->itr.snapshot_start = cs_etm_snapshot_start;
554 ptr->itr.snapshot_finish = cs_etm_snapshot_finish;
555 ptr->itr.reference = cs_etm_reference;
556 ptr->itr.free = cs_etm_recording_free;
557 ptr->itr.read_finish = cs_etm_read_finish;
558
559 *err = 0;
560 return &ptr->itr;
561out:
562 return NULL;
563}
564
565static FILE *cs_device__open_file(const char *name)
566{
567 struct stat st;
568 char path[PATH_MAX];
569 const char *sysfs;
570
571 sysfs = sysfs__mountpoint();
572 if (!sysfs)
573 return NULL;
574
575 snprintf(path, PATH_MAX,
576 "%s" CS_BUS_DEVICE_PATH "%s", sysfs, name);
577
578 printf("path: %s\n", path);
579
580 if (stat(path, &st) < 0)
581 return NULL;
582
583 return fopen(path, "w");
584
585}
586
587static __attribute__((format(printf, 2, 3)))
588int cs_device__print_file(const char *name, const char *fmt, ...)
589{
590 va_list args;
591 FILE *file;
592 int ret = -EINVAL;
593
594 va_start(args, fmt);
595 file = cs_device__open_file(name);
596 if (file) {
597 ret = vfprintf(file, fmt, args);
598 fclose(file);
599 }
600 va_end(args);
601 return ret;
602}
603
604int cs_etm_set_drv_config(struct perf_evsel_config_term *term)
605{
606 int ret;
607 char enable_sink[ENABLE_SINK_MAX];
608
609 snprintf(enable_sink, ENABLE_SINK_MAX, "%s/%s",
610 term->val.drv_cfg, "enable_sink");
611
612 ret = cs_device__print_file(enable_sink, "%d", 1);
613 if (ret < 0)
614 return ret;
615
616 return 0;
617}
diff --git a/tools/perf/arch/arm/util/cs-etm.h b/tools/perf/arch/arm/util/cs-etm.h
new file mode 100644
index 000000000000..5256741be549
--- /dev/null
+++ b/tools/perf/arch/arm/util/cs-etm.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef INCLUDE__PERF_CS_ETM_H__
19#define INCLUDE__PERF_CS_ETM_H__
20
21#include "../../util/evsel.h"
22
23struct auxtrace_record *cs_etm_record_init(int *err);
24int cs_etm_set_drv_config(struct perf_evsel_config_term *term);
25
26#endif
diff --git a/tools/perf/arch/arm/util/pmu.c b/tools/perf/arch/arm/util/pmu.c
new file mode 100644
index 000000000000..98d67399a0d6
--- /dev/null
+++ b/tools/perf/arch/arm/util/pmu.c
@@ -0,0 +1,36 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <string.h>
19#include <linux/coresight-pmu.h>
20#include <linux/perf_event.h>
21
22#include "cs-etm.h"
23#include "../../util/pmu.h"
24
25struct perf_event_attr
26*perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
27{
28#ifdef HAVE_AUXTRACE_SUPPORT
29 if (!strcmp(pmu->name, CORESIGHT_ETM_PMU_NAME)) {
30 /* add ETM default config here */
31 pmu->selectable = true;
32 pmu->set_drv_config = cs_etm_set_drv_config;
33 }
34#endif
35 return NULL;
36}
diff --git a/tools/perf/arch/arm64/include/dwarf-regs-table.h b/tools/perf/arch/arm64/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..26759363f921
--- /dev/null
+++ b/tools/perf/arch/arm64/include/dwarf-regs-table.h
@@ -0,0 +1,13 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const aarch64_regstr_tbl[] = {
5 "%r0", "%r1", "%r2", "%r3", "%r4",
6 "%r5", "%r6", "%r7", "%r8", "%r9",
7 "%r10", "%r11", "%r12", "%r13", "%r14",
8 "%r15", "%r16", "%r17", "%r18", "%r19",
9 "%r20", "%r21", "%r22", "%r23", "%r24",
10 "%r25", "%r26", "%r27", "%r28", "%r29",
11 "%lr", "%sp",
12};
13#endif
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index 02f41dba4f4f..cef6fb38d17e 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -1,2 +1,6 @@
1libperf-$(CONFIG_DWARF) += dwarf-regs.o 1libperf-$(CONFIG_DWARF) += dwarf-regs.o
2libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o 2libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
3
4libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
5 ../../arm/util/auxtrace.o \
6 ../../arm/util/cs-etm.o
diff --git a/tools/perf/arch/powerpc/Build b/tools/perf/arch/powerpc/Build
index 54afe4a467e7..db52fa22d3a1 100644
--- a/tools/perf/arch/powerpc/Build
+++ b/tools/perf/arch/powerpc/Build
@@ -1 +1,2 @@
1libperf-y += util/ 1libperf-y += util/
2libperf-y += tests/
diff --git a/tools/perf/arch/powerpc/include/arch-tests.h b/tools/perf/arch/powerpc/include/arch-tests.h
new file mode 100644
index 000000000000..84d8dedef2ed
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/arch-tests.h
@@ -0,0 +1,13 @@
1#ifndef ARCH_TESTS_H
2#define ARCH_TESTS_H
3
4#ifdef HAVE_DWARF_UNWIND_SUPPORT
5struct thread;
6struct perf_sample;
7int test__arch_unwind_sample(struct perf_sample *sample,
8 struct thread *thread);
9#endif
10
11extern struct test arch_tests[];
12
13#endif
diff --git a/tools/perf/arch/powerpc/include/dwarf-regs-table.h b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..db4730f5585c
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
@@ -0,0 +1,27 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4/*
5 * Reference:
6 * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
7 * http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
8 */
9#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
10
11static const char * const powerpc_regstr_tbl[] = {
12 "%gpr0", "%gpr1", "%gpr2", "%gpr3", "%gpr4",
13 "%gpr5", "%gpr6", "%gpr7", "%gpr8", "%gpr9",
14 "%gpr10", "%gpr11", "%gpr12", "%gpr13", "%gpr14",
15 "%gpr15", "%gpr16", "%gpr17", "%gpr18", "%gpr19",
16 "%gpr20", "%gpr21", "%gpr22", "%gpr23", "%gpr24",
17 "%gpr25", "%gpr26", "%gpr27", "%gpr28", "%gpr29",
18 "%gpr30", "%gpr31",
19 REG_DWARFNUM_NAME(msr, 66),
20 REG_DWARFNUM_NAME(ctr, 109),
21 REG_DWARFNUM_NAME(link, 108),
22 REG_DWARFNUM_NAME(xer, 101),
23 REG_DWARFNUM_NAME(dar, 119),
24 REG_DWARFNUM_NAME(dsisr, 118),
25};
26
27#endif
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
index 75de0e92e71e..c12f4e804f66 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -5,6 +5,8 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8void perf_regs_load(u64 *regs);
9
8#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1) 10#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_POWERPC_MAX 11#define PERF_REGS_MAX PERF_REG_POWERPC_MAX
10#ifdef __powerpc64__ 12#ifdef __powerpc64__
diff --git a/tools/perf/arch/powerpc/tests/Build b/tools/perf/arch/powerpc/tests/Build
new file mode 100644
index 000000000000..d827ef384b33
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/Build
@@ -0,0 +1,4 @@
1libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o
2libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
3
4libperf-y += arch-tests.o
diff --git a/tools/perf/arch/powerpc/tests/arch-tests.c b/tools/perf/arch/powerpc/tests/arch-tests.c
new file mode 100644
index 000000000000..e24f46241f40
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/arch-tests.c
@@ -0,0 +1,15 @@
1#include <string.h>
2#include "tests/tests.h"
3#include "arch-tests.h"
4
5struct test arch_tests[] = {
6#ifdef HAVE_DWARF_UNWIND_SUPPORT
7 {
8 .desc = "Test dwarf unwind",
9 .func = test__dwarf_unwind,
10 },
11#endif
12 {
13 .func = NULL,
14 },
15};
diff --git a/tools/perf/arch/powerpc/tests/dwarf-unwind.c b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
new file mode 100644
index 000000000000..0bac3137ccbd
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
@@ -0,0 +1,62 @@
1#include <string.h>
2#include "perf_regs.h"
3#include "thread.h"
4#include "map.h"
5#include "event.h"
6#include "debug.h"
7#include "tests/tests.h"
8#include "arch-tests.h"
9
10#define STACK_SIZE 8192
11
12static int sample_ustack(struct perf_sample *sample,
13 struct thread *thread, u64 *regs)
14{
15 struct stack_dump *stack = &sample->user_stack;
16 struct map *map;
17 unsigned long sp;
18 u64 stack_size, *buf;
19
20 buf = malloc(STACK_SIZE);
21 if (!buf) {
22 pr_debug("failed to allocate sample uregs data\n");
23 return -1;
24 }
25
26 sp = (unsigned long) regs[PERF_REG_POWERPC_R1];
27
28 map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp);
29 if (!map) {
30 pr_debug("failed to get stack map\n");
31 free(buf);
32 return -1;
33 }
34
35 stack_size = map->end - sp;
36 stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
37
38 memcpy(buf, (void *) sp, stack_size);
39 stack->data = (char *) buf;
40 stack->size = stack_size;
41 return 0;
42}
43
44int test__arch_unwind_sample(struct perf_sample *sample,
45 struct thread *thread)
46{
47 struct regs_dump *regs = &sample->user_regs;
48 u64 *buf;
49
50 buf = calloc(1, sizeof(u64) * PERF_REGS_MAX);
51 if (!buf) {
52 pr_debug("failed to allocate sample uregs data\n");
53 return -1;
54 }
55
56 perf_regs_load(buf);
57 regs->abi = PERF_SAMPLE_REGS_ABI;
58 regs->regs = buf;
59 regs->mask = PERF_REGS_MASK;
60
61 return sample_ustack(sample, thread, buf);
62}
diff --git a/tools/perf/arch/powerpc/tests/regs_load.S b/tools/perf/arch/powerpc/tests/regs_load.S
new file mode 100644
index 000000000000..d76c9a32f327
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/regs_load.S
@@ -0,0 +1,94 @@
1#include <linux/linkage.h>
2
3/* Offset is based on macros from arch/powerpc/include/uapi/asm/ptrace.h. */
4#define R0 0
5#define R1 1 * 8
6#define R2 2 * 8
7#define R3 3 * 8
8#define R4 4 * 8
9#define R5 5 * 8
10#define R6 6 * 8
11#define R7 7 * 8
12#define R8 8 * 8
13#define R9 9 * 8
14#define R10 10 * 8
15#define R11 11 * 8
16#define R12 12 * 8
17#define R13 13 * 8
18#define R14 14 * 8
19#define R15 15 * 8
20#define R16 16 * 8
21#define R17 17 * 8
22#define R18 18 * 8
23#define R19 19 * 8
24#define R20 20 * 8
25#define R21 21 * 8
26#define R22 22 * 8
27#define R23 23 * 8
28#define R24 24 * 8
29#define R25 25 * 8
30#define R26 26 * 8
31#define R27 27 * 8
32#define R28 28 * 8
33#define R29 29 * 8
34#define R30 30 * 8
35#define R31 31 * 8
36#define NIP 32 * 8
37#define CTR 35 * 8
38#define LINK 36 * 8
39#define XER 37 * 8
40
41.globl perf_regs_load
42perf_regs_load:
43 std 0, R0(3)
44 std 1, R1(3)
45 std 2, R2(3)
46 std 3, R3(3)
47 std 4, R4(3)
48 std 5, R5(3)
49 std 6, R6(3)
50 std 7, R7(3)
51 std 8, R8(3)
52 std 9, R9(3)
53 std 10, R10(3)
54 std 11, R11(3)
55 std 12, R12(3)
56 std 13, R13(3)
57 std 14, R14(3)
58 std 15, R15(3)
59 std 16, R16(3)
60 std 17, R17(3)
61 std 18, R18(3)
62 std 19, R19(3)
63 std 20, R20(3)
64 std 21, R21(3)
65 std 22, R22(3)
66 std 23, R23(3)
67 std 24, R24(3)
68 std 25, R25(3)
69 std 26, R26(3)
70 std 27, R27(3)
71 std 28, R28(3)
72 std 29, R29(3)
73 std 30, R30(3)
74 std 31, R31(3)
75
76 /* store NIP */
77 mflr 4
78 std 4, NIP(3)
79
80 /* Store LR */
81 std 4, LINK(3)
82
83 /* Store XER */
84 mfxer 4
85 std 4, XER(3)
86
87 /* Store CTR */
88 mfctr 4
89 std 4, CTR(3)
90
91 /* Restore original value of r4 */
92 ld 4, R4(3)
93
94 blr
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index 35745a733100..ed9d5d15d5b6 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -108,7 +108,7 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
108 int i = 0; 108 int i = 0;
109 109
110 map = get_target_map(pev->target, pev->uprobes); 110 map = get_target_map(pev->target, pev->uprobes);
111 if (!map || map__load(map, NULL) < 0) 111 if (!map || map__load(map) < 0)
112 return; 112 return;
113 113
114 for (i = 0; i < ntevs; i++) { 114 for (i = 0; i < ntevs; i++) {
diff --git a/tools/perf/arch/s390/include/dwarf-regs-table.h b/tools/perf/arch/s390/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..9da74a933bd6
--- /dev/null
+++ b/tools/perf/arch/s390/include/dwarf-regs-table.h
@@ -0,0 +1,8 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const s390_regstr_tbl[] = {
5 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
6 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
7};
8#endif
diff --git a/tools/perf/arch/sh/include/dwarf-regs-table.h b/tools/perf/arch/sh/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..3a2deaf3dab4
--- /dev/null
+++ b/tools/perf/arch/sh/include/dwarf-regs-table.h
@@ -0,0 +1,25 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4const char * const sh_regstr_tbl[] = {
5 "r0",
6 "r1",
7 "r2",
8 "r3",
9 "r4",
10 "r5",
11 "r6",
12 "r7",
13 "r8",
14 "r9",
15 "r10",
16 "r11",
17 "r12",
18 "r13",
19 "r14",
20 "r15",
21 "pc",
22 "pr",
23};
24
25#endif
diff --git a/tools/perf/arch/sparc/include/dwarf-regs-table.h b/tools/perf/arch/sparc/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..12c07619002c
--- /dev/null
+++ b/tools/perf/arch/sparc/include/dwarf-regs-table.h
@@ -0,0 +1,18 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const sparc_regstr_tbl[] = {
5 "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
6 "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
7 "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
8 "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7",
9 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
10 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
11 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
12 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
13 "%f32", "%f33", "%f34", "%f35", "%f36", "%f37", "%f38", "%f39",
14 "%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47",
15 "%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55",
16 "%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63",
17};
18#endif
diff --git a/tools/perf/arch/x86/include/dwarf-regs-table.h b/tools/perf/arch/x86/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..9b5e5cbb4209
--- /dev/null
+++ b/tools/perf/arch/x86/include/dwarf-regs-table.h
@@ -0,0 +1,14 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const x86_32_regstr_tbl[] = {
5 "%ax", "%cx", "%dx", "%bx", "$stack",/* Stack address instead of %sp */
6 "%bp", "%si", "%di",
7};
8
9static const char * const x86_64_regstr_tbl[] = {
10 "%ax", "%dx", "%cx", "%bx", "%si", "%di",
11 "%bp", "%sp", "%r8", "%r9", "%r10", "%r11",
12 "%r12", "%r13", "%r14", "%r15",
13};
14#endif
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index a2412e9d883b..90fa2286edcf 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -62,6 +62,7 @@ struct intel_pt_recording {
62 size_t snapshot_ref_buf_size; 62 size_t snapshot_ref_buf_size;
63 int snapshot_ref_cnt; 63 int snapshot_ref_cnt;
64 struct intel_pt_snapshot_ref *snapshot_refs; 64 struct intel_pt_snapshot_ref *snapshot_refs;
65 size_t priv_size;
65}; 66};
66 67
67static int intel_pt_parse_terms_with_default(struct list_head *formats, 68static int intel_pt_parse_terms_with_default(struct list_head *formats,
@@ -273,11 +274,37 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
273 return attr; 274 return attr;
274} 275}
275 276
277static const char *intel_pt_find_filter(struct perf_evlist *evlist,
278 struct perf_pmu *intel_pt_pmu)
279{
280 struct perf_evsel *evsel;
281
282 evlist__for_each_entry(evlist, evsel) {
283 if (evsel->attr.type == intel_pt_pmu->type)
284 return evsel->filter;
285 }
286
287 return NULL;
288}
289
290static size_t intel_pt_filter_bytes(const char *filter)
291{
292 size_t len = filter ? strlen(filter) : 0;
293
294 return len ? roundup(len + 1, 8) : 0;
295}
296
276static size_t 297static size_t
277intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused, 298intel_pt_info_priv_size(struct auxtrace_record *itr, struct perf_evlist *evlist)
278 struct perf_evlist *evlist __maybe_unused)
279{ 299{
280 return INTEL_PT_AUXTRACE_PRIV_SIZE; 300 struct intel_pt_recording *ptr =
301 container_of(itr, struct intel_pt_recording, itr);
302 const char *filter = intel_pt_find_filter(evlist, ptr->intel_pt_pmu);
303
304 ptr->priv_size = (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64)) +
305 intel_pt_filter_bytes(filter);
306
307 return ptr->priv_size;
281} 308}
282 309
283static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d) 310static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
@@ -302,9 +329,13 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
302 bool cap_user_time_zero = false, per_cpu_mmaps; 329 bool cap_user_time_zero = false, per_cpu_mmaps;
303 u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit; 330 u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
304 u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d; 331 u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
332 unsigned long max_non_turbo_ratio;
333 size_t filter_str_len;
334 const char *filter;
335 u64 *info;
305 int err; 336 int err;
306 337
307 if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE) 338 if (priv_size != ptr->priv_size)
308 return -EINVAL; 339 return -EINVAL;
309 340
310 intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit); 341 intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
@@ -317,6 +348,13 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
317 348
318 intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d); 349 intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d);
319 350
351 if (perf_pmu__scan_file(intel_pt_pmu, "max_nonturbo_ratio",
352 "%lu", &max_non_turbo_ratio) != 1)
353 max_non_turbo_ratio = 0;
354
355 filter = intel_pt_find_filter(session->evlist, ptr->intel_pt_pmu);
356 filter_str_len = filter ? strlen(filter) : 0;
357
320 if (!session->evlist->nr_mmaps) 358 if (!session->evlist->nr_mmaps)
321 return -EINVAL; 359 return -EINVAL;
322 360
@@ -351,6 +389,17 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
351 auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n; 389 auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n;
352 auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d; 390 auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
353 auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit; 391 auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
392 auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO] = max_non_turbo_ratio;
393 auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] = filter_str_len;
394
395 info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
396
397 if (filter_str_len) {
398 size_t len = intel_pt_filter_bytes(filter);
399
400 strncpy((char *)info, filter, len);
401 info += len >> 3;
402 }
354 403
355 return 0; 404 return 0;
356} 405}
diff --git a/tools/perf/arch/xtensa/include/dwarf-regs-table.h b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..aa0444a33fe6
--- /dev/null
+++ b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
@@ -0,0 +1,8 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const xtensa_regstr_tbl[] = {
5 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
6 "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
7};
8#endif
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index f96e22ed9f87..2b9705a8734c 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -16,6 +16,7 @@
16#include <subcmd/parse-options.h> 16#include <subcmd/parse-options.h>
17#include <linux/compiler.h> 17#include <linux/compiler.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/time64.h>
19#include <errno.h> 20#include <errno.h>
20#include "bench.h" 21#include "bench.h"
21#include "futex.h" 22#include "futex.h"
@@ -62,7 +63,7 @@ static void print_summary(void)
62 printf("Requeued %d of %d threads in %.4f ms (+-%.2f%%)\n", 63 printf("Requeued %d of %d threads in %.4f ms (+-%.2f%%)\n",
63 requeued_avg, 64 requeued_avg,
64 nthreads, 65 nthreads,
65 requeuetime_avg/1e3, 66 requeuetime_avg / USEC_PER_MSEC,
66 rel_stddev_stats(requeuetime_stddev, requeuetime_avg)); 67 rel_stddev_stats(requeuetime_stddev, requeuetime_avg));
67} 68}
68 69
@@ -184,7 +185,7 @@ int bench_futex_requeue(int argc, const char **argv,
184 185
185 if (!silent) { 186 if (!silent) {
186 printf("[Run %d]: Requeued %d of %d threads in %.4f ms\n", 187 printf("[Run %d]: Requeued %d of %d threads in %.4f ms\n",
187 j + 1, nrequeued, nthreads, runtime.tv_usec/1e3); 188 j + 1, nrequeued, nthreads, runtime.tv_usec / (double)USEC_PER_MSEC);
188 } 189 }
189 190
190 /* everybody should be blocked on futex2, wake'em up */ 191 /* everybody should be blocked on futex2, wake'em up */
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 4a2ecd7438ca..2c8fa67ad537 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -15,6 +15,7 @@
15#include <subcmd/parse-options.h> 15#include <subcmd/parse-options.h>
16#include <linux/compiler.h> 16#include <linux/compiler.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/time64.h>
18#include <errno.h> 19#include <errno.h>
19#include "bench.h" 20#include "bench.h"
20#include "futex.h" 21#include "futex.h"
@@ -156,7 +157,7 @@ static void print_run(struct thread_data *waking_worker, unsigned int run_num)
156 157
157 printf("[Run %d]: Avg per-thread latency (waking %d/%d threads) " 158 printf("[Run %d]: Avg per-thread latency (waking %d/%d threads) "
158 "in %.4f ms (+-%.2f%%)\n", run_num + 1, wakeup_avg, 159 "in %.4f ms (+-%.2f%%)\n", run_num + 1, wakeup_avg,
159 nblocked_threads, waketime_avg/1e3, 160 nblocked_threads, waketime_avg / USEC_PER_MSEC,
160 rel_stddev_stats(waketime_stddev, waketime_avg)); 161 rel_stddev_stats(waketime_stddev, waketime_avg));
161} 162}
162 163
@@ -172,7 +173,7 @@ static void print_summary(void)
172 printf("Avg per-thread latency (waking %d/%d threads) in %.4f ms (+-%.2f%%)\n", 173 printf("Avg per-thread latency (waking %d/%d threads) in %.4f ms (+-%.2f%%)\n",
173 wakeup_avg, 174 wakeup_avg,
174 nblocked_threads, 175 nblocked_threads,
175 waketime_avg/1e3, 176 waketime_avg / USEC_PER_MSEC,
176 rel_stddev_stats(waketime_stddev, waketime_avg)); 177 rel_stddev_stats(waketime_stddev, waketime_avg));
177} 178}
178 179
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 87d8f4f292d9..e246b1b8388a 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -16,6 +16,7 @@
16#include <subcmd/parse-options.h> 16#include <subcmd/parse-options.h>
17#include <linux/compiler.h> 17#include <linux/compiler.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/time64.h>
19#include <errno.h> 20#include <errno.h>
20#include "bench.h" 21#include "bench.h"
21#include "futex.h" 22#include "futex.h"
@@ -81,7 +82,7 @@ static void print_summary(void)
81 printf("Wokeup %d of %d threads in %.4f ms (+-%.2f%%)\n", 82 printf("Wokeup %d of %d threads in %.4f ms (+-%.2f%%)\n",
82 wakeup_avg, 83 wakeup_avg,
83 nthreads, 84 nthreads,
84 waketime_avg/1e3, 85 waketime_avg / USEC_PER_MSEC,
85 rel_stddev_stats(waketime_stddev, waketime_avg)); 86 rel_stddev_stats(waketime_stddev, waketime_avg));
86} 87}
87 88
@@ -182,7 +183,7 @@ int bench_futex_wake(int argc, const char **argv,
182 183
183 if (!silent) { 184 if (!silent) {
184 printf("[Run %d]: Wokeup %d of %d threads in %.4f ms\n", 185 printf("[Run %d]: Wokeup %d of %d threads in %.4f ms\n",
185 j + 1, nwoken, nthreads, runtime.tv_usec/1e3); 186 j + 1, nwoken, nthreads, runtime.tv_usec / (double)USEC_PER_MSEC);
186 } 187 }
187 188
188 for (i = 0; i < nthreads; i++) { 189 for (i = 0; i < nthreads; i++) {
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index 2b54d0f2672a..c684910e5a48 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -21,6 +21,7 @@
21#include <string.h> 21#include <string.h>
22#include <sys/time.h> 22#include <sys/time.h>
23#include <errno.h> 23#include <errno.h>
24#include <linux/time64.h>
24 25
25#define K 1024 26#define K 1024
26 27
@@ -89,7 +90,7 @@ static u64 get_cycles(void)
89 90
90static double timeval2double(struct timeval *ts) 91static double timeval2double(struct timeval *ts)
91{ 92{
92 return (double)ts->tv_sec + (double)ts->tv_usec / (double)1000000; 93 return (double)ts->tv_sec + (double)ts->tv_usec / (double)USEC_PER_SEC;
93} 94}
94 95
95#define print_bps(x) do { \ 96#define print_bps(x) do { \
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index f7f530081aa9..8efe904e486b 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -30,6 +30,7 @@
30#include <sys/wait.h> 30#include <sys/wait.h>
31#include <sys/prctl.h> 31#include <sys/prctl.h>
32#include <sys/types.h> 32#include <sys/types.h>
33#include <linux/time64.h>
33 34
34#include <numa.h> 35#include <numa.h>
35#include <numaif.h> 36#include <numaif.h>
@@ -1004,7 +1005,7 @@ static void calc_convergence(double runtime_ns_max, double *convergence)
1004 if (strong && process_groups == g->p.nr_proc) { 1005 if (strong && process_groups == g->p.nr_proc) {
1005 if (!*convergence) { 1006 if (!*convergence) {
1006 *convergence = runtime_ns_max; 1007 *convergence = runtime_ns_max;
1007 tprintf(" (%6.1fs converged)\n", *convergence/1e9); 1008 tprintf(" (%6.1fs converged)\n", *convergence / NSEC_PER_SEC);
1008 if (g->p.measure_convergence) { 1009 if (g->p.measure_convergence) {
1009 g->all_converged = true; 1010 g->all_converged = true;
1010 g->stop_work = true; 1011 g->stop_work = true;
@@ -1012,7 +1013,7 @@ static void calc_convergence(double runtime_ns_max, double *convergence)
1012 } 1013 }
1013 } else { 1014 } else {
1014 if (*convergence) { 1015 if (*convergence) {
1015 tprintf(" (%6.1fs de-converged)", runtime_ns_max/1e9); 1016 tprintf(" (%6.1fs de-converged)", runtime_ns_max / NSEC_PER_SEC);
1016 *convergence = 0; 1017 *convergence = 0;
1017 } 1018 }
1018 tprintf("\n"); 1019 tprintf("\n");
@@ -1022,7 +1023,7 @@ static void calc_convergence(double runtime_ns_max, double *convergence)
1022static void show_summary(double runtime_ns_max, int l, double *convergence) 1023static void show_summary(double runtime_ns_max, int l, double *convergence)
1023{ 1024{
1024 tprintf("\r # %5.1f%% [%.1f mins]", 1025 tprintf("\r # %5.1f%% [%.1f mins]",
1025 (double)(l+1)/g->p.nr_loops*100.0, runtime_ns_max/1e9 / 60.0); 1026 (double)(l+1)/g->p.nr_loops*100.0, runtime_ns_max / NSEC_PER_SEC / 60.0);
1026 1027
1027 calc_convergence(runtime_ns_max, convergence); 1028 calc_convergence(runtime_ns_max, convergence);
1028 1029
@@ -1179,8 +1180,8 @@ static void *worker_thread(void *__tdata)
1179 1180
1180 if (details >= 3) { 1181 if (details >= 3) {
1181 timersub(&stop, &start, &diff); 1182 timersub(&stop, &start, &diff);
1182 runtime_ns_max = diff.tv_sec * 1000000000; 1183 runtime_ns_max = diff.tv_sec * NSEC_PER_SEC;
1183 runtime_ns_max += diff.tv_usec * 1000; 1184 runtime_ns_max += diff.tv_usec * NSEC_PER_USEC;
1184 1185
1185 if (details >= 0) { 1186 if (details >= 0) {
1186 printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016"PRIx64"]\n", 1187 printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016"PRIx64"]\n",
@@ -1192,23 +1193,23 @@ static void *worker_thread(void *__tdata)
1192 continue; 1193 continue;
1193 1194
1194 timersub(&stop, &start0, &diff); 1195 timersub(&stop, &start0, &diff);
1195 runtime_ns_max = diff.tv_sec * 1000000000ULL; 1196 runtime_ns_max = diff.tv_sec * NSEC_PER_SEC;
1196 runtime_ns_max += diff.tv_usec * 1000ULL; 1197 runtime_ns_max += diff.tv_usec * NSEC_PER_USEC;
1197 1198
1198 show_summary(runtime_ns_max, l, &convergence); 1199 show_summary(runtime_ns_max, l, &convergence);
1199 } 1200 }
1200 1201
1201 gettimeofday(&stop, NULL); 1202 gettimeofday(&stop, NULL);
1202 timersub(&stop, &start0, &diff); 1203 timersub(&stop, &start0, &diff);
1203 td->runtime_ns = diff.tv_sec * 1000000000ULL; 1204 td->runtime_ns = diff.tv_sec * NSEC_PER_SEC;
1204 td->runtime_ns += diff.tv_usec * 1000ULL; 1205 td->runtime_ns += diff.tv_usec * NSEC_PER_USEC;
1205 td->speed_gbs = bytes_done / (td->runtime_ns / 1e9) / 1e9; 1206 td->speed_gbs = bytes_done / (td->runtime_ns / NSEC_PER_SEC) / 1e9;
1206 1207
1207 getrusage(RUSAGE_THREAD, &rusage); 1208 getrusage(RUSAGE_THREAD, &rusage);
1208 td->system_time_ns = rusage.ru_stime.tv_sec * 1000000000ULL; 1209 td->system_time_ns = rusage.ru_stime.tv_sec * NSEC_PER_SEC;
1209 td->system_time_ns += rusage.ru_stime.tv_usec * 1000ULL; 1210 td->system_time_ns += rusage.ru_stime.tv_usec * NSEC_PER_USEC;
1210 td->user_time_ns = rusage.ru_utime.tv_sec * 1000000000ULL; 1211 td->user_time_ns = rusage.ru_utime.tv_sec * NSEC_PER_SEC;
1211 td->user_time_ns += rusage.ru_utime.tv_usec * 1000ULL; 1212 td->user_time_ns += rusage.ru_utime.tv_usec * NSEC_PER_USEC;
1212 1213
1213 free_data(thread_data, g->p.bytes_thread); 1214 free_data(thread_data, g->p.bytes_thread);
1214 1215
@@ -1469,7 +1470,7 @@ static int __bench_numa(const char *name)
1469 } 1470 }
1470 /* Wait for all the threads to start up: */ 1471 /* Wait for all the threads to start up: */
1471 while (g->nr_tasks_started != g->p.nr_tasks) 1472 while (g->nr_tasks_started != g->p.nr_tasks)
1472 usleep(1000); 1473 usleep(USEC_PER_MSEC);
1473 1474
1474 BUG_ON(g->nr_tasks_started != g->p.nr_tasks); 1475 BUG_ON(g->nr_tasks_started != g->p.nr_tasks);
1475 1476
@@ -1488,9 +1489,9 @@ static int __bench_numa(const char *name)
1488 1489
1489 timersub(&stop, &start, &diff); 1490 timersub(&stop, &start, &diff);
1490 1491
1491 startup_sec = diff.tv_sec * 1000000000.0; 1492 startup_sec = diff.tv_sec * NSEC_PER_SEC;
1492 startup_sec += diff.tv_usec * 1000.0; 1493 startup_sec += diff.tv_usec * NSEC_PER_USEC;
1493 startup_sec /= 1e9; 1494 startup_sec /= NSEC_PER_SEC;
1494 1495
1495 tprintf(" threads initialized in %.6f seconds.\n", startup_sec); 1496 tprintf(" threads initialized in %.6f seconds.\n", startup_sec);
1496 tprintf(" #\n"); 1497 tprintf(" #\n");
@@ -1529,14 +1530,14 @@ static int __bench_numa(const char *name)
1529 tprintf("\n ###\n"); 1530 tprintf("\n ###\n");
1530 tprintf("\n"); 1531 tprintf("\n");
1531 1532
1532 runtime_sec_max = diff.tv_sec * 1000000000.0; 1533 runtime_sec_max = diff.tv_sec * NSEC_PER_SEC;
1533 runtime_sec_max += diff.tv_usec * 1000.0; 1534 runtime_sec_max += diff.tv_usec * NSEC_PER_USEC;
1534 runtime_sec_max /= 1e9; 1535 runtime_sec_max /= NSEC_PER_SEC;
1535 1536
1536 runtime_sec_min = runtime_ns_min/1e9; 1537 runtime_sec_min = runtime_ns_min / NSEC_PER_SEC;
1537 1538
1538 bytes = g->bytes_done; 1539 bytes = g->bytes_done;
1539 runtime_avg = (double)runtime_ns_sum / g->p.nr_tasks / 1e9; 1540 runtime_avg = (double)runtime_ns_sum / g->p.nr_tasks / NSEC_PER_SEC;
1540 1541
1541 if (g->p.measure_convergence) { 1542 if (g->p.measure_convergence) {
1542 print_res(name, runtime_sec_max, 1543 print_res(name, runtime_sec_max,
@@ -1562,7 +1563,7 @@ static int __bench_numa(const char *name)
1562 print_res(name, bytes / 1e9, 1563 print_res(name, bytes / 1e9,
1563 "GB,", "data-total", "GB data processed, total"); 1564 "GB,", "data-total", "GB data processed, total");
1564 1565
1565 print_res(name, runtime_sec_max * 1e9 / (bytes / g->p.nr_tasks), 1566 print_res(name, runtime_sec_max * NSEC_PER_SEC / (bytes / g->p.nr_tasks),
1566 "nsecs,", "runtime/byte/thread","nsecs/byte/thread runtime"); 1567 "nsecs,", "runtime/byte/thread","nsecs/byte/thread runtime");
1567 1568
1568 print_res(name, bytes / g->p.nr_tasks / 1e9 / runtime_sec_max, 1569 print_res(name, bytes / g->p.nr_tasks / 1e9 / runtime_sec_max,
@@ -1581,9 +1582,9 @@ static int __bench_numa(const char *name)
1581 snprintf(tname, 32, "process%d:thread%d", p, t); 1582 snprintf(tname, 32, "process%d:thread%d", p, t);
1582 print_res(tname, td->speed_gbs, 1583 print_res(tname, td->speed_gbs,
1583 "GB/sec", "thread-speed", "GB/sec/thread speed"); 1584 "GB/sec", "thread-speed", "GB/sec/thread speed");
1584 print_res(tname, td->system_time_ns / 1e9, 1585 print_res(tname, td->system_time_ns / NSEC_PER_SEC,
1585 "secs", "thread-system-time", "system CPU time/thread"); 1586 "secs", "thread-system-time", "system CPU time/thread");
1586 print_res(tname, td->user_time_ns / 1e9, 1587 print_res(tname, td->user_time_ns / NSEC_PER_SEC,
1587 "secs", "thread-user-time", "user CPU time/thread"); 1588 "secs", "thread-user-time", "user CPU time/thread");
1588 } 1589 }
1589 } 1590 }
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index bfaf9503de8e..6a111e775210 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -29,6 +29,7 @@
29#include <poll.h> 29#include <poll.h>
30#include <limits.h> 30#include <limits.h>
31#include <err.h> 31#include <err.h>
32#include <linux/time64.h>
32 33
33#define DATASIZE 100 34#define DATASIZE 100
34 35
@@ -312,11 +313,11 @@ int bench_sched_messaging(int argc, const char **argv,
312 thread_mode ? "threads" : "processes"); 313 thread_mode ? "threads" : "processes");
313 printf(" %14s: %lu.%03lu [sec]\n", "Total time", 314 printf(" %14s: %lu.%03lu [sec]\n", "Total time",
314 diff.tv_sec, 315 diff.tv_sec,
315 (unsigned long) (diff.tv_usec/1000)); 316 (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
316 break; 317 break;
317 case BENCH_FORMAT_SIMPLE: 318 case BENCH_FORMAT_SIMPLE:
318 printf("%lu.%03lu\n", diff.tv_sec, 319 printf("%lu.%03lu\n", diff.tv_sec,
319 (unsigned long) (diff.tv_usec/1000)); 320 (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
320 break; 321 break;
321 default: 322 default:
322 /* reaching here is something disaster */ 323 /* reaching here is something disaster */
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 1dc2d13cc272..2243f0150d76 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -25,6 +25,7 @@
25#include <sys/time.h> 25#include <sys/time.h>
26#include <sys/types.h> 26#include <sys/types.h>
27#include <sys/syscall.h> 27#include <sys/syscall.h>
28#include <linux/time64.h>
28 29
29#include <pthread.h> 30#include <pthread.h>
30 31
@@ -153,24 +154,24 @@ int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unu
153 printf("# Executed %d pipe operations between two %s\n\n", 154 printf("# Executed %d pipe operations between two %s\n\n",
154 loops, threaded ? "threads" : "processes"); 155 loops, threaded ? "threads" : "processes");
155 156
156 result_usec = diff.tv_sec * 1000000; 157 result_usec = diff.tv_sec * USEC_PER_SEC;
157 result_usec += diff.tv_usec; 158 result_usec += diff.tv_usec;
158 159
159 printf(" %14s: %lu.%03lu [sec]\n\n", "Total time", 160 printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
160 diff.tv_sec, 161 diff.tv_sec,
161 (unsigned long) (diff.tv_usec/1000)); 162 (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
162 163
163 printf(" %14lf usecs/op\n", 164 printf(" %14lf usecs/op\n",
164 (double)result_usec / (double)loops); 165 (double)result_usec / (double)loops);
165 printf(" %14d ops/sec\n", 166 printf(" %14d ops/sec\n",
166 (int)((double)loops / 167 (int)((double)loops /
167 ((double)result_usec / (double)1000000))); 168 ((double)result_usec / (double)USEC_PER_SEC)));
168 break; 169 break;
169 170
170 case BENCH_FORMAT_SIMPLE: 171 case BENCH_FORMAT_SIMPLE:
171 printf("%lu.%03lu\n", 172 printf("%lu.%03lu\n",
172 diff.tv_sec, 173 diff.tv_sec,
173 (unsigned long) (diff.tv_usec / 1000)); 174 (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
174 break; 175 break;
175 176
176 default: 177 default:
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 9c1034d81b4f..ebb628332a6e 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -30,6 +30,7 @@
30#include "util/tool.h" 30#include "util/tool.h"
31#include "util/data.h" 31#include "util/data.h"
32#include "arch/common.h" 32#include "arch/common.h"
33#include "util/block-range.h"
33 34
34#include <dlfcn.h> 35#include <dlfcn.h>
35#include <linux/bitmap.h> 36#include <linux/bitmap.h>
@@ -46,6 +47,103 @@ struct perf_annotate {
46 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 47 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
47}; 48};
48 49
50/*
51 * Given one basic block:
52 *
53 * from to branch_i
54 * * ----> *
55 * |
56 * | block
57 * v
58 * * ----> *
59 * from to branch_i+1
60 *
61 * where the horizontal are the branches and the vertical is the executed
62 * block of instructions.
63 *
64 * We count, for each 'instruction', the number of blocks that covered it as
65 * well as count the ratio each branch is taken.
66 *
67 * We can do this without knowing the actual instruction stream by keeping
68 * track of the address ranges. We break down ranges such that there is no
69 * overlap and iterate from the start until the end.
70 *
71 * @acme: once we parse the objdump output _before_ processing the samples,
72 * we can easily fold the branch.cycles IPC bits in.
73 */
74static void process_basic_block(struct addr_map_symbol *start,
75 struct addr_map_symbol *end,
76 struct branch_flags *flags)
77{
78 struct symbol *sym = start->sym;
79 struct annotation *notes = sym ? symbol__annotation(sym) : NULL;
80 struct block_range_iter iter;
81 struct block_range *entry;
82
83 /*
84 * Sanity; NULL isn't executable and the CPU cannot execute backwards
85 */
86 if (!start->addr || start->addr > end->addr)
87 return;
88
89 iter = block_range__create(start->addr, end->addr);
90 if (!block_range_iter__valid(&iter))
91 return;
92
93 /*
94 * First block in range is a branch target.
95 */
96 entry = block_range_iter(&iter);
97 assert(entry->is_target);
98 entry->entry++;
99
100 do {
101 entry = block_range_iter(&iter);
102
103 entry->coverage++;
104 entry->sym = sym;
105
106 if (notes)
107 notes->max_coverage = max(notes->max_coverage, entry->coverage);
108
109 } while (block_range_iter__next(&iter));
110
111 /*
112 * Last block in rage is a branch.
113 */
114 entry = block_range_iter(&iter);
115 assert(entry->is_branch);
116 entry->taken++;
117 if (flags->predicted)
118 entry->pred++;
119}
120
121static void process_branch_stack(struct branch_stack *bs, struct addr_location *al,
122 struct perf_sample *sample)
123{
124 struct addr_map_symbol *prev = NULL;
125 struct branch_info *bi;
126 int i;
127
128 if (!bs || !bs->nr)
129 return;
130
131 bi = sample__resolve_bstack(sample, al);
132 if (!bi)
133 return;
134
135 for (i = bs->nr - 1; i >= 0; i--) {
136 /*
137 * XXX filter against symbol
138 */
139 if (prev)
140 process_basic_block(prev, &bi[i].from, &bi[i].flags);
141 prev = &bi[i].to;
142 }
143
144 free(bi);
145}
146
49static int perf_evsel__add_sample(struct perf_evsel *evsel, 147static int perf_evsel__add_sample(struct perf_evsel *evsel,
50 struct perf_sample *sample, 148 struct perf_sample *sample,
51 struct addr_location *al, 149 struct addr_location *al,
@@ -72,6 +170,12 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
72 return 0; 170 return 0;
73 } 171 }
74 172
173 /*
174 * XXX filtered samples can still have branch entires pointing into our
175 * symbol and are missed.
176 */
177 process_branch_stack(sample->branch_stack, al, sample);
178
75 sample->period = 1; 179 sample->period = 1;
76 sample->weight = 1; 180 sample->weight = 1;
77 181
@@ -204,8 +308,6 @@ static int __cmd_annotate(struct perf_annotate *ann)
204 struct perf_evsel *pos; 308 struct perf_evsel *pos;
205 u64 total_nr_samples; 309 u64 total_nr_samples;
206 310
207 machines__set_symbol_filter(&session->machines, symbol__annotate_init);
208
209 if (ann->cpu_list) { 311 if (ann->cpu_list) {
210 ret = perf_session__cpu_bitmap(session, ann->cpu_list, 312 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
211 ann->cpu_bitmap); 313 ann->cpu_bitmap);
@@ -367,7 +469,10 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
367 if (annotate.session == NULL) 469 if (annotate.session == NULL)
368 return -1; 470 return -1;
369 471
370 symbol_conf.priv_size = sizeof(struct annotation); 472 ret = symbol__annotation_init();
473 if (ret < 0)
474 goto out_delete;
475
371 symbol_conf.try_vmlinux_path = true; 476 symbol_conf.try_vmlinux_path = true;
372 477
373 ret = symbol__init(&annotate.session->header.env); 478 ret = symbol__init(&annotate.session->header.env);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 21ee753211ad..9ff0db4e2d0c 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -1033,7 +1033,9 @@ static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
1033} 1033}
1034 1034
1035static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1035static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1036 struct hists *hists __maybe_unused) 1036 struct hists *hists __maybe_unused,
1037 int line __maybe_unused,
1038 int *span __maybe_unused)
1037{ 1039{
1038 struct diff_hpp_fmt *dfmt = 1040 struct diff_hpp_fmt *dfmt =
1039 container_of(fmt, struct diff_hpp_fmt, fmt); 1041 container_of(fmt, struct diff_hpp_fmt, fmt);
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 73c1c4cc3600..b9bc7e39833a 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -429,7 +429,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
429 if (al.map != NULL) { 429 if (al.map != NULL) {
430 if (!al.map->dso->hit) { 430 if (!al.map->dso->hit) {
431 al.map->dso->hit = 1; 431 al.map->dso->hit = 1;
432 if (map__load(al.map, NULL) >= 0) { 432 if (map__load(al.map) >= 0) {
433 dso__inject_build_id(al.map->dso, tool, machine); 433 dso__inject_build_id(al.map->dso, tool, machine);
434 /* 434 /*
435 * If this fails, too bad, let the other side 435 * If this fails, too bad, let the other side
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index fdde1bd3e306..d426dcb18ce9 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -330,7 +330,7 @@ static int build_alloc_func_list(void)
330 } 330 }
331 331
332 kernel_map = machine__kernel_map(machine); 332 kernel_map = machine__kernel_map(machine);
333 if (map__load(kernel_map, NULL) < 0) { 333 if (map__load(kernel_map) < 0) {
334 pr_err("cannot load kernel map\n"); 334 pr_err("cannot load kernel map\n");
335 return -ENOENT; 335 return -ENOENT;
336 } 336 }
@@ -979,7 +979,7 @@ static void __print_slab_result(struct rb_root *root,
979 if (is_caller) { 979 if (is_caller) {
980 addr = data->call_site; 980 addr = data->call_site;
981 if (!raw_ip) 981 if (!raw_ip)
982 sym = machine__find_kernel_function(machine, addr, &map, NULL); 982 sym = machine__find_kernel_function(machine, addr, &map);
983 } else 983 } else
984 addr = data->ptr; 984 addr = data->ptr;
985 985
@@ -1043,8 +1043,7 @@ static void __print_page_alloc_result(struct perf_session *session, int n_lines)
1043 char *caller = buf; 1043 char *caller = buf;
1044 1044
1045 data = rb_entry(next, struct page_stat, node); 1045 data = rb_entry(next, struct page_stat, node);
1046 sym = machine__find_kernel_function(machine, data->callsite, 1046 sym = machine__find_kernel_function(machine, data->callsite, &map);
1047 &map, NULL);
1048 if (sym && sym->name) 1047 if (sym && sym->name)
1049 caller = sym->name; 1048 caller = sym->name;
1050 else 1049 else
@@ -1086,8 +1085,7 @@ static void __print_page_caller_result(struct perf_session *session, int n_lines
1086 char *caller = buf; 1085 char *caller = buf;
1087 1086
1088 data = rb_entry(next, struct page_stat, node); 1087 data = rb_entry(next, struct page_stat, node);
1089 sym = machine__find_kernel_function(machine, data->callsite, 1088 sym = machine__find_kernel_function(machine, data->callsite, &map);
1090 &map, NULL);
1091 if (sym && sym->name) 1089 if (sym && sym->name)
1092 caller = sym->name; 1090 caller = sym->name;
1093 else 1091 else
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 5e2127e04f83..08fa88f62a24 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -24,6 +24,7 @@
24#include <sys/timerfd.h> 24#include <sys/timerfd.h>
25#endif 25#endif
26 26
27#include <linux/time64.h>
27#include <termios.h> 28#include <termios.h>
28#include <semaphore.h> 29#include <semaphore.h>
29#include <pthread.h> 30#include <pthread.h>
@@ -362,7 +363,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
362 if (!skip_event(decode)) { 363 if (!skip_event(decode)) {
363 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n", 364 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n",
364 sample->time, sample->pid, vcpu_record->vcpu_id, 365 sample->time, sample->pid, vcpu_record->vcpu_id,
365 decode, time_diff/1000); 366 decode, time_diff / NSEC_PER_USEC);
366 } 367 }
367 } 368 }
368 369
@@ -608,15 +609,15 @@ static void print_result(struct perf_kvm_stat *kvm)
608 pr_info("%10llu ", (unsigned long long)ecount); 609 pr_info("%10llu ", (unsigned long long)ecount);
609 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 610 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
610 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); 611 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
611 pr_info("%9.2fus ", (double)min / 1e3); 612 pr_info("%9.2fus ", (double)min / NSEC_PER_USEC);
612 pr_info("%9.2fus ", (double)max / 1e3); 613 pr_info("%9.2fus ", (double)max / NSEC_PER_USEC);
613 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, 614 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount / NSEC_PER_USEC,
614 kvm_event_rel_stddev(vcpu, event)); 615 kvm_event_rel_stddev(vcpu, event));
615 pr_info("\n"); 616 pr_info("\n");
616 } 617 }
617 618
618 pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n", 619 pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
619 kvm->total_count, kvm->total_time / 1e3); 620 kvm->total_count, kvm->total_time / (double)NSEC_PER_USEC);
620 621
621 if (kvm->lost_events) 622 if (kvm->lost_events)
622 pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events); 623 pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index ee5b42173ba3..f87996b0cb29 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -326,6 +326,11 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
326 if (ret < 0) 326 if (ret < 0)
327 goto out_cleanup; 327 goto out_cleanup;
328 328
329 if (params.command == 'D') { /* it shows definition */
330 ret = show_probe_trace_events(pevs, npevs);
331 goto out_cleanup;
332 }
333
329 ret = apply_perf_probe_events(pevs, npevs); 334 ret = apply_perf_probe_events(pevs, npevs);
330 if (ret < 0) 335 if (ret < 0)
331 goto out_cleanup; 336 goto out_cleanup;
@@ -454,6 +459,14 @@ out:
454 return ret; 459 return ret;
455} 460}
456 461
462#ifdef HAVE_DWARF_SUPPORT
463#define PROBEDEF_STR \
464 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT [[NAME=]ARG ...]"
465#else
466#define PROBEDEF_STR "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]"
467#endif
468
469
457static int 470static int
458__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) 471__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
459{ 472{
@@ -479,13 +492,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
479 opt_set_filter_with_command, DEFAULT_LIST_FILTER), 492 opt_set_filter_with_command, DEFAULT_LIST_FILTER),
480 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 493 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
481 opt_set_filter_with_command), 494 opt_set_filter_with_command),
482 OPT_CALLBACK('a', "add", NULL, 495 OPT_CALLBACK('a', "add", NULL, PROBEDEF_STR,
483#ifdef HAVE_DWARF_SUPPORT
484 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
485 " [[NAME=]ARG ...]",
486#else
487 "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
488#endif
489 "probe point definition, where\n" 496 "probe point definition, where\n"
490 "\t\tGROUP:\tGroup name (optional)\n" 497 "\t\tGROUP:\tGroup name (optional)\n"
491 "\t\tEVENT:\tEvent name\n" 498 "\t\tEVENT:\tEvent name\n"
@@ -503,6 +510,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
503 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n", 510 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
504#endif 511#endif
505 opt_add_probe_event), 512 opt_add_probe_event),
513 OPT_CALLBACK('D', "definition", NULL, PROBEDEF_STR,
514 "Show trace event definition of given traceevent for k/uprobe_events.",
515 opt_add_probe_event),
506 OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events" 516 OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
507 " with existing name"), 517 " with existing name"),
508 OPT_CALLBACK('L', "line", NULL, 518 OPT_CALLBACK('L', "line", NULL,
@@ -548,6 +558,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
548 558
549 set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE); 559 set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
550 set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE); 560 set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
561 set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE);
551 set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE); 562 set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
552#ifdef HAVE_DWARF_SUPPORT 563#ifdef HAVE_DWARF_SUPPORT
553 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE); 564 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
@@ -600,6 +611,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
600 */ 611 */
601 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 612 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
602 613
614 /*
615 * Except for --list, --del and --add, other command doesn't depend
616 * nor change running kernel. So if user gives offline vmlinux,
617 * ignore its buildid.
618 */
619 if (!strchr("lda", params.command) && symbol_conf.vmlinux_name)
620 symbol_conf.ignore_vmlinux_buildid = true;
621
603 switch (params.command) { 622 switch (params.command) {
604 case 'l': 623 case 'l':
605 if (params.uprobes) { 624 if (params.uprobes) {
@@ -643,7 +662,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
643 return ret; 662 return ret;
644 } 663 }
645 break; 664 break;
665 case 'D':
646 case 'a': 666 case 'a':
667
647 /* Ensure the last given target is used */ 668 /* Ensure the last given target is used */
648 if (params.target && !params.target_used) { 669 if (params.target && !params.target_used) {
649 pr_err(" Error: -x/-m must follow the probe definitions.\n"); 670 pr_err(" Error: -x/-m must follow the probe definitions.\n");
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6355902fbfc8..67d2a9003294 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -22,6 +22,7 @@
22#include "util/evlist.h" 22#include "util/evlist.h"
23#include "util/evsel.h" 23#include "util/evsel.h"
24#include "util/debug.h" 24#include "util/debug.h"
25#include "util/drv_configs.h"
25#include "util/session.h" 26#include "util/session.h"
26#include "util/tool.h" 27#include "util/tool.h"
27#include "util/symbol.h" 28#include "util/symbol.h"
@@ -42,7 +43,7 @@
42#include <sched.h> 43#include <sched.h>
43#include <sys/mman.h> 44#include <sys/mman.h>
44#include <asm/bug.h> 45#include <asm/bug.h>
45 46#include <linux/time64.h>
46 47
47struct record { 48struct record {
48 struct perf_tool tool; 49 struct perf_tool tool;
@@ -96,7 +97,7 @@ backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
96 *start = head; 97 *start = head;
97 while (true) { 98 while (true) {
98 if (evt_head - head >= (unsigned int)size) { 99 if (evt_head - head >= (unsigned int)size) {
99 pr_debug("Finshed reading backward ring buffer: rewind\n"); 100 pr_debug("Finished reading backward ring buffer: rewind\n");
100 if (evt_head - head > (unsigned int)size) 101 if (evt_head - head > (unsigned int)size)
101 evt_head -= pheader->size; 102 evt_head -= pheader->size;
102 *end = evt_head; 103 *end = evt_head;
@@ -106,7 +107,7 @@ backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
106 pheader = (struct perf_event_header *)(buf + (evt_head & mask)); 107 pheader = (struct perf_event_header *)(buf + (evt_head & mask));
107 108
108 if (pheader->size == 0) { 109 if (pheader->size == 0) {
109 pr_debug("Finshed reading backward ring buffer: get start\n"); 110 pr_debug("Finished reading backward ring buffer: get start\n");
110 *end = evt_head; 111 *end = evt_head;
111 return 0; 112 return 0;
112 } 113 }
@@ -383,6 +384,7 @@ static int record__open(struct record *rec)
383 struct perf_evlist *evlist = rec->evlist; 384 struct perf_evlist *evlist = rec->evlist;
384 struct perf_session *session = rec->session; 385 struct perf_session *session = rec->session;
385 struct record_opts *opts = &rec->opts; 386 struct record_opts *opts = &rec->opts;
387 struct perf_evsel_config_term *err_term;
386 int rc = 0; 388 int rc = 0;
387 389
388 perf_evlist__config(evlist, opts, &callchain_param); 390 perf_evlist__config(evlist, opts, &callchain_param);
@@ -412,6 +414,14 @@ try_again:
412 goto out; 414 goto out;
413 } 415 }
414 416
417 if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) {
418 error("failed to set config \"%s\" on event %s with %d (%s)\n",
419 err_term->val.drv_cfg, perf_evsel__name(pos), errno,
420 str_error_r(errno, msg, sizeof(msg)));
421 rc = -1;
422 goto out;
423 }
424
415 rc = record__mmap(rec); 425 rc = record__mmap(rec);
416 if (rc) 426 if (rc)
417 goto out; 427 goto out;
@@ -954,7 +964,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
954 } 964 }
955 965
956 if (opts->initial_delay) { 966 if (opts->initial_delay) {
957 usleep(opts->initial_delay * 1000); 967 usleep(opts->initial_delay * USEC_PER_MSEC);
958 perf_evlist__enable(rec->evlist); 968 perf_evlist__enable(rec->evlist);
959 } 969 }
960 970
@@ -1563,29 +1573,39 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1563 if (!rec->itr) { 1573 if (!rec->itr) {
1564 rec->itr = auxtrace_record__init(rec->evlist, &err); 1574 rec->itr = auxtrace_record__init(rec->evlist, &err);
1565 if (err) 1575 if (err)
1566 return err; 1576 goto out;
1567 } 1577 }
1568 1578
1569 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 1579 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
1570 rec->opts.auxtrace_snapshot_opts); 1580 rec->opts.auxtrace_snapshot_opts);
1571 if (err) 1581 if (err)
1572 return err; 1582 goto out;
1583
1584 /*
1585 * Allow aliases to facilitate the lookup of symbols for address
1586 * filters. Refer to auxtrace_parse_filters().
1587 */
1588 symbol_conf.allow_aliases = true;
1589
1590 symbol__init(NULL);
1591
1592 err = auxtrace_parse_filters(rec->evlist);
1593 if (err)
1594 goto out;
1573 1595
1574 if (dry_run) 1596 if (dry_run)
1575 return 0; 1597 goto out;
1576 1598
1577 err = bpf__setup_stdout(rec->evlist); 1599 err = bpf__setup_stdout(rec->evlist);
1578 if (err) { 1600 if (err) {
1579 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 1601 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1580 pr_err("ERROR: Setup BPF stdout failed: %s\n", 1602 pr_err("ERROR: Setup BPF stdout failed: %s\n",
1581 errbuf); 1603 errbuf);
1582 return err; 1604 goto out;
1583 } 1605 }
1584 1606
1585 err = -ENOMEM; 1607 err = -ENOMEM;
1586 1608
1587 symbol__init(NULL);
1588
1589 if (symbol_conf.kptr_restrict) 1609 if (symbol_conf.kptr_restrict)
1590 pr_warning( 1610 pr_warning(
1591"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1611"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
@@ -1633,7 +1653,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1633 if (rec->evlist->nr_entries == 0 && 1653 if (rec->evlist->nr_entries == 0 &&
1634 perf_evlist__add_default(rec->evlist) < 0) { 1654 perf_evlist__add_default(rec->evlist) < 0) {
1635 pr_err("Not enough memory for event selector list\n"); 1655 pr_err("Not enough memory for event selector list\n");
1636 goto out_symbol_exit; 1656 goto out;
1637 } 1657 }
1638 1658
1639 if (rec->opts.target.tid && !rec->opts.no_inherit_set) 1659 if (rec->opts.target.tid && !rec->opts.no_inherit_set)
@@ -1653,7 +1673,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1653 ui__error("%s", errbuf); 1673 ui__error("%s", errbuf);
1654 1674
1655 err = -saved_errno; 1675 err = -saved_errno;
1656 goto out_symbol_exit; 1676 goto out;
1657 } 1677 }
1658 1678
1659 err = -ENOMEM; 1679 err = -ENOMEM;
@@ -1662,7 +1682,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1662 1682
1663 err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1683 err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1664 if (err) 1684 if (err)
1665 goto out_symbol_exit; 1685 goto out;
1666 1686
1667 /* 1687 /*
1668 * We take all buildids when the file contains 1688 * We take all buildids when the file contains
@@ -1674,11 +1694,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1674 1694
1675 if (record_opts__config(&rec->opts)) { 1695 if (record_opts__config(&rec->opts)) {
1676 err = -EINVAL; 1696 err = -EINVAL;
1677 goto out_symbol_exit; 1697 goto out;
1678 } 1698 }
1679 1699
1680 err = __cmd_record(&record, argc, argv); 1700 err = __cmd_record(&record, argc, argv);
1681out_symbol_exit: 1701out:
1682 perf_evlist__delete(rec->evlist); 1702 perf_evlist__delete(rec->evlist);
1683 symbol__exit(); 1703 symbol__exit();
1684 auxtrace_record__free(rec->itr); 1704 auxtrace_record__free(rec->itr);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 949e5a15c960..6e88460cd13d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -89,6 +89,10 @@ static int report__config(const char *var, const char *value, void *cb)
89 rep->queue_size = perf_config_u64(var, value); 89 rep->queue_size = perf_config_u64(var, value);
90 return 0; 90 return 0;
91 } 91 }
92 if (!strcmp(var, "report.sort_order")) {
93 default_sort_order = strdup(value);
94 return 0;
95 }
92 96
93 return 0; 97 return 0;
94} 98}
@@ -931,7 +935,6 @@ repeat:
931 935
932 if (symbol_conf.report_hierarchy) { 936 if (symbol_conf.report_hierarchy) {
933 /* disable incompatible options */ 937 /* disable incompatible options */
934 symbol_conf.event_group = false;
935 symbol_conf.cumulate_callchain = false; 938 symbol_conf.cumulate_callchain = false;
936 939
937 if (field_order) { 940 if (field_order) {
@@ -980,9 +983,9 @@ repeat:
980 * implementation. 983 * implementation.
981 */ 984 */
982 if (ui__has_annotation()) { 985 if (ui__has_annotation()) {
983 symbol_conf.priv_size = sizeof(struct annotation); 986 ret = symbol__annotation_init();
984 machines__set_symbol_filter(&session->machines, 987 if (ret < 0)
985 symbol__annotate_init); 988 goto error;
986 /* 989 /*
987 * For searching by name on the "Browse map details". 990 * For searching by name on the "Browse map details".
988 * providing it only in verbose mode not to bloat too 991 * providing it only in verbose mode not to bloat too
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 0dfe8df2ab9b..f5503ca22e1c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -26,6 +26,7 @@
26#include <pthread.h> 26#include <pthread.h>
27#include <math.h> 27#include <math.h>
28#include <api/fs/fs.h> 28#include <api/fs/fs.h>
29#include <linux/time64.h>
29 30
30#define PR_SET_NAME 15 /* Set process name */ 31#define PR_SET_NAME 15 /* Set process name */
31#define MAX_CPUS 4096 32#define MAX_CPUS 4096
@@ -199,7 +200,7 @@ static u64 get_nsecs(void)
199 200
200 clock_gettime(CLOCK_MONOTONIC, &ts); 201 clock_gettime(CLOCK_MONOTONIC, &ts);
201 202
202 return ts.tv_sec * 1000000000ULL + ts.tv_nsec; 203 return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
203} 204}
204 205
205static void burn_nsecs(struct perf_sched *sched, u64 nsecs) 206static void burn_nsecs(struct perf_sched *sched, u64 nsecs)
@@ -223,7 +224,7 @@ static void sleep_nsecs(u64 nsecs)
223 224
224static void calibrate_run_measurement_overhead(struct perf_sched *sched) 225static void calibrate_run_measurement_overhead(struct perf_sched *sched)
225{ 226{
226 u64 T0, T1, delta, min_delta = 1000000000ULL; 227 u64 T0, T1, delta, min_delta = NSEC_PER_SEC;
227 int i; 228 int i;
228 229
229 for (i = 0; i < 10; i++) { 230 for (i = 0; i < 10; i++) {
@@ -240,7 +241,7 @@ static void calibrate_run_measurement_overhead(struct perf_sched *sched)
240 241
241static void calibrate_sleep_measurement_overhead(struct perf_sched *sched) 242static void calibrate_sleep_measurement_overhead(struct perf_sched *sched)
242{ 243{
243 u64 T0, T1, delta, min_delta = 1000000000ULL; 244 u64 T0, T1, delta, min_delta = NSEC_PER_SEC;
244 int i; 245 int i;
245 246
246 for (i = 0; i < 10; i++) { 247 for (i = 0; i < 10; i++) {
@@ -452,8 +453,8 @@ static u64 get_cpu_usage_nsec_parent(void)
452 err = getrusage(RUSAGE_SELF, &ru); 453 err = getrusage(RUSAGE_SELF, &ru);
453 BUG_ON(err); 454 BUG_ON(err);
454 455
455 sum = ru.ru_utime.tv_sec*1e9 + ru.ru_utime.tv_usec*1e3; 456 sum = ru.ru_utime.tv_sec * NSEC_PER_SEC + ru.ru_utime.tv_usec * NSEC_PER_USEC;
456 sum += ru.ru_stime.tv_sec*1e9 + ru.ru_stime.tv_usec*1e3; 457 sum += ru.ru_stime.tv_sec * NSEC_PER_SEC + ru.ru_stime.tv_usec * NSEC_PER_USEC;
457 458
458 return sum; 459 return sum;
459} 460}
@@ -667,12 +668,12 @@ static void run_one_test(struct perf_sched *sched)
667 sched->run_avg = delta; 668 sched->run_avg = delta;
668 sched->run_avg = (sched->run_avg * (sched->replay_repeat - 1) + delta) / sched->replay_repeat; 669 sched->run_avg = (sched->run_avg * (sched->replay_repeat - 1) + delta) / sched->replay_repeat;
669 670
670 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0); 671 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / NSEC_PER_MSEC);
671 672
672 printf("ravg: %0.2f, ", (double)sched->run_avg / 1e6); 673 printf("ravg: %0.2f, ", (double)sched->run_avg / NSEC_PER_MSEC);
673 674
674 printf("cpu: %0.2f / %0.2f", 675 printf("cpu: %0.2f / %0.2f",
675 (double)sched->cpu_usage / 1e6, (double)sched->runavg_cpu_usage / 1e6); 676 (double)sched->cpu_usage / NSEC_PER_MSEC, (double)sched->runavg_cpu_usage / NSEC_PER_MSEC);
676 677
677#if 0 678#if 0
678 /* 679 /*
@@ -680,8 +681,8 @@ static void run_one_test(struct perf_sched *sched)
680 * accurate than the sched->sum_exec_runtime based statistics: 681 * accurate than the sched->sum_exec_runtime based statistics:
681 */ 682 */
682 printf(" [%0.2f / %0.2f]", 683 printf(" [%0.2f / %0.2f]",
683 (double)sched->parent_cpu_usage/1e6, 684 (double)sched->parent_cpu_usage / NSEC_PER_MSEC,
684 (double)sched->runavg_parent_cpu_usage/1e6); 685 (double)sched->runavg_parent_cpu_usage / NSEC_PER_MSEC);
685#endif 686#endif
686 687
687 printf("\n"); 688 printf("\n");
@@ -696,13 +697,13 @@ static void test_calibrations(struct perf_sched *sched)
696 u64 T0, T1; 697 u64 T0, T1;
697 698
698 T0 = get_nsecs(); 699 T0 = get_nsecs();
699 burn_nsecs(sched, 1e6); 700 burn_nsecs(sched, NSEC_PER_MSEC);
700 T1 = get_nsecs(); 701 T1 = get_nsecs();
701 702
702 printf("the run test took %" PRIu64 " nsecs\n", T1 - T0); 703 printf("the run test took %" PRIu64 " nsecs\n", T1 - T0);
703 704
704 T0 = get_nsecs(); 705 T0 = get_nsecs();
705 sleep_nsecs(1e6); 706 sleep_nsecs(NSEC_PER_MSEC);
706 T1 = get_nsecs(); 707 T1 = get_nsecs();
707 708
708 printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0); 709 printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0);
@@ -1213,10 +1214,10 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1213 avg = work_list->total_lat / work_list->nb_atoms; 1214 avg = work_list->total_lat / work_list->nb_atoms;
1214 1215
1215 printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %13.6f s\n", 1216 printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %13.6f s\n",
1216 (double)work_list->total_runtime / 1e6, 1217 (double)work_list->total_runtime / NSEC_PER_MSEC,
1217 work_list->nb_atoms, (double)avg / 1e6, 1218 work_list->nb_atoms, (double)avg / NSEC_PER_MSEC,
1218 (double)work_list->max_lat / 1e6, 1219 (double)work_list->max_lat / NSEC_PER_MSEC,
1219 (double)work_list->max_lat_at / 1e9); 1220 (double)work_list->max_lat_at / NSEC_PER_SEC);
1220} 1221}
1221 1222
1222static int pid_cmp(struct work_atoms *l, struct work_atoms *r) 1223static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
@@ -1491,7 +1492,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1491 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu)) 1492 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu))
1492 goto out; 1493 goto out;
1493 1494
1494 color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9); 1495 color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp / NSEC_PER_SEC);
1495 if (new_shortname) { 1496 if (new_shortname) {
1496 const char *pid_color = color; 1497 const char *pid_color = color;
1497 1498
@@ -1753,7 +1754,7 @@ static int perf_sched__lat(struct perf_sched *sched)
1753 1754
1754 printf(" -----------------------------------------------------------------------------------------------------------------\n"); 1755 printf(" -----------------------------------------------------------------------------------------------------------------\n");
1755 printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n", 1756 printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n",
1756 (double)sched->all_runtime / 1e6, sched->all_count); 1757 (double)sched->all_runtime / NSEC_PER_MSEC, sched->all_count);
1757 1758
1758 printf(" ---------------------------------------------------\n"); 1759 printf(" ---------------------------------------------------\n");
1759 1760
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index c859e59dfe3e..7228d141a789 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -24,6 +24,7 @@
24#include "util/thread-stack.h" 24#include "util/thread-stack.h"
25#include <linux/bitmap.h> 25#include <linux/bitmap.h>
26#include <linux/stringify.h> 26#include <linux/stringify.h>
27#include <linux/time64.h>
27#include "asm/bug.h" 28#include "asm/bug.h"
28#include "util/mem-events.h" 29#include "util/mem-events.h"
29 30
@@ -464,9 +465,9 @@ static void print_sample_start(struct perf_sample *sample,
464 465
465 if (PRINT_FIELD(TIME)) { 466 if (PRINT_FIELD(TIME)) {
466 nsecs = sample->time; 467 nsecs = sample->time;
467 secs = nsecs / NSECS_PER_SEC; 468 secs = nsecs / NSEC_PER_SEC;
468 nsecs -= secs * NSECS_PER_SEC; 469 nsecs -= secs * NSEC_PER_SEC;
469 usecs = nsecs / NSECS_PER_USEC; 470 usecs = nsecs / NSEC_PER_USEC;
470 if (nanosecs) 471 if (nanosecs)
471 printf("%5lu.%09llu: ", secs, nsecs); 472 printf("%5lu.%09llu: ", secs, nsecs);
472 else 473 else
@@ -521,11 +522,11 @@ static void print_sample_brstacksym(struct perf_sample *sample,
521 522
522 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); 523 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf);
523 if (alf.map) 524 if (alf.map)
524 alf.sym = map__find_symbol(alf.map, alf.addr, NULL); 525 alf.sym = map__find_symbol(alf.map, alf.addr);
525 526
526 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); 527 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt);
527 if (alt.map) 528 if (alt.map)
528 alt.sym = map__find_symbol(alt.map, alt.addr, NULL); 529 alt.sym = map__find_symbol(alt.map, alt.addr);
529 530
530 symbol__fprintf_symname_offs(alf.sym, &alf, stdout); 531 symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
531 putchar('/'); 532 putchar('/');
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3c7452b39f57..688dea7cb08f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -52,6 +52,7 @@
52#include "util/evlist.h" 52#include "util/evlist.h"
53#include "util/evsel.h" 53#include "util/evsel.h"
54#include "util/debug.h" 54#include "util/debug.h"
55#include "util/drv_configs.h"
55#include "util/color.h" 56#include "util/color.h"
56#include "util/stat.h" 57#include "util/stat.h"
57#include "util/header.h" 58#include "util/header.h"
@@ -65,6 +66,7 @@
65#include "util/group.h" 66#include "util/group.h"
66#include "asm/bug.h" 67#include "asm/bug.h"
67 68
69#include <linux/time64.h>
68#include <api/fs/fs.h> 70#include <api/fs/fs.h>
69#include <stdlib.h> 71#include <stdlib.h>
70#include <sys/prctl.h> 72#include <sys/prctl.h>
@@ -172,7 +174,7 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a,
172{ 174{
173 r->tv_sec = a->tv_sec - b->tv_sec; 175 r->tv_sec = a->tv_sec - b->tv_sec;
174 if (a->tv_nsec < b->tv_nsec) { 176 if (a->tv_nsec < b->tv_nsec) {
175 r->tv_nsec = a->tv_nsec + 1000000000L - b->tv_nsec; 177 r->tv_nsec = a->tv_nsec + NSEC_PER_SEC - b->tv_nsec;
176 r->tv_sec--; 178 r->tv_sec--;
177 } else { 179 } else {
178 r->tv_nsec = a->tv_nsec - b->tv_nsec ; 180 r->tv_nsec = a->tv_nsec - b->tv_nsec ;
@@ -354,7 +356,7 @@ static void process_interval(void)
354 diff_timespec(&rs, &ts, &ref_time); 356 diff_timespec(&rs, &ts, &ref_time);
355 357
356 if (STAT_RECORD) { 358 if (STAT_RECORD) {
357 if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSECS_PER_SEC + rs.tv_nsec, INTERVAL)) 359 if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSEC_PER_SEC + rs.tv_nsec, INTERVAL))
358 pr_err("failed to write stat round event\n"); 360 pr_err("failed to write stat round event\n");
359 } 361 }
360 362
@@ -364,7 +366,7 @@ static void process_interval(void)
364static void enable_counters(void) 366static void enable_counters(void)
365{ 367{
366 if (initial_delay) 368 if (initial_delay)
367 usleep(initial_delay * 1000); 369 usleep(initial_delay * USEC_PER_MSEC);
368 370
369 /* 371 /*
370 * We need to enable counters only if: 372 * We need to enable counters only if:
@@ -539,10 +541,11 @@ static int __run_perf_stat(int argc, const char **argv)
539 int status = 0; 541 int status = 0;
540 const bool forks = (argc > 0); 542 const bool forks = (argc > 0);
541 bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false; 543 bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false;
544 struct perf_evsel_config_term *err_term;
542 545
543 if (interval) { 546 if (interval) {
544 ts.tv_sec = interval / 1000; 547 ts.tv_sec = interval / USEC_PER_MSEC;
545 ts.tv_nsec = (interval % 1000) * 1000000; 548 ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC;
546 } else { 549 } else {
547 ts.tv_sec = 1; 550 ts.tv_sec = 1;
548 ts.tv_nsec = 0; 551 ts.tv_nsec = 0;
@@ -610,6 +613,13 @@ try_again:
610 return -1; 613 return -1;
611 } 614 }
612 615
616 if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) {
617 error("failed to set config \"%s\" on event %s with %d (%s)\n",
618 err_term->val.drv_cfg, perf_evsel__name(counter), errno,
619 str_error_r(errno, msg, sizeof(msg)));
620 return -1;
621 }
622
613 if (STAT_RECORD) { 623 if (STAT_RECORD) {
614 int err, fd = perf_data_file__fd(&perf_stat.file); 624 int err, fd = perf_data_file__fd(&perf_stat.file);
615 625
@@ -971,7 +981,7 @@ static void print_metric_header(void *ctx, const char *color __maybe_unused,
971static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg) 981static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
972{ 982{
973 FILE *output = stat_config.output; 983 FILE *output = stat_config.output;
974 double msecs = avg / 1e6; 984 double msecs = avg / NSEC_PER_MSEC;
975 const char *fmt_v, *fmt_n; 985 const char *fmt_v, *fmt_n;
976 char name[25]; 986 char name[25];
977 987
@@ -1460,7 +1470,7 @@ static void print_footer(void)
1460 if (!null_run) 1470 if (!null_run)
1461 fprintf(output, "\n"); 1471 fprintf(output, "\n");
1462 fprintf(output, " %17.9f seconds time elapsed", 1472 fprintf(output, " %17.9f seconds time elapsed",
1463 avg_stats(&walltime_nsecs_stats)/1e9); 1473 avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC);
1464 if (run_count > 1) { 1474 if (run_count > 1) {
1465 fprintf(output, " "); 1475 fprintf(output, " ");
1466 print_noise_pct(stddev_stats(&walltime_nsecs_stats), 1476 print_noise_pct(stddev_stats(&walltime_nsecs_stats),
@@ -2175,8 +2185,8 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2175 update_stats(&walltime_nsecs_stats, stat_round->time); 2185 update_stats(&walltime_nsecs_stats, stat_round->time);
2176 2186
2177 if (stat_config.interval && stat_round->time) { 2187 if (stat_config.interval && stat_round->time) {
2178 tsh.tv_sec = stat_round->time / NSECS_PER_SEC; 2188 tsh.tv_sec = stat_round->time / NSEC_PER_SEC;
2179 tsh.tv_nsec = stat_round->time % NSECS_PER_SEC; 2189 tsh.tv_nsec = stat_round->time % NSEC_PER_SEC;
2180 ts = &tsh; 2190 ts = &tsh;
2181 } 2191 }
2182 2192
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 733a55422d03..e7eaa298d34a 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -24,6 +24,7 @@
24#include "util/evlist.h" 24#include "util/evlist.h"
25#include "util/evsel.h" 25#include "util/evsel.h"
26#include <linux/rbtree.h> 26#include <linux/rbtree.h>
27#include <linux/time64.h>
27#include "util/symbol.h" 28#include "util/symbol.h"
28#include "util/callchain.h" 29#include "util/callchain.h"
29#include "util/strlist.h" 30#include "util/strlist.h"
@@ -1288,9 +1289,9 @@ static void draw_process_bars(struct timechart *tchart)
1288 if (c->comm) { 1289 if (c->comm) {
1289 char comm[256]; 1290 char comm[256];
1290 if (c->total_time > 5000000000) /* 5 seconds */ 1291 if (c->total_time > 5000000000) /* 5 seconds */
1291 sprintf(comm, "%s:%i (%2.2fs)", c->comm, p->pid, c->total_time / 1000000000.0); 1292 sprintf(comm, "%s:%i (%2.2fs)", c->comm, p->pid, c->total_time / (double)NSEC_PER_SEC);
1292 else 1293 else
1293 sprintf(comm, "%s:%i (%3.1fms)", c->comm, p->pid, c->total_time / 1000000.0); 1294 sprintf(comm, "%s:%i (%3.1fms)", c->comm, p->pid, c->total_time / (double)NSEC_PER_MSEC);
1294 1295
1295 svg_text(Y, c->start_time, comm); 1296 svg_text(Y, c->start_time, comm);
1296 } 1297 }
@@ -1637,7 +1638,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1637 write_svg_file(tchart, output_name); 1638 write_svg_file(tchart, output_name);
1638 1639
1639 pr_info("Written %2.1f seconds of trace to %s.\n", 1640 pr_info("Written %2.1f seconds of trace to %s.\n",
1640 (tchart->last_time - tchart->first_time) / 1000000000.0, output_name); 1641 (tchart->last_time - tchart->first_time) / (double)NSEC_PER_SEC, output_name);
1641out_delete: 1642out_delete:
1642 perf_session__delete(session); 1643 perf_session__delete(session);
1643 return ret; 1644 return ret;
@@ -1901,10 +1902,10 @@ parse_time(const struct option *opt, const char *arg, int __maybe_unused unset)
1901 if (sscanf(arg, "%" PRIu64 "%cs", value, &unit) > 0) { 1902 if (sscanf(arg, "%" PRIu64 "%cs", value, &unit) > 0) {
1902 switch (unit) { 1903 switch (unit) {
1903 case 'm': 1904 case 'm':
1904 *value *= 1000000; 1905 *value *= NSEC_PER_MSEC;
1905 break; 1906 break;
1906 case 'u': 1907 case 'u':
1907 *value *= 1000; 1908 *value *= NSEC_PER_USEC;
1908 break; 1909 break;
1909 case 'n': 1910 case 'n':
1910 break; 1911 break;
@@ -1928,7 +1929,7 @@ int cmd_timechart(int argc, const char **argv,
1928 .ordered_events = true, 1929 .ordered_events = true,
1929 }, 1930 },
1930 .proc_num = 15, 1931 .proc_num = 15,
1931 .min_time = 1000000, 1932 .min_time = NSEC_PER_MSEC,
1932 .merge_dist = 1000, 1933 .merge_dist = 1000,
1933 }; 1934 };
1934 const char *output_name = "output.svg"; 1935 const char *output_name = "output.svg";
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 418ed94756d3..fe3af9535e85 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -24,6 +24,7 @@
24#include "util/annotate.h" 24#include "util/annotate.h"
25#include "util/config.h" 25#include "util/config.h"
26#include "util/color.h" 26#include "util/color.h"
27#include "util/drv_configs.h"
27#include "util/evlist.h" 28#include "util/evlist.h"
28#include "util/evsel.h" 29#include "util/evsel.h"
29#include "util/machine.h" 30#include "util/machine.h"
@@ -68,6 +69,7 @@
68#include <sys/mman.h> 69#include <sys/mman.h>
69 70
70#include <linux/stringify.h> 71#include <linux/stringify.h>
72#include <linux/time64.h>
71#include <linux/types.h> 73#include <linux/types.h>
72 74
73static volatile int done; 75static volatile int done;
@@ -624,7 +626,7 @@ static void *display_thread(void *arg)
624 display_setup_sig(); 626 display_setup_sig();
625 pthread__unblock_sigwinch(); 627 pthread__unblock_sigwinch();
626repeat: 628repeat:
627 delay_msecs = top->delay_secs * 1000; 629 delay_msecs = top->delay_secs * MSEC_PER_SEC;
628 set_term_quiet_input(&save); 630 set_term_quiet_input(&save);
629 /* trash return*/ 631 /* trash return*/
630 getc(stdin); 632 getc(stdin);
@@ -656,34 +658,6 @@ repeat:
656 return NULL; 658 return NULL;
657} 659}
658 660
659static int symbol_filter(struct map *map, struct symbol *sym)
660{
661 const char *name = sym->name;
662
663 if (!__map__is_kernel(map))
664 return 0;
665 /*
666 * ppc64 uses function descriptors and appends a '.' to the
667 * start of every instruction address. Remove it.
668 */
669 if (name[0] == '.')
670 name++;
671
672 if (!strcmp(name, "_text") ||
673 !strcmp(name, "_etext") ||
674 !strcmp(name, "_sinittext") ||
675 !strncmp("init_module", name, 11) ||
676 !strncmp("cleanup_module", name, 14) ||
677 strstr(name, "_text_start") ||
678 strstr(name, "_text_end"))
679 return 1;
680
681 if (symbol__is_idle(sym))
682 sym->ignore = true;
683
684 return 0;
685}
686
687static int hist_iter__top_callback(struct hist_entry_iter *iter, 661static int hist_iter__top_callback(struct hist_entry_iter *iter,
688 struct addr_location *al, bool single, 662 struct addr_location *al, bool single,
689 void *arg) 663 void *arg)
@@ -782,7 +756,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
782 } 756 }
783 } 757 }
784 758
785 if (al.sym == NULL || !al.sym->ignore) { 759 if (al.sym == NULL || !al.sym->idle) {
786 struct hists *hists = evsel__hists(evsel); 760 struct hists *hists = evsel__hists(evsel);
787 struct hist_entry_iter iter = { 761 struct hist_entry_iter iter = {
788 .evsel = evsel, 762 .evsel = evsel,
@@ -940,6 +914,10 @@ static int callchain_param__setup_sample_type(struct callchain_param *callchain)
940 914
941static int __cmd_top(struct perf_top *top) 915static int __cmd_top(struct perf_top *top)
942{ 916{
917 char msg[512];
918 struct perf_evsel *pos;
919 struct perf_evsel_config_term *err_term;
920 struct perf_evlist *evlist = top->evlist;
943 struct record_opts *opts = &top->record_opts; 921 struct record_opts *opts = &top->record_opts;
944 pthread_t thread; 922 pthread_t thread;
945 int ret; 923 int ret;
@@ -948,8 +926,6 @@ static int __cmd_top(struct perf_top *top)
948 if (top->session == NULL) 926 if (top->session == NULL)
949 return -1; 927 return -1;
950 928
951 machines__set_symbol_filter(&top->session->machines, symbol_filter);
952
953 if (!objdump_path) { 929 if (!objdump_path) {
954 ret = perf_env__lookup_objdump(&top->session->header.env); 930 ret = perf_env__lookup_objdump(&top->session->header.env);
955 if (ret) 931 if (ret)
@@ -976,6 +952,14 @@ static int __cmd_top(struct perf_top *top)
976 if (ret) 952 if (ret)
977 goto out_delete; 953 goto out_delete;
978 954
955 ret = perf_evlist__apply_drv_configs(evlist, &pos, &err_term);
956 if (ret) {
957 error("failed to set config \"%s\" on event %s with %d (%s)\n",
958 err_term->val.drv_cfg, perf_evsel__name(pos), errno,
959 str_error_r(errno, msg, sizeof(msg)));
960 goto out_delete;
961 }
962
979 top->session->evlist = top->evlist; 963 top->session->evlist = top->evlist;
980 perf_session__set_id_hdr_size(top->session); 964 perf_session__set_id_hdr_size(top->session);
981 965
@@ -1323,7 +1307,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1323 if (symbol_conf.cumulate_callchain && !callchain_param.order_set) 1307 if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
1324 callchain_param.order = ORDER_CALLER; 1308 callchain_param.order = ORDER_CALLER;
1325 1309
1326 symbol_conf.priv_size = sizeof(struct annotation); 1310 status = symbol__annotation_init();
1311 if (status < 0)
1312 goto out_delete_evlist;
1327 1313
1328 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1314 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1329 if (symbol__init(NULL) < 0) 1315 if (symbol__init(NULL) < 0)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index b8c6766301db..c298bd3e1d90 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -45,6 +45,7 @@
45#include <linux/audit.h> 45#include <linux/audit.h>
46#include <linux/random.h> 46#include <linux/random.h>
47#include <linux/stringify.h> 47#include <linux/stringify.h>
48#include <linux/time64.h>
48 49
49#ifndef O_CLOEXEC 50#ifndef O_CLOEXEC
50# define O_CLOEXEC 02000000 51# define O_CLOEXEC 02000000
@@ -741,6 +742,8 @@ static struct syscall_fmt {
741 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 742 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
742 { .name = "rt_tgsigqueueinfo", .errmsg = true, 743 { .name = "rt_tgsigqueueinfo", .errmsg = true,
743 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 744 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
745 { .name = "sched_getattr", .errmsg = true, },
746 { .name = "sched_setattr", .errmsg = true, },
744 { .name = "sched_setscheduler", .errmsg = true, 747 { .name = "sched_setscheduler", .errmsg = true,
745 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, }, 748 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
746 { .name = "seccomp", .errmsg = true, 749 { .name = "seccomp", .errmsg = true,
@@ -2140,6 +2143,7 @@ out_delete_sys_enter:
2140static int trace__set_ev_qualifier_filter(struct trace *trace) 2143static int trace__set_ev_qualifier_filter(struct trace *trace)
2141{ 2144{
2142 int err = -1; 2145 int err = -1;
2146 struct perf_evsel *sys_exit;
2143 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier, 2147 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2144 trace->ev_qualifier_ids.nr, 2148 trace->ev_qualifier_ids.nr,
2145 trace->ev_qualifier_ids.entries); 2149 trace->ev_qualifier_ids.entries);
@@ -2147,8 +2151,11 @@ static int trace__set_ev_qualifier_filter(struct trace *trace)
2147 if (filter == NULL) 2151 if (filter == NULL)
2148 goto out_enomem; 2152 goto out_enomem;
2149 2153
2150 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter)) 2154 if (!perf_evsel__append_tp_filter(trace->syscalls.events.sys_enter,
2151 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter); 2155 filter)) {
2156 sys_exit = trace->syscalls.events.sys_exit;
2157 err = perf_evsel__append_tp_filter(sys_exit, filter);
2158 }
2152 2159
2153 free(filter); 2160 free(filter);
2154out: 2161out:
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index 7ed72a475c57..e4b717e9eb6c 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -20,7 +20,6 @@
20#endif 20#endif
21 21
22#ifdef __powerpc__ 22#ifdef __powerpc__
23#include "../../arch/powerpc/include/uapi/asm/unistd.h"
24#define CPUINFO_PROC {"cpu"} 23#define CPUINFO_PROC {"cpu"}
25#endif 24#endif
26 25
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index cb0f1356ff81..9a0236a4cf95 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -14,13 +14,6 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
14#define HAVE_ATTR_TEST 14#define HAVE_ATTR_TEST
15#include "perf-sys.h" 15#include "perf-sys.h"
16 16
17#ifndef NSEC_PER_SEC
18# define NSEC_PER_SEC 1000000000ULL
19#endif
20#ifndef NSEC_PER_USEC
21# define NSEC_PER_USEC 1000ULL
22#endif
23
24static inline unsigned long long rdclock(void) 17static inline unsigned long long rdclock(void)
25{ 18{
26 struct timespec ts; 19 struct timespec ts;
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index dc51bc570e51..8a4ce492f7b2 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -71,7 +71,7 @@ $(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/B
71 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@ 71 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
72 $(Q)echo ';' >> $@ 72 $(Q)echo ';' >> $@
73 73
74ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) 74ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64 powerpc))
75perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o 75perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
76endif 76endif
77 77
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index 615780cbfe1d..e6d1816e431a 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -97,7 +97,7 @@ int test__backward_ring_buffer(int subtest __maybe_unused)
97 97
98 evlist = perf_evlist__new(); 98 evlist = perf_evlist__new();
99 if (!evlist) { 99 if (!evlist) {
100 pr_debug("No ehough memory to create evlist\n"); 100 pr_debug("No enough memory to create evlist\n");
101 return TEST_FAIL; 101 return TEST_FAIL;
102 } 102 }
103 103
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index fc54064b9186..2673e86ed50f 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -125,7 +125,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
125 /* Instead of perf_evlist__new_default, don't add default events */ 125 /* Instead of perf_evlist__new_default, don't add default events */
126 evlist = perf_evlist__new(); 126 evlist = perf_evlist__new();
127 if (!evlist) { 127 if (!evlist) {
128 pr_debug("No ehough memory to create evlist\n"); 128 pr_debug("No enough memory to create evlist\n");
129 return TEST_FAIL; 129 return TEST_FAIL;
130 } 130 }
131 131
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 2af156a8d4e5..ff5bc6363a79 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -263,7 +263,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
263 * Converting addresses for use by objdump requires more information. 263 * Converting addresses for use by objdump requires more information.
264 * map__load() does that. See map__rip_2objdump() for details. 264 * map__load() does that. See map__rip_2objdump() for details.
265 */ 265 */
266 if (map__load(al.map, NULL)) 266 if (map__load(al.map))
267 return -1; 267 return -1;
268 268
269 /* objdump struggles with kcore - try each map only once */ 269 /* objdump struggles with kcore - try each map only once */
@@ -511,7 +511,7 @@ static int do_test_code_reading(bool try_kcore)
511 511
512 /* Load kernel map */ 512 /* Load kernel map */
513 map = machine__kernel_map(machine); 513 map = machine__kernel_map(machine);
514 ret = map__load(map, NULL); 514 ret = map__load(map);
515 if (ret < 0) { 515 if (ret < 0) {
516 pr_debug("map__load failed\n"); 516 pr_debug("map__load failed\n");
517 goto out_err; 517 goto out_err;
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 8f6eb853aaf7..1046491de4b2 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -11,7 +11,7 @@
11#include "thread.h" 11#include "thread.h"
12#include "callchain.h" 12#include "callchain.h"
13 13
14#if defined (__x86_64__) || defined (__i386__) 14#if defined (__x86_64__) || defined (__i386__) || defined (__powerpc__)
15#include "arch-tests.h" 15#include "arch-tests.h"
16#endif 16#endif
17 17
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index e63abab7d5a1..a5082331f246 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -8,14 +8,6 @@
8#include "debug.h" 8#include "debug.h"
9#include "machine.h" 9#include "machine.h"
10 10
11static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
12 struct symbol *sym)
13{
14 bool *visited = symbol__priv(sym);
15 *visited = true;
16 return 0;
17}
18
19#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x)) 11#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x))
20 12
21int test__vmlinux_matches_kallsyms(int subtest __maybe_unused) 13int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
@@ -28,6 +20,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
28 enum map_type type = MAP__FUNCTION; 20 enum map_type type = MAP__FUNCTION;
29 struct maps *maps = &vmlinux.kmaps.maps[type]; 21 struct maps *maps = &vmlinux.kmaps.maps[type];
30 u64 mem_start, mem_end; 22 u64 mem_start, mem_end;
23 bool header_printed;
31 24
32 /* 25 /*
33 * Step 1: 26 * Step 1:
@@ -61,7 +54,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
61 * be compacted against the list of modules found in the "vmlinux" 54 * 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. 55 * code and with the one got from /proc/modules from the "kallsyms" code.
63 */ 56 */
64 if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true, NULL) <= 0) { 57 if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true) <= 0) {
65 pr_debug("dso__load_kallsyms "); 58 pr_debug("dso__load_kallsyms ");
66 goto out; 59 goto out;
67 } 60 }
@@ -99,8 +92,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
99 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines 92 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
100 * to fixup the symbols. 93 * to fixup the symbols.
101 */ 94 */
102 if (machine__load_vmlinux_path(&vmlinux, type, 95 if (machine__load_vmlinux_path(&vmlinux, type) <= 0) {
103 vmlinux_matches_kallsyms_filter) <= 0) {
104 pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n"); 96 pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n");
105 err = TEST_SKIP; 97 err = TEST_SKIP;
106 goto out; 98 goto out;
@@ -126,7 +118,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
126 mem_end = vmlinux_map->unmap_ip(vmlinux_map, sym->end); 118 mem_end = vmlinux_map->unmap_ip(vmlinux_map, sym->end);
127 119
128 first_pair = machine__find_kernel_symbol(&kallsyms, type, 120 first_pair = machine__find_kernel_symbol(&kallsyms, type,
129 mem_start, NULL, NULL); 121 mem_start, NULL);
130 pair = first_pair; 122 pair = first_pair;
131 123
132 if (pair && UM(pair->start) == mem_start) { 124 if (pair && UM(pair->start) == mem_start) {
@@ -143,7 +135,7 @@ next_pair:
143 */ 135 */
144 s64 skew = mem_end - UM(pair->end); 136 s64 skew = mem_end - UM(pair->end);
145 if (llabs(skew) >= page_size) 137 if (llabs(skew) >= page_size)
146 pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n", 138 pr_debug("WARN: %#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
147 mem_start, sym->name, mem_end, 139 mem_start, sym->name, mem_end,
148 UM(pair->end)); 140 UM(pair->end));
149 141
@@ -154,22 +146,23 @@ next_pair:
154 * kallsyms. 146 * kallsyms.
155 */ 147 */
156 continue; 148 continue;
157
158 } else { 149 } else {
159 pair = machine__find_kernel_symbol_by_name(&kallsyms, type, sym->name, NULL, NULL); 150 pair = machine__find_kernel_symbol_by_name(&kallsyms, type, sym->name, NULL);
160 if (pair) { 151 if (pair) {
161 if (UM(pair->start) == mem_start) 152 if (UM(pair->start) == mem_start)
162 goto next_pair; 153 goto next_pair;
163 154
164 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", 155 pr_debug("WARN: %#" PRIx64 ": diff name v: %s k: %s\n",
165 mem_start, sym->name, pair->name); 156 mem_start, sym->name, pair->name);
166 } else { 157 } else {
167 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", 158 pr_debug("WARN: %#" PRIx64 ": diff name v: %s k: %s\n",
168 mem_start, sym->name, first_pair->name); 159 mem_start, sym->name, first_pair->name);
169 } 160 }
161
162 continue;
170 } 163 }
171 } else 164 } else
172 pr_debug("%#" PRIx64 ": %s not on kallsyms\n", 165 pr_debug("ERR : %#" PRIx64 ": %s not on kallsyms\n",
173 mem_start, sym->name); 166 mem_start, sym->name);
174 167
175 err = -1; 168 err = -1;
@@ -178,7 +171,7 @@ next_pair:
178 if (!verbose) 171 if (!verbose)
179 goto out; 172 goto out;
180 173
181 pr_info("Maps only in vmlinux:\n"); 174 header_printed = false;
182 175
183 for (map = maps__first(maps); map; map = map__next(map)) { 176 for (map = maps__first(maps); map; map = map__next(map)) {
184 struct map * 177 struct map *
@@ -192,13 +185,18 @@ next_pair:
192 (map->dso->kernel ? 185 (map->dso->kernel ?
193 map->dso->short_name : 186 map->dso->short_name :
194 map->dso->name)); 187 map->dso->name));
195 if (pair) 188 if (pair) {
196 pair->priv = 1; 189 pair->priv = 1;
197 else 190 } else {
191 if (!header_printed) {
192 pr_info("WARN: Maps only in vmlinux:\n");
193 header_printed = true;
194 }
198 map__fprintf(map, stderr); 195 map__fprintf(map, stderr);
196 }
199 } 197 }
200 198
201 pr_info("Maps in vmlinux with a different name in kallsyms:\n"); 199 header_printed = false;
202 200
203 for (map = maps__first(maps); map; map = map__next(map)) { 201 for (map = maps__first(maps); map; map = map__next(map)) {
204 struct map *pair; 202 struct map *pair;
@@ -211,24 +209,33 @@ next_pair:
211 continue; 209 continue;
212 210
213 if (pair->start == mem_start) { 211 if (pair->start == mem_start) {
214 pair->priv = 1; 212 if (!header_printed) {
215 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", 213 pr_info("WARN: Maps in vmlinux with a different name in kallsyms:\n");
214 header_printed = true;
215 }
216
217 pr_info("WARN: %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
216 map->start, map->end, map->pgoff, map->dso->name); 218 map->start, map->end, map->pgoff, map->dso->name);
217 if (mem_end != pair->end) 219 if (mem_end != pair->end)
218 pr_info(":\n*%" PRIx64 "-%" PRIx64 " %" PRIx64, 220 pr_info(":\nWARN: *%" PRIx64 "-%" PRIx64 " %" PRIx64,
219 pair->start, pair->end, pair->pgoff); 221 pair->start, pair->end, pair->pgoff);
220 pr_info(" %s\n", pair->dso->name); 222 pr_info(" %s\n", pair->dso->name);
221 pair->priv = 1; 223 pair->priv = 1;
222 } 224 }
223 } 225 }
224 226
225 pr_info("Maps only in kallsyms:\n"); 227 header_printed = false;
226 228
227 maps = &kallsyms.kmaps.maps[type]; 229 maps = &kallsyms.kmaps.maps[type];
228 230
229 for (map = maps__first(maps); map; map = map__next(map)) { 231 for (map = maps__first(maps); map; map = map__next(map)) {
230 if (!map->priv) 232 if (!map->priv) {
233 if (!header_printed) {
234 pr_info("WARN: Maps only in kallsyms:\n");
235 header_printed = true;
236 }
231 map__fprintf(map, stderr); 237 map__fprintf(map, stderr);
238 }
232 } 239 }
233out: 240out:
234 machine__exit(&kallsyms); 241 machine__exit(&kallsyms);
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index d0a3a8e402e7..fd710ab33684 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -1,8 +1,4 @@
1#include <sys/mman.h> 1#include <uapi/linux/mman.h>
2
3#ifndef PROT_SEM
4#define PROT_SEM 0x8
5#endif
6 2
7static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, 3static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
8 struct syscall_arg *arg) 4 struct syscall_arg *arg)
@@ -33,31 +29,6 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
33 29
34#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot 30#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
35 31
36#ifndef MAP_FIXED
37#define MAP_FIXED 0x10
38#endif
39
40#ifndef MAP_ANONYMOUS
41#define MAP_ANONYMOUS 0x20
42#endif
43
44#ifndef MAP_32BIT
45#define MAP_32BIT 0x40
46#endif
47
48#ifndef MAP_STACK
49#define MAP_STACK 0x20000
50#endif
51
52#ifndef MAP_HUGETLB
53#define MAP_HUGETLB 0x40000
54#endif
55
56#ifndef MAP_UNINITIALIZED
57#define MAP_UNINITIALIZED 0x4000000
58#endif
59
60
61static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, 32static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
62 struct syscall_arg *arg) 33 struct syscall_arg *arg)
63{ 34{
@@ -95,13 +66,6 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
95 66
96#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 67#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
97 68
98#ifndef MREMAP_MAYMOVE
99#define MREMAP_MAYMOVE 1
100#endif
101#ifndef MREMAP_FIXED
102#define MREMAP_FIXED 2
103#endif
104
105static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size, 69static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
106 struct syscall_arg *arg) 70 struct syscall_arg *arg)
107{ 71{
@@ -125,39 +89,6 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
125 89
126#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags 90#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
127 91
128#ifndef MADV_HWPOISON
129#define MADV_HWPOISON 100
130#endif
131
132#ifndef MADV_SOFT_OFFLINE
133#define MADV_SOFT_OFFLINE 101
134#endif
135
136#ifndef MADV_MERGEABLE
137#define MADV_MERGEABLE 12
138#endif
139
140#ifndef MADV_UNMERGEABLE
141#define MADV_UNMERGEABLE 13
142#endif
143
144#ifndef MADV_HUGEPAGE
145#define MADV_HUGEPAGE 14
146#endif
147
148#ifndef MADV_NOHUGEPAGE
149#define MADV_NOHUGEPAGE 15
150#endif
151
152#ifndef MADV_DONTDUMP
153#define MADV_DONTDUMP 16
154#endif
155
156#ifndef MADV_DODUMP
157#define MADV_DODUMP 17
158#endif
159
160
161static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 92static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
162 struct syscall_arg *arg) 93 struct syscall_arg *arg)
163{ 94{
@@ -170,6 +101,7 @@ static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
170 P_MADV_BHV(SEQUENTIAL); 101 P_MADV_BHV(SEQUENTIAL);
171 P_MADV_BHV(WILLNEED); 102 P_MADV_BHV(WILLNEED);
172 P_MADV_BHV(DONTNEED); 103 P_MADV_BHV(DONTNEED);
104 P_MADV_BHV(FREE);
173 P_MADV_BHV(REMOVE); 105 P_MADV_BHV(REMOVE);
174 P_MADV_BHV(DONTFORK); 106 P_MADV_BHV(DONTFORK);
175 P_MADV_BHV(DOFORK); 107 P_MADV_BHV(DOFORK);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 2e2d10022355..4c18271c71c9 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -495,7 +495,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
495 if (!ins__is_call(dl->ins)) 495 if (!ins__is_call(dl->ins))
496 return false; 496 return false;
497 497
498 if (map_groups__find_ams(&target, NULL) || 498 if (map_groups__find_ams(&target) ||
499 map__rip_2objdump(target.map, target.map->map_ip(target.map, 499 map__rip_2objdump(target.map, target.map->map_ip(target.map,
500 target.addr)) != 500 target.addr)) !=
501 dl->ops.target.addr) { 501 dl->ops.target.addr) {
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 13d414384739..fb8e42c7507a 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -69,8 +69,11 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb)
69static void hist_browser__update_rows(struct hist_browser *hb) 69static void hist_browser__update_rows(struct hist_browser *hb)
70{ 70{
71 struct ui_browser *browser = &hb->b; 71 struct ui_browser *browser = &hb->b;
72 u16 header_offset = hb->show_headers ? 1 : 0, index_row; 72 struct hists *hists = hb->hists;
73 struct perf_hpp_list *hpp_list = hists->hpp_list;
74 u16 header_offset, index_row;
73 75
76 header_offset = hb->show_headers ? hpp_list->nr_header_lines : 0;
74 browser->rows = browser->height - header_offset; 77 browser->rows = browser->height - header_offset;
75 /* 78 /*
76 * Verify if we were at the last line and that line isn't 79 * Verify if we were at the last line and that line isn't
@@ -99,8 +102,11 @@ static void hist_browser__refresh_dimensions(struct ui_browser *browser)
99 102
100static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) 103static void hist_browser__gotorc(struct hist_browser *browser, int row, int column)
101{ 104{
102 u16 header_offset = browser->show_headers ? 1 : 0; 105 struct hists *hists = browser->hists;
106 struct perf_hpp_list *hpp_list = hists->hpp_list;
107 u16 header_offset;
103 108
109 header_offset = browser->show_headers ? hpp_list->nr_header_lines : 0;
104 ui_browser__gotorc(&browser->b, row + header_offset, column); 110 ui_browser__gotorc(&browser->b, row + header_offset, column);
105} 111}
106 112
@@ -1074,7 +1080,7 @@ struct hpp_arg {
1074 bool current_entry; 1080 bool current_entry;
1075}; 1081};
1076 1082
1077static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...) 1083int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
1078{ 1084{
1079 struct hpp_arg *arg = hpp->ptr; 1085 struct hpp_arg *arg = hpp->ptr;
1080 int ret, len; 1086 int ret, len;
@@ -1091,7 +1097,6 @@ static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
1091 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent); 1097 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent);
1092 ui_browser__printf(arg->b, "%s", hpp->buf); 1098 ui_browser__printf(arg->b, "%s", hpp->buf);
1093 1099
1094 advance_hpp(hpp, ret);
1095 return ret; 1100 return ret;
1096} 1101}
1097 1102
@@ -1496,7 +1501,9 @@ static int advance_hpp_check(struct perf_hpp *hpp, int inc)
1496 return hpp->size <= 0; 1501 return hpp->size <= 0;
1497} 1502}
1498 1503
1499static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf, size_t size) 1504static int
1505hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf,
1506 size_t size, int line)
1500{ 1507{
1501 struct hists *hists = browser->hists; 1508 struct hists *hists = browser->hists;
1502 struct perf_hpp dummy_hpp = { 1509 struct perf_hpp dummy_hpp = {
@@ -1506,6 +1513,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
1506 struct perf_hpp_fmt *fmt; 1513 struct perf_hpp_fmt *fmt;
1507 size_t ret = 0; 1514 size_t ret = 0;
1508 int column = 0; 1515 int column = 0;
1516 int span = 0;
1509 1517
1510 if (symbol_conf.use_callchain) { 1518 if (symbol_conf.use_callchain) {
1511 ret = scnprintf(buf, size, " "); 1519 ret = scnprintf(buf, size, " ");
@@ -1517,10 +1525,13 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
1517 if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) 1525 if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll)
1518 continue; 1526 continue;
1519 1527
1520 ret = fmt->header(fmt, &dummy_hpp, hists); 1528 ret = fmt->header(fmt, &dummy_hpp, hists, line, &span);
1521 if (advance_hpp_check(&dummy_hpp, ret)) 1529 if (advance_hpp_check(&dummy_hpp, ret))
1522 break; 1530 break;
1523 1531
1532 if (span)
1533 continue;
1534
1524 ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " "); 1535 ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " ");
1525 if (advance_hpp_check(&dummy_hpp, ret)) 1536 if (advance_hpp_check(&dummy_hpp, ret))
1526 break; 1537 break;
@@ -1554,7 +1565,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
1554 if (column++ < browser->b.horiz_scroll) 1565 if (column++ < browser->b.horiz_scroll)
1555 continue; 1566 continue;
1556 1567
1557 ret = fmt->header(fmt, &dummy_hpp, hists); 1568 ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL);
1558 if (advance_hpp_check(&dummy_hpp, ret)) 1569 if (advance_hpp_check(&dummy_hpp, ret))
1559 break; 1570 break;
1560 1571
@@ -1591,7 +1602,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
1591 } 1602 }
1592 first_col = false; 1603 first_col = false;
1593 1604
1594 ret = fmt->header(fmt, &dummy_hpp, hists); 1605 ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL);
1595 dummy_hpp.buf[ret] = '\0'; 1606 dummy_hpp.buf[ret] = '\0';
1596 1607
1597 start = trim(dummy_hpp.buf); 1608 start = trim(dummy_hpp.buf);
@@ -1622,14 +1633,21 @@ static void hists_browser__hierarchy_headers(struct hist_browser *browser)
1622 1633
1623static void hists_browser__headers(struct hist_browser *browser) 1634static void hists_browser__headers(struct hist_browser *browser)
1624{ 1635{
1625 char headers[1024]; 1636 struct hists *hists = browser->hists;
1637 struct perf_hpp_list *hpp_list = hists->hpp_list;
1626 1638
1627 hists_browser__scnprintf_headers(browser, headers, 1639 int line;
1628 sizeof(headers));
1629 1640
1630 ui_browser__gotorc(&browser->b, 0, 0); 1641 for (line = 0; line < hpp_list->nr_header_lines; line++) {
1631 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); 1642 char headers[1024];
1632 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); 1643
1644 hists_browser__scnprintf_headers(browser, headers,
1645 sizeof(headers), line);
1646
1647 ui_browser__gotorc(&browser->b, line, 0);
1648 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
1649 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
1650 }
1633} 1651}
1634 1652
1635static void hist_browser__show_headers(struct hist_browser *browser) 1653static void hist_browser__show_headers(struct hist_browser *browser)
@@ -1656,10 +1674,13 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)
1656 u16 header_offset = 0; 1674 u16 header_offset = 0;
1657 struct rb_node *nd; 1675 struct rb_node *nd;
1658 struct hist_browser *hb = container_of(browser, struct hist_browser, b); 1676 struct hist_browser *hb = container_of(browser, struct hist_browser, b);
1677 struct hists *hists = hb->hists;
1659 1678
1660 if (hb->show_headers) { 1679 if (hb->show_headers) {
1680 struct perf_hpp_list *hpp_list = hists->hpp_list;
1681
1661 hist_browser__show_headers(hb); 1682 hist_browser__show_headers(hb);
1662 header_offset = 1; 1683 header_offset = hpp_list->nr_header_lines;
1663 } 1684 }
1664 1685
1665 ui_browser__hists_init_top(browser); 1686 ui_browser__hists_init_top(browser);
@@ -2054,10 +2075,10 @@ void hist_browser__init(struct hist_browser *browser,
2054 browser->b.use_navkeypressed = true; 2075 browser->b.use_navkeypressed = true;
2055 browser->show_headers = symbol_conf.show_hist_headers; 2076 browser->show_headers = symbol_conf.show_hist_headers;
2056 2077
2057 hists__for_each_format(hists, fmt) { 2078 hists__for_each_format(hists, fmt)
2058 perf_hpp__reset_width(fmt, hists);
2059 ++browser->b.columns; 2079 ++browser->b.columns;
2060 } 2080
2081 hists__reset_column_width(hists);
2061} 2082}
2062 2083
2063struct hist_browser *hist_browser__new(struct hists *hists) 2084struct hist_browser *hist_browser__new(struct hists *hists)
@@ -2418,8 +2439,6 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
2418 browser->hists->dso_filter = NULL; 2439 browser->hists->dso_filter = NULL;
2419 ui_helpline__pop(); 2440 ui_helpline__pop();
2420 } else { 2441 } else {
2421 if (map == NULL)
2422 return 0;
2423 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s DSO\"", 2442 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s DSO\"",
2424 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name); 2443 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name);
2425 browser->hists->dso_filter = map->dso; 2444 browser->hists->dso_filter = map->dso;
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index 80912778bb6d..98a34664bb7e 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -52,9 +52,9 @@ static int map_browser__search(struct map_browser *browser)
52 52
53 if (target[0] == '0' && tolower(target[1]) == 'x') { 53 if (target[0] == '0' && tolower(target[1]) == 'x') {
54 u64 addr = strtoull(target, NULL, 16); 54 u64 addr = strtoull(target, NULL, 16);
55 sym = map__find_symbol(browser->map, addr, NULL); 55 sym = map__find_symbol(browser->map, addr);
56 } else 56 } else
57 sym = map__find_symbol_by_name(browser->map, target, NULL); 57 sym = map__find_symbol_by_name(browser->map, target);
58 58
59 if (sym != NULL) { 59 if (sym != NULL) {
60 u32 *idx = symbol__browser_index(sym); 60 u32 *idx = symbol__browser_index(sym);
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index c5f3677f6679..a4f02de7c1b5 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -549,7 +549,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
549 strcat(buf, "+"); 549 strcat(buf, "+");
550 first_col = false; 550 first_col = false;
551 551
552 fmt->header(fmt, &hpp, hists); 552 fmt->header(fmt, &hpp, hists, 0, NULL);
553 strcat(buf, ltrim(rtrim(hpp.buf))); 553 strcat(buf, ltrim(rtrim(hpp.buf)));
554 } 554 }
555 } 555 }
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 4274969ddc89..37388397b5bc 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -230,13 +230,14 @@ static int hpp__width_fn(struct perf_hpp_fmt *fmt,
230} 230}
231 231
232static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 232static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
233 struct hists *hists) 233 struct hists *hists, int line __maybe_unused,
234 int *span __maybe_unused)
234{ 235{
235 int len = hpp__width_fn(fmt, hpp, hists); 236 int len = hpp__width_fn(fmt, hpp, hists);
236 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name); 237 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
237} 238}
238 239
239static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) 240int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
240{ 241{
241 va_list args; 242 va_list args;
242 ssize_t ssize = hpp->size; 243 ssize_t ssize = hpp->size;
@@ -441,6 +442,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
441struct perf_hpp_list perf_hpp_list = { 442struct perf_hpp_list perf_hpp_list = {
442 .fields = LIST_HEAD_INIT(perf_hpp_list.fields), 443 .fields = LIST_HEAD_INIT(perf_hpp_list.fields),
443 .sorts = LIST_HEAD_INIT(perf_hpp_list.sorts), 444 .sorts = LIST_HEAD_INIT(perf_hpp_list.sorts),
445 .nr_header_lines = 1,
444}; 446};
445 447
446#undef HPP__COLOR_PRINT_FNS 448#undef HPP__COLOR_PRINT_FNS
@@ -697,6 +699,21 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
697 } 699 }
698} 700}
699 701
702void hists__reset_column_width(struct hists *hists)
703{
704 struct perf_hpp_fmt *fmt;
705 struct perf_hpp_list_node *node;
706
707 hists__for_each_format(hists, fmt)
708 perf_hpp__reset_width(fmt, hists);
709
710 /* hierarchy entries have their own hpp list */
711 list_for_each_entry(node, &hists->hpp_formats, list) {
712 perf_hpp_list__for_each_format(&node->hpp, fmt)
713 perf_hpp__reset_width(fmt, hists);
714 }
715}
716
700void perf_hpp__set_user_width(const char *width_list_str) 717void perf_hpp__set_user_width(const char *width_list_str)
701{ 718{
702 struct perf_hpp_fmt *fmt; 719 struct perf_hpp_fmt *fmt;
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index f04a63112079..89d8441f9890 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -373,7 +373,8 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
373 return 0; 373 return 0;
374} 374}
375 375
376static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) 376int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp,
377 struct perf_hpp_list *hpp_list)
377{ 378{
378 const char *sep = symbol_conf.field_sep; 379 const char *sep = symbol_conf.field_sep;
379 struct perf_hpp_fmt *fmt; 380 struct perf_hpp_fmt *fmt;
@@ -384,7 +385,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
384 if (symbol_conf.exclude_other && !he->parent) 385 if (symbol_conf.exclude_other && !he->parent)
385 return 0; 386 return 0;
386 387
387 hists__for_each_format(he->hists, fmt) { 388 perf_hpp_list__for_each_format(hpp_list, fmt) {
388 if (perf_hpp__should_skip(fmt, he->hists)) 389 if (perf_hpp__should_skip(fmt, he->hists))
389 continue; 390 continue;
390 391
@@ -410,6 +411,11 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
410 return hpp->buf - start; 411 return hpp->buf - start;
411} 412}
412 413
414static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
415{
416 return __hist_entry__snprintf(he, hpp, he->hists->hpp_list);
417}
418
413static int hist_entry__hierarchy_fprintf(struct hist_entry *he, 419static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
414 struct perf_hpp *hpp, 420 struct perf_hpp *hpp,
415 struct hists *hists, 421 struct hists *hists,
@@ -528,8 +534,8 @@ static int print_hierarchy_indent(const char *sep, int indent,
528 return fprintf(fp, "%-.*s", (indent - 2) * HIERARCHY_INDENT, line); 534 return fprintf(fp, "%-.*s", (indent - 2) * HIERARCHY_INDENT, line);
529} 535}
530 536
531static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, 537static int hists__fprintf_hierarchy_headers(struct hists *hists,
532 const char *sep, FILE *fp) 538 struct perf_hpp *hpp, FILE *fp)
533{ 539{
534 bool first_node, first_col; 540 bool first_node, first_col;
535 int indent; 541 int indent;
@@ -538,6 +544,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
538 unsigned header_width = 0; 544 unsigned header_width = 0;
539 struct perf_hpp_fmt *fmt; 545 struct perf_hpp_fmt *fmt;
540 struct perf_hpp_list_node *fmt_node; 546 struct perf_hpp_list_node *fmt_node;
547 const char *sep = symbol_conf.field_sep;
541 548
542 indent = hists->nr_hpp_node; 549 indent = hists->nr_hpp_node;
543 550
@@ -549,7 +556,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
549 struct perf_hpp_list_node, list); 556 struct perf_hpp_list_node, list);
550 557
551 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { 558 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
552 fmt->header(fmt, hpp, hists); 559 fmt->header(fmt, hpp, hists, 0, NULL);
553 fprintf(fp, "%s%s", hpp->buf, sep ?: " "); 560 fprintf(fp, "%s%s", hpp->buf, sep ?: " ");
554 } 561 }
555 562
@@ -569,7 +576,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
569 header_width += fprintf(fp, "+"); 576 header_width += fprintf(fp, "+");
570 first_col = false; 577 first_col = false;
571 578
572 fmt->header(fmt, hpp, hists); 579 fmt->header(fmt, hpp, hists, 0, NULL);
573 580
574 header_width += fprintf(fp, "%s", trim(hpp->buf)); 581 header_width += fprintf(fp, "%s", trim(hpp->buf));
575 } 582 }
@@ -623,20 +630,28 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
623 return 2; 630 return 2;
624} 631}
625 632
626static int 633static void fprintf_line(struct hists *hists, struct perf_hpp *hpp,
627hists__fprintf_hierarchy_headers(struct hists *hists, 634 int line, FILE *fp)
628 struct perf_hpp *hpp,
629 FILE *fp)
630{ 635{
631 struct perf_hpp_list_node *fmt_node;
632 struct perf_hpp_fmt *fmt; 636 struct perf_hpp_fmt *fmt;
637 const char *sep = symbol_conf.field_sep;
638 bool first = true;
639 int span = 0;
633 640
634 list_for_each_entry(fmt_node, &hists->hpp_formats, list) { 641 hists__for_each_format(hists, fmt) {
635 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) 642 if (perf_hpp__should_skip(fmt, hists))
636 perf_hpp__reset_width(fmt, hists); 643 continue;
637 } 644
645 if (!first && !span)
646 fprintf(fp, "%s", sep ?: " ");
647 else
648 first = false;
649
650 fmt->header(fmt, hpp, hists, line, &span);
638 651
639 return print_hierarchy_header(hists, hpp, symbol_conf.field_sep, fp); 652 if (!span)
653 fprintf(fp, "%s", hpp->buf);
654 }
640} 655}
641 656
642static int 657static int
@@ -644,28 +659,23 @@ hists__fprintf_standard_headers(struct hists *hists,
644 struct perf_hpp *hpp, 659 struct perf_hpp *hpp,
645 FILE *fp) 660 FILE *fp)
646{ 661{
662 struct perf_hpp_list *hpp_list = hists->hpp_list;
647 struct perf_hpp_fmt *fmt; 663 struct perf_hpp_fmt *fmt;
648 unsigned int width; 664 unsigned int width;
649 const char *sep = symbol_conf.field_sep; 665 const char *sep = symbol_conf.field_sep;
650 bool first = true; 666 bool first = true;
651 667 int line;
652 hists__for_each_format(hists, fmt) { 668
653 if (perf_hpp__should_skip(fmt, hists)) 669 for (line = 0; line < hpp_list->nr_header_lines; line++) {
654 continue; 670 /* first # is displayed one level up */
655 671 if (line)
656 if (!first) 672 fprintf(fp, "# ");
657 fprintf(fp, "%s", sep ?: " "); 673 fprintf_line(hists, hpp, line, fp);
658 else 674 fprintf(fp, "\n");
659 first = false;
660
661 fmt->header(fmt, hpp, hists);
662 fprintf(fp, "%s", hpp->buf);
663 } 675 }
664 676
665 fprintf(fp, "\n");
666
667 if (sep) 677 if (sep)
668 return 1; 678 return hpp_list->nr_header_lines;
669 679
670 first = true; 680 first = true;
671 681
@@ -689,12 +699,12 @@ hists__fprintf_standard_headers(struct hists *hists,
689 699
690 fprintf(fp, "\n"); 700 fprintf(fp, "\n");
691 fprintf(fp, "#\n"); 701 fprintf(fp, "#\n");
692 return 3; 702 return hpp_list->nr_header_lines + 2;
693} 703}
694 704
695static int hists__fprintf_headers(struct hists *hists, FILE *fp) 705int hists__fprintf_headers(struct hists *hists, FILE *fp)
696{ 706{
697 char bf[96]; 707 char bf[1024];
698 struct perf_hpp dummy_hpp = { 708 struct perf_hpp dummy_hpp = {
699 .buf = bf, 709 .buf = bf,
700 .size = sizeof(bf), 710 .size = sizeof(bf),
@@ -713,7 +723,6 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
713 int max_cols, float min_pcnt, FILE *fp, 723 int max_cols, float min_pcnt, FILE *fp,
714 bool use_callchain) 724 bool use_callchain)
715{ 725{
716 struct perf_hpp_fmt *fmt;
717 struct rb_node *nd; 726 struct rb_node *nd;
718 size_t ret = 0; 727 size_t ret = 0;
719 const char *sep = symbol_conf.field_sep; 728 const char *sep = symbol_conf.field_sep;
@@ -724,8 +733,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
724 733
725 init_rem_hits(); 734 init_rem_hits();
726 735
727 hists__for_each_format(hists, fmt) 736 hists__reset_column_width(hists);
728 perf_hpp__reset_width(fmt, hists);
729 737
730 if (symbol_conf.col_width_list_str) 738 if (symbol_conf.col_width_list_str)
731 perf_hpp__set_user_width(symbol_conf.col_width_list_str); 739 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 91c5f6e1af59..eb60e613d795 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -1,5 +1,6 @@
1libperf-y += alias.o 1libperf-y += alias.o
2libperf-y += annotate.o 2libperf-y += annotate.o
3libperf-y += block-range.o
3libperf-y += build-id.o 4libperf-y += build-id.o
4libperf-y += config.o 5libperf-y += config.o
5libperf-y += ctype.o 6libperf-y += ctype.o
@@ -85,6 +86,7 @@ libperf-y += term.o
85libperf-y += help-unknown-cmd.o 86libperf-y += help-unknown-cmd.o
86libperf-y += mem-events.o 87libperf-y += mem-events.o
87libperf-y += vsprintf.o 88libperf-y += vsprintf.o
89libperf-y += drv_configs.o
88 90
89libperf-$(CONFIG_LIBBPF) += bpf-loader.o 91libperf-$(CONFIG_LIBBPF) += bpf-loader.o
90libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 92libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -98,6 +100,7 @@ endif
98 100
99libperf-$(CONFIG_DWARF) += probe-finder.o 101libperf-$(CONFIG_DWARF) += probe-finder.o
100libperf-$(CONFIG_DWARF) += dwarf-aux.o 102libperf-$(CONFIG_DWARF) += dwarf-aux.o
103libperf-$(CONFIG_DWARF) += dwarf-regs.o
101 104
102libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 105libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
103libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o 106libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 4024d309bb00..aeb5a441bd74 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -17,6 +17,7 @@
17#include "debug.h" 17#include "debug.h"
18#include "annotate.h" 18#include "annotate.h"
19#include "evsel.h" 19#include "evsel.h"
20#include "block-range.h"
20#include <regex.h> 21#include <regex.h>
21#include <pthread.h> 22#include <pthread.h>
22#include <linux/bitops.h> 23#include <linux/bitops.h>
@@ -53,7 +54,7 @@ int ins__scnprintf(struct ins *ins, char *bf, size_t size,
53 return ins__raw_scnprintf(ins, bf, size, ops); 54 return ins__raw_scnprintf(ins, bf, size, ops);
54} 55}
55 56
56static int call__parse(struct ins_operands *ops) 57static int call__parse(struct ins_operands *ops, struct map *map)
57{ 58{
58 char *endptr, *tok, *name; 59 char *endptr, *tok, *name;
59 60
@@ -81,16 +82,16 @@ static int call__parse(struct ins_operands *ops)
81 return ops->target.name == NULL ? -1 : 0; 82 return ops->target.name == NULL ? -1 : 0;
82 83
83indirect_call: 84indirect_call:
84 tok = strchr(endptr, '('); 85 tok = strchr(endptr, '*');
85 if (tok != NULL) { 86 if (tok == NULL) {
86 ops->target.addr = 0; 87 struct symbol *sym = map__find_symbol(map, map->map_ip(map, ops->target.addr));
88 if (sym != NULL)
89 ops->target.name = strdup(sym->name);
90 else
91 ops->target.addr = 0;
87 return 0; 92 return 0;
88 } 93 }
89 94
90 tok = strchr(endptr, '*');
91 if (tok == NULL)
92 return -1;
93
94 ops->target.addr = strtoull(tok + 1, NULL, 16); 95 ops->target.addr = strtoull(tok + 1, NULL, 16);
95 return 0; 96 return 0;
96} 97}
@@ -117,7 +118,7 @@ bool ins__is_call(const struct ins *ins)
117 return ins->ops == &call_ops; 118 return ins->ops == &call_ops;
118} 119}
119 120
120static int jump__parse(struct ins_operands *ops) 121static int jump__parse(struct ins_operands *ops, struct map *map __maybe_unused)
121{ 122{
122 const char *s = strchr(ops->raw, '+'); 123 const char *s = strchr(ops->raw, '+');
123 124
@@ -172,7 +173,7 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
172 return 0; 173 return 0;
173} 174}
174 175
175static int lock__parse(struct ins_operands *ops) 176static int lock__parse(struct ins_operands *ops, struct map *map)
176{ 177{
177 char *name; 178 char *name;
178 179
@@ -193,7 +194,7 @@ static int lock__parse(struct ins_operands *ops)
193 return 0; 194 return 0;
194 195
195 if (ops->locked.ins->ops->parse && 196 if (ops->locked.ins->ops->parse &&
196 ops->locked.ins->ops->parse(ops->locked.ops) < 0) 197 ops->locked.ins->ops->parse(ops->locked.ops, map) < 0)
197 goto out_free_ops; 198 goto out_free_ops;
198 199
199 return 0; 200 return 0;
@@ -236,7 +237,7 @@ static struct ins_ops lock_ops = {
236 .scnprintf = lock__scnprintf, 237 .scnprintf = lock__scnprintf,
237}; 238};
238 239
239static int mov__parse(struct ins_operands *ops) 240static int mov__parse(struct ins_operands *ops, struct map *map __maybe_unused)
240{ 241{
241 char *s = strchr(ops->raw, ','), *target, *comment, prev; 242 char *s = strchr(ops->raw, ','), *target, *comment, prev;
242 243
@@ -303,7 +304,7 @@ static struct ins_ops mov_ops = {
303 .scnprintf = mov__scnprintf, 304 .scnprintf = mov__scnprintf,
304}; 305};
305 306
306static int dec__parse(struct ins_operands *ops) 307static int dec__parse(struct ins_operands *ops, struct map *map __maybe_unused)
307{ 308{
308 char *target, *comment, *s, prev; 309 char *target, *comment, *s, prev;
309 310
@@ -491,13 +492,6 @@ static struct ins *ins__find(const char *name)
491 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp); 492 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp);
492} 493}
493 494
494int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
495{
496 struct annotation *notes = symbol__annotation(sym);
497 pthread_mutex_init(&notes->lock, NULL);
498 return 0;
499}
500
501int symbol__alloc_hist(struct symbol *sym) 495int symbol__alloc_hist(struct symbol *sym)
502{ 496{
503 struct annotation *notes = symbol__annotation(sym); 497 struct annotation *notes = symbol__annotation(sym);
@@ -715,7 +709,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
715 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); 709 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
716} 710}
717 711
718static void disasm_line__init_ins(struct disasm_line *dl) 712static void disasm_line__init_ins(struct disasm_line *dl, struct map *map)
719{ 713{
720 dl->ins = ins__find(dl->name); 714 dl->ins = ins__find(dl->name);
721 715
@@ -725,7 +719,7 @@ static void disasm_line__init_ins(struct disasm_line *dl)
725 if (!dl->ins->ops) 719 if (!dl->ins->ops)
726 return; 720 return;
727 721
728 if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops) < 0) 722 if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops, map) < 0)
729 dl->ins = NULL; 723 dl->ins = NULL;
730} 724}
731 725
@@ -767,7 +761,8 @@ out_free_name:
767} 761}
768 762
769static struct disasm_line *disasm_line__new(s64 offset, char *line, 763static struct disasm_line *disasm_line__new(s64 offset, char *line,
770 size_t privsize, int line_nr) 764 size_t privsize, int line_nr,
765 struct map *map)
771{ 766{
772 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); 767 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
773 768
@@ -782,7 +777,7 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line,
782 if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0) 777 if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0)
783 goto out_free_line; 778 goto out_free_line;
784 779
785 disasm_line__init_ins(dl); 780 disasm_line__init_ins(dl, map);
786 } 781 }
787 } 782 }
788 783
@@ -866,6 +861,89 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
866 return percent; 861 return percent;
867} 862}
868 863
864static const char *annotate__address_color(struct block_range *br)
865{
866 double cov = block_range__coverage(br);
867
868 if (cov >= 0) {
869 /* mark red for >75% coverage */
870 if (cov > 0.75)
871 return PERF_COLOR_RED;
872
873 /* mark dull for <1% coverage */
874 if (cov < 0.01)
875 return PERF_COLOR_NORMAL;
876 }
877
878 return PERF_COLOR_MAGENTA;
879}
880
881static const char *annotate__asm_color(struct block_range *br)
882{
883 double cov = block_range__coverage(br);
884
885 if (cov >= 0) {
886 /* mark dull for <1% coverage */
887 if (cov < 0.01)
888 return PERF_COLOR_NORMAL;
889 }
890
891 return PERF_COLOR_BLUE;
892}
893
894static void annotate__branch_printf(struct block_range *br, u64 addr)
895{
896 bool emit_comment = true;
897
898 if (!br)
899 return;
900
901#if 1
902 if (br->is_target && br->start == addr) {
903 struct block_range *branch = br;
904 double p;
905
906 /*
907 * Find matching branch to our target.
908 */
909 while (!branch->is_branch)
910 branch = block_range__next(branch);
911
912 p = 100 *(double)br->entry / branch->coverage;
913
914 if (p > 0.1) {
915 if (emit_comment) {
916 emit_comment = false;
917 printf("\t#");
918 }
919
920 /*
921 * The percentage of coverage joined at this target in relation
922 * to the next branch.
923 */
924 printf(" +%.2f%%", p);
925 }
926 }
927#endif
928 if (br->is_branch && br->end == addr) {
929 double p = 100*(double)br->taken / br->coverage;
930
931 if (p > 0.1) {
932 if (emit_comment) {
933 emit_comment = false;
934 printf("\t#");
935 }
936
937 /*
938 * The percentage of coverage leaving at this branch, and
939 * its prediction ratio.
940 */
941 printf(" -%.2f%% (p:%.2f%%)", p, 100*(double)br->pred / br->taken);
942 }
943 }
944}
945
946
869static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 start, 947static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 start,
870 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed, 948 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
871 int max_lines, struct disasm_line *queue) 949 int max_lines, struct disasm_line *queue)
@@ -885,6 +963,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
885 s64 offset = dl->offset; 963 s64 offset = dl->offset;
886 const u64 addr = start + offset; 964 const u64 addr = start + offset;
887 struct disasm_line *next; 965 struct disasm_line *next;
966 struct block_range *br;
888 967
889 next = disasm__get_next_ip_line(&notes->src->source, dl); 968 next = disasm__get_next_ip_line(&notes->src->source, dl);
890 969
@@ -954,8 +1033,12 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
954 } 1033 }
955 1034
956 printf(" : "); 1035 printf(" : ");
957 color_fprintf(stdout, PERF_COLOR_MAGENTA, " %" PRIx64 ":", addr); 1036
958 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", dl->line); 1037 br = block_range__find(addr);
1038 color_fprintf(stdout, annotate__address_color(br), " %" PRIx64 ":", addr);
1039 color_fprintf(stdout, annotate__asm_color(br), "%s", dl->line);
1040 annotate__branch_printf(br, addr);
1041 printf("\n");
959 1042
960 if (ppercents != &percent) 1043 if (ppercents != &percent)
961 free(ppercents); 1044 free(ppercents);
@@ -1066,7 +1149,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
1066 parsed_line = tmp2 + 1; 1149 parsed_line = tmp2 + 1;
1067 } 1150 }
1068 1151
1069 dl = disasm_line__new(offset, parsed_line, privsize, *line_nr); 1152 dl = disasm_line__new(offset, parsed_line, privsize, *line_nr, map);
1070 free(line); 1153 free(line);
1071 (*line_nr)++; 1154 (*line_nr)++;
1072 1155
@@ -1084,7 +1167,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
1084 .addr = dl->ops.target.addr, 1167 .addr = dl->ops.target.addr,
1085 }; 1168 };
1086 1169
1087 if (!map_groups__find_ams(&target, NULL) && 1170 if (!map_groups__find_ams(&target) &&
1088 target.sym->start == target.al_addr) 1171 target.sym->start == target.al_addr)
1089 dl->ops.target.name = strdup(target.sym->name); 1172 dl->ops.target.name = strdup(target.sym->name);
1090 } 1173 }
@@ -1162,53 +1245,60 @@ int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *
1162 return 0; 1245 return 0;
1163} 1246}
1164 1247
1165int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) 1248static int dso__disassemble_filename(struct dso *dso, char *filename, size_t filename_size)
1166{ 1249{
1167 struct dso *dso = map->dso; 1250 char linkname[PATH_MAX];
1168 char *filename = dso__build_id_filename(dso, NULL, 0); 1251 char *build_id_filename;
1169 bool free_filename = true;
1170 char command[PATH_MAX * 2];
1171 FILE *file;
1172 int err = 0;
1173 char symfs_filename[PATH_MAX];
1174 struct kcore_extract kce;
1175 bool delete_extract = false;
1176 int stdout_fd[2];
1177 int lineno = 0;
1178 int nline;
1179 pid_t pid;
1180 1252
1181 if (filename) 1253 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1182 symbol__join_symfs(symfs_filename, filename); 1254 !dso__is_kcore(dso))
1255 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1183 1256
1184 if (filename == NULL) { 1257 build_id_filename = dso__build_id_filename(dso, NULL, 0);
1258 if (build_id_filename) {
1259 __symbol__join_symfs(filename, filename_size, build_id_filename);
1260 free(build_id_filename);
1261 } else {
1185 if (dso->has_build_id) 1262 if (dso->has_build_id)
1186 return ENOMEM; 1263 return ENOMEM;
1187 goto fallback; 1264 goto fallback;
1188 } else if (dso__is_kcore(dso) || 1265 }
1189 readlink(symfs_filename, command, sizeof(command)) < 0 || 1266
1190 strstr(command, DSO__NAME_KALLSYMS) || 1267 if (dso__is_kcore(dso) ||
1191 access(symfs_filename, R_OK)) { 1268 readlink(filename, linkname, sizeof(linkname)) < 0 ||
1192 free(filename); 1269 strstr(linkname, DSO__NAME_KALLSYMS) ||
1270 access(filename, R_OK)) {
1193fallback: 1271fallback:
1194 /* 1272 /*
1195 * If we don't have build-ids or the build-id file isn't in the 1273 * If we don't have build-ids or the build-id file isn't in the
1196 * cache, or is just a kallsyms file, well, lets hope that this 1274 * cache, or is just a kallsyms file, well, lets hope that this
1197 * DSO is the same as when 'perf record' ran. 1275 * DSO is the same as when 'perf record' ran.
1198 */ 1276 */
1199 filename = (char *)dso->long_name; 1277 __symbol__join_symfs(filename, filename_size, dso->long_name);
1200 symbol__join_symfs(symfs_filename, filename);
1201 free_filename = false;
1202 } 1278 }
1203 1279
1204 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1280 return 0;
1205 !dso__is_kcore(dso)) { 1281}
1206 err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX; 1282
1207 goto out_free_filename; 1283int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize)
1208 } 1284{
1285 struct dso *dso = map->dso;
1286 char command[PATH_MAX * 2];
1287 FILE *file;
1288 char symfs_filename[PATH_MAX];
1289 struct kcore_extract kce;
1290 bool delete_extract = false;
1291 int stdout_fd[2];
1292 int lineno = 0;
1293 int nline;
1294 pid_t pid;
1295 int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
1296
1297 if (err)
1298 return err;
1209 1299
1210 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, 1300 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1211 filename, sym->name, map->unmap_ip(map, sym->start), 1301 symfs_filename, sym->name, map->unmap_ip(map, sym->start),
1212 map->unmap_ip(map, sym->end)); 1302 map->unmap_ip(map, sym->end));
1213 1303
1214 pr_debug("annotating [%p] %30s : [%p] %30s\n", 1304 pr_debug("annotating [%p] %30s : [%p] %30s\n",
@@ -1223,11 +1313,6 @@ fallback:
1223 delete_extract = true; 1313 delete_extract = true;
1224 strlcpy(symfs_filename, kce.extract_filename, 1314 strlcpy(symfs_filename, kce.extract_filename,
1225 sizeof(symfs_filename)); 1315 sizeof(symfs_filename));
1226 if (free_filename) {
1227 free(filename);
1228 free_filename = false;
1229 }
1230 filename = symfs_filename;
1231 } 1316 }
1232 } else if (dso__needs_decompress(dso)) { 1317 } else if (dso__needs_decompress(dso)) {
1233 char tmp[PATH_MAX]; 1318 char tmp[PATH_MAX];
@@ -1236,14 +1321,14 @@ fallback:
1236 bool ret; 1321 bool ret;
1237 1322
1238 if (kmod_path__parse_ext(&m, symfs_filename)) 1323 if (kmod_path__parse_ext(&m, symfs_filename))
1239 goto out_free_filename; 1324 goto out;
1240 1325
1241 snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX"); 1326 snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX");
1242 1327
1243 fd = mkstemp(tmp); 1328 fd = mkstemp(tmp);
1244 if (fd < 0) { 1329 if (fd < 0) {
1245 free(m.ext); 1330 free(m.ext);
1246 goto out_free_filename; 1331 goto out;
1247 } 1332 }
1248 1333
1249 ret = decompress_to_file(m.ext, symfs_filename, fd); 1334 ret = decompress_to_file(m.ext, symfs_filename, fd);
@@ -1255,7 +1340,7 @@ fallback:
1255 close(fd); 1340 close(fd);
1256 1341
1257 if (!ret) 1342 if (!ret)
1258 goto out_free_filename; 1343 goto out;
1259 1344
1260 strcpy(symfs_filename, tmp); 1345 strcpy(symfs_filename, tmp);
1261 } 1346 }
@@ -1271,7 +1356,7 @@ fallback:
1271 map__rip_2objdump(map, sym->end), 1356 map__rip_2objdump(map, sym->end),
1272 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", 1357 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
1273 symbol_conf.annotate_src ? "-S" : "", 1358 symbol_conf.annotate_src ? "-S" : "",
1274 symfs_filename, filename); 1359 symfs_filename, symfs_filename);
1275 1360
1276 pr_debug("Executing: %s\n", command); 1361 pr_debug("Executing: %s\n", command);
1277 1362
@@ -1333,11 +1418,10 @@ out_remove_tmp:
1333 1418
1334 if (dso__needs_decompress(dso)) 1419 if (dso__needs_decompress(dso))
1335 unlink(symfs_filename); 1420 unlink(symfs_filename);
1336out_free_filename: 1421
1337 if (delete_extract) 1422 if (delete_extract)
1338 kcore_extract__delete(&kce); 1423 kcore_extract__delete(&kce);
1339 if (free_filename) 1424out:
1340 free(filename);
1341 return err; 1425 return err;
1342 1426
1343out_close_stdout: 1427out_close_stdout:
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index f67ccb027561..5bbcec173b82 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -36,7 +36,7 @@ struct ins_operands {
36 36
37struct ins_ops { 37struct ins_ops {
38 void (*free)(struct ins_operands *ops); 38 void (*free)(struct ins_operands *ops);
39 int (*parse)(struct ins_operands *ops); 39 int (*parse)(struct ins_operands *ops, struct map *map);
40 int (*scnprintf)(struct ins *ins, char *bf, size_t size, 40 int (*scnprintf)(struct ins *ins, char *bf, size_t size,
41 struct ins_operands *ops); 41 struct ins_operands *ops);
42}; 42};
@@ -130,6 +130,7 @@ struct annotated_source {
130 130
131struct annotation { 131struct annotation {
132 pthread_mutex_t lock; 132 pthread_mutex_t lock;
133 u64 max_coverage;
133 struct annotated_source *src; 134 struct annotated_source *src;
134}; 135};
135 136
@@ -177,7 +178,6 @@ enum symbol_disassemble_errno {
177int symbol__strerror_disassemble(struct symbol *sym, struct map *map, 178int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
178 int errnum, char *buf, size_t buflen); 179 int errnum, char *buf, size_t buflen);
179 180
180int symbol__annotate_init(struct map *map, struct symbol *sym);
181int symbol__annotate_printf(struct symbol *sym, struct map *map, 181int symbol__annotate_printf(struct symbol *sym, struct map *map,
182 struct perf_evsel *evsel, bool full_paths, 182 struct perf_evsel *evsel, bool full_paths,
183 int min_pcnt, int max_lines, int context); 183 int min_pcnt, int max_lines, int context);
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c9169011e55e..c5a6e0b12452 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -16,6 +16,10 @@
16#include <sys/types.h> 16#include <sys/types.h>
17#include <sys/mman.h> 17#include <sys/mman.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <ctype.h>
20#include <string.h>
21#include <limits.h>
22#include <errno.h>
19 23
20#include <linux/kernel.h> 24#include <linux/kernel.h>
21#include <linux/perf_event.h> 25#include <linux/perf_event.h>
@@ -35,9 +39,14 @@
35#include "../perf.h" 39#include "../perf.h"
36#include "util.h" 40#include "util.h"
37#include "evlist.h" 41#include "evlist.h"
42#include "dso.h"
43#include "map.h"
44#include "pmu.h"
45#include "evsel.h"
38#include "cpumap.h" 46#include "cpumap.h"
39#include "thread_map.h" 47#include "thread_map.h"
40#include "asm/bug.h" 48#include "asm/bug.h"
49#include "symbol/kallsyms.h"
41#include "auxtrace.h" 50#include "auxtrace.h"
42 51
43#include <linux/hash.h> 52#include <linux/hash.h>
@@ -892,6 +901,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
892 return intel_pt_process_auxtrace_info(event, session); 901 return intel_pt_process_auxtrace_info(event, session);
893 case PERF_AUXTRACE_INTEL_BTS: 902 case PERF_AUXTRACE_INTEL_BTS:
894 return intel_bts_process_auxtrace_info(event, session); 903 return intel_bts_process_auxtrace_info(event, session);
904 case PERF_AUXTRACE_CS_ETM:
895 case PERF_AUXTRACE_UNKNOWN: 905 case PERF_AUXTRACE_UNKNOWN:
896 default: 906 default:
897 return -EINVAL; 907 return -EINVAL;
@@ -1398,3 +1408,731 @@ void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key)
1398 1408
1399 return NULL; 1409 return NULL;
1400} 1410}
1411
1412static void addr_filter__free_str(struct addr_filter *filt)
1413{
1414 free(filt->str);
1415 filt->action = NULL;
1416 filt->sym_from = NULL;
1417 filt->sym_to = NULL;
1418 filt->filename = NULL;
1419 filt->str = NULL;
1420}
1421
1422static struct addr_filter *addr_filter__new(void)
1423{
1424 struct addr_filter *filt = zalloc(sizeof(*filt));
1425
1426 if (filt)
1427 INIT_LIST_HEAD(&filt->list);
1428
1429 return filt;
1430}
1431
1432static void addr_filter__free(struct addr_filter *filt)
1433{
1434 if (filt)
1435 addr_filter__free_str(filt);
1436 free(filt);
1437}
1438
1439static void addr_filters__add(struct addr_filters *filts,
1440 struct addr_filter *filt)
1441{
1442 list_add_tail(&filt->list, &filts->head);
1443 filts->cnt += 1;
1444}
1445
1446static void addr_filters__del(struct addr_filters *filts,
1447 struct addr_filter *filt)
1448{
1449 list_del_init(&filt->list);
1450 filts->cnt -= 1;
1451}
1452
1453void addr_filters__init(struct addr_filters *filts)
1454{
1455 INIT_LIST_HEAD(&filts->head);
1456 filts->cnt = 0;
1457}
1458
1459void addr_filters__exit(struct addr_filters *filts)
1460{
1461 struct addr_filter *filt, *n;
1462
1463 list_for_each_entry_safe(filt, n, &filts->head, list) {
1464 addr_filters__del(filts, filt);
1465 addr_filter__free(filt);
1466 }
1467}
1468
1469static int parse_num_or_str(char **inp, u64 *num, const char **str,
1470 const char *str_delim)
1471{
1472 *inp += strspn(*inp, " ");
1473
1474 if (isdigit(**inp)) {
1475 char *endptr;
1476
1477 if (!num)
1478 return -EINVAL;
1479 errno = 0;
1480 *num = strtoull(*inp, &endptr, 0);
1481 if (errno)
1482 return -errno;
1483 if (endptr == *inp)
1484 return -EINVAL;
1485 *inp = endptr;
1486 } else {
1487 size_t n;
1488
1489 if (!str)
1490 return -EINVAL;
1491 *inp += strspn(*inp, " ");
1492 *str = *inp;
1493 n = strcspn(*inp, str_delim);
1494 if (!n)
1495 return -EINVAL;
1496 *inp += n;
1497 if (**inp) {
1498 **inp = '\0';
1499 *inp += 1;
1500 }
1501 }
1502 return 0;
1503}
1504
1505static int parse_action(struct addr_filter *filt)
1506{
1507 if (!strcmp(filt->action, "filter")) {
1508 filt->start = true;
1509 filt->range = true;
1510 } else if (!strcmp(filt->action, "start")) {
1511 filt->start = true;
1512 } else if (!strcmp(filt->action, "stop")) {
1513 filt->start = false;
1514 } else if (!strcmp(filt->action, "tracestop")) {
1515 filt->start = false;
1516 filt->range = true;
1517 filt->action += 5; /* Change 'tracestop' to 'stop' */
1518 } else {
1519 return -EINVAL;
1520 }
1521 return 0;
1522}
1523
1524static int parse_sym_idx(char **inp, int *idx)
1525{
1526 *idx = -1;
1527
1528 *inp += strspn(*inp, " ");
1529
1530 if (**inp != '#')
1531 return 0;
1532
1533 *inp += 1;
1534
1535 if (**inp == 'g' || **inp == 'G') {
1536 *inp += 1;
1537 *idx = 0;
1538 } else {
1539 unsigned long num;
1540 char *endptr;
1541
1542 errno = 0;
1543 num = strtoul(*inp, &endptr, 0);
1544 if (errno)
1545 return -errno;
1546 if (endptr == *inp || num > INT_MAX)
1547 return -EINVAL;
1548 *inp = endptr;
1549 *idx = num;
1550 }
1551
1552 return 0;
1553}
1554
1555static int parse_addr_size(char **inp, u64 *num, const char **str, int *idx)
1556{
1557 int err = parse_num_or_str(inp, num, str, " ");
1558
1559 if (!err && *str)
1560 err = parse_sym_idx(inp, idx);
1561
1562 return err;
1563}
1564
1565static int parse_one_filter(struct addr_filter *filt, const char **filter_inp)
1566{
1567 char *fstr;
1568 int err;
1569
1570 filt->str = fstr = strdup(*filter_inp);
1571 if (!fstr)
1572 return -ENOMEM;
1573
1574 err = parse_num_or_str(&fstr, NULL, &filt->action, " ");
1575 if (err)
1576 goto out_err;
1577
1578 err = parse_action(filt);
1579 if (err)
1580 goto out_err;
1581
1582 err = parse_addr_size(&fstr, &filt->addr, &filt->sym_from,
1583 &filt->sym_from_idx);
1584 if (err)
1585 goto out_err;
1586
1587 fstr += strspn(fstr, " ");
1588
1589 if (*fstr == '/') {
1590 fstr += 1;
1591 err = parse_addr_size(&fstr, &filt->size, &filt->sym_to,
1592 &filt->sym_to_idx);
1593 if (err)
1594 goto out_err;
1595 filt->range = true;
1596 }
1597
1598 fstr += strspn(fstr, " ");
1599
1600 if (*fstr == '@') {
1601 fstr += 1;
1602 err = parse_num_or_str(&fstr, NULL, &filt->filename, " ,");
1603 if (err)
1604 goto out_err;
1605 }
1606
1607 fstr += strspn(fstr, " ,");
1608
1609 *filter_inp += fstr - filt->str;
1610
1611 return 0;
1612
1613out_err:
1614 addr_filter__free_str(filt);
1615
1616 return err;
1617}
1618
1619int addr_filters__parse_bare_filter(struct addr_filters *filts,
1620 const char *filter)
1621{
1622 struct addr_filter *filt;
1623 const char *fstr = filter;
1624 int err;
1625
1626 while (*fstr) {
1627 filt = addr_filter__new();
1628 err = parse_one_filter(filt, &fstr);
1629 if (err) {
1630 addr_filter__free(filt);
1631 addr_filters__exit(filts);
1632 return err;
1633 }
1634 addr_filters__add(filts, filt);
1635 }
1636
1637 return 0;
1638}
1639
1640struct sym_args {
1641 const char *name;
1642 u64 start;
1643 u64 size;
1644 int idx;
1645 int cnt;
1646 bool started;
1647 bool global;
1648 bool selected;
1649 bool duplicate;
1650 bool near;
1651};
1652
1653static bool kern_sym_match(struct sym_args *args, const char *name, char type)
1654{
1655 /* A function with the same name, and global or the n'th found or any */
1656 return symbol_type__is_a(type, MAP__FUNCTION) &&
1657 !strcmp(name, args->name) &&
1658 ((args->global && isupper(type)) ||
1659 (args->selected && ++(args->cnt) == args->idx) ||
1660 (!args->global && !args->selected));
1661}
1662
1663static int find_kern_sym_cb(void *arg, const char *name, char type, u64 start)
1664{
1665 struct sym_args *args = arg;
1666
1667 if (args->started) {
1668 if (!args->size)
1669 args->size = start - args->start;
1670 if (args->selected) {
1671 if (args->size)
1672 return 1;
1673 } else if (kern_sym_match(args, name, type)) {
1674 args->duplicate = true;
1675 return 1;
1676 }
1677 } else if (kern_sym_match(args, name, type)) {
1678 args->started = true;
1679 args->start = start;
1680 }
1681
1682 return 0;
1683}
1684
1685static int print_kern_sym_cb(void *arg, const char *name, char type, u64 start)
1686{
1687 struct sym_args *args = arg;
1688
1689 if (kern_sym_match(args, name, type)) {
1690 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
1691 ++args->cnt, start, type, name);
1692 args->near = true;
1693 } else if (args->near) {
1694 args->near = false;
1695 pr_err("\t\twhich is near\t\t%s\n", name);
1696 }
1697
1698 return 0;
1699}
1700
1701static int sym_not_found_error(const char *sym_name, int idx)
1702{
1703 if (idx > 0) {
1704 pr_err("N'th occurrence (N=%d) of symbol '%s' not found.\n",
1705 idx, sym_name);
1706 } else if (!idx) {
1707 pr_err("Global symbol '%s' not found.\n", sym_name);
1708 } else {
1709 pr_err("Symbol '%s' not found.\n", sym_name);
1710 }
1711 pr_err("Note that symbols must be functions.\n");
1712
1713 return -EINVAL;
1714}
1715
1716static int find_kern_sym(const char *sym_name, u64 *start, u64 *size, int idx)
1717{
1718 struct sym_args args = {
1719 .name = sym_name,
1720 .idx = idx,
1721 .global = !idx,
1722 .selected = idx > 0,
1723 };
1724 int err;
1725
1726 *start = 0;
1727 *size = 0;
1728
1729 err = kallsyms__parse("/proc/kallsyms", &args, find_kern_sym_cb);
1730 if (err < 0) {
1731 pr_err("Failed to parse /proc/kallsyms\n");
1732 return err;
1733 }
1734
1735 if (args.duplicate) {
1736 pr_err("Multiple kernel symbols with name '%s'\n", sym_name);
1737 args.cnt = 0;
1738 kallsyms__parse("/proc/kallsyms", &args, print_kern_sym_cb);
1739 pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
1740 sym_name);
1741 pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
1742 return -EINVAL;
1743 }
1744
1745 if (!args.started) {
1746 pr_err("Kernel symbol lookup: ");
1747 return sym_not_found_error(sym_name, idx);
1748 }
1749
1750 *start = args.start;
1751 *size = args.size;
1752
1753 return 0;
1754}
1755
1756static int find_entire_kern_cb(void *arg, const char *name __maybe_unused,
1757 char type, u64 start)
1758{
1759 struct sym_args *args = arg;
1760
1761 if (!symbol_type__is_a(type, MAP__FUNCTION))
1762 return 0;
1763
1764 if (!args->started) {
1765 args->started = true;
1766 args->start = start;
1767 }
1768 /* Don't know exactly where the kernel ends, so we add a page */
1769 args->size = round_up(start, page_size) + page_size - args->start;
1770
1771 return 0;
1772}
1773
1774static int addr_filter__entire_kernel(struct addr_filter *filt)
1775{
1776 struct sym_args args = { .started = false };
1777 int err;
1778
1779 err = kallsyms__parse("/proc/kallsyms", &args, find_entire_kern_cb);
1780 if (err < 0 || !args.started) {
1781 pr_err("Failed to parse /proc/kallsyms\n");
1782 return err;
1783 }
1784
1785 filt->addr = args.start;
1786 filt->size = args.size;
1787
1788 return 0;
1789}
1790
1791static int check_end_after_start(struct addr_filter *filt, u64 start, u64 size)
1792{
1793 if (start + size >= filt->addr)
1794 return 0;
1795
1796 if (filt->sym_from) {
1797 pr_err("Symbol '%s' (0x%"PRIx64") comes before '%s' (0x%"PRIx64")\n",
1798 filt->sym_to, start, filt->sym_from, filt->addr);
1799 } else {
1800 pr_err("Symbol '%s' (0x%"PRIx64") comes before address 0x%"PRIx64")\n",
1801 filt->sym_to, start, filt->addr);
1802 }
1803
1804 return -EINVAL;
1805}
1806
1807static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
1808{
1809 bool no_size = false;
1810 u64 start, size;
1811 int err;
1812
1813 if (symbol_conf.kptr_restrict) {
1814 pr_err("Kernel addresses are restricted. Unable to resolve kernel symbols.\n");
1815 return -EINVAL;
1816 }
1817
1818 if (filt->sym_from && !strcmp(filt->sym_from, "*"))
1819 return addr_filter__entire_kernel(filt);
1820
1821 if (filt->sym_from) {
1822 err = find_kern_sym(filt->sym_from, &start, &size,
1823 filt->sym_from_idx);
1824 if (err)
1825 return err;
1826 filt->addr = start;
1827 if (filt->range && !filt->size && !filt->sym_to) {
1828 filt->size = size;
1829 no_size = !!size;
1830 }
1831 }
1832
1833 if (filt->sym_to) {
1834 err = find_kern_sym(filt->sym_to, &start, &size,
1835 filt->sym_to_idx);
1836 if (err)
1837 return err;
1838
1839 err = check_end_after_start(filt, start, size);
1840 if (err)
1841 return err;
1842 filt->size = start + size - filt->addr;
1843 no_size = !!size;
1844 }
1845
1846 /* The very last symbol in kallsyms does not imply a particular size */
1847 if (no_size) {
1848 pr_err("Cannot determine size of symbol '%s'\n",
1849 filt->sym_to ? filt->sym_to : filt->sym_from);
1850 return -EINVAL;
1851 }
1852
1853 return 0;
1854}
1855
1856static struct dso *load_dso(const char *name)
1857{
1858 struct map *map;
1859 struct dso *dso;
1860
1861 map = dso__new_map(name);
1862 if (!map)
1863 return NULL;
1864
1865 map__load(map);
1866
1867 dso = dso__get(map->dso);
1868
1869 map__put(map);
1870
1871 return dso;
1872}
1873
1874static bool dso_sym_match(struct symbol *sym, const char *name, int *cnt,
1875 int idx)
1876{
1877 /* Same name, and global or the n'th found or any */
1878 return !arch__compare_symbol_names(name, sym->name) &&
1879 ((!idx && sym->binding == STB_GLOBAL) ||
1880 (idx > 0 && ++*cnt == idx) ||
1881 idx < 0);
1882}
1883
1884static void print_duplicate_syms(struct dso *dso, const char *sym_name)
1885{
1886 struct symbol *sym;
1887 bool near = false;
1888 int cnt = 0;
1889
1890 pr_err("Multiple symbols with name '%s'\n", sym_name);
1891
1892 sym = dso__first_symbol(dso, MAP__FUNCTION);
1893 while (sym) {
1894 if (dso_sym_match(sym, sym_name, &cnt, -1)) {
1895 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
1896 ++cnt, sym->start,
1897 sym->binding == STB_GLOBAL ? 'g' :
1898 sym->binding == STB_LOCAL ? 'l' : 'w',
1899 sym->name);
1900 near = true;
1901 } else if (near) {
1902 near = false;
1903 pr_err("\t\twhich is near\t\t%s\n", sym->name);
1904 }
1905 sym = dso__next_symbol(sym);
1906 }
1907
1908 pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
1909 sym_name);
1910 pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
1911}
1912
1913static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
1914 u64 *size, int idx)
1915{
1916 struct symbol *sym;
1917 int cnt = 0;
1918
1919 *start = 0;
1920 *size = 0;
1921
1922 sym = dso__first_symbol(dso, MAP__FUNCTION);
1923 while (sym) {
1924 if (*start) {
1925 if (!*size)
1926 *size = sym->start - *start;
1927 if (idx > 0) {
1928 if (*size)
1929 return 1;
1930 } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
1931 print_duplicate_syms(dso, sym_name);
1932 return -EINVAL;
1933 }
1934 } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
1935 *start = sym->start;
1936 *size = sym->end - sym->start;
1937 }
1938 sym = dso__next_symbol(sym);
1939 }
1940
1941 if (!*start)
1942 return sym_not_found_error(sym_name, idx);
1943
1944 return 0;
1945}
1946
1947static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso)
1948{
1949 struct symbol *first_sym = dso__first_symbol(dso, MAP__FUNCTION);
1950 struct symbol *last_sym = dso__last_symbol(dso, MAP__FUNCTION);
1951
1952 if (!first_sym || !last_sym) {
1953 pr_err("Failed to determine filter for %s\nNo symbols found.\n",
1954 filt->filename);
1955 return -EINVAL;
1956 }
1957
1958 filt->addr = first_sym->start;
1959 filt->size = last_sym->end - first_sym->start;
1960
1961 return 0;
1962}
1963
1964static int addr_filter__resolve_syms(struct addr_filter *filt)
1965{
1966 u64 start, size;
1967 struct dso *dso;
1968 int err = 0;
1969
1970 if (!filt->sym_from && !filt->sym_to)
1971 return 0;
1972
1973 if (!filt->filename)
1974 return addr_filter__resolve_kernel_syms(filt);
1975
1976 dso = load_dso(filt->filename);
1977 if (!dso) {
1978 pr_err("Failed to load symbols from: %s\n", filt->filename);
1979 return -EINVAL;
1980 }
1981
1982 if (filt->sym_from && !strcmp(filt->sym_from, "*")) {
1983 err = addr_filter__entire_dso(filt, dso);
1984 goto put_dso;
1985 }
1986
1987 if (filt->sym_from) {
1988 err = find_dso_sym(dso, filt->sym_from, &start, &size,
1989 filt->sym_from_idx);
1990 if (err)
1991 goto put_dso;
1992 filt->addr = start;
1993 if (filt->range && !filt->size && !filt->sym_to)
1994 filt->size = size;
1995 }
1996
1997 if (filt->sym_to) {
1998 err = find_dso_sym(dso, filt->sym_to, &start, &size,
1999 filt->sym_to_idx);
2000 if (err)
2001 goto put_dso;
2002
2003 err = check_end_after_start(filt, start, size);
2004 if (err)
2005 return err;
2006
2007 filt->size = start + size - filt->addr;
2008 }
2009
2010put_dso:
2011 dso__put(dso);
2012
2013 return err;
2014}
2015
2016static char *addr_filter__to_str(struct addr_filter *filt)
2017{
2018 char filename_buf[PATH_MAX];
2019 const char *at = "";
2020 const char *fn = "";
2021 char *filter;
2022 int err;
2023
2024 if (filt->filename) {
2025 at = "@";
2026 fn = realpath(filt->filename, filename_buf);
2027 if (!fn)
2028 return NULL;
2029 }
2030
2031 if (filt->range) {
2032 err = asprintf(&filter, "%s 0x%"PRIx64"/0x%"PRIx64"%s%s",
2033 filt->action, filt->addr, filt->size, at, fn);
2034 } else {
2035 err = asprintf(&filter, "%s 0x%"PRIx64"%s%s",
2036 filt->action, filt->addr, at, fn);
2037 }
2038
2039 return err < 0 ? NULL : filter;
2040}
2041
2042static int parse_addr_filter(struct perf_evsel *evsel, const char *filter,
2043 int max_nr)
2044{
2045 struct addr_filters filts;
2046 struct addr_filter *filt;
2047 int err;
2048
2049 addr_filters__init(&filts);
2050
2051 err = addr_filters__parse_bare_filter(&filts, filter);
2052 if (err)
2053 goto out_exit;
2054
2055 if (filts.cnt > max_nr) {
2056 pr_err("Error: number of address filters (%d) exceeds maximum (%d)\n",
2057 filts.cnt, max_nr);
2058 err = -EINVAL;
2059 goto out_exit;
2060 }
2061
2062 list_for_each_entry(filt, &filts.head, list) {
2063 char *new_filter;
2064
2065 err = addr_filter__resolve_syms(filt);
2066 if (err)
2067 goto out_exit;
2068
2069 new_filter = addr_filter__to_str(filt);
2070 if (!new_filter) {
2071 err = -ENOMEM;
2072 goto out_exit;
2073 }
2074
2075 if (perf_evsel__append_addr_filter(evsel, new_filter)) {
2076 err = -ENOMEM;
2077 goto out_exit;
2078 }
2079 }
2080
2081out_exit:
2082 addr_filters__exit(&filts);
2083
2084 if (err) {
2085 pr_err("Failed to parse address filter: '%s'\n", filter);
2086 pr_err("Filter format is: filter|start|stop|tracestop <start symbol or address> [/ <end symbol or size>] [@<file name>]\n");
2087 pr_err("Where multiple filters are separated by space or comma.\n");
2088 }
2089
2090 return err;
2091}
2092
2093static struct perf_pmu *perf_evsel__find_pmu(struct perf_evsel *evsel)
2094{
2095 struct perf_pmu *pmu = NULL;
2096
2097 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
2098 if (pmu->type == evsel->attr.type)
2099 break;
2100 }
2101
2102 return pmu;
2103}
2104
2105static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel)
2106{
2107 struct perf_pmu *pmu = perf_evsel__find_pmu(evsel);
2108 int nr_addr_filters = 0;
2109
2110 if (!pmu)
2111 return 0;
2112
2113 perf_pmu__scan_file(pmu, "nr_addr_filters", "%d", &nr_addr_filters);
2114
2115 return nr_addr_filters;
2116}
2117
2118int auxtrace_parse_filters(struct perf_evlist *evlist)
2119{
2120 struct perf_evsel *evsel;
2121 char *filter;
2122 int err, max_nr;
2123
2124 evlist__for_each_entry(evlist, evsel) {
2125 filter = evsel->filter;
2126 max_nr = perf_evsel__nr_addr_filter(evsel);
2127 if (!filter || !max_nr)
2128 continue;
2129 evsel->filter = NULL;
2130 err = parse_addr_filter(evsel, filter, max_nr);
2131 free(filter);
2132 if (err)
2133 return err;
2134 pr_debug("Address filter: %s\n", evsel->filter);
2135 }
2136
2137 return 0;
2138}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index ac5f0d7167e6..26fb1ee5746a 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -41,6 +41,7 @@ enum auxtrace_type {
41 PERF_AUXTRACE_UNKNOWN, 41 PERF_AUXTRACE_UNKNOWN,
42 PERF_AUXTRACE_INTEL_PT, 42 PERF_AUXTRACE_INTEL_PT,
43 PERF_AUXTRACE_INTEL_BTS, 43 PERF_AUXTRACE_INTEL_BTS,
44 PERF_AUXTRACE_CS_ETM,
44}; 45};
45 46
46enum itrace_period_type { 47enum itrace_period_type {
@@ -317,6 +318,48 @@ struct auxtrace_record {
317 unsigned int alignment; 318 unsigned int alignment;
318}; 319};
319 320
321/**
322 * struct addr_filter - address filter.
323 * @list: list node
324 * @range: true if it is a range filter
325 * @start: true if action is 'filter' or 'start'
326 * @action: 'filter', 'start' or 'stop' ('tracestop' is accepted but converted
327 * to 'stop')
328 * @sym_from: symbol name for the filter address
329 * @sym_to: symbol name that determines the filter size
330 * @sym_from_idx: selects n'th from symbols with the same name (0 means global
331 * and less than 0 means symbol must be unique)
332 * @sym_to_idx: same as @sym_from_idx but for @sym_to
333 * @addr: filter address
334 * @size: filter region size (for range filters)
335 * @filename: DSO file name or NULL for the kernel
336 * @str: allocated string that contains the other string members
337 */
338struct addr_filter {
339 struct list_head list;
340 bool range;
341 bool start;
342 const char *action;
343 const char *sym_from;
344 const char *sym_to;
345 int sym_from_idx;
346 int sym_to_idx;
347 u64 addr;
348 u64 size;
349 const char *filename;
350 char *str;
351};
352
353/**
354 * struct addr_filters - list of address filters.
355 * @head: list of address filters
356 * @cnt: number of address filters
357 */
358struct addr_filters {
359 struct list_head head;
360 int cnt;
361};
362
320#ifdef HAVE_AUXTRACE_SUPPORT 363#ifdef HAVE_AUXTRACE_SUPPORT
321 364
322/* 365/*
@@ -481,6 +524,12 @@ void perf_session__auxtrace_error_inc(struct perf_session *session,
481 union perf_event *event); 524 union perf_event *event);
482void events_stats__auxtrace_error_warn(const struct events_stats *stats); 525void events_stats__auxtrace_error_warn(const struct events_stats *stats);
483 526
527void addr_filters__init(struct addr_filters *filts);
528void addr_filters__exit(struct addr_filters *filts);
529int addr_filters__parse_bare_filter(struct addr_filters *filts,
530 const char *filter);
531int auxtrace_parse_filters(struct perf_evlist *evlist);
532
484static inline int auxtrace__process_event(struct perf_session *session, 533static inline int auxtrace__process_event(struct perf_session *session,
485 union perf_event *event, 534 union perf_event *event,
486 struct perf_sample *sample, 535 struct perf_sample *sample,
@@ -639,6 +688,12 @@ void auxtrace_index__free(struct list_head *head __maybe_unused)
639{ 688{
640} 689}
641 690
691static inline
692int auxtrace_parse_filters(struct perf_evlist *evlist __maybe_unused)
693{
694 return 0;
695}
696
642int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, 697int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
643 struct auxtrace_mmap_params *mp, 698 struct auxtrace_mmap_params *mp,
644 void *userpg, int fd); 699 void *userpg, int fd);
diff --git a/tools/perf/util/block-range.c b/tools/perf/util/block-range.c
new file mode 100644
index 000000000000..7b3e1d75d803
--- /dev/null
+++ b/tools/perf/util/block-range.c
@@ -0,0 +1,328 @@
1#include "block-range.h"
2#include "annotate.h"
3
4struct {
5 struct rb_root root;
6 u64 blocks;
7} block_ranges;
8
9static void block_range__debug(void)
10{
11 /*
12 * XXX still paranoid for now; see if we can make this depend on
13 * DEBUG=1 builds.
14 */
15#if 1
16 struct rb_node *rb;
17 u64 old = 0; /* NULL isn't executable */
18
19 for (rb = rb_first(&block_ranges.root); rb; rb = rb_next(rb)) {
20 struct block_range *entry = rb_entry(rb, struct block_range, node);
21
22 assert(old < entry->start);
23 assert(entry->start <= entry->end); /* single instruction block; jump to a jump */
24
25 old = entry->end;
26 }
27#endif
28}
29
30struct block_range *block_range__find(u64 addr)
31{
32 struct rb_node **p = &block_ranges.root.rb_node;
33 struct rb_node *parent = NULL;
34 struct block_range *entry;
35
36 while (*p != NULL) {
37 parent = *p;
38 entry = rb_entry(parent, struct block_range, node);
39
40 if (addr < entry->start)
41 p = &parent->rb_left;
42 else if (addr > entry->end)
43 p = &parent->rb_right;
44 else
45 return entry;
46 }
47
48 return NULL;
49}
50
51static inline void rb_link_left_of_node(struct rb_node *left, struct rb_node *node)
52{
53 struct rb_node **p = &node->rb_left;
54 while (*p) {
55 node = *p;
56 p = &node->rb_right;
57 }
58 rb_link_node(left, node, p);
59}
60
61static inline void rb_link_right_of_node(struct rb_node *right, struct rb_node *node)
62{
63 struct rb_node **p = &node->rb_right;
64 while (*p) {
65 node = *p;
66 p = &node->rb_left;
67 }
68 rb_link_node(right, node, p);
69}
70
71/**
72 * block_range__create
73 * @start: branch target starting this basic block
74 * @end: branch ending this basic block
75 *
76 * Create all the required block ranges to precisely span the given range.
77 */
78struct block_range_iter block_range__create(u64 start, u64 end)
79{
80 struct rb_node **p = &block_ranges.root.rb_node;
81 struct rb_node *n, *parent = NULL;
82 struct block_range *next, *entry = NULL;
83 struct block_range_iter iter = { NULL, NULL };
84
85 while (*p != NULL) {
86 parent = *p;
87 entry = rb_entry(parent, struct block_range, node);
88
89 if (start < entry->start)
90 p = &parent->rb_left;
91 else if (start > entry->end)
92 p = &parent->rb_right;
93 else
94 break;
95 }
96
97 /*
98 * Didn't find anything.. there's a hole at @start, however @end might
99 * be inside/behind the next range.
100 */
101 if (!*p) {
102 if (!entry) /* tree empty */
103 goto do_whole;
104
105 /*
106 * If the last node is before, advance one to find the next.
107 */
108 n = parent;
109 if (entry->end < start) {
110 n = rb_next(n);
111 if (!n)
112 goto do_whole;
113 }
114 next = rb_entry(n, struct block_range, node);
115
116 if (next->start <= end) { /* add head: [start...][n->start...] */
117 struct block_range *head = malloc(sizeof(struct block_range));
118 if (!head)
119 return iter;
120
121 *head = (struct block_range){
122 .start = start,
123 .end = next->start - 1,
124 .is_target = 1,
125 .is_branch = 0,
126 };
127
128 rb_link_left_of_node(&head->node, &next->node);
129 rb_insert_color(&head->node, &block_ranges.root);
130 block_range__debug();
131
132 iter.start = head;
133 goto do_tail;
134 }
135
136do_whole:
137 /*
138 * The whole [start..end] range is non-overlapping.
139 */
140 entry = malloc(sizeof(struct block_range));
141 if (!entry)
142 return iter;
143
144 *entry = (struct block_range){
145 .start = start,
146 .end = end,
147 .is_target = 1,
148 .is_branch = 1,
149 };
150
151 rb_link_node(&entry->node, parent, p);
152 rb_insert_color(&entry->node, &block_ranges.root);
153 block_range__debug();
154
155 iter.start = entry;
156 iter.end = entry;
157 goto done;
158 }
159
160 /*
161 * We found a range that overlapped with ours, split if needed.
162 */
163 if (entry->start < start) { /* split: [e->start...][start...] */
164 struct block_range *head = malloc(sizeof(struct block_range));
165 if (!head)
166 return iter;
167
168 *head = (struct block_range){
169 .start = entry->start,
170 .end = start - 1,
171 .is_target = entry->is_target,
172 .is_branch = 0,
173
174 .coverage = entry->coverage,
175 .entry = entry->entry,
176 };
177
178 entry->start = start;
179 entry->is_target = 1;
180 entry->entry = 0;
181
182 rb_link_left_of_node(&head->node, &entry->node);
183 rb_insert_color(&head->node, &block_ranges.root);
184 block_range__debug();
185
186 } else if (entry->start == start)
187 entry->is_target = 1;
188
189 iter.start = entry;
190
191do_tail:
192 /*
193 * At this point we've got: @iter.start = [@start...] but @end can still be
194 * inside or beyond it.
195 */
196 entry = iter.start;
197 for (;;) {
198 /*
199 * If @end is inside @entry, split.
200 */
201 if (end < entry->end) { /* split: [...end][...e->end] */
202 struct block_range *tail = malloc(sizeof(struct block_range));
203 if (!tail)
204 return iter;
205
206 *tail = (struct block_range){
207 .start = end + 1,
208 .end = entry->end,
209 .is_target = 0,
210 .is_branch = entry->is_branch,
211
212 .coverage = entry->coverage,
213 .taken = entry->taken,
214 .pred = entry->pred,
215 };
216
217 entry->end = end;
218 entry->is_branch = 1;
219 entry->taken = 0;
220 entry->pred = 0;
221
222 rb_link_right_of_node(&tail->node, &entry->node);
223 rb_insert_color(&tail->node, &block_ranges.root);
224 block_range__debug();
225
226 iter.end = entry;
227 goto done;
228 }
229
230 /*
231 * If @end matches @entry, done
232 */
233 if (end == entry->end) {
234 entry->is_branch = 1;
235 iter.end = entry;
236 goto done;
237 }
238
239 next = block_range__next(entry);
240 if (!next)
241 goto add_tail;
242
243 /*
244 * If @end is in beyond @entry but not inside @next, add tail.
245 */
246 if (end < next->start) { /* add tail: [...e->end][...end] */
247 struct block_range *tail;
248add_tail:
249 tail = malloc(sizeof(struct block_range));
250 if (!tail)
251 return iter;
252
253 *tail = (struct block_range){
254 .start = entry->end + 1,
255 .end = end,
256 .is_target = 0,
257 .is_branch = 1,
258 };
259
260 rb_link_right_of_node(&tail->node, &entry->node);
261 rb_insert_color(&tail->node, &block_ranges.root);
262 block_range__debug();
263
264 iter.end = tail;
265 goto done;
266 }
267
268 /*
269 * If there is a hole between @entry and @next, fill it.
270 */
271 if (entry->end + 1 != next->start) {
272 struct block_range *hole = malloc(sizeof(struct block_range));
273 if (!hole)
274 return iter;
275
276 *hole = (struct block_range){
277 .start = entry->end + 1,
278 .end = next->start - 1,
279 .is_target = 0,
280 .is_branch = 0,
281 };
282
283 rb_link_left_of_node(&hole->node, &next->node);
284 rb_insert_color(&hole->node, &block_ranges.root);
285 block_range__debug();
286 }
287
288 entry = next;
289 }
290
291done:
292 assert(iter.start->start == start && iter.start->is_target);
293 assert(iter.end->end == end && iter.end->is_branch);
294
295 block_ranges.blocks++;
296
297 return iter;
298}
299
300
301/*
302 * Compute coverage as:
303 *
304 * br->coverage / br->sym->max_coverage
305 *
306 * This ensures each symbol has a 100% spot, to reflect that each symbol has a
307 * most covered section.
308 *
309 * Returns [0-1] for coverage and -1 if we had no data what so ever or the
310 * symbol does not exist.
311 */
312double block_range__coverage(struct block_range *br)
313{
314 struct symbol *sym;
315
316 if (!br) {
317 if (block_ranges.blocks)
318 return 0;
319
320 return -1;
321 }
322
323 sym = br->sym;
324 if (!sym)
325 return -1;
326
327 return (double)br->coverage / symbol__annotation(sym)->max_coverage;
328}
diff --git a/tools/perf/util/block-range.h b/tools/perf/util/block-range.h
new file mode 100644
index 000000000000..a8c841381131
--- /dev/null
+++ b/tools/perf/util/block-range.h
@@ -0,0 +1,71 @@
1#ifndef __PERF_BLOCK_RANGE_H
2#define __PERF_BLOCK_RANGE_H
3
4#include "symbol.h"
5
6/*
7 * struct block_range - non-overlapping parts of basic blocks
8 * @node: treenode
9 * @start: inclusive start of range
10 * @end: inclusive end of range
11 * @is_target: @start is a jump target
12 * @is_branch: @end is a branch instruction
13 * @coverage: number of blocks that cover this range
14 * @taken: number of times the branch is taken (requires @is_branch)
15 * @pred: number of times the taken branch was predicted
16 */
17struct block_range {
18 struct rb_node node;
19
20 struct symbol *sym;
21
22 u64 start;
23 u64 end;
24
25 int is_target, is_branch;
26
27 u64 coverage;
28 u64 entry;
29 u64 taken;
30 u64 pred;
31};
32
33static inline struct block_range *block_range__next(struct block_range *br)
34{
35 struct rb_node *n = rb_next(&br->node);
36 if (!n)
37 return NULL;
38 return rb_entry(n, struct block_range, node);
39}
40
41struct block_range_iter {
42 struct block_range *start;
43 struct block_range *end;
44};
45
46static inline struct block_range *block_range_iter(struct block_range_iter *iter)
47{
48 return iter->start;
49}
50
51static inline bool block_range_iter__next(struct block_range_iter *iter)
52{
53 if (iter->start == iter->end)
54 return false;
55
56 iter->start = block_range__next(iter->start);
57 return true;
58}
59
60static inline bool block_range_iter__valid(struct block_range_iter *iter)
61{
62 if (!iter->start || !iter->end)
63 return false;
64 return true;
65}
66
67extern struct block_range *block_range__find(u64 addr);
68extern struct block_range_iter block_range__create(u64 start, u64 end);
69extern double block_range__coverage(struct block_range *br);
70
71#endif /* __PERF_BLOCK_RANGE_H */
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 1f12e4e40006..2b2c9b82f5ab 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -531,7 +531,7 @@ static int map_prologue(struct perf_probe_event *pev, int *mapping,
531 531
532 ptevs = malloc(array_sz); 532 ptevs = malloc(array_sz);
533 if (!ptevs) { 533 if (!ptevs) {
534 pr_debug("No ehough memory: alloc ptevs failed\n"); 534 pr_debug("No enough memory: alloc ptevs failed\n");
535 return -ENOMEM; 535 return -ENOMEM;
536 } 536 }
537 537
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 5651f3c12f93..e528c40739cc 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
620 620
621 ret = probe_cache__scan_sdt(cache, realname); 621 ret = probe_cache__scan_sdt(cache, realname);
622 if (ret >= 0) { 622 if (ret >= 0) {
623 pr_debug("Found %d SDTs in %s\n", ret, realname); 623 pr_debug4("Found %d SDTs in %s\n", ret, realname);
624 if (probe_cache__commit(cache) < 0) 624 if (probe_cache__commit(cache) < 0)
625 ret = -1; 625 ret = -1;
626 } 626 }
@@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
691 691
692 /* Update SDT cache : error is just warned */ 692 /* Update SDT cache : error is just warned */
693 if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0) 693 if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
694 pr_debug("Failed to update/scan SDT cache for %s\n", realname); 694 pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
695 695
696out_free: 696out_free:
697 if (!is_kallsyms) 697 if (!is_kallsyms)
diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
new file mode 100644
index 000000000000..3cc6bc3263fe
--- /dev/null
+++ b/tools/perf/util/cs-etm.h
@@ -0,0 +1,74 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef INCLUDE__UTIL_PERF_CS_ETM_H__
19#define INCLUDE__UTIL_PERF_CS_ETM_H__
20
21/* Versionning header in case things need tro change in the future. That way
22 * decoding of old snapshot is still possible.
23 */
24enum {
25 /* Starting with 0x0 */
26 CS_HEADER_VERSION_0,
27 /* PMU->type (32 bit), total # of CPUs (32 bit) */
28 CS_PMU_TYPE_CPUS,
29 CS_ETM_SNAPSHOT,
30 CS_HEADER_VERSION_0_MAX,
31};
32
33/* Beginning of header common to both ETMv3 and V4 */
34enum {
35 CS_ETM_MAGIC,
36 CS_ETM_CPU,
37};
38
39/* ETMv3/PTM metadata */
40enum {
41 /* Dynamic, configurable parameters */
42 CS_ETM_ETMCR = CS_ETM_CPU + 1,
43 CS_ETM_ETMTRACEIDR,
44 /* RO, taken from sysFS */
45 CS_ETM_ETMCCER,
46 CS_ETM_ETMIDR,
47 CS_ETM_PRIV_MAX,
48};
49
50/* ETMv4 metadata */
51enum {
52 /* Dynamic, configurable parameters */
53 CS_ETMV4_TRCCONFIGR = CS_ETM_CPU + 1,
54 CS_ETMV4_TRCTRACEIDR,
55 /* RO, taken from sysFS */
56 CS_ETMV4_TRCIDR0,
57 CS_ETMV4_TRCIDR1,
58 CS_ETMV4_TRCIDR2,
59 CS_ETMV4_TRCIDR8,
60 CS_ETMV4_TRCAUTHSTATUS,
61 CS_ETMV4_PRIV_MAX,
62};
63
64#define KiB(x) ((x) * 1024)
65#define MiB(x) ((x) * 1024 * 1024)
66
67#define CS_ETM_HEADER_SIZE (CS_HEADER_VERSION_0_MAX * sizeof(u64))
68
69static const u64 __perf_cs_etmv3_magic = 0x3030303030303030ULL;
70static const u64 __perf_cs_etmv4_magic = 0x4040404040404040ULL;
71#define CS_ETMV3_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64))
72#define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64))
73
74#endif
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 4f979bb27b6c..7123f4de32cc 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -437,7 +437,7 @@ add_bpf_output_values(struct bt_ctf_event_class *event_class,
437 int ret; 437 int ret;
438 438
439 if (nr_elements * sizeof(u32) != raw_size) 439 if (nr_elements * sizeof(u32) != raw_size)
440 pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n", 440 pr_warning("Incorrect raw_size (%u) in bpf output event, skip %zu bytes\n",
441 raw_size, nr_elements * sizeof(u32) - raw_size); 441 raw_size, nr_elements * sizeof(u32) - raw_size);
442 442
443 len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len"); 443 len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 8c4212abd19b..c1838b643108 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -6,6 +6,7 @@
6#include <stdarg.h> 6#include <stdarg.h>
7#include <stdio.h> 7#include <stdio.h>
8#include <api/debug.h> 8#include <api/debug.h>
9#include <linux/time64.h>
9 10
10#include "cache.h" 11#include "cache.h"
11#include "color.h" 12#include "color.h"
@@ -14,9 +15,6 @@
14#include "util.h" 15#include "util.h"
15#include "target.h" 16#include "target.h"
16 17
17#define NSECS_PER_SEC 1000000000ULL
18#define NSECS_PER_USEC 1000ULL
19
20int verbose; 18int verbose;
21bool dump_trace = false, quiet = false; 19bool dump_trace = false, quiet = false;
22int debug_ordered_events; 20int debug_ordered_events;
@@ -54,9 +52,9 @@ static int veprintf_time(u64 t, const char *fmt, va_list args)
54 int ret = 0; 52 int ret = 0;
55 u64 secs, usecs, nsecs = t; 53 u64 secs, usecs, nsecs = t;
56 54
57 secs = nsecs / NSECS_PER_SEC; 55 secs = nsecs / NSEC_PER_SEC;
58 nsecs -= secs * NSECS_PER_SEC; 56 nsecs -= secs * NSEC_PER_SEC;
59 usecs = nsecs / NSECS_PER_USEC; 57 usecs = nsecs / NSEC_PER_USEC;
60 58
61 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ", 59 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
62 secs, usecs); 60 secs, usecs);
diff --git a/tools/perf/util/drv_configs.c b/tools/perf/util/drv_configs.c
new file mode 100644
index 000000000000..1647f285c629
--- /dev/null
+++ b/tools/perf/util/drv_configs.c
@@ -0,0 +1,77 @@
1/*
2 * drv_configs.h: Interface to apply PMU specific configuration
3 * Copyright (c) 2016-2018, Linaro Ltd.
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 "drv_configs.h"
17#include "evlist.h"
18#include "evsel.h"
19#include "pmu.h"
20
21static int
22perf_evsel__apply_drv_configs(struct perf_evsel *evsel,
23 struct perf_evsel_config_term **err_term)
24{
25 bool found = false;
26 int err = 0;
27 struct perf_evsel_config_term *term;
28 struct perf_pmu *pmu = NULL;
29
30 while ((pmu = perf_pmu__scan(pmu)) != NULL)
31 if (pmu->type == evsel->attr.type) {
32 found = true;
33 break;
34 }
35
36 list_for_each_entry(term, &evsel->config_terms, list) {
37 if (term->type != PERF_EVSEL__CONFIG_TERM_DRV_CFG)
38 continue;
39
40 /*
41 * We have a configuration term, report an error if we
42 * can't find the PMU or if the PMU driver doesn't support
43 * cmd line driver configuration.
44 */
45 if (!found || !pmu->set_drv_config) {
46 err = -EINVAL;
47 *err_term = term;
48 break;
49 }
50
51 err = pmu->set_drv_config(term);
52 if (err) {
53 *err_term = term;
54 break;
55 }
56 }
57
58 return err;
59}
60
61int perf_evlist__apply_drv_configs(struct perf_evlist *evlist,
62 struct perf_evsel **err_evsel,
63 struct perf_evsel_config_term **err_term)
64{
65 struct perf_evsel *evsel;
66 int err = 0;
67
68 evlist__for_each_entry(evlist, evsel) {
69 err = perf_evsel__apply_drv_configs(evsel, err_term);
70 if (err) {
71 *err_evsel = evsel;
72 break;
73 }
74 }
75
76 return err;
77}
diff --git a/tools/perf/util/drv_configs.h b/tools/perf/util/drv_configs.h
new file mode 100644
index 000000000000..32bc9babc2e0
--- /dev/null
+++ b/tools/perf/util/drv_configs.h
@@ -0,0 +1,26 @@
1/*
2 * drv_configs.h: Interface to apply PMU specific configuration
3 * Copyright (c) 2016-2018, Linaro Ltd.
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_DRV_CONFIGS_H
17#define __PERF_DRV_CONFIGS_H
18
19#include "drv_configs.h"
20#include "evlist.h"
21#include "evsel.h"
22
23int perf_evlist__apply_drv_configs(struct perf_evlist *evlist,
24 struct perf_evsel **err_evsel,
25 struct perf_evsel_config_term **term);
26#endif
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 774f6ec884d5..d2c6cdd9d42b 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -363,6 +363,9 @@ static int __open_dso(struct dso *dso, struct machine *machine)
363 return -EINVAL; 363 return -EINVAL;
364 } 364 }
365 365
366 if (!is_regular_file(name))
367 return -EINVAL;
368
366 fd = do_open(name); 369 fd = do_open(name);
367 free(name); 370 free(name);
368 return fd; 371 return fd;
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index a347b19c961a..41e068e94349 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -130,6 +130,22 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
130} 130}
131 131
132/** 132/**
133 * die_get_linkage_name - Get the linkage name of the object
134 * @dw_die: A DIE of the object
135 *
136 * Get the linkage name attiribute of given @dw_die.
137 * For C++ binary, the linkage name will be the mangled symbol.
138 */
139const char *die_get_linkage_name(Dwarf_Die *dw_die)
140{
141 Dwarf_Attribute attr;
142
143 if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
144 return NULL;
145 return dwarf_formstring(&attr);
146}
147
148/**
133 * die_compare_name - Compare diename and tname 149 * die_compare_name - Compare diename and tname
134 * @dw_die: a DIE 150 * @dw_die: a DIE
135 * @tname: a string of target name 151 * @tname: a string of target name
@@ -145,18 +161,26 @@ bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
145} 161}
146 162
147/** 163/**
148 * die_match_name - Match diename and glob 164 * die_match_name - Match diename/linkage name and glob
149 * @dw_die: a DIE 165 * @dw_die: a DIE
150 * @glob: a string of target glob pattern 166 * @glob: a string of target glob pattern
151 * 167 *
152 * Glob matching the name of @dw_die and @glob. Return false if matching fail. 168 * Glob matching the name of @dw_die and @glob. Return false if matching fail.
169 * This also match linkage name.
153 */ 170 */
154bool die_match_name(Dwarf_Die *dw_die, const char *glob) 171bool die_match_name(Dwarf_Die *dw_die, const char *glob)
155{ 172{
156 const char *name; 173 const char *name;
157 174
158 name = dwarf_diename(dw_die); 175 name = dwarf_diename(dw_die);
159 return name ? strglobmatch(name, glob) : false; 176 if (name && strglobmatch(name, glob))
177 return true;
178 /* fall back to check linkage name */
179 name = die_get_linkage_name(dw_die);
180 if (name && strglobmatch(name, glob))
181 return true;
182
183 return false;
160} 184}
161 185
162/** 186/**
@@ -1085,3 +1109,182 @@ int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
1085 return -ENOTSUP; 1109 return -ENOTSUP;
1086} 1110}
1087#endif 1111#endif
1112
1113/*
1114 * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
1115 * @vr_die: a variable DIE
1116 */
1117static bool die_has_loclist(Dwarf_Die *vr_die)
1118{
1119 Dwarf_Attribute loc;
1120 int tag = dwarf_tag(vr_die);
1121
1122 if (tag != DW_TAG_formal_parameter &&
1123 tag != DW_TAG_variable)
1124 return false;
1125
1126 return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
1127 dwarf_whatform(&loc) == DW_FORM_sec_offset);
1128}
1129
1130/*
1131 * die_is_optimized_target - Check if target program is compiled with
1132 * optimization
1133 * @cu_die: a CU DIE
1134 *
1135 * For any object in given CU whose DW_AT_location is a location list,
1136 * target program is compiled with optimization. This is applicable to
1137 * clang as well.
1138 */
1139bool die_is_optimized_target(Dwarf_Die *cu_die)
1140{
1141 Dwarf_Die tmp_die;
1142
1143 if (die_has_loclist(cu_die))
1144 return true;
1145
1146 if (!dwarf_child(cu_die, &tmp_die) &&
1147 die_is_optimized_target(&tmp_die))
1148 return true;
1149
1150 if (!dwarf_siblingof(cu_die, &tmp_die) &&
1151 die_is_optimized_target(&tmp_die))
1152 return true;
1153
1154 return false;
1155}
1156
1157/*
1158 * die_search_idx - Search index of given line address
1159 * @lines: Line records of single CU
1160 * @nr_lines: Number of @lines
1161 * @addr: address we are looking for
1162 * @idx: index to be set by this function (return value)
1163 *
1164 * Search for @addr by looping over every lines of CU. If address
1165 * matches, set index of that line in @idx. Note that single source
1166 * line can have multiple line records. i.e. single source line can
1167 * have multiple index.
1168 */
1169static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
1170 Dwarf_Addr addr, unsigned long *idx)
1171{
1172 unsigned long i;
1173 Dwarf_Addr tmp;
1174
1175 for (i = 0; i < nr_lines; i++) {
1176 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
1177 return false;
1178
1179 if (tmp == addr) {
1180 *idx = i;
1181 return true;
1182 }
1183 }
1184 return false;
1185}
1186
1187/*
1188 * die_get_postprologue_addr - Search next address after function prologue
1189 * @entrypc_idx: entrypc index
1190 * @lines: Line records of single CU
1191 * @nr_lines: Number of @lines
1192 * @hignpc: high PC address of function
1193 * @postprologue_addr: Next address after function prologue (return value)
1194 *
1195 * Look for prologue-end marker. If there is no explicit marker, return
1196 * address of next line record or next source line.
1197 */
1198static bool die_get_postprologue_addr(unsigned long entrypc_idx,
1199 Dwarf_Lines *lines,
1200 unsigned long nr_lines,
1201 Dwarf_Addr highpc,
1202 Dwarf_Addr *postprologue_addr)
1203{
1204 unsigned long i;
1205 int entrypc_lno, lno;
1206 Dwarf_Line *line;
1207 Dwarf_Addr addr;
1208 bool p_end;
1209
1210 /* entrypc_lno is actual source line number */
1211 line = dwarf_onesrcline(lines, entrypc_idx);
1212 if (dwarf_lineno(line, &entrypc_lno))
1213 return false;
1214
1215 for (i = entrypc_idx; i < nr_lines; i++) {
1216 line = dwarf_onesrcline(lines, i);
1217
1218 if (dwarf_lineaddr(line, &addr) ||
1219 dwarf_lineno(line, &lno) ||
1220 dwarf_lineprologueend(line, &p_end))
1221 return false;
1222
1223 /* highpc is exclusive. [entrypc,highpc) */
1224 if (addr >= highpc)
1225 break;
1226
1227 /* clang supports prologue-end marker */
1228 if (p_end)
1229 break;
1230
1231 /* Actual next line in source */
1232 if (lno != entrypc_lno)
1233 break;
1234
1235 /*
1236 * Single source line can have multiple line records.
1237 * For Example,
1238 * void foo() { printf("hello\n"); }
1239 * contains two line records. One points to declaration and
1240 * other points to printf() line. Variable 'lno' won't get
1241 * incremented in this case but 'i' will.
1242 */
1243 if (i != entrypc_idx)
1244 break;
1245 }
1246
1247 dwarf_lineaddr(line, postprologue_addr);
1248 if (*postprologue_addr >= highpc)
1249 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1250 postprologue_addr);
1251
1252 return true;
1253}
1254
1255/*
1256 * die_skip_prologue - Use next address after prologue as probe location
1257 * @sp_die: a subprogram DIE
1258 * @cu_die: a CU DIE
1259 * @entrypc: entrypc of the function
1260 *
1261 * Function prologue prepares stack and registers before executing function
1262 * logic. When target program is compiled without optimization, function
1263 * parameter information is only valid after prologue. When we probe entrypc
1264 * of the function, and try to record function parameter, it contains
1265 * garbage value.
1266 */
1267void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
1268 Dwarf_Addr *entrypc)
1269{
1270 size_t nr_lines = 0;
1271 unsigned long entrypc_idx = 0;
1272 Dwarf_Lines *lines = NULL;
1273 Dwarf_Addr postprologue_addr;
1274 Dwarf_Addr highpc;
1275
1276 if (dwarf_highpc(sp_die, &highpc))
1277 return;
1278
1279 if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
1280 return;
1281
1282 if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
1283 return;
1284
1285 if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
1286 highpc, &postprologue_addr))
1287 return;
1288
1289 *entrypc = postprologue_addr;
1290}
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index dc0ce1adb075..8ac53bf1ec4e 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -38,6 +38,9 @@ int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
38int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, 38int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
39 int (*callback)(Dwarf_Die *, void *), void *data); 39 int (*callback)(Dwarf_Die *, void *), void *data);
40 40
41/* Get DW_AT_linkage_name (should be NULL for C binary) */
42const char *die_get_linkage_name(Dwarf_Die *dw_die);
43
41/* Ensure that this DIE is a subprogram and definition (not declaration) */ 44/* Ensure that this DIE is a subprogram and definition (not declaration) */
42bool die_is_func_def(Dwarf_Die *dw_die); 45bool die_is_func_def(Dwarf_Die *dw_die);
43 46
@@ -125,4 +128,12 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
125/* Get the name and type of given variable DIE, stored as "type\tname" */ 128/* Get the name and type of given variable DIE, stored as "type\tname" */
126int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf); 129int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
127int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); 130int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);
131
132/* Check if target program is compiled with optimization */
133bool die_is_optimized_target(Dwarf_Die *cu_die);
134
135/* Use next address after prologue as probe location */
136void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
137 Dwarf_Addr *entrypc);
138
128#endif 139#endif
diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c
new file mode 100644
index 000000000000..62bc4a86a970
--- /dev/null
+++ b/tools/perf/util/dwarf-regs.c
@@ -0,0 +1,59 @@
1/*
2 * dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
3 *
4 * Written by: Masami Hiramatsu <mhiramat@kernel.org>
5 */
6
7#include <util.h>
8#include <debug.h>
9#include <dwarf-regs.h>
10#include <elf.h>
11
12#ifndef EM_AARCH64
13#define EM_AARCH64 183 /* ARM 64 bit */
14#endif
15
16/* Define const char * {arch}_register_tbl[] */
17#define DEFINE_DWARF_REGSTR_TABLE
18#include "../arch/x86/include/dwarf-regs-table.h"
19#include "../arch/arm/include/dwarf-regs-table.h"
20#include "../arch/arm64/include/dwarf-regs-table.h"
21#include "../arch/sh/include/dwarf-regs-table.h"
22#include "../arch/powerpc/include/dwarf-regs-table.h"
23#include "../arch/s390/include/dwarf-regs-table.h"
24#include "../arch/sparc/include/dwarf-regs-table.h"
25#include "../arch/xtensa/include/dwarf-regs-table.h"
26
27#define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL)
28
29/* Return architecture dependent register string (for kprobe-tracer) */
30const char *get_dwarf_regstr(unsigned int n, unsigned int machine)
31{
32 switch (machine) {
33 case EM_NONE: /* Generic arch - use host arch */
34 return get_arch_regstr(n);
35 case EM_386:
36 return __get_dwarf_regstr(x86_32_regstr_tbl, n);
37 case EM_X86_64:
38 return __get_dwarf_regstr(x86_64_regstr_tbl, n);
39 case EM_ARM:
40 return __get_dwarf_regstr(arm_regstr_tbl, n);
41 case EM_AARCH64:
42 return __get_dwarf_regstr(aarch64_regstr_tbl, n);
43 case EM_SH:
44 return __get_dwarf_regstr(sh_regstr_tbl, n);
45 case EM_S390:
46 return __get_dwarf_regstr(s390_regstr_tbl, n);
47 case EM_PPC:
48 case EM_PPC64:
49 return __get_dwarf_regstr(powerpc_regstr_tbl, n);
50 case EM_SPARC:
51 case EM_SPARCV9:
52 return __get_dwarf_regstr(sparc_regstr_tbl, n);
53 case EM_XTENSA:
54 return __get_dwarf_regstr(xtensa_regstr_tbl, n);
55 default:
56 pr_err("ELF MACHINE %x is not supported.\n", machine);
57 }
58 return NULL;
59}
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index e20438b784be..8ab0d7da956b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,5 +1,6 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <sys/mman.h> 2#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
3#include <api/fs/fs.h>
3#include "event.h" 4#include "event.h"
4#include "debug.h" 5#include "debug.h"
5#include "hist.h" 6#include "hist.h"
@@ -248,6 +249,8 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
248 bool truncation = false; 249 bool truncation = false;
249 unsigned long long timeout = proc_map_timeout * 1000000ULL; 250 unsigned long long timeout = proc_map_timeout * 1000000ULL;
250 int rc = 0; 251 int rc = 0;
252 const char *hugetlbfs_mnt = hugetlbfs__mountpoint();
253 int hugetlbfs_mnt_len = hugetlbfs_mnt ? strlen(hugetlbfs_mnt) : 0;
251 254
252 if (machine__is_default_guest(machine)) 255 if (machine__is_default_guest(machine))
253 return 0; 256 return 0;
@@ -343,6 +346,12 @@ out:
343 if (!strcmp(execname, "")) 346 if (!strcmp(execname, ""))
344 strcpy(execname, anonstr); 347 strcpy(execname, anonstr);
345 348
349 if (hugetlbfs_mnt_len &&
350 !strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {
351 strcpy(execname, anonstr);
352 event->mmap2.flags |= MAP_HUGETLB;
353 }
354
346 size = strlen(execname) + 1; 355 size = strlen(execname) + 1;
347 memcpy(event->mmap2.filename, execname, size); 356 memcpy(event->mmap2.filename, execname, size);
348 size = PERF_ALIGN(size, sizeof(u64)); 357 size = PERF_ALIGN(size, sizeof(u64));
@@ -1286,7 +1295,7 @@ try_again:
1286 * must be done prior to using kernel maps. 1295 * must be done prior to using kernel maps.
1287 */ 1296 */
1288 if (load_map) 1297 if (load_map)
1289 map__load(al->map, machine->symbol_filter); 1298 map__load(al->map);
1290 al->addr = al->map->map_ip(al->map, al->addr); 1299 al->addr = al->map->map_ip(al->map, al->addr);
1291 } 1300 }
1292} 1301}
@@ -1297,8 +1306,7 @@ void thread__find_addr_location(struct thread *thread,
1297{ 1306{
1298 thread__find_addr_map(thread, cpumode, type, addr, al); 1307 thread__find_addr_map(thread, cpumode, type, addr, al);
1299 if (al->map != NULL) 1308 if (al->map != NULL)
1300 al->sym = map__find_symbol(al->map, al->addr, 1309 al->sym = map__find_symbol(al->map, al->addr);
1301 thread->mg->machine->symbol_filter);
1302 else 1310 else
1303 al->sym = NULL; 1311 al->sym = NULL;
1304} 1312}
@@ -1359,8 +1367,7 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
1359 al->filtered |= (1 << HIST_FILTER__DSO); 1367 al->filtered |= (1 << HIST_FILTER__DSO);
1360 } 1368 }
1361 1369
1362 al->sym = map__find_symbol(al->map, al->addr, 1370 al->sym = map__find_symbol(al->map, al->addr);
1363 machine->symbol_filter);
1364 } 1371 }
1365 1372
1366 if (symbol_conf.sym_list && 1373 if (symbol_conf.sym_list &&
@@ -1416,5 +1423,5 @@ void thread__resolve(struct thread *thread, struct addr_location *al,
1416 al->sym = NULL; 1423 al->sym = NULL;
1417 1424
1418 if (al->map) 1425 if (al->map)
1419 al->sym = map__find_symbol(al->map, al->addr, NULL); 1426 al->sym = map__find_symbol(al->map, al->addr);
1420} 1427}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 097b3ed77fdd..ea34c5a32c11 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1032,16 +1032,18 @@ perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused,
1032} 1032}
1033 1033
1034static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, 1034static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
1035 struct mmap_params *mp, int cpu, 1035 struct mmap_params *mp, int cpu_idx,
1036 int thread, int *_output, int *_output_backward) 1036 int thread, int *_output, int *_output_backward)
1037{ 1037{
1038 struct perf_evsel *evsel; 1038 struct perf_evsel *evsel;
1039 int revent; 1039 int revent;
1040 int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx);
1040 1041
1041 evlist__for_each_entry(evlist, evsel) { 1042 evlist__for_each_entry(evlist, evsel) {
1042 struct perf_mmap *maps = evlist->mmap; 1043 struct perf_mmap *maps = evlist->mmap;
1043 int *output = _output; 1044 int *output = _output;
1044 int fd; 1045 int fd;
1046 int cpu;
1045 1047
1046 if (evsel->attr.write_backward) { 1048 if (evsel->attr.write_backward) {
1047 output = _output_backward; 1049 output = _output_backward;
@@ -1060,6 +1062,10 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
1060 if (evsel->system_wide && thread) 1062 if (evsel->system_wide && thread)
1061 continue; 1063 continue;
1062 1064
1065 cpu = cpu_map__idx(evsel->cpus, evlist_cpu);
1066 if (cpu == -1)
1067 continue;
1068
1063 fd = FD(evsel, cpu, thread); 1069 fd = FD(evsel, cpu, thread);
1064 1070
1065 if (*output == -1) { 1071 if (*output == -1) {
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21fd573106ed..380e84c3af3d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1045,15 +1045,15 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter)
1045 return -1; 1045 return -1;
1046} 1046}
1047 1047
1048int perf_evsel__append_filter(struct perf_evsel *evsel, 1048static int perf_evsel__append_filter(struct perf_evsel *evsel,
1049 const char *op, const char *filter) 1049 const char *fmt, const char *filter)
1050{ 1050{
1051 char *new_filter; 1051 char *new_filter;
1052 1052
1053 if (evsel->filter == NULL) 1053 if (evsel->filter == NULL)
1054 return perf_evsel__set_filter(evsel, filter); 1054 return perf_evsel__set_filter(evsel, filter);
1055 1055
1056 if (asprintf(&new_filter,"(%s) %s (%s)", evsel->filter, op, filter) > 0) { 1056 if (asprintf(&new_filter, fmt, evsel->filter, filter) > 0) {
1057 free(evsel->filter); 1057 free(evsel->filter);
1058 evsel->filter = new_filter; 1058 evsel->filter = new_filter;
1059 return 0; 1059 return 0;
@@ -1062,6 +1062,16 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
1062 return -1; 1062 return -1;
1063} 1063}
1064 1064
1065int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter)
1066{
1067 return perf_evsel__append_filter(evsel, "(%s) && (%s)", filter);
1068}
1069
1070int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter)
1071{
1072 return perf_evsel__append_filter(evsel, "%s,%s", filter);
1073}
1074
1065int perf_evsel__enable(struct perf_evsel *evsel) 1075int perf_evsel__enable(struct perf_evsel *evsel)
1066{ 1076{
1067 int nthreads = thread_map__nr(evsel->threads); 1077 int nthreads = thread_map__nr(evsel->threads);
@@ -1728,7 +1738,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1728 data->cpu = data->pid = data->tid = -1; 1738 data->cpu = data->pid = data->tid = -1;
1729 data->stream_id = data->id = data->time = -1ULL; 1739 data->stream_id = data->id = data->time = -1ULL;
1730 data->period = evsel->attr.sample_period; 1740 data->period = evsel->attr.sample_period;
1731 data->weight = 0;
1732 data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1741 data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1733 1742
1734 if (event->header.type != PERF_RECORD_SAMPLE) { 1743 if (event->header.type != PERF_RECORD_SAMPLE) {
@@ -1935,7 +1944,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1935 } 1944 }
1936 } 1945 }
1937 1946
1938 data->weight = 0;
1939 if (type & PERF_SAMPLE_WEIGHT) { 1947 if (type & PERF_SAMPLE_WEIGHT) {
1940 OVERFLOW_CHECK_u64(array); 1948 OVERFLOW_CHECK_u64(array);
1941 data->weight = *array; 1949 data->weight = *array;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4d44129e050b..b1503b0ecdff 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -46,6 +46,7 @@ enum {
46 PERF_EVSEL__CONFIG_TERM_INHERIT, 46 PERF_EVSEL__CONFIG_TERM_INHERIT,
47 PERF_EVSEL__CONFIG_TERM_MAX_STACK, 47 PERF_EVSEL__CONFIG_TERM_MAX_STACK,
48 PERF_EVSEL__CONFIG_TERM_OVERWRITE, 48 PERF_EVSEL__CONFIG_TERM_OVERWRITE,
49 PERF_EVSEL__CONFIG_TERM_DRV_CFG,
49 PERF_EVSEL__CONFIG_TERM_MAX, 50 PERF_EVSEL__CONFIG_TERM_MAX,
50}; 51};
51 52
@@ -57,6 +58,7 @@ struct perf_evsel_config_term {
57 u64 freq; 58 u64 freq;
58 bool time; 59 bool time;
59 char *callgraph; 60 char *callgraph;
61 char *drv_cfg;
60 u64 stack_user; 62 u64 stack_user;
61 int max_stack; 63 int max_stack;
62 bool inherit; 64 bool inherit;
@@ -233,8 +235,9 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
233 bool use_sample_identifier); 235 bool use_sample_identifier);
234 236
235int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter); 237int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter);
236int perf_evsel__append_filter(struct perf_evsel *evsel, 238int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter);
237 const char *op, const char *filter); 239int perf_evsel__append_addr_filter(struct perf_evsel *evsel,
240 const char *filter);
238int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 241int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
239 const char *filter); 242 const char *filter);
240int perf_evsel__enable(struct perf_evsel *evsel); 243int perf_evsel__enable(struct perf_evsel *evsel);
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 3674e77ad640..662a0a6182e7 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -122,9 +122,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
122 if (!node) 122 if (!node)
123 break; 123 break;
124 124
125 if (node->sym && node->sym->ignore)
126 goto next;
127
128 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); 125 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
129 126
130 if (print_ip) 127 if (print_ip)
@@ -158,7 +155,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
158 155
159 if (!print_oneline) 156 if (!print_oneline)
160 printed += fprintf(fp, "\n"); 157 printed += fprintf(fp, "\n");
161next: 158
162 callchain_cursor_advance(cursor); 159 callchain_cursor_advance(cursor);
163 } 160 }
164 } 161 }
@@ -181,7 +178,7 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
181 if (cursor != NULL) { 178 if (cursor != NULL) {
182 printed += sample__fprintf_callchain(sample, left_alignment, 179 printed += sample__fprintf_callchain(sample, left_alignment,
183 print_opts, cursor, fp); 180 print_opts, cursor, fp);
184 } else if (!(al->sym && al->sym->ignore)) { 181 } else {
185 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); 182 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
186 183
187 if (print_ip) 184 if (print_ip)
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 8f0db4007282..85dd0db0a127 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -828,8 +828,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
828 * default get_cpuid(): nothing gets recorded 828 * default get_cpuid(): nothing gets recorded
829 * actual implementation must be in arch/$(ARCH)/util/header.c 829 * actual implementation must be in arch/$(ARCH)/util/header.c
830 */ 830 */
831int __attribute__ ((weak)) get_cpuid(char *buffer __maybe_unused, 831int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
832 size_t sz __maybe_unused)
833{ 832{
834 return -1; 833 return -1;
835} 834}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index de15dbcdcecf..b02992efb513 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -177,8 +177,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
177 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); 177 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
178 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); 178 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
179 179
180 if (h->srcline) 180 if (h->srcline) {
181 hists__new_col_len(hists, HISTC_SRCLINE, strlen(h->srcline)); 181 len = MAX(strlen(h->srcline), strlen(sort_srcline.se_header));
182 hists__new_col_len(hists, HISTC_SRCLINE, len);
183 }
182 184
183 if (h->srcfile) 185 if (h->srcfile)
184 hists__new_col_len(hists, HISTC_SRCFILE, strlen(h->srcfile)); 186 hists__new_col_len(hists, HISTC_SRCFILE, strlen(h->srcfile));
@@ -417,6 +419,8 @@ static int hist_entry__init(struct hist_entry *he,
417 } 419 }
418 INIT_LIST_HEAD(&he->pairs.node); 420 INIT_LIST_HEAD(&he->pairs.node);
419 thread__get(he->thread); 421 thread__get(he->thread);
422 he->hroot_in = RB_ROOT;
423 he->hroot_out = RB_ROOT;
420 424
421 if (!symbol_conf.report_hierarchy) 425 if (!symbol_conf.report_hierarchy)
422 he->leaf = true; 426 he->leaf = true;
@@ -2149,6 +2153,50 @@ out:
2149 return he; 2153 return he;
2150} 2154}
2151 2155
2156static struct hist_entry *add_dummy_hierarchy_entry(struct hists *hists,
2157 struct rb_root *root,
2158 struct hist_entry *pair)
2159{
2160 struct rb_node **p;
2161 struct rb_node *parent = NULL;
2162 struct hist_entry *he;
2163 struct perf_hpp_fmt *fmt;
2164
2165 p = &root->rb_node;
2166 while (*p != NULL) {
2167 int64_t cmp = 0;
2168
2169 parent = *p;
2170 he = rb_entry(parent, struct hist_entry, rb_node_in);
2171
2172 perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
2173 cmp = fmt->collapse(fmt, he, pair);
2174 if (cmp)
2175 break;
2176 }
2177 if (!cmp)
2178 goto out;
2179
2180 if (cmp < 0)
2181 p = &parent->rb_left;
2182 else
2183 p = &parent->rb_right;
2184 }
2185
2186 he = hist_entry__new(pair, true);
2187 if (he) {
2188 rb_link_node(&he->rb_node_in, parent, p);
2189 rb_insert_color(&he->rb_node_in, root);
2190
2191 he->dummy = true;
2192 he->hists = hists;
2193 memset(&he->stat, 0, sizeof(he->stat));
2194 hists__inc_stats(hists, he);
2195 }
2196out:
2197 return he;
2198}
2199
2152static struct hist_entry *hists__find_entry(struct hists *hists, 2200static struct hist_entry *hists__find_entry(struct hists *hists,
2153 struct hist_entry *he) 2201 struct hist_entry *he)
2154{ 2202{
@@ -2174,6 +2222,51 @@ static struct hist_entry *hists__find_entry(struct hists *hists,
2174 return NULL; 2222 return NULL;
2175} 2223}
2176 2224
2225static struct hist_entry *hists__find_hierarchy_entry(struct rb_root *root,
2226 struct hist_entry *he)
2227{
2228 struct rb_node *n = root->rb_node;
2229
2230 while (n) {
2231 struct hist_entry *iter;
2232 struct perf_hpp_fmt *fmt;
2233 int64_t cmp = 0;
2234
2235 iter = rb_entry(n, struct hist_entry, rb_node_in);
2236 perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
2237 cmp = fmt->collapse(fmt, iter, he);
2238 if (cmp)
2239 break;
2240 }
2241
2242 if (cmp < 0)
2243 n = n->rb_left;
2244 else if (cmp > 0)
2245 n = n->rb_right;
2246 else
2247 return iter;
2248 }
2249
2250 return NULL;
2251}
2252
2253static void hists__match_hierarchy(struct rb_root *leader_root,
2254 struct rb_root *other_root)
2255{
2256 struct rb_node *nd;
2257 struct hist_entry *pos, *pair;
2258
2259 for (nd = rb_first(leader_root); nd; nd = rb_next(nd)) {
2260 pos = rb_entry(nd, struct hist_entry, rb_node_in);
2261 pair = hists__find_hierarchy_entry(other_root, pos);
2262
2263 if (pair) {
2264 hist_entry__add_pair(pair, pos);
2265 hists__match_hierarchy(&pos->hroot_in, &pair->hroot_in);
2266 }
2267 }
2268}
2269
2177/* 2270/*
2178 * Look for pairs to link to the leader buckets (hist_entries): 2271 * Look for pairs to link to the leader buckets (hist_entries):
2179 */ 2272 */
@@ -2183,6 +2276,12 @@ void hists__match(struct hists *leader, struct hists *other)
2183 struct rb_node *nd; 2276 struct rb_node *nd;
2184 struct hist_entry *pos, *pair; 2277 struct hist_entry *pos, *pair;
2185 2278
2279 if (symbol_conf.report_hierarchy) {
2280 /* hierarchy report always collapses entries */
2281 return hists__match_hierarchy(&leader->entries_collapsed,
2282 &other->entries_collapsed);
2283 }
2284
2186 if (hists__has(leader, need_collapse)) 2285 if (hists__has(leader, need_collapse))
2187 root = &leader->entries_collapsed; 2286 root = &leader->entries_collapsed;
2188 else 2287 else
@@ -2197,6 +2296,50 @@ void hists__match(struct hists *leader, struct hists *other)
2197 } 2296 }
2198} 2297}
2199 2298
2299static int hists__link_hierarchy(struct hists *leader_hists,
2300 struct hist_entry *parent,
2301 struct rb_root *leader_root,
2302 struct rb_root *other_root)
2303{
2304 struct rb_node *nd;
2305 struct hist_entry *pos, *leader;
2306
2307 for (nd = rb_first(other_root); nd; nd = rb_next(nd)) {
2308 pos = rb_entry(nd, struct hist_entry, rb_node_in);
2309
2310 if (hist_entry__has_pairs(pos)) {
2311 bool found = false;
2312
2313 list_for_each_entry(leader, &pos->pairs.head, pairs.node) {
2314 if (leader->hists == leader_hists) {
2315 found = true;
2316 break;
2317 }
2318 }
2319 if (!found)
2320 return -1;
2321 } else {
2322 leader = add_dummy_hierarchy_entry(leader_hists,
2323 leader_root, pos);
2324 if (leader == NULL)
2325 return -1;
2326
2327 /* do not point parent in the pos */
2328 leader->parent_he = parent;
2329
2330 hist_entry__add_pair(pos, leader);
2331 }
2332
2333 if (!pos->leaf) {
2334 if (hists__link_hierarchy(leader_hists, leader,
2335 &leader->hroot_in,
2336 &pos->hroot_in) < 0)
2337 return -1;
2338 }
2339 }
2340 return 0;
2341}
2342
2200/* 2343/*
2201 * Look for entries in the other hists that are not present in the leader, if 2344 * Look for entries in the other hists that are not present in the leader, if
2202 * we find them, just add a dummy entry on the leader hists, with period=0, 2345 * we find them, just add a dummy entry on the leader hists, with period=0,
@@ -2208,6 +2351,13 @@ int hists__link(struct hists *leader, struct hists *other)
2208 struct rb_node *nd; 2351 struct rb_node *nd;
2209 struct hist_entry *pos, *pair; 2352 struct hist_entry *pos, *pair;
2210 2353
2354 if (symbol_conf.report_hierarchy) {
2355 /* hierarchy report always collapses entries */
2356 return hists__link_hierarchy(leader, NULL,
2357 &leader->entries_collapsed,
2358 &other->entries_collapsed);
2359 }
2360
2211 if (hists__has(other, need_collapse)) 2361 if (hists__has(other, need_collapse))
2212 root = &other->entries_collapsed; 2362 root = &other->entries_collapsed;
2213 else 2363 else
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 0a1edf1ab450..9928fed8bc59 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -230,7 +230,7 @@ struct perf_hpp {
230struct perf_hpp_fmt { 230struct perf_hpp_fmt {
231 const char *name; 231 const char *name;
232 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 232 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
233 struct hists *hists); 233 struct hists *hists, int line, int *span);
234 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 234 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
235 struct hists *hists); 235 struct hists *hists);
236 int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 236 int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -259,6 +259,7 @@ struct perf_hpp_list {
259 struct list_head fields; 259 struct list_head fields;
260 struct list_head sorts; 260 struct list_head sorts;
261 261
262 int nr_header_lines;
262 int need_collapse; 263 int need_collapse;
263 int parent; 264 int parent;
264 int sym; 265 int sym;
@@ -367,6 +368,7 @@ static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format,
367void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 368void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
368void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists); 369void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists);
369void perf_hpp__set_user_width(const char *width_list_str); 370void perf_hpp__set_user_width(const char *width_list_str);
371void hists__reset_column_width(struct hists *hists);
370 372
371typedef u64 (*hpp_field_fn)(struct hist_entry *he); 373typedef u64 (*hpp_field_fn)(struct hist_entry *he);
372typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); 374typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front);
@@ -483,5 +485,10 @@ static inline struct rb_node *rb_hierarchy_next(struct rb_node *node)
483#define HIERARCHY_INDENT 3 485#define HIERARCHY_INDENT 3
484 486
485bool hist_entry__has_hierarchy_children(struct hist_entry *he, float limit); 487bool hist_entry__has_hierarchy_children(struct hist_entry *he, float limit);
488int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...);
489int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...);
490int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp,
491 struct perf_hpp_list *hpp_list);
492int hists__fprintf_headers(struct hists *hists, FILE *fp);
486 493
487#endif /* __PERF_HIST_H */ 494#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index 07c644ed64c4..43bfd8da7919 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -3,6 +3,12 @@
3 3
4#ifdef HAVE_DWARF_SUPPORT 4#ifdef HAVE_DWARF_SUPPORT
5const char *get_arch_regstr(unsigned int n); 5const char *get_arch_regstr(unsigned int n);
6/*
7 * get_dwarf_regstr - Returns ftrace register string from DWARF regnum
8 * n: DWARF register number
9 * machine: ELF machine signature (EM_*)
10 */
11const char *get_dwarf_regstr(unsigned int n, unsigned int machine);
6#endif 12#endif
7 13
8#ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET 14#ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 749e6f2e37ca..f545ec1e758a 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -346,7 +346,7 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
346 goto out_put; 346 goto out_put;
347 347
348 /* Load maps to ensure dso->is_64_bit has been updated */ 348 /* Load maps to ensure dso->is_64_bit has been updated */
349 map__load(al.map, machine->symbol_filter); 349 map__load(al.map);
350 350
351 x86_64 = al.map->dso->is_64_bit; 351 x86_64 = al.map->dso->is_64_bit;
352 352
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 8ff6c6a61291..7591a0c37473 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -80,6 +80,7 @@ struct intel_pt_decoder {
80 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, 80 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
81 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, 81 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
82 uint64_t max_insn_cnt, void *data); 82 uint64_t max_insn_cnt, void *data);
83 bool (*pgd_ip)(uint64_t ip, void *data);
83 void *data; 84 void *data;
84 struct intel_pt_state state; 85 struct intel_pt_state state;
85 const unsigned char *buf; 86 const unsigned char *buf;
@@ -186,6 +187,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
186 187
187 decoder->get_trace = params->get_trace; 188 decoder->get_trace = params->get_trace;
188 decoder->walk_insn = params->walk_insn; 189 decoder->walk_insn = params->walk_insn;
190 decoder->pgd_ip = params->pgd_ip;
189 decoder->data = params->data; 191 decoder->data = params->data;
190 decoder->return_compression = params->return_compression; 192 decoder->return_compression = params->return_compression;
191 193
@@ -1008,6 +1010,19 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1008 int err; 1010 int err;
1009 1011
1010 err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0); 1012 err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0);
1013 if (err == INTEL_PT_RETURN &&
1014 decoder->pgd_ip &&
1015 decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
1016 (decoder->state.type & INTEL_PT_BRANCH) &&
1017 decoder->pgd_ip(decoder->state.to_ip, decoder->data)) {
1018 /* Unconditional branch leaving filter region */
1019 decoder->no_progress = 0;
1020 decoder->pge = false;
1021 decoder->continuous_period = false;
1022 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1023 decoder->state.to_ip = 0;
1024 return 0;
1025 }
1011 if (err == INTEL_PT_RETURN) 1026 if (err == INTEL_PT_RETURN)
1012 return 0; 1027 return 0;
1013 if (err) 1028 if (err)
@@ -1036,6 +1051,21 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1036 } 1051 }
1037 1052
1038 if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) { 1053 if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
1054 uint64_t to_ip = decoder->ip + intel_pt_insn.length +
1055 intel_pt_insn.rel;
1056
1057 if (decoder->pgd_ip &&
1058 decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
1059 decoder->pgd_ip(to_ip, decoder->data)) {
1060 /* Conditional branch leaving filter region */
1061 decoder->pge = false;
1062 decoder->continuous_period = false;
1063 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1064 decoder->ip = to_ip;
1065 decoder->state.from_ip = decoder->ip;
1066 decoder->state.to_ip = 0;
1067 return 0;
1068 }
1039 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch", 1069 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch",
1040 decoder->ip); 1070 decoder->ip);
1041 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; 1071 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 02c38fec1c37..89399985fa4d 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -83,6 +83,7 @@ struct intel_pt_params {
83 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, 83 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
84 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, 84 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
85 uint64_t max_insn_cnt, void *data); 85 uint64_t max_insn_cnt, void *data);
86 bool (*pgd_ip)(uint64_t ip, void *data);
86 void *data; 87 void *data;
87 bool return_compression; 88 bool return_compression;
88 uint64_t period; 89 uint64_t period;
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 551ff6f640be..dc041d4368c8 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -103,6 +103,9 @@ struct intel_pt {
103 unsigned max_non_turbo_ratio; 103 unsigned max_non_turbo_ratio;
104 104
105 unsigned long num_events; 105 unsigned long num_events;
106
107 char *filter;
108 struct addr_filters filts;
106}; 109};
107 110
108enum switch_state { 111enum switch_state {
@@ -241,7 +244,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
241 } 244 }
242 245
243 queue = &ptq->pt->queues.queue_array[ptq->queue_nr]; 246 queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
244 247next:
245 buffer = auxtrace_buffer__next(queue, buffer); 248 buffer = auxtrace_buffer__next(queue, buffer);
246 if (!buffer) { 249 if (!buffer) {
247 if (old_buffer) 250 if (old_buffer)
@@ -264,9 +267,6 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
264 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer)) 267 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
265 return -ENOMEM; 268 return -ENOMEM;
266 269
267 if (old_buffer)
268 auxtrace_buffer__drop_data(old_buffer);
269
270 if (buffer->use_data) { 270 if (buffer->use_data) {
271 b->len = buffer->use_size; 271 b->len = buffer->use_size;
272 b->buf = buffer->use_data; 272 b->buf = buffer->use_data;
@@ -276,6 +276,16 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
276 } 276 }
277 b->ref_timestamp = buffer->reference; 277 b->ref_timestamp = buffer->reference;
278 278
279 /*
280 * If in snapshot mode and the buffer has no usable data, get next
281 * buffer and again check overlap against old_buffer.
282 */
283 if (ptq->pt->snapshot_mode && !b->len)
284 goto next;
285
286 if (old_buffer)
287 auxtrace_buffer__drop_data(old_buffer);
288
279 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode && 289 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
280 !buffer->consecutive)) { 290 !buffer->consecutive)) {
281 b->consecutive = false; 291 b->consecutive = false;
@@ -477,7 +487,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
477 start_ip = *ip; 487 start_ip = *ip;
478 488
479 /* Load maps to ensure dso->is_64_bit has been updated */ 489 /* Load maps to ensure dso->is_64_bit has been updated */
480 map__load(al.map, machine->symbol_filter); 490 map__load(al.map);
481 491
482 x86_64 = al.map->dso->is_64_bit; 492 x86_64 = al.map->dso->is_64_bit;
483 493
@@ -541,6 +551,76 @@ out_no_cache:
541 return 0; 551 return 0;
542} 552}
543 553
554static bool intel_pt_match_pgd_ip(struct intel_pt *pt, uint64_t ip,
555 uint64_t offset, const char *filename)
556{
557 struct addr_filter *filt;
558 bool have_filter = false;
559 bool hit_tracestop = false;
560 bool hit_filter = false;
561
562 list_for_each_entry(filt, &pt->filts.head, list) {
563 if (filt->start)
564 have_filter = true;
565
566 if ((filename && !filt->filename) ||
567 (!filename && filt->filename) ||
568 (filename && strcmp(filename, filt->filename)))
569 continue;
570
571 if (!(offset >= filt->addr && offset < filt->addr + filt->size))
572 continue;
573
574 intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s hit filter: %s offset %#"PRIx64" size %#"PRIx64"\n",
575 ip, offset, filename ? filename : "[kernel]",
576 filt->start ? "filter" : "stop",
577 filt->addr, filt->size);
578
579 if (filt->start)
580 hit_filter = true;
581 else
582 hit_tracestop = true;
583 }
584
585 if (!hit_tracestop && !hit_filter)
586 intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s is not in a filter region\n",
587 ip, offset, filename ? filename : "[kernel]");
588
589 return hit_tracestop || (have_filter && !hit_filter);
590}
591
592static int __intel_pt_pgd_ip(uint64_t ip, void *data)
593{
594 struct intel_pt_queue *ptq = data;
595 struct thread *thread;
596 struct addr_location al;
597 u8 cpumode;
598 u64 offset;
599
600 if (ip >= ptq->pt->kernel_start)
601 return intel_pt_match_pgd_ip(ptq->pt, ip, ip, NULL);
602
603 cpumode = PERF_RECORD_MISC_USER;
604
605 thread = ptq->thread;
606 if (!thread)
607 return -EINVAL;
608
609 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, ip, &al);
610 if (!al.map || !al.map->dso)
611 return -EINVAL;
612
613 offset = al.map->map_ip(al.map, ip);
614
615 return intel_pt_match_pgd_ip(ptq->pt, ip, offset,
616 al.map->dso->long_name);
617}
618
619static bool intel_pt_pgd_ip(uint64_t ip, void *data)
620{
621 return __intel_pt_pgd_ip(ip, data) > 0;
622}
623
544static bool intel_pt_get_config(struct intel_pt *pt, 624static bool intel_pt_get_config(struct intel_pt *pt,
545 struct perf_event_attr *attr, u64 *config) 625 struct perf_event_attr *attr, u64 *config)
546{ 626{
@@ -717,6 +797,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
717 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n; 797 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
718 params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d; 798 params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d;
719 799
800 if (pt->filts.cnt > 0)
801 params.pgd_ip = intel_pt_pgd_ip;
802
720 if (pt->synth_opts.instructions) { 803 if (pt->synth_opts.instructions) {
721 if (pt->synth_opts.period) { 804 if (pt->synth_opts.period) {
722 switch (pt->synth_opts.period_type) { 805 switch (pt->synth_opts.period_type) {
@@ -1294,7 +1377,7 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
1294 if (!map) 1377 if (!map)
1295 return 0; 1378 return 0;
1296 1379
1297 if (map__load(map, machine->symbol_filter)) 1380 if (map__load(map))
1298 return 0; 1381 return 0;
1299 1382
1300 start = dso__first_symbol(map->dso, MAP__FUNCTION); 1383 start = dso__first_symbol(map->dso, MAP__FUNCTION);
@@ -1767,6 +1850,8 @@ static void intel_pt_free(struct perf_session *session)
1767 intel_pt_free_events(session); 1850 intel_pt_free_events(session);
1768 session->auxtrace = NULL; 1851 session->auxtrace = NULL;
1769 thread__put(pt->unknown_thread); 1852 thread__put(pt->unknown_thread);
1853 addr_filters__exit(&pt->filts);
1854 zfree(&pt->filter);
1770 free(pt); 1855 free(pt);
1771} 1856}
1772 1857
@@ -2016,6 +2101,8 @@ static const char * const intel_pt_info_fmts[] = {
2016 [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n", 2101 [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n",
2017 [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", 2102 [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n",
2018 [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", 2103 [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n",
2104 [INTEL_PT_MAX_NONTURBO_RATIO] = " Max non-turbo ratio %"PRIu64"\n",
2105 [INTEL_PT_FILTER_STR_LEN] = " Filter string len. %"PRIu64"\n",
2019}; 2106};
2020 2107
2021static void intel_pt_print_info(u64 *arr, int start, int finish) 2108static void intel_pt_print_info(u64 *arr, int start, int finish)
@@ -2029,12 +2116,28 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)
2029 fprintf(stdout, intel_pt_info_fmts[i], arr[i]); 2116 fprintf(stdout, intel_pt_info_fmts[i], arr[i]);
2030} 2117}
2031 2118
2119static void intel_pt_print_info_str(const char *name, const char *str)
2120{
2121 if (!dump_trace)
2122 return;
2123
2124 fprintf(stdout, " %-20s%s\n", name, str ? str : "");
2125}
2126
2127static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos)
2128{
2129 return auxtrace_info->header.size >=
2130 sizeof(struct auxtrace_info_event) + (sizeof(u64) * (pos + 1));
2131}
2132
2032int intel_pt_process_auxtrace_info(union perf_event *event, 2133int intel_pt_process_auxtrace_info(union perf_event *event,
2033 struct perf_session *session) 2134 struct perf_session *session)
2034{ 2135{
2035 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info; 2136 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
2036 size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS; 2137 size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS;
2037 struct intel_pt *pt; 2138 struct intel_pt *pt;
2139 void *info_end;
2140 u64 *info;
2038 int err; 2141 int err;
2039 2142
2040 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) + 2143 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
@@ -2045,6 +2148,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2045 if (!pt) 2148 if (!pt)
2046 return -ENOMEM; 2149 return -ENOMEM;
2047 2150
2151 addr_filters__init(&pt->filts);
2152
2048 perf_config(intel_pt_perf_config, pt); 2153 perf_config(intel_pt_perf_config, pt);
2049 2154
2050 err = auxtrace_queues__init(&pt->queues); 2155 err = auxtrace_queues__init(&pt->queues);
@@ -2069,8 +2174,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2069 intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE, 2174 intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE,
2070 INTEL_PT_PER_CPU_MMAPS); 2175 INTEL_PT_PER_CPU_MMAPS);
2071 2176
2072 if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) + 2177 if (intel_pt_has(auxtrace_info, INTEL_PT_CYC_BIT)) {
2073 (sizeof(u64) * INTEL_PT_CYC_BIT)) {
2074 pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT]; 2178 pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT];
2075 pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS]; 2179 pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS];
2076 pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N]; 2180 pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N];
@@ -2080,6 +2184,54 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2080 INTEL_PT_CYC_BIT); 2184 INTEL_PT_CYC_BIT);
2081 } 2185 }
2082 2186
2187 if (intel_pt_has(auxtrace_info, INTEL_PT_MAX_NONTURBO_RATIO)) {
2188 pt->max_non_turbo_ratio =
2189 auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO];
2190 intel_pt_print_info(&auxtrace_info->priv[0],
2191 INTEL_PT_MAX_NONTURBO_RATIO,
2192 INTEL_PT_MAX_NONTURBO_RATIO);
2193 }
2194
2195 info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
2196 info_end = (void *)info + auxtrace_info->header.size;
2197
2198 if (intel_pt_has(auxtrace_info, INTEL_PT_FILTER_STR_LEN)) {
2199 size_t len;
2200
2201 len = auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN];
2202 intel_pt_print_info(&auxtrace_info->priv[0],
2203 INTEL_PT_FILTER_STR_LEN,
2204 INTEL_PT_FILTER_STR_LEN);
2205 if (len) {
2206 const char *filter = (const char *)info;
2207
2208 len = roundup(len + 1, 8);
2209 info += len >> 3;
2210 if ((void *)info > info_end) {
2211 pr_err("%s: bad filter string length\n", __func__);
2212 err = -EINVAL;
2213 goto err_free_queues;
2214 }
2215 pt->filter = memdup(filter, len);
2216 if (!pt->filter) {
2217 err = -ENOMEM;
2218 goto err_free_queues;
2219 }
2220 if (session->header.needs_swap)
2221 mem_bswap_64(pt->filter, len);
2222 if (pt->filter[len - 1]) {
2223 pr_err("%s: filter string not null terminated\n", __func__);
2224 err = -EINVAL;
2225 goto err_free_queues;
2226 }
2227 err = addr_filters__parse_bare_filter(&pt->filts,
2228 filter);
2229 if (err)
2230 goto err_free_queues;
2231 }
2232 intel_pt_print_info_str("Filter string", pt->filter);
2233 }
2234
2083 pt->timeless_decoding = intel_pt_timeless_decoding(pt); 2235 pt->timeless_decoding = intel_pt_timeless_decoding(pt);
2084 pt->have_tsc = intel_pt_have_tsc(pt); 2236 pt->have_tsc = intel_pt_have_tsc(pt);
2085 pt->sampling_mode = false; 2237 pt->sampling_mode = false;
@@ -2121,11 +2273,13 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2121 pt->switch_evsel = intel_pt_find_sched_switch(session->evlist); 2273 pt->switch_evsel = intel_pt_find_sched_switch(session->evlist);
2122 if (!pt->switch_evsel) { 2274 if (!pt->switch_evsel) {
2123 pr_err("%s: missing sched_switch event\n", __func__); 2275 pr_err("%s: missing sched_switch event\n", __func__);
2276 err = -EINVAL;
2124 goto err_delete_thread; 2277 goto err_delete_thread;
2125 } 2278 }
2126 } else if (pt->have_sched_switch == 2 && 2279 } else if (pt->have_sched_switch == 2 &&
2127 !intel_pt_find_switch(session->evlist)) { 2280 !intel_pt_find_switch(session->evlist)) {
2128 pr_err("%s: missing context_switch attribute flag\n", __func__); 2281 pr_err("%s: missing context_switch attribute flag\n", __func__);
2282 err = -EINVAL;
2129 goto err_delete_thread; 2283 goto err_delete_thread;
2130 } 2284 }
2131 2285
@@ -2149,7 +2303,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2149 if (pt->tc.time_mult) { 2303 if (pt->tc.time_mult) {
2150 u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000); 2304 u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000);
2151 2305
2152 pt->max_non_turbo_ratio = (tsc_freq + 50000000) / 100000000; 2306 if (!pt->max_non_turbo_ratio)
2307 pt->max_non_turbo_ratio =
2308 (tsc_freq + 50000000) / 100000000;
2153 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq); 2309 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq);
2154 intel_pt_log("Maximum non-turbo ratio %u\n", 2310 intel_pt_log("Maximum non-turbo ratio %u\n",
2155 pt->max_non_turbo_ratio); 2311 pt->max_non_turbo_ratio);
@@ -2193,6 +2349,8 @@ err_free_queues:
2193 auxtrace_queues__free(&pt->queues); 2349 auxtrace_queues__free(&pt->queues);
2194 session->auxtrace = NULL; 2350 session->auxtrace = NULL;
2195err_free: 2351err_free:
2352 addr_filters__exit(&pt->filts);
2353 zfree(&pt->filter);
2196 free(pt); 2354 free(pt);
2197 return err; 2355 return err;
2198} 2356}
diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h
index 0065949df693..e13b14e5a37b 100644
--- a/tools/perf/util/intel-pt.h
+++ b/tools/perf/util/intel-pt.h
@@ -34,11 +34,11 @@ enum {
34 INTEL_PT_TSC_CTC_N, 34 INTEL_PT_TSC_CTC_N,
35 INTEL_PT_TSC_CTC_D, 35 INTEL_PT_TSC_CTC_D,
36 INTEL_PT_CYC_BIT, 36 INTEL_PT_CYC_BIT,
37 INTEL_PT_MAX_NONTURBO_RATIO,
38 INTEL_PT_FILTER_STR_LEN,
37 INTEL_PT_AUXTRACE_PRIV_MAX, 39 INTEL_PT_AUXTRACE_PRIV_MAX,
38}; 40};
39 41
40#define INTEL_PT_AUXTRACE_PRIV_SIZE (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64))
41
42struct auxtrace_record; 42struct auxtrace_record;
43struct perf_tool; 43struct perf_tool;
44union perf_event; 44union perf_event;
diff --git a/tools/perf/util/lzma.c b/tools/perf/util/lzma.c
index 95a1acb61245..9ddea5cecd94 100644
--- a/tools/perf/util/lzma.c
+++ b/tools/perf/util/lzma.c
@@ -29,6 +29,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
29 lzma_action action = LZMA_RUN; 29 lzma_action action = LZMA_RUN;
30 lzma_stream strm = LZMA_STREAM_INIT; 30 lzma_stream strm = LZMA_STREAM_INIT;
31 lzma_ret ret; 31 lzma_ret ret;
32 int err = -1;
32 33
33 u8 buf_in[BUFSIZE]; 34 u8 buf_in[BUFSIZE];
34 u8 buf_out[BUFSIZE]; 35 u8 buf_out[BUFSIZE];
@@ -45,7 +46,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
45 if (ret != LZMA_OK) { 46 if (ret != LZMA_OK) {
46 pr_err("lzma: lzma_stream_decoder failed %s (%d)\n", 47 pr_err("lzma: lzma_stream_decoder failed %s (%d)\n",
47 lzma_strerror(ret), ret); 48 lzma_strerror(ret), ret);
48 return -1; 49 goto err_fclose;
49 } 50 }
50 51
51 strm.next_in = NULL; 52 strm.next_in = NULL;
@@ -60,7 +61,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
60 61
61 if (ferror(infile)) { 62 if (ferror(infile)) {
62 pr_err("lzma: read error: %s\n", strerror(errno)); 63 pr_err("lzma: read error: %s\n", strerror(errno));
63 return -1; 64 goto err_fclose;
64 } 65 }
65 66
66 if (feof(infile)) 67 if (feof(infile))
@@ -74,7 +75,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
74 75
75 if (writen(output_fd, buf_out, write_size) != write_size) { 76 if (writen(output_fd, buf_out, write_size) != write_size) {
76 pr_err("lzma: write error: %s\n", strerror(errno)); 77 pr_err("lzma: write error: %s\n", strerror(errno));
77 return -1; 78 goto err_fclose;
78 } 79 }
79 80
80 strm.next_out = buf_out; 81 strm.next_out = buf_out;
@@ -83,13 +84,15 @@ int lzma_decompress_to_file(const char *input, int output_fd)
83 84
84 if (ret != LZMA_OK) { 85 if (ret != LZMA_OK) {
85 if (ret == LZMA_STREAM_END) 86 if (ret == LZMA_STREAM_END)
86 return 0; 87 break;
87 88
88 pr_err("lzma: failed %s\n", lzma_strerror(ret)); 89 pr_err("lzma: failed %s\n", lzma_strerror(ret));
89 return -1; 90 goto err_fclose;
90 } 91 }
91 } 92 }
92 93
94 err = 0;
95err_fclose:
93 fclose(infile); 96 fclose(infile);
94 return 0; 97 return err;
95} 98}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index cb6388dbdd98..18e4519abef2 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -41,7 +41,6 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
41 41
42 machine->pid = pid; 42 machine->pid = pid;
43 43
44 machine->symbol_filter = NULL;
45 machine->id_hdr_size = 0; 44 machine->id_hdr_size = 0;
46 machine->kptr_restrict_warned = false; 45 machine->kptr_restrict_warned = false;
47 machine->comm_exec = false; 46 machine->comm_exec = false;
@@ -148,7 +147,6 @@ void machines__init(struct machines *machines)
148{ 147{
149 machine__init(&machines->host, "", HOST_KERNEL_ID); 148 machine__init(&machines->host, "", HOST_KERNEL_ID);
150 machines->guests = RB_ROOT; 149 machines->guests = RB_ROOT;
151 machines->symbol_filter = NULL;
152} 150}
153 151
154void machines__exit(struct machines *machines) 152void machines__exit(struct machines *machines)
@@ -172,8 +170,6 @@ struct machine *machines__add(struct machines *machines, pid_t pid,
172 return NULL; 170 return NULL;
173 } 171 }
174 172
175 machine->symbol_filter = machines->symbol_filter;
176
177 while (*p != NULL) { 173 while (*p != NULL) {
178 parent = *p; 174 parent = *p;
179 pos = rb_entry(parent, struct machine, rb_node); 175 pos = rb_entry(parent, struct machine, rb_node);
@@ -189,21 +185,6 @@ struct machine *machines__add(struct machines *machines, pid_t pid,
189 return machine; 185 return machine;
190} 186}
191 187
192void machines__set_symbol_filter(struct machines *machines,
193 symbol_filter_t symbol_filter)
194{
195 struct rb_node *nd;
196
197 machines->symbol_filter = symbol_filter;
198 machines->host.symbol_filter = symbol_filter;
199
200 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
201 struct machine *machine = rb_entry(nd, struct machine, rb_node);
202
203 machine->symbol_filter = symbol_filter;
204 }
205}
206
207void machines__set_comm_exec(struct machines *machines, bool comm_exec) 188void machines__set_comm_exec(struct machines *machines, bool comm_exec)
208{ 189{
209 struct rb_node *nd; 190 struct rb_node *nd;
@@ -916,10 +897,10 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
916} 897}
917 898
918int __machine__load_kallsyms(struct machine *machine, const char *filename, 899int __machine__load_kallsyms(struct machine *machine, const char *filename,
919 enum map_type type, bool no_kcore, symbol_filter_t filter) 900 enum map_type type, bool no_kcore)
920{ 901{
921 struct map *map = machine__kernel_map(machine); 902 struct map *map = machine__kernel_map(machine);
922 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore, filter); 903 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore);
923 904
924 if (ret > 0) { 905 if (ret > 0) {
925 dso__set_loaded(map->dso, type); 906 dso__set_loaded(map->dso, type);
@@ -935,16 +916,15 @@ int __machine__load_kallsyms(struct machine *machine, const char *filename,
935} 916}
936 917
937int machine__load_kallsyms(struct machine *machine, const char *filename, 918int machine__load_kallsyms(struct machine *machine, const char *filename,
938 enum map_type type, symbol_filter_t filter) 919 enum map_type type)
939{ 920{
940 return __machine__load_kallsyms(machine, filename, type, false, filter); 921 return __machine__load_kallsyms(machine, filename, type, false);
941} 922}
942 923
943int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 924int machine__load_vmlinux_path(struct machine *machine, enum map_type type)
944 symbol_filter_t filter)
945{ 925{
946 struct map *map = machine__kernel_map(machine); 926 struct map *map = machine__kernel_map(machine);
947 int ret = dso__load_vmlinux_path(map->dso, map, filter); 927 int ret = dso__load_vmlinux_path(map->dso, map);
948 928
949 if (ret > 0) 929 if (ret > 0)
950 dso__set_loaded(map->dso, type); 930 dso__set_loaded(map->dso, type);
@@ -1313,7 +1293,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1313 /* 1293 /*
1314 * preload dso of guest kernel and modules 1294 * preload dso of guest kernel and modules
1315 */ 1295 */
1316 dso__load(kernel, machine__kernel_map(machine), NULL); 1296 dso__load(kernel, machine__kernel_map(machine));
1317 } 1297 }
1318 } 1298 }
1319 return 0; 1299 return 0;
@@ -2115,7 +2095,7 @@ int machine__get_kernel_start(struct machine *machine)
2115 */ 2095 */
2116 machine->kernel_start = 1ULL << 63; 2096 machine->kernel_start = 1ULL << 63;
2117 if (map) { 2097 if (map) {
2118 err = map__load(map, machine->symbol_filter); 2098 err = map__load(map);
2119 if (map->start) 2099 if (map->start)
2120 machine->kernel_start = map->start; 2100 machine->kernel_start = map->start;
2121 } 2101 }
@@ -2131,7 +2111,7 @@ char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, ch
2131{ 2111{
2132 struct machine *machine = vmachine; 2112 struct machine *machine = vmachine;
2133 struct map *map; 2113 struct map *map;
2134 struct symbol *sym = map_groups__find_symbol(&machine->kmaps, MAP__FUNCTION, *addrp, &map, NULL); 2114 struct symbol *sym = map_groups__find_symbol(&machine->kmaps, MAP__FUNCTION, *addrp, &map);
2135 2115
2136 if (sym == NULL) 2116 if (sym == NULL)
2137 return NULL; 2117 return NULL;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 20739f746bc4..354de6e56109 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -41,7 +41,6 @@ struct machine {
41 struct map_groups kmaps; 41 struct map_groups kmaps;
42 struct map *vmlinux_maps[MAP__NR_TYPES]; 42 struct map *vmlinux_maps[MAP__NR_TYPES];
43 u64 kernel_start; 43 u64 kernel_start;
44 symbol_filter_t symbol_filter;
45 pid_t *current_tid; 44 pid_t *current_tid;
46 union { /* Tool specific area */ 45 union { /* Tool specific area */
47 void *priv; 46 void *priv;
@@ -110,7 +109,6 @@ typedef void (*machine__process_t)(struct machine *machine, void *data);
110struct machines { 109struct machines {
111 struct machine host; 110 struct machine host;
112 struct rb_root guests; 111 struct rb_root guests;
113 symbol_filter_t symbol_filter;
114}; 112};
115 113
116void machines__init(struct machines *machines); 114void machines__init(struct machines *machines);
@@ -128,8 +126,6 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid);
128void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); 126void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
129char *machine__mmap_name(struct machine *machine, char *bf, size_t size); 127char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
130 128
131void machines__set_symbol_filter(struct machines *machines,
132 symbol_filter_t symbol_filter);
133void machines__set_comm_exec(struct machines *machines, bool comm_exec); 129void machines__set_comm_exec(struct machines *machines, bool comm_exec);
134 130
135struct machine *machine__new_host(void); 131struct machine *machine__new_host(void);
@@ -178,40 +174,33 @@ size_t machine__fprintf(struct machine *machine, FILE *fp);
178static inline 174static inline
179struct symbol *machine__find_kernel_symbol(struct machine *machine, 175struct symbol *machine__find_kernel_symbol(struct machine *machine,
180 enum map_type type, u64 addr, 176 enum map_type type, u64 addr,
181 struct map **mapp, 177 struct map **mapp)
182 symbol_filter_t filter)
183{ 178{
184 return map_groups__find_symbol(&machine->kmaps, type, addr, 179 return map_groups__find_symbol(&machine->kmaps, type, addr, mapp);
185 mapp, filter);
186} 180}
187 181
188static inline 182static inline
189struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine, 183struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine,
190 enum map_type type, const char *name, 184 enum map_type type, const char *name,
191 struct map **mapp, 185 struct map **mapp)
192 symbol_filter_t filter)
193{ 186{
194 return map_groups__find_symbol_by_name(&machine->kmaps, type, name, 187 return map_groups__find_symbol_by_name(&machine->kmaps, type, name, mapp);
195 mapp, filter);
196} 188}
197 189
198static inline 190static inline
199struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr, 191struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr,
200 struct map **mapp, 192 struct map **mapp)
201 symbol_filter_t filter)
202{ 193{
203 return machine__find_kernel_symbol(machine, MAP__FUNCTION, addr, 194 return machine__find_kernel_symbol(machine, MAP__FUNCTION, addr,
204 mapp, filter); 195 mapp);
205} 196}
206 197
207static inline 198static inline
208struct symbol *machine__find_kernel_function_by_name(struct machine *machine, 199struct symbol *machine__find_kernel_function_by_name(struct machine *machine,
209 const char *name, 200 const char *name,
210 struct map **mapp, 201 struct map **mapp)
211 symbol_filter_t filter)
212{ 202{
213 return map_groups__find_function_by_name(&machine->kmaps, name, mapp, 203 return map_groups__find_function_by_name(&machine->kmaps, name, mapp);
214 filter);
215} 204}
216 205
217struct map *machine__findnew_module_map(struct machine *machine, u64 start, 206struct map *machine__findnew_module_map(struct machine *machine, u64 start,
@@ -219,11 +208,10 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
219int arch__fix_module_text_start(u64 *start, const char *name); 208int arch__fix_module_text_start(u64 *start, const char *name);
220 209
221int __machine__load_kallsyms(struct machine *machine, const char *filename, 210int __machine__load_kallsyms(struct machine *machine, const char *filename,
222 enum map_type type, bool no_kcore, symbol_filter_t filter); 211 enum map_type type, bool no_kcore);
223int machine__load_kallsyms(struct machine *machine, const char *filename, 212int machine__load_kallsyms(struct machine *machine, const char *filename,
224 enum map_type type, symbol_filter_t filter); 213 enum map_type type);
225int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 214int machine__load_vmlinux_path(struct machine *machine, enum map_type type);
226 symbol_filter_t filter);
227 215
228size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 216size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
229 bool (skip)(struct dso *dso, int parm), int parm); 217 bool (skip)(struct dso *dso, int parm), int parm);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 728129ac653a..c662fef95d14 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -6,6 +6,7 @@
6#include <string.h> 6#include <string.h>
7#include <stdio.h> 7#include <stdio.h>
8#include <unistd.h> 8#include <unistd.h>
9#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
9#include "map.h" 10#include "map.h"
10#include "thread.h" 11#include "thread.h"
11#include "strlist.h" 12#include "strlist.h"
@@ -24,9 +25,10 @@ const char *map_type__name[MAP__NR_TYPES] = {
24 [MAP__VARIABLE] = "Variables", 25 [MAP__VARIABLE] = "Variables",
25}; 26};
26 27
27static inline int is_anon_memory(const char *filename) 28static inline int is_anon_memory(const char *filename, u32 flags)
28{ 29{
29 return !strcmp(filename, "//anon") || 30 return flags & MAP_HUGETLB ||
31 !strcmp(filename, "//anon") ||
30 !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) || 32 !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) ||
31 !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1); 33 !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1);
32} 34}
@@ -155,7 +157,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
155 int anon, no_dso, vdso, android; 157 int anon, no_dso, vdso, android;
156 158
157 android = is_android_lib(filename); 159 android = is_android_lib(filename);
158 anon = is_anon_memory(filename); 160 anon = is_anon_memory(filename, flags);
159 vdso = is_vdso_map(filename); 161 vdso = is_vdso_map(filename);
160 no_dso = is_no_dso_memory(filename); 162 no_dso = is_no_dso_memory(filename);
161 163
@@ -279,7 +281,7 @@ void map__fixup_end(struct map *map)
279 281
280#define DSO__DELETED "(deleted)" 282#define DSO__DELETED "(deleted)"
281 283
282int map__load(struct map *map, symbol_filter_t filter) 284int map__load(struct map *map)
283{ 285{
284 const char *name = map->dso->long_name; 286 const char *name = map->dso->long_name;
285 int nr; 287 int nr;
@@ -287,7 +289,7 @@ int map__load(struct map *map, symbol_filter_t filter)
287 if (dso__loaded(map->dso, map->type)) 289 if (dso__loaded(map->dso, map->type))
288 return 0; 290 return 0;
289 291
290 nr = dso__load(map->dso, map, filter); 292 nr = dso__load(map->dso, map);
291 if (nr < 0) { 293 if (nr < 0) {
292 if (map->dso->has_build_id) { 294 if (map->dso->has_build_id) {
293 char sbuild_id[SBUILD_ID_SIZE]; 295 char sbuild_id[SBUILD_ID_SIZE];
@@ -312,9 +314,6 @@ int map__load(struct map *map, symbol_filter_t filter)
312 pr_warning("%.*s was updated (is prelink enabled?). " 314 pr_warning("%.*s was updated (is prelink enabled?). "
313 "Restart the long running apps that use it!\n", 315 "Restart the long running apps that use it!\n",
314 (int)real_len, name); 316 (int)real_len, name);
315 } else if (filter) {
316 pr_warning("no symbols passed the given filter.\n");
317 return -2; /* Empty but maybe by the filter */
318 } else { 317 } else {
319 pr_warning("no symbols found in %s, maybe install " 318 pr_warning("no symbols found in %s, maybe install "
320 "a debug package?\n", name); 319 "a debug package?\n", name);
@@ -331,19 +330,17 @@ int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
331 return strcmp(namea, nameb); 330 return strcmp(namea, nameb);
332} 331}
333 332
334struct symbol *map__find_symbol(struct map *map, u64 addr, 333struct symbol *map__find_symbol(struct map *map, u64 addr)
335 symbol_filter_t filter)
336{ 334{
337 if (map__load(map, filter) < 0) 335 if (map__load(map) < 0)
338 return NULL; 336 return NULL;
339 337
340 return dso__find_symbol(map->dso, map->type, addr); 338 return dso__find_symbol(map->dso, map->type, addr);
341} 339}
342 340
343struct symbol *map__find_symbol_by_name(struct map *map, const char *name, 341struct symbol *map__find_symbol_by_name(struct map *map, const char *name)
344 symbol_filter_t filter)
345{ 342{
346 if (map__load(map, filter) < 0) 343 if (map__load(map) < 0)
347 return NULL; 344 return NULL;
348 345
349 if (!dso__sorted_by_name(map->dso, map->type)) 346 if (!dso__sorted_by_name(map->dso, map->type))
@@ -556,23 +553,22 @@ void map_groups__put(struct map_groups *mg)
556 553
557struct symbol *map_groups__find_symbol(struct map_groups *mg, 554struct symbol *map_groups__find_symbol(struct map_groups *mg,
558 enum map_type type, u64 addr, 555 enum map_type type, u64 addr,
559 struct map **mapp, 556 struct map **mapp)
560 symbol_filter_t filter)
561{ 557{
562 struct map *map = map_groups__find(mg, type, addr); 558 struct map *map = map_groups__find(mg, type, addr);
563 559
564 /* Ensure map is loaded before using map->map_ip */ 560 /* Ensure map is loaded before using map->map_ip */
565 if (map != NULL && map__load(map, filter) >= 0) { 561 if (map != NULL && map__load(map) >= 0) {
566 if (mapp != NULL) 562 if (mapp != NULL)
567 *mapp = map; 563 *mapp = map;
568 return map__find_symbol(map, map->map_ip(map, addr), filter); 564 return map__find_symbol(map, map->map_ip(map, addr));
569 } 565 }
570 566
571 return NULL; 567 return NULL;
572} 568}
573 569
574struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, 570struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
575 struct map **mapp, symbol_filter_t filter) 571 struct map **mapp)
576{ 572{
577 struct symbol *sym; 573 struct symbol *sym;
578 struct rb_node *nd; 574 struct rb_node *nd;
@@ -582,7 +578,7 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
582 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) { 578 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
583 struct map *pos = rb_entry(nd, struct map, rb_node); 579 struct map *pos = rb_entry(nd, struct map, rb_node);
584 580
585 sym = map__find_symbol_by_name(pos, name, filter); 581 sym = map__find_symbol_by_name(pos, name);
586 582
587 if (sym == NULL) 583 if (sym == NULL)
588 continue; 584 continue;
@@ -600,15 +596,14 @@ out:
600struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 596struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
601 enum map_type type, 597 enum map_type type,
602 const char *name, 598 const char *name,
603 struct map **mapp, 599 struct map **mapp)
604 symbol_filter_t filter)
605{ 600{
606 struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp, filter); 601 struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp);
607 602
608 return sym; 603 return sym;
609} 604}
610 605
611int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) 606int map_groups__find_ams(struct addr_map_symbol *ams)
612{ 607{
613 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { 608 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
614 if (ams->map->groups == NULL) 609 if (ams->map->groups == NULL)
@@ -620,7 +615,7 @@ int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
620 } 615 }
621 616
622 ams->al_addr = ams->map->map_ip(ams->map, ams->addr); 617 ams->al_addr = ams->map->map_ip(ams->map, ams->addr);
623 ams->sym = map__find_symbol(ams->map, ams->al_addr, filter); 618 ams->sym = map__find_symbol(ams->map, ams->al_addr);
624 619
625 return ams->sym ? 0 : -1; 620 return ams->sym ? 0 : -1;
626} 621}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index d83396ceecba..abdacf800c98 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -127,17 +127,14 @@ struct thread;
127 * @map: the 'struct map *' in which symbols itereated 127 * @map: the 'struct map *' in which symbols itereated
128 * @sym_name: the symbol name 128 * @sym_name: the symbol name
129 * @pos: the 'struct symbol *' to use as a loop cursor 129 * @pos: the 'struct symbol *' to use as a loop cursor
130 * @filter: to use when loading the DSO
131 */ 130 */
132#define __map__for_each_symbol_by_name(map, sym_name, pos, filter) \ 131#define __map__for_each_symbol_by_name(map, sym_name, pos) \
133 for (pos = map__find_symbol_by_name(map, sym_name, filter); \ 132 for (pos = map__find_symbol_by_name(map, sym_name); \
134 pos && arch__compare_symbol_names(pos->name, sym_name) == 0; \ 133 pos && arch__compare_symbol_names(pos->name, sym_name) == 0; \
135 pos = symbol__next_by_name(pos)) 134 pos = symbol__next_by_name(pos))
136 135
137#define map__for_each_symbol_by_name(map, sym_name, pos) \ 136#define map__for_each_symbol_by_name(map, sym_name, pos) \
138 __map__for_each_symbol_by_name(map, sym_name, (pos), NULL) 137 __map__for_each_symbol_by_name(map, sym_name, (pos))
139
140typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
141 138
142int arch__compare_symbol_names(const char *namea, const char *nameb); 139int arch__compare_symbol_names(const char *namea, const char *nameb);
143void map__init(struct map *map, enum map_type type, 140void map__init(struct map *map, enum map_type type,
@@ -173,11 +170,9 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp);
173int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, 170int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
174 FILE *fp); 171 FILE *fp);
175 172
176int map__load(struct map *map, symbol_filter_t filter); 173int map__load(struct map *map);
177struct symbol *map__find_symbol(struct map *map, 174struct symbol *map__find_symbol(struct map *map, u64 addr);
178 u64 addr, symbol_filter_t filter); 175struct symbol *map__find_symbol_by_name(struct map *map, const char *name);
179struct symbol *map__find_symbol_by_name(struct map *map, const char *name,
180 symbol_filter_t filter);
181void map__fixup_start(struct map *map); 176void map__fixup_start(struct map *map);
182void map__fixup_end(struct map *map); 177void map__fixup_end(struct map *map);
183 178
@@ -191,7 +186,7 @@ struct map *maps__find(struct maps *maps, u64 addr);
191struct map *maps__first(struct maps *maps); 186struct map *maps__first(struct maps *maps);
192struct map *map__next(struct map *map); 187struct map *map__next(struct map *map);
193struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, 188struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
194 struct map **mapp, symbol_filter_t filter); 189 struct map **mapp);
195void map_groups__init(struct map_groups *mg, struct machine *machine); 190void map_groups__init(struct map_groups *mg, struct machine *machine);
196void map_groups__exit(struct map_groups *mg); 191void map_groups__exit(struct map_groups *mg);
197int map_groups__clone(struct thread *thread, 192int map_groups__clone(struct thread *thread,
@@ -231,25 +226,22 @@ static inline struct map *map_groups__next(struct map *map)
231 226
232struct symbol *map_groups__find_symbol(struct map_groups *mg, 227struct symbol *map_groups__find_symbol(struct map_groups *mg,
233 enum map_type type, u64 addr, 228 enum map_type type, u64 addr,
234 struct map **mapp, 229 struct map **mapp);
235 symbol_filter_t filter);
236 230
237struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 231struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
238 enum map_type type, 232 enum map_type type,
239 const char *name, 233 const char *name,
240 struct map **mapp, 234 struct map **mapp);
241 symbol_filter_t filter);
242 235
243struct addr_map_symbol; 236struct addr_map_symbol;
244 237
245int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter); 238int map_groups__find_ams(struct addr_map_symbol *ams);
246 239
247static inline 240static inline
248struct symbol *map_groups__find_function_by_name(struct map_groups *mg, 241struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
249 const char *name, struct map **mapp, 242 const char *name, struct map **mapp)
250 symbol_filter_t filter)
251{ 243{
252 return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp, filter); 244 return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp);
253} 245}
254 246
255int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 247int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 6c913c3914fb..33546c3ac1fe 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -904,6 +904,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
904 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", 904 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack",
905 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", 905 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite",
906 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", 906 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite",
907 [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config",
907}; 908};
908 909
909static bool config_term_shrinked; 910static bool config_term_shrinked;
@@ -1034,7 +1035,8 @@ static int config_term_pmu(struct perf_event_attr *attr,
1034 struct parse_events_term *term, 1035 struct parse_events_term *term,
1035 struct parse_events_error *err) 1036 struct parse_events_error *err)
1036{ 1037{
1037 if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) 1038 if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER ||
1039 term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG)
1038 /* 1040 /*
1039 * Always succeed for sysfs terms, as we dont know 1041 * Always succeed for sysfs terms, as we dont know
1040 * at this point what type they need to have. 1042 * at this point what type they need to have.
@@ -1134,6 +1136,9 @@ do { \
1134 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1136 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1135 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1); 1137 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1);
1136 break; 1138 break;
1139 case PARSE_EVENTS__TERM_TYPE_DRV_CFG:
1140 ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str);
1141 break;
1137 default: 1142 default:
1138 break; 1143 break;
1139 } 1144 }
@@ -1755,20 +1760,49 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist,
1755static int set_filter(struct perf_evsel *evsel, const void *arg) 1760static int set_filter(struct perf_evsel *evsel, const void *arg)
1756{ 1761{
1757 const char *str = arg; 1762 const char *str = arg;
1763 bool found = false;
1764 int nr_addr_filters = 0;
1765 struct perf_pmu *pmu = NULL;
1758 1766
1759 if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) { 1767 if (evsel == NULL)
1760 fprintf(stderr, 1768 goto err;
1761 "--filter option should follow a -e tracepoint option\n"); 1769
1762 return -1; 1770 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
1771 if (perf_evsel__append_tp_filter(evsel, str) < 0) {
1772 fprintf(stderr,
1773 "not enough memory to hold filter string\n");
1774 return -1;
1775 }
1776
1777 return 0;
1763 } 1778 }
1764 1779
1765 if (perf_evsel__append_filter(evsel, "&&", str) < 0) { 1780 while ((pmu = perf_pmu__scan(pmu)) != NULL)
1781 if (pmu->type == evsel->attr.type) {
1782 found = true;
1783 break;
1784 }
1785
1786 if (found)
1787 perf_pmu__scan_file(pmu, "nr_addr_filters",
1788 "%d", &nr_addr_filters);
1789
1790 if (!nr_addr_filters)
1791 goto err;
1792
1793 if (perf_evsel__append_addr_filter(evsel, str) < 0) {
1766 fprintf(stderr, 1794 fprintf(stderr,
1767 "not enough memory to hold filter string\n"); 1795 "not enough memory to hold filter string\n");
1768 return -1; 1796 return -1;
1769 } 1797 }
1770 1798
1771 return 0; 1799 return 0;
1800
1801err:
1802 fprintf(stderr,
1803 "--filter option should follow a -e tracepoint or HW tracer option\n");
1804
1805 return -1;
1772} 1806}
1773 1807
1774int parse_filter(const struct option *opt, const char *str, 1808int parse_filter(const struct option *opt, const char *str,
@@ -1793,7 +1827,7 @@ static int add_exclude_perf_filter(struct perf_evsel *evsel,
1793 1827
1794 snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid()); 1828 snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
1795 1829
1796 if (perf_evsel__append_filter(evsel, "&&", new_filter) < 0) { 1830 if (perf_evsel__append_tp_filter(evsel, new_filter) < 0) {
1797 fprintf(stderr, 1831 fprintf(stderr,
1798 "not enough memory to hold filter string\n"); 1832 "not enough memory to hold filter string\n");
1799 return -1; 1833 return -1;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index d1edbf8cc66a..8d09a976fca8 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -71,6 +71,7 @@ enum {
71 PARSE_EVENTS__TERM_TYPE_MAX_STACK, 71 PARSE_EVENTS__TERM_TYPE_MAX_STACK,
72 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE, 72 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
73 PARSE_EVENTS__TERM_TYPE_OVERWRITE, 73 PARSE_EVENTS__TERM_TYPE_OVERWRITE,
74 PARSE_EVENTS__TERM_TYPE_DRV_CFG,
74 __PARSE_EVENTS__TERM_TYPE_NR, 75 __PARSE_EVENTS__TERM_TYPE_NR,
75}; 76};
76 77
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 7a2519435da0..9f43fda2570f 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -53,6 +53,26 @@ static int str(yyscan_t scanner, int token)
53 return token; 53 return token;
54} 54}
55 55
56/*
57 * This function is called when the parser gets two kind of input:
58 *
59 * @cfg1 or @cfg2=config
60 *
61 * The leading '@' is stripped off before 'cfg1' and 'cfg2=config' are given to
62 * bison. In the latter case it is necessary to keep the string intact so that
63 * the PMU kernel driver can determine what configurable is associated to
64 * 'config'.
65 */
66static int drv_str(yyscan_t scanner, int token)
67{
68 YYSTYPE *yylval = parse_events_get_lval(scanner);
69 char *text = parse_events_get_text(scanner);
70
71 /* Strip off the '@' */
72 yylval->str = strdup(text + 1);
73 return token;
74}
75
56#define REWIND(__alloc) \ 76#define REWIND(__alloc) \
57do { \ 77do { \
58 YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \ 78 YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \
@@ -124,6 +144,7 @@ num_hex 0x[a-fA-F0-9]+
124num_raw_hex [a-fA-F0-9]+ 144num_raw_hex [a-fA-F0-9]+
125name [a-zA-Z_*?][a-zA-Z0-9_*?.]* 145name [a-zA-Z_*?][a-zA-Z0-9_*?.]*
126name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* 146name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
147drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
127/* If you add a modifier you need to update check_modifier() */ 148/* If you add a modifier you need to update check_modifier() */
128modifier_event [ukhpPGHSDI]+ 149modifier_event [ukhpPGHSDI]+
129modifier_bp [rwx]{1,3} 150modifier_bp [rwx]{1,3}
@@ -209,6 +230,7 @@ no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
209{name_minus} { return str(yyscanner, PE_NAME); } 230{name_minus} { return str(yyscanner, PE_NAME); }
210\[all\] { return PE_ARRAY_ALL; } 231\[all\] { return PE_ARRAY_ALL; }
211"[" { BEGIN(array); return '['; } 232"[" { BEGIN(array); return '['; }
233@{drv_cfg_term} { return drv_str(yyscanner, PE_DRV_CFG_TERM); }
212} 234}
213 235
214<mem>{ 236<mem>{
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 5be4a5f216d6..879115f93edc 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -49,6 +49,7 @@ static void inc_group_count(struct list_head *list,
49%token PE_ERROR 49%token PE_ERROR
50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
51%token PE_ARRAY_ALL PE_ARRAY_RANGE 51%token PE_ARRAY_ALL PE_ARRAY_RANGE
52%token PE_DRV_CFG_TERM
52%type <num> PE_VALUE 53%type <num> PE_VALUE
53%type <num> PE_VALUE_SYM_HW 54%type <num> PE_VALUE_SYM_HW
54%type <num> PE_VALUE_SYM_SW 55%type <num> PE_VALUE_SYM_SW
@@ -63,6 +64,7 @@ static void inc_group_count(struct list_head *list,
63%type <str> PE_MODIFIER_BP 64%type <str> PE_MODIFIER_BP
64%type <str> PE_EVENT_NAME 65%type <str> PE_EVENT_NAME
65%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 66%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
67%type <str> PE_DRV_CFG_TERM
66%type <num> value_sym 68%type <num> value_sym
67%type <head> event_config 69%type <head> event_config
68%type <head> opt_event_config 70%type <head> opt_event_config
@@ -599,6 +601,15 @@ PE_NAME array '=' PE_VALUE
599 term->array = $2; 601 term->array = $2;
600 $$ = term; 602 $$ = term;
601} 603}
604|
605PE_DRV_CFG_TERM
606{
607 struct parse_events_term *term;
608
609 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG,
610 $1, $1, &@1, NULL));
611 $$ = term;
612}
602 613
603array: 614array:
604'[' array_terms ']' 615'[' array_terms ']'
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index ddb0261b2577..2babcdf62839 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -445,14 +445,23 @@ static struct cpu_map *pmu_cpumask(const char *name)
445 FILE *file; 445 FILE *file;
446 struct cpu_map *cpus; 446 struct cpu_map *cpus;
447 const char *sysfs = sysfs__mountpoint(); 447 const char *sysfs = sysfs__mountpoint();
448 const char *templates[] = {
449 "%s/bus/event_source/devices/%s/cpumask",
450 "%s/bus/event_source/devices/%s/cpus",
451 NULL
452 };
453 const char **template;
448 454
449 if (!sysfs) 455 if (!sysfs)
450 return NULL; 456 return NULL;
451 457
452 snprintf(path, PATH_MAX, 458 for (template = templates; *template; template++) {
453 "%s/bus/event_source/devices/%s/cpumask", sysfs, name); 459 snprintf(path, PATH_MAX, *template, sysfs, name);
460 if (stat(path, &st) == 0)
461 break;
462 }
454 463
455 if (stat(path, &st) < 0) 464 if (!*template)
456 return NULL; 465 return NULL;
457 466
458 file = fopen(path, "r"); 467 file = fopen(path, "r");
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 5d7e84466bee..743422ad900b 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -4,6 +4,7 @@
4#include <linux/bitmap.h> 4#include <linux/bitmap.h>
5#include <linux/perf_event.h> 5#include <linux/perf_event.h>
6#include <stdbool.h> 6#include <stdbool.h>
7#include "evsel.h"
7#include "parse-events.h" 8#include "parse-events.h"
8 9
9enum { 10enum {
@@ -25,6 +26,7 @@ struct perf_pmu {
25 struct list_head format; /* HEAD struct perf_pmu_format -> list */ 26 struct list_head format; /* HEAD struct perf_pmu_format -> list */
26 struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */ 27 struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
27 struct list_head list; /* ELEM */ 28 struct list_head list; /* ELEM */
29 int (*set_drv_config) (struct perf_evsel_config_term *term);
28}; 30};
29 31
30struct perf_pmu_info { 32struct perf_pmu_info {
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 28733962cd80..fcfbef07b92d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -110,13 +110,12 @@ void exit_probe_symbol_maps(void)
110static struct symbol *__find_kernel_function_by_name(const char *name, 110static struct symbol *__find_kernel_function_by_name(const char *name,
111 struct map **mapp) 111 struct map **mapp)
112{ 112{
113 return machine__find_kernel_function_by_name(host_machine, name, mapp, 113 return machine__find_kernel_function_by_name(host_machine, name, mapp);
114 NULL);
115} 114}
116 115
117static struct symbol *__find_kernel_function(u64 addr, struct map **mapp) 116static struct symbol *__find_kernel_function(u64 addr, struct map **mapp)
118{ 117{
119 return machine__find_kernel_function(host_machine, addr, mapp, NULL); 118 return machine__find_kernel_function(host_machine, addr, mapp);
120} 119}
121 120
122static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) 121static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
@@ -125,7 +124,7 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
125 struct kmap *kmap; 124 struct kmap *kmap;
126 struct map *map = machine__kernel_map(host_machine); 125 struct map *map = machine__kernel_map(host_machine);
127 126
128 if (map__load(map, NULL) < 0) 127 if (map__load(map) < 0)
129 return NULL; 128 return NULL;
130 129
131 kmap = map__kmap(map); 130 kmap = map__kmap(map);
@@ -214,9 +213,13 @@ static int convert_exec_to_group(const char *exec, char **result)
214 goto out; 213 goto out;
215 } 214 }
216 215
217 ptr2 = strpbrk(ptr1, "-._"); 216 for (ptr2 = ptr1; ptr2 != '\0'; ptr2++) {
218 if (ptr2) 217 if (!isalnum(*ptr2) && *ptr2 != '_') {
219 *ptr2 = '\0'; 218 *ptr2 = '\0';
219 break;
220 }
221 }
222
220 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); 223 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1);
221 if (ret < 0) 224 if (ret < 0)
222 goto out; 225 goto out;
@@ -351,9 +354,9 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso)
351 vmlinux_name = symbol_conf.vmlinux_name; 354 vmlinux_name = symbol_conf.vmlinux_name;
352 dso->load_errno = 0; 355 dso->load_errno = 0;
353 if (vmlinux_name) 356 if (vmlinux_name)
354 ret = dso__load_vmlinux(dso, map, vmlinux_name, false, NULL); 357 ret = dso__load_vmlinux(dso, map, vmlinux_name, false);
355 else 358 else
356 ret = dso__load_vmlinux_path(dso, map, NULL); 359 ret = dso__load_vmlinux_path(dso, map);
357found: 360found:
358 *pdso = dso; 361 *pdso = dso;
359 return ret; 362 return ret;
@@ -674,6 +677,10 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
674 char *tmp; 677 char *tmp;
675 int i, skipped = 0; 678 int i, skipped = 0;
676 679
680 /* Skip post process if the target is an offline kernel */
681 if (symbol_conf.ignore_vmlinux_buildid)
682 return 0;
683
677 reloc_sym = kernel_get_ref_reloc_sym(); 684 reloc_sym = kernel_get_ref_reloc_sym();
678 if (!reloc_sym) { 685 if (!reloc_sym) {
679 pr_warning("Relocated base symbol is not found!\n"); 686 pr_warning("Relocated base symbol is not found!\n");
@@ -1614,19 +1621,27 @@ out:
1614 return ret; 1621 return ret;
1615} 1622}
1616 1623
1624/* Returns true if *any* ARG is either C variable, $params or $vars. */
1625bool perf_probe_with_var(struct perf_probe_event *pev)
1626{
1627 int i = 0;
1628
1629 for (i = 0; i < pev->nargs; i++)
1630 if (is_c_varname(pev->args[i].var) ||
1631 !strcmp(pev->args[i].var, PROBE_ARG_PARAMS) ||
1632 !strcmp(pev->args[i].var, PROBE_ARG_VARS))
1633 return true;
1634 return false;
1635}
1636
1617/* Return true if this perf_probe_event requires debuginfo */ 1637/* Return true if this perf_probe_event requires debuginfo */
1618bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 1638bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
1619{ 1639{
1620 int i;
1621
1622 if (pev->point.file || pev->point.line || pev->point.lazy_line) 1640 if (pev->point.file || pev->point.line || pev->point.lazy_line)
1623 return true; 1641 return true;
1624 1642
1625 for (i = 0; i < pev->nargs; i++) 1643 if (perf_probe_with_var(pev))
1626 if (is_c_varname(pev->args[i].var) || 1644 return true;
1627 !strcmp(pev->args[i].var, "$params") ||
1628 !strcmp(pev->args[i].var, "$vars"))
1629 return true;
1630 1645
1631 return false; 1646 return false;
1632} 1647}
@@ -1987,7 +2002,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
1987 map = dso__new_map(tp->module); 2002 map = dso__new_map(tp->module);
1988 if (!map) 2003 if (!map)
1989 goto out; 2004 goto out;
1990 sym = map__find_symbol(map, addr, NULL); 2005 sym = map__find_symbol(map, addr);
1991 } else { 2006 } else {
1992 if (tp->symbol && !addr) { 2007 if (tp->symbol && !addr) {
1993 if (kernel_get_symbol_address_by_name(tp->symbol, 2008 if (kernel_get_symbol_address_by_name(tp->symbol,
@@ -2692,7 +2707,7 @@ static int find_probe_functions(struct map *map, char *name,
2692 struct symbol *sym; 2707 struct symbol *sym;
2693 struct rb_node *tmp; 2708 struct rb_node *tmp;
2694 2709
2695 if (map__load(map, NULL) < 0) 2710 if (map__load(map) < 0)
2696 return 0; 2711 return 0;
2697 2712
2698 map__for_each_symbol(map, sym, tmp) { 2713 map__for_each_symbol(map, sym, tmp) {
@@ -3207,6 +3222,52 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
3207 return 0; 3222 return 0;
3208} 3223}
3209 3224
3225static int show_probe_trace_event(struct probe_trace_event *tev)
3226{
3227 char *buf = synthesize_probe_trace_command(tev);
3228
3229 if (!buf) {
3230 pr_debug("Failed to synthesize probe trace event.\n");
3231 return -EINVAL;
3232 }
3233
3234 /* Showing definition always go stdout */
3235 printf("%s\n", buf);
3236 free(buf);
3237
3238 return 0;
3239}
3240
3241int show_probe_trace_events(struct perf_probe_event *pevs, int npevs)
3242{
3243 struct strlist *namelist = strlist__new(NULL, NULL);
3244 struct probe_trace_event *tev;
3245 struct perf_probe_event *pev;
3246 int i, j, ret = 0;
3247
3248 if (!namelist)
3249 return -ENOMEM;
3250
3251 for (j = 0; j < npevs && !ret; j++) {
3252 pev = &pevs[j];
3253 for (i = 0; i < pev->ntevs && !ret; i++) {
3254 tev = &pev->tevs[i];
3255 /* Skip if the symbol is out of .text or blacklisted */
3256 if (!tev->point.symbol && !pev->uprobes)
3257 continue;
3258
3259 /* Set new name for tev (and update namelist) */
3260 ret = probe_trace_event__set_name(tev, pev,
3261 namelist, true);
3262 if (!ret)
3263 ret = show_probe_trace_event(tev);
3264 }
3265 }
3266 strlist__delete(namelist);
3267
3268 return ret;
3269}
3270
3210int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs) 3271int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
3211{ 3272{
3212 int i, ret = 0; 3273 int i, ret = 0;
@@ -3289,24 +3350,10 @@ out:
3289 return ret; 3350 return ret;
3290} 3351}
3291 3352
3292/* TODO: don't use a global variable for filter ... */
3293static struct strfilter *available_func_filter;
3294
3295/*
3296 * If a symbol corresponds to a function with global binding and
3297 * matches filter return 0. For all others return 1.
3298 */
3299static int filter_available_functions(struct map *map __maybe_unused,
3300 struct symbol *sym)
3301{
3302 if (strfilter__compare(available_func_filter, sym->name))
3303 return 0;
3304 return 1;
3305}
3306
3307int show_available_funcs(const char *target, struct strfilter *_filter, 3353int show_available_funcs(const char *target, struct strfilter *_filter,
3308 bool user) 3354 bool user)
3309{ 3355{
3356 struct rb_node *nd;
3310 struct map *map; 3357 struct map *map;
3311 int ret; 3358 int ret;
3312 3359
@@ -3324,9 +3371,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
3324 return -EINVAL; 3371 return -EINVAL;
3325 } 3372 }
3326 3373
3327 /* Load symbols with given filter */ 3374 ret = map__load(map);
3328 available_func_filter = _filter;
3329 ret = map__load(map, filter_available_functions);
3330 if (ret) { 3375 if (ret) {
3331 if (ret == -2) { 3376 if (ret == -2) {
3332 char *str = strfilter__string(_filter); 3377 char *str = strfilter__string(_filter);
@@ -3343,7 +3388,14 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
3343 3388
3344 /* Show all (filtered) symbols */ 3389 /* Show all (filtered) symbols */
3345 setup_pager(); 3390 setup_pager();
3346 dso__fprintf_symbols_by_name(map->dso, map->type, stdout); 3391
3392 for (nd = rb_first(&map->dso->symbol_names[map->type]); nd; nd = rb_next(nd)) {
3393 struct symbol_name_rb_node *pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
3394
3395 if (strfilter__compare(_filter, pos->sym.name))
3396 printf("%s\n", pos->sym.name);
3397 }
3398
3347end: 3399end:
3348 if (user) { 3400 if (user) {
3349 map__put(map); 3401 map__put(map);
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index f4f45db77c1c..8091d15113f7 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -128,6 +128,8 @@ char *synthesize_perf_probe_point(struct perf_probe_point *pp);
128int perf_probe_event__copy(struct perf_probe_event *dst, 128int perf_probe_event__copy(struct perf_probe_event *dst,
129 struct perf_probe_event *src); 129 struct perf_probe_event *src);
130 130
131bool perf_probe_with_var(struct perf_probe_event *pev);
132
131/* Check the perf_probe_event needs debuginfo */ 133/* Check the perf_probe_event needs debuginfo */
132bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); 134bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
133 135
@@ -147,6 +149,7 @@ int line_range__init(struct line_range *lr);
147int add_perf_probe_events(struct perf_probe_event *pevs, int npevs); 149int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
148int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs); 150int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs);
149int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs); 151int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs);
152int show_probe_trace_events(struct perf_probe_event *pevs, int npevs);
150void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs); 153void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);
151int del_perf_probe_events(struct strfilter *filter); 154int del_perf_probe_events(struct strfilter *filter);
152 155
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 9c3b9ed5b3c3..436b64731f65 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -73,11 +73,10 @@ static void print_both_open_warning(int kerr, int uerr)
73static int open_probe_events(const char *trace_file, bool readwrite) 73static int open_probe_events(const char *trace_file, bool readwrite)
74{ 74{
75 char buf[PATH_MAX]; 75 char buf[PATH_MAX];
76 const char *tracing_dir = "";
77 int ret; 76 int ret;
78 77
79 ret = e_snprintf(buf, PATH_MAX, "%s/%s%s", 78 ret = e_snprintf(buf, PATH_MAX, "%s/%s",
80 tracing_path, tracing_dir, trace_file); 79 tracing_path, trace_file);
81 if (ret >= 0) { 80 if (ret >= 0) {
82 pr_debug("Opening %s write=%d\n", buf, readwrite); 81 pr_debug("Opening %s write=%d\n", buf, readwrite);
83 if (readwrite && !probe_event_dry_run) 82 if (readwrite && !probe_event_dry_run)
@@ -700,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
700 INIT_LIST_HEAD(&sdtlist); 699 INIT_LIST_HEAD(&sdtlist);
701 ret = get_sdt_note_list(&sdtlist, pathname); 700 ret = get_sdt_note_list(&sdtlist, pathname);
702 if (ret < 0) { 701 if (ret < 0) {
703 pr_debug("Failed to get sdt note: %d\n", ret); 702 pr_debug4("Failed to get sdt note: %d\n", ret);
704 return ret; 703 return ret;
705 } 704 }
706 list_for_each_entry(note, &sdtlist, note_list) { 705 list_for_each_entry(note, &sdtlist, note_list) {
@@ -877,3 +876,60 @@ int probe_cache__show_all_caches(struct strfilter *filter)
877 876
878 return 0; 877 return 0;
879} 878}
879
880static struct {
881 const char *pattern;
882 bool avail;
883 bool checked;
884} probe_type_table[] = {
885#define DEFINE_TYPE(idx, pat, def_avail) \
886 [idx] = {.pattern = pat, .avail = (def_avail)}
887 DEFINE_TYPE(PROBE_TYPE_U, "* u8/16/32/64,*", true),
888 DEFINE_TYPE(PROBE_TYPE_S, "* s8/16/32/64,*", true),
889 DEFINE_TYPE(PROBE_TYPE_X, "* x8/16/32/64,*", false),
890 DEFINE_TYPE(PROBE_TYPE_STRING, "* string,*", true),
891 DEFINE_TYPE(PROBE_TYPE_BITFIELD,
892 "* b<bit-width>@<bit-offset>/<container-size>", true),
893};
894
895bool probe_type_is_available(enum probe_type type)
896{
897 FILE *fp;
898 char *buf = NULL;
899 size_t len = 0;
900 bool target_line = false;
901 bool ret = probe_type_table[type].avail;
902
903 if (type >= PROBE_TYPE_END)
904 return false;
905 /* We don't have to check the type which supported by default */
906 if (ret || probe_type_table[type].checked)
907 return ret;
908
909 if (asprintf(&buf, "%s/README", tracing_path) < 0)
910 return ret;
911
912 fp = fopen(buf, "r");
913 if (!fp)
914 goto end;
915
916 zfree(&buf);
917 while (getline(&buf, &len, fp) > 0 && !ret) {
918 if (!target_line) {
919 target_line = !!strstr(buf, " type: ");
920 if (!target_line)
921 continue;
922 } else if (strstr(buf, "\t ") != buf)
923 break;
924 ret = strglobmatch(buf, probe_type_table[type].pattern);
925 }
926 /* Cache the result */
927 probe_type_table[type].checked = true;
928 probe_type_table[type].avail = ret;
929
930 fclose(fp);
931end:
932 free(buf);
933
934 return ret;
935}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 9577b5c0b487..eba44c3e9dca 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -19,6 +19,15 @@ struct probe_cache {
19 struct list_head entries; 19 struct list_head entries;
20}; 20};
21 21
22enum probe_type {
23 PROBE_TYPE_U = 0,
24 PROBE_TYPE_S,
25 PROBE_TYPE_X,
26 PROBE_TYPE_STRING,
27 PROBE_TYPE_BITFIELD,
28 PROBE_TYPE_END,
29};
30
22#define PF_FL_UPROBE 1 31#define PF_FL_UPROBE 1
23#define PF_FL_RW 2 32#define PF_FL_RW 2
24#define for_each_probe_cache_entry(entry, pcache) \ 33#define for_each_probe_cache_entry(entry, pcache) \
@@ -54,6 +63,7 @@ struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
54struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache, 63struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
55 const char *group, const char *event); 64 const char *group, const char *event);
56int probe_cache__show_all_caches(struct strfilter *filter); 65int probe_cache__show_all_caches(struct strfilter *filter);
66bool probe_type_is_available(enum probe_type type);
57#else /* ! HAVE_LIBELF_SUPPORT */ 67#else /* ! HAVE_LIBELF_SUPPORT */
58static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused) 68static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
59{ 69{
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 5c290c682afe..df4debe564da 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -39,6 +39,7 @@
39#include "util.h" 39#include "util.h"
40#include "symbol.h" 40#include "symbol.h"
41#include "probe-finder.h" 41#include "probe-finder.h"
42#include "probe-file.h"
42 43
43/* Kprobe tracer basic type is up to u64 */ 44/* Kprobe tracer basic type is up to u64 */
44#define MAX_BASIC_TYPE_BITS 64 45#define MAX_BASIC_TYPE_BITS 64
@@ -170,6 +171,7 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
170 */ 171 */
171static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, 172static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
172 Dwarf_Op *fb_ops, Dwarf_Die *sp_die, 173 Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
174 unsigned int machine,
173 struct probe_trace_arg *tvar) 175 struct probe_trace_arg *tvar)
174{ 176{
175 Dwarf_Attribute attr; 177 Dwarf_Attribute attr;
@@ -265,7 +267,7 @@ static_var:
265 if (!tvar) 267 if (!tvar)
266 return ret2; 268 return ret2;
267 269
268 regs = get_arch_regstr(regn); 270 regs = get_dwarf_regstr(regn, machine);
269 if (!regs) { 271 if (!regs) {
270 /* This should be a bug in DWARF or this tool */ 272 /* This should be a bug in DWARF or this tool */
271 pr_warning("Mapping for the register number %u " 273 pr_warning("Mapping for the register number %u "
@@ -297,13 +299,13 @@ static int convert_variable_type(Dwarf_Die *vr_die,
297 char sbuf[STRERR_BUFSIZE]; 299 char sbuf[STRERR_BUFSIZE];
298 int bsize, boffs, total; 300 int bsize, boffs, total;
299 int ret; 301 int ret;
300 char sign; 302 char prefix;
301 303
302 /* TODO: check all types */ 304 /* TODO: check all types */
303 if (cast && strcmp(cast, "string") != 0 && 305 if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "x") != 0 &&
304 strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) { 306 strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
305 /* Non string type is OK */ 307 /* Non string type is OK */
306 /* and respect signedness cast */ 308 /* and respect signedness/hexadecimal cast */
307 tvar->type = strdup(cast); 309 tvar->type = strdup(cast);
308 return (tvar->type == NULL) ? -ENOMEM : 0; 310 return (tvar->type == NULL) ? -ENOMEM : 0;
309 } 311 }
@@ -365,11 +367,15 @@ static int convert_variable_type(Dwarf_Die *vr_die,
365 } 367 }
366 368
367 if (cast && (strcmp(cast, "u") == 0)) 369 if (cast && (strcmp(cast, "u") == 0))
368 sign = 'u'; 370 prefix = 'u';
369 else if (cast && (strcmp(cast, "s") == 0)) 371 else if (cast && (strcmp(cast, "s") == 0))
370 sign = 's'; 372 prefix = 's';
373 else if (cast && (strcmp(cast, "x") == 0) &&
374 probe_type_is_available(PROBE_TYPE_X))
375 prefix = 'x';
371 else 376 else
372 sign = die_is_signed_type(&type) ? 's' : 'u'; 377 prefix = die_is_signed_type(&type) ? 's' :
378 probe_type_is_available(PROBE_TYPE_X) ? 'x' : 'u';
373 379
374 ret = dwarf_bytesize(&type); 380 ret = dwarf_bytesize(&type);
375 if (ret <= 0) 381 if (ret <= 0)
@@ -383,7 +389,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
383 dwarf_diename(&type), MAX_BASIC_TYPE_BITS); 389 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
384 ret = MAX_BASIC_TYPE_BITS; 390 ret = MAX_BASIC_TYPE_BITS;
385 } 391 }
386 ret = snprintf(buf, 16, "%c%d", sign, ret); 392 ret = snprintf(buf, 16, "%c%d", prefix, ret);
387 393
388formatted: 394formatted:
389 if (ret < 0 || ret >= 16) { 395 if (ret < 0 || ret >= 16) {
@@ -538,7 +544,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
538 dwarf_diename(vr_die)); 544 dwarf_diename(vr_die));
539 545
540 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, 546 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
541 &pf->sp_die, pf->tvar); 547 &pf->sp_die, pf->machine, pf->tvar);
542 if (ret == -ENOENT || ret == -EINVAL) { 548 if (ret == -ENOENT || ret == -EINVAL) {
543 pr_err("Failed to find the location of the '%s' variable at this address.\n" 549 pr_err("Failed to find the location of the '%s' variable at this address.\n"
544 " Perhaps it has been optimized out.\n" 550 " Perhaps it has been optimized out.\n"
@@ -901,6 +907,38 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
901 return die_walk_lines(sp_die, probe_point_lazy_walker, pf); 907 return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
902} 908}
903 909
910static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
911{
912 struct perf_probe_point *pp = &pf->pev->point;
913
914 /* Not uprobe? */
915 if (!pf->pev->uprobes)
916 return;
917
918 /* Compiled with optimization? */
919 if (die_is_optimized_target(&pf->cu_die))
920 return;
921
922 /* Don't know entrypc? */
923 if (!pf->addr)
924 return;
925
926 /* Only FUNC and FUNC@SRC are eligible. */
927 if (!pp->function || pp->line || pp->retprobe || pp->lazy_line ||
928 pp->offset || pp->abs_address)
929 return;
930
931 /* Not interested in func parameter? */
932 if (!perf_probe_with_var(pf->pev))
933 return;
934
935 pr_info("Target program is compiled without optimization. Skipping prologue.\n"
936 "Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
937 pf->addr);
938
939 die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
940}
941
904static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 942static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
905{ 943{
906 struct probe_finder *pf = data; 944 struct probe_finder *pf = data;
@@ -917,6 +955,11 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
917 dwarf_diename(in_die)); 955 dwarf_diename(in_die));
918 return -ENOENT; 956 return -ENOENT;
919 } 957 }
958 if (addr == 0) {
959 pr_debug("%s has no valid entry address. skipped.\n",
960 dwarf_diename(in_die));
961 return -ENOENT;
962 }
920 pf->addr = addr; 963 pf->addr = addr;
921 pf->addr += pp->offset; 964 pf->addr += pp->offset;
922 pr_debug("found inline addr: 0x%jx\n", 965 pr_debug("found inline addr: 0x%jx\n",
@@ -950,7 +993,8 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
950 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die))) 993 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
951 return DWARF_CB_OK; 994 return DWARF_CB_OK;
952 995
953 pr_debug("Matched function: %s\n", dwarf_diename(sp_die)); 996 pr_debug("Matched function: %s [%lx]\n", dwarf_diename(sp_die),
997 (unsigned long)dwarf_dieoffset(sp_die));
954 pf->fname = dwarf_decl_file(sp_die); 998 pf->fname = dwarf_decl_file(sp_die);
955 if (pp->line) { /* Function relative line */ 999 if (pp->line) { /* Function relative line */
956 dwarf_decl_line(sp_die, &pf->lno); 1000 dwarf_decl_line(sp_die, &pf->lno);
@@ -959,10 +1003,16 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
959 } else if (die_is_func_instance(sp_die)) { 1003 } else if (die_is_func_instance(sp_die)) {
960 /* Instances always have the entry address */ 1004 /* Instances always have the entry address */
961 dwarf_entrypc(sp_die, &pf->addr); 1005 dwarf_entrypc(sp_die, &pf->addr);
1006 /* But in some case the entry address is 0 */
1007 if (pf->addr == 0) {
1008 pr_debug("%s has no entry PC. Skipped\n",
1009 dwarf_diename(sp_die));
1010 param->retval = 0;
962 /* Real function */ 1011 /* Real function */
963 if (pp->lazy_line) 1012 } else if (pp->lazy_line)
964 param->retval = find_probe_point_lazy(sp_die, pf); 1013 param->retval = find_probe_point_lazy(sp_die, pf);
965 else { 1014 else {
1015 skip_prologue(sp_die, pf);
966 pf->addr += pp->offset; 1016 pf->addr += pp->offset;
967 /* TODO: Check the address in this function */ 1017 /* TODO: Check the address in this function */
968 param->retval = call_probe_finder(sp_die, pf); 1018 param->retval = call_probe_finder(sp_die, pf);
@@ -972,7 +1022,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
972 param->retval = die_walk_instances(sp_die, 1022 param->retval = die_walk_instances(sp_die,
973 probe_point_inline_cb, (void *)pf); 1023 probe_point_inline_cb, (void *)pf);
974 /* This could be a non-existed inline definition */ 1024 /* This could be a non-existed inline definition */
975 if (param->retval == -ENOENT && strisglob(pp->function)) 1025 if (param->retval == -ENOENT)
976 param->retval = 0; 1026 param->retval = 0;
977 } 1027 }
978 1028
@@ -1101,11 +1151,8 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
1101 struct probe_finder *pf) 1151 struct probe_finder *pf)
1102{ 1152{
1103 int ret = 0; 1153 int ret = 0;
1104
1105#if _ELFUTILS_PREREQ(0, 142)
1106 Elf *elf; 1154 Elf *elf;
1107 GElf_Ehdr ehdr; 1155 GElf_Ehdr ehdr;
1108 GElf_Shdr shdr;
1109 1156
1110 if (pf->cfi_eh || pf->cfi_dbg) 1157 if (pf->cfi_eh || pf->cfi_dbg)
1111 return debuginfo__find_probe_location(dbg, pf); 1158 return debuginfo__find_probe_location(dbg, pf);
@@ -1118,11 +1165,18 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
1118 if (gelf_getehdr(elf, &ehdr) == NULL) 1165 if (gelf_getehdr(elf, &ehdr) == NULL)
1119 return -EINVAL; 1166 return -EINVAL;
1120 1167
1121 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) && 1168 pf->machine = ehdr.e_machine;
1122 shdr.sh_type == SHT_PROGBITS) 1169
1123 pf->cfi_eh = dwarf_getcfi_elf(elf); 1170#if _ELFUTILS_PREREQ(0, 142)
1171 do {
1172 GElf_Shdr shdr;
1173
1174 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1175 shdr.sh_type == SHT_PROGBITS)
1176 pf->cfi_eh = dwarf_getcfi_elf(elf);
1124 1177
1125 pf->cfi_dbg = dwarf_getcfi(dbg->dbg); 1178 pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
1179 } while (0);
1126#endif 1180#endif
1127 1181
1128 ret = debuginfo__find_probe_location(dbg, pf); 1182 ret = debuginfo__find_probe_location(dbg, pf);
@@ -1150,7 +1204,7 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
1150 (tag == DW_TAG_variable && vf->vars)) { 1204 (tag == DW_TAG_variable && vf->vars)) {
1151 if (convert_variable_location(die_mem, vf->pf->addr, 1205 if (convert_variable_location(die_mem, vf->pf->addr,
1152 vf->pf->fb_ops, &pf->sp_die, 1206 vf->pf->fb_ops, &pf->sp_die,
1153 NULL) == 0) { 1207 pf->machine, NULL) == 0) {
1154 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem); 1208 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
1155 if (vf->args[vf->nargs].var == NULL) { 1209 if (vf->args[vf->nargs].var == NULL) {
1156 vf->ret = -ENOMEM; 1210 vf->ret = -ENOMEM;
@@ -1313,7 +1367,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1313 tag == DW_TAG_variable) { 1367 tag == DW_TAG_variable) {
1314 ret = convert_variable_location(die_mem, af->pf.addr, 1368 ret = convert_variable_location(die_mem, af->pf.addr,
1315 af->pf.fb_ops, &af->pf.sp_die, 1369 af->pf.fb_ops, &af->pf.sp_die,
1316 NULL); 1370 af->pf.machine, NULL);
1317 if (ret == 0 || ret == -ERANGE) { 1371 if (ret == 0 || ret == -ERANGE) {
1318 int ret2; 1372 int ret2;
1319 bool externs = !af->child; 1373 bool externs = !af->child;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 51137fccb9c8..f1d8558f498e 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -80,6 +80,7 @@ struct probe_finder {
80 Dwarf_CFI *cfi_dbg; 80 Dwarf_CFI *cfi_dbg;
81#endif 81#endif
82 Dwarf_Op *fb_ops; /* Frame base attribute */ 82 Dwarf_Op *fb_ops; /* Frame base attribute */
83 unsigned int machine; /* Target machine arch */
83 struct perf_probe_arg *pvar; /* Current target variable */ 84 struct perf_probe_arg *pvar; /* Current target variable */
84 struct probe_trace_arg *tvar; /* Current result variable */ 85 struct probe_trace_arg *tvar; /* Current result variable */
85}; 86};
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 5d1eb1ccd96c..e55a132f69b7 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -25,6 +25,7 @@
25#include <ctype.h> 25#include <ctype.h>
26#include <errno.h> 26#include <errno.h>
27#include <linux/bitmap.h> 27#include <linux/bitmap.h>
28#include <linux/time64.h>
28 29
29#include "../util.h" 30#include "../util.h"
30#include <EXTERN.h> 31#include <EXTERN.h>
@@ -359,8 +360,8 @@ static void perl_process_tracepoint(struct perf_sample *sample,
359 if (!test_and_set_bit(event->id, events_defined)) 360 if (!test_and_set_bit(event->id, events_defined))
360 define_event_symbols(event, handler, event->print_fmt.args); 361 define_event_symbols(event, handler, event->print_fmt.args);
361 362
362 s = nsecs / NSECS_PER_SEC; 363 s = nsecs / NSEC_PER_SEC;
363 ns = nsecs - s * NSECS_PER_SEC; 364 ns = nsecs - s * NSEC_PER_SEC;
364 365
365 scripting_context->event_data = data; 366 scripting_context->event_data = data;
366 scripting_context->pevent = evsel->tp_format->pevent; 367 scripting_context->pevent = evsel->tp_format->pevent;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index e0203b979474..089438da1f7f 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -27,6 +27,7 @@
27#include <stdbool.h> 27#include <stdbool.h>
28#include <errno.h> 28#include <errno.h>
29#include <linux/bitmap.h> 29#include <linux/bitmap.h>
30#include <linux/time64.h>
30 31
31#include "../../perf.h" 32#include "../../perf.h"
32#include "../debug.h" 33#include "../debug.h"
@@ -426,8 +427,8 @@ static void python_process_tracepoint(struct perf_sample *sample,
426 if (!dict) 427 if (!dict)
427 Py_FatalError("couldn't create Python dict"); 428 Py_FatalError("couldn't create Python dict");
428 } 429 }
429 s = nsecs / NSECS_PER_SEC; 430 s = nsecs / NSEC_PER_SEC;
430 ns = nsecs - s * NSECS_PER_SEC; 431 ns = nsecs - s * NSEC_PER_SEC;
431 432
432 scripting_context->event_data = data; 433 scripting_context->event_data = data;
433 scripting_context->pevent = evsel->tp_format->pevent; 434 scripting_context->pevent = evsel->tp_format->pevent;
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 3d3cb8392c86..452e15a10dd2 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -11,7 +11,7 @@
11regex_t parent_regex; 11regex_t parent_regex;
12const char default_parent_pattern[] = "^sys_|^do_page_fault"; 12const char default_parent_pattern[] = "^sys_|^do_page_fault";
13const char *parent_pattern = default_parent_pattern; 13const char *parent_pattern = default_parent_pattern;
14const char default_sort_order[] = "comm,dso,symbol"; 14const char *default_sort_order = "comm,dso,symbol";
15const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles"; 15const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles";
16const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked"; 16const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
17const char default_top_sort_order[] = "dso,symbol"; 17const char default_top_sort_order[] = "dso,symbol";
@@ -867,7 +867,7 @@ struct sort_entry sort_cycles = {
867}; 867};
868 868
869/* --sort daddr_sym */ 869/* --sort daddr_sym */
870static int64_t 870int64_t
871sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right) 871sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
872{ 872{
873 uint64_t l = 0, r = 0; 873 uint64_t l = 0, r = 0;
@@ -896,7 +896,7 @@ static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
896 width); 896 width);
897} 897}
898 898
899static int64_t 899int64_t
900sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right) 900sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right)
901{ 901{
902 uint64_t l = 0, r = 0; 902 uint64_t l = 0, r = 0;
@@ -1062,7 +1062,7 @@ static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
1062 return repsep_snprintf(bf, size, "%-*s", width, out); 1062 return repsep_snprintf(bf, size, "%-*s", width, out);
1063} 1063}
1064 1064
1065static int64_t 1065int64_t
1066sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right) 1066sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
1067{ 1067{
1068 u64 l, r; 1068 u64 l, r;
@@ -1492,7 +1492,8 @@ void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1492} 1492}
1493 1493
1494static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1494static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1495 struct hists *hists) 1495 struct hists *hists, int line __maybe_unused,
1496 int *span __maybe_unused)
1496{ 1497{
1497 struct hpp_sort_entry *hse; 1498 struct hpp_sort_entry *hse;
1498 size_t len = fmt->user_len; 1499 size_t len = fmt->user_len;
@@ -1797,7 +1798,9 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde,
1797} 1798}
1798 1799
1799static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1800static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1800 struct hists *hists __maybe_unused) 1801 struct hists *hists __maybe_unused,
1802 int line __maybe_unused,
1803 int *span __maybe_unused)
1801{ 1804{
1802 struct hpp_dynamic_entry *hde; 1805 struct hpp_dynamic_entry *hde;
1803 size_t len = fmt->user_len; 1806 size_t len = fmt->user_len;
@@ -2305,9 +2308,9 @@ int hpp_dimension__add_output(unsigned col)
2305 return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]); 2308 return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]);
2306} 2309}
2307 2310
2308static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, 2311int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2309 struct perf_evlist *evlist, 2312 struct perf_evlist *evlist,
2310 int level) 2313 int level)
2311{ 2314{
2312 unsigned int i; 2315 unsigned int i;
2313 2316
@@ -2682,7 +2685,7 @@ void sort__setup_elide(FILE *output)
2682 } 2685 }
2683} 2686}
2684 2687
2685static int output_field_add(struct perf_hpp_list *list, char *tok) 2688int output_field_add(struct perf_hpp_list *list, char *tok)
2686{ 2689{
2687 unsigned int i; 2690 unsigned int i;
2688 2691
@@ -2745,7 +2748,7 @@ static int setup_output_list(struct perf_hpp_list *list, char *str)
2745 return ret; 2748 return ret;
2746} 2749}
2747 2750
2748static void reset_dimensions(void) 2751void reset_dimensions(void)
2749{ 2752{
2750 unsigned int i; 2753 unsigned int i;
2751 2754
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 7ca37ea17395..099c97557d33 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -28,7 +28,7 @@ extern const char *sort_order;
28extern const char *field_order; 28extern const char *field_order;
29extern const char default_parent_pattern[]; 29extern const char default_parent_pattern[];
30extern const char *parent_pattern; 30extern 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 enum sort_mode sort__mode; 34extern enum sort_mode sort__mode;
@@ -40,6 +40,7 @@ extern struct sort_entry sort_dso_from;
40extern struct sort_entry sort_dso_to; 40extern struct sort_entry sort_dso_to;
41extern struct sort_entry sort_sym_from; 41extern struct sort_entry sort_sym_from;
42extern struct sort_entry sort_sym_to; 42extern struct sort_entry sort_sym_to;
43extern struct sort_entry sort_srcline;
43extern enum sort_type sort__first_dimension; 44extern enum sort_type sort__first_dimension;
44extern const char default_mem_sort_order[]; 45extern const char default_mem_sort_order[];
45 46
@@ -268,4 +269,15 @@ int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, i
268bool is_strict_order(const char *order); 269bool is_strict_order(const char *order);
269 270
270int hpp_dimension__add_output(unsigned col); 271int hpp_dimension__add_output(unsigned col);
272void reset_dimensions(void);
273int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
274 struct perf_evlist *evlist,
275 int level);
276int output_field_add(struct perf_hpp_list *list, char *tok);
277int64_t
278sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right);
279int64_t
280sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right);
281int64_t
282sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right);
271#endif /* __PERF_SORT_H */ 283#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index eec6c1149f44..1cbada2dc6be 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -18,6 +18,7 @@
18#include <unistd.h> 18#include <unistd.h>
19#include <string.h> 19#include <string.h>
20#include <linux/bitmap.h> 20#include <linux/bitmap.h>
21#include <linux/time64.h>
21 22
22#include "perf.h" 23#include "perf.h"
23#include "svghelper.h" 24#include "svghelper.h"
@@ -274,14 +275,14 @@ static char *time_to_string(u64 duration)
274 275
275 text[0] = 0; 276 text[0] = 0;
276 277
277 if (duration < 1000) /* less than 1 usec */ 278 if (duration < NSEC_PER_USEC) /* less than 1 usec */
278 return text; 279 return text;
279 280
280 if (duration < 1000 * 1000) { /* less than 1 msec */ 281 if (duration < NSEC_PER_MSEC) { /* less than 1 msec */
281 sprintf(text, "%.1f us", duration / 1000.0); 282 sprintf(text, "%.1f us", duration / (double)NSEC_PER_USEC);
282 return text; 283 return text;
283 } 284 }
284 sprintf(text, "%.1f ms", duration / 1000.0 / 1000); 285 sprintf(text, "%.1f ms", duration / (double)NSEC_PER_MSEC);
285 286
286 return text; 287 return text;
287} 288}
@@ -297,7 +298,7 @@ void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
297 298
298 style = "waiting"; 299 style = "waiting";
299 300
300 if (end-start > 10 * 1000000) /* 10 msec */ 301 if (end-start > 10 * NSEC_PER_MSEC) /* 10 msec */
301 style = "WAITING"; 302 style = "WAITING";
302 303
303 text = time_to_string(end-start); 304 text = time_to_string(end-start);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index a811c13a74d6..99400b0e8f2a 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -206,6 +206,37 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
206 return NULL; 206 return NULL;
207} 207}
208 208
209static bool want_demangle(bool is_kernel_sym)
210{
211 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
212}
213
214static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
215{
216 int demangle_flags = verbose ? (DMGL_PARAMS | DMGL_ANSI) : DMGL_NO_OPTS;
217 char *demangled = NULL;
218
219 /*
220 * We need to figure out if the object was created from C++ sources
221 * DWARF DW_compile_unit has this, but we don't always have access
222 * to it...
223 */
224 if (!want_demangle(dso->kernel || kmodule))
225 return demangled;
226
227 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
228 if (demangled == NULL)
229 demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
230 else if (rust_is_mangled(demangled))
231 /*
232 * Input to Rust demangling is the BFD-demangled
233 * name which it Rust-demangles in place.
234 */
235 rust_demangle_sym(demangled);
236
237 return demangled;
238}
239
209#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ 240#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
210 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \ 241 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
211 idx < nr_entries; \ 242 idx < nr_entries; \
@@ -223,8 +254,7 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
223 * And always look at the original dso, not at debuginfo packages, that 254 * And always look at the original dso, not at debuginfo packages, that
224 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 255 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
225 */ 256 */
226int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map, 257int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map)
227 symbol_filter_t filter)
228{ 258{
229 uint32_t nr_rel_entries, idx; 259 uint32_t nr_rel_entries, idx;
230 GElf_Sym sym; 260 GElf_Sym sym;
@@ -301,45 +331,53 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
301 331
302 elf_section__for_each_rela(reldata, pos, pos_mem, idx, 332 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
303 nr_rel_entries) { 333 nr_rel_entries) {
334 const char *elf_name = NULL;
335 char *demangled = NULL;
304 symidx = GELF_R_SYM(pos->r_info); 336 symidx = GELF_R_SYM(pos->r_info);
305 plt_offset += shdr_plt.sh_entsize; 337 plt_offset += shdr_plt.sh_entsize;
306 gelf_getsym(syms, symidx, &sym); 338 gelf_getsym(syms, symidx, &sym);
339
340 elf_name = elf_sym__name(&sym, symstrs);
341 demangled = demangle_sym(dso, 0, elf_name);
342 if (demangled != NULL)
343 elf_name = demangled;
307 snprintf(sympltname, sizeof(sympltname), 344 snprintf(sympltname, sizeof(sympltname),
308 "%s@plt", elf_sym__name(&sym, symstrs)); 345 "%s@plt", elf_name);
346 free(demangled);
309 347
310 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 348 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
311 STB_GLOBAL, sympltname); 349 STB_GLOBAL, sympltname);
312 if (!f) 350 if (!f)
313 goto out_elf_end; 351 goto out_elf_end;
314 352
315 if (filter && filter(map, f)) 353 symbols__insert(&dso->symbols[map->type], f);
316 symbol__delete(f); 354 ++nr;
317 else {
318 symbols__insert(&dso->symbols[map->type], f);
319 ++nr;
320 }
321 } 355 }
322 } else if (shdr_rel_plt.sh_type == SHT_REL) { 356 } else if (shdr_rel_plt.sh_type == SHT_REL) {
323 GElf_Rel pos_mem, *pos; 357 GElf_Rel pos_mem, *pos;
324 elf_section__for_each_rel(reldata, pos, pos_mem, idx, 358 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
325 nr_rel_entries) { 359 nr_rel_entries) {
360 const char *elf_name = NULL;
361 char *demangled = NULL;
326 symidx = GELF_R_SYM(pos->r_info); 362 symidx = GELF_R_SYM(pos->r_info);
327 plt_offset += shdr_plt.sh_entsize; 363 plt_offset += shdr_plt.sh_entsize;
328 gelf_getsym(syms, symidx, &sym); 364 gelf_getsym(syms, symidx, &sym);
365
366 elf_name = elf_sym__name(&sym, symstrs);
367 demangled = demangle_sym(dso, 0, elf_name);
368 if (demangled != NULL)
369 elf_name = demangled;
329 snprintf(sympltname, sizeof(sympltname), 370 snprintf(sympltname, sizeof(sympltname),
330 "%s@plt", elf_sym__name(&sym, symstrs)); 371 "%s@plt", elf_name);
372 free(demangled);
331 373
332 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 374 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
333 STB_GLOBAL, sympltname); 375 STB_GLOBAL, sympltname);
334 if (!f) 376 if (!f)
335 goto out_elf_end; 377 goto out_elf_end;
336 378
337 if (filter && filter(map, f)) 379 symbols__insert(&dso->symbols[map->type], f);
338 symbol__delete(f); 380 ++nr;
339 else {
340 symbols__insert(&dso->symbols[map->type], f);
341 ++nr;
342 }
343 } 381 }
344 } 382 }
345 383
@@ -685,7 +723,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
685 } 723 }
686 724
687 /* Always reject images with a mismatched build-id: */ 725 /* Always reject images with a mismatched build-id: */
688 if (dso->has_build_id) { 726 if (dso->has_build_id && !symbol_conf.ignore_vmlinux_buildid) {
689 u8 build_id[BUILD_ID_SIZE]; 727 u8 build_id[BUILD_ID_SIZE];
690 728
691 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) { 729 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) {
@@ -775,17 +813,11 @@ static u64 ref_reloc(struct kmap *kmap)
775 return 0; 813 return 0;
776} 814}
777 815
778static bool want_demangle(bool is_kernel_sym)
779{
780 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
781}
782
783void __weak arch__sym_update(struct symbol *s __maybe_unused, 816void __weak arch__sym_update(struct symbol *s __maybe_unused,
784 GElf_Sym *sym __maybe_unused) { } 817 GElf_Sym *sym __maybe_unused) { }
785 818
786int dso__load_sym(struct dso *dso, struct map *map, 819int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
787 struct symsrc *syms_ss, struct symsrc *runtime_ss, 820 struct symsrc *runtime_ss, int kmodule)
788 symbol_filter_t filter, int kmodule)
789{ 821{
790 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; 822 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
791 struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL; 823 struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL;
@@ -1070,29 +1102,10 @@ int dso__load_sym(struct dso *dso, struct map *map,
1070 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 1102 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
1071 } 1103 }
1072new_symbol: 1104new_symbol:
1073 /* 1105 demangled = demangle_sym(dso, kmodule, elf_name);
1074 * We need to figure out if the object was created from C++ sources 1106 if (demangled != NULL)
1075 * DWARF DW_compile_unit has this, but we don't always have access 1107 elf_name = demangled;
1076 * to it...
1077 */
1078 if (want_demangle(dso->kernel || kmodule)) {
1079 int demangle_flags = DMGL_NO_OPTS;
1080 if (verbose)
1081 demangle_flags = DMGL_PARAMS | DMGL_ANSI;
1082
1083 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
1084 if (demangled == NULL)
1085 demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
1086 else if (rust_is_mangled(demangled))
1087 /*
1088 * Input to Rust demangling is the BFD-demangled
1089 * name which it Rust-demangles in place.
1090 */
1091 rust_demangle_sym(demangled);
1092 1108
1093 if (demangled != NULL)
1094 elf_name = demangled;
1095 }
1096 f = symbol__new(sym.st_value, sym.st_size, 1109 f = symbol__new(sym.st_value, sym.st_size,
1097 GELF_ST_BIND(sym.st_info), elf_name); 1110 GELF_ST_BIND(sym.st_info), elf_name);
1098 free(demangled); 1111 free(demangled);
@@ -1101,21 +1114,16 @@ new_symbol:
1101 1114
1102 arch__sym_update(f, &sym); 1115 arch__sym_update(f, &sym);
1103 1116
1104 if (filter && filter(curr_map, f)) 1117 __symbols__insert(&curr_dso->symbols[curr_map->type], f, dso->kernel);
1105 symbol__delete(f); 1118 nr++;
1106 else {
1107 symbols__insert(&curr_dso->symbols[curr_map->type], f);
1108 nr++;
1109 }
1110 } 1119 }
1111 1120
1112 /* 1121 /*
1113 * For misannotated, zeroed, ASM function sizes. 1122 * For misannotated, zeroed, ASM function sizes.
1114 */ 1123 */
1115 if (nr > 0) { 1124 if (nr > 0) {
1116 if (!symbol_conf.allow_aliases)
1117 symbols__fixup_duplicate(&dso->symbols[map->type]);
1118 symbols__fixup_end(&dso->symbols[map->type]); 1125 symbols__fixup_end(&dso->symbols[map->type]);
1126 symbols__fixup_duplicate(&dso->symbols[map->type]);
1119 if (kmap) { 1127 if (kmap) {
1120 /* 1128 /*
1121 * We need to fixup this here too because we create new 1129 * We need to fixup this here too because we create new
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 48906333a858..11cdde980545 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -287,8 +287,7 @@ void symsrc__destroy(struct symsrc *ss)
287 287
288int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused, 288int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
289 struct symsrc *ss __maybe_unused, 289 struct symsrc *ss __maybe_unused,
290 struct map *map __maybe_unused, 290 struct map *map __maybe_unused)
291 symbol_filter_t filter __maybe_unused)
292{ 291{
293 return 0; 292 return 0;
294} 293}
@@ -334,7 +333,6 @@ enum dso_type dso__type_fd(int fd)
334int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, 333int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
335 struct symsrc *ss, 334 struct symsrc *ss,
336 struct symsrc *runtime_ss __maybe_unused, 335 struct symsrc *runtime_ss __maybe_unused,
337 symbol_filter_t filter __maybe_unused,
338 int kmodule __maybe_unused) 336 int kmodule __maybe_unused)
339{ 337{
340 unsigned char build_id[BUILD_ID_SIZE]; 338 unsigned char build_id[BUILD_ID_SIZE];
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 37e8d20ae03e..aecff69a510d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -9,6 +9,7 @@
9#include <fcntl.h> 9#include <fcntl.h>
10#include <unistd.h> 10#include <unistd.h>
11#include <inttypes.h> 11#include <inttypes.h>
12#include "annotate.h"
12#include "build-id.h" 13#include "build-id.h"
13#include "util.h" 14#include "util.h"
14#include "debug.h" 15#include "debug.h"
@@ -23,10 +24,10 @@
23#include <symbol/kallsyms.h> 24#include <symbol/kallsyms.h>
24#include <sys/utsname.h> 25#include <sys/utsname.h>
25 26
26static int dso__load_kernel_sym(struct dso *dso, struct map *map, 27static int dso__load_kernel_sym(struct dso *dso, struct map *map);
27 symbol_filter_t filter); 28static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map);
28static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 29static bool symbol__is_idle(const char *name);
29 symbol_filter_t filter); 30
30int vmlinux_path__nr_entries; 31int vmlinux_path__nr_entries;
31char **vmlinux_path; 32char **vmlinux_path;
32 33
@@ -152,6 +153,9 @@ void symbols__fixup_duplicate(struct rb_root *symbols)
152 struct rb_node *nd; 153 struct rb_node *nd;
153 struct symbol *curr, *next; 154 struct symbol *curr, *next;
154 155
156 if (symbol_conf.allow_aliases)
157 return;
158
155 nd = rb_first(symbols); 159 nd = rb_first(symbols);
156 160
157 while (nd) { 161 while (nd) {
@@ -235,8 +239,13 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
235 if (sym == NULL) 239 if (sym == NULL)
236 return NULL; 240 return NULL;
237 241
238 if (symbol_conf.priv_size) 242 if (symbol_conf.priv_size) {
243 if (symbol_conf.init_annotation) {
244 struct annotation *notes = (void *)sym;
245 pthread_mutex_init(&notes->lock, NULL);
246 }
239 sym = ((void *)sym) + symbol_conf.priv_size; 247 sym = ((void *)sym) + symbol_conf.priv_size;
248 }
240 249
241 sym->start = start; 250 sym->start = start;
242 sym->end = len ? start + len : start; 251 sym->end = len ? start + len : start;
@@ -268,13 +277,24 @@ void symbols__delete(struct rb_root *symbols)
268 } 277 }
269} 278}
270 279
271void symbols__insert(struct rb_root *symbols, struct symbol *sym) 280void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel)
272{ 281{
273 struct rb_node **p = &symbols->rb_node; 282 struct rb_node **p = &symbols->rb_node;
274 struct rb_node *parent = NULL; 283 struct rb_node *parent = NULL;
275 const u64 ip = sym->start; 284 const u64 ip = sym->start;
276 struct symbol *s; 285 struct symbol *s;
277 286
287 if (kernel) {
288 const char *name = sym->name;
289 /*
290 * ppc64 uses function descriptors and appends a '.' to the
291 * start of every instruction address. Remove it.
292 */
293 if (name[0] == '.')
294 name++;
295 sym->idle = symbol__is_idle(name);
296 }
297
278 while (*p != NULL) { 298 while (*p != NULL) {
279 parent = *p; 299 parent = *p;
280 s = rb_entry(parent, struct symbol, rb_node); 300 s = rb_entry(parent, struct symbol, rb_node);
@@ -287,6 +307,11 @@ void symbols__insert(struct rb_root *symbols, struct symbol *sym)
287 rb_insert_color(&sym->rb_node, symbols); 307 rb_insert_color(&sym->rb_node, symbols);
288} 308}
289 309
310void symbols__insert(struct rb_root *symbols, struct symbol *sym)
311{
312 __symbols__insert(symbols, sym, false);
313}
314
290static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) 315static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
291{ 316{
292 struct rb_node *n; 317 struct rb_node *n;
@@ -320,6 +345,16 @@ static struct symbol *symbols__first(struct rb_root *symbols)
320 return NULL; 345 return NULL;
321} 346}
322 347
348static struct symbol *symbols__last(struct rb_root *symbols)
349{
350 struct rb_node *n = rb_last(symbols);
351
352 if (n)
353 return rb_entry(n, struct symbol, rb_node);
354
355 return NULL;
356}
357
323static struct symbol *symbols__next(struct symbol *sym) 358static struct symbol *symbols__next(struct symbol *sym)
324{ 359{
325 struct rb_node *n = rb_next(&sym->rb_node); 360 struct rb_node *n = rb_next(&sym->rb_node);
@@ -415,7 +450,7 @@ void dso__reset_find_symbol_cache(struct dso *dso)
415 450
416void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym) 451void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym)
417{ 452{
418 symbols__insert(&dso->symbols[type], sym); 453 __symbols__insert(&dso->symbols[type], sym, dso->kernel);
419 454
420 /* update the symbol cache if necessary */ 455 /* update the symbol cache if necessary */
421 if (dso->last_find_result[type].addr >= sym->start && 456 if (dso->last_find_result[type].addr >= sym->start &&
@@ -441,6 +476,11 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
441 return symbols__first(&dso->symbols[type]); 476 return symbols__first(&dso->symbols[type]);
442} 477}
443 478
479struct symbol *dso__last_symbol(struct dso *dso, enum map_type type)
480{
481 return symbols__last(&dso->symbols[type]);
482}
483
444struct symbol *dso__next_symbol(struct symbol *sym) 484struct symbol *dso__next_symbol(struct symbol *sym)
445{ 485{
446 return symbols__next(sym); 486 return symbols__next(sym);
@@ -537,7 +577,7 @@ struct process_kallsyms_args {
537 * These are symbols in the kernel image, so make sure that 577 * These are symbols in the kernel image, so make sure that
538 * sym is from a kernel DSO. 578 * sym is from a kernel DSO.
539 */ 579 */
540bool symbol__is_idle(struct symbol *sym) 580static bool symbol__is_idle(const char *name)
541{ 581{
542 const char * const idle_symbols[] = { 582 const char * const idle_symbols[] = {
543 "cpu_idle", 583 "cpu_idle",
@@ -554,14 +594,10 @@ bool symbol__is_idle(struct symbol *sym)
554 "pseries_dedicated_idle_sleep", 594 "pseries_dedicated_idle_sleep",
555 NULL 595 NULL
556 }; 596 };
557
558 int i; 597 int i;
559 598
560 if (!sym)
561 return false;
562
563 for (i = 0; idle_symbols[i]; i++) { 599 for (i = 0; idle_symbols[i]; i++) {
564 if (!strcmp(idle_symbols[i], sym->name)) 600 if (!strcmp(idle_symbols[i], name))
565 return true; 601 return true;
566 } 602 }
567 603
@@ -590,7 +626,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
590 * We will pass the symbols to the filter later, in 626 * We will pass the symbols to the filter later, in
591 * map__split_kallsyms, when we have split the maps per module 627 * map__split_kallsyms, when we have split the maps per module
592 */ 628 */
593 symbols__insert(root, sym); 629 __symbols__insert(root, sym, !strchr(name, '['));
594 630
595 return 0; 631 return 0;
596} 632}
@@ -607,8 +643,7 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
607 return kallsyms__parse(filename, &args, map__process_kallsym_symbol); 643 return kallsyms__parse(filename, &args, map__process_kallsym_symbol);
608} 644}
609 645
610static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, 646static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map)
611 symbol_filter_t filter)
612{ 647{
613 struct map_groups *kmaps = map__kmaps(map); 648 struct map_groups *kmaps = map__kmaps(map);
614 struct map *curr_map; 649 struct map *curr_map;
@@ -637,7 +672,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
637 672
638 curr_map = map_groups__find(kmaps, map->type, pos->start); 673 curr_map = map_groups__find(kmaps, map->type, pos->start);
639 674
640 if (!curr_map || (filter && filter(curr_map, pos))) { 675 if (!curr_map) {
641 symbol__delete(pos); 676 symbol__delete(pos);
642 continue; 677 continue;
643 } 678 }
@@ -660,8 +695,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
660 * kernel range is broken in several maps, named [kernel].N, as we don't have 695 * kernel range is broken in several maps, named [kernel].N, as we don't have
661 * the original ELF section names vmlinux have. 696 * the original ELF section names vmlinux have.
662 */ 697 */
663static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, 698static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta)
664 symbol_filter_t filter)
665{ 699{
666 struct map_groups *kmaps = map__kmaps(map); 700 struct map_groups *kmaps = map__kmaps(map);
667 struct machine *machine; 701 struct machine *machine;
@@ -738,7 +772,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
738 772
739 if (count == 0) { 773 if (count == 0) {
740 curr_map = map; 774 curr_map = map;
741 goto filter_symbol; 775 goto add_symbol;
742 } 776 }
743 777
744 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 778 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
@@ -770,18 +804,18 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
770 pos->start -= delta; 804 pos->start -= delta;
771 pos->end -= delta; 805 pos->end -= delta;
772 } 806 }
773filter_symbol: 807add_symbol:
774 if (filter && filter(curr_map, pos)) { 808 if (curr_map != map) {
775discard_symbol: rb_erase(&pos->rb_node, root); 809 rb_erase(&pos->rb_node, root);
776 symbol__delete(pos); 810 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
777 } else { 811 ++moved;
778 if (curr_map != map) { 812 } else
779 rb_erase(&pos->rb_node, root); 813 ++count;
780 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); 814
781 ++moved; 815 continue;
782 } else 816discard_symbol:
783 ++count; 817 rb_erase(&pos->rb_node, root);
784 } 818 symbol__delete(pos);
785 } 819 }
786 820
787 if (curr_map != map && 821 if (curr_map != map &&
@@ -1221,7 +1255,7 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1221} 1255}
1222 1256
1223int __dso__load_kallsyms(struct dso *dso, const char *filename, 1257int __dso__load_kallsyms(struct dso *dso, const char *filename,
1224 struct map *map, bool no_kcore, symbol_filter_t filter) 1258 struct map *map, bool no_kcore)
1225{ 1259{
1226 u64 delta = 0; 1260 u64 delta = 0;
1227 1261
@@ -1234,8 +1268,8 @@ int __dso__load_kallsyms(struct dso *dso, const char *filename,
1234 if (kallsyms__delta(map, filename, &delta)) 1268 if (kallsyms__delta(map, filename, &delta))
1235 return -1; 1269 return -1;
1236 1270
1237 symbols__fixup_duplicate(&dso->symbols[map->type]);
1238 symbols__fixup_end(&dso->symbols[map->type]); 1271 symbols__fixup_end(&dso->symbols[map->type]);
1272 symbols__fixup_duplicate(&dso->symbols[map->type]);
1239 1273
1240 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1274 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1241 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; 1275 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
@@ -1243,19 +1277,18 @@ int __dso__load_kallsyms(struct dso *dso, const char *filename,
1243 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; 1277 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
1244 1278
1245 if (!no_kcore && !dso__load_kcore(dso, map, filename)) 1279 if (!no_kcore && !dso__load_kcore(dso, map, filename))
1246 return dso__split_kallsyms_for_kcore(dso, map, filter); 1280 return dso__split_kallsyms_for_kcore(dso, map);
1247 else 1281 else
1248 return dso__split_kallsyms(dso, map, delta, filter); 1282 return dso__split_kallsyms(dso, map, delta);
1249} 1283}
1250 1284
1251int dso__load_kallsyms(struct dso *dso, const char *filename, 1285int dso__load_kallsyms(struct dso *dso, const char *filename,
1252 struct map *map, symbol_filter_t filter) 1286 struct map *map)
1253{ 1287{
1254 return __dso__load_kallsyms(dso, filename, map, false, filter); 1288 return __dso__load_kallsyms(dso, filename, map, false);
1255} 1289}
1256 1290
1257static int dso__load_perf_map(struct dso *dso, struct map *map, 1291static int dso__load_perf_map(struct dso *dso, struct map *map)
1258 symbol_filter_t filter)
1259{ 1292{
1260 char *line = NULL; 1293 char *line = NULL;
1261 size_t n; 1294 size_t n;
@@ -1297,12 +1330,8 @@ static int dso__load_perf_map(struct dso *dso, struct map *map,
1297 if (sym == NULL) 1330 if (sym == NULL)
1298 goto out_delete_line; 1331 goto out_delete_line;
1299 1332
1300 if (filter && filter(map, sym)) 1333 symbols__insert(&dso->symbols[map->type], sym);
1301 symbol__delete(sym); 1334 nr_syms++;
1302 else {
1303 symbols__insert(&dso->symbols[map->type], sym);
1304 nr_syms++;
1305 }
1306 } 1335 }
1307 1336
1308 free(line); 1337 free(line);
@@ -1358,7 +1387,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1358 } 1387 }
1359} 1388}
1360 1389
1361int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 1390int dso__load(struct dso *dso, struct map *map)
1362{ 1391{
1363 char *name; 1392 char *name;
1364 int ret = -1; 1393 int ret = -1;
@@ -1381,9 +1410,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1381 1410
1382 if (dso->kernel) { 1411 if (dso->kernel) {
1383 if (dso->kernel == DSO_TYPE_KERNEL) 1412 if (dso->kernel == DSO_TYPE_KERNEL)
1384 ret = dso__load_kernel_sym(dso, map, filter); 1413 ret = dso__load_kernel_sym(dso, map);
1385 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1414 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1386 ret = dso__load_guest_kernel_sym(dso, map, filter); 1415 ret = dso__load_guest_kernel_sym(dso, map);
1387 1416
1388 goto out; 1417 goto out;
1389 } 1418 }
@@ -1407,7 +1436,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1407 goto out; 1436 goto out;
1408 } 1437 }
1409 1438
1410 ret = dso__load_perf_map(dso, map, filter); 1439 ret = dso__load_perf_map(dso, map);
1411 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : 1440 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1412 DSO_BINARY_TYPE__NOT_FOUND; 1441 DSO_BINARY_TYPE__NOT_FOUND;
1413 goto out; 1442 goto out;
@@ -1498,14 +1527,14 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1498 kmod = true; 1527 kmod = true;
1499 1528
1500 if (syms_ss) 1529 if (syms_ss)
1501 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod); 1530 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, kmod);
1502 else 1531 else
1503 ret = -1; 1532 ret = -1;
1504 1533
1505 if (ret > 0) { 1534 if (ret > 0) {
1506 int nr_plt; 1535 int nr_plt;
1507 1536
1508 nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map, filter); 1537 nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map);
1509 if (nr_plt > 0) 1538 if (nr_plt > 0)
1510 ret += nr_plt; 1539 ret += nr_plt;
1511 } 1540 }
@@ -1544,8 +1573,7 @@ out_unlock:
1544} 1573}
1545 1574
1546int dso__load_vmlinux(struct dso *dso, struct map *map, 1575int dso__load_vmlinux(struct dso *dso, struct map *map,
1547 const char *vmlinux, bool vmlinux_allocated, 1576 const char *vmlinux, bool vmlinux_allocated)
1548 symbol_filter_t filter)
1549{ 1577{
1550 int err = -1; 1578 int err = -1;
1551 struct symsrc ss; 1579 struct symsrc ss;
@@ -1565,7 +1593,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1565 if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type)) 1593 if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type))
1566 return -1; 1594 return -1;
1567 1595
1568 err = dso__load_sym(dso, map, &ss, &ss, filter, 0); 1596 err = dso__load_sym(dso, map, &ss, &ss, 0);
1569 symsrc__destroy(&ss); 1597 symsrc__destroy(&ss);
1570 1598
1571 if (err > 0) { 1599 if (err > 0) {
@@ -1581,8 +1609,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1581 return err; 1609 return err;
1582} 1610}
1583 1611
1584int dso__load_vmlinux_path(struct dso *dso, struct map *map, 1612int dso__load_vmlinux_path(struct dso *dso, struct map *map)
1585 symbol_filter_t filter)
1586{ 1613{
1587 int i, err = 0; 1614 int i, err = 0;
1588 char *filename = NULL; 1615 char *filename = NULL;
@@ -1591,7 +1618,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1591 vmlinux_path__nr_entries + 1); 1618 vmlinux_path__nr_entries + 1);
1592 1619
1593 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1620 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1594 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); 1621 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false);
1595 if (err > 0) 1622 if (err > 0)
1596 goto out; 1623 goto out;
1597 } 1624 }
@@ -1599,7 +1626,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1599 if (!symbol_conf.ignore_vmlinux_buildid) 1626 if (!symbol_conf.ignore_vmlinux_buildid)
1600 filename = dso__build_id_filename(dso, NULL, 0); 1627 filename = dso__build_id_filename(dso, NULL, 0);
1601 if (filename != NULL) { 1628 if (filename != NULL) {
1602 err = dso__load_vmlinux(dso, map, filename, true, filter); 1629 err = dso__load_vmlinux(dso, map, filename, true);
1603 if (err > 0) 1630 if (err > 0)
1604 goto out; 1631 goto out;
1605 free(filename); 1632 free(filename);
@@ -1713,8 +1740,7 @@ proc_kallsyms:
1713 return strdup(path); 1740 return strdup(path);
1714} 1741}
1715 1742
1716static int dso__load_kernel_sym(struct dso *dso, struct map *map, 1743static int dso__load_kernel_sym(struct dso *dso, struct map *map)
1717 symbol_filter_t filter)
1718{ 1744{
1719 int err; 1745 int err;
1720 const char *kallsyms_filename = NULL; 1746 const char *kallsyms_filename = NULL;
@@ -1740,12 +1766,11 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1740 } 1766 }
1741 1767
1742 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { 1768 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
1743 return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name, 1769 return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name, false);
1744 false, filter);
1745 } 1770 }
1746 1771
1747 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { 1772 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
1748 err = dso__load_vmlinux_path(dso, map, filter); 1773 err = dso__load_vmlinux_path(dso, map);
1749 if (err > 0) 1774 if (err > 0)
1750 return err; 1775 return err;
1751 } 1776 }
@@ -1761,7 +1786,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1761 kallsyms_filename = kallsyms_allocated_filename; 1786 kallsyms_filename = kallsyms_allocated_filename;
1762 1787
1763do_kallsyms: 1788do_kallsyms:
1764 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1789 err = dso__load_kallsyms(dso, kallsyms_filename, map);
1765 if (err > 0) 1790 if (err > 0)
1766 pr_debug("Using %s for symbols\n", kallsyms_filename); 1791 pr_debug("Using %s for symbols\n", kallsyms_filename);
1767 free(kallsyms_allocated_filename); 1792 free(kallsyms_allocated_filename);
@@ -1776,8 +1801,7 @@ do_kallsyms:
1776 return err; 1801 return err;
1777} 1802}
1778 1803
1779static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 1804static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map)
1780 symbol_filter_t filter)
1781{ 1805{
1782 int err; 1806 int err;
1783 const char *kallsyms_filename = NULL; 1807 const char *kallsyms_filename = NULL;
@@ -1799,7 +1823,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1799 if (symbol_conf.default_guest_vmlinux_name != NULL) { 1823 if (symbol_conf.default_guest_vmlinux_name != NULL) {
1800 err = dso__load_vmlinux(dso, map, 1824 err = dso__load_vmlinux(dso, map,
1801 symbol_conf.default_guest_vmlinux_name, 1825 symbol_conf.default_guest_vmlinux_name,
1802 false, filter); 1826 false);
1803 return err; 1827 return err;
1804 } 1828 }
1805 1829
@@ -1811,7 +1835,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1811 kallsyms_filename = path; 1835 kallsyms_filename = path;
1812 } 1836 }
1813 1837
1814 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1838 err = dso__load_kallsyms(dso, kallsyms_filename, map);
1815 if (err > 0) 1839 if (err > 0)
1816 pr_debug("Using %s for symbols\n", kallsyms_filename); 1840 pr_debug("Using %s for symbols\n", kallsyms_filename);
1817 if (err > 0 && !dso__is_kcore(dso)) { 1841 if (err > 0 && !dso__is_kcore(dso)) {
@@ -1948,6 +1972,23 @@ static bool symbol__read_kptr_restrict(void)
1948 return value; 1972 return value;
1949} 1973}
1950 1974
1975int symbol__annotation_init(void)
1976{
1977 if (symbol_conf.initialized) {
1978 pr_err("Annotation needs to be init before symbol__init()\n");
1979 return -1;
1980 }
1981
1982 if (symbol_conf.init_annotation) {
1983 pr_warning("Annotation being initialized multiple times\n");
1984 return 0;
1985 }
1986
1987 symbol_conf.priv_size += sizeof(struct annotation);
1988 symbol_conf.init_annotation = true;
1989 return 0;
1990}
1991
1951int symbol__init(struct perf_env *env) 1992int symbol__init(struct perf_env *env)
1952{ 1993{
1953 const char *symfs; 1994 const char *symfs;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 699f7cbcfe72..d964844eb314 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -57,7 +57,7 @@ struct symbol {
57 u64 end; 57 u64 end;
58 u16 namelen; 58 u16 namelen;
59 u8 binding; 59 u8 binding;
60 bool ignore; 60 u8 idle:1;
61 u8 arch_sym; 61 u8 arch_sym;
62 char name[0]; 62 char name[0];
63}; 63};
@@ -88,6 +88,7 @@ struct symbol_conf {
88 unsigned short priv_size; 88 unsigned short priv_size;
89 unsigned short nr_events; 89 unsigned short nr_events;
90 bool try_vmlinux_path, 90 bool try_vmlinux_path,
91 init_annotation,
91 force, 92 force,
92 ignore_vmlinux, 93 ignore_vmlinux,
93 ignore_vmlinux_buildid, 94 ignore_vmlinux_buildid,
@@ -240,16 +241,13 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
240bool symsrc__has_symtab(struct symsrc *ss); 241bool symsrc__has_symtab(struct symsrc *ss);
241bool symsrc__possibly_runtime(struct symsrc *ss); 242bool symsrc__possibly_runtime(struct symsrc *ss);
242 243
243int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); 244int dso__load(struct dso *dso, struct map *map);
244int dso__load_vmlinux(struct dso *dso, struct map *map, 245int dso__load_vmlinux(struct dso *dso, struct map *map,
245 const char *vmlinux, bool vmlinux_allocated, 246 const char *vmlinux, bool vmlinux_allocated);
246 symbol_filter_t filter); 247int dso__load_vmlinux_path(struct dso *dso, struct map *map);
247int dso__load_vmlinux_path(struct dso *dso, struct map *map,
248 symbol_filter_t filter);
249int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 248int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
250 bool no_kcore, symbol_filter_t filter); 249 bool no_kcore);
251int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 250int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map);
252 symbol_filter_t filter);
253 251
254void dso__insert_symbol(struct dso *dso, enum map_type type, 252void dso__insert_symbol(struct dso *dso, enum map_type type,
255 struct symbol *sym); 253 struct symbol *sym);
@@ -261,6 +259,7 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
261struct symbol *symbol__next_by_name(struct symbol *sym); 259struct symbol *symbol__next_by_name(struct symbol *sym);
262 260
263struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); 261struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
262struct symbol *dso__last_symbol(struct dso *dso, enum map_type type);
264struct symbol *dso__next_symbol(struct symbol *sym); 263struct symbol *dso__next_symbol(struct symbol *sym);
265 264
266enum dso_type dso__type_fd(int fd); 265enum dso_type dso__type_fd(int fd);
@@ -277,6 +276,8 @@ struct perf_env;
277int symbol__init(struct perf_env *env); 276int symbol__init(struct perf_env *env);
278void symbol__exit(void); 277void symbol__exit(void);
279void symbol__elf_init(void); 278void symbol__elf_init(void);
279int symbol__annotation_init(void);
280
280struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 281struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
281size_t __symbol__fprintf_symname_offs(const struct symbol *sym, 282size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
282 const struct addr_location *al, 283 const struct addr_location *al,
@@ -291,16 +292,15 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp);
291bool symbol_type__is_a(char symbol_type, enum map_type map_type); 292bool symbol_type__is_a(char symbol_type, enum map_type map_type);
292bool symbol__restricted_filename(const char *filename, 293bool symbol__restricted_filename(const char *filename,
293 const char *restricted_filename); 294 const char *restricted_filename);
294bool symbol__is_idle(struct symbol *sym);
295int symbol__config_symfs(const struct option *opt __maybe_unused, 295int symbol__config_symfs(const struct option *opt __maybe_unused,
296 const char *dir, int unset __maybe_unused); 296 const char *dir, int unset __maybe_unused);
297 297
298int 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,
299 struct symsrc *runtime_ss, symbol_filter_t filter, 299 struct symsrc *runtime_ss, int kmodule);
300 int kmodule);
301int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, 300int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
302 struct map *map, symbol_filter_t filter); 301 struct map *map);
303 302
303void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
304void symbols__insert(struct rb_root *symbols, struct symbol *sym); 304void symbols__insert(struct rb_root *symbols, struct symbol *sym);
305void symbols__fixup_duplicate(struct rb_root *symbols); 305void symbols__fixup_duplicate(struct rb_root *symbols);
306void symbols__fixup_end(struct rb_root *symbols); 306void symbols__fixup_end(struct rb_root *symbols);
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index cee559d8c9e8..85c56800f17a 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -15,6 +15,7 @@
15#include <byteswap.h> 15#include <byteswap.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/log2.h> 17#include <linux/log2.h>
18#include <linux/time64.h>
18#include <unistd.h> 19#include <unistd.h>
19#include "callchain.h" 20#include "callchain.h"
20#include "strlist.h" 21#include "strlist.h"
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index e5f55477491d..43899e0d6fa1 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -179,10 +179,6 @@ static inline void *zalloc(size_t size)
179#undef tolower 179#undef tolower
180#undef toupper 180#undef toupper
181 181
182#ifndef NSEC_PER_MSEC
183#define NSEC_PER_MSEC 1000000L
184#endif
185
186int parse_nsec_time(const char *str, u64 *ptime); 182int parse_nsec_time(const char *str, u64 *ptime);
187 183
188extern unsigned char sane_ctype[256]; 184extern unsigned char sane_ctype[256];
diff --git a/tools/power/acpi/common/cmfsize.c b/tools/power/acpi/common/cmfsize.c
index e73a79fce015..bc82596d7354 100644
--- a/tools/power/acpi/common/cmfsize.c
+++ b/tools/power/acpi/common/cmfsize.c
@@ -44,7 +44,6 @@
44#include <acpi/acpi.h> 44#include <acpi/acpi.h>
45#include "accommon.h" 45#include "accommon.h"
46#include "acapps.h" 46#include "acapps.h"
47#include <stdio.h>
48 47
49#define _COMPONENT ACPI_TOOLS 48#define _COMPONENT ACPI_TOOLS
50ACPI_MODULE_NAME("cmfsize") 49ACPI_MODULE_NAME("cmfsize")
@@ -69,24 +68,24 @@ u32 cm_get_file_size(ACPI_FILE file)
69 68
70 /* Save the current file pointer, seek to EOF to obtain file size */ 69 /* Save the current file pointer, seek to EOF to obtain file size */
71 70
72 current_offset = acpi_os_get_file_offset(file); 71 current_offset = ftell(file);
73 if (current_offset < 0) { 72 if (current_offset < 0) {
74 goto offset_error; 73 goto offset_error;
75 } 74 }
76 75
77 status = acpi_os_set_file_offset(file, 0, ACPI_FILE_END); 76 status = fseek(file, 0, SEEK_END);
78 if (ACPI_FAILURE(status)) { 77 if (ACPI_FAILURE(status)) {
79 goto seek_error; 78 goto seek_error;
80 } 79 }
81 80
82 file_size = acpi_os_get_file_offset(file); 81 file_size = ftell(file);
83 if (file_size < 0) { 82 if (file_size < 0) {
84 goto offset_error; 83 goto offset_error;
85 } 84 }
86 85
87 /* Restore original file pointer */ 86 /* Restore original file pointer */
88 87
89 status = acpi_os_set_file_offset(file, current_offset, ACPI_FILE_BEGIN); 88 status = fseek(file, current_offset, SEEK_SET);
90 if (ACPI_FAILURE(status)) { 89 if (ACPI_FAILURE(status)) {
91 goto seek_error; 90 goto seek_error;
92 } 91 }
@@ -94,10 +93,10 @@ u32 cm_get_file_size(ACPI_FILE file)
94 return ((u32)file_size); 93 return ((u32)file_size);
95 94
96offset_error: 95offset_error:
97 acpi_log_error("Could not get file offset"); 96 fprintf(stderr, "Could not get file offset\n");
98 return (ACPI_UINT32_MAX); 97 return (ACPI_UINT32_MAX);
99 98
100seek_error: 99seek_error:
101 acpi_log_error("Could not set file offset"); 100 fprintf(stderr, "Could not set file offset\n");
102 return (ACPI_UINT32_MAX); 101 return (ACPI_UINT32_MAX);
103} 102}
diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c
index 0bd343f136a4..3919970f5aea 100644
--- a/tools/power/acpi/common/getopt.c
+++ b/tools/power/acpi/common/getopt.c
@@ -57,7 +57,7 @@
57#include "acapps.h" 57#include "acapps.h"
58 58
59#define ACPI_OPTION_ERROR(msg, badchar) \ 59#define ACPI_OPTION_ERROR(msg, badchar) \
60 if (acpi_gbl_opterr) {acpi_log_error ("%s%c\n", msg, badchar);} 60 if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);}
61 61
62int acpi_gbl_opterr = 1; 62int acpi_gbl_opterr = 1;
63int acpi_gbl_optind = 1; 63int acpi_gbl_optind = 1;
@@ -94,7 +94,7 @@ int acpi_getopt_argument(int argc, char **argv)
94 acpi_gbl_optarg = 94 acpi_gbl_optarg =
95 &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)]; 95 &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)];
96 } else if (++acpi_gbl_optind >= argc) { 96 } else if (++acpi_gbl_optind >= argc) {
97 ACPI_OPTION_ERROR("Option requires an argument: -", 'v'); 97 ACPI_OPTION_ERROR("\nOption requires an argument", 0);
98 98
99 current_char_ptr = 1; 99 current_char_ptr = 1;
100 return (-1); 100 return (-1);
diff --git a/tools/power/acpi/os_specific/service_layers/oslibcfs.c b/tools/power/acpi/os_specific/service_layers/oslibcfs.c
deleted file mode 100644
index 11f4aba55aab..000000000000
--- a/tools/power/acpi/os_specific/service_layers/oslibcfs.c
+++ /dev/null
@@ -1,217 +0,0 @@
1/******************************************************************************
2 *
3 * Module Name: oslibcfs - C library OSL for file I/O
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include <stdio.h>
46#include <stdarg.h>
47
48#define _COMPONENT ACPI_OS_SERVICES
49ACPI_MODULE_NAME("oslibcfs")
50
51/*******************************************************************************
52 *
53 * FUNCTION: acpi_os_open_file
54 *
55 * PARAMETERS: path - File path
56 * modes - File operation type
57 *
58 * RETURN: File descriptor.
59 *
60 * DESCRIPTION: Open a file for reading (ACPI_FILE_READING) or/and writing
61 * (ACPI_FILE_WRITING).
62 *
63 ******************************************************************************/
64ACPI_FILE acpi_os_open_file(const char *path, u8 modes)
65{
66 ACPI_FILE file;
67 u32 i = 0;
68 char modes_str[4];
69
70 if (modes & ACPI_FILE_READING) {
71 modes_str[i++] = 'r';
72 }
73 if (modes & ACPI_FILE_WRITING) {
74 modes_str[i++] = 'w';
75 }
76
77 if (modes & ACPI_FILE_BINARY) {
78 modes_str[i++] = 'b';
79 }
80
81 modes_str[i++] = '\0';
82
83 file = fopen(path, modes_str);
84 if (!file) {
85 perror("Could not open file");
86 }
87
88 return (file);
89}
90
91/*******************************************************************************
92 *
93 * FUNCTION: acpi_os_close_file
94 *
95 * PARAMETERS: file - An open file descriptor
96 *
97 * RETURN: None.
98 *
99 * DESCRIPTION: Close a file opened via acpi_os_open_file.
100 *
101 ******************************************************************************/
102
103void acpi_os_close_file(ACPI_FILE file)
104{
105
106 fclose(file);
107}
108
109/*******************************************************************************
110 *
111 * FUNCTION: acpi_os_read_file
112 *
113 * PARAMETERS: file - An open file descriptor
114 * buffer - Data buffer
115 * size - Data block size
116 * count - Number of data blocks
117 *
118 * RETURN: Number of bytes actually read.
119 *
120 * DESCRIPTION: Read from a file.
121 *
122 ******************************************************************************/
123
124int
125acpi_os_read_file(ACPI_FILE file, void *buffer, acpi_size size, acpi_size count)
126{
127 int length;
128
129 length = fread(buffer, size, count, file);
130 if (length < 0) {
131 perror("Error reading file");
132 }
133
134 return (length);
135}
136
137/*******************************************************************************
138 *
139 * FUNCTION: acpi_os_write_file
140 *
141 * PARAMETERS: file - An open file descriptor
142 * buffer - Data buffer
143 * size - Data block size
144 * count - Number of data blocks
145 *
146 * RETURN: Number of bytes actually written.
147 *
148 * DESCRIPTION: Write to a file.
149 *
150 ******************************************************************************/
151
152int
153acpi_os_write_file(ACPI_FILE file,
154 void *buffer, acpi_size size, acpi_size count)
155{
156 int length;
157
158 length = fwrite(buffer, size, count, file);
159 if (length < 0) {
160 perror("Error writing file");
161 }
162
163 return (length);
164}
165
166/*******************************************************************************
167 *
168 * FUNCTION: acpi_os_get_file_offset
169 *
170 * PARAMETERS: file - An open file descriptor
171 *
172 * RETURN: Current file pointer position.
173 *
174 * DESCRIPTION: Get current file offset.
175 *
176 ******************************************************************************/
177
178long acpi_os_get_file_offset(ACPI_FILE file)
179{
180 long offset;
181
182 offset = ftell(file);
183 return (offset);
184}
185
186/*******************************************************************************
187 *
188 * FUNCTION: acpi_os_set_file_offset
189 *
190 * PARAMETERS: file - An open file descriptor
191 * offset - New file offset
192 * from - From begin/end of file
193 *
194 * RETURN: Status
195 *
196 * DESCRIPTION: Set current file offset.
197 *
198 ******************************************************************************/
199
200acpi_status acpi_os_set_file_offset(ACPI_FILE file, long offset, u8 from)
201{
202 int ret = 0;
203
204 if (from == ACPI_FILE_BEGIN) {
205 ret = fseek(file, offset, SEEK_SET);
206 }
207
208 if (from == ACPI_FILE_END) {
209 ret = fseek(file, offset, SEEK_END);
210 }
211
212 if (ret < 0) {
213 return (AE_ERROR);
214 } else {
215 return (AE_OK);
216 }
217}
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index 88aa66ef4ad5..8d8003c919d4 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -63,10 +63,7 @@
63#define _COMPONENT ACPI_OS_SERVICES 63#define _COMPONENT ACPI_OS_SERVICES
64ACPI_MODULE_NAME("osunixxf") 64ACPI_MODULE_NAME("osunixxf")
65 65
66u8 acpi_gbl_debug_timeout = FALSE;
67
68/* Upcalls to acpi_exec */ 66/* Upcalls to acpi_exec */
69
70void 67void
71ae_table_override(struct acpi_table_header *existing_table, 68ae_table_override(struct acpi_table_header *existing_table,
72 struct acpi_table_header **new_table); 69 struct acpi_table_header **new_table);
diff --git a/tools/power/acpi/tools/acpidump/Makefile b/tools/power/acpi/tools/acpidump/Makefile
index 2942cdced2ad..04b5db7c7c0b 100644
--- a/tools/power/acpi/tools/acpidump/Makefile
+++ b/tools/power/acpi/tools/acpidump/Makefile
@@ -36,12 +36,13 @@ TOOL_OBJS = \
36 utdebug.o\ 36 utdebug.o\
37 utexcep.o\ 37 utexcep.o\
38 utglobal.o\ 38 utglobal.o\
39 uthex.o\
39 utmath.o\ 40 utmath.o\
40 utnonansi.o\ 41 utnonansi.o\
41 utprint.o\ 42 utprint.o\
42 utstring.o\ 43 utstring.o\
44 utstrtoul64.o\
43 utxferror.o\ 45 utxferror.o\
44 oslibcfs.o\
45 oslinuxtbl.o\ 46 oslinuxtbl.o\
46 cmfsize.o\ 47 cmfsize.o\
47 getopt.o 48 getopt.o
diff --git a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h
index 025c232e920d..00423fc45e7c 100644
--- a/tools/power/acpi/tools/acpidump/acpidump.h
+++ b/tools/power/acpi/tools/acpidump/acpidump.h
@@ -55,11 +55,7 @@
55#include <acpi/acpi.h> 55#include <acpi/acpi.h>
56#include "accommon.h" 56#include "accommon.h"
57#include "actables.h" 57#include "actables.h"
58 58#include "acapps.h"
59#include <stdio.h>
60#include <fcntl.h>
61#include <errno.h>
62#include <sys/stat.h>
63 59
64/* Globals */ 60/* Globals */
65 61
@@ -72,12 +68,6 @@ EXTERN ACPI_FILE INIT_GLOBAL(gbl_output_file, NULL);
72EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL); 68EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL);
73EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0); 69EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0);
74 70
75/* Globals required for use with ACPICA modules */
76
77#ifdef _DECLARE_GLOBALS
78u8 acpi_gbl_integer_byte_width = 8;
79#endif
80
81/* Action table used to defer requested options */ 71/* Action table used to defer requested options */
82 72
83struct ap_dump_action { 73struct ap_dump_action {
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c
index fb8f1d9e3b1b..9031be1afe63 100644
--- a/tools/power/acpi/tools/acpidump/apdump.c
+++ b/tools/power/acpi/tools/acpidump/apdump.c
@@ -69,16 +69,17 @@ u8 ap_is_valid_header(struct acpi_table_header *table)
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_nameseg(table->signature)) { 71 if (!acpi_ut_valid_nameseg(table->signature)) {
72 acpi_log_error("Table signature (0x%8.8X) is invalid\n", 72 fprintf(stderr,
73 *(u32 *)table->signature); 73 "Table signature (0x%8.8X) is invalid\n",
74 *(u32 *)table->signature);
74 return (FALSE); 75 return (FALSE);
75 } 76 }
76 77
77 /* Check for minimum table length */ 78 /* Check for minimum table length */
78 79
79 if (table->length < sizeof(struct acpi_table_header)) { 80 if (table->length < sizeof(struct acpi_table_header)) {
80 acpi_log_error("Table length (0x%8.8X) is invalid\n", 81 fprintf(stderr, "Table length (0x%8.8X) is invalid\n",
81 table->length); 82 table->length);
82 return (FALSE); 83 return (FALSE);
83 } 84 }
84 } 85 }
@@ -115,8 +116,8 @@ u8 ap_is_valid_checksum(struct acpi_table_header *table)
115 } 116 }
116 117
117 if (ACPI_FAILURE(status)) { 118 if (ACPI_FAILURE(status)) {
118 acpi_log_error("%4.4s: Warning: wrong checksum in table\n", 119 fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n",
119 table->signature); 120 table->signature);
120 } 121 }
121 122
122 return (AE_OK); 123 return (AE_OK);
@@ -195,13 +196,13 @@ ap_dump_table_buffer(struct acpi_table_header *table,
195 * Note: simplest to just always emit a 64-bit address. acpi_xtract 196 * Note: simplest to just always emit a 64-bit address. acpi_xtract
196 * utility can handle this. 197 * utility can handle this.
197 */ 198 */
198 acpi_ut_file_printf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n", 199 fprintf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n",
199 table->signature, ACPI_FORMAT_UINT64(address)); 200 table->signature, ACPI_FORMAT_UINT64(address));
200 201
201 acpi_ut_dump_buffer_to_file(gbl_output_file, 202 acpi_ut_dump_buffer_to_file(gbl_output_file,
202 ACPI_CAST_PTR(u8, table), table_length, 203 ACPI_CAST_PTR(u8, table), table_length,
203 DB_BYTE_DISPLAY, 0); 204 DB_BYTE_DISPLAY, 0);
204 acpi_ut_file_printf(gbl_output_file, "\n"); 205 fprintf(gbl_output_file, "\n");
205 return (0); 206 return (0);
206} 207}
207 208
@@ -239,14 +240,14 @@ int ap_dump_all_tables(void)
239 if (status == AE_LIMIT) { 240 if (status == AE_LIMIT) {
240 return (0); 241 return (0);
241 } else if (i == 0) { 242 } else if (i == 0) {
242 acpi_log_error 243 fprintf(stderr,
243 ("Could not get ACPI tables, %s\n", 244 "Could not get ACPI tables, %s\n",
244 acpi_format_exception(status)); 245 acpi_format_exception(status));
245 return (-1); 246 return (-1);
246 } else { 247 } else {
247 acpi_log_error 248 fprintf(stderr,
248 ("Could not get ACPI table at index %u, %s\n", 249 "Could not get ACPI table at index %u, %s\n",
249 i, acpi_format_exception(status)); 250 i, acpi_format_exception(status));
250 continue; 251 continue;
251 } 252 }
252 } 253 }
@@ -286,20 +287,20 @@ int ap_dump_table_by_address(char *ascii_address)
286 287
287 /* Convert argument to an integer physical address */ 288 /* Convert argument to an integer physical address */
288 289
289 status = acpi_ut_strtoul64(ascii_address, ACPI_ANY_BASE, 290 status = acpi_ut_strtoul64(ascii_address, ACPI_STRTOUL_64BIT,
290 ACPI_MAX64_BYTE_WIDTH, &long_address); 291 &long_address);
291 if (ACPI_FAILURE(status)) { 292 if (ACPI_FAILURE(status)) {
292 acpi_log_error("%s: Could not convert to a physical address\n", 293 fprintf(stderr, "%s: Could not convert to a physical address\n",
293 ascii_address); 294 ascii_address);
294 return (-1); 295 return (-1);
295 } 296 }
296 297
297 address = (acpi_physical_address)long_address; 298 address = (acpi_physical_address)long_address;
298 status = acpi_os_get_table_by_address(address, &table); 299 status = acpi_os_get_table_by_address(address, &table);
299 if (ACPI_FAILURE(status)) { 300 if (ACPI_FAILURE(status)) {
300 acpi_log_error("Could not get table at 0x%8.8X%8.8X, %s\n", 301 fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n",
301 ACPI_FORMAT_UINT64(address), 302 ACPI_FORMAT_UINT64(address),
302 acpi_format_exception(status)); 303 acpi_format_exception(status));
303 return (-1); 304 return (-1);
304 } 305 }
305 306
@@ -331,9 +332,9 @@ int ap_dump_table_by_name(char *signature)
331 int table_status; 332 int table_status;
332 333
333 if (strlen(signature) != ACPI_NAME_SIZE) { 334 if (strlen(signature) != ACPI_NAME_SIZE) {
334 acpi_log_error 335 fprintf(stderr,
335 ("Invalid table signature [%s]: must be exactly 4 characters\n", 336 "Invalid table signature [%s]: must be exactly 4 characters\n",
336 signature); 337 signature);
337 return (-1); 338 return (-1);
338 } 339 }
339 340
@@ -363,9 +364,9 @@ int ap_dump_table_by_name(char *signature)
363 return (0); 364 return (0);
364 } 365 }
365 366
366 acpi_log_error 367 fprintf(stderr,
367 ("Could not get ACPI table with signature [%s], %s\n", 368 "Could not get ACPI table with signature [%s], %s\n",
368 local_signature, acpi_format_exception(status)); 369 local_signature, acpi_format_exception(status));
369 return (-1); 370 return (-1);
370 } 371 }
371 372
@@ -408,24 +409,24 @@ int ap_dump_table_from_file(char *pathname)
408 } 409 }
409 410
410 if (!acpi_ut_valid_nameseg(table->signature)) { 411 if (!acpi_ut_valid_nameseg(table->signature)) {
411 acpi_log_error 412 fprintf(stderr,
412 ("No valid ACPI signature was found in input file %s\n", 413 "No valid ACPI signature was found in input file %s\n",
413 pathname); 414 pathname);
414 } 415 }
415 416
416 /* File must be at least as long as the table length */ 417 /* File must be at least as long as the table length */
417 418
418 if (table->length > file_size) { 419 if (table->length > file_size) {
419 acpi_log_error 420 fprintf(stderr,
420 ("Table length (0x%X) is too large for input file (0x%X) %s\n", 421 "Table length (0x%X) is too large for input file (0x%X) %s\n",
421 table->length, file_size, pathname); 422 table->length, file_size, pathname);
422 goto exit; 423 goto exit;
423 } 424 }
424 425
425 if (gbl_verbose_mode) { 426 if (gbl_verbose_mode) {
426 acpi_log_error 427 fprintf(stderr,
427 ("Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n", 428 "Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n",
428 pathname, table->signature, file_size, file_size); 429 pathname, table->signature, file_size, file_size);
429 } 430 }
430 431
431 table_status = ap_dump_table_buffer(table, 0, 0); 432 table_status = ap_dump_table_buffer(table, 0, 0);
diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c
index 5fcd9700ac18..dd5b861dc4a8 100644
--- a/tools/power/acpi/tools/acpidump/apfiles.c
+++ b/tools/power/acpi/tools/acpidump/apfiles.c
@@ -42,7 +42,6 @@
42 */ 42 */
43 43
44#include "acpidump.h" 44#include "acpidump.h"
45#include "acapps.h"
46 45
47/* Local prototypes */ 46/* Local prototypes */
48 47
@@ -66,7 +65,8 @@ static int ap_is_existing_file(char *pathname)
66 struct stat stat_info; 65 struct stat stat_info;
67 66
68 if (!stat(pathname, &stat_info)) { 67 if (!stat(pathname, &stat_info)) {
69 acpi_log_error("Target path already exists, overwrite? [y|n] "); 68 fprintf(stderr,
69 "Target path already exists, overwrite? [y|n] ");
70 70
71 if (getchar() != 'y') { 71 if (getchar() != 'y') {
72 return (-1); 72 return (-1);
@@ -102,9 +102,9 @@ int ap_open_output_file(char *pathname)
102 102
103 /* Point stdout to the file */ 103 /* Point stdout to the file */
104 104
105 file = acpi_os_open_file(pathname, ACPI_FILE_WRITING); 105 file = fopen(pathname, "w");
106 if (!file) { 106 if (!file) {
107 acpi_log_error("Could not open output file: %s\n", pathname); 107 fprintf(stderr, "Could not open output file: %s\n", pathname);
108 return (-1); 108 return (-1);
109 } 109 }
110 110
@@ -134,7 +134,7 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
134 char filename[ACPI_NAME_SIZE + 16]; 134 char filename[ACPI_NAME_SIZE + 16];
135 char instance_str[16]; 135 char instance_str[16];
136 ACPI_FILE file; 136 ACPI_FILE file;
137 size_t actual; 137 acpi_size actual;
138 u32 table_length; 138 u32 table_length;
139 139
140 /* Obtain table length */ 140 /* Obtain table length */
@@ -158,37 +158,36 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
158 /* Handle multiple SSDts - create different filenames for each */ 158 /* Handle multiple SSDts - create different filenames for each */
159 159
160 if (instance > 0) { 160 if (instance > 0) {
161 acpi_ut_snprintf(instance_str, sizeof(instance_str), "%u", 161 snprintf(instance_str, sizeof(instance_str), "%u", instance);
162 instance);
163 strcat(filename, instance_str); 162 strcat(filename, instance_str);
164 } 163 }
165 164
166 strcat(filename, FILE_SUFFIX_BINARY_TABLE); 165 strcat(filename, FILE_SUFFIX_BINARY_TABLE);
167 166
168 if (gbl_verbose_mode) { 167 if (gbl_verbose_mode) {
169 acpi_log_error 168 fprintf(stderr,
170 ("Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", 169 "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n",
171 table->signature, filename, table->length, table->length); 170 table->signature, filename, table->length,
171 table->length);
172 } 172 }
173 173
174 /* Open the file and dump the entire table in binary mode */ 174 /* Open the file and dump the entire table in binary mode */
175 175
176 file = acpi_os_open_file(filename, 176 file = fopen(filename, "wb");
177 ACPI_FILE_WRITING | ACPI_FILE_BINARY);
178 if (!file) { 177 if (!file) {
179 acpi_log_error("Could not open output file: %s\n", filename); 178 fprintf(stderr, "Could not open output file: %s\n", filename);
180 return (-1); 179 return (-1);
181 } 180 }
182 181
183 actual = acpi_os_write_file(file, table, 1, table_length); 182 actual = fwrite(table, 1, table_length, file);
184 if (actual != table_length) { 183 if (actual != table_length) {
185 acpi_log_error("Error writing binary output file: %s\n", 184 fprintf(stderr, "Error writing binary output file: %s\n",
186 filename); 185 filename);
187 acpi_os_close_file(file); 186 fclose(file);
188 return (-1); 187 return (-1);
189 } 188 }
190 189
191 acpi_os_close_file(file); 190 fclose(file);
192 return (0); 191 return (0);
193} 192}
194 193
@@ -211,14 +210,13 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname,
211 struct acpi_table_header *buffer = NULL; 210 struct acpi_table_header *buffer = NULL;
212 ACPI_FILE file; 211 ACPI_FILE file;
213 u32 file_size; 212 u32 file_size;
214 size_t actual; 213 acpi_size actual;
215 214
216 /* Must use binary mode */ 215 /* Must use binary mode */
217 216
218 file = 217 file = fopen(pathname, "rb");
219 acpi_os_open_file(pathname, ACPI_FILE_READING | ACPI_FILE_BINARY);
220 if (!file) { 218 if (!file) {
221 acpi_log_error("Could not open input file: %s\n", pathname); 219 fprintf(stderr, "Could not open input file: %s\n", pathname);
222 return (NULL); 220 return (NULL);
223 } 221 }
224 222
@@ -226,7 +224,8 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname,
226 224
227 file_size = cm_get_file_size(file); 225 file_size = cm_get_file_size(file);
228 if (file_size == ACPI_UINT32_MAX) { 226 if (file_size == ACPI_UINT32_MAX) {
229 acpi_log_error("Could not get input file size: %s\n", pathname); 227 fprintf(stderr,
228 "Could not get input file size: %s\n", pathname);
230 goto cleanup; 229 goto cleanup;
231 } 230 }
232 231
@@ -234,16 +233,17 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname,
234 233
235 buffer = ACPI_ALLOCATE_ZEROED(file_size); 234 buffer = ACPI_ALLOCATE_ZEROED(file_size);
236 if (!buffer) { 235 if (!buffer) {
237 acpi_log_error("Could not allocate file buffer of size: %u\n", 236 fprintf(stderr,
238 file_size); 237 "Could not allocate file buffer of size: %u\n",
238 file_size);
239 goto cleanup; 239 goto cleanup;
240 } 240 }
241 241
242 /* Read the entire file */ 242 /* Read the entire file */
243 243
244 actual = acpi_os_read_file(file, buffer, 1, file_size); 244 actual = fread(buffer, 1, file_size, file);
245 if (actual != file_size) { 245 if (actual != file_size) {
246 acpi_log_error("Could not read input file: %s\n", pathname); 246 fprintf(stderr, "Could not read input file: %s\n", pathname);
247 ACPI_FREE(buffer); 247 ACPI_FREE(buffer);
248 buffer = NULL; 248 buffer = NULL;
249 goto cleanup; 249 goto cleanup;
@@ -252,6 +252,6 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname,
252 *out_file_size = file_size; 252 *out_file_size = file_size;
253 253
254cleanup: 254cleanup:
255 acpi_os_close_file(file); 255 fclose(file);
256 return (buffer); 256 return (buffer);
257} 257}
diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c
index 7692e6b887e1..7ff46be908f0 100644
--- a/tools/power/acpi/tools/acpidump/apmain.c
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -43,7 +43,6 @@
43 43
44#define _DECLARE_GLOBALS 44#define _DECLARE_GLOBALS
45#include "acpidump.h" 45#include "acpidump.h"
46#include "acapps.h"
47 46
48/* 47/*
49 * acpidump - A portable utility for obtaining system ACPI tables and dumping 48 * acpidump - A portable utility for obtaining system ACPI tables and dumping
@@ -140,8 +139,8 @@ static int ap_insert_action(char *argument, u32 to_be_done)
140 139
141 current_action++; 140 current_action++;
142 if (current_action > AP_MAX_ACTIONS) { 141 if (current_action > AP_MAX_ACTIONS) {
143 acpi_log_error("Too many table options (max %u)\n", 142 fprintf(stderr, "Too many table options (max %u)\n",
144 AP_MAX_ACTIONS); 143 AP_MAX_ACTIONS);
145 return (-1); 144 return (-1);
146 } 145 }
147 146
@@ -186,9 +185,9 @@ static int ap_do_options(int argc, char **argv)
186 } else if (!strcmp(acpi_gbl_optarg, "off")) { 185 } else if (!strcmp(acpi_gbl_optarg, "off")) {
187 gbl_dump_customized_tables = FALSE; 186 gbl_dump_customized_tables = FALSE;
188 } else { 187 } else {
189 acpi_log_error 188 fprintf(stderr,
190 ("%s: Cannot handle this switch, please use on|off\n", 189 "%s: Cannot handle this switch, please use on|off\n",
191 acpi_gbl_optarg); 190 acpi_gbl_optarg);
192 return (-1); 191 return (-1);
193 } 192 }
194 continue; 193 continue;
@@ -209,13 +208,13 @@ static int ap_do_options(int argc, char **argv)
209 case 'r': /* Dump tables from specified RSDP */ 208 case 'r': /* Dump tables from specified RSDP */
210 209
211 status = 210 status =
212 acpi_ut_strtoul64(acpi_gbl_optarg, ACPI_ANY_BASE, 211 acpi_ut_strtoul64(acpi_gbl_optarg,
213 ACPI_MAX64_BYTE_WIDTH, 212 ACPI_STRTOUL_64BIT,
214 &gbl_rsdp_base); 213 &gbl_rsdp_base);
215 if (ACPI_FAILURE(status)) { 214 if (ACPI_FAILURE(status)) {
216 acpi_log_error 215 fprintf(stderr,
217 ("%s: Could not convert to a physical address\n", 216 "%s: Could not convert to a physical address\n",
218 acpi_gbl_optarg); 217 acpi_gbl_optarg);
219 return (-1); 218 return (-1);
220 } 219 }
221 continue; 220 continue;
@@ -242,7 +241,7 @@ static int ap_do_options(int argc, char **argv)
242 case 'z': /* Verbose mode */ 241 case 'z': /* Verbose mode */
243 242
244 gbl_verbose_mode = TRUE; 243 gbl_verbose_mode = TRUE;
245 acpi_log_error(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); 244 fprintf(stderr, ACPI_COMMON_SIGNON(AP_UTILITY_NAME));
246 continue; 245 continue;
247 246
248 /* 247 /*
@@ -315,6 +314,7 @@ int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
315 ACPI_DEBUG_INITIALIZE(); /* For debug version only */ 314 ACPI_DEBUG_INITIALIZE(); /* For debug version only */
316 acpi_os_initialize(); 315 acpi_os_initialize();
317 gbl_output_file = ACPI_FILE_OUT; 316 gbl_output_file = ACPI_FILE_OUT;
317 acpi_gbl_integer_byte_width = 8;
318 318
319 /* Process command line options */ 319 /* Process command line options */
320 320
@@ -353,8 +353,9 @@ int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
353 353
354 default: 354 default:
355 355
356 acpi_log_error("Internal error, invalid action: 0x%X\n", 356 fprintf(stderr,
357 action->to_be_done); 357 "Internal error, invalid action: 0x%X\n",
358 action->to_be_done);
358 return (-1); 359 return (-1);
359 } 360 }
360 361
@@ -369,12 +370,12 @@ int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
369 /* Summary for the output file */ 370 /* Summary for the output file */
370 371
371 file_size = cm_get_file_size(gbl_output_file); 372 file_size = cm_get_file_size(gbl_output_file);
372 acpi_log_error 373 fprintf(stderr,
373 ("Output file %s contains 0x%X (%u) bytes\n\n", 374 "Output file %s contains 0x%X (%u) bytes\n\n",
374 gbl_output_filename, file_size, file_size); 375 gbl_output_filename, file_size, file_size);
375 } 376 }
376 377
377 acpi_os_close_file(gbl_output_file); 378 fclose(gbl_output_file);
378 } 379 }
379 380
380 return (status); 381 return (status);
diff --git a/tools/spi/Makefile b/tools/spi/Makefile
index cd0db62e4d9d..3815b18ba070 100644
--- a/tools/spi/Makefile
+++ b/tools/spi/Makefile
@@ -1,3 +1,5 @@
1CC = $(CROSS_COMPILE)gcc
2
1all: spidev_test spidev_fdx 3all: spidev_test spidev_fdx
2 4
3clean: 5clean:
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index 8a73d8185316..f046b77cfefe 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -19,6 +19,7 @@
19#include <getopt.h> 19#include <getopt.h>
20#include <fcntl.h> 20#include <fcntl.h>
21#include <sys/ioctl.h> 21#include <sys/ioctl.h>
22#include <linux/ioctl.h>
22#include <sys/stat.h> 23#include <sys/stat.h>
23#include <linux/types.h> 24#include <linux/types.h>
24#include <linux/spi/spidev.h> 25#include <linux/spi/spidev.h>
@@ -284,7 +285,7 @@ static void parse_opts(int argc, char *argv[])
284 285
285static void transfer_escaped_string(int fd, char *str) 286static void transfer_escaped_string(int fd, char *str)
286{ 287{
287 size_t size = strlen(str + 1); 288 size_t size = strlen(str);
288 uint8_t *tx; 289 uint8_t *tx;
289 uint8_t *rx; 290 uint8_t *rx;
290 291
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index dd48f421844c..f64c57bf1d4b 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -603,7 +603,8 @@ static int nfit_test0_alloc(struct nfit_test *t)
603 return -ENOMEM; 603 return -ENOMEM;
604 sprintf(t->label[i], "label%d", i); 604 sprintf(t->label[i], "label%d", i);
605 605
606 t->flush[i] = test_alloc(t, sizeof(u64) * NUM_HINTS, 606 t->flush[i] = test_alloc(t, max(PAGE_SIZE,
607 sizeof(u64) * NUM_HINTS),
607 &t->flush_dma[i]); 608 &t->flush_dma[i]);
608 if (!t->flush[i]) 609 if (!t->flush[i])
609 return -ENOMEM; 610 return -ENOMEM;
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index 3b530467148e..9d0919ed52a4 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -1,5 +1,5 @@
1 1
2CFLAGS += -I. -g -Wall -D_LGPL_SOURCE 2CFLAGS += -I. -g -O2 -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 \
diff --git a/tools/testing/radix-tree/linux/cpu.h b/tools/testing/radix-tree/linux/cpu.h
index 60a40459f269..7cf412103205 100644
--- a/tools/testing/radix-tree/linux/cpu.h
+++ b/tools/testing/radix-tree/linux/cpu.h
@@ -7,19 +7,8 @@
7#define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */ 7#define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */
8#define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */ 8#define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */
9#define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */ 9#define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */
10#define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task,
11 * not handling interrupts, soon dead.
12 * Called on the dying cpu, interrupts
13 * are already disabled. Must not
14 * sleep, must not fail */
15#define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug 10#define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug
16 * lock is dropped */ 11 * lock is dropped */
17#define CPU_STARTING 0x000A /* CPU (unsigned)v soon running.
18 * Called on the new cpu, just before
19 * enabling interrupts. Must not sleep,
20 * must not fail */
21#define CPU_DYING_IDLE 0x000B /* CPU (unsigned)v dying, reached
22 * idle loop. */
23#define CPU_BROKEN 0x000C /* CPU (unsigned)v did not die properly, 12#define CPU_BROKEN 0x000C /* CPU (unsigned)v did not die properly,
24 * perhaps due to preemption. */ 13 * perhaps due to preemption. */
25#define CPU_TASKS_FROZEN 0x0010 14#define CPU_TASKS_FROZEN 0x0010
@@ -30,5 +19,3 @@
30#define CPU_DOWN_PREPARE_FROZEN (CPU_DOWN_PREPARE | CPU_TASKS_FROZEN) 19#define CPU_DOWN_PREPARE_FROZEN (CPU_DOWN_PREPARE | CPU_TASKS_FROZEN)
31#define CPU_DOWN_FAILED_FROZEN (CPU_DOWN_FAILED | CPU_TASKS_FROZEN) 20#define CPU_DOWN_FAILED_FROZEN (CPU_DOWN_FAILED | CPU_TASKS_FROZEN)
32#define CPU_DEAD_FROZEN (CPU_DEAD | CPU_TASKS_FROZEN) 21#define CPU_DEAD_FROZEN (CPU_DEAD | CPU_TASKS_FROZEN)
33#define CPU_DYING_FROZEN (CPU_DYING | CPU_TASKS_FROZEN)
34#define CPU_STARTING_FROZEN (CPU_STARTING | CPU_TASKS_FROZEN)
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index 39d9b9568fe2..05d7bc488971 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -124,6 +124,8 @@ static void multiorder_check(unsigned long index, int order)
124 unsigned long i; 124 unsigned long i;
125 unsigned long min = index & ~((1UL << order) - 1); 125 unsigned long min = index & ~((1UL << order) - 1);
126 unsigned long max = min + (1UL << order); 126 unsigned long max = min + (1UL << order);
127 void **slot;
128 struct item *item2 = item_create(min);
127 RADIX_TREE(tree, GFP_KERNEL); 129 RADIX_TREE(tree, GFP_KERNEL);
128 130
129 printf("Multiorder index %ld, order %d\n", index, order); 131 printf("Multiorder index %ld, order %d\n", index, order);
@@ -139,13 +141,19 @@ static void multiorder_check(unsigned long index, int order)
139 item_check_absent(&tree, i); 141 item_check_absent(&tree, i);
140 for (i = max; i < 2*max; i++) 142 for (i = max; i < 2*max; i++)
141 item_check_absent(&tree, i); 143 item_check_absent(&tree, i);
144 for (i = min; i < max; i++)
145 assert(radix_tree_insert(&tree, i, item2) == -EEXIST);
146
147 slot = radix_tree_lookup_slot(&tree, index);
148 free(*slot);
149 radix_tree_replace_slot(slot, item2);
142 for (i = min; i < max; i++) { 150 for (i = min; i < max; i++) {
143 static void *entry = (void *) 151 struct item *item = item_lookup(&tree, i);
144 (0xA0 | RADIX_TREE_EXCEPTIONAL_ENTRY); 152 assert(item != 0);
145 assert(radix_tree_insert(&tree, i, entry) == -EEXIST); 153 assert(item->index == min);
146 } 154 }
147 155
148 assert(item_delete(&tree, index) != 0); 156 assert(item_delete(&tree, min) != 0);
149 157
150 for (i = 0; i < 2*max; i++) 158 for (i = 0; i < 2*max; i++)
151 item_check_absent(&tree, i); 159 item_check_absent(&tree, i);
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index ff9e5f20a5a7..f770dba2a6f6 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -15,6 +15,7 @@ TARGETS += memory-hotplug
15TARGETS += mount 15TARGETS += mount
16TARGETS += mqueue 16TARGETS += mqueue
17TARGETS += net 17TARGETS += net
18TARGETS += nsfs
18TARGETS += powerpc 19TARGETS += powerpc
19TARGETS += pstore 20TARGETS += pstore
20TARGETS += ptrace 21TARGETS += ptrace
diff --git a/tools/testing/selftests/nsfs/Makefile b/tools/testing/selftests/nsfs/Makefile
new file mode 100644
index 000000000000..2306054a901a
--- /dev/null
+++ b/tools/testing/selftests/nsfs/Makefile
@@ -0,0 +1,12 @@
1TEST_PROGS := owner pidns
2
3CFLAGS := -Wall -Werror
4
5all: owner pidns
6owner: owner.c
7pidns: pidns.c
8
9clean:
10 $(RM) owner pidns
11
12include ../lib.mk
diff --git a/tools/testing/selftests/nsfs/owner.c b/tools/testing/selftests/nsfs/owner.c
new file mode 100644
index 000000000000..437205f8b714
--- /dev/null
+++ b/tools/testing/selftests/nsfs/owner.c
@@ -0,0 +1,91 @@
1#define _GNU_SOURCE
2#include <sched.h>
3#include <unistd.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <signal.h>
7#include <errno.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <sys/ioctl.h>
12#include <sys/prctl.h>
13#include <sys/wait.h>
14
15#define NSIO 0xb7
16#define NS_GET_USERNS _IO(NSIO, 0x1)
17
18#define pr_err(fmt, ...) \
19 ({ \
20 fprintf(stderr, "%s:%d:" fmt ": %m\n", \
21 __func__, __LINE__, ##__VA_ARGS__); \
22 1; \
23 })
24
25int main(int argc, char *argvp[])
26{
27 int pfd[2], ns, uns, init_uns;
28 struct stat st1, st2;
29 char path[128];
30 pid_t pid;
31 char c;
32
33 if (pipe(pfd))
34 return 1;
35
36 pid = fork();
37 if (pid < 0)
38 return pr_err("fork");
39 if (pid == 0) {
40 prctl(PR_SET_PDEATHSIG, SIGKILL);
41 if (unshare(CLONE_NEWUTS | CLONE_NEWUSER))
42 return pr_err("unshare");
43 close(pfd[0]);
44 close(pfd[1]);
45 while (1)
46 sleep(1);
47 return 0;
48 }
49 close(pfd[1]);
50 if (read(pfd[0], &c, 1) != 0)
51 return pr_err("Unable to read from pipe");
52 close(pfd[0]);
53
54 snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid);
55 ns = open(path, O_RDONLY);
56 if (ns < 0)
57 return pr_err("Unable to open %s", path);
58
59 uns = ioctl(ns, NS_GET_USERNS);
60 if (uns < 0)
61 return pr_err("Unable to get an owning user namespace");
62
63 if (fstat(uns, &st1))
64 return pr_err("fstat");
65
66 snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
67 if (stat(path, &st2))
68 return pr_err("stat");
69
70 if (st1.st_ino != st2.st_ino)
71 return pr_err("NS_GET_USERNS returned a wrong namespace");
72
73 init_uns = ioctl(uns, NS_GET_USERNS);
74 if (uns < 0)
75 return pr_err("Unable to get an owning user namespace");
76
77 if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
78 return pr_err("Don't get EPERM");
79
80 if (unshare(CLONE_NEWUSER))
81 return pr_err("unshare");
82
83 if (ioctl(ns, NS_GET_USERNS) >= 0 || errno != EPERM)
84 return pr_err("Don't get EPERM");
85 if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
86 return pr_err("Don't get EPERM");
87
88 kill(pid, SIGKILL);
89 wait(NULL);
90 return 0;
91}
diff --git a/tools/testing/selftests/nsfs/pidns.c b/tools/testing/selftests/nsfs/pidns.c
new file mode 100644
index 000000000000..ae3a0d68e966
--- /dev/null
+++ b/tools/testing/selftests/nsfs/pidns.c
@@ -0,0 +1,78 @@
1#define _GNU_SOURCE
2#include <sched.h>
3#include <unistd.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <signal.h>
7#include <errno.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <sys/ioctl.h>
12#include <sys/prctl.h>
13#include <sys/wait.h>
14
15#define pr_err(fmt, ...) \
16 ({ \
17 fprintf(stderr, "%s:%d:" fmt ": %m\n", \
18 __func__, __LINE__, ##__VA_ARGS__); \
19 1; \
20 })
21
22#define NSIO 0xb7
23#define NS_GET_USERNS _IO(NSIO, 0x1)
24#define NS_GET_PARENT _IO(NSIO, 0x2)
25
26#define __stack_aligned__ __attribute__((aligned(16)))
27struct cr_clone_arg {
28 char stack[128] __stack_aligned__;
29 char stack_ptr[0];
30};
31
32static int child(void *args)
33{
34 prctl(PR_SET_PDEATHSIG, SIGKILL);
35 while (1)
36 sleep(1);
37 exit(0);
38}
39
40int main(int argc, char *argv[])
41{
42 char *ns_strs[] = {"pid", "user"};
43 char path[] = "/proc/0123456789/ns/pid";
44 struct cr_clone_arg ca;
45 struct stat st1, st2;
46 int ns, pns, i;
47 pid_t pid;
48
49 pid = clone(child, ca.stack_ptr, CLONE_NEWUSER | CLONE_NEWPID | SIGCHLD, NULL);
50 if (pid < 0)
51 return pr_err("clone");
52
53 for (i = 0; i < 2; i++) {
54 snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns_strs[i]);
55 ns = open(path, O_RDONLY);
56 if (ns < 0)
57 return pr_err("Unable to open %s", path);
58
59 pns = ioctl(ns, NS_GET_PARENT);
60 if (pns < 0)
61 return pr_err("Unable to get a parent pidns");
62
63 snprintf(path, sizeof(path), "/proc/self/ns/%s", ns_strs[i]);
64 if (stat(path, &st2))
65 return pr_err("Unable to stat %s", path);
66 if (fstat(pns, &st1))
67 return pr_err("Unable to stat the parent pidns");
68 if (st1.st_ino != st2.st_ino)
69 return pr_err("NS_GET_PARENT returned a wrong namespace");
70
71 if (ioctl(pns, NS_GET_PARENT) >= 0 || errno != EPERM)
72 return pr_err("Don't get EPERM");;
73 }
74
75 kill(pid, SIGKILL);
76 wait(NULL);
77 return 0;
78}
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index 1cc6d64c39b7..db54a33f850f 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -19,6 +19,7 @@ SUB_DIRS = alignment \
19 dscr \ 19 dscr \
20 mm \ 20 mm \
21 pmu \ 21 pmu \
22 signal \
22 primitives \ 23 primitives \
23 stringloops \ 24 stringloops \
24 switch_endian \ 25 switch_endian \
diff --git a/tools/testing/selftests/powerpc/fpu_asm.h b/tools/testing/selftests/powerpc/fpu_asm.h
new file mode 100644
index 000000000000..6a387d255e27
--- /dev/null
+++ b/tools/testing/selftests/powerpc/fpu_asm.h
@@ -0,0 +1,80 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
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#ifndef _SELFTESTS_POWERPC_FPU_ASM_H
11#define _SELFTESTS_POWERPC_FPU_ASM_H
12#include "basic_asm.h"
13
14#define PUSH_FPU(stack_size) \
15 stfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \
16 stfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \
17 stfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \
18 stfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \
19 stfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \
20 stfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \
21 stfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \
22 stfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \
23 stfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \
24 stfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \
25 stfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \
26 stfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \
27 stfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \
28 stfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \
29 stfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \
30 stfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \
31 stfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \
32 stfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1);
33
34#define POP_FPU(stack_size) \
35 lfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \
36 lfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \
37 lfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \
38 lfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \
39 lfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \
40 lfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \
41 lfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \
42 lfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \
43 lfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \
44 lfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \
45 lfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \
46 lfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \
47 lfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \
48 lfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \
49 lfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \
50 lfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \
51 lfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \
52 lfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1);
53
54/*
55 * Careful calling this, it will 'clobber' fpu (by design)
56 * Don't call this from C
57 */
58FUNC_START(load_fpu)
59 lfd f14,0(r3)
60 lfd f15,8(r3)
61 lfd f16,16(r3)
62 lfd f17,24(r3)
63 lfd f18,32(r3)
64 lfd f19,40(r3)
65 lfd f20,48(r3)
66 lfd f21,56(r3)
67 lfd f22,64(r3)
68 lfd f23,72(r3)
69 lfd f24,80(r3)
70 lfd f25,88(r3)
71 lfd f26,96(r3)
72 lfd f27,104(r3)
73 lfd f28,112(r3)
74 lfd f29,120(r3)
75 lfd f30,128(r3)
76 lfd f31,136(r3)
77 blr
78FUNC_END(load_fpu)
79
80#endif /* _SELFTESTS_POWERPC_FPU_ASM_H */
diff --git a/tools/testing/selftests/powerpc/gpr_asm.h b/tools/testing/selftests/powerpc/gpr_asm.h
new file mode 100644
index 000000000000..f6f38852d3a0
--- /dev/null
+++ b/tools/testing/selftests/powerpc/gpr_asm.h
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
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#ifndef _SELFTESTS_POWERPC_GPR_ASM_H
11#define _SELFTESTS_POWERPC_GPR_ASM_H
12
13#include "basic_asm.h"
14
15#define __PUSH_NVREGS(top_pos); \
16 std r31,(top_pos)(%r1); \
17 std r30,(top_pos - 8)(%r1); \
18 std r29,(top_pos - 16)(%r1); \
19 std r28,(top_pos - 24)(%r1); \
20 std r27,(top_pos - 32)(%r1); \
21 std r26,(top_pos - 40)(%r1); \
22 std r25,(top_pos - 48)(%r1); \
23 std r24,(top_pos - 56)(%r1); \
24 std r23,(top_pos - 64)(%r1); \
25 std r22,(top_pos - 72)(%r1); \
26 std r21,(top_pos - 80)(%r1); \
27 std r20,(top_pos - 88)(%r1); \
28 std r19,(top_pos - 96)(%r1); \
29 std r18,(top_pos - 104)(%r1); \
30 std r17,(top_pos - 112)(%r1); \
31 std r16,(top_pos - 120)(%r1); \
32 std r15,(top_pos - 128)(%r1); \
33 std r14,(top_pos - 136)(%r1)
34
35#define __POP_NVREGS(top_pos); \
36 ld r31,(top_pos)(%r1); \
37 ld r30,(top_pos - 8)(%r1); \
38 ld r29,(top_pos - 16)(%r1); \
39 ld r28,(top_pos - 24)(%r1); \
40 ld r27,(top_pos - 32)(%r1); \
41 ld r26,(top_pos - 40)(%r1); \
42 ld r25,(top_pos - 48)(%r1); \
43 ld r24,(top_pos - 56)(%r1); \
44 ld r23,(top_pos - 64)(%r1); \
45 ld r22,(top_pos - 72)(%r1); \
46 ld r21,(top_pos - 80)(%r1); \
47 ld r20,(top_pos - 88)(%r1); \
48 ld r19,(top_pos - 96)(%r1); \
49 ld r18,(top_pos - 104)(%r1); \
50 ld r17,(top_pos - 112)(%r1); \
51 ld r16,(top_pos - 120)(%r1); \
52 ld r15,(top_pos - 128)(%r1); \
53 ld r14,(top_pos - 136)(%r1)
54
55#define PUSH_NVREGS(stack_size) \
56 __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE)
57
58/* 18 NV FPU REGS */
59#define PUSH_NVREGS_BELOW_FPU(stack_size) \
60 __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8))
61
62#define POP_NVREGS(stack_size) \
63 __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE)
64
65/* 18 NV FPU REGS */
66#define POP_NVREGS_BELOW_FPU(stack_size) \
67 __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8))
68
69/*
70 * Careful calling this, it will 'clobber' NVGPRs (by design)
71 * Don't call this from C
72 */
73FUNC_START(load_gpr)
74 ld r14,0(r3)
75 ld r15,8(r3)
76 ld r16,16(r3)
77 ld r17,24(r3)
78 ld r18,32(r3)
79 ld r19,40(r3)
80 ld r20,48(r3)
81 ld r21,56(r3)
82 ld r22,64(r3)
83 ld r23,72(r3)
84 ld r24,80(r3)
85 ld r25,88(r3)
86 ld r26,96(r3)
87 ld r27,104(r3)
88 ld r28,112(r3)
89 ld r29,120(r3)
90 ld r30,128(r3)
91 ld r31,136(r3)
92 blr
93FUNC_END(load_gpr)
94
95
96#endif /* _SELFTESTS_POWERPC_GPR_ASM_H */
diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
index 52f9be7f61f0..248a820048df 100644
--- a/tools/testing/selftests/powerpc/harness.c
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -19,9 +19,9 @@
19#include "subunit.h" 19#include "subunit.h"
20#include "utils.h" 20#include "utils.h"
21 21
22#define TIMEOUT 120
23#define KILL_TIMEOUT 5 22#define KILL_TIMEOUT 5
24 23
24static uint64_t timeout = 120;
25 25
26int run_test(int (test_function)(void), char *name) 26int run_test(int (test_function)(void), char *name)
27{ 27{
@@ -44,7 +44,7 @@ int run_test(int (test_function)(void), char *name)
44 setpgid(pid, pid); 44 setpgid(pid, pid);
45 45
46 /* Wake us up in timeout seconds */ 46 /* Wake us up in timeout seconds */
47 alarm(TIMEOUT); 47 alarm(timeout);
48 terminated = false; 48 terminated = false;
49 49
50wait: 50wait:
@@ -94,6 +94,11 @@ static struct sigaction alarm_action = {
94 .sa_handler = alarm_handler, 94 .sa_handler = alarm_handler,
95}; 95};
96 96
97void test_harness_set_timeout(uint64_t time)
98{
99 timeout = time;
100}
101
97int test_harness(int (test_function)(void), char *name) 102int test_harness(int (test_function)(void), char *name)
98{ 103{
99 int rc; 104 int rc;
diff --git a/tools/testing/selftests/powerpc/math/Makefile b/tools/testing/selftests/powerpc/math/Makefile
index 5b88875d5955..a505b66d408a 100644
--- a/tools/testing/selftests/powerpc/math/Makefile
+++ b/tools/testing/selftests/powerpc/math/Makefile
@@ -1,4 +1,4 @@
1TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal 1TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal vsx_preempt
2 2
3all: $(TEST_PROGS) 3all: $(TEST_PROGS)
4 4
@@ -13,6 +13,9 @@ vmx_syscall: vmx_asm.S
13vmx_preempt: vmx_asm.S 13vmx_preempt: vmx_asm.S
14vmx_signal: vmx_asm.S 14vmx_signal: vmx_asm.S
15 15
16vsx_preempt: CFLAGS += -mvsx
17vsx_preempt: vsx_asm.S
18
16include ../../lib.mk 19include ../../lib.mk
17 20
18clean: 21clean:
diff --git a/tools/testing/selftests/powerpc/math/fpu_asm.S b/tools/testing/selftests/powerpc/math/fpu_asm.S
index f3711d80e709..241f067a510f 100644
--- a/tools/testing/selftests/powerpc/math/fpu_asm.S
+++ b/tools/testing/selftests/powerpc/math/fpu_asm.S
@@ -8,70 +8,7 @@
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "../basic_asm.h"
11 11#include "../fpu_asm.h"
12#define PUSH_FPU(pos) \
13 stfd f14,pos(sp); \
14 stfd f15,pos+8(sp); \
15 stfd f16,pos+16(sp); \
16 stfd f17,pos+24(sp); \
17 stfd f18,pos+32(sp); \
18 stfd f19,pos+40(sp); \
19 stfd f20,pos+48(sp); \
20 stfd f21,pos+56(sp); \
21 stfd f22,pos+64(sp); \
22 stfd f23,pos+72(sp); \
23 stfd f24,pos+80(sp); \
24 stfd f25,pos+88(sp); \
25 stfd f26,pos+96(sp); \
26 stfd f27,pos+104(sp); \
27 stfd f28,pos+112(sp); \
28 stfd f29,pos+120(sp); \
29 stfd f30,pos+128(sp); \
30 stfd f31,pos+136(sp);
31
32#define POP_FPU(pos) \
33 lfd f14,pos(sp); \
34 lfd f15,pos+8(sp); \
35 lfd f16,pos+16(sp); \
36 lfd f17,pos+24(sp); \
37 lfd f18,pos+32(sp); \
38 lfd f19,pos+40(sp); \
39 lfd f20,pos+48(sp); \
40 lfd f21,pos+56(sp); \
41 lfd f22,pos+64(sp); \
42 lfd f23,pos+72(sp); \
43 lfd f24,pos+80(sp); \
44 lfd f25,pos+88(sp); \
45 lfd f26,pos+96(sp); \
46 lfd f27,pos+104(sp); \
47 lfd f28,pos+112(sp); \
48 lfd f29,pos+120(sp); \
49 lfd f30,pos+128(sp); \
50 lfd f31,pos+136(sp);
51
52# Careful calling this, it will 'clobber' fpu (by design)
53# Don't call this from C
54FUNC_START(load_fpu)
55 lfd f14,0(r3)
56 lfd f15,8(r3)
57 lfd f16,16(r3)
58 lfd f17,24(r3)
59 lfd f18,32(r3)
60 lfd f19,40(r3)
61 lfd f20,48(r3)
62 lfd f21,56(r3)
63 lfd f22,64(r3)
64 lfd f23,72(r3)
65 lfd f24,80(r3)
66 lfd f25,88(r3)
67 lfd f26,96(r3)
68 lfd f27,104(r3)
69 lfd f28,112(r3)
70 lfd f29,120(r3)
71 lfd f30,128(r3)
72 lfd f31,136(r3)
73 blr
74FUNC_END(load_fpu)
75 12
76FUNC_START(check_fpu) 13FUNC_START(check_fpu)
77 mr r4,r3 14 mr r4,r3
@@ -138,9 +75,9 @@ FUNC_START(test_fpu)
138 # r4 holds pointer to the pid 75 # r4 holds pointer to the pid
139 # f14-f31 are non volatiles 76 # f14-f31 are non volatiles
140 PUSH_BASIC_STACK(256) 77 PUSH_BASIC_STACK(256)
78 PUSH_FPU(256)
141 std r3,STACK_FRAME_PARAM(0)(sp) # Address of darray 79 std r3,STACK_FRAME_PARAM(0)(sp) # Address of darray
142 std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid 80 std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid
143 PUSH_FPU(STACK_FRAME_LOCAL(2,0))
144 81
145 bl load_fpu 82 bl load_fpu
146 nop 83 nop
@@ -155,7 +92,7 @@ FUNC_START(test_fpu)
155 bl check_fpu 92 bl check_fpu
156 nop 93 nop
157 94
158 POP_FPU(STACK_FRAME_LOCAL(2,0)) 95 POP_FPU(256)
159 POP_BASIC_STACK(256) 96 POP_BASIC_STACK(256)
160 blr 97 blr
161FUNC_END(test_fpu) 98FUNC_END(test_fpu)
@@ -166,10 +103,10 @@ FUNC_END(test_fpu)
166# registers while running is not zero. 103# registers while running is not zero.
167FUNC_START(preempt_fpu) 104FUNC_START(preempt_fpu)
168 PUSH_BASIC_STACK(256) 105 PUSH_BASIC_STACK(256)
106 PUSH_FPU(256)
169 std r3,STACK_FRAME_PARAM(0)(sp) # double *darray 107 std r3,STACK_FRAME_PARAM(0)(sp) # double *darray
170 std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting 108 std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
171 std r5,STACK_FRAME_PARAM(2)(sp) # int *running 109 std r5,STACK_FRAME_PARAM(2)(sp) # int *running
172 PUSH_FPU(STACK_FRAME_LOCAL(3,0))
173 110
174 bl load_fpu 111 bl load_fpu
175 nop 112 nop
@@ -192,7 +129,7 @@ FUNC_START(preempt_fpu)
192 cmpwi r5,0 129 cmpwi r5,0
193 bne 2b 130 bne 2b
194 131
1953: POP_FPU(STACK_FRAME_LOCAL(3,0)) 1323: POP_FPU(256)
196 POP_BASIC_STACK(256) 133 POP_BASIC_STACK(256)
197 blr 134 blr
198FUNC_END(preempt_fpu) 135FUNC_END(preempt_fpu)
diff --git a/tools/testing/selftests/powerpc/math/vmx_asm.S b/tools/testing/selftests/powerpc/math/vmx_asm.S
index 1b8c248b3ac1..fd74da488625 100644
--- a/tools/testing/selftests/powerpc/math/vmx_asm.S
+++ b/tools/testing/selftests/powerpc/math/vmx_asm.S
@@ -8,90 +8,7 @@
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "../basic_asm.h"
11 11#include "../vmx_asm.h"
12# POS MUST BE 16 ALIGNED!
13#define PUSH_VMX(pos,reg) \
14 li reg,pos; \
15 stvx v20,reg,sp; \
16 addi reg,reg,16; \
17 stvx v21,reg,sp; \
18 addi reg,reg,16; \
19 stvx v22,reg,sp; \
20 addi reg,reg,16; \
21 stvx v23,reg,sp; \
22 addi reg,reg,16; \
23 stvx v24,reg,sp; \
24 addi reg,reg,16; \
25 stvx v25,reg,sp; \
26 addi reg,reg,16; \
27 stvx v26,reg,sp; \
28 addi reg,reg,16; \
29 stvx v27,reg,sp; \
30 addi reg,reg,16; \
31 stvx v28,reg,sp; \
32 addi reg,reg,16; \
33 stvx v29,reg,sp; \
34 addi reg,reg,16; \
35 stvx v30,reg,sp; \
36 addi reg,reg,16; \
37 stvx v31,reg,sp;
38
39# POS MUST BE 16 ALIGNED!
40#define POP_VMX(pos,reg) \
41 li reg,pos; \
42 lvx v20,reg,sp; \
43 addi reg,reg,16; \
44 lvx v21,reg,sp; \
45 addi reg,reg,16; \
46 lvx v22,reg,sp; \
47 addi reg,reg,16; \
48 lvx v23,reg,sp; \
49 addi reg,reg,16; \
50 lvx v24,reg,sp; \
51 addi reg,reg,16; \
52 lvx v25,reg,sp; \
53 addi reg,reg,16; \
54 lvx v26,reg,sp; \
55 addi reg,reg,16; \
56 lvx v27,reg,sp; \
57 addi reg,reg,16; \
58 lvx v28,reg,sp; \
59 addi reg,reg,16; \
60 lvx v29,reg,sp; \
61 addi reg,reg,16; \
62 lvx v30,reg,sp; \
63 addi reg,reg,16; \
64 lvx v31,reg,sp;
65
66# Carefull this will 'clobber' vmx (by design)
67# Don't call this from C
68FUNC_START(load_vmx)
69 li r5,0
70 lvx v20,r5,r3
71 addi r5,r5,16
72 lvx v21,r5,r3
73 addi r5,r5,16
74 lvx v22,r5,r3
75 addi r5,r5,16
76 lvx v23,r5,r3
77 addi r5,r5,16
78 lvx v24,r5,r3
79 addi r5,r5,16
80 lvx v25,r5,r3
81 addi r5,r5,16
82 lvx v26,r5,r3
83 addi r5,r5,16
84 lvx v27,r5,r3
85 addi r5,r5,16
86 lvx v28,r5,r3
87 addi r5,r5,16
88 lvx v29,r5,r3
89 addi r5,r5,16
90 lvx v30,r5,r3
91 addi r5,r5,16
92 lvx v31,r5,r3
93 blr
94FUNC_END(load_vmx)
95 12
96# Should be safe from C, only touches r4, r5 and v0,v1,v2 13# Should be safe from C, only touches r4, r5 and v0,v1,v2
97FUNC_START(check_vmx) 14FUNC_START(check_vmx)
diff --git a/tools/testing/selftests/powerpc/math/vsx_asm.S b/tools/testing/selftests/powerpc/math/vsx_asm.S
new file mode 100644
index 000000000000..a110dd882d5e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/math/vsx_asm.S
@@ -0,0 +1,61 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
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 "../basic_asm.h"
11#include "../vsx_asm.h"
12
13#long check_vsx(vector int *r3);
14#This function wraps storeing VSX regs to the end of an array and a
15#call to a comparison function in C which boils down to a memcmp()
16FUNC_START(check_vsx)
17 PUSH_BASIC_STACK(32)
18 std r3,STACK_FRAME_PARAM(0)(sp)
19 addi r3, r3, 16 * 12 #Second half of array
20 bl store_vsx
21 ld r3,STACK_FRAME_PARAM(0)(sp)
22 bl vsx_memcmp
23 POP_BASIC_STACK(32)
24 blr
25FUNC_END(check_vsx)
26
27# int preempt_vmx(vector int *varray, int *threads_starting,
28# int *running);
29# On starting will (atomically) decrement threads_starting as a signal
30# that the VMX have been loaded with varray. Will proceed to check the
31# validity of the VMX registers while running is not zero.
32FUNC_START(preempt_vsx)
33 PUSH_BASIC_STACK(512)
34 std r3,STACK_FRAME_PARAM(0)(sp) # vector int *varray
35 std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
36 std r5,STACK_FRAME_PARAM(2)(sp) # int *running
37
38 bl load_vsx
39 nop
40
41 sync
42 # Atomic DEC
43 ld r3,STACK_FRAME_PARAM(1)(sp)
441: lwarx r4,0,r3
45 addi r4,r4,-1
46 stwcx. r4,0,r3
47 bne- 1b
48
492: ld r3,STACK_FRAME_PARAM(0)(sp)
50 bl check_vsx
51 nop
52 cmpdi r3,0
53 bne 3f
54 ld r4,STACK_FRAME_PARAM(2)(sp)
55 ld r5,0(r4)
56 cmpwi r5,0
57 bne 2b
58
593: POP_BASIC_STACK(512)
60 blr
61FUNC_END(preempt_vsx)
diff --git a/tools/testing/selftests/powerpc/math/vsx_preempt.c b/tools/testing/selftests/powerpc/math/vsx_preempt.c
new file mode 100644
index 000000000000..6387f03a0a6a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/math/vsx_preempt.c
@@ -0,0 +1,147 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
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 * This test attempts to see if the VSX registers change across preemption.
10 * There is no way to be sure preemption happened so this test just
11 * uses many threads and a long wait. As such, a successful test
12 * doesn't mean much but a failure is bad.
13 */
14
15#include <stdio.h>
16#include <string.h>
17#include <unistd.h>
18#include <sys/syscall.h>
19#include <sys/time.h>
20#include <sys/types.h>
21#include <sys/wait.h>
22#include <stdlib.h>
23#include <pthread.h>
24
25#include "utils.h"
26
27/* Time to wait for workers to get preempted (seconds) */
28#define PREEMPT_TIME 20
29/*
30 * Factor by which to multiply number of online CPUs for total number of
31 * worker threads
32 */
33#define THREAD_FACTOR 8
34
35/*
36 * Ensure there is twice the number of non-volatile VMX regs!
37 * check_vmx() is going to use the other half as space to put the live
38 * registers before calling vsx_memcmp()
39 */
40__thread vector int varray[24] = {
41 {1, 2, 3, 4 }, {5, 6, 7, 8 }, {9, 10,11,12},
42 {13,14,15,16}, {17,18,19,20}, {21,22,23,24},
43 {25,26,27,28}, {29,30,31,32}, {33,34,35,36},
44 {37,38,39,40}, {41,42,43,44}, {45,46,47,48}
45};
46
47int threads_starting;
48int running;
49
50extern long preempt_vsx(vector int *varray, int *threads_starting, int *running);
51
52long vsx_memcmp(vector int *a) {
53 vector int zero = {0, 0, 0, 0};
54 int i;
55
56 FAIL_IF(a != varray);
57
58 for(i = 0; i < 12; i++) {
59 if (memcmp(&a[i + 12], &zero, sizeof(vector int)) == 0) {
60 fprintf(stderr, "Detected zero from the VSX reg %d\n", i + 12);
61 return 2;
62 }
63 }
64
65 if (memcmp(a, &a[12], 12 * sizeof(vector int))) {
66 long *p = (long *)a;
67 fprintf(stderr, "VSX mismatch\n");
68 for (i = 0; i < 24; i=i+2)
69 fprintf(stderr, "%d: 0x%08lx%08lx | 0x%08lx%08lx\n",
70 i/2 + i%2 + 20, p[i], p[i + 1], p[i + 24], p[i + 25]);
71 return 1;
72 }
73 return 0;
74}
75
76void *preempt_vsx_c(void *p)
77{
78 int i, j;
79 long rc;
80 srand(pthread_self());
81 for (i = 0; i < 12; i++)
82 for (j = 0; j < 4; j++) {
83 varray[i][j] = rand();
84 /* Don't want zero because it hides kernel problems */
85 if (varray[i][j] == 0)
86 j--;
87 }
88 rc = preempt_vsx(varray, &threads_starting, &running);
89 if (rc == 2)
90 fprintf(stderr, "Caught zeros in VSX compares\n");
91 return (void *)rc;
92}
93
94int test_preempt_vsx(void)
95{
96 int i, rc, threads;
97 pthread_t *tids;
98
99 threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
100 tids = malloc(threads * sizeof(pthread_t));
101 FAIL_IF(!tids);
102
103 running = true;
104 threads_starting = threads;
105 for (i = 0; i < threads; i++) {
106 rc = pthread_create(&tids[i], NULL, preempt_vsx_c, NULL);
107 FAIL_IF(rc);
108 }
109
110 setbuf(stdout, NULL);
111 /* Not really nessesary but nice to wait for every thread to start */
112 printf("\tWaiting for %d workers to start...", threads_starting);
113 while(threads_starting)
114 asm volatile("": : :"memory");
115 printf("done\n");
116
117 printf("\tWaiting for %d seconds to let some workers get preempted...", PREEMPT_TIME);
118 sleep(PREEMPT_TIME);
119 printf("done\n");
120
121 printf("\tStopping workers...");
122 /*
123 * Working are checking this value every loop. In preempt_vsx 'cmpwi r5,0; bne 2b'.
124 * r5 will have loaded the value of running.
125 */
126 running = 0;
127 for (i = 0; i < threads; i++) {
128 void *rc_p;
129 pthread_join(tids[i], &rc_p);
130
131 /*
132 * Harness will say the fail was here, look at why preempt_vsx
133 * returned
134 */
135 if ((long) rc_p)
136 printf("oops\n");
137 FAIL_IF((long) rc_p);
138 }
139 printf("done\n");
140
141 return 0;
142}
143
144int main(int argc, char *argv[])
145{
146 return test_harness(test_preempt_vsx, "vsx_preempt");
147}
diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile
new file mode 100644
index 000000000000..f0eef27458e2
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/Makefile
@@ -0,0 +1,13 @@
1TEST_PROGS := signal signal_tm
2
3all: $(TEST_PROGS)
4
5$(TEST_PROGS): ../harness.c ../utils.c signal.S
6
7CFLAGS += -maltivec
8signal_tm: CFLAGS += -mhtm
9
10include ../../lib.mk
11
12clean:
13 rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/signal/signal.S b/tools/testing/selftests/powerpc/signal/signal.S
new file mode 100644
index 000000000000..7043d521df0a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/signal.S
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
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 "../basic_asm.h"
11
12/* long signal_self(pid_t pid, int sig); */
13FUNC_START(signal_self)
14 li r0,37 /* sys_kill */
15 /* r3 already has our pid in it */
16 /* r4 already has signal type in it */
17 sc
18 bc 4,3,1f
19 subfze r3,r3
201: blr
21FUNC_END(signal_self)
22
23/* long tm_signal_self(pid_t pid, int sig, int *ret); */
24FUNC_START(tm_signal_self)
25 PUSH_BASIC_STACK(8)
26 std r5,STACK_FRAME_PARAM(0)(sp) /* ret */
27 tbegin.
28 beq 1f
29 tsuspend.
30 li r0,37 /* sys_kill */
31 /* r3 already has our pid in it */
32 /* r4 already has signal type in it */
33 sc
34 ld r5,STACK_FRAME_PARAM(0)(sp) /* ret */
35 bc 4,3,2f
36 subfze r3,r3
372: std r3,0(r5)
38 tabort. 0
39 tresume. /* Be nice to some cleanup, jumps back to tbegin then to 1: */
40 /*
41 * Transaction should be proper doomed and we should never get
42 * here
43 */
44 li r3,1
45 POP_BASIC_STACK(8)
46 blr
471: li r3,0
48 POP_BASIC_STACK(8)
49 blr
50FUNC_END(tm_signal_self)
diff --git a/tools/testing/selftests/powerpc/signal/signal.c b/tools/testing/selftests/powerpc/signal/signal.c
new file mode 100644
index 000000000000..e7dedd28b3c2
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/signal.c
@@ -0,0 +1,111 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
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 * Sending one self a signal should always get delivered.
10 */
11
12#include <signal.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <sys/types.h>
17#include <sys/wait.h>
18#include <unistd.h>
19
20#include <altivec.h>
21
22#include "utils.h"
23
24#define MAX_ATTEMPT 500000
25#define TIMEOUT 5
26
27extern long signal_self(pid_t pid, int sig);
28
29static sig_atomic_t signaled;
30static sig_atomic_t fail;
31
32static void signal_handler(int sig)
33{
34 if (sig == SIGUSR1)
35 signaled = 1;
36 else
37 fail = 1;
38}
39
40static int test_signal()
41{
42 int i;
43 struct sigaction act;
44 pid_t ppid = getpid();
45 pid_t pid;
46
47 act.sa_handler = signal_handler;
48 act.sa_flags = 0;
49 sigemptyset(&act.sa_mask);
50 if (sigaction(SIGUSR1, &act, NULL) < 0) {
51 perror("sigaction SIGUSR1");
52 exit(1);
53 }
54 if (sigaction(SIGALRM, &act, NULL) < 0) {
55 perror("sigaction SIGALRM");
56 exit(1);
57 }
58
59 /* Don't do this for MAX_ATTEMPT, its simply too long */
60 for(i = 0; i < 1000; i++) {
61 pid = fork();
62 if (pid == -1) {
63 perror("fork");
64 exit(1);
65 }
66 if (pid == 0) {
67 signal_self(ppid, SIGUSR1);
68 exit(1);
69 } else {
70 alarm(0); /* Disable any pending */
71 alarm(2);
72 while (!signaled && !fail)
73 asm volatile("": : :"memory");
74 if (!signaled) {
75 fprintf(stderr, "Didn't get signal from child\n");
76 FAIL_IF(1); /* For the line number */
77 }
78 /* Otherwise we'll loop too fast and fork() will eventually fail */
79 waitpid(pid, NULL, 0);
80 }
81 }
82
83 for (i = 0; i < MAX_ATTEMPT; i++) {
84 long rc;
85
86 alarm(0); /* Disable any pending */
87 signaled = 0;
88 alarm(TIMEOUT);
89 rc = signal_self(ppid, SIGUSR1);
90 if (rc) {
91 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
92 i, fail, rc);
93 FAIL_IF(1); /* For the line number */
94 }
95 while (!signaled && !fail)
96 asm volatile("": : :"memory");
97 if (!signaled) {
98 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
99 i, fail, rc);
100 FAIL_IF(1); /* For the line number */
101 }
102 }
103
104 return 0;
105}
106
107int main(void)
108{
109 test_harness_set_timeout(300);
110 return test_harness(test_signal, "signal");
111}
diff --git a/tools/testing/selftests/powerpc/signal/signal_tm.c b/tools/testing/selftests/powerpc/signal/signal_tm.c
new file mode 100644
index 000000000000..2e7451a37cc6
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/signal_tm.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
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 * Sending one self a signal should always get delivered.
10 */
11
12#include <errno.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <signal.h>
17#include <unistd.h>
18
19#include <altivec.h>
20
21#include "utils.h"
22#include "../tm/tm.h"
23
24#define MAX_ATTEMPT 500000
25#define TIMEOUT 10
26
27extern long tm_signal_self(pid_t pid, int sig, long *ret);
28
29static sig_atomic_t signaled;
30static sig_atomic_t fail;
31
32static void signal_handler(int sig)
33{
34 if (tcheck_active()) {
35 fail = 2;
36 return;
37 }
38
39 if (sig == SIGUSR1)
40 signaled = 1;
41 else
42 fail = 1;
43}
44
45static int test_signal_tm()
46{
47 int i;
48 struct sigaction act;
49
50 act.sa_handler = signal_handler;
51 act.sa_flags = 0;
52 sigemptyset(&act.sa_mask);
53 if (sigaction(SIGUSR1, &act, NULL) < 0) {
54 perror("sigaction SIGUSR1");
55 exit(1);
56 }
57 if (sigaction(SIGALRM, &act, NULL) < 0) {
58 perror("sigaction SIGALRM");
59 exit(1);
60 }
61
62 SKIP_IF(!have_htm());
63
64 for (i = 0; i < MAX_ATTEMPT; i++) {
65 /*
66 * If anything bad happens in ASM and we fail to set ret
67 * because *handwave* TM this will cause failure
68 */
69 long ret = 0xdead;
70 long rc = 0xbeef;
71
72 alarm(0); /* Disable any pending */
73 signaled = 0;
74 alarm(TIMEOUT);
75 FAIL_IF(tcheck_transactional());
76 rc = tm_signal_self(getpid(), SIGUSR1, &ret);
77 if (ret == 0xdead)
78 /*
79 * This basically means the transaction aborted before we
80 * even got to the suspend... this is crazy but it
81 * happens.
82 * Yes this also means we might never make forward
83 * progress... the alarm() will trip eventually...
84 */
85 continue;
86
87 if (rc || ret) {
88 /* Ret is actually an errno */
89 printf("TEXASR 0x%016lx, TFIAR 0x%016lx\n",
90 __builtin_get_texasr(), __builtin_get_tfiar());
91 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n",
92 i, fail, rc, ret);
93 FAIL_IF(ret);
94 }
95 while(!signaled && !fail)
96 asm volatile("": : :"memory");
97 if (!signaled) {
98 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n",
99 i, fail, rc, ret);
100 FAIL_IF(fail); /* For the line number */
101 }
102 }
103
104 return 0;
105}
106
107int main(void)
108{
109 return test_harness(test_signal_tm, "signal_tm");
110}
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index 9d301d785d9e..c6c53c82fdd6 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,5 +1,8 @@
1SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu \
2 tm-signal-context-chk-vmx tm-signal-context-chk-vsx
3
1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \ 4TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
2 tm-vmxcopy tm-fork tm-tar tm-tmspr tm-exec tm-execed 5 tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS)
3 6
4all: $(TEST_PROGS) 7all: $(TEST_PROGS)
5 8
@@ -11,6 +14,9 @@ tm-syscall: tm-syscall-asm.S
11tm-syscall: CFLAGS += -I../../../../../usr/include 14tm-syscall: CFLAGS += -I../../../../../usr/include
12tm-tmspr: CFLAGS += -pthread 15tm-tmspr: CFLAGS += -pthread
13 16
17$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
18$(SIGNAL_CONTEXT_CHK_TESTS): CFLAGS += -mhtm -m64 -mvsx
19
14include ../../lib.mk 20include ../../lib.mk
15 21
16clean: 22clean:
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
new file mode 100644
index 000000000000..c760debbd5ad
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
@@ -0,0 +1,92 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
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 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <signal.h>
27#include <unistd.h>
28
29#include <altivec.h>
30
31#include "utils.h"
32#include "tm.h"
33
34#define MAX_ATTEMPT 500000
35
36#define NV_FPU_REGS 18
37
38long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
39
40/* Be sure there are 2x as many as there are NV FPU regs (2x18) */
41static double fps[] = {
42 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
43 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
44};
45
46static sig_atomic_t fail;
47
48static void signal_usr1(int signum, siginfo_t *info, void *uc)
49{
50 int i;
51 ucontext_t *ucp = uc;
52 ucontext_t *tm_ucp = ucp->uc_link;
53
54 for (i = 0; i < NV_FPU_REGS && !fail; i++) {
55 fail = (ucp->uc_mcontext.fp_regs[i + 14] != fps[i]);
56 fail |= (tm_ucp->uc_mcontext.fp_regs[i + 14] != fps[i + NV_FPU_REGS]);
57 if (fail)
58 printf("Failed on %d FP %g or %g\n", i, ucp->uc_mcontext.fp_regs[i + 14], tm_ucp->uc_mcontext.fp_regs[i + 14]);
59 }
60}
61
62static int tm_signal_context_chk_fpu()
63{
64 struct sigaction act;
65 int i;
66 long rc;
67 pid_t pid = getpid();
68
69 SKIP_IF(!have_htm());
70
71 act.sa_sigaction = signal_usr1;
72 sigemptyset(&act.sa_mask);
73 act.sa_flags = SA_SIGINFO;
74 if (sigaction(SIGUSR1, &act, NULL) < 0) {
75 perror("sigaction sigusr1");
76 exit(1);
77 }
78
79 i = 0;
80 while (i < MAX_ATTEMPT && !fail) {
81 rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL);
82 FAIL_IF(rc != pid);
83 i++;
84 }
85
86 return fail;
87}
88
89int main(void)
90{
91 return test_harness(tm_signal_context_chk_fpu, "tm_signal_context_chk_fpu");
92}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
new file mode 100644
index 000000000000..df91330a08ef
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
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 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <signal.h>
27#include <unistd.h>
28
29#include <altivec.h>
30
31#include "utils.h"
32#include "tm.h"
33
34#define MAX_ATTEMPT 500000
35
36#define NV_GPR_REGS 18
37
38long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
39
40static sig_atomic_t fail;
41
42static long gps[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
43 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18};
44
45static void signal_usr1(int signum, siginfo_t *info, void *uc)
46{
47 int i;
48 ucontext_t *ucp = uc;
49 ucontext_t *tm_ucp = ucp->uc_link;
50
51 for (i = 0; i < NV_GPR_REGS && !fail; i++) {
52 fail = (ucp->uc_mcontext.gp_regs[i + 14] != gps[i]);
53 fail |= (tm_ucp->uc_mcontext.gp_regs[i + 14] != gps[i + NV_GPR_REGS]);
54 if (fail)
55 printf("Failed on %d GPR %lu or %lu\n", i,
56 ucp->uc_mcontext.gp_regs[i + 14], tm_ucp->uc_mcontext.gp_regs[i + 14]);
57 }
58}
59
60static int tm_signal_context_chk_gpr()
61{
62 struct sigaction act;
63 int i;
64 long rc;
65 pid_t pid = getpid();
66
67 SKIP_IF(!have_htm());
68
69 act.sa_sigaction = signal_usr1;
70 sigemptyset(&act.sa_mask);
71 act.sa_flags = SA_SIGINFO;
72 if (sigaction(SIGUSR1, &act, NULL) < 0) {
73 perror("sigaction sigusr1");
74 exit(1);
75 }
76
77 i = 0;
78 while (i < MAX_ATTEMPT && !fail) {
79 rc = tm_signal_self_context_load(pid, gps, NULL, NULL, NULL);
80 FAIL_IF(rc != pid);
81 i++;
82 }
83
84 return fail;
85}
86
87int main(void)
88{
89 return test_harness(tm_signal_context_chk_gpr, "tm_signal_context_chk_gpr");
90}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
new file mode 100644
index 000000000000..f0ee55fd5185
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
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 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29
30#include <altivec.h>
31
32#include "utils.h"
33#include "tm.h"
34
35#define MAX_ATTEMPT 500000
36
37#define NV_VMX_REGS 12
38
39long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
40
41static sig_atomic_t fail;
42
43vector int vms[] = {
44 {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12},
45 {13,14,15,16},{17,18,19,20},{21,22,23,24},
46 {25,26,27,28},{29,30,31,32},{33,34,35,36},
47 {37,38,39,40},{41,42,43,44},{45,46,47,48},
48 {-1, -2, -3, -4}, {-5, -6, -7, -8}, {-9, -10,-11,-12},
49 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24},
50 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36},
51 {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48}
52};
53
54static void signal_usr1(int signum, siginfo_t *info, void *uc)
55{
56 int i;
57 ucontext_t *ucp = uc;
58 ucontext_t *tm_ucp = ucp->uc_link;
59
60 for (i = 0; i < NV_VMX_REGS && !fail; i++) {
61 fail = memcmp(ucp->uc_mcontext.v_regs->vrregs[i + 20],
62 &vms[i], sizeof(vector int));
63 fail |= memcmp(tm_ucp->uc_mcontext.v_regs->vrregs[i + 20],
64 &vms[i + NV_VMX_REGS], sizeof (vector int));
65
66 if (fail) {
67 int j;
68
69 fprintf(stderr, "Failed on %d vmx 0x", i);
70 for (j = 0; j < 4; j++)
71 fprintf(stderr, "%04x", ucp->uc_mcontext.v_regs->vrregs[i + 20][j]);
72 fprintf(stderr, " vs 0x");
73 for (j = 0 ; j < 4; j++)
74 fprintf(stderr, "%04x", tm_ucp->uc_mcontext.v_regs->vrregs[i + 20][j]);
75 fprintf(stderr, "\n");
76 }
77 }
78}
79
80static int tm_signal_context_chk()
81{
82 struct sigaction act;
83 int i;
84 long rc;
85 pid_t pid = getpid();
86
87 SKIP_IF(!have_htm());
88
89 act.sa_sigaction = signal_usr1;
90 sigemptyset(&act.sa_mask);
91 act.sa_flags = SA_SIGINFO;
92 if (sigaction(SIGUSR1, &act, NULL) < 0) {
93 perror("sigaction sigusr1");
94 exit(1);
95 }
96
97 i = 0;
98 while (i < MAX_ATTEMPT && !fail) {
99 rc = tm_signal_self_context_load(pid, NULL, NULL, vms, NULL);
100 FAIL_IF(rc != pid);
101 i++;
102 }
103
104 return fail;
105}
106
107int main(void)
108{
109 return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vmx");
110}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
new file mode 100644
index 000000000000..b99c3d835957
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
@@ -0,0 +1,125 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
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 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29
30#include <altivec.h>
31
32#include "utils.h"
33#include "tm.h"
34
35#define MAX_ATTEMPT 500000
36
37#define NV_VSX_REGS 12
38
39long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
40
41static sig_atomic_t fail;
42
43vector int vss[] = {
44 {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12},
45 {13,14,15,16},{17,18,19,20},{21,22,23,24},
46 {25,26,27,28},{29,30,31,32},{33,34,35,36},
47 {37,38,39,40},{41,42,43,44},{45,46,47,48},
48 {-1, -2, -3, -4 },{-5, -6, -7, -8 },{-9, -10,-11,-12},
49 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24},
50 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36},
51 {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48}
52};
53
54static void signal_usr1(int signum, siginfo_t *info, void *uc)
55{
56 int i;
57 uint8_t vsc[sizeof(vector int)];
58 uint8_t vst[sizeof(vector int)];
59 ucontext_t *ucp = uc;
60 ucontext_t *tm_ucp = ucp->uc_link;
61
62 /*
63 * The other half of the VSX regs will be after v_regs.
64 *
65 * In short, vmx_reserve array holds everything. v_regs is a 16
66 * byte aligned pointer at the start of vmx_reserve (vmx_reserve
67 * may or may not be 16 aligned) where the v_regs structure exists.
68 * (half of) The VSX regsters are directly after v_regs so the
69 * easiest way to find them below.
70 */
71 long *vsx_ptr = (long *)(ucp->uc_mcontext.v_regs + 1);
72 long *tm_vsx_ptr = (long *)(tm_ucp->uc_mcontext.v_regs + 1);
73 for (i = 0; i < NV_VSX_REGS && !fail; i++) {
74 memcpy(vsc, &ucp->uc_mcontext.fp_regs[i + 20], 8);
75 memcpy(vsc + 8, &vsx_ptr[20 + i], 8);
76 fail = memcmp(vsc, &vss[i], sizeof(vector int));
77 memcpy(vst, &tm_ucp->uc_mcontext.fp_regs[i + 20], 8);
78 memcpy(vst + 8, &tm_vsx_ptr[20 + i], 8);
79 fail |= memcmp(vst, &vss[i + NV_VSX_REGS], sizeof(vector int));
80
81 if (fail) {
82 int j;
83
84 fprintf(stderr, "Failed on %d vsx 0x", i);
85 for (j = 0; j < 16; j++)
86 fprintf(stderr, "%02x", vsc[j]);
87 fprintf(stderr, " vs 0x");
88 for (j = 0; j < 16; j++)
89 fprintf(stderr, "%02x", vst[j]);
90 fprintf(stderr, "\n");
91 }
92 }
93}
94
95static int tm_signal_context_chk()
96{
97 struct sigaction act;
98 int i;
99 long rc;
100 pid_t pid = getpid();
101
102 SKIP_IF(!have_htm());
103
104 act.sa_sigaction = signal_usr1;
105 sigemptyset(&act.sa_mask);
106 act.sa_flags = SA_SIGINFO;
107 if (sigaction(SIGUSR1, &act, NULL) < 0) {
108 perror("sigaction sigusr1");
109 exit(1);
110 }
111
112 i = 0;
113 while (i < MAX_ATTEMPT && !fail) {
114 rc = tm_signal_self_context_load(pid, NULL, NULL, NULL, vss);
115 FAIL_IF(rc != pid);
116 i++;
117 }
118
119 return fail;
120}
121
122int main(void)
123{
124 return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vsx");
125}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal.S b/tools/testing/selftests/powerpc/tm/tm-signal.S
new file mode 100644
index 000000000000..4e13e8b3a96f
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal.S
@@ -0,0 +1,114 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
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 "../basic_asm.h"
11#include "../gpr_asm.h"
12#include "../fpu_asm.h"
13#include "../vmx_asm.h"
14#include "../vsx_asm.h"
15
16/*
17 * Large caveat here being that the caller cannot expect the
18 * signal to always be sent! The hardware can (AND WILL!) abort
19 * the transaction between the tbegin and the tsuspend (however
20 * unlikely it seems or infrequently it actually happens).
21 * You have been warned.
22 */
23/* long tm_signal_self(pid_t pid, long *gprs, double *fps, vector *vms, vector *vss); */
24FUNC_START(tm_signal_self_context_load)
25 PUSH_BASIC_STACK(512)
26 /*
27 * Don't strictly need to save and restore as it depends on if
28 * we're going to use them, however this reduces messy logic
29 */
30 PUSH_VMX(STACK_FRAME_LOCAL(5,0),r8)
31 PUSH_FPU(512)
32 PUSH_NVREGS_BELOW_FPU(512)
33 std r3, STACK_FRAME_PARAM(0)(sp) /* pid */
34 std r4, STACK_FRAME_PARAM(1)(sp) /* gps */
35 std r5, STACK_FRAME_PARAM(2)(sp) /* fps */
36 std r6, STACK_FRAME_PARAM(3)(sp) /* vms */
37 std r7, STACK_FRAME_PARAM(4)(sp) /* vss */
38
39 ld r3, STACK_FRAME_PARAM(1)(sp)
40 cmpdi r3, 0
41 beq skip_gpr_lc
42 bl load_gpr
43skip_gpr_lc:
44 ld r3, STACK_FRAME_PARAM(2)(sp)
45 cmpdi r3, 0
46 beq skip_fpu_lc
47 bl load_fpu
48skip_fpu_lc:
49 ld r3, STACK_FRAME_PARAM(3)(sp)
50 cmpdi r3, 0
51 beq skip_vmx_lc
52 bl load_vmx
53skip_vmx_lc:
54 ld r3, STACK_FRAME_PARAM(4)(sp)
55 cmpdi r3, 0
56 beq skip_vsx_lc
57 bl load_vsx
58skip_vsx_lc:
59 /*
60 * Set r3 (return value) before tbegin. Use the pid as a known
61 * 'all good' return value, zero is used to indicate a non-doomed
62 * transaction.
63 */
64 ld r3, STACK_FRAME_PARAM(0)(sp)
65 tbegin.
66 beq 1f
67 tsuspend. /* Can't enter a syscall transactionally */
68 ld r3, STACK_FRAME_PARAM(1)(sp)
69 cmpdi r3, 0
70 beq skip_gpr_lt
71 /* Get the second half of the array */
72 addi r3, r3, 8 * 18
73 bl load_gpr
74skip_gpr_lt:
75 ld r3, STACK_FRAME_PARAM(2)(sp)
76 cmpdi r3, 0
77 beq skip_fpu_lt
78 /* Get the second half of the array */
79 addi r3, r3, 8 * 18
80 bl load_fpu
81skip_fpu_lt:
82 ld r3, STACK_FRAME_PARAM(3)(sp)
83 cmpdi r3, 0
84 beq skip_vmx_lt
85 /* Get the second half of the array */
86 addi r3, r3, 16 * 12
87 bl load_vmx
88skip_vmx_lt:
89 ld r3, STACK_FRAME_PARAM(4)(sp)
90 cmpdi r3, 0
91 beq skip_vsx_lt
92 /* Get the second half of the array */
93 addi r3, r3, 16 * 12
94 bl load_vsx
95skip_vsx_lt:
96 li r0, 37 /* sys_kill */
97 ld r3, STACK_FRAME_PARAM(0)(sp) /* pid */
98 li r4, 10 /* SIGUSR1 */
99 sc /* Taking the signal will doom the transaction */
100 tabort. 0
101 tresume. /* Be super sure we abort */
102 /*
103 * This will cause us to resume doomed transaction and cause
104 * hardware to cleanup, we'll end up at 1: anything between
105 * tresume. and 1: shouldn't ever run.
106 */
107 li r3, 0
108 1:
109 POP_VMX(STACK_FRAME_LOCAL(5,0),r4)
110 POP_FPU(512)
111 POP_NVREGS_BELOW_FPU(512)
112 POP_BASIC_STACK(512)
113 blr
114FUNC_END(tm_signal_self_context_load)
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h
index 60318bad7d7a..2c8da74304e7 100644
--- a/tools/testing/selftests/powerpc/tm/tm.h
+++ b/tools/testing/selftests/powerpc/tm/tm.h
@@ -52,4 +52,31 @@ static inline bool failure_is_nesting(void)
52 return (__builtin_get_texasru() & 0x400000); 52 return (__builtin_get_texasru() & 0x400000);
53} 53}
54 54
55static inline int tcheck(void)
56{
57 long cr;
58 asm volatile ("tcheck 0" : "=r"(cr) : : "cr0");
59 return (cr >> 28) & 4;
60}
61
62static inline bool tcheck_doomed(void)
63{
64 return tcheck() & 8;
65}
66
67static inline bool tcheck_active(void)
68{
69 return tcheck() & 4;
70}
71
72static inline bool tcheck_suspended(void)
73{
74 return tcheck() & 2;
75}
76
77static inline bool tcheck_transactional(void)
78{
79 return tcheck() & 6;
80}
81
55#endif /* _SELFTESTS_POWERPC_TM_TM_H */ 82#endif /* _SELFTESTS_POWERPC_TM_TM_H */
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
index fbd33e52ef8f..53405e8a52ab 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -22,7 +22,7 @@ typedef uint32_t u32;
22typedef uint16_t u16; 22typedef uint16_t u16;
23typedef uint8_t u8; 23typedef uint8_t u8;
24 24
25 25void test_harness_set_timeout(uint64_t time);
26int test_harness(int (test_function)(void), char *name); 26int test_harness(int (test_function)(void), char *name);
27extern void *get_auxv_entry(int type); 27extern void *get_auxv_entry(int type);
28int pick_online_cpu(void); 28int pick_online_cpu(void);
@@ -32,10 +32,17 @@ static inline bool have_hwcap(unsigned long ftr)
32 return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr; 32 return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr;
33} 33}
34 34
35#ifdef AT_HWCAP2
35static inline bool have_hwcap2(unsigned long ftr2) 36static inline bool have_hwcap2(unsigned long ftr2)
36{ 37{
37 return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2; 38 return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2;
38} 39}
40#else
41static inline bool have_hwcap2(unsigned long ftr2)
42{
43 return false;
44}
45#endif
39 46
40/* Yes, this is evil */ 47/* Yes, this is evil */
41#define FAIL_IF(x) \ 48#define FAIL_IF(x) \
diff --git a/tools/testing/selftests/powerpc/vmx_asm.h b/tools/testing/selftests/powerpc/vmx_asm.h
new file mode 100644
index 000000000000..2eaaeca9cf1d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vmx_asm.h
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
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 "basic_asm.h"
11
12/* POS MUST BE 16 ALIGNED! */
13#define PUSH_VMX(pos,reg) \
14 li reg,pos; \
15 stvx v20,reg,%r1; \
16 addi reg,reg,16; \
17 stvx v21,reg,%r1; \
18 addi reg,reg,16; \
19 stvx v22,reg,%r1; \
20 addi reg,reg,16; \
21 stvx v23,reg,%r1; \
22 addi reg,reg,16; \
23 stvx v24,reg,%r1; \
24 addi reg,reg,16; \
25 stvx v25,reg,%r1; \
26 addi reg,reg,16; \
27 stvx v26,reg,%r1; \
28 addi reg,reg,16; \
29 stvx v27,reg,%r1; \
30 addi reg,reg,16; \
31 stvx v28,reg,%r1; \
32 addi reg,reg,16; \
33 stvx v29,reg,%r1; \
34 addi reg,reg,16; \
35 stvx v30,reg,%r1; \
36 addi reg,reg,16; \
37 stvx v31,reg,%r1;
38
39/* POS MUST BE 16 ALIGNED! */
40#define POP_VMX(pos,reg) \
41 li reg,pos; \
42 lvx v20,reg,%r1; \
43 addi reg,reg,16; \
44 lvx v21,reg,%r1; \
45 addi reg,reg,16; \
46 lvx v22,reg,%r1; \
47 addi reg,reg,16; \
48 lvx v23,reg,%r1; \
49 addi reg,reg,16; \
50 lvx v24,reg,%r1; \
51 addi reg,reg,16; \
52 lvx v25,reg,%r1; \
53 addi reg,reg,16; \
54 lvx v26,reg,%r1; \
55 addi reg,reg,16; \
56 lvx v27,reg,%r1; \
57 addi reg,reg,16; \
58 lvx v28,reg,%r1; \
59 addi reg,reg,16; \
60 lvx v29,reg,%r1; \
61 addi reg,reg,16; \
62 lvx v30,reg,%r1; \
63 addi reg,reg,16; \
64 lvx v31,reg,%r1;
65
66/*
67 * Careful this will 'clobber' vmx (by design)
68 * Don't call this from C
69 */
70FUNC_START(load_vmx)
71 li r5,0
72 lvx v20,r5,r3
73 addi r5,r5,16
74 lvx v21,r5,r3
75 addi r5,r5,16
76 lvx v22,r5,r3
77 addi r5,r5,16
78 lvx v23,r5,r3
79 addi r5,r5,16
80 lvx v24,r5,r3
81 addi r5,r5,16
82 lvx v25,r5,r3
83 addi r5,r5,16
84 lvx v26,r5,r3
85 addi r5,r5,16
86 lvx v27,r5,r3
87 addi r5,r5,16
88 lvx v28,r5,r3
89 addi r5,r5,16
90 lvx v29,r5,r3
91 addi r5,r5,16
92 lvx v30,r5,r3
93 addi r5,r5,16
94 lvx v31,r5,r3
95 blr
96FUNC_END(load_vmx)
diff --git a/tools/testing/selftests/powerpc/vsx_asm.h b/tools/testing/selftests/powerpc/vsx_asm.h
new file mode 100644
index 000000000000..d828bfb6ef2d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vsx_asm.h
@@ -0,0 +1,71 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
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 "basic_asm.h"
11
12/*
13 * Careful this will 'clobber' vsx (by design), VSX are always
14 * volatile though so unlike vmx this isn't so much of an issue
15 * Still should avoid calling from C
16 */
17FUNC_START(load_vsx)
18 li r5,0
19 lxvx vs20,r5,r3
20 addi r5,r5,16
21 lxvx vs21,r5,r3
22 addi r5,r5,16
23 lxvx vs22,r5,r3
24 addi r5,r5,16
25 lxvx vs23,r5,r3
26 addi r5,r5,16
27 lxvx vs24,r5,r3
28 addi r5,r5,16
29 lxvx vs25,r5,r3
30 addi r5,r5,16
31 lxvx vs26,r5,r3
32 addi r5,r5,16
33 lxvx vs27,r5,r3
34 addi r5,r5,16
35 lxvx vs28,r5,r3
36 addi r5,r5,16
37 lxvx vs29,r5,r3
38 addi r5,r5,16
39 lxvx vs30,r5,r3
40 addi r5,r5,16
41 lxvx vs31,r5,r3
42 blr
43FUNC_END(load_vsx)
44
45FUNC_START(store_vsx)
46 li r5,0
47 stxvx vs20,r5,r3
48 addi r5,r5,16
49 stxvx vs21,r5,r3
50 addi r5,r5,16
51 stxvx vs22,r5,r3
52 addi r5,r5,16
53 stxvx vs23,r5,r3
54 addi r5,r5,16
55 stxvx vs24,r5,r3
56 addi r5,r5,16
57 stxvx vs25,r5,r3
58 addi r5,r5,16
59 stxvx vs26,r5,r3
60 addi r5,r5,16
61 stxvx vs27,r5,r3
62 addi r5,r5,16
63 stxvx vs28,r5,r3
64 addi r5,r5,16
65 stxvx vs29,r5,r3
66 addi r5,r5,16
67 stxvx vs30,r5,r3
68 addi r5,r5,16
69 stxvx vs31,r5,r3
70 blr
71FUNC_END(store_vsx)
diff --git a/tools/testing/selftests/x86/ptrace_syscall.c b/tools/testing/selftests/x86/ptrace_syscall.c
index 421456784bc6..b037ce9cf116 100644
--- a/tools/testing/selftests/x86/ptrace_syscall.c
+++ b/tools/testing/selftests/x86/ptrace_syscall.c
@@ -147,7 +147,7 @@ static void test_sys32_regs(void (*do_syscall)(struct syscall_args32 *))
147 if (args.nr != getpid() || 147 if (args.nr != getpid() ||
148 args.arg0 != 10 || args.arg1 != 11 || args.arg2 != 12 || 148 args.arg0 != 10 || args.arg1 != 11 || args.arg2 != 12 ||
149 args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) { 149 args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) {
150 printf("[FAIL]\tgetpid() failed to preseve regs\n"); 150 printf("[FAIL]\tgetpid() failed to preserve regs\n");
151 nerrs++; 151 nerrs++;
152 } else { 152 } else {
153 printf("[OK]\tgetpid() preserves regs\n"); 153 printf("[OK]\tgetpid() preserves regs\n");
@@ -162,7 +162,7 @@ static void test_sys32_regs(void (*do_syscall)(struct syscall_args32 *))
162 if (args.nr != 0 || 162 if (args.nr != 0 ||
163 args.arg0 != getpid() || args.arg1 != SIGUSR1 || args.arg2 != 12 || 163 args.arg0 != getpid() || args.arg1 != SIGUSR1 || args.arg2 != 12 ||
164 args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) { 164 args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) {
165 printf("[FAIL]\tkill(getpid(), SIGUSR1) failed to preseve regs\n"); 165 printf("[FAIL]\tkill(getpid(), SIGUSR1) failed to preserve regs\n");
166 nerrs++; 166 nerrs++;
167 } else { 167 } else {
168 printf("[OK]\tkill(getpid(), SIGUSR1) preserves regs\n"); 168 printf("[OK]\tkill(getpid(), SIGUSR1) preserves regs\n");
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c
index 8a577e7070c6..246145b84a12 100644
--- a/tools/testing/selftests/x86/sigreturn.c
+++ b/tools/testing/selftests/x86/sigreturn.c
@@ -106,7 +106,7 @@ asm (".pushsection .text\n\t"
106 ".type int3, @function\n\t" 106 ".type int3, @function\n\t"
107 ".align 4096\n\t" 107 ".align 4096\n\t"
108 "int3:\n\t" 108 "int3:\n\t"
109 "mov %ss,%eax\n\t" 109 "mov %ss,%ecx\n\t"
110 "int3\n\t" 110 "int3\n\t"
111 ".size int3, . - int3\n\t" 111 ".size int3, . - int3\n\t"
112 ".align 4096, 0xcc\n\t" 112 ".align 4096, 0xcc\n\t"
@@ -306,7 +306,7 @@ static volatile sig_atomic_t sig_corrupt_final_ss;
306#ifdef __x86_64__ 306#ifdef __x86_64__
307# define REG_IP REG_RIP 307# define REG_IP REG_RIP
308# define REG_SP REG_RSP 308# define REG_SP REG_RSP
309# define REG_AX REG_RAX 309# define REG_CX REG_RCX
310 310
311struct selectors { 311struct selectors {
312 unsigned short cs, gs, fs, ss; 312 unsigned short cs, gs, fs, ss;
@@ -326,7 +326,7 @@ static unsigned short *csptr(ucontext_t *ctx)
326#else 326#else
327# define REG_IP REG_EIP 327# define REG_IP REG_EIP
328# define REG_SP REG_ESP 328# define REG_SP REG_ESP
329# define REG_AX REG_EAX 329# define REG_CX REG_ECX
330 330
331static greg_t *ssptr(ucontext_t *ctx) 331static greg_t *ssptr(ucontext_t *ctx)
332{ 332{
@@ -457,10 +457,10 @@ static void sigusr1(int sig, siginfo_t *info, void *ctx_void)
457 ctx->uc_mcontext.gregs[REG_IP] = 457 ctx->uc_mcontext.gregs[REG_IP] =
458 sig_cs == code16_sel ? 0 : (unsigned long)&int3; 458 sig_cs == code16_sel ? 0 : (unsigned long)&int3;
459 ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL; 459 ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL;
460 ctx->uc_mcontext.gregs[REG_AX] = 0; 460 ctx->uc_mcontext.gregs[REG_CX] = 0;
461 461
462 memcpy(&requested_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t)); 462 memcpy(&requested_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
463 requested_regs[REG_AX] = *ssptr(ctx); /* The asm code does this. */ 463 requested_regs[REG_CX] = *ssptr(ctx); /* The asm code does this. */
464 464
465 return; 465 return;
466} 466}
@@ -482,7 +482,7 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
482 unsigned short ss; 482 unsigned short ss;
483 asm ("mov %%ss,%0" : "=r" (ss)); 483 asm ("mov %%ss,%0" : "=r" (ss));
484 484
485 greg_t asm_ss = ctx->uc_mcontext.gregs[REG_AX]; 485 greg_t asm_ss = ctx->uc_mcontext.gregs[REG_CX];
486 if (asm_ss != sig_ss && sig == SIGTRAP) { 486 if (asm_ss != sig_ss && sig == SIGTRAP) {
487 /* Sanity check failure. */ 487 /* Sanity check failure. */
488 printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n", 488 printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n",
@@ -654,8 +654,8 @@ static int test_valid_sigreturn(int cs_bits, bool use_16bit_ss, int force_ss)
654#endif 654#endif
655 655
656 /* Sanity check on the kernel */ 656 /* Sanity check on the kernel */
657 if (i == REG_AX && requested_regs[i] != resulting_regs[i]) { 657 if (i == REG_CX && requested_regs[i] != resulting_regs[i]) {
658 printf("[FAIL]\tAX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n", 658 printf("[FAIL]\tCX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n",
659 (unsigned long long)requested_regs[i], 659 (unsigned long long)requested_regs[i],
660 (unsigned long long)resulting_regs[i]); 660 (unsigned long long)resulting_regs[i]);
661 nerrs++; 661 nerrs++;