aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 09:58:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-13 09:58:15 -0400
commit9d9420f1209a1facea7110d549ac695f5aeeb503 (patch)
tree7956d1c40420644830decbbc90b8bbdfeb194364
parent6d5f0ebfc0be9cbfeaafdd9258d5fa24b7975a36 (diff)
parentcc6cd47e7395bc05c5077009808b820633eb3f18 (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "Kernel side updates: - Fix and enhance poll support (Jiri Olsa) - Re-enable inheritance optimization (Jiri Olsa) - Enhance Intel memory events support (Stephane Eranian) - Refactor the Intel uncore driver to be more maintainable (Zheng Yan) - Enhance and fix Intel CPU and uncore PMU drivers (Peter Zijlstra, Andi Kleen) - [ plus various smaller fixes/cleanups ] User visible tooling updates: - Add +field argument support for --field option, so that one can add fields to the default list of fields to show, ie now one can just do: perf report --fields +pid And the pid will appear in addition to the default fields (Jiri Olsa) - Add +field argument support for --sort option (Jiri Olsa) - Honour -w in the report tools (report, top), allowing to specify the widths for the histogram entries columns (Namhyung Kim) - Properly show submicrosecond times in 'perf kvm stat' (Christian Borntraeger) - Add beautifier for mremap flags param in 'trace' (Alex Snast) - perf script: Allow callchains if any event samples them - Don't truncate Intel style addresses in 'annotate' (Alex Converse) - Allow profiling when kptr_restrict == 1 for non root users, kernel samples will just remain unresolved (Andi Kleen) - Allow configuring default options for callchains in config file (Namhyung Kim) - Support operations for shared futexes. (Davidlohr Bueso) - "perf kvm stat report" improvements by Alexander Yarygin: - Save pid string in opts.target.pid - Enable the target.system_wide flag - Unify the title bar output - [ plus lots of other fixes and small improvements. ] Tooling infrastructure changes: - Refactor unit and scale function parameters for PMU parsing routines (Matt Fleming) - Improve DSO long names lookup with rbtree, resulting in great speedup for workloads with lots of DSOs (Waiman Long) - We were not handling POLLHUP notifications for event file descriptors Fix it by filtering entries in the events file descriptor array after poll() returns, refcounting mmaps so that when the last fd pointing to a perf mmap goes away we do the unmap (Arnaldo Carvalho de Melo) - Intel PT prep work, from Adrian Hunter, including: - Let a user specify a PMU event without any config terms - Add perf-with-kcore script - Let default config be defined for a PMU - Add perf_pmu__scan_file() - Add a 'perf test' for tracking with sched_switch - Add 'flush' callback to scripting API - Use ring buffer consume method to look like other tools (Arnaldo Carvalho de Melo) - hists browser (used in top and report) refactorings, getting rid of unused variables and reducing source code size by handling similar cases in a fewer functions (Namhyung Kim). - Replace thread unsafe strerror() with strerror_r() accross the whole tools/perf/ tree (Masami Hiramatsu) - Rename ordered_samples to ordered_events and allow setting a queue size for ordering events (Jiri Olsa) - [ plus lots of fixes, cleanups and other improvements ]" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (198 commits) perf/x86: Tone down kernel messages when the PMU check fails in a virtual environment perf/x86/intel/uncore: Fix minor race in box set up perf record: Fix error message for --filter option not coming after tracepoint perf tools: Fix build breakage on arm64 targets perf symbols: Improve DSO long names lookup speed with rbtree perf symbols: Encapsulate dsos list head into struct dsos perf bench futex: Sanitize -q option in requeue perf bench futex: Support operations for shared futexes perf trace: Fix mmap return address truncation to 32-bit perf tools: Refactor unit and scale function parameters perf tools: Fix line number in the config file error message perf tools: Convert {record,top}.call-graph option to call-graph.record-mode perf tools: Introduce perf_callchain_config() perf callchain: Move some parser functions to callchain.c perf tools: Move callchain config from record_opts to callchain_param perf hists browser: Fix callchain print bug on TUI perf tools: Use ACCESS_ONCE() instead of volatile cast perf tools: Modify error code for when perf_session__new() fails perf tools: Fix perf record as non root with kptr_restrict == 1 perf stat: Fix --per-core on multi socket systems ...
-rw-r--r--arch/x86/include/asm/perf_event.h8
-rw-r--r--arch/x86/kernel/cpu/Makefile4
-rw-r--r--arch/x86/kernel/cpu/perf_event.c14
-rw-r--r--arch/x86/kernel/cpu/perf_event.h49
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c229
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c185
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_lbr.c8
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.c3175
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.h439
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c1221
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c636
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c2258
-rw-r--r--include/linux/jump_label.h17
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/linux/perf_event.h14
-rw-r--r--kernel/events/callchain.c2
-rw-r--r--kernel/events/core.c158
-rw-r--r--tools/lib/api/Makefile7
-rw-r--r--tools/lib/api/fd/array.c127
-rw-r--r--tools/lib/api/fd/array.h46
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/perf-probe.txt3
-rw-r--r--tools/perf/Documentation/perf-report.txt5
-rw-r--r--tools/perf/Documentation/perf-top.txt9
-rw-r--r--tools/perf/Makefile.perf11
-rw-r--r--tools/perf/arch/arm/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/arm/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/arm64/include/perf_regs.h2
-rw-r--r--tools/perf/arch/arm64/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/common.c9
-rw-r--r--tools/perf/arch/powerpc/Makefile2
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c1
-rw-r--r--tools/perf/bench/futex-hash.c7
-rw-r--r--tools/perf/bench/futex-requeue.c28
-rw-r--r--tools/perf/bench/futex-wake.c15
-rw-r--r--tools/perf/bench/sched-messaging.c2
-rw-r--r--tools/perf/builtin-annotate.c77
-rw-r--r--tools/perf/builtin-buildid-cache.c44
-rw-r--r--tools/perf/builtin-diff.c6
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-help.c20
-rw-r--r--tools/perf/builtin-inject.c33
-rw-r--r--tools/perf/builtin-kmem.c56
-rw-r--r--tools/perf/builtin-kvm.c98
-rw-r--r--tools/perf/builtin-lock.c7
-rw-r--r--tools/perf/builtin-mem.c6
-rw-r--r--tools/perf/builtin-probe.c10
-rw-r--r--tools/perf/builtin-record.c146
-rw-r--r--tools/perf/builtin-report.c23
-rw-r--r--tools/perf/builtin-sched.c9
-rw-r--r--tools/perf/builtin-script.c74
-rw-r--r--tools/perf/builtin-stat.c11
-rw-r--r--tools/perf/builtin-timechart.c8
-rw-r--r--tools/perf/builtin-top.c87
-rw-r--r--tools/perf/builtin-trace.c57
-rw-r--r--tools/perf/config/Makefile52
-rw-r--r--tools/perf/config/feature-checks/Makefile18
-rw-r--r--tools/perf/config/utilities.mak2
-rw-r--r--tools/perf/perf-with-kcore.sh259
-rw-r--r--tools/perf/perf.c10
-rw-r--r--tools/perf/perf.h3
-rw-r--r--tools/perf/tests/builtin-test.c18
-rw-r--r--tools/perf/tests/fdarray.c174
-rw-r--r--tools/perf/tests/mmap-basic.c7
-rw-r--r--tools/perf/tests/open-syscall-all-cpus.c5
-rw-r--r--tools/perf/tests/open-syscall-tp-fields.c9
-rw-r--r--tools/perf/tests/open-syscall.c3
-rw-r--r--tools/perf/tests/perf-record.c15
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/rdpmc.c6
-rw-r--r--tools/perf/tests/sw-clock.c6
-rw-r--r--tools/perf/tests/switch-tracking.c572
-rw-r--r--tools/perf/tests/task-exit.c8
-rw-r--r--tools/perf/tests/tests.h3
-rw-r--r--tools/perf/ui/browsers/hists.c384
-rw-r--r--tools/perf/ui/gtk/hists.c18
-rw-r--r--tools/perf/ui/hist.c284
-rw-r--r--tools/perf/ui/stdio/hist.c4
-rw-r--r--tools/perf/util/annotate.c21
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c240
-rw-r--r--tools/perf/util/callchain.h6
-rw-r--r--tools/perf/util/cloexec.c35
-rw-r--r--tools/perf/util/color.c16
-rw-r--r--tools/perf/util/color.h1
-rw-r--r--tools/perf/util/comm.c7
-rw-r--r--tools/perf/util/comm.h6
-rw-r--r--tools/perf/util/config.c40
-rw-r--r--tools/perf/util/data.c8
-rw-r--r--tools/perf/util/debug.c36
-rw-r--r--tools/perf/util/debug.h11
-rw-r--r--tools/perf/util/dso.c121
-rw-r--r--tools/perf/util/dso.h16
-rw-r--r--tools/perf/util/event.c14
-rw-r--r--tools/perf/util/event.h2
-rw-r--r--tools/perf/util/evlist.c236
-rw-r--r--tools/perf/util/evlist.h21
-rw-r--r--tools/perf/util/evsel.c67
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/header.c32
-rw-r--r--tools/perf/util/hist.c22
-rw-r--r--tools/perf/util/hist.h18
-rw-r--r--tools/perf/util/kvm-stat.h1
-rw-r--r--tools/perf/util/machine.c96
-rw-r--r--tools/perf/util/machine.h26
-rw-r--r--tools/perf/util/map.c1
-rw-r--r--tools/perf/util/ordered-events.c245
-rw-r--r--tools/perf/util/ordered-events.h51
-rw-r--r--tools/perf/util/parse-events.c29
-rw-r--r--tools/perf/util/parse-events.y10
-rw-r--r--tools/perf/util/pmu.c121
-rw-r--r--tools/perf/util/pmu.h25
-rw-r--r--tools/perf/util/probe-event.c181
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/probe-finder.c23
-rw-r--r--tools/perf/util/python.c6
-rw-r--r--tools/perf/util/record.c40
-rw-r--r--tools/perf/util/run-command.c9
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c120
-rw-r--r--tools/perf/util/session.c300
-rw-r--r--tools/perf/util/session.h32
-rw-r--r--tools/perf/util/sort.c119
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/symbol-elf.c31
-rw-r--r--tools/perf/util/symbol.c43
-rw-r--r--tools/perf/util/symbol.h14
-rw-r--r--tools/perf/util/thread.c24
-rw-r--r--tools/perf/util/thread.h10
-rw-r--r--tools/perf/util/tool.h2
-rw-r--r--tools/perf/util/trace-event-scripting.c7
-rw-r--r--tools/perf/util/trace-event.h1
-rw-r--r--tools/perf/util/util.c54
-rw-r--r--tools/perf/util/util.h23
134 files changed, 8840 insertions, 5125 deletions
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 8249df45d2f2..8dfc9fd094a3 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -51,6 +51,14 @@
51 ARCH_PERFMON_EVENTSEL_EDGE | \ 51 ARCH_PERFMON_EVENTSEL_EDGE | \
52 ARCH_PERFMON_EVENTSEL_INV | \ 52 ARCH_PERFMON_EVENTSEL_INV | \
53 ARCH_PERFMON_EVENTSEL_CMASK) 53 ARCH_PERFMON_EVENTSEL_CMASK)
54#define X86_ALL_EVENT_FLAGS \
55 (ARCH_PERFMON_EVENTSEL_EDGE | \
56 ARCH_PERFMON_EVENTSEL_INV | \
57 ARCH_PERFMON_EVENTSEL_CMASK | \
58 ARCH_PERFMON_EVENTSEL_ANY | \
59 ARCH_PERFMON_EVENTSEL_PIN_CONTROL | \
60 HSW_IN_TX | \
61 HSW_IN_TX_CHECKPOINTED)
54#define AMD64_RAW_EVENT_MASK \ 62#define AMD64_RAW_EVENT_MASK \
55 (X86_RAW_EVENT_MASK | \ 63 (X86_RAW_EVENT_MASK | \
56 AMD64_EVENTSEL_EVENT) 64 AMD64_EVENTSEL_EVENT)
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 77dcab277710..01d5453b5502 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -39,7 +39,9 @@ obj-$(CONFIG_CPU_SUP_AMD) += perf_event_amd_iommu.o
39endif 39endif
40obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_p6.o perf_event_knc.o perf_event_p4.o 40obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_p6.o perf_event_knc.o perf_event_p4.o
41obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o 41obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
42obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_uncore.o perf_event_intel_rapl.o 42obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_uncore.o perf_event_intel_uncore_snb.o
43obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_uncore_snbep.o perf_event_intel_uncore_nhmex.o
44obj-$(CONFIG_CPU_SUP_INTEL) += perf_event_intel_rapl.o
43endif 45endif
44 46
45 47
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 2879ecdaac43..16c73022306e 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -243,7 +243,8 @@ static bool check_hw_exists(void)
243 243
244msr_fail: 244msr_fail:
245 printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n"); 245 printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n");
246 printk(KERN_ERR "Failed to access perfctr msr (MSR %x is %Lx)\n", reg, val_new); 246 printk(boot_cpu_has(X86_FEATURE_HYPERVISOR) ? KERN_INFO : KERN_ERR
247 "Failed to access perfctr msr (MSR %x is %Lx)\n", reg, val_new);
247 248
248 return false; 249 return false;
249} 250}
@@ -387,7 +388,7 @@ int x86_pmu_hw_config(struct perf_event *event)
387 precise++; 388 precise++;
388 389
389 /* Support for IP fixup */ 390 /* Support for IP fixup */
390 if (x86_pmu.lbr_nr) 391 if (x86_pmu.lbr_nr || x86_pmu.intel_cap.pebs_format >= 2)
391 precise++; 392 precise++;
392 } 393 }
393 394
@@ -443,6 +444,12 @@ int x86_pmu_hw_config(struct perf_event *event)
443 if (event->attr.type == PERF_TYPE_RAW) 444 if (event->attr.type == PERF_TYPE_RAW)
444 event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK; 445 event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK;
445 446
447 if (event->attr.sample_period && x86_pmu.limit_period) {
448 if (x86_pmu.limit_period(event, event->attr.sample_period) >
449 event->attr.sample_period)
450 return -EINVAL;
451 }
452
446 return x86_setup_perfctr(event); 453 return x86_setup_perfctr(event);
447} 454}
448 455
@@ -980,6 +987,9 @@ int x86_perf_event_set_period(struct perf_event *event)
980 if (left > x86_pmu.max_period) 987 if (left > x86_pmu.max_period)
981 left = x86_pmu.max_period; 988 left = x86_pmu.max_period;
982 989
990 if (x86_pmu.limit_period)
991 left = x86_pmu.limit_period(event, left);
992
983 per_cpu(pmc_prev_left[idx], smp_processor_id()) = left; 993 per_cpu(pmc_prev_left[idx], smp_processor_id()) = left;
984 994
985 /* 995 /*
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 8ade93111e03..d98a34d435d7 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -67,8 +67,10 @@ struct event_constraint {
67 */ 67 */
68#define PERF_X86_EVENT_PEBS_LDLAT 0x1 /* ld+ldlat data address sampling */ 68#define PERF_X86_EVENT_PEBS_LDLAT 0x1 /* ld+ldlat data address sampling */
69#define PERF_X86_EVENT_PEBS_ST 0x2 /* st data address sampling */ 69#define PERF_X86_EVENT_PEBS_ST 0x2 /* st data address sampling */
70#define PERF_X86_EVENT_PEBS_ST_HSW 0x4 /* haswell style st data sampling */ 70#define PERF_X86_EVENT_PEBS_ST_HSW 0x4 /* haswell style datala, store */
71#define PERF_X86_EVENT_COMMITTED 0x8 /* event passed commit_txn */ 71#define PERF_X86_EVENT_COMMITTED 0x8 /* event passed commit_txn */
72#define PERF_X86_EVENT_PEBS_LD_HSW 0x10 /* haswell style datala, load */
73#define PERF_X86_EVENT_PEBS_NA_HSW 0x20 /* haswell style datala, unknown */
72 74
73struct amd_nb { 75struct amd_nb {
74 int nb_id; /* NorthBridge id */ 76 int nb_id; /* NorthBridge id */
@@ -252,18 +254,52 @@ struct cpu_hw_events {
252 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK) 254 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
253 255
254#define INTEL_PLD_CONSTRAINT(c, n) \ 256#define INTEL_PLD_CONSTRAINT(c, n) \
255 __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK, \ 257 __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
256 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LDLAT) 258 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LDLAT)
257 259
258#define INTEL_PST_CONSTRAINT(c, n) \ 260#define INTEL_PST_CONSTRAINT(c, n) \
259 __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK, \ 261 __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
260 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST) 262 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST)
261 263
262/* DataLA version of store sampling without extra enable bit. */ 264/* Event constraint, but match on all event flags too. */
263#define INTEL_PST_HSW_CONSTRAINT(c, n) \ 265#define INTEL_FLAGS_EVENT_CONSTRAINT(c, n) \
264 __EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK, \ 266 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS)
267
268/* Check only flags, but allow all event/umask */
269#define INTEL_ALL_EVENT_CONSTRAINT(code, n) \
270 EVENT_CONSTRAINT(code, n, X86_ALL_EVENT_FLAGS)
271
272/* Check flags and event code, and set the HSW store flag */
273#define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_ST(code, n) \
274 __EVENT_CONSTRAINT(code, n, \
275 ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
276 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
277
278/* Check flags and event code, and set the HSW load flag */
279#define INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(code, n) \
280 __EVENT_CONSTRAINT(code, n, \
281 ARCH_PERFMON_EVENTSEL_EVENT|X86_ALL_EVENT_FLAGS, \
282 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LD_HSW)
283
284/* Check flags and event code/umask, and set the HSW store flag */
285#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(code, n) \
286 __EVENT_CONSTRAINT(code, n, \
287 INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
265 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW) 288 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_ST_HSW)
266 289
290/* Check flags and event code/umask, and set the HSW load flag */
291#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(code, n) \
292 __EVENT_CONSTRAINT(code, n, \
293 INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
294 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_LD_HSW)
295
296/* Check flags and event code/umask, and set the HSW N/A flag */
297#define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(code, n) \
298 __EVENT_CONSTRAINT(code, n, \
299 INTEL_ARCH_EVENT_MASK|INTEL_ARCH_EVENT_MASK, \
300 HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_NA_HSW)
301
302
267/* 303/*
268 * We define the end marker as having a weight of -1 304 * We define the end marker as having a weight of -1
269 * to enable blacklisting of events using a counter bitmask 305 * to enable blacklisting of events using a counter bitmask
@@ -409,6 +445,7 @@ struct x86_pmu {
409 struct x86_pmu_quirk *quirks; 445 struct x86_pmu_quirk *quirks;
410 int perfctr_second_write; 446 int perfctr_second_write;
411 bool late_ack; 447 bool late_ack;
448 unsigned (*limit_period)(struct perf_event *event, unsigned l);
412 449
413 /* 450 /*
414 * sysfs attrs 451 * sysfs attrs
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 2502d0d9d246..3851def5057c 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -220,6 +220,15 @@ static struct event_constraint intel_hsw_event_constraints[] = {
220 EVENT_CONSTRAINT_END 220 EVENT_CONSTRAINT_END
221}; 221};
222 222
223static struct event_constraint intel_bdw_event_constraints[] = {
224 FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
225 FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
226 FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
227 INTEL_UEVENT_CONSTRAINT(0x148, 0x4), /* L1D_PEND_MISS.PENDING */
228 INTEL_EVENT_CONSTRAINT(0xa3, 0x4), /* CYCLE_ACTIVITY.* */
229 EVENT_CONSTRAINT_END
230};
231
223static u64 intel_pmu_event_map(int hw_event) 232static u64 intel_pmu_event_map(int hw_event)
224{ 233{
225 return intel_perfmon_event_map[hw_event]; 234 return intel_perfmon_event_map[hw_event];
@@ -415,6 +424,126 @@ static __initconst const u64 snb_hw_cache_event_ids
415 424
416}; 425};
417 426
427static __initconst const u64 hsw_hw_cache_event_ids
428 [PERF_COUNT_HW_CACHE_MAX]
429 [PERF_COUNT_HW_CACHE_OP_MAX]
430 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
431{
432 [ C(L1D ) ] = {
433 [ C(OP_READ) ] = {
434 [ C(RESULT_ACCESS) ] = 0x81d0, /* MEM_UOPS_RETIRED.ALL_LOADS */
435 [ C(RESULT_MISS) ] = 0x151, /* L1D.REPLACEMENT */
436 },
437 [ C(OP_WRITE) ] = {
438 [ C(RESULT_ACCESS) ] = 0x82d0, /* MEM_UOPS_RETIRED.ALL_STORES */
439 [ C(RESULT_MISS) ] = 0x0,
440 },
441 [ C(OP_PREFETCH) ] = {
442 [ C(RESULT_ACCESS) ] = 0x0,
443 [ C(RESULT_MISS) ] = 0x0,
444 },
445 },
446 [ C(L1I ) ] = {
447 [ C(OP_READ) ] = {
448 [ C(RESULT_ACCESS) ] = 0x0,
449 [ C(RESULT_MISS) ] = 0x280, /* ICACHE.MISSES */
450 },
451 [ C(OP_WRITE) ] = {
452 [ C(RESULT_ACCESS) ] = -1,
453 [ C(RESULT_MISS) ] = -1,
454 },
455 [ C(OP_PREFETCH) ] = {
456 [ C(RESULT_ACCESS) ] = 0x0,
457 [ C(RESULT_MISS) ] = 0x0,
458 },
459 },
460 [ C(LL ) ] = {
461 [ C(OP_READ) ] = {
462 /* OFFCORE_RESPONSE:ALL_DATA_RD|ALL_CODE_RD */
463 [ C(RESULT_ACCESS) ] = 0x1b7,
464 /* OFFCORE_RESPONSE:ALL_DATA_RD|ALL_CODE_RD|SUPPLIER_NONE|
465 L3_MISS|ANY_SNOOP */
466 [ C(RESULT_MISS) ] = 0x1b7,
467 },
468 [ C(OP_WRITE) ] = {
469 [ C(RESULT_ACCESS) ] = 0x1b7, /* OFFCORE_RESPONSE:ALL_RFO */
470 /* OFFCORE_RESPONSE:ALL_RFO|SUPPLIER_NONE|L3_MISS|ANY_SNOOP */
471 [ C(RESULT_MISS) ] = 0x1b7,
472 },
473 [ C(OP_PREFETCH) ] = {
474 [ C(RESULT_ACCESS) ] = 0x0,
475 [ C(RESULT_MISS) ] = 0x0,
476 },
477 },
478 [ C(DTLB) ] = {
479 [ C(OP_READ) ] = {
480 [ C(RESULT_ACCESS) ] = 0x81d0, /* MEM_UOPS_RETIRED.ALL_LOADS */
481 [ C(RESULT_MISS) ] = 0x108, /* DTLB_LOAD_MISSES.MISS_CAUSES_A_WALK */
482 },
483 [ C(OP_WRITE) ] = {
484 [ C(RESULT_ACCESS) ] = 0x82d0, /* MEM_UOPS_RETIRED.ALL_STORES */
485 [ C(RESULT_MISS) ] = 0x149, /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
486 },
487 [ C(OP_PREFETCH) ] = {
488 [ C(RESULT_ACCESS) ] = 0x0,
489 [ C(RESULT_MISS) ] = 0x0,
490 },
491 },
492 [ C(ITLB) ] = {
493 [ C(OP_READ) ] = {
494 [ C(RESULT_ACCESS) ] = 0x6085, /* ITLB_MISSES.STLB_HIT */
495 [ C(RESULT_MISS) ] = 0x185, /* ITLB_MISSES.MISS_CAUSES_A_WALK */
496 },
497 [ C(OP_WRITE) ] = {
498 [ C(RESULT_ACCESS) ] = -1,
499 [ C(RESULT_MISS) ] = -1,
500 },
501 [ C(OP_PREFETCH) ] = {
502 [ C(RESULT_ACCESS) ] = -1,
503 [ C(RESULT_MISS) ] = -1,
504 },
505 },
506 [ C(BPU ) ] = {
507 [ C(OP_READ) ] = {
508 [ C(RESULT_ACCESS) ] = 0xc4, /* BR_INST_RETIRED.ALL_BRANCHES */
509 [ C(RESULT_MISS) ] = 0xc5, /* BR_MISP_RETIRED.ALL_BRANCHES */
510 },
511 [ C(OP_WRITE) ] = {
512 [ C(RESULT_ACCESS) ] = -1,
513 [ C(RESULT_MISS) ] = -1,
514 },
515 [ C(OP_PREFETCH) ] = {
516 [ C(RESULT_ACCESS) ] = -1,
517 [ C(RESULT_MISS) ] = -1,
518 },
519 },
520};
521
522static __initconst const u64 hsw_hw_cache_extra_regs
523 [PERF_COUNT_HW_CACHE_MAX]
524 [PERF_COUNT_HW_CACHE_OP_MAX]
525 [PERF_COUNT_HW_CACHE_RESULT_MAX] =
526{
527 [ C(LL ) ] = {
528 [ C(OP_READ) ] = {
529 /* OFFCORE_RESPONSE:ALL_DATA_RD|ALL_CODE_RD */
530 [ C(RESULT_ACCESS) ] = 0x2d5,
531 /* OFFCORE_RESPONSE:ALL_DATA_RD|ALL_CODE_RD|SUPPLIER_NONE|
532 L3_MISS|ANY_SNOOP */
533 [ C(RESULT_MISS) ] = 0x3fbc0202d5ull,
534 },
535 [ C(OP_WRITE) ] = {
536 [ C(RESULT_ACCESS) ] = 0x122, /* OFFCORE_RESPONSE:ALL_RFO */
537 /* OFFCORE_RESPONSE:ALL_RFO|SUPPLIER_NONE|L3_MISS|ANY_SNOOP */
538 [ C(RESULT_MISS) ] = 0x3fbc020122ull,
539 },
540 [ C(OP_PREFETCH) ] = {
541 [ C(RESULT_ACCESS) ] = 0x0,
542 [ C(RESULT_MISS) ] = 0x0,
543 },
544 },
545};
546
418static __initconst const u64 westmere_hw_cache_event_ids 547static __initconst const u64 westmere_hw_cache_event_ids
419 [PERF_COUNT_HW_CACHE_MAX] 548 [PERF_COUNT_HW_CACHE_MAX]
420 [PERF_COUNT_HW_CACHE_OP_MAX] 549 [PERF_COUNT_HW_CACHE_OP_MAX]
@@ -1905,6 +2034,24 @@ hsw_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
1905 return c; 2034 return c;
1906} 2035}
1907 2036
2037/*
2038 * Broadwell:
2039 * The INST_RETIRED.ALL period always needs to have lowest
2040 * 6bits cleared (BDM57). It shall not use a period smaller
2041 * than 100 (BDM11). We combine the two to enforce
2042 * a min-period of 128.
2043 */
2044static unsigned bdw_limit_period(struct perf_event *event, unsigned left)
2045{
2046 if ((event->hw.config & INTEL_ARCH_EVENT_MASK) ==
2047 X86_CONFIG(.event=0xc0, .umask=0x01)) {
2048 if (left < 128)
2049 left = 128;
2050 left &= ~0x3fu;
2051 }
2052 return left;
2053}
2054
1908PMU_FORMAT_ATTR(event, "config:0-7" ); 2055PMU_FORMAT_ATTR(event, "config:0-7" );
1909PMU_FORMAT_ATTR(umask, "config:8-15" ); 2056PMU_FORMAT_ATTR(umask, "config:8-15" );
1910PMU_FORMAT_ATTR(edge, "config:18" ); 2057PMU_FORMAT_ATTR(edge, "config:18" );
@@ -2367,15 +2514,15 @@ __init int intel_pmu_init(void)
2367 * Install the hw-cache-events table: 2514 * Install the hw-cache-events table:
2368 */ 2515 */
2369 switch (boot_cpu_data.x86_model) { 2516 switch (boot_cpu_data.x86_model) {
2370 case 14: /* 65 nm core solo/duo, "Yonah" */ 2517 case 14: /* 65nm Core "Yonah" */
2371 pr_cont("Core events, "); 2518 pr_cont("Core events, ");
2372 break; 2519 break;
2373 2520
2374 case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ 2521 case 15: /* 65nm Core2 "Merom" */
2375 x86_add_quirk(intel_clovertown_quirk); 2522 x86_add_quirk(intel_clovertown_quirk);
2376 case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ 2523 case 22: /* 65nm Core2 "Merom-L" */
2377 case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ 2524 case 23: /* 45nm Core2 "Penryn" */
2378 case 29: /* six-core 45 nm xeon "Dunnington" */ 2525 case 29: /* 45nm Core2 "Dunnington (MP) */
2379 memcpy(hw_cache_event_ids, core2_hw_cache_event_ids, 2526 memcpy(hw_cache_event_ids, core2_hw_cache_event_ids,
2380 sizeof(hw_cache_event_ids)); 2527 sizeof(hw_cache_event_ids));
2381 2528
@@ -2386,9 +2533,9 @@ __init int intel_pmu_init(void)
2386 pr_cont("Core2 events, "); 2533 pr_cont("Core2 events, ");
2387 break; 2534 break;
2388 2535
2389 case 26: /* 45 nm nehalem, "Bloomfield" */ 2536 case 30: /* 45nm Nehalem */
2390 case 30: /* 45 nm nehalem, "Lynnfield" */ 2537 case 26: /* 45nm Nehalem-EP */
2391 case 46: /* 45 nm nehalem-ex, "Beckton" */ 2538 case 46: /* 45nm Nehalem-EX */
2392 memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, 2539 memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
2393 sizeof(hw_cache_event_ids)); 2540 sizeof(hw_cache_event_ids));
2394 memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs, 2541 memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
@@ -2415,11 +2562,11 @@ __init int intel_pmu_init(void)
2415 pr_cont("Nehalem events, "); 2562 pr_cont("Nehalem events, ");
2416 break; 2563 break;
2417 2564
2418 case 28: /* Atom */ 2565 case 28: /* 45nm Atom "Pineview" */
2419 case 38: /* Lincroft */ 2566 case 38: /* 45nm Atom "Lincroft" */
2420 case 39: /* Penwell */ 2567 case 39: /* 32nm Atom "Penwell" */
2421 case 53: /* Cloverview */ 2568 case 53: /* 32nm Atom "Cloverview" */
2422 case 54: /* Cedarview */ 2569 case 54: /* 32nm Atom "Cedarview" */
2423 memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, 2570 memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
2424 sizeof(hw_cache_event_ids)); 2571 sizeof(hw_cache_event_ids));
2425 2572
@@ -2430,8 +2577,8 @@ __init int intel_pmu_init(void)
2430 pr_cont("Atom events, "); 2577 pr_cont("Atom events, ");
2431 break; 2578 break;
2432 2579
2433 case 55: /* Atom 22nm "Silvermont" */ 2580 case 55: /* 22nm Atom "Silvermont" */
2434 case 77: /* Avoton "Silvermont" */ 2581 case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
2435 memcpy(hw_cache_event_ids, slm_hw_cache_event_ids, 2582 memcpy(hw_cache_event_ids, slm_hw_cache_event_ids,
2436 sizeof(hw_cache_event_ids)); 2583 sizeof(hw_cache_event_ids));
2437 memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs, 2584 memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
@@ -2446,9 +2593,9 @@ __init int intel_pmu_init(void)
2446 pr_cont("Silvermont events, "); 2593 pr_cont("Silvermont events, ");
2447 break; 2594 break;
2448 2595
2449 case 37: /* 32 nm nehalem, "Clarkdale" */ 2596 case 37: /* 32nm Westmere */
2450 case 44: /* 32 nm nehalem, "Gulftown" */ 2597 case 44: /* 32nm Westmere-EP */
2451 case 47: /* 32 nm Xeon E7 */ 2598 case 47: /* 32nm Westmere-EX */
2452 memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids, 2599 memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
2453 sizeof(hw_cache_event_ids)); 2600 sizeof(hw_cache_event_ids));
2454 memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs, 2601 memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
@@ -2474,8 +2621,8 @@ __init int intel_pmu_init(void)
2474 pr_cont("Westmere events, "); 2621 pr_cont("Westmere events, ");
2475 break; 2622 break;
2476 2623
2477 case 42: /* SandyBridge */ 2624 case 42: /* 32nm SandyBridge */
2478 case 45: /* SandyBridge, "Romely-EP" */ 2625 case 45: /* 32nm SandyBridge-E/EN/EP */
2479 x86_add_quirk(intel_sandybridge_quirk); 2626 x86_add_quirk(intel_sandybridge_quirk);
2480 memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, 2627 memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
2481 sizeof(hw_cache_event_ids)); 2628 sizeof(hw_cache_event_ids));
@@ -2506,8 +2653,9 @@ __init int intel_pmu_init(void)
2506 2653
2507 pr_cont("SandyBridge events, "); 2654 pr_cont("SandyBridge events, ");
2508 break; 2655 break;
2509 case 58: /* IvyBridge */ 2656
2510 case 62: /* IvyBridge EP */ 2657 case 58: /* 22nm IvyBridge */
2658 case 62: /* 22nm IvyBridge-EP/EX */
2511 memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, 2659 memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
2512 sizeof(hw_cache_event_ids)); 2660 sizeof(hw_cache_event_ids));
2513 /* dTLB-load-misses on IVB is different than SNB */ 2661 /* dTLB-load-misses on IVB is different than SNB */
@@ -2539,20 +2687,19 @@ __init int intel_pmu_init(void)
2539 break; 2687 break;
2540 2688
2541 2689
2542 case 60: /* Haswell Client */ 2690 case 60: /* 22nm Haswell Core */
2543 case 70: 2691 case 63: /* 22nm Haswell Server */
2544 case 71: 2692 case 69: /* 22nm Haswell ULT */
2545 case 63: 2693 case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
2546 case 69:
2547 x86_pmu.late_ack = true; 2694 x86_pmu.late_ack = true;
2548 memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); 2695 memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
2549 memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs)); 2696 memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
2550 2697
2551 intel_pmu_lbr_init_snb(); 2698 intel_pmu_lbr_init_snb();
2552 2699
2553 x86_pmu.event_constraints = intel_hsw_event_constraints; 2700 x86_pmu.event_constraints = intel_hsw_event_constraints;
2554 x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints; 2701 x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
2555 x86_pmu.extra_regs = intel_snb_extra_regs; 2702 x86_pmu.extra_regs = intel_snbep_extra_regs;
2556 x86_pmu.pebs_aliases = intel_pebs_aliases_snb; 2703 x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
2557 /* all extra regs are per-cpu when HT is on */ 2704 /* all extra regs are per-cpu when HT is on */
2558 x86_pmu.er_flags |= ERF_HAS_RSP_1; 2705 x86_pmu.er_flags |= ERF_HAS_RSP_1;
@@ -2565,6 +2712,28 @@ __init int intel_pmu_init(void)
2565 pr_cont("Haswell events, "); 2712 pr_cont("Haswell events, ");
2566 break; 2713 break;
2567 2714
2715 case 61: /* 14nm Broadwell Core-M */
2716 x86_pmu.late_ack = true;
2717 memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
2718 memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
2719
2720 intel_pmu_lbr_init_snb();
2721
2722 x86_pmu.event_constraints = intel_bdw_event_constraints;
2723 x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints;
2724 x86_pmu.extra_regs = intel_snbep_extra_regs;
2725 x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
2726 /* all extra regs are per-cpu when HT is on */
2727 x86_pmu.er_flags |= ERF_HAS_RSP_1;
2728 x86_pmu.er_flags |= ERF_NO_HT_SHARING;
2729
2730 x86_pmu.hw_config = hsw_hw_config;
2731 x86_pmu.get_event_constraints = hsw_get_event_constraints;
2732 x86_pmu.cpu_events = hsw_events_attrs;
2733 x86_pmu.limit_period = bdw_limit_period;
2734 pr_cont("Broadwell events, ");
2735 break;
2736
2568 default: 2737 default:
2569 switch (x86_pmu.version) { 2738 switch (x86_pmu.version) {
2570 case 1: 2739 case 1:
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 696ade311ded..b1553d05a5cb 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -108,14 +108,16 @@ static u64 precise_store_data(u64 status)
108 return val; 108 return val;
109} 109}
110 110
111static u64 precise_store_data_hsw(struct perf_event *event, u64 status) 111static u64 precise_datala_hsw(struct perf_event *event, u64 status)
112{ 112{
113 union perf_mem_data_src dse; 113 union perf_mem_data_src dse;
114 u64 cfg = event->hw.config & INTEL_ARCH_EVENT_MASK;
115 114
116 dse.val = 0; 115 dse.val = PERF_MEM_NA;
117 dse.mem_op = PERF_MEM_OP_STORE; 116
118 dse.mem_lvl = PERF_MEM_LVL_NA; 117 if (event->hw.flags & PERF_X86_EVENT_PEBS_ST_HSW)
118 dse.mem_op = PERF_MEM_OP_STORE;
119 else if (event->hw.flags & PERF_X86_EVENT_PEBS_LD_HSW)
120 dse.mem_op = PERF_MEM_OP_LOAD;
119 121
120 /* 122 /*
121 * L1 info only valid for following events: 123 * L1 info only valid for following events:
@@ -125,15 +127,12 @@ static u64 precise_store_data_hsw(struct perf_event *event, u64 status)
125 * MEM_UOPS_RETIRED.SPLIT_STORES 127 * MEM_UOPS_RETIRED.SPLIT_STORES
126 * MEM_UOPS_RETIRED.ALL_STORES 128 * MEM_UOPS_RETIRED.ALL_STORES
127 */ 129 */
128 if (cfg != 0x12d0 && cfg != 0x22d0 && cfg != 0x42d0 && cfg != 0x82d0) 130 if (event->hw.flags & PERF_X86_EVENT_PEBS_ST_HSW) {
129 return dse.mem_lvl; 131 if (status & 1)
130 132 dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT;
131 if (status & 1) 133 else
132 dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT; 134 dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_MISS;
133 else 135 }
134 dse.mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_MISS;
135
136 /* Nothing else supported. Sorry. */
137 return dse.val; 136 return dse.val;
138} 137}
139 138
@@ -569,28 +568,10 @@ struct event_constraint intel_atom_pebs_event_constraints[] = {
569}; 568};
570 569
571struct event_constraint intel_slm_pebs_event_constraints[] = { 570struct event_constraint intel_slm_pebs_event_constraints[] = {
572 INTEL_UEVENT_CONSTRAINT(0x0103, 0x1), /* REHABQ.LD_BLOCK_ST_FORWARD_PS */ 571 /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
573 INTEL_UEVENT_CONSTRAINT(0x0803, 0x1), /* REHABQ.LD_SPLITS_PS */ 572 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
574 INTEL_UEVENT_CONSTRAINT(0x0204, 0x1), /* MEM_UOPS_RETIRED.L2_HIT_LOADS_PS */ 573 /* Allow all events as PEBS with no flags */
575 INTEL_UEVENT_CONSTRAINT(0x0404, 0x1), /* MEM_UOPS_RETIRED.L2_MISS_LOADS_PS */ 574 INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
576 INTEL_UEVENT_CONSTRAINT(0x0804, 0x1), /* MEM_UOPS_RETIRED.DTLB_MISS_LOADS_PS */
577 INTEL_UEVENT_CONSTRAINT(0x2004, 0x1), /* MEM_UOPS_RETIRED.HITM_PS */
578 INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY_PS */
579 INTEL_UEVENT_CONSTRAINT(0x00c4, 0x1), /* BR_INST_RETIRED.ALL_BRANCHES_PS */
580 INTEL_UEVENT_CONSTRAINT(0x7ec4, 0x1), /* BR_INST_RETIRED.JCC_PS */
581 INTEL_UEVENT_CONSTRAINT(0xbfc4, 0x1), /* BR_INST_RETIRED.FAR_BRANCH_PS */
582 INTEL_UEVENT_CONSTRAINT(0xebc4, 0x1), /* BR_INST_RETIRED.NON_RETURN_IND_PS */
583 INTEL_UEVENT_CONSTRAINT(0xf7c4, 0x1), /* BR_INST_RETIRED.RETURN_PS */
584 INTEL_UEVENT_CONSTRAINT(0xf9c4, 0x1), /* BR_INST_RETIRED.CALL_PS */
585 INTEL_UEVENT_CONSTRAINT(0xfbc4, 0x1), /* BR_INST_RETIRED.IND_CALL_PS */
586 INTEL_UEVENT_CONSTRAINT(0xfdc4, 0x1), /* BR_INST_RETIRED.REL_CALL_PS */
587 INTEL_UEVENT_CONSTRAINT(0xfec4, 0x1), /* BR_INST_RETIRED.TAKEN_JCC_PS */
588 INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_MISP_RETIRED.ALL_BRANCHES_PS */
589 INTEL_UEVENT_CONSTRAINT(0x7ec5, 0x1), /* BR_INST_MISP_RETIRED.JCC_PS */
590 INTEL_UEVENT_CONSTRAINT(0xebc5, 0x1), /* BR_INST_MISP_RETIRED.NON_RETURN_IND_PS */
591 INTEL_UEVENT_CONSTRAINT(0xf7c5, 0x1), /* BR_INST_MISP_RETIRED.RETURN_PS */
592 INTEL_UEVENT_CONSTRAINT(0xfbc5, 0x1), /* BR_INST_MISP_RETIRED.IND_CALL_PS */
593 INTEL_UEVENT_CONSTRAINT(0xfec5, 0x1), /* BR_INST_MISP_RETIRED.TAKEN_JCC_PS */
594 EVENT_CONSTRAINT_END 575 EVENT_CONSTRAINT_END
595}; 576};
596 577
@@ -626,68 +607,44 @@ struct event_constraint intel_westmere_pebs_event_constraints[] = {
626 607
627struct event_constraint intel_snb_pebs_event_constraints[] = { 608struct event_constraint intel_snb_pebs_event_constraints[] = {
628 INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ 609 INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
629 INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
630 INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
631 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
632 INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */
633 INTEL_PLD_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */ 610 INTEL_PLD_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */
634 INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */ 611 INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */
635 INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ 612 /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
636 INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ 613 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
637 INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ 614 /* Allow all events as PEBS with no flags */
638 INTEL_EVENT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */ 615 INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
639 INTEL_UEVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */
640 EVENT_CONSTRAINT_END 616 EVENT_CONSTRAINT_END
641}; 617};
642 618
643struct event_constraint intel_ivb_pebs_event_constraints[] = { 619struct event_constraint intel_ivb_pebs_event_constraints[] = {
644 INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ 620 INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
645 INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
646 INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
647 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
648 INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */
649 INTEL_PLD_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */ 621 INTEL_PLD_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */
650 INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */ 622 INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */
651 INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ 623 /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
652 INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ 624 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
653 INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ 625 /* Allow all events as PEBS with no flags */
654 INTEL_EVENT_CONSTRAINT(0xd3, 0xf), /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */ 626 INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
655 EVENT_CONSTRAINT_END 627 EVENT_CONSTRAINT_END
656}; 628};
657 629
658struct event_constraint intel_hsw_pebs_event_constraints[] = { 630struct event_constraint intel_hsw_pebs_event_constraints[] = {
659 INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ 631 INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
660 INTEL_PST_HSW_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ 632 INTEL_PLD_CONSTRAINT(0x01cd, 0xf), /* MEM_TRANS_RETIRED.* */
661 INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */ 633 /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
662 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ 634 INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
663 INTEL_UEVENT_CONSTRAINT(0x01c5, 0xf), /* BR_MISP_RETIRED.CONDITIONAL */ 635 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
664 INTEL_UEVENT_CONSTRAINT(0x04c5, 0xf), /* BR_MISP_RETIRED.ALL_BRANCHES */ 636 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */
665 INTEL_UEVENT_CONSTRAINT(0x20c5, 0xf), /* BR_MISP_RETIRED.NEAR_TAKEN */ 637 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */
666 INTEL_PLD_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.* */ 638 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_LOADS */
667 /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */ 639 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_UOPS_RETIRED.ALL_LOADS */
668 INTEL_UEVENT_CONSTRAINT(0x11d0, 0xf), 640 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_STORES */
669 /* MEM_UOPS_RETIRED.STLB_MISS_STORES */ 641 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_STORES */
670 INTEL_UEVENT_CONSTRAINT(0x12d0, 0xf), 642 INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_UOPS_RETIRED.ALL_STORES */
671 INTEL_UEVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */ 643 INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
672 INTEL_UEVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOPS_RETIRED.SPLIT_LOADS */ 644 INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd2, 0xf), /* MEM_LOAD_UOPS_L3_HIT_RETIRED.* */
673 /* MEM_UOPS_RETIRED.SPLIT_STORES */ 645 INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD(0xd3, 0xf), /* MEM_LOAD_UOPS_L3_MISS_RETIRED.* */
674 INTEL_UEVENT_CONSTRAINT(0x42d0, 0xf), 646 /* Allow all events as PEBS with no flags */
675 INTEL_UEVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOPS_RETIRED.ALL_LOADS */ 647 INTEL_ALL_EVENT_CONSTRAINT(0, 0xf),
676 INTEL_PST_HSW_CONSTRAINT(0x82d0, 0xf), /* MEM_UOPS_RETIRED.ALL_STORES */
677 INTEL_UEVENT_CONSTRAINT(0x01d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.L1_HIT */
678 INTEL_UEVENT_CONSTRAINT(0x02d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.L2_HIT */
679 INTEL_UEVENT_CONSTRAINT(0x04d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.L3_HIT */
680 /* MEM_LOAD_UOPS_RETIRED.HIT_LFB */
681 INTEL_UEVENT_CONSTRAINT(0x40d1, 0xf),
682 /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS */
683 INTEL_UEVENT_CONSTRAINT(0x01d2, 0xf),
684 /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT */
685 INTEL_UEVENT_CONSTRAINT(0x02d2, 0xf),
686 /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.LOCAL_DRAM */
687 INTEL_UEVENT_CONSTRAINT(0x01d3, 0xf),
688 INTEL_UEVENT_CONSTRAINT(0x04c8, 0xf), /* HLE_RETIRED.Abort */
689 INTEL_UEVENT_CONSTRAINT(0x04c9, 0xf), /* RTM_RETIRED.Abort */
690
691 EVENT_CONSTRAINT_END 648 EVENT_CONSTRAINT_END
692}; 649};
693 650
@@ -864,6 +821,10 @@ static inline u64 intel_hsw_transaction(struct pebs_record_hsw *pebs)
864static void __intel_pmu_pebs_event(struct perf_event *event, 821static void __intel_pmu_pebs_event(struct perf_event *event,
865 struct pt_regs *iregs, void *__pebs) 822 struct pt_regs *iregs, void *__pebs)
866{ 823{
824#define PERF_X86_EVENT_PEBS_HSW_PREC \
825 (PERF_X86_EVENT_PEBS_ST_HSW | \
826 PERF_X86_EVENT_PEBS_LD_HSW | \
827 PERF_X86_EVENT_PEBS_NA_HSW)
867 /* 828 /*
868 * We cast to the biggest pebs_record but are careful not to 829 * We cast to the biggest pebs_record but are careful not to
869 * unconditionally access the 'extra' entries. 830 * unconditionally access the 'extra' entries.
@@ -873,42 +834,40 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
873 struct perf_sample_data data; 834 struct perf_sample_data data;
874 struct pt_regs regs; 835 struct pt_regs regs;
875 u64 sample_type; 836 u64 sample_type;
876 int fll, fst; 837 int fll, fst, dsrc;
838 int fl = event->hw.flags;
877 839
878 if (!intel_pmu_save_and_restart(event)) 840 if (!intel_pmu_save_and_restart(event))
879 return; 841 return;
880 842
881 fll = event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT; 843 sample_type = event->attr.sample_type;
882 fst = event->hw.flags & (PERF_X86_EVENT_PEBS_ST | 844 dsrc = sample_type & PERF_SAMPLE_DATA_SRC;
883 PERF_X86_EVENT_PEBS_ST_HSW); 845
846 fll = fl & PERF_X86_EVENT_PEBS_LDLAT;
847 fst = fl & (PERF_X86_EVENT_PEBS_ST | PERF_X86_EVENT_PEBS_HSW_PREC);
884 848
885 perf_sample_data_init(&data, 0, event->hw.last_period); 849 perf_sample_data_init(&data, 0, event->hw.last_period);
886 850
887 data.period = event->hw.last_period; 851 data.period = event->hw.last_period;
888 sample_type = event->attr.sample_type;
889 852
890 /* 853 /*
891 * if PEBS-LL or PreciseStore 854 * Use latency for weight (only avail with PEBS-LL)
892 */ 855 */
893 if (fll || fst) { 856 if (fll && (sample_type & PERF_SAMPLE_WEIGHT))
894 /* 857 data.weight = pebs->lat;
895 * Use latency for weight (only avail with PEBS-LL) 858
896 */ 859 /*
897 if (fll && (sample_type & PERF_SAMPLE_WEIGHT)) 860 * data.data_src encodes the data source
898 data.weight = pebs->lat; 861 */
899 862 if (dsrc) {
900 /* 863 u64 val = PERF_MEM_NA;
901 * data.data_src encodes the data source 864 if (fll)
902 */ 865 val = load_latency_data(pebs->dse);
903 if (sample_type & PERF_SAMPLE_DATA_SRC) { 866 else if (fst && (fl & PERF_X86_EVENT_PEBS_HSW_PREC))
904 if (fll) 867 val = precise_datala_hsw(event, pebs->dse);
905 data.data_src.val = load_latency_data(pebs->dse); 868 else if (fst)
906 else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST_HSW) 869 val = precise_store_data(pebs->dse);
907 data.data_src.val = 870 data.data_src.val = val;
908 precise_store_data_hsw(event, pebs->dse);
909 else
910 data.data_src.val = precise_store_data(pebs->dse);
911 }
912 } 871 }
913 872
914 /* 873 /*
@@ -935,16 +894,16 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
935 else 894 else
936 regs.flags &= ~PERF_EFLAGS_EXACT; 895 regs.flags &= ~PERF_EFLAGS_EXACT;
937 896
938 if ((event->attr.sample_type & PERF_SAMPLE_ADDR) && 897 if ((sample_type & PERF_SAMPLE_ADDR) &&
939 x86_pmu.intel_cap.pebs_format >= 1) 898 x86_pmu.intel_cap.pebs_format >= 1)
940 data.addr = pebs->dla; 899 data.addr = pebs->dla;
941 900
942 if (x86_pmu.intel_cap.pebs_format >= 2) { 901 if (x86_pmu.intel_cap.pebs_format >= 2) {
943 /* Only set the TSX weight when no memory weight. */ 902 /* Only set the TSX weight when no memory weight. */
944 if ((event->attr.sample_type & PERF_SAMPLE_WEIGHT) && !fll) 903 if ((sample_type & PERF_SAMPLE_WEIGHT) && !fll)
945 data.weight = intel_hsw_weight(pebs); 904 data.weight = intel_hsw_weight(pebs);
946 905
947 if (event->attr.sample_type & PERF_SAMPLE_TRANSACTION) 906 if (sample_type & PERF_SAMPLE_TRANSACTION)
948 data.txn = intel_hsw_transaction(pebs); 907 data.txn = intel_hsw_transaction(pebs);
949 } 908 }
950 909
@@ -1055,7 +1014,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
1055 * BTS, PEBS probe and setup 1014 * BTS, PEBS probe and setup
1056 */ 1015 */
1057 1016
1058void intel_ds_init(void) 1017void __init intel_ds_init(void)
1059{ 1018{
1060 /* 1019 /*
1061 * No support for 32bit formats 1020 * No support for 32bit formats
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index 9dd2459a4c73..4af10617de33 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -697,7 +697,7 @@ static const int snb_lbr_sel_map[PERF_SAMPLE_BRANCH_MAX] = {
697}; 697};
698 698
699/* core */ 699/* core */
700void intel_pmu_lbr_init_core(void) 700void __init intel_pmu_lbr_init_core(void)
701{ 701{
702 x86_pmu.lbr_nr = 4; 702 x86_pmu.lbr_nr = 4;
703 x86_pmu.lbr_tos = MSR_LBR_TOS; 703 x86_pmu.lbr_tos = MSR_LBR_TOS;
@@ -712,7 +712,7 @@ void intel_pmu_lbr_init_core(void)
712} 712}
713 713
714/* nehalem/westmere */ 714/* nehalem/westmere */
715void intel_pmu_lbr_init_nhm(void) 715void __init intel_pmu_lbr_init_nhm(void)
716{ 716{
717 x86_pmu.lbr_nr = 16; 717 x86_pmu.lbr_nr = 16;
718 x86_pmu.lbr_tos = MSR_LBR_TOS; 718 x86_pmu.lbr_tos = MSR_LBR_TOS;
@@ -733,7 +733,7 @@ void intel_pmu_lbr_init_nhm(void)
733} 733}
734 734
735/* sandy bridge */ 735/* sandy bridge */
736void intel_pmu_lbr_init_snb(void) 736void __init intel_pmu_lbr_init_snb(void)
737{ 737{
738 x86_pmu.lbr_nr = 16; 738 x86_pmu.lbr_nr = 16;
739 x86_pmu.lbr_tos = MSR_LBR_TOS; 739 x86_pmu.lbr_tos = MSR_LBR_TOS;
@@ -753,7 +753,7 @@ void intel_pmu_lbr_init_snb(void)
753} 753}
754 754
755/* atom */ 755/* atom */
756void intel_pmu_lbr_init_atom(void) 756void __init intel_pmu_lbr_init_atom(void)
757{ 757{
758 /* 758 /*
759 * only models starting at stepping 10 seems 759 * only models starting at stepping 10 seems
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 0939f86f543d..9762dbd9f3f7 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -1,83 +1,39 @@
1#include "perf_event_intel_uncore.h" 1#include "perf_event_intel_uncore.h"
2 2
3static struct intel_uncore_type *empty_uncore[] = { NULL, }; 3static struct intel_uncore_type *empty_uncore[] = { NULL, };
4static struct intel_uncore_type **msr_uncores = empty_uncore; 4struct intel_uncore_type **uncore_msr_uncores = empty_uncore;
5static struct intel_uncore_type **pci_uncores = empty_uncore; 5struct intel_uncore_type **uncore_pci_uncores = empty_uncore;
6/* pci bus to socket mapping */
7static int pcibus_to_physid[256] = { [0 ... 255] = -1, };
8 6
9static struct pci_dev *extra_pci_dev[UNCORE_SOCKET_MAX][UNCORE_EXTRA_PCI_DEV_MAX]; 7static bool pcidrv_registered;
8struct pci_driver *uncore_pci_driver;
9/* pci bus to socket mapping */
10int uncore_pcibus_to_physid[256] = { [0 ... 255] = -1, };
11struct pci_dev *uncore_extra_pci_dev[UNCORE_SOCKET_MAX][UNCORE_EXTRA_PCI_DEV_MAX];
10 12
11static DEFINE_RAW_SPINLOCK(uncore_box_lock); 13static DEFINE_RAW_SPINLOCK(uncore_box_lock);
12
13/* mask of cpus that collect uncore events */ 14/* mask of cpus that collect uncore events */
14static cpumask_t uncore_cpu_mask; 15static cpumask_t uncore_cpu_mask;
15 16
16/* constraint for the fixed counter */ 17/* constraint for the fixed counter */
17static struct event_constraint constraint_fixed = 18static struct event_constraint uncore_constraint_fixed =
18 EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL); 19 EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL);
19static struct event_constraint constraint_empty = 20struct event_constraint uncore_constraint_empty =
20 EVENT_CONSTRAINT(0, 0, 0); 21 EVENT_CONSTRAINT(0, 0, 0);
21 22
22#define __BITS_VALUE(x, i, n) ((typeof(x))(((x) >> ((i) * (n))) & \ 23ssize_t uncore_event_show(struct kobject *kobj,
23 ((1ULL << (n)) - 1))) 24 struct kobj_attribute *attr, char *buf)
24 25{
25DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7"); 26 struct uncore_event_desc *event =
26DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21"); 27 container_of(attr, struct uncore_event_desc, attr);
27DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15"); 28 return sprintf(buf, "%s", event->config);
28DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18"); 29}
29DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19"); 30
30DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23"); 31struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
31DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28");
32DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31");
33DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
34DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28");
35DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15");
36DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30");
37DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51");
38DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4");
39DEFINE_UNCORE_FORMAT_ATTR(filter_link, filter_link, "config1:5-8");
40DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17");
41DEFINE_UNCORE_FORMAT_ATTR(filter_nid2, filter_nid, "config1:32-47");
42DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22");
43DEFINE_UNCORE_FORMAT_ATTR(filter_state2, filter_state, "config1:17-22");
44DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31");
45DEFINE_UNCORE_FORMAT_ATTR(filter_opc2, filter_opc, "config1:52-60");
46DEFINE_UNCORE_FORMAT_ATTR(filter_band0, filter_band0, "config1:0-7");
47DEFINE_UNCORE_FORMAT_ATTR(filter_band1, filter_band1, "config1:8-15");
48DEFINE_UNCORE_FORMAT_ATTR(filter_band2, filter_band2, "config1:16-23");
49DEFINE_UNCORE_FORMAT_ATTR(filter_band3, filter_band3, "config1:24-31");
50DEFINE_UNCORE_FORMAT_ATTR(match_rds, match_rds, "config1:48-51");
51DEFINE_UNCORE_FORMAT_ATTR(match_rnid30, match_rnid30, "config1:32-35");
52DEFINE_UNCORE_FORMAT_ATTR(match_rnid4, match_rnid4, "config1:31");
53DEFINE_UNCORE_FORMAT_ATTR(match_dnid, match_dnid, "config1:13-17");
54DEFINE_UNCORE_FORMAT_ATTR(match_mc, match_mc, "config1:9-12");
55DEFINE_UNCORE_FORMAT_ATTR(match_opc, match_opc, "config1:5-8");
56DEFINE_UNCORE_FORMAT_ATTR(match_vnw, match_vnw, "config1:3-4");
57DEFINE_UNCORE_FORMAT_ATTR(match0, match0, "config1:0-31");
58DEFINE_UNCORE_FORMAT_ATTR(match1, match1, "config1:32-63");
59DEFINE_UNCORE_FORMAT_ATTR(mask_rds, mask_rds, "config2:48-51");
60DEFINE_UNCORE_FORMAT_ATTR(mask_rnid30, mask_rnid30, "config2:32-35");
61DEFINE_UNCORE_FORMAT_ATTR(mask_rnid4, mask_rnid4, "config2:31");
62DEFINE_UNCORE_FORMAT_ATTR(mask_dnid, mask_dnid, "config2:13-17");
63DEFINE_UNCORE_FORMAT_ATTR(mask_mc, mask_mc, "config2:9-12");
64DEFINE_UNCORE_FORMAT_ATTR(mask_opc, mask_opc, "config2:5-8");
65DEFINE_UNCORE_FORMAT_ATTR(mask_vnw, mask_vnw, "config2:3-4");
66DEFINE_UNCORE_FORMAT_ATTR(mask0, mask0, "config2:0-31");
67DEFINE_UNCORE_FORMAT_ATTR(mask1, mask1, "config2:32-63");
68
69static void uncore_pmu_start_hrtimer(struct intel_uncore_box *box);
70static void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box);
71static void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event);
72static void uncore_pmu_event_read(struct perf_event *event);
73
74static struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
75{ 32{
76 return container_of(event->pmu, struct intel_uncore_pmu, pmu); 33 return container_of(event->pmu, struct intel_uncore_pmu, pmu);
77} 34}
78 35
79static struct intel_uncore_box * 36struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
80uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
81{ 37{
82 struct intel_uncore_box *box; 38 struct intel_uncore_box *box;
83 39
@@ -86,6 +42,9 @@ uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
86 return box; 42 return box;
87 43
88 raw_spin_lock(&uncore_box_lock); 44 raw_spin_lock(&uncore_box_lock);
45 /* Recheck in lock to handle races. */
46 if (*per_cpu_ptr(pmu->box, cpu))
47 goto out;
89 list_for_each_entry(box, &pmu->box_list, list) { 48 list_for_each_entry(box, &pmu->box_list, list) {
90 if (box->phys_id == topology_physical_package_id(cpu)) { 49 if (box->phys_id == topology_physical_package_id(cpu)) {
91 atomic_inc(&box->refcnt); 50 atomic_inc(&box->refcnt);
@@ -93,12 +52,13 @@ uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
93 break; 52 break;
94 } 53 }
95 } 54 }
55out:
96 raw_spin_unlock(&uncore_box_lock); 56 raw_spin_unlock(&uncore_box_lock);
97 57
98 return *per_cpu_ptr(pmu->box, cpu); 58 return *per_cpu_ptr(pmu->box, cpu);
99} 59}
100 60
101static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event) 61struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
102{ 62{
103 /* 63 /*
104 * perf core schedules event on the basis of cpu, uncore events are 64 * perf core schedules event on the basis of cpu, uncore events are
@@ -107,7 +67,7 @@ static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
107 return uncore_pmu_to_box(uncore_event_to_pmu(event), smp_processor_id()); 67 return uncore_pmu_to_box(uncore_event_to_pmu(event), smp_processor_id());
108} 68}
109 69
110static u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event) 70u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
111{ 71{
112 u64 count; 72 u64 count;
113 73
@@ -119,7 +79,7 @@ static u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_eve
119/* 79/*
120 * generic get constraint function for shared match/mask registers. 80 * generic get constraint function for shared match/mask registers.
121 */ 81 */
122static struct event_constraint * 82struct event_constraint *
123uncore_get_constraint(struct intel_uncore_box *box, struct perf_event *event) 83uncore_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
124{ 84{
125 struct intel_uncore_extra_reg *er; 85 struct intel_uncore_extra_reg *er;
@@ -154,10 +114,10 @@ uncore_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
154 return NULL; 114 return NULL;
155 } 115 }
156 116
157 return &constraint_empty; 117 return &uncore_constraint_empty;
158} 118}
159 119
160static void uncore_put_constraint(struct intel_uncore_box *box, struct perf_event *event) 120void uncore_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
161{ 121{
162 struct intel_uncore_extra_reg *er; 122 struct intel_uncore_extra_reg *er;
163 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg; 123 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
@@ -178,7 +138,7 @@ static void uncore_put_constraint(struct intel_uncore_box *box, struct perf_even
178 reg1->alloc = 0; 138 reg1->alloc = 0;
179} 139}
180 140
181static u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx) 141u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx)
182{ 142{
183 struct intel_uncore_extra_reg *er; 143 struct intel_uncore_extra_reg *er;
184 unsigned long flags; 144 unsigned long flags;
@@ -193,2936 +153,6 @@ static u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx)
193 return config; 153 return config;
194} 154}
195 155
196/* Sandy Bridge-EP uncore support */
197static struct intel_uncore_type snbep_uncore_cbox;
198static struct intel_uncore_type snbep_uncore_pcu;
199
200static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
201{
202 struct pci_dev *pdev = box->pci_dev;
203 int box_ctl = uncore_pci_box_ctl(box);
204 u32 config = 0;
205
206 if (!pci_read_config_dword(pdev, box_ctl, &config)) {
207 config |= SNBEP_PMON_BOX_CTL_FRZ;
208 pci_write_config_dword(pdev, box_ctl, config);
209 }
210}
211
212static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
213{
214 struct pci_dev *pdev = box->pci_dev;
215 int box_ctl = uncore_pci_box_ctl(box);
216 u32 config = 0;
217
218 if (!pci_read_config_dword(pdev, box_ctl, &config)) {
219 config &= ~SNBEP_PMON_BOX_CTL_FRZ;
220 pci_write_config_dword(pdev, box_ctl, config);
221 }
222}
223
224static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event)
225{
226 struct pci_dev *pdev = box->pci_dev;
227 struct hw_perf_event *hwc = &event->hw;
228
229 pci_write_config_dword(pdev, hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
230}
231
232static void snbep_uncore_pci_disable_event(struct intel_uncore_box *box, struct perf_event *event)
233{
234 struct pci_dev *pdev = box->pci_dev;
235 struct hw_perf_event *hwc = &event->hw;
236
237 pci_write_config_dword(pdev, hwc->config_base, hwc->config);
238}
239
240static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct perf_event *event)
241{
242 struct pci_dev *pdev = box->pci_dev;
243 struct hw_perf_event *hwc = &event->hw;
244 u64 count = 0;
245
246 pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
247 pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
248
249 return count;
250}
251
252static void snbep_uncore_pci_init_box(struct intel_uncore_box *box)
253{
254 struct pci_dev *pdev = box->pci_dev;
255
256 pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL, SNBEP_PMON_BOX_CTL_INT);
257}
258
259static void snbep_uncore_msr_disable_box(struct intel_uncore_box *box)
260{
261 u64 config;
262 unsigned msr;
263
264 msr = uncore_msr_box_ctl(box);
265 if (msr) {
266 rdmsrl(msr, config);
267 config |= SNBEP_PMON_BOX_CTL_FRZ;
268 wrmsrl(msr, config);
269 }
270}
271
272static void snbep_uncore_msr_enable_box(struct intel_uncore_box *box)
273{
274 u64 config;
275 unsigned msr;
276
277 msr = uncore_msr_box_ctl(box);
278 if (msr) {
279 rdmsrl(msr, config);
280 config &= ~SNBEP_PMON_BOX_CTL_FRZ;
281 wrmsrl(msr, config);
282 }
283}
284
285static void snbep_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
286{
287 struct hw_perf_event *hwc = &event->hw;
288 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
289
290 if (reg1->idx != EXTRA_REG_NONE)
291 wrmsrl(reg1->reg, uncore_shared_reg_config(box, 0));
292
293 wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
294}
295
296static void snbep_uncore_msr_disable_event(struct intel_uncore_box *box,
297 struct perf_event *event)
298{
299 struct hw_perf_event *hwc = &event->hw;
300
301 wrmsrl(hwc->config_base, hwc->config);
302}
303
304static void snbep_uncore_msr_init_box(struct intel_uncore_box *box)
305{
306 unsigned msr = uncore_msr_box_ctl(box);
307
308 if (msr)
309 wrmsrl(msr, SNBEP_PMON_BOX_CTL_INT);
310}
311
312static struct attribute *snbep_uncore_formats_attr[] = {
313 &format_attr_event.attr,
314 &format_attr_umask.attr,
315 &format_attr_edge.attr,
316 &format_attr_inv.attr,
317 &format_attr_thresh8.attr,
318 NULL,
319};
320
321static struct attribute *snbep_uncore_ubox_formats_attr[] = {
322 &format_attr_event.attr,
323 &format_attr_umask.attr,
324 &format_attr_edge.attr,
325 &format_attr_inv.attr,
326 &format_attr_thresh5.attr,
327 NULL,
328};
329
330static struct attribute *snbep_uncore_cbox_formats_attr[] = {
331 &format_attr_event.attr,
332 &format_attr_umask.attr,
333 &format_attr_edge.attr,
334 &format_attr_tid_en.attr,
335 &format_attr_inv.attr,
336 &format_attr_thresh8.attr,
337 &format_attr_filter_tid.attr,
338 &format_attr_filter_nid.attr,
339 &format_attr_filter_state.attr,
340 &format_attr_filter_opc.attr,
341 NULL,
342};
343
344static struct attribute *snbep_uncore_pcu_formats_attr[] = {
345 &format_attr_event_ext.attr,
346 &format_attr_occ_sel.attr,
347 &format_attr_edge.attr,
348 &format_attr_inv.attr,
349 &format_attr_thresh5.attr,
350 &format_attr_occ_invert.attr,
351 &format_attr_occ_edge.attr,
352 &format_attr_filter_band0.attr,
353 &format_attr_filter_band1.attr,
354 &format_attr_filter_band2.attr,
355 &format_attr_filter_band3.attr,
356 NULL,
357};
358
359static struct attribute *snbep_uncore_qpi_formats_attr[] = {
360 &format_attr_event_ext.attr,
361 &format_attr_umask.attr,
362 &format_attr_edge.attr,
363 &format_attr_inv.attr,
364 &format_attr_thresh8.attr,
365 &format_attr_match_rds.attr,
366 &format_attr_match_rnid30.attr,
367 &format_attr_match_rnid4.attr,
368 &format_attr_match_dnid.attr,
369 &format_attr_match_mc.attr,
370 &format_attr_match_opc.attr,
371 &format_attr_match_vnw.attr,
372 &format_attr_match0.attr,
373 &format_attr_match1.attr,
374 &format_attr_mask_rds.attr,
375 &format_attr_mask_rnid30.attr,
376 &format_attr_mask_rnid4.attr,
377 &format_attr_mask_dnid.attr,
378 &format_attr_mask_mc.attr,
379 &format_attr_mask_opc.attr,
380 &format_attr_mask_vnw.attr,
381 &format_attr_mask0.attr,
382 &format_attr_mask1.attr,
383 NULL,
384};
385
386static struct uncore_event_desc snbep_uncore_imc_events[] = {
387 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
388 INTEL_UNCORE_EVENT_DESC(cas_count_read, "event=0x04,umask=0x03"),
389 INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
390 { /* end: all zeroes */ },
391};
392
393static struct uncore_event_desc snbep_uncore_qpi_events[] = {
394 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0x14"),
395 INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"),
396 INTEL_UNCORE_EVENT_DESC(drs_data, "event=0x102,umask=0x08"),
397 INTEL_UNCORE_EVENT_DESC(ncb_data, "event=0x103,umask=0x04"),
398 { /* end: all zeroes */ },
399};
400
401static struct attribute_group snbep_uncore_format_group = {
402 .name = "format",
403 .attrs = snbep_uncore_formats_attr,
404};
405
406static struct attribute_group snbep_uncore_ubox_format_group = {
407 .name = "format",
408 .attrs = snbep_uncore_ubox_formats_attr,
409};
410
411static struct attribute_group snbep_uncore_cbox_format_group = {
412 .name = "format",
413 .attrs = snbep_uncore_cbox_formats_attr,
414};
415
416static struct attribute_group snbep_uncore_pcu_format_group = {
417 .name = "format",
418 .attrs = snbep_uncore_pcu_formats_attr,
419};
420
421static struct attribute_group snbep_uncore_qpi_format_group = {
422 .name = "format",
423 .attrs = snbep_uncore_qpi_formats_attr,
424};
425
426#define SNBEP_UNCORE_MSR_OPS_COMMON_INIT() \
427 .init_box = snbep_uncore_msr_init_box, \
428 .disable_box = snbep_uncore_msr_disable_box, \
429 .enable_box = snbep_uncore_msr_enable_box, \
430 .disable_event = snbep_uncore_msr_disable_event, \
431 .enable_event = snbep_uncore_msr_enable_event, \
432 .read_counter = uncore_msr_read_counter
433
434static struct intel_uncore_ops snbep_uncore_msr_ops = {
435 SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
436};
437
438#define SNBEP_UNCORE_PCI_OPS_COMMON_INIT() \
439 .init_box = snbep_uncore_pci_init_box, \
440 .disable_box = snbep_uncore_pci_disable_box, \
441 .enable_box = snbep_uncore_pci_enable_box, \
442 .disable_event = snbep_uncore_pci_disable_event, \
443 .read_counter = snbep_uncore_pci_read_counter
444
445static struct intel_uncore_ops snbep_uncore_pci_ops = {
446 SNBEP_UNCORE_PCI_OPS_COMMON_INIT(),
447 .enable_event = snbep_uncore_pci_enable_event, \
448};
449
450static struct event_constraint snbep_uncore_cbox_constraints[] = {
451 UNCORE_EVENT_CONSTRAINT(0x01, 0x1),
452 UNCORE_EVENT_CONSTRAINT(0x02, 0x3),
453 UNCORE_EVENT_CONSTRAINT(0x04, 0x3),
454 UNCORE_EVENT_CONSTRAINT(0x05, 0x3),
455 UNCORE_EVENT_CONSTRAINT(0x07, 0x3),
456 UNCORE_EVENT_CONSTRAINT(0x09, 0x3),
457 UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
458 UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
459 UNCORE_EVENT_CONSTRAINT(0x13, 0x3),
460 UNCORE_EVENT_CONSTRAINT(0x1b, 0xc),
461 UNCORE_EVENT_CONSTRAINT(0x1c, 0xc),
462 UNCORE_EVENT_CONSTRAINT(0x1d, 0xc),
463 UNCORE_EVENT_CONSTRAINT(0x1e, 0xc),
464 EVENT_CONSTRAINT_OVERLAP(0x1f, 0xe, 0xff),
465 UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
466 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
467 UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
468 UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
469 UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
470 UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
471 UNCORE_EVENT_CONSTRAINT(0x35, 0x3),
472 UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
473 UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
474 UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
475 UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
476 UNCORE_EVENT_CONSTRAINT(0x3b, 0x1),
477 EVENT_CONSTRAINT_END
478};
479
480static struct event_constraint snbep_uncore_r2pcie_constraints[] = {
481 UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
482 UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
483 UNCORE_EVENT_CONSTRAINT(0x12, 0x1),
484 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
485 UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
486 UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
487 UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
488 UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
489 UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
490 UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
491 EVENT_CONSTRAINT_END
492};
493
494static struct event_constraint snbep_uncore_r3qpi_constraints[] = {
495 UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
496 UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
497 UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
498 UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
499 UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
500 UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
501 UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
502 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
503 UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
504 UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
505 UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
506 UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
507 UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
508 UNCORE_EVENT_CONSTRAINT(0x2a, 0x3),
509 UNCORE_EVENT_CONSTRAINT(0x2b, 0x3),
510 UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
511 UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
512 UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
513 UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
514 UNCORE_EVENT_CONSTRAINT(0x30, 0x3),
515 UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
516 UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
517 UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
518 UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
519 UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
520 UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
521 UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
522 UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
523 EVENT_CONSTRAINT_END
524};
525
526static struct intel_uncore_type snbep_uncore_ubox = {
527 .name = "ubox",
528 .num_counters = 2,
529 .num_boxes = 1,
530 .perf_ctr_bits = 44,
531 .fixed_ctr_bits = 48,
532 .perf_ctr = SNBEP_U_MSR_PMON_CTR0,
533 .event_ctl = SNBEP_U_MSR_PMON_CTL0,
534 .event_mask = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
535 .fixed_ctr = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
536 .fixed_ctl = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
537 .ops = &snbep_uncore_msr_ops,
538 .format_group = &snbep_uncore_ubox_format_group,
539};
540
541static struct extra_reg snbep_uncore_cbox_extra_regs[] = {
542 SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
543 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
544 SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
545 SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0x6),
546 SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
547 SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0x6),
548 SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
549 SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0x6),
550 SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x6),
551 SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x8),
552 SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x8),
553 SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0xa),
554 SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0xa),
555 SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x2),
556 SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x2),
557 SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x2),
558 SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x2),
559 SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x8),
560 SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x8),
561 SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0xa),
562 SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0xa),
563 SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x2),
564 SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x2),
565 SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x2),
566 SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x2),
567 EVENT_EXTRA_END
568};
569
570static void snbep_cbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
571{
572 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
573 struct intel_uncore_extra_reg *er = &box->shared_regs[0];
574 int i;
575
576 if (uncore_box_is_fake(box))
577 return;
578
579 for (i = 0; i < 5; i++) {
580 if (reg1->alloc & (0x1 << i))
581 atomic_sub(1 << (i * 6), &er->ref);
582 }
583 reg1->alloc = 0;
584}
585
586static struct event_constraint *
587__snbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event,
588 u64 (*cbox_filter_mask)(int fields))
589{
590 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
591 struct intel_uncore_extra_reg *er = &box->shared_regs[0];
592 int i, alloc = 0;
593 unsigned long flags;
594 u64 mask;
595
596 if (reg1->idx == EXTRA_REG_NONE)
597 return NULL;
598
599 raw_spin_lock_irqsave(&er->lock, flags);
600 for (i = 0; i < 5; i++) {
601 if (!(reg1->idx & (0x1 << i)))
602 continue;
603 if (!uncore_box_is_fake(box) && (reg1->alloc & (0x1 << i)))
604 continue;
605
606 mask = cbox_filter_mask(0x1 << i);
607 if (!__BITS_VALUE(atomic_read(&er->ref), i, 6) ||
608 !((reg1->config ^ er->config) & mask)) {
609 atomic_add(1 << (i * 6), &er->ref);
610 er->config &= ~mask;
611 er->config |= reg1->config & mask;
612 alloc |= (0x1 << i);
613 } else {
614 break;
615 }
616 }
617 raw_spin_unlock_irqrestore(&er->lock, flags);
618 if (i < 5)
619 goto fail;
620
621 if (!uncore_box_is_fake(box))
622 reg1->alloc |= alloc;
623
624 return NULL;
625fail:
626 for (; i >= 0; i--) {
627 if (alloc & (0x1 << i))
628 atomic_sub(1 << (i * 6), &er->ref);
629 }
630 return &constraint_empty;
631}
632
633static u64 snbep_cbox_filter_mask(int fields)
634{
635 u64 mask = 0;
636
637 if (fields & 0x1)
638 mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_TID;
639 if (fields & 0x2)
640 mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_NID;
641 if (fields & 0x4)
642 mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_STATE;
643 if (fields & 0x8)
644 mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_OPC;
645
646 return mask;
647}
648
649static struct event_constraint *
650snbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
651{
652 return __snbep_cbox_get_constraint(box, event, snbep_cbox_filter_mask);
653}
654
655static int snbep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
656{
657 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
658 struct extra_reg *er;
659 int idx = 0;
660
661 for (er = snbep_uncore_cbox_extra_regs; er->msr; er++) {
662 if (er->event != (event->hw.config & er->config_mask))
663 continue;
664 idx |= er->idx;
665 }
666
667 if (idx) {
668 reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
669 SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
670 reg1->config = event->attr.config1 & snbep_cbox_filter_mask(idx);
671 reg1->idx = idx;
672 }
673 return 0;
674}
675
676static struct intel_uncore_ops snbep_uncore_cbox_ops = {
677 SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
678 .hw_config = snbep_cbox_hw_config,
679 .get_constraint = snbep_cbox_get_constraint,
680 .put_constraint = snbep_cbox_put_constraint,
681};
682
683static struct intel_uncore_type snbep_uncore_cbox = {
684 .name = "cbox",
685 .num_counters = 4,
686 .num_boxes = 8,
687 .perf_ctr_bits = 44,
688 .event_ctl = SNBEP_C0_MSR_PMON_CTL0,
689 .perf_ctr = SNBEP_C0_MSR_PMON_CTR0,
690 .event_mask = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
691 .box_ctl = SNBEP_C0_MSR_PMON_BOX_CTL,
692 .msr_offset = SNBEP_CBO_MSR_OFFSET,
693 .num_shared_regs = 1,
694 .constraints = snbep_uncore_cbox_constraints,
695 .ops = &snbep_uncore_cbox_ops,
696 .format_group = &snbep_uncore_cbox_format_group,
697};
698
699static u64 snbep_pcu_alter_er(struct perf_event *event, int new_idx, bool modify)
700{
701 struct hw_perf_event *hwc = &event->hw;
702 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
703 u64 config = reg1->config;
704
705 if (new_idx > reg1->idx)
706 config <<= 8 * (new_idx - reg1->idx);
707 else
708 config >>= 8 * (reg1->idx - new_idx);
709
710 if (modify) {
711 hwc->config += new_idx - reg1->idx;
712 reg1->config = config;
713 reg1->idx = new_idx;
714 }
715 return config;
716}
717
718static struct event_constraint *
719snbep_pcu_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
720{
721 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
722 struct intel_uncore_extra_reg *er = &box->shared_regs[0];
723 unsigned long flags;
724 int idx = reg1->idx;
725 u64 mask, config1 = reg1->config;
726 bool ok = false;
727
728 if (reg1->idx == EXTRA_REG_NONE ||
729 (!uncore_box_is_fake(box) && reg1->alloc))
730 return NULL;
731again:
732 mask = 0xffULL << (idx * 8);
733 raw_spin_lock_irqsave(&er->lock, flags);
734 if (!__BITS_VALUE(atomic_read(&er->ref), idx, 8) ||
735 !((config1 ^ er->config) & mask)) {
736 atomic_add(1 << (idx * 8), &er->ref);
737 er->config &= ~mask;
738 er->config |= config1 & mask;
739 ok = true;
740 }
741 raw_spin_unlock_irqrestore(&er->lock, flags);
742
743 if (!ok) {
744 idx = (idx + 1) % 4;
745 if (idx != reg1->idx) {
746 config1 = snbep_pcu_alter_er(event, idx, false);
747 goto again;
748 }
749 return &constraint_empty;
750 }
751
752 if (!uncore_box_is_fake(box)) {
753 if (idx != reg1->idx)
754 snbep_pcu_alter_er(event, idx, true);
755 reg1->alloc = 1;
756 }
757 return NULL;
758}
759
760static void snbep_pcu_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
761{
762 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
763 struct intel_uncore_extra_reg *er = &box->shared_regs[0];
764
765 if (uncore_box_is_fake(box) || !reg1->alloc)
766 return;
767
768 atomic_sub(1 << (reg1->idx * 8), &er->ref);
769 reg1->alloc = 0;
770}
771
772static int snbep_pcu_hw_config(struct intel_uncore_box *box, struct perf_event *event)
773{
774 struct hw_perf_event *hwc = &event->hw;
775 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
776 int ev_sel = hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK;
777
778 if (ev_sel >= 0xb && ev_sel <= 0xe) {
779 reg1->reg = SNBEP_PCU_MSR_PMON_BOX_FILTER;
780 reg1->idx = ev_sel - 0xb;
781 reg1->config = event->attr.config1 & (0xff << reg1->idx);
782 }
783 return 0;
784}
785
786static struct intel_uncore_ops snbep_uncore_pcu_ops = {
787 SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
788 .hw_config = snbep_pcu_hw_config,
789 .get_constraint = snbep_pcu_get_constraint,
790 .put_constraint = snbep_pcu_put_constraint,
791};
792
793static struct intel_uncore_type snbep_uncore_pcu = {
794 .name = "pcu",
795 .num_counters = 4,
796 .num_boxes = 1,
797 .perf_ctr_bits = 48,
798 .perf_ctr = SNBEP_PCU_MSR_PMON_CTR0,
799 .event_ctl = SNBEP_PCU_MSR_PMON_CTL0,
800 .event_mask = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
801 .box_ctl = SNBEP_PCU_MSR_PMON_BOX_CTL,
802 .num_shared_regs = 1,
803 .ops = &snbep_uncore_pcu_ops,
804 .format_group = &snbep_uncore_pcu_format_group,
805};
806
807static struct intel_uncore_type *snbep_msr_uncores[] = {
808 &snbep_uncore_ubox,
809 &snbep_uncore_cbox,
810 &snbep_uncore_pcu,
811 NULL,
812};
813
814enum {
815 SNBEP_PCI_QPI_PORT0_FILTER,
816 SNBEP_PCI_QPI_PORT1_FILTER,
817};
818
819static int snbep_qpi_hw_config(struct intel_uncore_box *box, struct perf_event *event)
820{
821 struct hw_perf_event *hwc = &event->hw;
822 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
823 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
824
825 if ((hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK) == 0x38) {
826 reg1->idx = 0;
827 reg1->reg = SNBEP_Q_Py_PCI_PMON_PKT_MATCH0;
828 reg1->config = event->attr.config1;
829 reg2->reg = SNBEP_Q_Py_PCI_PMON_PKT_MASK0;
830 reg2->config = event->attr.config2;
831 }
832 return 0;
833}
834
835static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_event *event)
836{
837 struct pci_dev *pdev = box->pci_dev;
838 struct hw_perf_event *hwc = &event->hw;
839 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
840 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
841
842 if (reg1->idx != EXTRA_REG_NONE) {
843 int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER;
844 struct pci_dev *filter_pdev = extra_pci_dev[box->phys_id][idx];
845 WARN_ON_ONCE(!filter_pdev);
846 if (filter_pdev) {
847 pci_write_config_dword(filter_pdev, reg1->reg,
848 (u32)reg1->config);
849 pci_write_config_dword(filter_pdev, reg1->reg + 4,
850 (u32)(reg1->config >> 32));
851 pci_write_config_dword(filter_pdev, reg2->reg,
852 (u32)reg2->config);
853 pci_write_config_dword(filter_pdev, reg2->reg + 4,
854 (u32)(reg2->config >> 32));
855 }
856 }
857
858 pci_write_config_dword(pdev, hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
859}
860
861static struct intel_uncore_ops snbep_uncore_qpi_ops = {
862 SNBEP_UNCORE_PCI_OPS_COMMON_INIT(),
863 .enable_event = snbep_qpi_enable_event,
864 .hw_config = snbep_qpi_hw_config,
865 .get_constraint = uncore_get_constraint,
866 .put_constraint = uncore_put_constraint,
867};
868
869#define SNBEP_UNCORE_PCI_COMMON_INIT() \
870 .perf_ctr = SNBEP_PCI_PMON_CTR0, \
871 .event_ctl = SNBEP_PCI_PMON_CTL0, \
872 .event_mask = SNBEP_PMON_RAW_EVENT_MASK, \
873 .box_ctl = SNBEP_PCI_PMON_BOX_CTL, \
874 .ops = &snbep_uncore_pci_ops, \
875 .format_group = &snbep_uncore_format_group
876
877static struct intel_uncore_type snbep_uncore_ha = {
878 .name = "ha",
879 .num_counters = 4,
880 .num_boxes = 1,
881 .perf_ctr_bits = 48,
882 SNBEP_UNCORE_PCI_COMMON_INIT(),
883};
884
885static struct intel_uncore_type snbep_uncore_imc = {
886 .name = "imc",
887 .num_counters = 4,
888 .num_boxes = 4,
889 .perf_ctr_bits = 48,
890 .fixed_ctr_bits = 48,
891 .fixed_ctr = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
892 .fixed_ctl = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
893 .event_descs = snbep_uncore_imc_events,
894 SNBEP_UNCORE_PCI_COMMON_INIT(),
895};
896
897static struct intel_uncore_type snbep_uncore_qpi = {
898 .name = "qpi",
899 .num_counters = 4,
900 .num_boxes = 2,
901 .perf_ctr_bits = 48,
902 .perf_ctr = SNBEP_PCI_PMON_CTR0,
903 .event_ctl = SNBEP_PCI_PMON_CTL0,
904 .event_mask = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
905 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
906 .num_shared_regs = 1,
907 .ops = &snbep_uncore_qpi_ops,
908 .event_descs = snbep_uncore_qpi_events,
909 .format_group = &snbep_uncore_qpi_format_group,
910};
911
912
913static struct intel_uncore_type snbep_uncore_r2pcie = {
914 .name = "r2pcie",
915 .num_counters = 4,
916 .num_boxes = 1,
917 .perf_ctr_bits = 44,
918 .constraints = snbep_uncore_r2pcie_constraints,
919 SNBEP_UNCORE_PCI_COMMON_INIT(),
920};
921
922static struct intel_uncore_type snbep_uncore_r3qpi = {
923 .name = "r3qpi",
924 .num_counters = 3,
925 .num_boxes = 2,
926 .perf_ctr_bits = 44,
927 .constraints = snbep_uncore_r3qpi_constraints,
928 SNBEP_UNCORE_PCI_COMMON_INIT(),
929};
930
931enum {
932 SNBEP_PCI_UNCORE_HA,
933 SNBEP_PCI_UNCORE_IMC,
934 SNBEP_PCI_UNCORE_QPI,
935 SNBEP_PCI_UNCORE_R2PCIE,
936 SNBEP_PCI_UNCORE_R3QPI,
937};
938
939static struct intel_uncore_type *snbep_pci_uncores[] = {
940 [SNBEP_PCI_UNCORE_HA] = &snbep_uncore_ha,
941 [SNBEP_PCI_UNCORE_IMC] = &snbep_uncore_imc,
942 [SNBEP_PCI_UNCORE_QPI] = &snbep_uncore_qpi,
943 [SNBEP_PCI_UNCORE_R2PCIE] = &snbep_uncore_r2pcie,
944 [SNBEP_PCI_UNCORE_R3QPI] = &snbep_uncore_r3qpi,
945 NULL,
946};
947
948static const struct pci_device_id snbep_uncore_pci_ids[] = {
949 { /* Home Agent */
950 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA),
951 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_HA, 0),
952 },
953 { /* MC Channel 0 */
954 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC0),
955 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 0),
956 },
957 { /* MC Channel 1 */
958 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC1),
959 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 1),
960 },
961 { /* MC Channel 2 */
962 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC2),
963 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 2),
964 },
965 { /* MC Channel 3 */
966 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC3),
967 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 3),
968 },
969 { /* QPI Port 0 */
970 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI0),
971 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_QPI, 0),
972 },
973 { /* QPI Port 1 */
974 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI1),
975 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_QPI, 1),
976 },
977 { /* R2PCIe */
978 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R2PCIE),
979 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R2PCIE, 0),
980 },
981 { /* R3QPI Link 0 */
982 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI0),
983 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R3QPI, 0),
984 },
985 { /* R3QPI Link 1 */
986 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI1),
987 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R3QPI, 1),
988 },
989 { /* QPI Port 0 filter */
990 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3c86),
991 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
992 SNBEP_PCI_QPI_PORT0_FILTER),
993 },
994 { /* QPI Port 0 filter */
995 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3c96),
996 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
997 SNBEP_PCI_QPI_PORT1_FILTER),
998 },
999 { /* end: all zeroes */ }
1000};
1001
1002static struct pci_driver snbep_uncore_pci_driver = {
1003 .name = "snbep_uncore",
1004 .id_table = snbep_uncore_pci_ids,
1005};
1006
1007/*
1008 * build pci bus to socket mapping
1009 */
1010static int snbep_pci2phy_map_init(int devid)
1011{
1012 struct pci_dev *ubox_dev = NULL;
1013 int i, bus, nodeid;
1014 int err = 0;
1015 u32 config = 0;
1016
1017 while (1) {
1018 /* find the UBOX device */
1019 ubox_dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, ubox_dev);
1020 if (!ubox_dev)
1021 break;
1022 bus = ubox_dev->bus->number;
1023 /* get the Node ID of the local register */
1024 err = pci_read_config_dword(ubox_dev, 0x40, &config);
1025 if (err)
1026 break;
1027 nodeid = config;
1028 /* get the Node ID mapping */
1029 err = pci_read_config_dword(ubox_dev, 0x54, &config);
1030 if (err)
1031 break;
1032 /*
1033 * every three bits in the Node ID mapping register maps
1034 * to a particular node.
1035 */
1036 for (i = 0; i < 8; i++) {
1037 if (nodeid == ((config >> (3 * i)) & 0x7)) {
1038 pcibus_to_physid[bus] = i;
1039 break;
1040 }
1041 }
1042 }
1043
1044 if (!err) {
1045 /*
1046 * For PCI bus with no UBOX device, find the next bus
1047 * that has UBOX device and use its mapping.
1048 */
1049 i = -1;
1050 for (bus = 255; bus >= 0; bus--) {
1051 if (pcibus_to_physid[bus] >= 0)
1052 i = pcibus_to_physid[bus];
1053 else
1054 pcibus_to_physid[bus] = i;
1055 }
1056 }
1057
1058 if (ubox_dev)
1059 pci_dev_put(ubox_dev);
1060
1061 return err ? pcibios_err_to_errno(err) : 0;
1062}
1063/* end of Sandy Bridge-EP uncore support */
1064
1065/* IvyTown uncore support */
1066static void ivt_uncore_msr_init_box(struct intel_uncore_box *box)
1067{
1068 unsigned msr = uncore_msr_box_ctl(box);
1069 if (msr)
1070 wrmsrl(msr, IVT_PMON_BOX_CTL_INT);
1071}
1072
1073static void ivt_uncore_pci_init_box(struct intel_uncore_box *box)
1074{
1075 struct pci_dev *pdev = box->pci_dev;
1076
1077 pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL, IVT_PMON_BOX_CTL_INT);
1078}
1079
1080#define IVT_UNCORE_MSR_OPS_COMMON_INIT() \
1081 .init_box = ivt_uncore_msr_init_box, \
1082 .disable_box = snbep_uncore_msr_disable_box, \
1083 .enable_box = snbep_uncore_msr_enable_box, \
1084 .disable_event = snbep_uncore_msr_disable_event, \
1085 .enable_event = snbep_uncore_msr_enable_event, \
1086 .read_counter = uncore_msr_read_counter
1087
1088static struct intel_uncore_ops ivt_uncore_msr_ops = {
1089 IVT_UNCORE_MSR_OPS_COMMON_INIT(),
1090};
1091
1092static struct intel_uncore_ops ivt_uncore_pci_ops = {
1093 .init_box = ivt_uncore_pci_init_box,
1094 .disable_box = snbep_uncore_pci_disable_box,
1095 .enable_box = snbep_uncore_pci_enable_box,
1096 .disable_event = snbep_uncore_pci_disable_event,
1097 .enable_event = snbep_uncore_pci_enable_event,
1098 .read_counter = snbep_uncore_pci_read_counter,
1099};
1100
1101#define IVT_UNCORE_PCI_COMMON_INIT() \
1102 .perf_ctr = SNBEP_PCI_PMON_CTR0, \
1103 .event_ctl = SNBEP_PCI_PMON_CTL0, \
1104 .event_mask = IVT_PMON_RAW_EVENT_MASK, \
1105 .box_ctl = SNBEP_PCI_PMON_BOX_CTL, \
1106 .ops = &ivt_uncore_pci_ops, \
1107 .format_group = &ivt_uncore_format_group
1108
1109static struct attribute *ivt_uncore_formats_attr[] = {
1110 &format_attr_event.attr,
1111 &format_attr_umask.attr,
1112 &format_attr_edge.attr,
1113 &format_attr_inv.attr,
1114 &format_attr_thresh8.attr,
1115 NULL,
1116};
1117
1118static struct attribute *ivt_uncore_ubox_formats_attr[] = {
1119 &format_attr_event.attr,
1120 &format_attr_umask.attr,
1121 &format_attr_edge.attr,
1122 &format_attr_inv.attr,
1123 &format_attr_thresh5.attr,
1124 NULL,
1125};
1126
1127static struct attribute *ivt_uncore_cbox_formats_attr[] = {
1128 &format_attr_event.attr,
1129 &format_attr_umask.attr,
1130 &format_attr_edge.attr,
1131 &format_attr_tid_en.attr,
1132 &format_attr_thresh8.attr,
1133 &format_attr_filter_tid.attr,
1134 &format_attr_filter_link.attr,
1135 &format_attr_filter_state2.attr,
1136 &format_attr_filter_nid2.attr,
1137 &format_attr_filter_opc2.attr,
1138 NULL,
1139};
1140
1141static struct attribute *ivt_uncore_pcu_formats_attr[] = {
1142 &format_attr_event_ext.attr,
1143 &format_attr_occ_sel.attr,
1144 &format_attr_edge.attr,
1145 &format_attr_thresh5.attr,
1146 &format_attr_occ_invert.attr,
1147 &format_attr_occ_edge.attr,
1148 &format_attr_filter_band0.attr,
1149 &format_attr_filter_band1.attr,
1150 &format_attr_filter_band2.attr,
1151 &format_attr_filter_band3.attr,
1152 NULL,
1153};
1154
1155static struct attribute *ivt_uncore_qpi_formats_attr[] = {
1156 &format_attr_event_ext.attr,
1157 &format_attr_umask.attr,
1158 &format_attr_edge.attr,
1159 &format_attr_thresh8.attr,
1160 &format_attr_match_rds.attr,
1161 &format_attr_match_rnid30.attr,
1162 &format_attr_match_rnid4.attr,
1163 &format_attr_match_dnid.attr,
1164 &format_attr_match_mc.attr,
1165 &format_attr_match_opc.attr,
1166 &format_attr_match_vnw.attr,
1167 &format_attr_match0.attr,
1168 &format_attr_match1.attr,
1169 &format_attr_mask_rds.attr,
1170 &format_attr_mask_rnid30.attr,
1171 &format_attr_mask_rnid4.attr,
1172 &format_attr_mask_dnid.attr,
1173 &format_attr_mask_mc.attr,
1174 &format_attr_mask_opc.attr,
1175 &format_attr_mask_vnw.attr,
1176 &format_attr_mask0.attr,
1177 &format_attr_mask1.attr,
1178 NULL,
1179};
1180
1181static struct attribute_group ivt_uncore_format_group = {
1182 .name = "format",
1183 .attrs = ivt_uncore_formats_attr,
1184};
1185
1186static struct attribute_group ivt_uncore_ubox_format_group = {
1187 .name = "format",
1188 .attrs = ivt_uncore_ubox_formats_attr,
1189};
1190
1191static struct attribute_group ivt_uncore_cbox_format_group = {
1192 .name = "format",
1193 .attrs = ivt_uncore_cbox_formats_attr,
1194};
1195
1196static struct attribute_group ivt_uncore_pcu_format_group = {
1197 .name = "format",
1198 .attrs = ivt_uncore_pcu_formats_attr,
1199};
1200
1201static struct attribute_group ivt_uncore_qpi_format_group = {
1202 .name = "format",
1203 .attrs = ivt_uncore_qpi_formats_attr,
1204};
1205
1206static struct intel_uncore_type ivt_uncore_ubox = {
1207 .name = "ubox",
1208 .num_counters = 2,
1209 .num_boxes = 1,
1210 .perf_ctr_bits = 44,
1211 .fixed_ctr_bits = 48,
1212 .perf_ctr = SNBEP_U_MSR_PMON_CTR0,
1213 .event_ctl = SNBEP_U_MSR_PMON_CTL0,
1214 .event_mask = IVT_U_MSR_PMON_RAW_EVENT_MASK,
1215 .fixed_ctr = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
1216 .fixed_ctl = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
1217 .ops = &ivt_uncore_msr_ops,
1218 .format_group = &ivt_uncore_ubox_format_group,
1219};
1220
1221static struct extra_reg ivt_uncore_cbox_extra_regs[] = {
1222 SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
1223 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
1224 SNBEP_CBO_EVENT_EXTRA_REG(0x1031, 0x10ff, 0x2),
1225
1226 SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
1227 SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc),
1228 SNBEP_CBO_EVENT_EXTRA_REG(0x5134, 0xffff, 0xc),
1229 SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
1230 SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0xc),
1231 SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
1232 SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0xc),
1233 SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
1234 SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0xc),
1235 SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x10),
1236 SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
1237 SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
1238 SNBEP_CBO_EVENT_EXTRA_REG(0x2335, 0xffff, 0x10),
1239 SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0x18),
1240 SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0x18),
1241 SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x8),
1242 SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x8),
1243 SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x8),
1244 SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x8),
1245 SNBEP_CBO_EVENT_EXTRA_REG(0x8135, 0xffff, 0x10),
1246 SNBEP_CBO_EVENT_EXTRA_REG(0x8335, 0xffff, 0x10),
1247 SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x10),
1248 SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x10),
1249 SNBEP_CBO_EVENT_EXTRA_REG(0x2136, 0xffff, 0x10),
1250 SNBEP_CBO_EVENT_EXTRA_REG(0x2336, 0xffff, 0x10),
1251 SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0x18),
1252 SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0x18),
1253 SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x8),
1254 SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x8),
1255 SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x8),
1256 SNBEP_CBO_EVENT_EXTRA_REG(0x5036, 0xffff, 0x8),
1257 SNBEP_CBO_EVENT_EXTRA_REG(0x8136, 0xffff, 0x10),
1258 SNBEP_CBO_EVENT_EXTRA_REG(0x8336, 0xffff, 0x10),
1259 SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x8),
1260 EVENT_EXTRA_END
1261};
1262
1263static u64 ivt_cbox_filter_mask(int fields)
1264{
1265 u64 mask = 0;
1266
1267 if (fields & 0x1)
1268 mask |= IVT_CB0_MSR_PMON_BOX_FILTER_TID;
1269 if (fields & 0x2)
1270 mask |= IVT_CB0_MSR_PMON_BOX_FILTER_LINK;
1271 if (fields & 0x4)
1272 mask |= IVT_CB0_MSR_PMON_BOX_FILTER_STATE;
1273 if (fields & 0x8)
1274 mask |= IVT_CB0_MSR_PMON_BOX_FILTER_NID;
1275 if (fields & 0x10)
1276 mask |= IVT_CB0_MSR_PMON_BOX_FILTER_OPC;
1277
1278 return mask;
1279}
1280
1281static struct event_constraint *
1282ivt_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
1283{
1284 return __snbep_cbox_get_constraint(box, event, ivt_cbox_filter_mask);
1285}
1286
1287static int ivt_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
1288{
1289 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
1290 struct extra_reg *er;
1291 int idx = 0;
1292
1293 for (er = ivt_uncore_cbox_extra_regs; er->msr; er++) {
1294 if (er->event != (event->hw.config & er->config_mask))
1295 continue;
1296 idx |= er->idx;
1297 }
1298
1299 if (idx) {
1300 reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
1301 SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
1302 reg1->config = event->attr.config1 & ivt_cbox_filter_mask(idx);
1303 reg1->idx = idx;
1304 }
1305 return 0;
1306}
1307
1308static void ivt_cbox_enable_event(struct intel_uncore_box *box, struct perf_event *event)
1309{
1310 struct hw_perf_event *hwc = &event->hw;
1311 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
1312
1313 if (reg1->idx != EXTRA_REG_NONE) {
1314 u64 filter = uncore_shared_reg_config(box, 0);
1315 wrmsrl(reg1->reg, filter & 0xffffffff);
1316 wrmsrl(reg1->reg + 6, filter >> 32);
1317 }
1318
1319 wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
1320}
1321
1322static struct intel_uncore_ops ivt_uncore_cbox_ops = {
1323 .init_box = ivt_uncore_msr_init_box,
1324 .disable_box = snbep_uncore_msr_disable_box,
1325 .enable_box = snbep_uncore_msr_enable_box,
1326 .disable_event = snbep_uncore_msr_disable_event,
1327 .enable_event = ivt_cbox_enable_event,
1328 .read_counter = uncore_msr_read_counter,
1329 .hw_config = ivt_cbox_hw_config,
1330 .get_constraint = ivt_cbox_get_constraint,
1331 .put_constraint = snbep_cbox_put_constraint,
1332};
1333
1334static struct intel_uncore_type ivt_uncore_cbox = {
1335 .name = "cbox",
1336 .num_counters = 4,
1337 .num_boxes = 15,
1338 .perf_ctr_bits = 44,
1339 .event_ctl = SNBEP_C0_MSR_PMON_CTL0,
1340 .perf_ctr = SNBEP_C0_MSR_PMON_CTR0,
1341 .event_mask = IVT_CBO_MSR_PMON_RAW_EVENT_MASK,
1342 .box_ctl = SNBEP_C0_MSR_PMON_BOX_CTL,
1343 .msr_offset = SNBEP_CBO_MSR_OFFSET,
1344 .num_shared_regs = 1,
1345 .constraints = snbep_uncore_cbox_constraints,
1346 .ops = &ivt_uncore_cbox_ops,
1347 .format_group = &ivt_uncore_cbox_format_group,
1348};
1349
1350static struct intel_uncore_ops ivt_uncore_pcu_ops = {
1351 IVT_UNCORE_MSR_OPS_COMMON_INIT(),
1352 .hw_config = snbep_pcu_hw_config,
1353 .get_constraint = snbep_pcu_get_constraint,
1354 .put_constraint = snbep_pcu_put_constraint,
1355};
1356
1357static struct intel_uncore_type ivt_uncore_pcu = {
1358 .name = "pcu",
1359 .num_counters = 4,
1360 .num_boxes = 1,
1361 .perf_ctr_bits = 48,
1362 .perf_ctr = SNBEP_PCU_MSR_PMON_CTR0,
1363 .event_ctl = SNBEP_PCU_MSR_PMON_CTL0,
1364 .event_mask = IVT_PCU_MSR_PMON_RAW_EVENT_MASK,
1365 .box_ctl = SNBEP_PCU_MSR_PMON_BOX_CTL,
1366 .num_shared_regs = 1,
1367 .ops = &ivt_uncore_pcu_ops,
1368 .format_group = &ivt_uncore_pcu_format_group,
1369};
1370
1371static struct intel_uncore_type *ivt_msr_uncores[] = {
1372 &ivt_uncore_ubox,
1373 &ivt_uncore_cbox,
1374 &ivt_uncore_pcu,
1375 NULL,
1376};
1377
1378static struct intel_uncore_type ivt_uncore_ha = {
1379 .name = "ha",
1380 .num_counters = 4,
1381 .num_boxes = 2,
1382 .perf_ctr_bits = 48,
1383 IVT_UNCORE_PCI_COMMON_INIT(),
1384};
1385
1386static struct intel_uncore_type ivt_uncore_imc = {
1387 .name = "imc",
1388 .num_counters = 4,
1389 .num_boxes = 8,
1390 .perf_ctr_bits = 48,
1391 .fixed_ctr_bits = 48,
1392 .fixed_ctr = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
1393 .fixed_ctl = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
1394 IVT_UNCORE_PCI_COMMON_INIT(),
1395};
1396
1397/* registers in IRP boxes are not properly aligned */
1398static unsigned ivt_uncore_irp_ctls[] = {0xd8, 0xdc, 0xe0, 0xe4};
1399static unsigned ivt_uncore_irp_ctrs[] = {0xa0, 0xb0, 0xb8, 0xc0};
1400
1401static void ivt_uncore_irp_enable_event(struct intel_uncore_box *box, struct perf_event *event)
1402{
1403 struct pci_dev *pdev = box->pci_dev;
1404 struct hw_perf_event *hwc = &event->hw;
1405
1406 pci_write_config_dword(pdev, ivt_uncore_irp_ctls[hwc->idx],
1407 hwc->config | SNBEP_PMON_CTL_EN);
1408}
1409
1410static void ivt_uncore_irp_disable_event(struct intel_uncore_box *box, struct perf_event *event)
1411{
1412 struct pci_dev *pdev = box->pci_dev;
1413 struct hw_perf_event *hwc = &event->hw;
1414
1415 pci_write_config_dword(pdev, ivt_uncore_irp_ctls[hwc->idx], hwc->config);
1416}
1417
1418static u64 ivt_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event)
1419{
1420 struct pci_dev *pdev = box->pci_dev;
1421 struct hw_perf_event *hwc = &event->hw;
1422 u64 count = 0;
1423
1424 pci_read_config_dword(pdev, ivt_uncore_irp_ctrs[hwc->idx], (u32 *)&count);
1425 pci_read_config_dword(pdev, ivt_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1);
1426
1427 return count;
1428}
1429
1430static struct intel_uncore_ops ivt_uncore_irp_ops = {
1431 .init_box = ivt_uncore_pci_init_box,
1432 .disable_box = snbep_uncore_pci_disable_box,
1433 .enable_box = snbep_uncore_pci_enable_box,
1434 .disable_event = ivt_uncore_irp_disable_event,
1435 .enable_event = ivt_uncore_irp_enable_event,
1436 .read_counter = ivt_uncore_irp_read_counter,
1437};
1438
1439static struct intel_uncore_type ivt_uncore_irp = {
1440 .name = "irp",
1441 .num_counters = 4,
1442 .num_boxes = 1,
1443 .perf_ctr_bits = 48,
1444 .event_mask = IVT_PMON_RAW_EVENT_MASK,
1445 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
1446 .ops = &ivt_uncore_irp_ops,
1447 .format_group = &ivt_uncore_format_group,
1448};
1449
1450static struct intel_uncore_ops ivt_uncore_qpi_ops = {
1451 .init_box = ivt_uncore_pci_init_box,
1452 .disable_box = snbep_uncore_pci_disable_box,
1453 .enable_box = snbep_uncore_pci_enable_box,
1454 .disable_event = snbep_uncore_pci_disable_event,
1455 .enable_event = snbep_qpi_enable_event,
1456 .read_counter = snbep_uncore_pci_read_counter,
1457 .hw_config = snbep_qpi_hw_config,
1458 .get_constraint = uncore_get_constraint,
1459 .put_constraint = uncore_put_constraint,
1460};
1461
1462static struct intel_uncore_type ivt_uncore_qpi = {
1463 .name = "qpi",
1464 .num_counters = 4,
1465 .num_boxes = 3,
1466 .perf_ctr_bits = 48,
1467 .perf_ctr = SNBEP_PCI_PMON_CTR0,
1468 .event_ctl = SNBEP_PCI_PMON_CTL0,
1469 .event_mask = IVT_QPI_PCI_PMON_RAW_EVENT_MASK,
1470 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
1471 .num_shared_regs = 1,
1472 .ops = &ivt_uncore_qpi_ops,
1473 .format_group = &ivt_uncore_qpi_format_group,
1474};
1475
1476static struct intel_uncore_type ivt_uncore_r2pcie = {
1477 .name = "r2pcie",
1478 .num_counters = 4,
1479 .num_boxes = 1,
1480 .perf_ctr_bits = 44,
1481 .constraints = snbep_uncore_r2pcie_constraints,
1482 IVT_UNCORE_PCI_COMMON_INIT(),
1483};
1484
1485static struct intel_uncore_type ivt_uncore_r3qpi = {
1486 .name = "r3qpi",
1487 .num_counters = 3,
1488 .num_boxes = 2,
1489 .perf_ctr_bits = 44,
1490 .constraints = snbep_uncore_r3qpi_constraints,
1491 IVT_UNCORE_PCI_COMMON_INIT(),
1492};
1493
1494enum {
1495 IVT_PCI_UNCORE_HA,
1496 IVT_PCI_UNCORE_IMC,
1497 IVT_PCI_UNCORE_IRP,
1498 IVT_PCI_UNCORE_QPI,
1499 IVT_PCI_UNCORE_R2PCIE,
1500 IVT_PCI_UNCORE_R3QPI,
1501};
1502
1503static struct intel_uncore_type *ivt_pci_uncores[] = {
1504 [IVT_PCI_UNCORE_HA] = &ivt_uncore_ha,
1505 [IVT_PCI_UNCORE_IMC] = &ivt_uncore_imc,
1506 [IVT_PCI_UNCORE_IRP] = &ivt_uncore_irp,
1507 [IVT_PCI_UNCORE_QPI] = &ivt_uncore_qpi,
1508 [IVT_PCI_UNCORE_R2PCIE] = &ivt_uncore_r2pcie,
1509 [IVT_PCI_UNCORE_R3QPI] = &ivt_uncore_r3qpi,
1510 NULL,
1511};
1512
1513static const struct pci_device_id ivt_uncore_pci_ids[] = {
1514 { /* Home Agent 0 */
1515 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe30),
1516 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_HA, 0),
1517 },
1518 { /* Home Agent 1 */
1519 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe38),
1520 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_HA, 1),
1521 },
1522 { /* MC0 Channel 0 */
1523 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb4),
1524 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 0),
1525 },
1526 { /* MC0 Channel 1 */
1527 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb5),
1528 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 1),
1529 },
1530 { /* MC0 Channel 3 */
1531 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb0),
1532 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 2),
1533 },
1534 { /* MC0 Channel 4 */
1535 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb1),
1536 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 3),
1537 },
1538 { /* MC1 Channel 0 */
1539 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef4),
1540 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 4),
1541 },
1542 { /* MC1 Channel 1 */
1543 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef5),
1544 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 5),
1545 },
1546 { /* MC1 Channel 3 */
1547 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef0),
1548 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 6),
1549 },
1550 { /* MC1 Channel 4 */
1551 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef1),
1552 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 7),
1553 },
1554 { /* IRP */
1555 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe39),
1556 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IRP, 0),
1557 },
1558 { /* QPI0 Port 0 */
1559 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe32),
1560 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_QPI, 0),
1561 },
1562 { /* QPI0 Port 1 */
1563 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe33),
1564 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_QPI, 1),
1565 },
1566 { /* QPI1 Port 2 */
1567 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3a),
1568 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_QPI, 2),
1569 },
1570 { /* R2PCIe */
1571 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe34),
1572 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_R2PCIE, 0),
1573 },
1574 { /* R3QPI0 Link 0 */
1575 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe36),
1576 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_R3QPI, 0),
1577 },
1578 { /* R3QPI0 Link 1 */
1579 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe37),
1580 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_R3QPI, 1),
1581 },
1582 { /* R3QPI1 Link 2 */
1583 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3e),
1584 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_R3QPI, 2),
1585 },
1586 { /* QPI Port 0 filter */
1587 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe86),
1588 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
1589 SNBEP_PCI_QPI_PORT0_FILTER),
1590 },
1591 { /* QPI Port 0 filter */
1592 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe96),
1593 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
1594 SNBEP_PCI_QPI_PORT1_FILTER),
1595 },
1596 { /* end: all zeroes */ }
1597};
1598
1599static struct pci_driver ivt_uncore_pci_driver = {
1600 .name = "ivt_uncore",
1601 .id_table = ivt_uncore_pci_ids,
1602};
1603/* end of IvyTown uncore support */
1604
1605/* Sandy Bridge uncore support */
1606static void snb_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
1607{
1608 struct hw_perf_event *hwc = &event->hw;
1609
1610 if (hwc->idx < UNCORE_PMC_IDX_FIXED)
1611 wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
1612 else
1613 wrmsrl(hwc->config_base, SNB_UNC_CTL_EN);
1614}
1615
1616static void snb_uncore_msr_disable_event(struct intel_uncore_box *box, struct perf_event *event)
1617{
1618 wrmsrl(event->hw.config_base, 0);
1619}
1620
1621static void snb_uncore_msr_init_box(struct intel_uncore_box *box)
1622{
1623 if (box->pmu->pmu_idx == 0) {
1624 wrmsrl(SNB_UNC_PERF_GLOBAL_CTL,
1625 SNB_UNC_GLOBAL_CTL_EN | SNB_UNC_GLOBAL_CTL_CORE_ALL);
1626 }
1627}
1628
1629static struct uncore_event_desc snb_uncore_events[] = {
1630 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
1631 { /* end: all zeroes */ },
1632};
1633
1634static struct attribute *snb_uncore_formats_attr[] = {
1635 &format_attr_event.attr,
1636 &format_attr_umask.attr,
1637 &format_attr_edge.attr,
1638 &format_attr_inv.attr,
1639 &format_attr_cmask5.attr,
1640 NULL,
1641};
1642
1643static struct attribute_group snb_uncore_format_group = {
1644 .name = "format",
1645 .attrs = snb_uncore_formats_attr,
1646};
1647
1648static struct intel_uncore_ops snb_uncore_msr_ops = {
1649 .init_box = snb_uncore_msr_init_box,
1650 .disable_event = snb_uncore_msr_disable_event,
1651 .enable_event = snb_uncore_msr_enable_event,
1652 .read_counter = uncore_msr_read_counter,
1653};
1654
1655static struct event_constraint snb_uncore_cbox_constraints[] = {
1656 UNCORE_EVENT_CONSTRAINT(0x80, 0x1),
1657 UNCORE_EVENT_CONSTRAINT(0x83, 0x1),
1658 EVENT_CONSTRAINT_END
1659};
1660
1661static struct intel_uncore_type snb_uncore_cbox = {
1662 .name = "cbox",
1663 .num_counters = 2,
1664 .num_boxes = 4,
1665 .perf_ctr_bits = 44,
1666 .fixed_ctr_bits = 48,
1667 .perf_ctr = SNB_UNC_CBO_0_PER_CTR0,
1668 .event_ctl = SNB_UNC_CBO_0_PERFEVTSEL0,
1669 .fixed_ctr = SNB_UNC_FIXED_CTR,
1670 .fixed_ctl = SNB_UNC_FIXED_CTR_CTRL,
1671 .single_fixed = 1,
1672 .event_mask = SNB_UNC_RAW_EVENT_MASK,
1673 .msr_offset = SNB_UNC_CBO_MSR_OFFSET,
1674 .constraints = snb_uncore_cbox_constraints,
1675 .ops = &snb_uncore_msr_ops,
1676 .format_group = &snb_uncore_format_group,
1677 .event_descs = snb_uncore_events,
1678};
1679
1680static struct intel_uncore_type *snb_msr_uncores[] = {
1681 &snb_uncore_cbox,
1682 NULL,
1683};
1684
1685enum {
1686 SNB_PCI_UNCORE_IMC,
1687};
1688
1689static struct uncore_event_desc snb_uncore_imc_events[] = {
1690 INTEL_UNCORE_EVENT_DESC(data_reads, "event=0x01"),
1691 INTEL_UNCORE_EVENT_DESC(data_reads.scale, "6.103515625e-5"),
1692 INTEL_UNCORE_EVENT_DESC(data_reads.unit, "MiB"),
1693
1694 INTEL_UNCORE_EVENT_DESC(data_writes, "event=0x02"),
1695 INTEL_UNCORE_EVENT_DESC(data_writes.scale, "6.103515625e-5"),
1696 INTEL_UNCORE_EVENT_DESC(data_writes.unit, "MiB"),
1697
1698 { /* end: all zeroes */ },
1699};
1700
1701#define SNB_UNCORE_PCI_IMC_EVENT_MASK 0xff
1702#define SNB_UNCORE_PCI_IMC_BAR_OFFSET 0x48
1703
1704/* page size multiple covering all config regs */
1705#define SNB_UNCORE_PCI_IMC_MAP_SIZE 0x6000
1706
1707#define SNB_UNCORE_PCI_IMC_DATA_READS 0x1
1708#define SNB_UNCORE_PCI_IMC_DATA_READS_BASE 0x5050
1709#define SNB_UNCORE_PCI_IMC_DATA_WRITES 0x2
1710#define SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE 0x5054
1711#define SNB_UNCORE_PCI_IMC_CTR_BASE SNB_UNCORE_PCI_IMC_DATA_READS_BASE
1712
1713static struct attribute *snb_uncore_imc_formats_attr[] = {
1714 &format_attr_event.attr,
1715 NULL,
1716};
1717
1718static struct attribute_group snb_uncore_imc_format_group = {
1719 .name = "format",
1720 .attrs = snb_uncore_imc_formats_attr,
1721};
1722
1723static void snb_uncore_imc_init_box(struct intel_uncore_box *box)
1724{
1725 struct pci_dev *pdev = box->pci_dev;
1726 int where = SNB_UNCORE_PCI_IMC_BAR_OFFSET;
1727 resource_size_t addr;
1728 u32 pci_dword;
1729
1730 pci_read_config_dword(pdev, where, &pci_dword);
1731 addr = pci_dword;
1732
1733#ifdef CONFIG_PHYS_ADDR_T_64BIT
1734 pci_read_config_dword(pdev, where + 4, &pci_dword);
1735 addr |= ((resource_size_t)pci_dword << 32);
1736#endif
1737
1738 addr &= ~(PAGE_SIZE - 1);
1739
1740 box->io_addr = ioremap(addr, SNB_UNCORE_PCI_IMC_MAP_SIZE);
1741 box->hrtimer_duration = UNCORE_SNB_IMC_HRTIMER_INTERVAL;
1742}
1743
1744static void snb_uncore_imc_enable_box(struct intel_uncore_box *box)
1745{}
1746
1747static void snb_uncore_imc_disable_box(struct intel_uncore_box *box)
1748{}
1749
1750static void snb_uncore_imc_enable_event(struct intel_uncore_box *box, struct perf_event *event)
1751{}
1752
1753static void snb_uncore_imc_disable_event(struct intel_uncore_box *box, struct perf_event *event)
1754{}
1755
1756static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf_event *event)
1757{
1758 struct hw_perf_event *hwc = &event->hw;
1759
1760 return (u64)*(unsigned int *)(box->io_addr + hwc->event_base);
1761}
1762
1763/*
1764 * custom event_init() function because we define our own fixed, free
1765 * running counters, so we do not want to conflict with generic uncore
1766 * logic. Also simplifies processing
1767 */
1768static int snb_uncore_imc_event_init(struct perf_event *event)
1769{
1770 struct intel_uncore_pmu *pmu;
1771 struct intel_uncore_box *box;
1772 struct hw_perf_event *hwc = &event->hw;
1773 u64 cfg = event->attr.config & SNB_UNCORE_PCI_IMC_EVENT_MASK;
1774 int idx, base;
1775
1776 if (event->attr.type != event->pmu->type)
1777 return -ENOENT;
1778
1779 pmu = uncore_event_to_pmu(event);
1780 /* no device found for this pmu */
1781 if (pmu->func_id < 0)
1782 return -ENOENT;
1783
1784 /* Sampling not supported yet */
1785 if (hwc->sample_period)
1786 return -EINVAL;
1787
1788 /* unsupported modes and filters */
1789 if (event->attr.exclude_user ||
1790 event->attr.exclude_kernel ||
1791 event->attr.exclude_hv ||
1792 event->attr.exclude_idle ||
1793 event->attr.exclude_host ||
1794 event->attr.exclude_guest ||
1795 event->attr.sample_period) /* no sampling */
1796 return -EINVAL;
1797
1798 /*
1799 * Place all uncore events for a particular physical package
1800 * onto a single cpu
1801 */
1802 if (event->cpu < 0)
1803 return -EINVAL;
1804
1805 /* check only supported bits are set */
1806 if (event->attr.config & ~SNB_UNCORE_PCI_IMC_EVENT_MASK)
1807 return -EINVAL;
1808
1809 box = uncore_pmu_to_box(pmu, event->cpu);
1810 if (!box || box->cpu < 0)
1811 return -EINVAL;
1812
1813 event->cpu = box->cpu;
1814
1815 event->hw.idx = -1;
1816 event->hw.last_tag = ~0ULL;
1817 event->hw.extra_reg.idx = EXTRA_REG_NONE;
1818 event->hw.branch_reg.idx = EXTRA_REG_NONE;
1819 /*
1820 * check event is known (whitelist, determines counter)
1821 */
1822 switch (cfg) {
1823 case SNB_UNCORE_PCI_IMC_DATA_READS:
1824 base = SNB_UNCORE_PCI_IMC_DATA_READS_BASE;
1825 idx = UNCORE_PMC_IDX_FIXED;
1826 break;
1827 case SNB_UNCORE_PCI_IMC_DATA_WRITES:
1828 base = SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE;
1829 idx = UNCORE_PMC_IDX_FIXED + 1;
1830 break;
1831 default:
1832 return -EINVAL;
1833 }
1834
1835 /* must be done before validate_group */
1836 event->hw.event_base = base;
1837 event->hw.config = cfg;
1838 event->hw.idx = idx;
1839
1840 /* no group validation needed, we have free running counters */
1841
1842 return 0;
1843}
1844
1845static int snb_uncore_imc_hw_config(struct intel_uncore_box *box, struct perf_event *event)
1846{
1847 return 0;
1848}
1849
1850static void snb_uncore_imc_event_start(struct perf_event *event, int flags)
1851{
1852 struct intel_uncore_box *box = uncore_event_to_box(event);
1853 u64 count;
1854
1855 if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
1856 return;
1857
1858 event->hw.state = 0;
1859 box->n_active++;
1860
1861 list_add_tail(&event->active_entry, &box->active_list);
1862
1863 count = snb_uncore_imc_read_counter(box, event);
1864 local64_set(&event->hw.prev_count, count);
1865
1866 if (box->n_active == 1)
1867 uncore_pmu_start_hrtimer(box);
1868}
1869
1870static void snb_uncore_imc_event_stop(struct perf_event *event, int flags)
1871{
1872 struct intel_uncore_box *box = uncore_event_to_box(event);
1873 struct hw_perf_event *hwc = &event->hw;
1874
1875 if (!(hwc->state & PERF_HES_STOPPED)) {
1876 box->n_active--;
1877
1878 WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
1879 hwc->state |= PERF_HES_STOPPED;
1880
1881 list_del(&event->active_entry);
1882
1883 if (box->n_active == 0)
1884 uncore_pmu_cancel_hrtimer(box);
1885 }
1886
1887 if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
1888 /*
1889 * Drain the remaining delta count out of a event
1890 * that we are disabling:
1891 */
1892 uncore_perf_event_update(box, event);
1893 hwc->state |= PERF_HES_UPTODATE;
1894 }
1895}
1896
1897static int snb_uncore_imc_event_add(struct perf_event *event, int flags)
1898{
1899 struct intel_uncore_box *box = uncore_event_to_box(event);
1900 struct hw_perf_event *hwc = &event->hw;
1901
1902 if (!box)
1903 return -ENODEV;
1904
1905 hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
1906 if (!(flags & PERF_EF_START))
1907 hwc->state |= PERF_HES_ARCH;
1908
1909 snb_uncore_imc_event_start(event, 0);
1910
1911 box->n_events++;
1912
1913 return 0;
1914}
1915
1916static void snb_uncore_imc_event_del(struct perf_event *event, int flags)
1917{
1918 struct intel_uncore_box *box = uncore_event_to_box(event);
1919 int i;
1920
1921 snb_uncore_imc_event_stop(event, PERF_EF_UPDATE);
1922
1923 for (i = 0; i < box->n_events; i++) {
1924 if (event == box->event_list[i]) {
1925 --box->n_events;
1926 break;
1927 }
1928 }
1929}
1930
1931static int snb_pci2phy_map_init(int devid)
1932{
1933 struct pci_dev *dev = NULL;
1934 int bus;
1935
1936 dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, dev);
1937 if (!dev)
1938 return -ENOTTY;
1939
1940 bus = dev->bus->number;
1941
1942 pcibus_to_physid[bus] = 0;
1943
1944 pci_dev_put(dev);
1945
1946 return 0;
1947}
1948
1949static struct pmu snb_uncore_imc_pmu = {
1950 .task_ctx_nr = perf_invalid_context,
1951 .event_init = snb_uncore_imc_event_init,
1952 .add = snb_uncore_imc_event_add,
1953 .del = snb_uncore_imc_event_del,
1954 .start = snb_uncore_imc_event_start,
1955 .stop = snb_uncore_imc_event_stop,
1956 .read = uncore_pmu_event_read,
1957};
1958
1959static struct intel_uncore_ops snb_uncore_imc_ops = {
1960 .init_box = snb_uncore_imc_init_box,
1961 .enable_box = snb_uncore_imc_enable_box,
1962 .disable_box = snb_uncore_imc_disable_box,
1963 .disable_event = snb_uncore_imc_disable_event,
1964 .enable_event = snb_uncore_imc_enable_event,
1965 .hw_config = snb_uncore_imc_hw_config,
1966 .read_counter = snb_uncore_imc_read_counter,
1967};
1968
1969static struct intel_uncore_type snb_uncore_imc = {
1970 .name = "imc",
1971 .num_counters = 2,
1972 .num_boxes = 1,
1973 .fixed_ctr_bits = 32,
1974 .fixed_ctr = SNB_UNCORE_PCI_IMC_CTR_BASE,
1975 .event_descs = snb_uncore_imc_events,
1976 .format_group = &snb_uncore_imc_format_group,
1977 .perf_ctr = SNB_UNCORE_PCI_IMC_DATA_READS_BASE,
1978 .event_mask = SNB_UNCORE_PCI_IMC_EVENT_MASK,
1979 .ops = &snb_uncore_imc_ops,
1980 .pmu = &snb_uncore_imc_pmu,
1981};
1982
1983static struct intel_uncore_type *snb_pci_uncores[] = {
1984 [SNB_PCI_UNCORE_IMC] = &snb_uncore_imc,
1985 NULL,
1986};
1987
1988static const struct pci_device_id snb_uncore_pci_ids[] = {
1989 { /* IMC */
1990 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SNB_IMC),
1991 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
1992 },
1993 { /* end: all zeroes */ },
1994};
1995
1996static const struct pci_device_id ivb_uncore_pci_ids[] = {
1997 { /* IMC */
1998 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_IMC),
1999 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
2000 },
2001 { /* end: all zeroes */ },
2002};
2003
2004static const struct pci_device_id hsw_uncore_pci_ids[] = {
2005 { /* IMC */
2006 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
2007 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
2008 },
2009 { /* end: all zeroes */ },
2010};
2011
2012static struct pci_driver snb_uncore_pci_driver = {
2013 .name = "snb_uncore",
2014 .id_table = snb_uncore_pci_ids,
2015};
2016
2017static struct pci_driver ivb_uncore_pci_driver = {
2018 .name = "ivb_uncore",
2019 .id_table = ivb_uncore_pci_ids,
2020};
2021
2022static struct pci_driver hsw_uncore_pci_driver = {
2023 .name = "hsw_uncore",
2024 .id_table = hsw_uncore_pci_ids,
2025};
2026
2027/* end of Sandy Bridge uncore support */
2028
2029/* Nehalem uncore support */
2030static void nhm_uncore_msr_disable_box(struct intel_uncore_box *box)
2031{
2032 wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, 0);
2033}
2034
2035static void nhm_uncore_msr_enable_box(struct intel_uncore_box *box)
2036{
2037 wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, NHM_UNC_GLOBAL_CTL_EN_PC_ALL | NHM_UNC_GLOBAL_CTL_EN_FC);
2038}
2039
2040static void nhm_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
2041{
2042 struct hw_perf_event *hwc = &event->hw;
2043
2044 if (hwc->idx < UNCORE_PMC_IDX_FIXED)
2045 wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
2046 else
2047 wrmsrl(hwc->config_base, NHM_UNC_FIXED_CTR_CTL_EN);
2048}
2049
2050static struct attribute *nhm_uncore_formats_attr[] = {
2051 &format_attr_event.attr,
2052 &format_attr_umask.attr,
2053 &format_attr_edge.attr,
2054 &format_attr_inv.attr,
2055 &format_attr_cmask8.attr,
2056 NULL,
2057};
2058
2059static struct attribute_group nhm_uncore_format_group = {
2060 .name = "format",
2061 .attrs = nhm_uncore_formats_attr,
2062};
2063
2064static struct uncore_event_desc nhm_uncore_events[] = {
2065 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
2066 INTEL_UNCORE_EVENT_DESC(qmc_writes_full_any, "event=0x2f,umask=0x0f"),
2067 INTEL_UNCORE_EVENT_DESC(qmc_normal_reads_any, "event=0x2c,umask=0x0f"),
2068 INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_reads, "event=0x20,umask=0x01"),
2069 INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_writes, "event=0x20,umask=0x02"),
2070 INTEL_UNCORE_EVENT_DESC(qhl_request_remote_reads, "event=0x20,umask=0x04"),
2071 INTEL_UNCORE_EVENT_DESC(qhl_request_remote_writes, "event=0x20,umask=0x08"),
2072 INTEL_UNCORE_EVENT_DESC(qhl_request_local_reads, "event=0x20,umask=0x10"),
2073 INTEL_UNCORE_EVENT_DESC(qhl_request_local_writes, "event=0x20,umask=0x20"),
2074 { /* end: all zeroes */ },
2075};
2076
2077static struct intel_uncore_ops nhm_uncore_msr_ops = {
2078 .disable_box = nhm_uncore_msr_disable_box,
2079 .enable_box = nhm_uncore_msr_enable_box,
2080 .disable_event = snb_uncore_msr_disable_event,
2081 .enable_event = nhm_uncore_msr_enable_event,
2082 .read_counter = uncore_msr_read_counter,
2083};
2084
2085static struct intel_uncore_type nhm_uncore = {
2086 .name = "",
2087 .num_counters = 8,
2088 .num_boxes = 1,
2089 .perf_ctr_bits = 48,
2090 .fixed_ctr_bits = 48,
2091 .event_ctl = NHM_UNC_PERFEVTSEL0,
2092 .perf_ctr = NHM_UNC_UNCORE_PMC0,
2093 .fixed_ctr = NHM_UNC_FIXED_CTR,
2094 .fixed_ctl = NHM_UNC_FIXED_CTR_CTRL,
2095 .event_mask = NHM_UNC_RAW_EVENT_MASK,
2096 .event_descs = nhm_uncore_events,
2097 .ops = &nhm_uncore_msr_ops,
2098 .format_group = &nhm_uncore_format_group,
2099};
2100
2101static struct intel_uncore_type *nhm_msr_uncores[] = {
2102 &nhm_uncore,
2103 NULL,
2104};
2105/* end of Nehalem uncore support */
2106
2107/* Nehalem-EX uncore support */
2108DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5");
2109DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7");
2110DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63");
2111DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63");
2112
2113static void nhmex_uncore_msr_init_box(struct intel_uncore_box *box)
2114{
2115 wrmsrl(NHMEX_U_MSR_PMON_GLOBAL_CTL, NHMEX_U_PMON_GLOBAL_EN_ALL);
2116}
2117
2118static void nhmex_uncore_msr_disable_box(struct intel_uncore_box *box)
2119{
2120 unsigned msr = uncore_msr_box_ctl(box);
2121 u64 config;
2122
2123 if (msr) {
2124 rdmsrl(msr, config);
2125 config &= ~((1ULL << uncore_num_counters(box)) - 1);
2126 /* WBox has a fixed counter */
2127 if (uncore_msr_fixed_ctl(box))
2128 config &= ~NHMEX_W_PMON_GLOBAL_FIXED_EN;
2129 wrmsrl(msr, config);
2130 }
2131}
2132
2133static void nhmex_uncore_msr_enable_box(struct intel_uncore_box *box)
2134{
2135 unsigned msr = uncore_msr_box_ctl(box);
2136 u64 config;
2137
2138 if (msr) {
2139 rdmsrl(msr, config);
2140 config |= (1ULL << uncore_num_counters(box)) - 1;
2141 /* WBox has a fixed counter */
2142 if (uncore_msr_fixed_ctl(box))
2143 config |= NHMEX_W_PMON_GLOBAL_FIXED_EN;
2144 wrmsrl(msr, config);
2145 }
2146}
2147
2148static void nhmex_uncore_msr_disable_event(struct intel_uncore_box *box, struct perf_event *event)
2149{
2150 wrmsrl(event->hw.config_base, 0);
2151}
2152
2153static void nhmex_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
2154{
2155 struct hw_perf_event *hwc = &event->hw;
2156
2157 if (hwc->idx >= UNCORE_PMC_IDX_FIXED)
2158 wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0);
2159 else if (box->pmu->type->event_mask & NHMEX_PMON_CTL_EN_BIT0)
2160 wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22);
2161 else
2162 wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);
2163}
2164
2165#define NHMEX_UNCORE_OPS_COMMON_INIT() \
2166 .init_box = nhmex_uncore_msr_init_box, \
2167 .disable_box = nhmex_uncore_msr_disable_box, \
2168 .enable_box = nhmex_uncore_msr_enable_box, \
2169 .disable_event = nhmex_uncore_msr_disable_event, \
2170 .read_counter = uncore_msr_read_counter
2171
2172static struct intel_uncore_ops nhmex_uncore_ops = {
2173 NHMEX_UNCORE_OPS_COMMON_INIT(),
2174 .enable_event = nhmex_uncore_msr_enable_event,
2175};
2176
2177static struct attribute *nhmex_uncore_ubox_formats_attr[] = {
2178 &format_attr_event.attr,
2179 &format_attr_edge.attr,
2180 NULL,
2181};
2182
2183static struct attribute_group nhmex_uncore_ubox_format_group = {
2184 .name = "format",
2185 .attrs = nhmex_uncore_ubox_formats_attr,
2186};
2187
2188static struct intel_uncore_type nhmex_uncore_ubox = {
2189 .name = "ubox",
2190 .num_counters = 1,
2191 .num_boxes = 1,
2192 .perf_ctr_bits = 48,
2193 .event_ctl = NHMEX_U_MSR_PMON_EV_SEL,
2194 .perf_ctr = NHMEX_U_MSR_PMON_CTR,
2195 .event_mask = NHMEX_U_PMON_RAW_EVENT_MASK,
2196 .box_ctl = NHMEX_U_MSR_PMON_GLOBAL_CTL,
2197 .ops = &nhmex_uncore_ops,
2198 .format_group = &nhmex_uncore_ubox_format_group
2199};
2200
2201static struct attribute *nhmex_uncore_cbox_formats_attr[] = {
2202 &format_attr_event.attr,
2203 &format_attr_umask.attr,
2204 &format_attr_edge.attr,
2205 &format_attr_inv.attr,
2206 &format_attr_thresh8.attr,
2207 NULL,
2208};
2209
2210static struct attribute_group nhmex_uncore_cbox_format_group = {
2211 .name = "format",
2212 .attrs = nhmex_uncore_cbox_formats_attr,
2213};
2214
2215/* msr offset for each instance of cbox */
2216static unsigned nhmex_cbox_msr_offsets[] = {
2217 0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0,
2218};
2219
2220static struct intel_uncore_type nhmex_uncore_cbox = {
2221 .name = "cbox",
2222 .num_counters = 6,
2223 .num_boxes = 10,
2224 .perf_ctr_bits = 48,
2225 .event_ctl = NHMEX_C0_MSR_PMON_EV_SEL0,
2226 .perf_ctr = NHMEX_C0_MSR_PMON_CTR0,
2227 .event_mask = NHMEX_PMON_RAW_EVENT_MASK,
2228 .box_ctl = NHMEX_C0_MSR_PMON_GLOBAL_CTL,
2229 .msr_offsets = nhmex_cbox_msr_offsets,
2230 .pair_ctr_ctl = 1,
2231 .ops = &nhmex_uncore_ops,
2232 .format_group = &nhmex_uncore_cbox_format_group
2233};
2234
2235static struct uncore_event_desc nhmex_uncore_wbox_events[] = {
2236 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0"),
2237 { /* end: all zeroes */ },
2238};
2239
2240static struct intel_uncore_type nhmex_uncore_wbox = {
2241 .name = "wbox",
2242 .num_counters = 4,
2243 .num_boxes = 1,
2244 .perf_ctr_bits = 48,
2245 .event_ctl = NHMEX_W_MSR_PMON_CNT0,
2246 .perf_ctr = NHMEX_W_MSR_PMON_EVT_SEL0,
2247 .fixed_ctr = NHMEX_W_MSR_PMON_FIXED_CTR,
2248 .fixed_ctl = NHMEX_W_MSR_PMON_FIXED_CTL,
2249 .event_mask = NHMEX_PMON_RAW_EVENT_MASK,
2250 .box_ctl = NHMEX_W_MSR_GLOBAL_CTL,
2251 .pair_ctr_ctl = 1,
2252 .event_descs = nhmex_uncore_wbox_events,
2253 .ops = &nhmex_uncore_ops,
2254 .format_group = &nhmex_uncore_cbox_format_group
2255};
2256
2257static int nhmex_bbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
2258{
2259 struct hw_perf_event *hwc = &event->hw;
2260 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
2261 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
2262 int ctr, ev_sel;
2263
2264 ctr = (hwc->config & NHMEX_B_PMON_CTR_MASK) >>
2265 NHMEX_B_PMON_CTR_SHIFT;
2266 ev_sel = (hwc->config & NHMEX_B_PMON_CTL_EV_SEL_MASK) >>
2267 NHMEX_B_PMON_CTL_EV_SEL_SHIFT;
2268
2269 /* events that do not use the match/mask registers */
2270 if ((ctr == 0 && ev_sel > 0x3) || (ctr == 1 && ev_sel > 0x6) ||
2271 (ctr == 2 && ev_sel != 0x4) || ctr == 3)
2272 return 0;
2273
2274 if (box->pmu->pmu_idx == 0)
2275 reg1->reg = NHMEX_B0_MSR_MATCH;
2276 else
2277 reg1->reg = NHMEX_B1_MSR_MATCH;
2278 reg1->idx = 0;
2279 reg1->config = event->attr.config1;
2280 reg2->config = event->attr.config2;
2281 return 0;
2282}
2283
2284static void nhmex_bbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
2285{
2286 struct hw_perf_event *hwc = &event->hw;
2287 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
2288 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
2289
2290 if (reg1->idx != EXTRA_REG_NONE) {
2291 wrmsrl(reg1->reg, reg1->config);
2292 wrmsrl(reg1->reg + 1, reg2->config);
2293 }
2294 wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0 |
2295 (hwc->config & NHMEX_B_PMON_CTL_EV_SEL_MASK));
2296}
2297
2298/*
2299 * The Bbox has 4 counters, but each counter monitors different events.
2300 * Use bits 6-7 in the event config to select counter.
2301 */
2302static struct event_constraint nhmex_uncore_bbox_constraints[] = {
2303 EVENT_CONSTRAINT(0 , 1, 0xc0),
2304 EVENT_CONSTRAINT(0x40, 2, 0xc0),
2305 EVENT_CONSTRAINT(0x80, 4, 0xc0),
2306 EVENT_CONSTRAINT(0xc0, 8, 0xc0),
2307 EVENT_CONSTRAINT_END,
2308};
2309
2310static struct attribute *nhmex_uncore_bbox_formats_attr[] = {
2311 &format_attr_event5.attr,
2312 &format_attr_counter.attr,
2313 &format_attr_match.attr,
2314 &format_attr_mask.attr,
2315 NULL,
2316};
2317
2318static struct attribute_group nhmex_uncore_bbox_format_group = {
2319 .name = "format",
2320 .attrs = nhmex_uncore_bbox_formats_attr,
2321};
2322
2323static struct intel_uncore_ops nhmex_uncore_bbox_ops = {
2324 NHMEX_UNCORE_OPS_COMMON_INIT(),
2325 .enable_event = nhmex_bbox_msr_enable_event,
2326 .hw_config = nhmex_bbox_hw_config,
2327 .get_constraint = uncore_get_constraint,
2328 .put_constraint = uncore_put_constraint,
2329};
2330
2331static struct intel_uncore_type nhmex_uncore_bbox = {
2332 .name = "bbox",
2333 .num_counters = 4,
2334 .num_boxes = 2,
2335 .perf_ctr_bits = 48,
2336 .event_ctl = NHMEX_B0_MSR_PMON_CTL0,
2337 .perf_ctr = NHMEX_B0_MSR_PMON_CTR0,
2338 .event_mask = NHMEX_B_PMON_RAW_EVENT_MASK,
2339 .box_ctl = NHMEX_B0_MSR_PMON_GLOBAL_CTL,
2340 .msr_offset = NHMEX_B_MSR_OFFSET,
2341 .pair_ctr_ctl = 1,
2342 .num_shared_regs = 1,
2343 .constraints = nhmex_uncore_bbox_constraints,
2344 .ops = &nhmex_uncore_bbox_ops,
2345 .format_group = &nhmex_uncore_bbox_format_group
2346};
2347
2348static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
2349{
2350 struct hw_perf_event *hwc = &event->hw;
2351 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
2352 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
2353
2354 /* only TO_R_PROG_EV event uses the match/mask register */
2355 if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) !=
2356 NHMEX_S_EVENT_TO_R_PROG_EV)
2357 return 0;
2358
2359 if (box->pmu->pmu_idx == 0)
2360 reg1->reg = NHMEX_S0_MSR_MM_CFG;
2361 else
2362 reg1->reg = NHMEX_S1_MSR_MM_CFG;
2363 reg1->idx = 0;
2364 reg1->config = event->attr.config1;
2365 reg2->config = event->attr.config2;
2366 return 0;
2367}
2368
2369static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
2370{
2371 struct hw_perf_event *hwc = &event->hw;
2372 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
2373 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
2374
2375 if (reg1->idx != EXTRA_REG_NONE) {
2376 wrmsrl(reg1->reg, 0);
2377 wrmsrl(reg1->reg + 1, reg1->config);
2378 wrmsrl(reg1->reg + 2, reg2->config);
2379 wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN);
2380 }
2381 wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22);
2382}
2383
2384static struct attribute *nhmex_uncore_sbox_formats_attr[] = {
2385 &format_attr_event.attr,
2386 &format_attr_umask.attr,
2387 &format_attr_edge.attr,
2388 &format_attr_inv.attr,
2389 &format_attr_thresh8.attr,
2390 &format_attr_match.attr,
2391 &format_attr_mask.attr,
2392 NULL,
2393};
2394
2395static struct attribute_group nhmex_uncore_sbox_format_group = {
2396 .name = "format",
2397 .attrs = nhmex_uncore_sbox_formats_attr,
2398};
2399
2400static struct intel_uncore_ops nhmex_uncore_sbox_ops = {
2401 NHMEX_UNCORE_OPS_COMMON_INIT(),
2402 .enable_event = nhmex_sbox_msr_enable_event,
2403 .hw_config = nhmex_sbox_hw_config,
2404 .get_constraint = uncore_get_constraint,
2405 .put_constraint = uncore_put_constraint,
2406};
2407
2408static struct intel_uncore_type nhmex_uncore_sbox = {
2409 .name = "sbox",
2410 .num_counters = 4,
2411 .num_boxes = 2,
2412 .perf_ctr_bits = 48,
2413 .event_ctl = NHMEX_S0_MSR_PMON_CTL0,
2414 .perf_ctr = NHMEX_S0_MSR_PMON_CTR0,
2415 .event_mask = NHMEX_PMON_RAW_EVENT_MASK,
2416 .box_ctl = NHMEX_S0_MSR_PMON_GLOBAL_CTL,
2417 .msr_offset = NHMEX_S_MSR_OFFSET,
2418 .pair_ctr_ctl = 1,
2419 .num_shared_regs = 1,
2420 .ops = &nhmex_uncore_sbox_ops,
2421 .format_group = &nhmex_uncore_sbox_format_group
2422};
2423
2424enum {
2425 EXTRA_REG_NHMEX_M_FILTER,
2426 EXTRA_REG_NHMEX_M_DSP,
2427 EXTRA_REG_NHMEX_M_ISS,
2428 EXTRA_REG_NHMEX_M_MAP,
2429 EXTRA_REG_NHMEX_M_MSC_THR,
2430 EXTRA_REG_NHMEX_M_PGT,
2431 EXTRA_REG_NHMEX_M_PLD,
2432 EXTRA_REG_NHMEX_M_ZDP_CTL_FVC,
2433};
2434
2435static struct extra_reg nhmex_uncore_mbox_extra_regs[] = {
2436 MBOX_INC_SEL_EXTAR_REG(0x0, DSP),
2437 MBOX_INC_SEL_EXTAR_REG(0x4, MSC_THR),
2438 MBOX_INC_SEL_EXTAR_REG(0x5, MSC_THR),
2439 MBOX_INC_SEL_EXTAR_REG(0x9, ISS),
2440 /* event 0xa uses two extra registers */
2441 MBOX_INC_SEL_EXTAR_REG(0xa, ISS),
2442 MBOX_INC_SEL_EXTAR_REG(0xa, PLD),
2443 MBOX_INC_SEL_EXTAR_REG(0xb, PLD),
2444 /* events 0xd ~ 0x10 use the same extra register */
2445 MBOX_INC_SEL_EXTAR_REG(0xd, ZDP_CTL_FVC),
2446 MBOX_INC_SEL_EXTAR_REG(0xe, ZDP_CTL_FVC),
2447 MBOX_INC_SEL_EXTAR_REG(0xf, ZDP_CTL_FVC),
2448 MBOX_INC_SEL_EXTAR_REG(0x10, ZDP_CTL_FVC),
2449 MBOX_INC_SEL_EXTAR_REG(0x16, PGT),
2450 MBOX_SET_FLAG_SEL_EXTRA_REG(0x0, DSP),
2451 MBOX_SET_FLAG_SEL_EXTRA_REG(0x1, ISS),
2452 MBOX_SET_FLAG_SEL_EXTRA_REG(0x5, PGT),
2453 MBOX_SET_FLAG_SEL_EXTRA_REG(0x6, MAP),
2454 EVENT_EXTRA_END
2455};
2456
2457/* Nehalem-EX or Westmere-EX ? */
2458static bool uncore_nhmex;
2459
2460static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config)
2461{
2462 struct intel_uncore_extra_reg *er;
2463 unsigned long flags;
2464 bool ret = false;
2465 u64 mask;
2466
2467 if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
2468 er = &box->shared_regs[idx];
2469 raw_spin_lock_irqsave(&er->lock, flags);
2470 if (!atomic_read(&er->ref) || er->config == config) {
2471 atomic_inc(&er->ref);
2472 er->config = config;
2473 ret = true;
2474 }
2475 raw_spin_unlock_irqrestore(&er->lock, flags);
2476
2477 return ret;
2478 }
2479 /*
2480 * The ZDP_CTL_FVC MSR has 4 fields which are used to control
2481 * events 0xd ~ 0x10. Besides these 4 fields, there are additional
2482 * fields which are shared.
2483 */
2484 idx -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
2485 if (WARN_ON_ONCE(idx >= 4))
2486 return false;
2487
2488 /* mask of the shared fields */
2489 if (uncore_nhmex)
2490 mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK;
2491 else
2492 mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK;
2493 er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
2494
2495 raw_spin_lock_irqsave(&er->lock, flags);
2496 /* add mask of the non-shared field if it's in use */
2497 if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) {
2498 if (uncore_nhmex)
2499 mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
2500 else
2501 mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
2502 }
2503
2504 if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) {
2505 atomic_add(1 << (idx * 8), &er->ref);
2506 if (uncore_nhmex)
2507 mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK |
2508 NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
2509 else
2510 mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK |
2511 WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
2512 er->config &= ~mask;
2513 er->config |= (config & mask);
2514 ret = true;
2515 }
2516 raw_spin_unlock_irqrestore(&er->lock, flags);
2517
2518 return ret;
2519}
2520
2521static void nhmex_mbox_put_shared_reg(struct intel_uncore_box *box, int idx)
2522{
2523 struct intel_uncore_extra_reg *er;
2524
2525 if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
2526 er = &box->shared_regs[idx];
2527 atomic_dec(&er->ref);
2528 return;
2529 }
2530
2531 idx -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
2532 er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
2533 atomic_sub(1 << (idx * 8), &er->ref);
2534}
2535
2536static u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)
2537{
2538 struct hw_perf_event *hwc = &event->hw;
2539 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
2540 u64 idx, orig_idx = __BITS_VALUE(reg1->idx, 0, 8);
2541 u64 config = reg1->config;
2542
2543 /* get the non-shared control bits and shift them */
2544 idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
2545 if (uncore_nhmex)
2546 config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
2547 else
2548 config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
2549 if (new_idx > orig_idx) {
2550 idx = new_idx - orig_idx;
2551 config <<= 3 * idx;
2552 } else {
2553 idx = orig_idx - new_idx;
2554 config >>= 3 * idx;
2555 }
2556
2557 /* add the shared control bits back */
2558 if (uncore_nhmex)
2559 config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
2560 else
2561 config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
2562 config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
2563 if (modify) {
2564 /* adjust the main event selector */
2565 if (new_idx > orig_idx)
2566 hwc->config += idx << NHMEX_M_PMON_CTL_INC_SEL_SHIFT;
2567 else
2568 hwc->config -= idx << NHMEX_M_PMON_CTL_INC_SEL_SHIFT;
2569 reg1->config = config;
2570 reg1->idx = ~0xff | new_idx;
2571 }
2572 return config;
2573}
2574
2575static struct event_constraint *
2576nhmex_mbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
2577{
2578 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
2579 struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
2580 int i, idx[2], alloc = 0;
2581 u64 config1 = reg1->config;
2582
2583 idx[0] = __BITS_VALUE(reg1->idx, 0, 8);
2584 idx[1] = __BITS_VALUE(reg1->idx, 1, 8);
2585again:
2586 for (i = 0; i < 2; i++) {
2587 if (!uncore_box_is_fake(box) && (reg1->alloc & (0x1 << i)))
2588 idx[i] = 0xff;
2589
2590 if (idx[i] == 0xff)
2591 continue;
2592
2593 if (!nhmex_mbox_get_shared_reg(box, idx[i],
2594 __BITS_VALUE(config1, i, 32)))
2595 goto fail;
2596 alloc |= (0x1 << i);
2597 }
2598
2599 /* for the match/mask registers */
2600 if (reg2->idx != EXTRA_REG_NONE &&
2601 (uncore_box_is_fake(box) || !reg2->alloc) &&
2602 !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config))
2603 goto fail;
2604
2605 /*
2606 * If it's a fake box -- as per validate_{group,event}() we
2607 * shouldn't touch event state and we can avoid doing so
2608 * since both will only call get_event_constraints() once
2609 * on each event, this avoids the need for reg->alloc.
2610 */
2611 if (!uncore_box_is_fake(box)) {
2612 if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8))
2613 nhmex_mbox_alter_er(event, idx[0], true);
2614 reg1->alloc |= alloc;
2615 if (reg2->idx != EXTRA_REG_NONE)
2616 reg2->alloc = 1;
2617 }
2618 return NULL;
2619fail:
2620 if (idx[0] != 0xff && !(alloc & 0x1) &&
2621 idx[0] >= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
2622 /*
2623 * events 0xd ~ 0x10 are functional identical, but are
2624 * controlled by different fields in the ZDP_CTL_FVC
2625 * register. If we failed to take one field, try the
2626 * rest 3 choices.
2627 */
2628 BUG_ON(__BITS_VALUE(reg1->idx, 1, 8) != 0xff);
2629 idx[0] -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
2630 idx[0] = (idx[0] + 1) % 4;
2631 idx[0] += EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
2632 if (idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) {
2633 config1 = nhmex_mbox_alter_er(event, idx[0], false);
2634 goto again;
2635 }
2636 }
2637
2638 if (alloc & 0x1)
2639 nhmex_mbox_put_shared_reg(box, idx[0]);
2640 if (alloc & 0x2)
2641 nhmex_mbox_put_shared_reg(box, idx[1]);
2642 return &constraint_empty;
2643}
2644
2645static void nhmex_mbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
2646{
2647 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
2648 struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
2649
2650 if (uncore_box_is_fake(box))
2651 return;
2652
2653 if (reg1->alloc & 0x1)
2654 nhmex_mbox_put_shared_reg(box, __BITS_VALUE(reg1->idx, 0, 8));
2655 if (reg1->alloc & 0x2)
2656 nhmex_mbox_put_shared_reg(box, __BITS_VALUE(reg1->idx, 1, 8));
2657 reg1->alloc = 0;
2658
2659 if (reg2->alloc) {
2660 nhmex_mbox_put_shared_reg(box, reg2->idx);
2661 reg2->alloc = 0;
2662 }
2663}
2664
2665static int nhmex_mbox_extra_reg_idx(struct extra_reg *er)
2666{
2667 if (er->idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC)
2668 return er->idx;
2669 return er->idx + (er->event >> NHMEX_M_PMON_CTL_INC_SEL_SHIFT) - 0xd;
2670}
2671
2672static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
2673{
2674 struct intel_uncore_type *type = box->pmu->type;
2675 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
2676 struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
2677 struct extra_reg *er;
2678 unsigned msr;
2679 int reg_idx = 0;
2680 /*
2681 * The mbox events may require 2 extra MSRs at the most. But only
2682 * the lower 32 bits in these MSRs are significant, so we can use
2683 * config1 to pass two MSRs' config.
2684 */
2685 for (er = nhmex_uncore_mbox_extra_regs; er->msr; er++) {
2686 if (er->event != (event->hw.config & er->config_mask))
2687 continue;
2688 if (event->attr.config1 & ~er->valid_mask)
2689 return -EINVAL;
2690
2691 msr = er->msr + type->msr_offset * box->pmu->pmu_idx;
2692 if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff))
2693 return -EINVAL;
2694
2695 /* always use the 32~63 bits to pass the PLD config */
2696 if (er->idx == EXTRA_REG_NHMEX_M_PLD)
2697 reg_idx = 1;
2698 else if (WARN_ON_ONCE(reg_idx > 0))
2699 return -EINVAL;
2700
2701 reg1->idx &= ~(0xff << (reg_idx * 8));
2702 reg1->reg &= ~(0xffff << (reg_idx * 16));
2703 reg1->idx |= nhmex_mbox_extra_reg_idx(er) << (reg_idx * 8);
2704 reg1->reg |= msr << (reg_idx * 16);
2705 reg1->config = event->attr.config1;
2706 reg_idx++;
2707 }
2708 /*
2709 * The mbox only provides ability to perform address matching
2710 * for the PLD events.
2711 */
2712 if (reg_idx == 2) {
2713 reg2->idx = EXTRA_REG_NHMEX_M_FILTER;
2714 if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN)
2715 reg2->config = event->attr.config2;
2716 else
2717 reg2->config = ~0ULL;
2718 if (box->pmu->pmu_idx == 0)
2719 reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG;
2720 else
2721 reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG;
2722 }
2723 return 0;
2724}
2725
2726static u64 nhmex_mbox_shared_reg_config(struct intel_uncore_box *box, int idx)
2727{
2728 struct intel_uncore_extra_reg *er;
2729 unsigned long flags;
2730 u64 config;
2731
2732 if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC)
2733 return box->shared_regs[idx].config;
2734
2735 er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
2736 raw_spin_lock_irqsave(&er->lock, flags);
2737 config = er->config;
2738 raw_spin_unlock_irqrestore(&er->lock, flags);
2739 return config;
2740}
2741
2742static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
2743{
2744 struct hw_perf_event *hwc = &event->hw;
2745 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
2746 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
2747 int idx;
2748
2749 idx = __BITS_VALUE(reg1->idx, 0, 8);
2750 if (idx != 0xff)
2751 wrmsrl(__BITS_VALUE(reg1->reg, 0, 16),
2752 nhmex_mbox_shared_reg_config(box, idx));
2753 idx = __BITS_VALUE(reg1->idx, 1, 8);
2754 if (idx != 0xff)
2755 wrmsrl(__BITS_VALUE(reg1->reg, 1, 16),
2756 nhmex_mbox_shared_reg_config(box, idx));
2757
2758 if (reg2->idx != EXTRA_REG_NONE) {
2759 wrmsrl(reg2->reg, 0);
2760 if (reg2->config != ~0ULL) {
2761 wrmsrl(reg2->reg + 1,
2762 reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK);
2763 wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK &
2764 (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT));
2765 wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN);
2766 }
2767 }
2768
2769 wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);
2770}
2771
2772DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3");
2773DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5");
2774DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6");
2775DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7");
2776DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13");
2777DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21");
2778DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en, filter_cfg_en, "config2:63");
2779DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33");
2780DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61");
2781DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31");
2782DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31");
2783DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31");
2784DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31");
2785DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31");
2786DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31");
2787DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63");
2788
2789static struct attribute *nhmex_uncore_mbox_formats_attr[] = {
2790 &format_attr_count_mode.attr,
2791 &format_attr_storage_mode.attr,
2792 &format_attr_wrap_mode.attr,
2793 &format_attr_flag_mode.attr,
2794 &format_attr_inc_sel.attr,
2795 &format_attr_set_flag_sel.attr,
2796 &format_attr_filter_cfg_en.attr,
2797 &format_attr_filter_match.attr,
2798 &format_attr_filter_mask.attr,
2799 &format_attr_dsp.attr,
2800 &format_attr_thr.attr,
2801 &format_attr_fvc.attr,
2802 &format_attr_pgt.attr,
2803 &format_attr_map.attr,
2804 &format_attr_iss.attr,
2805 &format_attr_pld.attr,
2806 NULL,
2807};
2808
2809static struct attribute_group nhmex_uncore_mbox_format_group = {
2810 .name = "format",
2811 .attrs = nhmex_uncore_mbox_formats_attr,
2812};
2813
2814static struct uncore_event_desc nhmex_uncore_mbox_events[] = {
2815 INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x2800"),
2816 INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x2820"),
2817 { /* end: all zeroes */ },
2818};
2819
2820static struct uncore_event_desc wsmex_uncore_mbox_events[] = {
2821 INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"),
2822 INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"),
2823 { /* end: all zeroes */ },
2824};
2825
2826static struct intel_uncore_ops nhmex_uncore_mbox_ops = {
2827 NHMEX_UNCORE_OPS_COMMON_INIT(),
2828 .enable_event = nhmex_mbox_msr_enable_event,
2829 .hw_config = nhmex_mbox_hw_config,
2830 .get_constraint = nhmex_mbox_get_constraint,
2831 .put_constraint = nhmex_mbox_put_constraint,
2832};
2833
2834static struct intel_uncore_type nhmex_uncore_mbox = {
2835 .name = "mbox",
2836 .num_counters = 6,
2837 .num_boxes = 2,
2838 .perf_ctr_bits = 48,
2839 .event_ctl = NHMEX_M0_MSR_PMU_CTL0,
2840 .perf_ctr = NHMEX_M0_MSR_PMU_CNT0,
2841 .event_mask = NHMEX_M_PMON_RAW_EVENT_MASK,
2842 .box_ctl = NHMEX_M0_MSR_GLOBAL_CTL,
2843 .msr_offset = NHMEX_M_MSR_OFFSET,
2844 .pair_ctr_ctl = 1,
2845 .num_shared_regs = 8,
2846 .event_descs = nhmex_uncore_mbox_events,
2847 .ops = &nhmex_uncore_mbox_ops,
2848 .format_group = &nhmex_uncore_mbox_format_group,
2849};
2850
2851static void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
2852{
2853 struct hw_perf_event *hwc = &event->hw;
2854 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
2855
2856 /* adjust the main event selector and extra register index */
2857 if (reg1->idx % 2) {
2858 reg1->idx--;
2859 hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
2860 } else {
2861 reg1->idx++;
2862 hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
2863 }
2864
2865 /* adjust extra register config */
2866 switch (reg1->idx % 6) {
2867 case 2:
2868 /* shift the 8~15 bits to the 0~7 bits */
2869 reg1->config >>= 8;
2870 break;
2871 case 3:
2872 /* shift the 0~7 bits to the 8~15 bits */
2873 reg1->config <<= 8;
2874 break;
2875 };
2876}
2877
2878/*
2879 * Each rbox has 4 event set which monitor PQI port 0~3 or 4~7.
2880 * An event set consists of 6 events, the 3rd and 4th events in
2881 * an event set use the same extra register. So an event set uses
2882 * 5 extra registers.
2883 */
2884static struct event_constraint *
2885nhmex_rbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
2886{
2887 struct hw_perf_event *hwc = &event->hw;
2888 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
2889 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
2890 struct intel_uncore_extra_reg *er;
2891 unsigned long flags;
2892 int idx, er_idx;
2893 u64 config1;
2894 bool ok = false;
2895
2896 if (!uncore_box_is_fake(box) && reg1->alloc)
2897 return NULL;
2898
2899 idx = reg1->idx % 6;
2900 config1 = reg1->config;
2901again:
2902 er_idx = idx;
2903 /* the 3rd and 4th events use the same extra register */
2904 if (er_idx > 2)
2905 er_idx--;
2906 er_idx += (reg1->idx / 6) * 5;
2907
2908 er = &box->shared_regs[er_idx];
2909 raw_spin_lock_irqsave(&er->lock, flags);
2910 if (idx < 2) {
2911 if (!atomic_read(&er->ref) || er->config == reg1->config) {
2912 atomic_inc(&er->ref);
2913 er->config = reg1->config;
2914 ok = true;
2915 }
2916 } else if (idx == 2 || idx == 3) {
2917 /*
2918 * these two events use different fields in a extra register,
2919 * the 0~7 bits and the 8~15 bits respectively.
2920 */
2921 u64 mask = 0xff << ((idx - 2) * 8);
2922 if (!__BITS_VALUE(atomic_read(&er->ref), idx - 2, 8) ||
2923 !((er->config ^ config1) & mask)) {
2924 atomic_add(1 << ((idx - 2) * 8), &er->ref);
2925 er->config &= ~mask;
2926 er->config |= config1 & mask;
2927 ok = true;
2928 }
2929 } else {
2930 if (!atomic_read(&er->ref) ||
2931 (er->config == (hwc->config >> 32) &&
2932 er->config1 == reg1->config &&
2933 er->config2 == reg2->config)) {
2934 atomic_inc(&er->ref);
2935 er->config = (hwc->config >> 32);
2936 er->config1 = reg1->config;
2937 er->config2 = reg2->config;
2938 ok = true;
2939 }
2940 }
2941 raw_spin_unlock_irqrestore(&er->lock, flags);
2942
2943 if (!ok) {
2944 /*
2945 * The Rbox events are always in pairs. The paired
2946 * events are functional identical, but use different
2947 * extra registers. If we failed to take an extra
2948 * register, try the alternative.
2949 */
2950 idx ^= 1;
2951 if (idx != reg1->idx % 6) {
2952 if (idx == 2)
2953 config1 >>= 8;
2954 else if (idx == 3)
2955 config1 <<= 8;
2956 goto again;
2957 }
2958 } else {
2959 if (!uncore_box_is_fake(box)) {
2960 if (idx != reg1->idx % 6)
2961 nhmex_rbox_alter_er(box, event);
2962 reg1->alloc = 1;
2963 }
2964 return NULL;
2965 }
2966 return &constraint_empty;
2967}
2968
2969static void nhmex_rbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
2970{
2971 struct intel_uncore_extra_reg *er;
2972 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
2973 int idx, er_idx;
2974
2975 if (uncore_box_is_fake(box) || !reg1->alloc)
2976 return;
2977
2978 idx = reg1->idx % 6;
2979 er_idx = idx;
2980 if (er_idx > 2)
2981 er_idx--;
2982 er_idx += (reg1->idx / 6) * 5;
2983
2984 er = &box->shared_regs[er_idx];
2985 if (idx == 2 || idx == 3)
2986 atomic_sub(1 << ((idx - 2) * 8), &er->ref);
2987 else
2988 atomic_dec(&er->ref);
2989
2990 reg1->alloc = 0;
2991}
2992
2993static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
2994{
2995 struct hw_perf_event *hwc = &event->hw;
2996 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
2997 struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
2998 int idx;
2999
3000 idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >>
3001 NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
3002 if (idx >= 0x18)
3003 return -EINVAL;
3004
3005 reg1->idx = idx;
3006 reg1->config = event->attr.config1;
3007
3008 switch (idx % 6) {
3009 case 4:
3010 case 5:
3011 hwc->config |= event->attr.config & (~0ULL << 32);
3012 reg2->config = event->attr.config2;
3013 break;
3014 };
3015 return 0;
3016}
3017
3018static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
3019{
3020 struct hw_perf_event *hwc = &event->hw;
3021 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
3022 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
3023 int idx, port;
3024
3025 idx = reg1->idx;
3026 port = idx / 6 + box->pmu->pmu_idx * 4;
3027
3028 switch (idx % 6) {
3029 case 0:
3030 wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config);
3031 break;
3032 case 1:
3033 wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config);
3034 break;
3035 case 2:
3036 case 3:
3037 wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port),
3038 uncore_shared_reg_config(box, 2 + (idx / 6) * 5));
3039 break;
3040 case 4:
3041 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port),
3042 hwc->config >> 32);
3043 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config);
3044 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config);
3045 break;
3046 case 5:
3047 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port),
3048 hwc->config >> 32);
3049 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config);
3050 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config);
3051 break;
3052 };
3053
3054 wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0 |
3055 (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK));
3056}
3057
3058DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63");
3059DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63");
3060DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63");
3061DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15");
3062DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31");
3063
3064static struct attribute *nhmex_uncore_rbox_formats_attr[] = {
3065 &format_attr_event5.attr,
3066 &format_attr_xbr_mm_cfg.attr,
3067 &format_attr_xbr_match.attr,
3068 &format_attr_xbr_mask.attr,
3069 &format_attr_qlx_cfg.attr,
3070 &format_attr_iperf_cfg.attr,
3071 NULL,
3072};
3073
3074static struct attribute_group nhmex_uncore_rbox_format_group = {
3075 .name = "format",
3076 .attrs = nhmex_uncore_rbox_formats_attr,
3077};
3078
3079static struct uncore_event_desc nhmex_uncore_rbox_events[] = {
3080 INTEL_UNCORE_EVENT_DESC(qpi0_flit_send, "event=0x0,iperf_cfg=0x80000000"),
3081 INTEL_UNCORE_EVENT_DESC(qpi1_filt_send, "event=0x6,iperf_cfg=0x80000000"),
3082 INTEL_UNCORE_EVENT_DESC(qpi0_idle_filt, "event=0x0,iperf_cfg=0x40000000"),
3083 INTEL_UNCORE_EVENT_DESC(qpi1_idle_filt, "event=0x6,iperf_cfg=0x40000000"),
3084 INTEL_UNCORE_EVENT_DESC(qpi0_date_response, "event=0x0,iperf_cfg=0xc4"),
3085 INTEL_UNCORE_EVENT_DESC(qpi1_date_response, "event=0x6,iperf_cfg=0xc4"),
3086 { /* end: all zeroes */ },
3087};
3088
3089static struct intel_uncore_ops nhmex_uncore_rbox_ops = {
3090 NHMEX_UNCORE_OPS_COMMON_INIT(),
3091 .enable_event = nhmex_rbox_msr_enable_event,
3092 .hw_config = nhmex_rbox_hw_config,
3093 .get_constraint = nhmex_rbox_get_constraint,
3094 .put_constraint = nhmex_rbox_put_constraint,
3095};
3096
3097static struct intel_uncore_type nhmex_uncore_rbox = {
3098 .name = "rbox",
3099 .num_counters = 8,
3100 .num_boxes = 2,
3101 .perf_ctr_bits = 48,
3102 .event_ctl = NHMEX_R_MSR_PMON_CTL0,
3103 .perf_ctr = NHMEX_R_MSR_PMON_CNT0,
3104 .event_mask = NHMEX_R_PMON_RAW_EVENT_MASK,
3105 .box_ctl = NHMEX_R_MSR_GLOBAL_CTL,
3106 .msr_offset = NHMEX_R_MSR_OFFSET,
3107 .pair_ctr_ctl = 1,
3108 .num_shared_regs = 20,
3109 .event_descs = nhmex_uncore_rbox_events,
3110 .ops = &nhmex_uncore_rbox_ops,
3111 .format_group = &nhmex_uncore_rbox_format_group
3112};
3113
3114static struct intel_uncore_type *nhmex_msr_uncores[] = {
3115 &nhmex_uncore_ubox,
3116 &nhmex_uncore_cbox,
3117 &nhmex_uncore_bbox,
3118 &nhmex_uncore_sbox,
3119 &nhmex_uncore_mbox,
3120 &nhmex_uncore_rbox,
3121 &nhmex_uncore_wbox,
3122 NULL,
3123};
3124/* end of Nehalem-EX uncore support */
3125
3126static void uncore_assign_hw_event(struct intel_uncore_box *box, struct perf_event *event, int idx) 156static void uncore_assign_hw_event(struct intel_uncore_box *box, struct perf_event *event, int idx)
3127{ 157{
3128 struct hw_perf_event *hwc = &event->hw; 158 struct hw_perf_event *hwc = &event->hw;
@@ -3140,7 +170,7 @@ static void uncore_assign_hw_event(struct intel_uncore_box *box, struct perf_eve
3140 hwc->event_base = uncore_perf_ctr(box, hwc->idx); 170 hwc->event_base = uncore_perf_ctr(box, hwc->idx);
3141} 171}
3142 172
3143static void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event) 173void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event)
3144{ 174{
3145 u64 prev_count, new_count, delta; 175 u64 prev_count, new_count, delta;
3146 int shift; 176 int shift;
@@ -3201,14 +231,14 @@ static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
3201 return HRTIMER_RESTART; 231 return HRTIMER_RESTART;
3202} 232}
3203 233
3204static void uncore_pmu_start_hrtimer(struct intel_uncore_box *box) 234void uncore_pmu_start_hrtimer(struct intel_uncore_box *box)
3205{ 235{
3206 __hrtimer_start_range_ns(&box->hrtimer, 236 __hrtimer_start_range_ns(&box->hrtimer,
3207 ns_to_ktime(box->hrtimer_duration), 0, 237 ns_to_ktime(box->hrtimer_duration), 0,
3208 HRTIMER_MODE_REL_PINNED, 0); 238 HRTIMER_MODE_REL_PINNED, 0);
3209} 239}
3210 240
3211static void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box) 241void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box)
3212{ 242{
3213 hrtimer_cancel(&box->hrtimer); 243 hrtimer_cancel(&box->hrtimer);
3214} 244}
@@ -3291,7 +321,7 @@ uncore_get_event_constraint(struct intel_uncore_box *box, struct perf_event *eve
3291 } 321 }
3292 322
3293 if (event->attr.config == UNCORE_FIXED_EVENT) 323 if (event->attr.config == UNCORE_FIXED_EVENT)
3294 return &constraint_fixed; 324 return &uncore_constraint_fixed;
3295 325
3296 if (type->constraints) { 326 if (type->constraints) {
3297 for_each_event_constraint(c, type->constraints) { 327 for_each_event_constraint(c, type->constraints) {
@@ -3496,7 +526,7 @@ static void uncore_pmu_event_del(struct perf_event *event, int flags)
3496 event->hw.last_tag = ~0ULL; 526 event->hw.last_tag = ~0ULL;
3497} 527}
3498 528
3499static void uncore_pmu_event_read(struct perf_event *event) 529void uncore_pmu_event_read(struct perf_event *event)
3500{ 530{
3501 struct intel_uncore_box *box = uncore_event_to_box(event); 531 struct intel_uncore_box *box = uncore_event_to_box(event);
3502 uncore_perf_event_update(box, event); 532 uncore_perf_event_update(box, event);
@@ -3635,7 +665,7 @@ static struct attribute_group uncore_pmu_attr_group = {
3635 .attrs = uncore_pmu_attrs, 665 .attrs = uncore_pmu_attrs,
3636}; 666};
3637 667
3638static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu) 668static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
3639{ 669{
3640 int ret; 670 int ret;
3641 671
@@ -3758,9 +788,6 @@ fail:
3758 return ret; 788 return ret;
3759} 789}
3760 790
3761static struct pci_driver *uncore_pci_driver;
3762static bool pcidrv_registered;
3763
3764/* 791/*
3765 * add a pci uncore device 792 * add a pci uncore device
3766 */ 793 */
@@ -3770,18 +797,20 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
3770 struct intel_uncore_box *box; 797 struct intel_uncore_box *box;
3771 struct intel_uncore_type *type; 798 struct intel_uncore_type *type;
3772 int phys_id; 799 int phys_id;
800 bool first_box = false;
3773 801
3774 phys_id = pcibus_to_physid[pdev->bus->number]; 802 phys_id = uncore_pcibus_to_physid[pdev->bus->number];
3775 if (phys_id < 0) 803 if (phys_id < 0)
3776 return -ENODEV; 804 return -ENODEV;
3777 805
3778 if (UNCORE_PCI_DEV_TYPE(id->driver_data) == UNCORE_EXTRA_PCI_DEV) { 806 if (UNCORE_PCI_DEV_TYPE(id->driver_data) == UNCORE_EXTRA_PCI_DEV) {
3779 extra_pci_dev[phys_id][UNCORE_PCI_DEV_IDX(id->driver_data)] = pdev; 807 int idx = UNCORE_PCI_DEV_IDX(id->driver_data);
808 uncore_extra_pci_dev[phys_id][idx] = pdev;
3780 pci_set_drvdata(pdev, NULL); 809 pci_set_drvdata(pdev, NULL);
3781 return 0; 810 return 0;
3782 } 811 }
3783 812
3784 type = pci_uncores[UNCORE_PCI_DEV_TYPE(id->driver_data)]; 813 type = uncore_pci_uncores[UNCORE_PCI_DEV_TYPE(id->driver_data)];
3785 box = uncore_alloc_box(type, NUMA_NO_NODE); 814 box = uncore_alloc_box(type, NUMA_NO_NODE);
3786 if (!box) 815 if (!box)
3787 return -ENOMEM; 816 return -ENOMEM;
@@ -3803,9 +832,13 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
3803 pci_set_drvdata(pdev, box); 832 pci_set_drvdata(pdev, box);
3804 833
3805 raw_spin_lock(&uncore_box_lock); 834 raw_spin_lock(&uncore_box_lock);
835 if (list_empty(&pmu->box_list))
836 first_box = true;
3806 list_add_tail(&box->list, &pmu->box_list); 837 list_add_tail(&box->list, &pmu->box_list);
3807 raw_spin_unlock(&uncore_box_lock); 838 raw_spin_unlock(&uncore_box_lock);
3808 839
840 if (first_box)
841 uncore_pmu_register(pmu);
3809 return 0; 842 return 0;
3810} 843}
3811 844
@@ -3813,13 +846,14 @@ static void uncore_pci_remove(struct pci_dev *pdev)
3813{ 846{
3814 struct intel_uncore_box *box = pci_get_drvdata(pdev); 847 struct intel_uncore_box *box = pci_get_drvdata(pdev);
3815 struct intel_uncore_pmu *pmu; 848 struct intel_uncore_pmu *pmu;
3816 int i, cpu, phys_id = pcibus_to_physid[pdev->bus->number]; 849 int i, cpu, phys_id = uncore_pcibus_to_physid[pdev->bus->number];
850 bool last_box = false;
3817 851
3818 box = pci_get_drvdata(pdev); 852 box = pci_get_drvdata(pdev);
3819 if (!box) { 853 if (!box) {
3820 for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) { 854 for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) {
3821 if (extra_pci_dev[phys_id][i] == pdev) { 855 if (uncore_extra_pci_dev[phys_id][i] == pdev) {
3822 extra_pci_dev[phys_id][i] = NULL; 856 uncore_extra_pci_dev[phys_id][i] = NULL;
3823 break; 857 break;
3824 } 858 }
3825 } 859 }
@@ -3835,6 +869,8 @@ static void uncore_pci_remove(struct pci_dev *pdev)
3835 869
3836 raw_spin_lock(&uncore_box_lock); 870 raw_spin_lock(&uncore_box_lock);
3837 list_del(&box->list); 871 list_del(&box->list);
872 if (list_empty(&pmu->box_list))
873 last_box = true;
3838 raw_spin_unlock(&uncore_box_lock); 874 raw_spin_unlock(&uncore_box_lock);
3839 875
3840 for_each_possible_cpu(cpu) { 876 for_each_possible_cpu(cpu) {
@@ -3846,6 +882,9 @@ static void uncore_pci_remove(struct pci_dev *pdev)
3846 882
3847 WARN_ON_ONCE(atomic_read(&box->refcnt) != 1); 883 WARN_ON_ONCE(atomic_read(&box->refcnt) != 1);
3848 kfree(box); 884 kfree(box);
885
886 if (last_box)
887 perf_pmu_unregister(&pmu->pmu);
3849} 888}
3850 889
3851static int __init uncore_pci_init(void) 890static int __init uncore_pci_init(void)
@@ -3854,46 +893,32 @@ static int __init uncore_pci_init(void)
3854 893
3855 switch (boot_cpu_data.x86_model) { 894 switch (boot_cpu_data.x86_model) {
3856 case 45: /* Sandy Bridge-EP */ 895 case 45: /* Sandy Bridge-EP */
3857 ret = snbep_pci2phy_map_init(0x3ce0); 896 ret = snbep_uncore_pci_init();
3858 if (ret)
3859 return ret;
3860 pci_uncores = snbep_pci_uncores;
3861 uncore_pci_driver = &snbep_uncore_pci_driver;
3862 break; 897 break;
3863 case 62: /* IvyTown */ 898 case 62: /* Ivy Bridge-EP */
3864 ret = snbep_pci2phy_map_init(0x0e1e); 899 ret = ivbep_uncore_pci_init();
3865 if (ret) 900 break;
3866 return ret; 901 case 63: /* Haswell-EP */
3867 pci_uncores = ivt_pci_uncores; 902 ret = hswep_uncore_pci_init();
3868 uncore_pci_driver = &ivt_uncore_pci_driver;
3869 break; 903 break;
3870 case 42: /* Sandy Bridge */ 904 case 42: /* Sandy Bridge */
3871 ret = snb_pci2phy_map_init(PCI_DEVICE_ID_INTEL_SNB_IMC); 905 ret = snb_uncore_pci_init();
3872 if (ret)
3873 return ret;
3874 pci_uncores = snb_pci_uncores;
3875 uncore_pci_driver = &snb_uncore_pci_driver;
3876 break; 906 break;
3877 case 58: /* Ivy Bridge */ 907 case 58: /* Ivy Bridge */
3878 ret = snb_pci2phy_map_init(PCI_DEVICE_ID_INTEL_IVB_IMC); 908 ret = ivb_uncore_pci_init();
3879 if (ret)
3880 return ret;
3881 pci_uncores = snb_pci_uncores;
3882 uncore_pci_driver = &ivb_uncore_pci_driver;
3883 break; 909 break;
3884 case 60: /* Haswell */ 910 case 60: /* Haswell */
3885 case 69: /* Haswell Celeron */ 911 case 69: /* Haswell Celeron */
3886 ret = snb_pci2phy_map_init(PCI_DEVICE_ID_INTEL_HSW_IMC); 912 ret = hsw_uncore_pci_init();
3887 if (ret)
3888 return ret;
3889 pci_uncores = snb_pci_uncores;
3890 uncore_pci_driver = &hsw_uncore_pci_driver;
3891 break; 913 break;
3892 default: 914 default:
3893 return 0; 915 return 0;
3894 } 916 }
3895 917
3896 ret = uncore_types_init(pci_uncores); 918 if (ret)
919 return ret;
920
921 ret = uncore_types_init(uncore_pci_uncores);
3897 if (ret) 922 if (ret)
3898 return ret; 923 return ret;
3899 924
@@ -3904,7 +929,7 @@ static int __init uncore_pci_init(void)
3904 if (ret == 0) 929 if (ret == 0)
3905 pcidrv_registered = true; 930 pcidrv_registered = true;
3906 else 931 else
3907 uncore_types_exit(pci_uncores); 932 uncore_types_exit(uncore_pci_uncores);
3908 933
3909 return ret; 934 return ret;
3910} 935}
@@ -3914,7 +939,7 @@ static void __init uncore_pci_exit(void)
3914 if (pcidrv_registered) { 939 if (pcidrv_registered) {
3915 pcidrv_registered = false; 940 pcidrv_registered = false;
3916 pci_unregister_driver(uncore_pci_driver); 941 pci_unregister_driver(uncore_pci_driver);
3917 uncore_types_exit(pci_uncores); 942 uncore_types_exit(uncore_pci_uncores);
3918 } 943 }
3919} 944}
3920 945
@@ -3940,8 +965,8 @@ static void uncore_cpu_dying(int cpu)
3940 struct intel_uncore_box *box; 965 struct intel_uncore_box *box;
3941 int i, j; 966 int i, j;
3942 967
3943 for (i = 0; msr_uncores[i]; i++) { 968 for (i = 0; uncore_msr_uncores[i]; i++) {
3944 type = msr_uncores[i]; 969 type = uncore_msr_uncores[i];
3945 for (j = 0; j < type->num_boxes; j++) { 970 for (j = 0; j < type->num_boxes; j++) {
3946 pmu = &type->pmus[j]; 971 pmu = &type->pmus[j];
3947 box = *per_cpu_ptr(pmu->box, cpu); 972 box = *per_cpu_ptr(pmu->box, cpu);
@@ -3961,8 +986,8 @@ static int uncore_cpu_starting(int cpu)
3961 986
3962 phys_id = topology_physical_package_id(cpu); 987 phys_id = topology_physical_package_id(cpu);
3963 988
3964 for (i = 0; msr_uncores[i]; i++) { 989 for (i = 0; uncore_msr_uncores[i]; i++) {
3965 type = msr_uncores[i]; 990 type = uncore_msr_uncores[i];
3966 for (j = 0; j < type->num_boxes; j++) { 991 for (j = 0; j < type->num_boxes; j++) {
3967 pmu = &type->pmus[j]; 992 pmu = &type->pmus[j];
3968 box = *per_cpu_ptr(pmu->box, cpu); 993 box = *per_cpu_ptr(pmu->box, cpu);
@@ -4002,8 +1027,8 @@ static int uncore_cpu_prepare(int cpu, int phys_id)
4002 struct intel_uncore_box *box; 1027 struct intel_uncore_box *box;
4003 int i, j; 1028 int i, j;
4004 1029
4005 for (i = 0; msr_uncores[i]; i++) { 1030 for (i = 0; uncore_msr_uncores[i]; i++) {
4006 type = msr_uncores[i]; 1031 type = uncore_msr_uncores[i];
4007 for (j = 0; j < type->num_boxes; j++) { 1032 for (j = 0; j < type->num_boxes; j++) {
4008 pmu = &type->pmus[j]; 1033 pmu = &type->pmus[j];
4009 if (pmu->func_id < 0) 1034 if (pmu->func_id < 0)
@@ -4083,8 +1108,8 @@ static void uncore_event_exit_cpu(int cpu)
4083 if (target >= 0) 1108 if (target >= 0)
4084 cpumask_set_cpu(target, &uncore_cpu_mask); 1109 cpumask_set_cpu(target, &uncore_cpu_mask);
4085 1110
4086 uncore_change_context(msr_uncores, cpu, target); 1111 uncore_change_context(uncore_msr_uncores, cpu, target);
4087 uncore_change_context(pci_uncores, cpu, target); 1112 uncore_change_context(uncore_pci_uncores, cpu, target);
4088} 1113}
4089 1114
4090static void uncore_event_init_cpu(int cpu) 1115static void uncore_event_init_cpu(int cpu)
@@ -4099,8 +1124,8 @@ static void uncore_event_init_cpu(int cpu)
4099 1124
4100 cpumask_set_cpu(cpu, &uncore_cpu_mask); 1125 cpumask_set_cpu(cpu, &uncore_cpu_mask);
4101 1126
4102 uncore_change_context(msr_uncores, -1, cpu); 1127 uncore_change_context(uncore_msr_uncores, -1, cpu);
4103 uncore_change_context(pci_uncores, -1, cpu); 1128 uncore_change_context(uncore_pci_uncores, -1, cpu);
4104} 1129}
4105 1130
4106static int uncore_cpu_notifier(struct notifier_block *self, 1131static int uncore_cpu_notifier(struct notifier_block *self,
@@ -4160,47 +1185,37 @@ static void __init uncore_cpu_setup(void *dummy)
4160 1185
4161static int __init uncore_cpu_init(void) 1186static int __init uncore_cpu_init(void)
4162{ 1187{
4163 int ret, max_cores; 1188 int ret;
4164 1189
4165 max_cores = boot_cpu_data.x86_max_cores;
4166 switch (boot_cpu_data.x86_model) { 1190 switch (boot_cpu_data.x86_model) {
4167 case 26: /* Nehalem */ 1191 case 26: /* Nehalem */
4168 case 30: 1192 case 30:
4169 case 37: /* Westmere */ 1193 case 37: /* Westmere */
4170 case 44: 1194 case 44:
4171 msr_uncores = nhm_msr_uncores; 1195 nhm_uncore_cpu_init();
4172 break; 1196 break;
4173 case 42: /* Sandy Bridge */ 1197 case 42: /* Sandy Bridge */
4174 case 58: /* Ivy Bridge */ 1198 case 58: /* Ivy Bridge */
4175 if (snb_uncore_cbox.num_boxes > max_cores) 1199 snb_uncore_cpu_init();
4176 snb_uncore_cbox.num_boxes = max_cores;
4177 msr_uncores = snb_msr_uncores;
4178 break; 1200 break;
4179 case 45: /* Sandy Bridge-EP */ 1201 case 45: /* Sandy Bridge-EP */
4180 if (snbep_uncore_cbox.num_boxes > max_cores) 1202 snbep_uncore_cpu_init();
4181 snbep_uncore_cbox.num_boxes = max_cores;
4182 msr_uncores = snbep_msr_uncores;
4183 break; 1203 break;
4184 case 46: /* Nehalem-EX */ 1204 case 46: /* Nehalem-EX */
4185 uncore_nhmex = true;
4186 case 47: /* Westmere-EX aka. Xeon E7 */ 1205 case 47: /* Westmere-EX aka. Xeon E7 */
4187 if (!uncore_nhmex) 1206 nhmex_uncore_cpu_init();
4188 nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events;
4189 if (nhmex_uncore_cbox.num_boxes > max_cores)
4190 nhmex_uncore_cbox.num_boxes = max_cores;
4191 msr_uncores = nhmex_msr_uncores;
4192 break; 1207 break;
4193 case 62: /* IvyTown */ 1208 case 62: /* Ivy Bridge-EP */
4194 if (ivt_uncore_cbox.num_boxes > max_cores) 1209 ivbep_uncore_cpu_init();
4195 ivt_uncore_cbox.num_boxes = max_cores; 1210 break;
4196 msr_uncores = ivt_msr_uncores; 1211 case 63: /* Haswell-EP */
1212 hswep_uncore_cpu_init();
4197 break; 1213 break;
4198
4199 default: 1214 default:
4200 return 0; 1215 return 0;
4201 } 1216 }
4202 1217
4203 ret = uncore_types_init(msr_uncores); 1218 ret = uncore_types_init(uncore_msr_uncores);
4204 if (ret) 1219 if (ret)
4205 return ret; 1220 return ret;
4206 1221
@@ -4213,16 +1228,8 @@ static int __init uncore_pmus_register(void)
4213 struct intel_uncore_type *type; 1228 struct intel_uncore_type *type;
4214 int i, j; 1229 int i, j;
4215 1230
4216 for (i = 0; msr_uncores[i]; i++) { 1231 for (i = 0; uncore_msr_uncores[i]; i++) {
4217 type = msr_uncores[i]; 1232 type = uncore_msr_uncores[i];
4218 for (j = 0; j < type->num_boxes; j++) {
4219 pmu = &type->pmus[j];
4220 uncore_pmu_register(pmu);
4221 }
4222 }
4223
4224 for (i = 0; pci_uncores[i]; i++) {
4225 type = pci_uncores[i];
4226 for (j = 0; j < type->num_boxes; j++) { 1233 for (j = 0; j < type->num_boxes; j++) {
4227 pmu = &type->pmus[j]; 1234 pmu = &type->pmus[j];
4228 uncore_pmu_register(pmu); 1235 uncore_pmu_register(pmu);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
index 90236f0c94a9..18eb78bbdd10 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
@@ -24,395 +24,6 @@
24 24
25#define UNCORE_EVENT_CONSTRAINT(c, n) EVENT_CONSTRAINT(c, n, 0xff) 25#define UNCORE_EVENT_CONSTRAINT(c, n) EVENT_CONSTRAINT(c, n, 0xff)
26 26
27/* SNB event control */
28#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff
29#define SNB_UNC_CTL_UMASK_MASK 0x0000ff00
30#define SNB_UNC_CTL_EDGE_DET (1 << 18)
31#define SNB_UNC_CTL_EN (1 << 22)
32#define SNB_UNC_CTL_INVERT (1 << 23)
33#define SNB_UNC_CTL_CMASK_MASK 0x1f000000
34#define NHM_UNC_CTL_CMASK_MASK 0xff000000
35#define NHM_UNC_FIXED_CTR_CTL_EN (1 << 0)
36
37#define SNB_UNC_RAW_EVENT_MASK (SNB_UNC_CTL_EV_SEL_MASK | \
38 SNB_UNC_CTL_UMASK_MASK | \
39 SNB_UNC_CTL_EDGE_DET | \
40 SNB_UNC_CTL_INVERT | \
41 SNB_UNC_CTL_CMASK_MASK)
42
43#define NHM_UNC_RAW_EVENT_MASK (SNB_UNC_CTL_EV_SEL_MASK | \
44 SNB_UNC_CTL_UMASK_MASK | \
45 SNB_UNC_CTL_EDGE_DET | \
46 SNB_UNC_CTL_INVERT | \
47 NHM_UNC_CTL_CMASK_MASK)
48
49/* SNB global control register */
50#define SNB_UNC_PERF_GLOBAL_CTL 0x391
51#define SNB_UNC_FIXED_CTR_CTRL 0x394
52#define SNB_UNC_FIXED_CTR 0x395
53
54/* SNB uncore global control */
55#define SNB_UNC_GLOBAL_CTL_CORE_ALL ((1 << 4) - 1)
56#define SNB_UNC_GLOBAL_CTL_EN (1 << 29)
57
58/* SNB Cbo register */
59#define SNB_UNC_CBO_0_PERFEVTSEL0 0x700
60#define SNB_UNC_CBO_0_PER_CTR0 0x706
61#define SNB_UNC_CBO_MSR_OFFSET 0x10
62
63/* NHM global control register */
64#define NHM_UNC_PERF_GLOBAL_CTL 0x391
65#define NHM_UNC_FIXED_CTR 0x394
66#define NHM_UNC_FIXED_CTR_CTRL 0x395
67
68/* NHM uncore global control */
69#define NHM_UNC_GLOBAL_CTL_EN_PC_ALL ((1ULL << 8) - 1)
70#define NHM_UNC_GLOBAL_CTL_EN_FC (1ULL << 32)
71
72/* NHM uncore register */
73#define NHM_UNC_PERFEVTSEL0 0x3c0
74#define NHM_UNC_UNCORE_PMC0 0x3b0
75
76/* SNB-EP Box level control */
77#define SNBEP_PMON_BOX_CTL_RST_CTRL (1 << 0)
78#define SNBEP_PMON_BOX_CTL_RST_CTRS (1 << 1)
79#define SNBEP_PMON_BOX_CTL_FRZ (1 << 8)
80#define SNBEP_PMON_BOX_CTL_FRZ_EN (1 << 16)
81#define SNBEP_PMON_BOX_CTL_INT (SNBEP_PMON_BOX_CTL_RST_CTRL | \
82 SNBEP_PMON_BOX_CTL_RST_CTRS | \
83 SNBEP_PMON_BOX_CTL_FRZ_EN)
84/* SNB-EP event control */
85#define SNBEP_PMON_CTL_EV_SEL_MASK 0x000000ff
86#define SNBEP_PMON_CTL_UMASK_MASK 0x0000ff00
87#define SNBEP_PMON_CTL_RST (1 << 17)
88#define SNBEP_PMON_CTL_EDGE_DET (1 << 18)
89#define SNBEP_PMON_CTL_EV_SEL_EXT (1 << 21)
90#define SNBEP_PMON_CTL_EN (1 << 22)
91#define SNBEP_PMON_CTL_INVERT (1 << 23)
92#define SNBEP_PMON_CTL_TRESH_MASK 0xff000000
93#define SNBEP_PMON_RAW_EVENT_MASK (SNBEP_PMON_CTL_EV_SEL_MASK | \
94 SNBEP_PMON_CTL_UMASK_MASK | \
95 SNBEP_PMON_CTL_EDGE_DET | \
96 SNBEP_PMON_CTL_INVERT | \
97 SNBEP_PMON_CTL_TRESH_MASK)
98
99/* SNB-EP Ubox event control */
100#define SNBEP_U_MSR_PMON_CTL_TRESH_MASK 0x1f000000
101#define SNBEP_U_MSR_PMON_RAW_EVENT_MASK \
102 (SNBEP_PMON_CTL_EV_SEL_MASK | \
103 SNBEP_PMON_CTL_UMASK_MASK | \
104 SNBEP_PMON_CTL_EDGE_DET | \
105 SNBEP_PMON_CTL_INVERT | \
106 SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
107
108#define SNBEP_CBO_PMON_CTL_TID_EN (1 << 19)
109#define SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK (SNBEP_PMON_RAW_EVENT_MASK | \
110 SNBEP_CBO_PMON_CTL_TID_EN)
111
112/* SNB-EP PCU event control */
113#define SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK 0x0000c000
114#define SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK 0x1f000000
115#define SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT (1 << 30)
116#define SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET (1 << 31)
117#define SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK \
118 (SNBEP_PMON_CTL_EV_SEL_MASK | \
119 SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
120 SNBEP_PMON_CTL_EDGE_DET | \
121 SNBEP_PMON_CTL_EV_SEL_EXT | \
122 SNBEP_PMON_CTL_INVERT | \
123 SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
124 SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
125 SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
126
127#define SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK \
128 (SNBEP_PMON_RAW_EVENT_MASK | \
129 SNBEP_PMON_CTL_EV_SEL_EXT)
130
131/* SNB-EP pci control register */
132#define SNBEP_PCI_PMON_BOX_CTL 0xf4
133#define SNBEP_PCI_PMON_CTL0 0xd8
134/* SNB-EP pci counter register */
135#define SNBEP_PCI_PMON_CTR0 0xa0
136
137/* SNB-EP home agent register */
138#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH0 0x40
139#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH1 0x44
140#define SNBEP_HA_PCI_PMON_BOX_OPCODEMATCH 0x48
141/* SNB-EP memory controller register */
142#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTL 0xf0
143#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTR 0xd0
144/* SNB-EP QPI register */
145#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH0 0x228
146#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH1 0x22c
147#define SNBEP_Q_Py_PCI_PMON_PKT_MASK0 0x238
148#define SNBEP_Q_Py_PCI_PMON_PKT_MASK1 0x23c
149
150/* SNB-EP Ubox register */
151#define SNBEP_U_MSR_PMON_CTR0 0xc16
152#define SNBEP_U_MSR_PMON_CTL0 0xc10
153
154#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTL 0xc08
155#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTR 0xc09
156
157/* SNB-EP Cbo register */
158#define SNBEP_C0_MSR_PMON_CTR0 0xd16
159#define SNBEP_C0_MSR_PMON_CTL0 0xd10
160#define SNBEP_C0_MSR_PMON_BOX_CTL 0xd04
161#define SNBEP_C0_MSR_PMON_BOX_FILTER 0xd14
162#define SNBEP_CBO_MSR_OFFSET 0x20
163
164#define SNBEP_CB0_MSR_PMON_BOX_FILTER_TID 0x1f
165#define SNBEP_CB0_MSR_PMON_BOX_FILTER_NID 0x3fc00
166#define SNBEP_CB0_MSR_PMON_BOX_FILTER_STATE 0x7c0000
167#define SNBEP_CB0_MSR_PMON_BOX_FILTER_OPC 0xff800000
168
169#define SNBEP_CBO_EVENT_EXTRA_REG(e, m, i) { \
170 .event = (e), \
171 .msr = SNBEP_C0_MSR_PMON_BOX_FILTER, \
172 .config_mask = (m), \
173 .idx = (i) \
174}
175
176/* SNB-EP PCU register */
177#define SNBEP_PCU_MSR_PMON_CTR0 0xc36
178#define SNBEP_PCU_MSR_PMON_CTL0 0xc30
179#define SNBEP_PCU_MSR_PMON_BOX_CTL 0xc24
180#define SNBEP_PCU_MSR_PMON_BOX_FILTER 0xc34
181#define SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK 0xffffffff
182#define SNBEP_PCU_MSR_CORE_C3_CTR 0x3fc
183#define SNBEP_PCU_MSR_CORE_C6_CTR 0x3fd
184
185/* IVT event control */
186#define IVT_PMON_BOX_CTL_INT (SNBEP_PMON_BOX_CTL_RST_CTRL | \
187 SNBEP_PMON_BOX_CTL_RST_CTRS)
188#define IVT_PMON_RAW_EVENT_MASK (SNBEP_PMON_CTL_EV_SEL_MASK | \
189 SNBEP_PMON_CTL_UMASK_MASK | \
190 SNBEP_PMON_CTL_EDGE_DET | \
191 SNBEP_PMON_CTL_TRESH_MASK)
192/* IVT Ubox */
193#define IVT_U_MSR_PMON_GLOBAL_CTL 0xc00
194#define IVT_U_PMON_GLOBAL_FRZ_ALL (1 << 31)
195#define IVT_U_PMON_GLOBAL_UNFRZ_ALL (1 << 29)
196
197#define IVT_U_MSR_PMON_RAW_EVENT_MASK \
198 (SNBEP_PMON_CTL_EV_SEL_MASK | \
199 SNBEP_PMON_CTL_UMASK_MASK | \
200 SNBEP_PMON_CTL_EDGE_DET | \
201 SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
202/* IVT Cbo */
203#define IVT_CBO_MSR_PMON_RAW_EVENT_MASK (IVT_PMON_RAW_EVENT_MASK | \
204 SNBEP_CBO_PMON_CTL_TID_EN)
205
206#define IVT_CB0_MSR_PMON_BOX_FILTER_TID (0x1fULL << 0)
207#define IVT_CB0_MSR_PMON_BOX_FILTER_LINK (0xfULL << 5)
208#define IVT_CB0_MSR_PMON_BOX_FILTER_STATE (0x3fULL << 17)
209#define IVT_CB0_MSR_PMON_BOX_FILTER_NID (0xffffULL << 32)
210#define IVT_CB0_MSR_PMON_BOX_FILTER_OPC (0x1ffULL << 52)
211#define IVT_CB0_MSR_PMON_BOX_FILTER_C6 (0x1ULL << 61)
212#define IVT_CB0_MSR_PMON_BOX_FILTER_NC (0x1ULL << 62)
213#define IVT_CB0_MSR_PMON_BOX_FILTER_IOSC (0x1ULL << 63)
214
215/* IVT home agent */
216#define IVT_HA_PCI_PMON_CTL_Q_OCC_RST (1 << 16)
217#define IVT_HA_PCI_PMON_RAW_EVENT_MASK \
218 (IVT_PMON_RAW_EVENT_MASK | \
219 IVT_HA_PCI_PMON_CTL_Q_OCC_RST)
220/* IVT PCU */
221#define IVT_PCU_MSR_PMON_RAW_EVENT_MASK \
222 (SNBEP_PMON_CTL_EV_SEL_MASK | \
223 SNBEP_PMON_CTL_EV_SEL_EXT | \
224 SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
225 SNBEP_PMON_CTL_EDGE_DET | \
226 SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
227 SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
228 SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
229/* IVT QPI */
230#define IVT_QPI_PCI_PMON_RAW_EVENT_MASK \
231 (IVT_PMON_RAW_EVENT_MASK | \
232 SNBEP_PMON_CTL_EV_SEL_EXT)
233
234/* NHM-EX event control */
235#define NHMEX_PMON_CTL_EV_SEL_MASK 0x000000ff
236#define NHMEX_PMON_CTL_UMASK_MASK 0x0000ff00
237#define NHMEX_PMON_CTL_EN_BIT0 (1 << 0)
238#define NHMEX_PMON_CTL_EDGE_DET (1 << 18)
239#define NHMEX_PMON_CTL_PMI_EN (1 << 20)
240#define NHMEX_PMON_CTL_EN_BIT22 (1 << 22)
241#define NHMEX_PMON_CTL_INVERT (1 << 23)
242#define NHMEX_PMON_CTL_TRESH_MASK 0xff000000
243#define NHMEX_PMON_RAW_EVENT_MASK (NHMEX_PMON_CTL_EV_SEL_MASK | \
244 NHMEX_PMON_CTL_UMASK_MASK | \
245 NHMEX_PMON_CTL_EDGE_DET | \
246 NHMEX_PMON_CTL_INVERT | \
247 NHMEX_PMON_CTL_TRESH_MASK)
248
249/* NHM-EX Ubox */
250#define NHMEX_U_MSR_PMON_GLOBAL_CTL 0xc00
251#define NHMEX_U_MSR_PMON_CTR 0xc11
252#define NHMEX_U_MSR_PMON_EV_SEL 0xc10
253
254#define NHMEX_U_PMON_GLOBAL_EN (1 << 0)
255#define NHMEX_U_PMON_GLOBAL_PMI_CORE_SEL 0x0000001e
256#define NHMEX_U_PMON_GLOBAL_EN_ALL (1 << 28)
257#define NHMEX_U_PMON_GLOBAL_RST_ALL (1 << 29)
258#define NHMEX_U_PMON_GLOBAL_FRZ_ALL (1 << 31)
259
260#define NHMEX_U_PMON_RAW_EVENT_MASK \
261 (NHMEX_PMON_CTL_EV_SEL_MASK | \
262 NHMEX_PMON_CTL_EDGE_DET)
263
264/* NHM-EX Cbox */
265#define NHMEX_C0_MSR_PMON_GLOBAL_CTL 0xd00
266#define NHMEX_C0_MSR_PMON_CTR0 0xd11
267#define NHMEX_C0_MSR_PMON_EV_SEL0 0xd10
268#define NHMEX_C_MSR_OFFSET 0x20
269
270/* NHM-EX Bbox */
271#define NHMEX_B0_MSR_PMON_GLOBAL_CTL 0xc20
272#define NHMEX_B0_MSR_PMON_CTR0 0xc31
273#define NHMEX_B0_MSR_PMON_CTL0 0xc30
274#define NHMEX_B_MSR_OFFSET 0x40
275#define NHMEX_B0_MSR_MATCH 0xe45
276#define NHMEX_B0_MSR_MASK 0xe46
277#define NHMEX_B1_MSR_MATCH 0xe4d
278#define NHMEX_B1_MSR_MASK 0xe4e
279
280#define NHMEX_B_PMON_CTL_EN (1 << 0)
281#define NHMEX_B_PMON_CTL_EV_SEL_SHIFT 1
282#define NHMEX_B_PMON_CTL_EV_SEL_MASK \
283 (0x1f << NHMEX_B_PMON_CTL_EV_SEL_SHIFT)
284#define NHMEX_B_PMON_CTR_SHIFT 6
285#define NHMEX_B_PMON_CTR_MASK \
286 (0x3 << NHMEX_B_PMON_CTR_SHIFT)
287#define NHMEX_B_PMON_RAW_EVENT_MASK \
288 (NHMEX_B_PMON_CTL_EV_SEL_MASK | \
289 NHMEX_B_PMON_CTR_MASK)
290
291/* NHM-EX Sbox */
292#define NHMEX_S0_MSR_PMON_GLOBAL_CTL 0xc40
293#define NHMEX_S0_MSR_PMON_CTR0 0xc51
294#define NHMEX_S0_MSR_PMON_CTL0 0xc50
295#define NHMEX_S_MSR_OFFSET 0x80
296#define NHMEX_S0_MSR_MM_CFG 0xe48
297#define NHMEX_S0_MSR_MATCH 0xe49
298#define NHMEX_S0_MSR_MASK 0xe4a
299#define NHMEX_S1_MSR_MM_CFG 0xe58
300#define NHMEX_S1_MSR_MATCH 0xe59
301#define NHMEX_S1_MSR_MASK 0xe5a
302
303#define NHMEX_S_PMON_MM_CFG_EN (0x1ULL << 63)
304#define NHMEX_S_EVENT_TO_R_PROG_EV 0
305
306/* NHM-EX Mbox */
307#define NHMEX_M0_MSR_GLOBAL_CTL 0xca0
308#define NHMEX_M0_MSR_PMU_DSP 0xca5
309#define NHMEX_M0_MSR_PMU_ISS 0xca6
310#define NHMEX_M0_MSR_PMU_MAP 0xca7
311#define NHMEX_M0_MSR_PMU_MSC_THR 0xca8
312#define NHMEX_M0_MSR_PMU_PGT 0xca9
313#define NHMEX_M0_MSR_PMU_PLD 0xcaa
314#define NHMEX_M0_MSR_PMU_ZDP_CTL_FVC 0xcab
315#define NHMEX_M0_MSR_PMU_CTL0 0xcb0
316#define NHMEX_M0_MSR_PMU_CNT0 0xcb1
317#define NHMEX_M_MSR_OFFSET 0x40
318#define NHMEX_M0_MSR_PMU_MM_CFG 0xe54
319#define NHMEX_M1_MSR_PMU_MM_CFG 0xe5c
320
321#define NHMEX_M_PMON_MM_CFG_EN (1ULL << 63)
322#define NHMEX_M_PMON_ADDR_MATCH_MASK 0x3ffffffffULL
323#define NHMEX_M_PMON_ADDR_MASK_MASK 0x7ffffffULL
324#define NHMEX_M_PMON_ADDR_MASK_SHIFT 34
325
326#define NHMEX_M_PMON_CTL_EN (1 << 0)
327#define NHMEX_M_PMON_CTL_PMI_EN (1 << 1)
328#define NHMEX_M_PMON_CTL_COUNT_MODE_SHIFT 2
329#define NHMEX_M_PMON_CTL_COUNT_MODE_MASK \
330 (0x3 << NHMEX_M_PMON_CTL_COUNT_MODE_SHIFT)
331#define NHMEX_M_PMON_CTL_STORAGE_MODE_SHIFT 4
332#define NHMEX_M_PMON_CTL_STORAGE_MODE_MASK \
333 (0x3 << NHMEX_M_PMON_CTL_STORAGE_MODE_SHIFT)
334#define NHMEX_M_PMON_CTL_WRAP_MODE (1 << 6)
335#define NHMEX_M_PMON_CTL_FLAG_MODE (1 << 7)
336#define NHMEX_M_PMON_CTL_INC_SEL_SHIFT 9
337#define NHMEX_M_PMON_CTL_INC_SEL_MASK \
338 (0x1f << NHMEX_M_PMON_CTL_INC_SEL_SHIFT)
339#define NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT 19
340#define NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK \
341 (0x7 << NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT)
342#define NHMEX_M_PMON_RAW_EVENT_MASK \
343 (NHMEX_M_PMON_CTL_COUNT_MODE_MASK | \
344 NHMEX_M_PMON_CTL_STORAGE_MODE_MASK | \
345 NHMEX_M_PMON_CTL_WRAP_MODE | \
346 NHMEX_M_PMON_CTL_FLAG_MODE | \
347 NHMEX_M_PMON_CTL_INC_SEL_MASK | \
348 NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK)
349
350#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 11) - 1) | (1 << 23))
351#define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7ULL << (11 + 3 * (n)))
352
353#define WSMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 12) - 1) | (1 << 24))
354#define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7ULL << (12 + 3 * (n)))
355
356/*
357 * use the 9~13 bits to select event If the 7th bit is not set,
358 * otherwise use the 19~21 bits to select event.
359 */
360#define MBOX_INC_SEL(x) ((x) << NHMEX_M_PMON_CTL_INC_SEL_SHIFT)
361#define MBOX_SET_FLAG_SEL(x) (((x) << NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT) | \
362 NHMEX_M_PMON_CTL_FLAG_MODE)
363#define MBOX_INC_SEL_MASK (NHMEX_M_PMON_CTL_INC_SEL_MASK | \
364 NHMEX_M_PMON_CTL_FLAG_MODE)
365#define MBOX_SET_FLAG_SEL_MASK (NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK | \
366 NHMEX_M_PMON_CTL_FLAG_MODE)
367#define MBOX_INC_SEL_EXTAR_REG(c, r) \
368 EVENT_EXTRA_REG(MBOX_INC_SEL(c), NHMEX_M0_MSR_PMU_##r, \
369 MBOX_INC_SEL_MASK, (u64)-1, NHMEX_M_##r)
370#define MBOX_SET_FLAG_SEL_EXTRA_REG(c, r) \
371 EVENT_EXTRA_REG(MBOX_SET_FLAG_SEL(c), NHMEX_M0_MSR_PMU_##r, \
372 MBOX_SET_FLAG_SEL_MASK, \
373 (u64)-1, NHMEX_M_##r)
374
375/* NHM-EX Rbox */
376#define NHMEX_R_MSR_GLOBAL_CTL 0xe00
377#define NHMEX_R_MSR_PMON_CTL0 0xe10
378#define NHMEX_R_MSR_PMON_CNT0 0xe11
379#define NHMEX_R_MSR_OFFSET 0x20
380
381#define NHMEX_R_MSR_PORTN_QLX_CFG(n) \
382 ((n) < 4 ? (0xe0c + (n)) : (0xe2c + (n) - 4))
383#define NHMEX_R_MSR_PORTN_IPERF_CFG0(n) (0xe04 + (n))
384#define NHMEX_R_MSR_PORTN_IPERF_CFG1(n) (0xe24 + (n))
385#define NHMEX_R_MSR_PORTN_XBR_OFFSET(n) \
386 (((n) < 4 ? 0 : 0x10) + (n) * 4)
387#define NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) \
388 (0xe60 + NHMEX_R_MSR_PORTN_XBR_OFFSET(n))
389#define NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(n) \
390 (NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) + 1)
391#define NHMEX_R_MSR_PORTN_XBR_SET1_MASK(n) \
392 (NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) + 2)
393#define NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) \
394 (0xe70 + NHMEX_R_MSR_PORTN_XBR_OFFSET(n))
395#define NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(n) \
396 (NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) + 1)
397#define NHMEX_R_MSR_PORTN_XBR_SET2_MASK(n) \
398 (NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) + 2)
399
400#define NHMEX_R_PMON_CTL_EN (1 << 0)
401#define NHMEX_R_PMON_CTL_EV_SEL_SHIFT 1
402#define NHMEX_R_PMON_CTL_EV_SEL_MASK \
403 (0x1f << NHMEX_R_PMON_CTL_EV_SEL_SHIFT)
404#define NHMEX_R_PMON_CTL_PMI_EN (1 << 6)
405#define NHMEX_R_PMON_RAW_EVENT_MASK NHMEX_R_PMON_CTL_EV_SEL_MASK
406
407/* NHM-EX Wbox */
408#define NHMEX_W_MSR_GLOBAL_CTL 0xc80
409#define NHMEX_W_MSR_PMON_CNT0 0xc90
410#define NHMEX_W_MSR_PMON_EVT_SEL0 0xc91
411#define NHMEX_W_MSR_PMON_FIXED_CTR 0x394
412#define NHMEX_W_MSR_PMON_FIXED_CTL 0x395
413
414#define NHMEX_W_PMON_GLOBAL_FIXED_EN (1ULL << 31)
415
416struct intel_uncore_ops; 27struct intel_uncore_ops;
417struct intel_uncore_pmu; 28struct intel_uncore_pmu;
418struct intel_uncore_box; 29struct intel_uncore_box;
@@ -505,6 +116,9 @@ struct uncore_event_desc {
505 const char *config; 116 const char *config;
506}; 117};
507 118
119ssize_t uncore_event_show(struct kobject *kobj,
120 struct kobj_attribute *attr, char *buf);
121
508#define INTEL_UNCORE_EVENT_DESC(_name, _config) \ 122#define INTEL_UNCORE_EVENT_DESC(_name, _config) \
509{ \ 123{ \
510 .attr = __ATTR(_name, 0444, uncore_event_show, NULL), \ 124 .attr = __ATTR(_name, 0444, uncore_event_show, NULL), \
@@ -522,15 +136,6 @@ static ssize_t __uncore_##_var##_show(struct kobject *kobj, \
522static struct kobj_attribute format_attr_##_var = \ 136static struct kobj_attribute format_attr_##_var = \
523 __ATTR(_name, 0444, __uncore_##_var##_show, NULL) 137 __ATTR(_name, 0444, __uncore_##_var##_show, NULL)
524 138
525
526static ssize_t uncore_event_show(struct kobject *kobj,
527 struct kobj_attribute *attr, char *buf)
528{
529 struct uncore_event_desc *event =
530 container_of(attr, struct uncore_event_desc, attr);
531 return sprintf(buf, "%s", event->config);
532}
533
534static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box) 139static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box)
535{ 140{
536 return box->pmu->type->box_ctl; 141 return box->pmu->type->box_ctl;
@@ -694,3 +299,41 @@ static inline bool uncore_box_is_fake(struct intel_uncore_box *box)
694{ 299{
695 return (box->phys_id < 0); 300 return (box->phys_id < 0);
696} 301}
302
303struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event);
304struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu);
305struct intel_uncore_box *uncore_event_to_box(struct perf_event *event);
306u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event);
307void uncore_pmu_start_hrtimer(struct intel_uncore_box *box);
308void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box);
309void uncore_pmu_event_read(struct perf_event *event);
310void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *event);
311struct event_constraint *
312uncore_get_constraint(struct intel_uncore_box *box, struct perf_event *event);
313void uncore_put_constraint(struct intel_uncore_box *box, struct perf_event *event);
314u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx);
315
316extern struct intel_uncore_type **uncore_msr_uncores;
317extern struct intel_uncore_type **uncore_pci_uncores;
318extern struct pci_driver *uncore_pci_driver;
319extern int uncore_pcibus_to_physid[256];
320extern struct pci_dev *uncore_extra_pci_dev[UNCORE_SOCKET_MAX][UNCORE_EXTRA_PCI_DEV_MAX];
321extern struct event_constraint uncore_constraint_empty;
322
323/* perf_event_intel_uncore_snb.c */
324int snb_uncore_pci_init(void);
325int ivb_uncore_pci_init(void);
326int hsw_uncore_pci_init(void);
327void snb_uncore_cpu_init(void);
328void nhm_uncore_cpu_init(void);
329
330/* perf_event_intel_uncore_snbep.c */
331int snbep_uncore_pci_init(void);
332void snbep_uncore_cpu_init(void);
333int ivbep_uncore_pci_init(void);
334void ivbep_uncore_cpu_init(void);
335int hswep_uncore_pci_init(void);
336void hswep_uncore_cpu_init(void);
337
338/* perf_event_intel_uncore_nhmex.c */
339void nhmex_uncore_cpu_init(void);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c
new file mode 100644
index 000000000000..2749965afed0
--- /dev/null
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c
@@ -0,0 +1,1221 @@
1/* Nehalem-EX/Westmere-EX uncore support */
2#include "perf_event_intel_uncore.h"
3
4/* NHM-EX event control */
5#define NHMEX_PMON_CTL_EV_SEL_MASK 0x000000ff
6#define NHMEX_PMON_CTL_UMASK_MASK 0x0000ff00
7#define NHMEX_PMON_CTL_EN_BIT0 (1 << 0)
8#define NHMEX_PMON_CTL_EDGE_DET (1 << 18)
9#define NHMEX_PMON_CTL_PMI_EN (1 << 20)
10#define NHMEX_PMON_CTL_EN_BIT22 (1 << 22)
11#define NHMEX_PMON_CTL_INVERT (1 << 23)
12#define NHMEX_PMON_CTL_TRESH_MASK 0xff000000
13#define NHMEX_PMON_RAW_EVENT_MASK (NHMEX_PMON_CTL_EV_SEL_MASK | \
14 NHMEX_PMON_CTL_UMASK_MASK | \
15 NHMEX_PMON_CTL_EDGE_DET | \
16 NHMEX_PMON_CTL_INVERT | \
17 NHMEX_PMON_CTL_TRESH_MASK)
18
19/* NHM-EX Ubox */
20#define NHMEX_U_MSR_PMON_GLOBAL_CTL 0xc00
21#define NHMEX_U_MSR_PMON_CTR 0xc11
22#define NHMEX_U_MSR_PMON_EV_SEL 0xc10
23
24#define NHMEX_U_PMON_GLOBAL_EN (1 << 0)
25#define NHMEX_U_PMON_GLOBAL_PMI_CORE_SEL 0x0000001e
26#define NHMEX_U_PMON_GLOBAL_EN_ALL (1 << 28)
27#define NHMEX_U_PMON_GLOBAL_RST_ALL (1 << 29)
28#define NHMEX_U_PMON_GLOBAL_FRZ_ALL (1 << 31)
29
30#define NHMEX_U_PMON_RAW_EVENT_MASK \
31 (NHMEX_PMON_CTL_EV_SEL_MASK | \
32 NHMEX_PMON_CTL_EDGE_DET)
33
34/* NHM-EX Cbox */
35#define NHMEX_C0_MSR_PMON_GLOBAL_CTL 0xd00
36#define NHMEX_C0_MSR_PMON_CTR0 0xd11
37#define NHMEX_C0_MSR_PMON_EV_SEL0 0xd10
38#define NHMEX_C_MSR_OFFSET 0x20
39
40/* NHM-EX Bbox */
41#define NHMEX_B0_MSR_PMON_GLOBAL_CTL 0xc20
42#define NHMEX_B0_MSR_PMON_CTR0 0xc31
43#define NHMEX_B0_MSR_PMON_CTL0 0xc30
44#define NHMEX_B_MSR_OFFSET 0x40
45#define NHMEX_B0_MSR_MATCH 0xe45
46#define NHMEX_B0_MSR_MASK 0xe46
47#define NHMEX_B1_MSR_MATCH 0xe4d
48#define NHMEX_B1_MSR_MASK 0xe4e
49
50#define NHMEX_B_PMON_CTL_EN (1 << 0)
51#define NHMEX_B_PMON_CTL_EV_SEL_SHIFT 1
52#define NHMEX_B_PMON_CTL_EV_SEL_MASK \
53 (0x1f << NHMEX_B_PMON_CTL_EV_SEL_SHIFT)
54#define NHMEX_B_PMON_CTR_SHIFT 6
55#define NHMEX_B_PMON_CTR_MASK \
56 (0x3 << NHMEX_B_PMON_CTR_SHIFT)
57#define NHMEX_B_PMON_RAW_EVENT_MASK \
58 (NHMEX_B_PMON_CTL_EV_SEL_MASK | \
59 NHMEX_B_PMON_CTR_MASK)
60
61/* NHM-EX Sbox */
62#define NHMEX_S0_MSR_PMON_GLOBAL_CTL 0xc40
63#define NHMEX_S0_MSR_PMON_CTR0 0xc51
64#define NHMEX_S0_MSR_PMON_CTL0 0xc50
65#define NHMEX_S_MSR_OFFSET 0x80
66#define NHMEX_S0_MSR_MM_CFG 0xe48
67#define NHMEX_S0_MSR_MATCH 0xe49
68#define NHMEX_S0_MSR_MASK 0xe4a
69#define NHMEX_S1_MSR_MM_CFG 0xe58
70#define NHMEX_S1_MSR_MATCH 0xe59
71#define NHMEX_S1_MSR_MASK 0xe5a
72
73#define NHMEX_S_PMON_MM_CFG_EN (0x1ULL << 63)
74#define NHMEX_S_EVENT_TO_R_PROG_EV 0
75
76/* NHM-EX Mbox */
77#define NHMEX_M0_MSR_GLOBAL_CTL 0xca0
78#define NHMEX_M0_MSR_PMU_DSP 0xca5
79#define NHMEX_M0_MSR_PMU_ISS 0xca6
80#define NHMEX_M0_MSR_PMU_MAP 0xca7
81#define NHMEX_M0_MSR_PMU_MSC_THR 0xca8
82#define NHMEX_M0_MSR_PMU_PGT 0xca9
83#define NHMEX_M0_MSR_PMU_PLD 0xcaa
84#define NHMEX_M0_MSR_PMU_ZDP_CTL_FVC 0xcab
85#define NHMEX_M0_MSR_PMU_CTL0 0xcb0
86#define NHMEX_M0_MSR_PMU_CNT0 0xcb1
87#define NHMEX_M_MSR_OFFSET 0x40
88#define NHMEX_M0_MSR_PMU_MM_CFG 0xe54
89#define NHMEX_M1_MSR_PMU_MM_CFG 0xe5c
90
91#define NHMEX_M_PMON_MM_CFG_EN (1ULL << 63)
92#define NHMEX_M_PMON_ADDR_MATCH_MASK 0x3ffffffffULL
93#define NHMEX_M_PMON_ADDR_MASK_MASK 0x7ffffffULL
94#define NHMEX_M_PMON_ADDR_MASK_SHIFT 34
95
96#define NHMEX_M_PMON_CTL_EN (1 << 0)
97#define NHMEX_M_PMON_CTL_PMI_EN (1 << 1)
98#define NHMEX_M_PMON_CTL_COUNT_MODE_SHIFT 2
99#define NHMEX_M_PMON_CTL_COUNT_MODE_MASK \
100 (0x3 << NHMEX_M_PMON_CTL_COUNT_MODE_SHIFT)
101#define NHMEX_M_PMON_CTL_STORAGE_MODE_SHIFT 4
102#define NHMEX_M_PMON_CTL_STORAGE_MODE_MASK \
103 (0x3 << NHMEX_M_PMON_CTL_STORAGE_MODE_SHIFT)
104#define NHMEX_M_PMON_CTL_WRAP_MODE (1 << 6)
105#define NHMEX_M_PMON_CTL_FLAG_MODE (1 << 7)
106#define NHMEX_M_PMON_CTL_INC_SEL_SHIFT 9
107#define NHMEX_M_PMON_CTL_INC_SEL_MASK \
108 (0x1f << NHMEX_M_PMON_CTL_INC_SEL_SHIFT)
109#define NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT 19
110#define NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK \
111 (0x7 << NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT)
112#define NHMEX_M_PMON_RAW_EVENT_MASK \
113 (NHMEX_M_PMON_CTL_COUNT_MODE_MASK | \
114 NHMEX_M_PMON_CTL_STORAGE_MODE_MASK | \
115 NHMEX_M_PMON_CTL_WRAP_MODE | \
116 NHMEX_M_PMON_CTL_FLAG_MODE | \
117 NHMEX_M_PMON_CTL_INC_SEL_MASK | \
118 NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK)
119
120#define NHMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 11) - 1) | (1 << 23))
121#define NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7ULL << (11 + 3 * (n)))
122
123#define WSMEX_M_PMON_ZDP_CTL_FVC_MASK (((1 << 12) - 1) | (1 << 24))
124#define WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(n) (0x7ULL << (12 + 3 * (n)))
125
126/*
127 * use the 9~13 bits to select event If the 7th bit is not set,
128 * otherwise use the 19~21 bits to select event.
129 */
130#define MBOX_INC_SEL(x) ((x) << NHMEX_M_PMON_CTL_INC_SEL_SHIFT)
131#define MBOX_SET_FLAG_SEL(x) (((x) << NHMEX_M_PMON_CTL_SET_FLAG_SEL_SHIFT) | \
132 NHMEX_M_PMON_CTL_FLAG_MODE)
133#define MBOX_INC_SEL_MASK (NHMEX_M_PMON_CTL_INC_SEL_MASK | \
134 NHMEX_M_PMON_CTL_FLAG_MODE)
135#define MBOX_SET_FLAG_SEL_MASK (NHMEX_M_PMON_CTL_SET_FLAG_SEL_MASK | \
136 NHMEX_M_PMON_CTL_FLAG_MODE)
137#define MBOX_INC_SEL_EXTAR_REG(c, r) \
138 EVENT_EXTRA_REG(MBOX_INC_SEL(c), NHMEX_M0_MSR_PMU_##r, \
139 MBOX_INC_SEL_MASK, (u64)-1, NHMEX_M_##r)
140#define MBOX_SET_FLAG_SEL_EXTRA_REG(c, r) \
141 EVENT_EXTRA_REG(MBOX_SET_FLAG_SEL(c), NHMEX_M0_MSR_PMU_##r, \
142 MBOX_SET_FLAG_SEL_MASK, \
143 (u64)-1, NHMEX_M_##r)
144
145/* NHM-EX Rbox */
146#define NHMEX_R_MSR_GLOBAL_CTL 0xe00
147#define NHMEX_R_MSR_PMON_CTL0 0xe10
148#define NHMEX_R_MSR_PMON_CNT0 0xe11
149#define NHMEX_R_MSR_OFFSET 0x20
150
151#define NHMEX_R_MSR_PORTN_QLX_CFG(n) \
152 ((n) < 4 ? (0xe0c + (n)) : (0xe2c + (n) - 4))
153#define NHMEX_R_MSR_PORTN_IPERF_CFG0(n) (0xe04 + (n))
154#define NHMEX_R_MSR_PORTN_IPERF_CFG1(n) (0xe24 + (n))
155#define NHMEX_R_MSR_PORTN_XBR_OFFSET(n) \
156 (((n) < 4 ? 0 : 0x10) + (n) * 4)
157#define NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) \
158 (0xe60 + NHMEX_R_MSR_PORTN_XBR_OFFSET(n))
159#define NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(n) \
160 (NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) + 1)
161#define NHMEX_R_MSR_PORTN_XBR_SET1_MASK(n) \
162 (NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(n) + 2)
163#define NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) \
164 (0xe70 + NHMEX_R_MSR_PORTN_XBR_OFFSET(n))
165#define NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(n) \
166 (NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) + 1)
167#define NHMEX_R_MSR_PORTN_XBR_SET2_MASK(n) \
168 (NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(n) + 2)
169
170#define NHMEX_R_PMON_CTL_EN (1 << 0)
171#define NHMEX_R_PMON_CTL_EV_SEL_SHIFT 1
172#define NHMEX_R_PMON_CTL_EV_SEL_MASK \
173 (0x1f << NHMEX_R_PMON_CTL_EV_SEL_SHIFT)
174#define NHMEX_R_PMON_CTL_PMI_EN (1 << 6)
175#define NHMEX_R_PMON_RAW_EVENT_MASK NHMEX_R_PMON_CTL_EV_SEL_MASK
176
177/* NHM-EX Wbox */
178#define NHMEX_W_MSR_GLOBAL_CTL 0xc80
179#define NHMEX_W_MSR_PMON_CNT0 0xc90
180#define NHMEX_W_MSR_PMON_EVT_SEL0 0xc91
181#define NHMEX_W_MSR_PMON_FIXED_CTR 0x394
182#define NHMEX_W_MSR_PMON_FIXED_CTL 0x395
183
184#define NHMEX_W_PMON_GLOBAL_FIXED_EN (1ULL << 31)
185
186#define __BITS_VALUE(x, i, n) ((typeof(x))(((x) >> ((i) * (n))) & \
187 ((1ULL << (n)) - 1)))
188
189DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
190DEFINE_UNCORE_FORMAT_ATTR(event5, event, "config:1-5");
191DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
192DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
193DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
194DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
195DEFINE_UNCORE_FORMAT_ATTR(counter, counter, "config:6-7");
196DEFINE_UNCORE_FORMAT_ATTR(match, match, "config1:0-63");
197DEFINE_UNCORE_FORMAT_ATTR(mask, mask, "config2:0-63");
198
199static void nhmex_uncore_msr_init_box(struct intel_uncore_box *box)
200{
201 wrmsrl(NHMEX_U_MSR_PMON_GLOBAL_CTL, NHMEX_U_PMON_GLOBAL_EN_ALL);
202}
203
204static void nhmex_uncore_msr_disable_box(struct intel_uncore_box *box)
205{
206 unsigned msr = uncore_msr_box_ctl(box);
207 u64 config;
208
209 if (msr) {
210 rdmsrl(msr, config);
211 config &= ~((1ULL << uncore_num_counters(box)) - 1);
212 /* WBox has a fixed counter */
213 if (uncore_msr_fixed_ctl(box))
214 config &= ~NHMEX_W_PMON_GLOBAL_FIXED_EN;
215 wrmsrl(msr, config);
216 }
217}
218
219static void nhmex_uncore_msr_enable_box(struct intel_uncore_box *box)
220{
221 unsigned msr = uncore_msr_box_ctl(box);
222 u64 config;
223
224 if (msr) {
225 rdmsrl(msr, config);
226 config |= (1ULL << uncore_num_counters(box)) - 1;
227 /* WBox has a fixed counter */
228 if (uncore_msr_fixed_ctl(box))
229 config |= NHMEX_W_PMON_GLOBAL_FIXED_EN;
230 wrmsrl(msr, config);
231 }
232}
233
234static void nhmex_uncore_msr_disable_event(struct intel_uncore_box *box, struct perf_event *event)
235{
236 wrmsrl(event->hw.config_base, 0);
237}
238
239static void nhmex_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
240{
241 struct hw_perf_event *hwc = &event->hw;
242
243 if (hwc->idx >= UNCORE_PMC_IDX_FIXED)
244 wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0);
245 else if (box->pmu->type->event_mask & NHMEX_PMON_CTL_EN_BIT0)
246 wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22);
247 else
248 wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);
249}
250
251#define NHMEX_UNCORE_OPS_COMMON_INIT() \
252 .init_box = nhmex_uncore_msr_init_box, \
253 .disable_box = nhmex_uncore_msr_disable_box, \
254 .enable_box = nhmex_uncore_msr_enable_box, \
255 .disable_event = nhmex_uncore_msr_disable_event, \
256 .read_counter = uncore_msr_read_counter
257
258static struct intel_uncore_ops nhmex_uncore_ops = {
259 NHMEX_UNCORE_OPS_COMMON_INIT(),
260 .enable_event = nhmex_uncore_msr_enable_event,
261};
262
263static struct attribute *nhmex_uncore_ubox_formats_attr[] = {
264 &format_attr_event.attr,
265 &format_attr_edge.attr,
266 NULL,
267};
268
269static struct attribute_group nhmex_uncore_ubox_format_group = {
270 .name = "format",
271 .attrs = nhmex_uncore_ubox_formats_attr,
272};
273
274static struct intel_uncore_type nhmex_uncore_ubox = {
275 .name = "ubox",
276 .num_counters = 1,
277 .num_boxes = 1,
278 .perf_ctr_bits = 48,
279 .event_ctl = NHMEX_U_MSR_PMON_EV_SEL,
280 .perf_ctr = NHMEX_U_MSR_PMON_CTR,
281 .event_mask = NHMEX_U_PMON_RAW_EVENT_MASK,
282 .box_ctl = NHMEX_U_MSR_PMON_GLOBAL_CTL,
283 .ops = &nhmex_uncore_ops,
284 .format_group = &nhmex_uncore_ubox_format_group
285};
286
287static struct attribute *nhmex_uncore_cbox_formats_attr[] = {
288 &format_attr_event.attr,
289 &format_attr_umask.attr,
290 &format_attr_edge.attr,
291 &format_attr_inv.attr,
292 &format_attr_thresh8.attr,
293 NULL,
294};
295
296static struct attribute_group nhmex_uncore_cbox_format_group = {
297 .name = "format",
298 .attrs = nhmex_uncore_cbox_formats_attr,
299};
300
301/* msr offset for each instance of cbox */
302static unsigned nhmex_cbox_msr_offsets[] = {
303 0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x240, 0x2c0,
304};
305
306static struct intel_uncore_type nhmex_uncore_cbox = {
307 .name = "cbox",
308 .num_counters = 6,
309 .num_boxes = 10,
310 .perf_ctr_bits = 48,
311 .event_ctl = NHMEX_C0_MSR_PMON_EV_SEL0,
312 .perf_ctr = NHMEX_C0_MSR_PMON_CTR0,
313 .event_mask = NHMEX_PMON_RAW_EVENT_MASK,
314 .box_ctl = NHMEX_C0_MSR_PMON_GLOBAL_CTL,
315 .msr_offsets = nhmex_cbox_msr_offsets,
316 .pair_ctr_ctl = 1,
317 .ops = &nhmex_uncore_ops,
318 .format_group = &nhmex_uncore_cbox_format_group
319};
320
321static struct uncore_event_desc nhmex_uncore_wbox_events[] = {
322 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0"),
323 { /* end: all zeroes */ },
324};
325
326static struct intel_uncore_type nhmex_uncore_wbox = {
327 .name = "wbox",
328 .num_counters = 4,
329 .num_boxes = 1,
330 .perf_ctr_bits = 48,
331 .event_ctl = NHMEX_W_MSR_PMON_CNT0,
332 .perf_ctr = NHMEX_W_MSR_PMON_EVT_SEL0,
333 .fixed_ctr = NHMEX_W_MSR_PMON_FIXED_CTR,
334 .fixed_ctl = NHMEX_W_MSR_PMON_FIXED_CTL,
335 .event_mask = NHMEX_PMON_RAW_EVENT_MASK,
336 .box_ctl = NHMEX_W_MSR_GLOBAL_CTL,
337 .pair_ctr_ctl = 1,
338 .event_descs = nhmex_uncore_wbox_events,
339 .ops = &nhmex_uncore_ops,
340 .format_group = &nhmex_uncore_cbox_format_group
341};
342
343static int nhmex_bbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
344{
345 struct hw_perf_event *hwc = &event->hw;
346 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
347 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
348 int ctr, ev_sel;
349
350 ctr = (hwc->config & NHMEX_B_PMON_CTR_MASK) >>
351 NHMEX_B_PMON_CTR_SHIFT;
352 ev_sel = (hwc->config & NHMEX_B_PMON_CTL_EV_SEL_MASK) >>
353 NHMEX_B_PMON_CTL_EV_SEL_SHIFT;
354
355 /* events that do not use the match/mask registers */
356 if ((ctr == 0 && ev_sel > 0x3) || (ctr == 1 && ev_sel > 0x6) ||
357 (ctr == 2 && ev_sel != 0x4) || ctr == 3)
358 return 0;
359
360 if (box->pmu->pmu_idx == 0)
361 reg1->reg = NHMEX_B0_MSR_MATCH;
362 else
363 reg1->reg = NHMEX_B1_MSR_MATCH;
364 reg1->idx = 0;
365 reg1->config = event->attr.config1;
366 reg2->config = event->attr.config2;
367 return 0;
368}
369
370static void nhmex_bbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
371{
372 struct hw_perf_event *hwc = &event->hw;
373 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
374 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
375
376 if (reg1->idx != EXTRA_REG_NONE) {
377 wrmsrl(reg1->reg, reg1->config);
378 wrmsrl(reg1->reg + 1, reg2->config);
379 }
380 wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0 |
381 (hwc->config & NHMEX_B_PMON_CTL_EV_SEL_MASK));
382}
383
384/*
385 * The Bbox has 4 counters, but each counter monitors different events.
386 * Use bits 6-7 in the event config to select counter.
387 */
388static struct event_constraint nhmex_uncore_bbox_constraints[] = {
389 EVENT_CONSTRAINT(0 , 1, 0xc0),
390 EVENT_CONSTRAINT(0x40, 2, 0xc0),
391 EVENT_CONSTRAINT(0x80, 4, 0xc0),
392 EVENT_CONSTRAINT(0xc0, 8, 0xc0),
393 EVENT_CONSTRAINT_END,
394};
395
396static struct attribute *nhmex_uncore_bbox_formats_attr[] = {
397 &format_attr_event5.attr,
398 &format_attr_counter.attr,
399 &format_attr_match.attr,
400 &format_attr_mask.attr,
401 NULL,
402};
403
404static struct attribute_group nhmex_uncore_bbox_format_group = {
405 .name = "format",
406 .attrs = nhmex_uncore_bbox_formats_attr,
407};
408
409static struct intel_uncore_ops nhmex_uncore_bbox_ops = {
410 NHMEX_UNCORE_OPS_COMMON_INIT(),
411 .enable_event = nhmex_bbox_msr_enable_event,
412 .hw_config = nhmex_bbox_hw_config,
413 .get_constraint = uncore_get_constraint,
414 .put_constraint = uncore_put_constraint,
415};
416
417static struct intel_uncore_type nhmex_uncore_bbox = {
418 .name = "bbox",
419 .num_counters = 4,
420 .num_boxes = 2,
421 .perf_ctr_bits = 48,
422 .event_ctl = NHMEX_B0_MSR_PMON_CTL0,
423 .perf_ctr = NHMEX_B0_MSR_PMON_CTR0,
424 .event_mask = NHMEX_B_PMON_RAW_EVENT_MASK,
425 .box_ctl = NHMEX_B0_MSR_PMON_GLOBAL_CTL,
426 .msr_offset = NHMEX_B_MSR_OFFSET,
427 .pair_ctr_ctl = 1,
428 .num_shared_regs = 1,
429 .constraints = nhmex_uncore_bbox_constraints,
430 .ops = &nhmex_uncore_bbox_ops,
431 .format_group = &nhmex_uncore_bbox_format_group
432};
433
434static int nhmex_sbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
435{
436 struct hw_perf_event *hwc = &event->hw;
437 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
438 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
439
440 /* only TO_R_PROG_EV event uses the match/mask register */
441 if ((hwc->config & NHMEX_PMON_CTL_EV_SEL_MASK) !=
442 NHMEX_S_EVENT_TO_R_PROG_EV)
443 return 0;
444
445 if (box->pmu->pmu_idx == 0)
446 reg1->reg = NHMEX_S0_MSR_MM_CFG;
447 else
448 reg1->reg = NHMEX_S1_MSR_MM_CFG;
449 reg1->idx = 0;
450 reg1->config = event->attr.config1;
451 reg2->config = event->attr.config2;
452 return 0;
453}
454
455static void nhmex_sbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
456{
457 struct hw_perf_event *hwc = &event->hw;
458 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
459 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
460
461 if (reg1->idx != EXTRA_REG_NONE) {
462 wrmsrl(reg1->reg, 0);
463 wrmsrl(reg1->reg + 1, reg1->config);
464 wrmsrl(reg1->reg + 2, reg2->config);
465 wrmsrl(reg1->reg, NHMEX_S_PMON_MM_CFG_EN);
466 }
467 wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22);
468}
469
470static struct attribute *nhmex_uncore_sbox_formats_attr[] = {
471 &format_attr_event.attr,
472 &format_attr_umask.attr,
473 &format_attr_edge.attr,
474 &format_attr_inv.attr,
475 &format_attr_thresh8.attr,
476 &format_attr_match.attr,
477 &format_attr_mask.attr,
478 NULL,
479};
480
481static struct attribute_group nhmex_uncore_sbox_format_group = {
482 .name = "format",
483 .attrs = nhmex_uncore_sbox_formats_attr,
484};
485
486static struct intel_uncore_ops nhmex_uncore_sbox_ops = {
487 NHMEX_UNCORE_OPS_COMMON_INIT(),
488 .enable_event = nhmex_sbox_msr_enable_event,
489 .hw_config = nhmex_sbox_hw_config,
490 .get_constraint = uncore_get_constraint,
491 .put_constraint = uncore_put_constraint,
492};
493
494static struct intel_uncore_type nhmex_uncore_sbox = {
495 .name = "sbox",
496 .num_counters = 4,
497 .num_boxes = 2,
498 .perf_ctr_bits = 48,
499 .event_ctl = NHMEX_S0_MSR_PMON_CTL0,
500 .perf_ctr = NHMEX_S0_MSR_PMON_CTR0,
501 .event_mask = NHMEX_PMON_RAW_EVENT_MASK,
502 .box_ctl = NHMEX_S0_MSR_PMON_GLOBAL_CTL,
503 .msr_offset = NHMEX_S_MSR_OFFSET,
504 .pair_ctr_ctl = 1,
505 .num_shared_regs = 1,
506 .ops = &nhmex_uncore_sbox_ops,
507 .format_group = &nhmex_uncore_sbox_format_group
508};
509
510enum {
511 EXTRA_REG_NHMEX_M_FILTER,
512 EXTRA_REG_NHMEX_M_DSP,
513 EXTRA_REG_NHMEX_M_ISS,
514 EXTRA_REG_NHMEX_M_MAP,
515 EXTRA_REG_NHMEX_M_MSC_THR,
516 EXTRA_REG_NHMEX_M_PGT,
517 EXTRA_REG_NHMEX_M_PLD,
518 EXTRA_REG_NHMEX_M_ZDP_CTL_FVC,
519};
520
521static struct extra_reg nhmex_uncore_mbox_extra_regs[] = {
522 MBOX_INC_SEL_EXTAR_REG(0x0, DSP),
523 MBOX_INC_SEL_EXTAR_REG(0x4, MSC_THR),
524 MBOX_INC_SEL_EXTAR_REG(0x5, MSC_THR),
525 MBOX_INC_SEL_EXTAR_REG(0x9, ISS),
526 /* event 0xa uses two extra registers */
527 MBOX_INC_SEL_EXTAR_REG(0xa, ISS),
528 MBOX_INC_SEL_EXTAR_REG(0xa, PLD),
529 MBOX_INC_SEL_EXTAR_REG(0xb, PLD),
530 /* events 0xd ~ 0x10 use the same extra register */
531 MBOX_INC_SEL_EXTAR_REG(0xd, ZDP_CTL_FVC),
532 MBOX_INC_SEL_EXTAR_REG(0xe, ZDP_CTL_FVC),
533 MBOX_INC_SEL_EXTAR_REG(0xf, ZDP_CTL_FVC),
534 MBOX_INC_SEL_EXTAR_REG(0x10, ZDP_CTL_FVC),
535 MBOX_INC_SEL_EXTAR_REG(0x16, PGT),
536 MBOX_SET_FLAG_SEL_EXTRA_REG(0x0, DSP),
537 MBOX_SET_FLAG_SEL_EXTRA_REG(0x1, ISS),
538 MBOX_SET_FLAG_SEL_EXTRA_REG(0x5, PGT),
539 MBOX_SET_FLAG_SEL_EXTRA_REG(0x6, MAP),
540 EVENT_EXTRA_END
541};
542
543/* Nehalem-EX or Westmere-EX ? */
544static bool uncore_nhmex;
545
546static bool nhmex_mbox_get_shared_reg(struct intel_uncore_box *box, int idx, u64 config)
547{
548 struct intel_uncore_extra_reg *er;
549 unsigned long flags;
550 bool ret = false;
551 u64 mask;
552
553 if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
554 er = &box->shared_regs[idx];
555 raw_spin_lock_irqsave(&er->lock, flags);
556 if (!atomic_read(&er->ref) || er->config == config) {
557 atomic_inc(&er->ref);
558 er->config = config;
559 ret = true;
560 }
561 raw_spin_unlock_irqrestore(&er->lock, flags);
562
563 return ret;
564 }
565 /*
566 * The ZDP_CTL_FVC MSR has 4 fields which are used to control
567 * events 0xd ~ 0x10. Besides these 4 fields, there are additional
568 * fields which are shared.
569 */
570 idx -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
571 if (WARN_ON_ONCE(idx >= 4))
572 return false;
573
574 /* mask of the shared fields */
575 if (uncore_nhmex)
576 mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK;
577 else
578 mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK;
579 er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
580
581 raw_spin_lock_irqsave(&er->lock, flags);
582 /* add mask of the non-shared field if it's in use */
583 if (__BITS_VALUE(atomic_read(&er->ref), idx, 8)) {
584 if (uncore_nhmex)
585 mask |= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
586 else
587 mask |= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
588 }
589
590 if (!atomic_read(&er->ref) || !((er->config ^ config) & mask)) {
591 atomic_add(1 << (idx * 8), &er->ref);
592 if (uncore_nhmex)
593 mask = NHMEX_M_PMON_ZDP_CTL_FVC_MASK |
594 NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
595 else
596 mask = WSMEX_M_PMON_ZDP_CTL_FVC_MASK |
597 WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
598 er->config &= ~mask;
599 er->config |= (config & mask);
600 ret = true;
601 }
602 raw_spin_unlock_irqrestore(&er->lock, flags);
603
604 return ret;
605}
606
607static void nhmex_mbox_put_shared_reg(struct intel_uncore_box *box, int idx)
608{
609 struct intel_uncore_extra_reg *er;
610
611 if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
612 er = &box->shared_regs[idx];
613 atomic_dec(&er->ref);
614 return;
615 }
616
617 idx -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
618 er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
619 atomic_sub(1 << (idx * 8), &er->ref);
620}
621
622static u64 nhmex_mbox_alter_er(struct perf_event *event, int new_idx, bool modify)
623{
624 struct hw_perf_event *hwc = &event->hw;
625 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
626 u64 idx, orig_idx = __BITS_VALUE(reg1->idx, 0, 8);
627 u64 config = reg1->config;
628
629 /* get the non-shared control bits and shift them */
630 idx = orig_idx - EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
631 if (uncore_nhmex)
632 config &= NHMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
633 else
634 config &= WSMEX_M_PMON_ZDP_CTL_FVC_EVENT_MASK(idx);
635 if (new_idx > orig_idx) {
636 idx = new_idx - orig_idx;
637 config <<= 3 * idx;
638 } else {
639 idx = orig_idx - new_idx;
640 config >>= 3 * idx;
641 }
642
643 /* add the shared control bits back */
644 if (uncore_nhmex)
645 config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
646 else
647 config |= WSMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
648 config |= NHMEX_M_PMON_ZDP_CTL_FVC_MASK & reg1->config;
649 if (modify) {
650 /* adjust the main event selector */
651 if (new_idx > orig_idx)
652 hwc->config += idx << NHMEX_M_PMON_CTL_INC_SEL_SHIFT;
653 else
654 hwc->config -= idx << NHMEX_M_PMON_CTL_INC_SEL_SHIFT;
655 reg1->config = config;
656 reg1->idx = ~0xff | new_idx;
657 }
658 return config;
659}
660
661static struct event_constraint *
662nhmex_mbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
663{
664 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
665 struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
666 int i, idx[2], alloc = 0;
667 u64 config1 = reg1->config;
668
669 idx[0] = __BITS_VALUE(reg1->idx, 0, 8);
670 idx[1] = __BITS_VALUE(reg1->idx, 1, 8);
671again:
672 for (i = 0; i < 2; i++) {
673 if (!uncore_box_is_fake(box) && (reg1->alloc & (0x1 << i)))
674 idx[i] = 0xff;
675
676 if (idx[i] == 0xff)
677 continue;
678
679 if (!nhmex_mbox_get_shared_reg(box, idx[i],
680 __BITS_VALUE(config1, i, 32)))
681 goto fail;
682 alloc |= (0x1 << i);
683 }
684
685 /* for the match/mask registers */
686 if (reg2->idx != EXTRA_REG_NONE &&
687 (uncore_box_is_fake(box) || !reg2->alloc) &&
688 !nhmex_mbox_get_shared_reg(box, reg2->idx, reg2->config))
689 goto fail;
690
691 /*
692 * If it's a fake box -- as per validate_{group,event}() we
693 * shouldn't touch event state and we can avoid doing so
694 * since both will only call get_event_constraints() once
695 * on each event, this avoids the need for reg->alloc.
696 */
697 if (!uncore_box_is_fake(box)) {
698 if (idx[0] != 0xff && idx[0] != __BITS_VALUE(reg1->idx, 0, 8))
699 nhmex_mbox_alter_er(event, idx[0], true);
700 reg1->alloc |= alloc;
701 if (reg2->idx != EXTRA_REG_NONE)
702 reg2->alloc = 1;
703 }
704 return NULL;
705fail:
706 if (idx[0] != 0xff && !(alloc & 0x1) &&
707 idx[0] >= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC) {
708 /*
709 * events 0xd ~ 0x10 are functional identical, but are
710 * controlled by different fields in the ZDP_CTL_FVC
711 * register. If we failed to take one field, try the
712 * rest 3 choices.
713 */
714 BUG_ON(__BITS_VALUE(reg1->idx, 1, 8) != 0xff);
715 idx[0] -= EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
716 idx[0] = (idx[0] + 1) % 4;
717 idx[0] += EXTRA_REG_NHMEX_M_ZDP_CTL_FVC;
718 if (idx[0] != __BITS_VALUE(reg1->idx, 0, 8)) {
719 config1 = nhmex_mbox_alter_er(event, idx[0], false);
720 goto again;
721 }
722 }
723
724 if (alloc & 0x1)
725 nhmex_mbox_put_shared_reg(box, idx[0]);
726 if (alloc & 0x2)
727 nhmex_mbox_put_shared_reg(box, idx[1]);
728 return &uncore_constraint_empty;
729}
730
731static void nhmex_mbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
732{
733 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
734 struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
735
736 if (uncore_box_is_fake(box))
737 return;
738
739 if (reg1->alloc & 0x1)
740 nhmex_mbox_put_shared_reg(box, __BITS_VALUE(reg1->idx, 0, 8));
741 if (reg1->alloc & 0x2)
742 nhmex_mbox_put_shared_reg(box, __BITS_VALUE(reg1->idx, 1, 8));
743 reg1->alloc = 0;
744
745 if (reg2->alloc) {
746 nhmex_mbox_put_shared_reg(box, reg2->idx);
747 reg2->alloc = 0;
748 }
749}
750
751static int nhmex_mbox_extra_reg_idx(struct extra_reg *er)
752{
753 if (er->idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC)
754 return er->idx;
755 return er->idx + (er->event >> NHMEX_M_PMON_CTL_INC_SEL_SHIFT) - 0xd;
756}
757
758static int nhmex_mbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
759{
760 struct intel_uncore_type *type = box->pmu->type;
761 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
762 struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
763 struct extra_reg *er;
764 unsigned msr;
765 int reg_idx = 0;
766 /*
767 * The mbox events may require 2 extra MSRs at the most. But only
768 * the lower 32 bits in these MSRs are significant, so we can use
769 * config1 to pass two MSRs' config.
770 */
771 for (er = nhmex_uncore_mbox_extra_regs; er->msr; er++) {
772 if (er->event != (event->hw.config & er->config_mask))
773 continue;
774 if (event->attr.config1 & ~er->valid_mask)
775 return -EINVAL;
776
777 msr = er->msr + type->msr_offset * box->pmu->pmu_idx;
778 if (WARN_ON_ONCE(msr >= 0xffff || er->idx >= 0xff))
779 return -EINVAL;
780
781 /* always use the 32~63 bits to pass the PLD config */
782 if (er->idx == EXTRA_REG_NHMEX_M_PLD)
783 reg_idx = 1;
784 else if (WARN_ON_ONCE(reg_idx > 0))
785 return -EINVAL;
786
787 reg1->idx &= ~(0xff << (reg_idx * 8));
788 reg1->reg &= ~(0xffff << (reg_idx * 16));
789 reg1->idx |= nhmex_mbox_extra_reg_idx(er) << (reg_idx * 8);
790 reg1->reg |= msr << (reg_idx * 16);
791 reg1->config = event->attr.config1;
792 reg_idx++;
793 }
794 /*
795 * The mbox only provides ability to perform address matching
796 * for the PLD events.
797 */
798 if (reg_idx == 2) {
799 reg2->idx = EXTRA_REG_NHMEX_M_FILTER;
800 if (event->attr.config2 & NHMEX_M_PMON_MM_CFG_EN)
801 reg2->config = event->attr.config2;
802 else
803 reg2->config = ~0ULL;
804 if (box->pmu->pmu_idx == 0)
805 reg2->reg = NHMEX_M0_MSR_PMU_MM_CFG;
806 else
807 reg2->reg = NHMEX_M1_MSR_PMU_MM_CFG;
808 }
809 return 0;
810}
811
812static u64 nhmex_mbox_shared_reg_config(struct intel_uncore_box *box, int idx)
813{
814 struct intel_uncore_extra_reg *er;
815 unsigned long flags;
816 u64 config;
817
818 if (idx < EXTRA_REG_NHMEX_M_ZDP_CTL_FVC)
819 return box->shared_regs[idx].config;
820
821 er = &box->shared_regs[EXTRA_REG_NHMEX_M_ZDP_CTL_FVC];
822 raw_spin_lock_irqsave(&er->lock, flags);
823 config = er->config;
824 raw_spin_unlock_irqrestore(&er->lock, flags);
825 return config;
826}
827
828static void nhmex_mbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
829{
830 struct hw_perf_event *hwc = &event->hw;
831 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
832 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
833 int idx;
834
835 idx = __BITS_VALUE(reg1->idx, 0, 8);
836 if (idx != 0xff)
837 wrmsrl(__BITS_VALUE(reg1->reg, 0, 16),
838 nhmex_mbox_shared_reg_config(box, idx));
839 idx = __BITS_VALUE(reg1->idx, 1, 8);
840 if (idx != 0xff)
841 wrmsrl(__BITS_VALUE(reg1->reg, 1, 16),
842 nhmex_mbox_shared_reg_config(box, idx));
843
844 if (reg2->idx != EXTRA_REG_NONE) {
845 wrmsrl(reg2->reg, 0);
846 if (reg2->config != ~0ULL) {
847 wrmsrl(reg2->reg + 1,
848 reg2->config & NHMEX_M_PMON_ADDR_MATCH_MASK);
849 wrmsrl(reg2->reg + 2, NHMEX_M_PMON_ADDR_MASK_MASK &
850 (reg2->config >> NHMEX_M_PMON_ADDR_MASK_SHIFT));
851 wrmsrl(reg2->reg, NHMEX_M_PMON_MM_CFG_EN);
852 }
853 }
854
855 wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT0);
856}
857
858DEFINE_UNCORE_FORMAT_ATTR(count_mode, count_mode, "config:2-3");
859DEFINE_UNCORE_FORMAT_ATTR(storage_mode, storage_mode, "config:4-5");
860DEFINE_UNCORE_FORMAT_ATTR(wrap_mode, wrap_mode, "config:6");
861DEFINE_UNCORE_FORMAT_ATTR(flag_mode, flag_mode, "config:7");
862DEFINE_UNCORE_FORMAT_ATTR(inc_sel, inc_sel, "config:9-13");
863DEFINE_UNCORE_FORMAT_ATTR(set_flag_sel, set_flag_sel, "config:19-21");
864DEFINE_UNCORE_FORMAT_ATTR(filter_cfg_en, filter_cfg_en, "config2:63");
865DEFINE_UNCORE_FORMAT_ATTR(filter_match, filter_match, "config2:0-33");
866DEFINE_UNCORE_FORMAT_ATTR(filter_mask, filter_mask, "config2:34-61");
867DEFINE_UNCORE_FORMAT_ATTR(dsp, dsp, "config1:0-31");
868DEFINE_UNCORE_FORMAT_ATTR(thr, thr, "config1:0-31");
869DEFINE_UNCORE_FORMAT_ATTR(fvc, fvc, "config1:0-31");
870DEFINE_UNCORE_FORMAT_ATTR(pgt, pgt, "config1:0-31");
871DEFINE_UNCORE_FORMAT_ATTR(map, map, "config1:0-31");
872DEFINE_UNCORE_FORMAT_ATTR(iss, iss, "config1:0-31");
873DEFINE_UNCORE_FORMAT_ATTR(pld, pld, "config1:32-63");
874
875static struct attribute *nhmex_uncore_mbox_formats_attr[] = {
876 &format_attr_count_mode.attr,
877 &format_attr_storage_mode.attr,
878 &format_attr_wrap_mode.attr,
879 &format_attr_flag_mode.attr,
880 &format_attr_inc_sel.attr,
881 &format_attr_set_flag_sel.attr,
882 &format_attr_filter_cfg_en.attr,
883 &format_attr_filter_match.attr,
884 &format_attr_filter_mask.attr,
885 &format_attr_dsp.attr,
886 &format_attr_thr.attr,
887 &format_attr_fvc.attr,
888 &format_attr_pgt.attr,
889 &format_attr_map.attr,
890 &format_attr_iss.attr,
891 &format_attr_pld.attr,
892 NULL,
893};
894
895static struct attribute_group nhmex_uncore_mbox_format_group = {
896 .name = "format",
897 .attrs = nhmex_uncore_mbox_formats_attr,
898};
899
900static struct uncore_event_desc nhmex_uncore_mbox_events[] = {
901 INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x2800"),
902 INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x2820"),
903 { /* end: all zeroes */ },
904};
905
906static struct uncore_event_desc wsmex_uncore_mbox_events[] = {
907 INTEL_UNCORE_EVENT_DESC(bbox_cmds_read, "inc_sel=0xd,fvc=0x5000"),
908 INTEL_UNCORE_EVENT_DESC(bbox_cmds_write, "inc_sel=0xd,fvc=0x5040"),
909 { /* end: all zeroes */ },
910};
911
912static struct intel_uncore_ops nhmex_uncore_mbox_ops = {
913 NHMEX_UNCORE_OPS_COMMON_INIT(),
914 .enable_event = nhmex_mbox_msr_enable_event,
915 .hw_config = nhmex_mbox_hw_config,
916 .get_constraint = nhmex_mbox_get_constraint,
917 .put_constraint = nhmex_mbox_put_constraint,
918};
919
920static struct intel_uncore_type nhmex_uncore_mbox = {
921 .name = "mbox",
922 .num_counters = 6,
923 .num_boxes = 2,
924 .perf_ctr_bits = 48,
925 .event_ctl = NHMEX_M0_MSR_PMU_CTL0,
926 .perf_ctr = NHMEX_M0_MSR_PMU_CNT0,
927 .event_mask = NHMEX_M_PMON_RAW_EVENT_MASK,
928 .box_ctl = NHMEX_M0_MSR_GLOBAL_CTL,
929 .msr_offset = NHMEX_M_MSR_OFFSET,
930 .pair_ctr_ctl = 1,
931 .num_shared_regs = 8,
932 .event_descs = nhmex_uncore_mbox_events,
933 .ops = &nhmex_uncore_mbox_ops,
934 .format_group = &nhmex_uncore_mbox_format_group,
935};
936
937static void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
938{
939 struct hw_perf_event *hwc = &event->hw;
940 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
941
942 /* adjust the main event selector and extra register index */
943 if (reg1->idx % 2) {
944 reg1->idx--;
945 hwc->config -= 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
946 } else {
947 reg1->idx++;
948 hwc->config += 1 << NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
949 }
950
951 /* adjust extra register config */
952 switch (reg1->idx % 6) {
953 case 2:
954 /* shift the 8~15 bits to the 0~7 bits */
955 reg1->config >>= 8;
956 break;
957 case 3:
958 /* shift the 0~7 bits to the 8~15 bits */
959 reg1->config <<= 8;
960 break;
961 }
962}
963
964/*
965 * Each rbox has 4 event set which monitor PQI port 0~3 or 4~7.
966 * An event set consists of 6 events, the 3rd and 4th events in
967 * an event set use the same extra register. So an event set uses
968 * 5 extra registers.
969 */
970static struct event_constraint *
971nhmex_rbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
972{
973 struct hw_perf_event *hwc = &event->hw;
974 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
975 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
976 struct intel_uncore_extra_reg *er;
977 unsigned long flags;
978 int idx, er_idx;
979 u64 config1;
980 bool ok = false;
981
982 if (!uncore_box_is_fake(box) && reg1->alloc)
983 return NULL;
984
985 idx = reg1->idx % 6;
986 config1 = reg1->config;
987again:
988 er_idx = idx;
989 /* the 3rd and 4th events use the same extra register */
990 if (er_idx > 2)
991 er_idx--;
992 er_idx += (reg1->idx / 6) * 5;
993
994 er = &box->shared_regs[er_idx];
995 raw_spin_lock_irqsave(&er->lock, flags);
996 if (idx < 2) {
997 if (!atomic_read(&er->ref) || er->config == reg1->config) {
998 atomic_inc(&er->ref);
999 er->config = reg1->config;
1000 ok = true;
1001 }
1002 } else if (idx == 2 || idx == 3) {
1003 /*
1004 * these two events use different fields in a extra register,
1005 * the 0~7 bits and the 8~15 bits respectively.
1006 */
1007 u64 mask = 0xff << ((idx - 2) * 8);
1008 if (!__BITS_VALUE(atomic_read(&er->ref), idx - 2, 8) ||
1009 !((er->config ^ config1) & mask)) {
1010 atomic_add(1 << ((idx - 2) * 8), &er->ref);
1011 er->config &= ~mask;
1012 er->config |= config1 & mask;
1013 ok = true;
1014 }
1015 } else {
1016 if (!atomic_read(&er->ref) ||
1017 (er->config == (hwc->config >> 32) &&
1018 er->config1 == reg1->config &&
1019 er->config2 == reg2->config)) {
1020 atomic_inc(&er->ref);
1021 er->config = (hwc->config >> 32);
1022 er->config1 = reg1->config;
1023 er->config2 = reg2->config;
1024 ok = true;
1025 }
1026 }
1027 raw_spin_unlock_irqrestore(&er->lock, flags);
1028
1029 if (!ok) {
1030 /*
1031 * The Rbox events are always in pairs. The paired
1032 * events are functional identical, but use different
1033 * extra registers. If we failed to take an extra
1034 * register, try the alternative.
1035 */
1036 idx ^= 1;
1037 if (idx != reg1->idx % 6) {
1038 if (idx == 2)
1039 config1 >>= 8;
1040 else if (idx == 3)
1041 config1 <<= 8;
1042 goto again;
1043 }
1044 } else {
1045 if (!uncore_box_is_fake(box)) {
1046 if (idx != reg1->idx % 6)
1047 nhmex_rbox_alter_er(box, event);
1048 reg1->alloc = 1;
1049 }
1050 return NULL;
1051 }
1052 return &uncore_constraint_empty;
1053}
1054
1055static void nhmex_rbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
1056{
1057 struct intel_uncore_extra_reg *er;
1058 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
1059 int idx, er_idx;
1060
1061 if (uncore_box_is_fake(box) || !reg1->alloc)
1062 return;
1063
1064 idx = reg1->idx % 6;
1065 er_idx = idx;
1066 if (er_idx > 2)
1067 er_idx--;
1068 er_idx += (reg1->idx / 6) * 5;
1069
1070 er = &box->shared_regs[er_idx];
1071 if (idx == 2 || idx == 3)
1072 atomic_sub(1 << ((idx - 2) * 8), &er->ref);
1073 else
1074 atomic_dec(&er->ref);
1075
1076 reg1->alloc = 0;
1077}
1078
1079static int nhmex_rbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
1080{
1081 struct hw_perf_event *hwc = &event->hw;
1082 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
1083 struct hw_perf_event_extra *reg2 = &event->hw.branch_reg;
1084 int idx;
1085
1086 idx = (event->hw.config & NHMEX_R_PMON_CTL_EV_SEL_MASK) >>
1087 NHMEX_R_PMON_CTL_EV_SEL_SHIFT;
1088 if (idx >= 0x18)
1089 return -EINVAL;
1090
1091 reg1->idx = idx;
1092 reg1->config = event->attr.config1;
1093
1094 switch (idx % 6) {
1095 case 4:
1096 case 5:
1097 hwc->config |= event->attr.config & (~0ULL << 32);
1098 reg2->config = event->attr.config2;
1099 break;
1100 }
1101 return 0;
1102}
1103
1104static void nhmex_rbox_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
1105{
1106 struct hw_perf_event *hwc = &event->hw;
1107 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
1108 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
1109 int idx, port;
1110
1111 idx = reg1->idx;
1112 port = idx / 6 + box->pmu->pmu_idx * 4;
1113
1114 switch (idx % 6) {
1115 case 0:
1116 wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG0(port), reg1->config);
1117 break;
1118 case 1:
1119 wrmsrl(NHMEX_R_MSR_PORTN_IPERF_CFG1(port), reg1->config);
1120 break;
1121 case 2:
1122 case 3:
1123 wrmsrl(NHMEX_R_MSR_PORTN_QLX_CFG(port),
1124 uncore_shared_reg_config(box, 2 + (idx / 6) * 5));
1125 break;
1126 case 4:
1127 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MM_CFG(port),
1128 hwc->config >> 32);
1129 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MATCH(port), reg1->config);
1130 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET1_MASK(port), reg2->config);
1131 break;
1132 case 5:
1133 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MM_CFG(port),
1134 hwc->config >> 32);
1135 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MATCH(port), reg1->config);
1136 wrmsrl(NHMEX_R_MSR_PORTN_XBR_SET2_MASK(port), reg2->config);
1137 break;
1138 }
1139
1140 wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0 |
1141 (hwc->config & NHMEX_R_PMON_CTL_EV_SEL_MASK));
1142}
1143
1144DEFINE_UNCORE_FORMAT_ATTR(xbr_mm_cfg, xbr_mm_cfg, "config:32-63");
1145DEFINE_UNCORE_FORMAT_ATTR(xbr_match, xbr_match, "config1:0-63");
1146DEFINE_UNCORE_FORMAT_ATTR(xbr_mask, xbr_mask, "config2:0-63");
1147DEFINE_UNCORE_FORMAT_ATTR(qlx_cfg, qlx_cfg, "config1:0-15");
1148DEFINE_UNCORE_FORMAT_ATTR(iperf_cfg, iperf_cfg, "config1:0-31");
1149
1150static struct attribute *nhmex_uncore_rbox_formats_attr[] = {
1151 &format_attr_event5.attr,
1152 &format_attr_xbr_mm_cfg.attr,
1153 &format_attr_xbr_match.attr,
1154 &format_attr_xbr_mask.attr,
1155 &format_attr_qlx_cfg.attr,
1156 &format_attr_iperf_cfg.attr,
1157 NULL,
1158};
1159
1160static struct attribute_group nhmex_uncore_rbox_format_group = {
1161 .name = "format",
1162 .attrs = nhmex_uncore_rbox_formats_attr,
1163};
1164
1165static struct uncore_event_desc nhmex_uncore_rbox_events[] = {
1166 INTEL_UNCORE_EVENT_DESC(qpi0_flit_send, "event=0x0,iperf_cfg=0x80000000"),
1167 INTEL_UNCORE_EVENT_DESC(qpi1_filt_send, "event=0x6,iperf_cfg=0x80000000"),
1168 INTEL_UNCORE_EVENT_DESC(qpi0_idle_filt, "event=0x0,iperf_cfg=0x40000000"),
1169 INTEL_UNCORE_EVENT_DESC(qpi1_idle_filt, "event=0x6,iperf_cfg=0x40000000"),
1170 INTEL_UNCORE_EVENT_DESC(qpi0_date_response, "event=0x0,iperf_cfg=0xc4"),
1171 INTEL_UNCORE_EVENT_DESC(qpi1_date_response, "event=0x6,iperf_cfg=0xc4"),
1172 { /* end: all zeroes */ },
1173};
1174
1175static struct intel_uncore_ops nhmex_uncore_rbox_ops = {
1176 NHMEX_UNCORE_OPS_COMMON_INIT(),
1177 .enable_event = nhmex_rbox_msr_enable_event,
1178 .hw_config = nhmex_rbox_hw_config,
1179 .get_constraint = nhmex_rbox_get_constraint,
1180 .put_constraint = nhmex_rbox_put_constraint,
1181};
1182
1183static struct intel_uncore_type nhmex_uncore_rbox = {
1184 .name = "rbox",
1185 .num_counters = 8,
1186 .num_boxes = 2,
1187 .perf_ctr_bits = 48,
1188 .event_ctl = NHMEX_R_MSR_PMON_CTL0,
1189 .perf_ctr = NHMEX_R_MSR_PMON_CNT0,
1190 .event_mask = NHMEX_R_PMON_RAW_EVENT_MASK,
1191 .box_ctl = NHMEX_R_MSR_GLOBAL_CTL,
1192 .msr_offset = NHMEX_R_MSR_OFFSET,
1193 .pair_ctr_ctl = 1,
1194 .num_shared_regs = 20,
1195 .event_descs = nhmex_uncore_rbox_events,
1196 .ops = &nhmex_uncore_rbox_ops,
1197 .format_group = &nhmex_uncore_rbox_format_group
1198};
1199
1200static struct intel_uncore_type *nhmex_msr_uncores[] = {
1201 &nhmex_uncore_ubox,
1202 &nhmex_uncore_cbox,
1203 &nhmex_uncore_bbox,
1204 &nhmex_uncore_sbox,
1205 &nhmex_uncore_mbox,
1206 &nhmex_uncore_rbox,
1207 &nhmex_uncore_wbox,
1208 NULL,
1209};
1210
1211void nhmex_uncore_cpu_init(void)
1212{
1213 if (boot_cpu_data.x86_model == 46)
1214 uncore_nhmex = true;
1215 else
1216 nhmex_uncore_mbox.event_descs = wsmex_uncore_mbox_events;
1217 if (nhmex_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
1218 nhmex_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
1219 uncore_msr_uncores = nhmex_msr_uncores;
1220}
1221/* end of Nehalem-EX uncore support */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c
new file mode 100644
index 000000000000..3001015b755c
--- /dev/null
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_snb.c
@@ -0,0 +1,636 @@
1/* Nehalem/SandBridge/Haswell uncore support */
2#include "perf_event_intel_uncore.h"
3
4/* SNB event control */
5#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff
6#define SNB_UNC_CTL_UMASK_MASK 0x0000ff00
7#define SNB_UNC_CTL_EDGE_DET (1 << 18)
8#define SNB_UNC_CTL_EN (1 << 22)
9#define SNB_UNC_CTL_INVERT (1 << 23)
10#define SNB_UNC_CTL_CMASK_MASK 0x1f000000
11#define NHM_UNC_CTL_CMASK_MASK 0xff000000
12#define NHM_UNC_FIXED_CTR_CTL_EN (1 << 0)
13
14#define SNB_UNC_RAW_EVENT_MASK (SNB_UNC_CTL_EV_SEL_MASK | \
15 SNB_UNC_CTL_UMASK_MASK | \
16 SNB_UNC_CTL_EDGE_DET | \
17 SNB_UNC_CTL_INVERT | \
18 SNB_UNC_CTL_CMASK_MASK)
19
20#define NHM_UNC_RAW_EVENT_MASK (SNB_UNC_CTL_EV_SEL_MASK | \
21 SNB_UNC_CTL_UMASK_MASK | \
22 SNB_UNC_CTL_EDGE_DET | \
23 SNB_UNC_CTL_INVERT | \
24 NHM_UNC_CTL_CMASK_MASK)
25
26/* SNB global control register */
27#define SNB_UNC_PERF_GLOBAL_CTL 0x391
28#define SNB_UNC_FIXED_CTR_CTRL 0x394
29#define SNB_UNC_FIXED_CTR 0x395
30
31/* SNB uncore global control */
32#define SNB_UNC_GLOBAL_CTL_CORE_ALL ((1 << 4) - 1)
33#define SNB_UNC_GLOBAL_CTL_EN (1 << 29)
34
35/* SNB Cbo register */
36#define SNB_UNC_CBO_0_PERFEVTSEL0 0x700
37#define SNB_UNC_CBO_0_PER_CTR0 0x706
38#define SNB_UNC_CBO_MSR_OFFSET 0x10
39
40/* NHM global control register */
41#define NHM_UNC_PERF_GLOBAL_CTL 0x391
42#define NHM_UNC_FIXED_CTR 0x394
43#define NHM_UNC_FIXED_CTR_CTRL 0x395
44
45/* NHM uncore global control */
46#define NHM_UNC_GLOBAL_CTL_EN_PC_ALL ((1ULL << 8) - 1)
47#define NHM_UNC_GLOBAL_CTL_EN_FC (1ULL << 32)
48
49/* NHM uncore register */
50#define NHM_UNC_PERFEVTSEL0 0x3c0
51#define NHM_UNC_UNCORE_PMC0 0x3b0
52
53DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
54DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
55DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
56DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
57DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28");
58DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31");
59
60/* Sandy Bridge uncore support */
61static void snb_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
62{
63 struct hw_perf_event *hwc = &event->hw;
64
65 if (hwc->idx < UNCORE_PMC_IDX_FIXED)
66 wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
67 else
68 wrmsrl(hwc->config_base, SNB_UNC_CTL_EN);
69}
70
71static void snb_uncore_msr_disable_event(struct intel_uncore_box *box, struct perf_event *event)
72{
73 wrmsrl(event->hw.config_base, 0);
74}
75
76static void snb_uncore_msr_init_box(struct intel_uncore_box *box)
77{
78 if (box->pmu->pmu_idx == 0) {
79 wrmsrl(SNB_UNC_PERF_GLOBAL_CTL,
80 SNB_UNC_GLOBAL_CTL_EN | SNB_UNC_GLOBAL_CTL_CORE_ALL);
81 }
82}
83
84static struct uncore_event_desc snb_uncore_events[] = {
85 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
86 { /* end: all zeroes */ },
87};
88
89static struct attribute *snb_uncore_formats_attr[] = {
90 &format_attr_event.attr,
91 &format_attr_umask.attr,
92 &format_attr_edge.attr,
93 &format_attr_inv.attr,
94 &format_attr_cmask5.attr,
95 NULL,
96};
97
98static struct attribute_group snb_uncore_format_group = {
99 .name = "format",
100 .attrs = snb_uncore_formats_attr,
101};
102
103static struct intel_uncore_ops snb_uncore_msr_ops = {
104 .init_box = snb_uncore_msr_init_box,
105 .disable_event = snb_uncore_msr_disable_event,
106 .enable_event = snb_uncore_msr_enable_event,
107 .read_counter = uncore_msr_read_counter,
108};
109
110static struct event_constraint snb_uncore_cbox_constraints[] = {
111 UNCORE_EVENT_CONSTRAINT(0x80, 0x1),
112 UNCORE_EVENT_CONSTRAINT(0x83, 0x1),
113 EVENT_CONSTRAINT_END
114};
115
116static struct intel_uncore_type snb_uncore_cbox = {
117 .name = "cbox",
118 .num_counters = 2,
119 .num_boxes = 4,
120 .perf_ctr_bits = 44,
121 .fixed_ctr_bits = 48,
122 .perf_ctr = SNB_UNC_CBO_0_PER_CTR0,
123 .event_ctl = SNB_UNC_CBO_0_PERFEVTSEL0,
124 .fixed_ctr = SNB_UNC_FIXED_CTR,
125 .fixed_ctl = SNB_UNC_FIXED_CTR_CTRL,
126 .single_fixed = 1,
127 .event_mask = SNB_UNC_RAW_EVENT_MASK,
128 .msr_offset = SNB_UNC_CBO_MSR_OFFSET,
129 .constraints = snb_uncore_cbox_constraints,
130 .ops = &snb_uncore_msr_ops,
131 .format_group = &snb_uncore_format_group,
132 .event_descs = snb_uncore_events,
133};
134
135static struct intel_uncore_type *snb_msr_uncores[] = {
136 &snb_uncore_cbox,
137 NULL,
138};
139
140void snb_uncore_cpu_init(void)
141{
142 uncore_msr_uncores = snb_msr_uncores;
143 if (snb_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
144 snb_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
145}
146
147enum {
148 SNB_PCI_UNCORE_IMC,
149};
150
151static struct uncore_event_desc snb_uncore_imc_events[] = {
152 INTEL_UNCORE_EVENT_DESC(data_reads, "event=0x01"),
153 INTEL_UNCORE_EVENT_DESC(data_reads.scale, "6.103515625e-5"),
154 INTEL_UNCORE_EVENT_DESC(data_reads.unit, "MiB"),
155
156 INTEL_UNCORE_EVENT_DESC(data_writes, "event=0x02"),
157 INTEL_UNCORE_EVENT_DESC(data_writes.scale, "6.103515625e-5"),
158 INTEL_UNCORE_EVENT_DESC(data_writes.unit, "MiB"),
159
160 { /* end: all zeroes */ },
161};
162
163#define SNB_UNCORE_PCI_IMC_EVENT_MASK 0xff
164#define SNB_UNCORE_PCI_IMC_BAR_OFFSET 0x48
165
166/* page size multiple covering all config regs */
167#define SNB_UNCORE_PCI_IMC_MAP_SIZE 0x6000
168
169#define SNB_UNCORE_PCI_IMC_DATA_READS 0x1
170#define SNB_UNCORE_PCI_IMC_DATA_READS_BASE 0x5050
171#define SNB_UNCORE_PCI_IMC_DATA_WRITES 0x2
172#define SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE 0x5054
173#define SNB_UNCORE_PCI_IMC_CTR_BASE SNB_UNCORE_PCI_IMC_DATA_READS_BASE
174
175static struct attribute *snb_uncore_imc_formats_attr[] = {
176 &format_attr_event.attr,
177 NULL,
178};
179
180static struct attribute_group snb_uncore_imc_format_group = {
181 .name = "format",
182 .attrs = snb_uncore_imc_formats_attr,
183};
184
185static void snb_uncore_imc_init_box(struct intel_uncore_box *box)
186{
187 struct pci_dev *pdev = box->pci_dev;
188 int where = SNB_UNCORE_PCI_IMC_BAR_OFFSET;
189 resource_size_t addr;
190 u32 pci_dword;
191
192 pci_read_config_dword(pdev, where, &pci_dword);
193 addr = pci_dword;
194
195#ifdef CONFIG_PHYS_ADDR_T_64BIT
196 pci_read_config_dword(pdev, where + 4, &pci_dword);
197 addr |= ((resource_size_t)pci_dword << 32);
198#endif
199
200 addr &= ~(PAGE_SIZE - 1);
201
202 box->io_addr = ioremap(addr, SNB_UNCORE_PCI_IMC_MAP_SIZE);
203 box->hrtimer_duration = UNCORE_SNB_IMC_HRTIMER_INTERVAL;
204}
205
206static void snb_uncore_imc_enable_box(struct intel_uncore_box *box)
207{}
208
209static void snb_uncore_imc_disable_box(struct intel_uncore_box *box)
210{}
211
212static void snb_uncore_imc_enable_event(struct intel_uncore_box *box, struct perf_event *event)
213{}
214
215static void snb_uncore_imc_disable_event(struct intel_uncore_box *box, struct perf_event *event)
216{}
217
218static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf_event *event)
219{
220 struct hw_perf_event *hwc = &event->hw;
221
222 return (u64)*(unsigned int *)(box->io_addr + hwc->event_base);
223}
224
225/*
226 * custom event_init() function because we define our own fixed, free
227 * running counters, so we do not want to conflict with generic uncore
228 * logic. Also simplifies processing
229 */
230static int snb_uncore_imc_event_init(struct perf_event *event)
231{
232 struct intel_uncore_pmu *pmu;
233 struct intel_uncore_box *box;
234 struct hw_perf_event *hwc = &event->hw;
235 u64 cfg = event->attr.config & SNB_UNCORE_PCI_IMC_EVENT_MASK;
236 int idx, base;
237
238 if (event->attr.type != event->pmu->type)
239 return -ENOENT;
240
241 pmu = uncore_event_to_pmu(event);
242 /* no device found for this pmu */
243 if (pmu->func_id < 0)
244 return -ENOENT;
245
246 /* Sampling not supported yet */
247 if (hwc->sample_period)
248 return -EINVAL;
249
250 /* unsupported modes and filters */
251 if (event->attr.exclude_user ||
252 event->attr.exclude_kernel ||
253 event->attr.exclude_hv ||
254 event->attr.exclude_idle ||
255 event->attr.exclude_host ||
256 event->attr.exclude_guest ||
257 event->attr.sample_period) /* no sampling */
258 return -EINVAL;
259
260 /*
261 * Place all uncore events for a particular physical package
262 * onto a single cpu
263 */
264 if (event->cpu < 0)
265 return -EINVAL;
266
267 /* check only supported bits are set */
268 if (event->attr.config & ~SNB_UNCORE_PCI_IMC_EVENT_MASK)
269 return -EINVAL;
270
271 box = uncore_pmu_to_box(pmu, event->cpu);
272 if (!box || box->cpu < 0)
273 return -EINVAL;
274
275 event->cpu = box->cpu;
276
277 event->hw.idx = -1;
278 event->hw.last_tag = ~0ULL;
279 event->hw.extra_reg.idx = EXTRA_REG_NONE;
280 event->hw.branch_reg.idx = EXTRA_REG_NONE;
281 /*
282 * check event is known (whitelist, determines counter)
283 */
284 switch (cfg) {
285 case SNB_UNCORE_PCI_IMC_DATA_READS:
286 base = SNB_UNCORE_PCI_IMC_DATA_READS_BASE;
287 idx = UNCORE_PMC_IDX_FIXED;
288 break;
289 case SNB_UNCORE_PCI_IMC_DATA_WRITES:
290 base = SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE;
291 idx = UNCORE_PMC_IDX_FIXED + 1;
292 break;
293 default:
294 return -EINVAL;
295 }
296
297 /* must be done before validate_group */
298 event->hw.event_base = base;
299 event->hw.config = cfg;
300 event->hw.idx = idx;
301
302 /* no group validation needed, we have free running counters */
303
304 return 0;
305}
306
307static int snb_uncore_imc_hw_config(struct intel_uncore_box *box, struct perf_event *event)
308{
309 return 0;
310}
311
312static void snb_uncore_imc_event_start(struct perf_event *event, int flags)
313{
314 struct intel_uncore_box *box = uncore_event_to_box(event);
315 u64 count;
316
317 if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
318 return;
319
320 event->hw.state = 0;
321 box->n_active++;
322
323 list_add_tail(&event->active_entry, &box->active_list);
324
325 count = snb_uncore_imc_read_counter(box, event);
326 local64_set(&event->hw.prev_count, count);
327
328 if (box->n_active == 1)
329 uncore_pmu_start_hrtimer(box);
330}
331
332static void snb_uncore_imc_event_stop(struct perf_event *event, int flags)
333{
334 struct intel_uncore_box *box = uncore_event_to_box(event);
335 struct hw_perf_event *hwc = &event->hw;
336
337 if (!(hwc->state & PERF_HES_STOPPED)) {
338 box->n_active--;
339
340 WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
341 hwc->state |= PERF_HES_STOPPED;
342
343 list_del(&event->active_entry);
344
345 if (box->n_active == 0)
346 uncore_pmu_cancel_hrtimer(box);
347 }
348
349 if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
350 /*
351 * Drain the remaining delta count out of a event
352 * that we are disabling:
353 */
354 uncore_perf_event_update(box, event);
355 hwc->state |= PERF_HES_UPTODATE;
356 }
357}
358
359static int snb_uncore_imc_event_add(struct perf_event *event, int flags)
360{
361 struct intel_uncore_box *box = uncore_event_to_box(event);
362 struct hw_perf_event *hwc = &event->hw;
363
364 if (!box)
365 return -ENODEV;
366
367 hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
368 if (!(flags & PERF_EF_START))
369 hwc->state |= PERF_HES_ARCH;
370
371 snb_uncore_imc_event_start(event, 0);
372
373 box->n_events++;
374
375 return 0;
376}
377
378static void snb_uncore_imc_event_del(struct perf_event *event, int flags)
379{
380 struct intel_uncore_box *box = uncore_event_to_box(event);
381 int i;
382
383 snb_uncore_imc_event_stop(event, PERF_EF_UPDATE);
384
385 for (i = 0; i < box->n_events; i++) {
386 if (event == box->event_list[i]) {
387 --box->n_events;
388 break;
389 }
390 }
391}
392
393static int snb_pci2phy_map_init(int devid)
394{
395 struct pci_dev *dev = NULL;
396 int bus;
397
398 dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, dev);
399 if (!dev)
400 return -ENOTTY;
401
402 bus = dev->bus->number;
403
404 uncore_pcibus_to_physid[bus] = 0;
405
406 pci_dev_put(dev);
407
408 return 0;
409}
410
411static struct pmu snb_uncore_imc_pmu = {
412 .task_ctx_nr = perf_invalid_context,
413 .event_init = snb_uncore_imc_event_init,
414 .add = snb_uncore_imc_event_add,
415 .del = snb_uncore_imc_event_del,
416 .start = snb_uncore_imc_event_start,
417 .stop = snb_uncore_imc_event_stop,
418 .read = uncore_pmu_event_read,
419};
420
421static struct intel_uncore_ops snb_uncore_imc_ops = {
422 .init_box = snb_uncore_imc_init_box,
423 .enable_box = snb_uncore_imc_enable_box,
424 .disable_box = snb_uncore_imc_disable_box,
425 .disable_event = snb_uncore_imc_disable_event,
426 .enable_event = snb_uncore_imc_enable_event,
427 .hw_config = snb_uncore_imc_hw_config,
428 .read_counter = snb_uncore_imc_read_counter,
429};
430
431static struct intel_uncore_type snb_uncore_imc = {
432 .name = "imc",
433 .num_counters = 2,
434 .num_boxes = 1,
435 .fixed_ctr_bits = 32,
436 .fixed_ctr = SNB_UNCORE_PCI_IMC_CTR_BASE,
437 .event_descs = snb_uncore_imc_events,
438 .format_group = &snb_uncore_imc_format_group,
439 .perf_ctr = SNB_UNCORE_PCI_IMC_DATA_READS_BASE,
440 .event_mask = SNB_UNCORE_PCI_IMC_EVENT_MASK,
441 .ops = &snb_uncore_imc_ops,
442 .pmu = &snb_uncore_imc_pmu,
443};
444
445static struct intel_uncore_type *snb_pci_uncores[] = {
446 [SNB_PCI_UNCORE_IMC] = &snb_uncore_imc,
447 NULL,
448};
449
450static const struct pci_device_id snb_uncore_pci_ids[] = {
451 { /* IMC */
452 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SNB_IMC),
453 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
454 },
455 { /* end: all zeroes */ },
456};
457
458static const struct pci_device_id ivb_uncore_pci_ids[] = {
459 { /* IMC */
460 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_IMC),
461 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
462 },
463 { /* IMC */
464 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_E3_IMC),
465 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
466 },
467 { /* end: all zeroes */ },
468};
469
470static const struct pci_device_id hsw_uncore_pci_ids[] = {
471 { /* IMC */
472 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
473 .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
474 },
475 { /* end: all zeroes */ },
476};
477
478static struct pci_driver snb_uncore_pci_driver = {
479 .name = "snb_uncore",
480 .id_table = snb_uncore_pci_ids,
481};
482
483static struct pci_driver ivb_uncore_pci_driver = {
484 .name = "ivb_uncore",
485 .id_table = ivb_uncore_pci_ids,
486};
487
488static struct pci_driver hsw_uncore_pci_driver = {
489 .name = "hsw_uncore",
490 .id_table = hsw_uncore_pci_ids,
491};
492
493struct imc_uncore_pci_dev {
494 __u32 pci_id;
495 struct pci_driver *driver;
496};
497#define IMC_DEV(a, d) \
498 { .pci_id = PCI_DEVICE_ID_INTEL_##a, .driver = (d) }
499
500static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
501 IMC_DEV(SNB_IMC, &snb_uncore_pci_driver),
502 IMC_DEV(IVB_IMC, &ivb_uncore_pci_driver), /* 3rd Gen Core processor */
503 IMC_DEV(IVB_E3_IMC, &ivb_uncore_pci_driver), /* Xeon E3-1200 v2/3rd Gen Core processor */
504 IMC_DEV(HSW_IMC, &hsw_uncore_pci_driver), /* 4th Gen Core Processor */
505 { /* end marker */ }
506};
507
508
509#define for_each_imc_pci_id(x, t) \
510 for (x = (t); (x)->pci_id; x++)
511
512static struct pci_driver *imc_uncore_find_dev(void)
513{
514 const struct imc_uncore_pci_dev *p;
515 int ret;
516
517 for_each_imc_pci_id(p, desktop_imc_pci_ids) {
518 ret = snb_pci2phy_map_init(p->pci_id);
519 if (ret == 0)
520 return p->driver;
521 }
522 return NULL;
523}
524
525static int imc_uncore_pci_init(void)
526{
527 struct pci_driver *imc_drv = imc_uncore_find_dev();
528
529 if (!imc_drv)
530 return -ENODEV;
531
532 uncore_pci_uncores = snb_pci_uncores;
533 uncore_pci_driver = imc_drv;
534
535 return 0;
536}
537
538int snb_uncore_pci_init(void)
539{
540 return imc_uncore_pci_init();
541}
542
543int ivb_uncore_pci_init(void)
544{
545 return imc_uncore_pci_init();
546}
547int hsw_uncore_pci_init(void)
548{
549 return imc_uncore_pci_init();
550}
551
552/* end of Sandy Bridge uncore support */
553
554/* Nehalem uncore support */
555static void nhm_uncore_msr_disable_box(struct intel_uncore_box *box)
556{
557 wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, 0);
558}
559
560static void nhm_uncore_msr_enable_box(struct intel_uncore_box *box)
561{
562 wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, NHM_UNC_GLOBAL_CTL_EN_PC_ALL | NHM_UNC_GLOBAL_CTL_EN_FC);
563}
564
565static void nhm_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
566{
567 struct hw_perf_event *hwc = &event->hw;
568
569 if (hwc->idx < UNCORE_PMC_IDX_FIXED)
570 wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
571 else
572 wrmsrl(hwc->config_base, NHM_UNC_FIXED_CTR_CTL_EN);
573}
574
575static struct attribute *nhm_uncore_formats_attr[] = {
576 &format_attr_event.attr,
577 &format_attr_umask.attr,
578 &format_attr_edge.attr,
579 &format_attr_inv.attr,
580 &format_attr_cmask8.attr,
581 NULL,
582};
583
584static struct attribute_group nhm_uncore_format_group = {
585 .name = "format",
586 .attrs = nhm_uncore_formats_attr,
587};
588
589static struct uncore_event_desc nhm_uncore_events[] = {
590 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
591 INTEL_UNCORE_EVENT_DESC(qmc_writes_full_any, "event=0x2f,umask=0x0f"),
592 INTEL_UNCORE_EVENT_DESC(qmc_normal_reads_any, "event=0x2c,umask=0x0f"),
593 INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_reads, "event=0x20,umask=0x01"),
594 INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_writes, "event=0x20,umask=0x02"),
595 INTEL_UNCORE_EVENT_DESC(qhl_request_remote_reads, "event=0x20,umask=0x04"),
596 INTEL_UNCORE_EVENT_DESC(qhl_request_remote_writes, "event=0x20,umask=0x08"),
597 INTEL_UNCORE_EVENT_DESC(qhl_request_local_reads, "event=0x20,umask=0x10"),
598 INTEL_UNCORE_EVENT_DESC(qhl_request_local_writes, "event=0x20,umask=0x20"),
599 { /* end: all zeroes */ },
600};
601
602static struct intel_uncore_ops nhm_uncore_msr_ops = {
603 .disable_box = nhm_uncore_msr_disable_box,
604 .enable_box = nhm_uncore_msr_enable_box,
605 .disable_event = snb_uncore_msr_disable_event,
606 .enable_event = nhm_uncore_msr_enable_event,
607 .read_counter = uncore_msr_read_counter,
608};
609
610static struct intel_uncore_type nhm_uncore = {
611 .name = "",
612 .num_counters = 8,
613 .num_boxes = 1,
614 .perf_ctr_bits = 48,
615 .fixed_ctr_bits = 48,
616 .event_ctl = NHM_UNC_PERFEVTSEL0,
617 .perf_ctr = NHM_UNC_UNCORE_PMC0,
618 .fixed_ctr = NHM_UNC_FIXED_CTR,
619 .fixed_ctl = NHM_UNC_FIXED_CTR_CTRL,
620 .event_mask = NHM_UNC_RAW_EVENT_MASK,
621 .event_descs = nhm_uncore_events,
622 .ops = &nhm_uncore_msr_ops,
623 .format_group = &nhm_uncore_format_group,
624};
625
626static struct intel_uncore_type *nhm_msr_uncores[] = {
627 &nhm_uncore,
628 NULL,
629};
630
631void nhm_uncore_cpu_init(void)
632{
633 uncore_msr_uncores = nhm_msr_uncores;
634}
635
636/* end of Nehalem uncore support */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
new file mode 100644
index 000000000000..adf138eac85c
--- /dev/null
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_snbep.c
@@ -0,0 +1,2258 @@
1/* SandyBridge-EP/IvyTown uncore support */
2#include "perf_event_intel_uncore.h"
3
4
5/* SNB-EP Box level control */
6#define SNBEP_PMON_BOX_CTL_RST_CTRL (1 << 0)
7#define SNBEP_PMON_BOX_CTL_RST_CTRS (1 << 1)
8#define SNBEP_PMON_BOX_CTL_FRZ (1 << 8)
9#define SNBEP_PMON_BOX_CTL_FRZ_EN (1 << 16)
10#define SNBEP_PMON_BOX_CTL_INT (SNBEP_PMON_BOX_CTL_RST_CTRL | \
11 SNBEP_PMON_BOX_CTL_RST_CTRS | \
12 SNBEP_PMON_BOX_CTL_FRZ_EN)
13/* SNB-EP event control */
14#define SNBEP_PMON_CTL_EV_SEL_MASK 0x000000ff
15#define SNBEP_PMON_CTL_UMASK_MASK 0x0000ff00
16#define SNBEP_PMON_CTL_RST (1 << 17)
17#define SNBEP_PMON_CTL_EDGE_DET (1 << 18)
18#define SNBEP_PMON_CTL_EV_SEL_EXT (1 << 21)
19#define SNBEP_PMON_CTL_EN (1 << 22)
20#define SNBEP_PMON_CTL_INVERT (1 << 23)
21#define SNBEP_PMON_CTL_TRESH_MASK 0xff000000
22#define SNBEP_PMON_RAW_EVENT_MASK (SNBEP_PMON_CTL_EV_SEL_MASK | \
23 SNBEP_PMON_CTL_UMASK_MASK | \
24 SNBEP_PMON_CTL_EDGE_DET | \
25 SNBEP_PMON_CTL_INVERT | \
26 SNBEP_PMON_CTL_TRESH_MASK)
27
28/* SNB-EP Ubox event control */
29#define SNBEP_U_MSR_PMON_CTL_TRESH_MASK 0x1f000000
30#define SNBEP_U_MSR_PMON_RAW_EVENT_MASK \
31 (SNBEP_PMON_CTL_EV_SEL_MASK | \
32 SNBEP_PMON_CTL_UMASK_MASK | \
33 SNBEP_PMON_CTL_EDGE_DET | \
34 SNBEP_PMON_CTL_INVERT | \
35 SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
36
37#define SNBEP_CBO_PMON_CTL_TID_EN (1 << 19)
38#define SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK (SNBEP_PMON_RAW_EVENT_MASK | \
39 SNBEP_CBO_PMON_CTL_TID_EN)
40
41/* SNB-EP PCU event control */
42#define SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK 0x0000c000
43#define SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK 0x1f000000
44#define SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT (1 << 30)
45#define SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET (1 << 31)
46#define SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK \
47 (SNBEP_PMON_CTL_EV_SEL_MASK | \
48 SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
49 SNBEP_PMON_CTL_EDGE_DET | \
50 SNBEP_PMON_CTL_EV_SEL_EXT | \
51 SNBEP_PMON_CTL_INVERT | \
52 SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
53 SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
54 SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
55
56#define SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK \
57 (SNBEP_PMON_RAW_EVENT_MASK | \
58 SNBEP_PMON_CTL_EV_SEL_EXT)
59
60/* SNB-EP pci control register */
61#define SNBEP_PCI_PMON_BOX_CTL 0xf4
62#define SNBEP_PCI_PMON_CTL0 0xd8
63/* SNB-EP pci counter register */
64#define SNBEP_PCI_PMON_CTR0 0xa0
65
66/* SNB-EP home agent register */
67#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH0 0x40
68#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH1 0x44
69#define SNBEP_HA_PCI_PMON_BOX_OPCODEMATCH 0x48
70/* SNB-EP memory controller register */
71#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTL 0xf0
72#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTR 0xd0
73/* SNB-EP QPI register */
74#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH0 0x228
75#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH1 0x22c
76#define SNBEP_Q_Py_PCI_PMON_PKT_MASK0 0x238
77#define SNBEP_Q_Py_PCI_PMON_PKT_MASK1 0x23c
78
79/* SNB-EP Ubox register */
80#define SNBEP_U_MSR_PMON_CTR0 0xc16
81#define SNBEP_U_MSR_PMON_CTL0 0xc10
82
83#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTL 0xc08
84#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTR 0xc09
85
86/* SNB-EP Cbo register */
87#define SNBEP_C0_MSR_PMON_CTR0 0xd16
88#define SNBEP_C0_MSR_PMON_CTL0 0xd10
89#define SNBEP_C0_MSR_PMON_BOX_CTL 0xd04
90#define SNBEP_C0_MSR_PMON_BOX_FILTER 0xd14
91#define SNBEP_CBO_MSR_OFFSET 0x20
92
93#define SNBEP_CB0_MSR_PMON_BOX_FILTER_TID 0x1f
94#define SNBEP_CB0_MSR_PMON_BOX_FILTER_NID 0x3fc00
95#define SNBEP_CB0_MSR_PMON_BOX_FILTER_STATE 0x7c0000
96#define SNBEP_CB0_MSR_PMON_BOX_FILTER_OPC 0xff800000
97
98#define SNBEP_CBO_EVENT_EXTRA_REG(e, m, i) { \
99 .event = (e), \
100 .msr = SNBEP_C0_MSR_PMON_BOX_FILTER, \
101 .config_mask = (m), \
102 .idx = (i) \
103}
104
105/* SNB-EP PCU register */
106#define SNBEP_PCU_MSR_PMON_CTR0 0xc36
107#define SNBEP_PCU_MSR_PMON_CTL0 0xc30
108#define SNBEP_PCU_MSR_PMON_BOX_CTL 0xc24
109#define SNBEP_PCU_MSR_PMON_BOX_FILTER 0xc34
110#define SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK 0xffffffff
111#define SNBEP_PCU_MSR_CORE_C3_CTR 0x3fc
112#define SNBEP_PCU_MSR_CORE_C6_CTR 0x3fd
113
114/* IVBEP event control */
115#define IVBEP_PMON_BOX_CTL_INT (SNBEP_PMON_BOX_CTL_RST_CTRL | \
116 SNBEP_PMON_BOX_CTL_RST_CTRS)
117#define IVBEP_PMON_RAW_EVENT_MASK (SNBEP_PMON_CTL_EV_SEL_MASK | \
118 SNBEP_PMON_CTL_UMASK_MASK | \
119 SNBEP_PMON_CTL_EDGE_DET | \
120 SNBEP_PMON_CTL_TRESH_MASK)
121/* IVBEP Ubox */
122#define IVBEP_U_MSR_PMON_GLOBAL_CTL 0xc00
123#define IVBEP_U_PMON_GLOBAL_FRZ_ALL (1 << 31)
124#define IVBEP_U_PMON_GLOBAL_UNFRZ_ALL (1 << 29)
125
126#define IVBEP_U_MSR_PMON_RAW_EVENT_MASK \
127 (SNBEP_PMON_CTL_EV_SEL_MASK | \
128 SNBEP_PMON_CTL_UMASK_MASK | \
129 SNBEP_PMON_CTL_EDGE_DET | \
130 SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
131/* IVBEP Cbo */
132#define IVBEP_CBO_MSR_PMON_RAW_EVENT_MASK (IVBEP_PMON_RAW_EVENT_MASK | \
133 SNBEP_CBO_PMON_CTL_TID_EN)
134
135#define IVBEP_CB0_MSR_PMON_BOX_FILTER_TID (0x1fULL << 0)
136#define IVBEP_CB0_MSR_PMON_BOX_FILTER_LINK (0xfULL << 5)
137#define IVBEP_CB0_MSR_PMON_BOX_FILTER_STATE (0x3fULL << 17)
138#define IVBEP_CB0_MSR_PMON_BOX_FILTER_NID (0xffffULL << 32)
139#define IVBEP_CB0_MSR_PMON_BOX_FILTER_OPC (0x1ffULL << 52)
140#define IVBEP_CB0_MSR_PMON_BOX_FILTER_C6 (0x1ULL << 61)
141#define IVBEP_CB0_MSR_PMON_BOX_FILTER_NC (0x1ULL << 62)
142#define IVBEP_CB0_MSR_PMON_BOX_FILTER_ISOC (0x1ULL << 63)
143
144/* IVBEP home agent */
145#define IVBEP_HA_PCI_PMON_CTL_Q_OCC_RST (1 << 16)
146#define IVBEP_HA_PCI_PMON_RAW_EVENT_MASK \
147 (IVBEP_PMON_RAW_EVENT_MASK | \
148 IVBEP_HA_PCI_PMON_CTL_Q_OCC_RST)
149/* IVBEP PCU */
150#define IVBEP_PCU_MSR_PMON_RAW_EVENT_MASK \
151 (SNBEP_PMON_CTL_EV_SEL_MASK | \
152 SNBEP_PMON_CTL_EV_SEL_EXT | \
153 SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
154 SNBEP_PMON_CTL_EDGE_DET | \
155 SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
156 SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
157 SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
158/* IVBEP QPI */
159#define IVBEP_QPI_PCI_PMON_RAW_EVENT_MASK \
160 (IVBEP_PMON_RAW_EVENT_MASK | \
161 SNBEP_PMON_CTL_EV_SEL_EXT)
162
163#define __BITS_VALUE(x, i, n) ((typeof(x))(((x) >> ((i) * (n))) & \
164 ((1ULL << (n)) - 1)))
165
166/* Haswell-EP Ubox */
167#define HSWEP_U_MSR_PMON_CTR0 0x705
168#define HSWEP_U_MSR_PMON_CTL0 0x709
169#define HSWEP_U_MSR_PMON_FILTER 0x707
170
171#define HSWEP_U_MSR_PMON_UCLK_FIXED_CTL 0x703
172#define HSWEP_U_MSR_PMON_UCLK_FIXED_CTR 0x704
173
174#define HSWEP_U_MSR_PMON_BOX_FILTER_TID (0x1 << 0)
175#define HSWEP_U_MSR_PMON_BOX_FILTER_CID (0x1fULL << 1)
176#define HSWEP_U_MSR_PMON_BOX_FILTER_MASK \
177 (HSWEP_U_MSR_PMON_BOX_FILTER_TID | \
178 HSWEP_U_MSR_PMON_BOX_FILTER_CID)
179
180/* Haswell-EP CBo */
181#define HSWEP_C0_MSR_PMON_CTR0 0xe08
182#define HSWEP_C0_MSR_PMON_CTL0 0xe01
183#define HSWEP_C0_MSR_PMON_BOX_CTL 0xe00
184#define HSWEP_C0_MSR_PMON_BOX_FILTER0 0xe05
185#define HSWEP_CBO_MSR_OFFSET 0x10
186
187
188#define HSWEP_CB0_MSR_PMON_BOX_FILTER_TID (0x3fULL << 0)
189#define HSWEP_CB0_MSR_PMON_BOX_FILTER_LINK (0xfULL << 6)
190#define HSWEP_CB0_MSR_PMON_BOX_FILTER_STATE (0x7fULL << 17)
191#define HSWEP_CB0_MSR_PMON_BOX_FILTER_NID (0xffffULL << 32)
192#define HSWEP_CB0_MSR_PMON_BOX_FILTER_OPC (0x1ffULL << 52)
193#define HSWEP_CB0_MSR_PMON_BOX_FILTER_C6 (0x1ULL << 61)
194#define HSWEP_CB0_MSR_PMON_BOX_FILTER_NC (0x1ULL << 62)
195#define HSWEP_CB0_MSR_PMON_BOX_FILTER_ISOC (0x1ULL << 63)
196
197
198/* Haswell-EP Sbox */
199#define HSWEP_S0_MSR_PMON_CTR0 0x726
200#define HSWEP_S0_MSR_PMON_CTL0 0x721
201#define HSWEP_S0_MSR_PMON_BOX_CTL 0x720
202#define HSWEP_SBOX_MSR_OFFSET 0xa
203#define HSWEP_S_MSR_PMON_RAW_EVENT_MASK (SNBEP_PMON_RAW_EVENT_MASK | \
204 SNBEP_CBO_PMON_CTL_TID_EN)
205
206/* Haswell-EP PCU */
207#define HSWEP_PCU_MSR_PMON_CTR0 0x717
208#define HSWEP_PCU_MSR_PMON_CTL0 0x711
209#define HSWEP_PCU_MSR_PMON_BOX_CTL 0x710
210#define HSWEP_PCU_MSR_PMON_BOX_FILTER 0x715
211
212
213DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
214DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21");
215DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
216DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
217DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19");
218DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
219DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
220DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28");
221DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15");
222DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30");
223DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51");
224DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4");
225DEFINE_UNCORE_FORMAT_ATTR(filter_tid2, filter_tid, "config1:0");
226DEFINE_UNCORE_FORMAT_ATTR(filter_tid3, filter_tid, "config1:0-5");
227DEFINE_UNCORE_FORMAT_ATTR(filter_cid, filter_cid, "config1:5");
228DEFINE_UNCORE_FORMAT_ATTR(filter_link, filter_link, "config1:5-8");
229DEFINE_UNCORE_FORMAT_ATTR(filter_link2, filter_link, "config1:6-8");
230DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17");
231DEFINE_UNCORE_FORMAT_ATTR(filter_nid2, filter_nid, "config1:32-47");
232DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22");
233DEFINE_UNCORE_FORMAT_ATTR(filter_state2, filter_state, "config1:17-22");
234DEFINE_UNCORE_FORMAT_ATTR(filter_state3, filter_state, "config1:17-23");
235DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31");
236DEFINE_UNCORE_FORMAT_ATTR(filter_opc2, filter_opc, "config1:52-60");
237DEFINE_UNCORE_FORMAT_ATTR(filter_nc, filter_nc, "config1:62");
238DEFINE_UNCORE_FORMAT_ATTR(filter_c6, filter_c6, "config1:61");
239DEFINE_UNCORE_FORMAT_ATTR(filter_isoc, filter_isoc, "config1:63");
240DEFINE_UNCORE_FORMAT_ATTR(filter_band0, filter_band0, "config1:0-7");
241DEFINE_UNCORE_FORMAT_ATTR(filter_band1, filter_band1, "config1:8-15");
242DEFINE_UNCORE_FORMAT_ATTR(filter_band2, filter_band2, "config1:16-23");
243DEFINE_UNCORE_FORMAT_ATTR(filter_band3, filter_band3, "config1:24-31");
244DEFINE_UNCORE_FORMAT_ATTR(match_rds, match_rds, "config1:48-51");
245DEFINE_UNCORE_FORMAT_ATTR(match_rnid30, match_rnid30, "config1:32-35");
246DEFINE_UNCORE_FORMAT_ATTR(match_rnid4, match_rnid4, "config1:31");
247DEFINE_UNCORE_FORMAT_ATTR(match_dnid, match_dnid, "config1:13-17");
248DEFINE_UNCORE_FORMAT_ATTR(match_mc, match_mc, "config1:9-12");
249DEFINE_UNCORE_FORMAT_ATTR(match_opc, match_opc, "config1:5-8");
250DEFINE_UNCORE_FORMAT_ATTR(match_vnw, match_vnw, "config1:3-4");
251DEFINE_UNCORE_FORMAT_ATTR(match0, match0, "config1:0-31");
252DEFINE_UNCORE_FORMAT_ATTR(match1, match1, "config1:32-63");
253DEFINE_UNCORE_FORMAT_ATTR(mask_rds, mask_rds, "config2:48-51");
254DEFINE_UNCORE_FORMAT_ATTR(mask_rnid30, mask_rnid30, "config2:32-35");
255DEFINE_UNCORE_FORMAT_ATTR(mask_rnid4, mask_rnid4, "config2:31");
256DEFINE_UNCORE_FORMAT_ATTR(mask_dnid, mask_dnid, "config2:13-17");
257DEFINE_UNCORE_FORMAT_ATTR(mask_mc, mask_mc, "config2:9-12");
258DEFINE_UNCORE_FORMAT_ATTR(mask_opc, mask_opc, "config2:5-8");
259DEFINE_UNCORE_FORMAT_ATTR(mask_vnw, mask_vnw, "config2:3-4");
260DEFINE_UNCORE_FORMAT_ATTR(mask0, mask0, "config2:0-31");
261DEFINE_UNCORE_FORMAT_ATTR(mask1, mask1, "config2:32-63");
262
263static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
264{
265 struct pci_dev *pdev = box->pci_dev;
266 int box_ctl = uncore_pci_box_ctl(box);
267 u32 config = 0;
268
269 if (!pci_read_config_dword(pdev, box_ctl, &config)) {
270 config |= SNBEP_PMON_BOX_CTL_FRZ;
271 pci_write_config_dword(pdev, box_ctl, config);
272 }
273}
274
275static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
276{
277 struct pci_dev *pdev = box->pci_dev;
278 int box_ctl = uncore_pci_box_ctl(box);
279 u32 config = 0;
280
281 if (!pci_read_config_dword(pdev, box_ctl, &config)) {
282 config &= ~SNBEP_PMON_BOX_CTL_FRZ;
283 pci_write_config_dword(pdev, box_ctl, config);
284 }
285}
286
287static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event)
288{
289 struct pci_dev *pdev = box->pci_dev;
290 struct hw_perf_event *hwc = &event->hw;
291
292 pci_write_config_dword(pdev, hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
293}
294
295static void snbep_uncore_pci_disable_event(struct intel_uncore_box *box, struct perf_event *event)
296{
297 struct pci_dev *pdev = box->pci_dev;
298 struct hw_perf_event *hwc = &event->hw;
299
300 pci_write_config_dword(pdev, hwc->config_base, hwc->config);
301}
302
303static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct perf_event *event)
304{
305 struct pci_dev *pdev = box->pci_dev;
306 struct hw_perf_event *hwc = &event->hw;
307 u64 count = 0;
308
309 pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
310 pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
311
312 return count;
313}
314
315static void snbep_uncore_pci_init_box(struct intel_uncore_box *box)
316{
317 struct pci_dev *pdev = box->pci_dev;
318
319 pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL, SNBEP_PMON_BOX_CTL_INT);
320}
321
322static void snbep_uncore_msr_disable_box(struct intel_uncore_box *box)
323{
324 u64 config;
325 unsigned msr;
326
327 msr = uncore_msr_box_ctl(box);
328 if (msr) {
329 rdmsrl(msr, config);
330 config |= SNBEP_PMON_BOX_CTL_FRZ;
331 wrmsrl(msr, config);
332 }
333}
334
335static void snbep_uncore_msr_enable_box(struct intel_uncore_box *box)
336{
337 u64 config;
338 unsigned msr;
339
340 msr = uncore_msr_box_ctl(box);
341 if (msr) {
342 rdmsrl(msr, config);
343 config &= ~SNBEP_PMON_BOX_CTL_FRZ;
344 wrmsrl(msr, config);
345 }
346}
347
348static void snbep_uncore_msr_enable_event(struct intel_uncore_box *box, struct perf_event *event)
349{
350 struct hw_perf_event *hwc = &event->hw;
351 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
352
353 if (reg1->idx != EXTRA_REG_NONE)
354 wrmsrl(reg1->reg, uncore_shared_reg_config(box, 0));
355
356 wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
357}
358
359static void snbep_uncore_msr_disable_event(struct intel_uncore_box *box,
360 struct perf_event *event)
361{
362 struct hw_perf_event *hwc = &event->hw;
363
364 wrmsrl(hwc->config_base, hwc->config);
365}
366
367static void snbep_uncore_msr_init_box(struct intel_uncore_box *box)
368{
369 unsigned msr = uncore_msr_box_ctl(box);
370
371 if (msr)
372 wrmsrl(msr, SNBEP_PMON_BOX_CTL_INT);
373}
374
375static struct attribute *snbep_uncore_formats_attr[] = {
376 &format_attr_event.attr,
377 &format_attr_umask.attr,
378 &format_attr_edge.attr,
379 &format_attr_inv.attr,
380 &format_attr_thresh8.attr,
381 NULL,
382};
383
384static struct attribute *snbep_uncore_ubox_formats_attr[] = {
385 &format_attr_event.attr,
386 &format_attr_umask.attr,
387 &format_attr_edge.attr,
388 &format_attr_inv.attr,
389 &format_attr_thresh5.attr,
390 NULL,
391};
392
393static struct attribute *snbep_uncore_cbox_formats_attr[] = {
394 &format_attr_event.attr,
395 &format_attr_umask.attr,
396 &format_attr_edge.attr,
397 &format_attr_tid_en.attr,
398 &format_attr_inv.attr,
399 &format_attr_thresh8.attr,
400 &format_attr_filter_tid.attr,
401 &format_attr_filter_nid.attr,
402 &format_attr_filter_state.attr,
403 &format_attr_filter_opc.attr,
404 NULL,
405};
406
407static struct attribute *snbep_uncore_pcu_formats_attr[] = {
408 &format_attr_event_ext.attr,
409 &format_attr_occ_sel.attr,
410 &format_attr_edge.attr,
411 &format_attr_inv.attr,
412 &format_attr_thresh5.attr,
413 &format_attr_occ_invert.attr,
414 &format_attr_occ_edge.attr,
415 &format_attr_filter_band0.attr,
416 &format_attr_filter_band1.attr,
417 &format_attr_filter_band2.attr,
418 &format_attr_filter_band3.attr,
419 NULL,
420};
421
422static struct attribute *snbep_uncore_qpi_formats_attr[] = {
423 &format_attr_event_ext.attr,
424 &format_attr_umask.attr,
425 &format_attr_edge.attr,
426 &format_attr_inv.attr,
427 &format_attr_thresh8.attr,
428 &format_attr_match_rds.attr,
429 &format_attr_match_rnid30.attr,
430 &format_attr_match_rnid4.attr,
431 &format_attr_match_dnid.attr,
432 &format_attr_match_mc.attr,
433 &format_attr_match_opc.attr,
434 &format_attr_match_vnw.attr,
435 &format_attr_match0.attr,
436 &format_attr_match1.attr,
437 &format_attr_mask_rds.attr,
438 &format_attr_mask_rnid30.attr,
439 &format_attr_mask_rnid4.attr,
440 &format_attr_mask_dnid.attr,
441 &format_attr_mask_mc.attr,
442 &format_attr_mask_opc.attr,
443 &format_attr_mask_vnw.attr,
444 &format_attr_mask0.attr,
445 &format_attr_mask1.attr,
446 NULL,
447};
448
449static struct uncore_event_desc snbep_uncore_imc_events[] = {
450 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
451 INTEL_UNCORE_EVENT_DESC(cas_count_read, "event=0x04,umask=0x03"),
452 INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
453 { /* end: all zeroes */ },
454};
455
456static struct uncore_event_desc snbep_uncore_qpi_events[] = {
457 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0x14"),
458 INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"),
459 INTEL_UNCORE_EVENT_DESC(drs_data, "event=0x102,umask=0x08"),
460 INTEL_UNCORE_EVENT_DESC(ncb_data, "event=0x103,umask=0x04"),
461 { /* end: all zeroes */ },
462};
463
464static struct attribute_group snbep_uncore_format_group = {
465 .name = "format",
466 .attrs = snbep_uncore_formats_attr,
467};
468
469static struct attribute_group snbep_uncore_ubox_format_group = {
470 .name = "format",
471 .attrs = snbep_uncore_ubox_formats_attr,
472};
473
474static struct attribute_group snbep_uncore_cbox_format_group = {
475 .name = "format",
476 .attrs = snbep_uncore_cbox_formats_attr,
477};
478
479static struct attribute_group snbep_uncore_pcu_format_group = {
480 .name = "format",
481 .attrs = snbep_uncore_pcu_formats_attr,
482};
483
484static struct attribute_group snbep_uncore_qpi_format_group = {
485 .name = "format",
486 .attrs = snbep_uncore_qpi_formats_attr,
487};
488
489#define SNBEP_UNCORE_MSR_OPS_COMMON_INIT() \
490 .init_box = snbep_uncore_msr_init_box, \
491 .disable_box = snbep_uncore_msr_disable_box, \
492 .enable_box = snbep_uncore_msr_enable_box, \
493 .disable_event = snbep_uncore_msr_disable_event, \
494 .enable_event = snbep_uncore_msr_enable_event, \
495 .read_counter = uncore_msr_read_counter
496
497static struct intel_uncore_ops snbep_uncore_msr_ops = {
498 SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
499};
500
501#define SNBEP_UNCORE_PCI_OPS_COMMON_INIT() \
502 .init_box = snbep_uncore_pci_init_box, \
503 .disable_box = snbep_uncore_pci_disable_box, \
504 .enable_box = snbep_uncore_pci_enable_box, \
505 .disable_event = snbep_uncore_pci_disable_event, \
506 .read_counter = snbep_uncore_pci_read_counter
507
508static struct intel_uncore_ops snbep_uncore_pci_ops = {
509 SNBEP_UNCORE_PCI_OPS_COMMON_INIT(),
510 .enable_event = snbep_uncore_pci_enable_event, \
511};
512
513static struct event_constraint snbep_uncore_cbox_constraints[] = {
514 UNCORE_EVENT_CONSTRAINT(0x01, 0x1),
515 UNCORE_EVENT_CONSTRAINT(0x02, 0x3),
516 UNCORE_EVENT_CONSTRAINT(0x04, 0x3),
517 UNCORE_EVENT_CONSTRAINT(0x05, 0x3),
518 UNCORE_EVENT_CONSTRAINT(0x07, 0x3),
519 UNCORE_EVENT_CONSTRAINT(0x09, 0x3),
520 UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
521 UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
522 UNCORE_EVENT_CONSTRAINT(0x13, 0x3),
523 UNCORE_EVENT_CONSTRAINT(0x1b, 0xc),
524 UNCORE_EVENT_CONSTRAINT(0x1c, 0xc),
525 UNCORE_EVENT_CONSTRAINT(0x1d, 0xc),
526 UNCORE_EVENT_CONSTRAINT(0x1e, 0xc),
527 EVENT_CONSTRAINT_OVERLAP(0x1f, 0xe, 0xff),
528 UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
529 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
530 UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
531 UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
532 UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
533 UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
534 UNCORE_EVENT_CONSTRAINT(0x35, 0x3),
535 UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
536 UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
537 UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
538 UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
539 UNCORE_EVENT_CONSTRAINT(0x3b, 0x1),
540 EVENT_CONSTRAINT_END
541};
542
543static struct event_constraint snbep_uncore_r2pcie_constraints[] = {
544 UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
545 UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
546 UNCORE_EVENT_CONSTRAINT(0x12, 0x1),
547 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
548 UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
549 UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
550 UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
551 UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
552 UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
553 UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
554 EVENT_CONSTRAINT_END
555};
556
557static struct event_constraint snbep_uncore_r3qpi_constraints[] = {
558 UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
559 UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
560 UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
561 UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
562 UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
563 UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
564 UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
565 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
566 UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
567 UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
568 UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
569 UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
570 UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
571 UNCORE_EVENT_CONSTRAINT(0x2a, 0x3),
572 UNCORE_EVENT_CONSTRAINT(0x2b, 0x3),
573 UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
574 UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
575 UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
576 UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
577 UNCORE_EVENT_CONSTRAINT(0x30, 0x3),
578 UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
579 UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
580 UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
581 UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
582 UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
583 UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
584 UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
585 UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
586 EVENT_CONSTRAINT_END
587};
588
589static struct intel_uncore_type snbep_uncore_ubox = {
590 .name = "ubox",
591 .num_counters = 2,
592 .num_boxes = 1,
593 .perf_ctr_bits = 44,
594 .fixed_ctr_bits = 48,
595 .perf_ctr = SNBEP_U_MSR_PMON_CTR0,
596 .event_ctl = SNBEP_U_MSR_PMON_CTL0,
597 .event_mask = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
598 .fixed_ctr = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
599 .fixed_ctl = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
600 .ops = &snbep_uncore_msr_ops,
601 .format_group = &snbep_uncore_ubox_format_group,
602};
603
604static struct extra_reg snbep_uncore_cbox_extra_regs[] = {
605 SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
606 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
607 SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
608 SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0x6),
609 SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
610 SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0x6),
611 SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
612 SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0x6),
613 SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x6),
614 SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x8),
615 SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x8),
616 SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0xa),
617 SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0xa),
618 SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x2),
619 SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x2),
620 SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x2),
621 SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x2),
622 SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x8),
623 SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x8),
624 SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0xa),
625 SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0xa),
626 SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x2),
627 SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x2),
628 SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x2),
629 SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x2),
630 EVENT_EXTRA_END
631};
632
633static void snbep_cbox_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
634{
635 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
636 struct intel_uncore_extra_reg *er = &box->shared_regs[0];
637 int i;
638
639 if (uncore_box_is_fake(box))
640 return;
641
642 for (i = 0; i < 5; i++) {
643 if (reg1->alloc & (0x1 << i))
644 atomic_sub(1 << (i * 6), &er->ref);
645 }
646 reg1->alloc = 0;
647}
648
649static struct event_constraint *
650__snbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event,
651 u64 (*cbox_filter_mask)(int fields))
652{
653 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
654 struct intel_uncore_extra_reg *er = &box->shared_regs[0];
655 int i, alloc = 0;
656 unsigned long flags;
657 u64 mask;
658
659 if (reg1->idx == EXTRA_REG_NONE)
660 return NULL;
661
662 raw_spin_lock_irqsave(&er->lock, flags);
663 for (i = 0; i < 5; i++) {
664 if (!(reg1->idx & (0x1 << i)))
665 continue;
666 if (!uncore_box_is_fake(box) && (reg1->alloc & (0x1 << i)))
667 continue;
668
669 mask = cbox_filter_mask(0x1 << i);
670 if (!__BITS_VALUE(atomic_read(&er->ref), i, 6) ||
671 !((reg1->config ^ er->config) & mask)) {
672 atomic_add(1 << (i * 6), &er->ref);
673 er->config &= ~mask;
674 er->config |= reg1->config & mask;
675 alloc |= (0x1 << i);
676 } else {
677 break;
678 }
679 }
680 raw_spin_unlock_irqrestore(&er->lock, flags);
681 if (i < 5)
682 goto fail;
683
684 if (!uncore_box_is_fake(box))
685 reg1->alloc |= alloc;
686
687 return NULL;
688fail:
689 for (; i >= 0; i--) {
690 if (alloc & (0x1 << i))
691 atomic_sub(1 << (i * 6), &er->ref);
692 }
693 return &uncore_constraint_empty;
694}
695
696static u64 snbep_cbox_filter_mask(int fields)
697{
698 u64 mask = 0;
699
700 if (fields & 0x1)
701 mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_TID;
702 if (fields & 0x2)
703 mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_NID;
704 if (fields & 0x4)
705 mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_STATE;
706 if (fields & 0x8)
707 mask |= SNBEP_CB0_MSR_PMON_BOX_FILTER_OPC;
708
709 return mask;
710}
711
712static struct event_constraint *
713snbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
714{
715 return __snbep_cbox_get_constraint(box, event, snbep_cbox_filter_mask);
716}
717
718static int snbep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
719{
720 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
721 struct extra_reg *er;
722 int idx = 0;
723
724 for (er = snbep_uncore_cbox_extra_regs; er->msr; er++) {
725 if (er->event != (event->hw.config & er->config_mask))
726 continue;
727 idx |= er->idx;
728 }
729
730 if (idx) {
731 reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
732 SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
733 reg1->config = event->attr.config1 & snbep_cbox_filter_mask(idx);
734 reg1->idx = idx;
735 }
736 return 0;
737}
738
739static struct intel_uncore_ops snbep_uncore_cbox_ops = {
740 SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
741 .hw_config = snbep_cbox_hw_config,
742 .get_constraint = snbep_cbox_get_constraint,
743 .put_constraint = snbep_cbox_put_constraint,
744};
745
746static struct intel_uncore_type snbep_uncore_cbox = {
747 .name = "cbox",
748 .num_counters = 4,
749 .num_boxes = 8,
750 .perf_ctr_bits = 44,
751 .event_ctl = SNBEP_C0_MSR_PMON_CTL0,
752 .perf_ctr = SNBEP_C0_MSR_PMON_CTR0,
753 .event_mask = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
754 .box_ctl = SNBEP_C0_MSR_PMON_BOX_CTL,
755 .msr_offset = SNBEP_CBO_MSR_OFFSET,
756 .num_shared_regs = 1,
757 .constraints = snbep_uncore_cbox_constraints,
758 .ops = &snbep_uncore_cbox_ops,
759 .format_group = &snbep_uncore_cbox_format_group,
760};
761
762static u64 snbep_pcu_alter_er(struct perf_event *event, int new_idx, bool modify)
763{
764 struct hw_perf_event *hwc = &event->hw;
765 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
766 u64 config = reg1->config;
767
768 if (new_idx > reg1->idx)
769 config <<= 8 * (new_idx - reg1->idx);
770 else
771 config >>= 8 * (reg1->idx - new_idx);
772
773 if (modify) {
774 hwc->config += new_idx - reg1->idx;
775 reg1->config = config;
776 reg1->idx = new_idx;
777 }
778 return config;
779}
780
781static struct event_constraint *
782snbep_pcu_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
783{
784 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
785 struct intel_uncore_extra_reg *er = &box->shared_regs[0];
786 unsigned long flags;
787 int idx = reg1->idx;
788 u64 mask, config1 = reg1->config;
789 bool ok = false;
790
791 if (reg1->idx == EXTRA_REG_NONE ||
792 (!uncore_box_is_fake(box) && reg1->alloc))
793 return NULL;
794again:
795 mask = 0xffULL << (idx * 8);
796 raw_spin_lock_irqsave(&er->lock, flags);
797 if (!__BITS_VALUE(atomic_read(&er->ref), idx, 8) ||
798 !((config1 ^ er->config) & mask)) {
799 atomic_add(1 << (idx * 8), &er->ref);
800 er->config &= ~mask;
801 er->config |= config1 & mask;
802 ok = true;
803 }
804 raw_spin_unlock_irqrestore(&er->lock, flags);
805
806 if (!ok) {
807 idx = (idx + 1) % 4;
808 if (idx != reg1->idx) {
809 config1 = snbep_pcu_alter_er(event, idx, false);
810 goto again;
811 }
812 return &uncore_constraint_empty;
813 }
814
815 if (!uncore_box_is_fake(box)) {
816 if (idx != reg1->idx)
817 snbep_pcu_alter_er(event, idx, true);
818 reg1->alloc = 1;
819 }
820 return NULL;
821}
822
823static void snbep_pcu_put_constraint(struct intel_uncore_box *box, struct perf_event *event)
824{
825 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
826 struct intel_uncore_extra_reg *er = &box->shared_regs[0];
827
828 if (uncore_box_is_fake(box) || !reg1->alloc)
829 return;
830
831 atomic_sub(1 << (reg1->idx * 8), &er->ref);
832 reg1->alloc = 0;
833}
834
835static int snbep_pcu_hw_config(struct intel_uncore_box *box, struct perf_event *event)
836{
837 struct hw_perf_event *hwc = &event->hw;
838 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
839 int ev_sel = hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK;
840
841 if (ev_sel >= 0xb && ev_sel <= 0xe) {
842 reg1->reg = SNBEP_PCU_MSR_PMON_BOX_FILTER;
843 reg1->idx = ev_sel - 0xb;
844 reg1->config = event->attr.config1 & (0xff << (reg1->idx * 8));
845 }
846 return 0;
847}
848
849static struct intel_uncore_ops snbep_uncore_pcu_ops = {
850 SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
851 .hw_config = snbep_pcu_hw_config,
852 .get_constraint = snbep_pcu_get_constraint,
853 .put_constraint = snbep_pcu_put_constraint,
854};
855
856static struct intel_uncore_type snbep_uncore_pcu = {
857 .name = "pcu",
858 .num_counters = 4,
859 .num_boxes = 1,
860 .perf_ctr_bits = 48,
861 .perf_ctr = SNBEP_PCU_MSR_PMON_CTR0,
862 .event_ctl = SNBEP_PCU_MSR_PMON_CTL0,
863 .event_mask = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
864 .box_ctl = SNBEP_PCU_MSR_PMON_BOX_CTL,
865 .num_shared_regs = 1,
866 .ops = &snbep_uncore_pcu_ops,
867 .format_group = &snbep_uncore_pcu_format_group,
868};
869
870static struct intel_uncore_type *snbep_msr_uncores[] = {
871 &snbep_uncore_ubox,
872 &snbep_uncore_cbox,
873 &snbep_uncore_pcu,
874 NULL,
875};
876
877void snbep_uncore_cpu_init(void)
878{
879 if (snbep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
880 snbep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
881 uncore_msr_uncores = snbep_msr_uncores;
882}
883
884enum {
885 SNBEP_PCI_QPI_PORT0_FILTER,
886 SNBEP_PCI_QPI_PORT1_FILTER,
887};
888
889static int snbep_qpi_hw_config(struct intel_uncore_box *box, struct perf_event *event)
890{
891 struct hw_perf_event *hwc = &event->hw;
892 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
893 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
894
895 if ((hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK) == 0x38) {
896 reg1->idx = 0;
897 reg1->reg = SNBEP_Q_Py_PCI_PMON_PKT_MATCH0;
898 reg1->config = event->attr.config1;
899 reg2->reg = SNBEP_Q_Py_PCI_PMON_PKT_MASK0;
900 reg2->config = event->attr.config2;
901 }
902 return 0;
903}
904
905static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_event *event)
906{
907 struct pci_dev *pdev = box->pci_dev;
908 struct hw_perf_event *hwc = &event->hw;
909 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
910 struct hw_perf_event_extra *reg2 = &hwc->branch_reg;
911
912 if (reg1->idx != EXTRA_REG_NONE) {
913 int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER;
914 struct pci_dev *filter_pdev = uncore_extra_pci_dev[box->phys_id][idx];
915 if (filter_pdev) {
916 pci_write_config_dword(filter_pdev, reg1->reg,
917 (u32)reg1->config);
918 pci_write_config_dword(filter_pdev, reg1->reg + 4,
919 (u32)(reg1->config >> 32));
920 pci_write_config_dword(filter_pdev, reg2->reg,
921 (u32)reg2->config);
922 pci_write_config_dword(filter_pdev, reg2->reg + 4,
923 (u32)(reg2->config >> 32));
924 }
925 }
926
927 pci_write_config_dword(pdev, hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
928}
929
930static struct intel_uncore_ops snbep_uncore_qpi_ops = {
931 SNBEP_UNCORE_PCI_OPS_COMMON_INIT(),
932 .enable_event = snbep_qpi_enable_event,
933 .hw_config = snbep_qpi_hw_config,
934 .get_constraint = uncore_get_constraint,
935 .put_constraint = uncore_put_constraint,
936};
937
938#define SNBEP_UNCORE_PCI_COMMON_INIT() \
939 .perf_ctr = SNBEP_PCI_PMON_CTR0, \
940 .event_ctl = SNBEP_PCI_PMON_CTL0, \
941 .event_mask = SNBEP_PMON_RAW_EVENT_MASK, \
942 .box_ctl = SNBEP_PCI_PMON_BOX_CTL, \
943 .ops = &snbep_uncore_pci_ops, \
944 .format_group = &snbep_uncore_format_group
945
946static struct intel_uncore_type snbep_uncore_ha = {
947 .name = "ha",
948 .num_counters = 4,
949 .num_boxes = 1,
950 .perf_ctr_bits = 48,
951 SNBEP_UNCORE_PCI_COMMON_INIT(),
952};
953
954static struct intel_uncore_type snbep_uncore_imc = {
955 .name = "imc",
956 .num_counters = 4,
957 .num_boxes = 4,
958 .perf_ctr_bits = 48,
959 .fixed_ctr_bits = 48,
960 .fixed_ctr = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
961 .fixed_ctl = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
962 .event_descs = snbep_uncore_imc_events,
963 SNBEP_UNCORE_PCI_COMMON_INIT(),
964};
965
966static struct intel_uncore_type snbep_uncore_qpi = {
967 .name = "qpi",
968 .num_counters = 4,
969 .num_boxes = 2,
970 .perf_ctr_bits = 48,
971 .perf_ctr = SNBEP_PCI_PMON_CTR0,
972 .event_ctl = SNBEP_PCI_PMON_CTL0,
973 .event_mask = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
974 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
975 .num_shared_regs = 1,
976 .ops = &snbep_uncore_qpi_ops,
977 .event_descs = snbep_uncore_qpi_events,
978 .format_group = &snbep_uncore_qpi_format_group,
979};
980
981
982static struct intel_uncore_type snbep_uncore_r2pcie = {
983 .name = "r2pcie",
984 .num_counters = 4,
985 .num_boxes = 1,
986 .perf_ctr_bits = 44,
987 .constraints = snbep_uncore_r2pcie_constraints,
988 SNBEP_UNCORE_PCI_COMMON_INIT(),
989};
990
991static struct intel_uncore_type snbep_uncore_r3qpi = {
992 .name = "r3qpi",
993 .num_counters = 3,
994 .num_boxes = 2,
995 .perf_ctr_bits = 44,
996 .constraints = snbep_uncore_r3qpi_constraints,
997 SNBEP_UNCORE_PCI_COMMON_INIT(),
998};
999
1000enum {
1001 SNBEP_PCI_UNCORE_HA,
1002 SNBEP_PCI_UNCORE_IMC,
1003 SNBEP_PCI_UNCORE_QPI,
1004 SNBEP_PCI_UNCORE_R2PCIE,
1005 SNBEP_PCI_UNCORE_R3QPI,
1006};
1007
1008static struct intel_uncore_type *snbep_pci_uncores[] = {
1009 [SNBEP_PCI_UNCORE_HA] = &snbep_uncore_ha,
1010 [SNBEP_PCI_UNCORE_IMC] = &snbep_uncore_imc,
1011 [SNBEP_PCI_UNCORE_QPI] = &snbep_uncore_qpi,
1012 [SNBEP_PCI_UNCORE_R2PCIE] = &snbep_uncore_r2pcie,
1013 [SNBEP_PCI_UNCORE_R3QPI] = &snbep_uncore_r3qpi,
1014 NULL,
1015};
1016
1017static const struct pci_device_id snbep_uncore_pci_ids[] = {
1018 { /* Home Agent */
1019 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA),
1020 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_HA, 0),
1021 },
1022 { /* MC Channel 0 */
1023 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC0),
1024 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 0),
1025 },
1026 { /* MC Channel 1 */
1027 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC1),
1028 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 1),
1029 },
1030 { /* MC Channel 2 */
1031 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC2),
1032 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 2),
1033 },
1034 { /* MC Channel 3 */
1035 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC3),
1036 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_IMC, 3),
1037 },
1038 { /* QPI Port 0 */
1039 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI0),
1040 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_QPI, 0),
1041 },
1042 { /* QPI Port 1 */
1043 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI1),
1044 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_QPI, 1),
1045 },
1046 { /* R2PCIe */
1047 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R2PCIE),
1048 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R2PCIE, 0),
1049 },
1050 { /* R3QPI Link 0 */
1051 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI0),
1052 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R3QPI, 0),
1053 },
1054 { /* R3QPI Link 1 */
1055 PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI1),
1056 .driver_data = UNCORE_PCI_DEV_DATA(SNBEP_PCI_UNCORE_R3QPI, 1),
1057 },
1058 { /* QPI Port 0 filter */
1059 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3c86),
1060 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
1061 SNBEP_PCI_QPI_PORT0_FILTER),
1062 },
1063 { /* QPI Port 0 filter */
1064 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3c96),
1065 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
1066 SNBEP_PCI_QPI_PORT1_FILTER),
1067 },
1068 { /* end: all zeroes */ }
1069};
1070
1071static struct pci_driver snbep_uncore_pci_driver = {
1072 .name = "snbep_uncore",
1073 .id_table = snbep_uncore_pci_ids,
1074};
1075
1076/*
1077 * build pci bus to socket mapping
1078 */
1079static int snbep_pci2phy_map_init(int devid)
1080{
1081 struct pci_dev *ubox_dev = NULL;
1082 int i, bus, nodeid;
1083 int err = 0;
1084 u32 config = 0;
1085
1086 while (1) {
1087 /* find the UBOX device */
1088 ubox_dev = pci_get_device(PCI_VENDOR_ID_INTEL, devid, ubox_dev);
1089 if (!ubox_dev)
1090 break;
1091 bus = ubox_dev->bus->number;
1092 /* get the Node ID of the local register */
1093 err = pci_read_config_dword(ubox_dev, 0x40, &config);
1094 if (err)
1095 break;
1096 nodeid = config;
1097 /* get the Node ID mapping */
1098 err = pci_read_config_dword(ubox_dev, 0x54, &config);
1099 if (err)
1100 break;
1101 /*
1102 * every three bits in the Node ID mapping register maps
1103 * to a particular node.
1104 */
1105 for (i = 0; i < 8; i++) {
1106 if (nodeid == ((config >> (3 * i)) & 0x7)) {
1107 uncore_pcibus_to_physid[bus] = i;
1108 break;
1109 }
1110 }
1111 }
1112
1113 if (!err) {
1114 /*
1115 * For PCI bus with no UBOX device, find the next bus
1116 * that has UBOX device and use its mapping.
1117 */
1118 i = -1;
1119 for (bus = 255; bus >= 0; bus--) {
1120 if (uncore_pcibus_to_physid[bus] >= 0)
1121 i = uncore_pcibus_to_physid[bus];
1122 else
1123 uncore_pcibus_to_physid[bus] = i;
1124 }
1125 }
1126
1127 if (ubox_dev)
1128 pci_dev_put(ubox_dev);
1129
1130 return err ? pcibios_err_to_errno(err) : 0;
1131}
1132
1133int snbep_uncore_pci_init(void)
1134{
1135 int ret = snbep_pci2phy_map_init(0x3ce0);
1136 if (ret)
1137 return ret;
1138 uncore_pci_uncores = snbep_pci_uncores;
1139 uncore_pci_driver = &snbep_uncore_pci_driver;
1140 return 0;
1141}
1142/* end of Sandy Bridge-EP uncore support */
1143
1144/* IvyTown uncore support */
1145static void ivbep_uncore_msr_init_box(struct intel_uncore_box *box)
1146{
1147 unsigned msr = uncore_msr_box_ctl(box);
1148 if (msr)
1149 wrmsrl(msr, IVBEP_PMON_BOX_CTL_INT);
1150}
1151
1152static void ivbep_uncore_pci_init_box(struct intel_uncore_box *box)
1153{
1154 struct pci_dev *pdev = box->pci_dev;
1155
1156 pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL, IVBEP_PMON_BOX_CTL_INT);
1157}
1158
1159#define IVBEP_UNCORE_MSR_OPS_COMMON_INIT() \
1160 .init_box = ivbep_uncore_msr_init_box, \
1161 .disable_box = snbep_uncore_msr_disable_box, \
1162 .enable_box = snbep_uncore_msr_enable_box, \
1163 .disable_event = snbep_uncore_msr_disable_event, \
1164 .enable_event = snbep_uncore_msr_enable_event, \
1165 .read_counter = uncore_msr_read_counter
1166
1167static struct intel_uncore_ops ivbep_uncore_msr_ops = {
1168 IVBEP_UNCORE_MSR_OPS_COMMON_INIT(),
1169};
1170
1171static struct intel_uncore_ops ivbep_uncore_pci_ops = {
1172 .init_box = ivbep_uncore_pci_init_box,
1173 .disable_box = snbep_uncore_pci_disable_box,
1174 .enable_box = snbep_uncore_pci_enable_box,
1175 .disable_event = snbep_uncore_pci_disable_event,
1176 .enable_event = snbep_uncore_pci_enable_event,
1177 .read_counter = snbep_uncore_pci_read_counter,
1178};
1179
1180#define IVBEP_UNCORE_PCI_COMMON_INIT() \
1181 .perf_ctr = SNBEP_PCI_PMON_CTR0, \
1182 .event_ctl = SNBEP_PCI_PMON_CTL0, \
1183 .event_mask = IVBEP_PMON_RAW_EVENT_MASK, \
1184 .box_ctl = SNBEP_PCI_PMON_BOX_CTL, \
1185 .ops = &ivbep_uncore_pci_ops, \
1186 .format_group = &ivbep_uncore_format_group
1187
1188static struct attribute *ivbep_uncore_formats_attr[] = {
1189 &format_attr_event.attr,
1190 &format_attr_umask.attr,
1191 &format_attr_edge.attr,
1192 &format_attr_inv.attr,
1193 &format_attr_thresh8.attr,
1194 NULL,
1195};
1196
1197static struct attribute *ivbep_uncore_ubox_formats_attr[] = {
1198 &format_attr_event.attr,
1199 &format_attr_umask.attr,
1200 &format_attr_edge.attr,
1201 &format_attr_inv.attr,
1202 &format_attr_thresh5.attr,
1203 NULL,
1204};
1205
1206static struct attribute *ivbep_uncore_cbox_formats_attr[] = {
1207 &format_attr_event.attr,
1208 &format_attr_umask.attr,
1209 &format_attr_edge.attr,
1210 &format_attr_tid_en.attr,
1211 &format_attr_thresh8.attr,
1212 &format_attr_filter_tid.attr,
1213 &format_attr_filter_link.attr,
1214 &format_attr_filter_state2.attr,
1215 &format_attr_filter_nid2.attr,
1216 &format_attr_filter_opc2.attr,
1217 &format_attr_filter_nc.attr,
1218 &format_attr_filter_c6.attr,
1219 &format_attr_filter_isoc.attr,
1220 NULL,
1221};
1222
1223static struct attribute *ivbep_uncore_pcu_formats_attr[] = {
1224 &format_attr_event_ext.attr,
1225 &format_attr_occ_sel.attr,
1226 &format_attr_edge.attr,
1227 &format_attr_thresh5.attr,
1228 &format_attr_occ_invert.attr,
1229 &format_attr_occ_edge.attr,
1230 &format_attr_filter_band0.attr,
1231 &format_attr_filter_band1.attr,
1232 &format_attr_filter_band2.attr,
1233 &format_attr_filter_band3.attr,
1234 NULL,
1235};
1236
1237static struct attribute *ivbep_uncore_qpi_formats_attr[] = {
1238 &format_attr_event_ext.attr,
1239 &format_attr_umask.attr,
1240 &format_attr_edge.attr,
1241 &format_attr_thresh8.attr,
1242 &format_attr_match_rds.attr,
1243 &format_attr_match_rnid30.attr,
1244 &format_attr_match_rnid4.attr,
1245 &format_attr_match_dnid.attr,
1246 &format_attr_match_mc.attr,
1247 &format_attr_match_opc.attr,
1248 &format_attr_match_vnw.attr,
1249 &format_attr_match0.attr,
1250 &format_attr_match1.attr,
1251 &format_attr_mask_rds.attr,
1252 &format_attr_mask_rnid30.attr,
1253 &format_attr_mask_rnid4.attr,
1254 &format_attr_mask_dnid.attr,
1255 &format_attr_mask_mc.attr,
1256 &format_attr_mask_opc.attr,
1257 &format_attr_mask_vnw.attr,
1258 &format_attr_mask0.attr,
1259 &format_attr_mask1.attr,
1260 NULL,
1261};
1262
1263static struct attribute_group ivbep_uncore_format_group = {
1264 .name = "format",
1265 .attrs = ivbep_uncore_formats_attr,
1266};
1267
1268static struct attribute_group ivbep_uncore_ubox_format_group = {
1269 .name = "format",
1270 .attrs = ivbep_uncore_ubox_formats_attr,
1271};
1272
1273static struct attribute_group ivbep_uncore_cbox_format_group = {
1274 .name = "format",
1275 .attrs = ivbep_uncore_cbox_formats_attr,
1276};
1277
1278static struct attribute_group ivbep_uncore_pcu_format_group = {
1279 .name = "format",
1280 .attrs = ivbep_uncore_pcu_formats_attr,
1281};
1282
1283static struct attribute_group ivbep_uncore_qpi_format_group = {
1284 .name = "format",
1285 .attrs = ivbep_uncore_qpi_formats_attr,
1286};
1287
1288static struct intel_uncore_type ivbep_uncore_ubox = {
1289 .name = "ubox",
1290 .num_counters = 2,
1291 .num_boxes = 1,
1292 .perf_ctr_bits = 44,
1293 .fixed_ctr_bits = 48,
1294 .perf_ctr = SNBEP_U_MSR_PMON_CTR0,
1295 .event_ctl = SNBEP_U_MSR_PMON_CTL0,
1296 .event_mask = IVBEP_U_MSR_PMON_RAW_EVENT_MASK,
1297 .fixed_ctr = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
1298 .fixed_ctl = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
1299 .ops = &ivbep_uncore_msr_ops,
1300 .format_group = &ivbep_uncore_ubox_format_group,
1301};
1302
1303static struct extra_reg ivbep_uncore_cbox_extra_regs[] = {
1304 SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
1305 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
1306 SNBEP_CBO_EVENT_EXTRA_REG(0x1031, 0x10ff, 0x2),
1307 SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
1308 SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0xc),
1309 SNBEP_CBO_EVENT_EXTRA_REG(0x5134, 0xffff, 0xc),
1310 SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
1311 SNBEP_CBO_EVENT_EXTRA_REG(0x4334, 0xffff, 0xc),
1312 SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
1313 SNBEP_CBO_EVENT_EXTRA_REG(0x4534, 0xffff, 0xc),
1314 SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
1315 SNBEP_CBO_EVENT_EXTRA_REG(0x4934, 0xffff, 0xc),
1316 SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x10),
1317 SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
1318 SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
1319 SNBEP_CBO_EVENT_EXTRA_REG(0x2335, 0xffff, 0x10),
1320 SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0x18),
1321 SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0x18),
1322 SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x8),
1323 SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x8),
1324 SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x8),
1325 SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x8),
1326 SNBEP_CBO_EVENT_EXTRA_REG(0x8135, 0xffff, 0x10),
1327 SNBEP_CBO_EVENT_EXTRA_REG(0x8335, 0xffff, 0x10),
1328 SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x10),
1329 SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x10),
1330 SNBEP_CBO_EVENT_EXTRA_REG(0x2136, 0xffff, 0x10),
1331 SNBEP_CBO_EVENT_EXTRA_REG(0x2336, 0xffff, 0x10),
1332 SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0x18),
1333 SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0x18),
1334 SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x8),
1335 SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x8),
1336 SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x8),
1337 SNBEP_CBO_EVENT_EXTRA_REG(0x5036, 0xffff, 0x8),
1338 SNBEP_CBO_EVENT_EXTRA_REG(0x8136, 0xffff, 0x10),
1339 SNBEP_CBO_EVENT_EXTRA_REG(0x8336, 0xffff, 0x10),
1340 SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x8),
1341 EVENT_EXTRA_END
1342};
1343
1344static u64 ivbep_cbox_filter_mask(int fields)
1345{
1346 u64 mask = 0;
1347
1348 if (fields & 0x1)
1349 mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_TID;
1350 if (fields & 0x2)
1351 mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_LINK;
1352 if (fields & 0x4)
1353 mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_STATE;
1354 if (fields & 0x8)
1355 mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_NID;
1356 if (fields & 0x10) {
1357 mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_OPC;
1358 mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_NC;
1359 mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_C6;
1360 mask |= IVBEP_CB0_MSR_PMON_BOX_FILTER_ISOC;
1361 }
1362
1363 return mask;
1364}
1365
1366static struct event_constraint *
1367ivbep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
1368{
1369 return __snbep_cbox_get_constraint(box, event, ivbep_cbox_filter_mask);
1370}
1371
1372static int ivbep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
1373{
1374 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
1375 struct extra_reg *er;
1376 int idx = 0;
1377
1378 for (er = ivbep_uncore_cbox_extra_regs; er->msr; er++) {
1379 if (er->event != (event->hw.config & er->config_mask))
1380 continue;
1381 idx |= er->idx;
1382 }
1383
1384 if (idx) {
1385 reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
1386 SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
1387 reg1->config = event->attr.config1 & ivbep_cbox_filter_mask(idx);
1388 reg1->idx = idx;
1389 }
1390 return 0;
1391}
1392
1393static void ivbep_cbox_enable_event(struct intel_uncore_box *box, struct perf_event *event)
1394{
1395 struct hw_perf_event *hwc = &event->hw;
1396 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
1397
1398 if (reg1->idx != EXTRA_REG_NONE) {
1399 u64 filter = uncore_shared_reg_config(box, 0);
1400 wrmsrl(reg1->reg, filter & 0xffffffff);
1401 wrmsrl(reg1->reg + 6, filter >> 32);
1402 }
1403
1404 wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
1405}
1406
1407static struct intel_uncore_ops ivbep_uncore_cbox_ops = {
1408 .init_box = ivbep_uncore_msr_init_box,
1409 .disable_box = snbep_uncore_msr_disable_box,
1410 .enable_box = snbep_uncore_msr_enable_box,
1411 .disable_event = snbep_uncore_msr_disable_event,
1412 .enable_event = ivbep_cbox_enable_event,
1413 .read_counter = uncore_msr_read_counter,
1414 .hw_config = ivbep_cbox_hw_config,
1415 .get_constraint = ivbep_cbox_get_constraint,
1416 .put_constraint = snbep_cbox_put_constraint,
1417};
1418
1419static struct intel_uncore_type ivbep_uncore_cbox = {
1420 .name = "cbox",
1421 .num_counters = 4,
1422 .num_boxes = 15,
1423 .perf_ctr_bits = 44,
1424 .event_ctl = SNBEP_C0_MSR_PMON_CTL0,
1425 .perf_ctr = SNBEP_C0_MSR_PMON_CTR0,
1426 .event_mask = IVBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
1427 .box_ctl = SNBEP_C0_MSR_PMON_BOX_CTL,
1428 .msr_offset = SNBEP_CBO_MSR_OFFSET,
1429 .num_shared_regs = 1,
1430 .constraints = snbep_uncore_cbox_constraints,
1431 .ops = &ivbep_uncore_cbox_ops,
1432 .format_group = &ivbep_uncore_cbox_format_group,
1433};
1434
1435static struct intel_uncore_ops ivbep_uncore_pcu_ops = {
1436 IVBEP_UNCORE_MSR_OPS_COMMON_INIT(),
1437 .hw_config = snbep_pcu_hw_config,
1438 .get_constraint = snbep_pcu_get_constraint,
1439 .put_constraint = snbep_pcu_put_constraint,
1440};
1441
1442static struct intel_uncore_type ivbep_uncore_pcu = {
1443 .name = "pcu",
1444 .num_counters = 4,
1445 .num_boxes = 1,
1446 .perf_ctr_bits = 48,
1447 .perf_ctr = SNBEP_PCU_MSR_PMON_CTR0,
1448 .event_ctl = SNBEP_PCU_MSR_PMON_CTL0,
1449 .event_mask = IVBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
1450 .box_ctl = SNBEP_PCU_MSR_PMON_BOX_CTL,
1451 .num_shared_regs = 1,
1452 .ops = &ivbep_uncore_pcu_ops,
1453 .format_group = &ivbep_uncore_pcu_format_group,
1454};
1455
1456static struct intel_uncore_type *ivbep_msr_uncores[] = {
1457 &ivbep_uncore_ubox,
1458 &ivbep_uncore_cbox,
1459 &ivbep_uncore_pcu,
1460 NULL,
1461};
1462
1463void ivbep_uncore_cpu_init(void)
1464{
1465 if (ivbep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
1466 ivbep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
1467 uncore_msr_uncores = ivbep_msr_uncores;
1468}
1469
1470static struct intel_uncore_type ivbep_uncore_ha = {
1471 .name = "ha",
1472 .num_counters = 4,
1473 .num_boxes = 2,
1474 .perf_ctr_bits = 48,
1475 IVBEP_UNCORE_PCI_COMMON_INIT(),
1476};
1477
1478static struct intel_uncore_type ivbep_uncore_imc = {
1479 .name = "imc",
1480 .num_counters = 4,
1481 .num_boxes = 8,
1482 .perf_ctr_bits = 48,
1483 .fixed_ctr_bits = 48,
1484 .fixed_ctr = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
1485 .fixed_ctl = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
1486 .event_descs = snbep_uncore_imc_events,
1487 IVBEP_UNCORE_PCI_COMMON_INIT(),
1488};
1489
1490/* registers in IRP boxes are not properly aligned */
1491static unsigned ivbep_uncore_irp_ctls[] = {0xd8, 0xdc, 0xe0, 0xe4};
1492static unsigned ivbep_uncore_irp_ctrs[] = {0xa0, 0xb0, 0xb8, 0xc0};
1493
1494static void ivbep_uncore_irp_enable_event(struct intel_uncore_box *box, struct perf_event *event)
1495{
1496 struct pci_dev *pdev = box->pci_dev;
1497 struct hw_perf_event *hwc = &event->hw;
1498
1499 pci_write_config_dword(pdev, ivbep_uncore_irp_ctls[hwc->idx],
1500 hwc->config | SNBEP_PMON_CTL_EN);
1501}
1502
1503static void ivbep_uncore_irp_disable_event(struct intel_uncore_box *box, struct perf_event *event)
1504{
1505 struct pci_dev *pdev = box->pci_dev;
1506 struct hw_perf_event *hwc = &event->hw;
1507
1508 pci_write_config_dword(pdev, ivbep_uncore_irp_ctls[hwc->idx], hwc->config);
1509}
1510
1511static u64 ivbep_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event)
1512{
1513 struct pci_dev *pdev = box->pci_dev;
1514 struct hw_perf_event *hwc = &event->hw;
1515 u64 count = 0;
1516
1517 pci_read_config_dword(pdev, ivbep_uncore_irp_ctrs[hwc->idx], (u32 *)&count);
1518 pci_read_config_dword(pdev, ivbep_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1);
1519
1520 return count;
1521}
1522
1523static struct intel_uncore_ops ivbep_uncore_irp_ops = {
1524 .init_box = ivbep_uncore_pci_init_box,
1525 .disable_box = snbep_uncore_pci_disable_box,
1526 .enable_box = snbep_uncore_pci_enable_box,
1527 .disable_event = ivbep_uncore_irp_disable_event,
1528 .enable_event = ivbep_uncore_irp_enable_event,
1529 .read_counter = ivbep_uncore_irp_read_counter,
1530};
1531
1532static struct intel_uncore_type ivbep_uncore_irp = {
1533 .name = "irp",
1534 .num_counters = 4,
1535 .num_boxes = 1,
1536 .perf_ctr_bits = 48,
1537 .event_mask = IVBEP_PMON_RAW_EVENT_MASK,
1538 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
1539 .ops = &ivbep_uncore_irp_ops,
1540 .format_group = &ivbep_uncore_format_group,
1541};
1542
1543static struct intel_uncore_ops ivbep_uncore_qpi_ops = {
1544 .init_box = ivbep_uncore_pci_init_box,
1545 .disable_box = snbep_uncore_pci_disable_box,
1546 .enable_box = snbep_uncore_pci_enable_box,
1547 .disable_event = snbep_uncore_pci_disable_event,
1548 .enable_event = snbep_qpi_enable_event,
1549 .read_counter = snbep_uncore_pci_read_counter,
1550 .hw_config = snbep_qpi_hw_config,
1551 .get_constraint = uncore_get_constraint,
1552 .put_constraint = uncore_put_constraint,
1553};
1554
1555static struct intel_uncore_type ivbep_uncore_qpi = {
1556 .name = "qpi",
1557 .num_counters = 4,
1558 .num_boxes = 3,
1559 .perf_ctr_bits = 48,
1560 .perf_ctr = SNBEP_PCI_PMON_CTR0,
1561 .event_ctl = SNBEP_PCI_PMON_CTL0,
1562 .event_mask = IVBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
1563 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
1564 .num_shared_regs = 1,
1565 .ops = &ivbep_uncore_qpi_ops,
1566 .format_group = &ivbep_uncore_qpi_format_group,
1567};
1568
1569static struct intel_uncore_type ivbep_uncore_r2pcie = {
1570 .name = "r2pcie",
1571 .num_counters = 4,
1572 .num_boxes = 1,
1573 .perf_ctr_bits = 44,
1574 .constraints = snbep_uncore_r2pcie_constraints,
1575 IVBEP_UNCORE_PCI_COMMON_INIT(),
1576};
1577
1578static struct intel_uncore_type ivbep_uncore_r3qpi = {
1579 .name = "r3qpi",
1580 .num_counters = 3,
1581 .num_boxes = 2,
1582 .perf_ctr_bits = 44,
1583 .constraints = snbep_uncore_r3qpi_constraints,
1584 IVBEP_UNCORE_PCI_COMMON_INIT(),
1585};
1586
1587enum {
1588 IVBEP_PCI_UNCORE_HA,
1589 IVBEP_PCI_UNCORE_IMC,
1590 IVBEP_PCI_UNCORE_IRP,
1591 IVBEP_PCI_UNCORE_QPI,
1592 IVBEP_PCI_UNCORE_R2PCIE,
1593 IVBEP_PCI_UNCORE_R3QPI,
1594};
1595
1596static struct intel_uncore_type *ivbep_pci_uncores[] = {
1597 [IVBEP_PCI_UNCORE_HA] = &ivbep_uncore_ha,
1598 [IVBEP_PCI_UNCORE_IMC] = &ivbep_uncore_imc,
1599 [IVBEP_PCI_UNCORE_IRP] = &ivbep_uncore_irp,
1600 [IVBEP_PCI_UNCORE_QPI] = &ivbep_uncore_qpi,
1601 [IVBEP_PCI_UNCORE_R2PCIE] = &ivbep_uncore_r2pcie,
1602 [IVBEP_PCI_UNCORE_R3QPI] = &ivbep_uncore_r3qpi,
1603 NULL,
1604};
1605
1606static const struct pci_device_id ivbep_uncore_pci_ids[] = {
1607 { /* Home Agent 0 */
1608 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe30),
1609 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_HA, 0),
1610 },
1611 { /* Home Agent 1 */
1612 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe38),
1613 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_HA, 1),
1614 },
1615 { /* MC0 Channel 0 */
1616 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb4),
1617 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 0),
1618 },
1619 { /* MC0 Channel 1 */
1620 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb5),
1621 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 1),
1622 },
1623 { /* MC0 Channel 3 */
1624 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb0),
1625 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 2),
1626 },
1627 { /* MC0 Channel 4 */
1628 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xeb1),
1629 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 3),
1630 },
1631 { /* MC1 Channel 0 */
1632 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef4),
1633 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 4),
1634 },
1635 { /* MC1 Channel 1 */
1636 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef5),
1637 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 5),
1638 },
1639 { /* MC1 Channel 3 */
1640 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef0),
1641 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 6),
1642 },
1643 { /* MC1 Channel 4 */
1644 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef1),
1645 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IMC, 7),
1646 },
1647 { /* IRP */
1648 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe39),
1649 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_IRP, 0),
1650 },
1651 { /* QPI0 Port 0 */
1652 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe32),
1653 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_QPI, 0),
1654 },
1655 { /* QPI0 Port 1 */
1656 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe33),
1657 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_QPI, 1),
1658 },
1659 { /* QPI1 Port 2 */
1660 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3a),
1661 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_QPI, 2),
1662 },
1663 { /* R2PCIe */
1664 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe34),
1665 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R2PCIE, 0),
1666 },
1667 { /* R3QPI0 Link 0 */
1668 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe36),
1669 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R3QPI, 0),
1670 },
1671 { /* R3QPI0 Link 1 */
1672 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe37),
1673 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R3QPI, 1),
1674 },
1675 { /* R3QPI1 Link 2 */
1676 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3e),
1677 .driver_data = UNCORE_PCI_DEV_DATA(IVBEP_PCI_UNCORE_R3QPI, 2),
1678 },
1679 { /* QPI Port 0 filter */
1680 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe86),
1681 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
1682 SNBEP_PCI_QPI_PORT0_FILTER),
1683 },
1684 { /* QPI Port 0 filter */
1685 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe96),
1686 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
1687 SNBEP_PCI_QPI_PORT1_FILTER),
1688 },
1689 { /* end: all zeroes */ }
1690};
1691
1692static struct pci_driver ivbep_uncore_pci_driver = {
1693 .name = "ivbep_uncore",
1694 .id_table = ivbep_uncore_pci_ids,
1695};
1696
1697int ivbep_uncore_pci_init(void)
1698{
1699 int ret = snbep_pci2phy_map_init(0x0e1e);
1700 if (ret)
1701 return ret;
1702 uncore_pci_uncores = ivbep_pci_uncores;
1703 uncore_pci_driver = &ivbep_uncore_pci_driver;
1704 return 0;
1705}
1706/* end of IvyTown uncore support */
1707
1708/* Haswell-EP uncore support */
1709static struct attribute *hswep_uncore_ubox_formats_attr[] = {
1710 &format_attr_event.attr,
1711 &format_attr_umask.attr,
1712 &format_attr_edge.attr,
1713 &format_attr_inv.attr,
1714 &format_attr_thresh5.attr,
1715 &format_attr_filter_tid2.attr,
1716 &format_attr_filter_cid.attr,
1717 NULL,
1718};
1719
1720static struct attribute_group hswep_uncore_ubox_format_group = {
1721 .name = "format",
1722 .attrs = hswep_uncore_ubox_formats_attr,
1723};
1724
1725static int hswep_ubox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
1726{
1727 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
1728 reg1->reg = HSWEP_U_MSR_PMON_FILTER;
1729 reg1->config = event->attr.config1 & HSWEP_U_MSR_PMON_BOX_FILTER_MASK;
1730 reg1->idx = 0;
1731 return 0;
1732}
1733
1734static struct intel_uncore_ops hswep_uncore_ubox_ops = {
1735 SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
1736 .hw_config = hswep_ubox_hw_config,
1737 .get_constraint = uncore_get_constraint,
1738 .put_constraint = uncore_put_constraint,
1739};
1740
1741static struct intel_uncore_type hswep_uncore_ubox = {
1742 .name = "ubox",
1743 .num_counters = 2,
1744 .num_boxes = 1,
1745 .perf_ctr_bits = 44,
1746 .fixed_ctr_bits = 48,
1747 .perf_ctr = HSWEP_U_MSR_PMON_CTR0,
1748 .event_ctl = HSWEP_U_MSR_PMON_CTL0,
1749 .event_mask = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
1750 .fixed_ctr = HSWEP_U_MSR_PMON_UCLK_FIXED_CTR,
1751 .fixed_ctl = HSWEP_U_MSR_PMON_UCLK_FIXED_CTL,
1752 .num_shared_regs = 1,
1753 .ops = &hswep_uncore_ubox_ops,
1754 .format_group = &hswep_uncore_ubox_format_group,
1755};
1756
1757static struct attribute *hswep_uncore_cbox_formats_attr[] = {
1758 &format_attr_event.attr,
1759 &format_attr_umask.attr,
1760 &format_attr_edge.attr,
1761 &format_attr_tid_en.attr,
1762 &format_attr_thresh8.attr,
1763 &format_attr_filter_tid3.attr,
1764 &format_attr_filter_link2.attr,
1765 &format_attr_filter_state3.attr,
1766 &format_attr_filter_nid2.attr,
1767 &format_attr_filter_opc2.attr,
1768 &format_attr_filter_nc.attr,
1769 &format_attr_filter_c6.attr,
1770 &format_attr_filter_isoc.attr,
1771 NULL,
1772};
1773
1774static struct attribute_group hswep_uncore_cbox_format_group = {
1775 .name = "format",
1776 .attrs = hswep_uncore_cbox_formats_attr,
1777};
1778
1779static struct event_constraint hswep_uncore_cbox_constraints[] = {
1780 UNCORE_EVENT_CONSTRAINT(0x01, 0x1),
1781 UNCORE_EVENT_CONSTRAINT(0x09, 0x1),
1782 UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
1783 UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
1784 UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
1785 UNCORE_EVENT_CONSTRAINT(0x3b, 0x1),
1786 UNCORE_EVENT_CONSTRAINT(0x3e, 0x1),
1787 EVENT_CONSTRAINT_END
1788};
1789
1790static struct extra_reg hswep_uncore_cbox_extra_regs[] = {
1791 SNBEP_CBO_EVENT_EXTRA_REG(SNBEP_CBO_PMON_CTL_TID_EN,
1792 SNBEP_CBO_PMON_CTL_TID_EN, 0x1),
1793 SNBEP_CBO_EVENT_EXTRA_REG(0x0334, 0xffff, 0x4),
1794 SNBEP_CBO_EVENT_EXTRA_REG(0x0534, 0xffff, 0x4),
1795 SNBEP_CBO_EVENT_EXTRA_REG(0x0934, 0xffff, 0x4),
1796 SNBEP_CBO_EVENT_EXTRA_REG(0x1134, 0xffff, 0x4),
1797 SNBEP_CBO_EVENT_EXTRA_REG(0x2134, 0xffff, 0x4),
1798 SNBEP_CBO_EVENT_EXTRA_REG(0x4134, 0xffff, 0x4),
1799 SNBEP_CBO_EVENT_EXTRA_REG(0x4037, 0x40ff, 0x8),
1800 SNBEP_CBO_EVENT_EXTRA_REG(0x4028, 0x40ff, 0x8),
1801 SNBEP_CBO_EVENT_EXTRA_REG(0x4032, 0x40ff, 0x8),
1802 SNBEP_CBO_EVENT_EXTRA_REG(0x4029, 0x40ff, 0x8),
1803 SNBEP_CBO_EVENT_EXTRA_REG(0x4033, 0x40ff, 0x8),
1804 SNBEP_CBO_EVENT_EXTRA_REG(0x402A, 0x40ff, 0x8),
1805 SNBEP_CBO_EVENT_EXTRA_REG(0x0135, 0xffff, 0x12),
1806 SNBEP_CBO_EVENT_EXTRA_REG(0x0335, 0xffff, 0x10),
1807 SNBEP_CBO_EVENT_EXTRA_REG(0x4135, 0xffff, 0x18),
1808 SNBEP_CBO_EVENT_EXTRA_REG(0x4435, 0xffff, 0x8),
1809 SNBEP_CBO_EVENT_EXTRA_REG(0x4835, 0xffff, 0x8),
1810 SNBEP_CBO_EVENT_EXTRA_REG(0x5035, 0xffff, 0x8),
1811 SNBEP_CBO_EVENT_EXTRA_REG(0x4335, 0xffff, 0x18),
1812 SNBEP_CBO_EVENT_EXTRA_REG(0x4a35, 0xffff, 0x8),
1813 SNBEP_CBO_EVENT_EXTRA_REG(0x2335, 0xffff, 0x10),
1814 SNBEP_CBO_EVENT_EXTRA_REG(0x8335, 0xffff, 0x10),
1815 SNBEP_CBO_EVENT_EXTRA_REG(0x2135, 0xffff, 0x10),
1816 SNBEP_CBO_EVENT_EXTRA_REG(0x8135, 0xffff, 0x10),
1817 SNBEP_CBO_EVENT_EXTRA_REG(0x0136, 0xffff, 0x10),
1818 SNBEP_CBO_EVENT_EXTRA_REG(0x0336, 0xffff, 0x10),
1819 SNBEP_CBO_EVENT_EXTRA_REG(0x4136, 0xffff, 0x18),
1820 SNBEP_CBO_EVENT_EXTRA_REG(0x4436, 0xffff, 0x8),
1821 SNBEP_CBO_EVENT_EXTRA_REG(0x4836, 0xffff, 0x8),
1822 SNBEP_CBO_EVENT_EXTRA_REG(0x4336, 0xffff, 0x18),
1823 SNBEP_CBO_EVENT_EXTRA_REG(0x4a36, 0xffff, 0x8),
1824 SNBEP_CBO_EVENT_EXTRA_REG(0x2336, 0xffff, 0x10),
1825 SNBEP_CBO_EVENT_EXTRA_REG(0x8336, 0xffff, 0x10),
1826 SNBEP_CBO_EVENT_EXTRA_REG(0x2136, 0xffff, 0x10),
1827 SNBEP_CBO_EVENT_EXTRA_REG(0x8136, 0xffff, 0x10),
1828 SNBEP_CBO_EVENT_EXTRA_REG(0x5036, 0xffff, 0x8),
1829 EVENT_EXTRA_END
1830};
1831
1832static u64 hswep_cbox_filter_mask(int fields)
1833{
1834 u64 mask = 0;
1835 if (fields & 0x1)
1836 mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_TID;
1837 if (fields & 0x2)
1838 mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_LINK;
1839 if (fields & 0x4)
1840 mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_STATE;
1841 if (fields & 0x8)
1842 mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_NID;
1843 if (fields & 0x10) {
1844 mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_OPC;
1845 mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_NC;
1846 mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_C6;
1847 mask |= HSWEP_CB0_MSR_PMON_BOX_FILTER_ISOC;
1848 }
1849 return mask;
1850}
1851
1852static struct event_constraint *
1853hswep_cbox_get_constraint(struct intel_uncore_box *box, struct perf_event *event)
1854{
1855 return __snbep_cbox_get_constraint(box, event, hswep_cbox_filter_mask);
1856}
1857
1858static int hswep_cbox_hw_config(struct intel_uncore_box *box, struct perf_event *event)
1859{
1860 struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
1861 struct extra_reg *er;
1862 int idx = 0;
1863
1864 for (er = hswep_uncore_cbox_extra_regs; er->msr; er++) {
1865 if (er->event != (event->hw.config & er->config_mask))
1866 continue;
1867 idx |= er->idx;
1868 }
1869
1870 if (idx) {
1871 reg1->reg = HSWEP_C0_MSR_PMON_BOX_FILTER0 +
1872 HSWEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
1873 reg1->config = event->attr.config1 & hswep_cbox_filter_mask(idx);
1874 reg1->idx = idx;
1875 }
1876 return 0;
1877}
1878
1879static void hswep_cbox_enable_event(struct intel_uncore_box *box,
1880 struct perf_event *event)
1881{
1882 struct hw_perf_event *hwc = &event->hw;
1883 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
1884
1885 if (reg1->idx != EXTRA_REG_NONE) {
1886 u64 filter = uncore_shared_reg_config(box, 0);
1887 wrmsrl(reg1->reg, filter & 0xffffffff);
1888 wrmsrl(reg1->reg + 1, filter >> 32);
1889 }
1890
1891 wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
1892}
1893
1894static struct intel_uncore_ops hswep_uncore_cbox_ops = {
1895 .init_box = snbep_uncore_msr_init_box,
1896 .disable_box = snbep_uncore_msr_disable_box,
1897 .enable_box = snbep_uncore_msr_enable_box,
1898 .disable_event = snbep_uncore_msr_disable_event,
1899 .enable_event = hswep_cbox_enable_event,
1900 .read_counter = uncore_msr_read_counter,
1901 .hw_config = hswep_cbox_hw_config,
1902 .get_constraint = hswep_cbox_get_constraint,
1903 .put_constraint = snbep_cbox_put_constraint,
1904};
1905
1906static struct intel_uncore_type hswep_uncore_cbox = {
1907 .name = "cbox",
1908 .num_counters = 4,
1909 .num_boxes = 18,
1910 .perf_ctr_bits = 44,
1911 .event_ctl = HSWEP_C0_MSR_PMON_CTL0,
1912 .perf_ctr = HSWEP_C0_MSR_PMON_CTR0,
1913 .event_mask = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
1914 .box_ctl = HSWEP_C0_MSR_PMON_BOX_CTL,
1915 .msr_offset = HSWEP_CBO_MSR_OFFSET,
1916 .num_shared_regs = 1,
1917 .constraints = hswep_uncore_cbox_constraints,
1918 .ops = &hswep_uncore_cbox_ops,
1919 .format_group = &hswep_uncore_cbox_format_group,
1920};
1921
1922static struct attribute *hswep_uncore_sbox_formats_attr[] = {
1923 &format_attr_event.attr,
1924 &format_attr_umask.attr,
1925 &format_attr_edge.attr,
1926 &format_attr_tid_en.attr,
1927 &format_attr_inv.attr,
1928 &format_attr_thresh8.attr,
1929 NULL,
1930};
1931
1932static struct attribute_group hswep_uncore_sbox_format_group = {
1933 .name = "format",
1934 .attrs = hswep_uncore_sbox_formats_attr,
1935};
1936
1937static struct intel_uncore_type hswep_uncore_sbox = {
1938 .name = "sbox",
1939 .num_counters = 4,
1940 .num_boxes = 4,
1941 .perf_ctr_bits = 44,
1942 .event_ctl = HSWEP_S0_MSR_PMON_CTL0,
1943 .perf_ctr = HSWEP_S0_MSR_PMON_CTR0,
1944 .event_mask = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
1945 .box_ctl = HSWEP_S0_MSR_PMON_BOX_CTL,
1946 .msr_offset = HSWEP_SBOX_MSR_OFFSET,
1947 .ops = &snbep_uncore_msr_ops,
1948 .format_group = &hswep_uncore_sbox_format_group,
1949};
1950
1951static int hswep_pcu_hw_config(struct intel_uncore_box *box, struct perf_event *event)
1952{
1953 struct hw_perf_event *hwc = &event->hw;
1954 struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
1955 int ev_sel = hwc->config & SNBEP_PMON_CTL_EV_SEL_MASK;
1956
1957 if (ev_sel >= 0xb && ev_sel <= 0xe) {
1958 reg1->reg = HSWEP_PCU_MSR_PMON_BOX_FILTER;
1959 reg1->idx = ev_sel - 0xb;
1960 reg1->config = event->attr.config1 & (0xff << reg1->idx);
1961 }
1962 return 0;
1963}
1964
1965static struct intel_uncore_ops hswep_uncore_pcu_ops = {
1966 SNBEP_UNCORE_MSR_OPS_COMMON_INIT(),
1967 .hw_config = hswep_pcu_hw_config,
1968 .get_constraint = snbep_pcu_get_constraint,
1969 .put_constraint = snbep_pcu_put_constraint,
1970};
1971
1972static struct intel_uncore_type hswep_uncore_pcu = {
1973 .name = "pcu",
1974 .num_counters = 4,
1975 .num_boxes = 1,
1976 .perf_ctr_bits = 48,
1977 .perf_ctr = HSWEP_PCU_MSR_PMON_CTR0,
1978 .event_ctl = HSWEP_PCU_MSR_PMON_CTL0,
1979 .event_mask = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
1980 .box_ctl = HSWEP_PCU_MSR_PMON_BOX_CTL,
1981 .num_shared_regs = 1,
1982 .ops = &hswep_uncore_pcu_ops,
1983 .format_group = &snbep_uncore_pcu_format_group,
1984};
1985
1986static struct intel_uncore_type *hswep_msr_uncores[] = {
1987 &hswep_uncore_ubox,
1988 &hswep_uncore_cbox,
1989 &hswep_uncore_sbox,
1990 &hswep_uncore_pcu,
1991 NULL,
1992};
1993
1994void hswep_uncore_cpu_init(void)
1995{
1996 if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
1997 hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
1998 uncore_msr_uncores = hswep_msr_uncores;
1999}
2000
2001static struct intel_uncore_type hswep_uncore_ha = {
2002 .name = "ha",
2003 .num_counters = 5,
2004 .num_boxes = 2,
2005 .perf_ctr_bits = 48,
2006 SNBEP_UNCORE_PCI_COMMON_INIT(),
2007};
2008
2009static struct uncore_event_desc hswep_uncore_imc_events[] = {
2010 INTEL_UNCORE_EVENT_DESC(clockticks, "event=0x00,umask=0x00"),
2011 INTEL_UNCORE_EVENT_DESC(cas_count_read, "event=0x04,umask=0x03"),
2012 INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
2013 { /* end: all zeroes */ },
2014};
2015
2016static struct intel_uncore_type hswep_uncore_imc = {
2017 .name = "imc",
2018 .num_counters = 5,
2019 .num_boxes = 8,
2020 .perf_ctr_bits = 48,
2021 .fixed_ctr_bits = 48,
2022 .fixed_ctr = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
2023 .fixed_ctl = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
2024 .event_descs = hswep_uncore_imc_events,
2025 SNBEP_UNCORE_PCI_COMMON_INIT(),
2026};
2027
2028static struct intel_uncore_ops hswep_uncore_irp_ops = {
2029 .init_box = snbep_uncore_pci_init_box,
2030 .disable_box = snbep_uncore_pci_disable_box,
2031 .enable_box = snbep_uncore_pci_enable_box,
2032 .disable_event = ivbep_uncore_irp_disable_event,
2033 .enable_event = ivbep_uncore_irp_enable_event,
2034 .read_counter = ivbep_uncore_irp_read_counter,
2035};
2036
2037static struct intel_uncore_type hswep_uncore_irp = {
2038 .name = "irp",
2039 .num_counters = 4,
2040 .num_boxes = 1,
2041 .perf_ctr_bits = 48,
2042 .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
2043 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
2044 .ops = &hswep_uncore_irp_ops,
2045 .format_group = &snbep_uncore_format_group,
2046};
2047
2048static struct intel_uncore_type hswep_uncore_qpi = {
2049 .name = "qpi",
2050 .num_counters = 5,
2051 .num_boxes = 3,
2052 .perf_ctr_bits = 48,
2053 .perf_ctr = SNBEP_PCI_PMON_CTR0,
2054 .event_ctl = SNBEP_PCI_PMON_CTL0,
2055 .event_mask = SNBEP_QPI_PCI_PMON_RAW_EVENT_MASK,
2056 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
2057 .num_shared_regs = 1,
2058 .ops = &snbep_uncore_qpi_ops,
2059 .format_group = &snbep_uncore_qpi_format_group,
2060};
2061
2062static struct event_constraint hswep_uncore_r2pcie_constraints[] = {
2063 UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
2064 UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
2065 UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
2066 UNCORE_EVENT_CONSTRAINT(0x23, 0x1),
2067 UNCORE_EVENT_CONSTRAINT(0x24, 0x1),
2068 UNCORE_EVENT_CONSTRAINT(0x25, 0x1),
2069 UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
2070 UNCORE_EVENT_CONSTRAINT(0x27, 0x1),
2071 UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
2072 UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
2073 UNCORE_EVENT_CONSTRAINT(0x2a, 0x1),
2074 UNCORE_EVENT_CONSTRAINT(0x2b, 0x3),
2075 UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
2076 UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
2077 UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
2078 UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
2079 UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
2080 UNCORE_EVENT_CONSTRAINT(0x35, 0x3),
2081 EVENT_CONSTRAINT_END
2082};
2083
2084static struct intel_uncore_type hswep_uncore_r2pcie = {
2085 .name = "r2pcie",
2086 .num_counters = 4,
2087 .num_boxes = 1,
2088 .perf_ctr_bits = 48,
2089 .constraints = hswep_uncore_r2pcie_constraints,
2090 SNBEP_UNCORE_PCI_COMMON_INIT(),
2091};
2092
2093static struct event_constraint hswep_uncore_r3qpi_constraints[] = {
2094 UNCORE_EVENT_CONSTRAINT(0x01, 0x3),
2095 UNCORE_EVENT_CONSTRAINT(0x07, 0x7),
2096 UNCORE_EVENT_CONSTRAINT(0x08, 0x7),
2097 UNCORE_EVENT_CONSTRAINT(0x09, 0x7),
2098 UNCORE_EVENT_CONSTRAINT(0x0a, 0x7),
2099 UNCORE_EVENT_CONSTRAINT(0x0e, 0x7),
2100 UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
2101 UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
2102 UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
2103 UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
2104 UNCORE_EVENT_CONSTRAINT(0x14, 0x3),
2105 UNCORE_EVENT_CONSTRAINT(0x15, 0x3),
2106 UNCORE_EVENT_CONSTRAINT(0x1f, 0x3),
2107 UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
2108 UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
2109 UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
2110 UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
2111 UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
2112 UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
2113 UNCORE_EVENT_CONSTRAINT(0x28, 0x3),
2114 UNCORE_EVENT_CONSTRAINT(0x29, 0x3),
2115 UNCORE_EVENT_CONSTRAINT(0x2c, 0x3),
2116 UNCORE_EVENT_CONSTRAINT(0x2d, 0x3),
2117 UNCORE_EVENT_CONSTRAINT(0x2e, 0x3),
2118 UNCORE_EVENT_CONSTRAINT(0x2f, 0x3),
2119 UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
2120 UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
2121 UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
2122 UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
2123 UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
2124 UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
2125 UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
2126 UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
2127 EVENT_CONSTRAINT_END
2128};
2129
2130static struct intel_uncore_type hswep_uncore_r3qpi = {
2131 .name = "r3qpi",
2132 .num_counters = 4,
2133 .num_boxes = 3,
2134 .perf_ctr_bits = 44,
2135 .constraints = hswep_uncore_r3qpi_constraints,
2136 SNBEP_UNCORE_PCI_COMMON_INIT(),
2137};
2138
2139enum {
2140 HSWEP_PCI_UNCORE_HA,
2141 HSWEP_PCI_UNCORE_IMC,
2142 HSWEP_PCI_UNCORE_IRP,
2143 HSWEP_PCI_UNCORE_QPI,
2144 HSWEP_PCI_UNCORE_R2PCIE,
2145 HSWEP_PCI_UNCORE_R3QPI,
2146};
2147
2148static struct intel_uncore_type *hswep_pci_uncores[] = {
2149 [HSWEP_PCI_UNCORE_HA] = &hswep_uncore_ha,
2150 [HSWEP_PCI_UNCORE_IMC] = &hswep_uncore_imc,
2151 [HSWEP_PCI_UNCORE_IRP] = &hswep_uncore_irp,
2152 [HSWEP_PCI_UNCORE_QPI] = &hswep_uncore_qpi,
2153 [HSWEP_PCI_UNCORE_R2PCIE] = &hswep_uncore_r2pcie,
2154 [HSWEP_PCI_UNCORE_R3QPI] = &hswep_uncore_r3qpi,
2155 NULL,
2156};
2157
2158static DEFINE_PCI_DEVICE_TABLE(hswep_uncore_pci_ids) = {
2159 { /* Home Agent 0 */
2160 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f30),
2161 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_HA, 0),
2162 },
2163 { /* Home Agent 1 */
2164 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f38),
2165 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_HA, 1),
2166 },
2167 { /* MC0 Channel 0 */
2168 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb0),
2169 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 0),
2170 },
2171 { /* MC0 Channel 1 */
2172 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb1),
2173 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 1),
2174 },
2175 { /* MC0 Channel 2 */
2176 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb4),
2177 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 2),
2178 },
2179 { /* MC0 Channel 3 */
2180 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fb5),
2181 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 3),
2182 },
2183 { /* MC1 Channel 0 */
2184 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd0),
2185 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 4),
2186 },
2187 { /* MC1 Channel 1 */
2188 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd1),
2189 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 5),
2190 },
2191 { /* MC1 Channel 2 */
2192 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd4),
2193 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 6),
2194 },
2195 { /* MC1 Channel 3 */
2196 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fd5),
2197 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IMC, 7),
2198 },
2199 { /* IRP */
2200 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f39),
2201 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_IRP, 0),
2202 },
2203 { /* QPI0 Port 0 */
2204 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f32),
2205 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_QPI, 0),
2206 },
2207 { /* QPI0 Port 1 */
2208 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f33),
2209 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_QPI, 1),
2210 },
2211 { /* QPI1 Port 2 */
2212 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f3a),
2213 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_QPI, 2),
2214 },
2215 { /* R2PCIe */
2216 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f34),
2217 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R2PCIE, 0),
2218 },
2219 { /* R3QPI0 Link 0 */
2220 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f36),
2221 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R3QPI, 0),
2222 },
2223 { /* R3QPI0 Link 1 */
2224 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f37),
2225 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R3QPI, 1),
2226 },
2227 { /* R3QPI1 Link 2 */
2228 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f3e),
2229 .driver_data = UNCORE_PCI_DEV_DATA(HSWEP_PCI_UNCORE_R3QPI, 2),
2230 },
2231 { /* QPI Port 0 filter */
2232 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f86),
2233 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
2234 SNBEP_PCI_QPI_PORT0_FILTER),
2235 },
2236 { /* QPI Port 1 filter */
2237 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2f96),
2238 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
2239 SNBEP_PCI_QPI_PORT1_FILTER),
2240 },
2241 { /* end: all zeroes */ }
2242};
2243
2244static struct pci_driver hswep_uncore_pci_driver = {
2245 .name = "hswep_uncore",
2246 .id_table = hswep_uncore_pci_ids,
2247};
2248
2249int hswep_uncore_pci_init(void)
2250{
2251 int ret = snbep_pci2phy_map_init(0x2f1e);
2252 if (ret)
2253 return ret;
2254 uncore_pci_uncores = hswep_pci_uncores;
2255 uncore_pci_driver = &hswep_uncore_pci_driver;
2256 return 0;
2257}
2258/* end of Haswell-EP uncore support */
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 784304b222b3..98f923b6a0ea 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -8,28 +8,28 @@
8 * Copyright (C) 2011-2012 Peter Zijlstra <pzijlstr@redhat.com> 8 * Copyright (C) 2011-2012 Peter Zijlstra <pzijlstr@redhat.com>
9 * 9 *
10 * Jump labels provide an interface to generate dynamic branches using 10 * Jump labels provide an interface to generate dynamic branches using
11 * self-modifying code. Assuming toolchain and architecture support the result 11 * self-modifying code. Assuming toolchain and architecture support, the result
12 * of a "if (static_key_false(&key))" statement is a unconditional branch (which 12 * of a "if (static_key_false(&key))" statement is an unconditional branch (which
13 * defaults to false - and the true block is placed out of line). 13 * defaults to false - and the true block is placed out of line).
14 * 14 *
15 * However at runtime we can change the branch target using 15 * However at runtime we can change the branch target using
16 * static_key_slow_{inc,dec}(). These function as a 'reference' count on the key 16 * static_key_slow_{inc,dec}(). These function as a 'reference' count on the key
17 * object and for as long as there are references all branches referring to 17 * object, and for as long as there are references all branches referring to
18 * that particular key will point to the (out of line) true block. 18 * that particular key will point to the (out of line) true block.
19 * 19 *
20 * Since this relies on modifying code the static_key_slow_{inc,dec}() functions 20 * Since this relies on modifying code, the static_key_slow_{inc,dec}() functions
21 * must be considered absolute slow paths (machine wide synchronization etc.). 21 * must be considered absolute slow paths (machine wide synchronization etc.).
22 * OTOH, since the affected branches are unconditional their runtime overhead 22 * OTOH, since the affected branches are unconditional, their runtime overhead
23 * will be absolutely minimal, esp. in the default (off) case where the total 23 * will be absolutely minimal, esp. in the default (off) case where the total
24 * effect is a single NOP of appropriate size. The on case will patch in a jump 24 * effect is a single NOP of appropriate size. The on case will patch in a jump
25 * to the out-of-line block. 25 * to the out-of-line block.
26 * 26 *
27 * When the control is directly exposed to userspace it is prudent to delay the 27 * When the control is directly exposed to userspace, it is prudent to delay the
28 * decrement to avoid high frequency code modifications which can (and do) 28 * decrement to avoid high frequency code modifications which can (and do)
29 * cause significant performance degradation. Struct static_key_deferred and 29 * cause significant performance degradation. Struct static_key_deferred and
30 * static_key_slow_dec_deferred() provide for this. 30 * static_key_slow_dec_deferred() provide for this.
31 * 31 *
32 * Lacking toolchain and or architecture support, it falls back to a simple 32 * Lacking toolchain and or architecture support, jump labels fall back to a simple
33 * conditional branch. 33 * conditional branch.
34 * 34 *
35 * struct static_key my_key = STATIC_KEY_INIT_TRUE; 35 * struct static_key my_key = STATIC_KEY_INIT_TRUE;
@@ -43,8 +43,7 @@
43 * 43 *
44 * Not initializing the key (static data is initialized to 0s anyway) is the 44 * Not initializing the key (static data is initialized to 0s anyway) is the
45 * same as using STATIC_KEY_INIT_FALSE. 45 * same as using STATIC_KEY_INIT_FALSE.
46 * 46 */
47*/
48 47
49#include <linux/types.h> 48#include <linux/types.h>
50#include <linux/compiler.h> 49#include <linux/compiler.h>
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 2338e68398cb..0aa51b451597 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2538,6 +2538,7 @@
2538#define PCI_DEVICE_ID_INTEL_EESSC 0x0008 2538#define PCI_DEVICE_ID_INTEL_EESSC 0x0008
2539#define PCI_DEVICE_ID_INTEL_SNB_IMC 0x0100 2539#define PCI_DEVICE_ID_INTEL_SNB_IMC 0x0100
2540#define PCI_DEVICE_ID_INTEL_IVB_IMC 0x0154 2540#define PCI_DEVICE_ID_INTEL_IVB_IMC 0x0154
2541#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150
2541#define PCI_DEVICE_ID_INTEL_HSW_IMC 0x0c00 2542#define PCI_DEVICE_ID_INTEL_HSW_IMC 0x0c00
2542#define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320 2543#define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320
2543#define PCI_DEVICE_ID_INTEL_PXHD_1 0x0321 2544#define PCI_DEVICE_ID_INTEL_PXHD_1 0x0321
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 707617a8c0f6..893a0d07986f 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -52,6 +52,7 @@ struct perf_guest_info_callbacks {
52#include <linux/atomic.h> 52#include <linux/atomic.h>
53#include <linux/sysfs.h> 53#include <linux/sysfs.h>
54#include <linux/perf_regs.h> 54#include <linux/perf_regs.h>
55#include <linux/workqueue.h>
55#include <asm/local.h> 56#include <asm/local.h>
56 57
57struct perf_callchain_entry { 58struct perf_callchain_entry {
@@ -268,6 +269,7 @@ struct pmu {
268 * enum perf_event_active_state - the states of a event 269 * enum perf_event_active_state - the states of a event
269 */ 270 */
270enum perf_event_active_state { 271enum perf_event_active_state {
272 PERF_EVENT_STATE_EXIT = -3,
271 PERF_EVENT_STATE_ERROR = -2, 273 PERF_EVENT_STATE_ERROR = -2,
272 PERF_EVENT_STATE_OFF = -1, 274 PERF_EVENT_STATE_OFF = -1,
273 PERF_EVENT_STATE_INACTIVE = 0, 275 PERF_EVENT_STATE_INACTIVE = 0,
@@ -507,6 +509,9 @@ struct perf_event_context {
507 int nr_cgroups; /* cgroup evts */ 509 int nr_cgroups; /* cgroup evts */
508 int nr_branch_stack; /* branch_stack evt */ 510 int nr_branch_stack; /* branch_stack evt */
509 struct rcu_head rcu_head; 511 struct rcu_head rcu_head;
512
513 struct delayed_work orphans_remove;
514 bool orphans_remove_sched;
510}; 515};
511 516
512/* 517/*
@@ -604,6 +609,13 @@ struct perf_sample_data {
604 u64 txn; 609 u64 txn;
605}; 610};
606 611
612/* default value for data source */
613#define PERF_MEM_NA (PERF_MEM_S(OP, NA) |\
614 PERF_MEM_S(LVL, NA) |\
615 PERF_MEM_S(SNOOP, NA) |\
616 PERF_MEM_S(LOCK, NA) |\
617 PERF_MEM_S(TLB, NA))
618
607static inline void perf_sample_data_init(struct perf_sample_data *data, 619static inline void perf_sample_data_init(struct perf_sample_data *data,
608 u64 addr, u64 period) 620 u64 addr, u64 period)
609{ 621{
@@ -616,7 +628,7 @@ static inline void perf_sample_data_init(struct perf_sample_data *data,
616 data->regs_user.regs = NULL; 628 data->regs_user.regs = NULL;
617 data->stack_user_size = 0; 629 data->stack_user_size = 0;
618 data->weight = 0; 630 data->weight = 0;
619 data->data_src.val = 0; 631 data->data_src.val = PERF_MEM_NA;
620 data->txn = 0; 632 data->txn = 0;
621} 633}
622 634
diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c
index 97b67df8fbfe..f2a88de87a49 100644
--- a/kernel/events/callchain.c
+++ b/kernel/events/callchain.c
@@ -52,7 +52,7 @@ static void release_callchain_buffers(void)
52 struct callchain_cpus_entries *entries; 52 struct callchain_cpus_entries *entries;
53 53
54 entries = callchain_cpus_entries; 54 entries = callchain_cpus_entries;
55 rcu_assign_pointer(callchain_cpus_entries, NULL); 55 RCU_INIT_POINTER(callchain_cpus_entries, NULL);
56 call_rcu(&entries->rcu_head, release_callchain_buffers_rcu); 56 call_rcu(&entries->rcu_head, release_callchain_buffers_rcu);
57} 57}
58 58
diff --git a/kernel/events/core.c b/kernel/events/core.c
index b1c663593f5c..385f11d94105 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -47,6 +47,8 @@
47 47
48#include <asm/irq_regs.h> 48#include <asm/irq_regs.h>
49 49
50static struct workqueue_struct *perf_wq;
51
50struct remote_function_call { 52struct remote_function_call {
51 struct task_struct *p; 53 struct task_struct *p;
52 int (*func)(void *info); 54 int (*func)(void *info);
@@ -120,6 +122,13 @@ static int cpu_function_call(int cpu, int (*func) (void *info), void *info)
120 return data.ret; 122 return data.ret;
121} 123}
122 124
125#define EVENT_OWNER_KERNEL ((void *) -1)
126
127static bool is_kernel_event(struct perf_event *event)
128{
129 return event->owner == EVENT_OWNER_KERNEL;
130}
131
123#define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\ 132#define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\
124 PERF_FLAG_FD_OUTPUT |\ 133 PERF_FLAG_FD_OUTPUT |\
125 PERF_FLAG_PID_CGROUP |\ 134 PERF_FLAG_PID_CGROUP |\
@@ -1370,6 +1379,45 @@ out:
1370 perf_event__header_size(tmp); 1379 perf_event__header_size(tmp);
1371} 1380}
1372 1381
1382/*
1383 * User event without the task.
1384 */
1385static bool is_orphaned_event(struct perf_event *event)
1386{
1387 return event && !is_kernel_event(event) && !event->owner;
1388}
1389
1390/*
1391 * Event has a parent but parent's task finished and it's
1392 * alive only because of children holding refference.
1393 */
1394static bool is_orphaned_child(struct perf_event *event)
1395{
1396 return is_orphaned_event(event->parent);
1397}
1398
1399static void orphans_remove_work(struct work_struct *work);
1400
1401static void schedule_orphans_remove(struct perf_event_context *ctx)
1402{
1403 if (!ctx->task || ctx->orphans_remove_sched || !perf_wq)
1404 return;
1405
1406 if (queue_delayed_work(perf_wq, &ctx->orphans_remove, 1)) {
1407 get_ctx(ctx);
1408 ctx->orphans_remove_sched = true;
1409 }
1410}
1411
1412static int __init perf_workqueue_init(void)
1413{
1414 perf_wq = create_singlethread_workqueue("perf");
1415 WARN(!perf_wq, "failed to create perf workqueue\n");
1416 return perf_wq ? 0 : -1;
1417}
1418
1419core_initcall(perf_workqueue_init);
1420
1373static inline int 1421static inline int
1374event_filter_match(struct perf_event *event) 1422event_filter_match(struct perf_event *event)
1375{ 1423{
@@ -1419,6 +1467,9 @@ event_sched_out(struct perf_event *event,
1419 if (event->attr.exclusive || !cpuctx->active_oncpu) 1467 if (event->attr.exclusive || !cpuctx->active_oncpu)
1420 cpuctx->exclusive = 0; 1468 cpuctx->exclusive = 0;
1421 1469
1470 if (is_orphaned_child(event))
1471 schedule_orphans_remove(ctx);
1472
1422 perf_pmu_enable(event->pmu); 1473 perf_pmu_enable(event->pmu);
1423} 1474}
1424 1475
@@ -1726,6 +1777,9 @@ event_sched_in(struct perf_event *event,
1726 if (event->attr.exclusive) 1777 if (event->attr.exclusive)
1727 cpuctx->exclusive = 1; 1778 cpuctx->exclusive = 1;
1728 1779
1780 if (is_orphaned_child(event))
1781 schedule_orphans_remove(ctx);
1782
1729out: 1783out:
1730 perf_pmu_enable(event->pmu); 1784 perf_pmu_enable(event->pmu);
1731 1785
@@ -2326,7 +2380,7 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
2326 next_parent = rcu_dereference(next_ctx->parent_ctx); 2380 next_parent = rcu_dereference(next_ctx->parent_ctx);
2327 2381
2328 /* If neither context have a parent context; they cannot be clones. */ 2382 /* If neither context have a parent context; they cannot be clones. */
2329 if (!parent || !next_parent) 2383 if (!parent && !next_parent)
2330 goto unlock; 2384 goto unlock;
2331 2385
2332 if (next_parent == ctx || next_ctx == parent || next_parent == parent) { 2386 if (next_parent == ctx || next_ctx == parent || next_parent == parent) {
@@ -3073,6 +3127,7 @@ static void __perf_event_init_context(struct perf_event_context *ctx)
3073 INIT_LIST_HEAD(&ctx->flexible_groups); 3127 INIT_LIST_HEAD(&ctx->flexible_groups);
3074 INIT_LIST_HEAD(&ctx->event_list); 3128 INIT_LIST_HEAD(&ctx->event_list);
3075 atomic_set(&ctx->refcount, 1); 3129 atomic_set(&ctx->refcount, 1);
3130 INIT_DELAYED_WORK(&ctx->orphans_remove, orphans_remove_work);
3076} 3131}
3077 3132
3078static struct perf_event_context * 3133static struct perf_event_context *
@@ -3318,16 +3373,12 @@ static void free_event(struct perf_event *event)
3318} 3373}
3319 3374
3320/* 3375/*
3321 * Called when the last reference to the file is gone. 3376 * Remove user event from the owner task.
3322 */ 3377 */
3323static void put_event(struct perf_event *event) 3378static void perf_remove_from_owner(struct perf_event *event)
3324{ 3379{
3325 struct perf_event_context *ctx = event->ctx;
3326 struct task_struct *owner; 3380 struct task_struct *owner;
3327 3381
3328 if (!atomic_long_dec_and_test(&event->refcount))
3329 return;
3330
3331 rcu_read_lock(); 3382 rcu_read_lock();
3332 owner = ACCESS_ONCE(event->owner); 3383 owner = ACCESS_ONCE(event->owner);
3333 /* 3384 /*
@@ -3360,6 +3411,20 @@ static void put_event(struct perf_event *event)
3360 mutex_unlock(&owner->perf_event_mutex); 3411 mutex_unlock(&owner->perf_event_mutex);
3361 put_task_struct(owner); 3412 put_task_struct(owner);
3362 } 3413 }
3414}
3415
3416/*
3417 * Called when the last reference to the file is gone.
3418 */
3419static void put_event(struct perf_event *event)
3420{
3421 struct perf_event_context *ctx = event->ctx;
3422
3423 if (!atomic_long_dec_and_test(&event->refcount))
3424 return;
3425
3426 if (!is_kernel_event(event))
3427 perf_remove_from_owner(event);
3363 3428
3364 WARN_ON_ONCE(ctx->parent_ctx); 3429 WARN_ON_ONCE(ctx->parent_ctx);
3365 /* 3430 /*
@@ -3394,6 +3459,42 @@ static int perf_release(struct inode *inode, struct file *file)
3394 return 0; 3459 return 0;
3395} 3460}
3396 3461
3462/*
3463 * Remove all orphanes events from the context.
3464 */
3465static void orphans_remove_work(struct work_struct *work)
3466{
3467 struct perf_event_context *ctx;
3468 struct perf_event *event, *tmp;
3469
3470 ctx = container_of(work, struct perf_event_context,
3471 orphans_remove.work);
3472
3473 mutex_lock(&ctx->mutex);
3474 list_for_each_entry_safe(event, tmp, &ctx->event_list, event_entry) {
3475 struct perf_event *parent_event = event->parent;
3476
3477 if (!is_orphaned_child(event))
3478 continue;
3479
3480 perf_remove_from_context(event, true);
3481
3482 mutex_lock(&parent_event->child_mutex);
3483 list_del_init(&event->child_list);
3484 mutex_unlock(&parent_event->child_mutex);
3485
3486 free_event(event);
3487 put_event(parent_event);
3488 }
3489
3490 raw_spin_lock_irq(&ctx->lock);
3491 ctx->orphans_remove_sched = false;
3492 raw_spin_unlock_irq(&ctx->lock);
3493 mutex_unlock(&ctx->mutex);
3494
3495 put_ctx(ctx);
3496}
3497
3397u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) 3498u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
3398{ 3499{
3399 struct perf_event *child; 3500 struct perf_event *child;
@@ -3491,6 +3592,19 @@ static int perf_event_read_one(struct perf_event *event,
3491 return n * sizeof(u64); 3592 return n * sizeof(u64);
3492} 3593}
3493 3594
3595static bool is_event_hup(struct perf_event *event)
3596{
3597 bool no_children;
3598
3599 if (event->state != PERF_EVENT_STATE_EXIT)
3600 return false;
3601
3602 mutex_lock(&event->child_mutex);
3603 no_children = list_empty(&event->child_list);
3604 mutex_unlock(&event->child_mutex);
3605 return no_children;
3606}
3607
3494/* 3608/*
3495 * Read the performance event - simple non blocking version for now 3609 * Read the performance event - simple non blocking version for now
3496 */ 3610 */
@@ -3532,7 +3646,12 @@ static unsigned int perf_poll(struct file *file, poll_table *wait)
3532{ 3646{
3533 struct perf_event *event = file->private_data; 3647 struct perf_event *event = file->private_data;
3534 struct ring_buffer *rb; 3648 struct ring_buffer *rb;
3535 unsigned int events = POLL_HUP; 3649 unsigned int events = POLLHUP;
3650
3651 poll_wait(file, &event->waitq, wait);
3652
3653 if (is_event_hup(event))
3654 return events;
3536 3655
3537 /* 3656 /*
3538 * Pin the event->rb by taking event->mmap_mutex; otherwise 3657 * Pin the event->rb by taking event->mmap_mutex; otherwise
@@ -3543,9 +3662,6 @@ static unsigned int perf_poll(struct file *file, poll_table *wait)
3543 if (rb) 3662 if (rb)
3544 events = atomic_xchg(&rb->poll, 0); 3663 events = atomic_xchg(&rb->poll, 0);
3545 mutex_unlock(&event->mmap_mutex); 3664 mutex_unlock(&event->mmap_mutex);
3546
3547 poll_wait(file, &event->waitq, wait);
3548
3549 return events; 3665 return events;
3550} 3666}
3551 3667
@@ -5809,7 +5925,7 @@ static void swevent_hlist_release(struct swevent_htable *swhash)
5809 if (!hlist) 5925 if (!hlist)
5810 return; 5926 return;
5811 5927
5812 rcu_assign_pointer(swhash->swevent_hlist, NULL); 5928 RCU_INIT_POINTER(swhash->swevent_hlist, NULL);
5813 kfree_rcu(hlist, rcu_head); 5929 kfree_rcu(hlist, rcu_head);
5814} 5930}
5815 5931
@@ -7392,6 +7508,9 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
7392 goto err; 7508 goto err;
7393 } 7509 }
7394 7510
7511 /* Mark owner so we could distinguish it from user events. */
7512 event->owner = EVENT_OWNER_KERNEL;
7513
7395 account_event(event); 7514 account_event(event);
7396 7515
7397 ctx = find_get_context(event->pmu, task, cpu); 7516 ctx = find_get_context(event->pmu, task, cpu);
@@ -7479,6 +7598,12 @@ static void sync_child_event(struct perf_event *child_event,
7479 mutex_unlock(&parent_event->child_mutex); 7598 mutex_unlock(&parent_event->child_mutex);
7480 7599
7481 /* 7600 /*
7601 * Make sure user/parent get notified, that we just
7602 * lost one event.
7603 */
7604 perf_event_wakeup(parent_event);
7605
7606 /*
7482 * Release the parent event, if this was the last 7607 * Release the parent event, if this was the last
7483 * reference to it. 7608 * reference to it.
7484 */ 7609 */
@@ -7512,6 +7637,9 @@ __perf_event_exit_task(struct perf_event *child_event,
7512 if (child_event->parent) { 7637 if (child_event->parent) {
7513 sync_child_event(child_event, child); 7638 sync_child_event(child_event, child);
7514 free_event(child_event); 7639 free_event(child_event);
7640 } else {
7641 child_event->state = PERF_EVENT_STATE_EXIT;
7642 perf_event_wakeup(child_event);
7515 } 7643 }
7516} 7644}
7517 7645
@@ -7695,6 +7823,7 @@ inherit_event(struct perf_event *parent_event,
7695 struct perf_event *group_leader, 7823 struct perf_event *group_leader,
7696 struct perf_event_context *child_ctx) 7824 struct perf_event_context *child_ctx)
7697{ 7825{
7826 enum perf_event_active_state parent_state = parent_event->state;
7698 struct perf_event *child_event; 7827 struct perf_event *child_event;
7699 unsigned long flags; 7828 unsigned long flags;
7700 7829
@@ -7715,7 +7844,8 @@ inherit_event(struct perf_event *parent_event,
7715 if (IS_ERR(child_event)) 7844 if (IS_ERR(child_event))
7716 return child_event; 7845 return child_event;
7717 7846
7718 if (!atomic_long_inc_not_zero(&parent_event->refcount)) { 7847 if (is_orphaned_event(parent_event) ||
7848 !atomic_long_inc_not_zero(&parent_event->refcount)) {
7719 free_event(child_event); 7849 free_event(child_event);
7720 return NULL; 7850 return NULL;
7721 } 7851 }
@@ -7727,7 +7857,7 @@ inherit_event(struct perf_event *parent_event,
7727 * not its attr.disabled bit. We hold the parent's mutex, 7857 * not its attr.disabled bit. We hold the parent's mutex,
7728 * so we won't race with perf_event_{en, dis}able_family. 7858 * so we won't race with perf_event_{en, dis}able_family.
7729 */ 7859 */
7730 if (parent_event->state >= PERF_EVENT_STATE_INACTIVE) 7860 if (parent_state >= PERF_EVENT_STATE_INACTIVE)
7731 child_event->state = PERF_EVENT_STATE_INACTIVE; 7861 child_event->state = PERF_EVENT_STATE_INACTIVE;
7732 else 7862 else
7733 child_event->state = PERF_EVENT_STATE_OFF; 7863 child_event->state = PERF_EVENT_STATE_OFF;
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index ce00f7ee6455..36c08b1f4afb 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -10,9 +10,14 @@ LIB_OBJS=
10 10
11LIB_H += fs/debugfs.h 11LIB_H += fs/debugfs.h
12LIB_H += fs/fs.h 12LIB_H += fs/fs.h
13# See comment below about piggybacking...
14LIB_H += fd/array.h
13 15
14LIB_OBJS += $(OUTPUT)fs/debugfs.o 16LIB_OBJS += $(OUTPUT)fs/debugfs.o
15LIB_OBJS += $(OUTPUT)fs/fs.o 17LIB_OBJS += $(OUTPUT)fs/fs.o
18# XXX piggybacking here, need to introduce libapikfd, or rename this
19# to plain libapik.a and make it have it all api goodies
20LIB_OBJS += $(OUTPUT)fd/array.o
16 21
17LIBFILE = libapikfs.a 22LIBFILE = libapikfs.a
18 23
@@ -29,7 +34,7 @@ $(LIBFILE): $(LIB_OBJS)
29$(LIB_OBJS): $(LIB_H) 34$(LIB_OBJS): $(LIB_H)
30 35
31libapi_dirs: 36libapi_dirs:
32 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/ 37 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs
33 38
34$(OUTPUT)%.o: %.c libapi_dirs 39$(OUTPUT)%.o: %.c libapi_dirs
35 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 40 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
diff --git a/tools/lib/api/fd/array.c b/tools/lib/api/fd/array.c
new file mode 100644
index 000000000000..0e636c4339b8
--- /dev/null
+++ b/tools/lib/api/fd/array.c
@@ -0,0 +1,127 @@
1/*
2 * Copyright (C) 2014, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Released under the GPL v2. (and only v2, not any later version)
5 */
6#include "array.h"
7#include <errno.h>
8#include <fcntl.h>
9#include <poll.h>
10#include <stdlib.h>
11#include <unistd.h>
12
13void fdarray__init(struct fdarray *fda, int nr_autogrow)
14{
15 fda->entries = NULL;
16 fda->priv = NULL;
17 fda->nr = fda->nr_alloc = 0;
18 fda->nr_autogrow = nr_autogrow;
19}
20
21int fdarray__grow(struct fdarray *fda, int nr)
22{
23 void *priv;
24 int nr_alloc = fda->nr_alloc + nr;
25 size_t psize = sizeof(fda->priv[0]) * nr_alloc;
26 size_t size = sizeof(struct pollfd) * nr_alloc;
27 struct pollfd *entries = realloc(fda->entries, size);
28
29 if (entries == NULL)
30 return -ENOMEM;
31
32 priv = realloc(fda->priv, psize);
33 if (priv == NULL) {
34 free(entries);
35 return -ENOMEM;
36 }
37
38 fda->nr_alloc = nr_alloc;
39 fda->entries = entries;
40 fda->priv = priv;
41 return 0;
42}
43
44struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow)
45{
46 struct fdarray *fda = calloc(1, sizeof(*fda));
47
48 if (fda != NULL) {
49 if (fdarray__grow(fda, nr_alloc)) {
50 free(fda);
51 fda = NULL;
52 } else {
53 fda->nr_autogrow = nr_autogrow;
54 }
55 }
56
57 return fda;
58}
59
60void fdarray__exit(struct fdarray *fda)
61{
62 free(fda->entries);
63 free(fda->priv);
64 fdarray__init(fda, 0);
65}
66
67void fdarray__delete(struct fdarray *fda)
68{
69 fdarray__exit(fda);
70 free(fda);
71}
72
73int fdarray__add(struct fdarray *fda, int fd, short revents)
74{
75 int pos = fda->nr;
76
77 if (fda->nr == fda->nr_alloc &&
78 fdarray__grow(fda, fda->nr_autogrow) < 0)
79 return -ENOMEM;
80
81 fda->entries[fda->nr].fd = fd;
82 fda->entries[fda->nr].events = revents;
83 fda->nr++;
84 return pos;
85}
86
87int fdarray__filter(struct fdarray *fda, short revents,
88 void (*entry_destructor)(struct fdarray *fda, int fd))
89{
90 int fd, nr = 0;
91
92 if (fda->nr == 0)
93 return 0;
94
95 for (fd = 0; fd < fda->nr; ++fd) {
96 if (fda->entries[fd].revents & revents) {
97 if (entry_destructor)
98 entry_destructor(fda, fd);
99
100 continue;
101 }
102
103 if (fd != nr) {
104 fda->entries[nr] = fda->entries[fd];
105 fda->priv[nr] = fda->priv[fd];
106 }
107
108 ++nr;
109 }
110
111 return fda->nr = nr;
112}
113
114int fdarray__poll(struct fdarray *fda, int timeout)
115{
116 return poll(fda->entries, fda->nr, timeout);
117}
118
119int fdarray__fprintf(struct fdarray *fda, FILE *fp)
120{
121 int fd, printed = fprintf(fp, "%d [ ", fda->nr);
122
123 for (fd = 0; fd < fda->nr; ++fd)
124 printed += fprintf(fp, "%s%d", fd ? ", " : "", fda->entries[fd].fd);
125
126 return printed + fprintf(fp, " ]");
127}
diff --git a/tools/lib/api/fd/array.h b/tools/lib/api/fd/array.h
new file mode 100644
index 000000000000..45db01818f45
--- /dev/null
+++ b/tools/lib/api/fd/array.h
@@ -0,0 +1,46 @@
1#ifndef __API_FD_ARRAY__
2#define __API_FD_ARRAY__
3
4#include <stdio.h>
5
6struct pollfd;
7
8/**
9 * struct fdarray: Array of file descriptors
10 *
11 * @priv: Per array entry priv area, users should access just its contents,
12 * not set it to anything, as it is kept in synch with @entries, being
13 * realloc'ed, * for instance, in fdarray__{grow,filter}.
14 *
15 * I.e. using 'fda->priv[N].idx = * value' where N < fda->nr is ok,
16 * but doing 'fda->priv = malloc(M)' is not allowed.
17 */
18struct fdarray {
19 int nr;
20 int nr_alloc;
21 int nr_autogrow;
22 struct pollfd *entries;
23 union {
24 int idx;
25 } *priv;
26};
27
28void fdarray__init(struct fdarray *fda, int nr_autogrow);
29void fdarray__exit(struct fdarray *fda);
30
31struct fdarray *fdarray__new(int nr_alloc, int nr_autogrow);
32void fdarray__delete(struct fdarray *fda);
33
34int fdarray__add(struct fdarray *fda, int fd, short revents);
35int fdarray__poll(struct fdarray *fda, int timeout);
36int fdarray__filter(struct fdarray *fda, short revents,
37 void (*entry_destructor)(struct fdarray *fda, int fd));
38int fdarray__grow(struct fdarray *fda, int extra);
39int fdarray__fprintf(struct fdarray *fda, FILE *fp);
40
41static inline int fdarray__available_entries(struct fdarray *fda)
42{
43 return fda->nr_alloc - fda->nr;
44}
45
46#endif /* __API_FD_ARRAY__ */
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 782d86e961b9..717221e98450 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -15,6 +15,7 @@ perf.data
15perf.data.old 15perf.data.old
16output.svg 16output.svg
17perf-archive 17perf-archive
18perf-with-kcore
18tags 19tags
19TAGS 20TAGS
20cscope* 21cscope*
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 1513935c399b..aaa869be3dc1 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -104,6 +104,9 @@ OPTIONS
104 Specify path to the executable or shared library file for user 104 Specify path to the executable or shared library file for user
105 space tracing. Can also be used with --funcs option. 105 space tracing. Can also be used with --funcs option.
106 106
107--demangle-kernel::
108 Demangle kernel symbols.
109
107In absence of -m/-x options, perf probe checks if the first argument after 110In absence of -m/-x options, perf probe checks if the first argument after
108the options is an absolute path name. If its an absolute path, perf probe 111the options is an absolute path name. If its an absolute path, perf probe
109uses it as a target module/target user space binary to probe. 112uses it as a target module/target user space binary to probe.
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index d2b59af62bc0..0927bf4e6c2a 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -147,7 +147,7 @@ OPTIONS
147-w:: 147-w::
148--column-widths=<width[,width...]>:: 148--column-widths=<width[,width...]>::
149 Force each column width to the provided list, for large terminal 149 Force each column width to the provided list, for large terminal
150 readability. 150 readability. 0 means no limit (default behavior).
151 151
152-t:: 152-t::
153--field-separator=:: 153--field-separator=::
@@ -276,6 +276,9 @@ OPTIONS
276 Demangle symbol names to human readable form. It's enabled by default, 276 Demangle symbol names to human readable form. It's enabled by default,
277 disable with --no-demangle. 277 disable with --no-demangle.
278 278
279--demangle-kernel::
280 Demangle kernel symbol names to human readable form (for C++ kernels).
281
279--mem-mode:: 282--mem-mode::
280 Use the data addresses of samples in addition to instruction addresses 283 Use the data addresses of samples in addition to instruction addresses
281 to build the histograms. To generate meaningful output, the perf.data 284 to build the histograms. To generate meaningful output, the perf.data
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 180ae02137a5..3265b1070518 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -98,6 +98,9 @@ Default is to monitor all CPUS.
98--hide_user_symbols:: 98--hide_user_symbols::
99 Hide user symbols. 99 Hide user symbols.
100 100
101--demangle-kernel::
102 Demangle kernel symbols.
103
101-D:: 104-D::
102--dump-symtab:: 105--dump-symtab::
103 Dump the symbol table used for profiling. 106 Dump the symbol table used for profiling.
@@ -193,6 +196,12 @@ Default is to monitor all CPUS.
193 sum of shown entries will be always 100%. "absolute" means it retains 196 sum of shown entries will be always 100%. "absolute" means it retains
194 the original value before and after the filter is applied. 197 the original value before and after the filter is applied.
195 198
199-w::
200--column-widths=<width[,width...]>::
201 Force each column width to the provided list, for large terminal
202 readability. 0 means no limit (default behavior).
203
204
196INTERACTIVE PROMPTING KEYS 205INTERACTIVE PROMPTING KEYS
197-------------------------- 206--------------------------
198 207
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 2240974b7745..262916f4a377 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -126,6 +126,7 @@ PYRF_OBJS =
126SCRIPT_SH = 126SCRIPT_SH =
127 127
128SCRIPT_SH += perf-archive.sh 128SCRIPT_SH += perf-archive.sh
129SCRIPT_SH += perf-with-kcore.sh
129 130
130grep-libs = $(filter -l%,$(1)) 131grep-libs = $(filter -l%,$(1))
131strip-libs = $(filter-out -l%,$(1)) 132strip-libs = $(filter-out -l%,$(1))
@@ -263,6 +264,7 @@ LIB_H += util/xyarray.h
263LIB_H += util/header.h 264LIB_H += util/header.h
264LIB_H += util/help.h 265LIB_H += util/help.h
265LIB_H += util/session.h 266LIB_H += util/session.h
267LIB_H += util/ordered-events.h
266LIB_H += util/strbuf.h 268LIB_H += util/strbuf.h
267LIB_H += util/strlist.h 269LIB_H += util/strlist.h
268LIB_H += util/strfilter.h 270LIB_H += util/strfilter.h
@@ -347,6 +349,7 @@ LIB_OBJS += $(OUTPUT)util/machine.o
347LIB_OBJS += $(OUTPUT)util/map.o 349LIB_OBJS += $(OUTPUT)util/map.o
348LIB_OBJS += $(OUTPUT)util/pstack.o 350LIB_OBJS += $(OUTPUT)util/pstack.o
349LIB_OBJS += $(OUTPUT)util/session.o 351LIB_OBJS += $(OUTPUT)util/session.o
352LIB_OBJS += $(OUTPUT)util/ordered-events.o
350LIB_OBJS += $(OUTPUT)util/comm.o 353LIB_OBJS += $(OUTPUT)util/comm.o
351LIB_OBJS += $(OUTPUT)util/thread.o 354LIB_OBJS += $(OUTPUT)util/thread.o
352LIB_OBJS += $(OUTPUT)util/thread_map.o 355LIB_OBJS += $(OUTPUT)util/thread_map.o
@@ -399,6 +402,7 @@ LIB_OBJS += $(OUTPUT)tests/perf-record.o
399LIB_OBJS += $(OUTPUT)tests/rdpmc.o 402LIB_OBJS += $(OUTPUT)tests/rdpmc.o
400LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o 403LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
401LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o 404LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
405LIB_OBJS += $(OUTPUT)tests/fdarray.o
402LIB_OBJS += $(OUTPUT)tests/pmu.o 406LIB_OBJS += $(OUTPUT)tests/pmu.o
403LIB_OBJS += $(OUTPUT)tests/hists_common.o 407LIB_OBJS += $(OUTPUT)tests/hists_common.o
404LIB_OBJS += $(OUTPUT)tests/hists_link.o 408LIB_OBJS += $(OUTPUT)tests/hists_link.o
@@ -423,6 +427,7 @@ endif
423endif 427endif
424LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o 428LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
425LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o 429LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
430LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
426 431
427BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 432BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
428BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 433BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -765,7 +770,7 @@ $(LIBTRACEEVENT)-clean:
765install-traceevent-plugins: $(LIBTRACEEVENT) 770install-traceevent-plugins: $(LIBTRACEEVENT)
766 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins 771 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins
767 772
768LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch]) 773LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch] $(LIB_PATH)fd/*.[ch])
769 774
770# if subdir is set, we've been called from above so target has been built 775# if subdir is set, we've been called from above so target has been built
771# already 776# already
@@ -875,6 +880,8 @@ install-bin: all install-gtk
875 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 880 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
876 $(call QUIET_INSTALL, perf-archive) \ 881 $(call QUIET_INSTALL, perf-archive) \
877 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 882 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
883 $(call QUIET_INSTALL, perf-with-kcore) \
884 $(INSTALL) $(OUTPUT)perf-with-kcore -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
878ifndef NO_LIBPERL 885ifndef NO_LIBPERL
879 $(call QUIET_INSTALL, perl-scripts) \ 886 $(call QUIET_INSTALL, perl-scripts) \
880 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \ 887 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
@@ -920,7 +927,7 @@ config-clean:
920 @$(MAKE) -C config/feature-checks clean >/dev/null 927 @$(MAKE) -C config/feature-checks clean >/dev/null
921 928
922clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 929clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
923 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 930 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
924 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 931 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
925 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 932 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
926 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 933 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
diff --git a/tools/perf/arch/arm/tests/dwarf-unwind.c b/tools/perf/arch/arm/tests/dwarf-unwind.c
index 9f870d27cb39..62eff847f91c 100644
--- a/tools/perf/arch/arm/tests/dwarf-unwind.c
+++ b/tools/perf/arch/arm/tests/dwarf-unwind.c
@@ -3,6 +3,7 @@
3#include "thread.h" 3#include "thread.h"
4#include "map.h" 4#include "map.h"
5#include "event.h" 5#include "event.h"
6#include "debug.h"
6#include "tests/tests.h" 7#include "tests/tests.h"
7 8
8#define STACK_SIZE 8192 9#define STACK_SIZE 8192
diff --git a/tools/perf/arch/arm/util/unwind-libunwind.c b/tools/perf/arch/arm/util/unwind-libunwind.c
index 729ed69a6664..62c397ed3d97 100644
--- a/tools/perf/arch/arm/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm/util/unwind-libunwind.c
@@ -3,6 +3,7 @@
3#include <libunwind.h> 3#include <libunwind.h>
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6#include "../../util/debug.h"
6 7
7int libunwind__arch_reg_id(int regnum) 8int libunwind__arch_reg_id(int regnum)
8{ 9{
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
index e9441b9e2a30..1d3f39c3aa56 100644
--- a/tools/perf/arch/arm64/include/perf_regs.h
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -6,6 +6,8 @@
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1) 8#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_ARM64_MAX
10
9#define PERF_REG_IP PERF_REG_ARM64_PC 11#define PERF_REG_IP PERF_REG_ARM64_PC
10#define PERF_REG_SP PERF_REG_ARM64_SP 12#define PERF_REG_SP PERF_REG_ARM64_SP
11 13
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c
index 436ee43859dc..a87afa91a99e 100644
--- a/tools/perf/arch/arm64/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm64/util/unwind-libunwind.c
@@ -3,6 +3,7 @@
3#include <libunwind.h> 3#include <libunwind.h>
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6#include "../../util/debug.h"
6 7
7int libunwind__arch_reg_id(int regnum) 8int libunwind__arch_reg_id(int regnum)
8{ 9{
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 42faf369211c..49776f190abf 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -12,6 +12,11 @@ const char *const arm_triplets[] = {
12 NULL 12 NULL
13}; 13};
14 14
15const char *const arm64_triplets[] = {
16 "aarch64-linux-android-",
17 NULL
18};
19
15const char *const powerpc_triplets[] = { 20const char *const powerpc_triplets[] = {
16 "powerpc-unknown-linux-gnu-", 21 "powerpc-unknown-linux-gnu-",
17 "powerpc64-unknown-linux-gnu-", 22 "powerpc64-unknown-linux-gnu-",
@@ -105,6 +110,8 @@ static const char *normalize_arch(char *arch)
105 return "x86"; 110 return "x86";
106 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5)) 111 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5))
107 return "sparc"; 112 return "sparc";
113 if (!strcmp(arch, "aarch64") || !strcmp(arch, "arm64"))
114 return "arm64";
108 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110")) 115 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110"))
109 return "arm"; 116 return "arm";
110 if (!strncmp(arch, "s390", 4)) 117 if (!strncmp(arch, "s390", 4))
@@ -159,6 +166,8 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
159 166
160 if (!strcmp(arch, "arm")) 167 if (!strcmp(arch, "arm"))
161 path_list = arm_triplets; 168 path_list = arm_triplets;
169 else if (!strcmp(arch, "arm64"))
170 path_list = arm64_triplets;
162 else if (!strcmp(arch, "powerpc")) 171 else if (!strcmp(arch, "powerpc"))
163 path_list = powerpc_triplets; 172 path_list = powerpc_triplets;
164 else if (!strcmp(arch, "sh")) 173 else if (!strcmp(arch, "sh"))
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index b92219b1900d..6f7782bea5dd 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -1,6 +1,6 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
4endif 5endif
5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o 6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index a7c23a4b3778..d73ef8bb08c7 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -15,6 +15,7 @@
15 15
16#include "util/thread.h" 16#include "util/thread.h"
17#include "util/callchain.h" 17#include "util/callchain.h"
18#include "util/debug.h"
18 19
19/* 20/*
20 * When saving the callchain on Power, the kernel conservatively saves 21 * When saving the callchain on Power, the kernel conservatively saves
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index a84206e9c4aa..fc9bebd2cca0 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -26,6 +26,7 @@ static unsigned int nsecs = 10;
26/* amount of futexes per thread */ 26/* amount of futexes per thread */
27static unsigned int nfutexes = 1024; 27static unsigned int nfutexes = 1024;
28static bool fshared = false, done = false, silent = false; 28static bool fshared = false, done = false, silent = false;
29static int futex_flag = 0;
29 30
30struct timeval start, end, runtime; 31struct timeval start, end, runtime;
31static pthread_mutex_t thread_lock; 32static pthread_mutex_t thread_lock;
@@ -75,8 +76,7 @@ static void *workerfn(void *arg)
75 * such as internal waitqueue handling, thus enlarging 76 * such as internal waitqueue handling, thus enlarging
76 * the critical region protected by hb->lock. 77 * the critical region protected by hb->lock.
77 */ 78 */
78 ret = futex_wait(&w->futex[i], 1234, NULL, 79 ret = futex_wait(&w->futex[i], 1234, NULL, futex_flag);
79 fshared ? 0 : FUTEX_PRIVATE_FLAG);
80 if (!silent && 80 if (!silent &&
81 (!ret || errno != EAGAIN || errno != EWOULDBLOCK)) 81 (!ret || errno != EAGAIN || errno != EWOULDBLOCK))
82 warn("Non-expected futex return call"); 82 warn("Non-expected futex return call");
@@ -135,6 +135,9 @@ int bench_futex_hash(int argc, const char **argv,
135 if (!worker) 135 if (!worker)
136 goto errmem; 136 goto errmem;
137 137
138 if (!fshared)
139 futex_flag = FUTEX_PRIVATE_FLAG;
140
138 printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n", 141 printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n",
139 getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs); 142 getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs);
140 143
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 732403bfd31a..bedff6b5b3cf 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -30,16 +30,18 @@ static u_int32_t futex1 = 0, futex2 = 0;
30static unsigned int nrequeue = 1; 30static unsigned int nrequeue = 1;
31 31
32static pthread_t *worker; 32static pthread_t *worker;
33static bool done = 0, silent = 0; 33static bool done = false, silent = false, fshared = false;
34static pthread_mutex_t thread_lock; 34static pthread_mutex_t thread_lock;
35static pthread_cond_t thread_parent, thread_worker; 35static pthread_cond_t thread_parent, thread_worker;
36static struct stats requeuetime_stats, requeued_stats; 36static struct stats requeuetime_stats, requeued_stats;
37static unsigned int ncpus, threads_starting, nthreads = 0; 37static unsigned int ncpus, threads_starting, nthreads = 0;
38static int futex_flag = 0;
38 39
39static const struct option options[] = { 40static const struct option options[] = {
40 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"), 41 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
41 OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"), 42 OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"),
42 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"), 43 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
44 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
43 OPT_END() 45 OPT_END()
44}; 46};
45 47
@@ -70,7 +72,7 @@ static void *workerfn(void *arg __maybe_unused)
70 pthread_cond_wait(&thread_worker, &thread_lock); 72 pthread_cond_wait(&thread_worker, &thread_lock);
71 pthread_mutex_unlock(&thread_lock); 73 pthread_mutex_unlock(&thread_lock);
72 74
73 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG); 75 futex_wait(&futex1, 0, NULL, futex_flag);
74 return NULL; 76 return NULL;
75} 77}
76 78
@@ -127,9 +129,12 @@ int bench_futex_requeue(int argc, const char **argv,
127 if (!worker) 129 if (!worker)
128 err(EXIT_FAILURE, "calloc"); 130 err(EXIT_FAILURE, "calloc");
129 131
130 printf("Run summary [PID %d]: Requeuing %d threads (from %p to %p), " 132 if (!fshared)
131 "%d at a time.\n\n", 133 futex_flag = FUTEX_PRIVATE_FLAG;
132 getpid(), nthreads, &futex1, &futex2, nrequeue); 134
135 printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
136 "%d at a time.\n\n", getpid(), nthreads,
137 fshared ? "shared":"private", &futex1, &futex2, nrequeue);
133 138
134 init_stats(&requeued_stats); 139 init_stats(&requeued_stats);
135 init_stats(&requeuetime_stats); 140 init_stats(&requeuetime_stats);
@@ -156,16 +161,20 @@ int bench_futex_requeue(int argc, const char **argv,
156 161
157 /* Ok, all threads are patiently blocked, start requeueing */ 162 /* Ok, all threads are patiently blocked, start requeueing */
158 gettimeofday(&start, NULL); 163 gettimeofday(&start, NULL);
159 for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) 164 for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) {
160 /* 165 /*
161 * Do not wakeup any tasks blocked on futex1, allowing 166 * Do not wakeup any tasks blocked on futex1, allowing
162 * us to really measure futex_wait functionality. 167 * us to really measure futex_wait functionality.
163 */ 168 */
164 futex_cmp_requeue(&futex1, 0, &futex2, 0, nrequeue, 169 futex_cmp_requeue(&futex1, 0, &futex2, 0,
165 FUTEX_PRIVATE_FLAG); 170 nrequeue, futex_flag);
171 }
166 gettimeofday(&end, NULL); 172 gettimeofday(&end, NULL);
167 timersub(&end, &start, &runtime); 173 timersub(&end, &start, &runtime);
168 174
175 if (nrequeued > nthreads)
176 nrequeued = nthreads;
177
169 update_stats(&requeued_stats, nrequeued); 178 update_stats(&requeued_stats, nrequeued);
170 update_stats(&requeuetime_stats, runtime.tv_usec); 179 update_stats(&requeuetime_stats, runtime.tv_usec);
171 180
@@ -175,7 +184,7 @@ int bench_futex_requeue(int argc, const char **argv,
175 } 184 }
176 185
177 /* everybody should be blocked on futex2, wake'em up */ 186 /* everybody should be blocked on futex2, wake'em up */
178 nrequeued = futex_wake(&futex2, nthreads, FUTEX_PRIVATE_FLAG); 187 nrequeued = futex_wake(&futex2, nthreads, futex_flag);
179 if (nthreads != nrequeued) 188 if (nthreads != nrequeued)
180 warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads); 189 warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
181 190
@@ -184,7 +193,6 @@ int bench_futex_requeue(int argc, const char **argv,
184 if (ret) 193 if (ret)
185 err(EXIT_FAILURE, "pthread_join"); 194 err(EXIT_FAILURE, "pthread_join");
186 } 195 }
187
188 } 196 }
189 197
190 /* cleanup & report results */ 198 /* cleanup & report results */
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 50022cbce87e..929f762be47e 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -31,16 +31,18 @@ static u_int32_t futex1 = 0;
31static unsigned int nwakes = 1; 31static unsigned int nwakes = 1;
32 32
33pthread_t *worker; 33pthread_t *worker;
34static bool done = false, silent = false; 34static bool done = false, silent = false, fshared = false;
35static pthread_mutex_t thread_lock; 35static pthread_mutex_t thread_lock;
36static pthread_cond_t thread_parent, thread_worker; 36static pthread_cond_t thread_parent, thread_worker;
37static struct stats waketime_stats, wakeup_stats; 37static struct stats waketime_stats, wakeup_stats;
38static unsigned int ncpus, threads_starting, nthreads = 0; 38static unsigned int ncpus, threads_starting, nthreads = 0;
39static int futex_flag = 0;
39 40
40static const struct option options[] = { 41static const struct option options[] = {
41 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"), 42 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
42 OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"), 43 OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"),
43 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"), 44 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
45 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
44 OPT_END() 46 OPT_END()
45}; 47};
46 48
@@ -58,7 +60,7 @@ static void *workerfn(void *arg __maybe_unused)
58 pthread_cond_wait(&thread_worker, &thread_lock); 60 pthread_cond_wait(&thread_worker, &thread_lock);
59 pthread_mutex_unlock(&thread_lock); 61 pthread_mutex_unlock(&thread_lock);
60 62
61 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG); 63 futex_wait(&futex1, 0, NULL, futex_flag);
62 return NULL; 64 return NULL;
63} 65}
64 66
@@ -130,9 +132,12 @@ int bench_futex_wake(int argc, const char **argv,
130 if (!worker) 132 if (!worker)
131 err(EXIT_FAILURE, "calloc"); 133 err(EXIT_FAILURE, "calloc");
132 134
133 printf("Run summary [PID %d]: blocking on %d threads (at futex %p), " 135 if (!fshared)
136 futex_flag = FUTEX_PRIVATE_FLAG;
137
138 printf("Run summary [PID %d]: blocking on %d threads (at [%s] futex %p), "
134 "waking up %d at a time.\n\n", 139 "waking up %d at a time.\n\n",
135 getpid(), nthreads, &futex1, nwakes); 140 getpid(), nthreads, fshared ? "shared":"private", &futex1, nwakes);
136 141
137 init_stats(&wakeup_stats); 142 init_stats(&wakeup_stats);
138 init_stats(&waketime_stats); 143 init_stats(&waketime_stats);
@@ -160,7 +165,7 @@ int bench_futex_wake(int argc, const char **argv,
160 /* Ok, all threads are patiently blocked, start waking folks up */ 165 /* Ok, all threads are patiently blocked, start waking folks up */
161 gettimeofday(&start, NULL); 166 gettimeofday(&start, NULL);
162 while (nwoken != nthreads) 167 while (nwoken != nthreads)
163 nwoken += futex_wake(&futex1, nwakes, FUTEX_PRIVATE_FLAG); 168 nwoken += futex_wake(&futex1, nwakes, futex_flag);
164 gettimeofday(&end, NULL); 169 gettimeofday(&end, NULL);
165 timersub(&end, &start, &runtime); 170 timersub(&end, &start, &runtime);
166 171
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index 52a56599a543..d7f281c2828d 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -26,7 +26,7 @@
26#include <sys/socket.h> 26#include <sys/socket.h>
27#include <sys/wait.h> 27#include <sys/wait.h>
28#include <sys/time.h> 28#include <sys/time.h>
29#include <sys/poll.h> 29#include <poll.h>
30#include <limits.h> 30#include <limits.h>
31#include <err.h> 31#include <err.h>
32 32
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1ec429fef2be..be5939418425 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -36,7 +36,8 @@
36 36
37struct perf_annotate { 37struct perf_annotate {
38 struct perf_tool tool; 38 struct perf_tool tool;
39 bool force, use_tui, use_stdio, use_gtk; 39 struct perf_session *session;
40 bool use_tui, use_stdio, use_gtk;
40 bool full_paths; 41 bool full_paths;
41 bool print_line; 42 bool print_line;
42 bool skip_missing; 43 bool skip_missing;
@@ -188,18 +189,9 @@ find_next:
188static int __cmd_annotate(struct perf_annotate *ann) 189static int __cmd_annotate(struct perf_annotate *ann)
189{ 190{
190 int ret; 191 int ret;
191 struct perf_session *session; 192 struct perf_session *session = ann->session;
192 struct perf_evsel *pos; 193 struct perf_evsel *pos;
193 u64 total_nr_samples; 194 u64 total_nr_samples;
194 struct perf_data_file file = {
195 .path = input_name,
196 .mode = PERF_DATA_MODE_READ,
197 .force = ann->force,
198 };
199
200 session = perf_session__new(&file, false, &ann->tool);
201 if (session == NULL)
202 return -ENOMEM;
203 195
204 machines__set_symbol_filter(&session->machines, symbol__annotate_init); 196 machines__set_symbol_filter(&session->machines, symbol__annotate_init);
205 197
@@ -207,22 +199,22 @@ static int __cmd_annotate(struct perf_annotate *ann)
207 ret = perf_session__cpu_bitmap(session, ann->cpu_list, 199 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
208 ann->cpu_bitmap); 200 ann->cpu_bitmap);
209 if (ret) 201 if (ret)
210 goto out_delete; 202 goto out;
211 } 203 }
212 204
213 if (!objdump_path) { 205 if (!objdump_path) {
214 ret = perf_session_env__lookup_objdump(&session->header.env); 206 ret = perf_session_env__lookup_objdump(&session->header.env);
215 if (ret) 207 if (ret)
216 goto out_delete; 208 goto out;
217 } 209 }
218 210
219 ret = perf_session__process_events(session, &ann->tool); 211 ret = perf_session__process_events(session, &ann->tool);
220 if (ret) 212 if (ret)
221 goto out_delete; 213 goto out;
222 214
223 if (dump_trace) { 215 if (dump_trace) {
224 perf_session__fprintf_nr_events(session, stdout); 216 perf_session__fprintf_nr_events(session, stdout);
225 goto out_delete; 217 goto out;
226 } 218 }
227 219
228 if (verbose > 3) 220 if (verbose > 3)
@@ -250,8 +242,8 @@ static int __cmd_annotate(struct perf_annotate *ann)
250 } 242 }
251 243
252 if (total_nr_samples == 0) { 244 if (total_nr_samples == 0) {
253 ui__error("The %s file has no samples!\n", file.path); 245 ui__error("The %s file has no samples!\n", session->file->path);
254 goto out_delete; 246 goto out;
255 } 247 }
256 248
257 if (use_browser == 2) { 249 if (use_browser == 2) {
@@ -261,24 +253,12 @@ static int __cmd_annotate(struct perf_annotate *ann)
261 "perf_gtk__show_annotations"); 253 "perf_gtk__show_annotations");
262 if (show_annotations == NULL) { 254 if (show_annotations == NULL) {
263 ui__error("GTK browser not found!\n"); 255 ui__error("GTK browser not found!\n");
264 goto out_delete; 256 goto out;
265 } 257 }
266 show_annotations(); 258 show_annotations();
267 } 259 }
268 260
269out_delete: 261out:
270 /*
271 * Speed up the exit process, for large files this can
272 * take quite a while.
273 *
274 * XXX Enable this when using valgrind or if we ever
275 * librarize this command.
276 *
277 * Also experiment with obstacks to see how much speed
278 * up we'll get here.
279 *
280 * perf_session__delete(session);
281 */
282 return ret; 262 return ret;
283} 263}
284 264
@@ -297,10 +277,14 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
297 .comm = perf_event__process_comm, 277 .comm = perf_event__process_comm,
298 .exit = perf_event__process_exit, 278 .exit = perf_event__process_exit,
299 .fork = perf_event__process_fork, 279 .fork = perf_event__process_fork,
300 .ordered_samples = true, 280 .ordered_events = true,
301 .ordering_requires_timestamps = true, 281 .ordering_requires_timestamps = true,
302 }, 282 },
303 }; 283 };
284 struct perf_data_file file = {
285 .path = input_name,
286 .mode = PERF_DATA_MODE_READ,
287 };
304 const struct option options[] = { 288 const struct option options[] = {
305 OPT_STRING('i', "input", &input_name, "file", 289 OPT_STRING('i', "input", &input_name, "file",
306 "input file name"), 290 "input file name"),
@@ -308,7 +292,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
308 "only consider symbols in these dsos"), 292 "only consider symbols in these dsos"),
309 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", 293 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
310 "symbol to annotate"), 294 "symbol to annotate"),
311 OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"), 295 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
312 OPT_INCR('v', "verbose", &verbose, 296 OPT_INCR('v', "verbose", &verbose,
313 "be more verbose (show symbol address, etc)"), 297 "be more verbose (show symbol address, etc)"),
314 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 298 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
@@ -341,6 +325,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
341 "Show event group information together"), 325 "Show event group information together"),
342 OPT_END() 326 OPT_END()
343 }; 327 };
328 int ret;
344 329
345 argc = parse_options(argc, argv, options, annotate_usage, 0); 330 argc = parse_options(argc, argv, options, annotate_usage, 0);
346 331
@@ -353,11 +338,16 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
353 338
354 setup_browser(true); 339 setup_browser(true);
355 340
341 annotate.session = perf_session__new(&file, false, &annotate.tool);
342 if (annotate.session == NULL)
343 return -1;
344
356 symbol_conf.priv_size = sizeof(struct annotation); 345 symbol_conf.priv_size = sizeof(struct annotation);
357 symbol_conf.try_vmlinux_path = true; 346 symbol_conf.try_vmlinux_path = true;
358 347
359 if (symbol__init() < 0) 348 ret = symbol__init(&annotate.session->header.env);
360 return -1; 349 if (ret < 0)
350 goto out_delete;
361 351
362 if (setup_sorting() < 0) 352 if (setup_sorting() < 0)
363 usage_with_options(annotate_usage, options); 353 usage_with_options(annotate_usage, options);
@@ -373,5 +363,20 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
373 annotate.sym_hist_filter = argv[0]; 363 annotate.sym_hist_filter = argv[0];
374 } 364 }
375 365
376 return __cmd_annotate(&annotate); 366 ret = __cmd_annotate(&annotate);
367
368out_delete:
369 /*
370 * Speed up the exit process, for large files this can
371 * take quite a while.
372 *
373 * XXX Enable this when using valgrind or if we ever
374 * librarize this command.
375 *
376 * Also experiment with obstacks to see how much speed
377 * up we'll get here.
378 *
379 * perf_session__delete(session);
380 */
381 return ret;
377} 382}
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 2a2c78f80876..70385756da63 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -246,20 +246,9 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
246 return true; 246 return true;
247} 247}
248 248
249static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) 249static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *fp)
250{ 250{
251 struct perf_data_file file = {
252 .path = filename,
253 .mode = PERF_DATA_MODE_READ,
254 .force = force,
255 };
256 struct perf_session *session = perf_session__new(&file, false, NULL);
257 if (session == NULL)
258 return -1;
259
260 perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0); 251 perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0);
261 perf_session__delete(session);
262
263 return 0; 252 return 0;
264} 253}
265 254
@@ -302,6 +291,12 @@ int cmd_buildid_cache(int argc, const char **argv,
302 *missing_filename = NULL, 291 *missing_filename = NULL,
303 *update_name_list_str = NULL, 292 *update_name_list_str = NULL,
304 *kcore_filename; 293 *kcore_filename;
294 char sbuf[STRERR_BUFSIZE];
295
296 struct perf_data_file file = {
297 .mode = PERF_DATA_MODE_READ,
298 };
299 struct perf_session *session = NULL;
305 300
306 const struct option buildid_cache_options[] = { 301 const struct option buildid_cache_options[] = {
307 OPT_STRING('a', "add", &add_name_list_str, 302 OPT_STRING('a', "add", &add_name_list_str,
@@ -326,8 +321,17 @@ int cmd_buildid_cache(int argc, const char **argv,
326 argc = parse_options(argc, argv, buildid_cache_options, 321 argc = parse_options(argc, argv, buildid_cache_options,
327 buildid_cache_usage, 0); 322 buildid_cache_usage, 0);
328 323
329 if (symbol__init() < 0) 324 if (missing_filename) {
330 return -1; 325 file.path = missing_filename;
326 file.force = force;
327
328 session = perf_session__new(&file, false, NULL);
329 if (session == NULL)
330 return -1;
331 }
332
333 if (symbol__init(session ? &session->header.env : NULL) < 0)
334 goto out;
331 335
332 setup_pager(); 336 setup_pager();
333 337
@@ -344,7 +348,7 @@ int cmd_buildid_cache(int argc, const char **argv,
344 continue; 348 continue;
345 } 349 }
346 pr_warning("Couldn't add %s: %s\n", 350 pr_warning("Couldn't add %s: %s\n",
347 pos->s, strerror(errno)); 351 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
348 } 352 }
349 353
350 strlist__delete(list); 354 strlist__delete(list);
@@ -362,7 +366,7 @@ int cmd_buildid_cache(int argc, const char **argv,
362 continue; 366 continue;
363 } 367 }
364 pr_warning("Couldn't remove %s: %s\n", 368 pr_warning("Couldn't remove %s: %s\n",
365 pos->s, strerror(errno)); 369 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
366 } 370 }
367 371
368 strlist__delete(list); 372 strlist__delete(list);
@@ -370,7 +374,7 @@ int cmd_buildid_cache(int argc, const char **argv,
370 } 374 }
371 375
372 if (missing_filename) 376 if (missing_filename)
373 ret = build_id_cache__fprintf_missing(missing_filename, force, stdout); 377 ret = build_id_cache__fprintf_missing(session, stdout);
374 378
375 if (update_name_list_str) { 379 if (update_name_list_str) {
376 list = strlist__new(true, update_name_list_str); 380 list = strlist__new(true, update_name_list_str);
@@ -383,7 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv,
383 continue; 387 continue;
384 } 388 }
385 pr_warning("Couldn't update %s: %s\n", 389 pr_warning("Couldn't update %s: %s\n",
386 pos->s, strerror(errno)); 390 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
387 } 391 }
388 392
389 strlist__delete(list); 393 strlist__delete(list);
@@ -394,5 +398,9 @@ int cmd_buildid_cache(int argc, const char **argv,
394 build_id_cache__add_kcore(kcore_filename, debugdir, force)) 398 build_id_cache__add_kcore(kcore_filename, debugdir, force))
395 pr_warning("Couldn't add %s\n", kcore_filename); 399 pr_warning("Couldn't add %s\n", kcore_filename);
396 400
401out:
402 if (session)
403 perf_session__delete(session);
404
397 return ret; 405 return ret;
398} 406}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 9a5a035cb426..a3ce19f7aebd 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -360,7 +360,7 @@ static struct perf_tool tool = {
360 .exit = perf_event__process_exit, 360 .exit = perf_event__process_exit,
361 .fork = perf_event__process_fork, 361 .fork = perf_event__process_fork,
362 .lost = perf_event__process_lost, 362 .lost = perf_event__process_lost,
363 .ordered_samples = true, 363 .ordered_events = true,
364 .ordering_requires_timestamps = true, 364 .ordering_requires_timestamps = true,
365}; 365};
366 366
@@ -683,7 +683,7 @@ static int __cmd_diff(void)
683 d->session = perf_session__new(&d->file, false, &tool); 683 d->session = perf_session__new(&d->file, false, &tool);
684 if (!d->session) { 684 if (!d->session) {
685 pr_err("Failed to open %s\n", d->file.path); 685 pr_err("Failed to open %s\n", d->file.path);
686 ret = -ENOMEM; 686 ret = -1;
687 goto out_delete; 687 goto out_delete;
688 } 688 }
689 689
@@ -1143,7 +1143,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1143 1143
1144 argc = parse_options(argc, argv, options, diff_usage, 0); 1144 argc = parse_options(argc, argv, options, diff_usage, 0);
1145 1145
1146 if (symbol__init() < 0) 1146 if (symbol__init(NULL) < 0)
1147 return -1; 1147 return -1;
1148 1148
1149 if (data_init(argc, argv) < 0) 1149 if (data_init(argc, argv) < 0)
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 66e12f55c052..0f93f859b782 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -28,7 +28,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
28 28
29 session = perf_session__new(&file, 0, NULL); 29 session = perf_session__new(&file, 0, NULL);
30 if (session == NULL) 30 if (session == NULL)
31 return -ENOMEM; 31 return -1;
32 32
33 evlist__for_each(session->evlist, pos) 33 evlist__for_each(session->evlist, pos)
34 perf_evsel__fprintf(pos, details, stdout); 34 perf_evsel__fprintf(pos, details, stdout);
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 0384d930480b..25d20628212e 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -103,6 +103,8 @@ static int check_emacsclient_version(void)
103 103
104static void exec_woman_emacs(const char *path, const char *page) 104static void exec_woman_emacs(const char *path, const char *page)
105{ 105{
106 char sbuf[STRERR_BUFSIZE];
107
106 if (!check_emacsclient_version()) { 108 if (!check_emacsclient_version()) {
107 /* This works only with emacsclient version >= 22. */ 109 /* This works only with emacsclient version >= 22. */
108 struct strbuf man_page = STRBUF_INIT; 110 struct strbuf man_page = STRBUF_INIT;
@@ -111,16 +113,19 @@ static void exec_woman_emacs(const char *path, const char *page)
111 path = "emacsclient"; 113 path = "emacsclient";
112 strbuf_addf(&man_page, "(woman \"%s\")", page); 114 strbuf_addf(&man_page, "(woman \"%s\")", page);
113 execlp(path, "emacsclient", "-e", man_page.buf, NULL); 115 execlp(path, "emacsclient", "-e", man_page.buf, NULL);
114 warning("failed to exec '%s': %s", path, strerror(errno)); 116 warning("failed to exec '%s': %s", path,
117 strerror_r(errno, sbuf, sizeof(sbuf)));
115 } 118 }
116} 119}
117 120
118static void exec_man_konqueror(const char *path, const char *page) 121static void exec_man_konqueror(const char *path, const char *page)
119{ 122{
120 const char *display = getenv("DISPLAY"); 123 const char *display = getenv("DISPLAY");
124
121 if (display && *display) { 125 if (display && *display) {
122 struct strbuf man_page = STRBUF_INIT; 126 struct strbuf man_page = STRBUF_INIT;
123 const char *filename = "kfmclient"; 127 const char *filename = "kfmclient";
128 char sbuf[STRERR_BUFSIZE];
124 129
125 /* It's simpler to launch konqueror using kfmclient. */ 130 /* It's simpler to launch konqueror using kfmclient. */
126 if (path) { 131 if (path) {
@@ -139,24 +144,31 @@ static void exec_man_konqueror(const char *path, const char *page)
139 path = "kfmclient"; 144 path = "kfmclient";
140 strbuf_addf(&man_page, "man:%s(1)", page); 145 strbuf_addf(&man_page, "man:%s(1)", page);
141 execlp(path, filename, "newTab", man_page.buf, NULL); 146 execlp(path, filename, "newTab", man_page.buf, NULL);
142 warning("failed to exec '%s': %s", path, strerror(errno)); 147 warning("failed to exec '%s': %s", path,
148 strerror_r(errno, sbuf, sizeof(sbuf)));
143 } 149 }
144} 150}
145 151
146static void exec_man_man(const char *path, const char *page) 152static void exec_man_man(const char *path, const char *page)
147{ 153{
154 char sbuf[STRERR_BUFSIZE];
155
148 if (!path) 156 if (!path)
149 path = "man"; 157 path = "man";
150 execlp(path, "man", page, NULL); 158 execlp(path, "man", page, NULL);
151 warning("failed to exec '%s': %s", path, strerror(errno)); 159 warning("failed to exec '%s': %s", path,
160 strerror_r(errno, sbuf, sizeof(sbuf)));
152} 161}
153 162
154static void exec_man_cmd(const char *cmd, const char *page) 163static void exec_man_cmd(const char *cmd, const char *page)
155{ 164{
156 struct strbuf shell_cmd = STRBUF_INIT; 165 struct strbuf shell_cmd = STRBUF_INIT;
166 char sbuf[STRERR_BUFSIZE];
167
157 strbuf_addf(&shell_cmd, "%s %s", cmd, page); 168 strbuf_addf(&shell_cmd, "%s %s", cmd, page);
158 execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL); 169 execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL);
159 warning("failed to exec '%s': %s", cmd, strerror(errno)); 170 warning("failed to exec '%s': %s", cmd,
171 strerror_r(errno, sbuf, sizeof(sbuf)));
160} 172}
161 173
162static void add_man_viewer(const char *name) 174static void add_man_viewer(const char *name)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9a02807387d6..de99ca1bb942 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -23,6 +23,7 @@
23 23
24struct perf_inject { 24struct perf_inject {
25 struct perf_tool tool; 25 struct perf_tool tool;
26 struct perf_session *session;
26 bool build_ids; 27 bool build_ids;
27 bool sched_stat; 28 bool sched_stat;
28 const char *input_name; 29 const char *input_name;
@@ -340,12 +341,8 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
340 341
341static int __cmd_inject(struct perf_inject *inject) 342static int __cmd_inject(struct perf_inject *inject)
342{ 343{
343 struct perf_session *session;
344 int ret = -EINVAL; 344 int ret = -EINVAL;
345 struct perf_data_file file = { 345 struct perf_session *session = inject->session;
346 .path = inject->input_name,
347 .mode = PERF_DATA_MODE_READ,
348 };
349 struct perf_data_file *file_out = &inject->output; 346 struct perf_data_file *file_out = &inject->output;
350 347
351 signal(SIGINT, sig_handler); 348 signal(SIGINT, sig_handler);
@@ -357,16 +354,12 @@ static int __cmd_inject(struct perf_inject *inject)
357 inject->tool.tracing_data = perf_event__repipe_tracing_data; 354 inject->tool.tracing_data = perf_event__repipe_tracing_data;
358 } 355 }
359 356
360 session = perf_session__new(&file, true, &inject->tool);
361 if (session == NULL)
362 return -ENOMEM;
363
364 if (inject->build_ids) { 357 if (inject->build_ids) {
365 inject->tool.sample = perf_event__inject_buildid; 358 inject->tool.sample = perf_event__inject_buildid;
366 } else if (inject->sched_stat) { 359 } else if (inject->sched_stat) {
367 struct perf_evsel *evsel; 360 struct perf_evsel *evsel;
368 361
369 inject->tool.ordered_samples = true; 362 inject->tool.ordered_events = true;
370 363
371 evlist__for_each(session->evlist, evsel) { 364 evlist__for_each(session->evlist, evsel) {
372 const char *name = perf_evsel__name(evsel); 365 const char *name = perf_evsel__name(evsel);
@@ -396,8 +389,6 @@ static int __cmd_inject(struct perf_inject *inject)
396 perf_session__write_header(session, session->evlist, file_out->fd, true); 389 perf_session__write_header(session, session->evlist, file_out->fd, true);
397 } 390 }
398 391
399 perf_session__delete(session);
400
401 return ret; 392 return ret;
402} 393}
403 394
@@ -427,6 +418,11 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
427 .mode = PERF_DATA_MODE_WRITE, 418 .mode = PERF_DATA_MODE_WRITE,
428 }, 419 },
429 }; 420 };
421 struct perf_data_file file = {
422 .mode = PERF_DATA_MODE_READ,
423 };
424 int ret;
425
430 const struct option options[] = { 426 const struct option options[] = {
431 OPT_BOOLEAN('b', "build-ids", &inject.build_ids, 427 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
432 "Inject build-ids into the output stream"), 428 "Inject build-ids into the output stream"),
@@ -461,8 +457,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
461 return -1; 457 return -1;
462 } 458 }
463 459
464 if (symbol__init() < 0) 460 file.path = inject.input_name;
461 inject.session = perf_session__new(&file, true, &inject.tool);
462 if (inject.session == NULL)
463 return -1;
464
465 if (symbol__init(&inject.session->header.env) < 0)
465 return -1; 466 return -1;
466 467
467 return __cmd_inject(&inject); 468 ret = __cmd_inject(&inject);
469
470 perf_session__delete(inject.session);
471
472 return ret;
468} 473}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index bef3376bfaf3..f295141025bc 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -256,7 +256,9 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
256static struct perf_tool perf_kmem = { 256static struct perf_tool perf_kmem = {
257 .sample = process_sample_event, 257 .sample = process_sample_event,
258 .comm = perf_event__process_comm, 258 .comm = perf_event__process_comm,
259 .ordered_samples = true, 259 .mmap = perf_event__process_mmap,
260 .mmap2 = perf_event__process_mmap2,
261 .ordered_events = true,
260}; 262};
261 263
262static double fragmentation(unsigned long n_req, unsigned long n_alloc) 264static double fragmentation(unsigned long n_req, unsigned long n_alloc)
@@ -403,10 +405,9 @@ static void sort_result(void)
403 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 405 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
404} 406}
405 407
406static int __cmd_kmem(void) 408static int __cmd_kmem(struct perf_session *session)
407{ 409{
408 int err = -EINVAL; 410 int err = -EINVAL;
409 struct perf_session *session;
410 const struct perf_evsel_str_handler kmem_tracepoints[] = { 411 const struct perf_evsel_str_handler kmem_tracepoints[] = {
411 { "kmem:kmalloc", perf_evsel__process_alloc_event, }, 412 { "kmem:kmalloc", perf_evsel__process_alloc_event, },
412 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, 413 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, },
@@ -415,34 +416,22 @@ static int __cmd_kmem(void)
415 { "kmem:kfree", perf_evsel__process_free_event, }, 416 { "kmem:kfree", perf_evsel__process_free_event, },
416 { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, 417 { "kmem:kmem_cache_free", perf_evsel__process_free_event, },
417 }; 418 };
418 struct perf_data_file file = {
419 .path = input_name,
420 .mode = PERF_DATA_MODE_READ,
421 };
422
423 session = perf_session__new(&file, false, &perf_kmem);
424 if (session == NULL)
425 return -ENOMEM;
426
427 if (perf_session__create_kernel_maps(session) < 0)
428 goto out_delete;
429 419
430 if (!perf_session__has_traces(session, "kmem record")) 420 if (!perf_session__has_traces(session, "kmem record"))
431 goto out_delete; 421 goto out;
432 422
433 if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) { 423 if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) {
434 pr_err("Initializing perf session tracepoint handlers failed\n"); 424 pr_err("Initializing perf session tracepoint handlers failed\n");
435 return -1; 425 goto out;
436 } 426 }
437 427
438 setup_pager(); 428 setup_pager();
439 err = perf_session__process_events(session, &perf_kmem); 429 err = perf_session__process_events(session, &perf_kmem);
440 if (err != 0) 430 if (err != 0)
441 goto out_delete; 431 goto out;
442 sort_result(); 432 sort_result();
443 print_result(session); 433 print_result(session);
444out_delete: 434out:
445 perf_session__delete(session);
446 return err; 435 return err;
447} 436}
448 437
@@ -689,29 +678,46 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
689 NULL, 678 NULL,
690 NULL 679 NULL
691 }; 680 };
681 struct perf_session *session;
682 struct perf_data_file file = {
683 .path = input_name,
684 .mode = PERF_DATA_MODE_READ,
685 };
686 int ret = -1;
687
692 argc = parse_options_subcommand(argc, argv, kmem_options, 688 argc = parse_options_subcommand(argc, argv, kmem_options,
693 kmem_subcommands, kmem_usage, 0); 689 kmem_subcommands, kmem_usage, 0);
694 690
695 if (!argc) 691 if (!argc)
696 usage_with_options(kmem_usage, kmem_options); 692 usage_with_options(kmem_usage, kmem_options);
697 693
698 symbol__init();
699
700 if (!strncmp(argv[0], "rec", 3)) { 694 if (!strncmp(argv[0], "rec", 3)) {
695 symbol__init(NULL);
701 return __cmd_record(argc, argv); 696 return __cmd_record(argc, argv);
702 } else if (!strcmp(argv[0], "stat")) { 697 }
698
699 session = perf_session__new(&file, false, &perf_kmem);
700 if (session == NULL)
701 return -1;
702
703 symbol__init(&session->header.env);
704
705 if (!strcmp(argv[0], "stat")) {
703 if (cpu__setup_cpunode_map()) 706 if (cpu__setup_cpunode_map())
704 return -1; 707 goto out_delete;
705 708
706 if (list_empty(&caller_sort)) 709 if (list_empty(&caller_sort))
707 setup_sorting(&caller_sort, default_sort_order); 710 setup_sorting(&caller_sort, default_sort_order);
708 if (list_empty(&alloc_sort)) 711 if (list_empty(&alloc_sort))
709 setup_sorting(&alloc_sort, default_sort_order); 712 setup_sorting(&alloc_sort, default_sort_order);
710 713
711 return __cmd_kmem(); 714 ret = __cmd_kmem(session);
712 } else 715 } else
713 usage_with_options(kmem_usage, kmem_options); 716 usage_with_options(kmem_usage, kmem_options);
714 717
715 return 0; 718out_delete:
719 perf_session__delete(session);
720
721 return ret;
716} 722}
717 723
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 43367eb00510..d8bf2271f4ea 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -543,14 +543,12 @@ static void print_vcpu_info(struct perf_kvm_stat *kvm)
543 543
544 pr_info("Analyze events for "); 544 pr_info("Analyze events for ");
545 545
546 if (kvm->live) { 546 if (kvm->opts.target.system_wide)
547 if (kvm->opts.target.system_wide) 547 pr_info("all VMs, ");
548 pr_info("all VMs, "); 548 else if (kvm->opts.target.pid)
549 else if (kvm->opts.target.pid) 549 pr_info("pid(s) %s, ", kvm->opts.target.pid);
550 pr_info("pid(s) %s, ", kvm->opts.target.pid); 550 else
551 else 551 pr_info("dazed and confused on what is monitored, ");
552 pr_info("dazed and confused on what is monitored, ");
553 }
554 552
555 if (vcpu == -1) 553 if (vcpu == -1)
556 pr_info("all VCPUs:\n\n"); 554 pr_info("all VCPUs:\n\n");
@@ -592,8 +590,8 @@ static void print_result(struct perf_kvm_stat *kvm)
592 pr_info("%9s ", "Samples%"); 590 pr_info("%9s ", "Samples%");
593 591
594 pr_info("%9s ", "Time%"); 592 pr_info("%9s ", "Time%");
595 pr_info("%10s ", "Min Time"); 593 pr_info("%11s ", "Min Time");
596 pr_info("%10s ", "Max Time"); 594 pr_info("%11s ", "Max Time");
597 pr_info("%16s ", "Avg time"); 595 pr_info("%16s ", "Avg time");
598 pr_info("\n\n"); 596 pr_info("\n\n");
599 597
@@ -610,8 +608,8 @@ static void print_result(struct perf_kvm_stat *kvm)
610 pr_info("%10llu ", (unsigned long long)ecount); 608 pr_info("%10llu ", (unsigned long long)ecount);
611 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 609 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
612 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); 610 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
613 pr_info("%8" PRIu64 "us ", min / 1000); 611 pr_info("%9.2fus ", (double)min / 1e3);
614 pr_info("%8" PRIu64 "us ", max / 1000); 612 pr_info("%9.2fus ", (double)max / 1e3);
615 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, 613 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
616 kvm_event_rel_stddev(vcpu, event)); 614 kvm_event_rel_stddev(vcpu, event));
617 pr_info("\n"); 615 pr_info("\n");
@@ -732,7 +730,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
732 return -1; 730 return -1;
733 } 731 }
734 732
735 err = perf_session_queue_event(kvm->session, event, &sample, 0); 733 err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0);
736 /* 734 /*
737 * FIXME: Here we can't consume the event, as perf_session_queue_event will 735 * FIXME: Here we can't consume the event, as perf_session_queue_event will
738 * point to it, and it'll get possibly overwritten by the kernel. 736 * point to it, and it'll get possibly overwritten by the kernel.
@@ -785,7 +783,7 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
785 783
786 /* flush queue after each round in which we processed events */ 784 /* flush queue after each round in which we processed events */
787 if (ntotal) { 785 if (ntotal) {
788 kvm->session->ordered_samples.next_flush = flush_time; 786 kvm->session->ordered_events.next_flush = flush_time;
789 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session); 787 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
790 if (err) { 788 if (err) {
791 if (kvm->lost_events) 789 if (kvm->lost_events)
@@ -885,15 +883,11 @@ static int fd_set_nonblock(int fd)
885 return 0; 883 return 0;
886} 884}
887 885
888static 886static int perf_kvm__handle_stdin(void)
889int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save)
890{ 887{
891 int c; 888 int c;
892 889
893 tcsetattr(0, TCSANOW, tc_now);
894 c = getc(stdin); 890 c = getc(stdin);
895 tcsetattr(0, TCSAFLUSH, tc_save);
896
897 if (c == 'q') 891 if (c == 'q')
898 return 1; 892 return 1;
899 893
@@ -904,7 +898,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
904{ 898{
905 struct pollfd *pollfds = NULL; 899 struct pollfd *pollfds = NULL;
906 int nr_fds, nr_stdin, ret, err = -EINVAL; 900 int nr_fds, nr_stdin, ret, err = -EINVAL;
907 struct termios tc, save; 901 struct termios save;
908 902
909 /* live flag must be set first */ 903 /* live flag must be set first */
910 kvm->live = true; 904 kvm->live = true;
@@ -919,26 +913,14 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
919 goto out; 913 goto out;
920 } 914 }
921 915
916 set_term_quiet_input(&save);
922 init_kvm_event_record(kvm); 917 init_kvm_event_record(kvm);
923 918
924 tcgetattr(0, &save);
925 tc = save;
926 tc.c_lflag &= ~(ICANON | ECHO);
927 tc.c_cc[VMIN] = 0;
928 tc.c_cc[VTIME] = 0;
929
930 signal(SIGINT, sig_handler); 919 signal(SIGINT, sig_handler);
931 signal(SIGTERM, sig_handler); 920 signal(SIGTERM, sig_handler);
932 921
933 /* copy pollfds -- need to add timerfd and stdin */ 922 /* use pollfds -- need to add timerfd and stdin */
934 nr_fds = kvm->evlist->nr_fds; 923 nr_fds = kvm->evlist->pollfd.nr;
935 pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2));
936 if (!pollfds) {
937 err = -ENOMEM;
938 goto out;
939 }
940 memcpy(pollfds, kvm->evlist->pollfd,
941 sizeof(struct pollfd) * kvm->evlist->nr_fds);
942 924
943 /* add timer fd */ 925 /* add timer fd */
944 if (perf_kvm__timerfd_create(kvm) < 0) { 926 if (perf_kvm__timerfd_create(kvm) < 0) {
@@ -946,17 +928,21 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
946 goto out; 928 goto out;
947 } 929 }
948 930
949 pollfds[nr_fds].fd = kvm->timerfd; 931 if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd))
950 pollfds[nr_fds].events = POLLIN; 932 goto out;
933
951 nr_fds++; 934 nr_fds++;
952 935
953 pollfds[nr_fds].fd = fileno(stdin); 936 if (perf_evlist__add_pollfd(kvm->evlist, fileno(stdin)))
954 pollfds[nr_fds].events = POLLIN; 937 goto out;
938
955 nr_stdin = nr_fds; 939 nr_stdin = nr_fds;
956 nr_fds++; 940 nr_fds++;
957 if (fd_set_nonblock(fileno(stdin)) != 0) 941 if (fd_set_nonblock(fileno(stdin)) != 0)
958 goto out; 942 goto out;
959 943
944 pollfds = kvm->evlist->pollfd.entries;
945
960 /* everything is good - enable the events and process */ 946 /* everything is good - enable the events and process */
961 perf_evlist__enable(kvm->evlist); 947 perf_evlist__enable(kvm->evlist);
962 948
@@ -972,7 +958,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
972 goto out; 958 goto out;
973 959
974 if (pollfds[nr_stdin].revents & POLLIN) 960 if (pollfds[nr_stdin].revents & POLLIN)
975 done = perf_kvm__handle_stdin(&tc, &save); 961 done = perf_kvm__handle_stdin();
976 962
977 if (!rc && !done) 963 if (!rc && !done)
978 err = poll(pollfds, nr_fds, 100); 964 err = poll(pollfds, nr_fds, 100);
@@ -989,7 +975,7 @@ out:
989 if (kvm->timerfd >= 0) 975 if (kvm->timerfd >= 0)
990 close(kvm->timerfd); 976 close(kvm->timerfd);
991 977
992 free(pollfds); 978 tcsetattr(0, TCSAFLUSH, &save);
993 return err; 979 return err;
994} 980}
995 981
@@ -998,6 +984,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
998 int err, rc = -1; 984 int err, rc = -1;
999 struct perf_evsel *pos; 985 struct perf_evsel *pos;
1000 struct perf_evlist *evlist = kvm->evlist; 986 struct perf_evlist *evlist = kvm->evlist;
987 char sbuf[STRERR_BUFSIZE];
1001 988
1002 perf_evlist__config(evlist, &kvm->opts); 989 perf_evlist__config(evlist, &kvm->opts);
1003 990
@@ -1034,12 +1021,14 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1034 1021
1035 err = perf_evlist__open(evlist); 1022 err = perf_evlist__open(evlist);
1036 if (err < 0) { 1023 if (err < 0) {
1037 printf("Couldn't create the events: %s\n", strerror(errno)); 1024 printf("Couldn't create the events: %s\n",
1025 strerror_r(errno, sbuf, sizeof(sbuf)));
1038 goto out; 1026 goto out;
1039 } 1027 }
1040 1028
1041 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { 1029 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
1042 ui__error("Failed to mmap the events: %s\n", strerror(errno)); 1030 ui__error("Failed to mmap the events: %s\n",
1031 strerror_r(errno, sbuf, sizeof(sbuf)));
1043 perf_evlist__close(evlist); 1032 perf_evlist__close(evlist);
1044 goto out; 1033 goto out;
1045 } 1034 }
@@ -1058,7 +1047,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1058 struct perf_tool eops = { 1047 struct perf_tool eops = {
1059 .sample = process_sample_event, 1048 .sample = process_sample_event,
1060 .comm = perf_event__process_comm, 1049 .comm = perf_event__process_comm,
1061 .ordered_samples = true, 1050 .ordered_events = true,
1062 }; 1051 };
1063 struct perf_data_file file = { 1052 struct perf_data_file file = {
1064 .path = kvm->file_name, 1053 .path = kvm->file_name,
@@ -1069,9 +1058,11 @@ static int read_events(struct perf_kvm_stat *kvm)
1069 kvm->session = perf_session__new(&file, false, &kvm->tool); 1058 kvm->session = perf_session__new(&file, false, &kvm->tool);
1070 if (!kvm->session) { 1059 if (!kvm->session) {
1071 pr_err("Initializing perf session failed\n"); 1060 pr_err("Initializing perf session failed\n");
1072 return -EINVAL; 1061 return -1;
1073 } 1062 }
1074 1063
1064 symbol__init(&kvm->session->header.env);
1065
1075 if (!perf_session__has_traces(kvm->session, "kvm record")) 1066 if (!perf_session__has_traces(kvm->session, "kvm record"))
1076 return -EINVAL; 1067 return -EINVAL;
1077 1068
@@ -1088,8 +1079,8 @@ static int read_events(struct perf_kvm_stat *kvm)
1088 1079
1089static int parse_target_str(struct perf_kvm_stat *kvm) 1080static int parse_target_str(struct perf_kvm_stat *kvm)
1090{ 1081{
1091 if (kvm->pid_str) { 1082 if (kvm->opts.target.pid) {
1092 kvm->pid_list = intlist__new(kvm->pid_str); 1083 kvm->pid_list = intlist__new(kvm->opts.target.pid);
1093 if (kvm->pid_list == NULL) { 1084 if (kvm->pid_list == NULL) {
1094 pr_err("Error parsing process id string\n"); 1085 pr_err("Error parsing process id string\n");
1095 return -EINVAL; 1086 return -EINVAL;
@@ -1191,7 +1182,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1191 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1182 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
1192 "key for sorting: sample(sort by samples number)" 1183 "key for sorting: sample(sort by samples number)"
1193 " time (sort by avg time)"), 1184 " time (sort by avg time)"),
1194 OPT_STRING('p', "pid", &kvm->pid_str, "pid", 1185 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1195 "analyze events only for given process id(s)"), 1186 "analyze events only for given process id(s)"),
1196 OPT_END() 1187 OPT_END()
1197 }; 1188 };
@@ -1201,8 +1192,6 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1201 NULL 1192 NULL
1202 }; 1193 };
1203 1194
1204 symbol__init();
1205
1206 if (argc) { 1195 if (argc) {
1207 argc = parse_options(argc, argv, 1196 argc = parse_options(argc, argv,
1208 kvm_events_report_options, 1197 kvm_events_report_options,
@@ -1212,6 +1201,9 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1212 kvm_events_report_options); 1201 kvm_events_report_options);
1213 } 1202 }
1214 1203
1204 if (!kvm->opts.target.pid)
1205 kvm->opts.target.system_wide = true;
1206
1215 return kvm_events_report_vcpu(kvm); 1207 return kvm_events_report_vcpu(kvm);
1216} 1208}
1217 1209
@@ -1311,7 +1303,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1311 kvm->tool.exit = perf_event__process_exit; 1303 kvm->tool.exit = perf_event__process_exit;
1312 kvm->tool.fork = perf_event__process_fork; 1304 kvm->tool.fork = perf_event__process_fork;
1313 kvm->tool.lost = process_lost_event; 1305 kvm->tool.lost = process_lost_event;
1314 kvm->tool.ordered_samples = true; 1306 kvm->tool.ordered_events = true;
1315 perf_tool__fill_defaults(&kvm->tool); 1307 perf_tool__fill_defaults(&kvm->tool);
1316 1308
1317 /* set defaults */ 1309 /* set defaults */
@@ -1322,7 +1314,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1322 kvm->opts.target.uid_str = NULL; 1314 kvm->opts.target.uid_str = NULL;
1323 kvm->opts.target.uid = UINT_MAX; 1315 kvm->opts.target.uid = UINT_MAX;
1324 1316
1325 symbol__init(); 1317 symbol__init(NULL);
1326 disable_buildid_cache(); 1318 disable_buildid_cache();
1327 1319
1328 use_browser = 0; 1320 use_browser = 0;
@@ -1369,7 +1361,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1369 */ 1361 */
1370 kvm->session = perf_session__new(&file, false, &kvm->tool); 1362 kvm->session = perf_session__new(&file, false, &kvm->tool);
1371 if (kvm->session == NULL) { 1363 if (kvm->session == NULL) {
1372 err = -ENOMEM; 1364 err = -1;
1373 goto out; 1365 goto out;
1374 } 1366 }
1375 kvm->session->evlist = kvm->evlist; 1367 kvm->session->evlist = kvm->evlist;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6148afc995c6..e7ec71589da6 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -852,7 +852,7 @@ static int __cmd_report(bool display_info)
852 struct perf_tool eops = { 852 struct perf_tool eops = {
853 .sample = process_sample_event, 853 .sample = process_sample_event,
854 .comm = perf_event__process_comm, 854 .comm = perf_event__process_comm,
855 .ordered_samples = true, 855 .ordered_events = true,
856 }; 856 };
857 struct perf_data_file file = { 857 struct perf_data_file file = {
858 .path = input_name, 858 .path = input_name,
@@ -862,9 +862,11 @@ static int __cmd_report(bool display_info)
862 session = perf_session__new(&file, false, &eops); 862 session = perf_session__new(&file, false, &eops);
863 if (!session) { 863 if (!session) {
864 pr_err("Initializing perf session failed\n"); 864 pr_err("Initializing perf session failed\n");
865 return -ENOMEM; 865 return -1;
866 } 866 }
867 867
868 symbol__init(&session->header.env);
869
868 if (!perf_session__has_traces(session, "lock record")) 870 if (!perf_session__has_traces(session, "lock record"))
869 goto out_delete; 871 goto out_delete;
870 872
@@ -974,7 +976,6 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
974 unsigned int i; 976 unsigned int i;
975 int rc = 0; 977 int rc = 0;
976 978
977 symbol__init();
978 for (i = 0; i < LOCKHASH_SIZE; i++) 979 for (i = 0; i < LOCKHASH_SIZE; i++)
979 INIT_LIST_HEAD(lockhash_table + i); 980 INIT_LIST_HEAD(lockhash_table + i);
980 981
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 4a1a6c94a5eb..24db6ffe2957 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -124,7 +124,7 @@ static int report_raw_events(struct perf_mem *mem)
124 &mem->tool); 124 &mem->tool);
125 125
126 if (session == NULL) 126 if (session == NULL)
127 return -ENOMEM; 127 return -1;
128 128
129 if (mem->cpu_list) { 129 if (mem->cpu_list) {
130 ret = perf_session__cpu_bitmap(session, mem->cpu_list, 130 ret = perf_session__cpu_bitmap(session, mem->cpu_list,
@@ -133,7 +133,7 @@ static int report_raw_events(struct perf_mem *mem)
133 goto out_delete; 133 goto out_delete;
134 } 134 }
135 135
136 if (symbol__init() < 0) 136 if (symbol__init(&session->header.env) < 0)
137 return -1; 137 return -1;
138 138
139 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 139 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
@@ -194,7 +194,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
194 .lost = perf_event__process_lost, 194 .lost = perf_event__process_lost,
195 .fork = perf_event__process_fork, 195 .fork = perf_event__process_fork,
196 .build_id = perf_event__process_build_id, 196 .build_id = perf_event__process_build_id,
197 .ordered_samples = true, 197 .ordered_events = true,
198 }, 198 },
199 .input_name = "perf.data", 199 .input_name = "perf.data",
200 }; 200 };
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c63fa2925075..04412b4770a2 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -290,8 +290,11 @@ static void cleanup_params(void)
290 290
291static void pr_err_with_code(const char *msg, int err) 291static void pr_err_with_code(const char *msg, int err)
292{ 292{
293 char sbuf[STRERR_BUFSIZE];
294
293 pr_err("%s", msg); 295 pr_err("%s", msg);
294 pr_debug(" Reason: %s (Code: %d)", strerror(-err), err); 296 pr_debug(" Reason: %s (Code: %d)",
297 strerror_r(-err, sbuf, sizeof(sbuf)), err);
295 pr_err("\n"); 298 pr_err("\n");
296} 299}
297 300
@@ -373,6 +376,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
373 "target executable name or path", opt_set_target), 376 "target executable name or path", opt_set_target),
374 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 377 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
375 "Disable symbol demangling"), 378 "Disable symbol demangling"),
379 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
380 "Enable kernel symbol demangling"),
376 OPT_END() 381 OPT_END()
377 }; 382 };
378 int ret; 383 int ret;
@@ -467,7 +472,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
467 usage_with_options(probe_usage, options); 472 usage_with_options(probe_usage, options);
468 } 473 }
469 474
470 ret = show_line_range(&params.line_range, params.target); 475 ret = show_line_range(&params.line_range, params.target,
476 params.uprobes);
471 if (ret < 0) 477 if (ret < 0)
472 pr_err_with_code(" Error: Failed to show lines.", ret); 478 pr_err_with_code(" Error: Failed to show lines.", ret);
473 return ret; 479 return ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4869050e7194..44c6f3d55ce7 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -65,8 +65,9 @@ static int process_synthesized_event(struct perf_tool *tool,
65 return record__write(rec, event, event->header.size); 65 return record__write(rec, event, event->header.size);
66} 66}
67 67
68static int record__mmap_read(struct record *rec, struct perf_mmap *md) 68static int record__mmap_read(struct record *rec, int idx)
69{ 69{
70 struct perf_mmap *md = &rec->evlist->mmap[idx];
70 unsigned int head = perf_mmap__read_head(md); 71 unsigned int head = perf_mmap__read_head(md);
71 unsigned int old = md->prev; 72 unsigned int old = md->prev;
72 unsigned char *data = md->base + page_size; 73 unsigned char *data = md->base + page_size;
@@ -102,8 +103,7 @@ static int record__mmap_read(struct record *rec, struct perf_mmap *md)
102 } 103 }
103 104
104 md->prev = old; 105 md->prev = old;
105 perf_mmap__write_tail(md, old); 106 perf_evlist__mmap_consume(rec->evlist, idx);
106
107out: 107out:
108 return rc; 108 return rc;
109} 109}
@@ -161,7 +161,7 @@ try_again:
161 161
162 if (perf_evlist__apply_filters(evlist)) { 162 if (perf_evlist__apply_filters(evlist)) {
163 error("failed to set filter with %d (%s)\n", errno, 163 error("failed to set filter with %d (%s)\n", errno,
164 strerror(errno)); 164 strerror_r(errno, msg, sizeof(msg)));
165 rc = -1; 165 rc = -1;
166 goto out; 166 goto out;
167 } 167 }
@@ -175,7 +175,8 @@ try_again:
175 "(current value: %u)\n", opts->mmap_pages); 175 "(current value: %u)\n", opts->mmap_pages);
176 rc = -errno; 176 rc = -errno;
177 } else { 177 } else {
178 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 178 pr_err("failed to mmap with %d (%s)\n", errno,
179 strerror_r(errno, msg, sizeof(msg)));
179 rc = -errno; 180 rc = -errno;
180 } 181 }
181 goto out; 182 goto out;
@@ -244,7 +245,7 @@ static int record__mmap_read_all(struct record *rec)
244 245
245 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 246 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
246 if (rec->evlist->mmap[i].base) { 247 if (rec->evlist->mmap[i].base) {
247 if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 248 if (record__mmap_read(rec, i) != 0) {
248 rc = -1; 249 rc = -1;
249 goto out; 250 goto out;
250 } 251 }
@@ -307,7 +308,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
307 struct record_opts *opts = &rec->opts; 308 struct record_opts *opts = &rec->opts;
308 struct perf_data_file *file = &rec->file; 309 struct perf_data_file *file = &rec->file;
309 struct perf_session *session; 310 struct perf_session *session;
310 bool disabled = false; 311 bool disabled = false, draining = false;
311 312
312 rec->progname = argv[0]; 313 rec->progname = argv[0];
313 314
@@ -456,9 +457,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
456 } 457 }
457 458
458 if (hits == rec->samples) { 459 if (hits == rec->samples) {
459 if (done) 460 if (done || draining)
460 break; 461 break;
461 err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1); 462 err = perf_evlist__poll(rec->evlist, -1);
462 /* 463 /*
463 * Propagate error, only if there's any. Ignore positive 464 * Propagate error, only if there's any. Ignore positive
464 * number of returned events and interrupt error. 465 * number of returned events and interrupt error.
@@ -466,6 +467,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
466 if (err > 0 || (err < 0 && errno == EINTR)) 467 if (err > 0 || (err < 0 && errno == EINTR))
467 err = 0; 468 err = 0;
468 waking++; 469 waking++;
470
471 if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
472 draining = true;
469 } 473 }
470 474
471 /* 475 /*
@@ -480,7 +484,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
480 } 484 }
481 485
482 if (forks && workload_exec_errno) { 486 if (forks && workload_exec_errno) {
483 char msg[512]; 487 char msg[STRERR_BUFSIZE];
484 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 488 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
485 pr_err("Workload failed: %s\n", emsg); 489 pr_err("Workload failed: %s\n", emsg);
486 err = -1; 490 err = -1;
@@ -620,145 +624,56 @@ error:
620 return ret; 624 return ret;
621} 625}
622 626
623#ifdef HAVE_DWARF_UNWIND_SUPPORT 627static void callchain_debug(void)
624static int get_stack_size(char *str, unsigned long *_size)
625{
626 char *endptr;
627 unsigned long size;
628 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
629
630 size = strtoul(str, &endptr, 0);
631
632 do {
633 if (*endptr)
634 break;
635
636 size = round_up(size, sizeof(u64));
637 if (!size || size > max_size)
638 break;
639
640 *_size = size;
641 return 0;
642
643 } while (0);
644
645 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
646 max_size, str);
647 return -1;
648}
649#endif /* HAVE_DWARF_UNWIND_SUPPORT */
650
651int record_parse_callchain(const char *arg, struct record_opts *opts)
652{
653 char *tok, *name, *saveptr = NULL;
654 char *buf;
655 int ret = -1;
656
657 /* We need buffer that we know we can write to. */
658 buf = malloc(strlen(arg) + 1);
659 if (!buf)
660 return -ENOMEM;
661
662 strcpy(buf, arg);
663
664 tok = strtok_r((char *)buf, ",", &saveptr);
665 name = tok ? : (char *)buf;
666
667 do {
668 /* Framepointer style */
669 if (!strncmp(name, "fp", sizeof("fp"))) {
670 if (!strtok_r(NULL, ",", &saveptr)) {
671 opts->call_graph = CALLCHAIN_FP;
672 ret = 0;
673 } else
674 pr_err("callchain: No more arguments "
675 "needed for -g fp\n");
676 break;
677
678#ifdef HAVE_DWARF_UNWIND_SUPPORT
679 /* Dwarf style */
680 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
681 const unsigned long default_stack_dump_size = 8192;
682
683 ret = 0;
684 opts->call_graph = CALLCHAIN_DWARF;
685 opts->stack_dump_size = default_stack_dump_size;
686
687 tok = strtok_r(NULL, ",", &saveptr);
688 if (tok) {
689 unsigned long size = 0;
690
691 ret = get_stack_size(tok, &size);
692 opts->stack_dump_size = size;
693 }
694#endif /* HAVE_DWARF_UNWIND_SUPPORT */
695 } else {
696 pr_err("callchain: Unknown --call-graph option "
697 "value: %s\n", arg);
698 break;
699 }
700
701 } while (0);
702
703 free(buf);
704 return ret;
705}
706
707static void callchain_debug(struct record_opts *opts)
708{ 628{
709 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" }; 629 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" };
710 630
711 pr_debug("callchain: type %s\n", str[opts->call_graph]); 631 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
712 632
713 if (opts->call_graph == CALLCHAIN_DWARF) 633 if (callchain_param.record_mode == CALLCHAIN_DWARF)
714 pr_debug("callchain: stack dump size %d\n", 634 pr_debug("callchain: stack dump size %d\n",
715 opts->stack_dump_size); 635 callchain_param.dump_size);
716} 636}
717 637
718int record_parse_callchain_opt(const struct option *opt, 638int record_parse_callchain_opt(const struct option *opt __maybe_unused,
719 const char *arg, 639 const char *arg,
720 int unset) 640 int unset)
721{ 641{
722 struct record_opts *opts = opt->value;
723 int ret; 642 int ret;
724 643
725 opts->call_graph_enabled = !unset; 644 callchain_param.enabled = !unset;
726 645
727 /* --no-call-graph */ 646 /* --no-call-graph */
728 if (unset) { 647 if (unset) {
729 opts->call_graph = CALLCHAIN_NONE; 648 callchain_param.record_mode = CALLCHAIN_NONE;
730 pr_debug("callchain: disabled\n"); 649 pr_debug("callchain: disabled\n");
731 return 0; 650 return 0;
732 } 651 }
733 652
734 ret = record_parse_callchain(arg, opts); 653 ret = parse_callchain_record_opt(arg);
735 if (!ret) 654 if (!ret)
736 callchain_debug(opts); 655 callchain_debug();
737 656
738 return ret; 657 return ret;
739} 658}
740 659
741int record_callchain_opt(const struct option *opt, 660int record_callchain_opt(const struct option *opt __maybe_unused,
742 const char *arg __maybe_unused, 661 const char *arg __maybe_unused,
743 int unset __maybe_unused) 662 int unset __maybe_unused)
744{ 663{
745 struct record_opts *opts = opt->value; 664 callchain_param.enabled = true;
746 665
747 opts->call_graph_enabled = !unset; 666 if (callchain_param.record_mode == CALLCHAIN_NONE)
667 callchain_param.record_mode = CALLCHAIN_FP;
748 668
749 if (opts->call_graph == CALLCHAIN_NONE) 669 callchain_debug();
750 opts->call_graph = CALLCHAIN_FP;
751
752 callchain_debug(opts);
753 return 0; 670 return 0;
754} 671}
755 672
756static int perf_record_config(const char *var, const char *value, void *cb) 673static int perf_record_config(const char *var, const char *value, void *cb)
757{ 674{
758 struct record *rec = cb;
759
760 if (!strcmp(var, "record.call-graph")) 675 if (!strcmp(var, "record.call-graph"))
761 return record_parse_callchain(value, &rec->opts); 676 var = "call-graph.record-mode"; /* fall-through */
762 677
763 return perf_default_config(var, value, cb); 678 return perf_default_config(var, value, cb);
764} 679}
@@ -781,6 +696,7 @@ static const char * const record_usage[] = {
781 */ 696 */
782static struct record record = { 697static struct record record = {
783 .opts = { 698 .opts = {
699 .sample_time = true,
784 .mmap_pages = UINT_MAX, 700 .mmap_pages = UINT_MAX,
785 .user_freq = UINT_MAX, 701 .user_freq = UINT_MAX,
786 .user_interval = ULLONG_MAX, 702 .user_interval = ULLONG_MAX,
@@ -907,7 +823,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
907 usage_with_options(record_usage, record_options); 823 usage_with_options(record_usage, record_options);
908 } 824 }
909 825
910 symbol__init(); 826 symbol__init(NULL);
911 827
912 if (symbol_conf.kptr_restrict) 828 if (symbol_conf.kptr_restrict)
913 pr_warning( 829 pr_warning(
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 21d830bafff3..ac145fae0521 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -58,17 +58,19 @@ struct report {
58 const char *symbol_filter_str; 58 const char *symbol_filter_str;
59 float min_percent; 59 float min_percent;
60 u64 nr_entries; 60 u64 nr_entries;
61 u64 queue_size;
61 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 62 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
62}; 63};
63 64
64static int report__config(const char *var, const char *value, void *cb) 65static int report__config(const char *var, const char *value, void *cb)
65{ 66{
67 struct report *rep = cb;
68
66 if (!strcmp(var, "report.group")) { 69 if (!strcmp(var, "report.group")) {
67 symbol_conf.event_group = perf_config_bool(var, value); 70 symbol_conf.event_group = perf_config_bool(var, value);
68 return 0; 71 return 0;
69 } 72 }
70 if (!strcmp(var, "report.percent-limit")) { 73 if (!strcmp(var, "report.percent-limit")) {
71 struct report *rep = cb;
72 rep->min_percent = strtof(value, NULL); 74 rep->min_percent = strtof(value, NULL);
73 return 0; 75 return 0;
74 } 76 }
@@ -76,6 +78,10 @@ static int report__config(const char *var, const char *value, void *cb)
76 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 78 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
77 return 0; 79 return 0;
78 } 80 }
81 if (!strcmp(var, "report.queue-size")) {
82 rep->queue_size = perf_config_u64(var, value);
83 return 0;
84 }
79 85
80 return perf_default_config(var, value, cb); 86 return perf_default_config(var, value, cb);
81} 87}
@@ -578,7 +584,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
578 .attr = perf_event__process_attr, 584 .attr = perf_event__process_attr,
579 .tracing_data = perf_event__process_tracing_data, 585 .tracing_data = perf_event__process_tracing_data,
580 .build_id = perf_event__process_build_id, 586 .build_id = perf_event__process_build_id,
581 .ordered_samples = true, 587 .ordered_events = true,
582 .ordering_requires_timestamps = true, 588 .ordering_requires_timestamps = true,
583 }, 589 },
584 .max_stack = PERF_MAX_STACK_DEPTH, 590 .max_stack = PERF_MAX_STACK_DEPTH,
@@ -674,6 +680,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
674 "objdump binary to use for disassembly and annotations"), 680 "objdump binary to use for disassembly and annotations"),
675 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 681 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
676 "Disable symbol demangling"), 682 "Disable symbol demangling"),
683 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
684 "Enable kernel symbol demangling"),
677 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), 685 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
678 OPT_CALLBACK(0, "percent-limit", &report, "percent", 686 OPT_CALLBACK(0, "percent-limit", &report, "percent",
679 "Don't show entries under that percent", parse_percent_limit), 687 "Don't show entries under that percent", parse_percent_limit),
@@ -712,14 +720,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
712repeat: 720repeat:
713 session = perf_session__new(&file, false, &report.tool); 721 session = perf_session__new(&file, false, &report.tool);
714 if (session == NULL) 722 if (session == NULL)
715 return -ENOMEM; 723 return -1;
724
725 if (report.queue_size) {
726 ordered_events__set_alloc_size(&session->ordered_events,
727 report.queue_size);
728 }
716 729
717 report.session = session; 730 report.session = session;
718 731
719 has_br_stack = perf_header__has_feat(&session->header, 732 has_br_stack = perf_header__has_feat(&session->header,
720 HEADER_BRANCH_STACK); 733 HEADER_BRANCH_STACK);
721 734
722 if (branch_mode == -1 && has_br_stack) { 735 if ((branch_mode == -1 && has_br_stack) || branch_mode == 1) {
723 sort__mode = SORT_MODE__BRANCH; 736 sort__mode = SORT_MODE__BRANCH;
724 symbol_conf.cumulate_callchain = false; 737 symbol_conf.cumulate_callchain = false;
725 } 738 }
@@ -787,7 +800,7 @@ repeat:
787 } 800 }
788 } 801 }
789 802
790 if (symbol__init() < 0) 803 if (symbol__init(&session->header.env) < 0)
791 goto error; 804 goto error;
792 805
793 if (argc) { 806 if (argc) {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index f83c08c0dd87..9c9287fbf8e9 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -428,6 +428,7 @@ static u64 get_cpu_usage_nsec_parent(void)
428static int self_open_counters(void) 428static int self_open_counters(void)
429{ 429{
430 struct perf_event_attr attr; 430 struct perf_event_attr attr;
431 char sbuf[STRERR_BUFSIZE];
431 int fd; 432 int fd;
432 433
433 memset(&attr, 0, sizeof(attr)); 434 memset(&attr, 0, sizeof(attr));
@@ -440,7 +441,8 @@ static int self_open_counters(void)
440 441
441 if (fd < 0) 442 if (fd < 0)
442 pr_err("Error: sys_perf_event_open() syscall returned " 443 pr_err("Error: sys_perf_event_open() syscall returned "
443 "with %d (%s)\n", fd, strerror(errno)); 444 "with %d (%s)\n", fd,
445 strerror_r(errno, sbuf, sizeof(sbuf)));
444 return fd; 446 return fd;
445} 447}
446 448
@@ -1462,6 +1464,8 @@ static int perf_sched__read_events(struct perf_sched *sched,
1462 return -1; 1464 return -1;
1463 } 1465 }
1464 1466
1467 symbol__init(&session->header.env);
1468
1465 if (perf_session__set_tracepoints_handlers(session, handlers)) 1469 if (perf_session__set_tracepoints_handlers(session, handlers))
1466 goto out_delete; 1470 goto out_delete;
1467 1471
@@ -1662,7 +1666,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1662 .comm = perf_event__process_comm, 1666 .comm = perf_event__process_comm,
1663 .lost = perf_event__process_lost, 1667 .lost = perf_event__process_lost,
1664 .fork = perf_sched__process_fork_event, 1668 .fork = perf_sched__process_fork_event,
1665 .ordered_samples = true, 1669 .ordered_events = true,
1666 }, 1670 },
1667 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), 1671 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1668 .sort_list = LIST_HEAD_INIT(sched.sort_list), 1672 .sort_list = LIST_HEAD_INIT(sched.sort_list),
@@ -1747,7 +1751,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1747 if (!strcmp(argv[0], "script")) 1751 if (!strcmp(argv[0], "script"))
1748 return cmd_script(argc, argv, prefix); 1752 return cmd_script(argc, argv, prefix);
1749 1753
1750 symbol__init();
1751 if (!strncmp(argv[0], "rec", 3)) { 1754 if (!strncmp(argv[0], "rec", 3)) {
1752 return __cmd_record(argc, argv); 1755 return __cmd_record(argc, argv);
1753 } else if (!strncmp(argv[0], "lat", 3)) { 1756 } else if (!strncmp(argv[0], "lat", 3)) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index f57035b89c15..b9b9e58a6c39 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -184,10 +184,6 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
184 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", 184 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
185 PERF_OUTPUT_IP)) 185 PERF_OUTPUT_IP))
186 return -EINVAL; 186 return -EINVAL;
187
188 if (!no_callchain &&
189 !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
190 symbol_conf.use_callchain = false;
191 } 187 }
192 188
193 if (PRINT_FIELD(ADDR) && 189 if (PRINT_FIELD(ADDR) &&
@@ -290,6 +286,19 @@ static int perf_session__check_output_opt(struct perf_session *session)
290 set_print_ip_opts(&evsel->attr); 286 set_print_ip_opts(&evsel->attr);
291 } 287 }
292 288
289 if (!no_callchain) {
290 bool use_callchain = false;
291
292 evlist__for_each(session->evlist, evsel) {
293 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
294 use_callchain = true;
295 break;
296 }
297 }
298 if (!use_callchain)
299 symbol_conf.use_callchain = false;
300 }
301
293 /* 302 /*
294 * set default for tracepoints to print symbols only 303 * set default for tracepoints to print symbols only
295 * if callchains are present 304 * if callchains are present
@@ -476,6 +485,11 @@ static int default_start_script(const char *script __maybe_unused,
476 return 0; 485 return 0;
477} 486}
478 487
488static int default_flush_script(void)
489{
490 return 0;
491}
492
479static int default_stop_script(void) 493static int default_stop_script(void)
480{ 494{
481 return 0; 495 return 0;
@@ -489,6 +503,7 @@ static int default_generate_script(struct pevent *pevent __maybe_unused,
489 503
490static struct scripting_ops default_scripting_ops = { 504static struct scripting_ops default_scripting_ops = {
491 .start_script = default_start_script, 505 .start_script = default_start_script,
506 .flush_script = default_flush_script,
492 .stop_script = default_stop_script, 507 .stop_script = default_stop_script,
493 .process_event = process_event, 508 .process_event = process_event,
494 .generate_script = default_generate_script, 509 .generate_script = default_generate_script,
@@ -504,6 +519,11 @@ static void setup_scripting(void)
504 scripting_ops = &default_scripting_ops; 519 scripting_ops = &default_scripting_ops;
505} 520}
506 521
522static int flush_scripting(void)
523{
524 return scripting_ops->flush_script();
525}
526
507static int cleanup_scripting(void) 527static int cleanup_scripting(void)
508{ 528{
509 pr_debug("\nperf script stopped\n"); 529 pr_debug("\nperf script stopped\n");
@@ -1471,12 +1491,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1471 bool show_full_info = false; 1491 bool show_full_info = false;
1472 bool header = false; 1492 bool header = false;
1473 bool header_only = false; 1493 bool header_only = false;
1494 bool script_started = false;
1474 char *rec_script_path = NULL; 1495 char *rec_script_path = NULL;
1475 char *rep_script_path = NULL; 1496 char *rep_script_path = NULL;
1476 struct perf_session *session; 1497 struct perf_session *session;
1477 char *script_path = NULL; 1498 char *script_path = NULL;
1478 const char **__argv; 1499 const char **__argv;
1479 int i, j, err; 1500 int i, j, err = 0;
1480 struct perf_script script = { 1501 struct perf_script script = {
1481 .tool = { 1502 .tool = {
1482 .sample = process_sample_event, 1503 .sample = process_sample_event,
@@ -1488,7 +1509,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1488 .attr = process_attr, 1509 .attr = process_attr,
1489 .tracing_data = perf_event__process_tracing_data, 1510 .tracing_data = perf_event__process_tracing_data,
1490 .build_id = perf_event__process_build_id, 1511 .build_id = perf_event__process_build_id,
1491 .ordered_samples = true, 1512 .ordered_events = true,
1492 .ordering_requires_timestamps = true, 1513 .ordering_requires_timestamps = true,
1493 }, 1514 },
1494 }; 1515 };
@@ -1718,26 +1739,28 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1718 exit(-1); 1739 exit(-1);
1719 } 1740 }
1720 1741
1721 if (symbol__init() < 0)
1722 return -1;
1723 if (!script_name) 1742 if (!script_name)
1724 setup_pager(); 1743 setup_pager();
1725 1744
1726 session = perf_session__new(&file, false, &script.tool); 1745 session = perf_session__new(&file, false, &script.tool);
1727 if (session == NULL) 1746 if (session == NULL)
1728 return -ENOMEM; 1747 return -1;
1729 1748
1730 if (header || header_only) { 1749 if (header || header_only) {
1731 perf_session__fprintf_info(session, stdout, show_full_info); 1750 perf_session__fprintf_info(session, stdout, show_full_info);
1732 if (header_only) 1751 if (header_only)
1733 return 0; 1752 goto out_delete;
1734 } 1753 }
1735 1754
1755 if (symbol__init(&session->header.env) < 0)
1756 goto out_delete;
1757
1736 script.session = session; 1758 script.session = session;
1737 1759
1738 if (cpu_list) { 1760 if (cpu_list) {
1739 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1761 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
1740 return -1; 1762 if (err < 0)
1763 goto out_delete;
1741 } 1764 }
1742 1765
1743 if (!no_callchain) 1766 if (!no_callchain)
@@ -1752,53 +1775,62 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1752 if (output_set_by_user()) { 1775 if (output_set_by_user()) {
1753 fprintf(stderr, 1776 fprintf(stderr,
1754 "custom fields not supported for generated scripts"); 1777 "custom fields not supported for generated scripts");
1755 return -1; 1778 err = -EINVAL;
1779 goto out_delete;
1756 } 1780 }
1757 1781
1758 input = open(file.path, O_RDONLY); /* input_name */ 1782 input = open(file.path, O_RDONLY); /* input_name */
1759 if (input < 0) { 1783 if (input < 0) {
1784 err = -errno;
1760 perror("failed to open file"); 1785 perror("failed to open file");
1761 return -1; 1786 goto out_delete;
1762 } 1787 }
1763 1788
1764 err = fstat(input, &perf_stat); 1789 err = fstat(input, &perf_stat);
1765 if (err < 0) { 1790 if (err < 0) {
1766 perror("failed to stat file"); 1791 perror("failed to stat file");
1767 return -1; 1792 goto out_delete;
1768 } 1793 }
1769 1794
1770 if (!perf_stat.st_size) { 1795 if (!perf_stat.st_size) {
1771 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1796 fprintf(stderr, "zero-sized file, nothing to do!\n");
1772 return 0; 1797 goto out_delete;
1773 } 1798 }
1774 1799
1775 scripting_ops = script_spec__lookup(generate_script_lang); 1800 scripting_ops = script_spec__lookup(generate_script_lang);
1776 if (!scripting_ops) { 1801 if (!scripting_ops) {
1777 fprintf(stderr, "invalid language specifier"); 1802 fprintf(stderr, "invalid language specifier");
1778 return -1; 1803 err = -ENOENT;
1804 goto out_delete;
1779 } 1805 }
1780 1806
1781 err = scripting_ops->generate_script(session->tevent.pevent, 1807 err = scripting_ops->generate_script(session->tevent.pevent,
1782 "perf-script"); 1808 "perf-script");
1783 goto out; 1809 goto out_delete;
1784 } 1810 }
1785 1811
1786 if (script_name) { 1812 if (script_name) {
1787 err = scripting_ops->start_script(script_name, argc, argv); 1813 err = scripting_ops->start_script(script_name, argc, argv);
1788 if (err) 1814 if (err)
1789 goto out; 1815 goto out_delete;
1790 pr_debug("perf script started with script %s\n\n", script_name); 1816 pr_debug("perf script started with script %s\n\n", script_name);
1817 script_started = true;
1791 } 1818 }
1792 1819
1793 1820
1794 err = perf_session__check_output_opt(session); 1821 err = perf_session__check_output_opt(session);
1795 if (err < 0) 1822 if (err < 0)
1796 goto out; 1823 goto out_delete;
1797 1824
1798 err = __cmd_script(&script); 1825 err = __cmd_script(&script);
1799 1826
1827 flush_scripting();
1828
1829out_delete:
1800 perf_session__delete(session); 1830 perf_session__delete(session);
1801 cleanup_scripting(); 1831
1832 if (script_started)
1833 cleanup_scripting();
1802out: 1834out:
1803 return err; 1835 return err;
1804} 1836}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3e80aa10cfd8..b22c62f80078 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -593,7 +593,7 @@ static int __run_perf_stat(int argc, const char **argv)
593 593
594 if (perf_evlist__apply_filters(evsel_list)) { 594 if (perf_evlist__apply_filters(evsel_list)) {
595 error("failed to set filter with %d (%s)\n", errno, 595 error("failed to set filter with %d (%s)\n", errno,
596 strerror(errno)); 596 strerror_r(errno, msg, sizeof(msg)));
597 return -1; 597 return -1;
598 } 598 }
599 599
@@ -732,7 +732,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
732 } 732 }
733} 733}
734 734
735static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 735static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
736{ 736{
737 double msecs = avg / 1e6; 737 double msecs = avg / 1e6;
738 const char *fmt_v, *fmt_n; 738 const char *fmt_v, *fmt_n;
@@ -741,7 +741,7 @@ static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
741 fmt_v = csv_output ? "%.6f%s" : "%18.6f%s"; 741 fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
742 fmt_n = csv_output ? "%s" : "%-25s"; 742 fmt_n = csv_output ? "%s" : "%-25s";
743 743
744 aggr_printout(evsel, cpu, nr); 744 aggr_printout(evsel, id, nr);
745 745
746 scnprintf(name, sizeof(name), "%s%s", 746 scnprintf(name, sizeof(name), "%s%s",
747 perf_evsel__name(evsel), csv_output ? "" : " (msec)"); 747 perf_evsel__name(evsel), csv_output ? "" : " (msec)");
@@ -947,11 +947,12 @@ static void print_ll_cache_misses(int cpu,
947 fprintf(output, " of all LL-cache hits "); 947 fprintf(output, " of all LL-cache hits ");
948} 948}
949 949
950static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 950static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
951{ 951{
952 double total, ratio = 0.0, total2; 952 double total, ratio = 0.0, total2;
953 double sc = evsel->scale; 953 double sc = evsel->scale;
954 const char *fmt; 954 const char *fmt;
955 int cpu = cpu_map__id_to_cpu(id);
955 956
956 if (csv_output) { 957 if (csv_output) {
957 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s"; 958 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
@@ -962,7 +963,7 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
962 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s"; 963 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
963 } 964 }
964 965
965 aggr_printout(evsel, cpu, nr); 966 aggr_printout(evsel, id, nr);
966 967
967 if (aggr_mode == AGGR_GLOBAL) 968 if (aggr_mode == AGGR_GLOBAL)
968 cpu = 0; 969 cpu = 0;
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 2f1a5220c090..35b425b6293f 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1605,7 +1605,9 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1605 int ret = -EINVAL; 1605 int ret = -EINVAL;
1606 1606
1607 if (session == NULL) 1607 if (session == NULL)
1608 return -ENOMEM; 1608 return -1;
1609
1610 symbol__init(&session->header.env);
1609 1611
1610 (void)perf_header__process_sections(&session->header, 1612 (void)perf_header__process_sections(&session->header,
1611 perf_data_file__fd(session->file), 1613 perf_data_file__fd(session->file),
@@ -1920,7 +1922,7 @@ int cmd_timechart(int argc, const char **argv,
1920 .fork = process_fork_event, 1922 .fork = process_fork_event,
1921 .exit = process_exit_event, 1923 .exit = process_exit_event,
1922 .sample = process_sample_event, 1924 .sample = process_sample_event,
1923 .ordered_samples = true, 1925 .ordered_events = true,
1924 }, 1926 },
1925 .proc_num = 15, 1927 .proc_num = 15,
1926 .min_time = 1000000, 1928 .min_time = 1000000,
@@ -1982,8 +1984,6 @@ int cmd_timechart(int argc, const char **argv,
1982 return -1; 1984 return -1;
1983 } 1985 }
1984 1986
1985 symbol__init();
1986
1987 if (argc && !strncmp(argv[0], "rec", 3)) { 1987 if (argc && !strncmp(argv[0], "rec", 3)) {
1988 argc = parse_options(argc, argv, record_options, record_usage, 1988 argc = parse_options(argc, argv, record_options, record_usage,
1989 PARSE_OPT_STOP_AT_NON_OPTION); 1989 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 377971dc89a3..fc3d55f832ac 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -59,7 +59,7 @@
59 59
60#include <sys/syscall.h> 60#include <sys/syscall.h>
61#include <sys/ioctl.h> 61#include <sys/ioctl.h>
62#include <sys/poll.h> 62#include <poll.h>
63#include <sys/prctl.h> 63#include <sys/prctl.h>
64#include <sys/wait.h> 64#include <sys/wait.h>
65#include <sys/uio.h> 65#include <sys/uio.h>
@@ -276,11 +276,17 @@ static void perf_top__print_sym_table(struct perf_top *top)
276 return; 276 return;
277 } 277 }
278 278
279 if (top->zero) {
280 hists__delete_entries(&top->sym_evsel->hists);
281 } else {
282 hists__decay_entries(&top->sym_evsel->hists,
283 top->hide_user_symbols,
284 top->hide_kernel_symbols);
285 }
286
279 hists__collapse_resort(&top->sym_evsel->hists, NULL); 287 hists__collapse_resort(&top->sym_evsel->hists, NULL);
280 hists__output_resort(&top->sym_evsel->hists); 288 hists__output_resort(&top->sym_evsel->hists);
281 hists__decay_entries(&top->sym_evsel->hists, 289
282 top->hide_user_symbols,
283 top->hide_kernel_symbols);
284 hists__output_recalc_col_len(&top->sym_evsel->hists, 290 hists__output_recalc_col_len(&top->sym_evsel->hists,
285 top->print_entries - printed); 291 top->print_entries - printed);
286 putchar('\n'); 292 putchar('\n');
@@ -427,18 +433,13 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
427 433
428 if (!perf_top__key_mapped(top, c)) { 434 if (!perf_top__key_mapped(top, c)) {
429 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 435 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
430 struct termios tc, save; 436 struct termios save;
431 437
432 perf_top__print_mapped_keys(top); 438 perf_top__print_mapped_keys(top);
433 fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 439 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
434 fflush(stdout); 440 fflush(stdout);
435 441
436 tcgetattr(0, &save); 442 set_term_quiet_input(&save);
437 tc = save;
438 tc.c_lflag &= ~(ICANON | ECHO);
439 tc.c_cc[VMIN] = 0;
440 tc.c_cc[VTIME] = 0;
441 tcsetattr(0, TCSANOW, &tc);
442 443
443 poll(&stdin_poll, 1, -1); 444 poll(&stdin_poll, 1, -1);
444 c = getc(stdin); 445 c = getc(stdin);
@@ -542,11 +543,16 @@ static void perf_top__sort_new_samples(void *arg)
542 if (t->evlist->selected != NULL) 543 if (t->evlist->selected != NULL)
543 t->sym_evsel = t->evlist->selected; 544 t->sym_evsel = t->evlist->selected;
544 545
546 if (t->zero) {
547 hists__delete_entries(&t->sym_evsel->hists);
548 } else {
549 hists__decay_entries(&t->sym_evsel->hists,
550 t->hide_user_symbols,
551 t->hide_kernel_symbols);
552 }
553
545 hists__collapse_resort(&t->sym_evsel->hists, NULL); 554 hists__collapse_resort(&t->sym_evsel->hists, NULL);
546 hists__output_resort(&t->sym_evsel->hists); 555 hists__output_resort(&t->sym_evsel->hists);
547 hists__decay_entries(&t->sym_evsel->hists,
548 t->hide_user_symbols,
549 t->hide_kernel_symbols);
550} 556}
551 557
552static void *display_thread_tui(void *arg) 558static void *display_thread_tui(void *arg)
@@ -577,23 +583,32 @@ static void *display_thread_tui(void *arg)
577 return NULL; 583 return NULL;
578} 584}
579 585
586static void display_sig(int sig __maybe_unused)
587{
588 done = 1;
589}
590
591static void display_setup_sig(void)
592{
593 signal(SIGSEGV, display_sig);
594 signal(SIGFPE, display_sig);
595 signal(SIGINT, display_sig);
596 signal(SIGQUIT, display_sig);
597 signal(SIGTERM, display_sig);
598}
599
580static void *display_thread(void *arg) 600static void *display_thread(void *arg)
581{ 601{
582 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 602 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
583 struct termios tc, save; 603 struct termios save;
584 struct perf_top *top = arg; 604 struct perf_top *top = arg;
585 int delay_msecs, c; 605 int delay_msecs, c;
586 606
587 tcgetattr(0, &save); 607 display_setup_sig();
588 tc = save;
589 tc.c_lflag &= ~(ICANON | ECHO);
590 tc.c_cc[VMIN] = 0;
591 tc.c_cc[VTIME] = 0;
592
593 pthread__unblock_sigwinch(); 608 pthread__unblock_sigwinch();
594repeat: 609repeat:
595 delay_msecs = top->delay_secs * 1000; 610 delay_msecs = top->delay_secs * 1000;
596 tcsetattr(0, TCSANOW, &tc); 611 set_term_quiet_input(&save);
597 /* trash return*/ 612 /* trash return*/
598 getc(stdin); 613 getc(stdin);
599 614
@@ -620,13 +635,16 @@ repeat:
620 } 635 }
621 } 636 }
622 637
638 tcsetattr(0, TCSAFLUSH, &save);
623 return NULL; 639 return NULL;
624} 640}
625 641
626static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) 642static int symbol_filter(struct map *map, struct symbol *sym)
627{ 643{
628 const char *name = sym->name; 644 const char *name = sym->name;
629 645
646 if (!map->dso->kernel)
647 return 0;
630 /* 648 /*
631 * ppc64 uses function descriptors and appends a '.' to the 649 * ppc64 uses function descriptors and appends a '.' to the
632 * start of every instruction address. Remove it. 650 * start of every instruction address. Remove it.
@@ -876,7 +894,7 @@ try_again:
876 894
877 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 895 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
878 ui__error("Failed to mmap with %d (%s)\n", 896 ui__error("Failed to mmap with %d (%s)\n",
879 errno, strerror(errno)); 897 errno, strerror_r(errno, msg, sizeof(msg)));
880 goto out_err; 898 goto out_err;
881 } 899 }
882 900
@@ -911,7 +929,7 @@ static int __cmd_top(struct perf_top *top)
911 929
912 top->session = perf_session__new(NULL, false, NULL); 930 top->session = perf_session__new(NULL, false, NULL);
913 if (top->session == NULL) 931 if (top->session == NULL)
914 return -ENOMEM; 932 return -1;
915 933
916 machines__set_symbol_filter(&top->session->machines, symbol_filter); 934 machines__set_symbol_filter(&top->session->machines, symbol_filter);
917 935
@@ -946,7 +964,7 @@ static int __cmd_top(struct perf_top *top)
946 perf_evlist__enable(top->evlist); 964 perf_evlist__enable(top->evlist);
947 965
948 /* Wait for a minimal set of events before starting the snapshot */ 966 /* Wait for a minimal set of events before starting the snapshot */
949 poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 967 perf_evlist__poll(top->evlist, 100);
950 968
951 perf_top__mmap_read(top); 969 perf_top__mmap_read(top);
952 970
@@ -963,7 +981,7 @@ static int __cmd_top(struct perf_top *top)
963 param.sched_priority = top->realtime_prio; 981 param.sched_priority = top->realtime_prio;
964 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 982 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
965 ui__error("Could not set realtime priority.\n"); 983 ui__error("Could not set realtime priority.\n");
966 goto out_delete; 984 goto out_join;
967 } 985 }
968 } 986 }
969 987
@@ -973,10 +991,12 @@ static int __cmd_top(struct perf_top *top)
973 perf_top__mmap_read(top); 991 perf_top__mmap_read(top);
974 992
975 if (hits == top->samples) 993 if (hits == top->samples)
976 ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 994 ret = perf_evlist__poll(top->evlist, 100);
977 } 995 }
978 996
979 ret = 0; 997 ret = 0;
998out_join:
999 pthread_join(thread, NULL);
980out_delete: 1000out_delete:
981 perf_session__delete(top->session); 1001 perf_session__delete(top->session);
982 top->session = NULL; 1002 top->session = NULL;
@@ -1000,10 +1020,8 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1000 1020
1001static int perf_top_config(const char *var, const char *value, void *cb) 1021static int perf_top_config(const char *var, const char *value, void *cb)
1002{ 1022{
1003 struct perf_top *top = cb;
1004
1005 if (!strcmp(var, "top.call-graph")) 1023 if (!strcmp(var, "top.call-graph"))
1006 return record_parse_callchain(value, &top->record_opts); 1024 var = "call-graph.record-mode"; /* fall-through */
1007 if (!strcmp(var, "top.children")) { 1025 if (!strcmp(var, "top.children")) {
1008 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 1026 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
1009 return 0; 1027 return 0;
@@ -1122,6 +1140,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1122 "Interleave source code with assembly code (default)"), 1140 "Interleave source code with assembly code (default)"),
1123 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 1141 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
1124 "Display raw encoding of assembly instructions (default)"), 1142 "Display raw encoding of assembly instructions (default)"),
1143 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
1144 "Enable kernel symbol demangling"),
1125 OPT_STRING(0, "objdump", &objdump_path, "path", 1145 OPT_STRING(0, "objdump", &objdump_path, "path",
1126 "objdump binary to use for disassembly and annotations"), 1146 "objdump binary to use for disassembly and annotations"),
1127 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1147 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
@@ -1131,6 +1151,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1131 "Don't show entries under that percent", parse_percent_limit), 1151 "Don't show entries under that percent", parse_percent_limit),
1132 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 1152 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
1133 "How to display percentage of filtered entries", parse_filter_percentage), 1153 "How to display percentage of filtered entries", parse_filter_percentage),
1154 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
1155 "width[,width...]",
1156 "don't try to adjust column width, use these fixed values"),
1134 OPT_END() 1157 OPT_END()
1135 }; 1158 };
1136 const char * const top_usage[] = { 1159 const char * const top_usage[] = {
@@ -1217,7 +1240,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1217 symbol_conf.priv_size = sizeof(struct annotation); 1240 symbol_conf.priv_size = sizeof(struct annotation);
1218 1241
1219 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1242 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1220 if (symbol__init() < 0) 1243 if (symbol__init(NULL) < 0)
1221 return -1; 1244 return -1;
1222 1245
1223 sort__setup_elide(stdout); 1246 sort__setup_elide(stdout);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a6c375224f46..09bcf2393910 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -402,6 +402,31 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
402 402
403#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 403#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
404 404
405static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
406 struct syscall_arg *arg)
407{
408 int printed = 0, flags = arg->val;
409
410#define P_MREMAP_FLAG(n) \
411 if (flags & MREMAP_##n) { \
412 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
413 flags &= ~MREMAP_##n; \
414 }
415
416 P_MREMAP_FLAG(MAYMOVE);
417#ifdef MREMAP_FIXED
418 P_MREMAP_FLAG(FIXED);
419#endif
420#undef P_MREMAP_FLAG
421
422 if (flags)
423 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
424
425 return printed;
426}
427
428#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
429
405static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 430static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
406 struct syscall_arg *arg) 431 struct syscall_arg *arg)
407{ 432{
@@ -1004,6 +1029,7 @@ static struct syscall_fmt {
1004 [2] = SCA_MMAP_PROT, /* prot */ }, }, 1029 [2] = SCA_MMAP_PROT, /* prot */ }, },
1005 { .name = "mremap", .hexret = true, 1030 { .name = "mremap", .hexret = true,
1006 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 1031 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
1032 [3] = SCA_MREMAP_FLAGS, /* flags */
1007 [4] = SCA_HEX, /* new_addr */ }, }, 1033 [4] = SCA_HEX, /* new_addr */ }, },
1008 { .name = "munlock", .errmsg = true, 1034 { .name = "munlock", .errmsg = true,
1009 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 1035 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
@@ -1385,7 +1411,7 @@ static int trace__tool_process(struct perf_tool *tool,
1385 1411
1386static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1412static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1387{ 1413{
1388 int err = symbol__init(); 1414 int err = symbol__init(NULL);
1389 1415
1390 if (err) 1416 if (err)
1391 return err; 1417 return err;
@@ -1669,7 +1695,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1669 union perf_event *event __maybe_unused, 1695 union perf_event *event __maybe_unused,
1670 struct perf_sample *sample) 1696 struct perf_sample *sample)
1671{ 1697{
1672 int ret; 1698 long ret;
1673 u64 duration = 0; 1699 u64 duration = 0;
1674 struct thread *thread; 1700 struct thread *thread;
1675 int id = perf_evsel__sc_tp_uint(evsel, id, sample); 1701 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
@@ -1722,9 +1748,9 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1722 1748
1723 if (sc->fmt == NULL) { 1749 if (sc->fmt == NULL) {
1724signed_print: 1750signed_print:
1725 fprintf(trace->output, ") = %d", ret); 1751 fprintf(trace->output, ") = %ld", ret);
1726 } else if (ret < 0 && sc->fmt->errmsg) { 1752 } else if (ret < 0 && sc->fmt->errmsg) {
1727 char bf[256]; 1753 char bf[STRERR_BUFSIZE];
1728 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 1754 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1729 *e = audit_errno_to_name(-ret); 1755 *e = audit_errno_to_name(-ret);
1730 1756
@@ -1732,7 +1758,7 @@ signed_print:
1732 } else if (ret == 0 && sc->fmt->timeout) 1758 } else if (ret == 0 && sc->fmt->timeout)
1733 fprintf(trace->output, ") = 0 Timeout"); 1759 fprintf(trace->output, ") = 0 Timeout");
1734 else if (sc->fmt->hexret) 1760 else if (sc->fmt->hexret)
1735 fprintf(trace->output, ") = %#x", ret); 1761 fprintf(trace->output, ") = %#lx", ret);
1736 else 1762 else
1737 goto signed_print; 1763 goto signed_print;
1738 1764
@@ -2018,6 +2044,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2018 int err = -1, i; 2044 int err = -1, i;
2019 unsigned long before; 2045 unsigned long before;
2020 const bool forks = argc > 0; 2046 const bool forks = argc > 0;
2047 bool draining = false;
2048 char sbuf[STRERR_BUFSIZE];
2021 2049
2022 trace->live = true; 2050 trace->live = true;
2023 2051
@@ -2079,7 +2107,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2079 2107
2080 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); 2108 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
2081 if (err < 0) { 2109 if (err < 0) {
2082 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno)); 2110 fprintf(trace->output, "Couldn't mmap the events: %s\n",
2111 strerror_r(errno, sbuf, sizeof(sbuf)));
2083 goto out_delete_evlist; 2112 goto out_delete_evlist;
2084 } 2113 }
2085 2114
@@ -2143,8 +2172,12 @@ next_event:
2143 if (trace->nr_events == before) { 2172 if (trace->nr_events == before) {
2144 int timeout = done ? 100 : -1; 2173 int timeout = done ? 100 : -1;
2145 2174
2146 if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0) 2175 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2176 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2177 draining = true;
2178
2147 goto again; 2179 goto again;
2180 }
2148 } else { 2181 } else {
2149 goto again; 2182 goto again;
2150 } 2183 }
@@ -2209,18 +2242,18 @@ static int trace__replay(struct trace *trace)
2209 trace->tool.tracing_data = perf_event__process_tracing_data; 2242 trace->tool.tracing_data = perf_event__process_tracing_data;
2210 trace->tool.build_id = perf_event__process_build_id; 2243 trace->tool.build_id = perf_event__process_build_id;
2211 2244
2212 trace->tool.ordered_samples = true; 2245 trace->tool.ordered_events = true;
2213 trace->tool.ordering_requires_timestamps = true; 2246 trace->tool.ordering_requires_timestamps = true;
2214 2247
2215 /* add tid to output */ 2248 /* add tid to output */
2216 trace->multiple_threads = true; 2249 trace->multiple_threads = true;
2217 2250
2218 if (symbol__init() < 0)
2219 return -1;
2220
2221 session = perf_session__new(&file, false, &trace->tool); 2251 session = perf_session__new(&file, false, &trace->tool);
2222 if (session == NULL) 2252 if (session == NULL)
2223 return -ENOMEM; 2253 return -1;
2254
2255 if (symbol__init(&session->header.env) < 0)
2256 goto out;
2224 2257
2225 trace->host = &session->machines.host; 2258 trace->host = &session->machines.host;
2226 2259
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 1f67aa02d240..58f609198c6d 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -48,10 +48,6 @@ ifneq ($(ARCH),$(filter $(ARCH),x86 arm))
48 NO_LIBDW_DWARF_UNWIND := 1 48 NO_LIBDW_DWARF_UNWIND := 1
49endif 49endif
50 50
51ifeq ($(ARCH),powerpc)
52 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
53endif
54
55ifeq ($(LIBUNWIND_LIBS),) 51ifeq ($(LIBUNWIND_LIBS),)
56 NO_LIBUNWIND := 1 52 NO_LIBUNWIND := 1
57else 53else
@@ -120,6 +116,29 @@ ifdef PARSER_DEBUG
120 CFLAGS += -DPARSER_DEBUG 116 CFLAGS += -DPARSER_DEBUG
121endif 117endif
122 118
119ifndef NO_LIBPYTHON
120 # Try different combinations to accommodate systems that only have
121 # python[2][-config] in weird combinations but always preferring
122 # python2 and python2-config as per pep-0394. If we catch a
123 # python[-config] in version 3, the version check will kill it.
124 PYTHON2 := $(if $(call get-executable,python2),python2,python)
125 override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2))
126 PYTHON2_CONFIG := \
127 $(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config)
128 override PYTHON_CONFIG := \
129 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG))
130
131 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
132
133 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
134 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
135
136 FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
137 FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
138 FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS)
139 FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
140endif
141
123CFLAGS += -fno-omit-frame-pointer 142CFLAGS += -fno-omit-frame-pointer
124CFLAGS += -ggdb3 143CFLAGS += -ggdb3
125CFLAGS += -funwind-tables 144CFLAGS += -funwind-tables
@@ -355,6 +374,12 @@ ifndef NO_LIBELF
355 endif # NO_DWARF 374 endif # NO_DWARF
356endif # NO_LIBELF 375endif # NO_LIBELF
357 376
377ifeq ($(ARCH),powerpc)
378 ifndef NO_DWARF
379 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
380 endif
381endif
382
358ifndef NO_LIBUNWIND 383ifndef NO_LIBUNWIND
359 ifneq ($(feature-libunwind), 1) 384 ifneq ($(feature-libunwind), 1)
360 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); 385 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
@@ -482,21 +507,14 @@ define disable-python_code
482 NO_LIBPYTHON := 1 507 NO_LIBPYTHON := 1
483endef 508endef
484 509
485override PYTHON := \ 510ifdef NO_LIBPYTHON
486 $(call get-executable-or-default,PYTHON,python) 511 $(call disable-python)
487
488ifndef PYTHON
489 $(call disable-python,python interpreter)
490else 512else
491 513
492 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 514 ifndef PYTHON
493 515 $(call disable-python,python interpreter)
494 ifdef NO_LIBPYTHON
495 $(call disable-python)
496 else 516 else
497 517 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
498 override PYTHON_CONFIG := \
499 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config)
500 518
501 ifndef PYTHON_CONFIG 519 ifndef PYTHON_CONFIG
502 $(call disable-python,python-config tool) 520 $(call disable-python,python-config tool)
@@ -635,11 +653,13 @@ else
635sysconfdir = $(prefix)/etc 653sysconfdir = $(prefix)/etc
636ETC_PERFCONFIG = etc/perfconfig 654ETC_PERFCONFIG = etc/perfconfig
637endif 655endif
656ifndef lib
638ifeq ($(IS_X86_64),1) 657ifeq ($(IS_X86_64),1)
639lib = lib64 658lib = lib64
640else 659else
641lib = lib 660lib = lib
642endif 661endif
662endif # lib
643libdir = $(prefix)/$(lib) 663libdir = $(prefix)/$(lib)
644 664
645# Shell quote (do not use $(call) to accommodate ancient setups); 665# Shell quote (do not use $(call) to accommodate ancient setups);
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 6088f8d8a434..72ab2984718e 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -101,25 +101,11 @@ FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
101test-libperl.bin: 101test-libperl.bin:
102 $(BUILD) $(FLAGS_PERL_EMBED) 102 $(BUILD) $(FLAGS_PERL_EMBED)
103 103
104override PYTHON := python
105override PYTHON_CONFIG := python-config
106
107escape-for-shell-sq = $(subst ','\'',$(1))
108shell-sq = '$(escape-for-shell-sq)'
109
110PYTHON_CONFIG_SQ = $(call shell-sq,$(PYTHON_CONFIG))
111
112PYTHON_EMBED_LDOPTS = $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
113PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
114PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
115PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
116FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
117
118test-libpython.bin: 104test-libpython.bin:
119 $(BUILD) $(FLAGS_PYTHON_EMBED) 105 $(BUILD)
120 106
121test-libpython-version.bin: 107test-libpython-version.bin:
122 $(BUILD) $(FLAGS_PYTHON_EMBED) 108 $(BUILD)
123 109
124test-libbfd.bin: 110test-libbfd.bin:
125 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 111 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 4d985e0f03f5..7076a62d0ff7 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -132,7 +132,7 @@ endef
132# 132#
133# Usage: bool-value = $(call is-absolute,path) 133# Usage: bool-value = $(call is-absolute,path)
134# 134#
135is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y) 135is-absolute = $(shell echo $(shell-sq) | grep -q ^/ && echo y)
136 136
137# lookup 137# lookup
138# 138#
diff --git a/tools/perf/perf-with-kcore.sh b/tools/perf/perf-with-kcore.sh
new file mode 100644
index 000000000000..c7ff90a90e4e
--- /dev/null
+++ b/tools/perf/perf-with-kcore.sh
@@ -0,0 +1,259 @@
1#!/bin/bash
2# perf-with-kcore: use perf with a copy of kcore
3# Copyright (c) 2014, Intel Corporation.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms and conditions of the GNU General Public License,
7# version 2, as published by the Free Software Foundation.
8#
9# This program is distributed in the hope it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details.
13
14set -e
15
16usage()
17{
18 echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2
19 echo " <perf sub-command> can be record, script, report or inject" >&2
20 echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2
21 exit 1
22}
23
24find_perf()
25{
26 if [ -n "$PERF" ] ; then
27 return
28 fi
29 PERF=`which perf || true`
30 if [ -z "$PERF" ] ; then
31 echo "Failed to find perf" >&2
32 exit 1
33 fi
34 if [ ! -x "$PERF" ] ; then
35 echo "Failed to find perf" >&2
36 exit 1
37 fi
38 echo "Using $PERF"
39 "$PERF" version
40}
41
42copy_kcore()
43{
44 echo "Copying kcore"
45
46 if [ $EUID -eq 0 ] ; then
47 SUDO=""
48 else
49 SUDO="sudo"
50 fi
51
52 rm -f perf.data.junk
53 ("$PERF" record -o perf.data.junk $PERF_OPTIONS -- sleep 60) >/dev/null 2>/dev/null &
54 PERF_PID=$!
55
56 # Need to make sure that perf has started
57 sleep 1
58
59 KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1)
60 case "$KCORE" in
61 "kcore added to build-id cache directory "*)
62 KCORE_DIR=${KCORE#"kcore added to build-id cache directory "}
63 ;;
64 *)
65 kill $PERF_PID
66 wait >/dev/null 2>/dev/null || true
67 rm perf.data.junk
68 echo "$KCORE"
69 echo "Failed to find kcore" >&2
70 exit 1
71 ;;
72 esac
73
74 kill $PERF_PID
75 wait >/dev/null 2>/dev/null || true
76 rm perf.data.junk
77
78 $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR"
79 $SUDO rm -f "$KCORE_DIR/kcore"
80 $SUDO rm -f "$KCORE_DIR/kallsyms"
81 $SUDO rm -f "$KCORE_DIR/modules"
82 $SUDO rmdir "$KCORE_DIR"
83
84 KCORE_DIR_BASENAME=$(basename "$KCORE_DIR")
85 KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME"
86
87 $SUDO chown $UID "$KCORE_DIR"
88 $SUDO chown $UID "$KCORE_DIR/kcore"
89 $SUDO chown $UID "$KCORE_DIR/kallsyms"
90 $SUDO chown $UID "$KCORE_DIR/modules"
91
92 $SUDO chgrp $GROUPS "$KCORE_DIR"
93 $SUDO chgrp $GROUPS "$KCORE_DIR/kcore"
94 $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms"
95 $SUDO chgrp $GROUPS "$KCORE_DIR/modules"
96
97 ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir"
98}
99
100fix_buildid_cache_permissions()
101{
102 if [ $EUID -ne 0 ] ; then
103 echo "This script must be run as root via sudo " >&2
104 exit 1
105 fi
106
107 if [ -z "$SUDO_USER" ] ; then
108 echo "This script must be run via sudo" >&2
109 exit 1
110 fi
111
112 USER_HOME=$(bash <<< "echo ~$SUDO_USER")
113
114 if [ "$HOME" != "$USER_HOME" ] ; then
115 echo "Fix unnecessary because root has a home: $HOME" >&2
116 exit 1
117 fi
118
119 echo "Fixing buildid cache permissions"
120
121 find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
122 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
123 find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \;
124
125 if [ -n "$SUDO_GID" ] ; then
126 find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
127 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
128 find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \;
129 fi
130
131 echo "Done"
132}
133
134check_buildid_cache_permissions()
135{
136 if [ $EUID -eq 0 ] ; then
137 return
138 fi
139
140 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit)
141 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit)
142 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit)
143
144 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit)
145 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit)
146 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit)
147
148 if [ -n "$PERMISSIONS_OK" ] ; then
149 echo "*** WARNING *** buildid cache permissions may need fixing" >&2
150 fi
151}
152
153record()
154{
155 echo "Recording"
156
157 if [ $EUID -ne 0 ] ; then
158
159 if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then
160 echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2
161 fi
162
163 if echo "$PERF_OPTIONS" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
164 echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
165 fi
166
167 if echo "$PERF_OPTIONS" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
168 if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then
169 echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2
170 fi
171
172 if echo "$PERF_OPTIONS" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
173 true
174 elif echo "$PERF_OPTIONS" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
175 true
176 elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then
177 echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2
178 fi
179 fi
180 fi
181
182 if [ -z "$1" ] ; then
183 echo "Workload is required for recording" >&2
184 usage
185 fi
186
187 if [ -e "$PERF_DATA_DIR" ] ; then
188 echo "'$PERF_DATA_DIR' exists" >&2
189 exit 1
190 fi
191
192 find_perf
193
194 mkdir "$PERF_DATA_DIR"
195
196 echo "$PERF record -o $PERF_DATA_DIR/perf.data $PERF_OPTIONS -- $*"
197 "$PERF" record -o "$PERF_DATA_DIR/perf.data" $PERF_OPTIONS -- $* || true
198
199 if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then
200 exit 1
201 fi
202
203 copy_kcore
204
205 echo "Done"
206}
207
208subcommand()
209{
210 find_perf
211 check_buildid_cache_permissions
212 echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $*"
213 "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" $*
214}
215
216if [ "$1" = "fix_buildid_cache_permissions" ] ; then
217 fix_buildid_cache_permissions
218 exit 0
219fi
220
221PERF_SUB_COMMAND=$1
222PERF_DATA_DIR=$2
223shift || true
224shift || true
225
226if [ -z "$PERF_SUB_COMMAND" ] ; then
227 usage
228fi
229
230if [ -z "$PERF_DATA_DIR" ] ; then
231 usage
232fi
233
234case "$PERF_SUB_COMMAND" in
235"record")
236 while [ "$1" != "--" ] ; do
237 PERF_OPTIONS+="$1 "
238 shift || break
239 done
240 if [ "$1" != "--" ] ; then
241 echo "Options and workload are required for recording" >&2
242 usage
243 fi
244 shift
245 record $*
246;;
247"script")
248 subcommand $*
249;;
250"report")
251 subcommand $*
252;;
253"inject")
254 subcommand $*
255;;
256*)
257 usage
258;;
259esac
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 2282d41879a2..452a8474d29d 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -313,6 +313,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
313 int status; 313 int status;
314 struct stat st; 314 struct stat st;
315 const char *prefix; 315 const char *prefix;
316 char sbuf[STRERR_BUFSIZE];
316 317
317 prefix = NULL; 318 prefix = NULL;
318 if (p->option & RUN_SETUP) 319 if (p->option & RUN_SETUP)
@@ -343,7 +344,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
343 status = 1; 344 status = 1;
344 /* Check for ENOSPC and EIO errors.. */ 345 /* Check for ENOSPC and EIO errors.. */
345 if (fflush(stdout)) { 346 if (fflush(stdout)) {
346 fprintf(stderr, "write failure on standard output: %s", strerror(errno)); 347 fprintf(stderr, "write failure on standard output: %s",
348 strerror_r(errno, sbuf, sizeof(sbuf)));
347 goto out; 349 goto out;
348 } 350 }
349 if (ferror(stdout)) { 351 if (ferror(stdout)) {
@@ -351,7 +353,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
351 goto out; 353 goto out;
352 } 354 }
353 if (fclose(stdout)) { 355 if (fclose(stdout)) {
354 fprintf(stderr, "close failed on standard output: %s", strerror(errno)); 356 fprintf(stderr, "close failed on standard output: %s",
357 strerror_r(errno, sbuf, sizeof(sbuf)));
355 goto out; 358 goto out;
356 } 359 }
357 status = 0; 360 status = 0;
@@ -466,6 +469,7 @@ void pthread__unblock_sigwinch(void)
466int main(int argc, const char **argv) 469int main(int argc, const char **argv)
467{ 470{
468 const char *cmd; 471 const char *cmd;
472 char sbuf[STRERR_BUFSIZE];
469 473
470 /* The page_size is placed in util object. */ 474 /* The page_size is placed in util object. */
471 page_size = sysconf(_SC_PAGE_SIZE); 475 page_size = sysconf(_SC_PAGE_SIZE);
@@ -561,7 +565,7 @@ int main(int argc, const char **argv)
561 } 565 }
562 566
563 fprintf(stderr, "Failed to run command '%s': %s\n", 567 fprintf(stderr, "Failed to run command '%s': %s\n",
564 cmd, strerror(errno)); 568 cmd, strerror_r(errno, sbuf, sizeof(sbuf)));
565out: 569out:
566 return 1; 570 return 1;
567} 571}
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 510c65f72858..220d44e44c1b 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -41,8 +41,6 @@ void pthread__unblock_sigwinch(void);
41 41
42struct record_opts { 42struct record_opts {
43 struct target target; 43 struct target target;
44 int call_graph;
45 bool call_graph_enabled;
46 bool group; 44 bool group;
47 bool inherit_stat; 45 bool inherit_stat;
48 bool no_buffering; 46 bool no_buffering;
@@ -60,7 +58,6 @@ struct record_opts {
60 u64 branch_stack; 58 u64 branch_stack;
61 u64 default_interval; 59 u64 default_interval;
62 u64 user_interval; 60 u64 user_interval;
63 u16 stack_dump_size;
64 bool sample_transaction; 61 bool sample_transaction;
65 unsigned initial_delay; 62 unsigned initial_delay;
66}; 63};
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 6f8b01bc6033..ac655b0700e7 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -154,6 +154,18 @@ static struct test {
154 .func = test__hists_cumulate, 154 .func = test__hists_cumulate,
155 }, 155 },
156 { 156 {
157 .desc = "Test tracking with sched_switch",
158 .func = test__switch_tracking,
159 },
160 {
161 .desc = "Filter fds with revents mask in a fdarray",
162 .func = test__fdarray__filter,
163 },
164 {
165 .desc = "Add fd to a fdarray, making it autogrow",
166 .func = test__fdarray__add,
167 },
168 {
157 .func = NULL, 169 .func = NULL,
158 }, 170 },
159}; 171};
@@ -185,9 +197,11 @@ static bool perf_test__matches(int curr, int argc, const char *argv[])
185static int run_test(struct test *test) 197static int run_test(struct test *test)
186{ 198{
187 int status, err = -1, child = fork(); 199 int status, err = -1, child = fork();
200 char sbuf[STRERR_BUFSIZE];
188 201
189 if (child < 0) { 202 if (child < 0) {
190 pr_err("failed to fork test: %s\n", strerror(errno)); 203 pr_err("failed to fork test: %s\n",
204 strerror_r(errno, sbuf, sizeof(sbuf)));
191 return -1; 205 return -1;
192 } 206 }
193 207
@@ -297,7 +311,7 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
297 symbol_conf.sort_by_name = true; 311 symbol_conf.sort_by_name = true;
298 symbol_conf.try_vmlinux_path = true; 312 symbol_conf.try_vmlinux_path = true;
299 313
300 if (symbol__init() < 0) 314 if (symbol__init(NULL) < 0)
301 return -1; 315 return -1;
302 316
303 if (skip != NULL) 317 if (skip != NULL)
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
new file mode 100644
index 000000000000..d24b837951d4
--- /dev/null
+++ b/tools/perf/tests/fdarray.c
@@ -0,0 +1,174 @@
1#include <api/fd/array.h>
2#include "util/debug.h"
3#include "tests/tests.h"
4
5static void fdarray__init_revents(struct fdarray *fda, short revents)
6{
7 int fd;
8
9 fda->nr = fda->nr_alloc;
10
11 for (fd = 0; fd < fda->nr; ++fd) {
12 fda->entries[fd].fd = fda->nr - fd;
13 fda->entries[fd].revents = revents;
14 }
15}
16
17static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE *fp)
18{
19 int printed = 0;
20
21 if (!verbose)
22 return 0;
23
24 printed += fprintf(fp, "\n%s: ", prefix);
25 return printed + fdarray__fprintf(fda, fp);
26}
27
28int test__fdarray__filter(void)
29{
30 int nr_fds, expected_fd[2], fd, err = TEST_FAIL;
31 struct fdarray *fda = fdarray__new(5, 5);
32
33 if (fda == NULL) {
34 pr_debug("\nfdarray__new() failed!");
35 goto out;
36 }
37
38 fdarray__init_revents(fda, POLLIN);
39 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
40 if (nr_fds != fda->nr_alloc) {
41 pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything",
42 nr_fds, fda->nr_alloc);
43 goto out_delete;
44 }
45
46 fdarray__init_revents(fda, POLLHUP);
47 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
48 if (nr_fds != 0) {
49 pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds",
50 nr_fds, fda->nr_alloc);
51 goto out_delete;
52 }
53
54 fdarray__init_revents(fda, POLLHUP);
55 fda->entries[2].revents = POLLIN;
56 expected_fd[0] = fda->entries[2].fd;
57
58 pr_debug("\nfiltering all but fda->entries[2]:");
59 fdarray__fprintf_prefix(fda, "before", stderr);
60 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
61 fdarray__fprintf_prefix(fda, " after", stderr);
62 if (nr_fds != 1) {
63 pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds);
64 goto out_delete;
65 }
66
67 if (fda->entries[0].fd != expected_fd[0]) {
68 pr_debug("\nfda->entries[0].fd=%d != %d\n",
69 fda->entries[0].fd, expected_fd[0]);
70 goto out_delete;
71 }
72
73 fdarray__init_revents(fda, POLLHUP);
74 fda->entries[0].revents = POLLIN;
75 expected_fd[0] = fda->entries[0].fd;
76 fda->entries[3].revents = POLLIN;
77 expected_fd[1] = fda->entries[3].fd;
78
79 pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):");
80 fdarray__fprintf_prefix(fda, "before", stderr);
81 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
82 fdarray__fprintf_prefix(fda, " after", stderr);
83 if (nr_fds != 2) {
84 pr_debug("\nfdarray__filter()=%d != 2, should have left just two events",
85 nr_fds);
86 goto out_delete;
87 }
88
89 for (fd = 0; fd < 2; ++fd) {
90 if (fda->entries[fd].fd != expected_fd[fd]) {
91 pr_debug("\nfda->entries[%d].fd=%d != %d\n", fd,
92 fda->entries[fd].fd, expected_fd[fd]);
93 goto out_delete;
94 }
95 }
96
97 pr_debug("\n");
98
99 err = 0;
100out_delete:
101 fdarray__delete(fda);
102out:
103 return err;
104}
105
106int test__fdarray__add(void)
107{
108 int err = TEST_FAIL;
109 struct fdarray *fda = fdarray__new(2, 2);
110
111 if (fda == NULL) {
112 pr_debug("\nfdarray__new() failed!");
113 goto out;
114 }
115
116#define FDA_CHECK(_idx, _fd, _revents) \
117 if (fda->entries[_idx].fd != _fd) { \
118 pr_debug("\n%d: fda->entries[%d](%d) != %d!", \
119 __LINE__, _idx, fda->entries[1].fd, _fd); \
120 goto out_delete; \
121 } \
122 if (fda->entries[_idx].events != (_revents)) { \
123 pr_debug("\n%d: fda->entries[%d].revents(%d) != %d!", \
124 __LINE__, _idx, fda->entries[_idx].fd, _revents); \
125 goto out_delete; \
126 }
127
128#define FDA_ADD(_idx, _fd, _revents, _nr) \
129 if (fdarray__add(fda, _fd, _revents) < 0) { \
130 pr_debug("\n%d: fdarray__add(fda, %d, %d) failed!", \
131 __LINE__,_fd, _revents); \
132 goto out_delete; \
133 } \
134 if (fda->nr != _nr) { \
135 pr_debug("\n%d: fdarray__add(fda, %d, %d)=%d != %d", \
136 __LINE__,_fd, _revents, fda->nr, _nr); \
137 goto out_delete; \
138 } \
139 FDA_CHECK(_idx, _fd, _revents)
140
141 FDA_ADD(0, 1, POLLIN, 1);
142 FDA_ADD(1, 2, POLLERR, 2);
143
144 fdarray__fprintf_prefix(fda, "before growing array", stderr);
145
146 FDA_ADD(2, 35, POLLHUP, 3);
147
148 if (fda->entries == NULL) {
149 pr_debug("\nfdarray__add(fda, 35, POLLHUP) should have allocated fda->pollfd!");
150 goto out_delete;
151 }
152
153 fdarray__fprintf_prefix(fda, "after 3rd add", stderr);
154
155 FDA_ADD(3, 88, POLLIN | POLLOUT, 4);
156
157 fdarray__fprintf_prefix(fda, "after 4th add", stderr);
158
159 FDA_CHECK(0, 1, POLLIN);
160 FDA_CHECK(1, 2, POLLERR);
161 FDA_CHECK(2, 35, POLLHUP);
162 FDA_CHECK(3, 88, POLLIN | POLLOUT);
163
164#undef FDA_ADD
165#undef FDA_CHECK
166
167 pr_debug("\n");
168
169 err = 0;
170out_delete:
171 fdarray__delete(fda);
172out:
173 return err;
174}
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 142263492f6f..9b9622a33932 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -31,6 +31,7 @@ int test__basic_mmap(void)
31 unsigned int nr_events[nsyscalls], 31 unsigned int nr_events[nsyscalls],
32 expected_nr_events[nsyscalls], i, j; 32 expected_nr_events[nsyscalls], i, j;
33 struct perf_evsel *evsels[nsyscalls], *evsel; 33 struct perf_evsel *evsels[nsyscalls], *evsel;
34 char sbuf[STRERR_BUFSIZE];
34 35
35 threads = thread_map__new(-1, getpid(), UINT_MAX); 36 threads = thread_map__new(-1, getpid(), UINT_MAX);
36 if (threads == NULL) { 37 if (threads == NULL) {
@@ -49,7 +50,7 @@ int test__basic_mmap(void)
49 sched_setaffinity(0, sizeof(cpu_set), &cpu_set); 50 sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
50 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 51 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
51 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 52 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
52 cpus->map[0], strerror(errno)); 53 cpus->map[0], strerror_r(errno, sbuf, sizeof(sbuf)));
53 goto out_free_cpus; 54 goto out_free_cpus;
54 } 55 }
55 56
@@ -79,7 +80,7 @@ int test__basic_mmap(void)
79 if (perf_evsel__open(evsels[i], cpus, threads) < 0) { 80 if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
80 pr_debug("failed to open counter: %s, " 81 pr_debug("failed to open counter: %s, "
81 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 82 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
82 strerror(errno)); 83 strerror_r(errno, sbuf, sizeof(sbuf)));
83 goto out_delete_evlist; 84 goto out_delete_evlist;
84 } 85 }
85 86
@@ -89,7 +90,7 @@ int test__basic_mmap(void)
89 90
90 if (perf_evlist__mmap(evlist, 128, true) < 0) { 91 if (perf_evlist__mmap(evlist, 128, true) < 0) {
91 pr_debug("failed to mmap events: %d (%s)\n", errno, 92 pr_debug("failed to mmap events: %d (%s)\n", errno,
92 strerror(errno)); 93 strerror_r(errno, sbuf, sizeof(sbuf)));
93 goto out_delete_evlist; 94 goto out_delete_evlist;
94 } 95 }
95 96
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c
index 5fecdbd2f5f7..8fa82d1700c7 100644
--- a/tools/perf/tests/open-syscall-all-cpus.c
+++ b/tools/perf/tests/open-syscall-all-cpus.c
@@ -12,6 +12,7 @@ int test__open_syscall_event_on_all_cpus(void)
12 unsigned int nr_open_calls = 111, i; 12 unsigned int nr_open_calls = 111, i;
13 cpu_set_t cpu_set; 13 cpu_set_t cpu_set;
14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
15 char sbuf[STRERR_BUFSIZE];
15 16
16 if (threads == NULL) { 17 if (threads == NULL) {
17 pr_debug("thread_map__new\n"); 18 pr_debug("thread_map__new\n");
@@ -35,7 +36,7 @@ int test__open_syscall_event_on_all_cpus(void)
35 if (perf_evsel__open(evsel, cpus, threads) < 0) { 36 if (perf_evsel__open(evsel, cpus, threads) < 0) {
36 pr_debug("failed to open counter: %s, " 37 pr_debug("failed to open counter: %s, "
37 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 38 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
38 strerror(errno)); 39 strerror_r(errno, sbuf, sizeof(sbuf)));
39 goto out_evsel_delete; 40 goto out_evsel_delete;
40 } 41 }
41 42
@@ -56,7 +57,7 @@ int test__open_syscall_event_on_all_cpus(void)
56 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 57 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
57 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 58 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
58 cpus->map[cpu], 59 cpus->map[cpu],
59 strerror(errno)); 60 strerror_r(errno, sbuf, sizeof(sbuf)));
60 goto out_close_fd; 61 goto out_close_fd;
61 } 62 }
62 for (i = 0; i < ncalls; ++i) { 63 for (i = 0; i < ncalls; ++i) {
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index 0785b64ffd6c..127dcae0b760 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -22,6 +22,7 @@ int test__syscall_open_tp_fields(void)
22 struct perf_evlist *evlist = perf_evlist__new(); 22 struct perf_evlist *evlist = perf_evlist__new();
23 struct perf_evsel *evsel; 23 struct perf_evsel *evsel;
24 int err = -1, i, nr_events = 0, nr_polls = 0; 24 int err = -1, i, nr_events = 0, nr_polls = 0;
25 char sbuf[STRERR_BUFSIZE];
25 26
26 if (evlist == NULL) { 27 if (evlist == NULL) {
27 pr_debug("%s: perf_evlist__new\n", __func__); 28 pr_debug("%s: perf_evlist__new\n", __func__);
@@ -48,13 +49,15 @@ int test__syscall_open_tp_fields(void)
48 49
49 err = perf_evlist__open(evlist); 50 err = perf_evlist__open(evlist);
50 if (err < 0) { 51 if (err < 0) {
51 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 52 pr_debug("perf_evlist__open: %s\n",
53 strerror_r(errno, sbuf, sizeof(sbuf)));
52 goto out_delete_evlist; 54 goto out_delete_evlist;
53 } 55 }
54 56
55 err = perf_evlist__mmap(evlist, UINT_MAX, false); 57 err = perf_evlist__mmap(evlist, UINT_MAX, false);
56 if (err < 0) { 58 if (err < 0) {
57 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 59 pr_debug("perf_evlist__mmap: %s\n",
60 strerror_r(errno, sbuf, sizeof(sbuf)));
58 goto out_delete_evlist; 61 goto out_delete_evlist;
59 } 62 }
60 63
@@ -102,7 +105,7 @@ int test__syscall_open_tp_fields(void)
102 } 105 }
103 106
104 if (nr_events == before) 107 if (nr_events == before)
105 poll(evlist->pollfd, evlist->nr_fds, 10); 108 perf_evlist__poll(evlist, 10);
106 109
107 if (++nr_polls > 5) { 110 if (++nr_polls > 5) {
108 pr_debug("%s: no events!\n", __func__); 111 pr_debug("%s: no events!\n", __func__);
diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c
index c1dc7d25f38c..a33b2daae40f 100644
--- a/tools/perf/tests/open-syscall.c
+++ b/tools/perf/tests/open-syscall.c
@@ -9,6 +9,7 @@ int test__open_syscall_event(void)
9 struct perf_evsel *evsel; 9 struct perf_evsel *evsel;
10 unsigned int nr_open_calls = 111, i; 10 unsigned int nr_open_calls = 111, i;
11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
12 char sbuf[STRERR_BUFSIZE];
12 13
13 if (threads == NULL) { 14 if (threads == NULL) {
14 pr_debug("thread_map__new\n"); 15 pr_debug("thread_map__new\n");
@@ -24,7 +25,7 @@ int test__open_syscall_event(void)
24 if (perf_evsel__open_per_thread(evsel, threads) < 0) { 25 if (perf_evsel__open_per_thread(evsel, threads) < 0) {
25 pr_debug("failed to open counter: %s, " 26 pr_debug("failed to open counter: %s, "
26 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 27 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
27 strerror(errno)); 28 strerror_r(errno, sbuf, sizeof(sbuf)));
28 goto out_evsel_delete; 29 goto out_evsel_delete;
29 } 30 }
30 31
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index aca1a83dd13a..7a228a2a070b 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -59,6 +59,7 @@ int test__PERF_RECORD(void)
59 int err = -1, errs = 0, i, wakeups = 0; 59 int err = -1, errs = 0, i, wakeups = 0;
60 u32 cpu; 60 u32 cpu;
61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; 61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
62 char sbuf[STRERR_BUFSIZE];
62 63
63 if (evlist == NULL || argv == NULL) { 64 if (evlist == NULL || argv == NULL) {
64 pr_debug("Not enough memory to create evlist\n"); 65 pr_debug("Not enough memory to create evlist\n");
@@ -100,7 +101,8 @@ int test__PERF_RECORD(void)
100 101
101 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); 102 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
102 if (err < 0) { 103 if (err < 0) {
103 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); 104 pr_debug("sched__get_first_possible_cpu: %s\n",
105 strerror_r(errno, sbuf, sizeof(sbuf)));
104 goto out_delete_evlist; 106 goto out_delete_evlist;
105 } 107 }
106 108
@@ -110,7 +112,8 @@ int test__PERF_RECORD(void)
110 * So that we can check perf_sample.cpu on all the samples. 112 * So that we can check perf_sample.cpu on all the samples.
111 */ 113 */
112 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { 114 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
113 pr_debug("sched_setaffinity: %s\n", strerror(errno)); 115 pr_debug("sched_setaffinity: %s\n",
116 strerror_r(errno, sbuf, sizeof(sbuf)));
114 goto out_delete_evlist; 117 goto out_delete_evlist;
115 } 118 }
116 119
@@ -120,7 +123,8 @@ int test__PERF_RECORD(void)
120 */ 123 */
121 err = perf_evlist__open(evlist); 124 err = perf_evlist__open(evlist);
122 if (err < 0) { 125 if (err < 0) {
123 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 126 pr_debug("perf_evlist__open: %s\n",
127 strerror_r(errno, sbuf, sizeof(sbuf)));
124 goto out_delete_evlist; 128 goto out_delete_evlist;
125 } 129 }
126 130
@@ -131,7 +135,8 @@ int test__PERF_RECORD(void)
131 */ 135 */
132 err = perf_evlist__mmap(evlist, opts.mmap_pages, false); 136 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
133 if (err < 0) { 137 if (err < 0) {
134 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 138 pr_debug("perf_evlist__mmap: %s\n",
139 strerror_r(errno, sbuf, sizeof(sbuf)));
135 goto out_delete_evlist; 140 goto out_delete_evlist;
136 } 141 }
137 142
@@ -263,7 +268,7 @@ int test__PERF_RECORD(void)
263 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does. 268 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
264 */ 269 */
265 if (total_events == before && false) 270 if (total_events == before && false)
266 poll(evlist->pollfd, evlist->nr_fds, -1); 271 perf_evlist__poll(evlist, -1);
267 272
268 sleep(1); 273 sleep(1);
269 if (++wakeups > 5) { 274 if (++wakeups > 5) {
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 12b322fa3475..eeb68bb1972d 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -152,7 +152,7 @@ int test__pmu(void)
152 if (ret) 152 if (ret)
153 break; 153 break;
154 154
155 ret = perf_pmu__config_terms(&formats, &attr, terms); 155 ret = perf_pmu__config_terms(&formats, &attr, terms, false);
156 if (ret) 156 if (ret)
157 break; 157 break;
158 158
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c
index c04d1f268576..d31f2c4d9f64 100644
--- a/tools/perf/tests/rdpmc.c
+++ b/tools/perf/tests/rdpmc.c
@@ -100,6 +100,7 @@ static int __test__rdpmc(void)
100 }; 100 };
101 u64 delta_sum = 0; 101 u64 delta_sum = 0;
102 struct sigaction sa; 102 struct sigaction sa;
103 char sbuf[STRERR_BUFSIZE];
103 104
104 sigfillset(&sa.sa_mask); 105 sigfillset(&sa.sa_mask);
105 sa.sa_sigaction = segfault_handler; 106 sa.sa_sigaction = segfault_handler;
@@ -109,14 +110,15 @@ static int __test__rdpmc(void)
109 perf_event_open_cloexec_flag()); 110 perf_event_open_cloexec_flag());
110 if (fd < 0) { 111 if (fd < 0) {
111 pr_err("Error: sys_perf_event_open() syscall returned " 112 pr_err("Error: sys_perf_event_open() syscall returned "
112 "with %d (%s)\n", fd, strerror(errno)); 113 "with %d (%s)\n", fd,
114 strerror_r(errno, sbuf, sizeof(sbuf)));
113 return -1; 115 return -1;
114 } 116 }
115 117
116 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); 118 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
117 if (addr == (void *)(-1)) { 119 if (addr == (void *)(-1)) {
118 pr_err("Error: mmap() syscall returned with (%s)\n", 120 pr_err("Error: mmap() syscall returned with (%s)\n",
119 strerror(errno)); 121 strerror_r(errno, sbuf, sizeof(sbuf)));
120 goto out_close; 122 goto out_close;
121 } 123 }
122 124
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 983d6b8562a8..1aa21c90731b 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -22,6 +22,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
22 volatile int tmp = 0; 22 volatile int tmp = 0;
23 u64 total_periods = 0; 23 u64 total_periods = 0;
24 int nr_samples = 0; 24 int nr_samples = 0;
25 char sbuf[STRERR_BUFSIZE];
25 union perf_event *event; 26 union perf_event *event;
26 struct perf_evsel *evsel; 27 struct perf_evsel *evsel;
27 struct perf_evlist *evlist; 28 struct perf_evlist *evlist;
@@ -62,14 +63,15 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
62 63
63 err = -errno; 64 err = -errno;
64 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", 65 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
65 strerror(errno), knob, (u64)attr.sample_freq); 66 strerror_r(errno, sbuf, sizeof(sbuf)),
67 knob, (u64)attr.sample_freq);
66 goto out_delete_evlist; 68 goto out_delete_evlist;
67 } 69 }
68 70
69 err = perf_evlist__mmap(evlist, 128, true); 71 err = perf_evlist__mmap(evlist, 128, true);
70 if (err < 0) { 72 if (err < 0) {
71 pr_debug("failed to mmap event: %d (%s)\n", errno, 73 pr_debug("failed to mmap event: %d (%s)\n", errno,
72 strerror(errno)); 74 strerror_r(errno, sbuf, sizeof(sbuf)));
73 goto out_delete_evlist; 75 goto out_delete_evlist;
74 } 76 }
75 77
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
new file mode 100644
index 000000000000..cc68648c7c55
--- /dev/null
+++ b/tools/perf/tests/switch-tracking.c
@@ -0,0 +1,572 @@
1#include <sys/time.h>
2#include <sys/prctl.h>
3#include <time.h>
4#include <stdlib.h>
5
6#include "parse-events.h"
7#include "evlist.h"
8#include "evsel.h"
9#include "thread_map.h"
10#include "cpumap.h"
11#include "tests.h"
12
13static int spin_sleep(void)
14{
15 struct timeval start, now, diff, maxtime;
16 struct timespec ts;
17 int err, i;
18
19 maxtime.tv_sec = 0;
20 maxtime.tv_usec = 50000;
21
22 err = gettimeofday(&start, NULL);
23 if (err)
24 return err;
25
26 /* Spin for 50ms */
27 while (1) {
28 for (i = 0; i < 1000; i++)
29 barrier();
30
31 err = gettimeofday(&now, NULL);
32 if (err)
33 return err;
34
35 timersub(&now, &start, &diff);
36 if (timercmp(&diff, &maxtime, > /* For checkpatch */))
37 break;
38 }
39
40 ts.tv_nsec = 50 * 1000 * 1000;
41 ts.tv_sec = 0;
42
43 /* Sleep for 50ms */
44 err = nanosleep(&ts, NULL);
45 if (err == EINTR)
46 err = 0;
47
48 return err;
49}
50
51struct switch_tracking {
52 struct perf_evsel *switch_evsel;
53 struct perf_evsel *cycles_evsel;
54 pid_t *tids;
55 int nr_tids;
56 int comm_seen[4];
57 int cycles_before_comm_1;
58 int cycles_between_comm_2_and_comm_3;
59 int cycles_after_comm_4;
60};
61
62static int check_comm(struct switch_tracking *switch_tracking,
63 union perf_event *event, const char *comm, int nr)
64{
65 if (event->header.type == PERF_RECORD_COMM &&
66 (pid_t)event->comm.pid == getpid() &&
67 (pid_t)event->comm.tid == getpid() &&
68 strcmp(event->comm.comm, comm) == 0) {
69 if (switch_tracking->comm_seen[nr]) {
70 pr_debug("Duplicate comm event\n");
71 return -1;
72 }
73 switch_tracking->comm_seen[nr] = 1;
74 pr_debug3("comm event: %s nr: %d\n", event->comm.comm, nr);
75 return 1;
76 }
77 return 0;
78}
79
80static int check_cpu(struct switch_tracking *switch_tracking, int cpu)
81{
82 int i, nr = cpu + 1;
83
84 if (cpu < 0)
85 return -1;
86
87 if (!switch_tracking->tids) {
88 switch_tracking->tids = calloc(nr, sizeof(pid_t));
89 if (!switch_tracking->tids)
90 return -1;
91 for (i = 0; i < nr; i++)
92 switch_tracking->tids[i] = -1;
93 switch_tracking->nr_tids = nr;
94 return 0;
95 }
96
97 if (cpu >= switch_tracking->nr_tids) {
98 void *addr;
99
100 addr = realloc(switch_tracking->tids, nr * sizeof(pid_t));
101 if (!addr)
102 return -1;
103 switch_tracking->tids = addr;
104 for (i = switch_tracking->nr_tids; i < nr; i++)
105 switch_tracking->tids[i] = -1;
106 switch_tracking->nr_tids = nr;
107 return 0;
108 }
109
110 return 0;
111}
112
113static int process_sample_event(struct perf_evlist *evlist,
114 union perf_event *event,
115 struct switch_tracking *switch_tracking)
116{
117 struct perf_sample sample;
118 struct perf_evsel *evsel;
119 pid_t next_tid, prev_tid;
120 int cpu, err;
121
122 if (perf_evlist__parse_sample(evlist, event, &sample)) {
123 pr_debug("perf_evlist__parse_sample failed\n");
124 return -1;
125 }
126
127 evsel = perf_evlist__id2evsel(evlist, sample.id);
128 if (evsel == switch_tracking->switch_evsel) {
129 next_tid = perf_evsel__intval(evsel, &sample, "next_pid");
130 prev_tid = perf_evsel__intval(evsel, &sample, "prev_pid");
131 cpu = sample.cpu;
132 pr_debug3("sched_switch: cpu: %d prev_tid %d next_tid %d\n",
133 cpu, prev_tid, next_tid);
134 err = check_cpu(switch_tracking, cpu);
135 if (err)
136 return err;
137 /*
138 * Check for no missing sched_switch events i.e. that the
139 * evsel->system_wide flag has worked.
140 */
141 if (switch_tracking->tids[cpu] != -1 &&
142 switch_tracking->tids[cpu] != prev_tid) {
143 pr_debug("Missing sched_switch events\n");
144 return -1;
145 }
146 switch_tracking->tids[cpu] = next_tid;
147 }
148
149 if (evsel == switch_tracking->cycles_evsel) {
150 pr_debug3("cycles event\n");
151 if (!switch_tracking->comm_seen[0])
152 switch_tracking->cycles_before_comm_1 = 1;
153 if (switch_tracking->comm_seen[1] &&
154 !switch_tracking->comm_seen[2])
155 switch_tracking->cycles_between_comm_2_and_comm_3 = 1;
156 if (switch_tracking->comm_seen[3])
157 switch_tracking->cycles_after_comm_4 = 1;
158 }
159
160 return 0;
161}
162
163static int process_event(struct perf_evlist *evlist, union perf_event *event,
164 struct switch_tracking *switch_tracking)
165{
166 if (event->header.type == PERF_RECORD_SAMPLE)
167 return process_sample_event(evlist, event, switch_tracking);
168
169 if (event->header.type == PERF_RECORD_COMM) {
170 int err, done = 0;
171
172 err = check_comm(switch_tracking, event, "Test COMM 1", 0);
173 if (err < 0)
174 return -1;
175 done += err;
176 err = check_comm(switch_tracking, event, "Test COMM 2", 1);
177 if (err < 0)
178 return -1;
179 done += err;
180 err = check_comm(switch_tracking, event, "Test COMM 3", 2);
181 if (err < 0)
182 return -1;
183 done += err;
184 err = check_comm(switch_tracking, event, "Test COMM 4", 3);
185 if (err < 0)
186 return -1;
187 done += err;
188 if (done != 1) {
189 pr_debug("Unexpected comm event\n");
190 return -1;
191 }
192 }
193
194 return 0;
195}
196
197struct event_node {
198 struct list_head list;
199 union perf_event *event;
200 u64 event_time;
201};
202
203static int add_event(struct perf_evlist *evlist, struct list_head *events,
204 union perf_event *event)
205{
206 struct perf_sample sample;
207 struct event_node *node;
208
209 node = malloc(sizeof(struct event_node));
210 if (!node) {
211 pr_debug("malloc failed\n");
212 return -1;
213 }
214 node->event = event;
215 list_add(&node->list, events);
216
217 if (perf_evlist__parse_sample(evlist, event, &sample)) {
218 pr_debug("perf_evlist__parse_sample failed\n");
219 return -1;
220 }
221
222 if (!sample.time) {
223 pr_debug("event with no time\n");
224 return -1;
225 }
226
227 node->event_time = sample.time;
228
229 return 0;
230}
231
232static void free_event_nodes(struct list_head *events)
233{
234 struct event_node *node;
235
236 while (!list_empty(events)) {
237 node = list_entry(events->next, struct event_node, list);
238 list_del(&node->list);
239 free(node);
240 }
241}
242
243static int compar(const void *a, const void *b)
244{
245 const struct event_node *nodea = a;
246 const struct event_node *nodeb = b;
247 s64 cmp = nodea->event_time - nodeb->event_time;
248
249 return cmp;
250}
251
252static int process_events(struct perf_evlist *evlist,
253 struct switch_tracking *switch_tracking)
254{
255 union perf_event *event;
256 unsigned pos, cnt = 0;
257 LIST_HEAD(events);
258 struct event_node *events_array, *node;
259 int i, ret;
260
261 for (i = 0; i < evlist->nr_mmaps; i++) {
262 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
263 cnt += 1;
264 ret = add_event(evlist, &events, event);
265 perf_evlist__mmap_consume(evlist, i);
266 if (ret < 0)
267 goto out_free_nodes;
268 }
269 }
270
271 events_array = calloc(cnt, sizeof(struct event_node));
272 if (!events_array) {
273 pr_debug("calloc failed\n");
274 ret = -1;
275 goto out_free_nodes;
276 }
277
278 pos = 0;
279 list_for_each_entry(node, &events, list)
280 events_array[pos++] = *node;
281
282 qsort(events_array, cnt, sizeof(struct event_node), compar);
283
284 for (pos = 0; pos < cnt; pos++) {
285 ret = process_event(evlist, events_array[pos].event,
286 switch_tracking);
287 if (ret < 0)
288 goto out_free;
289 }
290
291 ret = 0;
292out_free:
293 pr_debug("%u events recorded\n", cnt);
294 free(events_array);
295out_free_nodes:
296 free_event_nodes(&events);
297 return ret;
298}
299
300/**
301 * test__switch_tracking - test using sched_switch and tracking events.
302 *
303 * This function implements a test that checks that sched_switch events and
304 * tracking events can be recorded for a workload (current process) using the
305 * evsel->system_wide and evsel->tracking flags (respectively) with other events
306 * sometimes enabled or disabled.
307 */
308int test__switch_tracking(void)
309{
310 const char *sched_switch = "sched:sched_switch";
311 struct switch_tracking switch_tracking = { .tids = NULL, };
312 struct record_opts opts = {
313 .mmap_pages = UINT_MAX,
314 .user_freq = UINT_MAX,
315 .user_interval = ULLONG_MAX,
316 .freq = 4000,
317 .target = {
318 .uses_mmap = true,
319 },
320 };
321 struct thread_map *threads = NULL;
322 struct cpu_map *cpus = NULL;
323 struct perf_evlist *evlist = NULL;
324 struct perf_evsel *evsel, *cpu_clocks_evsel, *cycles_evsel;
325 struct perf_evsel *switch_evsel, *tracking_evsel;
326 const char *comm;
327 int err = -1;
328
329 threads = thread_map__new(-1, getpid(), UINT_MAX);
330 if (!threads) {
331 pr_debug("thread_map__new failed!\n");
332 goto out_err;
333 }
334
335 cpus = cpu_map__new(NULL);
336 if (!cpus) {
337 pr_debug("cpu_map__new failed!\n");
338 goto out_err;
339 }
340
341 evlist = perf_evlist__new();
342 if (!evlist) {
343 pr_debug("perf_evlist__new failed!\n");
344 goto out_err;
345 }
346
347 perf_evlist__set_maps(evlist, cpus, threads);
348
349 /* First event */
350 err = parse_events(evlist, "cpu-clock:u");
351 if (err) {
352 pr_debug("Failed to parse event dummy:u\n");
353 goto out_err;
354 }
355
356 cpu_clocks_evsel = perf_evlist__last(evlist);
357
358 /* Second event */
359 err = parse_events(evlist, "cycles:u");
360 if (err) {
361 pr_debug("Failed to parse event cycles:u\n");
362 goto out_err;
363 }
364
365 cycles_evsel = perf_evlist__last(evlist);
366
367 /* Third event */
368 if (!perf_evlist__can_select_event(evlist, sched_switch)) {
369 fprintf(stderr, " (no sched_switch)");
370 err = 0;
371 goto out;
372 }
373
374 err = parse_events(evlist, sched_switch);
375 if (err) {
376 pr_debug("Failed to parse event %s\n", sched_switch);
377 goto out_err;
378 }
379
380 switch_evsel = perf_evlist__last(evlist);
381
382 perf_evsel__set_sample_bit(switch_evsel, CPU);
383 perf_evsel__set_sample_bit(switch_evsel, TIME);
384
385 switch_evsel->system_wide = true;
386 switch_evsel->no_aux_samples = true;
387 switch_evsel->immediate = true;
388
389 /* Test moving an event to the front */
390 if (cycles_evsel == perf_evlist__first(evlist)) {
391 pr_debug("cycles event already at front");
392 goto out_err;
393 }
394 perf_evlist__to_front(evlist, cycles_evsel);
395 if (cycles_evsel != perf_evlist__first(evlist)) {
396 pr_debug("Failed to move cycles event to front");
397 goto out_err;
398 }
399
400 perf_evsel__set_sample_bit(cycles_evsel, CPU);
401 perf_evsel__set_sample_bit(cycles_evsel, TIME);
402
403 /* Fourth event */
404 err = parse_events(evlist, "dummy:u");
405 if (err) {
406 pr_debug("Failed to parse event dummy:u\n");
407 goto out_err;
408 }
409
410 tracking_evsel = perf_evlist__last(evlist);
411
412 perf_evlist__set_tracking_event(evlist, tracking_evsel);
413
414 tracking_evsel->attr.freq = 0;
415 tracking_evsel->attr.sample_period = 1;
416
417 perf_evsel__set_sample_bit(tracking_evsel, TIME);
418
419 /* Config events */
420 perf_evlist__config(evlist, &opts);
421
422 /* Check moved event is still at the front */
423 if (cycles_evsel != perf_evlist__first(evlist)) {
424 pr_debug("Front event no longer at front");
425 goto out_err;
426 }
427
428 /* Check tracking event is tracking */
429 if (!tracking_evsel->attr.mmap || !tracking_evsel->attr.comm) {
430 pr_debug("Tracking event not tracking\n");
431 goto out_err;
432 }
433
434 /* Check non-tracking events are not tracking */
435 evlist__for_each(evlist, evsel) {
436 if (evsel != tracking_evsel) {
437 if (evsel->attr.mmap || evsel->attr.comm) {
438 pr_debug("Non-tracking event is tracking\n");
439 goto out_err;
440 }
441 }
442 }
443
444 if (perf_evlist__open(evlist) < 0) {
445 fprintf(stderr, " (not supported)");
446 err = 0;
447 goto out;
448 }
449
450 err = perf_evlist__mmap(evlist, UINT_MAX, false);
451 if (err) {
452 pr_debug("perf_evlist__mmap failed!\n");
453 goto out_err;
454 }
455
456 perf_evlist__enable(evlist);
457
458 err = perf_evlist__disable_event(evlist, cpu_clocks_evsel);
459 if (err) {
460 pr_debug("perf_evlist__disable_event failed!\n");
461 goto out_err;
462 }
463
464 err = spin_sleep();
465 if (err) {
466 pr_debug("spin_sleep failed!\n");
467 goto out_err;
468 }
469
470 comm = "Test COMM 1";
471 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
472 if (err) {
473 pr_debug("PR_SET_NAME failed!\n");
474 goto out_err;
475 }
476
477 err = perf_evlist__disable_event(evlist, cycles_evsel);
478 if (err) {
479 pr_debug("perf_evlist__disable_event failed!\n");
480 goto out_err;
481 }
482
483 comm = "Test COMM 2";
484 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
485 if (err) {
486 pr_debug("PR_SET_NAME failed!\n");
487 goto out_err;
488 }
489
490 err = spin_sleep();
491 if (err) {
492 pr_debug("spin_sleep failed!\n");
493 goto out_err;
494 }
495
496 comm = "Test COMM 3";
497 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
498 if (err) {
499 pr_debug("PR_SET_NAME failed!\n");
500 goto out_err;
501 }
502
503 err = perf_evlist__enable_event(evlist, cycles_evsel);
504 if (err) {
505 pr_debug("perf_evlist__disable_event failed!\n");
506 goto out_err;
507 }
508
509 comm = "Test COMM 4";
510 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
511 if (err) {
512 pr_debug("PR_SET_NAME failed!\n");
513 goto out_err;
514 }
515
516 err = spin_sleep();
517 if (err) {
518 pr_debug("spin_sleep failed!\n");
519 goto out_err;
520 }
521
522 perf_evlist__disable(evlist);
523
524 switch_tracking.switch_evsel = switch_evsel;
525 switch_tracking.cycles_evsel = cycles_evsel;
526
527 err = process_events(evlist, &switch_tracking);
528
529 zfree(&switch_tracking.tids);
530
531 if (err)
532 goto out_err;
533
534 /* Check all 4 comm events were seen i.e. that evsel->tracking works */
535 if (!switch_tracking.comm_seen[0] || !switch_tracking.comm_seen[1] ||
536 !switch_tracking.comm_seen[2] || !switch_tracking.comm_seen[3]) {
537 pr_debug("Missing comm events\n");
538 goto out_err;
539 }
540
541 /* Check cycles event got enabled */
542 if (!switch_tracking.cycles_before_comm_1) {
543 pr_debug("Missing cycles events\n");
544 goto out_err;
545 }
546
547 /* Check cycles event got disabled */
548 if (switch_tracking.cycles_between_comm_2_and_comm_3) {
549 pr_debug("cycles events even though event was disabled\n");
550 goto out_err;
551 }
552
553 /* Check cycles event got enabled again */
554 if (!switch_tracking.cycles_after_comm_4) {
555 pr_debug("Missing cycles events\n");
556 goto out_err;
557 }
558out:
559 if (evlist) {
560 perf_evlist__disable(evlist);
561 perf_evlist__delete(evlist);
562 } else {
563 cpu_map__delete(cpus);
564 thread_map__delete(threads);
565 }
566
567 return err;
568
569out_err:
570 err = -1;
571 goto out;
572}
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 5ff3db318f12..3a8fedef83bc 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -42,6 +42,7 @@ int test__task_exit(void)
42 .uses_mmap = true, 42 .uses_mmap = true,
43 }; 43 };
44 const char *argv[] = { "true", NULL }; 44 const char *argv[] = { "true", NULL };
45 char sbuf[STRERR_BUFSIZE];
45 46
46 signal(SIGCHLD, sig_handler); 47 signal(SIGCHLD, sig_handler);
47 48
@@ -82,13 +83,14 @@ int test__task_exit(void)
82 83
83 err = perf_evlist__open(evlist); 84 err = perf_evlist__open(evlist);
84 if (err < 0) { 85 if (err < 0) {
85 pr_debug("Couldn't open the evlist: %s\n", strerror(-err)); 86 pr_debug("Couldn't open the evlist: %s\n",
87 strerror_r(-err, sbuf, sizeof(sbuf)));
86 goto out_delete_evlist; 88 goto out_delete_evlist;
87 } 89 }
88 90
89 if (perf_evlist__mmap(evlist, 128, true) < 0) { 91 if (perf_evlist__mmap(evlist, 128, true) < 0) {
90 pr_debug("failed to mmap events: %d (%s)\n", errno, 92 pr_debug("failed to mmap events: %d (%s)\n", errno,
91 strerror(errno)); 93 strerror_r(errno, sbuf, sizeof(sbuf)));
92 goto out_delete_evlist; 94 goto out_delete_evlist;
93 } 95 }
94 96
@@ -103,7 +105,7 @@ retry:
103 } 105 }
104 106
105 if (!exited || !nr_exit) { 107 if (!exited || !nr_exit) {
106 poll(evlist->pollfd, evlist->nr_fds, -1); 108 perf_evlist__poll(evlist, -1);
107 goto retry; 109 goto retry;
108 } 110 }
109 111
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index ed64790a395f..00e776a87a9c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -48,6 +48,9 @@ int test__mmap_thread_lookup(void);
48int test__thread_mg_share(void); 48int test__thread_mg_share(void);
49int test__hists_output(void); 49int test__hists_output(void);
50int test__hists_cumulate(void); 50int test__hists_cumulate(void);
51int test__switch_tracking(void);
52int test__fdarray__filter(void);
53int test__fdarray__add(void);
51 54
52#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 55#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
53#ifdef HAVE_DWARF_UNWIND_SUPPORT 56#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a94b11fc5e00..8f60a970404f 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -10,6 +10,7 @@
10#include "../../util/pstack.h" 10#include "../../util/pstack.h"
11#include "../../util/sort.h" 11#include "../../util/sort.h"
12#include "../../util/util.h" 12#include "../../util/util.h"
13#include "../../util/top.h"
13#include "../../arch/common.h" 14#include "../../arch/common.h"
14 15
15#include "../browser.h" 16#include "../browser.h"
@@ -228,8 +229,10 @@ static void callchain_node__init_have_children(struct callchain_node *node)
228{ 229{
229 struct callchain_list *chain; 230 struct callchain_list *chain;
230 231
231 list_for_each_entry(chain, &node->val, list) 232 if (!list_empty(&node->val)) {
233 chain = list_entry(node->val.prev, struct callchain_list, list);
232 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); 234 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root);
235 }
233 236
234 callchain_node__init_have_children_rb_tree(node); 237 callchain_node__init_have_children_rb_tree(node);
235} 238}
@@ -474,26 +477,87 @@ static char *callchain_list__sym_name(struct callchain_list *cl,
474 return bf; 477 return bf;
475} 478}
476 479
480struct callchain_print_arg {
481 /* for hists browser */
482 off_t row_offset;
483 bool is_current_entry;
484
485 /* for file dump */
486 FILE *fp;
487 int printed;
488};
489
490typedef void (*print_callchain_entry_fn)(struct hist_browser *browser,
491 struct callchain_list *chain,
492 const char *str, int offset,
493 unsigned short row,
494 struct callchain_print_arg *arg);
495
496static void hist_browser__show_callchain_entry(struct hist_browser *browser,
497 struct callchain_list *chain,
498 const char *str, int offset,
499 unsigned short row,
500 struct callchain_print_arg *arg)
501{
502 int color, width;
503 char folded_sign = callchain_list__folded(chain);
504
505 color = HE_COLORSET_NORMAL;
506 width = browser->b.width - (offset + 2);
507 if (ui_browser__is_current_entry(&browser->b, row)) {
508 browser->selection = &chain->ms;
509 color = HE_COLORSET_SELECTED;
510 arg->is_current_entry = true;
511 }
512
513 ui_browser__set_color(&browser->b, color);
514 hist_browser__gotorc(browser, row, 0);
515 slsmg_write_nstring(" ", offset);
516 slsmg_printf("%c ", folded_sign);
517 slsmg_write_nstring(str, width);
518}
519
520static void hist_browser__fprintf_callchain_entry(struct hist_browser *b __maybe_unused,
521 struct callchain_list *chain,
522 const char *str, int offset,
523 unsigned short row __maybe_unused,
524 struct callchain_print_arg *arg)
525{
526 char folded_sign = callchain_list__folded(chain);
527
528 arg->printed += fprintf(arg->fp, "%*s%c %s\n", offset, " ",
529 folded_sign, str);
530}
531
532typedef bool (*check_output_full_fn)(struct hist_browser *browser,
533 unsigned short row);
534
535static bool hist_browser__check_output_full(struct hist_browser *browser,
536 unsigned short row)
537{
538 return browser->b.rows == row;
539}
540
541static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_unused,
542 unsigned short row __maybe_unused)
543{
544 return false;
545}
546
477#define LEVEL_OFFSET_STEP 3 547#define LEVEL_OFFSET_STEP 3
478 548
479static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browser, 549static int hist_browser__show_callchain(struct hist_browser *browser,
480 struct callchain_node *chain_node, 550 struct rb_root *root, int level,
481 u64 total, int level, 551 unsigned short row, u64 total,
482 unsigned short row, 552 print_callchain_entry_fn print,
483 off_t *row_offset, 553 struct callchain_print_arg *arg,
484 bool *is_current_entry) 554 check_output_full_fn is_output_full)
485{ 555{
486 struct rb_node *node; 556 struct rb_node *node;
487 int first_row = row, width, offset = level * LEVEL_OFFSET_STEP; 557 int first_row = row, offset = level * LEVEL_OFFSET_STEP;
488 u64 new_total, remaining; 558 u64 new_total;
489 559
490 if (callchain_param.mode == CHAIN_GRAPH_REL) 560 node = rb_first(root);
491 new_total = chain_node->children_hit;
492 else
493 new_total = total;
494
495 remaining = new_total;
496 node = rb_first(&chain_node->rb_root);
497 while (node) { 561 while (node) {
498 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); 562 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
499 struct rb_node *next = rb_next(node); 563 struct rb_node *next = rb_next(node);
@@ -503,30 +567,28 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse
503 int first = true; 567 int first = true;
504 int extra_offset = 0; 568 int extra_offset = 0;
505 569
506 remaining -= cumul;
507
508 list_for_each_entry(chain, &child->val, list) { 570 list_for_each_entry(chain, &child->val, list) {
509 char bf[1024], *alloc_str; 571 char bf[1024], *alloc_str;
510 const char *str; 572 const char *str;
511 int color;
512 bool was_first = first; 573 bool was_first = first;
513 574
514 if (first) 575 if (first)
515 first = false; 576 first = false;
516 else 577 else if (level > 1)
517 extra_offset = LEVEL_OFFSET_STEP; 578 extra_offset = LEVEL_OFFSET_STEP;
518 579
519 folded_sign = callchain_list__folded(chain); 580 folded_sign = callchain_list__folded(chain);
520 if (*row_offset != 0) { 581 if (arg->row_offset != 0) {
521 --*row_offset; 582 arg->row_offset--;
522 goto do_next; 583 goto do_next;
523 } 584 }
524 585
525 alloc_str = NULL; 586 alloc_str = NULL;
526 str = callchain_list__sym_name(chain, bf, sizeof(bf), 587 str = callchain_list__sym_name(chain, bf, sizeof(bf),
527 browser->show_dso); 588 browser->show_dso);
528 if (was_first) { 589
529 double percent = cumul * 100.0 / new_total; 590 if (was_first && level > 1) {
591 double percent = cumul * 100.0 / total;
530 592
531 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) 593 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
532 str = "Not enough memory!"; 594 str = "Not enough memory!";
@@ -534,22 +596,11 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse
534 str = alloc_str; 596 str = alloc_str;
535 } 597 }
536 598
537 color = HE_COLORSET_NORMAL; 599 print(browser, chain, str, offset + extra_offset, row, arg);
538 width = browser->b.width - (offset + extra_offset + 2);
539 if (ui_browser__is_current_entry(&browser->b, row)) {
540 browser->selection = &chain->ms;
541 color = HE_COLORSET_SELECTED;
542 *is_current_entry = true;
543 }
544 600
545 ui_browser__set_color(&browser->b, color);
546 hist_browser__gotorc(browser, row, 0);
547 slsmg_write_nstring(" ", offset + extra_offset);
548 slsmg_printf("%c ", folded_sign);
549 slsmg_write_nstring(str, width);
550 free(alloc_str); 601 free(alloc_str);
551 602
552 if (++row == browser->b.rows) 603 if (is_output_full(browser, ++row))
553 goto out; 604 goto out;
554do_next: 605do_next:
555 if (folded_sign == '+') 606 if (folded_sign == '+')
@@ -558,89 +609,21 @@ do_next:
558 609
559 if (folded_sign == '-') { 610 if (folded_sign == '-') {
560 const int new_level = level + (extra_offset ? 2 : 1); 611 const int new_level = level + (extra_offset ? 2 : 1);
561 row += hist_browser__show_callchain_node_rb_tree(browser, child, new_total,
562 new_level, row, row_offset,
563 is_current_entry);
564 }
565 if (row == browser->b.rows)
566 goto out;
567 node = next;
568 }
569out:
570 return row - first_row;
571}
572
573static int hist_browser__show_callchain_node(struct hist_browser *browser,
574 struct callchain_node *node,
575 int level, unsigned short row,
576 off_t *row_offset,
577 bool *is_current_entry)
578{
579 struct callchain_list *chain;
580 int first_row = row,
581 offset = level * LEVEL_OFFSET_STEP,
582 width = browser->b.width - offset;
583 char folded_sign = ' ';
584 612
585 list_for_each_entry(chain, &node->val, list) { 613 if (callchain_param.mode == CHAIN_GRAPH_REL)
586 char bf[1024], *s; 614 new_total = child->children_hit;
587 int color; 615 else
588 616 new_total = total;
589 folded_sign = callchain_list__folded(chain);
590
591 if (*row_offset != 0) {
592 --*row_offset;
593 continue;
594 }
595 617
596 color = HE_COLORSET_NORMAL; 618 row += hist_browser__show_callchain(browser, &child->rb_root,
597 if (ui_browser__is_current_entry(&browser->b, row)) { 619 new_level, row, new_total,
598 browser->selection = &chain->ms; 620 print, arg, is_output_full);
599 color = HE_COLORSET_SELECTED;
600 *is_current_entry = true;
601 } 621 }
602 622 if (is_output_full(browser, row))
603 s = callchain_list__sym_name(chain, bf, sizeof(bf),
604 browser->show_dso);
605 hist_browser__gotorc(browser, row, 0);
606 ui_browser__set_color(&browser->b, color);
607 slsmg_write_nstring(" ", offset);
608 slsmg_printf("%c ", folded_sign);
609 slsmg_write_nstring(s, width - 2);
610
611 if (++row == browser->b.rows)
612 goto out;
613 }
614
615 if (folded_sign == '-')
616 row += hist_browser__show_callchain_node_rb_tree(browser, node,
617 browser->hists->stats.total_period,
618 level + 1, row,
619 row_offset,
620 is_current_entry);
621out:
622 return row - first_row;
623}
624
625static int hist_browser__show_callchain(struct hist_browser *browser,
626 struct rb_root *chain,
627 int level, unsigned short row,
628 off_t *row_offset,
629 bool *is_current_entry)
630{
631 struct rb_node *nd;
632 int first_row = row;
633
634 for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
635 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
636
637 row += hist_browser__show_callchain_node(browser, node, level,
638 row, row_offset,
639 is_current_entry);
640 if (row == browser->b.rows)
641 break; 623 break;
624 node = next;
642 } 625 }
643 626out:
644 return row - first_row; 627 return row - first_row;
645} 628}
646 629
@@ -653,17 +636,18 @@ struct hpp_arg {
653static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...) 636static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
654{ 637{
655 struct hpp_arg *arg = hpp->ptr; 638 struct hpp_arg *arg = hpp->ptr;
656 int ret; 639 int ret, len;
657 va_list args; 640 va_list args;
658 double percent; 641 double percent;
659 642
660 va_start(args, fmt); 643 va_start(args, fmt);
644 len = va_arg(args, int);
661 percent = va_arg(args, double); 645 percent = va_arg(args, double);
662 va_end(args); 646 va_end(args);
663 647
664 ui_browser__set_percent_color(arg->b, percent, arg->current_entry); 648 ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
665 649
666 ret = scnprintf(hpp->buf, hpp->size, fmt, percent); 650 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent);
667 slsmg_printf("%s", hpp->buf); 651 slsmg_printf("%s", hpp->buf);
668 652
669 advance_hpp(hpp, ret); 653 advance_hpp(hpp, ret);
@@ -677,12 +661,12 @@ static u64 __hpp_get_##_field(struct hist_entry *he) \
677} \ 661} \
678 \ 662 \
679static int \ 663static int \
680hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\ 664hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
681 struct perf_hpp *hpp, \ 665 struct perf_hpp *hpp, \
682 struct hist_entry *he) \ 666 struct hist_entry *he) \
683{ \ 667{ \
684 return __hpp__fmt(hpp, he, __hpp_get_##_field, " %6.2f%%", \ 668 return hpp__fmt(fmt, hpp, he, __hpp_get_##_field, " %*.2f%%", \
685 __hpp__slsmg_color_printf, true); \ 669 __hpp__slsmg_color_printf, true); \
686} 670}
687 671
688#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 672#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
@@ -692,18 +676,20 @@ static u64 __hpp_get_acc_##_field(struct hist_entry *he) \
692} \ 676} \
693 \ 677 \
694static int \ 678static int \
695hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\ 679hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
696 struct perf_hpp *hpp, \ 680 struct perf_hpp *hpp, \
697 struct hist_entry *he) \ 681 struct hist_entry *he) \
698{ \ 682{ \
699 if (!symbol_conf.cumulate_callchain) { \ 683 if (!symbol_conf.cumulate_callchain) { \
700 int ret = scnprintf(hpp->buf, hpp->size, "%8s", "N/A"); \ 684 int len = fmt->user_len ?: fmt->len; \
685 int ret = scnprintf(hpp->buf, hpp->size, \
686 "%*s", len, "N/A"); \
701 slsmg_printf("%s", hpp->buf); \ 687 slsmg_printf("%s", hpp->buf); \
702 \ 688 \
703 return ret; \ 689 return ret; \
704 } \ 690 } \
705 return __hpp__fmt(hpp, he, __hpp_get_acc_##_field, " %6.2f%%", \ 691 return hpp__fmt(fmt, hpp, he, __hpp_get_acc_##_field, \
706 __hpp__slsmg_color_printf, true); \ 692 " %*.2f%%", __hpp__slsmg_color_printf, true); \
707} 693}
708 694
709__HPP_COLOR_PERCENT_FN(overhead, period) 695__HPP_COLOR_PERCENT_FN(overhead, period)
@@ -812,10 +798,18 @@ static int hist_browser__show_entry(struct hist_browser *browser,
812 --row_offset; 798 --row_offset;
813 799
814 if (folded_sign == '-' && row != browser->b.rows) { 800 if (folded_sign == '-' && row != browser->b.rows) {
815 printed += hist_browser__show_callchain(browser, &entry->sorted_chain, 801 u64 total = hists__total_period(entry->hists);
816 1, row, &row_offset, 802 struct callchain_print_arg arg = {
817 &current_entry); 803 .row_offset = row_offset,
818 if (current_entry) 804 .is_current_entry = current_entry,
805 };
806
807 printed += hist_browser__show_callchain(browser,
808 &entry->sorted_chain, 1, row, total,
809 hist_browser__show_callchain_entry, &arg,
810 hist_browser__check_output_full);
811
812 if (arg.is_current_entry)
819 browser->he_selection = entry; 813 browser->he_selection = entry;
820 } 814 }
821 815
@@ -847,9 +841,6 @@ static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists)
847 if (perf_hpp__should_skip(fmt)) 841 if (perf_hpp__should_skip(fmt))
848 continue; 842 continue;
849 843
850 /* We need to add the length of the columns header. */
851 perf_hpp__reset_width(fmt, hists);
852
853 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 844 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
854 if (advance_hpp_check(&dummy_hpp, ret)) 845 if (advance_hpp_check(&dummy_hpp, ret))
855 break; 846 break;
@@ -1074,113 +1065,21 @@ do_offset:
1074 } 1065 }
1075} 1066}
1076 1067
1077static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *browser,
1078 struct callchain_node *chain_node,
1079 u64 total, int level,
1080 FILE *fp)
1081{
1082 struct rb_node *node;
1083 int offset = level * LEVEL_OFFSET_STEP;
1084 u64 new_total, remaining;
1085 int printed = 0;
1086
1087 if (callchain_param.mode == CHAIN_GRAPH_REL)
1088 new_total = chain_node->children_hit;
1089 else
1090 new_total = total;
1091
1092 remaining = new_total;
1093 node = rb_first(&chain_node->rb_root);
1094 while (node) {
1095 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
1096 struct rb_node *next = rb_next(node);
1097 u64 cumul = callchain_cumul_hits(child);
1098 struct callchain_list *chain;
1099 char folded_sign = ' ';
1100 int first = true;
1101 int extra_offset = 0;
1102
1103 remaining -= cumul;
1104
1105 list_for_each_entry(chain, &child->val, list) {
1106 char bf[1024], *alloc_str;
1107 const char *str;
1108 bool was_first = first;
1109
1110 if (first)
1111 first = false;
1112 else
1113 extra_offset = LEVEL_OFFSET_STEP;
1114
1115 folded_sign = callchain_list__folded(chain);
1116
1117 alloc_str = NULL;
1118 str = callchain_list__sym_name(chain, bf, sizeof(bf),
1119 browser->show_dso);
1120 if (was_first) {
1121 double percent = cumul * 100.0 / new_total;
1122
1123 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
1124 str = "Not enough memory!";
1125 else
1126 str = alloc_str;
1127 }
1128
1129 printed += fprintf(fp, "%*s%c %s\n", offset + extra_offset, " ", folded_sign, str);
1130 free(alloc_str);
1131 if (folded_sign == '+')
1132 break;
1133 }
1134
1135 if (folded_sign == '-') {
1136 const int new_level = level + (extra_offset ? 2 : 1);
1137 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, child, new_total,
1138 new_level, fp);
1139 }
1140
1141 node = next;
1142 }
1143
1144 return printed;
1145}
1146
1147static int hist_browser__fprintf_callchain_node(struct hist_browser *browser,
1148 struct callchain_node *node,
1149 int level, FILE *fp)
1150{
1151 struct callchain_list *chain;
1152 int offset = level * LEVEL_OFFSET_STEP;
1153 char folded_sign = ' ';
1154 int printed = 0;
1155
1156 list_for_each_entry(chain, &node->val, list) {
1157 char bf[1024], *s;
1158
1159 folded_sign = callchain_list__folded(chain);
1160 s = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso);
1161 printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s);
1162 }
1163
1164 if (folded_sign == '-')
1165 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, node,
1166 browser->hists->stats.total_period,
1167 level + 1, fp);
1168 return printed;
1169}
1170
1171static int hist_browser__fprintf_callchain(struct hist_browser *browser, 1068static int hist_browser__fprintf_callchain(struct hist_browser *browser,
1172 struct rb_root *chain, int level, FILE *fp) 1069 struct hist_entry *he, FILE *fp)
1173{ 1070{
1174 struct rb_node *nd; 1071 u64 total = hists__total_period(he->hists);
1175 int printed = 0; 1072 struct callchain_print_arg arg = {
1073 .fp = fp,
1074 };
1176 1075
1177 for (nd = rb_first(chain); nd; nd = rb_next(nd)) { 1076 if (symbol_conf.cumulate_callchain)
1178 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); 1077 total = he->stat_acc->period;
1179 1078
1180 printed += hist_browser__fprintf_callchain_node(browser, node, level, fp); 1079 hist_browser__show_callchain(browser, &he->sorted_chain, 1, 0, total,
1181 } 1080 hist_browser__fprintf_callchain_entry, &arg,
1182 1081 hist_browser__check_dump_full);
1183 return printed; 1082 return arg.printed;
1184} 1083}
1185 1084
1186static int hist_browser__fprintf_entry(struct hist_browser *browser, 1085static int hist_browser__fprintf_entry(struct hist_browser *browser,
@@ -1219,7 +1118,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1219 printed += fprintf(fp, "%s\n", rtrim(s)); 1118 printed += fprintf(fp, "%s\n", rtrim(s));
1220 1119
1221 if (folded_sign == '-') 1120 if (folded_sign == '-')
1222 printed += hist_browser__fprintf_callchain(browser, &he->sorted_chain, 1, fp); 1121 printed += hist_browser__fprintf_callchain(browser, he, fp);
1223 1122
1224 return printed; 1123 return printed;
1225} 1124}
@@ -1498,6 +1397,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1498 char buf[64]; 1397 char buf[64];
1499 char script_opt[64]; 1398 char script_opt[64];
1500 int delay_secs = hbt ? hbt->refresh : 0; 1399 int delay_secs = hbt ? hbt->refresh : 0;
1400 struct perf_hpp_fmt *fmt;
1501 1401
1502#define HIST_BROWSER_HELP_COMMON \ 1402#define HIST_BROWSER_HELP_COMMON \
1503 "h/?/F1 Show this window\n" \ 1403 "h/?/F1 Show this window\n" \
@@ -1529,6 +1429,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1529 "P Print histograms to perf.hist.N\n" 1429 "P Print histograms to perf.hist.N\n"
1530 "t Zoom into current Thread\n" 1430 "t Zoom into current Thread\n"
1531 "V Verbose (DSO names in callchains, etc)\n" 1431 "V Verbose (DSO names in callchains, etc)\n"
1432 "z Toggle zeroing of samples\n"
1532 "/ Filter symbol by name"; 1433 "/ Filter symbol by name";
1533 1434
1534 if (browser == NULL) 1435 if (browser == NULL)
@@ -1547,6 +1448,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1547 1448
1548 memset(options, 0, sizeof(options)); 1449 memset(options, 0, sizeof(options));
1549 1450
1451 perf_hpp__for_each_format(fmt)
1452 perf_hpp__reset_width(fmt, hists);
1453
1454 if (symbol_conf.col_width_list_str)
1455 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
1456
1550 while (1) { 1457 while (1) {
1551 const struct thread *thread = NULL; 1458 const struct thread *thread = NULL;
1552 const struct dso *dso = NULL; 1459 const struct dso *dso = NULL;
@@ -1623,6 +1530,13 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1623 case 'F': 1530 case 'F':
1624 symbol_conf.filter_relative ^= 1; 1531 symbol_conf.filter_relative ^= 1;
1625 continue; 1532 continue;
1533 case 'z':
1534 if (!is_report_browser(hbt)) {
1535 struct perf_top *top = hbt->arg;
1536
1537 top->zero = !top->zero;
1538 }
1539 continue;
1626 case K_F1: 1540 case K_F1:
1627 case 'h': 1541 case 'h':
1628 case '?': 1542 case '?':
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 6ca60e482cdc..f3fa4258b256 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -11,6 +11,7 @@
11static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...) 11static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
12{ 12{
13 int ret = 0; 13 int ret = 0;
14 int len;
14 va_list args; 15 va_list args;
15 double percent; 16 double percent;
16 const char *markup; 17 const char *markup;
@@ -18,6 +19,7 @@ static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
18 size_t size = hpp->size; 19 size_t size = hpp->size;
19 20
20 va_start(args, fmt); 21 va_start(args, fmt);
22 len = va_arg(args, int);
21 percent = va_arg(args, double); 23 percent = va_arg(args, double);
22 va_end(args); 24 va_end(args);
23 25
@@ -25,7 +27,7 @@ static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
25 if (markup) 27 if (markup)
26 ret += scnprintf(buf, size, markup); 28 ret += scnprintf(buf, size, markup);
27 29
28 ret += scnprintf(buf + ret, size - ret, fmt, percent); 30 ret += scnprintf(buf + ret, size - ret, fmt, len, percent);
29 31
30 if (markup) 32 if (markup)
31 ret += scnprintf(buf + ret, size - ret, "</span>"); 33 ret += scnprintf(buf + ret, size - ret, "</span>");
@@ -39,12 +41,12 @@ static u64 he_get_##_field(struct hist_entry *he) \
39 return he->stat._field; \ 41 return he->stat._field; \
40} \ 42} \
41 \ 43 \
42static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 44static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
43 struct perf_hpp *hpp, \ 45 struct perf_hpp *hpp, \
44 struct hist_entry *he) \ 46 struct hist_entry *he) \
45{ \ 47{ \
46 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 48 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
47 __percent_color_snprintf, true); \ 49 __percent_color_snprintf, true); \
48} 50}
49 51
50#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 52#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
@@ -57,8 +59,8 @@ static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,
57 struct perf_hpp *hpp, \ 59 struct perf_hpp *hpp, \
58 struct hist_entry *he) \ 60 struct hist_entry *he) \
59{ \ 61{ \
60 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, " %6.2f%%", \ 62 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
61 __percent_color_snprintf, true); \ 63 __percent_color_snprintf, true); \
62} 64}
63 65
64__HPP_COLOR_PERCENT_FN(overhead, period) 66__HPP_COLOR_PERCENT_FN(overhead, period)
@@ -205,10 +207,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
205 if (perf_hpp__is_sort_entry(fmt)) 207 if (perf_hpp__is_sort_entry(fmt))
206 sym_col = col_idx; 208 sym_col = col_idx;
207 209
208 fmt->header(fmt, &hpp, hists_to_evsel(hists));
209
210 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), 210 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
211 -1, ltrim(s), 211 -1, fmt->name,
212 renderer, "markup", 212 renderer, "markup",
213 col_idx++, NULL); 213 col_idx++, NULL);
214 } 214 }
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 498adb23c02e..2af18376b077 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -15,9 +15,9 @@
15 __ret; \ 15 __ret; \
16}) 16})
17 17
18int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 18static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
19 hpp_field_fn get_field, const char *fmt, 19 hpp_field_fn get_field, const char *fmt, int len,
20 hpp_snprint_fn print_fn, bool fmt_percent) 20 hpp_snprint_fn print_fn, bool fmt_percent)
21{ 21{
22 int ret; 22 int ret;
23 struct hists *hists = he->hists; 23 struct hists *hists = he->hists;
@@ -32,9 +32,9 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
32 if (total) 32 if (total)
33 percent = 100.0 * get_field(he) / total; 33 percent = 100.0 * get_field(he) / total;
34 34
35 ret = hpp__call_print_fn(hpp, print_fn, fmt, percent); 35 ret = hpp__call_print_fn(hpp, print_fn, fmt, len, percent);
36 } else 36 } else
37 ret = hpp__call_print_fn(hpp, print_fn, fmt, get_field(he)); 37 ret = hpp__call_print_fn(hpp, print_fn, fmt, len, get_field(he));
38 38
39 if (perf_evsel__is_group_event(evsel)) { 39 if (perf_evsel__is_group_event(evsel)) {
40 int prev_idx, idx_delta; 40 int prev_idx, idx_delta;
@@ -60,19 +60,19 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
60 */ 60 */
61 if (fmt_percent) { 61 if (fmt_percent) {
62 ret += hpp__call_print_fn(hpp, print_fn, 62 ret += hpp__call_print_fn(hpp, print_fn,
63 fmt, 0.0); 63 fmt, len, 0.0);
64 } else { 64 } else {
65 ret += hpp__call_print_fn(hpp, print_fn, 65 ret += hpp__call_print_fn(hpp, print_fn,
66 fmt, 0ULL); 66 fmt, len, 0ULL);
67 } 67 }
68 } 68 }
69 69
70 if (fmt_percent) { 70 if (fmt_percent) {
71 ret += hpp__call_print_fn(hpp, print_fn, fmt, 71 ret += hpp__call_print_fn(hpp, print_fn, fmt, len,
72 100.0 * period / total); 72 100.0 * period / total);
73 } else { 73 } else {
74 ret += hpp__call_print_fn(hpp, print_fn, fmt, 74 ret += hpp__call_print_fn(hpp, print_fn, fmt,
75 period); 75 len, period);
76 } 76 }
77 77
78 prev_idx = perf_evsel__group_idx(evsel); 78 prev_idx = perf_evsel__group_idx(evsel);
@@ -86,10 +86,10 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
86 */ 86 */
87 if (fmt_percent) { 87 if (fmt_percent) {
88 ret += hpp__call_print_fn(hpp, print_fn, 88 ret += hpp__call_print_fn(hpp, print_fn,
89 fmt, 0.0); 89 fmt, len, 0.0);
90 } else { 90 } else {
91 ret += hpp__call_print_fn(hpp, print_fn, 91 ret += hpp__call_print_fn(hpp, print_fn,
92 fmt, 0ULL); 92 fmt, len, 0ULL);
93 } 93 }
94 } 94 }
95 } 95 }
@@ -104,16 +104,35 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
104 return ret; 104 return ret;
105} 105}
106 106
107int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, 107int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
108 hpp_field_fn get_field, const char *fmt, 108 struct hist_entry *he, hpp_field_fn get_field,
109 hpp_snprint_fn print_fn, bool fmt_percent) 109 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
110{
111 int len = fmt->user_len ?: fmt->len;
112
113 if (symbol_conf.field_sep) {
114 return __hpp__fmt(hpp, he, get_field, fmtstr, 1,
115 print_fn, fmt_percent);
116 }
117
118 if (fmt_percent)
119 len -= 2; /* 2 for a space and a % sign */
120 else
121 len -= 1;
122
123 return __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent);
124}
125
126int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
127 struct hist_entry *he, hpp_field_fn get_field,
128 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
110{ 129{
111 if (!symbol_conf.cumulate_callchain) { 130 if (!symbol_conf.cumulate_callchain) {
112 return snprintf(hpp->buf, hpp->size, "%*s", 131 int len = fmt->user_len ?: fmt->len;
113 fmt_percent ? 8 : 12, "N/A"); 132 return snprintf(hpp->buf, hpp->size, " %*s", len - 1, "N/A");
114 } 133 }
115 134
116 return __hpp__fmt(hpp, he, get_field, fmt, print_fn, fmt_percent); 135 return hpp__fmt(fmt, hpp, he, get_field, fmtstr, print_fn, fmt_percent);
117} 136}
118 137
119static int field_cmp(u64 field_a, u64 field_b) 138static int field_cmp(u64 field_a, u64 field_b)
@@ -190,30 +209,26 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
190 return ret; 209 return ret;
191} 210}
192 211
193#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ 212static int hpp__width_fn(struct perf_hpp_fmt *fmt,
194static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 213 struct perf_hpp *hpp __maybe_unused,
195 struct perf_hpp *hpp, \ 214 struct perf_evsel *evsel)
196 struct perf_evsel *evsel) \ 215{
197{ \ 216 int len = fmt->user_len ?: fmt->len;
198 int len = _min_width; \ 217
199 \ 218 if (symbol_conf.event_group)
200 if (symbol_conf.event_group) \ 219 len = max(len, evsel->nr_members * fmt->len);
201 len = max(len, evsel->nr_members * _unit_width); \ 220
202 \ 221 if (len < (int)strlen(fmt->name))
203 return scnprintf(hpp->buf, hpp->size, "%*s", len, _str); \ 222 len = strlen(fmt->name);
204} 223
205 224 return len;
206#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \ 225}
207static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 226
208 struct perf_hpp *hpp __maybe_unused, \ 227static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
209 struct perf_evsel *evsel) \ 228 struct perf_evsel *evsel)
210{ \ 229{
211 int len = _min_width; \ 230 int len = hpp__width_fn(fmt, hpp, evsel);
212 \ 231 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
213 if (symbol_conf.event_group) \
214 len = max(len, evsel->nr_members * _unit_width); \
215 \
216 return len; \
217} 232}
218 233
219static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) 234static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
@@ -221,11 +236,12 @@ static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
221 va_list args; 236 va_list args;
222 ssize_t ssize = hpp->size; 237 ssize_t ssize = hpp->size;
223 double percent; 238 double percent;
224 int ret; 239 int ret, len;
225 240
226 va_start(args, fmt); 241 va_start(args, fmt);
242 len = va_arg(args, int);
227 percent = va_arg(args, double); 243 percent = va_arg(args, double);
228 ret = value_color_snprintf(hpp->buf, hpp->size, fmt, percent); 244 ret = percent_color_len_snprintf(hpp->buf, hpp->size, fmt, len, percent);
229 va_end(args); 245 va_end(args);
230 246
231 return (ret >= ssize) ? (ssize - 1) : ret; 247 return (ret >= ssize) ? (ssize - 1) : ret;
@@ -250,20 +266,19 @@ static u64 he_get_##_field(struct hist_entry *he) \
250 return he->stat._field; \ 266 return he->stat._field; \
251} \ 267} \
252 \ 268 \
253static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 269static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
254 struct perf_hpp *hpp, struct hist_entry *he) \ 270 struct perf_hpp *hpp, struct hist_entry *he) \
255{ \ 271{ \
256 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 272 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
257 hpp_color_scnprintf, true); \ 273 hpp_color_scnprintf, true); \
258} 274}
259 275
260#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 276#define __HPP_ENTRY_PERCENT_FN(_type, _field) \
261static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 277static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
262 struct perf_hpp *hpp, struct hist_entry *he) \ 278 struct perf_hpp *hpp, struct hist_entry *he) \
263{ \ 279{ \
264 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 280 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
265 return __hpp__fmt(hpp, he, he_get_##_field, fmt, \ 281 hpp_entry_scnprintf, true); \
266 hpp_entry_scnprintf, true); \
267} 282}
268 283
269#define __HPP_SORT_FN(_type, _field) \ 284#define __HPP_SORT_FN(_type, _field) \
@@ -278,20 +293,19 @@ static u64 he_get_acc_##_field(struct hist_entry *he) \
278 return he->stat_acc->_field; \ 293 return he->stat_acc->_field; \
279} \ 294} \
280 \ 295 \
281static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 296static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
282 struct perf_hpp *hpp, struct hist_entry *he) \ 297 struct perf_hpp *hpp, struct hist_entry *he) \
283{ \ 298{ \
284 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, " %6.2f%%", \ 299 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
285 hpp_color_scnprintf, true); \ 300 hpp_color_scnprintf, true); \
286} 301}
287 302
288#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 303#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
289static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 304static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
290 struct perf_hpp *hpp, struct hist_entry *he) \ 305 struct perf_hpp *hpp, struct hist_entry *he) \
291{ \ 306{ \
292 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 307 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
293 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, fmt, \ 308 hpp_entry_scnprintf, true); \
294 hpp_entry_scnprintf, true); \
295} 309}
296 310
297#define __HPP_SORT_ACC_FN(_type, _field) \ 311#define __HPP_SORT_ACC_FN(_type, _field) \
@@ -306,12 +320,11 @@ static u64 he_get_raw_##_field(struct hist_entry *he) \
306 return he->stat._field; \ 320 return he->stat._field; \
307} \ 321} \
308 \ 322 \
309static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 323static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
310 struct perf_hpp *hpp, struct hist_entry *he) \ 324 struct perf_hpp *hpp, struct hist_entry *he) \
311{ \ 325{ \
312 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \ 326 return hpp__fmt(fmt, hpp, he, he_get_raw_##_field, " %*"PRIu64, \
313 return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, \ 327 hpp_entry_scnprintf, false); \
314 hpp_entry_scnprintf, false); \
315} 328}
316 329
317#define __HPP_SORT_RAW_FN(_type, _field) \ 330#define __HPP_SORT_RAW_FN(_type, _field) \
@@ -321,37 +334,29 @@ static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \
321} 334}
322 335
323 336
324#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width) \ 337#define HPP_PERCENT_FNS(_type, _field) \
325__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
326__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
327__HPP_COLOR_PERCENT_FN(_type, _field) \ 338__HPP_COLOR_PERCENT_FN(_type, _field) \
328__HPP_ENTRY_PERCENT_FN(_type, _field) \ 339__HPP_ENTRY_PERCENT_FN(_type, _field) \
329__HPP_SORT_FN(_type, _field) 340__HPP_SORT_FN(_type, _field)
330 341
331#define HPP_PERCENT_ACC_FNS(_type, _str, _field, _min_width, _unit_width)\ 342#define HPP_PERCENT_ACC_FNS(_type, _field) \
332__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
333__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
334__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 343__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
335__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 344__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
336__HPP_SORT_ACC_FN(_type, _field) 345__HPP_SORT_ACC_FN(_type, _field)
337 346
338#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width) \ 347#define HPP_RAW_FNS(_type, _field) \
339__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
340__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
341__HPP_ENTRY_RAW_FN(_type, _field) \ 348__HPP_ENTRY_RAW_FN(_type, _field) \
342__HPP_SORT_RAW_FN(_type, _field) 349__HPP_SORT_RAW_FN(_type, _field)
343 350
344__HPP_HEADER_FN(overhead_self, "Self", 8, 8) 351HPP_PERCENT_FNS(overhead, period)
345 352HPP_PERCENT_FNS(overhead_sys, period_sys)
346HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8) 353HPP_PERCENT_FNS(overhead_us, period_us)
347HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8) 354HPP_PERCENT_FNS(overhead_guest_sys, period_guest_sys)
348HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8) 355HPP_PERCENT_FNS(overhead_guest_us, period_guest_us)
349HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8) 356HPP_PERCENT_ACC_FNS(overhead_acc, period)
350HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
351HPP_PERCENT_ACC_FNS(overhead_acc, "Children", period, 8, 8)
352 357
353HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12) 358HPP_RAW_FNS(samples, nr_events)
354HPP_RAW_FNS(period, "Period", period, 12, 12) 359HPP_RAW_FNS(period, period)
355 360
356static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused, 361static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused,
357 struct hist_entry *b __maybe_unused) 362 struct hist_entry *b __maybe_unused)
@@ -359,47 +364,50 @@ static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused,
359 return 0; 364 return 0;
360} 365}
361 366
362#define HPP__COLOR_PRINT_FNS(_name) \ 367#define HPP__COLOR_PRINT_FNS(_name, _fn) \
363 { \ 368 { \
364 .header = hpp__header_ ## _name, \ 369 .name = _name, \
365 .width = hpp__width_ ## _name, \ 370 .header = hpp__header_fn, \
366 .color = hpp__color_ ## _name, \ 371 .width = hpp__width_fn, \
367 .entry = hpp__entry_ ## _name, \ 372 .color = hpp__color_ ## _fn, \
373 .entry = hpp__entry_ ## _fn, \
368 .cmp = hpp__nop_cmp, \ 374 .cmp = hpp__nop_cmp, \
369 .collapse = hpp__nop_cmp, \ 375 .collapse = hpp__nop_cmp, \
370 .sort = hpp__sort_ ## _name, \ 376 .sort = hpp__sort_ ## _fn, \
371 } 377 }
372 378
373#define HPP__COLOR_ACC_PRINT_FNS(_name) \ 379#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn) \
374 { \ 380 { \
375 .header = hpp__header_ ## _name, \ 381 .name = _name, \
376 .width = hpp__width_ ## _name, \ 382 .header = hpp__header_fn, \
377 .color = hpp__color_ ## _name, \ 383 .width = hpp__width_fn, \
378 .entry = hpp__entry_ ## _name, \ 384 .color = hpp__color_ ## _fn, \
385 .entry = hpp__entry_ ## _fn, \
379 .cmp = hpp__nop_cmp, \ 386 .cmp = hpp__nop_cmp, \
380 .collapse = hpp__nop_cmp, \ 387 .collapse = hpp__nop_cmp, \
381 .sort = hpp__sort_ ## _name, \ 388 .sort = hpp__sort_ ## _fn, \
382 } 389 }
383 390
384#define HPP__PRINT_FNS(_name) \ 391#define HPP__PRINT_FNS(_name, _fn) \
385 { \ 392 { \
386 .header = hpp__header_ ## _name, \ 393 .name = _name, \
387 .width = hpp__width_ ## _name, \ 394 .header = hpp__header_fn, \
388 .entry = hpp__entry_ ## _name, \ 395 .width = hpp__width_fn, \
396 .entry = hpp__entry_ ## _fn, \
389 .cmp = hpp__nop_cmp, \ 397 .cmp = hpp__nop_cmp, \
390 .collapse = hpp__nop_cmp, \ 398 .collapse = hpp__nop_cmp, \
391 .sort = hpp__sort_ ## _name, \ 399 .sort = hpp__sort_ ## _fn, \
392 } 400 }
393 401
394struct perf_hpp_fmt perf_hpp__format[] = { 402struct perf_hpp_fmt perf_hpp__format[] = {
395 HPP__COLOR_PRINT_FNS(overhead), 403 HPP__COLOR_PRINT_FNS("Overhead", overhead),
396 HPP__COLOR_PRINT_FNS(overhead_sys), 404 HPP__COLOR_PRINT_FNS("sys", overhead_sys),
397 HPP__COLOR_PRINT_FNS(overhead_us), 405 HPP__COLOR_PRINT_FNS("usr", overhead_us),
398 HPP__COLOR_PRINT_FNS(overhead_guest_sys), 406 HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys),
399 HPP__COLOR_PRINT_FNS(overhead_guest_us), 407 HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us),
400 HPP__COLOR_ACC_PRINT_FNS(overhead_acc), 408 HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc),
401 HPP__PRINT_FNS(samples), 409 HPP__PRINT_FNS("Samples", samples),
402 HPP__PRINT_FNS(period) 410 HPP__PRINT_FNS("Period", period)
403}; 411};
404 412
405LIST_HEAD(perf_hpp__list); 413LIST_HEAD(perf_hpp__list);
@@ -444,14 +452,12 @@ void perf_hpp__init(void)
444 /* 452 /*
445 * If user specified field order, no need to setup default fields. 453 * If user specified field order, no need to setup default fields.
446 */ 454 */
447 if (field_order) 455 if (is_strict_order(field_order))
448 return; 456 return;
449 457
450 if (symbol_conf.cumulate_callchain) { 458 if (symbol_conf.cumulate_callchain) {
451 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC); 459 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC);
452 460 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self";
453 perf_hpp__format[PERF_HPP__OVERHEAD].header =
454 hpp__header_overhead_self;
455 } 461 }
456 462
457 perf_hpp__column_enable(PERF_HPP__OVERHEAD); 463 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
@@ -513,11 +519,11 @@ void perf_hpp__column_disable(unsigned col)
513 519
514void perf_hpp__cancel_cumulate(void) 520void perf_hpp__cancel_cumulate(void)
515{ 521{
516 if (field_order) 522 if (is_strict_order(field_order))
517 return; 523 return;
518 524
519 perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC); 525 perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC);
520 perf_hpp__format[PERF_HPP__OVERHEAD].header = hpp__header_overhead; 526 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Overhead";
521} 527}
522 528
523void perf_hpp__setup_output_field(void) 529void perf_hpp__setup_output_field(void)
@@ -622,3 +628,59 @@ unsigned int hists__sort_list_width(struct hists *hists)
622 628
623 return ret; 629 return ret;
624} 630}
631
632void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
633{
634 int idx;
635
636 if (perf_hpp__is_sort_entry(fmt))
637 return perf_hpp__reset_sort_width(fmt, hists);
638
639 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
640 if (fmt == &perf_hpp__format[idx])
641 break;
642 }
643
644 if (idx == PERF_HPP__MAX_INDEX)
645 return;
646
647 switch (idx) {
648 case PERF_HPP__OVERHEAD:
649 case PERF_HPP__OVERHEAD_SYS:
650 case PERF_HPP__OVERHEAD_US:
651 case PERF_HPP__OVERHEAD_ACC:
652 fmt->len = 8;
653 break;
654
655 case PERF_HPP__OVERHEAD_GUEST_SYS:
656 case PERF_HPP__OVERHEAD_GUEST_US:
657 fmt->len = 9;
658 break;
659
660 case PERF_HPP__SAMPLES:
661 case PERF_HPP__PERIOD:
662 fmt->len = 12;
663 break;
664
665 default:
666 break;
667 }
668}
669
670void perf_hpp__set_user_width(const char *width_list_str)
671{
672 struct perf_hpp_fmt *fmt;
673 const char *ptr = width_list_str;
674
675 perf_hpp__for_each_format(fmt) {
676 char *p;
677
678 int len = strtol(ptr, &p, 10);
679 fmt->user_len = len;
680
681 if (*p == ',')
682 ptr = p + 1;
683 else
684 break;
685 }
686}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 40af0acb4fe9..15b451acbde6 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -395,10 +395,12 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
395 395
396 init_rem_hits(); 396 init_rem_hits();
397 397
398
399 perf_hpp__for_each_format(fmt) 398 perf_hpp__for_each_format(fmt)
400 perf_hpp__reset_width(fmt, hists); 399 perf_hpp__reset_width(fmt, hists);
401 400
401 if (symbol_conf.col_width_list_str)
402 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
403
402 if (!show_header) 404 if (!show_header)
403 goto print_entries; 405 goto print_entries;
404 406
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 809b4c50beae..36437527dbb3 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -232,9 +232,16 @@ static int mov__parse(struct ins_operands *ops)
232 return -1; 232 return -1;
233 233
234 target = ++s; 234 target = ++s;
235 comment = strchr(s, '#');
235 236
236 while (s[0] != '\0' && !isspace(s[0])) 237 if (comment != NULL)
237 ++s; 238 s = comment - 1;
239 else
240 s = strchr(s, '\0') - 1;
241
242 while (s > target && isspace(s[0]))
243 --s;
244 s++;
238 prev = *s; 245 prev = *s;
239 *s = '\0'; 246 *s = '\0';
240 247
@@ -244,7 +251,6 @@ static int mov__parse(struct ins_operands *ops)
244 if (ops->target.raw == NULL) 251 if (ops->target.raw == NULL)
245 goto out_free_source; 252 goto out_free_source;
246 253
247 comment = strchr(s, '#');
248 if (comment == NULL) 254 if (comment == NULL)
249 return 0; 255 return 0;
250 256
@@ -899,10 +905,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
899 struct kcore_extract kce; 905 struct kcore_extract kce;
900 bool delete_extract = false; 906 bool delete_extract = false;
901 907
902 if (filename) { 908 if (filename)
903 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 909 symbol__join_symfs(symfs_filename, filename);
904 symbol_conf.symfs, filename);
905 }
906 910
907 if (filename == NULL) { 911 if (filename == NULL) {
908 if (dso->has_build_id) { 912 if (dso->has_build_id) {
@@ -922,8 +926,7 @@ fallback:
922 * DSO is the same as when 'perf record' ran. 926 * DSO is the same as when 'perf record' ran.
923 */ 927 */
924 filename = (char *)dso->long_name; 928 filename = (char *)dso->long_name;
925 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 929 symbol__join_symfs(symfs_filename, filename);
926 symbol_conf.symfs, filename);
927 free_filename = false; 930 free_filename = false;
928 } 931 }
929 932
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 7b176dd02e1a..5cf9e1b5989d 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -22,6 +22,7 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *); 22extern int perf_default_config(const char *, const char *, void *);
23extern int perf_config(config_fn_t fn, void *); 23extern int perf_config(config_fn_t fn, void *);
24extern int perf_config_int(const char *, const char *); 24extern int perf_config_int(const char *, const char *);
25extern u64 perf_config_u64(const char *, const char *);
25extern int perf_config_bool(const char *, const char *); 26extern int perf_config_bool(const char *, const char *);
26extern int config_error_nonbool(const char *); 27extern int config_error_nonbool(const char *);
27extern const char *perf_config_dirname(const char *, const char *); 28extern const char *perf_config_dirname(const char *, const char *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 437ee09727e6..c84d3f8dcb75 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -25,77 +25,172 @@
25 25
26__thread struct callchain_cursor callchain_cursor; 26__thread struct callchain_cursor callchain_cursor;
27 27
28int 28#ifdef HAVE_DWARF_UNWIND_SUPPORT
29parse_callchain_report_opt(const char *arg) 29static int get_stack_size(const char *str, unsigned long *_size)
30{ 30{
31 char *tok, *tok2;
32 char *endptr; 31 char *endptr;
32 unsigned long size;
33 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
33 34
34 symbol_conf.use_callchain = true; 35 size = strtoul(str, &endptr, 0);
35 36
36 if (!arg) 37 do {
38 if (*endptr)
39 break;
40
41 size = round_up(size, sizeof(u64));
42 if (!size || size > max_size)
43 break;
44
45 *_size = size;
37 return 0; 46 return 0;
38 47
39 tok = strtok((char *)arg, ","); 48 } while (0);
40 if (!tok)
41 return -1;
42 49
43 /* get the output mode */ 50 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
44 if (!strncmp(tok, "graph", strlen(arg))) { 51 max_size, str);
45 callchain_param.mode = CHAIN_GRAPH_ABS; 52 return -1;
53}
54#endif /* HAVE_DWARF_UNWIND_SUPPORT */
46 55
47 } else if (!strncmp(tok, "flat", strlen(arg))) { 56int parse_callchain_record_opt(const char *arg)
48 callchain_param.mode = CHAIN_FLAT; 57{
49 } else if (!strncmp(tok, "fractal", strlen(arg))) { 58 char *tok, *name, *saveptr = NULL;
50 callchain_param.mode = CHAIN_GRAPH_REL; 59 char *buf;
51 } else if (!strncmp(tok, "none", strlen(arg))) { 60 int ret = -1;
52 callchain_param.mode = CHAIN_NONE; 61
53 symbol_conf.use_callchain = false; 62 /* We need buffer that we know we can write to. */
54 return 0; 63 buf = malloc(strlen(arg) + 1);
55 } else { 64 if (!buf)
56 return -1; 65 return -ENOMEM;
57 } 66
67 strcpy(buf, arg);
68
69 tok = strtok_r((char *)buf, ",", &saveptr);
70 name = tok ? : (char *)buf;
71
72 do {
73 /* Framepointer style */
74 if (!strncmp(name, "fp", sizeof("fp"))) {
75 if (!strtok_r(NULL, ",", &saveptr)) {
76 callchain_param.record_mode = CALLCHAIN_FP;
77 ret = 0;
78 } else
79 pr_err("callchain: No more arguments "
80 "needed for -g fp\n");
81 break;
58 82
59 /* get the min percentage */ 83#ifdef HAVE_DWARF_UNWIND_SUPPORT
60 tok = strtok(NULL, ","); 84 /* Dwarf style */
61 if (!tok) 85 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
62 goto setup; 86 const unsigned long default_stack_dump_size = 8192;
63 87
64 callchain_param.min_percent = strtod(tok, &endptr); 88 ret = 0;
65 if (tok == endptr) 89 callchain_param.record_mode = CALLCHAIN_DWARF;
66 return -1; 90 callchain_param.dump_size = default_stack_dump_size;
67 91
68 /* get the print limit */ 92 tok = strtok_r(NULL, ",", &saveptr);
69 tok2 = strtok(NULL, ","); 93 if (tok) {
70 if (!tok2) 94 unsigned long size = 0;
71 goto setup;
72 95
73 if (tok2[0] != 'c') { 96 ret = get_stack_size(tok, &size);
74 callchain_param.print_limit = strtoul(tok2, &endptr, 0); 97 callchain_param.dump_size = size;
75 tok2 = strtok(NULL, ","); 98 }
76 if (!tok2) 99#endif /* HAVE_DWARF_UNWIND_SUPPORT */
77 goto setup; 100 } else {
101 pr_err("callchain: Unknown --call-graph option "
102 "value: %s\n", arg);
103 break;
104 }
105
106 } while (0);
107
108 free(buf);
109 return ret;
110}
111
112static int parse_callchain_mode(const char *value)
113{
114 if (!strncmp(value, "graph", strlen(value))) {
115 callchain_param.mode = CHAIN_GRAPH_ABS;
116 return 0;
117 }
118 if (!strncmp(value, "flat", strlen(value))) {
119 callchain_param.mode = CHAIN_FLAT;
120 return 0;
78 } 121 }
122 if (!strncmp(value, "fractal", strlen(value))) {
123 callchain_param.mode = CHAIN_GRAPH_REL;
124 return 0;
125 }
126 return -1;
127}
79 128
80 /* get the call chain order */ 129static int parse_callchain_order(const char *value)
81 if (!strncmp(tok2, "caller", strlen("caller"))) 130{
131 if (!strncmp(value, "caller", strlen(value))) {
82 callchain_param.order = ORDER_CALLER; 132 callchain_param.order = ORDER_CALLER;
83 else if (!strncmp(tok2, "callee", strlen("callee"))) 133 return 0;
134 }
135 if (!strncmp(value, "callee", strlen(value))) {
84 callchain_param.order = ORDER_CALLEE; 136 callchain_param.order = ORDER_CALLEE;
85 else 137 return 0;
86 return -1; 138 }
139 return -1;
140}
87 141
88 /* Get the sort key */ 142static int parse_callchain_sort_key(const char *value)
89 tok2 = strtok(NULL, ","); 143{
90 if (!tok2) 144 if (!strncmp(value, "function", strlen(value))) {
91 goto setup;
92 if (!strncmp(tok2, "function", strlen("function")))
93 callchain_param.key = CCKEY_FUNCTION; 145 callchain_param.key = CCKEY_FUNCTION;
94 else if (!strncmp(tok2, "address", strlen("address"))) 146 return 0;
147 }
148 if (!strncmp(value, "address", strlen(value))) {
95 callchain_param.key = CCKEY_ADDRESS; 149 callchain_param.key = CCKEY_ADDRESS;
96 else 150 return 0;
97 return -1; 151 }
98setup: 152 return -1;
153}
154
155int
156parse_callchain_report_opt(const char *arg)
157{
158 char *tok;
159 char *endptr;
160 bool minpcnt_set = false;
161
162 symbol_conf.use_callchain = true;
163
164 if (!arg)
165 return 0;
166
167 while ((tok = strtok((char *)arg, ",")) != NULL) {
168 if (!strncmp(tok, "none", strlen(tok))) {
169 callchain_param.mode = CHAIN_NONE;
170 symbol_conf.use_callchain = false;
171 return 0;
172 }
173
174 if (!parse_callchain_mode(tok) ||
175 !parse_callchain_order(tok) ||
176 !parse_callchain_sort_key(tok)) {
177 /* parsing ok - move on to the next */
178 } else if (!minpcnt_set) {
179 /* try to get the min percent */
180 callchain_param.min_percent = strtod(tok, &endptr);
181 if (tok == endptr)
182 return -1;
183 minpcnt_set = true;
184 } else {
185 /* try print limit at last */
186 callchain_param.print_limit = strtoul(tok, &endptr, 0);
187 if (tok == endptr)
188 return -1;
189 }
190
191 arg = NULL;
192 }
193
99 if (callchain_register_param(&callchain_param) < 0) { 194 if (callchain_register_param(&callchain_param) < 0) {
100 pr_err("Can't register callchain params\n"); 195 pr_err("Can't register callchain params\n");
101 return -1; 196 return -1;
@@ -103,6 +198,47 @@ setup:
103 return 0; 198 return 0;
104} 199}
105 200
201int perf_callchain_config(const char *var, const char *value)
202{
203 char *endptr;
204
205 if (prefixcmp(var, "call-graph."))
206 return 0;
207 var += sizeof("call-graph.") - 1;
208
209 if (!strcmp(var, "record-mode"))
210 return parse_callchain_record_opt(value);
211#ifdef HAVE_DWARF_UNWIND_SUPPORT
212 if (!strcmp(var, "dump-size")) {
213 unsigned long size = 0;
214 int ret;
215
216 ret = get_stack_size(value, &size);
217 callchain_param.dump_size = size;
218
219 return ret;
220 }
221#endif
222 if (!strcmp(var, "print-type"))
223 return parse_callchain_mode(value);
224 if (!strcmp(var, "order"))
225 return parse_callchain_order(value);
226 if (!strcmp(var, "sort-key"))
227 return parse_callchain_sort_key(value);
228 if (!strcmp(var, "threshold")) {
229 callchain_param.min_percent = strtod(value, &endptr);
230 if (value == endptr)
231 return -1;
232 }
233 if (!strcmp(var, "print-limit")) {
234 callchain_param.print_limit = strtod(value, &endptr);
235 if (value == endptr)
236 return -1;
237 }
238
239 return 0;
240}
241
106static void 242static void
107rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, 243rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
108 enum chain_mode mode) 244 enum chain_mode mode)
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index da43619d6173..2a1f5a46543a 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -54,6 +54,9 @@ enum chain_key {
54}; 54};
55 55
56struct callchain_param { 56struct callchain_param {
57 bool enabled;
58 enum perf_call_graph_mode record_mode;
59 u32 dump_size;
57 enum chain_mode mode; 60 enum chain_mode mode;
58 u32 print_limit; 61 u32 print_limit;
59 double min_percent; 62 double min_percent;
@@ -154,7 +157,6 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
154struct option; 157struct option;
155struct hist_entry; 158struct hist_entry;
156 159
157int record_parse_callchain(const char *arg, struct record_opts *opts);
158int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 160int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
159int record_callchain_opt(const struct option *opt, const char *arg, int unset); 161int record_callchain_opt(const struct option *opt, const char *arg, int unset);
160 162
@@ -166,7 +168,9 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
166 bool hide_unresolved); 168 bool hide_unresolved);
167 169
168extern const char record_callchain_help[]; 170extern const char record_callchain_help[];
171int parse_callchain_record_opt(const char *arg);
169int parse_callchain_report_opt(const char *arg); 172int parse_callchain_report_opt(const char *arg);
173int perf_callchain_config(const char *var, const char *value);
170 174
171static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, 175static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
172 struct callchain_cursor *src) 176 struct callchain_cursor *src)
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index c5d05ec17220..47b78b3f0325 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -1,7 +1,9 @@
1#include <sched.h>
1#include "util.h" 2#include "util.h"
2#include "../perf.h" 3#include "../perf.h"
3#include "cloexec.h" 4#include "cloexec.h"
4#include "asm/bug.h" 5#include "asm/bug.h"
6#include "debug.h"
5 7
6static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 8static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
7 9
@@ -9,15 +11,30 @@ static int perf_flag_probe(void)
9{ 11{
10 /* use 'safest' configuration as used in perf_evsel__fallback() */ 12 /* use 'safest' configuration as used in perf_evsel__fallback() */
11 struct perf_event_attr attr = { 13 struct perf_event_attr attr = {
12 .type = PERF_COUNT_SW_CPU_CLOCK, 14 .type = PERF_TYPE_SOFTWARE,
13 .config = PERF_COUNT_SW_CPU_CLOCK, 15 .config = PERF_COUNT_SW_CPU_CLOCK,
16 .exclude_kernel = 1,
14 }; 17 };
15 int fd; 18 int fd;
16 int err; 19 int err;
20 int cpu;
21 pid_t pid = -1;
22 char sbuf[STRERR_BUFSIZE];
17 23
18 /* check cloexec flag */ 24 cpu = sched_getcpu();
19 fd = sys_perf_event_open(&attr, 0, -1, -1, 25 if (cpu < 0)
20 PERF_FLAG_FD_CLOEXEC); 26 cpu = 0;
27
28 while (1) {
29 /* check cloexec flag */
30 fd = sys_perf_event_open(&attr, pid, cpu, -1,
31 PERF_FLAG_FD_CLOEXEC);
32 if (fd < 0 && pid == -1 && errno == EACCES) {
33 pid = 0;
34 continue;
35 }
36 break;
37 }
21 err = errno; 38 err = errno;
22 39
23 if (fd >= 0) { 40 if (fd >= 0) {
@@ -25,17 +42,17 @@ static int perf_flag_probe(void)
25 return 1; 42 return 1;
26 } 43 }
27 44
28 WARN_ONCE(err != EINVAL, 45 WARN_ONCE(err != EINVAL && err != EBUSY,
29 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", 46 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
30 err, strerror(err)); 47 err, strerror_r(err, sbuf, sizeof(sbuf)));
31 48
32 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 49 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
33 fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 50 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
34 err = errno; 51 err = errno;
35 52
36 if (WARN_ONCE(fd < 0, 53 if (WARN_ONCE(fd < 0 && err != EBUSY,
37 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 54 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
38 err, strerror(err))) 55 err, strerror_r(err, sbuf, sizeof(sbuf))))
39 return -1; 56 return -1;
40 57
41 close(fd); 58 close(fd);
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 87b8672eb413..f4654183d391 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -335,3 +335,19 @@ int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
335 va_end(args); 335 va_end(args);
336 return value_color_snprintf(bf, size, fmt, percent); 336 return value_color_snprintf(bf, size, fmt, percent);
337} 337}
338
339int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
340{
341 va_list args;
342 int len;
343 double percent;
344 const char *color;
345
346 va_start(args, fmt);
347 len = va_arg(args, int);
348 percent = va_arg(args, double);
349 va_end(args);
350
351 color = get_percent_color(percent);
352 return color_snprintf(bf, size, color, fmt, len, percent);
353}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 7ff30a62a132..0a594b8a0c26 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -41,6 +41,7 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); 42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value);
43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); 43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 45int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
45const char *get_percent_color(double percent); 46const char *get_percent_color(double percent);
46 47
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index f9e777629e21..b2bb59df65e1 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -74,7 +74,7 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
74 return new; 74 return new;
75} 75}
76 76
77struct comm *comm__new(const char *str, u64 timestamp) 77struct comm *comm__new(const char *str, u64 timestamp, bool exec)
78{ 78{
79 struct comm *comm = zalloc(sizeof(*comm)); 79 struct comm *comm = zalloc(sizeof(*comm));
80 80
@@ -82,6 +82,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
82 return NULL; 82 return NULL;
83 83
84 comm->start = timestamp; 84 comm->start = timestamp;
85 comm->exec = exec;
85 86
86 comm->comm_str = comm_str__findnew(str, &comm_str_root); 87 comm->comm_str = comm_str__findnew(str, &comm_str_root);
87 if (!comm->comm_str) { 88 if (!comm->comm_str) {
@@ -94,7 +95,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
94 return comm; 95 return comm;
95} 96}
96 97
97int comm__override(struct comm *comm, const char *str, u64 timestamp) 98int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
98{ 99{
99 struct comm_str *new, *old = comm->comm_str; 100 struct comm_str *new, *old = comm->comm_str;
100 101
@@ -106,6 +107,8 @@ int comm__override(struct comm *comm, const char *str, u64 timestamp)
106 comm_str__put(old); 107 comm_str__put(old);
107 comm->comm_str = new; 108 comm->comm_str = new;
108 comm->start = timestamp; 109 comm->start = timestamp;
110 if (exec)
111 comm->exec = true;
109 112
110 return 0; 113 return 0;
111} 114}
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index fac5bd51befc..51c10ab257f8 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -11,11 +11,13 @@ struct comm {
11 struct comm_str *comm_str; 11 struct comm_str *comm_str;
12 u64 start; 12 u64 start;
13 struct list_head list; 13 struct list_head list;
14 bool exec;
14}; 15};
15 16
16void comm__free(struct comm *comm); 17void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp); 18struct comm *comm__new(const char *str, u64 timestamp, bool exec);
18const char *comm__str(const struct comm *comm); 19const char *comm__str(const struct comm *comm);
19int comm__override(struct comm *comm, const char *str, u64 timestamp); 20int comm__override(struct comm *comm, const char *str, u64 timestamp,
21 bool exec);
20 22
21#endif /* __PERF_COMM_H */ 23#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 1e5e2e5af6b1..57ff826f150b 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -222,7 +222,8 @@ static int perf_parse_file(config_fn_t fn, void *data)
222 const unsigned char *bomptr = utf8_bom; 222 const unsigned char *bomptr = utf8_bom;
223 223
224 for (;;) { 224 for (;;) {
225 int c = get_next_char(); 225 int line, c = get_next_char();
226
226 if (bomptr && *bomptr) { 227 if (bomptr && *bomptr) {
227 /* We are at the file beginning; skip UTF8-encoded BOM 228 /* We are at the file beginning; skip UTF8-encoded BOM
228 * if present. Sane editors won't put this in on their 229 * if present. Sane editors won't put this in on their
@@ -261,8 +262,16 @@ static int perf_parse_file(config_fn_t fn, void *data)
261 if (!isalpha(c)) 262 if (!isalpha(c))
262 break; 263 break;
263 var[baselen] = tolower(c); 264 var[baselen] = tolower(c);
264 if (get_value(fn, data, var, baselen+1) < 0) 265
266 /*
267 * The get_value function might or might not reach the '\n',
268 * so saving the current line number for error reporting.
269 */
270 line = config_linenr;
271 if (get_value(fn, data, var, baselen+1) < 0) {
272 config_linenr = line;
265 break; 273 break;
274 }
266 } 275 }
267 die("bad config file line %d in %s", config_linenr, config_file_name); 276 die("bad config file line %d in %s", config_linenr, config_file_name);
268} 277}
@@ -286,6 +295,21 @@ static int parse_unit_factor(const char *end, unsigned long *val)
286 return 0; 295 return 0;
287} 296}
288 297
298static int perf_parse_llong(const char *value, long long *ret)
299{
300 if (value && *value) {
301 char *end;
302 long long val = strtoll(value, &end, 0);
303 unsigned long factor = 1;
304
305 if (!parse_unit_factor(end, &factor))
306 return 0;
307 *ret = val * factor;
308 return 1;
309 }
310 return 0;
311}
312
289static int perf_parse_long(const char *value, long *ret) 313static int perf_parse_long(const char *value, long *ret)
290{ 314{
291 if (value && *value) { 315 if (value && *value) {
@@ -307,6 +331,15 @@ static void die_bad_config(const char *name)
307 die("bad config value for '%s'", name); 331 die("bad config value for '%s'", name);
308} 332}
309 333
334u64 perf_config_u64(const char *name, const char *value)
335{
336 long long ret = 0;
337
338 if (!perf_parse_llong(value, &ret))
339 die_bad_config(name);
340 return (u64) ret;
341}
342
310int perf_config_int(const char *name, const char *value) 343int perf_config_int(const char *name, const char *value)
311{ 344{
312 long ret = 0; 345 long ret = 0;
@@ -372,6 +405,9 @@ int perf_default_config(const char *var, const char *value,
372 if (!prefixcmp(var, "ui.")) 405 if (!prefixcmp(var, "ui."))
373 return perf_ui_config(var, value); 406 return perf_ui_config(var, value);
374 407
408 if (!prefixcmp(var, "call-graph."))
409 return perf_callchain_config(var, value);
410
375 /* Add other config variables here. */ 411 /* Add other config variables here. */
376 return 0; 412 return 0;
377} 413}
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 29d720cf5844..1921942fc2e0 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -50,12 +50,14 @@ static int open_file_read(struct perf_data_file *file)
50{ 50{
51 struct stat st; 51 struct stat st;
52 int fd; 52 int fd;
53 char sbuf[STRERR_BUFSIZE];
53 54
54 fd = open(file->path, O_RDONLY); 55 fd = open(file->path, O_RDONLY);
55 if (fd < 0) { 56 if (fd < 0) {
56 int err = errno; 57 int err = errno;
57 58
58 pr_err("failed to open %s: %s", file->path, strerror(err)); 59 pr_err("failed to open %s: %s", file->path,
60 strerror_r(err, sbuf, sizeof(sbuf)));
59 if (err == ENOENT && !strcmp(file->path, "perf.data")) 61 if (err == ENOENT && !strcmp(file->path, "perf.data"))
60 pr_err(" (try 'perf record' first)"); 62 pr_err(" (try 'perf record' first)");
61 pr_err("\n"); 63 pr_err("\n");
@@ -88,6 +90,7 @@ static int open_file_read(struct perf_data_file *file)
88static int open_file_write(struct perf_data_file *file) 90static int open_file_write(struct perf_data_file *file)
89{ 91{
90 int fd; 92 int fd;
93 char sbuf[STRERR_BUFSIZE];
91 94
92 if (check_backup(file)) 95 if (check_backup(file))
93 return -1; 96 return -1;
@@ -95,7 +98,8 @@ static int open_file_write(struct perf_data_file *file)
95 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 98 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
96 99
97 if (fd < 0) 100 if (fd < 0)
98 pr_err("failed to open %s : %s\n", file->path, strerror(errno)); 101 pr_err("failed to open %s : %s\n", file->path,
102 strerror_r(errno, sbuf, sizeof(sbuf)));
99 103
100 return fd; 104 return fd;
101} 105}
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 71d419362634..ba357f3226c6 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -13,8 +13,12 @@
13#include "util.h" 13#include "util.h"
14#include "target.h" 14#include "target.h"
15 15
16#define NSECS_PER_SEC 1000000000ULL
17#define NSECS_PER_USEC 1000ULL
18
16int verbose; 19int verbose;
17bool dump_trace = false, quiet = false; 20bool dump_trace = false, quiet = false;
21int debug_ordered_events;
18 22
19static int _eprintf(int level, int var, const char *fmt, va_list args) 23static int _eprintf(int level, int var, const char *fmt, va_list args)
20{ 24{
@@ -42,6 +46,35 @@ int eprintf(int level, int var, const char *fmt, ...)
42 return ret; 46 return ret;
43} 47}
44 48
49static int __eprintf_time(u64 t, const char *fmt, va_list args)
50{
51 int ret = 0;
52 u64 secs, usecs, nsecs = t;
53
54 secs = nsecs / NSECS_PER_SEC;
55 nsecs -= secs * NSECS_PER_SEC;
56 usecs = nsecs / NSECS_PER_USEC;
57
58 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
59 secs, usecs);
60 ret += vfprintf(stderr, fmt, args);
61 return ret;
62}
63
64int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
65{
66 int ret = 0;
67 va_list args;
68
69 if (var >= level) {
70 va_start(args, fmt);
71 ret = __eprintf_time(t, fmt, args);
72 va_end(args);
73 }
74
75 return ret;
76}
77
45/* 78/*
46 * Overloading libtraceevent standard info print 79 * Overloading libtraceevent standard info print
47 * function, display with -v in perf. 80 * function, display with -v in perf.
@@ -110,7 +143,8 @@ static struct debug_variable {
110 const char *name; 143 const char *name;
111 int *ptr; 144 int *ptr;
112} debug_variables[] = { 145} debug_variables[] = {
113 { .name = "verbose", .ptr = &verbose }, 146 { .name = "verbose", .ptr = &verbose },
147 { .name = "ordered-events", .ptr = &debug_ordered_events},
114 { .name = NULL, } 148 { .name = NULL, }
115}; 149};
116 150
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 89fb6b0f7ab2..be264d6f3b30 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -3,6 +3,7 @@
3#define __PERF_DEBUG_H 3#define __PERF_DEBUG_H
4 4
5#include <stdbool.h> 5#include <stdbool.h>
6#include <string.h>
6#include "event.h" 7#include "event.h"
7#include "../ui/helpline.h" 8#include "../ui/helpline.h"
8#include "../ui/progress.h" 9#include "../ui/progress.h"
@@ -10,6 +11,7 @@
10 11
11extern int verbose; 12extern int verbose;
12extern bool quiet, dump_trace; 13extern bool quiet, dump_trace;
14extern int debug_ordered_events;
13 15
14#ifndef pr_fmt 16#ifndef pr_fmt
15#define pr_fmt(fmt) fmt 17#define pr_fmt(fmt) fmt
@@ -29,6 +31,14 @@ extern bool quiet, dump_trace;
29#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 31#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
30#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 32#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
31 33
34#define pr_time_N(n, var, t, fmt, ...) \
35 eprintf_time(n, var, t, fmt, ##__VA_ARGS__)
36
37#define pr_oe_time(t, fmt, ...) pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
38#define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
39
40#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
41
32int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 42int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
33void trace_event(union perf_event *event); 43void trace_event(union perf_event *event);
34 44
@@ -38,6 +48,7 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
38void pr_stat(const char *fmt, ...); 48void pr_stat(const char *fmt, ...);
39 49
40int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4))); 50int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
51int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__((format(printf, 4, 5)));
41 52
42int perf_debug_option(const char *str); 53int perf_debug_option(const char *str);
43 54
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 90d02c661dd4..0247acfdfaca 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -37,6 +37,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
37{ 37{
38 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 38 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
39 int ret = 0; 39 int ret = 0;
40 size_t len;
40 41
41 switch (type) { 42 switch (type) {
42 case DSO_BINARY_TYPE__DEBUGLINK: { 43 case DSO_BINARY_TYPE__DEBUGLINK: {
@@ -60,26 +61,25 @@ int dso__read_binary_type_filename(const struct dso *dso,
60 break; 61 break;
61 62
62 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: 63 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
63 snprintf(filename, size, "%s/usr/lib/debug%s.debug", 64 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
64 symbol_conf.symfs, dso->long_name); 65 snprintf(filename + len, size - len, "%s.debug", dso->long_name);
65 break; 66 break;
66 67
67 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: 68 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
68 snprintf(filename, size, "%s/usr/lib/debug%s", 69 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
69 symbol_conf.symfs, dso->long_name); 70 snprintf(filename + len, size - len, "%s", dso->long_name);
70 break; 71 break;
71 72
72 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: 73 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
73 { 74 {
74 const char *last_slash; 75 const char *last_slash;
75 size_t len;
76 size_t dir_size; 76 size_t dir_size;
77 77
78 last_slash = dso->long_name + dso->long_name_len; 78 last_slash = dso->long_name + dso->long_name_len;
79 while (last_slash != dso->long_name && *last_slash != '/') 79 while (last_slash != dso->long_name && *last_slash != '/')
80 last_slash--; 80 last_slash--;
81 81
82 len = scnprintf(filename, size, "%s", symbol_conf.symfs); 82 len = __symbol__join_symfs(filename, size, "");
83 dir_size = last_slash - dso->long_name + 2; 83 dir_size = last_slash - dso->long_name + 2;
84 if (dir_size > (size - len)) { 84 if (dir_size > (size - len)) {
85 ret = -1; 85 ret = -1;
@@ -100,26 +100,24 @@ int dso__read_binary_type_filename(const struct dso *dso,
100 build_id__sprintf(dso->build_id, 100 build_id__sprintf(dso->build_id,
101 sizeof(dso->build_id), 101 sizeof(dso->build_id),
102 build_id_hex); 102 build_id_hex);
103 snprintf(filename, size, 103 len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
104 "%s/usr/lib/debug/.build-id/%.2s/%s.debug", 104 snprintf(filename + len, size - len, "%.2s/%s.debug",
105 symbol_conf.symfs, build_id_hex, build_id_hex + 2); 105 build_id_hex, build_id_hex + 2);
106 break; 106 break;
107 107
108 case DSO_BINARY_TYPE__VMLINUX: 108 case DSO_BINARY_TYPE__VMLINUX:
109 case DSO_BINARY_TYPE__GUEST_VMLINUX: 109 case DSO_BINARY_TYPE__GUEST_VMLINUX:
110 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: 110 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
111 snprintf(filename, size, "%s%s", 111 __symbol__join_symfs(filename, size, dso->long_name);
112 symbol_conf.symfs, dso->long_name);
113 break; 112 break;
114 113
115 case DSO_BINARY_TYPE__GUEST_KMODULE: 114 case DSO_BINARY_TYPE__GUEST_KMODULE:
116 snprintf(filename, size, "%s%s%s", symbol_conf.symfs, 115 path__join3(filename, size, symbol_conf.symfs,
117 root_dir, dso->long_name); 116 root_dir, dso->long_name);
118 break; 117 break;
119 118
120 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 119 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
121 snprintf(filename, size, "%s%s", symbol_conf.symfs, 120 __symbol__join_symfs(filename, size, dso->long_name);
122 dso->long_name);
123 break; 121 break;
124 122
125 case DSO_BINARY_TYPE__KCORE: 123 case DSO_BINARY_TYPE__KCORE:
@@ -164,13 +162,15 @@ static void close_first_dso(void);
164static int do_open(char *name) 162static int do_open(char *name)
165{ 163{
166 int fd; 164 int fd;
165 char sbuf[STRERR_BUFSIZE];
167 166
168 do { 167 do {
169 fd = open(name, O_RDONLY); 168 fd = open(name, O_RDONLY);
170 if (fd >= 0) 169 if (fd >= 0)
171 return fd; 170 return fd;
172 171
173 pr_debug("dso open failed, mmap: %s\n", strerror(errno)); 172 pr_debug("dso open failed, mmap: %s\n",
173 strerror_r(errno, sbuf, sizeof(sbuf)));
174 if (!dso__data_open_cnt || errno != EMFILE) 174 if (!dso__data_open_cnt || errno != EMFILE)
175 break; 175 break;
176 176
@@ -532,10 +532,12 @@ static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
532static int data_file_size(struct dso *dso) 532static int data_file_size(struct dso *dso)
533{ 533{
534 struct stat st; 534 struct stat st;
535 char sbuf[STRERR_BUFSIZE];
535 536
536 if (!dso->data.file_size) { 537 if (!dso->data.file_size) {
537 if (fstat(dso->data.fd, &st)) { 538 if (fstat(dso->data.fd, &st)) {
538 pr_err("dso mmap failed, fstat: %s\n", strerror(errno)); 539 pr_err("dso mmap failed, fstat: %s\n",
540 strerror_r(errno, sbuf, sizeof(sbuf)));
539 return -1; 541 return -1;
540 } 542 }
541 dso->data.file_size = st.st_size; 543 dso->data.file_size = st.st_size;
@@ -651,6 +653,65 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
651 return dso; 653 return dso;
652} 654}
653 655
656/*
657 * Find a matching entry and/or link current entry to RB tree.
658 * Either one of the dso or name parameter must be non-NULL or the
659 * function will not work.
660 */
661static struct dso *dso__findlink_by_longname(struct rb_root *root,
662 struct dso *dso, const char *name)
663{
664 struct rb_node **p = &root->rb_node;
665 struct rb_node *parent = NULL;
666
667 if (!name)
668 name = dso->long_name;
669 /*
670 * Find node with the matching name
671 */
672 while (*p) {
673 struct dso *this = rb_entry(*p, struct dso, rb_node);
674 int rc = strcmp(name, this->long_name);
675
676 parent = *p;
677 if (rc == 0) {
678 /*
679 * In case the new DSO is a duplicate of an existing
680 * one, print an one-time warning & put the new entry
681 * at the end of the list of duplicates.
682 */
683 if (!dso || (dso == this))
684 return this; /* Find matching dso */
685 /*
686 * The core kernel DSOs may have duplicated long name.
687 * In this case, the short name should be different.
688 * Comparing the short names to differentiate the DSOs.
689 */
690 rc = strcmp(dso->short_name, this->short_name);
691 if (rc == 0) {
692 pr_err("Duplicated dso name: %s\n", name);
693 return NULL;
694 }
695 }
696 if (rc < 0)
697 p = &parent->rb_left;
698 else
699 p = &parent->rb_right;
700 }
701 if (dso) {
702 /* Add new node and rebalance tree */
703 rb_link_node(&dso->rb_node, parent, p);
704 rb_insert_color(&dso->rb_node, root);
705 }
706 return NULL;
707}
708
709static inline struct dso *
710dso__find_by_longname(const struct rb_root *root, const char *name)
711{
712 return dso__findlink_by_longname((struct rb_root *)root, NULL, name);
713}
714
654void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) 715void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
655{ 716{
656 if (name == NULL) 717 if (name == NULL)
@@ -753,6 +814,7 @@ struct dso *dso__new(const char *name)
753 dso->a2l_fails = 1; 814 dso->a2l_fails = 1;
754 dso->kernel = DSO_TYPE_USER; 815 dso->kernel = DSO_TYPE_USER;
755 dso->needs_swap = DSO_SWAP__UNSET; 816 dso->needs_swap = DSO_SWAP__UNSET;
817 RB_CLEAR_NODE(&dso->rb_node);
756 INIT_LIST_HEAD(&dso->node); 818 INIT_LIST_HEAD(&dso->node);
757 INIT_LIST_HEAD(&dso->data.open_entry); 819 INIT_LIST_HEAD(&dso->data.open_entry);
758 } 820 }
@@ -763,6 +825,10 @@ struct dso *dso__new(const char *name)
763void dso__delete(struct dso *dso) 825void dso__delete(struct dso *dso)
764{ 826{
765 int i; 827 int i;
828
829 if (!RB_EMPTY_NODE(&dso->rb_node))
830 pr_err("DSO %s is still in rbtree when being deleted!\n",
831 dso->long_name);
766 for (i = 0; i < MAP__NR_TYPES; ++i) 832 for (i = 0; i < MAP__NR_TYPES; ++i)
767 symbols__delete(&dso->symbols[i]); 833 symbols__delete(&dso->symbols[i]);
768 834
@@ -849,35 +915,34 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
849 return have_build_id; 915 return have_build_id;
850} 916}
851 917
852void dsos__add(struct list_head *head, struct dso *dso) 918void dsos__add(struct dsos *dsos, struct dso *dso)
853{ 919{
854 list_add_tail(&dso->node, head); 920 list_add_tail(&dso->node, &dsos->head);
921 dso__findlink_by_longname(&dsos->root, dso, NULL);
855} 922}
856 923
857struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short) 924struct dso *dsos__find(const struct dsos *dsos, const char *name,
925 bool cmp_short)
858{ 926{
859 struct dso *pos; 927 struct dso *pos;
860 928
861 if (cmp_short) { 929 if (cmp_short) {
862 list_for_each_entry(pos, head, node) 930 list_for_each_entry(pos, &dsos->head, node)
863 if (strcmp(pos->short_name, name) == 0) 931 if (strcmp(pos->short_name, name) == 0)
864 return pos; 932 return pos;
865 return NULL; 933 return NULL;
866 } 934 }
867 list_for_each_entry(pos, head, node) 935 return dso__find_by_longname(&dsos->root, name);
868 if (strcmp(pos->long_name, name) == 0)
869 return pos;
870 return NULL;
871} 936}
872 937
873struct dso *__dsos__findnew(struct list_head *head, const char *name) 938struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
874{ 939{
875 struct dso *dso = dsos__find(head, name, false); 940 struct dso *dso = dsos__find(dsos, name, false);
876 941
877 if (!dso) { 942 if (!dso) {
878 dso = dso__new(name); 943 dso = dso__new(name);
879 if (dso != NULL) { 944 if (dso != NULL) {
880 dsos__add(head, dso); 945 dsos__add(dsos, dso);
881 dso__set_basename(dso); 946 dso__set_basename(dso);
882 } 947 }
883 } 948 }
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 5e463c0964d4..acb651acc7fd 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -90,8 +90,18 @@ struct dso_cache {
90 char data[0]; 90 char data[0];
91}; 91};
92 92
93/*
94 * DSOs are put into both a list for fast iteration and rbtree for fast
95 * long name lookup.
96 */
97struct dsos {
98 struct list_head head;
99 struct rb_root root; /* rbtree root sorted by long name */
100};
101
93struct dso { 102struct dso {
94 struct list_head node; 103 struct list_head node;
104 struct rb_node rb_node; /* rbtree node sorted by long name */
95 struct rb_root symbols[MAP__NR_TYPES]; 105 struct rb_root symbols[MAP__NR_TYPES];
96 struct rb_root symbol_names[MAP__NR_TYPES]; 106 struct rb_root symbol_names[MAP__NR_TYPES];
97 void *a2l; 107 void *a2l;
@@ -224,10 +234,10 @@ struct map *dso__new_map(const char *name);
224struct dso *dso__kernel_findnew(struct machine *machine, const char *name, 234struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
225 const char *short_name, int dso_type); 235 const char *short_name, int dso_type);
226 236
227void dsos__add(struct list_head *head, struct dso *dso); 237void dsos__add(struct dsos *dsos, struct dso *dso);
228struct dso *dsos__find(const struct list_head *head, const char *name, 238struct dso *dsos__find(const struct dsos *dsos, const char *name,
229 bool cmp_short); 239 bool cmp_short);
230struct dso *__dsos__findnew(struct list_head *head, const char *name); 240struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
231bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 241bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
232 242
233size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 243size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 1398c83d896d..4af6b279e34a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -558,13 +558,17 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
558 struct map *map; 558 struct map *map;
559 struct kmap *kmap; 559 struct kmap *kmap;
560 int err; 560 int err;
561 union perf_event *event;
562
563 if (machine->vmlinux_maps[0] == NULL)
564 return -1;
565
561 /* 566 /*
562 * We should get this from /sys/kernel/sections/.text, but till that is 567 * We should get this from /sys/kernel/sections/.text, but till that is
563 * available use this, and after it is use this as a fallback for older 568 * available use this, and after it is use this as a fallback for older
564 * kernels. 569 * kernels.
565 */ 570 */
566 union perf_event *event = zalloc((sizeof(event->mmap) + 571 event = zalloc((sizeof(event->mmap) + machine->id_hdr_size));
567 machine->id_hdr_size));
568 if (event == NULL) { 572 if (event == NULL) {
569 pr_debug("Not enough memory synthesizing mmap event " 573 pr_debug("Not enough memory synthesizing mmap event "
570 "for kernel modules\n"); 574 "for kernel modules\n");
@@ -784,9 +788,9 @@ try_again:
784 * "[vdso]" dso, but for now lets use the old trick of looking 788 * "[vdso]" dso, but for now lets use the old trick of looking
785 * in the whole kernel symbol list. 789 * in the whole kernel symbol list.
786 */ 790 */
787 if ((long long)al->addr < 0 && 791 if (cpumode == PERF_RECORD_MISC_USER && machine &&
788 cpumode == PERF_RECORD_MISC_USER && 792 mg != &machine->kmaps &&
789 machine && mg != &machine->kmaps) { 793 machine__kernel_ip(machine, al->addr)) {
790 mg = &machine->kmaps; 794 mg = &machine->kmaps;
791 load_map = true; 795 load_map = true;
792 goto try_again; 796 goto try_again;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 94d6976180da..7eb7107731ec 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -156,6 +156,8 @@ struct perf_sample {
156 u32 cpu; 156 u32 cpu;
157 u32 raw_size; 157 u32 raw_size;
158 u64 data_src; 158 u64 data_src;
159 u32 flags;
160 u16 insn_len;
159 void *raw_data; 161 void *raw_data;
160 struct ip_callchain *callchain; 162 struct ip_callchain *callchain;
161 struct branch_stack *branch_stack; 163 struct branch_stack *branch_stack;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 814e954c1318..3cebc9a8d52e 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -25,6 +25,9 @@
25#include <linux/bitops.h> 25#include <linux/bitops.h>
26#include <linux/hash.h> 26#include <linux/hash.h>
27 27
28static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
29static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
30
28#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 31#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
29#define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 32#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
30 33
@@ -37,6 +40,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
37 INIT_HLIST_HEAD(&evlist->heads[i]); 40 INIT_HLIST_HEAD(&evlist->heads[i]);
38 INIT_LIST_HEAD(&evlist->entries); 41 INIT_LIST_HEAD(&evlist->entries);
39 perf_evlist__set_maps(evlist, cpus, threads); 42 perf_evlist__set_maps(evlist, cpus, threads);
43 fdarray__init(&evlist->pollfd, 64);
40 evlist->workload.pid = -1; 44 evlist->workload.pid = -1;
41} 45}
42 46
@@ -102,7 +106,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
102void perf_evlist__exit(struct perf_evlist *evlist) 106void perf_evlist__exit(struct perf_evlist *evlist)
103{ 107{
104 zfree(&evlist->mmap); 108 zfree(&evlist->mmap);
105 zfree(&evlist->pollfd); 109 fdarray__exit(&evlist->pollfd);
106} 110}
107 111
108void perf_evlist__delete(struct perf_evlist *evlist) 112void perf_evlist__delete(struct perf_evlist *evlist)
@@ -122,6 +126,7 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
122{ 126{
123 list_add_tail(&entry->node, &evlist->entries); 127 list_add_tail(&entry->node, &evlist->entries);
124 entry->idx = evlist->nr_entries; 128 entry->idx = evlist->nr_entries;
129 entry->tracking = !entry->idx;
125 130
126 if (!evlist->nr_entries++) 131 if (!evlist->nr_entries++)
127 perf_evlist__set_id_pos(evlist); 132 perf_evlist__set_id_pos(evlist);
@@ -265,17 +270,27 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
265 return 0; 270 return 0;
266} 271}
267 272
273static int perf_evlist__nr_threads(struct perf_evlist *evlist,
274 struct perf_evsel *evsel)
275{
276 if (evsel->system_wide)
277 return 1;
278 else
279 return thread_map__nr(evlist->threads);
280}
281
268void perf_evlist__disable(struct perf_evlist *evlist) 282void perf_evlist__disable(struct perf_evlist *evlist)
269{ 283{
270 int cpu, thread; 284 int cpu, thread;
271 struct perf_evsel *pos; 285 struct perf_evsel *pos;
272 int nr_cpus = cpu_map__nr(evlist->cpus); 286 int nr_cpus = cpu_map__nr(evlist->cpus);
273 int nr_threads = thread_map__nr(evlist->threads); 287 int nr_threads;
274 288
275 for (cpu = 0; cpu < nr_cpus; cpu++) { 289 for (cpu = 0; cpu < nr_cpus; cpu++) {
276 evlist__for_each(evlist, pos) { 290 evlist__for_each(evlist, pos) {
277 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 291 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
278 continue; 292 continue;
293 nr_threads = perf_evlist__nr_threads(evlist, pos);
279 for (thread = 0; thread < nr_threads; thread++) 294 for (thread = 0; thread < nr_threads; thread++)
280 ioctl(FD(pos, cpu, thread), 295 ioctl(FD(pos, cpu, thread),
281 PERF_EVENT_IOC_DISABLE, 0); 296 PERF_EVENT_IOC_DISABLE, 0);
@@ -288,12 +303,13 @@ void perf_evlist__enable(struct perf_evlist *evlist)
288 int cpu, thread; 303 int cpu, thread;
289 struct perf_evsel *pos; 304 struct perf_evsel *pos;
290 int nr_cpus = cpu_map__nr(evlist->cpus); 305 int nr_cpus = cpu_map__nr(evlist->cpus);
291 int nr_threads = thread_map__nr(evlist->threads); 306 int nr_threads;
292 307
293 for (cpu = 0; cpu < nr_cpus; cpu++) { 308 for (cpu = 0; cpu < nr_cpus; cpu++) {
294 evlist__for_each(evlist, pos) { 309 evlist__for_each(evlist, pos) {
295 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 310 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
296 continue; 311 continue;
312 nr_threads = perf_evlist__nr_threads(evlist, pos);
297 for (thread = 0; thread < nr_threads; thread++) 313 for (thread = 0; thread < nr_threads; thread++)
298 ioctl(FD(pos, cpu, thread), 314 ioctl(FD(pos, cpu, thread),
299 PERF_EVENT_IOC_ENABLE, 0); 315 PERF_EVENT_IOC_ENABLE, 0);
@@ -305,12 +321,14 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
305 struct perf_evsel *evsel) 321 struct perf_evsel *evsel)
306{ 322{
307 int cpu, thread, err; 323 int cpu, thread, err;
324 int nr_cpus = cpu_map__nr(evlist->cpus);
325 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
308 326
309 if (!evsel->fd) 327 if (!evsel->fd)
310 return 0; 328 return 0;
311 329
312 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 330 for (cpu = 0; cpu < nr_cpus; cpu++) {
313 for (thread = 0; thread < evlist->threads->nr; thread++) { 331 for (thread = 0; thread < nr_threads; thread++) {
314 err = ioctl(FD(evsel, cpu, thread), 332 err = ioctl(FD(evsel, cpu, thread),
315 PERF_EVENT_IOC_DISABLE, 0); 333 PERF_EVENT_IOC_DISABLE, 0);
316 if (err) 334 if (err)
@@ -324,12 +342,14 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
324 struct perf_evsel *evsel) 342 struct perf_evsel *evsel)
325{ 343{
326 int cpu, thread, err; 344 int cpu, thread, err;
345 int nr_cpus = cpu_map__nr(evlist->cpus);
346 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
327 347
328 if (!evsel->fd) 348 if (!evsel->fd)
329 return -EINVAL; 349 return -EINVAL;
330 350
331 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 351 for (cpu = 0; cpu < nr_cpus; cpu++) {
332 for (thread = 0; thread < evlist->threads->nr; thread++) { 352 for (thread = 0; thread < nr_threads; thread++) {
333 err = ioctl(FD(evsel, cpu, thread), 353 err = ioctl(FD(evsel, cpu, thread),
334 PERF_EVENT_IOC_ENABLE, 0); 354 PERF_EVENT_IOC_ENABLE, 0);
335 if (err) 355 if (err)
@@ -339,21 +359,111 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
339 return 0; 359 return 0;
340} 360}
341 361
342static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 362static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
363 struct perf_evsel *evsel, int cpu)
364{
365 int thread, err;
366 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
367
368 if (!evsel->fd)
369 return -EINVAL;
370
371 for (thread = 0; thread < nr_threads; thread++) {
372 err = ioctl(FD(evsel, cpu, thread),
373 PERF_EVENT_IOC_ENABLE, 0);
374 if (err)
375 return err;
376 }
377 return 0;
378}
379
380static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
381 struct perf_evsel *evsel,
382 int thread)
383{
384 int cpu, err;
385 int nr_cpus = cpu_map__nr(evlist->cpus);
386
387 if (!evsel->fd)
388 return -EINVAL;
389
390 for (cpu = 0; cpu < nr_cpus; cpu++) {
391 err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
392 if (err)
393 return err;
394 }
395 return 0;
396}
397
398int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
399 struct perf_evsel *evsel, int idx)
400{
401 bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus);
402
403 if (per_cpu_mmaps)
404 return perf_evlist__enable_event_cpu(evlist, evsel, idx);
405 else
406 return perf_evlist__enable_event_thread(evlist, evsel, idx);
407}
408
409int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
343{ 410{
344 int nr_cpus = cpu_map__nr(evlist->cpus); 411 int nr_cpus = cpu_map__nr(evlist->cpus);
345 int nr_threads = thread_map__nr(evlist->threads); 412 int nr_threads = thread_map__nr(evlist->threads);
346 int nfds = nr_cpus * nr_threads * evlist->nr_entries; 413 int nfds = 0;
347 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 414 struct perf_evsel *evsel;
348 return evlist->pollfd != NULL ? 0 : -ENOMEM; 415
416 list_for_each_entry(evsel, &evlist->entries, node) {
417 if (evsel->system_wide)
418 nfds += nr_cpus;
419 else
420 nfds += nr_cpus * nr_threads;
421 }
422
423 if (fdarray__available_entries(&evlist->pollfd) < nfds &&
424 fdarray__grow(&evlist->pollfd, nfds) < 0)
425 return -ENOMEM;
426
427 return 0;
428}
429
430static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx)
431{
432 int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
433 /*
434 * Save the idx so that when we filter out fds POLLHUP'ed we can
435 * close the associated evlist->mmap[] entry.
436 */
437 if (pos >= 0) {
438 evlist->pollfd.priv[pos].idx = idx;
439
440 fcntl(fd, F_SETFL, O_NONBLOCK);
441 }
442
443 return pos;
444}
445
446int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
447{
448 return __perf_evlist__add_pollfd(evlist, fd, -1);
449}
450
451static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd)
452{
453 struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd);
454
455 perf_evlist__mmap_put(evlist, fda->priv[fd].idx);
456}
457
458int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
459{
460 return fdarray__filter(&evlist->pollfd, revents_and_mask,
461 perf_evlist__munmap_filtered);
349} 462}
350 463
351void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 464int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
352{ 465{
353 fcntl(fd, F_SETFL, O_NONBLOCK); 466 return fdarray__poll(&evlist->pollfd, timeout);
354 evlist->pollfd[evlist->nr_fds].fd = fd;
355 evlist->pollfd[evlist->nr_fds].events = POLLIN;
356 evlist->nr_fds++;
357} 467}
358 468
359static void perf_evlist__id_hash(struct perf_evlist *evlist, 469static void perf_evlist__id_hash(struct perf_evlist *evlist,
@@ -566,14 +676,36 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
566 return event; 676 return event;
567} 677}
568 678
679static bool perf_mmap__empty(struct perf_mmap *md)
680{
681 return perf_mmap__read_head(md) != md->prev;
682}
683
684static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
685{
686 ++evlist->mmap[idx].refcnt;
687}
688
689static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
690{
691 BUG_ON(evlist->mmap[idx].refcnt == 0);
692
693 if (--evlist->mmap[idx].refcnt == 0)
694 __perf_evlist__munmap(evlist, idx);
695}
696
569void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 697void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
570{ 698{
699 struct perf_mmap *md = &evlist->mmap[idx];
700
571 if (!evlist->overwrite) { 701 if (!evlist->overwrite) {
572 struct perf_mmap *md = &evlist->mmap[idx];
573 unsigned int old = md->prev; 702 unsigned int old = md->prev;
574 703
575 perf_mmap__write_tail(md, old); 704 perf_mmap__write_tail(md, old);
576 } 705 }
706
707 if (md->refcnt == 1 && perf_mmap__empty(md))
708 perf_evlist__mmap_put(evlist, idx);
577} 709}
578 710
579static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 711static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
@@ -581,6 +713,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
581 if (evlist->mmap[idx].base != NULL) { 713 if (evlist->mmap[idx].base != NULL) {
582 munmap(evlist->mmap[idx].base, evlist->mmap_len); 714 munmap(evlist->mmap[idx].base, evlist->mmap_len);
583 evlist->mmap[idx].base = NULL; 715 evlist->mmap[idx].base = NULL;
716 evlist->mmap[idx].refcnt = 0;
584 } 717 }
585} 718}
586 719
@@ -614,6 +747,20 @@ struct mmap_params {
614static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 747static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
615 struct mmap_params *mp, int fd) 748 struct mmap_params *mp, int fd)
616{ 749{
750 /*
751 * The last one will be done at perf_evlist__mmap_consume(), so that we
752 * make sure we don't prevent tools from consuming every last event in
753 * the ring buffer.
754 *
755 * I.e. we can get the POLLHUP meaning that the fd doesn't exist
756 * anymore, but the last events for it are still in the ring buffer,
757 * waiting to be consumed.
758 *
759 * Tools can chose to ignore this at their own discretion, but the
760 * evlist layer can't just drop it when filtering events in
761 * perf_evlist__filter_pollfd().
762 */
763 evlist->mmap[idx].refcnt = 2;
617 evlist->mmap[idx].prev = 0; 764 evlist->mmap[idx].prev = 0;
618 evlist->mmap[idx].mask = mp->mask; 765 evlist->mmap[idx].mask = mp->mask;
619 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 766 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
@@ -625,7 +772,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
625 return -1; 772 return -1;
626 } 773 }
627 774
628 perf_evlist__add_pollfd(evlist, fd);
629 return 0; 775 return 0;
630} 776}
631 777
@@ -636,7 +782,12 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
636 struct perf_evsel *evsel; 782 struct perf_evsel *evsel;
637 783
638 evlist__for_each(evlist, evsel) { 784 evlist__for_each(evlist, evsel) {
639 int fd = FD(evsel, cpu, thread); 785 int fd;
786
787 if (evsel->system_wide && thread)
788 continue;
789
790 fd = FD(evsel, cpu, thread);
640 791
641 if (*output == -1) { 792 if (*output == -1) {
642 *output = fd; 793 *output = fd;
@@ -645,6 +796,13 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
645 } else { 796 } else {
646 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 797 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
647 return -1; 798 return -1;
799
800 perf_evlist__mmap_get(evlist, idx);
801 }
802
803 if (__perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
804 perf_evlist__mmap_put(evlist, idx);
805 return -1;
648 } 806 }
649 807
650 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 808 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -804,7 +962,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
804 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 962 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
805 return -ENOMEM; 963 return -ENOMEM;
806 964
807 if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 965 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
808 return -ENOMEM; 966 return -ENOMEM;
809 967
810 evlist->overwrite = overwrite; 968 evlist->overwrite = overwrite;
@@ -1061,6 +1219,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1061 } 1219 }
1062 1220
1063 if (!evlist->workload.pid) { 1221 if (!evlist->workload.pid) {
1222 int ret;
1223
1064 if (pipe_output) 1224 if (pipe_output)
1065 dup2(2, 1); 1225 dup2(2, 1);
1066 1226
@@ -1078,8 +1238,22 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1078 /* 1238 /*
1079 * Wait until the parent tells us to go. 1239 * Wait until the parent tells us to go.
1080 */ 1240 */
1081 if (read(go_pipe[0], &bf, 1) == -1) 1241 ret = read(go_pipe[0], &bf, 1);
1082 perror("unable to read pipe"); 1242 /*
1243 * The parent will ask for the execvp() to be performed by
1244 * writing exactly one byte, in workload.cork_fd, usually via
1245 * perf_evlist__start_workload().
1246 *
1247 * For cancelling the workload without actuallin running it,
1248 * the parent will just close workload.cork_fd, without writing
1249 * anything, i.e. read will return zero and we just exit()
1250 * here.
1251 */
1252 if (ret != 1) {
1253 if (ret == -1)
1254 perror("unable to read pipe");
1255 exit(ret);
1256 }
1083 1257
1084 execvp(argv[0], (char **)argv); 1258 execvp(argv[0], (char **)argv);
1085 1259
@@ -1202,7 +1376,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1202 int err, char *buf, size_t size) 1376 int err, char *buf, size_t size)
1203{ 1377{
1204 int printed, value; 1378 int printed, value;
1205 char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1379 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1206 1380
1207 switch (err) { 1381 switch (err) {
1208 case EACCES: 1382 case EACCES:
@@ -1250,3 +1424,19 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
1250 1424
1251 list_splice(&move, &evlist->entries); 1425 list_splice(&move, &evlist->entries);
1252} 1426}
1427
1428void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
1429 struct perf_evsel *tracking_evsel)
1430{
1431 struct perf_evsel *evsel;
1432
1433 if (tracking_evsel->tracking)
1434 return;
1435
1436 evlist__for_each(evlist, evsel) {
1437 if (evsel != tracking_evsel)
1438 evsel->tracking = false;
1439 }
1440
1441 tracking_evsel->tracking = true;
1442}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index f5173cd63693..bd312b01e876 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,6 +2,7 @@
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <api/fd/array.h>
5#include <stdio.h> 6#include <stdio.h>
6#include "../perf.h" 7#include "../perf.h"
7#include "event.h" 8#include "event.h"
@@ -17,9 +18,15 @@ struct record_opts;
17#define PERF_EVLIST__HLIST_BITS 8 18#define PERF_EVLIST__HLIST_BITS 8
18#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 19#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
19 20
21/**
22 * struct perf_mmap - perf's ring buffer mmap details
23 *
24 * @refcnt - e.g. code using PERF_EVENT_IOC_SET_OUTPUT to share this
25 */
20struct perf_mmap { 26struct perf_mmap {
21 void *base; 27 void *base;
22 int mask; 28 int mask;
29 int refcnt;
23 unsigned int prev; 30 unsigned int prev;
24 char event_copy[PERF_SAMPLE_MAX_SIZE]; 31 char event_copy[PERF_SAMPLE_MAX_SIZE];
25}; 32};
@@ -29,7 +36,6 @@ struct perf_evlist {
29 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 36 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
30 int nr_entries; 37 int nr_entries;
31 int nr_groups; 38 int nr_groups;
32 int nr_fds;
33 int nr_mmaps; 39 int nr_mmaps;
34 size_t mmap_len; 40 size_t mmap_len;
35 int id_pos; 41 int id_pos;
@@ -40,8 +46,8 @@ struct perf_evlist {
40 pid_t pid; 46 pid_t pid;
41 } workload; 47 } workload;
42 bool overwrite; 48 bool overwrite;
49 struct fdarray pollfd;
43 struct perf_mmap *mmap; 50 struct perf_mmap *mmap;
44 struct pollfd *pollfd;
45 struct thread_map *threads; 51 struct thread_map *threads;
46 struct cpu_map *cpus; 52 struct cpu_map *cpus;
47 struct perf_evsel *selected; 53 struct perf_evsel *selected;
@@ -82,7 +88,11 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
82void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 88void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
83 int cpu, int thread, u64 id); 89 int cpu, int thread, u64 id);
84 90
85void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 91int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
92int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
93int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
94
95int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
86 96
87struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 97struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
88 98
@@ -122,6 +132,8 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
122 struct perf_evsel *evsel); 132 struct perf_evsel *evsel);
123int perf_evlist__enable_event(struct perf_evlist *evlist, 133int perf_evlist__enable_event(struct perf_evlist *evlist,
124 struct perf_evsel *evsel); 134 struct perf_evsel *evsel);
135int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
136 struct perf_evsel *evsel, int idx);
125 137
126void perf_evlist__set_selected(struct perf_evlist *evlist, 138void perf_evlist__set_selected(struct perf_evlist *evlist,
127 struct perf_evsel *evsel); 139 struct perf_evsel *evsel);
@@ -262,4 +274,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
262#define evlist__for_each_safe(evlist, tmp, evsel) \ 274#define evlist__for_each_safe(evlist, tmp, evsel) \
263 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) 275 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel)
264 276
277void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
278 struct perf_evsel *tracking_evsel);
279
265#endif /* __PERF_EVLIST_H */ 280#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21a373ebea22..e0868a901c4a 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -162,6 +162,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
162 struct perf_event_attr *attr, int idx) 162 struct perf_event_attr *attr, int idx)
163{ 163{
164 evsel->idx = idx; 164 evsel->idx = idx;
165 evsel->tracking = !idx;
165 evsel->attr = *attr; 166 evsel->attr = *attr;
166 evsel->leader = evsel; 167 evsel->leader = evsel;
167 evsel->unit = ""; 168 evsel->unit = "";
@@ -502,20 +503,19 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
502} 503}
503 504
504static void 505static void
505perf_evsel__config_callgraph(struct perf_evsel *evsel, 506perf_evsel__config_callgraph(struct perf_evsel *evsel)
506 struct record_opts *opts)
507{ 507{
508 bool function = perf_evsel__is_function_event(evsel); 508 bool function = perf_evsel__is_function_event(evsel);
509 struct perf_event_attr *attr = &evsel->attr; 509 struct perf_event_attr *attr = &evsel->attr;
510 510
511 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 511 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
512 512
513 if (opts->call_graph == CALLCHAIN_DWARF) { 513 if (callchain_param.record_mode == CALLCHAIN_DWARF) {
514 if (!function) { 514 if (!function) {
515 perf_evsel__set_sample_bit(evsel, REGS_USER); 515 perf_evsel__set_sample_bit(evsel, REGS_USER);
516 perf_evsel__set_sample_bit(evsel, STACK_USER); 516 perf_evsel__set_sample_bit(evsel, STACK_USER);
517 attr->sample_regs_user = PERF_REGS_MASK; 517 attr->sample_regs_user = PERF_REGS_MASK;
518 attr->sample_stack_user = opts->stack_dump_size; 518 attr->sample_stack_user = callchain_param.dump_size;
519 attr->exclude_callchain_user = 1; 519 attr->exclude_callchain_user = 1;
520 } else { 520 } else {
521 pr_info("Cannot use DWARF unwind for function trace event," 521 pr_info("Cannot use DWARF unwind for function trace event,"
@@ -561,7 +561,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
561{ 561{
562 struct perf_evsel *leader = evsel->leader; 562 struct perf_evsel *leader = evsel->leader;
563 struct perf_event_attr *attr = &evsel->attr; 563 struct perf_event_attr *attr = &evsel->attr;
564 int track = !evsel->idx; /* only the first counter needs these */ 564 int track = evsel->tracking;
565 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; 565 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
566 566
567 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; 567 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
@@ -624,8 +624,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
624 attr->mmap_data = track; 624 attr->mmap_data = track;
625 } 625 }
626 626
627 if (opts->call_graph_enabled && !evsel->no_aux_samples) 627 if (callchain_param.enabled && !evsel->no_aux_samples)
628 perf_evsel__config_callgraph(evsel, opts); 628 perf_evsel__config_callgraph(evsel);
629 629
630 if (target__has_cpu(&opts->target)) 630 if (target__has_cpu(&opts->target))
631 perf_evsel__set_sample_bit(evsel, CPU); 631 perf_evsel__set_sample_bit(evsel, CPU);
@@ -633,9 +633,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
633 if (opts->period) 633 if (opts->period)
634 perf_evsel__set_sample_bit(evsel, PERIOD); 634 perf_evsel__set_sample_bit(evsel, PERIOD);
635 635
636 if (!perf_missing_features.sample_id_all && 636 /*
637 (opts->sample_time || !opts->no_inherit || 637 * When the user explicitely disabled time don't force it here.
638 target__has_cpu(&opts->target) || per_cpu)) 638 */
639 if (opts->sample_time &&
640 (!perf_missing_features.sample_id_all &&
641 (!opts->no_inherit || target__has_cpu(&opts->target) || per_cpu)))
639 perf_evsel__set_sample_bit(evsel, TIME); 642 perf_evsel__set_sample_bit(evsel, TIME);
640 643
641 if (opts->raw_samples && !evsel->no_aux_samples) { 644 if (opts->raw_samples && !evsel->no_aux_samples) {
@@ -692,6 +695,10 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
692int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 695int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
693{ 696{
694 int cpu, thread; 697 int cpu, thread;
698
699 if (evsel->system_wide)
700 nthreads = 1;
701
695 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 702 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
696 703
697 if (evsel->fd) { 704 if (evsel->fd) {
@@ -710,6 +717,9 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthrea
710{ 717{
711 int cpu, thread; 718 int cpu, thread;
712 719
720 if (evsel->system_wide)
721 nthreads = 1;
722
713 for (cpu = 0; cpu < ncpus; cpu++) { 723 for (cpu = 0; cpu < ncpus; cpu++) {
714 for (thread = 0; thread < nthreads; thread++) { 724 for (thread = 0; thread < nthreads; thread++) {
715 int fd = FD(evsel, cpu, thread), 725 int fd = FD(evsel, cpu, thread),
@@ -740,6 +750,9 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
740 750
741int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 751int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
742{ 752{
753 if (evsel->system_wide)
754 nthreads = 1;
755
743 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 756 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
744 if (evsel->sample_id == NULL) 757 if (evsel->sample_id == NULL)
745 return -ENOMEM; 758 return -ENOMEM;
@@ -784,6 +797,9 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
784{ 797{
785 int cpu, thread; 798 int cpu, thread;
786 799
800 if (evsel->system_wide)
801 nthreads = 1;
802
787 for (cpu = 0; cpu < ncpus; cpu++) 803 for (cpu = 0; cpu < ncpus; cpu++)
788 for (thread = 0; thread < nthreads; ++thread) { 804 for (thread = 0; thread < nthreads; ++thread) {
789 close(FD(evsel, cpu, thread)); 805 close(FD(evsel, cpu, thread));
@@ -872,6 +888,9 @@ int __perf_evsel__read(struct perf_evsel *evsel,
872 int cpu, thread; 888 int cpu, thread;
873 struct perf_counts_values *aggr = &evsel->counts->aggr, count; 889 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
874 890
891 if (evsel->system_wide)
892 nthreads = 1;
893
875 aggr->val = aggr->ena = aggr->run = 0; 894 aggr->val = aggr->ena = aggr->run = 0;
876 895
877 for (cpu = 0; cpu < ncpus; cpu++) { 896 for (cpu = 0; cpu < ncpus; cpu++) {
@@ -994,13 +1013,18 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
994static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1013static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
995 struct thread_map *threads) 1014 struct thread_map *threads)
996{ 1015{
997 int cpu, thread; 1016 int cpu, thread, nthreads;
998 unsigned long flags = PERF_FLAG_FD_CLOEXEC; 1017 unsigned long flags = PERF_FLAG_FD_CLOEXEC;
999 int pid = -1, err; 1018 int pid = -1, err;
1000 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; 1019 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
1001 1020
1021 if (evsel->system_wide)
1022 nthreads = 1;
1023 else
1024 nthreads = threads->nr;
1025
1002 if (evsel->fd == NULL && 1026 if (evsel->fd == NULL &&
1003 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 1027 perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0)
1004 return -ENOMEM; 1028 return -ENOMEM;
1005 1029
1006 if (evsel->cgrp) { 1030 if (evsel->cgrp) {
@@ -1024,10 +1048,10 @@ retry_sample_id:
1024 1048
1025 for (cpu = 0; cpu < cpus->nr; cpu++) { 1049 for (cpu = 0; cpu < cpus->nr; cpu++) {
1026 1050
1027 for (thread = 0; thread < threads->nr; thread++) { 1051 for (thread = 0; thread < nthreads; thread++) {
1028 int group_fd; 1052 int group_fd;
1029 1053
1030 if (!evsel->cgrp) 1054 if (!evsel->cgrp && !evsel->system_wide)
1031 pid = threads->map[thread]; 1055 pid = threads->map[thread];
1032 1056
1033 group_fd = get_group_fd(evsel, cpu, thread); 1057 group_fd = get_group_fd(evsel, cpu, thread);
@@ -1100,7 +1124,7 @@ out_close:
1100 close(FD(evsel, cpu, thread)); 1124 close(FD(evsel, cpu, thread));
1101 FD(evsel, cpu, thread) = -1; 1125 FD(evsel, cpu, thread) = -1;
1102 } 1126 }
1103 thread = threads->nr; 1127 thread = nthreads;
1104 } while (--cpu >= 0); 1128 } while (--cpu >= 0);
1105 return err; 1129 return err;
1106} 1130}
@@ -2002,6 +2026,8 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2002int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 2026int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2003 int err, char *msg, size_t size) 2027 int err, char *msg, size_t size)
2004{ 2028{
2029 char sbuf[STRERR_BUFSIZE];
2030
2005 switch (err) { 2031 switch (err) {
2006 case EPERM: 2032 case EPERM:
2007 case EACCES: 2033 case EACCES:
@@ -2036,13 +2062,20 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2036 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); 2062 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.");
2037#endif 2063#endif
2038 break; 2064 break;
2065 case EBUSY:
2066 if (find_process("oprofiled"))
2067 return scnprintf(msg, size,
2068 "The PMU counters are busy/taken by another profiler.\n"
2069 "We found oprofile daemon running, please stop it and try again.");
2070 break;
2039 default: 2071 default:
2040 break; 2072 break;
2041 } 2073 }
2042 2074
2043 return scnprintf(msg, size, 2075 return scnprintf(msg, size,
2044 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s). \n" 2076 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2045 "/bin/dmesg may provide additional information.\n" 2077 "/bin/dmesg may provide additional information.\n"
2046 "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 2078 "No CONFIG_PERF_EVENTS=y kernel support configured?\n",
2047 err, strerror(err), perf_evsel__name(evsel)); 2079 err, strerror_r(err, sbuf, sizeof(sbuf)),
2080 perf_evsel__name(evsel));
2048} 2081}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d7f93ce0ebc1..7bc314be6a7b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -85,6 +85,8 @@ struct perf_evsel {
85 bool needs_swap; 85 bool needs_swap;
86 bool no_aux_samples; 86 bool no_aux_samples;
87 bool immediate; 87 bool immediate;
88 bool system_wide;
89 bool tracking;
88 /* parse modifier helper */ 90 /* parse modifier helper */
89 int exclude_GH; 91 int exclude_GH;
90 int nr_members; 92 int nr_members;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 158c787ce0c4..ce0de00399da 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -214,11 +214,11 @@ static int machine__hit_all_dsos(struct machine *machine)
214{ 214{
215 int err; 215 int err;
216 216
217 err = __dsos__hit_all(&machine->kernel_dsos); 217 err = __dsos__hit_all(&machine->kernel_dsos.head);
218 if (err) 218 if (err)
219 return err; 219 return err;
220 220
221 return __dsos__hit_all(&machine->user_dsos); 221 return __dsos__hit_all(&machine->user_dsos.head);
222} 222}
223 223
224int dsos__hit_all(struct perf_session *session) 224int dsos__hit_all(struct perf_session *session)
@@ -288,11 +288,12 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
288 umisc = PERF_RECORD_MISC_GUEST_USER; 288 umisc = PERF_RECORD_MISC_GUEST_USER;
289 } 289 }
290 290
291 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine, 291 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
292 machine->pid, kmisc, fd); 292 machine->pid, kmisc, fd);
293 if (err == 0) 293 if (err == 0)
294 err = __dsos__write_buildid_table(&machine->user_dsos, machine, 294 err = __dsos__write_buildid_table(&machine->user_dsos.head,
295 machine->pid, umisc, fd); 295 machine, machine->pid, umisc,
296 fd);
296 return err; 297 return err;
297} 298}
298 299
@@ -455,9 +456,10 @@ static int __dsos__cache_build_ids(struct list_head *head,
455 456
456static int machine__cache_build_ids(struct machine *machine, const char *debugdir) 457static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
457{ 458{
458 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, machine, 459 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
459 debugdir); 460 debugdir);
460 ret |= __dsos__cache_build_ids(&machine->user_dsos, machine, debugdir); 461 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
462 debugdir);
461 return ret; 463 return ret;
462} 464}
463 465
@@ -483,8 +485,10 @@ static int perf_session__cache_build_ids(struct perf_session *session)
483 485
484static bool machine__read_build_ids(struct machine *machine, bool with_hits) 486static bool machine__read_build_ids(struct machine *machine, bool with_hits)
485{ 487{
486 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits); 488 bool ret;
487 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits); 489
490 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
491 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
488 return ret; 492 return ret;
489} 493}
490 494
@@ -1548,7 +1552,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1548 struct perf_session *session) 1552 struct perf_session *session)
1549{ 1553{
1550 int err = -1; 1554 int err = -1;
1551 struct list_head *head; 1555 struct dsos *dsos;
1552 struct machine *machine; 1556 struct machine *machine;
1553 u16 misc; 1557 u16 misc;
1554 struct dso *dso; 1558 struct dso *dso;
@@ -1563,22 +1567,22 @@ static int __event_process_build_id(struct build_id_event *bev,
1563 switch (misc) { 1567 switch (misc) {
1564 case PERF_RECORD_MISC_KERNEL: 1568 case PERF_RECORD_MISC_KERNEL:
1565 dso_type = DSO_TYPE_KERNEL; 1569 dso_type = DSO_TYPE_KERNEL;
1566 head = &machine->kernel_dsos; 1570 dsos = &machine->kernel_dsos;
1567 break; 1571 break;
1568 case PERF_RECORD_MISC_GUEST_KERNEL: 1572 case PERF_RECORD_MISC_GUEST_KERNEL:
1569 dso_type = DSO_TYPE_GUEST_KERNEL; 1573 dso_type = DSO_TYPE_GUEST_KERNEL;
1570 head = &machine->kernel_dsos; 1574 dsos = &machine->kernel_dsos;
1571 break; 1575 break;
1572 case PERF_RECORD_MISC_USER: 1576 case PERF_RECORD_MISC_USER:
1573 case PERF_RECORD_MISC_GUEST_USER: 1577 case PERF_RECORD_MISC_GUEST_USER:
1574 dso_type = DSO_TYPE_USER; 1578 dso_type = DSO_TYPE_USER;
1575 head = &machine->user_dsos; 1579 dsos = &machine->user_dsos;
1576 break; 1580 break;
1577 default: 1581 default:
1578 goto out; 1582 goto out;
1579 } 1583 }
1580 1584
1581 dso = __dsos__findnew(head, filename); 1585 dso = __dsos__findnew(dsos, filename);
1582 if (dso != NULL) { 1586 if (dso != NULL) {
1583 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1587 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1584 1588
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 30df6187ee02..86569fa3651d 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -277,6 +277,28 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
277 } 277 }
278} 278}
279 279
280void hists__delete_entries(struct hists *hists)
281{
282 struct rb_node *next = rb_first(&hists->entries);
283 struct hist_entry *n;
284
285 while (next) {
286 n = rb_entry(next, struct hist_entry, rb_node);
287 next = rb_next(&n->rb_node);
288
289 rb_erase(&n->rb_node, &hists->entries);
290
291 if (sort__need_collapse)
292 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
293
294 --hists->nr_entries;
295 if (!n->filtered)
296 --hists->nr_non_filtered_entries;
297
298 hist_entry__free(n);
299 }
300}
301
280/* 302/*
281 * histogram, sorted on item, collects periods 303 * histogram, sorted on item, collects periods
282 */ 304 */
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 742f49a85725..8c9c70e18cbb 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -152,6 +152,7 @@ void hists__output_resort(struct hists *hists);
152void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 152void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
153 153
154void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 154void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
155void hists__delete_entries(struct hists *hists);
155void hists__output_recalc_col_len(struct hists *hists, int max_rows); 156void hists__output_recalc_col_len(struct hists *hists, int max_rows);
156 157
157u64 hists__total_period(struct hists *hists); 158u64 hists__total_period(struct hists *hists);
@@ -192,6 +193,7 @@ struct perf_hpp {
192}; 193};
193 194
194struct perf_hpp_fmt { 195struct perf_hpp_fmt {
196 const char *name;
195 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 197 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
196 struct perf_evsel *evsel); 198 struct perf_evsel *evsel);
197 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 199 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -207,6 +209,8 @@ struct perf_hpp_fmt {
207 struct list_head list; 209 struct list_head list;
208 struct list_head sort_list; 210 struct list_head sort_list;
209 bool elide; 211 bool elide;
212 int len;
213 int user_len;
210}; 214};
211 215
212extern struct list_head perf_hpp__list; 216extern struct list_head perf_hpp__list;
@@ -261,17 +265,19 @@ static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format)
261} 265}
262 266
263void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 267void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
268void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists);
269void perf_hpp__set_user_width(const char *width_list_str);
264 270
265typedef u64 (*hpp_field_fn)(struct hist_entry *he); 271typedef u64 (*hpp_field_fn)(struct hist_entry *he);
266typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); 272typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front);
267typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...); 273typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...);
268 274
269int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 275int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
270 hpp_field_fn get_field, const char *fmt, 276 struct hist_entry *he, hpp_field_fn get_field,
271 hpp_snprint_fn print_fn, bool fmt_percent); 277 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
272int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, 278int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
273 hpp_field_fn get_field, const char *fmt, 279 struct hist_entry *he, hpp_field_fn get_field,
274 hpp_snprint_fn print_fn, bool fmt_percent); 280 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
275 281
276static inline void advance_hpp(struct perf_hpp *hpp, int inc) 282static inline void advance_hpp(struct perf_hpp *hpp, int inc)
277{ 283{
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
index 0b5a8cd2ee79..cf1d7913783b 100644
--- a/tools/perf/util/kvm-stat.h
+++ b/tools/perf/util/kvm-stat.h
@@ -92,7 +92,6 @@ struct perf_kvm_stat {
92 u64 lost_events; 92 u64 lost_events;
93 u64 duration; 93 u64 duration;
94 94
95 const char *pid_str;
96 struct intlist *pid_list; 95 struct intlist *pid_list;
97 96
98 struct rb_root result; 97 struct rb_root result;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 16bba9fff2c8..b7d477fbda02 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -17,8 +17,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
17{ 17{
18 map_groups__init(&machine->kmaps); 18 map_groups__init(&machine->kmaps);
19 RB_CLEAR_NODE(&machine->rb_node); 19 RB_CLEAR_NODE(&machine->rb_node);
20 INIT_LIST_HEAD(&machine->user_dsos); 20 INIT_LIST_HEAD(&machine->user_dsos.head);
21 INIT_LIST_HEAD(&machine->kernel_dsos); 21 INIT_LIST_HEAD(&machine->kernel_dsos.head);
22 22
23 machine->threads = RB_ROOT; 23 machine->threads = RB_ROOT;
24 INIT_LIST_HEAD(&machine->dead_threads); 24 INIT_LIST_HEAD(&machine->dead_threads);
@@ -31,6 +31,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
31 31
32 machine->symbol_filter = NULL; 32 machine->symbol_filter = NULL;
33 machine->id_hdr_size = 0; 33 machine->id_hdr_size = 0;
34 machine->comm_exec = false;
35 machine->kernel_start = 0;
34 36
35 machine->root_dir = strdup(root_dir); 37 machine->root_dir = strdup(root_dir);
36 if (machine->root_dir == NULL) 38 if (machine->root_dir == NULL)
@@ -70,11 +72,12 @@ out_delete:
70 return NULL; 72 return NULL;
71} 73}
72 74
73static void dsos__delete(struct list_head *dsos) 75static void dsos__delete(struct dsos *dsos)
74{ 76{
75 struct dso *pos, *n; 77 struct dso *pos, *n;
76 78
77 list_for_each_entry_safe(pos, n, dsos, node) { 79 list_for_each_entry_safe(pos, n, &dsos->head, node) {
80 RB_CLEAR_NODE(&pos->rb_node);
78 list_del(&pos->node); 81 list_del(&pos->node);
79 dso__delete(pos); 82 dso__delete(pos);
80 } 83 }
@@ -179,6 +182,19 @@ void machines__set_symbol_filter(struct machines *machines,
179 } 182 }
180} 183}
181 184
185void machines__set_comm_exec(struct machines *machines, bool comm_exec)
186{
187 struct rb_node *nd;
188
189 machines->host.comm_exec = comm_exec;
190
191 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
192 struct machine *machine = rb_entry(nd, struct machine, rb_node);
193
194 machine->comm_exec = comm_exec;
195 }
196}
197
182struct machine *machines__find(struct machines *machines, pid_t pid) 198struct machine *machines__find(struct machines *machines, pid_t pid)
183{ 199{
184 struct rb_node **p = &machines->guests.rb_node; 200 struct rb_node **p = &machines->guests.rb_node;
@@ -398,17 +414,31 @@ struct thread *machine__find_thread(struct machine *machine, pid_t pid,
398 return __machine__findnew_thread(machine, pid, tid, false); 414 return __machine__findnew_thread(machine, pid, tid, false);
399} 415}
400 416
417struct comm *machine__thread_exec_comm(struct machine *machine,
418 struct thread *thread)
419{
420 if (machine->comm_exec)
421 return thread__exec_comm(thread);
422 else
423 return thread__comm(thread);
424}
425
401int machine__process_comm_event(struct machine *machine, union perf_event *event, 426int machine__process_comm_event(struct machine *machine, union perf_event *event,
402 struct perf_sample *sample) 427 struct perf_sample *sample)
403{ 428{
404 struct thread *thread = machine__findnew_thread(machine, 429 struct thread *thread = machine__findnew_thread(machine,
405 event->comm.pid, 430 event->comm.pid,
406 event->comm.tid); 431 event->comm.tid);
432 bool exec = event->header.misc & PERF_RECORD_MISC_COMM_EXEC;
433
434 if (exec)
435 machine->comm_exec = true;
407 436
408 if (dump_trace) 437 if (dump_trace)
409 perf_event__fprintf_comm(event, stdout); 438 perf_event__fprintf_comm(event, stdout);
410 439
411 if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) { 440 if (thread == NULL ||
441 __thread__set_comm(thread, event->comm.comm, sample->time, exec)) {
412 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 442 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
413 return -1; 443 return -1;
414 } 444 }
@@ -448,23 +478,23 @@ struct map *machine__new_module(struct machine *machine, u64 start,
448size_t machines__fprintf_dsos(struct machines *machines, FILE *fp) 478size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
449{ 479{
450 struct rb_node *nd; 480 struct rb_node *nd;
451 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos, fp) + 481 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos.head, fp) +
452 __dsos__fprintf(&machines->host.user_dsos, fp); 482 __dsos__fprintf(&machines->host.user_dsos.head, fp);
453 483
454 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 484 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
455 struct machine *pos = rb_entry(nd, struct machine, rb_node); 485 struct machine *pos = rb_entry(nd, struct machine, rb_node);
456 ret += __dsos__fprintf(&pos->kernel_dsos, fp); 486 ret += __dsos__fprintf(&pos->kernel_dsos.head, fp);
457 ret += __dsos__fprintf(&pos->user_dsos, fp); 487 ret += __dsos__fprintf(&pos->user_dsos.head, fp);
458 } 488 }
459 489
460 return ret; 490 return ret;
461} 491}
462 492
463size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 493size_t machine__fprintf_dsos_buildid(struct machine *m, FILE *fp,
464 bool (skip)(struct dso *dso, int parm), int parm) 494 bool (skip)(struct dso *dso, int parm), int parm)
465{ 495{
466 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) + 496 return __dsos__fprintf_buildid(&m->kernel_dsos.head, fp, skip, parm) +
467 __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm); 497 __dsos__fprintf_buildid(&m->user_dsos.head, fp, skip, parm);
468} 498}
469 499
470size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp, 500size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
@@ -565,8 +595,8 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
565 * Returns the name of the start symbol in *symbol_name. Pass in NULL as 595 * Returns the name of the start symbol in *symbol_name. Pass in NULL as
566 * symbol_name if it's not that important. 596 * symbol_name if it's not that important.
567 */ 597 */
568static u64 machine__get_kernel_start_addr(struct machine *machine, 598static u64 machine__get_running_kernel_start(struct machine *machine,
569 const char **symbol_name) 599 const char **symbol_name)
570{ 600{
571 char filename[PATH_MAX]; 601 char filename[PATH_MAX];
572 int i; 602 int i;
@@ -593,7 +623,7 @@ static u64 machine__get_kernel_start_addr(struct machine *machine,
593int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 623int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
594{ 624{
595 enum map_type type; 625 enum map_type type;
596 u64 start = machine__get_kernel_start_addr(machine, NULL); 626 u64 start = machine__get_running_kernel_start(machine, NULL);
597 627
598 for (type = 0; type < MAP__NR_TYPES; ++type) { 628 for (type = 0; type < MAP__NR_TYPES; ++type) {
599 struct kmap *kmap; 629 struct kmap *kmap;
@@ -912,7 +942,7 @@ int machine__create_kernel_maps(struct machine *machine)
912{ 942{
913 struct dso *kernel = machine__get_kernel(machine); 943 struct dso *kernel = machine__get_kernel(machine);
914 const char *name; 944 const char *name;
915 u64 addr = machine__get_kernel_start_addr(machine, &name); 945 u64 addr = machine__get_running_kernel_start(machine, &name);
916 if (!addr) 946 if (!addr)
917 return -1; 947 return -1;
918 948
@@ -965,7 +995,7 @@ static bool machine__uses_kcore(struct machine *machine)
965{ 995{
966 struct dso *dso; 996 struct dso *dso;
967 997
968 list_for_each_entry(dso, &machine->kernel_dsos, node) { 998 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
969 if (dso__is_kcore(dso)) 999 if (dso__is_kcore(dso))
970 return true; 1000 return true;
971 } 1001 }
@@ -1285,6 +1315,16 @@ static void ip__resolve_data(struct machine *machine, struct thread *thread,
1285 1315
1286 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, 1316 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr,
1287 &al); 1317 &al);
1318 if (al.map == NULL) {
1319 /*
1320 * some shared data regions have execute bit set which puts
1321 * their mapping in the MAP__FUNCTION type array.
1322 * Check there as a fallback option before dropping the sample.
1323 */
1324 thread__find_addr_location(thread, machine, m, MAP__FUNCTION, addr,
1325 &al);
1326 }
1327
1288 ams->addr = addr; 1328 ams->addr = addr;
1289 ams->al_addr = al.addr; 1329 ams->al_addr = al.addr;
1290 ams->sym = al.sym; 1330 ams->sym = al.sym;
@@ -1531,3 +1571,25 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
1531 1571
1532 return 0; 1572 return 0;
1533} 1573}
1574
1575int machine__get_kernel_start(struct machine *machine)
1576{
1577 struct map *map = machine__kernel_map(machine, MAP__FUNCTION);
1578 int err = 0;
1579
1580 /*
1581 * The only addresses above 2^63 are kernel addresses of a 64-bit
1582 * kernel. Note that addresses are unsigned so that on a 32-bit system
1583 * all addresses including kernel addresses are less than 2^32. In
1584 * that case (32-bit system), if the kernel mapping is unknown, all
1585 * addresses will be assumed to be in user space - see
1586 * machine__kernel_ip().
1587 */
1588 machine->kernel_start = 1ULL << 63;
1589 if (map) {
1590 err = map__load(map, machine->symbol_filter);
1591 if (map->start)
1592 machine->kernel_start = map->start;
1593 }
1594 return err;
1595}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index b972824e6294..2b651a7f5d0d 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -4,6 +4,7 @@
4#include <sys/types.h> 4#include <sys/types.h>
5#include <linux/rbtree.h> 5#include <linux/rbtree.h>
6#include "map.h" 6#include "map.h"
7#include "dso.h"
7#include "event.h" 8#include "event.h"
8 9
9struct addr_location; 10struct addr_location;
@@ -26,15 +27,17 @@ struct machine {
26 struct rb_node rb_node; 27 struct rb_node rb_node;
27 pid_t pid; 28 pid_t pid;
28 u16 id_hdr_size; 29 u16 id_hdr_size;
30 bool comm_exec;
29 char *root_dir; 31 char *root_dir;
30 struct rb_root threads; 32 struct rb_root threads;
31 struct list_head dead_threads; 33 struct list_head dead_threads;
32 struct thread *last_match; 34 struct thread *last_match;
33 struct vdso_info *vdso_info; 35 struct vdso_info *vdso_info;
34 struct list_head user_dsos; 36 struct dsos user_dsos;
35 struct list_head kernel_dsos; 37 struct dsos kernel_dsos;
36 struct map_groups kmaps; 38 struct map_groups kmaps;
37 struct map *vmlinux_maps[MAP__NR_TYPES]; 39 struct map *vmlinux_maps[MAP__NR_TYPES];
40 u64 kernel_start;
38 symbol_filter_t symbol_filter; 41 symbol_filter_t symbol_filter;
39 pid_t *current_tid; 42 pid_t *current_tid;
40}; 43};
@@ -45,8 +48,26 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
45 return machine->vmlinux_maps[type]; 48 return machine->vmlinux_maps[type];
46} 49}
47 50
51int machine__get_kernel_start(struct machine *machine);
52
53static inline u64 machine__kernel_start(struct machine *machine)
54{
55 if (!machine->kernel_start)
56 machine__get_kernel_start(machine);
57 return machine->kernel_start;
58}
59
60static inline bool machine__kernel_ip(struct machine *machine, u64 ip)
61{
62 u64 kernel_start = machine__kernel_start(machine);
63
64 return ip >= kernel_start;
65}
66
48struct thread *machine__find_thread(struct machine *machine, pid_t pid, 67struct thread *machine__find_thread(struct machine *machine, pid_t pid,
49 pid_t tid); 68 pid_t tid);
69struct comm *machine__thread_exec_comm(struct machine *machine,
70 struct thread *thread);
50 71
51int machine__process_comm_event(struct machine *machine, union perf_event *event, 72int machine__process_comm_event(struct machine *machine, union perf_event *event,
52 struct perf_sample *sample); 73 struct perf_sample *sample);
@@ -88,6 +109,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
88 109
89void machines__set_symbol_filter(struct machines *machines, 110void machines__set_symbol_filter(struct machines *machines,
90 symbol_filter_t symbol_filter); 111 symbol_filter_t symbol_filter);
112void machines__set_comm_exec(struct machines *machines, bool comm_exec);
91 113
92struct machine *machine__new_host(void); 114struct machine *machine__new_host(void);
93int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 115int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 31b8905dd863..b7090596ac50 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -31,6 +31,7 @@ static inline int is_anon_memory(const char *filename)
31static inline int is_no_dso_memory(const char *filename) 31static inline int is_no_dso_memory(const char *filename)
32{ 32{
33 return !strncmp(filename, "[stack", 6) || 33 return !strncmp(filename, "[stack", 6) ||
34 !strncmp(filename, "/SYSV",5) ||
34 !strcmp(filename, "[heap]"); 35 !strcmp(filename, "[heap]");
35} 36}
36 37
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
new file mode 100644
index 000000000000..706ce1a66169
--- /dev/null
+++ b/tools/perf/util/ordered-events.c
@@ -0,0 +1,245 @@
1#include <linux/list.h>
2#include <linux/compiler.h>
3#include "ordered-events.h"
4#include "evlist.h"
5#include "session.h"
6#include "asm/bug.h"
7#include "debug.h"
8
9#define pr_N(n, fmt, ...) \
10 eprintf(n, debug_ordered_events, fmt, ##__VA_ARGS__)
11
12#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
13
14static void queue_event(struct ordered_events *oe, struct ordered_event *new)
15{
16 struct ordered_event *last = oe->last;
17 u64 timestamp = new->timestamp;
18 struct list_head *p;
19
20 ++oe->nr_events;
21 oe->last = new;
22
23 pr_oe_time2(timestamp, "queue_event nr_events %u\n", oe->nr_events);
24
25 if (!last) {
26 list_add(&new->list, &oe->events);
27 oe->max_timestamp = timestamp;
28 return;
29 }
30
31 /*
32 * last event might point to some random place in the list as it's
33 * the last queued event. We expect that the new event is close to
34 * this.
35 */
36 if (last->timestamp <= timestamp) {
37 while (last->timestamp <= timestamp) {
38 p = last->list.next;
39 if (p == &oe->events) {
40 list_add_tail(&new->list, &oe->events);
41 oe->max_timestamp = timestamp;
42 return;
43 }
44 last = list_entry(p, struct ordered_event, list);
45 }
46 list_add_tail(&new->list, &last->list);
47 } else {
48 while (last->timestamp > timestamp) {
49 p = last->list.prev;
50 if (p == &oe->events) {
51 list_add(&new->list, &oe->events);
52 return;
53 }
54 last = list_entry(p, struct ordered_event, list);
55 }
56 list_add(&new->list, &last->list);
57 }
58}
59
60#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
61static struct ordered_event *alloc_event(struct ordered_events *oe)
62{
63 struct list_head *cache = &oe->cache;
64 struct ordered_event *new = NULL;
65
66 if (!list_empty(cache)) {
67 new = list_entry(cache->next, struct ordered_event, list);
68 list_del(&new->list);
69 } else if (oe->buffer) {
70 new = oe->buffer + oe->buffer_idx;
71 if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
72 oe->buffer = NULL;
73 } else if (oe->cur_alloc_size < oe->max_alloc_size) {
74 size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
75
76 oe->buffer = malloc(size);
77 if (!oe->buffer)
78 return NULL;
79
80 pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n",
81 oe->cur_alloc_size, size, oe->max_alloc_size);
82
83 oe->cur_alloc_size += size;
84 list_add(&oe->buffer->list, &oe->to_free);
85
86 /* First entry is abused to maintain the to_free list. */
87 oe->buffer_idx = 2;
88 new = oe->buffer + 1;
89 } else {
90 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
91 }
92
93 return new;
94}
95
96struct ordered_event *
97ordered_events__new(struct ordered_events *oe, u64 timestamp)
98{
99 struct ordered_event *new;
100
101 new = alloc_event(oe);
102 if (new) {
103 new->timestamp = timestamp;
104 queue_event(oe, new);
105 }
106
107 return new;
108}
109
110void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event)
111{
112 list_move(&event->list, &oe->cache);
113 oe->nr_events--;
114}
115
116static int __ordered_events__flush(struct perf_session *s,
117 struct perf_tool *tool)
118{
119 struct ordered_events *oe = &s->ordered_events;
120 struct list_head *head = &oe->events;
121 struct ordered_event *tmp, *iter;
122 struct perf_sample sample;
123 u64 limit = oe->next_flush;
124 u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
125 bool show_progress = limit == ULLONG_MAX;
126 struct ui_progress prog;
127 int ret;
128
129 if (!tool->ordered_events || !limit)
130 return 0;
131
132 if (show_progress)
133 ui_progress__init(&prog, oe->nr_events, "Processing time ordered events...");
134
135 list_for_each_entry_safe(iter, tmp, head, list) {
136 if (session_done())
137 return 0;
138
139 if (iter->timestamp > limit)
140 break;
141
142 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
143 if (ret)
144 pr_err("Can't parse sample, err = %d\n", ret);
145 else {
146 ret = perf_session__deliver_event(s, iter->event, &sample, tool,
147 iter->file_offset);
148 if (ret)
149 return ret;
150 }
151
152 ordered_events__delete(oe, iter);
153 oe->last_flush = iter->timestamp;
154
155 if (show_progress)
156 ui_progress__update(&prog, 1);
157 }
158
159 if (list_empty(head))
160 oe->last = NULL;
161 else if (last_ts <= limit)
162 oe->last = list_entry(head->prev, struct ordered_event, list);
163
164 return 0;
165}
166
167int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
168 enum oe_flush how)
169{
170 struct ordered_events *oe = &s->ordered_events;
171 static const char * const str[] = {
172 "NONE",
173 "FINAL",
174 "ROUND",
175 "HALF ",
176 };
177 int err;
178
179 switch (how) {
180 case OE_FLUSH__FINAL:
181 oe->next_flush = ULLONG_MAX;
182 break;
183
184 case OE_FLUSH__HALF:
185 {
186 struct ordered_event *first, *last;
187 struct list_head *head = &oe->events;
188
189 first = list_entry(head->next, struct ordered_event, list);
190 last = oe->last;
191
192 /* Warn if we are called before any event got allocated. */
193 if (WARN_ONCE(!last || list_empty(head), "empty queue"))
194 return 0;
195
196 oe->next_flush = first->timestamp;
197 oe->next_flush += (last->timestamp - first->timestamp) / 2;
198 break;
199 }
200
201 case OE_FLUSH__ROUND:
202 case OE_FLUSH__NONE:
203 default:
204 break;
205 };
206
207 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush PRE %s, nr_events %u\n",
208 str[how], oe->nr_events);
209 pr_oe_time(oe->max_timestamp, "max_timestamp\n");
210
211 err = __ordered_events__flush(s, tool);
212
213 if (!err) {
214 if (how == OE_FLUSH__ROUND)
215 oe->next_flush = oe->max_timestamp;
216
217 oe->last_flush_type = how;
218 }
219
220 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush POST %s, nr_events %u\n",
221 str[how], oe->nr_events);
222 pr_oe_time(oe->last_flush, "last_flush\n");
223
224 return err;
225}
226
227void ordered_events__init(struct ordered_events *oe)
228{
229 INIT_LIST_HEAD(&oe->events);
230 INIT_LIST_HEAD(&oe->cache);
231 INIT_LIST_HEAD(&oe->to_free);
232 oe->max_alloc_size = (u64) -1;
233 oe->cur_alloc_size = 0;
234}
235
236void ordered_events__free(struct ordered_events *oe)
237{
238 while (!list_empty(&oe->to_free)) {
239 struct ordered_event *event;
240
241 event = list_entry(oe->to_free.next, struct ordered_event, list);
242 list_del(&event->list);
243 free(event);
244 }
245}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
new file mode 100644
index 000000000000..3b2f20542a01
--- /dev/null
+++ b/tools/perf/util/ordered-events.h
@@ -0,0 +1,51 @@
1#ifndef __ORDERED_EVENTS_H
2#define __ORDERED_EVENTS_H
3
4#include <linux/types.h>
5#include "tool.h"
6
7struct perf_session;
8
9struct ordered_event {
10 u64 timestamp;
11 u64 file_offset;
12 union perf_event *event;
13 struct list_head list;
14};
15
16enum oe_flush {
17 OE_FLUSH__NONE,
18 OE_FLUSH__FINAL,
19 OE_FLUSH__ROUND,
20 OE_FLUSH__HALF,
21};
22
23struct ordered_events {
24 u64 last_flush;
25 u64 next_flush;
26 u64 max_timestamp;
27 u64 max_alloc_size;
28 u64 cur_alloc_size;
29 struct list_head events;
30 struct list_head cache;
31 struct list_head to_free;
32 struct ordered_event *buffer;
33 struct ordered_event *last;
34 int buffer_idx;
35 unsigned int nr_events;
36 enum oe_flush last_flush_type;
37};
38
39struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp);
40void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
41int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
42 enum oe_flush how);
43void ordered_events__init(struct ordered_events *oe);
44void ordered_events__free(struct ordered_events *oe);
45
46static inline
47void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
48{
49 oe->max_alloc_size = size;
50}
51#endif /* __ORDERED_EVENTS_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1e15df10a88c..d76aa30cb1fb 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -10,6 +10,7 @@
10#include "symbol.h" 10#include "symbol.h"
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include "debug.h"
13#include <api/fs/debugfs.h> 14#include <api/fs/debugfs.h>
14#include "parse-events-bison.h" 15#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int 16#define YY_EXTRA_TYPE int
@@ -633,18 +634,28 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
633 char *name, struct list_head *head_config) 634 char *name, struct list_head *head_config)
634{ 635{
635 struct perf_event_attr attr; 636 struct perf_event_attr attr;
637 struct perf_pmu_info info;
636 struct perf_pmu *pmu; 638 struct perf_pmu *pmu;
637 struct perf_evsel *evsel; 639 struct perf_evsel *evsel;
638 const char *unit;
639 double scale;
640 640
641 pmu = perf_pmu__find(name); 641 pmu = perf_pmu__find(name);
642 if (!pmu) 642 if (!pmu)
643 return -EINVAL; 643 return -EINVAL;
644 644
645 memset(&attr, 0, sizeof(attr)); 645 if (pmu->default_config) {
646 memcpy(&attr, pmu->default_config,
647 sizeof(struct perf_event_attr));
648 } else {
649 memset(&attr, 0, sizeof(attr));
650 }
651
652 if (!head_config) {
653 attr.type = pmu->type;
654 evsel = __add_event(list, idx, &attr, NULL, pmu->cpus);
655 return evsel ? 0 : -ENOMEM;
656 }
646 657
647 if (perf_pmu__check_alias(pmu, head_config, &unit, &scale)) 658 if (perf_pmu__check_alias(pmu, head_config, &info))
648 return -EINVAL; 659 return -EINVAL;
649 660
650 /* 661 /*
@@ -659,8 +670,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
659 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config), 670 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config),
660 pmu->cpus); 671 pmu->cpus);
661 if (evsel) { 672 if (evsel) {
662 evsel->unit = unit; 673 evsel->unit = info.unit;
663 evsel->scale = scale; 674 evsel->scale = info.scale;
664 } 675 }
665 676
666 return evsel ? 0 : -ENOMEM; 677 return evsel ? 0 : -ENOMEM;
@@ -973,7 +984,7 @@ int parse_filter(const struct option *opt, const char *str,
973 984
974 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 985 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
975 fprintf(stderr, 986 fprintf(stderr,
976 "-F option should follow a -e tracepoint option\n"); 987 "--filter option should follow a -e tracepoint option\n");
977 return -1; 988 return -1;
978 } 989 }
979 990
@@ -1006,9 +1017,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1006 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1017 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1007 char evt_path[MAXPATHLEN]; 1018 char evt_path[MAXPATHLEN];
1008 char dir_path[MAXPATHLEN]; 1019 char dir_path[MAXPATHLEN];
1020 char sbuf[STRERR_BUFSIZE];
1009 1021
1010 if (debugfs_valid_mountpoint(tracing_events_path)) { 1022 if (debugfs_valid_mountpoint(tracing_events_path)) {
1011 printf(" [ Tracepoints not available: %s ]\n", strerror(errno)); 1023 printf(" [ Tracepoints not available: %s ]\n",
1024 strerror_r(errno, sbuf, sizeof(sbuf)));
1012 return; 1025 return;
1013 } 1026 }
1014 1027
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 0bc87ba46bf3..55fab6ad609a 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -210,6 +210,16 @@ PE_NAME '/' event_config '/'
210 parse_events__free_terms($3); 210 parse_events__free_terms($3);
211 $$ = list; 211 $$ = list;
212} 212}
213|
214PE_NAME '/' '/'
215{
216 struct parse_events_evlist *data = _data;
217 struct list_head *list;
218
219 ALLOC_LIST(list);
220 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL));
221 $$ = list;
222}
213 223
214value_sym: 224value_sym:
215PE_VALUE_SYM_HW 225PE_VALUE_SYM_HW
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 7a811eb61f75..93a41ca96b8e 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -2,6 +2,8 @@
2#include <sys/types.h> 2#include <sys/types.h>
3#include <unistd.h> 3#include <unistd.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <stdbool.h>
6#include <stdarg.h>
5#include <dirent.h> 7#include <dirent.h>
6#include <api/fs/fs.h> 8#include <api/fs/fs.h>
7#include <locale.h> 9#include <locale.h>
@@ -14,8 +16,8 @@
14 16
15struct perf_pmu_alias { 17struct perf_pmu_alias {
16 char *name; 18 char *name;
17 struct list_head terms; 19 struct list_head terms; /* HEAD struct parse_events_term -> list */
18 struct list_head list; 20 struct list_head list; /* ELEM */
19 char unit[UNIT_MAX_LEN+1]; 21 char unit[UNIT_MAX_LEN+1];
20 double scale; 22 double scale;
21}; 23};
@@ -208,6 +210,19 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
208 return 0; 210 return 0;
209} 211}
210 212
213static inline bool pmu_alias_info_file(char *name)
214{
215 size_t len;
216
217 len = strlen(name);
218 if (len > 5 && !strcmp(name + len - 5, ".unit"))
219 return true;
220 if (len > 6 && !strcmp(name + len - 6, ".scale"))
221 return true;
222
223 return false;
224}
225
211/* 226/*
212 * Process all the sysfs attributes located under the directory 227 * Process all the sysfs attributes located under the directory
213 * specified in 'dir' parameter. 228 * specified in 'dir' parameter.
@@ -216,7 +231,6 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
216{ 231{
217 struct dirent *evt_ent; 232 struct dirent *evt_ent;
218 DIR *event_dir; 233 DIR *event_dir;
219 size_t len;
220 int ret = 0; 234 int ret = 0;
221 235
222 event_dir = opendir(dir); 236 event_dir = opendir(dir);
@@ -232,13 +246,9 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
232 continue; 246 continue;
233 247
234 /* 248 /*
235 * skip .unit and .scale info files 249 * skip info files parsed in perf_pmu__new_alias()
236 * parsed in perf_pmu__new_alias()
237 */ 250 */
238 len = strlen(name); 251 if (pmu_alias_info_file(name))
239 if (len > 5 && !strcmp(name + len - 5, ".unit"))
240 continue;
241 if (len > 6 && !strcmp(name + len - 6, ".scale"))
242 continue; 252 continue;
243 253
244 snprintf(path, PATH_MAX, "%s/%s", dir, name); 254 snprintf(path, PATH_MAX, "%s/%s", dir, name);
@@ -387,6 +397,12 @@ static struct cpu_map *pmu_cpumask(const char *name)
387 return cpus; 397 return cpus;
388} 398}
389 399
400struct perf_event_attr *__attribute__((weak))
401perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
402{
403 return NULL;
404}
405
390static struct perf_pmu *pmu_lookup(const char *name) 406static struct perf_pmu *pmu_lookup(const char *name)
391{ 407{
392 struct perf_pmu *pmu; 408 struct perf_pmu *pmu;
@@ -421,6 +437,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
421 pmu->name = strdup(name); 437 pmu->name = strdup(name);
422 pmu->type = type; 438 pmu->type = type;
423 list_add_tail(&pmu->list, &pmus); 439 list_add_tail(&pmu->list, &pmus);
440
441 pmu->default_config = perf_pmu__get_default_config(pmu);
442
424 return pmu; 443 return pmu;
425} 444}
426 445
@@ -479,28 +498,24 @@ pmu_find_format(struct list_head *formats, char *name)
479} 498}
480 499
481/* 500/*
482 * Returns value based on the format definition (format parameter) 501 * Sets value based on the format definition (format parameter)
483 * and unformated value (value parameter). 502 * and unformated value (value parameter).
484 *
485 * TODO maybe optimize a little ;)
486 */ 503 */
487static __u64 pmu_format_value(unsigned long *format, __u64 value) 504static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
505 bool zero)
488{ 506{
489 unsigned long fbit, vbit; 507 unsigned long fbit, vbit;
490 __u64 v = 0;
491 508
492 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 509 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
493 510
494 if (!test_bit(fbit, format)) 511 if (!test_bit(fbit, format))
495 continue; 512 continue;
496 513
497 if (!(value & (1llu << vbit++))) 514 if (value & (1llu << vbit++))
498 continue; 515 *v |= (1llu << fbit);
499 516 else if (zero)
500 v |= (1llu << fbit); 517 *v &= ~(1llu << fbit);
501 } 518 }
502
503 return v;
504} 519}
505 520
506/* 521/*
@@ -509,7 +524,8 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
509 */ 524 */
510static int pmu_config_term(struct list_head *formats, 525static int pmu_config_term(struct list_head *formats,
511 struct perf_event_attr *attr, 526 struct perf_event_attr *attr,
512 struct parse_events_term *term) 527 struct parse_events_term *term,
528 bool zero)
513{ 529{
514 struct perf_pmu_format *format; 530 struct perf_pmu_format *format;
515 __u64 *vp; 531 __u64 *vp;
@@ -548,18 +564,19 @@ static int pmu_config_term(struct list_head *formats,
548 * non-hardcoded terms, here's the place to translate 564 * non-hardcoded terms, here's the place to translate
549 * them into value. 565 * them into value.
550 */ 566 */
551 *vp |= pmu_format_value(format->bits, term->val.num); 567 pmu_format_value(format->bits, term->val.num, vp, zero);
552 return 0; 568 return 0;
553} 569}
554 570
555int perf_pmu__config_terms(struct list_head *formats, 571int perf_pmu__config_terms(struct list_head *formats,
556 struct perf_event_attr *attr, 572 struct perf_event_attr *attr,
557 struct list_head *head_terms) 573 struct list_head *head_terms,
574 bool zero)
558{ 575{
559 struct parse_events_term *term; 576 struct parse_events_term *term;
560 577
561 list_for_each_entry(term, head_terms, list) 578 list_for_each_entry(term, head_terms, list)
562 if (pmu_config_term(formats, attr, term)) 579 if (pmu_config_term(formats, attr, term, zero))
563 return -EINVAL; 580 return -EINVAL;
564 581
565 return 0; 582 return 0;
@@ -573,8 +590,10 @@ int perf_pmu__config_terms(struct list_head *formats,
573int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 590int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
574 struct list_head *head_terms) 591 struct list_head *head_terms)
575{ 592{
593 bool zero = !!pmu->default_config;
594
576 attr->type = pmu->type; 595 attr->type = pmu->type;
577 return perf_pmu__config_terms(&pmu->format, attr, head_terms); 596 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
578} 597}
579 598
580static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 599static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
@@ -634,7 +653,7 @@ static int check_unit_scale(struct perf_pmu_alias *alias,
634 * defined for the alias 653 * defined for the alias
635 */ 654 */
636int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 655int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
637 const char **unit, double *scale) 656 struct perf_pmu_info *info)
638{ 657{
639 struct parse_events_term *term, *h; 658 struct parse_events_term *term, *h;
640 struct perf_pmu_alias *alias; 659 struct perf_pmu_alias *alias;
@@ -644,8 +663,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
644 * Mark unit and scale as not set 663 * Mark unit and scale as not set
645 * (different from default values, see below) 664 * (different from default values, see below)
646 */ 665 */
647 *unit = NULL; 666 info->unit = NULL;
648 *scale = 0.0; 667 info->scale = 0.0;
649 668
650 list_for_each_entry_safe(term, h, head_terms, list) { 669 list_for_each_entry_safe(term, h, head_terms, list) {
651 alias = pmu_find_alias(pmu, term); 670 alias = pmu_find_alias(pmu, term);
@@ -655,7 +674,7 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
655 if (ret) 674 if (ret)
656 return ret; 675 return ret;
657 676
658 ret = check_unit_scale(alias, unit, scale); 677 ret = check_unit_scale(alias, &info->unit, &info->scale);
659 if (ret) 678 if (ret)
660 return ret; 679 return ret;
661 680
@@ -668,11 +687,11 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
668 * set defaults as for evsel 687 * set defaults as for evsel
669 * unit cannot left to NULL 688 * unit cannot left to NULL
670 */ 689 */
671 if (*unit == NULL) 690 if (info->unit == NULL)
672 *unit = ""; 691 info->unit = "";
673 692
674 if (*scale == 0.0) 693 if (info->scale == 0.0)
675 *scale = 1.0; 694 info->scale = 1.0;
676 695
677 return 0; 696 return 0;
678} 697}
@@ -794,3 +813,39 @@ bool pmu_have_event(const char *pname, const char *name)
794 } 813 }
795 return false; 814 return false;
796} 815}
816
817static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
818{
819 struct stat st;
820 char path[PATH_MAX];
821 const char *sysfs;
822
823 sysfs = sysfs__mountpoint();
824 if (!sysfs)
825 return NULL;
826
827 snprintf(path, PATH_MAX,
828 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
829
830 if (stat(path, &st) < 0)
831 return NULL;
832
833 return fopen(path, "r");
834}
835
836int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
837 ...)
838{
839 va_list args;
840 FILE *file;
841 int ret = EOF;
842
843 va_start(args, fmt);
844 file = perf_pmu__open_file(pmu, name);
845 if (file) {
846 ret = vfscanf(file, fmt, args);
847 fclose(file);
848 }
849 va_end(args);
850 return ret;
851}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index c14a543ce1f3..fe90a012c003 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -13,13 +13,21 @@ enum {
13 13
14#define PERF_PMU_FORMAT_BITS 64 14#define PERF_PMU_FORMAT_BITS 64
15 15
16struct perf_event_attr;
17
16struct perf_pmu { 18struct perf_pmu {
17 char *name; 19 char *name;
18 __u32 type; 20 __u32 type;
21 struct perf_event_attr *default_config;
19 struct cpu_map *cpus; 22 struct cpu_map *cpus;
20 struct list_head format; 23 struct list_head format; /* HEAD struct perf_pmu_format -> list */
21 struct list_head aliases; 24 struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
22 struct list_head list; 25 struct list_head list; /* ELEM */
26};
27
28struct perf_pmu_info {
29 const char *unit;
30 double scale;
23}; 31};
24 32
25struct perf_pmu *perf_pmu__find(const char *name); 33struct perf_pmu *perf_pmu__find(const char *name);
@@ -27,9 +35,10 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
27 struct list_head *head_terms); 35 struct list_head *head_terms);
28int perf_pmu__config_terms(struct list_head *formats, 36int perf_pmu__config_terms(struct list_head *formats,
29 struct perf_event_attr *attr, 37 struct perf_event_attr *attr,
30 struct list_head *head_terms); 38 struct list_head *head_terms,
39 bool zero);
31int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 40int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
32 const char **unit, double *scale); 41 struct perf_pmu_info *info);
33struct list_head *perf_pmu__alias(struct perf_pmu *pmu, 42struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
34 struct list_head *head_terms); 43 struct list_head *head_terms);
35int perf_pmu_wrap(void); 44int perf_pmu_wrap(void);
@@ -45,5 +54,11 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
45void print_pmu_events(const char *event_glob, bool name_only); 54void print_pmu_events(const char *event_glob, bool name_only);
46bool pmu_have_event(const char *pname, const char *name); 55bool pmu_have_event(const char *pname, const char *name);
47 56
57int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
58 ...) __attribute__((format(scanf, 3, 4)));
59
48int perf_pmu__test(void); 60int perf_pmu__test(void);
61
62struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
63
49#endif /* __PMU_H */ 64#endif /* __PMU_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9a0a1839a377..c150ca4343eb 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -79,7 +79,7 @@ static int init_symbol_maps(bool user_only)
79 int ret; 79 int ret;
80 80
81 symbol_conf.sort_by_name = true; 81 symbol_conf.sort_by_name = true;
82 ret = symbol__init(); 82 ret = symbol__init(NULL);
83 if (ret < 0) { 83 if (ret < 0) {
84 pr_debug("Failed to init symbol map.\n"); 84 pr_debug("Failed to init symbol map.\n");
85 goto out; 85 goto out;
@@ -184,7 +184,8 @@ static struct dso *kernel_get_module_dso(const char *module)
184 const char *vmlinux_name; 184 const char *vmlinux_name;
185 185
186 if (module) { 186 if (module) {
187 list_for_each_entry(dso, &host_machine->kernel_dsos, node) { 187 list_for_each_entry(dso, &host_machine->kernel_dsos.head,
188 node) {
188 if (strncmp(dso->short_name + 1, module, 189 if (strncmp(dso->short_name + 1, module,
189 dso->short_name_len - 2) == 0) 190 dso->short_name_len - 2) == 0)
190 goto found; 191 goto found;
@@ -258,21 +259,33 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
258#ifdef HAVE_DWARF_SUPPORT 259#ifdef HAVE_DWARF_SUPPORT
259 260
260/* Open new debuginfo of given module */ 261/* Open new debuginfo of given module */
261static struct debuginfo *open_debuginfo(const char *module) 262static struct debuginfo *open_debuginfo(const char *module, bool silent)
262{ 263{
263 const char *path = module; 264 const char *path = module;
265 struct debuginfo *ret;
264 266
265 if (!module || !strchr(module, '/')) { 267 if (!module || !strchr(module, '/')) {
266 path = kernel_get_module_path(module); 268 path = kernel_get_module_path(module);
267 if (!path) { 269 if (!path) {
268 pr_err("Failed to find path of %s module.\n", 270 if (!silent)
269 module ?: "kernel"); 271 pr_err("Failed to find path of %s module.\n",
272 module ?: "kernel");
270 return NULL; 273 return NULL;
271 } 274 }
272 } 275 }
273 return debuginfo__new(path); 276 ret = debuginfo__new(path);
277 if (!ret && !silent) {
278 pr_warning("The %s file has no debug information.\n", path);
279 if (!module || !strtailcmp(path, ".ko"))
280 pr_warning("Rebuild with CONFIG_DEBUG_INFO=y, ");
281 else
282 pr_warning("Rebuild with -g, ");
283 pr_warning("or install an appropriate debuginfo package.\n");
284 }
285 return ret;
274} 286}
275 287
288
276static int get_text_start_address(const char *exec, unsigned long *address) 289static int get_text_start_address(const char *exec, unsigned long *address)
277{ 290{
278 Elf *elf; 291 Elf *elf;
@@ -333,15 +346,13 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
333 pr_debug("try to find information at %" PRIx64 " in %s\n", addr, 346 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
334 tp->module ? : "kernel"); 347 tp->module ? : "kernel");
335 348
336 dinfo = open_debuginfo(tp->module); 349 dinfo = open_debuginfo(tp->module, verbose == 0);
337 if (dinfo) { 350 if (dinfo) {
338 ret = debuginfo__find_probe_point(dinfo, 351 ret = debuginfo__find_probe_point(dinfo,
339 (unsigned long)addr, pp); 352 (unsigned long)addr, pp);
340 debuginfo__delete(dinfo); 353 debuginfo__delete(dinfo);
341 } else { 354 } else
342 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", addr);
343 ret = -ENOENT; 355 ret = -ENOENT;
344 }
345 356
346 if (ret > 0) { 357 if (ret > 0) {
347 pp->retprobe = tp->retprobe; 358 pp->retprobe = tp->retprobe;
@@ -457,13 +468,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
457 struct debuginfo *dinfo; 468 struct debuginfo *dinfo;
458 int ntevs, ret = 0; 469 int ntevs, ret = 0;
459 470
460 dinfo = open_debuginfo(target); 471 dinfo = open_debuginfo(target, !need_dwarf);
461 472
462 if (!dinfo) { 473 if (!dinfo) {
463 if (need_dwarf) { 474 if (need_dwarf)
464 pr_warning("Failed to open debuginfo file.\n");
465 return -ENOENT; 475 return -ENOENT;
466 }
467 pr_debug("Could not open debuginfo. Try to use symbols.\n"); 476 pr_debug("Could not open debuginfo. Try to use symbols.\n");
468 return 0; 477 return 0;
469 } 478 }
@@ -565,7 +574,7 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
565 574
566static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) 575static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
567{ 576{
568 char buf[LINEBUF_SIZE]; 577 char buf[LINEBUF_SIZE], sbuf[STRERR_BUFSIZE];
569 const char *color = show_num ? "" : PERF_COLOR_BLUE; 578 const char *color = show_num ? "" : PERF_COLOR_BLUE;
570 const char *prefix = NULL; 579 const char *prefix = NULL;
571 580
@@ -585,7 +594,8 @@ static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
585 return 1; 594 return 1;
586error: 595error:
587 if (ferror(fp)) { 596 if (ferror(fp)) {
588 pr_warning("File read error: %s\n", strerror(errno)); 597 pr_warning("File read error: %s\n",
598 strerror_r(errno, sbuf, sizeof(sbuf)));
589 return -1; 599 return -1;
590 } 600 }
591 return 0; 601 return 0;
@@ -618,13 +628,12 @@ static int __show_line_range(struct line_range *lr, const char *module)
618 FILE *fp; 628 FILE *fp;
619 int ret; 629 int ret;
620 char *tmp; 630 char *tmp;
631 char sbuf[STRERR_BUFSIZE];
621 632
622 /* Search a line range */ 633 /* Search a line range */
623 dinfo = open_debuginfo(module); 634 dinfo = open_debuginfo(module, false);
624 if (!dinfo) { 635 if (!dinfo)
625 pr_warning("Failed to open debuginfo file.\n");
626 return -ENOENT; 636 return -ENOENT;
627 }
628 637
629 ret = debuginfo__find_line_range(dinfo, lr); 638 ret = debuginfo__find_line_range(dinfo, lr);
630 debuginfo__delete(dinfo); 639 debuginfo__delete(dinfo);
@@ -656,7 +665,7 @@ static int __show_line_range(struct line_range *lr, const char *module)
656 fp = fopen(lr->path, "r"); 665 fp = fopen(lr->path, "r");
657 if (fp == NULL) { 666 if (fp == NULL) {
658 pr_warning("Failed to open %s: %s\n", lr->path, 667 pr_warning("Failed to open %s: %s\n", lr->path,
659 strerror(errno)); 668 strerror_r(errno, sbuf, sizeof(sbuf)));
660 return -errno; 669 return -errno;
661 } 670 }
662 /* Skip to starting line number */ 671 /* Skip to starting line number */
@@ -689,11 +698,11 @@ end:
689 return ret; 698 return ret;
690} 699}
691 700
692int show_line_range(struct line_range *lr, const char *module) 701int show_line_range(struct line_range *lr, const char *module, bool user)
693{ 702{
694 int ret; 703 int ret;
695 704
696 ret = init_symbol_maps(false); 705 ret = init_symbol_maps(user);
697 if (ret < 0) 706 if (ret < 0)
698 return ret; 707 return ret;
699 ret = __show_line_range(lr, module); 708 ret = __show_line_range(lr, module);
@@ -768,13 +777,12 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
768 int i, ret = 0; 777 int i, ret = 0;
769 struct debuginfo *dinfo; 778 struct debuginfo *dinfo;
770 779
771 ret = init_symbol_maps(false); 780 ret = init_symbol_maps(pevs->uprobes);
772 if (ret < 0) 781 if (ret < 0)
773 return ret; 782 return ret;
774 783
775 dinfo = open_debuginfo(module); 784 dinfo = open_debuginfo(module, false);
776 if (!dinfo) { 785 if (!dinfo) {
777 pr_warning("Failed to open debuginfo file.\n");
778 ret = -ENOENT; 786 ret = -ENOENT;
779 goto out; 787 goto out;
780 } 788 }
@@ -815,7 +823,8 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
815} 823}
816 824
817int show_line_range(struct line_range *lr __maybe_unused, 825int show_line_range(struct line_range *lr __maybe_unused,
818 const char *module __maybe_unused) 826 const char *module __maybe_unused,
827 bool user __maybe_unused)
819{ 828{
820 pr_warning("Debuginfo-analysis is not supported.\n"); 829 pr_warning("Debuginfo-analysis is not supported.\n");
821 return -ENOSYS; 830 return -ENOSYS;
@@ -1405,8 +1414,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1405 1414
1406 return tmp - buf; 1415 return tmp - buf;
1407error: 1416error:
1408 pr_debug("Failed to synthesize perf probe argument: %s\n", 1417 pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
1409 strerror(-ret));
1410 return ret; 1418 return ret;
1411} 1419}
1412 1420
@@ -1455,8 +1463,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1455 1463
1456 return buf; 1464 return buf;
1457error: 1465error:
1458 pr_debug("Failed to synthesize perf probe point: %s\n", 1466 pr_debug("Failed to synthesize perf probe point: %d\n", ret);
1459 strerror(-ret));
1460 free(buf); 1467 free(buf);
1461 return NULL; 1468 return NULL;
1462} 1469}
@@ -1780,10 +1787,11 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1780 memset(tev, 0, sizeof(*tev)); 1787 memset(tev, 0, sizeof(*tev));
1781} 1788}
1782 1789
1783static void print_warn_msg(const char *file, bool is_kprobe) 1790static void print_open_warning(int err, bool is_kprobe)
1784{ 1791{
1792 char sbuf[STRERR_BUFSIZE];
1785 1793
1786 if (errno == ENOENT) { 1794 if (err == -ENOENT) {
1787 const char *config; 1795 const char *config;
1788 1796
1789 if (!is_kprobe) 1797 if (!is_kprobe)
@@ -1791,25 +1799,43 @@ static void print_warn_msg(const char *file, bool is_kprobe)
1791 else 1799 else
1792 config = "CONFIG_KPROBE_EVENTS"; 1800 config = "CONFIG_KPROBE_EVENTS";
1793 1801
1794 pr_warning("%s file does not exist - please rebuild kernel" 1802 pr_warning("%cprobe_events file does not exist"
1795 " with %s.\n", file, config); 1803 " - please rebuild kernel with %s.\n",
1796 } else 1804 is_kprobe ? 'k' : 'u', config);
1797 pr_warning("Failed to open %s file: %s\n", file, 1805 } else if (err == -ENOTSUP)
1798 strerror(errno)); 1806 pr_warning("Debugfs is not mounted.\n");
1807 else
1808 pr_warning("Failed to open %cprobe_events: %s\n",
1809 is_kprobe ? 'k' : 'u',
1810 strerror_r(-err, sbuf, sizeof(sbuf)));
1811}
1812
1813static void print_both_open_warning(int kerr, int uerr)
1814{
1815 /* Both kprobes and uprobes are disabled, warn it. */
1816 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
1817 pr_warning("Debugfs is not mounted.\n");
1818 else if (kerr == -ENOENT && uerr == -ENOENT)
1819 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1820 "or/and CONFIG_UPROBE_EVENTS.\n");
1821 else {
1822 char sbuf[STRERR_BUFSIZE];
1823 pr_warning("Failed to open kprobe events: %s.\n",
1824 strerror_r(-kerr, sbuf, sizeof(sbuf)));
1825 pr_warning("Failed to open uprobe events: %s.\n",
1826 strerror_r(-uerr, sbuf, sizeof(sbuf)));
1827 }
1799} 1828}
1800 1829
1801static int open_probe_events(const char *trace_file, bool readwrite, 1830static int open_probe_events(const char *trace_file, bool readwrite)
1802 bool is_kprobe)
1803{ 1831{
1804 char buf[PATH_MAX]; 1832 char buf[PATH_MAX];
1805 const char *__debugfs; 1833 const char *__debugfs;
1806 int ret; 1834 int ret;
1807 1835
1808 __debugfs = debugfs_find_mountpoint(); 1836 __debugfs = debugfs_find_mountpoint();
1809 if (__debugfs == NULL) { 1837 if (__debugfs == NULL)
1810 pr_warning("Debugfs is not mounted.\n"); 1838 return -ENOTSUP;
1811 return -ENOENT;
1812 }
1813 1839
1814 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 1840 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
1815 if (ret >= 0) { 1841 if (ret >= 0) {
@@ -1820,19 +1846,19 @@ static int open_probe_events(const char *trace_file, bool readwrite,
1820 ret = open(buf, O_RDONLY, 0); 1846 ret = open(buf, O_RDONLY, 0);
1821 1847
1822 if (ret < 0) 1848 if (ret < 0)
1823 print_warn_msg(buf, is_kprobe); 1849 ret = -errno;
1824 } 1850 }
1825 return ret; 1851 return ret;
1826} 1852}
1827 1853
1828static int open_kprobe_events(bool readwrite) 1854static int open_kprobe_events(bool readwrite)
1829{ 1855{
1830 return open_probe_events("tracing/kprobe_events", readwrite, true); 1856 return open_probe_events("tracing/kprobe_events", readwrite);
1831} 1857}
1832 1858
1833static int open_uprobe_events(bool readwrite) 1859static int open_uprobe_events(bool readwrite)
1834{ 1860{
1835 return open_probe_events("tracing/uprobe_events", readwrite, false); 1861 return open_probe_events("tracing/uprobe_events", readwrite);
1836} 1862}
1837 1863
1838/* Get raw string list of current kprobe_events or uprobe_events */ 1864/* Get raw string list of current kprobe_events or uprobe_events */
@@ -1857,7 +1883,7 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
1857 p[idx] = '\0'; 1883 p[idx] = '\0';
1858 ret = strlist__add(sl, buf); 1884 ret = strlist__add(sl, buf);
1859 if (ret < 0) { 1885 if (ret < 0) {
1860 pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1886 pr_debug("strlist__add failed (%d)\n", ret);
1861 strlist__delete(sl); 1887 strlist__delete(sl);
1862 return NULL; 1888 return NULL;
1863 } 1889 }
@@ -1916,7 +1942,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1916 1942
1917 rawlist = get_probe_trace_command_rawlist(fd); 1943 rawlist = get_probe_trace_command_rawlist(fd);
1918 if (!rawlist) 1944 if (!rawlist)
1919 return -ENOENT; 1945 return -ENOMEM;
1920 1946
1921 strlist__for_each(ent, rawlist) { 1947 strlist__for_each(ent, rawlist) {
1922 ret = parse_probe_trace_command(ent->s, &tev); 1948 ret = parse_probe_trace_command(ent->s, &tev);
@@ -1940,27 +1966,34 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1940/* List up current perf-probe events */ 1966/* List up current perf-probe events */
1941int show_perf_probe_events(void) 1967int show_perf_probe_events(void)
1942{ 1968{
1943 int fd, ret; 1969 int kp_fd, up_fd, ret;
1944 1970
1945 setup_pager(); 1971 setup_pager();
1946 fd = open_kprobe_events(false);
1947
1948 if (fd < 0)
1949 return fd;
1950 1972
1951 ret = init_symbol_maps(false); 1973 ret = init_symbol_maps(false);
1952 if (ret < 0) 1974 if (ret < 0)
1953 return ret; 1975 return ret;
1954 1976
1955 ret = __show_perf_probe_events(fd, true); 1977 kp_fd = open_kprobe_events(false);
1956 close(fd); 1978 if (kp_fd >= 0) {
1979 ret = __show_perf_probe_events(kp_fd, true);
1980 close(kp_fd);
1981 if (ret < 0)
1982 goto out;
1983 }
1957 1984
1958 fd = open_uprobe_events(false); 1985 up_fd = open_uprobe_events(false);
1959 if (fd >= 0) { 1986 if (kp_fd < 0 && up_fd < 0) {
1960 ret = __show_perf_probe_events(fd, false); 1987 print_both_open_warning(kp_fd, up_fd);
1961 close(fd); 1988 ret = kp_fd;
1989 goto out;
1962 } 1990 }
1963 1991
1992 if (up_fd >= 0) {
1993 ret = __show_perf_probe_events(up_fd, false);
1994 close(up_fd);
1995 }
1996out:
1964 exit_symbol_maps(); 1997 exit_symbol_maps();
1965 return ret; 1998 return ret;
1966} 1999}
@@ -1976,6 +2009,8 @@ static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1976 2009
1977 memset(&tev, 0, sizeof(tev)); 2010 memset(&tev, 0, sizeof(tev));
1978 rawlist = get_probe_trace_command_rawlist(fd); 2011 rawlist = get_probe_trace_command_rawlist(fd);
2012 if (!rawlist)
2013 return NULL;
1979 sl = strlist__new(true, NULL); 2014 sl = strlist__new(true, NULL);
1980 strlist__for_each(ent, rawlist) { 2015 strlist__for_each(ent, rawlist) {
1981 ret = parse_probe_trace_command(ent->s, &tev); 2016 ret = parse_probe_trace_command(ent->s, &tev);
@@ -2005,6 +2040,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2005{ 2040{
2006 int ret = 0; 2041 int ret = 0;
2007 char *buf = synthesize_probe_trace_command(tev); 2042 char *buf = synthesize_probe_trace_command(tev);
2043 char sbuf[STRERR_BUFSIZE];
2008 2044
2009 if (!buf) { 2045 if (!buf) {
2010 pr_debug("Failed to synthesize probe trace event.\n"); 2046 pr_debug("Failed to synthesize probe trace event.\n");
@@ -2016,7 +2052,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2016 ret = write(fd, buf, strlen(buf)); 2052 ret = write(fd, buf, strlen(buf));
2017 if (ret <= 0) 2053 if (ret <= 0)
2018 pr_warning("Failed to write event: %s\n", 2054 pr_warning("Failed to write event: %s\n",
2019 strerror(errno)); 2055 strerror_r(errno, sbuf, sizeof(sbuf)));
2020 } 2056 }
2021 free(buf); 2057 free(buf);
2022 return ret; 2058 return ret;
@@ -2030,7 +2066,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2030 /* Try no suffix */ 2066 /* Try no suffix */
2031 ret = e_snprintf(buf, len, "%s", base); 2067 ret = e_snprintf(buf, len, "%s", base);
2032 if (ret < 0) { 2068 if (ret < 0) {
2033 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2069 pr_debug("snprintf() failed: %d\n", ret);
2034 return ret; 2070 return ret;
2035 } 2071 }
2036 if (!strlist__has_entry(namelist, buf)) 2072 if (!strlist__has_entry(namelist, buf))
@@ -2046,7 +2082,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2046 for (i = 1; i < MAX_EVENT_INDEX; i++) { 2082 for (i = 1; i < MAX_EVENT_INDEX; i++) {
2047 ret = e_snprintf(buf, len, "%s_%d", base, i); 2083 ret = e_snprintf(buf, len, "%s_%d", base, i);
2048 if (ret < 0) { 2084 if (ret < 0) {
2049 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2085 pr_debug("snprintf() failed: %d\n", ret);
2050 return ret; 2086 return ret;
2051 } 2087 }
2052 if (!strlist__has_entry(namelist, buf)) 2088 if (!strlist__has_entry(namelist, buf))
@@ -2075,8 +2111,11 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2075 else 2111 else
2076 fd = open_kprobe_events(true); 2112 fd = open_kprobe_events(true);
2077 2113
2078 if (fd < 0) 2114 if (fd < 0) {
2115 print_open_warning(fd, !pev->uprobes);
2079 return fd; 2116 return fd;
2117 }
2118
2080 /* Get current event names */ 2119 /* Get current event names */
2081 namelist = get_probe_trace_event_names(fd, false); 2120 namelist = get_probe_trace_event_names(fd, false);
2082 if (!namelist) { 2121 if (!namelist) {
@@ -2408,7 +2447,8 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
2408 printf("Removed event: %s\n", ent->s); 2447 printf("Removed event: %s\n", ent->s);
2409 return 0; 2448 return 0;
2410error: 2449error:
2411 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 2450 pr_warning("Failed to delete event: %s\n",
2451 strerror_r(-ret, buf, sizeof(buf)));
2412 return ret; 2452 return ret;
2413} 2453}
2414 2454
@@ -2449,15 +2489,18 @@ int del_perf_probe_events(struct strlist *dellist)
2449 2489
2450 /* Get current event names */ 2490 /* Get current event names */
2451 kfd = open_kprobe_events(true); 2491 kfd = open_kprobe_events(true);
2452 if (kfd < 0) 2492 if (kfd >= 0)
2453 return kfd; 2493 namelist = get_probe_trace_event_names(kfd, true);
2454 2494
2455 namelist = get_probe_trace_event_names(kfd, true);
2456 ufd = open_uprobe_events(true); 2495 ufd = open_uprobe_events(true);
2457
2458 if (ufd >= 0) 2496 if (ufd >= 0)
2459 unamelist = get_probe_trace_event_names(ufd, true); 2497 unamelist = get_probe_trace_event_names(ufd, true);
2460 2498
2499 if (kfd < 0 && ufd < 0) {
2500 print_both_open_warning(kfd, ufd);
2501 goto error;
2502 }
2503
2461 if (namelist == NULL && unamelist == NULL) 2504 if (namelist == NULL && unamelist == NULL)
2462 goto error; 2505 goto error;
2463 2506
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 776c9347a3b6..e01e9943139f 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -128,7 +128,8 @@ extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
128 bool force_add); 128 bool force_add);
129extern int del_perf_probe_events(struct strlist *dellist); 129extern int del_perf_probe_events(struct strlist *dellist);
130extern int show_perf_probe_events(void); 130extern int show_perf_probe_events(void);
131extern int show_line_range(struct line_range *lr, const char *module); 131extern int show_line_range(struct line_range *lr, const char *module,
132 bool user);
132extern int show_available_vars(struct perf_probe_event *pevs, int npevs, 133extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
133 int max_probe_points, const char *module, 134 int max_probe_points, const char *module,
134 struct strfilter *filter, bool externs); 135 struct strfilter *filter, bool externs);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index dca9145d704c..c7918f83b300 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -281,6 +281,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref; 281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
282 Dwarf_Die type; 282 Dwarf_Die type;
283 char buf[16]; 283 char buf[16];
284 char sbuf[STRERR_BUFSIZE];
284 int bsize, boffs, total; 285 int bsize, boffs, total;
285 int ret; 286 int ret;
286 287
@@ -367,7 +368,7 @@ formatted:
367 if (ret >= 16) 368 if (ret >= 16)
368 ret = -E2BIG; 369 ret = -E2BIG;
369 pr_warning("Failed to convert variable type: %s\n", 370 pr_warning("Failed to convert variable type: %s\n",
370 strerror(-ret)); 371 strerror_r(-ret, sbuf, sizeof(sbuf)));
371 return ret; 372 return ret;
372 } 373 }
373 tvar->type = strdup(buf); 374 tvar->type = strdup(buf);
@@ -608,14 +609,18 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
608 return -EINVAL; 609 return -EINVAL;
609 } 610 }
610 611
611 /* Get an appropriate symbol from symtab */ 612 symbol = dwarf_diename(sp_die);
612 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
613 if (!symbol) { 613 if (!symbol) {
614 pr_warning("Failed to find symbol at 0x%lx\n", 614 /* Try to get the symbol name from symtab */
615 (unsigned long)paddr); 615 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
616 return -ENOENT; 616 if (!symbol) {
617 pr_warning("Failed to find symbol at 0x%lx\n",
618 (unsigned long)paddr);
619 return -ENOENT;
620 }
621 eaddr = sym.st_value;
617 } 622 }
618 tp->offset = (unsigned long)(paddr - sym.st_value); 623 tp->offset = (unsigned long)(paddr - eaddr);
619 tp->address = (unsigned long)paddr; 624 tp->address = (unsigned long)paddr;
620 tp->symbol = strdup(symbol); 625 tp->symbol = strdup(symbol);
621 if (!tp->symbol) 626 if (!tp->symbol)
@@ -779,10 +784,12 @@ static int find_lazy_match_lines(struct intlist *list,
779 size_t line_len; 784 size_t line_len;
780 ssize_t len; 785 ssize_t len;
781 int count = 0, linenum = 1; 786 int count = 0, linenum = 1;
787 char sbuf[STRERR_BUFSIZE];
782 788
783 fp = fopen(fname, "r"); 789 fp = fopen(fname, "r");
784 if (!fp) { 790 if (!fp) {
785 pr_warning("Failed to open %s: %s\n", fname, strerror(errno)); 791 pr_warning("Failed to open %s: %s\n", fname,
792 strerror_r(errno, sbuf, sizeof(sbuf)));
786 return -errno; 793 return -errno;
787 } 794 }
788 795
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 12aa9b0d0ba1..3dda85ca50c1 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -736,7 +736,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) 736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
737 return NULL; 737 return NULL;
738 738
739 n = poll(evlist->pollfd, evlist->nr_fds, timeout); 739 n = perf_evlist__poll(evlist, timeout);
740 if (n < 0) { 740 if (n < 0) {
741 PyErr_SetFromErrno(PyExc_OSError); 741 PyErr_SetFromErrno(PyExc_OSError);
742 return NULL; 742 return NULL;
@@ -753,9 +753,9 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
753 PyObject *list = PyList_New(0); 753 PyObject *list = PyList_New(0);
754 int i; 754 int i;
755 755
756 for (i = 0; i < evlist->nr_fds; ++i) { 756 for (i = 0; i < evlist->pollfd.nr; ++i) {
757 PyObject *file; 757 PyObject *file;
758 FILE *fp = fdopen(evlist->pollfd[i].fd, "r"); 758 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
759 759
760 if (fp == NULL) 760 if (fp == NULL)
761 goto free_list; 761 goto free_list;
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index fe8079edbdc1..cf69325b985f 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -14,6 +14,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
14 struct perf_evsel *evsel; 14 struct perf_evsel *evsel;
15 unsigned long flags = perf_event_open_cloexec_flag(); 15 unsigned long flags = perf_event_open_cloexec_flag();
16 int err = -EAGAIN, fd; 16 int err = -EAGAIN, fd;
17 static pid_t pid = -1;
17 18
18 evlist = perf_evlist__new(); 19 evlist = perf_evlist__new();
19 if (!evlist) 20 if (!evlist)
@@ -24,14 +25,22 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
24 25
25 evsel = perf_evlist__first(evlist); 26 evsel = perf_evlist__first(evlist);
26 27
27 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 28 while (1) {
28 if (fd < 0) 29 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
29 goto out_delete; 30 if (fd < 0) {
31 if (pid == -1 && errno == EACCES) {
32 pid = 0;
33 continue;
34 }
35 goto out_delete;
36 }
37 break;
38 }
30 close(fd); 39 close(fd);
31 40
32 fn(evsel); 41 fn(evsel);
33 42
34 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 43 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
35 if (fd < 0) { 44 if (fd < 0) {
36 if (errno == EINVAL) 45 if (errno == EINVAL)
37 err = -EINVAL; 46 err = -EINVAL;
@@ -47,7 +56,7 @@ out_delete:
47 56
48static bool perf_probe_api(setup_probe_fn_t fn) 57static bool perf_probe_api(setup_probe_fn_t fn)
49{ 58{
50 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock", NULL}; 59 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL};
51 struct cpu_map *cpus; 60 struct cpu_map *cpus;
52 int cpu, ret, i = 0; 61 int cpu, ret, i = 0;
53 62
@@ -106,7 +115,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
106 115
107 evlist__for_each(evlist, evsel) { 116 evlist__for_each(evlist, evsel) {
108 perf_evsel__config(evsel, opts); 117 perf_evsel__config(evsel, opts);
109 if (!evsel->idx && use_comm_exec) 118 if (evsel->tracking && use_comm_exec)
110 evsel->attr.comm_exec = 1; 119 evsel->attr.comm_exec = 1;
111 } 120 }
112 121
@@ -201,6 +210,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
201 struct perf_evsel *evsel; 210 struct perf_evsel *evsel;
202 int err, fd, cpu; 211 int err, fd, cpu;
203 bool ret = false; 212 bool ret = false;
213 pid_t pid = -1;
204 214
205 temp_evlist = perf_evlist__new(); 215 temp_evlist = perf_evlist__new();
206 if (!temp_evlist) 216 if (!temp_evlist)
@@ -221,12 +231,20 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
221 cpu = evlist->cpus->map[0]; 231 cpu = evlist->cpus->map[0];
222 } 232 }
223 233
224 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 234 while (1) {
225 perf_event_open_cloexec_flag()); 235 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1,
226 if (fd >= 0) { 236 perf_event_open_cloexec_flag());
227 close(fd); 237 if (fd < 0) {
228 ret = true; 238 if (pid == -1 && errno == EACCES) {
239 pid = 0;
240 continue;
241 }
242 goto out_delete;
243 }
244 break;
229 } 245 }
246 close(fd);
247 ret = true;
230 248
231out_delete: 249out_delete:
232 perf_evlist__delete(temp_evlist); 250 perf_evlist__delete(temp_evlist);
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index da8e9b285f51..34622b53e733 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -1,6 +1,7 @@
1#include "cache.h" 1#include "cache.h"
2#include "run-command.h" 2#include "run-command.h"
3#include "exec_cmd.h" 3#include "exec_cmd.h"
4#include "debug.h"
4 5
5static inline void close_pair(int fd[2]) 6static inline void close_pair(int fd[2])
6{ 7{
@@ -19,6 +20,7 @@ int start_command(struct child_process *cmd)
19{ 20{
20 int need_in, need_out, need_err; 21 int need_in, need_out, need_err;
21 int fdin[2], fdout[2], fderr[2]; 22 int fdin[2], fdout[2], fderr[2];
23 char sbuf[STRERR_BUFSIZE];
22 24
23 /* 25 /*
24 * In case of errors we must keep the promise to close FDs 26 * In case of errors we must keep the promise to close FDs
@@ -99,7 +101,7 @@ int start_command(struct child_process *cmd)
99 101
100 if (cmd->dir && chdir(cmd->dir)) 102 if (cmd->dir && chdir(cmd->dir))
101 die("exec %s: cd to %s failed (%s)", cmd->argv[0], 103 die("exec %s: cd to %s failed (%s)", cmd->argv[0],
102 cmd->dir, strerror(errno)); 104 cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf)));
103 if (cmd->env) { 105 if (cmd->env) {
104 for (; *cmd->env; cmd->env++) { 106 for (; *cmd->env; cmd->env++) {
105 if (strchr(*cmd->env, '=')) 107 if (strchr(*cmd->env, '='))
@@ -153,6 +155,8 @@ int start_command(struct child_process *cmd)
153 155
154static int wait_or_whine(pid_t pid) 156static int wait_or_whine(pid_t pid)
155{ 157{
158 char sbuf[STRERR_BUFSIZE];
159
156 for (;;) { 160 for (;;) {
157 int status, code; 161 int status, code;
158 pid_t waiting = waitpid(pid, &status, 0); 162 pid_t waiting = waitpid(pid, &status, 0);
@@ -160,7 +164,8 @@ static int wait_or_whine(pid_t pid)
160 if (waiting < 0) { 164 if (waiting < 0) {
161 if (errno == EINTR) 165 if (errno == EINTR)
162 continue; 166 continue;
163 error("waitpid failed (%s)", strerror(errno)); 167 error("waitpid failed (%s)",
168 strerror_r(errno, sbuf, sizeof(sbuf)));
164 return -ERR_RUN_COMMAND_WAITPID; 169 return -ERR_RUN_COMMAND_WAITPID;
165 } 170 }
166 if (waiting != pid) 171 if (waiting != pid)
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b2dba9c0a3a1..0a01bac4ce02 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -432,6 +432,11 @@ error:
432 return err; 432 return err;
433} 433}
434 434
435static int perl_flush_script(void)
436{
437 return 0;
438}
439
435/* 440/*
436 * Stop trace script 441 * Stop trace script
437 */ 442 */
@@ -633,6 +638,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
633struct scripting_ops perl_scripting_ops = { 638struct scripting_ops perl_scripting_ops = {
634 .name = "Perl", 639 .name = "Perl",
635 .start_script = perl_start_script, 640 .start_script = perl_start_script,
641 .flush_script = perl_flush_script,
636 .stop_script = perl_stop_script, 642 .stop_script = perl_stop_script,
637 .process_event = perl_process_event, 643 .process_event = perl_process_event,
638 .generate_script = perl_generate_script, 644 .generate_script = perl_generate_script,
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cbce2545da45..56ba07cce549 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -73,6 +73,35 @@ static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObj
73 Py_DECREF(val); 73 Py_DECREF(val);
74} 74}
75 75
76static PyObject *get_handler(const char *handler_name)
77{
78 PyObject *handler;
79
80 handler = PyDict_GetItemString(main_dict, handler_name);
81 if (handler && !PyCallable_Check(handler))
82 return NULL;
83 return handler;
84}
85
86static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
87{
88 PyObject *retval;
89
90 retval = PyObject_CallObject(handler, args);
91 if (retval == NULL)
92 handler_call_die(die_msg);
93 Py_DECREF(retval);
94}
95
96static void try_call_object(const char *handler_name, PyObject *args)
97{
98 PyObject *handler;
99
100 handler = get_handler(handler_name);
101 if (handler)
102 call_object(handler, args, handler_name);
103}
104
76static void define_value(enum print_arg_type field_type, 105static void define_value(enum print_arg_type field_type,
77 const char *ev_name, 106 const char *ev_name,
78 const char *field_name, 107 const char *field_name,
@@ -80,7 +109,7 @@ static void define_value(enum print_arg_type field_type,
80 const char *field_str) 109 const char *field_str)
81{ 110{
82 const char *handler_name = "define_flag_value"; 111 const char *handler_name = "define_flag_value";
83 PyObject *handler, *t, *retval; 112 PyObject *t;
84 unsigned long long value; 113 unsigned long long value;
85 unsigned n = 0; 114 unsigned n = 0;
86 115
@@ -98,13 +127,7 @@ static void define_value(enum print_arg_type field_type,
98 PyTuple_SetItem(t, n++, PyInt_FromLong(value)); 127 PyTuple_SetItem(t, n++, PyInt_FromLong(value));
99 PyTuple_SetItem(t, n++, PyString_FromString(field_str)); 128 PyTuple_SetItem(t, n++, PyString_FromString(field_str));
100 129
101 handler = PyDict_GetItemString(main_dict, handler_name); 130 try_call_object(handler_name, t);
102 if (handler && PyCallable_Check(handler)) {
103 retval = PyObject_CallObject(handler, t);
104 if (retval == NULL)
105 handler_call_die(handler_name);
106 Py_DECREF(retval);
107 }
108 131
109 Py_DECREF(t); 132 Py_DECREF(t);
110} 133}
@@ -127,7 +150,7 @@ static void define_field(enum print_arg_type field_type,
127 const char *delim) 150 const char *delim)
128{ 151{
129 const char *handler_name = "define_flag_field"; 152 const char *handler_name = "define_flag_field";
130 PyObject *handler, *t, *retval; 153 PyObject *t;
131 unsigned n = 0; 154 unsigned n = 0;
132 155
133 if (field_type == PRINT_SYMBOL) 156 if (field_type == PRINT_SYMBOL)
@@ -145,13 +168,7 @@ static void define_field(enum print_arg_type field_type,
145 if (field_type == PRINT_FLAGS) 168 if (field_type == PRINT_FLAGS)
146 PyTuple_SetItem(t, n++, PyString_FromString(delim)); 169 PyTuple_SetItem(t, n++, PyString_FromString(delim));
147 170
148 handler = PyDict_GetItemString(main_dict, handler_name); 171 try_call_object(handler_name, t);
149 if (handler && PyCallable_Check(handler)) {
150 retval = PyObject_CallObject(handler, t);
151 if (retval == NULL)
152 handler_call_die(handler_name);
153 Py_DECREF(retval);
154 }
155 172
156 Py_DECREF(t); 173 Py_DECREF(t);
157} 174}
@@ -362,7 +379,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
362 struct thread *thread, 379 struct thread *thread,
363 struct addr_location *al) 380 struct addr_location *al)
364{ 381{
365 PyObject *handler, *retval, *context, *t, *obj, *callchain; 382 PyObject *handler, *context, *t, *obj, *callchain;
366 PyObject *dict = NULL; 383 PyObject *dict = NULL;
367 static char handler_name[256]; 384 static char handler_name[256];
368 struct format_field *field; 385 struct format_field *field;
@@ -387,9 +404,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
387 404
388 sprintf(handler_name, "%s__%s", event->system, event->name); 405 sprintf(handler_name, "%s__%s", event->system, event->name);
389 406
390 handler = PyDict_GetItemString(main_dict, handler_name); 407 handler = get_handler(handler_name);
391 if (handler && !PyCallable_Check(handler))
392 handler = NULL;
393 if (!handler) { 408 if (!handler) {
394 dict = PyDict_New(); 409 dict = PyDict_New();
395 if (!dict) 410 if (!dict)
@@ -450,19 +465,9 @@ static void python_process_tracepoint(struct perf_sample *sample,
450 Py_FatalError("error resizing Python tuple"); 465 Py_FatalError("error resizing Python tuple");
451 466
452 if (handler) { 467 if (handler) {
453 retval = PyObject_CallObject(handler, t); 468 call_object(handler, t, handler_name);
454 if (retval == NULL)
455 handler_call_die(handler_name);
456 Py_DECREF(retval);
457 } else { 469 } else {
458 handler = PyDict_GetItemString(main_dict, "trace_unhandled"); 470 try_call_object("trace_unhandled", t);
459 if (handler && PyCallable_Check(handler)) {
460
461 retval = PyObject_CallObject(handler, t);
462 if (retval == NULL)
463 handler_call_die("trace_unhandled");
464 Py_DECREF(retval);
465 }
466 Py_DECREF(dict); 471 Py_DECREF(dict);
467 } 472 }
468 473
@@ -474,7 +479,7 @@ static void python_process_general_event(struct perf_sample *sample,
474 struct thread *thread, 479 struct thread *thread,
475 struct addr_location *al) 480 struct addr_location *al)
476{ 481{
477 PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample; 482 PyObject *handler, *t, *dict, *callchain, *dict_sample;
478 static char handler_name[64]; 483 static char handler_name[64];
479 unsigned n = 0; 484 unsigned n = 0;
480 485
@@ -496,8 +501,8 @@ static void python_process_general_event(struct perf_sample *sample,
496 501
497 snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); 502 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
498 503
499 handler = PyDict_GetItemString(main_dict, handler_name); 504 handler = get_handler(handler_name);
500 if (!handler || !PyCallable_Check(handler)) 505 if (!handler)
501 goto exit; 506 goto exit;
502 507
503 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 508 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
@@ -539,10 +544,7 @@ static void python_process_general_event(struct perf_sample *sample,
539 if (_PyTuple_Resize(&t, n) == -1) 544 if (_PyTuple_Resize(&t, n) == -1)
540 Py_FatalError("error resizing Python tuple"); 545 Py_FatalError("error resizing Python tuple");
541 546
542 retval = PyObject_CallObject(handler, t); 547 call_object(handler, t, handler_name);
543 if (retval == NULL)
544 handler_call_die(handler_name);
545 Py_DECREF(retval);
546exit: 548exit:
547 Py_DECREF(dict); 549 Py_DECREF(dict);
548 Py_DECREF(t); 550 Py_DECREF(t);
@@ -566,36 +568,24 @@ static void python_process_event(union perf_event *event __maybe_unused,
566 568
567static int run_start_sub(void) 569static int run_start_sub(void)
568{ 570{
569 PyObject *handler, *retval;
570 int err = 0;
571
572 main_module = PyImport_AddModule("__main__"); 571 main_module = PyImport_AddModule("__main__");
573 if (main_module == NULL) 572 if (main_module == NULL)
574 return -1; 573 return -1;
575 Py_INCREF(main_module); 574 Py_INCREF(main_module);
576 575
577 main_dict = PyModule_GetDict(main_module); 576 main_dict = PyModule_GetDict(main_module);
578 if (main_dict == NULL) { 577 if (main_dict == NULL)
579 err = -1;
580 goto error; 578 goto error;
581 }
582 Py_INCREF(main_dict); 579 Py_INCREF(main_dict);
583 580
584 handler = PyDict_GetItemString(main_dict, "trace_begin"); 581 try_call_object("trace_begin", NULL);
585 if (handler == NULL || !PyCallable_Check(handler))
586 goto out;
587 582
588 retval = PyObject_CallObject(handler, NULL); 583 return 0;
589 if (retval == NULL)
590 handler_call_die("trace_begin");
591 584
592 Py_DECREF(retval);
593 return err;
594error: 585error:
595 Py_XDECREF(main_dict); 586 Py_XDECREF(main_dict);
596 Py_XDECREF(main_module); 587 Py_XDECREF(main_module);
597out: 588 return -1;
598 return err;
599} 589}
600 590
601/* 591/*
@@ -649,28 +639,23 @@ error:
649 return err; 639 return err;
650} 640}
651 641
642static int python_flush_script(void)
643{
644 return 0;
645}
646
652/* 647/*
653 * Stop trace script 648 * Stop trace script
654 */ 649 */
655static int python_stop_script(void) 650static int python_stop_script(void)
656{ 651{
657 PyObject *handler, *retval; 652 try_call_object("trace_end", NULL);
658 int err = 0;
659 653
660 handler = PyDict_GetItemString(main_dict, "trace_end");
661 if (handler == NULL || !PyCallable_Check(handler))
662 goto out;
663
664 retval = PyObject_CallObject(handler, NULL);
665 if (retval == NULL)
666 handler_call_die("trace_end");
667 Py_DECREF(retval);
668out:
669 Py_XDECREF(main_dict); 654 Py_XDECREF(main_dict);
670 Py_XDECREF(main_module); 655 Py_XDECREF(main_module);
671 Py_Finalize(); 656 Py_Finalize();
672 657
673 return err; 658 return 0;
674} 659}
675 660
676static int python_generate_script(struct pevent *pevent, const char *outfile) 661static int python_generate_script(struct pevent *pevent, const char *outfile)
@@ -843,6 +828,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
843struct scripting_ops python_scripting_ops = { 828struct scripting_ops python_scripting_ops = {
844 .name = "Python", 829 .name = "Python",
845 .start_script = python_start_script, 830 .start_script = python_start_script,
831 .flush_script = python_flush_script,
846 .stop_script = python_stop_script, 832 .stop_script = python_stop_script,
847 .process_event = python_process_event, 833 .process_event = python_process_event,
848 .generate_script = python_generate_script, 834 .generate_script = python_generate_script,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 88dfef70c13d..883406f4b381 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,6 +14,7 @@
14#include "util.h" 14#include "util.h"
15#include "cpumap.h" 15#include "cpumap.h"
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "asm/bug.h"
17 18
18static int perf_session__open(struct perf_session *session) 19static int perf_session__open(struct perf_session *session)
19{ 20{
@@ -66,6 +67,25 @@ static void perf_session__destroy_kernel_maps(struct perf_session *session)
66 machines__destroy_kernel_maps(&session->machines); 67 machines__destroy_kernel_maps(&session->machines);
67} 68}
68 69
70static bool perf_session__has_comm_exec(struct perf_session *session)
71{
72 struct perf_evsel *evsel;
73
74 evlist__for_each(session->evlist, evsel) {
75 if (evsel->attr.comm_exec)
76 return true;
77 }
78
79 return false;
80}
81
82static void perf_session__set_comm_exec(struct perf_session *session)
83{
84 bool comm_exec = perf_session__has_comm_exec(session);
85
86 machines__set_comm_exec(&session->machines, comm_exec);
87}
88
69struct perf_session *perf_session__new(struct perf_data_file *file, 89struct perf_session *perf_session__new(struct perf_data_file *file,
70 bool repipe, struct perf_tool *tool) 90 bool repipe, struct perf_tool *tool)
71{ 91{
@@ -75,9 +95,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
75 goto out; 95 goto out;
76 96
77 session->repipe = repipe; 97 session->repipe = repipe;
78 INIT_LIST_HEAD(&session->ordered_samples.samples); 98 ordered_events__init(&session->ordered_events);
79 INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
80 INIT_LIST_HEAD(&session->ordered_samples.to_free);
81 machines__init(&session->machines); 99 machines__init(&session->machines);
82 100
83 if (file) { 101 if (file) {
@@ -91,6 +109,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
91 goto out_close; 109 goto out_close;
92 110
93 perf_session__set_id_hdr_size(session); 111 perf_session__set_id_hdr_size(session);
112 perf_session__set_comm_exec(session);
94 } 113 }
95 } 114 }
96 115
@@ -100,13 +119,13 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
100 * kernel MMAP event, in perf_event__process_mmap(). 119 * kernel MMAP event, in perf_event__process_mmap().
101 */ 120 */
102 if (perf_session__create_kernel_maps(session) < 0) 121 if (perf_session__create_kernel_maps(session) < 0)
103 goto out_delete; 122 pr_warning("Cannot read kernel map\n");
104 } 123 }
105 124
106 if (tool && tool->ordering_requires_timestamps && 125 if (tool && tool->ordering_requires_timestamps &&
107 tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) { 126 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
108 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 127 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
109 tool->ordered_samples = false; 128 tool->ordered_events = false;
110 } 129 }
111 130
112 return session; 131 return session;
@@ -238,7 +257,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
238 if (tool->build_id == NULL) 257 if (tool->build_id == NULL)
239 tool->build_id = process_finished_round_stub; 258 tool->build_id = process_finished_round_stub;
240 if (tool->finished_round == NULL) { 259 if (tool->finished_round == NULL) {
241 if (tool->ordered_samples) 260 if (tool->ordered_events)
242 tool->finished_round = process_finished_round; 261 tool->finished_round = process_finished_round;
243 else 262 else
244 tool->finished_round = process_finished_round_stub; 263 tool->finished_round = process_finished_round_stub;
@@ -444,87 +463,6 @@ static perf_event__swap_op perf_event__swap_ops[] = {
444 [PERF_RECORD_HEADER_MAX] = NULL, 463 [PERF_RECORD_HEADER_MAX] = NULL,
445}; 464};
446 465
447struct sample_queue {
448 u64 timestamp;
449 u64 file_offset;
450 union perf_event *event;
451 struct list_head list;
452};
453
454static void perf_session_free_sample_buffers(struct perf_session *session)
455{
456 struct ordered_samples *os = &session->ordered_samples;
457
458 while (!list_empty(&os->to_free)) {
459 struct sample_queue *sq;
460
461 sq = list_entry(os->to_free.next, struct sample_queue, list);
462 list_del(&sq->list);
463 free(sq);
464 }
465}
466
467static int perf_session_deliver_event(struct perf_session *session,
468 union perf_event *event,
469 struct perf_sample *sample,
470 struct perf_tool *tool,
471 u64 file_offset);
472
473static int flush_sample_queue(struct perf_session *s,
474 struct perf_tool *tool)
475{
476 struct ordered_samples *os = &s->ordered_samples;
477 struct list_head *head = &os->samples;
478 struct sample_queue *tmp, *iter;
479 struct perf_sample sample;
480 u64 limit = os->next_flush;
481 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
482 bool show_progress = limit == ULLONG_MAX;
483 struct ui_progress prog;
484 int ret;
485
486 if (!tool->ordered_samples || !limit)
487 return 0;
488
489 if (show_progress)
490 ui_progress__init(&prog, os->nr_samples, "Processing time ordered events...");
491
492 list_for_each_entry_safe(iter, tmp, head, list) {
493 if (session_done())
494 return 0;
495
496 if (iter->timestamp > limit)
497 break;
498
499 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
500 if (ret)
501 pr_err("Can't parse sample, err = %d\n", ret);
502 else {
503 ret = perf_session_deliver_event(s, iter->event, &sample, tool,
504 iter->file_offset);
505 if (ret)
506 return ret;
507 }
508
509 os->last_flush = iter->timestamp;
510 list_del(&iter->list);
511 list_add(&iter->list, &os->sample_cache);
512 os->nr_samples--;
513
514 if (show_progress)
515 ui_progress__update(&prog, 1);
516 }
517
518 if (list_empty(head)) {
519 os->last_sample = NULL;
520 } else if (last_ts <= limit) {
521 os->last_sample =
522 list_entry(head->prev, struct sample_queue, list);
523 }
524
525 return 0;
526}
527
528/* 466/*
529 * When perf record finishes a pass on every buffers, it records this pseudo 467 * When perf record finishes a pass on every buffers, it records this pseudo
530 * event. 468 * event.
@@ -568,99 +506,43 @@ static int process_finished_round(struct perf_tool *tool,
568 union perf_event *event __maybe_unused, 506 union perf_event *event __maybe_unused,
569 struct perf_session *session) 507 struct perf_session *session)
570{ 508{
571 int ret = flush_sample_queue(session, tool); 509 return ordered_events__flush(session, tool, OE_FLUSH__ROUND);
572 if (!ret)
573 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
574
575 return ret;
576}
577
578/* The queue is ordered by time */
579static void __queue_event(struct sample_queue *new, struct perf_session *s)
580{
581 struct ordered_samples *os = &s->ordered_samples;
582 struct sample_queue *sample = os->last_sample;
583 u64 timestamp = new->timestamp;
584 struct list_head *p;
585
586 ++os->nr_samples;
587 os->last_sample = new;
588
589 if (!sample) {
590 list_add(&new->list, &os->samples);
591 os->max_timestamp = timestamp;
592 return;
593 }
594
595 /*
596 * last_sample might point to some random place in the list as it's
597 * the last queued event. We expect that the new event is close to
598 * this.
599 */
600 if (sample->timestamp <= timestamp) {
601 while (sample->timestamp <= timestamp) {
602 p = sample->list.next;
603 if (p == &os->samples) {
604 list_add_tail(&new->list, &os->samples);
605 os->max_timestamp = timestamp;
606 return;
607 }
608 sample = list_entry(p, struct sample_queue, list);
609 }
610 list_add_tail(&new->list, &sample->list);
611 } else {
612 while (sample->timestamp > timestamp) {
613 p = sample->list.prev;
614 if (p == &os->samples) {
615 list_add(&new->list, &os->samples);
616 return;
617 }
618 sample = list_entry(p, struct sample_queue, list);
619 }
620 list_add(&new->list, &sample->list);
621 }
622} 510}
623 511
624#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
625
626int perf_session_queue_event(struct perf_session *s, union perf_event *event, 512int perf_session_queue_event(struct perf_session *s, union perf_event *event,
627 struct perf_sample *sample, u64 file_offset) 513 struct perf_tool *tool, struct perf_sample *sample,
514 u64 file_offset)
628{ 515{
629 struct ordered_samples *os = &s->ordered_samples; 516 struct ordered_events *oe = &s->ordered_events;
630 struct list_head *sc = &os->sample_cache;
631 u64 timestamp = sample->time; 517 u64 timestamp = sample->time;
632 struct sample_queue *new; 518 struct ordered_event *new;
633 519
634 if (!timestamp || timestamp == ~0ULL) 520 if (!timestamp || timestamp == ~0ULL)
635 return -ETIME; 521 return -ETIME;
636 522
637 if (timestamp < s->ordered_samples.last_flush) { 523 if (timestamp < oe->last_flush) {
638 printf("Warning: Timestamp below last timeslice flush\n"); 524 WARN_ONCE(1, "Timestamp below last timeslice flush\n");
639 return -EINVAL; 525
526 pr_oe_time(timestamp, "out of order event");
527 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
528 oe->last_flush_type);
529
530 /* We could get out of order messages after forced flush. */
531 if (oe->last_flush_type != OE_FLUSH__HALF)
532 return -EINVAL;
640 } 533 }
641 534
642 if (!list_empty(sc)) { 535 new = ordered_events__new(oe, timestamp);
643 new = list_entry(sc->next, struct sample_queue, list); 536 if (!new) {
644 list_del(&new->list); 537 ordered_events__flush(s, tool, OE_FLUSH__HALF);
645 } else if (os->sample_buffer) { 538 new = ordered_events__new(oe, timestamp);
646 new = os->sample_buffer + os->sample_buffer_idx;
647 if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER)
648 os->sample_buffer = NULL;
649 } else {
650 os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
651 if (!os->sample_buffer)
652 return -ENOMEM;
653 list_add(&os->sample_buffer->list, &os->to_free);
654 os->sample_buffer_idx = 2;
655 new = os->sample_buffer + 1;
656 } 539 }
657 540
658 new->timestamp = timestamp; 541 if (!new)
542 return -ENOMEM;
543
659 new->file_offset = file_offset; 544 new->file_offset = file_offset;
660 new->event = event; 545 new->event = event;
661
662 __queue_event(new, s);
663
664 return 0; 546 return 0;
665} 547}
666 548
@@ -920,11 +802,10 @@ perf_session__deliver_sample(struct perf_session *session,
920 &sample->read.one, machine); 802 &sample->read.one, machine);
921} 803}
922 804
923static int perf_session_deliver_event(struct perf_session *session, 805int perf_session__deliver_event(struct perf_session *session,
924 union perf_event *event, 806 union perf_event *event,
925 struct perf_sample *sample, 807 struct perf_sample *sample,
926 struct perf_tool *tool, 808 struct perf_tool *tool, u64 file_offset)
927 u64 file_offset)
928{ 809{
929 struct perf_evsel *evsel; 810 struct perf_evsel *evsel;
930 struct machine *machine; 811 struct machine *machine;
@@ -1005,8 +886,10 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1005 switch (event->header.type) { 886 switch (event->header.type) {
1006 case PERF_RECORD_HEADER_ATTR: 887 case PERF_RECORD_HEADER_ATTR:
1007 err = tool->attr(tool, event, &session->evlist); 888 err = tool->attr(tool, event, &session->evlist);
1008 if (err == 0) 889 if (err == 0) {
1009 perf_session__set_id_hdr_size(session); 890 perf_session__set_id_hdr_size(session);
891 perf_session__set_comm_exec(session);
892 }
1010 return err; 893 return err;
1011 case PERF_RECORD_HEADER_EVENT_TYPE: 894 case PERF_RECORD_HEADER_EVENT_TYPE:
1012 /* 895 /*
@@ -1036,6 +919,61 @@ static void event_swap(union perf_event *event, bool sample_id_all)
1036 swap(event, sample_id_all); 919 swap(event, sample_id_all);
1037} 920}
1038 921
922int perf_session__peek_event(struct perf_session *session, off_t file_offset,
923 void *buf, size_t buf_sz,
924 union perf_event **event_ptr,
925 struct perf_sample *sample)
926{
927 union perf_event *event;
928 size_t hdr_sz, rest;
929 int fd;
930
931 if (session->one_mmap && !session->header.needs_swap) {
932 event = file_offset - session->one_mmap_offset +
933 session->one_mmap_addr;
934 goto out_parse_sample;
935 }
936
937 if (perf_data_file__is_pipe(session->file))
938 return -1;
939
940 fd = perf_data_file__fd(session->file);
941 hdr_sz = sizeof(struct perf_event_header);
942
943 if (buf_sz < hdr_sz)
944 return -1;
945
946 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 ||
947 readn(fd, &buf, hdr_sz) != (ssize_t)hdr_sz)
948 return -1;
949
950 event = (union perf_event *)buf;
951
952 if (session->header.needs_swap)
953 perf_event_header__bswap(&event->header);
954
955 if (event->header.size < hdr_sz)
956 return -1;
957
958 rest = event->header.size - hdr_sz;
959
960 if (readn(fd, &buf, rest) != (ssize_t)rest)
961 return -1;
962
963 if (session->header.needs_swap)
964 event_swap(event, perf_evlist__sample_id_all(session->evlist));
965
966out_parse_sample:
967
968 if (sample && event->header.type < PERF_RECORD_USER_TYPE_START &&
969 perf_evlist__parse_sample(session->evlist, event, sample))
970 return -1;
971
972 *event_ptr = event;
973
974 return 0;
975}
976
1039static s64 perf_session__process_event(struct perf_session *session, 977static s64 perf_session__process_event(struct perf_session *session,
1040 union perf_event *event, 978 union perf_event *event,
1041 struct perf_tool *tool, 979 struct perf_tool *tool,
@@ -1062,15 +1000,15 @@ static s64 perf_session__process_event(struct perf_session *session,
1062 if (ret) 1000 if (ret)
1063 return ret; 1001 return ret;
1064 1002
1065 if (tool->ordered_samples) { 1003 if (tool->ordered_events) {
1066 ret = perf_session_queue_event(session, event, &sample, 1004 ret = perf_session_queue_event(session, event, tool, &sample,
1067 file_offset); 1005 file_offset);
1068 if (ret != -ETIME) 1006 if (ret != -ETIME)
1069 return ret; 1007 return ret;
1070 } 1008 }
1071 1009
1072 return perf_session_deliver_event(session, event, &sample, tool, 1010 return perf_session__deliver_event(session, event, &sample, tool,
1073 file_offset); 1011 file_offset);
1074} 1012}
1075 1013
1076void perf_event_header__bswap(struct perf_event_header *hdr) 1014void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1222,12 +1160,11 @@ more:
1222 goto more; 1160 goto more;
1223done: 1161done:
1224 /* do the final flush for ordered samples */ 1162 /* do the final flush for ordered samples */
1225 session->ordered_samples.next_flush = ULLONG_MAX; 1163 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1226 err = flush_sample_queue(session, tool);
1227out_err: 1164out_err:
1228 free(buf); 1165 free(buf);
1229 perf_session__warn_about_errors(session, tool); 1166 perf_session__warn_about_errors(session, tool);
1230 perf_session_free_sample_buffers(session); 1167 ordered_events__free(&session->ordered_events);
1231 return err; 1168 return err;
1232} 1169}
1233 1170
@@ -1368,12 +1305,11 @@ more:
1368 1305
1369out: 1306out:
1370 /* do the final flush for ordered samples */ 1307 /* do the final flush for ordered samples */
1371 session->ordered_samples.next_flush = ULLONG_MAX; 1308 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1372 err = flush_sample_queue(session, tool);
1373out_err: 1309out_err:
1374 ui_progress__finish(); 1310 ui_progress__finish();
1375 perf_session__warn_about_errors(session, tool); 1311 perf_session__warn_about_errors(session, tool);
1376 perf_session_free_sample_buffers(session); 1312 ordered_events__free(&session->ordered_events);
1377 session->one_mmap = false; 1313 session->one_mmap = false;
1378 return err; 1314 return err;
1379} 1315}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0321013bd9fd..ffb440462008 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -9,26 +9,13 @@
9#include "symbol.h" 9#include "symbol.h"
10#include "thread.h" 10#include "thread.h"
11#include "data.h" 11#include "data.h"
12#include "ordered-events.h"
12#include <linux/rbtree.h> 13#include <linux/rbtree.h>
13#include <linux/perf_event.h> 14#include <linux/perf_event.h>
14 15
15struct sample_queue;
16struct ip_callchain; 16struct ip_callchain;
17struct thread; 17struct thread;
18 18
19struct ordered_samples {
20 u64 last_flush;
21 u64 next_flush;
22 u64 max_timestamp;
23 struct list_head samples;
24 struct list_head sample_cache;
25 struct list_head to_free;
26 struct sample_queue *sample_buffer;
27 struct sample_queue *last_sample;
28 int sample_buffer_idx;
29 unsigned int nr_samples;
30};
31
32struct perf_session { 19struct perf_session {
33 struct perf_header header; 20 struct perf_header header;
34 struct machines machines; 21 struct machines machines;
@@ -39,7 +26,7 @@ struct perf_session {
39 bool one_mmap; 26 bool one_mmap;
40 void *one_mmap_addr; 27 void *one_mmap_addr;
41 u64 one_mmap_offset; 28 u64 one_mmap_offset;
42 struct ordered_samples ordered_samples; 29 struct ordered_events ordered_events;
43 struct perf_data_file *file; 30 struct perf_data_file *file;
44}; 31};
45 32
@@ -58,6 +45,11 @@ void perf_session__delete(struct perf_session *session);
58 45
59void perf_event_header__bswap(struct perf_event_header *hdr); 46void perf_event_header__bswap(struct perf_event_header *hdr);
60 47
48int perf_session__peek_event(struct perf_session *session, off_t file_offset,
49 void *buf, size_t buf_sz,
50 union perf_event **event_ptr,
51 struct perf_sample *sample);
52
61int __perf_session__process_events(struct perf_session *session, 53int __perf_session__process_events(struct perf_session *session,
62 u64 data_offset, u64 data_size, u64 size, 54 u64 data_offset, u64 data_size, u64 size,
63 struct perf_tool *tool); 55 struct perf_tool *tool);
@@ -65,10 +57,16 @@ int perf_session__process_events(struct perf_session *session,
65 struct perf_tool *tool); 57 struct perf_tool *tool);
66 58
67int perf_session_queue_event(struct perf_session *s, union perf_event *event, 59int perf_session_queue_event(struct perf_session *s, union perf_event *event,
68 struct perf_sample *sample, u64 file_offset); 60 struct perf_tool *tool, struct perf_sample *sample,
61 u64 file_offset);
69 62
70void perf_tool__fill_defaults(struct perf_tool *tool); 63void perf_tool__fill_defaults(struct perf_tool *tool);
71 64
65int perf_session__deliver_event(struct perf_session *session,
66 union perf_event *event,
67 struct perf_sample *sample,
68 struct perf_tool *tool, u64 file_offset);
69
72int perf_session__resolve_callchain(struct perf_session *session, 70int perf_session__resolve_callchain(struct perf_session *session,
73 struct perf_evsel *evsel, 71 struct perf_evsel *evsel,
74 struct thread *thread, 72 struct thread *thread,
@@ -128,5 +126,5 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
128 126
129extern volatile int session_done; 127extern volatile int session_done;
130 128
131#define session_done() (*(volatile int *)(&session_done)) 129#define session_done() ACCESS_ONCE(session_done)
132#endif /* __PERF_SESSION_H */ 130#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 14e5a039bc45..289df9d1e65a 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -70,12 +70,14 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
70 size_t size, unsigned int width) 70 size_t size, unsigned int width)
71{ 71{
72 const char *comm = thread__comm_str(he->thread); 72 const char *comm = thread__comm_str(he->thread);
73 return repsep_snprintf(bf, size, "%*s:%5d", width - 6, 73
74 comm ?: "", he->thread->tid); 74 width = max(7U, width) - 6;
75 return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
76 width, width, comm ?: "");
75} 77}
76 78
77struct sort_entry sort_thread = { 79struct sort_entry sort_thread = {
78 .se_header = "Command: Pid", 80 .se_header = " Pid:Command",
79 .se_cmp = sort__thread_cmp, 81 .se_cmp = sort__thread_cmp,
80 .se_snprintf = hist_entry__thread_snprintf, 82 .se_snprintf = hist_entry__thread_snprintf,
81 .se_width_idx = HISTC_THREAD, 83 .se_width_idx = HISTC_THREAD,
@@ -106,7 +108,7 @@ sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
106static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf, 108static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
107 size_t size, unsigned int width) 109 size_t size, unsigned int width)
108{ 110{
109 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm)); 111 return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm));
110} 112}
111 113
112struct sort_entry sort_comm = { 114struct sort_entry sort_comm = {
@@ -152,10 +154,10 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf,
152 if (map && map->dso) { 154 if (map && map->dso) {
153 const char *dso_name = !verbose ? map->dso->short_name : 155 const char *dso_name = !verbose ? map->dso->short_name :
154 map->dso->long_name; 156 map->dso->long_name;
155 return repsep_snprintf(bf, size, "%-*s", width, dso_name); 157 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
156 } 158 }
157 159
158 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); 160 return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]");
159} 161}
160 162
161static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf, 163static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
@@ -257,7 +259,10 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
257 width - ret, ""); 259 width - ret, "");
258 } 260 }
259 261
260 return ret; 262 if (ret > width)
263 bf[width] = '\0';
264
265 return width;
261} 266}
262 267
263static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, 268static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
@@ -302,10 +307,9 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
302} 307}
303 308
304static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, 309static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
305 size_t size, 310 size_t size, unsigned int width)
306 unsigned int width __maybe_unused)
307{ 311{
308 return repsep_snprintf(bf, size, "%s", he->srcline); 312 return repsep_snprintf(bf, size, "%*.*-s", width, width, he->srcline);
309} 313}
310 314
311struct sort_entry sort_srcline = { 315struct sort_entry sort_srcline = {
@@ -332,7 +336,7 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
332static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf, 336static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
333 size_t size, unsigned int width) 337 size_t size, unsigned int width)
334{ 338{
335 return repsep_snprintf(bf, size, "%-*s", width, 339 return repsep_snprintf(bf, size, "%-*.*s", width, width,
336 he->parent ? he->parent->name : "[other]"); 340 he->parent ? he->parent->name : "[other]");
337} 341}
338 342
@@ -354,7 +358,7 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
354static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, 358static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
355 size_t size, unsigned int width) 359 size_t size, unsigned int width)
356{ 360{
357 return repsep_snprintf(bf, size, "%*d", width, he->cpu); 361 return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu);
358} 362}
359 363
360struct sort_entry sort_cpu = { 364struct sort_entry sort_cpu = {
@@ -484,7 +488,7 @@ static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
484 else if (he->branch_info->flags.mispred) 488 else if (he->branch_info->flags.mispred)
485 out = "Y"; 489 out = "Y";
486 490
487 return repsep_snprintf(bf, size, "%-*s", width, out); 491 return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
488} 492}
489 493
490/* --sort daddr_sym */ 494/* --sort daddr_sym */
@@ -1194,7 +1198,7 @@ bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1194 return hse_a->se == hse_b->se; 1198 return hse_a->se == hse_b->se;
1195} 1199}
1196 1200
1197void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists) 1201void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1198{ 1202{
1199 struct hpp_sort_entry *hse; 1203 struct hpp_sort_entry *hse;
1200 1204
@@ -1202,20 +1206,21 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1202 return; 1206 return;
1203 1207
1204 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1208 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1205 hists__new_col_len(hists, hse->se->se_width_idx, 1209 hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name));
1206 strlen(hse->se->se_header));
1207} 1210}
1208 1211
1209static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1212static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1210 struct perf_evsel *evsel) 1213 struct perf_evsel *evsel)
1211{ 1214{
1212 struct hpp_sort_entry *hse; 1215 struct hpp_sort_entry *hse;
1213 size_t len; 1216 size_t len = fmt->user_len;
1214 1217
1215 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1218 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1216 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1217 1219
1218 return scnprintf(hpp->buf, hpp->size, "%-*s", len, hse->se->se_header); 1220 if (!len)
1221 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1222
1223 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1219} 1224}
1220 1225
1221static int __sort__hpp_width(struct perf_hpp_fmt *fmt, 1226static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
@@ -1223,20 +1228,26 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1223 struct perf_evsel *evsel) 1228 struct perf_evsel *evsel)
1224{ 1229{
1225 struct hpp_sort_entry *hse; 1230 struct hpp_sort_entry *hse;
1231 size_t len = fmt->user_len;
1226 1232
1227 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1233 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1228 1234
1229 return hists__col_len(&evsel->hists, hse->se->se_width_idx); 1235 if (!len)
1236 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1237
1238 return len;
1230} 1239}
1231 1240
1232static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1241static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1233 struct hist_entry *he) 1242 struct hist_entry *he)
1234{ 1243{
1235 struct hpp_sort_entry *hse; 1244 struct hpp_sort_entry *hse;
1236 size_t len; 1245 size_t len = fmt->user_len;
1237 1246
1238 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1247 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1239 len = hists__col_len(he->hists, hse->se->se_width_idx); 1248
1249 if (!len)
1250 len = hists__col_len(he->hists, hse->se->se_width_idx);
1240 1251
1241 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); 1252 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1242} 1253}
@@ -1253,6 +1264,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1253 } 1264 }
1254 1265
1255 hse->se = sd->entry; 1266 hse->se = sd->entry;
1267 hse->hpp.name = sd->entry->se_header;
1256 hse->hpp.header = __sort__hpp_header; 1268 hse->hpp.header = __sort__hpp_header;
1257 hse->hpp.width = __sort__hpp_width; 1269 hse->hpp.width = __sort__hpp_width;
1258 hse->hpp.entry = __sort__hpp_entry; 1270 hse->hpp.entry = __sort__hpp_entry;
@@ -1265,6 +1277,8 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1265 INIT_LIST_HEAD(&hse->hpp.list); 1277 INIT_LIST_HEAD(&hse->hpp.list);
1266 INIT_LIST_HEAD(&hse->hpp.sort_list); 1278 INIT_LIST_HEAD(&hse->hpp.sort_list);
1267 hse->hpp.elide = false; 1279 hse->hpp.elide = false;
1280 hse->hpp.len = 0;
1281 hse->hpp.user_len = 0;
1268 1282
1269 return hse; 1283 return hse;
1270} 1284}
@@ -1432,14 +1446,49 @@ static const char *get_default_sort_order(void)
1432 return default_sort_orders[sort__mode]; 1446 return default_sort_orders[sort__mode];
1433} 1447}
1434 1448
1449static int setup_sort_order(void)
1450{
1451 char *new_sort_order;
1452
1453 /*
1454 * Append '+'-prefixed sort order to the default sort
1455 * order string.
1456 */
1457 if (!sort_order || is_strict_order(sort_order))
1458 return 0;
1459
1460 if (sort_order[1] == '\0') {
1461 error("Invalid --sort key: `+'");
1462 return -EINVAL;
1463 }
1464
1465 /*
1466 * We allocate new sort_order string, but we never free it,
1467 * because it's checked over the rest of the code.
1468 */
1469 if (asprintf(&new_sort_order, "%s,%s",
1470 get_default_sort_order(), sort_order + 1) < 0) {
1471 error("Not enough memory to set up --sort");
1472 return -ENOMEM;
1473 }
1474
1475 sort_order = new_sort_order;
1476 return 0;
1477}
1478
1435static int __setup_sorting(void) 1479static int __setup_sorting(void)
1436{ 1480{
1437 char *tmp, *tok, *str; 1481 char *tmp, *tok, *str;
1438 const char *sort_keys = sort_order; 1482 const char *sort_keys;
1439 int ret = 0; 1483 int ret = 0;
1440 1484
1485 ret = setup_sort_order();
1486 if (ret)
1487 return ret;
1488
1489 sort_keys = sort_order;
1441 if (sort_keys == NULL) { 1490 if (sort_keys == NULL) {
1442 if (field_order) { 1491 if (is_strict_order(field_order)) {
1443 /* 1492 /*
1444 * If user specified field order but no sort order, 1493 * If user specified field order but no sort order,
1445 * we'll honor it and not add default sort orders. 1494 * we'll honor it and not add default sort orders.
@@ -1625,23 +1674,36 @@ static void reset_dimensions(void)
1625 memory_sort_dimensions[i].taken = 0; 1674 memory_sort_dimensions[i].taken = 0;
1626} 1675}
1627 1676
1677bool is_strict_order(const char *order)
1678{
1679 return order && (*order != '+');
1680}
1681
1628static int __setup_output_field(void) 1682static int __setup_output_field(void)
1629{ 1683{
1630 char *tmp, *tok, *str; 1684 char *tmp, *tok, *str, *strp;
1631 int ret = 0; 1685 int ret = -EINVAL;
1632 1686
1633 if (field_order == NULL) 1687 if (field_order == NULL)
1634 return 0; 1688 return 0;
1635 1689
1636 reset_dimensions(); 1690 reset_dimensions();
1637 1691
1638 str = strdup(field_order); 1692 strp = str = strdup(field_order);
1639 if (str == NULL) { 1693 if (str == NULL) {
1640 error("Not enough memory to setup output fields"); 1694 error("Not enough memory to setup output fields");
1641 return -ENOMEM; 1695 return -ENOMEM;
1642 } 1696 }
1643 1697
1644 for (tok = strtok_r(str, ", ", &tmp); 1698 if (!is_strict_order(field_order))
1699 strp++;
1700
1701 if (!strlen(strp)) {
1702 error("Invalid --fields key: `+'");
1703 goto out;
1704 }
1705
1706 for (tok = strtok_r(strp, ", ", &tmp);
1645 tok; tok = strtok_r(NULL, ", ", &tmp)) { 1707 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1646 ret = output_field_add(tok); 1708 ret = output_field_add(tok);
1647 if (ret == -EINVAL) { 1709 if (ret == -EINVAL) {
@@ -1653,6 +1715,7 @@ static int __setup_output_field(void)
1653 } 1715 }
1654 } 1716 }
1655 1717
1718out:
1656 free(str); 1719 free(str);
1657 return ret; 1720 return ret;
1658} 1721}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 041f0c9cea2b..c03e4ff8beff 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -218,4 +218,5 @@ void perf_hpp__set_elide(int idx, bool elide);
218 218
219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); 219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);
220 220
221bool is_strict_order(const char *order);
221#endif /* __PERF_SORT_H */ 222#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index d75349979e65..1e23a5bfb044 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -6,6 +6,7 @@
6#include <inttypes.h> 6#include <inttypes.h>
7 7
8#include "symbol.h" 8#include "symbol.h"
9#include "machine.h"
9#include "vdso.h" 10#include "vdso.h"
10#include <symbol/kallsyms.h> 11#include <symbol/kallsyms.h>
11#include "debug.h" 12#include "debug.h"
@@ -680,6 +681,11 @@ static u64 ref_reloc(struct kmap *kmap)
680 return 0; 681 return 0;
681} 682}
682 683
684static bool want_demangle(bool is_kernel_sym)
685{
686 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
687}
688
683int dso__load_sym(struct dso *dso, struct map *map, 689int dso__load_sym(struct dso *dso, struct map *map,
684 struct symsrc *syms_ss, struct symsrc *runtime_ss, 690 struct symsrc *syms_ss, struct symsrc *runtime_ss,
685 symbol_filter_t filter, int kmodule) 691 symbol_filter_t filter, int kmodule)
@@ -712,6 +718,14 @@ int dso__load_sym(struct dso *dso, struct map *map,
712 symbols__delete(&dso->symbols[map->type]); 718 symbols__delete(&dso->symbols[map->type]);
713 719
714 if (!syms_ss->symtab) { 720 if (!syms_ss->symtab) {
721 /*
722 * If the vmlinux is stripped, fail so we will fall back
723 * to using kallsyms. The vmlinux runtime symbols aren't
724 * of much use.
725 */
726 if (dso->kernel)
727 goto out_elf_end;
728
715 syms_ss->symtab = syms_ss->dynsym; 729 syms_ss->symtab = syms_ss->dynsym;
716 syms_ss->symshdr = syms_ss->dynshdr; 730 syms_ss->symshdr = syms_ss->dynshdr;
717 } 731 }
@@ -736,7 +750,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
736 if (symstrs == NULL) 750 if (symstrs == NULL)
737 goto out_elf_end; 751 goto out_elf_end;
738 752
739 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 753 sec_strndx = elf_getscn(runtime_ss->elf, runtime_ss->ehdr.e_shstrndx);
740 if (sec_strndx == NULL) 754 if (sec_strndx == NULL)
741 goto out_elf_end; 755 goto out_elf_end;
742 756
@@ -916,7 +930,11 @@ int dso__load_sym(struct dso *dso, struct map *map,
916 } 930 }
917 curr_dso->symtab_type = dso->symtab_type; 931 curr_dso->symtab_type = dso->symtab_type;
918 map_groups__insert(kmap->kmaps, curr_map); 932 map_groups__insert(kmap->kmaps, curr_map);
919 dsos__add(&dso->node, curr_dso); 933 /*
934 * The new DSO should go to the kernel DSOS
935 */
936 dsos__add(&map->groups->machine->kernel_dsos,
937 curr_dso);
920 dso__set_loaded(curr_dso, map->type); 938 dso__set_loaded(curr_dso, map->type);
921 } else 939 } else
922 curr_dso = curr_map->dso; 940 curr_dso = curr_map->dso;
@@ -938,9 +956,12 @@ new_symbol:
938 * DWARF DW_compile_unit has this, but we don't always have access 956 * DWARF DW_compile_unit has this, but we don't always have access
939 * to it... 957 * to it...
940 */ 958 */
941 if (symbol_conf.demangle) { 959 if (want_demangle(dso->kernel || kmodule)) {
942 demangled = bfd_demangle(NULL, elf_name, 960 int demangle_flags = DMGL_NO_OPTS;
943 DMGL_PARAMS | DMGL_ANSI); 961 if (verbose)
962 demangle_flags = DMGL_PARAMS | DMGL_ANSI;
963
964 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
944 if (demangled != NULL) 965 if (demangled != NULL)
945 elf_name = demangled; 966 elf_name = demangled;
946 } 967 }
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index eb06746b06b2..be84f7a9838b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -15,6 +15,7 @@
15#include "machine.h" 15#include "machine.h"
16#include "symbol.h" 16#include "symbol.h"
17#include "strlist.h" 17#include "strlist.h"
18#include "header.h"
18 19
19#include <elf.h> 20#include <elf.h>
20#include <limits.h> 21#include <limits.h>
@@ -33,6 +34,7 @@ struct symbol_conf symbol_conf = {
33 .try_vmlinux_path = true, 34 .try_vmlinux_path = true,
34 .annotate_src = true, 35 .annotate_src = true,
35 .demangle = true, 36 .demangle = true,
37 .demangle_kernel = false,
36 .cumulate_callchain = true, 38 .cumulate_callchain = true,
37 .show_hist_headers = true, 39 .show_hist_headers = true,
38 .symfs = "", 40 .symfs = "",
@@ -523,10 +525,15 @@ struct process_kallsyms_args {
523 struct dso *dso; 525 struct dso *dso;
524}; 526};
525 527
528/*
529 * These are symbols in the kernel image, so make sure that
530 * sym is from a kernel DSO.
531 */
526bool symbol__is_idle(struct symbol *sym) 532bool symbol__is_idle(struct symbol *sym)
527{ 533{
528 const char * const idle_symbols[] = { 534 const char * const idle_symbols[] = {
529 "cpu_idle", 535 "cpu_idle",
536 "cpu_startup_entry",
530 "intel_idle", 537 "intel_idle",
531 "default_idle", 538 "default_idle",
532 "native_safe_halt", 539 "native_safe_halt",
@@ -1468,8 +1475,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1468 if (vmlinux[0] == '/') 1475 if (vmlinux[0] == '/')
1469 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux); 1476 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux);
1470 else 1477 else
1471 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", 1478 symbol__join_symfs(symfs_vmlinux, vmlinux);
1472 symbol_conf.symfs, vmlinux);
1473 1479
1474 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1480 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1475 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1481 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
@@ -1745,12 +1751,13 @@ static void vmlinux_path__exit(void)
1745 zfree(&vmlinux_path); 1751 zfree(&vmlinux_path);
1746} 1752}
1747 1753
1748static int vmlinux_path__init(void) 1754static int vmlinux_path__init(struct perf_session_env *env)
1749{ 1755{
1750 struct utsname uts; 1756 struct utsname uts;
1751 char bf[PATH_MAX]; 1757 char bf[PATH_MAX];
1758 char *kernel_version;
1752 1759
1753 vmlinux_path = malloc(sizeof(char *) * 5); 1760 vmlinux_path = malloc(sizeof(char *) * 6);
1754 if (vmlinux_path == NULL) 1761 if (vmlinux_path == NULL)
1755 return -1; 1762 return -1;
1756 1763
@@ -1763,25 +1770,37 @@ static int vmlinux_path__init(void)
1763 goto out_fail; 1770 goto out_fail;
1764 ++vmlinux_path__nr_entries; 1771 ++vmlinux_path__nr_entries;
1765 1772
1766 /* only try running kernel version if no symfs was given */ 1773 /* only try kernel version if no symfs was given */
1767 if (symbol_conf.symfs[0] != 0) 1774 if (symbol_conf.symfs[0] != 0)
1768 return 0; 1775 return 0;
1769 1776
1770 if (uname(&uts) < 0) 1777 if (env) {
1771 return -1; 1778 kernel_version = env->os_release;
1779 } else {
1780 if (uname(&uts) < 0)
1781 goto out_fail;
1772 1782
1773 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 1783 kernel_version = uts.release;
1784 }
1785
1786 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", kernel_version);
1774 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1787 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1775 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1788 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1776 goto out_fail; 1789 goto out_fail;
1777 ++vmlinux_path__nr_entries; 1790 ++vmlinux_path__nr_entries;
1778 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release); 1791 snprintf(bf, sizeof(bf), "/usr/lib/debug/boot/vmlinux-%s",
1792 kernel_version);
1793 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1794 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1795 goto out_fail;
1796 ++vmlinux_path__nr_entries;
1797 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version);
1779 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1798 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1780 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1799 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1781 goto out_fail; 1800 goto out_fail;
1782 ++vmlinux_path__nr_entries; 1801 ++vmlinux_path__nr_entries;
1783 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", 1802 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1784 uts.release); 1803 kernel_version);
1785 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1804 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1786 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1805 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1787 goto out_fail; 1806 goto out_fail;
@@ -1827,7 +1846,7 @@ static bool symbol__read_kptr_restrict(void)
1827 return value; 1846 return value;
1828} 1847}
1829 1848
1830int symbol__init(void) 1849int symbol__init(struct perf_session_env *env)
1831{ 1850{
1832 const char *symfs; 1851 const char *symfs;
1833 1852
@@ -1842,7 +1861,7 @@ int symbol__init(void)
1842 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 1861 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
1843 sizeof(struct symbol)); 1862 sizeof(struct symbol));
1844 1863
1845 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0) 1864 if (symbol_conf.try_vmlinux_path && vmlinux_path__init(env) < 0)
1846 return -1; 1865 return -1;
1847 1866
1848 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { 1867 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index e7295e93cff9..bec4b7bd09de 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,6 +13,7 @@
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h" 14#include "build-id.h"
15#include "event.h" 15#include "event.h"
16#include "util.h"
16 17
17#ifdef HAVE_LIBELF_SUPPORT 18#ifdef HAVE_LIBELF_SUPPORT
18#include <libelf.h> 19#include <libelf.h>
@@ -59,6 +60,7 @@ extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
59#endif 60#endif
60 61
61#ifndef DMGL_PARAMS 62#ifndef DMGL_PARAMS
63#define DMGL_NO_OPTS 0 /* For readability... */
62#define DMGL_PARAMS (1 << 0) /* Include function args */ 64#define DMGL_PARAMS (1 << 0) /* Include function args */
63#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 65#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
64#endif 66#endif
@@ -118,6 +120,7 @@ struct symbol_conf {
118 annotate_src, 120 annotate_src,
119 event_group, 121 event_group,
120 demangle, 122 demangle,
123 demangle_kernel,
121 filter_relative, 124 filter_relative,
122 show_hist_headers; 125 show_hist_headers;
123 const char *vmlinux_name, 126 const char *vmlinux_name,
@@ -143,6 +146,14 @@ struct symbol_conf {
143}; 146};
144 147
145extern struct symbol_conf symbol_conf; 148extern struct symbol_conf symbol_conf;
149
150static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)
151{
152 return path__join(bf, size, symbol_conf.symfs, path);
153}
154
155#define symbol__join_symfs(bf, path) __symbol__join_symfs(bf, sizeof(bf), path)
156
146extern int vmlinux_path__nr_entries; 157extern int vmlinux_path__nr_entries;
147extern char **vmlinux_path; 158extern char **vmlinux_path;
148 159
@@ -253,7 +264,8 @@ int modules__parse(const char *filename, void *arg,
253int filename__read_debuglink(const char *filename, char *debuglink, 264int filename__read_debuglink(const char *filename, char *debuglink,
254 size_t size); 265 size_t size);
255 266
256int symbol__init(void); 267struct perf_session_env;
268int symbol__init(struct perf_session_env *env);
257void symbol__exit(void); 269void symbol__exit(void);
258void symbol__elf_init(void); 270void symbol__elf_init(void);
259struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 271struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 12c7a253a63c..a9df7f2c6dc9 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -42,7 +42,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
42 goto err_thread; 42 goto err_thread;
43 43
44 snprintf(comm_str, 32, ":%d", tid); 44 snprintf(comm_str, 32, ":%d", tid);
45 comm = comm__new(comm_str, 0); 45 comm = comm__new(comm_str, 0, false);
46 free(comm_str); 46 free(comm_str);
47 if (!comm) 47 if (!comm)
48 goto err_thread; 48 goto err_thread;
@@ -81,19 +81,33 @@ struct comm *thread__comm(const struct thread *thread)
81 return list_first_entry(&thread->comm_list, struct comm, list); 81 return list_first_entry(&thread->comm_list, struct comm, list);
82} 82}
83 83
84struct comm *thread__exec_comm(const struct thread *thread)
85{
86 struct comm *comm, *last = NULL;
87
88 list_for_each_entry(comm, &thread->comm_list, list) {
89 if (comm->exec)
90 return comm;
91 last = comm;
92 }
93
94 return last;
95}
96
84/* CHECKME: time should always be 0 if event aren't ordered */ 97/* CHECKME: time should always be 0 if event aren't ordered */
85int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) 98int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
99 bool exec)
86{ 100{
87 struct comm *new, *curr = thread__comm(thread); 101 struct comm *new, *curr = thread__comm(thread);
88 int err; 102 int err;
89 103
90 /* Override latest entry if it had no specific time coverage */ 104 /* Override latest entry if it had no specific time coverage */
91 if (!curr->start) { 105 if (!curr->start && !curr->exec) {
92 err = comm__override(curr, str, timestamp); 106 err = comm__override(curr, str, timestamp, exec);
93 if (err) 107 if (err)
94 return err; 108 return err;
95 } else { 109 } else {
96 new = comm__new(str, timestamp); 110 new = comm__new(str, timestamp, exec);
97 if (!new) 111 if (!new)
98 return -ENOMEM; 112 return -ENOMEM;
99 list_add(&new->list, &thread->comm_list); 113 list_add(&new->list, &thread->comm_list);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 716b7723cce2..8c75fa774706 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -38,9 +38,17 @@ static inline void thread__exited(struct thread *thread)
38 thread->dead = true; 38 thread->dead = true;
39} 39}
40 40
41int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp); 41int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
42 bool exec);
43static inline int thread__set_comm(struct thread *thread, const char *comm,
44 u64 timestamp)
45{
46 return __thread__set_comm(thread, comm, timestamp, false);
47}
48
42int thread__comm_len(struct thread *thread); 49int thread__comm_len(struct thread *thread);
43struct comm *thread__comm(const struct thread *thread); 50struct comm *thread__comm(const struct thread *thread);
51struct comm *thread__exec_comm(const struct thread *thread);
44const char *thread__comm_str(const struct thread *thread); 52const char *thread__comm_str(const struct thread *thread);
45void thread__insert_map(struct thread *thread, struct map *map); 53void thread__insert_map(struct thread *thread, struct map *map);
46int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 54int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 4385816d3d49..f11636966a0f 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -40,7 +40,7 @@ struct perf_tool {
40 event_op2 tracing_data; 40 event_op2 tracing_data;
41 event_op2 finished_round, 41 event_op2 finished_round,
42 build_id; 42 build_id;
43 bool ordered_samples; 43 bool ordered_events;
44 bool ordering_requires_timestamps; 44 bool ordering_requires_timestamps;
45}; 45};
46 46
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 57aaccc1692e..5c9bdd1591a9 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -30,6 +30,11 @@
30 30
31struct scripting_context *scripting_context; 31struct scripting_context *scripting_context;
32 32
33static int flush_script_unsupported(void)
34{
35 return 0;
36}
37
33static int stop_script_unsupported(void) 38static int stop_script_unsupported(void)
34{ 39{
35 return 0; 40 return 0;
@@ -74,6 +79,7 @@ static int python_generate_script_unsupported(struct pevent *pevent
74struct scripting_ops python_scripting_unsupported_ops = { 79struct scripting_ops python_scripting_unsupported_ops = {
75 .name = "Python", 80 .name = "Python",
76 .start_script = python_start_script_unsupported, 81 .start_script = python_start_script_unsupported,
82 .flush_script = flush_script_unsupported,
77 .stop_script = stop_script_unsupported, 83 .stop_script = stop_script_unsupported,
78 .process_event = process_event_unsupported, 84 .process_event = process_event_unsupported,
79 .generate_script = python_generate_script_unsupported, 85 .generate_script = python_generate_script_unsupported,
@@ -137,6 +143,7 @@ static int perl_generate_script_unsupported(struct pevent *pevent
137struct scripting_ops perl_scripting_unsupported_ops = { 143struct scripting_ops perl_scripting_unsupported_ops = {
138 .name = "Perl", 144 .name = "Perl",
139 .start_script = perl_start_script_unsupported, 145 .start_script = perl_start_script_unsupported,
146 .flush_script = flush_script_unsupported,
140 .stop_script = stop_script_unsupported, 147 .stop_script = stop_script_unsupported,
141 .process_event = process_event_unsupported, 148 .process_event = process_event_unsupported,
142 .generate_script = perl_generate_script_unsupported, 149 .generate_script = perl_generate_script_unsupported,
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 7b6d68688327..52aaa19e1eb1 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -64,6 +64,7 @@ struct perf_session;
64struct scripting_ops { 64struct scripting_ops {
65 const char *name; 65 const char *name;
66 int (*start_script) (const char *script, int argc, const char **argv); 66 int (*start_script) (const char *script, int argc, const char **argv);
67 int (*flush_script) (void);
67 int (*stop_script) (void); 68 int (*stop_script) (void);
68 void (*process_event) (union perf_event *event, 69 void (*process_event) (union perf_event *event,
69 struct perf_sample *sample, 70 struct perf_sample *sample,
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index e52e7461911b..24e8d871b74e 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -13,6 +13,7 @@
13#include <limits.h> 13#include <limits.h>
14#include <byteswap.h> 14#include <byteswap.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <unistd.h>
16 17
17/* 18/*
18 * XXX We need to find a better place for these things... 19 * XXX We need to find a better place for these things...
@@ -282,6 +283,18 @@ void get_term_dimensions(struct winsize *ws)
282 ws->ws_col = 80; 283 ws->ws_col = 80;
283} 284}
284 285
286void set_term_quiet_input(struct termios *old)
287{
288 struct termios tc;
289
290 tcgetattr(0, old);
291 tc = *old;
292 tc.c_lflag &= ~(ICANON | ECHO);
293 tc.c_cc[VMIN] = 0;
294 tc.c_cc[VTIME] = 0;
295 tcsetattr(0, TCSANOW, &tc);
296}
297
285static void set_tracing_events_path(const char *mountpoint) 298static void set_tracing_events_path(const char *mountpoint)
286{ 299{
287 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 300 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
@@ -443,6 +456,7 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
443 size_t size = 0, alloc_size = 0; 456 size_t size = 0, alloc_size = 0;
444 void *bf = NULL, *nbf; 457 void *bf = NULL, *nbf;
445 int fd, n, err = 0; 458 int fd, n, err = 0;
459 char sbuf[STRERR_BUFSIZE];
446 460
447 fd = open(filename, O_RDONLY); 461 fd = open(filename, O_RDONLY);
448 if (fd < 0) 462 if (fd < 0)
@@ -463,8 +477,8 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
463 n = read(fd, bf + size, alloc_size - size); 477 n = read(fd, bf + size, alloc_size - size);
464 if (n < 0) { 478 if (n < 0) {
465 if (size) { 479 if (size) {
466 pr_warning("read failed %d: %s\n", 480 pr_warning("read failed %d: %s\n", errno,
467 errno, strerror(errno)); 481 strerror_r(errno, sbuf, sizeof(sbuf)));
468 err = 0; 482 err = 0;
469 } else 483 } else
470 err = -errno; 484 err = -errno;
@@ -536,3 +550,39 @@ void mem_bswap_64(void *src, int byte_size)
536 ++m; 550 ++m;
537 } 551 }
538} 552}
553
554bool find_process(const char *name)
555{
556 size_t len = strlen(name);
557 DIR *dir;
558 struct dirent *d;
559 int ret = -1;
560
561 dir = opendir(procfs__mountpoint());
562 if (!dir)
563 return -1;
564
565 /* Walk through the directory. */
566 while (ret && (d = readdir(dir)) != NULL) {
567 char path[PATH_MAX];
568 char *data;
569 size_t size;
570
571 if ((d->d_type != DT_DIR) ||
572 !strcmp(".", d->d_name) ||
573 !strcmp("..", d->d_name))
574 continue;
575
576 scnprintf(path, sizeof(path), "%s/%s/comm",
577 procfs__mountpoint(), d->d_name);
578
579 if (filename__read_str(path, &data, &size))
580 continue;
581
582 ret = strncmp(name, data, len);
583 free(data);
584 }
585
586 closedir(dir);
587 return ret ? false : true;
588}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 66864364ccb4..80bfdaa0e2a4 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -39,6 +39,8 @@
39 39
40#define _ALL_SOURCE 1 40#define _ALL_SOURCE 1
41#define _BSD_SOURCE 1 41#define _BSD_SOURCE 1
42/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
43#define _DEFAULT_SOURCE 1
42#define HAS_BOOL 44#define HAS_BOOL
43 45
44#include <unistd.h> 46#include <unistd.h>
@@ -64,16 +66,18 @@
64#include <regex.h> 66#include <regex.h>
65#include <utime.h> 67#include <utime.h>
66#include <sys/wait.h> 68#include <sys/wait.h>
67#include <sys/poll.h> 69#include <poll.h>
68#include <sys/socket.h> 70#include <sys/socket.h>
69#include <sys/ioctl.h> 71#include <sys/ioctl.h>
70#include <inttypes.h> 72#include <inttypes.h>
73#include <linux/kernel.h>
71#include <linux/magic.h> 74#include <linux/magic.h>
72#include <linux/types.h> 75#include <linux/types.h>
73#include <sys/ttydefaults.h> 76#include <sys/ttydefaults.h>
74#include <api/fs/debugfs.h> 77#include <api/fs/debugfs.h>
75#include <termios.h> 78#include <termios.h>
76#include <linux/bitops.h> 79#include <linux/bitops.h>
80#include <termios.h>
77 81
78extern const char *graph_line; 82extern const char *graph_line;
79extern const char *graph_dotted_line; 83extern const char *graph_dotted_line;
@@ -307,6 +311,7 @@ extern unsigned int page_size;
307extern int cacheline_size; 311extern int cacheline_size;
308 312
309void get_term_dimensions(struct winsize *ws); 313void get_term_dimensions(struct winsize *ws);
314void set_term_quiet_input(struct termios *old);
310 315
311struct parse_tag { 316struct parse_tag {
312 char tag; 317 char tag;
@@ -317,6 +322,21 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
317 322
318#define SRCLINE_UNKNOWN ((char *) "??:0") 323#define SRCLINE_UNKNOWN ((char *) "??:0")
319 324
325static inline int path__join(char *bf, size_t size,
326 const char *path1, const char *path2)
327{
328 return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2);
329}
330
331static inline int path__join3(char *bf, size_t size,
332 const char *path1, const char *path2,
333 const char *path3)
334{
335 return scnprintf(bf, size, "%s%s%s%s%s",
336 path1, path1[0] ? "/" : "",
337 path2, path2[0] ? "/" : "", path3);
338}
339
320struct dso; 340struct dso;
321 341
322char *get_srcline(struct dso *dso, unsigned long addr); 342char *get_srcline(struct dso *dso, unsigned long addr);
@@ -330,4 +350,5 @@ void mem_bswap_64(void *src, int byte_size);
330void mem_bswap_32(void *src, int byte_size); 350void mem_bswap_32(void *src, int byte_size);
331 351
332const char *get_filename_for_perf_kvm(void); 352const char *get_filename_for_perf_kvm(void);
353bool find_process(const char *name);
333#endif /* GIT_COMPAT_UTIL_H */ 354#endif /* GIT_COMPAT_UTIL_H */