Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 6 Mar 2019 15:59:36 +0000 (07:59 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 6 Mar 2019 15:59:36 +0000 (07:59 -0800)
Pull perf updates from Ingo Molnar:
 "Lots of tooling updates - too many to list, here's a few highlights:

   - Various subcommand updates to 'perf trace', 'perf report', 'perf
     record', 'perf annotate', 'perf script', 'perf test', etc.

   - CPU and NUMA topology and affinity handling improvements,

   - HW tracing and HW support updates:
      - Intel PT updates
      - ARM CoreSight updates
      - vendor HW event updates

   - BPF updates

   - Tons of infrastructure updates, both on the build system and the
     library support side

   - Documentation updates.

   - ... and lots of other changes, see the changelog for details.

  Kernel side updates:

   - Tighten up kprobes blacklist handling, reduce the number of places
     where developers can install a kprobe and hang/crash the system.

   - Fix/enhance vma address filter handling.

   - Various PMU driver updates, small fixes and additions.

   - refcount_t conversions

   - BPF updates

   - error code propagation enhancements

   - misc other changes"

* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (238 commits)
  perf script python: Add Python3 support to syscall-counts-by-pid.py
  perf script python: Add Python3 support to syscall-counts.py
  perf script python: Add Python3 support to stat-cpi.py
  perf script python: Add Python3 support to stackcollapse.py
  perf script python: Add Python3 support to sctop.py
  perf script python: Add Python3 support to powerpc-hcalls.py
  perf script python: Add Python3 support to net_dropmonitor.py
  perf script python: Add Python3 support to mem-phys-addr.py
  perf script python: Add Python3 support to failed-syscalls-by-pid.py
  perf script python: Add Python3 support to netdev-times.py
  perf tools: Add perf_exe() helper to find perf binary
  perf script: Handle missing fields with -F +..
  perf data: Add perf_data__open_dir_data function
  perf data: Add perf_data__(create_dir|close_dir) functions
  perf data: Fail check_backup in case of error
  perf data: Make check_backup work over directories
  perf tools: Add rm_rf_perf_data function
  perf tools: Add pattern name checking to rm_rf
  perf tools: Add depth checking to rm_rf
  perf data: Add global path holder
  ...

315 files changed:
arch/alpha/kernel/perf_event.c
arch/arm/mach-imx/mmdc.c
arch/arm/mm/cache-l2x0-pmu.c
arch/powerpc/perf/hv-24x7.c
arch/powerpc/perf/hv-gpci.c
arch/powerpc/perf/imc-pmu.c
arch/s390/kernel/perf_cpum_sf.c
arch/x86/events/amd/ibs.c
arch/x86/events/amd/iommu.c
arch/x86/events/amd/power.c
arch/x86/events/amd/uncore.c
arch/x86/events/intel/bts.c
arch/x86/events/intel/core.c
arch/x86/events/intel/cstate.c
arch/x86/events/intel/ds.c
arch/x86/events/intel/pt.c
arch/x86/events/intel/rapl.c
arch/x86/events/intel/uncore.c
arch/x86/events/intel/uncore_snb.c
arch/x86/events/msr.c
arch/x86/events/perf_event.h
arch/x86/include/asm/cpu_device_id.h
arch/x86/kernel/alternative.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/match.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kprobes/opt.c
arch/x86/kernel/traps.c
drivers/hwtracing/coresight/coresight-etm-perf.c
drivers/hwtracing/coresight/coresight-etm-perf.h
drivers/hwtracing/coresight/coresight-priv.h
drivers/hwtracing/coresight/coresight.c
drivers/perf/arm-cci.c
drivers/perf/arm-ccn.c
drivers/perf/arm_dsu_pmu.c
drivers/perf/arm_pmu.c
drivers/perf/arm_spe_pmu.c
drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
drivers/perf/hisilicon/hisi_uncore_pmu.c
drivers/perf/qcom_l2_pmu.c
drivers/perf/qcom_l3_pmu.c
drivers/perf/thunderx2_pmu.c
drivers/perf/xgene_pmu.c
include/linux/coresight.h
include/linux/filter.h
include/linux/perf_event.h
include/uapi/linux/perf_event.h
kernel/bpf/core.c
kernel/bpf/syscall.c
kernel/events/callchain.c
kernel/events/core.c
kernel/events/hw_breakpoint.c
kernel/events/internal.h
kernel/events/ring_buffer.c
kernel/events/uprobes.c
kernel/kallsyms.c
kernel/kprobes.c
kernel/locking/lockdep.c
kernel/rcu/tree.c
kernel/rcu/update.c
kernel/trace/bpf_trace.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_preemptirq.c
lib/bsearch.c
lib/smp_processor_id.c
tools/build/Makefile.feature
tools/build/feature/test-all.c
tools/build/feature/test-get_current_dir_name.c
tools/build/feature/test-libpython.c
tools/build/feature/test-reallocarray.c
tools/build/feature/test-sched_getcpu.c
tools/build/feature/test-setns.c
tools/include/linux/rbtree.h
tools/include/linux/rbtree_augmented.h
tools/include/uapi/linux/perf_event.h
tools/lib/rbtree.c
tools/perf/Build
tools/perf/Documentation/perf-config.txt
tools/perf/Documentation/perf-record.txt
tools/perf/Documentation/perf-script.txt
tools/perf/Documentation/perf-trace.txt
tools/perf/Documentation/perf.data-file-format.txt
tools/perf/Makefile.config
tools/perf/Makefile.perf
tools/perf/arch/Build
tools/perf/arch/arm/Build
tools/perf/arch/arm/tests/Build
tools/perf/arch/arm/tests/dwarf-unwind.c
tools/perf/arch/arm/util/Build
tools/perf/arch/arm/util/cs-etm.c
tools/perf/arch/arm/util/cs-etm.h
tools/perf/arch/arm/util/pmu.c
tools/perf/arch/arm64/Build
tools/perf/arch/arm64/tests/Build
tools/perf/arch/arm64/tests/dwarf-unwind.c
tools/perf/arch/arm64/util/Build
tools/perf/arch/nds32/Build
tools/perf/arch/nds32/util/Build
tools/perf/arch/powerpc/Build
tools/perf/arch/powerpc/tests/Build
tools/perf/arch/powerpc/tests/dwarf-unwind.c
tools/perf/arch/powerpc/util/Build
tools/perf/arch/powerpc/util/kvm-stat.c
tools/perf/arch/powerpc/util/skip-callchain-idx.c
tools/perf/arch/s390/Build
tools/perf/arch/s390/util/Build
tools/perf/arch/s390/util/kvm-stat.c
tools/perf/arch/sh/Build
tools/perf/arch/sh/util/Build
tools/perf/arch/sparc/Build
tools/perf/arch/sparc/util/Build
tools/perf/arch/x86/Build
tools/perf/arch/x86/tests/Build
tools/perf/arch/x86/tests/dwarf-unwind.c
tools/perf/arch/x86/util/Build
tools/perf/arch/x86/util/kvm-stat.c
tools/perf/arch/xtensa/Build
tools/perf/arch/xtensa/util/Build
tools/perf/builtin-annotate.c
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-buildid-list.c
tools/perf/builtin-c2c.c
tools/perf/builtin-diff.c
tools/perf/builtin-evlist.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/design.txt
tools/perf/examples/bpf/augmented_raw_syscalls.c
tools/perf/examples/bpf/augmented_syscalls.c
tools/perf/examples/bpf/etcsnoop.c
tools/perf/include/bpf/bpf.h
tools/perf/perf.h
tools/perf/pmu-events/arch/powerpc/power8/metrics.json [new file with mode: 0644]
tools/perf/pmu-events/arch/powerpc/power9/metrics.json [new file with mode: 0644]
tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json
tools/perf/scripts/Build
tools/perf/scripts/perl/Perf-Trace-Util/Build
tools/perf/scripts/python/Perf-Trace-Util/Build
tools/perf/scripts/python/export-to-postgresql.py
tools/perf/scripts/python/export-to-sqlite.py
tools/perf/scripts/python/exported-sql-viewer.py
tools/perf/scripts/python/failed-syscalls-by-pid.py
tools/perf/scripts/python/mem-phys-addr.py
tools/perf/scripts/python/net_dropmonitor.py
tools/perf/scripts/python/netdev-times.py
tools/perf/scripts/python/powerpc-hcalls.py
tools/perf/scripts/python/sched-migration.py
tools/perf/scripts/python/sctop.py
tools/perf/scripts/python/stackcollapse.py
tools/perf/scripts/python/stat-cpi.py
tools/perf/scripts/python/syscall-counts-by-pid.py
tools/perf/scripts/python/syscall-counts.py
tools/perf/tests/attr.py
tools/perf/tests/bp_account.c
tools/perf/tests/code-reading.c
tools/perf/tests/dwarf-unwind.c
tools/perf/tests/evsel-tp-sched.c
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/mmap-thread-lookup.c
tools/perf/tests/parse-events.c
tools/perf/tests/pmu.c
tools/perf/tests/sample-parsing.c
tools/perf/tests/sdt.c
tools/perf/tests/shell/lib/probe.sh
tools/perf/tests/shell/trace+probe_vfs_getname.sh
tools/perf/trace/beauty/Build
tools/perf/trace/beauty/ioctl.c
tools/perf/trace/beauty/waitid_options.c
tools/perf/ui/Build
tools/perf/ui/browsers/Build
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/stdio/hist.c
tools/perf/ui/tui/Build
tools/perf/util/Build
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/auxtrace.c
tools/perf/util/auxtrace.h
tools/perf/util/block-range.c
tools/perf/util/block-range.h
tools/perf/util/bpf-event.c [new file with mode: 0644]
tools/perf/util/bpf-event.h [new file with mode: 0644]
tools/perf/util/bpf-loader.c
tools/perf/util/bpf-loader.h
tools/perf/util/bpf_map.c [new file with mode: 0644]
tools/perf/util/bpf_map.h [new file with mode: 0644]
tools/perf/util/branch.h
tools/perf/util/build-id.c
tools/perf/util/build-id.h
tools/perf/util/c++/Build
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/color.c
tools/perf/util/color.h
tools/perf/util/color_config.c [new file with mode: 0644]
tools/perf/util/comm.c
tools/perf/util/comm.h
tools/perf/util/config.c
tools/perf/util/cpu-set-sched.h [new file with mode: 0644]
tools/perf/util/cpumap.c
tools/perf/util/cpumap.h
tools/perf/util/cputopo.c [new file with mode: 0644]
tools/perf/util/cputopo.h [new file with mode: 0644]
tools/perf/util/cs-etm-decoder/Build
tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
tools/perf/util/cs-etm.c
tools/perf/util/cs-etm.h
tools/perf/util/data-convert-bt.c
tools/perf/util/data.c
tools/perf/util/data.h
tools/perf/util/db-export.c
tools/perf/util/drv_configs.c [deleted file]
tools/perf/util/drv_configs.h [deleted file]
tools/perf/util/dso.c
tools/perf/util/dso.h
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/header.c
tools/perf/util/hist.c
tools/perf/util/hist.h
tools/perf/util/intel-bts.c
tools/perf/util/intel-pt-decoder/Build
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
tools/perf/util/intel-pt.c
tools/perf/util/intlist.h
tools/perf/util/jitdump.c
tools/perf/util/kvm-stat.h
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/map_groups.h [new file with mode: 0644]
tools/perf/util/map_symbol.h [new file with mode: 0644]
tools/perf/util/metricgroup.c
tools/perf/util/metricgroup.h
tools/perf/util/mmap.c
tools/perf/util/mmap.h
tools/perf/util/parse-events.c
tools/perf/util/parse-events.y
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h
tools/perf/util/probe-file.c
tools/perf/util/rb_resort.h
tools/perf/util/rblist.c
tools/perf/util/rblist.h
tools/perf/util/s390-cpumcf-kernel.h [new file with mode: 0644]
tools/perf/util/s390-cpumsf.c
tools/perf/util/s390-sample-raw.c [new file with mode: 0644]
tools/perf/util/sample-raw.c [new file with mode: 0644]
tools/perf/util/sample-raw.h [new file with mode: 0644]
tools/perf/util/scripting-engines/Build
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/setup.py
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/srccode.h
tools/perf/util/srcline.c
tools/perf/util/srcline.h
tools/perf/util/stat-display.c
tools/perf/util/stat-shadow.c
tools/perf/util/strlist.h
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/symbol_conf.h [new file with mode: 0644]
tools/perf/util/symbol_fprintf.c
tools/perf/util/thread-stack.c
tools/perf/util/thread-stack.h
tools/perf/util/thread.c
tools/perf/util/thread.h
tools/perf/util/tool.h
tools/perf/util/unwind-libdw.c
tools/perf/util/unwind-libunwind-local.c
tools/perf/util/unwind-libunwind.c
tools/perf/util/util.c
tools/perf/util/util.h
tools/perf/util/vdso.c
tools/perf/util/zlib.c

index 5613aa378a83bbb4b9ecdfd301d438c6560abad5..4341ccf5c0c43e89dac23da91c4ad306a902939e 100644 (file)
@@ -630,12 +630,6 @@ static int __hw_perf_event_init(struct perf_event *event)
                return ev;
        }
 
-       /* The EV67 does not support mode exclusion */
-       if (attr->exclude_kernel || attr->exclude_user
-                       || attr->exclude_hv || attr->exclude_idle) {
-               return -EPERM;
-       }
-
        /*
         * We place the event type in event_base here and leave calculation
         * of the codes to programme the PMU for alpha_pmu_enable() because
@@ -771,6 +765,7 @@ static struct pmu pmu = {
        .start          = alpha_pmu_start,
        .stop           = alpha_pmu_stop,
        .read           = alpha_pmu_read,
+       .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
 };
 
 
index e49e068345162ba77d77ae36dbef324c446ef862..fce4b426c37917f1ade36f684077175488d5073d 100644 (file)
@@ -294,13 +294,7 @@ static int mmdc_pmu_event_init(struct perf_event *event)
                return -EOPNOTSUPP;
        }
 
-       if (event->attr.exclude_user            ||
-                       event->attr.exclude_kernel      ||
-                       event->attr.exclude_hv          ||
-                       event->attr.exclude_idle        ||
-                       event->attr.exclude_host        ||
-                       event->attr.exclude_guest       ||
-                       event->attr.sample_period)
+       if (event->attr.sample_period)
                return -EINVAL;
 
        if (cfg < 0 || cfg >= MMDC_NUM_COUNTERS)
@@ -456,6 +450,7 @@ static int mmdc_pmu_init(struct mmdc_pmu *pmu_mmdc,
                        .start          = mmdc_pmu_event_start,
                        .stop           = mmdc_pmu_event_stop,
                        .read           = mmdc_pmu_event_update,
+                       .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
                },
                .mmdc_base = mmdc_base,
                .dev = dev,
index afe5b4c7b164d89721d0fad3c69ff4245cd52dc0..99bcd074916ac9d7ad1f5a4d0e84a39c037d80a7 100644 (file)
@@ -314,14 +314,6 @@ static int l2x0_pmu_event_init(struct perf_event *event)
            event->attach_state & PERF_ATTACH_TASK)
                return -EINVAL;
 
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest)
-               return -EINVAL;
-
        if (event->cpu < 0)
                return -EINVAL;
 
@@ -544,6 +536,7 @@ static __init int l2x0_pmu_init(void)
                .del = l2x0_pmu_event_del,
                .event_init = l2x0_pmu_event_init,
                .attr_groups = l2x0_pmu_attr_groups,
+               .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        l2x0_pmu_reset();
index 72238eedc360fa1d24fa382c2d696097739d44c5..d2b8e6061933aa855a752bc2bf1cd79c0822b7c2 100644 (file)
@@ -1306,15 +1306,6 @@ static int h_24x7_event_init(struct perf_event *event)
                return -EINVAL;
        }
 
-       /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest)
-               return -EINVAL;
-
        /* no branch sampling */
        if (has_branch_stack(event))
                return -EOPNOTSUPP;
@@ -1577,6 +1568,7 @@ static struct pmu h_24x7_pmu = {
        .start_txn   = h_24x7_event_start_txn,
        .commit_txn  = h_24x7_event_commit_txn,
        .cancel_txn  = h_24x7_event_cancel_txn,
+       .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
 };
 
 static int hv_24x7_init(void)
index 43fabb3cae0fa2cd1895732332f8929cb88e147e..735e77b09cdb77c6bd3a1ca6be887cbecb326840 100644 (file)
@@ -232,15 +232,6 @@ static int h_gpci_event_init(struct perf_event *event)
                return -EINVAL;
        }
 
-       /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest)
-               return -EINVAL;
-
        /* no branch sampling */
        if (has_branch_stack(event))
                return -EOPNOTSUPP;
@@ -285,6 +276,7 @@ static struct pmu h_gpci_pmu = {
        .start       = h_gpci_event_start,
        .stop        = h_gpci_event_stop,
        .read        = h_gpci_event_update,
+       .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
 };
 
 static int hv_gpci_init(void)
index f292a3f284f1cfaf15ecc5084efe2214206ed8d3..b1c37cc3fa98bfcb34d5b4904e351ebe7496e9cf 100644 (file)
@@ -473,15 +473,6 @@ static int nest_imc_event_init(struct perf_event *event)
        if (event->hw.sample_period)
                return -EINVAL;
 
-       /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest)
-               return -EINVAL;
-
        if (event->cpu < 0)
                return -EINVAL;
 
@@ -748,15 +739,6 @@ static int core_imc_event_init(struct perf_event *event)
        if (event->hw.sample_period)
                return -EINVAL;
 
-       /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest)
-               return -EINVAL;
-
        if (event->cpu < 0)
                return -EINVAL;
 
@@ -1069,6 +1051,7 @@ static int update_pmu_ops(struct imc_pmu *pmu)
        pmu->pmu.stop = imc_event_stop;
        pmu->pmu.read = imc_event_update;
        pmu->pmu.attr_groups = pmu->attr_groups;
+       pmu->pmu.capabilities = PERF_PMU_CAP_NO_EXCLUDE;
        pmu->attr_groups[IMC_FORMAT_ATTR] = &imc_format_group;
 
        switch (pmu->domain) {
index bfabeb1889cc0cca5c6859cb36bbbeb15b662049..1266194afb026fb04d626ff8f0a598b7cb2f4cbe 100644 (file)
@@ -1600,7 +1600,7 @@ static void aux_sdb_init(unsigned long sdb)
 
 /*
  * aux_buffer_setup() - Setup AUX buffer for diagnostic mode sampling
- * @cpu:       On which to allocate, -1 means current
+ * @event:     Event the buffer is setup for, event->cpu == -1 means current
  * @pages:     Array of pointers to buffer pages passed from perf core
  * @nr_pages:  Total pages
  * @snapshot:  Flag for snapshot mode
@@ -1612,8 +1612,8 @@ static void aux_sdb_init(unsigned long sdb)
  *
  * Return the private AUX buffer structure if success or NULL if fails.
  */
-static void *aux_buffer_setup(int cpu, void **pages, int nr_pages,
-                             bool snapshot)
+static void *aux_buffer_setup(struct perf_event *event, void **pages,
+                             int nr_pages, bool snapshot)
 {
        struct sf_buffer *sfb;
        struct aux_buffer *aux;
index d50bb4dc065036181f7fc3b05182c7c8dce6b8ec..62f317c9113afc0ff252ffb4b05c82b1ac158bd6 100644 (file)
@@ -253,15 +253,6 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config)
        return -EOPNOTSUPP;
 }
 
-static const struct perf_event_attr ibs_notsupp = {
-       .exclude_user   = 1,
-       .exclude_kernel = 1,
-       .exclude_hv     = 1,
-       .exclude_idle   = 1,
-       .exclude_host   = 1,
-       .exclude_guest  = 1,
-};
-
 static int perf_ibs_init(struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
@@ -282,9 +273,6 @@ static int perf_ibs_init(struct perf_event *event)
        if (event->pmu != &perf_ibs->pmu)
                return -ENOENT;
 
-       if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp))
-               return -EINVAL;
-
        if (config & ~perf_ibs->config_mask)
                return -EINVAL;
 
@@ -537,6 +525,7 @@ static struct perf_ibs perf_ibs_fetch = {
                .start          = perf_ibs_start,
                .stop           = perf_ibs_stop,
                .read           = perf_ibs_read,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        },
        .msr                    = MSR_AMD64_IBSFETCHCTL,
        .config_mask            = IBS_FETCH_CONFIG_MASK,
index 3210fee27e7f9ac55a844d9709dc31ff14907e9c..7635c23f7d82e9839ba306fbb6721333d532d11f 100644 (file)
@@ -223,11 +223,6 @@ static int perf_iommu_event_init(struct perf_event *event)
        if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
                return -EINVAL;
 
-       /* IOMMU counters do not have usr/os/guest/host bits */
-       if (event->attr.exclude_user || event->attr.exclude_kernel ||
-           event->attr.exclude_host || event->attr.exclude_guest)
-               return -EINVAL;
-
        if (event->cpu < 0)
                return -EINVAL;
 
@@ -414,6 +409,7 @@ static const struct pmu iommu_pmu __initconst = {
        .read           = perf_iommu_read,
        .task_ctx_nr    = perf_invalid_context,
        .attr_groups    = amd_iommu_attr_groups,
+       .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
 };
 
 static __init int init_one_iommu(unsigned int idx)
index 2aefacf5c5b2ab84ebf557fba5cb07681d7cc0ee..c5ff084551c6f25e1256560dad93324a388ddea9 100644 (file)
@@ -136,14 +136,7 @@ static int pmu_event_init(struct perf_event *event)
                return -ENOENT;
 
        /* Unsupported modes and filters. */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           /* no sampling */
-           event->attr.sample_period)
+       if (event->attr.sample_period)
                return -EINVAL;
 
        if (cfg != AMD_POWER_EVENTSEL_PKG)
@@ -226,6 +219,7 @@ static struct pmu pmu_class = {
        .start          = pmu_event_start,
        .stop           = pmu_event_stop,
        .read           = pmu_event_read,
+       .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
 };
 
 static int power_cpu_exit(unsigned int cpu)
index 398df6eaa1094b749cb38bcdda285712d314c9ff..79cfd3b30ceb4fd42f0cefea9c547f0b46fce32a 100644 (file)
@@ -201,11 +201,6 @@ static int amd_uncore_event_init(struct perf_event *event)
        if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
                return -EINVAL;
 
-       /* NB and Last level cache counters do not have usr/os/guest/host bits */
-       if (event->attr.exclude_user || event->attr.exclude_kernel ||
-           event->attr.exclude_host || event->attr.exclude_guest)
-               return -EINVAL;
-
        /* and we do not enable counter overflow interrupts */
        hwc->config = event->attr.config & AMD64_RAW_EVENT_MASK_NB;
        hwc->idx = -1;
@@ -307,6 +302,7 @@ static struct pmu amd_nb_pmu = {
        .start          = amd_uncore_start,
        .stop           = amd_uncore_stop,
        .read           = amd_uncore_read,
+       .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
 };
 
 static struct pmu amd_llc_pmu = {
@@ -317,6 +313,7 @@ static struct pmu amd_llc_pmu = {
        .start          = amd_uncore_start,
        .stop           = amd_uncore_stop,
        .read           = amd_uncore_read,
+       .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
 };
 
 static struct amd_uncore *amd_uncore_alloc(unsigned int cpu)
index a01ef1b0f8833fd08285ef18f7307fada4d3c059..7cdd7b13bbda67352ed0c6e8dad5f381f027514d 100644 (file)
@@ -77,10 +77,12 @@ static size_t buf_size(struct page *page)
 }
 
 static void *
-bts_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool overwrite)
+bts_buffer_setup_aux(struct perf_event *event, void **pages,
+                    int nr_pages, bool overwrite)
 {
        struct bts_buffer *buf;
        struct page *page;
+       int cpu = event->cpu;
        int node = (cpu == -1) ? cpu : cpu_to_node(cpu);
        unsigned long offset;
        size_t size = nr_pages << PAGE_SHIFT;
index 730978dff63f5e577628936e26183b5a36da0cca..17096d3cd616483b0958a90c98f18c4397e9dc0b 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/hardirq.h>
 #include <asm/intel-family.h>
 #include <asm/apic.h>
+#include <asm/cpu_device_id.h>
 
 #include "../perf_event.h"
 
@@ -3206,16 +3207,27 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr)
        arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;
        arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask;
        arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask;
-       /*
-        * If PMU counter has PEBS enabled it is not enough to disable counter
-        * on a guest entry since PEBS memory write can overshoot guest entry
-        * and corrupt guest memory. Disabling PEBS solves the problem.
-        */
-       arr[1].msr = MSR_IA32_PEBS_ENABLE;
-       arr[1].host = cpuc->pebs_enabled;
-       arr[1].guest = 0;
+       if (x86_pmu.flags & PMU_FL_PEBS_ALL)
+               arr[0].guest &= ~cpuc->pebs_enabled;
+       else
+               arr[0].guest &= ~(cpuc->pebs_enabled & PEBS_COUNTER_MASK);
+       *nr = 1;
+
+       if (x86_pmu.pebs && x86_pmu.pebs_no_isolation) {
+               /*
+                * If PMU counter has PEBS enabled it is not enough to
+                * disable counter on a guest entry since PEBS memory
+                * write can overshoot guest entry and corrupt guest
+                * memory. Disabling PEBS solves the problem.
+                *
+                * Don't do this if the CPU already enforces it.
+                */
+               arr[1].msr = MSR_IA32_PEBS_ENABLE;
+               arr[1].host = cpuc->pebs_enabled;
+               arr[1].guest = 0;
+               *nr = 2;
+       }
 
-       *nr = 2;
        return arr;
 }
 
@@ -3748,36 +3760,62 @@ static __init void intel_clovertown_quirk(void)
        x86_pmu.pebs_constraints = NULL;
 }
 
-static int intel_snb_pebs_broken(int cpu)
+static const struct x86_cpu_desc isolation_ucodes[] = {
+       INTEL_CPU_DESC(INTEL_FAM6_HASWELL_CORE,          3, 0x0000001f),
+       INTEL_CPU_DESC(INTEL_FAM6_HASWELL_ULT,           1, 0x0000001e),
+       INTEL_CPU_DESC(INTEL_FAM6_HASWELL_GT3E,          1, 0x00000015),
+       INTEL_CPU_DESC(INTEL_FAM6_HASWELL_X,             2, 0x00000037),
+       INTEL_CPU_DESC(INTEL_FAM6_HASWELL_X,             4, 0x0000000a),
+       INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_CORE,        4, 0x00000023),
+       INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_GT3E,        1, 0x00000014),
+       INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D,      2, 0x00000010),
+       INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D,      3, 0x07000009),
+       INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D,      4, 0x0f000009),
+       INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D,      5, 0x0e000002),
+       INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_X,           2, 0x0b000014),
+       INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,             3, 0x00000021),
+       INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,             4, 0x00000000),
+       INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_MOBILE,        3, 0x0000007c),
+       INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_DESKTOP,       3, 0x0000007c),
+       INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,      9, 0x0000004e),
+       INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE,       9, 0x0000004e),
+       INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE,      10, 0x0000004e),
+       INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE,      11, 0x0000004e),
+       INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE,      12, 0x0000004e),
+       INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,     10, 0x0000004e),
+       INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,     11, 0x0000004e),
+       INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,     12, 0x0000004e),
+       INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,     13, 0x0000004e),
+       {}
+};
+
+static void intel_check_pebs_isolation(void)
 {
-       u32 rev = UINT_MAX; /* default to broken for unknown models */
+       x86_pmu.pebs_no_isolation = !x86_cpu_has_min_microcode_rev(isolation_ucodes);
+}
 
-       switch (cpu_data(cpu).x86_model) {
-       case INTEL_FAM6_SANDYBRIDGE:
-               rev = 0x28;
-               break;
+static __init void intel_pebs_isolation_quirk(void)
+{
+       WARN_ON_ONCE(x86_pmu.check_microcode);
+       x86_pmu.check_microcode = intel_check_pebs_isolation;
+       intel_check_pebs_isolation();
+}
 
-       case INTEL_FAM6_SANDYBRIDGE_X:
-               switch (cpu_data(cpu).x86_stepping) {
-               case 6: rev = 0x618; break;
-               case 7: rev = 0x70c; break;
-               }
-       }
+static const struct x86_cpu_desc pebs_ucodes[] = {
+       INTEL_CPU_DESC(INTEL_FAM6_SANDYBRIDGE,          7, 0x00000028),
+       INTEL_CPU_DESC(INTEL_FAM6_SANDYBRIDGE_X,        6, 0x00000618),
+       INTEL_CPU_DESC(INTEL_FAM6_SANDYBRIDGE_X,        7, 0x0000070c),
+       {}
+};
 
-       return (cpu_data(cpu).microcode < rev);
+static bool intel_snb_pebs_broken(void)
+{
+       return !x86_cpu_has_min_microcode_rev(pebs_ucodes);
 }
 
 static void intel_snb_check_microcode(void)
 {
-       int pebs_broken = 0;
-       int cpu;
-
-       for_each_online_cpu(cpu) {
-               if ((pebs_broken = intel_snb_pebs_broken(cpu)))
-                       break;
-       }
-
-       if (pebs_broken == x86_pmu.pebs_broken)
+       if (intel_snb_pebs_broken() == x86_pmu.pebs_broken)
                return;
 
        /*
@@ -3894,23 +3932,22 @@ static __init void intel_nehalem_quirk(void)
        }
 }
 
-static bool intel_glp_counter_freezing_broken(int cpu)
-{
-       u32 rev = UINT_MAX; /* default to broken for unknown stepping */
-
-       switch (cpu_data(cpu).x86_stepping) {
-       case 1:
-               rev = 0x28;
-               break;
-       case 8:
-               rev = 0x6;
-               break;
-       }
+static const struct x86_cpu_desc counter_freezing_ucodes[] = {
+       INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT,         2, 0x0000000e),
+       INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT,         9, 0x0000002e),
+       INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT,        10, 0x00000008),
+       INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_X,       1, 0x00000028),
+       INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_PLUS,    1, 0x00000028),
+       INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_PLUS,    8, 0x00000006),
+       {}
+};
 
-       return (cpu_data(cpu).microcode < rev);
+static bool intel_counter_freezing_broken(void)
+{
+       return !x86_cpu_has_min_microcode_rev(counter_freezing_ucodes);
 }
 
-static __init void intel_glp_counter_freezing_quirk(void)
+static __init void intel_counter_freezing_quirk(void)
 {
        /* Check if it's already disabled */
        if (disable_counter_freezing)
@@ -3920,7 +3957,7 @@ static __init void intel_glp_counter_freezing_quirk(void)
         * If the system starts with the wrong ucode, leave the
         * counter-freezing feature permanently disabled.
         */
-       if (intel_glp_counter_freezing_broken(raw_smp_processor_id())) {
+       if (intel_counter_freezing_broken()) {
                pr_info("PMU counter freezing disabled due to CPU errata,"
                        "please upgrade microcode\n");
                x86_pmu.counter_freezing = false;
@@ -4271,6 +4308,7 @@ __init int intel_pmu_init(void)
 
        case INTEL_FAM6_ATOM_GOLDMONT:
        case INTEL_FAM6_ATOM_GOLDMONT_X:
+               x86_add_quirk(intel_counter_freezing_quirk);
                memcpy(hw_cache_event_ids, glm_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, glm_hw_cache_extra_regs,
@@ -4297,7 +4335,7 @@ __init int intel_pmu_init(void)
                break;
 
        case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
-               x86_add_quirk(intel_glp_counter_freezing_quirk);
+               x86_add_quirk(intel_counter_freezing_quirk);
                memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, glp_hw_cache_extra_regs,
@@ -4440,6 +4478,7 @@ __init int intel_pmu_init(void)
        case INTEL_FAM6_HASWELL_ULT:
        case INTEL_FAM6_HASWELL_GT3E:
                x86_add_quirk(intel_ht_bug);
+               x86_add_quirk(intel_pebs_isolation_quirk);
                x86_pmu.late_ack = true;
                memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
@@ -4471,6 +4510,7 @@ __init int intel_pmu_init(void)
        case INTEL_FAM6_BROADWELL_XEON_D:
        case INTEL_FAM6_BROADWELL_GT3E:
        case INTEL_FAM6_BROADWELL_X:
+               x86_add_quirk(intel_pebs_isolation_quirk);
                x86_pmu.late_ack = true;
                memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
@@ -4533,6 +4573,7 @@ __init int intel_pmu_init(void)
        case INTEL_FAM6_SKYLAKE_X:
        case INTEL_FAM6_KABYLAKE_MOBILE:
        case INTEL_FAM6_KABYLAKE_DESKTOP:
+               x86_add_quirk(intel_pebs_isolation_quirk);
                x86_pmu.late_ack = true;
                memcpy(hw_cache_event_ids, skl_hw_cache_event_ids, sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, skl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
index d2e780705c5a2036952417c21ba20308c54dc5c1..94a4b7fc75d0ecf344bade95be1cf563576250d2 100644 (file)
@@ -280,13 +280,7 @@ static int cstate_pmu_event_init(struct perf_event *event)
                return -ENOENT;
 
        /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           event->attr.sample_period) /* no sampling */
+       if (event->attr.sample_period) /* no sampling */
                return -EINVAL;
 
        if (event->cpu < 0)
@@ -437,7 +431,7 @@ static struct pmu cstate_core_pmu = {
        .start          = cstate_pmu_event_start,
        .stop           = cstate_pmu_event_stop,
        .read           = cstate_pmu_event_update,
-       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
+       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE,
        .module         = THIS_MODULE,
 };
 
@@ -451,7 +445,7 @@ static struct pmu cstate_pkg_pmu = {
        .start          = cstate_pmu_event_start,
        .stop           = cstate_pmu_event_stop,
        .read           = cstate_pmu_event_update,
-       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
+       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE,
        .module         = THIS_MODULE,
 };
 
index e9acf1d2e7b28874a3708c21ea59f75591650312..10c99ce1feaddf5fa196bfbd385cbd02b55ef57a 100644 (file)
@@ -1628,6 +1628,8 @@ void __init intel_ds_init(void)
        x86_pmu.bts  = boot_cpu_has(X86_FEATURE_BTS);
        x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS);
        x86_pmu.pebs_buffer_size = PEBS_BUFFER_SIZE;
+       if (x86_pmu.version <= 4)
+               x86_pmu.pebs_no_isolation = 1;
        if (x86_pmu.pebs) {
                char pebs_type = x86_pmu.intel_cap.pebs_trap ?  '+' : '-';
                int format = x86_pmu.intel_cap.pebs_format;
index 9494ca68fd9df094ab9a699f4fd814b55114ee98..fb3a2f13fc709256e81719a229d5d3fdcde6e430 100644 (file)
@@ -1114,10 +1114,11 @@ static int pt_buffer_init_topa(struct pt_buffer *buf, unsigned long nr_pages,
  * Return:     Our private PT buffer structure.
  */
 static void *
-pt_buffer_setup_aux(int cpu, void **pages, int nr_pages, bool snapshot)
+pt_buffer_setup_aux(struct perf_event *event, void **pages,
+                   int nr_pages, bool snapshot)
 {
        struct pt_buffer *buf;
-       int node, ret;
+       int node, ret, cpu = event->cpu;
 
        if (!nr_pages)
                return NULL;
@@ -1222,7 +1223,8 @@ static int pt_event_addr_filters_validate(struct list_head *filters)
 static void pt_event_addr_filters_sync(struct perf_event *event)
 {
        struct perf_addr_filters_head *head = perf_event_addr_filters(event);
-       unsigned long msr_a, msr_b, *offs = event->addr_filters_offs;
+       unsigned long msr_a, msr_b;
+       struct perf_addr_filter_range *fr = event->addr_filter_ranges;
        struct pt_filters *filters = event->hw.addr_filters;
        struct perf_addr_filter *filter;
        int range = 0;
@@ -1231,12 +1233,12 @@ static void pt_event_addr_filters_sync(struct perf_event *event)
                return;
 
        list_for_each_entry(filter, &head->list, entry) {
-               if (filter->path.dentry && !offs[range]) {
+               if (filter->path.dentry && !fr[range].start) {
                        msr_a = msr_b = 0;
                } else {
                        /* apply the offset */
-                       msr_a = filter->offset + offs[range];
-                       msr_b = filter->size + msr_a - 1;
+                       msr_a = fr[range].start;
+                       msr_b = msr_a + fr[range].size - 1;
                }
 
                filters->filter[range].msr_a  = msr_a;
index 91039ffed63334828717ac4647d2c353d95a39ab..94dc564146ca89190cc203d2b78e6651b4742f19 100644 (file)
@@ -397,13 +397,7 @@ static int rapl_pmu_event_init(struct perf_event *event)
                return -EINVAL;
 
        /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           event->attr.sample_period) /* no sampling */
+       if (event->attr.sample_period) /* no sampling */
                return -EINVAL;
 
        /* must be done before validate_group */
@@ -699,6 +693,7 @@ static int __init init_rapl_pmus(void)
        rapl_pmus->pmu.stop             = rapl_pmu_event_stop;
        rapl_pmus->pmu.read             = rapl_pmu_event_read;
        rapl_pmus->pmu.module           = THIS_MODULE;
+       rapl_pmus->pmu.capabilities     = PERF_PMU_CAP_NO_EXCLUDE;
        return 0;
 }
 
index 27a461414b306851d70ca2438d054a43d8aa9fed..d516161c00c4710ed401ce3e148e7de73548824c 100644 (file)
@@ -695,14 +695,6 @@ static int uncore_pmu_event_init(struct perf_event *event)
        if (pmu->func_id < 0)
                return -ENOENT;
 
-       /*
-        * Uncore PMU does measure at all privilege level all the time.
-        * So it doesn't make sense to specify any exclude bits.
-        */
-       if (event->attr.exclude_user || event->attr.exclude_kernel ||
-                       event->attr.exclude_hv || event->attr.exclude_idle)
-               return -EINVAL;
-
        /* Sampling not supported yet */
        if (hwc->sample_period)
                return -EINVAL;
@@ -800,6 +792,7 @@ static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
                        .stop           = uncore_pmu_event_stop,
                        .read           = uncore_pmu_event_read,
                        .module         = THIS_MODULE,
+                       .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
                };
        } else {
                pmu->pmu = *pmu->type->pmu;
index 2593b0d7aeee6089413d980618ce07c35d84c101..b12517fae77a505b4c4beda2cacac9ea519fd83e 100644 (file)
@@ -397,13 +397,7 @@ static int snb_uncore_imc_event_init(struct perf_event *event)
                return -EINVAL;
 
        /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           event->attr.sample_period) /* no sampling */
+       if (event->attr.sample_period) /* no sampling */
                return -EINVAL;
 
        /*
@@ -497,6 +491,7 @@ static struct pmu snb_uncore_imc_pmu = {
        .start          = uncore_pmu_event_start,
        .stop           = uncore_pmu_event_stop,
        .read           = uncore_pmu_event_read,
+       .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
 };
 
 static struct intel_uncore_ops snb_uncore_imc_ops = {
index 1b9f85abf9bc10c3b058c244b051186cbb8fd309..a878e6286e4afa0a6840d90d84f1386ee4934605 100644 (file)
@@ -160,13 +160,7 @@ static int msr_event_init(struct perf_event *event)
                return -ENOENT;
 
        /* unsupported modes and filters */
-       if (event->attr.exclude_user   ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv     ||
-           event->attr.exclude_idle   ||
-           event->attr.exclude_host   ||
-           event->attr.exclude_guest  ||
-           event->attr.sample_period) /* no sampling */
+       if (event->attr.sample_period) /* no sampling */
                return -EINVAL;
 
        if (cfg >= PERF_MSR_EVENT_MAX)
@@ -256,7 +250,7 @@ static struct pmu pmu_msr = {
        .start          = msr_event_start,
        .stop           = msr_event_stop,
        .read           = msr_event_update,
-       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT,
+       .capabilities   = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE,
 };
 
 static int __init msr_init(void)
index d46fd6754d920b0c5331c2658a55e1685b111957..7e75f474b076518e4bb512655224ef1e059e336c 100644 (file)
@@ -601,13 +601,14 @@ struct x86_pmu {
        /*
         * Intel DebugStore bits
         */
-       unsigned int    bts             :1,
-                       bts_active      :1,
-                       pebs            :1,
-                       pebs_active     :1,
-                       pebs_broken     :1,
-                       pebs_prec_dist  :1,
-                       pebs_no_tlb     :1;
+       unsigned int    bts                     :1,
+                       bts_active              :1,
+                       pebs                    :1,
+                       pebs_active             :1,
+                       pebs_broken             :1,
+                       pebs_prec_dist          :1,
+                       pebs_no_tlb             :1,
+                       pebs_no_isolation       :1;
        int             pebs_record_size;
        int             pebs_buffer_size;
        void            (*drain_pebs)(struct pt_regs *regs);
index baeba05671268cc7d835ecf6decbfc9fc5fc93ea..3417110574c12212f7185213bfe566ac2b541a1e 100644 (file)
 
 extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match);
 
+/*
+ * Match specific microcode revisions.
+ *
+ * vendor/family/model/stepping must be all set.
+ *
+ * Only checks against the boot CPU.  When mixed-stepping configs are
+ * valid for a CPU model, add a quirk for every valid stepping and
+ * do the fine-tuning in the quirk handler.
+ */
+
+struct x86_cpu_desc {
+       __u8    x86_family;
+       __u8    x86_vendor;
+       __u8    x86_model;
+       __u8    x86_stepping;
+       __u32   x86_microcode_rev;
+};
+
+#define INTEL_CPU_DESC(mod, step, rev) {                       \
+       .x86_family = 6,                                        \
+       .x86_vendor = X86_VENDOR_INTEL,                         \
+       .x86_model = mod,                                       \
+       .x86_stepping = step,                                   \
+       .x86_microcode_rev = rev,                               \
+}
+
+extern bool x86_cpu_has_min_microcode_rev(const struct x86_cpu_desc *table);
+
 #endif
index ebeac487a20c79614d3892e982191124b2216e9c..e8b628b1b2799555ac5a0c9ef64303907009c737 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/stop_machine.h>
 #include <linux/slab.h>
 #include <linux/kdebug.h>
+#include <linux/kprobes.h>
 #include <asm/text-patching.h>
 #include <asm/alternative.h>
 #include <asm/sections.h>
@@ -764,8 +765,8 @@ int poke_int3_handler(struct pt_regs *regs)
        regs->ip = (unsigned long) bp_int3_handler;
 
        return 1;
-
 }
+NOKPROBE_SYMBOL(poke_int3_handler);
 
 /**
  * text_poke_bp() -- update instructions on live kernel on SMP
index 69f6bbb41be0bfb8a3e360a8294dd5861eb44582..01004bfb1a1bcdd4a9f5b41c987939fe43f6ec62 100644 (file)
@@ -819,11 +819,9 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
 static void init_amd_zn(struct cpuinfo_x86 *c)
 {
        set_cpu_cap(c, X86_FEATURE_ZEN);
-       /*
-        * Fix erratum 1076: CPB feature bit not being set in CPUID. It affects
-        * all up to and including B1.
-        */
-       if (c->x86_model <= 1 && c->x86_stepping <= 1)
+
+       /* Fix erratum 1076: CPB feature bit not being set in CPUID. */
+       if (!cpu_has(c, X86_FEATURE_CPB))
                set_cpu_cap(c, X86_FEATURE_CPB);
 }
 
index 3fed38812eea340ff1ca2adb4b47534de1e73a59..6dd78d8235e4498abe83b624d69f9104315ae56e 100644 (file)
@@ -48,3 +48,34 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match)
        return NULL;
 }
 EXPORT_SYMBOL(x86_match_cpu);
+
+static const struct x86_cpu_desc *
+x86_match_cpu_with_stepping(const struct x86_cpu_desc *match)
+{
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+       const struct x86_cpu_desc *m;
+
+       for (m = match; m->x86_family | m->x86_model; m++) {
+               if (c->x86_vendor != m->x86_vendor)
+                       continue;
+               if (c->x86 != m->x86_family)
+                       continue;
+               if (c->x86_model != m->x86_model)
+                       continue;
+               if (c->x86_stepping != m->x86_stepping)
+                       continue;
+               return m;
+       }
+       return NULL;
+}
+
+bool x86_cpu_has_min_microcode_rev(const struct x86_cpu_desc *table)
+{
+       const struct x86_cpu_desc *res = x86_match_cpu_with_stepping(table);
+
+       if (!res || res->x86_microcode_rev > boot_cpu_data.microcode)
+               return false;
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(x86_cpu_has_min_microcode_rev);
index 8257a59704ae9f5dd0726c8680c44abaeb44ec3b..3e3789c8f8e1a7c91df904d2e990fc6f5de3ca01 100644 (file)
@@ -269,7 +269,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
        return ret;
 }
 
-static int is_ftrace_caller(unsigned long ip)
+static nokprobe_inline int is_ftrace_caller(unsigned long ip)
 {
        if (ip == ftrace_update_func)
                return 1;
@@ -299,6 +299,7 @@ int ftrace_int3_handler(struct pt_regs *regs)
 
        return 1;
 }
+NOKPROBE_SYMBOL(ftrace_int3_handler);
 
 static int ftrace_write(unsigned long ip, const char *val, int size)
 {
index 4ba75afba5271e599565dbe355ca10d5d8a802cd..a034cb808e7eb482e6fd8eae3fac9afca63b429c 100644 (file)
@@ -1028,6 +1028,13 @@ NOKPROBE_SYMBOL(kprobe_fault_handler);
 
 int __init arch_populate_kprobe_blacklist(void)
 {
+       int ret;
+
+       ret = kprobe_add_area_blacklist((unsigned long)__irqentry_text_start,
+                                        (unsigned long)__irqentry_text_end);
+       if (ret)
+               return ret;
+
        return kprobe_add_area_blacklist((unsigned long)__entry_text_start,
                                         (unsigned long)__entry_text_end);
 }
index 6adf6e6c2933945598b32a530098b3dc1b2be690..f142629520158244fe75335cbe8b30a1bcd2ef3a 100644 (file)
@@ -97,6 +97,7 @@ static void synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val)
 }
 
 asm (
+                       ".pushsection .rodata\n"
                        "optprobe_template_func:\n"
                        ".global optprobe_template_entry\n"
                        "optprobe_template_entry:\n"
@@ -136,8 +137,7 @@ asm (
 #endif
                        ".global optprobe_template_end\n"
                        "optprobe_template_end:\n"
-                       ".type optprobe_template_func, @function\n"
-                       ".size optprobe_template_func, .-optprobe_template_func\n");
+                       ".popsection\n");
 
 void optprobe_template_func(void);
 STACK_FRAME_NON_STANDARD(optprobe_template_func);
index 9b7c4ca8f0a7358ce19741de1c875a75e8f52f8e..e289ce1332ab4c7459b84ad6ad50f8fef940f332 100644 (file)
@@ -111,6 +111,7 @@ void ist_enter(struct pt_regs *regs)
        /* This code is a bit fragile.  Test it. */
        RCU_LOCKDEP_WARN(!rcu_is_watching(), "ist_enter didn't work");
 }
+NOKPROBE_SYMBOL(ist_enter);
 
 void ist_exit(struct pt_regs *regs)
 {
index abe8249b893bbd6c5d564010e5f2c17af7db28c8..4d5a2b9f9d6aa8455fb012f5b2eda60b18a0a02b 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/perf_event.h>
 #include <linux/percpu-defs.h>
 #include <linux/slab.h>
+#include <linux/stringhash.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
 
@@ -30,11 +31,14 @@ static DEFINE_PER_CPU(struct coresight_device *, csdev_src);
 PMU_FORMAT_ATTR(cycacc,                "config:" __stringify(ETM_OPT_CYCACC));
 PMU_FORMAT_ATTR(timestamp,     "config:" __stringify(ETM_OPT_TS));
 PMU_FORMAT_ATTR(retstack,      "config:" __stringify(ETM_OPT_RETSTK));
+/* Sink ID - same for all ETMs */
+PMU_FORMAT_ATTR(sinkid,                "config2:0-31");
 
 static struct attribute *etm_config_formats_attr[] = {
        &format_attr_cycacc.attr,
        &format_attr_timestamp.attr,
        &format_attr_retstack.attr,
+       &format_attr_sinkid.attr,
        NULL,
 };
 
@@ -43,8 +47,18 @@ static const struct attribute_group etm_pmu_format_group = {
        .attrs  = etm_config_formats_attr,
 };
 
+static struct attribute *etm_config_sinks_attr[] = {
+       NULL,
+};
+
+static const struct attribute_group etm_pmu_sinks_group = {
+       .name   = "sinks",
+       .attrs  = etm_config_sinks_attr,
+};
+
 static const struct attribute_group *etm_pmu_attr_groups[] = {
        &etm_pmu_format_group,
+       &etm_pmu_sinks_group,
        NULL,
 };
 
@@ -177,31 +191,28 @@ static void etm_free_aux(void *data)
        schedule_work(&event_data->work);
 }
 
-static void *etm_setup_aux(int event_cpu, void **pages,
+static void *etm_setup_aux(struct perf_event *event, void **pages,
                           int nr_pages, bool overwrite)
 {
-       int cpu;
+       u32 id;
+       int cpu = event->cpu;
        cpumask_t *mask;
        struct coresight_device *sink;
        struct etm_event_data *event_data = NULL;
 
-       event_data = alloc_event_data(event_cpu);
+       event_data = alloc_event_data(cpu);
        if (!event_data)
                return NULL;
        INIT_WORK(&event_data->work, free_event_data);
 
-       /*
-        * In theory nothing prevent tracers in a trace session from being
-        * associated with different sinks, nor having a sink per tracer.  But
-        * until we have HW with this kind of topology we need to assume tracers
-        * in a trace session are using the same sink.  Therefore go through
-        * the coresight bus and pick the first enabled sink.
-        *
-        * When operated from sysFS users are responsible to enable the sink
-        * while from perf, the perf tools will do it based on the choice made
-        * on the cmd line.  As such the "enable_sink" flag in sysFS is reset.
-        */
-       sink = coresight_get_enabled_sink(true);
+       /* First get the selected sink from user space. */
+       if (event->attr.config2) {
+               id = (u32)event->attr.config2;
+               sink = coresight_get_sink_by_id(id);
+       } else {
+               sink = coresight_get_enabled_sink(true);
+       }
+
        if (!sink || !sink_ops(sink)->alloc_buffer)
                goto err;
 
@@ -422,15 +433,16 @@ static int etm_addr_filters_validate(struct list_head *filters)
 static void etm_addr_filters_sync(struct perf_event *event)
 {
        struct perf_addr_filters_head *head = perf_event_addr_filters(event);
-       unsigned long start, stop, *offs = event->addr_filters_offs;
+       unsigned long start, stop;
+       struct perf_addr_filter_range *fr = event->addr_filter_ranges;
        struct etm_filters *filters = event->hw.addr_filters;
        struct etm_filter *etm_filter;
        struct perf_addr_filter *filter;
        int i = 0;
 
        list_for_each_entry(filter, &head->list, entry) {
-               start = filter->offset + offs[i];
-               stop = start + filter->size;
+               start = fr[i].start;
+               stop = start + fr[i].size;
                etm_filter = &filters->etm_filter[i];
 
                switch (filter->action) {
@@ -479,6 +491,77 @@ int etm_perf_symlink(struct coresight_device *csdev, bool link)
        return 0;
 }
 
+static ssize_t etm_perf_sink_name_show(struct device *dev,
+                                      struct device_attribute *dattr,
+                                      char *buf)
+{
+       struct dev_ext_attribute *ea;
+
+       ea = container_of(dattr, struct dev_ext_attribute, attr);
+       return scnprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)(ea->var));
+}
+
+int etm_perf_add_symlink_sink(struct coresight_device *csdev)
+{
+       int ret;
+       unsigned long hash;
+       const char *name;
+       struct device *pmu_dev = etm_pmu.dev;
+       struct device *pdev = csdev->dev.parent;
+       struct dev_ext_attribute *ea;
+
+       if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
+           csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
+               return -EINVAL;
+
+       if (csdev->ea != NULL)
+               return -EINVAL;
+
+       if (!etm_perf_up)
+               return -EPROBE_DEFER;
+
+       ea = devm_kzalloc(pdev, sizeof(*ea), GFP_KERNEL);
+       if (!ea)
+               return -ENOMEM;
+
+       name = dev_name(pdev);
+       /* See function coresight_get_sink_by_id() to know where this is used */
+       hash = hashlen_hash(hashlen_string(NULL, name));
+
+       ea->attr.attr.name = devm_kstrdup(pdev, name, GFP_KERNEL);
+       if (!ea->attr.attr.name)
+               return -ENOMEM;
+
+       ea->attr.attr.mode = 0444;
+       ea->attr.show = etm_perf_sink_name_show;
+       ea->var = (unsigned long *)hash;
+
+       ret = sysfs_add_file_to_group(&pmu_dev->kobj,
+                                     &ea->attr.attr, "sinks");
+
+       if (!ret)
+               csdev->ea = ea;
+
+       return ret;
+}
+
+void etm_perf_del_symlink_sink(struct coresight_device *csdev)
+{
+       struct device *pmu_dev = etm_pmu.dev;
+       struct dev_ext_attribute *ea = csdev->ea;
+
+       if (csdev->type != CORESIGHT_DEV_TYPE_SINK &&
+           csdev->type != CORESIGHT_DEV_TYPE_LINKSINK)
+               return;
+
+       if (!ea)
+               return;
+
+       sysfs_remove_file_from_group(&pmu_dev->kobj,
+                                    &ea->attr.attr, "sinks");
+       csdev->ea = NULL;
+}
+
 static int __init etm_perf_init(void)
 {
        int ret;
index da7d9336a15c5b7b133e9e81513ce98c95e88180..015213abe00a716b08142c7780658d8f6ce23989 100644 (file)
@@ -59,6 +59,8 @@ struct etm_event_data {
 
 #ifdef CONFIG_CORESIGHT
 int etm_perf_symlink(struct coresight_device *csdev, bool link);
+int etm_perf_add_symlink_sink(struct coresight_device *csdev);
+void etm_perf_del_symlink_sink(struct coresight_device *csdev);
 static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
 {
        struct etm_event_data *data = perf_get_aux(handle);
@@ -70,7 +72,9 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
 #else
 static inline int etm_perf_symlink(struct coresight_device *csdev, bool link)
 { return -EINVAL; }
-
+int etm_perf_add_symlink_sink(struct coresight_device *csdev)
+{ return -EINVAL; }
+void etm_perf_del_symlink_sink(struct coresight_device *csdev) {}
 static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
 {
        return NULL;
index 579f34943bf1ab9fea05ff1cd2079460c1cefc39..b936c6d7e13f3a31b7668dcb508772d3dbf3d0e2 100644 (file)
@@ -147,6 +147,7 @@ void coresight_disable_path(struct list_head *path);
 int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data);
 struct coresight_device *coresight_get_sink(struct list_head *path);
 struct coresight_device *coresight_get_enabled_sink(bool reset);
+struct coresight_device *coresight_get_sink_by_id(u32 id);
 struct list_head *coresight_build_path(struct coresight_device *csdev,
                                       struct coresight_device *sink);
 void coresight_release_path(struct list_head *path);
index 2b0df1a0a8df4c8c463e8169fa73b5e279330b60..29cef898afba0b0ba715bac31ac21695ea4ffe6a 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/err.h>
 #include <linux/export.h>
 #include <linux/slab.h>
+#include <linux/stringhash.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/coresight.h>
@@ -18,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/pm_runtime.h>
 
+#include "coresight-etm-perf.h"
 #include "coresight-priv.h"
 
 static DEFINE_MUTEX(coresight_mutex);
@@ -540,6 +542,47 @@ struct coresight_device *coresight_get_enabled_sink(bool deactivate)
        return dev ? to_coresight_device(dev) : NULL;
 }
 
+static int coresight_sink_by_id(struct device *dev, void *data)
+{
+       struct coresight_device *csdev = to_coresight_device(dev);
+       unsigned long hash;
+
+       if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
+            csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
+
+               if (!csdev->ea)
+                       return 0;
+               /*
+                * See function etm_perf_add_symlink_sink() to know where
+                * this comes from.
+                */
+               hash = (unsigned long)csdev->ea->var;
+
+               if ((u32)hash == *(u32 *)data)
+                       return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * coresight_get_sink_by_id - returns the sink that matches the id
+ * @id: Id of the sink to match
+ *
+ * The name of a sink is unique, whether it is found on the AMBA bus or
+ * otherwise.  As such the hash of that name can easily be used to identify
+ * a sink.
+ */
+struct coresight_device *coresight_get_sink_by_id(u32 id)
+{
+       struct device *dev = NULL;
+
+       dev = bus_find_device(&coresight_bustype, NULL, &id,
+                             coresight_sink_by_id);
+
+       return dev ? to_coresight_device(dev) : NULL;
+}
+
 /*
  * coresight_grab_device - Power up this device and any of the helper
  * devices connected to it for trace operation. Since the helper devices
@@ -1167,6 +1210,22 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
                goto err_out;
        }
 
+       if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
+           csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
+               ret = etm_perf_add_symlink_sink(csdev);
+
+               if (ret) {
+                       device_unregister(&csdev->dev);
+                       /*
+                        * As with the above, all resources are free'd
+                        * explicitly via coresight_device_release() triggered
+                        * from put_device(), which is in turn called from
+                        * function device_unregister().
+                        */
+                       goto err_out;
+               }
+       }
+
        mutex_lock(&coresight_mutex);
 
        coresight_fixup_device_conns(csdev);
@@ -1185,6 +1244,7 @@ EXPORT_SYMBOL_GPL(coresight_register);
 
 void coresight_unregister(struct coresight_device *csdev)
 {
+       etm_perf_del_symlink_sink(csdev);
        /* Remove references of that device in the topology */
        coresight_remove_conns(csdev);
        device_unregister(&csdev->dev);
index 1bfeb160c5b16b841f34415efbfaba97972f747b..bfd03e0233084e4c1a9bc11882f4f0695f6ed71e 100644 (file)
@@ -1327,15 +1327,6 @@ static int cci_pmu_event_init(struct perf_event *event)
        if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
                return -EOPNOTSUPP;
 
-       /* We have no filtering of any kind */
-       if (event->attr.exclude_user    ||
-           event->attr.exclude_kernel  ||
-           event->attr.exclude_hv      ||
-           event->attr.exclude_idle    ||
-           event->attr.exclude_host    ||
-           event->attr.exclude_guest)
-               return -EINVAL;
-
        /*
         * Following the example set by other "uncore" PMUs, we accept any CPU
         * and rewrite its affinity dynamically rather than having perf core
@@ -1433,6 +1424,7 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
                .stop           = cci_pmu_stop,
                .read           = pmu_read,
                .attr_groups    = pmu_attr_groups,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        cci_pmu->plat_device = pdev;
index 7dd850e02f192e43fbb9ad3ab6868975d4170abe..2ae76026e947fc38f0fb4ab1c33b601f42cc7e51 100644 (file)
@@ -741,10 +741,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
                return -EOPNOTSUPP;
        }
 
-       if (has_branch_stack(event) || event->attr.exclude_user ||
-                       event->attr.exclude_kernel || event->attr.exclude_hv ||
-                       event->attr.exclude_idle || event->attr.exclude_host ||
-                       event->attr.exclude_guest) {
+       if (has_branch_stack(event)) {
                dev_dbg(ccn->dev, "Can't exclude execution levels!\n");
                return -EINVAL;
        }
@@ -1290,6 +1287,7 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
                .read = arm_ccn_pmu_event_read,
                .pmu_enable = arm_ccn_pmu_enable,
                .pmu_disable = arm_ccn_pmu_disable,
+               .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        /* No overflow interrupt? Have to use a timer instead. */
index 660cb8ac886ac9bb11319c5205f6dfd451264a8d..5851de56bbd03d1ee05045cda3adf2a0c4dafb3d 100644 (file)
@@ -562,13 +562,7 @@ static int dsu_pmu_event_init(struct perf_event *event)
                return -EINVAL;
        }
 
-       if (has_branch_stack(event) ||
-           event->attr.exclude_user ||
-           event->attr.exclude_kernel ||
-           event->attr.exclude_hv ||
-           event->attr.exclude_idle ||
-           event->attr.exclude_host ||
-           event->attr.exclude_guest) {
+       if (has_branch_stack(event)) {
                dev_dbg(dsu_pmu->pmu.dev, "Can't support filtering\n");
                return -EINVAL;
        }
@@ -735,6 +729,7 @@ static int dsu_pmu_device_probe(struct platform_device *pdev)
                .read           = dsu_pmu_read,
 
                .attr_groups    = dsu_pmu_attr_groups,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        rc = perf_pmu_register(&dsu_pmu->pmu, name, -1);
index d0b7dd8fb184b041446707dceccda87588ba45a2..eec75b97e7eae0f5d4ac3443ac8485ae9ab44e3b 100644 (file)
@@ -356,13 +356,6 @@ static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
        return ret;
 }
 
-static int
-event_requires_mode_exclusion(struct perf_event_attr *attr)
-{
-       return attr->exclude_idle || attr->exclude_user ||
-              attr->exclude_kernel || attr->exclude_hv;
-}
-
 static int
 __hw_perf_event_init(struct perf_event *event)
 {
@@ -393,9 +386,8 @@ __hw_perf_event_init(struct perf_event *event)
        /*
         * Check whether we need to exclude the counter from certain modes.
         */
-       if ((!armpmu->set_event_filter ||
-            armpmu->set_event_filter(hwc, &event->attr)) &&
-            event_requires_mode_exclusion(&event->attr)) {
+       if (armpmu->set_event_filter &&
+           armpmu->set_event_filter(hwc, &event->attr)) {
                pr_debug("ARM performance counters do not support "
                         "mode exclusion\n");
                return -EOPNOTSUPP;
@@ -867,6 +859,9 @@ int armpmu_register(struct arm_pmu *pmu)
        if (ret)
                return ret;
 
+       if (!pmu->set_event_filter)
+               pmu->pmu.capabilities |= PERF_PMU_CAP_NO_EXCLUDE;
+
        ret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
        if (ret)
                goto out_destroy;
index 8e46a9dad2fa2880ce629c8279ada5fa6ed54701..7cb766dafe851fc711f388b4d230dc96e3f1f665 100644 (file)
@@ -824,10 +824,10 @@ static void arm_spe_pmu_read(struct perf_event *event)
 {
 }
 
-static void *arm_spe_pmu_setup_aux(int cpu, void **pages, int nr_pages,
-                                  bool snapshot)
+static void *arm_spe_pmu_setup_aux(struct perf_event *event, void **pages,
+                                  int nr_pages, bool snapshot)
 {
-       int i;
+       int i, cpu = event->cpu;
        struct page **pglist;
        struct arm_spe_pmu_buf *buf;
 
index 69372e2bc93c7df0ce3921d6b9666773d80bbef2..0eba947c2ee9035ed5a07fb9cc707cf15139bb0a 100644 (file)
@@ -396,6 +396,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
                .stop           = hisi_uncore_pmu_stop,
                .read           = hisi_uncore_pmu_read,
                .attr_groups    = hisi_ddrc_pmu_attr_groups,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
index 443906e0aff3edad67ebd2514473b1f11f3dbeea..2553a844ebf60771b3b75e1c60b2a03aa217cf3d 100644 (file)
@@ -407,6 +407,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
                .stop           = hisi_uncore_pmu_stop,
                .read           = hisi_uncore_pmu_read,
                .attr_groups    = hisi_hha_pmu_attr_groups,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
index 0bde5d919b2eb49db7c0a8dc3d5f99b028b1930d..cf1cc34f402af8c20aee9b81183d92c19d05072b 100644 (file)
@@ -397,6 +397,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
                .stop           = hisi_uncore_pmu_stop,
                .read           = hisi_uncore_pmu_read,
                .attr_groups    = hisi_l3c_pmu_attr_groups,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
index 9efd2413240cb43ceb0471363cbd679ca776748c..f028cbc3443c466654495cb079fc5cc472a109cd 100644 (file)
@@ -142,15 +142,6 @@ int hisi_uncore_pmu_event_init(struct perf_event *event)
        if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
                return -EOPNOTSUPP;
 
-       /* counters do not have these bits */
-       if (event->attr.exclude_user    ||
-           event->attr.exclude_kernel  ||
-           event->attr.exclude_host    ||
-           event->attr.exclude_guest   ||
-           event->attr.exclude_hv      ||
-           event->attr.exclude_idle)
-               return -EINVAL;
-
        /*
         *  The uncore counters not specific to any CPU, so cannot
         *  support per-task
index 842135cf35a3acba6f72b4d27c9ebb2335d40ee9..091b4d7d32c4885a4434b20f05f577784097c2bf 100644 (file)
@@ -509,14 +509,6 @@ static int l2_cache_event_init(struct perf_event *event)
                return -EOPNOTSUPP;
        }
 
-       /* We cannot filter accurately so we just don't allow it. */
-       if (event->attr.exclude_user || event->attr.exclude_kernel ||
-           event->attr.exclude_hv || event->attr.exclude_idle) {
-               dev_dbg_ratelimited(&l2cache_pmu->pdev->dev,
-                                   "Can't exclude execution levels\n");
-               return -EOPNOTSUPP;
-       }
-
        if (((L2_EVT_GROUP(event->attr.config) > L2_EVT_GROUP_MAX) ||
             ((event->attr.config & ~L2_EVT_MASK) != 0)) &&
            (event->attr.config != L2CYCLE_CTR_RAW_CODE)) {
@@ -982,6 +974,7 @@ static int l2_cache_pmu_probe(struct platform_device *pdev)
                .stop           = l2_cache_event_stop,
                .read           = l2_cache_event_read,
                .attr_groups    = l2_cache_pmu_attr_grps,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        l2cache_pmu->num_counters = get_num_counters();
index 2dc63d61f2ea885991977bb3c830b0f9b2f6cc27..5d70646da8c78c64a6ec704bfe9bcc95facc4a53 100644 (file)
@@ -494,13 +494,6 @@ static int qcom_l3_cache__event_init(struct perf_event *event)
        if (event->attr.type != event->pmu->type)
                return -ENOENT;
 
-       /*
-        * There are no per-counter mode filters in the PMU.
-        */
-       if (event->attr.exclude_user || event->attr.exclude_kernel ||
-           event->attr.exclude_hv || event->attr.exclude_idle)
-               return -EINVAL;
-
        /*
         * Sampling not supported since these events are not core-attributable.
         */
@@ -777,6 +770,7 @@ static int qcom_l3_cache_pmu_probe(struct platform_device *pdev)
                .read           = qcom_l3_cache__event_read,
 
                .attr_groups    = qcom_l3_cache_pmu_attr_grps,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        memrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
index c9a1701d3e542998ee08ae54dea08347fc40ca19..43d76c85da56b7a4941e28f435c2877f3d512a08 100644 (file)
@@ -424,15 +424,6 @@ static int tx2_uncore_event_init(struct perf_event *event)
        if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
                return -EINVAL;
 
-       /* We have no filtering of any kind */
-       if (event->attr.exclude_user    ||
-           event->attr.exclude_kernel  ||
-           event->attr.exclude_hv      ||
-           event->attr.exclude_idle    ||
-           event->attr.exclude_host    ||
-           event->attr.exclude_guest)
-               return -EINVAL;
-
        if (event->cpu < 0)
                return -EINVAL;
 
@@ -572,6 +563,7 @@ static int tx2_uncore_pmu_register(
                .start          = tx2_uncore_event_start,
                .stop           = tx2_uncore_event_stop,
                .read           = tx2_uncore_event_read,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        tx2_pmu->pmu.name = devm_kasprintf(dev, GFP_KERNEL,
index 0dc9ff0f88940c6b1fe8b74003f5284736c305c4..d4ec04868d598c73ffff3c0c35c1f09db4b2d9d5 100644 (file)
@@ -917,11 +917,6 @@ static int xgene_perf_event_init(struct perf_event *event)
        if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
                return -EINVAL;
 
-       /* SOC counters do not have usr/os/guest/host bits */
-       if (event->attr.exclude_user || event->attr.exclude_kernel ||
-           event->attr.exclude_host || event->attr.exclude_guest)
-               return -EINVAL;
-
        if (event->cpu < 0)
                return -EINVAL;
        /*
@@ -1136,6 +1131,7 @@ static int xgene_init_perf(struct xgene_pmu_dev *pmu_dev, char *name)
                .start          = xgene_perf_start,
                .stop           = xgene_perf_stop,
                .read           = xgene_perf_read,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        };
 
        /* Hardware counter init */
index 46c67a7648778d8e7e1b0793bd8683567d132fce..7b87965f7a65c90d8e98f11b14ab5b5b1f967abb 100644 (file)
@@ -154,8 +154,9 @@ struct coresight_connection {
  * @orphan:    true if the component has connections that haven't been linked.
  * @enable:    'true' if component is currently part of an active path.
  * @activated: 'true' only if a _sink_ has been activated.  A sink can be
-               activated but not yet enabled.  Enabling for a _sink_
-               happens when a source has been selected for that it.
+ *             activated but not yet enabled.  Enabling for a _sink_
+ *             appens when a source has been selected for that it.
+ * @ea:                Device attribute for sink representation under PMU directory.
  */
 struct coresight_device {
        struct coresight_connection *conns;
@@ -168,7 +169,9 @@ struct coresight_device {
        atomic_t *refcnt;
        bool orphan;
        bool enable;    /* true only if configured as part of a path */
+       /* sink specific fields */
        bool activated; /* true only if a sink is part of a path */
+       struct dev_ext_attribute *ea;
 };
 
 #define to_coresight_device(d) container_of(d, struct coresight_device, dev)
index 7e5e3db11106f719b8736ff5a81ab1da71a23993..6074aa064b540929ce076781884d436a7598f533 100644 (file)
@@ -1007,6 +1007,7 @@ bpf_address_lookup(unsigned long addr, unsigned long *size,
 
 void bpf_prog_kallsyms_add(struct bpf_prog *fp);
 void bpf_prog_kallsyms_del(struct bpf_prog *fp);
+void bpf_get_prog_name(const struct bpf_prog *prog, char *sym);
 
 #else /* CONFIG_BPF_JIT */
 
@@ -1062,6 +1063,12 @@ static inline void bpf_prog_kallsyms_add(struct bpf_prog *fp)
 static inline void bpf_prog_kallsyms_del(struct bpf_prog *fp)
 {
 }
+
+static inline void bpf_get_prog_name(const struct bpf_prog *prog, char *sym)
+{
+       sym[0] = '\0';
+}
+
 #endif /* CONFIG_BPF_JIT */
 
 void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp);
index e1a051724f7ef9c89864bfaffe31af328c5ecd68..e47ef764f613ed5231121e8347575e37a53d5b1d 100644 (file)
@@ -53,8 +53,8 @@ struct perf_guest_info_callbacks {
 #include <linux/atomic.h>
 #include <linux/sysfs.h>
 #include <linux/perf_regs.h>
-#include <linux/workqueue.h>
 #include <linux/cgroup.h>
+#include <linux/refcount.h>
 #include <asm/local.h>
 
 struct perf_callchain_entry {
@@ -244,6 +244,7 @@ struct perf_event;
 #define PERF_PMU_CAP_EXCLUSIVE                 0x10
 #define PERF_PMU_CAP_ITRACE                    0x20
 #define PERF_PMU_CAP_HETEROGENEOUS_CPUS                0x40
+#define PERF_PMU_CAP_NO_EXCLUDE                        0x80
 
 /**
  * struct pmu - generic performance monitoring unit
@@ -409,7 +410,7 @@ struct pmu {
        /*
         * Set up pmu-private data structures for an AUX area
         */
-       void *(*setup_aux)              (int cpu, void **pages,
+       void *(*setup_aux)              (struct perf_event *event, void **pages,
                                         int nr_pages, bool overwrite);
                                        /* optional */
 
@@ -494,6 +495,11 @@ struct perf_addr_filters_head {
        unsigned int            nr_file_filters;
 };
 
+struct perf_addr_filter_range {
+       unsigned long           start;
+       unsigned long           size;
+};
+
 /**
  * enum perf_event_state - the states of an event:
  */
@@ -670,7 +676,7 @@ struct perf_event {
        /* address range filters */
        struct perf_addr_filters_head   addr_filters;
        /* vma address array for file-based filders */
-       unsigned long                   *addr_filters_offs;
+       struct perf_addr_filter_range   *addr_filter_ranges;
        unsigned long                   addr_filters_gen;
 
        void (*destroy)(struct perf_event *);
@@ -742,7 +748,7 @@ struct perf_event_context {
        int                             nr_stat;
        int                             nr_freq;
        int                             rotate_disable;
-       atomic_t                        refcount;
+       refcount_t                      refcount;
        struct task_struct              *task;
 
        /*
@@ -983,9 +989,9 @@ extern void perf_event_output_forward(struct perf_event *event,
 extern void perf_event_output_backward(struct perf_event *event,
                                       struct perf_sample_data *data,
                                       struct pt_regs *regs);
-extern void perf_event_output(struct perf_event *event,
-                             struct perf_sample_data *data,
-                             struct pt_regs *regs);
+extern int perf_event_output(struct perf_event *event,
+                            struct perf_sample_data *data,
+                            struct pt_regs *regs);
 
 static inline bool
 is_default_overflow_handler(struct perf_event *event)
@@ -1009,6 +1015,15 @@ perf_event__output_id_sample(struct perf_event *event,
 extern void
 perf_log_lost_samples(struct perf_event *event, u64 lost);
 
+static inline bool event_has_any_exclude_flag(struct perf_event *event)
+{
+       struct perf_event_attr *attr = &event->attr;
+
+       return attr->exclude_idle || attr->exclude_user ||
+              attr->exclude_kernel || attr->exclude_hv ||
+              attr->exclude_guest || attr->exclude_host;
+}
+
 static inline bool is_sampling_event(struct perf_event *event)
 {
        return event->attr.sample_period != 0;
@@ -1118,6 +1133,13 @@ static inline void perf_event_task_sched_out(struct task_struct *prev,
 }
 
 extern void perf_event_mmap(struct vm_area_struct *vma);
+
+extern void perf_event_ksymbol(u16 ksym_type, u64 addr, u32 len,
+                              bool unregister, const char *sym);
+extern void perf_event_bpf_event(struct bpf_prog *prog,
+                                enum perf_bpf_event_type type,
+                                u16 flags);
+
 extern struct perf_guest_info_callbacks *perf_guest_cbs;
 extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks);
 extern int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks);
@@ -1338,6 +1360,13 @@ static inline int perf_unregister_guest_info_callbacks
 (struct perf_guest_info_callbacks *callbacks)                          { return 0; }
 
 static inline void perf_event_mmap(struct vm_area_struct *vma)         { }
+
+typedef int (perf_ksymbol_get_name_f)(char *name, int name_len, void *data);
+static inline void perf_event_ksymbol(u16 ksym_type, u64 addr, u32 len,
+                                     bool unregister, const char *sym) { }
+static inline void perf_event_bpf_event(struct bpf_prog *prog,
+                                       enum perf_bpf_event_type type,
+                                       u16 flags)                      { }
 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)      { }
index 9de8780ac8d97568932d3857de3dc2c8e5de2806..7198ddd0c6b11d07286aa60504aedc6a0bea69ed 100644 (file)
@@ -372,7 +372,9 @@ struct perf_event_attr {
                                context_switch :  1, /* context switch data */
                                write_backward :  1, /* Write ring buffer from end to beginning */
                                namespaces     :  1, /* include namespaces data */
-                               __reserved_1   : 35;
+                               ksymbol        :  1, /* include ksymbol events */
+                               bpf_event      :  1, /* include bpf events */
+                               __reserved_1   : 33;
 
        union {
                __u32           wakeup_events;    /* wakeup every n events */
@@ -445,8 +447,6 @@ struct perf_event_query_bpf {
        __u32   ids[0];
 };
 
-#define perf_flags(attr)       (*(&(attr)->read_format + 1))
-
 /*
  * Ioctls that can be done on a perf event fd:
  */
@@ -965,9 +965,58 @@ enum perf_event_type {
         */
        PERF_RECORD_NAMESPACES                  = 16,
 
+       /*
+        * Record ksymbol register/unregister events:
+        *
+        * struct {
+        *      struct perf_event_header        header;
+        *      u64                             addr;
+        *      u32                             len;
+        *      u16                             ksym_type;
+        *      u16                             flags;
+        *      char                            name[];
+        *      struct sample_id                sample_id;
+        * };
+        */
+       PERF_RECORD_KSYMBOL                     = 17,
+
+       /*
+        * Record bpf events:
+        *  enum perf_bpf_event_type {
+        *      PERF_BPF_EVENT_UNKNOWN          = 0,
+        *      PERF_BPF_EVENT_PROG_LOAD        = 1,
+        *      PERF_BPF_EVENT_PROG_UNLOAD      = 2,
+        *  };
+        *
+        * struct {
+        *      struct perf_event_header        header;
+        *      u16                             type;
+        *      u16                             flags;
+        *      u32                             id;
+        *      u8                              tag[BPF_TAG_SIZE];
+        *      struct sample_id                sample_id;
+        * };
+        */
+       PERF_RECORD_BPF_EVENT                   = 18,
+
        PERF_RECORD_MAX,                        /* non-ABI */
 };
 
+enum perf_record_ksymbol_type {
+       PERF_RECORD_KSYMBOL_TYPE_UNKNOWN        = 0,
+       PERF_RECORD_KSYMBOL_TYPE_BPF            = 1,
+       PERF_RECORD_KSYMBOL_TYPE_MAX            /* non-ABI */
+};
+
+#define PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER   (1 << 0)
+
+enum perf_bpf_event_type {
+       PERF_BPF_EVENT_UNKNOWN          = 0,
+       PERF_BPF_EVENT_PROG_LOAD        = 1,
+       PERF_BPF_EVENT_PROG_UNLOAD      = 2,
+       PERF_BPF_EVENT_MAX,             /* non-ABI */
+};
+
 #define PERF_MAX_STACK_DEPTH           127
 #define PERF_MAX_CONTEXTS_PER_STACK      8
 
index 3f08c257858e1570339cd64a6351824bcc332ee3..ff09d32a8a1be210e88a0e6f7f14596ee6b89f06 100644 (file)
@@ -539,7 +539,7 @@ bpf_get_prog_addr_region(const struct bpf_prog *prog,
        *symbol_end   = addr + hdr->pages * PAGE_SIZE;
 }
 
-static void bpf_get_prog_name(const struct bpf_prog *prog, char *sym)
+void bpf_get_prog_name(const struct bpf_prog *prog, char *sym)
 {
        const char *end = sym + KSYM_NAME_LEN;
        const struct btf_type *type;
index bc34cf9fe9eedd1e1e3779fe06fa94db22b6231a..62f6bced3a3c486732dd871693d5d44cf19ab8c2 100644 (file)
@@ -1258,6 +1258,7 @@ static void __bpf_prog_put_rcu(struct rcu_head *rcu)
 static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
 {
        if (atomic_dec_and_test(&prog->aux->refcnt)) {
+               perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
                /* bpf_prog_free_id() must be called first */
                bpf_prog_free_id(prog, do_idr_lock);
                bpf_prog_kallsyms_del_all(prog);
@@ -1631,6 +1632,7 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
        }
 
        bpf_prog_kallsyms_add(prog);
+       perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0);
        return err;
 
 free_used_maps:
index 24a77c34e9adbcda4bcb7bd6991b1bc2efbaf3e5..c2b41a263166c72e9c569ab4957aeb928e06dda9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Performance events callchain code, extracted from core.c:
  *
@@ -5,8 +6,6 @@
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
  *  Copyright  ©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
- *
- * For licensing details see kernel-base/COPYING
  */
 
 #include <linux/perf_event.h>
index 26d6edab051a1e41c81d23b8c29ab097d6c4c71b..5f59d848171ea587f4cfcc8c8e18e4b5ea01ae85 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Performance events core code:
  *
@@ -5,8 +6,6 @@
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
  *  Copyright  ©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
- *
- * For licensing details see kernel-base/COPYING
  */
 
 #include <linux/fs.h>
@@ -385,6 +384,8 @@ 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;
+static atomic_t nr_ksymbol_events __read_mostly;
+static atomic_t nr_bpf_events __read_mostly;
 
 static LIST_HEAD(pmus);
 static DEFINE_MUTEX(pmus_lock);
@@ -1171,7 +1172,7 @@ static void perf_event_ctx_deactivate(struct perf_event_context *ctx)
 
 static void get_ctx(struct perf_event_context *ctx)
 {
-       WARN_ON(!atomic_inc_not_zero(&ctx->refcount));
+       refcount_inc(&ctx->refcount);
 }
 
 static void free_ctx(struct rcu_head *head)
@@ -1185,7 +1186,7 @@ static void free_ctx(struct rcu_head *head)
 
 static void put_ctx(struct perf_event_context *ctx)
 {
-       if (atomic_dec_and_test(&ctx->refcount)) {
+       if (refcount_dec_and_test(&ctx->refcount)) {
                if (ctx->parent_ctx)
                        put_ctx(ctx->parent_ctx);
                if (ctx->task && ctx->task != TASK_TOMBSTONE)
@@ -1254,6 +1255,7 @@ static void put_ctx(struct perf_event_context *ctx)
  *           perf_event_context::lock
  *         perf_event::mmap_mutex
  *         mmap_sem
+ *           perf_addr_filters_head::lock
  *
  *    cpu_hotplug_lock
  *      pmus_lock
@@ -1267,7 +1269,7 @@ perf_event_ctx_lock_nested(struct perf_event *event, int nesting)
 again:
        rcu_read_lock();
        ctx = READ_ONCE(event->ctx);
-       if (!atomic_inc_not_zero(&ctx->refcount)) {
+       if (!refcount_inc_not_zero(&ctx->refcount)) {
                rcu_read_unlock();
                goto again;
        }
@@ -1400,7 +1402,7 @@ retry:
                }
 
                if (ctx->task == TASK_TOMBSTONE ||
-                   !atomic_inc_not_zero(&ctx->refcount)) {
+                   !refcount_inc_not_zero(&ctx->refcount)) {
                        raw_spin_unlock(&ctx->lock);
                        ctx = NULL;
                } else {
@@ -2797,7 +2799,7 @@ static int perf_event_stop(struct perf_event *event, int restart)
  *
  * (p1) when userspace mappings change as a result of (1) or (2) or (3) below,
  *      we update the addresses of corresponding vmas in
- *     event::addr_filters_offs array and bump the event::addr_filters_gen;
+ *     event::addr_filter_ranges array and bump the event::addr_filters_gen;
  * (p2) when an event is scheduled in (pmu::add), it calls
  *      perf_event_addr_filters_sync() which calls pmu::addr_filters_sync()
  *      if the generation has changed since the previous call.
@@ -4056,7 +4058,7 @@ static void __perf_event_init_context(struct perf_event_context *ctx)
        INIT_LIST_HEAD(&ctx->event_list);
        INIT_LIST_HEAD(&ctx->pinned_active);
        INIT_LIST_HEAD(&ctx->flexible_active);
-       atomic_set(&ctx->refcount, 1);
+       refcount_set(&ctx->refcount, 1);
 }
 
 static struct perf_event_context *
@@ -4235,7 +4237,7 @@ static bool is_sb_event(struct perf_event *event)
 
        if (attr->mmap || attr->mmap_data || attr->mmap2 ||
            attr->comm || attr->comm_exec ||
-           attr->task ||
+           attr->task || attr->ksymbol ||
            attr->context_switch)
                return true;
        return false;
@@ -4305,6 +4307,10 @@ static void unaccount_event(struct perf_event *event)
                dec = true;
        if (has_branch_stack(event))
                dec = true;
+       if (event->attr.ksymbol)
+               atomic_dec(&nr_ksymbol_events);
+       if (event->attr.bpf_event)
+               atomic_dec(&nr_bpf_events);
 
        if (dec) {
                if (!atomic_add_unless(&perf_sched_count, -1, 1))
@@ -4440,7 +4446,7 @@ static void _free_event(struct perf_event *event)
 
        perf_event_free_bpf_prog(event);
        perf_addr_filters_splice(event, NULL);
-       kfree(event->addr_filters_offs);
+       kfree(event->addr_filter_ranges);
 
        if (event->destroy)
                event->destroy(event);
@@ -5396,7 +5402,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event *event)
        rcu_read_lock();
        rb = rcu_dereference(event->rb);
        if (rb) {
-               if (!atomic_inc_not_zero(&rb->refcount))
+               if (!refcount_inc_not_zero(&rb->refcount))
                        rb = NULL;
        }
        rcu_read_unlock();
@@ -5406,7 +5412,7 @@ struct ring_buffer *ring_buffer_get(struct perf_event *event)
 
 void ring_buffer_put(struct ring_buffer *rb)
 {
-       if (!atomic_dec_and_test(&rb->refcount))
+       if (!refcount_dec_and_test(&rb->refcount))
                return;
 
        WARN_ON_ONCE(!list_empty(&rb->event_list));
@@ -5471,7 +5477,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
 
                /* this has to be the last one */
                rb_free_aux(rb);
-               WARN_ON_ONCE(atomic_read(&rb->aux_refcount));
+               WARN_ON_ONCE(refcount_read(&rb->aux_refcount));
 
                mutex_unlock(&event->mmap_mutex);
        }
@@ -6497,7 +6503,7 @@ void perf_prepare_sample(struct perf_event_header *header,
                data->phys_addr = perf_virt_to_phys(data->addr);
 }
 
-static __always_inline void
+static __always_inline int
 __perf_event_output(struct perf_event *event,
                    struct perf_sample_data *data,
                    struct pt_regs *regs,
@@ -6507,13 +6513,15 @@ __perf_event_output(struct perf_event *event,
 {
        struct perf_output_handle handle;
        struct perf_event_header header;
+       int err;
 
        /* protect the callchain buffers */
        rcu_read_lock();
 
        perf_prepare_sample(&header, data, event, regs);
 
-       if (output_begin(&handle, event, header.size))
+       err = output_begin(&handle, event, header.size);
+       if (err)
                goto exit;
 
        perf_output_sample(&handle, &header, data, event);
@@ -6522,6 +6530,7 @@ __perf_event_output(struct perf_event *event,
 
 exit:
        rcu_read_unlock();
+       return err;
 }
 
 void
@@ -6540,12 +6549,12 @@ perf_event_output_backward(struct perf_event *event,
        __perf_event_output(event, data, regs, perf_output_begin_backward);
 }
 
-void
+int
 perf_event_output(struct perf_event *event,
                  struct perf_sample_data *data,
                  struct pt_regs *regs)
 {
-       __perf_event_output(event, data, regs, perf_output_begin);
+       return __perf_event_output(event, data, regs, perf_output_begin);
 }
 
 /*
@@ -6686,7 +6695,8 @@ static void perf_event_addr_filters_exec(struct perf_event *event, void *data)
        raw_spin_lock_irqsave(&ifh->lock, flags);
        list_for_each_entry(filter, &ifh->list, entry) {
                if (filter->path.dentry) {
-                       event->addr_filters_offs[count] = 0;
+                       event->addr_filter_ranges[count].start = 0;
+                       event->addr_filter_ranges[count].size = 0;
                        restart++;
                }
 
@@ -7366,28 +7376,47 @@ static bool perf_addr_filter_match(struct perf_addr_filter *filter,
        return true;
 }
 
+static bool perf_addr_filter_vma_adjust(struct perf_addr_filter *filter,
+                                       struct vm_area_struct *vma,
+                                       struct perf_addr_filter_range *fr)
+{
+       unsigned long vma_size = vma->vm_end - vma->vm_start;
+       unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+       struct file *file = vma->vm_file;
+
+       if (!perf_addr_filter_match(filter, file, off, vma_size))
+               return false;
+
+       if (filter->offset < off) {
+               fr->start = vma->vm_start;
+               fr->size = min(vma_size, filter->size - (off - filter->offset));
+       } else {
+               fr->start = vma->vm_start + filter->offset - off;
+               fr->size = min(vma->vm_end - fr->start, filter->size);
+       }
+
+       return true;
+}
+
 static void __perf_addr_filters_adjust(struct perf_event *event, void *data)
 {
        struct perf_addr_filters_head *ifh = perf_event_addr_filters(event);
        struct vm_area_struct *vma = data;
-       unsigned long off = vma->vm_pgoff << PAGE_SHIFT, flags;
-       struct file *file = vma->vm_file;
        struct perf_addr_filter *filter;
        unsigned int restart = 0, count = 0;
+       unsigned long flags;
 
        if (!has_addr_filter(event))
                return;
 
-       if (!file)
+       if (!vma->vm_file)
                return;
 
        raw_spin_lock_irqsave(&ifh->lock, flags);
        list_for_each_entry(filter, &ifh->list, entry) {
-               if (perf_addr_filter_match(filter, file, off,
-                                            vma->vm_end - vma->vm_start)) {
-                       event->addr_filters_offs[count] = vma->vm_start;
+               if (perf_addr_filter_vma_adjust(filter, vma,
+                                               &event->addr_filter_ranges[count]))
                        restart++;
-               }
 
                count++;
        }
@@ -7658,6 +7687,207 @@ static void perf_log_throttle(struct perf_event *event, int enable)
        perf_output_end(&handle);
 }
 
+/*
+ * ksymbol register/unregister tracking
+ */
+
+struct perf_ksymbol_event {
+       const char      *name;
+       int             name_len;
+       struct {
+               struct perf_event_header        header;
+               u64                             addr;
+               u32                             len;
+               u16                             ksym_type;
+               u16                             flags;
+       } event_id;
+};
+
+static int perf_event_ksymbol_match(struct perf_event *event)
+{
+       return event->attr.ksymbol;
+}
+
+static void perf_event_ksymbol_output(struct perf_event *event, void *data)
+{
+       struct perf_ksymbol_event *ksymbol_event = data;
+       struct perf_output_handle handle;
+       struct perf_sample_data sample;
+       int ret;
+
+       if (!perf_event_ksymbol_match(event))
+               return;
+
+       perf_event_header__init_id(&ksymbol_event->event_id.header,
+                                  &sample, event);
+       ret = perf_output_begin(&handle, event,
+                               ksymbol_event->event_id.header.size);
+       if (ret)
+               return;
+
+       perf_output_put(&handle, ksymbol_event->event_id);
+       __output_copy(&handle, ksymbol_event->name, ksymbol_event->name_len);
+       perf_event__output_id_sample(event, &handle, &sample);
+
+       perf_output_end(&handle);
+}
+
+void perf_event_ksymbol(u16 ksym_type, u64 addr, u32 len, bool unregister,
+                       const char *sym)
+{
+       struct perf_ksymbol_event ksymbol_event;
+       char name[KSYM_NAME_LEN];
+       u16 flags = 0;
+       int name_len;
+
+       if (!atomic_read(&nr_ksymbol_events))
+               return;
+
+       if (ksym_type >= PERF_RECORD_KSYMBOL_TYPE_MAX ||
+           ksym_type == PERF_RECORD_KSYMBOL_TYPE_UNKNOWN)
+               goto err;
+
+       strlcpy(name, sym, KSYM_NAME_LEN);
+       name_len = strlen(name) + 1;
+       while (!IS_ALIGNED(name_len, sizeof(u64)))
+               name[name_len++] = '\0';
+       BUILD_BUG_ON(KSYM_NAME_LEN % sizeof(u64));
+
+       if (unregister)
+               flags |= PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER;
+
+       ksymbol_event = (struct perf_ksymbol_event){
+               .name = name,
+               .name_len = name_len,
+               .event_id = {
+                       .header = {
+                               .type = PERF_RECORD_KSYMBOL,
+                               .size = sizeof(ksymbol_event.event_id) +
+                                       name_len,
+                       },
+                       .addr = addr,
+                       .len = len,
+                       .ksym_type = ksym_type,
+                       .flags = flags,
+               },
+       };
+
+       perf_iterate_sb(perf_event_ksymbol_output, &ksymbol_event, NULL);
+       return;
+err:
+       WARN_ONCE(1, "%s: Invalid KSYMBOL type 0x%x\n", __func__, ksym_type);
+}
+
+/*
+ * bpf program load/unload tracking
+ */
+
+struct perf_bpf_event {
+       struct bpf_prog *prog;
+       struct {
+               struct perf_event_header        header;
+               u16                             type;
+               u16                             flags;
+               u32                             id;
+               u8                              tag[BPF_TAG_SIZE];
+       } event_id;
+};
+
+static int perf_event_bpf_match(struct perf_event *event)
+{
+       return event->attr.bpf_event;
+}
+
+static void perf_event_bpf_output(struct perf_event *event, void *data)
+{
+       struct perf_bpf_event *bpf_event = data;
+       struct perf_output_handle handle;
+       struct perf_sample_data sample;
+       int ret;
+
+       if (!perf_event_bpf_match(event))
+               return;
+
+       perf_event_header__init_id(&bpf_event->event_id.header,
+                                  &sample, event);
+       ret = perf_output_begin(&handle, event,
+                               bpf_event->event_id.header.size);
+       if (ret)
+               return;
+
+       perf_output_put(&handle, bpf_event->event_id);
+       perf_event__output_id_sample(event, &handle, &sample);
+
+       perf_output_end(&handle);
+}
+
+static void perf_event_bpf_emit_ksymbols(struct bpf_prog *prog,
+                                        enum perf_bpf_event_type type)
+{
+       bool unregister = type == PERF_BPF_EVENT_PROG_UNLOAD;
+       char sym[KSYM_NAME_LEN];
+       int i;
+
+       if (prog->aux->func_cnt == 0) {
+               bpf_get_prog_name(prog, sym);
+               perf_event_ksymbol(PERF_RECORD_KSYMBOL_TYPE_BPF,
+                                  (u64)(unsigned long)prog->bpf_func,
+                                  prog->jited_len, unregister, sym);
+       } else {
+               for (i = 0; i < prog->aux->func_cnt; i++) {
+                       struct bpf_prog *subprog = prog->aux->func[i];
+
+                       bpf_get_prog_name(subprog, sym);
+                       perf_event_ksymbol(
+                               PERF_RECORD_KSYMBOL_TYPE_BPF,
+                               (u64)(unsigned long)subprog->bpf_func,
+                               subprog->jited_len, unregister, sym);
+               }
+       }
+}
+
+void perf_event_bpf_event(struct bpf_prog *prog,
+                         enum perf_bpf_event_type type,
+                         u16 flags)
+{
+       struct perf_bpf_event bpf_event;
+
+       if (type <= PERF_BPF_EVENT_UNKNOWN ||
+           type >= PERF_BPF_EVENT_MAX)
+               return;
+
+       switch (type) {
+       case PERF_BPF_EVENT_PROG_LOAD:
+       case PERF_BPF_EVENT_PROG_UNLOAD:
+               if (atomic_read(&nr_ksymbol_events))
+                       perf_event_bpf_emit_ksymbols(prog, type);
+               break;
+       default:
+               break;
+       }
+
+       if (!atomic_read(&nr_bpf_events))
+               return;
+
+       bpf_event = (struct perf_bpf_event){
+               .prog = prog,
+               .event_id = {
+                       .header = {
+                               .type = PERF_RECORD_BPF_EVENT,
+                               .size = sizeof(bpf_event.event_id),
+                       },
+                       .type = type,
+                       .flags = flags,
+                       .id = prog->aux->id,
+               },
+       };
+
+       BUILD_BUG_ON(BPF_TAG_SIZE % sizeof(u64));
+
+       memcpy(bpf_event.event_id.tag, prog->tag, BPF_TAG_SIZE);
+       perf_iterate_sb(perf_event_bpf_output, &bpf_event, NULL);
+}
+
 void perf_event_itrace_started(struct perf_event *event)
 {
        event->attach_state |= PERF_ATTACH_ITRACE;
@@ -8776,26 +9006,19 @@ static void perf_addr_filters_splice(struct perf_event *event,
  * @filter; if so, adjust filter's address range.
  * Called with mm::mmap_sem down for reading.
  */
-static unsigned long perf_addr_filter_apply(struct perf_addr_filter *filter,
-                                           struct mm_struct *mm)
+static void perf_addr_filter_apply(struct perf_addr_filter *filter,
+                                  struct mm_struct *mm,
+                                  struct perf_addr_filter_range *fr)
 {
        struct vm_area_struct *vma;
 
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
-               struct file *file = vma->vm_file;
-               unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
-               unsigned long vma_size = vma->vm_end - vma->vm_start;
-
-               if (!file)
-                       continue;
-
-               if (!perf_addr_filter_match(filter, file, off, vma_size))
+               if (!vma->vm_file)
                        continue;
 
-               return vma->vm_start;
+               if (perf_addr_filter_vma_adjust(filter, vma, fr))
+                       return;
        }
-
-       return 0;
 }
 
 /*
@@ -8829,15 +9052,15 @@ static void perf_event_addr_filters_apply(struct perf_event *event)
 
        raw_spin_lock_irqsave(&ifh->lock, flags);
        list_for_each_entry(filter, &ifh->list, entry) {
-               event->addr_filters_offs[count] = 0;
+               event->addr_filter_ranges[count].start = 0;
+               event->addr_filter_ranges[count].size = 0;
 
                /*
                 * Adjust base offset if the filter is associated to a binary
                 * that needs to be mapped:
                 */
                if (filter->path.dentry)
-                       event->addr_filters_offs[count] =
-                               perf_addr_filter_apply(filter, mm);
+                       perf_addr_filter_apply(filter, mm, &event->addr_filter_ranges[count]);
 
                count++;
        }
@@ -9788,6 +10011,15 @@ static int perf_try_init_event(struct pmu *pmu, struct perf_event *event)
        if (ctx)
                perf_event_ctx_unlock(event->group_leader, ctx);
 
+       if (!ret) {
+               if (pmu->capabilities & PERF_PMU_CAP_NO_EXCLUDE &&
+                               event_has_any_exclude_flag(event)) {
+                       if (event->destroy)
+                               event->destroy(event);
+                       ret = -EINVAL;
+               }
+       }
+
        if (ret)
                module_put(pmu->module);
 
@@ -9916,6 +10148,10 @@ static void account_event(struct perf_event *event)
                inc = true;
        if (is_cgroup_event(event))
                inc = true;
+       if (event->attr.ksymbol)
+               atomic_inc(&nr_ksymbol_events);
+       if (event->attr.bpf_event)
+               atomic_inc(&nr_bpf_events);
 
        if (inc) {
                /*
@@ -10098,14 +10334,28 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
                goto err_pmu;
 
        if (has_addr_filter(event)) {
-               event->addr_filters_offs = kcalloc(pmu->nr_addr_filters,
-                                                  sizeof(unsigned long),
-                                                  GFP_KERNEL);
-               if (!event->addr_filters_offs) {
+               event->addr_filter_ranges = kcalloc(pmu->nr_addr_filters,
+                                                   sizeof(struct perf_addr_filter_range),
+                                                   GFP_KERNEL);
+               if (!event->addr_filter_ranges) {
                        err = -ENOMEM;
                        goto err_per_task;
                }
 
+               /*
+                * Clone the parent's vma offsets: they are valid until exec()
+                * even if the mm is not shared with the parent.
+                */
+               if (event->parent) {
+                       struct perf_addr_filters_head *ifh = perf_event_addr_filters(event);
+
+                       raw_spin_lock_irq(&ifh->lock);
+                       memcpy(event->addr_filter_ranges,
+                              event->parent->addr_filter_ranges,
+                              pmu->nr_addr_filters * sizeof(struct perf_addr_filter_range));
+                       raw_spin_unlock_irq(&ifh->lock);
+               }
+
                /* force hw sync on the address filters */
                event->addr_filters_gen = 1;
        }
@@ -10124,7 +10374,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
        return event;
 
 err_addr_filters:
-       kfree(event->addr_filters_offs);
+       kfree(event->addr_filter_ranges);
 
 err_per_task:
        exclusive_event_destroy(event);
@@ -10407,7 +10657,7 @@ __perf_event_ctx_lock_double(struct perf_event *group_leader,
 again:
        rcu_read_lock();
        gctx = READ_ONCE(group_leader->ctx);
-       if (!atomic_inc_not_zero(&gctx->refcount)) {
+       if (!refcount_inc_not_zero(&gctx->refcount)) {
                rcu_read_unlock();
                goto again;
        }
index 5befb338a18d88ac5daec5c7593c11d34f43bd96..c5cd852fe86bb4e6eda1466330d7d6ea5f5a5fac 100644 (file)
@@ -1,18 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
  * Copyright (C) 2007 Alan Stern
  * Copyright (C) IBM Corporation, 2009
  * Copyright (C) 2009, Frederic Weisbecker <fweisbec@gmail.com>
index 6dc725a7e7bc91a866a85b7ac4045d92a610ecaa..79c47076700af5d1276d5ccb8c63d6435fff8cf8 100644 (file)
@@ -4,13 +4,14 @@
 
 #include <linux/hardirq.h>
 #include <linux/uaccess.h>
+#include <linux/refcount.h>
 
 /* Buffer handling */
 
 #define RING_BUFFER_WRITABLE           0x01
 
 struct ring_buffer {
-       atomic_t                        refcount;
+       refcount_t                      refcount;
        struct rcu_head                 rcu_head;
 #ifdef CONFIG_PERF_USE_VMALLOC
        struct work_struct              work;
@@ -48,7 +49,7 @@ struct ring_buffer {
        atomic_t                        aux_mmap_count;
        unsigned long                   aux_mmap_locked;
        void                            (*free_aux)(void *);
-       atomic_t                        aux_refcount;
+       refcount_t                      aux_refcount;
        void                            **aux_pages;
        void                            *aux_priv;
 
index 5ab4fe3b1dcc0b6a90bc2b4a5eb0e02a44ee909b..678ccec60d8fa4215754c01afea488e4668bbc58 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Performance events ring-buffer code:
  *
@@ -5,8 +6,6 @@
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
  *  Copyright  ©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
- *
- * For licensing details see kernel-base/COPYING
  */
 
 #include <linux/perf_event.h>
@@ -285,7 +284,7 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
        else
                rb->overwrite = 1;
 
-       atomic_set(&rb->refcount, 1);
+       refcount_set(&rb->refcount, 1);
 
        INIT_LIST_HEAD(&rb->event_list);
        spin_lock_init(&rb->event_lock);
@@ -358,7 +357,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
        if (!atomic_read(&rb->aux_mmap_count))
                goto err;
 
-       if (!atomic_inc_not_zero(&rb->aux_refcount))
+       if (!refcount_inc_not_zero(&rb->aux_refcount))
                goto err;
 
        /*
@@ -658,7 +657,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
                        goto out;
        }
 
-       rb->aux_priv = event->pmu->setup_aux(event->cpu, rb->aux_pages, nr_pages,
+       rb->aux_priv = event->pmu->setup_aux(event, rb->aux_pages, nr_pages,
                                             overwrite);
        if (!rb->aux_priv)
                goto out;
@@ -671,7 +670,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
         * we keep a refcount here to make sure either of the two can
         * reference them safely.
         */
-       atomic_set(&rb->aux_refcount, 1);
+       refcount_set(&rb->aux_refcount, 1);
 
        rb->aux_overwrite = overwrite;
        rb->aux_watermark = watermark;
@@ -690,7 +689,7 @@ out:
 
 void rb_free_aux(struct ring_buffer *rb)
 {
-       if (atomic_dec_and_test(&rb->aux_refcount))
+       if (refcount_dec_and_test(&rb->aux_refcount))
                __rb_free_aux(rb);
 }
 
index 8aef47ee7bfad62f6147412caa9af28314bd7758..affa830a198cd8a8a2d935050875ddd12f6eef72 100644 (file)
@@ -1,20 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * User-space Probes (UProbes)
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
  * Copyright (C) IBM Corporation, 2008-2012
  * Authors:
  *     Srikar Dronamraju
index f3a04994e0637c1180db334c582859f988fdfb3d..14934afa9e68bf9dd8ae2a497da412f25c253d55 100644 (file)
@@ -494,7 +494,7 @@ static int get_ksymbol_ftrace_mod(struct kallsym_iter *iter)
 
 static int get_ksymbol_bpf(struct kallsym_iter *iter)
 {
-       iter->module_name[0] = '\0';
+       strlcpy(iter->module_name, "bpf", MODULE_NAME_LEN);
        iter->exported = 0;
        return bpf_get_kallsym(iter->pos - iter->pos_ftrace_mod_end,
                               &iter->value, &iter->type,
index f4ddfdd2d07ea154387483fa539c3555dd775b10..c83e547271312e9f32ed5447fdb9eef1b8e2c2e7 100644 (file)
@@ -1396,7 +1396,7 @@ bool __weak arch_within_kprobe_blacklist(unsigned long addr)
               addr < (unsigned long)__kprobes_text_end;
 }
 
-bool within_kprobe_blacklist(unsigned long addr)
+static bool __within_kprobe_blacklist(unsigned long addr)
 {
        struct kprobe_blacklist_entry *ent;
 
@@ -1410,7 +1410,26 @@ bool within_kprobe_blacklist(unsigned long addr)
                if (addr >= ent->start_addr && addr < ent->end_addr)
                        return true;
        }
+       return false;
+}
 
+bool within_kprobe_blacklist(unsigned long addr)
+{
+       char symname[KSYM_NAME_LEN], *p;
+
+       if (__within_kprobe_blacklist(addr))
+               return true;
+
+       /* Check if the address is on a suffixed-symbol */
+       if (!lookup_symbol_name(addr, symname)) {
+               p = strchr(symname, '.');
+               if (!p)
+                       return false;
+               *p = '\0';
+               addr = (unsigned long)kprobe_lookup_name(symname, 0);
+               if (addr)
+                       return __within_kprobe_blacklist(addr);
+       }
        return false;
 }
 
index fda370ca529cd46c32707d5e9251467e1d27bfb2..21cb81fe63591b47ec61b6854d2050d0a8eb7153 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/jhash.h>
 #include <linux/nmi.h>
 #include <linux/rcupdate.h>
+#include <linux/kprobes.h>
 
 #include <asm/sections.h>
 
@@ -3161,6 +3162,7 @@ void lockdep_hardirqs_on(unsigned long ip)
        __trace_hardirqs_on_caller(ip);
        current->lockdep_recursion = 0;
 }
+NOKPROBE_SYMBOL(lockdep_hardirqs_on);
 
 /*
  * Hardirqs were disabled:
@@ -3190,6 +3192,7 @@ void lockdep_hardirqs_off(unsigned long ip)
        } else
                debug_atomic_inc(redundant_hardirqs_off);
 }
+NOKPROBE_SYMBOL(lockdep_hardirqs_off);
 
 /*
  * Softirqs will be enabled:
@@ -4007,7 +4010,8 @@ __lock_release(struct lockdep_map *lock, int nested, unsigned long ip)
        return 0;
 }
 
-static int __lock_is_held(const struct lockdep_map *lock, int read)
+static nokprobe_inline
+int __lock_is_held(const struct lockdep_map *lock, int read)
 {
        struct task_struct *curr = current;
        int i;
@@ -4240,6 +4244,7 @@ int lock_is_held_type(const struct lockdep_map *lock, int read)
        return ret;
 }
 EXPORT_SYMBOL_GPL(lock_is_held_type);
+NOKPROBE_SYMBOL(lock_is_held_type);
 
 struct pin_cookie lock_pin_lock(struct lockdep_map *lock)
 {
index 3b084dbfb4bc5fb6f4cdc0d4f355c305b0d05455..acd6ccf56faf9ff090b43ea08458b3380f22cc3d 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/ftrace.h>
 #include <linux/tick.h>
 #include <linux/sysrq.h>
+#include <linux/kprobes.h>
 
 #include "tree.h"
 #include "rcu.h"
@@ -882,6 +883,7 @@ void rcu_nmi_enter(void)
 {
        rcu_nmi_enter_common(false);
 }
+NOKPROBE_SYMBOL(rcu_nmi_enter);
 
 /**
  * rcu_irq_enter - inform RCU that current CPU is entering irq away from idle
index e3c6395c9b4c9f9e1093752fe782ec41dea9bf66..cbaa976c594518653bc3ef985361e812187e1ff2 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/tick.h>
 #include <linux/rcupdate_wait.h>
 #include <linux/sched/isolation.h>
+#include <linux/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 
@@ -236,6 +237,7 @@ int notrace debug_lockdep_rcu_enabled(void)
               current->lockdep_recursion == 0;
 }
 EXPORT_SYMBOL_GPL(debug_lockdep_rcu_enabled);
+NOKPROBE_SYMBOL(debug_lockdep_rcu_enabled);
 
 /**
  * rcu_read_lock_held() - might we be in RCU read-side critical section?
index f1a86a0d881ddb877b4a800bd4f31c30c76fab8e..d64c00afceb5de33df28e0a590635bca0d333e69 100644 (file)
@@ -431,8 +431,7 @@ __bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
        if (unlikely(event->oncpu != cpu))
                return -EOPNOTSUPP;
 
-       perf_event_output(event, sd, regs);
-       return 0;
+       return perf_event_output(event, sd, regs);
 }
 
 BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
index d3294721f11904010e8c5ddbcc833589310078e2..d42a473b82407f954f95427e129ff8cd00143179 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/ftrace.h>
+#include <linux/kprobes.h>
 
 #include "trace.h"
 
@@ -365,7 +366,7 @@ out:
        __trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc);
 }
 
-static inline void
+static nokprobe_inline void
 start_critical_timing(unsigned long ip, unsigned long parent_ip, int pc)
 {
        int cpu;
@@ -401,7 +402,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip, int pc)
        atomic_dec(&data->disabled);
 }
 
-static inline void
+static nokprobe_inline void
 stop_critical_timing(unsigned long ip, unsigned long parent_ip, int pc)
 {
        int cpu;
@@ -443,6 +444,7 @@ void start_critical_timings(void)
                start_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc);
 }
 EXPORT_SYMBOL_GPL(start_critical_timings);
+NOKPROBE_SYMBOL(start_critical_timings);
 
 void stop_critical_timings(void)
 {
@@ -452,6 +454,7 @@ void stop_critical_timings(void)
                stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc);
 }
 EXPORT_SYMBOL_GPL(stop_critical_timings);
+NOKPROBE_SYMBOL(stop_critical_timings);
 
 #ifdef CONFIG_FUNCTION_TRACER
 static bool function_enabled;
@@ -611,6 +614,7 @@ void tracer_hardirqs_on(unsigned long a0, unsigned long a1)
        if (!preempt_trace(pc) && irq_trace())
                stop_critical_timing(a0, a1, pc);
 }
+NOKPROBE_SYMBOL(tracer_hardirqs_on);
 
 void tracer_hardirqs_off(unsigned long a0, unsigned long a1)
 {
@@ -619,6 +623,7 @@ void tracer_hardirqs_off(unsigned long a0, unsigned long a1)
        if (!preempt_trace(pc) && irq_trace())
                start_critical_timing(a0, a1, pc);
 }
+NOKPROBE_SYMBOL(tracer_hardirqs_off);
 
 static int irqsoff_tracer_init(struct trace_array *tr)
 {
index 71f553cceb3c1ee07bafe04b419797e59793f8b7..4d8e99fdbbbeec6472919cd13ca0df2ea38a27d2 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/ftrace.h>
+#include <linux/kprobes.h>
 #include "trace.h"
 
 #define CREATE_TRACE_POINTS
@@ -30,6 +31,7 @@ void trace_hardirqs_on(void)
        lockdep_hardirqs_on(CALLER_ADDR0);
 }
 EXPORT_SYMBOL(trace_hardirqs_on);
+NOKPROBE_SYMBOL(trace_hardirqs_on);
 
 void trace_hardirqs_off(void)
 {
@@ -43,6 +45,7 @@ void trace_hardirqs_off(void)
        lockdep_hardirqs_off(CALLER_ADDR0);
 }
 EXPORT_SYMBOL(trace_hardirqs_off);
+NOKPROBE_SYMBOL(trace_hardirqs_off);
 
 __visible void trace_hardirqs_on_caller(unsigned long caller_addr)
 {
@@ -56,6 +59,7 @@ __visible void trace_hardirqs_on_caller(unsigned long caller_addr)
        lockdep_hardirqs_on(CALLER_ADDR0);
 }
 EXPORT_SYMBOL(trace_hardirqs_on_caller);
+NOKPROBE_SYMBOL(trace_hardirqs_on_caller);
 
 __visible void trace_hardirqs_off_caller(unsigned long caller_addr)
 {
@@ -69,6 +73,7 @@ __visible void trace_hardirqs_off_caller(unsigned long caller_addr)
        lockdep_hardirqs_off(CALLER_ADDR0);
 }
 EXPORT_SYMBOL(trace_hardirqs_off_caller);
+NOKPROBE_SYMBOL(trace_hardirqs_off_caller);
 #endif /* CONFIG_TRACE_IRQFLAGS */
 
 #ifdef CONFIG_TRACE_PREEMPT_TOGGLE
index 18b445b010c35a87be7480192d5aefa62583ac03..82512fe7b33c02dc6a2b3ae9c7887c0014ad734e 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/export.h>
 #include <linux/bsearch.h>
+#include <linux/kprobes.h>
 
 /*
  * bsearch - binary search an array of elements
@@ -53,3 +54,4 @@ void *bsearch(const void *key, const void *base, size_t num, size_t size,
        return NULL;
 }
 EXPORT_SYMBOL(bsearch);
+NOKPROBE_SYMBOL(bsearch);
index 85925aaa4fff5f6cb0831d3587c7a3ce18df751b..157d9e31f6c214f97e5b743a74657194d98501bb 100644 (file)
@@ -5,10 +5,11 @@
  * DEBUG_PREEMPT variant of smp_processor_id().
  */
 #include <linux/export.h>
+#include <linux/kprobes.h>
 #include <linux/sched.h>
 
-notrace static unsigned int check_preemption_disabled(const char *what1,
-                                                       const char *what2)
+notrace static nokprobe_inline
+unsigned int check_preemption_disabled(const char *what1, const char *what2)
 {
        int this_cpu = raw_smp_processor_id();
 
@@ -56,9 +57,11 @@ notrace unsigned int debug_smp_processor_id(void)
        return check_preemption_disabled("smp_processor_id", "");
 }
 EXPORT_SYMBOL(debug_smp_processor_id);
+NOKPROBE_SYMBOL(debug_smp_processor_id);
 
 notrace void __this_cpu_preempt_check(const char *op)
 {
        check_preemption_disabled("__this_cpu_", op);
 }
 EXPORT_SYMBOL(__this_cpu_preempt_check);
+NOKPROBE_SYMBOL(__this_cpu_preempt_check);
index 5467c6bf9cebebd01e03acd3e38d3cbc8c47e977..61e46d54a67c0dff521e665782b316f92ef9c320 100644 (file)
@@ -53,10 +53,6 @@ FEATURE_TESTS_BASIC :=                  \
         libslang                        \
         libcrypto                       \
         libunwind                       \
-        libunwind-x86                   \
-        libunwind-x86_64                \
-        libunwind-arm                   \
-        libunwind-aarch64               \
         pthread-attr-setaffinity-np     \
         pthread-barrier                \
         reallocarray                    \
@@ -70,7 +66,6 @@ FEATURE_TESTS_BASIC :=                  \
         sched_getcpu                   \
         sdt                            \
         setns                          \
-        libopencsd                     \
         libaio
 
 # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
@@ -84,6 +79,11 @@ FEATURE_TESTS_EXTRA :=                  \
          libbabeltrace                  \
          libbfd-liberty                 \
          libbfd-liberty-z               \
+         libopencsd                     \
+         libunwind-x86                  \
+         libunwind-x86_64               \
+         libunwind-arm                  \
+         libunwind-aarch64              \
          libunwind-debug-frame          \
          libunwind-debug-frame-arm      \
          libunwind-debug-frame-aarch64  \
index 20cdaa4fc112aa82d5c60bc4323420a331e360ae..e903b86b742f29d31c383165dab4bec120ee04ae 100644 (file)
 # include "test-setns.c"
 #undef main
 
-#define main main_test_libopencsd
-# include "test-libopencsd.c"
-#undef main
-
 #define main main_test_libaio
 # include "test-libaio.c"
 #undef main
 
+#define main main_test_reallocarray
+# include "test-reallocarray.c"
+#undef main
+
 int main(int argc, char *argv[])
 {
        main_test_libpython();
@@ -217,8 +217,8 @@ int main(int argc, char *argv[])
        main_test_sched_getcpu();
        main_test_sdt();
        main_test_setns();
-       main_test_libopencsd();
        main_test_libaio();
+       main_test_reallocarray();
 
        return 0;
 }
index 573000f932124b49fa5e6a6f060a326da85e0453..c3c201691b4fb93039324deadc1821d84e8b9cbb 100644 (file)
@@ -8,3 +8,4 @@ int main(void)
        free(get_current_dir_name());
        return 0;
 }
+#undef _GNU_SOURCE
index 0c1641b0d9a748983880b05067104037dc301d47..371c9113e49d1b7eb42fb5d46d63ad53a8762ce6 100644 (file)
@@ -7,3 +7,4 @@ int main(void)
 
        return 0;
 }
+#undef _GNU_SOURCE
index 8170de35150dd35c6ee4b67896edacddd6aece39..8f6743e31da71a1abca1bcc07512aae51957430e 100644 (file)
@@ -6,3 +6,5 @@ int main(void)
 {
        return !!reallocarray(NULL, 1, 1);
 }
+
+#undef _GNU_SOURCE
index e448deb4124c1ea8ed96f7b9a430095cdcac2e88..48995ac7911eae5084fada30c9b48069bdf2ba77 100644 (file)
@@ -8,3 +8,5 @@ int main(void)
 {
        return sched_getcpu();
 }
+
+#undef _GNU_SOURCE
index 1f714d2a658b11cd3c88926df7b271e9737e5989..4a1581ae7a5585c4bb4924802cc2c33956cec7fe 100644 (file)
@@ -5,3 +5,4 @@ int main(void)
 {
        return setns(0, 0);
 }
+#undef _GNU_SOURCE
index 112582253dd0319004e691953c27a475509a005e..8e9ed4786269260acb443182287fb41368815894 100644 (file)
@@ -43,13 +43,28 @@ struct rb_root {
        struct rb_node *rb_node;
 };
 
+/*
+ * Leftmost-cached rbtrees.
+ *
+ * We do not cache the rightmost node based on footprint
+ * size vs number of potential users that could benefit
+ * from O(1) rb_last(). Just not worth it, users that want
+ * this feature can always implement the logic explicitly.
+ * Furthermore, users that want to cache both pointers may
+ * find it a bit asymmetric, but that's ok.
+ */
+struct rb_root_cached {
+       struct rb_root rb_root;
+       struct rb_node *rb_leftmost;
+};
 
 #define rb_parent(r)   ((struct rb_node *)((r)->__rb_parent_color & ~3))
 
 #define RB_ROOT        (struct rb_root) { NULL, }
+#define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL }
 #define        rb_entry(ptr, type, member) container_of(ptr, type, member)
 
-#define RB_EMPTY_ROOT(root)  ((root)->rb_node == NULL)
+#define RB_EMPTY_ROOT(root)  (READ_ONCE((root)->rb_node) == NULL)
 
 /* 'empty' nodes are nodes that are known not to be inserted in an rbtree */
 #define RB_EMPTY_NODE(node)  \
@@ -68,6 +83,12 @@ extern struct rb_node *rb_prev(const struct rb_node *);
 extern struct rb_node *rb_first(const struct rb_root *);
 extern struct rb_node *rb_last(const struct rb_root *);
 
+extern void rb_insert_color_cached(struct rb_node *,
+                                  struct rb_root_cached *, bool);
+extern void rb_erase_cached(struct rb_node *node, struct rb_root_cached *);
+/* Same as rb_first(), but O(1) */
+#define rb_first_cached(root) (root)->rb_leftmost
+
 /* Postorder iteration - always visit the parent after its children */
 extern struct rb_node *rb_first_postorder(const struct rb_root *);
 extern struct rb_node *rb_next_postorder(const struct rb_node *);
@@ -75,6 +96,8 @@ extern struct rb_node *rb_next_postorder(const struct rb_node *);
 /* Fast replacement of a single node without remove/rebalance/add/rebalance */
 extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
                            struct rb_root *root);
+extern void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new,
+                                  struct rb_root_cached *root);
 
 static inline void rb_link_node(struct rb_node *node, struct rb_node *parent,
                                struct rb_node **rb_link)
@@ -90,12 +113,29 @@ static inline void rb_link_node(struct rb_node *node, struct rb_node *parent,
           ____ptr ? rb_entry(____ptr, type, member) : NULL; \
        })
 
-
-/*
- * Handy for checking that we are not deleting an entry that is
- * already in a list, found in block/{blk-throttle,cfq-iosched}.c,
- * probably should be moved to lib/rbtree.c...
+/**
+ * rbtree_postorder_for_each_entry_safe - iterate in post-order over rb_root of
+ * given type allowing the backing memory of @pos to be invalidated
+ *
+ * @pos:       the 'type *' to use as a loop cursor.
+ * @n:         another 'type *' to use as temporary storage
+ * @root:      'rb_root *' of the rbtree.
+ * @field:     the name of the rb_node field within 'type'.
+ *
+ * rbtree_postorder_for_each_entry_safe() provides a similar guarantee as
+ * list_for_each_entry_safe() and allows the iteration to continue independent
+ * of changes to @pos by the body of the loop.
+ *
+ * Note, however, that it cannot handle other modifications that re-order the
+ * rbtree it is iterating over. This includes calling rb_erase() on @pos, as
+ * rb_erase() may rebalance the tree, causing us to miss some nodes.
  */
+#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \
+       for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \
+            pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \
+                       typeof(*pos), field); 1; }); \
+            pos = n)
+
 static inline void rb_erase_init(struct rb_node *n, struct rb_root *root)
 {
        rb_erase(n, root);
index 43be941db695958ff2dbd3c084860407976ea5b3..d008e14045802fb77cf1fc0138b340a4f2285647 100644 (file)
@@ -44,7 +44,9 @@ struct rb_augment_callbacks {
        void (*rotate)(struct rb_node *old, struct rb_node *new);
 };
 
-extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
+extern void __rb_insert_augmented(struct rb_node *node,
+                                 struct rb_root *root,
+                                 bool newleft, struct rb_node **leftmost,
        void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
 /*
  * Fixup the rbtree and update the augmented information when rebalancing.
@@ -60,7 +62,16 @@ static inline void
 rb_insert_augmented(struct rb_node *node, struct rb_root *root,
                    const struct rb_augment_callbacks *augment)
 {
-       __rb_insert_augmented(node, root, augment->rotate);
+       __rb_insert_augmented(node, root, false, NULL, augment->rotate);
+}
+
+static inline void
+rb_insert_augmented_cached(struct rb_node *node,
+                          struct rb_root_cached *root, bool newleft,
+                          const struct rb_augment_callbacks *augment)
+{
+       __rb_insert_augmented(node, &root->rb_root,
+                             newleft, &root->rb_leftmost, augment->rotate);
 }
 
 #define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield,      \
@@ -93,7 +104,9 @@ rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new)    \
        old->rbaugmented = rbcompute(old);                              \
 }                                                                      \
 rbstatic const struct rb_augment_callbacks rbname = {                  \
-       rbname ## _propagate, rbname ## _copy, rbname ## _rotate        \
+       .propagate = rbname ## _propagate,                              \
+       .copy = rbname ## _copy,                                        \
+       .rotate = rbname ## _rotate                                     \
 };
 
 
@@ -126,11 +139,11 @@ __rb_change_child(struct rb_node *old, struct rb_node *new,
 {
        if (parent) {
                if (parent->rb_left == old)
-                       parent->rb_left = new;
+                       WRITE_ONCE(parent->rb_left, new);
                else
-                       parent->rb_right = new;
+                       WRITE_ONCE(parent->rb_right, new);
        } else
-               root->rb_node = new;
+               WRITE_ONCE(root->rb_node, new);
 }
 
 extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
@@ -138,12 +151,17 @@ extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
 
 static __always_inline struct rb_node *
 __rb_erase_augmented(struct rb_node *node, struct rb_root *root,
+                    struct rb_node **leftmost,
                     const struct rb_augment_callbacks *augment)
 {
-       struct rb_node *child = node->rb_right, *tmp = node->rb_left;
+       struct rb_node *child = node->rb_right;
+       struct rb_node *tmp = node->rb_left;
        struct rb_node *parent, *rebalance;
        unsigned long pc;
 
+       if (leftmost && node == *leftmost)
+               *leftmost = rb_next(node);
+
        if (!tmp) {
                /*
                 * Case 1: node to erase has no more than 1 child (easy!)
@@ -170,6 +188,7 @@ __rb_erase_augmented(struct rb_node *node, struct rb_root *root,
                tmp = parent;
        } else {
                struct rb_node *successor = child, *child2;
+
                tmp = child->rb_left;
                if (!tmp) {
                        /*
@@ -183,6 +202,7 @@ __rb_erase_augmented(struct rb_node *node, struct rb_root *root,
                         */
                        parent = successor;
                        child2 = successor->rb_right;
+
                        augment->copy(node, successor);
                } else {
                        /*
@@ -204,19 +224,23 @@ __rb_erase_augmented(struct rb_node *node, struct rb_root *root,
                                successor = tmp;
                                tmp = tmp->rb_left;
                        } while (tmp);
-                       parent->rb_left = child2 = successor->rb_right;
-                       successor->rb_right = child;
+                       child2 = successor->rb_right;
+                       WRITE_ONCE(parent->rb_left, child2);
+                       WRITE_ONCE(successor->rb_right, child);
                        rb_set_parent(child, successor);
+
                        augment->copy(node, successor);
                        augment->propagate(parent, successor);
                }
 
-               successor->rb_left = tmp = node->rb_left;
+               tmp = node->rb_left;
+               WRITE_ONCE(successor->rb_left, tmp);
                rb_set_parent(tmp, successor);
 
                pc = node->__rb_parent_color;
                tmp = __rb_parent(pc);
                __rb_change_child(node, successor, tmp, root);
+
                if (child2) {
                        successor->__rb_parent_color = pc;
                        rb_set_parent_color(child2, parent, RB_BLACK);
@@ -237,9 +261,21 @@ static __always_inline void
 rb_erase_augmented(struct rb_node *node, struct rb_root *root,
                   const struct rb_augment_callbacks *augment)
 {
-       struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
+       struct rb_node *rebalance = __rb_erase_augmented(node, root,
+                                                        NULL, augment);
        if (rebalance)
                __rb_erase_color(rebalance, root, augment->rotate);
 }
 
-#endif /* _TOOLS_LINUX_RBTREE_AUGMENTED_H */
+static __always_inline void
+rb_erase_augmented_cached(struct rb_node *node, struct rb_root_cached *root,
+                         const struct rb_augment_callbacks *augment)
+{
+       struct rb_node *rebalance = __rb_erase_augmented(node, &root->rb_root,
+                                                        &root->rb_leftmost,
+                                                        augment);
+       if (rebalance)
+               __rb_erase_color(rebalance, &root->rb_root, augment->rotate);
+}
+
+#endif /* _TOOLS_LINUX_RBTREE_AUGMENTED_H */
index 9de8780ac8d97568932d3857de3dc2c8e5de2806..7198ddd0c6b11d07286aa60504aedc6a0bea69ed 100644 (file)
@@ -372,7 +372,9 @@ struct perf_event_attr {
                                context_switch :  1, /* context switch data */
                                write_backward :  1, /* Write ring buffer from end to beginning */
                                namespaces     :  1, /* include namespaces data */
-                               __reserved_1   : 35;
+                               ksymbol        :  1, /* include ksymbol events */
+                               bpf_event      :  1, /* include bpf events */
+                               __reserved_1   : 33;
 
        union {
                __u32           wakeup_events;    /* wakeup every n events */
@@ -445,8 +447,6 @@ struct perf_event_query_bpf {
        __u32   ids[0];
 };
 
-#define perf_flags(attr)       (*(&(attr)->read_format + 1))
-
 /*
  * Ioctls that can be done on a perf event fd:
  */
@@ -965,9 +965,58 @@ enum perf_event_type {
         */
        PERF_RECORD_NAMESPACES                  = 16,
 
+       /*
+        * Record ksymbol register/unregister events:
+        *
+        * struct {
+        *      struct perf_event_header        header;
+        *      u64                             addr;
+        *      u32                             len;
+        *      u16                             ksym_type;
+        *      u16                             flags;
+        *      char                            name[];
+        *      struct sample_id                sample_id;
+        * };
+        */
+       PERF_RECORD_KSYMBOL                     = 17,
+
+       /*
+        * Record bpf events:
+        *  enum perf_bpf_event_type {
+        *      PERF_BPF_EVENT_UNKNOWN          = 0,
+        *      PERF_BPF_EVENT_PROG_LOAD        = 1,
+        *      PERF_BPF_EVENT_PROG_UNLOAD      = 2,
+        *  };
+        *
+        * struct {
+        *      struct perf_event_header        header;
+        *      u16                             type;
+        *      u16                             flags;
+        *      u32                             id;
+        *      u8                              tag[BPF_TAG_SIZE];
+        *      struct sample_id                sample_id;
+        * };
+        */
+       PERF_RECORD_BPF_EVENT                   = 18,
+
        PERF_RECORD_MAX,                        /* non-ABI */
 };
 
+enum perf_record_ksymbol_type {
+       PERF_RECORD_KSYMBOL_TYPE_UNKNOWN        = 0,
+       PERF_RECORD_KSYMBOL_TYPE_BPF            = 1,
+       PERF_RECORD_KSYMBOL_TYPE_MAX            /* non-ABI */
+};
+
+#define PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER   (1 << 0)
+
+enum perf_bpf_event_type {
+       PERF_BPF_EVENT_UNKNOWN          = 0,
+       PERF_BPF_EVENT_PROG_LOAD        = 1,
+       PERF_BPF_EVENT_PROG_UNLOAD      = 2,
+       PERF_BPF_EVENT_MAX,             /* non-ABI */
+};
+
 #define PERF_MAX_STACK_DEPTH           127
 #define PERF_MAX_CONTEXTS_PER_STACK      8
 
index 17c2b596f0437f1f32d46441558f6f2329434351..904adb70a4f065acfda1c56b8b0de642796cb222 100644 (file)
@@ -22,6 +22,7 @@
 */
 
 #include <linux/rbtree_augmented.h>
+#include <linux/export.h>
 
 /*
  * red-black trees properties:  http://en.wikipedia.org/wiki/Rbtree
  *  parentheses and have some accompanying text comment.
  */
 
+/*
+ * Notes on lockless lookups:
+ *
+ * All stores to the tree structure (rb_left and rb_right) must be done using
+ * WRITE_ONCE(). And we must not inadvertently cause (temporary) loops in the
+ * tree structure as seen in program order.
+ *
+ * These two requirements will allow lockless iteration of the tree -- not
+ * correct iteration mind you, tree rotations are not atomic so a lookup might
+ * miss entire subtrees.
+ *
+ * But they do guarantee that any such traversal will only see valid elements
+ * and that it will indeed complete -- does not get stuck in a loop.
+ *
+ * It also guarantees that if the lookup returns an element it is the 'correct'
+ * one. But not returning an element does _NOT_ mean it's not present.
+ *
+ * NOTE:
+ *
+ * Stores to __rb_parent_color are not important for simple lookups so those
+ * are left undone as of now. Nor did I check for loops involving parent
+ * pointers.
+ */
+
 static inline void rb_set_black(struct rb_node *rb)
 {
        rb->__rb_parent_color |= RB_BLACK;
@@ -70,22 +95,35 @@ __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new,
 
 static __always_inline void
 __rb_insert(struct rb_node *node, struct rb_root *root,
+           bool newleft, struct rb_node **leftmost,
            void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
 {
        struct rb_node *parent = rb_red_parent(node), *gparent, *tmp;
 
+       if (newleft)
+               *leftmost = node;
+
        while (true) {
                /*
-                * Loop invariant: node is red
-                *
-                * If there is a black parent, we are done.
-                * Otherwise, take some corrective action as we don't
-                * want a red root or two consecutive red nodes.
+                * Loop invariant: node is red.
                 */
-               if (!parent) {
+               if (unlikely(!parent)) {
+                       /*
+                        * The inserted node is root. Either this is the
+                        * first node, or we recursed at Case 1 below and
+                        * are no longer violating 4).
+                        */
                        rb_set_parent_color(node, NULL, RB_BLACK);
                        break;
-               } else if (rb_is_black(parent))
+               }
+
+               /*
+                * If there is a black parent, we are done.
+                * Otherwise, take some corrective action as,
+                * per 4), we don't want a red root or two
+                * consecutive red nodes.
+                */
+               if(rb_is_black(parent))
                        break;
 
                gparent = rb_red_parent(parent);
@@ -94,7 +132,7 @@ __rb_insert(struct rb_node *node, struct rb_root *root,
                if (parent != tmp) {    /* parent == gparent->rb_left */
                        if (tmp && rb_is_red(tmp)) {
                                /*
-                                * Case 1 - color flips
+                                * Case 1 - node's uncle is red (color flips).
                                 *
                                 *       G            g
                                 *      / \          / \
@@ -117,7 +155,8 @@ __rb_insert(struct rb_node *node, struct rb_root *root,
                        tmp = parent->rb_right;
                        if (node == tmp) {
                                /*
-                                * Case 2 - left rotate at parent
+                                * Case 2 - node's uncle is black and node is
+                                * the parent's right child (left rotate at parent).
                                 *
                                 *      G             G
                                 *     / \           / \
@@ -128,8 +167,9 @@ __rb_insert(struct rb_node *node, struct rb_root *root,
                                 * This still leaves us in violation of 4), the
                                 * continuation into Case 3 will fix that.
                                 */
-                               parent->rb_right = tmp = node->rb_left;
-                               node->rb_left = parent;
+                               tmp = node->rb_left;
+                               WRITE_ONCE(parent->rb_right, tmp);
+                               WRITE_ONCE(node->rb_left, parent);
                                if (tmp)
                                        rb_set_parent_color(tmp, parent,
                                                            RB_BLACK);
@@ -140,7 +180,8 @@ __rb_insert(struct rb_node *node, struct rb_root *root,
                        }
 
                        /*
-                        * Case 3 - right rotate at gparent
+                        * Case 3 - node's uncle is black and node is
+                        * the parent's left child (right rotate at gparent).
                         *
                         *        G           P
                         *       / \         / \
@@ -148,8 +189,8 @@ __rb_insert(struct rb_node *node, struct rb_root *root,
                         *     /                 \
                         *    n                   U
                         */
-                       gparent->rb_left = tmp;  /* == parent->rb_right */
-                       parent->rb_right = gparent;
+                       WRITE_ONCE(gparent->rb_left, tmp); /* == parent->rb_right */
+                       WRITE_ONCE(parent->rb_right, gparent);
                        if (tmp)
                                rb_set_parent_color(tmp, gparent, RB_BLACK);
                        __rb_rotate_set_parents(gparent, parent, root, RB_RED);
@@ -170,8 +211,9 @@ __rb_insert(struct rb_node *node, struct rb_root *root,
                        tmp = parent->rb_left;
                        if (node == tmp) {
                                /* Case 2 - right rotate at parent */
-                               parent->rb_left = tmp = node->rb_right;
-                               node->rb_right = parent;
+                               tmp = node->rb_right;
+                               WRITE_ONCE(parent->rb_left, tmp);
+                               WRITE_ONCE(node->rb_right, parent);
                                if (tmp)
                                        rb_set_parent_color(tmp, parent,
                                                            RB_BLACK);
@@ -182,8 +224,8 @@ __rb_insert(struct rb_node *node, struct rb_root *root,
                        }
 
                        /* Case 3 - left rotate at gparent */
-                       gparent->rb_right = tmp;  /* == parent->rb_left */
-                       parent->rb_left = gparent;
+                       WRITE_ONCE(gparent->rb_right, tmp); /* == parent->rb_left */
+                       WRITE_ONCE(parent->rb_left, gparent);
                        if (tmp)
                                rb_set_parent_color(tmp, gparent, RB_BLACK);
                        __rb_rotate_set_parents(gparent, parent, root, RB_RED);
@@ -223,8 +265,9 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
                                 *      / \         / \
                                 *     Sl  Sr      N   Sl
                                 */
-                               parent->rb_right = tmp1 = sibling->rb_left;
-                               sibling->rb_left = parent;
+                               tmp1 = sibling->rb_left;
+                               WRITE_ONCE(parent->rb_right, tmp1);
+                               WRITE_ONCE(sibling->rb_left, parent);
                                rb_set_parent_color(tmp1, parent, RB_BLACK);
                                __rb_rotate_set_parents(parent, sibling, root,
                                                        RB_RED);
@@ -268,15 +311,31 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
                                 *
                                 *   (p)           (p)
                                 *   / \           / \
-                                *  N   S    -->  N   Sl
+                                *  N   S    -->  N   sl
                                 *     / \             \
-                                *    sl  Sr            s
+                                *    sl  Sr            S
                                 *                       \
                                 *                        Sr
+                                *
+                                * Note: p might be red, and then both
+                                * p and sl are red after rotation(which
+                                * breaks property 4). This is fixed in
+                                * Case 4 (in __rb_rotate_set_parents()
+                                *         which set sl the color of p
+                                *         and set p RB_BLACK)
+                                *
+                                *   (p)            (sl)
+                                *   / \            /  \
+                                *  N   sl   -->   P    S
+                                *       \        /      \
+                                *        S      N        Sr
+                                *         \
+                                *          Sr
                                 */
-                               sibling->rb_left = tmp1 = tmp2->rb_right;
-                               tmp2->rb_right = sibling;
-                               parent->rb_right = tmp2;
+                               tmp1 = tmp2->rb_right;
+                               WRITE_ONCE(sibling->rb_left, tmp1);
+                               WRITE_ONCE(tmp2->rb_right, sibling);
+                               WRITE_ONCE(parent->rb_right, tmp2);
                                if (tmp1)
                                        rb_set_parent_color(tmp1, sibling,
                                                            RB_BLACK);
@@ -296,8 +355,9 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
                         *        / \         / \
                         *      (sl) sr      N  (sl)
                         */
-                       parent->rb_right = tmp2 = sibling->rb_left;
-                       sibling->rb_left = parent;
+                       tmp2 = sibling->rb_left;
+                       WRITE_ONCE(parent->rb_right, tmp2);
+                       WRITE_ONCE(sibling->rb_left, parent);
                        rb_set_parent_color(tmp1, sibling, RB_BLACK);
                        if (tmp2)
                                rb_set_parent(tmp2, parent);
@@ -309,8 +369,9 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
                        sibling = parent->rb_left;
                        if (rb_is_red(sibling)) {
                                /* Case 1 - right rotate at parent */
-                               parent->rb_left = tmp1 = sibling->rb_right;
-                               sibling->rb_right = parent;
+                               tmp1 = sibling->rb_right;
+                               WRITE_ONCE(parent->rb_left, tmp1);
+                               WRITE_ONCE(sibling->rb_right, parent);
                                rb_set_parent_color(tmp1, parent, RB_BLACK);
                                __rb_rotate_set_parents(parent, sibling, root,
                                                        RB_RED);
@@ -334,10 +395,11 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
                                        }
                                        break;
                                }
-                               /* Case 3 - right rotate at sibling */
-                               sibling->rb_right = tmp1 = tmp2->rb_left;
-                               tmp2->rb_left = sibling;
-                               parent->rb_left = tmp2;
+                               /* Case 3 - left rotate at sibling */
+                               tmp1 = tmp2->rb_left;
+                               WRITE_ONCE(sibling->rb_right, tmp1);
+                               WRITE_ONCE(tmp2->rb_left, sibling);
+                               WRITE_ONCE(parent->rb_left, tmp2);
                                if (tmp1)
                                        rb_set_parent_color(tmp1, sibling,
                                                            RB_BLACK);
@@ -345,9 +407,10 @@ ____rb_erase_color(struct rb_node *parent, struct rb_root *root,
                                tmp1 = sibling;
                                sibling = tmp2;
                        }
-                       /* Case 4 - left rotate at parent + color flips */
-                       parent->rb_left = tmp2 = sibling->rb_right;
-                       sibling->rb_right = parent;
+                       /* Case 4 - right rotate at parent + color flips */
+                       tmp2 = sibling->rb_right;
+                       WRITE_ONCE(parent->rb_left, tmp2);
+                       WRITE_ONCE(sibling->rb_right, parent);
                        rb_set_parent_color(tmp1, sibling, RB_BLACK);
                        if (tmp2)
                                rb_set_parent(tmp2, parent);
@@ -378,22 +441,41 @@ static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {}
 static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {}
 
 static const struct rb_augment_callbacks dummy_callbacks = {
-       dummy_propagate, dummy_copy, dummy_rotate
+       .propagate = dummy_propagate,
+       .copy = dummy_copy,
+       .rotate = dummy_rotate
 };
 
 void rb_insert_color(struct rb_node *node, struct rb_root *root)
 {
-       __rb_insert(node, root, dummy_rotate);
+       __rb_insert(node, root, false, NULL, dummy_rotate);
 }
 
 void rb_erase(struct rb_node *node, struct rb_root *root)
 {
        struct rb_node *rebalance;
-       rebalance = __rb_erase_augmented(node, root, &dummy_callbacks);
+       rebalance = __rb_erase_augmented(node, root,
+                                        NULL, &dummy_callbacks);
        if (rebalance)
                ____rb_erase_color(rebalance, root, dummy_rotate);
 }
 
+void rb_insert_color_cached(struct rb_node *node,
+                           struct rb_root_cached *root, bool leftmost)
+{
+       __rb_insert(node, &root->rb_root, leftmost,
+                   &root->rb_leftmost, dummy_rotate);
+}
+
+void rb_erase_cached(struct rb_node *node, struct rb_root_cached *root)
+{
+       struct rb_node *rebalance;
+       rebalance = __rb_erase_augmented(node, &root->rb_root,
+                                        &root->rb_leftmost, &dummy_callbacks);
+       if (rebalance)
+               ____rb_erase_color(rebalance, &root->rb_root, dummy_rotate);
+}
+
 /*
  * Augmented rbtree manipulation functions.
  *
@@ -402,9 +484,10 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
  */
 
 void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
+                          bool newleft, struct rb_node **leftmost,
        void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
 {
-       __rb_insert(node, root, augment_rotate);
+       __rb_insert(node, root, newleft, leftmost, augment_rotate);
 }
 
 /*
@@ -498,15 +581,24 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new,
 {
        struct rb_node *parent = rb_parent(victim);
 
+       /* Copy the pointers/colour from the victim to the replacement */
+       *new = *victim;
+
        /* Set the surrounding nodes to point to the replacement */
-       __rb_change_child(victim, new, parent, root);
        if (victim->rb_left)
                rb_set_parent(victim->rb_left, new);
        if (victim->rb_right)
                rb_set_parent(victim->rb_right, new);
+       __rb_change_child(victim, new, parent, root);
+}
 
-       /* Copy the pointers/colour from the victim to the replacement */
-       *new = *victim;
+void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new,
+                           struct rb_root_cached *root)
+{
+       rb_replace_node(victim, new, &root->rb_root);
+
+       if (root->rb_leftmost == victim)
+               root->rb_leftmost = new;
 }
 
 static struct rb_node *rb_left_deepest_node(const struct rb_node *node)
index e5232d567611b36aa5092262c8252f527e543c74..5f392dbb88fc6923266a0b274a1dc64861ec6cf8 100644 (file)
@@ -46,10 +46,10 @@ CFLAGS_builtin-trace.o         += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_
 CFLAGS_builtin-report.o           += -DTIPDIR="BUILD_STR($(tipdir_SQ))"
 CFLAGS_builtin-report.o           += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)"
 
-libperf-y += util/
-libperf-y += arch/
-libperf-y += ui/
-libperf-y += scripts/
-libperf-$(CONFIG_TRACE) += trace/beauty/
+perf-y += util/
+perf-y += arch/
+perf-y += ui/
+perf-y += scripts/
+perf-$(CONFIG_TRACE) += trace/beauty/
 
 gtk-y += ui/gtk/
index 4ac7775fbc114023c57b294f9dcb5539cab31b49..86f3dcc15f8375726f0ed90d333e79e3cfadb669 100644 (file)
@@ -120,6 +120,10 @@ Given a $HOME/.perfconfig like this:
                children = true
                group = true
 
+       [llvm]
+               dump-obj = true
+               clang-opt = -g
+
 You can hide source code of annotate feature setting the config to false with
 
        % perf config annotate.hide_src_code=true
@@ -553,6 +557,33 @@ trace.*::
        trace.show_zeros::
                Do not suppress syscall arguments that are equal to zero.
 
+llvm.*::
+       llvm.clang-path::
+               Path to clang. If omit, search it from $PATH.
+
+       llvm.clang-bpf-cmd-template::
+               Cmdline template. Below lines show its default value. Environment
+               variable is used to pass options.
+               "$CLANG_EXEC -D__KERNEL__ $CLANG_OPTIONS $KERNEL_INC_OPTIONS \
+               -Wno-unused-value -Wno-pointer-sign -working-directory \
+               $WORKING_DIR  -c $CLANG_SOURCE -target bpf -O2 -o -"
+
+       llvm.clang-opt::
+               Options passed to clang.
+
+       llvm.kbuild-dir::
+               kbuild directory. If not set, use /lib/modules/`uname -r`/build.
+               If set to "" deliberately, skip kernel header auto-detector.
+
+       llvm.kbuild-opts::
+               Options passed to 'make' when detecting kernel header options.
+
+       llvm.dump-obj::
+               Enable perf dump BPF object files compiled by LLVM.
+
+       llvm.opts::
+               Options passed to llc.
+
 SEE ALSO
 --------
 linkperf:perf[1]
index d232b13ea7137c493304853426cba67a514383f3..8f0c2be34848f1a382722be4fa2ff25df7bdbace 100644 (file)
@@ -88,6 +88,20 @@ OPTIONS
           If you want to profile write accesses in [0x1000~1008), just set
           'mem:0x1000/8:w'.
 
+        - a BPF source file (ending in .c) or a precompiled object file (ending
+          in .o) selects one or more BPF events.
+          The BPF program can attach to various perf events based on the ELF section
+          names.
+
+          When processing a '.c' file, perf searches an installed LLVM to compile it
+          into an object file first. Optional clang options can be passed via the
+          '--clang-opt' command line option, e.g.:
+
+            perf record --clang-opt "-DLINUX_VERSION_CODE=0x50000" \
+                        -e tests/bpf-script-example.c
+
+          Note: '--clang-opt' must be placed before '--event/-e'.
+
        - a group of events surrounded by a pair of brace ("{event1,event2,...}").
          Each event is separated by commas and the group should be quoted to
          prevent the shell interpretation.  You also need to use --group on
@@ -440,6 +454,11 @@ Use <n> control blocks in asynchronous (Posix AIO) trace writing mode (default:
 Asynchronous mode is supported only when linking Perf tool with libc library
 providing implementation for Posix AIO API.
 
+--affinity=mode::
+Set affinity mask of trace reading thread according to the policy defined by 'mode' value:
+  node - thread affinity mask is set to NUMA node cpu mask of the processed mmap buffer
+  cpu  - thread affinity mask is set to cpu of the processed mmap buffer
+
 --all-kernel::
 Configure all used events to run in kernel space.
 
index 9e4def08d5693683b6646431378d9d31de3b4a8b..2e19fd7ffe35135a94fb55f66ea367171cc3fb2d 100644 (file)
@@ -159,6 +159,12 @@ OPTIONS
        the override, and the result of the above is that only S/W and H/W
        events are displayed with the given fields.
 
+       It's possible tp add/remove fields only for specific event type:
+
+               -Fsw:-cpu,-period
+
+       removes cpu and period from software events.
+
        For the 'wildcard' option if a user selected field is invalid for an
        event type, a message is displayed to the user that the option is
        ignored for that type. For example:
index 631e687be4eb9a09ddb2eb41435f2c640dc2144c..fc6e43262c418f278da07e37688bca39bd21917f 100644 (file)
@@ -210,6 +210,14 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
        may happen, for instance, when a thread gets migrated to a different CPU
        while processing a syscall.
 
+--map-dump::
+       Dump BPF maps setup by events passed via -e, for instance the augmented_raw_syscalls
+       living in tools/perf/examples/bpf/augmented_raw_syscalls.c. For now this
+       dumps just boolean map values and integer keys, in time this will print in hex
+       by default and use BTF when available, as well as use functions to do pretty
+       printing using the existing 'perf trace' syscall arg beautifiers to map integer
+       arguments to strings (pid to comm, syscall id to syscall name, etc).
+
 
 PAGEFAULTS
 ----------
index dfb218feaad92d557046b0cc4cfb6ee0d1057d2a..593ef49b273c12f0d7e6839887c04dd04eeee418 100644 (file)
@@ -43,11 +43,10 @@ struct perf_file_section {
 
 Flags section:
 
-The header is followed by different optional headers, described by the bits set
-in flags. Only headers for which the bit is set are included. Each header
-consists of a perf_file_section located after the initial header.
-The respective perf_file_section points to the data of the additional
-header and defines its size.
+For each of the optional features a perf_file_section it placed after the data
+section if the feature bit is set in the perf_header flags bitset. The
+respective perf_file_section points to the data of the additional header and
+defines its size.
 
 Some headers consist of strings, which are defined like this:
 
@@ -131,7 +130,7 @@ An uint64_t with the total memory in bytes.
 
        HEADER_CMDLINE = 11,
 
-A perf_header_string with the perf command line used to collect the data.
+A perf_header_string_list with the perf arg-vector used to collect the data.
 
        HEADER_EVENT_DESC = 12,
 
index b441c88cafa1f3a18cbb42d82ca90429e1f4d1a9..0f11d5891301ad17cf7b2e3d572464e670abb03f 100644 (file)
@@ -109,6 +109,13 @@ FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS)
 FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
 FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS)
 
+FEATURE_CHECK_LDFLAGS-libunwind-arm = -lunwind -lunwind-arm
+FEATURE_CHECK_LDFLAGS-libunwind-aarch64 = -lunwind -lunwind-aarch64
+FEATURE_CHECK_LDFLAGS-libunwind-x86 = -lunwind -llzma -lunwind-x86
+FEATURE_CHECK_LDFLAGS-libunwind-x86_64 = -lunwind -llzma -lunwind-x86_64
+
+FEATURE_CHECK_LDFLAGS-libcrypto = -lcrypto
+
 ifdef CSINCLUDES
   LIBOPENCSD_CFLAGS := -I$(CSINCLUDES)
 endif
@@ -218,6 +225,8 @@ FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
 FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS)
 FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
 
+FEATURE_CHECK_LDFLAGS-libaio = -lrt
+
 CFLAGS += -fno-omit-frame-pointer
 CFLAGS += -ggdb3
 CFLAGS += -funwind-tables
@@ -386,7 +395,8 @@ ifeq ($(feature-setns), 1)
   $(call detected,CONFIG_SETNS)
 endif
 
-ifndef NO_CORESIGHT
+ifdef CORESIGHT
+  $(call feature_check,libopencsd)
   ifeq ($(feature-libopencsd), 1)
     CFLAGS += -DHAVE_CSTRACE_SUPPORT $(LIBOPENCSD_CFLAGS)
     LDFLAGS += $(LIBOPENCSD_LDFLAGS)
@@ -482,6 +492,7 @@ endif
 ifndef NO_LIBUNWIND
   have_libunwind :=
 
+  $(call feature_check,libunwind-x86)
   ifeq ($(feature-libunwind-x86), 1)
     $(call detected,CONFIG_LIBUNWIND_X86)
     CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT
@@ -490,6 +501,7 @@ ifndef NO_LIBUNWIND
     have_libunwind = 1
   endif
 
+  $(call feature_check,libunwind-aarch64)
   ifeq ($(feature-libunwind-aarch64), 1)
     $(call detected,CONFIG_LIBUNWIND_AARCH64)
     CFLAGS += -DHAVE_LIBUNWIND_AARCH64_SUPPORT
index 0ee6795d82cc58c23d6f46e0e1fd4b6b9cfb013d..01f7555fd93369a60d8abe6bee7198eb1cbd3e12 100644 (file)
@@ -102,7 +102,7 @@ include ../scripts/utilities.mak
 # When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if
 # llvm-config is not in $PATH.
 #
-# Define NO_CORESIGHT if you do not want support for CoreSight trace decoding.
+# Define CORESIGHT if you DO WANT support for CoreSight trace decoding.
 #
 # Define NO_AIO if you do not want support of Posix AIO based trace
 # streaming for record mode. Currently Posix AIO trace streaming is
@@ -344,9 +344,9 @@ endif
 
 export PERL_PATH
 
-LIB_FILE=$(OUTPUT)libperf.a
+LIBPERF_A=$(OUTPUT)libperf.a
 
-PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD)
+PERFLIBS = $(LIBAPI) $(LIBTRACEEVENT) $(LIBSUBCMD)
 ifndef NO_LIBBPF
   PERFLIBS += $(LIBBPF)
 endif
@@ -549,6 +549,8 @@ JEVENTS_IN    := $(OUTPUT)pmu-events/jevents-in.o
 
 PMU_EVENTS_IN := $(OUTPUT)pmu-events/pmu-events-in.o
 
+LIBPERF_IN := $(OUTPUT)libperf-in.o
+
 export JEVENTS
 
 build := -f $(srctree)/tools/build/Makefile.build dir=. obj
@@ -565,9 +567,12 @@ $(JEVENTS): $(JEVENTS_IN)
 $(PMU_EVENTS_IN): $(JEVENTS) FORCE
        $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=pmu-events
 
-$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
+$(LIBPERF_IN): prepare FORCE
+       $(Q)$(MAKE) $(build)=libperf
+
+$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBPERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
        $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
-               $(PERF_IN) $(PMU_EVENTS_IN) $(LIBS) -o $@
+               $(PERF_IN) $(PMU_EVENTS_IN) $(LIBPERF_IN) $(LIBS) -o $@
 
 $(GTK_IN): FORCE
        $(Q)$(MAKE) $(build)=gtk
@@ -683,12 +688,7 @@ endif
 
 $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
 
-LIBPERF_IN := $(OUTPUT)libperf-in.o
-
-$(LIBPERF_IN): prepare FORCE
-       $(Q)$(MAKE) $(build)=libperf
-
-$(LIB_FILE): $(LIBPERF_IN)
+$(LIBPERF_A): $(LIBPERF_IN)
        $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS)
 
 LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 'EXTRA_CFLAGS=$(EXTRA_CFLAGS)' 'LDFLAGS=$(LDFLAGS)'
@@ -863,8 +863,8 @@ ifndef NO_LIBPYTHON
        $(call QUIET_INSTALL, python-scripts) \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
                $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'; \
-               $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
-               $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
+               $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
+               $(INSTALL) scripts/python/*.py -m 644 -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
                $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
 endif
        $(call QUIET_INSTALL, perf_completion-script) \
@@ -910,7 +910,7 @@ python-clean:
        $(python-clean)
 
 clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean fixdep-clean python-clean
-       $(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
+       $(call QUIET_CLEAN, core-objs)  $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
        $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
        $(Q)$(RM) $(OUTPUT).config-detected
        $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents $(OUTPUT)$(LIBJVMTI).so
index d9b6af837c7d392fce6168d9ce5ebe2b9a6b57d5..688818844c1133ec58e34e645d82d53d9a4c98b4 100644 (file)
@@ -1,2 +1,2 @@
-libperf-y += common.o
-libperf-y += $(SRCARCH)/
+perf-y += common.o
+perf-y += $(SRCARCH)/
index 41bf61da476a4ce3150fc0184c84718d807be894..36222e64bbf7d00c5701c4f6fed009da02782cca 100644 (file)
@@ -1,2 +1,2 @@
-libperf-y += util/
-libperf-$(CONFIG_DWARF_UNWIND) += tests/
+perf-y += util/
+perf-$(CONFIG_DWARF_UNWIND) += tests/
index d9ae2733f9ccce4e4e852979e459c85fda37362e..bc8e97380c82677d46b87b577d16c49d2ad08535 100644 (file)
@@ -1,5 +1,5 @@
-libperf-y += regs_load.o
-libperf-y += dwarf-unwind.o
-libperf-y += vectors-page.o
+perf-y += regs_load.o
+perf-y += dwarf-unwind.o
+perf-y += vectors-page.o
 
-libperf-y += arch-tests.o
+perf-y += arch-tests.o
index 9a0242e74cfc3e5b53736977e588ffc8027b347c..2c35e532bc9af76956b6731a8bfd1528dea24a14 100644 (file)
@@ -3,6 +3,7 @@
 #include "perf_regs.h"
 #include "thread.h"
 #include "map.h"
+#include "map_groups.h"
 #include "event.h"
 #include "debug.h"
 #include "tests/tests.h"
index e64c5f216448069f4f184ffbb391963b49be6856..296f0eac5e18ca5f26105c0b55de9e0bdde49fa2 100644 (file)
@@ -1,6 +1,6 @@
-libperf-$(CONFIG_DWARF) += dwarf-regs.o
+perf-$(CONFIG_DWARF) += dwarf-regs.o
 
-libperf-$(CONFIG_LOCAL_LIBUNWIND)    += unwind-libunwind.o
-libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+perf-$(CONFIG_LOCAL_LIBUNWIND)    += unwind-libunwind.o
+perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
 
-libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs-etm.o
+perf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs-etm.o
index 2f595cd73da662be982a71f130f045f734c29fce..911426721170b5fa495e63ef8ec3c03b9c836afd 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <api/fs/fs.h>
+#include <linux/bits.h>
 #include <linux/bitops.h>
 #include <linux/compiler.h>
 #include <linux/coresight-pmu.h>
 #include "../../util/thread_map.h"
 #include "../../util/cs-etm.h"
 
+#include <errno.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 
-#define ENABLE_SINK_MAX        128
-#define CS_BUS_DEVICE_PATH "/bus/coresight/devices/"
-
 struct cs_etm_recording {
        struct auxtrace_record  itr;
        struct perf_pmu         *cs_etm_pmu;
@@ -60,10 +59,48 @@ static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
        return 0;
 }
 
+static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
+                               struct perf_evsel *evsel)
+{
+       char msg[BUFSIZ], path[PATH_MAX], *sink;
+       struct perf_evsel_config_term *term;
+       int ret = -EINVAL;
+       u32 hash;
+
+       if (evsel->attr.config2 & GENMASK(31, 0))
+               return 0;
+
+       list_for_each_entry(term, &evsel->config_terms, list) {
+               if (term->type != PERF_EVSEL__CONFIG_TERM_DRV_CFG)
+                       continue;
+
+               sink = term->val.drv_cfg;
+               snprintf(path, PATH_MAX, "sinks/%s", sink);
+
+               ret = perf_pmu__scan_file(pmu, path, "%x", &hash);
+               if (ret != 1) {
+                       pr_err("failed to set sink \"%s\" on event %s with %d (%s)\n",
+                              sink, perf_evsel__name(evsel), errno,
+                              str_error_r(errno, msg, sizeof(msg)));
+                       return ret;
+               }
+
+               evsel->attr.config2 |= hash;
+               return 0;
+       }
+
+       /*
+        * No sink was provided on the command line - for _now_ treat
+        * this as an error.
+        */
+       return ret;
+}
+
 static int cs_etm_recording_options(struct auxtrace_record *itr,
                                    struct perf_evlist *evlist,
                                    struct record_opts *opts)
 {
+       int ret;
        struct cs_etm_recording *ptr =
                                container_of(itr, struct cs_etm_recording, itr);
        struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
@@ -92,6 +129,10 @@ static int cs_etm_recording_options(struct auxtrace_record *itr,
        if (!cs_etm_evsel)
                return 0;
 
+       ret = cs_etm_set_sink_attr(cs_etm_pmu, cs_etm_evsel);
+       if (ret)
+               return ret;
+
        if (opts->use_clockid) {
                pr_err("Cannot use clockid (-k option) with %s\n",
                       CORESIGHT_ETM_PMU_NAME);
@@ -598,54 +639,3 @@ struct auxtrace_record *cs_etm_record_init(int *err)
 out:
        return NULL;
 }
-
-static FILE *cs_device__open_file(const char *name)
-{
-       struct stat st;
-       char path[PATH_MAX];
-       const char *sysfs;
-
-       sysfs = sysfs__mountpoint();
-       if (!sysfs)
-               return NULL;
-
-       snprintf(path, PATH_MAX,
-                "%s" CS_BUS_DEVICE_PATH "%s", sysfs, name);
-
-       if (stat(path, &st) < 0)
-               return NULL;
-
-       return fopen(path, "w");
-
-}
-
-static int __printf(2, 3) cs_device__print_file(const char *name, const char *fmt, ...)
-{
-       va_list args;
-       FILE *file;
-       int ret = -EINVAL;
-
-       va_start(args, fmt);
-       file = cs_device__open_file(name);
-       if (file) {
-               ret = vfprintf(file, fmt, args);
-               fclose(file);
-       }
-       va_end(args);
-       return ret;
-}
-
-int cs_etm_set_drv_config(struct perf_evsel_config_term *term)
-{
-       int ret;
-       char enable_sink[ENABLE_SINK_MAX];
-
-       snprintf(enable_sink, ENABLE_SINK_MAX, "%s/%s",
-                term->val.drv_cfg, "enable_sink");
-
-       ret = cs_device__print_file(enable_sink, "%d", 1);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
index 1a12e64f51279293dd1f515b84444116d794afbc..a3354bda4fe8e255309dc0ed5df435e80b2dc4c8 100644 (file)
@@ -7,9 +7,6 @@
 #ifndef INCLUDE__PERF_CS_ETM_H__
 #define INCLUDE__PERF_CS_ETM_H__
 
-#include "../../util/evsel.h"
-
 struct auxtrace_record *cs_etm_record_init(int *err);
-int cs_etm_set_drv_config(struct perf_evsel_config_term *term);
 
 #endif
index e047571e60800e34aeb4fc8f141289132ef22387..bbc297a7e2e3517059f9c3b33816deb69074ac20 100644 (file)
@@ -7,8 +7,8 @@
 #include <string.h>
 #include <linux/coresight-pmu.h>
 #include <linux/perf_event.h>
+#include <linux/string.h>
 
-#include "cs-etm.h"
 #include "arm-spe.h"
 #include "../../util/pmu.h"
 
@@ -19,7 +19,6 @@ struct perf_event_attr
        if (!strcmp(pmu->name, CORESIGHT_ETM_PMU_NAME)) {
                /* add ETM default config here */
                pmu->selectable = true;
-               pmu->set_drv_config = cs_etm_set_drv_config;
 #if defined(__aarch64__)
        } else if (strstarts(pmu->name, ARM_SPE_PMU_NAME)) {
                return arm_spe_pmu_default_config(pmu);
index 41bf61da476a4ce3150fc0184c84718d807be894..36222e64bbf7d00c5701c4f6fed009da02782cca 100644 (file)
@@ -1,2 +1,2 @@
-libperf-y += util/
-libperf-$(CONFIG_DWARF_UNWIND) += tests/
+perf-y += util/
+perf-$(CONFIG_DWARF_UNWIND) += tests/
index 883c57ff0c084fb00a5b4dffa6275840f97dc814..41707fea74b3e7c73401644a6b9c195376267446 100644 (file)
@@ -1,4 +1,4 @@
-libperf-y += regs_load.o
-libperf-y += dwarf-unwind.o
+perf-y += regs_load.o
+perf-y += dwarf-unwind.o
 
-libperf-y += arch-tests.o
+perf-y += arch-tests.o
index 5522ce384723ae84abd5e8d42bce33239247a9e8..a6a407fa1b8b9f2cfb95f5c70aef6d1b929bda6b 100644 (file)
@@ -3,6 +3,7 @@
 #include "perf_regs.h"
 #include "thread.h"
 #include "map.h"
+#include "map_groups.h"
 #include "event.h"
 #include "debug.h"
 #include "tests/tests.h"
index 68f8a8eb3ad0459b544ec8283ae738f2a8e5c6ac..3cde540d2fcf3c99be3f936e4efef02a10547a4d 100644 (file)
@@ -1,10 +1,10 @@
-libperf-y += header.o
-libperf-y += sym-handling.o
-libperf-$(CONFIG_DWARF)     += dwarf-regs.o
-libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
-libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+perf-y += header.o
+perf-y += sym-handling.o
+perf-$(CONFIG_DWARF)     += dwarf-regs.o
+perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
+perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
 
-libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
+perf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
                              ../../arm/util/auxtrace.o \
                              ../../arm/util/cs-etm.o \
                              arm-spe.o
index 54afe4a467e7d9a3f505cad40650378bdcd27296..e4e5f33c84d862aaba8e05ded73e0c336d6e90bd 100644 (file)
@@ -1 +1 @@
-libperf-y += util/
+perf-y += util/
index ca623bbf993c6e1c1718b0461bf893c936abfdcd..d0bc205fe49ab1b57e79d8f44e98c7b8a6ee425c 100644 (file)
@@ -1 +1 @@
-libperf-y += header.o
+perf-y += header.o
index db52fa22d3a1d64a6fe62cffd4b34cd9ffe066f9..a7dd46a5b67850223f6b641914575726acf23633 100644 (file)
@@ -1,2 +1,2 @@
-libperf-y += util/
-libperf-y += tests/
+perf-y += util/
+perf-y += tests/
index d827ef384b333be9846854da1838d29714a1b4d2..3526ab0af9f9a1247eb03195f8706fa96d788e5c 100644 (file)
@@ -1,4 +1,4 @@
-libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o
-libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
+perf-$(CONFIG_DWARF_UNWIND) += regs_load.o
+perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 
-libperf-y += arch-tests.o
+perf-y += arch-tests.o
index 5f39efef0856d0294ba817f975dcc56283e0afcc..5c178e4a199593a507825b5900e6e12f65ef7f79 100644 (file)
@@ -3,6 +3,7 @@
 #include "perf_regs.h"
 #include "thread.h"
 #include "map.h"
+#include "map_groups.h"
 #include "event.h"
 #include "debug.h"
 #include "tests/tests.h"
index ba98bd00648809f6d1b1bddf9ade824a59af3e90..7cf0b880309760efcdfd58fa0be5e2c119baf98d 100644 (file)
@@ -1,11 +1,11 @@
-libperf-y += header.o
-libperf-y += sym-handling.o
-libperf-y += kvm-stat.o
-libperf-y += perf_regs.o
-libperf-y += mem-events.o
+perf-y += header.o
+perf-y += sym-handling.o
+perf-y += kvm-stat.o
+perf-y += perf_regs.o
+perf-y += mem-events.o
 
-libperf-$(CONFIG_DWARF) += dwarf-regs.o
-libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
+perf-$(CONFIG_DWARF) += dwarf-regs.o
+perf-$(CONFIG_DWARF) += skip-callchain-idx.o
 
-libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
-libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+perf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
+perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
index 596ad6aedaace816c0f7b37db55ae8ec7b5eef0f..f9db341c47b608eb7d89a290a1c952d98675488a 100644 (file)
@@ -3,6 +3,8 @@
 #include "util/kvm-stat.h"
 #include "util/parse-events.h"
 #include "util/debug.h"
+#include "util/evsel.h"
+#include "util/evlist.h"
 
 #include "book3s_hv_exits.h"
 #include "book3s_hcalls.h"
index 7c6eeb4633fe139e49d9434d5bec4d03849c4712..2918bb16c892f5eaa545506ec476e7d0958a95eb 100644 (file)
@@ -16,6 +16,9 @@
 #include "util/thread.h"
 #include "util/callchain.h"
 #include "util/debug.h"
+#include "util/dso.h"
+#include "util/map.h"
+#include "util/symbol.h"
 
 /*
  * When saving the callchain on Power, the kernel conservatively saves
index 54afe4a467e7d9a3f505cad40650378bdcd27296..e4e5f33c84d862aaba8e05ded73e0c336d6e90bd 100644 (file)
@@ -1 +1 @@
-libperf-y += util/
+perf-y += util/
index 4a233683c6848115f8619253aaa1109a92522f54..22797f043b844378d7889d6243a38b079e7336d1 100644 (file)
@@ -1,9 +1,9 @@
-libperf-y += header.o
-libperf-y += kvm-stat.o
+perf-y += header.o
+perf-y += kvm-stat.o
 
-libperf-$(CONFIG_DWARF) += dwarf-regs.o
-libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+perf-$(CONFIG_DWARF) += dwarf-regs.o
+perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
 
-libperf-y += machine.o
+perf-y += machine.o
 
-libperf-$(CONFIG_AUXTRACE) += auxtrace.o
+perf-$(CONFIG_AUXTRACE) += auxtrace.o
index aaabab5e28300d4120cdbf44c29c7d7b61563603..7e3961a4b292c8f1d217f26fd28f85bfcdd17079 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <errno.h>
 #include "../../util/kvm-stat.h"
+#include "../../util/evsel.h"
 #include <asm/sie.h>
 
 define_exit_reasons_table(sie_exit_reasons, sie_intercept_code);
index 54afe4a467e7d9a3f505cad40650378bdcd27296..e4e5f33c84d862aaba8e05ded73e0c336d6e90bd 100644 (file)
@@ -1 +1 @@
-libperf-y += util/
+perf-y += util/
index 954e287bbb8988c5094f01308f99fa0b7fb58152..e813e618954b001659e6762785295471881d8c2d 100644 (file)
@@ -1 +1 @@
-libperf-$(CONFIG_DWARF) += dwarf-regs.o
+perf-$(CONFIG_DWARF) += dwarf-regs.o
index 54afe4a467e7d9a3f505cad40650378bdcd27296..e4e5f33c84d862aaba8e05ded73e0c336d6e90bd 100644 (file)
@@ -1 +1 @@
-libperf-y += util/
+perf-y += util/
index 954e287bbb8988c5094f01308f99fa0b7fb58152..e813e618954b001659e6762785295471881d8c2d 100644 (file)
@@ -1 +1 @@
-libperf-$(CONFIG_DWARF) += dwarf-regs.o
+perf-$(CONFIG_DWARF) += dwarf-regs.o
index db52fa22d3a1d64a6fe62cffd4b34cd9ffe066f9..a7dd46a5b67850223f6b641914575726acf23633 100644 (file)
@@ -1,2 +1,2 @@
-libperf-y += util/
-libperf-y += tests/
+perf-y += util/
+perf-y += tests/
index 586849ff83a079468abc96294077c28b68a3e0c0..3d83d0c6982dc6a80bef06e225a23b844c2e823e 100644 (file)
@@ -1,8 +1,8 @@
-libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o
-libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
+perf-$(CONFIG_DWARF_UNWIND) += regs_load.o
+perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
 
-libperf-y += arch-tests.o
-libperf-y += rdpmc.o
-libperf-y += perf-time-to-tsc.o
-libperf-$(CONFIG_AUXTRACE) += insn-x86.o
-libperf-$(CONFIG_X86_64) += bp-modify.o
+perf-y += arch-tests.o
+perf-y += rdpmc.o
+perf-y += perf-time-to-tsc.o
+perf-$(CONFIG_AUXTRACE) += insn-x86.o
+perf-$(CONFIG_X86_64) += bp-modify.o
index 7879df34569a0d8b3098226f0c7eeb095a059360..6ad0a1cedb13c3c838a102bd809981e4f115c107 100644 (file)
@@ -3,6 +3,7 @@
 #include "perf_regs.h"
 #include "thread.h"
 #include "map.h"
+#include "map_groups.h"
 #include "event.h"
 #include "debug.h"
 #include "tests/tests.h"
index 844b8f335532e8aecfdde40972f86f0cf830c2c5..7aab0be5fc5ffb8fc09081b2617cbeccae9dfc42 100644 (file)
@@ -1,18 +1,18 @@
-libperf-y += header.o
-libperf-y += tsc.o
-libperf-y += pmu.o
-libperf-y += kvm-stat.o
-libperf-y += perf_regs.o
-libperf-y += group.o
-libperf-y += machine.o
-libperf-y += event.o
+perf-y += header.o
+perf-y += tsc.o
+perf-y += pmu.o
+perf-y += kvm-stat.o
+perf-y += perf_regs.o
+perf-y += group.o
+perf-y += machine.o
+perf-y += event.o
 
-libperf-$(CONFIG_DWARF) += dwarf-regs.o
-libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o
+perf-$(CONFIG_DWARF) += dwarf-regs.o
+perf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o
 
-libperf-$(CONFIG_LOCAL_LIBUNWIND)    += unwind-libunwind.o
-libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+perf-$(CONFIG_LOCAL_LIBUNWIND)    += unwind-libunwind.o
+perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
 
-libperf-$(CONFIG_AUXTRACE) += auxtrace.o
-libperf-$(CONFIG_AUXTRACE) += intel-pt.o
-libperf-$(CONFIG_AUXTRACE) += intel-bts.o
+perf-$(CONFIG_AUXTRACE) += auxtrace.o
+perf-$(CONFIG_AUXTRACE) += intel-pt.o
+perf-$(CONFIG_AUXTRACE) += intel-bts.o
index 081353d7b095c873c23d973732e2c363da9c4835..865a9762f22ef78edfa3dd09c63a3c929b2eae35 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <errno.h>
 #include "../../util/kvm-stat.h"
+#include "../../util/evsel.h"
 #include <asm/svm.h>
 #include <asm/vmx.h>
 #include <asm/kvm.h>
index 54afe4a467e7d9a3f505cad40650378bdcd27296..e4e5f33c84d862aaba8e05ded73e0c336d6e90bd 100644 (file)
@@ -1 +1 @@
-libperf-y += util/
+perf-y += util/
index 954e287bbb8988c5094f01308f99fa0b7fb58152..e813e618954b001659e6762785295471881d8c2d 100644 (file)
@@ -1 +1 @@
-libperf-$(CONFIG_DWARF) += dwarf-regs.o
+perf-$(CONFIG_DWARF) += dwarf-regs.o
index 93d679eaf1f485b1d8c0a0a74137e20136d47a99..67f9d9ffacfbb9cdfe9e56496a7c1c264b700c5f 100644 (file)
@@ -27,6 +27,7 @@
 #include "util/thread.h"
 #include "util/sort.h"
 #include "util/hist.h"
+#include "util/map.h"
 #include "util/session.h"
 #include "util/tool.h"
 #include "util/data.h"
@@ -227,7 +228,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
                 * the DSO?
                 */
                if (al->sym != NULL) {
-                       rb_erase(&al->sym->rb_node,
+                       rb_erase_cached(&al->sym->rb_node,
                                 &al->map->dso->symbols);
                        symbol__delete(al->sym);
                        dso__reset_find_symbol_cache(al->map->dso);
@@ -305,7 +306,7 @@ static void hists__find_annotations(struct hists *hists,
                                    struct perf_evsel *evsel,
                                    struct perf_annotate *ann)
 {
-       struct rb_node *nd = rb_first(&hists->entries), *next;
+       struct rb_node *nd = rb_first_cached(&hists->entries), *next;
        int key = K_RIGHT;
 
        while (nd) {
@@ -440,7 +441,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
        }
 
        if (total_nr_samples == 0) {
-               ui__error("The %s file has no samples!\n", session->data->file.path);
+               ui__error("The %s data has no samples!\n", session->data->path);
                goto out;
        }
 
@@ -577,7 +578,7 @@ int cmd_annotate(int argc, const char **argv)
        if (quiet)
                perf_quiet_option();
 
-       data.file.path = input_name;
+       data.path = input_name;
 
        annotate.session = perf_session__new(&data, false, &annotate.tool);
        if (annotate.session == NULL)
index 115110a4796a1aa60ab8730066aad7df7522fd3a..10457b10e568492813c1b5ccbf832e28f9535dba 100644 (file)
@@ -416,8 +416,8 @@ int cmd_buildid_cache(int argc, const char **argv)
                nsi = nsinfo__new(ns_id);
 
        if (missing_filename) {
-               data.file.path = missing_filename;
-               data.force     = force;
+               data.path  = missing_filename;
+               data.force = force;
 
                session = perf_session__new(&data, false, NULL);
                if (session == NULL)
index 78abbe8d9d5ff0a8c2c396619d1566f2c00def44..f403e19488b5e4c6607ad1c9a5ccd5bfe968bd78 100644 (file)
@@ -52,11 +52,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
 {
        struct perf_session *session;
        struct perf_data data = {
-               .file      = {
-                       .path = input_name,
-               },
-               .mode      = PERF_DATA_MODE_READ,
-               .force     = force,
+               .path  = input_name,
+               .mode  = PERF_DATA_MODE_READ,
+               .force = force,
        };
 
        symbol__elf_init();
index d340d2e42776175811388eefb4fa0376caeacbab..4272763a5e968fe00ff4024ee4504aa8749e8a7f 100644 (file)
@@ -33,6 +33,7 @@
 #include "ui/browsers/hists.h"
 #include "thread.h"
 #include "mem2node.h"
+#include "symbol.h"
 
 struct c2c_hists {
        struct hists            hists;
@@ -1969,7 +1970,7 @@ static void calc_width(struct c2c_hist_entry *c2c_he)
        set_nodestr(c2c_he);
 }
 
-static int filter_cb(struct hist_entry *he)
+static int filter_cb(struct hist_entry *he, void *arg __maybe_unused)
 {
        struct c2c_hist_entry *c2c_he;
 
@@ -1986,7 +1987,7 @@ static int filter_cb(struct hist_entry *he)
        return 0;
 }
 
-static int resort_cl_cb(struct hist_entry *he)
+static int resort_cl_cb(struct hist_entry *he, void *arg __maybe_unused)
 {
        struct c2c_hist_entry *c2c_he;
        struct c2c_hists *c2c_hists;
@@ -2073,7 +2074,7 @@ static int setup_nodes(struct perf_session *session)
 
 #define HAS_HITMS(__h) ((__h)->stats.lcl_hitm || (__h)->stats.rmt_hitm)
 
-static int resort_hitm_cb(struct hist_entry *he)
+static int resort_hitm_cb(struct hist_entry *he, void *arg __maybe_unused)
 {
        struct c2c_hist_entry *c2c_he;
        c2c_he = container_of(he, struct c2c_hist_entry, he);
@@ -2088,14 +2089,14 @@ static int resort_hitm_cb(struct hist_entry *he)
 
 static int hists__iterate_cb(struct hists *hists, hists__resort_cb_t cb)
 {
-       struct rb_node *next = rb_first(&hists->entries);
+       struct rb_node *next = rb_first_cached(&hists->entries);
        int ret = 0;
 
        while (next) {
                struct hist_entry *he;
 
                he = rb_entry(next, struct hist_entry, rb_node);
-               ret = cb(he);
+               ret = cb(he, NULL);
                if (ret)
                        break;
                next = rb_next(&he->rb_node);
@@ -2215,7 +2216,7 @@ static void print_pareto(FILE *out)
        if (WARN_ONCE(ret, "failed to setup sort entries\n"))
                return;
 
-       nd = rb_first(&c2c.hists.hists.entries);
+       nd = rb_first_cached(&c2c.hists.hists.entries);
 
        for (; nd; nd = rb_next(nd)) {
                struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
@@ -2283,7 +2284,7 @@ static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
 static void c2c_browser__update_nr_entries(struct hist_browser *hb)
 {
        u64 nr_entries = 0;
-       struct rb_node *nd = rb_first(&hb->hists->entries);
+       struct rb_node *nd = rb_first_cached(&hb->hists->entries);
 
        while (nd) {
                struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
@@ -2343,7 +2344,7 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)
        struct c2c_cacheline_browser *cl_browser;
        struct hist_browser *browser;
        int key = -1;
-       const char help[] =
+       static const char help[] =
        " ENTER         Toggle callchains (if present) \n"
        " n             Toggle Node details info \n"
        " s             Toggle full length of symbol and source line columns \n"
@@ -2424,7 +2425,7 @@ static int perf_c2c__hists_browse(struct hists *hists)
 {
        struct hist_browser *browser;
        int key = -1;
-       const char help[] =
+       static const char help[] =
        " d             Display cacheline details \n"
        " ENTER         Toggle callchains (if present) \n"
        " q             Quit \n";
@@ -2749,8 +2750,8 @@ static int perf_c2c__report(int argc, const char **argv)
        if (!input_name || !strlen(input_name))
                input_name = "perf.data";
 
-       data.file.path = input_name;
-       data.force     = symbol_conf.force;
+       data.path  = input_name;
+       data.force = symbol_conf.force;
 
        err = setup_display(display);
        if (err)
index 39db2ee32d484703cc4ecc02a6df283cf6d7577b..58fe0e88215c058b920299d552881c54c878f89e 100644 (file)
@@ -429,7 +429,7 @@ get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt)
 
 static void hists__baseline_only(struct hists *hists)
 {
-       struct rb_root *root;
+       struct rb_root_cached *root;
        struct rb_node *next;
 
        if (hists__has(hists, need_collapse))
@@ -437,13 +437,13 @@ static void hists__baseline_only(struct hists *hists)
        else
                root = hists->entries_in;
 
-       next = rb_first(root);
+       next = rb_first_cached(root);
        while (next != NULL) {
                struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in);
 
                next = rb_next(&he->rb_node_in);
                if (!hist_entry__next_pair(he)) {
-                       rb_erase(&he->rb_node_in, root);
+                       rb_erase_cached(&he->rb_node_in, root);
                        hist_entry__delete(he);
                }
        }
@@ -451,7 +451,7 @@ static void hists__baseline_only(struct hists *hists)
 
 static void hists__precompute(struct hists *hists)
 {
-       struct rb_root *root;
+       struct rb_root_cached *root;
        struct rb_node *next;
 
        if (hists__has(hists, need_collapse))
@@ -459,7 +459,7 @@ static void hists__precompute(struct hists *hists)
        else
                root = hists->entries_in;
 
-       next = rb_first(root);
+       next = rb_first_cached(root);
        while (next != NULL) {
                struct hist_entry *he, *pair;
                struct data__file *d;
@@ -708,7 +708,7 @@ static void data__fprintf(void)
 
        data__for_each_file(i, d)
                fprintf(stdout, "#  [%d] %s %s\n",
-                       d->idx, d->data.file.path,
+                       d->idx, d->data.path,
                        !d->idx ? "(Baseline)" : "");
 
        fprintf(stdout, "#\n");
@@ -779,14 +779,14 @@ static int __cmd_diff(void)
        data__for_each_file(i, d) {
                d->session = perf_session__new(&d->data, false, &tool);
                if (!d->session) {
-                       pr_err("Failed to open %s\n", d->data.file.path);
+                       pr_err("Failed to open %s\n", d->data.path);
                        ret = -1;
                        goto out_delete;
                }
 
                ret = perf_session__process_events(d->session);
                if (ret) {
-                       pr_err("Failed to process %s\n", d->data.file.path);
+                       pr_err("Failed to process %s\n", d->data.path);
                        goto out_delete;
                }
 
@@ -1289,9 +1289,9 @@ static int data_init(int argc, const char **argv)
        data__for_each_file(i, d) {
                struct perf_data *data = &d->data;
 
-               data->file.path = use_default ? defaults[i] : argv[i];
-               data->mode      = PERF_DATA_MODE_READ,
-               data->force     = force,
+               data->path  = use_default ? defaults[i] : argv[i];
+               data->mode  = PERF_DATA_MODE_READ,
+               data->force = force,
 
                d->idx  = i;
        }
index e06e822ce6348768ee12ac45d70f39c9d9827a90..6e4f63b0da4a124f3914184a83d724ccedc70bb7 100644 (file)
@@ -23,9 +23,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
        struct perf_session *session;