mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 01:32:21 +02:00
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:
commit
05d2a3da15
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.*
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <libunwind.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern int
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
30
tools/lib/perf/TODO
Normal 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.
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
20
tools/perf/.clang-format
Normal 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
|
||||
1
tools/perf/.gitignore
vendored
1
tools/perf/.gitignore
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
--------
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
|
||||
|
||||
perf-util-y += pmu.o auxtrace.o cs-etm.o
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
perf-util-y += header.o
|
||||
|
||||
perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
perf-util-y += util/
|
||||
|
|
@ -1 +0,0 @@
|
|||
perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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[] = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
static char *_get_field(const char *line)
|
||||
{
|
||||
char *line2, *nl;
|
||||
const char *line2, *nl;
|
||||
|
||||
line2 = strrchr(line, ' ');
|
||||
if (!line2)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
109
tools/perf/bpf_skel.mak
Normal 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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
]
|
||||
310
tools/perf/pmu-events/arch/x86/clearwaterforest/cwf-metrics.json
Normal file
310
tools/perf/pmu-events/arch/x86/clearwaterforest/cwf-metrics.json
Normal 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"
|
||||
}
|
||||
]
|
||||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
|
@ -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
Loading…
Reference in New Issue
Block a user