aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/trace/kprobetrace.txt9
-rw-r--r--Documentation/trace/uprobetracer.txt9
-rw-r--r--MAINTAINERS5
-rw-r--r--arch/x86/events/core.c24
-rw-r--r--arch/x86/events/intel/core.c31
-rw-r--r--arch/x86/events/intel/ds.c108
-rw-r--r--arch/x86/events/intel/lbr.c70
-rw-r--r--arch/x86/events/intel/pt.c24
-rw-r--r--arch/x86/events/intel/pt.h5
-rw-r--r--arch/x86/events/intel/rapl.c4
-rw-r--r--arch/x86/events/intel/uncore.c11
-rw-r--r--arch/x86/events/intel/uncore.h7
-rw-r--r--arch/x86/events/intel/uncore_snb.c2
-rw-r--r--arch/x86/events/intel/uncore_snbep.c626
-rw-r--r--arch/x86/events/perf_event.h13
-rw-r--r--include/linux/bitmap.h18
-rw-r--r--include/linux/perf_event.h24
-rw-r--r--kernel/events/core.c99
-rw-r--r--kernel/events/uprobes.c36
-rw-r--r--kernel/trace/trace.c24
-rw-r--r--kernel/trace/trace_kprobe.c4
-rw-r--r--kernel/trace/trace_probe.c30
-rw-r--r--kernel/trace/trace_probe.h11
-rw-r--r--kernel/trace/trace_uprobe.c4
-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/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/lib/api/fs/fs.c15
-rw-r--r--tools/lib/api/fs/fs.h1
-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
179 files changed, 6053 insertions, 988 deletions
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index ea52ec1f8484..e4991fb1eedc 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -44,8 +44,8 @@ Synopsis of kprobe_events
44 +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**) 44 +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
45 NAME=FETCHARG : Set NAME as the argument name of FETCHARG. 45 NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
46 FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types 46 FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
47 (u8/u16/u32/u64/s8/s16/s32/s64), "string" and bitfield 47 (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
48 are supported. 48 (x8/x16/x32/x64), "string" and bitfield are supported.
49 49
50 (*) only for return probe. 50 (*) only for return probe.
51 (**) this is useful for fetching a field of data structures. 51 (**) this is useful for fetching a field of data structures.
@@ -54,7 +54,10 @@ Types
54----- 54-----
55Several types are supported for fetch-args. Kprobe tracer will access memory 55Several types are supported for fetch-args. Kprobe tracer will access memory
56by given type. Prefix 's' and 'u' means those types are signed and unsigned 56by given type. Prefix 's' and 'u' means those types are signed and unsigned
57respectively. Traced arguments are shown in decimal (signed) or hex (unsigned). 57respectively. 'x' prefix implies it is unsigned. Traced arguments are shown
58in decimal ('s' and 'u') or hexadecimal ('x'). Without type casting, 'x32'
59or 'x64' is used depends on the architecture (e.g. x86-32 uses x32, and
60x86-64 uses x64).
58String type is a special type, which fetches a "null-terminated" string from 61String type is a special type, which fetches a "null-terminated" string from
59kernel space. This means it will fail and store NULL if the string container 62kernel space. This means it will fail and store NULL if the string container
60has been paged out. 63has been paged out.
diff --git a/Documentation/trace/uprobetracer.txt b/Documentation/trace/uprobetracer.txt
index 72d1cd4f7bf3..94b6b4581763 100644
--- a/Documentation/trace/uprobetracer.txt
+++ b/Documentation/trace/uprobetracer.txt
@@ -40,8 +40,8 @@ Synopsis of uprobe_tracer
40 +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**) 40 +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
41 NAME=FETCHARG : Set NAME as the argument name of FETCHARG. 41 NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
42 FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types 42 FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
43 (u8/u16/u32/u64/s8/s16/s32/s64), "string" and bitfield 43 (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types
44 are supported. 44 (x8/x16/x32/x64), "string" and bitfield are supported.
45 45
46 (*) only for return probe. 46 (*) only for return probe.
47 (**) this is useful for fetching a field of data structures. 47 (**) this is useful for fetching a field of data structures.
@@ -50,7 +50,10 @@ Types
50----- 50-----
51Several types are supported for fetch-args. Uprobe tracer will access memory 51Several types are supported for fetch-args. Uprobe tracer will access memory
52by given type. Prefix 's' and 'u' means those types are signed and unsigned 52by given type. Prefix 's' and 'u' means those types are signed and unsigned
53respectively. Traced arguments are shown in decimal (signed) or hex (unsigned). 53respectively. 'x' prefix implies it is unsigned. Traced arguments are shown
54in decimal ('s' and 'u') or hexadecimal ('x'). Without type casting, 'x32'
55or 'x64' is used depends on the architecture (e.g. x86-32 uses x32, and
56x86-64 uses x64).
54String type is a special type, which fetches a "null-terminated" string from 57String type is a special type, which fetches a "null-terminated" string from
55user space. 58user space.
56Bitfield is another special type, which takes 3 parameters, bit-width, bit- 59Bitfield is another special type, which takes 3 parameters, bit-width, bit-
diff --git a/MAINTAINERS b/MAINTAINERS
index 413b0da2620d..9a7a9c6cd64c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1125,6 +1125,11 @@ F: drivers/hwtracing/coresight/*
1125F: Documentation/trace/coresight.txt 1125F: Documentation/trace/coresight.txt
1126F: Documentation/devicetree/bindings/arm/coresight.txt 1126F: Documentation/devicetree/bindings/arm/coresight.txt
1127F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* 1127F: Documentation/ABI/testing/sysfs-bus-coresight-devices-*
1128F: tools/perf/arch/arm/util/pmu.c
1129F: tools/perf/arch/arm/util/auxtrace.c
1130F: tools/perf/arch/arm/util/cs-etm.c
1131F: tools/perf/arch/arm/util/cs-etm.h
1132F: tools/perf/util/cs-etm.h
1128 1133
1129ARM/CORGI MACHINE SUPPORT 1134ARM/CORGI MACHINE SUPPORT
1130M: Richard Purdie <rpurdie@rpsys.net> 1135M: Richard Purdie <rpurdie@rpsys.net>
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index d0efb5cb1b00..18a1acf86c90 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1201,6 +1201,9 @@ static int x86_pmu_add(struct perf_event *event, int flags)
1201 * If group events scheduling transaction was started, 1201 * If group events scheduling transaction was started,
1202 * skip the schedulability test here, it will be performed 1202 * skip the schedulability test here, it will be performed
1203 * at commit time (->commit_txn) as a whole. 1203 * at commit time (->commit_txn) as a whole.
1204 *
1205 * If commit fails, we'll call ->del() on all events
1206 * for which ->add() was called.
1204 */ 1207 */
1205 if (cpuc->txn_flags & PERF_PMU_TXN_ADD) 1208 if (cpuc->txn_flags & PERF_PMU_TXN_ADD)
1206 goto done_collect; 1209 goto done_collect;
@@ -1223,6 +1226,14 @@ done_collect:
1223 cpuc->n_added += n - n0; 1226 cpuc->n_added += n - n0;
1224 cpuc->n_txn += n - n0; 1227 cpuc->n_txn += n - n0;
1225 1228
1229 if (x86_pmu.add) {
1230 /*
1231 * This is before x86_pmu_enable() will call x86_pmu_start(),
1232 * so we enable LBRs before an event needs them etc..
1233 */
1234 x86_pmu.add(event);
1235 }
1236
1226 ret = 0; 1237 ret = 0;
1227out: 1238out:
1228 return ret; 1239 return ret;
@@ -1346,7 +1357,7 @@ static void x86_pmu_del(struct perf_event *event, int flags)
1346 event->hw.flags &= ~PERF_X86_EVENT_COMMITTED; 1357 event->hw.flags &= ~PERF_X86_EVENT_COMMITTED;
1347 1358
1348 /* 1359 /*
1349 * If we're called during a txn, we don't need to do anything. 1360 * If we're called during a txn, we only need to undo x86_pmu.add.
1350 * The events never got scheduled and ->cancel_txn will truncate 1361 * The events never got scheduled and ->cancel_txn will truncate
1351 * the event_list. 1362 * the event_list.
1352 * 1363 *
@@ -1354,7 +1365,7 @@ static void x86_pmu_del(struct perf_event *event, int flags)
1354 * an event added during that same TXN. 1365 * an event added during that same TXN.
1355 */ 1366 */
1356 if (cpuc->txn_flags & PERF_PMU_TXN_ADD) 1367 if (cpuc->txn_flags & PERF_PMU_TXN_ADD)
1357 return; 1368 goto do_del;
1358 1369
1359 /* 1370 /*
1360 * Not a TXN, therefore cleanup properly. 1371 * Not a TXN, therefore cleanup properly.
@@ -1384,6 +1395,15 @@ static void x86_pmu_del(struct perf_event *event, int flags)
1384 --cpuc->n_events; 1395 --cpuc->n_events;
1385 1396
1386 perf_event_update_userpage(event); 1397 perf_event_update_userpage(event);
1398
1399do_del:
1400 if (x86_pmu.del) {
1401 /*
1402 * This is after x86_pmu_stop(); so we disable LBRs after any
1403 * event can need them etc..
1404 */
1405 x86_pmu.del(event);
1406 }
1387} 1407}
1388 1408
1389int x86_pmu_handle_irq(struct pt_regs *regs) 1409int x86_pmu_handle_irq(struct pt_regs *regs)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 4c9a79b9cd69..a3a9eb84b5cf 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -1906,13 +1906,6 @@ static void intel_pmu_disable_event(struct perf_event *event)
1906 cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx); 1906 cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
1907 cpuc->intel_cp_status &= ~(1ull << hwc->idx); 1907 cpuc->intel_cp_status &= ~(1ull << hwc->idx);
1908 1908
1909 /*
1910 * must disable before any actual event
1911 * because any event may be combined with LBR
1912 */
1913 if (needs_branch_stack(event))
1914 intel_pmu_lbr_disable(event);
1915
1916 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { 1909 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
1917 intel_pmu_disable_fixed(hwc); 1910 intel_pmu_disable_fixed(hwc);
1918 return; 1911 return;
@@ -1924,6 +1917,14 @@ static void intel_pmu_disable_event(struct perf_event *event)
1924 intel_pmu_pebs_disable(event); 1917 intel_pmu_pebs_disable(event);
1925} 1918}
1926 1919
1920static void intel_pmu_del_event(struct perf_event *event)
1921{
1922 if (needs_branch_stack(event))
1923 intel_pmu_lbr_del(event);
1924 if (event->attr.precise_ip)
1925 intel_pmu_pebs_del(event);
1926}
1927
1927static void intel_pmu_enable_fixed(struct hw_perf_event *hwc) 1928static void intel_pmu_enable_fixed(struct hw_perf_event *hwc)
1928{ 1929{
1929 int idx = hwc->idx - INTEL_PMC_IDX_FIXED; 1930 int idx = hwc->idx - INTEL_PMC_IDX_FIXED;
@@ -1967,12 +1968,6 @@ static void intel_pmu_enable_event(struct perf_event *event)
1967 intel_pmu_enable_bts(hwc->config); 1968 intel_pmu_enable_bts(hwc->config);
1968 return; 1969 return;
1969 } 1970 }
1970 /*
1971 * must enabled before any actual event
1972 * because any event may be combined with LBR
1973 */
1974 if (needs_branch_stack(event))
1975 intel_pmu_lbr_enable(event);
1976 1971
1977 if (event->attr.exclude_host) 1972 if (event->attr.exclude_host)
1978 cpuc->intel_ctrl_guest_mask |= (1ull << hwc->idx); 1973 cpuc->intel_ctrl_guest_mask |= (1ull << hwc->idx);
@@ -1993,6 +1988,14 @@ static void intel_pmu_enable_event(struct perf_event *event)
1993 __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE); 1988 __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
1994} 1989}
1995 1990
1991static void intel_pmu_add_event(struct perf_event *event)
1992{
1993 if (event->attr.precise_ip)
1994 intel_pmu_pebs_add(event);
1995 if (needs_branch_stack(event))
1996 intel_pmu_lbr_add(event);
1997}
1998
1996/* 1999/*
1997 * Save and restart an expired event. Called by NMI contexts, 2000 * Save and restart an expired event. Called by NMI contexts,
1998 * so it has to be careful about preempting normal event ops: 2001 * so it has to be careful about preempting normal event ops:
@@ -3291,6 +3294,8 @@ static __initconst const struct x86_pmu intel_pmu = {
3291 .enable_all = intel_pmu_enable_all, 3294 .enable_all = intel_pmu_enable_all,
3292 .enable = intel_pmu_enable_event, 3295 .enable = intel_pmu_enable_event,
3293 .disable = intel_pmu_disable_event, 3296 .disable = intel_pmu_disable_event,
3297 .add = intel_pmu_add_event,
3298 .del = intel_pmu_del_event,
3294 .hw_config = intel_pmu_hw_config, 3299 .hw_config = intel_pmu_hw_config,
3295 .schedule_events = x86_schedule_events, 3300 .schedule_events = x86_schedule_events,
3296 .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, 3301 .eventsel = MSR_ARCH_PERFMON_EVENTSEL0,
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index 9b983a474253..0319311dbdbb 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -806,9 +806,65 @@ struct event_constraint *intel_pebs_constraints(struct perf_event *event)
806 return &emptyconstraint; 806 return &emptyconstraint;
807} 807}
808 808
809static inline bool pebs_is_enabled(struct cpu_hw_events *cpuc) 809/*
810 * We need the sched_task callback even for per-cpu events when we use
811 * the large interrupt threshold, such that we can provide PID and TID
812 * to PEBS samples.
813 */
814static inline bool pebs_needs_sched_cb(struct cpu_hw_events *cpuc)
815{
816 return cpuc->n_pebs && (cpuc->n_pebs == cpuc->n_large_pebs);
817}
818
819static inline void pebs_update_threshold(struct cpu_hw_events *cpuc)
820{
821 struct debug_store *ds = cpuc->ds;
822 u64 threshold;
823
824 if (cpuc->n_pebs == cpuc->n_large_pebs) {
825 threshold = ds->pebs_absolute_maximum -
826 x86_pmu.max_pebs_events * x86_pmu.pebs_record_size;
827 } else {
828 threshold = ds->pebs_buffer_base + x86_pmu.pebs_record_size;
829 }
830
831 ds->pebs_interrupt_threshold = threshold;
832}
833
834static void
835pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc, struct pmu *pmu)
836{
837 /*
838 * Make sure we get updated with the first PEBS
839 * event. It will trigger also during removal, but
840 * that does not hurt:
841 */
842 bool update = cpuc->n_pebs == 1;
843
844 if (needed_cb != pebs_needs_sched_cb(cpuc)) {
845 if (!needed_cb)
846 perf_sched_cb_inc(pmu);
847 else
848 perf_sched_cb_dec(pmu);
849
850 update = true;
851 }
852
853 if (update)
854 pebs_update_threshold(cpuc);
855}
856
857void intel_pmu_pebs_add(struct perf_event *event)
810{ 858{
811 return (cpuc->pebs_enabled & ((1ULL << MAX_PEBS_EVENTS) - 1)); 859 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
860 struct hw_perf_event *hwc = &event->hw;
861 bool needed_cb = pebs_needs_sched_cb(cpuc);
862
863 cpuc->n_pebs++;
864 if (hwc->flags & PERF_X86_EVENT_FREERUNNING)
865 cpuc->n_large_pebs++;
866
867 pebs_update_state(needed_cb, cpuc, event->ctx->pmu);
812} 868}
813 869
814void intel_pmu_pebs_enable(struct perf_event *event) 870void intel_pmu_pebs_enable(struct perf_event *event)
@@ -816,12 +872,9 @@ void intel_pmu_pebs_enable(struct perf_event *event)
816 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 872 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
817 struct hw_perf_event *hwc = &event->hw; 873 struct hw_perf_event *hwc = &event->hw;
818 struct debug_store *ds = cpuc->ds; 874 struct debug_store *ds = cpuc->ds;
819 bool first_pebs;
820 u64 threshold;
821 875
822 hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT; 876 hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT;
823 877
824 first_pebs = !pebs_is_enabled(cpuc);
825 cpuc->pebs_enabled |= 1ULL << hwc->idx; 878 cpuc->pebs_enabled |= 1ULL << hwc->idx;
826 879
827 if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT) 880 if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT)
@@ -830,46 +883,34 @@ void intel_pmu_pebs_enable(struct perf_event *event)
830 cpuc->pebs_enabled |= 1ULL << 63; 883 cpuc->pebs_enabled |= 1ULL << 63;
831 884
832 /* 885 /*
833 * When the event is constrained enough we can use a larger 886 * Use auto-reload if possible to save a MSR write in the PMI.
834 * threshold and run the event with less frequent PMI. 887 * This must be done in pmu::start(), because PERF_EVENT_IOC_PERIOD.
835 */ 888 */
836 if (hwc->flags & PERF_X86_EVENT_FREERUNNING) {
837 threshold = ds->pebs_absolute_maximum -
838 x86_pmu.max_pebs_events * x86_pmu.pebs_record_size;
839
840 if (first_pebs)
841 perf_sched_cb_inc(event->ctx->pmu);
842 } else {
843 threshold = ds->pebs_buffer_base + x86_pmu.pebs_record_size;
844
845 /*
846 * If not all events can use larger buffer,
847 * roll back to threshold = 1
848 */
849 if (!first_pebs &&
850 (ds->pebs_interrupt_threshold > threshold))
851 perf_sched_cb_dec(event->ctx->pmu);
852 }
853
854 /* Use auto-reload if possible to save a MSR write in the PMI */
855 if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) { 889 if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) {
856 ds->pebs_event_reset[hwc->idx] = 890 ds->pebs_event_reset[hwc->idx] =
857 (u64)(-hwc->sample_period) & x86_pmu.cntval_mask; 891 (u64)(-hwc->sample_period) & x86_pmu.cntval_mask;
858 } 892 }
893}
894
895void intel_pmu_pebs_del(struct perf_event *event)
896{
897 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
898 struct hw_perf_event *hwc = &event->hw;
899 bool needed_cb = pebs_needs_sched_cb(cpuc);
859 900
860 if (first_pebs || ds->pebs_interrupt_threshold > threshold) 901 cpuc->n_pebs--;
861 ds->pebs_interrupt_threshold = threshold; 902 if (hwc->flags & PERF_X86_EVENT_FREERUNNING)
903 cpuc->n_large_pebs--;
904
905 pebs_update_state(needed_cb, cpuc, event->ctx->pmu);
862} 906}
863 907
864void intel_pmu_pebs_disable(struct perf_event *event) 908void intel_pmu_pebs_disable(struct perf_event *event)
865{ 909{
866 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 910 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
867 struct hw_perf_event *hwc = &event->hw; 911 struct hw_perf_event *hwc = &event->hw;
868 struct debug_store *ds = cpuc->ds;
869 bool large_pebs = ds->pebs_interrupt_threshold >
870 ds->pebs_buffer_base + x86_pmu.pebs_record_size;
871 912
872 if (large_pebs) 913 if (cpuc->n_pebs == cpuc->n_large_pebs)
873 intel_pmu_drain_pebs_buffer(); 914 intel_pmu_drain_pebs_buffer();
874 915
875 cpuc->pebs_enabled &= ~(1ULL << hwc->idx); 916 cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
@@ -879,9 +920,6 @@ void intel_pmu_pebs_disable(struct perf_event *event)
879 else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST) 920 else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
880 cpuc->pebs_enabled &= ~(1ULL << 63); 921 cpuc->pebs_enabled &= ~(1ULL << 63);
881 922
882 if (large_pebs && !pebs_is_enabled(cpuc))
883 perf_sched_cb_dec(event->ctx->pmu);
884
885 if (cpuc->enabled) 923 if (cpuc->enabled)
886 wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); 924 wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled);
887 925
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index 707d358e0dff..fc6cf21c535e 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -380,7 +380,6 @@ static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
380 380
381void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in) 381void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
382{ 382{
383 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
384 struct x86_perf_task_context *task_ctx; 383 struct x86_perf_task_context *task_ctx;
385 384
386 /* 385 /*
@@ -390,31 +389,21 @@ void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
390 */ 389 */
391 task_ctx = ctx ? ctx->task_ctx_data : NULL; 390 task_ctx = ctx ? ctx->task_ctx_data : NULL;
392 if (task_ctx) { 391 if (task_ctx) {
393 if (sched_in) { 392 if (sched_in)
394 __intel_pmu_lbr_restore(task_ctx); 393 __intel_pmu_lbr_restore(task_ctx);
395 cpuc->lbr_context = ctx; 394 else
396 } else {
397 __intel_pmu_lbr_save(task_ctx); 395 __intel_pmu_lbr_save(task_ctx);
398 }
399 return; 396 return;
400 } 397 }
401 398
402 /* 399 /*
403 * When sampling the branck stack in system-wide, it may be 400 * Since a context switch can flip the address space and LBR entries
404 * necessary to flush the stack on context switch. This happens 401 * are not tagged with an identifier, we need to wipe the LBR, even for
405 * when the branch stack does not tag its entries with the pid 402 * per-cpu events. You simply cannot resolve the branches from the old
406 * of the current task. Otherwise it becomes impossible to 403 * address space.
407 * associate a branch entry with a task. This ambiguity is more 404 */
408 * likely to appear when the branch stack supports priv level 405 if (sched_in)
409 * filtering and the user sets it to monitor only at the user
410 * level (which could be a useful measurement in system-wide
411 * mode). In that case, the risk is high of having a branch
412 * stack with branch from multiple tasks.
413 */
414 if (sched_in) {
415 intel_pmu_lbr_reset(); 406 intel_pmu_lbr_reset();
416 cpuc->lbr_context = ctx;
417 }
418} 407}
419 408
420static inline bool branch_user_callstack(unsigned br_sel) 409static inline bool branch_user_callstack(unsigned br_sel)
@@ -422,7 +411,7 @@ static inline bool branch_user_callstack(unsigned br_sel)
422 return (br_sel & X86_BR_USER) && (br_sel & X86_BR_CALL_STACK); 411 return (br_sel & X86_BR_USER) && (br_sel & X86_BR_CALL_STACK);
423} 412}
424 413
425void intel_pmu_lbr_enable(struct perf_event *event) 414void intel_pmu_lbr_add(struct perf_event *event)
426{ 415{
427 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 416 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
428 struct x86_perf_task_context *task_ctx; 417 struct x86_perf_task_context *task_ctx;
@@ -430,27 +419,38 @@ void intel_pmu_lbr_enable(struct perf_event *event)
430 if (!x86_pmu.lbr_nr) 419 if (!x86_pmu.lbr_nr)
431 return; 420 return;
432 421
433 /*
434 * Reset the LBR stack if we changed task context to
435 * avoid data leaks.
436 */
437 if (event->ctx->task && cpuc->lbr_context != event->ctx) {
438 intel_pmu_lbr_reset();
439 cpuc->lbr_context = event->ctx;
440 }
441 cpuc->br_sel = event->hw.branch_reg.reg; 422 cpuc->br_sel = event->hw.branch_reg.reg;
442 423
443 if (branch_user_callstack(cpuc->br_sel) && event->ctx && 424 if (branch_user_callstack(cpuc->br_sel) && event->ctx->task_ctx_data) {
444 event->ctx->task_ctx_data) {
445 task_ctx = event->ctx->task_ctx_data; 425 task_ctx = event->ctx->task_ctx_data;
446 task_ctx->lbr_callstack_users++; 426 task_ctx->lbr_callstack_users++;
447 } 427 }
448 428
449 cpuc->lbr_users++; 429 /*
430 * Request pmu::sched_task() callback, which will fire inside the
431 * regular perf event scheduling, so that call will:
432 *
433 * - restore or wipe; when LBR-callstack,
434 * - wipe; otherwise,
435 *
436 * when this is from __perf_event_task_sched_in().
437 *
438 * However, if this is from perf_install_in_context(), no such callback
439 * will follow and we'll need to reset the LBR here if this is the
440 * first LBR event.
441 *
442 * The problem is, we cannot tell these cases apart... but we can
443 * exclude the biggest chunk of cases by looking at
444 * event->total_time_running. An event that has accrued runtime cannot
445 * be 'new'. Conversely, a new event can get installed through the
446 * context switch path for the first time.
447 */
450 perf_sched_cb_inc(event->ctx->pmu); 448 perf_sched_cb_inc(event->ctx->pmu);
449 if (!cpuc->lbr_users++ && !event->total_time_running)
450 intel_pmu_lbr_reset();
451} 451}
452 452
453void intel_pmu_lbr_disable(struct perf_event *event) 453void intel_pmu_lbr_del(struct perf_event *event)
454{ 454{
455 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); 455 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
456 struct x86_perf_task_context *task_ctx; 456 struct x86_perf_task_context *task_ctx;
@@ -467,12 +467,6 @@ void intel_pmu_lbr_disable(struct perf_event *event)
467 cpuc->lbr_users--; 467 cpuc->lbr_users--;
468 WARN_ON_ONCE(cpuc->lbr_users < 0); 468 WARN_ON_ONCE(cpuc->lbr_users < 0);
469 perf_sched_cb_dec(event->ctx->pmu); 469 perf_sched_cb_dec(event->ctx->pmu);
470
471 if (cpuc->enabled && !cpuc->lbr_users) {
472 __intel_pmu_lbr_disable();
473 /* avoid stale pointer */
474 cpuc->lbr_context = NULL;
475 }
476} 470}
477 471
478void intel_pmu_lbr_enable_all(bool pmi) 472void intel_pmu_lbr_enable_all(bool pmi)
diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 861a7d9cb60f..c5047b8f777b 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -69,6 +69,8 @@ static struct pt_cap_desc {
69 PT_CAP(psb_cyc, 0, CR_EBX, BIT(1)), 69 PT_CAP(psb_cyc, 0, CR_EBX, BIT(1)),
70 PT_CAP(ip_filtering, 0, CR_EBX, BIT(2)), 70 PT_CAP(ip_filtering, 0, CR_EBX, BIT(2)),
71 PT_CAP(mtc, 0, CR_EBX, BIT(3)), 71 PT_CAP(mtc, 0, CR_EBX, BIT(3)),
72 PT_CAP(ptwrite, 0, CR_EBX, BIT(4)),
73 PT_CAP(power_event_trace, 0, CR_EBX, BIT(5)),
72 PT_CAP(topa_output, 0, CR_ECX, BIT(0)), 74 PT_CAP(topa_output, 0, CR_ECX, BIT(0)),
73 PT_CAP(topa_multiple_entries, 0, CR_ECX, BIT(1)), 75 PT_CAP(topa_multiple_entries, 0, CR_ECX, BIT(1)),
74 PT_CAP(single_range_output, 0, CR_ECX, BIT(2)), 76 PT_CAP(single_range_output, 0, CR_ECX, BIT(2)),
@@ -259,10 +261,16 @@ fail:
259#define RTIT_CTL_MTC (RTIT_CTL_MTC_EN | \ 261#define RTIT_CTL_MTC (RTIT_CTL_MTC_EN | \
260 RTIT_CTL_MTC_RANGE) 262 RTIT_CTL_MTC_RANGE)
261 263
264#define RTIT_CTL_PTW (RTIT_CTL_PTW_EN | \
265 RTIT_CTL_FUP_ON_PTW)
266
262#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN | \ 267#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN | \
263 RTIT_CTL_DISRETC | \ 268 RTIT_CTL_DISRETC | \
264 RTIT_CTL_CYC_PSB | \ 269 RTIT_CTL_CYC_PSB | \
265 RTIT_CTL_MTC) 270 RTIT_CTL_MTC | \
271 RTIT_CTL_PWR_EVT_EN | \
272 RTIT_CTL_FUP_ON_PTW | \
273 RTIT_CTL_PTW_EN)
266 274
267static bool pt_event_valid(struct perf_event *event) 275static bool pt_event_valid(struct perf_event *event)
268{ 276{
@@ -311,6 +319,20 @@ static bool pt_event_valid(struct perf_event *event)
311 return false; 319 return false;
312 } 320 }
313 321
322 if (config & RTIT_CTL_PWR_EVT_EN &&
323 !pt_cap_get(PT_CAP_power_event_trace))
324 return false;
325
326 if (config & RTIT_CTL_PTW) {
327 if (!pt_cap_get(PT_CAP_ptwrite))
328 return false;
329
330 /* FUPonPTW without PTW doesn't make sense */
331 if ((config & RTIT_CTL_FUP_ON_PTW) &&
332 !(config & RTIT_CTL_PTW_EN))
333 return false;
334 }
335
314 return true; 336 return true;
315} 337}
316 338
diff --git a/arch/x86/events/intel/pt.h b/arch/x86/events/intel/pt.h
index efffa4a09f68..53473c21b554 100644
--- a/arch/x86/events/intel/pt.h
+++ b/arch/x86/events/intel/pt.h
@@ -26,11 +26,14 @@
26#define RTIT_CTL_CYCLEACC BIT(1) 26#define RTIT_CTL_CYCLEACC BIT(1)
27#define RTIT_CTL_OS BIT(2) 27#define RTIT_CTL_OS BIT(2)
28#define RTIT_CTL_USR BIT(3) 28#define RTIT_CTL_USR BIT(3)
29#define RTIT_CTL_PWR_EVT_EN BIT(4)
30#define RTIT_CTL_FUP_ON_PTW BIT(5)
29#define RTIT_CTL_CR3EN BIT(7) 31#define RTIT_CTL_CR3EN BIT(7)
30#define RTIT_CTL_TOPA BIT(8) 32#define RTIT_CTL_TOPA BIT(8)
31#define RTIT_CTL_MTC_EN BIT(9) 33#define RTIT_CTL_MTC_EN BIT(9)
32#define RTIT_CTL_TSC_EN BIT(10) 34#define RTIT_CTL_TSC_EN BIT(10)
33#define RTIT_CTL_DISRETC BIT(11) 35#define RTIT_CTL_DISRETC BIT(11)
36#define RTIT_CTL_PTW_EN BIT(12)
34#define RTIT_CTL_BRANCH_EN BIT(13) 37#define RTIT_CTL_BRANCH_EN BIT(13)
35#define RTIT_CTL_MTC_RANGE_OFFSET 14 38#define RTIT_CTL_MTC_RANGE_OFFSET 14
36#define RTIT_CTL_MTC_RANGE (0x0full << RTIT_CTL_MTC_RANGE_OFFSET) 39#define RTIT_CTL_MTC_RANGE (0x0full << RTIT_CTL_MTC_RANGE_OFFSET)
@@ -91,6 +94,8 @@ enum pt_capabilities {
91 PT_CAP_psb_cyc, 94 PT_CAP_psb_cyc,
92 PT_CAP_ip_filtering, 95 PT_CAP_ip_filtering,
93 PT_CAP_mtc, 96 PT_CAP_mtc,
97 PT_CAP_ptwrite,
98 PT_CAP_power_event_trace,
94 PT_CAP_topa_output, 99 PT_CAP_topa_output,
95 PT_CAP_topa_multiple_entries, 100 PT_CAP_topa_multiple_entries,
96 PT_CAP_single_range_output, 101 PT_CAP_single_range_output,
diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
index 28865938aadf..b0f0e835a770 100644
--- a/arch/x86/events/intel/rapl.c
+++ b/arch/x86/events/intel/rapl.c
@@ -357,6 +357,8 @@ static int rapl_pmu_event_init(struct perf_event *event)
357 if (event->cpu < 0) 357 if (event->cpu < 0)
358 return -EINVAL; 358 return -EINVAL;
359 359
360 event->event_caps |= PERF_EV_CAP_READ_ACTIVE_PKG;
361
360 /* 362 /*
361 * check event is known (determines counter) 363 * check event is known (determines counter)
362 */ 364 */
@@ -765,6 +767,8 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
765 X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_rapl_init), 767 X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_rapl_init),
766 X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP, skl_rapl_init), 768 X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP, skl_rapl_init),
767 X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, hsx_rapl_init), 769 X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, hsx_rapl_init),
770
771 X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT, hsw_rapl_init),
768 {}, 772 {},
769}; 773};
770 774
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index 463dc7a5a6c3..d9844cc74486 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -664,6 +664,8 @@ static int uncore_pmu_event_init(struct perf_event *event)
664 event->cpu = box->cpu; 664 event->cpu = box->cpu;
665 event->pmu_private = box; 665 event->pmu_private = box;
666 666
667 event->event_caps |= PERF_EV_CAP_READ_ACTIVE_PKG;
668
667 event->hw.idx = -1; 669 event->hw.idx = -1;
668 event->hw.last_tag = ~0ULL; 670 event->hw.last_tag = ~0ULL;
669 event->hw.extra_reg.idx = EXTRA_REG_NONE; 671 event->hw.extra_reg.idx = EXTRA_REG_NONE;
@@ -683,7 +685,8 @@ static int uncore_pmu_event_init(struct perf_event *event)
683 /* fixed counters have event field hardcoded to zero */ 685 /* fixed counters have event field hardcoded to zero */
684 hwc->config = 0ULL; 686 hwc->config = 0ULL;
685 } else { 687 } else {
686 hwc->config = event->attr.config & pmu->type->event_mask; 688 hwc->config = event->attr.config &
689 (pmu->type->event_mask | ((u64)pmu->type->event_mask_ext << 32));
687 if (pmu->type->ops->hw_config) { 690 if (pmu->type->ops->hw_config) {
688 ret = pmu->type->ops->hw_config(box, event); 691 ret = pmu->type->ops->hw_config(box, event);
689 if (ret) 692 if (ret)
@@ -1321,6 +1324,11 @@ static const struct intel_uncore_init_fun skl_uncore_init __initconst = {
1321 .pci_init = skl_uncore_pci_init, 1324 .pci_init = skl_uncore_pci_init,
1322}; 1325};
1323 1326
1327static const struct intel_uncore_init_fun skx_uncore_init __initconst = {
1328 .cpu_init = skx_uncore_cpu_init,
1329 .pci_init = skx_uncore_pci_init,
1330};
1331
1324static const struct x86_cpu_id intel_uncore_match[] __initconst = { 1332static const struct x86_cpu_id intel_uncore_match[] __initconst = {
1325 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_NEHALEM_EP, nhm_uncore_init), 1333 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_NEHALEM_EP, nhm_uncore_init),
1326 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_NEHALEM, nhm_uncore_init), 1334 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_NEHALEM, nhm_uncore_init),
@@ -1343,6 +1351,7 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = {
1343 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_uncore_init), 1351 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_uncore_init),
1344 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP,skl_uncore_init), 1352 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP,skl_uncore_init),
1345 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_uncore_init), 1353 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_uncore_init),
1354 X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, skx_uncore_init),
1346 {}, 1355 {},
1347}; 1356};
1348 1357
diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index 78b9c23e2d8d..ad986c1e29bc 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -44,6 +44,7 @@ struct intel_uncore_type {
44 unsigned perf_ctr; 44 unsigned perf_ctr;
45 unsigned event_ctl; 45 unsigned event_ctl;
46 unsigned event_mask; 46 unsigned event_mask;
47 unsigned event_mask_ext;
47 unsigned fixed_ctr; 48 unsigned fixed_ctr;
48 unsigned fixed_ctl; 49 unsigned fixed_ctl;
49 unsigned box_ctl; 50 unsigned box_ctl;
@@ -120,6 +121,7 @@ struct intel_uncore_box {
120}; 121};
121 122
122#define UNCORE_BOX_FLAG_INITIATED 0 123#define UNCORE_BOX_FLAG_INITIATED 0
124#define UNCORE_BOX_FLAG_CTL_OFFS8 1 /* event config registers are 8-byte apart */
123 125
124struct uncore_event_desc { 126struct uncore_event_desc {
125 struct kobj_attribute attr; 127 struct kobj_attribute attr;
@@ -172,6 +174,9 @@ static inline unsigned uncore_pci_fixed_ctr(struct intel_uncore_box *box)
172static inline 174static inline
173unsigned uncore_pci_event_ctl(struct intel_uncore_box *box, int idx) 175unsigned uncore_pci_event_ctl(struct intel_uncore_box *box, int idx)
174{ 176{
177 if (test_bit(UNCORE_BOX_FLAG_CTL_OFFS8, &box->flags))
178 return idx * 8 + box->pmu->type->event_ctl;
179
175 return idx * 4 + box->pmu->type->event_ctl; 180 return idx * 4 + box->pmu->type->event_ctl;
176} 181}
177 182
@@ -377,6 +382,8 @@ int bdx_uncore_pci_init(void);
377void bdx_uncore_cpu_init(void); 382void bdx_uncore_cpu_init(void);
378int knl_uncore_pci_init(void); 383int knl_uncore_pci_init(void);
379void knl_uncore_cpu_init(void); 384void knl_uncore_cpu_init(void);
385int skx_uncore_pci_init(void);
386void skx_uncore_cpu_init(void);
380 387
381/* perf_event_intel_uncore_nhmex.c */ 388/* perf_event_intel_uncore_nhmex.c */
382void nhmex_uncore_cpu_init(void); 389void nhmex_uncore_cpu_init(void);
diff --git a/arch/x86/events/intel/uncore_snb.c b/arch/x86/events/intel/uncore_snb.c
index 9d35ec0cb8fc..5f845eef9a4d 100644
--- a/arch/x86/events/intel/uncore_snb.c
+++ b/arch/x86/events/intel/uncore_snb.c
@@ -388,6 +388,8 @@ static int snb_uncore_imc_event_init(struct perf_event *event)
388 event->cpu = box->cpu; 388 event->cpu = box->cpu;
389 event->pmu_private = box; 389 event->pmu_private = box;
390 390
391 event->event_caps |= PERF_EV_CAP_READ_ACTIVE_PKG;
392
391 event->hw.idx = -1; 393 event->hw.idx = -1;
392 event->hw.last_tag = ~0ULL; 394 event->hw.last_tag = ~0ULL;
393 event->hw.extra_reg.idx = EXTRA_REG_NONE; 395 event->hw.extra_reg.idx = EXTRA_REG_NONE;
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 8aee83bcf71f..272427700d48 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -1,6 +1,10 @@
1/* SandyBridge-EP/IvyTown uncore support */ 1/* SandyBridge-EP/IvyTown uncore support */
2#include "uncore.h" 2#include "uncore.h"
3 3
4/* SNB-EP pci bus to socket mapping */
5#define SNBEP_CPUNODEID 0x40
6#define SNBEP_GIDNIDMAP 0x54
7
4/* SNB-EP Box level control */ 8/* SNB-EP Box level control */
5#define SNBEP_PMON_BOX_CTL_RST_CTRL (1 << 0) 9#define SNBEP_PMON_BOX_CTL_RST_CTRL (1 << 0)
6#define SNBEP_PMON_BOX_CTL_RST_CTRS (1 << 1) 10#define SNBEP_PMON_BOX_CTL_RST_CTRS (1 << 1)
@@ -264,15 +268,72 @@
264 SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \ 268 SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
265 SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET) 269 SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
266 270
271/* SKX pci bus to socket mapping */
272#define SKX_CPUNODEID 0xc0
273#define SKX_GIDNIDMAP 0xd4
274
275/* SKX CHA */
276#define SKX_CHA_MSR_PMON_BOX_FILTER_TID (0x1ffULL << 0)
277#define SKX_CHA_MSR_PMON_BOX_FILTER_LINK (0xfULL << 9)
278#define SKX_CHA_MSR_PMON_BOX_FILTER_STATE (0x3ffULL << 17)
279#define SKX_CHA_MSR_PMON_BOX_FILTER_REM (0x1ULL << 32)
280#define SKX_CHA_MSR_PMON_BOX_FILTER_LOC (0x1ULL << 33)
281#define SKX_CHA_MSR_PMON_BOX_FILTER_ALL_OPC (0x1ULL << 35)
282#define SKX_CHA_MSR_PMON_BOX_FILTER_NM (0x1ULL << 36)
283#define SKX_CHA_MSR_PMON_BOX_FILTER_NOT_NM (0x1ULL << 37)
284#define SKX_CHA_MSR_PMON_BOX_FILTER_OPC0 (0x3ffULL << 41)
285#define SKX_CHA_MSR_PMON_BOX_FILTER_OPC1 (0x3ffULL << 51)
286#define SKX_CHA_MSR_PMON_BOX_FILTER_C6 (0x1ULL << 61)
287#define SKX_CHA_MSR_PMON_BOX_FILTER_NC (0x1ULL << 62)
288#define SKX_CHA_MSR_PMON_BOX_FILTER_ISOC (0x1ULL << 63)
289
290/* SKX IIO */
291#define SKX_IIO0_MSR_PMON_CTL0 0xa48
292#define SKX_IIO0_MSR_PMON_CTR0 0xa41
293#define SKX_IIO0_MSR_PMON_BOX_CTL 0xa40
294#define SKX_IIO_MSR_OFFSET 0x20
295
296#define SKX_PMON_CTL_TRESH_MASK (0xff << 24)
297#define SKX_PMON_CTL_TRESH_MASK_EXT (0xf)
298#define SKX_PMON_CTL_CH_MASK (0xff << 4)
299#define SKX_PMON_CTL_FC_MASK (0x7 << 12)
300#define SKX_IIO_PMON_RAW_EVENT_MASK (SNBEP_PMON_CTL_EV_SEL_MASK | \
301 SNBEP_PMON_CTL_UMASK_MASK | \
302 SNBEP_PMON_CTL_EDGE_DET | \
303 SNBEP_PMON_CTL_INVERT | \
304 SKX_PMON_CTL_TRESH_MASK)
305#define SKX_IIO_PMON_RAW_EVENT_MASK_EXT (SKX_PMON_CTL_TRESH_MASK_EXT | \
306 SKX_PMON_CTL_CH_MASK | \
307 SKX_PMON_CTL_FC_MASK)
308
309/* SKX IRP */
310#define SKX_IRP0_MSR_PMON_CTL0 0xa5b
311#define SKX_IRP0_MSR_PMON_CTR0 0xa59
312#define SKX_IRP0_MSR_PMON_BOX_CTL 0xa58
313#define SKX_IRP_MSR_OFFSET 0x20
314
315/* SKX UPI */
316#define SKX_UPI_PCI_PMON_CTL0 0x350
317#define SKX_UPI_PCI_PMON_CTR0 0x318
318#define SKX_UPI_PCI_PMON_BOX_CTL 0x378
319#define SKX_PMON_CTL_UMASK_EXT 0xff
320
321/* SKX M2M */
322#define SKX_M2M_PCI_PMON_CTL0 0x228
323#define SKX_M2M_PCI_PMON_CTR0 0x200
324#define SKX_M2M_PCI_PMON_BOX_CTL 0x258
325
267DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7"); 326DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
268DEFINE_UNCORE_FORMAT_ATTR(event2, event, "config:0-6"); 327DEFINE_UNCORE_FORMAT_ATTR(event2, event, "config:0-6");
269DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21"); 328DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21");
270DEFINE_UNCORE_FORMAT_ATTR(use_occ_ctr, use_occ_ctr, "config:7"); 329DEFINE_UNCORE_FORMAT_ATTR(use_occ_ctr, use_occ_ctr, "config:7");
271DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15"); 330DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
331DEFINE_UNCORE_FORMAT_ATTR(umask_ext, umask, "config:8-15,32-39");
272DEFINE_UNCORE_FORMAT_ATTR(qor, qor, "config:16"); 332DEFINE_UNCORE_FORMAT_ATTR(qor, qor, "config:16");
273DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18"); 333DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
274DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19"); 334DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19");
275DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23"); 335DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
336DEFINE_UNCORE_FORMAT_ATTR(thresh9, thresh, "config:24-35");
276DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31"); 337DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
277DEFINE_UNCORE_FORMAT_ATTR(thresh6, thresh, "config:24-29"); 338DEFINE_UNCORE_FORMAT_ATTR(thresh6, thresh, "config:24-29");
278DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28"); 339DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28");
@@ -280,6 +341,8 @@ DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15");
280DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30"); 341DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30");
281DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51"); 342DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51");
282DEFINE_UNCORE_FORMAT_ATTR(occ_edge_det, occ_edge_det, "config:31"); 343DEFINE_UNCORE_FORMAT_ATTR(occ_edge_det, occ_edge_det, "config:31");
344DEFINE_UNCORE_FORMAT_ATTR(ch_mask, ch_mask, "config:36-43");
345DEFINE_UNCORE_FORMAT_ATTR(fc_mask, fc_mask, "config:44-46");
283DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4"); 346DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4");
284DEFINE_UNCORE_FORMAT_ATTR(filter_tid2, filter_tid, "config1:0"); 347DEFINE_UNCORE_FORMAT_ATTR(filter_tid2, filter_tid, "config1:0");
285DEFINE_UNCORE_FORMAT_ATTR(filter_tid3, filter_tid, "config1:0-5"); 348DEFINE_UNCORE_FORMAT_ATTR(filter_tid3, filter_tid, "config1:0-5");
@@ -288,18 +351,26 @@ DEFINE_UNCORE_FORMAT_ATTR(filter_cid, filter_cid, "config1:5");
288DEFINE_UNCORE_FORMAT_ATTR(filter_link, filter_link, "config1:5-8"); 351DEFINE_UNCORE_FORMAT_ATTR(filter_link, filter_link, "config1:5-8");
289DEFINE_UNCORE_FORMAT_ATTR(filter_link2, filter_link, "config1:6-8"); 352DEFINE_UNCORE_FORMAT_ATTR(filter_link2, filter_link, "config1:6-8");
290DEFINE_UNCORE_FORMAT_ATTR(filter_link3, filter_link, "config1:12"); 353DEFINE_UNCORE_FORMAT_ATTR(filter_link3, filter_link, "config1:12");
354DEFINE_UNCORE_FORMAT_ATTR(filter_link4, filter_link, "config1:9-12");
291DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17"); 355DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17");
292DEFINE_UNCORE_FORMAT_ATTR(filter_nid2, filter_nid, "config1:32-47"); 356DEFINE_UNCORE_FORMAT_ATTR(filter_nid2, filter_nid, "config1:32-47");
293DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22"); 357DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22");
294DEFINE_UNCORE_FORMAT_ATTR(filter_state2, filter_state, "config1:17-22"); 358DEFINE_UNCORE_FORMAT_ATTR(filter_state2, filter_state, "config1:17-22");
295DEFINE_UNCORE_FORMAT_ATTR(filter_state3, filter_state, "config1:17-23"); 359DEFINE_UNCORE_FORMAT_ATTR(filter_state3, filter_state, "config1:17-23");
296DEFINE_UNCORE_FORMAT_ATTR(filter_state4, filter_state, "config1:18-20"); 360DEFINE_UNCORE_FORMAT_ATTR(filter_state4, filter_state, "config1:18-20");
361DEFINE_UNCORE_FORMAT_ATTR(filter_state5, filter_state, "config1:17-26");
362DEFINE_UNCORE_FORMAT_ATTR(filter_rem, filter_rem, "config1:32");
363DEFINE_UNCORE_FORMAT_ATTR(filter_loc, filter_loc, "config1:33");
364DEFINE_UNCORE_FORMAT_ATTR(filter_nm, filter_nm, "config1:36");
365DEFINE_UNCORE_FORMAT_ATTR(filter_not_nm, filter_not_nm, "config1:37");
297DEFINE_UNCORE_FORMAT_ATTR(filter_local, filter_local, "config1:33"); 366DEFINE_UNCORE_FORMAT_ATTR(filter_local, filter_local, "config1:33");
298DEFINE_UNCORE_FORMAT_ATTR(filter_all_op, filter_all_op, "config1:35"); 367DEFINE_UNCORE_FORMAT_ATTR(filter_all_op, filter_all_op, "config1:35");
299DEFINE_UNCORE_FORMAT_ATTR(filter_nnm, filter_nnm, "config1:37"); 368DEFINE_UNCORE_FORMAT_ATTR(filter_nnm, filter_nnm, "config1:37");
300DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31"); 369DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31");
301DEFINE_UNCORE_FORMAT_ATTR(filter_opc2, filter_opc, "config1:52-60"); 370DEFINE_UNCORE_FORMAT_ATTR(filter_opc2, filter_opc, "config1:52-60");
302DEFINE_UNCORE_FORMAT_ATTR(filter_opc3, filter_opc, "config1:41-60"); 371DEFINE_UNCORE_FORMAT_ATTR(filter_opc3, filter_opc, "config1:41-60");
372DEFINE_UNCORE_FORMAT_ATTR(filter_opc_0, filter_opc0, "config1:41-50");
373DEFINE_UNCORE_FORMAT_ATTR(filter_opc_1, filter_opc1, "config1:51-60");
303DEFINE_UNCORE_FORMAT_ATTR(filter_nc, filter_nc, "config1:62"); 374DEFINE_UNCORE_FORMAT_ATTR(filter_nc, filter_nc, "config1:62");
304DEFINE_UNCORE_FORMAT_ATTR(filter_c6, filter_c6, "config1:61"); 375DEFINE_UNCORE_FORMAT_ATTR(filter_c6, filter_c6, "config1:61");
305DEFINE_UNCORE_FORMAT_ATTR(filter_isoc, filter_isoc, "config1:63"); 376DEFINE_UNCORE_FORMAT_ATTR(filter_isoc, filter_isoc, "config1:63");
@@ -1153,7 +1224,7 @@ static struct pci_driver snbep_uncore_pci_driver = {
1153/* 1224/*
1154 * build pci bus to socket mapping 1225 * build pci bus to socket mapping
1155 */ 1226 */
1156static int snbep_pci2phy_map_init(int devid) 1227static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool reverse)
1157{ 1228{
1158 struct pci_dev *ubox_dev = NULL; 1229 struct pci_dev *ubox_dev = NULL;
1159 int i, bus, nodeid, segment; 1230 int i, bus, nodeid, segment;
@@ -1168,12 +1239,12 @@ static int snbep_pci2phy_map_init(int devid)
1168 break; 1239 break;
1169 bus = ubox_dev->bus->number; 1240 bus = ubox_dev->bus->number;
1170 /* get the Node ID of the local register */ 1241 /* get the Node ID of the local register */
1171 err = pci_read_config_dword(ubox_dev, 0x40, &config); 1242 err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
1172 if (err) 1243 if (err)
1173 break; 1244 break;
1174 nodeid = config; 1245 nodeid = config;
1175 /* get the Node ID mapping */ 1246 /* get the Node ID mapping */
1176 err = pci_read_config_dword(ubox_dev, 0x54, &config); 1247 err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
1177 if (err) 1248 if (err)
1178 break; 1249 break;
1179 1250
@@ -1207,11 +1278,20 @@ static int snbep_pci2phy_map_init(int devid)
1207 raw_spin_lock(&pci2phy_map_lock); 1278 raw_spin_lock(&pci2phy_map_lock);
1208 list_for_each_entry(map, &pci2phy_map_head, list) { 1279 list_for_each_entry(map, &pci2phy_map_head, list) {
1209 i = -1; 1280 i = -1;
1210 for (bus = 255; bus >= 0; bus--) { 1281 if (reverse) {
1211 if (map->pbus_to_physid[bus] >= 0) 1282 for (bus = 255; bus >= 0; bus--) {
1212 i = map->pbus_to_physid[bus]; 1283 if (map->pbus_to_physid[bus] >= 0)
1213 else 1284 i = map->pbus_to_physid[bus];
1214 map->pbus_to_physid[bus] = i; 1285 else
1286 map->pbus_to_physid[bus] = i;
1287 }
1288 } else {
1289 for (bus = 0; bus <= 255; bus++) {
1290 if (map->pbus_to_physid[bus] >= 0)
1291 i = map->pbus_to_physid[bus];
1292 else
1293 map->pbus_to_physid[bus] = i;
1294 }
1215 } 1295 }
1216 } 1296 }
1217 raw_spin_unlock(&pci2phy_map_lock); 1297 raw_spin_unlock(&pci2phy_map_lock);
@@ -1224,7 +1304,7 @@ static int snbep_pci2phy_map_init(int devid)
1224 1304
1225int snbep_uncore_pci_init(void) 1305int snbep_uncore_pci_init(void)
1226{ 1306{
1227 int ret = snbep_pci2phy_map_init(0x3ce0); 1307 int ret = snbep_pci2phy_map_init(0x3ce0, SNBEP_CPUNODEID, SNBEP_GIDNIDMAP, true);
1228 if (ret) 1308 if (ret)
1229 return ret; 1309 return ret;
1230 uncore_pci_uncores = snbep_pci_uncores; 1310 uncore_pci_uncores = snbep_pci_uncores;
@@ -1788,7 +1868,7 @@ static struct pci_driver ivbep_uncore_pci_driver = {
1788 1868
1789int ivbep_uncore_pci_init(void) 1869int ivbep_uncore_pci_init(void)
1790{ 1870{
1791 int ret = snbep_pci2phy_map_init(0x0e1e); 1871 int ret = snbep_pci2phy_map_init(0x0e1e, SNBEP_CPUNODEID, SNBEP_GIDNIDMAP, true);
1792 if (ret) 1872 if (ret)
1793 return ret; 1873 return ret;
1794 uncore_pci_uncores = ivbep_pci_uncores; 1874 uncore_pci_uncores = ivbep_pci_uncores;
@@ -2897,7 +2977,7 @@ static struct pci_driver hswep_uncore_pci_driver = {
2897 2977
2898int hswep_uncore_pci_init(void) 2978int hswep_uncore_pci_init(void)
2899{ 2979{
2900 int ret = snbep_pci2phy_map_init(0x2f1e); 2980 int ret = snbep_pci2phy_map_init(0x2f1e, SNBEP_CPUNODEID, SNBEP_GIDNIDMAP, true);
2901 if (ret) 2981 if (ret)
2902 return ret; 2982 return ret;
2903 uncore_pci_uncores = hswep_pci_uncores; 2983 uncore_pci_uncores = hswep_pci_uncores;
@@ -3186,7 +3266,7 @@ static struct pci_driver bdx_uncore_pci_driver = {
3186 3266
3187int bdx_uncore_pci_init(void) 3267int bdx_uncore_pci_init(void)
3188{ 3268{
3189 int ret = snbep_pci2phy_map_init(0x6f1e); 3269 int ret = snbep_pci2phy_map_init(0x6f1e, SNBEP_CPUNODEID, SNBEP_GIDNIDMAP, true);
3190 3270
3191 if (ret) 3271 if (ret)
3192 return ret; 3272 return ret;
@@ -3196,3 +3276,525 @@ int bdx_uncore_pci_init(void)
3196} 3276}
3197 3277
3198/* end of BDX uncore support */ 3278/* end of BDX uncore support */
3279
3280/* SKX uncore support */
3281
3282static struct intel_uncore_type skx_uncore_ubox = {
3283 .name = "ubox",
3284 .num_counters = 2,
3285 .num_boxes = 1,
3286 .perf_ctr_bits = 48,
3287 .fixed_ctr_bits = 48,
3288 .perf_ctr = HSWEP_U_MSR_PMON_CTR0,
3289 .event_ctl = HSWEP_U_MSR_PMON_CTL0,
3290 .event_mask = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
3291 .fixed_ctr = HSWEP_U_MSR_PMON_UCLK_FIXED_CTR,
3292 .fixed_ctl = HSWEP_U_MSR_PMON_UCLK_FIXED_CTL,
3293 .ops = &ivbep_uncore_msr_ops,
3294 .format_group = &ivbep_uncore_ubox_format_group,
3295};
3296
3297static struct attribute *skx_uncore_cha_formats_attr[] = {
3298 &format_attr_event.attr,
3299 &format_attr_umask.attr,
3300 &format_attr_edge.attr,
3301 &format_attr_tid_en.attr,
3302 &format_attr_inv.attr,
3303 &format_attr_thresh8.attr,
3304 &format_attr_filter_tid4.attr,
3305 &format_attr_filter_link4.attr,
3306 &format_attr_filter_state5.attr,
3307 &format_attr_filter_rem.attr,
3308 &format_attr_filter_loc.attr,
3309 &format_attr_filter_nm.attr,
3310 &format_attr_filter_all_op.attr,
3311 &format_attr_filter_not_nm.attr,
3312 &format_attr_filter_opc_0.attr,
3313 &format_attr_filter_opc_1.attr,
3314 &format_attr_filter_nc.attr,
3315 &format_attr_filter_c6.attr,
3316 &format_attr_filter_isoc.attr,
3317 NULL,
3318};
3319
3320static struct attribute_group skx_uncore_chabox_format_group = {
3321 .name = "format",
3322 .attrs = skx_uncore_cha_formats_attr,
3323};
3324
3325static struct event_constraint skx_uncore_chabox_constraints[] = {
3326 UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
3327 UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
3328 EVENT_CONSTRAINT_END
3329};
3330
3331static struct extra_reg skx_uncore_cha_extra_regs[] = {
3332 SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
3333 SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
3334 SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
3335 SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
3336 SNBEP_CBO_EVENT_EXTRA_REG(0x2134, 0xffff, 0x4),
3337 SNBEP_CBO_EVENT_EXTRA_REG(0x8134, 0xffff, 0x4),
3338};
3339
3340static u64 skx_cha_filter_mask(int fields)
3341{
3342 u64 mask = 0;
3343
3344 if (fields & 0x1)
3345 mask |= SKX_CHA_MSR_PMON_BOX_FILTER_TID;
3346 if (fields & 0x2)
3347 mask |= SKX_CHA_MSR_PMON_BOX_FILTER_LINK;
3348 if (fields & 0x4)
3349 mask |= SKX_CHA_MSR_PMON_BOX_FILTER_STATE;
3350 return mask;
3351}
3352
3353static struct event_constraint *
3354skx_cha_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
3355{
3356 return __snbep_cbox_get_constraint(box, event, skx_cha_filter_mask);
3357}
3358
3359static int skx_cha_hw_config(struct intel_uncore_box *box, struct perf_event *event)
3360{
3361 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
3362 struct extra_reg *er;
3363 int idx = 0;
3364
3365 for (er = skx_uncore_cha_extra_regs; er->msr; er++) {
3366 if (er->event != (event->hw.config & er->config_mask))
3367 continue;
3368 idx |= er->idx;
3369 }
3370
3371 if (idx) {
3372 reg1->reg = HSWEP_C0_MSR_PMON_BOX_FILTER0 +
3373 HSWEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
3374 reg1->config = event->attr.config1 & skx_cha_filter_mask(idx);
3375 reg1->idx = idx;
3376 }
3377 return 0;
3378}
3379
3380static struct intel_uncore_ops skx_uncore_chabox_ops = {
3381 /* There is no frz_en for chabox ctl */
3382 .init_box = ivbep_uncore_msr_init_box,
3383 .disable_box = snbep_uncore_msr_disable_box,
3384 .enable_box = snbep_uncore_msr_enable_box,
3385 .disable_event = snbep_uncore_msr_disable_event,
3386 .enable_event = hswep_cbox_enable_event,
3387 .read_counter = uncore_msr_read_counter,
3388 .hw_config = skx_cha_hw_config,
3389 .get_constraint = skx_cha_get_constraint,
3390 .put_constraint = snbep_cbox_put_constraint,
3391};
3392
3393static struct intel_uncore_type skx_uncore_chabox = {
3394 .name = "cha",
3395 .num_counters = 4,
3396 .perf_ctr_bits = 48,
3397 .event_ctl = HSWEP_C0_MSR_PMON_CTL0,
3398 .perf_ctr = HSWEP_C0_MSR_PMON_CTR0,
3399 .event_mask = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
3400 .box_ctl = HSWEP_C0_MSR_PMON_BOX_CTL,
3401 .msr_offset = HSWEP_CBO_MSR_OFFSET,
3402 .num_shared_regs = 1,
3403 .constraints = skx_uncore_chabox_constraints,
3404 .ops = &skx_uncore_chabox_ops,
3405 .format_group = &skx_uncore_chabox_format_group,
3406};
3407
3408static struct attribute *skx_uncore_iio_formats_attr[] = {
3409 &format_attr_event.attr,
3410 &format_attr_umask.attr,
3411 &format_attr_edge.attr,
3412 &format_attr_inv.attr,
3413 &format_attr_thresh9.attr,
3414 &format_attr_ch_mask.attr,
3415 &format_attr_fc_mask.attr,
3416 NULL,
3417};
3418
3419static struct attribute_group skx_uncore_iio_format_group = {
3420 .name = "format",
3421 .attrs = skx_uncore_iio_formats_attr,
3422};
3423
3424static struct event_constraint skx_uncore_iio_constraints[] = {
3425 UNCORE_EVENT_CONSTRAINT(0x83, 0x3),
3426 UNCORE_EVENT_CONSTRAINT(0x88, 0xc),
3427 UNCORE_EVENT_CONSTRAINT(0x95, 0xc),
3428 UNCORE_EVENT_CONSTRAINT(0xc0, 0xc),
3429 UNCORE_EVENT_CONSTRAINT(0xc5, 0xc),
3430 UNCORE_EVENT_CONSTRAINT(0xd4, 0xc),
3431 EVENT_CONSTRAINT_END
3432};
3433
3434static void skx_iio_enable_event(struct intel_uncore_box *box,
3435 struct perf_event *event)
3436{
3437 struct hw_perf_event *hwc = &event->hw;
3438
3439 wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
3440}
3441
3442static struct intel_uncore_ops skx_uncore_iio_ops = {
3443 .init_box = ivbep_uncore_msr_init_box,
3444 .disable_box = snbep_uncore_msr_disable_box,
3445 .enable_box = snbep_uncore_msr_enable_box,
3446 .disable_event = snbep_uncore_msr_disable_event,
3447 .enable_event = skx_iio_enable_event,
3448 .read_counter = uncore_msr_read_counter,
3449};
3450
3451static struct intel_uncore_type skx_uncore_iio = {
3452 .name = "iio",
3453 .num_counters = 4,
3454 .num_boxes = 5,
3455 .perf_ctr_bits = 48,
3456 .event_ctl = SKX_IIO0_MSR_PMON_CTL0,
3457 .perf_ctr = SKX_IIO0_MSR_PMON_CTR0,
3458 .event_mask = SKX_IIO_PMON_RAW_EVENT_MASK,
3459 .event_mask_ext = SKX_IIO_PMON_RAW_EVENT_MASK_EXT,
3460 .box_ctl = SKX_IIO0_MSR_PMON_BOX_CTL,
3461 .msr_offset = SKX_IIO_MSR_OFFSET,
3462 .constraints = skx_uncore_iio_constraints,
3463 .ops = &skx_uncore_iio_ops,
3464 .format_group = &skx_uncore_iio_format_group,
3465};
3466
3467static struct attribute *skx_uncore_formats_attr[] = {
3468 &format_attr_event.attr,
3469 &format_attr_umask.attr,
3470 &format_attr_edge.attr,
3471 &format_attr_inv.attr,
3472 &format_attr_thresh8.attr,
3473 NULL,
3474};
3475
3476static struct attribute_group skx_uncore_format_group = {
3477 .name = "format",
3478 .attrs = skx_uncore_formats_attr,
3479};
3480
3481static struct intel_uncore_type skx_uncore_irp = {
3482 .name = "irp",
3483 .num_counters = 2,
3484 .num_boxes = 5,
3485 .perf_ctr_bits = 48,
3486 .event_ctl = SKX_IRP0_MSR_PMON_CTL0,
3487 .perf_ctr = SKX_IRP0_MSR_PMON_CTR0,
3488 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
3489 .box_ctl = SKX_IRP0_MSR_PMON_BOX_CTL,
3490 .msr_offset = SKX_IRP_MSR_OFFSET,
3491 .ops = &skx_uncore_iio_ops,
3492 .format_group = &skx_uncore_format_group,
3493};
3494
3495static struct intel_uncore_ops skx_uncore_pcu_ops = {
3496 IVBEP_UNCORE_MSR_OPS_COMMON_INIT(),
3497 .hw_config = hswep_pcu_hw_config,
3498 .get_constraint = snbep_pcu_get_constraint,
3499 .put_constraint = snbep_pcu_put_constraint,
3500};
3501
3502static struct intel_uncore_type skx_uncore_pcu = {
3503 .name = "pcu",
3504 .num_counters = 4,
3505 .num_boxes = 1,
3506 .perf_ctr_bits = 48,
3507 .perf_ctr = HSWEP_PCU_MSR_PMON_CTR0,
3508 .event_ctl = HSWEP_PCU_MSR_PMON_CTL0,
3509 .event_mask = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
3510 .box_ctl = HSWEP_PCU_MSR_PMON_BOX_CTL,
3511 .num_shared_regs = 1,
3512 .ops = &skx_uncore_pcu_ops,
3513 .format_group = &snbep_uncore_pcu_format_group,
3514};
3515
3516static struct intel_uncore_type *skx_msr_uncores[] = {
3517 &skx_uncore_ubox,
3518 &skx_uncore_chabox,
3519 &skx_uncore_iio,
3520 &skx_uncore_irp,
3521 &skx_uncore_pcu,
3522 NULL,
3523};
3524
3525static int skx_count_chabox(void)
3526{
3527 struct pci_dev *chabox_dev = NULL;
3528 int bus, count = 0;
3529
3530 while (1) {
3531 chabox_dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x208d, chabox_dev);
3532 if (!chabox_dev)
3533 break;
3534 if (count == 0)
3535 bus = chabox_dev->bus->number;
3536 if (bus != chabox_dev->bus->number)
3537 break;
3538 count++;
3539 }
3540
3541 pci_dev_put(chabox_dev);
3542 return count;
3543}
3544
3545void skx_uncore_cpu_init(void)
3546{
3547 skx_uncore_chabox.num_boxes = skx_count_chabox();
3548 uncore_msr_uncores = skx_msr_uncores;
3549}
3550
3551static struct intel_uncore_type skx_uncore_imc = {
3552 .name = "imc",
3553 .num_counters = 4,
3554 .num_boxes = 6,
3555 .perf_ctr_bits = 48,
3556 .fixed_ctr_bits = 48,
3557 .fixed_ctr = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
3558 .fixed_ctl = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
3559 .event_descs = hswep_uncore_imc_events,
3560 .perf_ctr = SNBEP_PCI_PMON_CTR0,
3561 .event_ctl = SNBEP_PCI_PMON_CTL0,
3562 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
3563 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
3564 .ops = &ivbep_uncore_pci_ops,
3565 .format_group = &skx_uncore_format_group,
3566};
3567
3568static struct attribute *skx_upi_uncore_formats_attr[] = {
3569 &format_attr_event_ext.attr,
3570 &format_attr_umask_ext.attr,
3571 &format_attr_edge.attr,
3572 &format_attr_inv.attr,
3573 &format_attr_thresh8.attr,
3574 NULL,
3575};
3576
3577static struct attribute_group skx_upi_uncore_format_group = {
3578 .name = "format",
3579 .attrs = skx_upi_uncore_formats_attr,
3580};
3581
3582static void skx_upi_uncore_pci_init_box(struct intel_uncore_box *box)
3583{
3584 struct pci_dev *pdev = box->pci_dev;
3585
3586 __set_bit(UNCORE_BOX_FLAG_CTL_OFFS8, &box->flags);
3587 pci_write_config_dword(pdev, SKX_UPI_PCI_PMON_BOX_CTL, IVBEP_PMON_BOX_CTL_INT);
3588}
3589
3590static struct intel_uncore_ops skx_upi_uncore_pci_ops = {
3591 .init_box = skx_upi_uncore_pci_init_box,
3592 .disable_box = snbep_uncore_pci_disable_box,
3593 .enable_box = snbep_uncore_pci_enable_box,
3594 .disable_event = snbep_uncore_pci_disable_event,
3595 .enable_event = snbep_uncore_pci_enable_event,
3596 .read_counter = snbep_uncore_pci_read_counter,
3597};
3598
3599static struct intel_uncore_type skx_uncore_upi = {
3600 .name = "upi",
3601 .num_counters = 4,
3602 .num_boxes = 3,
3603 .perf_ctr_bits = 48,
3604 .perf_ctr = SKX_UPI_PCI_PMON_CTR0,
3605 .event_ctl = SKX_UPI_PCI_PMON_CTL0,
3606 .event_mask = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
3607 .event_mask_ext = SKX_PMON_CTL_UMASK_EXT,
3608 .box_ctl = SKX_UPI_PCI_PMON_BOX_CTL,
3609 .ops = &skx_upi_uncore_pci_ops,
3610 .format_group = &skx_upi_uncore_format_group,
3611};
3612
3613static void skx_m2m_uncore_pci_init_box(struct intel_uncore_box *box)
3614{
3615 struct pci_dev *pdev = box->pci_dev;
3616
3617 __set_bit(UNCORE_BOX_FLAG_CTL_OFFS8, &box->flags);
3618 pci_write_config_dword(pdev, SKX_M2M_PCI_PMON_BOX_CTL, IVBEP_PMON_BOX_CTL_INT);
3619}
3620
3621static struct intel_uncore_ops skx_m2m_uncore_pci_ops = {
3622 .init_box = skx_m2m_uncore_pci_init_box,
3623 .disable_box = snbep_uncore_pci_disable_box,
3624 .enable_box = snbep_uncore_pci_enable_box,
3625 .disable_event = snbep_uncore_pci_disable_event,
3626 .enable_event = snbep_uncore_pci_enable_event,
3627 .read_counter = snbep_uncore_pci_read_counter,
3628};
3629
3630static struct intel_uncore_type skx_uncore_m2m = {
3631 .name = "m2m",
3632 .num_counters = 4,
3633 .num_boxes = 2,
3634 .perf_ctr_bits = 48,
3635 .perf_ctr = SKX_M2M_PCI_PMON_CTR0,
3636 .event_ctl = SKX_M2M_PCI_PMON_CTL0,
3637 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
3638 .box_ctl = SKX_M2M_PCI_PMON_BOX_CTL,
3639 .ops = &skx_m2m_uncore_pci_ops,
3640 .format_group = &skx_uncore_format_group,
3641};
3642
3643static struct event_constraint skx_uncore_m2pcie_constraints[] = {
3644 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
3645 EVENT_CONSTRAINT_END
3646};
3647
3648static struct intel_uncore_type skx_uncore_m2pcie = {
3649 .name = "m2pcie",
3650 .num_counters = 4,
3651 .num_boxes = 4,
3652 .perf_ctr_bits = 48,
3653 .constraints = skx_uncore_m2pcie_constraints,
3654 .perf_ctr = SNBEP_PCI_PMON_CTR0,
3655 .event_ctl = SNBEP_PCI_PMON_CTL0,
3656 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
3657 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
3658 .ops = &ivbep_uncore_pci_ops,
3659 .format_group = &skx_uncore_format_group,
3660};
3661
3662static struct event_constraint skx_uncore_m3upi_constraints[] = {
3663 UNCORE_EVENT_CONSTRAINT(0x1d, 0x1),
3664 UNCORE_EVENT_CONSTRAINT(0x1e, 0x1),
3665 UNCORE_EVENT_CONSTRAINT(0x40, 0x7),
3666 UNCORE_EVENT_CONSTRAINT(0x4e, 0x7),
3667 UNCORE_EVENT_CONSTRAINT(0x4f, 0x7),
3668 UNCORE_EVENT_CONSTRAINT(0x50, 0x7),
3669 UNCORE_EVENT_CONSTRAINT(0x51, 0x7),
3670 UNCORE_EVENT_CONSTRAINT(0x52, 0x7),
3671 EVENT_CONSTRAINT_END
3672};
3673
3674static struct intel_uncore_type skx_uncore_m3upi = {
3675 .name = "m3upi",
3676 .num_counters = 3,
3677 .num_boxes = 3,
3678 .perf_ctr_bits = 48,
3679 .constraints = skx_uncore_m3upi_constraints,
3680 .perf_ctr = SNBEP_PCI_PMON_CTR0,
3681 .event_ctl = SNBEP_PCI_PMON_CTL0,
3682 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
3683 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
3684 .ops = &ivbep_uncore_pci_ops,
3685 .format_group = &skx_uncore_format_group,
3686};
3687
3688enum {
3689 SKX_PCI_UNCORE_IMC,
3690 SKX_PCI_UNCORE_M2M,
3691 SKX_PCI_UNCORE_UPI,
3692 SKX_PCI_UNCORE_M2PCIE,
3693 SKX_PCI_UNCORE_M3UPI,
3694};
3695
3696static struct intel_uncore_type *skx_pci_uncores[] = {
3697 [SKX_PCI_UNCORE_IMC] = &skx_uncore_imc,
3698 [SKX_PCI_UNCORE_M2M] = &skx_uncore_m2m,
3699 [SKX_PCI_UNCORE_UPI] = &skx_uncore_upi,
3700 [SKX_PCI_UNCORE_M2PCIE] = &skx_uncore_m2pcie,
3701 [SKX_PCI_UNCORE_M3UPI] = &skx_uncore_m3upi,
3702 NULL,
3703};
3704
3705static const struct pci_device_id skx_uncore_pci_ids[] = {
3706 { /* MC0 Channel 0 */
3707 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2042),
3708 .driver_data = UNCORE_PCI_DEV_FULL_DATA(10, 2, SKX_PCI_UNCORE_IMC, 0),
3709 },
3710 { /* MC0 Channel 1 */
3711 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2046),
3712 .driver_data = UNCORE_PCI_DEV_FULL_DATA(10, 6, SKX_PCI_UNCORE_IMC, 1),
3713 },
3714 { /* MC0 Channel 2 */
3715 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x204a),
3716 .driver_data = UNCORE_PCI_DEV_FULL_DATA(11, 2, SKX_PCI_UNCORE_IMC, 2),
3717 },
3718 { /* MC1 Channel 0 */
3719 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2042),
3720 .driver_data = UNCORE_PCI_DEV_FULL_DATA(12, 2, SKX_PCI_UNCORE_IMC, 3),
3721 },
3722 { /* MC1 Channel 1 */
3723 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2046),
3724 .driver_data = UNCORE_PCI_DEV_FULL_DATA(12, 6, SKX_PCI_UNCORE_IMC, 4),
3725 },
3726 { /* MC1 Channel 2 */
3727 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x204a),
3728 .driver_data = UNCORE_PCI_DEV_FULL_DATA(13, 2, SKX_PCI_UNCORE_IMC, 5),
3729 },
3730 { /* M2M0 */
3731 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2066),
3732 .driver_data = UNCORE_PCI_DEV_FULL_DATA(8, 0, SKX_PCI_UNCORE_M2M, 0),
3733 },
3734 { /* M2M1 */
3735 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2066),
3736 .driver_data = UNCORE_PCI_DEV_FULL_DATA(9, 0, SKX_PCI_UNCORE_M2M, 1),
3737 },
3738 { /* UPI0 Link 0 */
3739 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2058),
3740 .driver_data = UNCORE_PCI_DEV_FULL_DATA(14, 0, SKX_PCI_UNCORE_UPI, 0),
3741 },
3742 { /* UPI0 Link 1 */
3743 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2058),
3744 .driver_data = UNCORE_PCI_DEV_FULL_DATA(15, 0, SKX_PCI_UNCORE_UPI, 1),
3745 },
3746 { /* UPI1 Link 2 */
3747 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2058),
3748 .driver_data = UNCORE_PCI_DEV_FULL_DATA(16, 0, SKX_PCI_UNCORE_UPI, 2),
3749 },
3750 { /* M2PCIe 0 */
3751 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2088),
3752 .driver_data = UNCORE_PCI_DEV_FULL_DATA(21, 1, SKX_PCI_UNCORE_M2PCIE, 0),
3753 },
3754 { /* M2PCIe 1 */
3755 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2088),
3756 .driver_data = UNCORE_PCI_DEV_FULL_DATA(22, 1, SKX_PCI_UNCORE_M2PCIE, 1),
3757 },
3758 { /* M2PCIe 2 */
3759 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2088),
3760 .driver_data = UNCORE_PCI_DEV_FULL_DATA(23, 1, SKX_PCI_UNCORE_M2PCIE, 2),
3761 },
3762 { /* M2PCIe 3 */
3763 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2088),
3764 .driver_data = UNCORE_PCI_DEV_FULL_DATA(21, 5, SKX_PCI_UNCORE_M2PCIE, 3),
3765 },
3766 { /* M3UPI0 Link 0 */
3767 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x204C),
3768 .driver_data = UNCORE_PCI_DEV_FULL_DATA(18, 0, SKX_PCI_UNCORE_M3UPI, 0),
3769 },
3770 { /* M3UPI0 Link 1 */
3771 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x204D),
3772 .driver_data = UNCORE_PCI_DEV_FULL_DATA(18, 1, SKX_PCI_UNCORE_M3UPI, 1),
3773 },
3774 { /* M3UPI1 Link 2 */
3775 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x204C),
3776 .driver_data = UNCORE_PCI_DEV_FULL_DATA(18, 4, SKX_PCI_UNCORE_M3UPI, 2),
3777 },
3778 { /* end: all zeroes */ }
3779};
3780
3781
3782static struct pci_driver skx_uncore_pci_driver = {
3783 .name = "skx_uncore",
3784 .id_table = skx_uncore_pci_ids,
3785};
3786
3787int skx_uncore_pci_init(void)
3788{
3789 /* need to double check pci address */
3790 int ret = snbep_pci2phy_map_init(0x2014, SKX_CPUNODEID, SKX_GIDNIDMAP, false);
3791
3792 if (ret)
3793 return ret;
3794
3795 uncore_pci_uncores = skx_pci_uncores;
3796 uncore_pci_driver = &skx_uncore_pci_driver;
3797 return 0;
3798}
3799
3800/* end of SKX uncore support */
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 8c4a47706296..5874d8de1f8d 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -194,12 +194,13 @@ struct cpu_hw_events {
194 */ 194 */
195 struct debug_store *ds; 195 struct debug_store *ds;
196 u64 pebs_enabled; 196 u64 pebs_enabled;
197 int n_pebs;
198 int n_large_pebs;
197 199
198 /* 200 /*
199 * Intel LBR bits 201 * Intel LBR bits
200 */ 202 */
201 int lbr_users; 203 int lbr_users;
202 void *lbr_context;
203 struct perf_branch_stack lbr_stack; 204 struct perf_branch_stack lbr_stack;
204 struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES]; 205 struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES];
205 struct er_account *lbr_sel; 206 struct er_account *lbr_sel;
@@ -508,6 +509,8 @@ struct x86_pmu {
508 void (*enable_all)(int added); 509 void (*enable_all)(int added);
509 void (*enable)(struct perf_event *); 510 void (*enable)(struct perf_event *);
510 void (*disable)(struct perf_event *); 511 void (*disable)(struct perf_event *);
512 void (*add)(struct perf_event *);
513 void (*del)(struct perf_event *);
511 int (*hw_config)(struct perf_event *event); 514 int (*hw_config)(struct perf_event *event);
512 int (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign); 515 int (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign);
513 unsigned eventsel; 516 unsigned eventsel;
@@ -888,6 +891,10 @@ extern struct event_constraint intel_skl_pebs_event_constraints[];
888 891
889struct event_constraint *intel_pebs_constraints(struct perf_event *event); 892struct event_constraint *intel_pebs_constraints(struct perf_event *event);
890 893
894void intel_pmu_pebs_add(struct perf_event *event);
895
896void intel_pmu_pebs_del(struct perf_event *event);
897
891void intel_pmu_pebs_enable(struct perf_event *event); 898void intel_pmu_pebs_enable(struct perf_event *event);
892 899
893void intel_pmu_pebs_disable(struct perf_event *event); 900void intel_pmu_pebs_disable(struct perf_event *event);
@@ -906,9 +913,9 @@ u64 lbr_from_signext_quirk_wr(u64 val);
906 913
907void intel_pmu_lbr_reset(void); 914void intel_pmu_lbr_reset(void);
908 915
909void intel_pmu_lbr_enable(struct perf_event *event); 916void intel_pmu_lbr_add(struct perf_event *event);
910 917
911void intel_pmu_lbr_disable(struct perf_event *event); 918void intel_pmu_lbr_del(struct perf_event *event);
912 919
913void intel_pmu_lbr_enable_all(bool pmi); 920void intel_pmu_lbr_enable_all(bool pmi);
914 921
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 598bc999f4c2..3b77588a9360 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -339,6 +339,24 @@ static inline int bitmap_parse(const char *buf, unsigned int buflen,
339 return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits); 339 return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
340} 340}
341 341
342/*
343 * bitmap_from_u64 - Check and swap words within u64.
344 * @mask: source bitmap
345 * @dst: destination bitmap
346 *
347 * In 32-bit Big Endian kernel, when using (u32 *)(&val)[*]
348 * to read u64 mask, we will get the wrong word.
349 * That is "(u32 *)(&val)[0]" gets the upper 32 bits,
350 * but we expect the lower 32-bits of u64.
351 */
352static inline void bitmap_from_u64(unsigned long *dst, u64 mask)
353{
354 dst[0] = mask & ULONG_MAX;
355
356 if (sizeof(mask) > sizeof(unsigned long))
357 dst[1] = mask >> 32;
358}
359
342#endif /* __ASSEMBLY__ */ 360#endif /* __ASSEMBLY__ */
343 361
344#endif /* __LINUX_BITMAP_H */ 362#endif /* __LINUX_BITMAP_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 2b6b43cc0dd5..5c5362584aba 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -510,9 +510,15 @@ typedef void (*perf_overflow_handler_t)(struct perf_event *,
510 struct perf_sample_data *, 510 struct perf_sample_data *,
511 struct pt_regs *regs); 511 struct pt_regs *regs);
512 512
513enum perf_group_flag { 513/*
514 PERF_GROUP_SOFTWARE = 0x1, 514 * Event capabilities. For event_caps and groups caps.
515}; 515 *
516 * PERF_EV_CAP_SOFTWARE: Is a software event.
517 * PERF_EV_CAP_READ_ACTIVE_PKG: A CPU event (or cgroup event) that can be read
518 * from any CPU in the package where it is active.
519 */
520#define PERF_EV_CAP_SOFTWARE BIT(0)
521#define PERF_EV_CAP_READ_ACTIVE_PKG BIT(1)
516 522
517#define SWEVENT_HLIST_BITS 8 523#define SWEVENT_HLIST_BITS 8
518#define SWEVENT_HLIST_SIZE (1 << SWEVENT_HLIST_BITS) 524#define SWEVENT_HLIST_SIZE (1 << SWEVENT_HLIST_BITS)
@@ -568,7 +574,12 @@ struct perf_event {
568 struct hlist_node hlist_entry; 574 struct hlist_node hlist_entry;
569 struct list_head active_entry; 575 struct list_head active_entry;
570 int nr_siblings; 576 int nr_siblings;
571 int group_flags; 577
578 /* Not serialized. Only written during event initialization. */
579 int event_caps;
580 /* The cumulative AND of all event_caps for events in this group. */
581 int group_caps;
582
572 struct perf_event *group_leader; 583 struct perf_event *group_leader;
573 struct pmu *pmu; 584 struct pmu *pmu;
574 void *pmu_private; 585 void *pmu_private;
@@ -774,6 +785,9 @@ struct perf_cpu_context {
774#ifdef CONFIG_CGROUP_PERF 785#ifdef CONFIG_CGROUP_PERF
775 struct perf_cgroup *cgrp; 786 struct perf_cgroup *cgrp;
776#endif 787#endif
788
789 struct list_head sched_cb_entry;
790 int sched_cb_usage;
777}; 791};
778 792
779struct perf_output_handle { 793struct perf_output_handle {
@@ -985,7 +999,7 @@ static inline bool is_sampling_event(struct perf_event *event)
985 */ 999 */
986static inline int is_software_event(struct perf_event *event) 1000static inline int is_software_event(struct perf_event *event)
987{ 1001{
988 return event->pmu->task_ctx_nr == perf_sw_context; 1002 return event->event_caps & PERF_EV_CAP_SOFTWARE;
989} 1003}
990 1004
991extern struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; 1005extern struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX];
diff --git a/kernel/events/core.c b/kernel/events/core.c
index fc9bb2225291..7c0d263f6bc5 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1475,8 +1475,7 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
1475 if (event->group_leader == event) { 1475 if (event->group_leader == event) {
1476 struct list_head *list; 1476 struct list_head *list;
1477 1477
1478 if (is_software_event(event)) 1478 event->group_caps = event->event_caps;
1479 event->group_flags |= PERF_GROUP_SOFTWARE;
1480 1479
1481 list = ctx_group_list(event, ctx); 1480 list = ctx_group_list(event, ctx);
1482 list_add_tail(&event->group_entry, list); 1481 list_add_tail(&event->group_entry, list);
@@ -1630,9 +1629,7 @@ static void perf_group_attach(struct perf_event *event)
1630 1629
1631 WARN_ON_ONCE(group_leader->ctx != event->ctx); 1630 WARN_ON_ONCE(group_leader->ctx != event->ctx);
1632 1631
1633 if (group_leader->group_flags & PERF_GROUP_SOFTWARE && 1632 group_leader->group_caps &= event->event_caps;
1634 !is_software_event(event))
1635 group_leader->group_flags &= ~PERF_GROUP_SOFTWARE;
1636 1633
1637 list_add_tail(&event->group_entry, &group_leader->sibling_list); 1634 list_add_tail(&event->group_entry, &group_leader->sibling_list);
1638 group_leader->nr_siblings++; 1635 group_leader->nr_siblings++;
@@ -1723,7 +1720,7 @@ static void perf_group_detach(struct perf_event *event)
1723 sibling->group_leader = sibling; 1720 sibling->group_leader = sibling;
1724 1721
1725 /* Inherit group flags from the previous leader */ 1722 /* Inherit group flags from the previous leader */
1726 sibling->group_flags = event->group_flags; 1723 sibling->group_caps = event->group_caps;
1727 1724
1728 WARN_ON_ONCE(sibling->ctx != event->ctx); 1725 WARN_ON_ONCE(sibling->ctx != event->ctx);
1729 } 1726 }
@@ -1832,6 +1829,8 @@ group_sched_out(struct perf_event *group_event,
1832 struct perf_event *event; 1829 struct perf_event *event;
1833 int state = group_event->state; 1830 int state = group_event->state;
1834 1831
1832 perf_pmu_disable(ctx->pmu);
1833
1835 event_sched_out(group_event, cpuctx, ctx); 1834 event_sched_out(group_event, cpuctx, ctx);
1836 1835
1837 /* 1836 /*
@@ -1840,6 +1839,8 @@ group_sched_out(struct perf_event *group_event,
1840 list_for_each_entry(event, &group_event->sibling_list, group_entry) 1839 list_for_each_entry(event, &group_event->sibling_list, group_entry)
1841 event_sched_out(event, cpuctx, ctx); 1840 event_sched_out(event, cpuctx, ctx);
1842 1841
1842 perf_pmu_enable(ctx->pmu);
1843
1843 if (state == PERF_EVENT_STATE_ACTIVE && group_event->attr.exclusive) 1844 if (state == PERF_EVENT_STATE_ACTIVE && group_event->attr.exclusive)
1844 cpuctx->exclusive = 0; 1845 cpuctx->exclusive = 0;
1845} 1846}
@@ -2145,7 +2146,7 @@ static int group_can_go_on(struct perf_event *event,
2145 /* 2146 /*
2146 * Groups consisting entirely of software events can always go on. 2147 * Groups consisting entirely of software events can always go on.
2147 */ 2148 */
2148 if (event->group_flags & PERF_GROUP_SOFTWARE) 2149 if (event->group_caps & PERF_EV_CAP_SOFTWARE)
2149 return 1; 2150 return 1;
2150 /* 2151 /*
2151 * If an exclusive group is already on, no other hardware 2152 * If an exclusive group is already on, no other hardware
@@ -2491,7 +2492,7 @@ static int __perf_event_stop(void *info)
2491 * while restarting. 2492 * while restarting.
2492 */ 2493 */
2493 if (sd->restart) 2494 if (sd->restart)
2494 event->pmu->start(event, PERF_EF_START); 2495 event->pmu->start(event, 0);
2495 2496
2496 return 0; 2497 return 0;
2497} 2498}
@@ -2837,19 +2838,36 @@ unlock:
2837 } 2838 }
2838} 2839}
2839 2840
2841static DEFINE_PER_CPU(struct list_head, sched_cb_list);
2842
2840void perf_sched_cb_dec(struct pmu *pmu) 2843void perf_sched_cb_dec(struct pmu *pmu)
2841{ 2844{
2845 struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
2846
2842 this_cpu_dec(perf_sched_cb_usages); 2847 this_cpu_dec(perf_sched_cb_usages);
2848
2849 if (!--cpuctx->sched_cb_usage)
2850 list_del(&cpuctx->sched_cb_entry);
2843} 2851}
2844 2852
2853
2845void perf_sched_cb_inc(struct pmu *pmu) 2854void perf_sched_cb_inc(struct pmu *pmu)
2846{ 2855{
2856 struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
2857
2858 if (!cpuctx->sched_cb_usage++)
2859 list_add(&cpuctx->sched_cb_entry, this_cpu_ptr(&sched_cb_list));
2860
2847 this_cpu_inc(perf_sched_cb_usages); 2861 this_cpu_inc(perf_sched_cb_usages);
2848} 2862}
2849 2863
2850/* 2864/*
2851 * This function provides the context switch callback to the lower code 2865 * This function provides the context switch callback to the lower code
2852 * layer. It is invoked ONLY when the context switch callback is enabled. 2866 * layer. It is invoked ONLY when the context switch callback is enabled.
2867 *
2868 * This callback is relevant even to per-cpu events; for example multi event
2869 * PEBS requires this to provide PID/TID information. This requires we flush
2870 * all queued PEBS records before we context switch to a new task.
2853 */ 2871 */
2854static void perf_pmu_sched_task(struct task_struct *prev, 2872static void perf_pmu_sched_task(struct task_struct *prev,
2855 struct task_struct *next, 2873 struct task_struct *next,
@@ -2857,34 +2875,24 @@ static void perf_pmu_sched_task(struct task_struct *prev,
2857{ 2875{
2858 struct perf_cpu_context *cpuctx; 2876 struct perf_cpu_context *cpuctx;
2859 struct pmu *pmu; 2877 struct pmu *pmu;
2860 unsigned long flags;
2861 2878
2862 if (prev == next) 2879 if (prev == next)
2863 return; 2880 return;
2864 2881
2865 local_irq_save(flags); 2882 list_for_each_entry(cpuctx, this_cpu_ptr(&sched_cb_list), sched_cb_entry) {
2866 2883 pmu = cpuctx->unique_pmu; /* software PMUs will not have sched_task */
2867 rcu_read_lock();
2868
2869 list_for_each_entry_rcu(pmu, &pmus, entry) {
2870 if (pmu->sched_task) {
2871 cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
2872
2873 perf_ctx_lock(cpuctx, cpuctx->task_ctx);
2874 2884
2875 perf_pmu_disable(pmu); 2885 if (WARN_ON_ONCE(!pmu->sched_task))
2886 continue;
2876 2887
2877 pmu->sched_task(cpuctx->task_ctx, sched_in); 2888 perf_ctx_lock(cpuctx, cpuctx->task_ctx);
2889 perf_pmu_disable(pmu);
2878 2890
2879 perf_pmu_enable(pmu); 2891 pmu->sched_task(cpuctx->task_ctx, sched_in);
2880 2892
2881 perf_ctx_unlock(cpuctx, cpuctx->task_ctx); 2893 perf_pmu_enable(pmu);
2882 } 2894 perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
2883 } 2895 }
2884
2885 rcu_read_unlock();
2886
2887 local_irq_restore(flags);
2888} 2896}
2889 2897
2890static void perf_event_switch(struct task_struct *task, 2898static void perf_event_switch(struct task_struct *task,
@@ -3416,6 +3424,22 @@ struct perf_read_data {
3416 int ret; 3424 int ret;
3417}; 3425};
3418 3426
3427static int find_cpu_to_read(struct perf_event *event, int local_cpu)
3428{
3429 int event_cpu = event->oncpu;
3430 u16 local_pkg, event_pkg;
3431
3432 if (event->group_caps & PERF_EV_CAP_READ_ACTIVE_PKG) {
3433 event_pkg = topology_physical_package_id(event_cpu);
3434 local_pkg = topology_physical_package_id(local_cpu);
3435
3436 if (event_pkg == local_pkg)
3437 return local_cpu;
3438 }
3439
3440 return event_cpu;
3441}
3442
3419/* 3443/*
3420 * Cross CPU call to read the hardware event 3444 * Cross CPU call to read the hardware event
3421 */ 3445 */
@@ -3537,7 +3561,7 @@ u64 perf_event_read_local(struct perf_event *event)
3537 3561
3538static int perf_event_read(struct perf_event *event, bool group) 3562static int perf_event_read(struct perf_event *event, bool group)
3539{ 3563{
3540 int ret = 0; 3564 int ret = 0, cpu_to_read, local_cpu;
3541 3565
3542 /* 3566 /*
3543 * If event is enabled and currently active on a CPU, update the 3567 * If event is enabled and currently active on a CPU, update the
@@ -3549,6 +3573,11 @@ static int perf_event_read(struct perf_event *event, bool group)
3549 .group = group, 3573 .group = group,
3550 .ret = 0, 3574 .ret = 0,
3551 }; 3575 };
3576
3577 local_cpu = get_cpu();
3578 cpu_to_read = find_cpu_to_read(event, local_cpu);
3579 put_cpu();
3580
3552 /* 3581 /*
3553 * Purposely ignore the smp_call_function_single() return 3582 * Purposely ignore the smp_call_function_single() return
3554 * value. 3583 * value.
@@ -3559,7 +3588,7 @@ static int perf_event_read(struct perf_event *event, bool group)
3559 * Therefore, either way, we'll have an up-to-date event count 3588 * Therefore, either way, we'll have an up-to-date event count
3560 * after this. 3589 * after this.
3561 */ 3590 */
3562 (void)smp_call_function_single(event->oncpu, __perf_event_read, &data, 1); 3591 (void)smp_call_function_single(cpu_to_read, __perf_event_read, &data, 1);
3563 ret = data.ret; 3592 ret = data.ret;
3564 } else if (event->state == PERF_EVENT_STATE_INACTIVE) { 3593 } else if (event->state == PERF_EVENT_STATE_INACTIVE) {
3565 struct perf_event_context *ctx = event->ctx; 3594 struct perf_event_context *ctx = event->ctx;
@@ -5350,9 +5379,10 @@ perf_output_sample_regs(struct perf_output_handle *handle,
5350 struct pt_regs *regs, u64 mask) 5379 struct pt_regs *regs, u64 mask)
5351{ 5380{
5352 int bit; 5381 int bit;
5382 DECLARE_BITMAP(_mask, 64);
5353 5383
5354 for_each_set_bit(bit, (const unsigned long *) &mask, 5384 bitmap_from_u64(_mask, mask);
5355 sizeof(mask) * BITS_PER_BYTE) { 5385 for_each_set_bit(bit, _mask, sizeof(mask) * BITS_PER_BYTE) {
5356 u64 val; 5386 u64 val;
5357 5387
5358 val = perf_reg_value(regs, bit); 5388 val = perf_reg_value(regs, bit);
@@ -9505,6 +9535,9 @@ SYSCALL_DEFINE5(perf_event_open,
9505 goto err_alloc; 9535 goto err_alloc;
9506 } 9536 }
9507 9537
9538 if (pmu->task_ctx_nr == perf_sw_context)
9539 event->event_caps |= PERF_EV_CAP_SOFTWARE;
9540
9508 if (group_leader && 9541 if (group_leader &&
9509 (is_software_event(event) != is_software_event(group_leader))) { 9542 (is_software_event(event) != is_software_event(group_leader))) {
9510 if (is_software_event(event)) { 9543 if (is_software_event(event)) {
@@ -9518,7 +9551,7 @@ SYSCALL_DEFINE5(perf_event_open,
9518 */ 9551 */
9519 pmu = group_leader->pmu; 9552 pmu = group_leader->pmu;
9520 } else if (is_software_event(group_leader) && 9553 } else if (is_software_event(group_leader) &&
9521 (group_leader->group_flags & PERF_GROUP_SOFTWARE)) { 9554 (group_leader->group_caps & PERF_EV_CAP_SOFTWARE)) {
9522 /* 9555 /*
9523 * In case the group is a pure software group, and we 9556 * In case the group is a pure software group, and we
9524 * try to add a hardware event, move the whole group to 9557 * try to add a hardware event, move the whole group to
@@ -10453,6 +10486,8 @@ static void __init perf_event_init_all_cpus(void)
10453 10486
10454 INIT_LIST_HEAD(&per_cpu(pmu_sb_events.list, cpu)); 10487 INIT_LIST_HEAD(&per_cpu(pmu_sb_events.list, cpu));
10455 raw_spin_lock_init(&per_cpu(pmu_sb_events.lock, cpu)); 10488 raw_spin_lock_init(&per_cpu(pmu_sb_events.lock, cpu));
10489
10490 INIT_LIST_HEAD(&per_cpu(sched_cb_list, cpu));
10456 } 10491 }
10457} 10492}
10458 10493
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 8c50276b60d1..d4129bb05e5d 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -150,7 +150,7 @@ static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
150 * Returns 0 on success, -EFAULT on failure. 150 * Returns 0 on success, -EFAULT on failure.
151 */ 151 */
152static int __replace_page(struct vm_area_struct *vma, unsigned long addr, 152static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
153 struct page *page, struct page *kpage) 153 struct page *old_page, struct page *new_page)
154{ 154{
155 struct mm_struct *mm = vma->vm_mm; 155 struct mm_struct *mm = vma->vm_mm;
156 spinlock_t *ptl; 156 spinlock_t *ptl;
@@ -161,49 +161,49 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
161 const unsigned long mmun_end = addr + PAGE_SIZE; 161 const unsigned long mmun_end = addr + PAGE_SIZE;
162 struct mem_cgroup *memcg; 162 struct mem_cgroup *memcg;
163 163
164 err = mem_cgroup_try_charge(kpage, vma->vm_mm, GFP_KERNEL, &memcg, 164 err = mem_cgroup_try_charge(new_page, vma->vm_mm, GFP_KERNEL, &memcg,
165 false); 165 false);
166 if (err) 166 if (err)
167 return err; 167 return err;
168 168
169 /* For try_to_free_swap() and munlock_vma_page() below */ 169 /* For try_to_free_swap() and munlock_vma_page() below */
170 lock_page(page); 170 lock_page(old_page);
171 171
172 mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); 172 mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
173 err = -EAGAIN; 173 err = -EAGAIN;
174 ptep = page_check_address(page, mm, addr, &ptl, 0); 174 ptep = page_check_address(old_page, mm, addr, &ptl, 0);
175 if (!ptep) { 175 if (!ptep) {
176 mem_cgroup_cancel_charge(kpage, memcg, false); 176 mem_cgroup_cancel_charge(new_page, memcg, false);
177 goto unlock; 177 goto unlock;
178 } 178 }
179 179
180 get_page(kpage); 180 get_page(new_page);
181 page_add_new_anon_rmap(kpage, vma, addr, false); 181 page_add_new_anon_rmap(new_page, vma, addr, false);
182 mem_cgroup_commit_charge(kpage, memcg, false, false); 182 mem_cgroup_commit_charge(new_page, memcg, false, false);
183 lru_cache_add_active_or_unevictable(kpage, vma); 183 lru_cache_add_active_or_unevictable(new_page, vma);
184 184
185 if (!PageAnon(page)) { 185 if (!PageAnon(old_page)) {
186 dec_mm_counter(mm, mm_counter_file(page)); 186 dec_mm_counter(mm, mm_counter_file(old_page));
187 inc_mm_counter(mm, MM_ANONPAGES); 187 inc_mm_counter(mm, MM_ANONPAGES);
188 } 188 }
189 189
190 flush_cache_page(vma, addr, pte_pfn(*ptep)); 190 flush_cache_page(vma, addr, pte_pfn(*ptep));
191 ptep_clear_flush_notify(vma, addr, ptep); 191 ptep_clear_flush_notify(vma, addr, ptep);
192 set_pte_at_notify(mm, addr, ptep, mk_pte(kpage, vma->vm_page_prot)); 192 set_pte_at_notify(mm, addr, ptep, mk_pte(new_page, vma->vm_page_prot));
193 193
194 page_remove_rmap(page, false); 194 page_remove_rmap(old_page, false);
195 if (!page_mapped(page)) 195 if (!page_mapped(old_page))
196 try_to_free_swap(page); 196 try_to_free_swap(old_page);
197 pte_unmap_unlock(ptep, ptl); 197 pte_unmap_unlock(ptep, ptl);
198 198
199 if (vma->vm_flags & VM_LOCKED) 199 if (vma->vm_flags & VM_LOCKED)
200 munlock_vma_page(page); 200 munlock_vma_page(old_page);
201 put_page(page); 201 put_page(old_page);
202 202
203 err = 0; 203 err = 0;
204 unlock: 204 unlock:
205 mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); 205 mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
206 unlock_page(page); 206 unlock_page(old_page);
207 return err; 207 return err;
208} 208}
209 209
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 7bc56762ca35..37824d98ae71 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4123,6 +4123,30 @@ static const char readme_msg[] =
4123 "\t\t\t traces\n" 4123 "\t\t\t traces\n"
4124#endif 4124#endif
4125#endif /* CONFIG_STACK_TRACER */ 4125#endif /* CONFIG_STACK_TRACER */
4126#ifdef CONFIG_KPROBE_EVENT
4127 " kprobe_events\t\t- Add/remove/show the kernel dynamic events\n"
4128 "\t\t\t Write into this file to define/undefine new trace events.\n"
4129#endif
4130#ifdef CONFIG_UPROBE_EVENT
4131 " uprobe_events\t\t- Add/remove/show the userspace dynamic events\n"
4132 "\t\t\t Write into this file to define/undefine new trace events.\n"
4133#endif
4134#if defined(CONFIG_KPROBE_EVENT) || defined(CONFIG_UPROBE_EVENT)
4135 "\t accepts: event-definitions (one definition per line)\n"
4136 "\t Format: p|r[:[<group>/]<event>] <place> [<args>]\n"
4137 "\t -:[<group>/]<event>\n"
4138#ifdef CONFIG_KPROBE_EVENT
4139 "\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
4140#endif
4141#ifdef CONFIG_UPROBE_EVENT
4142 "\t place: <path>:<offset>\n"
4143#endif
4144 "\t args: <name>=fetcharg[:type]\n"
4145 "\t fetcharg: %<register>, @<address>, @<symbol>[+|-<offset>],\n"
4146 "\t $stack<index>, $stack, $retval, $comm\n"
4147 "\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string,\n"
4148 "\t b<bit-width>@<bit-offset>/<container-size>\n"
4149#endif
4126 " events/\t\t- Directory containing all trace event subsystems:\n" 4150 " events/\t\t- Directory containing all trace event subsystems:\n"
4127 " enable\t\t- Write 0/1 to enable/disable tracing of all events\n" 4151 " enable\t\t- Write 0/1 to enable/disable tracing of all events\n"
4128 " events/<system>/\t- Directory containing all trace events for <system>:\n" 4152 " events/<system>/\t- Directory containing all trace events for <system>:\n"
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 9aedb0b06683..eb6c9f1d3a93 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -253,6 +253,10 @@ static const struct fetch_type kprobes_fetch_type_table[] = {
253 ASSIGN_FETCH_TYPE(s16, u16, 1), 253 ASSIGN_FETCH_TYPE(s16, u16, 1),
254 ASSIGN_FETCH_TYPE(s32, u32, 1), 254 ASSIGN_FETCH_TYPE(s32, u32, 1),
255 ASSIGN_FETCH_TYPE(s64, u64, 1), 255 ASSIGN_FETCH_TYPE(s64, u64, 1),
256 ASSIGN_FETCH_TYPE_ALIAS(x8, u8, u8, 0),
257 ASSIGN_FETCH_TYPE_ALIAS(x16, u16, u16, 0),
258 ASSIGN_FETCH_TYPE_ALIAS(x32, u32, u32, 0),
259 ASSIGN_FETCH_TYPE_ALIAS(x64, u64, u64, 0),
256 260
257 ASSIGN_FETCH_TYPE_END 261 ASSIGN_FETCH_TYPE_END
258}; 262};
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index 74e80a582c28..8c0553d9afd3 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -36,24 +36,28 @@ const char *reserved_field_names[] = {
36}; 36};
37 37
38/* Printing in basic type function template */ 38/* Printing in basic type function template */
39#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt) \ 39#define DEFINE_BASIC_PRINT_TYPE_FUNC(tname, type, fmt) \
40int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, const char *name, \ 40int PRINT_TYPE_FUNC_NAME(tname)(struct trace_seq *s, const char *name, \
41 void *data, void *ent) \ 41 void *data, void *ent) \
42{ \ 42{ \
43 trace_seq_printf(s, " %s=" fmt, name, *(type *)data); \ 43 trace_seq_printf(s, " %s=" fmt, name, *(type *)data); \
44 return !trace_seq_has_overflowed(s); \ 44 return !trace_seq_has_overflowed(s); \
45} \ 45} \
46const char PRINT_TYPE_FMT_NAME(type)[] = fmt; \ 46const char PRINT_TYPE_FMT_NAME(tname)[] = fmt; \
47NOKPROBE_SYMBOL(PRINT_TYPE_FUNC_NAME(type)); 47NOKPROBE_SYMBOL(PRINT_TYPE_FUNC_NAME(tname));
48 48
49DEFINE_BASIC_PRINT_TYPE_FUNC(u8 , "0x%x") 49DEFINE_BASIC_PRINT_TYPE_FUNC(u8, u8, "%u")
50DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "0x%x") 50DEFINE_BASIC_PRINT_TYPE_FUNC(u16, u16, "%u")
51DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "0x%x") 51DEFINE_BASIC_PRINT_TYPE_FUNC(u32, u32, "%u")
52DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "0x%Lx") 52DEFINE_BASIC_PRINT_TYPE_FUNC(u64, u64, "%Lu")
53DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d") 53DEFINE_BASIC_PRINT_TYPE_FUNC(s8, s8, "%d")
54DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d") 54DEFINE_BASIC_PRINT_TYPE_FUNC(s16, s16, "%d")
55DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%d") 55DEFINE_BASIC_PRINT_TYPE_FUNC(s32, s32, "%d")
56DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%Ld") 56DEFINE_BASIC_PRINT_TYPE_FUNC(s64, s64, "%Ld")
57DEFINE_BASIC_PRINT_TYPE_FUNC(x8, u8, "0x%x")
58DEFINE_BASIC_PRINT_TYPE_FUNC(x16, u16, "0x%x")
59DEFINE_BASIC_PRINT_TYPE_FUNC(x32, u32, "0x%x")
60DEFINE_BASIC_PRINT_TYPE_FUNC(x64, u64, "0x%Lx")
57 61
58/* Print type function for string type */ 62/* Print type function for string type */
59int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, const char *name, 63int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, const char *name,
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 45400ca5ded1..0c0ae54d44c6 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -149,6 +149,11 @@ DECLARE_BASIC_PRINT_TYPE_FUNC(s8);
149DECLARE_BASIC_PRINT_TYPE_FUNC(s16); 149DECLARE_BASIC_PRINT_TYPE_FUNC(s16);
150DECLARE_BASIC_PRINT_TYPE_FUNC(s32); 150DECLARE_BASIC_PRINT_TYPE_FUNC(s32);
151DECLARE_BASIC_PRINT_TYPE_FUNC(s64); 151DECLARE_BASIC_PRINT_TYPE_FUNC(s64);
152DECLARE_BASIC_PRINT_TYPE_FUNC(x8);
153DECLARE_BASIC_PRINT_TYPE_FUNC(x16);
154DECLARE_BASIC_PRINT_TYPE_FUNC(x32);
155DECLARE_BASIC_PRINT_TYPE_FUNC(x64);
156
152DECLARE_BASIC_PRINT_TYPE_FUNC(string); 157DECLARE_BASIC_PRINT_TYPE_FUNC(string);
153 158
154#define FETCH_FUNC_NAME(method, type) fetch_##method##_##type 159#define FETCH_FUNC_NAME(method, type) fetch_##method##_##type
@@ -203,7 +208,7 @@ DEFINE_FETCH_##method(u32) \
203DEFINE_FETCH_##method(u64) 208DEFINE_FETCH_##method(u64)
204 209
205/* Default (unsigned long) fetch type */ 210/* Default (unsigned long) fetch type */
206#define __DEFAULT_FETCH_TYPE(t) u##t 211#define __DEFAULT_FETCH_TYPE(t) x##t
207#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) 212#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t)
208#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) 213#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG)
209#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) 214#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE)
@@ -234,6 +239,10 @@ ASSIGN_FETCH_FUNC(file_offset, ftype), \
234#define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ 239#define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \
235 __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype) 240 __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype)
236 241
242/* If ptype is an alias of atype, use this macro (show atype in format) */
243#define ASSIGN_FETCH_TYPE_ALIAS(ptype, atype, ftype, sign) \
244 __ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #atype)
245
237#define ASSIGN_FETCH_TYPE_END {} 246#define ASSIGN_FETCH_TYPE_END {}
238 247
239#define FETCH_TYPE_STRING 0 248#define FETCH_TYPE_STRING 0
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index c53485441c88..7a687320f867 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -211,6 +211,10 @@ static const struct fetch_type uprobes_fetch_type_table[] = {
211 ASSIGN_FETCH_TYPE(s16, u16, 1), 211 ASSIGN_FETCH_TYPE(s16, u16, 1),
212 ASSIGN_FETCH_TYPE(s32, u32, 1), 212 ASSIGN_FETCH_TYPE(s32, u32, 1),
213 ASSIGN_FETCH_TYPE(s64, u64, 1), 213 ASSIGN_FETCH_TYPE(s64, u64, 1),
214 ASSIGN_FETCH_TYPE_ALIAS(x8, u8, u8, 0),
215 ASSIGN_FETCH_TYPE_ALIAS(x16, u16, u16, 0),
216 ASSIGN_FETCH_TYPE_ALIAS(x32, u32, u32, 0),
217 ASSIGN_FETCH_TYPE_ALIAS(x64, u64, u64, 0),
214 218
215 ASSIGN_FETCH_TYPE_END 219 ASSIGN_FETCH_TYPE_END
216}; 220};
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/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/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/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];