]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'perf-core-for-mingo-4.12-20170503' of git://git.kernel.org/pub/scm/linux...
authorIngo Molnar <mingo@kernel.org>
Wed, 3 May 2017 17:28:27 +0000 (19:28 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 3 May 2017 17:28:27 +0000 (19:28 +0200)
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

Fixes:

- Support setting probes in versioned user space symbols, such as
  pthread_create@@GLIBC_2.1, picking the default one, more work
  needed to make it possible to set it on the other versions, as
  the 'perf probe' syntax already uses @ for other purposes.
  (Paul Clarke)

- Do not special case address zero as an error for routines that
  return addresses (symbol lookup), instead use the return as the
  success/error indication and pass a pointer to return the address,
  fixing 'perf test vmlinux' (the one that compares address between
  vmlinux and kallsyms) on s/390, where the '_text' address is equal
  to zero (Arnaldo Carvalho de Melo)

Infrastructure changes:

- More header sanitization, moving stuff out of util.h into
  more appropriate headers and objects and sometimes creating
  new ones (Arnaldo Carvalho de Melo)

- Refactor a duplicated code for obtaining config file name (Taeung Song)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
389 files changed:
Documentation/trace/kprobetrace.txt
arch/um/include/shared/os.h
arch/x86/entry/syscalls/syscall_32.tbl
arch/x86/events/amd/iommu.c
arch/x86/events/amd/iommu.h
arch/x86/events/amd/uncore.c
arch/x86/events/intel/bts.c
arch/x86/events/intel/core.c
arch/x86/events/intel/ds.c
arch/x86/events/intel/pt.c
arch/x86/events/intel/pt.h
arch/x86/events/perf_event.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/kprobes.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/proto.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/tlbflush.h
arch/x86/include/uapi/asm/prctl.h
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/kprobes/common.h
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kprobes/ftrace.c
arch/x86/kernel/kprobes/opt.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/ptrace.c
arch/x86/um/Makefile
arch/x86/um/asm/ptrace.h
arch/x86/um/os-Linux/prctl.c
arch/x86/um/syscalls_32.c [new file with mode: 0644]
arch/x86/um/syscalls_64.c
drivers/hwtracing/coresight/coresight-etb10.c
drivers/hwtracing/coresight/coresight-etm-perf.c
drivers/hwtracing/coresight/coresight-priv.h
drivers/hwtracing/coresight/coresight-tmc-etf.c
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_proto.h
drivers/iommu/amd_iommu_types.h
fs/exec.c
include/linux/compat.h
include/linux/coresight.h
include/linux/kprobes.h
include/linux/perf_event.h
include/linux/thread_info.h
include/uapi/linux/perf_event.h
kernel/events/core.c
kernel/events/ring_buffer.c
kernel/fork.c
kernel/kprobes.c
kernel/nsproxy.c
kernel/trace/Kconfig
kernel/trace/trace.c
kernel/trace/trace_kprobe.c
tools/arch/arm/include/uapi/asm/kvm.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/powerpc/include/uapi/asm/kvm.h
tools/arch/x86/include/asm/atomic.h
tools/arch/x86/include/asm/cmpxchg.h [new file with mode: 0644]
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/lib/memcpy_64.S
tools/build/Makefile.feature
tools/build/feature/Makefile
tools/build/feature/test-all.c
tools/build/feature/test-sched_getcpu.c [new file with mode: 0644]
tools/include/asm-generic/atomic-gcc.h
tools/include/linux/atomic.h
tools/include/linux/bug.h [new file with mode: 0644]
tools/include/linux/compiler-gcc.h
tools/include/linux/compiler.h
tools/include/linux/hashtable.h
tools/include/linux/kernel.h
tools/include/linux/log2.h
tools/include/linux/refcount.h [new file with mode: 0644]
tools/include/linux/string.h
tools/include/linux/types.h
tools/include/uapi/linux/fcntl.h [new file with mode: 0644]
tools/include/uapi/linux/perf_event.h
tools/include/uapi/linux/stat.h [new file with mode: 0644]
tools/lib/api/fs/fs.c
tools/lib/api/fs/fs.h
tools/lib/string.c
tools/lib/subcmd/help.c
tools/lib/subcmd/help.h
tools/lib/subcmd/parse-options.c
tools/lib/subcmd/subcmd-util.h
tools/lib/symbol/kallsyms.c
tools/objtool/builtin-check.c
tools/objtool/objtool.c
tools/perf/.gitignore
tools/perf/Build
tools/perf/Documentation/perf-ftrace.txt
tools/perf/Documentation/perf-list.txt
tools/perf/Documentation/perf-record.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Documentation/perf-sched.txt
tools/perf/Documentation/perf-script.txt
tools/perf/Documentation/perf-stat.txt
tools/perf/Documentation/perf-trace.txt
tools/perf/Documentation/perf.data-file-format.txt
tools/perf/MANIFEST
tools/perf/Makefile.config
tools/perf/arch/arm/util/cs-etm.c
tools/perf/arch/arm/util/dwarf-regs.c
tools/perf/arch/arm/util/unwind-libdw.c
tools/perf/arch/arm64/util/dwarf-regs.c
tools/perf/arch/arm64/util/unwind-libunwind.c
tools/perf/arch/common.c
tools/perf/arch/powerpc/util/dwarf-regs.c
tools/perf/arch/powerpc/util/kvm-stat.c
tools/perf/arch/powerpc/util/perf_regs.c
tools/perf/arch/powerpc/util/sym-handling.c
tools/perf/arch/s390/annotate/instructions.c [new file with mode: 0644]
tools/perf/arch/s390/util/kvm-stat.c
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/arch/x86/tests/intel-cqm.c
tools/perf/arch/x86/tests/perf-time-to-tsc.c
tools/perf/arch/x86/util/auxtrace.c
tools/perf/arch/x86/util/intel-bts.c
tools/perf/arch/x86/util/intel-pt.c
tools/perf/arch/x86/util/kvm-stat.c
tools/perf/arch/x86/util/perf_regs.c
tools/perf/arch/x86/util/unwind-libdw.c
tools/perf/bench/bench.h
tools/perf/bench/futex-hash.c
tools/perf/bench/futex-lock-pi.c
tools/perf/bench/futex-requeue.c
tools/perf/bench/futex-wake-parallel.c
tools/perf/bench/futex-wake.c
tools/perf/bench/futex.h
tools/perf/bench/mem-functions.c
tools/perf/bench/numa.c
tools/perf/bench/sched-messaging.c
tools/perf/bench/sched-pipe.c
tools/perf/builtin-annotate.c
tools/perf/builtin-bench.c
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-buildid-list.c
tools/perf/builtin-c2c.c
tools/perf/builtin-config.c
tools/perf/builtin-data.c
tools/perf/builtin-diff.c
tools/perf/builtin-evlist.c
tools/perf/builtin-ftrace.c
tools/perf/builtin-help.c
tools/perf/builtin-inject.c
tools/perf/builtin-kallsyms.c
tools/perf/builtin-kmem.c
tools/perf/builtin-kvm.c
tools/perf/builtin-list.c
tools/perf/builtin-lock.c
tools/perf/builtin-mem.c
tools/perf/builtin-probe.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-timechart.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/builtin-version.c
tools/perf/builtin.h
tools/perf/check-headers.sh
tools/perf/command-list.txt
tools/perf/perf.c
tools/perf/perf.h
tools/perf/pmu-events/arch/x86/broadwell/uncore.json [new file with mode: 0644]
tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json
tools/perf/pmu-events/arch/x86/broadwellde/uncore-memory.json
tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json
tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json
tools/perf/pmu-events/arch/x86/broadwellx/uncore-interconnect.json
tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json
tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json
tools/perf/pmu-events/arch/x86/haswell/uncore.json [new file with mode: 0644]
tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json
tools/perf/pmu-events/arch/x86/haswellx/uncore-interconnect.json
tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json
tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json
tools/perf/pmu-events/arch/x86/ivybridge/uncore.json [new file with mode: 0644]
tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json
tools/perf/pmu-events/arch/x86/ivytown/uncore-interconnect.json
tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json
tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json
tools/perf/pmu-events/arch/x86/jaketown/uncore-interconnect.json
tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json
tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
tools/perf/pmu-events/arch/x86/mapfile.csv
tools/perf/pmu-events/arch/x86/sandybridge/uncore.json [new file with mode: 0644]
tools/perf/pmu-events/arch/x86/skylake/uncore.json [new file with mode: 0644]
tools/perf/pmu-events/jevents.c
tools/perf/pmu-events/jevents.h
tools/perf/pmu-events/pmu-events.h
tools/perf/tests/Build
tools/perf/tests/attr.c
tools/perf/tests/backward-ring-buffer.c
tools/perf/tests/bpf.c
tools/perf/tests/builtin-test.c
tools/perf/tests/clang.c
tools/perf/tests/code-reading.c
tools/perf/tests/cpumap.c
tools/perf/tests/dso-data.c
tools/perf/tests/dwarf-unwind.c
tools/perf/tests/event-times.c
tools/perf/tests/evsel-roundtrip-name.c
tools/perf/tests/expr.c [new file with mode: 0644]
tools/perf/tests/hists_common.c
tools/perf/tests/hists_cumulate.c
tools/perf/tests/hists_filter.c
tools/perf/tests/hists_link.c
tools/perf/tests/hists_output.c
tools/perf/tests/is_printable_array.c
tools/perf/tests/mmap-basic.c
tools/perf/tests/mmap-thread-lookup.c
tools/perf/tests/openat-syscall-all-cpus.c
tools/perf/tests/openat-syscall-tp-fields.c
tools/perf/tests/openat-syscall.c
tools/perf/tests/parse-events.c
tools/perf/tests/parse-no-sample-id-all.c
tools/perf/tests/perf-record.c
tools/perf/tests/pmu.c
tools/perf/tests/sample-parsing.c
tools/perf/tests/sdt.c
tools/perf/tests/sw-clock.c
tools/perf/tests/switch-tracking.c
tools/perf/tests/task-exit.c
tools/perf/tests/tests.h
tools/perf/tests/thread-map.c
tools/perf/tests/thread-mg-share.c
tools/perf/tests/unit_number__scnprintf.c
tools/perf/tests/vmlinux-kallsyms.c
tools/perf/trace/beauty/Build [new file with mode: 0644]
tools/perf/trace/beauty/beauty.h [new file with mode: 0644]
tools/perf/trace/beauty/signum.c
tools/perf/trace/beauty/statx.c [new file with mode: 0644]
tools/perf/ui/browser.c
tools/perf/ui/browsers/annotate.c
tools/perf/ui/browsers/header.c
tools/perf/ui/browsers/hists.c
tools/perf/ui/browsers/map.c
tools/perf/ui/gtk/annotate.c
tools/perf/ui/gtk/hists.c
tools/perf/ui/hist.c
tools/perf/ui/setup.c
tools/perf/ui/stdio/hist.c
tools/perf/ui/tui/setup.c
tools/perf/util/Build
tools/perf/util/alias.c [deleted file]
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/auxtrace.c
tools/perf/util/auxtrace.h
tools/perf/util/bpf-loader.c
tools/perf/util/bpf-loader.h
tools/perf/util/bpf-prologue.c
tools/perf/util/bpf-prologue.h
tools/perf/util/build-id.c
tools/perf/util/build-id.h
tools/perf/util/c++/clang-c.h
tools/perf/util/cache.h
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/cgroup.c
tools/perf/util/cgroup.h
tools/perf/util/cloexec.c
tools/perf/util/cloexec.h
tools/perf/util/color.h
tools/perf/util/comm.c
tools/perf/util/compress.h [new file with mode: 0644]
tools/perf/util/config.c
tools/perf/util/counts.c
tools/perf/util/cpumap.c
tools/perf/util/cpumap.h
tools/perf/util/ctype.c
tools/perf/util/data-convert-bt.c
tools/perf/util/data.c
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/demangle-java.c
tools/perf/util/drv_configs.c
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/dump-insn.c [new file with mode: 0644]
tools/perf/util/dump-insn.h [new file with mode: 0644]
tools/perf/util/dwarf-aux.c
tools/perf/util/dwarf-regs.c
tools/perf/util/env.c
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/evsel_fprintf.c
tools/perf/util/expr.h [new file with mode: 0644]
tools/perf/util/expr.y [new file with mode: 0644]
tools/perf/util/header.c
tools/perf/util/help-unknown-cmd.c
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/intel-bts.c
tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
tools/perf/util/intel-pt.c
tools/perf/util/jitdump.c
tools/perf/util/llvm-utils.c
tools/perf/util/lzma.c
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/mem-events.c
tools/perf/util/memswap.c [new file with mode: 0644]
tools/perf/util/memswap.h [new file with mode: 0644]
tools/perf/util/namespaces.c [new file with mode: 0644]
tools/perf/util/namespaces.h [new file with mode: 0644]
tools/perf/util/ordered-events.c
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-events.y
tools/perf/util/path.c
tools/perf/util/path.h [new file with mode: 0644]
tools/perf/util/perf-hooks.c
tools/perf/util/perf_regs.c
tools/perf/util/perf_regs.h
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/print_binary.c [new file with mode: 0644]
tools/perf/util/print_binary.h [new file with mode: 0644]
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h
tools/perf/util/probe-file.c
tools/perf/util/probe-file.h
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/python-ext-sources
tools/perf/util/python.c
tools/perf/util/quote.c
tools/perf/util/record.c
tools/perf/util/sane_ctype.h [new file with mode: 0644]
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/srcline.c
tools/perf/util/srcline.h [new file with mode: 0644]
tools/perf/util/stat-shadow.c
tools/perf/util/stat.c
tools/perf/util/stat.h
tools/perf/util/strbuf.c
tools/perf/util/strfilter.c
tools/perf/util/string.c
tools/perf/util/string2.h [new file with mode: 0644]
tools/perf/util/strlist.c
tools/perf/util/symbol-elf.c
tools/perf/util/symbol-minimal.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/term.c
tools/perf/util/thread-stack.c
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/perf/util/thread_map.c
tools/perf/util/thread_map.h
tools/perf/util/time-utils.c
tools/perf/util/time-utils.h
tools/perf/util/tool.h
tools/perf/util/top.h
tools/perf/util/trace-event-parse.c
tools/perf/util/trace-event-read.c
tools/perf/util/units.c [new file with mode: 0644]
tools/perf/util/units.h [new file with mode: 0644]
tools/perf/util/unwind-libdw.c
tools/perf/util/unwind-libdw.h
tools/perf/util/unwind-libunwind-local.c
tools/perf/util/unwind.h
tools/perf/util/util.c
tools/perf/util/util.h
tools/perf/util/values.c
tools/perf/util/vdso.c
tools/perf/util/xyarray.c
tools/perf/util/zlib.c
tools/scripts/Makefile.include

index 41ef9d8efe9517f602e59b21bfe1448196cb3450..5ea85059db3b964f31be6129d8f9c714ca578fbf 100644 (file)
@@ -8,8 +8,9 @@ Overview
 --------
 These events are similar to tracepoint based events. Instead of Tracepoint,
 this is based on kprobes (kprobe and kretprobe). So it can probe wherever
-kprobes can probe (this means, all functions body except for __kprobes
-functions). Unlike the Tracepoint based event, this can be added and removed
+kprobes can probe (this means, all functions except those with
+__kprobes/nokprobe_inline annotation and those marked NOKPROBE_SYMBOL).
+Unlike the Tracepoint based event, this can be added and removed
 dynamically, on the fly.
 
 To enable this feature, build your kernel with CONFIG_KPROBE_EVENTS=y.
index de5d572225f3adb4c1cdab6e30c2dc3383ae02c1..cd1fa97776c302e03aa60267624e5d8bb56c2092 100644 (file)
@@ -302,8 +302,8 @@ extern int ignore_sigio_fd(int fd);
 extern void maybe_sigio_broken(int fd, int read);
 extern void sigio_broken(int fd, int read);
 
-/* sys-x86_64/prctl.c */
-extern int os_arch_prctl(int pid, int code, unsigned long *addr);
+/* prctl.c */
+extern int os_arch_prctl(int pid, int option, unsigned long *arg2);
 
 /* tty.c */
 extern int get_pty(void);
index 9ba050fe47f30e6eff1d119ed33fa1505b2a661d..0af59fa789ea6fd250f79125cad3aef01468a39b 100644 (file)
 381    i386    pkey_alloc              sys_pkey_alloc
 382    i386    pkey_free               sys_pkey_free
 383    i386    statx                   sys_statx
+384    i386    arch_prctl              sys_arch_prctl                  compat_sys_arch_prctl
index b28200dea715c3ae254b647b72aba2d8e5957afc..3641e24fdac5801a32b2d23b89c1ce7775807e2f 100644 (file)
@@ -11,6 +11,8 @@
  * published by the Free Software Foundation.
  */
 
+#define pr_fmt(fmt)    "perf/amd_iommu: " fmt
+
 #include <linux/perf_event.h>
 #include <linux/init.h>
 #include <linux/cpumask.h>
 
 #define COUNTER_SHIFT          16
 
-#define _GET_BANK(ev)       ((u8)(ev->hw.extra_reg.reg >> 8))
-#define _GET_CNTR(ev)       ((u8)(ev->hw.extra_reg.reg))
+/* iommu pmu conf masks */
+#define GET_CSOURCE(x)     ((x)->conf & 0xFFULL)
+#define GET_DEVID(x)       (((x)->conf >> 8)  & 0xFFFFULL)
+#define GET_DOMID(x)       (((x)->conf >> 24) & 0xFFFFULL)
+#define GET_PASID(x)       (((x)->conf >> 40) & 0xFFFFFULL)
 
-/* iommu pmu config masks */
-#define _GET_CSOURCE(ev)    ((ev->hw.config & 0xFFULL))
-#define _GET_DEVID(ev)      ((ev->hw.config >> 8)  & 0xFFFFULL)
-#define _GET_PASID(ev)      ((ev->hw.config >> 24) & 0xFFFFULL)
-#define _GET_DOMID(ev)      ((ev->hw.config >> 40) & 0xFFFFULL)
-#define _GET_DEVID_MASK(ev) ((ev->hw.extra_reg.config)  & 0xFFFFULL)
-#define _GET_PASID_MASK(ev) ((ev->hw.extra_reg.config >> 16) & 0xFFFFULL)
-#define _GET_DOMID_MASK(ev) ((ev->hw.extra_reg.config >> 32) & 0xFFFFULL)
+/* iommu pmu conf1 masks */
+#define GET_DEVID_MASK(x)  ((x)->conf1  & 0xFFFFULL)
+#define GET_DOMID_MASK(x)  (((x)->conf1 >> 16) & 0xFFFFULL)
+#define GET_PASID_MASK(x)  (((x)->conf1 >> 32) & 0xFFFFFULL)
 
-static struct perf_amd_iommu __perf_iommu;
+#define IOMMU_NAME_SIZE 16
 
 struct perf_amd_iommu {
+       struct list_head list;
        struct pmu pmu;
+       struct amd_iommu *iommu;
+       char name[IOMMU_NAME_SIZE];
        u8 max_banks;
        u8 max_counters;
        u64 cntr_assign_mask;
        raw_spinlock_t lock;
-       const struct attribute_group *attr_groups[4];
 };
 
-#define format_group   attr_groups[0]
-#define cpumask_group  attr_groups[1]
-#define events_group   attr_groups[2]
-#define null_group     attr_groups[3]
+static LIST_HEAD(perf_amd_iommu_list);
 
 /*---------------------------------------------
  * sysfs format attributes
  *---------------------------------------------*/
 PMU_FORMAT_ATTR(csource,    "config:0-7");
 PMU_FORMAT_ATTR(devid,      "config:8-23");
-PMU_FORMAT_ATTR(pasid,      "config:24-39");
-PMU_FORMAT_ATTR(domid,      "config:40-55");
+PMU_FORMAT_ATTR(domid,      "config:24-39");
+PMU_FORMAT_ATTR(pasid,      "config:40-59");
 PMU_FORMAT_ATTR(devid_mask, "config1:0-15");
-PMU_FORMAT_ATTR(pasid_mask, "config1:16-31");
-PMU_FORMAT_ATTR(domid_mask, "config1:32-47");
+PMU_FORMAT_ATTR(domid_mask, "config1:16-31");
+PMU_FORMAT_ATTR(pasid_mask, "config1:32-51");
 
 static struct attribute *iommu_format_attrs[] = {
        &format_attr_csource.attr,
@@ -79,6 +79,10 @@ static struct attribute_group amd_iommu_format_group = {
 /*---------------------------------------------
  * sysfs events attributes
  *---------------------------------------------*/
+static struct attribute_group amd_iommu_events_group = {
+       .name = "events",
+};
+
 struct amd_iommu_event_desc {
        struct kobj_attribute attr;
        const char *event;
@@ -150,30 +154,34 @@ static struct attribute_group amd_iommu_cpumask_group = {
 
 /*---------------------------------------------*/
 
-static int get_next_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu)
+static int get_next_avail_iommu_bnk_cntr(struct perf_event *event)
 {
+       struct perf_amd_iommu *piommu = container_of(event->pmu, struct perf_amd_iommu, pmu);
+       int max_cntrs = piommu->max_counters;
+       int max_banks = piommu->max_banks;
+       u32 shift, bank, cntr;
        unsigned long flags;
-       int shift, bank, cntr, retval;
-       int max_banks = perf_iommu->max_banks;
-       int max_cntrs = perf_iommu->max_counters;
+       int retval;
 
-       raw_spin_lock_irqsave(&perf_iommu->lock, flags);
+       raw_spin_lock_irqsave(&piommu->lock, flags);
 
        for (bank = 0, shift = 0; bank < max_banks; bank++) {
                for (cntr = 0; cntr < max_cntrs; cntr++) {
                        shift = bank + (bank*3) + cntr;
-                       if (perf_iommu->cntr_assign_mask & (1ULL<<shift)) {
+                       if (piommu->cntr_assign_mask & BIT_ULL(shift)) {
                                continue;
                        } else {
-                               perf_iommu->cntr_assign_mask |= (1ULL<<shift);
-                               retval = ((u16)((u16)bank<<8) | (u8)(cntr));
+                               piommu->cntr_assign_mask |= BIT_ULL(shift);
+                               event->hw.iommu_bank = bank;
+                               event->hw.iommu_cntr = cntr;
+                               retval = 0;
                                goto out;
                        }
                }
        }
        retval = -ENOSPC;
 out:
-       raw_spin_unlock_irqrestore(&perf_iommu->lock, flags);
+       raw_spin_unlock_irqrestore(&piommu->lock, flags);
        return retval;
 }
 
@@ -202,8 +210,6 @@ static int clear_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu,
 static int perf_iommu_event_init(struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
-       struct perf_amd_iommu *perf_iommu;
-       u64 config, config1;
 
        /* test the event attr type check for PMU enumeration */
        if (event->attr.type != event->pmu->type)
@@ -225,80 +231,62 @@ static int perf_iommu_event_init(struct perf_event *event)
        if (event->cpu < 0)
                return -EINVAL;
 
-       perf_iommu = &__perf_iommu;
-
-       if (event->pmu != &perf_iommu->pmu)
-               return -ENOENT;
-
-       if (perf_iommu) {
-               config = event->attr.config;
-               config1 = event->attr.config1;
-       } else {
-               return -EINVAL;
-       }
-
-       /* integrate with iommu base devid (0000), assume one iommu */
-       perf_iommu->max_banks =
-               amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID);
-       perf_iommu->max_counters =
-               amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID);
-       if ((perf_iommu->max_banks == 0) || (perf_iommu->max_counters == 0))
-               return -EINVAL;
-
        /* update the hw_perf_event struct with the iommu config data */
-       hwc->config = config;
-       hwc->extra_reg.config = config1;
+       hwc->conf  = event->attr.config;
+       hwc->conf1 = event->attr.config1;
 
        return 0;
 }
 
+static inline struct amd_iommu *perf_event_2_iommu(struct perf_event *ev)
+{
+       return (container_of(ev->pmu, struct perf_amd_iommu, pmu))->iommu;
+}
+
 static void perf_iommu_enable_event(struct perf_event *ev)
 {
-       u8 csource = _GET_CSOURCE(ev);
-       u16 devid = _GET_DEVID(ev);
+       struct amd_iommu *iommu = perf_event_2_iommu(ev);
+       struct hw_perf_event *hwc = &ev->hw;
+       u8 bank = hwc->iommu_bank;
+       u8 cntr = hwc->iommu_cntr;
        u64 reg = 0ULL;
 
-       reg = csource;
-       amd_iommu_pc_get_set_reg_val(devid,
-                       _GET_BANK(ev), _GET_CNTR(ev) ,
-                        IOMMU_PC_COUNTER_SRC_REG, &reg, true);
+       reg = GET_CSOURCE(hwc);
+       amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_COUNTER_SRC_REG, &reg);
 
-       reg = 0ULL | devid | (_GET_DEVID_MASK(ev) << 32);
+       reg = GET_DEVID_MASK(hwc);
+       reg = GET_DEVID(hwc) | (reg << 32);
        if (reg)
-               reg |= (1UL << 31);
-       amd_iommu_pc_get_set_reg_val(devid,
-                       _GET_BANK(ev), _GET_CNTR(ev) ,
-                        IOMMU_PC_DEVID_MATCH_REG, &reg, true);
+               reg |= BIT(31);
+       amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DEVID_MATCH_REG, &reg);
 
-       reg = 0ULL | _GET_PASID(ev) | (_GET_PASID_MASK(ev) << 32);
+       reg = GET_PASID_MASK(hwc);
+       reg = GET_PASID(hwc) | (reg << 32);
        if (reg)
-               reg |= (1UL << 31);
-       amd_iommu_pc_get_set_reg_val(devid,
-                       _GET_BANK(ev), _GET_CNTR(ev) ,
-                        IOMMU_PC_PASID_MATCH_REG, &reg, true);
+               reg |= BIT(31);
+       amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_PASID_MATCH_REG, &reg);
 
-       reg = 0ULL | _GET_DOMID(ev) | (_GET_DOMID_MASK(ev) << 32);
+       reg = GET_DOMID_MASK(hwc);
+       reg = GET_DOMID(hwc) | (reg << 32);
        if (reg)
-               reg |= (1UL << 31);
-       amd_iommu_pc_get_set_reg_val(devid,
-                       _GET_BANK(ev), _GET_CNTR(ev) ,
-                        IOMMU_PC_DOMID_MATCH_REG, &reg, true);
+               reg |= BIT(31);
+       amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DOMID_MATCH_REG, &reg);
 }
 
 static void perf_iommu_disable_event(struct perf_event *event)
 {
+       struct amd_iommu *iommu = perf_event_2_iommu(event);
+       struct hw_perf_event *hwc = &event->hw;
        u64 reg = 0ULL;
 
-       amd_iommu_pc_get_set_reg_val(_GET_DEVID(event),
-                       _GET_BANK(event), _GET_CNTR(event),
-                       IOMMU_PC_COUNTER_SRC_REG, &reg, true);
+       amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
+                            IOMMU_PC_COUNTER_SRC_REG, &reg);
 }
 
 static void perf_iommu_start(struct perf_event *event, int flags)
 {
        struct hw_perf_event *hwc = &event->hw;
 
-       pr_debug("perf: amd_iommu:perf_iommu_start\n");
        if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
                return;
 
@@ -306,10 +294,11 @@ static void perf_iommu_start(struct perf_event *event, int flags)
        hwc->state = 0;
 
        if (flags & PERF_EF_RELOAD) {
-               u64 prev_raw_count =  local64_read(&hwc->prev_count);
-               amd_iommu_pc_get_set_reg_val(_GET_DEVID(event),
-                               _GET_BANK(event), _GET_CNTR(event),
-                               IOMMU_PC_COUNTER_REG, &prev_raw_count, true);
+               u64 prev_raw_count = local64_read(&hwc->prev_count);
+               struct amd_iommu *iommu = perf_event_2_iommu(event);
+
+               amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
+                                    IOMMU_PC_COUNTER_REG, &prev_raw_count);
        }
 
        perf_iommu_enable_event(event);
@@ -319,37 +308,30 @@ static void perf_iommu_start(struct perf_event *event, int flags)
 
 static void perf_iommu_read(struct perf_event *event)
 {
-       u64 count = 0ULL;
-       u64 prev_raw_count = 0ULL;
-       u64 delta = 0ULL;
+       u64 count, prev, delta;
        struct hw_perf_event *hwc = &event->hw;
-       pr_debug("perf: amd_iommu:perf_iommu_read\n");
+       struct amd_iommu *iommu = perf_event_2_iommu(event);
 
-       amd_iommu_pc_get_set_reg_val(_GET_DEVID(event),
-                               _GET_BANK(event), _GET_CNTR(event),
-                               IOMMU_PC_COUNTER_REG, &count, false);
+       if (amd_iommu_pc_get_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
+                                IOMMU_PC_COUNTER_REG, &count))
+               return;
 
        /* IOMMU pc counter register is only 48 bits */
-       count &= 0xFFFFFFFFFFFFULL;
+       count &= GENMASK_ULL(47, 0);
 
-       prev_raw_count =  local64_read(&hwc->prev_count);
-       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
-                                       count) != prev_raw_count)
+       prev = local64_read(&hwc->prev_count);
+       if (local64_cmpxchg(&hwc->prev_count, prev, count) != prev)
                return;
 
-       /* Handling 48-bit counter overflowing */
-       delta = (count << COUNTER_SHIFT) - (prev_raw_count << COUNTER_SHIFT);
+       /* Handle 48-bit counter overflow */
+       delta = (count << COUNTER_SHIFT) - (prev << COUNTER_SHIFT);
        delta >>= COUNTER_SHIFT;
        local64_add(delta, &event->count);
-
 }
 
 static void perf_iommu_stop(struct perf_event *event, int flags)
 {
        struct hw_perf_event *hwc = &event->hw;
-       u64 config;
-
-       pr_debug("perf: amd_iommu:perf_iommu_stop\n");
 
        if (hwc->state & PERF_HES_UPTODATE)
                return;
@@ -361,7 +343,6 @@ static void perf_iommu_stop(struct perf_event *event, int flags)
        if (hwc->state & PERF_HES_UPTODATE)
                return;
 
-       config = hwc->config;
        perf_iommu_read(event);
        hwc->state |= PERF_HES_UPTODATE;
 }
@@ -369,17 +350,12 @@ static void perf_iommu_stop(struct perf_event *event, int flags)
 static int perf_iommu_add(struct perf_event *event, int flags)
 {
        int retval;
-       struct perf_amd_iommu *perf_iommu =
-                       container_of(event->pmu, struct perf_amd_iommu, pmu);
 
-       pr_debug("perf: amd_iommu:perf_iommu_add\n");
        event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
 
        /* request an iommu bank/counter */
-       retval = get_next_avail_iommu_bnk_cntr(perf_iommu);
-       if (retval != -ENOSPC)
-               event->hw.extra_reg.reg = (u16)retval;
-       else
+       retval = get_next_avail_iommu_bnk_cntr(event);
+       if (retval)
                return retval;
 
        if (flags & PERF_EF_START)
@@ -390,115 +366,124 @@ static int perf_iommu_add(struct perf_event *event, int flags)
 
 static void perf_iommu_del(struct perf_event *event, int flags)
 {
+       struct hw_perf_event *hwc = &event->hw;
        struct perf_amd_iommu *perf_iommu =
                        container_of(event->pmu, struct perf_amd_iommu, pmu);
 
-       pr_debug("perf: amd_iommu:perf_iommu_del\n");
        perf_iommu_stop(event, PERF_EF_UPDATE);
 
        /* clear the assigned iommu bank/counter */
        clear_avail_iommu_bnk_cntr(perf_iommu,
-                                    _GET_BANK(event),
-                                    _GET_CNTR(event));
+                                  hwc->iommu_bank, hwc->iommu_cntr);
 
        perf_event_update_userpage(event);
 }
 
-static __init int _init_events_attrs(struct perf_amd_iommu *perf_iommu)
+static __init int _init_events_attrs(void)
 {
-       struct attribute **attrs;
-       struct attribute_group *attr_group;
        int i = 0, j;
+       struct attribute **attrs;
 
        while (amd_iommu_v2_event_descs[i].attr.attr.name)
                i++;
 
-       attr_group = kzalloc(sizeof(struct attribute *)
-               * (i + 1) + sizeof(*attr_group), GFP_KERNEL);
-       if (!attr_group)
+       attrs = kzalloc(sizeof(struct attribute **) * (i + 1), GFP_KERNEL);
+       if (!attrs)
                return -ENOMEM;
 
-       attrs = (struct attribute **)(attr_group + 1);
        for (j = 0; j < i; j++)
                attrs[j] = &amd_iommu_v2_event_descs[j].attr.attr;
 
-       attr_group->name = "events";
-       attr_group->attrs = attrs;
-       perf_iommu->events_group = attr_group;
-
+       amd_iommu_events_group.attrs = attrs;
        return 0;
 }
 
-static __init void amd_iommu_pc_exit(void)
-{
-       if (__perf_iommu.events_group != NULL) {
-               kfree(__perf_iommu.events_group);
-               __perf_iommu.events_group = NULL;
-       }
-}
+const struct attribute_group *amd_iommu_attr_groups[] = {
+       &amd_iommu_format_group,
+       &amd_iommu_cpumask_group,
+       &amd_iommu_events_group,
+       NULL,
+};
+
+static struct pmu iommu_pmu = {
+       .event_init     = perf_iommu_event_init,
+       .add            = perf_iommu_add,
+       .del            = perf_iommu_del,
+       .start          = perf_iommu_start,
+       .stop           = perf_iommu_stop,
+       .read           = perf_iommu_read,
+       .task_ctx_nr    = perf_invalid_context,
+       .attr_groups    = amd_iommu_attr_groups,
+};
 
-static __init int _init_perf_amd_iommu(
-       struct perf_amd_iommu *perf_iommu, char *name)
+static __init int init_one_iommu(unsigned int idx)
 {
+       struct perf_amd_iommu *perf_iommu;
        int ret;
 
+       perf_iommu = kzalloc(sizeof(struct perf_amd_iommu), GFP_KERNEL);
+       if (!perf_iommu)
+               return -ENOMEM;
+
        raw_spin_lock_init(&perf_iommu->lock);
 
-       /* Init format attributes */
-       perf_iommu->format_group = &amd_iommu_format_group;
+       perf_iommu->pmu          = iommu_pmu;
+       perf_iommu->iommu        = get_amd_iommu(idx);
+       perf_iommu->max_banks    = amd_iommu_pc_get_max_banks(idx);
+       perf_iommu->max_counters = amd_iommu_pc_get_max_counters(idx);
 
-       /* Init cpumask attributes to only core 0 */
-       cpumask_set_cpu(0, &iommu_cpumask);
-       perf_iommu->cpumask_group = &amd_iommu_cpumask_group;
-
-       /* Init events attributes */
-       if (_init_events_attrs(perf_iommu) != 0)
-               pr_err("perf: amd_iommu: Only support raw events.\n");
+       if (!perf_iommu->iommu ||
+           !perf_iommu->max_banks ||
+           !perf_iommu->max_counters) {
+               kfree(perf_iommu);
+               return -EINVAL;
+       }
 
-       /* Init null attributes */
-       perf_iommu->null_group = NULL;
-       perf_iommu->pmu.attr_groups = perf_iommu->attr_groups;
+       snprintf(perf_iommu->name, IOMMU_NAME_SIZE, "amd_iommu_%u", idx);
 
-       ret = perf_pmu_register(&perf_iommu->pmu, name, -1);
-       if (ret) {
-               pr_err("perf: amd_iommu: Failed to initialized.\n");
-               amd_iommu_pc_exit();
+       ret = perf_pmu_register(&perf_iommu->pmu, perf_iommu->name, -1);
+       if (!ret) {
+               pr_info("Detected AMD IOMMU #%d (%d banks, %d counters/bank).\n",
+                       idx, perf_iommu->max_banks, perf_iommu->max_counters);
+               list_add_tail(&perf_iommu->list, &perf_amd_iommu_list);
        } else {
-               pr_info("perf: amd_iommu: Detected. (%d banks, %d counters/bank)\n",
-                       amd_iommu_pc_get_max_banks(IOMMU_BASE_DEVID),
-                       amd_iommu_pc_get_max_counters(IOMMU_BASE_DEVID));
+               pr_warn("Error initializing IOMMU %d.\n", idx);
+               kfree(perf_iommu);
        }
-
        return ret;
 }
 
-static struct perf_amd_iommu __perf_iommu = {
-       .pmu = {
-               .task_ctx_nr    = perf_invalid_context,
-               .event_init     = perf_iommu_event_init,
-               .add            = perf_iommu_add,
-               .del            = perf_iommu_del,
-               .start          = perf_iommu_start,
-               .stop           = perf_iommu_stop,
-               .read           = perf_iommu_read,
-       },
-       .max_banks              = 0x00,
-       .max_counters           = 0x00,
-       .cntr_assign_mask       = 0ULL,
-       .format_group           = NULL,
-       .cpumask_group          = NULL,
-       .events_group           = NULL,
-       .null_group             = NULL,
-};
-
 static __init int amd_iommu_pc_init(void)
 {
+       unsigned int i, cnt = 0;
+       int ret;
+
        /* Make sure the IOMMU PC resource is available */
        if (!amd_iommu_pc_supported())
                return -ENODEV;
 
-       _init_perf_amd_iommu(&__perf_iommu, "amd_iommu");
+       ret = _init_events_attrs();
+       if (ret)
+               return ret;
+
+       /*
+        * An IOMMU PMU is specific to an IOMMU, and can function independently.
+        * So we go through all IOMMUs and ignore the one that fails init
+        * unless all IOMMU are failing.
+        */
+       for (i = 0; i < amd_iommu_get_num_iommus(); i++) {
+               ret = init_one_iommu(i);
+               if (!ret)
+                       cnt++;
+       }
+
+       if (!cnt) {
+               kfree(amd_iommu_events_group.attrs);
+               return -ENODEV;
+       }
 
+       /* Init cpumask attributes to only core 0 */
+       cpumask_set_cpu(0, &iommu_cpumask);
        return 0;
 }
 
index 845d173278e3bd7daa17817b0e0d03ad5a4e240d..62e0702c4374a25f05505eff61eb2b66ad6e417d 100644 (file)
 #define PC_MAX_SPEC_BNKS                       64
 #define PC_MAX_SPEC_CNTRS                      16
 
-/* iommu pc reg masks*/
-#define IOMMU_BASE_DEVID                       0x0000
+struct amd_iommu;
 
 /* amd_iommu_init.c external support functions */
+extern int amd_iommu_get_num_iommus(void);
+
 extern bool amd_iommu_pc_supported(void);
 
-extern u8 amd_iommu_pc_get_max_banks(u16 devid);
+extern u8 amd_iommu_pc_get_max_banks(unsigned int idx);
+
+extern u8 amd_iommu_pc_get_max_counters(unsigned int idx);
+
+extern int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
+                               u8 fxn, u64 *value);
 
-extern u8 amd_iommu_pc_get_max_counters(u16 devid);
+extern int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
+                               u8 fxn, u64 *value);
 
-extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr,
-                       u8 fxn, u64 *value, bool is_write);
+extern struct amd_iommu *get_amd_iommu(int idx);
 
 #endif /*_PERF_EVENT_AMD_IOMMU_H_*/
index 4d1f7f2d9aff6f3383ab09de7119d3812d8ed3fe..ad44af0dd6679b50ce2c48bf37b56959b967c3cb 100644 (file)
@@ -30,6 +30,9 @@
 
 #define COUNTER_SHIFT          16
 
+#undef pr_fmt
+#define pr_fmt(fmt)    "amd_uncore: " fmt
+
 static int num_counters_llc;
 static int num_counters_nb;
 
@@ -509,51 +512,34 @@ static int __init amd_uncore_init(void)
        int ret = -ENODEV;
 
        if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
-               goto fail_nodev;
-
-       switch(boot_cpu_data.x86) {
-               case 23:
-                       /* Family 17h: */
-                       num_counters_nb = NUM_COUNTERS_NB;
-                       num_counters_llc = NUM_COUNTERS_L3;
-                       /*
-                        * For Family17h, the NorthBridge counters are
-                        * re-purposed as Data Fabric counters. Also, support is
-                        * added for L3 counters. The pmus are exported based on
-                        * family as either L2 or L3 and NB or DF.
-                        */
-                       amd_nb_pmu.name = "amd_df";
-                       amd_llc_pmu.name = "amd_l3";
-                       format_attr_event_df.show = &event_show_df;
-                       format_attr_event_l3.show = &event_show_l3;
-                       break;
-               case 22:
-                       /* Family 16h - may change: */
-                       num_counters_nb = NUM_COUNTERS_NB;
-                       num_counters_llc = NUM_COUNTERS_L2;
-                       amd_nb_pmu.name = "amd_nb";
-                       amd_llc_pmu.name = "amd_l2";
-                       format_attr_event_df = format_attr_event;
-                       format_attr_event_l3 = format_attr_event;
-                       break;
-               default:
-                       /*
-                        * All prior families have the same number of
-                        * NorthBridge and Last Level Cache counters
-                        */
-                       num_counters_nb = NUM_COUNTERS_NB;
-                       num_counters_llc = NUM_COUNTERS_L2;
-                       amd_nb_pmu.name = "amd_nb";
-                       amd_llc_pmu.name = "amd_l2";
-                       format_attr_event_df = format_attr_event;
-                       format_attr_event_l3 = format_attr_event;
-                       break;
-       }
-       amd_nb_pmu.attr_groups = amd_uncore_attr_groups_df;
-       amd_llc_pmu.attr_groups = amd_uncore_attr_groups_l3;
+               return -ENODEV;
 
        if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
-               goto fail_nodev;
+               return -ENODEV;
+
+       if (boot_cpu_data.x86 == 0x17) {
+               /*
+                * For F17h, the Northbridge counters are repurposed as Data
+                * Fabric counters. Also, L3 counters are supported too. The PMUs
+                * are exported based on  family as either L2 or L3 and NB or DF.
+                */
+               num_counters_nb           = NUM_COUNTERS_NB;
+               num_counters_llc          = NUM_COUNTERS_L3;
+               amd_nb_pmu.name           = "amd_df";
+               amd_llc_pmu.name          = "amd_l3";
+               format_attr_event_df.show = &event_show_df;
+               format_attr_event_l3.show = &event_show_l3;
+       } else {
+               num_counters_nb           = NUM_COUNTERS_NB;
+               num_counters_llc          = NUM_COUNTERS_L2;
+               amd_nb_pmu.name           = "amd_nb";
+               amd_llc_pmu.name          = "amd_l2";
+               format_attr_event_df      = format_attr_event;
+               format_attr_event_l3      = format_attr_event;
+       }
+
+       amd_nb_pmu.attr_groups  = amd_uncore_attr_groups_df;
+       amd_llc_pmu.attr_groups = amd_uncore_attr_groups_l3;
 
        if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) {
                amd_uncore_nb = alloc_percpu(struct amd_uncore *);
@@ -565,7 +551,7 @@ static int __init amd_uncore_init(void)
                if (ret)
                        goto fail_nb;
 
-               pr_info("perf: AMD NB counters detected\n");
+               pr_info("AMD NB counters detected\n");
                ret = 0;
        }
 
@@ -579,7 +565,7 @@ static int __init amd_uncore_init(void)
                if (ret)
                        goto fail_llc;
 
-               pr_info("perf: AMD LLC counters detected\n");
+               pr_info("AMD LLC counters detected\n");
                ret = 0;
        }
 
@@ -615,7 +601,6 @@ fail_nb:
        if (amd_uncore_nb)
                free_percpu(amd_uncore_nb);
 
-fail_nodev:
        return ret;
 }
 device_initcall(amd_uncore_init);
index 982c9e31daca441cc66b0b7fc652f3b4251be7b0..8ae8c5ce3a1f94debb2fe81f5652cbd7b35f2c4a 100644 (file)
@@ -63,7 +63,6 @@ struct bts_buffer {
        unsigned int    cur_buf;
        bool            snapshot;
        local_t         data_size;
-       local_t         lost;
        local_t         head;
        unsigned long   end;
        void            **data_pages;
@@ -199,7 +198,8 @@ static void bts_update(struct bts_ctx *bts)
                        return;
 
                if (ds->bts_index >= ds->bts_absolute_maximum)
-                       local_inc(&buf->lost);
+                       perf_aux_output_flag(&bts->handle,
+                                            PERF_AUX_FLAG_TRUNCATED);
 
                /*
                 * old and head are always in the same physical buffer, so we
@@ -276,7 +276,7 @@ static void bts_event_start(struct perf_event *event, int flags)
        return;
 
 fail_end_stop:
-       perf_aux_output_end(&bts->handle, 0, false);
+       perf_aux_output_end(&bts->handle, 0);
 
 fail_stop:
        event->hw.state = PERF_HES_STOPPED;
@@ -319,9 +319,8 @@ static void bts_event_stop(struct perf_event *event, int flags)
                                bts->handle.head =
                                        local_xchg(&buf->data_size,
                                                   buf->nr_pages << PAGE_SHIFT);
-
-                       perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
-                                           !!local_xchg(&buf->lost, 0));
+                       perf_aux_output_end(&bts->handle,
+                                           local_xchg(&buf->data_size, 0));
                }
 
                cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
@@ -484,8 +483,7 @@ int intel_bts_interrupt(void)
        if (old_head == local_read(&buf->head))
                return handled;
 
-       perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
-                           !!local_xchg(&buf->lost, 0));
+       perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0));
 
        buf = perf_aux_output_begin(&bts->handle, event);
        if (buf)
@@ -500,7 +498,7 @@ int intel_bts_interrupt(void)
                         * cleared handle::event
                         */
                        barrier();
-                       perf_aux_output_end(&bts->handle, 0, false);
+                       perf_aux_output_end(&bts->handle, 0);
                }
        }
 
index eb1484c86bb4b4611450c49df01aab1a18d8fa5f..a6d91d4e37a1f1dadae588a1c084e31e65d08f5d 100644 (file)
@@ -1553,6 +1553,27 @@ static __initconst const u64 slm_hw_cache_event_ids
  },
 };
 
+EVENT_ATTR_STR(topdown-total-slots, td_total_slots_glm, "event=0x3c");
+EVENT_ATTR_STR(topdown-total-slots.scale, td_total_slots_scale_glm, "3");
+/* UOPS_NOT_DELIVERED.ANY */
+EVENT_ATTR_STR(topdown-fetch-bubbles, td_fetch_bubbles_glm, "event=0x9c");
+/* ISSUE_SLOTS_NOT_CONSUMED.RECOVERY */
+EVENT_ATTR_STR(topdown-recovery-bubbles, td_recovery_bubbles_glm, "event=0xca,umask=0x02");
+/* UOPS_RETIRED.ANY */
+EVENT_ATTR_STR(topdown-slots-retired, td_slots_retired_glm, "event=0xc2");
+/* UOPS_ISSUED.ANY */
+EVENT_ATTR_STR(topdown-slots-issued, td_slots_issued_glm, "event=0x0e");
+
+static struct attribute *glm_events_attrs[] = {
+       EVENT_PTR(td_total_slots_glm),
+       EVENT_PTR(td_total_slots_scale_glm),
+       EVENT_PTR(td_fetch_bubbles_glm),
+       EVENT_PTR(td_recovery_bubbles_glm),
+       EVENT_PTR(td_slots_issued_glm),
+       EVENT_PTR(td_slots_retired_glm),
+       NULL
+};
+
 static struct extra_reg intel_glm_extra_regs[] __read_mostly = {
        /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
        INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x760005ffbfull, RSP_0),
@@ -2130,7 +2151,7 @@ again:
         * counters from the GLOBAL_STATUS mask and we always process PEBS
         * events via drain_pebs().
         */
-       status &= ~cpuc->pebs_enabled;
+       status &= ~(cpuc->pebs_enabled & PEBS_COUNTER_MASK);
 
        /*
         * PEBS overflow sets bit 62 in the global status register
@@ -3750,6 +3771,7 @@ __init int intel_pmu_init(void)
                x86_pmu.pebs_prec_dist = true;
                x86_pmu.lbr_pt_coexist = true;
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+               x86_pmu.cpu_events = glm_events_attrs;
                pr_cont("Goldmont events, ");
                break;
 
index 9dfeeeca0ea8f11a3beb4c23eeb1d115e77189db..c6d23ffe422d110bf91483427a6198e6dd0eaad4 100644 (file)
@@ -1222,7 +1222,7 @@ get_next_pebs_record_by_bit(void *base, void *top, int bit)
 
                        /* clear non-PEBS bit and re-check */
                        pebs_status = p->status & cpuc->pebs_enabled;
-                       pebs_status &= (1ULL << MAX_PEBS_EVENTS) - 1;
+                       pebs_status &= PEBS_COUNTER_MASK;
                        if (pebs_status == (1 << bit))
                                return at;
                }
index 5900471ee50824a6c70b36fb26fce6c311094cb8..ae8324d65e619551bfb07ec98b20171c41e03bb3 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/insn.h>
 #include <asm/io.h>
 #include <asm/intel_pt.h>
+#include <asm/intel-family.h>
 
 #include "../perf_event.h"
 #include "pt.h"
@@ -98,6 +99,7 @@ static struct attribute_group pt_cap_group = {
        .name   = "caps",
 };
 
+PMU_FORMAT_ATTR(pt,            "config:0"      );
 PMU_FORMAT_ATTR(cyc,           "config:1"      );
 PMU_FORMAT_ATTR(pwr_evt,       "config:4"      );
 PMU_FORMAT_ATTR(fup_on_ptw,    "config:5"      );
@@ -105,11 +107,13 @@ PMU_FORMAT_ATTR(mtc,              "config:9"      );
 PMU_FORMAT_ATTR(tsc,           "config:10"     );
 PMU_FORMAT_ATTR(noretcomp,     "config:11"     );
 PMU_FORMAT_ATTR(ptw,           "config:12"     );
+PMU_FORMAT_ATTR(branch,                "config:13"     );
 PMU_FORMAT_ATTR(mtc_period,    "config:14-17"  );
 PMU_FORMAT_ATTR(cyc_thresh,    "config:19-22"  );
 PMU_FORMAT_ATTR(psb_period,    "config:24-27"  );
 
 static struct attribute *pt_formats_attr[] = {
+       &format_attr_pt.attr,
        &format_attr_cyc.attr,
        &format_attr_pwr_evt.attr,
        &format_attr_fup_on_ptw.attr,
@@ -117,6 +121,7 @@ static struct attribute *pt_formats_attr[] = {
        &format_attr_tsc.attr,
        &format_attr_noretcomp.attr,
        &format_attr_ptw.attr,
+       &format_attr_branch.attr,
        &format_attr_mtc_period.attr,
        &format_attr_cyc_thresh.attr,
        &format_attr_psb_period.attr,
@@ -197,6 +202,19 @@ static int __init pt_pmu_hw_init(void)
                pt_pmu.tsc_art_den = eax;
        }
 
+       /* model-specific quirks */
+       switch (boot_cpu_data.x86_model) {
+       case INTEL_FAM6_BROADWELL_CORE:
+       case INTEL_FAM6_BROADWELL_XEON_D:
+       case INTEL_FAM6_BROADWELL_GT3E:
+       case INTEL_FAM6_BROADWELL_X:
+               /* not setting BRANCH_EN will #GP, erratum BDM106 */
+               pt_pmu.branch_en_always_on = true;
+               break;
+       default:
+               break;
+       }
+
        if (boot_cpu_has(X86_FEATURE_VMX)) {
                /*
                 * Intel SDM, 36.5 "Tracing post-VMXON" says that
@@ -263,8 +281,20 @@ fail:
 #define RTIT_CTL_PTW   (RTIT_CTL_PTW_EN        | \
                         RTIT_CTL_FUP_ON_PTW)
 
-#define PT_CONFIG_MASK (RTIT_CTL_TSC_EN                | \
+/*
+ * Bit 0 (TraceEn) in the attr.config is meaningless as the
+ * corresponding bit in the RTIT_CTL can only be controlled
+ * by the driver; therefore, repurpose it to mean: pass
+ * through the bit that was previously assumed to be always
+ * on for PT, thereby allowing the user to *not* set it if
+ * they so wish. See also pt_event_valid() and pt_config().
+ */
+#define RTIT_CTL_PASSTHROUGH RTIT_CTL_TRACEEN
+
+#define PT_CONFIG_MASK (RTIT_CTL_TRACEEN       | \
+                       RTIT_CTL_TSC_EN         | \
                        RTIT_CTL_DISRETC        | \
+                       RTIT_CTL_BRANCH_EN      | \
                        RTIT_CTL_CYC_PSB        | \
                        RTIT_CTL_MTC            | \
                        RTIT_CTL_PWR_EVT_EN     | \
@@ -332,6 +362,33 @@ static bool pt_event_valid(struct perf_event *event)
                        return false;
        }
 
+       /*
+        * Setting bit 0 (TraceEn in RTIT_CTL MSR) in the attr.config
+        * clears the assomption that BranchEn must always be enabled,
+        * as was the case with the first implementation of PT.
+        * If this bit is not set, the legacy behavior is preserved
+        * for compatibility with the older userspace.
+        *
+        * Re-using bit 0 for this purpose is fine because it is never
+        * directly set by the user; previous attempts at setting it in
+        * the attr.config resulted in -EINVAL.
+        */
+       if (config & RTIT_CTL_PASSTHROUGH) {
+               /*
+                * Disallow not setting BRANCH_EN where BRANCH_EN is
+                * always required.
+                */
+               if (pt_pmu.branch_en_always_on &&
+                   !(config & RTIT_CTL_BRANCH_EN))
+                       return false;
+       } else {
+               /*
+                * Disallow BRANCH_EN without the PASSTHROUGH.
+                */
+               if (config & RTIT_CTL_BRANCH_EN)
+                       return false;
+       }
+
        return true;
 }
 
@@ -411,6 +468,7 @@ static u64 pt_config_filters(struct perf_event *event)
 
 static void pt_config(struct perf_event *event)
 {
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
        u64 reg;
 
        if (!event->hw.itrace_started) {
@@ -419,7 +477,20 @@ static void pt_config(struct perf_event *event)
        }
 
        reg = pt_config_filters(event);
-       reg |= RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN;
+       reg |= RTIT_CTL_TOPA | RTIT_CTL_TRACEEN;
+
+       /*
+        * Previously, we had BRANCH_EN on by default, but now that PT has
+        * grown features outside of branch tracing, it is useful to allow
+        * the user to disable it. Setting bit 0 in the event's attr.config
+        * allows BRANCH_EN to pass through instead of being always on. See
+        * also the comment in pt_event_valid().
+        */
+       if (event->attr.config & BIT(0)) {
+               reg |= event->attr.config & RTIT_CTL_BRANCH_EN;
+       } else {
+               reg |= RTIT_CTL_BRANCH_EN;
+       }
 
        if (!event->attr.exclude_kernel)
                reg |= RTIT_CTL_OS;
@@ -429,11 +500,15 @@ static void pt_config(struct perf_event *event)
        reg |= (event->attr.config & PT_CONFIG_MASK);
 
        event->hw.config = reg;
-       wrmsrl(MSR_IA32_RTIT_CTL, reg);
+       if (READ_ONCE(pt->vmx_on))
+               perf_aux_output_flag(&pt->handle, PERF_AUX_FLAG_PARTIAL);
+       else
+               wrmsrl(MSR_IA32_RTIT_CTL, reg);
 }
 
 static void pt_config_stop(struct perf_event *event)
 {
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
        u64 ctl = READ_ONCE(event->hw.config);
 
        /* may be already stopped by a PMI */
@@ -441,7 +516,8 @@ static void pt_config_stop(struct perf_event *event)
                return;
 
        ctl &= ~RTIT_CTL_TRACEEN;
-       wrmsrl(MSR_IA32_RTIT_CTL, ctl);
+       if (!READ_ONCE(pt->vmx_on))
+               wrmsrl(MSR_IA32_RTIT_CTL, ctl);
 
        WRITE_ONCE(event->hw.config, ctl);
 
@@ -753,7 +829,8 @@ static void pt_handle_status(struct pt *pt)
                 */
                if (!pt_cap_get(PT_CAP_topa_multiple_entries) ||
                    buf->output_off == sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
-                       local_inc(&buf->lost);
+                       perf_aux_output_flag(&pt->handle,
+                                            PERF_AUX_FLAG_TRUNCATED);
                        advance++;
                }
        }
@@ -846,8 +923,10 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
 
        /* can't stop in the middle of an output region */
        if (buf->output_off + handle->size + 1 <
-           sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size))
+           sizes(TOPA_ENTRY(buf->cur, buf->cur_idx)->size)) {
+               perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
                return -EINVAL;
+       }
 
 
        /* single entry ToPA is handled by marking all regions STOP=1 INT=1 */
@@ -1171,12 +1250,6 @@ void intel_pt_interrupt(void)
        if (!READ_ONCE(pt->handle_nmi))
                return;
 
-       /*
-        * If VMX is on and PT does not support it, don't touch anything.
-        */
-       if (READ_ONCE(pt->vmx_on))
-               return;
-
        if (!event)
                return;
 
@@ -1192,8 +1265,7 @@ void intel_pt_interrupt(void)
 
        pt_update_head(pt);
 
-       perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0),
-                           local_xchg(&buf->lost, 0));
+       perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0));
 
        if (!event->hw.state) {
                int ret;
@@ -1208,7 +1280,7 @@ void intel_pt_interrupt(void)
                /* snapshot counters don't use PMI, so it's safe */
                ret = pt_buffer_reset_markers(buf, &pt->handle);
                if (ret) {
-                       perf_aux_output_end(&pt->handle, 0, true);
+                       perf_aux_output_end(&pt->handle, 0);
                        return;
                }
 
@@ -1237,12 +1309,19 @@ void intel_pt_handle_vmx(int on)
        local_irq_save(flags);
        WRITE_ONCE(pt->vmx_on, on);
 
-       if (on) {
-               /* prevent pt_config_stop() from writing RTIT_CTL */
-               event = pt->handle.event;
-               if (event)
-                       event->hw.config = 0;
-       }
+       /*
+        * If an AUX transaction is in progress, it will contain
+        * gap(s), so flag it PARTIAL to inform the user.
+        */
+       event = pt->handle.event;
+       if (event)
+               perf_aux_output_flag(&pt->handle,
+                                    PERF_AUX_FLAG_PARTIAL);
+
+       /* Turn PTs back on */
+       if (!on && event)
+               wrmsrl(MSR_IA32_RTIT_CTL, event->hw.config);
+
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(intel_pt_handle_vmx);
@@ -1257,9 +1336,6 @@ static void pt_event_start(struct perf_event *event, int mode)
        struct pt *pt = this_cpu_ptr(&pt_ctx);
        struct pt_buffer *buf;
 
-       if (READ_ONCE(pt->vmx_on))
-               return;
-
        buf = perf_aux_output_begin(&pt->handle, event);
        if (!buf)
                goto fail_stop;
@@ -1280,7 +1356,7 @@ static void pt_event_start(struct perf_event *event, int mode)
        return;
 
 fail_end_stop:
-       perf_aux_output_end(&pt->handle, 0, true);
+       perf_aux_output_end(&pt->handle, 0);
 fail_stop:
        hwc->state = PERF_HES_STOPPED;
 }
@@ -1321,8 +1397,7 @@ static void pt_event_stop(struct perf_event *event, int mode)
                        pt->handle.head =
                                local_xchg(&buf->data_size,
                                           buf->nr_pages << PAGE_SHIFT);
-               perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0),
-                                   local_xchg(&buf->lost, 0));
+               perf_aux_output_end(&pt->handle, local_xchg(&buf->data_size, 0));
        }
 }
 
index 53473c21b5543f4aae0f65b8a2bceade17509d19..0eb41d07b79a1baefafae17c380d713872f15b37 100644 (file)
@@ -110,6 +110,7 @@ struct pt_pmu {
        struct pmu              pmu;
        u32                     caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];
        bool                    vmx;
+       bool                    branch_en_always_on;
        unsigned long           max_nonturbo_ratio;
        unsigned int            tsc_art_num;
        unsigned int            tsc_art_den;
@@ -143,7 +144,6 @@ struct pt_buffer {
        size_t                  output_off;
        unsigned long           nr_pages;
        local_t                 data_size;
-       local_t                 lost;
        local64_t               head;
        bool                    snapshot;
        unsigned long           stop_pos, intr_pos;
index bcbb1d2ae10b21c2346c725d0f2ea74b0b641326..be3d36254040f76016cd55dc500b1ab51230b6a5 100644 (file)
@@ -79,6 +79,7 @@ struct amd_nb {
 
 /* The maximal number of PEBS events: */
 #define MAX_PEBS_EVENTS                8
+#define PEBS_COUNTER_MASK      ((1ULL << MAX_PEBS_EVENTS) - 1)
 
 /*
  * Flags PEBS can handle without an PMI.
index b04bb6dfed7f8464c1425df50c0fa9d1481dcee2..0fe00446f9cac8c16e1ae3fcabc4a469b772597b 100644 (file)
  * Reuse free bits when adding new feature flags!
  */
 #define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT */
+#define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* Intel CPUID faulting */
 #define X86_FEATURE_CPB                ( 7*32+ 2) /* AMD Core Performance Boost */
 #define X86_FEATURE_EPB                ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
 #define X86_FEATURE_CAT_L3     ( 7*32+ 4) /* Cache Allocation Technology L3 */
index 200581691c6e3b98b7540681ea9866456900142d..34b984c607903751f867b85d962457f7ea04776b 100644 (file)
@@ -72,14 +72,13 @@ struct arch_specific_insn {
        /* copy of the original instruction */
        kprobe_opcode_t *insn;
        /*
-        * boostable = -1: This instruction type is not boostable.
-        * boostable = 0: This instruction type is boostable.
-        * boostable = 1: This instruction has been boosted: we have
+        * boostable = false: This instruction type is not boostable.
+        * boostable = true: This instruction has been boosted: we have
         * added a relative jump after the instruction copy in insn,
         * so no single-step and fixup are needed (unless there's
         * a post_handler or break_handler).
         */
-       int boostable;
+       bool boostable;
        bool if_modifier;
 };
 
index d8b5f8ab8ef9e79fb76586bc3ca0f7f27325123e..673f9ac50f6d12612612e8efcce4eab0ef98bcbb 100644 (file)
@@ -45,6 +45,8 @@
 #define MSR_IA32_PERFCTR1              0x000000c2
 #define MSR_FSB_FREQ                   0x000000cd
 #define MSR_PLATFORM_INFO              0x000000ce
+#define MSR_PLATFORM_INFO_CPUID_FAULT_BIT      31
+#define MSR_PLATFORM_INFO_CPUID_FAULT          BIT_ULL(MSR_PLATFORM_INFO_CPUID_FAULT_BIT)
 
 #define MSR_PKG_CST_CONFIG_CONTROL     0x000000e2
 #define NHM_C3_AUTO_DEMOTE             (1UL << 25)
 
 /* DEBUGCTLMSR bits (others vary by model): */
 #define DEBUGCTLMSR_LBR                        (1UL <<  0) /* last branch recording */
+#define DEBUGCTLMSR_BTF_SHIFT          1
 #define DEBUGCTLMSR_BTF                        (1UL <<  1) /* single-step on branches */
 #define DEBUGCTLMSR_TR                 (1UL <<  6)
 #define DEBUGCTLMSR_BTS                        (1UL <<  7)
 #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT       39
 #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE           (1ULL << MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE_BIT)
 
-/* MISC_FEATURE_ENABLES non-architectural features */
-#define MSR_MISC_FEATURE_ENABLES       0x00000140
+/* MISC_FEATURES_ENABLES non-architectural features */
+#define MSR_MISC_FEATURES_ENABLES      0x00000140
 
-#define MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT                1
+#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT      0
+#define MSR_MISC_FEATURES_ENABLES_CPUID_FAULT          BIT_ULL(MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT)
+#define MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT       1
 
 #define MSR_IA32_TSC_DEADLINE          0x000006E0
 
index f385eca5407a0f47770564506bd918ac686102c4..a80c1b3997ed00047c93af99a68ef0b10aedb2e7 100644 (file)
@@ -884,6 +884,8 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
 extern int get_tsc_mode(unsigned long adr);
 extern int set_tsc_mode(unsigned int val);
 
+DECLARE_PER_CPU(u64, msr_misc_features_shadow);
+
 /* Register/unregister a process' MPX related resource */
 #define MPX_ENABLE_MANAGEMENT()        mpx_enable_management()
 #define MPX_DISABLE_MANAGEMENT()       mpx_disable_management()
index 9b9b30b1944187c8c3de3ed5c4ef1d82ea7c422d..8d3964fc5f915c37ec7bf74706446adc8ad2e93b 100644 (file)
@@ -9,6 +9,7 @@ void syscall_init(void);
 
 #ifdef CONFIG_X86_64
 void entry_SYSCALL_64(void);
+long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2);
 #endif
 
 #ifdef CONFIG_X86_32
@@ -30,6 +31,7 @@ void x86_report_nx(void);
 
 extern int reboot_force;
 
-long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
+long do_arch_prctl_common(struct task_struct *task, int option,
+                         unsigned long cpuid_enabled);
 
 #endif /* _ASM_X86_PROTO_H */
index ad6f5eb07a95bd221fe4e13c8cdb3af0cd27aa37..9fc44b95f7cb1097f3c5b55d6f40a7e89f8f9175 100644 (file)
@@ -87,6 +87,7 @@ struct thread_info {
 #define TIF_SECCOMP            8       /* secure computing */
 #define TIF_USER_RETURN_NOTIFY 11      /* notify kernel of userspace return */
 #define TIF_UPROBE             12      /* breakpointed or singlestepping */
+#define TIF_NOCPUID            15      /* CPUID is not accessible in userland */
 #define TIF_NOTSC              16      /* TSC is not accessible in userland */
 #define TIF_IA32               17      /* IA32 compatibility process */
 #define TIF_NOHZ               19      /* in adaptive nohz mode */
@@ -110,6 +111,7 @@ struct thread_info {
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
 #define _TIF_USER_RETURN_NOTIFY        (1 << TIF_USER_RETURN_NOTIFY)
 #define _TIF_UPROBE            (1 << TIF_UPROBE)
+#define _TIF_NOCPUID           (1 << TIF_NOCPUID)
 #define _TIF_NOTSC             (1 << TIF_NOTSC)
 #define _TIF_IA32              (1 << TIF_IA32)
 #define _TIF_NOHZ              (1 << TIF_NOHZ)
@@ -138,7 +140,7 @@ struct thread_info {
 
 /* flags to check in __switch_to() */
 #define _TIF_WORK_CTXSW                                                        \
-       (_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP)
+       (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP)
 
 #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
 #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
@@ -239,6 +241,8 @@ static inline int arch_within_stack_frames(const void * const stack,
 extern void arch_task_cache_init(void);
 extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
 extern void arch_release_task_struct(struct task_struct *tsk);
+extern void arch_setup_new_exec(void);
+#define arch_setup_new_exec arch_setup_new_exec
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_X86_THREAD_INFO_H */
index fc5abff9b7fd63d6b3a01a18061be8b3f752d109..75d002bdb3f35bcc12c06ec4acc213bc49241ae9 100644 (file)
@@ -110,6 +110,16 @@ static inline void cr4_clear_bits(unsigned long mask)
        }
 }
 
+static inline void cr4_toggle_bits(unsigned long mask)
+{
+       unsigned long cr4;
+
+       cr4 = this_cpu_read(cpu_tlbstate.cr4);
+       cr4 ^= mask;
+       this_cpu_write(cpu_tlbstate.cr4, cr4);
+       __write_cr4(cr4);
+}
+
 /* Read the CR4 shadow. */
 static inline unsigned long cr4_read_shadow(void)
 {
index 835aa51c7f6ebb914592752373f55287ca8cc235..c4576551709216cd51c17e42af20c36a19cd5e7a 100644 (file)
@@ -1,10 +1,13 @@
 #ifndef _ASM_X86_PRCTL_H
 #define _ASM_X86_PRCTL_H
 
-#define ARCH_SET_GS 0x1001
-#define ARCH_SET_FS 0x1002
-#define ARCH_GET_FS 0x1003
-#define ARCH_GET_GS 0x1004
+#define ARCH_SET_GS            0x1001
+#define ARCH_SET_FS            0x1002
+#define ARCH_GET_FS            0x1003
+#define ARCH_GET_GS            0x1004
+
+#define ARCH_GET_CPUID         0x1011
+#define ARCH_SET_CPUID         0x1012
 
 #define ARCH_MAP_VDSO_X32      0x2001
 #define ARCH_MAP_VDSO_32       0x2002
index 063197771b8d7ba08f2eafe474cacb0efe9e79d3..dfa90a3a5145d784dafdcd201243d2bcde537897 100644 (file)
@@ -90,16 +90,12 @@ static void probe_xeon_phi_r3mwait(struct cpuinfo_x86 *c)
                return;
        }
 
-       if (ring3mwait_disabled) {
-               msr_clear_bit(MSR_MISC_FEATURE_ENABLES,
-                             MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT);
+       if (ring3mwait_disabled)
                return;
-       }
-
-       msr_set_bit(MSR_MISC_FEATURE_ENABLES,
-                   MSR_MISC_FEATURE_ENABLES_RING3MWAIT_BIT);
 
        set_cpu_cap(c, X86_FEATURE_RING3MWAIT);
+       this_cpu_or(msr_misc_features_shadow,
+                   1UL << MSR_MISC_FEATURES_ENABLES_RING3MWAIT_BIT);
 
        if (c == &boot_cpu_data)
                ELF_HWCAP2 |= HWCAP2_RING3MWAIT;
@@ -488,6 +484,34 @@ static void intel_bsp_resume(struct cpuinfo_x86 *c)
        init_intel_energy_perf(c);
 }
 
+static void init_cpuid_fault(struct cpuinfo_x86 *c)
+{
+       u64 msr;
+
+       if (!rdmsrl_safe(MSR_PLATFORM_INFO, &msr)) {
+               if (msr & MSR_PLATFORM_INFO_CPUID_FAULT)
+                       set_cpu_cap(c, X86_FEATURE_CPUID_FAULT);
+       }
+}
+
+static void init_intel_misc_features(struct cpuinfo_x86 *c)
+{
+       u64 msr;
+
+       if (rdmsrl_safe(MSR_MISC_FEATURES_ENABLES, &msr))
+               return;
+
+       /* Clear all MISC features */
+       this_cpu_write(msr_misc_features_shadow, 0);
+
+       /* Check features and update capabilities and shadow control bits */
+       init_cpuid_fault(c);
+       probe_xeon_phi_r3mwait(c);
+
+       msr = this_cpu_read(msr_misc_features_shadow);
+       wrmsrl(MSR_MISC_FEATURES_ENABLES, msr);
+}
+
 static void init_intel(struct cpuinfo_x86 *c)
 {
        unsigned int l2 = 0;
@@ -602,7 +626,7 @@ static void init_intel(struct cpuinfo_x86 *c)
 
        init_intel_energy_perf(c);
 
-       probe_xeon_phi_r3mwait(c);
+       init_intel_misc_features(c);
 }
 
 #ifdef CONFIG_X86_32
index d688826e5736a18c9f9343ebe278ec2b04bff66d..db2182d63ed0c40ae9057ea100314d0a7c7de8fb 100644 (file)
@@ -67,7 +67,7 @@
 #endif
 
 /* Ensure if the instruction can be boostable */
-extern int can_boost(kprobe_opcode_t *instruction, void *addr);
+extern int can_boost(struct insn *insn, void *orig_addr);
 /* Recover instruction if given address is probed */
 extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf,
                                         unsigned long addr);
@@ -75,7 +75,7 @@ extern unsigned long recover_probed_instruction(kprobe_opcode_t *buf,
  * Copy an instruction and adjust the displacement if the instruction
  * uses the %rip-relative addressing mode.
  */
-extern int __copy_instruction(u8 *dest, u8 *src);
+extern int __copy_instruction(u8 *dest, u8 *src, struct insn *insn);
 
 /* Generate a relative-jump/call instruction */
 extern void synthesize_reljump(void *from, void *to);
index 993fa4fe4f68694a3fa75406b2e762cfadbbf745..19e1f2a6d7b0a74cbae05aaca928d6194d7e0f10 100644 (file)
@@ -164,42 +164,38 @@ static kprobe_opcode_t *skip_prefixes(kprobe_opcode_t *insn)
 NOKPROBE_SYMBOL(skip_prefixes);
 
 /*
- * Returns non-zero if opcode is boostable.
+ * Returns non-zero if INSN is boostable.
  * RIP relative instructions are adjusted at copying time in 64 bits mode
  */
-int can_boost(kprobe_opcode_t *opcodes, void *addr)
+int can_boost(struct insn *insn, void *addr)
 {
        kprobe_opcode_t opcode;
-       kprobe_opcode_t *orig_opcodes = opcodes;
 
        if (search_exception_tables((unsigned long)addr))
                return 0;       /* Page fault may occur on this address. */
 
-retry:
-       if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
-               return 0;
-       opcode = *(opcodes++);
-
        /* 2nd-byte opcode */
-       if (opcode == 0x0f) {
-               if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
-                       return 0;
-               return test_bit(*opcodes,
+       if (insn->opcode.nbytes == 2)
+               return test_bit(insn->opcode.bytes[1],
                                (unsigned long *)twobyte_is_boostable);
-       }
+
+       if (insn->opcode.nbytes != 1)
+               return 0;
+
+       /* Can't boost Address-size override prefix */
+       if (unlikely(inat_is_address_size_prefix(insn->attr)))
+               return 0;
+
+       opcode = insn->opcode.bytes[0];
 
        switch (opcode & 0xf0) {
-#ifdef CONFIG_X86_64
-       case 0x40:
-               goto retry; /* REX prefix is boostable */
-#endif
        case 0x60:
-               if (0x63 < opcode && opcode < 0x67)
-                       goto retry; /* prefixes */
-               /* can't boost Address-size override and bound */
-               return (opcode != 0x62 && opcode != 0x67);
+               /* can't boost "bound" */
+               return (opcode != 0x62);
        case 0x70:
                return 0; /* can't boost conditional jump */
+       case 0x90:
+               return opcode != 0x9a;  /* can't boost call far */
        case 0xc0:
                /* can't boost software-interruptions */
                return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf;
@@ -210,14 +206,9 @@ retry:
                /* can boost in/out and absolute jmps */
                return ((opcode & 0x04) || opcode == 0xea);
        case 0xf0:
-               if ((opcode & 0x0c) == 0 && opcode != 0xf1)
-                       goto retry; /* lock/rep(ne) prefix */
                /* clear and set flags are boostable */
                return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
        default:
-               /* segment override prefixes are boostable */
-               if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e)
-                       goto retry; /* prefixes */
                /* CS override prefix and call are not boostable */
                return (opcode != 0x2e && opcode != 0x9a);
        }
@@ -264,7 +255,10 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
         * Fortunately, we know that the original code is the ideal 5-byte
         * long NOP.
         */
-       memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+       if (probe_kernel_read(buf, (void *)addr,
+               MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
+               return 0UL;
+
        if (faddr)
                memcpy(buf, ideal_nops[NOP_ATOMIC5], 5);
        else
@@ -276,7 +270,7 @@ __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
  * Recover the probed instruction at addr for further analysis.
  * Caller must lock kprobes by kprobe_mutex, or disable preemption
  * for preventing to release referencing kprobes.
- * Returns zero if the instruction can not get recovered.
+ * Returns zero if the instruction can not get recovered (or access failed).
  */
 unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long addr)
 {
@@ -348,37 +342,36 @@ static int is_IF_modifier(kprobe_opcode_t *insn)
 }
 
 /*
- * Copy an instruction and adjust the displacement if the instruction
- * uses the %rip-relative addressing mode.
- * If it does, Return the address of the 32-bit displacement word.
- * If not, return null.
- * Only applicable to 64-bit x86.
+ * Copy an instruction with recovering modified instruction by kprobes
+ * and adjust the displacement if the instruction uses the %rip-relative
+ * addressing mode.
+ * This returns the length of copied instruction, or 0 if it has an error.
  */
-int __copy_instruction(u8 *dest, u8 *src)
+int __copy_instruction(u8 *dest, u8 *src, struct insn *insn)
 {
-       struct insn insn;
        kprobe_opcode_t buf[MAX_INSN_SIZE];
-       int length;
        unsigned long recovered_insn =
                recover_probed_instruction(buf, (unsigned long)src);
 
-       if (!recovered_insn)
+       if (!recovered_insn || !insn)
+               return 0;
+
+       /* This can access kernel text if given address is not recovered */
+       if (probe_kernel_read(dest, (void *)recovered_insn, MAX_INSN_SIZE))
                return 0;
-       kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
-       insn_get_length(&insn);
-       length = insn.length;
+
+       kernel_insn_init(insn, dest, MAX_INSN_SIZE);
+       insn_get_length(insn);
 
        /* Another subsystem puts a breakpoint, failed to recover */
-       if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
+       if (insn->opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
                return 0;
-       memcpy(dest, insn.kaddr, length);
 
 #ifdef CONFIG_X86_64
-       if (insn_rip_relative(&insn)) {
+       /* Only x86_64 has RIP relative instructions */
+       if (insn_rip_relative(insn)) {
                s64 newdisp;
                u8 *disp;
-               kernel_insn_init(&insn, dest, length);
-               insn_get_displacement(&insn);
                /*
                 * The copied instruction uses the %rip-relative addressing
                 * mode.  Adjust the displacement for the difference between
@@ -391,36 +384,57 @@ int __copy_instruction(u8 *dest, u8 *src)
                 * extension of the original signed 32-bit displacement would
                 * have given.
                 */
-               newdisp = (u8 *) src + (s64) insn.displacement.value - (u8 *) dest;
+               newdisp = (u8 *) src + (s64) insn->displacement.value
+                         - (u8 *) dest;
                if ((s64) (s32) newdisp != newdisp) {
                        pr_err("Kprobes error: new displacement does not fit into s32 (%llx)\n", newdisp);
-                       pr_err("\tSrc: %p, Dest: %p, old disp: %x\n", src, dest, insn.displacement.value);
+                       pr_err("\tSrc: %p, Dest: %p, old disp: %x\n",
+                               src, dest, insn->displacement.value);
                        return 0;
                }
-               disp = (u8 *) dest + insn_offset_displacement(&insn);
+               disp = (u8 *) dest + insn_offset_displacement(insn);
                *(s32 *) disp = (s32) newdisp;
        }
 #endif
-       return length;
+       return insn->length;
+}
+
+/* Prepare reljump right after instruction to boost */
+static void prepare_boost(struct kprobe *p, struct insn *insn)
+{
+       if (can_boost(insn, p->addr) &&
+           MAX_INSN_SIZE - insn->length >= RELATIVEJUMP_SIZE) {
+               /*
+                * These instructions can be executed directly if it
+                * jumps back to correct address.
+                */
+               synthesize_reljump(p->ainsn.insn + insn->length,
+                                  p->addr + insn->length);
+               p->ainsn.boostable = true;
+       } else {
+               p->ainsn.boostable = false;
+       }
 }
 
 static int arch_copy_kprobe(struct kprobe *p)
 {
-       int ret;
+       struct insn insn;
+       int len;
+
+       set_memory_rw((unsigned long)p->ainsn.insn & PAGE_MASK, 1);
 
        /* Copy an instruction with recovering if other optprobe modifies it.*/
-       ret = __copy_instruction(p->ainsn.insn, p->addr);
-       if (!ret)
+       len = __copy_instruction(p->ainsn.insn, p->addr, &insn);
+       if (!len)
                return -EINVAL;
 
        /*
         * __copy_instruction can modify the displacement of the instruction,
         * but it doesn't affect boostable check.
         */
-       if (can_boost(p->ainsn.insn, p->addr))
-               p->ainsn.boostable = 0;
-       else
-               p->ainsn.boostable = -1;
+       prepare_boost(p, &insn);
+
+       set_memory_ro((unsigned long)p->ainsn.insn & PAGE_MASK, 1);
 
        /* Check whether the instruction modifies Interrupt Flag or not */
        p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn);
@@ -459,7 +473,7 @@ void arch_disarm_kprobe(struct kprobe *p)
 void arch_remove_kprobe(struct kprobe *p)
 {
        if (p->ainsn.insn) {
-               free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
+               free_insn_slot(p->ainsn.insn, p->ainsn.boostable);
                p->ainsn.insn = NULL;
        }
 }
@@ -531,7 +545,7 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs,
                return;
 
 #if !defined(CONFIG_PREEMPT)
-       if (p->ainsn.boostable == 1 && !p->post_handler) {
+       if (p->ainsn.boostable && !p->post_handler) {
                /* Boost up -- we can execute copied instructions directly */
                if (!reenter)
                        reset_current_kprobe();
@@ -851,7 +865,7 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs,
        case 0xcf:
        case 0xea:      /* jmp absolute -- ip is correct */
                /* ip is already adjusted, no more changes required */
-               p->ainsn.boostable = 1;
+               p->ainsn.boostable = true;
                goto no_change;
        case 0xe8:      /* call relative - Fix return addr */
                *tos = orig_ip + (*tos - copy_ip);
@@ -876,28 +890,13 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs,
                         * jmp near and far, absolute indirect
                         * ip is correct. And this is boostable
                         */
-                       p->ainsn.boostable = 1;
+                       p->ainsn.boostable = true;
                        goto no_change;
                }
        default:
                break;
        }
 
-       if (p->ainsn.boostable == 0) {
-               if ((regs->ip > copy_ip) &&
-                   (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
-                       /*
-                        * These instructions can be executed directly if it
-                        * jumps back to correct address.
-                        */
-                       synthesize_reljump((void *)regs->ip,
-                               (void *)orig_ip + (regs->ip - copy_ip));
-                       p->ainsn.boostable = 1;
-               } else {
-                       p->ainsn.boostable = -1;
-               }
-       }
-
        regs->ip += orig_ip - copy_ip;
 
 no_change:
index 5f8f0b3cc6740bc63a925c5f54e168baa8c39add..041f7b6dfa0fe00f9c6e6611451889d41dc006b9 100644 (file)
@@ -94,6 +94,6 @@ NOKPROBE_SYMBOL(kprobe_ftrace_handler);
 int arch_prepare_kprobe_ftrace(struct kprobe *p)
 {
        p->ainsn.insn = NULL;
-       p->ainsn.boostable = -1;
+       p->ainsn.boostable = false;
        return 0;
 }
index 3e7c6e5a08ffde197c192ab57f3bb38aac590969..9aadff3d0902a910afeb2ea8a82e4bef53e3a299 100644 (file)
@@ -65,7 +65,10 @@ found:
         * overwritten by jump destination address. In this case, original
         * bytes must be recovered from op->optinsn.copied_insn buffer.
         */
-       memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+       if (probe_kernel_read(buf, (void *)addr,
+               MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
+               return 0UL;
+
        if (addr == (unsigned long)kp->addr) {
                buf[0] = kp->opcode;
                memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
@@ -174,11 +177,12 @@ NOKPROBE_SYMBOL(optimized_callback);
 
 static int copy_optimized_instructions(u8 *dest, u8 *src)
 {
+       struct insn insn;
        int len = 0, ret;
 
        while (len < RELATIVEJUMP_SIZE) {
-               ret = __copy_instruction(dest + len, src + len);
-               if (!ret || !can_boost(dest + len, src + len))
+               ret = __copy_instruction(dest + len, src + len, &insn);
+               if (!ret || !can_boost(&insn, src + len))
                        return -EINVAL;
                len += ret;
        }
@@ -350,6 +354,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
        }
 
        buf = (u8 *)op->optinsn.insn;
+       set_memory_rw((unsigned long)buf & PAGE_MASK, 1);
 
        /* Copy instructions into the out-of-line buffer */
        ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr);
@@ -372,6 +377,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
        synthesize_reljump(buf + TMPL_END_IDX + op->optinsn.size,
                           (u8 *)op->kp.addr + op->optinsn.size);
 
+       set_memory_ro((unsigned long)buf & PAGE_MASK, 1);
+
        flush_icache_range((unsigned long) buf,
                           (unsigned long) buf + TMPL_END_IDX +
                           op->optinsn.size + RELATIVEJUMP_SIZE);
index f675915617110fa4cae6c74efc35ba8ccd12eb46..0bb88428cbf2697c89a60311051cc5351ea55fde 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/vm86.h>
 #include <asm/switch_to.h>
 #include <asm/desc.h>
+#include <asm/prctl.h>
 
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
@@ -124,11 +125,6 @@ void flush_thread(void)
        fpu__clear(&tsk->thread.fpu);
 }
 
-static void hard_disable_TSC(void)
-{
-       cr4_set_bits(X86_CR4_TSD);
-}
-
 void disable_TSC(void)
 {
        preempt_disable();
@@ -137,15 +133,10 @@ void disable_TSC(void)
                 * Must flip the CPU state synchronously with
                 * TIF_NOTSC in the current running context.
                 */
-               hard_disable_TSC();
+               cr4_set_bits(X86_CR4_TSD);
        preempt_enable();
 }
 
-static void hard_enable_TSC(void)
-{
-       cr4_clear_bits(X86_CR4_TSD);
-}
-
 static void enable_TSC(void)
 {
        preempt_disable();
@@ -154,7 +145,7 @@ static void enable_TSC(void)
                 * Must flip the CPU state synchronously with
                 * TIF_NOTSC in the current running context.
                 */
-               hard_enable_TSC();
+               cr4_clear_bits(X86_CR4_TSD);
        preempt_enable();
 }
 
@@ -182,54 +173,129 @@ int set_tsc_mode(unsigned int val)
        return 0;
 }
 
-void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
-                     struct tss_struct *tss)
-{
-       struct thread_struct *prev, *next;
-
-       prev = &prev_p->thread;
-       next = &next_p->thread;
+DEFINE_PER_CPU(u64, msr_misc_features_shadow);
 
-       if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^
-           test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) {
-               unsigned long debugctl = get_debugctlmsr();
+static void set_cpuid_faulting(bool on)
+{
+       u64 msrval;
 
-               debugctl &= ~DEBUGCTLMSR_BTF;
-               if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP))
-                       debugctl |= DEBUGCTLMSR_BTF;
+       msrval = this_cpu_read(msr_misc_features_shadow);
+       msrval &= ~MSR_MISC_FEATURES_ENABLES_CPUID_FAULT;
+       msrval |= (on << MSR_MISC_FEATURES_ENABLES_CPUID_FAULT_BIT);
+       this_cpu_write(msr_misc_features_shadow, msrval);
+       wrmsrl(MSR_MISC_FEATURES_ENABLES, msrval);
+}
 
-               update_debugctlmsr(debugctl);
+static void disable_cpuid(void)
+{
+       preempt_disable();
+       if (!test_and_set_thread_flag(TIF_NOCPUID)) {
+               /*
+                * Must flip the CPU state synchronously with
+                * TIF_NOCPUID in the current running context.
+                */
+               set_cpuid_faulting(true);
        }
+       preempt_enable();
+}
 
-       if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
-           test_tsk_thread_flag(next_p, TIF_NOTSC)) {
-               /* prev and next are different */
-               if (test_tsk_thread_flag(next_p, TIF_NOTSC))
-                       hard_disable_TSC();
-               else
-                       hard_enable_TSC();
+static void enable_cpuid(void)
+{
+       preempt_disable();
+       if (test_and_clear_thread_flag(TIF_NOCPUID)) {
+               /*
+                * Must flip the CPU state synchronously with
+                * TIF_NOCPUID in the current running context.
+                */
+               set_cpuid_faulting(false);
        }
+       preempt_enable();
+}
+
+static int get_cpuid_mode(void)
+{
+       return !test_thread_flag(TIF_NOCPUID);
+}
+
+static int set_cpuid_mode(struct task_struct *task, unsigned long cpuid_enabled)
+{
+       if (!static_cpu_has(X86_FEATURE_CPUID_FAULT))
+               return -ENODEV;
+
+       if (cpuid_enabled)
+               enable_cpuid();
+       else
+               disable_cpuid();
+
+       return 0;
+}
+
+/*
+ * Called immediately after a successful exec.
+ */
+void arch_setup_new_exec(void)
+{
+       /* If cpuid was previously disabled for this task, re-enable it. */
+       if (test_thread_flag(TIF_NOCPUID))
+               enable_cpuid();
+}
 
-       if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
+static inline void switch_to_bitmap(struct tss_struct *tss,
+                                   struct thread_struct *prev,
+                                   struct thread_struct *next,
+                                   unsigned long tifp, unsigned long tifn)
+{
+       if (tifn & _TIF_IO_BITMAP) {
                /*
                 * Copy the relevant range of the IO bitmap.
                 * Normally this is 128 bytes or less:
                 */
                memcpy(tss->io_bitmap, next->io_bitmap_ptr,
                       max(prev->io_bitmap_max, next->io_bitmap_max));
-
                /*
                 * Make sure that the TSS limit is correct for the CPU
                 * to notice the IO bitmap.
                 */
                refresh_tss_limit();
-       } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) {
+       } else if (tifp & _TIF_IO_BITMAP) {
                /*
                 * Clear any possible leftover bits:
                 */
                memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
        }
+}
+
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+                     struct tss_struct *tss)
+{
+       struct thread_struct *prev, *next;
+       unsigned long tifp, tifn;
+
+       prev = &prev_p->thread;
+       next = &next_p->thread;
+
+       tifn = READ_ONCE(task_thread_info(next_p)->flags);
+       tifp = READ_ONCE(task_thread_info(prev_p)->flags);
+       switch_to_bitmap(tss, prev, next, tifp, tifn);
+
        propagate_user_return_notify(prev_p, next_p);
+
+       if ((tifp & _TIF_BLOCKSTEP || tifn & _TIF_BLOCKSTEP) &&
+           arch_has_block_step()) {
+               unsigned long debugctl, msk;
+
+               rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+               debugctl &= ~DEBUGCTLMSR_BTF;
+               msk = tifn & _TIF_BLOCKSTEP;
+               debugctl |= (msk >> TIF_BLOCKSTEP) << DEBUGCTLMSR_BTF_SHIFT;
+               wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+       }
+
+       if ((tifp ^ tifn) & _TIF_NOTSC)
+               cr4_toggle_bits(X86_CR4_TSD);
+
+       if ((tifp ^ tifn) & _TIF_NOCPUID)
+               set_cpuid_faulting(!!(tifn & _TIF_NOCPUID));
 }
 
 /*
@@ -550,3 +616,16 @@ out:
        put_task_stack(p);
        return ret;
 }
+
+long do_arch_prctl_common(struct task_struct *task, int option,
+                         unsigned long cpuid_enabled)
+{
+       switch (option) {
+       case ARCH_GET_CPUID:
+               return get_cpuid_mode();
+       case ARCH_SET_CPUID:
+               return set_cpuid_mode(task, cpuid_enabled);
+       }
+
+       return -EINVAL;
+}
index 4c818f8bc1352b46263b63abd111de3910e9811a..ff40e74c9181f0e009b51909a0e76ce25c1c2cf3 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/kdebug.h>
+#include <linux/syscalls.h>
 
 #include <asm/pgtable.h>
 #include <asm/ldt.h>
@@ -56,6 +57,7 @@
 #include <asm/switch_to.h>
 #include <asm/vm86.h>
 #include <asm/intel_rdt.h>
+#include <asm/proto.h>
 
 void __show_regs(struct pt_regs *regs, int all)
 {
@@ -304,3 +306,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 
        return prev_p;
 }
+
+SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
+{
+       return do_arch_prctl_common(current, option, arg2);
+}
index d6b784a5520daf2938cd228daa2bf6bde74c421d..ea1a6180bf3999eed7e2aa27f44500cfb1dfa59f 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/ftrace.h>
+#include <linux/syscalls.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -204,7 +205,7 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
                                (struct user_desc __user *)tls, 0);
                else
 #endif
-                       err = do_arch_prctl(p, ARCH_SET_FS, tls);
+                       err = do_arch_prctl_64(p, ARCH_SET_FS, tls);
                if (err)
                        goto out;
        }
@@ -547,70 +548,72 @@ static long prctl_map_vdso(const struct vdso_image *image, unsigned long addr)
 }
 #endif
 
-long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
+long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2)
 {
        int ret = 0;
        int doit = task == current;
        int cpu;
 
-       switch (code) {
+       switch (option) {
        case ARCH_SET_GS:
-               if (addr >= TASK_SIZE_MAX)
+               if (arg2 >= TASK_SIZE_MAX)
                        return -EPERM;
                cpu = get_cpu();
                task->thread.gsindex = 0;
-               task->thread.gsbase = addr;
+               task->thread.gsbase = arg2;
                if (doit) {
                        load_gs_index(0);
-                       ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr);
+                       ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, arg2);
                }
                put_cpu();
                break;
        case ARCH_SET_FS:
                /* Not strictly needed for fs, but do it for symmetry
                   with gs */
-               if (addr >= TASK_SIZE_MAX)
+               if (arg2 >= TASK_SIZE_MAX)
                        return -EPERM;
                cpu = get_cpu();
                task->thread.fsindex = 0;
-               task->thread.fsbase = addr;
+               task->thread.fsbase = arg2;
                if (doit) {
                        /* set the selector to 0 to not confuse __switch_to */
                        loadsegment(fs, 0);
-                       ret = wrmsrl_safe(MSR_FS_BASE, addr);
+                       ret = wrmsrl_safe(MSR_FS_BASE, arg2);
                }
                put_cpu();
                break;
        case ARCH_GET_FS: {
                unsigned long base;
+
                if (doit)
                        rdmsrl(MSR_FS_BASE, base);
                else
                        base = task->thread.fsbase;
-               ret = put_user(base, (unsigned long __user *)addr);
+               ret = put_user(base, (unsigned long __user *)arg2);
                break;
        }
        case ARCH_GET_GS: {
                unsigned long base;
+
                if (doit)
                        rdmsrl(MSR_KERNEL_GS_BASE, base);
                else
                        base = task->thread.gsbase;
-               ret = put_user(base, (unsigned long __user *)addr);
+               ret = put_user(base, (unsigned long __user *)arg2);
                break;
        }
 
 #ifdef CONFIG_CHECKPOINT_RESTORE
 # ifdef CONFIG_X86_X32_ABI
        case ARCH_MAP_VDSO_X32:
-               return prctl_map_vdso(&vdso_image_x32, addr);
+               return prctl_map_vdso(&vdso_image_x32, arg2);
 # endif
 # if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
        case ARCH_MAP_VDSO_32:
-               return prctl_map_vdso(&vdso_image_32, addr);
+               return prctl_map_vdso(&vdso_image_32, arg2);
 # endif
        case ARCH_MAP_VDSO_64:
-               return prctl_map_vdso(&vdso_image_64, addr);
+               return prctl_map_vdso(&vdso_image_64, arg2);
 #endif
 
        default:
@@ -621,10 +624,23 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
        return ret;
 }
 
-long sys_arch_prctl(int code, unsigned long addr)
+SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
+{
+       long ret;
+
+       ret = do_arch_prctl_64(current, option, arg2);
+       if (ret == -EINVAL)
+               ret = do_arch_prctl_common(current, option, arg2);
+
+       return ret;
+}
+
+#ifdef CONFIG_IA32_EMULATION
+COMPAT_SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
 {
-       return do_arch_prctl(current, code, addr);
+       return do_arch_prctl_common(current, option, arg2);
 }
+#endif
 
 unsigned long KSTK_ESP(struct task_struct *task)
 {
index 2364b23ea3e52c3f5f9901a66574337ae2e23a3f..f37d18124648fb9591779e50c878c4ffd51c51b1 100644 (file)
@@ -396,12 +396,12 @@ static int putreg(struct task_struct *child,
                if (value >= TASK_SIZE_MAX)
                        return -EIO;
                /*
-                * When changing the segment base, use do_arch_prctl
+                * When changing the segment base, use do_arch_prctl_64
                 * to set either thread.fs or thread.fsindex and the
                 * corresponding GDT slot.
                 */
                if (child->thread.fsbase != value)
-                       return do_arch_prctl(child, ARCH_SET_FS, value);
+                       return do_arch_prctl_64(child, ARCH_SET_FS, value);
                return 0;
        case offsetof(struct user_regs_struct,gs_base):
                /*
@@ -410,7 +410,7 @@ static int putreg(struct task_struct *child,
                if (value >= TASK_SIZE_MAX)
                        return -EIO;
                if (child->thread.gsbase != value)
-                       return do_arch_prctl(child, ARCH_SET_GS, value);
+                       return do_arch_prctl_64(child, ARCH_SET_GS, value);
                return 0;
 #endif
        }
@@ -869,7 +869,7 @@ long arch_ptrace(struct task_struct *child, long request,
                   Works just like arch_prctl, except that the arguments
                   are reversed. */
        case PTRACE_ARCH_PRCTL:
-               ret = do_arch_prctl(child, data, addr);
+               ret = do_arch_prctl_64(child, data, addr);
                break;
 #endif
 
index e7e7055a86589dea6d0f9ca043365db4ab8b1b9c..69f0827d5f5391e1ad3b4ff970aa63504c17b434 100644 (file)
@@ -16,7 +16,7 @@ obj-y = bug.o bugs_$(BITS).o delay.o fault.o ldt.o \
 
 ifeq ($(CONFIG_X86_32),y)
 
-obj-y += checksum_32.o
+obj-y += checksum_32.o syscalls_32.o
 obj-$(CONFIG_ELF_CORE) += elfcore.o
 
 subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
index e59eef20647b3e722cc3f5a97fdec08c29071c14..b291ca5cf66bfc83e8176d0d6c05fa82a49ad823 100644 (file)
@@ -78,7 +78,7 @@ static inline int ptrace_set_thread_area(struct task_struct *child, int idx,
         return -ENOSYS;
 }
 
-extern long arch_prctl(struct task_struct *task, int code,
+extern long arch_prctl(struct task_struct *task, int option,
                       unsigned long __user *addr);
 
 #endif
index 96eb2bd288320b28e1ff6278bd0d410f1536ceab..8431e87ac33338eed5d037fe07259558c9b5ee23 100644 (file)
@@ -6,7 +6,7 @@
 #include <sys/ptrace.h>
 #include <asm/ptrace.h>
 
-int os_arch_prctl(int pid, int code, unsigned long *addr)
+int os_arch_prctl(int pid, int option, unsigned long *arg2)
 {
-        return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code);
+       return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) arg2, option);
 }
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c
new file mode 100644 (file)
index 0000000..627d688
--- /dev/null
@@ -0,0 +1,7 @@
+#include <linux/syscalls.h>
+#include <os.h>
+
+SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
+{
+       return -EINVAL;
+}
index 10d907098c2614835b002cbdc8d754cca1f7d56a..81b9fe100f7c085b1fc04b14c758a16edde34321 100644 (file)
@@ -7,13 +7,15 @@
 
 #include <linux/sched.h>
 #include <linux/sched/mm.h>
+#include <linux/syscalls.h>
 #include <linux/uaccess.h>
 #include <asm/prctl.h> /* XXX This should get the constants from libc */
 #include <os.h>
 
-long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
+long arch_prctl(struct task_struct *task, int option)
+               unsigned long __user *arg2)
 {
-       unsigned long *ptr = addr, tmp;
+       unsigned long *ptr = arg2, tmp;
        long ret;
        int pid = task->mm->context.id.u.pid;
 
@@ -30,7 +32,7 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
         * arch_prctl is run on the host, then the registers are read
         * back.
         */
-       switch (code) {
+       switch (option) {
        case ARCH_SET_FS:
        case ARCH_SET_GS:
                ret = restore_registers(pid, &current->thread.regs.regs);
@@ -50,11 +52,11 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
                ptr = &tmp;
        }
 
-       ret = os_arch_prctl(pid, code, ptr);
+       ret = os_arch_prctl(pid, option, ptr);
        if (ret)
                return ret;
 
-       switch (code) {
+       switch (option) {
        case ARCH_SET_FS:
                current->thread.arch.fs = (unsigned long) ptr;
                ret = save_registers(pid, &current->thread.regs.regs);
@@ -63,19 +65,19 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
                ret = save_registers(pid, &current->thread.regs.regs);
                break;
        case ARCH_GET_FS:
-               ret = put_user(tmp, addr);
+               ret = put_user(tmp, arg2);
                break;
        case ARCH_GET_GS:
-               ret = put_user(tmp, addr);
+               ret = put_user(tmp, arg2);
                break;
        }
 
        return ret;
 }
 
-long sys_arch_prctl(int code, unsigned long addr)
+SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
 {
-       return arch_prctl(current, code, (unsigned long __user *) addr);
+       return arch_prctl(current, option, (unsigned long __user *) arg2);
 }
 
 void arch_switch_to(struct task_struct *to)
index d7325c6534ad9d96e899fce16ddb6fa2e6148c4b..979ea6ec7902b26f4382f8c0b56530c69226233f 100644 (file)
@@ -321,7 +321,7 @@ static int etb_set_buffer(struct coresight_device *csdev,
 
 static unsigned long etb_reset_buffer(struct coresight_device *csdev,
                                      struct perf_output_handle *handle,
-                                     void *sink_config, bool *lost)
+                                     void *sink_config)
 {
        unsigned long size = 0;
        struct cs_buffers *buf = sink_config;
@@ -343,7 +343,6 @@ static unsigned long etb_reset_buffer(struct coresight_device *csdev,
                 * resetting parameters here and squaring off with the ring
                 * buffer API in the tracer PMU is fine.
                 */
-               *lost = !!local_xchg(&buf->lost, 0);
                size = local_xchg(&buf->data_size, 0);
        }
 
@@ -385,7 +384,7 @@ static void etb_update_buffer(struct coresight_device *csdev,
                        (unsigned long)write_ptr);
 
                write_ptr &= ~(ETB_FRAME_SIZE_WORDS - 1);
-               local_inc(&buf->lost);
+               perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
        }
 
        /*
@@ -396,7 +395,7 @@ static void etb_update_buffer(struct coresight_device *csdev,
         */
        status = readl_relaxed(drvdata->base + ETB_STATUS_REG);
        if (status & ETB_STATUS_RAM_FULL) {
-               local_inc(&buf->lost);
+               perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
                to_read = capacity;
                read_ptr = write_ptr;
        } else {
@@ -429,7 +428,7 @@ static void etb_update_buffer(struct coresight_device *csdev,
                if (read_ptr > (drvdata->buffer_depth - 1))
                        read_ptr -= drvdata->buffer_depth;
                /* let the decoder know we've skipped ahead */
-               local_inc(&buf->lost);
+               perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
        }
 
        /* finally tell HW where we want to start reading from */
index 26cfac3e6de7be45d6de4e7d2ffa1e8c52a3f39d..288a423c1b27022e21e887beceb5e1709af18f84 100644 (file)
@@ -302,7 +302,8 @@ out:
        return;
 
 fail_end_stop:
-       perf_aux_output_end(handle, 0, true);
+       perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
+       perf_aux_output_end(handle, 0);
 fail:
        event->hw.state = PERF_HES_STOPPED;
        goto out;
@@ -310,7 +311,6 @@ fail:
 
 static void etm_event_stop(struct perf_event *event, int mode)
 {
-       bool lost;
        int cpu = smp_processor_id();
        unsigned long size;
        struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
@@ -348,10 +348,9 @@ static void etm_event_stop(struct perf_event *event, int mode)
                        return;
 
                size = sink_ops(sink)->reset_buffer(sink, handle,
-                                                   event_data->snk_config,
-                                                   &lost);
+                                                   event_data->snk_config);
 
-               perf_aux_output_end(handle, size, lost);
+               perf_aux_output_end(handle, size);
        }
 
        /* Disabling the path make its elements available to other sessions */
index ef9d8e93e3b2e0b6959107b57b2689695e33604d..5f662d82052c5c148ba334f1569d5dbd1f975df6 100644 (file)
@@ -76,7 +76,6 @@ enum cs_mode {
  * @nr_pages:  max number of pages granted to us
  * @offset:    offset within the current buffer
  * @data_size: how much we collected in this run
- * @lost:      other than zero if we had a HW buffer wrap around
  * @snapshot:  is this run in snapshot mode
  * @data_pages:        a handle the ring buffer
  */
@@ -85,7 +84,6 @@ struct cs_buffers {
        unsigned int            nr_pages;
        unsigned long           offset;
        local_t                 data_size;
-       local_t                 lost;
        bool                    snapshot;
        void                    **data_pages;
 };
index 1549436e249242064fe1238957e7d00f4bf5ba3c..aec61a6d5c633ee6ec64437af6daaec68953fbde 100644 (file)
@@ -329,7 +329,7 @@ static int tmc_set_etf_buffer(struct coresight_device *csdev,
 
 static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev,
                                          struct perf_output_handle *handle,
-                                         void *sink_config, bool *lost)
+                                         void *sink_config)
 {
        long size = 0;
        struct cs_buffers *buf = sink_config;
@@ -350,7 +350,6 @@ static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev,
                 * resetting parameters here and squaring off with the ring
                 * buffer API in the tracer PMU is fine.
                 */
-               *lost = !!local_xchg(&buf->lost, 0);
                size = local_xchg(&buf->data_size, 0);
        }
 
@@ -389,7 +388,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
         */
        status = readl_relaxed(drvdata->base + TMC_STS);
        if (status & TMC_STS_FULL) {
-               local_inc(&buf->lost);
+               perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
                to_read = drvdata->size;
        } else {
                to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size);
@@ -434,7 +433,7 @@ static void tmc_update_etf_buffer(struct coresight_device *csdev,
                        read_ptr -= drvdata->size;
                /* Tell the HW */
                writel_relaxed(read_ptr, drvdata->base + TMC_RRP);
-               local_inc(&buf->lost);
+               perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
        }
 
        cur = buf->cur;
index b17536d6e69bdbf956a61d8c3dff06351a1a51df..63cacf5d6cf23ab5611ba4219207a47c00662226 100644 (file)
@@ -1234,7 +1234,7 @@ static void __domain_flush_pages(struct protection_domain *domain,
 
        build_inv_iommu_pages(&cmd, address, size, domain->id, pde);
 
-       for (i = 0; i < amd_iommus_present; ++i) {
+       for (i = 0; i < amd_iommu_get_num_iommus(); ++i) {
                if (!domain->dev_iommu[i])
                        continue;
 
@@ -1278,7 +1278,7 @@ static void domain_flush_complete(struct protection_domain *domain)
 {
        int i;
 
-       for (i = 0; i < amd_iommus_present; ++i) {
+       for (i = 0; i < amd_iommu_get_num_iommus(); ++i) {
                if (domain && !domain->dev_iommu[i])
                        continue;
 
@@ -3363,7 +3363,7 @@ static int __flush_pasid(struct protection_domain *domain, int pasid,
         * IOMMU TLB needs to be flushed before Device TLB to
         * prevent device TLB refill from IOMMU TLB
         */
-       for (i = 0; i < amd_iommus_present; ++i) {
+       for (i = 0; i < amd_iommu_get_num_iommus(); ++i) {
                if (domain->dev_iommu[i] == 0)
                        continue;
 
index 6130278c5d71bd08e925cc35007610bc32736938..5a11328f4d9854457f5e078ab0b3dd29aff04b6e 100644 (file)
@@ -167,7 +167,9 @@ LIST_HEAD(amd_iommu_list);          /* list of all AMD IOMMUs in the
 
 /* Array to assign indices to IOMMUs*/
 struct amd_iommu *amd_iommus[MAX_IOMMUS];
-int amd_iommus_present;
+
+/* Number of IOMMUs present in the system */
+static int amd_iommus_present;
 
 /* IOMMUs have a non-present cache? */
 bool amd_iommu_np_cache __read_mostly;
@@ -254,10 +256,6 @@ static int amd_iommu_enable_interrupts(void);
 static int __init iommu_go_to_state(enum iommu_init_state state);
 static void init_device_table_dma(void);
 
-static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
-                                   u8 bank, u8 cntr, u8 fxn,
-                                   u64 *value, bool is_write);
-
 static inline void update_last_devid(u16 devid)
 {
        if (devid > amd_iommu_last_bdf)
@@ -272,6 +270,11 @@ static inline unsigned long tbl_size(int entry_size)
        return 1UL << shift;
 }
 
+int amd_iommu_get_num_iommus(void)
+{
+       return amd_iommus_present;
+}
+
 /* Access to l1 and l2 indexed register spaces */
 
 static u32 iommu_read_l1(struct amd_iommu *iommu, u16 l1, u8 address)
@@ -1336,7 +1339,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
 
        /* Add IOMMU to internal data structures */
        list_add_tail(&iommu->list, &amd_iommu_list);
-       iommu->index             = amd_iommus_present++;
+       iommu->index = amd_iommus_present++;
 
        if (unlikely(iommu->index >= MAX_IOMMUS)) {
                WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n");
@@ -1477,6 +1480,8 @@ static int __init init_iommu_all(struct acpi_table_header *table)
        return 0;
 }
 
+static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
+                               u8 fxn, u64 *value, bool is_write);
 
 static void init_iommu_perf_ctr(struct amd_iommu *iommu)
 {
@@ -1488,8 +1493,8 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu)
        amd_iommu_pc_present = true;
 
        /* Check if the performance counters can be written to */
-       if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) ||
-           (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) ||
+       if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) ||
+           (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) ||
            (val != val2)) {
                pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n");
                amd_iommu_pc_present = false;
@@ -2711,6 +2716,18 @@ bool amd_iommu_v2_supported(void)
 }
 EXPORT_SYMBOL(amd_iommu_v2_supported);
 
+struct amd_iommu *get_amd_iommu(unsigned int idx)
+{
+       unsigned int i = 0;
+       struct amd_iommu *iommu;
+
+       for_each_iommu(iommu)
+               if (i++ == idx)
+                       return iommu;
+       return NULL;
+}
+EXPORT_SYMBOL(get_amd_iommu);
+
 /****************************************************************************
  *
  * IOMMU EFR Performance Counter support functionality. This code allows
@@ -2718,17 +2735,14 @@ EXPORT_SYMBOL(amd_iommu_v2_supported);
  *
  ****************************************************************************/
 
-u8 amd_iommu_pc_get_max_banks(u16 devid)
+u8 amd_iommu_pc_get_max_banks(unsigned int idx)
 {
-       struct amd_iommu *iommu;
-       u8 ret = 0;
+       struct amd_iommu *iommu = get_amd_iommu(idx);
 
-       /* locate the iommu governing the devid */
-       iommu = amd_iommu_rlookup_table[devid];
        if (iommu)
-               ret = iommu->max_banks;
+               return iommu->max_banks;
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(amd_iommu_pc_get_max_banks);
 
@@ -2738,62 +2752,69 @@ bool amd_iommu_pc_supported(void)
 }
 EXPORT_SYMBOL(amd_iommu_pc_supported);
 
-u8 amd_iommu_pc_get_max_counters(u16 devid)
+u8 amd_iommu_pc_get_max_counters(unsigned int idx)
 {
-       struct amd_iommu *iommu;
-       u8 ret = 0;
+       struct amd_iommu *iommu = get_amd_iommu(idx);
 
-       /* locate the iommu governing the devid */
-       iommu = amd_iommu_rlookup_table[devid];
        if (iommu)
-               ret = iommu->max_counters;
+               return iommu->max_counters;
 
-       return ret;
+       return 0;
 }
 EXPORT_SYMBOL(amd_iommu_pc_get_max_counters);
 
-static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
-                                   u8 bank, u8 cntr, u8 fxn,
-                                   u64 *value, bool is_write)
+static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
+                               u8 fxn, u64 *value, bool is_write)
 {
        u32 offset;
        u32 max_offset_lim;
 
+       /* Make sure the IOMMU PC resource is available */
+       if (!amd_iommu_pc_present)
+               return -ENODEV;
+
        /* Check for valid iommu and pc register indexing */
-       if (WARN_ON((fxn > 0x28) || (fxn & 7)))
+       if (WARN_ON(!iommu || (fxn > 0x28) || (fxn & 7)))
                return -ENODEV;
 
-       offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn);
+       offset = (u32)(((0x40 | bank) << 12) | (cntr << 8) | fxn);
 
        /* Limit the offset to the hw defined mmio region aperture */
-       max_offset_lim = (u32)(((0x40|iommu->max_banks) << 12) |
+       max_offset_lim = (u32)(((0x40 | iommu->max_banks) << 12) |
                                (iommu->max_counters << 8) | 0x28);
        if ((offset < MMIO_CNTR_REG_OFFSET) ||
            (offset > max_offset_lim))
                return -EINVAL;
 
        if (is_write) {
-               writel((u32)*value, iommu->mmio_base + offset);
-               writel((*value >> 32), iommu->mmio_base + offset + 4);
+               u64 val = *value & GENMASK_ULL(47, 0);
+
+               writel((u32)val, iommu->mmio_base + offset);
+               writel((val >> 32), iommu->mmio_base + offset + 4);
        } else {
                *value = readl(iommu->mmio_base + offset + 4);
                *value <<= 32;
-               *value = readl(iommu->mmio_base + offset);
+               *value |= readl(iommu->mmio_base + offset);
+               *value &= GENMASK_ULL(47, 0);
        }
 
        return 0;
 }
-EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val);
 
-int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
-                                   u64 *value, bool is_write)
+int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, u8 fxn, u64 *value)
 {
-       struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+       if (!iommu)
+               return -EINVAL;
 
-       /* Make sure the IOMMU PC resource is available */
-       if (!amd_iommu_pc_present || iommu == NULL)
-               return -ENODEV;
+       return iommu_pc_get_set_reg(iommu, bank, cntr, fxn, value, false);
+}
+EXPORT_SYMBOL(amd_iommu_pc_get_reg);
+
+int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, u8 fxn, u64 *value)
+{
+       if (!iommu)
+               return -EINVAL;
 
-       return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn,
-                                       value, is_write);
+       return iommu_pc_get_set_reg(iommu, bank, cntr, fxn, value, true);
 }
+EXPORT_SYMBOL(amd_iommu_pc_set_reg);
index 7eb60c15c5826c83c594b47bd43316c3985e5bd5..466260f8a1df37bb79738d4c8f91b90568cdd7c6 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "amd_iommu_types.h"
 
+extern int amd_iommu_get_num_iommus(void);
 extern int amd_iommu_init_dma_ops(void);
 extern int amd_iommu_init_passthrough(void);
 extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
@@ -56,13 +57,6 @@ extern int amd_iommu_domain_set_gcr3(struct iommu_domain *dom, int pasid,
 extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid);
 extern struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev);
 
-/* IOMMU Performance Counter functions */
-extern bool amd_iommu_pc_supported(void);
-extern u8 amd_iommu_pc_get_max_banks(u16 devid);
-extern u8 amd_iommu_pc_get_max_counters(u16 devid);
-extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
-                                   u64 *value, bool is_write);
-
 #ifdef CONFIG_IRQ_REMAP
 extern int amd_iommu_create_irq_domain(struct amd_iommu *iommu);
 #else
index 003f3ceb2661c3cf1112cf39ecb7e1afb3488772..4de8f4160bb81592bea7dd0aaa6e06aebcd777cf 100644 (file)
@@ -611,9 +611,6 @@ extern struct list_head amd_iommu_list;
  */
 extern struct amd_iommu *amd_iommus[MAX_IOMMUS];
 
-/* Number of IOMMUs present in the system */
-extern int amd_iommus_present;
-
 /*
  * Declarations for the global list of all protection domains
  */
index 65145a3df065192345c66ebc311d464fe09a6f29..72934df6847150ba50dfbadad78fe10e01d2eadd 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1320,6 +1320,7 @@ void setup_new_exec(struct linux_binprm * bprm)
        else
                set_dumpable(current->mm, suid_dumpable);
 
+       arch_setup_new_exec();
        perf_event_exec();
        __set_task_comm(current, kbasename(bprm->filename), true);
 
index aef47be2a5c1a3fd3ea75161f5bc93627772515c..af9dbc44fd9212f42b1fd07212f8dda7d059ed53 100644 (file)
@@ -723,6 +723,8 @@ asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid,
 asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32,
                                            int, const char __user *);
 
+asmlinkage long compat_sys_arch_prctl(int option, unsigned long arg2);
+
 /*
  * For most but not all architectures, "am I in a compat syscall?" and
  * "am I a compat task?" are the same question.  For architectures on which
index 2a5982c37dfb660d344777c79dcde044ca304f1c..035c16c9a5051afccd8e77db5417335866812c8d 100644 (file)
@@ -201,7 +201,7 @@ struct coresight_ops_sink {
                          void *sink_config);
        unsigned long (*reset_buffer)(struct coresight_device *csdev,
                                      struct perf_output_handle *handle,
-                                     void *sink_config, bool *lost);
+                                     void *sink_config);
        void (*update_buffer)(struct coresight_device *csdev,
                              struct perf_output_handle *handle,
                              void *sink_config);
index c328e4f7dcadb4276bddcfbcc97caa323c48a0a3..47e4da5b4fa29a71a21ceb988ce715dd7a478f47 100644 (file)
@@ -267,6 +267,8 @@ extern int arch_init_kprobes(void);
 extern void show_registers(struct pt_regs *regs);
 extern void kprobes_inc_nmissed_count(struct kprobe *p);
 extern bool arch_within_kprobe_blacklist(unsigned long addr);
+extern bool arch_function_offset_within_entry(unsigned long offset);
+extern bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset);
 
 extern bool within_kprobe_blacklist(unsigned long addr);
 
index 000fdb211c7d7e2c8fc7351a99dbf6b58fbcb135..24a635887f28df99379d8b683fd94154c7888a69 100644 (file)
@@ -165,6 +165,13 @@ struct hw_perf_event {
                        struct list_head                bp_list;
                };
 #endif
+               struct { /* amd_iommu */
+                       u8      iommu_bank;
+                       u8      iommu_cntr;
+                       u16     padding;
+                       u64     conf;
+                       u64     conf1;
+               };
        };
        /*
         * If the event is a per task event, this will point to the task in
@@ -801,6 +808,7 @@ struct perf_output_handle {
        struct ring_buffer              *rb;
        unsigned long                   wakeup;
        unsigned long                   size;
+       u64                             aux_flags;
        union {
                void                    *addr;
                unsigned long           head;
@@ -849,10 +857,11 @@ perf_cgroup_from_task(struct task_struct *task, struct perf_event_context *ctx)
 extern void *perf_aux_output_begin(struct perf_output_handle *handle,
                                   struct perf_event *event);
 extern void perf_aux_output_end(struct perf_output_handle *handle,
-                               unsigned long size, bool truncated);
+                               unsigned long size);
 extern int perf_aux_output_skip(struct perf_output_handle *handle,
                                unsigned long size);
 extern void *perf_get_aux(struct perf_output_handle *handle);
+extern void perf_aux_output_flag(struct perf_output_handle *handle, u64 flags);
 
 extern int perf_pmu_register(struct pmu *pmu, const char *name, int type);
 extern void perf_pmu_unregister(struct pmu *pmu);
@@ -1112,6 +1121,7 @@ extern int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks
 
 extern void perf_event_exec(void);
 extern void perf_event_comm(struct task_struct *tsk, bool exec);
+extern void perf_event_namespaces(struct task_struct *tsk);
 extern void perf_event_fork(struct task_struct *tsk);
 
 /* Callchains */
@@ -1267,8 +1277,8 @@ static inline void *
 perf_aux_output_begin(struct perf_output_handle *handle,
                      struct perf_event *event)                         { return NULL; }
 static inline void
-perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
-                   bool truncated)                                     { }
+perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
+                                                                       { }
 static inline int
 perf_aux_output_skip(struct perf_output_handle *handle,
                     unsigned long size)                                { return -EINVAL; }
@@ -1315,6 +1325,7 @@ static inline int perf_unregister_guest_info_callbacks
 static inline void perf_event_mmap(struct vm_area_struct *vma)         { }
 static inline void perf_event_exec(void)                               { }
 static inline void perf_event_comm(struct task_struct *tsk, bool exec) { }
+static inline void perf_event_namespaces(struct task_struct *tsk)      { }
 static inline void perf_event_fork(struct task_struct *tsk)            { }
 static inline void perf_event_init(void)                               { }
 static inline int  perf_swevent_get_recursion_context(void)            { return -1; }
index 58373875e8eec2aee668e5fdac4526796ebe78c8..55125d67433851df5fffba9f641e907735bae772 100644 (file)
@@ -101,6 +101,10 @@ static inline void check_object_size(const void *ptr, unsigned long n,
 { }
 #endif /* CONFIG_HARDENED_USERCOPY */
 
+#ifndef arch_setup_new_exec
+static inline void arch_setup_new_exec(void) { }
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_THREAD_INFO_H */
index c66a485a24ac81e324ea53ea17b405a3c73b520a..d09a9cd021b1230730d23eefd0c149df51852c93 100644 (file)
@@ -344,7 +344,8 @@ struct perf_event_attr {
                                use_clockid    :  1, /* use @clockid for time fields */
                                context_switch :  1, /* context switch data */
                                write_backward :  1, /* Write ring buffer from end to beginning */
-                               __reserved_1   : 36;
+                               namespaces     :  1, /* include namespaces data */
+                               __reserved_1   : 35;
 
        union {
                __u32           wakeup_events;    /* wakeup every n events */
@@ -610,6 +611,23 @@ struct perf_event_header {
        __u16   size;
 };
 
+struct perf_ns_link_info {
+       __u64   dev;
+       __u64   ino;
+};
+
+enum {
+       NET_NS_INDEX            = 0,
+       UTS_NS_INDEX            = 1,
+       IPC_NS_INDEX            = 2,
+       PID_NS_INDEX            = 3,
+       USER_NS_INDEX           = 4,
+       MNT_NS_INDEX            = 5,
+       CGROUP_NS_INDEX         = 6,
+
+       NR_NAMESPACES,          /* number of available namespaces */
+};
+
 enum perf_event_type {
 
        /*
@@ -862,6 +880,18 @@ enum perf_event_type {
         */
        PERF_RECORD_SWITCH_CPU_WIDE             = 15,
 
+       /*
+        * struct {
+        *      struct perf_event_header        header;
+        *      u32                             pid;
+        *      u32                             tid;
+        *      u64                             nr_namespaces;
+        *      { u64                           dev, inode; } [nr_namespaces];
+        *      struct sample_id                sample_id;
+        * };
+        */
+       PERF_RECORD_NAMESPACES                  = 16,
+
        PERF_RECORD_MAX,                        /* non-ABI */
 };
 
@@ -885,6 +915,7 @@ enum perf_callchain_context {
  */
 #define PERF_AUX_FLAG_TRUNCATED                0x01    /* record was truncated to fit */
 #define PERF_AUX_FLAG_OVERWRITE                0x02    /* snapshot from overwrite mode */
+#define PERF_AUX_FLAG_PARTIAL          0x04    /* record contains gaps */
 
 #define PERF_FLAG_FD_NO_GROUP          (1UL << 0)
 #define PERF_FLAG_FD_OUTPUT            (1UL << 1)
index ff01cba86f430fd29916ab73c755698bf81feff0..6e75a5c9412dee17daabc1cb131bb517ad431207 100644 (file)
@@ -48,6 +48,8 @@
 #include <linux/parser.h>
 #include <linux/sched/clock.h>
 #include <linux/sched/mm.h>
+#include <linux/proc_ns.h>
+#include <linux/mount.h>
 
 #include "internal.h"
 
@@ -379,6 +381,7 @@ static DEFINE_PER_CPU(struct pmu_event_list, pmu_sb_events);
 
 static atomic_t nr_mmap_events __read_mostly;
 static atomic_t nr_comm_events __read_mostly;
+static atomic_t nr_namespaces_events __read_mostly;
 static atomic_t nr_task_events __read_mostly;
 static atomic_t nr_freq_events __read_mostly;
 static atomic_t nr_switch_events __read_mostly;
@@ -3991,6 +3994,8 @@ static void unaccount_event(struct perf_event *event)
                atomic_dec(&nr_mmap_events);
        if (event->attr.comm)
                atomic_dec(&nr_comm_events);
+       if (event->attr.namespaces)
+               atomic_dec(&nr_namespaces_events);
        if (event->attr.task)
                atomic_dec(&nr_task_events);
        if (event->attr.freq)
@@ -6491,6 +6496,7 @@ static void perf_event_task(struct task_struct *task,
 void perf_event_fork(struct task_struct *task)
 {
        perf_event_task(task, NULL, 1);
+       perf_event_namespaces(task);
 }
 
 /*
@@ -6592,6 +6598,132 @@ void perf_event_comm(struct task_struct *task, bool exec)
        perf_event_comm_event(&comm_event);
 }
 
+/*
+ * namespaces tracking
+ */
+
+struct perf_namespaces_event {
+       struct task_struct              *task;
+
+       struct {
+               struct perf_event_header        header;
+
+               u32                             pid;
+               u32                             tid;
+               u64                             nr_namespaces;
+               struct perf_ns_link_info        link_info[NR_NAMESPACES];
+       } event_id;
+};
+
+static int perf_event_namespaces_match(struct perf_event *event)
+{
+       return event->attr.namespaces;
+}
+
+static void perf_event_namespaces_output(struct perf_event *event,
+                                        void *data)
+{
+       struct perf_namespaces_event *namespaces_event = data;
+       struct perf_output_handle handle;
+       struct perf_sample_data sample;
+       int ret;
+
+       if (!perf_event_namespaces_match(event))
+               return;
+
+       perf_event_header__init_id(&namespaces_event->event_id.header,
+                                  &sample, event);
+       ret = perf_output_begin(&handle, event,
+                               namespaces_event->event_id.header.size);
+       if (ret)
+               return;
+
+       namespaces_event->event_id.pid = perf_event_pid(event,
+                                                       namespaces_event->task);
+       namespaces_event->event_id.tid = perf_event_tid(event,
+                                                       namespaces_event->task);
+
+       perf_output_put(&handle, namespaces_event->event_id);
+
+       perf_event__output_id_sample(event, &handle, &sample);
+
+       perf_output_end(&handle);
+}
+
+static void perf_fill_ns_link_info(struct perf_ns_link_info *ns_link_info,
+                                  struct task_struct *task,
+                                  const struct proc_ns_operations *ns_ops)
+{
+       struct path ns_path;
+       struct inode *ns_inode;
+       void *error;
+
+       error = ns_get_path(&ns_path, task, ns_ops);
+       if (!error) {
+               ns_inode = ns_path.dentry->d_inode;
+               ns_link_info->dev = new_encode_dev(ns_inode->i_sb->s_dev);
+               ns_link_info->ino = ns_inode->i_ino;
+       }
+}
+
+void perf_event_namespaces(struct task_struct *task)
+{
+       struct perf_namespaces_event namespaces_event;
+       struct perf_ns_link_info *ns_link_info;
+
+       if (!atomic_read(&nr_namespaces_events))
+               return;
+
+       namespaces_event = (struct perf_namespaces_event){
+               .task   = task,
+               .event_id  = {
+                       .header = {
+                               .type = PERF_RECORD_NAMESPACES,
+                               .misc = 0,
+                               .size = sizeof(namespaces_event.event_id),
+                       },
+                       /* .pid */
+                       /* .tid */
+                       .nr_namespaces = NR_NAMESPACES,
+                       /* .link_info[NR_NAMESPACES] */
+               },
+       };
+
+       ns_link_info = namespaces_event.event_id.link_info;
+
+       perf_fill_ns_link_info(&ns_link_info[MNT_NS_INDEX],
+                              task, &mntns_operations);
+
+#ifdef CONFIG_USER_NS
+       perf_fill_ns_link_info(&ns_link_info[USER_NS_INDEX],
+                              task, &userns_operations);
+#endif
+#ifdef CONFIG_NET_NS
+       perf_fill_ns_link_info(&ns_link_info[NET_NS_INDEX],
+                              task, &netns_operations);
+#endif
+#ifdef CONFIG_UTS_NS
+       perf_fill_ns_link_info(&ns_link_info[UTS_NS_INDEX],
+                              task, &utsns_operations);
+#endif
+#ifdef CONFIG_IPC_NS
+       perf_fill_ns_link_info(&ns_link_info[IPC_NS_INDEX],
+                              task, &ipcns_operations);
+#endif
+#ifdef CONFIG_PID_NS
+       perf_fill_ns_link_info(&ns_link_info[PID_NS_INDEX],
+                              task, &pidns_operations);
+#endif
+#ifdef CONFIG_CGROUPS
+       perf_fill_ns_link_info(&ns_link_info[CGROUP_NS_INDEX],
+                              task, &cgroupns_operations);
+#endif
+
+       perf_iterate_sb(perf_event_namespaces_output,
+                       &namespaces_event,
+                       NULL);
+}
+
 /*
  * mmap tracking
  */
@@ -9146,6 +9278,8 @@ static void account_event(struct perf_event *event)
                atomic_inc(&nr_mmap_events);
        if (event->attr.comm)
                atomic_inc(&nr_comm_events);
+       if (event->attr.namespaces)
+               atomic_inc(&nr_namespaces_events);
        if (event->attr.task)
                atomic_inc(&nr_task_events);
        if (event->attr.freq)
@@ -9691,6 +9825,11 @@ SYSCALL_DEFINE5(perf_event_open,
                        return -EACCES;
        }
 
+       if (attr.namespaces) {
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EACCES;
+       }
+
        if (attr.freq) {
                if (attr.sample_freq > sysctl_perf_event_sample_rate)
                        return -EINVAL;
index 257fa460b846032744e2da500d489d0995678571..2831480c63a28b8e9b8cee1c0b30968860b3fcd0 100644 (file)
@@ -297,6 +297,19 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
                rb->paused = 1;
 }
 
+void perf_aux_output_flag(struct perf_output_handle *handle, u64 flags)
+{
+       /*
+        * OVERWRITE is determined by perf_aux_output_end() and can't
+        * be passed in directly.
+        */
+       if (WARN_ON_ONCE(flags & PERF_AUX_FLAG_OVERWRITE))
+               return;
+
+       handle->aux_flags |= flags;
+}
+EXPORT_SYMBOL_GPL(perf_aux_output_flag);
+
 /*
  * This is called before hardware starts writing to the AUX area to
  * obtain an output handle and make sure there's room in the buffer.
@@ -360,6 +373,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
        handle->event = event;
        handle->head = aux_head;
        handle->size = 0;
+       handle->aux_flags = 0;
 
        /*
         * In overwrite mode, AUX data stores do not depend on aux_tail,
@@ -408,34 +422,32 @@ err:
  * of the AUX buffer management code is that after pmu::stop(), the AUX
  * transaction must be stopped and therefore drop the AUX reference count.
  */
-void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
-                        bool truncated)
+void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
 {
+       bool wakeup = !!(handle->aux_flags & PERF_AUX_FLAG_TRUNCATED);
        struct ring_buffer *rb = handle->rb;
-       bool wakeup = truncated;
        unsigned long aux_head;
-       u64 flags = 0;
-
-       if (truncated)
-               flags |= PERF_AUX_FLAG_TRUNCATED;
 
        /* in overwrite mode, driver provides aux_head via handle */
        if (rb->aux_overwrite) {
-               flags |= PERF_AUX_FLAG_OVERWRITE;
+               handle->aux_flags |= PERF_AUX_FLAG_OVERWRITE;
 
                aux_head = handle->head;
                local_set(&rb->aux_head, aux_head);
        } else {
+               handle->aux_flags &= ~PERF_AUX_FLAG_OVERWRITE;
+
                aux_head = local_read(&rb->aux_head);
                local_add(size, &rb->aux_head);
        }
 
-       if (size || flags) {
+       if (size || handle->aux_flags) {
                /*
                 * Only send RECORD_AUX if we have something useful to communicate
                 */
 
-               perf_event_aux_event(handle->event, aux_head, size, flags);
+               perf_event_aux_event(handle->event, aux_head, size,
+                                    handle->aux_flags);
        }
 
        aux_head = rb->user_page->aux_head = local_read(&rb->aux_head);
@@ -446,7 +458,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
        }
 
        if (wakeup) {
-               if (truncated)
+               if (handle->aux_flags & PERF_AUX_FLAG_TRUNCATED)
                        handle->event->pending_disable = 1;
                perf_output_wakeup(handle);
        }
index 6c463c80e93de8c3be3180f3cbd8694b955a1ac3..afa2947286cd84e3f311780cfd0116dcf7edc90e 100644 (file)
@@ -2352,6 +2352,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
                }
        }
 
+       perf_event_namespaces(current);
+
 bad_unshare_cleanup_cred:
        if (new_cred)
                put_cred(new_cred);
index 699c5bc51a9219d664578e4d7978dee94d291c82..d733479a10eeebc79250cf3905437a082b7300c9 100644 (file)
@@ -1391,21 +1391,19 @@ bool within_kprobe_blacklist(unsigned long addr)
  * This returns encoded errors if it fails to look up symbol or invalid
  * combination of parameters.
  */
-static kprobe_opcode_t *kprobe_addr(struct kprobe *p)
+static kprobe_opcode_t *_kprobe_addr(kprobe_opcode_t *addr,
+                       const char *symbol_name, unsigned int offset)
 {
-       kprobe_opcode_t *addr = p->addr;
-
-       if ((p->symbol_name && p->addr) ||
-           (!p->symbol_name && !p->addr))
+       if ((symbol_name && addr) || (!symbol_name && !addr))
                goto invalid;
 
-       if (p->symbol_name) {
-               kprobe_lookup_name(p->symbol_name, addr);
+       if (symbol_name) {
+               kprobe_lookup_name(symbol_name, addr);
                if (!addr)
                        return ERR_PTR(-ENOENT);
        }
 
-       addr = (kprobe_opcode_t *)(((char *)addr) + p->offset);
+       addr = (kprobe_opcode_t *)(((char *)addr) + offset);
        if (addr)
                return addr;
 
@@ -1413,6 +1411,11 @@ invalid:
        return ERR_PTR(-EINVAL);
 }
 
+static kprobe_opcode_t *kprobe_addr(struct kprobe *p)
+{
+       return _kprobe_addr(p->addr, p->symbol_name, p->offset);
+}
+
 /* Check passed kprobe is valid and return kprobe in kprobe_table. */
 static struct kprobe *__get_valid_kprobe(struct kprobe *p)
 {
@@ -1740,11 +1743,12 @@ void unregister_kprobes(struct kprobe **kps, int num)
 }
 EXPORT_SYMBOL_GPL(unregister_kprobes);
 
-int __weak __kprobes kprobe_exceptions_notify(struct notifier_block *self,
-                                             unsigned long val, void *data)
+int __weak kprobe_exceptions_notify(struct notifier_block *self,
+                                       unsigned long val, void *data)
 {
        return NOTIFY_DONE;
 }
+NOKPROBE_SYMBOL(kprobe_exceptions_notify);
 
 static struct notifier_block kprobe_exceptions_nb = {
        .notifier_call = kprobe_exceptions_notify,
@@ -1875,6 +1879,25 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
 }
 NOKPROBE_SYMBOL(pre_handler_kretprobe);
 
+bool __weak arch_function_offset_within_entry(unsigned long offset)
+{
+       return !offset;
+}
+
+bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset)
+{
+       kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset);
+
+       if (IS_ERR(kp_addr))
+               return false;
+
+       if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset) ||
+                                               !arch_function_offset_within_entry(offset))
+               return false;
+
+       return true;
+}
+
 int register_kretprobe(struct kretprobe *rp)
 {
        int ret = 0;
@@ -1882,6 +1905,9 @@ int register_kretprobe(struct kretprobe *rp)
        int i;
        void *addr;
 
+       if (!function_offset_within_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset))
+               return -EINVAL;
+
        if (kretprobe_blacklist_size) {
                addr = kprobe_addr(&rp->kp);
                if (IS_ERR(addr))
index 782102e59eed5b4b5379126b865fb9c795892cdd..f6c5d330059ac7996a1aeb7a4c4fdfad128d847d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/file.h>
 #include <linux/syscalls.h>
 #include <linux/cgroup.h>
+#include <linux/perf_event.h>
 
 static struct kmem_cache *nsproxy_cachep;
 
@@ -262,6 +263,8 @@ SYSCALL_DEFINE2(setns, int, fd, int, nstype)
                goto out;
        }
        switch_task_namespaces(tsk, new_nsproxy);
+
+       perf_event_namespaces(tsk);
 out:
        fput(file);
        return err;
index d4a06e714645df56f75db97ba6bb052534a4bb41..9619b5768e4b26e93adb066734d82421970c5516 100644 (file)
@@ -455,7 +455,7 @@ config UPROBE_EVENTS
        select UPROBES
        select PROBE_EVENTS
        select TRACING
-       default n
+       default y
        help
          This allows the user to add tracing events on top of userspace
          dynamic events (similar to tracepoints) on the fly via the trace
index 0ad75e9698f6b0f918df83af90da1204e99d8308..b253d59b9c518a4c71ad03d2e4940e782dd4e8a4 100644 (file)
@@ -4355,6 +4355,7 @@ static const char readme_msg[] =
        "\t           -:[<group>/]<event>\n"
 #ifdef CONFIG_KPROBE_EVENTS
        "\t    place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
+  "place (kretprobe): [<module>:]<symbol>[+<offset>]|<memaddr>\n"
 #endif
 #ifdef CONFIG_UPROBE_EVENTS
        "\t    place: <path>:<offset>\n"
index 5f688cc724f00abcd9d09686adc75fb96e4b5b02..013f4e7146d483d34e37180bbe4dce8375ff3ca6 100644 (file)
@@ -681,10 +681,6 @@ static int create_trace_kprobe(int argc, char **argv)
                return -EINVAL;
        }
        if (isdigit(argv[1][0])) {
-               if (is_return) {
-                       pr_info("Return probe point must be a symbol.\n");
-                       return -EINVAL;
-               }
                /* an address specified */
                ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr);
                if (ret) {
@@ -700,8 +696,9 @@ static int create_trace_kprobe(int argc, char **argv)
                        pr_info("Failed to parse symbol.\n");
                        return ret;
                }
-               if (offset && is_return) {
-                       pr_info("Return probe must be used without offset.\n");
+               if (offset && is_return &&
+                   !function_offset_within_entry(NULL, symbol, offset)) {
+                       pr_info("Given offset is not valid for return probe.\n");
                        return -EINVAL;
                }
        }
index af05f8e0903e27baccddc00748bf0f75820c9d3d..6ebd3e6a1fd12d3202067020b48446fd9bdcff98 100644 (file)
@@ -181,10 +181,23 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CPU_REGS  2
 #define   KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
 #define   KVM_DEV_ARM_VGIC_CPUID_MASK  (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define   KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
+#define   KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
+                       (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
 #define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT        0
 #define   KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
+#define   KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
 #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS   3
 #define KVM_DEV_ARM_VGIC_GRP_CTRL       4
+#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
+#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
+#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
+                       (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
+#define VGIC_LEVEL_INFO_LINE_LEVEL     0
+
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT    0
 
 /* KVM_IRQ_LINE irq field index values */
index 3051f86a9b5f4ab976568b266b41f47313f86b82..c2860358ae3e0c3271d9ca4b944351986276e397 100644 (file)
@@ -201,10 +201,23 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CPU_REGS  2
 #define   KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
 #define   KVM_DEV_ARM_VGIC_CPUID_MASK  (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define   KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
+#define   KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
+                       (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
 #define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT        0
 #define   KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
+#define   KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
 #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS   3
 #define KVM_DEV_ARM_VGIC_GRP_CTRL      4
+#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
+#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
+#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
+                       (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
+#define VGIC_LEVEL_INFO_LINE_LEVEL     0
+
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT   0
 
 /* Device Control API on vcpu fd */
index 3603b6f51b11beae38c1c1645086cafc807b07ab..4edbe4bb0e8b0cdd2553c74df9988823990833d9 100644 (file)
@@ -413,6 +413,26 @@ struct kvm_get_htab_header {
        __u16   n_invalid;
 };
 
+/* For KVM_PPC_CONFIGURE_V3_MMU */
+struct kvm_ppc_mmuv3_cfg {
+       __u64   flags;
+       __u64   process_table;  /* second doubleword of partition table entry */
+};
+
+/* Flag values for KVM_PPC_CONFIGURE_V3_MMU */
+#define KVM_PPC_MMUV3_RADIX    1       /* 1 = radix mode, 0 = HPT */
+#define KVM_PPC_MMUV3_GTSE     2       /* global translation shootdown enb. */
+
+/* For KVM_PPC_GET_RMMU_INFO */
+struct kvm_ppc_rmmu_info {
+       struct kvm_ppc_radix_geom {
+               __u8    page_shift;
+               __u8    level_bits[4];
+               __u8    pad[3];
+       }       geometries[8];
+       __u32   ap_encodings[8];
+};
+
 /* Per-vcpu XICS interrupt controller state */
 #define KVM_REG_PPC_ICP_STATE  (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c)
 
@@ -613,5 +633,7 @@ struct kvm_get_htab_header {
 #define  KVM_XICS_LEVEL_SENSITIVE      (1ULL << 40)
 #define  KVM_XICS_MASKED               (1ULL << 41)
 #define  KVM_XICS_PENDING              (1ULL << 42)
+#define  KVM_XICS_PRESENTED            (1ULL << 43)
+#define  KVM_XICS_QUEUED               (1ULL << 44)
 
 #endif /* __LINUX_KVM_POWERPC_H */
index 059e33e94260ab5cab2dcf2b95a46704619a1756..328eeceec709803b91fa11ab14860341828f6639 100644 (file)
@@ -7,6 +7,8 @@
 
 #define LOCK_PREFIX "\n\tlock; "
 
+#include <asm/cmpxchg.h>
+
 /*
  * Atomic operations that C can't guarantee us.  Useful for
  * resource counting etc..
@@ -62,4 +64,9 @@ static inline int atomic_dec_and_test(atomic_t *v)
        GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e");
 }
 
+static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+       return cmpxchg(&v->counter, old, new);
+}
+
 #endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */
diff --git a/tools/arch/x86/include/asm/cmpxchg.h b/tools/arch/x86/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..f525326
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef TOOLS_ASM_X86_CMPXCHG_H
+#define TOOLS_ASM_X86_CMPXCHG_H
+
+#include <linux/compiler.h>
+
+/*
+ * Non-existant functions to indicate usage errors at link time
+ * (or compile-time if the compiler implements __compiletime_error().
+ */
+extern void __cmpxchg_wrong_size(void)
+       __compiletime_error("Bad argument size for cmpxchg");
+
+/*
+ * Constants for operation sizes. On 32-bit, the 64-bit size it set to
+ * -1 because sizeof will never return -1, thereby making those switch
+ * case statements guaranteeed dead code which the compiler will
+ * eliminate, and allowing the "missing symbol in the default case" to
+ * indicate a usage error.
+ */
+#define __X86_CASE_B   1
+#define __X86_CASE_W   2
+#define __X86_CASE_L   4
+#ifdef __x86_64__
+#define __X86_CASE_Q   8
+#else
+#define        __X86_CASE_Q    -1              /* sizeof will never return -1 */
+#endif
+
+/*
+ * Atomic compare and exchange.  Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.  Success is
+ * indicated by comparing RETURN with OLD.
+ */
+#define __raw_cmpxchg(ptr, old, new, size, lock)                       \
+({                                                                     \
+       __typeof__(*(ptr)) __ret;                                       \
+       __typeof__(*(ptr)) __old = (old);                               \
+       __typeof__(*(ptr)) __new = (new);                               \
+       switch (size) {                                                 \
+       case __X86_CASE_B:                                              \
+       {                                                               \
+               volatile u8 *__ptr = (volatile u8 *)(ptr);              \
+               asm volatile(lock "cmpxchgb %2,%1"                      \
+                            : "=a" (__ret), "+m" (*__ptr)              \
+                            : "q" (__new), "0" (__old)                 \
+                            : "memory");                               \
+               break;                                                  \
+       }                                                               \
+       case __X86_CASE_W:                                              \
+       {                                                               \
+               volatile u16 *__ptr = (volatile u16 *)(ptr);            \
+               asm volatile(lock "cmpxchgw %2,%1"                      \
+                            : "=a" (__ret), "+m" (*__ptr)              \
+                            : "r" (__new), "0" (__old)                 \
+                            : "memory");                               \
+               break;                                                  \
+       }                                                               \
+       case __X86_CASE_L:                                              \
+       {                                                               \
+               volatile u32 *__ptr = (volatile u32 *)(ptr);            \
+               asm volatile(lock "cmpxchgl %2,%1"                      \
+                            : "=a" (__ret), "+m" (*__ptr)              \
+                            : "r" (__new), "0" (__old)                 \
+                            : "memory");                               \
+               break;                                                  \
+       }                                                               \
+       case __X86_CASE_Q:                                              \
+       {                                                               \
+               volatile u64 *__ptr = (volatile u64 *)(ptr);            \
+               asm volatile(lock "cmpxchgq %2,%1"                      \
+                            : "=a" (__ret), "+m" (*__ptr)              \
+                            : "r" (__new), "0" (__old)                 \
+                            : "memory");                               \
+               break;                                                  \
+       }                                                               \
+       default:                                                        \
+               __cmpxchg_wrong_size();                                 \
+       }                                                               \
+       __ret;                                                          \
+})
+
+#define __cmpxchg(ptr, old, new, size)                                 \
+       __raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
+
+#define cmpxchg(ptr, old, new)                                         \
+       __cmpxchg(ptr, old, new, sizeof(*(ptr)))
+
+
+#endif /* TOOLS_ASM_X86_CMPXCHG_H */
index 293149a1c6a114999473a78199a186a5cf040d22..0fe00446f9cac8c16e1ae3fcabc4a469b772597b 100644 (file)
 #define X86_FEATURE_XTOPOLOGY  ( 3*32+22) /* cpu topology enum extensions */
 #define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
 #define X86_FEATURE_NONSTOP_TSC        ( 3*32+24) /* TSC does not stop in C states */
-/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
+#define X86_FEATURE_CPUID      ( 3*32+25) /* CPU has CPUID instruction itself */
 #define X86_FEATURE_EXTD_APICID        ( 3*32+26) /* has extended APICID (8 bits) */
 #define X86_FEATURE_AMD_DCM     ( 3*32+27) /* multi-node processor */
 #define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
  *
  * Reuse free bits when adding new feature flags!
  */
-
+#define X86_FEATURE_RING3MWAIT ( 7*32+ 0) /* Ring 3 MONITOR/MWAIT */
+#define X86_FEATURE_CPUID_FAULT ( 7*32+ 1) /* Intel CPUID faulting */
 #define X86_FEATURE_CPB                ( 7*32+ 2) /* AMD Core Performance Boost */
 #define X86_FEATURE_EPB                ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
 #define X86_FEATURE_CAT_L3     ( 7*32+ 4) /* Cache Allocation Technology L3 */
 #define X86_FEATURE_PKU                (16*32+ 3) /* Protection Keys for Userspace */
 #define X86_FEATURE_OSPKE      (16*32+ 4) /* OS Protection Keys Enable */
 #define X86_FEATURE_AVX512_VPOPCNTDQ (16*32+14) /* POPCNT for vectors of DW/QW */
-#define X86_FEATURE_RDPID      (16*32+ 22) /* RDPID instruction */
+#define X86_FEATURE_LA57       (16*32+16) /* 5-level page tables */
+#define X86_FEATURE_RDPID      (16*32+22) /* RDPID instruction */
 
 /* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
 #define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
 #define X86_BUG_SWAPGS_FENCE   X86_BUG(11) /* SWAPGS without input dep on GS */
 #define X86_BUG_MONITOR                X86_BUG(12) /* IPI required to wake up remote CPU */
 #define X86_BUG_AMD_E400       X86_BUG(13) /* CPU is among the affected by Erratum 400 */
-
 #endif /* _ASM_X86_CPUFEATURES_H */
index 49e6ebac7e73e33b0a03327cb65c95a29afc1c67..98dcc112b36349147dd9266dc758444a469f052f 100644 (file)
@@ -286,7 +286,7 @@ ENDPROC(memcpy_mcsafe_unrolled)
        _ASM_EXTABLE_FAULT(.L_copy_leading_bytes, .L_memcpy_mcsafe_fail)
        _ASM_EXTABLE_FAULT(.L_cache_w0, .L_memcpy_mcsafe_fail)
        _ASM_EXTABLE_FAULT(.L_cache_w1, .L_memcpy_mcsafe_fail)
-       _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
+       _ASM_EXTABLE_FAULT(.L_cache_w2, .L_memcpy_mcsafe_fail)
        _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
        _ASM_EXTABLE_FAULT(.L_cache_w4, .L_memcpy_mcsafe_fail)
        _ASM_EXTABLE_FAULT(.L_cache_w5, .L_memcpy_mcsafe_fail)
index e3fb5ecbdcb65cee24172baecbe7f87da959b640..523911f316ce5e65511962f0c13fe0032a06427a 100644 (file)
@@ -63,6 +63,7 @@ FEATURE_TESTS_BASIC :=                  \
         lzma                            \
         get_cpuid                       \
         bpf                             \
+        sched_getcpu                   \
         sdt
 
 # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
index b564a2eea03904636f41101dd485e441d2d4fe00..e35e4e5ad192e6126404b4f5ee52e397e2bb22db 100644 (file)
@@ -48,21 +48,22 @@ FILES=                                          \
          test-get_cpuid.bin                     \
          test-sdt.bin                           \
          test-cxx.bin                           \
-         test-jvmti.bin
+         test-jvmti.bin                                \
+         test-sched_getcpu.bin
 
 FILES := $(addprefix $(OUTPUT),$(FILES))
 
-CC := $(CROSS_COMPILE)gcc -MD
-CXX := $(CROSS_COMPILE)g++ -MD
-PKG_CONFIG := $(CROSS_COMPILE)pkg-config
+CC ?= $(CROSS_COMPILE)gcc
+CXX ?= $(CROSS_COMPILE)g++
+PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config
 LLVM_CONFIG ?= llvm-config
 
 all: $(FILES)
 
-__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS)
+__BUILD = $(CC) $(CFLAGS) -MD -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS)
   BUILD = $(__BUILD) > $(@:.bin=.make.output) 2>&1
 
-__BUILDXX = $(CXX) $(CXXFLAGS) -Wall -Werror -o $@ $(patsubst %.bin,%.cpp,$(@F)) $(LDFLAGS)
+__BUILDXX = $(CXX) $(CXXFLAGS) -MD -Wall -Werror -o $@ $(patsubst %.bin,%.cpp,$(@F)) $(LDFLAGS)
   BUILDXX = $(__BUILDXX) > $(@:.bin=.make.output) 2>&1
 
 ###############################
@@ -91,6 +92,9 @@ $(OUTPUT)test-libelf.bin:
 $(OUTPUT)test-glibc.bin:
        $(BUILD)
 
+$(OUTPUT)test-sched_getcpu.bin:
+       $(BUILD)
+
 DWARFLIBS := -ldw
 ifeq ($(findstring -static,${LDFLAGS}),-static)
 DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
@@ -171,7 +175,7 @@ $(OUTPUT)test-libperl.bin:
        $(BUILD) $(FLAGS_PERL_EMBED)
 
 $(OUTPUT)test-libpython.bin:
-       $(BUILD)
+       $(BUILD) $(FLAGS_PYTHON_EMBED)
 
 $(OUTPUT)test-libpython-version.bin:
        $(BUILD)
index 699e43627397b5c3008cd74008016f4812550c77..cc6c7c01f4cadd5f8fe28ced947b9c80a2a0515d 100644 (file)
 # include "test-pthread-attr-setaffinity-np.c"
 #undef main
 
+#define main main_test_sched_getcpu
+# include "test-sched_getcpu.c"
+#undef main
+
 # if 0
 /*
  * Disable libbabeltrace check for test-all, because the requested
@@ -182,6 +186,7 @@ int main(int argc, char *argv[])
        main_test_get_cpuid();
        main_test_bpf();
        main_test_libcrypto();
+       main_test_sched_getcpu();
        main_test_sdt();
 
        return 0;
diff --git a/tools/build/feature/test-sched_getcpu.c b/tools/build/feature/test-sched_getcpu.c
new file mode 100644 (file)
index 0000000..c4a148d
--- /dev/null
@@ -0,0 +1,7 @@
+#define _GNU_SOURCE
+#include <sched.h>
+
+int main(void)
+{
+       return sched_getcpu();
+}
index 2ba78c9f570108ac8284fa96c209ea07498adf09..5e9738f97bf38f471067c7e4e205ed1d6bb5bd78 100644 (file)
@@ -60,4 +60,12 @@ static inline int atomic_dec_and_test(atomic_t *v)
        return __sync_sub_and_fetch(&v->counter, 1) == 0;
 }
 
+#define cmpxchg(ptr, oldval, newval) \
+       __sync_val_compare_and_swap(ptr, oldval, newval)
+
+static inline int atomic_cmpxchg(atomic_t *v, int oldval, int newval)
+{
+       return cmpxchg(&(v)->counter, oldval, newval);
+}
+
 #endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */
index 4e3d3d18ebab6271dec637a017620fe80666fd11..9f21fc2b092b834f3badabe0233ed4e8b509444b 100644 (file)
@@ -3,4 +3,10 @@
 
 #include <asm/atomic.h>
 
+/* atomic_cmpxchg_relaxed */
+#ifndef atomic_cmpxchg_relaxed
+#define  atomic_cmpxchg_relaxed                atomic_cmpxchg
+#define  atomic_cmpxchg_release         atomic_cmpxchg
+#endif /* atomic_cmpxchg_relaxed */
+
 #endif /* __TOOLS_LINUX_ATOMIC_H */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644 (file)
index 0000000..8e4a4f4
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _TOOLS_PERF_LINUX_BUG_H
+#define _TOOLS_PERF_LINUX_BUG_H
+
+/* Force a compilation error if condition is true, but also produce a
+   result (of value 0 and type size_t), so the expression can be used
+   e.g. in a structure initializer (or where-ever else comma expressions
+   aren't permitted). */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+
+#endif /* _TOOLS_PERF_LINUX_BUG_H */
index 48af2f10a42d00942b5262391f3f576c9856c0e4..825d44f89a2901035cb78a138eabc7175fcf246b 100644 (file)
 #if GCC_VERSION >= 70000 && !defined(__CHECKER__)
 # define __fallthrough __attribute__ ((fallthrough))
 #endif
+
+#if GCC_VERSION >= 40300
+# define __compiletime_error(message) __attribute__((error(message)))
+#endif /* GCC_VERSION >= 40300 */
+
+/* &a[0] degrades to a pointer: a different type from an array */
+#define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
index 8de163b17c0d00011d33083d247936d8265465e7..23299d7e71602efd2bd317786ca5fc800b2ed4a2 100644 (file)
@@ -5,6 +5,10 @@
 #include <linux/compiler-gcc.h>
 #endif
 
+#ifndef __compiletime_error
+# define __compiletime_error(message)
+#endif
+
 /* Optimization barrier */
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 # define __always_inline       inline __attribute__((always_inline))
 #endif
 
+/* Are two types/vars the same type (ignoring qualifiers)? */
+#ifndef __same_type
+# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
+#endif
+
 #ifdef __ANDROID__
 /*
  * FIXME: Big hammer to get rid of tons of:
index c65cc0aa2659186cf04f91b8376691563c6ae27d..251eabf2a05e91ea4197ffce4541613e2eb92b1d 100644 (file)
 #include <linux/hash.h>
 #include <linux/log2.h>
 
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-#endif
-
 #define DEFINE_HASHTABLE(name, bits)                                           \
        struct hlist_head name[1 << (bits)] =                                   \
                        { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
index 28607db02bd3ed165cd535de415ffd3d4476753f..73ccc48126bb5f5d0032709af649638eb4dc1cf6 100644 (file)
@@ -4,6 +4,11 @@
 #include <stdarg.h>
 #include <stddef.h>
 #include <assert.h>
+#include <linux/compiler.h>
+
+#ifndef UINT_MAX
+#define UINT_MAX       (~0U)
+#endif
 
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
@@ -72,6 +77,8 @@
 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
 int scnprintf(char * buf, size_t size, const char * fmt, ...);
 
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
+
 /*
  * This looks more complex than it should be. But we need to
  * get the type for the ~ right in round_down (it needs to be
index d5677d39c1e4c88c254b0d55b9d0ca5ab505fd92..0325cefc2220b8de2815e88aaada80020b80060c 100644 (file)
@@ -12,6 +12,9 @@
 #ifndef _TOOLS_LINUX_LOG2_H
 #define _TOOLS_LINUX_LOG2_H
 
+#include <linux/bitops.h>
+#include <linux/types.h>
+
 /*
  * non-constant log of base 2 calculators
  * - the arch may override these in asm/bitops.h if they can be implemented
diff --git a/tools/include/linux/refcount.h b/tools/include/linux/refcount.h
new file mode 100644 (file)
index 0000000..a0177c1
--- /dev/null
@@ -0,0 +1,151 @@
+#ifndef _TOOLS_LINUX_REFCOUNT_H
+#define _TOOLS_LINUX_REFCOUNT_H
+
+/*
+ * Variant of atomic_t specialized for reference counts.
+ *
+ * The interface matches the atomic_t interface (to aid in porting) but only
+ * provides the few functions one should use for reference counting.
+ *
+ * It differs in that the counter saturates at UINT_MAX and will not move once
+ * there. This avoids wrapping the counter and causing 'spurious'
+ * use-after-free issues.
+ *
+ * Memory ordering rules are slightly relaxed wrt regular atomic_t functions
+ * and provide only what is strictly required for refcounts.
+ *
+ * The increments are fully relaxed; these will not provide ordering. The
+ * rationale is that whatever is used to obtain the object we're increasing the
+ * reference count on will provide the ordering. For locked data structures,
+ * its the lock acquire, for RCU/lockless data structures its the dependent
+ * load.
+ *
+ * Do note that inc_not_zero() provides a control dependency which will order
+ * future stores against the inc, this ensures we'll never modify the object
+ * if we did not in fact acquire a reference.
+ *
+ * The decrements will provide release order, such that all the prior loads and
+ * stores will be issued before, it also provides a control dependency, which
+ * will order us against the subsequent free().
+ *
+ * The control dependency is against the load of the cmpxchg (ll/sc) that
+ * succeeded. This means the stores aren't fully ordered, but this is fine
+ * because the 1->0 transition indicates no concurrency.
+ *
+ * Note that the allocator is responsible for ordering things between free()
+ * and alloc().
+ *
+ */
+
+#include <linux/atomic.h>
+#include <linux/kernel.h>
+
+#ifdef NDEBUG
+#define REFCOUNT_WARN(cond, str) (void)(cond)
+#define __refcount_check
+#else
+#define REFCOUNT_WARN(cond, str) BUG_ON(cond)
+#define __refcount_check       __must_check
+#endif
+
+typedef struct refcount_struct {
+       atomic_t refs;
+} refcount_t;
+
+#define REFCOUNT_INIT(n)       { .refs = ATOMIC_INIT(n), }
+
+static inline void refcount_set(refcount_t *r, unsigned int n)
+{
+       atomic_set(&r->refs, n);
+}
+
+static inline unsigned int refcount_read(const refcount_t *r)
+{
+       return atomic_read(&r->refs);
+}
+
+/*
+ * Similar to atomic_inc_not_zero(), will saturate at UINT_MAX and WARN.
+ *
+ * Provides no memory ordering, it is assumed the caller has guaranteed the
+ * object memory to be stable (RCU, etc.). It does provide a control dependency
+ * and thereby orders future stores. See the comment on top.
+ */
+static inline __refcount_check
+bool refcount_inc_not_zero(refcount_t *r)
+{
+       unsigned int old, new, val = atomic_read(&r->refs);
+
+       for (;;) {
+               new = val + 1;
+
+               if (!val)
+                       return false;
+
+               if (unlikely(!new))
+                       return true;
+
+               old = atomic_cmpxchg_relaxed(&r->refs, val, new);
+               if (old == val)
+                       break;
+
+               val = old;
+       }
+
+       REFCOUNT_WARN(new == UINT_MAX, "refcount_t: saturated; leaking memory.\n");
+
+       return true;
+}
+
+/*
+ * Similar to atomic_inc(), will saturate at UINT_MAX and WARN.
+ *
+ * Provides no memory ordering, it is assumed the caller already has a
+ * reference on the object, will WARN when this is not so.
+ */
+static inline void refcount_inc(refcount_t *r)
+{
+       REFCOUNT_WARN(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use-after-free.\n");
+}
+
+/*
+ * Similar to atomic_dec_and_test(), it will WARN on underflow and fail to
+ * decrement when saturated at UINT_MAX.
+ *
+ * Provides release memory ordering, such that prior loads and stores are done
+ * before, and provides a control dependency such that free() must come after.
+ * See the comment on top.
+ */
+static inline __refcount_check
+bool refcount_sub_and_test(unsigned int i, refcount_t *r)
+{
+       unsigned int old, new, val = atomic_read(&r->refs);
+
+       for (;;) {
+               if (unlikely(val == UINT_MAX))
+                       return false;
+
+               new = val - i;
+               if (new > val) {
+                       REFCOUNT_WARN(new > val, "refcount_t: underflow; use-after-free.\n");
+                       return false;
+               }
+
+               old = atomic_cmpxchg_release(&r->refs, val, new);
+               if (old == val)
+                       break;
+
+               val = old;
+       }
+
+       return !new;
+}
+
+static inline __refcount_check
+bool refcount_dec_and_test(refcount_t *r)
+{
+       return refcount_sub_and_test(1, r);
+}
+
+
+#endif /* _ATOMIC_LINUX_REFCOUNT_H */
index f436d2420a18575095e66b7bfbf15b0abbe83fe8..d62b56cf8c12eedcdda935bc1180c4b4b70270b9 100644 (file)
@@ -18,4 +18,6 @@ extern size_t strlcpy(char *dest, const char *src, size_t size);
 
 char *str_error_r(int errnum, char *buf, size_t buflen);
 
+int prefixcmp(const char *str, const char *prefix);
+
 #endif /* _LINUX_STRING_H_ */
index c24b3e3ae29691d404ad36bc56bdea3497ea0de7..77a28a26a6709fe3fe90026acfd9936849824890 100644 (file)
@@ -7,6 +7,7 @@
 
 #define __SANE_USERSPACE_TYPES__       /* For PPC64, to get LL64 types */
 #include <asm/types.h>
+#include <asm/posix_types.h>
 
 struct page;
 struct kmem_cache;
diff --git a/tools/include/uapi/linux/fcntl.h b/tools/include/uapi/linux/fcntl.h
new file mode 100644 (file)
index 0000000..813afd6
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _UAPI_LINUX_FCNTL_H
+#define _UAPI_LINUX_FCNTL_H
+
+#include <asm/fcntl.h>
+
+#define F_SETLEASE     (F_LINUX_SPECIFIC_BASE + 0)
+#define F_GETLEASE     (F_LINUX_SPECIFIC_BASE + 1)
+
+/*
+ * Cancel a blocking posix lock; internal use only until we expose an
+ * asynchronous lock api to userspace:
+ */
+#define F_CANCELLK     (F_LINUX_SPECIFIC_BASE + 5)
+
+/* Create a file descriptor with FD_CLOEXEC set. */
+#define F_DUPFD_CLOEXEC        (F_LINUX_SPECIFIC_BASE + 6)
+
+/*
+ * Request nofications on a directory.
+ * See below for events that may be notified.
+ */
+#define F_NOTIFY       (F_LINUX_SPECIFIC_BASE+2)
+
+/*
+ * Set and get of pipe page size array
+ */
+#define F_SETPIPE_SZ   (F_LINUX_SPECIFIC_BASE + 7)
+#define F_GETPIPE_SZ   (F_LINUX_SPECIFIC_BASE + 8)
+
+/*
+ * Set/Get seals
+ */
+#define F_ADD_SEALS    (F_LINUX_SPECIFIC_BASE + 9)
+#define F_GET_SEALS    (F_LINUX_SPECIFIC_BASE + 10)
+
+/*
+ * Types of seals
+ */
+#define F_SEAL_SEAL    0x0001  /* prevent further seals from being set */
+#define F_SEAL_SHRINK  0x0002  /* prevent file from shrinking */
+#define F_SEAL_GROW    0x0004  /* prevent file from growing */
+#define F_SEAL_WRITE   0x0008  /* prevent writes */
+/* (1U << 31) is reserved for signed error codes */
+
+/*
+ * Types of directory notifications that may be requested.
+ */
+#define DN_ACCESS      0x00000001      /* File accessed */
+#define DN_MODIFY      0x00000002      /* File modified */
+#define DN_CREATE      0x00000004      /* File created */
+#define DN_DELETE      0x00000008      /* File removed */
+#define DN_RENAME      0x00000010      /* File renamed */
+#define DN_ATTRIB      0x00000020      /* File changed attibutes */
+#define DN_MULTISHOT   0x80000000      /* Don't remove notifier */
+
+#define AT_FDCWD               -100    /* Special value used to indicate
+                                           openat should use the current
+                                           working directory. */
+#define AT_SYMLINK_NOFOLLOW    0x100   /* Do not follow symbolic links.  */
+#define AT_REMOVEDIR           0x200   /* Remove directory instead of
+                                           unlinking file.  */
+#define AT_SYMLINK_FOLLOW      0x400   /* Follow symbolic links.  */
+#define AT_NO_AUTOMOUNT                0x800   /* Suppress terminal automount traversal */
+#define AT_EMPTY_PATH          0x1000  /* Allow empty relative pathname */
+
+#define AT_STATX_SYNC_TYPE     0x6000  /* Type of synchronisation required from statx() */
+#define AT_STATX_SYNC_AS_STAT  0x0000  /* - Do whatever stat() does */
+#define AT_STATX_FORCE_SYNC    0x2000  /* - Force the attributes to be sync'd with the server */
+#define AT_STATX_DONT_SYNC     0x4000  /* - Don't sync attributes with the server */
+
+
+#endif /* _UAPI_LINUX_FCNTL_H */
index c66a485a24ac81e324ea53ea17b405a3c73b520a..d09a9cd021b1230730d23eefd0c149df51852c93 100644 (file)
@@ -344,7 +344,8 @@ struct perf_event_attr {
                                use_clockid    :  1, /* use @clockid for time fields */
                                context_switch :  1, /* context switch data */
                                write_backward :  1, /* Write ring buffer from end to beginning */
-                               __reserved_1   : 36;
+                               namespaces     :  1, /* include namespaces data */
+                               __reserved_1   : 35;
 
        union {
                __u32           wakeup_events;    /* wakeup every n events */
@@ -610,6 +611,23 @@ struct perf_event_header {
        __u16   size;
 };
 
+struct perf_ns_link_info {
+       __u64   dev;
+       __u64   ino;
+};
+
+enum {
+       NET_NS_INDEX            = 0,
+       UTS_NS_INDEX            = 1,
+       IPC_NS_INDEX            = 2,
+       PID_NS_INDEX            = 3,
+       USER_NS_INDEX           = 4,
+       MNT_NS_INDEX            = 5,
+       CGROUP_NS_INDEX         = 6,
+
+       NR_NAMESPACES,          /* number of available namespaces */
+};
+
 enum perf_event_type {
 
        /*
@@ -862,6 +880,18 @@ enum perf_event_type {
         */
        PERF_RECORD_SWITCH_CPU_WIDE             = 15,
 
+       /*
+        * struct {
+        *      struct perf_event_header        header;
+        *      u32                             pid;
+        *      u32                             tid;
+        *      u64                             nr_namespaces;
+        *      { u64                           dev, inode; } [nr_namespaces];
+        *      struct sample_id                sample_id;
+        * };
+        */
+       PERF_RECORD_NAMESPACES                  = 16,
+
        PERF_RECORD_MAX,                        /* non-ABI */
 };
 
@@ -885,6 +915,7 @@ enum perf_callchain_context {
  */
 #define PERF_AUX_FLAG_TRUNCATED                0x01    /* record was truncated to fit */
 #define PERF_AUX_FLAG_OVERWRITE                0x02    /* snapshot from overwrite mode */
+#define PERF_AUX_FLAG_PARTIAL          0x04    /* record contains gaps */
 
 #define PERF_FLAG_FD_NO_GROUP          (1UL << 0)
 #define PERF_FLAG_FD_OUTPUT            (1UL << 1)
diff --git a/tools/include/uapi/linux/stat.h b/tools/include/uapi/linux/stat.h
new file mode 100644 (file)
index 0000000..d538897
--- /dev/null
@@ -0,0 +1,177 @@
+#ifndef _UAPI_LINUX_STAT_H
+#define _UAPI_LINUX_STAT_H
+
+#include <linux/types.h>
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#define S_IFMT  00170000
+#define S_IFSOCK 0140000
+#define S_IFLNK         0120000
+#define S_IFREG  0100000
+#define S_IFBLK  0060000
+#define S_IFDIR  0040000
+#define S_IFCHR  0020000
+#define S_IFIFO  0010000
+#define S_ISUID  0004000
+#define S_ISGID  0002000
+#define S_ISVTX  0001000
+
+#define S_ISLNK(m)     (((m) & S_IFMT) == S_IFLNK)
+#define S_ISREG(m)     (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m)     (((m) & S_IFMT) == S_IFDIR)
+#define S_ISCHR(m)     (((m) & S_IFMT) == S_IFCHR)
+#define S_ISBLK(m)     (((m) & S_IFMT) == S_IFBLK)
+#define S_ISFIFO(m)    (((m) & S_IFMT) == S_IFIFO)
+#define S_ISSOCK(m)    (((m) & S_IFMT) == S_IFSOCK)
+
+#define S_IRWXU 00700
+#define S_IRUSR 00400
+#define S_IWUSR 00200
+#define S_IXUSR 00100
+
+#define S_IRWXG 00070
+#define S_IRGRP 00040
+#define S_IWGRP 00020
+#define S_IXGRP 00010
+
+#define S_IRWXO 00007
+#define S_IROTH 00004
+#define S_IWOTH 00002
+#define S_IXOTH 00001
+
+#endif
+
+/*
+ * Timestamp structure for the timestamps in struct statx.
+ *
+ * tv_sec holds the number of seconds before (negative) or after (positive)
+ * 00:00:00 1st January 1970 UTC.
+ *
+ * tv_nsec holds a number of nanoseconds before (0..-999,999,999 if tv_sec is
+ * negative) or after (0..999,999,999 if tv_sec is positive) the tv_sec time.
+ *
+ * Note that if both tv_sec and tv_nsec are non-zero, then the two values must
+ * either be both positive or both negative.
+ *
+ * __reserved is held in case we need a yet finer resolution.
+ */
+struct statx_timestamp {
+       __s64   tv_sec;
+       __s32   tv_nsec;
+       __s32   __reserved;
+};
+
+/*
+ * Structures for the extended file attribute retrieval system call
+ * (statx()).
+ *
+ * The caller passes a mask of what they're specifically interested in as a
+ * parameter to statx().  What statx() actually got will be indicated in
+ * st_mask upon return.
+ *
+ * For each bit in the mask argument:
+ *
+ * - if the datum is not supported:
+ *
+ *   - the bit will be cleared, and
+ *
+ *   - the datum will be set to an appropriate fabricated value if one is
+ *     available (eg. CIFS can take a default uid and gid), otherwise
+ *
+ *   - the field will be cleared;
+ *
+ * - otherwise, if explicitly requested:
+ *
+ *   - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is
+ *     set or if the datum is considered out of date, and
+ *
+ *   - the field will be filled in and the bit will be set;
+ *
+ * - otherwise, if not requested, but available in approximate form without any
+ *   effort, it will be filled in anyway, and the bit will be set upon return
+ *   (it might not be up to date, however, and no attempt will be made to
+ *   synchronise the internal state first);
+ *
+ * - otherwise the field and the bit will be cleared before returning.
+ *
+ * Items in STATX_BASIC_STATS may be marked unavailable on return, but they
+ * will have values installed for compatibility purposes so that stat() and
+ * co. can be emulated in userspace.
+ */
+struct statx {
+       /* 0x00 */
+       __u32   stx_mask;       /* What results were written [uncond] */
+       __u32   stx_blksize;    /* Preferred general I/O size [uncond] */
+       __u64   stx_attributes; /* Flags conveying information about the file [uncond] */
+       /* 0x10 */
+       __u32   stx_nlink;      /* Number of hard links */
+       __u32   stx_uid;        /* User ID of owner */
+       __u32   stx_gid;        /* Group ID of owner */
+       __u16   stx_mode;       /* File mode */
+       __u16   __spare0[1];
+       /* 0x20 */
+       __u64   stx_ino;        /* Inode number */
+       __u64   stx_size;       /* File size */
+       __u64   stx_blocks;     /* Number of 512-byte blocks allocated */
+       __u64   stx_attributes_mask; /* Mask to show what's supported in stx_attributes */
+       /* 0x40 */
+       struct statx_timestamp  stx_atime;      /* Last access time */
+       struct statx_timestamp  stx_btime;      /* File creation time */
+       struct statx_timestamp  stx_ctime;      /* Last attribute change time */
+       struct statx_timestamp  stx_mtime;      /* Last data modification time */
+       /* 0x80 */
+       __u32   stx_rdev_major; /* Device ID of special file [if bdev/cdev] */
+       __u32   stx_rdev_minor;
+       __u32   stx_dev_major;  /* ID of device containing file [uncond] */
+       __u32   stx_dev_minor;
+       /* 0x90 */
+       __u64   __spare2[14];   /* Spare space for future expansion */
+       /* 0x100 */
+};
+
+/*
+ * Flags to be stx_mask
+ *
+ * Query request/result mask for statx() and struct statx::stx_mask.
+ *
+ * These bits should be set in the mask argument of statx() to request
+ * particular items when calling statx().
+ */
+#define STATX_TYPE             0x00000001U     /* Want/got stx_mode & S_IFMT */
+#define STATX_MODE             0x00000002U     /* Want/got stx_mode & ~S_IFMT */
+#define STATX_NLINK            0x00000004U     /* Want/got stx_nlink */
+#define STATX_UID              0x00000008U     /* Want/got stx_uid */
+#define STATX_GID              0x00000010U     /* Want/got stx_gid */
+#define STATX_ATIME            0x00000020U     /* Want/got stx_atime */
+#define STATX_MTIME            0x00000040U     /* Want/got stx_mtime */
+#define STATX_CTIME            0x00000080U     /* Want/got stx_ctime */
+#define STATX_INO              0x00000100U     /* Want/got stx_ino */
+#define STATX_SIZE             0x00000200U     /* Want/got stx_size */
+#define STATX_BLOCKS           0x00000400U     /* Want/got stx_blocks */
+#define STATX_BASIC_STATS      0x000007ffU     /* The stuff in the normal stat struct */
+#define STATX_BTIME            0x00000800U     /* Want/got stx_btime */
+#define STATX_ALL              0x00000fffU     /* All currently supported flags */
+#define STATX__RESERVED                0x80000000U     /* Reserved for future struct statx expansion */
+
+/*
+ * Attributes to be found in stx_attributes and masked in stx_attributes_mask.
+ *
+ * These give information about the features or the state of a file that might
+ * be of use to ordinary userspace programs such as GUIs or ls rather than
+ * specialised tools.
+ *
+ * Note that the flags marked [I] correspond to generic FS_IOC_FLAGS
+ * semantically.  Where possible, the numerical value is picked to correspond
+ * also.
+ */
+#define STATX_ATTR_COMPRESSED          0x00000004 /* [I] File is compressed by the fs */
+#define STATX_ATTR_IMMUTABLE           0x00000010 /* [I] File is marked immutable */
+#define STATX_ATTR_APPEND              0x00000020 /* [I] File is append-only */
+#define STATX_ATTR_NODUMP              0x00000040 /* [I] File is not to be dumped */
+#define STATX_ATTR_ENCRYPTED           0x00000800 /* [I] File requires key to decrypt in fs */
+
+#define STATX_ATTR_AUTOMOUNT           0x00001000 /* Dir: Automount trigger */
+
+
+#endif /* _UAPI_LINUX_STAT_H */
index 4b6bfc43cccf0e096c3c88e272afa1491fa69e97..809c7721cd2451a5e1a8e3bbe5a3994965106346 100644 (file)
@@ -439,6 +439,35 @@ int sysfs__read_str(const char *entry, char **buf, size_t *sizep)
        return filename__read_str(path, buf, sizep);
 }
 
+int sysfs__read_bool(const char *entry, bool *value)
+{
+       char *buf;
+       size_t size;
+       int ret;
+
+       ret = sysfs__read_str(entry, &buf, &size);
+       if (ret < 0)
+               return ret;
+
+       switch (buf[0]) {
+       case '1':
+       case 'y':
+       case 'Y':
+               *value = true;
+               break;
+       case '0':
+       case 'n':
+       case 'N':
+               *value = false;
+               break;
+       default:
+               ret = -1;
+       }
+
+       free(buf);
+
+       return ret;
+}
 int sysctl__read_int(const char *sysctl, int *value)
 {
        char path[PATH_MAX];
index 6b332dc74498fc35a1f26b0488391e12435eb269..956c21127d1ef7d9817c0bbb8a9423ff4bdf1de8 100644 (file)
@@ -37,4 +37,5 @@ int sysctl__read_int(const char *sysctl, int *value);
 int sysfs__read_int(const char *entry, int *value);
 int sysfs__read_ull(const char *entry, unsigned long long *value);
 int sysfs__read_str(const char *entry, char **buf, size_t *sizep);
+int sysfs__read_bool(const char *entry, bool *value);
 #endif /* __API_FS__ */
index bd239bc1d557dbde447e8128ac7cd3163dc11a04..8e678af1c6ee479eae333cf5766598db5dce5208 100644 (file)
@@ -87,3 +87,12 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size)
        }
        return ret;
 }
+
+int prefixcmp(const char *str, const char *prefix)
+{
+       for (; ; str++, prefix++)
+               if (!*prefix)
+                       return 0;
+               else if (*str != *prefix)
+                       return (unsigned char)*prefix - (unsigned char)*str;
+}
index e228c3cb37160b8fd5bda5e3a7c9e76f89ea4537..ba970a73d053f3c019a318dbb7fa14b9dbab9b40 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <linux/string.h>
 #include <termios.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
index e145a020780c0d5dc03c39b60205bb7d782dfcf7..9bd4223dc722013bbfd170d652064f5b056cc07d 100644 (file)
@@ -2,6 +2,7 @@
 #define __SUBCMD_HELP_H
 
 #include <sys/types.h>
+#include <stdio.h>
 
 struct cmdnames {
        size_t alloc;
index 6bc24025d05457098b504c3a1e9e5a1316b21817..359bfa77f39cdebac7df82876b227d1a63975c39 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/compiler.h>
+#include <linux/string.h>
 #include <linux/types.h>
 #include <stdio.h>
 #include <stdlib.h>
index fc2e45d8aaf1d04c09d53fd4db6478d60d066895..8fa5f036eff08002ee802dc6014f6689d790a80f 100644 (file)
@@ -79,13 +79,4 @@ static inline void astrcat(char **out, const char *add)
        free(tmp);
 }
 
-static inline int prefixcmp(const char *str, const char *prefix)
-{
-       for (; ; str++, prefix++)
-               if (!*prefix)
-                       return 0;
-               else if (*str != *prefix)
-                       return (unsigned char)*prefix - (unsigned char)*str;
-}
-
 #endif /* __SUBCMD_UTIL_H */
index 5e431077fcd6784ac9567a785bc6fb90a40bc7bb..d270ac00613d60612802e85cd71661a54c762f41 100644 (file)
@@ -1,3 +1,4 @@
+#include <ctype.h>
 #include "symbol/kallsyms.h"
 #include <stdio.h>
 #include <stdlib.h>
index 066086dd59a8017e293993a50d2f432d47441cfe..282a60368b14df9e88b304d7e60aac77fd8e6bc0 100644 (file)
@@ -36,8 +36,7 @@
 #include "warn.h"
 
 #include <linux/hashtable.h>
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#include <linux/kernel.h>
 
 #define STATE_FP_SAVED         0x1
 #define STATE_FP_SETUP         0x2
index 46c326db4f464e4bef4a073c93c52c61c4262e77..ecc5b1b5d15df6fddd1fe27d929f92f5111b8894 100644 (file)
 #include <stdlib.h>
 #include <subcmd/exec-cmd.h>
 #include <subcmd/pager.h>
+#include <linux/kernel.h>
 
 #include "builtin.h"
 
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
-
 struct cmd_struct {
        const char *name;
        int (*fn)(int, const char **);
index 3db3db9278be6f52af6bb9935eb7698eb1fc2f79..643cc4ba6872511d7941fad057ac875f5382deb2 100644 (file)
@@ -31,3 +31,5 @@ config.mak.autogen
 .config-detected
 util/intel-pt-decoder/inat-tables.c
 arch/*/include/generated/
+pmu-events/pmu-events.c
+pmu-events/jevents
index 9b79f8d7db50e3dafcbe200ad8f3b47230ead69b..bd8eeb60533cdee3311dd6277b728990e4e70042 100644 (file)
@@ -50,5 +50,6 @@ libperf-y += util/
 libperf-y += arch/
 libperf-y += ui/
 libperf-y += scripts/
+libperf-y += trace/beauty/
 
 gtk-y += ui/gtk/
index 2d96de6132a941dcd50d9808aafead39bc7df6ea..6e6a8b22c8594f42e9727c81a8e4b4adc8301e43 100644 (file)
@@ -30,6 +30,24 @@ OPTIONS
 --verbose=::
         Verbosity level.
 
+-p::
+--pid=::
+       Trace on existing process id (comma separated list).
+
+-a::
+--all-cpus::
+       Force system-wide collection.  Scripts run without a <command>
+       normally use -a by default, while scripts run with a <command>
+       normally don't - this option allows the latter to be run in
+       system-wide mode.
+
+-C::
+--cpu=::
+       Only trace for the list of CPUs provided.  Multiple CPUs can
+       be provided as a comma separated list with no space like: 0,1.
+       Ranges of CPUs are specified with -: 0-2.
+       Default is to trace on all online CPUs.
+
 
 SEE ALSO
 --------
index 41857cce5e86f4404929051d4daf0414386452d9..f709de54707b714feff11e3e0e7f28cbb0c9fb8d 100644 (file)
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
 SYNOPSIS
 --------
 [verse]
-'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|event_glob]
+'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|sdt|event_glob]
 
 DESCRIPTION
 -----------
@@ -24,6 +24,10 @@ Don't print descriptions.
 --long-desc::
 Print longer event descriptions.
 
+--details::
+Print how named events are resolved internally into perf events, and also
+any extra expressions computed by perf stat.
+
 
 [[EVENT_MODIFIERS]]
 EVENT MODIFIERS
@@ -240,6 +244,8 @@ To limit the list use:
 
 . 'pmu' to print the kernel supplied PMU events.
 
+. 'sdt' to list all Statically Defined Tracepoint events.
+
 . If none of the above is matched, it will apply the supplied glob to all
   events, printing the ones that match.
 
index b16003ec14a743bcdcc8473798388b0849aa3523..ea3789d05e5e69fa60f2d8daf230f62aaae073c8 100644 (file)
@@ -347,6 +347,9 @@ Enable weightened sampling. An additional weight is recorded per sample and can
 displayed with the weight and local_weight sort keys.  This currently works for TSX
 abort events and some memory events in precise mode on modern Intel CPUs.
 
+--namespaces::
+Record events of type PERF_RECORD_NAMESPACES.
+
 --transaction::
 Record transaction flags for transaction related events.
 
index c04cc0647c16e6d8bbb458d655ab8ddbec3262c9..37a1759141579b6fdf35ee1ebcb996060ef01c71 100644 (file)
@@ -72,7 +72,8 @@ OPTIONS
 --sort=::
        Sort histogram entries by given key(s) - multiple keys can be specified
        in CSV format.  Following sort keys are available:
-       pid, comm, dso, symbol, parent, cpu, socket, srcline, weight, local_weight.
+       pid, comm, dso, symbol, parent, cpu, socket, srcline, weight,
+       local_weight, cgroup_id.
 
        Each key has following meaning:
 
@@ -80,6 +81,7 @@ OPTIONS
        - pid: command and tid of the task
        - dso: name of library or module executed at the time of sample
        - symbol: name of function executed at the time of sample
+       - symbol_size: size of function executed at the time of sample
        - parent: name of function matched to the parent regex filter. Unmatched
        entries are displayed as "[other]".
        - cpu: cpu number the task ran at the time of sample
@@ -91,6 +93,7 @@ OPTIONS
        - weight: Event specific weight, e.g. memory latency or transaction
        abort cost. This is the global weight.
        - local_weight: Local weight version of the weight above.
+       - cgroup_id: ID derived from cgroup namespace device and inode numbers.
        - transaction: Transaction abort flags.
        - overhead: Overhead percentage of sample
        - overhead_sys: Overhead percentage of sample running in system mode
@@ -172,6 +175,9 @@ OPTIONS
        By default, every sort keys not specified in -F will be appended
        automatically.
 
+       If the keys starts with a prefix '+', then it will append the specified
+        field(s) to the default field order. For example: perf report -F +period,sample.
+
 -p::
 --parent=<regex>::
         A regex filter to identify parent. The parent is a caller of this
@@ -229,6 +235,7 @@ OPTIONS
        sort_key can be:
        - function: compare on functions (default)
        - address: compare on individual code addresses
+       - srcline: compare on source filename and line number
 
        branch can be:
        - branch: include last branch information in callgraph when available.
@@ -424,6 +431,10 @@ include::itrace.txt[]
 --hierarchy::
        Enable hierarchical output.
 
+--inline::
+       If a callgraph address belongs to an inlined function, the inline stack
+       will be printed. Each entry is function name or file/line.
+
 include::callchain-overhead-calculation.txt[]
 
 SEE ALSO
index d33deddb0146cc9500f29fe6f0b1e65d6f237b10..a092a2499e8f8f2003681369c140a19a84b9c401 100644 (file)
@@ -132,6 +132,10 @@ OPTIONS for 'perf sched timehist'
 --migrations::
        Show migration events.
 
+-n::
+--next::
+       Show next task.
+
 -I::
 --idle-hist::
        Show idle-related events only.
index 4ed5f239ba7dee9fe2fc44854e3b8daa42091a97..cb0eda3925e6d8562da9d3091147c5fca602ebbf 100644 (file)
@@ -116,7 +116,7 @@ OPTIONS
 --fields::
         Comma separated list of fields to print. Options are:
         comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
-        srcline, period, iregs, brstack, brstacksym, flags, bpf-output,
+        srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn,
         callindent, insn, insnlen. Field list can be prepended with the type, trace, sw or hw,
         to indicate to which event type the field list applies.
         e.g., -F sw:comm,tid,time,ip,sym  and -F trace:time,cpu,trace
@@ -189,15 +189,20 @@ OPTIONS
        i.e., -F "" is not allowed.
 
        The brstack output includes branch related information with raw addresses using the
-       /v/v/v/v/ syntax in the following order:
+       /v/v/v/v/cycles syntax in the following order:
        FROM: branch source instruction
        TO  : branch target instruction
         M/P/-: M=branch target mispredicted or branch direction was mispredicted, P=target predicted or direction predicted, -=not supported
        X/- : X=branch inside a transactional region, -=not in transaction region or not supported
        A/- : A=TSX abort entry, -=not aborted region or not supported
+       cycles
 
        The brstacksym is identical to brstack, except that the FROM and TO addresses are printed in a symbolic form if possible.
 
+       When brstackinsn is specified the full assembler sequences of branch sequences for each sample
+       is printed. This is the full execution path leading to the sample. This is only supported when the
+       sample was recorded with perf record -b or -j any.
+
 -k::
 --vmlinux=<file>::
         vmlinux pathname
@@ -248,6 +253,9 @@ OPTIONS
 --show-mmap-events
        Display mmap related events (e.g. MMAP, MMAP2).
 
+--show-namespace-events
+       Display namespace events i.e. events of type PERF_RECORD_NAMESPACES.
+
 --show-switch-events
        Display context switch events i.e. events of type PERF_RECORD_SWITCH or
        PERF_RECORD_SWITCH_CPU_WIDE.
@@ -299,6 +307,10 @@ include::itrace.txt[]
        stop time is not given (i.e, time string is 'x.y,') then analysis goes
        to end of file.
 
+--max-blocks::
+       Set the maximum number of program blocks to print with brstackasm for
+       each sample.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-script-perl[1],
index aecf2a87e7d60bf4a759f47d7c60aac1b12aec07..bd0e4417f2be63f892a870ec5ad60ae0fd5d9994 100644 (file)
@@ -94,8 +94,7 @@ to activate system-wide monitoring. Default is to count on all CPUs.
 
 -A::
 --no-aggr::
-Do not aggregate counts across all monitored CPUs in system-wide mode (-a).
-This option is only valid in system-wide mode.
+Do not aggregate counts across all monitored CPUs.
 
 -n::
 --null::
@@ -237,6 +236,9 @@ To interpret the results it is usually needed to know on which
 CPUs the workload runs on. If needed the CPUs can be forced using
 taskset.
 
+--no-merge::
+Do not merge results from same PMUs.
+
 EXAMPLES
 --------
 
index afd728672b6fb488415ca4c58043baaf6b264226..c1e3288a2dfbcc80100a88cd8286fdc2a707c541 100644 (file)
@@ -123,7 +123,8 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
        major or all pagefaults. Default value is maj.
 
 --syscalls::
-       Trace system calls. This options is enabled by default.
+       Trace system calls. This options is enabled by default, disable with
+       --no-syscalls.
 
 --call-graph [mode,type,min[,limit],order[,key][,branch]]::
         Setup and enable call-graph (stack chain/backtrace) recording.
index b664b18d3991b16f28168527320e5402b755fba3..fa2a9132f0a9438d2637501c711c33d3a4e68ac9 100644 (file)
@@ -11,8 +11,8 @@ All fields are in native-endian of the machine that generated the perf.data.
 
 When perf is writing to a pipe it uses a special version of the file
 format that does not rely on seeking to adjust data offsets.  This
-format is not described here. The pipe version can be converted to
-normal perf.data with perf inject.
+format is described in "Pipe-mode data" section. The pipe data version can be
+augmented with additional events using perf inject.
 
 The file starts with a perf_header:
 
@@ -411,6 +411,21 @@ An array bound by the perf_file_section size.
 
 ids points to a array of uint64_t defining the ids for event attr attr.
 
+Pipe-mode data
+
+Pipe-mode avoid seeks in the file by removing the perf_file_section and flags
+from the struct perf_header. The trimmed header is:
+
+struct perf_pipe_file_header {
+       u64                             magic;
+       u64                             size;
+};
+
+The information about attrs, data, and event_types is instead in the
+synthesized events PERF_RECORD_ATTR, PERF_RECORD_HEADER_TRACING_DATA and
+PERF_RECORD_HEADER_EVENT_TYPE that are generated by perf record in pipe-mode.
+
+
 References:
 
 include/uapi/linux/perf_event.h
index 8672f835ae4eff2659ff314c40bf77d3730b7986..a29da46d180f8780507938f5183af24e189a1c21 100644 (file)
@@ -12,6 +12,7 @@ tools/arch/sparc/include/asm/barrier_32.h
 tools/arch/sparc/include/asm/barrier_64.h
 tools/arch/tile/include/asm/barrier.h
 tools/arch/x86/include/asm/barrier.h
+tools/arch/x86/include/asm/cmpxchg.h
 tools/arch/x86/include/asm/cpufeatures.h
 tools/arch/x86/include/asm/disabled-features.h
 tools/arch/x86/include/asm/required-features.h
@@ -63,6 +64,7 @@ tools/include/linux/bitops.h
 tools/include/linux/compiler.h
 tools/include/linux/compiler-gcc.h
 tools/include/linux/coresight-pmu.h
+tools/include/linux/bug.h
 tools/include/linux/filter.h
 tools/include/linux/hash.h
 tools/include/linux/kernel.h
@@ -72,12 +74,15 @@ tools/include/uapi/asm-generic/mman-common.h
 tools/include/uapi/asm-generic/mman.h
 tools/include/uapi/linux/bpf.h
 tools/include/uapi/linux/bpf_common.h
+tools/include/uapi/linux/fcntl.h
 tools/include/uapi/linux/hw_breakpoint.h
 tools/include/uapi/linux/mman.h
 tools/include/uapi/linux/perf_event.h
+tools/include/uapi/linux/stat.h
 tools/include/linux/poison.h
 tools/include/linux/rbtree.h
 tools/include/linux/rbtree_augmented.h
+tools/include/linux/refcount.h
 tools/include/linux/string.h
 tools/include/linux/stringify.h
 tools/include/linux/types.h
index 27c9fbca7bd9c79eb703ad2d37d4280f9d286cc4..8354d04b392fd9e94c0812731b55e7267b41504e 100644 (file)
@@ -170,13 +170,20 @@ PYTHON2_CONFIG := \
 override PYTHON_CONFIG := \
   $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG))
 
-PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
+grep-libs  = $(filter -l%,$(1))
+strip-libs  = $(filter-out -l%,$(1))
 
-PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
-PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
+PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
 
-ifeq ($(CC), clang)
-  PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
+ifdef PYTHON_CONFIG
+  PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
+  PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
+  PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
+  PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
+  ifeq ($(CC), clang)
+    PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
+  endif
+  FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
 endif
 
 FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
@@ -267,6 +274,7 @@ ifdef NO_LIBELF
   NO_LIBUNWIND := 1
   NO_LIBDW_DWARF_UNWIND := 1
   NO_LIBBPF := 1
+  NO_JVMTI := 1
 else
   ifeq ($(feature-libelf), 0)
     ifeq ($(feature-glibc), 1)
@@ -276,7 +284,7 @@ else
       LIBC_SUPPORT := 1
     endif
     ifeq ($(LIBC_SUPPORT),1)
-      msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install libelf-dev, libelf-devel or elfutils-libelf-devel);
+      msg := $(warning No libelf found. Disables 'probe' tool, jvmti and BPF support in 'perf record'. Please install libelf-dev, libelf-devel or elfutils-libelf-devel);
 
       NO_LIBELF := 1
       NO_DWARF := 1
@@ -284,6 +292,7 @@ else
       NO_LIBUNWIND := 1
       NO_LIBDW_DWARF_UNWIND := 1
       NO_LIBBPF := 1
+      NO_JVMTI := 1
     else
       ifneq ($(filter s% -static%,$(LDFLAGS),),)
         msg := $(error No static glibc found, please install glibc-static);
@@ -317,6 +326,10 @@ ifdef NO_DWARF
   NO_LIBDW_DWARF_UNWIND := 1
 endif
 
+ifeq ($(feature-sched_getcpu), 1)
+  CFLAGS += -DHAVE_SCHED_GETCPU_SUPPORT
+endif
+
 ifndef NO_LIBELF
   CFLAGS += -DHAVE_LIBELF_SUPPORT
   EXTLIBS += -lelf
@@ -550,8 +563,6 @@ ifndef NO_GTK2
   endif
 endif
 
-grep-libs  = $(filter -l%,$(1))
-strip-libs = $(filter-out -l%,$(1))
 
 ifdef NO_LIBPERL
   CFLAGS += -DNO_LIBPERL
@@ -599,21 +610,9 @@ else
       $(call disable-python,No 'python-config' tool was found: disables Python support - please install python-devel/python-dev)
     else
 
-      PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
-
-      PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
-      PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
-      PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
-      PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
-      ifeq ($(CC), clang)
-        PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
-      endif
-      FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
-
       ifneq ($(feature-libpython), 1)
         $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev)
       else
-
         ifneq ($(feature-libpython-version), 1)
           $(warning Python 3 is not yet supported; please set)
           $(warning PYTHON and/or PYTHON_CONFIG appropriately.)
index dfea6b6355254e0eac677dfc05dcce0463089f6e..29361d9b635a67ec323d4e6470b20b8e6ef3e385 100644 (file)
@@ -33,6 +33,7 @@
 #include "../../util/cs-etm.h"
 
 #include <stdlib.h>
+#include <sys/stat.h>
 
 #define ENABLE_SINK_MAX        128
 #define CS_BUS_DEVICE_PATH "/bus/coresight/devices/"
index 33ec5b339da87fca6c49757e58816f076c738ba6..8bb176a37990501c8cce8dd834840b07b29ed503 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <stddef.h>
+#include <linux/stringify.h>
 #include <dwarf-regs.h>
 
 struct pt_regs_dwarfnum {
@@ -16,10 +17,9 @@ struct pt_regs_dwarfnum {
        unsigned int dwarfnum;
 };
 
-#define STR(s) #s
 #define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
 #define GPR_DWARFNUM_NAME(num) \
-       {.name = STR(%r##num), .dwarfnum = num}
+       {.name = __stringify(%r##num), .dwarfnum = num}
 #define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
 
 /*
index b4176c60117a58b8dc8a4adf7a181576a542f7b0..bacfa00fca398ed59c1caa901cfe77d0e510f8b1 100644 (file)
@@ -1,6 +1,7 @@
 #include <elfutils/libdwfl.h>
 #include "../../util/unwind-libdw.h"
 #include "../../util/perf_regs.h"
+#include "../../util/event.h"
 
 bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
 {
index 068b6189157b6eb9a11c58f7cbca1f4ca1348efb..cd764a9fd0983de57e02feca3967dd1e5e2504d2 100644 (file)
@@ -8,9 +8,12 @@
  * published by the Free Software Foundation.
  */
 
+#include <errno.h>
 #include <stddef.h>
+#include <string.h>
 #include <dwarf-regs.h>
 #include <linux/ptrace.h> /* for struct user_pt_regs */
+#include <linux/stringify.h>
 #include "util.h"
 
 struct pt_regs_dwarfnum {
@@ -20,7 +23,7 @@ struct pt_regs_dwarfnum {
 
 #define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
 #define GPR_DWARFNUM_NAME(num) \
-       {.name = STR(%x##num), .dwarfnum = num}
+       {.name = __stringify(%x##num), .dwarfnum = num}
 #define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
 #define DWARFNUM2OFFSET(index) \
        (index * sizeof((struct user_pt_regs *)0)->regs[0])
index c116b713f7f773e296ff9485ff1f2ce6046c6add..b415dfdbcccabadfce60eebfa2e0fd7bcef37fcd 100644 (file)
@@ -1,6 +1,6 @@
+#include <errno.h>
 
 #ifndef REMOTE_UNWIND_LIBUNWIND
-#include <errno.h>
 #include <libunwind.h>
 #include "perf_regs.h"
 #include "../../util/unwind.h"
index 886dd2aaff0d81533468ad60db70abbd23465ec3..837067f48a4c54a88b883e8de6dc95df0dd5b3d0 100644 (file)
@@ -4,6 +4,8 @@
 #include "../util/util.h"
 #include "../util/debug.h"
 
+#include "sane_ctype.h"
+
 const char *const arm_triplets[] = {
        "arm-eabi-",
        "arm-linux-androideabi-",
index 41bdf9530d821d6b14d7bd1eb007e2ddda06a5a9..98ac87052a74c5cbdf2c954221d8ce4d3f9e9752 100644 (file)
@@ -15,6 +15,7 @@
 #include <dwarf-regs.h>
 #include <linux/ptrace.h>
 #include <linux/kernel.h>
+#include <linux/stringify.h>
 #include "util.h"
 
 struct pt_regs_dwarfnum {
@@ -24,10 +25,10 @@ struct pt_regs_dwarfnum {
 };
 
 #define REG_DWARFNUM_NAME(r, num)                                      \
-               {.name = STR(%)STR(r), .dwarfnum = num,                 \
+               {.name = __stringify(%)__stringify(r), .dwarfnum = num,                 \
                .ptregs_offset = offsetof(struct pt_regs, r)}
 #define GPR_DWARFNUM_NAME(num)                                         \
-               {.name = STR(%gpr##num), .dwarfnum = num,               \
+               {.name = __stringify(%gpr##num), .dwarfnum = num,               \
                .ptregs_offset = offsetof(struct pt_regs, gpr[num])}
 #define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0, .ptregs_offset = 0}
 
index 74eee30398f807d559a33800d7d43094f525e19d..249723f0e6a9e4bc3b64df49df7add18c0b175e6 100644 (file)
@@ -1,3 +1,4 @@
+#include <errno.h>
 #include "util/kvm-stat.h"
 #include "util/parse-events.h"
 #include "util/debug.h"
index a3c3e1ce6807cefddeaffd1304f353218c8bc835..f860dc411f69a9236a9ef9e37a7f660c9e9062d4 100644 (file)
@@ -1,5 +1,11 @@
+#include <errno.h>
+#include <string.h>
+#include <regex.h>
+
 #include "../../perf.h"
+#include "../../util/util.h"
 #include "../../util/perf_regs.h"
+#include "../../util/debug.h"
 
 const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(r0, PERF_REG_POWERPC_R0),
@@ -47,3 +53,109 @@ const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
        SMPL_REG_END
 };
+
+/* REG or %rREG */
+#define SDT_OP_REGEX1  "^(%r)?([1-2]?[0-9]|3[0-1])$"
+
+/* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
+#define SDT_OP_REGEX2  "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$"
+
+static regex_t sdt_op_regex1, sdt_op_regex2;
+
+static int sdt_init_op_regex(void)
+{
+       static int initialized;
+       int ret = 0;
+
+       if (initialized)
+               return 0;
+
+       ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED);
+       if (ret)
+               goto error;
+
+       ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED);
+       if (ret)
+               goto free_regex1;
+
+       initialized = 1;
+       return 0;
+
+free_regex1:
+       regfree(&sdt_op_regex1);
+error:
+       pr_debug4("Regex compilation error.\n");
+       return ret;
+}
+
+/*
+ * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
+ * Possible variants of OP are:
+ *     Format          Example
+ *     -------------------------
+ *     NUM(REG)        48(18)
+ *     -NUM(REG)       -48(18)
+ *     NUM(%rREG)      48(%r18)
+ *     -NUM(%rREG)     -48(%r18)
+ *     REG             18
+ *     %rREG           %r18
+ *     iNUM            i0
+ *     i-NUM           i-1
+ *
+ * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
+ * and REG form with -mno-regnames. Here REG is general purpose register,
+ * which is in 0 to 31 range.
+ */
+int arch_sdt_arg_parse_op(char *old_op, char **new_op)
+{
+       int ret, new_len;
+       regmatch_t rm[5];
+       char prefix;
+
+       /* Constant argument. Uprobe does not support it */
+       if (old_op[0] == 'i') {
+               pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
+               return SDT_ARG_SKIP;
+       }
+
+       ret = sdt_init_op_regex();
+       if (ret < 0)
+               return ret;
+
+       if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
+               /* REG or %rREG --> %gprREG */
+
+               new_len = 5;    /* % g p r NULL */
+               new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
+
+               *new_op = zalloc(new_len);
+               if (!*new_op)
+                       return -ENOMEM;
+
+               scnprintf(*new_op, new_len, "%%gpr%.*s",
+                       (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so);
+       } else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
+               /*
+                * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
+                *      +/-NUM(%gprREG)
+                */
+               prefix = (rm[1].rm_so == -1) ? '+' : '-';
+
+               new_len = 8;    /* +/- ( % g p r ) NULL */
+               new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
+               new_len += (int)(rm[4].rm_eo - rm[4].rm_so);
+
+               *new_op = zalloc(new_len);
+               if (!*new_op)
+                       return -ENOMEM;
+
+               scnprintf(*new_op, new_len, "%c%.*s(%%gpr%.*s)", prefix,
+                       (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
+                       (int)(rm[4].rm_eo - rm[4].rm_so), old_op + rm[4].rm_so);
+       } else {
+               pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
+               return SDT_ARG_SKIP;
+       }
+
+       return SDT_ARG_VALID;
+}
index 1030a6e504bb9fe2a8f7eca185a419332613d924..bf9a2594572c7ff3e94adfab36dce813476bb6a9 100644 (file)
@@ -10,6 +10,7 @@
 #include "symbol.h"
 #include "map.h"
 #include "probe-event.h"
+#include "probe-file.h"
 
 #ifdef HAVE_LIBELF_SUPPORT
 bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
@@ -51,6 +52,18 @@ int arch__compare_symbol_names(const char *namea, const char *nameb)
 
        return strcmp(namea, nameb);
 }
+
+int arch__compare_symbol_names_n(const char *namea, const char *nameb,
+                                unsigned int n)
+{
+       /* Skip over initial dot */
+       if (*namea == '.')
+               namea++;
+       if (*nameb == '.')
+               nameb++;
+
+       return strncmp(namea, nameb, n);
+}
 #endif
 
 #if defined(_CALL_ELF) && _CALL_ELF == 2
@@ -79,13 +92,18 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev,
         * However, if the user specifies an offset, we fall back to using the
         * GEP since all userspace applications (objdump/readelf) show function
         * disassembly with offsets from the GEP.
-        *
-        * In addition, we shouldn't specify an offset for kretprobes.
         */
-       if (pev->point.offset || (!pev->uprobes && pev->point.retprobe) ||
-           !map || !sym)
+       if (pev->point.offset || !map || !sym)
                return;
 
+       /* For kretprobes, add an offset only if the kernel supports it */
+       if (!pev->uprobes && pev->point.retprobe) {
+#ifdef HAVE_LIBELF_SUPPORT
+               if (!kretprobe_offset_is_supported())
+#endif
+                       return;
+       }
+
        lep_offset = PPC64_LOCAL_ENTRY_OFFSET(sym->arch_sym);
 
        if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS)
diff --git a/tools/perf/arch/s390/annotate/instructions.c b/tools/perf/arch/s390/annotate/instructions.c
new file mode 100644 (file)
index 0000000..745b4b1
--- /dev/null
@@ -0,0 +1,30 @@
+static struct ins_ops *s390__associate_ins_ops(struct arch *arch, const char *name)
+{
+       struct ins_ops *ops = NULL;
+
+       /* catch all kind of jumps */
+       if (strchr(name, 'j') ||
+           !strncmp(name, "bct", 3) ||
+           !strncmp(name, "br", 2))
+               ops = &jump_ops;
+       /* override call/returns */
+       if (!strcmp(name, "bras") ||
+           !strcmp(name, "brasl") ||
+           !strcmp(name, "basr"))
+               ops = &call_ops;
+       if (!strcmp(name, "br"))
+               ops = &ret_ops;
+
+       arch__associate_ins_ops(arch, name, ops);
+       return ops;
+}
+
+static int s390__annotate_init(struct arch *arch)
+{
+       if (!arch->initialized) {
+               arch->initialized = true;
+               arch->associate_instruction_ops = s390__associate_ins_ops;
+       }
+
+       return 0;
+}
index ed57df2e6d687d89ccf95d9aa03c263411de7fe9..d233e2eb959223174b9d6808016778361b338b0b 100644 (file)
@@ -9,6 +9,7 @@
  * as published by the Free Software Foundation.
  */
 
+#include <errno.h>
 #include "../../util/kvm-stat.h"
 #include <asm/sie.h>
 
index e93ef0b38db8e16a38f83e2e3f08dfb8d5fff4a0..5aef183e2f85c5f6c45e44d4e9a68c9ea62c0d74 100644 (file)
 329    common  pkey_mprotect           sys_pkey_mprotect
 330    common  pkey_alloc              sys_pkey_alloc
 331    common  pkey_free               sys_pkey_free
+332    common  statx                   sys_statx
 
 #
 # x32-specific system call numbers start at 512 to avoid cache impact
index 7f064eb371589aa887e112cddb54145d6268141b..f9713a71d77e8be3d7766ba91cf69556d401bedc 100644 (file)
@@ -6,7 +6,10 @@
 #include "evsel.h"
 #include "arch-tests.h"
 
+#include <signal.h>
 #include <sys/mman.h>
+#include <sys/wait.h>
+#include <errno.h>
 #include <string.h>
 
 static pid_t spawn(void)
index 5c76cc83186a24ae0df5f3986a922dc75e4ff959..e3ae9cff2b6716617088c2baf3d962370df49b81 100644 (file)
@@ -1,3 +1,5 @@
+#include <errno.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <linux/types.h>
index cc1d865e31f1b7975578343761104db81398e8de..6aa3f2a38321e170c9cba5cca97d85e6364ffeda 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 
+#include <errno.h>
 #include <stdbool.h>
 
 #include "../../util/header.h"
index 5132775a044fd7b1acf2a6c814567f56c7e03b3b..af2bce7a2cd60d5fbe5beaf371e6cd189733a9e0 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 
+#include <errno.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
index 90fa2286edcf91d9e780c87fa87dd3f645acbccc..f630de0206a17248308c928618040a5b793db4ae 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 
+#include <errno.h>
 #include <stdbool.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
index b63d4be655a24a678f69d6deea3b4ee87283b938..bf817beca0a822f498efa88ff64089319c2a27a3 100644 (file)
@@ -1,3 +1,4 @@
+#include <errno.h>
 #include "../../util/kvm-stat.h"
 #include <asm/svm.h>
 #include <asm/vmx.h>
index c5db14f36cc7a145257385b61cf9c39a02a592ce..f95edebfb7162daaef5a04d5363084d980565cb6 100644 (file)
@@ -1,5 +1,11 @@
+#include <errno.h>
+#include <string.h>
+#include <regex.h>
+
 #include "../../perf.h"
+#include "../../util/util.h"
 #include "../../util/perf_regs.h"
+#include "../../util/debug.h"
 
 const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(AX, PERF_REG_X86_AX),
@@ -26,3 +32,224 @@ const struct sample_reg sample_reg_masks[] = {
 #endif
        SMPL_REG_END
 };
+
+struct sdt_name_reg {
+       const char *sdt_name;
+       const char *uprobe_name;
+};
+#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
+#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
+
+static const struct sdt_name_reg sdt_reg_tbl[] = {
+       SDT_NAME_REG(eax, ax),
+       SDT_NAME_REG(rax, ax),
+       SDT_NAME_REG(al,  ax),
+       SDT_NAME_REG(ah,  ax),
+       SDT_NAME_REG(ebx, bx),
+       SDT_NAME_REG(rbx, bx),
+       SDT_NAME_REG(bl,  bx),
+       SDT_NAME_REG(bh,  bx),
+       SDT_NAME_REG(ecx, cx),
+       SDT_NAME_REG(rcx, cx),
+       SDT_NAME_REG(cl,  cx),
+       SDT_NAME_REG(ch,  cx),
+       SDT_NAME_REG(edx, dx),
+       SDT_NAME_REG(rdx, dx),
+       SDT_NAME_REG(dl,  dx),
+       SDT_NAME_REG(dh,  dx),
+       SDT_NAME_REG(esi, si),
+       SDT_NAME_REG(rsi, si),
+       SDT_NAME_REG(sil, si),
+       SDT_NAME_REG(edi, di),
+       SDT_NAME_REG(rdi, di),
+       SDT_NAME_REG(dil, di),
+       SDT_NAME_REG(ebp, bp),
+       SDT_NAME_REG(rbp, bp),
+       SDT_NAME_REG(bpl, bp),
+       SDT_NAME_REG(rsp, sp),
+       SDT_NAME_REG(esp, sp),
+       SDT_NAME_REG(spl, sp),
+
+       /* rNN registers */
+       SDT_NAME_REG(r8b,  r8),
+       SDT_NAME_REG(r8w,  r8),
+       SDT_NAME_REG(r8d,  r8),
+       SDT_NAME_REG(r9b,  r9),
+       SDT_NAME_REG(r9w,  r9),
+       SDT_NAME_REG(r9d,  r9),
+       SDT_NAME_REG(r10b, r10),
+       SDT_NAME_REG(r10w, r10),
+       SDT_NAME_REG(r10d, r10),
+       SDT_NAME_REG(r11b, r11),
+       SDT_NAME_REG(r11w, r11),
+       SDT_NAME_REG(r11d, r11),
+       SDT_NAME_REG(r12b, r12),
+       SDT_NAME_REG(r12w, r12),
+       SDT_NAME_REG(r12d, r12),
+       SDT_NAME_REG(r13b, r13),
+       SDT_NAME_REG(r13w, r13),
+       SDT_NAME_REG(r13d, r13),
+       SDT_NAME_REG(r14b, r14),
+       SDT_NAME_REG(r14w, r14),
+       SDT_NAME_REG(r14d, r14),
+       SDT_NAME_REG(r15b, r15),
+       SDT_NAME_REG(r15w, r15),
+       SDT_NAME_REG(r15d, r15),
+       SDT_NAME_REG_END,
+};
+
+/*
+ * Perf only supports OP which is in  +/-NUM(REG)  form.
+ * Here plus-minus sign, NUM and parenthesis are optional,
+ * only REG is mandatory.
+ *
+ * SDT events also supports indirect addressing mode with a
+ * symbol as offset, scaled mode and constants in OP. But
+ * perf does not support them yet. Below are few examples.
+ *
+ * OP with scaled mode:
+ *     (%rax,%rsi,8)
+ *     10(%ras,%rsi,8)
+ *
+ * OP with indirect addressing mode:
+ *     check_action(%rip)
+ *     mp_+52(%rip)
+ *     44+mp_(%rip)
+ *
+ * OP with constant values:
+ *     $0
+ *     $123
+ *     $-1
+ */
+#define SDT_OP_REGEX  "^([+\\-]?)([0-9]*)(\\(?)(%[a-z][a-z0-9]+)(\\)?)$"
+
+static regex_t sdt_op_regex;
+
+static int sdt_init_op_regex(void)
+{
+       static int initialized;
+       int ret = 0;
+
+       if (initialized)
+               return 0;
+
+       ret = regcomp(&sdt_op_regex, SDT_OP_REGEX, REG_EXTENDED);
+       if (ret < 0) {
+               pr_debug4("Regex compilation error.\n");
+               return ret;
+       }
+
+       initialized = 1;
+       return 0;
+}
+
+/*
+ * Max x86 register name length is 5(ex: %r15d). So, 6th char
+ * should always contain NULL. This helps to find register name
+ * length using strlen, insted of maintaing one more variable.
+ */
+#define SDT_REG_NAME_SIZE  6
+
+/*
+ * The uprobe parser does not support all gas register names;
+ * so, we have to replace them (ex. for x86_64: %rax -> %ax).
+ * Note: If register does not require renaming, just copy
+ * paste as it is, but don't leave it empty.
+ */
+static void sdt_rename_register(char *sdt_reg, int sdt_len, char *uprobe_reg)
+{
+       int i = 0;
+
+       for (i = 0; sdt_reg_tbl[i].sdt_name != NULL; i++) {
+               if (!strncmp(sdt_reg_tbl[i].sdt_name, sdt_reg, sdt_len)) {
+                       strcpy(uprobe_reg, sdt_reg_tbl[i].uprobe_name);
+                       return;
+               }
+       }
+
+       strncpy(uprobe_reg, sdt_reg, sdt_len);
+}
+
+int arch_sdt_arg_parse_op(char *old_op, char **new_op)
+{
+       char new_reg[SDT_REG_NAME_SIZE] = {0};
+       int new_len = 0, ret;
+       /*
+        * rm[0]:  +/-NUM(REG)
+        * rm[1]:  +/-
+        * rm[2]:  NUM
+        * rm[3]:  (
+        * rm[4]:  REG
+        * rm[5]:  )
+        */
+       regmatch_t rm[6];
+       /*
+        * Max prefix length is 2 as it may contains sign(+/-)
+        * and displacement 0 (Both sign and displacement 0 are
+        * optional so it may be empty). Use one more character
+        * to hold last NULL so that strlen can be used to find
+        * prefix length, instead of maintaing one more variable.
+        */
+       char prefix[3] = {0};
+
+       ret = sdt_init_op_regex();
+       if (ret < 0)
+               return ret;
+
+       /*
+        * If unsupported OR does not match with regex OR
+        * register name too long, skip it.
+        */
+       if (strchr(old_op, ',') || strchr(old_op, '$') ||
+           regexec(&sdt_op_regex, old_op, 6, rm, 0)   ||
+           rm[4].rm_eo - rm[4].rm_so > SDT_REG_NAME_SIZE) {
+               pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
+               return SDT_ARG_SKIP;
+       }
+
+       /*
+        * Prepare prefix.
+        * If SDT OP has parenthesis but does not provide
+        * displacement, add 0 for displacement.
+        *     SDT         Uprobe     Prefix
+        *     -----------------------------
+        *     +24(%rdi)   +24(%di)   +
+        *     24(%rdi)    +24(%di)   +
+        *     %rdi        %di
+        *     (%rdi)      +0(%di)    +0
+        *     -80(%rbx)   -80(%bx)   -
+        */
+       if (rm[3].rm_so != rm[3].rm_eo) {
+               if (rm[1].rm_so != rm[1].rm_eo)
+                       prefix[0] = *(old_op + rm[1].rm_so);
+               else if (rm[2].rm_so != rm[2].rm_eo)
+                       prefix[0] = '+';
+               else
+                       strncpy(prefix, "+0", 2);
+       }
+
+       /* Rename register */
+       sdt_rename_register(old_op + rm[4].rm_so, rm[4].rm_eo - rm[4].rm_so,
+                           new_reg);
+
+       /* Prepare final OP which should be valid for uprobe_events */
+       new_len = strlen(prefix)              +
+                 (rm[2].rm_eo - rm[2].rm_so) +
+                 (rm[3].rm_eo - rm[3].rm_so) +
+                 strlen(new_reg)             +
+                 (rm[5].rm_eo - rm[5].rm_so) +
+                 1;                                    /* NULL */
+
+       *new_op = zalloc(new_len);
+       if (!*new_op)
+               return -ENOMEM;
+
+       scnprintf(*new_op, new_len, "%.*s%.*s%.*s%.*s%.*s",
+                 strlen(prefix), prefix,
+                 (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
+                 (int)(rm[3].rm_eo - rm[3].rm_so), old_op + rm[3].rm_so,
+                 strlen(new_reg), new_reg,
+                 (int)(rm[5].rm_eo - rm[5].rm_so), old_op + rm[5].rm_so);
+
+       return SDT_ARG_VALID;
+}
index c4b72176ca8361b024fbab0905422bca1a9657b0..38dc9bb2a7c90a7ee8cf8c5aca9078fecc546743 100644 (file)
@@ -1,6 +1,7 @@
 #include <elfutils/libdwfl.h>
 #include "../../util/unwind-libdw.h"
 #include "../../util/perf_regs.h"
+#include "../../util/event.h"
 
 bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
 {
index 579a592990dd996bfd16fcf7214a30567a6b24f2..842ab2781cdc51196a9496ea2759f64a2f350103 100644 (file)
 # endif
 #endif
 
-int bench_numa(int argc, const char **argv, const char *prefix);
-int bench_sched_messaging(int argc, const char **argv, const char *prefix);
-int bench_sched_pipe(int argc, const char **argv, const char *prefix);
-int bench_mem_memcpy(int argc, const char **argv, const char *prefix);
-int bench_mem_memset(int argc, const char **argv, const char *prefix);
-int bench_futex_hash(int argc, const char **argv, const char *prefix);
-int bench_futex_wake(int argc, const char **argv, const char *prefix);
-int bench_futex_wake_parallel(int argc, const char **argv, const char *prefix);
-int bench_futex_requeue(int argc, const char **argv, const char *prefix);
+int bench_numa(int argc, const char **argv);
+int bench_sched_messaging(int argc, const char **argv);
+int bench_sched_pipe(int argc, const char **argv);
+int bench_mem_memcpy(int argc, const char **argv);
+int bench_mem_memset(int argc, const char **argv);
+int bench_futex_hash(int argc, const char **argv);
+int bench_futex_wake(int argc, const char **argv);
+int bench_futex_wake_parallel(int argc, const char **argv);
+int bench_futex_requeue(int argc, const char **argv);
 /* pi futexes */
-int bench_futex_lock_pi(int argc, const char **argv, const char *prefix);
+int bench_futex_lock_pi(int argc, const char **argv);
 
 #define BENCH_FORMAT_DEFAULT_STR       "default"
 #define BENCH_FORMAT_DEFAULT           0
index da04b8c5568a39cf509b9aa5df844641866bcfd1..fe16b310097f509042a87ec8d2ee26a0f445c199 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 /* For the CLR_() macros */
+#include <string.h>
 #include <pthread.h>
 
 #include <errno.h>
@@ -113,8 +114,7 @@ static void print_summary(void)
               (int) runtime.tv_sec);
 }
 
-int bench_futex_hash(int argc, const char **argv,
-                    const char *prefix __maybe_unused)
+int bench_futex_hash(int argc, const char **argv)
 {
        int ret = 0;
        cpu_set_t cpu;
index 91877777ec6e3a4052e49eca9cba4793fa551f73..73a1c44ea63c9c916f3b1b2e3fbfb82d8a93fb77 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 /* For the CLR_() macros */
+#include <string.h>
 #include <pthread.h>
 
 #include <signal.h>
@@ -139,8 +140,7 @@ static void create_threads(struct worker *w, pthread_attr_t thread_attr)
        }
 }
 
-int bench_futex_lock_pi(int argc, const char **argv,
-                       const char *prefix __maybe_unused)
+int bench_futex_lock_pi(int argc, const char **argv)
 {
        int ret = 0;
        unsigned int i;
index 2b9705a8734cd6005fd3149943e2ff20eecf4bbe..41786cbea24c643373af4884ab2901ae3dc99669 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 /* For the CLR_() macros */
+#include <string.h>
 #include <pthread.h>
 
 #include <signal.h>
@@ -108,8 +109,7 @@ static void toggle_done(int sig __maybe_unused,
        done = true;
 }
 
-int bench_futex_requeue(int argc, const char **argv,
-                       const char *prefix __maybe_unused)
+int bench_futex_requeue(int argc, const char **argv)
 {
        int ret = 0;
        unsigned int i, j;
index 2c8fa67ad53767e43c7e91dc84279528268fcb3a..4ab12c8e016a7d8f8e90d47a25ff3a9c145b8171 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 /* For the CLR_() macros */
+#include <string.h>
 #include <pthread.h>
 
 #include <signal.h>
@@ -196,8 +197,7 @@ static void toggle_done(int sig __maybe_unused,
        done = true;
 }
 
-int bench_futex_wake_parallel(int argc, const char **argv,
-                             const char *prefix __maybe_unused)
+int bench_futex_wake_parallel(int argc, const char **argv)
 {
        int ret = 0;
        unsigned int i, j;
index e246b1b8388a3fd3bfc7c9c398a90efc26d86c79..2fa49222ef8deeb0dbc0616d7bbc181bfea28cbf 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 /* For the CLR_() macros */
+#include <string.h>
 #include <pthread.h>
 
 #include <signal.h>
@@ -114,8 +115,7 @@ static void toggle_done(int sig __maybe_unused,
        done = true;
 }
 
-int bench_futex_wake(int argc, const char **argv,
-                    const char *prefix __maybe_unused)
+int bench_futex_wake(int argc, const char **argv)
 {
        int ret = 0;
        unsigned int i, j;
index b2e06d1190d0766694c97f7f0b808717442af604..e44fd32395305cc5e58042ec7a85fee2e9ef1748 100644 (file)
@@ -88,13 +88,11 @@ futex_cmp_requeue(u_int32_t *uaddr, u_int32_t val, u_int32_t *uaddr2, int nr_wak
 
 #ifndef HAVE_PTHREAD_ATTR_SETAFFINITY_NP
 #include <pthread.h>
-static inline int pthread_attr_setaffinity_np(pthread_attr_t *attr,
-                                             size_t cpusetsize,
-                                             cpu_set_t *cpuset)
+#include <linux/compiler.h>
+static inline int pthread_attr_setaffinity_np(pthread_attr_t *attr __maybe_unused,
+                                             size_t cpusetsize __maybe_unused,
+                                             cpu_set_t *cpuset __maybe_unused)
 {
-       attr = attr;
-       cpusetsize = cpusetsize;
-       cpuset = cpuset;
        return 0;
 }
 #endif
index 52504a83b5a15a0649f45f936d72d97a0fe4159f..fbd732b54047976ec3abae8f54c630c6a6f78e2e 100644 (file)
@@ -12,6 +12,7 @@
 #include <subcmd/parse-options.h>
 #include "../util/header.h"
 #include "../util/cloexec.h"
+#include "../util/string2.h"
 #include "bench.h"
 #include "mem-memcpy-arch.h"
 #include "mem-memset-arch.h"
@@ -284,7 +285,7 @@ static const char * const bench_mem_memcpy_usage[] = {
        NULL
 };
 
-int bench_mem_memcpy(int argc, const char **argv, const char *prefix __maybe_unused)
+int bench_mem_memcpy(int argc, const char **argv)
 {
        struct bench_mem_info info = {
                .functions              = memcpy_functions,
@@ -358,7 +359,7 @@ static const struct function memset_functions[] = {
        { .name = NULL, }
 };
 
-int bench_mem_memset(int argc, const char **argv, const char *prefix __maybe_unused)
+int bench_mem_memset(int argc, const char **argv)
 {
        struct bench_mem_info info = {
                .functions              = memset_functions,
index 3083fc36282b564d3fc5da05864907c3ac222cf4..27de0c8c5c19a19e42f20c15f4d198cf31405857 100644 (file)
@@ -4,6 +4,7 @@
  * numa: Simulate NUMA-sensitive workload and measure their NUMA performance
  */
 
+#include <inttypes.h>
 /* For the CLR_() macros */
 #include <pthread.h>
 
@@ -30,6 +31,7 @@
 #include <sys/wait.h>
 #include <sys/prctl.h>
 #include <sys/types.h>
+#include <linux/kernel.h>
 #include <linux/time64.h>
 
 #include <numa.h>
@@ -187,7 +189,8 @@ static const struct option options[] = {
        OPT_INCR   ('d', "show_details" , &p0.show_details,     "Show details"),
        OPT_INCR   ('a', "all"          , &p0.run_all,          "Run all tests in the suite"),
        OPT_INTEGER('H', "thp"          , &p0.thp,              "MADV_NOHUGEPAGE < 0 < MADV_HUGEPAGE"),
-       OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details"),
+       OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details, "
+                   "convergence is reached when each process (all its threads) is running on a single NUMA node."),
        OPT_BOOLEAN('m', "measure_convergence", &p0.measure_convergence, "measure convergence latency"),
        OPT_BOOLEAN('q', "quiet"        , &p0.show_quiet,       "quiet mode"),
        OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"),
@@ -1766,7 +1769,7 @@ static int bench_all(void)
        return 0;
 }
 
-int bench_numa(int argc, const char **argv, const char *prefix __maybe_unused)
+int bench_numa(int argc, const char **argv)
 {
        init_params(&p0, "main,", argc, argv);
        argc = parse_options(argc, argv, options, bench_numa_usage, 0);
index 6a111e775210f700de6e3b796b703675748a0b05..4f961e74535b9c0d9141ecd0df51c236f30d358d 100644 (file)
@@ -260,8 +260,7 @@ static const char * const bench_sched_message_usage[] = {
        NULL
 };
 
-int bench_sched_messaging(int argc, const char **argv,
-                   const char *prefix __maybe_unused)
+int bench_sched_messaging(int argc, const char **argv)
 {
        unsigned int i, total_children;
        struct timeval start, stop, diff;
index 2243f0150d76452da3502c0d5f3ead12b85de512..a152737370c59342866e003807a318bafd475cbb 100644 (file)
@@ -76,7 +76,7 @@ static void *worker_thread(void *__tdata)
        return NULL;
 }
 
-int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unused)
+int bench_sched_pipe(int argc, const char **argv)
 {
        struct thread_data threads[2], *td;
        int pipe_1[2], pipe_2[2];
index 4f52d85f5ebc574daa91f29b1a3d24758c3d276d..7a5dc7e5c577270edaa3a36f7a916d7f3cc5a182 100644 (file)
@@ -33,6 +33,7 @@
 #include "util/block-range.h"
 
 #include <dlfcn.h>
+#include <errno.h>
 #include <linux/bitmap.h>
 
 struct perf_annotate {
@@ -383,7 +384,7 @@ static const char * const annotate_usage[] = {
        NULL
 };
 
-int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_annotate(int argc, const char **argv)
 {
        struct perf_annotate annotate = {
                .tool = {
@@ -393,6 +394,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
                        .comm   = perf_event__process_comm,
                        .exit   = perf_event__process_exit,
                        .fork   = perf_event__process_fork,
+                       .namespaces = perf_event__process_namespaces,
+                       .attr   = perf_event__process_attr,
+                       .build_id = perf_event__process_build_id,
                        .ordered_events = true,
                        .ordering_requires_timestamps = true,
                },
index a1cddc6bbf0f178f44ee03b2a3729b85a385dbd4..445e62881254437d9f4d3067dc6f31b3b2233169 100644 (file)
@@ -25,7 +25,7 @@
 #include <string.h>
 #include <sys/prctl.h>
 
-typedef int (*bench_fn_t)(int argc, const char **argv, const char *prefix);
+typedef int (*bench_fn_t)(int argc, const char **argv);
 
 struct bench {
        const char      *name;
@@ -155,7 +155,7 @@ static int bench_str2int(const char *str)
  * to something meaningful:
  */
 static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn,
-                    int argc, const char **argv, const char *prefix)
+                    int argc, const char **argv)
 {
        int size;
        char *name;
@@ -171,7 +171,7 @@ static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t f
        prctl(PR_SET_NAME, name);
        argv[0] = name;
 
-       ret = fn(argc, argv, prefix);
+       ret = fn(argc, argv);
 
        free(name);
 
@@ -198,7 +198,7 @@ static void run_collection(struct collection *coll)
                fflush(stdout);
 
                argv[1] = bench->name;
-               run_bench(coll->name, bench->name, bench->fn, 1, argv, NULL);
+               run_bench(coll->name, bench->name, bench->fn, 1, argv);
                printf("\n");
        }
 }
@@ -211,7 +211,7 @@ static void run_all_collections(void)
                run_collection(coll);
 }
 
-int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_bench(int argc, const char **argv)
 {
        struct collection *coll;
        int ret = 0;
@@ -270,7 +270,7 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
                        if (bench_format == BENCH_FORMAT_DEFAULT)
                                printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name);
                        fflush(stdout);
-                       ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1, prefix);
+                       ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1);
                        goto end;
                }
 
index 30e2b2cb2421219de6cc168483f5e9144af8036c..9eba7f1add1f9706f2b8153fb33f3574b362d5ee 100644 (file)
@@ -10,6 +10,7 @@
 #include <sys/time.h>
 #include <time.h>
 #include <dirent.h>
+#include <errno.h>
 #include <unistd.h>
 #include "builtin.h"
 #include "perf.h"
@@ -21,6 +22,7 @@
 #include "util/build-id.h"
 #include "util/session.h"
 #include "util/symbol.h"
+#include "util/time-utils.h"
 
 static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
 {
@@ -47,19 +49,22 @@ static bool same_kallsyms_reloc(const char *from_dir, char *to_dir)
        char to[PATH_MAX];
        const char *name;
        u64 addr1 = 0, addr2 = 0;
-       int i;
+       int i, err = -1;
 
        scnprintf(from, sizeof(from), "%s/kallsyms", from_dir);
        scnprintf(to, sizeof(to), "%s/kallsyms", to_dir);
 
        for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
-               addr1 = kallsyms__get_function_start(from, name);
-               if (addr1)
+               err = kallsyms__get_function_start(from, name, &addr1);
+               if (!err)
                        break;
        }
 
-       if (name)
-               addr2 = kallsyms__get_function_start(to, name);
+       if (err)
+               return false;
+
+       if (kallsyms__get_function_start(to, name, &addr2))
+               return false;
 
        return addr1 == addr2;
 }
@@ -276,8 +281,7 @@ static int build_id_cache__update_file(const char *filename)
        return err;
 }
 
-int cmd_buildid_cache(int argc, const char **argv,
-                     const char *prefix __maybe_unused)
+int cmd_buildid_cache(int argc, const char **argv)
 {
        struct strlist *list;
        struct str_node *pos;
index 5e914ee79eb3f0eb3a5e38db5f02e7b792b2ce2c..fdaca16e0c7488fc1c5fc1548f736b974a1ad95b 100644 (file)
@@ -16,6 +16,7 @@
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/data.h"
+#include <errno.h>
 
 static int sysfs__fprintf_build_id(FILE *fp)
 {
@@ -87,8 +88,7 @@ out:
        return 0;
 }
 
-int cmd_buildid_list(int argc, const char **argv,
-                    const char *prefix __maybe_unused)
+int cmd_buildid_list(int argc, const char **argv)
 {
        bool show_kernel = false;
        bool with_hits = false;
index e2b21723bbf8acddac596ebf519ba5b7f82c84b3..620a467ee3043c5cadfedd02c87c0195bb681413 100644 (file)
@@ -9,10 +9,13 @@
  *   Dick Fowles <fowles@inreach.com>
  *   Joe Mario <jmario@redhat.com>
  */
+#include <errno.h>
+#include <inttypes.h>
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/stringify.h>
 #include <asm/bug.h>
+#include <sys/param.h>
 #include "util.h"
 #include "debug.h"
 #include "builtin.h"
 #include "tool.h"
 #include "data.h"
 #include "sort.h"
+#include "event.h"
 #include "evlist.h"
 #include "evsel.h"
 #include <asm/bug.h>
 #include "ui/browsers/hists.h"
 #include "evlist.h"
+#include "thread.h"
 
 struct c2c_hists {
        struct hists            hists;
@@ -2334,7 +2339,7 @@ out:
 
 static void perf_c2c_display(struct perf_session *session)
 {
-       if (c2c.use_stdio)
+       if (use_browser == 0)
                perf_c2c__hists_fprintf(stdout, session);
        else
                perf_c2c__hists_browse(&c2c.hists.hists);
@@ -2536,7 +2541,7 @@ static int perf_c2c__report(int argc, const char **argv)
        OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"),
 #endif
        OPT_BOOLEAN(0, "stats", &c2c.stats_only,
-                   "Use the stdio interface"),
+                   "Display only statistic tables (implies --stdio)"),
        OPT_BOOLEAN(0, "full-symbols", &c2c.symbol_full,
                    "Display full length of symbols"),
        OPT_BOOLEAN(0, "no-source", &no_source,
@@ -2755,12 +2760,12 @@ static int perf_c2c__record(int argc, const char **argv)
                pr_debug("\n");
        }
 
-       ret = cmd_record(i, rec_argv, NULL);
+       ret = cmd_record(i, rec_argv);
        free(rec_argv);
        return ret;
 }
 
-int cmd_c2c(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_c2c(int argc, const char **argv)
 {
        argc = parse_options(argc, argv, c2c_options, c2c_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
index 8c0d93b7c2f0316dc95d18d1b36bbb38b3fac191..80668fa7556ef5731b97c795c5a3a760134a9d8f 100644 (file)
@@ -154,11 +154,12 @@ static int parse_config_arg(char *arg, char **var, char **value)
        return 0;
 }
 
-int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_config(int argc, const char **argv)
 {
        int i, ret = 0;
        struct perf_config_set *set;
        char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
+       const char *config_filename;
 
        argc = parse_options(argc, argv, config_options, config_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
@@ -175,6 +176,11 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
        else if (use_user_config)
                config_exclusive_filename = user_config;
 
+       if (!config_exclusive_filename)
+               config_filename = user_config;
+       else
+               config_filename = config_exclusive_filename;
+
        /*
         * At only 'config' sub-command, individually use the config set
         * because of reinitializing with options config file location.
@@ -192,13 +198,9 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
                        parse_options_usage(config_usage, config_options, "l", 1);
                } else {
                        ret = show_config(set);
-                       if (ret < 0) {
-                               const char * config_filename = config_exclusive_filename;
-                               if (!config_exclusive_filename)
-                                       config_filename = user_config;
+                       if (ret < 0)
                                pr_err("Nothing configured, "
                                       "please check your %s \n", config_filename);
-                       }
                }
                break;
        default:
@@ -221,13 +223,8 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
 
                                if (value == NULL)
                                        ret = show_spec_config(set, var);
-                               else {
-                                       const char *config_filename = config_exclusive_filename;
-
-                                       if (!config_exclusive_filename)
-                                               config_filename = user_config;
+                               else
                                        ret = set_config(set, config_filename, var, value);
-                               }
                                free(arg);
                        }
                } else
index 7ad6e17ac6b362cadb02e453d36ce5bb288ff2e1..0adb5f82335ad22534a6f7d91e4fc3b34086bb47 100644 (file)
@@ -6,7 +6,7 @@
 #include "data-convert.h"
 #include "data-convert-bt.h"
 
-typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
+typedef int (*data_cmd_fn_t)(int argc, const char **argv);
 
 struct data_cmd {
        const char      *name;
@@ -50,8 +50,7 @@ static const char * const data_convert_usage[] = {
        NULL
 };
 
-static int cmd_data_convert(int argc, const char **argv,
-                           const char *prefix __maybe_unused)
+static int cmd_data_convert(int argc, const char **argv)
 {
        const char *to_ctf     = NULL;
        struct perf_data_convert_opts opts = {
@@ -98,7 +97,7 @@ static struct data_cmd data_cmds[] = {
        { .name = NULL, },
 };
 
-int cmd_data(int argc, const char **argv, const char *prefix)
+int cmd_data(int argc, const char **argv)
 {
        struct data_cmd *cmd;
        const char *cmdstr;
@@ -118,7 +117,7 @@ int cmd_data(int argc, const char **argv, const char *prefix)
                if (strcmp(cmd->name, cmdstr))
                        continue;
 
-               return cmd->fn(argc, argv, prefix);
+               return cmd->fn(argc, argv);
        }
 
        pr_err("Unknown command: %s\n", cmdstr);
index 1b96a3122228f913af671d315ad0a71cedb6c11d..eec5df80f5a30460ad19962f62ad318e50f76e2f 100644 (file)
@@ -19,6 +19,8 @@
 #include "util/data.h"
 #include "util/config.h"
 
+#include <errno.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <math.h>
 
@@ -364,6 +366,7 @@ static struct perf_tool tool = {
        .exit   = perf_event__process_exit,
        .fork   = perf_event__process_fork,
        .lost   = perf_event__process_lost,
+       .namespaces = perf_event__process_namespaces,
        .ordered_events = true,
        .ordering_requires_timestamps = true,
 };
@@ -1320,7 +1323,7 @@ static int diff__config(const char *var, const char *value,
        return 0;
 }
 
-int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_diff(int argc, const char **argv)
 {
        int ret = hists__init();
 
index e09c4287fe87435d200e20f9f216de9aa71129c7..6d210e40d611b00b5a5292ccc76d5f2881a51ee5 100644 (file)
@@ -46,7 +46,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
        return 0;
 }
 
-int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_evlist(int argc, const char **argv)
 {
        struct perf_attr_details details = { .verbose = false, };
        const struct option options[] = {
index c3e643666c722cf743252a7f89b0b2b50d46d604..9e0b35cd0eeae3e7a072cbd0f11a99ee1685c97c 100644 (file)
@@ -9,13 +9,18 @@
 #include "builtin.h"
 #include "perf.h"
 
+#include <errno.h>
 #include <unistd.h>
 #include <signal.h>
+#include <fcntl.h>
+#include <poll.h>
 
 #include "debug.h"
 #include <subcmd/parse-options.h>
+#include <api/fs/tracing_path.h>
 #include "evlist.h"
 #include "target.h"
+#include "cpumap.h"
 #include "thread_map.h"
 #include "util/config.h"
 
@@ -50,11 +55,12 @@ static void ftrace__workload_exec_failed_signal(int signo __maybe_unused,
        done = true;
 }
 
-static int write_tracing_file(const char *name, const char *val)
+static int __write_tracing_file(const char *name, const char *val, bool append)
 {
        char *file;
        int fd, ret = -1;
        ssize_t size = strlen(val);
+       int flags = O_WRONLY;
 
        file = get_tracing_file(name);
        if (!file) {
@@ -62,7 +68,12 @@ static int write_tracing_file(const char *name, const char *val)
                return -1;
        }
 
-       fd = open(file, O_WRONLY);
+       if (append)
+               flags |= O_APPEND;
+       else
+               flags |= O_TRUNC;
+
+       fd = open(file, flags);
        if (fd < 0) {
                pr_debug("cannot open tracing file: %s\n", name);
                goto out;
@@ -79,6 +90,18 @@ out:
        return ret;
 }
 
+static int write_tracing_file(const char *name, const char *val)
+{
+       return __write_tracing_file(name, val, false);
+}
+
+static int append_tracing_file(const char *name, const char *val)
+{
+       return __write_tracing_file(name, val, true);
+}
+
+static int reset_tracing_cpu(void);
+
 static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
 {
        if (write_tracing_file("tracing_on", "0") < 0)
@@ -90,14 +113,78 @@ static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
        if (write_tracing_file("set_ftrace_pid", " ") < 0)
                return -1;
 
+       if (reset_tracing_cpu() < 0)
+               return -1;
+
+       return 0;
+}
+
+static int set_tracing_pid(struct perf_ftrace *ftrace)
+{
+       int i;
+       char buf[16];
+
+       if (target__has_cpu(&ftrace->target))
+               return 0;
+
+       for (i = 0; i < thread_map__nr(ftrace->evlist->threads); i++) {
+               scnprintf(buf, sizeof(buf), "%d",
+                         ftrace->evlist->threads->map[i]);
+               if (append_tracing_file("set_ftrace_pid", buf) < 0)
+                       return -1;
+       }
        return 0;
 }
 
+static int set_tracing_cpumask(struct cpu_map *cpumap)
+{
+       char *cpumask;
+       size_t mask_size;
+       int ret;
+       int last_cpu;
+
+       last_cpu = cpu_map__cpu(cpumap, cpumap->nr - 1);
+       mask_size = (last_cpu + 3) / 4 + 1;
+       mask_size += last_cpu / 32; /* ',' is needed for every 32th cpus */
+
+       cpumask = malloc(mask_size);
+       if (cpumask == NULL) {
+               pr_debug("failed to allocate cpu mask\n");
+               return -1;
+       }
+
+       cpu_map__snprint_mask(cpumap, cpumask, mask_size);
+
+       ret = write_tracing_file("tracing_cpumask", cpumask);
+
+       free(cpumask);
+       return ret;
+}
+
+static int set_tracing_cpu(struct perf_ftrace *ftrace)
+{
+       struct cpu_map *cpumap = ftrace->evlist->cpus;
+
+       if (!target__has_cpu(&ftrace->target))
+               return 0;
+
+       return set_tracing_cpumask(cpumap);
+}
+
+static int reset_tracing_cpu(void)
+{
+       struct cpu_map *cpumap = cpu_map__new(NULL);
+       int ret;
+
+       ret = set_tracing_cpumask(cpumap);
+       cpu_map__put(cpumap);
+       return ret;
+}
+
 static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
 {
        char *trace_file;
        int trace_fd;
-       char *trace_pid;
        char buf[4096];
        struct pollfd pollfd = {
                .events = POLLIN,
@@ -108,42 +195,43 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
                return -1;
        }
 
-       if (argc < 1)
-               return -1;
-
        signal(SIGINT, sig_handler);
        signal(SIGUSR1, sig_handler);
        signal(SIGCHLD, sig_handler);
+       signal(SIGPIPE, sig_handler);
 
-       reset_tracing_files(ftrace);
+       if (reset_tracing_files(ftrace) < 0)
+               goto out;
 
        /* reset ftrace buffer */
        if (write_tracing_file("trace", "0") < 0)
                goto out;
 
-       if (perf_evlist__prepare_workload(ftrace->evlist, &ftrace->target,
-                                         argv, false, ftrace__workload_exec_failed_signal) < 0)
+       if (argc && perf_evlist__prepare_workload(ftrace->evlist,
+                               &ftrace->target, argv, false,
+                               ftrace__workload_exec_failed_signal) < 0) {
                goto out;
+       }
 
-       if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
-               pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
-               goto out;
+       if (set_tracing_pid(ftrace) < 0) {
+               pr_err("failed to set ftrace pid\n");
+               goto out_reset;
        }
 
-       if (asprintf(&trace_pid, "%d", thread_map__pid(ftrace->evlist->threads, 0)) < 0) {
-               pr_err("failed to allocate pid string\n");
-               goto out;
+       if (set_tracing_cpu(ftrace) < 0) {
+               pr_err("failed to set tracing cpumask\n");
+               goto out_reset;
        }
 
-       if (write_tracing_file("set_ftrace_pid", trace_pid) < 0) {
-               pr_err("failed to set pid: %s\n", trace_pid);
-               goto out_free_pid;
+       if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
+               pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
+               goto out_reset;
        }
 
        trace_file = get_tracing_file("trace_pipe");
        if (!trace_file) {
                pr_err("failed to open trace_pipe\n");
-               goto out_free_pid;
+               goto out_reset;
        }
 
        trace_fd = open(trace_file, O_RDONLY);
@@ -152,7 +240,7 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
 
        if (trace_fd < 0) {
                pr_err("failed to open trace_pipe\n");
-               goto out_free_pid;
+               goto out_reset;
        }
 
        fcntl(trace_fd, F_SETFL, O_NONBLOCK);
@@ -163,6 +251,8 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
                goto out_close_fd;
        }
 
+       setup_pager();
+
        perf_evlist__start_workload(ftrace->evlist);
 
        while (!done) {
@@ -191,11 +281,9 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
 
 out_close_fd:
        close(trace_fd);
-out_free_pid:
-       free(trace_pid);
-out:
+out_reset:
        reset_tracing_files(ftrace);
-
+out:
        return done ? 0 : -1;
 }
 
@@ -219,7 +307,7 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb)
        return -1;
 }
 
-int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_ftrace(int argc, const char **argv)
 {
        int ret;
        struct perf_ftrace ftrace = {
@@ -227,15 +315,21 @@ int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused)
                .target = { .uid = UINT_MAX, },
        };
        const char * const ftrace_usage[] = {
-               "perf ftrace [<options>] <command>",
+               "perf ftrace [<options>] [<command>]",
                "perf ftrace [<options>] -- <command> [<options>]",
                NULL
        };
        const struct option ftrace_options[] = {
        OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
                   "tracer to use: function_graph(default) or function"),
+       OPT_STRING('p', "pid", &ftrace.target.pid, "pid",
+                  "trace on existing process id"),
        OPT_INCR('v', "verbose", &verbose,
                 "be more verbose"),
+       OPT_BOOLEAN('a', "all-cpus", &ftrace.target.system_wide,
+                   "system-wide collection from all CPUs"),
+       OPT_STRING('C', "cpu", &ftrace.target.cpu_list, "cpu",
+                   "list of cpus to monitor"),
        OPT_END()
        };
 
@@ -245,9 +339,18 @@ int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused)
 
        argc = parse_options(argc, argv, ftrace_options, ftrace_usage,
                            PARSE_OPT_STOP_AT_NON_OPTION);
-       if (!argc)
+       if (!argc && target__none(&ftrace.target))
                usage_with_options(ftrace_usage, ftrace_options);
 
+       ret = target__validate(&ftrace.target);
+       if (ret) {
+               char errbuf[512];
+
+               target__strerror(&ftrace.target, ret, errbuf, 512);
+               pr_err("%s\n", errbuf);
+               return -EINVAL;
+       }
+
        ftrace.evlist = perf_evlist__new();
        if (ftrace.evlist == NULL)
                return -ENOMEM;
index aed0d844e8c271426137abf3b622362913de2340..492f8e14ab09826f15f58023bb721206fbb9cc8f 100644 (file)
 #include <subcmd/run-command.h>
 #include <subcmd/help.h>
 #include "util/debug.h"
+#include <linux/kernel.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 static struct man_viewer_list {
        struct man_viewer_list *next;
-       char name[FLEX_ARRAY];
+       char name[0];
 } *man_viewer_list;
 
 static struct man_viewer_info_list {
        struct man_viewer_info_list *next;
        const char *info;
-       char name[FLEX_ARRAY];
+       char name[0];
 } *man_viewer_info_list;
 
 enum help_format {
@@ -301,12 +307,6 @@ void list_common_cmds_help(void)
        }
 }
 
-static int is_perf_command(const char *s)
-{
-       return is_in_cmdlist(&main_cmds, s) ||
-               is_in_cmdlist(&other_cmds, s);
-}
-
 static const char *cmd_to_page(const char *perf_cmd)
 {
        char *s;
@@ -418,7 +418,7 @@ static int show_html_page(const char *perf_cmd)
        return 0;
 }
 
-int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_help(int argc, const char **argv)
 {
        bool show_all = false;
        enum help_format help_format = HELP_FORMAT_MAN;
@@ -446,7 +446,6 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
                "perf help [--all] [--man|--web|--info] [command]",
                NULL
        };
-       const char *alias;
        int rc;
 
        load_command_list("perf-", &main_cmds, &other_cmds);
@@ -472,12 +471,6 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
                return 0;
        }
 
-       alias = alias_lookup(argv[0]);
-       if (alias && !is_perf_command(argv[0])) {
-               printf("`perf %s' is aliased to `%s'\n", argv[0], alias);
-               return 0;
-       }
-
        switch (help_format) {
        case HELP_FORMAT_MAN:
                rc = show_man_page(argv[0]);
index b9bc7e39833a47055608feffa1f5917aada33174..ea8db38eedd10a987534da2c81a1ca83cbb2109f 100644 (file)
 #include "util/data.h"
 #include "util/auxtrace.h"
 #include "util/jit.h"
+#include "util/thread.h"
 
 #include <subcmd/parse-options.h>
 
 #include <linux/list.h>
+#include <errno.h>
+#include <signal.h>
 
 struct perf_inject {
        struct perf_tool        tool;
@@ -333,6 +336,18 @@ static int perf_event__repipe_comm(struct perf_tool *tool,
        return err;
 }
 
+static int perf_event__repipe_namespaces(struct perf_tool *tool,
+                                        union perf_event *event,
+                                        struct perf_sample *sample,
+                                        struct machine *machine)
+{
+       int err = perf_event__process_namespaces(tool, event, sample, machine);
+
+       perf_event__repipe(tool, event, sample, machine);
+
+       return err;
+}
+
 static int perf_event__repipe_exit(struct perf_tool *tool,
                                   union perf_event *event,
                                   struct perf_sample *sample,
@@ -660,6 +675,7 @@ static int __cmd_inject(struct perf_inject *inject)
                session->itrace_synth_opts = &inject->itrace_synth_opts;
                inject->itrace_synth_opts.inject = true;
                inject->tool.comm           = perf_event__repipe_comm;
+               inject->tool.namespaces     = perf_event__repipe_namespaces;
                inject->tool.exit           = perf_event__repipe_exit;
                inject->tool.id_index       = perf_event__repipe_id_index;
                inject->tool.auxtrace_info  = perf_event__process_auxtrace_info;
@@ -681,6 +697,8 @@ static int __cmd_inject(struct perf_inject *inject)
                lseek(fd, output_data_offset, SEEK_SET);
 
        ret = perf_session__process_events(session);
+       if (ret)
+               return ret;
 
        if (!file_out->is_pipe) {
                if (inject->build_ids)
@@ -725,7 +743,7 @@ static int __cmd_inject(struct perf_inject *inject)
        return ret;
 }
 
-int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_inject(int argc, const char **argv)
 {
        struct perf_inject inject = {
                .tool = {
index 224bfc454b4aa53d049e642dfc9feeadb1b37165..bcfb363112d3c999b7b09d2d99b771c04358fdfa 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Released under the GPL v2. (and only v2, not any later version)
  */
+#include <inttypes.h>
 #include "builtin.h"
 #include <linux/compiler.h>
 #include <subcmd/parse-options.h>
@@ -43,7 +44,7 @@ static int __cmd_kallsyms(int argc, const char **argv)
        return 0;
 }
 
-int cmd_kallsyms(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_kallsyms(int argc, const char **argv)
 {
        const struct option options[] = {
        OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
index 6da8d083e4e596d821673ed7408c814723029aca..9409c9464667023c60841e3fb4e7a2364bc23167 100644 (file)
 
 #include "util/debug.h"
 
+#include <linux/kernel.h>
 #include <linux/rbtree.h>
 #include <linux/string.h>
+#include <errno.h>
+#include <inttypes.h>
 #include <locale.h>
 #include <regex.h>
 
+#include "sane_ctype.h"
+
 static int     kmem_slab;
 static int     kmem_page;
 
@@ -964,6 +969,7 @@ static struct perf_tool perf_kmem = {
        .comm            = perf_event__process_comm,
        .mmap            = perf_event__process_mmap,
        .mmap2           = perf_event__process_mmap2,
+       .namespaces      = perf_event__process_namespaces,
        .ordered_events  = true,
 };
 
@@ -1865,7 +1871,7 @@ static int __cmd_record(int argc, const char **argv)
        for (j = 1; j < (unsigned int)argc; j++, i++)
                rec_argv[i] = argv[j];
 
-       return cmd_record(i, rec_argv, NULL);
+       return cmd_record(i, rec_argv);
 }
 
 static int kmem_config(const char *var, const char *value, void *cb __maybe_unused)
@@ -1884,7 +1890,7 @@ static int kmem_config(const char *var, const char *value, void *cb __maybe_unus
        return 0;
 }
 
-int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_kmem(int argc, const char **argv)
 {
        const char * const default_slab_sort = "frag,hit,bytes";
        const char * const default_page_sort = "bytes,hit";
index 08fa88f62a246f4f309410da45379aa21949f14e..f309c3773522dee5c5c8a515b1c278757fca58c6 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "util/evsel.h"
 #include "util/evlist.h"
+#include "util/term.h"
 #include "util/util.h"
 #include "util/cache.h"
 #include "util/symbol.h"
 #ifdef HAVE_TIMERFD_SUPPORT
 #include <sys/timerfd.h>
 #endif
+#include <sys/time.h>
 
+#include <linux/kernel.h>
 #include <linux/time64.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <poll.h>
 #include <termios.h>
 #include <semaphore.h>
+#include <signal.h>
 #include <pthread.h>
 #include <math.h>
 
+static const char *get_filename_for_perf_kvm(void)
+{
+       const char *filename;
+
+       if (perf_host && !perf_guest)
+               filename = strdup("perf.data.host");
+       else if (!perf_host && perf_guest)
+               filename = strdup("perf.data.guest");
+       else
+               filename = strdup("perf.data.kvm");
+
+       return filename;
+}
+
 #ifdef HAVE_KVM_STAT_SUPPORT
 #include "util/kvm-stat.h"
 
@@ -1044,6 +1065,7 @@ static int read_events(struct perf_kvm_stat *kvm)
        struct perf_tool eops = {
                .sample                 = process_sample_event,
                .comm                   = perf_event__process_comm,
+               .namespaces             = perf_event__process_namespaces,
                .ordered_events         = true,
        };
        struct perf_data_file file = {
@@ -1208,7 +1230,7 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
        set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED);
 
        record_usage = kvm_stat_record_usage;
-       return cmd_record(i, rec_argv, NULL);
+       return cmd_record(i, rec_argv);
 }
 
 static int
@@ -1348,6 +1370,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
        kvm->tool.exit   = perf_event__process_exit;
        kvm->tool.fork   = perf_event__process_fork;
        kvm->tool.lost   = process_lost_event;
+       kvm->tool.namespaces  = perf_event__process_namespaces;
        kvm->tool.ordered_events = true;
        perf_tool__fill_defaults(&kvm->tool);
 
@@ -1475,7 +1498,7 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
 #endif
 
 perf_stat:
-       return cmd_stat(argc, argv, NULL);
+       return cmd_stat(argc, argv);
 }
 #endif /* HAVE_KVM_STAT_SUPPORT */
 
@@ -1494,7 +1517,7 @@ static int __cmd_record(const char *file_name, int argc, const char **argv)
 
        BUG_ON(i != rec_argc);
 
-       return cmd_record(i, rec_argv, NULL);
+       return cmd_record(i, rec_argv);
 }
 
 static int __cmd_report(const char *file_name, int argc, const char **argv)
@@ -1512,7 +1535,7 @@ static int __cmd_report(const char *file_name, int argc, const char **argv)
 
        BUG_ON(i != rec_argc);
 
-       return cmd_report(i, rec_argv, NULL);
+       return cmd_report(i, rec_argv);
 }
 
 static int
@@ -1531,10 +1554,10 @@ __cmd_buildid_list(const char *file_name, int argc, const char **argv)
 
        BUG_ON(i != rec_argc);
 
-       return cmd_buildid_list(i, rec_argv, NULL);
+       return cmd_buildid_list(i, rec_argv);
 }
 
-int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_kvm(int argc, const char **argv)
 {
        const char *file_name = NULL;
        const struct option kvm_options[] = {
@@ -1589,9 +1612,9 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
        else if (!strncmp(argv[0], "rep", 3))
                return __cmd_report(file_name, argc, argv);
        else if (!strncmp(argv[0], "diff", 4))
-               return cmd_diff(argc, argv, NULL);
+               return cmd_diff(argc, argv);
        else if (!strncmp(argv[0], "top", 3))
-               return cmd_top(argc, argv, NULL);
+               return cmd_top(argc, argv);
        else if (!strncmp(argv[0], "buildid-list", 12))
                return __cmd_buildid_list(file_name, argc, argv);
 #ifdef HAVE_KVM_STAT_SUPPORT
index 3b9d98b5feef69182a0036b3c2f57d29a3364fc9..4bf2cb4d25aa6bdba591495974f65091078d0b85 100644 (file)
@@ -18,8 +18,9 @@
 #include <subcmd/parse-options.h>
 
 static bool desc_flag = true;
+static bool details_flag;
 
-int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_list(int argc, const char **argv)
 {
        int i;
        bool raw_dump = false;
@@ -30,6 +31,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
                            "Print extra event descriptions. --no-desc to not print."),
                OPT_BOOLEAN('v', "long-desc", &long_desc_flag,
                            "Print longer event descriptions."),
+               OPT_BOOLEAN(0, "details", &details_flag,
+                           "Print information on the perf event names and expressions used internally by events."),
                OPT_INCR(0, "debug", &verbose,
                             "Enable debugging output"),
                OPT_END()
@@ -50,7 +53,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
                printf("\nList of pre-defined events (to be used in -e):\n\n");
 
        if (argc == 0) {
-               print_events(NULL, raw_dump, !desc_flag, long_desc_flag);
+               print_events(NULL, raw_dump, !desc_flag, long_desc_flag,
+                               details_flag);
                return 0;
        }
 
@@ -72,7 +76,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
                        print_hwcache_events(NULL, raw_dump);
                else if (strcmp(argv[i], "pmu") == 0)
                        print_pmu_events(NULL, raw_dump, !desc_flag,
-                                               long_desc_flag);
+                                               long_desc_flag, details_flag);
                else if (strcmp(argv[i], "sdt") == 0)
                        print_sdt_events(NULL, NULL, raw_dump);
                else if ((sep = strchr(argv[i], ':')) != NULL) {
@@ -80,7 +84,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 
                        if (sep == NULL) {
                                print_events(argv[i], raw_dump, !desc_flag,
-                                                       long_desc_flag);
+                                                       long_desc_flag,
+                                                       details_flag);
                                continue;
                        }
                        sep_idx = sep - argv[i];
@@ -103,7 +108,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
                                            event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump);
                        print_hwcache_events(s, raw_dump);
                        print_pmu_events(s, raw_dump, !desc_flag,
-                                               long_desc_flag);
+                                               long_desc_flag,
+                                               details_flag);
                        print_tracepoint_events(NULL, s, raw_dump);
                        print_sdt_events(NULL, s, raw_dump);
                        free(s);
index ce3bfb48b26f0f309b5c90cf49bb4870fbd76a4b..ff98652484a77efaa86a835b7c8f9a796ab36b50 100644 (file)
@@ -1,3 +1,5 @@
+#include <errno.h>
+#include <inttypes.h>
 #include "builtin.h"
 #include "perf.h"
 
@@ -26,6 +28,7 @@
 
 #include <linux/list.h>
 #include <linux/hash.h>
+#include <linux/kernel.h>
 
 static struct perf_session *session;
 
@@ -858,6 +861,7 @@ static int __cmd_report(bool display_info)
        struct perf_tool eops = {
                .sample          = process_sample_event,
                .comm            = perf_event__process_comm,
+               .namespaces      = perf_event__process_namespaces,
                .ordered_events  = true,
        };
        struct perf_data_file file = {
@@ -940,34 +944,36 @@ static int __cmd_record(int argc, const char **argv)
 
        BUG_ON(i != rec_argc);
 
-       ret = cmd_record(i, rec_argv, NULL);
+       ret = cmd_record(i, rec_argv);
        free(rec_argv);
        return ret;
 }
 
-int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_lock(int argc, const char **argv)
 {
-       const struct option info_options[] = {
-       OPT_BOOLEAN('t', "threads", &info_threads,
-                   "dump thread list in perf.data"),
-       OPT_BOOLEAN('m', "map", &info_map,
-                   "map of lock instances (address:name table)"),
-       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
-       OPT_END()
-       };
        const struct option lock_options[] = {
        OPT_STRING('i', "input", &input_name, "file", "input file name"),
        OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
+       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
        OPT_END()
        };
+
+       const struct option info_options[] = {
+       OPT_BOOLEAN('t', "threads", &info_threads,
+                   "dump thread list in perf.data"),
+       OPT_BOOLEAN('m', "map", &info_map,
+                   "map of lock instances (address:name table)"),
+       OPT_PARENT(lock_options)
+       };
+
        const struct option report_options[] = {
        OPT_STRING('k', "key", &sort_key, "acquired",
                    "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
-       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
        /* TODO: type */
-       OPT_END()
+       OPT_PARENT(lock_options)
        };
+
        const char * const info_usage[] = {
                "perf lock info [<options>]",
                NULL
@@ -1006,7 +1012,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
                rc = __cmd_report(false);
        } else if (!strcmp(argv[0], "script")) {
                /* Aliased to 'perf script' */
-               return cmd_script(argc, argv, prefix);
+               return cmd_script(argc, argv);
        } else if (!strcmp(argv[0], "info")) {
                if (argc) {
                        argc = parse_options(argc, argv,
index 6114e07ca6131ca94ed1a6107fb69ae3ccbab145..e001c02907937792d373f5245be0e6489b3e5210 100644 (file)
@@ -1,3 +1,7 @@
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "builtin.h"
 #include "perf.h"
 
@@ -8,6 +12,7 @@
 #include "util/data.h"
 #include "util/mem-events.h"
 #include "util/debug.h"
+#include "util/symbol.h"
 
 #define MEM_OPERATION_LOAD     0x1
 #define MEM_OPERATION_STORE    0x2
@@ -129,7 +134,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
                pr_debug("\n");
        }
 
-       ret = cmd_record(i, rec_argv, NULL);
+       ret = cmd_record(i, rec_argv);
        free(rec_argv);
        return ret;
 }
@@ -256,7 +261,7 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)
        for (j = 1; j < argc; j++, i++)
                rep_argv[i] = argv[j];
 
-       ret = cmd_report(i, rep_argv, NULL);
+       ret = cmd_report(i, rep_argv);
        free(rep_argv);
        return ret;
 }
@@ -330,7 +335,7 @@ error:
        return ret;
 }
 
-int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_mem(int argc, const char **argv)
 {
        struct stat st;
        struct perf_mem mem = {
@@ -342,6 +347,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
                        .lost           = perf_event__process_lost,
                        .fork           = perf_event__process_fork,
                        .build_id       = perf_event__process_build_id,
+                       .namespaces     = perf_event__process_namespaces,
                        .ordered_events = true,
                },
                .input_name              = "perf.data",
index 1fcebc31a50810b18c50b1a39b28f90f350a6327..d7360c2bda135ecddcbe92e33a7a808ae4269c07 100644 (file)
@@ -442,9 +442,9 @@ static int perf_del_probe_events(struct strfilter *filter)
        }
 
        if (ret == -ENOENT && ret2 == -ENOENT)
-               pr_debug("\"%s\" does not hit any event.\n", str);
-               /* Note that this is silently ignored */
-       ret = 0;
+               pr_warning("\"%s\" does not hit any event.\n", str);
+       else
+               ret = 0;
 
 error:
        if (kfd >= 0)
@@ -468,7 +468,7 @@ out:
 
 
 static int
-__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
+__cmd_probe(int argc, const char **argv)
 {
        const char * const probe_usage[] = {
                "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
@@ -687,13 +687,13 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
        return 0;
 }
 
-int cmd_probe(int argc, const char **argv, const char *prefix)
+int cmd_probe(int argc, const char **argv)
 {
        int ret;
 
        ret = init_params();
        if (!ret) {
-               ret = __cmd_probe(argc, argv, prefix);
+               ret = __cmd_probe(argc, argv);
                cleanup_params();
        }
 
index bc84a375295d7cb4920df6a4be1f91403bcdc04b..ee7d0a82ccd073cb52a49cea6b15e14d827436ad 100644 (file)
 #include "util/bpf-loader.h"
 #include "util/trigger.h"
 #include "util/perf-hooks.h"
+#include "util/time-utils.h"
+#include "util/units.h"
 #include "asm/bug.h"
 
+#include <errno.h>
+#include <inttypes.h>
+#include <poll.h>
 #include <unistd.h>
 #include <sched.h>
+#include <signal.h>
 #include <sys/mman.h>
+#include <sys/wait.h>
 #include <asm/bug.h>
 #include <linux/time64.h>
 
@@ -876,6 +883,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
        signal(SIGTERM, sig_handler);
        signal(SIGSEGV, sigsegv_handler);
 
+       if (rec->opts.record_namespaces)
+               tool->namespace_events = true;
+
        if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
                signal(SIGUSR2, snapshot_sig_handler);
                if (rec->opts.auxtrace_snapshot_mode)
@@ -983,6 +993,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
         */
        if (forks) {
                union perf_event *event;
+               pid_t tgid;
 
                event = malloc(sizeof(event->comm) + machine->id_hdr_size);
                if (event == NULL) {
@@ -996,10 +1007,30 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
                 * cannot see a correct process name for those events.
                 * Synthesize COMM event to prevent it.
                 */
-               perf_event__synthesize_comm(tool, event,
-                                           rec->evlist->workload.pid,
-                                           process_synthesized_event,
-                                           machine);
+               tgid = perf_event__synthesize_comm(tool, event,
+                                                  rec->evlist->workload.pid,
+                                                  process_synthesized_event,
+                                                  machine);
+               free(event);
+
+               if (tgid == -1)
+                       goto out_child;
+
+               event = malloc(sizeof(event->namespaces) +
+                              (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
+                              machine->id_hdr_size);
+               if (event == NULL) {
+                       err = -ENOMEM;
+                       goto out_child;
+               }
+
+               /*
+                * Synthesize NAMESPACES event for the command specified.
+                */
+               perf_event__synthesize_namespaces(tool, event,
+                                                 rec->evlist->workload.pid,
+                                                 tgid, process_synthesized_event,
+                                                 machine);
                free(event);
 
                perf_evlist__start_workload(rec->evlist);
@@ -1497,6 +1528,7 @@ static struct record record = {
                .fork           = perf_event__process_fork,
                .exit           = perf_event__process_exit,
                .comm           = perf_event__process_comm,
+               .namespaces     = perf_event__process_namespaces,
                .mmap           = perf_event__process_mmap,
                .mmap2          = perf_event__process_mmap2,
                .ordered_events = true,
@@ -1611,6 +1643,8 @@ static struct option __record_options[] = {
                          "opts", "AUX area tracing Snapshot Mode", ""),
        OPT_UINTEGER(0, "proc-map-timeout", &record.opts.proc_map_timeout,
                        "per thread proc mmap processing timeout in ms"),
+       OPT_BOOLEAN(0, "namespaces", &record.opts.record_namespaces,
+                   "Record namespaces events"),
        OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
                    "Record context switch events"),
        OPT_BOOLEAN_FLAG(0, "all-kernel", &record.opts.all_kernel,
@@ -1640,7 +1674,7 @@ static struct option __record_options[] = {
 
 struct option *record_options = __record_options;
 
-int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_record(int argc, const char **argv)
 {
        int err;
        struct record *rec = &record;
index 0a88670e56f35f6d8c5397e80264001acaf35e94..22478ff2b706ad1b9fc15c6fe13e341b98af10e5 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/rbtree.h>
 #include "util/symbol.h"
 #include "util/callchain.h"
-#include "util/strlist.h"
 #include "util/values.h"
 
 #include "perf.h"
 #include "arch/common.h"
 #include "util/time-utils.h"
 #include "util/auxtrace.h"
+#include "util/units.h"
 
 #include <dlfcn.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <regex.h>
+#include <signal.h>
 #include <linux/bitmap.h>
 #include <linux/stringify.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 struct report {
        struct perf_tool        tool;
@@ -394,8 +401,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
                fprintf(stdout, "\n\n");
        }
 
-       if (sort_order == NULL &&
-           parent_pattern == default_parent_pattern)
+       if (!quiet)
                fprintf(stdout, "#\n# (%s)\n#\n", help);
 
        if (rep->show_threads) {
@@ -682,7 +688,7 @@ const char report_callchain_help[] = "Display call graph (stack chain/backtrace)
                                     CALLCHAIN_REPORT_HELP
                                     "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
 
-int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_report(int argc, const char **argv)
 {
        struct perf_session *session;
        struct itrace_synth_opts itrace_synth_opts = { .set = 0, };
@@ -701,6 +707,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                        .mmap            = perf_event__process_mmap,
                        .mmap2           = perf_event__process_mmap2,
                        .comm            = perf_event__process_comm,
+                       .namespaces      = perf_event__process_namespaces,
                        .exit            = perf_event__process_exit,
                        .fork            = perf_event__process_fork,
                        .lost            = perf_event__process_lost,
@@ -845,6 +852,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
                             stdio__config_color, "always"),
        OPT_STRING(0, "time", &report.time_str, "str",
                   "Time span of interest (start,stop)"),
+       OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
+                   "Show inline function"),
        OPT_END()
        };
        struct perf_data_file file = {
index b94cf0de715ab9a2d6205c12053916c31d276a13..39996c53995a2f57b982536a09b420020cd9e256 100644 (file)
 
 #include "util/debug.h"
 
+#include <linux/kernel.h>
 #include <linux/log2.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
+#include <inttypes.h>
 
+#include <errno.h>
 #include <semaphore.h>
 #include <pthread.h>
 #include <math.h>
 #include <api/fs/fs.h>
 #include <linux/time64.h>
 
+#include "sane_ctype.h"
+
 #define PR_SET_NAME            15               /* Set process name */
 #define MAX_CPUS               4096
 #define COMM_LEN               20
@@ -221,6 +226,7 @@ struct perf_sched {
        unsigned int    max_stack;
        bool            show_cpu_visual;
        bool            show_wakeups;
+       bool            show_next;
        bool            show_migrations;
        bool            show_state;
        u64             skipped_samples;
@@ -1897,14 +1903,18 @@ static char task_state_char(struct thread *thread, int state)
 }
 
 static void timehist_print_sample(struct perf_sched *sched,
+                                 struct perf_evsel *evsel,
                                  struct perf_sample *sample,
                                  struct addr_location *al,
                                  struct thread *thread,
                                  u64 t, int state)
 {
        struct thread_runtime *tr = thread__priv(thread);
+       const char *next_comm = perf_evsel__strval(evsel, sample, "next_comm");
+       const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid");
        u32 max_cpus = sched->max_cpu + 1;
        char tstr[64];
+       char nstr[30];
        u64 wait_time;
 
        timestamp__scnprintf_usec(t, tstr, sizeof(tstr));
@@ -1937,7 +1947,12 @@ static void timehist_print_sample(struct perf_sched *sched,
        if (sched->show_state)
                printf(" %5c ", task_state_char(thread, state));
 
-       if (sched->show_wakeups)
+       if (sched->show_next) {
+               snprintf(nstr, sizeof(nstr), "next: %s[%d]", next_comm, next_pid);
+               printf(" %-*s", comm_width, nstr);
+       }
+
+       if (sched->show_wakeups && !sched->show_next)
                printf("  %-*s", comm_width, "");
 
        if (thread->tid == 0)
@@ -2531,7 +2546,7 @@ static int timehist_sched_change_event(struct perf_tool *tool,
        }
 
        if (!sched->summary_only)
-               timehist_print_sample(sched, sample, &al, thread, t, state);
+               timehist_print_sample(sched, evsel, sample, &al, thread, t, state);
 
 out:
        if (sched->hist_time.start == 0 && t >= ptime->start)
@@ -3262,16 +3277,17 @@ static int __cmd_record(int argc, const char **argv)
 
        BUG_ON(i != rec_argc);
 
-       return cmd_record(i, rec_argv, NULL);
+       return cmd_record(i, rec_argv);
 }
 
-int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_sched(int argc, const char **argv)
 {
        const char default_sort_order[] = "avg, max, switch, runtime";
        struct perf_sched sched = {
                .tool = {
                        .sample          = perf_sched__process_tracepoint_sample,
                        .comm            = perf_event__process_comm,
+                       .namespaces      = perf_event__process_namespaces,
                        .lost            = perf_event__process_lost,
                        .fork            = perf_sched__process_fork_event,
                        .ordered_events = true,
@@ -3340,6 +3356,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
        OPT_BOOLEAN('S', "with-summary", &sched.summary,
                    "Show all syscalls and summary with statistics"),
        OPT_BOOLEAN('w', "wakeups", &sched.show_wakeups, "Show wakeup events"),
+       OPT_BOOLEAN('n', "next", &sched.show_next, "Show next task"),
        OPT_BOOLEAN('M', "migrations", &sched.show_migrations, "Show migration events"),
        OPT_BOOLEAN('V', "cpu-visual", &sched.show_cpu_visual, "Add CPU visual"),
        OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"),
@@ -3400,7 +3417,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
         * Aliased to 'perf script' for now:
         */
        if (!strcmp(argv[0], "script"))
-               return cmd_script(argc, argv, prefix);
+               return cmd_script(argc, argv);
 
        if (!strncmp(argv[0], "rec", 3)) {
                return __cmd_record(argc, argv);
@@ -3437,10 +3454,14 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
                        if (argc)
                                usage_with_options(timehist_usage, timehist_options);
                }
-               if (sched.show_wakeups && sched.summary_only) {
-                       pr_err(" Error: -s and -w are mutually exclusive.\n");
+               if ((sched.show_wakeups || sched.show_next) &&
+                   sched.summary_only) {
+                       pr_err(" Error: -s and -[n|w] are mutually exclusive.\n");
                        parse_options_usage(timehist_usage, timehist_options, "s", true);
-                       parse_options_usage(NULL, timehist_options, "w", true);
+                       if (sched.show_wakeups)
+                               parse_options_usage(NULL, timehist_options, "w", true);
+                       if (sched.show_next)
+                               parse_options_usage(NULL, timehist_options, "n", true);
                        return -EINVAL;
                }
 
index c0783b4f7b6c650e2c35ffebfe1e2d7bb3e51e61..d05aec491cff22189d7fe763120884a639cd2cfb 100644 (file)
 #include "util/cpumap.h"
 #include "util/thread_map.h"
 #include "util/stat.h"
+#include "util/string2.h"
 #include "util/thread-stack.h"
 #include "util/time-utils.h"
+#include "print_binary.h"
 #include <linux/bitmap.h>
+#include <linux/kernel.h>
 #include <linux/stringify.h>
 #include <linux/time64.h>
 #include "asm/bug.h"
 #include "util/mem-events.h"
+#include "util/dump-insn.h"
+#include <dirent.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "sane_ctype.h"
 
 static char const              *script_name;
 static char const              *generate_script_lang;
@@ -42,6 +56,7 @@ static bool                   nanosecs;
 static const char              *cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 static struct perf_stat_config stat_config;
+static int                     max_blocks;
 
 unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH;
 
@@ -69,6 +84,7 @@ enum perf_output_field {
        PERF_OUTPUT_CALLINDENT      = 1U << 20,
        PERF_OUTPUT_INSN            = 1U << 21,
        PERF_OUTPUT_INSNLEN         = 1U << 22,
+       PERF_OUTPUT_BRSTACKINSN     = 1U << 23,
 };
 
 struct output_option {
@@ -98,6 +114,7 @@ struct output_option {
        {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
        {.str = "insn", .field = PERF_OUTPUT_INSN},
        {.str = "insnlen", .field = PERF_OUTPUT_INSNLEN},
+       {.str = "brstackinsn", .field = PERF_OUTPUT_BRSTACKINSN},
 };
 
 /* default set to maintain compatibility with current format */
@@ -292,7 +309,13 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
                       "selected. Hence, no address to lookup the source line number.\n");
                return -EINVAL;
        }
-
+       if (PRINT_FIELD(BRSTACKINSN) &&
+           !(perf_evlist__combined_branch_type(session->evlist) &
+             PERF_SAMPLE_BRANCH_ANY)) {
+               pr_err("Display of branch stack assembler requested, but non all-branch filter set\n"
+                      "Hint: run 'perf record -b ...'\n");
+               return -EINVAL;
+       }
        if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
                perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
                                        PERF_OUTPUT_TID|PERF_OUTPUT_PID))
@@ -546,6 +569,233 @@ static void print_sample_brstacksym(struct perf_sample *sample,
        }
 }
 
+#define MAXBB 16384UL
+
+static int grab_bb(u8 *buffer, u64 start, u64 end,
+                   struct machine *machine, struct thread *thread,
+                   bool *is64bit, u8 *cpumode, bool last)
+{
+       long offset, len;
+       struct addr_location al;
+       bool kernel;
+
+       if (!start || !end)
+               return 0;
+
+       kernel = machine__kernel_ip(machine, start);
+       if (kernel)
+               *cpumode = PERF_RECORD_MISC_KERNEL;
+       else
+               *cpumode = PERF_RECORD_MISC_USER;
+
+       /*
+        * Block overlaps between kernel and user.
+        * This can happen due to ring filtering
+        * On Intel CPUs the entry into the kernel is filtered,
+        * but the exit is not. Let the caller patch it up.
+        */
+       if (kernel != machine__kernel_ip(machine, end)) {
+               printf("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n",
+                               start, end);
+               return -ENXIO;
+       }
+
+       memset(&al, 0, sizeof(al));
+       if (end - start > MAXBB - MAXINSN) {
+               if (last)
+                       printf("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end);
+               else
+                       printf("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start);
+               return 0;
+       }
+
+       thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al);
+       if (!al.map || !al.map->dso) {
+               printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
+               return 0;
+       }
+       if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) {
+               printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
+               return 0;
+       }
+
+       /* Load maps to ensure dso->is_64_bit has been updated */
+       map__load(al.map);
+
+       offset = al.map->map_ip(al.map, start);
+       len = dso__data_read_offset(al.map->dso, machine, offset, (u8 *)buffer,
+                                   end - start + MAXINSN);
+
+       *is64bit = al.map->dso->is_64_bit;
+       if (len <= 0)
+               printf("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n",
+                       start, end);
+       return len;
+}
+
+static void print_jump(uint64_t ip, struct branch_entry *en,
+                      struct perf_insn *x, u8 *inbuf, int len,
+                      int insn)
+{
+       printf("\t%016" PRIx64 "\t%-30s\t#%s%s%s%s",
+              ip,
+              dump_insn(x, ip, inbuf, len, NULL),
+              en->flags.predicted ? " PRED" : "",
+              en->flags.mispred ? " MISPRED" : "",
+              en->flags.in_tx ? " INTX" : "",
+              en->flags.abort ? " ABORT" : "");
+       if (en->flags.cycles) {
+               printf(" %d cycles", en->flags.cycles);
+               if (insn)
+                       printf(" %.2f IPC", (float)insn / en->flags.cycles);
+       }
+       putchar('\n');
+}
+
+static void print_ip_sym(struct thread *thread, u8 cpumode, int cpu,
+                        uint64_t addr, struct symbol **lastsym,
+                        struct perf_event_attr *attr)
+{
+       struct addr_location al;
+       int off;
+
+       memset(&al, 0, sizeof(al));
+
+       thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
+       if (!al.map)
+               thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
+                                     addr, &al);
+       if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end)
+               return;
+
+       al.cpu = cpu;
+       al.sym = NULL;
+       if (al.map)
+               al.sym = map__find_symbol(al.map, al.addr);
+
+       if (!al.sym)
+               return;
+
+       if (al.addr < al.sym->end)
+               off = al.addr - al.sym->start;
+       else
+               off = al.addr - al.map->start - al.sym->start;
+       printf("\t%s", al.sym->name);
+       if (off)
+               printf("%+d", off);
+       putchar(':');
+       if (PRINT_FIELD(SRCLINE))
+               map__fprintf_srcline(al.map, al.addr, "\t", stdout);
+       putchar('\n');
+       *lastsym = al.sym;
+}
+
+static void print_sample_brstackinsn(struct perf_sample *sample,
+                                    struct thread *thread,
+                                    struct perf_event_attr *attr,
+                                    struct machine *machine)
+{
+       struct branch_stack *br = sample->branch_stack;
+       u64 start, end;
+       int i, insn, len, nr, ilen;
+       struct perf_insn x;
+       u8 buffer[MAXBB];
+       unsigned off;
+       struct symbol *lastsym = NULL;
+
+       if (!(br && br->nr))
+               return;
+       nr = br->nr;
+       if (max_blocks && nr > max_blocks + 1)
+               nr = max_blocks + 1;
+
+       x.thread = thread;
+       x.cpu = sample->cpu;
+
+       putchar('\n');
+
+       /* Handle first from jump, of which we don't know the entry. */
+       len = grab_bb(buffer, br->entries[nr-1].from,
+                       br->entries[nr-1].from,
+                       machine, thread, &x.is64bit, &x.cpumode, false);
+       if (len > 0) {
+               print_ip_sym(thread, x.cpumode, x.cpu,
+                            br->entries[nr - 1].from, &lastsym, attr);
+               print_jump(br->entries[nr - 1].from, &br->entries[nr - 1],
+                           &x, buffer, len, 0);
+       }
+
+       /* Print all blocks */
+       for (i = nr - 2; i >= 0; i--) {
+               if (br->entries[i].from || br->entries[i].to)
+                       pr_debug("%d: %" PRIx64 "-%" PRIx64 "\n", i,
+                                br->entries[i].from,
+                                br->entries[i].to);
+               start = br->entries[i + 1].to;
+               end   = br->entries[i].from;
+
+               len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
+               /* Patch up missing kernel transfers due to ring filters */
+               if (len == -ENXIO && i > 0) {
+                       end = br->entries[--i].from;
+                       pr_debug("\tpatching up to %" PRIx64 "-%" PRIx64 "\n", start, end);
+                       len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false);
+               }
+               if (len <= 0)
+                       continue;
+
+               insn = 0;
+               for (off = 0;; off += ilen) {
+                       uint64_t ip = start + off;
+
+                       print_ip_sym(thread, x.cpumode, x.cpu, ip, &lastsym, attr);
+                       if (ip == end) {
+                               print_jump(ip, &br->entries[i], &x, buffer + off, len - off, insn);
+                               break;
+                       } else {
+                               printf("\t%016" PRIx64 "\t%s\n", ip,
+                                       dump_insn(&x, ip, buffer + off, len - off, &ilen));
+                               if (ilen == 0)
+                                       break;
+                               insn++;
+                       }
+               }
+       }
+
+       /*
+        * Hit the branch? In this case we are already done, and the target
+        * has not been executed yet.
+        */
+       if (br->entries[0].from == sample->ip)
+               return;
+       if (br->entries[0].flags.abort)
+               return;
+
+       /*
+        * Print final block upto sample
+        */
+       start = br->entries[0].to;
+       end = sample->ip;
+       len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true);
+       print_ip_sym(thread, x.cpumode, x.cpu, start, &lastsym, attr);
+       if (len <= 0) {
+               /* Print at least last IP if basic block did not work */
+               len = grab_bb(buffer, sample->ip, sample->ip,
+                             machine, thread, &x.is64bit, &x.cpumode, false);
+               if (len <= 0)
+                       return;
+
+               printf("\t%016" PRIx64 "\t%s\n", sample->ip,
+                       dump_insn(&x, sample->ip, buffer, len, NULL));
+               return;
+       }
+       for (off = 0; off <= end - start; off += ilen) {
+               printf("\t%016" PRIx64 "\t%s\n", start + off,
+                       dump_insn(&x, start + off, buffer + off, len - off, &ilen));
+               if (ilen == 0)
+                       break;
+       }
+}
 
 static void print_sample_addr(struct perf_sample *sample,
                          struct thread *thread,
@@ -632,7 +882,9 @@ static void print_sample_callindent(struct perf_sample *sample,
 }
 
 static void print_insn(struct perf_sample *sample,
-                      struct perf_event_attr *attr)
+                      struct perf_event_attr *attr,
+                      struct thread *thread,
+                      struct machine *machine)
 {
        if (PRINT_FIELD(INSNLEN))
                printf(" ilen: %d", sample->insn_len);
@@ -643,12 +895,15 @@ static void print_insn(struct perf_sample *sample,
                for (i = 0; i < sample->insn_len; i++)
                        printf(" %02x", (unsigned char)sample->insn[i]);
        }
+       if (PRINT_FIELD(BRSTACKINSN))
+               print_sample_brstackinsn(sample, thread, attr, machine);
 }
 
 static void print_sample_bts(struct perf_sample *sample,
                             struct perf_evsel *evsel,
                             struct thread *thread,
-                            struct addr_location *al)
+                            struct addr_location *al,
+                            struct machine *machine)
 {
        struct perf_event_attr *attr = &evsel->attr;
        bool print_srcline_last = false;
@@ -689,7 +944,7 @@ static void print_sample_bts(struct perf_sample *sample,
        if (print_srcline_last)
                map__fprintf_srcline(al->map, al->addr, "\n  ", stdout);
 
-       print_insn(sample, attr);
+       print_insn(sample, attr, thread, machine);
 
        printf("\n");
 }
@@ -830,6 +1085,7 @@ struct perf_script {
        bool                    show_task_events;
        bool                    show_mmap_events;
        bool                    show_switch_events;
+       bool                    show_namespace_events;
        bool                    allocated;
        struct cpu_map          *cpus;
        struct thread_map       *threads;
@@ -871,7 +1127,8 @@ static size_t data_src__printf(u64 data_src)
 
 static void process_event(struct perf_script *script,
                          struct perf_sample *sample, struct perf_evsel *evsel,
-                         struct addr_location *al)
+                         struct addr_location *al,
+                         struct machine *machine)
 {
        struct thread *thread = al->thread;
        struct perf_event_attr *attr = &evsel->attr;
@@ -898,7 +1155,7 @@ static void process_event(struct perf_script *script,
                print_sample_flags(sample->flags);
 
        if (is_bts_event(attr)) {
-               print_sample_bts(sample, evsel, thread, al);
+               print_sample_bts(sample, evsel, thread, al, machine);
                return;
        }
 
@@ -936,7 +1193,7 @@ static void process_event(struct perf_script *script,
 
        if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT))
                print_sample_bpf_output(sample);
-       print_insn(sample, attr);
+       print_insn(sample, attr, thread, machine);
        printf("\n");
 }
 
@@ -1046,7 +1303,7 @@ static int process_sample_event(struct perf_tool *tool,
        if (scripting_ops)
                scripting_ops->process_event(event, sample, evsel, &al);
        else
-               process_event(scr, sample, evsel, &al);
+               process_event(scr, sample, evsel, &al, machine);
 
 out_put:
        addr_location__put(&al);
@@ -1118,6 +1375,41 @@ out:
        return ret;
 }
 
+static int process_namespaces_event(struct perf_tool *tool,
+                                   union perf_event *event,
+                                   struct perf_sample *sample,
+                                   struct machine *machine)
+{
+       struct thread *thread;
+       struct perf_script *script = container_of(tool, struct perf_script, tool);
+       struct perf_session *session = script->session;
+       struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+       int ret = -1;
+
+       thread = machine__findnew_thread(machine, event->namespaces.pid,
+                                        event->namespaces.tid);
+       if (thread == NULL) {
+               pr_debug("problem processing NAMESPACES event, skipping it.\n");
+               return -1;
+       }
+
+       if (perf_event__process_namespaces(tool, event, sample, machine) < 0)
+               goto out;
+
+       if (!evsel->attr.sample_id_all) {
+               sample->cpu = 0;
+               sample->time = 0;
+               sample->tid = event->namespaces.tid;
+               sample->pid = event->namespaces.pid;
+       }
+       print_sample_start(sample, thread, evsel);
+       perf_event__fprintf(event, stdout);
+       ret = 0;
+out:
+       thread__put(thread);
+       return ret;
+}
+
 static int process_fork_event(struct perf_tool *tool,
                              union perf_event *event,
                              struct perf_sample *sample,
@@ -1293,6 +1585,8 @@ static int __cmd_script(struct perf_script *script)
        }
        if (script->show_switch_events)
                script->tool.context_switch = process_switch_event;
+       if (script->show_namespace_events)
+               script->tool.namespaces = process_namespaces_event;
 
        ret = perf_session__process_events(script->session);
 
@@ -1427,7 +1721,7 @@ static int parse_scriptname(const struct option *opt __maybe_unused,
 static int parse_output_fields(const struct option *opt __maybe_unused,
                            const char *arg, int unset __maybe_unused)
 {
-       char *tok;
+       char *tok, *strtok_saveptr = NULL;
        int i, imax = ARRAY_SIZE(all_output_options);
        int j;
        int rc = 0;
@@ -1488,7 +1782,7 @@ static int parse_output_fields(const struct option *opt __maybe_unused,
                }
        }
 
-       for (tok = strtok(tok, ","); tok; tok = strtok(NULL, ",")) {
+       for (tok = strtok_r(tok, ",", &strtok_saveptr); tok; tok = strtok_r(NULL, ",", &strtok_saveptr)) {
                for (i = 0; i < imax; ++i) {
                        if (strcmp(tok, all_output_options[i].str) == 0)
                                break;
@@ -2078,7 +2372,7 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
        return set_maps(script);
 }
 
-int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_script(int argc, const char **argv)
 {
        bool show_full_info = false;
        bool header = false;
@@ -2097,6 +2391,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                        .mmap            = perf_event__process_mmap,
                        .mmap2           = perf_event__process_mmap2,
                        .comm            = perf_event__process_comm,
+                       .namespaces      = perf_event__process_namespaces,
                        .exit            = perf_event__process_exit,
                        .fork            = perf_event__process_fork,
                        .attr            = process_attr,
@@ -2152,7 +2447,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                     "Valid types: hw,sw,trace,raw. "
                     "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
                     "addr,symoff,period,iregs,brstack,brstacksym,flags,"
-                    "bpf-output,callindent,insn,insnlen", parse_output_fields),
+                    "bpf-output,callindent,insn,insnlen,brstackinsn",
+                    parse_output_fields),
        OPT_BOOLEAN('a', "all-cpus", &system_wide,
                    "system-wide collection from all CPUs"),
        OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -2180,7 +2476,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
                    "Show the mmap events"),
        OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
                    "Show context switch events (if recorded)"),
+       OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events,
+                   "Show namespace events (if recorded)"),
        OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
+       OPT_INTEGER(0, "max-blocks", &max_blocks,
+                   "Maximum number of code blocks to dump with brstackinsn"),
        OPT_BOOLEAN(0, "ns", &nanosecs,
                    "Use 9 decimal places when displaying time"),
        OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
@@ -2217,7 +2517,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
        if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
                rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
                if (!rec_script_path)
-                       return cmd_record(argc, argv, NULL);
+                       return cmd_record(argc, argv);
        }
 
        if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
index 13b54999ad79ecd4f765d557bf57764486f1fac8..a935b502373253217d6f43680e6b88a6ab143bfe 100644 (file)
 #include "util/session.h"
 #include "util/tool.h"
 #include "util/group.h"
+#include "util/string2.h"
 #include "asm/bug.h"
 
 #include <linux/time64.h>
 #include <api/fs/fs.h>
+#include <errno.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <sys/prctl.h>
+#include <inttypes.h>
 #include <locale.h>
 #include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "sane_ctype.h"
 
 #define DEFAULT_SEPARATOR      " "
 #define CNTR_NOT_SUPPORTED     "<not supported>"
@@ -140,12 +150,14 @@ static unsigned int               unit_width                      = 4; /* strlen("unit") */
 static bool                    forever                         = false;
 static bool                    metric_only                     = false;
 static bool                    force_metric_only               = false;
+static bool                    no_merge                        = false;
 static struct timespec         ref_time;
 static struct cpu_map          *aggr_map;
 static aggr_get_id_t           aggr_get_id;
 static bool                    append_file;
 static const char              *output_name;
 static int                     output_fd;
+static int                     print_free_counters_hint;
 
 struct perf_stat {
        bool                     record;
@@ -310,8 +322,12 @@ static int read_counter(struct perf_evsel *counter)
                        struct perf_counts_values *count;
 
                        count = perf_counts(counter->counts, cpu, thread);
-                       if (perf_evsel__read(counter, cpu, thread, count))
+                       if (perf_evsel__read(counter, cpu, thread, count)) {
+                               counter->counts->scaled = -1;
+                               perf_counts(counter->counts, cpu, thread)->ena = 0;
+                               perf_counts(counter->counts, cpu, thread)->run = 0;
                                return -1;
+                       }
 
                        if (STAT_RECORD) {
                                if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
@@ -336,12 +352,14 @@ static int read_counter(struct perf_evsel *counter)
 static void read_counters(void)
 {
        struct perf_evsel *counter;
+       int ret;
 
        evlist__for_each_entry(evsel_list, counter) {
-               if (read_counter(counter))
+               ret = read_counter(counter);
+               if (ret)
                        pr_debug("failed to read counter %s\n", counter->name);
 
-               if (perf_stat_process_counter(&stat_config, counter))
+               if (ret == 0 && perf_stat_process_counter(&stat_config, counter))
                        pr_warning("failed to process counter %s\n", counter->name);
        }
 }
@@ -873,10 +891,7 @@ static void print_metric_csv(void *ctx,
                return;
        }
        snprintf(buf, sizeof(buf), fmt, val);
-       vals = buf;
-       while (isspace(*vals))
-               vals++;
-       ends = vals;
+       ends = vals = ltrim(buf);
        while (isdigit(*ends) || *ends == '.')
                ends++;
        *ends = 0;
@@ -948,10 +963,7 @@ static void print_metric_only_csv(void *ctx, const char *color __maybe_unused,
                return;
        unit = fixunit(tbuf, os->evsel, unit);
        snprintf(buf, sizeof buf, fmt, val);
-       vals = buf;
-       while (isspace(*vals))
-               vals++;
-       ends = vals;
+       ends = vals = ltrim(buf);
        while (isdigit(*ends) || *ends == '.')
                ends++;
        *ends = 0;
@@ -1109,6 +1121,9 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
                        counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
                        csv_sep);
 
+               if (counter->supported)
+                       print_free_counters_hint = 1;
+
                fprintf(stat_config.output, "%-*s%s",
                        csv_output ? 0 : unit_width,
                        counter->unit, csv_sep);
@@ -1140,6 +1155,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
        out.print_metric = pm;
        out.new_line = nl;
        out.ctx = &os;
+       out.force_header = false;
 
        if (csv_output && !metric_only) {
                print_noise(counter, noise);
@@ -1178,11 +1194,81 @@ static void aggr_update_shadow(void)
        }
 }
 
+static void collect_all_aliases(struct perf_evsel *counter,
+                           void (*cb)(struct perf_evsel *counter, void *data,
+                                      bool first),
+                           void *data)
+{
+       struct perf_evsel *alias;
+
+       alias = list_prepare_entry(counter, &(evsel_list->entries), node);
+       list_for_each_entry_continue (alias, &evsel_list->entries, node) {
+               if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) ||
+                   alias->scale != counter->scale ||
+                   alias->cgrp != counter->cgrp ||
+                   strcmp(alias->unit, counter->unit) ||
+                   nsec_counter(alias) != nsec_counter(counter))
+                       break;
+               alias->merged_stat = true;
+               cb(alias, data, false);
+       }
+}
+
+static bool collect_data(struct perf_evsel *counter,
+                           void (*cb)(struct perf_evsel *counter, void *data,
+                                      bool first),
+                           void *data)
+{
+       if (counter->merged_stat)
+               return false;
+       cb(counter, data, true);
+       if (!no_merge)
+               collect_all_aliases(counter, cb, data);
+       return true;
+}
+
+struct aggr_data {
+       u64 ena, run, val;
+       int id;
+       int nr;
+       int cpu;
+};
+
+static void aggr_cb(struct perf_evsel *counter, void *data, bool first)
+{
+       struct aggr_data *ad = data;
+       int cpu, s2;
+
+       for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
+               struct perf_counts_values *counts;
+
+               s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
+               if (s2 != ad->id)
+                       continue;
+               if (first)
+                       ad->nr++;
+               counts = perf_counts(counter->counts, cpu, 0);
+               /*
+                * When any result is bad, make them all to give
+                * consistent output in interval mode.
+                */
+               if (counts->ena == 0 || counts->run == 0 ||
+                   counter->counts->scaled == -1) {
+                       ad->ena = 0;
+                       ad->run = 0;
+                       break;
+               }
+               ad->val += counts->val;
+               ad->ena += counts->ena;
+               ad->run += counts->run;
+       }
+}
+
 static void print_aggr(char *prefix)
 {
        FILE *output = stat_config.output;
        struct perf_evsel *counter;
-       int cpu, s, s2, id, nr;
+       int s, id, nr;
        double uval;
        u64 ena, run, val;
        bool first;
@@ -1197,23 +1283,21 @@ static void print_aggr(char *prefix)
         * Without each counter has its own line.
         */
        for (s = 0; s < aggr_map->nr; s++) {
+               struct aggr_data ad;
                if (prefix && metric_only)
                        fprintf(output, "%s", prefix);
 
-               id = aggr_map->map[s];
+               ad.id = id = aggr_map->map[s];
                first = true;
                evlist__for_each_entry(evsel_list, counter) {
-                       val = ena = run = 0;
-                       nr = 0;
-                       for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-                               s2 = aggr_get_id(perf_evsel__cpus(counter), cpu);
-                               if (s2 != id)
-                                       continue;
-                               val += perf_counts(counter->counts, cpu, 0)->val;
-                               ena += perf_counts(counter->counts, cpu, 0)->ena;
-                               run += perf_counts(counter->counts, cpu, 0)->run;
-                               nr++;
-                       }
+                       ad.val = ad.ena = ad.run = 0;
+                       ad.nr = 0;
+                       if (!collect_data(counter, aggr_cb, &ad))
+                               continue;
+                       nr = ad.nr;
+                       ena = ad.ena;
+                       run = ad.run;
+                       val = ad.val;
                        if (first && metric_only) {
                                first = false;
                                aggr_printout(counter, id, nr);
@@ -1257,6 +1341,21 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
        }
 }
 
+struct caggr_data {
+       double avg, avg_enabled, avg_running;
+};
+
+static void counter_aggr_cb(struct perf_evsel *counter, void *data,
+                           bool first __maybe_unused)
+{
+       struct caggr_data *cd = data;
+       struct perf_stat_evsel *ps = counter->priv;
+
+       cd->avg += avg_stats(&ps->res_stats[0]);
+       cd->avg_enabled += avg_stats(&ps->res_stats[1]);
+       cd->avg_running += avg_stats(&ps->res_stats[2]);
+}
+
 /*
  * Print out the results of a single counter:
  * aggregated counts in system-wide mode
@@ -1264,23 +1363,31 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
 static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 {
        FILE *output = stat_config.output;
-       struct perf_stat_evsel *ps = counter->priv;
-       double avg = avg_stats(&ps->res_stats[0]);
        double uval;
-       double avg_enabled, avg_running;
+       struct caggr_data cd = { .avg = 0.0 };
 
-       avg_enabled = avg_stats(&ps->res_stats[1]);
-       avg_running = avg_stats(&ps->res_stats[2]);
+       if (!collect_data(counter, counter_aggr_cb, &cd))
+               return;
 
        if (prefix && !metric_only)
                fprintf(output, "%s", prefix);
 
-       uval = avg * counter->scale;
-       printout(-1, 0, counter, uval, prefix, avg_running, avg_enabled, avg);
+       uval = cd.avg * counter->scale;
+       printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, cd.avg);
        if (!metric_only)
                fprintf(output, "\n");
 }
 
+static void counter_cb(struct perf_evsel *counter, void *data,
+                      bool first __maybe_unused)
+{
+       struct aggr_data *ad = data;
+
+       ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
+       ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
+       ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
+}
+
 /*
  * Print out the results of a single counter:
  * does not use aggregated count in system-wide
@@ -1293,9 +1400,13 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
        int cpu;
 
        for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-               val = perf_counts(counter->counts, cpu, 0)->val;
-               ena = perf_counts(counter->counts, cpu, 0)->ena;
-               run = perf_counts(counter->counts, cpu, 0)->run;
+               struct aggr_data ad = { .cpu = cpu };
+
+               if (!collect_data(counter, counter_cb, &ad))
+                       return;
+               val = ad.val;
+               ena = ad.ena;
+               run = ad.run;
 
                if (prefix)
                        fprintf(output, "%s", prefix);
@@ -1380,6 +1491,7 @@ static void print_metric_headers(const char *prefix, bool no_indent)
                out.ctx = &os;
                out.print_metric = print_metric_header;
                out.new_line = new_line_metric;
+               out.force_header = true;
                os.evsel = counter;
                perf_stat__print_shadow_stats(counter, 0,
                                              0,
@@ -1477,6 +1589,13 @@ static void print_footer(void)
                                avg_stats(&walltime_nsecs_stats));
        }
        fprintf(output, "\n\n");
+
+       if (print_free_counters_hint)
+               fprintf(output,
+"Some events weren't counted. Try disabling the NMI watchdog:\n"
+"      echo 0 > /proc/sys/kernel/nmi_watchdog\n"
+"      perf stat ...\n"
+"      echo 1 > /proc/sys/kernel/nmi_watchdog\n");
 }
 
 static void print_counters(struct timespec *ts, int argc, const char **argv)
@@ -1633,6 +1752,7 @@ static const struct option stat_options[] = {
                    "list of cpus to monitor in system-wide"),
        OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,
                    "disable CPU count aggregation", AGGR_NONE),
+       OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"),
        OPT_STRING('x', "field-separator", &csv_sep, "separator",
                   "print counts with custom separator"),
        OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
@@ -2339,7 +2459,36 @@ static int __cmd_report(int argc, const char **argv)
        return 0;
 }
 
-int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
+static void setup_system_wide(int forks)
+{
+       /*
+        * Make system wide (-a) the default target if
+        * no target was specified and one of following
+        * conditions is met:
+        *
+        *   - there's no workload specified
+        *   - there is workload specified but all requested
+        *     events are system wide events
+        */
+       if (!target__none(&target))
+               return;
+
+       if (!forks)
+               target.system_wide = true;
+       else {
+               struct perf_evsel *counter;
+
+               evlist__for_each_entry(evsel_list, counter) {
+                       if (!counter->system_wide)
+                               return;
+               }
+
+               if (evsel_list->nr_entries)
+                       target.system_wide = true;
+       }
+}
+
+int cmd_stat(int argc, const char **argv)
 {
        const char * const stat_usage[] = {
                "perf stat [<options>] [<command>]",
@@ -2361,6 +2510,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
        argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands,
                                        (const char **) stat_usage,
                                        PARSE_OPT_STOP_AT_NON_OPTION);
+       perf_stat__collect_metric_expr(evsel_list);
        perf_stat__init_shadow_stats();
 
        if (csv_sep) {
@@ -2445,9 +2595,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
        } else if (big_num_opt == 0) /* User passed --no-big-num */
                big_num = false;
 
-       /* Make system wide (-a) the default target. */
-       if (!argc && target__none(&target))
-               target.system_wide = true;
+       setup_system_wide(argc);
 
        if (run_count < 0) {
                pr_err("Run count must be a positive number\n");
index e7eaa298d34a1ec020a123ade8296451ffe30b73..4e2e61695986350a93b04b322712267068974e9e 100644 (file)
@@ -12,6 +12,8 @@
  * of the License.
  */
 
+#include <errno.h>
+#include <inttypes.h>
 #include <traceevent/event-parse.h>
 
 #include "builtin.h"
 #include "util/cache.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
+#include <linux/kernel.h>
 #include <linux/rbtree.h>
 #include <linux/time64.h>
 #include "util/symbol.h"
+#include "util/thread.h"
 #include "util/callchain.h"
-#include "util/strlist.h"
 
 #include "perf.h"
 #include "util/header.h"
@@ -1773,7 +1776,7 @@ static int timechart__io_record(int argc, const char **argv)
        for (i = 0; i < (unsigned int)argc; i++)
                *p++ = argv[i];
 
-       return cmd_record(rec_argc, rec_argv, NULL);
+       return cmd_record(rec_argc, rec_argv);
 }
 
 
@@ -1864,7 +1867,7 @@ static int timechart__record(struct timechart *tchart, int argc, const char **ar
        for (j = 0; j < (unsigned int)argc; j++)
                *p++ = argv[j];
 
-       return cmd_record(rec_argc, rec_argv, NULL);
+       return cmd_record(rec_argc, rec_argv);
 }
 
 static int
@@ -1917,8 +1920,7 @@ parse_time(const struct option *opt, const char *arg, int __maybe_unused unset)
        return 0;
 }
 
-int cmd_timechart(int argc, const char **argv,
-                 const char *prefix __maybe_unused)
+int cmd_timechart(int argc, const char **argv)
 {
        struct timechart tchart = {
                .tool = {
@@ -1933,6 +1935,11 @@ int cmd_timechart(int argc, const char **argv,
                .merge_dist = 1000,
        };
        const char *output_name = "output.svg";
+       const struct option timechart_common_options[] = {
+       OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
+       OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, "output processes data only"),
+       OPT_END()
+       };
        const struct option timechart_options[] = {
        OPT_STRING('i', "input", &input_name, "file", "input file name"),
        OPT_STRING('o', "output", &output_name, "file", "output file name"),
@@ -1940,9 +1947,6 @@ int cmd_timechart(int argc, const char **argv,
        OPT_CALLBACK(0, "highlight", NULL, "duration or task name",
                      "highlight tasks. Pass duration in ns or process name.",
                       parse_highlight),
-       OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
-       OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
-                   "output processes data only"),
        OPT_CALLBACK('p', "process", NULL, "process",
                      "process selector. Pass a pid or process name.",
                       parse_process),
@@ -1962,22 +1966,18 @@ int cmd_timechart(int argc, const char **argv,
                     "merge events that are merge-dist us apart",
                     parse_time),
        OPT_BOOLEAN('f', "force", &tchart.force, "don't complain, do it"),
-       OPT_END()
+       OPT_PARENT(timechart_common_options),
        };
        const char * const timechart_subcommands[] = { "record", NULL };
        const char *timechart_usage[] = {
                "perf timechart [<options>] {record}",
                NULL
        };
-
        const struct option timechart_record_options[] = {
-       OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
-       OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
-                   "output processes data only"),
        OPT_BOOLEAN('I', "io-only", &tchart.io_only,
                    "record only IO data"),
        OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"),
-       OPT_END()
+       OPT_PARENT(timechart_common_options),
        };
        const char * const timechart_record_usage[] = {
                "perf timechart record [<options>]",
index ab9077915763f19a71b1b36a8b50135e6a0ffbb3..10b6362ca0bf7e0b6d5fce4697b15645ba816f02 100644 (file)
 #include "util/drv_configs.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
+#include "util/event.h"
 #include "util/machine.h"
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/thread.h"
 #include "util/thread_map.h"
 #include "util/top.h"
-#include "util/util.h"
 #include <linux/rbtree.h>
 #include <subcmd/parse-options.h>
 #include "util/parse-events.h"
 #include "util/cpumap.h"
 #include "util/xyarray.h"
 #include "util/sort.h"
+#include "util/term.h"
 #include "util/intlist.h"
 #include "util/parse-branch-options.h"
 #include "arch/common.h"
@@ -58,6 +59,7 @@
 #include <errno.h>
 #include <time.h>
 #include <sched.h>
+#include <signal.h>
 
 #include <sys/syscall.h>
 #include <sys/ioctl.h>
@@ -72,6 +74,8 @@
 #include <linux/time64.h>
 #include <linux/types.h>
 
+#include "sane_ctype.h"
+
 static volatile int done;
 
 #define HEADER_LINE_NR  5
@@ -1075,7 +1079,7 @@ parse_percent_limit(const struct option *opt, const char *arg,
 const char top_callchain_help[] = CALLCHAIN_RECORD_HELP CALLCHAIN_REPORT_HELP
        "\n\t\t\t\tDefault: fp,graph,0.5,caller,function";
 
-int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_top(int argc, const char **argv)
 {
        char errbuf[BUFSIZ];
        struct perf_top top = {
index 256f1fac6f7e0069ebb047cf080fa55999dd0ae1..d014350adc526722da3a12f29421cd6d3c00f4af 100644 (file)
 #include "builtin.h"
 #include "util/color.h"
 #include "util/debug.h"
+#include "util/event.h"
 #include "util/evlist.h"
 #include <subcmd/exec-cmd.h>
 #include "util/machine.h"
+#include "util/path.h"
 #include "util/session.h"
 #include "util/thread.h"
 #include <subcmd/parse-options.h>
 #include "util/intlist.h"
 #include "util/thread_map.h"
 #include "util/stat.h"
+#include "trace/beauty/beauty.h"
 #include "trace-event.h"
 #include "util/parse-events.h"
 #include "util/bpf-loader.h"
 #include "callchain.h"
+#include "print_binary.h"
+#include "string2.h"
 #include "syscalltbl.h"
 #include "rb_resort.h"
 
+#include <errno.h>
+#include <inttypes.h>
 #include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
+#include <poll.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <string.h>
 #include <linux/err.h>
 #include <linux/filter.h>
 #include <linux/audit.h>
+#include <linux/kernel.h>
 #include <linux/random.h>
 #include <linux/stringify.h>
 #include <linux/time64.h>
 
+#include "sane_ctype.h"
+
 #ifndef O_CLOEXEC
 # define O_CLOEXEC             02000000
 #endif
@@ -267,15 +279,6 @@ out_delete:
        ({ struct syscall_tp *fields = evsel->priv; \
           fields->name.pointer(&fields->name, sample); })
 
-struct syscall_arg {
-       unsigned long val;
-       struct thread *thread;
-       struct trace  *trace;
-       void          *parm;
-       u8            idx;
-       u8            mask;
-};
-
 struct strarray {
        int         offset;
        int         nr_entries;
@@ -771,6 +774,10 @@ static struct syscall_fmt {
          .arg_parm      = { [0] = &strarray__socket_families, /* family */ }, },
        { .name     = "stat",       .errmsg = true, .alias = "newstat", },
        { .name     = "statfs",     .errmsg = true, },
+       { .name     = "statx",      .errmsg = true,
+         .arg_scnprintf = { [0] = SCA_FDAT, /* flags */
+                            [2] = SCA_STATX_FLAGS, /* flags */
+                            [3] = SCA_STATX_MASK, /* mask */ }, },
        { .name     = "swapoff",    .errmsg = true,
          .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
        { .name     = "swapon",     .errmsg = true,
@@ -821,12 +828,21 @@ struct syscall {
        void                **arg_parm;
 };
 
-static size_t fprintf_duration(unsigned long t, FILE *fp)
+/*
+ * We need to have this 'calculated' boolean because in some cases we really
+ * don't know what is the duration of a syscall, for instance, when we start
+ * a session and some threads are waiting for a syscall to finish, say 'poll',
+ * in which case all we can do is to print "( ? ) for duration and for the
+ * start timestamp.
+ */
+static size_t fprintf_duration(unsigned long t, bool calculated, FILE *fp)
 {
        double duration = (double)t / NSEC_PER_MSEC;
        size_t printed = fprintf(fp, "(");
 
-       if (duration >= 1.0)
+       if (!calculated)
+               printed += fprintf(fp, "     ?   ");
+       else if (duration >= 1.0)
                printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
        else if (duration >= 0.01)
                printed += color_fprintf(fp, PERF_COLOR_YELLOW, "%6.3f ms", duration);
@@ -1028,13 +1044,27 @@ static bool trace__filter_duration(struct trace *trace, double t)
        return t < (trace->duration_filter * NSEC_PER_MSEC);
 }
 
-static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
+static size_t __trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
 {
        double ts = (double)(tstamp - trace->base_time) / NSEC_PER_MSEC;
 
        return fprintf(fp, "%10.3f ", ts);
 }
 
+/*
+ * We're handling tstamp=0 as an undefined tstamp, i.e. like when we are
+ * using ttrace->entry_time for a thread that receives a sys_exit without
+ * first having received a sys_enter ("poll" issued before tracing session
+ * starts, lost sys_enter exit due to ring buffer overflow).
+ */
+static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
+{
+       if (tstamp > 0)
+               return __trace__fprintf_tstamp(trace, tstamp, fp);
+
+       return fprintf(fp, "         ? ");
+}
+
 static bool done = false;
 static bool interrupted = false;
 
@@ -1045,10 +1075,10 @@ static void sig_handler(int sig)
 }
 
 static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
-                                       u64 duration, u64 tstamp, FILE *fp)
+                                       u64 duration, bool duration_calculated, u64 tstamp, FILE *fp)
 {
        size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
-       printed += fprintf_duration(duration, fp);
+       printed += fprintf_duration(duration, duration_calculated, fp);
 
        if (trace->multiple_threads) {
                if (trace->show_comm)
@@ -1450,7 +1480,7 @@ static int trace__printf_interrupted_entry(struct trace *trace, struct perf_samp
 
        duration = sample->time - ttrace->entry_time;
 
-       printed  = trace__fprintf_entry_head(trace, trace->current, duration, ttrace->entry_time, trace->output);
+       printed  = trace__fprintf_entry_head(trace, trace->current, duration, true, ttrace->entry_time, trace->output);
        printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
        ttrace->entry_pending = false;
 
@@ -1497,7 +1527,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
 
        if (sc->is_exit) {
                if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
-                       trace__fprintf_entry_head(trace, thread, 1, ttrace->entry_time, trace->output);
+                       trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output);
                        fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
                }
        } else {
@@ -1545,6 +1575,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
 {
        long ret;
        u64 duration = 0;
+       bool duration_calculated = false;
        struct thread *thread;
        int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
        struct syscall *sc = trace__syscall_info(trace, evsel, id);
@@ -1573,6 +1604,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
                duration = sample->time - ttrace->entry_time;
                if (trace__filter_duration(trace, duration))
                        goto out;
+               duration_calculated = true;
        } else if (trace->duration_filter)
                goto out;
 
@@ -1588,7 +1620,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
        if (trace->summary_only)
                goto out;
 
-       trace__fprintf_entry_head(trace, thread, duration, ttrace->entry_time, trace->output);
+       trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output);
 
        if (ttrace->entry_pending) {
                fprintf(trace->output, "%-70s", ttrace->entry_str);
@@ -1653,15 +1685,17 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
 
        ttrace = thread__priv(thread);
        if (!ttrace)
-               goto out;
+               goto out_put;
 
        filename_len = strlen(filename);
+       if (filename_len == 0)
+               goto out_put;
 
        if (ttrace->filename.namelen < filename_len) {
                char *f = realloc(ttrace->filename.name, filename_len + 1);
 
                if (f == NULL)
-                               goto out;
+                       goto out_put;
 
                ttrace->filename.namelen = filename_len;
                ttrace->filename.name = f;
@@ -1671,12 +1705,12 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
        ttrace->filename.pending_open = true;
 
        if (!ttrace->filename.ptr)
-               goto out;
+               goto out_put;
 
        entry_str_len = strlen(ttrace->entry_str);
        remaining_space = trace__entry_str_size - entry_str_len - 1; /* \0 */
        if (remaining_space <= 0)
-               goto out;
+               goto out_put;
 
        if (filename_len > (size_t)remaining_space) {
                filename += filename_len - remaining_space;
@@ -1690,6 +1724,8 @@ static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
 
        ttrace->filename.ptr = 0;
        ttrace->filename.entry_str_pos = 0;
+out_put:
+       thread__put(thread);
 out:
        return 0;
 }
@@ -1710,6 +1746,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs
 
        ttrace->runtime_ms += runtime_ms;
        trace->runtime_ms += runtime_ms;
+out_put:
        thread__put(thread);
        return 0;
 
@@ -1720,8 +1757,7 @@ out_dump:
               (pid_t)perf_evsel__intval(evsel, sample, "pid"),
               runtime,
               perf_evsel__intval(evsel, sample, "vruntime"));
-       thread__put(thread);
-       return 0;
+       goto out_put;
 }
 
 static void bpf_output__printer(enum binary_printer_ops op,
@@ -1851,7 +1887,7 @@ static int trace__pgfault(struct trace *trace,
        thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION,
                              sample->ip, &al);
 
-       trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
+       trace__fprintf_entry_head(trace, thread, 0, true, sample->time, trace->output);
 
        fprintf(trace->output, "%sfault [",
                evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
@@ -1920,7 +1956,7 @@ static int trace__process_sample(struct perf_tool *tool,
 
        thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
        if (thread && thread__is_filtered(thread))
-               return 0;
+               goto out;
 
        trace__set_base_time(trace, evsel, sample);
 
@@ -1928,7 +1964,8 @@ static int trace__process_sample(struct perf_tool *tool,
                ++trace->nr_events;
                handler(trace, evsel, event, sample);
        }
-
+out:
+       thread__put(thread);
        return err;
 }
 
@@ -1988,7 +2025,7 @@ static int trace__record(struct trace *trace, int argc, const char **argv)
        for (i = 0; i < (unsigned int)argc; i++)
                rec_argv[j++] = argv[i];
 
-       return cmd_record(j, rec_argv, NULL);
+       return cmd_record(j, rec_argv);
 }
 
 static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
@@ -2415,8 +2452,9 @@ static int trace__replay(struct trace *trace)
        trace->tool.exit          = perf_event__process_exit;
        trace->tool.fork          = perf_event__process_fork;
        trace->tool.attr          = perf_event__process_attr;
-       trace->tool.tracing_data = perf_event__process_tracing_data;
+       trace->tool.tracing_data  = perf_event__process_tracing_data;
        trace->tool.build_id      = perf_event__process_build_id;
+       trace->tool.namespaces    = perf_event__process_namespaces;
 
        trace->tool.ordered_events = true;
        trace->tool.ordering_requires_timestamps = true;
@@ -2785,7 +2823,7 @@ out:
        return err;
 }
 
-int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_trace(int argc, const char **argv)
 {
        const char *trace_usage[] = {
                "perf trace [<options>] [<command>]",
index 9b10cda6b6dcca3ef7ffedb95aec802851401464..d25149456a2fc336b5d817c2d80c86d73cb06503 100644 (file)
@@ -1,9 +1,9 @@
-#include "util/util.h"
 #include "builtin.h"
 #include "perf.h"
+#include <linux/compiler.h>
+#include <stdio.h>
 
-int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused,
-               const char *prefix __maybe_unused)
+int cmd_version(int argc __maybe_unused, const char **argv __maybe_unused)
 {
        printf("perf version %s\n", perf_version_string);
        return 0;
index 036e1e35b1a8fa5ed64439cb5c73d30558ed71b4..d4d19fe3d050a86e2f0d868e1729a6c5fbb95cb8 100644 (file)
@@ -2,46 +2,42 @@
 #define BUILTIN_H
 
 #include "util/util.h"
-#include "util/strbuf.h"
 
 extern const char perf_usage_string[];
 extern const char perf_more_info_string[];
 
 void list_common_cmds_help(void);
 const char *help_unknown_cmd(const char *cmd);
-void prune_packed_objects(int);
-int read_line_with_nul(char *buf, int size, FILE *file);
-int check_pager_config(const char *cmd);
 
-int cmd_annotate(int argc, const char **argv, const char *prefix);
-int cmd_bench(int argc, const char **argv, const char *prefix);
-int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
-int cmd_buildid_list(int argc, const char **argv, const char *prefix);
-int cmd_config(int argc, const char **argv, const char *prefix);
-int cmd_c2c(int argc, const char **argv, const char *prefix);
-int cmd_diff(int argc, const char **argv, const char *prefix);
-int cmd_evlist(int argc, const char **argv, const char *prefix);
-int cmd_help(int argc, const char **argv, const char *prefix);
-int cmd_sched(int argc, const char **argv, const char *prefix);
-int cmd_kallsyms(int argc, const char **argv, const char *prefix);
-int cmd_list(int argc, const char **argv, const char *prefix);
-int cmd_record(int argc, const char **argv, const char *prefix);
-int cmd_report(int argc, const char **argv, const char *prefix);
-int cmd_stat(int argc, const char **argv, const char *prefix);
-int cmd_timechart(int argc, const char **argv, const char *prefix);
-int cmd_top(int argc, const char **argv, const char *prefix);
-int cmd_script(int argc, const char **argv, const char *prefix);
-int cmd_version(int argc, const char **argv, const char *prefix);
-int cmd_probe(int argc, const char **argv, const char *prefix);
-int cmd_kmem(int argc, const char **argv, const char *prefix);
-int cmd_lock(int argc, const char **argv, const char *prefix);
-int cmd_kvm(int argc, const char **argv, const char *prefix);
-int cmd_test(int argc, const char **argv, const char *prefix);
-int cmd_trace(int argc, const char **argv, const char *prefix);
-int cmd_inject(int argc, const char **argv, const char *prefix);
-int cmd_mem(int argc, const char **argv, const char *prefix);
-int cmd_data(int argc, const char **argv, const char *prefix);
-int cmd_ftrace(int argc, const char **argv, const char *prefix);
+int cmd_annotate(int argc, const char **argv);
+int cmd_bench(int argc, const char **argv);
+int cmd_buildid_cache(int argc, const char **argv);
+int cmd_buildid_list(int argc, const char **argv);
+int cmd_config(int argc, const char **argv);
+int cmd_c2c(int argc, const char **argv);
+int cmd_diff(int argc, const char **argv);
+int cmd_evlist(int argc, const char **argv);
+int cmd_help(int argc, const char **argv);
+int cmd_sched(int argc, const char **argv);
+int cmd_kallsyms(int argc, const char **argv);
+int cmd_list(int argc, const char **argv);
+int cmd_record(int argc, const char **argv);
+int cmd_report(int argc, const char **argv);
+int cmd_stat(int argc, const char **argv);
+int cmd_timechart(int argc, const char **argv);
+int cmd_top(int argc, const char **argv);
+int cmd_script(int argc, const char **argv);
+int cmd_version(int argc, const char **argv);
+int cmd_probe(int argc, const char **argv);
+int cmd_kmem(int argc, const char **argv);
+int cmd_lock(int argc, const char **argv);
+int cmd_kvm(int argc, const char **argv);
+int cmd_test(int argc, const char **argv);
+int cmd_trace(int argc, const char **argv);
+int cmd_inject(int argc, const char **argv);
+int cmd_mem(int argc, const char **argv);
+int cmd_data(int argc, const char **argv);
+int cmd_ftrace(int argc, const char **argv);
 
 int find_scripts(char **scripts_array, char **scripts_path_array);
 #endif
index c747bfd7f14da88e5478692a00cb30d587852a08..83fe2202382eda0cd95eafc15a726cb9022527d8 100755 (executable)
@@ -1,7 +1,9 @@
 #!/bin/sh
 
 HEADERS='
+include/uapi/linux/fcntl.h
 include/uapi/linux/perf_event.h
+include/uapi/linux/stat.h
 include/linux/hash.h
 include/uapi/linux/hw_breakpoint.h
 arch/x86/include/asm/disabled-features.h
index ac3efd396a727298802b49e6a24e530f696fcdf7..2d0caf20ff3a49dc11f8406959f46fd6d687c06b 100644 (file)
@@ -9,6 +9,7 @@ perf-buildid-cache              mainporcelain common
 perf-buildid-list              mainporcelain common
 perf-data                      mainporcelain common
 perf-diff                      mainporcelain common
+perf-c2c                       mainporcelain common
 perf-config                    mainporcelain common
 perf-evlist                    mainporcelain common
 perf-ftrace                    mainporcelain common
index 6d5479e03e0dbc080531f3037d5fe5a6644bc3c9..628a5e412cb14b00d9ead40bdcbb13db4c82bd75 100644 (file)
 #include <subcmd/parse-options.h>
 #include "util/bpf-loader.h"
 #include "util/debug.h"
+#include "util/event.h"
 #include <api/fs/fs.h>
 #include <api/fs/tracing_path.h>
+#include <errno.h>
 #include <pthread.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <linux/kernel.h>
 
 const char perf_usage_string[] =
        "perf [--version] [--help] [OPTIONS] COMMAND [ARGS]";
@@ -34,7 +41,7 @@ const char *input_name;
 
 struct cmd_struct {
        const char *cmd;
-       int (*fn)(int, const char **, const char *);
+       int (*fn)(int, const char **);
        int option;
 };
 
@@ -88,7 +95,7 @@ static int pager_command_config(const char *var, const char *value, void *data)
 }
 
 /* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
-int check_pager_config(const char *cmd)
+static int check_pager_config(const char *cmd)
 {
        int err;
        struct pager_config c;
@@ -267,71 +274,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
        return handled;
 }
 
-static int handle_alias(int *argcp, const char ***argv)
-{
-       int envchanged = 0, ret = 0, saved_errno = errno;
-       int count, option_count;
-       const char **new_argv;
-       const char *alias_command;
-       char *alias_string;
-
-       alias_command = (*argv)[0];
-       alias_string = alias_lookup(alias_command);
-       if (alias_string) {
-               if (alias_string[0] == '!') {
-                       if (*argcp > 1) {
-                               struct strbuf buf;
-
-                               if (strbuf_init(&buf, PATH_MAX) < 0 ||
-                                   strbuf_addstr(&buf, alias_string) < 0 ||
-                                   sq_quote_argv(&buf, (*argv) + 1,
-                                                 PATH_MAX) < 0)
-                                       die("Failed to allocate memory.");
-                               free(alias_string);
-                               alias_string = buf.buf;
-                       }
-                       ret = system(alias_string + 1);
-                       if (ret >= 0 && WIFEXITED(ret) &&
-                           WEXITSTATUS(ret) != 127)
-                               exit(WEXITSTATUS(ret));
-                       die("Failed to run '%s' when expanding alias '%s'",
-                           alias_string + 1, alias_command);
-               }
-               count = split_cmdline(alias_string, &new_argv);
-               if (count < 0)
-                       die("Bad alias.%s string", alias_command);
-               option_count = handle_options(&new_argv, &count, &envchanged);
-               if (envchanged)
-                       die("alias '%s' changes environment variables\n"
-                                "You can use '!perf' in the alias to do this.",
-                                alias_command);
-               memmove(new_argv - option_count, new_argv,
-                               count * sizeof(char *));
-               new_argv -= option_count;
-
-               if (count < 1)
-                       die("empty alias for %s", alias_command);
-
-               if (!strcmp(alias_command, new_argv[0]))
-                       die("recursive alias: %s", alias_command);
-
-               new_argv = realloc(new_argv, sizeof(char *) *
-                                   (count + *argcp + 1));
-               /* insert after command name */
-               memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
-               new_argv[count + *argcp] = NULL;
-
-               *argv = new_argv;
-               *argcp += count - 1;
-
-               ret = 1;
-       }
-
-       errno = saved_errno;
-
-       return ret;
-}
-
 #define RUN_SETUP      (1<<0)
 #define USE_PAGER      (1<<1)
 
@@ -339,13 +281,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
 {
        int status;
        struct stat st;
-       const char *prefix;
        char sbuf[STRERR_BUFSIZE];
 
-       prefix = NULL;
-       if (p->option & RUN_SETUP)
-               prefix = NULL; /* setup_perf_directory(); */
-
        if (use_browser == -1)
                use_browser = check_browser_config(p->cmd);
 
@@ -356,7 +293,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
        commit_pager_choice();
 
        perf_env__set_cmdline(&perf_env, argc, argv);
-       status = p->fn(argc, argv, prefix);
+       status = p->fn(argc, argv);
        perf_config__exit();
        exit_browser(status);
        perf_env__exit(&perf_env);
@@ -397,16 +334,6 @@ static void handle_internal_command(int argc, const char **argv)
 {
        const char *cmd = argv[0];
        unsigned int i;
-       static const char ext[] = STRIP_EXTENSION;
-
-       if (sizeof(ext) > 1) {
-               i = strlen(argv[0]) - strlen(ext);
-               if (i > 0 && !strcmp(argv[0] + i, ext)) {
-                       char *argv0 = strdup(argv[0]);
-                       argv[0] = cmd = argv0;
-                       argv0[i] = '\0';
-               }
-       }
 
        /* Turn "perf cmd --help" into "perf help cmd" */
        if (argc > 1 && !strcmp(argv[1], "--help")) {
@@ -448,7 +375,8 @@ static void execv_dashed_external(const char **argv)
        if (status != -ERR_RUN_COMMAND_EXEC) {
                if (IS_RUN_COMMAND_ERR(status)) {
 do_die:
-                       die("unable to run '%s'", argv[0]);
+                       pr_err("FATAL: unable to run '%s'", argv[0]);
+                       status = -128;
                }
                exit(-status);
        }
@@ -460,25 +388,12 @@ do_die:
 
 static int run_argv(int *argcp, const char ***argv)
 {
-       int done_alias = 0;
+       /* See if it's an internal command */
+       handle_internal_command(*argcp, *argv);
 
-       while (1) {
-               /* See if it's an internal command */
-               handle_internal_command(*argcp, *argv);
-
-               /* .. then try the external ones */
-               execv_dashed_external(*argv);
-
-               /* It could be an alias -- this works around the insanity
-                * of overriding "perf log" with "perf show" by having
-                * alias.log = show
-                */
-               if (done_alias || !handle_alias(argcp, argv))
-                       break;
-               done_alias = 1;
-       }
-
-       return done_alias;
+       /* .. then try the external ones */
+       execv_dashed_external(*argv);
+       return 0;
 }
 
 static void pthread__block_sigwinch(void)
@@ -566,7 +481,7 @@ int main(int argc, const char **argv)
 #ifdef HAVE_LIBAUDIT_SUPPORT
                setup_path();
                argv[0] = "trace";
-               return cmd_trace(argc, argv, NULL);
+               return cmd_trace(argc, argv);
 #else
                fprintf(stderr,
                        "trace command not available: missing audit-libs devel package at build time.\n");
@@ -611,17 +526,12 @@ int main(int argc, const char **argv)
 
        while (1) {
                static int done_help;
-               int was_alias = run_argv(&argc, &argv);
+
+               run_argv(&argc, &argv);
 
                if (errno != ENOENT)
                        break;
 
-               if (was_alias) {
-                       fprintf(stderr, "Expansion of alias '%s' failed; "
-                               "'%s' is not a perf-command\n",
-                               cmd, argv[0]);
-                       goto out;
-               }
                if (!done_help) {
                        cmd = argv[0] = help_unknown_cmd(cmd);
                        done_help = 1;
index 1c27d947c2fe55c9f0d0390695e6b586d839ec0b..806c216a1078210a028167c26eb442cec8e219b9 100644 (file)
@@ -50,6 +50,7 @@ struct record_opts {
        bool         running_time;
        bool         full_auxtrace;
        bool         auxtrace_snapshot_mode;
+       bool         record_namespaces;
        bool         record_switch_events;
        bool         all_kernel;
        bool         all_user;
diff --git a/tools/perf/pmu-events/arch/x86/broadwell/uncore.json b/tools/perf/pmu-events/arch/x86/broadwell/uncore.json
new file mode 100644 (file)
index 0000000..28e1e15
--- /dev/null
@@ -0,0 +1,278 @@
+[
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x41",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_XCORE",
+    "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
+    "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x81",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EVICTION",
+    "BriefDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
+    "PublicDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x44",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_XCORE",
+    "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
+    "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x48",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_XCORE",
+    "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
+    "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x11",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_M",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in M-state",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x21",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_M",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in M-state",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x81",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_M",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in M-state",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x18",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_I",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in I-state",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x88",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_I",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in I-state",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x1f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_MESI",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in any MESI-state",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in any MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x2f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_MESI",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in MESI-state",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x8f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_MESI",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in MESI-state",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x86",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_ES",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in E or S-state",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x16",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_ES",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in E or S-state",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x26",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_ES",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in E or S-state",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
+    "BriefDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from it's allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
+    "PublicDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from it's allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
+    "Counter": "0,",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x80",
+    "UMask": "0x02",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.DRD_DIRECT",
+    "BriefDescription": "Each cycle count number of 'valid' coherent Data Read entries that are in DirectData mode. Such entry is defined as valid when it is allocated till data sent to Core (first chunk, IDI0). Applicable for IA Cores' requests in normal case.",
+    "PublicDescription": "Each cycle count number of 'valid' coherent Data Read entries that are in DirectData mode. Such entry is defined as valid when it is allocated till data sent to Core (first chunk, IDI0). Applicable for IA Cores' requests in normal case.",
+    "Counter": "0,",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x81",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
+    "BriefDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
+    "PublicDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x81",
+    "UMask": "0x02",
+    "EventName": "UNC_ARB_TRK_REQUESTS.DRD_DIRECT",
+    "BriefDescription": "Number of Core coherent Data Read entries allocated in DirectData mode",
+    "PublicDescription": "Number of Core coherent Data Read entries allocated in DirectData mode.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x81",
+    "UMask": "0x20",
+    "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
+    "BriefDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
+    "PublicDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x84",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
+    "BriefDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
+    "PublicDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_WITH_ANY_REQUEST",
+    "BriefDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.;",
+    "PublicDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "Counter": "0,",
+    "CounterMask": "1",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "NCU",
+    "EventCode": "0x0",
+    "UMask": "0x01",
+    "EventName": "UNC_CLOCK.SOCKET",
+    "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles",
+    "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
+    "Counter": "FIXED",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  }
+]
\ No newline at end of file
index 076459c51d4e1d2cc4b91e04fb2b4efbb670ca3a..58ed6d33d1f47fcaa4b7961e0587ca4af55a9a0a 100644 (file)
@@ -1,13 +1,13 @@
 [
     {
-        "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
+        "BriefDescription": "Uncore cache clock ticks",
         "Counter": "0,1,2,3",
         "EventName": "UNC_C_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
+        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
         "Counter": "0,1,2,3",
         "EventCode": "0x34",
         "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
+        "BriefDescription": "M line evictions from LLC (writebacks to memory)",
         "Counter": "0,1,2,3",
         "EventCode": "0x37",
         "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
+        "BriefDescription": "read requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local",
+        "BriefDescription": "read requests to local home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS_LOCAL",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote",
+        "BriefDescription": "read requests to remote home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS_REMOTE",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
+        "BriefDescription": "write requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local",
+        "BriefDescription": "write requests to local home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote",
+        "BriefDescription": "write requests to remote home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct",
+        "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously)",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
+        "BriefDescription": "M line forwarded from remote cache along with writeback to memory",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
+        "BriefDescription": "M line forwarded from remote cache with no writeback to memory",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
+        "BriefDescription": "Shared line response from remote cache",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPS",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
+        "BriefDescription": "Shared line forwarded from remote cache",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
index d17dc235f7346b7efa5826c39f74329de366e125..f4b0745cdbbfcc86163f7e52c8b61854c60d30de 100644 (file)
@@ -3,7 +3,7 @@
         "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.RD",
+        "EventName": "LLC_MISSES.MEM_READ",
         "PerPkg": "1",
         "ScaleUnit": "64Bytes",
         "UMask": "0x3",
         "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.WR",
+        "EventName": "LLC_MISSES.MEM_WRITE",
         "PerPkg": "1",
         "ScaleUnit": "64Bytes",
         "UMask": "0xC",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks",
+        "BriefDescription": "Memory controller clock ticks",
         "Counter": "0,1,2,3",
-        "EventName": "UNC_M_CLOCKTICKS",
+        "EventName": "UNC_M_DCLOCKTICKS",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
+        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x85",
         "EventName": "UNC_M_POWER_CHANNEL_PPD",
-        "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
+        "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_DCLOCKTICKS) * 100.",
+        "MetricName": "power_channel_ppd %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
+        "BriefDescription": "Cycles all ranks are in critical thermal throttle",
         "Counter": "0,1,2,3",
         "EventCode": "0x86",
         "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
-        "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
+        "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_DCLOCKTICKS) * 100.",
+        "MetricName": "power_critical_throttle_cycles %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
+        "BriefDescription": "Cycles Memory is in self refresh power mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x43",
         "EventName": "UNC_M_POWER_SELF_REFRESH",
-        "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
+        "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_DCLOCKTICKS) * 100.",
+        "MetricName": "power_self_refresh %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss",
+        "BriefDescription": "Pre-charges due to page misses",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
@@ -63,7 +66,7 @@
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd",
+        "BriefDescription": "Pre-charge for reads",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.RD",
@@ -72,7 +75,7 @@
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr",
+        "BriefDescription": "Pre-charge for writes",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.WR",
index b44d43088bbb793fb407d5d99608f8eee5ceb0b1..dd1b95655d1d763c5dd1771a80ff15f3f28c5f58 100644 (file)
@@ -1,83 +1,91 @@
 [
     {
-        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
+        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
         "Counter": "0,1,2,3",
         "EventName": "UNC_P_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
         "Filter": "occ_sel=1",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c0 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
         "Filter": "occ_sel=2",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c3 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
         "Filter": "occ_sel=3",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c6 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles",
+        "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode.  This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
         "Counter": "0,1,2,3",
         "EventCode": "0xA",
         "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
         "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "prochot_external_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles",
+        "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
         "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_limit_thermal_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles",
+        "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x6",
         "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_os_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles",
+        "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x5",
         "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_power_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
+        "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x74",
         "EventName": "UNC_P_FREQ_TRANS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_trans_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     }
index 076459c51d4e1d2cc4b91e04fb2b4efbb670ca3a..58ed6d33d1f47fcaa4b7961e0587ca4af55a9a0a 100644 (file)
@@ -1,13 +1,13 @@
 [
     {
-        "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
+        "BriefDescription": "Uncore cache clock ticks",
         "Counter": "0,1,2,3",
         "EventName": "UNC_C_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
+        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
         "Counter": "0,1,2,3",
         "EventCode": "0x34",
         "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
+        "BriefDescription": "M line evictions from LLC (writebacks to memory)",
         "Counter": "0,1,2,3",
         "EventCode": "0x37",
         "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
+        "BriefDescription": "read requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local",
+        "BriefDescription": "read requests to local home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS_LOCAL",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote",
+        "BriefDescription": "read requests to remote home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS_REMOTE",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
+        "BriefDescription": "write requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local",
+        "BriefDescription": "write requests to local home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote",
+        "BriefDescription": "write requests to remote home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct",
+        "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously)",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
+        "BriefDescription": "M line forwarded from remote cache along with writeback to memory",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
+        "BriefDescription": "M line forwarded from remote cache with no writeback to memory",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
+        "BriefDescription": "Shared line response from remote cache",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPS",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
+        "BriefDescription": "Shared line forwarded from remote cache",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
index 39387f7909b265cebd52edd7967ef7d76fa3f6fa..824961318c1e5ffd8cff04c5edc34367a52afe55 100644 (file)
@@ -1,6 +1,6 @@
 [
     {
-        "BriefDescription": "QPI clock ticks. Derived from unc_q_clockticks",
+        "BriefDescription": "QPI clock ticks",
         "Counter": "0,1,2,3",
         "EventCode": "0x14",
         "EventName": "UNC_Q_CLOCKTICKS",
@@ -10,7 +10,7 @@
     {
         "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
         "Counter": "0,1,2,3",
-        "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
+        "EventName": "QPI_DATA_BANDWIDTH_TX",
         "PerPkg": "1",
         "ScaleUnit": "8Bytes",
         "UMask": "0x2",
@@ -19,7 +19,7 @@
     {
         "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
         "Counter": "0,1,2,3",
-        "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
+        "EventName": "QPI_CTL_BANDWIDTH_TX",
         "PerPkg": "1",
         "ScaleUnit": "8Bytes",
         "UMask": "0x4",
index d17dc235f7346b7efa5826c39f74329de366e125..66eed399724cd5bc574bba1abb6c9b1f4bb62ac3 100644 (file)
@@ -3,7 +3,7 @@
         "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.RD",
+        "EventName": "LLC_MISSES.MEM_READ",
         "PerPkg": "1",
         "ScaleUnit": "64Bytes",
         "UMask": "0x3",
         "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.WR",
+        "EventName": "LLC_MISSES.MEM_WRITE",
         "PerPkg": "1",
         "ScaleUnit": "64Bytes",
         "UMask": "0xC",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks",
+        "BriefDescription": "Memory controller clock ticks",
         "Counter": "0,1,2,3",
         "EventName": "UNC_M_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
+        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x85",
         "EventName": "UNC_M_POWER_CHANNEL_PPD",
         "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_channel_ppd %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
+        "BriefDescription": "Cycles all ranks are in critical thermal throttle",
         "Counter": "0,1,2,3",
         "EventCode": "0x86",
         "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
         "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_critical_throttle_cycles %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
+        "BriefDescription": "Cycles Memory is in self refresh power mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x43",
         "EventName": "UNC_M_POWER_SELF_REFRESH",
         "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_self_refresh %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss",
+        "BriefDescription": "Pre-charges due to page misses",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
@@ -63,7 +66,7 @@
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd",
+        "BriefDescription": "Pre-charge for reads",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.RD",
@@ -72,7 +75,7 @@
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr",
+        "BriefDescription": "Pre-charge for writes",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.WR",
index b44d43088bbb793fb407d5d99608f8eee5ceb0b1..dd1b95655d1d763c5dd1771a80ff15f3f28c5f58 100644 (file)
@@ -1,83 +1,91 @@
 [
     {
-        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
+        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
         "Counter": "0,1,2,3",
         "EventName": "UNC_P_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
         "Filter": "occ_sel=1",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c0 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
         "Filter": "occ_sel=2",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c3 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
         "Filter": "occ_sel=3",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c6 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles",
+        "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode.  This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
         "Counter": "0,1,2,3",
         "EventCode": "0xA",
         "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
         "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "prochot_external_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles",
+        "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
         "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_limit_thermal_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles",
+        "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x6",
         "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_os_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles",
+        "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x5",
         "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_power_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
+        "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x74",
         "EventName": "UNC_P_FREQ_TRANS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_trans_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     }
diff --git a/tools/perf/pmu-events/arch/x86/haswell/uncore.json b/tools/perf/pmu-events/arch/x86/haswell/uncore.json
new file mode 100644 (file)
index 0000000..3ef5c21
--- /dev/null
@@ -0,0 +1,374 @@
+[
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x21",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EXTERNAL",
+    "BriefDescription": "An external snoop misses in some processor core.",
+    "PublicDescription": "An external snoop misses in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x41",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_XCORE",
+    "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
+    "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x81",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EVICTION",
+    "BriefDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
+    "PublicDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x24",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_EXTERNAL",
+    "BriefDescription": "An external snoop hits a non-modified line in some processor core.",
+    "PublicDescription": "An external snoop hits a non-modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x44",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_XCORE",
+    "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
+    "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x84",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_EVICTION",
+    "BriefDescription": "A cross-core snoop resulted from L3 Eviction which hits a non-modified line in some processor core.",
+    "PublicDescription": "A cross-core snoop resulted from L3 Eviction which hits a non-modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x28",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_EXTERNAL",
+    "BriefDescription": "An external snoop hits a modified line in some processor core.",
+    "PublicDescription": "An external snoop hits a modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x48",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_XCORE",
+    "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
+    "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x88",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_EVICTION",
+    "BriefDescription": "A cross-core snoop resulted from L3 Eviction which hits a modified line in some processor core.",
+    "PublicDescription": "A cross-core snoop resulted from L3 Eviction which hits a modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x11",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_M",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in M-state.",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x21",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_M",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in M-state.",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x41",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_M",
+    "BriefDescription": "L3 Lookup external snoop request that access cache and found line in M-state.",
+    "PublicDescription": "L3 Lookup external snoop request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x81",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_M",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in M-state.",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x18",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_I",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in I-state.",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x28",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_I",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in I-state.",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x48",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_I",
+    "BriefDescription": "L3 Lookup external snoop request that access cache and found line in I-state.",
+    "PublicDescription": "L3 Lookup external snoop request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x88",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_I",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in I-state.",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x1f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_MESI",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in any MESI-state.",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in any MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x2f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_MESI",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in MESI-state.",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x4f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_MESI",
+    "BriefDescription": "L3 Lookup external snoop request that access cache and found line in MESI-state.",
+    "PublicDescription": "L3 Lookup external snoop request that access cache and found line in MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x8f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_MESI",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in MESI-state.",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x86",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_ES",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in E or S-state.",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x46",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_ES",
+    "BriefDescription": "L3 Lookup external snoop request that access cache and found line in E or S-state.",
+    "PublicDescription": "L3 Lookup external snoop request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x16",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_ES",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in E or S-state.",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x26",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_ES",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in E or S-state.",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
+    "BriefDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from it's allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
+    "PublicDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from it's allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
+    "Counter": "0",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x81",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
+    "BriefDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
+    "PublicDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x81",
+    "UMask": "0x20",
+    "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
+    "BriefDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
+    "PublicDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x83",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_COH_TRK_OCCUPANCY.All",
+    "BriefDescription": "Each cycle count number of valid entries in Coherency Tracker queue from allocation till deallocation. Aperture requests (snoops) appear as NC decoded internally and become coherent (snoop L3, access memory)",
+    "PublicDescription": "Each cycle count number of valid entries in Coherency Tracker queue from allocation till deallocation. Aperture requests (snoops) appear as NC decoded internally and become coherent (snoop L3, access memory).",
+    "Counter": "0",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x84",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
+    "BriefDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
+    "PublicDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "NCU",
+    "EventCode": "0x0",
+    "UMask": "0x01",
+    "EventName": "UNC_CLOCK.SOCKET",
+    "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles.",
+    "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
+    "Counter": "FIXED",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  }
+]
\ No newline at end of file
index 076459c51d4e1d2cc4b91e04fb2b4efbb670ca3a..58ed6d33d1f47fcaa4b7961e0587ca4af55a9a0a 100644 (file)
@@ -1,13 +1,13 @@
 [
     {
-        "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
+        "BriefDescription": "Uncore cache clock ticks",
         "Counter": "0,1,2,3",
         "EventName": "UNC_C_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
+        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
         "Counter": "0,1,2,3",
         "EventCode": "0x34",
         "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
+        "BriefDescription": "M line evictions from LLC (writebacks to memory)",
         "Counter": "0,1,2,3",
         "EventCode": "0x37",
         "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
+        "BriefDescription": "read requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local",
+        "BriefDescription": "read requests to local home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS_LOCAL",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote",
+        "BriefDescription": "read requests to remote home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS_REMOTE",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
+        "BriefDescription": "write requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local",
+        "BriefDescription": "write requests to local home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote",
+        "BriefDescription": "write requests to remote home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct",
+        "BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously)",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
+        "BriefDescription": "M line forwarded from remote cache along with writeback to memory",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
+        "BriefDescription": "M line forwarded from remote cache with no writeback to memory",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
+        "BriefDescription": "Shared line response from remote cache",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPS",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
+        "BriefDescription": "Shared line forwarded from remote cache",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
index 39387f7909b265cebd52edd7967ef7d76fa3f6fa..824961318c1e5ffd8cff04c5edc34367a52afe55 100644 (file)
@@ -1,6 +1,6 @@
 [
     {
-        "BriefDescription": "QPI clock ticks. Derived from unc_q_clockticks",
+        "BriefDescription": "QPI clock ticks",
         "Counter": "0,1,2,3",
         "EventCode": "0x14",
         "EventName": "UNC_Q_CLOCKTICKS",
@@ -10,7 +10,7 @@
     {
         "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
         "Counter": "0,1,2,3",
-        "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
+        "EventName": "QPI_DATA_BANDWIDTH_TX",
         "PerPkg": "1",
         "ScaleUnit": "8Bytes",
         "UMask": "0x2",
@@ -19,7 +19,7 @@
     {
         "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
         "Counter": "0,1,2,3",
-        "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
+        "EventName": "QPI_CTL_BANDWIDTH_TX",
         "PerPkg": "1",
         "ScaleUnit": "8Bytes",
         "UMask": "0x4",
index d17dc235f7346b7efa5826c39f74329de366e125..66eed399724cd5bc574bba1abb6c9b1f4bb62ac3 100644 (file)
@@ -3,7 +3,7 @@
         "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.RD",
+        "EventName": "LLC_MISSES.MEM_READ",
         "PerPkg": "1",
         "ScaleUnit": "64Bytes",
         "UMask": "0x3",
         "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.WR",
+        "EventName": "LLC_MISSES.MEM_WRITE",
         "PerPkg": "1",
         "ScaleUnit": "64Bytes",
         "UMask": "0xC",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks",
+        "BriefDescription": "Memory controller clock ticks",
         "Counter": "0,1,2,3",
         "EventName": "UNC_M_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
+        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x85",
         "EventName": "UNC_M_POWER_CHANNEL_PPD",
         "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_channel_ppd %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
+        "BriefDescription": "Cycles all ranks are in critical thermal throttle",
         "Counter": "0,1,2,3",
         "EventCode": "0x86",
         "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
         "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_critical_throttle_cycles %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
+        "BriefDescription": "Cycles Memory is in self refresh power mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x43",
         "EventName": "UNC_M_POWER_SELF_REFRESH",
         "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_self_refresh %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss",
+        "BriefDescription": "Pre-charges due to page misses",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
@@ -63,7 +66,7 @@
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd",
+        "BriefDescription": "Pre-charge for reads",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.RD",
@@ -72,7 +75,7 @@
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr",
+        "BriefDescription": "Pre-charge for writes",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.WR",
index b44d43088bbb793fb407d5d99608f8eee5ceb0b1..dd1b95655d1d763c5dd1771a80ff15f3f28c5f58 100644 (file)
@@ -1,83 +1,91 @@
 [
     {
-        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
+        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
         "Counter": "0,1,2,3",
         "EventName": "UNC_P_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
         "Filter": "occ_sel=1",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c0 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
         "Filter": "occ_sel=2",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c3 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
         "Filter": "occ_sel=3",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c6 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles",
+        "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode.  This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
         "Counter": "0,1,2,3",
         "EventCode": "0xA",
         "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
         "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "prochot_external_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles",
+        "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
         "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_limit_thermal_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles",
+        "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x6",
         "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_os_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles",
+        "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x5",
         "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_power_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
+        "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x74",
         "EventName": "UNC_P_FREQ_TRANS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_trans_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     }
diff --git a/tools/perf/pmu-events/arch/x86/ivybridge/uncore.json b/tools/perf/pmu-events/arch/x86/ivybridge/uncore.json
new file mode 100644 (file)
index 0000000..42c70ee
--- /dev/null
@@ -0,0 +1,314 @@
+[
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x01",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.MISS",
+    "BriefDescription": "A snoop misses in some processor core.",
+    "PublicDescription": "A snoop misses in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x02",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.INVAL",
+    "BriefDescription": "A snoop invalidates a non-modified line in some processor core.",
+    "PublicDescription": "A snoop invalidates a non-modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x04",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HIT",
+    "BriefDescription": "A snoop hits a non-modified line in some processor core.",
+    "PublicDescription": "A snoop hits a non-modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x08",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HITM",
+    "BriefDescription": "A snoop hits a modified line in some processor core.",
+    "PublicDescription": "A snoop hits a modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x10",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.INVAL_M",
+    "BriefDescription": "A snoop invalidates a modified line in some processor core.",
+    "PublicDescription": "A snoop invalidates a modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x20",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.EXTERNAL_FILTER",
+    "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to external snoop request.",
+    "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to external snoop request.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x40",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.XCORE_FILTER",
+    "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to processor core memory request.",
+    "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to processor core memory request.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x80",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.EVICTION_FILTER",
+    "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to LLC eviction.",
+    "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to LLC eviction.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x01",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.M",
+    "BriefDescription": "LLC lookup request that access cache and found line in M-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x02",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.E",
+    "BriefDescription": "LLC lookup request that access cache and found line in E-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in E-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x04",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.S",
+    "BriefDescription": "LLC lookup request that access cache and found line in S-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x08",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.I",
+    "BriefDescription": "LLC lookup request that access cache and found line in I-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x10",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_FILTER",
+    "BriefDescription": "Filter on processor core initiated cacheable read requests.",
+    "PublicDescription": "Filter on processor core initiated cacheable read requests.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x20",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_FILTER",
+    "BriefDescription": "Filter on processor core initiated cacheable write requests.",
+    "PublicDescription": "Filter on processor core initiated cacheable write requests.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x40",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_FILTER",
+    "BriefDescription": "Filter on external snoop requests.",
+    "PublicDescription": "Filter on external snoop requests.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x80",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_REQUEST_FILTER",
+    "BriefDescription": "Filter on any IRQ or IPQ initiated requests including uncacheable, non-coherent requests.",
+    "PublicDescription": "Filter on any IRQ or IPQ initiated requests including uncacheable, non-coherent requests.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
+    "BriefDescription": "Counts cycles weighted by the number of requests waiting for data returning from the memory controller. Accounts for coherent and non-coherent requests initiated by IA cores, processor graphic units, or LLC.",
+    "PublicDescription": "Counts cycles weighted by the number of requests waiting for data returning from the memory controller. Accounts for coherent and non-coherent requests initiated by IA cores, processor graphic units, or LLC.",
+    "Counter": "0",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x81",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
+    "BriefDescription": "Counts the number of coherent and in-coherent requests initiated by IA cores, processor graphic units, or LLC.",
+    "PublicDescription": "Counts the number of coherent and in-coherent requests initiated by IA cores, processor graphic units, or LLC.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x81",
+    "UMask": "0x20",
+    "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
+    "BriefDescription": "Counts the number of allocated write entries, include full, partial, and LLC evictions.",
+    "PublicDescription": "Counts the number of allocated write entries, include full, partial, and LLC evictions.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x81",
+    "UMask": "0x80",
+    "EventName": "UNC_ARB_TRK_REQUESTS.EVICTIONS",
+    "BriefDescription": "Counts the number of LLC evictions allocated.",
+    "PublicDescription": "Counts the number of LLC evictions allocated.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x83",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_COH_TRK_OCCUPANCY.ALL",
+    "BriefDescription": "Cycles weighted by number of requests pending in Coherency Tracker.",
+    "PublicDescription": "Cycles weighted by number of requests pending in Coherency Tracker.",
+    "Counter": "0",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x84",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
+    "BriefDescription": "Number of requests allocated in Coherency Tracker.",
+    "PublicDescription": "Number of requests allocated in Coherency Tracker.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_WITH_ANY_REQUEST",
+    "BriefDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "PublicDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "Counter": "0,1",
+    "CounterMask": "1",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_OVER_HALF_FULL",
+    "BriefDescription": "Cycles with at least half of the requests outstanding are waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "PublicDescription": "Cycles with at least half of the requests outstanding are waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "Counter": "0,1",
+    "CounterMask": "10",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x0",
+    "UMask": "0x01",
+    "EventName": "UNC_CLOCK.SOCKET",
+    "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles.",
+    "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
+    "Counter": "Fixed",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x06",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ES",
+    "BriefDescription": "LLC lookup request that access cache and found line in E-state or S-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in E-state or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  }
+]
\ No newline at end of file
index 2efdc6772e0b6a3a081d9b10b4644102363394c3..2674105948331ca104395cee5bb659ad318757bf 100644 (file)
@@ -1,13 +1,13 @@
 [
     {
-        "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
+        "BriefDescription": "Uncore cache clock ticks",
         "Counter": "0,1,2,3",
         "EventName": "UNC_C_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
+        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
         "Counter": "0,1",
         "EventCode": "0x34",
         "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
+        "BriefDescription": "M line evictions from LLC (writebacks to memory)",
         "Counter": "0,1",
         "EventCode": "0x37",
         "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "Occupancy for all LLC misses that are addressed to local memory. Derived from unc_c_tor_occupancy.miss_local",
+        "BriefDescription": "Occupancy for all LLC misses that are addressed to local memory",
         "EventCode": "0x36",
         "EventName": "UNC_C_TOR_OCCUPANCY.MISS_LOCAL",
         "PerPkg": "1",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "Occupancy for all LLC misses that are addressed to remote memory. Derived from unc_c_tor_occupancy.miss_remote",
+        "BriefDescription": "Occupancy for all LLC misses that are addressed to remote memory",
         "EventCode": "0x36",
         "EventName": "UNC_C_TOR_OCCUPANCY.MISS_REMOTE",
         "PerPkg": "1",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "Read requests to home agent. Derived from unc_h_requests.reads",
+        "BriefDescription": "Read requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Write requests to home agent. Derived from unc_h_requests.writes",
+        "BriefDescription": "Write requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
+        "BriefDescription": "M line forwarded from remote cache along with writeback to memory",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
+        "BriefDescription": "M line forwarded from remote cache with no writeback to memory",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
+        "BriefDescription": "Shared line response from remote cache",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPS",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
+        "BriefDescription": "Shared line forwarded from remote cache",
         "Counter": "0,1,2,3",
         "EventCode": "0x21",
         "EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
index d7e2fda1d695cabdcfeb0ad49aa9e85eefcc1fbc..b798a860bc81487873a07ea41fe5882b78b9afd4 100644 (file)
@@ -1,6 +1,6 @@
 [
     {
-        "BriefDescription": "QPI clock ticks. Use to get percentages for QPI cycles events. Derived from unc_q_clockticks",
+        "BriefDescription": "QPI clock ticks. Use to get percentages for QPI cycles events",
         "Counter": "0,1,2,3",
         "EventCode": "0x14",
         "EventName": "UNC_Q_CLOCKTICKS",
@@ -8,25 +8,27 @@
         "Unit": "QPI LL"
     },
     {
-        "BriefDescription": "Cycles where receiving QPI link is in half-width mode. Derived from unc_q_rxl0p_power_cycles",
+        "BriefDescription": "Cycles where receiving QPI link is in half-width mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x10",
         "EventName": "UNC_Q_RxL0P_POWER_CYCLES",
         "MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
+        "MetricName": "rxl0p_power_cycles %",
         "PerPkg": "1",
         "Unit": "QPI LL"
     },
     {
-        "BriefDescription": "Cycles where transmitting QPI link is in half-width mode. Derived from unc_q_txl0p_power_cycles",
+        "BriefDescription": "Cycles where transmitting QPI link is in half-width mode",
         "Counter": "0,1,2,3",
         "EventCode": "0xd",
         "EventName": "UNC_Q_TxL0P_POWER_CYCLES",
         "MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
+        "MetricName": "txl0p_power_cycles %",
         "PerPkg": "1",
         "Unit": "QPI LL"
     },
     {
-        "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
+        "BriefDescription": "Number of data flits transmitted ",
         "Counter": "0,1,2,3",
         "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
         "PerPkg": "1",
@@ -35,7 +37,7 @@
         "Unit": "QPI LL"
     },
     {
-        "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
+        "BriefDescription": "Number of non data (control) flits transmitted ",
         "Counter": "0,1,2,3",
         "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
         "PerPkg": "1",
index ac4ad4d6357b00bf98adf866904cc7786eed2855..df4b43294fa00ccd11e0594da61ec7aaeb8c03a2 100644 (file)
@@ -1,6 +1,6 @@
 [
     {
-        "BriefDescription": "Memory page activates for reads and writes. Derived from unc_m_act_count.rd",
+        "BriefDescription": "Memory page activates for reads and writes",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_M_ACT_COUNT.RD",
@@ -13,7 +13,7 @@
         "BriefDescription": "Read requests to memory controller. Derived from unc_m_cas_count.rd",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.RD",
+        "EventName": "LLC_MISSES.MEM_READ",
         "PerPkg": "1",
         "ScaleUnit": "64Bytes",
         "UMask": "0x3",
         "BriefDescription": "Write requests to memory controller. Derived from unc_m_cas_count.wr",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.WR",
+        "EventName": "LLC_MISSES.MEM_WRITE",
         "PerPkg": "1",
         "ScaleUnit": "64Bytes",
         "UMask": "0xC",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Memory controller clock ticks. Use to generate percentages for memory controller CYCLES events. Derived from unc_m_clockticks",
+        "BriefDescription": "Memory controller clock ticks. Use to generate percentages for memory controller CYCLES events",
         "Counter": "0,1,2,3",
         "EventName": "UNC_M_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
+        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x85",
         "EventName": "UNC_M_POWER_CHANNEL_PPD",
         "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_channel_ppd %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
+        "BriefDescription": "Cycles all ranks are in critical thermal throttle",
         "Counter": "0,1,2,3",
         "EventCode": "0x86",
         "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
         "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_critical_throttle_cycles %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
+        "BriefDescription": "Cycles Memory is in self refresh power mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x43",
         "EventName": "UNC_M_POWER_SELF_REFRESH",
         "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_self_refresh %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Memory page conflicts. Derived from unc_m_pre_count.page_miss",
+        "BriefDescription": "Memory page conflicts",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
index dc2586db0dfce9ba5e0f2125f65d2cf37c835b40..d40498f2cb1e9a4f3e881a1145743934f0b21576 100644 (file)
@@ -1,44 +1,48 @@
 [
     {
-        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
+        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
         "Counter": "0,1,2,3",
         "EventName": "UNC_P_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band0=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
+        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band0=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0xb",
         "EventName": "UNC_P_FREQ_BAND0_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band0_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band1=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
+        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band1=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0xc",
         "EventName": "UNC_P_FREQ_BAND1_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band1_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band2=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
+        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band2=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0xd",
         "EventName": "UNC_P_FREQ_BAND2_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band2_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
+        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0xe",
         "EventName": "UNC_P_FREQ_BAND3_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band3_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
@@ -49,6 +53,7 @@
         "EventName": "UNC_P_FREQ_BAND0_TRANSITIONS",
         "Filter": "edge=1",
         "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band0_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
@@ -59,6 +64,7 @@
         "EventName": "UNC_P_FREQ_BAND1_TRANSITIONS",
         "Filter": "edge=1",
         "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band1_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
@@ -69,6 +75,7 @@
         "EventName": "UNC_P_FREQ_BAND2_TRANSITIONS",
         "Filter": "edge=1",
         "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band2_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_BAND3_TRANSITIONS",
         "Filter": "edge=1",
         "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band3_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State.  It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c0",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
         "Filter": "occ_sel=1",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c0 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State.  It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c3",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
         "Filter": "occ_sel=2",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c3 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State.  It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c6",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
         "Filter": "occ_sel=3",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c6 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode.  This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip. Derived from unc_p_prochot_external_cycles",
+        "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode.  This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
         "Counter": "0,1,2,3",
         "EventCode": "0xa",
         "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
         "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "prochot_external_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles when thermal conditions are the upper limit on frequency.  This is related to the THERMAL_THROTTLE CYCLES_ABOVE_TEMP event, which always counts cycles when we are above the thermal temperature.  This event (STRONGEST_UPPER_LIMIT) is sampled at the output of the algorithm that determines the actual frequency, while THERMAL_THROTTLE looks at the input. Derived from unc_p_freq_max_limit_thermal_cycles",
+        "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
         "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_limit_thermal_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency. Derived from unc_p_freq_max_os_cycles",
+        "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x6",
         "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_os_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency. Derived from unc_p_freq_max_power_cycles",
+        "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x5",
         "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_power_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency. Derived from unc_p_freq_max_current_cycles",
+        "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x7",
         "EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_current_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles when the system is changing frequency.  This can not be filtered by thread ID.  One can also use it with the occupancy counter that monitors number of threads in C0 to estimate the performance impact that frequency transitions had on the system. Derived from unc_p_freq_trans_cycles",
+        "BriefDescription": "Cycles spent changing Frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x60",
         "EventName": "UNC_P_FREQ_TRANS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_trans_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
         "Filter": "filter_band0=1200",
         "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_1200mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
         "Filter": "filter_band1=2000",
         "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_2000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
         "Filter": "filter_band2=3000",
         "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_3000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
         "Filter": "filter_band3=4000",
         "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_4000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
         "Filter": "edge=1,filter_band0=1200",
         "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_1200mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
         "Filter": "edge=1,filter_band1=2000",
         "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_2000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
         "Filter": "edge=1,filter_band2=4000",
         "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_3000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
         "Filter": "edge=1,filter_band3=4000",
         "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_4000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     }
index 2f23cf0129e7ad2a61c1c04d700bce0645a92126..3fa61d962607e6a48711cf4cd0ec286c4a87c31b 100644 (file)
@@ -1,13 +1,13 @@
 [
     {
-        "BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
+        "BriefDescription": "Uncore cache clock ticks",
         "Counter": "0,1,2,3",
         "EventName": "UNC_C_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
+        "BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch)",
         "Counter": "0,1",
         "EventCode": "0x34",
         "EventName": "UNC_C_LLC_LOOKUP.ANY",
@@ -18,7 +18,7 @@
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
+        "BriefDescription": "M line evictions from LLC (writebacks to memory)",
         "Counter": "0,1",
         "EventCode": "0x37",
         "EventName": "UNC_C_LLC_VICTIMS.M_STATE",
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "Occupancy counter for all LLC misses; we divide this by UNC_C_CLOCKTICKS to get average Q depth. Derived from unc_c_tor_occupancy.miss_all",
+        "BriefDescription": "Occupancy counter for all LLC misses; we divide this by UNC_C_CLOCKTICKS to get average Q depth",
         "EventCode": "0x36",
         "EventName": "UNC_C_TOR_OCCUPANCY.MISS_ALL",
         "Filter": "filter_opc=0x182",
         "MetricExpr": "(UNC_C_TOR_OCCUPANCY.MISS_ALL / UNC_C_CLOCKTICKS) * 100.",
+        "MetricName": "tor_occupancy.miss_all %",
         "PerPkg": "1",
         "UMask": "0xa",
         "Unit": "CBO"
         "Unit": "CBO"
     },
     {
-        "BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
+        "BriefDescription": "read requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.READS",
         "Unit": "HA"
     },
     {
-        "BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
+        "BriefDescription": "write requests to home agent",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_H_REQUESTS.WRITES",
index 63351876eb57afeb65276c5225d76fbfce7f739d..1b53c0e609e33ad2a8a83133132a308b8a1d63f8 100644 (file)
@@ -1,6 +1,6 @@
 [
     {
-        "BriefDescription": "QPI clock ticks. Used to get percentages of QPI cycles events. Derived from unc_q_clockticks",
+        "BriefDescription": "QPI clock ticks. Used to get percentages of QPI cycles events",
         "Counter": "0,1,2,3",
         "EventCode": "0x14",
         "EventName": "UNC_Q_CLOCKTICKS",
@@ -8,25 +8,27 @@
         "Unit": "QPI LL"
     },
     {
-        "BriefDescription": "Cycles where receiving QPI link is in half-width mode. Derived from unc_q_rxl0p_power_cycles",
+        "BriefDescription": "Cycles where receiving QPI link is in half-width mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x10",
         "EventName": "UNC_Q_RxL0P_POWER_CYCLES",
         "MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
+        "MetricName": "rxl0p_power_cycles %",
         "PerPkg": "1",
         "Unit": "QPI LL"
     },
     {
-        "BriefDescription": "Cycles where transmitting QPI link is in half-width mode. Derived from unc_q_txl0p_power_cycles",
+        "BriefDescription": "Cycles where transmitting QPI link is in half-width mode",
         "Counter": "0,1,2,3",
         "EventCode": "0xd",
         "EventName": "UNC_Q_TxL0P_POWER_CYCLES",
         "MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
+        "MetricName": "txl0p_power_cycles %",
         "PerPkg": "1",
         "Unit": "QPI LL"
     },
     {
-        "BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
+        "BriefDescription": "Number of data flits transmitted ",
         "Counter": "0,1,2,3",
         "EventName": "UNC_Q_TxL_FLITS_G0.DATA",
         "PerPkg": "1",
@@ -35,7 +37,7 @@
         "Unit": "QPI LL"
     },
     {
-        "BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
+        "BriefDescription": "Number of non data (control) flits transmitted ",
         "Counter": "0,1,2,3",
         "EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
         "PerPkg": "1",
index e2cf6daa7b37cdeb195193bce36da2df73545758..8551cebeba23b5a92949cd62dcbc455a7a8f52a7 100644 (file)
@@ -1,6 +1,6 @@
 [
     {
-        "BriefDescription": "Memory page activates. Derived from unc_m_act_count",
+        "BriefDescription": "Memory page activates",
         "Counter": "0,1,2,3",
         "EventCode": "0x1",
         "EventName": "UNC_M_ACT_COUNT",
@@ -11,7 +11,7 @@
         "BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.RD",
+        "EventName": "LLC_MISSES.MEM_READ",
         "PerPkg": "1",
         "UMask": "0x3",
         "Unit": "iMC"
         "BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
-        "EventName": "UNC_M_CAS_COUNT.WR",
+        "EventName": "LLC_MISSES.MEM_WRITE",
         "PerPkg": "1",
         "UMask": "0xc",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Memory controller clock ticks. Used to get percentages of memory controller cycles events. Derived from unc_m_clockticks",
+        "BriefDescription": "Memory controller clock ticks. Used to get percentages of memory controller cycles events",
         "Counter": "0,1,2,3",
         "EventName": "UNC_M_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
+        "BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x85",
         "EventName": "UNC_M_POWER_CHANNEL_PPD",
         "MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_channel_ppd %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
+        "BriefDescription": "Cycles all ranks are in critical thermal throttle",
         "Counter": "0,1,2,3",
         "EventCode": "0x86",
         "EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
         "MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_critical_throttle_cycles %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
+        "BriefDescription": "Cycles Memory is in self refresh power mode",
         "Counter": "0,1,2,3",
         "EventCode": "0x43",
         "EventName": "UNC_M_POWER_SELF_REFRESH",
         "MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
+        "MetricName": "power_self_refresh %",
         "PerPkg": "1",
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Memory page conflicts. Derived from unc_m_pre_count.page_miss",
+        "BriefDescription": "Memory page conflicts",
         "Counter": "0,1,2,3",
         "EventCode": "0x2",
         "EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
@@ -69,7 +72,7 @@
         "Unit": "iMC"
     },
     {
-        "BriefDescription": "Occupancy counter for memory read queue. Derived from unc_m_rpq_occupancy",
+        "BriefDescription": "Occupancy counter for memory read queue",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_M_RPQ_OCCUPANCY",
index bbe36d547386ae7ee7ff9696874ffac82ebe0022..16034bfd06dd91ae575abaef2c219e24100cfa14 100644 (file)
@@ -1,44 +1,48 @@
 [
     {
-        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
+        "BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events",
         "Counter": "0,1,2,3",
         "EventName": "UNC_P_CLOCKTICKS",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band0=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
+        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band0=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0xb",
         "EventName": "UNC_P_FREQ_BAND0_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band0_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band1=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
+        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band1=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0xc",
         "EventName": "UNC_P_FREQ_BAND1_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band1_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band2=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
+        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band2=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0xd",
         "EventName": "UNC_P_FREQ_BAND2_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band2_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
+        "BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter.  (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0xe",
         "EventName": "UNC_P_FREQ_BAND3_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band3_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
@@ -49,6 +53,7 @@
         "EventName": "UNC_P_FREQ_BAND0_TRANSITIONS",
         "Filter": "edge=1",
         "MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band0_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
@@ -59,6 +64,7 @@
         "EventName": "UNC_P_FREQ_BAND1_TRANSITIONS",
         "Filter": "edge=1",
         "MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band1_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
@@ -69,6 +75,7 @@
         "EventName": "UNC_P_FREQ_BAND2_TRANSITIONS",
         "Filter": "edge=1",
         "MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band2_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_BAND3_TRANSITIONS",
         "Filter": "edge=1",
         "MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_band3_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c0",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
         "Filter": "occ_sel=1",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c0 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c3",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
         "Filter": "occ_sel=2",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c3 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events . Derived from unc_p_power_state_occupancy.cores_c6",
+        "BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6.  It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events ",
         "Counter": "0,1,2,3",
         "EventCode": "0x80",
         "EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
         "Filter": "occ_sel=3",
         "MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "power_state_occupancy.cores_c6 %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode.  This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip. Derived from unc_p_prochot_external_cycles",
+        "BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode.  This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip",
         "Counter": "0,1,2,3",
         "EventCode": "0xa",
         "EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
         "MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "prochot_external_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency. Derived from unc_p_freq_max_limit_thermal_cycles",
+        "BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x4",
         "EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_limit_thermal_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency. Derived from unc_p_freq_max_os_cycles",
+        "BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x6",
         "EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_os_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency. Derived from unc_p_freq_max_power_cycles",
+        "BriefDescription": "Counts the number of cycles when power is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x5",
         "EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_power_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency. Derived from unc_p_freq_max_current_cycles",
+        "BriefDescription": "Counts the number of cycles when current is the upper limit on frequency",
         "Counter": "0,1,2,3",
         "EventCode": "0x7",
         "EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_max_current_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
     {
-        "BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
+        "BriefDescription": "Cycles spent changing Frequency",
         "Counter": "0,1,2,3",
         "EventName": "UNC_P_FREQ_TRANS_CYCLES",
         "MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_trans_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
         "Filter": "filter_band0=1200",
         "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_1200mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
         "Filter": "filter_band1=2000",
         "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_2000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
         "Filter": "filter_band2=3000",
         "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_3000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
         "Filter": "filter_band3=4000",
         "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_4000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
         "Filter": "edge=1,filter_band0=1200",
         "MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_1200mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
         "Filter": "edge=1,filter_band1=2000",
         "MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_2000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
         "Filter": "edge=1,filter_band2=4000",
         "MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_3000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     },
         "EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
         "Filter": "edge=1,filter_band3=4000",
         "MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
+        "MetricName": "freq_ge_4000mhz_cycles %",
         "PerPkg": "1",
         "Unit": "PCU"
     }
index 12181bb1da2a8a294da7487b00287413fb3d8c54..d1a12e584c1b8e1223dd66266dac6745247e0aff 100644 (file)
@@ -17,6 +17,7 @@ GenuineIntel-6-3A,v18,ivybridge,core
 GenuineIntel-6-3E,v19,ivytown,core
 GenuineIntel-6-2D,v20,jaketown,core
 GenuineIntel-6-57,v9,knightslanding,core
+GenuineIntel-6-85,v9,knightslanding,core
 GenuineIntel-6-1E,v2,nehalemep,core
 GenuineIntel-6-1F,v2,nehalemep,core
 GenuineIntel-6-1A,v2,nehalemep,core
diff --git a/tools/perf/pmu-events/arch/x86/sandybridge/uncore.json b/tools/perf/pmu-events/arch/x86/sandybridge/uncore.json
new file mode 100644 (file)
index 0000000..42c70ee
--- /dev/null
@@ -0,0 +1,314 @@
+[
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x01",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.MISS",
+    "BriefDescription": "A snoop misses in some processor core.",
+    "PublicDescription": "A snoop misses in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x02",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.INVAL",
+    "BriefDescription": "A snoop invalidates a non-modified line in some processor core.",
+    "PublicDescription": "A snoop invalidates a non-modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x04",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HIT",
+    "BriefDescription": "A snoop hits a non-modified line in some processor core.",
+    "PublicDescription": "A snoop hits a non-modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x08",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HITM",
+    "BriefDescription": "A snoop hits a modified line in some processor core.",
+    "PublicDescription": "A snoop hits a modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x10",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.INVAL_M",
+    "BriefDescription": "A snoop invalidates a modified line in some processor core.",
+    "PublicDescription": "A snoop invalidates a modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x20",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.EXTERNAL_FILTER",
+    "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to external snoop request.",
+    "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to external snoop request.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x40",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.XCORE_FILTER",
+    "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to processor core memory request.",
+    "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to processor core memory request.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x80",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.EVICTION_FILTER",
+    "BriefDescription": "Filter on cross-core snoops initiated by this Cbox due to LLC eviction.",
+    "PublicDescription": "Filter on cross-core snoops initiated by this Cbox due to LLC eviction.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x01",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.M",
+    "BriefDescription": "LLC lookup request that access cache and found line in M-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x02",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.E",
+    "BriefDescription": "LLC lookup request that access cache and found line in E-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in E-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x04",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.S",
+    "BriefDescription": "LLC lookup request that access cache and found line in S-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x08",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.I",
+    "BriefDescription": "LLC lookup request that access cache and found line in I-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x10",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_FILTER",
+    "BriefDescription": "Filter on processor core initiated cacheable read requests.",
+    "PublicDescription": "Filter on processor core initiated cacheable read requests.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x20",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_FILTER",
+    "BriefDescription": "Filter on processor core initiated cacheable write requests.",
+    "PublicDescription": "Filter on processor core initiated cacheable write requests.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x40",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.EXTSNP_FILTER",
+    "BriefDescription": "Filter on external snoop requests.",
+    "PublicDescription": "Filter on external snoop requests.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x80",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_REQUEST_FILTER",
+    "BriefDescription": "Filter on any IRQ or IPQ initiated requests including uncacheable, non-coherent requests.",
+    "PublicDescription": "Filter on any IRQ or IPQ initiated requests including uncacheable, non-coherent requests.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
+    "BriefDescription": "Counts cycles weighted by the number of requests waiting for data returning from the memory controller. Accounts for coherent and non-coherent requests initiated by IA cores, processor graphic units, or LLC.",
+    "PublicDescription": "Counts cycles weighted by the number of requests waiting for data returning from the memory controller. Accounts for coherent and non-coherent requests initiated by IA cores, processor graphic units, or LLC.",
+    "Counter": "0",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x81",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
+    "BriefDescription": "Counts the number of coherent and in-coherent requests initiated by IA cores, processor graphic units, or LLC.",
+    "PublicDescription": "Counts the number of coherent and in-coherent requests initiated by IA cores, processor graphic units, or LLC.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x81",
+    "UMask": "0x20",
+    "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
+    "BriefDescription": "Counts the number of allocated write entries, include full, partial, and LLC evictions.",
+    "PublicDescription": "Counts the number of allocated write entries, include full, partial, and LLC evictions.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x81",
+    "UMask": "0x80",
+    "EventName": "UNC_ARB_TRK_REQUESTS.EVICTIONS",
+    "BriefDescription": "Counts the number of LLC evictions allocated.",
+    "PublicDescription": "Counts the number of LLC evictions allocated.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x83",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_COH_TRK_OCCUPANCY.ALL",
+    "BriefDescription": "Cycles weighted by number of requests pending in Coherency Tracker.",
+    "PublicDescription": "Cycles weighted by number of requests pending in Coherency Tracker.",
+    "Counter": "0",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x84",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
+    "BriefDescription": "Number of requests allocated in Coherency Tracker.",
+    "PublicDescription": "Number of requests allocated in Coherency Tracker.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_WITH_ANY_REQUEST",
+    "BriefDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "PublicDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "Counter": "0,1",
+    "CounterMask": "1",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_OVER_HALF_FULL",
+    "BriefDescription": "Cycles with at least half of the requests outstanding are waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "PublicDescription": "Cycles with at least half of the requests outstanding are waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "Counter": "0,1",
+    "CounterMask": "10",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "ARB",
+    "EventCode": "0x0",
+    "UMask": "0x01",
+    "EventName": "UNC_CLOCK.SOCKET",
+    "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles.",
+    "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
+    "Counter": "Fixed",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x06",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ES",
+    "BriefDescription": "LLC lookup request that access cache and found line in E-state or S-state.",
+    "PublicDescription": "LLC lookup request that access cache and found line in E-state or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  }
+]
\ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/x86/skylake/uncore.json b/tools/perf/pmu-events/arch/x86/skylake/uncore.json
new file mode 100644 (file)
index 0000000..dbc1932
--- /dev/null
@@ -0,0 +1,254 @@
+[
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x41",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_XCORE",
+    "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
+    "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which misses in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x81",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.MISS_EVICTION",
+    "BriefDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
+    "PublicDescription": "A cross-core snoop resulted from L3 Eviction which misses in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x44",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HIT_XCORE",
+    "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
+    "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a non-modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x22",
+    "UMask": "0x48",
+    "EventName": "UNC_CBO_XSNP_RESPONSE.HITM_XCORE",
+    "BriefDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
+    "PublicDescription": "A cross-core snoop initiated by this Cbox due to processor core memory request which hits a modified line in some processor core.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x21",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_M",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in M-state",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x81",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_M",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in M-state",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in M-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x18",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_I",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in I-state",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x88",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_I",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in I-state",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in I-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x1f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_MESI",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in any MESI-state",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in any MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x2f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_MESI",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in MESI-state",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x8f",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_MESI",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in MESI-state",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in MESI-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x86",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.ANY_ES",
+    "BriefDescription": "L3 Lookup any request that access cache and found line in E or S-state",
+    "PublicDescription": "L3 Lookup any request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x16",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.READ_ES",
+    "BriefDescription": "L3 Lookup read request that access cache and found line in E or S-state",
+    "PublicDescription": "L3 Lookup read request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "CBO",
+    "EventCode": "0x34",
+    "UMask": "0x26",
+    "EventName": "UNC_CBO_CACHE_LOOKUP.WRITE_ES",
+    "BriefDescription": "L3 Lookup write request that access cache and found line in E or S-state",
+    "PublicDescription": "L3 Lookup write request that access cache and found line in E or S-state.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.ALL",
+    "BriefDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from its allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
+    "PublicDescription": "Each cycle count number of all Core outgoing valid entries. Such entry is defined as valid from its allocation till first of IDI0 or DRS0 messages is sent out. Accounts for Coherent and non-coherent traffic.",
+    "Counter": "0",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x81",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_REQUESTS.ALL",
+    "BriefDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
+    "PublicDescription": "Total number of Core outgoing entries allocated. Accounts for Coherent and non-coherent traffic.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x81",
+    "UMask": "0x02",
+    "EventName": "UNC_ARB_TRK_REQUESTS.DRD_DIRECT",
+    "BriefDescription": "Number of Core coherent Data Read entries allocated in DirectData mode",
+    "PublicDescription": "Number of Core coherent Data Read entries allocated in DirectData mode.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x81",
+    "UMask": "0x20",
+    "EventName": "UNC_ARB_TRK_REQUESTS.WRITES",
+    "BriefDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
+    "PublicDescription": "Number of Writes allocated - any write transactions: full/partials writes and evictions.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x84",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_COH_TRK_REQUESTS.ALL",
+    "BriefDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
+    "PublicDescription": "Number of entries allocated. Account for Any type: e.g. Snoop, Core aperture, etc.",
+    "Counter": "0,1",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "iMPH-U",
+    "EventCode": "0x80",
+    "UMask": "0x01",
+    "EventName": "UNC_ARB_TRK_OCCUPANCY.CYCLES_WITH_ANY_REQUEST",
+    "BriefDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.;",
+    "PublicDescription": "Cycles with at least one request outstanding is waiting for data return from memory controller. Account for coherent and non-coherent requests initiated by IA Cores, Processor Graphics Unit, or LLC.",
+    "Counter": "0",
+    "CounterMask": "1",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  },
+  {
+    "Unit": "NCU",
+    "EventCode": "0x0",
+    "UMask": "0x01",
+    "EventName": "UNC_CLOCK.SOCKET",
+    "BriefDescription": "This 48-bit fixed counter counts the UCLK cycles",
+    "PublicDescription": "This 48-bit fixed counter counts the UCLK cycles.",
+    "Counter": "FIXED",
+    "CounterMask": "0",
+    "Invert": "0",
+    "EdgeDetect": "0"
+  }
+]
\ No newline at end of file
index eed09346a72afab1ede36b7b3b507f3dc5d62a84..baa073f3833475ac422e20d1ba080d18c11ed82b 100644 (file)
@@ -195,6 +195,7 @@ static struct map {
        { "CBO", "uncore_cbox" },
        { "QPI LL", "uncore_qpi" },
        { "SBO", "uncore_sbox" },
+       { "iMPH-U", "uncore_arb" },
        {}
 };
 
@@ -291,7 +292,9 @@ static void print_events_table_prefix(FILE *fp, const char *tblname)
 
 static int print_events_table_entry(void *data, char *name, char *event,
                                    char *desc, char *long_desc,
-                                   char *pmu, char *unit, char *perpkg)
+                                   char *pmu, char *unit, char *perpkg,
+                                   char *metric_expr,
+                                   char *metric_name)
 {
        struct perf_entry_data *pd = data;
        FILE *outfp = pd->outfp;
@@ -315,6 +318,10 @@ static int print_events_table_entry(void *data, char *name, char *event,
                fprintf(outfp, "\t.unit = \"%s\",\n", unit);
        if (perpkg)
                fprintf(outfp, "\t.perpkg = \"%s\",\n", perpkg);
+       if (metric_expr)
+               fprintf(outfp, "\t.metric_expr = \"%s\",\n", metric_expr);
+       if (metric_name)
+               fprintf(outfp, "\t.metric_name = \"%s\",\n", metric_name);
        fprintf(outfp, "},\n");
 
        return 0;
@@ -362,7 +369,9 @@ static char *real_event(const char *name, char *event)
 int json_events(const char *fn,
          int (*func)(void *data, char *name, char *event, char *desc,
                      char *long_desc,
-                     char *pmu, char *unit, char *perpkg),
+                     char *pmu, char *unit, char *perpkg,
+                     char *metric_expr,
+                     char *metric_name),
          void *data)
 {
        int err = -EIO;
@@ -388,6 +397,8 @@ int json_events(const char *fn,
                char *filter = NULL;
                char *perpkg = NULL;
                char *unit = NULL;
+               char *metric_expr = NULL;
+               char *metric_name = NULL;
                unsigned long long eventcode = 0;
                struct msrmap *msr = NULL;
                jsmntok_t *msrval = NULL;
@@ -398,6 +409,7 @@ int json_events(const char *fn,
                for (j = 0; j < obj->size; j += 2) {
                        jsmntok_t *field, *val;
                        int nz;
+                       char *s;
 
                        field = tok + j;
                        EXPECT(field->type == JSMN_STRING, tok + j,
@@ -444,7 +456,6 @@ int json_events(const char *fn,
                                        NULL);
                        } else if (json_streq(map, field, "Unit")) {
                                const char *ppmu;
-                               char *s;
 
                                ppmu = field_to_perf(unit_to_pmu, map, val);
                                if (ppmu) {
@@ -458,12 +469,19 @@ int json_events(const char *fn,
                                }
                                addfield(map, &desc, ". ", "Unit: ", NULL);
                                addfield(map, &desc, "", pmu, NULL);
+                               addfield(map, &desc, "", " ", NULL);
                        } else if (json_streq(map, field, "Filter")) {
                                addfield(map, &filter, "", "", val);
                        } else if (json_streq(map, field, "ScaleUnit")) {
                                addfield(map, &unit, "", "", val);
                        } else if (json_streq(map, field, "PerPkg")) {
                                addfield(map, &perpkg, "", "", val);
+                       } else if (json_streq(map, field, "MetricName")) {
+                               addfield(map, &metric_name, "", "", val);
+                       } else if (json_streq(map, field, "MetricExpr")) {
+                               addfield(map, &metric_expr, "", "", val);
+                               for (s = metric_expr; *s; s++)
+                                       *s = tolower(*s);
                        }
                        /* ignore unknown fields */
                }
@@ -488,7 +506,7 @@ int json_events(const char *fn,
                fixname(name);
 
                err = func(data, name, real_event(name, event), desc, long_desc,
-                               pmu, unit, perpkg);
+                               pmu, unit, perpkg, metric_expr, metric_name);
                free(event);
                free(desc);
                free(name);
@@ -498,6 +516,8 @@ int json_events(const char *fn,
                free(filter);
                free(perpkg);
                free(unit);
+               free(metric_expr);
+               free(metric_name);
                if (err)
                        break;
                tok += j;
index 71e13de31092f2de94827573f4e4dc537df8b726..611fac01913de14335924f1b7e02a86263fa377e 100644 (file)
@@ -5,7 +5,8 @@ int json_events(const char *fn,
                int (*func)(void *data, char *name, char *event, char *desc,
                                char *long_desc,
                                char *pmu,
-                               char *unit, char *perpkg),
+                               char *unit, char *perpkg, char *metric_expr,
+                               char *metric_name),
                void *data);
 char *get_cpu_str(void);
 
index c669a3cdb9f0279c96caa80cf68aab2862e202a9..569eab3688dd084236e6261d7511a31a40dc7117 100644 (file)
@@ -13,6 +13,8 @@ struct pmu_event {
        const char *pmu;
        const char *unit;
        const char *perpkg;
+       const char *metric_expr;
+       const char *metric_name;
 };
 
 /*
index 1cb3d9b540e9eda133f4548efc9316ad0d014898..af58ebc243ef635ff2ddc6efcd26b377cc24a30b 100644 (file)
@@ -38,6 +38,7 @@ perf-y += cpumap.o
 perf-y += stat.o
 perf-y += event_update.o
 perf-y += event-times.o
+perf-y += expr.o
 perf-y += backward-ring-buffer.o
 perf-y += sdt.o
 perf-y += is_printable_array.o
index 88dc51f4c27b2df8c5d8dc482a189b9831cb2832..0dd77494bb58e62620b0ad21843c95add77e5bfa 100644 (file)
  * permissions. All the event text files are stored there.
  */
 
+#include <errno.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "../perf.h"
 #include "util.h"
 #include <subcmd/exec-cmd.h>
index 42e892b1e97981a19511d026f977c45feff0497b..50f6d7afee586320b7193b88dea7f521c28aa5f6 100644 (file)
@@ -8,6 +8,7 @@
 #include <sys/prctl.h>
 #include "tests.h"
 #include "debug.h"
+#include <errno.h>
 
 #define NR_ITERS 111
 
index 1a04fe77487dc54512b3764f8a89961364c9ad45..5876da126b584febb15b128fb28baac1b30baac9 100644 (file)
@@ -1,10 +1,14 @@
+#include <errno.h>
 #include <stdio.h>
 #include <sys/epoll.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <util/util.h>
 #include <util/bpf-loader.h>
 #include <util/evlist.h>
 #include <linux/bpf.h>
 #include <linux/filter.h>
+#include <linux/kernel.h>
 #include <api/fs/fs.h>
 #include <bpf/bpf.h>
 #include "tests.h"
index 83c4669cbc5b9e30576321026dd38d68aa117fde..9e08d297f1a905f57554bf6fd7b9555e980ad10a 100644 (file)
@@ -3,8 +3,10 @@
  *
  * Builtin regression testing command: ever growing number of sanity tests
  */
+#include <errno.h>
 #include <unistd.h>
 #include <string.h>
+#include <sys/wait.h>
 #include "builtin.h"
 #include "hist.h"
 #include "intlist.h"
@@ -13,6 +15,7 @@
 #include "color.h"
 #include <subcmd/parse-options.h>
 #include "symbol.h"
+#include <linux/kernel.h>
 
 static bool dont_fork;
 
@@ -43,6 +46,10 @@ static struct test generic_tests[] = {
                .desc = "Parse event definition strings",
                .func = test__parse_events,
        },
+       {
+               .desc = "Simple expression parser",
+               .func = test__expr,
+       },
        {
                .desc = "PERF_RECORD_* events & perf_sample fields",
                .func = test__PERF_RECORD,
@@ -460,7 +467,7 @@ static int perf_test__list(int argc, const char **argv)
        return 0;
 }
 
-int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
+int cmd_test(int argc, const char **argv)
 {
        const char *test_usage[] = {
        "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
index f853e242a86c014ecfb80da3a6fa30f64295c963..c5bb2203f5a90850564397998a8af4b8cb3bfbc1 100644 (file)
@@ -2,6 +2,7 @@
 #include "debug.h"
 #include "util.h"
 #include "c++/clang-c.h"
+#include <linux/kernel.h>
 
 static struct {
        int (*func)(void);
index d1f693041324a8a6670ff56081537c3ed3f528f0..1f14e7612cbb1615e993c73758a3c9ac7024a0e1 100644 (file)
@@ -1,9 +1,12 @@
+#include <errno.h>
+#include <linux/kernel.h>
 #include <linux/types.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
-#include <ctype.h>
 #include <string.h>
+#include <sys/param.h>
 
 #include "parse-events.h"
 #include "evlist.h"
@@ -16,6 +19,8 @@
 
 #include "tests.h"
 
+#include "sane_ctype.h"
+
 #define BUFSZ  1024
 #define READLEN        128
 
index f168a85992d0ca3fec6c5abe4f2fd0efc3917224..4478773cdb9751b4f1f5a89f97c1808ad81d1bae 100644 (file)
@@ -66,7 +66,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
        TEST_ASSERT_VAL("wrong nr",  map->nr == 2);
        TEST_ASSERT_VAL("wrong cpu", map->map[0] == 1);
        TEST_ASSERT_VAL("wrong cpu", map->map[1] == 256);
-       TEST_ASSERT_VAL("wrong refcnt", atomic_read(&map->refcnt) == 1);
+       TEST_ASSERT_VAL("wrong refcnt", refcount_read(&map->refcnt) == 1);
        cpu_map__put(map);
        return 0;
 }
index 13725e09ba22447ed97b498e6751a34c2a027cbf..8f08df5861cb36c7b3415dd706e63cff8ad1aa46 100644 (file)
@@ -1,4 +1,6 @@
+#include <dirent.h>
 #include <stdlib.h>
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
index 1046491de4b295830f0a3ecea7616e018859d1aa..dfe5c89e2049f03fdb1305f8161928fa9f71f37e 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <inttypes.h>
 #include <unistd.h>
 #include "tests.h"
 #include "debug.h"
index 19ef77bd6eb4152b539dc46638d4ef3a8db972e3..634f20c631d8f9981dc89499998e3315d7661243 100644 (file)
@@ -1,5 +1,8 @@
 #include <linux/compiler.h>
+#include <errno.h>
+#include <inttypes.h>
 #include <string.h>
+#include <sys/wait.h>
 #include "tests.h"
 #include "evlist.h"
 #include "evsel.h"
index 60926a1f6fd7fcf128924759545d7f6620128406..d2bea6f780f8a1184c67c92d96727c7ddc715046 100644 (file)
@@ -3,6 +3,8 @@
 #include "parse-events.h"
 #include "tests.h"
 #include "debug.h"
+#include <errno.h>
+#include <linux/kernel.h>
 
 static int perf_evsel__roundtrip_cache_name_test(void)
 {
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
new file mode 100644 (file)
index 0000000..6c6a374
--- /dev/null
@@ -0,0 +1,56 @@
+#include "util/debug.h"
+#include "util/expr.h"
+#include "tests.h"
+#include <stdlib.h>
+
+static int test(struct parse_ctx *ctx, const char *e, double val2)
+{
+       double val;
+
+       if (expr__parse(&val, ctx, &e))
+               TEST_ASSERT_VAL("parse test failed", 0);
+       TEST_ASSERT_VAL("unexpected value", val == val2);
+       return 0;
+}
+
+int test__expr(int subtest __maybe_unused)
+{
+       const char *p;
+       const char **other;
+       double val;
+       int ret;
+       struct parse_ctx ctx;
+       int num_other;
+
+       expr__ctx_init(&ctx);
+       expr__add_id(&ctx, "FOO", 1);
+       expr__add_id(&ctx, "BAR", 2);
+
+       ret = test(&ctx, "1+1", 2);
+       ret |= test(&ctx, "FOO+BAR", 3);
+       ret |= test(&ctx, "(BAR/2)%2", 1);
+       ret |= test(&ctx, "1 - -4",  5);
+       ret |= test(&ctx, "(FOO-1)*2 + (BAR/2)%2 - -4",  5);
+
+       if (ret)
+               return ret;
+
+       p = "FOO/0";
+       ret = expr__parse(&val, &ctx, &p);
+       TEST_ASSERT_VAL("division by zero", ret == 1);
+
+       p = "BAR/";
+       ret = expr__parse(&val, &ctx, &p);
+       TEST_ASSERT_VAL("missing operand", ret == 1);
+
+       TEST_ASSERT_VAL("find other",
+                       expr__find_other("FOO + BAR + BAZ + BOZO", "FOO", &other, &num_other) == 0);
+       TEST_ASSERT_VAL("find other", num_other == 3);
+       TEST_ASSERT_VAL("find other", !strcmp(other[0], "BAR"));
+       TEST_ASSERT_VAL("find other", !strcmp(other[1], "BAZ"));
+       TEST_ASSERT_VAL("find other", !strcmp(other[2], "BOZO"));
+       TEST_ASSERT_VAL("find other", other[3] == NULL);
+       free((void *)other);
+
+       return 0;
+}
index 6b21746d6eec84b0bf443fc4cd05523be57f9878..00b8dc50f3dba8ffa1cbcc75938d15718741d75b 100644 (file)
@@ -1,3 +1,4 @@
+#include <inttypes.h>
 #include "perf.h"
 #include "util/debug.h"
 #include "util/symbol.h"
@@ -7,6 +8,7 @@
 #include "util/machine.h"
 #include "util/thread.h"
 #include "tests/hists_common.h"
+#include <linux/kernel.h>
 
 static struct {
        u32 pid;
index 9fd54b79a7886266889f17f5865d69b46171cbf3..d549a9f2c41b30f4d35eae742dbdfcb584ee804d 100644 (file)
@@ -1,5 +1,6 @@
 #include "perf.h"
 #include "util/debug.h"
+#include "util/event.h"
 #include "util/symbol.h"
 #include "util/sort.h"
 #include "util/evsel.h"
@@ -9,6 +10,7 @@
 #include "util/parse-events.h"
 #include "tests/tests.h"
 #include "tests/hists_common.h"
+#include <linux/kernel.h>
 
 struct sample {
        u32 pid;
index 62efb14f3a5a7eabb0dfbc7bae31e90276ef9c54..df9c91f49af19927ad48bc9c103aaf8bd43e0c40 100644 (file)
@@ -3,12 +3,14 @@
 #include "util/symbol.h"
 #include "util/sort.h"
 #include "util/evsel.h"
+#include "util/event.h"
 #include "util/evlist.h"
 #include "util/machine.h"
 #include "util/thread.h"
 #include "util/parse-events.h"
 #include "tests/tests.h"
 #include "tests/hists_common.h"
+#include <linux/kernel.h>
 
 struct sample {
        u32 pid;
index eddc7407ff8a9341a2e19e859bf1cab8781e8eda..a26cbb79e988832af5eeddd4b9970ba37326a248 100644 (file)
@@ -9,6 +9,8 @@
 #include "thread.h"
 #include "parse-events.h"
 #include "hists_common.h"
+#include <errno.h>
+#include <linux/kernel.h>
 
 struct sample {
        u32 pid;
index 63c5efaba1b5c611d3bb96da433d93415b3b87ca..06e5080182d31e879b25d2cabfc43c7a9a552097 100644 (file)
@@ -1,5 +1,6 @@
 #include "perf.h"
 #include "util/debug.h"
+#include "util/event.h"
 #include "util/symbol.h"
 #include "util/sort.h"
 #include "util/evsel.h"
@@ -9,6 +10,7 @@
 #include "util/parse-events.h"
 #include "tests/tests.h"
 #include "tests/hists_common.h"
+#include <linux/kernel.h>
 
 struct sample {
        u32 cpu;
index 42e13393e5028c2d1bfe515b990b0e79275e96c3..a5192f6a20d798990958adcfea8da970416183cd 100644 (file)
@@ -1,7 +1,8 @@
 #include <linux/compiler.h>
+#include <linux/kernel.h>
 #include "tests.h"
 #include "debug.h"
-#include "util.h"
+#include "print_binary.h"
 
 int test__is_printable_array(int subtest __maybe_unused)
 {
index 634bce9caebd343278e24f6c32ab3569f9bc003d..15c770856aacc6363c5b2618e51bb1356debbde1 100644 (file)
@@ -1,3 +1,5 @@
+#include <errno.h>
+#include <inttypes.h>
 /* For the CLR_() macros */
 #include <pthread.h>
 
@@ -7,6 +9,7 @@
 #include "cpumap.h"
 #include "tests.h"
 #include <linux/err.h>
+#include <linux/kernel.h>
 
 /*
  * This test will generate random numbers of calls to some getpid syscalls,
index 0c5ce44f723fcbfd9c43b6c15377c27d2d503038..6ea4d8a5d26b15ff4b3e0a228c51850260263d13 100644 (file)
@@ -1,3 +1,4 @@
+#include <inttypes.h>
 #include <unistd.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
@@ -11,6 +12,7 @@
 #include "thread_map.h"
 #include "symbol.h"
 #include "thread.h"
+#include "util.h"
 
 #define THREADS 4
 
index c8d9592eb142dd08ef4cf216dd67e6e6614996b7..1a74dd9fd06792001f111d3ca4b42ce484319704 100644 (file)
@@ -1,8 +1,14 @@
+#include <errno.h>
+#include <inttypes.h>
 /* For the CPU_* macros */
 #include <pthread.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <api/fs/fs.h>
 #include <linux/err.h>
+#include <api/fs/tracing_path.h>
 #include "evsel.h"
 #include "tests.h"
 #include "thread_map.h"
index f52239fed361913a219dd563f17ef7b5103fb238..9788fac910950d63244f83d417a1e421edd98ee4 100644 (file)
@@ -5,6 +5,7 @@
 #include "thread_map.h"
 #include "tests.h"
 #include "debug.h"
+#include <errno.h>
 
 #ifndef O_DIRECTORY
 #define O_DIRECTORY    00200000
index d7414128d7fe40d150dcb2424082dd858f6779d1..e44506e21ee779e33f4d8ffa7e6e6b4ebe40cc36 100644 (file)
@@ -1,5 +1,10 @@
+#include <errno.h>
+#include <inttypes.h>
 #include <api/fs/tracing_path.h>
 #include <linux/err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include "thread_map.h"
 #include "evsel.h"
 #include "debug.h"
index 1dc8380144220bd2c37f5c6338ad9a38e1c641bf..7fad885491c5710acb1e1d82e290d5a34639f88e 100644 (file)
@@ -1,4 +1,3 @@
-
 #include "parse-events.h"
 #include "evsel.h"
 #include "evlist.h"
@@ -6,8 +5,15 @@
 #include "tests.h"
 #include "debug.h"
 #include "util.h"
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <linux/kernel.h>
 #include <linux/hw_breakpoint.h>
 #include <api/fs/fs.h>
+#include <api/fs/tracing_path.h>
 
 #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
                             PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
index 65dcf48a92fbc2bbc7e89fc8a5243c1bcec3eead..c6207db09f12850f02123525a07c0c025e08a55d 100644 (file)
@@ -1,3 +1,4 @@
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <stddef.h>
 
index 87893f3ba5f1766cffa093ce44db50de45526279..d37cd9588cc0357577a513bca0afe9e600b0c58f 100644 (file)
@@ -1,3 +1,5 @@
+#include <errno.h>
+#include <inttypes.h>
 /* For the CLR_() macros */
 #include <pthread.h>
 
index 1e2ba26029301ffd85e1a1803eea8b8f40f134e6..a6d7aef3003056446f0b4507409d6672a63c986a 100644 (file)
@@ -2,6 +2,8 @@
 #include "pmu.h"
 #include "util.h"
 #include "tests.h"
+#include <errno.h>
+#include <linux/kernel.h>
 
 /* Simulated format definitions. */
 static struct test_format {
index 5f23710b9fee62855de88f11f39e6054d12c9a27..bac5c3885b3be58180eb4fc258c72b9b0c8241be 100644 (file)
@@ -1,4 +1,6 @@
 #include <stdbool.h>
+#include <inttypes.h>
+#include <linux/kernel.h>
 #include <linux/types.h>
 
 #include "util.h"
index f59d210e1bafbe21f5689587b718a8fb04f252cc..06eda675ae2c1ee3a59758c00285dc1a1f793230 100644 (file)
@@ -1,6 +1,6 @@
+#include <errno.h>
 #include <stdio.h>
 #include <sys/epoll.h>
-#include <util/util.h>
 #include <util/evlist.h>
 #include <linux/filter.h>
 #include "tests.h"
@@ -43,7 +43,7 @@ static char *get_self_path(void)
 {
        char *buf = calloc(PATH_MAX, sizeof(char));
 
-       if (buf && readlink("/proc/self/exe", buf, PATH_MAX) < 0) {
+       if (buf && readlink("/proc/self/exe", buf, PATH_MAX - 1) < 0) {
                pr_debug("Failed to get correct path of perf\n");
                free(buf);
                return NULL;
index 4c9fd046d57b1772422747fbf7deea8be036d68f..828494db4a190945dd3da7aa0d3ae3a987a52d36 100644 (file)
@@ -1,3 +1,5 @@
+#include <errno.h>
+#include <inttypes.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <signal.h>
index 7ddbe267d0acbae827010e6408bde3faf575003e..65474fd80da7216df44bc2e221660b89f4b3a02d 100644 (file)
@@ -1,5 +1,6 @@
 #include <sys/time.h>
 #include <sys/prctl.h>
+#include <errno.h>
 #include <time.h>
 #include <stdlib.h>
 
index 01a5ba2788c604c8c6b6c6e9f0a0364444f90da0..32873ec91a4e1307b30884c1141fe0e8f1da154e 100644 (file)
@@ -4,6 +4,7 @@
 #include "cpumap.h"
 #include "tests.h"
 
+#include <errno.h>
 #include <signal.h>
 
 static int exited;
index 1fa9b9d83aa51ba80beb9df29b48ee58be7f4619..6318596294032602b2858acf42c2aa80993fdac9 100644 (file)
@@ -62,6 +62,7 @@ int test__sample_parsing(int subtest);
 int test__keep_tracking(int subtest);
 int test__parse_no_sample_id_all(int subtest);
 int test__dwarf_unwind(int subtest);
+int test__expr(int subtest);
 int test__hists_filter(int subtest);
 int test__mmap_thread_lookup(int subtest);
 int test__thread_mg_share(int subtest);
index f2d2e542d0ee77a8abf7bfc6074f0934da85b5c4..a63d6945807b3a0e7fe9247475068e258dbd9cdc 100644 (file)
@@ -29,7 +29,7 @@ int test__thread_map(int subtest __maybe_unused)
                        thread_map__comm(map, 0) &&
                        !strcmp(thread_map__comm(map, 0), NAME));
        TEST_ASSERT_VAL("wrong refcnt",
-                       atomic_read(&map->refcnt) == 1);
+                       refcount_read(&map->refcnt) == 1);
        thread_map__put(map);
 
        /* test dummy pid */
@@ -44,7 +44,7 @@ int test__thread_map(int subtest __maybe_unused)
                        thread_map__comm(map, 0) &&
                        !strcmp(thread_map__comm(map, 0), "dummy"));
        TEST_ASSERT_VAL("wrong refcnt",
-                       atomic_read(&map->refcnt) == 1);
+                       refcount_read(&map->refcnt) == 1);
        thread_map__put(map);
        return 0;
 }
@@ -71,7 +71,7 @@ static int process_event(struct perf_tool *tool __maybe_unused,
                        thread_map__comm(threads, 0) &&
                        !strcmp(thread_map__comm(threads, 0), NAME));
        TEST_ASSERT_VAL("wrong refcnt",
-                       atomic_read(&threads->refcnt) == 1);
+                       refcount_read(&threads->refcnt) == 1);
        thread_map__put(threads);
        return 0;
 }
index 188b63140fc841f8c3111d20439b78d7f73133db..76686dd6f5ecfd235705bca7b39d7abdc237a150 100644 (file)
@@ -43,7 +43,7 @@ int test__thread_mg_share(int subtest __maybe_unused)
                        leader && t1 && t2 && t3 && other);
 
        mg = leader->mg;
-       TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 4);
+       TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&mg->refcnt), 4);
 
        /* test the map groups pointer is shared */
        TEST_ASSERT_VAL("map groups don't match", mg == t1->mg);
@@ -71,25 +71,25 @@ int test__thread_mg_share(int subtest __maybe_unused)
        machine__remove_thread(machine, other_leader);
 
        other_mg = other->mg;
-       TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&other_mg->refcnt), 2);
+       TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&other_mg->refcnt), 2);
 
        TEST_ASSERT_VAL("map groups don't match", other_mg == other_leader->mg);
 
        /* release thread group */
        thread__put(leader);
-       TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 3);
+       TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&mg->refcnt), 3);
 
        thread__put(t1);
-       TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 2);
+       TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&mg->refcnt), 2);
 
        thread__put(t2);
-       TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&mg->refcnt), 1);
+       TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&mg->refcnt), 1);
 
        thread__put(t3);
 
        /* release other group  */
        thread__put(other_leader);
-       TEST_ASSERT_EQUAL("wrong refcnt", atomic_read(&other_mg->refcnt), 1);
+       TEST_ASSERT_EQUAL("wrong refcnt", refcount_read(&other_mg->refcnt), 1);
 
        thread__put(other);
 
index 623c2aa53c4aa37e109a595ed31d799bc2205564..44589de084b824319063df71ce0543f7f054088b 100644 (file)
@@ -1,7 +1,8 @@
+#include <inttypes.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include "tests.h"
-#include "util.h"
+#include "units.h"
 #include "debug.h"
 
 int test__unit_number__scnprint(int subtest __maybe_unused)
index 862b043e59243588671c75298b337d8cd4e29c3b..8456175fc23458091aaf787a465d3a7123fd5f71 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/compiler.h>
 #include <linux/rbtree.h>
+#include <inttypes.h>
 #include <string.h>
 #include "map.h"
 #include "symbol.h"
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build
new file mode 100644 (file)
index 0000000..be95ac6
--- /dev/null
@@ -0,0 +1 @@
+libperf-y += statx.o
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h
new file mode 100644 (file)
index 0000000..cf50be3
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _PERF_TRACE_BEAUTY_H
+#define _PERF_TRACE_BEAUTY_H
+
+#include <linux/types.h>
+
+struct trace;
+struct thread;
+
+struct syscall_arg {
+       unsigned long val;
+       struct thread *thread;
+       struct trace  *trace;
+       void          *parm;
+       u8            idx;
+       u8            mask;
+};
+
+size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags
+
+size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg);
+#define SCA_STATX_MASK syscall_arg__scnprintf_statx_mask
+
+#endif /* _PERF_TRACE_BEAUTY_H */
index d3b0b1fab077a79f0e0db4f2880bff109ab775eb..fde8f2fc65589d54a457cabc8604b7389c5a985b 100644 (file)
@@ -1,3 +1,4 @@
+#include <signal.h>
 
 static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
 {
diff --git a/tools/perf/trace/beauty/statx.c b/tools/perf/trace/beauty/statx.c
new file mode 100644 (file)
index 0000000..5643b69
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * trace/beauty/statx.c
+ *
+ *  Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "trace/beauty/beauty.h"
+#include <linux/kernel.h>
+#include <sys/types.h>
+#include <uapi/linux/fcntl.h>
+#include <uapi/linux/stat.h>
+
+size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg)
+{
+       int printed = 0, flags = arg->val;
+
+       if (flags == 0)
+               return scnprintf(bf, size, "SYNC_AS_STAT");
+#define        P_FLAG(n) \
+       if (flags & AT_##n) { \
+               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+               flags &= ~AT_##n; \
+       }
+
+       P_FLAG(SYMLINK_NOFOLLOW);
+       P_FLAG(REMOVEDIR);
+       P_FLAG(SYMLINK_FOLLOW);
+       P_FLAG(NO_AUTOMOUNT);
+       P_FLAG(EMPTY_PATH);
+       P_FLAG(STATX_FORCE_SYNC);
+       P_FLAG(STATX_DONT_SYNC);
+
+#undef P_FLAG
+
+       if (flags)
+               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+       return printed;
+}
+
+size_t syscall_arg__scnprintf_statx_mask(char *bf, size_t size, struct syscall_arg *arg)
+{
+       int printed = 0, flags = arg->val;
+
+#define        P_FLAG(n) \
+       if (flags & STATX_##n) { \
+               printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
+               flags &= ~STATX_##n; \
+       }
+
+       P_FLAG(TYPE);
+       P_FLAG(MODE);
+       P_FLAG(NLINK);
+       P_FLAG(UID);
+       P_FLAG(GID);
+       P_FLAG(ATIME);
+       P_FLAG(MTIME);
+       P_FLAG(CTIME);
+       P_FLAG(INO);
+       P_FLAG(SIZE);
+       P_FLAG(BLOCKS);
+       P_FLAG(BTIME);
+
+#undef P_FLAG
+
+       if (flags)
+               printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
+
+       return printed;
+}
index 3eb3edb307a4814d1d11346f94117d3c006e87b7..a4d3762cd8250c0e799978d0454d52a04073b8f1 100644 (file)
@@ -1,4 +1,5 @@
 #include "../util.h"
+#include "../string2.h"
 #include "../config.h"
 #include "../../perf.h"
 #include "libslang.h"
@@ -13,6 +14,7 @@
 #include "helpline.h"
 #include "keysyms.h"
 #include "../color.h"
+#include "sane_ctype.h"
 
 static int ui_browser__percent_color(struct ui_browser *browser,
                                     double percent, bool current)
@@ -579,7 +581,7 @@ static int ui_browser__color_config(const char *var, const char *value,
                        break;
 
                *bg = '\0';
-               while (isspace(*++bg));
+               bg = ltrim(++bg);
                ui_browser__colorsets[i].bg = bg;
                ui_browser__colorsets[i].fg = fg;
                return 0;
index ba36aac340bc7d6531eaeaace7ee40ee38851806..d990ad08a3c69f79fdffbb3e9405e8a1d109827d 100644 (file)
@@ -9,7 +9,10 @@
 #include "../../util/symbol.h"
 #include "../../util/evsel.h"
 #include "../../util/config.h"
+#include <inttypes.h>
 #include <pthread.h>
+#include <linux/kernel.h>
+#include <sys/ttydefaults.h>
 
 struct disasm_line_samples {
        double          percent;
index edbeaaf31acea117e2d94fd7c3d11f17ae4dbfaa..e2c9390ff4c5244d8b0640844cc5c8bd957c963e 100644 (file)
@@ -8,6 +8,8 @@
 #include "util/header.h"
 #include "util/session.h"
 
+#include <sys/ttydefaults.h>
+
 static void ui_browser__argv_write(struct ui_browser *browser,
                                   void *entry, int row)
 {
index fc4fb669ceee37404bdda0e2ba0652f4304c28f8..69f4570bd4f941bee8a67fc48741994ce41a127e 100644 (file)
@@ -1,7 +1,11 @@
+#include <dirent.h>
+#include <errno.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <linux/rbtree.h>
+#include <sys/ttydefaults.h>
 
 #include "../../util/evsel.h"
 #include "../../util/evlist.h"
@@ -10,6 +14,7 @@
 #include "../../util/sort.h"
 #include "../../util/util.h"
 #include "../../util/top.h"
+#include "../../util/thread.h"
 #include "../../arch/common.h"
 
 #include "../browsers/hists.h"
 #include "../ui.h"
 #include "map.h"
 #include "annotate.h"
+#include "srcline.h"
+#include "string2.h"
+#include "units.h"
+
+#include "sane_ctype.h"
 
 extern void hist_browser__init_hpp(void);
 
@@ -144,9 +154,60 @@ static void callchain_list__set_folding(struct callchain_list *cl, bool unfold)
        cl->unfolded = unfold ? cl->has_children : false;
 }
 
+static struct inline_node *inline_node__create(struct map *map, u64 ip)
+{
+       struct dso *dso;
+       struct inline_node *node;
+
+       if (map == NULL)
+               return NULL;
+
+       dso = map->dso;
+       if (dso == NULL)
+               return NULL;
+
+       if (dso->kernel != DSO_TYPE_USER)
+               return NULL;
+
+       node = dso__parse_addr_inlines(dso,
+                                      map__rip_2objdump(map, ip));
+
+       return node;
+}
+
+static int inline__count_rows(struct inline_node *node)
+{
+       struct inline_list *ilist;
+       int i = 0;
+
+       if (node == NULL)
+               return 0;
+
+       list_for_each_entry(ilist, &node->val, list) {
+               if ((ilist->filename != NULL) || (ilist->funcname != NULL))
+                       i++;
+       }
+
+       return i;
+}
+
+static int callchain_list__inline_rows(struct callchain_list *chain)
+{
+       struct inline_node *node;
+       int rows;
+
+       node = inline_node__create(chain->ms.map, chain->ip);
+       if (node == NULL)
+               return 0;
+
+       rows = inline__count_rows(node);
+       inline_node__delete(node);
+       return rows;
+}
+
 static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
 {
-       int n = 0;
+       int n = 0, inline_rows;
        struct rb_node *nd;
 
        for (nd = rb_first(&node->rb_root); nd; nd = rb_next(nd)) {
@@ -156,6 +217,13 @@ static int callchain_node__count_rows_rb_tree(struct callchain_node *node)
 
                list_for_each_entry(chain, &child->val, list) {
                        ++n;
+
+                       if (symbol_conf.inline_name) {
+                               inline_rows =
+                                       callchain_list__inline_rows(chain);
+                               n += inline_rows;
+                       }
+
                        /* We need this because we may not have children */
                        folded_sign = callchain_list__folded(chain);
                        if (folded_sign == '+')
@@ -207,7 +275,7 @@ static int callchain_node__count_rows(struct callchain_node *node)
 {
        struct callchain_list *chain;
        bool unfolded = false;
-       int n = 0;
+       int n = 0, inline_rows;
 
        if (callchain_param.mode == CHAIN_FLAT)
                return callchain_node__count_flat_rows(node);
@@ -216,6 +284,11 @@ static int callchain_node__count_rows(struct callchain_node *node)
 
        list_for_each_entry(chain, &node->val, list) {
                ++n;
+               if (symbol_conf.inline_name) {
+                       inline_rows = callchain_list__inline_rows(chain);
+                       n += inline_rows;
+               }
+
                unfolded = chain->unfolded;
        }
 
@@ -362,6 +435,19 @@ static void hist_entry__init_have_children(struct hist_entry *he)
        he->init_have_children = true;
 }
 
+static void hist_entry_init_inline_node(struct hist_entry *he)
+{
+       if (he->inline_node)
+               return;
+
+       he->inline_node = inline_node__create(he->ms.map, he->ip);
+
+       if (he->inline_node == NULL)
+               return;
+
+       he->has_children = true;
+}
+
 static bool hist_browser__toggle_fold(struct hist_browser *browser)
 {
        struct hist_entry *he = browser->he_selection;
@@ -393,7 +479,12 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser)
 
                if (he->unfolded) {
                        if (he->leaf)
-                               he->nr_rows = callchain__count_rows(&he->sorted_chain);
+                               if (he->inline_node)
+                                       he->nr_rows = inline__count_rows(
+                                                       he->inline_node);
+                               else
+                                       he->nr_rows = callchain__count_rows(
+                                                       &he->sorted_chain);
                        else
                                he->nr_rows = hierarchy_count_rows(browser, he, false);
 
@@ -753,6 +844,71 @@ static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_u
 
 #define LEVEL_OFFSET_STEP 3
 
+static int hist_browser__show_inline(struct hist_browser *browser,
+                                    struct inline_node *node,
+                                    unsigned short row,
+                                    int offset)
+{
+       struct inline_list *ilist;
+       char buf[1024];
+       int color, width, first_row;
+
+       first_row = row;
+       width = browser->b.width - (LEVEL_OFFSET_STEP + 2);
+       list_for_each_entry(ilist, &node->val, list) {
+               if ((ilist->filename != NULL) || (ilist->funcname != NULL)) {
+                       color = HE_COLORSET_NORMAL;
+                       if (ui_browser__is_current_entry(&browser->b, row))
+                               color = HE_COLORSET_SELECTED;
+
+                       if (callchain_param.key == CCKEY_ADDRESS ||
+                           callchain_param.key == CCKEY_SRCLINE) {
+                               if (ilist->filename != NULL)
+                                       scnprintf(buf, sizeof(buf),
+                                                 "%s:%d (inline)",
+                                                 ilist->filename,
+                                                 ilist->line_nr);
+                               else
+                                       scnprintf(buf, sizeof(buf), "??");
+                       } else if (ilist->funcname != NULL)
+                               scnprintf(buf, sizeof(buf), "%s (inline)",
+                                         ilist->funcname);
+                       else if (ilist->filename != NULL)
+                               scnprintf(buf, sizeof(buf),
+                                         "%s:%d (inline)",
+                                         ilist->filename,
+                                         ilist->line_nr);
+                       else
+                               scnprintf(buf, sizeof(buf), "??");
+
+                       ui_browser__set_color(&browser->b, color);
+                       hist_browser__gotorc(browser, row, 0);
+                       ui_browser__write_nstring(&browser->b, " ",
+                               LEVEL_OFFSET_STEP + offset);
+                       ui_browser__write_nstring(&browser->b, buf, width);
+                       row++;
+               }
+       }
+
+       return row - first_row;
+}
+
+static size_t show_inline_list(struct hist_browser *browser, struct map *map,
+                              u64 ip, int row, int offset)
+{
+       struct inline_node *node;
+       int ret;
+
+       node = inline_node__create(map, ip);
+       if (node == NULL)
+               return 0;
+
+       ret = hist_browser__show_inline(browser, node, row, offset);
+
+       inline_node__delete(node);
+       return ret;
+}
+
 static int hist_browser__show_callchain_list(struct hist_browser *browser,
                                             struct callchain_node *node,
                                             struct callchain_list *chain,
@@ -764,6 +920,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
        char bf[1024], *alloc_str;
        char buf[64], *alloc_str2;
        const char *str;
+       int inline_rows = 0, ret = 1;
 
        if (arg->row_offset != 0) {
                arg->row_offset--;
@@ -801,10 +958,15 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser,
        }
 
        print(browser, chain, str, offset, row, arg);
-
        free(alloc_str);
        free(alloc_str2);
-       return 1;
+
+       if (symbol_conf.inline_name) {
+               inline_rows = show_inline_list(browser, chain->ms.map,
+                                              chain->ip, row + 1, offset);
+       }
+
+       return ret + inline_rows;
 }
 
 static bool check_percent_display(struct rb_node *node, u64 parent_total)
@@ -1228,6 +1390,12 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                folded_sign = hist_entry__folded(entry);
        }
 
+       if (symbol_conf.inline_name &&
+           (!entry->has_children)) {
+               hist_entry_init_inline_node(entry);
+               folded_sign = hist_entry__folded(entry);
+       }
+
        if (row_offset == 0) {
                struct hpp_arg arg = {
                        .b              = &browser->b,
@@ -1259,7 +1427,8 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                        }
 
                        if (first) {
-                               if (symbol_conf.use_callchain) {
+                               if (symbol_conf.use_callchain ||
+                                       symbol_conf.inline_name) {
                                        ui_browser__printf(&browser->b, "%c ", folded_sign);
                                        width -= 2;
                                }
@@ -1301,8 +1470,14 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                        .is_current_entry = current_entry,
                };
 
-               printed += hist_browser__show_callchain(browser, entry, 1, row,
-                                       hist_browser__show_callchain_entry, &arg,
+               if (entry->inline_node)
+                       printed += hist_browser__show_inline(browser,
+                                       entry->inline_node, row, 0);
+               else
+                       printed += hist_browser__show_callchain(browser,
+                                       entry, 1, row,
+                                       hist_browser__show_callchain_entry,
+                                       &arg,
                                        hist_browser__check_output_full);
        }
 
@@ -2308,7 +2483,7 @@ static int switch_data_file(void)
                return ret;
 
        memset(options, 0, sizeof(options));
-       memset(options, 0, sizeof(abs_path));
+       memset(abs_path, 0, sizeof(abs_path));
 
        while ((dent = readdir(pwd_dir))) {
                char path[PATH_MAX];
index 9ce142de536d0dcbb4017d2d80a40a9a668775c4..ffa5addf631d95fab3b1abcb8fcd6389aef45aba 100644 (file)
@@ -11,6 +11,8 @@
 #include "../keysyms.h"
 #include "map.h"
 
+#include "sane_ctype.h"
+
 struct map_browser {
        struct ui_browser b;
        struct map        *map;
index 8c9308ac30b7e77024170e441ef97be14ccb4865..e99ba86158d29b9ab637e66bac3182f7f429d88f 100644 (file)
@@ -3,7 +3,8 @@
 #include "util/annotate.h"
 #include "util/evsel.h"
 #include "ui/helpline.h"
-
+#include <inttypes.h>
+#include <signal.h>
 
 enum {
        ANN_COL__PERCENT,
index a4f02de7c1b54d426bb1b3f50b7fc2ba39ae5fa8..e24f83957705529bb1e62eda964840f4798fe430 100644 (file)
@@ -4,7 +4,9 @@
 #include "../sort.h"
 #include "../hist.h"
 #include "../helpline.h"
+#include "../string2.h"
 #include "gtk.h"
+#include <signal.h>
 
 #define MAX_COLUMNS                    32
 
index 5d632dca672aef2851778fb50be672e39c99bf50..59addd52d9cd51ab2d8789989a9d377d2ce23eb5 100644 (file)
@@ -1,3 +1,4 @@
+#include <inttypes.h>
 #include <math.h>
 #include <linux/compiler.h>
 
index 50d13e58210f0d7dc4b59421914317604757ac10..caf1ce6f51527ba5e542caacfb26d06c37829674 100644 (file)
@@ -4,12 +4,16 @@
 #include "../util/cache.h"
 #include "../util/debug.h"
 #include "../util/hist.h"
+#include "../util/util.h"
 
 pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
 void *perf_gtk_handle;
 int use_browser = -1;
 
+#define PERF_GTK_DSO "libperf-gtk.so"
+
 #ifdef HAVE_GTK2_SUPPORT
+
 static int setup_gtk_browser(void)
 {
        int (*perf_ui_init)(void);
index 668f4aecf2e6dfd933deb963d50362d09caa9fd9..42e432bd2eb4b59a1f15f6af69c788c66a62f1af 100644 (file)
@@ -4,7 +4,10 @@
 #include "../../util/hist.h"
 #include "../../util/sort.h"
 #include "../../util/evsel.h"
-
+#include "../../util/srcline.h"
+#include "../../util/string2.h"
+#include "../../util/thread.h"
+#include "../../util/sane_ctype.h"
 
 static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
 {
@@ -17,6 +20,67 @@ static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
        return ret;
 }
 
+static size_t inline__fprintf(struct map *map, u64 ip, int left_margin,
+                             int depth, int depth_mask, FILE *fp)
+{
+       struct dso *dso;
+       struct inline_node *node;
+       struct inline_list *ilist;
+       int ret = 0, i;
+
+       if (map == NULL)
+               return 0;
+
+       dso = map->dso;
+       if (dso == NULL)
+               return 0;
+
+       if (dso->kernel != DSO_TYPE_USER)
+               return 0;
+
+       node = dso__parse_addr_inlines(dso,
+                                      map__rip_2objdump(map, ip));
+       if (node == NULL)
+               return 0;
+
+       list_for_each_entry(ilist, &node->val, list) {
+               if ((ilist->filename != NULL) || (ilist->funcname != NULL)) {
+                       ret += callchain__fprintf_left_margin(fp, left_margin);
+
+                       for (i = 0; i < depth; i++) {
+                               if (depth_mask & (1 << i))
+                                       ret += fprintf(fp, "|");
+                               else
+                                       ret += fprintf(fp, " ");
+                               ret += fprintf(fp, "          ");
+                       }
+
+                       if (callchain_param.key == CCKEY_ADDRESS ||
+                           callchain_param.key == CCKEY_SRCLINE) {
+                               if (ilist->filename != NULL)
+                                       ret += fprintf(fp, "%s:%d (inline)",
+                                                      ilist->filename,
+                                                      ilist->line_nr);
+                               else
+                                       ret += fprintf(fp, "??");
+                       } else if (ilist->funcname != NULL)
+                               ret += fprintf(fp, "%s (inline)",
+                                              ilist->funcname);
+                       else if (ilist->filename != NULL)
+                               ret += fprintf(fp, "%s:%d (inline)",
+                                              ilist->filename,
+                                              ilist->line_nr);
+                       else
+                               ret += fprintf(fp, "??");
+
+                       ret += fprintf(fp, "\n");
+               }
+       }
+
+       inline_node__delete(node);
+       return ret;
+}
+
 static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
                                          int left_margin)
 {
@@ -78,6 +142,10 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_node *node,
        fputs(str, fp);
        fputc('\n', fp);
        free(alloc_str);
+
+       if (symbol_conf.inline_name)
+               ret += inline__fprintf(chain->ms.map, chain->ip,
+                                      left_margin, depth, depth_mask, fp);
        return ret;
 }
 
@@ -229,6 +297,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
                        if (!i++ && field_order == NULL &&
                            sort_order && !prefixcmp(sort_order, "sym"))
                                continue;
+
                        if (!printed) {
                                ret += callchain__fprintf_left_margin(fp, left_margin);
                                ret += fprintf(fp, "|\n");
@@ -251,6 +320,13 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
 
                        if (++entries_printed == callchain_param.print_limit)
                                break;
+
+                       if (symbol_conf.inline_name)
+                               ret += inline__fprintf(chain->ms.map,
+                                                      chain->ip,
+                                                      left_margin,
+                                                      0, 0,
+                                                      fp);
                }
                root = &cnode->rb_root;
        }
@@ -529,6 +605,8 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
                               bool use_callchain)
 {
        int ret;
+       int callchain_ret = 0;
+       int inline_ret = 0;
        struct perf_hpp hpp = {
                .buf            = bf,
                .size           = size,
@@ -547,7 +625,16 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
        ret = fprintf(fp, "%s\n", bf);
 
        if (use_callchain)
-               ret += hist_entry_callchain__fprintf(he, total_period, 0, fp);
+               callchain_ret = hist_entry_callchain__fprintf(he, total_period,
+                                                             0, fp);
+
+       if (callchain_ret == 0 && symbol_conf.inline_name) {
+               inline_ret = inline__fprintf(he->ms.map, he->ip, 0, 0, 0, fp);
+               ret += inline_ret;
+               if (inline_ret > 0)
+                       ret += fprintf(fp, "\n");
+       } else
+               ret += callchain_ret;
 
        return ret;
 }
index 4ea2ba861fc2fe6624fff3b67e2c0663015ff91d..d9350a1da48b46bbfaad0170e6ccb60a3f6f135b 100644 (file)
@@ -1,6 +1,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <stdbool.h>
+#include <linux/kernel.h>
 #ifdef HAVE_BACKTRACE_SUPPORT
 #include <execinfo.h>
 #endif
index 5da376bc1afca6733664f798e0e9d3050dab6e21..79dea95a7f688ca9fa9b16346b3fae25af797f5c 100644 (file)
@@ -1,4 +1,3 @@
-libperf-y += alias.o
 libperf-y += annotate.o
 libperf-y += block-range.o
 libperf-y += build-id.o
@@ -14,9 +13,11 @@ libperf-y += find_bit.o
 libperf-y += kallsyms.o
 libperf-y += levenshtein.o
 libperf-y += llvm-utils.o
+libperf-y += memswap.o
 libperf-y += parse-events.o
 libperf-y += perf_regs.o
 libperf-y += path.o
+libperf-y += print_binary.o
 libperf-y += rbtree.o
 libperf-y += libstring.o
 libperf-y += bitmap.o
@@ -42,6 +43,7 @@ libperf-y += pstack.o
 libperf-y += session.o
 libperf-$(CONFIG_AUDIT) += syscalltbl.o
 libperf-y += ordered-events.o
+libperf-y += namespaces.o
 libperf-y += comm.o
 libperf-y += thread.o
 libperf-y += thread_map.o
@@ -81,13 +83,16 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
 libperf-$(CONFIG_AUXTRACE) += intel-pt.o
 libperf-$(CONFIG_AUXTRACE) += intel-bts.o
 libperf-y += parse-branch-options.o
+libperf-y += dump-insn.o
 libperf-y += parse-regs-options.o
 libperf-y += term.o
 libperf-y += help-unknown-cmd.o
 libperf-y += mem-events.o
 libperf-y += vsprintf.o
 libperf-y += drv_configs.o
+libperf-y += units.o
 libperf-y += time-utils.o
+libperf-y += expr-bison.o
 
 libperf-$(CONFIG_LIBBPF) += bpf-loader.o
 libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -140,6 +145,10 @@ $(OUTPUT)util/parse-events-bison.c: util/parse-events.y
        $(call rule_mkdir)
        $(Q)$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_
 
+$(OUTPUT)util/expr-bison.c: util/expr.y
+       $(call rule_mkdir)
+       $(Q)$(call echo-cmd,bison)$(BISON) -v util/expr.y -d $(PARSER_DEBUG_BISON) -o $@ -p expr__
+
 $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
        $(call rule_mkdir)
        $(Q)$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
@@ -152,6 +161,7 @@ CFLAGS_parse-events-flex.o  += -w
 CFLAGS_pmu-flex.o           += -w
 CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -w
 CFLAGS_pmu-bison.o          += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
+CFLAGS_expr-bison.o         += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
 
 $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
 $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c
deleted file mode 100644 (file)
index 6455471..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "cache.h"
-#include "util.h"
-#include "config.h"
-
-static const char *alias_key;
-static char *alias_val;
-
-static int alias_lookup_cb(const char *k, const char *v,
-                          void *cb __maybe_unused)
-{
-       if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) {
-               if (!v)
-                       return config_error_nonbool(k);
-               alias_val = strdup(v);
-               return 0;
-       }
-       return 0;
-}
-
-char *alias_lookup(const char *alias)
-{
-       alias_key = alias;
-       alias_val = NULL;
-       perf_config(alias_lookup_cb, NULL);
-       return alias_val;
-}
-
-int split_cmdline(char *cmdline, const char ***argv)
-{
-       int src, dst, count = 0, size = 16;
-       char quoted = 0;
-
-       *argv = malloc(sizeof(char*) * size);
-
-       /* split alias_string */
-       (*argv)[count++] = cmdline;
-       for (src = dst = 0; cmdline[src];) {
-               char c = cmdline[src];
-               if (!quoted && isspace(c)) {
-                       cmdline[dst++] = 0;
-                       while (cmdline[++src]
-                                       && isspace(cmdline[src]))
-                               ; /* skip */
-                       if (count >= size) {
-                               size += 16;
-                               *argv = realloc(*argv, sizeof(char*) * size);
-                       }
-                       (*argv)[count++] = cmdline + dst;
-               } else if (!quoted && (c == '\'' || c == '"')) {
-                       quoted = c;
-                       src++;
-               } else if (c == quoted) {
-                       quoted = 0;
-                       src++;
-               } else {
-                       if (c == '\\' && quoted != '\'') {
-                               src++;
-                               c = cmdline[src];
-                               if (!c) {
-                                       zfree(argv);
-                                       return error("cmdline ends with \\");
-                               }
-                       }
-                       cmdline[dst++] = c;
-                       src++;
-               }
-       }
-
-       cmdline[dst] = 0;
-
-       if (quoted) {
-               zfree(argv);
-               return error("unclosed quote");
-       }
-
-       return count;
-}
-
index 7aa57225cbf7971b08db04c27151494c071b163b..683f8340460c1777f82f35860b3bb581a07f222a 100644 (file)
@@ -7,6 +7,8 @@
  * Released under the GPL v2. (and only v2, not any later version)
  */
 
+#include <errno.h>
+#include <inttypes.h>
 #include "util.h"
 #include "ui/ui.h"
 #include "sort.h"
 #include "annotate.h"
 #include "evsel.h"
 #include "block-range.h"
+#include "string2.h"
 #include "arch/common.h"
 #include <regex.h>
 #include <pthread.h>
 #include <linux/bitops.h>
+#include <linux/kernel.h>
 #include <sys/utsname.h>
 
+#include "sane_ctype.h"
+
 const char     *disassembler_style;
 const char     *objdump_path;
 static regex_t  file_lineno;
@@ -108,6 +114,7 @@ static int arch__associate_ins_ops(struct arch* arch, const char *name, struct i
 #include "arch/arm64/annotate/instructions.c"
 #include "arch/x86/annotate/instructions.c"
 #include "arch/powerpc/annotate/instructions.c"
+#include "arch/s390/annotate/instructions.c"
 
 static struct arch architectures[] = {
        {
@@ -132,6 +139,7 @@ static struct arch architectures[] = {
        },
        {
                .name = "s390",
+               .init = s390__annotate_init,
                .objdump =  {
                        .comment_char = '#',
                },
@@ -385,9 +393,7 @@ static int mov__parse(struct arch *arch, struct ins_operands *ops, struct map *m
        if (comment == NULL)
                return 0;
 
-       while (comment[0] != '\0' && isspace(comment[0]))
-               ++comment;
-
+       comment = ltrim(comment);
        comment__symbol(ops->source.raw, comment, &ops->source.addr, &ops->source.name);
        comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
 
@@ -432,9 +438,7 @@ static int dec__parse(struct arch *arch __maybe_unused, struct ins_operands *ops
        if (comment == NULL)
                return 0;
 
-       while (comment[0] != '\0' && isspace(comment[0]))
-               ++comment;
-
+       comment = ltrim(comment);
        comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
 
        return 0;
@@ -783,10 +787,7 @@ static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, str
 
 static int disasm_line__parse(char *line, const char **namep, char **rawp)
 {
-       char *name = line, tmp;
-
-       while (isspace(name[0]))
-               ++name;
+       char tmp, *name = ltrim(line);
 
        if (name[0] == '\0')
                return -1;
@@ -804,12 +805,7 @@ static int disasm_line__parse(char *line, const char **namep, char **rawp)
                goto out_free_name;
 
        (*rawp)[0] = tmp;
-
-       if ((*rawp)[0] != '\0') {
-               (*rawp)++;
-               while (isspace((*rawp)[0]))
-                       ++(*rawp);
-       }
+       *rawp = ltrim(*rawp);
 
        return 0;
 
@@ -1154,7 +1150,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
 {
        struct annotation *notes = symbol__annotation(sym);
        struct disasm_line *dl;
-       char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
+       char *line = NULL, *parsed_line, *tmp, *tmp2;
        size_t line_len;
        s64 line_ip, offset = -1;
        regmatch_t match[2];
@@ -1165,32 +1161,16 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
        if (!line)
                return -1;
 
-       while (line_len != 0 && isspace(line[line_len - 1]))
-               line[--line_len] = '\0';
-
-       c = strchr(line, '\n');
-       if (c)
-               *c = 0;
-
        line_ip = -1;
-       parsed_line = line;
+       parsed_line = rtrim(line);
 
        /* /filename:linenr ? Save line number and ignore. */
-       if (regexec(&file_lineno, line, 2, match, 0) == 0) {
-               *line_nr = atoi(line + match[1].rm_so);
+       if (regexec(&file_lineno, parsed_line, 2, match, 0) == 0) {
+               *line_nr = atoi(parsed_line + match[1].rm_so);
                return 0;
        }
 
-       /*
-        * Strip leading spaces:
-        */
-       tmp = line;
-       while (*tmp) {
-               if (*tmp != ' ')
-                       break;
-               tmp++;
-       }
-
+       tmp = ltrim(parsed_line);
        if (*tmp) {
                /*
                 * Parse hexa addresses followed by ':'
@@ -1313,6 +1293,7 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
 {
        char linkname[PATH_MAX];
        char *build_id_filename;
+       char *build_id_path = NULL;
 
        if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
            !dso__is_kcore(dso))
@@ -1328,8 +1309,14 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
                goto fallback;
        }
 
+       build_id_path = strdup(filename);
+       if (!build_id_path)
+               return -1;
+
+       dirname(build_id_path);
+
        if (dso__is_kcore(dso) ||
-           readlink(filename, linkname, sizeof(linkname)) < 0 ||
+           readlink(build_id_path, linkname, sizeof(linkname)) < 0 ||
            strstr(linkname, DSO__NAME_KALLSYMS) ||
            access(filename, R_OK)) {
 fallback:
@@ -1341,6 +1328,7 @@ fallback:
                __symbol__join_symfs(filename, filename_size, dso->long_name);
        }
 
+       free(build_id_path);
        return 0;
 }
 
@@ -1441,7 +1429,7 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
        snprintf(command, sizeof(command),
                 "%s %s%s --start-address=0x%016" PRIx64
                 " --stop-address=0x%016" PRIx64
-                " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
+                " -l -d %s %s -C %s 2>/dev/null|grep -v %s:|expand",
                 objdump_path ? objdump_path : "objdump",
                 disassembler_style ? "-M " : "",
                 disassembler_style ? disassembler_style : "",
@@ -1488,6 +1476,12 @@ int symbol__disassemble(struct symbol *sym, struct map *map, const char *arch_na
 
        nline = 0;
        while (!feof(file)) {
+               /*
+                * The source code line number (lineno) needs to be kept in
+                * accross calls to symbol__parse_objdump_line(), so that it
+                * can associate it with the instructions till the next one.
+                * See disasm_line__new() and struct disasm_line::line_nr.
+                */
                if (symbol__parse_objdump_line(sym, map, arch, file, privsize,
                            &lineno) < 0)
                        break;
@@ -1657,24 +1651,31 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
        start = map__rip_2objdump(map, sym->start);
 
        for (i = 0; i < len; i++) {
-               u64 offset;
+               u64 offset, nr_samples;
                double percent_max = 0.0;
 
                src_line->nr_pcnt = nr_pcnt;
 
                for (k = 0; k < nr_pcnt; k++) {
+                       double percent = 0.0;
+
                        h = annotation__histogram(notes, evidx + k);
-                       src_line->samples[k].percent = 100.0 * h->addr[i] / h->sum;
+                       nr_samples = h->addr[i];
+                       if (h->sum)
+                               percent = 100.0 * nr_samples / h->sum;
 
-                       if (src_line->samples[k].percent > percent_max)
-                               percent_max = src_line->samples[k].percent;
+                       if (percent > percent_max)
+                               percent_max = percent;
+                       src_line->samples[k].percent = percent;
+                       src_line->samples[k].nr = nr_samples;
                }
 
                if (percent_max <= 0.5)
                        goto next;
 
                offset = start + i;
-               src_line->path = get_srcline(map->dso, offset, NULL, false);
+               src_line->path = get_srcline(map->dso, offset, NULL,
+                                            false, true);
                insert_source_line(&tmp_root, src_line);
 
        next:
index 09776b5af991d3334fd35c1b9218999bdfda38da..948aa8e6fd394729bc67441823f64c17508756d6 100644 (file)
@@ -98,7 +98,7 @@ struct cyc_hist {
 struct source_line_samples {
        double          percent;
        double          percent_sum;
-       double          nr;
+       u64             nr;
 };
 
 struct source_line {
index c5a6e0b124529e876cf9b2844b485b7177e6e4a2..0daf63b9ee3e1482cdc5fc5e96a968c4117e3a0c 100644 (file)
  *
  */
 
+#include <inttypes.h>
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <stdbool.h>
-#include <ctype.h>
 #include <string.h>
 #include <limits.h>
 #include <errno.h>
@@ -46,7 +46,6 @@
 #include "cpumap.h"
 #include "thread_map.h"
 #include "asm/bug.h"
-#include "symbol/kallsyms.h"
 #include "auxtrace.h"
 
 #include <linux/hash.h>
@@ -59,6 +58,9 @@
 #include "intel-pt.h"
 #include "intel-bts.h"
 
+#include "sane_ctype.h"
+#include "symbol/kallsyms.h"
+
 int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
                        struct auxtrace_mmap_params *mp,
                        void *userpg, int fd)
@@ -1826,7 +1828,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
                filt->addr = start;
                if (filt->range && !filt->size && !filt->sym_to) {
                        filt->size = size;
-                       no_size = !!size;
+                       no_size = !size;
                }
        }
 
@@ -1840,7 +1842,7 @@ static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
                if (err)
                        return err;
                filt->size = start + size - filt->addr;
-               no_size = !!size;
+               no_size = !size;
        }
 
        /* The very last symbol in kallsyms does not imply a particular size */
index 26fb1ee5746aaf7fa15db352f848d13bdd299736..9f0de72d58e26f07c479e53965cc106c365b3b70 100644 (file)
@@ -17,6 +17,7 @@
 #define __PERF_AUXTRACE_H
 
 #include <sys/types.h>
+#include <errno.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <linux/list.h>
index bc6bc7062eb4ffed74457bff52a5ab5c2d885300..4bd2d1d882af1d6e9da7561e80d572a82258b5cd 100644 (file)
@@ -9,7 +9,9 @@
 #include <bpf/libbpf.h>
 #include <bpf/bpf.h>
 #include <linux/err.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
+#include <errno.h>
 #include "perf.h"
 #include "debug.h"
 #include "bpf-loader.h"
@@ -17,6 +19,7 @@
 #include "probe-event.h"
 #include "probe-finder.h" // for MAX_PROBES
 #include "parse-events.h"
+#include "strfilter.h"
 #include "llvm-utils.h"
 #include "c++/clang-c.h"
 
index f2b737b225f2e0233d9d73aa9944588bf1f4d64e..48863867878bc35413d6bf94e460da4e57976869 100644 (file)
@@ -85,6 +85,8 @@ int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err,
                               char *buf, size_t size);
 
 #else
+#include <errno.h>
+
 static inline struct bpf_object *
 bpf__prepare_load(const char *filename __maybe_unused,
                  bool source __maybe_unused)
index 6cdbee119ceb3fa8f550368f9b93cc5b31aacbb0..1356220a9f1b6eee97e56c51132f394922225d36 100644 (file)
@@ -12,6 +12,7 @@
 #include "bpf-loader.h"
 #include "bpf-prologue.h"
 #include "probe-finder.h"
+#include <errno.h>
 #include <dwarf-regs.h>
 #include <linux/filter.h>
 
index d94cbea128999aab4368404140b07a0755ba4439..ba564838375f7b50bfc8d057b7c69f42c7b0f5cb 100644 (file)
@@ -18,6 +18,8 @@ int bpf__gen_prologue(struct probe_trace_arg *args, int nargs,
                      struct bpf_insn *new_prog, size_t *new_cnt,
                      size_t cnt_space);
 #else
+#include <errno.h>
+
 static inline int
 bpf__gen_prologue(struct probe_trace_arg *args __maybe_unused,
                  int nargs __maybe_unused,
index e528c40739ccec0b60e392c5d815ccdbf79541db..168cc49654e7a4b18f69d177e29373f8a13e3471 100644 (file)
@@ -7,18 +7,26 @@
  * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
  */
 #include "util.h"
+#include <dirent.h>
+#include <errno.h>
 #include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include "build-id.h"
 #include "event.h"
 #include "symbol.h"
+#include "thread.h"
 #include <linux/kernel.h>
 #include "debug.h"
 #include "session.h"
 #include "tool.h"
 #include "header.h"
 #include "vdso.h"
+#include "path.h"
 #include "probe-file.h"
+#include "strlist.h"
 
+#include "sane_ctype.h"
 
 static bool no_buildid_cache;
 
@@ -182,13 +190,17 @@ char *build_id_cache__origname(const char *sbuild_id)
        char buf[PATH_MAX];
        char *ret = NULL, *p;
        size_t offs = 5;        /* == strlen("../..") */
+       ssize_t len;
 
        linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
        if (!linkname)
                return NULL;
 
-       if (readlink(linkname, buf, PATH_MAX) < 0)
+       len = readlink(linkname, buf, sizeof(buf) - 1);
+       if (len <= 0)
                goto out;
+       buf[len] = '\0';
+
        /* The link should be "../..<origpath>/<sbuild_id>" */
        p = strrchr(buf, '/');  /* Cut off the "/<sbuild_id>" */
        if (p && (p > buf + offs)) {
@@ -443,14 +455,14 @@ void disable_buildid_cache(void)
 }
 
 static bool lsdir_bid_head_filter(const char *name __maybe_unused,
-                                 struct dirent *d __maybe_unused)
+                                 struct dirent *d)
 {
        return (strlen(d->d_name) == 2) &&
                isxdigit(d->d_name[0]) && isxdigit(d->d_name[1]);
 }
 
 static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
-                                 struct dirent *d __maybe_unused)
+                                 struct dirent *d)
 {
        int i = 0;
        while (isxdigit(d->d_name[i]) && i < SBUILD_ID_SIZE - 3)
@@ -690,7 +702,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
                err = 0;
 
        /* Update SDT cache : error is just warned */
-       if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
+       if (realname && build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
                pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
 
 out_free:
index d27990610f9f4bfff8598bd71855f4b1f14f1a8c..8a89b195c1fc3a5c36d7ca260dafe9c6b3fa8262 100644 (file)
@@ -5,7 +5,6 @@
 #define SBUILD_ID_SIZE (BUILD_ID_SIZE * 2 + 1)
 
 #include "tool.h"
-#include "strlist.h"
 #include <linux/types.h>
 
 extern struct perf_tool build_id__mark_dso_hit_ops;
@@ -34,6 +33,9 @@ char *build_id_cache__origname(const char *sbuild_id);
 char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
 char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
                               bool is_kallsyms, bool is_vdso);
+
+struct strlist;
+
 struct strlist *build_id_cache__list_all(bool validonly);
 char *build_id_cache__complement(const char *incomplete_sbuild_id);
 int build_id_cache__list_build_ids(const char *pathname,
@@ -42,6 +44,10 @@ bool build_id_cache__cached(const char *sbuild_id);
 int build_id_cache__add_s(const char *sbuild_id,
                          const char *name, bool is_kallsyms, bool is_vdso);
 int build_id_cache__remove_s(const char *sbuild_id);
+
+extern char buildid_dir[];
+
+void set_buildid_dir(const char *dir);
 void disable_buildid_cache(void);
 
 #endif
index 0eadd792ab1f0b99a784d14eb71fae99a6f1214f..ccafcf72b37a84d02b6b5d93e50a58cecdebf7ed 100644 (file)
@@ -20,6 +20,7 @@ extern int perf_clang__compile_bpf(const char *filename,
                                   size_t *p_obj_buf_sz);
 #else
 
+#include <errno.h>
 
 static inline void perf_clang__init(void) { }
 static inline void perf_clang__cleanup(void) { }
index 512c0c83fbc6a9a9ed2a9c996de74ff6fb45eb62..0328f297a748380d7e128e69b204e42001c3e8c1 100644 (file)
@@ -15,7 +15,6 @@
 #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
 #define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
 
-char *alias_lookup(const char *alias);
 int split_cmdline(char *cmdline, const char ***argv);
 
 #define alloc_nr(x) (((x)+16)*3/2)
index aba953421a0329d0de0f2adc5ce1a4599d0fe320..81fc29ac798facf789712d81147eacda0c01552d 100644 (file)
@@ -9,6 +9,7 @@
  *
  */
 
+#include <inttypes.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include "machine.h"
 #include "callchain.h"
 
+#define CALLCHAIN_PARAM_DEFAULT                        \
+       .mode           = CHAIN_GRAPH_ABS,      \
+       .min_percent    = 0.5,                  \
+       .order          = ORDER_CALLEE,         \
+       .key            = CCKEY_FUNCTION,       \
+       .value          = CCVAL_PERCENT,        \
+
+struct callchain_param callchain_param = {
+       CALLCHAIN_PARAM_DEFAULT
+};
+
+struct callchain_param callchain_param_default = {
+       CALLCHAIN_PARAM_DEFAULT
+};
+
 __thread struct callchain_cursor callchain_cursor;
 
 int parse_callchain_record_opt(const char *arg, struct callchain_param *param)
@@ -80,6 +96,10 @@ static int parse_callchain_sort_key(const char *value)
                callchain_param.key = CCKEY_ADDRESS;
                return 0;
        }
+       if (!strncmp(value, "srcline", strlen(value))) {
+               callchain_param.key = CCKEY_SRCLINE;
+               return 0;
+       }
        if (!strncmp(value, "branch", strlen(value))) {
                callchain_param.branch_callstack = 1;
                return 0;
@@ -108,11 +128,37 @@ static int parse_callchain_value(const char *value)
        return -1;
 }
 
+static int get_stack_size(const char *str, unsigned long *_size)
+{
+       char *endptr;
+       unsigned long size;
+       unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
+
+       size = strtoul(str, &endptr, 0);
+
+       do {
+               if (*endptr)
+                       break;
+
+               size = round_up(size, sizeof(u64));
+               if (!size || size > max_size)
+                       break;
+
+               *_size = size;
+               return 0;
+
+       } while (0);
+
+       pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
+              max_size, str);
+       return -1;
+}
+
 static int
 __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
 {
        char *tok;
-       char *endptr;
+       char *endptr, *saveptr = NULL;
        bool minpcnt_set = false;
        bool record_opt_set = false;
        bool try_stack_size = false;
@@ -123,7 +169,7 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
        if (!arg)
                return 0;
 
-       while ((tok = strtok((char *)arg, ",")) != NULL) {
+       while ((tok = strtok_r((char *)arg, ",", &saveptr)) != NULL) {
                if (!strncmp(tok, "none", strlen(tok))) {
                        callchain_param.mode = CHAIN_NONE;
                        callchain_param.enabled = false;
@@ -191,6 +237,68 @@ int parse_callchain_top_opt(const char *arg)
        return __parse_callchain_report_opt(arg, true);
 }
 
+int parse_callchain_record(const char *arg, struct callchain_param *param)
+{
+       char *tok, *name, *saveptr = NULL;
+       char *buf;
+       int ret = -1;
+
+       /* We need buffer that we know we can write to. */
+       buf = malloc(strlen(arg) + 1);
+       if (!buf)
+               return -ENOMEM;
+
+       strcpy(buf, arg);
+
+       tok = strtok_r((char *)buf, ",", &saveptr);
+       name = tok ? : (char *)buf;
+
+       do {
+               /* Framepointer style */
+               if (!strncmp(name, "fp", sizeof("fp"))) {
+                       if (!strtok_r(NULL, ",", &saveptr)) {
+                               param->record_mode = CALLCHAIN_FP;
+                               ret = 0;
+                       } else
+                               pr_err("callchain: No more arguments "
+                                      "needed for --call-graph fp\n");
+                       break;
+
+               /* Dwarf style */
+               } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
+                       const unsigned long default_stack_dump_size = 8192;
+
+                       ret = 0;
+                       param->record_mode = CALLCHAIN_DWARF;
+                       param->dump_size = default_stack_dump_size;
+
+                       tok = strtok_r(NULL, ",", &saveptr);
+                       if (tok) {
+                               unsigned long size = 0;
+
+                               ret = get_stack_size(tok, &size);
+                               param->dump_size = size;
+                       }
+               } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
+                       if (!strtok_r(NULL, ",", &saveptr)) {
+                               param->record_mode = CALLCHAIN_LBR;
+                               ret = 0;
+                       } else
+                               pr_err("callchain: No more arguments "
+                                       "needed for --call-graph lbr\n");
+                       break;
+               } else {
+                       pr_err("callchain: Unknown --call-graph option "
+                              "value: %s\n", arg);
+                       break;
+               }
+
+       } while (0);
+
+       free(buf);
+       return ret;
+}
+
 int perf_callchain_config(const char *var, const char *value)
 {
        char *endptr;
@@ -510,14 +618,51 @@ enum match_result {
        MATCH_GT,
 };
 
+static enum match_result match_chain_srcline(struct callchain_cursor_node *node,
+                                            struct callchain_list *cnode)
+{
+       char *left = get_srcline(cnode->ms.map->dso,
+                                map__rip_2objdump(cnode->ms.map, cnode->ip),
+                                cnode->ms.sym, true, false);
+       char *right = get_srcline(node->map->dso,
+                                 map__rip_2objdump(node->map, node->ip),
+                                 node->sym, true, false);
+       enum match_result ret = MATCH_EQ;
+       int cmp;
+
+       if (left && right)
+               cmp = strcmp(left, right);
+       else if (!left && right)
+               cmp = 1;
+       else if (left && !right)
+               cmp = -1;
+       else if (cnode->ip == node->ip)
+               cmp = 0;
+       else
+               cmp = (cnode->ip < node->ip) ? -1 : 1;
+
+       if (cmp != 0)
+               ret = cmp < 0 ? MATCH_LT : MATCH_GT;
+
+       free_srcline(left);
+       free_srcline(right);
+       return ret;
+}
+
 static enum match_result match_chain(struct callchain_cursor_node *node,
                                     struct callchain_list *cnode)
 {
        struct symbol *sym = node->sym;
        u64 left, right;
 
-       if (cnode->ms.sym && sym &&
-           callchain_param.key == CCKEY_FUNCTION) {
+       if (callchain_param.key == CCKEY_SRCLINE) {
+               enum match_result match = match_chain_srcline(node, cnode);
+
+               if (match != MATCH_ERROR)
+                       return match;
+       }
+
+       if (cnode->ms.sym && sym && callchain_param.key == CCKEY_FUNCTION) {
                left = cnode->ms.sym->start;
                right = sym->start;
        } else {
@@ -911,15 +1056,16 @@ out:
 char *callchain_list__sym_name(struct callchain_list *cl,
                               char *bf, size_t bfsize, bool show_dso)
 {
+       bool show_addr = callchain_param.key == CCKEY_ADDRESS;
+       bool show_srcline = show_addr || callchain_param.key == CCKEY_SRCLINE;
        int printed;
 
        if (cl->ms.sym) {
-               if (callchain_param.key == CCKEY_ADDRESS &&
-                   cl->ms.map && !cl->srcline)
+               if (show_srcline && cl->ms.map && !cl->srcline)
                        cl->srcline = get_srcline(cl->ms.map->dso,
                                                  map__rip_2objdump(cl->ms.map,
                                                                    cl->ip),
-                                                 cl->ms.sym, false);
+                                                 cl->ms.sym, false, show_addr);
                if (cl->srcline)
                        printed = scnprintf(bf, bfsize, "%s %s",
                                        cl->ms.sym->name, cl->srcline);
@@ -1063,63 +1209,100 @@ int callchain_branch_counts(struct callchain_root *root,
                                                  cycles_count);
 }
 
-static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
-                                  u64 branch_count, u64 predicted_count,
-                                  u64 abort_count, u64 cycles_count,
-                                  u64 iter_count, u64 samples_count)
+static int counts_str_build(char *bf, int bfsize,
+                            u64 branch_count, u64 predicted_count,
+                            u64 abort_count, u64 cycles_count,
+                            u64 iter_count, u64 samples_count)
 {
        double predicted_percent = 0.0;
        const char *null_str = "";
        char iter_str[32];
-       char *str;
-       u64 cycles = 0;
-
-       if (branch_count == 0) {
-               if (fp)
-                       return fprintf(fp, " (calltrace)");
+       char cycle_str[32];
+       char *istr, *cstr;
+       u64 cycles;
 
+       if (branch_count == 0)
                return scnprintf(bf, bfsize, " (calltrace)");
-       }
+
+       cycles = cycles_count / branch_count;
 
        if (iter_count && samples_count) {
-               scnprintf(iter_str, sizeof(iter_str),
-                        ", iterations:%" PRId64 "",
-                        iter_count / samples_count);
-               str = iter_str;
+               if (cycles > 0)
+                       scnprintf(iter_str, sizeof(iter_str),
+                                " iterations:%" PRId64 "",
+                                iter_count / samples_count);
+               else
+                       scnprintf(iter_str, sizeof(iter_str),
+                                "iterations:%" PRId64 "",
+                                iter_count / samples_count);
+               istr = iter_str;
+       } else
+               istr = (char *)null_str;
+
+       if (cycles > 0) {
+               scnprintf(cycle_str, sizeof(cycle_str),
+                         "cycles:%" PRId64 "", cycles);
+               cstr = cycle_str;
        } else
-               str = (char *)null_str;
+               cstr = (char *)null_str;
 
        predicted_percent = predicted_count * 100.0 / branch_count;
-       cycles = cycles_count / branch_count;
 
-       if ((predicted_percent >= 100.0) && (abort_count == 0)) {
-               if (fp)
-                       return fprintf(fp, " (cycles:%" PRId64 "%s)",
-                                      cycles, str);
+       if ((predicted_count == branch_count) && (abort_count == 0)) {
+               if ((cycles > 0) || (istr != (char *)null_str))
+                       return scnprintf(bf, bfsize, " (%s%s)", cstr, istr);
+               else
+                       return scnprintf(bf, bfsize, "%s", (char *)null_str);
+       }
 
-               return scnprintf(bf, bfsize, " (cycles:%" PRId64 "%s)",
-                                cycles, str);
+       if ((predicted_count < branch_count) && (abort_count == 0)) {
+               if ((cycles > 0) || (istr != (char *)null_str))
+                       return scnprintf(bf, bfsize,
+                               " (predicted:%.1f%% %s%s)",
+                               predicted_percent, cstr, istr);
+               else {
+                       return scnprintf(bf, bfsize,
+                               " (predicted:%.1f%%)",
+                               predicted_percent);
+               }
        }
 
-       if ((predicted_percent < 100.0) && (abort_count == 0)) {
-               if (fp)
-                       return fprintf(fp,
-                               " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
-                               predicted_percent, cycles, str);
+       if ((predicted_count == branch_count) && (abort_count > 0)) {
+               if ((cycles > 0) || (istr != (char *)null_str))
+                       return scnprintf(bf, bfsize,
+                               " (abort:%" PRId64 " %s%s)",
+                               abort_count, cstr, istr);
+               else
+                       return scnprintf(bf, bfsize,
+                               " (abort:%" PRId64 ")",
+                               abort_count);
+       }
 
+       if ((cycles > 0) || (istr != (char *)null_str))
                return scnprintf(bf, bfsize,
-                       " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
-                       predicted_percent, cycles, str);
-       }
+                       " (predicted:%.1f%% abort:%" PRId64 " %s%s)",
+                       predicted_percent, abort_count, cstr, istr);
+
+       return scnprintf(bf, bfsize,
+                       " (predicted:%.1f%% abort:%" PRId64 ")",
+                       predicted_percent, abort_count);
+}
+
+static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
+                                  u64 branch_count, u64 predicted_count,
+                                  u64 abort_count, u64 cycles_count,
+                                  u64 iter_count, u64 samples_count)
+{
+       char str[128];
+
+       counts_str_build(str, sizeof(str), branch_count,
+                        predicted_count, abort_count, cycles_count,
+                        iter_count, samples_count);
 
        if (fp)
-               return fprintf(fp,
-               " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
-                       predicted_percent, abort_count, cycles, str);
+               return fprintf(fp, "%s", str);
 
-       return scnprintf(bf, bfsize,
-               " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
-               predicted_percent, abort_count, cycles, str);
+       return scnprintf(bf, bfsize, "%s", str);
 }
 
 int callchain_list_counts__printf_value(struct callchain_node *node,
index 4f4b60f1558a827cbe34d9d387e6a91a917b58dd..c56c23dbbf72838b8758ec703759a6ad09f229a6 100644 (file)
@@ -77,7 +77,8 @@ typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
 
 enum chain_key {
        CCKEY_FUNCTION,
-       CCKEY_ADDRESS
+       CCKEY_ADDRESS,
+       CCKEY_SRCLINE
 };
 
 enum chain_value {
index eafbf11442b224f90ad9c5d704df75d86985f917..03347748f3fadc43f070fa0b6ef789f071c30d65 100644 (file)
@@ -4,6 +4,7 @@
 #include "evsel.h"
 #include "cgroup.h"
 #include "evlist.h"
+#include <linux/stringify.h>
 
 int nr_cgroups;
 
@@ -27,8 +28,8 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
        path_v1[0] = '\0';
        path_v2[0] = '\0';
 
-       while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %"
-                               STR(PATH_MAX)"s %*d %*d\n",
+       while (fscanf(fp, "%*s %"__stringify(PATH_MAX)"s %"__stringify(PATH_MAX)"s %"
+                               __stringify(PATH_MAX)"s %*d %*d\n",
                                mountpoint, type, tokens) == 3) {
 
                if (!path_v1[0] && !strcmp(type, "cgroup")) {
@@ -127,19 +128,19 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
                        goto found;
                n++;
        }
-       if (atomic_read(&cgrp->refcnt) == 0)
+       if (refcount_read(&cgrp->refcnt) == 0)
                free(cgrp);
 
        return -1;
 found:
-       atomic_inc(&cgrp->refcnt);
+       refcount_inc(&cgrp->refcnt);
        counter->cgrp = cgrp;
        return 0;
 }
 
 void close_cgroup(struct cgroup_sel *cgrp)
 {
-       if (cgrp && atomic_dec_and_test(&cgrp->refcnt)) {
+       if (cgrp && refcount_dec_and_test(&cgrp->refcnt)) {
                close(cgrp->fd);
                zfree(&cgrp->name);
                free(cgrp);
index 31f8dcdbd7efefac48353b90715c027cf2c13386..d91966b97cbd7235f9fd756c50cd41ba7d7fadae 100644 (file)
@@ -1,14 +1,14 @@
 #ifndef __CGROUP_H__
 #define __CGROUP_H__
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 struct option;
 
 struct cgroup_sel {
        char *name;
        int fd;
-       atomic_t refcnt;
+       refcount_t refcnt;
 };
 
 
index f0dcd0ee0afaa0505470ca382a9d597a5e88fb3a..4b4f00df58a8253c46e3e912753f8d2d25c06044 100644 (file)
@@ -1,3 +1,4 @@
+#include <errno.h>
 #include <sched.h>
 #include "util.h"
 #include "../perf.h"
index d0d465953d36e16c07038ea69182e71c44db0558..94a5a7d829d5ba32efe646f9c04729ab363ac593 100644 (file)
@@ -3,10 +3,4 @@
 
 unsigned long perf_event_open_cloexec_flag(void);
 
-#ifdef __GLIBC_PREREQ
-#if !__GLIBC_PREREQ(2, 6) && !defined(__UCLIBC__)
-int sched_getcpu(void) __THROW;
-#endif
-#endif
-
 #endif /* __PERF_CLOEXEC_H */
index a93997f16dec3b2b9815e4bf298a0928a52f4a1a..52122bcc31701fef202cbdb95e5502841def750c 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __PERF_COLOR_H
 #define __PERF_COLOR_H
 
+#include <stdio.h>
+
 /* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
 #define COLOR_MAXLEN 24
 
index 21b7ff382c3f0dfb2e0bff43074adae3c0b10973..7bc981b6bf296ae000407a787bc30aaa22fa574b 100644 (file)
@@ -1,13 +1,15 @@
 #include "comm.h"
 #include "util.h"
+#include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <linux/atomic.h>
+#include <string.h>
+#include <linux/refcount.h>
 
 struct comm_str {
        char *str;
        struct rb_node rb_node;
-       atomic_t refcnt;
+       refcount_t refcnt;
 };
 
 /* Should perhaps be moved to struct machine */
@@ -16,13 +18,13 @@ static struct rb_root comm_str_root;
 static struct comm_str *comm_str__get(struct comm_str *cs)
 {
        if (cs)
-               atomic_inc(&cs->refcnt);
+               refcount_inc(&cs->refcnt);
        return cs;
 }
 
 static void comm_str__put(struct comm_str *cs)
 {
-       if (cs && atomic_dec_and_test(&cs->refcnt)) {
+       if (cs && refcount_dec_and_test(&cs->refcnt)) {
                rb_erase(&cs->rb_node, &comm_str_root);
                zfree(&cs->str);
                free(cs);
@@ -43,7 +45,7 @@ static struct comm_str *comm_str__alloc(const char *str)
                return NULL;
        }
 
-       atomic_set(&cs->refcnt, 0);
+       refcount_set(&cs->refcnt, 1);
 
        return cs;
 }
@@ -61,7 +63,7 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
 
                cmp = strcmp(str, iter->str);
                if (!cmp)
-                       return iter;
+                       return comm_str__get(iter);
 
                if (cmp < 0)
                        p = &(*p)->rb_left;
@@ -95,8 +97,6 @@ struct comm *comm__new(const char *str, u64 timestamp, bool exec)
                return NULL;
        }
 
-       comm_str__get(comm->comm_str);
-
        return comm;
 }
 
@@ -108,7 +108,6 @@ int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
        if (!new)
                return -ENOMEM;
 
-       comm_str__get(new);
        comm_str__put(old);
        comm->comm_str = new;
        comm->start = timestamp;
diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h
new file mode 100644 (file)
index 0000000..67fd1bb
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef PERF_COMPRESS_H
+#define PERF_COMPRESS_H
+
+#ifdef HAVE_ZLIB_SUPPORT
+int gzip_decompress_to_file(const char *input, int output_fd);
+#endif
+
+#ifdef HAVE_LZMA_SUPPORT
+int lzma_decompress_to_file(const char *input, int output_fd);
+#endif
+
+#endif /* PERF_COMPRESS_H */
index 0c7d5a4975cd4a8f798533cbd15660c058652d37..8d724f0fa5a81f09ac2547010179ad60f1ed39fd 100644 (file)
@@ -8,12 +8,19 @@
  * Copyright (C) Johannes Schindelin, 2005
  *
  */
+#include <errno.h>
+#include <sys/param.h>
 #include "util.h"
 #include "cache.h"
 #include <subcmd/exec-cmd.h>
 #include "util/hist.h"  /* perf_hist_config */
 #include "util/llvm-utils.h"   /* perf_llvm_config */
 #include "config.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "sane_ctype.h"
 
 #define MAXNAME (256)
 
@@ -627,6 +634,8 @@ static int perf_config_set__init(struct perf_config_set *set)
 {
        int ret = -1;
        const char *home = NULL;
+       char *user_config;
+       struct stat st;
 
        /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
        if (config_exclusive_filename)
@@ -637,35 +646,41 @@ static int perf_config_set__init(struct perf_config_set *set)
        }
 
        home = getenv("HOME");
-       if (perf_config_global() && home) {
-               char *user_config = strdup(mkpath("%s/.perfconfig", home));
-               struct stat st;
 
-               if (user_config == NULL) {
-                       warning("Not enough memory to process %s/.perfconfig, "
-                               "ignoring it.", home);
-                       goto out;
-               }
+       /*
+        * Skip reading user config if:
+        *   - there is no place to read it from (HOME)
+        *   - we are asked not to (PERF_CONFIG_NOGLOBAL=1)
+        */
+       if (!home || !*home || !perf_config_global())
+               return 0;
 
-               if (stat(user_config, &st) < 0) {
-                       if (errno == ENOENT)
-                               ret = 0;
-                       goto out_free;
-               }
+       user_config = strdup(mkpath("%s/.perfconfig", home));
+       if (user_config == NULL) {
+               warning("Not enough memory to process %s/.perfconfig, "
+                       "ignoring it.", home);
+               goto out;
+       }
 
-               ret = 0;
+       if (stat(user_config, &st) < 0) {
+               if (errno == ENOENT)
+                       ret = 0;
+               goto out_free;
+       }
 
-               if (st.st_uid && (st.st_uid != geteuid())) {
-                       warning("File %s not owned by current user or root, "
-                               "ignoring it.", user_config);
-                       goto out_free;
-               }
+       ret = 0;
 
-               if (st.st_size)
-                       ret = perf_config_from_file(collect_config, user_config, set);
-out_free:
-               free(user_config);
+       if (st.st_uid && (st.st_uid != geteuid())) {
+               warning("File %s not owned by current user or root, "
+                       "ignoring it.", user_config);
+               goto out_free;
        }
+
+       if (st.st_size)
+               ret = perf_config_from_file(collect_config, user_config, set);
+
+out_free:
+       free(user_config);
 out:
        return ret;
 }
index e3fde313deb27371de3782eaa76e1e2ee232fdf8..c4af82ab7808c2049216acad5efb2824fecabb1f 100644 (file)
@@ -1,6 +1,8 @@
+#include <errno.h>
 #include <stdlib.h>
 #include "evsel.h"
 #include "counts.h"
+#include "util.h"
 
 struct perf_counts *perf_counts__new(int ncpus, int nthreads)
 {
index 8c750493911369976d0fa171e74f3b678f62c054..37b3bb79ee08db66122c30f6ae5af2473f005d7a 100644 (file)
@@ -3,11 +3,14 @@
 #include "../perf.h"
 #include "cpumap.h"
 #include <assert.h>
+#include <dirent.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <linux/bitmap.h>
 #include "asm/bug.h"
 
+#include "sane_ctype.h"
+
 static int max_cpu_num;
 static int max_present_cpu_num;
 static int max_node_num;
@@ -29,7 +32,7 @@ static struct cpu_map *cpu_map__default_new(void)
                        cpus->map[i] = i;
 
                cpus->nr = nr_cpus;
-               atomic_set(&cpus->refcnt, 1);
+               refcount_set(&cpus->refcnt, 1);
        }
 
        return cpus;
@@ -43,7 +46,7 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
        if (cpus != NULL) {
                cpus->nr = nr_cpus;
                memcpy(cpus->map, tmp_cpus, payload_size);
-               atomic_set(&cpus->refcnt, 1);
+               refcount_set(&cpus->refcnt, 1);
        }
 
        return cpus;
@@ -252,7 +255,7 @@ struct cpu_map *cpu_map__dummy_new(void)
        if (cpus != NULL) {
                cpus->nr = 1;
                cpus->map[0] = -1;
-               atomic_set(&cpus->refcnt, 1);
+               refcount_set(&cpus->refcnt, 1);
        }
 
        return cpus;
@@ -269,7 +272,7 @@ struct cpu_map *cpu_map__empty_new(int nr)
                for (i = 0; i < nr; i++)
                        cpus->map[i] = -1;
 
-               atomic_set(&cpus->refcnt, 1);
+               refcount_set(&cpus->refcnt, 1);
        }
 
        return cpus;
@@ -278,7 +281,7 @@ struct cpu_map *cpu_map__empty_new(int nr)
 static void cpu_map__delete(struct cpu_map *map)
 {
        if (map) {
-               WARN_ONCE(atomic_read(&map->refcnt) != 0,
+               WARN_ONCE(refcount_read(&map->refcnt) != 0,
                          "cpu_map refcnt unbalanced\n");
                free(map);
        }
@@ -287,13 +290,13 @@ static void cpu_map__delete(struct cpu_map *map)
 struct cpu_map *cpu_map__get(struct cpu_map *map)
 {
        if (map)
-               atomic_inc(&map->refcnt);
+               refcount_inc(&map->refcnt);
        return map;
 }
 
 void cpu_map__put(struct cpu_map *map)
 {
-       if (map && atomic_dec_and_test(&map->refcnt))
+       if (map && refcount_dec_and_test(&map->refcnt))
                cpu_map__delete(map);
 }
 
@@ -357,7 +360,7 @@ int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
        /* ensure we process id in increasing order */
        qsort(c->map, c->nr, sizeof(int), cmp_ids);
 
-       atomic_set(&c->refcnt, 1);
+       refcount_set(&c->refcnt, 1);
        *res = c;
        return 0;
 }
@@ -673,3 +676,49 @@ size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size)
        pr_debug("cpumask list: %s\n", buf);
        return ret;
 }
+
+static char hex_char(unsigned char val)
+{
+       if (val < 10)
+               return val + '0';
+       if (val < 16)
+               return val - 10 + 'a';
+       return '?';
+}
+
+size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size)
+{
+       int i, cpu;
+       char *ptr = buf;
+       unsigned char *bitmap;
+       int last_cpu = cpu_map__cpu(map, map->nr - 1);
+
+       bitmap = zalloc((last_cpu + 7) / 8);
+       if (bitmap == NULL) {
+               buf[0] = '\0';
+               return 0;
+       }
+
+       for (i = 0; i < map->nr; i++) {
+               cpu = cpu_map__cpu(map, i);
+               bitmap[cpu / 8] |= 1 << (cpu % 8);
+       }
+
+       for (cpu = last_cpu / 4 * 4; cpu >= 0; cpu -= 4) {
+               unsigned char bits = bitmap[cpu / 8];
+
+               if (cpu % 8)
+                       bits >>= 4;
+               else
+                       bits &= 0xf;
+
+               *ptr++ = hex_char(bits);
+               if ((cpu % 32) == 0 && cpu > 0)
+                       *ptr++ = ',';
+       }
+       *ptr = '\0';
+       free(bitmap);
+
+       buf[size - 1] = '\0';
+       return ptr - buf;
+}
index 1a0549af8f5c944b4fc2b8b619164a107dcf613d..6b8bff87481d090a0e72f7391772bb307d0e1f7c 100644 (file)
@@ -3,13 +3,13 @@
 
 #include <stdio.h>
 #include <stdbool.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 #include "perf.h"
 #include "util/debug.h"
 
 struct cpu_map {
-       atomic_t refcnt;
+       refcount_t refcnt;
        int nr;
        int map[];
 };
@@ -20,6 +20,7 @@ struct cpu_map *cpu_map__dummy_new(void);
 struct cpu_map *cpu_map__new_data(struct cpu_map_data *data);
 struct cpu_map *cpu_map__read(FILE *file);
 size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size);
+size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size);
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
 int cpu_map__get_socket_id(int cpu);
 int cpu_map__get_socket(struct cpu_map *map, int idx, void *data);
index d4a5a21c2a7e2e47596444665b5f5828874da337..4b261c2ec0f10a8e85b68a8a16832ee54ea177b9 100644 (file)
@@ -3,7 +3,7 @@
  *
  * No surprises, and works with signed and unsigned chars.
  */
-#include "util.h"
+#include "sane_ctype.h"
 
 enum {
        S = GIT_SPACE,
index 4e6cbc99f08efc608c2d73ffb9054672d25fb7d9..89d50318833d94e751dc693e6d100b85fce41c28 100644 (file)
@@ -7,7 +7,10 @@
  * Released under the GPL v2. (and only v2, not any later version)
  */
 
+#include <errno.h>
+#include <inttypes.h>
 #include <linux/compiler.h>
+#include <linux/kernel.h>
 #include <babeltrace/ctf-writer/writer.h>
 #include <babeltrace/ctf-writer/clock.h>
 #include <babeltrace/ctf-writer/stream.h>
@@ -27,6 +30,7 @@
 #include "evsel.h"
 #include "machine.h"
 #include "config.h"
+#include "sane_ctype.h"
 
 #define pr_N(n, fmt, ...) \
        eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
@@ -1468,6 +1472,7 @@ int bt_convert__perf2ctf(const char *input, const char *path,
                        .lost            = perf_event__process_lost,
                        .tracing_data    = perf_event__process_tracing_data,
                        .build_id        = perf_event__process_build_id,
+                       .namespaces      = perf_event__process_namespaces,
                        .ordered_events  = true,
                        .ordering_requires_timestamps = true,
                },
index 60bfc9ca1e22f3a1b10d58169d2ed70ccfe040cc..e84bbc8ec058916c968ae940ae662746495efe67 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/kernel.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <errno.h>
 #include <unistd.h>
 #include <string.h>
 
index 03eb81f30d0d0d471fdff09e8779ed02fd73eb36..a5b3777ffee601aa28e358c4f9928fd16088d1c8 100644 (file)
@@ -2,19 +2,26 @@
 
 #include "../perf.h"
 
+#include <inttypes.h>
 #include <string.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <sys/wait.h>
 #include <api/debug.h>
 #include <linux/time64.h>
-
+#ifdef HAVE_BACKTRACE_SUPPORT
+#include <execinfo.h>
+#endif
 #include "cache.h"
 #include "color.h"
 #include "event.h"
 #include "debug.h"
+#include "print_binary.h"
 #include "util.h"
 #include "target.h"
 
+#include "sane_ctype.h"
+
 int verbose;
 bool dump_trace = false, quiet = false;
 int debug_ordered_events;
@@ -244,3 +251,31 @@ void perf_debug_setup(void)
 {
        libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);
 }
+
+/* Obtain a backtrace and print it to stdout. */
+#ifdef HAVE_BACKTRACE_SUPPORT
+void dump_stack(void)
+{
+       void *array[16];
+       size_t size = backtrace(array, ARRAY_SIZE(array));
+       char **strings = backtrace_symbols(array, size);
+       size_t i;
+
+       printf("Obtained %zd stack frames.\n", size);
+
+       for (i = 0; i < size; i++)
+               printf("%s\n", strings[i]);
+
+       free(strings);
+}
+#else
+void dump_stack(void) {}
+#endif
+
+void sighandler_dump_stack(int sig)
+{
+       psignal(sig, "perf");
+       dump_stack();
+       signal(sig, SIG_DFL);
+       raise(sig);
+}
index 98832f5531d3d0931b8a21560e56330bf1db5cdc..8a23ea1a71c7cff1bc24cd3dd063d261b5fc18db 100644 (file)
@@ -56,4 +56,7 @@ int perf_debug_option(const char *str);
 void perf_debug_setup(void);
 int perf_quiet_option(void);
 
+void dump_stack(void);
+void sighandler_dump_stack(int sig);
+
 #endif /* __PERF_DEBUG_H */
index 3e6062ab2cdda23e9b74b54ef4f021031905249b..cb66d334f5328690072193b5a902df50076786dc 100644 (file)
@@ -7,6 +7,8 @@
 
 #include "demangle-java.h"
 
+#include "sane_ctype.h"
+
 enum {
        MODE_PREFIX = 0,
        MODE_CLASS  = 1,
index 1647f285c6296d62ef031b5e880732fefa25863f..eec754243f4d3b257ae1013875215d7c6ec007f3 100644 (file)
@@ -17,6 +17,7 @@
 #include "evlist.h"
 #include "evsel.h"
 #include "pmu.h"
+#include <errno.h>
 
 static int
 perf_evsel__apply_drv_configs(struct perf_evsel *evsel,
index d38b62a700ca126c293756baa83dbc27df61e53a..a96a99d2369f800634025bcdfa9838d1d6bc9d97 100644 (file)
@@ -1,12 +1,20 @@
 #include <asm/bug.h>
+#include <linux/kernel.h>
 #include <sys/time.h>
 #include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include "compress.h"
+#include "path.h"
 #include "symbol.h"
 #include "dso.h"
 #include "machine.h"
 #include "auxtrace.h"
 #include "util.h"
 #include "debug.h"
+#include "string2.h"
 #include "vdso.h"
 
 static const char * const debuglink_paths[] = {
@@ -1109,7 +1117,7 @@ struct dso *dso__new(const char *name)
                INIT_LIST_HEAD(&dso->node);
                INIT_LIST_HEAD(&dso->data.open_entry);
                pthread_mutex_init(&dso->lock, NULL);
-               atomic_set(&dso->refcnt, 1);
+               refcount_set(&dso->refcnt, 1);
        }
 
        return dso;
@@ -1147,13 +1155,13 @@ void dso__delete(struct dso *dso)
 struct dso *dso__get(struct dso *dso)
 {
        if (dso)
-               atomic_inc(&dso->refcnt);
+               refcount_inc(&dso->refcnt);
        return dso;
 }
 
 void dso__put(struct dso *dso)
 {
-       if (dso && atomic_dec_and_test(&dso->refcnt))
+       if (dso && refcount_dec_and_test(&dso->refcnt))
                dso__delete(dso);
 }
 
index ecc4bbd3f82e3e172a89480d04466ba95eab7b09..12350b17172730adf0dffdf324cb9e0b4a4be2ba 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __PERF_DSO
 #define __PERF_DSO
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/types.h>
 #include <linux/rbtree.h>
 #include <sys/types.h>
@@ -187,7 +187,7 @@ struct dso {
                void     *priv;
                u64      db_id;
        };
-       atomic_t         refcnt;
+       refcount_t       refcnt;
        char             name[0];
 };
 
diff --git a/tools/perf/util/dump-insn.c b/tools/perf/util/dump-insn.c
new file mode 100644 (file)
index 0000000..ffbdb19
--- /dev/null
@@ -0,0 +1,14 @@
+#include <linux/compiler.h>
+#include "dump-insn.h"
+
+/* Fallback code */
+
+__weak
+const char *dump_insn(struct perf_insn *x __maybe_unused,
+                     u64 ip __maybe_unused, u8 *inbuf __maybe_unused,
+                     int inlen __maybe_unused, int *lenp)
+{
+       if (lenp)
+               *lenp = 0;
+       return "?";
+}
diff --git a/tools/perf/util/dump-insn.h b/tools/perf/util/dump-insn.h
new file mode 100644 (file)
index 0000000..90fb115
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __PERF_DUMP_INSN_H
+#define __PERF_DUMP_INSN_H 1
+
+#define MAXINSN 15
+
+#include <linux/types.h>
+
+struct thread;
+
+struct perf_insn {
+       /* Initialized by callers: */
+       struct thread *thread;
+       u8            cpumode;
+       bool          is64bit;
+       int           cpu;
+       /* Temporary */
+       char          out[256];
+};
+
+const char *dump_insn(struct perf_insn *x, u64 ip,
+                     u8 *inbuf, int inlen, int *lenp);
+#endif
index 41e068e943499d2e7ce7a1794936eff09afd7077..f5acda13dcfa7daef429510fbfde922ea28a2789 100644 (file)
  *
  */
 
+#include <errno.h>
+#include <inttypes.h>
 #include <stdbool.h>
 #include "util.h"
 #include "debug.h"
 #include "dwarf-aux.h"
+#include "string2.h"
 
 /**
  * cu_find_realpath - Find the realpath of the target file
index 62bc4a86a970f8a7cda3cac3f7626e1014408027..c708395b3cb661933ed0357dfafd3528614870f7 100644 (file)
@@ -8,6 +8,7 @@
 #include <debug.h>
 #include <dwarf-regs.h>
 #include <elf.h>
+#include <linux/kernel.h>
 
 #ifndef EM_AARCH64
 #define EM_AARCH64     183  /* ARM 64 bit */
index 075fc77286bf05feb5cca14fc3825f34d0fdaed1..9e21538c42ae96747b671e4f27a9f73ff83dc6ec 100644 (file)
@@ -1,6 +1,7 @@
 #include "cpumap.h"
 #include "env.h"
 #include "util.h"
+#include <errno.h>
 
 struct perf_env perf_env;
 
index 4ea7ce72ed9c8e3fb92ffca44b3f51fb09f6b01f..dc5c3bb69d73882ebbac88dfec2d16c55b56355e 100644 (file)
@@ -1,15 +1,24 @@
+#include <dirent.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
 #include <api/fs/fs.h>
+#include <linux/perf_event.h>
 #include "event.h"
 #include "debug.h"
 #include "hist.h"
 #include "machine.h"
 #include "sort.h"
-#include "string.h"
+#include "string2.h"
 #include "strlist.h"
 #include "thread.h"
 #include "thread_map.h"
+#include "sane_ctype.h"
 #include "symbol/kallsyms.h"
 #include "asm/bug.h"
 #include "stat.h"
@@ -31,6 +40,7 @@ static const char *perf_event__names[] = {
        [PERF_RECORD_LOST_SAMPLES]              = "LOST_SAMPLES",
        [PERF_RECORD_SWITCH]                    = "SWITCH",
        [PERF_RECORD_SWITCH_CPU_WIDE]           = "SWITCH_CPU_WIDE",
+       [PERF_RECORD_NAMESPACES]                = "NAMESPACES",
        [PERF_RECORD_HEADER_ATTR]               = "ATTR",
        [PERF_RECORD_HEADER_EVENT_TYPE]         = "EVENT_TYPE",
        [PERF_RECORD_HEADER_TRACING_DATA]       = "TRACING_DATA",
@@ -49,6 +59,16 @@ static const char *perf_event__names[] = {
        [PERF_RECORD_TIME_CONV]                 = "TIME_CONV",
 };
 
+static const char *perf_ns__names[] = {
+       [NET_NS_INDEX]          = "net",
+       [UTS_NS_INDEX]          = "uts",
+       [IPC_NS_INDEX]          = "ipc",
+       [PID_NS_INDEX]          = "pid",
+       [USER_NS_INDEX]         = "user",
+       [MNT_NS_INDEX]          = "mnt",
+       [CGROUP_NS_INDEX]       = "cgroup",
+};
+
 const char *perf_event__name(unsigned int id)
 {
        if (id >= ARRAY_SIZE(perf_event__names))
@@ -58,6 +78,13 @@ const char *perf_event__name(unsigned int id)
        return perf_event__names[id];
 }
 
+static const char *perf_ns__name(unsigned int id)
+{
+       if (id >= ARRAY_SIZE(perf_ns__names))
+               return "UNKNOWN";
+       return perf_ns__names[id];
+}
+
 static int perf_tool__process_synth_event(struct perf_tool *tool,
                                          union perf_event *event,
                                          struct machine *machine,
@@ -88,7 +115,7 @@ static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
        int fd;
        size_t size = 0;
        ssize_t n;
-       char *nl, *name, *tgids, *ppids;
+       char *name, *tgids, *ppids;
 
        *tgid = -1;
        *ppid = -1;
@@ -115,10 +142,10 @@ static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
        ppids = strstr(bf, "PPid:");
 
        if (name) {
-               name += 5;  /* strlen("Name:") */
+               char *nl;
 
-               while (*name && isspace(*name))
-                       ++name;
+               name += 5;  /* strlen("Name:") */
+               name = ltrim(name);
 
                nl = strchr(name, '\n');
                if (nl)
@@ -203,6 +230,58 @@ pid_t perf_event__synthesize_comm(struct perf_tool *tool,
        return tgid;
 }
 
+static void perf_event__get_ns_link_info(pid_t pid, const char *ns,
+                                        struct perf_ns_link_info *ns_link_info)
+{
+       struct stat64 st;
+       char proc_ns[128];
+
+       sprintf(proc_ns, "/proc/%u/ns/%s", pid, ns);
+       if (stat64(proc_ns, &st) == 0) {
+               ns_link_info->dev = st.st_dev;
+               ns_link_info->ino = st.st_ino;
+       }
+}
+
+int perf_event__synthesize_namespaces(struct perf_tool *tool,
+                                     union perf_event *event,
+                                     pid_t pid, pid_t tgid,
+                                     perf_event__handler_t process,
+                                     struct machine *machine)
+{
+       u32 idx;
+       struct perf_ns_link_info *ns_link_info;
+
+       if (!tool || !tool->namespace_events)
+               return 0;
+
+       memset(&event->namespaces, 0, (sizeof(event->namespaces) +
+              (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
+              machine->id_hdr_size));
+
+       event->namespaces.pid = tgid;
+       event->namespaces.tid = pid;
+
+       event->namespaces.nr_namespaces = NR_NAMESPACES;
+
+       ns_link_info = event->namespaces.link_info;
+
+       for (idx = 0; idx < event->namespaces.nr_namespaces; idx++)
+               perf_event__get_ns_link_info(pid, perf_ns__name(idx),
+                                            &ns_link_info[idx]);
+
+       event->namespaces.header.type = PERF_RECORD_NAMESPACES;
+
+       event->namespaces.header.size = (sizeof(event->namespaces) +
+                       (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
+                       machine->id_hdr_size);
+
+       if (perf_tool__process_synth_event(tool, event, machine, process) != 0)
+               return -1;
+
+       return 0;
+}
+
 static int perf_event__synthesize_fork(struct perf_tool *tool,
                                       union perf_event *event,
                                       pid_t pid, pid_t tgid, pid_t ppid,
@@ -255,8 +334,8 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
        if (machine__is_default_guest(machine))
                return 0;
 
-       snprintf(filename, sizeof(filename), "%s/proc/%d/maps",
-                machine->root_dir, pid);
+       snprintf(filename, sizeof(filename), "%s/proc/%d/task/%d/maps",
+                machine->root_dir, pid, pid);
 
        fp = fopen(filename, "r");
        if (fp == NULL) {
@@ -434,8 +513,9 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
 static int __event__synthesize_thread(union perf_event *comm_event,
                                      union perf_event *mmap_event,
                                      union perf_event *fork_event,
+                                     union perf_event *namespaces_event,
                                      pid_t pid, int full,
-                                         perf_event__handler_t process,
+                                     perf_event__handler_t process,
                                      struct perf_tool *tool,
                                      struct machine *machine,
                                      bool mmap_data,
@@ -455,6 +535,11 @@ static int __event__synthesize_thread(union perf_event *comm_event,
                if (tgid == -1)
                        return -1;
 
+               if (perf_event__synthesize_namespaces(tool, namespaces_event, pid,
+                                                     tgid, process, machine) < 0)
+                       return -1;
+
+
                return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
                                                          process, machine, mmap_data,
                                                          proc_map_timeout);
@@ -488,6 +573,11 @@ static int __event__synthesize_thread(union perf_event *comm_event,
                if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
                                                ppid, process, machine) < 0)
                        break;
+
+               if (perf_event__synthesize_namespaces(tool, namespaces_event, _pid,
+                                                     tgid, process, machine) < 0)
+                       break;
+
                /*
                 * Send the prepared comm event
                 */
@@ -516,6 +606,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
                                      unsigned int proc_map_timeout)
 {
        union perf_event *comm_event, *mmap_event, *fork_event;
+       union perf_event *namespaces_event;
        int err = -1, thread, j;
 
        comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
@@ -530,10 +621,16 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
        if (fork_event == NULL)
                goto out_free_mmap;
 
+       namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
+                                 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
+                                 machine->id_hdr_size);
+       if (namespaces_event == NULL)
+               goto out_free_fork;
+
        err = 0;
        for (thread = 0; thread < threads->nr; ++thread) {
                if (__event__synthesize_thread(comm_event, mmap_event,
-                                              fork_event,
+                                              fork_event, namespaces_event,
                                               thread_map__pid(threads, thread), 0,
                                               process, tool, machine,
                                               mmap_data, proc_map_timeout)) {
@@ -559,7 +656,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
                        /* if not, generate events for it */
                        if (need_leader &&
                            __event__synthesize_thread(comm_event, mmap_event,
-                                                      fork_event,
+                                                      fork_event, namespaces_event,
                                                       comm_event->comm.pid, 0,
                                                       process, tool, machine,
                                                       mmap_data, proc_map_timeout)) {
@@ -568,6 +665,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
                        }
                }
        }
+       free(namespaces_event);
+out_free_fork:
        free(fork_event);
 out_free_mmap:
        free(mmap_event);
@@ -587,6 +686,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
        char proc_path[PATH_MAX];
        struct dirent *dirent;
        union perf_event *comm_event, *mmap_event, *fork_event;
+       union perf_event *namespaces_event;
        int err = -1;
 
        if (machine__is_default_guest(machine))
@@ -604,11 +704,17 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
        if (fork_event == NULL)
                goto out_free_mmap;
 
+       namespaces_event = malloc(sizeof(namespaces_event->namespaces) +
+                                 (NR_NAMESPACES * sizeof(struct perf_ns_link_info)) +
+                                 machine->id_hdr_size);
+       if (namespaces_event == NULL)
+               goto out_free_fork;
+
        snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
        proc = opendir(proc_path);
 
        if (proc == NULL)
-               goto out_free_fork;
+               goto out_free_namespaces;
 
        while ((dirent = readdir(proc)) != NULL) {
                char *end;
@@ -620,13 +726,16 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
                 * We may race with exiting thread, so don't stop just because
                 * one thread couldn't be synthesized.
                 */
-               __event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
-                                          1, process, tool, machine, mmap_data,
+               __event__synthesize_thread(comm_event, mmap_event, fork_event,
+                                          namespaces_event, pid, 1, process,
+                                          tool, machine, mmap_data,
                                           proc_map_timeout);
        }
 
        err = 0;
        closedir(proc);
+out_free_namespaces:
+       free(namespaces_event);
 out_free_fork:
        free(fork_event);
 out_free_mmap:
@@ -659,15 +768,16 @@ static int find_symbol_cb(void *arg, const char *name, char type,
        return 1;
 }
 
-u64 kallsyms__get_function_start(const char *kallsyms_filename,
-                                const char *symbol_name)
+int kallsyms__get_function_start(const char *kallsyms_filename,
+                                const char *symbol_name, u64 *addr)
 {
        struct process_symbol_args args = { .name = symbol_name, };
 
        if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
-               return 0;
+               return -1;
 
-       return args.start;
+       *addr = args.start;
+       return 0;
 }
 
 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
@@ -1008,6 +1118,33 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
        return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
 }
 
+size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp)
+{
+       size_t ret = 0;
+       struct perf_ns_link_info *ns_link_info;
+       u32 nr_namespaces, idx;
+
+       ns_link_info = event->namespaces.link_info;
+       nr_namespaces = event->namespaces.nr_namespaces;
+
+       ret += fprintf(fp, " %d/%d - nr_namespaces: %u\n\t\t[",
+                      event->namespaces.pid,
+                      event->namespaces.tid,
+                      nr_namespaces);
+
+       for (idx = 0; idx < nr_namespaces; idx++) {
+               if (idx && (idx % 4 == 0))
+                       ret += fprintf(fp, "\n\t\t ");
+
+               ret  += fprintf(fp, "%u/%s: %" PRIu64 "/%#" PRIx64 "%s", idx,
+                               perf_ns__name(idx), (u64)ns_link_info[idx].dev,
+                               (u64)ns_link_info[idx].ino,
+                               ((idx + 1) != nr_namespaces) ? ", " : "]\n");
+       }
+
+       return ret;
+}
+
 int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
                             union perf_event *event,
                             struct perf_sample *sample,
@@ -1016,6 +1153,14 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
        return machine__process_comm_event(machine, event, sample);
 }
 
+int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused,
+                                  union perf_event *event,
+                                  struct perf_sample *sample,
+                                  struct machine *machine)
+{
+       return machine__process_namespaces_event(machine, event, sample);
+}
+
 int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
                             union perf_event *event,
                             struct perf_sample *sample,
@@ -1153,11 +1298,12 @@ int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
 
 size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp)
 {
-       return fprintf(fp, " offset: %#"PRIx64" size: %#"PRIx64" flags: %#"PRIx64" [%s%s]\n",
+       return fprintf(fp, " offset: %#"PRIx64" size: %#"PRIx64" flags: %#"PRIx64" [%s%s%s]\n",
                       event->aux.aux_offset, event->aux.aux_size,
                       event->aux.flags,
                       event->aux.flags & PERF_AUX_FLAG_TRUNCATED ? "T" : "",
-                      event->aux.flags & PERF_AUX_FLAG_OVERWRITE ? "O" : "");
+                      event->aux.flags & PERF_AUX_FLAG_OVERWRITE ? "O" : "",
+                      event->aux.flags & PERF_AUX_FLAG_PARTIAL   ? "P" : "");
 }
 
 size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp)
@@ -1196,6 +1342,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
        case PERF_RECORD_MMAP:
                ret += perf_event__fprintf_mmap(event, fp);
                break;
+       case PERF_RECORD_NAMESPACES:
+               ret += perf_event__fprintf_namespaces(event, fp);
+               break;
        case PERF_RECORD_MMAP2:
                ret += perf_event__fprintf_mmap2(event, fp);
                break;
index c735c53a26f8f6dcb37727299e0560d07a5f6ddb..27ac047490c3ace9287a4de53c2ba2c9a4339d41 100644 (file)
@@ -3,9 +3,9 @@
 
 #include <limits.h>
 #include <stdio.h>
+#include <linux/kernel.h>
 
 #include "../perf.h"
-#include "map.h"
 #include "build-id.h"
 #include "perf_regs.h"
 
@@ -39,6 +39,13 @@ struct comm_event {
        char comm[16];
 };
 
+struct namespaces_event {
+       struct perf_event_header header;
+       u32 pid, tid;
+       u64 nr_namespaces;
+       struct perf_ns_link_info link_info[];
+};
+
 struct fork_event {
        struct perf_event_header header;
        u32 pid, ppid;
@@ -269,6 +276,7 @@ struct events_stats {
        u64 total_lost;
        u64 total_lost_samples;
        u64 total_aux_lost;
+       u64 total_aux_partial;
        u64 total_invalid_chains;
        u32 nr_events[PERF_RECORD_HEADER_MAX];
        u32 nr_non_filtered_samples;
@@ -485,6 +493,7 @@ union perf_event {
        struct mmap_event               mmap;
        struct mmap2_event              mmap2;
        struct comm_event               comm;
+       struct namespaces_event         namespaces;
        struct fork_event               fork;
        struct lost_event               lost;
        struct lost_samples_event       lost_samples;
@@ -587,6 +596,10 @@ int perf_event__process_switch(struct perf_tool *tool,
                               union perf_event *event,
                               struct perf_sample *sample,
                               struct machine *machine);
+int perf_event__process_namespaces(struct perf_tool *tool,
+                                  union perf_event *event,
+                                  struct perf_sample *sample,
+                                  struct machine *machine);
 int perf_event__process_mmap(struct perf_tool *tool,
                             union perf_event *event,
                             struct perf_sample *sample,
@@ -636,6 +649,12 @@ pid_t perf_event__synthesize_comm(struct perf_tool *tool,
                                  perf_event__handler_t process,
                                  struct machine *machine);
 
+int perf_event__synthesize_namespaces(struct perf_tool *tool,
+                                     union perf_event *event,
+                                     pid_t pid, pid_t tgid,
+                                     perf_event__handler_t process,
+                                     struct machine *machine);
+
 int perf_event__synthesize_mmap_events(struct perf_tool *tool,
                                       union perf_event *event,
                                       pid_t pid, pid_t tgid,
@@ -653,12 +672,21 @@ size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
+size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
-u64 kallsyms__get_function_start(const char *kallsyms_filename,
-                                const char *symbol_name);
+int kallsyms__get_function_start(const char *kallsyms_filename,
+                                const char *symbol_name, u64 *addr);
 
 void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max);
 void  cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
                               u16 type, int max);
+
+void event_attr_init(struct perf_event_attr *attr);
+
+int perf_event_paranoid(void);
+
+extern int sysctl_perf_event_max_stack;
+extern int sysctl_perf_event_max_contexts_per_stack;
+
 #endif /* __PERF_RECORD_H */
index b601f2814a30e9d7d2b6f689b5e495659c34e600..46c0faf6c502b9ae31ac09901bbca31de61691bf 100644 (file)
@@ -8,6 +8,8 @@
  */
 #include "util.h"
 #include <api/fs/fs.h>
+#include <errno.h>
+#include <inttypes.h>
 #include <poll.h>
 #include "cpumap.h"
 #include "thread_map.h"
 #include "evlist.h"
 #include "evsel.h"
 #include "debug.h"
+#include "units.h"
 #include "asm/bug.h"
+#include <signal.h>
 #include <unistd.h>
 
 #include "parse-events.h"
 #include <subcmd/parse-options.h>
 
+#include <sys/ioctl.h>
 #include <sys/mman.h>
 
 #include <linux/bitops.h>
@@ -777,7 +782,7 @@ union perf_event *perf_mmap__read_forward(struct perf_mmap *md, bool check_messu
        /*
         * Check if event was unmapped due to a POLLHUP/POLLERR.
         */
-       if (!atomic_read(&md->refcnt))
+       if (!refcount_read(&md->refcnt))
                return NULL;
 
        head = perf_mmap__read_head(md);
@@ -794,7 +799,7 @@ perf_mmap__read_backward(struct perf_mmap *md)
        /*
         * Check if event was unmapped due to a POLLHUP/POLLERR.
         */
-       if (!atomic_read(&md->refcnt))
+       if (!refcount_read(&md->refcnt))
                return NULL;
 
        head = perf_mmap__read_head(md);
@@ -856,7 +861,7 @@ void perf_mmap__read_catchup(struct perf_mmap *md)
 {
        u64 head;
 
-       if (!atomic_read(&md->refcnt))
+       if (!refcount_read(&md->refcnt))
                return;
 
        head = perf_mmap__read_head(md);
@@ -875,14 +880,14 @@ static bool perf_mmap__empty(struct perf_mmap *md)
 
 static void perf_mmap__get(struct perf_mmap *map)
 {
-       atomic_inc(&map->refcnt);
+       refcount_inc(&map->refcnt);
 }
 
 static void perf_mmap__put(struct perf_mmap *md)
 {
-       BUG_ON(md->base && atomic_read(&md->refcnt) == 0);
+       BUG_ON(md->base && refcount_read(&md->refcnt) == 0);
 
-       if (atomic_dec_and_test(&md->refcnt))
+       if (refcount_dec_and_test(&md->refcnt))
                perf_mmap__munmap(md);
 }
 
@@ -894,7 +899,7 @@ void perf_mmap__consume(struct perf_mmap *md, bool overwrite)
                perf_mmap__write_tail(md, old);
        }
 
-       if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
+       if (refcount_read(&md->refcnt) == 1 && perf_mmap__empty(md))
                perf_mmap__put(md);
 }
 
@@ -937,7 +942,7 @@ static void perf_mmap__munmap(struct perf_mmap *map)
                munmap(map->base, perf_mmap__mmap_len(map));
                map->base = NULL;
                map->fd = -1;
-               atomic_set(&map->refcnt, 0);
+               refcount_set(&map->refcnt, 0);
        }
        auxtrace_mmap__munmap(&map->auxtrace_mmap);
 }
@@ -974,8 +979,19 @@ static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
        if (!map)
                return NULL;
 
-       for (i = 0; i < evlist->nr_mmaps; i++)
+       for (i = 0; i < evlist->nr_mmaps; i++) {
                map[i].fd = -1;
+               /*
+                * When the perf_mmap() call is made we grab one refcount, plus
+                * one extra to let perf_evlist__mmap_consume() get the last
+                * events after all real references (perf_mmap__get()) are
+                * dropped.
+                *
+                * Each PERF_EVENT_IOC_SET_OUTPUT points to this mmap and
+                * thus does perf_mmap__get() on it.
+                */
+               refcount_set(&map[i].refcnt, 0);
+       }
        return map;
 }
 
@@ -1001,7 +1017,7 @@ static int perf_mmap__mmap(struct perf_mmap *map,
         * evlist layer can't just drop it when filtering events in
         * perf_evlist__filter_pollfd().
         */
-       atomic_set(&map->refcnt, 2);
+       refcount_set(&map->refcnt, 2);
        map->prev = 0;
        map->mask = mp->mask;
        map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot,
index 389b9ccdf8c75db39d8e2163d6909a4db01e65a8..94cea4398a13aeefb1eff28fdd2defa3194209f0 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef __PERF_EVLIST_H
 #define __PERF_EVLIST_H 1
 
-#include <linux/atomic.h>
+#include <linux/kernel.h>
+#include <linux/refcount.h>
 #include <linux/list.h>
 #include <api/fd/array.h>
 #include <stdio.h>
@@ -10,6 +11,7 @@
 #include "evsel.h"
 #include "util.h"
 #include "auxtrace.h"
+#include <signal.h>
 #include <unistd.h>
 
 struct pollfd;
@@ -29,7 +31,7 @@ struct perf_mmap {
        void             *base;
        int              mask;
        int              fd;
-       atomic_t         refcnt;
+       refcount_t       refcnt;
        u64              prev;
        struct auxtrace_mmap auxtrace_mmap;
        char             event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
index ac59710b79e0b4cbee35cacc1e40a2102e091d8e..e4f7902d5afa62f0aecab1103bc05ca4bcb226e9 100644 (file)
@@ -8,16 +8,20 @@
  */
 
 #include <byteswap.h>
+#include <errno.h>
+#include <inttypes.h>
 #include <linux/bitops.h>
 #include <api/fs/tracing_path.h>
 #include <traceevent/event-parse.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/perf_event.h>
 #include <linux/err.h>
+#include <sys/ioctl.h>
 #include <sys/resource.h>
 #include "asm/bug.h"
 #include "callchain.h"
 #include "cgroup.h"
+#include "event.h"
 #include "evsel.h"
 #include "evlist.h"
 #include "util.h"
@@ -30,6 +34,8 @@
 #include "stat.h"
 #include "util/parse-branch-options.h"
 
+#include "sane_ctype.h"
+
 static struct {
        bool sample_id_all;
        bool exclude_guest;
@@ -236,6 +242,10 @@ void perf_evsel__init(struct perf_evsel *evsel,
        evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
        perf_evsel__calc_id_pos(evsel);
        evsel->cmdline_group_boundary = false;
+       evsel->metric_expr   = NULL;
+       evsel->metric_name   = NULL;
+       evsel->metric_events = NULL;
+       evsel->collect_stat  = false;
 }
 
 struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
@@ -932,6 +942,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
        attr->mmap2 = track && !perf_missing_features.mmap2;
        attr->comm  = track;
 
+       if (opts->record_namespaces)
+               attr->namespaces  = track;
+
        if (opts->record_switch_events)
                attr->context_switch = track;
 
@@ -1232,7 +1245,7 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
        if (FD(evsel, cpu, thread) < 0)
                return -EINVAL;
 
-       if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) < 0)
+       if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) <= 0)
                return -errno;
 
        return 0;
@@ -1250,7 +1263,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
        if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1, thread + 1) < 0)
                return -ENOMEM;
 
-       if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
+       if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) <= 0)
                return -errno;
 
        perf_evsel__compute_deltas(evsel, cpu, thread, &count);
@@ -2450,11 +2463,17 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
                              int err, char *msg, size_t size)
 {
        char sbuf[STRERR_BUFSIZE];
+       int printed = 0;
 
        switch (err) {
        case EPERM:
        case EACCES:
-               return scnprintf(msg, size,
+               if (err == EPERM)
+                       printed = scnprintf(msg, size,
+                               "No permission to enable %s event.\n\n",
+                               perf_evsel__name(evsel));
+
+               return scnprintf(msg + printed, size - printed,
                 "You may not have permission to collect %sstats.\n\n"
                 "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n"
                 "which controls use of the performance events system by\n"
index 06ef6f29efa12a6c1300eca641e9446a0a4d17f8..d101695c482cfb288db70b1f268372d4f4323f65 100644 (file)
@@ -131,6 +131,11 @@ struct perf_evsel {
        bool                    cmdline_group_boundary;
        struct list_head        config_terms;
        int                     bpf_fd;
+       bool                    merged_stat;
+       const char *            metric_expr;
+       const char *            metric_name;
+       struct perf_evsel       **metric_events;
+       bool                    collect_stat;
 };
 
 union u64_swap {
index 4ef5184819a0975d592aecff5204d9d273494b4f..e415aee6a24520f3c88e9ce70d621b39109896b6 100644 (file)
@@ -1,9 +1,11 @@
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include <traceevent/event-parse.h>
 #include "evsel.h"
 #include "callchain.h"
 #include "map.h"
+#include "strlist.h"
 #include "symbol.h"
 
 static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
diff --git a/tools/perf/util/expr.h b/tools/perf/util/expr.h
new file mode 100644 (file)
index 0000000..9c2760a
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef PARSE_CTX_H
+#define PARSE_CTX_H 1
+
+#define EXPR_MAX_OTHER 8
+#define MAX_PARSE_ID EXPR_MAX_OTHER
+
+struct parse_id {
+       const char *name;
+       double val;
+};
+
+struct parse_ctx {
+       int num_ids;
+       struct parse_id ids[MAX_PARSE_ID];
+};
+
+void expr__ctx_init(struct parse_ctx *ctx);
+void expr__add_id(struct parse_ctx *ctx, const char *id, double val);
+#ifndef IN_EXPR_Y
+int expr__parse(double *final_val, struct parse_ctx *ctx, const char **pp);
+#endif
+int expr__find_other(const char *p, const char *one, const char ***other,
+               int *num_other);
+
+#endif
diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y
new file mode 100644 (file)
index 0000000..954556b
--- /dev/null
@@ -0,0 +1,173 @@
+/* Simple expression parser */
+%{
+#include "util.h"
+#include "util/debug.h"
+#define IN_EXPR_Y 1
+#include "expr.h"
+#include <string.h>
+
+#define MAXIDLEN 256
+%}
+
+%pure-parser
+%parse-param { double *final_val }
+%parse-param { struct parse_ctx *ctx }
+%parse-param { const char **pp }
+%lex-param { const char **pp }
+
+%union {
+       double num;
+       char id[MAXIDLEN+1];
+}
+
+%token <num> NUMBER
+%token <id> ID
+%left '|'
+%left '^'
+%left '&'
+%left '-' '+'
+%left '*' '/' '%'
+%left NEG NOT
+%type <num> expr
+
+%{
+static int expr__lex(YYSTYPE *res, const char **pp);
+
+static void expr__error(double *final_val __maybe_unused,
+                      struct parse_ctx *ctx __maybe_unused,
+                      const char **pp __maybe_unused,
+                      const char *s)
+{
+       pr_debug("%s\n", s);
+}
+
+static int lookup_id(struct parse_ctx *ctx, char *id, double *val)
+{
+       int i;
+
+       for (i = 0; i < ctx->num_ids; i++) {
+               if (!strcasecmp(ctx->ids[i].name, id)) {
+                       *val = ctx->ids[i].val;
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+%}
+%%
+
+all_expr: expr                 { *final_val = $1; }
+       ;
+
+expr:    NUMBER
+       | ID                    { if (lookup_id(ctx, $1, &$$) < 0) {
+                                       pr_debug("%s not found", $1);
+                                       YYABORT;
+                                 }
+                               }
+       | expr '+' expr         { $$ = $1 + $3; }
+       | expr '-' expr         { $$ = $1 - $3; }
+       | expr '*' expr         { $$ = $1 * $3; }
+       | expr '/' expr         { if ($3 == 0) YYABORT; $$ = $1 / $3; }
+       | expr '%' expr         { if ((long)$3 == 0) YYABORT; $$ = (long)$1 % (long)$3; }
+       | '-' expr %prec NEG    { $$ = -$2; }
+       | '(' expr ')'          { $$ = $2; }
+       ;
+
+%%
+
+static int expr__symbol(YYSTYPE *res, const char *p, const char **pp)
+{
+       char *dst = res->id;
+       const char *s = p;
+
+       while (isalnum(*p) || *p == '_' || *p == '.') {
+               if (p - s >= MAXIDLEN)
+                       return -1;
+               *dst++ = *p++;
+       }
+       *dst = 0;
+       *pp = p;
+       return ID;
+}
+
+static int expr__lex(YYSTYPE *res, const char **pp)
+{
+       int tok;
+       const char *s;
+       const char *p = *pp;
+
+       while (isspace(*p))
+               p++;
+       s = p;
+       switch (*p++) {
+       case 'a' ... 'z':
+       case 'A' ... 'Z':
+               return expr__symbol(res, p - 1, pp);
+       case '0' ... '9': case '.':
+               res->num = strtod(s, (char **)&p);
+               tok = NUMBER;
+               break;
+       default:
+               tok = *s;
+               break;
+       }
+       *pp = p;
+       return tok;
+}
+
+/* Caller must make sure id is allocated */
+void expr__add_id(struct parse_ctx *ctx, const char *name, double val)
+{
+       int idx;
+       assert(ctx->num_ids < MAX_PARSE_ID);
+       idx = ctx->num_ids++;
+       ctx->ids[idx].name = name;
+       ctx->ids[idx].val = val;
+}
+
+void expr__ctx_init(struct parse_ctx *ctx)
+{
+       ctx->num_ids = 0;
+}
+
+int expr__find_other(const char *p, const char *one, const char ***other,
+                    int *num_otherp)
+{
+       const char *orig = p;
+       int err = -1;
+       int num_other;
+
+       *other = malloc((EXPR_MAX_OTHER + 1) * sizeof(char *));
+       if (!*other)
+               return -1;
+
+       num_other = 0;
+       for (;;) {
+               YYSTYPE val;
+               int tok = expr__lex(&val, &p);
+               if (tok == 0) {
+                       err = 0;
+                       break;
+               }
+               if (tok == ID && strcasecmp(one, val.id)) {
+                       if (num_other >= EXPR_MAX_OTHER - 1) {
+                               pr_debug("Too many extra events in %s\n", orig);
+                               break;
+                       }
+                       (*other)[num_other] = strdup(val.id);
+                       if (!(*other)[num_other])
+                               return -1;
+                       num_other++;
+               }
+       }
+       (*other)[num_other] = NULL;
+       *num_otherp = num_other;
+       if (err) {
+               *num_otherp = 0;
+               free(*other);
+               *other = NULL;
+       }
+       return err;
+}
index 05714d548584b30297892854469c584d280f3a8b..314a07151fb772377752dae62658b79ffdc87cd6 100644 (file)
@@ -1,4 +1,8 @@
+#include <errno.h>
+#include <inttypes.h>
 #include "util.h"
+#include "string2.h"
+#include <sys/param.h>
 #include <sys/types.h>
 #include <byteswap.h>
 #include <unistd.h>
 #include <linux/list.h>
 #include <linux/kernel.h>
 #include <linux/bitops.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/utsname.h>
+#include <unistd.h>
 
 #include "evlist.h"
 #include "evsel.h"
 #include "header.h"
+#include "memswap.h"
 #include "../perf.h"
 #include "trace-event.h"
 #include "session.h"
@@ -26,6 +34,8 @@
 #include <api/fs/fs.h>
 #include "asm/bug.h"
 
+#include "sane_ctype.h"
+
 /*
  * magic2 = "PERFILE2"
  * must be a numerical value to let the endianness
@@ -370,15 +380,11 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
                         struct perf_evlist *evlist __maybe_unused)
 {
        char buf[MAXPATHLEN];
-       char proc[32];
        u32 n;
        int i, ret;
 
-       /*
-        * actual atual path to perf binary
-        */
-       sprintf(proc, "/proc/%d/exe", getpid());
-       ret = readlink(proc, buf, sizeof(buf));
+       /* actual path to perf binary */
+       ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
        if (ret <= 0)
                return -1;
 
@@ -2274,6 +2280,9 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
        perf_header__process_sections(header, fd, &hd,
                                      perf_file_section__fprintf_info);
 
+       if (session->file->is_pipe)
+               return 0;
+
        fprintf(fp, "# missing features: ");
        for_each_clear_bit(bit, header->adds_features, HEADER_LAST_FEATURE) {
                if (bit)
index 2821f8d77e5208116cbd5832f9b9833d0764221e..1c88ad6425b8ce722a5fad4ebe0ee99509dc4462 100644 (file)
@@ -1,21 +1,18 @@
 #include "cache.h"
 #include "config.h"
+#include <poll.h>
 #include <stdio.h>
 #include <subcmd/help.h>
 #include "../builtin.h"
 #include "levenshtein.h"
 
 static int autocorrect;
-static struct cmdnames aliases;
 
 static int perf_unknown_cmd_config(const char *var, const char *value,
                                   void *cb __maybe_unused)
 {
        if (!strcmp(var, "help.autocorrect"))
                autocorrect = perf_config_int(var,value);
-       /* Also use aliases for command lookup */
-       if (!prefixcmp(var, "alias."))
-               add_cmdname(&aliases, var + 6, strlen(var + 6));
 
        return 0;
 }
@@ -59,14 +56,12 @@ const char *help_unknown_cmd(const char *cmd)
 
        memset(&main_cmds, 0, sizeof(main_cmds));
        memset(&other_cmds, 0, sizeof(main_cmds));
-       memset(&aliases, 0, sizeof(aliases));
 
        perf_config(perf_unknown_cmd_config, NULL);
 
        load_command_list("perf-", &main_cmds, &other_cmds);
 
-       if (add_cmd_list(&main_cmds, &aliases) < 0 ||
-           add_cmd_list(&main_cmds, &other_cmds) < 0) {
+       if (add_cmd_list(&main_cmds, &other_cmds) < 0) {
                fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n");
                goto end;
        }
index eaf72a938fb423ed4ba46982c69324d2341839bc..cf0186a088c17f90c2357f1694af2241addf4eef 100644 (file)
@@ -3,12 +3,17 @@
 #include "hist.h"
 #include "map.h"
 #include "session.h"
+#include "namespaces.h"
 #include "sort.h"
 #include "evlist.h"
 #include "evsel.h"
 #include "annotate.h"
+#include "srcline.h"
+#include "thread.h"
 #include "ui/progress.h"
+#include <errno.h>
 #include <math.h>
+#include <sys/param.h>
 
 static bool hists__filter_entry_by_dso(struct hists *hists,
                                       struct hist_entry *he);
@@ -169,6 +174,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
                hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
        }
 
+       hists__new_col_len(hists, HISTC_CGROUP_ID, 20);
        hists__new_col_len(hists, HISTC_CPU, 3);
        hists__new_col_len(hists, HISTC_SOCKET, 6);
        hists__new_col_len(hists, HISTC_MEM_LOCKED, 6);
@@ -574,9 +580,14 @@ __hists__add_entry(struct hists *hists,
                   bool sample_self,
                   struct hist_entry_ops *ops)
 {
+       struct namespaces *ns = thread__namespaces(al->thread);
        struct hist_entry entry = {
                .thread = al->thread,
                .comm = thread__comm(al->thread),
+               .cgroup_id = {
+                       .dev = ns ? ns->link_info[CGROUP_NS_INDEX].dev : 0,
+                       .ino = ns ? ns->link_info[CGROUP_NS_INDEX].ino : 0,
+               },
                .ms = {
                        .map    = al->map,
                        .sym    = al->sym,
@@ -1129,6 +1140,11 @@ void hist_entry__delete(struct hist_entry *he)
                zfree(&he->mem_info);
        }
 
+       if (he->inline_node) {
+               inline_node__delete(he->inline_node);
+               he->inline_node = NULL;
+       }
+
        zfree(&he->stat_acc);
        free_srcline(he->srcline);
        if (he->srcfile && he->srcfile[0])
@@ -2447,7 +2463,7 @@ int parse_filter_percentage(const struct option *opt __maybe_unused,
        else if (!strcmp(arg, "absolute"))
                symbol_conf.filter_relative = false;
        else {
-               pr_debug("Invalud percentage: %s\n", arg);
+               pr_debug("Invalid percentage: %s\n", arg);
                return -1;
        }
 
index 28c216e3d5b72557825a8918ab2aa6d6369c40f8..ee3670a388df8f825fd6c79cb698e5fb6d7e5695 100644 (file)
@@ -30,6 +30,7 @@ enum hist_column {
        HISTC_DSO,
        HISTC_THREAD,
        HISTC_COMM,
+       HISTC_CGROUP_ID,
        HISTC_PARENT,
        HISTC_CPU,
        HISTC_SOCKET,
@@ -57,6 +58,7 @@ enum hist_column {
        HISTC_SRCLINE_FROM,
        HISTC_SRCLINE_TO,
        HISTC_TRACE,
+       HISTC_SYM_SIZE,
        HISTC_NR_COLS, /* Last entry */
 };
 
index 6c2eb5da4afc0d290786881ebd9a7d9c5f83775f..b2834ac7b1f558fd8ecbf4b680cfa0d290ab5987 100644 (file)
@@ -14,7 +14,9 @@
  */
 
 #include <endian.h>
+#include <errno.h>
 #include <byteswap.h>
+#include <inttypes.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/bitops.h>
index 4f3c758d875d6ce6855db7fa0731436f9bb06671..54818828023bf4ad0960165d26afce60fe7166d1 100644 (file)
@@ -26,6 +26,7 @@
 #include "insn.c"
 
 #include "intel-pt-insn-decoder.h"
+#include "dump-insn.h"
 
 #if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE || INTEL_PT_INSN_BUF_SZ > MAX_INSN
 #error Instruction buffer size too small
@@ -39,6 +40,8 @@ static void intel_pt_insn_decoder(struct insn *insn,
        enum intel_pt_insn_branch branch = INTEL_PT_BR_NO_BRANCH;
        int ext;
 
+       intel_pt_insn->rel = 0;
+
        if (insn_is_avx(insn)) {
                intel_pt_insn->op = INTEL_PT_OP_OTHER;
                intel_pt_insn->branch = INTEL_PT_BR_NO_BRANCH;
@@ -177,6 +180,29 @@ int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
        return 0;
 }
 
+const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused,
+                     u8 *inbuf, int inlen, int *lenp)
+{
+       struct insn insn;
+       int n, i;
+       int left;
+
+       insn_init(&insn, inbuf, inlen, x->is64bit);
+       insn_get_length(&insn);
+       if (!insn_complete(&insn) || insn.length > inlen)
+               return "<bad>";
+       if (lenp)
+               *lenp = insn.length;
+       left = sizeof(x->out);
+       n = snprintf(x->out, left, "insn: ");
+       left -= n;
+       for (i = 0; i < insn.length; i++) {
+               n += snprintf(x->out + n, left, "%02x ", inbuf[i]);
+               left -= n;
+       }
+       return x->out;
+}
+
 const char *branch_name[] = {
        [INTEL_PT_OP_OTHER]     = "Other",
        [INTEL_PT_OP_CALL]      = "Call",
index da20cd5612e97f53853a3fdfb79502cdfa5d3a6b..4c7718f87a0890ee64e2f78e0b97291b67ecf33e 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include <errno.h>
@@ -22,6 +23,7 @@
 #include "../perf.h"
 #include "session.h"
 #include "machine.h"
+#include "memswap.h"
 #include "sort.h"
 #include "tool.h"
 #include "event.h"
index c9a941ef0f6dde0c88da23a6d233d120646c3257..9084930e17571f890710a63dbdd885b9ee65a2aa 100644 (file)
@@ -1,5 +1,6 @@
 #include <sys/sysmacros.h>
 #include <sys/types.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <byteswap.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <linux/stringify.h>
 
 #include "util.h"
 #include "event.h"
 #include "debug.h"
 #include "evlist.h"
 #include "symbol.h"
-#include "strlist.h"
 #include <elf.h>
 
 #include "tsc.h"
@@ -25,6 +26,8 @@
 #include "genelf.h"
 #include "../builtin.h"
 
+#include "sane_ctype.h"
+
 struct jit_buf_desc {
        struct perf_data_file *output;
        struct perf_session *session;
@@ -181,7 +184,7 @@ jit_open(struct jit_buf_desc *jd, const char *name)
                        jd->use_arch_timestamp);
 
        if (header.version > JITHEADER_VERSION) {
-               pr_err("wrong jitdump version %u, expected " STR(JITHEADER_VERSION),
+               pr_err("wrong jitdump version %u, expected " __stringify(JITHEADER_VERSION),
                        header.version);
                goto error;
        }
index 824356488ce6a8c7d9ecda1748456b262f0a7114..c6a15f204c03827bec7fa4cfdf879d8d9d5b89fc 100644 (file)
@@ -12,6 +12,7 @@
 #include "llvm-utils.h"
 #include "config.h"
 #include "util.h"
+#include <sys/wait.h>
 
 #define CLANG_BPF_CMD_DEFAULT_TEMPLATE                         \
                "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
index 9ddea5cecd94b57f9d177f94f447d89f4716a5a8..4ca7c5c6cdcd0a9e2aeeefad5cd08c9fe9020c8f 100644 (file)
@@ -1,6 +1,8 @@
+#include <errno.h>
 #include <lzma.h>
 #include <stdio.h>
 #include <linux/compiler.h>
+#include "compress.h"
 #include "util.h"
 #include "debug.h"
 
index 71c9720d49730066dc1100defee124a4d3c198b9..d97e014c3df395e51e61da31f9624e12927a43b2 100644 (file)
@@ -1,3 +1,7 @@
+#include <dirent.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <regex.h>
 #include "callchain.h"
 #include "debug.h"
 #include "event.h"
 #include "thread.h"
 #include "vdso.h"
 #include <stdbool.h>
-#include <symbol/kallsyms.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 #include "unwind.h"
 #include "linux/hash.h"
+#include "asm/bug.h"
+
+#include "sane_ctype.h"
+#include <symbol/kallsyms.h>
 
 static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
 
@@ -501,6 +511,37 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
        return err;
 }
 
+int machine__process_namespaces_event(struct machine *machine __maybe_unused,
+                                     union perf_event *event,
+                                     struct perf_sample *sample __maybe_unused)
+{
+       struct thread *thread = machine__findnew_thread(machine,
+                                                       event->namespaces.pid,
+                                                       event->namespaces.tid);
+       int err = 0;
+
+       WARN_ONCE(event->namespaces.nr_namespaces > NR_NAMESPACES,
+                 "\nWARNING: kernel seems to support more namespaces than perf"
+                 " tool.\nTry updating the perf tool..\n\n");
+
+       WARN_ONCE(event->namespaces.nr_namespaces < NR_NAMESPACES,
+                 "\nWARNING: perf tool seems to support more namespaces than"
+                 " the kernel.\nTry updating the kernel..\n\n");
+
+       if (dump_trace)
+               perf_event__fprintf_namespaces(event, stdout);
+
+       if (thread == NULL ||
+           thread__set_namespaces(thread, sample->time, &event->namespaces)) {
+               dump_printf("problem processing PERF_RECORD_NAMESPACES, skipping event.\n");
+               err = -1;
+       }
+
+       thread__put(thread);
+
+       return err;
+}
+
 int machine__process_lost_event(struct machine *machine __maybe_unused,
                                union perf_event *event, struct perf_sample *sample __maybe_unused)
 {
@@ -755,11 +796,11 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
  * Returns the name of the start symbol in *symbol_name. Pass in NULL as
  * symbol_name if it's not that important.
  */
-static u64 machine__get_running_kernel_start(struct machine *machine,
-                                            const char **symbol_name)
+static int machine__get_running_kernel_start(struct machine *machine,
+                                            const char **symbol_name, u64 *start)
 {
        char filename[PATH_MAX];
-       int i;
+       int i, err = -1;
        const char *name;
        u64 addr = 0;
 
@@ -769,21 +810,28 @@ static u64 machine__get_running_kernel_start(struct machine *machine,
                return 0;
 
        for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
-               addr = kallsyms__get_function_start(filename, name);
-               if (addr)
+               err = kallsyms__get_function_start(filename, name, &addr);
+               if (!err)
                        break;
        }
 
+       if (err)
+               return -1;
+
        if (symbol_name)
                *symbol_name = name;
 
-       return addr;
+       *start = addr;
+       return 0;
 }
 
 int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
 {
        int type;
-       u64 start = machine__get_running_kernel_start(machine, NULL);
+       u64 start = 0;
+
+       if (machine__get_running_kernel_start(machine, NULL, &start))
+               return -1;
 
        /* In case of renewal the kernel map, destroy previous one */
        machine__destroy_kernel_maps(machine);
@@ -1144,8 +1192,8 @@ static int machine__create_modules(struct machine *machine)
 int machine__create_kernel_maps(struct machine *machine)
 {
        struct dso *kernel = machine__get_kernel(machine);
-       const char *name;
-       u64 addr;
+       const char *name = NULL;
+       u64 addr = 0;
        int ret;
 
        if (kernel == NULL)
@@ -1170,8 +1218,7 @@ int machine__create_kernel_maps(struct machine *machine)
         */
        map_groups__fixup_end(&machine->kmaps);
 
-       addr = machine__get_running_kernel_start(machine, &name);
-       if (!addr) {
+       if (machine__get_running_kernel_start(machine, &name, &addr)) {
        } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
                machine__destroy_kernel_maps(machine);
                return -1;
@@ -1439,7 +1486,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
        if (machine->last_match == th)
                machine->last_match = NULL;
 
-       BUG_ON(atomic_read(&th->refcnt) == 0);
+       BUG_ON(refcount_read(&th->refcnt) == 0);
        if (lock)
                pthread_rwlock_wrlock(&machine->threads_lock);
        rb_erase_init(&th->rb_node, &machine->threads);
@@ -1538,6 +1585,8 @@ int machine__process_event(struct machine *machine, union perf_event *event,
                ret = machine__process_comm_event(machine, event, sample); break;
        case PERF_RECORD_MMAP:
                ret = machine__process_mmap_event(machine, event, sample); break;
+       case PERF_RECORD_NAMESPACES:
+               ret = machine__process_namespaces_event(machine, event, sample); break;
        case PERF_RECORD_MMAP2:
                ret = machine__process_mmap2_event(machine, event, sample); break;
        case PERF_RECORD_FORK:
index a28305029711c08f56c89385c85fa49611e55aa3..3cdb1340f9170ad388e827b218fae3cd541502fc 100644 (file)
@@ -97,6 +97,9 @@ int machine__process_itrace_start_event(struct machine *machine,
                                        union perf_event *event);
 int machine__process_switch_event(struct machine *machine,
                                  union perf_event *event);
+int machine__process_namespaces_event(struct machine *machine,
+                                     union perf_event *event,
+                                     struct perf_sample *sample);
 int machine__process_mmap_event(struct machine *machine, union perf_event *event,
                                struct perf_sample *sample);
 int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
index 0a943e7b1ea7fc745485f016875395e91feca8c8..2179b2deb7307c749fb171e48c784e4bc158b028 100644 (file)
@@ -9,13 +9,13 @@
 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
 #include "map.h"
 #include "thread.h"
-#include "strlist.h"
 #include "vdso.h"
 #include "build-id.h"
 #include "util.h"
 #include "debug.h"
 #include "machine.h"
 #include <linux/string.h>
+#include "srcline.h"
 #include "unwind.h"
 
 static void __maps__insert(struct maps *maps, struct map *map);
@@ -141,7 +141,7 @@ void map__init(struct map *map, enum map_type type,
        RB_CLEAR_NODE(&map->rb_node);
        map->groups   = NULL;
        map->erange_warned = false;
-       atomic_set(&map->refcnt, 1);
+       refcount_set(&map->refcnt, 1);
 }
 
 struct map *map__new(struct machine *machine, u64 start, u64 len,
@@ -255,7 +255,7 @@ void map__delete(struct map *map)
 
 void map__put(struct map *map)
 {
-       if (map && atomic_dec_and_test(&map->refcnt))
+       if (map && refcount_dec_and_test(&map->refcnt))
                map__delete(map);
 }
 
@@ -325,11 +325,6 @@ int map__load(struct map *map)
        return 0;
 }
 
-int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
-{
-       return strcmp(namea, nameb);
-}
-
 struct symbol *map__find_symbol(struct map *map, u64 addr)
 {
        if (map__load(map) < 0)
@@ -354,7 +349,7 @@ struct map *map__clone(struct map *from)
        struct map *map = memdup(from, sizeof(*map));
 
        if (map != NULL) {
-               atomic_set(&map->refcnt, 1);
+               refcount_set(&map->refcnt, 1);
                RB_CLEAR_NODE(&map->rb_node);
                dso__get(map->dso);
                map->groups = NULL;
@@ -405,7 +400,8 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
 
        if (map && map->dso) {
                srcline = get_srcline(map->dso,
-                                     map__rip_2objdump(map, addr), NULL, true);
+                                     map__rip_2objdump(map, addr), NULL,
+                                     true, true);
                if (srcline != SRCLINE_UNKNOWN)
                        ret = fprintf(fp, "%s%s", prefix, srcline);
                free_srcline(srcline);
@@ -485,7 +481,7 @@ void map_groups__init(struct map_groups *mg, struct machine *machine)
                maps__init(&mg->maps[i]);
        }
        mg->machine = machine;
-       atomic_set(&mg->refcnt, 1);
+       refcount_set(&mg->refcnt, 1);
 }
 
 static void __maps__purge(struct maps *maps)
@@ -547,7 +543,7 @@ void map_groups__delete(struct map_groups *mg)
 
 void map_groups__put(struct map_groups *mg)
 {
-       if (mg && atomic_dec_and_test(&mg->refcnt))
+       if (mg && refcount_dec_and_test(&mg->refcnt))
                map_groups__delete(mg);
 }
 
index abdacf800c98a78148565f23b7d9b4c916cbacaf..f9e8ac8a52cde5fefb74cb87464c1346e3d08431 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __PERF_MAP_H
 #define __PERF_MAP_H
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/compiler.h>
 #include <linux/list.h>
 #include <linux/rbtree.h>
@@ -51,7 +51,7 @@ struct map {
 
        struct dso              *dso;
        struct map_groups       *groups;
-       atomic_t                refcnt;
+       refcount_t              refcnt;
 };
 
 struct kmap {
@@ -67,7 +67,7 @@ struct maps {
 struct map_groups {
        struct maps      maps[MAP__NR_TYPES];
        struct machine   *machine;
-       atomic_t         refcnt;
+       refcount_t       refcnt;
 };
 
 struct map_groups *map_groups__new(struct machine *machine);
@@ -77,7 +77,7 @@ bool map_groups__empty(struct map_groups *mg);
 static inline struct map_groups *map_groups__get(struct map_groups *mg)
 {
        if (mg)
-               atomic_inc(&mg->refcnt);
+               refcount_inc(&mg->refcnt);
        return mg;
 }
 
@@ -130,13 +130,14 @@ struct thread;
  */
 #define __map__for_each_symbol_by_name(map, sym_name, pos)     \
        for (pos = map__find_symbol_by_name(map, sym_name);     \
-            pos && arch__compare_symbol_names(pos->name, sym_name) == 0;       \
+            pos &&                                             \
+            !symbol__match_symbol_name(pos->name, sym_name,    \
+                                       SYMBOL_TAG_INCLUDE__DEFAULT_ONLY); \
             pos = symbol__next_by_name(pos))
 
 #define map__for_each_symbol_by_name(map, sym_name, pos)               \
        __map__for_each_symbol_by_name(map, sym_name, (pos))
 
-int arch__compare_symbol_names(const char *namea, const char *nameb);
 void map__init(struct map *map, enum map_type type,
               u64 start, u64 end, u64 pgoff, struct dso *dso);
 struct map *map__new(struct machine *machine, u64 start, u64 len,
@@ -150,7 +151,7 @@ struct map *map__clone(struct map *map);
 static inline struct map *map__get(struct map *map)
 {
        if (map)
-               atomic_inc(&map->refcnt);
+               refcount_inc(&map->refcnt);
        return map;
 }
 
index 1d4ab53c60cae7b8075dd1bc3a0f1f37a3d9f08a..06f5a3a4295c52cac138ac2526afdac04ffbf0dc 100644 (file)
@@ -6,6 +6,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <api/fs/fs.h>
+#include <linux/kernel.h>
 #include "mem-events.h"
 #include "debug.h"
 #include "symbol.h"
@@ -205,8 +206,8 @@ int perf_mem__lvl_scnprintf(char *out, size_t sz, struct mem_info *mem_info)
 static const char * const snoop_access[] = {
        "N/A",
        "None",
-       "Miss",
        "Hit",
+       "Miss",
        "HitM",
 };
 
diff --git a/tools/perf/util/memswap.c b/tools/perf/util/memswap.c
new file mode 100644 (file)
index 0000000..55f7faa
--- /dev/null
@@ -0,0 +1,24 @@
+#include <byteswap.h>
+#include "memswap.h"
+#include <linux/types.h>
+
+void mem_bswap_32(void *src, int byte_size)
+{
+       u32 *m = src;
+       while (byte_size > 0) {
+               *m = bswap_32(*m);
+               byte_size -= sizeof(u32);
+               ++m;
+       }
+}
+
+void mem_bswap_64(void *src, int byte_size)
+{
+       u64 *m = src;
+
+       while (byte_size > 0) {
+               *m = bswap_64(*m);
+               byte_size -= sizeof(u64);
+               ++m;
+       }
+}
diff --git a/tools/perf/util/memswap.h b/tools/perf/util/memswap.h
new file mode 100644 (file)
index 0000000..7d1b1c3
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef PERF_MEMSWAP_H_
+#define PERF_MEMSWAP_H_
+
+void mem_bswap_64(void *src, int byte_size);
+void mem_bswap_32(void *src, int byte_size);
+
+#endif /* PERF_MEMSWAP_H_ */
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
new file mode 100644 (file)
index 0000000..67dcbcc
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (C) 2017 Hari Bathini, IBM Corporation
+ */
+
+#include "namespaces.h"
+#include "util.h"
+#include "event.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+struct namespaces *namespaces__new(struct namespaces_event *event)
+{
+       struct namespaces *namespaces;
+       u64 link_info_size = ((event ? event->nr_namespaces : NR_NAMESPACES) *
+                             sizeof(struct perf_ns_link_info));
+
+       namespaces = zalloc(sizeof(struct namespaces) + link_info_size);
+       if (!namespaces)
+               return NULL;
+
+       namespaces->end_time = -1;
+
+       if (event)
+               memcpy(namespaces->link_info, event->link_info, link_info_size);
+
+       return namespaces;
+}
+
+void namespaces__free(struct namespaces *namespaces)
+{
+       free(namespaces);
+}
diff --git a/tools/perf/util/namespaces.h b/tools/perf/util/namespaces.h
new file mode 100644 (file)
index 0000000..468f1e9
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (C) 2017 Hari Bathini, IBM Corporation
+ */
+
+#ifndef __PERF_NAMESPACES_H
+#define __PERF_NAMESPACES_H
+
+#include "../perf.h"
+#include <linux/list.h>
+
+struct namespaces_event;
+
+struct namespaces {
+       struct list_head list;
+       u64 end_time;
+       struct perf_ns_link_info link_info[];
+};
+
+struct namespaces *namespaces__new(struct namespaces_event *event);
+void namespaces__free(struct namespaces *namespaces);
+
+#endif  /* __PERF_NAMESPACES_H */
index fe84df1875aa9e231d63d56ba3417f242ea4e3b7..4de398cfb577177af2a2bff7a4212a5f569b1ee5 100644 (file)
@@ -1,3 +1,5 @@
+#include <errno.h>
+#include <inttypes.h>
 #include <linux/list.h>
 #include <linux/compiler.h>
 #include <linux/string.h>
@@ -79,7 +81,7 @@ static union perf_event *dup_event(struct ordered_events *oe,
 
 static void free_dup_event(struct ordered_events *oe, union perf_event *event)
 {
-       if (oe->copy_on_queue) {
+       if (event && oe->copy_on_queue) {
                oe->cur_alloc_size -= event->header.size;
                free(event);
        }
@@ -150,6 +152,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
        list_move(&event->list, &oe->cache);
        oe->nr_events--;
        free_dup_event(oe, event->event);
+       event->event = NULL;
 }
 
 int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
index 67a8aebc67ab492a9936ad56ae9655526f9d9781..01e779b91c8ef618984fcdb8d68d526b1870828a 100644 (file)
@@ -1,13 +1,18 @@
 #include <linux/hw_breakpoint.h>
 #include <linux/err.h>
-#include "util.h"
+#include <dirent.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include "term.h"
 #include "../perf.h"
 #include "evlist.h"
 #include "evsel.h"
 #include <subcmd/parse-options.h>
 #include "parse-events.h"
 #include <subcmd/exec-cmd.h>
-#include "string.h"
+#include "string2.h"
+#include "strlist.h"
 #include "symbol.h"
 #include "cache.h"
 #include "header.h"
@@ -316,8 +321,9 @@ __add_event(struct list_head *list, int *idx,
                return NULL;
 
        (*idx)++;
-       evsel->cpus     = cpu_map__get(cpus);
-       evsel->own_cpus = cpu_map__get(cpus);
+       evsel->cpus        = cpu_map__get(cpus);
+       evsel->own_cpus    = cpu_map__get(cpus);
+       evsel->system_wide = !!cpus;
 
        if (name)
                evsel->name = strdup(name);
@@ -1254,11 +1260,59 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
                evsel->scale = info.scale;
                evsel->per_pkg = info.per_pkg;
                evsel->snapshot = info.snapshot;
+               evsel->metric_expr = info.metric_expr;
+               evsel->metric_name = info.metric_name;
        }
 
        return evsel ? 0 : -ENOMEM;
 }
 
+int parse_events_multi_pmu_add(struct parse_events_evlist *data,
+                              char *str, struct list_head **listp)
+{
+       struct list_head *head;
+       struct parse_events_term *term;
+       struct list_head *list;
+       struct perf_pmu *pmu = NULL;
+       int ok = 0;
+
+       *listp = NULL;
+       /* Add it for all PMUs that support the alias */
+       list = malloc(sizeof(struct list_head));
+       if (!list)
+               return -1;
+       INIT_LIST_HEAD(list);
+       while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+               struct perf_pmu_alias *alias;
+
+               list_for_each_entry(alias, &pmu->aliases, list) {
+                       if (!strcasecmp(alias->name, str)) {
+                               head = malloc(sizeof(struct list_head));
+                               if (!head)
+                                       return -1;
+                               INIT_LIST_HEAD(head);
+                               if (parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
+                                                          str, 1, false, &str, NULL) < 0)
+                                       return -1;
+                               list_add_tail(&term->list, head);
+
+                               if (!parse_events_add_pmu(data, list,
+                                                 pmu->name, head)) {
+                                       pr_debug("%s -> %s/%s/\n", str,
+                                                pmu->name, alias->str);
+                                       ok++;
+                               }
+
+                               parse_events_terms__delete(head);
+                       }
+               }
+       }
+       if (!ok)
+               return -1;
+       *listp = list;
+       return 0;
+}
+
 int parse_events__modifier_group(struct list_head *list,
                                 char *event_mod)
 {
@@ -2276,7 +2330,7 @@ out_enomem:
  * Print the help text for the event symbols:
  */
 void print_events(const char *event_glob, bool name_only, bool quiet_flag,
-                       bool long_desc)
+                       bool long_desc, bool details_flag)
 {
        print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
                            event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
@@ -2286,7 +2340,8 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag,
 
        print_hwcache_events(event_glob, name_only);
 
-       print_pmu_events(event_glob, name_only, quiet_flag, long_desc);
+       print_pmu_events(event_glob, name_only, quiet_flag, long_desc,
+                       details_flag);
 
        if (event_glob != NULL)
                return;
@@ -2415,6 +2470,31 @@ int parse_events_term__clone(struct parse_events_term **new,
        return new_term(new, &temp, term->val.str, term->val.num);
 }
 
+int parse_events_copy_term_list(struct list_head *old,
+                                struct list_head **new)
+{
+       struct parse_events_term *term, *n;
+       int ret;
+
+       if (!old) {
+               *new = NULL;
+               return 0;
+       }
+
+       *new = malloc(sizeof(struct list_head));
+       if (!*new)
+               return -ENOMEM;
+       INIT_LIST_HEAD(*new);
+
+       list_for_each_entry (term, old, list) {
+               ret = parse_events_term__clone(&n, term);
+               if (ret)
+                       return ret;
+               list_add_tail(&n->list, *new);
+       }
+       return 0;
+}
+
 void parse_events_terms__purge(struct list_head *terms)
 {
        struct parse_events_term *term, *h;
index 1af6a267c21bfd3a437e3bed1f2122f96c4dced7..a235f4d6d5e514f60055db58ce5ebb0b8e723d0b 100644 (file)
@@ -8,6 +8,7 @@
 #include <stdbool.h>
 #include <linux/types.h>
 #include <linux/perf_event.h>
+#include <string.h>
 
 struct list_head;
 struct perf_evsel;
@@ -166,6 +167,14 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
 int parse_events_add_pmu(struct parse_events_evlist *data,
                         struct list_head *list, char *name,
                         struct list_head *head_config);
+
+int parse_events_multi_pmu_add(struct parse_events_evlist *data,
+                              char *str,
+                              struct list_head **listp);
+
+int parse_events_copy_term_list(struct list_head *old,
+                                struct list_head **new);
+
 enum perf_pmu_event_symbol_type
 perf_pmu__parse_check(const char *name);
 void parse_events__set_leader(char *name, struct list_head *list);
@@ -175,7 +184,7 @@ void parse_events_evlist_error(struct parse_events_evlist *data,
                               int idx, const char *str);
 
 void print_events(const char *event_glob, bool name_only, bool quiet,
-                 bool long_desc);
+                 bool long_desc, bool details_flag);
 
 struct event_symbol {
        const char      *symbol;
@@ -196,4 +205,23 @@ int is_valid_tracepoint(const char *event_string);
 int valid_event_mount(const char *eventfs);
 char *parse_events_formats_error_string(char *additional_terms);
 
+#ifdef HAVE_LIBELF_SUPPORT
+/*
+ * If the probe point starts with '%',
+ * or starts with "sdt_" and has a ':' but no '=',
+ * then it should be a SDT/cached probe point.
+ */
+static inline bool is_sdt_event(char *str)
+{
+       return (str[0] == '%' ||
+               (!strncmp(str, "sdt_", 4) &&
+                !!strchr(str, ':') && !strchr(str, '=')));
+}
+#else
+static inline bool is_sdt_event(char *str __maybe_unused)
+{
+       return false;
+}
+#endif /* HAVE_LIBELF_SUPPORT */
+
 #endif /* __PERF_PARSE_EVENTS_H */
index 30f018ea137096c22d6798e4bcd7723373db26af..04fd8c9af9f9578c0f8f44a3c8cb05cf087d992f 100644 (file)
@@ -226,68 +226,55 @@ event_pmu:
 PE_NAME opt_event_config
 {
        struct parse_events_evlist *data = _data;
-       struct list_head *list;
+       struct list_head *list, *orig_terms, *terms;
+
+       if (parse_events_copy_term_list($2, &orig_terms))
+               YYABORT;
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_pmu(data, list, $1, $2));
+       if (parse_events_add_pmu(data, list, $1, $2)) {
+               struct perf_pmu *pmu = NULL;
+               int ok = 0;
+
+               while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+                       char *name = pmu->name;
+
+                       if (!strncmp(name, "uncore_", 7) &&
+                           strncmp($1, "uncore_", 7))
+                               name += 7;
+                       if (!strncmp($1, name, strlen($1))) {
+                               if (parse_events_copy_term_list(orig_terms, &terms))
+                                       YYABORT;
+                               if (!parse_events_add_pmu(data, list, pmu->name, terms))
+                                       ok++;
+                               parse_events_terms__delete(terms);
+                       }
+               }
+               if (!ok)
+                       YYABORT;
+       }
        parse_events_terms__delete($2);
+       parse_events_terms__delete(orig_terms);
        $$ = list;
 }
 |
 PE_KERNEL_PMU_EVENT sep_dc
 {
-       struct parse_events_evlist *data = _data;
-       struct list_head *head;
-       struct parse_events_term *term;
        struct list_head *list;
-       struct perf_pmu *pmu = NULL;
-       int ok = 0;
-
-       /* Add it for all PMUs that support the alias */
-       ALLOC_LIST(list);
-       while ((pmu = perf_pmu__scan(pmu)) != NULL) {
-               struct perf_pmu_alias *alias;
-
-               list_for_each_entry(alias, &pmu->aliases, list) {
-                       if (!strcasecmp(alias->name, $1)) {
-                               ALLOC_LIST(head);
-                               ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
-                                       $1, 1, false, &@1, NULL));
-                               list_add_tail(&term->list, head);
-
-                               if (!parse_events_add_pmu(data, list,
-                                                 pmu->name, head)) {
-                                       pr_debug("%s -> %s/%s/\n", $1,
-                                                pmu->name, alias->str);
-                                       ok++;
-                               }
 
-                               parse_events_terms__delete(head);
-                       }
-               }
-       }
-       if (!ok)
+       if (parse_events_multi_pmu_add(_data, $1, &list) < 0)
                YYABORT;
        $$ = list;
 }
 |
 PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
 {
-       struct parse_events_evlist *data = _data;
-       struct list_head *head;
-       struct parse_events_term *term;
        struct list_head *list;
        char pmu_name[128];
-       snprintf(&pmu_name, 128, "%s-%s", $1, $3);
 
-       ALLOC_LIST(head);
-       ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
-                                       &pmu_name, 1, false, &@1, NULL));
-       list_add_tail(&term->list, head);
-
-       ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
-       parse_events_terms__delete(head);
+       snprintf(&pmu_name, 128, "%s-%s", $1, $3);
+       if (parse_events_multi_pmu_add(_data, pmu_name, &list) < 0)
+               YYABORT;
        $$ = list;
 }
 
index 7c7630be5a897d651bbda7eaf2e0c4addcf95a03..50ec3bc87a60442570d6e5a5d27acffc4e06ba26 100644 (file)
  * which is what it's designed for.
  */
 #include "cache.h"
-#include "util.h"
+#include "path.h"
+#include <linux/kernel.h>
 #include <limits.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 static char bad_path[] = "/bad-path/";
 /*
@@ -50,3 +55,24 @@ char *mkpath(const char *fmt, ...)
                return bad_path;
        return cleanup_path(pathname);
 }
+
+int path__join(char *bf, size_t size, const char *path1, const char *path2)
+{
+       return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2);
+}
+
+int path__join3(char *bf, size_t size, const char *path1, const char *path2, const char *path3)
+{
+       return scnprintf(bf, size, "%s%s%s%s%s", path1, path1[0] ? "/" : "",
+                        path2, path2[0] ? "/" : "", path3);
+}
+
+bool is_regular_file(const char *file)
+{
+       struct stat st;
+
+       if (stat(file, &st))
+               return false;
+
+       return S_ISREG(st.st_mode);
+}
diff --git a/tools/perf/util/path.h b/tools/perf/util/path.h
new file mode 100644 (file)
index 0000000..9a276a5
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _PERF_PATH_H
+#define _PERF_PATH_H
+
+int path__join(char *bf, size_t size, const char *path1, const char *path2);
+int path__join3(char *bf, size_t size, const char *path1, const char *path2, const char *path3);
+
+bool is_regular_file(const char *file);
+
+#endif /* _PERF_PATH_H */
index cb368306b12b7e023f1a2f3eb501529699f2fde6..d55092964da2f3fec32b61f6ef7906093d0945fe 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <setjmp.h>
 #include <linux/err.h>
+#include <linux/kernel.h>
 #include "util/util.h"
 #include "util/debug.h"
 #include "util/perf-hooks.h"
index c4023f22f287dd7fb6cdf4a395af2f0d631665fb..b2ae039eff85c4c7166fecaa713704edf952956c 100644 (file)
@@ -6,6 +6,12 @@ const struct sample_reg __weak sample_reg_masks[] = {
        SMPL_REG_END
 };
 
+int __weak arch_sdt_arg_parse_op(char *old_op __maybe_unused,
+                                char **new_op __maybe_unused)
+{
+       return SDT_ARG_SKIP;
+}
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
 {
index 679d6e493962267f7b219b88c05d06c61ef1d2ea..32b37d19dcc34b4bffffcdb0f755d4ea14cab55f 100644 (file)
@@ -15,6 +15,13 @@ struct sample_reg {
 
 extern const struct sample_reg sample_reg_masks[];
 
+enum {
+       SDT_ARG_VALID = 0,
+       SDT_ARG_SKIP,
+};
+
+int arch_sdt_arg_parse_op(char *old_op, char **new_op);
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
 
index 12f84dd2ac5dfddc9f7e124fa25b5da4bb2be021..ac16a9db1fb566ca14d272e33bc34e5166ea2b81 100644 (file)
@@ -1,6 +1,8 @@
 #include <linux/list.h>
 #include <linux/compiler.h>
 #include <sys/types.h>
+#include <errno.h>
+#include <sys/stat.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdbool.h>
@@ -15,6 +17,7 @@
 #include "header.h"
 #include "pmu-events/pmu-events.h"
 #include "cache.h"
+#include "string2.h"
 
 struct perf_pmu_format {
        char *name;
@@ -231,7 +234,9 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
 static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
                                 char *desc, char *val,
                                 char *long_desc, char *topic,
-                                char *unit, char *perpkg)
+                                char *unit, char *perpkg,
+                                char *metric_expr,
+                                char *metric_name)
 {
        struct perf_pmu_alias *alias;
        int ret;
@@ -265,6 +270,8 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
                perf_pmu__parse_snapshot(alias, dir, name);
        }
 
+       alias->metric_expr = metric_expr ? strdup(metric_expr) : NULL;
+       alias->metric_name = metric_name ? strdup(metric_name): NULL;
        alias->desc = desc ? strdup(desc) : NULL;
        alias->long_desc = long_desc ? strdup(long_desc) :
                                desc ? strdup(desc) : NULL;
@@ -294,7 +301,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
        buf[ret] = 0;
 
        return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
-                                    NULL);
+                                    NULL, NULL, NULL);
 }
 
 static inline bool pmu_alias_info_file(char *name)
@@ -564,7 +571,9 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
                __perf_pmu__new_alias(head, NULL, (char *)pe->name,
                                (char *)pe->desc, (char *)pe->event,
                                (char *)pe->long_desc, (char *)pe->topic,
-                               (char *)pe->unit, (char *)pe->perpkg);
+                               (char *)pe->unit, (char *)pe->perpkg,
+                               (char *)pe->metric_expr,
+                               (char *)pe->metric_name);
        }
 
 out:
@@ -991,6 +1000,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
        info->unit     = NULL;
        info->scale    = 0.0;
        info->snapshot = false;
+       info->metric_expr = NULL;
+       info->metric_name = NULL;
 
        list_for_each_entry_safe(term, h, head_terms, list) {
                alias = pmu_find_alias(pmu, term);
@@ -1006,6 +1017,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
 
                if (alias->per_pkg)
                        info->per_pkg = true;
+               info->metric_expr = alias->metric_expr;
+               info->metric_name = alias->metric_name;
 
                list_del(&term->list);
                free(term);
@@ -1100,6 +1113,8 @@ struct sevent {
        char *topic;
        char *str;
        char *pmu;
+       char *metric_expr;
+       char *metric_name;
 };
 
 static int cmp_sevent(const void *a, const void *b)
@@ -1136,13 +1151,12 @@ static void wordwrap(char *s, int start, int max, int corr)
                        break;
                s += wlen;
                column += n;
-               while (isspace(*s))
-                       s++;
+               s = ltrim(s);
        }
 }
 
 void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
-                       bool long_desc)
+                       bool long_desc, bool details_flag)
 {
        struct perf_pmu *pmu;
        struct perf_pmu_alias *alias;
@@ -1198,6 +1212,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
                        aliases[j].topic = alias->topic;
                        aliases[j].str = alias->str;
                        aliases[j].pmu = pmu->name;
+                       aliases[j].metric_expr = alias->metric_expr;
+                       aliases[j].metric_name = alias->metric_name;
                        j++;
                }
                if (pmu->selectable &&
@@ -1232,8 +1248,14 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
                        printf("%*s", 8, "[");
                        wordwrap(aliases[j].desc, 8, columns, 0);
                        printf("]\n");
-                       if (verbose > 0)
-                               printf("%*s%s/%s/\n", 8, "", aliases[j].pmu, aliases[j].str);
+                       if (details_flag) {
+                               printf("%*s%s/%s/ ", 8, "", aliases[j].pmu, aliases[j].str);
+                               if (aliases[j].metric_name)
+                                       printf(" MetricName: %s", aliases[j].metric_name);
+                               if (aliases[j].metric_expr)
+                                       printf(" MetricExpr: %s", aliases[j].metric_expr);
+                               putchar('\n');
+                       }
                } else
                        printf("  %-50s [Kernel PMU event]\n", aliases[j].name);
                printed++;
index 00852ddc7741b068e212adf2eb3e5e2b0c56c872..ea7f450dc60928ab46e2288cf3acbdd35b31af38 100644 (file)
@@ -31,6 +31,8 @@ struct perf_pmu {
 
 struct perf_pmu_info {
        const char *unit;
+       const char *metric_expr;
+       const char *metric_name;
        double scale;
        bool per_pkg;
        bool snapshot;
@@ -50,6 +52,8 @@ struct perf_pmu_alias {
        double scale;
        bool per_pkg;
        bool snapshot;
+       char *metric_expr;
+       char *metric_name;
 };
 
 struct perf_pmu *perf_pmu__find(const char *name);
@@ -76,7 +80,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);
 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
 
 void print_pmu_events(const char *event_glob, bool name_only, bool quiet,
-                     bool long_desc);
+                     bool long_desc, bool details_flag);
 bool pmu_have_event(const char *pname, const char *name);
 
 int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
diff --git a/tools/perf/util/print_binary.c b/tools/perf/util/print_binary.c
new file mode 100644 (file)
index 0000000..e908177
--- /dev/null
@@ -0,0 +1,55 @@
+#include "print_binary.h"
+#include <linux/log2.h>
+#include "sane_ctype.h"
+
+void print_binary(unsigned char *data, size_t len,
+                 size_t bytes_per_line, print_binary_t printer,
+                 void *extra)
+{
+       size_t i, j, mask;
+
+       if (!printer)
+               return;
+
+       bytes_per_line = roundup_pow_of_two(bytes_per_line);
+       mask = bytes_per_line - 1;
+
+       printer(BINARY_PRINT_DATA_BEGIN, 0, extra);
+       for (i = 0; i < len; i++) {
+               if ((i & mask) == 0) {
+                       printer(BINARY_PRINT_LINE_BEGIN, -1, extra);
+                       printer(BINARY_PRINT_ADDR, i, extra);
+               }
+
+               printer(BINARY_PRINT_NUM_DATA, data[i], extra);
+
+               if (((i & mask) == mask) || i == len - 1) {
+                       for (j = 0; j < mask-(i & mask); j++)
+                               printer(BINARY_PRINT_NUM_PAD, -1, extra);
+
+                       printer(BINARY_PRINT_SEP, i, extra);
+                       for (j = i & ~mask; j <= i; j++)
+                               printer(BINARY_PRINT_CHAR_DATA, data[j], extra);
+                       for (j = 0; j < mask-(i & mask); j++)
+                               printer(BINARY_PRINT_CHAR_PAD, i, extra);
+                       printer(BINARY_PRINT_LINE_END, -1, extra);
+               }
+       }
+       printer(BINARY_PRINT_DATA_END, -1, extra);
+}
+
+int is_printable_array(char *p, unsigned int len)
+{
+       unsigned int i;
+
+       if (!p || !len || p[len - 1] != 0)
+               return 0;
+
+       len--;
+
+       for (i = 0; i < len; i++) {
+               if (!isprint(p[i]) && !isspace(p[i]))
+                       return 0;
+       }
+       return 1;
+}
diff --git a/tools/perf/util/print_binary.h b/tools/perf/util/print_binary.h
new file mode 100644 (file)
index 0000000..da04272
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef PERF_PRINT_BINARY_H
+#define PERF_PRINT_BINARY_H
+
+#include <stddef.h>
+
+enum binary_printer_ops {
+       BINARY_PRINT_DATA_BEGIN,
+       BINARY_PRINT_LINE_BEGIN,
+       BINARY_PRINT_ADDR,
+       BINARY_PRINT_NUM_DATA,
+       BINARY_PRINT_NUM_PAD,
+       BINARY_PRINT_SEP,
+       BINARY_PRINT_CHAR_DATA,
+       BINARY_PRINT_CHAR_PAD,
+       BINARY_PRINT_LINE_END,
+       BINARY_PRINT_DATA_END,
+};
+
+typedef void (*print_binary_t)(enum binary_printer_ops op,
+                              unsigned int val, void *extra);
+
+void print_binary(unsigned char *data, size_t len,
+                 size_t bytes_per_line, print_binary_t printer,
+                 void *extra);
+
+int is_printable_array(char *p, unsigned int len);
+
+#endif /* PERF_PRINT_BINARY_H */
index 28fb62c32678483cd6d54a9c88e620022e1f9d08..84e7e698411e6a80a39050514227cbb90556ca13 100644 (file)
@@ -19,6 +19,7 @@
  *
  */
 
+#include <inttypes.h>
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -35,6 +36,7 @@
 #include "util.h"
 #include "event.h"
 #include "strlist.h"
+#include "strfilter.h"
 #include "debug.h"
 #include "cache.h"
 #include "color.h"
 #include "probe-finder.h"
 #include "probe-file.h"
 #include "session.h"
+#include "string2.h"
+
+#include "sane_ctype.h"
 
-#define MAX_CMDLEN 256
 #define PERFPROBE_GROUP "probe"
 
 bool probe_event_dry_run;      /* Dry run flag */
@@ -757,7 +761,9 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
        }
 
        for (i = 0; i < ntevs; i++) {
-               if (!tevs[i].point.address || tevs[i].point.retprobe)
+               if (!tevs[i].point.address)
+                       continue;
+               if (tevs[i].point.retprobe && !kretprobe_offset_is_supported())
                        continue;
                /* If we found a wrong one, mark it by NULL symbol */
                if (kprobe_warn_out_range(tevs[i].point.symbol,
@@ -1339,14 +1345,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
        if (!arg)
                return -EINVAL;
 
-       /*
-        * If the probe point starts with '%',
-        * or starts with "sdt_" and has a ':' but no '=',
-        * then it should be a SDT/cached probe point.
-        */
-       if (arg[0] == '%' ||
-           (!strncmp(arg, "sdt_", 4) &&
-            !!strchr(arg, ':') && !strchr(arg, '='))) {
+       if (is_sdt_event(arg)) {
                pev->sdt = true;
                if (arg[0] == '%')
                        arg++;
@@ -1528,11 +1527,6 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
                return -EINVAL;
        }
 
-       if (pp->retprobe && !pp->function) {
-               semantic_error("Return probe requires an entry function.\n");
-               return -EINVAL;
-       }
-
        if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
                semantic_error("Offset/Line/Lazy pattern can't be used with "
                               "return probe.\n");
@@ -2841,7 +2835,8 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
        }
 
        /* Note that the symbols in the kmodule are not relocated */
-       if (!pev->uprobes && !pp->retprobe && !pev->target) {
+       if (!pev->uprobes && !pev->target &&
+                       (!pp->retprobe || kretprobe_offset_is_supported())) {
                reloc_sym = kernel_get_ref_reloc_sym();
                if (!reloc_sym) {
                        pr_warning("Relocated base symbol is not found!\n");
@@ -3057,7 +3052,7 @@ concat_probe_trace_events(struct probe_trace_event **tevs, int *ntevs,
        struct probe_trace_event *new_tevs;
        int ret = 0;
 
-       if (ntevs == 0) {
+       if (*ntevs == 0) {
                *tevs = *tevs2;
                *ntevs = ntevs2;
                *tevs2 = NULL;
index 5d4e940614024ddf9a5d0420b8bdfa51ee07cd38..373842656fb6444f7ffdbe1aefc2f4a4add50818 100644 (file)
@@ -3,8 +3,6 @@
 
 #include <stdbool.h>
 #include "intlist.h"
-#include "strlist.h"
-#include "strfilter.h"
 
 /* Probe related configurations */
 struct probe_conf {
@@ -107,6 +105,8 @@ struct line_range {
        struct intlist          *line_list;     /* Visible lines */
 };
 
+struct strlist;
+
 /* List of variables */
 struct variable_list {
        struct probe_trace_point        point;  /* Actual probepoint */
@@ -153,6 +153,9 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs);
 int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs);
 int show_probe_trace_events(struct perf_probe_event *pevs, int npevs);
 void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);
+
+struct strfilter;
+
 int del_perf_probe_events(struct strfilter *filter);
 
 int show_perf_probe_event(const char *group, const char *event,
index 436b64731f65112f3c624a70a077f7370532da5a..d679389e627c1800c58b6b632ef65e67ff49d771 100644 (file)
  * GNU General Public License for more details.
  *
  */
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <sys/uio.h>
+#include <unistd.h>
 #include "util.h"
 #include "event.h"
 #include "strlist.h"
+#include "strfilter.h"
 #include "debug.h"
 #include "cache.h"
 #include "color.h"
 #include "probe-event.h"
 #include "probe-file.h"
 #include "session.h"
+#include "perf_regs.h"
+#include "string2.h"
 
-#define MAX_CMDLEN 256
+/* 4096 - 2 ('\n' + '\0') */
+#define MAX_CMDLEN 4094
 
 static void print_open_warning(int err, bool uprobe)
 {
@@ -70,7 +78,7 @@ static void print_both_open_warning(int kerr, int uerr)
        }
 }
 
-static int open_probe_events(const char *trace_file, bool readwrite)
+int open_trace_file(const char *trace_file, bool readwrite)
 {
        char buf[PATH_MAX];
        int ret;
@@ -92,12 +100,12 @@ static int open_probe_events(const char *trace_file, bool readwrite)
 
 static int open_kprobe_events(bool readwrite)
 {
-       return open_probe_events("kprobe_events", readwrite);
+       return open_trace_file("kprobe_events", readwrite);
 }
 
 static int open_uprobe_events(bool readwrite)
 {
-       return open_probe_events("uprobe_events", readwrite);
+       return open_trace_file("uprobe_events", readwrite);
 }
 
 int probe_file__open(int flag)
@@ -687,6 +695,110 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
                 : (unsigned long long)note->addr.a64[0];
 }
 
+static const char * const type_to_suffix[] = {
+       ":s64", "", "", "", ":s32", "", ":s16", ":s8",
+       "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
+};
+
+/*
+ * Isolate the string number and convert it into a decimal value;
+ * this will be an index to get suffix of the uprobe name (defining
+ * the type)
+ */
+static int sdt_arg_parse_size(char *n_ptr, const char **suffix)
+{
+       long type_idx;
+
+       type_idx = strtol(n_ptr, NULL, 10);
+       if (type_idx < -8 || type_idx > 8) {
+               pr_debug4("Failed to get a valid sdt type\n");
+               return -1;
+       }
+
+       *suffix = type_to_suffix[type_idx + 8];
+       return 0;
+}
+
+static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
+{
+       char *op, *desc = strdup(arg), *new_op = NULL;
+       const char *suffix = "";
+       int ret = -1;
+
+       if (desc == NULL) {
+               pr_debug4("Allocation error\n");
+               return ret;
+       }
+
+       /*
+        * Argument is in N@OP format. N is size of the argument and OP is
+        * the actual assembly operand. N can be omitted; in that case
+        * argument is just OP(without @).
+        */
+       op = strchr(desc, '@');
+       if (op) {
+               op[0] = '\0';
+               op++;
+
+               if (sdt_arg_parse_size(desc, &suffix))
+                       goto error;
+       } else {
+               op = desc;
+       }
+
+       ret = arch_sdt_arg_parse_op(op, &new_op);
+
+       if (ret < 0)
+               goto error;
+
+       if (ret == SDT_ARG_VALID) {
+               ret = strbuf_addf(buf, " arg%d=%s%s", i + 1, new_op, suffix);
+               if (ret < 0)
+                       goto error;
+       }
+
+       ret = 0;
+error:
+       free(desc);
+       free(new_op);
+       return ret;
+}
+
+static char *synthesize_sdt_probe_command(struct sdt_note *note,
+                                       const char *pathname,
+                                       const char *sdtgrp)
+{
+       struct strbuf buf;
+       char *ret = NULL, **args;
+       int i, args_count;
+
+       if (strbuf_init(&buf, 32) < 0)
+               return NULL;
+
+       if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
+                               sdtgrp, note->name, pathname,
+                               sdt_note__get_addr(note)) < 0)
+               goto error;
+
+       if (!note->args)
+               goto out;
+
+       if (note->args) {
+               args = argv_split(note->args, &args_count);
+
+               for (i = 0; i < args_count; ++i) {
+                       if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
+                               goto error;
+               }
+       }
+
+out:
+       ret = strbuf_detach(&buf, NULL);
+error:
+       strbuf_release(&buf);
+       return ret;
+}
+
 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 {
        struct probe_cache_entry *entry = NULL;
@@ -723,11 +835,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
                        entry->pev.group = strdup(sdtgrp);
                        list_add_tail(&entry->node, &pcache->entries);
                }
-               ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
-                               sdtgrp, note->name, pathname,
-                               sdt_note__get_addr(note));
-               if (ret < 0)
+               buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
+               if (!buf) {
+                       ret = -ENOMEM;
                        break;
+               }
+
                strlist__add(entry->tevlist, buf);
                free(buf);
                entry = NULL;
@@ -877,59 +990,72 @@ int probe_cache__show_all_caches(struct strfilter *filter)
        return 0;
 }
 
+enum ftrace_readme {
+       FTRACE_README_PROBE_TYPE_X = 0,
+       FTRACE_README_KRETPROBE_OFFSET,
+       FTRACE_README_END,
+};
+
 static struct {
        const char *pattern;
-       bool    avail;
-       bool    checked;
-} probe_type_table[] = {
-#define DEFINE_TYPE(idx, pat, def_avail)       \
-       [idx] = {.pattern = pat, .avail = (def_avail)}
-       DEFINE_TYPE(PROBE_TYPE_U, "* u8/16/32/64,*", true),
-       DEFINE_TYPE(PROBE_TYPE_S, "* s8/16/32/64,*", true),
-       DEFINE_TYPE(PROBE_TYPE_X, "* x8/16/32/64,*", false),
-       DEFINE_TYPE(PROBE_TYPE_STRING, "* string,*", true),
-       DEFINE_TYPE(PROBE_TYPE_BITFIELD,
-                   "* b<bit-width>@<bit-offset>/<container-size>", true),
+       bool avail;
+} ftrace_readme_table[] = {
+#define DEFINE_TYPE(idx, pat)                  \
+       [idx] = {.pattern = pat, .avail = false}
+       DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
+       DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
 };
 
-bool probe_type_is_available(enum probe_type type)
+static bool scan_ftrace_readme(enum ftrace_readme type)
 {
+       int fd;
        FILE *fp;
        char *buf = NULL;
        size_t len = 0;
-       bool target_line = false;
-       bool ret = probe_type_table[type].avail;
+       bool ret = false;
+       static bool scanned = false;
 
-       if (type >= PROBE_TYPE_END)
-               return false;
-       /* We don't have to check the type which supported by default */
-       if (ret || probe_type_table[type].checked)
-               return ret;
+       if (scanned)
+               goto result;
 
-       if (asprintf(&buf, "%s/README", tracing_path) < 0)
+       fd = open_trace_file("README", false);
+       if (fd < 0)
                return ret;
 
-       fp = fopen(buf, "r");
-       if (!fp)
-               goto end;
-
-       zfree(&buf);
-       while (getline(&buf, &len, fp) > 0 && !ret) {
-               if (!target_line) {
-                       target_line = !!strstr(buf, " type: ");
-                       if (!target_line)
-                               continue;
-               } else if (strstr(buf, "\t          ") != buf)
-                       break;
-               ret = strglobmatch(buf, probe_type_table[type].pattern);
+       fp = fdopen(fd, "r");
+       if (!fp) {
+               close(fd);
+               return ret;
        }
-       /* Cache the result */
-       probe_type_table[type].checked = true;
-       probe_type_table[type].avail = ret;
+
+       while (getline(&buf, &len, fp) > 0)
+               for (enum ftrace_readme i = 0; i < FTRACE_README_END; i++)
+                       if (!ftrace_readme_table[i].avail)
+                               ftrace_readme_table[i].avail =
+                                       strglobmatch(buf, ftrace_readme_table[i].pattern);
+       scanned = true;
 
        fclose(fp);
-end:
        free(buf);
 
-       return ret;
+result:
+       if (type >= FTRACE_README_END)
+               return false;
+
+       return ftrace_readme_table[type].avail;
+}
+
+bool probe_type_is_available(enum probe_type type)
+{
+       if (type >= PROBE_TYPE_END)
+               return false;
+       else if (type == PROBE_TYPE_X)
+               return scan_ftrace_readme(FTRACE_README_PROBE_TYPE_X);
+
+       return true;
+}
+
+bool kretprobe_offset_is_supported(void)
+{
+       return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET);
 }
index eba44c3e9dca9ac670d06736237feb49fb21734b..5ecc9d3925dbb53c3190d8c6aa075c5e38bd3935 100644 (file)
@@ -1,10 +1,11 @@
 #ifndef __PROBE_FILE_H
 #define __PROBE_FILE_H
 
-#include "strlist.h"
-#include "strfilter.h"
 #include "probe-event.h"
 
+struct strlist;
+struct strfilter;
+
 /* Cache of probe definitions */
 struct probe_cache_entry {
        struct list_head        node;
@@ -35,11 +36,13 @@ enum probe_type {
 
 /* probe-file.c depends on libelf */
 #ifdef HAVE_LIBELF_SUPPORT
+int open_trace_file(const char *trace_file, bool readwrite);
 int probe_file__open(int flag);
 int probe_file__open_both(int *kfd, int *ufd, int flag);
 struct strlist *probe_file__get_namelist(int fd);
 struct strlist *probe_file__get_rawlist(int fd);
 int probe_file__add_event(int fd, struct probe_trace_event *tev);
+
 int probe_file__del_events(int fd, struct strfilter *filter);
 int probe_file__get_events(int fd, struct strfilter *filter,
                                  struct strlist *plist);
@@ -64,6 +67,7 @@ struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
                                        const char *group, const char *event);
 int probe_cache__show_all_caches(struct strfilter *filter);
 bool probe_type_is_available(enum probe_type type);
+bool kretprobe_offset_is_supported(void);
 #else  /* ! HAVE_LIBELF_SUPPORT */
 static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
 {
index 57cd268d4275bd2c8a3f8f1e43f29fab1fe1a835..a5731de0e5ebc73ed3fbc35dd1b334e664f20b69 100644 (file)
@@ -19,6 +19,7 @@
  *
  */
 
+#include <inttypes.h>
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include "debug.h"
 #include "intlist.h"
 #include "util.h"
+#include "strlist.h"
 #include "symbol.h"
 #include "probe-finder.h"
 #include "probe-file.h"
+#include "string2.h"
 
 /* Kprobe tracer basic type is up to u64 */
 #define MAX_BASIC_TYPE_BITS    64
index 2956c51986529ee7481f922d488a449c0a7619a0..27f06155101298e1e5ab878d75b9944745c22bf4 100644 (file)
@@ -2,9 +2,9 @@
 #define _PROBE_FINDER_H
 
 #include <stdbool.h>
-#include "util.h"
 #include "intlist.h"
 #include "probe-event.h"
+#include "sane_ctype.h"
 
 #define MAX_PROBE_BUFFER       1024
 #define MAX_PROBES              128
index 0546a430434735c902a8c23e45bea583349f9851..9f3b0d9754a896484fa193865d2141bd37a82ca1 100644 (file)
@@ -21,8 +21,10 @@ util/cgroup.c
 util/parse-branch-options.c
 util/rblist.c
 util/counts.c
+util/print_binary.c
 util/strlist.c
 util/trace-event.c
 ../lib/rbtree.c
 util/string.c
 util/symbol_fprintf.c
+util/units.c
index a5fbc012e3df974adcec3581386ff80b6fdedf6a..c129e99114aedfcead61505802ec50aef0e22cd2 100644 (file)
@@ -4,11 +4,25 @@
 #include <poll.h>
 #include <linux/err.h>
 #include "evlist.h"
+#include "callchain.h"
 #include "evsel.h"
 #include "event.h"
 #include "cpumap.h"
+#include "print_binary.h"
 #include "thread_map.h"
 
+/*
+ * Provide these two so that we don't have to link against callchain.c and
+ * start dragging hist.c, etc.
+ */
+struct callchain_param callchain_param;
+
+int parse_callchain_record(const char *arg __maybe_unused,
+                          struct callchain_param *param __maybe_unused)
+{
+       return 0;
+}
+
 /*
  * Support debug printing even though util/debug.c is not linked.  That means
  * implementing 'verbose' and 'eprintf'.
index 293534c1a474352486df78087a4d452bcb96fe20..1ba8920151d8919e3d8b7b2a1236d7a82d27a939 100644 (file)
@@ -1,3 +1,4 @@
+#include <errno.h>
 #include <stdlib.h>
 #include "strbuf.h"
 #include "quote.h"
index 98bf584853ea28e0fd9ab3828aa1e83f9d4010e5..d91bdf5a1aa45985040d6321c33ef56d7dcb3f18 100644 (file)
@@ -2,6 +2,7 @@
 #include "evsel.h"
 #include "cpumap.h"
 #include "parse-events.h"
+#include <errno.h>
 #include <api/fs/fs.h>
 #include "util.h"
 #include "cloexec.h"
diff --git a/tools/perf/util/sane_ctype.h b/tools/perf/util/sane_ctype.h
new file mode 100644 (file)
index 0000000..4308c22
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef _PERF_SANE_CTYPE_H
+#define _PERF_SANE_CTYPE_H
+
+extern const char *graph_line;
+extern const char *graph_dotted_line;
+extern const char *spaces;
+extern const char *dots;
+
+/* Sane ctype - no locale, and works with signed chars */
+#undef isascii
+#undef isspace
+#undef isdigit
+#undef isxdigit
+#undef isalpha
+#undef isprint
+#undef isalnum
+#undef islower
+#undef isupper
+#undef tolower
+#undef toupper
+
+extern unsigned char sane_ctype[256];
+#define GIT_SPACE              0x01
+#define GIT_DIGIT              0x02
+#define GIT_ALPHA              0x04
+#define GIT_GLOB_SPECIAL       0x08
+#define GIT_REGEX_SPECIAL      0x10
+#define GIT_PRINT_EXTRA                0x20
+#define GIT_PRINT              0x3E
+#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
+#define isascii(x) (((x) & ~0x7f) == 0)
+#define isspace(x) sane_istest(x,GIT_SPACE)
+#define isdigit(x) sane_istest(x,GIT_DIGIT)
+#define isxdigit(x)    \
+       (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G')
+#define isalpha(x) sane_istest(x,GIT_ALPHA)
+#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
+#define isprint(x) sane_istest(x,GIT_PRINT)
+#define islower(x) (sane_istest(x,GIT_ALPHA) && (x & 0x20))
+#define isupper(x) (sane_istest(x,GIT_ALPHA) && !(x & 0x20))
+#define tolower(x) sane_case((unsigned char)(x), 0x20)
+#define toupper(x) sane_case((unsigned char)(x), 0)
+
+static inline int sane_case(int x, int high)
+{
+       if (sane_istest(x, GIT_ALPHA))
+               x = (x & ~0x20) | high;
+       return x;
+}
+
+#endif /* _PERF_SANE_CTYPE_H */
index dff043a2958921f61e0e9ee7f803bdcfb9bfc5bf..7b79c413486b3a6ef8b0f6c32e330911c5ce7638 100644 (file)
@@ -19,6 +19,7 @@
  *
  */
 
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -27,7 +28,9 @@
 #include <linux/bitmap.h>
 #include <linux/time64.h>
 
-#include "../util.h"
+#include <stdbool.h>
+/* perl needs the following define, right after including stdbool.h */
+#define HAS_BOOL
 #include <EXTERN.h>
 #include <perl.h>
 
index 783326cfbaa6bfdaeef277dc9545f55213ffa942..9d92af7d07182e662b1a6d7ad5e66c0147a78234 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <Python.h>
 
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -45,6 +46,7 @@
 #include "../call-path.h"
 #include "thread_map.h"
 #include "cpumap.h"
+#include "print_binary.h"
 #include "stat.h"
 
 PyMODINIT_FUNC initperf_trace_context(void);
index 1dd617d116b5d844f23c88592f9dac9f061a7ff6..7dc1096264c575cbbd1cd41d07f041585a997453 100644 (file)
@@ -1,5 +1,8 @@
+#include <errno.h>
+#include <inttypes.h>
 #include <linux/kernel.h>
 #include <traceevent/event-parse.h>
+#include <api/fs/fs.h>
 
 #include <byteswap.h>
 #include <unistd.h>
@@ -8,6 +11,7 @@
 
 #include "evlist.h"
 #include "evsel.h"
+#include "memswap.h"
 #include "session.h"
 #include "tool.h"
 #include "sort.h"
@@ -16,6 +20,7 @@
 #include "perf_regs.h"
 #include "asm/bug.h"
 #include "auxtrace.h"
+#include "thread.h"
 #include "thread-stack.h"
 #include "stat.h"
 
@@ -139,8 +144,14 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
                        if (perf_session__open(session) < 0)
                                goto out_close;
 
-                       perf_session__set_id_hdr_size(session);
-                       perf_session__set_comm_exec(session);
+                       /*
+                        * set session attributes that are present in perf.data
+                        * but not in pipe-mode.
+                        */
+                       if (!file->is_pipe) {
+                               perf_session__set_id_hdr_size(session);
+                               perf_session__set_comm_exec(session);
+                       }
                }
        } else  {
                session->machines.host.env = &perf_env;
@@ -155,7 +166,11 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
                        pr_warning("Cannot read kernel map\n");
        }
 
-       if (tool && tool->ordering_requires_timestamps &&
+       /*
+        * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is
+        * processed, so perf_evlist__sample_id_all is not meaningful here.
+        */
+       if ((!file || !file->is_pipe) && tool && tool->ordering_requires_timestamps &&
            tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
                dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
                tool->ordered_events = false;
@@ -1239,6 +1254,8 @@ static int machines__deliver_event(struct machines *machines,
                return tool->mmap2(tool, event, sample, machine);
        case PERF_RECORD_COMM:
                return tool->comm(tool, event, sample, machine);
+       case PERF_RECORD_NAMESPACES:
+               return tool->namespaces(tool, event, sample, machine);
        case PERF_RECORD_FORK:
                return tool->fork(tool, event, sample, machine);
        case PERF_RECORD_EXIT:
@@ -1258,9 +1275,12 @@ static int machines__deliver_event(struct machines *machines,
        case PERF_RECORD_UNTHROTTLE:
                return tool->unthrottle(tool, event, sample, machine);
        case PERF_RECORD_AUX:
-               if (tool->aux == perf_event__process_aux &&
-                   (event->aux.flags & PERF_AUX_FLAG_TRUNCATED))
-                       evlist->stats.total_aux_lost += 1;
+               if (tool->aux == perf_event__process_aux) {
+                       if (event->aux.flags & PERF_AUX_FLAG_TRUNCATED)
+                               evlist->stats.total_aux_lost += 1;
+                       if (event->aux.flags & PERF_AUX_FLAG_PARTIAL)
+                               evlist->stats.total_aux_partial += 1;
+               }
                return tool->aux(tool, event, sample, machine);
        case PERF_RECORD_ITRACE_START:
                return tool->itrace_start(tool, event, sample, machine);
@@ -1494,6 +1514,11 @@ int perf_session__register_idle_thread(struct perf_session *session)
                err = -1;
        }
 
+       if (thread == NULL || thread__set_namespaces(thread, 0, NULL)) {
+               pr_err("problem inserting idle task.\n");
+               err = -1;
+       }
+
        /* machine__findnew_thread() got the thread, so put it */
        thread__put(thread);
        return err;
@@ -1548,6 +1573,23 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
                            stats->nr_events[PERF_RECORD_AUX]);
        }
 
+       if (session->tool->aux == perf_event__process_aux &&
+           stats->total_aux_partial != 0) {
+               bool vmm_exclusive = false;
+
+               (void)sysfs__read_bool("module/kvm_intel/parameters/vmm_exclusive",
+                                      &vmm_exclusive);
+
+               ui__warning("AUX data had gaps in it %" PRIu64 " times out of %u!\n\n"
+                           "Are you running a KVM guest in the background?%s\n\n",
+                           stats->total_aux_partial,
+                           stats->nr_events[PERF_RECORD_AUX],
+                           vmm_exclusive ?
+                           "\nReloading kvm_intel module with vmm_exclusive=0\n"
+                           "will reduce the gaps to only guest's timeslices." :
+                           "");
+       }
+
        if (stats->nr_unknown_events != 0) {
                ui__warning("Found %u unknown events!\n\n"
                            "Is this an older tool processing a perf.data "
@@ -1628,6 +1670,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session)
        buf = malloc(cur_size);
        if (!buf)
                return -errno;
+       ordered_events__set_copy_on_queue(oe, true);
 more:
        event = buf;
        err = readn(fd, event, sizeof(struct perf_event_header));
index 4bd758553450c8904860d19dd642f790310bc591..47b5e7dbcb18d420ea526508d0fbe0e1e3da7234 100644 (file)
@@ -5,14 +5,14 @@
 #include "event.h"
 #include "header.h"
 #include "machine.h"
-#include "symbol.h"
-#include "thread.h"
 #include "data.h"
 #include "ordered-events.h"
+#include <linux/kernel.h>
 #include <linux/rbtree.h>
 #include <linux/perf_event.h>
 
 struct ip_callchain;
+struct symbol;
 struct thread;
 
 struct auxtrace;
index 0ff622288d243c4edad03a904b6da3a52cf4da50..5762ae4e9e912e30dc158ee293c503373d80cc1f 100644 (file)
@@ -1,12 +1,18 @@
+#include <errno.h>
+#include <inttypes.h>
+#include <regex.h>
 #include <sys/mman.h>
 #include "sort.h"
 #include "hist.h"
 #include "comm.h"
 #include "symbol.h"
+#include "thread.h"
 #include "evsel.h"
 #include "evlist.h"
+#include "strlist.h"
 #include <traceevent/event-parse.h>
 #include "mem-events.h"
+#include <linux/kernel.h>
 
 regex_t                parent_regex;
 const char     default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -323,7 +329,7 @@ char *hist_entry__get_srcline(struct hist_entry *he)
                return SRCLINE_UNKNOWN;
 
        return get_srcline(map->dso, map__rip_2objdump(map, he->ip),
-                          he->ms.sym, true);
+                          he->ms.sym, true, true);
 }
 
 static int64_t
@@ -366,7 +372,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
                        left->branch_info->srcline_from = get_srcline(map->dso,
                                           map__rip_2objdump(map,
                                                             left->branch_info->from.al_addr),
-                                                        left->branch_info->from.sym, true);
+                                                        left->branch_info->from.sym,
+                                                        true, true);
        }
        if (!right->branch_info->srcline_from) {
                struct map *map = right->branch_info->from.map;
@@ -376,7 +383,8 @@ sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
                        right->branch_info->srcline_from = get_srcline(map->dso,
                                             map__rip_2objdump(map,
                                                               right->branch_info->from.al_addr),
-                                                    right->branch_info->from.sym, true);
+                                                    right->branch_info->from.sym,
+                                                    true, true);
        }
        return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
 }
@@ -407,7 +415,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
                        left->branch_info->srcline_to = get_srcline(map->dso,
                                           map__rip_2objdump(map,
                                                             left->branch_info->to.al_addr),
-                                                        left->branch_info->from.sym, true);
+                                                        left->branch_info->from.sym,
+                                                        true, true);
        }
        if (!right->branch_info->srcline_to) {
                struct map *map = right->branch_info->to.map;
@@ -417,7 +426,8 @@ sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
                        right->branch_info->srcline_to = get_srcline(map->dso,
                                             map__rip_2objdump(map,
                                                               right->branch_info->to.al_addr),
-                                                    right->branch_info->to.sym, true);
+                                                    right->branch_info->to.sym,
+                                                    true, true);
        }
        return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
 }
@@ -448,7 +458,7 @@ static char *hist_entry__get_srcfile(struct hist_entry *e)
                return no_srcfile;
 
        sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
-                        e->ms.sym, false, true);
+                        e->ms.sym, false, true, true);
        if (!strcmp(sf, SRCLINE_UNKNOWN))
                return no_srcfile;
        p = strchr(sf, ':');
@@ -536,6 +546,46 @@ struct sort_entry sort_cpu = {
        .se_width_idx   = HISTC_CPU,
 };
 
+/* --sort cgroup_id */
+
+static int64_t _sort__cgroup_dev_cmp(u64 left_dev, u64 right_dev)
+{
+       return (int64_t)(right_dev - left_dev);
+}
+
+static int64_t _sort__cgroup_inode_cmp(u64 left_ino, u64 right_ino)
+{
+       return (int64_t)(right_ino - left_ino);
+}
+
+static int64_t
+sort__cgroup_id_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+       int64_t ret;
+
+       ret = _sort__cgroup_dev_cmp(right->cgroup_id.dev, left->cgroup_id.dev);
+       if (ret != 0)
+               return ret;
+
+       return _sort__cgroup_inode_cmp(right->cgroup_id.ino,
+                                      left->cgroup_id.ino);
+}
+
+static int hist_entry__cgroup_id_snprintf(struct hist_entry *he,
+                                         char *bf, size_t size,
+                                         unsigned int width __maybe_unused)
+{
+       return repsep_snprintf(bf, size, "%lu/0x%lx", he->cgroup_id.dev,
+                              he->cgroup_id.ino);
+}
+
+struct sort_entry sort_cgroup_id = {
+       .se_header      = "cgroup id (dev/inode)",
+       .se_cmp         = sort__cgroup_id_cmp,
+       .se_snprintf    = hist_entry__cgroup_id_snprintf,
+       .se_width_idx   = HISTC_CGROUP_ID,
+};
+
 /* --sort socket */
 
 static int64_t
@@ -846,6 +896,9 @@ static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
 static int64_t
 sort__cycles_cmp(struct hist_entry *left, struct hist_entry *right)
 {
+       if (!left->branch_info || !right->branch_info)
+               return cmp_null(left->branch_info, right->branch_info);
+
        return left->branch_info->flags.cycles -
                right->branch_info->flags.cycles;
 }
@@ -853,6 +906,8 @@ sort__cycles_cmp(struct hist_entry *left, struct hist_entry *right)
 static int hist_entry__cycles_snprintf(struct hist_entry *he, char *bf,
                                    size_t size, unsigned int width)
 {
+       if (!he->branch_info)
+               return scnprintf(bf, size, "%-.*s", width, "N/A");
        if (he->branch_info->flags.cycles == 0)
                return repsep_snprintf(bf, size, "%-*s", width, "-");
        return repsep_snprintf(bf, size, "%-*hd", width,
@@ -1396,6 +1451,46 @@ struct sort_entry sort_transaction = {
        .se_width_idx   = HISTC_TRANSACTION,
 };
 
+/* --sort symbol_size */
+
+static int64_t _sort__sym_size_cmp(struct symbol *sym_l, struct symbol *sym_r)
+{
+       int64_t size_l = sym_l != NULL ? symbol__size(sym_l) : 0;
+       int64_t size_r = sym_r != NULL ? symbol__size(sym_r) : 0;
+
+       return size_l < size_r ? -1 :
+               size_l == size_r ? 0 : 1;
+}
+
+static int64_t
+sort__sym_size_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+       return _sort__sym_size_cmp(right->ms.sym, left->ms.sym);
+}
+
+static int _hist_entry__sym_size_snprintf(struct symbol *sym, char *bf,
+                                         size_t bf_size, unsigned int width)
+{
+       if (sym)
+               return repsep_snprintf(bf, bf_size, "%*d", width, symbol__size(sym));
+
+       return repsep_snprintf(bf, bf_size, "%*s", width, "unknown");
+}
+
+static int hist_entry__sym_size_snprintf(struct hist_entry *he, char *bf,
+                                        size_t size, unsigned int width)
+{
+       return _hist_entry__sym_size_snprintf(he->ms.sym, bf, size, width);
+}
+
+struct sort_entry sort_sym_size = {
+       .se_header      = "Symbol size",
+       .se_cmp         = sort__sym_size_cmp,
+       .se_snprintf    = hist_entry__sym_size_snprintf,
+       .se_width_idx   = HISTC_SYM_SIZE,
+};
+
+
 struct sort_dimension {
        const char              *name;
        struct sort_entry       *entry;
@@ -1418,6 +1513,8 @@ static struct sort_dimension common_sort_dimensions[] = {
        DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
        DIM(SORT_TRANSACTION, "transaction", sort_transaction),
        DIM(SORT_TRACE, "trace", sort_trace),
+       DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size),
+       DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id),
 };
 
 #undef DIM
index 796c847e2f000d6722ed2cb35321e7f3b8b0489e..b7c75597e18fd226c190e8fbb81ef610690f8541 100644 (file)
@@ -2,7 +2,7 @@
 #define __PERF_SORT_H
 #include "../builtin.h"
 
-#include "util.h"
+#include <regex.h>
 
 #include "color.h"
 #include <linux/list.h>
@@ -11,7 +11,6 @@
 #include "symbol.h"
 #include "string.h"
 #include "callchain.h"
-#include "strlist.h"
 #include "values.h"
 
 #include "../perf.h"
@@ -21,7 +20,9 @@
 #include <subcmd/parse-options.h>
 #include "parse-events.h"
 #include "hist.h"
-#include "thread.h"
+#include "srcline.h"
+
+struct thread;
 
 extern regex_t parent_regex;
 extern const char *sort_order;
@@ -54,6 +55,11 @@ struct he_stat {
        u32                     nr_events;
 };
 
+struct namespace_id {
+       u64                     dev;
+       u64                     ino;
+};
+
 struct hist_entry_diff {
        bool    computed;
        union {
@@ -91,6 +97,7 @@ struct hist_entry {
        struct map_symbol       ms;
        struct thread           *thread;
        struct comm             *comm;
+       struct namespace_id     cgroup_id;
        u64                     ip;
        u64                     transaction;
        s32                     socket;
@@ -122,6 +129,7 @@ struct hist_entry {
        };
        char                    *srcline;
        char                    *srcfile;
+       struct inline_node      *inline_node;
        struct symbol           *parent;
        struct branch_info      *branch_info;
        struct hists            *hists;
@@ -211,6 +219,8 @@ enum sort_type {
        SORT_GLOBAL_WEIGHT,
        SORT_TRANSACTION,
        SORT_TRACE,
+       SORT_SYM_SIZE,
+       SORT_CGROUP_ID,
 
        /* branch stack specific sort keys */
        __SORT_BRANCH_STACK,
index b4db3f48e3b09784f00d610c8cbffea8c26e38c6..df051a52393c1de8e85f46d43f567755888133e7 100644 (file)
@@ -1,3 +1,4 @@
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -7,11 +8,59 @@
 #include "util/dso.h"
 #include "util/util.h"
 #include "util/debug.h"
+#include "util/callchain.h"
+#include "srcline.h"
 
 #include "symbol.h"
 
 bool srcline_full_filename;
 
+static const char *dso__name(struct dso *dso)
+{
+       const char *dso_name;
+
+       if (dso->symsrc_filename)
+               dso_name = dso->symsrc_filename;
+       else
+               dso_name = dso->long_name;
+
+       if (dso_name[0] == '[')
+               return NULL;
+
+       if (!strncmp(dso_name, "/tmp/perf-", 10))
+               return NULL;
+
+       return dso_name;
+}
+
+static int inline_list__append(char *filename, char *funcname, int line_nr,
+                              struct inline_node *node, struct dso *dso)
+{
+       struct inline_list *ilist;
+       char *demangled;
+
+       ilist = zalloc(sizeof(*ilist));
+       if (ilist == NULL)
+               return -1;
+
+       ilist->filename = filename;
+       ilist->line_nr = line_nr;
+
+       if (dso != NULL) {
+               demangled = dso__demangle_sym(dso, 0, funcname);
+               if (demangled == NULL) {
+                       ilist->funcname = funcname;
+               } else {
+                       ilist->funcname = demangled;
+                       free(funcname);
+               }
+       }
+
+       list_add_tail(&ilist->list, &node->val);
+
+       return 0;
+}
+
 #ifdef HAVE_LIBBFD_SUPPORT
 
 /*
@@ -151,9 +200,17 @@ static void addr2line_cleanup(struct a2l_data *a2l)
 
 #define MAX_INLINE_NEST 1024
 
+static void inline_list__reverse(struct inline_node *node)
+{
+       struct inline_list *ilist, *n;
+
+       list_for_each_entry_safe_reverse(ilist, n, &node->val, list)
+               list_move_tail(&ilist->list, &node->val);
+}
+
 static int addr2line(const char *dso_name, u64 addr,
                     char **file, unsigned int *line, struct dso *dso,
-                    bool unwind_inlines)
+                    bool unwind_inlines, struct inline_node *node)
 {
        int ret = 0;
        struct a2l_data *a2l = dso->a2l;
@@ -178,8 +235,21 @@ static int addr2line(const char *dso_name, u64 addr,
 
                while (bfd_find_inliner_info(a2l->abfd, &a2l->filename,
                                             &a2l->funcname, &a2l->line) &&
-                      cnt++ < MAX_INLINE_NEST)
-                       ;
+                      cnt++ < MAX_INLINE_NEST) {
+
+                       if (node != NULL) {
+                               if (inline_list__append(strdup(a2l->filename),
+                                                       strdup(a2l->funcname),
+                                                       a2l->line, node,
+                                                       dso) != 0)
+                                       return 0;
+                       }
+               }
+
+               if ((node != NULL) &&
+                   (callchain_param.order != ORDER_CALLEE)) {
+                       inline_list__reverse(node);
+               }
        }
 
        if (a2l->found && a2l->filename) {
@@ -205,18 +275,68 @@ void dso__free_a2l(struct dso *dso)
        dso->a2l = NULL;
 }
 
+static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
+       struct dso *dso)
+{
+       char *file = NULL;
+       unsigned int line = 0;
+       struct inline_node *node;
+
+       node = zalloc(sizeof(*node));
+       if (node == NULL) {
+               perror("not enough memory for the inline node");
+               return NULL;
+       }
+
+       INIT_LIST_HEAD(&node->val);
+       node->addr = addr;
+
+       if (!addr2line(dso_name, addr, &file, &line, dso, TRUE, node))
+               goto out_free_inline_node;
+
+       if (list_empty(&node->val))
+               goto out_free_inline_node;
+
+       return node;
+
+out_free_inline_node:
+       inline_node__delete(node);
+       return NULL;
+}
+
 #else /* HAVE_LIBBFD_SUPPORT */
 
+static int filename_split(char *filename, unsigned int *line_nr)
+{
+       char *sep;
+
+       sep = strchr(filename, '\n');
+       if (sep)
+               *sep = '\0';
+
+       if (!strcmp(filename, "??:0"))
+               return 0;
+
+       sep = strchr(filename, ':');
+       if (sep) {
+               *sep++ = '\0';
+               *line_nr = strtoul(sep, NULL, 0);
+               return 1;
+       }
+
+       return 0;
+}
+
 static int addr2line(const char *dso_name, u64 addr,
                     char **file, unsigned int *line_nr,
                     struct dso *dso __maybe_unused,
-                    bool unwind_inlines __maybe_unused)
+                    bool unwind_inlines __maybe_unused,
+                    struct inline_node *node __maybe_unused)
 {
        FILE *fp;
        char cmd[PATH_MAX];
        char *filename = NULL;
        size_t len;
-       char *sep;
        int ret = 0;
 
        scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
@@ -233,23 +353,14 @@ static int addr2line(const char *dso_name, u64 addr,
                goto out;
        }
 
-       sep = strchr(filename, '\n');
-       if (sep)
-               *sep = '\0';
-
-       if (!strcmp(filename, "??:0")) {
-               pr_debug("no debugging info in %s\n", dso_name);
+       ret = filename_split(filename, line_nr);
+       if (ret != 1) {
                free(filename);
                goto out;
        }
 
-       sep = strchr(filename, ':');
-       if (sep) {
-               *sep++ = '\0';
-               *file = filename;
-               *line_nr = strtoul(sep, NULL, 0);
-               ret = 1;
-       }
+       *file = filename;
+
 out:
        pclose(fp);
        return ret;
@@ -259,6 +370,58 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
 {
 }
 
+static struct inline_node *addr2inlines(const char *dso_name, u64 addr,
+       struct dso *dso __maybe_unused)
+{
+       FILE *fp;
+       char cmd[PATH_MAX];
+       struct inline_node *node;
+       char *filename = NULL;
+       size_t len;
+       unsigned int line_nr = 0;
+
+       scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64,
+                 dso_name, addr);
+
+       fp = popen(cmd, "r");
+       if (fp == NULL) {
+               pr_err("popen failed for %s\n", dso_name);
+               return NULL;
+       }
+
+       node = zalloc(sizeof(*node));
+       if (node == NULL) {
+               perror("not enough memory for the inline node");
+               goto out;
+       }
+
+       INIT_LIST_HEAD(&node->val);
+       node->addr = addr;
+
+       while (getline(&filename, &len, fp) != -1) {
+               if (filename_split(filename, &line_nr) != 1) {
+                       free(filename);
+                       goto out;
+               }
+
+               if (inline_list__append(filename, NULL, line_nr, node,
+                                       NULL) != 0)
+                       goto out;
+
+               filename = NULL;
+       }
+
+out:
+       pclose(fp);
+
+       if (list_empty(&node->val)) {
+               inline_node__delete(node);
+               return NULL;
+       }
+
+       return node;
+}
+
 #endif /* HAVE_LIBBFD_SUPPORT */
 
 /*
@@ -268,7 +431,7 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
 #define A2L_FAIL_LIMIT 123
 
 char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
-                 bool show_sym, bool unwind_inlines)
+                 bool show_sym, bool show_addr, bool unwind_inlines)
 {
        char *file = NULL;
        unsigned line = 0;
@@ -278,18 +441,11 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
        if (!dso->has_srcline)
                goto out;
 
-       if (dso->symsrc_filename)
-               dso_name = dso->symsrc_filename;
-       else
-               dso_name = dso->long_name;
-
-       if (dso_name[0] == '[')
-               goto out;
-
-       if (!strncmp(dso_name, "/tmp/perf-", 10))
+       dso_name = dso__name(dso);
+       if (dso_name == NULL)
                goto out;
 
-       if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines))
+       if (!addr2line(dso_name, addr, &file, &line, dso, unwind_inlines, NULL))
                goto out;
 
        if (asprintf(&srcline, "%s:%u",
@@ -309,6 +465,11 @@ out:
                dso->has_srcline = 0;
                dso__free_a2l(dso);
        }
+
+       if (!show_addr)
+               return (show_sym && sym) ?
+                           strndup(sym->name, sym->namelen) : NULL;
+
        if (sym) {
                if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
                                        addr - sym->start) < 0)
@@ -325,7 +486,32 @@ void free_srcline(char *srcline)
 }
 
 char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
-                 bool show_sym)
+                 bool show_sym, bool show_addr)
+{
+       return __get_srcline(dso, addr, sym, show_sym, show_addr, false);
+}
+
+struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr)
 {
-       return __get_srcline(dso, addr, sym, show_sym, false);
+       const char *dso_name;
+
+       dso_name = dso__name(dso);
+       if (dso_name == NULL)
+               return NULL;
+
+       return addr2inlines(dso_name, addr, dso);
+}
+
+void inline_node__delete(struct inline_node *node)
+{
+       struct inline_list *ilist, *tmp;
+
+       list_for_each_entry_safe(ilist, tmp, &node->val, list) {
+               list_del_init(&ilist->list);
+               zfree(&ilist->filename);
+               zfree(&ilist->funcname);
+               free(ilist);
+       }
+
+       free(node);
 }
diff --git a/tools/perf/util/srcline.h b/tools/perf/util/srcline.h
new file mode 100644 (file)
index 0000000..7b52ba8
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef PERF_SRCLINE_H
+#define PERF_SRCLINE_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+
+struct dso;
+struct symbol;
+
+extern bool srcline_full_filename;
+char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
+                 bool show_sym, bool show_addr);
+char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
+                 bool show_sym, bool show_addr, bool unwind_inlines);
+void free_srcline(char *srcline);
+
+#define SRCLINE_UNKNOWN  ((char *) "??:0")
+
+struct inline_list {
+       char                    *filename;
+       char                    *funcname;
+       unsigned int            line_nr;
+       struct list_head        list;
+};
+
+struct inline_node {
+       u64                     addr;
+       struct list_head        val;
+};
+
+struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr);
+void inline_node__delete(struct inline_node *node);
+
+#endif /* PERF_SRCLINE_H */
index 8a2bbd2a4d828c83deb2f203d25d5e452752c90b..ac10cc675d39579bfca249abbc4353e7c9accc6e 100644 (file)
@@ -3,6 +3,9 @@
 #include "stat.h"
 #include "color.h"
 #include "pmu.h"
+#include "rblist.h"
+#include "evlist.h"
+#include "expr.h"
 
 enum {
        CTX_BIT_USER    = 1 << 0,
@@ -41,13 +44,73 @@ static struct stats runtime_topdown_slots_issued[NUM_CTX][MAX_NR_CPUS];
 static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS];
 static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS];
 static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS];
+static struct rblist runtime_saved_values;
 static bool have_frontend_stalled;
 
 struct stats walltime_nsecs_stats;
 
+struct saved_value {
+       struct rb_node rb_node;
+       struct perf_evsel *evsel;
+       int cpu;
+       int ctx;
+       struct stats stats;
+};
+
+static int saved_value_cmp(struct rb_node *rb_node, const void *entry)
+{
+       struct saved_value *a = container_of(rb_node,
+                                            struct saved_value,
+                                            rb_node);
+       const struct saved_value *b = entry;
+
+       if (a->ctx != b->ctx)
+               return a->ctx - b->ctx;
+       if (a->cpu != b->cpu)
+               return a->cpu - b->cpu;
+       return a->evsel - b->evsel;
+}
+
+static struct rb_node *saved_value_new(struct rblist *rblist __maybe_unused,
+                                    const void *entry)
+{
+       struct saved_value *nd = malloc(sizeof(struct saved_value));
+
+       if (!nd)
+               return NULL;
+       memcpy(nd, entry, sizeof(struct saved_value));
+       return &nd->rb_node;
+}
+
+static struct saved_value *saved_value_lookup(struct perf_evsel *evsel,
+                                             int cpu, int ctx,
+                                             bool create)
+{
+       struct rb_node *nd;
+       struct saved_value dm = {
+               .cpu = cpu,
+               .ctx = ctx,
+               .evsel = evsel,
+       };
+       nd = rblist__find(&runtime_saved_values, &dm);
+       if (nd)
+               return container_of(nd, struct saved_value, rb_node);
+       if (create) {
+               rblist__add_node(&runtime_saved_values, &dm);
+               nd = rblist__find(&runtime_saved_values, &dm);
+               if (nd)
+                       return container_of(nd, struct saved_value, rb_node);
+       }
+       return NULL;
+}
+
 void perf_stat__init_shadow_stats(void)
 {
        have_frontend_stalled = pmu_have_event("cpu", "stalled-cycles-frontend");
+       rblist__init(&runtime_saved_values);
+       runtime_saved_values.node_cmp = saved_value_cmp;
+       runtime_saved_values.node_new = saved_value_new;
+       /* No delete for now */
 }
 
 static int evsel_context(struct perf_evsel *evsel)
@@ -70,6 +133,8 @@ static int evsel_context(struct perf_evsel *evsel)
 
 void perf_stat__reset_shadow_stats(void)
 {
+       struct rb_node *pos, *next;
+
        memset(runtime_nsecs_stats, 0, sizeof(runtime_nsecs_stats));
        memset(runtime_cycles_stats, 0, sizeof(runtime_cycles_stats));
        memset(runtime_stalled_cycles_front_stats, 0, sizeof(runtime_stalled_cycles_front_stats));
@@ -92,6 +157,15 @@ void perf_stat__reset_shadow_stats(void)
        memset(runtime_topdown_slots_issued, 0, sizeof(runtime_topdown_slots_issued));
        memset(runtime_topdown_fetch_bubbles, 0, sizeof(runtime_topdown_fetch_bubbles));
        memset(runtime_topdown_recovery_bubbles, 0, sizeof(runtime_topdown_recovery_bubbles));
+
+       next = rb_first(&runtime_saved_values.entries);
+       while (next) {
+               pos = next;
+               next = rb_next(pos);
+               memset(&container_of(pos, struct saved_value, rb_node)->stats,
+                      0,
+                      sizeof(struct stats));
+       }
 }
 
 /*
@@ -143,6 +217,12 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
                update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]);
        else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
                update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]);
+
+       if (counter->collect_stat) {
+               struct saved_value *v = saved_value_lookup(counter, cpu, ctx,
+                                                          true);
+               update_stats(&v->stats, count[0]);
+       }
 }
 
 /* used for get_ratio_color() */
@@ -172,6 +252,95 @@ static const char *get_ratio_color(enum grc_type type, double ratio)
        return color;
 }
 
+static struct perf_evsel *perf_stat__find_event(struct perf_evlist *evsel_list,
+                                               const char *name)
+{
+       struct perf_evsel *c2;
+
+       evlist__for_each_entry (evsel_list, c2) {
+               if (!strcasecmp(c2->name, name))
+                       return c2;
+       }
+       return NULL;
+}
+
+/* Mark MetricExpr target events and link events using them to them. */
+void perf_stat__collect_metric_expr(struct perf_evlist *evsel_list)
+{
+       struct perf_evsel *counter, *leader, **metric_events, *oc;
+       bool found;
+       const char **metric_names;
+       int i;
+       int num_metric_names;
+
+       evlist__for_each_entry(evsel_list, counter) {
+               bool invalid = false;
+
+               leader = counter->leader;
+               if (!counter->metric_expr)
+                       continue;
+               metric_events = counter->metric_events;
+               if (!metric_events) {
+                       if (expr__find_other(counter->metric_expr, counter->name,
+                                               &metric_names, &num_metric_names) < 0)
+                               continue;
+
+                       metric_events = calloc(sizeof(struct perf_evsel *),
+                                              num_metric_names + 1);
+                       if (!metric_events)
+                               return;
+                       counter->metric_events = metric_events;
+               }
+
+               for (i = 0; i < num_metric_names; i++) {
+                       found = false;
+                       if (leader) {
+                               /* Search in group */
+                               for_each_group_member (oc, leader) {
+                                       if (!strcasecmp(oc->name, metric_names[i])) {
+                                               found = true;
+                                               break;
+                                       }
+                               }
+                       }
+                       if (!found) {
+                               /* Search ignoring groups */
+                               oc = perf_stat__find_event(evsel_list, metric_names[i]);
+                       }
+                       if (!oc) {
+                               /* Deduping one is good enough to handle duplicated PMUs. */
+                               static char *printed;
+
+                               /*
+                                * Adding events automatically would be difficult, because
+                                * it would risk creating groups that are not schedulable.
+                                * perf stat doesn't understand all the scheduling constraints
+                                * of events. So we ask the user instead to add the missing
+                                * events.
+                                */
+                               if (!printed || strcasecmp(printed, metric_names[i])) {
+                                       fprintf(stderr,
+                                               "Add %s event to groups to get metric expression for %s\n",
+                                               metric_names[i],
+                                               counter->name);
+                                       printed = strdup(metric_names[i]);
+                               }
+                               invalid = true;
+                               continue;
+                       }
+                       metric_events[i] = oc;
+                       oc->collect_stat = true;
+               }
+               metric_events[i] = NULL;
+               free(metric_names);
+               if (invalid) {
+                       free(metric_events);
+                       counter->metric_events = NULL;
+                       counter->metric_expr = NULL;
+               }
+       }
+}
+
 static void print_stalled_cycles_frontend(int cpu,
                                          struct perf_evsel *evsel, double avg,
                                          struct perf_stat_output_ctx *out)
@@ -614,6 +783,34 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
                                        be_bound * 100.);
                else
                        print_metric(ctxp, NULL, NULL, name, 0);
+       } else if (evsel->metric_expr) {
+               struct parse_ctx pctx;
+               int i;
+
+               expr__ctx_init(&pctx);
+               expr__add_id(&pctx, evsel->name, avg);
+               for (i = 0; evsel->metric_events[i]; i++) {
+                       struct saved_value *v;
+
+                       v = saved_value_lookup(evsel->metric_events[i], cpu, ctx, false);
+                       if (!v)
+                               break;
+                       expr__add_id(&pctx, evsel->metric_events[i]->name,
+                                            avg_stats(&v->stats));
+               }
+               if (!evsel->metric_events[i]) {
+                       const char *p = evsel->metric_expr;
+
+                       if (expr__parse(&ratio, &pctx, &p) == 0)
+                               print_metric(ctxp, NULL, "%8.1f",
+                                       evsel->metric_name ?
+                                       evsel->metric_name :
+                                       out->force_header ?  evsel->name : "",
+                                       ratio);
+                       else
+                               print_metric(ctxp, NULL, NULL, "", 0);
+               } else
+                       print_metric(ctxp, NULL, NULL, "", 0);
        } else if (runtime_nsecs_stats[cpu].n != 0) {
                char unit = 'M';
                char unit_buf[10];
index 0d51334a9b4628090f35ffe4da921b4e0ecb15b0..c58174443dc12c7fad840d8b67a34223e5283f9f 100644 (file)
@@ -1,3 +1,5 @@
+#include <errno.h>
+#include <inttypes.h>
 #include <math.h>
 #include "stat.h"
 #include "evlist.h"
index c29bb94c48a4b6070a659e3674f4ae84694724f9..0a65ae23f49504874bf82134d4e9ed40d5408a7f 100644 (file)
@@ -85,11 +85,13 @@ struct perf_stat_output_ctx {
        void *ctx;
        print_metric_t print_metric;
        new_line_t new_line;
+       bool force_header;
 };
 
 void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
                                   double avg, int cpu,
                                   struct perf_stat_output_ctx *out);
+void perf_stat__collect_metric_expr(struct perf_evlist *);
 
 int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw);
 void perf_evlist__free_stats(struct perf_evlist *evlist);
index 817593908d47a3d1ea27eb73080b94852e88d990..aafe908b82b5720b4487c242370ed326ec520e2c 100644 (file)
@@ -1,15 +1,7 @@
 #include "debug.h"
 #include "util.h"
 #include <linux/kernel.h>
-
-int prefixcmp(const char *str, const char *prefix)
-{
-       for (; ; str++, prefix++)
-               if (!*prefix)
-                       return 0;
-               else if (*str != *prefix)
-                       return (unsigned char)*prefix - (unsigned char)*str;
-}
+#include <errno.h>
 
 /*
  * Used as the default ->buf value, so that people can always assume
index efb53772e0ecc8e6a9c9ea4493d37c6dc55d38bf..4dc0af669a3009f72726ff124913057413e1758f 100644 (file)
@@ -1,7 +1,10 @@
 #include "util.h"
-#include "string.h"
+#include "string2.h"
 #include "strfilter.h"
 
+#include <errno.h>
+#include "sane_ctype.h"
+
 /* Operators */
 static const char *OP_and      = "&";  /* Logical AND */
 static const char *OP_or       = "|";  /* Logical OR */
index bddca519dd5854a0fd3319e85d54d7e638514b47..cca53b693a48d852450c00bf7ef6f90285d7ce4d 100644 (file)
@@ -1,5 +1,9 @@
-#include "util.h"
-#include "linux/string.h"
+#include "string2.h"
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <stdlib.h>
+
+#include "sane_ctype.h"
 
 #define K 1024LL
 /*
@@ -99,8 +103,10 @@ static int count_argc(const char *str)
 void argv_free(char **argv)
 {
        char **p;
-       for (p = argv; *p; p++)
-               zfree(p);
+       for (p = argv; *p; p++) {
+               free(*p);
+               *p = NULL;
+       }
 
        free(argv);
 }
@@ -120,7 +126,7 @@ void argv_free(char **argv)
 char **argv_split(const char *str, int *argcp)
 {
        int argc = count_argc(str);
-       char **argv = zalloc(sizeof(*argv) * (argc+1));
+       char **argv = calloc(argc + 1, sizeof(*argv));
        char **argvp;
 
        if (argv == NULL)
@@ -322,12 +328,8 @@ char *strxfrchar(char *s, char from, char to)
  */
 char *ltrim(char *s)
 {
-       int len = strlen(s);
-
-       while (len && isspace(*s)) {
-               len--;
+       while (isspace(*s))
                s++;
-       }
 
        return s;
 }
@@ -381,7 +383,7 @@ char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints
                                goto out_err_overflow;
 
                        if (i > 0)
-                               printed += snprintf(e + printed, size - printed, " %s ", or_and);
+                               printed += scnprintf(e + printed, size - printed, " %s ", or_and);
                        printed += scnprintf(e + printed, size - printed,
                                             "%s %s %d", var, eq_neq, ints[i]);
                }
diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h
new file mode 100644 (file)
index 0000000..2f61968
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef PERF_STRING_H
+#define PERF_STRING_H
+
+#include <linux/types.h>
+#include <stddef.h>
+#include <string.h>
+
+s64 perf_atoll(const char *str);
+char **argv_split(const char *str, int *argcp);
+void argv_free(char **argv);
+bool strglobmatch(const char *str, const char *pat);
+bool strglobmatch_nocase(const char *str, const char *pat);
+bool strlazymatch(const char *str, const char *pat);
+static inline bool strisglob(const char *str)
+{
+       return strpbrk(str, "*?[") != NULL;
+}
+int strtailcmp(const char *s1, const char *s2);
+char *strxfrchar(char *s, char from, char to);
+
+char *ltrim(char *s);
+char *rtrim(char *s);
+
+static inline char *trim(char *s)
+{
+       return ltrim(rtrim(s));
+}
+
+char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints);
+
+static inline char *asprintf_expr_in_ints(const char *var, size_t nints, int *ints)
+{
+       return asprintf_expr_inout_ints(var, true, nints, ints);
+}
+
+static inline char *asprintf_expr_not_in_ints(const char *var, size_t nints, int *ints)
+{
+       return asprintf_expr_inout_ints(var, false, nints, ints);
+}
+
+
+#endif /* PERF_STRING_H */
index 0d3dfcb919b44936dfa42f2f437176f833afa39c..9de5434bb49ea355c25358c5441290b28ea0fb60 100644 (file)
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 static
 struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry)
index 4e59ddeb4eda7cd8e75ec2c0c42e1fec4de0432a..e7ee47f7377ab17bbb414be4240cf01565ae863a 100644 (file)
@@ -10,8 +10,9 @@
 #include "demangle-rust.h"
 #include "machine.h"
 #include "vdso.h"
-#include <symbol/kallsyms.h>
 #include "debug.h"
+#include "sane_ctype.h"
+#include <symbol/kallsyms.h>
 
 #ifndef EM_AARCH64
 #define EM_AARCH64     183  /* ARM 64 bit */
@@ -390,6 +391,11 @@ out_elf_end:
        return 0;
 }
 
+char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name)
+{
+       return demangle_sym(dso, kmodule, elf_name);
+}
+
 /*
  * Align offset to 4 bytes as needed for note name and descriptor data.
  */
@@ -1828,7 +1834,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
 static int populate_sdt_note(Elf **elf, const char *data, size_t len,
                             struct list_head *sdt_notes)
 {
-       const char *provider, *name;
+       const char *provider, *name, *args;
        struct sdt_note *tmp = NULL;
        GElf_Ehdr ehdr;
        GElf_Addr base_off = 0;
@@ -1887,6 +1893,25 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
                goto out_free_prov;
        }
 
+       args = memchr(name, '\0', data + len - name);
+
+       /*
+        * There is no argument if:
+        * - We reached the end of the note;
+        * - There is not enough room to hold a potential string;
+        * - The argument string is empty or just contains ':'.
+        */
+       if (args == NULL || data + len - args < 2 ||
+               args[1] == ':' || args[1] == '\0')
+               tmp->args = NULL;
+       else {
+               tmp->args = strdup(++args);
+               if (!tmp->args) {
+                       ret = -ENOMEM;
+                       goto out_free_name;
+               }
+       }
+
        if (gelf_getclass(*elf) == ELFCLASS32) {
                memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
                tmp->bit32 = true;
@@ -1898,7 +1923,7 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
        if (!gelf_getehdr(*elf, &ehdr)) {
                pr_debug("%s : cannot get elf header.\n", __func__);
                ret = -EBADF;
-               goto out_free_name;
+               goto out_free_args;
        }
 
        /* Adjust the prelink effect :
@@ -1923,6 +1948,8 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
        list_add_tail(&tmp->note_list, sdt_notes);
        return 0;
 
+out_free_args:
+       free(tmp->args);
 out_free_name:
        free(tmp->name);
 out_free_prov:
index 11cdde9805455b52563af827a9d9d352bd2ede35..40bf5d4c0bfd4a6bc9aa4564dc9613e66ca1d7b6 100644 (file)
@@ -1,6 +1,7 @@
 #include "symbol.h"
 #include "util.h"
 
+#include <errno.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <string.h>
@@ -373,3 +374,10 @@ int kcore_copy(const char *from_dir __maybe_unused,
 void symbol__elf_init(void)
 {
 }
+
+char *dso__demangle_sym(struct dso *dso __maybe_unused,
+                       int kmodule __maybe_unused,
+                       char *elf_name __maybe_unused)
+{
+       return NULL;
+}
index 9b4d8ba22fed85f1f2bef6f5d47dc88cbb4df5d1..8f2b068ff7564900c989d1cdec96757c1b3ab45b 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <linux/kernel.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/param.h>
@@ -18,6 +19,8 @@
 #include "strlist.h"
 #include "intlist.h"
 #include "header.h"
+#include "path.h"
+#include "sane_ctype.h"
 
 #include <elf.h>
 #include <limits.h>
@@ -87,6 +90,17 @@ static int prefix_underscores_count(const char *str)
        return tail - str;
 }
 
+int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
+{
+       return strcmp(namea, nameb);
+}
+
+int __weak arch__compare_symbol_names_n(const char *namea, const char *nameb,
+                                       unsigned int n)
+{
+       return strncmp(namea, nameb, n);
+}
+
 int __weak arch__choose_best_symbol(struct symbol *syma,
                                    struct symbol *symb __maybe_unused)
 {
@@ -396,8 +410,26 @@ static void symbols__sort_by_name(struct rb_root *symbols,
        }
 }
 
+int symbol__match_symbol_name(const char *name, const char *str,
+                             enum symbol_tag_include includes)
+{
+       const char *versioning;
+
+       if (includes == SYMBOL_TAG_INCLUDE__DEFAULT_ONLY &&
+           (versioning = strstr(name, "@@"))) {
+               int len = strlen(str);
+
+               if (len < versioning - name)
+                       len = versioning - name;
+
+               return arch__compare_symbol_names_n(name, str, len);
+       } else
+               return arch__compare_symbol_names(name, str);
+}
+
 static struct symbol *symbols__find_by_name(struct rb_root *symbols,
-                                           const char *name)
+                                           const char *name,
+                                           enum symbol_tag_include includes)
 {
        struct rb_node *n;
        struct symbol_name_rb_node *s = NULL;
@@ -411,11 +443,11 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
                int cmp;
 
                s = rb_entry(n, struct symbol_name_rb_node, rb_node);
-               cmp = arch__compare_symbol_names(name, s->sym.name);
+               cmp = symbol__match_symbol_name(s->sym.name, name, includes);
 
-               if (cmp < 0)
+               if (cmp > 0)
                        n = n->rb_left;
-               else if (cmp > 0)
+               else if (cmp < 0)
                        n = n->rb_right;
                else
                        break;
@@ -424,16 +456,17 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
        if (n == NULL)
                return NULL;
 
-       /* return first symbol that has same name (if any) */
-       for (n = rb_prev(n); n; n = rb_prev(n)) {
-               struct symbol_name_rb_node *tmp;
+       if (includes != SYMBOL_TAG_INCLUDE__DEFAULT_ONLY)
+               /* return first symbol that has same name (if any) */
+               for (n = rb_prev(n); n; n = rb_prev(n)) {
+                       struct symbol_name_rb_node *tmp;
 
-               tmp = rb_entry(n, struct symbol_name_rb_node, rb_node);
-               if (arch__compare_symbol_names(tmp->sym.name, s->sym.name))
-                       break;
+                       tmp = rb_entry(n, struct symbol_name_rb_node, rb_node);
+                       if (arch__compare_symbol_names(tmp->sym.name, s->sym.name))
+                               break;
 
-               s = tmp;
-       }
+                       s = tmp;
+               }
 
        return &s->sym;
 }
@@ -463,7 +496,7 @@ void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym)
 struct symbol *dso__find_symbol(struct dso *dso,
                                enum map_type type, u64 addr)
 {
-       if (dso->last_find_result[type].addr != addr) {
+       if (dso->last_find_result[type].addr != addr || dso->last_find_result[type].symbol == NULL) {
                dso->last_find_result[type].addr   = addr;
                dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr);
        }
@@ -500,7 +533,12 @@ struct symbol *symbol__next_by_name(struct symbol *sym)
 struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
                                        const char *name)
 {
-       return symbols__find_by_name(&dso->symbol_names[type], name);
+       struct symbol *s = symbols__find_by_name(&dso->symbol_names[type], name,
+                                                SYMBOL_TAG_INCLUDE__NONE);
+       if (!s)
+               s = symbols__find_by_name(&dso->symbol_names[type], name,
+                                         SYMBOL_TAG_INCLUDE__DEFAULT_ONLY);
+       return s;
 }
 
 void dso__sort_by_name(struct dso *dso, enum map_type type)
@@ -1072,8 +1110,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename,
        if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
                u64 start;
 
-               start = kallsyms__get_function_start(kallsyms_filename,
-                                                    kmap->ref_reloc_sym->name);
+               if (kallsyms__get_function_start(kallsyms_filename,
+                                                kmap->ref_reloc_sym->name, &start))
+                       return -ENOENT;
                if (start != kmap->ref_reloc_sym->addr)
                        return -EINVAL;
        }
@@ -1245,9 +1284,7 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
        if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
                return 0;
 
-       addr = kallsyms__get_function_start(filename,
-                                           kmap->ref_reloc_sym->name);
-       if (!addr)
+       if (kallsyms__get_function_start(filename, kmap->ref_reloc_sym->name, &addr))
                return -1;
 
        *delta = addr - kmap->ref_reloc_sym->addr;
index 6c358b7ed336c72fe9984c8f5b33fb3d200c638c..41ebba9a2eb2f3849635daf67125a851ff717d95 100644 (file)
@@ -13,7 +13,7 @@
 #include <libgen.h>
 #include "build-id.h"
 #include "event.h"
-#include "util.h"
+#include "path.h"
 
 #ifdef HAVE_LIBELF_SUPPORT
 #include <libelf.h>
@@ -118,7 +118,8 @@ struct symbol_conf {
                        show_ref_callgraph,
                        hide_unresolved,
                        raw_trace,
-                       report_hierarchy;
+                       report_hierarchy,
+                       inline_name;
        const char      *vmlinux_name,
                        *kallsyms_name,
                        *source_prefix,
@@ -305,6 +306,8 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
 int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
                                struct map *map);
 
+char *dso__demangle_sym(struct dso *dso, int kmodule, char *elf_name);
+
 void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
 void symbols__insert(struct rb_root *symbols, struct symbol *sym);
 void symbols__fixup_duplicate(struct rb_root *symbols);
@@ -345,12 +348,24 @@ void arch__sym_update(struct symbol *s, GElf_Sym *sym);
 #define SYMBOL_A 0
 #define SYMBOL_B 1
 
+int arch__compare_symbol_names(const char *namea, const char *nameb);
+int arch__compare_symbol_names_n(const char *namea, const char *nameb,
+                                unsigned int n);
 int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
 
+enum symbol_tag_include {
+       SYMBOL_TAG_INCLUDE__NONE = 0,
+       SYMBOL_TAG_INCLUDE__DEFAULT_ONLY
+};
+
+int symbol__match_symbol_name(const char *namea, const char *nameb,
+                             enum symbol_tag_include includes);
+
 /* structure containing an SDT note's info */
 struct sdt_note {
        char *name;                     /* name of the note*/
        char *provider;                 /* provider name */
+       char *args;
        bool bit32;                     /* whether the location is 32 bits? */
        union {                         /* location, base and semaphore addrs */
                Elf64_Addr a64[3];
index 90b47d8aa19c41305f4b0823e459d6e60f19f3f5..8f254a74d97deed4abc357d2d527ff1453a7c4f1 100644 (file)
@@ -1,4 +1,8 @@
-#include "util.h"
+#include "term.h"
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
 
 void get_term_dimensions(struct winsize *ws)
 {
index d3301529f6a762a17e5e390f8fd53286b5fc6145..dd17d6a38d3a1bc666a81c175e78295307ff40f9 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/rbtree.h>
 #include <linux/list.h>
+#include <errno.h>
 #include "thread.h"
 #include "event.h"
 #include "machine.h"
index f5af87f6666303df886d4c70fd2d565c1d0436e9..378c418ca0c173ddcc83425d590c32d3d71d2a39 100644 (file)
@@ -1,12 +1,15 @@
 #include "../perf.h"
+#include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <linux/kernel.h>
 #include "session.h"
 #include "thread.h"
 #include "thread-stack.h"
 #include "util.h"
 #include "debug.h"
+#include "namespaces.h"
 #include "comm.h"
 #include "unwind.h"
 
@@ -40,6 +43,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
                thread->tid = tid;
                thread->ppid = -1;
                thread->cpu = -1;
+               INIT_LIST_HEAD(&thread->namespaces_list);
                INIT_LIST_HEAD(&thread->comm_list);
 
                comm_str = malloc(32);
@@ -53,7 +57,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
                        goto err_thread;
 
                list_add(&comm->list, &thread->comm_list);
-               atomic_set(&thread->refcnt, 1);
+               refcount_set(&thread->refcnt, 1);
                RB_CLEAR_NODE(&thread->rb_node);
        }
 
@@ -66,7 +70,8 @@ err_thread:
 
 void thread__delete(struct thread *thread)
 {
-       struct comm *comm, *tmp;
+       struct namespaces *namespaces, *tmp_namespaces;
+       struct comm *comm, *tmp_comm;
 
        BUG_ON(!RB_EMPTY_NODE(&thread->rb_node));
 
@@ -76,7 +81,12 @@ void thread__delete(struct thread *thread)
                map_groups__put(thread->mg);
                thread->mg = NULL;
        }
-       list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
+       list_for_each_entry_safe(namespaces, tmp_namespaces,
+                                &thread->namespaces_list, list) {
+               list_del(&namespaces->list);
+               namespaces__free(namespaces);
+       }
+       list_for_each_entry_safe(comm, tmp_comm, &thread->comm_list, list) {
                list_del(&comm->list);
                comm__free(comm);
        }
@@ -88,13 +98,13 @@ void thread__delete(struct thread *thread)
 struct thread *thread__get(struct thread *thread)
 {
        if (thread)
-               atomic_inc(&thread->refcnt);
+               refcount_inc(&thread->refcnt);
        return thread;
 }
 
 void thread__put(struct thread *thread)
 {
-       if (thread && atomic_dec_and_test(&thread->refcnt)) {
+       if (thread && refcount_dec_and_test(&thread->refcnt)) {
                /*
                 * Remove it from the dead_threads list, as last reference
                 * is gone.
@@ -104,6 +114,38 @@ void thread__put(struct thread *thread)
        }
 }
 
+struct namespaces *thread__namespaces(const struct thread *thread)
+{
+       if (list_empty(&thread->namespaces_list))
+               return NULL;
+
+       return list_first_entry(&thread->namespaces_list, struct namespaces, list);
+}
+
+int thread__set_namespaces(struct thread *thread, u64 timestamp,
+                          struct namespaces_event *event)
+{
+       struct namespaces *new, *curr = thread__namespaces(thread);
+
+       new = namespaces__new(event);
+       if (!new)
+               return -ENOMEM;
+
+       list_add(&new->list, &thread->namespaces_list);
+
+       if (timestamp && curr) {
+               /*
+                * setns syscall must have changed few or all the namespaces
+                * of this thread. Update end time for the namespaces
+                * previously used.
+                */
+               curr = list_next_entry(new, list);
+               curr->end_time = timestamp;
+       }
+
+       return 0;
+}
+
 struct comm *thread__comm(const struct thread *thread)
 {
        if (list_empty(&thread->comm_list))
index 99263cb6e6b646bd987fc3ff410c2efa495f3944..4eb849e9098f5ca0115cb90527dd9f564476e4ea 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __PERF_THREAD_H
 #define __PERF_THREAD_H
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/rbtree.h>
 #include <linux/list.h>
 #include <unistd.h>
@@ -23,11 +23,12 @@ struct thread {
        pid_t                   tid;
        pid_t                   ppid;
        int                     cpu;
-       atomic_t                refcnt;
+       refcount_t              refcnt;
        char                    shortname[3];
        bool                    comm_set;
        int                     comm_len;
        bool                    dead; /* if set thread has exited */
+       struct list_head        namespaces_list;
        struct list_head        comm_list;
        u64                     db_id;
 
@@ -40,6 +41,7 @@ struct thread {
 };
 
 struct machine;
+struct namespaces;
 struct comm;
 
 struct thread *thread__new(pid_t pid, pid_t tid);
@@ -62,6 +64,10 @@ static inline void thread__exited(struct thread *thread)
        thread->dead = true;
 }
 
+struct namespaces *thread__namespaces(const struct thread *thread);
+int thread__set_namespaces(struct thread *thread, u64 timestamp,
+                          struct namespaces_event *event);
+
 int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
                       bool exec);
 static inline int thread__set_comm(struct thread *thread, const char *comm,
index 7c3fcc538a705f9df580c33b6444512547b3f453..63ead7b06324c1615ceacb9c421b7f47129f3f5e 100644 (file)
@@ -1,4 +1,5 @@
 #include <dirent.h>
+#include <errno.h>
 #include <limits.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -6,6 +7,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include "string2.h"
 #include "strlist.h"
 #include <string.h>
 #include <api/fs/fs.h>
@@ -66,7 +68,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
                for (i = 0; i < items; i++)
                        thread_map__set_pid(threads, i, atoi(namelist[i]->d_name));
                threads->nr = items;
-               atomic_set(&threads->refcnt, 1);
+               refcount_set(&threads->refcnt, 1);
        }
 
        for (i=0; i<items; i++)
@@ -83,7 +85,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
        if (threads != NULL) {
                thread_map__set_pid(threads, 0, tid);
                threads->nr = 1;
-               atomic_set(&threads->refcnt, 1);
+               refcount_set(&threads->refcnt, 1);
        }
 
        return threads;
@@ -105,7 +107,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
                goto out_free_threads;
 
        threads->nr = 0;
-       atomic_set(&threads->refcnt, 1);
+       refcount_set(&threads->refcnt, 1);
 
        while ((dirent = readdir(proc)) != NULL) {
                char *end;
@@ -235,7 +237,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
 out:
        strlist__delete(slist);
        if (threads)
-               atomic_set(&threads->refcnt, 1);
+               refcount_set(&threads->refcnt, 1);
        return threads;
 
 out_free_namelist:
@@ -255,7 +257,7 @@ struct thread_map *thread_map__new_dummy(void)
        if (threads != NULL) {
                thread_map__set_pid(threads, 0, -1);
                threads->nr = 1;
-               atomic_set(&threads->refcnt, 1);
+               refcount_set(&threads->refcnt, 1);
        }
        return threads;
 }
@@ -300,7 +302,7 @@ struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
        }
 out:
        if (threads)
-               atomic_set(&threads->refcnt, 1);
+               refcount_set(&threads->refcnt, 1);
        return threads;
 
 out_free_threads:
@@ -326,7 +328,7 @@ static void thread_map__delete(struct thread_map *threads)
        if (threads) {
                int i;
 
-               WARN_ONCE(atomic_read(&threads->refcnt) != 0,
+               WARN_ONCE(refcount_read(&threads->refcnt) != 0,
                          "thread map refcnt unbalanced\n");
                for (i = 0; i < threads->nr; i++)
                        free(thread_map__comm(threads, i));
@@ -337,13 +339,13 @@ static void thread_map__delete(struct thread_map *threads)
 struct thread_map *thread_map__get(struct thread_map *map)
 {
        if (map)
-               atomic_inc(&map->refcnt);
+               refcount_inc(&map->refcnt);
        return map;
 }
 
 void thread_map__put(struct thread_map *map)
 {
-       if (map && atomic_dec_and_test(&map->refcnt))
+       if (map && refcount_dec_and_test(&map->refcnt))
                thread_map__delete(map);
 }
 
@@ -423,7 +425,7 @@ static void thread_map__copy_event(struct thread_map *threads,
                threads->map[i].comm = strndup(event->entries[i].comm, 16);
        }
 
-       atomic_set(&threads->refcnt, 1);
+       refcount_set(&threads->refcnt, 1);
 }
 
 struct thread_map *thread_map__new_event(struct thread_map_event *event)
index ea0ef08c6303413b6ececf2b93ec905914e558aa..bd34d7a0b9fa9fbcd92224e3f83208f7479cac09 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <sys/types.h>
 #include <stdio.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 
 struct thread_map_data {
        pid_t    pid;
@@ -11,7 +11,7 @@ struct thread_map_data {
 };
 
 struct thread_map {
-       atomic_t refcnt;
+       refcount_t refcnt;
        int nr;
        struct thread_map_data map[];
 };
index d1b21c72206d8b1a6a52697adb3091ff09e81ec2..5b5d0214debdcb99c563c84abe4d98746ff6a518 100644 (file)
@@ -117,3 +117,28 @@ bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp)
 
        return false;
 }
+
+int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
+{
+       u64  sec = timestamp / NSEC_PER_SEC;
+       u64 usec = (timestamp % NSEC_PER_SEC) / NSEC_PER_USEC;
+
+       return scnprintf(buf, sz, "%"PRIu64".%06"PRIu64, sec, usec);
+}
+
+int fetch_current_timestamp(char *buf, size_t sz)
+{
+       struct timeval tv;
+       struct tm tm;
+       char dt[32];
+
+       if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
+               return -1;
+
+       if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
+               return -1;
+
+       scnprintf(buf, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
+
+       return 0;
+}
index c1f197c4af6c9aa019cdebc9625b07020f30ad4e..8656be08513b178ab64e4c716ca2d4f0a9378900 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef _TIME_UTILS_H_
 #define _TIME_UTILS_H_
 
+#include <stddef.h>
+#include <linux/types.h>
+
 struct perf_time_interval {
        u64 start, end;
 };
@@ -11,4 +14,8 @@ int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr);
 
 bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp);
 
+int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
+
+int fetch_current_timestamp(char *buf, size_t sz);
+
 #endif
index ac2590a3de2d1586fa60a1893d9ec4233967b5e0..829471a1c6d76bc637c5fcefbeaec89b8d61d39a 100644 (file)
@@ -40,6 +40,7 @@ struct perf_tool {
        event_op        mmap,
                        mmap2,
                        comm,
+                       namespaces,
                        fork,
                        exit,
                        lost,
@@ -66,6 +67,7 @@ struct perf_tool {
        event_op3       auxtrace;
        bool            ordered_events;
        bool            ordering_requires_timestamps;
+       bool            namespace_events;
 };
 
 #endif /* __PERF_TOOL_H */
index b2940c88734a01e280046f5c806c2a530fafc25a..9bdfb78a9a35d2b27a3c38bf5234af0af1f7985d 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/types.h>
 #include <stddef.h>
 #include <stdbool.h>
-#include <termios.h>
+#include <sys/ioctl.h>
 
 struct perf_evlist;
 struct perf_evsel;
index de0078e21408149fcf1105e357a3d829343233ff..746bbee645d98a69e3edabb73d92dd9a87da7422 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 #include <errno.h>
 
 #include "../perf.h"
 #include "util.h"
 #include "trace-event.h"
 
+#include "sane_ctype.h"
+
 static int get_common_field(struct scripting_context *context,
                            int *offset, int *size, const char *type)
 {
index 27420159bf6944df76eb76a45943a4810e0ba972..8a9a677f75768205c47343c126813808e564a38a 100644 (file)
@@ -192,7 +192,7 @@ static int read_ftrace_printk(struct pevent *pevent)
        if (!size)
                return 0;
 
-       buf = malloc(size);
+       buf = malloc(size + 1);
        if (buf == NULL)
                return -1;
 
@@ -201,6 +201,8 @@ static int read_ftrace_printk(struct pevent *pevent)
                return -1;
        }
 
+       buf[size] = '\0';
+
        parse_ftrace_printk(pevent, buf, size);
 
        free(buf);
diff --git a/tools/perf/util/units.c b/tools/perf/util/units.c
new file mode 100644 (file)
index 0000000..4767ec2
--- /dev/null
@@ -0,0 +1,68 @@
+#include "units.h"
+#include <inttypes.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <linux/kernel.h>
+#include <linux/time64.h>
+
+unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
+{
+       struct parse_tag *i = tags;
+
+       while (i->tag) {
+               char *s = strchr(str, i->tag);
+
+               if (s) {
+                       unsigned long int value;
+                       char *endptr;
+
+                       value = strtoul(str, &endptr, 10);
+                       if (s != endptr)
+                               break;
+
+                       if (value > ULONG_MAX / i->mult)
+                               break;
+                       value *= i->mult;
+                       return value;
+               }
+               i++;
+       }
+
+       return (unsigned long) -1;
+}
+
+unsigned long convert_unit(unsigned long value, char *unit)
+{
+       *unit = ' ';
+
+       if (value > 1000) {
+               value /= 1000;
+               *unit = 'K';
+       }
+
+       if (value > 1000) {
+               value /= 1000;
+               *unit = 'M';
+       }
+
+       if (value > 1000) {
+               value /= 1000;
+               *unit = 'G';
+       }
+
+       return value;
+}
+
+int unit_number__scnprintf(char *buf, size_t size, u64 n)
+{
+       char unit[4] = "BKMG";
+       int i = 0;
+
+       while (((n / 1024) > 1) && (i < 3)) {
+               n /= 1024;
+               i++;
+       }
+
+       return scnprintf(buf, size, "%" PRIu64 "%c", n, unit[i]);
+}
diff --git a/tools/perf/util/units.h b/tools/perf/util/units.h
new file mode 100644 (file)
index 0000000..f02c873
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef PERF_UNIT_H
+#define PERF_UNIT_H
+
+#include <stddef.h>
+#include <linux/types.h>
+
+struct parse_tag {
+       char tag;
+       int  mult;
+};
+
+unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
+
+unsigned long convert_unit(unsigned long value, char *unit);
+int unit_number__scnprintf(char *buf, size_t size, u64 n);
+
+#endif /* PERF_UNIT_H */
index 783a53fb7a4ed41c2fef9e90de26355e6b1bcc7e..f90e11a555b208302f9dd2a4163d73051e0d2f47 100644 (file)
@@ -12,6 +12,7 @@
 #include "event.h"
 #include "perf_regs.h"
 #include "callchain.h"
+#include "util.h"
 
 static char *debuginfo_path;
 
index 58328669ed16a7af3b475bb569b73310a48678df..4a2b269a7b3be24e766d892d475075984639b4cc 100644 (file)
@@ -2,10 +2,12 @@
 #define __PERF_UNWIND_LIBDW_H
 
 #include <elfutils/libdwfl.h>
-#include "event.h"
-#include "thread.h"
 #include "unwind.h"
 
+struct machine;
+struct perf_sample;
+struct thread;
+
 bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg);
 
 struct unwind_info {
index bfb9b7987692ee583104c54f7756c43ca13cf52e..f8455bed6e653705183b878c40d294991edf4e92 100644 (file)
  */
 
 #include <elf.h>
+#include <errno.h>
 #include <gelf.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/mman.h>
index 61fb1e90ff5166c6c1f50f8446650cf302aa610d..bfbdcc6198c9d85c09f9859866ac7974e8dd61c7 100644 (file)
@@ -1,10 +1,13 @@
 #ifndef __UNWIND_H
 #define __UNWIND_H
 
+#include <linux/compiler.h>
 #include <linux/types.h>
-#include "event.h"
-#include "symbol.h"
-#include "thread.h"
+
+struct map;
+struct perf_sample;
+struct symbol;
+struct thread;
 
 struct unwind_entry {
        struct map      *map;
index d8b45cea54d08233c3d743cc38c6c0ef7af90328..28c9f335006c962a5df924e30d9a45687775c201 100644 (file)
@@ -3,38 +3,22 @@
 #include "debug.h"
 #include <api/fs/fs.h>
 #include <sys/mman.h>
+#include <sys/stat.h>
 #include <sys/utsname.h>
-#ifdef HAVE_BACKTRACE_SUPPORT
-#include <execinfo.h>
-#endif
+#include <dirent.h>
+#include <inttypes.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <limits.h>
-#include <byteswap.h>
 #include <linux/kernel.h>
 #include <linux/log2.h>
 #include <linux/time64.h>
 #include <unistd.h>
-#include "callchain.h"
 #include "strlist.h"
 
-#define CALLCHAIN_PARAM_DEFAULT                        \
-       .mode           = CHAIN_GRAPH_ABS,      \
-       .min_percent    = 0.5,                  \
-       .order          = ORDER_CALLEE,         \
-       .key            = CCKEY_FUNCTION,       \
-       .value          = CCVAL_PERCENT,        \
-
-struct callchain_param callchain_param = {
-       CALLCHAIN_PARAM_DEFAULT
-};
-
-struct callchain_param callchain_param_default = {
-       CALLCHAIN_PARAM_DEFAULT
-};
-
 /*
  * XXX We need to find a better place for these things...
  */
@@ -269,28 +253,6 @@ int copyfile(const char *from, const char *to)
        return copyfile_mode(from, to, 0755);
 }
 
-unsigned long convert_unit(unsigned long value, char *unit)
-{
-       *unit = ' ';
-
-       if (value > 1000) {
-               value /= 1000;
-               *unit = 'K';
-       }
-
-       if (value > 1000) {
-               value /= 1000;
-               *unit = 'M';
-       }
-
-       if (value > 1000) {
-               value /= 1000;
-               *unit = 'G';
-       }
-
-       return value;
-}
-
 static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
 {
        void *buf_start = buf;
@@ -372,171 +334,6 @@ int hex2u64(const char *ptr, u64 *long_val)
        return p - ptr;
 }
 
-/* Obtain a backtrace and print it to stdout. */
-#ifdef HAVE_BACKTRACE_SUPPORT
-void dump_stack(void)
-{
-       void *array[16];
-       size_t size = backtrace(array, ARRAY_SIZE(array));
-       char **strings = backtrace_symbols(array, size);
-       size_t i;
-
-       printf("Obtained %zd stack frames.\n", size);
-
-       for (i = 0; i < size; i++)
-               printf("%s\n", strings[i]);
-
-       free(strings);
-}
-#else
-void dump_stack(void) {}
-#endif
-
-void sighandler_dump_stack(int sig)
-{
-       psignal(sig, "perf");
-       dump_stack();
-       signal(sig, SIG_DFL);
-       raise(sig);
-}
-
-int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
-{
-       u64  sec = timestamp / NSEC_PER_SEC;
-       u64 usec = (timestamp % NSEC_PER_SEC) / NSEC_PER_USEC;
-
-       return scnprintf(buf, sz, "%"PRIu64".%06"PRIu64, sec, usec);
-}
-
-unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
-{
-       struct parse_tag *i = tags;
-
-       while (i->tag) {
-               char *s;
-
-               s = strchr(str, i->tag);
-               if (s) {
-                       unsigned long int value;
-                       char *endptr;
-
-                       value = strtoul(str, &endptr, 10);
-                       if (s != endptr)
-                               break;
-
-                       if (value > ULONG_MAX / i->mult)
-                               break;
-                       value *= i->mult;
-                       return value;
-               }
-               i++;
-       }
-
-       return (unsigned long) -1;
-}
-
-int get_stack_size(const char *str, unsigned long *_size)
-{
-       char *endptr;
-       unsigned long size;
-       unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
-
-       size = strtoul(str, &endptr, 0);
-
-       do {
-               if (*endptr)
-                       break;
-
-               size = round_up(size, sizeof(u64));
-               if (!size || size > max_size)
-                       break;
-
-               *_size = size;
-               return 0;
-
-       } while (0);
-
-       pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
-              max_size, str);
-       return -1;
-}
-
-int parse_callchain_record(const char *arg, struct callchain_param *param)
-{
-       char *tok, *name, *saveptr = NULL;
-       char *buf;
-       int ret = -1;
-
-       /* We need buffer that we know we can write to. */
-       buf = malloc(strlen(arg) + 1);
-       if (!buf)
-               return -ENOMEM;
-
-       strcpy(buf, arg);
-
-       tok = strtok_r((char *)buf, ",", &saveptr);
-       name = tok ? : (char *)buf;
-
-       do {
-               /* Framepointer style */
-               if (!strncmp(name, "fp", sizeof("fp"))) {
-                       if (!strtok_r(NULL, ",", &saveptr)) {
-                               param->record_mode = CALLCHAIN_FP;
-                               ret = 0;
-                       } else
-                               pr_err("callchain: No more arguments "
-                                      "needed for --call-graph fp\n");
-                       break;
-
-               /* Dwarf style */
-               } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
-                       const unsigned long default_stack_dump_size = 8192;
-
-                       ret = 0;
-                       param->record_mode = CALLCHAIN_DWARF;
-                       param->dump_size = default_stack_dump_size;
-
-                       tok = strtok_r(NULL, ",", &saveptr);
-                       if (tok) {
-                               unsigned long size = 0;
-
-                               ret = get_stack_size(tok, &size);
-                               param->dump_size = size;
-                       }
-               } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
-                       if (!strtok_r(NULL, ",", &saveptr)) {
-                               param->record_mode = CALLCHAIN_LBR;
-                               ret = 0;
-                       } else
-                               pr_err("callchain: No more arguments "
-                                       "needed for --call-graph lbr\n");
-                       break;
-               } else {
-                       pr_err("callchain: Unknown --call-graph option "
-                              "value: %s\n", arg);
-                       break;
-               }
-
-       } while (0);
-
-       free(buf);
-       return ret;
-}
-
-const char *get_filename_for_perf_kvm(void)
-{
-       const char *filename;
-
-       if (perf_host && !perf_guest)
-               filename = strdup("perf.data.host");
-       else if (!perf_host && perf_guest)
-               filename = strdup("perf.data.guest");
-       else
-               filename = strdup("perf.data.kvm");
-
-       return filename;
-}
-
 int perf_event_paranoid(void)
 {
        int value;
@@ -547,27 +344,6 @@ int perf_event_paranoid(void)
        return value;
 }
 
-void mem_bswap_32(void *src, int byte_size)
-{
-       u32 *m = src;
-       while (byte_size > 0) {
-               *m = bswap_32(*m);
-               byte_size -= sizeof(u32);
-               ++m;
-       }
-}
-
-void mem_bswap_64(void *src, int byte_size)
-{
-       u64 *m = src;
-
-       while (byte_size > 0) {
-               *m = bswap_64(*m);
-               byte_size -= sizeof(u64);
-               ++m;
-       }
-}
-
 bool find_process(const char *name)
 {
        size_t len = strlen(name);
@@ -696,7 +472,8 @@ const char *perf_tip(const char *dirpath)
 
        tips = strlist__new("tips.txt", &conf);
        if (tips == NULL)
-               return errno == ENOENT ? NULL : "Tip: get more memory! ;-p";
+               return errno == ENOENT ? NULL :
+                       "Tip: check path of tips.txt or get more memory! ;-p";
 
        if (strlist__nr_entries(tips) == 0)
                goto out;
@@ -710,95 +487,3 @@ out:
 
        return tip;
 }
-
-bool is_regular_file(const char *file)
-{
-       struct stat st;
-
-       if (stat(file, &st))
-               return false;
-
-       return S_ISREG(st.st_mode);
-}
-
-int fetch_current_timestamp(char *buf, size_t sz)
-{
-       struct timeval tv;
-       struct tm tm;
-       char dt[32];
-
-       if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
-               return -1;
-
-       if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
-               return -1;
-
-       scnprintf(buf, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
-
-       return 0;
-}
-
-void print_binary(unsigned char *data, size_t len,
-                 size_t bytes_per_line, print_binary_t printer,
-                 void *extra)
-{
-       size_t i, j, mask;
-
-       if (!printer)
-               return;
-
-       bytes_per_line = roundup_pow_of_two(bytes_per_line);
-       mask = bytes_per_line - 1;
-
-       printer(BINARY_PRINT_DATA_BEGIN, 0, extra);
-       for (i = 0; i < len; i++) {
-               if ((i & mask) == 0) {
-                       printer(BINARY_PRINT_LINE_BEGIN, -1, extra);
-                       printer(BINARY_PRINT_ADDR, i, extra);
-               }
-
-               printer(BINARY_PRINT_NUM_DATA, data[i], extra);
-
-               if (((i & mask) == mask) || i == len - 1) {
-                       for (j = 0; j < mask-(i & mask); j++)
-                               printer(BINARY_PRINT_NUM_PAD, -1, extra);
-
-                       printer(BINARY_PRINT_SEP, i, extra);
-                       for (j = i & ~mask; j <= i; j++)
-                               printer(BINARY_PRINT_CHAR_DATA, data[j], extra);
-                       for (j = 0; j < mask-(i & mask); j++)
-                               printer(BINARY_PRINT_CHAR_PAD, i, extra);
-                       printer(BINARY_PRINT_LINE_END, -1, extra);
-               }
-       }
-       printer(BINARY_PRINT_DATA_END, -1, extra);
-}
-
-int is_printable_array(char *p, unsigned int len)
-{
-       unsigned int i;
-
-       if (!p || !len || p[len - 1] != 0)
-               return 0;
-
-       len--;
-
-       for (i = 0; i < len; i++) {
-               if (!isprint(p[i]) && !isspace(p[i]))
-                       return 0;
-       }
-       return 1;
-}
-
-int unit_number__scnprintf(char *buf, size_t size, u64 n)
-{
-       char unit[4] = "BKMG";
-       int i = 0;
-
-       while (((n / 1024) > 1) && (i < 3)) {
-               n /= 1024;
-               i++;
-       }
-
-       return scnprintf(buf, size, "%" PRIu64 "%c", n, unit[i]);
-}
index c74708da857129356e2a308cd987dec34f371104..5dfb9bb6482d3103d494a9234fef50b308b3d7ef 100644 (file)
 #ifndef GIT_COMPAT_UTIL_H
 #define GIT_COMPAT_UTIL_H
 
-#ifndef FLEX_ARRAY
-/*
- * See if our compiler is known to support flexible array members.
- */
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-# define FLEX_ARRAY /* empty */
-#elif defined(__GNUC__)
-# if (__GNUC__ >= 3)
-#  define FLEX_ARRAY /* empty */
-# else
-#  define FLEX_ARRAY 0 /* older GNU extension */
-# endif
-#endif
-
-/*
- * Otherwise, default to safer but a bit wasteful traditional style
- */
-#ifndef FLEX_ARRAY
-# define FLEX_ARRAY 1
-#endif
-#endif
-
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
-
-#ifdef __GNUC__
-#define TYPEOF(x) (__typeof__(x))
-#else
-#define TYPEOF(x)
-#endif
-
-#define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
-#define HAS_MULTI_BITS(i)  ((i) & ((i) - 1))  /* checks if an integer has more than 1 bit set */
-
-/* Approximation of the length of the decimal representation of this type. */
-#define decimal_length(x)      ((int)(sizeof(x) * 2.56 + 0.5) + 1)
-
 #define _ALL_SOURCE 1
 #define _BSD_SOURCE 1
 /* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
 #define _DEFAULT_SOURCE 1
-#define HAS_BOOL
 
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
 #include <fcntl.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <stdarg.h>
-#include <string.h>
-#include <term.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <time.h>
-#include <signal.h>
-#include <fnmatch.h>
-#include <assert.h>
-#include <regex.h>
-#include <utime.h>
-#include <sys/wait.h>
-#include <poll.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <inttypes.h>
-#include <linux/kernel.h>
 #include <linux/types.h>
-#include <sys/ttydefaults.h>
-#include <api/fs/tracing_path.h>
-#include <termios.h>
-#include <linux/bitops.h>
-#include <termios.h>
-#include "strlist.h"
-
-extern const char *graph_line;
-extern const char *graph_dotted_line;
-extern const char *spaces;
-extern const char *dots;
-extern char buildid_dir[];
-
-/* On most systems <limits.h> would have given us this, but
- * not on some systems (e.g. GNU/Hurd).
- */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-#ifndef PRIuMAX
-#define PRIuMAX "llu"
-#endif
-
-#ifndef PRIu32
-#define PRIu32 "u"
-#endif
-
-#ifndef PRIx32
-#define PRIx32 "x"
-#endif
-
-#ifndef PATH_SEP
-#define PATH_SEP ':'
-#endif
-
-#ifndef STRIP_EXTENSION
-#define STRIP_EXTENSION ""
-#endif
-
-#ifndef has_dos_drive_prefix
-#define has_dos_drive_prefix(path) 0
-#endif
-
-#ifndef is_dir_sep
-#define is_dir_sep(c) ((c) == '/')
-#endif
 
 #ifdef __GNUC__
 #define NORETURN __attribute__((__noreturn__))
@@ -130,8 +22,6 @@ extern char buildid_dir[];
 #endif
 #endif
 
-#define PERF_GTK_DSO  "libperf-gtk.so"
-
 /* General helper functions */
 void usage(const char *err) NORETURN;
 void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
@@ -140,25 +30,6 @@ void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
 
 void set_warning_routine(void (*routine)(const char *err, va_list params));
 
-int prefixcmp(const char *str, const char *prefix);
-void set_buildid_dir(const char *dir);
-
-#ifdef __GLIBC_PREREQ
-#if __GLIBC_PREREQ(2, 1)
-#define HAVE_STRCHRNUL
-#endif
-#endif
-
-#ifndef HAVE_STRCHRNUL
-#define strchrnul gitstrchrnul
-static inline char *gitstrchrnul(const char *s, int c)
-{
-       while (*s && *s != c)
-               s++;
-       return (char *)s;
-}
-#endif
-
 static inline void *zalloc(size_t size)
 {
        return calloc(1, size);
@@ -166,47 +37,8 @@ static inline void *zalloc(size_t size)
 
 #define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
 
-/* Sane ctype - no locale, and works with signed chars */
-#undef isascii
-#undef isspace
-#undef isdigit
-#undef isxdigit
-#undef isalpha
-#undef isprint
-#undef isalnum
-#undef islower
-#undef isupper
-#undef tolower
-#undef toupper
-
-extern unsigned char sane_ctype[256];
-#define GIT_SPACE              0x01
-#define GIT_DIGIT              0x02
-#define GIT_ALPHA              0x04
-#define GIT_GLOB_SPECIAL       0x08
-#define GIT_REGEX_SPECIAL      0x10
-#define GIT_PRINT_EXTRA                0x20
-#define GIT_PRINT              0x3E
-#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
-#define isascii(x) (((x) & ~0x7f) == 0)
-#define isspace(x) sane_istest(x,GIT_SPACE)
-#define isdigit(x) sane_istest(x,GIT_DIGIT)
-#define isxdigit(x)    \
-       (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G')
-#define isalpha(x) sane_istest(x,GIT_ALPHA)
-#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
-#define isprint(x) sane_istest(x,GIT_PRINT)
-#define islower(x) (sane_istest(x,GIT_ALPHA) && (x & 0x20))
-#define isupper(x) (sane_istest(x,GIT_ALPHA) && !(x & 0x20))
-#define tolower(x) sane_case((unsigned char)(x), 0x20)
-#define toupper(x) sane_case((unsigned char)(x), 0)
-
-static inline int sane_case(int x, int high)
-{
-       if (sane_istest(x, GIT_ALPHA))
-               x = (x & ~0x20) | high;
-       return x;
-}
+struct dirent;
+struct strlist;
 
 int mkdir_p(char *path, mode_t mode);
 int rm_rf(const char *path);
@@ -216,112 +48,17 @@ int copyfile(const char *from, const char *to);
 int copyfile_mode(const char *from, const char *to, mode_t mode);
 int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);
 
-s64 perf_atoll(const char *str);
-char **argv_split(const char *str, int *argcp);
-void argv_free(char **argv);
-bool strglobmatch(const char *str, const char *pat);
-bool strglobmatch_nocase(const char *str, const char *pat);
-bool strlazymatch(const char *str, const char *pat);
-static inline bool strisglob(const char *str)
-{
-       return strpbrk(str, "*?[") != NULL;
-}
-int strtailcmp(const char *s1, const char *s2);
-char *strxfrchar(char *s, char from, char to);
-unsigned long convert_unit(unsigned long value, char *unit);
 ssize_t readn(int fd, void *buf, size_t n);
 ssize_t writen(int fd, void *buf, size_t n);
 
-struct perf_event_attr;
-
-void event_attr_init(struct perf_event_attr *attr);
-
-#define _STR(x) #x
-#define STR(x) _STR(x)
-
 size_t hex_width(u64 v);
 int hex2u64(const char *ptr, u64 *val);
 
-char *ltrim(char *s);
-char *rtrim(char *s);
-
-static inline char *trim(char *s)
-{
-       return ltrim(rtrim(s));
-}
-
-void dump_stack(void);
-void sighandler_dump_stack(int sig);
-
 extern unsigned int page_size;
 extern int cacheline_size;
-extern int sysctl_perf_event_max_stack;
-extern int sysctl_perf_event_max_contexts_per_stack;
-
-struct parse_tag {
-       char tag;
-       int mult;
-};
-
-unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
-
-#define SRCLINE_UNKNOWN  ((char *) "??:0")
-
-static inline int path__join(char *bf, size_t size,
-                            const char *path1, const char *path2)
-{
-       return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2);
-}
-
-static inline int path__join3(char *bf, size_t size,
-                             const char *path1, const char *path2,
-                             const char *path3)
-{
-       return scnprintf(bf, size, "%s%s%s%s%s",
-                        path1, path1[0] ? "/" : "",
-                        path2, path2[0] ? "/" : "", path3);
-}
-
-struct dso;
-struct symbol;
 
-extern bool srcline_full_filename;
-char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
-                 bool show_sym);
-char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
-                 bool show_sym, bool unwind_inlines);
-void free_srcline(char *srcline);
-
-int perf_event_paranoid(void);
-
-void mem_bswap_64(void *src, int byte_size);
-void mem_bswap_32(void *src, int byte_size);
-
-const char *get_filename_for_perf_kvm(void);
 bool find_process(const char *name);
 
-#ifdef HAVE_ZLIB_SUPPORT
-int gzip_decompress_to_file(const char *input, int output_fd);
-#endif
-
-#ifdef HAVE_LZMA_SUPPORT
-int lzma_decompress_to_file(const char *input, int output_fd);
-#endif
-
-char *asprintf_expr_inout_ints(const char *var, bool in, size_t nints, int *ints);
-
-static inline char *asprintf_expr_in_ints(const char *var, size_t nints, int *ints)
-{
-       return asprintf_expr_inout_ints(var, true, nints, ints);
-}
-
-static inline char *asprintf_expr_not_in_ints(const char *var, size_t nints, int *ints)
-{
-       return asprintf_expr_inout_ints(var, false, nints, ints);
-}
-
-int get_stack_size(const char *str, unsigned long *_size);
-
 int fetch_kernel_version(unsigned int *puint,
                         char *str, size_t str_sz);
 #define KVER_VERSION(x)                (((x) >> 16) & 0xff)
@@ -331,37 +68,9 @@ int fetch_kernel_version(unsigned int *puint,
 #define KVER_PARAM(x)  KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
 
 const char *perf_tip(const char *dirpath);
-bool is_regular_file(const char *file);
-int fetch_current_timestamp(char *buf, size_t sz);
 
-enum binary_printer_ops {
-       BINARY_PRINT_DATA_BEGIN,
-       BINARY_PRINT_LINE_BEGIN,
-       BINARY_PRINT_ADDR,
-       BINARY_PRINT_NUM_DATA,
-       BINARY_PRINT_NUM_PAD,
-       BINARY_PRINT_SEP,
-       BINARY_PRINT_CHAR_DATA,
-       BINARY_PRINT_CHAR_PAD,
-       BINARY_PRINT_LINE_END,
-       BINARY_PRINT_DATA_END,
-};
-
-typedef void (*print_binary_t)(enum binary_printer_ops,
-                              unsigned int val,
-                              void *extra);
-
-void print_binary(unsigned char *data, size_t len,
-                 size_t bytes_per_line, print_binary_t printer,
-                 void *extra);
-
-#if !defined(__GLIBC__) && !defined(__ANDROID__)
-extern int sched_getcpu(void);
+#ifndef HAVE_SCHED_GETCPU_SUPPORT
+int sched_getcpu(void);
 #endif
 
-int is_printable_array(char *p, unsigned int len);
-
-int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
-
-int unit_number__scnprintf(char *buf, size_t size, u64 n);
 #endif /* GIT_COMPAT_UTIL_H */
index 5074be4ed467bcad894ccb2ed9936d593f12907f..5de2e15e2eda9c343246431caf0ba68d9559e614 100644 (file)
@@ -1,4 +1,7 @@
+#include <inttypes.h>
+#include <stdio.h>
 #include <stdlib.h>
+#include <errno.h>
 
 #include "util.h"
 #include "values.h"
@@ -108,24 +111,45 @@ static int perf_read_values__findnew_thread(struct perf_read_values *values,
        return i;
 }
 
-static void perf_read_values__enlarge_counters(struct perf_read_values *values)
+static int perf_read_values__enlarge_counters(struct perf_read_values *values)
 {
-       int i;
+       char **countername;
+       int i, counters_max = values->counters_max * 2;
+       u64 *counterrawid = realloc(values->counterrawid, counters_max * sizeof(*values->counterrawid));
+
+       if (!counterrawid) {
+               pr_debug("failed to enlarge read_values rawid array");
+               goto out_enomem;
+       }
 
-       values->counters_max *= 2;
-       values->counterrawid = realloc(values->counterrawid,
-                                      values->counters_max * sizeof(*values->counterrawid));
-       values->countername = realloc(values->countername,
-                                     values->counters_max * sizeof(*values->countername));
-       if (!values->counterrawid || !values->countername)
-               die("failed to enlarge read_values counters arrays");
+       countername = realloc(values->countername, counters_max * sizeof(*values->countername));
+       if (!countername) {
+               pr_debug("failed to enlarge read_values rawid array");
+               goto out_free_rawid;
+       }
 
        for (i = 0; i < values->threads; i++) {
-               values->value[i] = realloc(values->value[i],
-                                          values->counters_max * sizeof(**values->value));
-               if (!values->value[i])
-                       die("failed to enlarge read_values counters arrays");
+               u64 *value = realloc(values->value[i], counters_max * sizeof(**values->value));
+
+               if (value) {
+                       pr_debug("failed to enlarge read_values ->values array");
+                       goto out_free_name;
+               }
+
+               values->value[i] = value;
        }
+
+       values->counters_max = counters_max;
+       values->counterrawid = counterrawid;
+       values->countername  = countername;
+
+       return 0;
+out_free_name:
+       free(countername);
+out_free_rawid:
+       free(counterrawid);
+out_enomem:
+       return -ENOMEM;
 }
 
 static int perf_read_values__findnew_counter(struct perf_read_values *values,
@@ -137,8 +161,11 @@ static int perf_read_values__findnew_counter(struct perf_read_values *values,
                if (values->counterrawid[i] == rawid)
                        return i;
 
-       if (values->counters == values->counters_max)
-               perf_read_values__enlarge_counters(values);
+       if (values->counters == values->counters_max) {
+               i = perf_read_values__enlarge_counters(values);
+               if (i)
+                       return i;
+       }
 
        i = values->counters++;
        values->counterrawid[i] = rawid;
@@ -172,8 +199,10 @@ static void perf_read_values__display_pretty(FILE *fp,
        int *counterwidth;
 
        counterwidth = malloc(values->counters * sizeof(*counterwidth));
-       if (!counterwidth)
-               die("failed to allocate counterwidth array");
+       if (!counterwidth) {
+               fprintf(fp, "INTERNAL ERROR: Failed to allocate counterwidth array\n");
+               return;
+       }
        tidwidth = 3;
        pidwidth = 3;
        for (j = 0; j < values->counters; j++)
index 7bdcad484225f13ed96ff07eb355a45acb997ac5..d3c39eec89a85b64f724bf27466c3dabc15a1029 100644 (file)
@@ -1,4 +1,4 @@
-
+#include <errno.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <string.h>
index c10ba41ef3f6298eb77e624f7f1b14f41555c36c..7251fdbabceda5e0bb88e4b9ae83f501ea9ad517 100644 (file)
@@ -1,5 +1,7 @@
 #include "xyarray.h"
 #include "util.h"
+#include <stdlib.h>
+#include <string.h>
 
 struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
 {
index 495a449fc25c35456c69f5e235fa8cbaff11d41c..1329d843eb7b4ef490517a8d631054151575106d 100644 (file)
@@ -4,6 +4,7 @@
 #include <sys/mman.h>
 #include <zlib.h>
 
+#include "util/compress.h"
 #include "util/util.h"
 #include "util/debug.h"
 
index 621578aa12d6fe456134369b97968126c3a1981e..fc74db62fef4d11851422586a87eb5dee6b17176 100644 (file)
@@ -43,6 +43,15 @@ ifneq ($(CC), clang)
 EXTRA_WARNINGS += -Wstrict-aliasing=3
 endif
 
+# Hack to avoid type-punned warnings on old systems such as RHEL5:
+# We should be changing CFLAGS and checking gcc version, but this
+# will do for now and keep the above -Wstrict-aliasing=3 in place
+# in newer systems.
+# Needed for the __raw_cmpxchg in tools/arch/x86/include/asm/cmpxchg.h
+ifneq ($(filter 3.%,$(MAKE_VERSION)),)  # make-3
+EXTRA_WARNINGS += -fno-strict-aliasing
+endif
+
 ifneq ($(findstring $(MAKEFLAGS), w),w)
 PRINT_DIR = --no-print-directory
 else