perf tools changes for v7.2:

- Introduce 'perf inject --aslr' to remap ASLR-randomized
   addresses in perf.data files, enabling reproducible analysis
   across runs with different address space layouts.
 
 - Refactor evsel out of sample processing paths: store evsel in
   struct perf_sample and remove the redundant evsel parameter from
   tool APIs, tracepoint handlers, hist entry iterators, and
   db-export, simplifying the entire tool callback chain.
 
 - Switch architecture detection from string-based perf_env__arch()
   comparisons to the numeric ELF e_machine field across the
   codebase (capstone, print_insn, c2c, lock-contention, sort,
   sample-raw, machine, header), making cross-analysis more robust.
 
 - Overhaul ARM CoreSight ETM tests: add deterministic and
   named_threads workloads, speed up basic and disassembly tests,
   add process attribution and concurrent threads tests, remove
   unused workloads and duplicate tests, queue context packets for
   the frontend decoder.
 
 - Add ARM SPE IMPDEF event decoding for Arm Neoverse N1, store
   MIDR in arm_spe_pkt for per-CPU event mapping, handle missing
   CPU IDs gracefully.
 
 - Refactor libunwind support: remove the libunwind-local backend,
   make register reading cross-platform, add RISC-V libunwind
   support, allow dynamic selection between libdw and libunwind
   unwinding at runtime.
 
 - Extensive hardening of perf.data parsing against crafted files:
   add bounds checks and byte-swap validation for session records,
   feature sections, header attributes, BPF metadata, auxtrace
   errors, compressed events, CPU maps, build ID notes, and ELF
   program headers. Add minimum event size validation and file
   offset diagnostics.
 
 - Fix libdw API contract violations across dwarf-aux, libdw,
   probe-finder, annotate-data, and debuginfo subsystems. Fix
   callchain parent update in ORDER_CALLER mode, support DWARF line
   0 in inline lists, handle multiple address spaces in callchains.
 
 - Fix numerous 'perf sched' bugs: thread reference leaks, memory
   leaks, heap overflows with cross-machine recordings, NULL
   dereferences, replace BUG_ON assertions with graceful error
   handling, bounds-check CPU indices, fix SIGCHLD vs pause() races
   in sched stats.
 
 - Overhaul the build system: move BPF skeleton generation out of
   Makefile.perf into bpf_skel.mak, decouple pmu-events from the
   prepare target, make beauty generated C code standalone .o files,
   compile BPF skeletons with -mcpu=v3, fix continuous rebuilds,
   various cleanups.
 
 - Add 'perf test' JUnit XML reporting with -j/--junit option, split
   monolithic test suites into sub-tests, add summary reporting,
   refactor parallel poll loop, fix test failures on musl-based
   systems.
 
 - Fix 'perf c2c' memory leaks in hist entry and format list
   handling, use-after-free in error paths, bounds-check CPU and
   node IDs.
 
 - Fix 'perf bpf' metadata leaks on duplicate insert and alloc
   failure, bounds-check array offsets, validate event sizes and
   func_info fields, add NULL checks.
 
 - Fix hwmon PMU: off-by-one null termination on sysfs reads,
   strlcpy buffer overflow in parse_hwmon_filename(), fd 0 check,
   empty label reads, scnprintf usage.
 
 - Fix symbols subsystem: bounds-check ELF and sysfs build ID note
   iteration, validate p_filesz, fix 32-bit ELF bswap error, fix
   signed overflow in size checks, bounds-check .gnu_debuglink
   section.
 
 - Fix tools lib api: null termination in filename__read_int/ull(),
   uninitialized stack data in filename__write_int(), snprintf
   truncation in mount_overload().
 
 - Replace libbabeltrace with babeltrace2-ctf-writer for CTF
   conversion in 'perf data'.
 
 - Add RISC-V SDT argument parsing for static tracepoints.
 
 - Add 'perf trace --show-cpu' option to display CPU id.
 
 - Add 'perf bench sched pipe --write-size' option.
 
 - Add a perf-specific .clang-format that overrides some kernel
   style behaviors.
 
 - Update Intel vendor events for Alder Lake, Arrow Lake, Clearwater
   Forest, Emerald Rapids, Granite Rapids, Grand Ridge, Lunar Lake,
   Meteor Lake, Panther Lake, Sapphire Rapids, Sierra Forest.
 
 - Add IOMMU metrics for AMD and Intel.
 
 - Fix AMD event: switch l2_itlb_misses to
   bp_l1_tlb_miss_l2_tlb_miss.all.
 
 - Add AMD IBS improvements: decode Streaming-store and
   Remote-Socket flags, suppress bogus fields on Zen4+, skip
   privilege test on Zen6+.
 
 - Fix 'perf lock contention' SIGCHLD vs pause() race, allow
   'mmap_lock' in -L filter, enable end-timestamp for cgroup
   aggregation, fix non-atomic data updates.
 
 - Fix 'perf stat' false NMI watchdog warning in aggregation modes,
   bounds-check CPU index in topology callbacks, add aggr_nr metric
   parser support for uncore scaling.
 
 - Fix 'perf timechart' memory leaks, CPU bounds checking,
   use-after-free on corrupted callchains.
 
 - Fix 'perf inject' itrace branch stack synthesis, fix synthesized
   sample size with branch stacks.
 
 - Fix DSO heap overflow on decompressed paths, uninitialized
   pathname on fallback, set proper error codes.
 
 - Fix various snprintf/scnprintf usages to prevent buffer overflows
   and truncation across the codebase.
 
 - Fix off-by-one stack buffer overflow in kallsyms__parse().
 
 - Fix 'perf kwork' memory management, address sanitizer issues,
   bounds check work->cpu.
 
 - Fix 'perf tpebs' concurrent stop races and PID reuse hazards.
 
 - Add O_CLOEXEC to open() calls and use mkostemp() for temporary
   files to prevent file descriptor leaks to child processes.
 
 - Fix s390 Python extension TEXTREL by compiling as PIC.
 
 - Fix build with ASAN for jitdump.
 
 - Fix build failure due to btf_vlen() return type change.
 
 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQR2GiIUctdOfX2qHhGyPKLppCJ+JwUCajmIQAAKCRCyPKLppCJ+
 J/8DAQCHYyodbD+Y+zX2kvaed6EStTTTLN4nyteWVb/3b0UZ5AEA4ECHdgpxgAx8
 h6C+n8m8aAC6LyMgSYJwGm92rGgaewM=
 =CPUX
 -----END PGP SIGNATURE-----

Merge tag 'perf-tools-for-v7.2-1-2026-06-22' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools

Pull perf tools updates from Arnaldo Carvalho de Melo:

 - Introduce 'perf inject --aslr' to remap ASLR-randomized addresses in
   perf.data files, enabling reproducible analysis across runs with
   different address space layouts

 - Refactor evsel out of sample processing paths: store evsel in struct
   perf_sample and remove the redundant evsel parameter from tool APIs,
   tracepoint handlers, hist entry iterators, and db-export, simplifying
   the entire tool callback chain

 - Switch architecture detection from string-based perf_env__arch()
   comparisons to the numeric ELF e_machine field across the codebase
   (capstone, print_insn, c2c, lock-contention, sort, sample-raw,
   machine, header), making cross-analysis more robust

 - Overhaul ARM CoreSight ETM tests: add deterministic and named_threads
   workloads, speed up basic and disassembly tests, add process
   attribution and concurrent threads tests, remove unused workloads and
   duplicate tests, queue context packets for the frontend decoder

 - Add ARM SPE IMPDEF event decoding for Arm Neoverse N1, store MIDR in
   arm_spe_pkt for per-CPU event mapping, handle missing CPU IDs
   gracefully

 - Refactor libunwind support: remove the libunwind-local backend, make
   register reading cross-platform, add RISC-V libunwind support, allow
   dynamic selection between libdw and libunwind unwinding at runtime

 - Extensive hardening of perf.data parsing against crafted files: add
   bounds checks and byte-swap validation for session records, feature
   sections, header attributes, BPF metadata, auxtrace errors,
   compressed events, CPU maps, build ID notes, and ELF program headers.
   Add minimum event size validation and file offset diagnostics

 - Fix libdw API contract violations across dwarf-aux, libdw,
   probe-finder, annotate-data, and debuginfo subsystems. Fix callchain
   parent update in ORDER_CALLER mode, support DWARF line 0 in inline
   lists, handle multiple address spaces in callchains

 - Fix numerous 'perf sched' bugs: thread reference leaks, memory leaks,
   heap overflows with cross-machine recordings, NULL dereferences,
   replace BUG_ON assertions with graceful error handling, bounds-check
   CPU indices, fix SIGCHLD vs pause() races in sched stats

 - Overhaul the build system: move BPF skeleton generation out of
   Makefile.perf into bpf_skel.mak, decouple pmu-events from the prepare
   target, make beauty generated C code standalone .o files, compile BPF
   skeletons with -mcpu=v3, fix continuous rebuilds, various cleanups

 - Add 'perf test' JUnit XML reporting with -j/--junit option, split
   monolithic test suites into sub-tests, add summary reporting,
   refactor parallel poll loop, fix test failures on musl-based systems

 - Fix 'perf c2c' memory leaks in hist entry and format list handling,
   use-after-free in error paths, bounds-check CPU and node IDs

 - Fix 'perf bpf' metadata leaks on duplicate insert and alloc failure,
   bounds-check array offsets, validate event sizes and func_info
   fields, add NULL checks

 - Fix hwmon PMU: off-by-one null termination on sysfs reads, strlcpy
   buffer overflow in parse_hwmon_filename(), fd 0 check, empty label
   reads, scnprintf usage

 - Fix symbols subsystem: bounds-check ELF and sysfs build ID note
   iteration, validate p_filesz, fix 32-bit ELF bswap error, fix signed
   overflow in size checks, bounds-check .gnu_debuglink section

 - Fix tools lib api: null termination in filename__read_int/ull(),
   uninitialized stack data in filename__write_int(), snprintf
   truncation in mount_overload()

 - Replace libbabeltrace with babeltrace2-ctf-writer for CTF conversion
   in 'perf data'

 - Add RISC-V SDT argument parsing for static tracepoints

 - Add 'perf trace --show-cpu' option to display CPU id

 - Add 'perf bench sched pipe --write-size' option

 - Add a perf-specific .clang-format that overrides some kernel style
   behaviors

 - Update Intel vendor events for Alder Lake, Arrow Lake, Clearwater
   Forest, Emerald Rapids, Granite Rapids, Grand Ridge, Lunar Lake,
   Meteor Lake, Panther Lake, Sapphire Rapids, Sierra Forest

 - Add IOMMU metrics for AMD and Intel

 - Fix AMD event: switch l2_itlb_misses to
   bp_l1_tlb_miss_l2_tlb_miss.all

 - Add AMD IBS improvements: decode Streaming-store and Remote-Socket
   flags, suppress bogus fields on Zen4+, skip privilege test on Zen6+

 - Fix 'perf lock contention' SIGCHLD vs pause() race, allow 'mmap_lock'
   in -L filter, enable end-timestamp for cgroup aggregation, fix
   non-atomic data updates

 - Fix 'perf stat' false NMI watchdog warning in aggregation modes,
   bounds-check CPU index in topology callbacks, add aggr_nr metric
   parser support for uncore scaling

 - Fix 'perf timechart' memory leaks, CPU bounds checking,
   use-after-free on corrupted callchains

 - Fix 'perf inject' itrace branch stack synthesis, fix synthesized
   sample size with branch stacks

 - Fix DSO heap overflow on decompressed paths, uninitialized pathname
   on fallback, set proper error codes

 - Fix various snprintf/scnprintf usages to prevent buffer overflows and
   truncation across the codebase

 - Fix off-by-one stack buffer overflow in kallsyms__parse()

 - Fix 'perf kwork' memory management, address sanitizer issues, bounds
   check work->cpu

 - Fix 'perf tpebs' concurrent stop races and PID reuse hazards

 - Add O_CLOEXEC to open() calls and use mkostemp() for temporary files
   to prevent file descriptor leaks to child processes

 - Fix s390 Python extension TEXTREL by compiling as PIC

 - Fix build with ASAN for jitdump

 - Fix build failure due to btf_vlen() return type change

* tag 'perf-tools-for-v7.2-1-2026-06-22' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools: (343 commits)
  perf bpf: Fix up build failure due to change of btf_vlen() return type
  perf dso: Set standard errno on decompression failure
  perf bpf: Validate array presence before casting BPF prog info pointers
  perf c2c: Fix hist entry and format list leaks in c2c_he_free()
  perf c2c: Free format list entries when c2c_hists__init() fails
  perf cs-etm: Bounds-check CPU in cs_etm__get_queue()
  perf cs-etm: Require full global header in auxtrace_info size check
  perf cs-etm: Validate num_cpu before metadata allocation
  perf machine: Use snprintf() for guestmount path construction
  perf machine: Propagate machine__init() error to callers
  perf trace: Guard __probe_ip suppression with evsel__is_probe()
  perf evsel: Add lazy-initialized probe type detection helpers
  perf evsel: Add no-libtraceevent stubs for evsel__field() and evsel__common_field()
  perf cs-etm: Reject CPU IDs that would overflow signed comparison
  perf c2c: Free format list entries when releasing c2c hist entries
  perf bpf: Bounds-check array offsets in bpil_offs_to_addr()
  perf bpf: Reject oversized BPF metadata events that truncate header.size
  perf bpf: Validate func_info_rec_size and sub_id in synthesize_bpf_prog_name()
  perf sched: Replace (void*)1 sentinel with proper runtime allocation
  perf hwmon: Fix fd check to accept fd 0 in hwmon_pmu__describe_items()
  ...
This commit is contained in:
Linus Torvalds 2026-06-23 11:34:49 -07:00
commit 05d2a3da15
392 changed files with 36566 additions and 9648 deletions

View File

@ -112,78 +112,6 @@ Example for triggering AUX pause and resume with PMU event::
Perf test - Verify kernel and userspace perf CoreSight work
-----------------------------------------------------------
When you run perf test, it will do a lot of self tests. Some of those
tests will cover CoreSight (only if enabled and on ARM64). You
generally would run perf test from the tools/perf directory in the
kernel tree. Some tests will check some internal perf support like:
There are a set of Perf tests for CoreSight which can be run with::
Check Arm CoreSight trace data recording and synthesized samples
Check Arm SPE trace data recording and synthesized samples
Some others will actually use perf record and some test binaries that
are in tests/shell/coresight and will collect traces to ensure a
minimum level of functionality is met. The scripts that launch these
tests are in the same directory. These will all look like:
CoreSight / ASM Pure Loop
CoreSight / Memcpy 16k 10 Threads
CoreSight / Thread Loop 10 Threads - Check TID
etc.
These perf record tests will not run if the tool binaries do not exist
in tests/shell/coresight/\*/ and will be skipped. If you do not have
CoreSight support in hardware then either do not build perf with
CoreSight support or remove these binaries in order to not have these
tests fail and have them skip instead.
These tests will log historical results in the current working
directory (e.g. tools/perf) and will be named stats-\*.csv like:
stats-asm_pure_loop-out.csv
stats-memcpy_thread-16k_10.csv
...
These statistic files log some aspects of the AUX data sections in
the perf data output counting some numbers of certain encodings (a
good way to know that it's working in a very simple way). One problem
with CoreSight is that given a large enough amount of data needing to
be logged, some of it can be lost due to the processor not waking up
in time to read out all the data from buffers etc.. You will notice
that the amount of data collected can vary a lot per run of perf test.
If you wish to see how this changes over time, simply run perf test
multiple times and all these csv files will have more and more data
appended to it that you can later examine, graph and otherwise use to
figure out if things have become worse or better.
This means sometimes these tests fail as they don't capture all the
data needed. This is about tracking quality and amount of data
produced over time and to see when changes to the Linux kernel improve
quality of traces.
Be aware that some of these tests take quite a while to run, specifically
in processing the perf data file and dumping contents to then examine what
is inside.
You can change where these csv logs are stored by setting the
PERF_TEST_CORESIGHT_STATDIR environment variable before running perf
test like::
export PERF_TEST_CORESIGHT_STATDIR=/var/tmp
perf test
They will also store resulting perf output data in the current
directory for later inspection like::
perf-asm_pure_loop-out.data
perf-memcpy_thread-16k_10.data
...
You can alter where the perf data files are stored by setting the
PERF_TEST_CORESIGHT_DATADIR environment variable such as::
PERF_TEST_CORESIGHT_DATADIR=/var/tmp
perf test
You may wish to set these above environment variables if you wish to
keep the output of tests outside of the current working directory for
longer term storage and examination.
sudo perf test coresight

View File

@ -2817,9 +2817,7 @@ F: tools/perf/arch/arm/util/auxtrace.c
F: tools/perf/arch/arm/util/cs-etm.c
F: tools/perf/arch/arm/util/cs-etm.h
F: tools/perf/arch/arm/util/pmu.c
F: tools/perf/tests/shell/*coresight*
F: tools/perf/tests/shell/coresight/*
F: tools/perf/tests/shell/lib/*coresight*
F: tools/perf/util/cs-etm-decoder/*
F: tools/perf/util/cs-etm.*

View File

@ -99,7 +99,9 @@ union ibs_op_data2 {
rmt_node:1, /* 4: destination node */
cache_hit_st:1, /* 5: cache hit state */
data_src_hi:2, /* 6-7: data source high */
reserved1:56; /* 8-63: reserved */
strm_st:1, /* 8: streaming store */
rmt_socket:1, /* 9: remote socket */
reserved1:54; /* 10-63: reserved */
};
};

View File

@ -104,6 +104,9 @@ FEATURE_TESTS_BASIC := \
# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
# of all feature tests
LIBUNWIND_ARCHS:=aarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x86 x86_64
FEATURE_TESTS_EXTRA := \
bionic \
compile-32 \
@ -113,7 +116,7 @@ FEATURE_TESTS_EXTRA := \
gtk2 \
gtk2-infobar \
hello \
libbabeltrace \
babeltrace2-ctf-writer \
libcapstone \
libcheck \
libbfd-liberty \
@ -127,7 +130,10 @@ FEATURE_TESTS_EXTRA := \
libpfm4 \
libdebuginfod \
clang-bpf-co-re \
bpftool-skeletons
bpftool-skeletons \
libunwind \
libunwind-debug-frame \
$(foreach arch,$(LIBUNWIND_ARCHS),libunwind-$(arch) libunwind-debug-frame-$(arch))
FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
@ -163,6 +169,7 @@ FEATURE_GROUP_MEMBERS-libbfd = libbfd-liberty libbfd-liberty-z
# Declare list of feature dependency packages that provide pkg-config files.
#
FEATURE_PKG_CONFIG ?= \
babeltrace2-ctf-writer \
libtraceevent \
libtracefs
@ -211,7 +218,11 @@ ifeq ($(feature-all), 1)
$(call feature_check,compile-32)
$(call feature_check,compile-x32)
$(call feature_check,bionic)
$(call feature_check,libbabeltrace)
$(call feature_check,babeltrace2-ctf-writer)
$(call feature_check,libunwind)
$(call feature_check,libunwind-debug-frame)
$(foreach arch,$(LIBUNWIND_ARCHS),$(call feature_check,libunwind-$(arch)))
$(foreach arch,$(LIBUNWIND_ARCHS),$(call feature_check,libunwind-debug-frame-$(arch)))
else
$(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat)))
endif

View File

@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
include ../../scripts/Makefile.include
LIBUNWIND_ARCHS:=aarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x86 x86_64
FILES= \
test-all.bin \
test-backtrace.bin \
@ -38,17 +40,12 @@ FILES= \
test-libtracefs.bin \
test-libunwind.bin \
test-libunwind-debug-frame.bin \
test-libunwind-x86.bin \
test-libunwind-x86_64.bin \
test-libunwind-arm.bin \
test-libunwind-aarch64.bin \
test-libunwind-debug-frame-arm.bin \
test-libunwind-debug-frame-aarch64.bin \
$(foreach arch,$(LIBUNWIND_ARCHS),test-libunwind-$(arch).bin test-libunwind-debug-frame-$(arch).bin) \
test-pthread-attr-setaffinity-np.bin \
test-pthread-barrier.bin \
test-stackprotector-all.bin \
test-timerfd.bin \
test-libbabeltrace.bin \
test-babeltrace2-ctf-writer.bin \
test-libcapstone.bin \
test-libcheck.bin \
test-compile-32.bin \
@ -75,7 +72,8 @@ FILES= \
test-file-handle.bin \
test-libpfm4.bin \
test-rust.bin \
test-libopenssl.bin
test-libopenssl.bin \
test-bpftool-skeletons.bin
FILES := $(addprefix $(OUTPUT),$(FILES))
@ -211,27 +209,26 @@ $(OUTPUT)test-numa_num_possible_cpus.bin:
$(BUILD) -lnuma
$(OUTPUT)test-libunwind.bin:
$(BUILD) -lelf -llzma
$(BUILD) -include libunwind.h -lelf -llzma -lunwind
$(OUTPUT)test-libunwind-debug-frame.bin:
$(BUILD) -lelf -llzma
$(OUTPUT)test-libunwind-x86.bin:
$(BUILD) -lelf -llzma -lunwind-x86
$(BUILD) -include libunwind.h -lelf -llzma -lunwind
$(OUTPUT)test-libunwind-x86_64.bin:
$(BUILD) -lelf -llzma -lunwind-x86_64
define LIBUNWIND_RULE
$$(OUTPUT)test-libunwind-$(1).bin:
$$(CC) $$(CFLAGS) -MD -Wall -Werror -include libunwind-$(1).h -o $$@ \
test-libunwind.c $$(LDFLAGS) -lelf -llzma -lunwind-$(1) \
> $$(@:.bin=.make.output) 2>&1
$(OUTPUT)test-libunwind-arm.bin:
$(BUILD) -lelf -llzma -lunwind-arm
$$(OUTPUT)test-libunwind-debug-frame-$(1).bin:
$$(CC) $$(CFLAGS) -MD -Wall -Werror -include libunwind-$(1).h -o $$@ \
test-libunwind-debug-frame.c $$(LDFLAGS) -lelf -llzma -lunwind-$(1) \
> $$(@:.bin=.make.output) 2>&1
$(OUTPUT)test-libunwind-aarch64.bin:
$(BUILD) -lelf -llzma -lunwind-aarch64
$(OUTPUT)test-libunwind-debug-frame-arm.bin:
$(BUILD) -lelf -llzma -lunwind-arm
$(OUTPUT)test-libunwind-debug-frame-aarch64.bin:
$(BUILD) -lelf -llzma -lunwind-aarch64
endef
$(foreach arch,$(LIBUNWIND_ARCHS), \
$(eval $(call LIBUNWIND_RULE,$(arch))) \
)
$(OUTPUT)test-libslang.bin:
$(BUILD) -lslang
@ -308,8 +305,8 @@ $(OUTPUT)test-backtrace.bin:
$(OUTPUT)test-timerfd.bin:
$(BUILD)
$(OUTPUT)test-libbabeltrace.bin:
$(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
$(OUTPUT)test-babeltrace2-ctf-writer.bin:
$(BUILD) # -lbabeltrace2-ctf-writer provided by $(FEATURE_CHECK_LDFLAGS-babeltrace2-ctf-writer)
$(OUTPUT)test-libcapstone.bin:
$(BUILD) # -lcapstone provided by $(FEATURE_CHECK_LDFLAGS-libcapstone)
@ -383,9 +380,9 @@ $(OUTPUT)test-libaio.bin:
$(OUTPUT)test-libzstd.bin:
$(BUILD) -lzstd
$(OUTPUT)test-clang-bpf-co-re.bin:
$(CLANG) -S -g --target=bpf -o - $(patsubst %.bin,%.c,$(@F)) | \
grep BTF_KIND_VAR
$(OUTPUT)test-clang-bpf-co-re.bin: test-clang-bpf-co-re.c
{ $(CLANG) -S -g --target=bpf -o - $< | \
grep BTF_KIND_VAR; } > $(@:.bin=.make.output) 2>&1 && touch $@
$(OUTPUT)test-file-handle.bin:
$(BUILD)
@ -397,8 +394,8 @@ $(OUTPUT)test-libopenssl.bin:
$(BUILD) $(shell $(PKG_CONFIG) --libs --cflags openssl 2>/dev/null)
$(OUTPUT)test-bpftool-skeletons.bin:
$(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons' \
> $(@:.bin=.make.output) 2>&1
{ $(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons'; } \
> $(@:.bin=.make.output) 2>&1 && touch $@
# Testing Rust is special: we don't compile anything, it's enough to check the
# compiler presence. Compiling a test code for this purposes is problematic,

View File

@ -100,13 +100,13 @@
# if 0
/*
* Disable libbabeltrace check for test-all, because the requested
* Disable babeltrace2-ctf-writer check for test-all, because the requested
* library version is not released yet in most distributions. Will
* reenable later.
*/
#define main main_test_libbabeltrace
# include "test-libbabeltrace.c"
#define main main_test_babeltrace2_ctf_writer
# include "test-babeltrace2-ctf-writer.c"
#undef main
#endif

View File

@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include <babeltrace/ctf-writer/writer.h>
#include <babeltrace/ctf-ir/stream-class.h>
#include <babeltrace2-ctf-writer/writer.h>
int main(void)
{

View File

@ -1,27 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-aarch64.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
unw_proc_info_t *pi,
int need_unwind_info, void *arg);
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
static unw_accessors_t accessors;
int main(void)
{
unw_addr_space_t addr_space;
addr_space = unw_create_addr_space(&accessors, 0);
if (addr_space)
return 0;
unw_init_remote(NULL, addr_space, NULL);
dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
return 0;
}

View File

@ -1,28 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-arm.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
unw_proc_info_t *pi,
int need_unwind_info, void *arg);
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
static unw_accessors_t accessors;
int main(void)
{
unw_addr_space_t addr_space;
addr_space = unw_create_addr_space(&accessors, 0);
if (addr_space)
return 0;
unw_init_remote(NULL, addr_space, NULL);
dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
return 0;
}

View File

@ -1,17 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-aarch64.h>
#include <stdlib.h>
extern int
UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
unw_word_t ip, unw_word_t segbase,
const char *obj_name, unw_word_t start,
unw_word_t end);
#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
int main(void)
{
dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
return 0;
}

View File

@ -1,17 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-arm.h>
#include <stdlib.h>
extern int
UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
unw_word_t ip, unw_word_t segbase,
const char *obj_name, unw_word_t start,
unw_word_t end);
#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
int main(void)
{
dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
return 0;
}

View File

@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind.h>
#include <stdlib.h>
extern int

View File

@ -1,28 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-x86.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
unw_proc_info_t *pi,
int need_unwind_info, void *arg);
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
static unw_accessors_t accessors;
int main(void)
{
unw_addr_space_t addr_space;
addr_space = unw_create_addr_space(&accessors, 0);
if (addr_space)
return 0;
unw_init_remote(NULL, addr_space, NULL);
dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
return 0;
}

View File

@ -1,28 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind-x86_64.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
unw_word_t ip,
unw_dyn_info_t *di,
unw_proc_info_t *pi,
int need_unwind_info, void *arg);
#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
static unw_accessors_t accessors;
int main(void)
{
unw_addr_space_t addr_space;
addr_space = unw_create_addr_space(&accessors, 0);
if (addr_space)
return 0;
unw_init_remote(NULL, addr_space, NULL);
dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
return 0;
}

View File

@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
#include <libunwind.h>
#include <stdlib.h>
extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,

View File

@ -261,8 +261,8 @@ static const char *mount_overload(struct fs *fs)
/* "PERF_" + name + "_ENVIRONMENT" + '\0' */
char upper_name[5 + name_len + 12 + 1];
snprintf(upper_name, name_len, "PERF_%s_ENVIRONMENT", fs->name);
mem_toupper(upper_name, name_len);
snprintf(upper_name, sizeof(upper_name), "PERF_%s_ENVIRONMENT", fs->name);
mem_toupper(upper_name, strlen(upper_name));
return getenv(upper_name) ?: *fs->mounts;
}
@ -294,11 +294,14 @@ int filename__read_int(const char *filename, int *value)
{
char line[64];
int fd = open(filename, O_RDONLY), err = -1;
ssize_t n;
if (fd < 0)
return -errno;
if (read(fd, line, sizeof(line)) > 0) {
n = read(fd, line, sizeof(line) - 1);
if (n > 0) {
line[n] = '\0';
*value = atoi(line);
err = 0;
}
@ -312,11 +315,14 @@ static int filename__read_ull_base(const char *filename,
{
char line[64];
int fd = open(filename, O_RDONLY), err = -1;
ssize_t n;
if (fd < 0)
return -errno;
if (read(fd, line, sizeof(line)) > 0) {
n = read(fd, line, sizeof(line) - 1);
if (n > 0) {
line[n] = '\0';
*value = strtoull(line, NULL, base);
if (*value != ULLONG_MAX)
err = 0;
@ -370,12 +376,13 @@ int filename__write_int(const char *filename, int value)
{
int fd = open(filename, O_WRONLY), err = -1;
char buf[64];
int len;
if (fd < 0)
return -errno;
sprintf(buf, "%d", value);
if (write(fd, buf, sizeof(buf)) == sizeof(buf))
len = sprintf(buf, "%d", value);
if (write(fd, buf, len) == len)
err = 0;
close(fd);

30
tools/lib/perf/TODO Normal file
View File

@ -0,0 +1,30 @@
Future ABI changes
==================
This file collects items that require a libperf ABI bump. Each entry
should describe the current limitation, the desired end state, and the
scope of the change so that a future ABI revision can batch them
together.
1. Widen struct perf_cpu.cpu from int16_t to int
- Current limit: 32767 CPUs. No architecture exceeds this today
(x86_64 max is 8192, arm64 is 4096), but NR_CPUS limits keep
growing. perf clamps to INT16_MAX in set_max_cpu_num() as a
safety net.
- Code simplification: the int16_t forces defensive truncation
checks at every boundary where a wider CPU index (int from
sample->cpu, al->cpu, etc.) is narrowed into struct perf_cpu.
Without these checks, values > 32767 silently wrap to negative
numbers (two's complement), bypassing bounds validation.
Widening to int eliminates this entire class of silent
truncation bugs and removes the need for the INT16_MAX clamp
in set_max_cpu_num().
- Scope: struct perf_cpu is embedded everywhere — perf_cpu_map__cpu(),
perf_cpu_map__min(), perf_cpu_map__max(), perf_cpu_map__has(), the
for_each_cpu macros, and all internal callers. The perf_cpu_map
internal array (RC_CHK_ACCESS(map)->map[]) stores struct perf_cpu
directly. Widening changes the struct layout and every function
that returns or accepts struct perf_cpu by value.
- Migration: bump LIBPERF version in libperf.map, audit all
sizeof(struct perf_cpu) assumptions, update perf.data
serialization if needed.

View File

@ -6,7 +6,13 @@
#include <stdbool.h>
#include <stdint.h>
/** A wrapper around a CPU to avoid confusion with the perf_cpu_map's map's indices. */
/**
* struct perf_cpu - wrapper around a CPU number.
* @cpu: CPU number, -1 for the "any CPU"/dummy value.
*
* int16_t limits this to 32767 CPUs. Widening to int requires a libperf
* ABI bump see tools/lib/perf/TODO for the full scope.
*/
struct perf_cpu {
int16_t cpu;
};

View File

@ -8,7 +8,14 @@
#include <linux/bpf.h>
#include <sys/types.h> /* pid_t */
#define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj), mem))
/*
* Verify the full field fits within the event, not just its start offset.
* Only valid for fixed-size scalar fields for trailing arrays like
* filename[PATH_MAX], sizeof() evaluates to the declared maximum, not
* the actual string length, so this would spuriously return false.
*/
#define event_contains(obj, mem) \
((obj).header.size >= offsetof(typeof(obj), mem) + sizeof((obj).mem))
struct perf_record_mmap {
struct perf_event_header header;

View File

@ -169,8 +169,18 @@ int start_command(struct child_process *cmd)
static int wait_or_whine(struct child_process *cmd, bool block)
{
bool finished = cmd->finished;
int result = cmd->finish_result;
bool finished;
int result;
if (cmd->pid <= 0) {
cmd->finished = 1;
if (cmd->pid < 0 && cmd->finish_result == 0)
cmd->finish_result = -ERR_RUN_COMMAND_FORK;
return cmd->finish_result;
}
finished = cmd->finished;
result = cmd->finish_result;
while (!finished) {
int status, code;
@ -233,7 +243,18 @@ int check_if_command_finished(struct child_process *cmd)
char filename[6 + MAX_STRLEN_TYPE(typeof(cmd->pid)) + 7 + 1];
char status_line[256];
FILE *status_file;
#endif
if (cmd->finished)
return 1;
if (cmd->pid <= 0) {
cmd->finished = 1;
if (cmd->pid < 0 && cmd->finish_result == 0)
cmd->finish_result = -ERR_RUN_COMMAND_FORK;
return 1;
}
#ifdef __linux__
/*
* Check by reading /proc/<pid>/status as calling waitpid causes
* stdout/stderr to be closed and data lost.
@ -241,8 +262,48 @@ int check_if_command_finished(struct child_process *cmd)
sprintf(filename, "/proc/%u/status", cmd->pid);
status_file = fopen(filename, "r");
if (status_file == NULL) {
/* Open failed assume finish_command was called. */
return true;
int status;
pid_t waiting;
/*
* fopen() can fail with ENOENT if the process has been reaped.
* It can also fail with EMFILE/ENFILE if RLIMIT_NOFILE is reached.
* In those cases, use waitpid(..., WNOHANG) to robustly check
* and reap the process if it has exited.
*/
if (errno == ENOENT)
return 1;
waiting = waitpid(cmd->pid, &status, WNOHANG);
if (waiting == cmd->pid) {
int result;
int code;
cmd->finished = 1;
if (WIFSIGNALED(status)) {
result = -ERR_RUN_COMMAND_WAITPID_SIGNAL;
} else if (!WIFEXITED(status)) {
result = -ERR_RUN_COMMAND_WAITPID_NOEXIT;
} else {
code = WEXITSTATUS(status);
switch (code) {
case 127:
result = -ERR_RUN_COMMAND_EXEC;
break;
case 0:
result = 0;
break;
default:
result = -code;
break;
}
}
cmd->finish_result = result;
return 1;
}
if (waiting < 0 && (errno == ECHILD || errno == ESRCH))
return 1;
return 0;
}
while (fgets(status_line, sizeof(status_line), status_file) != NULL) {
char *p;

View File

@ -60,7 +60,7 @@ int kallsyms__parse(const char *filename, void *arg,
read_to_eol(&io);
continue;
}
for (i = 0; i < sizeof(symbol_name); i++) {
for (i = 0; i < KSYM_NAME_LEN; i++) {
ch = io__get_char(&io);
if (ch < 0 || ch == '\n')
break;
@ -68,6 +68,9 @@ int kallsyms__parse(const char *filename, void *arg,
}
symbol_name[i] = '\0';
if (i == KSYM_NAME_LEN)
read_to_eol(&io);
err = process_symbol(arg, symbol_name, symbol_type, start);
if (err)
break;

20
tools/perf/.clang-format Normal file
View File

@ -0,0 +1,20 @@
BasedOnStyle: InheritParentConfig
SortIncludes: true
IncludeBlocks: Regroup
IncludeCategories:
# Implicitly the corresponding header for the C file has Priority 0
# C Standard Library Headers
- Regex: '^<(assert|complex|ctype|errno|fenv|float|inttypes|iso646|limits|locale|math|setjmp|signal|stdalign|stdarg|stdatomic|stdbool|stddef|stdint|stdio|stdlib|stdnoreturn|string|tgmath|threads|time|uchar|wchar|wctype)\.h>'
Priority: 1
# OS/System-Specific Headers (directories)
- Regex: '^<(sys|linux|asm|arpa|net|netinet|x86_64|machine)/.*>'
Priority: 2
# OS/System-Specific Headers (POSIX/System flat headers)
- Regex: '^<(unistd|pthread|fcntl|dirent|dlfcn|poll|sched|semaphore|spawn|syslog|termios|pwd|grp|netdb|sysexits|err|paths|pty|utmp|resolv|ifaddrs|elf|libelf|gelf)\.h>'
Priority: 2
# Third-Party Library Headers
- Regex: '^<.*>'
Priority: 3
# Your Project's Other Headers
- Regex: '^".*"'
Priority: 4

View File

@ -38,6 +38,7 @@ arch/*/include/generated/
trace/beauty/generated/
pmu-events/arch/common/common/legacy-cache.json
pmu-events/pmu-events.c
pmu-events/pmu-events-string.c
pmu-events/jevents
pmu-events/metric_test.log
pmu-events/empty-pmu-events.log

View File

@ -34,6 +34,8 @@ ifeq ($(CONFIG_LIBTRACEEVENT),y)
perf-$(CONFIG_TRACE) += trace/beauty/
endif
perf-util-y += trace/beauty/
perf-$(CONFIG_LIBELF) += builtin-probe.o
perf-bench-y += bench/

View File

@ -69,6 +69,14 @@ Per-cpu profile (cpu10), cycles event, sampling period: 100000
# perf record -e ibs_op// -c 100000 -C 10
Userspace only, per-cpu profile (cpu10), cycles event, sampling period: 100000
Zen6 onward (See NOTES):
# perf record -e ibs_op//u -c 100000 -C 10
Until Zen5:
# perf record -e ibs_op/swfilt=1/u -c 100000 -C 10
Per-cpu profile (cpu10), cycles event, sampling freq: 1000
# perf record -e ibs_op// -F 1000 -C 10
@ -94,6 +102,11 @@ onward)
Latency value which is a multiple of 128 incurs a little less profiling
overhead compared to other values.
System-wide profile, cycles event, sampling period: 100000, streaming store
filter (Zen6 onward)
# perf record -e ibs_op/strmst=1/ -c 100000 -a
Per process(upstream v6.2 onward), uOps event, sampling period: 100000
# perf record -e ibs_op/cnt_ctl=1/ -c 100000 -p 1234
@ -150,6 +163,14 @@ System-wide profile, fetch ops event, sampling period: 100000
# perf record -e ibs_fetch// -c 100000 -a
Userspace only, system-wide profile, fetch ops event, sampling period: 100000
Zen6 onward (See NOTES):
# perf record -e ibs_fetch//u -c 100000 -a
Until Zen5:
# perf record -e ibs_fetch/swfilt=1/u -c 100000 -a
System-wide profile, fetch ops event, sampling period: 100000, Random enable
# perf record -e ibs_fetch/rand_en=1/ -c 100000 -a
@ -158,6 +179,15 @@ System-wide profile, fetch ops event, sampling period: 100000, Random enable
helps in cases like long running loops where PMU is tagging the same
instruction over and over because of fixed sample period.
System-wide profile, fetch ops event, sampling period: 10000, fetch latency
filter (Zen6 onward)
# perf record -e ibs_fetch/fetchlat=128/ -c 10000 -a
Supported fetch latency threshold values are 128 to 1920 (both inclusive).
Latency value which is a multiple of 128 incurs a little less profiling
overhead compared to other values.
etc.
PERF MEM AND PERF C2C
@ -216,6 +246,15 @@ sort keys. For example:
Please refer to their man page for more detail.
NOTES
-----
Hardware privilege filtering uses bit 63 to distinguish between kernel
and userspace addresses. Hardware privilege filtering is not supported
on 32-bit systems. Also, the bit 63 convention is not universal and can
fail in specific environments, such as, using 64-bit host IBS to profile
a 32-bit guest, using 64-bit host IBS to profile non-Linux 64-bit guests
that do not adhere to the bit 63 privilege standard etc.
SEE ALSO
--------

View File

@ -55,17 +55,33 @@ OPTIONS
-w::
--workload=::
Run a built-in workload, to list them use '--list-workloads', current ones include:
noploop, thloop, leafloop, sqrtloop, brstack, datasym and landlock.
Run a built-in workload, to list them use '--list-workloads', current
ones include: noploop, thloop, leafloop, sqrtloop, brstack, datasym,
context_switch_loop, deterministic, named_threads and landlock.
Used with the shell script regression tests.
Some accept an extra parameter:
seconds: leafloop, noploop, sqrtloop, thloop
nrloops: brstack
nrloops: brstack, context_switch_loop
The datasym and landlock workloads don't accept any.
'named_threads' accepts the number of threads and the number of loops to
do in each thread.
The datasym, landlock and deterministic workloads don't accept any.
--list-workloads::
List the available workloads to use with -w/--workload.
--record-ctl=fifo:ctl-fifo[,ack-fifo]::
This option is used to communicate with a perf record session in order
to control the recording scope to only the workload and avoid recording
setup and teardown code. When specifying this option, the same FIFO path
must be specified in the record session via:
perf record -D -1 --control=fifo:ctl-fifo[,ack-fifo] ...
Perf test sends 'enable' and 'disable' commands through ctl-fifo to
control event recording. If 'ack-fifo' is provided, the workload runner
waits for an 'ack' response after each command.

View File

@ -199,6 +199,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
--show-on-off-events::
Show the --switch-on/off events too.
--show-cpu::
Show cpu id.
--max-stack::
Set the stack depth limit when parsing the callchain, anything
beyond the specified depth will be ignored. Note that at this point

View File

@ -464,7 +464,21 @@ struct cpu_domain_info {
struct domain_info domains[];
};
other bits are reserved and should ignored for now
HEADER_E_MACHINE = 33,
ELF machine and flags data. e_machine is expanded from 16 to 32 bits
for alignment. Format:
u32 e_machine;
u32 e_flags;
HEADER_CLN_SIZE = 34,
The size of the cacheline in bytes. Format:
unsigned int cln_size;
other bits are reserved and should be ignored for now
HEADER_FEAT_BITS = 256,
Attributes

View File

@ -65,95 +65,85 @@ $(call detected_var,SRCARCH)
CFLAGS += -I$(OUTPUT)arch/$(SRCARCH)/include/generated
# Additional ARCH settings for ppc
ifeq ($(SRCARCH),powerpc)
ifndef NO_LIBUNWIND
LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
endif
endif
# Additional ARCH settings for x86
ifeq ($(SRCARCH),x86)
$(call detected,CONFIG_X86)
ifeq (${IS_64_BIT}, 1)
CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
ifndef NO_LIBUNWIND
LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma
endif
$(call detected,CONFIG_X86_64)
else
ifndef NO_LIBUNWIND
LIBUNWIND_LIBS = -lunwind-x86 -llzma -lunwind
endif
endif
endif
ifeq ($(SRCARCH),arm)
ifndef NO_LIBUNWIND
LIBUNWIND_LIBS = -lunwind -lunwind-arm
endif
endif
ifeq ($(SRCARCH),arm64)
ifndef NO_LIBUNWIND
LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
endif
endif
ifeq ($(SRCARCH),loongarch)
ifndef NO_LIBUNWIND
LIBUNWIND_LIBS = -lunwind -lunwind-loongarch64
endif
endif
ifeq ($(ARCH),s390)
CFLAGS += -fPIC
CXXFLAGS += -fPIC
endif
# Unconditionally set up the libunwind feature build flags as a
# feature-dump build doesn't specify LIBUNWIND=1. This means that
# dumping the libunwind features will be broken that can impact later
# builds that use the feature dump.
ifeq ($(SRCARCH),arm)
LIBUNWIND_LIBS = -lunwind -lunwind-arm
endif
ifeq ($(SRCARCH),arm64)
LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
endif
ifeq ($(SRCARCH),loongarch)
LIBUNWIND_LIBS = -lunwind -lunwind-loongarch64
endif
ifeq ($(ARCH),mips)
ifndef NO_LIBUNWIND
LIBUNWIND_LIBS = -lunwind -lunwind-mips
LIBUNWIND_LIBS = -lunwind -lunwind-mips
endif
ifeq ($(SRCARCH),powerpc)
LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
endif
ifeq ($(SRCARCH),riscv)
LIBUNWIND_LIBS := -lunwind -lunwind-riscv
endif
ifeq ($(SRCARCH),s390)
LIBUNWIND_LIBS := -lunwind -lunwind-s390x
endif
ifeq ($(SRCARCH),x86)
ifeq (${IS_64_BIT}, 1)
LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma
else
LIBUNWIND_LIBS = -lunwind-x86 -lunwind -llzma
endif
endif
ifneq ($(LIBUNWIND),1)
NO_LIBUNWIND := 1
endif
ifeq ($(LIBUNWIND_LIBS),)
NO_LIBUNWIND := 1
endif
#
# For linking with debug library, run like:
#
# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
#
LIBUNWIND_ARCHS:=aarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x86 x86_64
libunwind_arch_set_flags = $(eval $(libunwind_arch_set_flags_code))
define libunwind_arch_set_flags_code
FEATURE_CHECK_CFLAGS-libunwind-$(1) = -I$(LIBUNWIND_DIR)/include
FEATURE_CHECK_LDFLAGS-libunwind-$(1) = -L$(LIBUNWIND_DIR)/lib
endef
# "Local" (no arch specified) feature test flags.
FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
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)
# Add directory into the "remote" (build for a a specific arch) feature tests.
ifdef LIBUNWIND_DIR
LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include
LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib
LIBUNWIND_ARCHS = x86 x86_64 arm aarch64 debug-frame-arm debug-frame-aarch64 loongarch
$(foreach libunwind_arch,$(LIBUNWIND_ARCHS),$(call libunwind_arch_set_flags,$(libunwind_arch)))
endif
ifndef NO_LIBUNWIND
# Set per-feature check compilation flags
FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
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
define libunwind_arch_set_flags
FEATURE_CHECK_CFLAGS-libunwind-$(1) = -I$(LIBUNWIND_DIR)/include
FEATURE_CHECK_LDFLAGS-libunwind-$(1) = -L$(LIBUNWIND_DIR)/lib -lunwind -lunwind-$(1)
endef
$(foreach arch,$(LIBUNWIND_ARCHS), \
$(eval $(call libunwind_arch_set_flags,$(arch))) \
)
endif
ifdef CSINCLUDES
@ -195,14 +185,11 @@ endif
FEATURE_CHECK_CFLAGS-libdw := $(LIBDW_CFLAGS)
FEATURE_CHECK_LDFLAGS-libdw := $(LIBDW_LDFLAGS) $(DWARFLIBS)
# for linking with debug library, run like:
# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
ifdef LIBBABELTRACE_DIR
LIBBABELTRACE_CFLAGS := -I$(LIBBABELTRACE_DIR)/include
LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib
ifneq ($(NO_BABELTRACE2),1)
ifeq ($(call get-executable,$(PKG_CONFIG)),)
$(error Error: $(PKG_CONFIG) needed by babeltrace2 is missing on this system, please install it)
endif
endif
FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
# for linking with debug library, run like:
# make DEBUG=1 LIBCAPSTONE_DIR=/opt/capstone/
@ -587,10 +574,8 @@ ifndef NO_LIBELF
ifndef NO_LIBBPF
ifeq ($(feature-bpf), 1)
# detecting libbpf without LIBBPF_DYNAMIC, so make VF=1 shows libbpf detection status
$(call feature_check,libbpf)
ifdef LIBBPF_DYNAMIC
$(call feature_check,libbpf)
ifeq ($(feature-libbpf), 1)
EXTLIBS += -lbpf
CFLAGS += -DHAVE_LIBBPF_SUPPORT
@ -638,49 +623,6 @@ ifeq ($(SRCARCH),powerpc)
endif
endif
ifndef NO_LIBUNWIND
have_libunwind :=
$(call feature_check,libunwind)
$(call feature_check,libunwind-x86)
ifeq ($(feature-libunwind-x86), 1)
$(call detected,CONFIG_LIBUNWIND_X86)
CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT
LDFLAGS += -lunwind-x86
EXTLIBS_LIBUNWIND += -lunwind-x86
have_libunwind = 1
endif
$(call feature_check,libunwind-aarch64)
ifeq ($(feature-libunwind-aarch64), 1)
$(call detected,CONFIG_LIBUNWIND_AARCH64)
CFLAGS += -DHAVE_LIBUNWIND_AARCH64_SUPPORT
LDFLAGS += -lunwind-aarch64
EXTLIBS_LIBUNWIND += -lunwind-aarch64
have_libunwind = 1
$(call feature_check,libunwind-debug-frame-aarch64)
ifneq ($(feature-libunwind-debug-frame-aarch64), 1)
$(warning No debug_frame support found in libunwind-aarch64)
CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_AARCH64
endif
endif
ifneq ($(feature-libunwind), 1)
$(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR and set LIBUNWIND=1 in the make command line as it is opt-in now)
NO_LOCAL_LIBUNWIND := 1
else
have_libunwind := 1
$(call detected,CONFIG_LOCAL_LIBUNWIND)
endif
ifneq ($(have_libunwind), 1)
NO_LIBUNWIND := 1
endif
else
NO_LOCAL_LIBUNWIND := 1
endif
ifndef NO_LIBBPF
ifneq ($(feature-bpf), 1)
$(warning BPF API too old. Please install recent kernel headers. BPF support in 'perf record' is disabled.)
@ -736,7 +678,61 @@ ifeq ($(BUILD_BPF_SKEL),1)
endif
ifndef GEN_VMLINUX_H
VMLINUX_H=$(src-perf)/util/bpf_skel/vmlinux/vmlinux.h
VMLINUX_H_FILE=$(src-perf)/util/bpf_skel/vmlinux/vmlinux.h
endif
ifndef NO_LIBUNWIND
have_libunwind :=
$(call feature_check,libunwind)
ifneq ($(feature-libunwind), 1)
$(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR and set LIBUNWIND=1 in the make command line as it is opt-in now)
NO_LOCAL_LIBUNWIND := 1
else
have_libunwind := 1
$(call detected,CONFIG_LOCAL_LIBUNWIND)
CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
CFLAGS += $(LIBUNWIND_CFLAGS)
LDFLAGS += $(LIBUNWIND_LDFLAGS)
EXTLIBS_LIBUNWIND := $(LIBUNWIND_LIBS)
$(call feature_check,libunwind-debug-frame)
ifneq ($(feature-libunwind-debug-frame), 1)
CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
endif
endif
define PROCESS_REMOTE_LIBUNWIND_ARCH
$(call feature_check,libunwind-$(1))
ifeq ($$(feature-libunwind-$(1)), 1)
upper_arch := $$(shell echo $(1) | tr '[:lower:]' '[:upper:]')
$$(call detected,CONFIG_LIBUNWIND_$$(upper_arch))
CFLAGS += -DHAVE_LIBUNWIND_$$(upper_arch)_SUPPORT
LDFLAGS += -lunwind-$(1)
EXTLIBS_LIBUNWIND += -lunwind-$(1)
have_libunwind := 1
$$(call feature_check,libunwind-debug-frame-$(1))
ifneq ($$(feature-libunwind-debug-frame-$(1)), 1)
CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_$$(upper_arch)
endif
endif
endef
$(foreach arch,$(LIBUNWIND_ARCHS), \
$(eval $(call PROCESS_REMOTE_LIBUNWIND_ARCH,$(arch))) \
)
EXTLIBS += $(EXTLIBS_LIBUNWIND)
ifeq ($(findstring -static,${LDFLAGS}),-static)
# gcc -static links libgcc_eh which contains piece of libunwind
LIBUNWIND_LDFLAGS += -Wl,--allow-multiple-definition
endif
ifneq ($(have_libunwind), 1)
NO_LIBUNWIND := 1
endif
endif
dwarf-post-unwind := 1
@ -761,31 +757,6 @@ ifeq ($(dwarf-post-unwind),1)
$(call detected,CONFIG_DWARF_UNWIND)
endif
ifndef NO_LIBUNWIND
ifndef NO_LOCAL_LIBUNWIND
ifeq ($(SRCARCH),$(filter $(SRCARCH),arm arm64))
$(call feature_check,libunwind-debug-frame)
ifneq ($(feature-libunwind-debug-frame), 1)
$(warning No debug_frame support found in libunwind)
CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
endif
else
# non-ARM has no dwarf_find_debug_frame() function:
CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
endif
EXTLIBS += $(LIBUNWIND_LIBS)
LDFLAGS += $(LIBUNWIND_LIBS)
endif
ifeq ($(findstring -static,${LDFLAGS}),-static)
# gcc -static links libgcc_eh which contans piece of libunwind
LIBUNWIND_LDFLAGS += -Wl,--allow-multiple-definition
endif
CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
CFLAGS += $(LIBUNWIND_CFLAGS)
LDFLAGS += $(LIBUNWIND_LDFLAGS)
EXTLIBS += $(EXTLIBS_LIBUNWIND)
endif
ifneq ($(NO_LIBTRACEEVENT),1)
$(call detected,CONFIG_TRACE)
endif
@ -923,7 +894,7 @@ ifdef BUILD_NONDISTRO
$(call feature_check,libbfd-liberty-z)
ifneq ($(feature-libbfd-threadsafe), 1)
$(error binutils 2.42 or later is required for non-distro builds)
$(error binutils-dev(el) 2.42 or later is required for non-distro builds)
endif
# we may be on a system that requires -liberty and (maybe) -lz
@ -953,11 +924,14 @@ ifndef NO_LIBLLVM
$(call feature_check,llvm-perf)
ifeq ($(feature-llvm-perf), 1)
CFLAGS += -DHAVE_LIBLLVM_SUPPORT
CFLAGS += $(shell $(LLVM_CONFIG) --cflags)
CXXFLAGS += -DHAVE_LIBLLVM_SUPPORT
CXXFLAGS += $(shell $(LLVM_CONFIG) --cxxflags)
LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) --system-libs)
EXTLIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM)
LLVM_CFLAGS := $(shell $(LLVM_CONFIG) --cflags 2>/dev/null)
LLVM_CXXFLAGS := $(shell $(LLVM_CONFIG) --cxxflags 2>/dev/null)
LLVM_LIBLLVM := $(shell $(LLVM_CONFIG) --libs all 2>/dev/null) $(shell $(LLVM_CONFIG) --system-libs 2>/dev/null)
LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
CFLAGS += $(LLVM_CFLAGS)
CXXFLAGS += -DHAVE_LIBLLVM_SUPPORT $(LLVM_CXXFLAGS)
LIBLLVM := $(LLVM_LIBLLVM)
EXTLIBS += -L$(LLVM_LIBDIR) $(LIBLLVM)
EXTLIBS += -lstdc++
$(call detected,CONFIG_LIBLLVM)
else
@ -1059,15 +1033,15 @@ else
NO_PERF_READ_VDSOX32 := 1
endif
ifndef NO_LIBBABELTRACE
$(call feature_check,libbabeltrace)
ifeq ($(feature-libbabeltrace), 1)
CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
LDFLAGS += $(LIBBABELTRACE_LDFLAGS)
EXTLIBS += -lbabeltrace-ctf
$(call detected,CONFIG_LIBBABELTRACE)
ifndef NO_BABELTRACE2
$(call feature_check,babeltrace2-ctf-writer)
ifeq ($(feature-babeltrace2-ctf-writer), 1)
CFLAGS += -DHAVE_BABELTRACE2_CTF_WRITER_SUPPORT $(shell $(PKG_CONFIG) --cflags babeltrace2-ctf-writer)
LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L babeltrace2-ctf-writer)
EXTLIBS += $(shell $(PKG_CONFIG) --libs-only-l babeltrace2-ctf-writer)
$(call detected,CONFIG_BABELTRACE2_CTF_WRITER)
else
$(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev)
$(warning No babeltrace2 found, disables 'perf data' CTF format support, please install libbabeltrace2-dev[el])
endif
endif

View File

@ -79,7 +79,7 @@ include ../scripts/utilities.mak
#
# Define NO_ZLIB if you do not want to support compressed kernel modules
#
# Define NO_LIBBABELTRACE if you do not want libbabeltrace support
# Define NO_BABELTRACE2 if you do not want babeltrace2-ctf-writer support
# for CTF data format.
#
# Define NO_CAPSTONE if you do not want libcapstone support
@ -274,8 +274,8 @@ ifeq ($(PYLINT),1)
PYLINT := $(shell which pylint 2> /dev/null)
endif
export srctree OUTPUT RM CC CXX RUSTC LD AR CFLAGS CXXFLAGS RUST_FLAGS V BISON FLEX AWK
export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK MYPY PYLINT
export srctree OUTPUT RM CC CXX RUSTC CLANG LD AR CFLAGS CXXFLAGS RUST_FLAGS V BISON FLEX AWK LIBBPF READELF
export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK MYPY PYLINT CONFIG_PERF_BPF_SKEL
include $(srctree)/tools/build/Makefile.include
@ -323,7 +323,7 @@ else
FEATURE_DUMP_EXPORT := $(realpath $(FEATURES_DUMP))
endif
export prefix bindir sharedir sysconfdir DESTDIR
export prefix bindir sharedir sysconfdir DESTDIR VMLINUX_H_FILE
# sparse is architecture-neutral, which means that we need to tell it
# explicitly what architecture to check for. Fix this up for yours..
@ -401,10 +401,14 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf*.so
ifneq ($(quiet),)
python_setup_quiet=--quiet
endif
# Use the detected configuration
-include $(OUTPUT).config-detected
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
SCRIPTS = $(addprefix $(OUTPUT),$(patsubst %.sh,%,$(SCRIPT_SH)))
PROGRAMS += $(OUTPUT)perf
@ -508,242 +512,7 @@ arm64-sysreg-defs-clean:
$(Q)$(MAKE) -C $(arm64_gen_sysreg_dir) O=$(arm64_gen_sysreg_outdir) \
prefix= subdir= clean > /dev/null
beauty_linux_dir := $(srctree)/tools/perf/trace/beauty/include/linux/
beauty_uapi_linux_dir := $(srctree)/tools/perf/trace/beauty/include/uapi/linux/
beauty_uapi_sound_dir := $(srctree)/tools/perf/trace/beauty/include/uapi/sound/
beauty_arch_asm_dir := $(srctree)/tools/perf/trace/beauty/arch/x86/include/asm/
beauty_x86_arch_asm_uapi_dir := $(srctree)/tools/perf/trace/beauty/arch/x86/include/uapi/asm/
linux_uapi_dir := $(srctree)/tools/include/uapi/linux
asm_generic_uapi_dir := $(srctree)/tools/include/uapi/asm-generic
arch_asm_uapi_dir := $(srctree)/tools/arch/$(SRCARCH)/include/uapi/asm/
x86_arch_asm_dir := $(srctree)/tools/arch/x86/include/asm/
beauty_outdir := $(OUTPUT)trace/beauty/generated
beauty_ioctl_outdir := $(beauty_outdir)/ioctl
# Create output directory if not already present
$(shell [ -d '$(beauty_ioctl_outdir)' ] || mkdir -p '$(beauty_ioctl_outdir)')
syscall_array := $(beauty_outdir)/syscalltbl.c
syscall_tbl := $(srctree)/tools/perf/trace/beauty/syscalltbl.sh
syscall_tbl_data := $(srctree)/tools/scripts/syscall.tbl \
$(wildcard $(srctree)/tools/perf/arch/*/entry/syscalls/syscall*.tbl)
$(syscall_array): $(syscall_tbl) $(syscall_tbl_data)
$(Q)$(SHELL) '$(syscall_tbl)' $(srctree)/tools $@
fs_at_flags_array := $(beauty_outdir)/fs_at_flags_array.c
fs_at_flags_tbl := $(srctree)/tools/perf/trace/beauty/fs_at_flags.sh
$(fs_at_flags_array): $(beauty_uapi_linux_dir)/fcntl.h $(fs_at_flags_tbl)
$(Q)$(SHELL) '$(fs_at_flags_tbl)' $(beauty_uapi_linux_dir) > $@
clone_flags_array := $(beauty_outdir)/clone_flags_array.c
clone_flags_tbl := $(srctree)/tools/perf/trace/beauty/clone.sh
$(clone_flags_array): $(beauty_uapi_linux_dir)/sched.h $(clone_flags_tbl)
$(Q)$(SHELL) '$(clone_flags_tbl)' $(beauty_uapi_linux_dir) > $@
drm_ioctl_array := $(beauty_ioctl_outdir)/drm_ioctl_array.c
drm_hdr_dir := $(srctree)/tools/perf/trace/beauty/include/uapi/drm
drm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/drm_ioctl.sh
$(drm_ioctl_array): $(drm_hdr_dir)/drm.h $(drm_hdr_dir)/i915_drm.h $(drm_ioctl_tbl)
$(Q)$(SHELL) '$(drm_ioctl_tbl)' $(drm_hdr_dir) > $@
fadvise_advice_array := $(beauty_outdir)/fadvise_advice_array.c
fadvise_advice_tbl := $(srctree)/tools/perf/trace/beauty/fadvise.sh
$(fadvise_advice_array): $(beauty_uapi_linux_dir)/fadvise.h $(fadvise_advice_tbl)
$(Q)$(SHELL) '$(fadvise_advice_tbl)' $(beauty_uapi_linux_dir) > $@
fsmount_arrays := $(beauty_outdir)/fsmount_arrays.c
fsmount_tbls := $(srctree)/tools/perf/trace/beauty/fsmount.sh
$(fsmount_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsmount_tbls)
$(Q)$(SHELL) '$(fsmount_tbls)' $(beauty_uapi_linux_dir) > $@
fsmount_attr_arrays := $(beauty_outdir)/fsmount_attr_arrays.c
fsmount_attr_tbls := $(srctree)/tools/perf/trace/beauty/fsmount_attr.sh
$(fsmount_attr_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsmount_attr_tbls)
$(Q)$(SHELL) '$(fsmount_attr_tbls)' $(beauty_uapi_linux_dir) > $@
fspick_arrays := $(beauty_outdir)/fspick_arrays.c
fspick_tbls := $(srctree)/tools/perf/trace/beauty/fspick.sh
$(fspick_arrays): $(beauty_uapi_linux_dir)/mount.h $(fspick_tbls)
$(Q)$(SHELL) '$(fspick_tbls)' $(beauty_uapi_linux_dir) > $@
fsconfig_arrays := $(beauty_outdir)/fsconfig_arrays.c
fsconfig_tbls := $(srctree)/tools/perf/trace/beauty/fsconfig.sh
$(fsconfig_arrays): $(beauty_uapi_linux_dir)/mount.h $(fsconfig_tbls)
$(Q)$(SHELL) '$(fsconfig_tbls)' $(beauty_uapi_linux_dir) > $@
pkey_alloc_access_rights_array := $(beauty_outdir)/pkey_alloc_access_rights_array.c
asm_generic_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/
pkey_alloc_access_rights_tbl := $(srctree)/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
$(pkey_alloc_access_rights_array): $(asm_generic_hdr_dir)/mman-common.h $(pkey_alloc_access_rights_tbl)
$(Q)$(SHELL) '$(pkey_alloc_access_rights_tbl)' $(asm_generic_hdr_dir) > $@
sndrv_ctl_ioctl_array := $(beauty_ioctl_outdir)/sndrv_ctl_ioctl_array.c
sndrv_ctl_hdr_dir := $(srctree)/tools/include/uapi/sound
sndrv_ctl_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
$(sndrv_ctl_ioctl_array): $(beauty_uapi_sound_dir)/asound.h $(sndrv_ctl_ioctl_tbl)
$(Q)$(SHELL) '$(sndrv_ctl_ioctl_tbl)' $(beauty_uapi_sound_dir) > $@
sndrv_pcm_ioctl_array := $(beauty_ioctl_outdir)/sndrv_pcm_ioctl_array.c
sndrv_pcm_hdr_dir := $(srctree)/tools/include/uapi/sound
sndrv_pcm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
$(sndrv_pcm_ioctl_array): $(beauty_uapi_sound_dir)/asound.h $(sndrv_pcm_ioctl_tbl)
$(Q)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(beauty_uapi_sound_dir) > $@
kcmp_type_array := $(beauty_outdir)/kcmp_type_array.c
kcmp_hdr_dir := $(srctree)/tools/include/uapi/linux/
kcmp_type_tbl := $(srctree)/tools/perf/trace/beauty/kcmp_type.sh
$(kcmp_type_array): $(kcmp_hdr_dir)/kcmp.h $(kcmp_type_tbl)
$(Q)$(SHELL) '$(kcmp_type_tbl)' $(kcmp_hdr_dir) > $@
kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c
kvm_hdr_dir := $(srctree)/tools/include/uapi/linux
kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh
$(kvm_ioctl_array): $(kvm_hdr_dir)/kvm.h $(kvm_ioctl_tbl)
$(Q)$(SHELL) '$(kvm_ioctl_tbl)' $(kvm_hdr_dir) > $@
socket_arrays := $(beauty_outdir)/socket.c
socket_tbl := $(srctree)/tools/perf/trace/beauty/socket.sh
$(socket_arrays): $(linux_uapi_dir)/in.h $(beauty_linux_dir)/socket.h $(socket_tbl)
$(Q)$(SHELL) '$(socket_tbl)' $(linux_uapi_dir) $(beauty_linux_dir) > $@
sockaddr_arrays := $(beauty_outdir)/sockaddr.c
sockaddr_tbl := $(srctree)/tools/perf/trace/beauty/sockaddr.sh
$(sockaddr_arrays): $(beauty_linux_dir)/socket.h $(sockaddr_tbl)
$(Q)$(SHELL) '$(sockaddr_tbl)' $(beauty_linux_dir) > $@
vhost_virtio_ioctl_array := $(beauty_ioctl_outdir)/vhost_virtio_ioctl_array.c
vhost_virtio_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
$(vhost_virtio_ioctl_array): $(beauty_uapi_linux_dir)/vhost.h $(vhost_virtio_ioctl_tbl)
$(Q)$(SHELL) '$(vhost_virtio_ioctl_tbl)' $(beauty_uapi_linux_dir) > $@
perf_ioctl_array := $(beauty_ioctl_outdir)/perf_ioctl_array.c
perf_hdr_dir := $(srctree)/tools/include/uapi/linux
perf_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/perf_ioctl.sh
$(perf_ioctl_array): $(perf_hdr_dir)/perf_event.h $(perf_ioctl_tbl)
$(Q)$(SHELL) '$(perf_ioctl_tbl)' $(perf_hdr_dir) > $@
madvise_behavior_array := $(beauty_outdir)/madvise_behavior_array.c
madvise_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/
madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh
$(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl)
$(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@
mmap_flags_array := $(beauty_outdir)/mmap_flags_array.c
mmap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mmap_flags.sh
$(mmap_flags_array): $(linux_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(mmap_flags_tbl)
$(Q)$(SHELL) '$(mmap_flags_tbl)' $(linux_uapi_dir) $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@
mremap_flags_array := $(beauty_outdir)/mremap_flags_array.c
mremap_flags_tbl := $(srctree)/tools/perf/trace/beauty/mremap_flags.sh
$(mremap_flags_array): $(linux_uapi_dir)/mman.h $(mremap_flags_tbl)
$(Q)$(SHELL) '$(mremap_flags_tbl)' $(linux_uapi_dir) > $@
mount_flags_array := $(beauty_outdir)/mount_flags_array.c
mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/mount_flags.sh
$(mount_flags_array): $(beauty_uapi_linux_dir)/mount.h $(mount_flags_tbl)
$(Q)$(SHELL) '$(mount_flags_tbl)' $(beauty_uapi_linux_dir) > $@
move_mount_flags_array := $(beauty_outdir)/move_mount_flags_array.c
move_mount_flags_tbl := $(srctree)/tools/perf/trace/beauty/move_mount_flags.sh
$(move_mount_flags_array): $(beauty_uapi_linux_dir)/mount.h $(move_mount_flags_tbl)
$(Q)$(SHELL) '$(move_mount_flags_tbl)' $(beauty_uapi_linux_dir) > $@
mmap_prot_array := $(beauty_outdir)/mmap_prot_array.c
mmap_prot_tbl := $(srctree)/tools/perf/trace/beauty/mmap_prot.sh
$(mmap_prot_array): $(asm_generic_uapi_dir)/mman.h $(asm_generic_uapi_dir)/mman-common.h $(mmap_prot_tbl)
$(Q)$(SHELL) '$(mmap_prot_tbl)' $(asm_generic_uapi_dir) $(arch_asm_uapi_dir) > $@
prctl_option_array := $(beauty_outdir)/prctl_option_array.c
prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh
$(prctl_option_array): $(beauty_uapi_linux_dir)/prctl.h $(prctl_option_tbl)
$(Q)$(SHELL) '$(prctl_option_tbl)' $(beauty_uapi_linux_dir) > $@
usbdevfs_ioctl_array := $(beauty_ioctl_outdir)/usbdevfs_ioctl_array.c
usbdevfs_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/usbdevfs_ioctl.sh
$(usbdevfs_ioctl_array): $(beauty_uapi_linux_dir)/usbdevice_fs.h $(usbdevfs_ioctl_tbl)
$(Q)$(SHELL) '$(usbdevfs_ioctl_tbl)' $(beauty_uapi_linux_dir) > $@
x86_arch_prctl_code_array := $(beauty_outdir)/x86_arch_prctl_code_array.c
x86_arch_prctl_code_tbl := $(srctree)/tools/perf/trace/beauty/x86_arch_prctl.sh
$(x86_arch_prctl_code_array): $(beauty_x86_arch_asm_uapi_dir)/prctl.h $(x86_arch_prctl_code_tbl)
$(Q)$(SHELL) '$(x86_arch_prctl_code_tbl)' $(beauty_x86_arch_asm_uapi_dir) > $@
x86_arch_irq_vectors_array := $(beauty_outdir)/x86_arch_irq_vectors_array.c
x86_arch_irq_vectors_tbl := $(srctree)/tools/perf/trace/beauty/tracepoints/x86_irq_vectors.sh
$(x86_arch_irq_vectors_array): $(beauty_arch_asm_dir)/irq_vectors.h $(x86_arch_irq_vectors_tbl)
$(Q)$(SHELL) '$(x86_arch_irq_vectors_tbl)' $(beauty_arch_asm_dir) > $@
x86_arch_MSRs_array := $(beauty_outdir)/x86_arch_MSRs_array.c
x86_arch_MSRs_tbl := $(srctree)/tools/perf/trace/beauty/tracepoints/x86_msr.sh
$(x86_arch_MSRs_array): $(x86_arch_asm_dir)/msr-index.h $(x86_arch_MSRs_tbl)
$(Q)$(SHELL) '$(x86_arch_MSRs_tbl)' $(x86_arch_asm_dir) > $@
rename_flags_array := $(beauty_outdir)/rename_flags_array.c
rename_flags_tbl := $(srctree)/tools/perf/trace/beauty/rename_flags.sh
$(rename_flags_array): $(beauty_uapi_linux_dir)/fs.h $(rename_flags_tbl)
$(Q)$(SHELL) '$(rename_flags_tbl)' $(beauty_uapi_linux_dir) > $@
arch_errno_name_array := $(beauty_outdir)/arch_errno_name_array.c
arch_errno_hdr_dir := $(srctree)/tools
arch_errno_tbl := $(srctree)/tools/perf/trace/beauty/arch_errno_names.sh
$(arch_errno_name_array): $(arch_errno_tbl)
$(Q)$(SHELL) '$(arch_errno_tbl)' '$(patsubst -%,,$(CC))' $(arch_errno_hdr_dir) > $@
statx_mask_array := $(beauty_outdir)/statx_mask_array.c
statx_mask_tbl := $(srctree)/tools/perf/trace/beauty/statx_mask.sh
$(statx_mask_array): $(beauty_uapi_linux_dir)/stat.h $(statx_mask_tbl)
$(Q)$(SHELL) '$(statx_mask_tbl)' $(beauty_uapi_linux_dir) > $@
sync_file_range_arrays := $(beauty_outdir)/sync_file_range_arrays.c
sync_file_range_tbls := $(srctree)/tools/perf/trace/beauty/sync_file_range.sh
$(sync_file_range_arrays): $(beauty_uapi_linux_dir)/fs.h $(sync_file_range_tbls)
$(Q)$(SHELL) '$(sync_file_range_tbls)' $(beauty_uapi_linux_dir) > $@
TESTS_CORESIGHT_DIR := $(srctree)/tools/perf/tests/shell/coresight
tests-coresight-targets: FORCE
$(Q)$(MAKE) -C $(TESTS_CORESIGHT_DIR)
tests-coresight-targets-clean:
$(call QUIET_CLEAN, coresight)
$(Q)$(MAKE) -C $(TESTS_CORESIGHT_DIR) O=$(OUTPUT) clean >/dev/null
all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) tests-coresight-targets
all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
# Create python binding output directory if not already present
$(shell [ -d '$(OUTPUT)python' ] || mkdir -p '$(OUTPUT)python')
@ -752,7 +521,7 @@ $(OUTPUT)python/perf$(PYTHON_EXTENSION_SUFFIX): util/python.c util/setup.py $(PE
$(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBS_PY)' \
$(PYTHON_WORD) util/setup.py \
--quiet build_ext; \
$(python_setup_quiet) build_ext; \
cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/
python_perf_target:
@ -774,13 +543,15 @@ build := -f $(srctree)/tools/build/Makefile.build dir=. obj
$(PERF_IN): prepare FORCE
$(Q)$(MAKE) $(build)=perf
$(LIBPMU_EVENTS_IN): FORCE prepare
$(LIBPMU_EVENTS_IN): FORCE $(LIBPERF)
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=pmu-events
$(LIBPMU_EVENTS): $(LIBPMU_EVENTS_IN)
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $<
$(LIBPERF_BENCH_IN): FORCE prepare
# The $(LIBPERF_UTIL) dependency is to ensure bpftool and vmlinux.h
# aren't racily built for bench/bpf_skel/bench_uprobe.bpf.c
$(LIBPERF_BENCH_IN): FORCE prepare $(LIBSYMBOL) | $(LIBPERF_UTIL)
$(Q)$(MAKE) $(build)=perf-bench
$(LIBPERF_BENCH): $(LIBPERF_BENCH_IN)
@ -798,7 +569,7 @@ $(LIBPERF_UI_IN): FORCE prepare
$(LIBPERF_UI): $(LIBPERF_UI_IN)
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $<
$(LIBPERF_UTIL_IN): FORCE prepare
$(LIBPERF_UTIL_IN): FORCE prepare $(LIBSYMBOL)
$(Q)$(MAKE) $(build)=perf-util
$(LIBPERF_UTIL): $(LIBPERF_UTIL_IN)
@ -814,8 +585,8 @@ $(GTK_IN): FORCE prepare
$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS)
$(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
$(SCRIPTS) : % : %.sh
$(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
$(SCRIPTS) : $(OUTPUT)% : %.sh
$(QUIET_GEN)$(INSTALL) '$<' '$@'
$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
$(Q)$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
@ -851,46 +622,15 @@ endif
__build-dir = $(subst $(OUTPUT),,$(dir $@))
build-dir = $(or $(__build-dir),.)
prepare: $(OUTPUT)PERF-VERSION-FILE archheaders \
bpf-skel-prepare:
$(Q)$(MAKE) -f bpf_skel.mak bpf-skel-prepare
prepare: $(OUTPUT)PERF-VERSION-FILE \
arm64-sysreg-defs \
$(syscall_array) \
$(fs_at_flags_array) \
$(clone_flags_array) \
$(drm_ioctl_array) \
$(fadvise_advice_array) \
$(fsconfig_arrays) \
$(fsmount_arrays) \
$(fsmount_attr_arrays) \
$(fspick_arrays) \
$(pkey_alloc_access_rights_array) \
$(sndrv_pcm_ioctl_array) \
$(sndrv_ctl_ioctl_array) \
$(kcmp_type_array) \
$(kvm_ioctl_array) \
$(socket_arrays) \
$(sockaddr_arrays) \
$(vhost_virtio_ioctl_array) \
$(madvise_behavior_array) \
$(mmap_flags_array) \
$(mmap_prot_array) \
$(mremap_flags_array) \
$(mount_flags_array) \
$(move_mount_flags_array) \
$(perf_ioctl_array) \
$(prctl_option_array) \
$(usbdevfs_ioctl_array) \
$(x86_arch_irq_vectors_array) \
$(x86_arch_MSRs_array) \
$(x86_arch_prctl_code_array) \
$(rename_flags_array) \
$(arch_errno_name_array) \
$(statx_mask_array) \
$(sync_file_range_arrays) \
bpf-skel-prepare \
$(LIBAPI) \
$(LIBPERF) \
$(LIBSUBCMD) \
$(LIBSYMBOL) \
bpf-skel
$(LIBSUBCMD)
ifdef LIBBPF_STATIC
prepare: $(LIBBPF)
@ -1151,14 +891,13 @@ install-tests: all install-gtk
$(INSTALL) tests/shell/base_report/*.txt '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/base_report'; \
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/coresight' ; \
$(INSTALL) tests/shell/coresight/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/coresight'
$(Q)$(MAKE) -C tests/shell/coresight install-tests
install-bin: install-tools install-tests
install: install-bin try-install-man
install-python_ext:
$(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
$(PYTHON_WORD) util/setup.py $(python_setup_quiet) install --root='/$(DESTDIR_SQ)'
# 'make install-doc' should call 'make -C Documentation install'
$(INSTALL_DOC_TARGETS):
@ -1169,114 +908,16 @@ $(INSTALL_DOC_TARGETS):
python-clean:
$(python-clean)
SKEL_OUT := $(abspath $(OUTPUT)util/bpf_skel)
SKEL_TMP_OUT := $(abspath $(SKEL_OUT)/.tmp)
SKELETONS := $(SKEL_OUT)/bpf_prog_profiler.skel.h
SKELETONS += $(SKEL_OUT)/bperf_leader.skel.h $(SKEL_OUT)/bperf_follower.skel.h
SKELETONS += $(SKEL_OUT)/bperf_cgroup.skel.h $(SKEL_OUT)/func_latency.skel.h
SKELETONS += $(SKEL_OUT)/off_cpu.skel.h $(SKEL_OUT)/lock_contention.skel.h
SKELETONS += $(SKEL_OUT)/kwork_trace.skel.h $(SKEL_OUT)/sample_filter.skel.h
SKELETONS += $(SKEL_OUT)/kwork_top.skel.h $(SKEL_OUT)/syscall_summary.skel.h
SKELETONS += $(SKEL_OUT)/bench_uprobe.skel.h
SKELETONS += $(SKEL_OUT)/augmented_raw_syscalls.skel.h
$(SKEL_TMP_OUT) $(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_OUTPUT) $(LIBSYMBOL_OUTPUT):
$(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_OUTPUT) $(LIBSYMBOL_OUTPUT):
$(Q)$(MKDIR) -p $@
ifeq ($(CONFIG_PERF_BPF_SKEL),y)
BPFTOOL := $(SKEL_TMP_OUT)/bootstrap/bpftool
# Get Clang's default includes on this system, as opposed to those seen by
# '--target=bpf'. This fixes "missing" files on some architectures/distros,
# such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc.
#
# Use '-idirafter': Don't interfere with include mechanics except where the
# build would have failed anyways.
define get_sys_includes
$(shell $(1) $(2) -v -E - </dev/null 2>&1 \
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \
$(shell $(1) $(2) -dM -E - </dev/null | grep '__riscv_xlen ' | awk '{printf("-D__riscv_xlen=%d -D__BITS_PER_LONG=%d", $$3, $$3)}')
endef
ifneq ($(CROSS_COMPILE),)
CLANG_TARGET_ARCH = --target=$(notdir $(CROSS_COMPILE:%-=%))
endif
CLANG_OPTIONS = -Wall
CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH))
BPF_INCLUDE := -I$(SKEL_TMP_OUT)/.. -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES)
TOOLS_UAPI_INCLUDE := -I$(srctree)/tools/include/uapi
ifneq ($(WERROR),0)
CLANG_OPTIONS += -Werror
endif
$(BPFTOOL): | $(SKEL_TMP_OUT)
$(Q)CFLAGS= $(MAKE) -C ../bpf/bpftool \
OUTPUT=$(SKEL_TMP_OUT)/ bootstrap
# Paths to search for a kernel to generate vmlinux.h from.
VMLINUX_BTF_ELF_PATHS ?= $(if $(O),$(O)/vmlinux) \
$(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \
../../vmlinux \
/boot/vmlinux-$(shell uname -r)
# Paths to BTF information.
VMLINUX_BTF_BTF_PATHS ?= /sys/kernel/btf/vmlinux
# Filter out kernels that don't exist or without a BTF section.
VMLINUX_BTF_ELF_ABSPATHS ?= $(abspath $(wildcard $(VMLINUX_BTF_ELF_PATHS)))
VMLINUX_BTF_PATHS ?= $(shell for file in $(VMLINUX_BTF_ELF_ABSPATHS); \
do \
if [ -f $$file ] && ($(READELF) -S "$$file" | grep -q .BTF); \
then \
echo "$$file"; \
fi; \
done) \
$(wildcard $(VMLINUX_BTF_BTF_PATHS))
# Select the first as the source of vmlinux.h.
VMLINUX_BTF ?= $(firstword $(VMLINUX_BTF_PATHS))
ifeq ($(VMLINUX_H),)
ifeq ($(VMLINUX_BTF),)
$(error Missing bpftool input for generating vmlinux.h)
endif
endif
$(SKEL_OUT)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) $(VMLINUX_H)
ifeq ($(VMLINUX_H),)
$(QUIET_GEN)$(BPFTOOL) btf dump file $< format c > $@
else
$(Q)cp "$(VMLINUX_H)" $@
endif
$(SKEL_TMP_OUT)/%.bpf.o: $(OUTPUT)PERF-VERSION-FILE util/bpf_skel/perf_version.h | $(SKEL_TMP_OUT)
$(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF) $(SKEL_OUT)/vmlinux.h
$(QUIET_CLANG)$(CLANG) -g -O2 -fno-stack-protector --target=bpf \
$(CLANG_OPTIONS) $(EXTRA_BPF_FLAGS) $(BPF_INCLUDE) $(TOOLS_UAPI_INCLUDE) \
-include $(OUTPUT)PERF-VERSION-FILE -include util/bpf_skel/perf_version.h \
-c $(filter util/bpf_skel/%.bpf.c,$^) -o $@
$(SKEL_OUT)/%.skel.h: $(SKEL_TMP_OUT)/%.bpf.o | $(BPFTOOL)
$(QUIET_GENSKEL)$(BPFTOOL) gen skeleton $< > $@
bpf-skel: $(SKELETONS)
.PRECIOUS: $(SKEL_TMP_OUT)/%.bpf.o
else # CONFIG_PERF_BPF_SKEL
bpf-skel:
endif # CONFIG_PERF_BPF_SKEL
bpf-skel-clean:
$(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TMP_OUT) $(SKELETONS) $(SKEL_OUT)/vmlinux.h
$(Q)$(MAKE) -f bpf_skel.mak clean
pmu-events-clean:
ifeq ($(OUTPUT),)
$(call QUIET_CLEAN, pmu-events) $(RM) \
pmu-events/pmu-events.c \
pmu-events/pmu-events*.c \
pmu-events/metric_test.log \
pmu-events/test-empty-pmu-events.c \
pmu-events/empty-pmu-events.log
@ -1284,7 +925,7 @@ ifeq ($(OUTPUT),)
-name 'extra-metricgroups.json' -delete
else # When an OUTPUT directory is present, clean up the copied pmu-events/arch directory.
$(call QUIET_CLEAN, pmu-events) $(RM) -r $(OUTPUT)pmu-events/arch \
$(OUTPUT)pmu-events/pmu-events.c \
$(OUTPUT)pmu-events/pmu-events*.c \
$(OUTPUT)pmu-events/metric_test.log \
$(OUTPUT)pmu-events/test-empty-pmu-events.c \
$(OUTPUT)pmu-events/empty-pmu-events.log
@ -1292,7 +933,7 @@ endif
clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(LIBPERF)-clean \
arm64-sysreg-defs-clean fixdep-clean python-clean bpf-skel-clean \
tests-coresight-targets-clean pmu-events-clean
pmu-events-clean
$(call QUIET_CLEAN, core-objs) $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive \
$(OUTPUT)perf-iostat $(LANG_BINDINGS)
$(Q)find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '*.a' -delete -o \
@ -1304,36 +945,8 @@ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(
TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE \
$(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
$(OUTPUT)util/intel-pt-decoder/inat-tables.c \
$(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
$(OUTPUT)$(fadvise_advice_array) \
$(OUTPUT)$(fsconfig_arrays) \
$(OUTPUT)$(fsmount_arrays) \
$(OUTPUT)$(fsmount_attr_arrays) \
$(OUTPUT)$(fspick_arrays) \
$(OUTPUT)$(madvise_behavior_array) \
$(OUTPUT)$(mmap_flags_array) \
$(OUTPUT)$(mmap_prot_array) \
$(OUTPUT)$(mremap_flags_array) \
$(OUTPUT)$(mount_flags_array) \
$(OUTPUT)$(move_mount_flags_array) \
$(OUTPUT)$(drm_ioctl_array) \
$(OUTPUT)$(pkey_alloc_access_rights_array) \
$(OUTPUT)$(sndrv_ctl_ioctl_array) \
$(OUTPUT)$(sndrv_pcm_ioctl_array) \
$(OUTPUT)$(kvm_ioctl_array) \
$(OUTPUT)$(kcmp_type_array) \
$(OUTPUT)$(socket_arrays) \
$(OUTPUT)$(sockaddr_arrays) \
$(OUTPUT)$(vhost_virtio_ioctl_array) \
$(OUTPUT)$(perf_ioctl_array) \
$(OUTPUT)$(prctl_option_array) \
$(OUTPUT)$(usbdevfs_ioctl_array) \
$(OUTPUT)$(x86_arch_irq_vectors_array) \
$(OUTPUT)$(x86_arch_MSRs_array) \
$(OUTPUT)$(x86_arch_prctl_code_array) \
$(OUTPUT)$(rename_flags_array) \
$(OUTPUT)$(arch_errno_name_array) \
$(OUTPUT)$(sync_file_range_arrays)
$(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c
$(Q)$(RM) -r $(OUTPUT)trace/beauty/generated
$(call QUIET_CLEAN, Documentation) \
$(MAKE) -C $(DOC_DIR) O=$(OUTPUT) clean >/dev/null
@ -1353,8 +966,8 @@ FORCE:
.PHONY: all install clean config-clean strip install-gtk
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope FORCE prepare
.PHONY: archheaders python_perf_target
.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope FORCE prepare bpf-skel-prepare
.PHONY: python_perf_target
endif # force_fixdep

View File

@ -1,3 +1 @@
perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
perf-util-y += pmu.o auxtrace.o cs-etm.o

View File

@ -3,10 +3,13 @@
* Copyright(C) 2015 Linaro Limited. All rights reserved.
* Author: Mathieu Poirier <mathieu.poirier@linaro.org>
*/
#include "../../../util/cs-etm.h"
#include <errno.h>
#include <stdlib.h>
#include <api/fs/fs.h>
#include <linux/bits.h>
#include <linux/bitops.h>
#include <linux/bits.h>
#include <linux/compiler.h>
#include <linux/coresight-pmu.h>
#include <linux/kernel.h>
@ -14,25 +17,24 @@
#include <linux/string.h>
#include <linux/types.h>
#include <linux/zalloc.h>
#include <sys/stat.h>
#include <api/fs/fs.h>
#include <internal/lib.h> // page_size
#include "cs-etm.h"
#include "../../../util/debug.h"
#include "../../../util/record.h"
#include "../../../util/auxtrace.h"
#include "../../../util/cpumap.h"
#include "../../../util/debug.h"
#include "../../../util/event.h"
#include "../../../util/evlist.h"
#include "../../../util/evsel.h"
#include "../../../util/perf_api_probe.h"
#include "../../../util/evsel_config.h"
#include "../../../util/perf_api_probe.h"
#include "../../../util/pmu.h"
#include "../../../util/pmus.h"
#include "../../../util/cs-etm.h"
#include <internal/lib.h> // page_size
#include "../../../util/record.h"
#include "../../../util/session.h"
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "cs-etm.h"
struct cs_etm_recording {
struct auxtrace_record itr;

View File

@ -1,50 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <libunwind.h>
#include "perf_regs.h"
#include "../../../util/unwind.h"
#include "../../../util/debug.h"
int libunwind__arch_reg_id(int regnum)
{
switch (regnum) {
case UNW_ARM_R0:
return PERF_REG_ARM_R0;
case UNW_ARM_R1:
return PERF_REG_ARM_R1;
case UNW_ARM_R2:
return PERF_REG_ARM_R2;
case UNW_ARM_R3:
return PERF_REG_ARM_R3;
case UNW_ARM_R4:
return PERF_REG_ARM_R4;
case UNW_ARM_R5:
return PERF_REG_ARM_R5;
case UNW_ARM_R6:
return PERF_REG_ARM_R6;
case UNW_ARM_R7:
return PERF_REG_ARM_R7;
case UNW_ARM_R8:
return PERF_REG_ARM_R8;
case UNW_ARM_R9:
return PERF_REG_ARM_R9;
case UNW_ARM_R10:
return PERF_REG_ARM_R10;
case UNW_ARM_R11:
return PERF_REG_ARM_FP;
case UNW_ARM_R12:
return PERF_REG_ARM_IP;
case UNW_ARM_R13:
return PERF_REG_ARM_SP;
case UNW_ARM_R14:
return PERF_REG_ARM_LR;
case UNW_ARM_R15:
return PERF_REG_ARM_PC;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}
return -EINVAL;
}

View File

@ -1,11 +1,9 @@
perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
perf-util-y += ../../arm/util/auxtrace.o
perf-util-y += ../../arm/util/cs-etm.o
perf-util-y += ../../arm/util/pmu.o
perf-util-y += arm-spe.o
perf-util-y += header.o
perf-util-y += hisi-ptt.o
perf-util-y += machine.o
perf-util-y += mem-events.o
perf-util-y += pmu.o
perf-util-y += tsc.o

View File

@ -428,7 +428,8 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
evlist__for_each_entry_safe(evlist, tmp, evsel) {
if (evsel__is_aux_event(evsel)) {
arm_spe_setup_evsel(evsel, cpus);
if (!evsel__get_config_val(evsel, "discard", &discard_bit))
if (evsel__config_exists(evsel, "discard") &&
!evsel__get_config_val(evsel, "discard", &discard_bit))
discard = !!discard_bit;
}
}

View File

@ -1,12 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include "callchain.h" // prototype of arch__add_leaf_frame_record_opts
#include "perf_regs.h"
#include "record.h"
#define SMPL_REG_MASK(b) (1ULL << (b))
void arch__add_leaf_frame_record_opts(struct record_opts *opts)
{
opts->sample_user_regs |= SMPL_REG_MASK(PERF_REG_ARM64_LR);
}

View File

@ -1,17 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#ifndef REMOTE_UNWIND_LIBUNWIND
#include <libunwind.h>
#include "perf_regs.h"
#include "../../../util/unwind.h"
#endif
#include "../../../util/debug.h"
int LIBUNWIND__ARCH_REG_ID(int regnum)
{
if (regnum < 0 || regnum >= PERF_REG_ARM64_EXTENDED_MAX)
return -EINVAL;
return regnum;
}

View File

@ -1,13 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
#include "common.h"
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "../util/env.h"
#include "../util/debug.h"
#include <linux/zalloc.h>
#include <unistd.h>
#include <dwarf-regs.h>
#include "../util/debug.h"
#include "../util/env.h"
static const char *const arc_triplets[] = {
"arc-linux-",
@ -141,11 +146,40 @@ static int lookup_triplets(const char *const *triplets, const char *name)
return -1;
}
static bool is_native_compatible(struct perf_env *env, uint16_t target, uint16_t host)
{
if (target != host) {
/* A 64-bit host can natively disassemble its 32-bit compat architecture */
if (host == EM_X86_64 && target == EM_386)
return true;
if (host == EM_AARCH64 && target == EM_ARM)
return true;
if (host == EM_PPC64 && target == EM_PPC)
return true;
if (host == EM_SPARCV9 && target == EM_SPARC)
return true;
return false;
}
/* target == host case */
if (target == EM_RISCV) {
bool target_is_64 = perf_env__kernel_is_64_bit(env);
bool host_is_64 = (sizeof(void *) == 8);
/* 32-bit host cannot natively disassemble 64-bit target */
if (!host_is_64 && target_is_64)
return false;
}
return true;
}
static int perf_env__lookup_binutils_path(struct perf_env *env,
const char *name, char **path)
{
int idx;
const char *arch = perf_env__arch(env), *cross_env;
uint16_t e_machine = perf_env__e_machine(env, /*e_flags=*/NULL);
const char *cross_env;
const char *const *path_list;
char *buf = NULL;
@ -153,7 +187,7 @@ static int perf_env__lookup_binutils_path(struct perf_env *env,
* We don't need to try to find objdump path for native system.
* Just use default binutils path (e.g.: "objdump").
*/
if (!strcmp(perf_env__arch(NULL), arch))
if (is_native_compatible(env, e_machine, EM_HOST))
goto out;
cross_env = getenv("CROSS_COMPILE");
@ -170,30 +204,42 @@ static int perf_env__lookup_binutils_path(struct perf_env *env,
zfree(&buf);
}
if (!strcmp(arch, "arc"))
switch (e_machine) {
case EM_ARC:
path_list = arc_triplets;
else if (!strcmp(arch, "arm"))
break;
case EM_ARM:
path_list = arm_triplets;
else if (!strcmp(arch, "arm64"))
break;
case EM_AARCH64:
path_list = arm64_triplets;
else if (!strcmp(arch, "powerpc"))
break;
case EM_PPC:
case EM_PPC64:
path_list = powerpc_triplets;
else if (!strcmp(arch, "riscv32"))
path_list = riscv32_triplets;
else if (!strcmp(arch, "riscv64"))
path_list = riscv64_triplets;
else if (!strcmp(arch, "sh"))
break;
case EM_RISCV:
path_list = perf_env__kernel_is_64_bit(env) ? riscv64_triplets : riscv32_triplets;
break;
case EM_SH:
path_list = sh_triplets;
else if (!strcmp(arch, "s390"))
break;
case EM_S390:
path_list = s390_triplets;
else if (!strcmp(arch, "sparc"))
break;
case EM_SPARC:
case EM_SPARCV9:
path_list = sparc_triplets;
else if (!strcmp(arch, "x86"))
break;
case EM_X86_64:
case EM_386:
path_list = x86_triplets;
else if (!strcmp(arch, "mips"))
break;
case EM_MIPS:
path_list = mips_triplets;
else {
ui__error("binutils for %s not supported.\n", arch);
break;
default:
ui__error("binutils for %s not supported.\n", perf_env__arch(env));
goto out_error;
}
@ -202,7 +248,7 @@ static int perf_env__lookup_binutils_path(struct perf_env *env,
ui__error("Please install %s for %s.\n"
"You can add it to PATH, set CROSS_COMPILE or "
"override the default using --%s.\n",
name, arch, name);
name, perf_env__arch(env), name);
goto out_error;
}
@ -237,5 +283,7 @@ int perf_env__lookup_objdump(struct perf_env *env, char **path)
*/
bool perf_env__single_address_space(struct perf_env *env)
{
return strcmp(perf_env__arch(env), "sparc");
uint16_t e_machine = perf_env__e_machine(env, /*e_flags=*/NULL);
return e_machine != EM_SPARC && e_machine != EM_SPARCV9 && e_machine != EM_S390;
}

View File

@ -1,3 +1 @@
perf-util-y += header.o
perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o

View File

@ -1,82 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <libunwind.h>
#include "perf_regs.h"
#include "../../util/unwind.h"
#include "util/debug.h"
int libunwind__arch_reg_id(int regnum)
{
switch (regnum) {
case UNW_LOONGARCH64_R1:
return PERF_REG_LOONGARCH_R1;
case UNW_LOONGARCH64_R2:
return PERF_REG_LOONGARCH_R2;
case UNW_LOONGARCH64_R3:
return PERF_REG_LOONGARCH_R3;
case UNW_LOONGARCH64_R4:
return PERF_REG_LOONGARCH_R4;
case UNW_LOONGARCH64_R5:
return PERF_REG_LOONGARCH_R5;
case UNW_LOONGARCH64_R6:
return PERF_REG_LOONGARCH_R6;
case UNW_LOONGARCH64_R7:
return PERF_REG_LOONGARCH_R7;
case UNW_LOONGARCH64_R8:
return PERF_REG_LOONGARCH_R8;
case UNW_LOONGARCH64_R9:
return PERF_REG_LOONGARCH_R9;
case UNW_LOONGARCH64_R10:
return PERF_REG_LOONGARCH_R10;
case UNW_LOONGARCH64_R11:
return PERF_REG_LOONGARCH_R11;
case UNW_LOONGARCH64_R12:
return PERF_REG_LOONGARCH_R12;
case UNW_LOONGARCH64_R13:
return PERF_REG_LOONGARCH_R13;
case UNW_LOONGARCH64_R14:
return PERF_REG_LOONGARCH_R14;
case UNW_LOONGARCH64_R15:
return PERF_REG_LOONGARCH_R15;
case UNW_LOONGARCH64_R16:
return PERF_REG_LOONGARCH_R16;
case UNW_LOONGARCH64_R17:
return PERF_REG_LOONGARCH_R17;
case UNW_LOONGARCH64_R18:
return PERF_REG_LOONGARCH_R18;
case UNW_LOONGARCH64_R19:
return PERF_REG_LOONGARCH_R19;
case UNW_LOONGARCH64_R20:
return PERF_REG_LOONGARCH_R20;
case UNW_LOONGARCH64_R21:
return PERF_REG_LOONGARCH_R21;
case UNW_LOONGARCH64_R22:
return PERF_REG_LOONGARCH_R22;
case UNW_LOONGARCH64_R23:
return PERF_REG_LOONGARCH_R23;
case UNW_LOONGARCH64_R24:
return PERF_REG_LOONGARCH_R24;
case UNW_LOONGARCH64_R25:
return PERF_REG_LOONGARCH_R25;
case UNW_LOONGARCH64_R26:
return PERF_REG_LOONGARCH_R26;
case UNW_LOONGARCH64_R27:
return PERF_REG_LOONGARCH_R27;
case UNW_LOONGARCH64_R28:
return PERF_REG_LOONGARCH_R28;
case UNW_LOONGARCH64_R29:
return PERF_REG_LOONGARCH_R29;
case UNW_LOONGARCH64_R30:
return PERF_REG_LOONGARCH_R30;
case UNW_LOONGARCH64_R31:
return PERF_REG_LOONGARCH_R31;
case UNW_LOONGARCH64_PC:
return PERF_REG_LOONGARCH_PC;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}
return -EINVAL;
}

View File

@ -1 +0,0 @@
perf-util-y += util/

View File

@ -1 +0,0 @@
perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o

View File

@ -1,22 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <libunwind.h>
#include "perf_regs.h"
#include "../../util/unwind.h"
#include "util/debug.h"
int libunwind__arch_reg_id(int regnum)
{
switch (regnum) {
case UNW_MIPS_R1 ... UNW_MIPS_R25:
return regnum - UNW_MIPS_R1 + PERF_REG_MIPS_R1;
case UNW_MIPS_R28 ... UNW_MIPS_R31:
return regnum - UNW_MIPS_R28 + PERF_REG_MIPS_R28;
case UNW_MIPS_PC:
return PERF_REG_MIPS_PC;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}
}

View File

@ -7,6 +7,7 @@
* http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
* http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
*/
#undef REG_DWARFNUM_NAME
#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
static const char * const powerpc_regstr_tbl[] = {

View File

@ -6,5 +6,4 @@ perf-util-y += evsel.o
perf-util-$(CONFIG_LIBDW) += skip-callchain-idx.o
perf-util-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
perf-util-y += auxtrace.o

View File

@ -71,6 +71,12 @@ struct auxtrace_record *auxtrace_record__init(struct evlist *evlist,
struct evsel *pos;
int found = 0;
/*
* Set err value to zero here. Any fail later
* will set appropriate return code to err.
*/
*err = 0;
evlist__for_each_entry(evlist, pos) {
if (strstarts(pos->name, "vpa_dtl")) {
found = 1;

View File

@ -1,92 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2016 Chandan Kumar, IBM Corporation.
*/
#include <errno.h>
#include <libunwind.h>
#include <asm/perf_regs.h>
#include "../../util/unwind.h"
#include "../../util/debug.h"
int libunwind__arch_reg_id(int regnum)
{
switch (regnum) {
case UNW_PPC64_R0:
return PERF_REG_POWERPC_R0;
case UNW_PPC64_R1:
return PERF_REG_POWERPC_R1;
case UNW_PPC64_R2:
return PERF_REG_POWERPC_R2;
case UNW_PPC64_R3:
return PERF_REG_POWERPC_R3;
case UNW_PPC64_R4:
return PERF_REG_POWERPC_R4;
case UNW_PPC64_R5:
return PERF_REG_POWERPC_R5;
case UNW_PPC64_R6:
return PERF_REG_POWERPC_R6;
case UNW_PPC64_R7:
return PERF_REG_POWERPC_R7;
case UNW_PPC64_R8:
return PERF_REG_POWERPC_R8;
case UNW_PPC64_R9:
return PERF_REG_POWERPC_R9;
case UNW_PPC64_R10:
return PERF_REG_POWERPC_R10;
case UNW_PPC64_R11:
return PERF_REG_POWERPC_R11;
case UNW_PPC64_R12:
return PERF_REG_POWERPC_R12;
case UNW_PPC64_R13:
return PERF_REG_POWERPC_R13;
case UNW_PPC64_R14:
return PERF_REG_POWERPC_R14;
case UNW_PPC64_R15:
return PERF_REG_POWERPC_R15;
case UNW_PPC64_R16:
return PERF_REG_POWERPC_R16;
case UNW_PPC64_R17:
return PERF_REG_POWERPC_R17;
case UNW_PPC64_R18:
return PERF_REG_POWERPC_R18;
case UNW_PPC64_R19:
return PERF_REG_POWERPC_R19;
case UNW_PPC64_R20:
return PERF_REG_POWERPC_R20;
case UNW_PPC64_R21:
return PERF_REG_POWERPC_R21;
case UNW_PPC64_R22:
return PERF_REG_POWERPC_R22;
case UNW_PPC64_R23:
return PERF_REG_POWERPC_R23;
case UNW_PPC64_R24:
return PERF_REG_POWERPC_R24;
case UNW_PPC64_R25:
return PERF_REG_POWERPC_R25;
case UNW_PPC64_R26:
return PERF_REG_POWERPC_R26;
case UNW_PPC64_R27:
return PERF_REG_POWERPC_R27;
case UNW_PPC64_R28:
return PERF_REG_POWERPC_R28;
case UNW_PPC64_R29:
return PERF_REG_POWERPC_R29;
case UNW_PPC64_R30:
return PERF_REG_POWERPC_R30;
case UNW_PPC64_R31:
return PERF_REG_POWERPC_R31;
case UNW_PPC64_LR:
return PERF_REG_POWERPC_LINK;
case UNW_PPC64_CTR:
return PERF_REG_POWERPC_CTR;
case UNW_PPC64_XER:
return PERF_REG_POWERPC_XER;
case UNW_PPC64_NIP:
return PERF_REG_POWERPC_NIP;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}
return -EINVAL;
}

View File

@ -2,7 +2,8 @@
#ifdef DEFINE_DWARF_REGSTR_TABLE
/* This is included in perf/util/dwarf-regs.c */
#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
#undef REG_DWARFNUM_NAME
#define REG_DWARFNUM_NAME(reg, idx) [idx] = reg
static const char * const riscv_regstr_tbl[] = {
REG_DWARFNUM_NAME("%zero", 0),

View File

@ -19,7 +19,7 @@
static char *_get_field(const char *line)
{
char *line2, *nl;
const char *line2, *nl;
line2 = strrchr(line, ' ');
if (!line2)

View File

@ -2,6 +2,7 @@
#ifndef S390_DWARF_REGS_TABLE_H
#define S390_DWARF_REGS_TABLE_H
#undef REG_DWARFNUM_NAME
#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
/*

View File

@ -932,7 +932,7 @@ static bool kernel_v6_15_or_newer(void)
endptr++;
minor = strtol(endptr, NULL, 10);
return major >= 6 && minor >= 15;
return major > 6 || (major == 6 && minor >= 15);
}
int test__amd_ibs_period(struct test_suite *test __maybe_unused,

View File

@ -75,4 +75,168 @@ static int test__x86_topdown(struct test_suite *test __maybe_unused, int subtest
return ret;
}
DEFINE_SUITE("x86 topdown", x86_topdown);
#define CHECK_COND(cond, text) \
do { \
if (!(cond)) { \
pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
ret = TEST_FAIL; \
goto out_err; \
} \
} while (0)
#define CHECK_EQUAL(val, expected, text) \
do { \
if ((val) != (expected)) { \
pr_debug("FAILED %s:%d %s (%d != %d)\n", \
__FILE__, __LINE__, text, (val), (expected)); \
ret = TEST_FAIL; \
goto out_err; \
} \
} while (0)
static int test_sort(const char *str, int expected_slots_group_size,
int expected_instructions_group_size)
{
struct evlist *evlist = NULL;
struct parse_events_error err;
struct evsel *evsel;
int ret = TEST_FAIL;
bool slots_seen = false;
parse_events_error__init(&err);
evlist = evlist__new();
if (!evlist)
goto out_err;
if (parse_events(evlist, str, &err)) {
pr_debug("parse_events failed for %s\n", str);
goto out_err;
}
evlist__for_each_entry(evlist, evsel) {
if (!evsel__is_group_leader(evsel))
continue;
if (strstr(evsel__name(evsel), "slots")) {
/*
* Slots as a leader means the PMU is for a perf metric
* group as the slots event isn't present when not.
*/
slots_seen = true;
CHECK_EQUAL(evsel->core.nr_members, expected_slots_group_size,
"slots group size");
if (expected_slots_group_size == 3) {
struct evsel *next = evsel__next(evsel);
struct evsel *next2 = evsel__next(next);
CHECK_COND(strstr(evsel__name(next), "instructions") != NULL,
"slots second event is instructions");
CHECK_COND(strstr(evsel__name(next2), "topdown-retiring") != NULL,
"slots third event is topdown-retiring");
} else if (expected_slots_group_size == 2) {
struct evsel *next = evsel__next(evsel);
CHECK_COND(strstr(evsel__name(next), "topdown-retiring") != NULL,
"slots second event is topdown-retiring");
}
} else if (strstr(evsel__name(evsel), "instructions")) {
CHECK_EQUAL(evsel->core.nr_members, expected_instructions_group_size,
"instructions group size");
if (expected_instructions_group_size == 2) {
/*
* On Intel hybrid CPUs (e.g., Alder Lake/
* Raptor Lake), E-cores (cpu_atom) do not
* support/enforce the slots event. When
* parsing event groups containing slots
* across all PMUs, slots is automatically
* filtered out from cpu_atom, leaving
* {cpu_atom/instructions/,
* cpu_atom/topdown-retiring/}. On cpu_atom,
* instructions correctly leads this group of
* 2 without slots reordering.
*/
struct evsel *next = evsel__next(evsel);
CHECK_COND(strstr(evsel__name(next), "topdown-retiring") != NULL,
"instructions second event is topdown-retiring");
}
} else if (strstr(evsel__name(evsel), "topdown-retiring")) {
/*
* A perf metric event where the PMU doesn't require
* slots as a leader.
*/
CHECK_EQUAL(evsel->core.nr_members, 1, "topdown-retiring group size");
} else if (strstr(evsel__name(evsel), "cycles")) {
CHECK_EQUAL(evsel->core.nr_members, 1, "cycles group size");
}
}
CHECK_COND(slots_seen, "slots seen");
ret = TEST_OK;
out_err:
evlist__delete(evlist);
parse_events_error__exit(&err);
return ret;
}
static int test__x86_topdown_sorting(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
int ret;
if (!topdown_sys_has_perf_metrics())
return TEST_OK;
ret = test_sort("{instructions,topdown-retiring,slots}", 3, 2);
TEST_ASSERT_EQUAL("all events in a group", ret, TEST_OK);
ret = test_sort("instructions,topdown-retiring,slots", 2, 1);
TEST_ASSERT_EQUAL("all events not in a group", ret, TEST_OK);
ret = test_sort("{instructions,slots},topdown-retiring", 2, 1);
TEST_ASSERT_EQUAL("slots event in a group but topdown metrics events outside the group",
ret, TEST_OK);
ret = test_sort("{instructions,slots},{topdown-retiring}", 2, 1);
TEST_ASSERT_EQUAL("slots event and topdown metrics events in two groups",
ret, TEST_OK);
ret = test_sort("{instructions,slots},cycles,topdown-retiring", 2, 1);
TEST_ASSERT_EQUAL("slots event and metrics event are not in a group and not adjacent",
ret, TEST_OK);
return TEST_OK;
}
static int test__x86_topdown_slots_injection(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
int ret;
if (!topdown_sys_has_perf_metrics())
return TEST_OK;
ret = test_sort("{instructions,topdown-retiring}", 3, 2);
TEST_ASSERT_EQUAL("all events in a group", ret, TEST_OK);
ret = test_sort("instructions,topdown-retiring", 2, 1);
TEST_ASSERT_EQUAL("all events not in a group", ret, TEST_OK);
ret = test_sort("{instructions},topdown-retiring", 2, 1);
TEST_ASSERT_EQUAL("event in a group but topdown metrics events outside the group",
ret, TEST_OK);
ret = test_sort("{instructions},{topdown-retiring}", 2, 1);
TEST_ASSERT_EQUAL("event and topdown metrics events in two groups",
ret, TEST_OK);
ret = test_sort("{instructions},cycles,topdown-retiring", 2, 1);
TEST_ASSERT_EQUAL("event and metrics event are not in a group and not adjacent",
ret, TEST_OK);
return TEST_OK;
}
static struct test_case x86_topdown_tests[] = {
TEST_CASE("topdown events", x86_topdown),
TEST_CASE("topdown sorting", x86_topdown_sorting),
TEST_CASE("topdown slots injection", x86_topdown_slots_injection),
{ .name = NULL, }
};
struct test_suite suite__x86_topdown = {
.desc = "x86 topdown",
.test_cases = x86_topdown_tests,
};

View File

@ -8,9 +8,6 @@ perf-util-y += evlist.o
perf-util-y += mem-events.o
perf-util-y += evsel.o
perf-util-y += iostat.o
perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
perf-util-y += auxtrace.o
perf-util-y += intel-pt.o
perf-util-y += intel-bts.o

View File

@ -4,27 +4,31 @@
* Copyright (c) 2013-2015, Intel Corporation.
*/
#include "../../../util/intel-bts.h"
#include <errno.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/types.h>
#include <linux/zalloc.h>
#include "../../../util/cpumap.h"
#include "../../../util/event.h"
#include "../../../util/evsel.h"
#include "../../../util/evlist.h"
#include "../../../util/mmap.h"
#include "../../../util/session.h"
#include "../../../util/pmus.h"
#include "../../../util/debug.h"
#include "../../../util/record.h"
#include "../../../util/tsc.h"
#include "../../../util/auxtrace.h"
#include "../../../util/intel-bts.h"
#include <internal/lib.h> // page_size
#include "../../../util/auxtrace.h"
#include "../../../util/cpumap.h"
#include "../../../util/debug.h"
#include "../../../util/event.h"
#include "../../../util/evlist.h"
#include "../../../util/evsel.h"
#include "../../../util/mmap.h"
#include "../../../util/pmu.h"
#include "../../../util/pmus.h"
#include "../../../util/record.h"
#include "../../../util/session.h"
#include "../../../util/tsc.h"
#define KiB(x) ((x) * 1024)
#define MiB(x) ((x) * 1024 * 1024)
#define KiB_MASK(x) (KiB(x) - 1)

View File

@ -3,36 +3,39 @@
* intel_pt.c: Intel Processor Trace support
* Copyright (c) 2013-2015, Intel Corporation.
*/
#include "../../../util/intel-pt.h"
#include <errno.h>
#include <stdbool.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/zalloc.h>
#include <linux/err.h>
#include "../../../util/session.h"
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/types.h>
#include <linux/zalloc.h>
#include <api/fs/fs.h>
#include <internal/lib.h> // page_size
#include <subcmd/parse-options.h>
#include "../../../util/auxtrace.h"
#include "../../../util/config.h"
#include "../../../util/cpumap.h"
#include "../../../util/debug.h"
#include "../../../util/event.h"
#include "../../../util/evlist.h"
#include "../../../util/evsel.h"
#include "../../../util/evsel_config.h"
#include "../../../util/config.h"
#include "../../../util/cpumap.h"
#include "../../../util/mmap.h"
#include <subcmd/parse-options.h>
#include "../../../util/parse-events.h"
#include "../../../util/pmus.h"
#include "../../../util/debug.h"
#include "../../../util/auxtrace.h"
#include "../../../util/perf_api_probe.h"
#include "../../../util/pmu.h"
#include "../../../util/pmus.h"
#include "../../../util/record.h"
#include "../../../util/session.h"
#include "../../../util/target.h"
#include "../../../util/tsc.h"
#include <internal/lib.h> // page_size
#include "../../../util/intel-pt.h"
#include <api/fs/fs.h>
#include "cpuid.h"
#define KiB(x) ((x) * 1024)

View File

@ -1,115 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include "../../util/debug.h"
#ifndef REMOTE_UNWIND_LIBUNWIND
#include <libunwind.h>
#include "perf_regs.h"
#include "../../util/unwind.h"
#endif
#ifdef HAVE_ARCH_X86_64_SUPPORT
int LIBUNWIND__ARCH_REG_ID(int regnum)
{
int id;
switch (regnum) {
case UNW_X86_64_RAX:
id = PERF_REG_X86_AX;
break;
case UNW_X86_64_RDX:
id = PERF_REG_X86_DX;
break;
case UNW_X86_64_RCX:
id = PERF_REG_X86_CX;
break;
case UNW_X86_64_RBX:
id = PERF_REG_X86_BX;
break;
case UNW_X86_64_RSI:
id = PERF_REG_X86_SI;
break;
case UNW_X86_64_RDI:
id = PERF_REG_X86_DI;
break;
case UNW_X86_64_RBP:
id = PERF_REG_X86_BP;
break;
case UNW_X86_64_RSP:
id = PERF_REG_X86_SP;
break;
case UNW_X86_64_R8:
id = PERF_REG_X86_R8;
break;
case UNW_X86_64_R9:
id = PERF_REG_X86_R9;
break;
case UNW_X86_64_R10:
id = PERF_REG_X86_R10;
break;
case UNW_X86_64_R11:
id = PERF_REG_X86_R11;
break;
case UNW_X86_64_R12:
id = PERF_REG_X86_R12;
break;
case UNW_X86_64_R13:
id = PERF_REG_X86_R13;
break;
case UNW_X86_64_R14:
id = PERF_REG_X86_R14;
break;
case UNW_X86_64_R15:
id = PERF_REG_X86_R15;
break;
case UNW_X86_64_RIP:
id = PERF_REG_X86_IP;
break;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}
return id;
}
#else
int LIBUNWIND__ARCH_REG_ID(int regnum)
{
int id;
switch (regnum) {
case UNW_X86_EAX:
id = PERF_REG_X86_AX;
break;
case UNW_X86_EDX:
id = PERF_REG_X86_DX;
break;
case UNW_X86_ECX:
id = PERF_REG_X86_CX;
break;
case UNW_X86_EBX:
id = PERF_REG_X86_BX;
break;
case UNW_X86_ESI:
id = PERF_REG_X86_SI;
break;
case UNW_X86_EDI:
id = PERF_REG_X86_DI;
break;
case UNW_X86_EBP:
id = PERF_REG_X86_BP;
break;
case UNW_X86_ESP:
id = PERF_REG_X86_SP;
break;
case UNW_X86_EIP:
id = PERF_REG_X86_IP;
break;
default:
pr_err("unwind: invalid reg id %d\n", regnum);
return -EINVAL;
}
return id;
}
#endif /* HAVE_ARCH_X86_64_SUPPORT */

View File

@ -24,3 +24,9 @@ perf-bench-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o
perf-bench-$(CONFIG_X86_64) += mem-memset-x86-64-asm.o
perf-bench-$(CONFIG_NUMA) += numa.o
ifeq ($(CONFIG_PERF_BPF_SKEL),y)
include $(srctree)/tools/perf/bpf_skel.mak
$(OUTPUT)bench/uprobe.o: $(SKEL_OUT)/bench_uprobe.skel.h
endif

View File

@ -228,9 +228,12 @@ static ssize_t synthesize_sample(struct bench_data *data, struct bench_dso *dso,
event.header.type = PERF_RECORD_SAMPLE;
event.header.misc = PERF_RECORD_MISC_USER;
event.header.size = perf_event__sample_event_size(&sample, bench_sample_type, 0);
perf_event__synthesize_sample(&event, bench_sample_type, 0, &sample);
event.header.size = perf_event__sample_event_size(&sample, bench_sample_type,
/*read_format=*/0,
/*branch_sample_type=*/0);
perf_event__synthesize_sample(&event, bench_sample_type,
/*read_format=*/0,
/*branch_sample_type=*/0, &sample);
return writen(data->input_pipe[1], &event, event.header.size);
}

View File

@ -22,7 +22,9 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <assert.h>
#include <poll.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/types.h>
@ -39,6 +41,7 @@ struct thread_data {
int epoll_fd;
bool cgroup_failed;
pthread_t pthread;
char *buf;
};
#define LOOPS_DEFAULT 1000000
@ -48,6 +51,7 @@ static int loops = LOOPS_DEFAULT;
static bool threaded;
static bool nonblocking;
static unsigned int write_size = sizeof(int);
static char *cgrp_names[2];
static struct cgroup *cgrps[2];
@ -88,6 +92,8 @@ static const struct option options[] = {
OPT_BOOLEAN('n', "nonblocking", &nonblocking, "Use non-blocking operations"),
OPT_INTEGER('l', "loop", &loops, "Specify number of loops"),
OPT_BOOLEAN('T', "threaded", &threaded, "Specify threads/process based task setup"),
OPT_UINTEGER('s', "write-size", &write_size,
"Bytes per ping-pong write (default 4-bytes). Use larger values to exercise the pipe page-allocation path."),
OPT_CALLBACK('G', "cgroups", NULL, "SEND,RECV",
"Put sender and receivers in given cgroups",
parse_two_cgroups),
@ -170,25 +176,77 @@ static void exit_cgroup(int nr)
free(cgrp_names[nr]);
}
/* Sleep until @fd is writable, so we don't busy-spin on EWOULDBLOCK. */
static inline void wait_writable(int fd)
{
struct pollfd pfd = {
.fd = fd,
.events = POLLOUT,
};
poll(&pfd, 1, -1);
}
/*
* Loop on short read()/write(): the kernel may return fewer bytes than
* requested, retry on EINTR, and in non-blocking mode wait via poll()
* when the writer transiently hits EWOULDBLOCK while the peer is still
* draining a full pipe (capacity is sized to write_size).
*/
static inline int write_pipe(struct thread_data *td)
{
unsigned int done = 0;
int ret;
while (done < write_size) {
ret = write(td->pipe_write, td->buf + done, write_size - done);
if (ret < 0) {
if (errno == EINTR)
continue;
if (nonblocking && errno == EWOULDBLOCK) {
wait_writable(td->pipe_write);
continue;
}
return ret;
}
done += ret;
}
return done;
}
static inline int read_pipe(struct thread_data *td)
{
int ret, m;
retry:
if (nonblocking) {
ret = epoll_wait(td->epoll_fd, &td->epoll_ev, 1, -1);
if (ret < 0)
unsigned int done = 0;
int ret;
while (done < write_size) {
if (nonblocking) {
ret = epoll_wait(td->epoll_fd, &td->epoll_ev, 1, -1);
if (ret < 0) {
if (errno == EINTR)
continue;
return ret;
}
}
ret = read(td->pipe_read, td->buf + done, write_size - done);
if (ret < 0) {
if (errno == EINTR)
continue;
if (nonblocking && errno == EWOULDBLOCK)
continue;
return ret;
}
if (ret == 0)
return done;
done += ret;
}
ret = read(td->pipe_read, &m, sizeof(int));
if (nonblocking && ret < 0 && errno == EWOULDBLOCK)
goto retry;
return ret;
return done;
}
static void *worker_thread(void *__tdata)
{
struct thread_data *td = __tdata;
int i, ret, m = 0;
int i, ret;
ret = enter_cgroup(td->nr);
if (ret < 0) {
@ -204,15 +262,38 @@ static void *worker_thread(void *__tdata)
}
for (i = 0; i < loops; i++) {
ret = write(td->pipe_write, &m, sizeof(int));
BUG_ON(ret != sizeof(int));
ret = write_pipe(td);
BUG_ON(ret != (int)write_size);
ret = read_pipe(td);
BUG_ON(ret != sizeof(int));
BUG_ON(ret != (int)write_size);
}
return NULL;
}
/*
* On a custom write_size, resize the pipes so a single payload fits.
*/
static int resize_pipes(int wfd1, int wfd2)
{
int r1, r2;
if (write_size <= sizeof(int))
return 0;
r1 = fcntl(wfd1, F_SETPIPE_SZ, write_size);
r2 = fcntl(wfd2, F_SETPIPE_SZ, write_size);
if (r1 < 0 || r2 < 0 ||
(unsigned int)r1 < write_size ||
(unsigned int)r2 < write_size) {
fprintf(stderr,
"--write-size %u exceeds /proc/sys/fs/pipe-max-size\n",
write_size);
return -1;
}
return 0;
}
int bench_sched_pipe(int argc, const char **argv)
{
struct thread_data threads[2] = {};
@ -233,12 +314,31 @@ int bench_sched_pipe(int argc, const char **argv)
argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0);
/*
* The error paths below return early without closing the pipes or
* freeing the cgroup state. That is fine: bench_sched_pipe() runs
* once and the process exits right after it returns, so these are
* not real leaks.
*/
if (write_size == 0 || write_size > INT_MAX) {
fprintf(stderr, "--write-size must be in 1..%d\n", INT_MAX);
return -1;
}
if (nonblocking)
flags |= O_NONBLOCK;
BUG_ON(pipe2(pipe_1, flags));
BUG_ON(pipe2(pipe_2, flags));
if (resize_pipes(pipe_1[1], pipe_2[1]) < 0)
return -1;
for (t = 0; t < nr_threads; t++) {
threads[t].buf = calloc(1, write_size);
BUG_ON(!threads[t].buf);
}
gettimeofday(&start, NULL);
for (t = 0; t < nr_threads; t++) {
@ -287,6 +387,9 @@ int bench_sched_pipe(int argc, const char **argv)
gettimeofday(&stop, NULL);
timersub(&stop, &start, &diff);
for (t = 0; t < nr_threads; t++)
free(threads[t].buf);
exit_cgroup(0);
exit_cgroup(1);

View File

@ -44,7 +44,7 @@ static const char * const bench_uprobe_usage[] = {
};
#ifdef HAVE_BPF_SKEL
#include "bpf_skel/bench_uprobe.skel.h"
#include "bench/bpf_skel/bench_uprobe.skel.h"
#define bench_uprobe__attach_uprobe(prog) \
skel->links.prog = bpf_program__attach_uprobe_opts(/*prog=*/skel->progs.prog, \

109
tools/perf/bpf_skel.mak Normal file
View File

@ -0,0 +1,109 @@
# SPDX-License-Identifier: GPL-2.0
# Shared BPF Skeleton Generator Rules
include $(srctree)/tools/scripts/Makefile.include
# Shared foundational tooling always lives in util/bpf_skel
SKEL_TOOL_OUT := $(abspath $(OUTPUT)util/bpf_skel)
SKEL_TOOL_TMP_OUT := $(abspath $(SKEL_TOOL_OUT)/.tmp)
# Component specific output lives in $(dir)/bpf_skel
SKEL_OUT := $(abspath $(OUTPUT)$(dir)/bpf_skel)
SKEL_TMP_OUT := $(abspath $(SKEL_OUT)/.tmp)
ifeq ($(CONFIG_PERF_BPF_SKEL),y)
BPFTOOL := $(SKEL_TOOL_TMP_OUT)/bootstrap/bpftool
VMLINUX_H := $(SKEL_TOOL_OUT)/vmlinux.h
.PHONY: bpf-skel-prepare
bpf-skel-prepare: $(BPFTOOL) $(VMLINUX_H)
@:
define get_sys_includes
$(shell $(1) $(2) -v -E - </dev/null 2>&1 \
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \
$(shell $(1) $(2) -dM -E - </dev/null | grep '__riscv_xlen ' | awk '{printf("-D__riscv_xlen=%d -D__BITS_PER_LONG=%d", $$3, $$3)}')
endef
ifneq ($(CROSS_COMPILE),)
CLANG_TARGET_ARCH = --target=$(notdir $(CROSS_COMPILE:%-=%))
endif
CLANG_OPTIONS = -Wall -mcpu=v3
CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH))
LIBBPF_INCLUDE := $(abspath $(or $(OUTPUT),.))/libbpf/include
BPF_INCLUDE := -I$(SKEL_TMP_OUT)/.. -I$(SKEL_TOOL_OUT) -I$(LIBBPF_INCLUDE) $(CLANG_SYS_INCLUDES)
TOOLS_UAPI_INCLUDE := -I$(srctree)/tools/include/uapi
ifneq ($(WERROR),0)
CLANG_OPTIONS += -Werror
endif
$(BPFTOOL):
$(Q)mkdir -p $(SKEL_TOOL_TMP_OUT)
$(Q)CFLAGS= $(MAKE) -C ../bpf/bpftool OUTPUT=$(SKEL_TOOL_TMP_OUT)/ bootstrap
# Paths to search for a kernel to generate vmlinux.h from.
VMLINUX_BTF_ELF_PATHS ?= $(if $(O),$(O)/vmlinux) \
$(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \
../../vmlinux \
/boot/vmlinux-$(shell uname -r)
# Paths to BTF information.
VMLINUX_BTF_BTF_PATHS ?= /sys/kernel/btf/vmlinux
# Filter out kernels that don't exist or without a BTF section.
VMLINUX_BTF_ELF_ABSPATHS ?= $(abspath $(wildcard $(VMLINUX_BTF_ELF_PATHS)))
VMLINUX_BTF_PATHS ?= $(shell for file in $(VMLINUX_BTF_ELF_ABSPATHS); \
do \
if [ -f $$file ] && ($(READELF) -S "$$file" | grep -q .BTF); \
then \
echo "$$file"; \
fi; \
done) \
$(wildcard $(VMLINUX_BTF_BTF_PATHS))
# Select the first as the source of vmlinux.h.
VMLINUX_BTF ?= $(firstword $(VMLINUX_BTF_PATHS))
ifeq ($(VMLINUX_H_FILE),)
ifeq ($(VMLINUX_BTF),)
$(error Missing bpftool input for generating vmlinux.h)
endif
endif
$(VMLINUX_H): $(VMLINUX_BTF) $(BPFTOOL) $(VMLINUX_H_FILE)
$(call rule_mkdir)
ifeq ($(VMLINUX_H_FILE),)
$(QUIET_GEN)$(BPFTOOL) btf dump file $< format c > $@
else
$(Q)cp "$(VMLINUX_H_FILE)" $@
endif
# Consolidated Pattern rule for $(dir)/bpf_skel/
$(SKEL_TMP_OUT)/%.bpf.o: $(srctree)/tools/perf/$(dir)/bpf_skel/%.bpf.c $(LIBBPF) $(VMLINUX_H) $(OUTPUT)PERF-VERSION-FILE util/bpf_skel/perf_version.h
$(call rule_mkdir)
$(QUIET_CLANG)
$(Q)$(CLANG) -g -O2 -fno-stack-protector --target=bpf \
$(CLANG_OPTIONS) $(EXTRA_BPF_FLAGS) $(BPF_INCLUDE) $(TOOLS_UAPI_INCLUDE) \
-include $(OUTPUT)PERF-VERSION-FILE -include util/bpf_skel/perf_version.h \
-fms-extensions -Wno-microsoft-anon-tag \
-c $< -o $@
$(SKEL_OUT)/%.skel.h: $(SKEL_TMP_OUT)/%.bpf.o $(BPFTOOL)
$(call rule_mkdir)
$(QUIET_GENSKEL)
$(Q)$(BPFTOOL) gen skeleton $< > $@
.PRECIOUS: $(SKEL_TMP_OUT)/%.bpf.o
else # CONFIG_PERF_BPF_SKEL
.PHONY: bpf-skel-prepare
bpf-skel-prepare:
@:
endif # CONFIG_PERF_BPF_SKEL
clean:
$(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TOOL_TMP_OUT) $(OUTPUT)bench/bpf_skel/.tmp $(SKEL_TOOL_OUT)/*.skel.h $(OUTPUT)bench/bpf_skel/*.skel.h $(SKEL_TOOL_OUT)/vmlinux.h
.PHONY: clean

View File

@ -176,29 +176,26 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
struct hist_entry *he = iter->he;
struct branch_info *bi;
struct perf_sample *sample = iter->sample;
struct evsel *evsel = iter->evsel;
int err;
bi = he->branch_info;
err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
err = addr_map_symbol__inc_samples(&bi->from, sample);
if (err)
goto out;
err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
err = addr_map_symbol__inc_samples(&bi->to, sample);
out:
return err;
}
static int process_branch_callback(struct evsel *evsel,
struct perf_sample *sample,
static int process_branch_callback(struct perf_sample *sample,
struct addr_location *al,
struct perf_annotate *ann,
struct machine *machine)
{
struct hist_entry_iter iter = {
.evsel = evsel,
.sample = sample,
.add_entry_cb = hist_iter__branch_callback,
.hide_unresolved = symbol_conf.hide_unresolved,
@ -221,8 +218,8 @@ static int process_branch_callback(struct evsel *evsel,
if (a.map != NULL)
dso__set_hit(map__dso(a.map));
hist__account_cycles(sample->branch_stack, al, sample, false,
NULL, evsel);
hist__account_cycles(sample->branch_stack, al, sample, /*nonany_branch_mode=*/false,
/*total_cycles=*/NULL);
ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann);
out:
@ -235,11 +232,11 @@ static bool has_annotation(struct perf_annotate *ann)
return ui__has_annotation() || ann->use_stdio2;
}
static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample,
struct addr_location *al, struct perf_annotate *ann,
struct machine *machine)
static int add_sample(struct perf_sample *sample,
struct addr_location *al, struct perf_annotate *ann,
struct machine *machine)
{
struct hists *hists = evsel__hists(evsel);
struct hists *hists = evsel__hists(sample->evsel);
struct hist_entry *he;
int ret;
@ -269,13 +266,13 @@ static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample,
process_branch_stack(sample->branch_stack, al, sample);
if (ann->has_br_stack && has_annotation(ann))
return process_branch_callback(evsel, sample, al, ann, machine);
return process_branch_callback(sample, al, ann, machine);
he = hists__add_entry(hists, al, NULL, NULL, NULL, NULL, sample, true);
if (he == NULL)
return -ENOMEM;
ret = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
ret = hist_entry__inc_addr_samples(he, sample, al->addr);
hists__inc_nr_samples(hists, true);
return ret;
}
@ -283,7 +280,6 @@ static int evsel__add_sample(struct evsel *evsel, struct perf_sample *sample,
static int process_sample_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);
@ -292,17 +288,19 @@ static int process_sample_event(const struct perf_tool *tool,
addr_location__init(&al);
if (machine__resolve(machine, &al, sample) < 0) {
pr_warning("problem processing %d event, skipping it.\n",
event->header.type);
pr_warning("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
ret = -1;
goto out_put;
}
if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
if (ann->cpu_list && (sample->cpu >= MAX_NR_CPUS ||
!test_bit(sample->cpu, ann->cpu_bitmap)))
goto out_put;
if (!al.filtered &&
evsel__add_sample(evsel, sample, &al, ann, machine)) {
add_sample(sample, &al, ann, machine)) {
pr_warning("problem incrementing symbol count, "
"skipping event\n");
ret = -1;
@ -563,6 +561,10 @@ static int __cmd_annotate(struct perf_annotate *ann)
if (ret)
goto out;
if ((use_browser == 1 || ann->use_stdio2) && ann->has_br_stack)
if (session->evlist->nr_br_cntr > 0)
annotate_opts.show_br_cntr = true;
if (dump_trace) {
perf_session__fprintf_nr_events(session, stdout);
evlist__fprintf_nr_events(session->evlist, stdout);
@ -926,11 +928,8 @@ int cmd_annotate(int argc, const char **argv)
* branch counters, if the corresponding branch info is available
* in the perf data in the TUI mode.
*/
if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) {
if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack)
sort__mode = SORT_MODE__BRANCH;
if (annotate.session->evlist->nr_br_cntr > 0)
annotate_opts.show_br_cntr = true;
}
if (setup_sorting(/*evlist=*/NULL, perf_session__env(annotate.session)) < 0)
usage_with_options(annotate_usage, options);

View File

@ -61,7 +61,7 @@ static int sysfs__fprintf_build_id(FILE *fp)
int ret;
ret = sysfs__snprintf_build_id("/", sbuild_id, sizeof(sbuild_id));
if (ret != sizeof(sbuild_id))
if (ret + 1 != sizeof(sbuild_id))
return ret < 0 ? ret : -EINVAL;
return fprintf(fp, "%s\n", sbuild_id);
@ -73,7 +73,7 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
int ret;
ret = filename__snprintf_build_id(name, sbuild_id, sizeof(sbuild_id));
if (ret != sizeof(sbuild_id))
if (ret + 1 != sizeof(sbuild_id))
return ret < 0 ? ret : -EINVAL;
return fprintf(fp, "%s\n", sbuild_id);

View File

@ -12,41 +12,45 @@
*/
#include <errno.h>
#include <inttypes.h>
#include <asm/bug.h>
#include <linux/compiler.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/stringify.h>
#include <linux/zalloc.h>
#include <asm/bug.h>
#include <sys/param.h>
#include "debug.h"
#include "builtin.h"
#include <dwarf-regs.h>
#include <perf/cpumap.h>
#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "map_symbol.h"
#include "mem-events.h"
#include "session.h"
#include "hist.h"
#include "sort.h"
#include "tool.h"
#include "builtin.h"
#include "cacheline.h"
#include "data.h"
#include "debug.h"
#include "event.h"
#include "evlist.h"
#include "evsel.h"
#include "ui/browsers/hists.h"
#include "thread.h"
#include "mem2node.h"
#include "hist.h"
#include "map_symbol.h"
#include "mem-events.h"
#include "mem-info.h"
#include "symbol.h"
#include "ui/ui.h"
#include "ui/progress.h"
#include "mem2node.h"
#include "pmus.h"
#include "session.h"
#include "sort.h"
#include "string2.h"
#include "util/util.h"
#include "util/symbol.h"
#include "symbol.h"
#include "thread.h"
#include "tool.h"
#include "ui/browsers/hists.h"
#include "ui/progress.h"
#include "ui/ui.h"
#include "util/annotate.h"
#include "util/symbol.h"
#include "util/util.h"
struct c2c_hists {
struct hists hists;
@ -180,7 +184,8 @@ static void c2c_he_free(void *he)
c2c_he = container_of(he, struct c2c_hist_entry, he);
if (c2c_he->hists) {
hists__delete_entries(&c2c_he->hists->hists);
hists__delete_all_entries(&c2c_he->hists->hists);
perf_hpp__reset_output_field(&c2c_he->hists->list);
zfree(&c2c_he->hists);
}
@ -221,6 +226,8 @@ he__get_c2c_hists(struct hist_entry *he,
ret = c2c_hists__init(hists, sort, nr_header_lines, env);
if (ret) {
perf_hpp__reset_output_field(&hists->list);
c2c_he->hists = NULL;
free(hists);
return NULL;
}
@ -241,6 +248,10 @@ static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,
"WARNING: no sample cpu value"))
return;
/* cpuset bitmap has c2c.cpus_cnt bits from env->nr_cpus_avail */
if (sample->cpu >= (unsigned int)c2c.cpus_cnt)
return;
__set_bit(sample->cpu, c2c_he->cpuset);
}
@ -258,6 +269,10 @@ static void c2c_he__set_node(struct c2c_hist_entry *c2c_he,
if (WARN_ONCE(node < 0, "WARNING: failed to find node\n"))
return;
/* nodeset bitmap has c2c.nodes_cnt bits from env->nr_numa_nodes */
if (node >= c2c.nodes_cnt)
return;
__set_bit(node, c2c_he->nodeset);
if (c2c_he->paddr != sample->phys_addr) {
@ -314,9 +329,9 @@ static void perf_c2c__evsel_hists_inc_stats(struct evsel *evsel,
static int process_sample_event(const struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct evsel *evsel = sample->evsel;
struct c2c_hists *c2c_hists = &c2c.hists;
struct c2c_hist_entry *c2c_he;
struct c2c_stats stats = { .nr_entries = 0, };
@ -328,8 +343,9 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
addr_location__init(&al);
if (machine__resolve(machine, &al, sample) < 0) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
ret = -1;
goto out;
}
@ -339,7 +355,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
cursor = get_tls_callchain_cursor();
ret = sample__resolve_callchain(sample, cursor, NULL,
evsel, &al, sysctl_perf_event_max_stack);
&al, sysctl_perf_event_max_stack);
if (ret)
goto out;
@ -371,7 +387,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
if (perf_c2c__has_annotation(NULL)) {
perf_c2c__evsel_hists_inc_stats(evsel, he, sample);
addr_map_symbol__inc_samples(mem_info__iaddr(mi), sample, evsel);
addr_map_symbol__inc_samples(mem_info__iaddr(mi), sample);
}
ret = hist_entry__append_callchain(he, sample);
@ -386,7 +402,12 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
* Doing node stats only for single callchain data.
*/
int cpu = sample->cpu == (unsigned int) -1 ? 0 : sample->cpu;
int node = c2c.cpu2node[cpu];
int node;
/* cpu2node[] has c2c.cpus_cnt entries; large u32 wraps signed negative */
if (cpu < 0 || cpu >= c2c.cpus_cnt)
cpu = 0;
node = c2c.cpu2node[cpu];
c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2, machine->env);
if (!c2c_hists) {
@ -405,7 +426,9 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
c2c_he = container_of(he, struct c2c_hist_entry, he);
c2c_add_stats(&c2c_he->stats, &stats);
c2c_add_stats(&c2c_hists->stats, &stats);
c2c_add_stats(&c2c_he->node_stats[node], &stats);
/* node_stats[] has c2c.nodes_cnt entries */
if (node >= 0 && node < c2c.nodes_cnt)
c2c_add_stats(&c2c_he->node_stats[node], &stats);
compute_stats(c2c_he, &stats, sample->weight);
@ -2351,6 +2374,10 @@ static int setup_nodes(struct perf_session *session)
nodes[node] = set;
perf_cpu_map__for_each_cpu_skip_any(cpu, idx, map) {
/* topology CPU IDs from perf.data may exceed nr_cpus_avail */
if (cpu.cpu < 0 || cpu.cpu >= c2c.cpus_cnt)
continue;
__set_bit(cpu.cpu, set);
if (WARN_ONCE(cpu2node[cpu.cpu] != -1, "node/cpu topology bug"))
@ -3202,7 +3229,7 @@ static int perf_c2c__report(int argc, const char **argv)
* default display type.
*/
if (!display) {
if (!strcmp(perf_env__arch(env), "arm64"))
if (perf_env__e_machine(env, /*e_flags=*/NULL) == EM_AARCH64)
display = "peer";
else
display = "tot";

View File

@ -43,7 +43,7 @@ struct feature_status supported_features[] = {
FEATURE_STATUS("dwarf_getlocations", HAVE_LIBDW_SUPPORT),
FEATURE_STATUS("dwarf-unwind", HAVE_DWARF_UNWIND_SUPPORT),
FEATURE_STATUS_TIP("libbfd", HAVE_LIBBFD_SUPPORT, "Deprecated, license incompatibility, use BUILD_NONDISTRO=1 and install binutils-dev[el]"),
FEATURE_STATUS("libbabeltrace", HAVE_LIBBABELTRACE_SUPPORT),
FEATURE_STATUS("babeltrace2-ctf-writer", HAVE_BABELTRACE2_CTF_WRITER_SUPPORT),
FEATURE_STATUS("libbpf-strings", HAVE_LIBBPF_STRINGS_SUPPORT),
FEATURE_STATUS("libcapstone", HAVE_LIBCAPSTONE_SUPPORT),
FEATURE_STATUS("libdw-dwarf-unwind", HAVE_LIBDW_SUPPORT),

View File

@ -40,10 +40,8 @@ static const struct option data_options[] = {
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
OPT_STRING('i', "input", &input_name, "file", "input file name"),
OPT_STRING(0, "to-json", &to_json, NULL, "Convert to JSON format"),
#ifdef HAVE_LIBBABELTRACE_SUPPORT
OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"),
OPT_BOOLEAN(0, "tod", &opts.tod, "Convert time to wall clock time"),
#endif
OPT_BOOLEAN('f', "force", &opts.force, "don't complain, do it"),
OPT_BOOLEAN(0, "all", &opts.all, "Convert all events"),
OPT_STRING(0, "time", &opts.time_str, "str",
@ -65,29 +63,21 @@ static int cmd_data_convert(int argc, const char **argv)
pr_err("You cannot specify both --to-ctf and --to-json.\n");
return -1;
}
#ifdef HAVE_LIBBABELTRACE_SUPPORT
if (!to_json && !to_ctf) {
pr_err("You must specify one of --to-ctf or --to-json.\n");
return -1;
}
#else
if (!to_json) {
pr_err("You must specify --to-json.\n");
return -1;
}
#endif
if (to_json)
return bt_convert__perf2json(input_name, to_json, &opts);
if (to_ctf) {
#if defined(HAVE_LIBBABELTRACE_SUPPORT) && defined(HAVE_LIBTRACEEVENT)
#if defined(HAVE_BABELTRACE2_CTF_WRITER_SUPPORT) && defined(HAVE_LIBTRACEEVENT)
return bt_convert__perf2ctf(input_name, to_ctf, &opts);
#else
pr_err("The libbabeltrace support is not compiled in. perf should be "
"compiled with environment variables LIBBABELTRACE=1 and "
"LIBBABELTRACE_DIR=/path/to/libbabeltrace/.\n"
"Check also if libbtraceevent devel files are available.\n");
pr_err("The babeltrace2 ctf support is not compiled in. Ensure you have both\n"
"libbabeltrace2-dev[el] and libtraceevent-dev[el] installed or set\n"
"PKG_CONFIG_PATH to find a local installation of those libraries.\n");
return -1;
#endif
}

View File

@ -390,14 +390,13 @@ static struct hist_entry_ops block_hist_ops = {
static int diff__process_sample_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct perf_diff *pdiff = container_of(tool, struct perf_diff, tool);
struct addr_location al;
struct evsel *evsel = sample->evsel;
struct hists *hists = evsel__hists(evsel);
struct hist_entry_iter iter = {
.evsel = evsel,
.sample = sample,
.ops = &hist_iter_normal,
};
@ -410,13 +409,15 @@ static int diff__process_sample_event(const struct perf_tool *tool,
addr_location__init(&al);
if (machine__resolve(machine, &al, sample) < 0) {
pr_warning("problem processing %d event, skipping it.\n",
event->header.type);
pr_warning("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
ret = -1;
goto out;
}
if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) {
if (cpu_list && (sample->cpu >= MAX_NR_CPUS ||
!test_bit(sample->cpu, cpu_bitmap))) {
ret = 0;
goto out;
}
@ -431,13 +432,14 @@ static int diff__process_sample_event(const struct perf_tool *tool,
}
hist__account_cycles(sample->branch_stack, &al, sample,
false, NULL, evsel);
/*nonany_branch_mode=*/false, /*total_cycles=*/NULL);
break;
case COMPUTE_STREAM:
if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH,
NULL)) {
pr_debug("problem adding hist entry, skipping event\n");
pr_debug("problem adding hist entry at offset %#" PRIx64 ", skipping event\n",
sample->file_offset);
goto out;
}
break;

View File

@ -8,6 +8,7 @@
*/
#include "builtin.h"
#include "util/aslr.h"
#include "util/color.h"
#include "util/dso.h"
#include "util/vdso.h"
@ -24,8 +25,10 @@
#include "util/string2.h"
#include "util/symbol.h"
#include "util/synthetic-events.h"
#include "util/pmus.h"
#include "util/thread.h"
#include "util/namespaces.h"
#include "util/unwind.h"
#include "util/util.h"
#include "util/tsc.h"
@ -123,6 +126,7 @@ struct perf_inject {
bool in_place_update_dry_run;
bool copy_kcore_dir;
bool convert_callchain;
bool aslr;
const char *input_name;
struct perf_data output;
u64 bytes_written;
@ -146,14 +150,12 @@ struct event_entry {
static int tool__inject_build_id(const struct perf_tool *tool,
struct perf_sample *sample,
struct machine *machine,
const struct evsel *evsel,
__u16 misc,
const char *filename,
struct dso *dso, u32 flags);
static int tool__inject_mmap2_build_id(const struct perf_tool *tool,
struct perf_sample *sample,
struct machine *machine,
const struct evsel *evsel,
__u16 misc,
__u32 pid, __u32 tid,
__u64 start, __u64 len, __u64 pgoff,
@ -215,23 +217,96 @@ static int perf_event__repipe_op4_synth(const struct perf_tool *tool,
return perf_event__repipe_synth(tool, event);
}
static int perf_event__repipe_synth_cb(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
struct machine *machine __maybe_unused)
{
return perf_event__repipe_synth(tool, event);
}
static int perf_event__repipe_attr(const struct perf_tool *tool,
union perf_event *event,
struct evlist **pevlist)
{
struct perf_inject *inject = container_of(tool, struct perf_inject,
tool);
struct perf_event_attr attr;
u32 raw_attr_size, attr_size;
size_t n_ids;
u64 *ids;
int ret;
union perf_event *aslr_event = NULL;
ret = perf_event__process_attr(tool, event, pevlist);
if (ret)
return ret;
/* If the output isn't a pipe then the attributes will be written as part of the header. */
if (!inject->output.is_pipe)
return 0;
if (inject->aslr) {
aslr_event = malloc(event->header.size);
if (!aslr_event)
return -ENOMEM;
memcpy(aslr_event, event, event->header.size);
aslr_tool__strip_attr_event(aslr_event, *pevlist);
event = aslr_event;
}
return perf_event__repipe_synth(tool, event);
/* If the output isn't a pipe then the attributes will be written as part of the header. */
if (!inject->output.is_pipe) {
ret = 0;
goto out;
}
if (!inject->itrace_synth_opts.set) {
ret = perf_event__repipe_synth(tool, event);
goto out;
}
if (event->header.size < sizeof(struct perf_event_header) + PERF_ATTR_SIZE_VER0) {
pr_err("Attribute event size %u is too small\n", event->header.size);
ret = -EINVAL;
goto out;
}
/*
* ABI0 pipe/inject events have attr.size == 0; default to
* PERF_ATTR_SIZE_VER0 (the ABI0 footprint) for the bounded
* copy and ID array position. Same pattern as
* perf_event__process_attr() in header.c.
*/
raw_attr_size = event->attr.attr.size;
attr_size = raw_attr_size ?: PERF_ATTR_SIZE_VER0;
if (raw_attr_size && (raw_attr_size < PERF_ATTR_SIZE_VER0 ||
raw_attr_size > event->header.size - sizeof(event->header))) {
pr_err("Attribute event size %u is too small for attr.size %u\n",
event->header.size, raw_attr_size);
ret = -EINVAL;
goto out;
}
memset(&attr, 0, sizeof(attr));
memcpy(&attr, &event->attr.attr,
min_t(size_t, sizeof(attr), attr_size));
n_ids = event->header.size - sizeof(event->header) - attr_size;
n_ids /= sizeof(u64);
ids = (void *)&event->attr.attr + attr_size;
attr.size = sizeof(struct perf_event_attr);
attr.sample_type &= ~PERF_SAMPLE_AUX;
if (inject->itrace_synth_opts.add_last_branch) {
attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX;
}
ret = perf_event__synthesize_attr(tool, &attr, (u32)n_ids, ids,
perf_event__repipe_synth_cb);
out:
free(aslr_event);
return ret;
}
static int perf_event__repipe_event_update(const struct perf_tool *tool,
@ -330,8 +405,8 @@ perf_inject__cut_auxtrace_sample(struct perf_inject *inject,
union perf_event *event,
struct perf_sample *sample)
{
size_t sz1 = sample->aux_sample.data - (void *)event;
size_t sz2 = event->header.size - sample->aux_sample.size - sz1;
size_t sz1 = sample->aux_sample.data - (void *)event - sizeof(u64);
size_t sz2 = event->header.size - sample->aux_sample.size - (sz1 + sizeof(u64));
union perf_event *ev;
if (inject->event_copy == NULL) {
@ -342,13 +417,12 @@ perf_inject__cut_auxtrace_sample(struct perf_inject *inject,
ev = (union perf_event *)inject->event_copy;
if (sz1 > event->header.size || sz2 > event->header.size ||
sz1 + sz2 > event->header.size ||
sz1 < sizeof(struct perf_event_header) + sizeof(u64))
sz1 < sizeof(struct perf_event_header))
return event;
memcpy(ev, event, sz1);
memcpy((void *)ev + sz1, (void *)event + event->header.size - sz2, sz2);
ev->header.size = sz1 + sz2;
((u64 *)((void *)ev + sz1))[-1] = 0;
return ev;
}
@ -356,26 +430,87 @@ perf_inject__cut_auxtrace_sample(struct perf_inject *inject,
typedef int (*inject_handler)(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine);
static int perf_event__repipe_sample(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct perf_inject *inject = container_of(tool, struct perf_inject,
tool);
struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
struct evsel *evsel = sample->evsel;
if (evsel && evsel->handler) {
if (evsel == NULL)
return perf_event__repipe_synth(tool, event);
if (evsel->handler) {
inject_handler f = evsel->handler;
return f(tool, event, sample, evsel, machine);
return f(tool, event, sample, machine);
}
build_id__mark_dso_hit(tool, event, sample, evsel, machine);
build_id__mark_dso_hit(tool, event, sample, machine);
if (inject->itrace_synth_opts.set && sample->aux_sample.size) {
if (inject->itrace_synth_opts.set &&
(inject->itrace_synth_opts.last_branch ||
inject->itrace_synth_opts.add_last_branch)) {
union perf_event *event_copy = (void *)inject->event_copy;
struct branch_stack dummy_bs = { .nr = 0, .hw_idx = 0 };
int err;
size_t sz;
u64 orig_type = evsel->core.attr.sample_type;
u64 orig_branch_type = evsel->core.attr.branch_sample_type;
struct branch_stack *orig_bs = sample->branch_stack;
if (event_copy == NULL) {
inject->event_copy = malloc(PERF_SAMPLE_MAX_SIZE);
if (!inject->event_copy)
return -ENOMEM;
event_copy = (void *)inject->event_copy;
}
if (!sample->branch_stack)
sample->branch_stack = &dummy_bs;
if (inject->itrace_synth_opts.add_last_branch) {
/* Temporarily add in type bits for synthesis. */
evsel->core.attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
evsel->core.attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX;
}
evsel->core.attr.sample_type &= ~PERF_SAMPLE_AUX;
sz = perf_event__sample_event_size(sample, evsel->core.attr.sample_type,
evsel->core.attr.read_format,
evsel->core.attr.branch_sample_type);
if (sz >= PERF_SAMPLE_MAX_SIZE) {
pr_err("Sample size %zu exceeds max size %d\n", sz, PERF_SAMPLE_MAX_SIZE);
evsel->core.attr.sample_type = orig_type;
evsel->core.attr.branch_sample_type = orig_branch_type;
sample->branch_stack = orig_bs;
return -EFAULT;
}
event_copy->header.type = PERF_RECORD_SAMPLE;
event_copy->header.misc = event->header.misc;
event_copy->header.size = sz;
err = perf_event__synthesize_sample(event_copy, evsel->core.attr.sample_type,
evsel->core.attr.read_format,
evsel->core.attr.branch_sample_type, sample);
evsel->core.attr.sample_type = orig_type;
evsel->core.attr.branch_sample_type = orig_branch_type;
sample->branch_stack = orig_bs;
if (err) {
pr_err("Failed to synthesize sample\n");
return err;
}
event = event_copy;
} else if (inject->itrace_synth_opts.set &&
(evsel->core.attr.sample_type & PERF_SAMPLE_AUX)) {
event = perf_inject__cut_auxtrace_sample(inject, event, sample);
if (IS_ERR(event))
return PTR_ERR(event);
@ -387,16 +522,16 @@ static int perf_event__repipe_sample(const struct perf_tool *tool,
static int perf_event__convert_sample_callchain(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
struct evsel *evsel = sample->evsel;
struct callchain_cursor *cursor = get_tls_callchain_cursor();
union perf_event *event_copy = (void *)inject->event_copy;
struct callchain_cursor_node *node;
struct thread *thread;
u64 sample_type = evsel->core.attr.sample_type;
u32 sample_size = event->header.size;
size_t sz;
u64 i, k;
int ret;
@ -418,7 +553,7 @@ static int perf_event__convert_sample_callchain(const struct perf_tool *tool,
goto out;
/* this will parse DWARF using stack and register data */
ret = thread__resolve_callchain(thread, cursor, evsel, sample,
ret = thread__resolve_callchain(thread, cursor, sample,
/*parent=*/NULL, /*root_al=*/NULL,
PERF_MAX_STACK_DEPTH);
thread__put(thread);
@ -438,12 +573,11 @@ static int perf_event__convert_sample_callchain(const struct perf_tool *tool,
node = cursor->first;
for (k = 0; k < cursor->nr && i < PERF_MAX_STACK_DEPTH; k++) {
if (machine__kernel_ip(machine, node->ip))
/* kernel IPs were added already */;
else if (node->ms.sym && node->ms.sym->inlined)
/* we can't handle inlined callchains */;
else
if (!(machine->single_address_space &&
machine__kernel_ip(machine, node->ip)) &&
!(node->ms.sym && symbol__inlined(node->ms.sym))) {
inject->raw_callchain->ips[i++] = node->ip;
}
node = node->next;
}
@ -454,17 +588,25 @@ static int perf_event__convert_sample_callchain(const struct perf_tool *tool,
out:
memcpy(event_copy, event, sizeof(event->header));
/* adjust sample size for stack and regs */
sample_size -= sample->user_stack.size;
sample_size -= (hweight64(evsel->core.attr.sample_regs_user) + 1) * sizeof(u64);
sample_size += (sample->callchain->nr + 1) * sizeof(u64);
event_copy->header.size = sample_size;
/* remove sample_type {STACK,REGS}_USER for synthesize */
sample_type &= ~(PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER);
perf_event__synthesize_sample(event_copy, sample_type,
evsel->core.attr.read_format, sample);
sz = perf_event__sample_event_size(sample, sample_type,
evsel->core.attr.read_format,
evsel->core.attr.branch_sample_type);
if (sz >= PERF_SAMPLE_MAX_SIZE) {
pr_err("Sample size %zu exceeds max size %d\n", sz, PERF_SAMPLE_MAX_SIZE);
return -EFAULT;
}
event_copy->header.size = sz;
ret = perf_event__synthesize_sample(event_copy, sample_type,
evsel->core.attr.read_format,
evsel->core.attr.branch_sample_type, sample);
if (ret) {
pr_err("Failed to synthesize sample\n");
return ret;
}
return perf_event__repipe_synth(tool, event_copy);
}
@ -584,11 +726,12 @@ static int perf_event__repipe_common_mmap(const struct perf_tool *tool,
}
if (dso && !dso__hit(dso)) {
struct evsel *evsel = evlist__event2evsel(inject->session->evlist, event);
if (!sample->evsel)
sample->evsel = evlist__event2evsel(inject->session->evlist, event);
if (evsel) {
if (sample->evsel) {
dso__set_hit(dso);
tool__inject_build_id(tool, sample, machine, evsel,
tool__inject_build_id(tool, sample, machine,
/*misc=*/sample->cpumode,
filename, dso, flags);
}
@ -615,23 +758,26 @@ static int perf_event__repipe_common_mmap(const struct perf_tool *tool,
}
if ((inject->build_id_style == BID_RWS__MMAP2_BUILDID_ALL) &&
!(event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) {
struct evsel *evsel = evlist__event2evsel(inject->session->evlist, event);
struct evsel *saved_evsel = sample->evsel;
if (evsel && !dso_sought) {
sample->evsel = evlist__event2evsel(inject->session->evlist, event);
if (sample->evsel && !dso_sought) {
dso = findnew_dso(pid, tid, filename, dso_id, machine);
dso_sought = true;
}
if (evsel && dso &&
!tool__inject_mmap2_build_id(tool, sample, machine, evsel,
if (sample->evsel && dso &&
!tool__inject_mmap2_build_id(tool, sample, machine,
sample->cpumode | PERF_RECORD_MISC_MMAP_BUILD_ID,
pid, tid, start, len, pgoff,
dso,
prot, flags,
filename)) {
/* Injected mmap2 so no need to repipe. */
sample->evsel = saved_evsel;
dso__put(dso);
return 0;
}
sample->evsel = saved_evsel;
}
dso__put(dso);
if (inject->build_id_style == BID_RWS__MMAP2_BUILDID_LAZY)
@ -836,7 +982,6 @@ static bool perf_inject__lookup_known_build_id(struct perf_inject *inject,
static int tool__inject_build_id(const struct perf_tool *tool,
struct perf_sample *sample,
struct machine *machine,
const struct evsel *evsel,
__u16 misc,
const char *filename,
struct dso *dso, u32 flags)
@ -860,7 +1005,7 @@ static int tool__inject_build_id(const struct perf_tool *tool,
err = perf_event__synthesize_build_id(tool, sample, machine,
perf_event__repipe,
evsel, misc, dso__bid(dso),
misc, dso__bid(dso),
filename);
if (err) {
pr_err("Can't synthesize build_id event for %s\n", filename);
@ -873,7 +1018,6 @@ static int tool__inject_build_id(const struct perf_tool *tool,
static int tool__inject_mmap2_build_id(const struct perf_tool *tool,
struct perf_sample *sample,
struct machine *machine,
const struct evsel *evsel,
__u16 misc,
__u32 pid, __u32 tid,
__u64 start, __u64 len, __u64 pgoff,
@ -896,7 +1040,6 @@ static int tool__inject_mmap2_build_id(const struct perf_tool *tool,
err = perf_event__synthesize_mmap2_build_id(tool, sample, machine,
perf_event__repipe,
evsel,
misc, pid, tid,
start, len, pgoff,
dso__bid(dso),
@ -913,7 +1056,7 @@ static int mark_dso_hit(const struct perf_inject *inject,
const struct perf_tool *tool,
struct perf_sample *sample,
struct machine *machine,
const struct evsel *mmap_evsel,
struct evsel *mmap_evsel,
struct map *map, bool sample_in_dso)
{
struct dso *dso;
@ -941,9 +1084,13 @@ static int mark_dso_hit(const struct perf_inject *inject,
dso = map__dso(map);
if (inject->build_id_style == BID_RWS__INJECT_HEADER_LAZY) {
if (dso && !dso__hit(dso)) {
/*
* The sample is just read for identifiers which we want
* to match the for the event of the sample.
*/
dso__set_hit(dso);
tool__inject_build_id(tool, sample, machine,
mmap_evsel, misc, dso__long_name(dso), dso,
misc, dso__long_name(dso), dso,
map__flags(map));
}
} else if (inject->build_id_style == BID_RWS__MMAP2_BUILDID_LAZY) {
@ -951,11 +1098,13 @@ static int mark_dso_hit(const struct perf_inject *inject,
const struct build_id null_bid = { .size = 0 };
const struct build_id *bid = dso ? dso__bid(dso) : &null_bid;
const char *filename = dso ? dso__long_name(dso) : "";
struct evsel *saved_evsel = sample->evsel;
map__set_hit(map);
/* Creating a new mmap2 event which has an evsel for the mmap event. */
sample->evsel = mmap_evsel;
perf_event__synthesize_mmap2_build_id(tool, sample, machine,
perf_event__repipe,
mmap_evsel,
misc,
sample->pid, sample->tid,
map__start(map),
@ -965,6 +1114,7 @@ static int mark_dso_hit(const struct perf_inject *inject,
map__prot(map),
map__flags(map),
filename);
sample->evsel = saved_evsel;
}
}
return 0;
@ -975,7 +1125,7 @@ struct mark_dso_hit_args {
const struct perf_tool *tool;
struct perf_sample *sample;
struct machine *machine;
const struct evsel *mmap_evsel;
struct evsel *mmap_evsel;
};
static int mark_dso_hit_callback(struct callchain_cursor_node *node, void *data)
@ -987,10 +1137,8 @@ static int mark_dso_hit_callback(struct callchain_cursor_node *node, void *data)
args->mmap_evsel, map, /*sample_in_dso=*/false);
}
int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel __maybe_unused,
struct machine *machine)
static int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *event,
struct perf_sample *sample, struct machine *machine)
{
struct addr_location al;
struct thread *thread;
@ -1020,7 +1168,7 @@ int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *e
/*sample_in_dso=*/true);
}
sample__for_each_callchain_node(thread, evsel, sample, PERF_MAX_STACK_DEPTH,
sample__for_each_callchain_node(thread, sample, PERF_MAX_STACK_DEPTH,
/*symbols=*/false, mark_dso_hit_callback, &args);
thread__put(thread);
repipe:
@ -1032,7 +1180,6 @@ int perf_event__inject_buildid(const struct perf_tool *tool, union perf_event *e
static int perf_inject__sched_process_exit(const struct perf_tool *tool,
union perf_event *event __maybe_unused,
struct perf_sample *sample,
struct evsel *evsel __maybe_unused,
struct machine *machine __maybe_unused)
{
struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
@ -1052,13 +1199,12 @@ static int perf_inject__sched_process_exit(const struct perf_tool *tool,
static int perf_inject__sched_switch(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
struct event_entry *ent;
perf_inject__sched_process_exit(tool, event, sample, evsel, machine);
perf_inject__sched_process_exit(tool, event, sample, machine);
ent = malloc(event->header.size + sizeof(struct event_entry));
if (ent == NULL) {
@ -1077,14 +1223,14 @@ static int perf_inject__sched_switch(const struct perf_tool *tool,
static int perf_inject__sched_stat(const struct perf_tool *tool,
union perf_event *event __maybe_unused,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct event_entry *ent;
union perf_event *event_sw;
struct perf_sample sample_sw;
struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
u32 pid = evsel__intval(evsel, sample, "pid");
struct evsel *evsel = sample->evsel;
u32 pid = perf_sample__intval(sample, "pid");
int ret;
list_for_each_entry(ent, &inject->samples, node) {
@ -1100,8 +1246,9 @@ static int perf_inject__sched_stat(const struct perf_tool *tool,
sample_sw.period = sample->period;
sample_sw.time = sample->time;
perf_event__synthesize_sample(event_sw, evsel->core.attr.sample_type,
evsel->core.attr.read_format, &sample_sw);
build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
evsel->core.attr.read_format,
evsel->core.attr.branch_sample_type, &sample_sw);
build_id__mark_dso_hit(tool, event_sw, &sample_sw, machine);
ret = perf_event__repipe(tool, event_sw, &sample_sw, machine);
perf_sample__exit(&sample_sw);
return ret;
@ -1448,7 +1595,7 @@ static int synthesize_build_id(struct perf_inject *inject, struct dso *dso, pid_
dso__set_hit(dso);
return perf_event__synthesize_build_id(&inject->tool, &synth_sample, machine,
process_build_id, inject__mmap_evsel(inject),
process_build_id,
/*misc=*/synth_sample.cpumode,
dso__bid(dso), dso__long_name(dso));
}
@ -2010,7 +2157,6 @@ static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char *
static int drop_sample(const struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct evsel *evsel __maybe_unused,
struct machine *machine __maybe_unused)
{
return 0;
@ -2434,12 +2580,27 @@ static int __cmd_inject(struct perf_inject *inject)
* synthesized hardware events, so clear the feature flag.
*/
if (inject->itrace_synth_opts.set) {
struct evsel *evsel;
perf_header__clear_feat(&session->header,
HEADER_AUXTRACE);
if (inject->itrace_synth_opts.last_branch ||
inject->itrace_synth_opts.add_last_branch)
evlist__for_each_entry(session->evlist, evsel) {
evsel->core.attr.sample_type &= ~PERF_SAMPLE_AUX;
}
if (inject->itrace_synth_opts.add_last_branch) {
perf_header__set_feat(&session->header,
HEADER_BRANCH_STACK);
evlist__for_each_entry(session->evlist, evsel) {
evsel->core.attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
if (evsel->core.attr.size < PERF_ATTR_SIZE_VER2)
evsel->core.attr.size = PERF_ATTR_SIZE_VER2;
evsel->core.attr.branch_sample_type |=
PERF_SAMPLE_BRANCH_HW_INDEX;
}
}
}
/*
@ -2458,6 +2619,9 @@ static int __cmd_inject(struct perf_inject *inject)
}
}
if (inject->aslr)
aslr_tool__strip_evlist(inject->session->tool, session->evlist);
session->header.data_offset = output_data_offset;
session->header.data_size = inject->bytes_written;
perf_session__inject_header(session, session->evlist, fd, &inj_fc.fc,
@ -2562,8 +2726,13 @@ int cmd_inject(int argc, const char **argv)
OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
"guest mount directory under which every guest os"
" instance has a subdir"),
OPT_CALLBACK(0, "unwind-style", NULL, "unwind style",
"unwind styles (libdw,libunwind)",
unwind__option),
OPT_BOOLEAN(0, "convert-callchain", &inject.convert_callchain,
"Generate callchains using DWARF and drop register/stack data"),
OPT_BOOLEAN(0, "aslr", &inject.aslr,
"Remap virtual memory addresses similar to ASLR"),
OPT_END()
};
const char * const inject_usage[] = {
@ -2571,6 +2740,7 @@ int cmd_inject(int argc, const char **argv)
NULL
};
bool ordered_events;
struct perf_tool *tool = &inject.tool;
if (!inject.itrace_synth_opts.set) {
/* Disable eager loading of kernel symbols that adds overhead to perf inject. */
@ -2591,6 +2761,11 @@ int cmd_inject(int argc, const char **argv)
if (argc)
usage_with_options(inject_usage, options);
if (inject.aslr && inject.convert_callchain) {
pr_err("Error: --aslr and --convert-callchain are mutually exclusive features.\n");
return -EINVAL;
}
if (inject.strip && !inject.itrace_synth_opts.set) {
pr_err("--strip option requires --itrace option\n");
return -1;
@ -2684,18 +2859,39 @@ int cmd_inject(int argc, const char **argv)
inject.tool.schedstat_domain = perf_event__repipe_op2_synth;
inject.tool.dont_split_sample_group = true;
inject.tool.merge_deferred_callchains = false;
inject.session = __perf_session__new(&data, &inject.tool,
if (inject.aslr) {
tool = aslr_tool__new(&inject.tool);
if (!tool) {
ret = -ENOMEM;
goto out_close_output;
}
}
inject.session = __perf_session__new(&data, tool,
/*trace_event_repipe=*/inject.output.is_pipe,
/*host_env=*/NULL);
if (IS_ERR(inject.session)) {
ret = PTR_ERR(inject.session);
if (inject.aslr)
aslr_tool__delete(tool);
goto out_close_output;
}
if (zstd_init(&(inject.session->zstd_data), 0) < 0)
pr_warning("Decompression initialization failed.\n");
if (inject.aslr) {
struct evsel *evsel;
evlist__for_each_entry(inject.session->evlist, evsel) {
ret = aslr_tool__cache_orig_attrs(tool, evsel);
if (ret) {
pr_err("Failed to cache original attributes: %d\n", ret);
goto out_delete;
}
}
}
/* Save original section info before feature bits change */
ret = save_section_info(&inject);
if (ret)
@ -2714,10 +2910,17 @@ int cmd_inject(int argc, const char **argv)
* the input.
*/
if (!data.is_pipe) {
if (inject.aslr)
aslr_tool__strip_evlist(tool, inject.session->evlist);
ret = perf_event__synthesize_for_pipe(&inject.tool,
inject.session,
&inject.output,
perf_event__repipe);
if (inject.aslr)
aslr_tool__restore_evlist(tool, inject.session->evlist);
if (ret < 0)
goto out_delete;
}
@ -2789,6 +2992,8 @@ int cmd_inject(int argc, const char **argv)
strlist__delete(inject.known_build_ids);
zstd_fini(&(inject.session->zstd_data));
perf_session__delete(inject.session);
if (inject.aslr)
aslr_tool__delete(tool);
out_close_output:
if (!inject.in_place_update)
perf_data__close(&inject.output);

View File

@ -22,6 +22,7 @@
#include "util/cpumap.h"
#include "util/debug.h"
#include "util/event.h"
#include "util/string2.h"
#include "util/util.h"
@ -171,12 +172,12 @@ static int insert_caller_stat(unsigned long call_site,
return 0;
}
static int evsel__process_alloc_event(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_alloc_event(struct perf_sample *sample)
{
unsigned long ptr = evsel__intval(evsel, sample, "ptr"),
call_site = evsel__intval(evsel, sample, "call_site");
int bytes_req = evsel__intval(evsel, sample, "bytes_req"),
bytes_alloc = evsel__intval(evsel, sample, "bytes_alloc");
unsigned long ptr = perf_sample__intval(sample, "ptr"),
call_site = perf_sample__intval(sample, "call_site");
int bytes_req = perf_sample__intval(sample, "bytes_req"),
bytes_alloc = perf_sample__intval(sample, "bytes_alloc");
if (insert_alloc_stat(call_site, ptr, bytes_req, bytes_alloc, sample->cpu) ||
insert_caller_stat(call_site, bytes_req, bytes_alloc))
@ -198,11 +199,11 @@ static int evsel__process_alloc_event(struct evsel *evsel, struct perf_sample *s
* If the tracepoint contains the field "node" the tool stats the
* cross allocation.
*/
if (evsel__field(evsel, "node")) {
if (evsel__field(sample->evsel, "node")) {
int node1, node2;
node1 = cpu__get_node((struct perf_cpu){.cpu = sample->cpu});
node2 = evsel__intval(evsel, sample, "node");
node2 = perf_sample__intval(sample, "node");
/*
* If the field "node" is NUMA_NO_NODE (-1), we don't take it
@ -243,9 +244,9 @@ static struct alloc_stat *search_alloc_stat(unsigned long ptr,
return NULL;
}
static int evsel__process_free_event(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_free_event(struct perf_sample *sample)
{
unsigned long ptr = evsel__intval(evsel, sample, "ptr");
unsigned long ptr = perf_sample__intval(sample, "ptr");
struct alloc_stat *s_alloc, *s_caller;
s_alloc = search_alloc_stat(ptr, 0, &root_alloc_stat, ptr_cmp);
@ -394,7 +395,7 @@ static int build_alloc_func_list(void)
* Find first non-memory allocation function from callchain.
* The allocation functions are in the 'alloc_func_list'.
*/
static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample)
static u64 find_callsite(struct perf_sample *sample)
{
struct addr_location al;
struct machine *machine = &kmem_session->machines.host;
@ -414,7 +415,7 @@ static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample)
if (cursor == NULL)
goto out;
sample__resolve_callchain(sample, cursor, NULL, evsel, &al, 16);
sample__resolve_callchain(sample, cursor, /*parent=*/NULL, &al, 16);
callchain_cursor_commit(cursor);
while (true) {
@ -751,8 +752,7 @@ static char *compact_gfp_string(unsigned long gfp_flags)
return NULL;
}
static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample,
unsigned int gfp_flags)
static int parse_gfp_flags(struct perf_sample *sample, unsigned int gfp_flags)
{
struct tep_record record = {
.cpu = sample->cpu,
@ -773,7 +773,7 @@ static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample,
}
trace_seq_init(&seq);
tp_format = evsel__tp_format(evsel);
tp_format = evsel__tp_format(sample->evsel);
if (tp_format)
tep_print_event(tp_format->tep, &seq, &record, "%s", TEP_PRINT_INFO);
@ -784,17 +784,21 @@ static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample,
new = realloc(gfps, (nr_gfps + 1) * sizeof(*gfps));
if (new == NULL)
return -ENOMEM;
goto err_out;
gfps = new;
new += nr_gfps++;
new += nr_gfps;
new->flags = gfp_flags;
new->human_readable = strdup(str + 10);
if (!new->human_readable)
goto err_out;
new->compact_str = compact_gfp_flags(str + 10);
if (!new->human_readable || !new->compact_str)
return -ENOMEM;
if (!new->compact_str) {
free(new->human_readable);
goto err_out;
}
nr_gfps++;
qsort(gfps, nr_gfps, sizeof(*gfps), gfpcmp);
}
@ -803,15 +807,17 @@ static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample,
trace_seq_destroy(&seq);
return 0;
err_out:
trace_seq_destroy(&seq);
return -ENOMEM;
}
static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_page_alloc_event(struct perf_sample *sample)
{
u64 page;
unsigned int order = evsel__intval(evsel, sample, "order");
unsigned int gfp_flags = evsel__intval(evsel, sample, "gfp_flags");
unsigned int migrate_type = evsel__intval(evsel, sample,
"migratetype");
unsigned int order = perf_sample__intval(sample, "order");
unsigned int gfp_flags = perf_sample__intval(sample, "gfp_flags");
unsigned int migrate_type = perf_sample__intval(sample, "migratetype");
u64 bytes = kmem_page_size << order;
u64 callsite;
struct page_stat *pstat;
@ -821,10 +827,20 @@ static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_samp
.migrate_type = migrate_type,
};
if (order >= MAX_PAGE_ORDER) {
pr_debug("Out-of-bounds order %u\n", order);
return -1;
}
if (migrate_type >= MAX_MIGRATE_TYPES) {
pr_debug("Out-of-bounds migratetype %u\n", migrate_type);
return -1;
}
if (use_pfn)
page = evsel__intval(evsel, sample, "pfn");
page = perf_sample__intval(sample, "pfn");
else
page = evsel__intval(evsel, sample, "page");
page = perf_sample__intval(sample, "page");
nr_page_allocs++;
total_page_alloc_bytes += bytes;
@ -836,10 +852,10 @@ static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_samp
return 0;
}
if (parse_gfp_flags(evsel, sample, gfp_flags) < 0)
if (parse_gfp_flags(sample, gfp_flags) < 0)
return -1;
callsite = find_callsite(evsel, sample);
callsite = find_callsite(sample);
/*
* This is to find the current page (with correct gfp flags and
@ -877,20 +893,25 @@ static int evsel__process_page_alloc_event(struct evsel *evsel, struct perf_samp
return 0;
}
static int evsel__process_page_free_event(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_page_free_event(struct perf_sample *sample)
{
u64 page;
unsigned int order = evsel__intval(evsel, sample, "order");
unsigned int order = perf_sample__intval(sample, "order");
u64 bytes = kmem_page_size << order;
struct page_stat *pstat;
struct page_stat this = {
.order = order,
};
if (order >= MAX_PAGE_ORDER) {
pr_debug("Out-of-bounds order %u\n", order);
return -1;
}
if (use_pfn)
page = evsel__intval(evsel, sample, "pfn");
page = perf_sample__intval(sample, "pfn");
else
page = evsel__intval(evsel, sample, "page");
page = perf_sample__intval(sample, "page");
nr_page_frees++;
total_page_free_bytes += bytes;
@ -954,33 +975,35 @@ static bool perf_kmem__skip_sample(struct perf_sample *sample)
return false;
}
typedef int (*tracepoint_handler)(struct evsel *evsel,
struct perf_sample *sample);
typedef int (*tracepoint_handler)(struct perf_sample *sample);
static int process_sample_event(const struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct evsel *evsel = sample->evsel;
int err = 0;
struct thread *thread = machine__findnew_thread(machine, sample->pid,
sample->tid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
return -1;
}
if (perf_kmem__skip_sample(sample))
if (perf_kmem__skip_sample(sample)) {
thread__put(thread);
return 0;
}
dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread__tid(thread));
if (evsel->handler != NULL) {
tracepoint_handler f = evsel->handler;
err = f(evsel, sample);
err = f(sample);
}
thread__put(thread);

View File

@ -22,6 +22,7 @@
#include "util/synthetic-events.h"
#include "util/top.h"
#include "util/data.h"
#include "util/event.h"
#include "util/ordered-events.h"
#include "util/kvm-stat.h"
#include "util/util.h"
@ -806,7 +807,6 @@ static bool update_kvm_event(struct perf_kvm_stat *kvm,
}
static bool is_child_event(struct perf_kvm_stat *kvm,
struct evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
@ -818,8 +818,8 @@ static bool is_child_event(struct perf_kvm_stat *kvm,
return false;
for (; child_ops->name; child_ops++) {
if (evsel__name_is(evsel, child_ops->name)) {
child_ops->get_key(evsel, sample, key);
if (evsel__name_is(sample->evsel, child_ops->name)) {
child_ops->get_key(sample, key);
return true;
}
}
@ -917,11 +917,10 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
static
struct vcpu_event_record *per_vcpu_record(struct thread *thread,
struct evsel *evsel,
struct perf_sample *sample)
{
/* Only kvm_entry records vcpu id. */
if (!thread__priv(thread) && kvm_entry_event(evsel)) {
if (!thread__priv(thread) && kvm_entry_event(sample->evsel)) {
struct vcpu_event_record *vcpu_record;
struct machine *machine = maps__machine(thread__maps(thread));
uint16_t e_machine = thread__e_machine(thread, machine, /*e_flags=*/NULL);
@ -932,7 +931,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
return NULL;
}
vcpu_record->vcpu_id = evsel__intval(evsel, sample, vcpu_id_str(e_machine));
vcpu_record->vcpu_id = perf_sample__intval(sample, vcpu_id_str(e_machine));
thread__set_priv(thread, vcpu_record);
}
@ -941,14 +940,13 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
static bool handle_kvm_event(struct perf_kvm_stat *kvm,
struct thread *thread,
struct evsel *evsel,
struct perf_sample *sample)
{
struct vcpu_event_record *vcpu_record;
struct event_key key = { .key = INVALID_KEY,
.exit_reasons = kvm->exit_reasons };
vcpu_record = per_vcpu_record(thread, evsel, sample);
vcpu_record = per_vcpu_record(thread, sample);
if (!vcpu_record)
return true;
@ -957,13 +955,13 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm,
(kvm->trace_vcpu != vcpu_record->vcpu_id))
return true;
if (kvm->events_ops->is_begin_event(evsel, sample, &key))
if (kvm->events_ops->is_begin_event(sample, &key))
return handle_begin_event(kvm, vcpu_record, &key, sample);
if (is_child_event(kvm, evsel, sample, &key))
if (is_child_event(kvm, sample, &key))
return handle_child_event(kvm, vcpu_record, &key, sample);
if (kvm->events_ops->is_end_event(evsel, sample, &key))
if (kvm->events_ops->is_end_event(sample, &key))
return handle_end_event(kvm, vcpu_record, &key, sample);
return true;
@ -1133,7 +1131,6 @@ static bool skip_sample(struct perf_kvm_stat *kvm,
static int process_sample_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
int err = 0;
@ -1145,18 +1142,20 @@ static int process_sample_event(const struct perf_tool *tool,
return 0;
if (machine__resolve(machine, &kvm->al, sample) < 0) {
pr_warning("Fail to resolve address location, skip sample.\n");
pr_warning("WARNING: at offset %#" PRIx64 ": fail to resolve address location, skipping sample\n",
sample->file_offset);
return 0;
}
thread = machine__findnew_thread(machine, sample->pid, sample->tid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
return -1;
}
if (!handle_kvm_event(kvm, thread, evsel, sample))
if (!handle_kvm_event(kvm, thread, sample))
err = -1;
thread__put(thread);

View File

@ -9,6 +9,7 @@
#include "perf.h"
#include "util/data.h"
#include "util/event.h"
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/header.h"
@ -323,8 +324,8 @@ static struct kwork_work *work_search(struct rb_root_cached *root,
else if (cmp < 0)
node = node->rb_right;
else {
if (work->name == NULL)
work->name = key->name;
if (work->name == NULL && key->name != NULL)
work->name = strdup(key->name);
return work;
}
}
@ -371,11 +372,54 @@ static struct kwork_work *work_new(struct kwork_work *key)
work->id = key->id;
work->cpu = key->cpu;
work->name = key->name;
work->name = key->name ? strdup(key->name) : NULL;
work->class = key->class;
return work;
}
static void work_delete(struct kwork_work *work)
{
if (work) {
work_exit(work);
free(work);
}
}
static void kwork_work__free_root(struct rb_root_cached *root)
{
struct rb_node *next;
struct kwork_work *work;
while ((next = rb_first_cached(root))) {
work = rb_entry(next, struct kwork_work, node);
rb_erase_cached(next, root);
work_delete(work);
}
}
static void perf_kwork__exit(struct perf_kwork *kwork)
{
struct kwork_class *class;
struct kwork_atom_page *page, *tmp_page;
list_for_each_entry(class, &kwork->class_list, list) {
kwork_work__free_root(&class->work_root);
}
kwork_work__free_root(&kwork->sorted_work_root);
list_for_each_entry_safe(page, tmp_page, &kwork->atom_page_list, list) {
list_del_init(&page->list);
free(page);
}
INIT_LIST_HEAD(&kwork->class_list);
INIT_LIST_HEAD(&kwork->atom_page_list);
INIT_LIST_HEAD(&kwork->sort_list);
INIT_LIST_HEAD(&kwork->cmp_id);
}
static struct kwork_work *work_findnew(struct rb_root_cached *root,
struct kwork_work *key,
struct list_head *sort_list)
@ -424,7 +468,9 @@ static bool profile_event_match(struct perf_kwork *kwork,
u64 time = sample->time;
struct perf_time_interval *ptime = &kwork->ptime;
if ((kwork->cpu_list != NULL) && !test_bit(cpu, kwork->cpu_bitmap))
/* Guard test_bit: cpu == -1 (absent PERF_SAMPLE_CPU) would index past the bitmap */
if ((kwork->cpu_list != NULL) &&
((unsigned int)cpu >= MAX_NR_CPUS || !test_bit(cpu, kwork->cpu_bitmap)))
return false;
if (((ptime->start != 0) && (ptime->start > time)) ||
@ -448,31 +494,34 @@ static int work_push_atom(struct perf_kwork *kwork,
struct kwork_class *class,
enum kwork_trace_type src_type,
enum kwork_trace_type dst_type,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine,
struct kwork_work **ret_work,
bool overwrite)
{
struct kwork_atom *atom, *dst_atom, *last_atom;
struct kwork_atom *atom = NULL, *dst_atom, *last_atom;
struct kwork_work *work, key;
int ret = 0;
BUG_ON(class->work_init == NULL);
class->work_init(kwork, class, &key, src_type, evsel, sample, machine);
class->work_init(kwork, class, &key, src_type, sample, machine);
atom = atom_new(kwork, sample);
if (atom == NULL)
return -1;
if (atom == NULL) {
ret = -1;
goto out;
}
work = work_findnew(&class->work_root, &key, &kwork->cmp_id);
if (work == NULL) {
atom_free(atom);
return -1;
ret = -1;
goto out;
}
if (!profile_event_match(kwork, work, sample)) {
atom_free(atom);
return 0;
goto out;
}
if (dst_type < KWORK_TRACE_MAX) {
@ -499,39 +548,39 @@ static int work_push_atom(struct perf_kwork *kwork,
}
list_add_tail(&atom->list, &work->atom_list[src_type]);
return 0;
out:
work_exit(&key);
return ret;
}
static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork,
struct kwork_class *class,
enum kwork_trace_type src_type,
enum kwork_trace_type dst_type,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine,
struct kwork_work **ret_work)
{
struct kwork_atom *atom, *src_atom;
struct kwork_atom *atom = NULL, *src_atom;
struct kwork_work *work, key;
BUG_ON(class->work_init == NULL);
class->work_init(kwork, class, &key, src_type, evsel, sample, machine);
class->work_init(kwork, class, &key, src_type, sample, machine);
work = work_findnew(&class->work_root, &key, &kwork->cmp_id);
if (ret_work != NULL)
*ret_work = work;
if (work == NULL)
return NULL;
goto out;
if (!profile_event_match(kwork, work, sample))
return NULL;
goto out;
atom = list_last_entry_or_null(&work->atom_list[dst_type],
struct kwork_atom, list);
if (atom != NULL)
return atom;
goto out;
src_atom = atom_new(kwork, sample);
if (src_atom != NULL)
@ -540,8 +589,9 @@ static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork,
if (ret_work != NULL)
*ret_work = NULL;
}
return NULL;
out:
work_exit(&key);
return atom;
}
static struct kwork_work *find_work_by_id(struct rb_root_cached *root,
@ -599,18 +649,16 @@ static void report_update_exit_event(struct kwork_work *work,
static int report_entry_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
return work_push_atom(kwork, class, KWORK_TRACE_ENTRY,
KWORK_TRACE_MAX, evsel, sample,
KWORK_TRACE_MAX, sample,
machine, NULL, true);
}
static int report_exit_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -618,7 +666,7 @@ static int report_exit_event(struct perf_kwork *kwork,
struct kwork_work *work = NULL;
atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
KWORK_TRACE_ENTRY, evsel, sample,
KWORK_TRACE_ENTRY, sample,
machine, &work);
if (work == NULL)
return -1;
@ -654,18 +702,16 @@ static void latency_update_entry_event(struct kwork_work *work,
static int latency_raise_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
return work_push_atom(kwork, class, KWORK_TRACE_RAISE,
KWORK_TRACE_MAX, evsel, sample,
KWORK_TRACE_MAX, sample,
machine, NULL, true);
}
static int latency_entry_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -673,7 +719,7 @@ static int latency_entry_event(struct perf_kwork *kwork,
struct kwork_work *work = NULL;
atom = work_pop_atom(kwork, class, KWORK_TRACE_ENTRY,
KWORK_TRACE_RAISE, evsel, sample,
KWORK_TRACE_RAISE, sample,
machine, &work);
if (work == NULL)
return -1;
@ -688,7 +734,6 @@ static int latency_entry_event(struct perf_kwork *kwork,
static void timehist_save_callchain(struct perf_kwork *kwork,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct symbol *sym;
@ -708,7 +753,7 @@ static void timehist_save_callchain(struct perf_kwork *kwork,
cursor = get_tls_callchain_cursor();
if (thread__resolve_callchain(thread, cursor, evsel, sample,
if (thread__resolve_callchain(thread, cursor, sample,
NULL, NULL, kwork->max_stack + 2) != 0) {
pr_debug("Failed to resolve callchain, skipping\n");
goto out_put;
@ -725,7 +770,7 @@ static void timehist_save_callchain(struct perf_kwork *kwork,
if (sym) {
if (!strcmp(sym->name, "__softirqentry_text_start") ||
!strcmp(sym->name, "__do_softirq"))
sym->ignore = 1;
symbol__set_ignore(sym, true);
}
callchain_cursor_advance(cursor);
@ -813,18 +858,16 @@ static void timehist_print_event(struct perf_kwork *kwork,
static int timehist_raise_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
return work_push_atom(kwork, class, KWORK_TRACE_RAISE,
KWORK_TRACE_MAX, evsel, sample,
KWORK_TRACE_MAX, sample,
machine, NULL, true);
}
static int timehist_entry_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -832,20 +875,19 @@ static int timehist_entry_event(struct perf_kwork *kwork,
struct kwork_work *work = NULL;
ret = work_push_atom(kwork, class, KWORK_TRACE_ENTRY,
KWORK_TRACE_RAISE, evsel, sample,
KWORK_TRACE_RAISE, sample,
machine, &work, true);
if (ret)
return ret;
if (work != NULL)
timehist_save_callchain(kwork, sample, evsel, machine);
timehist_save_callchain(kwork, sample, machine);
return 0;
}
static int timehist_exit_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -856,13 +898,14 @@ static int timehist_exit_event(struct perf_kwork *kwork,
addr_location__init(&al);
if (machine__resolve(machine, &al, sample) < 0) {
pr_debug("Problem processing event, skipping it\n");
pr_debug("problem processing event at offset %#" PRIx64 ", skipping it\n",
sample->file_offset);
ret = -1;
goto out;
}
atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
KWORK_TRACE_ENTRY, evsel, sample,
KWORK_TRACE_ENTRY, sample,
machine, &work);
if (work == NULL) {
ret = -1;
@ -896,18 +939,16 @@ static void top_update_runtime(struct kwork_work *work,
static int top_entry_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
return work_push_atom(kwork, class, KWORK_TRACE_ENTRY,
KWORK_TRACE_MAX, evsel, sample,
KWORK_TRACE_MAX, sample,
machine, NULL, true);
}
static int top_exit_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -916,7 +957,7 @@ static int top_exit_event(struct perf_kwork *kwork,
struct kwork_atom *atom;
atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
KWORK_TRACE_ENTRY, evsel, sample,
KWORK_TRACE_ENTRY, sample,
machine, &work);
if (!work)
return -1;
@ -937,7 +978,6 @@ static int top_exit_event(struct perf_kwork *kwork,
static int top_sched_switch_event(struct perf_kwork *kwork,
struct kwork_class *class,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -945,7 +985,7 @@ static int top_sched_switch_event(struct perf_kwork *kwork,
struct kwork_work *work;
atom = work_pop_atom(kwork, class, KWORK_TRACE_EXIT,
KWORK_TRACE_ENTRY, evsel, sample,
KWORK_TRACE_ENTRY, sample,
machine, &work);
if (!work)
return -1;
@ -955,12 +995,11 @@ static int top_sched_switch_event(struct perf_kwork *kwork,
atom_del(atom);
}
return top_entry_event(kwork, class, evsel, sample, machine);
return top_entry_event(kwork, class, sample, machine);
}
static struct kwork_class kwork_irq;
static int process_irq_handler_entry_event(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -968,12 +1007,11 @@ static int process_irq_handler_entry_event(const struct perf_tool *tool,
if (kwork->tp_handler->entry_event)
return kwork->tp_handler->entry_event(kwork, &kwork_irq,
evsel, sample, machine);
sample, machine);
return 0;
}
static int process_irq_handler_exit_event(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -981,7 +1019,7 @@ static int process_irq_handler_exit_event(const struct perf_tool *tool,
if (kwork->tp_handler->exit_event)
return kwork->tp_handler->exit_event(kwork, &kwork_irq,
evsel, sample, machine);
sample, machine);
return 0;
}
@ -1006,7 +1044,6 @@ static void irq_work_init(struct perf_kwork *kwork,
struct kwork_class *class,
struct kwork_work *work,
enum kwork_trace_type src_type __maybe_unused,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine __maybe_unused)
{
@ -1014,17 +1051,20 @@ static void irq_work_init(struct perf_kwork *kwork,
work->cpu = sample->cpu;
if (kwork->report == KWORK_REPORT_TOP) {
work->id = evsel__intval_common(evsel, sample, "common_pid");
work->id = perf_sample__intval_common(sample, "common_pid");
work->name = NULL;
} else {
work->id = evsel__intval(evsel, sample, "irq");
work->name = evsel__strval(evsel, sample, "name");
work->id = perf_sample__intval(sample, "irq");
work->name = strdup(perf_sample__strval(sample, "name") ?: "<unknown>");
}
}
static void irq_work_name(struct kwork_work *work, char *buf, int len)
{
snprintf(buf, len, "%s:%" PRIu64 "", work->name, work->id);
if (work->name != NULL)
snprintf(buf, len, "%s:%" PRIu64 "", work->name, work->id);
else
snprintf(buf, len, "%" PRIu64 "", work->id);
}
static struct kwork_class kwork_irq = {
@ -1039,7 +1079,6 @@ static struct kwork_class kwork_irq = {
static struct kwork_class kwork_softirq;
static int process_softirq_raise_event(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -1047,13 +1086,12 @@ static int process_softirq_raise_event(const struct perf_tool *tool,
if (kwork->tp_handler->raise_event)
return kwork->tp_handler->raise_event(kwork, &kwork_softirq,
evsel, sample, machine);
sample, machine);
return 0;
}
static int process_softirq_entry_event(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -1061,13 +1099,12 @@ static int process_softirq_entry_event(const struct perf_tool *tool,
if (kwork->tp_handler->entry_event)
return kwork->tp_handler->entry_event(kwork, &kwork_softirq,
evsel, sample, machine);
sample, machine);
return 0;
}
static int process_softirq_exit_event(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -1075,7 +1112,7 @@ static int process_softirq_exit_event(const struct perf_tool *tool,
if (kwork->tp_handler->exit_event)
return kwork->tp_handler->exit_event(kwork, &kwork_softirq,
evsel, sample, machine);
sample, machine);
return 0;
}
@ -1134,7 +1171,6 @@ static void softirq_work_init(struct perf_kwork *kwork,
struct kwork_class *class,
struct kwork_work *work,
enum kwork_trace_type src_type __maybe_unused,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine __maybe_unused)
{
@ -1144,18 +1180,21 @@ static void softirq_work_init(struct perf_kwork *kwork,
work->cpu = sample->cpu;
if (kwork->report == KWORK_REPORT_TOP) {
work->id = evsel__intval_common(evsel, sample, "common_pid");
work->id = perf_sample__intval_common(sample, "common_pid");
work->name = NULL;
} else {
num = evsel__intval(evsel, sample, "vec");
num = perf_sample__intval(sample, "vec");
work->id = num;
work->name = evsel__softirq_name(evsel, num);
work->name = evsel__softirq_name(sample->evsel, num);
}
}
static void softirq_work_name(struct kwork_work *work, char *buf, int len)
{
snprintf(buf, len, "(s)%s:%" PRIu64 "", work->name, work->id);
if (work->name != NULL)
snprintf(buf, len, "(s)%s:%" PRIu64 "", work->name, work->id);
else
snprintf(buf, len, "(s)%" PRIu64 "", work->id);
}
static struct kwork_class kwork_softirq = {
@ -1170,7 +1209,6 @@ static struct kwork_class kwork_softirq = {
static struct kwork_class kwork_workqueue;
static int process_workqueue_activate_work_event(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -1178,13 +1216,12 @@ static int process_workqueue_activate_work_event(const struct perf_tool *tool,
if (kwork->tp_handler->raise_event)
return kwork->tp_handler->raise_event(kwork, &kwork_workqueue,
evsel, sample, machine);
sample, machine);
return 0;
}
static int process_workqueue_execute_start_event(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -1192,13 +1229,12 @@ static int process_workqueue_execute_start_event(const struct perf_tool *tool,
if (kwork->tp_handler->entry_event)
return kwork->tp_handler->entry_event(kwork, &kwork_workqueue,
evsel, sample, machine);
sample, machine);
return 0;
}
static int process_workqueue_execute_end_event(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -1206,7 +1242,7 @@ static int process_workqueue_execute_end_event(const struct perf_tool *tool,
if (kwork->tp_handler->exit_event)
return kwork->tp_handler->exit_event(kwork, &kwork_workqueue,
evsel, sample, machine);
sample, machine);
return 0;
}
@ -1234,19 +1270,23 @@ static void workqueue_work_init(struct perf_kwork *kwork __maybe_unused,
struct kwork_class *class,
struct kwork_work *work,
enum kwork_trace_type src_type __maybe_unused,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
char *modp = NULL;
unsigned long long function_addr = evsel__intval(evsel,
sample, "function");
unsigned long long function_addr = perf_sample__intval(sample, "function");
work->class = class;
work->cpu = sample->cpu;
work->id = evsel__intval(evsel, sample, "work");
work->name = function_addr == 0 ? NULL :
machine__resolve_kernel_addr(machine, &function_addr, &modp);
work->id = perf_sample__intval(sample, "work");
work->name = NULL;
if (function_addr != 0) {
const char *name = machine__resolve_kernel_addr(machine, &function_addr, &modp);
if (name)
work->name = strdup(name);
}
}
static void workqueue_work_name(struct kwork_work *work, char *buf, int len)
@ -1269,7 +1309,6 @@ static struct kwork_class kwork_workqueue = {
static struct kwork_class kwork_sched;
static int process_sched_switch_event(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -1277,7 +1316,7 @@ static int process_sched_switch_event(const struct perf_tool *tool,
if (kwork->tp_handler->sched_switch_event)
return kwork->tp_handler->sched_switch_event(kwork, &kwork_sched,
evsel, sample, machine);
sample, machine);
return 0;
}
@ -1302,7 +1341,6 @@ static void sched_work_init(struct perf_kwork *kwork __maybe_unused,
struct kwork_class *class,
struct kwork_work *work,
enum kwork_trace_type src_type,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine __maybe_unused)
{
@ -1310,17 +1348,17 @@ static void sched_work_init(struct perf_kwork *kwork __maybe_unused,
work->cpu = sample->cpu;
if (src_type == KWORK_TRACE_EXIT) {
work->id = evsel__intval(evsel, sample, "prev_pid");
work->name = strdup(evsel__strval(evsel, sample, "prev_comm"));
work->id = perf_sample__intval(sample, "prev_pid");
work->name = strdup(perf_sample__strval(sample, "prev_comm") ?: "<unknown>");
} else if (src_type == KWORK_TRACE_ENTRY) {
work->id = evsel__intval(evsel, sample, "next_pid");
work->name = strdup(evsel__strval(evsel, sample, "next_comm"));
work->id = perf_sample__intval(sample, "next_pid");
work->name = strdup(perf_sample__strval(sample, "next_comm") ?: "<unknown>");
}
}
static void sched_work_name(struct kwork_work *work, char *buf, int len)
{
snprintf(buf, len, "%s", work->name);
snprintf(buf, len, "%s", work->name ?: "");
}
static struct kwork_class kwork_sched = {
@ -1948,22 +1986,21 @@ static int perf_kwork__report(struct perf_kwork *kwork)
}
typedef int (*tracepoint_handler)(const struct perf_tool *tool,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine);
static int perf_kwork__process_tracepoint_sample(const struct perf_tool *tool,
union perf_event *event __maybe_unused,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct evsel *evsel = sample->evsel;
int err = 0;
if (evsel->handler != NULL) {
tracepoint_handler f = evsel->handler;
err = f(tool, evsel, sample, machine);
err = f(tool, sample, machine);
}
return err;
@ -2008,7 +2045,18 @@ static void top_calc_total_runtime(struct perf_kwork *kwork)
next = rb_first_cached(&class->work_root);
while (next) {
work = rb_entry(next, struct kwork_work, node);
BUG_ON(work->cpu >= MAX_NR_CPUS);
/*
* work->cpu comes from sample->cpu which is -1 when
* PERF_SAMPLE_CPU is absent. As int that's -1, but as
* unsigned it exceeds MAX_NR_CPUS skip to avoid OOB
* on cpus_runtime[].
*/
/* Counted and reported in perf_kwork__top_report() */
if ((unsigned int)work->cpu >= MAX_NR_CPUS) {
stat->nr_skipped_cpu++;
next = rb_next(next);
continue;
}
stat->cpus_runtime[work->cpu].total += work->total_runtime;
stat->cpus_runtime[MAX_NR_CPUS].total += work->total_runtime;
next = rb_next(next);
@ -2020,7 +2068,8 @@ static void top_calc_idle_time(struct perf_kwork *kwork,
{
struct kwork_top_stat *stat = &kwork->top_stat;
if (work->id == 0) {
/* See comment in top_calc_total_runtime() */
if (work->id == 0 && (unsigned int)work->cpu < MAX_NR_CPUS) {
stat->cpus_runtime[work->cpu].idle += work->total_runtime;
stat->cpus_runtime[MAX_NR_CPUS].idle += work->total_runtime;
}
@ -2032,6 +2081,10 @@ static void top_calc_irq_runtime(struct perf_kwork *kwork,
{
struct kwork_top_stat *stat = &kwork->top_stat;
/* See comment in top_calc_total_runtime() */
if ((unsigned int)work->cpu >= MAX_NR_CPUS)
return;
if (type == KWORK_CLASS_IRQ) {
stat->cpus_runtime[work->cpu].irq += work->total_runtime;
stat->cpus_runtime[MAX_NR_CPUS].irq += work->total_runtime;
@ -2084,12 +2137,19 @@ static void top_calc_cpu_usage(struct perf_kwork *kwork)
if (work->total_runtime == 0)
goto next;
/* See comment in top_calc_total_runtime() */
if ((unsigned int)work->cpu >= MAX_NR_CPUS)
goto next;
__set_bit(work->cpu, stat->all_cpus_bitmap);
top_subtract_irq_runtime(kwork, work);
work->cpu_usage = work->total_runtime * 10000 /
stat->cpus_runtime[work->cpu].total;
/* Guard against division by zero if no runtime was accumulated */
if (stat->cpus_runtime[work->cpu].total) {
work->cpu_usage = work->total_runtime * 10000 /
stat->cpus_runtime[work->cpu].total;
}
top_calc_idle_time(kwork, work);
next:
@ -2102,7 +2162,8 @@ static void top_calc_load_runtime(struct perf_kwork *kwork,
{
struct kwork_top_stat *stat = &kwork->top_stat;
if (work->id != 0) {
/* See comment in top_calc_total_runtime() */
if (work->id != 0 && (unsigned int)work->cpu < MAX_NR_CPUS) {
stat->cpus_runtime[work->cpu].load += work->total_runtime;
stat->cpus_runtime[MAX_NR_CPUS].load += work->total_runtime;
}
@ -2128,8 +2189,10 @@ static void top_merge_tasks(struct perf_kwork *kwork)
rb_erase_cached(node, &class->work_root);
data = rb_entry(node, struct kwork_work, node);
if (!profile_name_match(kwork, data))
if (!profile_name_match(kwork, data)) {
work_delete(data);
continue;
}
cpu = data->cpu;
merged_work = find_work_by_id(&merged_root, data->id,
@ -2137,11 +2200,17 @@ static void top_merge_tasks(struct perf_kwork *kwork)
if (!merged_work) {
work_insert(&merged_root, data, &kwork->cmp_id);
} else {
if (merged_work->name == NULL && data->name != NULL)
merged_work->name = strdup(data->name);
merged_work->total_runtime += data->total_runtime;
merged_work->cpu_usage += data->cpu_usage;
}
top_calc_load_runtime(kwork, data);
if (merged_work)
work_delete(data);
}
work_sort(kwork, class, &merged_root);
@ -2170,6 +2239,13 @@ static void perf_kwork__top_report(struct perf_kwork *kwork)
next = rb_next(next);
}
if (kwork->top_stat.nr_skipped_cpu) {
printf(" Warning: %u work entries with invalid CPU were excluded from totals.\n"
" Task runtimes may appear inflated (IRQ time not subtracted).\n"
" Consider re-recording with PERF_SAMPLE_CPU enabled.\n",
kwork->top_stat.nr_skipped_cpu);
}
printf("\n");
}
@ -2286,7 +2362,7 @@ static void setup_event_list(struct perf_kwork *kwork,
static int perf_kwork__record(struct perf_kwork *kwork,
int argc, const char **argv)
{
const char **rec_argv;
const char **rec_argv, **to_free = NULL;
unsigned int rec_argc, i, j;
struct kwork_class *class;
int ret;
@ -2323,16 +2399,27 @@ static int perf_kwork__record(struct perf_kwork *kwork,
BUG_ON(i != rec_argc);
/* Save the pointers as the array will be mutated by cmd_record. */
to_free = calloc(rec_argc + 1, sizeof(char *));
if (to_free == NULL) {
ret = -ENOMEM;
goto EXIT;
}
pr_debug("record comm: ");
for (j = 0; j < rec_argc; j++)
for (j = 0; j < rec_argc; j++) {
pr_debug("%s ", rec_argv[j]);
to_free[j] = rec_argv[j];
}
pr_debug("\n");
ret = cmd_record(i, rec_argv);
EXIT:
for (i = 0; i < rec_argc; i++)
free((void *)rec_argv[i]);
free((void *)(to_free ? to_free[i] : rec_argv[i]));
free(to_free);
free(rec_argv);
return ret;
}
@ -2475,6 +2562,7 @@ int cmd_kwork(int argc, const char **argv)
const char *const kwork_subcommands[] = {
"record", "report", "latency", "timehist", "top", NULL
};
int ret = 0;
perf_tool__init(&kwork.tool, /*ordered_events=*/true);
kwork.tool.mmap = perf_event__process_mmap;
@ -2491,7 +2579,7 @@ int cmd_kwork(int argc, const char **argv)
if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) {
setup_event_list(&kwork, kwork_options, kwork_usage);
return perf_kwork__record(&kwork, argc, argv);
ret = perf_kwork__record(&kwork, argc, argv);
} else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) {
kwork.sort_order = default_report_sort_order;
if (argc > 1) {
@ -2502,7 +2590,7 @@ int cmd_kwork(int argc, const char **argv)
kwork.report = KWORK_REPORT_RUNTIME;
setup_sorting(&kwork, report_options, report_usage);
setup_event_list(&kwork, kwork_options, kwork_usage);
return perf_kwork__report(&kwork);
ret = perf_kwork__report(&kwork);
} else if (strlen(argv[0]) > 2 && strstarts("latency", argv[0])) {
kwork.sort_order = default_latency_sort_order;
if (argc > 1) {
@ -2513,7 +2601,7 @@ int cmd_kwork(int argc, const char **argv)
kwork.report = KWORK_REPORT_LATENCY;
setup_sorting(&kwork, latency_options, latency_usage);
setup_event_list(&kwork, kwork_options, kwork_usage);
return perf_kwork__report(&kwork);
ret = perf_kwork__report(&kwork);
} else if (strlen(argv[0]) > 2 && strstarts("timehist", argv[0])) {
if (argc > 1) {
argc = parse_options(argc, argv, timehist_options, timehist_usage, 0);
@ -2522,7 +2610,7 @@ int cmd_kwork(int argc, const char **argv)
}
kwork.report = KWORK_REPORT_TIMEHIST;
setup_event_list(&kwork, kwork_options, kwork_usage);
return perf_kwork__timehist(&kwork);
ret = perf_kwork__timehist(&kwork);
} else if (strlen(argv[0]) > 2 && strstarts("top", argv[0])) {
kwork.sort_order = default_top_sort_order;
if (argc > 1) {
@ -2535,12 +2623,14 @@ int cmd_kwork(int argc, const char **argv)
kwork.event_list_str = "sched, irq, softirq";
setup_event_list(&kwork, kwork_options, kwork_usage);
setup_sorting(&kwork, top_options, top_usage);
return perf_kwork__top(&kwork);
ret = perf_kwork__top(&kwork);
} else
usage_with_options(kwork_usage, kwork_options);
perf_kwork__exit(&kwork);
/* free usage string allocated by parse_options_subcommand */
free((void *)kwork_usage[0]);
return 0;
return ret;
}

View File

@ -21,6 +21,7 @@
#include "util/tracepoint.h"
#include "util/debug.h"
#include "util/event.h"
#include "util/session.h"
#include "util/tool.h"
#include "util/data.h"
@ -31,6 +32,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <math.h>
#include <limits.h>
@ -473,28 +475,22 @@ static struct lock_stat *pop_from_result(void)
struct trace_lock_handler {
/* it's used on CONFIG_LOCKDEP */
int (*acquire_event)(struct evsel *evsel,
struct perf_sample *sample);
int (*acquire_event)(struct perf_sample *sample);
/* it's used on CONFIG_LOCKDEP && CONFIG_LOCK_STAT */
int (*acquired_event)(struct evsel *evsel,
struct perf_sample *sample);
int (*acquired_event)(struct perf_sample *sample);
/* it's used on CONFIG_LOCKDEP && CONFIG_LOCK_STAT */
int (*contended_event)(struct evsel *evsel,
struct perf_sample *sample);
int (*contended_event)(struct perf_sample *sample);
/* it's used on CONFIG_LOCKDEP */
int (*release_event)(struct evsel *evsel,
struct perf_sample *sample);
int (*release_event)(struct perf_sample *sample);
/* it's used when CONFIG_LOCKDEP is off */
int (*contention_begin_event)(struct evsel *evsel,
struct perf_sample *sample);
int (*contention_begin_event)(struct perf_sample *sample);
/* it's used when CONFIG_LOCKDEP is off */
int (*contention_end_event)(struct evsel *evsel,
struct perf_sample *sample);
int (*contention_end_event)(struct perf_sample *sample);
};
static struct lock_seq_stat *get_seq(struct thread_stat *ts, u64 addr)
@ -551,27 +547,26 @@ static int get_key_by_aggr_mode_simple(u64 *key, u64 addr, u32 tid)
return 0;
}
static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample);
static u64 callchain_id(struct perf_sample *sample);
static int get_key_by_aggr_mode(u64 *key, u64 addr, struct evsel *evsel,
static int get_key_by_aggr_mode(u64 *key, u64 addr,
struct perf_sample *sample)
{
if (aggr_mode == LOCK_AGGR_CALLER) {
*key = callchain_id(evsel, sample);
*key = callchain_id(sample);
return 0;
}
return get_key_by_aggr_mode_simple(key, addr, sample->tid);
}
static int report_lock_acquire_event(struct evsel *evsel,
struct perf_sample *sample)
static int report_lock_acquire_event(struct perf_sample *sample)
{
struct lock_stat *ls;
struct thread_stat *ts;
struct lock_seq_stat *seq;
const char *name = evsel__strval(evsel, sample, "name");
u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
int flag = evsel__intval(evsel, sample, "flags");
const char *name = perf_sample__strval(sample, "name");
u64 addr = perf_sample__intval(sample, "lockdep_addr");
int flag = perf_sample__intval(sample, "flags");
u64 key;
int ret;
@ -638,15 +633,14 @@ static int report_lock_acquire_event(struct evsel *evsel,
return 0;
}
static int report_lock_acquired_event(struct evsel *evsel,
struct perf_sample *sample)
static int report_lock_acquired_event(struct perf_sample *sample)
{
struct lock_stat *ls;
struct thread_stat *ts;
struct lock_seq_stat *seq;
u64 contended_term;
const char *name = evsel__strval(evsel, sample, "name");
u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
const char *name = perf_sample__strval(sample, "name");
u64 addr = perf_sample__intval(sample, "lockdep_addr");
u64 key;
int ret;
@ -704,14 +698,13 @@ static int report_lock_acquired_event(struct evsel *evsel,
return 0;
}
static int report_lock_contended_event(struct evsel *evsel,
struct perf_sample *sample)
static int report_lock_contended_event(struct perf_sample *sample)
{
struct lock_stat *ls;
struct thread_stat *ts;
struct lock_seq_stat *seq;
const char *name = evsel__strval(evsel, sample, "name");
u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
const char *name = perf_sample__strval(sample, "name");
u64 addr = perf_sample__intval(sample, "lockdep_addr");
u64 key;
int ret;
@ -762,14 +755,13 @@ static int report_lock_contended_event(struct evsel *evsel,
return 0;
}
static int report_lock_release_event(struct evsel *evsel,
struct perf_sample *sample)
static int report_lock_release_event(struct perf_sample *sample)
{
struct lock_stat *ls;
struct thread_stat *ts;
struct lock_seq_stat *seq;
const char *name = evsel__strval(evsel, sample, "name");
u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
const char *name = perf_sample__strval(sample, "name");
u64 addr = perf_sample__intval(sample, "lockdep_addr");
u64 key;
int ret;
@ -841,7 +833,7 @@ static int get_symbol_name_offset(struct map *map, struct symbol *sym, u64 ip,
else
return strlcpy(buf, sym->name, size);
}
static int lock_contention_caller(struct evsel *evsel, struct perf_sample *sample,
static int lock_contention_caller(struct perf_sample *sample,
char *buf, int size)
{
struct thread *thread;
@ -862,7 +854,7 @@ static int lock_contention_caller(struct evsel *evsel, struct perf_sample *sampl
cursor = get_tls_callchain_cursor();
/* use caller function name from the callchain */
ret = thread__resolve_callchain(thread, cursor, evsel, sample,
ret = thread__resolve_callchain(thread, cursor, sample,
NULL, NULL, max_stack_depth);
if (ret != 0) {
thread__put(thread);
@ -896,7 +888,7 @@ static int lock_contention_caller(struct evsel *evsel, struct perf_sample *sampl
return -1;
}
static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample)
static u64 callchain_id(struct perf_sample *sample)
{
struct callchain_cursor *cursor;
struct machine *machine = &session->machines.host;
@ -911,7 +903,7 @@ static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample)
cursor = get_tls_callchain_cursor();
/* use caller function name from the callchain */
ret = thread__resolve_callchain(thread, cursor, evsel, sample,
ret = thread__resolve_callchain(thread, cursor, sample,
NULL, NULL, max_stack_depth);
thread__put(thread);
@ -948,9 +940,16 @@ static u64 *get_callstack(struct perf_sample *sample, int max_stack)
u64 i;
int c;
callstack = calloc(max_stack, sizeof(*callstack));
if (callstack == NULL)
if (!sample->callchain) {
pr_debug("Sample unexpectedly missing callchain\n");
return NULL;
}
callstack = calloc(max_stack, sizeof(*callstack));
if (callstack == NULL) {
pr_debug("Failed to allocate callstack\n");
return NULL;
}
for (i = 0, c = 0; i < sample->callchain->nr && c < max_stack; i++) {
u64 ip = sample->callchain->ips[i];
@ -963,14 +962,13 @@ static u64 *get_callstack(struct perf_sample *sample, int max_stack)
return callstack;
}
static int report_lock_contention_begin_event(struct evsel *evsel,
struct perf_sample *sample)
static int report_lock_contention_begin_event(struct perf_sample *sample)
{
struct lock_stat *ls;
struct thread_stat *ts;
struct lock_seq_stat *seq;
u64 addr = evsel__intval(evsel, sample, "lock_addr");
unsigned int flags = evsel__intval(evsel, sample, "flags");
u64 addr = perf_sample__intval(sample, "lock_addr");
unsigned int flags = perf_sample__intval(sample, "flags");
u64 key;
int i, ret;
static bool kmap_loaded;
@ -978,7 +976,7 @@ static int report_lock_contention_begin_event(struct evsel *evsel,
struct map *kmap;
struct symbol *sym;
ret = get_key_by_aggr_mode(&key, addr, evsel, sample);
ret = get_key_by_aggr_mode(&key, addr, sample);
if (ret < 0)
return ret;
@ -1025,7 +1023,7 @@ static int report_lock_contention_begin_event(struct evsel *evsel,
break;
case LOCK_AGGR_CALLER:
name = buf;
if (lock_contention_caller(evsel, sample, buf, sizeof(buf)) < 0)
if (lock_contention_caller(sample, buf, sizeof(buf)) < 0)
name = "Unknown";
break;
case LOCK_AGGR_CGROUP:
@ -1070,7 +1068,7 @@ static int report_lock_contention_begin_event(struct evsel *evsel,
if (needs_callstack()) {
u64 *callstack = get_callstack(sample, max_stack_depth);
if (callstack == NULL)
return -ENOMEM;
return 0;
if (!match_callstack_filter(machine, callstack, max_stack_depth)) {
free(callstack);
@ -1127,18 +1125,17 @@ static int report_lock_contention_begin_event(struct evsel *evsel,
return 0;
}
static int report_lock_contention_end_event(struct evsel *evsel,
struct perf_sample *sample)
static int report_lock_contention_end_event(struct perf_sample *sample)
{
struct lock_stat *ls;
struct thread_stat *ts;
struct lock_seq_stat *seq;
u64 contended_term;
u64 addr = evsel__intval(evsel, sample, "lock_addr");
u64 addr = perf_sample__intval(sample, "lock_addr");
u64 key;
int ret;
ret = get_key_by_aggr_mode(&key, addr, evsel, sample);
ret = get_key_by_aggr_mode(&key, addr, sample);
if (ret < 0)
return ret;
@ -1191,7 +1188,7 @@ static int report_lock_contention_end_event(struct evsel *evsel,
/* lock oriented handlers */
/* TODO: handlers for CPU oriented, thread oriented */
static struct trace_lock_handler report_lock_ops = {
static const struct trace_lock_handler report_lock_ops = {
.acquire_event = report_lock_acquire_event,
.acquired_event = report_lock_acquired_event,
.contended_event = report_lock_contended_event,
@ -1200,53 +1197,53 @@ static struct trace_lock_handler report_lock_ops = {
.contention_end_event = report_lock_contention_end_event,
};
static struct trace_lock_handler contention_lock_ops = {
static const struct trace_lock_handler contention_lock_ops = {
.contention_begin_event = report_lock_contention_begin_event,
.contention_end_event = report_lock_contention_end_event,
};
static struct trace_lock_handler *trace_handler;
static const struct trace_lock_handler *trace_handler;
static int evsel__process_lock_acquire(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_lock_acquire(struct perf_sample *sample)
{
if (trace_handler->acquire_event)
return trace_handler->acquire_event(evsel, sample);
return trace_handler->acquire_event(sample);
return 0;
}
static int evsel__process_lock_acquired(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_lock_acquired(struct perf_sample *sample)
{
if (trace_handler->acquired_event)
return trace_handler->acquired_event(evsel, sample);
return trace_handler->acquired_event(sample);
return 0;
}
static int evsel__process_lock_contended(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_lock_contended(struct perf_sample *sample)
{
if (trace_handler->contended_event)
return trace_handler->contended_event(evsel, sample);
return trace_handler->contended_event(sample);
return 0;
}
static int evsel__process_lock_release(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_lock_release(struct perf_sample *sample)
{
if (trace_handler->release_event)
return trace_handler->release_event(evsel, sample);
return trace_handler->release_event(sample);
return 0;
}
static int evsel__process_contention_begin(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_contention_begin(struct perf_sample *sample)
{
if (trace_handler->contention_begin_event)
return trace_handler->contention_begin_event(evsel, sample);
return trace_handler->contention_begin_event(sample);
return 0;
}
static int evsel__process_contention_end(struct evsel *evsel, struct perf_sample *sample)
static int evsel__process_contention_end(struct perf_sample *sample)
{
if (trace_handler->contention_end_event)
return trace_handler->contention_end_event(evsel, sample);
return trace_handler->contention_end_event(sample);
return 0;
}
@ -1424,28 +1421,28 @@ static int process_event_update(const struct perf_tool *tool,
return 0;
}
typedef int (*tracepoint_handler)(struct evsel *evsel,
struct perf_sample *sample);
typedef int (*tracepoint_handler)(struct perf_sample *sample);
static int process_sample_event(const struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct evsel *evsel = sample->evsel;
int err = 0;
struct thread *thread = machine__findnew_thread(machine, sample->pid,
sample->tid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
return -1;
}
if (evsel->handler != NULL) {
tracepoint_handler f = evsel->handler;
err = f(evsel, sample);
err = f(sample);
}
thread__put(thread);
@ -1921,8 +1918,11 @@ static int __cmd_report(bool display_info)
return err;
}
static volatile sig_atomic_t done;
static void sighandler(int sig __maybe_unused)
{
done = 1;
}
static int check_lock_contention_options(const struct option *options,
@ -2060,6 +2060,7 @@ static int __cmd_contention(int argc, const char **argv)
goto out_delete;
}
done = 0;
signal(SIGINT, sighandler);
signal(SIGCHLD, sighandler);
signal(SIGTERM, sighandler);
@ -2127,8 +2128,11 @@ static int __cmd_contention(int argc, const char **argv)
if (argc)
evlist__start_workload(con.evlist);
/* wait for signal */
pause();
while (!done) {
if (argc && waitpid(con.evlist->workload.pid, NULL, WNOHANG) > 0)
break;
sleep(1);
}
lock_contention_stop();
lock_contention_read(&con);

View File

@ -255,7 +255,6 @@ dump_raw_samples(const struct perf_tool *tool,
static int process_sample_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel __maybe_unused,
struct machine *machine)
{
return dump_raw_samples(tool, event, sample, machine);

View File

@ -14,6 +14,7 @@
#include "util/parse-events.h"
#include "util/config.h"
#include "util/arm64-frame-pointer-unwind-support.h"
#include "util/callchain.h"
#include "util/cgroup.h"
#include "util/header.h"
@ -865,6 +866,7 @@ static int record__auxtrace_init(struct record *rec)
}
if (!rec->itr) {
err = -EINVAL;
rec->itr = auxtrace_record__init(rec->evlist, &err);
if (err)
return err;
@ -1489,7 +1491,6 @@ static void set_timestamp_boundary(struct record *rec, u64 sample_time)
static int process_sample_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct record *rec = container_of(tool, struct record, tool);
@ -1500,7 +1501,7 @@ static int process_sample_event(const struct perf_tool *tool,
return 0;
rec->samples++;
return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
return build_id__mark_dso_hit(tool, event, sample, machine);
}
static int process_buildids(struct record *rec)
@ -2743,7 +2744,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
trigger_error(&auxtrace_snapshot_trigger);
trigger_error(&switch_output_trigger);
err = -1;
goto out_child;
goto out_child_no_flush;
}
if (auxtrace_record__snapshot_started) {
@ -2890,6 +2891,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
out_child:
record__stop_threads(rec);
record__mmap_read_all(rec, true);
goto out_free_threads;
out_child_no_flush:
/* mmap read already failed — retrying would just fail again */
record__stop_threads(rec);
out_free_threads:
record__free_thread_data(rec);
evlist__finalize_ctlfd(rec->evlist);
@ -3079,6 +3084,7 @@ static int record__mmap_cpu_mask_alloc(struct mmap_cpu_mask *mask, int nr_bits)
static void record__mmap_cpu_mask_free(struct mmap_cpu_mask *mask)
{
bitmap_free(mask->bits);
mask->bits = NULL;
mask->nbits = 0;
}
@ -3230,10 +3236,6 @@ static int record__parse_off_cpu_thresh(const struct option *opt,
return 0;
}
void __weak arch__add_leaf_frame_record_opts(struct record_opts *opts __maybe_unused)
{
}
static int parse_control_option(const struct option *opt,
const char *str,
int unset __maybe_unused)
@ -4319,8 +4321,10 @@ int cmd_record(int argc, const char **argv)
evlist__warn_user_requested_cpus(rec->evlist, rec->opts.target.cpu_list);
if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP)
arch__add_leaf_frame_record_opts(&rec->opts);
if (callchain_param.enabled && callchain_param.record_mode == CALLCHAIN_FP) {
if (EM_HOST == EM_AARCH64)
add_leaf_frame_caller_opts_aarch64(&rec->opts);
}
err = -ENOMEM;
if (evlist__create_maps(rec->evlist, &rec->opts.target) < 0) {

View File

@ -27,6 +27,7 @@
#include "perf.h"
#include "util/debug.h"
#include "util/event.h"
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/evswitch.h"
@ -48,6 +49,7 @@
#include "util/time-utils.h"
#include "util/auxtrace.h"
#include "util/units.h"
#include "util/unwind.h"
#include "util/util.h" // perf_tip()
#include "ui/ui.h"
#include "ui/progress.h"
@ -170,7 +172,6 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
int err = 0;
struct report *rep = arg;
struct hist_entry *he = iter->he;
struct evsel *evsel = iter->evsel;
struct perf_sample *sample = iter->sample;
struct mem_info *mi;
struct branch_info *bi;
@ -180,25 +181,25 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
if (sort__mode == SORT_MODE__BRANCH) {
bi = he->branch_info;
err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
err = addr_map_symbol__inc_samples(&bi->from, sample);
if (err)
goto out;
err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
err = addr_map_symbol__inc_samples(&bi->to, sample);
} else if (rep->mem_mode) {
mi = he->mem_info;
err = addr_map_symbol__inc_samples(mem_info__daddr(mi), sample, evsel);
err = addr_map_symbol__inc_samples(mem_info__daddr(mi), sample);
if (err)
goto out;
err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
err = hist_entry__inc_addr_samples(he, sample, al->addr);
} else if (symbol_conf.cumulate_callchain) {
if (single)
err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
err = hist_entry__inc_addr_samples(he, sample, al->addr);
} else {
err = hist_entry__inc_addr_samples(he, sample, evsel, al->addr);
err = hist_entry__inc_addr_samples(he, sample, al->addr);
}
out:
@ -214,7 +215,6 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
struct report *rep = arg;
struct branch_info *bi = he->branch_info;
struct perf_sample *sample = iter->sample;
struct evsel *evsel = iter->evsel;
int err;
branch_type_count(&rep->brtype_stat, &bi->flags,
@ -223,11 +223,11 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
if (!ui__has_annotation() && !rep->symbol_ipc)
return 0;
err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
err = addr_map_symbol__inc_samples(&bi->from, sample);
if (err)
goto out;
err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
err = addr_map_symbol__inc_samples(&bi->to, sample);
out:
return err;
@ -264,13 +264,11 @@ static int process_feature_event(const struct perf_tool *tool,
static int process_sample_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct report *rep = container_of(tool, struct report, tool);
struct addr_location al;
struct hist_entry_iter iter = {
.evsel = evsel,
.sample = sample,
.hide_unresolved = symbol_conf.hide_unresolved,
.add_entry_cb = hist_iter__report_callback,
@ -282,13 +280,14 @@ static int process_sample_event(const struct perf_tool *tool,
return 0;
}
if (evswitch__discard(&rep->evswitch, evsel))
if (evswitch__discard(&rep->evswitch, sample->evsel))
return 0;
addr_location__init(&al);
if (machine__resolve(machine, &al, sample) < 0) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
pr_debug("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
ret = -1;
goto out_put;
}
@ -299,7 +298,8 @@ static int process_sample_event(const struct perf_tool *tool,
if (symbol_conf.hide_unresolved && al.sym == NULL)
goto out_put;
if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
if (rep->cpu_list && (sample->cpu >= MAX_NR_CPUS ||
!test_bit(sample->cpu, rep->cpu_bitmap)))
goto out_put;
if (sort__mode == SORT_MODE__BRANCH) {
@ -326,7 +326,7 @@ static int process_sample_event(const struct perf_tool *tool,
if (ui__has_annotation() || rep->symbol_ipc || rep->total_cycles_mode) {
hist__account_cycles(sample->branch_stack, &al, sample,
rep->nonany_branch_mode,
&rep->total_cycles, evsel);
&rep->total_cycles);
}
rep->total_samples++;
@ -335,7 +335,8 @@ static int process_sample_event(const struct perf_tool *tool,
ret = hist_entry_iter__add(&iter, &al, rep->max_stack, rep);
if (ret < 0)
pr_debug("problem adding hist entry, skipping event\n");
pr_debug("problem adding hist entry at offset %#" PRIx64 ", skipping event\n",
sample->file_offset);
out_put:
addr_location__exit(&al);
return ret;
@ -344,7 +345,6 @@ static int process_sample_event(const struct perf_tool *tool,
static int process_read_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
struct evsel *evsel,
struct machine *machine __maybe_unused)
{
struct report *rep = container_of(tool, struct report, tool);
@ -352,7 +352,7 @@ static int process_read_event(const struct perf_tool *tool,
if (rep->show_threads) {
int err = perf_read_values_add_value(&rep->show_threads_values,
event->read.pid, event->read.tid,
evsel,
sample->evsel,
event->read.value);
if (err)
@ -753,7 +753,7 @@ static int hists__resort_cb(struct hist_entry *he, void *arg)
struct report *rep = arg;
struct symbol *sym = he->ms.sym;
if (rep->symbol_ipc && sym && !sym->annotate2) {
if (rep->symbol_ipc && sym && !symbol__is_annotate2(sym)) {
struct evsel *evsel = hists_to_evsel(he->hists);
symbol__annotate2(&he->ms, evsel, NULL);
@ -778,11 +778,10 @@ static void report__output_resort(struct report *rep)
static int count_sample_event(const struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine __maybe_unused)
{
struct hists *hists = evsel__hists(evsel);
struct hists *hists = evsel__hists(sample->evsel);
hists__inc_nr_events(hists);
return 0;
@ -794,9 +793,11 @@ static int count_lost_samples_event(const struct perf_tool *tool,
struct machine *machine __maybe_unused)
{
struct report *rep = container_of(tool, struct report, tool);
struct evsel *evsel;
struct evsel *evsel = sample->evsel;
if (!evsel)
evsel = evlist__id2evsel(rep->session->evlist, sample->id);
evsel = evlist__id2evsel(rep->session->evlist, sample->id);
if (evsel) {
struct hists *hists = evsel__hists(evsel);
u32 count = event->lost_samples.lost;
@ -1449,6 +1450,9 @@ int cmd_report(int argc, const char **argv)
OPT_CALLBACK(0, "addr2line-style", NULL, "addr2line style",
"addr2line styles (libdw,llvm,libbfd,addr2line)",
report_parse_addr2line_config),
OPT_CALLBACK(0, "unwind-style", NULL, "unwind style",
"unwind styles (libdw,libunwind)",
unwind__option),
OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
"Symbol demangling. Enabled by default, use --no-demangle to disable."),
OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +1,78 @@
// SPDX-License-Identifier: GPL-2.0
#include "builtin.h"
#include "util/counts.h"
#include "util/debug.h"
#include "util/dso.h"
#include <subcmd/exec-cmd.h>
#include "util/header.h"
#include <subcmd/parse-options.h>
#include "util/perf_regs.h"
#include "util/session.h"
#include "util/tool.h"
#include "util/map.h"
#include "util/srcline.h"
#include "util/symbol.h"
#include "util/thread.h"
#include "util/trace-event.h"
#include "util/env.h"
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/evsel_fprintf.h"
#include "util/evswitch.h"
#include "util/sort.h"
#include "util/data.h"
#include "util/auxtrace.h"
#include "util/cpumap.h"
#include "util/thread_map.h"
#include "util/stat.h"
#include "util/color.h"
#include "util/string2.h"
#include "util/thread-stack.h"
#include "util/time-utils.h"
#include "util/path.h"
#include "util/event.h"
#include "util/mem-info.h"
#include "util/metricgroup.h"
#include "ui/ui.h"
#include "print_binary.h"
#include "print_insn.h"
#include <linux/bitmap.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/stringify.h>
#include <linux/time64.h>
#include <linux/zalloc.h>
#include <linux/unaligned.h>
#include <sys/utsname.h>
#include "asm/bug.h"
#include "util/mem-events.h"
#include "util/dump-insn.h"
#include <dirent.h>
#include <errno.h>
#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <subcmd/pager.h>
#include <perf/evlist.h>
#include <linux/err.h>
#include "util/dlfilter.h"
#include "util/record.h"
#include "util/util.h"
#include "util/cgroup.h"
#include "util/annotate.h"
#include "perf.h"
#include <dirent.h>
#include <fcntl.h>
#include <linux/bitmap.h>
#include <linux/compiler.h>
#include <linux/ctype.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/stringify.h>
#include <linux/time64.h>
#include <linux/unaligned.h>
#include <linux/zalloc.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <perf/evlist.h>
#include <subcmd/exec-cmd.h>
#include <subcmd/pager.h>
#include <subcmd/parse-options.h>
#include "asm/bug.h"
#include "builtin.h"
#include "perf.h"
#include "print_binary.h"
#include "print_insn.h"
#include "ui/ui.h"
#include "util/annotate.h"
#include "util/auxtrace.h"
#include "util/cgroup.h"
#include "util/color.h"
#include "util/counts.h"
#include "util/cpumap.h"
#include "util/data.h"
#include "util/debug.h"
#include "util/dlfilter.h"
#include "util/dso.h"
#include "util/dump-insn.h"
#include "util/env.h"
#include "util/event.h"
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/evsel_fprintf.h"
#include "util/evswitch.h"
#include "util/header.h"
#include "util/map.h"
#include "util/mem-events.h"
#include "util/mem-info.h"
#include "util/metricgroup.h"
#include "util/path.h"
#include "util/perf_regs.h"
#include "util/pmu.h"
#include "util/record.h"
#include "util/session.h"
#include "util/sort.h"
#include "util/srcline.h"
#include "util/stat.h"
#include "util/string2.h"
#include "util/symbol.h"
#include "util/thread-stack.h"
#include "util/thread.h"
#include "util/thread_map.h"
#include "util/time-utils.h"
#include "util/tool.h"
#include "util/trace-event.h"
#include "util/unwind.h"
#include "util/util.h"
#ifdef HAVE_LIBTRACEEVENT
#include <event-parse.h>
#endif
@ -1287,8 +1291,12 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
if (!verbose) {
for (j = 0; j < num; j++)
printed += fprintf(fp, "%s", pos->abbr_name);
} else
printed += fprintf(fp, "%s %d ", pos->name, num);
if (mask && (num == mask))
printed += fprintf(fp, "+");
} else {
printed += fprintf(fp, "%s %d%s", pos->name,
num, mask && (num == mask) ? "+ " : " ");
}
}
if (numprinted == 0 && !verbose)
printed += fprintf(fp, "-");
@ -1683,7 +1691,7 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample,
if (symbol_conf.use_callchain && sample->callchain) {
cursor = get_tls_callchain_cursor();
if (thread__resolve_callchain(al->thread, cursor, evsel,
if (thread__resolve_callchain(al->thread, cursor,
sample, NULL, NULL,
scripting_max_stack))
cursor = NULL;
@ -2418,12 +2426,13 @@ static bool show_event(struct perf_sample *sample,
}
static void process_event(struct perf_script *script,
struct perf_sample *sample, struct evsel *evsel,
struct perf_sample *sample,
struct addr_location *al,
struct addr_location *addr_al,
struct machine *machine)
{
struct thread *thread = al->thread;
struct evsel *evsel = sample->evsel;
struct perf_event_attr *attr = &evsel->core.attr;
unsigned int type = evsel__output_type(evsel);
struct evsel_script *es = evsel->priv;
@ -2506,7 +2515,7 @@ static void process_event(struct perf_script *script,
if (symbol_conf.use_callchain && sample->callchain) {
cursor = get_tls_callchain_cursor();
if (thread__resolve_callchain(al->thread, cursor, evsel,
if (thread__resolve_callchain(al->thread, cursor,
sample, NULL, NULL,
scripting_max_stack))
cursor = NULL;
@ -2637,7 +2646,7 @@ static int cleanup_scripting(void)
static bool filter_cpu(struct perf_sample *sample)
{
if (cpu_list && sample->cpu != (u32)-1)
if (cpu_list && sample->cpu != (u32)-1 && sample->cpu < MAX_NR_CPUS)
return !test_bit(sample->cpu, cpu_bitmap);
return false;
}
@ -2645,10 +2654,10 @@ static bool filter_cpu(struct perf_sample *sample)
static int process_sample_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct perf_script *scr = container_of(tool, struct perf_script, tool);
struct evsel *evsel = sample->evsel;
struct addr_location al;
struct addr_location addr_al;
int ret = 0;
@ -2684,8 +2693,9 @@ static int process_sample_event(const struct perf_tool *tool,
goto out_put;
if (!al.thread && machine__resolve(machine, &al, sample) < 0) {
pr_err("problem processing %d event, skipping it.\n",
event->header.type);
pr_err("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
ret = -1;
goto out_put;
}
@ -2715,9 +2725,9 @@ static int process_sample_event(const struct perf_tool *tool,
thread__resolve(al.thread, &addr_al, sample);
addr_al_ptr = &addr_al;
}
scripting_ops->process_event(event, sample, evsel, &al, addr_al_ptr);
scripting_ops->process_event(event, sample, &al, addr_al_ptr);
} else {
process_event(scr, sample, evsel, &al, &addr_al, machine);
process_event(scr, sample, &al, &addr_al, machine);
}
out_put:
@ -2729,10 +2739,10 @@ static int process_sample_event(const struct perf_tool *tool,
static int process_deferred_sample_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct perf_script *scr = container_of(tool, struct perf_script, tool);
struct evsel *evsel = sample->evsel;
struct perf_event_attr *attr = &evsel->core.attr;
struct evsel_script *es = evsel->priv;
unsigned int type = output_type(attr->type);
@ -2766,8 +2776,9 @@ static int process_deferred_sample_event(const struct perf_tool *tool,
goto out_put;
if (machine__resolve(machine, &al, sample) < 0) {
pr_err("problem processing %d event, skipping it.\n",
event->header.type);
pr_err("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
ret = -1;
goto out_put;
}
@ -2791,7 +2802,7 @@ static int process_deferred_sample_event(const struct perf_tool *tool,
if (symbol_conf.use_callchain && sample->callchain) {
cursor = get_tls_callchain_cursor();
if (thread__resolve_callchain(al.thread, cursor, evsel,
if (thread__resolve_callchain(al.thread, cursor,
sample, NULL, NULL,
scripting_max_stack)) {
pr_info("cannot resolve deferred callchains\n");
@ -2893,9 +2904,12 @@ static int print_event_with_time(const struct perf_tool *tool,
{
struct perf_script *script = container_of(tool, struct perf_script, tool);
struct perf_session *session = script->session;
struct evsel *evsel = evlist__id2evsel(session->evlist, sample->id);
struct evsel *evsel = sample->evsel;
struct thread *thread = NULL;
if (!evsel)
evsel = evlist__id2evsel(session->evlist, sample->id);
if (evsel && !evsel->core.attr.sample_id_all) {
sample->cpu = 0;
sample->time = timestamp;
@ -4159,6 +4173,9 @@ int cmd_script(int argc, const char **argv)
"Enable symbol demangling"),
OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
"Enable kernel symbol demangling"),
OPT_CALLBACK(0, "unwind-style", NULL, "unwind style",
"unwind styles (libdw,libunwind)",
unwind__option),
OPT_STRING(0, "addr2line", &symbol_conf.addr2line_path, "path",
"addr2line binary to use for line numbers"),
OPT_STRING(0, "time", &script.time_str, "str",

View File

@ -1637,9 +1637,10 @@ static struct aggr_cpu_id perf_env__get_socket_aggr_by_cpu(struct perf_cpu cpu,
{
struct perf_env *env = data;
struct aggr_cpu_id id = aggr_cpu_id__empty();
struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
if (cpu.cpu != -1)
id.socket = env->cpu[cpu.cpu].socket_id;
if (topo)
id.socket = topo->socket_id;
return id;
}
@ -1648,15 +1649,16 @@ static struct aggr_cpu_id perf_env__get_die_aggr_by_cpu(struct perf_cpu cpu, voi
{
struct perf_env *env = data;
struct aggr_cpu_id id = aggr_cpu_id__empty();
struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
if (cpu.cpu != -1) {
if (topo) {
/*
* die_id is relative to socket, so start
* with the socket ID and then add die to
* make a unique ID.
*/
id.socket = env->cpu[cpu.cpu].socket_id;
id.die = env->cpu[cpu.cpu].die_id;
id.socket = topo->socket_id;
id.die = topo->die_id;
}
return id;
@ -1704,12 +1706,13 @@ static struct aggr_cpu_id perf_env__get_cache_aggr_by_cpu(struct perf_cpu cpu,
{
struct perf_env *env = data;
struct aggr_cpu_id id = aggr_cpu_id__empty();
struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
if (cpu.cpu != -1) {
if (topo) {
u32 cache_level = (perf_stat.aggr_level) ?: stat_config.aggr_level;
id.socket = env->cpu[cpu.cpu].socket_id;
id.die = env->cpu[cpu.cpu].die_id;
id.socket = topo->socket_id;
id.die = topo->die_id;
perf_env__get_cache_id_for_cpu(cpu, env, cache_level, &id);
}
@ -1721,11 +1724,12 @@ static struct aggr_cpu_id perf_env__get_cluster_aggr_by_cpu(struct perf_cpu cpu,
{
struct perf_env *env = data;
struct aggr_cpu_id id = aggr_cpu_id__empty();
struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
if (cpu.cpu != -1) {
id.socket = env->cpu[cpu.cpu].socket_id;
id.die = env->cpu[cpu.cpu].die_id;
id.cluster = env->cpu[cpu.cpu].cluster_id;
if (topo) {
id.socket = topo->socket_id;
id.die = topo->die_id;
id.cluster = topo->cluster_id;
}
return id;
@ -1735,16 +1739,17 @@ static struct aggr_cpu_id perf_env__get_core_aggr_by_cpu(struct perf_cpu cpu, vo
{
struct perf_env *env = data;
struct aggr_cpu_id id = aggr_cpu_id__empty();
struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
if (cpu.cpu != -1) {
if (topo) {
/*
* core_id is relative to socket, die and cluster, we need a
* global id. So we set socket, die id, cluster id and core id.
*/
id.socket = env->cpu[cpu.cpu].socket_id;
id.die = env->cpu[cpu.cpu].die_id;
id.cluster = env->cpu[cpu.cpu].cluster_id;
id.core = env->cpu[cpu.cpu].core_id;
id.socket = topo->socket_id;
id.die = topo->die_id;
id.cluster = topo->cluster_id;
id.core = topo->core_id;
}
return id;
@ -1754,18 +1759,19 @@ static struct aggr_cpu_id perf_env__get_cpu_aggr_by_cpu(struct perf_cpu cpu, voi
{
struct perf_env *env = data;
struct aggr_cpu_id id = aggr_cpu_id__empty();
struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
if (cpu.cpu != -1) {
if (topo) {
/*
* core_id is relative to socket and die,
* we need a global id. So we set
* socket, die id and core id
*/
id.socket = env->cpu[cpu.cpu].socket_id;
id.die = env->cpu[cpu.cpu].die_id;
id.core = env->cpu[cpu.cpu].core_id;
id.cpu = cpu;
id.socket = topo->socket_id;
id.die = topo->die_id;
id.core = topo->core_id;
}
id.cpu = cpu;
return id;
}

View File

@ -299,7 +299,7 @@ static void pid_put_sample(struct timechart *tchart, int pid, int type,
sample->type = type;
sample->next = c->samples;
sample->cpu = cpu;
sample->backtrace = backtrace;
sample->backtrace = backtrace ? strdup(backtrace) : NULL;
c->samples = sample;
if (sample->type == TYPE_RUNNING && end > start && start > 0) {
@ -433,7 +433,7 @@ static void sched_wakeup(struct timechart *tchart, int cpu, u64 timestamp,
we->time = timestamp;
we->waker = waker;
we->backtrace = backtrace;
we->backtrace = backtrace ? strdup(backtrace) : NULL;
if ((flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ))
we->waker = -1;
@ -489,9 +489,13 @@ static void sched_switch(struct timechart *tchart, int cpu, u64 timestamp,
}
}
static const char *cat_backtrace(union perf_event *event,
struct perf_sample *sample,
struct machine *machine)
/*
* Returns a malloc'd backtrace string built via open_memstream, or NULL
* on error. Caller must free() the returned pointer.
*/
static char *cat_backtrace(union perf_event *event,
struct perf_sample *sample,
struct machine *machine)
{
struct addr_location al;
unsigned int i;
@ -500,6 +504,7 @@ static const char *cat_backtrace(union perf_event *event,
u8 cpumode = PERF_RECORD_MISC_USER;
struct ip_callchain *chain = sample->callchain;
FILE *f = open_memstream(&p, &p_len);
bool corrupted = false;
if (!f) {
perror("open_memstream error");
@ -511,8 +516,9 @@ static const char *cat_backtrace(union perf_event *event,
goto exit;
if (machine__resolve(machine, &al, sample) < 0) {
fprintf(stderr, "problem processing %d event, skipping it.\n",
event->header.type);
pr_err("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n",
perf_event__name(event->header.type), event->header.type,
sample->file_offset);
goto exit;
}
@ -537,14 +543,8 @@ static const char *cat_backtrace(union perf_event *event,
cpumode = PERF_RECORD_MISC_USER;
break;
default:
pr_debug("invalid callchain context: "
"%"PRId64"\n", (s64) ip);
/*
* It seems the callchain is corrupted.
* Discard all.
*/
zfree(&p);
pr_debug("invalid callchain context: %" PRId64 "\n", (s64) ip);
corrupted = true;
goto exit;
}
continue;
@ -561,23 +561,30 @@ static const char *cat_backtrace(union perf_event *event,
}
exit:
addr_location__exit(&al);
/*
* fclose() on an open_memstream always sets p to a valid buffer,
* even if nothing was written see open_memstream(3). So p is
* never NULL after fclose and we need the flag to discard it.
*/
fclose(f);
if (corrupted)
zfree(&p);
return p;
}
typedef int (*tracepoint_handler)(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace);
static int process_sample_event(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine)
{
struct timechart *tchart = container_of(tool, struct timechart, tool);
struct evsel *evsel = sample->evsel;
int ret = 0;
if (evsel->core.attr.sample_type & PERF_SAMPLE_TIME) {
if (!tchart->first_time || tchart->first_time > sample->time)
@ -588,22 +595,29 @@ static int process_sample_event(const struct perf_tool *tool,
if (evsel->handler != NULL) {
tracepoint_handler f = evsel->handler;
return f(tchart, evsel, sample,
cat_backtrace(event, sample, machine));
char *backtrace = cat_backtrace(event, sample, machine);
ret = f(tchart, sample, backtrace);
free(backtrace);
}
return 0;
return ret;
}
static int
process_sample_cpu_idle(struct timechart *tchart __maybe_unused,
struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
u32 state = evsel__intval(evsel, sample, "state");
u32 cpu_id = evsel__intval(evsel, sample, "cpu_id");
u32 state = perf_sample__intval(sample, "state");
u32 cpu_id = perf_sample__intval(sample, "cpu_id");
/* perf.data is untrusted input — cpu_id may be corrupted */
if (cpu_id >= MAX_CPUS) {
pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu_id %u\n",
sample->file_offset, cpu_id);
return -1;
}
if (state == (u32)PWR_EVENT_EXIT)
c_state_end(tchart, cpu_id, sample->time);
else
@ -613,41 +627,56 @@ process_sample_cpu_idle(struct timechart *tchart __maybe_unused,
static int
process_sample_cpu_frequency(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
u32 state = evsel__intval(evsel, sample, "state");
u32 cpu_id = evsel__intval(evsel, sample, "cpu_id");
u32 state = perf_sample__intval(sample, "state");
u32 cpu_id = perf_sample__intval(sample, "cpu_id");
/* perf.data is untrusted input — cpu_id may be corrupted */
if (cpu_id >= MAX_CPUS) {
pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu_id %u\n",
sample->file_offset, cpu_id);
return -1;
}
p_state_change(tchart, cpu_id, sample->time, state);
return 0;
}
static int
process_sample_sched_wakeup(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace)
{
u8 flags = evsel__intval(evsel, sample, "common_flags");
int waker = evsel__intval(evsel, sample, "common_pid");
int wakee = evsel__intval(evsel, sample, "pid");
u8 flags = perf_sample__intval(sample, "common_flags");
int waker = perf_sample__intval(sample, "common_pid");
int wakee = perf_sample__intval(sample, "pid");
/* perf.data is untrusted input — CPU may be absent or corrupted */
if (sample->cpu >= MAX_CPUS) {
pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu %u\n",
sample->file_offset, sample->cpu);
return -1;
}
sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace);
return 0;
}
static int
process_sample_sched_switch(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace)
{
int prev_pid = evsel__intval(evsel, sample, "prev_pid");
int next_pid = evsel__intval(evsel, sample, "next_pid");
u64 prev_state = evsel__intval(evsel, sample, "prev_state");
int prev_pid = perf_sample__intval(sample, "prev_pid");
int next_pid = perf_sample__intval(sample, "next_pid");
u64 prev_state = perf_sample__intval(sample, "prev_state");
/* perf.data is untrusted input — CPU may be absent or corrupted */
if (sample->cpu >= MAX_CPUS) {
pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu %u\n",
sample->file_offset, sample->cpu);
return -1;
}
sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid,
prev_state, backtrace);
return 0;
@ -656,36 +685,51 @@ process_sample_sched_switch(struct timechart *tchart,
#ifdef SUPPORT_OLD_POWER_EVENTS
static int
process_sample_power_start(struct timechart *tchart __maybe_unused,
struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
u64 cpu_id = evsel__intval(evsel, sample, "cpu_id");
u64 value = evsel__intval(evsel, sample, "value");
u64 cpu_id = perf_sample__intval(sample, "cpu_id");
u64 value = perf_sample__intval(sample, "value");
/* perf.data is untrusted input — cpu_id may be corrupted */
if (cpu_id >= MAX_CPUS) {
pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu_id %llu\n",
sample->file_offset, (unsigned long long)cpu_id);
return -1;
}
c_state_start(cpu_id, sample->time, value);
return 0;
}
static int
process_sample_power_end(struct timechart *tchart,
struct evsel *evsel __maybe_unused,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
/* perf.data is untrusted input — CPU may be absent or corrupted */
if (sample->cpu >= MAX_CPUS) {
pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu %u\n",
sample->file_offset, sample->cpu);
return -1;
}
c_state_end(tchart, sample->cpu, sample->time);
return 0;
}
static int
process_sample_power_frequency(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
u64 cpu_id = evsel__intval(evsel, sample, "cpu_id");
u64 value = evsel__intval(evsel, sample, "value");
u64 cpu_id = perf_sample__intval(sample, "cpu_id");
u64 value = perf_sample__intval(sample, "value");
/* perf.data is untrusted input — cpu_id may be corrupted */
if (cpu_id >= MAX_CPUS) {
pr_debug("at offset %#" PRIx64 ": out-of-bounds cpu_id %llu\n",
sample->file_offset, (unsigned long long)cpu_id);
return -1;
}
p_state_change(tchart, cpu_id, sample->time, value);
return 0;
}
@ -697,10 +741,9 @@ process_sample_power_frequency(struct timechart *tchart,
*/
static void end_sample_processing(struct timechart *tchart)
{
u64 cpu;
struct power_event *pwr;
for (u64 cpu = 0; cpu < tchart->numcpus; cpu++) {
struct power_event *pwr;
for (cpu = 0; cpu <= tchart->numcpus; cpu++) {
/* C state */
#if 0
pwr = zalloc(sizeof(*pwr));
@ -849,120 +892,120 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type,
static int
process_enter_read(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long fd = evsel__intval(evsel, sample, "fd");
long fd = perf_sample__intval(sample, "fd");
return pid_begin_io_sample(tchart, sample->tid, IOTYPE_READ,
sample->time, fd);
}
static int
process_exit_read(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long ret = evsel__intval(evsel, sample, "ret");
long ret = perf_sample__intval(sample, "ret");
return pid_end_io_sample(tchart, sample->tid, IOTYPE_READ,
sample->time, ret);
}
static int
process_enter_write(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long fd = evsel__intval(evsel, sample, "fd");
long fd = perf_sample__intval(sample, "fd");
return pid_begin_io_sample(tchart, sample->tid, IOTYPE_WRITE,
sample->time, fd);
}
static int
process_exit_write(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long ret = evsel__intval(evsel, sample, "ret");
long ret = perf_sample__intval(sample, "ret");
return pid_end_io_sample(tchart, sample->tid, IOTYPE_WRITE,
sample->time, ret);
}
static int
process_enter_sync(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long fd = evsel__intval(evsel, sample, "fd");
long fd = perf_sample__intval(sample, "fd");
return pid_begin_io_sample(tchart, sample->tid, IOTYPE_SYNC,
sample->time, fd);
}
static int
process_exit_sync(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long ret = evsel__intval(evsel, sample, "ret");
long ret = perf_sample__intval(sample, "ret");
return pid_end_io_sample(tchart, sample->tid, IOTYPE_SYNC,
sample->time, ret);
}
static int
process_enter_tx(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long fd = evsel__intval(evsel, sample, "fd");
long fd = perf_sample__intval(sample, "fd");
return pid_begin_io_sample(tchart, sample->tid, IOTYPE_TX,
sample->time, fd);
}
static int
process_exit_tx(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long ret = evsel__intval(evsel, sample, "ret");
long ret = perf_sample__intval(sample, "ret");
return pid_end_io_sample(tchart, sample->tid, IOTYPE_TX,
sample->time, ret);
}
static int
process_enter_rx(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long fd = evsel__intval(evsel, sample, "fd");
long fd = perf_sample__intval(sample, "fd");
return pid_begin_io_sample(tchart, sample->tid, IOTYPE_RX,
sample->time, fd);
}
static int
process_exit_rx(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long ret = evsel__intval(evsel, sample, "ret");
long ret = perf_sample__intval(sample, "ret");
return pid_end_io_sample(tchart, sample->tid, IOTYPE_RX,
sample->time, ret);
}
static int
process_enter_poll(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long fd = evsel__intval(evsel, sample, "fd");
long fd = perf_sample__intval(sample, "fd");
return pid_begin_io_sample(tchart, sample->tid, IOTYPE_POLL,
sample->time, fd);
}
static int
process_exit_poll(struct timechart *tchart,
struct evsel *evsel,
struct perf_sample *sample)
struct perf_sample *sample,
const char *backtrace __maybe_unused)
{
long ret = evsel__intval(evsel, sample, "ret");
long ret = perf_sample__intval(sample, "ret");
return pid_end_io_sample(tchart, sample->tid, IOTYPE_POLL,
sample->time, ret);
}
@ -1520,6 +1563,8 @@ static int process_header(struct perf_file_section *section __maybe_unused,
switch (feat) {
case HEADER_NRCPUS:
tchart->numcpus = ph->env.nr_cpus_avail;
if (tchart->numcpus > MAX_CPUS)
tchart->numcpus = MAX_CPUS;
break;
case HEADER_CPU_TOPOLOGY:

View File

@ -186,8 +186,8 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
"Please report to linux-kernel@vger.kernel.org\n",
ip, dso__long_name(dso), dso__symtab_origin(dso),
map__start(map), map__end(map), sym->start, sym->end,
sym->binding == STB_GLOBAL ? 'g' :
sym->binding == STB_LOCAL ? 'l' : 'w', sym->name,
symbol__binding(sym) == STB_GLOBAL ? 'g' :
symbol__binding(sym) == STB_LOCAL ? 'l' : 'w', sym->name,
err ? "[unknown]" : uts.machine,
err ? "[unknown]" : uts.release, perf_version_string);
if (use_browser <= 0)
@ -199,7 +199,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
static void perf_top__record_precise_ip(struct perf_top *top,
struct hist_entry *he,
struct perf_sample *sample,
struct evsel *evsel, u64 ip)
u64 ip)
EXCLUSIVE_LOCKS_REQUIRED(he->hists->lock)
{
struct annotation *notes;
@ -216,7 +216,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
if (!annotation__trylock(notes))
return;
err = hist_entry__inc_addr_samples(he, sample, evsel, ip);
err = hist_entry__inc_addr_samples(he, sample, ip);
annotation__unlock(notes);
@ -732,20 +732,18 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
EXCLUSIVE_LOCKS_REQUIRED(iter->he->hists->lock)
{
struct perf_top *top = arg;
struct evsel *evsel = iter->evsel;
if (perf_hpp_list.sym && single)
perf_top__record_precise_ip(top, iter->he, iter->sample, evsel, al->addr);
perf_top__record_precise_ip(top, iter->he, iter->sample, al->addr);
hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
!(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY),
NULL, evsel);
/*total_cycles=*/NULL);
return 0;
}
static void perf_event__process_sample(const struct perf_tool *tool,
const union perf_event *event,
struct evsel *evsel,
struct perf_sample *sample,
struct machine *machine)
{
@ -830,10 +828,10 @@ static void perf_event__process_sample(const struct perf_tool *tool,
}
}
if (al.sym == NULL || !al.sym->idle) {
struct hists *hists = evsel__hists(evsel);
if (al.sym == NULL ||
!symbol__is_idle(al.sym, al.map ? map__dso(al.map) : NULL, machine->env)) {
struct hists *hists = evsel__hists(sample->evsel);
struct hist_entry_iter iter = {
.evsel = evsel,
.sample = sample,
.add_entry_cb = hist_iter__top_callback,
};
@ -1167,7 +1165,9 @@ static int deliver_event(struct ordered_events *qe,
goto next_event;
}
evsel = evlist__id2evsel(session->evlist, sample.id);
evsel = sample.evsel;
if (!evsel)
evsel = evlist__id2evsel(session->evlist, sample.id);
assert(evsel != NULL);
if (event->header.type == PERF_RECORD_SAMPLE) {
@ -1211,7 +1211,7 @@ static int deliver_event(struct ordered_events *qe,
}
if (event->header.type == PERF_RECORD_SAMPLE) {
perf_event__process_sample(&top->tool, event, evsel,
perf_event__process_sample(&top->tool, event,
&sample, machine);
} else if (event->header.type == PERF_RECORD_LOST) {
perf_top__process_lost(top, event, evsel);

View File

@ -60,12 +60,13 @@
#include "callchain.h"
#include "print_binary.h"
#include "string2.h"
#include "syscalltbl.h"
#include "trace/beauty/syscalltbl.h"
#include "../perf.h"
#include "trace_augment.h"
#include "dwarf-regs.h"
#include <errno.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <poll.h>
#include <signal.h>
@ -217,6 +218,7 @@ struct trace {
bool kernel_syscallchains;
s16 args_alignment;
bool show_tstamp;
bool show_cpu;
bool show_duration;
bool show_zeros;
bool show_arg_names;
@ -234,6 +236,16 @@ struct trace {
const char *uid_str;
};
bool trace__show_zeros(const struct trace *trace)
{
return trace->show_zeros;
}
struct machine *trace__host(const struct trace *trace)
{
return trace->host;
}
static void trace__load_vmlinux_btf(struct trace *trace __maybe_unused)
{
#ifdef HAVE_LIBBPF_SUPPORT
@ -535,12 +547,12 @@ static struct evsel *perf_evsel__raw_syscall_newtp(const char *direction, void *
return NULL;
}
#define perf_evsel__sc_tp_uint(evsel, name, sample) \
({ struct syscall_tp *fields = __evsel__syscall_tp(evsel); \
#define perf_evsel__sc_tp_uint(name, sample) \
({ struct syscall_tp *fields = __evsel__syscall_tp(sample->evsel); \
fields->name.integer(&fields->name, sample); })
#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
({ struct syscall_tp *fields = __evsel__syscall_tp(evsel); \
#define perf_evsel__sc_tp_ptr(name, sample) \
({ struct syscall_tp *fields = __evsel__syscall_tp(sample->evsel); \
fields->name.pointer(&fields->name, sample); })
size_t strarray__scnprintf_suffix(struct strarray *sa, char *bf, size_t size, const char *intfmt, bool show_suffix, int val)
@ -771,10 +783,6 @@ static const char *bpf_cmd[] = {
};
static DEFINE_STRARRAY(bpf_cmd, "BPF_");
#include "trace/beauty/generated/fsconfig_arrays.c"
static DEFINE_STRARRAY(fsconfig_cmds, "FSCONFIG_");
static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, "EPOLL_CTL_", 1);
@ -964,7 +972,7 @@ static bool syscall_arg__strtoul_btf_enum(char *bf, size_t size, struct syscall_
struct btf *btf = arg->trace->btf;
struct btf_enum *be = btf_enum(bt);
for (int i = 0; i < btf_vlen(bt); ++i, ++be) {
for (u32 i = 0; i < btf_vlen(bt); ++i, ++be) {
const char *name = btf__name_by_offset(btf, be->name_off);
int max_len = max(size, strlen(name));
@ -1009,9 +1017,9 @@ static bool syscall_arg__strtoul_btf_type(char *bf, size_t size, struct syscall_
static size_t btf_enum_scnprintf(const struct btf_type *type, struct btf *btf, char *bf, size_t size, int val)
{
struct btf_enum *be = btf_enum(type);
const int nr_entries = btf_vlen(type);
const unsigned int nr_entries = btf_vlen(type);
for (int i = 0; i < nr_entries; ++i, ++be) {
for (unsigned int i = 0; i < nr_entries; ++i, ++be) {
if (be->val == val) {
return scnprintf(bf, size, "%s",
btf__name_by_offset(btf, be->name_off));
@ -1123,21 +1131,6 @@ static bool syscall_arg__strtoul_btf_type(char *bf __maybe_unused, size_t size _
.parm = &strarray__##array, \
.show_zero = true, }
#include "trace/beauty/eventfd.c"
#include "trace/beauty/futex_op.c"
#include "trace/beauty/futex_val3.c"
#include "trace/beauty/mmap.c"
#include "trace/beauty/mode_t.c"
#include "trace/beauty/msg_flags.c"
#include "trace/beauty/open_flags.c"
#include "trace/beauty/perf_event_open.c"
#include "trace/beauty/pid.c"
#include "trace/beauty/sched_policy.c"
#include "trace/beauty/seccomp.c"
#include "trace/beauty/signum.c"
#include "trace/beauty/socket_type.c"
#include "trace/beauty/waitid_options.c"
static const struct syscall_fmt syscall_fmts[] = {
{ .name = "access",
.arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
@ -1528,6 +1521,7 @@ static size_t fprintf_duration(unsigned long t, bool calculated, FILE *fp)
*/
struct thread_trace {
u64 entry_time;
u32 entry_cpu;
bool entry_pending;
unsigned long nr_events;
unsigned long pfmaj, pfmin;
@ -1890,6 +1884,27 @@ static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
return fprintf(fp, " ? ");
}
/**
* trace__fprintf_cpu - Print the CPU ID to a given file stream
* @cpu: The CPU ID to print
* @fp: The file stream to write to
*
* Formats and prints the specified CPU ID enclosed in brackets
* (e.g., "[003] ") to the provided file pointer. It is used to
* align and display the CPU ID consistently within the trace output.
*
* Return: The number of characters printed.
*/
static size_t trace__fprintf_cpu(u32 cpu, FILE *fp)
{
size_t printed = 0;
if (cpu != (u32)-1)
printed += fprintf(fp, "[%03u] ", cpu);
return printed;
}
static pid_t workload_pid = -1;
static volatile sig_atomic_t done = false;
static volatile sig_atomic_t interrupted = false;
@ -1920,12 +1935,15 @@ static size_t trace__fprintf_comm_tid(struct trace *trace, struct thread *thread
}
static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
u64 duration, bool duration_calculated, u64 tstamp, FILE *fp)
u64 duration, bool duration_calculated,
u64 tstamp, u32 cpu, FILE *fp)
{
size_t printed = 0;
if (trace->show_tstamp)
printed = trace__fprintf_tstamp(trace, tstamp, fp);
if (trace->show_cpu && cpu != (u32)-1)
printed += trace__fprintf_cpu(cpu, fp);
if (trace->show_duration)
printed += fprintf_duration(duration, duration_calculated, fp);
return printed + trace__fprintf_comm_tid(trace, thread, fp);
@ -2579,7 +2597,7 @@ static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, i
return sc;
}
typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel,
typedef int (*tracepoint_handler)(struct trace *trace,
union perf_event *event,
struct perf_sample *sample);
@ -2704,7 +2722,9 @@ static int trace__printf_interrupted_entry(struct trace *trace)
if (!ttrace->entry_pending)
return 0;
printed = trace__fprintf_entry_head(trace, trace->current, 0, false, ttrace->entry_time, trace->output);
printed = trace__fprintf_entry_head(trace, trace->current, 0, false,
ttrace->entry_time, ttrace->entry_cpu,
trace->output);
printed += len = fprintf(trace->output, "%s)", ttrace->entry_str);
if (len < trace->args_alignment - 4)
@ -2718,8 +2738,8 @@ static int trace__printf_interrupted_entry(struct trace *trace)
return printed;
}
static int trace__fprintf_sample(struct trace *trace, struct evsel *evsel,
struct perf_sample *sample, struct thread *thread)
static int trace__fprintf_sample(struct trace *trace, struct perf_sample *sample,
struct thread *thread)
{
int printed = 0;
@ -2727,7 +2747,7 @@ static int trace__fprintf_sample(struct trace *trace, struct evsel *evsel,
double ts = (double)sample->time / NSEC_PER_MSEC;
printed += fprintf(trace->output, "%22s %10.3f %s %d/%d [%d]\n",
evsel__name(evsel), ts,
evsel__name(sample->evsel), ts,
thread__comm_str(thread),
sample->pid, sample->tid, sample->cpu);
}
@ -2774,15 +2794,16 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
return NULL;
}
static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
static int trace__sys_enter(struct trace *trace,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
struct evsel *evsel = sample->evsel;
char *msg;
void *args;
int printed = 0;
struct thread *thread;
int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
int id = perf_evsel__sc_tp_uint(id, sample), err = -1;
int augmented_args_size = 0, e_machine;
void *augmented_args = NULL;
struct syscall *sc;
@ -2797,9 +2818,9 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
if (ttrace == NULL)
goto out_put;
trace__fprintf_sample(trace, evsel, sample, thread);
trace__fprintf_sample(trace, sample, thread);
args = perf_evsel__sc_tp_ptr(evsel, args, sample);
args = perf_evsel__sc_tp_ptr(args, sample);
if (ttrace->entry_str == NULL) {
ttrace->entry_str = malloc(trace__entry_str_size);
@ -2822,6 +2843,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
if (evsel != trace->syscalls.events.sys_enter)
augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size);
ttrace->entry_time = sample->time;
ttrace->entry_cpu = sample->cpu;
msg = ttrace->entry_str;
printed += scnprintf(msg + printed, trace__entry_str_size - printed, "%s(", sc->name);
@ -2832,7 +2854,9 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
if (!(trace->duration_filter || trace->summary_only || trace->failure_only || trace->min_stack)) {
int alignment = 0;
trace__fprintf_entry_head(trace, thread, 0, false, ttrace->entry_time, trace->output);
trace__fprintf_entry_head(trace, thread, 0, false,
ttrace->entry_time,
sample->cpu, trace->output);
printed = fprintf(trace->output, "%s)", ttrace->entry_str);
if (trace->args_alignment > printed)
alignment = trace->args_alignment - printed;
@ -2854,12 +2878,11 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
return err;
}
static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
struct perf_sample *sample)
static int trace__fprintf_sys_enter(struct trace *trace, struct perf_sample *sample)
{
struct thread_trace *ttrace;
struct thread *thread;
int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
int id = perf_evsel__sc_tp_uint(id, sample), err = -1;
struct syscall *sc;
char msg[1024];
void *args, *augmented_args = NULL;
@ -2869,7 +2892,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
e_machine = thread__e_machine(thread, trace->host, /*e_flags=*/NULL);
sc = trace__syscall_info(trace, evsel, e_machine, id);
sc = trace__syscall_info(trace, sample->evsel, e_machine, id);
if (sc == NULL)
goto out_put;
ttrace = thread__trace(thread, trace);
@ -2880,7 +2903,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
if (ttrace == NULL)
goto out_put;
args = perf_evsel__sc_tp_ptr(evsel, args, sample);
args = perf_evsel__sc_tp_ptr(args, sample);
augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size);
printed += syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread);
fprintf(trace->output, "%.*s", (int)printed, msg);
@ -2890,10 +2913,11 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
return err;
}
static int trace__resolve_callchain(struct trace *trace, struct evsel *evsel,
static int trace__resolve_callchain(struct trace *trace,
struct perf_sample *sample,
struct callchain_cursor *cursor)
{
struct evsel *evsel = sample->evsel;
struct addr_location al;
int max_stack = evsel->core.attr.sample_max_stack ?
evsel->core.attr.sample_max_stack :
@ -2904,7 +2928,7 @@ static int trace__resolve_callchain(struct trace *trace, struct evsel *evsel,
if (machine__resolve(trace->host, &al, sample) < 0)
goto out;
err = thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack);
err = thread__resolve_callchain(al.thread, cursor, sample, NULL, NULL, max_stack);
out:
addr_location__exit(&al);
return err;
@ -2920,15 +2944,16 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sam
return sample__fprintf_callchain(sample, 38, print_opts, get_tls_callchain_cursor(), symbol_conf.bt_stop_list, trace->output);
}
static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
static int trace__sys_exit(struct trace *trace,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
struct evsel *evsel = sample->evsel;
long ret;
u64 duration = 0;
bool duration_calculated = false;
struct thread *thread;
int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
int id = perf_evsel__sc_tp_uint(id, sample), err = -1, callchain_ret = 0, printed = 0;
int alignment = trace->args_alignment, e_machine;
struct syscall *sc;
struct thread_trace *ttrace;
@ -2942,9 +2967,9 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
if (ttrace == NULL)
goto out_put;
trace__fprintf_sample(trace, evsel, sample, thread);
trace__fprintf_sample(trace, sample, thread);
ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
ret = perf_evsel__sc_tp_uint(ret, sample);
if (trace->summary)
thread__update_stats(thread, ttrace, id, sample, ret, trace);
@ -2966,7 +2991,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
if (sample->callchain) {
struct callchain_cursor *cursor = get_tls_callchain_cursor();
callchain_ret = trace__resolve_callchain(trace, evsel, sample, cursor);
callchain_ret = trace__resolve_callchain(trace, sample, cursor);
if (callchain_ret == 0) {
if (cursor->nr < trace->min_stack)
goto out;
@ -2977,7 +3002,9 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
if (trace->summary_only || (ret >= 0 && trace->failure_only))
goto out;
trace__fprintf_entry_head(trace, thread, duration, duration_calculated, ttrace->entry_time, trace->output);
trace__fprintf_entry_head(trace, thread, duration,
duration_calculated, ttrace->entry_time,
sample->cpu, trace->output);
if (ttrace->entry_pending) {
printed = fprintf(trace->output, "%s", ttrace->entry_str);
@ -3005,9 +3032,8 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
} else if (ret < 0) {
errno_print: {
char bf[STRERR_BUFSIZE];
struct perf_env *env = evsel__env(evsel) ?: &trace->host_env;
const char *emsg = str_error_r(-ret, bf, sizeof(bf));
const char *e = perf_env__arch_strerrno(env, err);
const char *e = perf_env__arch_strerrno(e_machine, err);
fprintf(trace->output, "-1 %s (%s)", e, emsg);
}
@ -3058,7 +3084,7 @@ errno_print: {
return err;
}
static int trace__vfs_getname(struct trace *trace, struct evsel *evsel,
static int trace__vfs_getname(struct trace *trace,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
@ -3067,7 +3093,7 @@ static int trace__vfs_getname(struct trace *trace, struct evsel *evsel,
size_t filename_len, entry_str_len, to_move;
ssize_t remaining_space;
char *pos;
const char *filename = evsel__rawptr(evsel, sample, "pathname");
const char *filename = perf_sample__strval(sample, "pathname");
if (!thread)
goto out;
@ -3119,11 +3145,11 @@ static int trace__vfs_getname(struct trace *trace, struct evsel *evsel,
return 0;
}
static int trace__sched_stat_runtime(struct trace *trace, struct evsel *evsel,
static int trace__sched_stat_runtime(struct trace *trace,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
u64 runtime = evsel__intval(evsel, sample, "runtime");
u64 runtime = perf_sample__intval(sample, "runtime");
double runtime_ms = (double)runtime / NSEC_PER_MSEC;
struct thread *thread = machine__findnew_thread(trace->host,
sample->pid,
@ -3141,11 +3167,11 @@ static int trace__sched_stat_runtime(struct trace *trace, struct evsel *evsel,
out_dump:
fprintf(trace->output, "%s: comm=%s,pid=%u,runtime=%" PRIu64 ",vruntime=%" PRIu64 ")\n",
evsel->name,
evsel__strval(evsel, sample, "comm"),
(pid_t)evsel__intval(evsel, sample, "pid"),
sample->evsel->name,
perf_sample__strval(sample, "comm"),
(pid_t)perf_sample__intval(sample, "pid"),
runtime,
evsel__intval(evsel, sample, "vruntime"));
perf_sample__intval(sample, "vruntime"));
goto out_put;
}
@ -3181,9 +3207,10 @@ static void bpf_output__fprintf(struct trace *trace,
++trace->nr_events_printed;
}
static size_t trace__fprintf_tp_fields(struct trace *trace, struct evsel *evsel, struct perf_sample *sample,
static size_t trace__fprintf_tp_fields(struct trace *trace, struct perf_sample *sample,
struct thread *thread, void *augmented_args, int augmented_args_size)
{
struct evsel *evsel = sample->evsel;
char bf[2048];
size_t size = sizeof(bf);
const struct tep_event *tp_format = evsel__tp_format(evsel);
@ -3234,6 +3261,27 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct evsel *evsel,
if (val == 0 && !trace->show_zeros && !arg->show_zero && arg->strtoul != STUL_BTF_TYPE)
continue;
/*
* __probe_ip is implicitly added to bare dynamic probes.
* Suppress it by default to avoid cluttering the output.
* If verbose mode is enabled, ensure it is formatted as a
* hexadecimal memory address rather than a signed integer.
*/
if (evsel__is_probe(evsel) && !strcmp(field->name, "__probe_ip")) {
if (!verbose)
continue;
printed += scnprintf(bf + printed, size - printed,
"%s", printed ? ", " : "");
if (trace->show_arg_names)
printed += scnprintf(bf + printed, size - printed,
"%s: ", field->name);
printed += scnprintf(bf + printed, size - printed, "%#016llx",
(unsigned long long)val);
continue;
}
printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : "");
if (trace->show_arg_names)
@ -3251,10 +3299,11 @@ static size_t trace__fprintf_tp_fields(struct trace *trace, struct evsel *evsel,
return fprintf(trace->output, "%.*s", (int)printed, bf);
}
static int trace__event_handler(struct trace *trace, struct evsel *evsel,
static int trace__event_handler(struct trace *trace,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
struct evsel *evsel = sample->evsel;
struct thread *thread;
int callchain_ret = 0;
@ -3266,7 +3315,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
if (sample->callchain) {
struct callchain_cursor *cursor = get_tls_callchain_cursor();
callchain_ret = trace__resolve_callchain(trace, evsel, sample, cursor);
callchain_ret = trace__resolve_callchain(trace, sample, cursor);
if (callchain_ret == 0) {
if (cursor->nr < trace->min_stack)
goto out;
@ -3277,6 +3326,9 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
trace__printf_interrupted_entry(trace);
trace__fprintf_tstamp(trace, sample->time, trace->output);
if (trace->show_cpu)
trace__fprintf_cpu(sample->cpu, trace->output);
if (trace->trace_syscalls && trace->show_duration)
fprintf(trace->output, "( ): ");
@ -3284,7 +3336,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
trace__fprintf_comm_tid(trace, thread, trace->output);
if (evsel == trace->syscalls.events.bpf_output) {
int id = perf_evsel__sc_tp_uint(evsel, id, sample);
int id = perf_evsel__sc_tp_uint(id, sample);
int e_machine = thread
? thread__e_machine(thread, trace->host, /*e_flags=*/NULL)
: EM_HOST;
@ -3292,7 +3344,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
if (sc) {
fprintf(trace->output, "%s(", sc->name);
trace__fprintf_sys_enter(trace, evsel, sample);
trace__fprintf_sys_enter(trace, sample);
fputc(')', trace->output);
goto newline;
}
@ -3312,13 +3364,13 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
const struct tep_event *tp_format = evsel__tp_format(evsel);
if (tp_format && (strncmp(tp_format->name, "sys_enter_", 10) ||
trace__fprintf_sys_enter(trace, evsel, sample))) {
trace__fprintf_sys_enter(trace, sample))) {
if (trace->libtraceevent_print) {
event_format__fprintf(tp_format, sample->cpu,
sample->raw_data, sample->raw_size,
trace->output);
} else {
trace__fprintf_tp_fields(trace, evsel, sample, thread, NULL, 0);
trace__fprintf_tp_fields(trace, sample, thread, NULL, 0);
}
}
}
@ -3360,7 +3412,6 @@ static void print_location(FILE *f, struct perf_sample *sample,
}
static int trace__pgfault(struct trace *trace,
struct evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
{
@ -3377,7 +3428,7 @@ static int trace__pgfault(struct trace *trace,
if (sample->callchain) {
struct callchain_cursor *cursor = get_tls_callchain_cursor();
callchain_ret = trace__resolve_callchain(trace, evsel, sample, cursor);
callchain_ret = trace__resolve_callchain(trace, sample, cursor);
if (callchain_ret == 0) {
if (cursor->nr < trace->min_stack)
goto out_put;
@ -3389,7 +3440,7 @@ static int trace__pgfault(struct trace *trace,
if (ttrace == NULL)
goto out_put;
if (evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ) {
if (sample->evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ) {
ttrace->pfmaj++;
trace->pfmaj++;
} else {
@ -3402,10 +3453,11 @@ static int trace__pgfault(struct trace *trace,
thread__find_symbol(thread, sample->cpumode, sample->ip, &al);
trace__fprintf_entry_head(trace, thread, 0, true, sample->time, trace->output);
trace__fprintf_entry_head(trace, thread, 0, true, sample->time,
sample->cpu, trace->output);
fprintf(trace->output, "%sfault [",
evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
sample->evsel->core.attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ?
"maj" : "min");
print_location(trace->output, sample, &al, false, true);
@ -3430,7 +3482,8 @@ static int trace__pgfault(struct trace *trace,
if (callchain_ret > 0)
trace__fprintf_callchain(trace, sample);
else if (callchain_ret < 0)
pr_err("Problem processing %s callchain, skipping...\n", evsel__name(evsel));
pr_err("Problem processing %s callchain, skipping...\n",
evsel__name(sample->evsel));
++trace->nr_events_printed;
out:
@ -3442,7 +3495,6 @@ static int trace__pgfault(struct trace *trace,
}
static void trace__set_base_time(struct trace *trace,
struct evsel *evsel,
struct perf_sample *sample)
{
/*
@ -3454,17 +3506,17 @@ static void trace__set_base_time(struct trace *trace,
* appears in our event stream (vfs_getname comes to mind).
*/
if (trace->base_time == 0 && !trace->full_time &&
(evsel->core.attr.sample_type & PERF_SAMPLE_TIME))
(sample->evsel->core.attr.sample_type & PERF_SAMPLE_TIME))
trace->base_time = sample->time;
}
static int trace__process_sample(const struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
struct machine *machine __maybe_unused)
{
struct trace *trace = container_of(tool, struct trace, tool);
struct evsel *evsel = sample->evsel;
struct thread *thread;
int err = 0;
@ -3474,11 +3526,11 @@ static int trace__process_sample(const struct perf_tool *tool,
if (thread && thread__is_filtered(thread))
goto out;
trace__set_base_time(trace, evsel, sample);
trace__set_base_time(trace, sample);
if (handler) {
++trace->nr_events;
handler(trace, evsel, event, sample);
handler(trace, event, sample);
}
out:
thread__put(thread);
@ -3620,32 +3672,34 @@ static void evlist__free_syscall_tp_fields(struct evlist *evlist)
static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
{
const u32 type = event->header.type;
struct evsel *evsel;
if (type != PERF_RECORD_SAMPLE) {
trace__process_event(trace, trace->host, event, sample);
return;
}
evsel = evlist__id2evsel(trace->evlist, sample->id);
if (evsel == NULL) {
if (sample->evsel == NULL)
sample->evsel = evlist__id2evsel(trace->evlist, sample->id);
if (sample->evsel == NULL) {
fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
return;
}
if (evswitch__discard(&trace->evswitch, evsel))
if (evswitch__discard(&trace->evswitch, sample->evsel))
return;
trace__set_base_time(trace, evsel, sample);
trace__set_base_time(trace, sample);
if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT &&
if (sample->evsel->core.attr.type == PERF_TYPE_TRACEPOINT &&
sample->raw_data == NULL) {
fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
evsel__name(evsel), sample->tid,
evsel__name(sample->evsel), sample->tid,
sample->cpu, sample->raw_size);
} else {
tracepoint_handler handler = evsel->handler;
handler(trace, evsel, event, sample);
tracepoint_handler handler = sample->evsel->handler;
handler(trace, event, sample);
}
if (trace->nr_events_printed >= trace->max_events && trace->max_events != ULONG_MAX)
@ -4887,7 +4941,9 @@ static size_t syscall__dump_stats(struct trace *trace, int e_machine, FILE *fp,
for (e = 0; e < stats->max_errno; ++e) {
if (stats->errnos[e] != 0)
fprintf(fp, "\t\t\t\t%s: %d\n", perf_env__arch_strerrno(trace->host->env, e + 1), stats->errnos[e]);
fprintf(fp, "\t\t\t\t%s: %d\n",
perf_env__arch_strerrno(e_machine, e + 1),
stats->errnos[e]);
}
}
lines++;
@ -5429,6 +5485,7 @@ int cmd_trace(int argc, const char **argv)
OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
"number of mmap data pages", evlist__parse_mmap_pages),
OPT_STRING('u', "uid", &trace.uid_str, "user", "user to profile"),
OPT_BOOLEAN(0, "show-cpu", &trace.show_cpu, "show cpu id"),
OPT_CALLBACK(0, "duration", &trace, "float",
"show only events with duration > N.M ms",
trace__set_duration),
@ -5563,6 +5620,9 @@ int cmd_trace(int argc, const char **argv)
goto out;
}
if (trace.show_cpu)
trace.opts.sample_cpu = true;
if ((nr_cgroups || trace.cgroup) && !trace.opts.target.system_wide) {
usage_with_options_msg(trace_usage, trace_options,
"cgroup monitoring only available in system-wide mode");

View File

@ -1,7 +1,12 @@
EMPTY_PMU_EVENTS_C = pmu-events/empty-pmu-events.c
# pmu-events.c will be generated by jevents.py or copied from EMPTY_PMU_EVENTS_C
PMU_EVENTS_C = $(OUTPUT)pmu-events/pmu-events.c
PMU_EVENTS_STRING_C = $(OUTPUT)pmu-events/pmu-events-string.c
pmu-events-y += pmu-events.o
ifneq ($(NO_JEVENTS),1)
pmu-events-y += pmu-events-string.o
endif
# pmu-events.c file is generated in the OUTPUT directory so it needs a
# separate rule to depend on it properly
@ -9,6 +14,10 @@ $(OUTPUT)pmu-events/pmu-events.o: $(PMU_EVENTS_C)
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
$(OUTPUT)pmu-events/pmu-events-string.o: $(PMU_EVENTS_STRING_C)
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
# Message for $(call echo-cmd,cp), possibly remove the src file from
# the destination to save space in the build log.
quiet_cmd_cp = COPY $(patsubst %$<,%,$@) <- $<
@ -47,12 +56,12 @@ $(LEGACY_CACHE_JSON): $(LEGACY_CACHE_PY)
# Python to generate architectural metrics
GEN_METRIC_DEPS := pmu-events/metric.py pmu-events/common_metrics.py
# Functions to extract the model from an extra-metrics.json or extra-metricgroups.json path.
model_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/extra-metric.*\.json@\1@')
vendor_name = $(shell echo $(1)|sed -e 's@.\+/\(.*\)/[^/]*/extra-metric.*\.json@\1@')
model_name = $(notdir $(patsubst %/,%,$(dir $(1))))
vendor_name = $(notdir $(patsubst %/,%,$(dir $(patsubst %/,%,$(dir $(1))))))
ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all))
# Generate AMD Json
ZENS = $(shell ls -d pmu-events/arch/x86/amdzen*)
ZENS := $(shell ls -d pmu-events/arch/x86/amdzen*)
ZEN_METRICS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metrics.json)
ZEN_METRICGROUPS = $(foreach x,$(ZENS),$(OUTPUT)$(x)/extra-metricgroups.json)
GEN_JSON += $(ZEN_METRICS) $(ZEN_METRICGROUPS)
@ -69,7 +78,7 @@ endif
ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),arm64 all))
# Generate ARM Json
ARMS = $(shell ls -d pmu-events/arch/arm64/arm/*|grep -v cmn)
ARMS := $(shell ls -d pmu-events/arch/arm64/arm/*|grep -v cmn)
ARM_METRICS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metrics.json)
ARM_METRICGROUPS = $(foreach x,$(ARMS),$(OUTPUT)$(x)/extra-metricgroups.json)
GEN_JSON += $(ARM_METRICS) $(ARM_METRICGROUPS)
@ -86,7 +95,7 @@ endif
ifeq ($(JEVENTS_ARCH),$(filter $(JEVENTS_ARCH),x86 all))
# Generate Intel Json
INTELS = $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v mapfile.csv)
INTELS := $(shell ls -d pmu-events/arch/x86/*|grep -v amdzen|grep -v mapfile.csv)
INTEL_METRICS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metrics.json)
INTEL_METRICGROUPS = $(foreach x,$(INTELS),$(OUTPUT)$(x)/extra-metricgroups.json)
GEN_JSON += $(INTEL_METRICS) $(INTEL_METRICGROUPS)
@ -118,6 +127,7 @@ CUR_OUT_JSON := $(shell [ -d $(OUT_DIR) ] && find $(OUT_DIR) -type f)
# Things in the OUTPUT directory but shouldn't be there as computed by
# OUT_JSON and GEN_JSON.
ORPHAN_FILES := $(filter-out $(OUT_JSON) $(GEN_JSON),$(CUR_OUT_JSON))
# Message for $(call echo-cmd,mkd). There is already a mkdir message
@ -224,6 +234,10 @@ endif
# and inputs are dependencies.
$(PMU_EVENTS_C): $(JEVENTS_DEPS)
$(call rule_mkdir)
$(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) $(OUT_DIR) $@
$(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(JEVENTS_ARCH) $(JEVENTS_MODEL) \
$(OUT_DIR) $(PMU_EVENTS_C) $(PMU_EVENTS_STRING_C)
$(PMU_EVENTS_STRING_C): $(PMU_EVENTS_C)
@:
endif # ifeq ($(NO_JEVENTS),1)

View File

@ -265,10 +265,66 @@ def AmdDtlb() -> Optional[MetricGroup]:
], description="Data TLB metrics")
def AmdIotlb() -> Optional[MetricGroup]:
global _zen_model
if _zen_model < 2:
return None
# On AMD, the pde events cover both 2M and 1G pages.
total_hit = Event("amd_iommu/mem_iommu_tlb_pte_hit/") + Event(
"amd_iommu/mem_iommu_tlb_pde_hit/"
)
total_miss = Event("amd_iommu/mem_iommu_tlb_pte_mis/") + Event(
"amd_iommu/mem_iommu_tlb_pde_mis/"
)
miss_rate = d_ratio(total_miss, total_miss + total_hit)
interrupt_cache_hit = Event("amd_iommu/int_dte_hit/")
interrupt_cache_miss = Event("amd_iommu/int_dte_mis/")
interrupt_cache_lookup = interrupt_cache_hit + interrupt_cache_miss
interrupt_cache_miss_rate = d_ratio(
interrupt_cache_miss, interrupt_cache_miss + interrupt_cache_hit
)
return MetricGroup(
"iotlb",
[
Metric("iotlb_total_hit", "IOTLB total hit", total_hit, "hits"),
Metric("iotlb_total_miss", "IOTLB total miss", total_miss, "misses"),
Metric("iotlb_miss_rate", "IOTLB miss rate", miss_rate, "100%"),
Metric(
"iotlb_interrupt_cache_hit",
"IOTLB interrupt cache hit",
interrupt_cache_hit,
"hits",
),
Metric(
"iotlb_interrupt_cache_miss",
"IOTLB interrupt cache miss",
interrupt_cache_miss,
"misses",
),
Metric(
"iotlb_interrupt_cache_lookup",
"IOTLB interrupt cache lookup",
interrupt_cache_lookup,
"lookups",
),
Metric(
"iotlb_interrupt_cache_miss_rate",
"IOTLB interrupt cache miss rate",
interrupt_cache_miss_rate,
"100%",
),
],
description="IOMMU TLB metrics",
)
def AmdItlb():
global _zen_model
l2h = Event("bp_l1_tlb_miss_l2_tlb_hit", "bp_l1_tlb_miss_l2_hit")
l2m = Event("l2_itlb_misses")
l2m = Event("bp_l1_tlb_miss_l2_tlb_miss.all", "l2_itlb_misses",)
l2r = l2h + l2m
itlb_l1_mg = None
@ -473,6 +529,7 @@ def main() -> None:
AmdBr(),
AmdCtxSw(),
AmdDtlb(),
AmdIotlb(),
AmdItlb(),
AmdLdSt(),
AmdUpc(),

View File

@ -150,6 +150,16 @@
"UMask": "0x2",
"Unit": "cpu_atom"
},
{
"BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]",
"Counter": "0,1,2,3",
"EventCode": "0x24",
"EventName": "L2_REQUEST.HIT",
"PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]",
"SampleAfterValue": "200003",
"UMask": "0xdf",
"Unit": "cpu_core"
},
{
"BriefDescription": "Counts the number of L2 Cache accesses that resulted in a miss. Counts on a per core basis.",
"Counter": "0,1,2,3,4,5",
@ -259,6 +269,16 @@
"UMask": "0x21",
"Unit": "cpu_core"
},
{
"BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]",
"Counter": "0,1,2,3",
"EventCode": "0x24",
"EventName": "L2_RQSTS.HIT",
"PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]",
"SampleAfterValue": "200003",
"UMask": "0xdf",
"Unit": "cpu_core"
},
{
"BriefDescription": "L2_RQSTS.HWPF_MISS",
"Counter": "0,1,2,3",
@ -338,6 +358,16 @@
"UMask": "0x40",
"Unit": "cpu_core"
},
{
"BriefDescription": "Cycles when L1D is locked",
"Counter": "0,1,2,3",
"EventCode": "0x42",
"EventName": "LOCK_CYCLES.CACHE_LOCK_DURATION",
"PublicDescription": "This event counts the number of cycles when the L1D is locked. It is a superset of the 0x1 mask (BUS_LOCK_CLOCKS.BUS_LOCK_DURATION).",
"SampleAfterValue": "2000003",
"UMask": "0x2",
"Unit": "cpu_core"
},
{
"BriefDescription": "Counts the number of cacheable memory requests that miss in the LLC. Counts on a per core basis.",
"Counter": "0,1,2,3,4,5",
@ -853,6 +883,17 @@
"UMask": "0x1",
"Unit": "cpu_core"
},
{
"BriefDescription": "Counts the number of memory uops retired.",
"Counter": "0,1,2,3,4,5",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.ALL",
"PublicDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST)",
"SampleAfterValue": "200003",
"UMask": "0x83",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of load uops retired.",
"Counter": "0,1,2,3,4,5",
@ -875,6 +916,18 @@
"UMask": "0x82",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024. Only counts with PEBS enabled.",
"Counter": "0,1",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024",
"MSRIndex": "0x3F6",
"MSRValue": "0x400",
"SampleAfterValue": "1000003",
"UMask": "0x5",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128. Only counts with PEBS enabled.",
"Counter": "0,1",
@ -899,6 +952,18 @@
"UMask": "0x5",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048. Only counts with PEBS enabled.",
"Counter": "0,1",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048",
"MSRIndex": "0x3F6",
"MSRValue": "0x800",
"SampleAfterValue": "1000003",
"UMask": "0x5",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256. Only counts with PEBS enabled.",
"Counter": "0,1",
@ -981,6 +1046,16 @@
"UMask": "0x21",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of memory uops retired that were splits.",
"Counter": "0,1,2,3,4,5",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.SPLIT",
"SampleAfterValue": "200003",
"UMask": "0x43",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of retired split load uops.",
"Counter": "0,1,2,3,4,5",
@ -991,6 +1066,16 @@
"UMask": "0x41",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of retired split store uops.",
"Counter": "0,1,2,3,4,5",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
"SampleAfterValue": "200003",
"UMask": "0x42",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the total number of load and store uops retired that missed in the second level TLB.",
"Counter": "0,1,2,3,4,5",

View File

@ -9,6 +9,15 @@
"UMask": "0x6",
"Unit": "cpu_core"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.ANY",
"SampleAfterValue": "1000003",
"UMask": "0x7f",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block, on a load that retires.",
"Counter": "0,1,2,3,4,5",
@ -27,6 +36,15 @@
"UMask": "0xf4",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DL1 miss.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.L1_MISS",
"SampleAfterValue": "1000003",
"UMask": "0x1",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DL1 miss.",
"Counter": "0,1,2,3,4,5",
@ -36,6 +54,16 @@
"UMask": "0x81",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.OTHER",
"PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases such as pipeline conflicts, fences, etc.",
"SampleAfterValue": "1000003",
"UMask": "0x40",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases.",
"Counter": "0,1,2,3,4,5",
@ -46,6 +74,15 @@
"UMask": "0xc0",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a pagewalk.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.PGWALK",
"SampleAfterValue": "1000003",
"UMask": "0x20",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a pagewalk.",
"Counter": "0,1,2,3,4,5",
@ -55,6 +92,15 @@
"UMask": "0xa0",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a store data forward block.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.ST_ADDR",
"SampleAfterValue": "1000003",
"UMask": "0x4",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a store address match.",
"Counter": "0,1,2,3,4,5",
@ -64,6 +110,24 @@
"UMask": "0x84",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.WCB_FULL",
"SampleAfterValue": "1000003",
"UMask": "0x2",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to request buffers full or lock in progress.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.WCB_FULL_AT_RET",
"SampleAfterValue": "1000003",
"UMask": "0x82",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of machine clears due to memory ordering caused by a snoop from an external agent. Does not count internally generated machine clears such as those due to memory disambiguation.",
"Counter": "0,1,2,3,4,5",

View File

@ -349,6 +349,15 @@
"UMask": "0xfd",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of near relative JMP branch instructions retired.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xc4",
"EventName": "BR_INST_RETIRED.REL_JMP",
"SampleAfterValue": "200003",
"UMask": "0xdf",
"Unit": "cpu_atom"
},
{
"BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.NEAR_RETURN",
"Counter": "0,1,2,3,4,5",
@ -359,6 +368,15 @@
"UMask": "0xf7",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of taken branch instructions retired.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xc4",
"EventName": "BR_INST_RETIRED.TAKEN",
"SampleAfterValue": "200003",
"UMask": "0x80",
"Unit": "cpu_atom"
},
{
"BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.COND_TAKEN",
"Counter": "0,1,2,3,4,5",
@ -560,6 +578,15 @@
"UMask": "0xfe",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the total number of BTCLEARS.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xe8",
"EventName": "BTCLEAR.ANY",
"PublicDescription": "Counts the total number of BTCLEARS which occurs when the Branch Target Buffer (BTB) predicts a taken branch.",
"SampleAfterValue": "200003",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Core clocks when the thread is in the C0.1 light-weight slower wakeup time but more power saving optimized state.",
"Counter": "0,1,2,3,4,5,6,7",
@ -1214,6 +1241,24 @@
"UMask": "0x8",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xc3",
"EventName": "MACHINE_CLEARS.FAST",
"SampleAfterValue": "20003",
"UMask": "0x10",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of virtual traps taken.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xc3",
"EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP",
"SampleAfterValue": "20003",
"UMask": "0x40",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of machines clears due to memory renaming.",
"Counter": "0,1,2,3,4,5",
@ -1410,6 +1455,15 @@
"UMask": "0x4",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number issue slots not consumed due to a color request for an FCW or MXCSR control register when all 4 colors (copies) are already in use.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x75",
"EventName": "SERIALIZATION.COLOR_STALLS",
"SampleAfterValue": "200003",
"UMask": "0x8",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires.",
"Counter": "0,1,2,3,4,5",

View File

@ -250,6 +250,15 @@
"UMask": "0x10",
"Unit": "cpu_core"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DTLB miss.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.DTLB_MISS",
"SampleAfterValue": "1000003",
"UMask": "0x10",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DTLB miss.",
"Counter": "0,1,2,3,4,5",

View File

@ -225,6 +225,16 @@
"SampleAfterValue": "20003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of memory uops retired.",
"Counter": "0,1,2,3,4,5",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.ALL",
"PublicDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST)",
"SampleAfterValue": "200003",
"UMask": "0x83"
},
{
"BriefDescription": "Counts the number of load uops retired.",
"Counter": "0,1,2,3,4,5",
@ -245,6 +255,17 @@
"SampleAfterValue": "200003",
"UMask": "0x82"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024. Only counts with PEBS enabled.",
"Counter": "0,1",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024",
"MSRIndex": "0x3F6",
"MSRValue": "0x400",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128. Only counts with PEBS enabled.",
"Counter": "0,1",
@ -267,6 +288,17 @@
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048. Only counts with PEBS enabled.",
"Counter": "0,1",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048",
"MSRIndex": "0x3F6",
"MSRValue": "0x800",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256. Only counts with PEBS enabled.",
"Counter": "0,1",
@ -342,6 +374,15 @@
"SampleAfterValue": "200003",
"UMask": "0x21"
},
{
"BriefDescription": "Counts the number of memory uops retired that were splits.",
"Counter": "0,1,2,3,4,5",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.SPLIT",
"SampleAfterValue": "200003",
"UMask": "0x43"
},
{
"BriefDescription": "Counts the number of retired split load uops.",
"Counter": "0,1,2,3,4,5",
@ -351,6 +392,15 @@
"SampleAfterValue": "200003",
"UMask": "0x41"
},
{
"BriefDescription": "Counts the number of retired split store uops.",
"Counter": "0,1,2,3,4,5",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
"SampleAfterValue": "200003",
"UMask": "0x42"
},
{
"BriefDescription": "Counts the total number of load and store uops retired that missed in the second level TLB.",
"Counter": "0,1,2,3,4,5",

View File

@ -1,4 +1,12 @@
[
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.ANY",
"SampleAfterValue": "1000003",
"UMask": "0x7f"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to any number of reasons, including an L1 miss, WCB full, pagewalk, store address block or store data block, on a load that retires.",
"Counter": "0,1,2,3,4,5",
@ -15,6 +23,14 @@
"SampleAfterValue": "1000003",
"UMask": "0xf4"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DL1 miss.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.L1_MISS",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DL1 miss.",
"Counter": "0,1,2,3,4,5",
@ -23,6 +39,15 @@
"SampleAfterValue": "1000003",
"UMask": "0x81"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.OTHER",
"PublicDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to other block cases such as pipeline conflicts, fences, etc.",
"SampleAfterValue": "1000003",
"UMask": "0x40"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to other block cases.",
"Counter": "0,1,2,3,4,5",
@ -32,6 +57,14 @@
"SampleAfterValue": "1000003",
"UMask": "0xc0"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a pagewalk.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.PGWALK",
"SampleAfterValue": "1000003",
"UMask": "0x20"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a pagewalk.",
"Counter": "0,1,2,3,4,5",
@ -40,6 +73,14 @@
"SampleAfterValue": "1000003",
"UMask": "0xa0"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a store data forward block.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.ST_ADDR",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a store address match.",
"Counter": "0,1,2,3,4,5",
@ -48,6 +89,22 @@
"SampleAfterValue": "1000003",
"UMask": "0x84"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to request buffers full or lock in progress.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.WCB_FULL",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to request buffers full or lock in progress.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.WCB_FULL_AT_RET",
"SampleAfterValue": "1000003",
"UMask": "0x82"
},
{
"BriefDescription": "Counts the number of machine clears due to memory ordering caused by a snoop from an external agent. Does not count internally generated machine clears such as those due to memory disambiguation.",
"Counter": "0,1,2,3,4,5",

View File

@ -175,6 +175,14 @@
"SampleAfterValue": "200003",
"UMask": "0xfd"
},
{
"BriefDescription": "Counts the number of near relative JMP branch instructions retired.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xc4",
"EventName": "BR_INST_RETIRED.REL_JMP",
"SampleAfterValue": "200003",
"UMask": "0xdf"
},
{
"BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.NEAR_RETURN",
"Counter": "0,1,2,3,4,5",
@ -184,6 +192,14 @@
"SampleAfterValue": "200003",
"UMask": "0xf7"
},
{
"BriefDescription": "Counts the number of taken branch instructions retired.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xc4",
"EventName": "BR_INST_RETIRED.TAKEN",
"SampleAfterValue": "200003",
"UMask": "0x80"
},
{
"BriefDescription": "This event is deprecated. Refer to new event BR_INST_RETIRED.COND_TAKEN",
"Counter": "0,1,2,3,4,5",
@ -293,6 +309,14 @@
"SampleAfterValue": "200003",
"UMask": "0xfe"
},
{
"BriefDescription": "Counts the total number of BTCLEARS.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xe8",
"EventName": "BTCLEAR.ANY",
"PublicDescription": "Counts the total number of BTCLEARS which occurs when the Branch Target Buffer (BTB) predicts a taken branch.",
"SampleAfterValue": "200003"
},
{
"BriefDescription": "Fixed Counter: Counts the number of unhalted core clock cycles. [This event is alias to CPU_CLK_UNHALTED.THREAD]",
"Counter": "Fixed counter 1",
@ -400,6 +424,22 @@
"SampleAfterValue": "20003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xc3",
"EventName": "MACHINE_CLEARS.FAST",
"SampleAfterValue": "20003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of virtual traps taken.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0xc3",
"EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP",
"SampleAfterValue": "20003",
"UMask": "0x40"
},
{
"BriefDescription": "Counts the number of machines clears due to memory renaming.",
"Counter": "0,1,2,3,4,5",
@ -482,6 +522,14 @@
"SampleAfterValue": "200003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number issue slots not consumed due to a color request for an FCW or MXCSR control register when all 4 colors (copies) are already in use.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x75",
"EventName": "SERIALIZATION.COLOR_STALLS",
"SampleAfterValue": "200003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of issue slots not consumed by the backend due to a micro-sequencer (MS) scoreboard, which stalls the front-end from issuing from the UROM until a specified older uop retires.",
"Counter": "0,1,2,3,4,5",

View File

@ -42,6 +42,14 @@
"SampleAfterValue": "200003",
"UMask": "0xe"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer is stalled due to a DTLB miss.",
"Counter": "0,1,2,3,4,5",
"EventCode": "0x05",
"EventName": "LD_HEAD.DTLB_MISS",
"SampleAfterValue": "1000003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of cycles that the head (oldest load) of the load buffer and retirement are both stalled due to a DTLB miss.",
"Counter": "0,1,2,3,4,5",

View File

@ -339,6 +339,16 @@
"UMask": "0x2",
"Unit": "cpu_atom"
},
{
"BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]",
"Counter": "0,1,2,3,4,5,6,7,8,9",
"EventCode": "0x24",
"EventName": "L2_REQUEST.HIT",
"PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_RQSTS.HIT]",
"SampleAfterValue": "200003",
"UMask": "0x5f",
"Unit": "cpu_core"
},
{
"BriefDescription": "Counts the number of L2 Cache Accesses that resulted in a Hit from a front door request only (does not include rejects or recycles), per core event",
"Counter": "0,1,2,3,4,5,6,7",
@ -464,6 +474,16 @@
"UMask": "0x21",
"Unit": "cpu_core"
},
{
"BriefDescription": "All requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]",
"Counter": "0,1,2,3,4,5,6,7,8,9",
"EventCode": "0x24",
"EventName": "L2_RQSTS.HIT",
"PublicDescription": "Counts all requests that hit L2 cache. [This event is alias to L2_REQUEST.HIT]",
"SampleAfterValue": "200003",
"UMask": "0x5f",
"Unit": "cpu_core"
},
{
"BriefDescription": "Read requests with true-miss in L2 cache [This event is alias to L2_REQUEST.MISS]",
"Counter": "0,1,2,3,4,5,6,7,8,9",
@ -1126,6 +1146,15 @@
"UMask": "0x20",
"Unit": "cpu_core"
},
{
"BriefDescription": "Counts the number of retired load ops that hit in the L3 cache in which a snoop was required and modified data was forwarded",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd4",
"EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_HITM",
"SampleAfterValue": "1000003",
"UMask": "0x8",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of retired load ops with an unknown source",
"Counter": "0,1,2,3,4,5,6,7",
@ -1393,6 +1422,18 @@
"UMask": "0x82",
"Unit": "cpu_lowpower"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024.",
"Counter": "0,1",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024",
"MSRIndex": "0x3F6",
"MSRValue": "0x400",
"SampleAfterValue": "200003",
"UMask": "0x5",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024. Only counts with PEBS enabled.",
"Counter": "0,1",
@ -1453,6 +1494,18 @@
"UMask": "0x5",
"Unit": "cpu_lowpower"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048.",
"Counter": "0,1",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048",
"MSRIndex": "0x3F6",
"MSRValue": "0x800",
"SampleAfterValue": "200003",
"UMask": "0x5",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048. Only counts with PEBS enabled.",
"Counter": "0,1",

View File

@ -564,6 +564,15 @@
"UMask": "0x1",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of uops executed on floating point and vector integer store data port.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xb2",
"EventName": "FP_VINT_UOPS_EXECUTED.STD",
"SampleAfterValue": "1000003",
"UMask": "0x1",
"Unit": "cpu_lowpower"
},
{
"BriefDescription": "Counts the number of floating point operations retired that required microcode assist.",
"Counter": "0,1,2,3,4,5,6,7",

View File

@ -376,7 +376,7 @@
"Unit": "cpu_lowpower"
},
{
"BriefDescription": "Counts the number of taken branch instructions retired",
"BriefDescription": "Counts the number of near taken branch instructions retired",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc4",
"EventName": "BR_INST_RETIRED.NEAR_TAKEN",
@ -422,6 +422,15 @@
"UMask": "0xfd",
"Unit": "cpu_lowpower"
},
{
"BriefDescription": "Counts the number of relative JMP branch instructions retired.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc4",
"EventName": "BR_INST_RETIRED.REL_JMP",
"SampleAfterValue": "200003",
"UMask": "0xdf",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of near relative JMP branch instructions retired.",
"Counter": "0,1,2,3,4,5,6,7",
@ -431,6 +440,25 @@
"UMask": "0xdf",
"Unit": "cpu_lowpower"
},
{
"BriefDescription": "Counts the number of taken branch instructions retired",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc4",
"EventName": "BR_INST_RETIRED.TAKEN",
"SampleAfterValue": "200003",
"UMask": "0x80",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of taken branch instructions retired.",
"Counter": "0,1,2,3,4,5,6,7",
"Errata": "ARL011",
"EventCode": "0xc4",
"EventName": "BR_INST_RETIRED.TAKEN",
"SampleAfterValue": "200003",
"UMask": "0x80",
"Unit": "cpu_lowpower"
},
{
"BriefDescription": "Counts the total number of mispredicted branch instructions retired for all branch types.",
"Counter": "0,1,2,3,4,5,6,7",
@ -1663,6 +1691,15 @@
"UMask": "0x88",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts number of virtual trap actually taken (e.g. highest priority event during retirement). It can count virtual trap from FPC port 0 or port 1 (x87/SSE) equally in a single counter.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc3",
"EventName": "MACHINE_CLEARS.FPC_VIRTUAL_TRAP",
"SampleAfterValue": "20003",
"UMask": "0x40",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of nukes due to memory renaming",
"Counter": "0,1,2,3,4,5,6,7",
@ -1672,6 +1709,15 @@
"UMask": "0x10",
"Unit": "cpu_atom"
},
{
"BriefDescription": "Counts the number of machines clears due to memory renaming.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc3",
"EventName": "MACHINE_CLEARS.MRN_NUKE",
"SampleAfterValue": "1000003",
"UMask": "0x80",
"Unit": "cpu_lowpower"
},
{
"BriefDescription": "Counts the number of machine clears that flush the pipeline and restart the machine without the use of microcode.",
"Counter": "0,1,2,3,4,5,6,7",

View File

@ -1,4 +1,140 @@
[
{
"BriefDescription": "Counts the number of requests that were not accepted into the L2Q because the L2Q is FULL.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x31",
"EventName": "CORE_REJECT_L2Q.ANY",
"PublicDescription": "Counts the number of (demand and L1 prefetchers) core requests rejected by the L2Q due to a full or nearly full condition which likely indicates back pressure from L2Q. It also counts requests that would have gone directly to the XQ, but are rejected due to a full or nearly full condition, indicating back pressure from the IDI link. The L2Q may also reject transactions from a core to ensure fairness between cores, or to delay a core's dirty eviction when the address conflicts with incoming external snoops. Note that L2 prefetcher requests that are dropped are not counted by this event. Counts on a per core basis.",
"SampleAfterValue": "1000003"
},
{
"BriefDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x30",
"EventName": "L2_REJECT_XQ.ANY",
"PublicDescription": "Counts the number of demand and prefetch transactions that the External Queue (XQ) rejects due to a full or near full condition which likely indicates back pressure from the IDI link. The IDI link is a central on-die protocol for memory and coherence traffic between the core and the uncore. It is highly optimized for efficiency, bandwidth, and coherency, using multiple channels and flow control mechanisms to manage high-throughput, low-latency data and protocol communication within the chip. The XQ may reject transactions from the L2Q (non-cacheable requests), BBL (L2 misses) and WOB (L2 write-back victims).",
"SampleAfterValue": "1000003"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door requests for Code Read, Data Read, RFO, ITOM, and L2 Prefetches. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.ALL",
"SampleAfterValue": "1000003",
"UMask": "0x1ff"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Demand Code Read requests. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.DEMAND_CODE_RD",
"SampleAfterValue": "1000003",
"UMask": "0xc4"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Demand Code Read requests that resulted in a hit. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.DEMAND_CODE_RD_HIT",
"SampleAfterValue": "1000003",
"UMask": "0x84"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Demand Code Read requests that resulted in a Miss. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.DEMAND_CODE_RD_MISS",
"SampleAfterValue": "1000003",
"UMask": "0x44"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Demand Data Read requests. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.DEMAND_DATA_RD",
"SampleAfterValue": "1000003",
"UMask": "0xc1"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Demand Data Read requests that resulted in a hit. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.DEMAND_DATA_RD_HIT",
"SampleAfterValue": "1000003",
"UMask": "0x81"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Demand Data Read requests that resulted in a Miss. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.DEMAND_DATA_RD_MISS",
"SampleAfterValue": "1000003",
"UMask": "0x41"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Demand RFO requests. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.DEMAND_RFO",
"SampleAfterValue": "1000003",
"UMask": "0xc2"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Demand RFO requests that resulted in a hit. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.DEMAND_RFO_HIT",
"SampleAfterValue": "1000003",
"UMask": "0x82"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Demand RFO requests that resulted in a Miss. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.DEMAND_RFO_MISS",
"SampleAfterValue": "1000003",
"UMask": "0x42"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door requests that resulted in a Hit. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.HIT",
"SampleAfterValue": "1000003",
"UMask": "0x1bf"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Hardware Prefetch requests, including hits and misses. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.HWPF",
"SampleAfterValue": "1000003",
"UMask": "0xc8"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Hardware Prefetch requests that result in a hit. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.HWPF_HIT",
"SampleAfterValue": "1000003",
"UMask": "0x88"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door Hardware Prefetch requests that result in a miss. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.HWPF_MISS",
"SampleAfterValue": "1000003",
"UMask": "0x48"
},
{
"BriefDescription": "Counts the number of L2 cache accesses from front door requests that resulted in a Miss. Does not include rejects or recycles, per core event.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x24",
"EventName": "L2_REQUEST.MISS",
"SampleAfterValue": "1000003",
"UMask": "0x17f"
},
{
"BriefDescription": "Counts the number of cacheable memory requests that miss in the LLC. Counts on a per core basis.",
"Counter": "0,1,2,3,4,5,6,7",
@ -17,6 +153,231 @@
"SampleAfterValue": "1000003",
"UMask": "0x4f"
},
{
"BriefDescription": "Counts the number of cycles the core is stalled due to a demand load which hit in the L2 cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x34",
"EventName": "MEM_BOUND_STALLS_LOAD.L2_HIT",
"PublicDescription": "Counts the number of cycles a core is stalled due to a demand load which hit in the L2 cache.",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which hit in the LLC.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x34",
"EventName": "MEM_BOUND_STALLS_LOAD.LLC_HIT",
"SampleAfterValue": "1000003",
"UMask": "0x6"
},
{
"BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which hit in the LLC, no snoop was required. LLC provided data.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x34",
"EventName": "MEM_BOUND_STALLS_LOAD.LLC_HIT_NOSNOOP",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which hit in the LLC, a snoop was required, the snoop misses or the snoop hits but no fwd. LLC provides the data.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x34",
"EventName": "MEM_BOUND_STALLS_LOAD.LLC_HIT_SNOOP",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which missed all the caches. DRAM, MMIO or other LOCAL memory type provides the data.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x34",
"EventName": "MEM_BOUND_STALLS_LOAD.LLC_MISS_LOCALMEM",
"SampleAfterValue": "1000003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of unhalted cycles when the core is stalled due to a demand load miss which missed all the caches, a snoop was required, and hits in other core or module on same die. Another core provides the data with a fwd, no fwd, or hitM.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x34",
"EventName": "MEM_BOUND_STALLS_LOAD.LLC_MISS_OTHERMOD",
"SampleAfterValue": "1000003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the total number of load ops retired that miss the L3 cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd3",
"EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.ALL",
"PublicDescription": "Counts the total number of load ops retired that miss the L3 cache. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0xff"
},
{
"BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in DRAM",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd3",
"EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.LOCAL_DRAM",
"PublicDescription": "Counts the number of load ops retired that miss the L3 cache and hit in DRAM Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote DRAM",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd3",
"EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_DRAM_OR_NOFWD",
"PublicDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote DRAM, OR had a Remote snoop miss/no fwd and hit in the Local DRAM. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote Cache and modified data was forwarded",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd3",
"EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_FWD_HITM",
"PublicDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote Cache and modified data was forwarded Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote Cache and non-modified data was forwarded",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd3",
"EventName": "MEM_LOAD_UOPS_L3_MISS_RETIRED.REMOTE_FWD_NONM",
"PublicDescription": "Counts the number of load ops retired that miss the L3 cache and hit in a Remote Cache and non-modified data was forwarded Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and modified data was forwarded.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd4",
"EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_HITM",
"PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and modified data was forwarded. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and no data was forwarded.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd4",
"EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_NO_FWD",
"PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and no data was forwarded. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x20"
},
{
"BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and non-modified data was forwarded.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd4",
"EventName": "MEM_LOAD_UOPS_MISC_RETIRED.L3_HIT_SNOOP_WITH_FWD",
"PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and non-modified data was forwarded. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of load ops retired that hit the L1 data cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd1",
"EventName": "MEM_LOAD_UOPS_RETIRED.L1_HIT",
"PublicDescription": "Counts the number of load ops retired that hit the L1 data cache. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of load ops retired that miss in the L1 data cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd1",
"EventName": "MEM_LOAD_UOPS_RETIRED.L1_MISS",
"PublicDescription": "Counts the number of load ops retired that miss in the L1 data cache. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x40"
},
{
"BriefDescription": "Counts the number of load ops retired that hit in the L2 cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd1",
"EventName": "MEM_LOAD_UOPS_RETIRED.L2_HIT",
"PublicDescription": "Counts the number of load ops retired that hit in the L2 cache. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of load ops retired that miss in the L2 cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd1",
"EventName": "MEM_LOAD_UOPS_RETIRED.L2_MISS",
"PublicDescription": "Counts the number of load ops retired that miss in the L2 cache. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x80"
},
{
"BriefDescription": "Counts the number of load ops retired that hit in the L3 cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd1",
"EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT",
"PublicDescription": "Counts the number of load ops retired that hit in the L3 cache. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x1c"
},
{
"BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which no snoop was required.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd1",
"EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT_NO_SNOOP",
"PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which no snoop was required. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and it hit and forwarded data, it hit and did not forward data, or it hit and the forwarded data was modified.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd1",
"EventName": "MEM_LOAD_UOPS_RETIRED.L3_HIT_SNOOP_HIT",
"PublicDescription": "Counts the number of load ops retired that hit in the L3 cache in which a snoop was required and it hit and forwarded data, it hit and did not forward data, or it hit and the forwarded data was modified. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of cycles that uops are blocked for any of the following reasons: load buffer, store buffer or RSV full.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x04",
"EventName": "MEM_SCHEDULER_BLOCK.ALL",
"SampleAfterValue": "1000003",
"UMask": "0x7"
},
{
"BriefDescription": "Counts the number of cycles that uops are blocked due to a load buffer full condition.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x04",
"EventName": "MEM_SCHEDULER_BLOCK.LD_BUF",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of cycles that uops are blocked due to an RSV full condition.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x04",
"EventName": "MEM_SCHEDULER_BLOCK.RSV",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of cycles that uops are blocked due to a store buffer full condition.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x04",
"EventName": "MEM_SCHEDULER_BLOCK.ST_BUF",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST).",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.ALL",
"PublicDescription": "Counts the number of memory uops retired. A single uop that performs both a load AND a store will be counted as 1, not 2 (e.g. ADD [mem], CONST). Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x83"
},
{
"BriefDescription": "Counts the number of load ops retired.",
"Counter": "0,1,2,3,4,5,6,7",
@ -36,121 +397,213 @@
"UMask": "0x82"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_1024",
"MSRIndex": "0x3F6",
"MSRValue": "0x400",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 1024. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_128",
"MSRIndex": "0x3F6",
"MSRValue": "0x80",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 128. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 16.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_16",
"MSRIndex": "0x3F6",
"MSRValue": "0x10",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 16. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_2048",
"MSRIndex": "0x3F6",
"MSRValue": "0x800",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 2048. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_256",
"MSRIndex": "0x3F6",
"MSRValue": "0x100",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 256. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 32.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_32",
"MSRIndex": "0x3F6",
"MSRValue": "0x20",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 32. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 4.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_4",
"MSRIndex": "0x3F6",
"MSRValue": "0x4",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 4. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 512.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_512",
"MSRIndex": "0x3F6",
"MSRValue": "0x200",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 512. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 64.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_64",
"MSRIndex": "0x3F6",
"MSRValue": "0x40",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 64. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled.",
"Counter": "0,1",
"BriefDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 8.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOAD_LATENCY_GT_8",
"MSRIndex": "0x3F6",
"MSRValue": "0x8",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold defined in MEC_CR_PEBS_LD_LAT_THRESHOLD - Only counts with PEBS enabled. Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of tagged load uops retired that exceed the latency threshold of 8. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x5"
},
{
"BriefDescription": "Counts the number of stores uops retired same as MEM_UOPS_RETIRED.ALL_STORES",
"BriefDescription": "Counts the number of load uops retired that performed one or more locks",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.LOCK_LOADS",
"PublicDescription": "Counts the number of load uops retired that performed one or more locks Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x21"
},
{
"BriefDescription": "Counts the number of load uops retired that were correctly predicated by the memory renaming (MRN) feature.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.MRN_LOADS",
"PublicDescription": "Counts the number of load uops retired that were correctly predicated by the memory renaming (MRN) feature. MRN loads are a part of the memory renaming process that optimizes data forwarding between stores and loads, reducing latency and improving performance. This involves tagging stores that forward to loads and copying the physical source (the actual data) directly from the store to the load. The MRN'd load can complete without accessing the memory, thus reducing load-to-use latency. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x9"
},
{
"BriefDescription": "Counts the number of store uops retired that were correctly tagged by the memory renaming (MRN) feature.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.MRN_STORES",
"PublicDescription": "Counts the number of store uops retired that were correctly tagged by the memory renaming (MRN) feature. MRN stores are a part of the memory renaming process that optimizes data forwarding between stores and loads, reducing latency and improving performance. This involves tagging stores that forward to loads and copying the physical source (the actual data) directly from the store to the load. The MRN store ensures that it's data is accurately forwarded to matching subsequent loads. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0xa"
},
{
"BriefDescription": "Counts the number of memory uops retired that were splits.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.SPLIT",
"PublicDescription": "Counts the number of memory uops retired that were splits. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x43"
},
{
"BriefDescription": "Counts the number of retired split load uops.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.SPLIT_LOADS",
"PublicDescription": "Counts the number of retired split load uops. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x41"
},
{
"BriefDescription": "Counts the number of retired split store uops.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.SPLIT_STORES",
"PublicDescription": "Counts the number of retired split store uops. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x42"
},
{
"BriefDescription": "Counts the number of memory uops retired that missed in the second level TLB.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.STLB_MISS",
"PublicDescription": "Counts the number of memory uops retired that missed in the second level TLB. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x13"
},
{
"BriefDescription": "Counts the number of load uops retired that miss in the second Level TLB.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.STLB_MISS_LOADS",
"PublicDescription": "Counts the number of load uops retired that miss in the second Level TLB. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x11"
},
{
"BriefDescription": "Counts the number of store uops retired that miss in the second level TLB.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.STLB_MISS_STORES",
"PublicDescription": "Counts the number of store uops retired that miss in the second level TLB. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x12"
},
{
"BriefDescription": "Counts the number of stores uops retired.",
"Counter": "0,1,2,3,4,5,6,7",
"Data_LA": "1",
"EventCode": "0xd0",
"EventName": "MEM_UOPS_RETIRED.STORE_LATENCY",
"PublicDescription": "Counts the number of stores uops retired same as MEM_UOPS_RETIRED.ALL_STORES Available PDIST counters: 0,1",
"PublicDescription": "Counts the number of stores uops retired. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x6"
},
@ -175,5 +628,13 @@
"PublicDescription": "Counts demand read for ownership (RFO) requests and software prefetches for exclusive ownership (PREFETCHW) that have any type of response. Available PDIST counters: 0",
"SampleAfterValue": "100003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of issue slots every cycle that were not delivered by the frontend due to an icache miss",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x71",
"EventName": "TOPDOWN_FE_BOUND.ICACHE",
"SampleAfterValue": "1000003",
"UMask": "0x20"
}
]

View File

@ -1,7 +1,82 @@
[
{
"Unit": "core",
"CountersNumFixed": "3",
"CountersNumGeneric": "39"
"CountersNumFixed": "7",
"CountersNumGeneric": "8"
},
{
"Unit": "B2CMI",
"CountersNumFixed": "0",
"CountersNumGeneric": "4"
},
{
"Unit": "CHA",
"CountersNumFixed": "0",
"CountersNumGeneric": "4"
},
{
"Unit": "IMC",
"CountersNumFixed": "0",
"CountersNumGeneric": "4"
},
{
"Unit": "B2HOT",
"CountersNumFixed": "0",
"CountersNumGeneric": 4
},
{
"Unit": "IIO",
"CountersNumFixed": "0",
"CountersNumGeneric": "4"
},
{
"Unit": "IRP",
"CountersNumFixed": "0",
"CountersNumGeneric": "4"
},
{
"Unit": "UPI",
"CountersNumFixed": "0",
"CountersNumGeneric": "4"
},
{
"Unit": "B2UPI",
"CountersNumFixed": "0",
"CountersNumGeneric": 4
},
{
"Unit": "B2CXL",
"CountersNumFixed": "0",
"CountersNumGeneric": 4
},
{
"Unit": "UBOX",
"CountersNumFixed": "0",
"CountersNumGeneric": "2"
},
{
"Unit": "PCU",
"CountersNumFixed": "0",
"CountersNumGeneric": "4"
},
{
"Unit": "CHACMS",
"CountersNumFixed": "0",
"CountersNumGeneric": "4"
},
{
"Unit": "MDF",
"CountersNumFixed": "0",
"CountersNumGeneric": 4
},
{
"Unit": "CXLCM",
"CountersNumFixed": "0",
"CountersNumGeneric": 8
},
{
"Unit": "CXLDP",
"CountersNumFixed": "0",
"CountersNumGeneric": 4
}
]

View File

@ -0,0 +1,310 @@
[
{
"BriefDescription": "C1 residency percent per core",
"MetricExpr": "cstate_core@c1\\-residency@ / msr@tsc@",
"MetricGroup": "Power",
"MetricName": "C1_Core_Residency",
"ScaleUnit": "100%"
},
{
"BriefDescription": "C2 residency percent per package",
"MetricExpr": "cstate_pkg@c2\\-residency@ / msr@tsc@",
"MetricGroup": "Power",
"MetricName": "C2_Pkg_Residency",
"ScaleUnit": "100%"
},
{
"BriefDescription": "C6 residency percent per core",
"MetricExpr": "cstate_core@c6\\-residency@ / msr@tsc@",
"MetricGroup": "Power",
"MetricName": "C6_Core_Residency",
"ScaleUnit": "100%"
},
{
"BriefDescription": "C6 residency percent per package",
"MetricExpr": "cstate_pkg@c6\\-residency@ / msr@tsc@",
"MetricGroup": "Power",
"MetricName": "C6_Pkg_Residency",
"ScaleUnit": "100%"
},
{
"BriefDescription": "Cycles per instruction retired; indicating how much time each executed instruction took; in units of cycles",
"MetricExpr": "CPU_CLK_UNHALTED.THREAD / INST_RETIRED.ANY",
"MetricName": "cpi",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "The average number of cores that are in cstate C0 as observed by the power control unit (PCU)",
"MetricExpr": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C0 / pcu_0@UNC_P_CLOCKTICKS@ * #num_packages",
"MetricName": "cpu_cstate_c0"
},
{
"BriefDescription": "The average number of cores are in cstate C6 as observed by the power control unit (PCU)",
"MetricExpr": "UNC_P_POWER_STATE_OCCUPANCY_CORES_C6 / pcu_0@UNC_P_CLOCKTICKS@ * #num_packages",
"MetricName": "cpu_cstate_c6"
},
{
"BriefDescription": "CPU operating frequency (in GHz)",
"MetricExpr": "CPU_CLK_UNHALTED.THREAD / CPU_CLK_UNHALTED.REF_TSC * #SYSTEM_TSC_FREQ / 1e9",
"MetricName": "cpu_operating_frequency",
"ScaleUnit": "1GHz"
},
{
"BriefDescription": "Percentage of time spent in the active CPU power state C0",
"MetricExpr": "CPU_CLK_UNHALTED.REF_TSC / msr@tsc@",
"MetricName": "cpu_utilization",
"ScaleUnit": "100%"
},
{
"BriefDescription": "Ratio of number of completed page walks (for all page sizes) caused by demand data loads to the total number of completed instructions",
"MetricExpr": "DTLB_LOAD_MISSES.WALK_COMPLETED / INST_RETIRED.ANY",
"MetricName": "dtlb_2nd_level_load_mpi",
"PublicDescription": "Ratio of number of completed page walks (for all page sizes) caused by demand data loads to the total number of completed instructions. This implies it missed in the DTLB and further levels of TLB",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Ratio of number of completed page walks (for all page sizes) caused by demand data stores to the total number of completed instructions",
"MetricExpr": "DTLB_STORE_MISSES.WALK_COMPLETED / INST_RETIRED.ANY",
"MetricName": "dtlb_2nd_level_store_mpi",
"PublicDescription": "Ratio of number of completed page walks (for all page sizes) caused by demand data stores to the total number of completed instructions. This implies it missed in the DTLB and further levels of TLB",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Bandwidth observed by the integrated I/O traffic controller (IIO) of IO reads that are initiated by end device controllers that are requesting memory from the CPU",
"MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_READ.ALL_PARTS * 4 / 1e6 / duration_time",
"MetricName": "iio_bandwidth_read",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth observed by the integrated I/O traffic controller (IIO) of IO writes that are initiated by end device controllers that are writing memory to the CPU",
"MetricExpr": "UNC_IIO_DATA_REQ_OF_CPU.MEM_WRITE.ALL_PARTS * 4 / 1e6 / duration_time",
"MetricName": "iio_bandwidth_write",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth of IO reads that are initiated by end device controllers that are requesting memory from the CPU",
"MetricExpr": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR * 64 / 1e6 / duration_time",
"MetricName": "io_bandwidth_read",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth of inbound IO reads that are initiated by end device controllers that are requesting memory from the CPU and miss the L3 cache",
"MetricExpr": "UNC_CHA_TOR_INSERTS.IO_MISS_PCIRDCUR * 64 / 1e6 / duration_time",
"MetricName": "io_bandwidth_read_l3_miss",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth of IO reads that are initiated by end device controllers that are requesting memory from the local CPU socket",
"MetricExpr": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR_LOCAL * 64 / 1e6 / duration_time",
"MetricName": "io_bandwidth_read_local",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth of IO reads that are initiated by end device controllers that are requesting memory from a remote CPU socket",
"MetricExpr": "UNC_CHA_TOR_INSERTS.IO_PCIRDCUR_REMOTE * 64 / 1e6 / duration_time",
"MetricName": "io_bandwidth_read_remote",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth of IO writes that are initiated by end device controllers that are writing memory to the CPU",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_ITOM + UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR) * 64 / 1e6 / duration_time",
"MetricName": "io_bandwidth_write",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth of inbound IO writes that are initiated by end device controllers that are writing memory to the CPU",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_MISS_ITOM + UNC_CHA_TOR_INSERTS.IO_MISS_ITOMCACHENEAR) * 64 / 1e6 / duration_time",
"MetricName": "io_bandwidth_write_l3_miss",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth of IO writes that are initiated by end device controllers that are writing memory to the local CPU socket",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_ITOM_LOCAL + UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR_LOCAL) * 64 / 1e6 / duration_time",
"MetricName": "io_bandwidth_write_local",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth of IO writes that are initiated by end device controllers that are writing memory to a remote CPU socket",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_ITOM_REMOTE + UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR_REMOTE) * 64 / 1e6 / duration_time",
"MetricName": "io_bandwidth_write_remote",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "The percent of inbound full cache line writes initiated by IO that miss the L3 cache",
"MetricExpr": "UNC_CHA_TOR_INSERTS.IO_MISS_ITOM / UNC_CHA_TOR_INSERTS.IO_ITOM",
"MetricName": "io_full_write_l3_miss",
"ScaleUnit": "100%"
},
{
"BriefDescription": "The number of times per second that ownership of a cacheline was stolen from the integrated IO controller before it was able to write back the modified line",
"MetricExpr": "(UNC_I_MISC1.LOST_FWD + UNC_I_MISC1.SEC_RCVD_INVLD) / duration_time",
"MetricName": "io_lost_fwd",
"ScaleUnit": "1per_sec"
},
{
"BriefDescription": "Message Signaled Interrupts (MSI) per second sent by the integrated I/O traffic controller (IIO) to System Configuration Controller (Ubox)",
"MetricExpr": "UNC_IIO_NUM_REQ_OF_CPU_BY_TGT.UBOX_POSTED / duration_time",
"MetricName": "io_msi",
"ScaleUnit": "1per_sec"
},
{
"BriefDescription": "",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR + UNC_CHA_TOR_INSERTS.IO_RFO) / duration_time",
"MetricName": "io_number_of_partial_pci_writes",
"ScaleUnit": "1per_sec"
},
{
"BriefDescription": "The percent of inbound partial writes initiated by IO that miss the L3 cache",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IO_MISS_ITOMCACHENEAR + UNC_CHA_TOR_INSERTS.IO_MISS_RFO) / (UNC_CHA_TOR_INSERTS.IO_ITOMCACHENEAR + UNC_CHA_TOR_INSERTS.IO_RFO)",
"MetricName": "io_partial_write_l3_miss",
"ScaleUnit": "100%"
},
{
"BriefDescription": "The percent of inbound reads initiated by IO that miss the L3 cache",
"MetricExpr": "UNC_CHA_TOR_INSERTS.IO_MISS_PCIRDCUR / UNC_CHA_TOR_INSERTS.IO_PCIRDCUR",
"MetricName": "io_read_l3_miss",
"ScaleUnit": "100%"
},
{
"BriefDescription": "Ratio of number of completed page walks (for all page sizes) caused by a code fetch to the total number of completed instructions",
"MetricExpr": "ITLB_MISSES.WALK_COMPLETED / INST_RETIRED.ANY",
"MetricName": "itlb_2nd_level_mpi",
"PublicDescription": "Ratio of number of completed page walks (for all page sizes) caused by a code fetch to the total number of completed instructions. This implies it missed in the ITLB (Instruction TLB) and further levels of TLB",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Ratio of number of code read requests missing in L1 instruction cache (includes prefetches) to the total number of completed instructions",
"MetricExpr": "ICACHE.MISSES / INST_RETIRED.ANY",
"MetricName": "l1_i_code_read_misses_with_prefetches_per_instr",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Ratio of number of demand load requests hitting in L1 data cache to the total number of completed instructions",
"MetricExpr": "MEM_LOAD_UOPS_RETIRED.L1_HIT / INST_RETIRED.ANY",
"MetricName": "l1d_demand_data_read_hits_per_instr",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Ratio of number of completed demand load requests hitting in L2 cache to the total number of completed instructions",
"MetricExpr": "MEM_LOAD_UOPS_RETIRED.L2_HIT / INST_RETIRED.ANY",
"MetricName": "l2_demand_data_read_hits_per_instr",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Ratio of number of completed data read request missing L2 cache to the total number of completed instructions",
"MetricExpr": "MEM_LOAD_UOPS_RETIRED.L2_MISS / INST_RETIRED.ANY",
"MetricName": "l2_demand_data_read_mpi",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Ratio of number of code read requests missing last level core cache (includes demand w/ prefetches) to the total number of completed instructions",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IA_MISS_CRD + UNC_CHA_TOR_INSERTS.IA_MISS_CRD_PREF) / INST_RETIRED.ANY",
"MetricName": "llc_code_read_mpi_demand_plus_prefetch",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Ratio of number of data read requests missing last level core cache (includes demand w/ prefetches) to the total number of completed instructions",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF + UNC_CHA_TOR_INSERTS.IA_MISS_LLCPREFDATA) / INST_RETIRED.ANY",
"MetricName": "llc_data_read_mpi_demand_plus_prefetch",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Average latency of a last level cache (LLC) demand data read miss (read memory access) in nano seconds",
"MetricExpr": "1e9 * (UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT / UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT) / (UNC_CHA_CLOCKTICKS / (source_count(UNC_CHA_TOR_OCCUPANCY.IA_MISS_DRD_OPT) * #num_packages)) * duration_time",
"MetricName": "llc_demand_data_read_miss_latency",
"ScaleUnit": "1ns"
},
{
"BriefDescription": "Bandwidth (MB/sec) of read requests that miss the last level cache (LLC) and go to local memory",
"MetricExpr": "UNC_CHA_REQUESTS.READS_LOCAL * 64 / 1e6 / duration_time",
"MetricName": "llc_miss_local_memory_bandwidth_read",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth (MB/sec) of write requests that miss the last level cache (LLC) and go to local memory",
"MetricExpr": "UNC_CHA_REQUESTS.WRITES_LOCAL * 64 / 1e6 / duration_time",
"MetricName": "llc_miss_local_memory_bandwidth_write",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth (MB/sec) of read requests that miss the last level cache (LLC) and go to remote memory",
"MetricExpr": "UNC_CHA_REQUESTS.READS_REMOTE * 64 / 1e6 / duration_time",
"MetricName": "llc_miss_remote_memory_bandwidth_read",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Bandwidth (MB/sec) of write requests that miss the last level cache (LLC) and go to remote memory",
"MetricExpr": "UNC_CHA_REQUESTS.WRITES_REMOTE * 64 / 1e6 / duration_time",
"MetricName": "llc_miss_remote_memory_bandwidth_write",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "",
"MetricExpr": "MEM_UOPS_RETIRED.ALL_LOADS / INST_RETIRED.ANY",
"MetricName": "loads_retired_per_instr",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "DDR memory read bandwidth (MB/sec)",
"MetricExpr": "(UNC_M_CAS_COUNT_SCH0.RD + UNC_M_CAS_COUNT_SCH1.RD) * 64 / 1e6 / duration_time",
"MetricName": "memory_bandwidth_read",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "DDR memory bandwidth (MB/sec)",
"MetricExpr": "(UNC_M_CAS_COUNT_SCH0.RD + UNC_M_CAS_COUNT_SCH1.RD + UNC_M_CAS_COUNT_SCH0.WR + UNC_M_CAS_COUNT_SCH1.WR) * 64 / 1e6 / duration_time",
"MetricName": "memory_bandwidth_total",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "DDR memory write bandwidth (MB/sec)",
"MetricExpr": "(UNC_M_CAS_COUNT_SCH0.WR + UNC_M_CAS_COUNT_SCH1.WR) * 64 / 1e6 / duration_time",
"MetricName": "memory_bandwidth_write",
"ScaleUnit": "1MB/s"
},
{
"BriefDescription": "Memory read that miss the last level cache (LLC) addressed to local DRAM as a percentage of total memory read accesses, does not include LLC prefetches",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_LOCAL) / (UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_REMOTE + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_REMOTE)",
"MetricName": "numa_reads_addressed_to_local_dram",
"ScaleUnit": "100%"
},
{
"BriefDescription": "Memory reads that miss the last level cache (LLC) addressed to remote DRAM as a percentage of total memory read accesses, does not include LLC prefetches",
"MetricExpr": "(UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_REMOTE + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_REMOTE) / (UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_LOCAL + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_REMOTE + UNC_CHA_TOR_INSERTS.IA_MISS_DRD_OPT_PREF_REMOTE)",
"MetricName": "numa_reads_addressed_to_remote_dram",
"ScaleUnit": "100%"
},
{
"BriefDescription": "Percentage of cycles spent in System Management Interrupts.",
"MetricExpr": "((msr@aperf@ - cycles) / msr@aperf@ if msr@smi@ > 0 else 0)",
"MetricGroup": "smi",
"MetricName": "smi_cycles",
"MetricThreshold": "smi_cycles > 0.1",
"ScaleUnit": "100%"
},
{
"BriefDescription": "Number of SMI interrupts.",
"MetricExpr": "msr@smi@",
"MetricGroup": "smi",
"MetricName": "smi_num",
"ScaleUnit": "1SMI#"
},
{
"BriefDescription": "",
"MetricExpr": "MEM_UOPS_RETIRED.ALL_STORES / INST_RETIRED.ANY",
"MetricName": "stores_retired_per_instr",
"ScaleUnit": "1per_instr"
},
{
"BriefDescription": "Uncore operating frequency in GHz",
"MetricExpr": "UNC_CHA_CLOCKTICKS / (source_count(UNC_CHA_CLOCKTICKS) * #num_packages) / 1e9 / duration_time",
"MetricName": "uncore_frequency",
"ScaleUnit": "1GHz"
},
{
"BriefDescription": "Intel(R) Ultra Path Interconnect (UPI) data transmit bandwidth (MB/sec)",
"MetricExpr": "UNC_UPI_TxL_FLITS.ALL_DATA * 7.111111111111111 / 1e6 / duration_time",
"MetricName": "upi_data_transmit_bw",
"ScaleUnit": "1MB/s"
}
]

View File

@ -0,0 +1,191 @@
[
{
"BriefDescription": "Counts the number of cycles when any of the floating point dividers are active.",
"Counter": "0,1,2,3,4,5,6,7",
"CounterMask": "1",
"EventCode": "0xcd",
"EventName": "ARITH.FPDIV_ACTIVE",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of floating point dividers per cycle in the loop stage.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xcd",
"EventName": "ARITH.FPDIV_OCCUPANCY",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of floating point divider uops executed per cycle.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xcd",
"EventName": "ARITH.FPDIV_UOPS",
"SampleAfterValue": "1000003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of all types of floating point operations per uop with all default weighting",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc8",
"EventName": "FP_FLOPS_RETIRED.ALL",
"PublicDescription": "Counts the number of all types of floating point operations per uop with all default weighting Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x3"
},
{
"BriefDescription": "Counts the number of floating point operations that produce 32 bit single precision results",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc8",
"EventName": "FP_FLOPS_RETIRED.FP32",
"PublicDescription": "Counts the number of floating point operations that produce 32 bit single precision results Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of floating point operations that produce 64 bit double precision results",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc8",
"EventName": "FP_FLOPS_RETIRED.FP64",
"PublicDescription": "Counts the number of floating point operations that produce 64 bit double precision results Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of retired instructions whose sources are a packed 128 bit double precision floating point. This may be SSE or AVX.128 operations.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_INST_RETIRED.128B_DP",
"PublicDescription": "Counts the number of retired instructions whose sources are a packed 128 bit double precision floating point. This may be SSE or AVX.128 operations. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of retired instructions whose sources are a packed 128 bit single precision floating point. This may be SSE or AVX.128 operations.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_INST_RETIRED.128B_SP",
"PublicDescription": "Counts the number of retired instructions whose sources are a packed 128 bit single precision floating point. This may be SSE or AVX.128 operations. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of retired instructions whose sources are a packed 256 bit double precision floating point.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_INST_RETIRED.256B_DP",
"PublicDescription": "Counts the number of retired instructions whose sources are a packed 256 bit double precision floating point. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x20"
},
{
"BriefDescription": "Counts the number of retired instructions whose sources are a packed 256 bit single precision floating point.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_INST_RETIRED.256B_SP",
"PublicDescription": "Counts the number of retired instructions whose sources are a packed 256 bit single precision floating point. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of retired instructions whose sources are a scalar 32bit single precision floating point.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_INST_RETIRED.32B_SP",
"PublicDescription": "Counts the number of retired instructions whose sources are a scalar 32bit single precision floating point. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of retired instructions whose sources are a scalar 64 bit double precision floating point.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_INST_RETIRED.64B_DP",
"PublicDescription": "Counts the number of retired instructions whose sources are a scalar 64 bit double precision floating point. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the total number of floating point retired instructions.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc7",
"EventName": "FP_INST_RETIRED.ALL",
"PublicDescription": "Counts the total number of floating point retired instructions. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x3f"
},
{
"BriefDescription": "Counts the number of uops executed on all floating point ports.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xb2",
"EventName": "FP_VINT_UOPS_EXECUTED.ALL",
"SampleAfterValue": "1000003",
"UMask": "0x1f"
},
{
"BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xb2",
"EventName": "FP_VINT_UOPS_EXECUTED.P0",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of uops executed on floating point and vector integer port 1.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xb2",
"EventName": "FP_VINT_UOPS_EXECUTED.P1",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of uops executed on floating point and vector integer port 2.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xb2",
"EventName": "FP_VINT_UOPS_EXECUTED.P2",
"SampleAfterValue": "1000003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of uops executed on floating point and vector integer port 3.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xb2",
"EventName": "FP_VINT_UOPS_EXECUTED.P3",
"SampleAfterValue": "1000003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of uops executed on floating point and vector integer port 0, 1, 2, 3.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xb2",
"EventName": "FP_VINT_UOPS_EXECUTED.PRIMARY",
"SampleAfterValue": "1000003",
"UMask": "0x1e"
},
{
"BriefDescription": "Counts the number of uops executed on floating point and vector integer store data port.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xb2",
"EventName": "FP_VINT_UOPS_EXECUTED.STD",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of floating point operations retired that required microcode assist.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc3",
"EventName": "MACHINE_CLEARS.FP_ASSIST",
"PublicDescription": "Counts the number of floating point operations retired that required microcode assist, which is not a reflection of the number of FP operations, instructions or uops.",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of floating point divide uops retired (x87 and sse, including x87 sqrt).",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc2",
"EventName": "UOPS_RETIRED.FPDIV",
"PublicDescription": "Counts the number of floating point divide uops retired (x87 and sse, including x87 sqrt). Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x40"
}
]

View File

@ -1,4 +1,206 @@
[
{
"BriefDescription": "Counts the total number of BACLEARS due to all branch types including conditional and unconditional jumps, returns, and indirect branches.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xe6",
"EventName": "BACLEARS.ANY",
"PublicDescription": "Counts the total number of BACLEARS, which occur when the Branch Target Buffer (BTB) prediction or lack thereof, was corrected by a later branch predictor in the frontend. Includes BACLEARS due to all branch types including conditional and unconditional jumps, returns, and indirect branches.",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of BACLEARS due to a conditional jump.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xe6",
"EventName": "BACLEARS.COND",
"SampleAfterValue": "1000003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of BACLEARS due to an indirect branch.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xe6",
"EventName": "BACLEARS.INDIRECT",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of BACLEARS due to a return branch.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xe6",
"EventName": "BACLEARS.RETURN",
"SampleAfterValue": "1000003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of BACLEARS due to a direct, unconditional jump.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xe6",
"EventName": "BACLEARS.UNCOND",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged with having preceded with frontend bound behavior",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc6",
"EventName": "FRONTEND_RETIRED.ALL",
"PublicDescription": "Counts the number of instructions retired that were tagged with having preceded with frontend bound behavior Available PDIST counters: 0,1",
"SampleAfterValue": "1000003"
},
{
"BriefDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a baclear",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc6",
"EventName": "FRONTEND_RETIRED.BRANCH_DETECT",
"PublicDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a baclear Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles /empty issue slots due to a btclear",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc6",
"EventName": "FRONTEND_RETIRED.BRANCH_RESTEER",
"PublicDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles /empty issue slots due to a btclear Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x40"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged following an ms flow due to the bubble/wasted issue slot from exiting long ms flow",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc6",
"EventName": "FRONTEND_RETIRED.CISC",
"PublicDescription": "Counts the number of instructions retired that were tagged following an ms flow due to the bubble/wasted issue slot from exiting long ms flow Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged every cycle the decoder is unable to send 3 uops per cycle.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc6",
"EventName": "FRONTEND_RETIRED.DECODE",
"PublicDescription": "Counts the number of instructions retired that were tagged every cycle the decoder is unable to send 3 uops per cycle. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to icache miss",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc6",
"EventName": "FRONTEND_RETIRED.ICACHE",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to icache miss Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x20"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc6",
"EventName": "FRONTEND_RETIRED.ITLB_MISS",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of instruction retired tagged after a wasted issue slot if none of the previous events occurred",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc6",
"EventName": "FRONTEND_RETIRED.OTHER",
"PublicDescription": "Counts the number of instruction retired tagged after a wasted issue slot if none of the previous events occurred Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x80"
},
{
"BriefDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a predecode wrong.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc6",
"EventName": "FRONTEND_RETIRED.PREDECODE",
"PublicDescription": "Counts the number of instruction retired that are tagged after a branch instruction causes bubbles/empty issue slots due to a predecode wrong. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L2 cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc9",
"EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L2_HIT",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L2 cache. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc9",
"EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L2_MISS",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 cache. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0xe"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc9",
"EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_HIT",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x6"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and did not have to snoop another core.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc9",
"EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_HIT_NO_SNOOP",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and did not have to snoop another core. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and required a snoop (that resulted in a snoop miss, snoop hitm, snoop hit with fwd, or snoop hit with no fwd).",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc9",
"EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_HIT_WITH_SNOOP",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that hit in the L3 cache, and required a snoop (that resulted in a snoop miss, snoop hitm, snoop hit with fwd, or snoop hit with no fwd). Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 and L3 caches.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc9",
"EventName": "FRONTEND_RETIRED_SOURCE.ICACHE_L3_MISS",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to Instruction L1 cache miss, that also missed in the L2 and L3 caches. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x8"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss that hit in the second level TLB.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc9",
"EventName": "FRONTEND_RETIRED_SOURCE.ITLB_STLB_HIT",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss that hit in the second level TLB. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x10"
},
{
"BriefDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss that also missed the second level TLB.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc9",
"EventName": "FRONTEND_RETIRED_SOURCE.ITLB_STLB_MISS",
"PublicDescription": "Counts the number of instructions retired that were tagged because empty issue slots were seen before the uop due to ITLB miss that also missed the second level TLB. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x20"
},
{
"BriefDescription": "Counts the number of instructions retired that were preceded by empty issue slots at allocation due to an Instruction L1 cache miss, that matched a current outstanding prefetch request initiated by a Code SWPF stream.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xc9",
"EventName": "FRONTEND_RETIRED_SOURCE.LATE_SWPF",
"PublicDescription": "Counts the number of instructions retired that were preceded by empty issue slots at allocation due to an Instruction L1 cache miss, that matched a current outstanding prefetch request initiated by a Code SWPF stream. Available PDIST counters: 0,1",
"SampleAfterValue": "1000003",
"UMask": "0x40"
},
{
"BriefDescription": "Counts every time the code stream enters into a new cache line by walking sequential from the previous line or being redirected by a jump.",
"Counter": "0,1,2,3,4,5,6,7",
@ -7,6 +209,14 @@
"SampleAfterValue": "1000003",
"UMask": "0x3"
},
{
"BriefDescription": "Counts every time the code stream enters into a new cache line by walking sequential from the previous line or being redirected by a jump and the instruction cache registers bytes are present.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0x80",
"EventName": "ICACHE.HIT",
"SampleAfterValue": "1000003",
"UMask": "0x1"
},
{
"BriefDescription": "Counts every time the code stream enters into a new cache line by walking sequential from the previous line or being redirected by a jump and the instruction cache registers bytes are not present. -",
"Counter": "0,1,2,3,4,5,6,7",
@ -14,5 +224,21 @@
"EventName": "ICACHE.MISSES",
"SampleAfterValue": "1000003",
"UMask": "0x2"
},
{
"BriefDescription": "Counts the number of cycles that the micro-sequencer is busy.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xe7",
"EventName": "MS_DECODED.MS_BUSY",
"SampleAfterValue": "1000003",
"UMask": "0x4"
},
{
"BriefDescription": "Counts the number of times entered into a ucode flow in the FEC. Includes inserted flows due to front-end detected faults or assists.",
"Counter": "0,1,2,3,4,5,6,7",
"EventCode": "0xe7",
"EventName": "MS_DECODED.MS_ENTRY",
"SampleAfterValue": "1000003",
"UMask": "0x1"
}
]

Some files were not shown because too many files have changed in this diff Show More