Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'perf-tools-for-v6.13-2024-11-24' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools

Pull perf tools updates from Namhyung Kim:
"perf record:

- Enable leader sampling for inherited task events. It was supported
only for system-wide events but the kernel started to support such
a setup since v6.12.

This is to reduce the number of PMU interrupts. The samples of the
leader event will contain counts of other events and no samples
will be generated for the other member events.

$ perf record -e '{cycles,instructions}:S' ${MYPROG}

perf report:

- Fix --branch-history option to display more branch-related
information like prediction, abort and cycles which is available
on Intel machines.

$ perf record -bg -- perf test -w brstack

$ perf report --branch-history
...
#
# Overhead Source:Line Symbol Shared Object Predicted Abort Cycles IPC [IPC Coverage]
# ........ ........................ .............. .................... ......... ..... ...... ....................
#
8.17% copy_page_64.S:19 [k] copy_page [kernel.kallsyms] 50.0% 0 5 - -
|
---xas_load xarray.h:171
|
|--5.68%--xas_load xarray.c:245 (cycles:1)
| xas_load xarray.c:242
| xas_load xarray.h:1260 (cycles:1)
| xas_descend xarray.c:146
| xas_load xarray.c:244 (cycles:2)
| xas_load xarray.c:245
| xas_descend xarray.c:218 (cycles:10)
...

perf stat:

- Add HWMON PMU support.

The HWMON provides various system information like CPU/GPU
temperature, fan speed and so on. Expose them as PMU events so that
users can see the values using perf stat commands.

$ perf stat -e temp_cpu,fan1 true

Performance counter stats for 'true':

60.00 'C temp_cpu
0 rpm fan1

0.000745382 seconds time elapsed

0.000883000 seconds user
0.000000000 seconds sys

- Display metric threshold in JSON output.

Some metrics define thresholds to classify value ranges. It used to
be in a different color but it won't work for JSON.

Add "metric-threshold" field to the JSON that can be one of "good",
"less good", "nearly bad" and "bad".

# perf stat -a -M TopdownL1 -j true
{"counter-value" : "18693525.000000", "unit" : "", "event" : "TOPDOWN.SLOTS", "event-runtime" : 5552708, "pcnt-running" : 100.00, "metric-value" : "43.226002", "metric-unit" : "% tma_backend_bound", "metric-threshold" : "bad"}
{"metric-value" : "29.212267", "metric-unit" : "% tma_frontend_bound", "metric-threshold" : "bad"}
{"metric-value" : "7.138972", "metric-unit" : "% tma_bad_speculation", "metric-threshold" : "good"}
{"metric-value" : "20.422759", "metric-unit" : "% tma_retiring", "metric-threshold" : "good"}
{"counter-value" : "3817732.000000", "unit" : "", "event" : "topdown-retiring", "event-runtime" : 5552708, "pcnt-running" : 100.00, }
{"counter-value" : "5472824.000000", "unit" : "", "event" : "topdown-fe-bound", "event-runtime" : 5552708, "pcnt-running" : 100.00, }
{"counter-value" : "7984780.000000", "unit" : "", "event" : "topdown-be-bound", "event-runtime" : 5552708, "pcnt-running" : 100.00, }
{"counter-value" : "1418181.000000", "unit" : "", "event" : "topdown-bad-spec", "event-runtime" : 5552708, "pcnt-running" : 100.00, }
...

perf sched:

- Add -P/--pre-migrations option for 'timehist' sub-command to track
time a task waited on a run-queue before migrating to a different
CPU.

$ perf sched timehist -P
time cpu task name wait time sch delay run time pre-mig time
[tid/pid] (msec) (msec) (msec) (msec)
--------------- ------ ------------------------------ --------- --------- --------- ---------
585940.535527 [0000] perf[584885] 0.000 0.000 0.000 0.000
585940.535535 [0000] migration/0[20] 0.000 0.002 0.008 0.000
585940.535559 [0001] perf[584885] 0.000 0.000 0.000 0.000
585940.535563 [0001] migration/1[25] 0.000 0.001 0.004 0.000
585940.535678 [0002] perf[584885] 0.000 0.000 0.000 0.000
585940.535686 [0002] migration/2[31] 0.000 0.002 0.008 0.000
585940.535905 [0001] <idle> 0.000 0.000 0.342 0.000
585940.535938 [0003] perf[584885] 0.000 0.000 0.000 0.000
585940.537048 [0001] sleep[584886] 0.000 0.019 1.142 0.001
585940.537749 [0002] <idle> 0.000 0.000 2.062 0.000
...

Build:

- Make libunwind opt-in (LIBUNWIND=1) rather than opt-out.

The perf tools are generally built with libelf and libdw which has
unwinder functionality. The libunwind support predates it and no
need to have duplicate unwinders by default.

- Rename NO_DWARF=1 build option to NO_LIBDW=1 in order to clarify
it's using libdw for handling DWARF information.

Internals:

- Do not set exclude_guest bit in the perf_event_attr by default.

This was causing a trouble in AMD IBS PMU as it doesn't support the
bit. The bit will be set when it's needed later by the fallback
logic. Also update the missing feature detection logic to make sure
not clear supported bits unnecessarily.

- Run perf test in parallel by default and mark flaky tests
"exclusive" to run them serially at the end. Some test numbers are
changed but the test can complete in less than half the time.

JSON vendor events:

- Add AMD Zen 5 events and metrics.

- Add i.MX91 and i.MX95 DDR metrics

- Fix HiSilicon HIP08 Topdown metric name.

- Support compat events on PowerPC"

* tag 'perf-tools-for-v6.13-2024-11-24' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools: (232 commits)
perf tests: Fix hwmon parsing with PMU name test
perf hwmon_pmu: Ensure hwmon key union is zeroed before use
perf tests hwmon_pmu: Remove double evlist__delete()
perf/test: fix perf ftrace test on s390
perf bpf-filter: Return -ENOMEM directly when pfi allocation fails
perf test: Correct hwmon test PMU detection
perf: Remove unused del_perf_probe_events()
perf pmu: Move pmu_metrics_table__find and remove ARM override
perf jevents: Add map_for_cpu()
perf header: Pass a perf_cpu rather than a PMU to get_cpuid_str
perf header: Avoid transitive PMU includes
perf arm64 header: Use cpu argument in get_cpuid
perf header: Refactor get_cpuid to take a CPU for ARM
perf header: Move is_cpu_online to numa bench
perf jevents: fix breakage when do perf stat on system metric
perf test: Add missing __exit calls in tool/hwmon tests
perf tests: Make leader sampling test work without branch event
perf util: Remove kernel version deadcode
perf test shell trace_exit_race: Use --no-comm to avoid cases where COMM isn't resolved
perf test shell trace_exit_race: Show what went wrong in verbose mode
...

+11077 -5717
+3 -8
tools/build/Makefile.feature
··· 30 30 # 31 31 FEATURE_TESTS_BASIC := \ 32 32 backtrace \ 33 - dwarf \ 34 - dwarf_getlocations \ 35 - dwarf_getcfi \ 33 + libdw \ 36 34 eventfd \ 37 35 fortify-source \ 38 36 get_current_dir_name \ ··· 59 61 reallocarray \ 60 62 stackprotector-all \ 61 63 timerfd \ 62 - libdw-dwarf-unwind \ 63 64 zlib \ 64 65 lzma \ 65 66 get_cpuid \ ··· 118 121 endif 119 122 120 123 FEATURE_DISPLAY ?= \ 121 - dwarf \ 122 - dwarf_getlocations \ 124 + libdw \ 123 125 glibc \ 124 126 libbfd \ 125 127 libbfd-buildid \ ··· 130 134 libpython \ 131 135 libcrypto \ 132 136 libunwind \ 133 - libdw-dwarf-unwind \ 134 137 libcapstone \ 135 138 llvm-perf \ 136 139 zlib \ ··· 229 234 230 235 # 231 236 # generates feature value assignment for name, like: 232 - # $(call feature_assign,dwarf) == feature-dwarf=1 237 + # $(call feature_assign,libdw) == feature-libdw=1 233 238 # 234 239 feature_assign = feature-$(1)=$(feature-$(1)) 235 240
+6 -18
tools/build/feature/Makefile
··· 5 5 test-all.bin \ 6 6 test-backtrace.bin \ 7 7 test-bionic.bin \ 8 - test-dwarf.bin \ 9 - test-dwarf_getlocations.bin \ 10 - test-dwarf_getcfi.bin \ 8 + test-libdw.bin \ 11 9 test-eventfd.bin \ 12 10 test-fortify-source.bin \ 13 11 test-get_current_dir_name.bin \ ··· 51 53 test-pthread-barrier.bin \ 52 54 test-stackprotector-all.bin \ 53 55 test-timerfd.bin \ 54 - test-libdw-dwarf-unwind.bin \ 55 56 test-libbabeltrace.bin \ 56 57 test-libcapstone.bin \ 57 58 test-compile-32.bin \ ··· 166 169 $(BUILD) # -lopencsd_c_api -lopencsd provided by 167 170 # $(FEATURE_CHECK_LDFLAGS-libopencsd) 168 171 169 - DWARFLIBS := -ldw 172 + DWLIBS := -ldw 170 173 ifeq ($(findstring -static,${LDFLAGS}),-static) 171 - DWARFLIBS += -lelf -lz -llzma -lbz2 -lzstd 174 + DWLIBS += -lelf -lz -llzma -lbz2 -lzstd 172 175 173 176 LIBDW_VERSION := $(shell $(PKG_CONFIG) --modversion libdw).0.0 174 177 LIBDW_VERSION_1 := $(word 1, $(subst ., ,$(LIBDW_VERSION))) ··· 177 180 # Elfutils merged libebl.a into libdw.a starting from version 0.177, 178 181 # Link libebl.a only if libdw is older than this version. 179 182 ifeq ($(shell test $(LIBDW_VERSION_2) -lt 177; echo $$?),0) 180 - DWARFLIBS += -lebl 183 + DWLIBS += -lebl 181 184 endif 182 185 183 186 # Must put -ldl after -lebl for dependency 184 187 DWARFLIBS += -ldl 185 188 endif 186 189 187 - $(OUTPUT)test-dwarf.bin: 188 - $(BUILD) $(DWARFLIBS) 189 - 190 - $(OUTPUT)test-dwarf_getlocations.bin: 191 - $(BUILD) $(DWARFLIBS) 192 - 193 - $(OUTPUT)test-dwarf_getcfi.bin: 194 - $(BUILD) $(DWARFLIBS) 190 + $(OUTPUT)test-libdw.bin: 191 + $(BUILD) $(DWLIBS) 195 192 196 193 $(OUTPUT)test-libelf-getphdrnum.bin: 197 194 $(BUILD) -lelf ··· 311 320 312 321 $(OUTPUT)test-timerfd.bin: 313 322 $(BUILD) 314 - 315 - $(OUTPUT)test-libdw-dwarf-unwind.bin: 316 - $(BUILD) # -ldw provided by $(FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind) 317 323 318 324 $(OUTPUT)test-libbabeltrace.bin: 319 325 $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
+3 -13
tools/build/feature/test-all.c
··· 38 38 # include "test-glibc.c" 39 39 #undef main 40 40 41 - #define main main_test_dwarf 42 - # include "test-dwarf.c" 43 - #undef main 44 - 45 - #define main main_test_dwarf_getlocations 46 - # include "test-dwarf_getlocations.c" 41 + #define main main_test_libdw 42 + # include "test-libdw.c" 47 43 #undef main 48 44 49 45 #define main main_test_eventfd ··· 92 96 93 97 #define main main_test_stackprotector_all 94 98 # include "test-stackprotector-all.c" 95 - #undef main 96 - 97 - #define main main_test_libdw_dwarf_unwind 98 - # include "test-libdw-dwarf-unwind.c" 99 99 #undef main 100 100 101 101 #define main main_test_zlib ··· 179 187 main_test_get_current_dir_name(); 180 188 main_test_gettid(); 181 189 main_test_glibc(); 182 - main_test_dwarf(); 183 - main_test_dwarf_getlocations(); 190 + main_test_libdw(); 184 191 main_test_eventfd(); 185 192 main_test_libelf_getphdrnum(); 186 193 main_test_libelf_gelf_getnote(); ··· 193 202 main_test_numa_num_possible_cpus(); 194 203 main_test_timerfd(); 195 204 main_test_stackprotector_all(); 196 - main_test_libdw_dwarf_unwind(); 197 205 main_test_zlib(); 198 206 main_test_pthread_attr_setaffinity_np(); 199 207 main_test_pthread_barrier();
-11
tools/build/feature/test-dwarf.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <dwarf.h> 3 - #include <elfutils/libdw.h> 4 - #include <elfutils/version.h> 5 - 6 - int main(void) 7 - { 8 - Dwarf *dbg = dwarf_begin(0, DWARF_C_READ); 9 - 10 - return (long)dbg; 11 - }
-9
tools/build/feature/test-dwarf_getcfi.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <stdio.h> 3 - #include <elfutils/libdw.h> 4 - 5 - int main(void) 6 - { 7 - Dwarf *dwarf = NULL; 8 - return dwarf_getcfi(dwarf) == NULL; 9 - }
-13
tools/build/feature/test-dwarf_getlocations.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <stdlib.h> 3 - #include <elfutils/libdw.h> 4 - 5 - int main(void) 6 - { 7 - Dwarf_Addr base, start, end; 8 - Dwarf_Attribute attr; 9 - Dwarf_Op *op; 10 - size_t nops; 11 - ptrdiff_t offset = 0; 12 - return (int)dwarf_getlocations(&attr, offset, &base, &start, &end, &op, &nops); 13 - }
-14
tools/build/feature/test-libdw-dwarf-unwind.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - 3 - #include <elfutils/libdwfl.h> 4 - 5 - int main(void) 6 - { 7 - /* 8 - * This function is guarded via: __nonnull_attribute__ (1, 2). 9 - * Passing '1' as arguments value. This code is never executed, 10 - * only compiled. 11 - */ 12 - dwfl_thread_getframes((void *) 1, (void *) 1, NULL); 13 - return 0; 14 - }
+56
tools/build/feature/test-libdw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <stdlib.h> 3 + #include <dwarf.h> 4 + #include <elfutils/libdw.h> 5 + #include <elfutils/libdwfl.h> 6 + #include <elfutils/version.h> 7 + 8 + int test_libdw(void) 9 + { 10 + Dwarf *dbg = dwarf_begin(0, DWARF_C_READ); 11 + 12 + return (long)dbg; 13 + } 14 + 15 + int test_libdw_unwind(void) 16 + { 17 + /* 18 + * This function is guarded via: __nonnull_attribute__ (1, 2). 19 + * Passing '1' as arguments value. This code is never executed, 20 + * only compiled. 21 + */ 22 + dwfl_thread_getframes((void *) 1, (void *) 1, NULL); 23 + return 0; 24 + } 25 + 26 + int test_libdw_getlocations(void) 27 + { 28 + Dwarf_Addr base, start, end; 29 + Dwarf_Attribute attr; 30 + Dwarf_Op *op; 31 + size_t nops; 32 + ptrdiff_t offset = 0; 33 + 34 + return (int)dwarf_getlocations(&attr, offset, &base, &start, &end, &op, &nops); 35 + } 36 + 37 + int test_libdw_getcfi(void) 38 + { 39 + Dwarf *dwarf = NULL; 40 + 41 + return dwarf_getcfi(dwarf) == NULL; 42 + } 43 + 44 + int test_elfutils(void) 45 + { 46 + Dwarf_CFI *cfi = NULL; 47 + 48 + dwarf_cfi_end(cfi); 49 + return 0; 50 + } 51 + 52 + int main(void) 53 + { 54 + return test_libdw() + test_libdw_unwind() + test_libdw_getlocations() + 55 + test_libdw_getcfi() + test_elfutils(); 56 + }
+1 -1
tools/build/feature/test-libtraceevent.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <traceevent/trace-seq.h> 2 + #include <trace-seq.h> 3 3 4 4 int main(void) 5 5 {
+1
tools/lib/api/io.h
··· 189 189 err_out: 190 190 free(line); 191 191 *line_out = NULL; 192 + *line_len_out = 0; 192 193 return -ENOMEM; 193 194 } 194 195
+1 -1
tools/lib/perf/Documentation/Makefile
··· 121 121 $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir); \ 122 122 $(INSTALL) -m 644 $(MAN_7) $(DESTDIR)$(man7dir); 123 123 124 - install-html: 124 + install-html: $(MAN_HTML) 125 125 $(call QUIET_INSTALL, html) \ 126 126 $(INSTALL) -d -m 755 $(DESTDIR)$(htmldir); \ 127 127 $(INSTALL) -m 644 $(MAN_HTML) $(DESTDIR)$(htmldir); \
+48
tools/lib/perf/evsel.c
··· 5 5 #include <perf/evsel.h> 6 6 #include <perf/cpumap.h> 7 7 #include <perf/threadmap.h> 8 + #include <linux/hash.h> 8 9 #include <linux/list.h> 9 10 #include <internal/evsel.h> 10 11 #include <linux/zalloc.h> ··· 24 23 int idx) 25 24 { 26 25 INIT_LIST_HEAD(&evsel->node); 26 + INIT_LIST_HEAD(&evsel->per_stream_periods); 27 27 evsel->attr = *attr; 28 28 evsel->idx = idx; 29 29 evsel->leader = evsel; ··· 533 531 534 532 void perf_evsel__free_id(struct perf_evsel *evsel) 535 533 { 534 + struct perf_sample_id_period *pos, *n; 535 + 536 536 xyarray__delete(evsel->sample_id); 537 537 evsel->sample_id = NULL; 538 538 zfree(&evsel->id); 539 539 evsel->ids = 0; 540 + 541 + perf_evsel_for_each_per_thread_period_safe(evsel, n, pos) { 542 + list_del_init(&pos->node); 543 + free(pos); 544 + } 545 + } 546 + 547 + bool perf_evsel__attr_has_per_thread_sample_period(struct perf_evsel *evsel) 548 + { 549 + return (evsel->attr.sample_type & PERF_SAMPLE_READ) && 550 + (evsel->attr.sample_type & PERF_SAMPLE_TID) && 551 + evsel->attr.inherit; 552 + } 553 + 554 + u64 *perf_sample_id__get_period_storage(struct perf_sample_id *sid, u32 tid, bool per_thread) 555 + { 556 + struct hlist_head *head; 557 + struct perf_sample_id_period *res; 558 + int hash; 559 + 560 + if (!per_thread) 561 + return &sid->period; 562 + 563 + hash = hash_32(tid, PERF_SAMPLE_ID__HLIST_BITS); 564 + head = &sid->periods[hash]; 565 + 566 + hlist_for_each_entry(res, head, hnode) 567 + if (res->tid == tid) 568 + return &res->period; 569 + 570 + if (sid->evsel == NULL) 571 + return NULL; 572 + 573 + res = zalloc(sizeof(struct perf_sample_id_period)); 574 + if (res == NULL) 575 + return NULL; 576 + 577 + INIT_LIST_HEAD(&res->node); 578 + res->tid = tid; 579 + 580 + list_add_tail(&res->node, &sid->evsel->per_stream_periods); 581 + hlist_add_head(&res->hnode, &sid->periods[hash]); 582 + 583 + return &res->period; 540 584 } 541 585 542 586 void perf_counts_values__scale(struct perf_counts_values *count,
+61 -2
tools/lib/perf/include/internal/evsel.h
··· 11 11 struct perf_thread_map; 12 12 struct xyarray; 13 13 14 + /** 15 + * The per-thread accumulated period storage node. 16 + */ 17 + struct perf_sample_id_period { 18 + struct list_head node; 19 + struct hlist_node hnode; 20 + /* Holds total ID period value for PERF_SAMPLE_READ processing. */ 21 + u64 period; 22 + /* The TID that the values belongs to */ 23 + u32 tid; 24 + }; 25 + 26 + /** 27 + * perf_evsel_for_each_per_thread_period_safe - safely iterate thru all the 28 + * per_stream_periods 29 + * @evlist:perf_evsel instance to iterate 30 + * @item: struct perf_sample_id_period iterator 31 + * @tmp: struct perf_sample_id_period temp iterator 32 + */ 33 + #define perf_evsel_for_each_per_thread_period_safe(evsel, tmp, item) \ 34 + list_for_each_entry_safe(item, tmp, &(evsel)->per_stream_periods, node) 35 + 36 + 37 + #define PERF_SAMPLE_ID__HLIST_BITS 4 38 + #define PERF_SAMPLE_ID__HLIST_SIZE (1 << PERF_SAMPLE_ID__HLIST_BITS) 39 + 14 40 /* 15 41 * Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are 16 42 * more than one entry in the evlist. ··· 60 34 pid_t machine_pid; 61 35 struct perf_cpu vcpu; 62 36 63 - /* Holds total ID period value for PERF_SAMPLE_READ processing. */ 64 - u64 period; 37 + /* 38 + * Per-thread, and global event counts are mutually exclusive: 39 + * Whilst it is possible to combine events into a group with differing 40 + * values of PERF_SAMPLE_READ, it is not valid to have inconsistent 41 + * values for `inherit`. Therefore it is not possible to have a 42 + * situation where a per-thread event is sampled as a global event; 43 + * all !inherit groups are global, and all groups where the sampling 44 + * event is inherit + PERF_SAMPLE_READ will be per-thread. Any event 45 + * that is part of such a group that is inherit but not PERF_SAMPLE_READ 46 + * will be read as per-thread. If such an event can also trigger a 47 + * sample (such as with sample_period > 0) then it will not cause 48 + * `read_format` to be included in its PERF_RECORD_SAMPLE, and 49 + * therefore will not expose the per-thread group members as global. 50 + */ 51 + union { 52 + /* 53 + * Holds total ID period value for PERF_SAMPLE_READ processing 54 + * (when period is not per-thread). 55 + */ 56 + u64 period; 57 + /* 58 + * Holds total ID period value for PERF_SAMPLE_READ processing 59 + * (when period is per-thread). 60 + */ 61 + struct hlist_head periods[PERF_SAMPLE_ID__HLIST_SIZE]; 62 + }; 65 63 }; 66 64 67 65 struct perf_evsel { ··· 107 57 u64 *id; 108 58 u32 ids; 109 59 struct perf_evsel *leader; 60 + 61 + /* For events where the read_format value is per-thread rather than 62 + * global, stores the per-thread cumulative period */ 63 + struct list_head per_stream_periods; 110 64 111 65 /* parse modifier helper */ 112 66 int nr_members; ··· 141 87 142 88 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 143 89 void perf_evsel__free_id(struct perf_evsel *evsel); 90 + 91 + bool perf_evsel__attr_has_per_thread_sample_period(struct perf_evsel *evsel); 92 + 93 + u64 *perf_sample_id__get_period_storage(struct perf_sample_id *sid, u32 tid, 94 + bool per_thread); 144 95 145 96 #endif /* __LIBPERF_INTERNAL_EVSEL_H */
+33
tools/lib/subcmd/run-command.c
··· 2 2 #include <unistd.h> 3 3 #include <sys/types.h> 4 4 #include <sys/stat.h> 5 + #include <ctype.h> 5 6 #include <fcntl.h> 6 7 #include <string.h> 7 8 #include <linux/string.h> ··· 218 217 219 218 int check_if_command_finished(struct child_process *cmd) 220 219 { 220 + #ifdef __linux__ 221 + char filename[FILENAME_MAX + 12]; 222 + char status_line[256]; 223 + FILE *status_file; 224 + 225 + /* 226 + * Check by reading /proc/<pid>/status as calling waitpid causes 227 + * stdout/stderr to be closed and data lost. 228 + */ 229 + sprintf(filename, "/proc/%d/status", cmd->pid); 230 + status_file = fopen(filename, "r"); 231 + if (status_file == NULL) { 232 + /* Open failed assume finish_command was called. */ 233 + return true; 234 + } 235 + while (fgets(status_line, sizeof(status_line), status_file) != NULL) { 236 + char *p; 237 + 238 + if (strncmp(status_line, "State:", 6)) 239 + continue; 240 + 241 + fclose(status_file); 242 + p = status_line + 6; 243 + while (isspace(*p)) 244 + p++; 245 + return *p == 'Z' ? 1 : 0; 246 + } 247 + /* Read failed assume finish_command was called. */ 248 + fclose(status_file); 249 + return 1; 250 + #else 221 251 wait_or_whine(cmd, /*block=*/false); 222 252 return cmd->finished; 253 + #endif 223 254 } 224 255 225 256 int finish_command(struct child_process *cmd)
+1 -1
tools/lib/subcmd/subcmd-util.h
··· 20 20 21 21 va_start(params, err); 22 22 report(" Fatal: ", err, params); 23 - exit(128); 24 23 va_end(params); 24 + exit(128); 25 25 } 26 26 27 27 #define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
+3 -3
tools/perf/.gitignore
··· 39 39 pmu-events/pmu-events.c 40 40 pmu-events/jevents 41 41 pmu-events/metric_test.log 42 - tests/shell/*.shellcheck_log 43 - tests/shell/coresight/*.shellcheck_log 44 - tests/shell/lib/*.shellcheck_log 42 + pmu-events/empty-pmu-events.log 43 + pmu-events/test-empty-pmu-events.c 44 + *.shellcheck_log 45 45 feature/ 46 46 libapi/ 47 47 libbpf/
+1 -1
tools/perf/Documentation/itrace.txt
··· 1 1 i synthesize instructions events 2 2 y synthesize cycles events 3 - b synthesize branches events (branch misses for Arm SPE) 3 + b synthesize branches events 4 4 c synthesize branches events (calls only) 5 5 r synthesize branches events (returns only) 6 6 x synthesize transactions events
+1 -1
tools/perf/Documentation/perf-arm-spe.txt
··· 187 187 7 llc-access 188 188 2 tlb-miss 189 189 1K tlb-access 190 - 36 branch-miss 190 + 36 branch 191 191 0 remote-access 192 192 900 memory 193 193
+3 -3
tools/perf/Documentation/perf-check.txt
··· 47 47 bpf / HAVE_LIBBPF_SUPPORT 48 48 bpf_skeletons / HAVE_BPF_SKEL 49 49 debuginfod / HAVE_DEBUGINFOD_SUPPORT 50 - dwarf / HAVE_DWARF_SUPPORT 51 - dwarf_getlocations / HAVE_DWARF_GETLOCATIONS_SUPPORT 50 + dwarf / HAVE_LIBDW_SUPPORT 51 + dwarf_getlocations / HAVE_LIBDW_SUPPORT 52 52 dwarf-unwind / HAVE_DWARF_UNWIND_SUPPORT 53 53 auxtrace / HAVE_AUXTRACE_SUPPORT 54 54 libaudit / HAVE_LIBAUDIT_SUPPORT 55 55 libbfd / HAVE_LIBBFD_SUPPORT 56 56 libcapstone / HAVE_LIBCAPSTONE_SUPPORT 57 57 libcrypto / HAVE_LIBCRYPTO_SUPPORT 58 - libdw-dwarf-unwind / HAVE_DWARF_SUPPORT 58 + libdw-dwarf-unwind / HAVE_LIBDW_SUPPORT 59 59 libelf / HAVE_LIBELF_SUPPORT 60 60 libnuma / HAVE_LIBNUMA_SUPPORT 61 61 libopencsd / HAVE_CSTRACE_SUPPORT
+13
tools/perf/Documentation/perf-config.txt
··· 247 247 These are in control of addresses, jump function, source code 248 248 in lines of assembly code from a specific program. 249 249 250 + annotate.disassemblers:: 251 + Choose the disassembler to use: "objdump", "llvm", "capstone", 252 + if not specified it will first try, if available, the "llvm" one, 253 + then, if it fails, "capstone", and finally the original "objdump" 254 + based one. 255 + 256 + Choosing a different one is useful when handling some feature that 257 + is known to be best support at some point by one of the options, 258 + to compare the output when in doubt about some bug, etc. 259 + 260 + This can be a list, in order of preference, the first one that works 261 + finishes the process. 262 + 250 263 annotate.addr2line:: 251 264 addr2line binary to use for file names and line numbers. 252 265
+16 -1
tools/perf/Documentation/perf-list.txt
··· 8 8 SYNOPSIS 9 9 -------- 10 10 [verse] 11 - 'perf list' [--no-desc] [--long-desc] 11 + 'perf list' [<options>] 12 12 [hw|sw|cache|tracepoint|pmu|sdt|metric|metricgroup|event_glob] 13 13 14 14 DESCRIPTION ··· 242 242 For accessing trace point events perf needs to have read access to 243 243 /sys/kernel/tracing, even when perf_event_paranoid is in a relaxed 244 244 setting. 245 + 246 + TOOL/HWMON EVENTS 247 + ----------------- 248 + 249 + Some events don't have an associated PMU instead reading values 250 + available to software without perf_event_open. As these events don't 251 + support sampling they can only really be read by tools like perf stat. 252 + 253 + Tool events provide times and certain system parameters. Examples 254 + include duration_time, user_time, system_time and num_cpus_online. 255 + 256 + Hwmon events provide easy access to hwmon sysfs data typically in 257 + /sys/class/hwmon. This information includes temperatures, fan speeds 258 + and energy usage. 259 + 245 260 246 261 TRACING 247 262 -------
+8
tools/perf/Documentation/perf-report.txt
··· 391 391 This allows to examine the path the program took to each sample. 392 392 The data collection must have used -b (or -j) and -g. 393 393 394 + Also show with some branch flags that can be: 395 + - Predicted: display the average percentage of predicated branches. 396 + (predicated number / total number) 397 + - Abort: display the number of tsx aborted branches. 398 + - Cycles: cycles in basic block. 399 + 400 + - iterations: display the average number of iterations in callchain list. 401 + 394 402 --addr2line=<path>:: 395 403 Path to addr2line binary. 396 404
+8
tools/perf/Documentation/perf-sched.txt
··· 221 221 priorities are specified with -: 120-129. A combination of both can also be 222 222 provided: 0,120-129. 223 223 224 + -P:: 225 + --pre-migrations:: 226 + Show pre-migration wait time. pre-migration wait time is the time spent 227 + by a task waiting on a runqueue but not getting the chance to run there 228 + and is migrated to a different runqueue where it is finally run. This 229 + time between sched_wakeup and migrate_task is the pre-migration wait 230 + time. 231 + 224 232 OPTIONS for 'perf sched replay' 225 233 ------------------------------ 226 234
+1 -1
tools/perf/Documentation/perf-script-python.txt
··· 624 624 perf_set_itrace_options(context, itrace_options) - set --itrace options if they have not been set already 625 625 perf_sample_srcline(context) - returns source_file_name, line_number 626 626 perf_sample_srccode(context) - returns source_file_name, line_number, source_line 627 - 627 + perf_config_get(config_name) - returns the value of the named config item, or None if unset 628 628 629 629 Util.py Module 630 630 ~~~~~~~~~~~~~~
+17
tools/perf/Documentation/perf-test.txt
··· 48 48 49 49 --dso:: 50 50 Specify a DSO for the "Symbols" test. 51 + 52 + -w:: 53 + --workload=:: 54 + Run a built-in workload, to list them use '--list-workloads', current ones include: 55 + noploop, thloop, leafloop, sqrtloop, brstack, datasym and landlock. 56 + 57 + Used with the shell script regression tests. 58 + 59 + Some accept an extra parameter: 60 + 61 + seconds: leafloop, noploop, sqrtloop, thloop 62 + nrloops: brstack 63 + 64 + The datasym and landlock workloads don't accept any. 65 + 66 + --list-workloads:: 67 + List the available workloads to use with -w/--workload.
+25 -45
tools/perf/Makefile.config
··· 31 31 ifneq ($(NO_SYSCALL_TABLE),1) 32 32 NO_SYSCALL_TABLE := 1 33 33 34 - ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 powerpc arm64 s390 mips loongarch)) 34 + ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 powerpc arm64 s390 mips loongarch riscv)) 35 35 NO_SYSCALL_TABLE := 0 36 36 endif 37 37 ··· 83 83 LIBUNWIND_LIBS = -lunwind -lunwind-mips 84 84 endif 85 85 86 + ifeq ($(ARCH),riscv) 87 + CFLAGS += -I$(OUTPUT)arch/riscv/include/generated 88 + endif 89 + 86 90 # So far there's only x86 and arm libdw unwind support merged in perf. 87 91 # Disable it on all other architectures in case libdw unwind 88 92 # support is detected in system. Add supported architectures 89 93 # to the check. 90 94 ifneq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc s390 csky riscv loongarch)) 91 95 NO_LIBDW_DWARF_UNWIND := 1 96 + endif 97 + 98 + ifneq ($(LIBUNWIND),1) 99 + NO_LIBUNWIND := 1 92 100 endif 93 101 94 102 ifeq ($(LIBUNWIND_LIBS),) ··· 170 162 # Must put -ldl after -lebl for dependency 171 163 DWARFLIBS += -ldl 172 164 endif 173 - FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS) 174 - FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) $(DWARFLIBS) 165 + FEATURE_CHECK_CFLAGS-libdw := $(LIBDW_CFLAGS) 166 + FEATURE_CHECK_LDFLAGS-libdw := $(LIBDW_LDFLAGS) $(DWARFLIBS) 175 167 176 168 # for linking with debug library, run like: 177 169 # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/ ··· 210 202 FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(SRCARCH)/include/uapi -I$(srctree)/tools/include/uapi 211 203 # include ARCH specific config 212 204 -include $(src-perf)/arch/$(SRCARCH)/Makefile 213 - 214 - ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET 215 - CFLAGS += -DHAVE_ARCH_REGS_QUERY_REGISTER_OFFSET 216 - endif 217 205 218 206 include $(srctree)/tools/scripts/utilities.mak 219 207 ··· 430 426 endif 431 427 432 428 ifdef NO_LIBELF 433 - NO_DWARF := 1 429 + NO_LIBDW := 1 434 430 NO_LIBUNWIND := 1 435 431 NO_LIBDW_DWARF_UNWIND := 1 436 432 NO_LIBBPF := 1 ··· 465 461 endif 466 462 endif 467 463 else 468 - ifndef NO_LIBDW_DWARF_UNWIND 469 - ifneq ($(feature-libdw-dwarf-unwind),1) 470 - NO_LIBDW_DWARF_UNWIND := 1 471 - $(warning No libdw DWARF unwind found, Please install elfutils-devel/libdw-dev >= 0.158 and/or set LIBDW_DIR) 464 + ifneq ($(feature-libdw), 1) 465 + ifndef NO_LIBDW 466 + $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.157, disables dwarf support. Please install new elfutils-devel/libdw-dev) 467 + NO_LIBDW := 1 472 468 endif 473 - endif 474 - ifneq ($(feature-dwarf), 1) 475 - ifndef NO_DWARF 476 - $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev) 477 - NO_DWARF := 1 478 - endif 479 - else 480 - ifneq ($(feature-dwarf_getlocations), 1) 481 - $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157) 482 - else 483 - CFLAGS += -DHAVE_DWARF_GETLOCATIONS_SUPPORT 484 - endif # dwarf_getlocations 485 - ifneq ($(feature-dwarf_getcfi), 1) 486 - $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.142) 487 - else 488 - CFLAGS += -DHAVE_DWARF_CFI_SUPPORT 489 - endif # dwarf_getcfi 490 469 endif # Dwarf support 491 470 endif # libelf support 492 471 endif # NO_LIBELF ··· 480 493 endif 481 494 endif 482 495 483 - ifdef NO_DWARF 496 + ifdef NO_LIBDW 484 497 NO_LIBDW_DWARF_UNWIND := 1 485 498 endif 486 499 ··· 558 571 endif 559 572 endif 560 573 561 - ifndef NO_DWARF 562 - ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 563 - $(warning DWARF register mappings have not been defined for architecture $(SRCARCH), DWARF support disabled) 564 - NO_DWARF := 1 565 - else 566 - CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) 567 - LDFLAGS += $(LIBDW_LDFLAGS) 568 - EXTLIBS += ${DWARFLIBS} 569 - $(call detected,CONFIG_DWARF) 570 - endif # PERF_HAVE_DWARF_REGS 571 - endif # NO_DWARF 574 + ifndef NO_LIBDW 575 + CFLAGS += -DHAVE_LIBDW_SUPPORT $(LIBDW_CFLAGS) 576 + LDFLAGS += $(LIBDW_LDFLAGS) 577 + EXTLIBS += ${DWARFLIBS} 578 + $(call detected,CONFIG_LIBDW) 579 + endif # NO_LIBDW 572 580 573 581 ifndef NO_LIBBPF 574 582 ifeq ($(feature-bpf), 1) ··· 612 630 endif 613 631 614 632 ifeq ($(SRCARCH),powerpc) 615 - ifndef NO_DWARF 633 + ifndef NO_LIBDW 616 634 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX 617 635 endif 618 636 endif ··· 732 750 ifeq ($(dwarf-post-unwind),1) 733 751 CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT 734 752 $(call detected,CONFIG_DWARF_UNWIND) 735 - else 736 - NO_DWARF_UNWIND := 1 737 753 endif 738 754 739 755 ifndef NO_LOCAL_LIBUNWIND ··· 1174 1194 ifneq ($(NO_LIBTRACEEVENT),1) 1175 1195 $(call feature_check,libtraceevent) 1176 1196 ifeq ($(feature-libtraceevent), 1) 1177 - CFLAGS += -DHAVE_LIBTRACEEVENT 1197 + CFLAGS += -DHAVE_LIBTRACEEVENT $(shell $(PKG_CONFIG) --cflags libtraceevent) 1178 1198 LDFLAGS += $(shell $(PKG_CONFIG) --libs-only-L libtraceevent) 1179 1199 EXTLIBS += $(shell $(PKG_CONFIG) --libs-only-l libtraceevent) 1180 1200 LIBTRACEEVENT_VERSION := $(shell $(PKG_CONFIG) --modversion libtraceevent).0.0
+4 -5
tools/perf/Makefile.perf
··· 40 40 # 41 41 # Define EXTRA_PERFLIBS to pass extra libraries to PERFLIBS. 42 42 # 43 - # Define NO_DWARF if you do not want debug-info analysis feature at all. 43 + # Define NO_LIBDW if you do not want debug-info analysis feature at all. 44 44 # 45 45 # Define WERROR=0 to disable treating any warnings as errors. 46 46 # ··· 52 52 # 53 53 # Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds) 54 54 # 55 - # Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf 55 + # Define LIBUNWIND if you do not want libunwind dependency for dwarf 56 56 # backtrace post unwind. 57 57 # 58 58 # Define NO_BACKTRACE if you do not want stack backtrace debug feature ··· 1128 1128 install-tests: all install-gtk 1129 1129 $(call QUIET_INSTALL, tests) \ 1130 1130 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 1131 - $(INSTALL) tests/attr.py -m 644 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 1132 1131 $(INSTALL) tests/pe-file.exe* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 1133 - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ 1134 - $(INSTALL) tests/attr/* -m 644 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ 1135 1132 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \ 1136 1133 $(INSTALL) tests/shell/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \ 1134 + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/attr'; \ 1135 + $(INSTALL) tests/shell/attr/* -m 644 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/attr'; \ 1137 1136 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'; \ 1138 1137 $(INSTALL) tests/shell/lib/*.sh -m 644 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'; \ 1139 1138 $(INSTALL) tests/shell/lib/*.py -m 644 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'; \
+2
tools/perf/arch/arc/annotate/instructions.c
··· 5 5 { 6 6 arch->initialized = true; 7 7 arch->objdump.comment_char = ';'; 8 + arch->e_machine = EM_ARC; 9 + arch->e_flags = 0; 8 10 return 0; 9 11 }
-3
tools/perf/arch/arm/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif 5 2 PERF_HAVE_JITDUMP := 1
+2
tools/perf/arch/arm/annotate/instructions.c
··· 53 53 arch->associate_instruction_ops = arm__associate_instruction_ops; 54 54 arch->objdump.comment_char = ';'; 55 55 arch->objdump.skip_functions_char = '+'; 56 + arch->e_machine = EM_ARM; 57 + arch->e_flags = 0; 56 58 return 0; 57 59 58 60 out_free_call:
-2
tools/perf/arch/arm/util/Build
··· 1 1 perf-util-y += perf_regs.o 2 2 3 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 4 - 5 3 perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o 6 4 perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 7 5
-61
tools/perf/arch/arm/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * Mapping of DWARF debug register numbers into register names. 4 - * 5 - * Copyright (C) 2010 Will Deacon, ARM Ltd. 6 - */ 7 - 8 - #include <stddef.h> 9 - #include <linux/stringify.h> 10 - #include <dwarf-regs.h> 11 - 12 - struct pt_regs_dwarfnum { 13 - const char *name; 14 - unsigned int dwarfnum; 15 - }; 16 - 17 - #define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} 18 - #define GPR_DWARFNUM_NAME(num) \ 19 - {.name = __stringify(%r##num), .dwarfnum = num} 20 - #define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} 21 - 22 - /* 23 - * Reference: 24 - * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf 25 - */ 26 - static const struct pt_regs_dwarfnum regdwarfnum_table[] = { 27 - GPR_DWARFNUM_NAME(0), 28 - GPR_DWARFNUM_NAME(1), 29 - GPR_DWARFNUM_NAME(2), 30 - GPR_DWARFNUM_NAME(3), 31 - GPR_DWARFNUM_NAME(4), 32 - GPR_DWARFNUM_NAME(5), 33 - GPR_DWARFNUM_NAME(6), 34 - GPR_DWARFNUM_NAME(7), 35 - GPR_DWARFNUM_NAME(8), 36 - GPR_DWARFNUM_NAME(9), 37 - GPR_DWARFNUM_NAME(10), 38 - REG_DWARFNUM_NAME("%fp", 11), 39 - REG_DWARFNUM_NAME("%ip", 12), 40 - REG_DWARFNUM_NAME("%sp", 13), 41 - REG_DWARFNUM_NAME("%lr", 14), 42 - REG_DWARFNUM_NAME("%pc", 15), 43 - REG_DWARFNUM_END, 44 - }; 45 - 46 - /** 47 - * get_arch_regstr() - lookup register name from it's DWARF register number 48 - * @n: the DWARF register number 49 - * 50 - * get_arch_regstr() returns the name of the register in struct 51 - * regdwarfnum_table from it's DWARF register number. If the register is not 52 - * found in the table, this returns NULL; 53 - */ 54 - const char *get_arch_regstr(unsigned int n) 55 - { 56 - const struct pt_regs_dwarfnum *roff; 57 - for (roff = regdwarfnum_table; roff->name != NULL; roff++) 58 - if (roff->dwarfnum == n) 59 - return roff->name; 60 - return NULL; 61 - }
-4
tools/perf/arch/arm64/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif 5 2 PERF_HAVE_JITDUMP := 1 6 - PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 7 3 HAVE_KVM_STAT_SUPPORT := 1 8 4 9 5 #
+2
tools/perf/arch/arm64/annotate/instructions.c
··· 113 113 arch->associate_instruction_ops = arm64__associate_instruction_ops; 114 114 arch->objdump.comment_char = '/'; 115 115 arch->objdump.skip_functions_char = '+'; 116 + arch->e_machine = EM_AARCH64; 117 + arch->e_flags = 0; 116 118 return 0; 117 119 118 120 out_free_call:
-1
tools/perf/arch/arm64/util/Build
··· 4 4 perf-util-y += tsc.o 5 5 perf-util-y += pmu.o 6 6 perf-util-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o 7 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 8 7 perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o 9 8 perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 10 9
+110 -8
tools/perf/arch/arm64/util/arm-spe.c
··· 23 23 #include "../../../util/debug.h" 24 24 #include "../../../util/auxtrace.h" 25 25 #include "../../../util/record.h" 26 + #include "../../../util/header.h" 26 27 #include "../../../util/arm-spe.h" 27 28 #include <tools/libc_compat.h> // reallocarray 29 + 30 + #define ARM_SPE_CPU_MAGIC 0x1010101010101010ULL 28 31 29 32 #define KiB(x) ((x) * 1024) 30 33 #define MiB(x) ((x) * 1024 * 1024) ··· 40 37 bool *wrapped; 41 38 }; 42 39 40 + /* 41 + * arm_spe_find_cpus() returns a new cpu map, and the caller should invoke 42 + * perf_cpu_map__put() to release the map after use. 43 + */ 44 + static struct perf_cpu_map *arm_spe_find_cpus(struct evlist *evlist) 45 + { 46 + struct perf_cpu_map *event_cpus = evlist->core.user_requested_cpus; 47 + struct perf_cpu_map *online_cpus = perf_cpu_map__new_online_cpus(); 48 + struct perf_cpu_map *intersect_cpus; 49 + 50 + /* cpu map is not "any" CPU , we have specific CPUs to work with */ 51 + if (!perf_cpu_map__has_any_cpu(event_cpus)) { 52 + intersect_cpus = perf_cpu_map__intersect(event_cpus, online_cpus); 53 + perf_cpu_map__put(online_cpus); 54 + /* Event can be "any" CPU so count all CPUs. */ 55 + } else { 56 + intersect_cpus = online_cpus; 57 + } 58 + 59 + return intersect_cpus; 60 + } 61 + 43 62 static size_t 44 63 arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused, 45 - struct evlist *evlist __maybe_unused) 64 + struct evlist *evlist) 46 65 { 47 - return ARM_SPE_AUXTRACE_PRIV_SIZE; 66 + struct perf_cpu_map *cpu_map = arm_spe_find_cpus(evlist); 67 + size_t size; 68 + 69 + if (!cpu_map) 70 + return 0; 71 + 72 + size = ARM_SPE_AUXTRACE_PRIV_MAX + 73 + ARM_SPE_CPU_PRIV_MAX * perf_cpu_map__nr(cpu_map); 74 + size *= sizeof(u64); 75 + 76 + perf_cpu_map__put(cpu_map); 77 + return size; 78 + } 79 + 80 + static int arm_spe_save_cpu_header(struct auxtrace_record *itr, 81 + struct perf_cpu cpu, __u64 data[]) 82 + { 83 + struct arm_spe_recording *sper = 84 + container_of(itr, struct arm_spe_recording, itr); 85 + struct perf_pmu *pmu = NULL; 86 + char *cpuid = NULL; 87 + u64 val; 88 + 89 + /* Read CPU MIDR */ 90 + cpuid = get_cpuid_allow_env_override(cpu); 91 + if (!cpuid) 92 + return -ENOMEM; 93 + val = strtol(cpuid, NULL, 16); 94 + 95 + data[ARM_SPE_MAGIC] = ARM_SPE_CPU_MAGIC; 96 + data[ARM_SPE_CPU] = cpu.cpu; 97 + data[ARM_SPE_CPU_NR_PARAMS] = ARM_SPE_CPU_PRIV_MAX - ARM_SPE_CPU_MIDR; 98 + data[ARM_SPE_CPU_MIDR] = val; 99 + 100 + /* Find the associate Arm SPE PMU for the CPU */ 101 + if (perf_cpu_map__has(sper->arm_spe_pmu->cpus, cpu)) 102 + pmu = sper->arm_spe_pmu; 103 + 104 + if (!pmu) { 105 + /* No Arm SPE PMU is found */ 106 + data[ARM_SPE_CPU_PMU_TYPE] = ULLONG_MAX; 107 + data[ARM_SPE_CAP_MIN_IVAL] = 0; 108 + } else { 109 + data[ARM_SPE_CPU_PMU_TYPE] = pmu->type; 110 + 111 + if (perf_pmu__scan_file(pmu, "caps/min_interval", "%lu", &val) != 1) 112 + val = 0; 113 + data[ARM_SPE_CAP_MIN_IVAL] = val; 114 + } 115 + 116 + free(cpuid); 117 + return ARM_SPE_CPU_PRIV_MAX; 48 118 } 49 119 50 120 static int arm_spe_info_fill(struct auxtrace_record *itr, ··· 125 49 struct perf_record_auxtrace_info *auxtrace_info, 126 50 size_t priv_size) 127 51 { 52 + int i, ret; 53 + size_t offset; 128 54 struct arm_spe_recording *sper = 129 55 container_of(itr, struct arm_spe_recording, itr); 130 56 struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu; 57 + struct perf_cpu_map *cpu_map; 58 + struct perf_cpu cpu; 59 + __u64 *data; 131 60 132 - if (priv_size != ARM_SPE_AUXTRACE_PRIV_SIZE) 61 + if (priv_size != arm_spe_info_priv_size(itr, session->evlist)) 133 62 return -EINVAL; 134 63 135 64 if (!session->evlist->core.nr_mmaps) 136 65 return -EINVAL; 137 66 138 - auxtrace_info->type = PERF_AUXTRACE_ARM_SPE; 139 - auxtrace_info->priv[ARM_SPE_PMU_TYPE] = arm_spe_pmu->type; 67 + cpu_map = arm_spe_find_cpus(session->evlist); 68 + if (!cpu_map) 69 + return -EINVAL; 140 70 141 - return 0; 71 + auxtrace_info->type = PERF_AUXTRACE_ARM_SPE; 72 + auxtrace_info->priv[ARM_SPE_HEADER_VERSION] = ARM_SPE_HEADER_CURRENT_VERSION; 73 + auxtrace_info->priv[ARM_SPE_HEADER_SIZE] = 74 + ARM_SPE_AUXTRACE_PRIV_MAX - ARM_SPE_HEADER_VERSION; 75 + auxtrace_info->priv[ARM_SPE_PMU_TYPE_V2] = arm_spe_pmu->type; 76 + auxtrace_info->priv[ARM_SPE_CPUS_NUM] = perf_cpu_map__nr(cpu_map); 77 + 78 + offset = ARM_SPE_AUXTRACE_PRIV_MAX; 79 + perf_cpu_map__for_each_cpu(cpu, i, cpu_map) { 80 + assert(offset < priv_size); 81 + data = &auxtrace_info->priv[offset]; 82 + ret = arm_spe_save_cpu_header(itr, cpu, data); 83 + if (ret < 0) 84 + goto out; 85 + offset += ret; 86 + } 87 + 88 + ret = 0; 89 + out: 90 + perf_cpu_map__put(cpu_map); 91 + return ret; 142 92 } 143 93 144 94 static void ··· 290 188 291 189 evlist__for_each_entry(evlist, evsel) { 292 190 if (evsel__is_aux_event(evsel)) { 293 - if (!strstarts(evsel->pmu_name, ARM_SPE_PMU_NAME)) { 191 + if (!strstarts(evsel->pmu->name, ARM_SPE_PMU_NAME)) { 294 192 pr_err("Found unexpected auxtrace event: %s\n", 295 - evsel->pmu_name); 193 + evsel->pmu->name); 296 194 return -EINVAL; 297 195 } 298 196 opts->full_auxtrace = true;
-92
tools/perf/arch/arm64/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-only 2 - /* 3 - * Mapping of DWARF debug register numbers into register names. 4 - * 5 - * Copyright (C) 2010 Will Deacon, ARM Ltd. 6 - */ 7 - 8 - #include <errno.h> 9 - #include <stddef.h> 10 - #include <string.h> 11 - #include <dwarf-regs.h> 12 - #include <linux/ptrace.h> /* for struct user_pt_regs */ 13 - #include <linux/stringify.h> 14 - 15 - struct pt_regs_dwarfnum { 16 - const char *name; 17 - unsigned int dwarfnum; 18 - }; 19 - 20 - #define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} 21 - #define GPR_DWARFNUM_NAME(num) \ 22 - {.name = __stringify(%x##num), .dwarfnum = num} 23 - #define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} 24 - #define DWARFNUM2OFFSET(index) \ 25 - (index * sizeof((struct user_pt_regs *)0)->regs[0]) 26 - 27 - /* 28 - * Reference: 29 - * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0057b/IHI0057B_aadwarf64.pdf 30 - */ 31 - static const struct pt_regs_dwarfnum regdwarfnum_table[] = { 32 - GPR_DWARFNUM_NAME(0), 33 - GPR_DWARFNUM_NAME(1), 34 - GPR_DWARFNUM_NAME(2), 35 - GPR_DWARFNUM_NAME(3), 36 - GPR_DWARFNUM_NAME(4), 37 - GPR_DWARFNUM_NAME(5), 38 - GPR_DWARFNUM_NAME(6), 39 - GPR_DWARFNUM_NAME(7), 40 - GPR_DWARFNUM_NAME(8), 41 - GPR_DWARFNUM_NAME(9), 42 - GPR_DWARFNUM_NAME(10), 43 - GPR_DWARFNUM_NAME(11), 44 - GPR_DWARFNUM_NAME(12), 45 - GPR_DWARFNUM_NAME(13), 46 - GPR_DWARFNUM_NAME(14), 47 - GPR_DWARFNUM_NAME(15), 48 - GPR_DWARFNUM_NAME(16), 49 - GPR_DWARFNUM_NAME(17), 50 - GPR_DWARFNUM_NAME(18), 51 - GPR_DWARFNUM_NAME(19), 52 - GPR_DWARFNUM_NAME(20), 53 - GPR_DWARFNUM_NAME(21), 54 - GPR_DWARFNUM_NAME(22), 55 - GPR_DWARFNUM_NAME(23), 56 - GPR_DWARFNUM_NAME(24), 57 - GPR_DWARFNUM_NAME(25), 58 - GPR_DWARFNUM_NAME(26), 59 - GPR_DWARFNUM_NAME(27), 60 - GPR_DWARFNUM_NAME(28), 61 - GPR_DWARFNUM_NAME(29), 62 - REG_DWARFNUM_NAME("%lr", 30), 63 - REG_DWARFNUM_NAME("%sp", 31), 64 - REG_DWARFNUM_END, 65 - }; 66 - 67 - /** 68 - * get_arch_regstr() - lookup register name from it's DWARF register number 69 - * @n: the DWARF register number 70 - * 71 - * get_arch_regstr() returns the name of the register in struct 72 - * regdwarfnum_table from it's DWARF register number. If the register is not 73 - * found in the table, this returns NULL; 74 - */ 75 - const char *get_arch_regstr(unsigned int n) 76 - { 77 - const struct pt_regs_dwarfnum *roff; 78 - for (roff = regdwarfnum_table; roff->name != NULL; roff++) 79 - if (roff->dwarfnum == n) 80 - return roff->name; 81 - return NULL; 82 - } 83 - 84 - int regs_query_register_offset(const char *name) 85 - { 86 - const struct pt_regs_dwarfnum *roff; 87 - 88 - for (roff = regdwarfnum_table; roff->name != NULL; roff++) 89 - if (!strcmp(roff->name, name)) 90 - return DWARFNUM2OFFSET(roff->dwarfnum); 91 - return -EINVAL; 92 - }
+33 -40
tools/perf/arch/arm64/util/header.c
··· 14 14 #define MIDR_REVISION_MASK GENMASK(3, 0) 15 15 #define MIDR_VARIANT_MASK GENMASK(23, 20) 16 16 17 - static int _get_cpuid(char *buf, size_t sz, struct perf_cpu_map *cpus) 17 + static int _get_cpuid(char *buf, size_t sz, struct perf_cpu cpu) 18 18 { 19 + char path[PATH_MAX]; 20 + FILE *file; 19 21 const char *sysfs = sysfs__mountpoint(); 20 - struct perf_cpu cpu; 21 - int idx, ret = EINVAL; 22 22 23 + assert(cpu.cpu != -1); 23 24 if (!sysfs || sz < MIDR_SIZE) 24 25 return EINVAL; 25 26 26 - perf_cpu_map__for_each_cpu(cpu, idx, cpus) { 27 - char path[PATH_MAX]; 28 - FILE *file; 27 + scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d" MIDR, sysfs, cpu.cpu); 29 28 30 - scnprintf(path, PATH_MAX, "%s/devices/system/cpu/cpu%d" MIDR, 31 - sysfs, cpu.cpu); 32 - 33 - file = fopen(path, "r"); 34 - if (!file) { 35 - pr_debug("fopen failed for file %s\n", path); 36 - continue; 37 - } 38 - 39 - if (!fgets(buf, MIDR_SIZE, file)) { 40 - fclose(file); 41 - continue; 42 - } 43 - fclose(file); 44 - 45 - /* got midr break loop */ 46 - ret = 0; 47 - break; 29 + file = fopen(path, "r"); 30 + if (!file) { 31 + pr_debug("fopen failed for file %s\n", path); 32 + return EINVAL; 48 33 } 49 34 50 - return ret; 35 + if (!fgets(buf, MIDR_SIZE, file)) { 36 + pr_debug("Failed to read file %s\n", path); 37 + fclose(file); 38 + return EINVAL; 39 + } 40 + fclose(file); 41 + return 0; 51 42 } 52 43 53 - int get_cpuid(char *buf, size_t sz) 44 + int get_cpuid(char *buf, size_t sz, struct perf_cpu cpu) 54 45 { 55 - struct perf_cpu_map *cpus = perf_cpu_map__new_online_cpus(); 56 - int ret; 46 + struct perf_cpu_map *cpus; 47 + int idx; 57 48 49 + if (cpu.cpu != -1) 50 + return _get_cpuid(buf, sz, cpu); 51 + 52 + cpus = perf_cpu_map__new_online_cpus(); 58 53 if (!cpus) 59 54 return EINVAL; 60 55 61 - ret = _get_cpuid(buf, sz, cpus); 56 + perf_cpu_map__for_each_cpu(cpu, idx, cpus) { 57 + int ret = _get_cpuid(buf, sz, cpu); 62 58 63 - perf_cpu_map__put(cpus); 64 - 65 - return ret; 59 + if (ret == 0) 60 + return 0; 61 + } 62 + return EINVAL; 66 63 } 67 64 68 - char *get_cpuid_str(struct perf_pmu *pmu) 65 + char *get_cpuid_str(struct perf_cpu cpu) 69 66 { 70 - char *buf = NULL; 67 + char *buf = malloc(MIDR_SIZE); 71 68 int res; 72 69 73 - if (!pmu || !pmu->cpus) 74 - return NULL; 75 - 76 - buf = malloc(MIDR_SIZE); 77 70 if (!buf) 78 71 return NULL; 79 72 80 73 /* read midr from list of cpus mapped to this pmu */ 81 - res = _get_cpuid(buf, MIDR_SIZE, pmu->cpus); 74 + res = get_cpuid(buf, MIDR_SIZE, cpu); 82 75 if (res) { 83 - pr_err("failed to get cpuid string for PMU %s\n", pmu->name); 76 + pr_err("failed to get cpuid string for CPU %d\n", cpu.cpu); 84 77 free(buf); 85 78 buf = NULL; 86 79 }
+3 -22
tools/perf/arch/arm64/util/pmu.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 - #include <internal/cpumap.h> 4 - #include "../../../util/cpumap.h" 5 - #include "../../../util/header.h" 6 3 #include "../../../util/pmu.h" 7 4 #include "../../../util/pmus.h" 5 + #include "../../../util/tool_pmu.h" 8 6 #include <api/fs/fs.h> 9 - #include <math.h> 10 7 11 - const struct pmu_metrics_table *pmu_metrics_table__find(void) 12 - { 13 - struct perf_pmu *pmu; 14 - 15 - /* Metrics aren't currently supported on heterogeneous Arm systems */ 16 - if (perf_pmus__num_core_pmus() > 1) 17 - return NULL; 18 - 19 - /* Doesn't matter which one here because they'll all be the same */ 20 - pmu = perf_pmus__find_core_pmu(); 21 - if (pmu) 22 - return perf_pmu__find_metrics_table(pmu); 23 - 24 - return NULL; 25 - } 26 - 27 - double perf_pmu__cpu_slots_per_cycle(void) 8 + u64 tool_pmu__cpu_slots_per_cycle(void) 28 9 { 29 10 char path[PATH_MAX]; 30 11 unsigned long long slots = 0; ··· 22 41 filename__read_ull(path, &slots); 23 42 } 24 43 25 - return slots ? (double)slots : NAN; 44 + return slots; 26 45 }
-4
tools/perf/arch/csky/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif
+6 -1
tools/perf/arch/csky/annotate/instructions.c
··· 43 43 arch->initialized = true; 44 44 arch->objdump.comment_char = '/'; 45 45 arch->associate_instruction_ops = csky__associate_ins_ops; 46 - 46 + arch->e_machine = EM_CSKY; 47 + #if defined(__CSKYABIV2__) 48 + arch->e_flags = EF_CSKY_ABIV2; 49 + #else 50 + arch->e_flags = EF_CSKY_ABIV1; 51 + #endif 47 52 return 0; 48 53 }
-1
tools/perf/arch/csky/util/Build
··· 1 1 perf-util-y += perf_regs.o 2 2 3 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 4 3 perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
-49
tools/perf/arch/csky/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - // Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. 3 - // Mapping of DWARF debug register numbers into register names. 4 - 5 - #include <stddef.h> 6 - #include <dwarf-regs.h> 7 - 8 - #if defined(__CSKYABIV2__) 9 - #define CSKY_MAX_REGS 73 10 - const char *csky_dwarf_regs_table[CSKY_MAX_REGS] = { 11 - /* r0 ~ r8 */ 12 - "%a0", "%a1", "%a2", "%a3", "%regs0", "%regs1", "%regs2", "%regs3", 13 - /* r9 ~ r15 */ 14 - "%regs4", "%regs5", "%regs6", "%regs7", "%regs8", "%regs9", "%sp", 15 - "%lr", 16 - /* r16 ~ r23 */ 17 - "%exregs0", "%exregs1", "%exregs2", "%exregs3", "%exregs4", 18 - "%exregs5", "%exregs6", "%exregs7", 19 - /* r24 ~ r31 */ 20 - "%exregs8", "%exregs9", "%exregs10", "%exregs11", "%exregs12", 21 - "%exregs13", "%exregs14", "%tls", 22 - "%pc", NULL, NULL, NULL, "%hi", "%lo", NULL, NULL, 23 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 24 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 25 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 26 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 27 - "%epc", 28 - }; 29 - #else 30 - #define CSKY_MAX_REGS 57 31 - const char *csky_dwarf_regs_table[CSKY_MAX_REGS] = { 32 - /* r0 ~ r8 */ 33 - "%sp", "%regs9", "%a0", "%a1", "%a2", "%a3", "%regs0", "%regs1", 34 - /* r9 ~ r15 */ 35 - "%regs2", "%regs3", "%regs4", "%regs5", "%regs6", "%regs7", "%regs8", 36 - "%lr", 37 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 38 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 39 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 40 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 41 - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 42 - "%epc", 43 - }; 44 - #endif 45 - 46 - const char *get_arch_regstr(unsigned int n) 47 - { 48 - return (n < CSKY_MAX_REGS) ? csky_dwarf_regs_table[n] : NULL; 49 - }
-4
tools/perf/arch/loongarch/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif 5 - PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 6 2 PERF_HAVE_JITDUMP := 1 7 3 HAVE_KVM_STAT_SUPPORT := 1 8 4
+2
tools/perf/arch/loongarch/annotate/instructions.c
··· 131 131 arch->associate_instruction_ops = loongarch__associate_ins_ops; 132 132 arch->initialized = true; 133 133 arch->objdump.comment_char = '#'; 134 + arch->e_machine = EM_LOONGARCH; 135 + arch->e_flags = 0; 134 136 } 135 137 136 138 return 0;
-1
tools/perf/arch/loongarch/util/Build
··· 1 1 perf-util-y += header.o 2 2 perf-util-y += perf_regs.o 3 3 4 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 5 4 perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o 6 5 perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 7 6 perf-util-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o
-44
tools/perf/arch/loongarch/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * dwarf-regs.c : Mapping of DWARF debug register numbers into register names. 4 - * 5 - * Copyright (C) 2020-2023 Loongson Technology Corporation Limited 6 - */ 7 - 8 - #include <stdio.h> 9 - #include <errno.h> /* for EINVAL */ 10 - #include <string.h> /* for strcmp */ 11 - #include <dwarf-regs.h> 12 - 13 - struct pt_regs_dwarfnum { 14 - const char *name; 15 - unsigned int dwarfnum; 16 - }; 17 - 18 - static struct pt_regs_dwarfnum loongarch_gpr_table[] = { 19 - {"%r0", 0}, {"%r1", 1}, {"%r2", 2}, {"%r3", 3}, 20 - {"%r4", 4}, {"%r5", 5}, {"%r6", 6}, {"%r7", 7}, 21 - {"%r8", 8}, {"%r9", 9}, {"%r10", 10}, {"%r11", 11}, 22 - {"%r12", 12}, {"%r13", 13}, {"%r14", 14}, {"%r15", 15}, 23 - {"%r16", 16}, {"%r17", 17}, {"%r18", 18}, {"%r19", 19}, 24 - {"%r20", 20}, {"%r21", 21}, {"%r22", 22}, {"%r23", 23}, 25 - {"%r24", 24}, {"%r25", 25}, {"%r26", 26}, {"%r27", 27}, 26 - {"%r28", 28}, {"%r29", 29}, {"%r30", 30}, {"%r31", 31}, 27 - {NULL, 0} 28 - }; 29 - 30 - const char *get_arch_regstr(unsigned int n) 31 - { 32 - n %= 32; 33 - return loongarch_gpr_table[n].name; 34 - } 35 - 36 - int regs_query_register_offset(const char *name) 37 - { 38 - const struct pt_regs_dwarfnum *roff; 39 - 40 - for (roff = loongarch_gpr_table; roff->name != NULL; roff++) 41 - if (!strcmp(roff->name, name)) 42 - return roff->dwarfnum; 43 - return -EINVAL; 44 - }
+2 -2
tools/perf/arch/loongarch/util/header.c
··· 70 70 return cpuid; 71 71 } 72 72 73 - int get_cpuid(char *buffer, size_t sz) 73 + int get_cpuid(char *buffer, size_t sz, struct perf_cpu cpu __maybe_unused) 74 74 { 75 75 int ret = 0; 76 76 char *cpuid = _get_cpuid(); ··· 90 90 return ret; 91 91 } 92 92 93 - char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused) 93 + char *get_cpuid_str(struct perf_cpu cpu __maybe_unused) 94 94 { 95 95 return _get_cpuid(); 96 96 }
-4
tools/perf/arch/mips/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif 5 - 6 2 # Syscall table generation for perf 7 3 out := $(OUTPUT)arch/mips/include/generated/asm 8 4 header := $(out)/syscalls_n64.c
+2
tools/perf/arch/mips/annotate/instructions.c
··· 40 40 arch->associate_instruction_ops = mips__associate_ins_ops; 41 41 arch->initialized = true; 42 42 arch->objdump.comment_char = '#'; 43 + arch->e_machine = EM_MIPS; 44 + arch->e_flags = 0; 43 45 } 44 46 45 47 return 0;
-1
tools/perf/arch/mips/util/Build
··· 1 1 perf-util-y += perf_regs.o 2 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 3 2 perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
-38
tools/perf/arch/mips/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * dwarf-regs.c : Mapping of DWARF debug register numbers into register names. 4 - * 5 - * Copyright (C) 2013 Cavium, Inc. 6 - * 7 - * This program is free software; you can redistribute it and/or modify 8 - * it under the terms of the GNU General Public License as published by 9 - * the Free Software Foundation; either version 2 of the License, or 10 - * (at your option) any later version. 11 - * 12 - * This program is distributed in the hope that it will be useful, 13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 - * GNU General Public License for more details. 16 - * 17 - */ 18 - 19 - #include <stdio.h> 20 - #include <dwarf-regs.h> 21 - 22 - static const char *mips_gpr_names[32] = { 23 - "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", 24 - "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", 25 - "$20", "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", 26 - "$30", "$31" 27 - }; 28 - 29 - const char *get_arch_regstr(unsigned int n) 30 - { 31 - if (n < 32) 32 - return mips_gpr_names[n]; 33 - if (n == 64) 34 - return "hi"; 35 - if (n == 65) 36 - return "lo"; 37 - return NULL; 38 - }
-5
tools/perf/arch/powerpc/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif 5 - 6 2 HAVE_KVM_STAT_SUPPORT := 1 7 - PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 8 3 PERF_HAVE_JITDUMP := 1 9 4 10 5 #
+4 -2
tools/perf/arch/powerpc/annotate/instructions.c
··· 255 255 * is moved to r31. update_insn_state_powerpc tracks these state 256 256 * changes 257 257 */ 258 - #ifdef HAVE_DWARF_SUPPORT 258 + #ifdef HAVE_LIBDW_SUPPORT 259 259 static void update_insn_state_powerpc(struct type_state *state, 260 260 struct data_loc_info *dloc, Dwarf_Die * cu_die __maybe_unused, 261 261 struct disasm_line *dl) ··· 300 300 insn_offset, src->reg1, dst->reg1); 301 301 pr_debug_type_name(&tsr->type, tsr->kind); 302 302 } 303 - #endif /* HAVE_DWARF_SUPPORT */ 303 + #endif /* HAVE_LIBDW_SUPPORT */ 304 304 305 305 static int powerpc__annotate_init(struct arch *arch, char *cpuid __maybe_unused) 306 306 { ··· 309 309 arch->associate_instruction_ops = powerpc__associate_instruction_ops; 310 310 arch->objdump.comment_char = '#'; 311 311 annotate_opts.show_asm_raw = true; 312 + arch->e_machine = EM_PPC; 313 + arch->e_flags = 0; 312 314 } 313 315 314 316 return 0;
+1 -2
tools/perf/arch/powerpc/util/Build
··· 7 7 perf-util-y += evsel.o 8 8 perf-util-y += event.o 9 9 10 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 11 - perf-util-$(CONFIG_DWARF) += skip-callchain-idx.o 10 + perf-util-$(CONFIG_LIBDW) += skip-callchain-idx.o 12 11 13 12 perf-util-$(CONFIG_LIBUNWIND) += unwind-libunwind.o 14 13 perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
-153
tools/perf/arch/powerpc/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * Mapping of DWARF debug register numbers into register names. 4 - * 5 - * Copyright (C) 2010 Ian Munsie, IBM Corporation. 6 - */ 7 - 8 - #include <stddef.h> 9 - #include <errno.h> 10 - #include <string.h> 11 - #include <dwarf-regs.h> 12 - #include <linux/ptrace.h> 13 - #include <linux/kernel.h> 14 - #include <linux/stringify.h> 15 - 16 - struct pt_regs_dwarfnum { 17 - const char *name; 18 - unsigned int dwarfnum; 19 - unsigned int ptregs_offset; 20 - }; 21 - 22 - #define REG_DWARFNUM_NAME(r, num) \ 23 - {.name = __stringify(%)__stringify(r), .dwarfnum = num, \ 24 - .ptregs_offset = offsetof(struct pt_regs, r)} 25 - #define GPR_DWARFNUM_NAME(num) \ 26 - {.name = __stringify(%gpr##num), .dwarfnum = num, \ 27 - .ptregs_offset = offsetof(struct pt_regs, gpr[num])} 28 - #define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0, .ptregs_offset = 0} 29 - 30 - /* 31 - * Reference: 32 - * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html 33 - */ 34 - static const struct pt_regs_dwarfnum regdwarfnum_table[] = { 35 - GPR_DWARFNUM_NAME(0), 36 - GPR_DWARFNUM_NAME(1), 37 - GPR_DWARFNUM_NAME(2), 38 - GPR_DWARFNUM_NAME(3), 39 - GPR_DWARFNUM_NAME(4), 40 - GPR_DWARFNUM_NAME(5), 41 - GPR_DWARFNUM_NAME(6), 42 - GPR_DWARFNUM_NAME(7), 43 - GPR_DWARFNUM_NAME(8), 44 - GPR_DWARFNUM_NAME(9), 45 - GPR_DWARFNUM_NAME(10), 46 - GPR_DWARFNUM_NAME(11), 47 - GPR_DWARFNUM_NAME(12), 48 - GPR_DWARFNUM_NAME(13), 49 - GPR_DWARFNUM_NAME(14), 50 - GPR_DWARFNUM_NAME(15), 51 - GPR_DWARFNUM_NAME(16), 52 - GPR_DWARFNUM_NAME(17), 53 - GPR_DWARFNUM_NAME(18), 54 - GPR_DWARFNUM_NAME(19), 55 - GPR_DWARFNUM_NAME(20), 56 - GPR_DWARFNUM_NAME(21), 57 - GPR_DWARFNUM_NAME(22), 58 - GPR_DWARFNUM_NAME(23), 59 - GPR_DWARFNUM_NAME(24), 60 - GPR_DWARFNUM_NAME(25), 61 - GPR_DWARFNUM_NAME(26), 62 - GPR_DWARFNUM_NAME(27), 63 - GPR_DWARFNUM_NAME(28), 64 - GPR_DWARFNUM_NAME(29), 65 - GPR_DWARFNUM_NAME(30), 66 - GPR_DWARFNUM_NAME(31), 67 - REG_DWARFNUM_NAME(msr, 66), 68 - REG_DWARFNUM_NAME(ctr, 109), 69 - REG_DWARFNUM_NAME(link, 108), 70 - REG_DWARFNUM_NAME(xer, 101), 71 - REG_DWARFNUM_NAME(dar, 119), 72 - REG_DWARFNUM_NAME(dsisr, 118), 73 - REG_DWARFNUM_END, 74 - }; 75 - 76 - /** 77 - * get_arch_regstr() - lookup register name from it's DWARF register number 78 - * @n: the DWARF register number 79 - * 80 - * get_arch_regstr() returns the name of the register in struct 81 - * regdwarfnum_table from it's DWARF register number. If the register is not 82 - * found in the table, this returns NULL; 83 - */ 84 - const char *get_arch_regstr(unsigned int n) 85 - { 86 - const struct pt_regs_dwarfnum *roff; 87 - for (roff = regdwarfnum_table; roff->name != NULL; roff++) 88 - if (roff->dwarfnum == n) 89 - return roff->name; 90 - return NULL; 91 - } 92 - 93 - int regs_query_register_offset(const char *name) 94 - { 95 - const struct pt_regs_dwarfnum *roff; 96 - for (roff = regdwarfnum_table; roff->name != NULL; roff++) 97 - if (!strcmp(roff->name, name)) 98 - return roff->ptregs_offset; 99 - return -EINVAL; 100 - } 101 - 102 - #define PPC_OP(op) (((op) >> 26) & 0x3F) 103 - #define PPC_RA(a) (((a) >> 16) & 0x1f) 104 - #define PPC_RT(t) (((t) >> 21) & 0x1f) 105 - #define PPC_RB(b) (((b) >> 11) & 0x1f) 106 - #define PPC_D(D) ((D) & 0xfffe) 107 - #define PPC_DS(DS) ((DS) & 0xfffc) 108 - #define OP_LD 58 109 - #define OP_STD 62 110 - 111 - static int get_source_reg(u32 raw_insn) 112 - { 113 - return PPC_RA(raw_insn); 114 - } 115 - 116 - static int get_target_reg(u32 raw_insn) 117 - { 118 - return PPC_RT(raw_insn); 119 - } 120 - 121 - static int get_offset_opcode(u32 raw_insn) 122 - { 123 - int opcode = PPC_OP(raw_insn); 124 - 125 - /* DS- form */ 126 - if ((opcode == OP_LD) || (opcode == OP_STD)) 127 - return PPC_DS(raw_insn); 128 - else 129 - return PPC_D(raw_insn); 130 - } 131 - 132 - /* 133 - * Fills the required fields for op_loc depending on if it 134 - * is a source or target. 135 - * D form: ins RT,D(RA) -> src_reg1 = RA, offset = D, dst_reg1 = RT 136 - * DS form: ins RT,DS(RA) -> src_reg1 = RA, offset = DS, dst_reg1 = RT 137 - * X form: ins RT,RA,RB -> src_reg1 = RA, src_reg2 = RB, dst_reg1 = RT 138 - */ 139 - void get_powerpc_regs(u32 raw_insn, int is_source, 140 - struct annotated_op_loc *op_loc) 141 - { 142 - if (is_source) 143 - op_loc->reg1 = get_source_reg(raw_insn); 144 - else 145 - op_loc->reg1 = get_target_reg(raw_insn); 146 - 147 - if (op_loc->multi_regs) 148 - op_loc->reg2 = PPC_RB(raw_insn); 149 - 150 - /* TODO: Implement offset handling for X Form */ 151 - if ((op_loc->mem_ref) && (PPC_OP(raw_insn) != 31)) 152 - op_loc->offset = get_offset_opcode(raw_insn); 153 - }
+33 -3
tools/perf/arch/powerpc/util/header.c
··· 10 10 #include "utils_header.h" 11 11 #include "metricgroup.h" 12 12 #include <api/fs/fs.h> 13 + #include <sys/auxv.h> 14 + 15 + static bool is_compat_mode(void) 16 + { 17 + u64 base_platform = getauxval(AT_BASE_PLATFORM); 18 + u64 platform = getauxval(AT_PLATFORM); 19 + 20 + if (!strcmp((char *)platform, (char *)base_platform)) 21 + return false; 22 + 23 + return true; 24 + } 13 25 14 26 int 15 - get_cpuid(char *buffer, size_t sz) 27 + get_cpuid(char *buffer, size_t sz, struct perf_cpu cpu __maybe_unused) 16 28 { 17 29 unsigned long pvr; 18 30 int nb; ··· 42 30 } 43 31 44 32 char * 45 - get_cpuid_str(struct perf_pmu *pmu __maybe_unused) 33 + get_cpuid_str(struct perf_cpu cpu __maybe_unused) 46 34 { 47 35 char *bufp; 36 + unsigned long pvr; 48 37 49 - if (asprintf(&bufp, "0x%.8lx", mfspr(SPRN_PVR)) < 0) 38 + /* 39 + * IBM Power System supports compatible mode. That is 40 + * Nth generation platform can support previous generation 41 + * OS in a mode called compatibile mode. For ex. LPAR can be 42 + * booted in a Power9 mode when the system is a Power10. 43 + * 44 + * In the compatible mode, care must be taken when generating 45 + * PVR value. When read, PVR will be of the AT_BASE_PLATFORM 46 + * To support generic events, return 0x00ffffff as pvr when 47 + * booted in compat mode. Based on this pvr value, json will 48 + * pick events from pmu-events/arch/powerpc/compat 49 + */ 50 + if (!is_compat_mode()) 51 + pvr = mfspr(SPRN_PVR); 52 + else 53 + pvr = 0x00ffffff; 54 + 55 + if (asprintf(&bufp, "0x%.8lx", pvr) < 0) 50 56 bufp = NULL; 51 57 52 58 return bufp;
+23 -4
tools/perf/arch/riscv/Makefile
··· 1 - ifndef NO_DWARF 2 - PERF_HAVE_DWARF_REGS := 1 3 - endif 4 - PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 1 + # SPDX-License-Identifier: GPL-2.0 5 2 PERF_HAVE_JITDUMP := 1 6 3 HAVE_KVM_STAT_SUPPORT := 1 4 + 5 + # 6 + # Syscall table generation for perf 7 + # 8 + 9 + out := $(OUTPUT)arch/riscv/include/generated/asm 10 + header := $(out)/syscalls.c 11 + incpath := $(srctree)/tools 12 + sysdef := $(srctree)/tools/arch/riscv/include/uapi/asm/unistd.h 13 + sysprf := $(srctree)/tools/perf/arch/riscv/entry/syscalls/ 14 + systbl := $(sysprf)/mksyscalltbl 15 + 16 + # Create output directory if not already present 17 + $(shell [ -d '$(out)' ] || mkdir -p '$(out)') 18 + 19 + $(header): $(sysdef) $(systbl) 20 + $(Q)$(SHELL) '$(systbl)' '$(CC)' '$(HOSTCC)' $(incpath) $(sysdef) > $@ 21 + 22 + clean:: 23 + $(call QUIET_CLEAN, riscv) $(RM) $(header) 24 + 25 + archheaders: $(header)
+47
tools/perf/arch/riscv/entry/syscalls/mksyscalltbl
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Generate system call table for perf. Derived from 5 + # powerpc script. 6 + # 7 + # Copyright IBM Corp. 2017 8 + # Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> 9 + # Changed by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> 10 + # Changed by: Kim Phillips <kim.phillips@arm.com> 11 + # Changed by: Björn Töpel <bjorn@rivosinc.com> 12 + 13 + gcc=$1 14 + hostcc=$2 15 + incpath=$3 16 + input=$4 17 + 18 + if ! test -r $input; then 19 + echo "Could not read input file" >&2 20 + exit 1 21 + fi 22 + 23 + create_sc_table() 24 + { 25 + local sc nr max_nr 26 + 27 + while read sc nr; do 28 + printf "%s\n" " [$nr] = \"$sc\"," 29 + max_nr=$nr 30 + done 31 + 32 + echo "#define SYSCALLTBL_RISCV_MAX_ID $max_nr" 33 + } 34 + 35 + create_table() 36 + { 37 + echo "#include \"$input\"" 38 + echo "static const char *const syscalltbl_riscv[] = {" 39 + create_sc_table 40 + echo "};" 41 + } 42 + 43 + $gcc -E -dM -x c -I $incpath/include/uapi $input \ 44 + |awk '$2 ~ "__NR" && $3 !~ "__NR3264_" { 45 + sub("^#define __NR(3264)?_", ""); 46 + print | "sort -k2 -n"}' \ 47 + |create_table
+42
tools/perf/arch/riscv/include/dwarf-regs-table.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifdef DEFINE_DWARF_REGSTR_TABLE 3 + /* This is included in perf/util/dwarf-regs.c */ 4 + 5 + #define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg 6 + 7 + static const char * const riscv_regstr_tbl[] = { 8 + REG_DWARFNUM_NAME("%zero", 0), 9 + REG_DWARFNUM_NAME("%ra", 1), 10 + REG_DWARFNUM_NAME("%sp", 2), 11 + REG_DWARFNUM_NAME("%gp", 3), 12 + REG_DWARFNUM_NAME("%tp", 4), 13 + REG_DWARFNUM_NAME("%t0", 5), 14 + REG_DWARFNUM_NAME("%t1", 6), 15 + REG_DWARFNUM_NAME("%t2", 7), 16 + REG_DWARFNUM_NAME("%s0", 8), 17 + REG_DWARFNUM_NAME("%s1", 9), 18 + REG_DWARFNUM_NAME("%a0", 10), 19 + REG_DWARFNUM_NAME("%a1", 11), 20 + REG_DWARFNUM_NAME("%a2", 12), 21 + REG_DWARFNUM_NAME("%a3", 13), 22 + REG_DWARFNUM_NAME("%a4", 14), 23 + REG_DWARFNUM_NAME("%a5", 15), 24 + REG_DWARFNUM_NAME("%a6", 16), 25 + REG_DWARFNUM_NAME("%a7", 17), 26 + REG_DWARFNUM_NAME("%s2", 18), 27 + REG_DWARFNUM_NAME("%s3", 19), 28 + REG_DWARFNUM_NAME("%s4", 20), 29 + REG_DWARFNUM_NAME("%s5", 21), 30 + REG_DWARFNUM_NAME("%s6", 22), 31 + REG_DWARFNUM_NAME("%s7", 23), 32 + REG_DWARFNUM_NAME("%s8", 24), 33 + REG_DWARFNUM_NAME("%s9", 25), 34 + REG_DWARFNUM_NAME("%s10", 26), 35 + REG_DWARFNUM_NAME("%s11", 27), 36 + REG_DWARFNUM_NAME("%t3", 28), 37 + REG_DWARFNUM_NAME("%t4", 29), 38 + REG_DWARFNUM_NAME("%t5", 30), 39 + REG_DWARFNUM_NAME("%t6", 31), 40 + }; 41 + 42 + #endif
-1
tools/perf/arch/riscv/util/Build
··· 2 2 perf-util-y += header.o 3 3 4 4 perf-util-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o 5 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 6 5 perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
-72
tools/perf/arch/riscv/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. 4 - * Mapping of DWARF debug register numbers into register names. 5 - */ 6 - 7 - #include <stddef.h> 8 - #include <errno.h> /* for EINVAL */ 9 - #include <string.h> /* for strcmp */ 10 - #include <dwarf-regs.h> 11 - 12 - struct pt_regs_dwarfnum { 13 - const char *name; 14 - unsigned int dwarfnum; 15 - }; 16 - 17 - #define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} 18 - #define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} 19 - 20 - struct pt_regs_dwarfnum riscv_dwarf_regs_table[] = { 21 - REG_DWARFNUM_NAME("%zero", 0), 22 - REG_DWARFNUM_NAME("%ra", 1), 23 - REG_DWARFNUM_NAME("%sp", 2), 24 - REG_DWARFNUM_NAME("%gp", 3), 25 - REG_DWARFNUM_NAME("%tp", 4), 26 - REG_DWARFNUM_NAME("%t0", 5), 27 - REG_DWARFNUM_NAME("%t1", 6), 28 - REG_DWARFNUM_NAME("%t2", 7), 29 - REG_DWARFNUM_NAME("%s0", 8), 30 - REG_DWARFNUM_NAME("%s1", 9), 31 - REG_DWARFNUM_NAME("%a0", 10), 32 - REG_DWARFNUM_NAME("%a1", 11), 33 - REG_DWARFNUM_NAME("%a2", 12), 34 - REG_DWARFNUM_NAME("%a3", 13), 35 - REG_DWARFNUM_NAME("%a4", 14), 36 - REG_DWARFNUM_NAME("%a5", 15), 37 - REG_DWARFNUM_NAME("%a6", 16), 38 - REG_DWARFNUM_NAME("%a7", 17), 39 - REG_DWARFNUM_NAME("%s2", 18), 40 - REG_DWARFNUM_NAME("%s3", 19), 41 - REG_DWARFNUM_NAME("%s4", 20), 42 - REG_DWARFNUM_NAME("%s5", 21), 43 - REG_DWARFNUM_NAME("%s6", 22), 44 - REG_DWARFNUM_NAME("%s7", 23), 45 - REG_DWARFNUM_NAME("%s8", 24), 46 - REG_DWARFNUM_NAME("%s9", 25), 47 - REG_DWARFNUM_NAME("%s10", 26), 48 - REG_DWARFNUM_NAME("%s11", 27), 49 - REG_DWARFNUM_NAME("%t3", 28), 50 - REG_DWARFNUM_NAME("%t4", 29), 51 - REG_DWARFNUM_NAME("%t5", 30), 52 - REG_DWARFNUM_NAME("%t6", 31), 53 - REG_DWARFNUM_END, 54 - }; 55 - 56 - #define RISCV_MAX_REGS ((sizeof(riscv_dwarf_regs_table) / \ 57 - sizeof(riscv_dwarf_regs_table[0])) - 1) 58 - 59 - const char *get_arch_regstr(unsigned int n) 60 - { 61 - return (n < RISCV_MAX_REGS) ? riscv_dwarf_regs_table[n].name : NULL; 62 - } 63 - 64 - int regs_query_register_offset(const char *name) 65 - { 66 - const struct pt_regs_dwarfnum *roff; 67 - 68 - for (roff = riscv_dwarf_regs_table; roff->name; roff++) 69 - if (!strcmp(roff->name, name)) 70 - return roff->dwarfnum; 71 - return -EINVAL; 72 - }
+2 -2
tools/perf/arch/riscv/util/header.c
··· 81 81 return cpuid; 82 82 } 83 83 84 - int get_cpuid(char *buffer, size_t sz) 84 + int get_cpuid(char *buffer, size_t sz, struct perf_cpu cpu __maybe_unused) 85 85 { 86 86 char *cpuid = _get_cpuid(); 87 87 int ret = 0; ··· 98 98 } 99 99 100 100 char * 101 - get_cpuid_str(struct perf_pmu *pmu __maybe_unused) 101 + get_cpuid_str(struct perf_cpu cpu __maybe_unused) 102 102 { 103 103 return _get_cpuid(); 104 104 }
+2
tools/perf/arch/riscv64/annotate/instructions.c
··· 28 28 arch->associate_instruction_ops = riscv64__associate_ins_ops; 29 29 arch->initialized = true; 30 30 arch->objdump.comment_char = '#'; 31 + arch->e_machine = EM_RISCV; 32 + arch->e_flags = 0; 31 33 } 32 34 33 35 return 0;
-4
tools/perf/arch/s390/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif 5 2 HAVE_KVM_STAT_SUPPORT := 1 6 - PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 7 3 PERF_HAVE_JITDUMP := 1 8 4 9 5 #
+2
tools/perf/arch/s390/annotate/instructions.c
··· 166 166 if (s390__cpuid_parse(arch, cpuid)) 167 167 err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING; 168 168 } 169 + arch->e_machine = EM_S390; 170 + arch->e_flags = 0; 169 171 } 170 172 171 173 return err;
-1
tools/perf/arch/s390/util/Build
··· 2 2 perf-util-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o 3 3 perf-util-y += perf_regs.o 4 4 5 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 6 5 perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 7 6 8 7 perf-util-y += machine.o
-43
tools/perf/arch/s390/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Mapping of DWARF debug register numbers into register names. 4 - * 5 - * Copyright IBM Corp. 2010, 2017 6 - * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> 7 - * 8 - */ 9 - 10 - #include <errno.h> 11 - #include <stddef.h> 12 - #include <stdlib.h> 13 - #include <linux/kernel.h> 14 - #include <asm/ptrace.h> 15 - #include <string.h> 16 - #include <dwarf-regs.h> 17 - #include "dwarf-regs-table.h" 18 - 19 - const char *get_arch_regstr(unsigned int n) 20 - { 21 - return (n >= ARRAY_SIZE(s390_dwarf_regs)) ? NULL : s390_dwarf_regs[n]; 22 - } 23 - 24 - /* 25 - * Convert the register name into an offset to struct pt_regs (kernel). 26 - * This is required by the BPF prologue generator. The BPF 27 - * program is called in the BPF overflow handler in the perf 28 - * core. 29 - */ 30 - int regs_query_register_offset(const char *name) 31 - { 32 - unsigned long gpr; 33 - 34 - if (!name || strncmp(name, "%r", 2)) 35 - return -EINVAL; 36 - 37 - errno = 0; 38 - gpr = strtoul(name + 2, NULL, 10); 39 - if (errno || gpr >= 16) 40 - return -EINVAL; 41 - 42 - return offsetof(user_pt_regs, gprs) + 8 * gpr; 43 - }
+3 -3
tools/perf/arch/s390/util/header.c
··· 27 27 #define SYSINFO "/proc/sysinfo" 28 28 #define SRVLVL "/proc/service_levels" 29 29 30 - int get_cpuid(char *buffer, size_t sz) 30 + int get_cpuid(char *buffer, size_t sz, struct perf_cpu cpu __maybe_unused) 31 31 { 32 32 char *cp, *line = NULL, *line2; 33 33 char type[8], model[33], version[8], manufacturer[32], authorization[8]; ··· 137 137 return (nbytes >= sz) ? ENOBUFS : 0; 138 138 } 139 139 140 - char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused) 140 + char *get_cpuid_str(struct perf_cpu cpu) 141 141 { 142 142 char *buf = malloc(128); 143 143 144 - if (buf && get_cpuid(buf, 128)) 144 + if (buf && get_cpuid(buf, 128, cpu)) 145 145 zfree(&buf); 146 146 return buf; 147 147 }
-1
tools/perf/arch/sh/Build
··· 1 - perf-util-y += util/
-4
tools/perf/arch/sh/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif
-1
tools/perf/arch/sh/util/Build
··· 1 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o
-41
tools/perf/arch/sh/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * Mapping of DWARF debug register numbers into register names. 4 - * 5 - * Copyright (C) 2010 Matt Fleming <matt@console-pimps.org> 6 - */ 7 - 8 - #include <stddef.h> 9 - #include <dwarf-regs.h> 10 - 11 - /* 12 - * Generic dwarf analysis helpers 13 - */ 14 - 15 - #define SH_MAX_REGS 18 16 - const char *sh_regs_table[SH_MAX_REGS] = { 17 - "r0", 18 - "r1", 19 - "r2", 20 - "r3", 21 - "r4", 22 - "r5", 23 - "r6", 24 - "r7", 25 - "r8", 26 - "r9", 27 - "r10", 28 - "r11", 29 - "r12", 30 - "r13", 31 - "r14", 32 - "r15", 33 - "pc", 34 - "pr", 35 - }; 36 - 37 - /* Return architecture dependent register string (for kprobe-tracer) */ 38 - const char *get_arch_regstr(unsigned int n) 39 - { 40 - return (n < SH_MAX_REGS) ? sh_regs_table[n] : NULL; 41 - }
-1
tools/perf/arch/sparc/Build
··· 1 - perf-util-y += util/
-4
tools/perf/arch/sparc/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif 5 - 6 2 PERF_HAVE_JITDUMP := 1
+2
tools/perf/arch/sparc/annotate/instructions.c
··· 163 163 arch->initialized = true; 164 164 arch->associate_instruction_ops = sparc__associate_instruction_ops; 165 165 arch->objdump.comment_char = '#'; 166 + arch->e_machine = EM_SPARC; 167 + arch->e_flags = 0; 166 168 } 167 169 168 170 return 0;
-1
tools/perf/arch/sparc/util/Build
··· 1 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o
-39
tools/perf/arch/sparc/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * Mapping of DWARF debug register numbers into register names. 4 - * 5 - * Copyright (C) 2010 David S. Miller <davem@davemloft.net> 6 - */ 7 - 8 - #include <stddef.h> 9 - #include <dwarf-regs.h> 10 - 11 - #define SPARC_MAX_REGS 96 12 - 13 - const char *sparc_regs_table[SPARC_MAX_REGS] = { 14 - "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7", 15 - "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7", 16 - "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", 17 - "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7", 18 - "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", 19 - "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15", 20 - "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23", 21 - "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31", 22 - "%f32", "%f33", "%f34", "%f35", "%f36", "%f37", "%f38", "%f39", 23 - "%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47", 24 - "%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55", 25 - "%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63", 26 - }; 27 - 28 - /** 29 - * get_arch_regstr() - lookup register name from it's DWARF register number 30 - * @n: the DWARF register number 31 - * 32 - * get_arch_regstr() returns the name of the register in struct 33 - * regdwarfnum_table from it's DWARF register number. If the register is not 34 - * found in the table, this returns NULL; 35 - */ 36 - const char *get_arch_regstr(unsigned int n) 37 - { 38 - return (n < SPARC_MAX_REGS) ? sparc_regs_table[n] : NULL; 39 - }
-4
tools/perf/arch/x86/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif 5 2 HAVE_KVM_STAT_SUPPORT := 1 6 - PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 7 3 PERF_HAVE_JITDUMP := 1 8 4 9 5 ###
+3 -2
tools/perf/arch/x86/annotate/instructions.c
··· 202 202 if (x86__cpuid_parse(arch, cpuid)) 203 203 err = SYMBOL_ANNOTATE_ERRNO__ARCH_INIT_CPUID_PARSING; 204 204 } 205 - 205 + arch->e_machine = EM_X86_64; 206 + arch->e_flags = 0; 206 207 arch->initialized = true; 207 208 return err; 208 209 } 209 210 210 - #ifdef HAVE_DWARF_SUPPORT 211 + #ifdef HAVE_LIBDW_SUPPORT 211 212 static void update_insn_state_x86(struct type_state *state, 212 213 struct data_loc_info *dloc, Dwarf_Die *cu_die, 213 214 struct disasm_line *dl)
-128
tools/perf/arch/x86/tests/intel-cqm.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include "tests/tests.h" 3 - #include "cloexec.h" 4 - #include "debug.h" 5 - #include "evlist.h" 6 - #include "evsel.h" 7 - #include "arch-tests.h" 8 - #include <internal/lib.h> // page_size 9 - 10 - #include <signal.h> 11 - #include <sys/mman.h> 12 - #include <sys/wait.h> 13 - #include <errno.h> 14 - #include <string.h> 15 - 16 - static pid_t spawn(void) 17 - { 18 - pid_t pid; 19 - 20 - pid = fork(); 21 - if (pid) 22 - return pid; 23 - 24 - while(1) 25 - sleep(5); 26 - return 0; 27 - } 28 - 29 - /* 30 - * Create an event group that contains both a sampled hardware 31 - * (cpu-cycles) and software (intel_cqm/llc_occupancy/) event. We then 32 - * wait for the hardware perf counter to overflow and generate a PMI, 33 - * which triggers an event read for both of the events in the group. 34 - * 35 - * Since reading Intel CQM event counters requires sending SMP IPIs, the 36 - * CQM pmu needs to handle the above situation gracefully, and return 37 - * the last read counter value to avoid triggering a WARN_ON_ONCE() in 38 - * smp_call_function_many() caused by sending IPIs from NMI context. 39 - */ 40 - int test__intel_cqm_count_nmi_context(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 41 - { 42 - struct evlist *evlist = NULL; 43 - struct evsel *evsel = NULL; 44 - struct perf_event_attr pe; 45 - int i, fd[2], flag, ret; 46 - size_t mmap_len; 47 - void *event; 48 - pid_t pid; 49 - int err = TEST_FAIL; 50 - 51 - flag = perf_event_open_cloexec_flag(); 52 - 53 - evlist = evlist__new(); 54 - if (!evlist) { 55 - pr_debug("evlist__new failed\n"); 56 - return TEST_FAIL; 57 - } 58 - 59 - ret = parse_event(evlist, "intel_cqm/llc_occupancy/"); 60 - if (ret) { 61 - pr_debug("parse_events failed, is \"intel_cqm/llc_occupancy/\" available?\n"); 62 - err = TEST_SKIP; 63 - goto out; 64 - } 65 - 66 - evsel = evlist__first(evlist); 67 - if (!evsel) { 68 - pr_debug("evlist__first failed\n"); 69 - goto out; 70 - } 71 - 72 - memset(&pe, 0, sizeof(pe)); 73 - pe.size = sizeof(pe); 74 - 75 - pe.type = PERF_TYPE_HARDWARE; 76 - pe.config = PERF_COUNT_HW_CPU_CYCLES; 77 - pe.read_format = PERF_FORMAT_GROUP; 78 - 79 - pe.sample_period = 128; 80 - pe.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_READ; 81 - 82 - pid = spawn(); 83 - 84 - fd[0] = sys_perf_event_open(&pe, pid, -1, -1, flag); 85 - if (fd[0] < 0) { 86 - pr_debug("failed to open event\n"); 87 - goto out; 88 - } 89 - 90 - memset(&pe, 0, sizeof(pe)); 91 - pe.size = sizeof(pe); 92 - 93 - pe.type = evsel->attr.type; 94 - pe.config = evsel->attr.config; 95 - 96 - fd[1] = sys_perf_event_open(&pe, pid, -1, fd[0], flag); 97 - if (fd[1] < 0) { 98 - pr_debug("failed to open event\n"); 99 - goto out; 100 - } 101 - 102 - /* 103 - * Pick a power-of-two number of pages + 1 for the meta-data 104 - * page (struct perf_event_mmap_page). See tools/perf/design.txt. 105 - */ 106 - mmap_len = page_size * 65; 107 - 108 - event = mmap(NULL, mmap_len, PROT_READ, MAP_SHARED, fd[0], 0); 109 - if (event == (void *)(-1)) { 110 - pr_debug("failed to mmap %d\n", errno); 111 - goto out; 112 - } 113 - 114 - sleep(1); 115 - 116 - err = TEST_OK; 117 - 118 - munmap(event, mmap_len); 119 - 120 - for (i = 0; i < 2; i++) 121 - close(fd[i]); 122 - 123 - kill(pid, SIGKILL); 124 - wait(NULL); 125 - out: 126 - evlist__delete(evlist); 127 - return err; 128 - }
+2 -2
tools/perf/arch/x86/tests/intel-pt-test.c
··· 375 375 return 0; 376 376 } 377 377 378 - static bool is_hydrid(void) 378 + static bool is_hybrid(void) 379 379 { 380 380 unsigned int eax, ebx, ecx, edx = 0; 381 381 bool result; ··· 441 441 int ret = TEST_OK; 442 442 int cpu; 443 443 444 - if (!is_hydrid()) { 444 + if (!is_hybrid()) { 445 445 test->test_cases[subtest].skip_reason = "not hybrid"; 446 446 return TEST_SKIP; 447 447 }
-4
tools/perf/arch/x86/util/Build
··· 10 10 perf-util-y += mem-events.o 11 11 perf-util-y += evsel.o 12 12 perf-util-y += iostat.o 13 - perf-util-y += env.o 14 - 15 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 16 - perf-util-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o 17 13 18 14 perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o 19 15 perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+2 -1
tools/perf/arch/x86/util/auxtrace.c
··· 55 55 int *err) 56 56 { 57 57 char buffer[64]; 58 + struct perf_cpu cpu = perf_cpu_map__min(evlist->core.all_cpus); 58 59 int ret; 59 60 60 61 *err = 0; 61 62 62 - ret = get_cpuid(buffer, sizeof(buffer)); 63 + ret = get_cpuid(buffer, sizeof(buffer), cpu); 63 64 if (ret) { 64 65 *err = ret; 65 66 return NULL;
-153
tools/perf/arch/x86/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * dwarf-regs.c : Mapping of DWARF debug register numbers into register names. 4 - * Extracted from probe-finder.c 5 - * 6 - * Written by Masami Hiramatsu <mhiramat@redhat.com> 7 - */ 8 - 9 - #include <stddef.h> 10 - #include <errno.h> /* for EINVAL */ 11 - #include <string.h> /* for strcmp */ 12 - #include <linux/ptrace.h> /* for struct pt_regs */ 13 - #include <linux/kernel.h> /* for offsetof */ 14 - #include <dwarf-regs.h> 15 - 16 - /* 17 - * See arch/x86/kernel/ptrace.c. 18 - * Different from it: 19 - * 20 - * - Since struct pt_regs is defined differently for user and kernel, 21 - * but we want to use 'ax, bx' instead of 'rax, rbx' (which is struct 22 - * field name of user's pt_regs), we make REG_OFFSET_NAME to accept 23 - * both string name and reg field name. 24 - * 25 - * - Since accessing x86_32's pt_regs from x86_64 building is difficult 26 - * and vise versa, we simply fill offset with -1, so 27 - * get_arch_regstr() still works but regs_query_register_offset() 28 - * returns error. 29 - * The only inconvenience caused by it now is that we are not allowed 30 - * to generate BPF prologue for a x86_64 kernel if perf is built for 31 - * x86_32. This is really a rare usecase. 32 - * 33 - * - Order is different from kernel's ptrace.c for get_arch_regstr(). Use 34 - * the order defined by dwarf. 35 - */ 36 - 37 - struct pt_regs_offset { 38 - const char *name; 39 - int offset; 40 - }; 41 - 42 - #define REG_OFFSET_END {.name = NULL, .offset = 0} 43 - 44 - #ifdef __x86_64__ 45 - # define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)} 46 - # define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = -1} 47 - #else 48 - # define REG_OFFSET_NAME_64(n, r) {.name = n, .offset = -1} 49 - # define REG_OFFSET_NAME_32(n, r) {.name = n, .offset = offsetof(struct pt_regs, r)} 50 - #endif 51 - 52 - /* TODO: switching by dwarf address size */ 53 - #ifndef __x86_64__ 54 - static const struct pt_regs_offset x86_32_regoffset_table[] = { 55 - REG_OFFSET_NAME_32("%ax", eax), 56 - REG_OFFSET_NAME_32("%cx", ecx), 57 - REG_OFFSET_NAME_32("%dx", edx), 58 - REG_OFFSET_NAME_32("%bx", ebx), 59 - REG_OFFSET_NAME_32("$stack", esp), /* Stack address instead of %sp */ 60 - REG_OFFSET_NAME_32("%bp", ebp), 61 - REG_OFFSET_NAME_32("%si", esi), 62 - REG_OFFSET_NAME_32("%di", edi), 63 - REG_OFFSET_END, 64 - }; 65 - 66 - #define regoffset_table x86_32_regoffset_table 67 - #else 68 - static const struct pt_regs_offset x86_64_regoffset_table[] = { 69 - REG_OFFSET_NAME_64("%ax", rax), 70 - REG_OFFSET_NAME_64("%dx", rdx), 71 - REG_OFFSET_NAME_64("%cx", rcx), 72 - REG_OFFSET_NAME_64("%bx", rbx), 73 - REG_OFFSET_NAME_64("%si", rsi), 74 - REG_OFFSET_NAME_64("%di", rdi), 75 - REG_OFFSET_NAME_64("%bp", rbp), 76 - REG_OFFSET_NAME_64("%sp", rsp), 77 - REG_OFFSET_NAME_64("%r8", r8), 78 - REG_OFFSET_NAME_64("%r9", r9), 79 - REG_OFFSET_NAME_64("%r10", r10), 80 - REG_OFFSET_NAME_64("%r11", r11), 81 - REG_OFFSET_NAME_64("%r12", r12), 82 - REG_OFFSET_NAME_64("%r13", r13), 83 - REG_OFFSET_NAME_64("%r14", r14), 84 - REG_OFFSET_NAME_64("%r15", r15), 85 - REG_OFFSET_END, 86 - }; 87 - 88 - #define regoffset_table x86_64_regoffset_table 89 - #endif 90 - 91 - /* Minus 1 for the ending REG_OFFSET_END */ 92 - #define ARCH_MAX_REGS ((sizeof(regoffset_table) / sizeof(regoffset_table[0])) - 1) 93 - 94 - /* Return architecture dependent register string (for kprobe-tracer) */ 95 - const char *get_arch_regstr(unsigned int n) 96 - { 97 - return (n < ARCH_MAX_REGS) ? regoffset_table[n].name : NULL; 98 - } 99 - 100 - /* Reuse code from arch/x86/kernel/ptrace.c */ 101 - /** 102 - * regs_query_register_offset() - query register offset from its name 103 - * @name: the name of a register 104 - * 105 - * regs_query_register_offset() returns the offset of a register in struct 106 - * pt_regs from its name. If the name is invalid, this returns -EINVAL; 107 - */ 108 - int regs_query_register_offset(const char *name) 109 - { 110 - const struct pt_regs_offset *roff; 111 - for (roff = regoffset_table; roff->name != NULL; roff++) 112 - if (!strcmp(roff->name, name)) 113 - return roff->offset; 114 - return -EINVAL; 115 - } 116 - 117 - struct dwarf_regs_idx { 118 - const char *name; 119 - int idx; 120 - }; 121 - 122 - static const struct dwarf_regs_idx x86_regidx_table[] = { 123 - { "rax", 0 }, { "eax", 0 }, { "ax", 0 }, { "al", 0 }, 124 - { "rdx", 1 }, { "edx", 1 }, { "dx", 1 }, { "dl", 1 }, 125 - { "rcx", 2 }, { "ecx", 2 }, { "cx", 2 }, { "cl", 2 }, 126 - { "rbx", 3 }, { "edx", 3 }, { "bx", 3 }, { "bl", 3 }, 127 - { "rsi", 4 }, { "esi", 4 }, { "si", 4 }, { "sil", 4 }, 128 - { "rdi", 5 }, { "edi", 5 }, { "di", 5 }, { "dil", 5 }, 129 - { "rbp", 6 }, { "ebp", 6 }, { "bp", 6 }, { "bpl", 6 }, 130 - { "rsp", 7 }, { "esp", 7 }, { "sp", 7 }, { "spl", 7 }, 131 - { "r8", 8 }, { "r8d", 8 }, { "r8w", 8 }, { "r8b", 8 }, 132 - { "r9", 9 }, { "r9d", 9 }, { "r9w", 9 }, { "r9b", 9 }, 133 - { "r10", 10 }, { "r10d", 10 }, { "r10w", 10 }, { "r10b", 10 }, 134 - { "r11", 11 }, { "r11d", 11 }, { "r11w", 11 }, { "r11b", 11 }, 135 - { "r12", 12 }, { "r12d", 12 }, { "r12w", 12 }, { "r12b", 12 }, 136 - { "r13", 13 }, { "r13d", 13 }, { "r13w", 13 }, { "r13b", 13 }, 137 - { "r14", 14 }, { "r14d", 14 }, { "r14w", 14 }, { "r14b", 14 }, 138 - { "r15", 15 }, { "r15d", 15 }, { "r15w", 15 }, { "r15b", 15 }, 139 - { "rip", DWARF_REG_PC }, 140 - }; 141 - 142 - int get_arch_regnum(const char *name) 143 - { 144 - unsigned int i; 145 - 146 - if (*name != '%') 147 - return -EINVAL; 148 - 149 - for (i = 0; i < ARRAY_SIZE(x86_regidx_table); i++) 150 - if (!strcmp(x86_regidx_table[i].name, name + 1)) 151 - return x86_regidx_table[i].idx; 152 - return -ENOENT; 153 - }
-19
tools/perf/arch/x86/util/env.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include "linux/string.h" 3 - #include "util/env.h" 4 - #include "env.h" 5 - 6 - bool x86__is_amd_cpu(void) 7 - { 8 - struct perf_env env = { .total_mem = 0, }; 9 - static int is_amd; /* 0: Uninitialized, 1: Yes, -1: No */ 10 - 11 - if (is_amd) 12 - goto ret; 13 - 14 - perf_env__cpuid(&env); 15 - is_amd = env.cpuid && strstarts(env.cpuid, "AuthenticAMD") ? 1 : -1; 16 - perf_env__exit(&env); 17 - ret: 18 - return is_amd >= 1 ? true : false; 19 - }
-7
tools/perf/arch/x86/util/env.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _X86_ENV_H 3 - #define _X86_ENV_H 4 - 5 - bool x86__is_amd_cpu(void); 6 - 7 - #endif /* _X86_ENV_H */
+71 -76
tools/perf/arch/x86/util/evlist.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <stdio.h> 3 - #include "util/pmu.h" 4 - #include "util/pmus.h" 5 - #include "util/evlist.h" 6 - #include "util/parse-events.h" 7 - #include "util/event.h" 2 + #include <string.h> 3 + #include "../../../util/evlist.h" 4 + #include "../../../util/evsel.h" 8 5 #include "topdown.h" 9 6 #include "evsel.h" 10 7 11 - static int ___evlist__add_default_attrs(struct evlist *evlist, 12 - struct perf_event_attr *attrs, 13 - size_t nr_attrs) 14 - { 15 - LIST_HEAD(head); 16 - size_t i = 0; 17 - 18 - for (i = 0; i < nr_attrs; i++) 19 - event_attr_init(attrs + i); 20 - 21 - if (perf_pmus__num_core_pmus() == 1) 22 - return evlist__add_attrs(evlist, attrs, nr_attrs); 23 - 24 - for (i = 0; i < nr_attrs; i++) { 25 - struct perf_pmu *pmu = NULL; 26 - 27 - if (attrs[i].type == PERF_TYPE_SOFTWARE) { 28 - struct evsel *evsel = evsel__new(attrs + i); 29 - 30 - if (evsel == NULL) 31 - goto out_delete_partial_list; 32 - list_add_tail(&evsel->core.node, &head); 33 - continue; 34 - } 35 - 36 - while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { 37 - struct perf_cpu_map *cpus; 38 - struct evsel *evsel; 39 - 40 - evsel = evsel__new(attrs + i); 41 - if (evsel == NULL) 42 - goto out_delete_partial_list; 43 - evsel->core.attr.config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; 44 - cpus = perf_cpu_map__get(pmu->cpus); 45 - evsel->core.cpus = cpus; 46 - evsel->core.own_cpus = perf_cpu_map__get(cpus); 47 - evsel->pmu_name = strdup(pmu->name); 48 - list_add_tail(&evsel->core.node, &head); 49 - } 50 - } 51 - 52 - evlist__splice_list_tail(evlist, &head); 53 - 54 - return 0; 55 - 56 - out_delete_partial_list: 57 - { 58 - struct evsel *evsel, *n; 59 - 60 - __evlist__for_each_entry_safe(&head, n, evsel) 61 - evsel__delete(evsel); 62 - } 63 - return -1; 64 - } 65 - 66 - int arch_evlist__add_default_attrs(struct evlist *evlist, 67 - struct perf_event_attr *attrs, 68 - size_t nr_attrs) 69 - { 70 - if (!nr_attrs) 71 - return 0; 72 - 73 - return ___evlist__add_default_attrs(evlist, attrs, nr_attrs); 74 - } 75 - 76 8 int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs) 77 9 { 10 + /* 11 + * Currently the following topdown events sequence are supported to 12 + * move and regroup correctly. 13 + * 14 + * a. all events in a group 15 + * perf stat -e "{instructions,topdown-retiring,slots}" -C0 sleep 1 16 + * WARNING: events were regrouped to match PMUs 17 + * Performance counter stats for 'CPU(s) 0': 18 + * 15,066,240 slots 19 + * 1,899,760 instructions 20 + * 2,126,998 topdown-retiring 21 + * b. all events not in a group 22 + * perf stat -e "instructions,topdown-retiring,slots" -C0 sleep 1 23 + * WARNING: events were regrouped to match PMUs 24 + * Performance counter stats for 'CPU(s) 0': 25 + * 2,045,561 instructions 26 + * 17,108,370 slots 27 + * 2,281,116 topdown-retiring 28 + * c. slots event in a group but topdown metrics events outside the group 29 + * perf stat -e "{instructions,slots},topdown-retiring" -C0 sleep 1 30 + * WARNING: events were regrouped to match PMUs 31 + * Performance counter stats for 'CPU(s) 0': 32 + * 20,323,878 slots 33 + * 2,634,884 instructions 34 + * 3,028,656 topdown-retiring 35 + * d. slots event and topdown metrics events in two groups 36 + * perf stat -e "{instructions,slots},{topdown-retiring}" -C0 sleep 1 37 + * WARNING: events were regrouped to match PMUs 38 + * Performance counter stats for 'CPU(s) 0': 39 + * 26,319,024 slots 40 + * 2,427,791 instructions 41 + * 2,683,508 topdown-retiring 42 + * 43 + * If slots event and topdown metrics events are not in same group, the 44 + * topdown metrics events must be first event after the slots event group, 45 + * otherwise topdown metrics events can't be regrouped correctly, e.g. 46 + * 47 + * a. perf stat -e "{instructions,slots},cycles,topdown-retiring" -C0 sleep 1 48 + * WARNING: events were regrouped to match PMUs 49 + * Performance counter stats for 'CPU(s) 0': 50 + * 17,923,134 slots 51 + * 2,154,855 instructions 52 + * 3,015,058 cycles 53 + * <not supported> topdown-retiring 54 + * 55 + * If slots event and topdown metrics events are in two groups, the group which 56 + * has topdown metrics events must contain only the topdown metrics event, 57 + * otherwise topdown metrics event can't be regrouped correctly as well, e.g. 58 + * 59 + * a. perf stat -e "{instructions,slots},{topdown-retiring,cycles}" -C0 sleep 1 60 + * WARNING: events were regrouped to match PMUs 61 + * Error: 62 + * The sys_perf_event_open() syscall returned with 22 (Invalid argument) for 63 + * event (topdown-retiring) 64 + */ 78 65 if (topdown_sys_has_perf_metrics() && 79 66 (arch_evsel__must_be_in_group(lhs) || arch_evsel__must_be_in_group(rhs))) { 80 67 /* Ensure the topdown slots comes first. */ 81 - if (strcasestr(lhs->name, "slots") && !strcasestr(lhs->name, "uops_retired.slots")) 68 + if (arch_is_topdown_slots(lhs)) 82 69 return -1; 83 - if (strcasestr(rhs->name, "slots") && !strcasestr(rhs->name, "uops_retired.slots")) 70 + if (arch_is_topdown_slots(rhs)) 84 71 return 1; 85 - /* Followed by topdown events. */ 86 - if (strcasestr(lhs->name, "topdown") && !strcasestr(rhs->name, "topdown")) 72 + 73 + /* 74 + * Move topdown metrics events forward only when topdown metrics 75 + * events are not in same group with previous slots event. If 76 + * topdown metrics events are already in same group with slots 77 + * event, do nothing. 78 + */ 79 + if (arch_is_topdown_metrics(lhs) && !arch_is_topdown_metrics(rhs) && 80 + lhs->core.leader != rhs->core.leader) 87 81 return -1; 88 - if (!strcasestr(lhs->name, "topdown") && strcasestr(rhs->name, "topdown")) 82 + if (!arch_is_topdown_metrics(lhs) && arch_is_topdown_metrics(rhs) && 83 + lhs->core.leader != rhs->core.leader) 89 84 return 1; 90 85 } 91 86
+30 -8
tools/perf/arch/x86/util/evsel.c
··· 6 6 #include "util/pmu.h" 7 7 #include "util/pmus.h" 8 8 #include "linux/string.h" 9 + #include "topdown.h" 9 10 #include "evsel.h" 10 11 #include "util/debug.h" 11 12 #include "env.h" ··· 22 21 /* Check whether the evsel's PMU supports the perf metrics */ 23 22 bool evsel__sys_has_perf_metrics(const struct evsel *evsel) 24 23 { 25 - const char *pmu_name = evsel->pmu_name ? evsel->pmu_name : "cpu"; 24 + struct perf_pmu *pmu; 25 + u32 type = evsel->core.attr.type; 26 26 27 27 /* 28 28 * The PERF_TYPE_RAW type is the core PMU type, e.g., "cpu" PMU ··· 33 31 * Checking both the PERF_TYPE_RAW type and the slots event 34 32 * should be good enough to detect the perf metrics feature. 35 33 */ 36 - if ((evsel->core.attr.type == PERF_TYPE_RAW) && 37 - perf_pmus__have_event(pmu_name, "slots")) 38 - return true; 34 + again: 35 + switch (type) { 36 + case PERF_TYPE_HARDWARE: 37 + case PERF_TYPE_HW_CACHE: 38 + type = evsel->core.attr.config >> PERF_PMU_TYPE_SHIFT; 39 + if (type) 40 + goto again; 41 + break; 42 + case PERF_TYPE_RAW: 43 + break; 44 + default: 45 + return false; 46 + } 39 47 40 - return false; 48 + pmu = evsel->pmu; 49 + if (pmu && perf_pmu__is_fake(pmu)) 50 + pmu = NULL; 51 + 52 + if (!pmu) { 53 + while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { 54 + if (pmu->type == PERF_TYPE_RAW) 55 + break; 56 + } 57 + } 58 + return pmu && perf_pmu__have_event(pmu, "slots"); 41 59 } 42 60 43 61 bool arch_evsel__must_be_in_group(const struct evsel *evsel) ··· 66 44 strcasestr(evsel->name, "uops_retired.slots")) 67 45 return false; 68 46 69 - return strcasestr(evsel->name, "topdown") || strcasestr(evsel->name, "slots"); 47 + return arch_is_topdown_metrics(evsel) || arch_is_topdown_slots(evsel); 70 48 } 71 49 72 50 int arch_evsel__hw_name(struct evsel *evsel, char *bf, size_t size) ··· 85 63 return scnprintf(bf, size, "%s", event_name); 86 64 87 65 return scnprintf(bf, size, "%s/%s/", 88 - evsel->pmu_name ? evsel->pmu_name : "cpu", 66 + evsel->pmu ? evsel->pmu->name : "cpu", 89 67 event_name); 90 68 } 91 69 ··· 130 108 return 0; 131 109 132 110 if (!evsel->core.attr.precise_ip && 133 - !(evsel->pmu_name && !strncmp(evsel->pmu_name, "ibs", 3))) 111 + !(evsel->pmu && !strncmp(evsel->pmu->name, "ibs", 3))) 134 112 return 0; 135 113 136 114 /* More verbose IBS errors. */
+2 -3
tools/perf/arch/x86/util/header.c
··· 58 58 } 59 59 60 60 int 61 - get_cpuid(char *buffer, size_t sz) 61 + get_cpuid(char *buffer, size_t sz, struct perf_cpu cpu __maybe_unused) 62 62 { 63 63 return __get_cpuid(buffer, sz, "%s,%u,%u,%u$"); 64 64 } 65 65 66 - char * 67 - get_cpuid_str(struct perf_pmu *pmu __maybe_unused) 66 + char *get_cpuid_str(struct perf_cpu cpu __maybe_unused) 68 67 { 69 68 char *buf = malloc(128); 70 69
+2 -1
tools/perf/arch/x86/util/intel-pt.c
··· 75 75 goto out_free; 76 76 77 77 attr.config = *config; 78 - err = perf_pmu__config_terms(pmu, &attr, &terms, /*zero=*/true, /*err=*/NULL); 78 + err = perf_pmu__config_terms(pmu, &attr, &terms, /*zero=*/true, /*apply_hardcoded=*/false, 79 + /*err=*/NULL); 79 80 if (err) 80 81 goto out_free; 81 82
+1 -1
tools/perf/arch/x86/util/iostat.c
··· 444 444 iostat_value = (count->val - prev_count_val) / 445 445 ((double) count->run / count->ena); 446 446 } 447 - out->print_metric(config, out->ctx, NULL, "%8.0f", iostat_metric, 447 + out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN, "%8.0f", iostat_metric, 448 448 iostat_value / (256 * 1024)); 449 449 } 450 450
+1 -1
tools/perf/arch/x86/util/pmu.c
··· 16 16 #include "../../../util/fncache.h" 17 17 #include "../../../util/pmus.h" 18 18 #include "mem-events.h" 19 - #include "env.h" 19 + #include "util/env.h" 20 20 21 21 void perf_pmu__arch_init(struct perf_pmu *pmu __maybe_unused) 22 22 {
+41 -2
tools/perf/arch/x86/util/topdown.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include "api/fs/fs.h" 3 3 #include "util/evsel.h" 4 + #include "util/evlist.h" 4 5 #include "util/pmu.h" 5 6 #include "util/pmus.h" 6 7 #include "util/topdown.h" ··· 33 32 } 34 33 35 34 #define TOPDOWN_SLOTS 0x0400 35 + bool arch_is_topdown_slots(const struct evsel *evsel) 36 + { 37 + if (evsel->core.attr.config == TOPDOWN_SLOTS) 38 + return true; 39 + 40 + return false; 41 + } 42 + 43 + bool arch_is_topdown_metrics(const struct evsel *evsel) 44 + { 45 + int config = evsel->core.attr.config; 46 + const char *name_from_config; 47 + struct perf_pmu *pmu; 48 + 49 + /* All topdown events have an event code of 0. */ 50 + if ((config & 0xFF) != 0) 51 + return false; 52 + 53 + pmu = evsel__find_pmu(evsel); 54 + if (!pmu || !pmu->is_core) 55 + return false; 56 + 57 + name_from_config = perf_pmu__name_from_config(pmu, config); 58 + return name_from_config && strcasestr(name_from_config, "topdown"); 59 + } 36 60 37 61 /* 38 62 * Check whether a topdown group supports sample-read. ··· 67 41 */ 68 42 bool arch_topdown_sample_read(struct evsel *leader) 69 43 { 44 + struct evsel *evsel; 45 + 70 46 if (!evsel__sys_has_perf_metrics(leader)) 71 47 return false; 72 48 73 - if (leader->core.attr.config == TOPDOWN_SLOTS) 74 - return true; 49 + if (!arch_is_topdown_slots(leader)) 50 + return false; 51 + 52 + /* 53 + * If slots event as leader event but no topdown metric events 54 + * in group, slots event should still sample as leader. 55 + */ 56 + evlist__for_each_entry(leader->evlist, evsel) { 57 + if (evsel->core.leader != leader->core.leader) 58 + return false; 59 + if (evsel != leader && arch_is_topdown_metrics(evsel)) 60 + return true; 61 + } 75 62 76 63 return false; 77 64 }
+2
tools/perf/arch/x86/util/topdown.h
··· 3 3 #define _TOPDOWN_H 1 4 4 5 5 bool topdown_sys_has_perf_metrics(void); 6 + bool arch_is_topdown_slots(const struct evsel *evsel); 7 + bool arch_is_topdown_metrics(const struct evsel *evsel); 6 8 7 9 #endif
+10 -8
tools/perf/arch/x86/util/tsc.c
··· 24 24 * ... 25 25 * will return 3000000000. 26 26 */ 27 - static double cpuinfo_tsc_freq(void) 27 + static u64 cpuinfo_tsc_freq(void) 28 28 { 29 - double result = 0; 29 + u64 result = 0; 30 30 FILE *cpuinfo; 31 31 char *line = NULL; 32 32 size_t len = 0; ··· 34 34 cpuinfo = fopen("/proc/cpuinfo", "r"); 35 35 if (!cpuinfo) { 36 36 pr_err("Failed to read /proc/cpuinfo for TSC frequency\n"); 37 - return NAN; 37 + return 0; 38 38 } 39 39 while (getline(&line, &len, cpuinfo) > 0) { 40 40 if (!strncmp(line, "model name", 10)) { 41 41 char *pos = strstr(line + 11, " @ "); 42 + double float_result; 42 43 43 - if (pos && sscanf(pos, " @ %lfGHz", &result) == 1) { 44 - result *= 1000000000; 44 + if (pos && sscanf(pos, " @ %lfGHz", &float_result) == 1) { 45 + float_result *= 1000000000; 46 + result = (u64)float_result; 45 47 goto out; 46 48 } 47 49 } 48 50 } 49 51 out: 50 - if (fpclassify(result) == FP_ZERO) 52 + if (result == 0) 51 53 pr_err("Failed to find TSC frequency in /proc/cpuinfo\n"); 52 54 53 55 free(line); ··· 57 55 return result; 58 56 } 59 57 60 - double arch_get_tsc_freq(void) 58 + u64 arch_get_tsc_freq(void) 61 59 { 62 60 unsigned int a, b, c, d, lvl; 63 61 static bool cached; ··· 88 86 return tsc; 89 87 } 90 88 91 - tsc = (double)c * (double)b / (double)a; 89 + tsc = (u64)c * (u64)b / (u64)a; 92 90 return tsc; 93 91 }
-1
tools/perf/arch/xtensa/Build
··· 1 - perf-util-y += util/
-4
tools/perf/arch/xtensa/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - ifndef NO_DWARF 3 - PERF_HAVE_DWARF_REGS := 1 4 - endif
-1
tools/perf/arch/xtensa/util/Build
··· 1 - perf-$(CONFIG_DWARF) += dwarf-regs.o
-21
tools/perf/arch/xtensa/util/dwarf-regs.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * Mapping of DWARF debug register numbers into register names. 4 - * 5 - * Copyright (c) 2015 Cadence Design Systems Inc. 6 - */ 7 - 8 - #include <stddef.h> 9 - #include <dwarf-regs.h> 10 - 11 - #define XTENSA_MAX_REGS 16 12 - 13 - const char *xtensa_regs_table[XTENSA_MAX_REGS] = { 14 - "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", 15 - "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15", 16 - }; 17 - 18 - const char *get_arch_regstr(unsigned int n) 19 - { 20 - return n < XTENSA_MAX_REGS ? xtensa_regs_table[n] : NULL; 21 - }
+53
tools/perf/bench/numa.c
··· 27 27 #include <sys/resource.h> 28 28 #include <sys/wait.h> 29 29 #include <sys/prctl.h> 30 + #include <sys/stat.h> 30 31 #include <sys/types.h> 31 32 #include <linux/kernel.h> 32 33 #include <linux/time64.h> ··· 36 35 37 36 #include "../util/header.h" 38 37 #include "../util/mutex.h" 38 + #include <api/fs/fs.h> 39 39 #include <numa.h> 40 40 #include <numaif.h> 41 41 ··· 533 531 dprintf("got CPU list: {%s}\n", p0.cpu_list_str); 534 532 535 533 return 0; 534 + } 535 + 536 + /* 537 + * Check whether a CPU is online 538 + * 539 + * Returns: 540 + * 1 -> if CPU is online 541 + * 0 -> if CPU is offline 542 + * -1 -> error case 543 + */ 544 + static int is_cpu_online(unsigned int cpu) 545 + { 546 + char *str; 547 + size_t strlen; 548 + char buf[256]; 549 + int status = -1; 550 + struct stat statbuf; 551 + 552 + snprintf(buf, sizeof(buf), 553 + "/sys/devices/system/cpu/cpu%d", cpu); 554 + if (stat(buf, &statbuf) != 0) 555 + return 0; 556 + 557 + /* 558 + * Check if /sys/devices/system/cpu/cpux/online file 559 + * exists. Some cases cpu0 won't have online file since 560 + * it is not expected to be turned off generally. 561 + * In kernels without CONFIG_HOTPLUG_CPU, this 562 + * file won't exist 563 + */ 564 + snprintf(buf, sizeof(buf), 565 + "/sys/devices/system/cpu/cpu%d/online", cpu); 566 + if (stat(buf, &statbuf) != 0) 567 + return 1; 568 + 569 + /* 570 + * Read online file using sysfs__read_str. 571 + * If read or open fails, return -1. 572 + * If read succeeds, return value from file 573 + * which gets stored in "str" 574 + */ 575 + snprintf(buf, sizeof(buf), 576 + "devices/system/cpu/cpu%d/online", cpu); 577 + 578 + if (sysfs__read_str(buf, &str, &strlen) < 0) 579 + return status; 580 + 581 + status = atoi(str); 582 + 583 + free(str); 584 + return status; 536 585 } 537 586 538 587 static int parse_setup_cpu_list(void)
+36 -7
tools/perf/bench/sched-pipe.c
··· 23 23 #include <errno.h> 24 24 #include <fcntl.h> 25 25 #include <assert.h> 26 + #include <sys/epoll.h> 26 27 #include <sys/time.h> 27 28 #include <sys/types.h> 28 29 #include <sys/syscall.h> ··· 35 34 int nr; 36 35 int pipe_read; 37 36 int pipe_write; 37 + struct epoll_event epoll_ev; 38 + int epoll_fd; 38 39 bool cgroup_failed; 39 40 pthread_t pthread; 40 41 }; ··· 47 44 /* Use processes by default: */ 48 45 static bool threaded; 49 46 47 + static bool nonblocking; 50 48 static char *cgrp_names[2]; 51 49 static struct cgroup *cgrps[2]; 52 50 ··· 85 81 } 86 82 87 83 static const struct option options[] = { 84 + OPT_BOOLEAN('n', "nonblocking", &nonblocking, "Use non-blocking operations"), 88 85 OPT_INTEGER('l', "loop", &loops, "Specify number of loops"), 89 86 OPT_BOOLEAN('T', "threaded", &threaded, "Specify threads/process based task setup"), 90 87 OPT_CALLBACK('G', "cgroups", NULL, "SEND,RECV", ··· 170 165 free(cgrp_names[nr]); 171 166 } 172 167 168 + static inline int read_pipe(struct thread_data *td) 169 + { 170 + int ret, m; 171 + retry: 172 + if (nonblocking) { 173 + ret = epoll_wait(td->epoll_fd, &td->epoll_ev, 1, -1); 174 + if (ret < 0) 175 + return ret; 176 + } 177 + ret = read(td->pipe_read, &m, sizeof(int)); 178 + if (nonblocking && ret < 0 && errno == EWOULDBLOCK) 179 + goto retry; 180 + return ret; 181 + } 182 + 173 183 static void *worker_thread(void *__tdata) 174 184 { 175 185 struct thread_data *td = __tdata; 176 - int m = 0, i; 177 - int ret; 186 + int i, ret, m = 0; 178 187 179 188 ret = enter_cgroup(td->nr); 180 189 if (ret < 0) { ··· 196 177 return NULL; 197 178 } 198 179 180 + if (nonblocking) { 181 + td->epoll_ev.events = EPOLLIN; 182 + td->epoll_fd = epoll_create(1); 183 + BUG_ON(td->epoll_fd < 0); 184 + BUG_ON(epoll_ctl(td->epoll_fd, EPOLL_CTL_ADD, td->pipe_read, &td->epoll_ev) < 0); 185 + } 186 + 199 187 for (i = 0; i < loops; i++) { 200 188 if (!td->nr) { 201 - ret = read(td->pipe_read, &m, sizeof(int)); 189 + ret = read_pipe(td); 202 190 BUG_ON(ret != sizeof(int)); 203 191 ret = write(td->pipe_write, &m, sizeof(int)); 204 192 BUG_ON(ret != sizeof(int)); 205 193 } else { 206 194 ret = write(td->pipe_write, &m, sizeof(int)); 207 195 BUG_ON(ret != sizeof(int)); 208 - ret = read(td->pipe_read, &m, sizeof(int)); 196 + ret = read_pipe(td); 209 197 BUG_ON(ret != sizeof(int)); 210 198 } 211 199 } ··· 235 209 * discarding returned value of read(), write() 236 210 * causes error in building environment for perf 237 211 */ 238 - int __maybe_unused ret, wait_stat; 212 + int __maybe_unused ret, wait_stat, flags = 0; 239 213 pid_t pid, retpid __maybe_unused; 240 214 241 215 argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0); 242 216 243 - BUG_ON(pipe(pipe_1)); 244 - BUG_ON(pipe(pipe_2)); 217 + if (nonblocking) 218 + flags |= O_NONBLOCK; 219 + 220 + BUG_ON(pipe2(pipe_1, flags)); 221 + BUG_ON(pipe2(pipe_2, flags)); 245 222 246 223 gettimeofday(&start, NULL); 247 224
+1 -1
tools/perf/builtin-annotate.c
··· 840 840 } 841 841 #endif 842 842 843 - #ifndef HAVE_DWARF_GETLOCATIONS_SUPPORT 843 + #ifndef HAVE_LIBDW_SUPPORT 844 844 if (annotate.data_type) { 845 845 pr_err("Error: Data type profiling is disabled due to missing DWARF support\n"); 846 846 return -ENOTSUP;
+3 -3
tools/perf/builtin-check.c
··· 27 27 FEATURE_STATUS("bpf", HAVE_LIBBPF_SUPPORT), 28 28 FEATURE_STATUS("bpf_skeletons", HAVE_BPF_SKEL), 29 29 FEATURE_STATUS("debuginfod", HAVE_DEBUGINFOD_SUPPORT), 30 - FEATURE_STATUS("dwarf", HAVE_DWARF_SUPPORT), 31 - FEATURE_STATUS("dwarf_getlocations", HAVE_DWARF_GETLOCATIONS_SUPPORT), 30 + FEATURE_STATUS("dwarf", HAVE_LIBDW_SUPPORT), 31 + FEATURE_STATUS("dwarf_getlocations", HAVE_LIBDW_SUPPORT), 32 32 FEATURE_STATUS("dwarf-unwind", HAVE_DWARF_UNWIND_SUPPORT), 33 33 FEATURE_STATUS("auxtrace", HAVE_AUXTRACE_SUPPORT), 34 34 FEATURE_STATUS("libaudit", HAVE_LIBAUDIT_SUPPORT), 35 35 FEATURE_STATUS("libbfd", HAVE_LIBBFD_SUPPORT), 36 36 FEATURE_STATUS("libcapstone", HAVE_LIBCAPSTONE_SUPPORT), 37 37 FEATURE_STATUS("libcrypto", HAVE_LIBCRYPTO_SUPPORT), 38 - FEATURE_STATUS("libdw-dwarf-unwind", HAVE_DWARF_SUPPORT), 38 + FEATURE_STATUS("libdw-dwarf-unwind", HAVE_LIBDW_SUPPORT), 39 39 FEATURE_STATUS("libelf", HAVE_LIBELF_SUPPORT), 40 40 FEATURE_STATUS("libnuma", HAVE_LIBNUMA_SUPPORT), 41 41 FEATURE_STATUS("libopencsd", HAVE_CSTRACE_SUPPORT),
+3 -3
tools/perf/builtin-diff.c
··· 469 469 470 470 static struct perf_diff pdiff; 471 471 472 - static struct evsel *evsel_match(struct evsel *evsel, 473 - struct evlist *evlist) 472 + static struct evsel *evsel_match(struct evsel *evsel, struct evlist *evlist) 474 473 { 475 474 struct evsel *e; 476 475 477 476 evlist__for_each_entry(evlist, e) { 478 - if (evsel__match2(evsel, e)) 477 + if ((evsel->core.attr.type == e->core.attr.type) && 478 + (evsel->core.attr.config == e->core.attr.config)) 479 479 return e; 480 480 } 481 481
+1 -1
tools/perf/builtin-ftrace.c
··· 815 815 816 816 bar_len = buckets[0] * bar_total / total; 817 817 printf(" %4d - %-4d %s | %10d | %.*s%*s |\n", 818 - 0, 1, "us", buckets[0], bar_len, bar, bar_total - bar_len, ""); 818 + 0, 1, use_nsec ? "ns" : "us", buckets[0], bar_len, bar, bar_total - bar_len, ""); 819 819 820 820 for (i = 1; i < NUM_BUCKET - 1; i++) { 821 821 int start = (1 << (i - 1));
+1 -1
tools/perf/builtin-kmem.c
··· 36 36 #include <regex.h> 37 37 38 38 #include <linux/ctype.h> 39 - #include <traceevent/event-parse.h> 39 + #include <event-parse.h> 40 40 41 41 static int kmem_slab; 42 42 static int kmem_page;
+4 -1
tools/perf/builtin-kvm.c
··· 1226 1226 int err; 1227 1227 1228 1228 if (kvm->live) { 1229 - err = get_cpuid(buf, sizeof(buf)); 1229 + struct perf_cpu cpu = {-1}; 1230 + 1231 + err = get_cpuid(buf, sizeof(buf), cpu); 1230 1232 if (err != 0) { 1231 1233 pr_err("Failed to look up CPU type: %s\n", 1232 1234 str_error_r(err, buf, sizeof(buf))); ··· 2149 2147 "buildid-list", "stat", NULL }; 2150 2148 const char *kvm_usage[] = { NULL, NULL }; 2151 2149 2150 + exclude_GH_default = true; 2152 2151 perf_host = 0; 2153 2152 perf_guest = 1; 2154 2153
+1 -1
tools/perf/builtin-kwork.c
··· 23 23 24 24 #include <subcmd/pager.h> 25 25 #include <subcmd/parse-options.h> 26 - #include <traceevent/event-parse.h> 26 + #include <event-parse.h> 27 27 28 28 #include <errno.h> 29 29 #include <inttypes.h>
+13 -4
tools/perf/builtin-list.c
··· 19 19 #include "util/string2.h" 20 20 #include "util/strlist.h" 21 21 #include "util/strbuf.h" 22 + #include "util/tool_pmu.h" 22 23 #include <subcmd/pager.h> 23 24 #include <subcmd/parse-options.h> 24 25 #include <linux/zalloc.h> ··· 113 112 } 114 113 } 115 114 116 - static void default_print_event(void *ps, const char *pmu_name, const char *topic, 115 + static void default_print_event(void *ps, const char *topic, const char *pmu_name, 117 116 const char *event_name, const char *event_alias, 118 117 const char *scale_unit __maybe_unused, 119 118 bool deprecated, const char *event_type_desc, ··· 354 353 fputs(buf->buf, fp); 355 354 } 356 355 357 - static void json_print_event(void *ps, const char *pmu_name, const char *topic, 356 + static void json_print_event(void *ps, const char *topic, const char *pmu_name, 358 357 const char *event_name, const char *event_alias, 359 358 const char *scale_unit, 360 359 bool deprecated, const char *event_type_desc, ··· 615 614 event_symbols_hw, PERF_COUNT_HW_MAX); 616 615 else if (strcmp(argv[i], "sw") == 0 || 617 616 strcmp(argv[i], "software") == 0) { 617 + char *old_pmu_glob = default_ps.pmu_glob; 618 + 618 619 print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE, 619 620 event_symbols_sw, PERF_COUNT_SW_MAX); 620 - print_tool_events(&print_cb, ps); 621 + default_ps.pmu_glob = strdup("tool"); 622 + if (!default_ps.pmu_glob) { 623 + ret = -1; 624 + goto out; 625 + } 626 + perf_pmus__print_pmu_events(&print_cb, ps); 627 + zfree(&default_ps.pmu_glob); 628 + default_ps.pmu_glob = old_pmu_glob; 621 629 } else if (strcmp(argv[i], "cache") == 0 || 622 630 strcmp(argv[i], "hwcache") == 0) 623 631 print_hwcache_events(&print_cb, ps); ··· 674 664 event_symbols_hw, PERF_COUNT_HW_MAX); 675 665 print_symbol_events(&print_cb, ps, PERF_TYPE_SOFTWARE, 676 666 event_symbols_sw, PERF_COUNT_SW_MAX); 677 - print_tool_events(&print_cb, ps); 678 667 print_hwcache_events(&print_cb, ps); 679 668 perf_pmus__print_pmu_events(&print_cb, ps); 680 669 print_tracepoint_events(&print_cb, ps);
+7 -7
tools/perf/builtin-probe.c
··· 229 229 230 230 /* Command option callbacks */ 231 231 232 - #ifdef HAVE_DWARF_SUPPORT 232 + #ifdef HAVE_LIBDW_SUPPORT 233 233 static int opt_show_lines(const struct option *opt, 234 234 const char *str, int unset __maybe_unused) 235 235 { ··· 505 505 return ret; 506 506 } 507 507 508 - #ifdef HAVE_DWARF_SUPPORT 508 + #ifdef HAVE_LIBDW_SUPPORT 509 509 #define PROBEDEF_STR \ 510 510 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT [[NAME=]ARG ...]" 511 511 #else ··· 521 521 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 522 522 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 523 523 "perf probe --list [GROUP:]EVENT ...", 524 - #ifdef HAVE_DWARF_SUPPORT 524 + #ifdef HAVE_LIBDW_SUPPORT 525 525 "perf probe [<options>] --line 'LINEDESC'", 526 526 "perf probe [<options>] --vars 'PROBEPOINT'", 527 527 #endif ··· 545 545 "\t\tFUNC:\tFunction name\n" 546 546 "\t\tOFF:\tOffset from function entry (in byte)\n" 547 547 "\t\t%return:\tPut the probe at function return\n" 548 - #ifdef HAVE_DWARF_SUPPORT 548 + #ifdef HAVE_LIBDW_SUPPORT 549 549 "\t\tSRC:\tSource code path\n" 550 550 "\t\tRL:\tRelative line number from function entry.\n" 551 551 "\t\tAL:\tAbsolute line number in file.\n" ··· 612 612 set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE); 613 613 set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE); 614 614 set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE); 615 - #ifdef HAVE_DWARF_SUPPORT 615 + #ifdef HAVE_LIBDW_SUPPORT 616 616 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE); 617 617 set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE); 618 618 #else 619 - # define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_DWARF=1", c) 619 + # define set_nobuild(s, l, c) set_option_nobuild(options, s, l, "NO_LIBDW=1", c) 620 620 set_nobuild('L', "line", false); 621 621 set_nobuild('V', "vars", false); 622 622 set_nobuild('\0', "externs", false); ··· 694 694 if (ret < 0) 695 695 pr_err_with_code(" Error: Failed to show functions.", ret); 696 696 return ret; 697 - #ifdef HAVE_DWARF_SUPPORT 697 + #ifdef HAVE_LIBDW_SUPPORT 698 698 case 'L': 699 699 ret = show_line_range(&params->line_range, params->target, 700 700 params->nsi, params->uprobes);
+1 -3
tools/perf/builtin-record.c
··· 4157 4157 record.opts.tail_synthesize = true; 4158 4158 4159 4159 if (rec->evlist->core.nr_entries == 0) { 4160 - bool can_profile_kernel = perf_event_paranoid_check(1); 4161 - 4162 - err = parse_event(rec->evlist, can_profile_kernel ? "cycles:P" : "cycles:Pu"); 4160 + err = parse_event(rec->evlist, "cycles:P"); 4163 4161 if (err) 4164 4162 goto out; 4165 4163 }
+8 -4
tools/perf/builtin-report.c
··· 70 70 #include <linux/mman.h> 71 71 72 72 #ifdef HAVE_LIBTRACEEVENT 73 - #include <traceevent/event-parse.h> 73 + #include <event-parse.h> 74 74 #endif 75 75 76 76 struct report { ··· 455 455 if (!(evlist__combined_branch_type(session->evlist) & PERF_SAMPLE_BRANCH_ANY)) 456 456 rep->nonany_branch_mode = true; 457 457 458 - #if !defined(HAVE_LIBUNWIND_SUPPORT) && !defined(HAVE_DWARF_SUPPORT) 458 + #if !defined(HAVE_LIBUNWIND_SUPPORT) && !defined(HAVE_LIBDW_SUPPORT) 459 459 if (dwarf_callchain_users) { 460 460 ui__warning("Please install libunwind or libdw " 461 461 "development packages during the perf build.\n"); ··· 1271 1271 return 0; 1272 1272 } 1273 1273 1274 + #define CALLCHAIN_BRANCH_SORT_ORDER \ 1275 + "srcline,symbol,dso,callchain_branch_predicted," \ 1276 + "callchain_branch_abort,callchain_branch_cycles" 1277 + 1274 1278 int cmd_report(int argc, const char **argv) 1275 1279 { 1276 1280 struct perf_session *session; ··· 1643 1639 symbol_conf.use_callchain = true; 1644 1640 callchain_register_param(&callchain_param); 1645 1641 if (sort_order == NULL) 1646 - sort_order = "srcline,symbol,dso"; 1642 + sort_order = CALLCHAIN_BRANCH_SORT_ORDER; 1647 1643 } 1648 1644 1649 1645 if (report.mem_mode) { ··· 1705 1701 report.data_type = true; 1706 1702 annotate_opts.annotate_src = false; 1707 1703 1708 - #ifndef HAVE_DWARF_GETLOCATIONS_SUPPORT 1704 + #ifndef HAVE_LIBDW_SUPPORT 1709 1705 pr_err("Error: Data type profiling is disabled due to missing DWARF support\n"); 1710 1706 goto error; 1711 1707 #endif
+63 -53
tools/perf/builtin-sched.c
··· 68 68 struct sched_atom **atoms; 69 69 70 70 pthread_t thread; 71 - sem_t sleep_sem; 72 71 73 72 sem_t ready_for_work; 74 73 sem_t work_done_sem; ··· 79 80 SCHED_EVENT_RUN, 80 81 SCHED_EVENT_SLEEP, 81 82 SCHED_EVENT_WAKEUP, 82 - SCHED_EVENT_MIGRATION, 83 83 }; 84 84 85 85 struct sched_atom { 86 86 enum sched_event_type type; 87 - int specific_wait; 88 87 u64 timestamp; 89 88 u64 duration; 90 89 unsigned long nr; ··· 225 228 bool show_wakeups; 226 229 bool show_next; 227 230 bool show_migrations; 231 + bool pre_migrations; 228 232 bool show_state; 229 233 bool show_prio; 230 234 u64 skipped_samples; ··· 245 247 u64 dt_iowait; /* time between CPU access by iowait (off cpu) */ 246 248 u64 dt_preempt; /* time between CPU access by preempt (off cpu) */ 247 249 u64 dt_delay; /* time between wakeup and sched-in */ 250 + u64 dt_pre_mig; /* time between migration and wakeup */ 248 251 u64 ready_to_run; /* time of wakeup */ 252 + u64 migrated; /* time when a thread is migrated */ 249 253 250 254 struct stats run_stats; 251 255 u64 total_run_time; ··· 255 255 u64 total_iowait_time; 256 256 u64 total_preempt_time; 257 257 u64 total_delay_time; 258 + u64 total_pre_mig_time; 258 259 259 260 char last_state; 260 261 ··· 422 421 423 422 wakee_event->wait_sem = zalloc(sizeof(*wakee_event->wait_sem)); 424 423 sem_init(wakee_event->wait_sem, 0, 0); 425 - wakee_event->specific_wait = 1; 426 424 event->wait_sem = wakee_event->wait_sem; 427 425 428 426 sched->nr_wakeup_events++; 429 427 } 430 428 431 429 static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *task, 432 - u64 timestamp, const char task_state __maybe_unused) 430 + u64 timestamp) 433 431 { 434 432 struct sched_atom *event = get_new_event(task, timestamp); 435 433 ··· 468 468 * every task starts in sleeping state - this gets ignored 469 469 * if there's no wakeup pointing to this sleep state: 470 470 */ 471 - add_sched_event_sleep(sched, task, 0, 0); 471 + add_sched_event_sleep(sched, task, 0); 472 472 473 473 sched->pid_to_task[pid] = task; 474 474 sched->nr_tasks++; ··· 528 528 if (atom->wait_sem) 529 529 ret = sem_post(atom->wait_sem); 530 530 BUG_ON(ret); 531 - break; 532 - case SCHED_EVENT_MIGRATION: 533 531 break; 534 532 default: 535 533 BUG_ON(1); ··· 671 673 parms->task = task = sched->tasks[i]; 672 674 parms->sched = sched; 673 675 parms->fd = self_open_counters(sched, i); 674 - sem_init(&task->sleep_sem, 0, 0); 675 676 sem_init(&task->ready_for_work, 0, 0); 676 677 sem_init(&task->work_done_sem, 0, 0); 677 678 task->curr_event = 0; ··· 694 697 task = sched->tasks[i]; 695 698 err = pthread_join(task->thread, NULL); 696 699 BUG_ON(err); 697 - sem_destroy(&task->sleep_sem); 698 700 sem_destroy(&task->ready_for_work); 699 701 sem_destroy(&task->work_done_sem); 700 702 } ··· 747 751 748 752 for (i = 0; i < sched->nr_tasks; i++) { 749 753 task = sched->tasks[i]; 750 - sem_init(&task->sleep_sem, 0, 0); 751 754 task->curr_event = 0; 752 755 } 753 756 } ··· 847 852 *next_comm = evsel__strval(evsel, sample, "next_comm"); 848 853 const u32 prev_pid = evsel__intval(evsel, sample, "prev_pid"), 849 854 next_pid = evsel__intval(evsel, sample, "next_pid"); 850 - const char prev_state = evsel__taskstate(evsel, sample, "prev_state"); 851 855 struct task_desc *prev, __maybe_unused *next; 852 856 u64 timestamp0, timestamp = sample->time; 853 857 int cpu = sample->cpu; ··· 878 884 sched->cpu_last_switched[cpu] = timestamp; 879 885 880 886 add_sched_event_run(sched, prev, timestamp, delta); 881 - add_sched_event_sleep(sched, prev, timestamp, prev_state); 887 + add_sched_event_sleep(sched, prev, timestamp); 882 888 883 889 return 0; 884 890 } ··· 1743 1749 } 1744 1750 1745 1751 if (sched->map.comp && new_cpu) 1746 - color_fprintf(stdout, color, " (CPU %d)", this_cpu); 1752 + color_fprintf(stdout, color, " (CPU %d)", this_cpu.cpu); 1747 1753 1748 1754 if (proceed != 1) { 1749 1755 color_fprintf(stdout, color, "\n"); ··· 2077 2083 printf(" "); 2078 2084 } 2079 2085 2080 - if (sched->show_prio) { 2081 - printf(" %-*s %-*s %9s %9s %9s", 2082 - comm_width, "task name", MAX_PRIO_STR_LEN, "prio", 2083 - "wait time", "sch delay", "run time"); 2084 - } else { 2085 - printf(" %-*s %9s %9s %9s", comm_width, 2086 - "task name", "wait time", "sch delay", "run time"); 2087 - } 2086 + printf(" %-*s", comm_width, "task name"); 2087 + 2088 + if (sched->show_prio) 2089 + printf(" %-*s", MAX_PRIO_STR_LEN, "prio"); 2090 + 2091 + printf(" %9s %9s %9s", "wait time", "sch delay", "run time"); 2092 + 2093 + if (sched->pre_migrations) 2094 + printf(" %9s", "pre-mig time"); 2088 2095 2089 2096 if (sched->show_state) 2090 2097 printf(" %s", "state"); ··· 2100 2105 if (sched->show_cpu_visual) 2101 2106 printf(" %*s ", ncpus, ""); 2102 2107 2103 - if (sched->show_prio) { 2104 - printf(" %-*s %-*s %9s %9s %9s", 2105 - comm_width, "[tid/pid]", MAX_PRIO_STR_LEN, "", 2106 - "(msec)", "(msec)", "(msec)"); 2107 - } else { 2108 - printf(" %-*s %9s %9s %9s", comm_width, 2109 - "[tid/pid]", "(msec)", "(msec)", "(msec)"); 2110 - } 2108 + printf(" %-*s", comm_width, "[tid/pid]"); 2111 2109 2112 - if (sched->show_state) 2113 - printf(" %5s", ""); 2110 + if (sched->show_prio) 2111 + printf(" %-*s", MAX_PRIO_STR_LEN, ""); 2112 + 2113 + printf(" %9s %9s %9s", "(msec)", "(msec)", "(msec)"); 2114 + 2115 + if (sched->pre_migrations) 2116 + printf(" %9s", "(msec)"); 2114 2117 2115 2118 printf("\n"); 2116 2119 ··· 2120 2127 if (sched->show_cpu_visual) 2121 2128 printf(" %.*s ", ncpus, graph_dotted_line); 2122 2129 2123 - if (sched->show_prio) { 2124 - printf(" %.*s %.*s %.9s %.9s %.9s", 2125 - comm_width, graph_dotted_line, MAX_PRIO_STR_LEN, graph_dotted_line, 2126 - graph_dotted_line, graph_dotted_line, graph_dotted_line); 2127 - } else { 2128 - printf(" %.*s %.9s %.9s %.9s", comm_width, 2129 - graph_dotted_line, graph_dotted_line, graph_dotted_line, 2130 - graph_dotted_line); 2131 - } 2130 + printf(" %.*s", comm_width, graph_dotted_line); 2131 + 2132 + if (sched->show_prio) 2133 + printf(" %.*s", MAX_PRIO_STR_LEN, graph_dotted_line); 2134 + 2135 + printf(" %.9s %.9s %.9s", graph_dotted_line, graph_dotted_line, graph_dotted_line); 2136 + 2137 + if (sched->pre_migrations) 2138 + printf(" %.9s", graph_dotted_line); 2132 2139 2133 2140 if (sched->show_state) 2134 2141 printf(" %.5s", graph_dotted_line); ··· 2183 2190 2184 2191 print_sched_time(tr->dt_delay, 6); 2185 2192 print_sched_time(tr->dt_run, 6); 2193 + if (sched->pre_migrations) 2194 + print_sched_time(tr->dt_pre_mig, 6); 2186 2195 2187 2196 if (sched->show_state) 2188 2197 printf(" %5c ", thread__tid(thread) == 0 ? 'I' : state); ··· 2222 2227 * last_time = time of last sched change event for current task 2223 2228 * (i.e, time process was last scheduled out) 2224 2229 * ready_to_run = time of wakeup for current task 2230 + * migrated = time of task migration to another CPU 2225 2231 * 2226 - * -----|------------|------------|------------|------ 2227 - * last ready tprev t 2232 + * -----|-------------|-------------|-------------|-------------|----- 2233 + * last ready migrated tprev t 2228 2234 * time to run 2229 2235 * 2230 - * |-------- dt_wait --------| 2231 - * |- dt_delay -|-- dt_run --| 2236 + * |---------------- dt_wait ----------------| 2237 + * |--------- dt_delay ---------|-- dt_run --| 2238 + * |- dt_pre_mig -| 2232 2239 * 2233 - * dt_run = run time of current task 2234 - * dt_wait = time between last schedule out event for task and tprev 2235 - * represents time spent off the cpu 2236 - * dt_delay = time between wakeup and schedule-in of task 2240 + * dt_run = run time of current task 2241 + * dt_wait = time between last schedule out event for task and tprev 2242 + * represents time spent off the cpu 2243 + * dt_delay = time between wakeup and schedule-in of task 2244 + * dt_pre_mig = time between wakeup and migration to another CPU 2237 2245 */ 2238 2246 2239 2247 static void timehist_update_runtime_stats(struct thread_runtime *r, ··· 2247 2249 r->dt_iowait = 0; 2248 2250 r->dt_preempt = 0; 2249 2251 r->dt_run = 0; 2252 + r->dt_pre_mig = 0; 2250 2253 2251 2254 if (tprev) { 2252 2255 r->dt_run = t - tprev; ··· 2256 2257 pr_debug("time travel: wakeup time for task > previous sched_switch event\n"); 2257 2258 else 2258 2259 r->dt_delay = tprev - r->ready_to_run; 2260 + 2261 + if ((r->migrated > r->ready_to_run) && (r->migrated < tprev)) 2262 + r->dt_pre_mig = r->migrated - r->ready_to_run; 2259 2263 } 2260 2264 2261 2265 if (r->last_time > tprev) ··· 2282 2280 r->total_sleep_time += r->dt_sleep; 2283 2281 r->total_iowait_time += r->dt_iowait; 2284 2282 r->total_preempt_time += r->dt_preempt; 2283 + r->total_pre_mig_time += r->dt_pre_mig; 2285 2284 } 2286 2285 2287 2286 static bool is_idle_sample(struct perf_sample *sample, ··· 2696 2693 return -1; 2697 2694 2698 2695 tr->migrations++; 2696 + tr->migrated = sample->time; 2699 2697 2700 2698 /* show migrations if requested */ 2701 - timehist_print_migration_event(sched, evsel, sample, machine, thread); 2699 + if (sched->show_migrations) { 2700 + timehist_print_migration_event(sched, evsel, sample, 2701 + machine, thread); 2702 + } 2702 2703 2703 2704 return 0; 2704 2705 } ··· 2853 2846 /* last state is used to determine where to account wait time */ 2854 2847 tr->last_state = state; 2855 2848 2856 - /* sched out event for task so reset ready to run time */ 2849 + /* sched out event for task so reset ready to run time and migrated time */ 2857 2850 if (state == 'R') 2858 2851 tr->ready_to_run = t; 2859 2852 else 2860 2853 tr->ready_to_run = 0; 2854 + 2855 + tr->migrated = 0; 2861 2856 } 2862 2857 2863 2858 evsel__save_time(evsel, sample->time, sample->cpu); ··· 3299 3290 goto out; 3300 3291 } 3301 3292 3302 - if (sched->show_migrations && 3303 - perf_session__set_tracepoints_handlers(session, migrate_handlers)) 3293 + if ((sched->show_migrations || sched->pre_migrations) && 3294 + perf_session__set_tracepoints_handlers(session, migrate_handlers)) 3304 3295 goto out; 3305 3296 3306 3297 /* pre-allocate struct for per-CPU idle stats */ ··· 3842 3833 OPT_BOOLEAN(0, "show-prio", &sched.show_prio, "Show task priority"), 3843 3834 OPT_STRING(0, "prio", &sched.prio_str, "prio", 3844 3835 "analyze events only for given task priority(ies)"), 3836 + OPT_BOOLEAN('P', "pre-migrations", &sched.pre_migrations, "Show pre-migration wait time"), 3845 3837 OPT_PARENT(sched_options) 3846 3838 }; 3847 3839
+5 -4
tools/perf/builtin-script.c
··· 67 67 68 68 #include <linux/ctype.h> 69 69 #ifdef HAVE_LIBTRACEEVENT 70 - #include <traceevent/event-parse.h> 70 + #include <event-parse.h> 71 71 #endif 72 72 73 73 static char const *script_name; ··· 1728 1728 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"}, 1729 1729 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vmentry"}, 1730 1730 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vmexit"}, 1731 + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_BRANCH_MISS, "br miss"}, 1731 1732 {0, NULL} 1732 1733 }; 1733 1734 ··· 2137 2136 }; 2138 2137 2139 2138 static void script_print_metric(struct perf_stat_config *config __maybe_unused, 2140 - void *ctx, const char *color, 2141 - const char *fmt, 2142 - const char *unit, double val) 2139 + void *ctx, enum metric_threshold_classify thresh, 2140 + const char *fmt, const char *unit, double val) 2143 2141 { 2144 2142 struct metric_ctx *mctx = ctx; 2143 + const char *color = metric_threshold_classify__color(thresh); 2145 2144 2146 2145 if (!fmt) 2147 2146 return;
+196 -202
tools/perf/builtin-stat.c
··· 46 46 #include "util/parse-events.h" 47 47 #include "util/pmus.h" 48 48 #include "util/pmu.h" 49 + #include "util/tool_pmu.h" 49 50 #include "util/event.h" 50 51 #include "util/evlist.h" 51 52 #include "util/evsel.h" ··· 295 294 * terminates. Use the wait4 values in that case. 296 295 */ 297 296 if (err && cpu_map_idx == 0 && 298 - (evsel__tool_event(counter) == PERF_TOOL_USER_TIME || 299 - evsel__tool_event(counter) == PERF_TOOL_SYSTEM_TIME)) { 297 + (evsel__tool_event(counter) == TOOL_PMU__EVENT_USER_TIME || 298 + evsel__tool_event(counter) == TOOL_PMU__EVENT_SYSTEM_TIME)) { 300 299 u64 val, *start_time; 301 300 struct perf_counts_values *count = 302 301 perf_counts(counter->counts, cpu_map_idx, thread); 303 302 304 303 start_time = xyarray__entry(counter->start_times, cpu_map_idx, thread); 305 - if (evsel__tool_event(counter) == PERF_TOOL_USER_TIME) 304 + if (evsel__tool_event(counter) == TOOL_PMU__EVENT_USER_TIME) 306 305 val = ru_stats.ru_utime_usec_stat.mean; 307 306 else 308 307 val = ru_stats.ru_stime_usec_stat.mean; ··· 640 639 * (behavior changed with commit b0a873e). 641 640 */ 642 641 if (errno == EINVAL || errno == ENOSYS || 643 - errno == ENOENT || errno == EOPNOTSUPP || 644 - errno == ENXIO) { 642 + errno == ENOENT || errno == ENXIO) { 645 643 if (verbose > 0) 646 644 ui__warning("%s event is not supported by the kernel.\n", 647 645 evsel__name(counter)); ··· 658 658 if (verbose > 0) 659 659 ui__warning("%s\n", msg); 660 660 return COUNTER_RETRY; 661 - } else if (target__has_per_thread(&target) && 661 + } else if (target__has_per_thread(&target) && errno != EOPNOTSUPP && 662 662 evsel_list->core.threads && 663 663 evsel_list->core.threads->err_thread != -1) { 664 664 /* ··· 677 677 counter->supported = false; 678 678 counter->errored = true; 679 679 return COUNTER_SKIP; 680 + } 681 + 682 + if (errno == EOPNOTSUPP) { 683 + if (verbose > 0) { 684 + ui__warning("%s event is not supported by the kernel.\n", 685 + evsel__name(counter)); 686 + } 687 + counter->supported = false; 688 + counter->errored = true; 689 + 690 + if ((evsel__leader(counter) != counter) || 691 + !(counter->core.leader->nr_members > 1)) 692 + return COUNTER_SKIP; 680 693 } 681 694 682 695 evsel__open_strerror(counter, &target, errno, msg, sizeof(msg)); ··· 729 716 } 730 717 731 718 if (!cpu_map__is_dummy(evsel_list->core.user_requested_cpus)) { 732 - if (affinity__setup(&saved_affinity) < 0) 733 - return -1; 719 + if (affinity__setup(&saved_affinity) < 0) { 720 + err = -1; 721 + goto err_out; 722 + } 734 723 affinity = &saved_affinity; 735 724 } 736 725 737 726 evlist__for_each_entry(evsel_list, counter) { 738 727 counter->reset_group = false; 739 - if (bpf_counter__load(counter, &target)) 740 - return -1; 728 + if (bpf_counter__load(counter, &target)) { 729 + err = -1; 730 + goto err_out; 731 + } 741 732 if (!(evsel__is_bperf(counter))) 742 733 all_counters_use_bpf = false; 743 734 } ··· 784 767 785 768 switch (stat_handle_error(counter)) { 786 769 case COUNTER_FATAL: 787 - return -1; 770 + err = -1; 771 + goto err_out; 788 772 case COUNTER_RETRY: 789 773 goto try_again; 790 774 case COUNTER_SKIP: ··· 826 808 827 809 switch (stat_handle_error(counter)) { 828 810 case COUNTER_FATAL: 829 - return -1; 811 + err = -1; 812 + goto err_out; 830 813 case COUNTER_RETRY: 831 814 goto try_again_reset; 832 815 case COUNTER_SKIP: ··· 840 821 } 841 822 } 842 823 affinity__cleanup(affinity); 824 + affinity = NULL; 843 825 844 826 evlist__for_each_entry(evsel_list, counter) { 845 827 if (!counter->supported) { ··· 853 833 stat_config.unit_width = l; 854 834 855 835 if (evsel__should_store_id(counter) && 856 - evsel__store_ids(counter, evsel_list)) 857 - return -1; 836 + evsel__store_ids(counter, evsel_list)) { 837 + err = -1; 838 + goto err_out; 839 + } 858 840 } 859 841 860 842 if (evlist__apply_filters(evsel_list, &counter, &target)) { ··· 877 855 } 878 856 879 857 if (err < 0) 880 - return err; 858 + goto err_out; 881 859 882 860 err = perf_event__synthesize_stat_events(&stat_config, NULL, evsel_list, 883 861 process_synthesized_event, is_pipe); 884 862 if (err < 0) 885 - return err; 863 + goto err_out; 864 + 886 865 } 887 866 888 867 if (target.initial_delay) { 889 868 pr_info(EVLIST_DISABLED_MSG); 890 869 } else { 891 870 err = enable_counters(); 892 - if (err) 893 - return -1; 871 + if (err) { 872 + err = -1; 873 + goto err_out; 874 + } 894 875 } 895 876 896 877 /* Exec the command, if any */ ··· 903 878 if (target.initial_delay > 0) { 904 879 usleep(target.initial_delay * USEC_PER_MSEC); 905 880 err = enable_counters(); 906 - if (err) 907 - return -1; 881 + if (err) { 882 + err = -1; 883 + goto err_out; 884 + } 908 885 909 886 pr_info(EVLIST_ENABLED_MSG); 910 887 } ··· 926 899 if (workload_exec_errno) { 927 900 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 928 901 pr_err("Workload failed: %s\n", emsg); 929 - return -1; 902 + err = -1; 903 + goto err_out; 930 904 } 931 905 932 906 if (WIFSIGNALED(status)) ··· 974 946 evlist__close(evsel_list); 975 947 976 948 return WEXITSTATUS(status); 949 + 950 + err_out: 951 + if (forks) 952 + evlist__cancel_workload(evsel_list); 953 + 954 + affinity__cleanup(affinity); 955 + return err; 977 956 } 978 957 958 + /* 959 + * Returns -1 for fatal errors which signifies to not continue 960 + * when in repeat mode. 961 + * 962 + * Returns < -1 error codes when stat record is used. These 963 + * result in the stat information being displayed, but writing 964 + * to the file fails and is non fatal. 965 + */ 979 966 static int run_perf_stat(int argc, const char **argv, int run_idx) 980 967 { 981 968 int ret; ··· 1857 1814 } 1858 1815 1859 1816 /* 1860 - * Add default attributes, if there were no attributes specified or 1817 + * Add default events, if there were no attributes specified or 1861 1818 * if -d/--detailed, -d -d or -d -d -d is used: 1862 1819 */ 1863 - static int add_default_attributes(void) 1820 + static int add_default_events(void) 1864 1821 { 1865 - struct perf_event_attr default_attrs0[] = { 1866 - 1867 - { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 1868 - { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES }, 1869 - { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 1870 - { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 1871 - 1872 - { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 1873 - }; 1874 - struct perf_event_attr frontend_attrs[] = { 1875 - { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, 1876 - }; 1877 - struct perf_event_attr backend_attrs[] = { 1878 - { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, 1879 - }; 1880 - struct perf_event_attr default_attrs1[] = { 1881 - { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 1882 - { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, 1883 - { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES }, 1884 - 1885 - }; 1886 - 1887 - /* 1888 - * Detailed stats (-d), covering the L1 and last level data caches: 1889 - */ 1890 - struct perf_event_attr detailed_attrs[] = { 1891 - 1892 - { .type = PERF_TYPE_HW_CACHE, 1893 - .config = 1894 - PERF_COUNT_HW_CACHE_L1D << 0 | 1895 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1896 - (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1897 - 1898 - { .type = PERF_TYPE_HW_CACHE, 1899 - .config = 1900 - PERF_COUNT_HW_CACHE_L1D << 0 | 1901 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1902 - (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1903 - 1904 - { .type = PERF_TYPE_HW_CACHE, 1905 - .config = 1906 - PERF_COUNT_HW_CACHE_LL << 0 | 1907 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1908 - (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1909 - 1910 - { .type = PERF_TYPE_HW_CACHE, 1911 - .config = 1912 - PERF_COUNT_HW_CACHE_LL << 0 | 1913 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1914 - (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1915 - }; 1916 - 1917 - /* 1918 - * Very detailed stats (-d -d), covering the instruction cache and the TLB caches: 1919 - */ 1920 - struct perf_event_attr very_detailed_attrs[] = { 1921 - 1922 - { .type = PERF_TYPE_HW_CACHE, 1923 - .config = 1924 - PERF_COUNT_HW_CACHE_L1I << 0 | 1925 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1926 - (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1927 - 1928 - { .type = PERF_TYPE_HW_CACHE, 1929 - .config = 1930 - PERF_COUNT_HW_CACHE_L1I << 0 | 1931 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1932 - (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1933 - 1934 - { .type = PERF_TYPE_HW_CACHE, 1935 - .config = 1936 - PERF_COUNT_HW_CACHE_DTLB << 0 | 1937 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1938 - (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1939 - 1940 - { .type = PERF_TYPE_HW_CACHE, 1941 - .config = 1942 - PERF_COUNT_HW_CACHE_DTLB << 0 | 1943 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1944 - (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1945 - 1946 - { .type = PERF_TYPE_HW_CACHE, 1947 - .config = 1948 - PERF_COUNT_HW_CACHE_ITLB << 0 | 1949 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1950 - (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1951 - 1952 - { .type = PERF_TYPE_HW_CACHE, 1953 - .config = 1954 - PERF_COUNT_HW_CACHE_ITLB << 0 | 1955 - (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1956 - (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1957 - 1958 - }; 1959 - 1960 - /* 1961 - * Very, very detailed stats (-d -d -d), adding prefetch events: 1962 - */ 1963 - struct perf_event_attr very_very_detailed_attrs[] = { 1964 - 1965 - { .type = PERF_TYPE_HW_CACHE, 1966 - .config = 1967 - PERF_COUNT_HW_CACHE_L1D << 0 | 1968 - (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 1969 - (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1970 - 1971 - { .type = PERF_TYPE_HW_CACHE, 1972 - .config = 1973 - PERF_COUNT_HW_CACHE_L1D << 0 | 1974 - (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 1975 - (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1976 - }; 1977 - 1978 - struct perf_event_attr default_null_attrs[] = {}; 1979 1822 const char *pmu = parse_events_option_args.pmu_filter ?: "all"; 1823 + struct parse_events_error err; 1824 + struct evlist *evlist = evlist__new(); 1825 + struct evsel *evsel; 1826 + int ret = 0; 1827 + 1828 + if (!evlist) 1829 + return -ENOMEM; 1830 + 1831 + parse_events_error__init(&err); 1980 1832 1981 1833 /* Set attrs if no event is selected and !null_run: */ 1982 1834 if (stat_config.null_run) 1983 - return 0; 1835 + goto out; 1984 1836 1985 1837 if (transaction_run) { 1986 1838 /* Handle -T as -M transaction. Once platform specific metrics ··· 1885 1947 */ 1886 1948 if (!metricgroup__has_metric(pmu, "transaction")) { 1887 1949 pr_err("Missing transaction metrics\n"); 1888 - return -1; 1950 + ret = -1; 1951 + goto out; 1889 1952 } 1890 - return metricgroup__parse_groups(evsel_list, pmu, "transaction", 1953 + ret = metricgroup__parse_groups(evlist, pmu, "transaction", 1891 1954 stat_config.metric_no_group, 1892 1955 stat_config.metric_no_merge, 1893 1956 stat_config.metric_no_threshold, ··· 1896 1957 stat_config.system_wide, 1897 1958 stat_config.hardware_aware_grouping, 1898 1959 &stat_config.metric_events); 1960 + goto out; 1899 1961 } 1900 1962 1901 1963 if (smi_cost) { ··· 1904 1964 1905 1965 if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) { 1906 1966 pr_err("freeze_on_smi is not supported.\n"); 1907 - return -1; 1967 + ret = -1; 1968 + goto out; 1908 1969 } 1909 1970 1910 1971 if (!smi) { 1911 1972 if (sysfs__write_int(FREEZE_ON_SMI_PATH, 1) < 0) { 1912 - fprintf(stderr, "Failed to set freeze_on_smi.\n"); 1913 - return -1; 1973 + pr_err("Failed to set freeze_on_smi.\n"); 1974 + ret = -1; 1975 + goto out; 1914 1976 } 1915 1977 smi_reset = true; 1916 1978 } 1917 1979 1918 1980 if (!metricgroup__has_metric(pmu, "smi")) { 1919 1981 pr_err("Missing smi metrics\n"); 1920 - return -1; 1982 + ret = -1; 1983 + goto out; 1921 1984 } 1922 1985 1923 1986 if (!force_metric_only) 1924 1987 stat_config.metric_only = true; 1925 1988 1926 - return metricgroup__parse_groups(evsel_list, pmu, "smi", 1989 + ret = metricgroup__parse_groups(evlist, pmu, "smi", 1927 1990 stat_config.metric_no_group, 1928 1991 stat_config.metric_no_merge, 1929 1992 stat_config.metric_no_threshold, ··· 1934 1991 stat_config.system_wide, 1935 1992 stat_config.hardware_aware_grouping, 1936 1993 &stat_config.metric_events); 1994 + goto out; 1937 1995 } 1938 1996 1939 1997 if (topdown_run) { ··· 1947 2003 if (!max_level) { 1948 2004 pr_err("Topdown requested but the topdown metric groups aren't present.\n" 1949 2005 "(See perf list the metric groups have names like TopdownL1)\n"); 1950 - return -1; 2006 + ret = -1; 2007 + goto out; 1951 2008 } 1952 2009 if (stat_config.topdown_level > max_level) { 1953 2010 pr_err("Invalid top-down metrics level. The max level is %u.\n", max_level); 1954 - return -1; 1955 - } else if (!stat_config.topdown_level) 2011 + ret = -1; 2012 + goto out; 2013 + } else if (!stat_config.topdown_level) { 1956 2014 stat_config.topdown_level = 1; 1957 - 2015 + } 1958 2016 if (!stat_config.interval && !stat_config.metric_only) { 1959 2017 fprintf(stat_config.output, 1960 2018 "Topdown accuracy may decrease when measuring long periods.\n" 1961 2019 "Please print the result regularly, e.g. -I1000\n"); 1962 2020 } 1963 2021 str[8] = stat_config.topdown_level + '0'; 1964 - if (metricgroup__parse_groups(evsel_list, 2022 + if (metricgroup__parse_groups(evlist, 1965 2023 pmu, str, 1966 2024 /*metric_no_group=*/false, 1967 2025 /*metric_no_merge=*/false, ··· 1971 2025 stat_config.user_requested_cpu_list, 1972 2026 stat_config.system_wide, 1973 2027 stat_config.hardware_aware_grouping, 1974 - &stat_config.metric_events) < 0) 1975 - return -1; 2028 + &stat_config.metric_events) < 0) { 2029 + ret = -1; 2030 + goto out; 2031 + } 1976 2032 } 1977 2033 1978 2034 if (!stat_config.topdown_level) 1979 2035 stat_config.topdown_level = 1; 1980 2036 1981 - if (!evsel_list->core.nr_entries) { 2037 + if (!evlist->core.nr_entries && !evsel_list->core.nr_entries) { 1982 2038 /* No events so add defaults. */ 1983 2039 if (target__has_cpu(&target)) 1984 - default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; 2040 + ret = parse_events(evlist, "cpu-clock", &err); 2041 + else 2042 + ret = parse_events(evlist, "task-clock", &err); 2043 + if (ret) 2044 + goto out; 1985 2045 1986 - if (evlist__add_default_attrs(evsel_list, default_attrs0) < 0) 1987 - return -1; 1988 - if (perf_pmus__have_event("cpu", "stalled-cycles-frontend")) { 1989 - if (evlist__add_default_attrs(evsel_list, frontend_attrs) < 0) 1990 - return -1; 1991 - } 1992 - if (perf_pmus__have_event("cpu", "stalled-cycles-backend")) { 1993 - if (evlist__add_default_attrs(evsel_list, backend_attrs) < 0) 1994 - return -1; 1995 - } 1996 - if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0) 1997 - return -1; 2046 + ret = parse_events(evlist, 2047 + "context-switches," 2048 + "cpu-migrations," 2049 + "page-faults," 2050 + "instructions," 2051 + "cycles," 2052 + "stalled-cycles-frontend," 2053 + "stalled-cycles-backend," 2054 + "branches," 2055 + "branch-misses", 2056 + &err); 2057 + if (ret) 2058 + goto out; 2059 + 1998 2060 /* 1999 2061 * Add TopdownL1 metrics if they exist. To minimize 2000 2062 * multiplexing, don't request threshold computation. 2001 2063 */ 2002 2064 if (metricgroup__has_metric(pmu, "Default")) { 2003 2065 struct evlist *metric_evlist = evlist__new(); 2004 - struct evsel *metric_evsel; 2005 2066 2006 - if (!metric_evlist) 2007 - return -1; 2008 - 2067 + if (!metric_evlist) { 2068 + ret = -ENOMEM; 2069 + goto out; 2070 + } 2009 2071 if (metricgroup__parse_groups(metric_evlist, pmu, "Default", 2010 2072 /*metric_no_group=*/false, 2011 2073 /*metric_no_merge=*/false, ··· 2021 2067 stat_config.user_requested_cpu_list, 2022 2068 stat_config.system_wide, 2023 2069 stat_config.hardware_aware_grouping, 2024 - &stat_config.metric_events) < 0) 2025 - return -1; 2026 - 2027 - evlist__for_each_entry(metric_evlist, metric_evsel) { 2028 - metric_evsel->skippable = true; 2029 - metric_evsel->default_metricgroup = true; 2070 + &stat_config.metric_events) < 0) { 2071 + ret = -1; 2072 + goto out; 2030 2073 } 2031 - evlist__splice_list_tail(evsel_list, &metric_evlist->core.entries); 2074 + 2075 + evlist__for_each_entry(metric_evlist, evsel) 2076 + evsel->default_metricgroup = true; 2077 + 2078 + evlist__splice_list_tail(evlist, &metric_evlist->core.entries); 2032 2079 evlist__delete(metric_evlist); 2033 2080 } 2034 - 2035 - /* Platform specific attrs */ 2036 - if (evlist__add_default_attrs(evsel_list, default_null_attrs) < 0) 2037 - return -1; 2038 2081 } 2039 2082 2040 2083 /* Detailed events get appended to the event list: */ 2041 2084 2042 - if (detailed_run < 1) 2043 - return 0; 2044 - 2045 - /* Append detailed run extra attributes: */ 2046 - if (evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) 2047 - return -1; 2048 - 2049 - if (detailed_run < 2) 2050 - return 0; 2051 - 2052 - /* Append very detailed run extra attributes: */ 2053 - if (evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) 2054 - return -1; 2055 - 2056 - if (detailed_run < 3) 2057 - return 0; 2058 - 2059 - /* Append very, very detailed run extra attributes: */ 2060 - return evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); 2085 + if (!ret && detailed_run >= 1) { 2086 + /* 2087 + * Detailed stats (-d), covering the L1 and last level data 2088 + * caches: 2089 + */ 2090 + ret = parse_events(evlist, 2091 + "L1-dcache-loads," 2092 + "L1-dcache-load-misses," 2093 + "LLC-loads," 2094 + "LLC-load-misses", 2095 + &err); 2096 + } 2097 + if (!ret && detailed_run >= 2) { 2098 + /* 2099 + * Very detailed stats (-d -d), covering the instruction cache 2100 + * and the TLB caches: 2101 + */ 2102 + ret = parse_events(evlist, 2103 + "L1-icache-loads," 2104 + "L1-icache-load-misses," 2105 + "dTLB-loads," 2106 + "dTLB-load-misses," 2107 + "iTLB-loads," 2108 + "iTLB-load-misses", 2109 + &err); 2110 + } 2111 + if (!ret && detailed_run >= 3) { 2112 + /* 2113 + * Very, very detailed stats (-d -d -d), adding prefetch events: 2114 + */ 2115 + ret = parse_events(evlist, 2116 + "L1-dcache-prefetches," 2117 + "L1-dcache-prefetch-misses", 2118 + &err); 2119 + } 2120 + out: 2121 + if (!ret) { 2122 + evlist__for_each_entry(evlist, evsel) { 2123 + /* 2124 + * Make at least one event non-skippable so fatal errors are visible. 2125 + * 'cycles' always used to be default and non-skippable, so use that. 2126 + */ 2127 + if (strcmp("cycles", evsel__name(evsel))) 2128 + evsel->skippable = true; 2129 + } 2130 + } 2131 + parse_events_error__exit(&err); 2132 + evlist__splice_list_tail(evsel_list, &evlist->core.entries); 2133 + evlist__delete(evlist); 2134 + return ret; 2061 2135 } 2062 2136 2063 2137 static const char * const stat_record_usage[] = { ··· 2573 2591 goto out; 2574 2592 } 2575 2593 2594 + if (stat_config.csv_output || (stat_config.metric_only && stat_config.json_output)) { 2595 + /* 2596 + * Current CSV and metric-only JSON output doesn't display the 2597 + * metric threshold so don't compute it. 2598 + */ 2599 + stat_config.metric_no_threshold = true; 2600 + } 2601 + 2576 2602 if (stat_config.walltime_run_table && stat_config.run_count <= 1) { 2577 2603 fprintf(stderr, "--table is only supported with -r\n"); 2578 2604 parse_options_usage(stat_usage, stat_options, "r", 1); ··· 2641 2651 } else if (big_num_opt == 0) /* User passed --no-big-num */ 2642 2652 stat_config.big_num = false; 2643 2653 2654 + target.inherit = !stat_config.no_inherit; 2644 2655 err = target__validate(&target); 2645 2656 if (err) { 2646 2657 target__strerror(&target, err, errbuf, BUFSIZ); ··· 2751 2760 } 2752 2761 } 2753 2762 2754 - if (add_default_attributes()) 2763 + if (add_default_events()) 2755 2764 goto out; 2756 2765 2757 2766 if (stat_config.cgroup_list) { ··· 2870 2879 evlist__reset_prev_raw_counts(evsel_list); 2871 2880 2872 2881 status = run_perf_stat(argc, argv, run_idx); 2873 - if (forever && status != -1 && !interval) { 2882 + if (status == -1) 2883 + break; 2884 + 2885 + if (forever && !interval) { 2874 2886 print_counters(NULL, argc, argv); 2875 2887 perf_stat__reset_stats(); 2876 2888 }
+1 -2
tools/perf/builtin-timechart.c
··· 38 38 #include "util/tracepoint.h" 39 39 #include "util/util.h" 40 40 #include <linux/err.h> 41 - #include <traceevent/event-parse.h> 41 + #include <event-parse.h> 42 42 43 43 #ifdef LACKS_OPEN_MEMSTREAM_PROTOTYPE 44 44 FILE *open_memstream(char **ptr, size_t *sizeloc); ··· 1158 1158 } 1159 1159 1160 1160 svg_box(Y, c->start_time, c->end_time, "process3"); 1161 - sample = c->io_samples; 1162 1161 for (sample = c->io_samples; sample; sample = sample->next) { 1163 1162 double h = (double)sample->bytes / c->max_bytes; 1164 1163
+15 -12
tools/perf/builtin-trace.c
··· 88 88 #include <perf/mmap.h> 89 89 90 90 #ifdef HAVE_LIBTRACEEVENT 91 - #include <traceevent/event-parse.h> 91 + #include <event-parse.h> 92 92 #endif 93 93 94 94 #ifndef O_CLOEXEC ··· 1873 1873 switch (event->header.type) { 1874 1874 case PERF_RECORD_LOST: 1875 1875 color_fprintf(trace->output, PERF_COLOR_RED, 1876 - "LOST %" PRIu64 " events!\n", event->lost.lost); 1876 + "LOST %" PRIu64 " events!\n", (u64)event->lost.lost); 1877 1877 ret = machine__process_lost_event(machine, event, sample); 1878 1878 break; 1879 1879 default: ··· 2702 2702 char msg[1024]; 2703 2703 void *args, *augmented_args = NULL; 2704 2704 int augmented_args_size; 2705 + size_t printed = 0; 2705 2706 2706 2707 if (sc == NULL) 2707 2708 return -1; ··· 2718 2717 2719 2718 args = perf_evsel__sc_tp_ptr(evsel, args, sample); 2720 2719 augmented_args = syscall__augmented_args(sc, sample, &augmented_args_size, trace->raw_augmented_syscalls_args_size); 2721 - syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread); 2722 - fprintf(trace->output, "%s", msg); 2720 + printed += syscall__scnprintf_args(sc, msg, sizeof(msg), args, augmented_args, augmented_args_size, trace, thread); 2721 + fprintf(trace->output, "%.*s", (int)printed, msg); 2723 2722 err = 0; 2724 2723 out_put: 2725 2724 thread__put(thread); ··· 3088 3087 printed += syscall_arg_fmt__scnprintf_val(arg, bf + printed, size - printed, &syscall_arg, val); 3089 3088 } 3090 3089 3091 - return printed + fprintf(trace->output, "%s", bf); 3090 + return printed + fprintf(trace->output, "%.*s", (int)printed, bf); 3092 3091 } 3093 3092 3094 3093 static int trace__event_handler(struct trace *trace, struct evsel *evsel, ··· 3097 3096 { 3098 3097 struct thread *thread; 3099 3098 int callchain_ret = 0; 3100 - /* 3101 - * Check if we called perf_evsel__disable(evsel) due to, for instance, 3102 - * this event's max_events having been hit and this is an entry coming 3103 - * from the ring buffer that we should discard, since the max events 3104 - * have already been considered/printed. 3105 - */ 3106 - if (evsel->disabled) 3099 + 3100 + if (evsel->nr_events_printed >= evsel->max_events) 3107 3101 return 0; 3108 3102 3109 3103 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); ··· 4322 4326 sizeof(__u32), BPF_ANY); 4323 4327 } 4324 4328 } 4329 + 4330 + if (trace->skel) 4331 + trace->filter_pids.map = trace->skel->maps.pids_filtered; 4325 4332 #endif 4326 4333 err = trace__set_filter_pids(trace); 4327 4334 if (err < 0) ··· 5447 5448 /* summary_only implies summary option, but don't overwrite summary if set */ 5448 5449 if (trace.summary_only) 5449 5450 trace.summary = trace.summary_only; 5451 + 5452 + /* Keep exited threads, otherwise information might be lost for summary */ 5453 + if (trace.summary) 5454 + symbol_conf.keep_exited_threads = true; 5450 5455 5451 5456 if (output_name != NULL) { 5452 5457 err = trace__open_output(&trace, output_name);
+1 -1
tools/perf/dlfilters/dlfilter-test-api-v0.c
··· 220 220 CHECK_SAMPLE(raw_callchain_nr); 221 221 CHECK(!sample->raw_callchain); 222 222 223 - #define EVENT_NAME "branches:" 223 + #define EVENT_NAME "branches" 224 224 CHECK(!strncmp(sample->event, EVENT_NAME, strlen(EVENT_NAME))); 225 225 226 226 return 0;
+1 -1
tools/perf/dlfilters/dlfilter-test-api-v2.c
··· 235 235 CHECK_SAMPLE(raw_callchain_nr); 236 236 CHECK(!sample->raw_callchain); 237 237 238 - #define EVENT_NAME "branches:" 238 + #define EVENT_NAME "branches" 239 239 CHECK(!strncmp(sample->event, EVENT_NAME, strlen(EVENT_NAME))); 240 240 241 241 return 0;
-2
tools/perf/perf.c
··· 542 542 } 543 543 cmd = argv[0]; 544 544 545 - test_attr__init(); 546 - 547 545 /* 548 546 * We use PATH to find perf commands, but we prepend some higher 549 547 * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH
+9
tools/perf/pmu-events/arch/arm64/freescale/imx91/sys/ddrc.json
··· 1 + [ 2 + { 3 + "BriefDescription": "ddr cycles event", 4 + "EventCode": "0x00", 5 + "EventName": "imx91_ddr.cycles", 6 + "Unit": "imx9_ddr", 7 + "Compat": "imx91" 8 + } 9 + ]
+26
tools/perf/pmu-events/arch/arm64/freescale/imx91/sys/metrics.json
··· 1 + [ 2 + { 3 + "BriefDescription": "bandwidth usage for lpddr4 evk board", 4 + "MetricName": "imx91_bandwidth_usage.lpddr4", 5 + "MetricExpr": "(((( imx9_ddr0@ddrc_pm_0@ ) * 2 * 8 ) + (( imx9_ddr0@ddrc_pm_3@ + imx9_ddr0@ddrc_pm_5@ + imx9_ddr0@ddrc_pm_7@ + imx9_ddr0@ddrc_pm_9@ - imx9_ddr0@ddrc_pm_2@ - imx9_ddr0@ddrc_pm_4@ - imx9_ddr0@ddrc_pm_6@ - imx9_ddr0@ddrc_pm_8@ ) * 32 )) / duration_time) / (2400 * 1000000 * 2)", 6 + "ScaleUnit": "1e2%", 7 + "Unit": "imx9_ddr", 8 + "Compat": "imx91" 9 + }, 10 + { 11 + "BriefDescription": "bytes all masters read from ddr", 12 + "MetricName": "imx91_ddr_read.all", 13 + "MetricExpr": "( imx9_ddr0@ddrc_pm_0@ ) * 2 * 8", 14 + "ScaleUnit": "9.765625e-4KB", 15 + "Unit": "imx9_ddr", 16 + "Compat": "imx91" 17 + }, 18 + { 19 + "BriefDescription": "bytes all masters write to ddr", 20 + "MetricName": "imx91_ddr_write.all", 21 + "MetricExpr": "( imx9_ddr0@ddrc_pm_3@ + imx9_ddr0@ddrc_pm_5@ + imx9_ddr0@ddrc_pm_7@ + imx9_ddr0@ddrc_pm_9@ - imx9_ddr0@ddrc_pm_2@ - imx9_ddr0@ddrc_pm_4@ - imx9_ddr0@ddrc_pm_6@ - imx9_ddr0@ddrc_pm_8@ ) * 32", 22 + "ScaleUnit": "9.765625e-4KB", 23 + "Unit": "imx9_ddr", 24 + "Compat": "imx91" 25 + } 26 + ]
+8
tools/perf/pmu-events/arch/arm64/freescale/imx95/sys/metrics.json
··· 8 8 "Compat": "imx95" 9 9 }, 10 10 { 11 + "BriefDescription": "bandwidth usage for lpddr4x evk board", 12 + "MetricName": "imx95_bandwidth_usage.lpddr4x", 13 + "MetricExpr": "(( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x000\\,axi_id\\=0x000@ + imx9_ddr0@eddrtq_pm_wr_beat_filt\\,axi_mask\\=0x000\\,axi_id\\=0x000@ ) * 32 / duration_time) / (4000 * 1000000 * 4)", 14 + "ScaleUnit": "1e2%", 15 + "Unit": "imx9_ddr", 16 + "Compat": "imx95" 17 + }, 18 + { 11 19 "BriefDescription": "bytes of all masters read from ddr", 12 20 "MetricName": "imx95_ddr_read.all", 13 21 "MetricExpr": "( imx9_ddr0@eddrtq_pm_rd_beat_filt0\\,axi_mask\\=0x000\\,axi_id\\=0x000@ ) * 32",
+37 -37
tools/perf/pmu-events/arch/arm64/hisilicon/hip08/metrics.json
··· 3 3 "MetricExpr": "FETCH_BUBBLE / (4 * CPU_CYCLES)", 4 4 "PublicDescription": "Frontend bound L1 topdown metric", 5 5 "BriefDescription": "Frontend bound L1 topdown metric", 6 - "DefaultMetricgroupName": "TopDownL1", 7 - "MetricGroup": "Default;TopDownL1", 6 + "DefaultMetricgroupName": "TopdownL1", 7 + "MetricGroup": "Default;TopdownL1", 8 8 "MetricName": "frontend_bound" 9 9 }, 10 10 { 11 11 "MetricExpr": "(INST_SPEC - INST_RETIRED) / (4 * CPU_CYCLES)", 12 12 "PublicDescription": "Bad Speculation L1 topdown metric", 13 13 "BriefDescription": "Bad Speculation L1 topdown metric", 14 - "DefaultMetricgroupName": "TopDownL1", 15 - "MetricGroup": "Default;TopDownL1", 14 + "DefaultMetricgroupName": "TopdownL1", 15 + "MetricGroup": "Default;TopdownL1", 16 16 "MetricName": "bad_speculation" 17 17 }, 18 18 { 19 19 "MetricExpr": "INST_RETIRED / (CPU_CYCLES * 4)", 20 20 "PublicDescription": "Retiring L1 topdown metric", 21 21 "BriefDescription": "Retiring L1 topdown metric", 22 - "DefaultMetricgroupName": "TopDownL1", 23 - "MetricGroup": "Default;TopDownL1", 22 + "DefaultMetricgroupName": "TopdownL1", 23 + "MetricGroup": "Default;TopdownL1", 24 24 "MetricName": "retiring" 25 25 }, 26 26 { 27 27 "MetricExpr": "1 - (frontend_bound + bad_speculation + retiring)", 28 28 "PublicDescription": "Backend Bound L1 topdown metric", 29 29 "BriefDescription": "Backend Bound L1 topdown metric", 30 - "DefaultMetricgroupName": "TopDownL1", 31 - "MetricGroup": "Default;TopDownL1", 30 + "DefaultMetricgroupName": "TopdownL1", 31 + "MetricGroup": "Default;TopdownL1", 32 32 "MetricName": "backend_bound" 33 33 }, 34 34 { 35 35 "MetricExpr": "armv8_pmuv3_0@event\\=0x201d@ / CPU_CYCLES", 36 36 "PublicDescription": "Fetch latency bound L2 topdown metric", 37 37 "BriefDescription": "Fetch latency bound L2 topdown metric", 38 - "MetricGroup": "TopDownL2", 38 + "MetricGroup": "TopdownL2", 39 39 "MetricName": "fetch_latency_bound" 40 40 }, 41 41 { 42 42 "MetricExpr": "frontend_bound - fetch_latency_bound", 43 43 "PublicDescription": "Fetch bandwidth bound L2 topdown metric", 44 44 "BriefDescription": "Fetch bandwidth bound L2 topdown metric", 45 - "MetricGroup": "TopDownL2", 45 + "MetricGroup": "TopdownL2", 46 46 "MetricName": "fetch_bandwidth_bound" 47 47 }, 48 48 { 49 49 "MetricExpr": "(bad_speculation * BR_MIS_PRED) / (BR_MIS_PRED + armv8_pmuv3_0@event\\=0x2013@)", 50 50 "PublicDescription": "Branch mispredicts L2 topdown metric", 51 51 "BriefDescription": "Branch mispredicts L2 topdown metric", 52 - "MetricGroup": "TopDownL2", 52 + "MetricGroup": "TopdownL2", 53 53 "MetricName": "branch_mispredicts" 54 54 }, 55 55 { 56 56 "MetricExpr": "bad_speculation - branch_mispredicts", 57 57 "PublicDescription": "Machine clears L2 topdown metric", 58 58 "BriefDescription": "Machine clears L2 topdown metric", 59 - "MetricGroup": "TopDownL2", 59 + "MetricGroup": "TopdownL2", 60 60 "MetricName": "machine_clears" 61 61 }, 62 62 { 63 63 "MetricExpr": "(EXE_STALL_CYCLE - (MEM_STALL_ANYLOAD + armv8_pmuv3_0@event\\=0x7005@)) / CPU_CYCLES", 64 64 "PublicDescription": "Core bound L2 topdown metric", 65 65 "BriefDescription": "Core bound L2 topdown metric", 66 - "MetricGroup": "TopDownL2", 66 + "MetricGroup": "TopdownL2", 67 67 "MetricName": "core_bound" 68 68 }, 69 69 { 70 70 "MetricExpr": "(MEM_STALL_ANYLOAD + armv8_pmuv3_0@event\\=0x7005@) / CPU_CYCLES", 71 71 "PublicDescription": "Memory bound L2 topdown metric", 72 72 "BriefDescription": "Memory bound L2 topdown metric", 73 - "MetricGroup": "TopDownL2", 73 + "MetricGroup": "TopdownL2", 74 74 "MetricName": "memory_bound" 75 75 }, 76 76 { 77 77 "MetricExpr": "(((L2I_TLB - L2I_TLB_REFILL) * 15) + (L2I_TLB_REFILL * 100)) / CPU_CYCLES", 78 78 "PublicDescription": "Idle by itlb miss L3 topdown metric", 79 79 "BriefDescription": "Idle by itlb miss L3 topdown metric", 80 - "MetricGroup": "TopDownL3", 80 + "MetricGroup": "TopdownL3", 81 81 "MetricName": "idle_by_itlb_miss" 82 82 }, 83 83 { 84 84 "MetricExpr": "(((L2I_CACHE - L2I_CACHE_REFILL) * 15) + (L2I_CACHE_REFILL * 100)) / CPU_CYCLES", 85 85 "PublicDescription": "Idle by icache miss L3 topdown metric", 86 86 "BriefDescription": "Idle by icache miss L3 topdown metric", 87 - "MetricGroup": "TopDownL3", 87 + "MetricGroup": "TopdownL3", 88 88 "MetricName": "idle_by_icache_miss" 89 89 }, 90 90 { 91 91 "MetricExpr": "(BR_MIS_PRED * 5) / CPU_CYCLES", 92 92 "PublicDescription": "BP misp flush L3 topdown metric", 93 93 "BriefDescription": "BP misp flush L3 topdown metric", 94 - "MetricGroup": "TopDownL3", 94 + "MetricGroup": "TopdownL3", 95 95 "MetricName": "bp_misp_flush" 96 96 }, 97 97 { 98 98 "MetricExpr": "(armv8_pmuv3_0@event\\=0x2013@ * 5) / CPU_CYCLES", 99 99 "PublicDescription": "OOO flush L3 topdown metric", 100 100 "BriefDescription": "OOO flush L3 topdown metric", 101 - "MetricGroup": "TopDownL3", 101 + "MetricGroup": "TopdownL3", 102 102 "MetricName": "ooo_flush" 103 103 }, 104 104 { 105 105 "MetricExpr": "(armv8_pmuv3_0@event\\=0x1001@ * 5) / CPU_CYCLES", 106 106 "PublicDescription": "Static predictor flush L3 topdown metric", 107 107 "BriefDescription": "Static predictor flush L3 topdown metric", 108 - "MetricGroup": "TopDownL3", 108 + "MetricGroup": "TopdownL3", 109 109 "MetricName": "sp_flush" 110 110 }, 111 111 { 112 112 "MetricExpr": "armv8_pmuv3_0@event\\=0x1010@ / BR_MIS_PRED", 113 113 "PublicDescription": "Indirect branch L3 topdown metric", 114 114 "BriefDescription": "Indirect branch L3 topdown metric", 115 - "MetricGroup": "TopDownL3", 115 + "MetricGroup": "TopdownL3", 116 116 "MetricName": "indirect_branch" 117 117 }, 118 118 { 119 119 "MetricExpr": "(armv8_pmuv3_0@event\\=0x1013@ + armv8_pmuv3_0@event\\=0x1016@) / BR_MIS_PRED", 120 120 "PublicDescription": "Push branch L3 topdown metric", 121 121 "BriefDescription": "Push branch L3 topdown metric", 122 - "MetricGroup": "TopDownL3", 122 + "MetricGroup": "TopdownL3", 123 123 "MetricName": "push_branch" 124 124 }, 125 125 { 126 126 "MetricExpr": "armv8_pmuv3_0@event\\=0x100d@ / BR_MIS_PRED", 127 127 "PublicDescription": "Pop branch L3 topdown metric", 128 128 "BriefDescription": "Pop branch L3 topdown metric", 129 - "MetricGroup": "TopDownL3", 129 + "MetricGroup": "TopdownL3", 130 130 "MetricName": "pop_branch" 131 131 }, 132 132 { 133 133 "MetricExpr": "(BR_MIS_PRED - armv8_pmuv3_0@event\\=0x1010@ - armv8_pmuv3_0@event\\=0x1013@ - armv8_pmuv3_0@event\\=0x1016@ - armv8_pmuv3_0@event\\=0x100d@) / BR_MIS_PRED", 134 134 "PublicDescription": "Other branch L3 topdown metric", 135 135 "BriefDescription": "Other branch L3 topdown metric", 136 - "MetricGroup": "TopDownL3", 136 + "MetricGroup": "TopdownL3", 137 137 "MetricName": "other_branch" 138 138 }, 139 139 { 140 140 "MetricExpr": "armv8_pmuv3_0@event\\=0x2012@ / armv8_pmuv3_0@event\\=0x2013@", 141 141 "PublicDescription": "Nuke flush L3 topdown metric", 142 142 "BriefDescription": "Nuke flush L3 topdown metric", 143 - "MetricGroup": "TopDownL3", 143 + "MetricGroup": "TopdownL3", 144 144 "MetricName": "nuke_flush" 145 145 }, 146 146 { 147 147 "MetricExpr": "1 - nuke_flush", 148 148 "PublicDescription": "Other flush L3 topdown metric", 149 149 "BriefDescription": "Other flush L3 topdown metric", 150 - "MetricGroup": "TopDownL3", 150 + "MetricGroup": "TopdownL3", 151 151 "MetricName": "other_flush" 152 152 }, 153 153 { 154 154 "MetricExpr": "armv8_pmuv3_0@event\\=0x2010@ / CPU_CYCLES", 155 155 "PublicDescription": "Sync stall L3 topdown metric", 156 156 "BriefDescription": "Sync stall L3 topdown metric", 157 - "MetricGroup": "TopDownL3", 157 + "MetricGroup": "TopdownL3", 158 158 "MetricName": "sync_stall" 159 159 }, 160 160 { 161 161 "MetricExpr": "armv8_pmuv3_0@event\\=0x2004@ / CPU_CYCLES", 162 162 "PublicDescription": "Rob stall L3 topdown metric", 163 163 "BriefDescription": "Rob stall L3 topdown metric", 164 - "MetricGroup": "TopDownL3", 164 + "MetricGroup": "TopdownL3", 165 165 "MetricName": "rob_stall" 166 166 }, 167 167 { 168 168 "MetricExpr": "(armv8_pmuv3_0@event\\=0x2006@ + armv8_pmuv3_0@event\\=0x2007@ + armv8_pmuv3_0@event\\=0x2008@) / CPU_CYCLES", 169 169 "PublicDescription": "Ptag stall L3 topdown metric", 170 170 "BriefDescription": "Ptag stall L3 topdown metric", 171 - "MetricGroup": "TopDownL3", 171 + "MetricGroup": "TopdownL3", 172 172 "MetricName": "ptag_stall" 173 173 }, 174 174 { 175 175 "MetricExpr": "armv8_pmuv3_0@event\\=0x201e@ / CPU_CYCLES", 176 176 "PublicDescription": "SaveOpQ stall L3 topdown metric", 177 177 "BriefDescription": "SaveOpQ stall L3 topdown metric", 178 - "MetricGroup": "TopDownL3", 178 + "MetricGroup": "TopdownL3", 179 179 "MetricName": "saveopq_stall" 180 180 }, 181 181 { 182 182 "MetricExpr": "armv8_pmuv3_0@event\\=0x2005@ / CPU_CYCLES", 183 183 "PublicDescription": "PC buffer stall L3 topdown metric", 184 184 "BriefDescription": "PC buffer stall L3 topdown metric", 185 - "MetricGroup": "TopDownL3", 185 + "MetricGroup": "TopdownL3", 186 186 "MetricName": "pc_buffer_stall" 187 187 }, 188 188 { 189 189 "MetricExpr": "armv8_pmuv3_0@event\\=0x7002@ / CPU_CYCLES", 190 190 "PublicDescription": "Divider L3 topdown metric", 191 191 "BriefDescription": "Divider L3 topdown metric", 192 - "MetricGroup": "TopDownL3", 192 + "MetricGroup": "TopdownL3", 193 193 "MetricName": "divider" 194 194 }, 195 195 { 196 196 "MetricExpr": "armv8_pmuv3_0@event\\=0x7003@ / CPU_CYCLES", 197 197 "PublicDescription": "FSU stall L3 topdown metric", 198 198 "BriefDescription": "FSU stall L3 topdown metric", 199 - "MetricGroup": "TopDownL3", 199 + "MetricGroup": "TopdownL3", 200 200 "MetricName": "fsu_stall" 201 201 }, 202 202 { 203 203 "MetricExpr": "core_bound - divider - fsu_stall", 204 204 "PublicDescription": "EXE ports util L3 topdown metric", 205 205 "BriefDescription": "EXE ports util L3 topdown metric", 206 - "MetricGroup": "TopDownL3", 206 + "MetricGroup": "TopdownL3", 207 207 "MetricName": "exe_ports_util" 208 208 }, 209 209 { 210 210 "MetricExpr": "(MEM_STALL_ANYLOAD - MEM_STALL_L1MISS) / CPU_CYCLES", 211 211 "PublicDescription": "L1 bound L3 topdown metric", 212 212 "BriefDescription": "L1 bound L3 topdown metric", 213 - "MetricGroup": "TopDownL3", 213 + "MetricGroup": "TopdownL3", 214 214 "MetricName": "l1_bound" 215 215 }, 216 216 { 217 217 "MetricExpr": "(MEM_STALL_L1MISS - MEM_STALL_L2MISS) / CPU_CYCLES", 218 218 "PublicDescription": "L2 bound L3 topdown metric", 219 219 "BriefDescription": "L2 bound L3 topdown metric", 220 - "MetricGroup": "TopDownL3", 220 + "MetricGroup": "TopdownL3", 221 221 "MetricName": "l2_bound" 222 222 }, 223 223 { 224 224 "MetricExpr": "MEM_STALL_L2MISS / CPU_CYCLES", 225 225 "PublicDescription": "Mem bound L3 topdown metric", 226 226 "BriefDescription": "Mem bound L3 topdown metric", 227 - "MetricGroup": "TopDownL3", 227 + "MetricGroup": "TopdownL3", 228 228 "MetricName": "mem_bound" 229 229 }, 230 230 { 231 231 "MetricExpr": "armv8_pmuv3_0@event\\=0x7005@ / CPU_CYCLES", 232 232 "PublicDescription": "Store bound L3 topdown metric", 233 233 "BriefDescription": "Store bound L3 topdown metric", 234 - "MetricGroup": "TopDownL3", 234 + "MetricGroup": "TopdownL3", 235 235 "MetricName": "store_bound" 236 236 } 237 237 ]
+74
tools/perf/pmu-events/arch/common/common/tool.json
··· 1 + [ 2 + { 3 + "Unit": "tool", 4 + "EventName": "duration_time", 5 + "BriefDescription": "Wall clock interval time in nanoseconds", 6 + "ConfigCode": "1" 7 + }, 8 + { 9 + "Unit": "tool", 10 + "EventName": "user_time", 11 + "BriefDescription": "User (non-kernel) time in nanoseconds", 12 + "ConfigCode": "2" 13 + }, 14 + { 15 + "Unit": "tool", 16 + "EventName": "system_time", 17 + "BriefDescription": "System/kernel time in nanoseconds", 18 + "ConfigCode": "3" 19 + }, 20 + { 21 + "Unit": "tool", 22 + "EventName": "has_pmem", 23 + "BriefDescription": "1 if persistent memory installed otherwise 0", 24 + "ConfigCode": "4" 25 + }, 26 + { 27 + "Unit": "tool", 28 + "EventName": "num_cores", 29 + "BriefDescription": "Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU", 30 + "ConfigCode": "5" 31 + }, 32 + { 33 + "Unit": "tool", 34 + "EventName": "num_cpus", 35 + "BriefDescription": "Number of logical Linux CPUs. There may be multiple such CPUs on a core", 36 + "ConfigCode": "6" 37 + }, 38 + { 39 + "Unit": "tool", 40 + "EventName": "num_cpus_online", 41 + "BriefDescription": "Number of online logical Linux CPUs. There may be multiple such CPUs on a core", 42 + "ConfigCode": "7" 43 + }, 44 + { 45 + "Unit": "tool", 46 + "EventName": "num_dies", 47 + "BriefDescription": "Number of dies. Each die has 1 or more cores", 48 + "ConfigCode": "8" 49 + }, 50 + { 51 + "Unit": "tool", 52 + "EventName": "num_packages", 53 + "BriefDescription": "Number of packages. Each package has 1 or more die", 54 + "ConfigCode": "9" 55 + }, 56 + { 57 + "Unit": "tool", 58 + "EventName": "slots", 59 + "BriefDescription": "Number of functional units that in parallel can execute parts of an instruction", 60 + "ConfigCode": "10" 61 + }, 62 + { 63 + "Unit": "tool", 64 + "EventName": "smt_on", 65 + "BriefDescription": "1 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0", 66 + "ConfigCode": "11" 67 + }, 68 + { 69 + "Unit": "tool", 70 + "EventName": "system_tsc_freq", 71 + "BriefDescription": "The amount a Time Stamp Counter (TSC) increases per second", 72 + "ConfigCode": "12" 73 + } 74 + ]
+117
tools/perf/pmu-events/arch/powerpc/compat/generic-events.json
··· 1 + [ 2 + { 3 + "EventCode": "0x600F4", 4 + "EventName": "PM_CYC", 5 + "BriefDescription": "Processor cycles." 6 + }, 7 + { 8 + "EventCode": "0x100F2", 9 + "EventName": "PM_CYC_INST_CMPL", 10 + "BriefDescription": "1 or more ppc insts finished" 11 + }, 12 + { 13 + "EventCode": "0x100f4", 14 + "EventName": "PM_FLOP_CMPL", 15 + "BriefDescription": "Floating Point Operations Finished." 16 + }, 17 + { 18 + "EventCode": "0x100F6", 19 + "EventName": "PM_L1_ITLB_MISS", 20 + "BriefDescription": "Number of I-ERAT reloads." 21 + }, 22 + { 23 + "EventCode": "0x100F8", 24 + "EventName": "PM_NO_INST_AVAIL", 25 + "BriefDescription": "Number of cycles the ICT has no itags assigned to this thread." 26 + }, 27 + { 28 + "EventCode": "0x100fc", 29 + "EventName": "PM_LD_CMPL", 30 + "BriefDescription": "Load instruction completed." 31 + }, 32 + { 33 + "EventCode": "0x200F0", 34 + "EventName": "PM_ST_CMPL", 35 + "BriefDescription": "Stores completed from S2Q (2nd-level store queue)." 36 + }, 37 + { 38 + "EventCode": "0x200F2", 39 + "EventName": "PM_INST_DISP", 40 + "BriefDescription": "PowerPC instruction dispatched." 41 + }, 42 + { 43 + "EventCode": "0x200F4", 44 + "EventName": "PM_RUN_CYC", 45 + "BriefDescription": "Processor cycles gated by the run latch." 46 + }, 47 + { 48 + "EventCode": "0x200F6", 49 + "EventName": "PM_L1_DTLB_RELOAD", 50 + "BriefDescription": "DERAT Reloaded due to a DERAT miss." 51 + }, 52 + { 53 + "EventCode": "0x200FA", 54 + "EventName": "PM_BR_TAKEN_CMPL", 55 + "BriefDescription": "Branch Taken instruction completed." 56 + }, 57 + { 58 + "EventCode": "0x200FC", 59 + "EventName": "PM_L1_ICACHE_MISS", 60 + "BriefDescription": "Demand instruction cache miss." 61 + }, 62 + { 63 + "EventCode": "0x200FE", 64 + "EventName": "PM_L1_RELOAD_FROM_MEM", 65 + "BriefDescription": "L1 Dcache reload from memory" 66 + }, 67 + { 68 + "EventCode": "0x300F0", 69 + "EventName": "PM_ST_MISS_L1", 70 + "BriefDescription": "Store Missed L1" 71 + }, 72 + { 73 + "EventCode": "0x300FC", 74 + "EventName": "PM_DTLB_MISS", 75 + "BriefDescription": "Data PTEG reload" 76 + }, 77 + { 78 + "EventCode": "0x300FE", 79 + "EventName": "PM_DATA_FROM_L3MISS", 80 + "BriefDescription": "Demand LD - L3 Miss (not L2 hit and not L3 hit)" 81 + }, 82 + { 83 + "EventCode": "0x400F0", 84 + "EventName": "PM_LD_MISS_L1", 85 + "BriefDescription": "L1 Dcache load miss" 86 + }, 87 + { 88 + "EventCode": "0x400F2", 89 + "EventName": "PM_CYC_INST_DISP", 90 + "BriefDescription": "Cycle when instruction(s) dispatched." 91 + }, 92 + { 93 + "EventCode": "0x400F6", 94 + "EventName": "PM_BR_MPRED_CMPL", 95 + "BriefDescription": "A mispredicted branch completed. Includes direction and target." 96 + }, 97 + { 98 + "EventCode": "0x400FA", 99 + "EventName": "PM_RUN_INST_CMPL", 100 + "BriefDescription": "PowerPC instruction completed while the run latch is set." 101 + }, 102 + { 103 + "EventCode": "0x400FC", 104 + "EventName": "PM_ITLB_MISS", 105 + "BriefDescription": "Instruction TLB reload (after a miss), all page sizes. Includes only demand misses." 106 + }, 107 + { 108 + "EventCode": "0x400fe", 109 + "EventName": "PM_LD_NOT_CACHED", 110 + "BriefDescription": "Load data not cached." 111 + }, 112 + { 113 + "EventCode": "0x500fa", 114 + "EventName": "PM_INST_CMPL", 115 + "BriefDescription": "Instructions." 116 + } 117 + ]
+1
tools/perf/pmu-events/arch/powerpc/mapfile.csv
··· 16 16 0x004e[[:xdigit:]]{4},1,power9,core 17 17 0x0080[[:xdigit:]]{4},1,power10,core 18 18 0x0082[[:xdigit:]]{4},1,power10,core 19 + 0x00ffffff,1,compat,core
+1634
tools/perf/pmu-events/arch/x86/amdzen5/data-fabric.json
··· 1 + [ 2 + { 3 + "EventName": "local_or_remote_socket_read_data_beats_dram_0", 4 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 0.", 5 + "EventCode": "0x1f", 6 + "UMask": "0xffe", 7 + "PerPkg": "1", 8 + "Unit": "DFPMC" 9 + }, 10 + { 11 + "EventName": "local_or_remote_socket_read_data_beats_dram_1", 12 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 1.", 13 + "EventCode": "0x5f", 14 + "UMask": "0xffe", 15 + "PerPkg": "1", 16 + "Unit": "DFPMC" 17 + }, 18 + { 19 + "EventName": "local_or_remote_socket_read_data_beats_dram_2", 20 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 2.", 21 + "EventCode": "0x9f", 22 + "UMask": "0xffe", 23 + "PerPkg": "1", 24 + "Unit": "DFPMC" 25 + }, 26 + { 27 + "EventName": "local_or_remote_socket_read_data_beats_dram_3", 28 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 3.", 29 + "EventCode": "0xdf", 30 + "UMask": "0xffe", 31 + "PerPkg": "1", 32 + "Unit": "DFPMC" 33 + }, 34 + { 35 + "EventName": "local_or_remote_socket_read_data_beats_dram_4", 36 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 4.", 37 + "EventCode": "0x11f", 38 + "UMask": "0xffe", 39 + "PerPkg": "1", 40 + "Unit": "DFPMC" 41 + }, 42 + { 43 + "EventName": "local_or_remote_socket_read_data_beats_dram_5", 44 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 5.", 45 + "EventCode": "0x15f", 46 + "UMask": "0xffe", 47 + "PerPkg": "1", 48 + "Unit": "DFPMC" 49 + }, 50 + { 51 + "EventName": "local_or_remote_socket_read_data_beats_dram_6", 52 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 6.", 53 + "EventCode": "0x19f", 54 + "UMask": "0xffe", 55 + "PerPkg": "1", 56 + "Unit": "DFPMC" 57 + }, 58 + { 59 + "EventName": "local_or_remote_socket_read_data_beats_dram_7", 60 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 7.", 61 + "EventCode": "0x1df", 62 + "UMask": "0xffe", 63 + "PerPkg": "1", 64 + "Unit": "DFPMC" 65 + }, 66 + { 67 + "EventName": "local_or_remote_socket_read_data_beats_dram_8", 68 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 8.", 69 + "EventCode": "0x21f", 70 + "UMask": "0xffe", 71 + "PerPkg": "1", 72 + "Unit": "DFPMC" 73 + }, 74 + { 75 + "EventName": "local_or_remote_socket_read_data_beats_dram_9", 76 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 9.", 77 + "EventCode": "0x25f", 78 + "UMask": "0xffe", 79 + "PerPkg": "1", 80 + "Unit": "DFPMC" 81 + }, 82 + { 83 + "EventName": "local_or_remote_socket_read_data_beats_dram_10", 84 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 10.", 85 + "EventCode": "0x29f", 86 + "UMask": "0xffe", 87 + "PerPkg": "1", 88 + "Unit": "DFPMC" 89 + }, 90 + { 91 + "EventName": "local_or_remote_socket_read_data_beats_dram_11", 92 + "PublicDescription": "Read data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 11.", 93 + "EventCode": "0x2df", 94 + "UMask": "0xffe", 95 + "PerPkg": "1", 96 + "Unit": "DFPMC" 97 + }, 98 + { 99 + "EventName": "local_socket_write_data_beats_dram_0", 100 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 0.", 101 + "EventCode": "0x1f", 102 + "UMask": "0x7ff", 103 + "PerPkg": "1", 104 + "Unit": "DFPMC" 105 + }, 106 + { 107 + "EventName": "local_socket_write_data_beats_dram_1", 108 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 1.", 109 + "EventCode": "0x5f", 110 + "UMask": "0x7ff", 111 + "PerPkg": "1", 112 + "Unit": "DFPMC" 113 + }, 114 + { 115 + "EventName": "local_socket_write_data_beats_dram_2", 116 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 2.", 117 + "EventCode": "0x9f", 118 + "UMask": "0x7ff", 119 + "PerPkg": "1", 120 + "Unit": "DFPMC" 121 + }, 122 + { 123 + "EventName": "local_socket_write_data_beats_dram_3", 124 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 3.", 125 + "EventCode": "0xdf", 126 + "UMask": "0x7ff", 127 + "PerPkg": "1", 128 + "Unit": "DFPMC" 129 + }, 130 + { 131 + "EventName": "local_socket_write_data_beats_dram_4", 132 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 4.", 133 + "EventCode": "0x11f", 134 + "UMask": "0x7ff", 135 + "PerPkg": "1", 136 + "Unit": "DFPMC" 137 + }, 138 + { 139 + "EventName": "local_socket_write_data_beats_dram_5", 140 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 5.", 141 + "EventCode": "0x15f", 142 + "UMask": "0x7ff", 143 + "PerPkg": "1", 144 + "Unit": "DFPMC" 145 + }, 146 + { 147 + "EventName": "local_socket_write_data_beats_dram_6", 148 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 6.", 149 + "EventCode": "0x19f", 150 + "UMask": "0x7ff", 151 + "PerPkg": "1", 152 + "Unit": "DFPMC" 153 + }, 154 + { 155 + "EventName": "local_socket_write_data_beats_dram_7", 156 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 7.", 157 + "EventCode": "0x1df", 158 + "UMask": "0x7ff", 159 + "PerPkg": "1", 160 + "Unit": "DFPMC" 161 + }, 162 + { 163 + "EventName": "local_socket_write_data_beats_dram_8", 164 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 8.", 165 + "EventCode": "0x21f", 166 + "UMask": "0x7ff", 167 + "PerPkg": "1", 168 + "Unit": "DFPMC" 169 + }, 170 + { 171 + "EventName": "local_socket_write_data_beats_dram_9", 172 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 9.", 173 + "EventCode": "0x25f", 174 + "UMask": "0x7ff", 175 + "PerPkg": "1", 176 + "Unit": "DFPMC" 177 + }, 178 + { 179 + "EventName": "local_socket_write_data_beats_dram_10", 180 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 10.", 181 + "EventCode": "0x29f", 182 + "UMask": "0x7ff", 183 + "PerPkg": "1", 184 + "Unit": "DFPMC" 185 + }, 186 + { 187 + "EventName": "local_socket_write_data_beats_dram_11", 188 + "PublicDescription": "Write data beats (64 bytes) for transactions between local socket and DRAM Channel 11.", 189 + "EventCode": "0x2df", 190 + "UMask": "0x7ff", 191 + "PerPkg": "1", 192 + "Unit": "DFPMC" 193 + }, 194 + { 195 + "EventName": "remote_socket_write_data_beats_dram_0", 196 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 0.", 197 + "EventCode": "0x1f", 198 + "UMask": "0xbff", 199 + "PerPkg": "1", 200 + "Unit": "DFPMC" 201 + }, 202 + { 203 + "EventName": "remote_socket_write_data_beats_dram_1", 204 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 1.", 205 + "EventCode": "0x5f", 206 + "UMask": "0xbff", 207 + "PerPkg": "1", 208 + "Unit": "DFPMC" 209 + }, 210 + { 211 + "EventName": "remote_socket_write_data_beats_dram_2", 212 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 2.", 213 + "EventCode": "0x9f", 214 + "UMask": "0xbff", 215 + "PerPkg": "1", 216 + "Unit": "DFPMC" 217 + }, 218 + { 219 + "EventName": "remote_socket_write_data_beats_dram_3", 220 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 3.", 221 + "EventCode": "0xdf", 222 + "UMask": "0xbff", 223 + "PerPkg": "1", 224 + "Unit": "DFPMC" 225 + }, 226 + { 227 + "EventName": "remote_socket_write_data_beats_dram_4", 228 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 4.", 229 + "EventCode": "0x11f", 230 + "UMask": "0xbff", 231 + "PerPkg": "1", 232 + "Unit": "DFPMC" 233 + }, 234 + { 235 + "EventName": "remote_socket_write_data_beats_dram_5", 236 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 5.", 237 + "EventCode": "0x15f", 238 + "UMask": "0xbff", 239 + "PerPkg": "1", 240 + "Unit": "DFPMC" 241 + }, 242 + { 243 + "EventName": "remote_socket_write_data_beats_dram_6", 244 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 6.", 245 + "EventCode": "0x19f", 246 + "UMask": "0xbff", 247 + "PerPkg": "1", 248 + "Unit": "DFPMC" 249 + }, 250 + { 251 + "EventName": "remote_socket_write_data_beats_dram_7", 252 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 7.", 253 + "EventCode": "0x1df", 254 + "UMask": "0xbff", 255 + "PerPkg": "1", 256 + "Unit": "DFPMC" 257 + }, 258 + { 259 + "EventName": "remote_socket_write_data_beats_dram_8", 260 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 8.", 261 + "EventCode": "0x21f", 262 + "UMask": "0xbff", 263 + "PerPkg": "1", 264 + "Unit": "DFPMC" 265 + }, 266 + { 267 + "EventName": "remote_socket_write_data_beats_dram_9", 268 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 9.", 269 + "EventCode": "0x25f", 270 + "UMask": "0xbff", 271 + "PerPkg": "1", 272 + "Unit": "DFPMC" 273 + }, 274 + { 275 + "EventName": "remote_socket_write_data_beats_dram_10", 276 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 10.", 277 + "EventCode": "0x29f", 278 + "UMask": "0xbff", 279 + "PerPkg": "1", 280 + "Unit": "DFPMC" 281 + }, 282 + { 283 + "EventName": "remote_socket_write_data_beats_dram_11", 284 + "PublicDescription": "Write data beats (64 bytes) for transactions between remote socket and DRAM Channel 11.", 285 + "EventCode": "0x2df", 286 + "UMask": "0xbff", 287 + "PerPkg": "1", 288 + "Unit": "DFPMC" 289 + }, 290 + { 291 + "EventName": "local_or_remote_socket_write_data_beats_dram_0", 292 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 0.", 293 + "EventCode": "0x1f", 294 + "UMask": "0xfff", 295 + "PerPkg": "1", 296 + "Unit": "DFPMC" 297 + }, 298 + { 299 + "EventName": "local_or_remote_socket_write_data_beats_dram_1", 300 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 1.", 301 + "EventCode": "0x5f", 302 + "UMask": "0xfff", 303 + "PerPkg": "1", 304 + "Unit": "DFPMC" 305 + }, 306 + { 307 + "EventName": "local_or_remote_socket_write_data_beats_dram_2", 308 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 2.", 309 + "EventCode": "0x9f", 310 + "UMask": "0xfff", 311 + "PerPkg": "1", 312 + "Unit": "DFPMC" 313 + }, 314 + { 315 + "EventName": "local_or_remote_socket_write_data_beats_dram_3", 316 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 3.", 317 + "EventCode": "0xdf", 318 + "UMask": "0xfff", 319 + "PerPkg": "1", 320 + "Unit": "DFPMC" 321 + }, 322 + { 323 + "EventName": "local_or_remote_socket_write_data_beats_dram_4", 324 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 4.", 325 + "EventCode": "0x11f", 326 + "UMask": "0xfff", 327 + "PerPkg": "1", 328 + "Unit": "DFPMC" 329 + }, 330 + { 331 + "EventName": "local_or_remote_socket_write_data_beats_dram_5", 332 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 5.", 333 + "EventCode": "0x15f", 334 + "UMask": "0xfff", 335 + "PerPkg": "1", 336 + "Unit": "DFPMC" 337 + }, 338 + { 339 + "EventName": "local_or_remote_socket_write_data_beats_dram_6", 340 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 6.", 341 + "EventCode": "0x19f", 342 + "UMask": "0xfff", 343 + "PerPkg": "1", 344 + "Unit": "DFPMC" 345 + }, 346 + { 347 + "EventName": "local_or_remote_socket_write_data_beats_dram_7", 348 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 7.", 349 + "EventCode": "0x1df", 350 + "UMask": "0xfff", 351 + "PerPkg": "1", 352 + "Unit": "DFPMC" 353 + }, 354 + { 355 + "EventName": "local_or_remote_socket_write_data_beats_dram_8", 356 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 8.", 357 + "EventCode": "0x21f", 358 + "UMask": "0xfff", 359 + "PerPkg": "1", 360 + "Unit": "DFPMC" 361 + }, 362 + { 363 + "EventName": "local_or_remote_socket_write_data_beats_dram_9", 364 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 9.", 365 + "EventCode": "0x25f", 366 + "UMask": "0xfff", 367 + "PerPkg": "1", 368 + "Unit": "DFPMC" 369 + }, 370 + { 371 + "EventName": "local_or_remote_socket_write_data_beats_dram_10", 372 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 10.", 373 + "EventCode": "0x29f", 374 + "UMask": "0xfff", 375 + "PerPkg": "1", 376 + "Unit": "DFPMC" 377 + }, 378 + { 379 + "EventName": "local_or_remote_socket_write_data_beats_dram_11", 380 + "PublicDescription": "Write data beats (64 bytes) for transactions between local or remote socket and DRAM Channel 11.", 381 + "EventCode": "0x2df", 382 + "UMask": "0xfff", 383 + "PerPkg": "1", 384 + "Unit": "DFPMC" 385 + }, 386 + { 387 + "EventName": "local_socket_upstream_read_data_beats_io_0", 388 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local socket and IO Root Complex 0.", 389 + "EventCode": "0x81f", 390 + "UMask": "0x7fe", 391 + "PerPkg": "1", 392 + "Unit": "DFPMC" 393 + }, 394 + { 395 + "EventName": "local_socket_upstream_read_data_beats_io_1", 396 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local socket and IO Root Complex 1.", 397 + "EventCode": "0x85f", 398 + "UMask": "0x7fe", 399 + "PerPkg": "1", 400 + "Unit": "DFPMC" 401 + }, 402 + { 403 + "EventName": "local_socket_upstream_read_data_beats_io_2", 404 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local socket and IO Root Complex 2.", 405 + "EventCode": "0x89f", 406 + "UMask": "0x7fe", 407 + "PerPkg": "1", 408 + "Unit": "DFPMC" 409 + }, 410 + { 411 + "EventName": "local_socket_upstream_read_data_beats_io_3", 412 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local socket and IO Root Complex 3.", 413 + "EventCode": "0x8df", 414 + "UMask": "0x7fe", 415 + "PerPkg": "1", 416 + "Unit": "DFPMC" 417 + }, 418 + { 419 + "EventName": "local_socket_upstream_read_data_beats_io_4", 420 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local socket and IO Root Complex 4.", 421 + "EventCode": "0x91f", 422 + "UMask": "0x7fe", 423 + "PerPkg": "1", 424 + "Unit": "DFPMC" 425 + }, 426 + { 427 + "EventName": "local_socket_upstream_read_data_beats_io_5", 428 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local socket and IO Root Complex 5.", 429 + "EventCode": "0x95f", 430 + "UMask": "0x7fe", 431 + "PerPkg": "1", 432 + "Unit": "DFPMC" 433 + }, 434 + { 435 + "EventName": "local_socket_upstream_read_data_beats_io_6", 436 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local socket and IO Root Complex 6.", 437 + "EventCode": "0x99f", 438 + "UMask": "0x7fe", 439 + "PerPkg": "1", 440 + "Unit": "DFPMC" 441 + }, 442 + { 443 + "EventName": "local_socket_upstream_read_data_beats_io_7", 444 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local socket and IO Root Complex 7.", 445 + "EventCode": "0x9df", 446 + "UMask": "0x7fe", 447 + "PerPkg": "1", 448 + "Unit": "DFPMC" 449 + }, 450 + { 451 + "EventName": "local_socket_upstream_write_data_beats_io_0", 452 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local socket and IO Root Complex 0.", 453 + "EventCode": "0x81f", 454 + "UMask": "0x7ff", 455 + "PerPkg": "1", 456 + "Unit": "DFPMC" 457 + }, 458 + { 459 + "EventName": "local_socket_upstream_write_data_beats_io_1", 460 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local socket and IO Root Complex 1.", 461 + "EventCode": "0x85f", 462 + "UMask": "0x7ff", 463 + "PerPkg": "1", 464 + "Unit": "DFPMC" 465 + }, 466 + { 467 + "EventName": "local_socket_upstream_write_data_beats_io_2", 468 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local socket and IO Root Complex 2.", 469 + "EventCode": "0x89f", 470 + "UMask": "0x7ff", 471 + "PerPkg": "1", 472 + "Unit": "DFPMC" 473 + }, 474 + { 475 + "EventName": "local_socket_upstream_write_data_beats_io_3", 476 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local socket and IO Root Complex 3.", 477 + "EventCode": "0x8df", 478 + "UMask": "0x7ff", 479 + "PerPkg": "1", 480 + "Unit": "DFPMC" 481 + }, 482 + { 483 + "EventName": "local_socket_upstream_write_data_beats_io_4", 484 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local socket and IO Root Complex 4.", 485 + "EventCode": "0x91f", 486 + "UMask": "0x7ff", 487 + "PerPkg": "1", 488 + "Unit": "DFPMC" 489 + }, 490 + { 491 + "EventName": "local_socket_upstream_write_data_beats_io_5", 492 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local socket and IO Root Complex 5.", 493 + "EventCode": "0x95f", 494 + "UMask": "0x7ff", 495 + "PerPkg": "1", 496 + "Unit": "DFPMC" 497 + }, 498 + { 499 + "EventName": "local_socket_upstream_write_data_beats_io_6", 500 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local socket and IO Root Complex 6.", 501 + "EventCode": "0x99f", 502 + "UMask": "0x7ff", 503 + "PerPkg": "1", 504 + "Unit": "DFPMC" 505 + }, 506 + { 507 + "EventName": "local_socket_upstream_write_data_beats_io_7", 508 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local socket and IO Root Complex 7.", 509 + "EventCode": "0x9df", 510 + "UMask": "0x7ff", 511 + "PerPkg": "1", 512 + "Unit": "DFPMC" 513 + }, 514 + { 515 + "EventName": "remote_socket_upstream_read_data_beats_io_0", 516 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between remote socket and IO Root Complex 0.", 517 + "EventCode": "0x81f", 518 + "UMask": "0xbfe", 519 + "PerPkg": "1", 520 + "Unit": "DFPMC" 521 + }, 522 + { 523 + "EventName": "remote_socket_upstream_read_data_beats_io_1", 524 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between remote socket and IO Root Complex 1.", 525 + "EventCode": "0x85f", 526 + "UMask": "0xbfe", 527 + "PerPkg": "1", 528 + "Unit": "DFPMC" 529 + }, 530 + { 531 + "EventName": "remote_socket_upstream_read_data_beats_io_2", 532 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between remote socket and IO Root Complex 2.", 533 + "EventCode": "0x89f", 534 + "UMask": "0xbfe", 535 + "PerPkg": "1", 536 + "Unit": "DFPMC" 537 + }, 538 + { 539 + "EventName": "remote_socket_upstream_read_data_beats_io_3", 540 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between remote socket and IO Root Complex 3.", 541 + "EventCode": "0x8df", 542 + "UMask": "0xbfe", 543 + "PerPkg": "1", 544 + "Unit": "DFPMC" 545 + }, 546 + { 547 + "EventName": "remote_socket_upstream_read_data_beats_io_4", 548 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between remote socket and IO Root Complex 4.", 549 + "EventCode": "0x91f", 550 + "UMask": "0xbfe", 551 + "PerPkg": "1", 552 + "Unit": "DFPMC" 553 + }, 554 + { 555 + "EventName": "remote_socket_upstream_read_data_beats_io_5", 556 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between remote socket and IO Root Complex 5.", 557 + "EventCode": "0x95f", 558 + "UMask": "0xbfe", 559 + "PerPkg": "1", 560 + "Unit": "DFPMC" 561 + }, 562 + { 563 + "EventName": "remote_socket_upstream_read_data_beats_io_6", 564 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between remote socket and IO Root Complex 6.", 565 + "EventCode": "0x99f", 566 + "UMask": "0xbfe", 567 + "PerPkg": "1", 568 + "Unit": "DFPMC" 569 + }, 570 + { 571 + "EventName": "remote_socket_upstream_read_data_beats_io_7", 572 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between remote socket and IO Root Complex 7.", 573 + "EventCode": "0x9df", 574 + "UMask": "0xbfe", 575 + "PerPkg": "1", 576 + "Unit": "DFPMC" 577 + }, 578 + { 579 + "EventName": "remote_socket_upstream_write_data_beats_io_0", 580 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between remote socket and IO Root Complex 0.", 581 + "EventCode": "0x81f", 582 + "UMask": "0xbff", 583 + "PerPkg": "1", 584 + "Unit": "DFPMC" 585 + }, 586 + { 587 + "EventName": "remote_socket_upstream_write_data_beats_io_1", 588 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between remote socket and IO Root Complex 1.", 589 + "EventCode": "0x85f", 590 + "UMask": "0xbff", 591 + "PerPkg": "1", 592 + "Unit": "DFPMC" 593 + }, 594 + { 595 + "EventName": "remote_socket_upstream_write_data_beats_io_2", 596 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between remote socket and IO Root Complex 2.", 597 + "EventCode": "0x89f", 598 + "UMask": "0xbff", 599 + "PerPkg": "1", 600 + "Unit": "DFPMC" 601 + }, 602 + { 603 + "EventName": "remote_socket_upstream_write_data_beats_io_3", 604 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between remote socket and IO Root Complex 3.", 605 + "EventCode": "0x8df", 606 + "UMask": "0xbff", 607 + "PerPkg": "1", 608 + "Unit": "DFPMC" 609 + }, 610 + { 611 + "EventName": "remote_socket_upstream_write_data_beats_io_4", 612 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between remote socket and IO Root Complex 4.", 613 + "EventCode": "0x91f", 614 + "UMask": "0xbff", 615 + "PerPkg": "1", 616 + "Unit": "DFPMC" 617 + }, 618 + { 619 + "EventName": "remote_socket_upstream_write_data_beats_io_5", 620 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between remote socket and IO Root Complex 5.", 621 + "EventCode": "0x95f", 622 + "UMask": "0xbff", 623 + "PerPkg": "1", 624 + "Unit": "DFPMC" 625 + }, 626 + { 627 + "EventName": "remote_socket_upstream_write_data_beats_io_6", 628 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between remote socket and IO Root Complex 6.", 629 + "EventCode": "0x99f", 630 + "UMask": "0xbff", 631 + "PerPkg": "1", 632 + "Unit": "DFPMC" 633 + }, 634 + { 635 + "EventName": "remote_socket_upstream_write_data_beats_io_7", 636 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between remote socket and IO Root Complex 7.", 637 + "EventCode": "0x9df", 638 + "UMask": "0xbff", 639 + "PerPkg": "1", 640 + "Unit": "DFPMC" 641 + }, 642 + { 643 + "EventName": "local_or_remote_socket_upstream_read_data_beats_io_0", 644 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 0.", 645 + "EventCode": "0x81f", 646 + "UMask": "0xffe", 647 + "PerPkg": "1", 648 + "Unit": "DFPMC" 649 + }, 650 + { 651 + "EventName": "local_or_remote_socket_upstream_read_data_beats_io_1", 652 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 1.", 653 + "EventCode": "0x85f", 654 + "UMask": "0xffe", 655 + "PerPkg": "1", 656 + "Unit": "DFPMC" 657 + }, 658 + { 659 + "EventName": "local_or_remote_socket_upstream_read_data_beats_io_2", 660 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 2.", 661 + "EventCode": "0x89f", 662 + "UMask": "0xffe", 663 + "PerPkg": "1", 664 + "Unit": "DFPMC" 665 + }, 666 + { 667 + "EventName": "local_or_remote_socket_upstream_read_data_beats_io_3", 668 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 3.", 669 + "EventCode": "0x8df", 670 + "UMask": "0xffe", 671 + "PerPkg": "1", 672 + "Unit": "DFPMC" 673 + }, 674 + { 675 + "EventName": "local_or_remote_socket_upstream_read_data_beats_io_4", 676 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 4.", 677 + "EventCode": "0x91f", 678 + "UMask": "0xffe", 679 + "PerPkg": "1", 680 + "Unit": "DFPMC" 681 + }, 682 + { 683 + "EventName": "local_or_remote_socket_upstream_read_data_beats_io_5", 684 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 5.", 685 + "EventCode": "0x95f", 686 + "UMask": "0xffe", 687 + "PerPkg": "1", 688 + "Unit": "DFPMC" 689 + }, 690 + { 691 + "EventName": "local_or_remote_socket_upstream_read_data_beats_io_6", 692 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 6.", 693 + "EventCode": "0x99f", 694 + "UMask": "0xffe", 695 + "PerPkg": "1", 696 + "Unit": "DFPMC" 697 + }, 698 + { 699 + "EventName": "local_or_remote_socket_upstream_read_data_beats_io_7", 700 + "PublicDescription": "Upstream DMA read data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 7.", 701 + "EventCode": "0x9df", 702 + "UMask": "0xffe", 703 + "PerPkg": "1", 704 + "Unit": "DFPMC" 705 + }, 706 + { 707 + "EventName": "local_or_remote_socket_upstream_write_data_beats_io_0", 708 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 0.", 709 + "EventCode": "0x81f", 710 + "UMask": "0xfff", 711 + "PerPkg": "1", 712 + "Unit": "DFPMC" 713 + }, 714 + { 715 + "EventName": "local_or_remote_socket_upstream_write_data_beats_io_1", 716 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 1.", 717 + "EventCode": "0x85f", 718 + "UMask": "0xfff", 719 + "PerPkg": "1", 720 + "Unit": "DFPMC" 721 + }, 722 + { 723 + "EventName": "local_or_remote_socket_upstream_write_data_beats_io_2", 724 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 2.", 725 + "EventCode": "0x89f", 726 + "UMask": "0xfff", 727 + "PerPkg": "1", 728 + "Unit": "DFPMC" 729 + }, 730 + { 731 + "EventName": "local_or_remote_socket_upstream_write_data_beats_io_3", 732 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 3.", 733 + "EventCode": "0x8df", 734 + "UMask": "0xfff", 735 + "PerPkg": "1", 736 + "Unit": "DFPMC" 737 + }, 738 + { 739 + "EventName": "local_or_remote_socket_upstream_write_data_beats_io_4", 740 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 4.", 741 + "EventCode": "0x91f", 742 + "UMask": "0xfff", 743 + "PerPkg": "1", 744 + "Unit": "DFPMC" 745 + }, 746 + { 747 + "EventName": "local_or_remote_socket_upstream_write_data_beats_io_5", 748 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 5.", 749 + "EventCode": "0x95f", 750 + "UMask": "0xfff", 751 + "PerPkg": "1", 752 + "Unit": "DFPMC" 753 + }, 754 + { 755 + "EventName": "local_or_remote_socket_upstream_write_data_beats_io_6", 756 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 6.", 757 + "EventCode": "0x99f", 758 + "UMask": "0xfff", 759 + "PerPkg": "1", 760 + "Unit": "DFPMC" 761 + }, 762 + { 763 + "EventName": "local_or_remote_socket_upstream_write_data_beats_io_7", 764 + "PublicDescription": "Upstream DMA write data beats (64 bytes) for transactions between local or remote socket and IO Root Complex 7.", 765 + "EventCode": "0x9df", 766 + "UMask": "0xfff", 767 + "PerPkg": "1", 768 + "Unit": "DFPMC" 769 + }, 770 + { 771 + "EventName": "local_socket_inbound_data_beats_cfi_0", 772 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 0.", 773 + "EventCode": "0x41e", 774 + "UMask": "0x7fe", 775 + "PerPkg": "1", 776 + "Unit": "DFPMC" 777 + }, 778 + { 779 + "EventName": "local_socket_inbound_data_beats_cfi_1", 780 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 1.", 781 + "EventCode": "0x45e", 782 + "UMask": "0x7fe", 783 + "PerPkg": "1", 784 + "Unit": "DFPMC" 785 + }, 786 + { 787 + "EventName": "local_socket_inbound_data_beats_cfi_2", 788 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 2.", 789 + "EventCode": "0x49e", 790 + "UMask": "0x7fe", 791 + "PerPkg": "1", 792 + "Unit": "DFPMC" 793 + }, 794 + { 795 + "EventName": "local_socket_inbound_data_beats_cfi_3", 796 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 3.", 797 + "EventCode": "0x4de", 798 + "UMask": "0x7fe", 799 + "PerPkg": "1", 800 + "Unit": "DFPMC" 801 + }, 802 + { 803 + "EventName": "local_socket_inbound_data_beats_cfi_4", 804 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 4.", 805 + "EventCode": "0x51e", 806 + "UMask": "0x7fe", 807 + "PerPkg": "1", 808 + "Unit": "DFPMC" 809 + }, 810 + { 811 + "EventName": "local_socket_inbound_data_beats_cfi_5", 812 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 5.", 813 + "EventCode": "0x55e", 814 + "UMask": "0x7fe", 815 + "PerPkg": "1", 816 + "Unit": "DFPMC" 817 + }, 818 + { 819 + "EventName": "local_socket_inbound_data_beats_cfi_6", 820 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 6.", 821 + "EventCode": "0x59e", 822 + "UMask": "0x7fe", 823 + "PerPkg": "1", 824 + "Unit": "DFPMC" 825 + }, 826 + { 827 + "EventName": "local_socket_inbound_data_beats_cfi_7", 828 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 7.", 829 + "EventCode": "0x5de", 830 + "UMask": "0x7fe", 831 + "PerPkg": "1", 832 + "Unit": "DFPMC" 833 + }, 834 + { 835 + "EventName": "local_socket_inbound_data_beats_cfi_8", 836 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 8.", 837 + "EventCode": "0x41f", 838 + "UMask": "0x7fe", 839 + "PerPkg": "1", 840 + "Unit": "DFPMC" 841 + }, 842 + { 843 + "EventName": "local_socket_inbound_data_beats_cfi_9", 844 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 9.", 845 + "EventCode": "0x45f", 846 + "UMask": "0x7fe", 847 + "PerPkg": "1", 848 + "Unit": "DFPMC" 849 + }, 850 + { 851 + "EventName": "local_socket_inbound_data_beats_cfi_10", 852 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 10.", 853 + "EventCode": "0x49f", 854 + "UMask": "0x7fe", 855 + "PerPkg": "1", 856 + "Unit": "DFPMC" 857 + }, 858 + { 859 + "EventName": "local_socket_inbound_data_beats_cfi_11", 860 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 11.", 861 + "EventCode": "0x4df", 862 + "UMask": "0x7fe", 863 + "PerPkg": "1", 864 + "Unit": "DFPMC" 865 + }, 866 + { 867 + "EventName": "local_socket_inbound_data_beats_cfi_12", 868 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 12.", 869 + "EventCode": "0x51f", 870 + "UMask": "0x7fe", 871 + "PerPkg": "1", 872 + "Unit": "DFPMC" 873 + }, 874 + { 875 + "EventName": "local_socket_inbound_data_beats_cfi_13", 876 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 13.", 877 + "EventCode": "0x55f", 878 + "UMask": "0x7fe", 879 + "PerPkg": "1", 880 + "Unit": "DFPMC" 881 + }, 882 + { 883 + "EventName": "local_socket_inbound_data_beats_cfi_14", 884 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 14.", 885 + "EventCode": "0x59f", 886 + "UMask": "0x7fe", 887 + "PerPkg": "1", 888 + "Unit": "DFPMC" 889 + }, 890 + { 891 + "EventName": "local_socket_inbound_data_beats_cfi_15", 892 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local socket and Core-to-Fabric Interface 15.", 893 + "EventCode": "0x5df", 894 + "UMask": "0x7fe", 895 + "PerPkg": "1", 896 + "Unit": "DFPMC" 897 + }, 898 + { 899 + "EventName": "local_socket_outbound_data_beats_cfi_0", 900 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 0.", 901 + "EventCode": "0x41e", 902 + "UMask": "0x7ff", 903 + "PerPkg": "1", 904 + "Unit": "DFPMC" 905 + }, 906 + { 907 + "EventName": "local_socket_outbound_data_beats_cfi_1", 908 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 1.", 909 + "EventCode": "0x45e", 910 + "UMask": "0x7ff", 911 + "PerPkg": "1", 912 + "Unit": "DFPMC" 913 + }, 914 + { 915 + "EventName": "local_socket_outbound_data_beats_cfi_2", 916 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 2.", 917 + "EventCode": "0x49e", 918 + "UMask": "0x7ff", 919 + "PerPkg": "1", 920 + "Unit": "DFPMC" 921 + }, 922 + { 923 + "EventName": "local_socket_outbound_data_beats_cfi_3", 924 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 3.", 925 + "EventCode": "0x4de", 926 + "UMask": "0x7ff", 927 + "PerPkg": "1", 928 + "Unit": "DFPMC" 929 + }, 930 + { 931 + "EventName": "local_socket_outbound_data_beats_cfi_4", 932 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 4.", 933 + "EventCode": "0x51e", 934 + "UMask": "0x7ff", 935 + "PerPkg": "1", 936 + "Unit": "DFPMC" 937 + }, 938 + { 939 + "EventName": "local_socket_outbound_data_beats_cfi_5", 940 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 5.", 941 + "EventCode": "0x55e", 942 + "UMask": "0x7ff", 943 + "PerPkg": "1", 944 + "Unit": "DFPMC" 945 + }, 946 + { 947 + "EventName": "local_socket_outbound_data_beats_cfi_6", 948 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 6.", 949 + "EventCode": "0x59e", 950 + "UMask": "0x7ff", 951 + "PerPkg": "1", 952 + "Unit": "DFPMC" 953 + }, 954 + { 955 + "EventName": "local_socket_outbound_data_beats_cfi_7", 956 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 7.", 957 + "EventCode": "0x5de", 958 + "UMask": "0x7ff", 959 + "PerPkg": "1", 960 + "Unit": "DFPMC" 961 + }, 962 + { 963 + "EventName": "local_socket_outbound_data_beats_cfi_8", 964 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 8.", 965 + "EventCode": "0x41f", 966 + "UMask": "0x7ff", 967 + "PerPkg": "1", 968 + "Unit": "DFPMC" 969 + }, 970 + { 971 + "EventName": "local_socket_outbound_data_beats_cfi_9", 972 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 9.", 973 + "EventCode": "0x45f", 974 + "UMask": "0x7ff", 975 + "PerPkg": "1", 976 + "Unit": "DFPMC" 977 + }, 978 + { 979 + "EventName": "local_socket_outbound_data_beats_cfi_10", 980 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 10.", 981 + "EventCode": "0x49f", 982 + "UMask": "0x7ff", 983 + "PerPkg": "1", 984 + "Unit": "DFPMC" 985 + }, 986 + { 987 + "EventName": "local_socket_outbound_data_beats_cfi_11", 988 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 11.", 989 + "EventCode": "0x4df", 990 + "UMask": "0x7ff", 991 + "PerPkg": "1", 992 + "Unit": "DFPMC" 993 + }, 994 + { 995 + "EventName": "local_socket_outbound_data_beats_cfi_12", 996 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 12.", 997 + "EventCode": "0x51f", 998 + "UMask": "0x7ff", 999 + "PerPkg": "1", 1000 + "Unit": "DFPMC" 1001 + }, 1002 + { 1003 + "EventName": "local_socket_outbound_data_beats_cfi_13", 1004 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 13.", 1005 + "EventCode": "0x55f", 1006 + "UMask": "0x7ff", 1007 + "PerPkg": "1", 1008 + "Unit": "DFPMC" 1009 + }, 1010 + { 1011 + "EventName": "local_socket_outbound_data_beats_cfi_14", 1012 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 14.", 1013 + "EventCode": "0x59f", 1014 + "UMask": "0x7ff", 1015 + "PerPkg": "1", 1016 + "Unit": "DFPMC" 1017 + }, 1018 + { 1019 + "EventName": "local_socket_outbound_data_beats_cfi_15", 1020 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and Core-to-Fabric Interface 15.", 1021 + "EventCode": "0x5df", 1022 + "UMask": "0x7ff", 1023 + "PerPkg": "1", 1024 + "Unit": "DFPMC" 1025 + }, 1026 + { 1027 + "EventName": "remote_socket_inbound_data_beats_cfi_0", 1028 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 0.", 1029 + "EventCode": "0x41e", 1030 + "UMask": "0xbfe", 1031 + "PerPkg": "1", 1032 + "Unit": "DFPMC" 1033 + }, 1034 + { 1035 + "EventName": "remote_socket_inbound_data_beats_cfi_1", 1036 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 1.", 1037 + "EventCode": "0x45e", 1038 + "UMask": "0xbfe", 1039 + "PerPkg": "1", 1040 + "Unit": "DFPMC" 1041 + }, 1042 + { 1043 + "EventName": "remote_socket_inbound_data_beats_cfi_2", 1044 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 2.", 1045 + "EventCode": "0x49e", 1046 + "UMask": "0xbfe", 1047 + "PerPkg": "1", 1048 + "Unit": "DFPMC" 1049 + }, 1050 + { 1051 + "EventName": "remote_socket_inbound_data_beats_cfi_3", 1052 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 3.", 1053 + "EventCode": "0x4de", 1054 + "UMask": "0xbfe", 1055 + "PerPkg": "1", 1056 + "Unit": "DFPMC" 1057 + }, 1058 + { 1059 + "EventName": "remote_socket_inbound_data_beats_cfi_4", 1060 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 4.", 1061 + "EventCode": "0x51e", 1062 + "UMask": "0xbfe", 1063 + "PerPkg": "1", 1064 + "Unit": "DFPMC" 1065 + }, 1066 + { 1067 + "EventName": "remote_socket_inbound_data_beats_cfi_5", 1068 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 5.", 1069 + "EventCode": "0x55e", 1070 + "UMask": "0xbfe", 1071 + "PerPkg": "1", 1072 + "Unit": "DFPMC" 1073 + }, 1074 + { 1075 + "EventName": "remote_socket_inbound_data_beats_cfi_6", 1076 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 6.", 1077 + "EventCode": "0x59e", 1078 + "UMask": "0xbfe", 1079 + "PerPkg": "1", 1080 + "Unit": "DFPMC" 1081 + }, 1082 + { 1083 + "EventName": "remote_socket_inbound_data_beats_cfi_7", 1084 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 7.", 1085 + "EventCode": "0x5de", 1086 + "UMask": "0xbfe", 1087 + "PerPkg": "1", 1088 + "Unit": "DFPMC" 1089 + }, 1090 + { 1091 + "EventName": "remote_socket_inbound_data_beats_cfi_8", 1092 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 8.", 1093 + "EventCode": "0x41f", 1094 + "UMask": "0xbfe", 1095 + "PerPkg": "1", 1096 + "Unit": "DFPMC" 1097 + }, 1098 + { 1099 + "EventName": "remote_socket_inbound_data_beats_cfi_9", 1100 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 9.", 1101 + "EventCode": "0x45f", 1102 + "UMask": "0xbfe", 1103 + "PerPkg": "1", 1104 + "Unit": "DFPMC" 1105 + }, 1106 + { 1107 + "EventName": "remote_socket_inbound_data_beats_cfi_10", 1108 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 10.", 1109 + "EventCode": "0x49f", 1110 + "UMask": "0xbfe", 1111 + "PerPkg": "1", 1112 + "Unit": "DFPMC" 1113 + }, 1114 + { 1115 + "EventName": "remote_socket_inbound_data_beats_cfi_11", 1116 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 11.", 1117 + "EventCode": "0x4df", 1118 + "UMask": "0xbfe", 1119 + "PerPkg": "1", 1120 + "Unit": "DFPMC" 1121 + }, 1122 + { 1123 + "EventName": "remote_socket_inbound_data_beats_cfi_12", 1124 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 12.", 1125 + "EventCode": "0x51f", 1126 + "UMask": "0xbfe", 1127 + "PerPkg": "1", 1128 + "Unit": "DFPMC" 1129 + }, 1130 + { 1131 + "EventName": "remote_socket_inbound_data_beats_cfi_13", 1132 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 13.", 1133 + "EventCode": "0x55f", 1134 + "UMask": "0xbfe", 1135 + "PerPkg": "1", 1136 + "Unit": "DFPMC" 1137 + }, 1138 + { 1139 + "EventName": "remote_socket_inbound_data_beats_cfi_14", 1140 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 14.", 1141 + "EventCode": "0x59f", 1142 + "UMask": "0xbfe", 1143 + "PerPkg": "1", 1144 + "Unit": "DFPMC" 1145 + }, 1146 + { 1147 + "EventName": "remote_socket_inbound_data_beats_cfi_15", 1148 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between remote socket and Core-to-Fabric Interface 15.", 1149 + "EventCode": "0x5df", 1150 + "UMask": "0xbfe", 1151 + "PerPkg": "1", 1152 + "Unit": "DFPMC" 1153 + }, 1154 + { 1155 + "EventName": "remote_socket_outbound_data_beats_cfi_0", 1156 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 0.", 1157 + "EventCode": "0x41e", 1158 + "UMask": "0xbff", 1159 + "PerPkg": "1", 1160 + "Unit": "DFPMC" 1161 + }, 1162 + { 1163 + "EventName": "remote_socket_outbound_data_beats_cfi_1", 1164 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 1.", 1165 + "EventCode": "0x45e", 1166 + "UMask": "0xbff", 1167 + "PerPkg": "1", 1168 + "Unit": "DFPMC" 1169 + }, 1170 + { 1171 + "EventName": "remote_socket_outbound_data_beats_cfi_2", 1172 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 2.", 1173 + "EventCode": "0x49e", 1174 + "UMask": "0xbff", 1175 + "PerPkg": "1", 1176 + "Unit": "DFPMC" 1177 + }, 1178 + { 1179 + "EventName": "remote_socket_outbound_data_beats_cfi_3", 1180 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 3.", 1181 + "EventCode": "0x4de", 1182 + "UMask": "0xbff", 1183 + "PerPkg": "1", 1184 + "Unit": "DFPMC" 1185 + }, 1186 + { 1187 + "EventName": "remote_socket_outbound_data_beats_cfi_4", 1188 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 4.", 1189 + "EventCode": "0x51e", 1190 + "UMask": "0xbff", 1191 + "PerPkg": "1", 1192 + "Unit": "DFPMC" 1193 + }, 1194 + { 1195 + "EventName": "remote_socket_outbound_data_beats_cfi_5", 1196 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 5.", 1197 + "EventCode": "0x55e", 1198 + "UMask": "0xbff", 1199 + "PerPkg": "1", 1200 + "Unit": "DFPMC" 1201 + }, 1202 + { 1203 + "EventName": "remote_socket_outbound_data_beats_cfi_6", 1204 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 6.", 1205 + "EventCode": "0x59e", 1206 + "UMask": "0xbff", 1207 + "PerPkg": "1", 1208 + "Unit": "DFPMC" 1209 + }, 1210 + { 1211 + "EventName": "remote_socket_outbound_data_beats_cfi_7", 1212 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 7.", 1213 + "EventCode": "0x5de", 1214 + "UMask": "0xbff", 1215 + "PerPkg": "1", 1216 + "Unit": "DFPMC" 1217 + }, 1218 + { 1219 + "EventName": "remote_socket_outbound_data_beats_cfi_8", 1220 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 8.", 1221 + "EventCode": "0x41f", 1222 + "UMask": "0xbff", 1223 + "PerPkg": "1", 1224 + "Unit": "DFPMC" 1225 + }, 1226 + { 1227 + "EventName": "remote_socket_outbound_data_beats_cfi_9", 1228 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 9.", 1229 + "EventCode": "0x45f", 1230 + "UMask": "0xbff", 1231 + "PerPkg": "1", 1232 + "Unit": "DFPMC" 1233 + }, 1234 + { 1235 + "EventName": "remote_socket_outbound_data_beats_cfi_10", 1236 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 10.", 1237 + "EventCode": "0x49f", 1238 + "UMask": "0xbff", 1239 + "PerPkg": "1", 1240 + "Unit": "DFPMC" 1241 + }, 1242 + { 1243 + "EventName": "remote_socket_outbound_data_beats_cfi_11", 1244 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 11.", 1245 + "EventCode": "0x4df", 1246 + "UMask": "0xbff", 1247 + "PerPkg": "1", 1248 + "Unit": "DFPMC" 1249 + }, 1250 + { 1251 + "EventName": "remote_socket_outbound_data_beats_cfi_12", 1252 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 12.", 1253 + "EventCode": "0x51f", 1254 + "UMask": "0xbff", 1255 + "PerPkg": "1", 1256 + "Unit": "DFPMC" 1257 + }, 1258 + { 1259 + "EventName": "remote_socket_outbound_data_beats_cfi_13", 1260 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 13.", 1261 + "EventCode": "0x55f", 1262 + "UMask": "0xbff", 1263 + "PerPkg": "1", 1264 + "Unit": "DFPMC" 1265 + }, 1266 + { 1267 + "EventName": "remote_socket_outbound_data_beats_cfi_14", 1268 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 14.", 1269 + "EventCode": "0x59f", 1270 + "UMask": "0xbff", 1271 + "PerPkg": "1", 1272 + "Unit": "DFPMC" 1273 + }, 1274 + { 1275 + "EventName": "remote_socket_outbound_data_beats_cfi_15", 1276 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between remote socket and Core-to-Fabric Interface 15.", 1277 + "EventCode": "0x5df", 1278 + "UMask": "0xbff", 1279 + "PerPkg": "1", 1280 + "Unit": "DFPMC" 1281 + }, 1282 + { 1283 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_0", 1284 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 0.", 1285 + "EventCode": "0x41e", 1286 + "UMask": "0xffe", 1287 + "PerPkg": "1", 1288 + "Unit": "DFPMC" 1289 + }, 1290 + { 1291 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_1", 1292 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 1.", 1293 + "EventCode": "0x45e", 1294 + "UMask": "0xffe", 1295 + "PerPkg": "1", 1296 + "Unit": "DFPMC" 1297 + }, 1298 + { 1299 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_2", 1300 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 2.", 1301 + "EventCode": "0x49e", 1302 + "UMask": "0xffe", 1303 + "PerPkg": "1", 1304 + "Unit": "DFPMC" 1305 + }, 1306 + { 1307 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_3", 1308 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 3.", 1309 + "EventCode": "0x4de", 1310 + "UMask": "0xffe", 1311 + "PerPkg": "1", 1312 + "Unit": "DFPMC" 1313 + }, 1314 + { 1315 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_4", 1316 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 4.", 1317 + "EventCode": "0x51e", 1318 + "UMask": "0xffe", 1319 + "PerPkg": "1", 1320 + "Unit": "DFPMC" 1321 + }, 1322 + { 1323 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_5", 1324 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 5.", 1325 + "EventCode": "0x55e", 1326 + "UMask": "0xffe", 1327 + "PerPkg": "1", 1328 + "Unit": "DFPMC" 1329 + }, 1330 + { 1331 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_6", 1332 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 6.", 1333 + "EventCode": "0x59e", 1334 + "UMask": "0xffe", 1335 + "PerPkg": "1", 1336 + "Unit": "DFPMC" 1337 + }, 1338 + { 1339 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_7", 1340 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 7.", 1341 + "EventCode": "0x5de", 1342 + "UMask": "0xffe", 1343 + "PerPkg": "1", 1344 + "Unit": "DFPMC" 1345 + }, 1346 + { 1347 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_8", 1348 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 8.", 1349 + "EventCode": "0x41f", 1350 + "UMask": "0xffe", 1351 + "PerPkg": "1", 1352 + "Unit": "DFPMC" 1353 + }, 1354 + { 1355 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_9", 1356 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 9.", 1357 + "EventCode": "0x45f", 1358 + "UMask": "0xffe", 1359 + "PerPkg": "1", 1360 + "Unit": "DFPMC" 1361 + }, 1362 + { 1363 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_10", 1364 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 10.", 1365 + "EventCode": "0x49f", 1366 + "UMask": "0xffe", 1367 + "PerPkg": "1", 1368 + "Unit": "DFPMC" 1369 + }, 1370 + { 1371 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_11", 1372 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 11.", 1373 + "EventCode": "0x4df", 1374 + "UMask": "0xffe", 1375 + "PerPkg": "1", 1376 + "Unit": "DFPMC" 1377 + }, 1378 + { 1379 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_12", 1380 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 12.", 1381 + "EventCode": "0x51f", 1382 + "UMask": "0xffe", 1383 + "PerPkg": "1", 1384 + "Unit": "DFPMC" 1385 + }, 1386 + { 1387 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_13", 1388 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 13.", 1389 + "EventCode": "0x55f", 1390 + "UMask": "0xffe", 1391 + "PerPkg": "1", 1392 + "Unit": "DFPMC" 1393 + }, 1394 + { 1395 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_14", 1396 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 14.", 1397 + "EventCode": "0x59f", 1398 + "UMask": "0xffe", 1399 + "PerPkg": "1", 1400 + "Unit": "DFPMC" 1401 + }, 1402 + { 1403 + "EventName": "local_or_remote_socket_inbound_data_beats_cfi_15", 1404 + "PublicDescription": "Inbound data beats (32 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 15.", 1405 + "EventCode": "0x5df", 1406 + "UMask": "0xffe", 1407 + "PerPkg": "1", 1408 + "Unit": "DFPMC" 1409 + }, 1410 + { 1411 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_0", 1412 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 0.", 1413 + "EventCode": "0x41e", 1414 + "UMask": "0xfff", 1415 + "PerPkg": "1", 1416 + "Unit": "DFPMC" 1417 + }, 1418 + { 1419 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_1", 1420 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 1.", 1421 + "EventCode": "0x45e", 1422 + "UMask": "0xfff", 1423 + "PerPkg": "1", 1424 + "Unit": "DFPMC" 1425 + }, 1426 + { 1427 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_2", 1428 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 2.", 1429 + "EventCode": "0x49e", 1430 + "UMask": "0xfff", 1431 + "PerPkg": "1", 1432 + "Unit": "DFPMC" 1433 + }, 1434 + { 1435 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_3", 1436 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 3.", 1437 + "EventCode": "0x4de", 1438 + "UMask": "0xfff", 1439 + "PerPkg": "1", 1440 + "Unit": "DFPMC" 1441 + }, 1442 + { 1443 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_4", 1444 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 4.", 1445 + "EventCode": "0x51e", 1446 + "UMask": "0xfff", 1447 + "PerPkg": "1", 1448 + "Unit": "DFPMC" 1449 + }, 1450 + { 1451 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_5", 1452 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 5.", 1453 + "EventCode": "0x55e", 1454 + "UMask": "0xfff", 1455 + "PerPkg": "1", 1456 + "Unit": "DFPMC" 1457 + }, 1458 + { 1459 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_6", 1460 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 6.", 1461 + "EventCode": "0x59e", 1462 + "UMask": "0xfff", 1463 + "PerPkg": "1", 1464 + "Unit": "DFPMC" 1465 + }, 1466 + { 1467 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_7", 1468 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 7.", 1469 + "EventCode": "0x5de", 1470 + "UMask": "0xfff", 1471 + "PerPkg": "1", 1472 + "Unit": "DFPMC" 1473 + }, 1474 + { 1475 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_8", 1476 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 8.", 1477 + "EventCode": "0x41f", 1478 + "UMask": "0xfff", 1479 + "PerPkg": "1", 1480 + "Unit": "DFPMC" 1481 + }, 1482 + { 1483 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_9", 1484 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 9.", 1485 + "EventCode": "0x45f", 1486 + "UMask": "0xfff", 1487 + "PerPkg": "1", 1488 + "Unit": "DFPMC" 1489 + }, 1490 + { 1491 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_10", 1492 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 10.", 1493 + "EventCode": "0x49f", 1494 + "UMask": "0xfff", 1495 + "PerPkg": "1", 1496 + "Unit": "DFPMC" 1497 + }, 1498 + { 1499 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_11", 1500 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 11.", 1501 + "EventCode": "0x4df", 1502 + "UMask": "0xfff", 1503 + "PerPkg": "1", 1504 + "Unit": "DFPMC" 1505 + }, 1506 + { 1507 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_12", 1508 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 12.", 1509 + "EventCode": "0x51f", 1510 + "UMask": "0xfff", 1511 + "PerPkg": "1", 1512 + "Unit": "DFPMC" 1513 + }, 1514 + { 1515 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_13", 1516 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 13.", 1517 + "EventCode": "0x55f", 1518 + "UMask": "0xfff", 1519 + "PerPkg": "1", 1520 + "Unit": "DFPMC" 1521 + }, 1522 + { 1523 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_14", 1524 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 14.", 1525 + "EventCode": "0x59f", 1526 + "UMask": "0xfff", 1527 + "PerPkg": "1", 1528 + "Unit": "DFPMC" 1529 + }, 1530 + { 1531 + "EventName": "local_or_remote_socket_outbound_data_beats_cfi_15", 1532 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local or remote socket and Core-to-Fabric Interface 15.", 1533 + "EventCode": "0x5df", 1534 + "UMask": "0xfff", 1535 + "PerPkg": "1", 1536 + "Unit": "DFPMC" 1537 + }, 1538 + { 1539 + "EventName": "local_socket_inbound_data_beats_link_0", 1540 + "PublicDescription": "Inbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 0.", 1541 + "EventCode": "0xd5f", 1542 + "UMask": "0xf3f", 1543 + "PerPkg": "1", 1544 + "Unit": "DFPMC" 1545 + }, 1546 + { 1547 + "EventName": "local_socket_inbound_data_beats_link_1", 1548 + "PublicDescription": "Inbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 1.", 1549 + "EventCode": "0xd9f", 1550 + "UMask": "0xf3f", 1551 + "PerPkg": "1", 1552 + "Unit": "DFPMC" 1553 + }, 1554 + { 1555 + "EventName": "local_socket_inbound_data_beats_link_2", 1556 + "PublicDescription": "Inbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 2.", 1557 + "EventCode": "0xddf", 1558 + "UMask": "0xf3f", 1559 + "PerPkg": "1", 1560 + "Unit": "DFPMC" 1561 + }, 1562 + { 1563 + "EventName": "local_socket_inbound_data_beats_link_3", 1564 + "PublicDescription": "Inbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 3.", 1565 + "EventCode": "0xe1f", 1566 + "UMask": "0xf3f", 1567 + "PerPkg": "1", 1568 + "Unit": "DFPMC" 1569 + }, 1570 + { 1571 + "EventName": "local_socket_inbound_data_beats_link_4", 1572 + "PublicDescription": "Inbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 4.", 1573 + "EventCode": "0xe5f", 1574 + "UMask": "0xf3f", 1575 + "PerPkg": "1", 1576 + "Unit": "DFPMC" 1577 + }, 1578 + { 1579 + "EventName": "local_socket_inbound_data_beats_link_5", 1580 + "PublicDescription": "Inbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 5.", 1581 + "EventCode": "0xe9f", 1582 + "UMask": "0xf3f", 1583 + "PerPkg": "1", 1584 + "Unit": "DFPMC" 1585 + }, 1586 + { 1587 + "EventName": "local_socket_outbound_data_beats_link_0", 1588 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 0.", 1589 + "EventCode": "0xd5f", 1590 + "UMask": "0xf3e", 1591 + "PerPkg": "1", 1592 + "Unit": "DFPMC" 1593 + }, 1594 + { 1595 + "EventName": "local_socket_outbound_data_beats_link_1", 1596 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 1.", 1597 + "EventCode": "0xd9f", 1598 + "UMask": "0xf3e", 1599 + "PerPkg": "1", 1600 + "Unit": "DFPMC" 1601 + }, 1602 + { 1603 + "EventName": "local_socket_outbound_data_beats_link_2", 1604 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 2.", 1605 + "EventCode": "0xddf", 1606 + "UMask": "0xf3e", 1607 + "PerPkg": "1", 1608 + "Unit": "DFPMC" 1609 + }, 1610 + { 1611 + "EventName": "local_socket_outbound_data_beats_link_3", 1612 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 3.", 1613 + "EventCode": "0xe1f", 1614 + "UMask": "0xf3e", 1615 + "PerPkg": "1", 1616 + "Unit": "DFPMC" 1617 + }, 1618 + { 1619 + "EventName": "local_socket_outbound_data_beats_link_4", 1620 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 4.", 1621 + "EventCode": "0xe5f", 1622 + "UMask": "0xf3e", 1623 + "PerPkg": "1", 1624 + "Unit": "DFPMC" 1625 + }, 1626 + { 1627 + "EventName": "local_socket_outbound_data_beats_link_5", 1628 + "PublicDescription": "Outbound data beats (64 bytes) for transactions between local socket and remote socket over Cross-socket Link 5.", 1629 + "EventCode": "0xe9f", 1630 + "UMask": "0xf3e", 1631 + "PerPkg": "1", 1632 + "Unit": "DFPMC" 1633 + } 1634 + ]
+72 -6
tools/perf/pmu-events/arch/x86/amdzen5/load-store.json
··· 97 97 "UMask": "0x02" 98 98 }, 99 99 { 100 + "EventName": "ls_dmnd_fills_from_sys.local_all", 101 + "EventCode": "0x43", 102 + "BriefDescription": "Demand data cache fills from local L2 cache, L3 cache or different L2 cache in the same CCX.", 103 + "UMask": "0x03" 104 + }, 105 + { 100 106 "EventName": "ls_dmnd_fills_from_sys.near_cache", 101 107 "EventCode": "0x43", 102 108 "BriefDescription": "Demand data cache fills from cache of another CCX when the address was in the same NUMA node.", ··· 121 115 "UMask": "0x10" 122 116 }, 123 117 { 118 + "EventName": "ls_dmnd_fills_from_sys.remote_cache", 119 + "EventCode": "0x43", 120 + "BriefDescription": "Demand data cache fills from cache of another CCX when the address was in the same or a different NUMA node.", 121 + "UMask": "0x14" 122 + }, 123 + { 124 124 "EventName": "ls_dmnd_fills_from_sys.dram_io_far", 125 125 "EventCode": "0x43", 126 126 "BriefDescription": "Demand data cache fills from either DRAM or MMIO in a different NUMA node (same or different socket).", 127 127 "UMask": "0x40" 128 + }, 129 + { 130 + "EventName": "ls_dmnd_fills_from_sys.dram_io_all", 131 + "EventCode": "0x43", 132 + "BriefDescription": "Demand data cache fills from either DRAM or MMIO in the same or a different NUMA node (same or different socket).", 133 + "UMask": "0x48" 134 + }, 135 + { 136 + "EventName": "ls_dmnd_fills_from_sys.far_all", 137 + "EventCode": "0x43", 138 + "BriefDescription": "Demand data cache fills from either cache of another CCX, DRAM or MMIO when the address was in a different NUMA node (same or different socket).", 139 + "UMask": "0x50" 128 140 }, 129 141 { 130 142 "EventName": "ls_dmnd_fills_from_sys.alternate_memories", ··· 215 191 "EventCode": "0x44", 216 192 "BriefDescription": "Any data cache fills from either cache of another CCX, DRAM or MMIO when the address was in a different NUMA node (same or different socket).", 217 193 "UMask": "0x50" 218 - }, 219 - { 220 - "EventName": "ls_any_fills_from_sys.all_dram_io", 221 - "EventCode": "0x44", 222 - "BriefDescription": "Any data cache fills from either DRAM or MMIO in any NUMA node (same or different socket).", 223 - "UMask": "0x48" 224 194 }, 225 195 { 226 196 "EventName": "ls_any_fills_from_sys.alternate_memories", ··· 361 343 "UMask": "0x02" 362 344 }, 363 345 { 346 + "EventName": "ls_sw_pf_dc_fills.local_all", 347 + "EventCode": "0x59", 348 + "BriefDescription": "Software prefetch data cache fills from local L2 cache, L3 cache or different L2 cache in the same CCX.", 349 + "UMask": "0x03" 350 + }, 351 + { 364 352 "EventName": "ls_sw_pf_dc_fills.near_cache", 365 353 "EventCode": "0x59", 366 354 "BriefDescription": "Software prefetch data cache fills from cache of another CCX in the same NUMA node.", ··· 385 361 "UMask": "0x10" 386 362 }, 387 363 { 364 + "EventName": "ls_sw_pf_dc_fills.remote_cache", 365 + "EventCode": "0x59", 366 + "BriefDescription": "Software prefetch data cache fills from cache of another CCX when the address was in the same or a different NUMA node.", 367 + "UMask": "0x14" 368 + }, 369 + { 388 370 "EventName": "ls_sw_pf_dc_fills.dram_io_far", 389 371 "EventCode": "0x59", 390 372 "BriefDescription": "Software prefetch data cache fills from either DRAM or MMIO in a different NUMA node (same or different socket).", 391 373 "UMask": "0x40" 374 + }, 375 + { 376 + "EventName": "ls_sw_pf_dc_fills.dram_io_all", 377 + "EventCode": "0x59", 378 + "BriefDescription": "Software prefetch data cache fills from either DRAM or MMIO in the same or a different NUMA node (same or different socket).", 379 + "UMask": "0x48" 380 + }, 381 + { 382 + "EventName": "ls_sw_pf_dc_fills.far_all", 383 + "EventCode": "0x59", 384 + "BriefDescription": "Software prefetch data cache fills from either cache of another CCX, DRAM or MMIO when the address was in a different NUMA node (same or different socket).", 385 + "UMask": "0x50" 392 386 }, 393 387 { 394 388 "EventName": "ls_sw_pf_dc_fills.alternate_memories", ··· 433 391 "UMask": "0x02" 434 392 }, 435 393 { 394 + "EventName": "ls_hw_pf_dc_fills.local_all", 395 + "EventCode": "0x5a", 396 + "BriefDescription": "Hardware prefetch data cache fills from local L2 cache, L3 cache or different L2 cache in the same CCX.", 397 + "UMask": "0x03" 398 + }, 399 + { 436 400 "EventName": "ls_hw_pf_dc_fills.near_cache", 437 401 "EventCode": "0x5a", 438 402 "BriefDescription": "Hardware prefetch data cache fills from cache of another CCX when the address was in the same NUMA node.", ··· 457 409 "UMask": "0x10" 458 410 }, 459 411 { 412 + "EventName": "ls_hw_pf_dc_fills.remote_cache", 413 + "EventCode": "0x5a", 414 + "BriefDescription": "Hardware prefetch data cache fills from cache of another CCX when the address was in the same or a different NUMA node.", 415 + "UMask": "0x14" 416 + }, 417 + { 460 418 "EventName": "ls_hw_pf_dc_fills.dram_io_far", 461 419 "EventCode": "0x5a", 462 420 "BriefDescription": "Hardware prefetch data cache fills from either DRAM or MMIO in a different NUMA node (same or different socket).", 463 421 "UMask": "0x40" 422 + }, 423 + { 424 + "EventName": "ls_hw_pf_dc_fills.dram_io_all", 425 + "EventCode": "0x5a", 426 + "BriefDescription": "Hardware prefetch data cache fills from either DRAM or MMIO in the same or a different NUMA node (same or different socket).", 427 + "UMask": "0x48" 428 + }, 429 + { 430 + "EventName": "ls_hw_pf_dc_fills.far_all", 431 + "EventCode": "0x5a", 432 + "BriefDescription": "Hardware prefetch data cache fills from either cache of another CCX, DRAM or MMIO when the address was in a different NUMA node (same or different socket).", 433 + "UMask": "0x50" 464 434 }, 465 435 { 466 436 "EventName": "ls_hw_pf_dc_fills.alternate_memories",
+112
tools/perf/pmu-events/arch/x86/amdzen5/recommended.json
··· 341 341 "MetricGroup": "memory_controller", 342 342 "PerPkg": "1", 343 343 "ScaleUnit": "1per_memclk" 344 + }, 345 + { 346 + "MetricName": "dram_read_bandwidth_for_local_or_remote_socket", 347 + "BriefDescription": "DRAM read data bandwidth for accesses in local or remote socket.", 348 + "MetricExpr": "(local_or_remote_socket_read_data_beats_dram_0 + local_or_remote_socket_read_data_beats_dram_1 + local_or_remote_socket_read_data_beats_dram_2 + local_or_remote_socket_read_data_beats_dram_3 + local_or_remote_socket_read_data_beats_dram_4 + local_or_remote_socket_read_data_beats_dram_5 + local_or_remote_socket_read_data_beats_dram_6 + local_or_remote_socket_read_data_beats_dram_7 + local_or_remote_socket_read_data_beats_dram_8 + local_or_remote_socket_read_data_beats_dram_9 + local_or_remote_socket_read_data_beats_dram_10 + local_or_remote_socket_read_data_beats_dram_11) / duration_time", 349 + "MetricGroup": "data_fabric", 350 + "PerPkg": "1", 351 + "ScaleUnit": "6.4e-5MB/s" 352 + }, 353 + { 354 + "MetricName": "dram_write_bandwidth_for_local_socket", 355 + "BriefDescription": "DRAM write data bandwidth for accesses in local socket.", 356 + "MetricExpr": "(local_socket_write_data_beats_dram_0 + local_socket_write_data_beats_dram_1 + local_socket_write_data_beats_dram_2 + local_socket_write_data_beats_dram_3 + local_socket_write_data_beats_dram_4 + local_socket_write_data_beats_dram_5 + local_socket_write_data_beats_dram_6 + local_socket_write_data_beats_dram_7 + local_socket_write_data_beats_dram_8 + local_socket_write_data_beats_dram_9 + local_socket_write_data_beats_dram_10 + local_socket_write_data_beats_dram_11) / duration_time", 357 + "MetricGroup": "data_fabric", 358 + "PerPkg": "1", 359 + "ScaleUnit": "6.4e-5MB/s" 360 + }, 361 + { 362 + "MetricName": "dram_write_bandwidth_for_remote_socket", 363 + "BriefDescription": "DRAM write data bandwidth for accesses in remote socket.", 364 + "MetricExpr": "(remote_socket_write_data_beats_dram_0 + remote_socket_write_data_beats_dram_1 + remote_socket_write_data_beats_dram_2 + remote_socket_write_data_beats_dram_3 + remote_socket_write_data_beats_dram_4 + remote_socket_write_data_beats_dram_5 + remote_socket_write_data_beats_dram_6 + remote_socket_write_data_beats_dram_7 + remote_socket_write_data_beats_dram_8 + remote_socket_write_data_beats_dram_9 + remote_socket_write_data_beats_dram_10 + remote_socket_write_data_beats_dram_11) / duration_time", 365 + "MetricGroup": "data_fabric", 366 + "PerPkg": "1", 367 + "ScaleUnit": "6.4e-5MB/s" 368 + }, 369 + { 370 + "MetricName": "dram_write_bandwidth_for_local_or_remote_socket", 371 + "BriefDescription": "DRAM write data bandwidth for accesses in local or remote socket.", 372 + "MetricExpr": "(local_or_remote_socket_write_data_beats_dram_0 + local_or_remote_socket_write_data_beats_dram_1 + local_or_remote_socket_write_data_beats_dram_2 + local_or_remote_socket_write_data_beats_dram_3 + local_or_remote_socket_write_data_beats_dram_4 + local_or_remote_socket_write_data_beats_dram_5 + local_or_remote_socket_write_data_beats_dram_6 + local_or_remote_socket_write_data_beats_dram_7 + local_or_remote_socket_write_data_beats_dram_8 + local_or_remote_socket_write_data_beats_dram_9 + local_or_remote_socket_write_data_beats_dram_10 + local_or_remote_socket_write_data_beats_dram_11) / duration_time", 373 + "MetricGroup": "data_fabric", 374 + "PerPkg": "1", 375 + "ScaleUnit": "6.4e-5MB/s" 376 + }, 377 + { 378 + "MetricName": "upstream_dma_read_bandwidth_for_local_socket", 379 + "BriefDescription": "Upstream DMA read data bandwidth for accesses in local socket.", 380 + "MetricExpr": "(local_socket_upstream_read_data_beats_io_0 + local_socket_upstream_read_data_beats_io_1 + local_socket_upstream_read_data_beats_io_2 + local_socket_upstream_read_data_beats_io_3 + local_socket_upstream_read_data_beats_io_4 + local_socket_upstream_read_data_beats_io_5 + local_socket_upstream_read_data_beats_io_6 + local_socket_upstream_read_data_beats_io_7) / duration_time", 381 + "MetricGroup": "data_fabric", 382 + "PerPkg": "1", 383 + "ScaleUnit": "6.4e-5MB/s" 384 + }, 385 + { 386 + "MetricName": "upstream_dma_write_bandwidth_for_local_socket", 387 + "BriefDescription": "Upstream DMA write data bandwidth for accesses in local socket.", 388 + "MetricExpr": "(local_socket_upstream_write_data_beats_io_0 + local_socket_upstream_write_data_beats_io_1 + local_socket_upstream_write_data_beats_io_2 + local_socket_upstream_write_data_beats_io_3 + local_socket_upstream_write_data_beats_io_4 + local_socket_upstream_write_data_beats_io_5 + local_socket_upstream_write_data_beats_io_6 + local_socket_upstream_write_data_beats_io_7) / duration_time", 389 + "MetricGroup": "data_fabric", 390 + "PerPkg": "1", 391 + "ScaleUnit": "6.4e-5MB/s" 392 + }, 393 + { 394 + "MetricName": "upstream_dma_read_bandwidth_for_remote_socket", 395 + "BriefDescription": "Upstream DMA read data bandwidth for accesses in remote socket.", 396 + "MetricExpr": "(remote_socket_upstream_read_data_beats_io_0 + remote_socket_upstream_read_data_beats_io_1 + remote_socket_upstream_read_data_beats_io_2 + remote_socket_upstream_read_data_beats_io_3 + remote_socket_upstream_read_data_beats_io_4 + remote_socket_upstream_read_data_beats_io_5 + remote_socket_upstream_read_data_beats_io_6 + remote_socket_upstream_read_data_beats_io_7) / duration_time", 397 + "MetricGroup": "data_fabric", 398 + "PerPkg": "1", 399 + "ScaleUnit": "6.4e-5MB/s" 400 + }, 401 + { 402 + "MetricName": "upstream_dma_write_bandwidth_for_remote_socket", 403 + "BriefDescription": "Upstream DMA write data bandwidth for accesses in remote socket.", 404 + "MetricExpr": "(remote_socket_upstream_write_data_beats_io_0 + remote_socket_upstream_write_data_beats_io_1 + remote_socket_upstream_write_data_beats_io_2 + remote_socket_upstream_write_data_beats_io_3 + remote_socket_upstream_write_data_beats_io_4 + remote_socket_upstream_write_data_beats_io_5 + remote_socket_upstream_write_data_beats_io_6 + remote_socket_upstream_write_data_beats_io_7) / duration_time", 405 + "MetricGroup": "data_fabric", 406 + "PerPkg": "1", 407 + "ScaleUnit": "6.4e-5MB/s" 408 + }, 409 + { 410 + "MetricName": "core_inbound_data_bandwidth_for_local_socket", 411 + "BriefDescription": "Core inbound data bandwidth for accesses in local socket.", 412 + "MetricExpr": "(local_socket_inbound_data_beats_cfi_0 + local_socket_inbound_data_beats_cfi_1 + local_socket_inbound_data_beats_cfi_2 + local_socket_inbound_data_beats_cfi_3 + local_socket_inbound_data_beats_cfi_4 + local_socket_inbound_data_beats_cfi_5 + local_socket_inbound_data_beats_cfi_6 + local_socket_inbound_data_beats_cfi_7 + local_socket_inbound_data_beats_cfi_8 + local_socket_inbound_data_beats_cfi_9 + local_socket_inbound_data_beats_cfi_10 + local_socket_inbound_data_beats_cfi_11 + local_socket_inbound_data_beats_cfi_12 + local_socket_inbound_data_beats_cfi_13 + local_socket_inbound_data_beats_cfi_14 + local_socket_inbound_data_beats_cfi_15) / duration_time", 413 + "MetricGroup": "data_fabric", 414 + "PerPkg": "1", 415 + "ScaleUnit": "3.2e-5MB/s" 416 + }, 417 + { 418 + "MetricName": "core_outbound_data_bandwidth_for_local_socket", 419 + "BriefDescription": "Core outbound data bandwidth for accesses in local socket.", 420 + "MetricExpr": "(local_socket_outbound_data_beats_cfi_0 + local_socket_outbound_data_beats_cfi_1 + local_socket_outbound_data_beats_cfi_2 + local_socket_outbound_data_beats_cfi_3 + local_socket_outbound_data_beats_cfi_4 + local_socket_outbound_data_beats_cfi_5 + local_socket_outbound_data_beats_cfi_6 + local_socket_outbound_data_beats_cfi_7 + local_socket_outbound_data_beats_cfi_8 + local_socket_outbound_data_beats_cfi_9 + local_socket_outbound_data_beats_cfi_10 + local_socket_outbound_data_beats_cfi_11 + local_socket_outbound_data_beats_cfi_12 + local_socket_outbound_data_beats_cfi_13 + local_socket_outbound_data_beats_cfi_14 + local_socket_outbound_data_beats_cfi_15) / duration_time", 421 + "MetricGroup": "data_fabric", 422 + "PerPkg": "1", 423 + "ScaleUnit": "6.4e-5MB/s" 424 + }, 425 + { 426 + "MetricName": "core_inbound_data_bandwidth_for_remote_socket", 427 + "BriefDescription": "Core inbound data bandwidth for accesses in remote socket.", 428 + "MetricExpr": "(remote_socket_inbound_data_beats_cfi_0 + remote_socket_inbound_data_beats_cfi_1 + remote_socket_inbound_data_beats_cfi_2 + remote_socket_inbound_data_beats_cfi_3 + remote_socket_inbound_data_beats_cfi_4 + remote_socket_inbound_data_beats_cfi_5 + remote_socket_inbound_data_beats_cfi_6 + remote_socket_inbound_data_beats_cfi_7 + remote_socket_inbound_data_beats_cfi_8 + remote_socket_inbound_data_beats_cfi_9 + remote_socket_inbound_data_beats_cfi_10 + remote_socket_inbound_data_beats_cfi_11 + remote_socket_inbound_data_beats_cfi_12 + remote_socket_inbound_data_beats_cfi_13 + remote_socket_inbound_data_beats_cfi_14 + remote_socket_inbound_data_beats_cfi_15) / duration_time", 429 + "MetricGroup": "data_fabric", 430 + "PerPkg": "1", 431 + "ScaleUnit": "3.2e-5MB/s" 432 + }, 433 + { 434 + "MetricName": "core_outbound_data_bandwidth_for_remote_socket", 435 + "BriefDescription": "Core outbound data bandwidth for accesses in remote socket.", 436 + "MetricExpr": "(remote_socket_outbound_data_beats_cfi_0 + remote_socket_outbound_data_beats_cfi_1 + remote_socket_outbound_data_beats_cfi_2 + remote_socket_outbound_data_beats_cfi_3 + remote_socket_outbound_data_beats_cfi_4 + remote_socket_outbound_data_beats_cfi_5 + remote_socket_outbound_data_beats_cfi_6 + remote_socket_outbound_data_beats_cfi_7 + remote_socket_outbound_data_beats_cfi_8 + remote_socket_outbound_data_beats_cfi_9 + remote_socket_outbound_data_beats_cfi_10 + remote_socket_outbound_data_beats_cfi_11 + remote_socket_outbound_data_beats_cfi_12 + remote_socket_outbound_data_beats_cfi_13 + remote_socket_outbound_data_beats_cfi_14 + remote_socket_outbound_data_beats_cfi_15) / duration_time", 437 + "MetricGroup": "data_fabric", 438 + "PerPkg": "1", 439 + "ScaleUnit": "6.4e-5MB/s" 440 + }, 441 + { 442 + "MetricName": "cross_socket_inbound_data_bandwidth_for_local_socket", 443 + "BriefDescription": "Inbound data bandwidth for accesses between local socket and remote socket.", 444 + "MetricExpr": "(local_socket_inbound_data_beats_link_0 + local_socket_inbound_data_beats_link_1 + local_socket_inbound_data_beats_link_2 + local_socket_inbound_data_beats_link_3 + local_socket_inbound_data_beats_link_4 + local_socket_inbound_data_beats_link_5) / duration_time", 445 + "MetricGroup": "data_fabric", 446 + "PerPkg": "1", 447 + "ScaleUnit": "6.4e-5MB/s" 448 + }, 449 + { 450 + "MetricName": "cross_socket_outbound_data_bandwidth_for_local_socket", 451 + "BriefDescription": "Outbound data bandwidth for accesses between local socket and remote socket.", 452 + "MetricExpr": "(local_socket_outbound_data_beats_link_0 + local_socket_outbound_data_beats_link_1 + local_socket_outbound_data_beats_link_2 + local_socket_outbound_data_beats_link_3 + local_socket_outbound_data_beats_link_4 + local_socket_outbound_data_beats_link_5) / duration_time", 453 + "MetricGroup": "data_fabric", 454 + "PerPkg": "1", 455 + "ScaleUnit": "6.4e-5MB/s" 344 456 } 345 457 ]
+146 -103
tools/perf/pmu-events/empty-pmu-events.c
··· 19 19 }; 20 20 21 21 static const char *const big_c_string = 22 - /* offset=0 */ "default_core\000" 23 - /* offset=13 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000" 24 - /* offset=72 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000" 25 - /* offset=131 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000" 26 - /* offset=226 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000" 27 - /* offset=325 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000" 28 - /* offset=455 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000" 29 - /* offset=570 */ "hisi_sccl,ddrc\000" 30 - /* offset=585 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000" 31 - /* offset=671 */ "uncore_cbox\000" 32 - /* offset=683 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000" 33 - /* offset=914 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000" 34 - /* offset=979 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000" 35 - /* offset=1050 */ "hisi_sccl,l3c\000" 36 - /* offset=1064 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000" 37 - /* offset=1144 */ "uncore_imc_free_running\000" 38 - /* offset=1168 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000" 39 - /* offset=1263 */ "uncore_imc\000" 40 - /* offset=1274 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000" 41 - /* offset=1352 */ "uncore_sys_ddr_pmu\000" 42 - /* offset=1371 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000" 43 - /* offset=1444 */ "uncore_sys_ccn_pmu\000" 44 - /* offset=1463 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000" 45 - /* offset=1537 */ "uncore_sys_cmn_pmu\000" 46 - /* offset=1556 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000" 47 - /* offset=1696 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" 48 - /* offset=1718 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" 49 - /* offset=1781 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" 50 - /* offset=1947 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" 51 - /* offset=2011 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" 52 - /* offset=2078 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" 53 - /* offset=2149 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" 54 - /* offset=2243 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" 55 - /* offset=2377 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" 56 - /* offset=2441 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" 57 - /* offset=2509 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" 58 - /* offset=2579 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" 59 - /* offset=2601 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" 60 - /* offset=2623 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" 61 - /* offset=2643 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" 22 + /* offset=0 */ "tool\000" 23 + /* offset=5 */ "duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000" 24 + /* offset=78 */ "user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000" 25 + /* offset=145 */ "system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000" 26 + /* offset=210 */ "has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000" 27 + /* offset=283 */ "num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000" 28 + /* offset=425 */ "num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000" 29 + /* offset=525 */ "num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000" 30 + /* offset=639 */ "num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000" 31 + /* offset=712 */ "num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000" 32 + /* offset=795 */ "slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000" 33 + /* offset=902 */ "smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000" 34 + /* offset=1006 */ "system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000" 35 + /* offset=1102 */ "default_core\000" 36 + /* offset=1115 */ "bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000" 37 + /* offset=1174 */ "bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000" 38 + /* offset=1233 */ "l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000" 39 + /* offset=1328 */ "segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000" 40 + /* offset=1427 */ "dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000" 41 + /* offset=1557 */ "eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000" 42 + /* offset=1672 */ "hisi_sccl,ddrc\000" 43 + /* offset=1687 */ "uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000" 44 + /* offset=1773 */ "uncore_cbox\000" 45 + /* offset=1785 */ "unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000" 46 + /* offset=2016 */ "event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000" 47 + /* offset=2081 */ "event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000" 48 + /* offset=2152 */ "hisi_sccl,l3c\000" 49 + /* offset=2166 */ "uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000" 50 + /* offset=2246 */ "uncore_imc_free_running\000" 51 + /* offset=2270 */ "uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000" 52 + /* offset=2365 */ "uncore_imc\000" 53 + /* offset=2376 */ "uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000" 54 + /* offset=2454 */ "uncore_sys_ddr_pmu\000" 55 + /* offset=2473 */ "sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000" 56 + /* offset=2546 */ "uncore_sys_ccn_pmu\000" 57 + /* offset=2565 */ "sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000" 58 + /* offset=2639 */ "uncore_sys_cmn_pmu\000" 59 + /* offset=2658 */ "sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000" 60 + /* offset=2798 */ "CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000" 61 + /* offset=2820 */ "IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000" 62 + /* offset=2883 */ "Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000" 63 + /* offset=3049 */ "dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" 64 + /* offset=3113 */ "icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000" 65 + /* offset=3180 */ "cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000" 66 + /* offset=3251 */ "DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000" 67 + /* offset=3345 */ "DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000" 68 + /* offset=3479 */ "DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000" 69 + /* offset=3543 */ "DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000" 70 + /* offset=3611 */ "DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000" 71 + /* offset=3681 */ "M1\000\000ipc + M2\000\000\000\000\000\000\000\00000" 72 + /* offset=3703 */ "M2\000\000ipc + M1\000\000\000\000\000\000\000\00000" 73 + /* offset=3725 */ "M3\000\0001 / M3\000\000\000\000\000\000\000\00000" 74 + /* offset=3745 */ "L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000" 62 75 ; 63 76 77 + static const struct compact_pmu_event pmu_events__common_tool[] = { 78 + { 5 }, /* duration_time\000tool\000Wall clock interval time in nanoseconds\000config=1\000\00000\000\000 */ 79 + { 210 }, /* has_pmem\000tool\0001 if persistent memory installed otherwise 0\000config=4\000\00000\000\000 */ 80 + { 283 }, /* num_cores\000tool\000Number of cores. A core consists of 1 or more thread, with each thread being associated with a logical Linux CPU\000config=5\000\00000\000\000 */ 81 + { 425 }, /* num_cpus\000tool\000Number of logical Linux CPUs. There may be multiple such CPUs on a core\000config=6\000\00000\000\000 */ 82 + { 525 }, /* num_cpus_online\000tool\000Number of online logical Linux CPUs. There may be multiple such CPUs on a core\000config=7\000\00000\000\000 */ 83 + { 639 }, /* num_dies\000tool\000Number of dies. Each die has 1 or more cores\000config=8\000\00000\000\000 */ 84 + { 712 }, /* num_packages\000tool\000Number of packages. Each package has 1 or more die\000config=9\000\00000\000\000 */ 85 + { 795 }, /* slots\000tool\000Number of functional units that in parallel can execute parts of an instruction\000config=0xa\000\00000\000\000 */ 86 + { 902 }, /* smt_on\000tool\0001 if simultaneous multithreading (aka hyperthreading) is enable otherwise 0\000config=0xb\000\00000\000\000 */ 87 + { 145 }, /* system_time\000tool\000System/kernel time in nanoseconds\000config=3\000\00000\000\000 */ 88 + { 1006 }, /* system_tsc_freq\000tool\000The amount a Time Stamp Counter (TSC) increases per second\000config=0xc\000\00000\000\000 */ 89 + { 78 }, /* user_time\000tool\000User (non-kernel) time in nanoseconds\000config=2\000\00000\000\000 */ 90 + 91 + }; 92 + 93 + const struct pmu_table_entry pmu_events__common[] = { 94 + { 95 + .entries = pmu_events__common_tool, 96 + .num_entries = ARRAY_SIZE(pmu_events__common_tool), 97 + .pmu_name = { 0 /* tool\000 */ }, 98 + }, 99 + }; 100 + 64 101 static const struct compact_pmu_event pmu_events__test_soc_cpu_default_core[] = { 65 - { 13 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000 */ 66 - { 72 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000 */ 67 - { 325 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000 */ 68 - { 455 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000 */ 69 - { 131 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000 */ 70 - { 226 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000 */ 102 + { 1115 }, /* bp_l1_btb_correct\000branch\000L1 BTB Correction\000event=0x8a\000\00000\000\000 */ 103 + { 1174 }, /* bp_l2_btb_correct\000branch\000L2 BTB Correction\000event=0x8b\000\00000\000\000 */ 104 + { 1427 }, /* dispatch_blocked.any\000other\000Memory cluster signals to block micro-op dispatch for any reason\000event=9,period=200000,umask=0x20\000\00000\000\000 */ 105 + { 1557 }, /* eist_trans\000other\000Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions\000event=0x3a,period=200000\000\00000\000\000 */ 106 + { 1233 }, /* l3_cache_rd\000cache\000L3 cache access, read\000event=0x40\000\00000\000Attributable Level 3 cache access, read\000 */ 107 + { 1328 }, /* segment_reg_loads.any\000other\000Number of segment register loads\000event=6,period=200000,umask=0x80\000\00000\000\000 */ 71 108 }; 72 109 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_ddrc[] = { 73 - { 585 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000 */ 110 + { 1687 }, /* uncore_hisi_ddrc.flux_wcmd\000uncore\000DDRC write commands\000event=2\000\00000\000DDRC write commands\000 */ 74 111 }; 75 112 static const struct compact_pmu_event pmu_events__test_soc_cpu_hisi_sccl_l3c[] = { 76 - { 1064 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000 */ 113 + { 2166 }, /* uncore_hisi_l3c.rd_hit_cpipe\000uncore\000Total read hits\000event=7\000\00000\000Total read hits\000 */ 77 114 }; 78 115 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_cbox[] = { 79 - { 914 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000 */ 80 - { 979 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000 */ 81 - { 683 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000 */ 116 + { 2016 }, /* event-hyphen\000uncore\000UNC_CBO_HYPHEN\000event=0xe0\000\00000\000UNC_CBO_HYPHEN\000 */ 117 + { 2081 }, /* event-two-hyph\000uncore\000UNC_CBO_TWO_HYPH\000event=0xc0\000\00000\000UNC_CBO_TWO_HYPH\000 */ 118 + { 1785 }, /* unc_cbo_xsnp_response.miss_eviction\000uncore\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000event=0x22,umask=0x81\000\00000\000A cross-core snoop resulted from L3 Eviction which misses in some processor core\000 */ 82 119 }; 83 120 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc[] = { 84 - { 1274 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000 */ 121 + { 2376 }, /* uncore_imc.cache_hits\000uncore\000Total cache hits\000event=0x34\000\00000\000Total cache hits\000 */ 85 122 }; 86 123 static const struct compact_pmu_event pmu_events__test_soc_cpu_uncore_imc_free_running[] = { 87 - { 1168 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000 */ 124 + { 2270 }, /* uncore_imc_free_running.cache_miss\000uncore\000Total cache misses\000event=0x12\000\00000\000Total cache misses\000 */ 88 125 89 126 }; 90 127 ··· 129 92 { 130 93 .entries = pmu_events__test_soc_cpu_default_core, 131 94 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_default_core), 132 - .pmu_name = { 0 /* default_core\000 */ }, 95 + .pmu_name = { 1102 /* default_core\000 */ }, 133 96 }, 134 97 { 135 98 .entries = pmu_events__test_soc_cpu_hisi_sccl_ddrc, 136 99 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_ddrc), 137 - .pmu_name = { 570 /* hisi_sccl,ddrc\000 */ }, 100 + .pmu_name = { 1672 /* hisi_sccl,ddrc\000 */ }, 138 101 }, 139 102 { 140 103 .entries = pmu_events__test_soc_cpu_hisi_sccl_l3c, 141 104 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_hisi_sccl_l3c), 142 - .pmu_name = { 1050 /* hisi_sccl,l3c\000 */ }, 105 + .pmu_name = { 2152 /* hisi_sccl,l3c\000 */ }, 143 106 }, 144 107 { 145 108 .entries = pmu_events__test_soc_cpu_uncore_cbox, 146 109 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_cbox), 147 - .pmu_name = { 671 /* uncore_cbox\000 */ }, 110 + .pmu_name = { 1773 /* uncore_cbox\000 */ }, 148 111 }, 149 112 { 150 113 .entries = pmu_events__test_soc_cpu_uncore_imc, 151 114 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc), 152 - .pmu_name = { 1263 /* uncore_imc\000 */ }, 115 + .pmu_name = { 2365 /* uncore_imc\000 */ }, 153 116 }, 154 117 { 155 118 .entries = pmu_events__test_soc_cpu_uncore_imc_free_running, 156 119 .num_entries = ARRAY_SIZE(pmu_events__test_soc_cpu_uncore_imc_free_running), 157 - .pmu_name = { 1144 /* uncore_imc_free_running\000 */ }, 120 + .pmu_name = { 2246 /* uncore_imc_free_running\000 */ }, 158 121 }, 159 122 }; 160 123 161 124 static const struct compact_pmu_event pmu_metrics__test_soc_cpu_default_core[] = { 162 - { 1696 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ 163 - { 2377 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ 164 - { 2149 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ 165 - { 2243 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ 166 - { 2441 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ 167 - { 2509 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ 168 - { 1781 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ 169 - { 1718 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ 170 - { 2643 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ 171 - { 2579 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ 172 - { 2601 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ 173 - { 2623 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ 174 - { 2078 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ 175 - { 1947 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ 176 - { 2011 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ 125 + { 2798 }, /* CPI\000\0001 / IPC\000\000\000\000\000\000\000\00000 */ 126 + { 3479 }, /* DCache_L2_All\000\000DCache_L2_All_Hits + DCache_L2_All_Miss\000\000\000\000\000\000\000\00000 */ 127 + { 3251 }, /* DCache_L2_All_Hits\000\000l2_rqsts.demand_data_rd_hit + l2_rqsts.pf_hit + l2_rqsts.rfo_hit\000\000\000\000\000\000\000\00000 */ 128 + { 3345 }, /* DCache_L2_All_Miss\000\000max(l2_rqsts.all_demand_data_rd - l2_rqsts.demand_data_rd_hit, 0) + l2_rqsts.pf_miss + l2_rqsts.rfo_miss\000\000\000\000\000\000\000\00000 */ 129 + { 3543 }, /* DCache_L2_Hits\000\000d_ratio(DCache_L2_All_Hits, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ 130 + { 3611 }, /* DCache_L2_Misses\000\000d_ratio(DCache_L2_All_Miss, DCache_L2_All)\000\000\000\000\000\000\000\00000 */ 131 + { 2883 }, /* Frontend_Bound_SMT\000\000idq_uops_not_delivered.core / (4 * (cpu_clk_unhalted.thread / 2 * (1 + cpu_clk_unhalted.one_thread_active / cpu_clk_unhalted.ref_xclk)))\000\000\000\000\000\000\000\00000 */ 132 + { 2820 }, /* IPC\000group1\000inst_retired.any / cpu_clk_unhalted.thread\000\000\000\000\000\000\000\00000 */ 133 + { 3745 }, /* L1D_Cache_Fill_BW\000\00064 * l1d.replacement / 1e9 / duration_time\000\000\000\000\000\000\000\00000 */ 134 + { 3681 }, /* M1\000\000ipc + M2\000\000\000\000\000\000\000\00000 */ 135 + { 3703 }, /* M2\000\000ipc + M1\000\000\000\000\000\000\000\00000 */ 136 + { 3725 }, /* M3\000\0001 / M3\000\000\000\000\000\000\000\00000 */ 137 + { 3180 }, /* cache_miss_cycles\000group1\000dcache_miss_cpi + icache_miss_cycles\000\000\000\000\000\000\000\00000 */ 138 + { 3049 }, /* dcache_miss_cpi\000\000l1d\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ 139 + { 3113 }, /* icache_miss_cycles\000\000l1i\\-loads\\-misses / inst_retired.any\000\000\000\000\000\000\000\00000 */ 177 140 178 141 }; 179 142 ··· 181 144 { 182 145 .entries = pmu_metrics__test_soc_cpu_default_core, 183 146 .num_entries = ARRAY_SIZE(pmu_metrics__test_soc_cpu_default_core), 184 - .pmu_name = { 0 /* default_core\000 */ }, 147 + .pmu_name = { 1102 /* default_core\000 */ }, 185 148 }, 186 149 }; 187 150 188 151 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ccn_pmu[] = { 189 - { 1463 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000 */ 152 + { 2565 }, /* sys_ccn_pmu.read_cycles\000uncore\000ccn read-cycles event\000config=0x2c\0000x01\00000\000\000 */ 190 153 }; 191 154 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_cmn_pmu[] = { 192 - { 1556 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000 */ 155 + { 2658 }, /* sys_cmn_pmu.hnf_cache_miss\000uncore\000Counts total cache misses in first lookup result (high priority)\000eventid=1,type=5\000(434|436|43c|43a).*\00000\000\000 */ 193 156 }; 194 157 static const struct compact_pmu_event pmu_events__test_soc_sys_uncore_sys_ddr_pmu[] = { 195 - { 1371 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000 */ 158 + { 2473 }, /* sys_ddr_pmu.write_cycles\000uncore\000ddr write-cycles event\000event=0x2b\000v8\00000\000\000 */ 196 159 197 160 }; 198 161 ··· 200 163 { 201 164 .entries = pmu_events__test_soc_sys_uncore_sys_ccn_pmu, 202 165 .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ccn_pmu), 203 - .pmu_name = { 1444 /* uncore_sys_ccn_pmu\000 */ }, 166 + .pmu_name = { 2546 /* uncore_sys_ccn_pmu\000 */ }, 204 167 }, 205 168 { 206 169 .entries = pmu_events__test_soc_sys_uncore_sys_cmn_pmu, 207 170 .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_cmn_pmu), 208 - .pmu_name = { 1537 /* uncore_sys_cmn_pmu\000 */ }, 171 + .pmu_name = { 2639 /* uncore_sys_cmn_pmu\000 */ }, 209 172 }, 210 173 { 211 174 .entries = pmu_events__test_soc_sys_uncore_sys_ddr_pmu, 212 175 .num_entries = ARRAY_SIZE(pmu_events__test_soc_sys_uncore_sys_ddr_pmu), 213 - .pmu_name = { 1352 /* uncore_sys_ddr_pmu\000 */ }, 176 + .pmu_name = { 2454 /* uncore_sys_ddr_pmu\000 */ }, 214 177 }, 215 178 }; 216 179 ··· 247 210 * table of PMU events. 248 211 */ 249 212 const struct pmu_events_map pmu_events_map[] = { 213 + { 214 + .arch = "common", 215 + .cpuid = "common", 216 + .event_table = { 217 + .pmus = pmu_events__common, 218 + .num_pmus = ARRAY_SIZE(pmu_events__common), 219 + }, 220 + .metric_table = {}, 221 + }, 250 222 { 251 223 .arch = "testarch", 252 224 .cpuid = "testcpu", ··· 426 380 continue; 427 381 428 382 ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); 429 - if (pmu || ret) 383 + if (ret) 430 384 return ret; 431 385 } 432 386 return 0; ··· 503 457 return 0; 504 458 } 505 459 506 - static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) 460 + static const struct pmu_events_map *map_for_cpu(struct perf_cpu cpu) 507 461 { 508 462 static struct { 509 463 const struct pmu_events_map *map; 510 - struct perf_pmu *pmu; 464 + struct perf_cpu cpu; 511 465 } last_result; 512 466 static struct { 513 467 const struct pmu_events_map *map; ··· 518 472 char *cpuid = NULL; 519 473 size_t i; 520 474 521 - if (has_last_result && last_result.pmu == pmu) 475 + if (has_last_result && last_result.cpu.cpu == cpu.cpu) 522 476 return last_result.map; 523 477 524 - cpuid = perf_pmu__getcpuid(pmu); 478 + cpuid = get_cpuid_allow_env_override(cpu); 525 479 526 480 /* 527 481 * On some platforms which uses cpus map, cpuid can be NULL for ··· 552 506 has_last_map_search = true; 553 507 } 554 508 out_update_last_result: 555 - last_result.pmu = pmu; 509 + last_result.cpu = cpu; 556 510 last_result.map = map; 557 511 has_last_result = true; 558 512 return map; 513 + } 514 + 515 + static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) 516 + { 517 + struct perf_cpu cpu = {-1}; 518 + 519 + if (pmu) 520 + cpu = perf_cpu_map__min(pmu->cpus); 521 + return map_for_cpu(cpu); 559 522 } 560 523 561 524 const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) ··· 587 532 return NULL; 588 533 } 589 534 590 - const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu) 535 + const struct pmu_metrics_table *pmu_metrics_table__find(void) 591 536 { 592 - const struct pmu_events_map *map = map_for_pmu(pmu); 537 + struct perf_cpu cpu = {-1}; 538 + const struct pmu_events_map *map = map_for_cpu(cpu); 593 539 594 - if (!map) 595 - return NULL; 596 - 597 - if (!pmu) 598 - return &map->metric_table; 599 - 600 - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { 601 - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; 602 - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 603 - 604 - if (pmu__name_match(pmu, pmu_name)) 605 - return &map->metric_table; 606 - } 607 - return NULL; 540 + return map ? &map->metric_table : NULL; 608 541 } 609 542 610 543 const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid)
+33 -24
tools/perf/pmu-events/jevents.py
··· 292 292 'cpu_atom': 'cpu_atom', 293 293 'ali_drw': 'ali_drw', 294 294 'arm_cmn': 'arm_cmn', 295 + 'tool': 'tool', 295 296 } 296 297 return table[unit] if unit in table else f'uncore_{unit.lower()}' 297 298 ··· 723 722 \t} 724 723 }, 725 724 """) 725 + elif arch == 'common': 726 + _args.output_file.write("""{ 727 + \t.arch = "common", 728 + \t.cpuid = "common", 729 + \t.event_table = { 730 + \t\t.pmus = pmu_events__common, 731 + \t\t.num_pmus = ARRAY_SIZE(pmu_events__common), 732 + \t}, 733 + \t.metric_table = {}, 734 + }, 735 + """) 726 736 else: 727 737 with open(f'{_args.starting_dir}/{arch}/mapfile.csv') as csvfile: 728 738 table = csv.reader(csvfile) ··· 942 930 continue; 943 931 944 932 ret = pmu_events_table__for_each_event_pmu(table, table_pmu, fn, data); 945 - if (pmu || ret) 933 + if (ret) 946 934 return ret; 947 935 } 948 936 return 0; ··· 1019 1007 return 0; 1020 1008 } 1021 1009 1022 - static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) 1010 + static const struct pmu_events_map *map_for_cpu(struct perf_cpu cpu) 1023 1011 { 1024 1012 static struct { 1025 1013 const struct pmu_events_map *map; 1026 - struct perf_pmu *pmu; 1014 + struct perf_cpu cpu; 1027 1015 } last_result; 1028 1016 static struct { 1029 1017 const struct pmu_events_map *map; ··· 1034 1022 char *cpuid = NULL; 1035 1023 size_t i; 1036 1024 1037 - if (has_last_result && last_result.pmu == pmu) 1025 + if (has_last_result && last_result.cpu.cpu == cpu.cpu) 1038 1026 return last_result.map; 1039 1027 1040 - cpuid = perf_pmu__getcpuid(pmu); 1028 + cpuid = get_cpuid_allow_env_override(cpu); 1041 1029 1042 1030 /* 1043 1031 * On some platforms which uses cpus map, cpuid can be NULL for ··· 1068 1056 has_last_map_search = true; 1069 1057 } 1070 1058 out_update_last_result: 1071 - last_result.pmu = pmu; 1059 + last_result.cpu = cpu; 1072 1060 last_result.map = map; 1073 1061 has_last_result = true; 1074 1062 return map; 1063 + } 1064 + 1065 + static const struct pmu_events_map *map_for_pmu(struct perf_pmu *pmu) 1066 + { 1067 + struct perf_cpu cpu = {-1}; 1068 + 1069 + if (pmu) 1070 + cpu = perf_cpu_map__min(pmu->cpus); 1071 + return map_for_cpu(cpu); 1075 1072 } 1076 1073 1077 1074 const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu) ··· 1103 1082 return NULL; 1104 1083 } 1105 1084 1106 - const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu) 1085 + const struct pmu_metrics_table *pmu_metrics_table__find(void) 1107 1086 { 1108 - const struct pmu_events_map *map = map_for_pmu(pmu); 1087 + struct perf_cpu cpu = {-1}; 1088 + const struct pmu_events_map *map = map_for_cpu(cpu); 1109 1089 1110 - if (!map) 1111 - return NULL; 1112 - 1113 - if (!pmu) 1114 - return &map->metric_table; 1115 - 1116 - for (size_t i = 0; i < map->metric_table.num_pmus; i++) { 1117 - const struct pmu_table_entry *table_pmu = &map->metric_table.pmus[i]; 1118 - const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset]; 1119 - 1120 - if (pmu__name_match(pmu, pmu_name)) 1121 - return &map->metric_table; 1122 - } 1123 - return NULL; 1090 + return map ? &map->metric_table : NULL; 1124 1091 } 1125 1092 1126 1093 const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid) ··· 1250 1241 if len(parents) == _args.model.split(',')[0].count('/'): 1251 1242 # We're testing the correct directory. 1252 1243 item_path = '/'.join(parents) + ('/' if len(parents) > 0 else '') + item.name 1253 - if 'test' not in item_path and item_path not in _args.model.split(','): 1244 + if 'test' not in item_path and 'common' not in item_path and item_path not in _args.model.split(','): 1254 1245 continue 1255 1246 action(parents, item) 1256 1247 if item.is_dir(): ··· 1298 1289 for item in os.scandir(_args.starting_dir): 1299 1290 if not item.is_dir(): 1300 1291 continue 1301 - if item.name == _args.arch or _args.arch == 'all' or item.name == 'test': 1292 + if item.name == _args.arch or _args.arch == 'all' or item.name == 'test' or item.name == 'common': 1302 1293 archs.append(item.name) 1303 1294 1304 1295 if len(archs) < 2 and _args.arch != 'none':
+1 -1
tools/perf/pmu-events/pmu-events.h
··· 103 103 void *data); 104 104 105 105 const struct pmu_events_table *perf_pmu__find_events_table(struct perf_pmu *pmu); 106 - const struct pmu_metrics_table *perf_pmu__find_metrics_table(struct perf_pmu *pmu); 106 + const struct pmu_metrics_table *pmu_metrics_table__find(void); 107 107 const struct pmu_events_table *find_core_events_table(const char *arch, const char *cpuid); 108 108 const struct pmu_metrics_table *find_core_metrics_table(const char *arch, const char *cpuid); 109 109 int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data);
+11
tools/perf/scripts/python/Perf-Trace-Util/Context.c
··· 12 12 #define PY_SSIZE_T_CLEAN 13 13 14 14 #include <Python.h> 15 + #include "../../../util/config.h" 15 16 #include "../../../util/trace-event.h" 16 17 #include "../../../util/event.h" 17 18 #include "../../../util/symbol.h" ··· 183 182 return perf_sample_src(obj, args, true); 184 183 } 185 184 185 + static PyObject *__perf_config_get(PyObject *obj, PyObject *args) 186 + { 187 + const char *config_name; 188 + 189 + if (!PyArg_ParseTuple(args, "s", &config_name)) 190 + return NULL; 191 + return Py_BuildValue("s", perf_config_get(config_name)); 192 + } 193 + 186 194 static PyMethodDef ContextMethods[] = { 187 195 #ifdef HAVE_LIBTRACEEVENT 188 196 { "common_pc", perf_trace_context_common_pc, METH_VARARGS, ··· 209 199 METH_VARARGS, "Get source file name and line number."}, 210 200 { "perf_sample_srccode", perf_sample_srccode, 211 201 METH_VARARGS, "Get source file name, line number and line."}, 202 + { "perf_config_get", __perf_config_get, METH_VARARGS, "Get perf config entry"}, 212 203 { NULL, NULL, 0, NULL} 213 204 }; 214 205
+112 -31
tools/perf/scripts/python/arm-cs-trace-disasm.py
··· 11 11 from os import path 12 12 import re 13 13 from subprocess import * 14 - from optparse import OptionParser, make_option 14 + import argparse 15 + import platform 15 16 16 - from perf_trace_context import perf_set_itrace_options, \ 17 - perf_sample_insn, perf_sample_srccode 17 + from perf_trace_context import perf_sample_srccode, perf_config_get 18 18 19 19 # Below are some example commands for using this script. 20 + # Note a --kcore recording is required for accurate decode 21 + # due to the alternatives patching mechanism. However this 22 + # script only supports reading vmlinux for disassembly dump, 23 + # meaning that any patched instructions will appear 24 + # as unpatched, but the instruction ranges themselves will 25 + # be correct. In addition to this, source line info comes 26 + # from Perf, and when using kcore there is no debug info. The 27 + # following lists the supported features in each mode: 20 28 # 21 - # Output disassembly with objdump: 22 - # perf script -s scripts/python/arm-cs-trace-disasm.py \ 23 - # -- -d objdump -k path/to/vmlinux 29 + # +-----------+-----------------+------------------+------------------+ 30 + # | Recording | Accurate decode | Source line dump | Disassembly dump | 31 + # +-----------+-----------------+------------------+------------------+ 32 + # | --kcore | yes | no | yes | 33 + # | normal | no | yes | yes | 34 + # +-----------+-----------------+------------------+------------------+ 35 + # 36 + # Output disassembly with objdump and auto detect vmlinux 37 + # (when running on same machine.) 38 + # perf script -s scripts/python/arm-cs-trace-disasm.py -d 39 + # 24 40 # Output disassembly with llvm-objdump: 25 41 # perf script -s scripts/python/arm-cs-trace-disasm.py \ 26 42 # -- -d llvm-objdump-11 -k path/to/vmlinux 43 + # 27 44 # Output only source line and symbols: 28 45 # perf script -s scripts/python/arm-cs-trace-disasm.py 29 46 30 - # Command line parsing. 31 - option_list = [ 32 - # formatting options for the bottom entry of the stack 33 - make_option("-k", "--vmlinux", dest="vmlinux_name", 34 - help="Set path to vmlinux file"), 35 - make_option("-d", "--objdump", dest="objdump_name", 36 - help="Set path to objdump executable file"), 37 - make_option("-v", "--verbose", dest="verbose", 38 - action="store_true", default=False, 39 - help="Enable debugging log") 40 - ] 47 + def default_objdump(): 48 + config = perf_config_get("annotate.objdump") 49 + return config if config else "objdump" 41 50 42 - parser = OptionParser(option_list=option_list) 43 - (options, args) = parser.parse_args() 51 + # Command line parsing. 52 + def int_arg(v): 53 + v = int(v) 54 + if v < 0: 55 + raise argparse.ArgumentTypeError("Argument must be a positive integer") 56 + return v 57 + 58 + args = argparse.ArgumentParser() 59 + args.add_argument("-k", "--vmlinux", 60 + help="Set path to vmlinux file. Omit to autodetect if running on same machine") 61 + args.add_argument("-d", "--objdump", nargs="?", const=default_objdump(), 62 + help="Show disassembly. Can also be used to change the objdump path"), 63 + args.add_argument("-v", "--verbose", action="store_true", help="Enable debugging log") 64 + args.add_argument("--start-time", type=int_arg, help="Monotonic clock time of sample to start from. " 65 + "See 'time' field on samples in -v mode.") 66 + args.add_argument("--stop-time", type=int_arg, help="Monotonic clock time of sample to stop at. " 67 + "See 'time' field on samples in -v mode.") 68 + args.add_argument("--start-sample", type=int_arg, help="Index of sample to start from. " 69 + "See 'index' field on samples in -v mode.") 70 + args.add_argument("--stop-sample", type=int_arg, help="Index of sample to stop at. " 71 + "See 'index' field on samples in -v mode.") 72 + 73 + options = args.parse_args() 74 + if (options.start_time and options.stop_time and 75 + options.start_time >= options.stop_time): 76 + print("--start-time must less than --stop-time") 77 + exit(2) 78 + if (options.start_sample and options.stop_sample and 79 + options.start_sample >= options.stop_sample): 80 + print("--start-sample must less than --stop-sample") 81 + exit(2) 44 82 45 83 # Initialize global dicts and regular expression 46 84 disasm_cache = dict() ··· 86 48 disasm_re = re.compile(r"^\s*([0-9a-fA-F]+):") 87 49 disasm_func_re = re.compile(r"^\s*([0-9a-fA-F]+)\s.*:") 88 50 cache_size = 64*1024 51 + sample_idx = -1 89 52 90 53 glb_source_file_name = None 91 54 glb_line_number = None 92 55 glb_dso = None 56 + 57 + kver = platform.release() 58 + vmlinux_paths = [ 59 + f"/usr/lib/debug/boot/vmlinux-{kver}.debug", 60 + f"/usr/lib/debug/lib/modules/{kver}/vmlinux", 61 + f"/lib/modules/{kver}/build/vmlinux", 62 + f"/usr/lib/debug/boot/vmlinux-{kver}", 63 + f"/boot/vmlinux-{kver}", 64 + f"/boot/vmlinux", 65 + f"vmlinux" 66 + ] 93 67 94 68 def get_optional(perf_dict, field): 95 69 if field in perf_dict: ··· 113 63 return "+%#x" % perf_dict[field] 114 64 return "" 115 65 66 + def find_vmlinux(): 67 + if hasattr(find_vmlinux, "path"): 68 + return find_vmlinux.path 69 + 70 + for v in vmlinux_paths: 71 + if os.access(v, os.R_OK): 72 + find_vmlinux.path = v 73 + break 74 + else: 75 + find_vmlinux.path = None 76 + 77 + return find_vmlinux.path 78 + 116 79 def get_dso_file_path(dso_name, dso_build_id): 117 80 if (dso_name == "[kernel.kallsyms]" or dso_name == "vmlinux"): 118 - if (options.vmlinux_name): 119 - return options.vmlinux_name; 81 + if (options.vmlinux): 82 + return options.vmlinux; 120 83 else: 121 - return dso_name 84 + return find_vmlinux() if find_vmlinux() else dso_name 122 85 123 86 if (dso_name == "[vdso]") : 124 87 append = "/vdso" ··· 155 92 else: 156 93 start_addr = start_addr - dso_start; 157 94 stop_addr = stop_addr - dso_start; 158 - disasm = [ options.objdump_name, "-d", "-z", 95 + disasm = [ options.objdump, "-d", "-z", 159 96 "--start-address="+format(start_addr,"#x"), 160 97 "--stop-address="+format(stop_addr,"#x") ] 161 98 disasm += [ dso_fname ] ··· 175 112 176 113 def print_sample(sample): 177 114 print("Sample = { cpu: %04d addr: 0x%016x phys_addr: 0x%016x ip: 0x%016x " \ 178 - "pid: %d tid: %d period: %d time: %d }" % \ 115 + "pid: %d tid: %d period: %d time: %d index: %d}" % \ 179 116 (sample['cpu'], sample['addr'], sample['phys_addr'], \ 180 117 sample['ip'], sample['pid'], sample['tid'], \ 181 - sample['period'], sample['time'])) 118 + sample['period'], sample['time'], sample_idx)) 182 119 183 120 def trace_begin(): 184 121 print('ARM CoreSight Trace Data Assembler Dump') ··· 240 177 def process_event(param_dict): 241 178 global cache_size 242 179 global options 180 + global sample_idx 243 181 244 182 sample = param_dict["sample"] 245 183 comm = param_dict["comm"] ··· 251 187 dso_start = get_optional(param_dict, "dso_map_start") 252 188 dso_end = get_optional(param_dict, "dso_map_end") 253 189 symbol = get_optional(param_dict, "symbol") 190 + map_pgoff = get_optional(param_dict, "map_pgoff") 191 + # check for valid map offset 192 + if (str(map_pgoff) == '[unknown]'): 193 + map_pgoff = 0 254 194 255 195 cpu = sample["cpu"] 256 196 ip = sample["ip"] 257 197 addr = sample["addr"] 198 + 199 + sample_idx += 1 200 + 201 + if (options.start_time and sample["time"] < options.start_time): 202 + return 203 + if (options.stop_time and sample["time"] > options.stop_time): 204 + exit(0) 205 + if (options.start_sample and sample_idx < options.start_sample): 206 + return 207 + if (options.stop_sample and sample_idx > options.stop_sample): 208 + exit(0) 258 209 259 210 if (options.verbose == True): 260 211 print("Event type: %s" % name) ··· 322 243 # Record for previous sample packet 323 244 cpu_data[str(cpu) + 'addr'] = addr 324 245 325 - # Handle CS_ETM_TRACE_ON packet if start_addr=0 and stop_addr=4 326 - if (start_addr == 0 and stop_addr == 4): 327 - print("CPU%d: CS_ETM_TRACE_ON packet is inserted" % cpu) 246 + # Filter out zero start_address. Optionally identify CS_ETM_TRACE_ON packet 247 + if (start_addr == 0): 248 + if ((stop_addr == 4) and (options.verbose == True)): 249 + print("CPU%d: CS_ETM_TRACE_ON packet is inserted" % cpu) 328 250 return 329 251 330 252 if (start_addr < int(dso_start) or start_addr > int(dso_end)): ··· 336 256 print("Stop address 0x%x is out of range [ 0x%x .. 0x%x ] for dso %s" % (stop_addr, int(dso_start), int(dso_end), dso)) 337 257 return 338 258 339 - if (options.objdump_name != None): 259 + if (options.objdump != None): 340 260 # It doesn't need to decrease virtual memory offset for disassembly 341 261 # for kernel dso and executable file dso, so in this case we set 342 262 # vm_start to zero. 343 263 if (dso == "[kernel.kallsyms]" or dso_start == 0x400000): 344 264 dso_vm_start = 0 265 + map_pgoff = 0 345 266 else: 346 267 dso_vm_start = int(dso_start) 347 268 348 269 dso_fname = get_dso_file_path(dso, dso_bid) 349 270 if path.exists(dso_fname): 350 - print_disam(dso_fname, dso_vm_start, start_addr, stop_addr) 271 + print_disam(dso_fname, dso_vm_start, start_addr + map_pgoff, stop_addr + map_pgoff) 351 272 else: 352 - print("Failed to find dso %s for address range [ 0x%x .. 0x%x ]" % (dso, start_addr, stop_addr)) 273 + print("Failed to find dso %s for address range [ 0x%x .. 0x%x ]" % (dso, start_addr + map_pgoff, stop_addr + map_pgoff)) 353 274 354 275 print_srccode(comm, param_dict, sample, symbol, dso)
+2 -2
tools/perf/tests/Build
··· 4 4 perf-test-y += tests-scripts.o 5 5 perf-test-y += parse-events.o 6 6 perf-test-y += dso-data.o 7 - perf-test-y += attr.o 8 7 perf-test-y += vmlinux-kallsyms.o 9 8 perf-test-$(CONFIG_LIBTRACEEVENT) += openat-syscall.o 10 9 perf-test-$(CONFIG_LIBTRACEEVENT) += openat-syscall-all-cpus.o ··· 66 67 perf-test-y += event_groups.o 67 68 perf-test-y += symbols.o 68 69 perf-test-y += util.o 70 + perf-test-y += hwmon_pmu.o 71 + perf-test-y += tool_pmu.o 69 72 70 73 ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 arm arm64 powerpc)) 71 74 perf-test-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o 72 75 endif 73 76 74 - CFLAGS_attr.o += -DBINDIR="BUILD_STR($(bindir_SQ))" -DPYTHON="BUILD_STR($(PYTHON_WORD))" 75 77 CFLAGS_python-use.o += -DPYTHONPATH="BUILD_STR($(OUTPUT)python)" -DPYTHON="BUILD_STR($(PYTHON_WORD))" 76 78 CFLAGS_dwarf-unwind.o += -fno-optimize-sibling-calls 77 79
-218
tools/perf/tests/attr.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * The struct perf_event_attr test support. 4 - * 5 - * This test is embedded inside into perf directly and is governed 6 - * by the PERF_TEST_ATTR environment variable and hook inside 7 - * sys_perf_event_open function. 8 - * 9 - * The general idea is to store 'struct perf_event_attr' details for 10 - * each event created within single perf command. Each event details 11 - * are stored into separate text file. Once perf command is finished 12 - * these files can be checked for values we expect for command. 13 - * 14 - * Besides 'struct perf_event_attr' values we also store 'fd' and 15 - * 'group_fd' values to allow checking for groups created. 16 - * 17 - * This all is triggered by setting PERF_TEST_ATTR environment variable. 18 - * It must contain name of existing directory with access and write 19 - * permissions. All the event text files are stored there. 20 - */ 21 - 22 - #include <debug.h> 23 - #include <errno.h> 24 - #include <inttypes.h> 25 - #include <stdlib.h> 26 - #include <stdio.h> 27 - #include <linux/types.h> 28 - #include <linux/kernel.h> 29 - #include <sys/param.h> 30 - #include <sys/types.h> 31 - #include <sys/stat.h> 32 - #include <unistd.h> 33 - #include <subcmd/exec-cmd.h> 34 - #include "event.h" 35 - #include "util.h" 36 - #include "tests.h" 37 - #include "pmus.h" 38 - 39 - #define ENV "PERF_TEST_ATTR" 40 - 41 - static char *dir; 42 - static bool ready; 43 - 44 - void test_attr__init(void) 45 - { 46 - dir = getenv(ENV); 47 - test_attr__enabled = (dir != NULL); 48 - } 49 - 50 - #define BUFSIZE 1024 51 - 52 - #define __WRITE_ASS(str, fmt, data) \ 53 - do { \ 54 - char buf[BUFSIZE]; \ 55 - size_t size; \ 56 - \ 57 - size = snprintf(buf, BUFSIZE, #str "=%"fmt "\n", data); \ 58 - if (1 != fwrite(buf, size, 1, file)) { \ 59 - perror("test attr - failed to write event file"); \ 60 - fclose(file); \ 61 - return -1; \ 62 - } \ 63 - \ 64 - } while (0) 65 - 66 - #define WRITE_ASS(field, fmt) __WRITE_ASS(field, fmt, attr->field) 67 - 68 - static int store_event(struct perf_event_attr *attr, pid_t pid, struct perf_cpu cpu, 69 - int fd, int group_fd, unsigned long flags) 70 - { 71 - FILE *file; 72 - char path[PATH_MAX]; 73 - 74 - if (!ready) 75 - return 0; 76 - 77 - snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir, 78 - attr->type, attr->config, fd); 79 - 80 - file = fopen(path, "w+"); 81 - if (!file) { 82 - perror("test attr - failed to open event file"); 83 - return -1; 84 - } 85 - 86 - if (fprintf(file, "[event-%d-%llu-%d]\n", 87 - attr->type, attr->config, fd) < 0) { 88 - perror("test attr - failed to write event file"); 89 - fclose(file); 90 - return -1; 91 - } 92 - 93 - /* syscall arguments */ 94 - __WRITE_ASS(fd, "d", fd); 95 - __WRITE_ASS(group_fd, "d", group_fd); 96 - __WRITE_ASS(cpu, "d", cpu.cpu); 97 - __WRITE_ASS(pid, "d", pid); 98 - __WRITE_ASS(flags, "lu", flags); 99 - 100 - /* struct perf_event_attr */ 101 - WRITE_ASS(type, PRIu32); 102 - WRITE_ASS(size, PRIu32); 103 - WRITE_ASS(config, "llu"); 104 - WRITE_ASS(sample_period, "llu"); 105 - WRITE_ASS(sample_type, "llu"); 106 - WRITE_ASS(read_format, "llu"); 107 - WRITE_ASS(disabled, "d"); 108 - WRITE_ASS(inherit, "d"); 109 - WRITE_ASS(pinned, "d"); 110 - WRITE_ASS(exclusive, "d"); 111 - WRITE_ASS(exclude_user, "d"); 112 - WRITE_ASS(exclude_kernel, "d"); 113 - WRITE_ASS(exclude_hv, "d"); 114 - WRITE_ASS(exclude_idle, "d"); 115 - WRITE_ASS(mmap, "d"); 116 - WRITE_ASS(comm, "d"); 117 - WRITE_ASS(freq, "d"); 118 - WRITE_ASS(inherit_stat, "d"); 119 - WRITE_ASS(enable_on_exec, "d"); 120 - WRITE_ASS(task, "d"); 121 - WRITE_ASS(watermark, "d"); 122 - WRITE_ASS(precise_ip, "d"); 123 - WRITE_ASS(mmap_data, "d"); 124 - WRITE_ASS(sample_id_all, "d"); 125 - WRITE_ASS(exclude_host, "d"); 126 - WRITE_ASS(exclude_guest, "d"); 127 - WRITE_ASS(exclude_callchain_kernel, "d"); 128 - WRITE_ASS(exclude_callchain_user, "d"); 129 - WRITE_ASS(mmap2, "d"); 130 - WRITE_ASS(comm_exec, "d"); 131 - WRITE_ASS(context_switch, "d"); 132 - WRITE_ASS(write_backward, "d"); 133 - WRITE_ASS(namespaces, "d"); 134 - WRITE_ASS(use_clockid, "d"); 135 - WRITE_ASS(wakeup_events, PRIu32); 136 - WRITE_ASS(bp_type, PRIu32); 137 - WRITE_ASS(config1, "llu"); 138 - WRITE_ASS(config2, "llu"); 139 - WRITE_ASS(branch_sample_type, "llu"); 140 - WRITE_ASS(sample_regs_user, "llu"); 141 - WRITE_ASS(sample_stack_user, PRIu32); 142 - 143 - fclose(file); 144 - return 0; 145 - } 146 - 147 - void test_attr__open(struct perf_event_attr *attr, pid_t pid, struct perf_cpu cpu, 148 - int fd, int group_fd, unsigned long flags) 149 - { 150 - int errno_saved = errno; 151 - 152 - if ((fd != -1) && store_event(attr, pid, cpu, fd, group_fd, flags)) { 153 - pr_err("test attr FAILED"); 154 - exit(128); 155 - } 156 - 157 - errno = errno_saved; 158 - } 159 - 160 - void test_attr__ready(void) 161 - { 162 - if (unlikely(test_attr__enabled) && !ready) 163 - ready = true; 164 - } 165 - 166 - static int run_dir(const char *d, const char *perf) 167 - { 168 - char v[] = "-vvvvv"; 169 - int vcnt = min(verbose, (int) sizeof(v) - 1); 170 - char cmd[3*PATH_MAX]; 171 - 172 - if (verbose > 0) 173 - vcnt++; 174 - 175 - scnprintf(cmd, 3*PATH_MAX, PYTHON " %s/attr.py -d %s/attr/ -p %s %.*s", 176 - d, d, perf, vcnt, v); 177 - 178 - return system(cmd) ? TEST_FAIL : TEST_OK; 179 - } 180 - 181 - static int test__attr(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 182 - { 183 - struct stat st; 184 - char path_perf[PATH_MAX]; 185 - char path_dir[PATH_MAX]; 186 - char *exec_path; 187 - 188 - if (perf_pmus__num_core_pmus() > 1) { 189 - /* 190 - * TODO: Attribute tests hard code the PMU type. If there are >1 191 - * core PMU then each PMU will have a different type which 192 - * requires additional support. 193 - */ 194 - pr_debug("Skip test on hybrid systems"); 195 - return TEST_SKIP; 196 - } 197 - 198 - /* First try development tree tests. */ 199 - if (!lstat("./tests", &st)) 200 - return run_dir("./tests", "./perf"); 201 - 202 - exec_path = get_argv_exec_path(); 203 - if (exec_path == NULL) 204 - return -1; 205 - 206 - /* Then installed path. */ 207 - snprintf(path_dir, PATH_MAX, "%s/tests", exec_path); 208 - snprintf(path_perf, PATH_MAX, "%s/perf", BINDIR); 209 - free(exec_path); 210 - 211 - if (!lstat(path_dir, &st) && 212 - !lstat(path_perf, &st)) 213 - return run_dir(path_dir, path_perf); 214 - 215 - return TEST_SKIP; 216 - } 217 - 218 - DEFINE_SUITE("Setup struct perf_event_attr", attr);
-458
tools/perf/tests/attr.py
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - 3 - from __future__ import print_function 4 - 5 - import os 6 - import sys 7 - import glob 8 - import optparse 9 - import platform 10 - import tempfile 11 - import logging 12 - import re 13 - import shutil 14 - import subprocess 15 - 16 - try: 17 - import configparser 18 - except ImportError: 19 - import ConfigParser as configparser 20 - 21 - def data_equal(a, b): 22 - # Allow multiple values in assignment separated by '|' 23 - a_list = a.split('|') 24 - b_list = b.split('|') 25 - 26 - for a_item in a_list: 27 - for b_item in b_list: 28 - if (a_item == b_item): 29 - return True 30 - elif (a_item == '*') or (b_item == '*'): 31 - return True 32 - 33 - return False 34 - 35 - class Fail(Exception): 36 - def __init__(self, test, msg): 37 - self.msg = msg 38 - self.test = test 39 - def getMsg(self): 40 - return '\'%s\' - %s' % (self.test.path, self.msg) 41 - 42 - class Notest(Exception): 43 - def __init__(self, test, arch): 44 - self.arch = arch 45 - self.test = test 46 - def getMsg(self): 47 - return '[%s] \'%s\'' % (self.arch, self.test.path) 48 - 49 - class Unsup(Exception): 50 - def __init__(self, test): 51 - self.test = test 52 - def getMsg(self): 53 - return '\'%s\'' % self.test.path 54 - 55 - class Event(dict): 56 - terms = [ 57 - 'cpu', 58 - 'flags', 59 - 'type', 60 - 'size', 61 - 'config', 62 - 'sample_period', 63 - 'sample_type', 64 - 'read_format', 65 - 'disabled', 66 - 'inherit', 67 - 'pinned', 68 - 'exclusive', 69 - 'exclude_user', 70 - 'exclude_kernel', 71 - 'exclude_hv', 72 - 'exclude_idle', 73 - 'mmap', 74 - 'comm', 75 - 'freq', 76 - 'inherit_stat', 77 - 'enable_on_exec', 78 - 'task', 79 - 'watermark', 80 - 'precise_ip', 81 - 'mmap_data', 82 - 'sample_id_all', 83 - 'exclude_host', 84 - 'exclude_guest', 85 - 'exclude_callchain_kernel', 86 - 'exclude_callchain_user', 87 - 'wakeup_events', 88 - 'bp_type', 89 - 'config1', 90 - 'config2', 91 - 'branch_sample_type', 92 - 'sample_regs_user', 93 - 'sample_stack_user', 94 - ] 95 - 96 - def add(self, data): 97 - for key, val in data: 98 - log.debug(" %s = %s" % (key, val)) 99 - self[key] = val 100 - 101 - def __init__(self, name, data, base): 102 - log.debug(" Event %s" % name); 103 - self.name = name; 104 - self.group = '' 105 - self.add(base) 106 - self.add(data) 107 - 108 - def equal(self, other): 109 - for t in Event.terms: 110 - log.debug(" [%s] %s %s" % (t, self[t], other[t])); 111 - if t not in self or t not in other: 112 - return False 113 - if not data_equal(self[t], other[t]): 114 - return False 115 - return True 116 - 117 - def optional(self): 118 - if 'optional' in self and self['optional'] == '1': 119 - return True 120 - return False 121 - 122 - def diff(self, other): 123 - for t in Event.terms: 124 - if t not in self or t not in other: 125 - continue 126 - if not data_equal(self[t], other[t]): 127 - log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) 128 - 129 - def parse_version(version): 130 - if not version: 131 - return None 132 - return [int(v) for v in version.split(".")[0:2]] 133 - 134 - # Test file description needs to have following sections: 135 - # [config] 136 - # - just single instance in file 137 - # - needs to specify: 138 - # 'command' - perf command name 139 - # 'args' - special command arguments 140 - # 'ret' - Skip test if Perf doesn't exit with this value (0 by default) 141 - # 'test_ret'- If set to 'true', fail test instead of skipping for 'ret' argument 142 - # 'arch' - architecture specific test (optional) 143 - # comma separated list, ! at the beginning 144 - # negates it. 145 - # 'auxv' - Truthy statement that is evaled in the scope of the auxv map. When false, 146 - # the test is skipped. For example 'auxv["AT_HWCAP"] == 10'. (optional) 147 - # 'kernel_since' - Inclusive kernel version from which the test will start running. Only the 148 - # first two values are supported, for example "6.1" (optional) 149 - # 'kernel_until' - Exclusive kernel version from which the test will stop running. (optional) 150 - # [eventX:base] 151 - # - one or multiple instances in file 152 - # - expected values assignments 153 - class Test(object): 154 - def __init__(self, path, options): 155 - parser = configparser.ConfigParser() 156 - parser.read(path) 157 - 158 - log.warning("running '%s'" % path) 159 - 160 - self.path = path 161 - self.test_dir = options.test_dir 162 - self.perf = options.perf 163 - self.command = parser.get('config', 'command') 164 - self.args = parser.get('config', 'args') 165 - 166 - try: 167 - self.ret = parser.get('config', 'ret') 168 - except: 169 - self.ret = 0 170 - 171 - self.test_ret = parser.getboolean('config', 'test_ret', fallback=False) 172 - 173 - try: 174 - self.arch = parser.get('config', 'arch') 175 - log.warning("test limitation '%s'" % self.arch) 176 - except: 177 - self.arch = '' 178 - 179 - self.auxv = parser.get('config', 'auxv', fallback=None) 180 - self.kernel_since = parse_version(parser.get('config', 'kernel_since', fallback=None)) 181 - self.kernel_until = parse_version(parser.get('config', 'kernel_until', fallback=None)) 182 - self.expect = {} 183 - self.result = {} 184 - log.debug(" loading expected events"); 185 - self.load_events(path, self.expect) 186 - 187 - def is_event(self, name): 188 - if name.find("event") == -1: 189 - return False 190 - else: 191 - return True 192 - 193 - def skip_test_kernel_since(self): 194 - if not self.kernel_since: 195 - return False 196 - return not self.kernel_since <= parse_version(platform.release()) 197 - 198 - def skip_test_kernel_until(self): 199 - if not self.kernel_until: 200 - return False 201 - return not parse_version(platform.release()) < self.kernel_until 202 - 203 - def skip_test_auxv(self): 204 - def new_auxv(a, pattern): 205 - items = list(filter(None, pattern.split(a))) 206 - # AT_HWCAP is hex but doesn't have a prefix, so special case it 207 - if items[0] == "AT_HWCAP": 208 - value = int(items[-1], 16) 209 - else: 210 - try: 211 - value = int(items[-1], 0) 212 - except: 213 - value = items[-1] 214 - return (items[0], value) 215 - 216 - if not self.auxv: 217 - return False 218 - auxv = subprocess.check_output("LD_SHOW_AUXV=1 sleep 0", shell=True) \ 219 - .decode(sys.stdout.encoding) 220 - pattern = re.compile(r"[: ]+") 221 - auxv = dict([new_auxv(a, pattern) for a in auxv.splitlines()]) 222 - return not eval(self.auxv) 223 - 224 - def skip_test_arch(self, myarch): 225 - # If architecture not set always run test 226 - if self.arch == '': 227 - # log.warning("test for arch %s is ok" % myarch) 228 - return False 229 - 230 - # Allow multiple values in assignment separated by ',' 231 - arch_list = self.arch.split(',') 232 - 233 - # Handle negated list such as !s390x,ppc 234 - if arch_list[0][0] == '!': 235 - arch_list[0] = arch_list[0][1:] 236 - log.warning("excluded architecture list %s" % arch_list) 237 - for arch_item in arch_list: 238 - # log.warning("test for %s arch is %s" % (arch_item, myarch)) 239 - if arch_item == myarch: 240 - return True 241 - return False 242 - 243 - for arch_item in arch_list: 244 - # log.warning("test for architecture '%s' current '%s'" % (arch_item, myarch)) 245 - if arch_item == myarch: 246 - return False 247 - return True 248 - 249 - def load_events(self, path, events): 250 - parser_event = configparser.ConfigParser() 251 - parser_event.read(path) 252 - 253 - # The event record section header contains 'event' word, 254 - # optionaly followed by ':' allowing to load 'parent 255 - # event' first as a base 256 - for section in filter(self.is_event, parser_event.sections()): 257 - 258 - parser_items = parser_event.items(section); 259 - base_items = {} 260 - 261 - # Read parent event if there's any 262 - if (':' in section): 263 - base = section[section.index(':') + 1:] 264 - parser_base = configparser.ConfigParser() 265 - parser_base.read(self.test_dir + '/' + base) 266 - base_items = parser_base.items('event') 267 - 268 - e = Event(section, parser_items, base_items) 269 - events[section] = e 270 - 271 - def run_cmd(self, tempdir): 272 - junk1, junk2, junk3, junk4, myarch = (os.uname()) 273 - 274 - if self.skip_test_arch(myarch): 275 - raise Notest(self, myarch) 276 - 277 - if self.skip_test_auxv(): 278 - raise Notest(self, "auxv skip") 279 - 280 - if self.skip_test_kernel_since(): 281 - raise Notest(self, "old kernel skip") 282 - 283 - if self.skip_test_kernel_until(): 284 - raise Notest(self, "new kernel skip") 285 - 286 - cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir, 287 - self.perf, self.command, tempdir, self.args) 288 - ret = os.WEXITSTATUS(os.system(cmd)) 289 - 290 - log.info(" '%s' ret '%s', expected '%s'" % (cmd, str(ret), str(self.ret))) 291 - 292 - if not data_equal(str(ret), str(self.ret)): 293 - if self.test_ret: 294 - raise Fail(self, "Perf exit code failure") 295 - else: 296 - raise Unsup(self) 297 - 298 - def compare(self, expect, result): 299 - match = {} 300 - 301 - log.debug(" compare"); 302 - 303 - # For each expected event find all matching 304 - # events in result. Fail if there's not any. 305 - for exp_name, exp_event in expect.items(): 306 - exp_list = [] 307 - res_event = {} 308 - log.debug(" matching [%s]" % exp_name) 309 - for res_name, res_event in result.items(): 310 - log.debug(" to [%s]" % res_name) 311 - if (exp_event.equal(res_event)): 312 - exp_list.append(res_name) 313 - log.debug(" ->OK") 314 - else: 315 - log.debug(" ->FAIL"); 316 - 317 - log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list))) 318 - 319 - # we did not any matching event - fail 320 - if not exp_list: 321 - if exp_event.optional(): 322 - log.debug(" %s does not match, but is optional" % exp_name) 323 - else: 324 - if not res_event: 325 - log.debug(" res_event is empty"); 326 - else: 327 - exp_event.diff(res_event) 328 - raise Fail(self, 'match failure'); 329 - 330 - match[exp_name] = exp_list 331 - 332 - # For each defined group in the expected events 333 - # check we match the same group in the result. 334 - for exp_name, exp_event in expect.items(): 335 - group = exp_event.group 336 - 337 - if (group == ''): 338 - continue 339 - 340 - for res_name in match[exp_name]: 341 - res_group = result[res_name].group 342 - if res_group not in match[group]: 343 - raise Fail(self, 'group failure') 344 - 345 - log.debug(" group: [%s] matches group leader %s" % 346 - (exp_name, str(match[group]))) 347 - 348 - log.debug(" matched") 349 - 350 - def resolve_groups(self, events): 351 - for name, event in events.items(): 352 - group_fd = event['group_fd']; 353 - if group_fd == '-1': 354 - continue; 355 - 356 - for iname, ievent in events.items(): 357 - if (ievent['fd'] == group_fd): 358 - event.group = iname 359 - log.debug('[%s] has group leader [%s]' % (name, iname)) 360 - break; 361 - 362 - def run(self): 363 - tempdir = tempfile.mkdtemp(); 364 - 365 - try: 366 - # run the test script 367 - self.run_cmd(tempdir); 368 - 369 - # load events expectation for the test 370 - log.debug(" loading result events"); 371 - for f in glob.glob(tempdir + '/event*'): 372 - self.load_events(f, self.result); 373 - 374 - # resolve group_fd to event names 375 - self.resolve_groups(self.expect); 376 - self.resolve_groups(self.result); 377 - 378 - # do the expectation - results matching - both ways 379 - self.compare(self.expect, self.result) 380 - self.compare(self.result, self.expect) 381 - 382 - finally: 383 - # cleanup 384 - shutil.rmtree(tempdir) 385 - 386 - 387 - def run_tests(options): 388 - for f in glob.glob(options.test_dir + '/' + options.test): 389 - try: 390 - Test(f, options).run() 391 - except Unsup as obj: 392 - log.warning("unsupp %s" % obj.getMsg()) 393 - except Notest as obj: 394 - log.warning("skipped %s" % obj.getMsg()) 395 - 396 - def setup_log(verbose): 397 - global log 398 - level = logging.CRITICAL 399 - 400 - if verbose == 1: 401 - level = logging.WARNING 402 - if verbose == 2: 403 - level = logging.INFO 404 - if verbose >= 3: 405 - level = logging.DEBUG 406 - 407 - log = logging.getLogger('test') 408 - log.setLevel(level) 409 - ch = logging.StreamHandler() 410 - ch.setLevel(level) 411 - formatter = logging.Formatter('%(message)s') 412 - ch.setFormatter(formatter) 413 - log.addHandler(ch) 414 - 415 - USAGE = '''%s [OPTIONS] 416 - -d dir # tests dir 417 - -p path # perf binary 418 - -t test # single test 419 - -v # verbose level 420 - ''' % sys.argv[0] 421 - 422 - def main(): 423 - parser = optparse.OptionParser(usage=USAGE) 424 - 425 - parser.add_option("-t", "--test", 426 - action="store", type="string", dest="test") 427 - parser.add_option("-d", "--test-dir", 428 - action="store", type="string", dest="test_dir") 429 - parser.add_option("-p", "--perf", 430 - action="store", type="string", dest="perf") 431 - parser.add_option("-v", "--verbose", 432 - default=0, action="count", dest="verbose") 433 - 434 - options, args = parser.parse_args() 435 - if args: 436 - parser.error('FAILED wrong arguments %s' % ' '.join(args)) 437 - return -1 438 - 439 - setup_log(options.verbose) 440 - 441 - if not options.test_dir: 442 - print('FAILED no -d option specified') 443 - sys.exit(-1) 444 - 445 - if not options.test: 446 - options.test = 'test*' 447 - 448 - try: 449 - run_tests(options) 450 - 451 - except Fail as obj: 452 - print("FAILED %s" % obj.getMsg()) 453 - sys.exit(-1) 454 - 455 - sys.exit(0) 456 - 457 - if __name__ == '__main__': 458 - main()
-69
tools/perf/tests/attr/README
··· 1 - The struct perf_event_attr test (attr tests) support 2 - ==================================================== 3 - This testing support is embedded into perf directly and is governed 4 - by the PERF_TEST_ATTR environment variable and hook inside the 5 - sys_perf_event_open function. 6 - 7 - The general idea is to store 'struct perf_event_attr' details for 8 - each event created within single perf command. Each event details 9 - are stored into separate text file. Once perf command is finished 10 - these files are checked for values we expect for command. 11 - 12 - The attr tests consist of following parts: 13 - 14 - tests/attr.c 15 - ------------ 16 - This is the sys_perf_event_open hook implementation. The hook 17 - is triggered when the PERF_TEST_ATTR environment variable is 18 - defined. It must contain name of existing directory with access 19 - and write permissions. 20 - 21 - For each sys_perf_event_open call event details are stored in 22 - separate file. Besides 'struct perf_event_attr' values we also 23 - store 'fd' and 'group_fd' values to allow checking for groups. 24 - 25 - tests/attr.py 26 - ------------- 27 - This is the python script that does all the hard work. It reads 28 - the test definition, executes it and checks results. 29 - 30 - tests/attr/ 31 - ----------- 32 - Directory containing all attr test definitions. 33 - Following tests are defined (with perf commands): 34 - 35 - perf record kill (test-record-basic) 36 - perf record -b kill (test-record-branch-any) 37 - perf record -j any kill (test-record-branch-filter-any) 38 - perf record -j any_call kill (test-record-branch-filter-any_call) 39 - perf record -j any_ret kill (test-record-branch-filter-any_ret) 40 - perf record -j hv kill (test-record-branch-filter-hv) 41 - perf record -j ind_call kill (test-record-branch-filter-ind_call) 42 - perf record -j k kill (test-record-branch-filter-k) 43 - perf record -j u kill (test-record-branch-filter-u) 44 - perf record -c 123 kill (test-record-count) 45 - perf record -d kill (test-record-data) 46 - perf record -F 100 kill (test-record-freq) 47 - perf record -g kill (test-record-graph-default) 48 - perf record -g kill (test-record-graph-default-aarch64) 49 - perf record --call-graph dwarf kill (test-record-graph-dwarf) 50 - perf record --call-graph fp kill (test-record-graph-fp) 51 - perf record --call-graph fp kill (test-record-graph-fp-aarch64) 52 - perf record -e '{cycles,instructions}' kill (test-record-group1) 53 - perf record -e '{cycles/period=1/,instructions/period=2/}:S' kill (test-record-group2) 54 - perf record -D kill (test-record-no-delay) 55 - perf record -i kill (test-record-no-inherit) 56 - perf record -n kill (test-record-no-samples) 57 - perf record -c 100 -P kill (test-record-period) 58 - perf record -c 1 --pfm-events=cycles:period=2 (test-record-pfm-period) 59 - perf record -R kill (test-record-raw) 60 - perf record -c 2 -e arm_spe_0// -- kill (test-record-spe-period) 61 - perf record -e arm_spe_0/period=3/ -- kill (test-record-spe-period-term) 62 - perf record -e arm_spe_0/pa_enable=1/ -- kill (test-record-spe-physical-address) 63 - perf stat -e cycles kill (test-stat-basic) 64 - perf stat kill (test-stat-default) 65 - perf stat -d kill (test-stat-detailed-1) 66 - perf stat -dd kill (test-stat-detailed-2) 67 - perf stat -ddd kill (test-stat-detailed-3) 68 - perf stat -e '{cycles,instructions}' kill (test-stat-group1) 69 - perf stat -i -e cycles kill (test-stat-no-inherit)
tools/perf/tests/attr/base-record tools/perf/tests/shell/attr/base-record
tools/perf/tests/attr/base-record-spe tools/perf/tests/shell/attr/base-record-spe
tools/perf/tests/attr/base-stat tools/perf/tests/shell/attr/base-stat
tools/perf/tests/attr/system-wide-dummy tools/perf/tests/shell/attr/system-wide-dummy
-22
tools/perf/tests/attr/test-record-C0
··· 1 - [config] 2 - command = record 3 - args = --no-bpf-event -C 0 kill >/dev/null 2>&1 4 - ret = 1 5 - 6 - [event:base-record] 7 - cpu=0 8 - 9 - # no enable on exec for CPU attached 10 - enable_on_exec=0 11 - 12 - # PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | 13 - # PERF_SAMPLE_PERIOD | PERF_SAMPLE_IDENTIFIER 14 - # + PERF_SAMPLE_CPU added by -C 0 15 - sample_type=65927 16 - 17 - # Dummy event handles mmaps, comm and task. 18 - mmap=0 19 - comm=0 20 - task=0 21 - 22 - [event:system-wide-dummy]
tools/perf/tests/attr/test-record-basic tools/perf/tests/shell/attr/test-record-basic
tools/perf/tests/attr/test-record-branch-any tools/perf/tests/shell/attr/test-record-branch-any
tools/perf/tests/attr/test-record-branch-filter-any tools/perf/tests/shell/attr/test-record-branch-filter-any
tools/perf/tests/attr/test-record-branch-filter-any_call tools/perf/tests/shell/attr/test-record-branch-filter-any_call
tools/perf/tests/attr/test-record-branch-filter-any_ret tools/perf/tests/shell/attr/test-record-branch-filter-any_ret
tools/perf/tests/attr/test-record-branch-filter-hv tools/perf/tests/shell/attr/test-record-branch-filter-hv
tools/perf/tests/attr/test-record-branch-filter-ind_call tools/perf/tests/shell/attr/test-record-branch-filter-ind_call
tools/perf/tests/attr/test-record-branch-filter-k tools/perf/tests/shell/attr/test-record-branch-filter-k
tools/perf/tests/attr/test-record-branch-filter-u tools/perf/tests/shell/attr/test-record-branch-filter-u
tools/perf/tests/attr/test-record-count tools/perf/tests/shell/attr/test-record-count
tools/perf/tests/attr/test-record-data tools/perf/tests/shell/attr/test-record-data
-55
tools/perf/tests/attr/test-record-dummy-C0
··· 1 - [config] 2 - command = record 3 - args = --no-bpf-event -e dummy -C 0 kill >/dev/null 2>&1 4 - ret = 1 5 - 6 - [event] 7 - fd=1 8 - group_fd=-1 9 - cpu=0 10 - pid=-1 11 - flags=8 12 - type=1 13 - size=136 14 - config=9 15 - sample_period=4000 16 - # PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | 17 - # PERF_SAMPLE_PERIOD 18 - # + PERF_SAMPLE_CPU added by -C 0 19 - sample_type=391 20 - read_format=4|20 21 - disabled=0 22 - inherit=1 23 - pinned=0 24 - exclusive=0 25 - exclude_user=0 26 - exclude_kernel=0 27 - exclude_hv=0 28 - exclude_idle=0 29 - mmap=1 30 - comm=1 31 - freq=1 32 - inherit_stat=0 33 - enable_on_exec=0 34 - task=1 35 - watermark=0 36 - precise_ip=0 37 - mmap_data=0 38 - sample_id_all=1 39 - exclude_host=0 40 - exclude_guest=1 41 - exclude_callchain_kernel=0 42 - exclude_callchain_user=0 43 - mmap2=1 44 - comm_exec=1 45 - context_switch=0 46 - write_backward=0 47 - namespaces=0 48 - use_clockid=0 49 - wakeup_events=0 50 - bp_type=0 51 - config1=0 52 - config2=0 53 - branch_sample_type=0 54 - sample_regs_user=0 55 - sample_stack_user=0
tools/perf/tests/attr/test-record-freq tools/perf/tests/shell/attr/test-record-freq
tools/perf/tests/attr/test-record-graph-default tools/perf/tests/shell/attr/test-record-graph-default
tools/perf/tests/attr/test-record-graph-default-aarch64 tools/perf/tests/shell/attr/test-record-graph-default-aarch64
tools/perf/tests/attr/test-record-graph-dwarf tools/perf/tests/shell/attr/test-record-graph-dwarf
tools/perf/tests/attr/test-record-graph-fp tools/perf/tests/shell/attr/test-record-graph-fp
tools/perf/tests/attr/test-record-graph-fp-aarch64 tools/perf/tests/shell/attr/test-record-graph-fp-aarch64
-39
tools/perf/tests/attr/test-record-group-sampling
··· 1 - [config] 2 - command = record 3 - args = --no-bpf-event -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 4 - ret = 1 5 - 6 - [event-1:base-record] 7 - fd=1 8 - group_fd=-1 9 - sample_type=343 10 - read_format=12|28 11 - inherit=0 12 - 13 - [event-2:base-record] 14 - fd=2 15 - group_fd=1 16 - 17 - # cache-misses 18 - type=0 19 - config=3 20 - 21 - # default | PERF_SAMPLE_READ 22 - sample_type=343 23 - 24 - # PERF_FORMAT_ID | PERF_FORMAT_GROUP | PERF_FORMAT_LOST 25 - read_format=12|28 26 - task=0 27 - mmap=0 28 - comm=0 29 - enable_on_exec=0 30 - disabled=0 31 - 32 - # inherit is disabled for group sampling 33 - inherit=0 34 - 35 - # sampling disabled 36 - sample_freq=0 37 - sample_period=0 38 - freq=0 39 - write_backward=0
tools/perf/tests/attr/test-record-group1 tools/perf/tests/shell/attr/test-record-group1
-29
tools/perf/tests/attr/test-record-group2
··· 1 - [config] 2 - command = record 3 - args = --no-bpf-event -e '{cycles/period=1234000/,instructions/period=6789000/}:S' kill >/dev/null 2>&1 4 - ret = 1 5 - 6 - [event-1:base-record] 7 - fd=1 8 - group_fd=-1 9 - config=0|1 10 - sample_period=1234000 11 - sample_type=87 12 - read_format=12|28 13 - inherit=0 14 - freq=0 15 - 16 - [event-2:base-record] 17 - fd=2 18 - group_fd=1 19 - config=0|1 20 - sample_period=6789000 21 - sample_type=87 22 - read_format=12|28 23 - disabled=0 24 - inherit=0 25 - mmap=0 26 - comm=0 27 - freq=0 28 - enable_on_exec=0 29 - task=0
tools/perf/tests/attr/test-record-no-buffering tools/perf/tests/shell/attr/test-record-no-buffering
tools/perf/tests/attr/test-record-no-inherit tools/perf/tests/shell/attr/test-record-no-inherit
tools/perf/tests/attr/test-record-no-samples tools/perf/tests/shell/attr/test-record-no-samples
tools/perf/tests/attr/test-record-period tools/perf/tests/shell/attr/test-record-period
tools/perf/tests/attr/test-record-pfm-period tools/perf/tests/shell/attr/test-record-pfm-period
tools/perf/tests/attr/test-record-raw tools/perf/tests/shell/attr/test-record-raw
tools/perf/tests/attr/test-record-spe-period tools/perf/tests/shell/attr/test-record-spe-period
tools/perf/tests/attr/test-record-spe-period-term tools/perf/tests/shell/attr/test-record-spe-period-term
tools/perf/tests/attr/test-record-spe-physical-address tools/perf/tests/shell/attr/test-record-spe-physical-address
tools/perf/tests/attr/test-record-user-regs-no-sve-aarch64 tools/perf/tests/shell/attr/test-record-user-regs-no-sve-aarch64
tools/perf/tests/attr/test-record-user-regs-old-sve-aarch64 tools/perf/tests/shell/attr/test-record-user-regs-old-sve-aarch64
tools/perf/tests/attr/test-record-user-regs-sve-aarch64 tools/perf/tests/shell/attr/test-record-user-regs-sve-aarch64
tools/perf/tests/attr/test-stat-C0 tools/perf/tests/shell/attr/test-stat-C0
tools/perf/tests/attr/test-stat-basic tools/perf/tests/shell/attr/test-stat-basic
-185
tools/perf/tests/attr/test-stat-default
··· 1 - [config] 2 - command = stat 3 - args = kill >/dev/null 2>&1 4 - ret = 1 5 - 6 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK 7 - [event1:base-stat] 8 - fd=1 9 - type=1 10 - config=1 11 - 12 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES 13 - [event2:base-stat] 14 - fd=2 15 - type=1 16 - config=3 17 - 18 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS 19 - [event3:base-stat] 20 - fd=3 21 - type=1 22 - config=4 23 - 24 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS 25 - [event4:base-stat] 26 - fd=4 27 - type=1 28 - config=2 29 - 30 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES 31 - [event5:base-stat] 32 - fd=5 33 - type=0 34 - config=0 35 - optional=1 36 - 37 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 38 - [event6:base-stat] 39 - fd=6 40 - type=0 41 - config=7 42 - optional=1 43 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 44 - [event7:base-stat] 45 - fd=7 46 - type=0 47 - config=8 48 - optional=1 49 - 50 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 51 - [event8:base-stat] 52 - fd=8 53 - type=0 54 - config=1 55 - optional=1 56 - 57 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 58 - [event9:base-stat] 59 - fd=9 60 - type=0 61 - config=4 62 - optional=1 63 - 64 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 65 - [event10:base-stat] 66 - fd=10 67 - type=0 68 - config=5 69 - optional=1 70 - 71 - # PERF_TYPE_RAW / slots (0x400) 72 - [event11:base-stat] 73 - fd=11 74 - group_fd=-1 75 - type=4 76 - config=1024 77 - read_format=15 78 - optional=1 79 - 80 - # PERF_TYPE_RAW / topdown-retiring (0x8000) 81 - [event12:base-stat] 82 - fd=12 83 - group_fd=11 84 - type=4 85 - config=32768 86 - disabled=0 87 - enable_on_exec=0 88 - read_format=15 89 - optional=1 90 - 91 - # PERF_TYPE_RAW / topdown-fe-bound (0x8200) 92 - [event13:base-stat] 93 - fd=13 94 - group_fd=11 95 - type=4 96 - config=33280 97 - disabled=0 98 - enable_on_exec=0 99 - read_format=15 100 - optional=1 101 - 102 - # PERF_TYPE_RAW / topdown-be-bound (0x8300) 103 - [event14:base-stat] 104 - fd=14 105 - group_fd=11 106 - type=4 107 - config=33536 108 - disabled=0 109 - enable_on_exec=0 110 - read_format=15 111 - optional=1 112 - 113 - # PERF_TYPE_RAW / topdown-bad-spec (0x8100) 114 - [event15:base-stat] 115 - fd=15 116 - group_fd=11 117 - type=4 118 - config=33024 119 - disabled=0 120 - enable_on_exec=0 121 - read_format=15 122 - optional=1 123 - 124 - # PERF_TYPE_RAW / INT_MISC.UOP_DROPPING 125 - [event16:base-stat] 126 - fd=16 127 - type=4 128 - config=4109 129 - optional=1 130 - 131 - # PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ 132 - [event17:base-stat] 133 - fd=17 134 - type=4 135 - config=17039629 136 - optional=1 137 - 138 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD 139 - [event18:base-stat] 140 - fd=18 141 - type=4 142 - config=60 143 - optional=1 144 - 145 - # PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY 146 - [event19:base-stat] 147 - fd=19 148 - type=4 149 - config=2097421 150 - optional=1 151 - 152 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK 153 - [event20:base-stat] 154 - fd=20 155 - type=4 156 - config=316 157 - optional=1 158 - 159 - # PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE 160 - [event21:base-stat] 161 - fd=21 162 - type=4 163 - config=412 164 - optional=1 165 - 166 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE 167 - [event22:base-stat] 168 - fd=22 169 - type=4 170 - config=572 171 - optional=1 172 - 173 - # PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS 174 - [event23:base-stat] 175 - fd=23 176 - type=4 177 - config=706 178 - optional=1 179 - 180 - # PERF_TYPE_RAW / UOPS_ISSUED.ANY 181 - [event24:base-stat] 182 - fd=24 183 - type=4 184 - config=270 185 - optional=1
-227
tools/perf/tests/attr/test-stat-detailed-1
··· 1 - [config] 2 - command = stat 3 - args = -d kill >/dev/null 2>&1 4 - ret = 1 5 - 6 - 7 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK 8 - [event1:base-stat] 9 - fd=1 10 - type=1 11 - config=1 12 - 13 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES 14 - [event2:base-stat] 15 - fd=2 16 - type=1 17 - config=3 18 - 19 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS 20 - [event3:base-stat] 21 - fd=3 22 - type=1 23 - config=4 24 - 25 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS 26 - [event4:base-stat] 27 - fd=4 28 - type=1 29 - config=2 30 - 31 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES 32 - [event5:base-stat] 33 - fd=5 34 - type=0 35 - config=0 36 - optional=1 37 - 38 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 39 - [event6:base-stat] 40 - fd=6 41 - type=0 42 - config=7 43 - optional=1 44 - 45 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 46 - [event7:base-stat] 47 - fd=7 48 - type=0 49 - config=8 50 - optional=1 51 - 52 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 53 - [event8:base-stat] 54 - fd=8 55 - type=0 56 - config=1 57 - optional=1 58 - 59 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 60 - [event9:base-stat] 61 - fd=9 62 - type=0 63 - config=4 64 - optional=1 65 - 66 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 67 - [event10:base-stat] 68 - fd=10 69 - type=0 70 - config=5 71 - optional=1 72 - 73 - # PERF_TYPE_RAW / slots (0x400) 74 - [event11:base-stat] 75 - fd=11 76 - group_fd=-1 77 - type=4 78 - config=1024 79 - read_format=15 80 - optional=1 81 - 82 - # PERF_TYPE_RAW / topdown-retiring (0x8000) 83 - [event12:base-stat] 84 - fd=12 85 - group_fd=11 86 - type=4 87 - config=32768 88 - disabled=0 89 - enable_on_exec=0 90 - read_format=15 91 - optional=1 92 - 93 - # PERF_TYPE_RAW / topdown-fe-bound (0x8200) 94 - [event13:base-stat] 95 - fd=13 96 - group_fd=11 97 - type=4 98 - config=33280 99 - disabled=0 100 - enable_on_exec=0 101 - read_format=15 102 - optional=1 103 - 104 - # PERF_TYPE_RAW / topdown-be-bound (0x8300) 105 - [event14:base-stat] 106 - fd=14 107 - group_fd=11 108 - type=4 109 - config=33536 110 - disabled=0 111 - enable_on_exec=0 112 - read_format=15 113 - optional=1 114 - 115 - # PERF_TYPE_RAW / topdown-bad-spec (0x8100) 116 - [event15:base-stat] 117 - fd=15 118 - group_fd=11 119 - type=4 120 - config=33024 121 - disabled=0 122 - enable_on_exec=0 123 - read_format=15 124 - optional=1 125 - 126 - # PERF_TYPE_RAW / INT_MISC.UOP_DROPPING 127 - [event16:base-stat] 128 - fd=16 129 - type=4 130 - config=4109 131 - optional=1 132 - 133 - # PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ 134 - [event17:base-stat] 135 - fd=17 136 - type=4 137 - config=17039629 138 - optional=1 139 - 140 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD 141 - [event18:base-stat] 142 - fd=18 143 - type=4 144 - config=60 145 - optional=1 146 - 147 - # PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY 148 - [event19:base-stat] 149 - fd=19 150 - type=4 151 - config=2097421 152 - optional=1 153 - 154 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK 155 - [event20:base-stat] 156 - fd=20 157 - type=4 158 - config=316 159 - optional=1 160 - 161 - # PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE 162 - [event21:base-stat] 163 - fd=21 164 - type=4 165 - config=412 166 - optional=1 167 - 168 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE 169 - [event22:base-stat] 170 - fd=22 171 - type=4 172 - config=572 173 - optional=1 174 - 175 - # PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS 176 - [event23:base-stat] 177 - fd=23 178 - type=4 179 - config=706 180 - optional=1 181 - 182 - # PERF_TYPE_RAW / UOPS_ISSUED.ANY 183 - [event24:base-stat] 184 - fd=24 185 - type=4 186 - config=270 187 - optional=1 188 - 189 - # PERF_TYPE_HW_CACHE / 190 - # PERF_COUNT_HW_CACHE_L1D << 0 | 191 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 192 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 193 - [event25:base-stat] 194 - fd=25 195 - type=3 196 - config=0 197 - optional=1 198 - 199 - # PERF_TYPE_HW_CACHE / 200 - # PERF_COUNT_HW_CACHE_L1D << 0 | 201 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 202 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 203 - [event26:base-stat] 204 - fd=26 205 - type=3 206 - config=65536 207 - optional=1 208 - 209 - # PERF_TYPE_HW_CACHE / 210 - # PERF_COUNT_HW_CACHE_LL << 0 | 211 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 212 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 213 - [event27:base-stat] 214 - fd=27 215 - type=3 216 - config=2 217 - optional=1 218 - 219 - # PERF_TYPE_HW_CACHE, 220 - # PERF_COUNT_HW_CACHE_LL << 0 | 221 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 222 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 223 - [event28:base-stat] 224 - fd=28 225 - type=3 226 - config=65538 227 - optional=1
-287
tools/perf/tests/attr/test-stat-detailed-2
··· 1 - [config] 2 - command = stat 3 - args = -dd kill >/dev/null 2>&1 4 - ret = 1 5 - 6 - 7 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK 8 - [event1:base-stat] 9 - fd=1 10 - type=1 11 - config=1 12 - 13 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES 14 - [event2:base-stat] 15 - fd=2 16 - type=1 17 - config=3 18 - 19 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS 20 - [event3:base-stat] 21 - fd=3 22 - type=1 23 - config=4 24 - 25 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS 26 - [event4:base-stat] 27 - fd=4 28 - type=1 29 - config=2 30 - 31 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES 32 - [event5:base-stat] 33 - fd=5 34 - type=0 35 - config=0 36 - optional=1 37 - 38 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 39 - [event6:base-stat] 40 - fd=6 41 - type=0 42 - config=7 43 - optional=1 44 - 45 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 46 - [event7:base-stat] 47 - fd=7 48 - type=0 49 - config=8 50 - optional=1 51 - 52 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 53 - [event8:base-stat] 54 - fd=8 55 - type=0 56 - config=1 57 - optional=1 58 - 59 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 60 - [event9:base-stat] 61 - fd=9 62 - type=0 63 - config=4 64 - optional=1 65 - 66 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 67 - [event10:base-stat] 68 - fd=10 69 - type=0 70 - config=5 71 - optional=1 72 - 73 - # PERF_TYPE_RAW / slots (0x400) 74 - [event11:base-stat] 75 - fd=11 76 - group_fd=-1 77 - type=4 78 - config=1024 79 - read_format=15 80 - optional=1 81 - 82 - # PERF_TYPE_RAW / topdown-retiring (0x8000) 83 - [event12:base-stat] 84 - fd=12 85 - group_fd=11 86 - type=4 87 - config=32768 88 - disabled=0 89 - enable_on_exec=0 90 - read_format=15 91 - optional=1 92 - 93 - # PERF_TYPE_RAW / topdown-fe-bound (0x8200) 94 - [event13:base-stat] 95 - fd=13 96 - group_fd=11 97 - type=4 98 - config=33280 99 - disabled=0 100 - enable_on_exec=0 101 - read_format=15 102 - optional=1 103 - 104 - # PERF_TYPE_RAW / topdown-be-bound (0x8300) 105 - [event14:base-stat] 106 - fd=14 107 - group_fd=11 108 - type=4 109 - config=33536 110 - disabled=0 111 - enable_on_exec=0 112 - read_format=15 113 - optional=1 114 - 115 - # PERF_TYPE_RAW / topdown-bad-spec (0x8100) 116 - [event15:base-stat] 117 - fd=15 118 - group_fd=11 119 - type=4 120 - config=33024 121 - disabled=0 122 - enable_on_exec=0 123 - read_format=15 124 - optional=1 125 - 126 - # PERF_TYPE_RAW / INT_MISC.UOP_DROPPING 127 - [event16:base-stat] 128 - fd=16 129 - type=4 130 - config=4109 131 - optional=1 132 - 133 - # PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ 134 - [event17:base-stat] 135 - fd=17 136 - type=4 137 - config=17039629 138 - optional=1 139 - 140 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD 141 - [event18:base-stat] 142 - fd=18 143 - type=4 144 - config=60 145 - optional=1 146 - 147 - # PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY 148 - [event19:base-stat] 149 - fd=19 150 - type=4 151 - config=2097421 152 - optional=1 153 - 154 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK 155 - [event20:base-stat] 156 - fd=20 157 - type=4 158 - config=316 159 - optional=1 160 - 161 - # PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE 162 - [event21:base-stat] 163 - fd=21 164 - type=4 165 - config=412 166 - optional=1 167 - 168 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE 169 - [event22:base-stat] 170 - fd=22 171 - type=4 172 - config=572 173 - optional=1 174 - 175 - # PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS 176 - [event23:base-stat] 177 - fd=23 178 - type=4 179 - config=706 180 - optional=1 181 - 182 - # PERF_TYPE_RAW / UOPS_ISSUED.ANY 183 - [event24:base-stat] 184 - fd=24 185 - type=4 186 - config=270 187 - optional=1 188 - 189 - # PERF_TYPE_HW_CACHE / 190 - # PERF_COUNT_HW_CACHE_L1D << 0 | 191 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 192 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 193 - [event25:base-stat] 194 - fd=25 195 - type=3 196 - config=0 197 - optional=1 198 - 199 - # PERF_TYPE_HW_CACHE / 200 - # PERF_COUNT_HW_CACHE_L1D << 0 | 201 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 202 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 203 - [event26:base-stat] 204 - fd=26 205 - type=3 206 - config=65536 207 - optional=1 208 - 209 - # PERF_TYPE_HW_CACHE / 210 - # PERF_COUNT_HW_CACHE_LL << 0 | 211 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 212 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 213 - [event27:base-stat] 214 - fd=27 215 - type=3 216 - config=2 217 - optional=1 218 - 219 - # PERF_TYPE_HW_CACHE, 220 - # PERF_COUNT_HW_CACHE_LL << 0 | 221 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 222 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 223 - [event28:base-stat] 224 - fd=28 225 - type=3 226 - config=65538 227 - optional=1 228 - 229 - # PERF_TYPE_HW_CACHE, 230 - # PERF_COUNT_HW_CACHE_L1I << 0 | 231 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 232 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 233 - [event29:base-stat] 234 - fd=29 235 - type=3 236 - config=1 237 - optional=1 238 - 239 - # PERF_TYPE_HW_CACHE, 240 - # PERF_COUNT_HW_CACHE_L1I << 0 | 241 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 242 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 243 - [event30:base-stat] 244 - fd=30 245 - type=3 246 - config=65537 247 - optional=1 248 - 249 - # PERF_TYPE_HW_CACHE, 250 - # PERF_COUNT_HW_CACHE_DTLB << 0 | 251 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 252 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 253 - [event31:base-stat] 254 - fd=31 255 - type=3 256 - config=3 257 - optional=1 258 - 259 - # PERF_TYPE_HW_CACHE, 260 - # PERF_COUNT_HW_CACHE_DTLB << 0 | 261 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 262 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 263 - [event32:base-stat] 264 - fd=32 265 - type=3 266 - config=65539 267 - optional=1 268 - 269 - # PERF_TYPE_HW_CACHE, 270 - # PERF_COUNT_HW_CACHE_ITLB << 0 | 271 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 272 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 273 - [event33:base-stat] 274 - fd=33 275 - type=3 276 - config=4 277 - optional=1 278 - 279 - # PERF_TYPE_HW_CACHE, 280 - # PERF_COUNT_HW_CACHE_ITLB << 0 | 281 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 282 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 283 - [event34:base-stat] 284 - fd=34 285 - type=3 286 - config=65540 287 - optional=1
-307
tools/perf/tests/attr/test-stat-detailed-3
··· 1 - [config] 2 - command = stat 3 - args = -ddd kill >/dev/null 2>&1 4 - ret = 1 5 - 6 - 7 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK 8 - [event1:base-stat] 9 - fd=1 10 - type=1 11 - config=1 12 - 13 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES 14 - [event2:base-stat] 15 - fd=2 16 - type=1 17 - config=3 18 - 19 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS 20 - [event3:base-stat] 21 - fd=3 22 - type=1 23 - config=4 24 - 25 - # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS 26 - [event4:base-stat] 27 - fd=4 28 - type=1 29 - config=2 30 - 31 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES 32 - [event5:base-stat] 33 - fd=5 34 - type=0 35 - config=0 36 - optional=1 37 - 38 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 39 - [event6:base-stat] 40 - fd=6 41 - type=0 42 - config=7 43 - optional=1 44 - 45 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 46 - [event7:base-stat] 47 - fd=7 48 - type=0 49 - config=8 50 - optional=1 51 - 52 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 53 - [event8:base-stat] 54 - fd=8 55 - type=0 56 - config=1 57 - optional=1 58 - 59 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 60 - [event9:base-stat] 61 - fd=9 62 - type=0 63 - config=4 64 - optional=1 65 - 66 - # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 67 - [event10:base-stat] 68 - fd=10 69 - type=0 70 - config=5 71 - optional=1 72 - 73 - # PERF_TYPE_RAW / slots (0x400) 74 - [event11:base-stat] 75 - fd=11 76 - group_fd=-1 77 - type=4 78 - config=1024 79 - read_format=15 80 - optional=1 81 - 82 - # PERF_TYPE_RAW / topdown-retiring (0x8000) 83 - [event12:base-stat] 84 - fd=12 85 - group_fd=11 86 - type=4 87 - config=32768 88 - disabled=0 89 - enable_on_exec=0 90 - read_format=15 91 - optional=1 92 - 93 - # PERF_TYPE_RAW / topdown-fe-bound (0x8200) 94 - [event13:base-stat] 95 - fd=13 96 - group_fd=11 97 - type=4 98 - config=33280 99 - disabled=0 100 - enable_on_exec=0 101 - read_format=15 102 - optional=1 103 - 104 - # PERF_TYPE_RAW / topdown-be-bound (0x8300) 105 - [event14:base-stat] 106 - fd=14 107 - group_fd=11 108 - type=4 109 - config=33536 110 - disabled=0 111 - enable_on_exec=0 112 - read_format=15 113 - optional=1 114 - 115 - # PERF_TYPE_RAW / topdown-bad-spec (0x8100) 116 - [event15:base-stat] 117 - fd=15 118 - group_fd=11 119 - type=4 120 - config=33024 121 - disabled=0 122 - enable_on_exec=0 123 - read_format=15 124 - optional=1 125 - 126 - # PERF_TYPE_RAW / INT_MISC.UOP_DROPPING 127 - [event16:base-stat] 128 - fd=16 129 - type=4 130 - config=4109 131 - optional=1 132 - 133 - # PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ 134 - [event17:base-stat] 135 - fd=17 136 - type=4 137 - config=17039629 138 - optional=1 139 - 140 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD 141 - [event18:base-stat] 142 - fd=18 143 - type=4 144 - config=60 145 - optional=1 146 - 147 - # PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY 148 - [event19:base-stat] 149 - fd=19 150 - type=4 151 - config=2097421 152 - optional=1 153 - 154 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK 155 - [event20:base-stat] 156 - fd=20 157 - type=4 158 - config=316 159 - optional=1 160 - 161 - # PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE 162 - [event21:base-stat] 163 - fd=21 164 - type=4 165 - config=412 166 - optional=1 167 - 168 - # PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE 169 - [event22:base-stat] 170 - fd=22 171 - type=4 172 - config=572 173 - optional=1 174 - 175 - # PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS 176 - [event23:base-stat] 177 - fd=23 178 - type=4 179 - config=706 180 - optional=1 181 - 182 - # PERF_TYPE_RAW / UOPS_ISSUED.ANY 183 - [event24:base-stat] 184 - fd=24 185 - type=4 186 - config=270 187 - optional=1 188 - 189 - # PERF_TYPE_HW_CACHE / 190 - # PERF_COUNT_HW_CACHE_L1D << 0 | 191 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 192 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 193 - [event25:base-stat] 194 - fd=25 195 - type=3 196 - config=0 197 - optional=1 198 - 199 - # PERF_TYPE_HW_CACHE / 200 - # PERF_COUNT_HW_CACHE_L1D << 0 | 201 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 202 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 203 - [event26:base-stat] 204 - fd=26 205 - type=3 206 - config=65536 207 - optional=1 208 - 209 - # PERF_TYPE_HW_CACHE / 210 - # PERF_COUNT_HW_CACHE_LL << 0 | 211 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 212 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 213 - [event27:base-stat] 214 - fd=27 215 - type=3 216 - config=2 217 - optional=1 218 - 219 - # PERF_TYPE_HW_CACHE, 220 - # PERF_COUNT_HW_CACHE_LL << 0 | 221 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 222 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 223 - [event28:base-stat] 224 - fd=28 225 - type=3 226 - config=65538 227 - optional=1 228 - 229 - # PERF_TYPE_HW_CACHE, 230 - # PERF_COUNT_HW_CACHE_L1I << 0 | 231 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 232 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 233 - [event29:base-stat] 234 - fd=29 235 - type=3 236 - config=1 237 - optional=1 238 - 239 - # PERF_TYPE_HW_CACHE, 240 - # PERF_COUNT_HW_CACHE_L1I << 0 | 241 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 242 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 243 - [event30:base-stat] 244 - fd=30 245 - type=3 246 - config=65537 247 - optional=1 248 - 249 - # PERF_TYPE_HW_CACHE, 250 - # PERF_COUNT_HW_CACHE_DTLB << 0 | 251 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 252 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 253 - [event31:base-stat] 254 - fd=31 255 - type=3 256 - config=3 257 - optional=1 258 - 259 - # PERF_TYPE_HW_CACHE, 260 - # PERF_COUNT_HW_CACHE_DTLB << 0 | 261 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 262 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 263 - [event32:base-stat] 264 - fd=32 265 - type=3 266 - config=65539 267 - optional=1 268 - 269 - # PERF_TYPE_HW_CACHE, 270 - # PERF_COUNT_HW_CACHE_ITLB << 0 | 271 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 272 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 273 - [event33:base-stat] 274 - fd=33 275 - type=3 276 - config=4 277 - optional=1 278 - 279 - # PERF_TYPE_HW_CACHE, 280 - # PERF_COUNT_HW_CACHE_ITLB << 0 | 281 - # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 282 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 283 - [event34:base-stat] 284 - fd=34 285 - type=3 286 - config=65540 287 - optional=1 288 - 289 - # PERF_TYPE_HW_CACHE, 290 - # PERF_COUNT_HW_CACHE_L1D << 0 | 291 - # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 292 - # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 293 - [event35:base-stat] 294 - fd=35 295 - type=3 296 - config=512 297 - optional=1 298 - 299 - # PERF_TYPE_HW_CACHE, 300 - # PERF_COUNT_HW_CACHE_L1D << 0 | 301 - # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 302 - # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 303 - [event36:base-stat] 304 - fd=36 305 - type=3 306 - config=66048 307 - optional=1
tools/perf/tests/attr/test-stat-group1 tools/perf/tests/shell/attr/test-stat-group1
tools/perf/tests/attr/test-stat-no-inherit tools/perf/tests/shell/attr/test-stat-no-inherit
+313 -129
tools/perf/tests/builtin-test.c
··· 8 8 #include <errno.h> 9 9 #include <poll.h> 10 10 #include <unistd.h> 11 + #include <setjmp.h> 11 12 #include <string.h> 12 13 #include <stdlib.h> 13 14 #include <sys/types.h> ··· 40 39 * making them easier to debug. 41 40 */ 42 41 static bool dont_fork; 43 - /* Don't fork the tests in parallel and wait for their completion. */ 44 - static bool sequential = true; 45 - /* Do it in parallel, lacks infrastructure to avoid running tests that clash for resources, 46 - * So leave it as the developers choice to enable while working on the needed infra */ 47 - static bool parallel; 42 + /* Fork the tests in parallel and wait for their completion. */ 43 + static bool sequential; 48 44 const char *dso_to_test; 49 45 const char *test_objdump_path = "objdump"; 50 46 ··· 71 73 &suite__PERF_RECORD, 72 74 &suite__pmu, 73 75 &suite__pmu_events, 76 + &suite__hwmon_pmu, 77 + &suite__tool_pmu, 74 78 &suite__dso_data, 75 79 &suite__perf_evsel__roundtrip_name_test, 76 80 #ifdef HAVE_LIBTRACEEVENT 77 81 &suite__perf_evsel__tp_sched_test, 78 82 &suite__syscall_openat_tp_fields, 79 83 #endif 80 - &suite__attr, 81 84 &suite__hists_link, 82 85 &suite__python_use, 83 86 &suite__bp_signal, ··· 138 139 NULL, 139 140 }; 140 141 141 - static struct test_suite **tests[] = { 142 - generic_tests, 143 - arch_tests, 144 - NULL, /* shell tests created at runtime. */ 145 - }; 146 - 147 142 static struct test_workload *workloads[] = { 148 143 &workload__noploop, 149 144 &workload__thloop, ··· 147 154 &workload__datasym, 148 155 &workload__landlock, 149 156 }; 157 + 158 + #define workloads__for_each(workload) \ 159 + for (unsigned i = 0; i < ARRAY_SIZE(workloads) && ({ workload = workloads[i]; 1; }); i++) 150 160 151 161 static int num_subtests(const struct test_suite *t) 152 162 { ··· 194 198 return t->test_cases[subtest].run_case; 195 199 } 196 200 201 + static bool test_exclusive(const struct test_suite *t, int subtest) 202 + { 203 + if (subtest <= 0) 204 + return t->test_cases[0].exclusive; 205 + 206 + return t->test_cases[subtest].exclusive; 207 + } 208 + 197 209 static bool perf_test__matches(const char *desc, int curr, int argc, const char *argv[]) 198 210 { 199 211 int i; ··· 233 229 int subtest; 234 230 }; 235 231 232 + static jmp_buf run_test_jmp_buf; 233 + 234 + static void child_test_sig_handler(int sig) 235 + { 236 + siglongjmp(run_test_jmp_buf, sig); 237 + } 238 + 236 239 static int run_test_child(struct child_process *process) 237 240 { 241 + const int signals[] = { 242 + SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGINT, SIGPIPE, SIGQUIT, SIGSEGV, SIGTERM, 243 + }; 238 244 struct child_test *child = container_of(process, struct child_test, process); 239 245 int err; 246 + 247 + err = sigsetjmp(run_test_jmp_buf, 1); 248 + if (err) { 249 + fprintf(stderr, "\n---- unexpected signal (%d) ----\n", err); 250 + err = err > 0 ? -err : -1; 251 + goto err_out; 252 + } 253 + 254 + for (size_t i = 0; i < ARRAY_SIZE(signals); i++) 255 + signal(signals[i], child_test_sig_handler); 240 256 241 257 pr_debug("--- start ---\n"); 242 258 pr_debug("test child forked, pid %d\n", getpid()); 243 259 err = test_function(child->test, child->subtest)(child->test, child->subtest); 244 260 pr_debug("---- end(%d) ----\n", err); 261 + 262 + err_out: 245 263 fflush(NULL); 264 + for (size_t i = 0; i < ARRAY_SIZE(signals); i++) 265 + signal(signals[i], SIG_DFL); 246 266 return -err; 247 267 } 248 268 249 - static int print_test_result(struct test_suite *t, int i, int subtest, int result, int width) 269 + #define TEST_RUNNING -3 270 + 271 + static int print_test_result(struct test_suite *t, int i, int subtest, int result, int width, 272 + int running) 250 273 { 251 274 if (has_subtests(t)) { 252 275 int subw = width > 2 ? width - 2 : width; ··· 283 252 pr_info("%3d: %-*s:", i + 1, width, test_description(t, subtest)); 284 253 285 254 switch (result) { 255 + case TEST_RUNNING: 256 + color_fprintf(stderr, PERF_COLOR_YELLOW, " Running (%d active)\n", running); 257 + break; 286 258 case TEST_OK: 287 259 pr_info(" Ok\n"); 288 260 break; ··· 307 273 return 0; 308 274 } 309 275 310 - static int finish_test(struct child_test *child_test, int width) 276 + static void finish_test(struct child_test **child_tests, int running_test, int child_test_num, 277 + int width) 311 278 { 312 - struct test_suite *t = child_test->test; 313 - int i = child_test->test_num; 314 - int subi = child_test->subtest; 315 - int err = child_test->process.err; 316 - bool err_done = err <= 0; 279 + struct child_test *child_test = child_tests[running_test]; 280 + struct test_suite *t; 281 + int i, subi, err; 282 + bool err_done = false; 317 283 struct strbuf err_output = STRBUF_INIT; 284 + int last_running = -1; 318 285 int ret; 319 286 287 + if (child_test == NULL) { 288 + /* Test wasn't started. */ 289 + return; 290 + } 291 + t = child_test->test; 292 + i = child_test->test_num; 293 + subi = child_test->subtest; 294 + err = child_test->process.err; 320 295 /* 321 296 * For test suites with subtests, display the suite name ahead of the 322 297 * sub test names. ··· 337 294 * Busy loop reading from the child's stdout/stderr that are set to be 338 295 * non-blocking until EOF. 339 296 */ 340 - if (!err_done) 297 + if (err > 0) 341 298 fcntl(err, F_SETFL, O_NONBLOCK); 342 299 if (verbose > 1) { 343 300 if (has_subtests(t)) ··· 351 308 .events = POLLIN | POLLERR | POLLHUP | POLLNVAL, 352 309 }, 353 310 }; 354 - char buf[512]; 355 - ssize_t len; 311 + if (perf_use_color_default) { 312 + int running = 0; 356 313 357 - /* Poll to avoid excessive spinning, timeout set for 100ms. */ 358 - poll(pfds, ARRAY_SIZE(pfds), /*timeout=*/100); 359 - if (!err_done && pfds[0].revents) { 360 - errno = 0; 361 - len = read(err, buf, sizeof(buf) - 1); 362 - 363 - if (len <= 0) { 364 - err_done = errno != EAGAIN; 365 - } else { 366 - buf[len] = '\0'; 367 - if (verbose > 1) 368 - fprintf(stdout, "%s", buf); 369 - else 370 - strbuf_addstr(&err_output, buf); 314 + for (int y = running_test; y < child_test_num; y++) { 315 + if (child_tests[y] == NULL) 316 + continue; 317 + if (check_if_command_finished(&child_tests[y]->process) == 0) 318 + running++; 319 + } 320 + if (running != last_running) { 321 + if (last_running != -1) { 322 + /* 323 + * Erase "Running (.. active)" line 324 + * printed before poll/sleep. 325 + */ 326 + fprintf(debug_file(), PERF_COLOR_DELETE_LINE); 327 + } 328 + print_test_result(t, i, subi, TEST_RUNNING, width, running); 329 + last_running = running; 371 330 } 372 331 } 332 + 333 + err_done = true; 334 + if (err <= 0) { 335 + /* No child stderr to poll, sleep for 10ms for child to complete. */ 336 + usleep(10 * 1000); 337 + } else { 338 + /* Poll to avoid excessive spinning, timeout set for 100ms. */ 339 + poll(pfds, ARRAY_SIZE(pfds), /*timeout=*/100); 340 + if (pfds[0].revents) { 341 + char buf[512]; 342 + ssize_t len; 343 + 344 + len = read(err, buf, sizeof(buf) - 1); 345 + 346 + if (len > 0) { 347 + err_done = false; 348 + buf[len] = '\0'; 349 + strbuf_addstr(&err_output, buf); 350 + } 351 + } 352 + } 353 + if (err_done) 354 + err_done = check_if_command_finished(&child_test->process); 355 + } 356 + if (perf_use_color_default && last_running != -1) { 357 + /* Erase "Running (.. active)" line printed before poll/sleep. */ 358 + fprintf(debug_file(), PERF_COLOR_DELETE_LINE); 373 359 } 374 360 /* Clean up child process. */ 375 361 ret = finish_command(&child_test->process); 376 - if (verbose == 1 && ret == TEST_FAIL) { 377 - /* Add header for test that was skipped above. */ 378 - if (has_subtests(t)) 379 - pr_info("%3d.%1d: %s:\n", i + 1, subi + 1, test_description(t, subi)); 380 - else 381 - pr_info("%3d: %s:\n", i + 1, test_description(t, -1)); 362 + if (verbose > 1 || (verbose == 1 && ret == TEST_FAIL)) 382 363 fprintf(stderr, "%s", err_output.buf); 383 - } 364 + 384 365 strbuf_release(&err_output); 385 - print_test_result(t, i, subi, ret, width); 366 + print_test_result(t, i, subi, ret, width, /*running=*/0); 386 367 if (err > 0) 387 368 close(err); 388 - return 0; 369 + zfree(&child_tests[running_test]); 389 370 } 390 371 391 372 static int start_test(struct test_suite *test, int i, int subi, struct child_test **child, 392 - int width) 373 + int width, int pass) 393 374 { 394 375 int err; 395 376 396 377 *child = NULL; 397 378 if (dont_fork) { 398 - pr_debug("--- start ---\n"); 399 - err = test_function(test, subi)(test, subi); 400 - pr_debug("---- end ----\n"); 401 - print_test_result(test, i, subi, err, width); 379 + if (pass == 1) { 380 + pr_debug("--- start ---\n"); 381 + err = test_function(test, subi)(test, subi); 382 + pr_debug("---- end ----\n"); 383 + print_test_result(test, i, subi, err, width, /*running=*/0); 384 + } 402 385 return 0; 403 386 } 404 - 387 + if (pass == 1 && !sequential && test_exclusive(test, subi)) { 388 + /* When parallel, skip exclusive tests on the first pass. */ 389 + return 0; 390 + } 391 + if (pass != 1 && (sequential || !test_exclusive(test, subi))) { 392 + /* Sequential and non-exclusive tests were run on the first pass. */ 393 + return 0; 394 + } 405 395 *child = zalloc(sizeof(**child)); 406 396 if (!*child) 407 397 return -ENOMEM; ··· 453 377 (*child)->process.err = -1; 454 378 } 455 379 (*child)->process.no_exec_cmd = run_test_child; 456 - err = start_command(&(*child)->process); 457 - if (err || !sequential) 458 - return err; 459 - return finish_test(*child, width); 380 + if (sequential || pass == 2) { 381 + err = start_command(&(*child)->process); 382 + if (err) 383 + return err; 384 + finish_test(child, /*running_test=*/0, /*child_test_num=*/1, width); 385 + return 0; 386 + } 387 + return start_command(&(*child)->process); 460 388 } 461 389 462 - #define for_each_test(j, k, t) \ 463 - for (j = 0, k = 0; j < ARRAY_SIZE(tests); j++, k = 0) \ 464 - while ((t = tests[j][k++]) != NULL) 390 + /* State outside of __cmd_test for the sake of the signal handler. */ 465 391 466 - static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist) 392 + static size_t num_tests; 393 + static struct child_test **child_tests; 394 + static jmp_buf cmd_test_jmp_buf; 395 + 396 + static void cmd_test_sig_handler(int sig) 467 397 { 468 - struct test_suite *t; 469 - unsigned int j, k; 470 - int i = 0; 471 - int width = 0; 472 - size_t num_tests = 0; 473 - struct child_test **child_tests; 474 - int child_test_num = 0; 398 + siglongjmp(cmd_test_jmp_buf, sig); 399 + } 475 400 476 - for_each_test(j, k, t) { 477 - int len = strlen(test_description(t, -1)); 401 + static int __cmd_test(struct test_suite **suites, int argc, const char *argv[], 402 + struct intlist *skiplist) 403 + { 404 + static int width = 0; 405 + int err = 0; 406 + 407 + for (struct test_suite **t = suites; *t; t++) { 408 + int len = strlen(test_description(*t, -1)); 478 409 479 410 if (width < len) 480 411 width = len; 481 412 482 - if (has_subtests(t)) { 483 - for (int subi = 0, subn = num_subtests(t); subi < subn; subi++) { 484 - len = strlen(test_description(t, subi)); 413 + if (has_subtests(*t)) { 414 + for (int subi = 0, subn = num_subtests(*t); subi < subn; subi++) { 415 + len = strlen(test_description(*t, subi)); 485 416 if (width < len) 486 417 width = len; 487 418 num_tests++; ··· 501 418 if (!child_tests) 502 419 return -ENOMEM; 503 420 504 - for_each_test(j, k, t) { 505 - int curr = i++; 421 + err = sigsetjmp(cmd_test_jmp_buf, 1); 422 + if (err) { 423 + pr_err("\nSignal (%d) while running tests.\nTerminating tests with the same signal\n", 424 + err); 425 + for (size_t x = 0; x < num_tests; x++) { 426 + struct child_test *child_test = child_tests[x]; 506 427 507 - if (!perf_test__matches(test_description(t, -1), curr, argc, argv)) { 508 - bool skip = true; 509 - 510 - for (int subi = 0, subn = num_subtests(t); subi < subn; subi++) { 511 - if (perf_test__matches(test_description(t, subi), 512 - curr, argc, argv)) 513 - skip = false; 514 - } 515 - 516 - if (skip) 428 + if (!child_test) 517 429 continue; 430 + 431 + pr_debug3("Killing %d pid %d\n", 432 + child_test->test_num + 1, 433 + child_test->process.pid); 434 + kill(child_test->process.pid, err); 518 435 } 436 + goto err_out; 437 + } 438 + signal(SIGINT, cmd_test_sig_handler); 439 + signal(SIGTERM, cmd_test_sig_handler); 519 440 520 - if (intlist__find(skiplist, i)) { 521 - pr_info("%3d: %-*s:", curr + 1, width, test_description(t, -1)); 522 - color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); 523 - continue; 524 - } 441 + /* 442 + * In parallel mode pass 1 runs non-exclusive tests in parallel, pass 2 443 + * runs the exclusive tests sequentially. In other modes all tests are 444 + * run in pass 1. 445 + */ 446 + for (int pass = 1; pass <= 2; pass++) { 447 + int child_test_num = 0; 448 + int i = 0; 525 449 526 - if (!has_subtests(t)) { 527 - int err = start_test(t, curr, -1, &child_tests[child_test_num++], width); 450 + for (struct test_suite **t = suites; *t; t++) { 451 + int curr = i++; 528 452 529 - if (err) { 530 - /* TODO: if !sequential waitpid the already forked children. */ 531 - free(child_tests); 532 - return err; 453 + if (!perf_test__matches(test_description(*t, -1), curr, argc, argv)) { 454 + /* 455 + * Test suite shouldn't be run based on 456 + * description. See if subtest should. 457 + */ 458 + bool skip = true; 459 + 460 + for (int subi = 0, subn = num_subtests(*t); subi < subn; subi++) { 461 + if (perf_test__matches(test_description(*t, subi), 462 + curr, argc, argv)) 463 + skip = false; 464 + } 465 + 466 + if (skip) 467 + continue; 533 468 } 534 - } else { 535 - for (int subi = 0, subn = num_subtests(t); subi < subn; subi++) { 536 - int err; 537 469 538 - if (!perf_test__matches(test_description(t, subi), 470 + if (intlist__find(skiplist, i)) { 471 + pr_info("%3d: %-*s:", curr + 1, width, test_description(*t, -1)); 472 + color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n"); 473 + continue; 474 + } 475 + 476 + if (!has_subtests(*t)) { 477 + err = start_test(*t, curr, -1, &child_tests[child_test_num++], 478 + width, pass); 479 + if (err) 480 + goto err_out; 481 + continue; 482 + } 483 + for (int subi = 0, subn = num_subtests(*t); subi < subn; subi++) { 484 + if (!perf_test__matches(test_description(*t, subi), 539 485 curr, argc, argv)) 540 486 continue; 541 487 542 - err = start_test(t, curr, subi, &child_tests[child_test_num++], 543 - width); 488 + err = start_test(*t, curr, subi, &child_tests[child_test_num++], 489 + width, pass); 544 490 if (err) 545 - return err; 491 + goto err_out; 546 492 } 547 493 } 548 - } 549 - for (i = 0; i < child_test_num; i++) { 550 494 if (!sequential) { 551 - int ret = finish_test(child_tests[i], width); 552 - 553 - if (ret) 554 - return ret; 495 + /* Parallel mode starts tests but doesn't finish them. Do that now. */ 496 + for (size_t x = 0; x < num_tests; x++) 497 + finish_test(child_tests, x, num_tests, width); 555 498 } 556 - free(child_tests[i]); 499 + } 500 + err_out: 501 + signal(SIGINT, SIG_DFL); 502 + signal(SIGTERM, SIG_DFL); 503 + if (err) { 504 + pr_err("Internal test harness failure. Completing any started tests:\n:"); 505 + for (size_t x = 0; x < num_tests; x++) 506 + finish_test(child_tests, x, num_tests, width); 557 507 } 558 508 free(child_tests); 559 - return 0; 509 + return err; 560 510 } 561 511 562 - static int perf_test__list(int argc, const char **argv) 512 + static int perf_test__list(struct test_suite **suites, int argc, const char **argv) 563 513 { 564 - unsigned int j, k; 565 - struct test_suite *t; 566 514 int i = 0; 567 515 568 - for_each_test(j, k, t) { 516 + for (struct test_suite **t = suites; *t; t++) { 569 517 int curr = i++; 570 518 571 - if (!perf_test__matches(test_description(t, -1), curr, argc, argv)) 519 + if (!perf_test__matches(test_description(*t, -1), curr, argc, argv)) 572 520 continue; 573 521 574 - pr_info("%3d: %s\n", i, test_description(t, -1)); 522 + pr_info("%3d: %s\n", i, test_description(*t, -1)); 575 523 576 - if (has_subtests(t)) { 577 - int subn = num_subtests(t); 524 + if (has_subtests(*t)) { 525 + int subn = num_subtests(*t); 578 526 int subi; 579 527 580 528 for (subi = 0; subi < subn; subi++) 581 529 pr_info("%3d:%1d: %s\n", i, subi + 1, 582 - test_description(t, subi)); 530 + test_description(*t, subi)); 583 531 } 584 532 } 585 533 return 0; 586 534 } 587 535 536 + static int workloads__fprintf_list(FILE *fp) 537 + { 538 + struct test_workload *twl; 539 + int printed = 0; 540 + 541 + workloads__for_each(twl) 542 + printed += fprintf(fp, "%s\n", twl->name); 543 + 544 + return printed; 545 + } 546 + 588 547 static int run_workload(const char *work, int argc, const char **argv) 589 548 { 590 - unsigned int i = 0; 591 549 struct test_workload *twl; 592 550 593 - for (i = 0; i < ARRAY_SIZE(workloads); i++) { 594 - twl = workloads[i]; 551 + workloads__for_each(twl) { 595 552 if (!strcmp(twl->name, work)) 596 553 return twl->func(argc, argv); 597 554 } ··· 649 526 return 0; 650 527 } 651 528 529 + static struct test_suite **build_suites(void) 530 + { 531 + /* 532 + * TODO: suites is static to avoid needing to clean up the scripts tests 533 + * for leak sanitizer. 534 + */ 535 + static struct test_suite **suites[] = { 536 + generic_tests, 537 + arch_tests, 538 + NULL, 539 + }; 540 + struct test_suite **result; 541 + struct test_suite *t; 542 + size_t n = 0, num_suites = 0; 543 + 544 + if (suites[2] == NULL) 545 + suites[2] = create_script_test_suites(); 546 + 547 + #define for_each_test(t) \ 548 + for (size_t i = 0, j = 0; i < ARRAY_SIZE(suites); i++, j = 0) \ 549 + while ((t = suites[i][j++]) != NULL) 550 + 551 + for_each_test(t) 552 + num_suites++; 553 + 554 + result = calloc(num_suites + 1, sizeof(struct test_suite *)); 555 + 556 + for (int pass = 1; pass <= 2; pass++) { 557 + for_each_test(t) { 558 + bool exclusive = false; 559 + 560 + if (!has_subtests(t)) { 561 + exclusive = test_exclusive(t, -1); 562 + } else { 563 + for (int subi = 0, subn = num_subtests(t); subi < subn; subi++) { 564 + if (test_exclusive(t, subi)) { 565 + exclusive = true; 566 + break; 567 + } 568 + } 569 + } 570 + if ((!exclusive && pass == 1) || (exclusive && pass == 2)) 571 + result[n++] = t; 572 + } 573 + } 574 + return result; 575 + #undef for_each_test 576 + } 577 + 652 578 int cmd_test(int argc, const char **argv) 653 579 { 654 580 const char *test_usage[] = { ··· 706 534 }; 707 535 const char *skip = NULL; 708 536 const char *workload = NULL; 537 + bool list_workloads = false; 709 538 const struct option test_options[] = { 710 539 OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), 711 540 OPT_INCR('v', "verbose", &verbose, 712 541 "be more verbose (show symbol address, etc)"), 713 542 OPT_BOOLEAN('F', "dont-fork", &dont_fork, 714 543 "Do not fork for testcase"), 715 - OPT_BOOLEAN('p', "parallel", &parallel, "Run the tests in parallel"), 716 544 OPT_BOOLEAN('S', "sequential", &sequential, 717 545 "Run the tests one after another rather than in parallel"), 718 - OPT_STRING('w', "workload", &workload, "work", "workload to run for testing"), 546 + OPT_STRING('w', "workload", &workload, "work", "workload to run for testing, use '--list-workloads' to list the available ones."), 547 + OPT_BOOLEAN(0, "list-workloads", &list_workloads, "List the available builtin workloads to use with -w/--workload"), 719 548 OPT_STRING(0, "dso", &dso_to_test, "dso", "dso to test"), 720 549 OPT_STRING(0, "objdump", &test_objdump_path, "path", 721 550 "objdump binary to use for disassembly and annotations"), ··· 725 552 const char * const test_subcommands[] = { "list", NULL }; 726 553 struct intlist *skiplist = NULL; 727 554 int ret = hists__init(); 555 + struct test_suite **suites; 728 556 729 557 if (ret < 0) 730 558 return ret; ··· 735 561 /* Unbuffered output */ 736 562 setvbuf(stdout, NULL, _IONBF, 0); 737 563 738 - tests[2] = create_script_test_suites(); 739 564 argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0); 740 - if (argc >= 1 && !strcmp(argv[0], "list")) 741 - return perf_test__list(argc - 1, argv + 1); 565 + if (argc >= 1 && !strcmp(argv[0], "list")) { 566 + suites = build_suites(); 567 + ret = perf_test__list(suites, argc - 1, argv + 1); 568 + free(suites); 569 + return ret; 570 + } 742 571 743 572 if (workload) 744 573 return run_workload(workload, argc, argv); 745 574 575 + if (list_workloads) { 576 + workloads__fprintf_list(stdout); 577 + return 0; 578 + } 579 + 746 580 if (dont_fork) 747 581 sequential = true; 748 - else if (parallel) 749 - sequential = false; 750 582 751 583 symbol_conf.priv_size = sizeof(int); 752 584 symbol_conf.try_vmlinux_path = true; 585 + 753 586 754 587 if (symbol__init(NULL) < 0) 755 588 return -1; ··· 769 588 */ 770 589 rlimit__bump_memlock(); 771 590 772 - return __cmd_test(argc, argv, skiplist); 591 + suites = build_suites(); 592 + ret = __cmd_test(suites, argc, argv, skiplist); 593 + free(suites); 594 + return ret; 773 595 }
+2 -1
tools/perf/tests/demangle-java-test.c
··· 2 2 #include <string.h> 3 3 #include <stdlib.h> 4 4 #include <stdio.h> 5 + #include <linux/kernel.h> 5 6 #include "tests.h" 6 7 #include "session.h" 7 8 #include "debug.h" ··· 29 28 "void java.lang.Object<init>()" }, 30 29 }; 31 30 32 - for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) { 31 + for (i = 0; i < ARRAY_SIZE(test_cases); i++) { 33 32 buf = java_demangle_sym(test_cases[i].mangled, 0); 34 33 if (strcmp(buf, test_cases[i].demangled)) { 35 34 pr_debug("FAILED: %s: %s != %s\n", test_cases[i].mangled,
+3 -2
tools/perf/tests/event-times.c
··· 126 126 evsel->core.attr.disabled = 1; 127 127 128 128 err = evsel__open_per_cpu(evsel, cpus, -1); 129 + perf_cpu_map__put(cpus); 129 130 if (err) { 130 131 if (err == -EACCES) 131 132 return TEST_SKIP; ··· 135 134 return err; 136 135 } 137 136 138 - perf_cpu_map__put(cpus); 139 137 return evsel__enable(evsel); 140 138 } 141 139 ··· 153 153 } 154 154 155 155 err = evsel__open_per_cpu(evsel, cpus, -1); 156 + perf_cpu_map__put(cpus); 156 157 if (err == -EACCES) 157 158 return TEST_SKIP; 158 159 159 - perf_cpu_map__put(cpus); 160 160 return err ? TEST_FAIL : TEST_OK; 161 161 } 162 162 ··· 188 188 err = attach(evlist); 189 189 if (err == TEST_SKIP) { 190 190 pr_debug(" SKIP : not enough rights\n"); 191 + evlist__delete(evlist); 191 192 return err; 192 193 } 193 194
+26 -16
tools/perf/tests/evsel-tp-sched.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 #include <linux/err.h> 3 - #include <traceevent/event-parse.h> 3 + #include <event-parse.h> 4 4 #include "evsel.h" 5 5 #include "tests.h" 6 6 #include "debug.h" ··· 36 36 int subtest __maybe_unused) 37 37 { 38 38 struct evsel *evsel = evsel__newtp("sched", "sched_switch"); 39 - int ret = 0; 39 + int ret = TEST_OK; 40 40 41 41 if (IS_ERR(evsel)) { 42 42 pr_debug("evsel__newtp failed with %ld\n", PTR_ERR(evsel)); 43 - return -1; 43 + return PTR_ERR(evsel) == -EACCES ? TEST_SKIP : TEST_FAIL; 44 44 } 45 45 46 46 if (evsel__test_field(evsel, "prev_comm", 16, false)) 47 - ret = -1; 47 + ret = TEST_FAIL; 48 48 49 49 if (evsel__test_field(evsel, "prev_pid", 4, true)) 50 - ret = -1; 50 + ret = TEST_FAIL; 51 51 52 52 if (evsel__test_field(evsel, "prev_prio", 4, true)) 53 - ret = -1; 53 + ret = TEST_FAIL; 54 54 55 55 if (evsel__test_field(evsel, "prev_state", sizeof(long), true)) 56 - ret = -1; 56 + ret = TEST_FAIL; 57 57 58 58 if (evsel__test_field(evsel, "next_comm", 16, false)) 59 - ret = -1; 59 + ret = TEST_FAIL; 60 60 61 61 if (evsel__test_field(evsel, "next_pid", 4, true)) 62 - ret = -1; 62 + ret = TEST_FAIL; 63 63 64 64 if (evsel__test_field(evsel, "next_prio", 4, true)) 65 - ret = -1; 65 + ret = TEST_FAIL; 66 66 67 67 evsel__delete(evsel); 68 68 ··· 70 70 71 71 if (IS_ERR(evsel)) { 72 72 pr_debug("evsel__newtp failed with %ld\n", PTR_ERR(evsel)); 73 - return -1; 73 + return TEST_FAIL; 74 74 } 75 75 76 76 if (evsel__test_field(evsel, "comm", 16, false)) 77 - ret = -1; 77 + ret = TEST_FAIL; 78 78 79 79 if (evsel__test_field(evsel, "pid", 4, true)) 80 - ret = -1; 80 + ret = TEST_FAIL; 81 81 82 82 if (evsel__test_field(evsel, "prio", 4, true)) 83 - ret = -1; 83 + ret = TEST_FAIL; 84 84 85 85 if (evsel__test_field(evsel, "target_cpu", 4, true)) 86 - ret = -1; 86 + ret = TEST_FAIL; 87 87 88 88 evsel__delete(evsel); 89 89 return ret; 90 90 } 91 91 92 - DEFINE_SUITE("Parse sched tracepoints fields", perf_evsel__tp_sched_test); 92 + static struct test_case tests__perf_evsel__tp_sched_test[] = { 93 + TEST_CASE_REASON("Parse sched tracepoints fields", 94 + perf_evsel__tp_sched_test, 95 + "permissions"), 96 + { .name = NULL, } 97 + }; 98 + 99 + struct test_suite suite__perf_evsel__tp_sched_test = { 100 + .desc = "Parse sched tracepoints fields", 101 + .test_cases = tests__perf_evsel__tp_sched_test, 102 + };
+3 -2
tools/perf/tests/expr.c
··· 6 6 #include "util/header.h" 7 7 #include "util/smt.h" 8 8 #include "tests.h" 9 + #include <perf/cpumap.h> 9 10 #include <math.h> 10 11 #include <stdlib.h> 11 12 #include <string.h> ··· 77 76 struct expr_parse_ctx *ctx; 78 77 bool is_intel = false; 79 78 char strcmp_cpuid_buf[256]; 80 - struct perf_pmu *pmu = perf_pmus__find_core_pmu(); 81 - char *cpuid = perf_pmu__getcpuid(pmu); 79 + struct perf_cpu cpu = {-1}; 80 + char *cpuid = get_cpuid_allow_env_override(cpu); 82 81 char *escaped_cpuid1, *escaped_cpuid2; 83 82 84 83 TEST_ASSERT_VAL("get_cpuid", cpuid);
+342
tools/perf/tests/hwmon_pmu.c
··· 1 + // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 + #include "debug.h" 3 + #include "evlist.h" 4 + #include "hwmon_pmu.h" 5 + #include "parse-events.h" 6 + #include "tests.h" 7 + #include <fcntl.h> 8 + #include <sys/stat.h> 9 + #include <linux/compiler.h> 10 + #include <linux/kernel.h> 11 + #include <linux/string.h> 12 + 13 + static const struct test_event { 14 + const char *name; 15 + const char *alias; 16 + long config; 17 + } test_events[] = { 18 + { 19 + "temp_test_hwmon_event1", 20 + "temp1", 21 + 0xA0001, 22 + }, 23 + { 24 + "temp_test_hwmon_event2", 25 + "temp2", 26 + 0xA0002, 27 + }, 28 + }; 29 + 30 + /* Cleanup test PMU directory. */ 31 + static int test_pmu_put(const char *dir, struct perf_pmu *hwm) 32 + { 33 + char buf[PATH_MAX + 20]; 34 + int ret; 35 + 36 + if (scnprintf(buf, sizeof(buf), "rm -fr %s", dir) < 0) { 37 + pr_err("Failure to set up buffer for \"%s\"\n", dir); 38 + return -EINVAL; 39 + } 40 + ret = system(buf); 41 + if (ret) 42 + pr_err("Failure to \"%s\"\n", buf); 43 + 44 + list_del(&hwm->list); 45 + perf_pmu__delete(hwm); 46 + return ret; 47 + } 48 + 49 + /* 50 + * Prepare test PMU directory data, normally exported by kernel at 51 + * /sys/class/hwmon/hwmon<number>/. Give as input a buffer to hold the file 52 + * path, the result is PMU loaded using that directory. 53 + */ 54 + static struct perf_pmu *test_pmu_get(char *dir, size_t sz) 55 + { 56 + const char *test_hwmon_name_nl = "A test hwmon PMU\n"; 57 + const char *test_hwmon_name = "A test hwmon PMU"; 58 + /* Simulated hwmon items. */ 59 + const struct test_item { 60 + const char *name; 61 + const char *value; 62 + } test_items[] = { 63 + { "temp1_label", "test hwmon event1\n", }, 64 + { "temp1_input", "40000\n", }, 65 + { "temp2_label", "test hwmon event2\n", }, 66 + { "temp2_input", "50000\n", }, 67 + }; 68 + int dirfd, file; 69 + struct perf_pmu *hwm = NULL; 70 + ssize_t len; 71 + 72 + /* Create equivalent of sysfs mount point. */ 73 + scnprintf(dir, sz, "/tmp/perf-hwmon-pmu-test-XXXXXX"); 74 + if (!mkdtemp(dir)) { 75 + pr_err("mkdtemp failed\n"); 76 + dir[0] = '\0'; 77 + return NULL; 78 + } 79 + dirfd = open(dir, O_DIRECTORY); 80 + if (dirfd < 0) { 81 + pr_err("Failed to open test directory \"%s\"\n", dir); 82 + goto err_out; 83 + } 84 + 85 + /* Create the test hwmon directory and give it a name. */ 86 + if (mkdirat(dirfd, "hwmon1234", 0755) < 0) { 87 + pr_err("Failed to mkdir hwmon directory\n"); 88 + goto err_out; 89 + } 90 + file = openat(dirfd, "hwmon1234/name", O_WRONLY | O_CREAT, 0600); 91 + if (!file) { 92 + pr_err("Failed to open for writing file \"name\"\n"); 93 + goto err_out; 94 + } 95 + len = strlen(test_hwmon_name_nl); 96 + if (write(file, test_hwmon_name_nl, len) < len) { 97 + close(file); 98 + pr_err("Failed to write to 'name' file\n"); 99 + goto err_out; 100 + } 101 + close(file); 102 + 103 + /* Create test hwmon files. */ 104 + for (size_t i = 0; i < ARRAY_SIZE(test_items); i++) { 105 + const struct test_item *item = &test_items[i]; 106 + 107 + file = openat(dirfd, item->name, O_WRONLY | O_CREAT, 0600); 108 + if (!file) { 109 + pr_err("Failed to open for writing file \"%s\"\n", item->name); 110 + goto err_out; 111 + } 112 + 113 + if (write(file, item->value, strlen(item->value)) < 0) { 114 + pr_err("Failed to write to file \"%s\"\n", item->name); 115 + close(file); 116 + goto err_out; 117 + } 118 + close(file); 119 + } 120 + 121 + /* Make the PMU reading the files created above. */ 122 + hwm = perf_pmus__add_test_hwmon_pmu(dirfd, "hwmon1234", test_hwmon_name); 123 + if (!hwm) 124 + pr_err("Test hwmon creation failed\n"); 125 + 126 + err_out: 127 + if (!hwm) { 128 + test_pmu_put(dir, hwm); 129 + if (dirfd >= 0) 130 + close(dirfd); 131 + } 132 + return hwm; 133 + } 134 + 135 + static int do_test(size_t i, bool with_pmu, bool with_alias) 136 + { 137 + const char *test_event = with_alias ? test_events[i].alias : test_events[i].name; 138 + struct evlist *evlist = evlist__new(); 139 + struct evsel *evsel; 140 + struct parse_events_error err; 141 + int ret; 142 + char str[128]; 143 + bool found = false; 144 + 145 + if (!evlist) { 146 + pr_err("evlist allocation failed\n"); 147 + return TEST_FAIL; 148 + } 149 + 150 + if (with_pmu) 151 + snprintf(str, sizeof(str), "hwmon_a_test_hwmon_pmu/%s/", test_event); 152 + else 153 + strlcpy(str, test_event, sizeof(str)); 154 + 155 + pr_debug("Testing '%s'\n", str); 156 + parse_events_error__init(&err); 157 + ret = parse_events(evlist, str, &err); 158 + if (ret) { 159 + pr_debug("FAILED %s:%d failed to parse event '%s', err %d\n", 160 + __FILE__, __LINE__, str, ret); 161 + parse_events_error__print(&err, str); 162 + ret = TEST_FAIL; 163 + goto out; 164 + } 165 + 166 + ret = TEST_OK; 167 + if (with_pmu ? (evlist->core.nr_entries != 1) : (evlist->core.nr_entries < 1)) { 168 + pr_debug("FAILED %s:%d Unexpected number of events for '%s' of %d\n", 169 + __FILE__, __LINE__, str, evlist->core.nr_entries); 170 + ret = TEST_FAIL; 171 + goto out; 172 + } 173 + 174 + evlist__for_each_entry(evlist, evsel) { 175 + if (!evsel->pmu || !evsel->pmu->name || 176 + strcmp(evsel->pmu->name, "hwmon_a_test_hwmon_pmu")) 177 + continue; 178 + 179 + if (evsel->core.attr.config != (u64)test_events[i].config) { 180 + pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %ld\n", 181 + __FILE__, __LINE__, str, 182 + evsel->core.attr.config, 183 + test_events[i].config); 184 + ret = TEST_FAIL; 185 + goto out; 186 + } 187 + found = true; 188 + } 189 + 190 + if (!found) { 191 + pr_debug("FAILED %s:%d Didn't find hwmon event '%s' in parsed evsels\n", 192 + __FILE__, __LINE__, str); 193 + ret = TEST_FAIL; 194 + } 195 + 196 + out: 197 + parse_events_error__exit(&err); 198 + evlist__delete(evlist); 199 + return ret; 200 + } 201 + 202 + static int test__hwmon_pmu(bool with_pmu) 203 + { 204 + char dir[PATH_MAX]; 205 + struct perf_pmu *pmu = test_pmu_get(dir, sizeof(dir)); 206 + int ret = TEST_OK; 207 + 208 + if (!pmu) 209 + return TEST_FAIL; 210 + 211 + for (size_t i = 0; i < ARRAY_SIZE(test_events); i++) { 212 + ret = do_test(i, with_pmu, /*with_alias=*/false); 213 + 214 + if (ret != TEST_OK) 215 + break; 216 + 217 + ret = do_test(i, with_pmu, /*with_alias=*/true); 218 + 219 + if (ret != TEST_OK) 220 + break; 221 + } 222 + test_pmu_put(dir, pmu); 223 + return ret; 224 + } 225 + 226 + static int test__hwmon_pmu_without_pmu(struct test_suite *test __maybe_unused, 227 + int subtest __maybe_unused) 228 + { 229 + return test__hwmon_pmu(/*with_pmu=*/false); 230 + } 231 + 232 + static int test__hwmon_pmu_with_pmu(struct test_suite *test __maybe_unused, 233 + int subtest __maybe_unused) 234 + { 235 + return test__hwmon_pmu(/*with_pmu=*/true); 236 + } 237 + 238 + static int test__parse_hwmon_filename(struct test_suite *test __maybe_unused, 239 + int subtest __maybe_unused) 240 + { 241 + const struct hwmon_parse_test { 242 + const char *filename; 243 + enum hwmon_type type; 244 + int number; 245 + enum hwmon_item item; 246 + bool alarm; 247 + bool parse_ok; 248 + } tests[] = { 249 + { 250 + .filename = "cpu0_accuracy", 251 + .type = HWMON_TYPE_CPU, 252 + .number = 0, 253 + .item = HWMON_ITEM_ACCURACY, 254 + .alarm = false, 255 + .parse_ok = true, 256 + }, 257 + { 258 + .filename = "temp1_input", 259 + .type = HWMON_TYPE_TEMP, 260 + .number = 1, 261 + .item = HWMON_ITEM_INPUT, 262 + .alarm = false, 263 + .parse_ok = true, 264 + }, 265 + { 266 + .filename = "fan2_vid", 267 + .type = HWMON_TYPE_FAN, 268 + .number = 2, 269 + .item = HWMON_ITEM_VID, 270 + .alarm = false, 271 + .parse_ok = true, 272 + }, 273 + { 274 + .filename = "power3_crit_alarm", 275 + .type = HWMON_TYPE_POWER, 276 + .number = 3, 277 + .item = HWMON_ITEM_CRIT, 278 + .alarm = true, 279 + .parse_ok = true, 280 + }, 281 + { 282 + .filename = "intrusion4_average_interval_min_alarm", 283 + .type = HWMON_TYPE_INTRUSION, 284 + .number = 4, 285 + .item = HWMON_ITEM_AVERAGE_INTERVAL_MIN, 286 + .alarm = true, 287 + .parse_ok = true, 288 + }, 289 + { 290 + .filename = "badtype5_baditem", 291 + .type = HWMON_TYPE_NONE, 292 + .number = 5, 293 + .item = HWMON_ITEM_NONE, 294 + .alarm = false, 295 + .parse_ok = false, 296 + }, 297 + { 298 + .filename = "humidity6_baditem", 299 + .type = HWMON_TYPE_NONE, 300 + .number = 6, 301 + .item = HWMON_ITEM_NONE, 302 + .alarm = false, 303 + .parse_ok = false, 304 + }, 305 + }; 306 + 307 + for (size_t i = 0; i < ARRAY_SIZE(tests); i++) { 308 + enum hwmon_type type; 309 + int number; 310 + enum hwmon_item item; 311 + bool alarm; 312 + 313 + TEST_ASSERT_EQUAL("parse_hwmon_filename", 314 + parse_hwmon_filename( 315 + tests[i].filename, 316 + &type, 317 + &number, 318 + &item, 319 + &alarm), 320 + tests[i].parse_ok 321 + ); 322 + if (tests[i].parse_ok) { 323 + TEST_ASSERT_EQUAL("parse_hwmon_filename type", type, tests[i].type); 324 + TEST_ASSERT_EQUAL("parse_hwmon_filename number", number, tests[i].number); 325 + TEST_ASSERT_EQUAL("parse_hwmon_filename item", item, tests[i].item); 326 + TEST_ASSERT_EQUAL("parse_hwmon_filename alarm", alarm, tests[i].alarm); 327 + } 328 + } 329 + return TEST_OK; 330 + } 331 + 332 + static struct test_case tests__hwmon_pmu[] = { 333 + TEST_CASE("Basic parsing test", parse_hwmon_filename), 334 + TEST_CASE("Parsing without PMU name", hwmon_pmu_without_pmu), 335 + TEST_CASE("Parsing with PMU name", hwmon_pmu_with_pmu), 336 + { .name = NULL, } 337 + }; 338 + 339 + struct test_suite suite__hwmon_pmu = { 340 + .desc = "Hwmon PMU", 341 + .test_cases = tests__hwmon_pmu, 342 + };
+3 -3
tools/perf/tests/make
··· 81 81 make_no_ui := NO_SLANG=1 NO_GTK2=1 82 82 make_no_demangle := NO_DEMANGLE=1 83 83 make_no_libelf := NO_LIBELF=1 84 - make_no_libunwind := NO_LIBUNWIND=1 84 + make_libunwind := LIBUNWIND=1 85 85 make_no_libdw_dwarf_unwind := NO_LIBDW_DWARF_UNWIND=1 86 86 make_no_backtrace := NO_BACKTRACE=1 87 87 make_no_libcapstone := NO_CAPSTONE=1 ··· 121 121 122 122 # all the NO_* variable combined 123 123 make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_GTK2=1 124 - make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 124 + make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_BACKTRACE=1 125 125 make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 126 126 make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 127 127 make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 NO_JVMTI=1 NO_LIBZSTD=1 ··· 153 153 run += make_no_ui 154 154 run += make_no_demangle 155 155 run += make_no_libelf 156 - run += make_no_libunwind 156 + run += make_libunwind 157 157 run += make_no_libdw_dwarf_unwind 158 158 run += make_no_backtrace 159 159 run += make_no_libcapstone
+15 -4
tools/perf/tests/openat-syscall-tp-fields.c
··· 40 40 int flags = O_RDONLY | O_DIRECTORY; 41 41 struct evlist *evlist = evlist__new(); 42 42 struct evsel *evsel; 43 - int err = -1, i, nr_events = 0, nr_polls = 0; 43 + int ret = TEST_FAIL, err, i, nr_events = 0, nr_polls = 0; 44 44 char sbuf[STRERR_BUFSIZE]; 45 45 46 46 if (evlist == NULL) { ··· 51 51 evsel = evsel__newtp("syscalls", "sys_enter_openat"); 52 52 if (IS_ERR(evsel)) { 53 53 pr_debug("%s: evsel__newtp\n", __func__); 54 + ret = PTR_ERR(evsel) == -EACCES ? TEST_SKIP : TEST_FAIL; 54 55 goto out_delete_evlist; 55 56 } 56 57 ··· 139 138 } 140 139 } 141 140 out_ok: 142 - err = 0; 141 + ret = TEST_OK; 143 142 out_delete_evlist: 144 143 evlist__delete(evlist); 145 144 out: 146 - return err; 145 + return ret; 147 146 } 148 147 149 - DEFINE_SUITE("syscalls:sys_enter_openat event fields", syscall_openat_tp_fields); 148 + static struct test_case tests__syscall_openat_tp_fields[] = { 149 + TEST_CASE_REASON("syscalls:sys_enter_openat event fields", 150 + syscall_openat_tp_fields, 151 + "permissions"), 152 + { .name = NULL, } 153 + }; 154 + 155 + struct test_suite suite__syscall_openat_tp_fields = { 156 + .desc = "syscalls:sys_enter_openat event fields", 157 + .test_cases = tests__syscall_openat_tp_fields, 158 + };
+14 -18
tools/perf/tests/parse-events.c
··· 730 730 731 731 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->core.nr_entries); 732 732 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type || 733 - strcmp(evsel->pmu_name, "cpu")); 733 + strcmp(evsel->pmu->name, "cpu")); 734 734 TEST_ASSERT_VAL("wrong exclude_user", 735 735 !evsel->core.attr.exclude_user); 736 736 TEST_ASSERT_VAL("wrong exclude_kernel", ··· 898 898 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 899 899 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 900 900 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); 901 - /* use of precise requires exclude_guest */ 902 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 901 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 903 902 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 904 903 TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2); 905 904 TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); ··· 931 932 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 932 933 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 933 934 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); 934 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 935 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 935 936 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 936 937 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 937 938 TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); ··· 946 947 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 947 948 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 948 949 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); 949 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 950 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 950 951 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 951 952 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 952 953 if (evsel__has_leader(evsel, leader)) ··· 1015 1016 TEST_ASSERT_VAL("wrong exclude_kernel", 1016 1017 !evsel->core.attr.exclude_kernel); 1017 1018 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); 1018 - /* use of precise requires exclude_guest */ 1019 1019 TEST_ASSERT_VAL("wrong exclude guest", 1020 - evsel->core.attr.exclude_guest); 1020 + !evsel->core.attr.exclude_guest); 1021 1021 TEST_ASSERT_VAL("wrong exclude host", 1022 1022 !evsel->core.attr.exclude_host); 1023 1023 TEST_ASSERT_VAL("wrong precise_ip", ··· 1070 1072 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1071 1073 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1072 1074 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); 1073 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1075 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1074 1076 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1075 1077 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1076 1078 TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); ··· 1101 1103 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1102 1104 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1103 1105 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); 1104 - /* use of precise requires exclude_guest */ 1105 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1106 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1106 1107 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1107 1108 TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 1); 1108 1109 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); ··· 1119 1122 TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); 1120 1123 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1121 1124 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); 1122 - /* use of precise requires exclude_guest */ 1123 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1125 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1124 1126 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1125 1127 TEST_ASSERT_VAL("wrong precise_ip", evsel->core.attr.precise_ip == 2); 1126 1128 TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); ··· 1218 1222 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1219 1223 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1220 1224 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); 1221 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1225 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1222 1226 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1223 1227 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1224 1228 TEST_ASSERT_VAL("wrong leader", evsel__is_group_leader(evsel)); ··· 1433 1437 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1434 1438 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1435 1439 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); 1436 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1440 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1437 1441 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1438 1442 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1439 1443 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); ··· 1449 1453 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1450 1454 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1451 1455 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); 1452 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1456 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1453 1457 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1454 1458 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1455 1459 TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); ··· 1464 1468 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1465 1469 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1466 1470 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); 1467 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1471 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1468 1472 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1469 1473 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1470 1474 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); ··· 1493 1497 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1494 1498 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1495 1499 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); 1496 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1500 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1497 1501 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1498 1502 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1499 1503 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); ··· 1509 1513 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1510 1514 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1511 1515 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); 1512 - TEST_ASSERT_VAL("wrong exclude guest", evsel->core.attr.exclude_guest); 1516 + TEST_ASSERT_VAL("wrong exclude guest", !evsel->core.attr.exclude_guest); 1513 1517 TEST_ASSERT_VAL("wrong exclude host", !evsel->core.attr.exclude_host); 1514 1518 TEST_ASSERT_VAL("wrong precise_ip", !evsel->core.attr.precise_ip); 1515 1519 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
+2 -1
tools/perf/tests/pmu.c
··· 176 176 } 177 177 178 178 memset(&attr, 0, sizeof(attr)); 179 - ret = perf_pmu__config_terms(pmu, &attr, &terms, /*zero=*/false, /*err=*/NULL); 179 + ret = perf_pmu__config_terms(pmu, &attr, &terms, /*zero=*/false, 180 + /*apply_hardcoded=*/false, /*err=*/NULL); 180 181 if (ret) { 181 182 pr_err("perf_pmu__config_terms failed"); 182 183 goto err_out;
+5 -5
tools/perf/tests/shell/annotate.sh
··· 44 44 fi 45 45 46 46 # Generate the annotated output file 47 - perf annotate -i "${perfdata}" --stdio 2> /dev/null > "${perfout}" 47 + perf annotate --no-demangle -i "${perfdata}" --stdio 2> /dev/null | head -250 > "${perfout}" 48 48 49 49 # check if it has the target symbol 50 50 if ! grep "${testsym}" "${perfout}" ··· 63 63 fi 64 64 65 65 # check again with a target symbol name 66 - if ! perf annotate -i "${perfdata}" "${testsym}" 2> /dev/null | \ 67 - grep -m 3 "${disasm_regex}" 66 + if ! perf annotate --no-demangle -i "${perfdata}" "${testsym}" 2> /dev/null | \ 67 + head -250 | grep -m 3 "${disasm_regex}" 68 68 then 69 69 echo "Basic annotate [Failed: missing disasm output when specifying the target symbol]" 70 70 err=1 ··· 72 72 fi 73 73 74 74 # check one more with external objdump tool (forced by --objdump option) 75 - if ! perf annotate -i "${perfdata}" --objdump=objdump 2> /dev/null | \ 76 - grep -m 3 "${disasm_regex}" 75 + if ! perf annotate --no-demangle -i "${perfdata}" --objdump=objdump 2> /dev/null | \ 76 + head -250 | grep -m 3 "${disasm_regex}" 77 77 then 78 78 echo "Basic annotate [Failed: missing disasm output from non default disassembler (using --objdump)]" 79 79 err=1
+22
tools/perf/tests/shell/attr.sh
··· 1 + #!/bin/bash 2 + # Perf attribute expectations test 3 + # SPDX-License-Identifier: GPL-2.0 4 + 5 + err=0 6 + 7 + cleanup() { 8 + trap - EXIT TERM INT 9 + } 10 + 11 + trap_cleanup() { 12 + echo "Unexpected signal in ${FUNCNAME[1]}" 13 + cleanup 14 + exit 1 15 + } 16 + trap trap_cleanup EXIT TERM INT 17 + 18 + shelldir=$(dirname "$0") 19 + perf_path=$(which perf) 20 + python "${shelldir}"/lib/attr.py -d "${shelldir}"/attr -v -p "$perf_path" 21 + cleanup 22 + exit $err
+71
tools/perf/tests/shell/attr/README
··· 1 + The struct perf_event_attr test (attr tests) support 2 + ==================================================== 3 + This testing support is embedded into perf directly and is governed 4 + by the PERF_TEST_ATTR environment variable and hook inside the 5 + sys_perf_event_open function. 6 + 7 + The general idea is to store 'struct perf_event_attr' details for 8 + each event created within single perf command. Each event details 9 + are stored into separate text file. Once perf command is finished 10 + these files are checked for values we expect for command. 11 + 12 + The attr tests consist of following parts: 13 + 14 + tests/attr.c 15 + ------------ 16 + This is the sys_perf_event_open hook implementation. The hook 17 + is triggered when the PERF_TEST_ATTR environment variable is 18 + defined. It must contain name of existing directory with access 19 + and write permissions. 20 + 21 + For each sys_perf_event_open call event details are stored in 22 + separate file. Besides 'struct perf_event_attr' values we also 23 + store 'fd' and 'group_fd' values to allow checking for groups. 24 + 25 + tests/attr.py 26 + ------------- 27 + This is the python script that does all the hard work. It reads 28 + the test definition, executes it and checks results. 29 + 30 + tests/attr/ 31 + ----------- 32 + Directory containing all attr test definitions. 33 + Following tests are defined (with perf commands): 34 + 35 + perf record kill (test-record-basic) 36 + perf record -b kill (test-record-branch-any) 37 + perf record -j any kill (test-record-branch-filter-any) 38 + perf record -j any_call kill (test-record-branch-filter-any_call) 39 + perf record -j any_ret kill (test-record-branch-filter-any_ret) 40 + perf record -j hv kill (test-record-branch-filter-hv) 41 + perf record -j ind_call kill (test-record-branch-filter-ind_call) 42 + perf record -j k kill (test-record-branch-filter-k) 43 + perf record -j u kill (test-record-branch-filter-u) 44 + perf record -c 123 kill (test-record-count) 45 + perf record -d kill (test-record-data) 46 + perf record -F 100 kill (test-record-freq) 47 + perf record -g kill (test-record-graph-default) 48 + perf record -g kill (test-record-graph-default-aarch64) 49 + perf record --call-graph dwarf kill (test-record-graph-dwarf) 50 + perf record --call-graph fp kill (test-record-graph-fp) 51 + perf record --call-graph fp kill (test-record-graph-fp-aarch64) 52 + perf record -e '{cycles,instructions}' kill (test-record-group1) 53 + perf record -e '{cycles/period=1/,instructions/period=2/}:S' kill (test-record-group2) 54 + perf record -e '{cycles,cache-misses}:S' kill (test-record-group-sampling1) 55 + perf record -c 10000 -e '{cycles,cache-misses}:S' kill (test-record-group-sampling2) 56 + perf record -D kill (test-record-no-delay) 57 + perf record -i kill (test-record-no-inherit) 58 + perf record -n kill (test-record-no-samples) 59 + perf record -c 100 -P kill (test-record-period) 60 + perf record -c 1 --pfm-events=cycles:period=2 (test-record-pfm-period) 61 + perf record -R kill (test-record-raw) 62 + perf record -c 2 -e arm_spe_0// -- kill (test-record-spe-period) 63 + perf record -e arm_spe_0/period=3/ -- kill (test-record-spe-period-term) 64 + perf record -e arm_spe_0/pa_enable=1/ -- kill (test-record-spe-physical-address) 65 + perf stat -e cycles kill (test-stat-basic) 66 + perf stat kill (test-stat-default) 67 + perf stat -d kill (test-stat-detailed-1) 68 + perf stat -dd kill (test-stat-detailed-2) 69 + perf stat -ddd kill (test-stat-detailed-3) 70 + perf stat -e '{cycles,instructions}' kill (test-stat-group1) 71 + perf stat -i -e cycles kill (test-stat-no-inherit)
+24
tools/perf/tests/shell/attr/test-record-C0
··· 1 + [config] 2 + command = record 3 + args = --no-bpf-event -C 0 kill >/dev/null 2>&1 4 + ret = 1 5 + 6 + [event:base-record] 7 + cpu=0 8 + 9 + # no enable on exec for CPU attached 10 + enable_on_exec=0 11 + 12 + # PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | 13 + # PERF_SAMPLE_PERIOD | PERF_SAMPLE_IDENTIFIER 14 + # + PERF_SAMPLE_CPU added by -C 0 15 + sample_type=65927 16 + 17 + # Dummy event handles mmaps, comm and task. 18 + mmap=0 19 + comm=0 20 + task=0 21 + inherit=0 22 + 23 + [event:system-wide-dummy] 24 + inherit=0
+55
tools/perf/tests/shell/attr/test-record-dummy-C0
··· 1 + [config] 2 + command = record 3 + args = --no-bpf-event -e dummy -C 0 kill >/dev/null 2>&1 4 + ret = 1 5 + 6 + [event] 7 + fd=1 8 + group_fd=-1 9 + cpu=0 10 + pid=-1 11 + flags=8 12 + type=1 13 + size=136 14 + config=9 15 + sample_period=4000 16 + # PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | 17 + # PERF_SAMPLE_PERIOD 18 + # + PERF_SAMPLE_CPU added by -C 0 19 + sample_type=391 20 + read_format=4|20 21 + disabled=0 22 + inherit=0 23 + pinned=0 24 + exclusive=0 25 + exclude_user=0 26 + exclude_kernel=0 27 + exclude_hv=0 28 + exclude_idle=0 29 + mmap=1 30 + comm=1 31 + freq=1 32 + inherit_stat=0 33 + enable_on_exec=0 34 + task=1 35 + watermark=0 36 + precise_ip=0 37 + mmap_data=0 38 + sample_id_all=1 39 + exclude_host=0 40 + exclude_guest=0 41 + exclude_callchain_kernel=0 42 + exclude_callchain_user=0 43 + mmap2=1 44 + comm_exec=1 45 + context_switch=0 46 + write_backward=0 47 + namespaces=0 48 + use_clockid=0 49 + wakeup_events=0 50 + bp_type=0 51 + config1=0 52 + config2=0 53 + branch_sample_type=0 54 + sample_regs_user=0 55 + sample_stack_user=0
+40
tools/perf/tests/shell/attr/test-record-group-sampling
··· 1 + [config] 2 + command = record 3 + args = --no-bpf-event -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 4 + ret = 1 5 + kernel_until = 6.12 6 + 7 + [event-1:base-record] 8 + fd=1 9 + group_fd=-1 10 + sample_type=343 11 + read_format=12|28 12 + inherit=0 13 + 14 + [event-2:base-record] 15 + fd=2 16 + group_fd=1 17 + 18 + # cache-misses 19 + type=0 20 + config=3 21 + 22 + # default | PERF_SAMPLE_READ | PERF_SAMPLE_PERIOD 23 + sample_type=343 24 + 25 + # PERF_FORMAT_ID | PERF_FORMAT_GROUP | PERF_FORMAT_LOST 26 + read_format=12|28 27 + task=0 28 + mmap=0 29 + comm=0 30 + enable_on_exec=0 31 + disabled=0 32 + 33 + # inherit is disabled for group sampling 34 + inherit=0 35 + 36 + # sampling disabled 37 + sample_freq=0 38 + sample_period=0 39 + freq=0 40 + write_backward=0
+50
tools/perf/tests/shell/attr/test-record-group-sampling1
··· 1 + [config] 2 + command = record 3 + args = --no-bpf-event -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 4 + ret = 1 5 + kernel_since = 6.12 6 + 7 + [event-1:base-record] 8 + fd=1 9 + group_fd=-1 10 + 11 + # cycles 12 + type=0 13 + config=0 14 + 15 + # default | PERF_SAMPLE_READ | PERF_SAMPLE_PERIOD 16 + sample_type=343 17 + 18 + # PERF_FORMAT_ID | PERF_FORMAT_GROUP | PERF_FORMAT_LOST | PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING 19 + read_format=28|31 20 + task=1 21 + mmap=1 22 + comm=1 23 + enable_on_exec=1 24 + disabled=1 25 + 26 + # inherit is enabled for group sampling 27 + inherit=1 28 + 29 + [event-2:base-record] 30 + fd=2 31 + group_fd=1 32 + 33 + # cache-misses 34 + type=0 35 + config=3 36 + 37 + # default | PERF_SAMPLE_READ | PERF_SAMPLE_PERIOD 38 + sample_type=343 39 + 40 + # PERF_FORMAT_ID | PERF_FORMAT_GROUP | PERF_FORMAT_LOST | PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING 41 + read_format=28|31 42 + task=0 43 + mmap=0 44 + comm=0 45 + enable_on_exec=0 46 + disabled=0 47 + freq=0 48 + 49 + # inherit is enabled for group sampling 50 + inherit=1
+61
tools/perf/tests/shell/attr/test-record-group-sampling2
··· 1 + [config] 2 + command = record 3 + args = --no-bpf-event -c 10000 -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1 4 + ret = 1 5 + kernel_since = 6.12 6 + 7 + [event-1:base-record] 8 + fd=1 9 + group_fd=-1 10 + 11 + # cycles 12 + type=0 13 + config=0 14 + 15 + # default | PERF_SAMPLE_READ 16 + sample_type=87 17 + 18 + # PERF_FORMAT_ID | PERF_FORMAT_GROUP | PERF_FORMAT_LOST | PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING 19 + read_format=28|31 20 + task=1 21 + mmap=1 22 + comm=1 23 + enable_on_exec=1 24 + disabled=1 25 + 26 + # inherit is enabled for group sampling 27 + inherit=1 28 + 29 + # sampling disabled 30 + sample_freq=0 31 + sample_period=10000 32 + freq=0 33 + write_backward=0 34 + 35 + [event-2:base-record] 36 + fd=2 37 + group_fd=1 38 + 39 + # cache-misses 40 + type=0 41 + config=3 42 + 43 + # default | PERF_SAMPLE_READ 44 + sample_type=87 45 + 46 + # PERF_FORMAT_ID | PERF_FORMAT_GROUP | PERF_FORMAT_LOST | PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING 47 + read_format=28|31 48 + task=0 49 + mmap=0 50 + comm=0 51 + enable_on_exec=0 52 + disabled=0 53 + 54 + # inherit is enabled for group sampling 55 + inherit=1 56 + 57 + # sampling disabled 58 + sample_freq=0 59 + sample_period=0 60 + freq=0 61 + write_backward=0
+30
tools/perf/tests/shell/attr/test-record-group2
··· 1 + [config] 2 + command = record 3 + args = --no-bpf-event -e '{cycles/period=1234000/,instructions/period=6789000/}:S' kill >/dev/null 2>&1 4 + ret = 1 5 + kernel_until = 6.12 6 + 7 + [event-1:base-record] 8 + fd=1 9 + group_fd=-1 10 + config=0|1 11 + sample_period=1234000 12 + sample_type=87 13 + read_format=12|28 14 + inherit=0 15 + freq=0 16 + 17 + [event-2:base-record] 18 + fd=2 19 + group_fd=1 20 + config=0|1 21 + sample_period=6789000 22 + sample_type=87 23 + read_format=12|28 24 + disabled=0 25 + inherit=0 26 + mmap=0 27 + comm=0 28 + freq=0 29 + enable_on_exec=0 30 + task=0
+31
tools/perf/tests/shell/attr/test-record-group3
··· 1 + [config] 2 + command = record 3 + args = --no-bpf-event -e '{cycles/period=1234000/,instructions/period=6789000/}:S' kill >/dev/null 2>&1 4 + ret = 1 5 + kernel_since = 6.12 6 + 7 + [event-1:base-record] 8 + fd=1 9 + group_fd=-1 10 + config=0|1 11 + sample_period=1234000 12 + sample_type=87 13 + read_format=28|31 14 + disabled=1 15 + inherit=1 16 + freq=0 17 + 18 + [event-2:base-record] 19 + fd=2 20 + group_fd=1 21 + config=0|1 22 + sample_period=6789000 23 + sample_type=87 24 + read_format=28|31 25 + disabled=0 26 + inherit=1 27 + mmap=0 28 + comm=0 29 + freq=0 30 + enable_on_exec=0 31 + task=0
+229
tools/perf/tests/shell/attr/test-stat-default
··· 1 + [config] 2 + command = stat 3 + args = kill >/dev/null 2>&1 4 + ret = 1 5 + 6 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK 7 + [event1:base-stat] 8 + fd=1 9 + type=1 10 + config=1 11 + 12 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES 13 + [event2:base-stat] 14 + fd=2 15 + type=1 16 + config=3 17 + 18 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS 19 + [event3:base-stat] 20 + fd=3 21 + type=1 22 + config=4 23 + 24 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS 25 + [event4:base-stat] 26 + fd=4 27 + type=1 28 + config=2 29 + 30 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES 31 + [event5:base-stat] 32 + fd=5 33 + type=0 34 + config=0 35 + optional=1 36 + 37 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 38 + [event6:base-stat] 39 + fd=6 40 + type=0 41 + config=7 42 + optional=1 43 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 44 + [event7:base-stat] 45 + fd=7 46 + type=0 47 + config=8 48 + optional=1 49 + 50 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 51 + [event8:base-stat] 52 + fd=8 53 + type=0 54 + config=1 55 + optional=1 56 + 57 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 58 + [event9:base-stat] 59 + fd=9 60 + type=0 61 + config=4 62 + optional=1 63 + 64 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 65 + [event10:base-stat] 66 + fd=10 67 + type=0 68 + config=5 69 + optional=1 70 + 71 + # PERF_TYPE_RAW / slots (0x400) 72 + [event11:base-stat] 73 + fd=11 74 + group_fd=-1 75 + type=4 76 + config=1024 77 + read_format=15 78 + optional=1 79 + 80 + # PERF_TYPE_RAW / topdown-retiring (0x8000) 81 + [event12:base-stat] 82 + fd=12 83 + group_fd=11 84 + type=4 85 + config=32768 86 + disabled=0 87 + enable_on_exec=0 88 + read_format=15 89 + optional=1 90 + 91 + # PERF_TYPE_RAW / topdown-bad-spec (0x8100) 92 + [event13:base-stat] 93 + fd=13 94 + group_fd=11 95 + type=4 96 + config=33024 97 + disabled=0 98 + enable_on_exec=0 99 + read_format=15 100 + optional=1 101 + 102 + # PERF_TYPE_RAW / topdown-fe-bound (0x8200) 103 + [event14:base-stat] 104 + fd=14 105 + group_fd=11 106 + type=4 107 + config=33280 108 + disabled=0 109 + enable_on_exec=0 110 + read_format=15 111 + optional=1 112 + 113 + # PERF_TYPE_RAW / topdown-be-bound (0x8300) 114 + [event15:base-stat] 115 + fd=15 116 + group_fd=11 117 + type=4 118 + config=33536 119 + disabled=0 120 + enable_on_exec=0 121 + read_format=15 122 + optional=1 123 + 124 + # PERF_TYPE_RAW / topdown-heavy-ops (0x8400) 125 + [event16:base-stat] 126 + fd=16 127 + group_fd=11 128 + type=4 129 + config=33792 130 + disabled=0 131 + enable_on_exec=0 132 + read_format=15 133 + optional=1 134 + 135 + # PERF_TYPE_RAW / topdown-br-mispredict (0x8500) 136 + [event17:base-stat] 137 + fd=17 138 + group_fd=11 139 + type=4 140 + config=34048 141 + disabled=0 142 + enable_on_exec=0 143 + read_format=15 144 + optional=1 145 + 146 + # PERF_TYPE_RAW / topdown-fetch-lat (0x8600) 147 + [event18:base-stat] 148 + fd=18 149 + group_fd=11 150 + type=4 151 + config=34304 152 + disabled=0 153 + enable_on_exec=0 154 + read_format=15 155 + optional=1 156 + 157 + # PERF_TYPE_RAW / topdown-mem-bound (0x8700) 158 + [event19:base-stat] 159 + fd=19 160 + group_fd=11 161 + type=4 162 + config=34560 163 + disabled=0 164 + enable_on_exec=0 165 + read_format=15 166 + optional=1 167 + 168 + # PERF_TYPE_RAW / INT_MISC.UOP_DROPPING 169 + [event20:base-stat] 170 + fd=20 171 + type=4 172 + config=4109 173 + optional=1 174 + 175 + # PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ 176 + [event21:base-stat] 177 + fd=21 178 + type=4 179 + config=17039629 180 + optional=1 181 + 182 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD 183 + [event22:base-stat] 184 + fd=22 185 + type=4 186 + config=60 187 + optional=1 188 + 189 + # PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY 190 + [event23:base-stat] 191 + fd=23 192 + type=4 193 + config=2097421 194 + optional=1 195 + 196 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK 197 + [event24:base-stat] 198 + fd=24 199 + type=4 200 + config=316 201 + optional=1 202 + 203 + # PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE 204 + [event25:base-stat] 205 + fd=25 206 + type=4 207 + config=412 208 + optional=1 209 + 210 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE 211 + [event26:base-stat] 212 + fd=26 213 + type=4 214 + config=572 215 + optional=1 216 + 217 + # PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS 218 + [event27:base-stat] 219 + fd=27 220 + type=4 221 + config=706 222 + optional=1 223 + 224 + # PERF_TYPE_RAW / UOPS_ISSUED.ANY 225 + [event28:base-stat] 226 + fd=28 227 + type=4 228 + config=270 229 + optional=1
+271
tools/perf/tests/shell/attr/test-stat-detailed-1
··· 1 + [config] 2 + command = stat 3 + args = -d kill >/dev/null 2>&1 4 + ret = 1 5 + 6 + 7 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK 8 + [event1:base-stat] 9 + fd=1 10 + type=1 11 + config=1 12 + 13 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES 14 + [event2:base-stat] 15 + fd=2 16 + type=1 17 + config=3 18 + 19 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS 20 + [event3:base-stat] 21 + fd=3 22 + type=1 23 + config=4 24 + 25 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS 26 + [event4:base-stat] 27 + fd=4 28 + type=1 29 + config=2 30 + 31 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES 32 + [event5:base-stat] 33 + fd=5 34 + type=0 35 + config=0 36 + optional=1 37 + 38 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 39 + [event6:base-stat] 40 + fd=6 41 + type=0 42 + config=7 43 + optional=1 44 + 45 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 46 + [event7:base-stat] 47 + fd=7 48 + type=0 49 + config=8 50 + optional=1 51 + 52 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 53 + [event8:base-stat] 54 + fd=8 55 + type=0 56 + config=1 57 + optional=1 58 + 59 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 60 + [event9:base-stat] 61 + fd=9 62 + type=0 63 + config=4 64 + optional=1 65 + 66 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 67 + [event10:base-stat] 68 + fd=10 69 + type=0 70 + config=5 71 + optional=1 72 + 73 + # PERF_TYPE_RAW / slots (0x400) 74 + [event11:base-stat] 75 + fd=11 76 + group_fd=-1 77 + type=4 78 + config=1024 79 + read_format=15 80 + optional=1 81 + 82 + # PERF_TYPE_RAW / topdown-retiring (0x8000) 83 + [event12:base-stat] 84 + fd=12 85 + group_fd=11 86 + type=4 87 + config=32768 88 + disabled=0 89 + enable_on_exec=0 90 + read_format=15 91 + optional=1 92 + 93 + # PERF_TYPE_RAW / topdown-bad-spec (0x8100) 94 + [event13:base-stat] 95 + fd=13 96 + group_fd=11 97 + type=4 98 + config=33024 99 + disabled=0 100 + enable_on_exec=0 101 + read_format=15 102 + optional=1 103 + 104 + # PERF_TYPE_RAW / topdown-fe-bound (0x8200) 105 + [event14:base-stat] 106 + fd=14 107 + group_fd=11 108 + type=4 109 + config=33280 110 + disabled=0 111 + enable_on_exec=0 112 + read_format=15 113 + optional=1 114 + 115 + # PERF_TYPE_RAW / topdown-be-bound (0x8300) 116 + [event15:base-stat] 117 + fd=15 118 + group_fd=11 119 + type=4 120 + config=33536 121 + disabled=0 122 + enable_on_exec=0 123 + read_format=15 124 + optional=1 125 + 126 + # PERF_TYPE_RAW / topdown-heavy-ops (0x8400) 127 + [event16:base-stat] 128 + fd=16 129 + group_fd=11 130 + type=4 131 + config=33792 132 + disabled=0 133 + enable_on_exec=0 134 + read_format=15 135 + optional=1 136 + 137 + # PERF_TYPE_RAW / topdown-br-mispredict (0x8500) 138 + [event17:base-stat] 139 + fd=17 140 + group_fd=11 141 + type=4 142 + config=34048 143 + disabled=0 144 + enable_on_exec=0 145 + read_format=15 146 + optional=1 147 + 148 + # PERF_TYPE_RAW / topdown-fetch-lat (0x8600) 149 + [event18:base-stat] 150 + fd=18 151 + group_fd=11 152 + type=4 153 + config=34304 154 + disabled=0 155 + enable_on_exec=0 156 + read_format=15 157 + optional=1 158 + 159 + # PERF_TYPE_RAW / topdown-mem-bound (0x8700) 160 + [event19:base-stat] 161 + fd=19 162 + group_fd=11 163 + type=4 164 + config=34560 165 + disabled=0 166 + enable_on_exec=0 167 + read_format=15 168 + optional=1 169 + 170 + # PERF_TYPE_RAW / INT_MISC.UOP_DROPPING 171 + [event20:base-stat] 172 + fd=20 173 + type=4 174 + config=4109 175 + optional=1 176 + 177 + # PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ 178 + [event21:base-stat] 179 + fd=21 180 + type=4 181 + config=17039629 182 + optional=1 183 + 184 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD 185 + [event22:base-stat] 186 + fd=22 187 + type=4 188 + config=60 189 + optional=1 190 + 191 + # PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY 192 + [event23:base-stat] 193 + fd=23 194 + type=4 195 + config=2097421 196 + optional=1 197 + 198 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK 199 + [event24:base-stat] 200 + fd=24 201 + type=4 202 + config=316 203 + optional=1 204 + 205 + # PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE 206 + [event25:base-stat] 207 + fd=25 208 + type=4 209 + config=412 210 + optional=1 211 + 212 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE 213 + [event26:base-stat] 214 + fd=26 215 + type=4 216 + config=572 217 + optional=1 218 + 219 + # PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS 220 + [event27:base-stat] 221 + fd=27 222 + type=4 223 + config=706 224 + optional=1 225 + 226 + # PERF_TYPE_RAW / UOPS_ISSUED.ANY 227 + [event28:base-stat] 228 + fd=28 229 + type=4 230 + config=270 231 + optional=1 232 + 233 + # PERF_TYPE_HW_CACHE / 234 + # PERF_COUNT_HW_CACHE_L1D << 0 | 235 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 236 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 237 + [event29:base-stat] 238 + fd=29 239 + type=3 240 + config=0 241 + optional=1 242 + 243 + # PERF_TYPE_HW_CACHE / 244 + # PERF_COUNT_HW_CACHE_L1D << 0 | 245 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 246 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 247 + [event30:base-stat] 248 + fd=30 249 + type=3 250 + config=65536 251 + optional=1 252 + 253 + # PERF_TYPE_HW_CACHE / 254 + # PERF_COUNT_HW_CACHE_LL << 0 | 255 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 256 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 257 + [event31:base-stat] 258 + fd=31 259 + type=3 260 + config=2 261 + optional=1 262 + 263 + # PERF_TYPE_HW_CACHE, 264 + # PERF_COUNT_HW_CACHE_LL << 0 | 265 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 266 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 267 + [event32:base-stat] 268 + fd=32 269 + type=3 270 + config=65538 271 + optional=1
+331
tools/perf/tests/shell/attr/test-stat-detailed-2
··· 1 + [config] 2 + command = stat 3 + args = -dd kill >/dev/null 2>&1 4 + ret = 1 5 + 6 + 7 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK 8 + [event1:base-stat] 9 + fd=1 10 + type=1 11 + config=1 12 + 13 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES 14 + [event2:base-stat] 15 + fd=2 16 + type=1 17 + config=3 18 + 19 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS 20 + [event3:base-stat] 21 + fd=3 22 + type=1 23 + config=4 24 + 25 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS 26 + [event4:base-stat] 27 + fd=4 28 + type=1 29 + config=2 30 + 31 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES 32 + [event5:base-stat] 33 + fd=5 34 + type=0 35 + config=0 36 + optional=1 37 + 38 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 39 + [event6:base-stat] 40 + fd=6 41 + type=0 42 + config=7 43 + optional=1 44 + 45 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 46 + [event7:base-stat] 47 + fd=7 48 + type=0 49 + config=8 50 + optional=1 51 + 52 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 53 + [event8:base-stat] 54 + fd=8 55 + type=0 56 + config=1 57 + optional=1 58 + 59 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 60 + [event9:base-stat] 61 + fd=9 62 + type=0 63 + config=4 64 + optional=1 65 + 66 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 67 + [event10:base-stat] 68 + fd=10 69 + type=0 70 + config=5 71 + optional=1 72 + 73 + # PERF_TYPE_RAW / slots (0x400) 74 + [event11:base-stat] 75 + fd=11 76 + group_fd=-1 77 + type=4 78 + config=1024 79 + read_format=15 80 + optional=1 81 + 82 + # PERF_TYPE_RAW / topdown-retiring (0x8000) 83 + [event12:base-stat] 84 + fd=12 85 + group_fd=11 86 + type=4 87 + config=32768 88 + disabled=0 89 + enable_on_exec=0 90 + read_format=15 91 + optional=1 92 + 93 + # PERF_TYPE_RAW / topdown-bad-spec (0x8100) 94 + [event13:base-stat] 95 + fd=13 96 + group_fd=11 97 + type=4 98 + config=33024 99 + disabled=0 100 + enable_on_exec=0 101 + read_format=15 102 + optional=1 103 + 104 + # PERF_TYPE_RAW / topdown-fe-bound (0x8200) 105 + [event14:base-stat] 106 + fd=14 107 + group_fd=11 108 + type=4 109 + config=33280 110 + disabled=0 111 + enable_on_exec=0 112 + read_format=15 113 + optional=1 114 + 115 + # PERF_TYPE_RAW / topdown-be-bound (0x8300) 116 + [event15:base-stat] 117 + fd=15 118 + group_fd=11 119 + type=4 120 + config=33536 121 + disabled=0 122 + enable_on_exec=0 123 + read_format=15 124 + optional=1 125 + 126 + # PERF_TYPE_RAW / topdown-heavy-ops (0x8400) 127 + [event16:base-stat] 128 + fd=16 129 + group_fd=11 130 + type=4 131 + config=33792 132 + disabled=0 133 + enable_on_exec=0 134 + read_format=15 135 + optional=1 136 + 137 + # PERF_TYPE_RAW / topdown-br-mispredict (0x8500) 138 + [event17:base-stat] 139 + fd=17 140 + group_fd=11 141 + type=4 142 + config=34048 143 + disabled=0 144 + enable_on_exec=0 145 + read_format=15 146 + optional=1 147 + 148 + # PERF_TYPE_RAW / topdown-fetch-lat (0x8600) 149 + [event18:base-stat] 150 + fd=18 151 + group_fd=11 152 + type=4 153 + config=34304 154 + disabled=0 155 + enable_on_exec=0 156 + read_format=15 157 + optional=1 158 + 159 + # PERF_TYPE_RAW / topdown-mem-bound (0x8700) 160 + [event19:base-stat] 161 + fd=19 162 + group_fd=11 163 + type=4 164 + config=34560 165 + disabled=0 166 + enable_on_exec=0 167 + read_format=15 168 + optional=1 169 + 170 + # PERF_TYPE_RAW / INT_MISC.UOP_DROPPING 171 + [event20:base-stat] 172 + fd=20 173 + type=4 174 + config=4109 175 + optional=1 176 + 177 + # PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ 178 + [event21:base-stat] 179 + fd=21 180 + type=4 181 + config=17039629 182 + optional=1 183 + 184 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD 185 + [event22:base-stat] 186 + fd=22 187 + type=4 188 + config=60 189 + optional=1 190 + 191 + # PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY 192 + [event23:base-stat] 193 + fd=23 194 + type=4 195 + config=2097421 196 + optional=1 197 + 198 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK 199 + [event24:base-stat] 200 + fd=24 201 + type=4 202 + config=316 203 + optional=1 204 + 205 + # PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE 206 + [event25:base-stat] 207 + fd=25 208 + type=4 209 + config=412 210 + optional=1 211 + 212 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE 213 + [event26:base-stat] 214 + fd=26 215 + type=4 216 + config=572 217 + optional=1 218 + 219 + # PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS 220 + [event27:base-stat] 221 + fd=27 222 + type=4 223 + config=706 224 + optional=1 225 + 226 + # PERF_TYPE_RAW / UOPS_ISSUED.ANY 227 + [event28:base-stat] 228 + fd=28 229 + type=4 230 + config=270 231 + optional=1 232 + 233 + # PERF_TYPE_HW_CACHE / 234 + # PERF_COUNT_HW_CACHE_L1D << 0 | 235 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 236 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 237 + [event29:base-stat] 238 + fd=29 239 + type=3 240 + config=0 241 + optional=1 242 + 243 + # PERF_TYPE_HW_CACHE / 244 + # PERF_COUNT_HW_CACHE_L1D << 0 | 245 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 246 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 247 + [event30:base-stat] 248 + fd=30 249 + type=3 250 + config=65536 251 + optional=1 252 + 253 + # PERF_TYPE_HW_CACHE / 254 + # PERF_COUNT_HW_CACHE_LL << 0 | 255 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 256 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 257 + [event31:base-stat] 258 + fd=31 259 + type=3 260 + config=2 261 + optional=1 262 + 263 + # PERF_TYPE_HW_CACHE, 264 + # PERF_COUNT_HW_CACHE_LL << 0 | 265 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 266 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 267 + [event32:base-stat] 268 + fd=32 269 + type=3 270 + config=65538 271 + optional=1 272 + 273 + # PERF_TYPE_HW_CACHE, 274 + # PERF_COUNT_HW_CACHE_L1I << 0 | 275 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 276 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 277 + [event33:base-stat] 278 + fd=33 279 + type=3 280 + config=1 281 + optional=1 282 + 283 + # PERF_TYPE_HW_CACHE, 284 + # PERF_COUNT_HW_CACHE_L1I << 0 | 285 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 286 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 287 + [event34:base-stat] 288 + fd=34 289 + type=3 290 + config=65537 291 + optional=1 292 + 293 + # PERF_TYPE_HW_CACHE, 294 + # PERF_COUNT_HW_CACHE_DTLB << 0 | 295 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 296 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 297 + [event35:base-stat] 298 + fd=35 299 + type=3 300 + config=3 301 + optional=1 302 + 303 + # PERF_TYPE_HW_CACHE, 304 + # PERF_COUNT_HW_CACHE_DTLB << 0 | 305 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 306 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 307 + [event36:base-stat] 308 + fd=36 309 + type=3 310 + config=65539 311 + optional=1 312 + 313 + # PERF_TYPE_HW_CACHE, 314 + # PERF_COUNT_HW_CACHE_ITLB << 0 | 315 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 316 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 317 + [event37:base-stat] 318 + fd=37 319 + type=3 320 + config=4 321 + optional=1 322 + 323 + # PERF_TYPE_HW_CACHE, 324 + # PERF_COUNT_HW_CACHE_ITLB << 0 | 325 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 326 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 327 + [event38:base-stat] 328 + fd=38 329 + type=3 330 + config=65540 331 + optional=1
+351
tools/perf/tests/shell/attr/test-stat-detailed-3
··· 1 + [config] 2 + command = stat 3 + args = -ddd kill >/dev/null 2>&1 4 + ret = 1 5 + 6 + 7 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK 8 + [event1:base-stat] 9 + fd=1 10 + type=1 11 + config=1 12 + 13 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES 14 + [event2:base-stat] 15 + fd=2 16 + type=1 17 + config=3 18 + 19 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS 20 + [event3:base-stat] 21 + fd=3 22 + type=1 23 + config=4 24 + 25 + # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS 26 + [event4:base-stat] 27 + fd=4 28 + type=1 29 + config=2 30 + 31 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES 32 + [event5:base-stat] 33 + fd=5 34 + type=0 35 + config=0 36 + optional=1 37 + 38 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND 39 + [event6:base-stat] 40 + fd=6 41 + type=0 42 + config=7 43 + optional=1 44 + 45 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND 46 + [event7:base-stat] 47 + fd=7 48 + type=0 49 + config=8 50 + optional=1 51 + 52 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS 53 + [event8:base-stat] 54 + fd=8 55 + type=0 56 + config=1 57 + optional=1 58 + 59 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS 60 + [event9:base-stat] 61 + fd=9 62 + type=0 63 + config=4 64 + optional=1 65 + 66 + # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES 67 + [event10:base-stat] 68 + fd=10 69 + type=0 70 + config=5 71 + optional=1 72 + 73 + # PERF_TYPE_RAW / slots (0x400) 74 + [event11:base-stat] 75 + fd=11 76 + group_fd=-1 77 + type=4 78 + config=1024 79 + read_format=15 80 + optional=1 81 + 82 + # PERF_TYPE_RAW / topdown-retiring (0x8000) 83 + [event12:base-stat] 84 + fd=12 85 + group_fd=11 86 + type=4 87 + config=32768 88 + disabled=0 89 + enable_on_exec=0 90 + read_format=15 91 + optional=1 92 + 93 + # PERF_TYPE_RAW / topdown-bad-spec (0x8100) 94 + [event13:base-stat] 95 + fd=13 96 + group_fd=11 97 + type=4 98 + config=33024 99 + disabled=0 100 + enable_on_exec=0 101 + read_format=15 102 + optional=1 103 + 104 + # PERF_TYPE_RAW / topdown-fe-bound (0x8200) 105 + [event14:base-stat] 106 + fd=14 107 + group_fd=11 108 + type=4 109 + config=33280 110 + disabled=0 111 + enable_on_exec=0 112 + read_format=15 113 + optional=1 114 + 115 + # PERF_TYPE_RAW / topdown-be-bound (0x8300) 116 + [event15:base-stat] 117 + fd=15 118 + group_fd=11 119 + type=4 120 + config=33536 121 + disabled=0 122 + enable_on_exec=0 123 + read_format=15 124 + optional=1 125 + 126 + # PERF_TYPE_RAW / topdown-heavy-ops (0x8400) 127 + [event16:base-stat] 128 + fd=16 129 + group_fd=11 130 + type=4 131 + config=33792 132 + disabled=0 133 + enable_on_exec=0 134 + read_format=15 135 + optional=1 136 + 137 + # PERF_TYPE_RAW / topdown-br-mispredict (0x8500) 138 + [event17:base-stat] 139 + fd=17 140 + group_fd=11 141 + type=4 142 + config=34048 143 + disabled=0 144 + enable_on_exec=0 145 + read_format=15 146 + optional=1 147 + 148 + # PERF_TYPE_RAW / topdown-fetch-lat (0x8600) 149 + [event18:base-stat] 150 + fd=18 151 + group_fd=11 152 + type=4 153 + config=34304 154 + disabled=0 155 + enable_on_exec=0 156 + read_format=15 157 + optional=1 158 + 159 + # PERF_TYPE_RAW / topdown-mem-bound (0x8700) 160 + [event19:base-stat] 161 + fd=19 162 + group_fd=11 163 + type=4 164 + config=34560 165 + disabled=0 166 + enable_on_exec=0 167 + read_format=15 168 + optional=1 169 + 170 + # PERF_TYPE_RAW / INT_MISC.UOP_DROPPING 171 + [event20:base-stat] 172 + fd=20 173 + type=4 174 + config=4109 175 + optional=1 176 + 177 + # PERF_TYPE_RAW / cpu/INT_MISC.RECOVERY_CYCLES,cmask=1,edge/ 178 + [event21:base-stat] 179 + fd=21 180 + type=4 181 + config=17039629 182 + optional=1 183 + 184 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.THREAD 185 + [event22:base-stat] 186 + fd=22 187 + type=4 188 + config=60 189 + optional=1 190 + 191 + # PERF_TYPE_RAW / INT_MISC.RECOVERY_CYCLES_ANY 192 + [event23:base-stat] 193 + fd=23 194 + type=4 195 + config=2097421 196 + optional=1 197 + 198 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.REF_XCLK 199 + [event24:base-stat] 200 + fd=24 201 + type=4 202 + config=316 203 + optional=1 204 + 205 + # PERF_TYPE_RAW / IDQ_UOPS_NOT_DELIVERED.CORE 206 + [event25:base-stat] 207 + fd=25 208 + type=4 209 + config=412 210 + optional=1 211 + 212 + # PERF_TYPE_RAW / CPU_CLK_UNHALTED.ONE_THREAD_ACTIVE 213 + [event26:base-stat] 214 + fd=26 215 + type=4 216 + config=572 217 + optional=1 218 + 219 + # PERF_TYPE_RAW / UOPS_RETIRED.RETIRE_SLOTS 220 + [event27:base-stat] 221 + fd=27 222 + type=4 223 + config=706 224 + optional=1 225 + 226 + # PERF_TYPE_RAW / UOPS_ISSUED.ANY 227 + [event28:base-stat] 228 + fd=28 229 + type=4 230 + config=270 231 + optional=1 232 + 233 + # PERF_TYPE_HW_CACHE / 234 + # PERF_COUNT_HW_CACHE_L1D << 0 | 235 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 236 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 237 + [event29:base-stat] 238 + fd=29 239 + type=3 240 + config=0 241 + optional=1 242 + 243 + # PERF_TYPE_HW_CACHE / 244 + # PERF_COUNT_HW_CACHE_L1D << 0 | 245 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 246 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 247 + [event30:base-stat] 248 + fd=30 249 + type=3 250 + config=65536 251 + optional=1 252 + 253 + # PERF_TYPE_HW_CACHE / 254 + # PERF_COUNT_HW_CACHE_LL << 0 | 255 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 256 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 257 + [event31:base-stat] 258 + fd=31 259 + type=3 260 + config=2 261 + optional=1 262 + 263 + # PERF_TYPE_HW_CACHE, 264 + # PERF_COUNT_HW_CACHE_LL << 0 | 265 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 266 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 267 + [event32:base-stat] 268 + fd=32 269 + type=3 270 + config=65538 271 + optional=1 272 + 273 + # PERF_TYPE_HW_CACHE, 274 + # PERF_COUNT_HW_CACHE_L1I << 0 | 275 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 276 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 277 + [event33:base-stat] 278 + fd=33 279 + type=3 280 + config=1 281 + optional=1 282 + 283 + # PERF_TYPE_HW_CACHE, 284 + # PERF_COUNT_HW_CACHE_L1I << 0 | 285 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 286 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 287 + [event34:base-stat] 288 + fd=34 289 + type=3 290 + config=65537 291 + optional=1 292 + 293 + # PERF_TYPE_HW_CACHE, 294 + # PERF_COUNT_HW_CACHE_DTLB << 0 | 295 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 296 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 297 + [event35:base-stat] 298 + fd=35 299 + type=3 300 + config=3 301 + optional=1 302 + 303 + # PERF_TYPE_HW_CACHE, 304 + # PERF_COUNT_HW_CACHE_DTLB << 0 | 305 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 306 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 307 + [event36:base-stat] 308 + fd=36 309 + type=3 310 + config=65539 311 + optional=1 312 + 313 + # PERF_TYPE_HW_CACHE, 314 + # PERF_COUNT_HW_CACHE_ITLB << 0 | 315 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 316 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 317 + [event37:base-stat] 318 + fd=37 319 + type=3 320 + config=4 321 + optional=1 322 + 323 + # PERF_TYPE_HW_CACHE, 324 + # PERF_COUNT_HW_CACHE_ITLB << 0 | 325 + # (PERF_COUNT_HW_CACHE_OP_READ << 8) | 326 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 327 + [event38:base-stat] 328 + fd=38 329 + type=3 330 + config=65540 331 + optional=1 332 + 333 + # PERF_TYPE_HW_CACHE, 334 + # PERF_COUNT_HW_CACHE_L1D << 0 | 335 + # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 336 + # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) 337 + [event39:base-stat] 338 + fd=39 339 + type=3 340 + config=512 341 + optional=1 342 + 343 + # PERF_TYPE_HW_CACHE, 344 + # PERF_COUNT_HW_CACHE_L1D << 0 | 345 + # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 346 + # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) 347 + [event40:base-stat] 348 + fd=40 349 + type=3 350 + config=66048 351 + optional=1
+1 -1
tools/perf/tests/shell/coresight/asm_pure_loop.sh
··· 1 1 #!/bin/sh -e 2 - # CoreSight / ASM Pure Loop 2 + # CoreSight / ASM Pure Loop (exclusive) 3 3 4 4 # SPDX-License-Identifier: GPL-2.0 5 5 # Carsten Haitzler <carsten.haitzler@arm.com>, 2021
+1 -1
tools/perf/tests/shell/coresight/memcpy_thread_16k_10.sh
··· 1 1 #!/bin/sh -e 2 - # CoreSight / Memcpy 16k 10 Threads 2 + # CoreSight / Memcpy 16k 10 Threads (exclusive) 3 3 4 4 # SPDX-License-Identifier: GPL-2.0 5 5 # Carsten Haitzler <carsten.haitzler@arm.com>, 2021
+1 -1
tools/perf/tests/shell/coresight/thread_loop_check_tid_10.sh
··· 1 1 #!/bin/sh -e 2 - # CoreSight / Thread Loop 10 Threads - Check TID 2 + # CoreSight / Thread Loop 10 Threads - Check TID (exclusive) 3 3 4 4 # SPDX-License-Identifier: GPL-2.0 5 5 # Carsten Haitzler <carsten.haitzler@arm.com>, 2021
+1 -1
tools/perf/tests/shell/coresight/thread_loop_check_tid_2.sh
··· 1 1 #!/bin/sh -e 2 - # CoreSight / Thread Loop 2 Threads - Check TID 2 + # CoreSight / Thread Loop 2 Threads - Check TID (exclusive) 3 3 4 4 # SPDX-License-Identifier: GPL-2.0 5 5 # Carsten Haitzler <carsten.haitzler@arm.com>, 2021
+1 -1
tools/perf/tests/shell/coresight/unroll_loop_thread_10.sh
··· 1 1 #!/bin/sh -e 2 - # CoreSight / Unroll Loop Thread 10 2 + # CoreSight / Unroll Loop Thread 10 (exclusive) 3 3 4 4 # SPDX-License-Identifier: GPL-2.0 5 5 # Carsten Haitzler <carsten.haitzler@arm.com>, 2021
+2 -2
tools/perf/tests/shell/ftrace.sh
··· 67 67 68 68 test_ftrace_profile() { 69 69 echo "perf ftrace profile test" 70 - perf ftrace profile sleep 0.1 > "${output}" 70 + perf ftrace profile -m 16M sleep 0.1 > "${output}" 71 71 grep ^# "${output}" 72 72 grep sleep "${output}" 73 73 grep schedule "${output}" 74 74 grep execve "${output}" 75 - time_re="[[:space:]]+10[[:digit:]]{4}\.[[:digit:]]{3}" 75 + time_re="[[:space:]]+1[[:digit:]]{5}\.[[:digit:]]{3}" 76 76 # 100283.000 100283.000 100283.000 1 __x64_sys_clock_nanosleep 77 77 # Check for one *clock_nanosleep line with a Count of just 1 that takes a bit more than 0.1 seconds 78 78 # Strip the _x64_sys part to work with other architectures
+476
tools/perf/tests/shell/lib/attr.py
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + from __future__ import print_function 4 + 5 + import os 6 + import sys 7 + import glob 8 + import optparse 9 + import platform 10 + import tempfile 11 + import logging 12 + import re 13 + import shutil 14 + import subprocess 15 + 16 + try: 17 + import configparser 18 + except ImportError: 19 + import ConfigParser as configparser 20 + 21 + def data_equal(a, b): 22 + # Allow multiple values in assignment separated by '|' 23 + a_list = a.split('|') 24 + b_list = b.split('|') 25 + 26 + for a_item in a_list: 27 + for b_item in b_list: 28 + if (a_item == b_item): 29 + return True 30 + elif (a_item == '*') or (b_item == '*'): 31 + return True 32 + 33 + return False 34 + 35 + class Fail(Exception): 36 + def __init__(self, test, msg): 37 + self.msg = msg 38 + self.test = test 39 + def getMsg(self): 40 + return '\'%s\' - %s' % (self.test.path, self.msg) 41 + 42 + class Notest(Exception): 43 + def __init__(self, test, arch): 44 + self.arch = arch 45 + self.test = test 46 + def getMsg(self): 47 + return '[%s] \'%s\'' % (self.arch, self.test.path) 48 + 49 + class Unsup(Exception): 50 + def __init__(self, test): 51 + self.test = test 52 + def getMsg(self): 53 + return '\'%s\'' % self.test.path 54 + 55 + class Event(dict): 56 + terms = [ 57 + 'cpu', 58 + 'flags', 59 + 'type', 60 + 'size', 61 + 'config', 62 + 'sample_period', 63 + 'sample_type', 64 + 'read_format', 65 + 'disabled', 66 + 'inherit', 67 + 'pinned', 68 + 'exclusive', 69 + 'exclude_user', 70 + 'exclude_kernel', 71 + 'exclude_hv', 72 + 'exclude_idle', 73 + 'mmap', 74 + 'comm', 75 + 'freq', 76 + 'inherit_stat', 77 + 'enable_on_exec', 78 + 'task', 79 + 'watermark', 80 + 'precise_ip', 81 + 'mmap_data', 82 + 'sample_id_all', 83 + 'exclude_host', 84 + 'exclude_guest', 85 + 'exclude_callchain_kernel', 86 + 'exclude_callchain_user', 87 + 'wakeup_events', 88 + 'bp_type', 89 + 'config1', 90 + 'config2', 91 + 'branch_sample_type', 92 + 'sample_regs_user', 93 + 'sample_stack_user', 94 + ] 95 + 96 + def add(self, data): 97 + for key, val in data: 98 + log.debug(" %s = %s" % (key, val)) 99 + self[key] = val 100 + 101 + def __init__(self, name, data, base): 102 + log.debug(" Event %s" % name); 103 + self.name = name; 104 + self.group = '' 105 + self.add(base) 106 + self.add(data) 107 + 108 + def equal(self, other): 109 + for t in Event.terms: 110 + log.debug(" [%s] %s %s" % (t, self[t], other[t])); 111 + if t not in self or t not in other: 112 + return False 113 + if not data_equal(self[t], other[t]): 114 + return False 115 + return True 116 + 117 + def optional(self): 118 + if 'optional' in self and self['optional'] == '1': 119 + return True 120 + return False 121 + 122 + def diff(self, other): 123 + for t in Event.terms: 124 + if t not in self or t not in other: 125 + continue 126 + if not data_equal(self[t], other[t]): 127 + log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) 128 + 129 + def parse_version(version): 130 + if not version: 131 + return None 132 + return [int(v) for v in version.split(".")[0:2]] 133 + 134 + # Test file description needs to have following sections: 135 + # [config] 136 + # - just single instance in file 137 + # - needs to specify: 138 + # 'command' - perf command name 139 + # 'args' - special command arguments 140 + # 'ret' - Skip test if Perf doesn't exit with this value (0 by default) 141 + # 'test_ret'- If set to 'true', fail test instead of skipping for 'ret' argument 142 + # 'arch' - architecture specific test (optional) 143 + # comma separated list, ! at the beginning 144 + # negates it. 145 + # 'auxv' - Truthy statement that is evaled in the scope of the auxv map. When false, 146 + # the test is skipped. For example 'auxv["AT_HWCAP"] == 10'. (optional) 147 + # 'kernel_since' - Inclusive kernel version from which the test will start running. Only the 148 + # first two values are supported, for example "6.1" (optional) 149 + # 'kernel_until' - Exclusive kernel version from which the test will stop running. (optional) 150 + # [eventX:base] 151 + # - one or multiple instances in file 152 + # - expected values assignments 153 + class Test(object): 154 + def __init__(self, path, options): 155 + parser = configparser.ConfigParser() 156 + parser.read(path) 157 + 158 + log.warning("running '%s'" % path) 159 + 160 + self.path = path 161 + self.test_dir = options.test_dir 162 + self.perf = options.perf 163 + self.command = parser.get('config', 'command') 164 + self.args = parser.get('config', 'args') 165 + 166 + try: 167 + self.ret = parser.get('config', 'ret') 168 + except: 169 + self.ret = 0 170 + 171 + self.test_ret = parser.getboolean('config', 'test_ret', fallback=False) 172 + 173 + try: 174 + self.arch = parser.get('config', 'arch') 175 + log.warning("test limitation '%s'" % self.arch) 176 + except: 177 + self.arch = '' 178 + 179 + self.auxv = parser.get('config', 'auxv', fallback=None) 180 + self.kernel_since = parse_version(parser.get('config', 'kernel_since', fallback=None)) 181 + self.kernel_until = parse_version(parser.get('config', 'kernel_until', fallback=None)) 182 + self.expect = {} 183 + self.result = {} 184 + log.debug(" loading expected events"); 185 + self.load_events(path, self.expect) 186 + 187 + def is_event(self, name): 188 + if name.find("event") == -1: 189 + return False 190 + else: 191 + return True 192 + 193 + def skip_test_kernel_since(self): 194 + if not self.kernel_since: 195 + return False 196 + return not self.kernel_since <= parse_version(platform.release()) 197 + 198 + def skip_test_kernel_until(self): 199 + if not self.kernel_until: 200 + return False 201 + return not parse_version(platform.release()) < self.kernel_until 202 + 203 + def skip_test_auxv(self): 204 + def new_auxv(a, pattern): 205 + items = list(filter(None, pattern.split(a))) 206 + # AT_HWCAP is hex but doesn't have a prefix, so special case it 207 + if items[0] == "AT_HWCAP": 208 + value = int(items[-1], 16) 209 + else: 210 + try: 211 + value = int(items[-1], 0) 212 + except: 213 + value = items[-1] 214 + return (items[0], value) 215 + 216 + if not self.auxv: 217 + return False 218 + auxv = subprocess.check_output("LD_SHOW_AUXV=1 sleep 0", shell=True) \ 219 + .decode(sys.stdout.encoding) 220 + pattern = re.compile(r"[: ]+") 221 + auxv = dict([new_auxv(a, pattern) for a in auxv.splitlines()]) 222 + return not eval(self.auxv) 223 + 224 + def skip_test_arch(self, myarch): 225 + # If architecture not set always run test 226 + if self.arch == '': 227 + # log.warning("test for arch %s is ok" % myarch) 228 + return False 229 + 230 + # Allow multiple values in assignment separated by ',' 231 + arch_list = self.arch.split(',') 232 + 233 + # Handle negated list such as !s390x,ppc 234 + if arch_list[0][0] == '!': 235 + arch_list[0] = arch_list[0][1:] 236 + log.warning("excluded architecture list %s" % arch_list) 237 + for arch_item in arch_list: 238 + # log.warning("test for %s arch is %s" % (arch_item, myarch)) 239 + if arch_item == myarch: 240 + return True 241 + return False 242 + 243 + for arch_item in arch_list: 244 + # log.warning("test for architecture '%s' current '%s'" % (arch_item, myarch)) 245 + if arch_item == myarch: 246 + return False 247 + return True 248 + 249 + def restore_sample_rate(self, value=10000): 250 + try: 251 + # Check value of sample_rate 252 + with open("/proc/sys/kernel/perf_event_max_sample_rate", "r") as fIn: 253 + curr_value = fIn.readline() 254 + # If too low restore to reasonable value 255 + if not curr_value or int(curr_value) < int(value): 256 + with open("/proc/sys/kernel/perf_event_max_sample_rate", "w") as fOut: 257 + fOut.write(str(value)) 258 + 259 + except IOError as e: 260 + log.warning("couldn't restore sample_rate value: I/O error %s" % e) 261 + except ValueError as e: 262 + log.warning("couldn't restore sample_rate value: Value error %s" % e) 263 + except TypeError as e: 264 + log.warning("couldn't restore sample_rate value: Type error %s" % e) 265 + 266 + def load_events(self, path, events): 267 + parser_event = configparser.ConfigParser() 268 + parser_event.read(path) 269 + 270 + # The event record section header contains 'event' word, 271 + # optionaly followed by ':' allowing to load 'parent 272 + # event' first as a base 273 + for section in filter(self.is_event, parser_event.sections()): 274 + 275 + parser_items = parser_event.items(section); 276 + base_items = {} 277 + 278 + # Read parent event if there's any 279 + if (':' in section): 280 + base = section[section.index(':') + 1:] 281 + parser_base = configparser.ConfigParser() 282 + parser_base.read(self.test_dir + '/' + base) 283 + base_items = parser_base.items('event') 284 + 285 + e = Event(section, parser_items, base_items) 286 + events[section] = e 287 + 288 + def run_cmd(self, tempdir): 289 + junk1, junk2, junk3, junk4, myarch = (os.uname()) 290 + 291 + if self.skip_test_arch(myarch): 292 + raise Notest(self, myarch) 293 + 294 + if self.skip_test_auxv(): 295 + raise Notest(self, "auxv skip") 296 + 297 + if self.skip_test_kernel_since(): 298 + raise Notest(self, "old kernel skip") 299 + 300 + if self.skip_test_kernel_until(): 301 + raise Notest(self, "new kernel skip") 302 + 303 + self.restore_sample_rate() 304 + cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir, 305 + self.perf, self.command, tempdir, self.args) 306 + ret = os.WEXITSTATUS(os.system(cmd)) 307 + 308 + log.info(" '%s' ret '%s', expected '%s'" % (cmd, str(ret), str(self.ret))) 309 + 310 + if not data_equal(str(ret), str(self.ret)): 311 + if self.test_ret: 312 + raise Fail(self, "Perf exit code failure") 313 + else: 314 + raise Unsup(self) 315 + 316 + def compare(self, expect, result): 317 + match = {} 318 + 319 + log.debug(" compare"); 320 + 321 + # For each expected event find all matching 322 + # events in result. Fail if there's not any. 323 + for exp_name, exp_event in expect.items(): 324 + exp_list = [] 325 + res_event = {} 326 + log.debug(" matching [%s]" % exp_name) 327 + for res_name, res_event in result.items(): 328 + log.debug(" to [%s]" % res_name) 329 + if (exp_event.equal(res_event)): 330 + exp_list.append(res_name) 331 + log.debug(" ->OK") 332 + else: 333 + log.debug(" ->FAIL"); 334 + 335 + log.debug(" match: [%s] matches %s" % (exp_name, str(exp_list))) 336 + 337 + # we did not any matching event - fail 338 + if not exp_list: 339 + if exp_event.optional(): 340 + log.debug(" %s does not match, but is optional" % exp_name) 341 + else: 342 + if not res_event: 343 + log.debug(" res_event is empty"); 344 + else: 345 + exp_event.diff(res_event) 346 + raise Fail(self, 'match failure'); 347 + 348 + match[exp_name] = exp_list 349 + 350 + # For each defined group in the expected events 351 + # check we match the same group in the result. 352 + for exp_name, exp_event in expect.items(): 353 + group = exp_event.group 354 + 355 + if (group == ''): 356 + continue 357 + 358 + for res_name in match[exp_name]: 359 + res_group = result[res_name].group 360 + if res_group not in match[group]: 361 + raise Fail(self, 'group failure') 362 + 363 + log.debug(" group: [%s] matches group leader %s" % 364 + (exp_name, str(match[group]))) 365 + 366 + log.debug(" matched") 367 + 368 + def resolve_groups(self, events): 369 + for name, event in events.items(): 370 + group_fd = event['group_fd']; 371 + if group_fd == '-1': 372 + continue; 373 + 374 + for iname, ievent in events.items(): 375 + if (ievent['fd'] == group_fd): 376 + event.group = iname 377 + log.debug('[%s] has group leader [%s]' % (name, iname)) 378 + break; 379 + 380 + def run(self): 381 + tempdir = tempfile.mkdtemp(); 382 + 383 + try: 384 + # run the test script 385 + self.run_cmd(tempdir); 386 + 387 + # load events expectation for the test 388 + log.debug(" loading result events"); 389 + for f in glob.glob(tempdir + '/event*'): 390 + self.load_events(f, self.result); 391 + 392 + # resolve group_fd to event names 393 + self.resolve_groups(self.expect); 394 + self.resolve_groups(self.result); 395 + 396 + # do the expectation - results matching - both ways 397 + self.compare(self.expect, self.result) 398 + self.compare(self.result, self.expect) 399 + 400 + finally: 401 + # cleanup 402 + shutil.rmtree(tempdir) 403 + 404 + 405 + def run_tests(options): 406 + for f in glob.glob(options.test_dir + '/' + options.test): 407 + try: 408 + Test(f, options).run() 409 + except Unsup as obj: 410 + log.warning("unsupp %s" % obj.getMsg()) 411 + except Notest as obj: 412 + log.warning("skipped %s" % obj.getMsg()) 413 + 414 + def setup_log(verbose): 415 + global log 416 + level = logging.CRITICAL 417 + 418 + if verbose == 1: 419 + level = logging.WARNING 420 + if verbose == 2: 421 + level = logging.INFO 422 + if verbose >= 3: 423 + level = logging.DEBUG 424 + 425 + log = logging.getLogger('test') 426 + log.setLevel(level) 427 + ch = logging.StreamHandler() 428 + ch.setLevel(level) 429 + formatter = logging.Formatter('%(message)s') 430 + ch.setFormatter(formatter) 431 + log.addHandler(ch) 432 + 433 + USAGE = '''%s [OPTIONS] 434 + -d dir # tests dir 435 + -p path # perf binary 436 + -t test # single test 437 + -v # verbose level 438 + ''' % sys.argv[0] 439 + 440 + def main(): 441 + parser = optparse.OptionParser(usage=USAGE) 442 + 443 + parser.add_option("-t", "--test", 444 + action="store", type="string", dest="test") 445 + parser.add_option("-d", "--test-dir", 446 + action="store", type="string", dest="test_dir") 447 + parser.add_option("-p", "--perf", 448 + action="store", type="string", dest="perf") 449 + parser.add_option("-v", "--verbose", 450 + default=0, action="count", dest="verbose") 451 + 452 + options, args = parser.parse_args() 453 + if args: 454 + parser.error('FAILED wrong arguments %s' % ' '.join(args)) 455 + return -1 456 + 457 + setup_log(options.verbose) 458 + 459 + if not options.test_dir: 460 + print('FAILED no -d option specified') 461 + sys.exit(-1) 462 + 463 + if not options.test: 464 + options.test = 'test*' 465 + 466 + try: 467 + run_tests(options) 468 + 469 + except Fail as obj: 470 + print("FAILED %s" % obj.getMsg()) 471 + sys.exit(-1) 472 + 473 + sys.exit(0) 474 + 475 + if __name__ == '__main__': 476 + main()
+1 -1
tools/perf/tests/shell/lib/coresight.sh
··· 18 18 # If the test tool/binary does not exist and is executable then skip the test 19 19 if ! test -x "$BIN"; then exit 2; fi 20 20 # If CoreSight is not available, skip the test 21 - perf list cs_etm | grep -q cs_etm || exit 2 21 + perf list pmu | grep -q cs_etm || exit 2 22 22 DATD="." 23 23 # If the data dir env is set then make the data dir use that instead of ./ 24 24 if test -n "$PERF_TEST_CORESIGHT_DATADIR"; then
+4 -1
tools/perf/tests/shell/lib/perf_json_output_lint.py
··· 57 57 'interval': lambda x: isfloat(x), 58 58 'metric-unit': lambda x: True, 59 59 'metric-value': lambda x: isfloat(x), 60 + 'metric-threshold': lambda x: x in ['unknown', 'good', 'less good', 'nearly bad', 'bad'], 60 61 'metricgroup': lambda x: True, 61 62 'node': lambda x: True, 62 63 'pcnt-running': lambda x: isfloat(x), ··· 69 68 for item in json.loads(input): 70 69 if expected_items != -1: 71 70 count = len(item) 72 - if count != expected_items and count >= 1 and count <= 6 and 'metric-value' in item: 71 + if count != expected_items and count >= 1 and count <= 7 and 'metric-value' in item: 73 72 # Events that generate >1 metric may have isolated metric 74 73 # values and possibly other prefixes like interval, core, 75 74 # aggregate-number, or event-runtime/pcnt-running from multiplexing. 76 75 pass 77 76 elif count != expected_items and count >= 1 and count <= 5 and 'metricgroup' in item: 78 77 pass 78 + elif count == expected_items + 1 and 'metric-threshold' in item: 79 + pass 79 80 elif count != expected_items: 80 81 raise RuntimeError(f'wrong number of fields. counted {count} expected {expected_items}' 81 82 f' in \'{item}\'')
+4 -1
tools/perf/tests/shell/list.sh
··· 24 24 25 25 test_list_json() { 26 26 echo "Json output test" 27 + # Generate perf list json output into list_output file. 27 28 perf list -j -o "${list_output}" 28 - $PYTHON -m json.tool "${list_output}" 29 + # Validate the json using python, redirect the json copy to /dev/null as 30 + # otherwise the test may block writing to stdout. 31 + $PYTHON -m json.tool "${list_output}" /dev/null 29 32 echo "Json output test [Success]" 30 33 } 31 34
+1 -1
tools/perf/tests/shell/lock_contention.sh
··· 27 27 exit 28 28 fi 29 29 30 - if ! perf list | grep -q lock:contention_begin; then 30 + if ! perf list tracepoint | grep -q lock:contention_begin; then 31 31 echo "[Skip] No lock contention tracepoints" 32 32 err=2 33 33 exit
+1 -1
tools/perf/tests/shell/perftool-testsuite_report.sh
··· 1 1 #!/bin/bash 2 - # perftool-testsuite_report 2 + # perftool-testsuite_report (exclusive) 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 5 5 test -d "$(dirname "$0")/base_report" || exit 2
+1
tools/perf/tests/shell/pipe_test.sh
··· 13 13 data=$(mktemp /tmp/perf.data.XXXXXX) 14 14 data2=$(mktemp /tmp/perf.data2.XXXXXX) 15 15 prog="perf test -w noploop" 16 + [ "$(uname -m)" = "s390x" ] && prog="$prog 3" 16 17 err=0 17 18 18 19 set -e
+1 -1
tools/perf/tests/shell/probe_vfs_getname.sh
··· 1 1 #!/bin/sh 2 - # Add vfs_getname probe to get syscall args filenames 2 + # Add vfs_getname probe to get syscall args filenames (exclusive) 3 3 4 4 # SPDX-License-Identifier: GPL-2.0 5 5 # Arnaldo Carvalho de Melo <acme@kernel.org>, 2017
+2 -2
tools/perf/tests/shell/record+probe_libc_inet_pton.sh
··· 40 40 case "$(uname -m)" in 41 41 s390x) 42 42 eventattr='call-graph=dwarf,max-stack=4' 43 - echo "(__GI_)?getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected 44 - echo "main\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$" >> $expected 43 + echo "((__GI_)?getaddrinfo|text_to_binary_address)\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected 44 + echo "(gaih_inet|main)\+0x[[:xdigit:]]+[[:space:]]\(inlined|.*/bin/ping.*\)$" >> $expected 45 45 ;; 46 46 ppc64|ppc64le) 47 47 eventattr='max-stack=4'
+1 -1
tools/perf/tests/shell/record+script_probe_vfs_getname.sh
··· 1 1 #!/bin/sh 2 - # Use vfs_getname probe to get syscall args filenames 2 + # Use vfs_getname probe to get syscall args filenames (exclusive) 3 3 4 4 # Uses the 'perf test shell' library to add probe:vfs_getname to the system 5 5 # then use it with 'perf record' using 'touch' to write to a temp file, then
+73 -2
tools/perf/tests/shell/record.sh
··· 1 1 #!/bin/bash 2 - # perf record tests 2 + # perf record tests (exclusive) 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 5 5 set -e ··· 17 17 18 18 err=0 19 19 perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) 20 + script_output=$(mktemp /tmp/__perf_test.perf.data.XXXXX.script) 20 21 testprog="perf test -w thloop" 21 22 cpu_pmu_dir="/sys/bus/event_source/devices/cpu*" 22 23 br_cntr_file="/caps/branch_counter_nr" ··· 94 93 95 94 test_register_capture() { 96 95 echo "Register capture test" 97 - if ! perf list | grep -q 'br_inst_retired.near_call' 96 + if ! perf list pmu | grep -q 'br_inst_retired.near_call' 98 97 then 99 98 echo "Register capture test [Skipped missing event]" 100 99 return ··· 229 228 echo "Cgroup sampling test [Success]" 230 229 } 231 230 231 + test_leader_sampling() { 232 + echo "Basic leader sampling test" 233 + if ! perf record -o "${perfdata}" -e "{instructions,instructions}:Su" -- \ 234 + perf test -w brstack 2> /dev/null 235 + then 236 + echo "Leader sampling [Failed record]" 237 + err=1 238 + return 239 + fi 240 + index=0 241 + perf script -i "${perfdata}" > $script_output 242 + while IFS= read -r line 243 + do 244 + # Check if the two instruction counts are equal in each record 245 + instructions=$(echo $line | awk '{for(i=1;i<=NF;i++) if($i=="instructions:") print $(i-1)}') 246 + if [ $(($index%2)) -ne 0 ] && [ ${instructions}x != ${prev_instructions}x ] 247 + then 248 + echo "Leader sampling [Failed inconsistent instructions count]" 249 + err=1 250 + return 251 + fi 252 + index=$(($index+1)) 253 + prev_instructions=$instructions 254 + done < $script_output 255 + echo "Basic leader sampling test [Success]" 256 + } 257 + 258 + test_topdown_leader_sampling() { 259 + echo "Topdown leader sampling test" 260 + if ! perf stat -e "{slots,topdown-retiring}" true 2> /dev/null 261 + then 262 + echo "Topdown leader sampling [Skipped event parsing failed]" 263 + return 264 + fi 265 + if ! perf record -o "${perfdata}" -e "{instructions,slots,topdown-retiring}:S" true 2> /dev/null 266 + then 267 + echo "Topdown leader sampling [Failed topdown events not reordered correctly]" 268 + err=1 269 + return 270 + fi 271 + echo "Topdown leader sampling test [Success]" 272 + } 273 + 274 + test_precise_max() { 275 + echo "precise_max attribute test" 276 + if ! perf stat -e "cycles,instructions" true 2> /dev/null 277 + then 278 + echo "precise_max attribute [Skipped no hardware events]" 279 + return 280 + fi 281 + # Just to make sure it doesn't fail 282 + if ! perf record -o "${perfdata}" -e "cycles:P" true 2> /dev/null 283 + then 284 + echo "precise_max attribute [Failed cycles:P event]" 285 + err=1 286 + return 287 + fi 288 + # On AMD, cycles and instructions events are treated differently 289 + if ! perf record -o "${perfdata}" -e "instructions:P" true 2> /dev/null 290 + then 291 + echo "precise_max attribute [Failed instructions:P event]" 292 + err=1 293 + return 294 + fi 295 + echo "precise_max attribute test [Success]" 296 + } 297 + 232 298 # raise the limit of file descriptors to minimum 233 299 if [[ $default_fd_limit -lt $min_fd_limit ]]; then 234 300 ulimit -Sn $min_fd_limit ··· 307 239 test_workload 308 240 test_branch_counter 309 241 test_cgroup 242 + test_leader_sampling 243 + test_topdown_leader_sampling 244 + test_precise_max 310 245 311 246 # restore the default value 312 247 ulimit -Sn $default_fd_limit
+1 -1
tools/perf/tests/shell/record_lbr.sh
··· 1 1 #!/bin/bash 2 - # perf record LBR tests 2 + # perf record LBR tests (exclusive) 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 5 5 set -e
+1 -1
tools/perf/tests/shell/record_offcpu.sh
··· 1 1 #!/bin/sh 2 - # perf record offcpu profiling tests 2 + # perf record offcpu profiling tests (exclusive) 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 5 5 set -e
+58 -7
tools/perf/tests/shell/stat.sh
··· 73 73 err=1 74 74 return 75 75 fi 76 - if perf stat -e '{topdown-retiring,slots}' true 2>&1 | grep -E -q "<not supported>" 76 + if perf stat -e 'instructions,topdown-retiring,slots' true 2>&1 | grep -E -q "<not supported>" 77 77 then 78 - echo "Topdown event group test [Failed slots not reordered first]" 78 + echo "Topdown event group test [Failed slots not reordered first in no-group case]" 79 + err=1 80 + return 81 + fi 82 + if perf stat -e '{instructions,topdown-retiring,slots}' true 2>&1 | grep -E -q "<not supported>" 83 + then 84 + echo "Topdown event group test [Failed slots not reordered first in single group case]" 85 + err=1 86 + return 87 + fi 88 + if perf stat -e '{instructions,slots},topdown-retiring' true 2>&1 | grep -E -q "<not supported>" 89 + then 90 + echo "Topdown event group test [Failed topdown metrics event not move into slots group]" 91 + err=1 92 + return 93 + fi 94 + if perf stat -e '{instructions,slots},{topdown-retiring}' true 2>&1 | grep -E -q "<not supported>" 95 + then 96 + echo "Topdown event group test [Failed topdown metrics group not merge into slots group]" 97 + err=1 98 + return 99 + fi 100 + if perf stat -e '{instructions,r400,r8000}' true 2>&1 | grep -E -q "<not supported>" 101 + then 102 + echo "Topdown event group test [Failed raw format slots not reordered first]" 79 103 err=1 80 104 return 81 105 fi ··· 141 117 142 118 # Find a known PMU for cputype. 143 119 pmu="" 144 - for i in cpu cpu_atom armv8_pmuv3_0 120 + devs="/sys/bus/event_source/devices" 121 + for i in $devs/cpu $devs/cpu_atom $devs/armv8_pmuv3_0 $devs/armv8_cortex_* 145 122 do 146 - if test -d "/sys/devices/$i" 123 + i_base=$(basename "$i") 124 + if test -d "$i" 147 125 then 148 - pmu="$i" 126 + pmu="$i_base" 149 127 break 150 128 fi 151 - if perf stat -e "$i/instructions/" true > /dev/null 2>&1 129 + if perf stat -e "$i_base/instructions/" true > /dev/null 2>&1 152 130 then 153 - pmu="$i" 131 + pmu="$i_base" 154 132 break 155 133 fi 156 134 done ··· 172 146 echo "cputype test [Success]" 173 147 } 174 148 149 + test_hybrid() { 150 + # Test the default stat command on hybrid devices opens one cycles event for 151 + # each CPU type. 152 + echo "hybrid test" 153 + 154 + # Count the number of core PMUs, assume minimum of 1 155 + pmus=$(ls /sys/bus/event_source/devices/*/cpus 2>/dev/null | wc -l) 156 + if [ "$pmus" -lt 1 ] 157 + then 158 + pmus=1 159 + fi 160 + 161 + # Run default Perf stat 162 + cycles_events=$(perf stat -- true 2>&1 | grep -E "/cycles/[uH]*| cycles[:uH]* " -c) 163 + 164 + if [ "$pmus" -ne "$cycles_events" ] 165 + then 166 + echo "hybrid test [Found $pmus PMUs but $cycles_events cycles events. Failed]" 167 + err=1 168 + return 169 + fi 170 + echo "hybrid test [Success]" 171 + } 172 + 175 173 test_default_stat 176 174 test_stat_record_report 177 175 test_stat_record_script ··· 203 153 test_topdown_groups 204 154 test_topdown_weak_groups 205 155 test_cputype 156 + test_hybrid 206 157 exit $err
+30 -6
tools/perf/tests/shell/stat_all_metricgroups.sh
··· 1 - #!/bin/sh 1 + #!/bin/bash 2 2 # perf all metricgroups test 3 3 # SPDX-License-Identifier: GPL-2.0 4 - 5 - set -e 6 4 7 5 ParanoidAndNotRoot() 8 6 { ··· 12 14 then 13 15 system_wide_flag="" 14 16 fi 15 - 17 + err=0 16 18 for m in $(perf list --raw-dump metricgroups) 17 19 do 18 20 echo "Testing $m" 19 - perf stat -M "$m" $system_wide_flag sleep 0.01 21 + result=$(perf stat -M "$m" $system_wide_flag sleep 0.01 2>&1) 22 + result_err=$? 23 + if [[ $result_err -gt 0 ]] 24 + then 25 + if [[ "$result" =~ \ 26 + "Access to performance monitoring and observability operations is limited" ]] 27 + then 28 + echo "Permission failure" 29 + echo $result 30 + if [[ $err -eq 0 ]] 31 + then 32 + err=2 # Skip 33 + fi 34 + elif [[ "$result" =~ "in per-thread mode, enable system wide" ]] 35 + then 36 + echo "Permissions - need system wide mode" 37 + echo $result 38 + if [[ $err -eq 0 ]] 39 + then 40 + err=2 # Skip 41 + fi 42 + else 43 + echo "Metric group $m failed" 44 + echo $result 45 + err=1 # Fail 46 + fi 47 + fi 20 48 done 21 49 22 - exit 0 50 + exit $err
+66 -21
tools/perf/tests/shell/stat_all_metrics.sh
··· 2 2 # perf all metrics test 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 5 + ParanoidAndNotRoot() 6 + { 7 + [ "$(id -u)" != 0 ] && [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt $1 ] 8 + } 9 + 10 + system_wide_flag="-a" 11 + if ParanoidAndNotRoot 0 12 + then 13 + system_wide_flag="" 14 + fi 15 + 5 16 err=0 6 17 for m in $(perf list --raw-dump metrics); do 7 18 echo "Testing $m" 8 - result=$(perf stat -M "$m" true 2>&1) 9 - if [[ "$result" =~ ${m:0:50} ]] || [[ "$result" =~ "<not supported>" ]] 19 + result=$(perf stat -M "$m" $system_wide_flag -- sleep 0.01 2>&1) 20 + result_err=$? 21 + if [[ $result_err -gt 0 ]] 10 22 then 11 - continue 23 + if [[ "$result" =~ \ 24 + "Access to performance monitoring and observability operations is limited" ]] 25 + then 26 + echo "Permission failure" 27 + echo $result 28 + if [[ $err -eq 0 ]] 29 + then 30 + err=2 # Skip 31 + fi 32 + continue 33 + elif [[ "$result" =~ "in per-thread mode, enable system wide" ]] 34 + then 35 + echo "Permissions - need system wide mode" 36 + echo $result 37 + if [[ $err -eq 0 ]] 38 + then 39 + err=2 # Skip 40 + fi 41 + continue 42 + elif [[ "$result" =~ "<not supported>" ]] 43 + then 44 + echo "Not supported events" 45 + echo $result 46 + if [[ $err -eq 0 ]] 47 + then 48 + err=2 # Skip 49 + fi 50 + continue 51 + elif [[ "$result" =~ "FP_ARITH" || "$result" =~ "AMX" ]] 52 + then 53 + echo "FP issues" 54 + echo $result 55 + if [[ $err -eq 0 ]] 56 + then 57 + err=2 # Skip 58 + fi 59 + continue 60 + elif [[ "$result" =~ "PMM" ]] 61 + then 62 + echo "Optane memory issues" 63 + echo $result 64 + if [[ $err -eq 0 ]] 65 + then 66 + err=2 # Skip 67 + fi 68 + continue 69 + fi 12 70 fi 13 - # Failed so try system wide. 14 - result=$(perf stat -M "$m" -a sleep 0.01 2>&1) 71 + 15 72 if [[ "$result" =~ ${m:0:50} ]] 16 73 then 17 74 continue 18 75 fi 19 - # Failed again, possibly the workload was too small so retry with something 20 - # longer. 21 - result=$(perf stat -M "$m" perf bench internals synthesize 2>&1) 76 + 77 + # Failed, possibly the workload was too small so retry with something longer. 78 + result=$(perf stat -M "$m" $system_wide_flag -- perf bench internals synthesize 2>&1) 22 79 if [[ "$result" =~ ${m:0:50} ]] 23 80 then 24 81 continue 25 82 fi 26 83 echo "Metric '$m' not printed in:" 27 84 echo "$result" 28 - if [[ "$err" != "1" ]] 29 - then 30 - err=2 31 - if [[ "$result" =~ "FP_ARITH" || "$result" =~ "AMX" ]] 32 - then 33 - echo "Skip, not fail, for FP issues" 34 - elif [[ "$result" =~ "PMM" ]] 35 - then 36 - echo "Skip, not fail, for Optane memory issues" 37 - else 38 - err=1 39 - fi 40 - fi 85 + err=1 41 86 done 42 87 43 88 exit "$err"
+41 -13
tools/perf/tests/shell/stat_all_pmu.sh
··· 1 - #!/bin/sh 2 - # perf all PMU test 1 + #!/bin/bash 2 + # perf all PMU test (exclusive) 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 5 5 set -e 6 + err=0 7 + result="" 8 + 9 + trap_cleanup() { 10 + echo "Unexpected signal in ${FUNCNAME[1]}" 11 + echo "$result" 12 + exit 1 13 + } 14 + trap trap_cleanup EXIT TERM INT 6 15 7 16 # Test all PMU events; however exclude parameterized ones (name contains '?') 8 - for p in $(perf list --raw-dump pmu | sed 's/[[:graph:]]\+?[[:graph:]]\+[[:space:]]//g'); do 17 + for p in $(perf list --raw-dump pmu | sed 's/[[:graph:]]\+?[[:graph:]]\+[[:space:]]//g') 18 + do 9 19 echo "Testing $p" 10 20 result=$(perf stat -e "$p" true 2>&1) 11 - if ! echo "$result" | grep -q "$p" && ! echo "$result" | grep -q "<not supported>" ; then 12 - # We failed to see the event and it is supported. Possibly the workload was 13 - # too small so retry with something longer. 14 - result=$(perf stat -e "$p" perf bench internals synthesize 2>&1) 15 - if ! echo "$result" | grep -q "$p" ; then 16 - echo "Event '$p' not printed in:" 17 - echo "$result" 18 - exit 1 19 - fi 21 + if echo "$result" | grep -q "$p" 22 + then 23 + # Event seen in output. 24 + continue 20 25 fi 26 + if echo "$result" | grep -q "<not supported>" 27 + then 28 + # Event not supported, so ignore. 29 + continue 30 + fi 31 + if echo "$result" | grep -q "Access to performance monitoring and observability operations is limited." 32 + then 33 + # Access is limited, so ignore. 34 + continue 35 + fi 36 + 37 + # We failed to see the event and it is supported. Possibly the workload was 38 + # too small so retry with something longer. 39 + result=$(perf stat -e "$p" perf bench internals synthesize 2>&1) 40 + if echo "$result" | grep -q "$p" 41 + then 42 + # Event seen in output. 43 + continue 44 + fi 45 + echo "Error: event '$p' not printed in:" 46 + echo "$result" 47 + err=1 21 48 done 22 49 23 - exit 0 50 + trap - EXIT TERM INT 51 + exit $err
+2 -2
tools/perf/tests/shell/stat_bpf_counters.sh
··· 1 1 #!/bin/sh 2 - # perf stat --bpf-counters test 2 + # perf stat --bpf-counters test (exclusive) 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 5 5 set -e 6 6 7 - workload="perf test -w brstack" 7 + workload="perf test -w sqrtloop" 8 8 9 9 # check whether $2 is within +/- 20% of $1 10 10 compare_number()
-13
tools/perf/tests/shell/stat_bpf_counters_cgrp.sh
··· 58 58 fi 59 59 } 60 60 61 - check_cpu_list_counted() 62 - { 63 - check_cpu_list_counted_output=$(perf stat -C 0,1 --bpf-counters --for-each-cgroup ${test_cgroups} -e cpu-clock -x, taskset -c 1 sleep 1 2>&1) 64 - if echo ${check_cpu_list_counted_output} | grep -q -F "<not "; then 65 - echo "Some CPU events are not counted" 66 - if [ "${verbose}" = "1" ]; then 67 - echo ${check_cpu_list_counted_output} 68 - fi 69 - exit 1 70 - fi 71 - } 72 - 73 61 check_bpf_counter 74 62 find_cgroups 75 63 76 64 check_system_wide_counted 77 - check_cpu_list_counted 78 65 79 66 exit 0
+2 -2
tools/perf/tests/shell/test_arm_coresight.sh
··· 1 1 #!/bin/sh 2 - # Check Arm CoreSight trace data recording and synthesized samples 2 + # Check Arm CoreSight trace data recording and synthesized samples (exclusive) 3 3 4 4 # Uses the 'perf record' to record trace data with Arm CoreSight sinks; 5 5 # then verify if there have any branch samples and instruction samples ··· 12 12 glb_err=0 13 13 14 14 skip_if_no_cs_etm_event() { 15 - perf list | grep -q 'cs_etm//' && return 0 15 + perf list pmu | grep -q 'cs_etm//' && return 0 16 16 17 17 # cs_etm event doesn't exist 18 18 return 2
+65
tools/perf/tests/shell/test_arm_coresight_disasm.sh
··· 1 + #!/bin/sh 2 + # Check Arm CoreSight disassembly script completes without errors (exclusive) 3 + # SPDX-License-Identifier: GPL-2.0 4 + 5 + # The disassembly script reconstructs ranges of instructions and gives these to objdump to 6 + # decode. objdump doesn't like ranges that go backwards, but these are a good indication 7 + # that decoding has gone wrong either in OpenCSD, Perf or in the range reconstruction in 8 + # the script. Test all 3 parts are working correctly by running the script. 9 + 10 + skip_if_no_cs_etm_event() { 11 + perf list pmu | grep -q 'cs_etm//' && return 0 12 + 13 + # cs_etm event doesn't exist 14 + return 2 15 + } 16 + 17 + skip_if_no_cs_etm_event || exit 2 18 + 19 + # Assume an error unless we reach the very end 20 + set -e 21 + glb_err=1 22 + 23 + perfdata_dir=$(mktemp -d /tmp/__perf_test.perf.data.XXXXX) 24 + perfdata=${perfdata_dir}/perf.data 25 + file=$(mktemp /tmp/temporary_file.XXXXX) 26 + # Relative path works whether it's installed or running from repo 27 + script_path=$(dirname "$0")/../../scripts/python/arm-cs-trace-disasm.py 28 + 29 + cleanup_files() 30 + { 31 + set +e 32 + rm -rf ${perfdata_dir} 33 + rm -f ${file} 34 + trap - EXIT TERM INT 35 + exit $glb_err 36 + } 37 + 38 + trap cleanup_files EXIT TERM INT 39 + 40 + # Ranges start and end on branches, so check for some likely branch instructions 41 + sep="\s\|\s" 42 + branch_search="\sbl${sep}b${sep}b.ne${sep}b.eq${sep}cbz\s" 43 + 44 + ## Test kernel ## 45 + if [ -e /proc/kcore ]; then 46 + echo "Testing kernel disassembly" 47 + perf record -o ${perfdata} -e cs_etm//k --kcore -- touch $file > /dev/null 2>&1 48 + perf script -i ${perfdata} -s python:${script_path} -- \ 49 + -d --stop-sample=30 2> /dev/null > ${file} 50 + grep -q -e ${branch_search} ${file} 51 + echo "Found kernel branches" 52 + else 53 + # kcore is required for correct kernel decode due to runtime code patching 54 + echo "No kcore, skipping kernel test" 55 + fi 56 + 57 + ## Test user ## 58 + echo "Testing userspace disassembly" 59 + perf record -o ${perfdata} -e cs_etm//u -- touch $file > /dev/null 2>&1 60 + perf script -i ${perfdata} -s python:${script_path} -- \ 61 + -d --stop-sample=30 2> /dev/null > ${file} 62 + grep -q -e ${branch_search} ${file} 63 + echo "Found userspace branches" 64 + 65 + glb_err=0
+2 -2
tools/perf/tests/shell/test_arm_spe.sh
··· 1 1 #!/bin/sh 2 - # Check Arm SPE trace data recording and synthesized samples 2 + # Check Arm SPE trace data recording and synthesized samples (exclusive) 3 3 4 4 # Uses the 'perf record' to record trace data of Arm SPE events; 5 5 # then verify if any SPE event samples are generated by SPE with ··· 9 9 # German Gomez <german.gomez@arm.com>, 2021 10 10 11 11 skip_if_no_arm_spe_event() { 12 - perf list | grep -E -q 'arm_spe_[0-9]+//' && return 0 12 + perf list pmu | grep -E -q 'arm_spe_[0-9]+//' && return 0 13 13 14 14 # arm_spe event doesn't exist 15 15 return 2
+1 -1
tools/perf/tests/shell/test_arm_spe_fork.sh
··· 5 5 # German Gomez <german.gomez@arm.com>, 2022 6 6 7 7 skip_if_no_arm_spe_event() { 8 - perf list | grep -E -q 'arm_spe_[0-9]+//' && return 0 8 + perf list pmu | grep -E -q 'arm_spe_[0-9]+//' && return 0 9 9 return 2 10 10 } 11 11
+1 -1
tools/perf/tests/shell/test_data_symbol.sh
··· 1 1 #!/bin/bash 2 - # Test data symbol 2 + # Test data symbol (exclusive) 3 3 4 4 # SPDX-License-Identifier: GPL-2.0 5 5 # Leo Yan <leo.yan@linaro.org>, 2022
+2 -2
tools/perf/tests/shell/test_intel_pt.sh
··· 1 1 #!/bin/sh 2 - # Miscellaneous Intel PT testing 2 + # Miscellaneous Intel PT testing (exclusive) 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 5 5 set -e 6 6 7 7 # Skip if no Intel PT 8 - perf list | grep -q 'intel_pt//' || exit 2 8 + perf list pmu | grep -q 'intel_pt//' || exit 2 9 9 10 10 shelldir=$(dirname "$0") 11 11 # shellcheck source=lib/waiting.sh
+8 -5
tools/perf/tests/shell/test_stat_intel_tpebs.sh
··· 1 1 #!/bin/bash 2 - # test Intel TPEBS counting mode 2 + # test Intel TPEBS counting mode (exclusive) 3 3 # SPDX-License-Identifier: GPL-2.0 4 4 5 5 set -e ··· 8 8 # Use this event for testing because it should exist in all platforms 9 9 event=cache-misses:R 10 10 11 + # Hybrid platforms output like "cpu_atom/cache-misses/R", rather than as above 12 + alt_name=/cache-misses/R 13 + 11 14 # Without this cmd option, default value or zero is returned 12 - echo "Testing without --record-tpebs" 13 - result=$(perf stat -e "$event" true 2>&1) 14 - [[ "$result" =~ $event ]] || exit 1 15 + #echo "Testing without --record-tpebs" 16 + #result=$(perf stat -e "$event" true 2>&1) 17 + #[[ "$result" =~ $event || "$result" =~ $alt_name ]] || exit 1 15 18 16 19 # In platforms that do not support TPEBS, it should execute without error. 17 20 echo "Testing with --record-tpebs" 18 21 result=$(perf stat -e "$event" --record-tpebs -a sleep 0.01 2>&1) 19 - [[ "$result" =~ "perf record" && "$result" =~ $event ]] || exit 1 22 + [[ "$result" =~ "perf record" && "$result" =~ $event || "$result" =~ $alt_name ]] || exit 1
+2 -2
tools/perf/tests/shell/trace+probe_vfs_getname.sh
··· 1 1 #!/bin/sh 2 - # Check open filename arg using perf trace + vfs_getname 2 + # Check open filename arg using perf trace + vfs_getname (exclusive) 3 3 4 4 # Uses the 'perf test shell' library to add probe:vfs_getname to the system 5 5 # then use it with 'perf trace' using 'touch' to write to a temp file, then ··· 19 19 . "$(dirname $0)"/lib/probe_vfs_getname.sh 20 20 21 21 trace_open_vfs_getname() { 22 - evts="$(echo "$(perf list syscalls:sys_enter_open* 2>/dev/null | grep -E 'open(at)? ' | sed -r 's/.*sys_enter_([a-z]+) +\[.*$/\1/')" | sed ':a;N;s:\n:,:g')" 22 + evts="$(echo "$(perf list tracepoint 2>/dev/null | grep -E 'syscalls:sys_enter_open(at)? ' | sed -r 's/.*sys_enter_([a-z]+) +\[.*$/\1/')" | sed ':a;N;s:\n:,:g')" 23 23 perf trace -e $evts touch $file 2>&1 | \ 24 24 grep -E " +[0-9]+\.[0-9]+ +\( +[0-9]+\.[0-9]+ ms\): +touch/[0-9]+ open(at)?\((dfd: +CWD, +)?filename: +\"?${file}\"?, +flags: CREAT\|NOCTTY\|NONBLOCK\|WRONLY, +mode: +IRUGO\|IWUGO\) += +[0-9]+$" 25 25 }
+51
tools/perf/tests/shell/trace_exit_race.sh
··· 1 + #!/bin/sh 2 + # perf trace exit race 3 + # SPDX-License-Identifier: GPL-2.0 4 + 5 + # Check that the last events of a perf trace'd subprocess are not 6 + # lost. Specifically, trace the exiting syscall of "true" 10 times and ensure 7 + # the output contains 10 correct lines. 8 + 9 + # shellcheck source=lib/probe.sh 10 + . "$(dirname $0)"/lib/probe.sh 11 + 12 + skip_if_no_perf_trace || exit 2 13 + 14 + if [ "$1" = "-v" ]; then 15 + verbose="1" 16 + fi 17 + 18 + iter=10 19 + regexp=" +[0-9]+\.[0-9]+ [0-9]+ syscalls:sys_enter_exit_group\(\)$" 20 + 21 + trace_shutdown_race() { 22 + for _ in $(seq $iter); do 23 + perf trace --no-comm -e syscalls:sys_enter_exit_group true 2>>$file 24 + done 25 + result="$(grep -c -E "$regexp" $file)" 26 + [ $result = $iter ] 27 + } 28 + 29 + 30 + file=$(mktemp /tmp/temporary_file.XXXXX) 31 + 32 + # Do not use whatever ~/.perfconfig file, it may change the output 33 + # via trace.{show_timestamp,show_prefix,etc} 34 + export PERF_CONFIG=/dev/null 35 + 36 + trace_shutdown_race 37 + err=$? 38 + 39 + if [ $err != 0 ] && [ "${verbose}" = "1" ]; then 40 + lines_not_matching=$(mktemp /tmp/temporary_file.XXXXX) 41 + if grep -v -E "$regexp" $file > $lines_not_matching ; then 42 + echo "Lines not matching the expected regexp: '$regexp':" 43 + cat $lines_not_matching 44 + else 45 + echo "Missing output, expected $iter but only got $result" 46 + fi 47 + rm -f $lines_not_matching 48 + fi 49 + 50 + rm -f ${file} 51 + exit $err
+8 -1
tools/perf/tests/task-exit.c
··· 152 152 return err; 153 153 } 154 154 155 - DEFINE_SUITE("Number of exit events of a simple workload", task_exit); 155 + struct test_case tests__task_exit[] = { 156 + TEST_CASE_EXCLUSIVE("Number of exit events of a simple workload", task_exit), 157 + { .name = NULL, } 158 + }; 159 + struct test_suite suite__task_exit = { 160 + .desc = "Number of exit events of a simple workload", 161 + .test_cases = tests__task_exit, 162 + };
+6 -1
tools/perf/tests/tests-scripts.c
··· 175 175 struct test_suite *test_suite, **result_tmp; 176 176 struct test_case *tests; 177 177 size_t len; 178 + char *exclusive; 178 179 179 180 snprintf(link, sizeof(link), "/proc/%d/fd/%d", getpid(), dir_fd); 180 181 len = readlink(link, filename, sizeof(filename)); ··· 192 191 return; 193 192 } 194 193 tests[0].name = strdup_check(name); 194 + exclusive = strstr(desc, " (exclusive)"); 195 + if (exclusive != NULL) { 196 + tests[0].exclusive = true; 197 + exclusive[0] = '\0'; 198 + } 195 199 tests[0].desc = strdup_check(desc); 196 200 tests[0].run_case = shell_test__run; 197 - 198 201 test_suite = zalloc(sizeof(*test_suite)); 199 202 if (!test_suite) { 200 203 pr_err("Out of memory while building script test suite list\n");
+11
tools/perf/tests/tests.h
··· 36 36 const char *desc; 37 37 const char *skip_reason; 38 38 test_fnptr run_case; 39 + bool exclusive; 39 40 }; 40 41 41 42 struct test_suite { ··· 63 62 .skip_reason = _reason, \ 64 63 } 65 64 65 + #define TEST_CASE_EXCLUSIVE(description, _name) \ 66 + { \ 67 + .name = #_name, \ 68 + .desc = description, \ 69 + .run_case = test__##_name, \ 70 + .exclusive = true, \ 71 + } 72 + 66 73 #define DEFINE_SUITE(description, _name) \ 67 74 struct test_case tests__##_name[] = { \ 68 75 TEST_CASE(description, _name), \ ··· 92 83 DECLARE_SUITE(syscall_openat_tp_fields); 93 84 DECLARE_SUITE(pmu); 94 85 DECLARE_SUITE(pmu_events); 86 + DECLARE_SUITE(hwmon_pmu); 87 + DECLARE_SUITE(tool_pmu); 95 88 DECLARE_SUITE(attr); 96 89 DECLARE_SUITE(dso_data); 97 90 DECLARE_SUITE(dso_data_cache);
+111
tools/perf/tests/tool_pmu.c
··· 1 + // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 + #include "debug.h" 3 + #include "evlist.h" 4 + #include "parse-events.h" 5 + #include "tests.h" 6 + #include "tool_pmu.h" 7 + 8 + static int do_test(enum tool_pmu_event ev, bool with_pmu) 9 + { 10 + struct evlist *evlist = evlist__new(); 11 + struct evsel *evsel; 12 + struct parse_events_error err; 13 + int ret; 14 + char str[128]; 15 + bool found = false; 16 + 17 + if (!evlist) { 18 + pr_err("evlist allocation failed\n"); 19 + return TEST_FAIL; 20 + } 21 + 22 + if (with_pmu) 23 + snprintf(str, sizeof(str), "tool/%s/", tool_pmu__event_to_str(ev)); 24 + else 25 + snprintf(str, sizeof(str), "%s", tool_pmu__event_to_str(ev)); 26 + 27 + parse_events_error__init(&err); 28 + ret = parse_events(evlist, str, &err); 29 + if (ret) { 30 + if (tool_pmu__skip_event(tool_pmu__event_to_str(ev))) { 31 + ret = TEST_OK; 32 + goto out; 33 + } 34 + 35 + pr_debug("FAILED %s:%d failed to parse event '%s', err %d\n", 36 + __FILE__, __LINE__, str, ret); 37 + parse_events_error__print(&err, str); 38 + ret = TEST_FAIL; 39 + goto out; 40 + } 41 + 42 + ret = TEST_OK; 43 + if (with_pmu ? (evlist->core.nr_entries != 1) : (evlist->core.nr_entries < 1)) { 44 + pr_debug("FAILED %s:%d Unexpected number of events for '%s' of %d\n", 45 + __FILE__, __LINE__, str, evlist->core.nr_entries); 46 + ret = TEST_FAIL; 47 + goto out; 48 + } 49 + 50 + evlist__for_each_entry(evlist, evsel) { 51 + if (perf_pmu__is_tool(evsel->pmu)) { 52 + if (evsel->core.attr.config != ev) { 53 + pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %d\n", 54 + __FILE__, __LINE__, str, evsel->core.attr.config, ev); 55 + ret = TEST_FAIL; 56 + goto out; 57 + } 58 + found = true; 59 + } 60 + } 61 + 62 + if (!found && !tool_pmu__skip_event(tool_pmu__event_to_str(ev))) { 63 + pr_debug("FAILED %s:%d Didn't find tool event '%s' in parsed evsels\n", 64 + __FILE__, __LINE__, str); 65 + ret = TEST_FAIL; 66 + } 67 + 68 + out: 69 + parse_events_error__exit(&err); 70 + evlist__delete(evlist); 71 + return ret; 72 + } 73 + 74 + static int test__tool_pmu_without_pmu(struct test_suite *test __maybe_unused, 75 + int subtest __maybe_unused) 76 + { 77 + int i; 78 + 79 + tool_pmu__for_each_event(i) { 80 + int ret = do_test(i, /*with_pmu=*/false); 81 + 82 + if (ret != TEST_OK) 83 + return ret; 84 + } 85 + return TEST_OK; 86 + } 87 + 88 + static int test__tool_pmu_with_pmu(struct test_suite *test __maybe_unused, 89 + int subtest __maybe_unused) 90 + { 91 + int i; 92 + 93 + tool_pmu__for_each_event(i) { 94 + int ret = do_test(i, /*with_pmu=*/true); 95 + 96 + if (ret != TEST_OK) 97 + return ret; 98 + } 99 + return TEST_OK; 100 + } 101 + 102 + static struct test_case tests__tool_pmu[] = { 103 + TEST_CASE("Parsing without PMU name", tool_pmu_without_pmu), 104 + TEST_CASE("Parsing with PMU name", tool_pmu_with_pmu), 105 + { .name = NULL, } 106 + }; 107 + 108 + struct test_suite suite__tool_pmu = { 109 + .desc = "Tool PMU", 110 + .test_cases = tests__tool_pmu, 111 + };
+11 -6
tools/perf/util/Build
··· 83 83 perf-util-y += pmus.o 84 84 perf-util-y += pmu-flex.o 85 85 perf-util-y += pmu-bison.o 86 + perf-util-y += hwmon_pmu.o 87 + perf-util-y += tool_pmu.o 86 88 perf-util-y += svghelper.o 87 89 perf-util-$(CONFIG_LIBTRACEEVENT) += trace-event-info.o 88 90 perf-util-y += trace-event-scripting.o ··· 201 199 perf-util-y += setns.o 202 200 endif 203 201 204 - perf-util-$(CONFIG_DWARF) += probe-finder.o 205 - perf-util-$(CONFIG_DWARF) += dwarf-aux.o 206 - perf-util-$(CONFIG_DWARF) += dwarf-regs.o 207 - perf-util-$(CONFIG_DWARF) += debuginfo.o 208 - perf-util-$(CONFIG_DWARF) += annotate-data.o 202 + perf-util-$(CONFIG_LIBDW) += probe-finder.o 203 + perf-util-$(CONFIG_LIBDW) += dwarf-aux.o 204 + perf-util-$(CONFIG_LIBDW) += dwarf-regs.o 205 + perf-util-$(CONFIG_LIBDW) += dwarf-regs-csky.o 206 + perf-util-$(CONFIG_LIBDW) += dwarf-regs-powerpc.o 207 + perf-util-$(CONFIG_LIBDW) += dwarf-regs-x86.o 208 + perf-util-$(CONFIG_LIBDW) += debuginfo.o 209 + perf-util-$(CONFIG_LIBDW) += annotate-data.o 209 210 210 211 perf-util-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 211 212 perf-util-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o ··· 239 234 ifdef CONFIG_JITDUMP 240 235 perf-util-$(CONFIG_LIBELF) += jitdump.o 241 236 perf-util-$(CONFIG_LIBELF) += genelf.o 242 - perf-util-$(CONFIG_DWARF) += genelf_debug.o 237 + perf-util-$(CONFIG_LIBDW) += genelf_debug.o 243 238 endif 244 239 245 240 perf-util-y += perf-hooks.o
+4 -4
tools/perf/util/annotate-data.h
··· 9 9 #include "dwarf-regs.h" 10 10 #include "annotate.h" 11 11 12 - #ifdef HAVE_DWARF_SUPPORT 12 + #ifdef HAVE_LIBDW_SUPPORT 13 13 #include "debuginfo.h" 14 14 #endif 15 15 ··· 165 165 }; 166 166 extern struct annotated_data_stat ann_data_stat; 167 167 168 - #ifdef HAVE_DWARF_SUPPORT 168 + #ifdef HAVE_LIBDW_SUPPORT 169 169 /* 170 170 * Type information in a register, valid when @ok is true. 171 171 * The @caller_saved registers are invalidated after a function call. ··· 244 244 const char **var_name, int *var_offset); 245 245 void pr_debug_type_name(Dwarf_Die *die, enum type_state_kind kind); 246 246 247 - #else /* HAVE_DWARF_SUPPORT */ 247 + #else /* HAVE_LIBDW_SUPPORT */ 248 248 249 249 static inline struct annotated_data_type * 250 250 find_data_type(struct data_loc_info *dloc __maybe_unused) ··· 276 276 return -1; 277 277 } 278 278 279 - #endif /* HAVE_DWARF_SUPPORT */ 279 + #endif /* HAVE_LIBDW_SUPPORT */ 280 280 281 281 #ifdef HAVE_SLANG_SUPPORT 282 282 int hist_entry__annotate_data_tui(struct hist_entry *he, struct evsel *evsel,
+9 -3
tools/perf/util/annotate.c
··· 2116 2116 opt->offset_level = ANNOTATION__MAX_OFFSET_LEVEL; 2117 2117 else if (opt->offset_level < ANNOTATION__MIN_OFFSET_LEVEL) 2118 2118 opt->offset_level = ANNOTATION__MIN_OFFSET_LEVEL; 2119 + } else if (!strcmp(var, "annotate.disassemblers")) { 2120 + opt->disassemblers_str = strdup(value); 2121 + if (!opt->disassemblers_str) { 2122 + pr_err("Not enough memory for annotate.disassemblers\n"); 2123 + return -1; 2124 + } 2119 2125 } else if (!strcmp(var, "annotate.hide_src_code")) { 2120 2126 opt->hide_src_code = perf_config_bool("hide_src_code", value); 2121 2127 } else if (!strcmp(var, "annotate.jump_arrows")) { ··· 2298 2292 if (regname == NULL) 2299 2293 return -1; 2300 2294 2301 - op_loc->reg1 = get_dwarf_regnum(regname, 0); 2295 + op_loc->reg1 = get_dwarf_regnum(regname, arch->e_machine, arch->e_flags); 2302 2296 free(regname); 2303 2297 2304 2298 /* Get the second register */ ··· 2311 2305 if (regname == NULL) 2312 2306 return -1; 2313 2307 2314 - op_loc->reg2 = get_dwarf_regnum(regname, 0); 2308 + op_loc->reg2 = get_dwarf_regnum(regname, arch->e_machine, arch->e_flags); 2315 2309 free(regname); 2316 2310 } 2317 2311 return 0; ··· 2411 2405 return -1; 2412 2406 2413 2407 if (*s == arch->objdump.register_char) 2414 - op_loc->reg1 = get_dwarf_regnum(s, 0); 2408 + op_loc->reg1 = get_dwarf_regnum(s, arch->e_machine, arch->e_flags); 2415 2409 else if (*s == arch->objdump.imm_char) { 2416 2410 op_loc->offset = strtol(s + 1, &p, 0); 2417 2411 if (p && p != s + 1)
+6
tools/perf/util/annotate.h
··· 34 34 #define ANNOTATION__BR_CNTR_WIDTH 30 35 35 #define ANNOTATION_DUMMY_LEN 256 36 36 37 + // llvm, capstone, objdump 38 + #define MAX_DISASSEMBLERS 3 39 + 37 40 struct annotation_options { 38 41 bool hide_src_code, 39 42 use_offset, ··· 52 49 annotate_src, 53 50 full_addr; 54 51 u8 offset_level; 52 + u8 nr_disassemblers; 55 53 int min_pcnt; 56 54 int max_lines; 57 55 int context; 58 56 char *objdump_path; 59 57 char *disassembler_style; 58 + const char *disassemblers_str; 59 + const char *disassemblers[MAX_DISASSEMBLERS]; 60 60 const char *prefix; 61 61 const char *prefix_strip; 62 62 unsigned int percent_type;
+9 -9
tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
··· 56 56 ARM_SPE_OP_BR_INDIRECT = 1 << 17, 57 57 }; 58 58 59 - enum arm_spe_neoverse_data_source { 60 - ARM_SPE_NV_L1D = 0x0, 61 - ARM_SPE_NV_L2 = 0x8, 62 - ARM_SPE_NV_PEER_CORE = 0x9, 63 - ARM_SPE_NV_LOCAL_CLUSTER = 0xa, 64 - ARM_SPE_NV_SYS_CACHE = 0xb, 65 - ARM_SPE_NV_PEER_CLUSTER = 0xc, 66 - ARM_SPE_NV_REMOTE = 0xd, 67 - ARM_SPE_NV_DRAM = 0xe, 59 + enum arm_spe_common_data_source { 60 + ARM_SPE_COMMON_DS_L1D = 0x0, 61 + ARM_SPE_COMMON_DS_L2 = 0x8, 62 + ARM_SPE_COMMON_DS_PEER_CORE = 0x9, 63 + ARM_SPE_COMMON_DS_LOCAL_CLUSTER = 0xa, 64 + ARM_SPE_COMMON_DS_SYS_CACHE = 0xb, 65 + ARM_SPE_COMMON_DS_PEER_CLUSTER = 0xc, 66 + ARM_SPE_COMMON_DS_REMOTE = 0xd, 67 + ARM_SPE_COMMON_DS_DRAM = 0xe, 68 68 }; 69 69 70 70 struct arm_spe_record {
+280 -41
tools/perf/util/arm-spe.c
··· 46 46 struct perf_session *session; 47 47 struct machine *machine; 48 48 u32 pmu_type; 49 - u64 midr; 50 49 51 50 struct perf_tsc_conversion tc; 52 51 ··· 68 69 u64 llc_access_id; 69 70 u64 tlb_miss_id; 70 71 u64 tlb_access_id; 71 - u64 branch_miss_id; 72 + u64 branch_id; 72 73 u64 remote_access_id; 73 74 u64 memory_id; 74 75 u64 instructions_id; ··· 77 78 78 79 unsigned long num_events; 79 80 u8 use_ctx_pkt_for_pid; 81 + 82 + u64 **metadata; 83 + u64 metadata_ver; 84 + u64 metadata_nr_cpu; 85 + bool is_homogeneous; 80 86 }; 81 87 82 88 struct arm_spe_queue { ··· 100 96 u64 timestamp; 101 97 struct thread *thread; 102 98 u64 period_instructions; 99 + u32 flags; 103 100 }; 104 101 105 102 static void arm_spe_dump(struct arm_spe *spe __maybe_unused, ··· 123 118 else 124 119 pkt_len = 1; 125 120 printf("."); 126 - color_fprintf(stdout, color, " %08x: ", pos); 121 + color_fprintf(stdout, color, " %08zx: ", pos); 127 122 for (i = 0; i < pkt_len; i++) 128 123 color_fprintf(stdout, color, " %02x", buf[i]); 129 124 for (; i < 16; i++) ··· 278 273 return 0; 279 274 } 280 275 276 + static u64 *arm_spe__get_metadata_by_cpu(struct arm_spe *spe, u64 cpu) 277 + { 278 + u64 i; 279 + 280 + if (!spe->metadata) 281 + return NULL; 282 + 283 + for (i = 0; i < spe->metadata_nr_cpu; i++) 284 + if (spe->metadata[i][ARM_SPE_CPU] == cpu) 285 + return spe->metadata[i]; 286 + 287 + return NULL; 288 + } 289 + 281 290 static struct simd_flags arm_spe__synth_simd_flags(const struct arm_spe_record *record) 282 291 { 283 292 struct simd_flags simd_flags = {}; ··· 395 376 sample.stream_id = spe_events_id; 396 377 sample.addr = record->to_ip; 397 378 sample.weight = record->latency; 379 + sample.flags = speq->flags; 398 380 399 381 return arm_spe_deliver_synth_event(spe, speq, event, &sample); 400 382 } ··· 420 400 421 401 sample.id = spe_events_id; 422 402 sample.stream_id = spe_events_id; 423 - sample.addr = record->virt_addr; 403 + sample.addr = record->to_ip; 424 404 sample.phys_addr = record->phys_addr; 425 405 sample.data_src = data_src; 426 406 sample.period = spe->instructions_sample_period; 427 407 sample.weight = record->latency; 408 + sample.flags = speq->flags; 428 409 429 410 return arm_spe_deliver_synth_event(spe, speq, event, &sample); 430 411 } 431 412 432 - static const struct midr_range neoverse_spe[] = { 413 + static const struct midr_range common_ds_encoding_cpus[] = { 414 + MIDR_ALL_VERSIONS(MIDR_CORTEX_A720), 415 + MIDR_ALL_VERSIONS(MIDR_CORTEX_A725), 416 + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C), 417 + MIDR_ALL_VERSIONS(MIDR_CORTEX_X3), 418 + MIDR_ALL_VERSIONS(MIDR_CORTEX_X925), 433 419 MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), 434 420 MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), 435 421 MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), 422 + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2), 436 423 {}, 437 424 }; 438 425 439 - static void arm_spe__synth_data_source_neoverse(const struct arm_spe_record *record, 440 - union perf_mem_data_src *data_src) 426 + static void arm_spe__sample_flags(struct arm_spe_queue *speq) 427 + { 428 + const struct arm_spe_record *record = &speq->decoder->record; 429 + 430 + speq->flags = 0; 431 + if (record->op & ARM_SPE_OP_BRANCH_ERET) { 432 + speq->flags = PERF_IP_FLAG_BRANCH; 433 + 434 + if (record->type & ARM_SPE_BRANCH_MISS) 435 + speq->flags |= PERF_IP_FLAG_BRANCH_MISS; 436 + } 437 + } 438 + 439 + static void arm_spe__synth_data_source_common(const struct arm_spe_record *record, 440 + union perf_mem_data_src *data_src) 441 441 { 442 442 /* 443 443 * Even though four levels of cache hierarchy are possible, no known ··· 479 439 } 480 440 481 441 switch (record->source) { 482 - case ARM_SPE_NV_L1D: 442 + case ARM_SPE_COMMON_DS_L1D: 483 443 data_src->mem_lvl = PERF_MEM_LVL_L1 | PERF_MEM_LVL_HIT; 484 444 data_src->mem_lvl_num = PERF_MEM_LVLNUM_L1; 485 445 data_src->mem_snoop = PERF_MEM_SNOOP_NONE; 486 446 break; 487 - case ARM_SPE_NV_L2: 447 + case ARM_SPE_COMMON_DS_L2: 488 448 data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; 489 449 data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; 490 450 data_src->mem_snoop = PERF_MEM_SNOOP_NONE; 491 451 break; 492 - case ARM_SPE_NV_PEER_CORE: 452 + case ARM_SPE_COMMON_DS_PEER_CORE: 493 453 data_src->mem_lvl = PERF_MEM_LVL_L2 | PERF_MEM_LVL_HIT; 494 454 data_src->mem_lvl_num = PERF_MEM_LVLNUM_L2; 495 455 data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; ··· 498 458 * We don't know if this is L1, L2 but we do know it was a cache-2-cache 499 459 * transfer, so set SNOOPX_PEER 500 460 */ 501 - case ARM_SPE_NV_LOCAL_CLUSTER: 502 - case ARM_SPE_NV_PEER_CLUSTER: 461 + case ARM_SPE_COMMON_DS_LOCAL_CLUSTER: 462 + case ARM_SPE_COMMON_DS_PEER_CLUSTER: 503 463 data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_HIT; 504 464 data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; 505 465 data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; ··· 507 467 /* 508 468 * System cache is assumed to be L3 509 469 */ 510 - case ARM_SPE_NV_SYS_CACHE: 470 + case ARM_SPE_COMMON_DS_SYS_CACHE: 511 471 data_src->mem_lvl = PERF_MEM_LVL_L3 | PERF_MEM_LVL_HIT; 512 472 data_src->mem_lvl_num = PERF_MEM_LVLNUM_L3; 513 473 data_src->mem_snoop = PERF_MEM_SNOOP_HIT; ··· 516 476 * We don't know what level it hit in, except it came from the other 517 477 * socket 518 478 */ 519 - case ARM_SPE_NV_REMOTE: 479 + case ARM_SPE_COMMON_DS_REMOTE: 520 480 data_src->mem_lvl = PERF_MEM_LVL_REM_CCE1; 521 481 data_src->mem_lvl_num = PERF_MEM_LVLNUM_ANY_CACHE; 522 482 data_src->mem_remote = PERF_MEM_REMOTE_REMOTE; 523 483 data_src->mem_snoopx = PERF_MEM_SNOOPX_PEER; 524 484 break; 525 - case ARM_SPE_NV_DRAM: 485 + case ARM_SPE_COMMON_DS_DRAM: 526 486 data_src->mem_lvl = PERF_MEM_LVL_LOC_RAM | PERF_MEM_LVL_HIT; 527 487 data_src->mem_lvl_num = PERF_MEM_LVLNUM_RAM; 528 488 data_src->mem_snoop = PERF_MEM_SNOOP_NONE; ··· 532 492 } 533 493 } 534 494 535 - static void arm_spe__synth_data_source_generic(const struct arm_spe_record *record, 536 - union perf_mem_data_src *data_src) 495 + static void arm_spe__synth_memory_level(const struct arm_spe_record *record, 496 + union perf_mem_data_src *data_src) 537 497 { 538 498 if (record->type & (ARM_SPE_LLC_ACCESS | ARM_SPE_LLC_MISS)) { 539 499 data_src->mem_lvl = PERF_MEM_LVL_L3; ··· 555 515 data_src->mem_lvl |= PERF_MEM_LVL_REM_CCE1; 556 516 } 557 517 558 - static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 midr) 518 + static bool arm_spe__is_common_ds_encoding(struct arm_spe_queue *speq) 519 + { 520 + struct arm_spe *spe = speq->spe; 521 + bool is_in_cpu_list; 522 + u64 *metadata = NULL; 523 + u64 midr = 0; 524 + 525 + /* Metadata version 1 assumes all CPUs are the same (old behavior) */ 526 + if (spe->metadata_ver == 1) { 527 + const char *cpuid; 528 + 529 + pr_warning_once("Old SPE metadata, re-record to improve decode accuracy\n"); 530 + cpuid = perf_env__cpuid(spe->session->evlist->env); 531 + midr = strtol(cpuid, NULL, 16); 532 + } else { 533 + /* CPU ID is -1 for per-thread mode */ 534 + if (speq->cpu < 0) { 535 + /* 536 + * On the heterogeneous system, due to CPU ID is -1, 537 + * cannot confirm the data source packet is supported. 538 + */ 539 + if (!spe->is_homogeneous) 540 + return false; 541 + 542 + /* In homogeneous system, simply use CPU0's metadata */ 543 + if (spe->metadata) 544 + metadata = spe->metadata[0]; 545 + } else { 546 + metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu); 547 + } 548 + 549 + if (!metadata) 550 + return false; 551 + 552 + midr = metadata[ARM_SPE_CPU_MIDR]; 553 + } 554 + 555 + is_in_cpu_list = is_midr_in_range_list(midr, common_ds_encoding_cpus); 556 + if (is_in_cpu_list) 557 + return true; 558 + else 559 + return false; 560 + } 561 + 562 + static u64 arm_spe__synth_data_source(struct arm_spe_queue *speq, 563 + const struct arm_spe_record *record) 559 564 { 560 565 union perf_mem_data_src data_src = { .mem_op = PERF_MEM_OP_NA }; 561 - bool is_neoverse = is_midr_in_range_list(midr, neoverse_spe); 566 + bool is_common = arm_spe__is_common_ds_encoding(speq); 562 567 563 568 if (record->op & ARM_SPE_OP_LD) 564 569 data_src.mem_op = PERF_MEM_OP_LOAD; ··· 612 527 else 613 528 return 0; 614 529 615 - if (is_neoverse) 616 - arm_spe__synth_data_source_neoverse(record, &data_src); 530 + if (is_common) 531 + arm_spe__synth_data_source_common(record, &data_src); 617 532 else 618 - arm_spe__synth_data_source_generic(record, &data_src); 533 + arm_spe__synth_memory_level(record, &data_src); 619 534 620 535 if (record->type & (ARM_SPE_TLB_ACCESS | ARM_SPE_TLB_MISS)) { 621 536 data_src.mem_dtlb = PERF_MEM_TLB_WK; ··· 636 551 u64 data_src; 637 552 int err; 638 553 639 - data_src = arm_spe__synth_data_source(record, spe->midr); 554 + arm_spe__sample_flags(speq); 555 + data_src = arm_spe__synth_data_source(speq, record); 640 556 641 557 if (spe->sample_flc) { 642 558 if (record->type & ARM_SPE_L1D_MISS) { ··· 687 601 } 688 602 } 689 603 690 - if (spe->sample_branch && (record->type & ARM_SPE_BRANCH_MISS)) { 691 - err = arm_spe__synth_branch_sample(speq, spe->branch_miss_id); 604 + if (spe->sample_branch && (record->op & ARM_SPE_OP_BRANCH_ERET)) { 605 + err = arm_spe__synth_branch_sample(speq, spe->branch_id); 692 606 if (err) 693 607 return err; 694 608 } ··· 1102 1016 return 0; 1103 1017 } 1104 1018 1019 + static u64 *arm_spe__alloc_per_cpu_metadata(u64 *buf, int per_cpu_size) 1020 + { 1021 + u64 *metadata; 1022 + 1023 + metadata = zalloc(per_cpu_size); 1024 + if (!metadata) 1025 + return NULL; 1026 + 1027 + memcpy(metadata, buf, per_cpu_size); 1028 + return metadata; 1029 + } 1030 + 1031 + static void arm_spe__free_metadata(u64 **metadata, int nr_cpu) 1032 + { 1033 + int i; 1034 + 1035 + for (i = 0; i < nr_cpu; i++) 1036 + zfree(&metadata[i]); 1037 + free(metadata); 1038 + } 1039 + 1040 + static u64 **arm_spe__alloc_metadata(struct perf_record_auxtrace_info *info, 1041 + u64 *ver, int *nr_cpu) 1042 + { 1043 + u64 *ptr = (u64 *)info->priv; 1044 + u64 metadata_size; 1045 + u64 **metadata = NULL; 1046 + int hdr_sz, per_cpu_sz, i; 1047 + 1048 + metadata_size = info->header.size - 1049 + sizeof(struct perf_record_auxtrace_info); 1050 + 1051 + /* Metadata version 1 */ 1052 + if (metadata_size == ARM_SPE_AUXTRACE_V1_PRIV_SIZE) { 1053 + *ver = 1; 1054 + *nr_cpu = 0; 1055 + /* No per CPU metadata */ 1056 + return NULL; 1057 + } 1058 + 1059 + *ver = ptr[ARM_SPE_HEADER_VERSION]; 1060 + hdr_sz = ptr[ARM_SPE_HEADER_SIZE]; 1061 + *nr_cpu = ptr[ARM_SPE_CPUS_NUM]; 1062 + 1063 + metadata = calloc(*nr_cpu, sizeof(*metadata)); 1064 + if (!metadata) 1065 + return NULL; 1066 + 1067 + /* Locate the start address of per CPU metadata */ 1068 + ptr += hdr_sz; 1069 + per_cpu_sz = (metadata_size - (hdr_sz * sizeof(u64))) / (*nr_cpu); 1070 + 1071 + for (i = 0; i < *nr_cpu; i++) { 1072 + metadata[i] = arm_spe__alloc_per_cpu_metadata(ptr, per_cpu_sz); 1073 + if (!metadata[i]) 1074 + goto err_per_cpu_metadata; 1075 + 1076 + ptr += per_cpu_sz / sizeof(u64); 1077 + } 1078 + 1079 + return metadata; 1080 + 1081 + err_per_cpu_metadata: 1082 + arm_spe__free_metadata(metadata, *nr_cpu); 1083 + return NULL; 1084 + } 1085 + 1105 1086 static void arm_spe_free_queue(void *priv) 1106 1087 { 1107 1088 struct arm_spe_queue *speq = priv; ··· 1203 1050 auxtrace_heap__free(&spe->heap); 1204 1051 arm_spe_free_events(session); 1205 1052 session->auxtrace = NULL; 1053 + arm_spe__free_metadata(spe->metadata, spe->metadata_nr_cpu); 1206 1054 free(spe); 1207 1055 } 1208 1056 ··· 1215 1061 return evsel->core.attr.type == spe->pmu_type; 1216 1062 } 1217 1063 1218 - static const char * const arm_spe_info_fmts[] = { 1219 - [ARM_SPE_PMU_TYPE] = " PMU Type %"PRId64"\n", 1064 + static const char * const metadata_hdr_v1_fmts[] = { 1065 + [ARM_SPE_PMU_TYPE] = " PMU Type :%"PRId64"\n", 1066 + [ARM_SPE_PER_CPU_MMAPS] = " Per CPU mmaps :%"PRId64"\n", 1220 1067 }; 1221 1068 1222 - static void arm_spe_print_info(__u64 *arr) 1069 + static const char * const metadata_hdr_fmts[] = { 1070 + [ARM_SPE_HEADER_VERSION] = " Header version :%"PRId64"\n", 1071 + [ARM_SPE_HEADER_SIZE] = " Header size :%"PRId64"\n", 1072 + [ARM_SPE_PMU_TYPE_V2] = " PMU type v2 :%"PRId64"\n", 1073 + [ARM_SPE_CPUS_NUM] = " CPU number :%"PRId64"\n", 1074 + }; 1075 + 1076 + static const char * const metadata_per_cpu_fmts[] = { 1077 + [ARM_SPE_MAGIC] = " Magic :0x%"PRIx64"\n", 1078 + [ARM_SPE_CPU] = " CPU # :%"PRId64"\n", 1079 + [ARM_SPE_CPU_NR_PARAMS] = " Num of params :%"PRId64"\n", 1080 + [ARM_SPE_CPU_MIDR] = " MIDR :0x%"PRIx64"\n", 1081 + [ARM_SPE_CPU_PMU_TYPE] = " PMU Type :%"PRId64"\n", 1082 + [ARM_SPE_CAP_MIN_IVAL] = " Min Interval :%"PRId64"\n", 1083 + }; 1084 + 1085 + static void arm_spe_print_info(struct arm_spe *spe, __u64 *arr) 1223 1086 { 1087 + unsigned int i, cpu, hdr_size, cpu_num, cpu_size; 1088 + const char * const *hdr_fmts; 1089 + 1224 1090 if (!dump_trace) 1225 1091 return; 1226 1092 1227 - fprintf(stdout, arm_spe_info_fmts[ARM_SPE_PMU_TYPE], arr[ARM_SPE_PMU_TYPE]); 1093 + if (spe->metadata_ver == 1) { 1094 + cpu_num = 0; 1095 + hdr_size = ARM_SPE_AUXTRACE_V1_PRIV_MAX; 1096 + hdr_fmts = metadata_hdr_v1_fmts; 1097 + } else { 1098 + cpu_num = arr[ARM_SPE_CPUS_NUM]; 1099 + hdr_size = arr[ARM_SPE_HEADER_SIZE]; 1100 + hdr_fmts = metadata_hdr_fmts; 1101 + } 1102 + 1103 + for (i = 0; i < hdr_size; i++) 1104 + fprintf(stdout, hdr_fmts[i], arr[i]); 1105 + 1106 + arr += hdr_size; 1107 + for (cpu = 0; cpu < cpu_num; cpu++) { 1108 + /* 1109 + * The parameters from ARM_SPE_MAGIC to ARM_SPE_CPU_NR_PARAMS 1110 + * are fixed. The sequential parameter size is decided by the 1111 + * field 'ARM_SPE_CPU_NR_PARAMS'. 1112 + */ 1113 + cpu_size = (ARM_SPE_CPU_NR_PARAMS + 1) + arr[ARM_SPE_CPU_NR_PARAMS]; 1114 + for (i = 0; i < cpu_size; i++) 1115 + fprintf(stdout, metadata_per_cpu_fmts[i], arr[i]); 1116 + arr += cpu_size; 1117 + } 1228 1118 } 1229 1119 1230 1120 static void arm_spe_set_event_name(struct evlist *evlist, u64 id, ··· 1400 1202 if (spe->synth_opts.branches) { 1401 1203 spe->sample_branch = true; 1402 1204 1403 - /* Branch miss */ 1205 + /* Branch */ 1404 1206 err = perf_session__deliver_synth_attr_event(session, &attr, id); 1405 1207 if (err) 1406 1208 return err; 1407 - spe->branch_miss_id = id; 1408 - arm_spe_set_event_name(evlist, id, "branch-miss"); 1209 + spe->branch_id = id; 1210 + arm_spe_set_event_name(evlist, id, "branch"); 1409 1211 id += 1; 1410 1212 } 1411 1213 ··· 1456 1258 return 0; 1457 1259 } 1458 1260 1261 + static bool arm_spe__is_homogeneous(u64 **metadata, int nr_cpu) 1262 + { 1263 + u64 midr; 1264 + int i; 1265 + 1266 + if (!nr_cpu) 1267 + return false; 1268 + 1269 + for (i = 0; i < nr_cpu; i++) { 1270 + if (!metadata[i]) 1271 + return false; 1272 + 1273 + if (i == 0) { 1274 + midr = metadata[i][ARM_SPE_CPU_MIDR]; 1275 + continue; 1276 + } 1277 + 1278 + if (midr != metadata[i][ARM_SPE_CPU_MIDR]) 1279 + return false; 1280 + } 1281 + 1282 + return true; 1283 + } 1284 + 1459 1285 int arm_spe_process_auxtrace_info(union perf_event *event, 1460 1286 struct perf_session *session) 1461 1287 { 1462 1288 struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; 1463 - size_t min_sz = sizeof(u64) * ARM_SPE_AUXTRACE_PRIV_MAX; 1289 + size_t min_sz = ARM_SPE_AUXTRACE_V1_PRIV_SIZE; 1464 1290 struct perf_record_time_conv *tc = &session->time_conv; 1465 - const char *cpuid = perf_env__cpuid(session->evlist->env); 1466 - u64 midr = strtol(cpuid, NULL, 16); 1467 1291 struct arm_spe *spe; 1468 - int err; 1292 + u64 **metadata = NULL; 1293 + u64 metadata_ver; 1294 + int nr_cpu, err; 1469 1295 1470 1296 if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) + 1471 1297 min_sz) 1472 1298 return -EINVAL; 1473 1299 1300 + metadata = arm_spe__alloc_metadata(auxtrace_info, &metadata_ver, 1301 + &nr_cpu); 1302 + if (!metadata && metadata_ver != 1) { 1303 + pr_err("Failed to parse Arm SPE metadata.\n"); 1304 + return -EINVAL; 1305 + } 1306 + 1474 1307 spe = zalloc(sizeof(struct arm_spe)); 1475 - if (!spe) 1476 - return -ENOMEM; 1308 + if (!spe) { 1309 + err = -ENOMEM; 1310 + goto err_free_metadata; 1311 + } 1477 1312 1478 1313 err = auxtrace_queues__init(&spe->queues); 1479 1314 if (err) ··· 1515 1284 spe->session = session; 1516 1285 spe->machine = &session->machines.host; /* No kvm support */ 1517 1286 spe->auxtrace_type = auxtrace_info->type; 1518 - spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE]; 1519 - spe->midr = midr; 1287 + if (metadata_ver == 1) 1288 + spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE]; 1289 + else 1290 + spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE_V2]; 1291 + spe->metadata = metadata; 1292 + spe->metadata_ver = metadata_ver; 1293 + spe->metadata_nr_cpu = nr_cpu; 1294 + spe->is_homogeneous = arm_spe__is_homogeneous(metadata, nr_cpu); 1520 1295 1521 1296 spe->timeless_decoding = arm_spe__is_timeless_decoding(spe); 1522 1297 ··· 1555 1318 spe->auxtrace.evsel_is_auxtrace = arm_spe_evsel_is_auxtrace; 1556 1319 session->auxtrace = &spe->auxtrace; 1557 1320 1558 - arm_spe_print_info(&auxtrace_info->priv[0]); 1321 + arm_spe_print_info(spe, &auxtrace_info->priv[0]); 1559 1322 1560 1323 if (dump_trace) 1561 1324 return 0; ··· 1583 1346 session->auxtrace = NULL; 1584 1347 err_free: 1585 1348 free(spe); 1349 + err_free_metadata: 1350 + arm_spe__free_metadata(metadata, nr_cpu); 1586 1351 return err; 1587 1352 }
+37 -1
tools/perf/util/arm-spe.h
··· 12 12 enum { 13 13 ARM_SPE_PMU_TYPE, 14 14 ARM_SPE_PER_CPU_MMAPS, 15 + ARM_SPE_AUXTRACE_V1_PRIV_MAX, 16 + }; 17 + 18 + #define ARM_SPE_AUXTRACE_V1_PRIV_SIZE \ 19 + (ARM_SPE_AUXTRACE_V1_PRIV_MAX * sizeof(u64)) 20 + 21 + enum { 22 + /* 23 + * The old metadata format (defined above) does not include a 24 + * field for version number. Version 1 is reserved and starts 25 + * from version 2. 26 + */ 27 + ARM_SPE_HEADER_VERSION, 28 + /* Number of sizeof(u64) */ 29 + ARM_SPE_HEADER_SIZE, 30 + /* PMU type shared by CPUs */ 31 + ARM_SPE_PMU_TYPE_V2, 32 + /* Number of CPUs */ 33 + ARM_SPE_CPUS_NUM, 15 34 ARM_SPE_AUXTRACE_PRIV_MAX, 16 35 }; 17 36 18 - #define ARM_SPE_AUXTRACE_PRIV_SIZE (ARM_SPE_AUXTRACE_PRIV_MAX * sizeof(u64)) 37 + enum { 38 + /* Magic number */ 39 + ARM_SPE_MAGIC, 40 + /* CPU logical number in system */ 41 + ARM_SPE_CPU, 42 + /* Number of parameters */ 43 + ARM_SPE_CPU_NR_PARAMS, 44 + /* CPU MIDR */ 45 + ARM_SPE_CPU_MIDR, 46 + /* Associated PMU type */ 47 + ARM_SPE_CPU_PMU_TYPE, 48 + /* Minimal interval */ 49 + ARM_SPE_CAP_MIN_IVAL, 50 + ARM_SPE_CPU_PRIV_MAX, 51 + }; 52 + 53 + #define ARM_SPE_HEADER_CURRENT_VERSION 2 54 + 19 55 20 56 union perf_event; 21 57 struct perf_session;
+1 -2
tools/perf/util/auxtrace.h
··· 75 75 * (not fully accurate, since CYC packets are only emitted 76 76 * together with other events, such as branches) 77 77 * @branches: whether to synthesize 'branches' events 78 - * (branch misses only for Arm SPE) 79 78 * @transactions: whether to synthesize events for transactions 80 79 * @ptwrites: whether to synthesize events for ptwrites 81 80 * @pwr_events: whether to synthesize power events ··· 649 650 #define ITRACE_HELP \ 650 651 " i[period]: synthesize instructions events\n" \ 651 652 " y[period]: synthesize cycles events (same period as i)\n" \ 652 - " b: synthesize branches events (branch misses for Arm SPE)\n" \ 653 + " b: synthesize branches events\n" \ 653 654 " c: synthesize branches events (calls only)\n" \ 654 655 " r: synthesize branches events (returns only)\n" \ 655 656 " x: synthesize transactions events\n" \
+1 -1
tools/perf/util/bpf-filter.c
··· 375 375 pfi = zalloc(sizeof(*pfi)); 376 376 if (pfi == NULL) { 377 377 pr_err("Cannot save pinned filter index\n"); 378 - goto err; 378 + return -ENOMEM; 379 379 } 380 380 381 381 pfi->evsel = evsel;
-37
tools/perf/util/bpf-prologue.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * Copyright (C) 2015, He Kuang <hekuang@huawei.com> 4 - * Copyright (C) 2015, Huawei Inc. 5 - */ 6 - #ifndef __BPF_PROLOGUE_H 7 - #define __BPF_PROLOGUE_H 8 - 9 - struct probe_trace_arg; 10 - struct bpf_insn; 11 - 12 - #define BPF_PROLOGUE_MAX_ARGS 3 13 - #define BPF_PROLOGUE_START_ARG_REG BPF_REG_3 14 - #define BPF_PROLOGUE_FETCH_RESULT_REG BPF_REG_2 15 - 16 - #ifdef HAVE_BPF_PROLOGUE 17 - int bpf__gen_prologue(struct probe_trace_arg *args, int nargs, 18 - struct bpf_insn *new_prog, size_t *new_cnt, 19 - size_t cnt_space); 20 - #else 21 - #include <linux/compiler.h> 22 - #include <errno.h> 23 - 24 - static inline int 25 - bpf__gen_prologue(struct probe_trace_arg *args __maybe_unused, 26 - int nargs __maybe_unused, 27 - struct bpf_insn *new_prog __maybe_unused, 28 - size_t *new_cnt, 29 - size_t cnt_space __maybe_unused) 30 - { 31 - if (!new_cnt) 32 - return -EINVAL; 33 - *new_cnt = 0; 34 - return -ENOTSUP; 35 - } 36 - #endif 37 - #endif /* __BPF_PROLOGUE_H */
+28 -7
tools/perf/util/bpf_counter.c
··· 394 394 } 395 395 396 396 static struct perf_cpu_map *all_cpu_map; 397 + static __u32 filter_entry_cnt; 397 398 398 399 static int bperf_reload_leader_program(struct evsel *evsel, int attr_map_fd, 399 400 struct perf_event_attr_map_entry *entry) ··· 445 444 return err; 446 445 } 447 446 447 + static int bperf_attach_follower_program(struct bperf_follower_bpf *skel, 448 + enum bperf_filter_type filter_type, 449 + bool inherit) 450 + { 451 + struct bpf_link *link; 452 + int err = 0; 453 + 454 + if ((filter_type == BPERF_FILTER_PID || 455 + filter_type == BPERF_FILTER_TGID) && inherit) 456 + /* attach all follower bpf progs to enable event inheritance */ 457 + err = bperf_follower_bpf__attach(skel); 458 + else { 459 + link = bpf_program__attach(skel->progs.fexit_XXX); 460 + if (IS_ERR(link)) 461 + err = PTR_ERR(link); 462 + } 463 + 464 + return err; 465 + } 466 + 448 467 static int bperf__load(struct evsel *evsel, struct target *target) 449 468 { 450 469 struct perf_event_attr_map_entry entry = {0xffffffff, 0xffffffff}; 451 470 int attr_map_fd, diff_map_fd = -1, err; 452 471 enum bperf_filter_type filter_type; 453 - __u32 filter_entry_cnt, i; 472 + __u32 i; 454 473 455 474 if (bperf_check_target(evsel, target, &filter_type, &filter_entry_cnt)) 456 475 return -1; ··· 550 529 /* set up reading map */ 551 530 bpf_map__set_max_entries(evsel->follower_skel->maps.accum_readings, 552 531 filter_entry_cnt); 553 - /* set up follower filter based on target */ 554 - bpf_map__set_max_entries(evsel->follower_skel->maps.filter, 555 - filter_entry_cnt); 556 532 err = bperf_follower_bpf__load(evsel->follower_skel); 557 533 if (err) { 558 534 pr_err("Failed to load follower skeleton\n"); ··· 561 543 for (i = 0; i < filter_entry_cnt; i++) { 562 544 int filter_map_fd; 563 545 __u32 key; 546 + struct bperf_filter_value fval = { i, 0 }; 564 547 565 548 if (filter_type == BPERF_FILTER_PID || 566 549 filter_type == BPERF_FILTER_TGID) ··· 572 553 break; 573 554 574 555 filter_map_fd = bpf_map__fd(evsel->follower_skel->maps.filter); 575 - bpf_map_update_elem(filter_map_fd, &key, &i, BPF_ANY); 556 + bpf_map_update_elem(filter_map_fd, &key, &fval, BPF_ANY); 576 557 } 577 558 578 559 evsel->follower_skel->bss->type = filter_type; 560 + evsel->follower_skel->bss->inherit = target->inherit; 579 561 580 - err = bperf_follower_bpf__attach(evsel->follower_skel); 562 + err = bperf_attach_follower_program(evsel->follower_skel, filter_type, 563 + target->inherit); 581 564 582 565 out: 583 566 if (err && evsel->bperf_leader_link_fd >= 0) ··· 644 623 bperf_sync_counters(evsel); 645 624 reading_map_fd = bpf_map__fd(skel->maps.accum_readings); 646 625 647 - for (i = 0; i < bpf_map__max_entries(skel->maps.accum_readings); i++) { 626 + for (i = 0; i < filter_entry_cnt; i++) { 648 627 struct perf_cpu entry; 649 628 __u32 cpu; 650 629
+91 -7
tools/perf/util/bpf_skel/bperf_follower.bpf.c
··· 5 5 #include <bpf/bpf_tracing.h> 6 6 #include "bperf_u.h" 7 7 8 + #define MAX_ENTRIES 102400 9 + 8 10 struct { 9 11 __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 10 12 __uint(key_size, sizeof(__u32)); ··· 24 22 struct { 25 23 __uint(type, BPF_MAP_TYPE_HASH); 26 24 __uint(key_size, sizeof(__u32)); 27 - __uint(value_size, sizeof(__u32)); 25 + __uint(value_size, sizeof(struct bperf_filter_value)); 26 + __uint(max_entries, MAX_ENTRIES); 27 + __uint(map_flags, BPF_F_NO_PREALLOC); 28 28 } filter SEC(".maps"); 29 29 30 30 enum bperf_filter_type type = 0; 31 31 int enabled = 0; 32 + int inherit; 32 33 33 34 SEC("fexit/XXX") 34 35 int BPF_PROG(fexit_XXX) 35 36 { 36 37 struct bpf_perf_event_value *diff_val, *accum_val; 37 38 __u32 filter_key, zero = 0; 38 - __u32 *accum_key; 39 + __u32 accum_key; 40 + struct bperf_filter_value *fval; 39 41 40 42 if (!enabled) 41 43 return 0; 42 44 43 45 switch (type) { 44 46 case BPERF_FILTER_GLOBAL: 45 - accum_key = &zero; 47 + accum_key = zero; 46 48 goto do_add; 47 49 case BPERF_FILTER_CPU: 48 50 filter_key = bpf_get_smp_processor_id(); ··· 55 49 filter_key = bpf_get_current_pid_tgid() & 0xffffffff; 56 50 break; 57 51 case BPERF_FILTER_TGID: 58 - filter_key = bpf_get_current_pid_tgid() >> 32; 52 + /* Use pid as the filter_key to exclude new task counts 53 + * when inherit is disabled. Don't worry about the existing 54 + * children in TGID losing their counts, bpf_counter has 55 + * already added them to the filter map via perf_thread_map 56 + * before this bpf prog runs. 57 + */ 58 + filter_key = inherit ? 59 + bpf_get_current_pid_tgid() >> 32 : 60 + bpf_get_current_pid_tgid() & 0xffffffff; 59 61 break; 60 62 default: 61 63 return 0; 62 64 } 63 65 64 - accum_key = bpf_map_lookup_elem(&filter, &filter_key); 65 - if (!accum_key) 66 + fval = bpf_map_lookup_elem(&filter, &filter_key); 67 + if (!fval) 66 68 return 0; 69 + 70 + accum_key = fval->accum_key; 71 + if (fval->exited) 72 + bpf_map_delete_elem(&filter, &filter_key); 67 73 68 74 do_add: 69 75 diff_val = bpf_map_lookup_elem(&diff_readings, &zero); 70 76 if (!diff_val) 71 77 return 0; 72 78 73 - accum_val = bpf_map_lookup_elem(&accum_readings, accum_key); 79 + accum_val = bpf_map_lookup_elem(&accum_readings, &accum_key); 74 80 if (!accum_val) 75 81 return 0; 76 82 77 83 accum_val->counter += diff_val->counter; 78 84 accum_val->enabled += diff_val->enabled; 79 85 accum_val->running += diff_val->running; 86 + 87 + return 0; 88 + } 89 + 90 + /* The program is only used for PID or TGID filter types. */ 91 + SEC("tp_btf/task_newtask") 92 + int BPF_PROG(on_newtask, struct task_struct *task, __u64 clone_flags) 93 + { 94 + __u32 parent_key, child_key; 95 + struct bperf_filter_value *parent_fval; 96 + struct bperf_filter_value child_fval = { 0 }; 97 + 98 + if (!enabled) 99 + return 0; 100 + 101 + switch (type) { 102 + case BPERF_FILTER_PID: 103 + parent_key = bpf_get_current_pid_tgid() & 0xffffffff; 104 + child_key = task->pid; 105 + break; 106 + case BPERF_FILTER_TGID: 107 + parent_key = bpf_get_current_pid_tgid() >> 32; 108 + child_key = task->tgid; 109 + if (child_key == parent_key) 110 + return 0; 111 + break; 112 + default: 113 + return 0; 114 + } 115 + 116 + /* Check if the current task is one of the target tasks to be counted */ 117 + parent_fval = bpf_map_lookup_elem(&filter, &parent_key); 118 + if (!parent_fval) 119 + return 0; 120 + 121 + /* Start counting for the new task by adding it into filter map, 122 + * inherit the accum key of its parent task so that they can be 123 + * counted together. 124 + */ 125 + child_fval.accum_key = parent_fval->accum_key; 126 + child_fval.exited = 0; 127 + bpf_map_update_elem(&filter, &child_key, &child_fval, BPF_NOEXIST); 128 + 129 + return 0; 130 + } 131 + 132 + /* The program is only used for PID or TGID filter types. */ 133 + SEC("tp_btf/sched_process_exit") 134 + int BPF_PROG(on_exittask, struct task_struct *task) 135 + { 136 + __u32 pid; 137 + struct bperf_filter_value *fval; 138 + 139 + if (!enabled) 140 + return 0; 141 + 142 + /* Stop counting for this task by removing it from filter map. 143 + * For TGID type, if the pid can be found in the map, it means that 144 + * this pid belongs to the leader task. After the task exits, the 145 + * tgid of its child tasks (if any) will be 1, so the pid can be 146 + * safely removed. 147 + */ 148 + pid = task->pid; 149 + fval = bpf_map_lookup_elem(&filter, &pid); 150 + if (fval) 151 + fval->exited = 1; 80 152 81 153 return 0; 82 154 }
+5
tools/perf/util/bpf_skel/bperf_u.h
··· 11 11 BPERF_FILTER_TGID, 12 12 }; 13 13 14 + struct bperf_filter_value { 15 + __u32 accum_key; 16 + __u8 exited; 17 + }; 18 + 14 19 #endif /* __BPERF_STAT_U_H */
-28
tools/perf/util/color.c
··· 93 93 return r; 94 94 } 95 95 96 - /* 97 - * This function splits the buffer by newlines and colors the lines individually. 98 - * 99 - * Returns 0 on success. 100 - */ 101 - int color_fwrite_lines(FILE *fp, const char *color, 102 - size_t count, const char *buf) 103 - { 104 - if (!*color) 105 - return fwrite(buf, count, 1, fp) != 1; 106 - 107 - while (count) { 108 - char *p = memchr(buf, '\n', count); 109 - 110 - if (p != buf && (fputs(color, fp) < 0 || 111 - fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 || 112 - fputs(PERF_COLOR_RESET, fp) < 0)) 113 - return -1; 114 - if (!p) 115 - return 0; 116 - if (fputc('\n', fp) < 0) 117 - return -1; 118 - count -= p + 1 - buf; 119 - buf = p + 1; 120 - } 121 - return 0; 122 - } 123 - 124 96 const char *get_percent_color(double percent) 125 97 { 126 98 const char *color = PERF_COLOR_NORMAL;
+6 -5
tools/perf/util/color.h
··· 2 2 #ifndef __PERF_COLOR_H 3 3 #define __PERF_COLOR_H 4 4 5 + #include <linux/compiler.h> 5 6 #include <stdio.h> 6 7 #include <stdarg.h> 7 8 ··· 23 22 #define MIN_GREEN 0.5 24 23 #define MIN_RED 5.0 25 24 25 + #define PERF_COLOR_DELETE_LINE "\033[A\33[2K\r" 26 26 /* 27 27 * This variable stores the value of color.ui 28 28 */ ··· 39 37 int color_vsnprintf(char *bf, size_t size, const char *color, 40 38 const char *fmt, va_list args); 41 39 int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args); 42 - int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); 43 - int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); 44 - int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 40 + int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) __printf(3, 4); 41 + int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...) __printf(4, 5); 45 42 int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); 46 - int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); 47 - int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...); 43 + int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) __printf(3, 4); 44 + int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...) __printf(3, 4); 48 45 int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 49 46 const char *get_percent_color(double percent); 50 47
+22
tools/perf/util/config.c
··· 912 912 struct perf_config_scan_data { 913 913 const char *name; 914 914 const char *fmt; 915 + const char *value; 915 916 va_list args; 916 917 int ret; 917 918 }; ··· 939 938 va_end(d.args); 940 939 941 940 return d.ret; 941 + } 942 + 943 + static int perf_config_get_cb(const char *var, const char *value, void *data) 944 + { 945 + struct perf_config_scan_data *d = data; 946 + 947 + if (!strcmp(var, d->name)) 948 + d->value = value; 949 + 950 + return 0; 951 + } 952 + 953 + const char *perf_config_get(const char *name) 954 + { 955 + struct perf_config_scan_data d = { 956 + .name = name, 957 + .value = NULL, 958 + }; 959 + 960 + perf_config(perf_config_get_cb, &d); 961 + return d.value; 942 962 }
+1
tools/perf/util/config.h
··· 30 30 int perf_default_config(const char *, const char *, void *); 31 31 int perf_config(config_fn_t fn, void *); 32 32 int perf_config_scan(const char *name, const char *fmt, ...) __scanf(2, 3); 33 + const char *perf_config_get(const char *name); 33 34 int perf_config_set(struct perf_config_set *set, 34 35 config_fn_t fn, void *data); 35 36 int perf_config_int(int *dest, const char *, const char *);
+6 -1
tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
··· 685 685 } 686 686 687 687 if (d_params->operation == CS_ETM_OPERATION_DECODE) { 688 + int decode_flags = OCSD_CREATE_FLG_FULL_DECODER; 689 + #ifdef OCSD_OPFLG_N_UNCOND_DIR_BR_CHK 690 + decode_flags |= OCSD_OPFLG_N_UNCOND_DIR_BR_CHK | OCSD_OPFLG_CHK_RANGE_CONTINUE | 691 + ETM4_OPFLG_PKTDEC_AA64_OPCODE_CHK; 692 + #endif 688 693 if (ocsd_dt_create_decoder(decoder->dcd_tree, 689 694 decoder->decoder_name, 690 - OCSD_CREATE_FLG_FULL_DECODER, 695 + decode_flags, 691 696 trace_config, &csid)) 692 697 return -1; 693 698
+18 -7
tools/perf/util/cs-etm.c
··· 2490 2490 2491 2491 /* Ignore return value */ 2492 2492 cs_etm__process_traceid_queue(etmq, tidq); 2493 - 2494 - /* 2495 - * Generate an instruction sample with the remaining 2496 - * branchstack entries. 2497 - */ 2498 - cs_etm__flush(etmq, tidq); 2499 2493 } 2500 2494 } 2501 2495 ··· 2632 2638 2633 2639 while (1) { 2634 2640 if (!etm->heap.heap_cnt) 2635 - goto out; 2641 + break; 2636 2642 2637 2643 /* Take the entry at the top of the min heap */ 2638 2644 cs_queue_nr = etm->heap.heap_array[0].queue_nr; ··· 2715 2721 ret = auxtrace_heap__add(&etm->heap, cs_queue_nr, cs_timestamp); 2716 2722 } 2717 2723 2724 + for (i = 0; i < etm->queues.nr_queues; i++) { 2725 + struct int_node *inode; 2726 + 2727 + etmq = etm->queues.queue_array[i].priv; 2728 + if (!etmq) 2729 + continue; 2730 + 2731 + intlist__for_each_entry(inode, etmq->traceid_queues_list) { 2732 + int idx = (int)(intptr_t)inode->priv; 2733 + 2734 + /* Flush any remaining branch stack entries */ 2735 + tidq = etmq->traceid_queues[idx]; 2736 + ret = cs_etm__end_block(etmq, tidq); 2737 + if (ret) 2738 + return ret; 2739 + } 2740 + } 2718 2741 out: 2719 2742 return ret; 2720 2743 }
+1 -1
tools/perf/util/data-convert-bt.c
··· 36 36 #include "util/sample.h" 37 37 38 38 #ifdef HAVE_LIBTRACEEVENT 39 - #include <traceevent/event-parse.h> 39 + #include <event-parse.h> 40 40 #endif 41 41 42 42 #define pr_N(n, fmt, ...) \
+1 -1
tools/perf/util/data-convert-json.c
··· 28 28 #include "util/tool.h" 29 29 30 30 #ifdef HAVE_LIBTRACEEVENT 31 - #include <traceevent/event-parse.h> 31 + #include <event-parse.h> 32 32 #endif 33 33 34 34 struct convert_json {
+1 -1
tools/perf/util/debug.c
··· 27 27 #include <linux/ctype.h> 28 28 29 29 #ifdef HAVE_LIBTRACEEVENT 30 - #include <traceevent/event-parse.h> 30 + #include <event-parse.h> 31 31 #else 32 32 #define LIBTRACEEVENT_VERSION 0 33 33 #endif
+3 -3
tools/perf/util/debuginfo.h
··· 5 5 #include <errno.h> 6 6 #include <linux/compiler.h> 7 7 8 - #ifdef HAVE_DWARF_SUPPORT 8 + #ifdef HAVE_LIBDW_SUPPORT 9 9 10 10 #include "dwarf-aux.h" 11 11 ··· 25 25 int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, 26 26 bool adjust_offset); 27 27 28 - #else /* HAVE_DWARF_SUPPORT */ 28 + #else /* HAVE_LIBDW_SUPPORT */ 29 29 30 30 /* dummy debug information structure */ 31 31 struct debuginfo { ··· 49 49 return -EINVAL; 50 50 } 51 51 52 - #endif /* HAVE_DWARF_SUPPORT */ 52 + #endif /* HAVE_LIBDW_SUPPORT */ 53 53 54 54 #ifdef HAVE_DEBUGINFOD_SUPPORT 55 55 int get_source_from_debuginfod(const char *raw_path, const char *sbuild_id,
+195 -103
tools/perf/util/disasm.c
··· 18 18 #include "disasm.h" 19 19 #include "disasm_bpf.h" 20 20 #include "dso.h" 21 + #include "dwarf-regs.h" 21 22 #include "env.h" 22 23 #include "evsel.h" 23 24 #include "map.h" ··· 152 151 .memory_ref_char = '(', 153 152 .imm_char = '$', 154 153 }, 155 - #ifdef HAVE_DWARF_SUPPORT 154 + #ifdef HAVE_LIBDW_SUPPORT 156 155 .update_insn_state = update_insn_state_x86, 157 156 #endif 158 157 }, 159 158 { 160 159 .name = "powerpc", 161 160 .init = powerpc__annotate_init, 162 - #ifdef HAVE_DWARF_SUPPORT 161 + #ifdef HAVE_LIBDW_SUPPORT 163 162 .update_insn_state = update_insn_state_powerpc, 164 163 #endif 165 164 }, ··· 1424 1423 } 1425 1424 #endif 1426 1425 1426 + #if !defined(HAVE_LIBCAPSTONE_SUPPORT) || !defined(HAVE_LIBLLVM_SUPPORT) 1427 + static void symbol__disassembler_missing(const char *disassembler, const char *filename, 1428 + struct symbol *sym) 1429 + { 1430 + pr_debug("The %s disassembler isn't linked in for %s in %s\n", 1431 + disassembler, sym->name, filename); 1432 + } 1433 + #endif 1434 + 1427 1435 #ifdef HAVE_LIBCAPSTONE_SUPPORT 1428 1436 static void print_capstone_detail(cs_insn *insn, char *buf, size_t len, 1429 1437 struct annotate_args *args, u64 addr) ··· 1583 1573 1584 1574 dl = disasm_line__new(args); 1585 1575 if (dl == NULL) 1586 - goto err; 1576 + break; 1587 1577 1588 1578 annotation_line__add(&dl->al, &notes->src->source); 1589 1579 ··· 1613 1603 err: 1614 1604 if (fd >= 0) 1615 1605 close(fd); 1616 - if (needs_cs_close) { 1617 - struct disasm_line *tmp; 1618 - 1619 - /* 1620 - * It probably failed in the middle of the above loop. 1621 - * Release any resources it might add. 1622 - */ 1623 - list_for_each_entry_safe(dl, tmp, &notes->src->source, al.node) { 1624 - list_del(&dl->al.node); 1625 - free(dl); 1626 - } 1627 - } 1628 1606 count = -1; 1629 1607 goto out; 1630 1608 } ··· 1625 1627 u64 start = map__rip_2objdump(map, sym->start); 1626 1628 u64 len; 1627 1629 u64 offset; 1628 - int i, count; 1630 + int i, count, free_count; 1629 1631 bool is_64bit = false; 1630 1632 bool needs_cs_close = false; 1631 1633 u8 *buf = NULL; 1632 1634 csh handle; 1633 - cs_insn *insn; 1635 + cs_insn *insn = NULL; 1634 1636 char disasm_buf[512]; 1635 1637 struct disasm_line *dl; 1636 1638 ··· 1662 1664 1663 1665 needs_cs_close = true; 1664 1666 1665 - count = cs_disasm(handle, buf, len, start, len, &insn); 1667 + free_count = count = cs_disasm(handle, buf, len, start, len, &insn); 1666 1668 for (i = 0, offset = 0; i < count; i++) { 1667 1669 int printed; 1668 1670 ··· 1700 1702 } 1701 1703 1702 1704 out: 1703 - if (needs_cs_close) 1705 + if (needs_cs_close) { 1704 1706 cs_close(&handle); 1707 + if (free_count > 0) 1708 + cs_free(insn, free_count); 1709 + } 1705 1710 free(buf); 1706 1711 return count < 0 ? count : 0; 1707 1712 ··· 1718 1717 */ 1719 1718 list_for_each_entry_safe(dl, tmp, &notes->src->source, al.node) { 1720 1719 list_del(&dl->al.node); 1721 - free(dl); 1720 + disasm_line__free(dl); 1722 1721 } 1723 1722 } 1724 1723 count = -1; 1725 1724 goto out; 1726 1725 } 1727 - #endif 1726 + #else // HAVE_LIBCAPSTONE_SUPPORT 1727 + static int symbol__disassemble_capstone(char *filename, struct symbol *sym, 1728 + struct annotate_args *args __maybe_unused) 1729 + { 1730 + symbol__disassembler_missing("capstone", filename, sym); 1731 + return -1; 1732 + } 1733 + 1734 + static int symbol__disassemble_capstone_powerpc(char *filename, struct symbol *sym, 1735 + struct annotate_args *args __maybe_unused) 1736 + { 1737 + symbol__disassembler_missing("capstone powerpc", filename, sym); 1738 + return -1; 1739 + } 1740 + #endif // HAVE_LIBCAPSTONE_SUPPORT 1728 1741 1729 1742 static int symbol__disassemble_raw(char *filename, struct symbol *sym, 1730 1743 struct annotate_args *args) ··· 1797 1782 sprintf(args->line, "%x", line[i]); 1798 1783 dl = disasm_line__new(args); 1799 1784 if (dl == NULL) 1800 - goto err; 1785 + break; 1801 1786 1802 1787 annotation_line__add(&dl->al, &notes->src->source); 1803 1788 offset += 4; ··· 2006 1991 free(line_storage); 2007 1992 return ret; 2008 1993 } 2009 - #endif 1994 + #else // HAVE_LIBLLVM_SUPPORT 1995 + static int symbol__disassemble_llvm(char *filename, struct symbol *sym, 1996 + struct annotate_args *args __maybe_unused) 1997 + { 1998 + symbol__disassembler_missing("LLVM", filename, sym); 1999 + return -1; 2000 + } 2001 + #endif // HAVE_LIBLLVM_SUPPORT 2010 2002 2011 2003 /* 2012 2004 * Possibly create a new version of line with tabs expanded. Returns the ··· 2075 2053 return new_line; 2076 2054 } 2077 2055 2078 - int symbol__disassemble(struct symbol *sym, struct annotate_args *args) 2056 + static int symbol__disassemble_objdump(const char *filename, struct symbol *sym, 2057 + struct annotate_args *args) 2079 2058 { 2080 2059 struct annotation_options *opts = &annotate_opts; 2081 2060 struct map *map = args->ms.map; 2082 2061 struct dso *dso = map__dso(map); 2083 2062 char *command; 2084 2063 FILE *file; 2085 - char symfs_filename[PATH_MAX]; 2086 - struct kcore_extract kce; 2087 - bool delete_extract = false; 2088 - bool decomp = false; 2089 2064 int lineno = 0; 2090 2065 char *fileloc = NULL; 2091 2066 int nline; ··· 2097 2078 NULL, 2098 2079 }; 2099 2080 struct child_process objdump_process; 2100 - int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename)); 2101 - 2102 - if (err) 2103 - return err; 2104 - 2105 - pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, 2106 - symfs_filename, sym->name, map__unmap_ip(map, sym->start), 2107 - map__unmap_ip(map, sym->end)); 2108 - 2109 - pr_debug("annotating [%p] %30s : [%p] %30s\n", 2110 - dso, dso__long_name(dso), sym, sym->name); 2111 - 2112 - if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) { 2113 - return symbol__disassemble_bpf(sym, args); 2114 - } else if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) { 2115 - return symbol__disassemble_bpf_image(sym, args); 2116 - } else if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) { 2117 - return -1; 2118 - } else if (dso__is_kcore(dso)) { 2119 - kce.kcore_filename = symfs_filename; 2120 - kce.addr = map__rip_2objdump(map, sym->start); 2121 - kce.offs = sym->start; 2122 - kce.len = sym->end - sym->start; 2123 - if (!kcore_extract__create(&kce)) { 2124 - delete_extract = true; 2125 - strlcpy(symfs_filename, kce.extract_filename, 2126 - sizeof(symfs_filename)); 2127 - } 2128 - } else if (dso__needs_decompress(dso)) { 2129 - char tmp[KMOD_DECOMP_LEN]; 2130 - 2131 - if (dso__decompress_kmodule_path(dso, symfs_filename, 2132 - tmp, sizeof(tmp)) < 0) 2133 - return -1; 2134 - 2135 - decomp = true; 2136 - strcpy(symfs_filename, tmp); 2137 - } 2138 - 2139 - /* 2140 - * For powerpc data type profiling, use the dso__data_read_offset 2141 - * to read raw instruction directly and interpret the binary code 2142 - * to understand instructions and register fields. For sort keys as 2143 - * type and typeoff, disassemble to mnemonic notation is 2144 - * not required in case of powerpc. 2145 - */ 2146 - if (arch__is(args->arch, "powerpc")) { 2147 - extern const char *sort_order; 2148 - 2149 - if (sort_order && !strstr(sort_order, "sym")) { 2150 - err = symbol__disassemble_raw(symfs_filename, sym, args); 2151 - if (err == 0) 2152 - goto out_remove_tmp; 2153 - #ifdef HAVE_LIBCAPSTONE_SUPPORT 2154 - err = symbol__disassemble_capstone_powerpc(symfs_filename, sym, args); 2155 - if (err == 0) 2156 - goto out_remove_tmp; 2157 - #endif 2158 - } 2159 - } 2160 - 2161 - #ifdef HAVE_LIBLLVM_SUPPORT 2162 - err = symbol__disassemble_llvm(symfs_filename, sym, args); 2163 - if (err == 0) 2164 - goto out_remove_tmp; 2165 - #endif 2166 - #ifdef HAVE_LIBCAPSTONE_SUPPORT 2167 - err = symbol__disassemble_capstone(symfs_filename, sym, args); 2168 - if (err == 0) 2169 - goto out_remove_tmp; 2170 - #endif 2081 + int err; 2171 2082 2172 2083 err = asprintf(&command, 2173 2084 "%s %s%s --start-address=0x%016" PRIx64 ··· 2120 2171 2121 2172 if (err < 0) { 2122 2173 pr_err("Failure allocating memory for the command to run\n"); 2123 - goto out_remove_tmp; 2174 + return err; 2124 2175 } 2125 2176 2126 2177 pr_debug("Executing: %s\n", command); 2127 2178 2128 2179 objdump_argv[2] = command; 2129 - objdump_argv[4] = symfs_filename; 2180 + objdump_argv[4] = filename; 2130 2181 2131 2182 /* Create a pipe to read from for stdout */ 2132 2183 memset(&objdump_process, 0, sizeof(objdump_process)); ··· 2164 2215 break; 2165 2216 2166 2217 /* Skip lines containing "filename:" */ 2167 - match = strstr(line, symfs_filename); 2168 - if (match && match[strlen(symfs_filename)] == ':') 2218 + match = strstr(line, filename); 2219 + if (match && match[strlen(filename)] == ':') 2169 2220 continue; 2170 2221 2171 2222 expanded_line = strim(line); ··· 2210 2261 2211 2262 out_free_command: 2212 2263 free(command); 2264 + return err; 2265 + } 2213 2266 2267 + static int annotation_options__init_disassemblers(struct annotation_options *options) 2268 + { 2269 + char *disassembler; 2270 + 2271 + if (options->disassemblers_str == NULL) { 2272 + const char *default_disassemblers_str = 2273 + #ifdef HAVE_LIBLLVM_SUPPORT 2274 + "llvm," 2275 + #endif 2276 + #ifdef HAVE_LIBCAPSTONE_SUPPORT 2277 + "capstone," 2278 + #endif 2279 + "objdump"; 2280 + 2281 + options->disassemblers_str = strdup(default_disassemblers_str); 2282 + if (!options->disassemblers_str) 2283 + goto out_enomem; 2284 + } 2285 + 2286 + disassembler = strdup(options->disassemblers_str); 2287 + if (disassembler == NULL) 2288 + goto out_enomem; 2289 + 2290 + while (1) { 2291 + char *comma = strchr(disassembler, ','); 2292 + 2293 + if (comma != NULL) 2294 + *comma = '\0'; 2295 + 2296 + options->disassemblers[options->nr_disassemblers++] = strim(disassembler); 2297 + 2298 + if (comma == NULL) 2299 + break; 2300 + 2301 + disassembler = comma + 1; 2302 + 2303 + if (options->nr_disassemblers >= MAX_DISASSEMBLERS) { 2304 + pr_debug("annotate.disassemblers can have at most %d entries, ignoring \"%s\"\n", 2305 + MAX_DISASSEMBLERS, disassembler); 2306 + break; 2307 + } 2308 + } 2309 + 2310 + return 0; 2311 + 2312 + out_enomem: 2313 + pr_err("Not enough memory for annotate.disassemblers\n"); 2314 + return -1; 2315 + } 2316 + 2317 + int symbol__disassemble(struct symbol *sym, struct annotate_args *args) 2318 + { 2319 + struct annotation_options *options = args->options; 2320 + struct map *map = args->ms.map; 2321 + struct dso *dso = map__dso(map); 2322 + char symfs_filename[PATH_MAX]; 2323 + bool delete_extract = false; 2324 + struct kcore_extract kce; 2325 + const char *disassembler; 2326 + bool decomp = false; 2327 + int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename)); 2328 + 2329 + if (err) 2330 + return err; 2331 + 2332 + pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, 2333 + symfs_filename, sym->name, map__unmap_ip(map, sym->start), 2334 + map__unmap_ip(map, sym->end)); 2335 + 2336 + pr_debug("annotating [%p] %30s : [%p] %30s\n", dso, dso__long_name(dso), sym, sym->name); 2337 + 2338 + if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_PROG_INFO) { 2339 + return symbol__disassemble_bpf(sym, args); 2340 + } else if (dso__binary_type(dso) == DSO_BINARY_TYPE__BPF_IMAGE) { 2341 + return symbol__disassemble_bpf_image(sym, args); 2342 + } else if (dso__binary_type(dso) == DSO_BINARY_TYPE__NOT_FOUND) { 2343 + return -1; 2344 + } else if (dso__is_kcore(dso)) { 2345 + kce.addr = map__rip_2objdump(map, sym->start); 2346 + kce.kcore_filename = symfs_filename; 2347 + kce.len = sym->end - sym->start; 2348 + kce.offs = sym->start; 2349 + 2350 + if (!kcore_extract__create(&kce)) { 2351 + delete_extract = true; 2352 + strlcpy(symfs_filename, kce.extract_filename, sizeof(symfs_filename)); 2353 + } 2354 + } else if (dso__needs_decompress(dso)) { 2355 + char tmp[KMOD_DECOMP_LEN]; 2356 + 2357 + if (dso__decompress_kmodule_path(dso, symfs_filename, tmp, sizeof(tmp)) < 0) 2358 + return -1; 2359 + 2360 + decomp = true; 2361 + strcpy(symfs_filename, tmp); 2362 + } 2363 + 2364 + /* 2365 + * For powerpc data type profiling, use the dso__data_read_offset to 2366 + * read raw instruction directly and interpret the binary code to 2367 + * understand instructions and register fields. For sort keys as type 2368 + * and typeoff, disassemble to mnemonic notation is not required in 2369 + * case of powerpc. 2370 + */ 2371 + if (arch__is(args->arch, "powerpc")) { 2372 + extern const char *sort_order; 2373 + 2374 + if (sort_order && !strstr(sort_order, "sym")) { 2375 + err = symbol__disassemble_raw(symfs_filename, sym, args); 2376 + if (err == 0) 2377 + goto out_remove_tmp; 2378 + 2379 + err = symbol__disassemble_capstone_powerpc(symfs_filename, sym, args); 2380 + if (err == 0) 2381 + goto out_remove_tmp; 2382 + } 2383 + } 2384 + 2385 + err = annotation_options__init_disassemblers(options); 2386 + if (err) 2387 + goto out_remove_tmp; 2388 + 2389 + err = -1; 2390 + 2391 + for (int i = 0; i < options->nr_disassemblers && err != 0; ++i) { 2392 + disassembler = options->disassemblers[i]; 2393 + 2394 + if (!strcmp(disassembler, "llvm")) 2395 + err = symbol__disassemble_llvm(symfs_filename, sym, args); 2396 + else if (!strcmp(disassembler, "capstone")) 2397 + err = symbol__disassemble_capstone(symfs_filename, sym, args); 2398 + else if (!strcmp(disassembler, "objdump")) 2399 + err = symbol__disassemble_objdump(symfs_filename, sym, args); 2400 + else 2401 + pr_debug("Unknown disassembler %s, skipping...\n", disassembler); 2402 + } 2403 + 2404 + if (err == 0) { 2405 + pr_debug("Disassembled with %s\nannotate.disassemblers=%s\n", 2406 + disassembler, options->disassemblers_str); 2407 + } 2214 2408 out_remove_tmp: 2215 2409 if (decomp) 2216 2410 unlink(symfs_filename);
+6 -2
tools/perf/util/disasm.h
··· 4 4 5 5 #include "map_symbol.h" 6 6 7 - #ifdef HAVE_DWARF_SUPPORT 7 + #ifdef HAVE_LIBDW_SUPPORT 8 8 #include "dwarf-aux.h" 9 9 #endif 10 10 ··· 39 39 char memory_ref_char; 40 40 char imm_char; 41 41 } objdump; 42 - #ifdef HAVE_DWARF_SUPPORT 42 + #ifdef HAVE_LIBDW_SUPPORT 43 43 void (*update_insn_state)(struct type_state *state, 44 44 struct data_loc_info *dloc, Dwarf_Die *cu_die, 45 45 struct disasm_line *dl); 46 46 #endif 47 + /** @e_machine: ELF machine associated with arch. */ 48 + unsigned int e_machine; 49 + /** @e_flags: Optional ELF flags associated with arch. */ 50 + unsigned int e_flags; 47 51 }; 48 52 49 53 struct ins {
-6
tools/perf/util/dwarf-aux.c
··· 1182 1182 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); 1183 1183 } 1184 1184 1185 - #if defined(HAVE_DWARF_GETLOCATIONS_SUPPORT) || defined(HAVE_DWARF_CFI_SUPPORT) 1186 1185 static int reg_from_dwarf_op(Dwarf_Op *op) 1187 1186 { 1188 1187 switch (op->atom) { ··· 1244 1245 } 1245 1246 return true; 1246 1247 } 1247 - #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT || HAVE_DWARF_CFI_SUPPORT */ 1248 1248 1249 - #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT 1250 1249 /** 1251 1250 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE 1252 1251 * @sp_die: a subprogram DIE ··· 1694 1697 1695 1698 die_find_child(cu_die, __die_collect_global_vars_cb, (void *)var_types, &die_mem); 1696 1699 } 1697 - #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ 1698 1700 1699 - #ifdef HAVE_DWARF_CFI_SUPPORT 1700 1701 /** 1701 1702 * die_get_cfa - Get frame base information 1702 1703 * @dwarf: a Dwarf info ··· 1727 1732 } 1728 1733 return -1; 1729 1734 } 1730 - #endif /* HAVE_DWARF_CFI_SUPPORT */ 1731 1735 1732 1736 /* 1733 1737 * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
-54
tools/perf/util/dwarf-aux.h
··· 9 9 #include <elfutils/libdw.h> 10 10 #include <elfutils/libdwfl.h> 11 11 #include <elfutils/version.h> 12 - #include <errno.h> 13 12 14 13 struct strbuf; 15 14 ··· 156 157 /* Return type info where the pointer and offset point to */ 157 158 Dwarf_Die *die_deref_ptr_type(Dwarf_Die *ptr_die, int offset, Dwarf_Die *die_mem); 158 159 159 - #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT 160 - 161 160 /* Get byte offset range of given variable DIE */ 162 161 int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); 163 162 ··· 174 177 /* Save all global variables in this CU */ 175 178 void die_collect_global_vars(Dwarf_Die *cu_die, struct die_var_type **var_types); 176 179 177 - #else /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ 178 - 179 - static inline int die_get_var_range(Dwarf_Die *sp_die __maybe_unused, 180 - Dwarf_Die *vr_die __maybe_unused, 181 - struct strbuf *buf __maybe_unused) 182 - { 183 - return -ENOTSUP; 184 - } 185 - 186 - static inline Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die __maybe_unused, 187 - Dwarf_Addr pc __maybe_unused, 188 - int reg __maybe_unused, 189 - int *poffset __maybe_unused, 190 - bool is_fbreg __maybe_unused, 191 - Dwarf_Die *die_mem __maybe_unused) 192 - { 193 - return NULL; 194 - } 195 - 196 - static inline Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die __maybe_unused, 197 - Dwarf_Addr addr __maybe_unused, 198 - Dwarf_Die *die_mem __maybe_unused, 199 - int *offset __maybe_unused) 200 - { 201 - return NULL; 202 - } 203 - 204 - static inline void die_collect_vars(Dwarf_Die *sc_die __maybe_unused, 205 - struct die_var_type **var_types __maybe_unused) 206 - { 207 - } 208 - 209 - static inline void die_collect_global_vars(Dwarf_Die *cu_die __maybe_unused, 210 - struct die_var_type **var_types __maybe_unused) 211 - { 212 - } 213 - 214 - #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ 215 - 216 - #ifdef HAVE_DWARF_CFI_SUPPORT 217 - 218 180 /* Get the frame base information from CFA */ 219 181 int die_get_cfa(Dwarf *dwarf, u64 pc, int *preg, int *poffset); 220 - 221 - #else /* HAVE_DWARF_CFI_SUPPORT */ 222 - 223 - static inline int die_get_cfa(Dwarf *dwarf __maybe_unused, u64 pc __maybe_unused, 224 - int *preg __maybe_unused, int *poffset __maybe_unused) 225 - { 226 - return -1; 227 - } 228 - 229 - #endif /* HAVE_DWARF_CFI_SUPPORT */ 230 182 231 183 #endif /* _DWARF_AUX_H */
+50
tools/perf/util/dwarf-regs-csky.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd. 3 + // Mapping of DWARF debug register numbers into register names. 4 + 5 + #include <stddef.h> 6 + #include <dwarf-regs.h> 7 + 8 + #define CSKY_ABIV2_MAX_REGS 73 9 + const char *csky_dwarf_regs_table_abiv2[CSKY_ABIV2_MAX_REGS] = { 10 + /* r0 ~ r8 */ 11 + "%a0", "%a1", "%a2", "%a3", "%regs0", "%regs1", "%regs2", "%regs3", 12 + /* r9 ~ r15 */ 13 + "%regs4", "%regs5", "%regs6", "%regs7", "%regs8", "%regs9", "%sp", 14 + "%lr", 15 + /* r16 ~ r23 */ 16 + "%exregs0", "%exregs1", "%exregs2", "%exregs3", "%exregs4", 17 + "%exregs5", "%exregs6", "%exregs7", 18 + /* r24 ~ r31 */ 19 + "%exregs8", "%exregs9", "%exregs10", "%exregs11", "%exregs12", 20 + "%exregs13", "%exregs14", "%tls", 21 + "%pc", NULL, NULL, NULL, "%hi", "%lo", NULL, NULL, 22 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 23 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 24 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 25 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 26 + "%epc", 27 + }; 28 + 29 + #define CSKY_ABIV1_MAX_REGS 57 30 + const char *csky_dwarf_regs_table_abiv1[CSKY_ABIV1_MAX_REGS] = { 31 + /* r0 ~ r8 */ 32 + "%sp", "%regs9", "%a0", "%a1", "%a2", "%a3", "%regs0", "%regs1", 33 + /* r9 ~ r15 */ 34 + "%regs2", "%regs3", "%regs4", "%regs5", "%regs6", "%regs7", "%regs8", 35 + "%lr", 36 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 37 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 38 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 39 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 40 + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 41 + "%epc", 42 + }; 43 + 44 + const char *get_csky_regstr(unsigned int n, unsigned int flags) 45 + { 46 + if (flags & EF_CSKY_ABIV2) 47 + return (n < CSKY_ABIV2_MAX_REGS) ? csky_dwarf_regs_table_abiv2[n] : NULL; 48 + 49 + return (n < CSKY_ABIV1_MAX_REGS) ? csky_dwarf_regs_table_abiv1[n] : NULL; 50 + }
+61
tools/perf/util/dwarf-regs-powerpc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Mapping of DWARF debug register numbers into register names. 4 + * 5 + * Copyright (C) 2010 Ian Munsie, IBM Corporation. 6 + */ 7 + 8 + #include <dwarf-regs.h> 9 + 10 + #define PPC_OP(op) (((op) >> 26) & 0x3F) 11 + #define PPC_RA(a) (((a) >> 16) & 0x1f) 12 + #define PPC_RT(t) (((t) >> 21) & 0x1f) 13 + #define PPC_RB(b) (((b) >> 11) & 0x1f) 14 + #define PPC_D(D) ((D) & 0xfffe) 15 + #define PPC_DS(DS) ((DS) & 0xfffc) 16 + #define OP_LD 58 17 + #define OP_STD 62 18 + 19 + static int get_source_reg(u32 raw_insn) 20 + { 21 + return PPC_RA(raw_insn); 22 + } 23 + 24 + static int get_target_reg(u32 raw_insn) 25 + { 26 + return PPC_RT(raw_insn); 27 + } 28 + 29 + static int get_offset_opcode(u32 raw_insn) 30 + { 31 + int opcode = PPC_OP(raw_insn); 32 + 33 + /* DS- form */ 34 + if ((opcode == OP_LD) || (opcode == OP_STD)) 35 + return PPC_DS(raw_insn); 36 + else 37 + return PPC_D(raw_insn); 38 + } 39 + 40 + /* 41 + * Fills the required fields for op_loc depending on if it 42 + * is a source or target. 43 + * D form: ins RT,D(RA) -> src_reg1 = RA, offset = D, dst_reg1 = RT 44 + * DS form: ins RT,DS(RA) -> src_reg1 = RA, offset = DS, dst_reg1 = RT 45 + * X form: ins RT,RA,RB -> src_reg1 = RA, src_reg2 = RB, dst_reg1 = RT 46 + */ 47 + void get_powerpc_regs(u32 raw_insn, int is_source, 48 + struct annotated_op_loc *op_loc) 49 + { 50 + if (is_source) 51 + op_loc->reg1 = get_source_reg(raw_insn); 52 + else 53 + op_loc->reg1 = get_target_reg(raw_insn); 54 + 55 + if (op_loc->multi_regs) 56 + op_loc->reg2 = PPC_RB(raw_insn); 57 + 58 + /* TODO: Implement offset handling for X Form */ 59 + if ((op_loc->mem_ref) && (PPC_OP(raw_insn) != 31)) 60 + op_loc->offset = get_offset_opcode(raw_insn); 61 + }
+50
tools/perf/util/dwarf-regs-x86.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * dwarf-regs.c : Mapping of DWARF debug register numbers into register names. 4 + * Extracted from probe-finder.c 5 + * 6 + * Written by Masami Hiramatsu <mhiramat@redhat.com> 7 + */ 8 + 9 + #include <errno.h> /* for EINVAL */ 10 + #include <string.h> /* for strcmp */ 11 + #include <linux/kernel.h> /* for ARRAY_SIZE */ 12 + #include <dwarf-regs.h> 13 + 14 + struct dwarf_regs_idx { 15 + const char *name; 16 + int idx; 17 + }; 18 + 19 + static const struct dwarf_regs_idx x86_regidx_table[] = { 20 + { "rax", 0 }, { "eax", 0 }, { "ax", 0 }, { "al", 0 }, 21 + { "rdx", 1 }, { "edx", 1 }, { "dx", 1 }, { "dl", 1 }, 22 + { "rcx", 2 }, { "ecx", 2 }, { "cx", 2 }, { "cl", 2 }, 23 + { "rbx", 3 }, { "edx", 3 }, { "bx", 3 }, { "bl", 3 }, 24 + { "rsi", 4 }, { "esi", 4 }, { "si", 4 }, { "sil", 4 }, 25 + { "rdi", 5 }, { "edi", 5 }, { "di", 5 }, { "dil", 5 }, 26 + { "rbp", 6 }, { "ebp", 6 }, { "bp", 6 }, { "bpl", 6 }, 27 + { "rsp", 7 }, { "esp", 7 }, { "sp", 7 }, { "spl", 7 }, 28 + { "r8", 8 }, { "r8d", 8 }, { "r8w", 8 }, { "r8b", 8 }, 29 + { "r9", 9 }, { "r9d", 9 }, { "r9w", 9 }, { "r9b", 9 }, 30 + { "r10", 10 }, { "r10d", 10 }, { "r10w", 10 }, { "r10b", 10 }, 31 + { "r11", 11 }, { "r11d", 11 }, { "r11w", 11 }, { "r11b", 11 }, 32 + { "r12", 12 }, { "r12d", 12 }, { "r12w", 12 }, { "r12b", 12 }, 33 + { "r13", 13 }, { "r13d", 13 }, { "r13w", 13 }, { "r13b", 13 }, 34 + { "r14", 14 }, { "r14d", 14 }, { "r14w", 14 }, { "r14b", 14 }, 35 + { "r15", 15 }, { "r15d", 15 }, { "r15w", 15 }, { "r15b", 15 }, 36 + { "rip", DWARF_REG_PC }, 37 + }; 38 + 39 + int get_x86_regnum(const char *name) 40 + { 41 + unsigned int i; 42 + 43 + if (*name != '%') 44 + return -EINVAL; 45 + 46 + for (i = 0; i < ARRAY_SIZE(x86_regidx_table); i++) 47 + if (!strcmp(x86_regidx_table[i].name, name + 1)) 48 + return x86_regidx_table[i].idx; 49 + return -ENOENT; 50 + }
+25 -13
tools/perf/util/dwarf-regs.c
··· 13 13 #include <errno.h> 14 14 #include <linux/kernel.h> 15 15 16 - #ifndef EM_AARCH64 17 - #define EM_AARCH64 183 /* ARM 64 bit */ 18 - #endif 19 - 20 - #ifndef EM_LOONGARCH 21 - #define EM_LOONGARCH 258 /* LoongArch */ 22 - #endif 23 - 24 16 /* Define const char * {arch}_register_tbl[] */ 25 17 #define DEFINE_DWARF_REGSTR_TABLE 26 18 #include "../arch/x86/include/dwarf-regs-table.h" ··· 20 28 #include "../arch/arm64/include/dwarf-regs-table.h" 21 29 #include "../arch/sh/include/dwarf-regs-table.h" 22 30 #include "../arch/powerpc/include/dwarf-regs-table.h" 31 + #include "../arch/riscv/include/dwarf-regs-table.h" 23 32 #include "../arch/s390/include/dwarf-regs-table.h" 24 33 #include "../arch/sparc/include/dwarf-regs-table.h" 25 34 #include "../arch/xtensa/include/dwarf-regs-table.h" ··· 30 37 #define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL) 31 38 32 39 /* Return architecture dependent register string (for kprobe-tracer) */ 33 - const char *get_dwarf_regstr(unsigned int n, unsigned int machine) 40 + const char *get_dwarf_regstr(unsigned int n, unsigned int machine, unsigned int flags) 34 41 { 42 + if (machine == EM_NONE) { 43 + /* Generic arch - use host arch */ 44 + machine = EM_HOST; 45 + } 35 46 switch (machine) { 36 - case EM_NONE: /* Generic arch - use host arch */ 37 - return get_arch_regstr(n); 38 47 case EM_386: 39 48 return __get_dwarf_regstr(x86_32_regstr_tbl, n); 40 49 case EM_X86_64: ··· 45 50 return __get_dwarf_regstr(arm_regstr_tbl, n); 46 51 case EM_AARCH64: 47 52 return __get_dwarf_regstr(aarch64_regstr_tbl, n); 53 + case EM_CSKY: 54 + return get_csky_regstr(n, flags); 48 55 case EM_SH: 49 56 return __get_dwarf_regstr(sh_regstr_tbl, n); 50 57 case EM_S390: ··· 54 57 case EM_PPC: 55 58 case EM_PPC64: 56 59 return __get_dwarf_regstr(powerpc_regstr_tbl, n); 60 + case EM_RISCV: 61 + return __get_dwarf_regstr(riscv_regstr_tbl, n); 57 62 case EM_SPARC: 58 63 case EM_SPARCV9: 59 64 return __get_dwarf_regstr(sparc_regstr_tbl, n); ··· 71 72 return NULL; 72 73 } 73 74 75 + #if EM_HOST != EM_X86_64 && EM_HOST != EM_386 74 76 __weak int get_arch_regnum(const char *name __maybe_unused) 75 77 { 76 78 return -ENOTSUP; 77 79 } 80 + #endif 78 81 79 82 /* Return DWARF register number from architecture register name */ 80 - int get_dwarf_regnum(const char *name, unsigned int machine) 83 + int get_dwarf_regnum(const char *name, unsigned int machine, unsigned int flags __maybe_unused) 81 84 { 82 85 char *regname = strdup(name); 83 86 int reg = -1; ··· 93 92 if (p) 94 93 *p = '\0'; 95 94 95 + if (machine == EM_NONE) { 96 + /* Generic arch - use host arch */ 97 + machine = EM_HOST; 98 + } 96 99 switch (machine) { 97 - case EM_NONE: /* Generic arch - use host arch */ 100 + #if EM_HOST != EM_X86_64 && EM_HOST != EM_386 101 + case EM_HOST: 98 102 reg = get_arch_regnum(regname); 103 + break; 104 + #endif 105 + case EM_X86_64: 106 + fallthrough; 107 + case EM_386: 108 + reg = get_x86_regnum(regname); 99 109 break; 100 110 default: 101 111 pr_err("ELF MACHINE %x is not supported.\n", machine);
+26 -1
tools/perf/util/env.c
··· 5 5 #include "util/header.h" 6 6 #include "linux/compiler.h" 7 7 #include <linux/ctype.h> 8 + #include <linux/string.h> 8 9 #include <linux/zalloc.h> 9 10 #include "cgroup.h" 10 11 #include <errno.h> 11 12 #include <sys/utsname.h> 12 13 #include <stdlib.h> 13 14 #include <string.h> 15 + #include "pmu.h" 14 16 #include "pmus.h" 15 17 #include "strbuf.h" 16 18 #include "trace/beauty/beauty.h" ··· 374 372 int perf_env__read_cpuid(struct perf_env *env) 375 373 { 376 374 char cpuid[128]; 377 - int err = get_cpuid(cpuid, sizeof(cpuid)); 375 + struct perf_cpu cpu = {-1}; 376 + int err = get_cpuid(cpuid, sizeof(cpuid), cpu); 378 377 379 378 if (err) 380 379 return err; ··· 641 638 *width = env->cpu_pmu_caps ? env->br_cntr_width : 642 639 env->pmu_caps->br_cntr_width; 643 640 } 641 + } 642 + 643 + bool perf_env__is_x86_amd_cpu(struct perf_env *env) 644 + { 645 + static int is_amd; /* 0: Uninitialized, 1: Yes, -1: No */ 646 + 647 + if (is_amd == 0) 648 + is_amd = env->cpuid && strstarts(env->cpuid, "AuthenticAMD") ? 1 : -1; 649 + 650 + return is_amd >= 1 ? true : false; 651 + } 652 + 653 + bool x86__is_amd_cpu(void) 654 + { 655 + struct perf_env env = { .total_mem = 0, }; 656 + bool is_amd; 657 + 658 + perf_env__cpuid(&env); 659 + is_amd = perf_env__is_x86_amd_cpu(&env); 660 + perf_env__exit(&env); 661 + 662 + return is_amd; 644 663 }
+4
tools/perf/util/env.h
··· 195 195 void perf_env__find_br_cntr_info(struct perf_env *env, 196 196 unsigned int *nr, 197 197 unsigned int *width); 198 + 199 + bool x86__is_amd_cpu(void); 200 + bool perf_env__is_x86_amd_cpu(struct perf_env *env); 201 + 198 202 #endif /* __PERF_ENV_H */
+1
tools/perf/util/event.h
··· 66 66 PERF_IP_FLAG_VMEXIT = 1ULL << 12, 67 67 PERF_IP_FLAG_INTR_DISABLE = 1ULL << 13, 68 68 PERF_IP_FLAG_INTR_TOGGLE = 1ULL << 14, 69 + PERF_IP_FLAG_BRANCH_MISS = 1ULL << 15, 69 70 }; 70 71 71 72 #define PERF_IP_FLAG_CHARS "bcrosyiABExghDt"
+19 -64
tools/perf/util/evlist.c
··· 48 48 #include <sys/mman.h> 49 49 #include <sys/prctl.h> 50 50 #include <sys/timerfd.h> 51 + #include <sys/wait.h> 51 52 52 53 #include <linux/bitops.h> 53 54 #include <linux/hash.h> ··· 319 318 return evsel; 320 319 } 321 320 #endif 322 - 323 - int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) 324 - { 325 - struct evsel *evsel, *n; 326 - LIST_HEAD(head); 327 - size_t i; 328 - 329 - for (i = 0; i < nr_attrs; i++) { 330 - evsel = evsel__new_idx(attrs + i, evlist->core.nr_entries + i); 331 - if (evsel == NULL) 332 - goto out_delete_partial_list; 333 - list_add_tail(&evsel->core.node, &head); 334 - } 335 - 336 - evlist__splice_list_tail(evlist, &head); 337 - 338 - return 0; 339 - 340 - out_delete_partial_list: 341 - __evlist__for_each_entry_safe(&head, n, evsel) 342 - evsel__delete(evsel); 343 - return -1; 344 - } 345 - 346 - int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) 347 - { 348 - size_t i; 349 - 350 - for (i = 0; i < nr_attrs; i++) 351 - event_attr_init(attrs + i); 352 - 353 - return evlist__add_attrs(evlist, attrs, nr_attrs); 354 - } 355 - 356 - __weak int arch_evlist__add_default_attrs(struct evlist *evlist, 357 - struct perf_event_attr *attrs, 358 - size_t nr_attrs) 359 - { 360 - if (!nr_attrs) 361 - return 0; 362 - 363 - return __evlist__add_default_attrs(evlist, attrs, nr_attrs); 364 - } 365 - 366 - struct evsel *evlist__find_tracepoint_by_id(struct evlist *evlist, int id) 367 - { 368 - struct evsel *evsel; 369 - 370 - evlist__for_each_entry(evlist, evsel) { 371 - if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT && 372 - (int)evsel->core.attr.config == id) 373 - return evsel; 374 - } 375 - 376 - return NULL; 377 - } 378 321 379 322 struct evsel *evlist__find_tracepoint_by_name(struct evlist *evlist, const char *name) 380 323 { ··· 1144 1199 return ret; 1145 1200 } 1146 1201 1147 - int evlist__set_tp_filter_pid(struct evlist *evlist, pid_t pid) 1148 - { 1149 - return evlist__set_tp_filter_pids(evlist, 1, &pid); 1150 - } 1151 - 1152 1202 int evlist__append_tp_filter_pids(struct evlist *evlist, size_t npids, pid_t *pids) 1153 1203 { 1154 1204 char *filter = asprintf__tp_filter_pids(npids, pids); ··· 1424 1484 int child_ready_pipe[2], go_pipe[2]; 1425 1485 char bf; 1426 1486 1487 + evlist->workload.cork_fd = -1; 1488 + 1427 1489 if (pipe(child_ready_pipe) < 0) { 1428 1490 perror("failed to create 'ready' pipe"); 1429 1491 return -1; ··· 1478 1536 * For cancelling the workload without actually running it, 1479 1537 * the parent will just close workload.cork_fd, without writing 1480 1538 * anything, i.e. read will return zero and we just exit() 1481 - * here. 1539 + * here (See evlist__cancel_workload()). 1482 1540 */ 1483 1541 if (ret != 1) { 1484 1542 if (ret == -1) ··· 1542 1600 1543 1601 int evlist__start_workload(struct evlist *evlist) 1544 1602 { 1545 - if (evlist->workload.cork_fd > 0) { 1603 + if (evlist->workload.cork_fd >= 0) { 1546 1604 char bf = 0; 1547 1605 int ret; 1548 1606 /* ··· 1553 1611 perror("unable to write to pipe"); 1554 1612 1555 1613 close(evlist->workload.cork_fd); 1614 + evlist->workload.cork_fd = -1; 1556 1615 return ret; 1557 1616 } 1558 1617 1559 1618 return 0; 1619 + } 1620 + 1621 + void evlist__cancel_workload(struct evlist *evlist) 1622 + { 1623 + int status; 1624 + 1625 + if (evlist->workload.cork_fd >= 0) { 1626 + close(evlist->workload.cork_fd); 1627 + evlist->workload.cork_fd = -1; 1628 + waitpid(evlist->workload.pid, &status, WNOHANG); 1629 + } 1560 1630 } 1561 1631 1562 1632 int evlist__parse_sample(struct evlist *evlist, union perf_event *event, struct perf_sample *sample) ··· 2573 2619 else 2574 2620 attributes = empty_attributes; 2575 2621 2576 - if (asprintf(&new_name, "%s/%s/%s", pos->pmu_name, pos->name, attributes + 1)) { 2622 + if (asprintf(&new_name, "%s/%s/%s", pos->pmu ? pos->pmu->name : "", 2623 + pos->name, attributes + 1)) { 2577 2624 free(pos->name); 2578 2625 pos->name = new_name; 2579 2626 } else {
+1 -14
tools/perf/util/evlist.h
··· 102 102 void evlist__add(struct evlist *evlist, struct evsel *entry); 103 103 void evlist__remove(struct evlist *evlist, struct evsel *evsel); 104 104 105 - int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs); 106 - 107 - int __evlist__add_default_attrs(struct evlist *evlist, 108 - struct perf_event_attr *attrs, size_t nr_attrs); 109 - 110 - int arch_evlist__add_default_attrs(struct evlist *evlist, 111 - struct perf_event_attr *attrs, 112 - size_t nr_attrs); 113 - 114 - #define evlist__add_default_attrs(evlist, array) \ 115 - arch_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) 116 - 117 105 int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs); 118 106 119 107 int evlist__add_dummy(struct evlist *evlist); ··· 132 144 __evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array)) 133 145 134 146 int evlist__set_tp_filter(struct evlist *evlist, const char *filter); 135 - int evlist__set_tp_filter_pid(struct evlist *evlist, pid_t pid); 136 147 int evlist__set_tp_filter_pids(struct evlist *evlist, size_t npids, pid_t *pids); 137 148 138 149 int evlist__append_tp_filter(struct evlist *evlist, const char *filter); ··· 139 152 int evlist__append_tp_filter_pid(struct evlist *evlist, pid_t pid); 140 153 int evlist__append_tp_filter_pids(struct evlist *evlist, size_t npids, pid_t *pids); 141 154 142 - struct evsel *evlist__find_tracepoint_by_id(struct evlist *evlist, int id); 143 155 struct evsel *evlist__find_tracepoint_by_name(struct evlist *evlist, const char *name); 144 156 145 157 int evlist__add_pollfd(struct evlist *evlist, int fd); ··· 172 186 const char *argv[], bool pipe_output, 173 187 void (*exec_error)(int signo, siginfo_t *info, void *ucontext)); 174 188 int evlist__start_workload(struct evlist *evlist); 189 + void evlist__cancel_workload(struct evlist *evlist); 175 190 176 191 struct option; 177 192
+541 -379
tools/perf/util/evsel.c
··· 5 5 * Parts came from builtin-{top,stat,record}.c, see those files for further 6 6 * copyright notes. 7 7 */ 8 + /* 9 + * Powerpc needs __SANE_USERSPACE_TYPES__ before <linux/types.h> to select 10 + * 'int-ll64.h' and avoid compile warnings when printing __u64 with %llu. 11 + */ 12 + #define __SANE_USERSPACE_TYPES__ 8 13 9 14 #include <byteswap.h> 10 15 #include <errno.h> 11 16 #include <inttypes.h> 12 17 #include <linux/bitops.h> 13 - #include <api/io.h> 14 18 #include <api/fs/fs.h> 15 19 #include <api/fs/tracing_path.h> 16 20 #include <linux/hw_breakpoint.h> ··· 24 20 #include <linux/zalloc.h> 25 21 #include <sys/ioctl.h> 26 22 #include <sys/resource.h> 23 + #include <sys/syscall.h> 27 24 #include <sys/types.h> 28 25 #include <dirent.h> 29 26 #include <stdlib.h> ··· 56 51 #include "off_cpu.h" 57 52 #include "pmu.h" 58 53 #include "pmus.h" 54 + #include "hwmon_pmu.h" 55 + #include "tool_pmu.h" 59 56 #include "rlimit.h" 60 57 #include "../perf-sys.h" 61 58 #include "util/parse-branch-options.h" ··· 71 64 #include <linux/ctype.h> 72 65 73 66 #ifdef HAVE_LIBTRACEEVENT 74 - #include <traceevent/event-parse.h> 67 + #include <event-parse.h> 75 68 #endif 76 69 77 70 struct perf_missing_features perf_missing_features; 78 71 79 72 static clockid_t clockid; 80 73 81 - static const char *const perf_tool_event__tool_names[PERF_TOOL_MAX] = { 82 - NULL, 83 - "duration_time", 84 - "user_time", 85 - "system_time", 86 - }; 87 - 88 - const char *perf_tool_event__to_str(enum perf_tool_event ev) 89 - { 90 - if (ev > PERF_TOOL_NONE && ev < PERF_TOOL_MAX) 91 - return perf_tool_event__tool_names[ev]; 92 - 93 - return NULL; 94 - } 95 - 96 - enum perf_tool_event perf_tool_event__from_str(const char *str) 97 - { 98 - int i; 99 - 100 - perf_tool_event__for_each_event(i) { 101 - if (!strcmp(str, perf_tool_event__tool_names[i])) 102 - return i; 103 - } 104 - return PERF_TOOL_NONE; 105 - } 106 - 107 - 108 74 static int evsel__no_extra_init(struct evsel *evsel __maybe_unused) 109 75 { 110 76 return 0; 111 77 } 112 78 113 - void __weak test_attr__ready(void) { } 79 + static bool test_attr__enabled(void) 80 + { 81 + static bool test_attr__enabled; 82 + static bool test_attr__enabled_tested; 83 + 84 + if (!test_attr__enabled_tested) { 85 + char *dir = getenv("PERF_TEST_ATTR"); 86 + 87 + test_attr__enabled = (dir != NULL); 88 + test_attr__enabled_tested = true; 89 + } 90 + return test_attr__enabled; 91 + } 92 + 93 + #define __WRITE_ASS(str, fmt, data) \ 94 + do { \ 95 + if (fprintf(file, #str "=%"fmt "\n", data) < 0) { \ 96 + perror("test attr - failed to write event file"); \ 97 + fclose(file); \ 98 + return -1; \ 99 + } \ 100 + } while (0) 101 + 102 + #define WRITE_ASS(field, fmt) __WRITE_ASS(field, fmt, attr->field) 103 + 104 + static int store_event(struct perf_event_attr *attr, pid_t pid, struct perf_cpu cpu, 105 + int fd, int group_fd, unsigned long flags) 106 + { 107 + FILE *file; 108 + char path[PATH_MAX]; 109 + char *dir = getenv("PERF_TEST_ATTR"); 110 + 111 + snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir, 112 + attr->type, attr->config, fd); 113 + 114 + file = fopen(path, "w+"); 115 + if (!file) { 116 + perror("test attr - failed to open event file"); 117 + return -1; 118 + } 119 + 120 + if (fprintf(file, "[event-%d-%llu-%d]\n", 121 + attr->type, attr->config, fd) < 0) { 122 + perror("test attr - failed to write event file"); 123 + fclose(file); 124 + return -1; 125 + } 126 + 127 + /* syscall arguments */ 128 + __WRITE_ASS(fd, "d", fd); 129 + __WRITE_ASS(group_fd, "d", group_fd); 130 + __WRITE_ASS(cpu, "d", cpu.cpu); 131 + __WRITE_ASS(pid, "d", pid); 132 + __WRITE_ASS(flags, "lu", flags); 133 + 134 + /* struct perf_event_attr */ 135 + WRITE_ASS(type, PRIu32); 136 + WRITE_ASS(size, PRIu32); 137 + WRITE_ASS(config, "llu"); 138 + WRITE_ASS(sample_period, "llu"); 139 + WRITE_ASS(sample_type, "llu"); 140 + WRITE_ASS(read_format, "llu"); 141 + WRITE_ASS(disabled, "d"); 142 + WRITE_ASS(inherit, "d"); 143 + WRITE_ASS(pinned, "d"); 144 + WRITE_ASS(exclusive, "d"); 145 + WRITE_ASS(exclude_user, "d"); 146 + WRITE_ASS(exclude_kernel, "d"); 147 + WRITE_ASS(exclude_hv, "d"); 148 + WRITE_ASS(exclude_idle, "d"); 149 + WRITE_ASS(mmap, "d"); 150 + WRITE_ASS(comm, "d"); 151 + WRITE_ASS(freq, "d"); 152 + WRITE_ASS(inherit_stat, "d"); 153 + WRITE_ASS(enable_on_exec, "d"); 154 + WRITE_ASS(task, "d"); 155 + WRITE_ASS(watermark, "d"); 156 + WRITE_ASS(precise_ip, "d"); 157 + WRITE_ASS(mmap_data, "d"); 158 + WRITE_ASS(sample_id_all, "d"); 159 + WRITE_ASS(exclude_host, "d"); 160 + WRITE_ASS(exclude_guest, "d"); 161 + WRITE_ASS(exclude_callchain_kernel, "d"); 162 + WRITE_ASS(exclude_callchain_user, "d"); 163 + WRITE_ASS(mmap2, "d"); 164 + WRITE_ASS(comm_exec, "d"); 165 + WRITE_ASS(context_switch, "d"); 166 + WRITE_ASS(write_backward, "d"); 167 + WRITE_ASS(namespaces, "d"); 168 + WRITE_ASS(use_clockid, "d"); 169 + WRITE_ASS(wakeup_events, PRIu32); 170 + WRITE_ASS(bp_type, PRIu32); 171 + WRITE_ASS(config1, "llu"); 172 + WRITE_ASS(config2, "llu"); 173 + WRITE_ASS(branch_sample_type, "llu"); 174 + WRITE_ASS(sample_regs_user, "llu"); 175 + WRITE_ASS(sample_stack_user, PRIu32); 176 + 177 + fclose(file); 178 + return 0; 179 + } 180 + 181 + #undef __WRITE_ASS 182 + #undef WRITE_ASS 183 + 184 + static void test_attr__open(struct perf_event_attr *attr, pid_t pid, struct perf_cpu cpu, 185 + int fd, int group_fd, unsigned long flags) 186 + { 187 + int errno_saved = errno; 188 + 189 + if ((fd != -1) && store_event(attr, pid, cpu, fd, group_fd, flags)) { 190 + pr_err("test attr FAILED"); 191 + exit(128); 192 + } 193 + 194 + errno = errno_saved; 195 + } 114 196 115 197 static void evsel__no_extra_fini(struct evsel *evsel __maybe_unused) 116 198 { ··· 392 296 evsel->metric_events = NULL; 393 297 evsel->per_pkg_mask = NULL; 394 298 evsel->collect_stat = false; 395 - evsel->pmu_name = NULL; 396 299 evsel->group_pmu_name = NULL; 397 300 evsel->skippable = false; 301 + evsel->alternate_hw_config = PERF_COUNT_HW_MAX; 398 302 } 399 303 400 304 struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx) ··· 489 393 if (evsel->group_name == NULL) 490 394 goto out_err; 491 395 } 492 - if (orig->pmu_name) { 493 - evsel->pmu_name = strdup(orig->pmu_name); 494 - if (evsel->pmu_name == NULL) 495 - goto out_err; 496 - } 497 396 if (orig->group_pmu_name) { 498 397 evsel->group_pmu_name = strdup(orig->group_pmu_name); 499 398 if (evsel->group_pmu_name == NULL) ··· 512 421 evsel->core.leader = orig->core.leader; 513 422 514 423 evsel->max_events = orig->max_events; 515 - evsel->tool_event = orig->tool_event; 516 424 free((char *)evsel->unit); 517 425 evsel->unit = strdup(orig->unit); 518 426 if (evsel->unit == NULL) ··· 534 444 535 445 if (evsel__copy_config_terms(evsel, orig) < 0) 536 446 goto out_err; 447 + 448 + evsel->alternate_hw_config = orig->alternate_hw_config; 537 449 538 450 return evsel; 539 451 ··· 640 548 { 641 549 int colon = 0, r = 0; 642 550 struct perf_event_attr *attr = &evsel->core.attr; 643 - bool exclude_guest_default = false; 644 551 645 552 #define MOD_PRINT(context, mod) do { \ 646 553 if (!attr->exclude_##context) { \ ··· 651 560 MOD_PRINT(kernel, 'k'); 652 561 MOD_PRINT(user, 'u'); 653 562 MOD_PRINT(hv, 'h'); 654 - exclude_guest_default = true; 655 563 } 656 564 657 565 if (attr->precise_ip) { 658 566 if (!colon) 659 567 colon = ++r; 660 568 r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp"); 661 - exclude_guest_default = true; 662 569 } 663 570 664 - if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) { 571 + if (attr->exclude_host || attr->exclude_guest) { 665 572 MOD_PRINT(host, 'H'); 666 573 MOD_PRINT(guest, 'G'); 667 574 } ··· 704 615 { 705 616 int r = scnprintf(bf, size, "%s", __evsel__sw_name(evsel->core.attr.config)); 706 617 return r + evsel__add_modifiers(evsel, bf + r, size - r); 707 - } 708 - 709 - static int evsel__tool_name(enum perf_tool_event ev, char *bf, size_t size) 710 - { 711 - return scnprintf(bf, size, "%s", perf_tool_event__to_str(ev)); 712 618 } 713 619 714 620 static int __evsel__bp_name(char *bf, size_t size, u64 addr, u64 type) ··· 856 772 break; 857 773 858 774 case PERF_TYPE_SOFTWARE: 859 - if (evsel__is_tool(evsel)) 860 - evsel__tool_name(evsel__tool_event(evsel), bf, sizeof(bf)); 861 - else 862 - evsel__sw_name(evsel, bf, sizeof(bf)); 775 + evsel__sw_name(evsel, bf, sizeof(bf)); 863 776 break; 864 777 865 778 case PERF_TYPE_TRACEPOINT: ··· 865 784 866 785 case PERF_TYPE_BREAKPOINT: 867 786 evsel__bp_name(evsel, bf, sizeof(bf)); 787 + break; 788 + 789 + case PERF_PMU_TYPE_TOOL: 790 + scnprintf(bf, sizeof(bf), "%s", evsel__tool_pmu_event_name(evsel)); 868 791 break; 869 792 870 793 default: ··· 896 811 return evsel->metric_id; 897 812 898 813 if (evsel__is_tool(evsel)) 899 - return perf_tool_event__to_str(evsel__tool_event(evsel)); 814 + return evsel__tool_pmu_event_name(evsel); 900 815 901 816 return "unknown"; 902 817 } ··· 947 862 { 948 863 bool function = evsel__is_function_event(evsel); 949 864 struct perf_event_attr *attr = &evsel->core.attr; 950 - const char *arch = perf_env__arch(evsel__env(evsel)); 951 865 952 866 evsel__set_sample_bit(evsel, CALLCHAIN); 953 867 ··· 977 893 978 894 if (param->record_mode == CALLCHAIN_DWARF) { 979 895 if (!function) { 896 + const char *arch = perf_env__arch(evsel__env(evsel)); 897 + 980 898 evsel__set_sample_bit(evsel, REGS_USER); 981 899 evsel__set_sample_bit(evsel, STACK_USER); 982 900 if (opts->sample_user_regs && ··· 1236 1150 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; 1237 1151 1238 1152 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; 1239 - attr->inherit = !opts->no_inherit; 1153 + attr->inherit = target__has_cpu(&opts->target) ? 0 : !opts->no_inherit; 1240 1154 attr->write_backward = opts->overwrite ? 1 : 0; 1241 1155 attr->read_format = PERF_FORMAT_LOST; 1242 1156 ··· 1258 1172 */ 1259 1173 if (leader->core.nr_members > 1) { 1260 1174 attr->read_format |= PERF_FORMAT_GROUP; 1261 - attr->inherit = 0; 1175 + } 1176 + 1177 + /* 1178 + * Inherit + SAMPLE_READ requires SAMPLE_TID in the read_format 1179 + */ 1180 + if (attr->inherit) { 1181 + evsel__set_sample_bit(evsel, TID); 1182 + evsel->core.attr.read_format |= 1183 + PERF_FORMAT_ID; 1262 1184 } 1263 1185 } 1264 1186 ··· 1588 1494 zfree(&evsel->group_name); 1589 1495 zfree(&evsel->name); 1590 1496 zfree(&evsel->filter); 1591 - zfree(&evsel->pmu_name); 1592 1497 zfree(&evsel->group_pmu_name); 1593 1498 zfree(&evsel->unit); 1594 1499 zfree(&evsel->metric_id); ··· 1596 1503 evsel->per_pkg_mask = NULL; 1597 1504 zfree(&evsel->metric_events); 1598 1505 perf_evsel__object.fini(evsel); 1599 - if (evsel__tool_event(evsel) == PERF_TOOL_SYSTEM_TIME || 1600 - evsel__tool_event(evsel) == PERF_TOOL_USER_TIME) 1506 + if (evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME || 1507 + evsel__tool_event(evsel) == TOOL_PMU__EVENT_USER_TIME) 1601 1508 xyarray__delete(evsel->start_times); 1602 1509 } 1603 1510 ··· 1777 1684 return evsel__process_group_data(leader, cpu_map_idx, thread, data); 1778 1685 } 1779 1686 1780 - static bool read_until_char(struct io *io, char e) 1687 + bool __evsel__match(const struct evsel *evsel, u32 type, u64 config) 1781 1688 { 1782 - int c; 1783 1689 1784 - do { 1785 - c = io__get_char(io); 1786 - if (c == -1) 1787 - return false; 1788 - } while (c != e); 1789 - return true; 1790 - } 1690 + u32 e_type = evsel->core.attr.type; 1691 + u64 e_config = evsel->core.attr.config; 1791 1692 1792 - static int read_stat_field(int fd, struct perf_cpu cpu, int field, __u64 *val) 1793 - { 1794 - char buf[256]; 1795 - struct io io; 1796 - int i; 1797 - 1798 - io__init(&io, fd, buf, sizeof(buf)); 1799 - 1800 - /* Skip lines to relevant CPU. */ 1801 - for (i = -1; i < cpu.cpu; i++) { 1802 - if (!read_until_char(&io, '\n')) 1803 - return -EINVAL; 1693 + if (e_type != type) { 1694 + return type == PERF_TYPE_HARDWARE && evsel->pmu && evsel->pmu->is_core && 1695 + evsel->alternate_hw_config == config; 1804 1696 } 1805 - /* Skip to "cpu". */ 1806 - if (io__get_char(&io) != 'c') return -EINVAL; 1807 - if (io__get_char(&io) != 'p') return -EINVAL; 1808 - if (io__get_char(&io) != 'u') return -EINVAL; 1809 1697 1810 - /* Skip N of cpuN. */ 1811 - if (!read_until_char(&io, ' ')) 1812 - return -EINVAL; 1698 + if ((type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE) && 1699 + perf_pmus__supports_extended_type()) 1700 + e_config &= PERF_HW_EVENT_MASK; 1813 1701 1814 - i = 1; 1815 - while (true) { 1816 - if (io__get_dec(&io, val) != ' ') 1817 - break; 1818 - if (field == i) 1819 - return 0; 1820 - i++; 1821 - } 1822 - return -EINVAL; 1823 - } 1824 - 1825 - static int read_pid_stat_field(int fd, int field, __u64 *val) 1826 - { 1827 - char buf[256]; 1828 - struct io io; 1829 - int c, i; 1830 - 1831 - io__init(&io, fd, buf, sizeof(buf)); 1832 - if (io__get_dec(&io, val) != ' ') 1833 - return -EINVAL; 1834 - if (field == 1) 1835 - return 0; 1836 - 1837 - /* Skip comm. */ 1838 - if (io__get_char(&io) != '(' || !read_until_char(&io, ')')) 1839 - return -EINVAL; 1840 - if (field == 2) 1841 - return -EINVAL; /* String can't be returned. */ 1842 - 1843 - /* Skip state */ 1844 - if (io__get_char(&io) != ' ' || io__get_char(&io) == -1) 1845 - return -EINVAL; 1846 - if (field == 3) 1847 - return -EINVAL; /* String can't be returned. */ 1848 - 1849 - /* Loop over numeric fields*/ 1850 - if (io__get_char(&io) != ' ') 1851 - return -EINVAL; 1852 - 1853 - i = 4; 1854 - while (true) { 1855 - c = io__get_dec(&io, val); 1856 - if (c == -1) 1857 - return -EINVAL; 1858 - if (c == -2) { 1859 - /* Assume a -ve was read */ 1860 - c = io__get_dec(&io, val); 1861 - *val *= -1; 1862 - } 1863 - if (c != ' ') 1864 - return -EINVAL; 1865 - if (field == i) 1866 - return 0; 1867 - i++; 1868 - } 1869 - return -EINVAL; 1870 - } 1871 - 1872 - static int evsel__read_tool(struct evsel *evsel, int cpu_map_idx, int thread) 1873 - { 1874 - __u64 *start_time, cur_time, delta_start; 1875 - int fd, err = 0; 1876 - struct perf_counts_values *count; 1877 - bool adjust = false; 1878 - 1879 - count = perf_counts(evsel->counts, cpu_map_idx, thread); 1880 - 1881 - switch (evsel__tool_event(evsel)) { 1882 - case PERF_TOOL_DURATION_TIME: 1883 - /* 1884 - * Pretend duration_time is only on the first CPU and thread, or 1885 - * else aggregation will scale duration_time by the number of 1886 - * CPUs/threads. 1887 - */ 1888 - start_time = &evsel->start_time; 1889 - if (cpu_map_idx == 0 && thread == 0) 1890 - cur_time = rdclock(); 1891 - else 1892 - cur_time = *start_time; 1893 - break; 1894 - case PERF_TOOL_USER_TIME: 1895 - case PERF_TOOL_SYSTEM_TIME: { 1896 - bool system = evsel__tool_event(evsel) == PERF_TOOL_SYSTEM_TIME; 1897 - 1898 - start_time = xyarray__entry(evsel->start_times, cpu_map_idx, thread); 1899 - fd = FD(evsel, cpu_map_idx, thread); 1900 - lseek(fd, SEEK_SET, 0); 1901 - if (evsel->pid_stat) { 1902 - /* The event exists solely on 1 CPU. */ 1903 - if (cpu_map_idx == 0) 1904 - err = read_pid_stat_field(fd, system ? 15 : 14, &cur_time); 1905 - else 1906 - cur_time = 0; 1907 - } else { 1908 - /* The event is for all threads. */ 1909 - if (thread == 0) { 1910 - struct perf_cpu cpu = perf_cpu_map__cpu(evsel->core.cpus, 1911 - cpu_map_idx); 1912 - 1913 - err = read_stat_field(fd, cpu, system ? 3 : 1, &cur_time); 1914 - } else { 1915 - cur_time = 0; 1916 - } 1917 - } 1918 - adjust = true; 1919 - break; 1920 - } 1921 - case PERF_TOOL_NONE: 1922 - case PERF_TOOL_MAX: 1923 - default: 1924 - err = -EINVAL; 1925 - } 1926 - if (err) 1927 - return err; 1928 - 1929 - delta_start = cur_time - *start_time; 1930 - if (adjust) { 1931 - __u64 ticks_per_sec = sysconf(_SC_CLK_TCK); 1932 - 1933 - delta_start *= 1000000000 / ticks_per_sec; 1934 - } 1935 - count->val = delta_start; 1936 - count->ena = count->run = delta_start; 1937 - count->lost = 0; 1938 - return 0; 1702 + return e_config == config; 1939 1703 } 1940 1704 1941 1705 int evsel__read_counter(struct evsel *evsel, int cpu_map_idx, int thread) 1942 1706 { 1943 1707 if (evsel__is_tool(evsel)) 1944 - return evsel__read_tool(evsel, cpu_map_idx, thread); 1708 + return evsel__tool_pmu_read(evsel, cpu_map_idx, thread); 1709 + 1710 + if (evsel__is_hwmon(evsel)) 1711 + return evsel__hwmon_pmu_read(evsel, cpu_map_idx, thread); 1945 1712 1946 1713 if (evsel__is_retire_lat(evsel)) 1947 1714 return evsel__read_retire_lat(evsel, cpu_map_idx, thread); ··· 1995 2042 static int __evsel__prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus, 1996 2043 struct perf_thread_map *threads) 1997 2044 { 2045 + int ret = 0; 1998 2046 int nthreads = perf_thread_map__nr(threads); 1999 2047 2000 2048 if ((perf_missing_features.write_backward && evsel->core.attr.write_backward) || ··· 2026 2072 perf_evsel__alloc_fd(&evsel->core, perf_cpu_map__nr(cpus), nthreads) < 0) 2027 2073 return -ENOMEM; 2028 2074 2029 - if ((evsel__tool_event(evsel) == PERF_TOOL_SYSTEM_TIME || 2030 - evsel__tool_event(evsel) == PERF_TOOL_USER_TIME) && 2031 - !evsel->start_times) { 2032 - evsel->start_times = xyarray__new(perf_cpu_map__nr(cpus), nthreads, sizeof(__u64)); 2033 - if (!evsel->start_times) 2034 - return -ENOMEM; 2035 - } 2075 + if (evsel__is_tool(evsel)) 2076 + ret = evsel__tool_pmu_prepare_open(evsel, cpus, nthreads); 2036 2077 2037 2078 evsel->open_flags = PERF_FLAG_FD_CLOEXEC; 2038 2079 if (evsel->cgrp) 2039 2080 evsel->open_flags |= PERF_FLAG_PID_CGROUP; 2040 2081 2041 - return 0; 2082 + return ret; 2042 2083 } 2043 2084 2044 2085 static void evsel__disable_missing_features(struct evsel *evsel) 2045 2086 { 2087 + if (perf_missing_features.inherit_sample_read && evsel->core.attr.inherit && 2088 + (evsel->core.attr.sample_type & PERF_SAMPLE_READ)) 2089 + evsel->core.attr.inherit = 0; 2046 2090 if (perf_missing_features.branch_counters) 2047 2091 evsel->core.attr.branch_sample_type &= ~PERF_SAMPLE_BRANCH_COUNTERS; 2048 2092 if (perf_missing_features.read_lost) ··· 2090 2138 return err; 2091 2139 } 2092 2140 2093 - bool evsel__detect_missing_features(struct evsel *evsel) 2141 + static bool has_attr_feature(struct perf_event_attr *attr, unsigned long flags) 2094 2142 { 2143 + int fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, /*cpu=*/-1, 2144 + /*group_fd=*/-1, flags); 2145 + close(fd); 2146 + 2147 + if (fd < 0) { 2148 + attr->exclude_kernel = 1; 2149 + 2150 + fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, /*cpu=*/-1, 2151 + /*group_fd=*/-1, flags); 2152 + close(fd); 2153 + } 2154 + 2155 + if (fd < 0) { 2156 + attr->exclude_hv = 1; 2157 + 2158 + fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, /*cpu=*/-1, 2159 + /*group_fd=*/-1, flags); 2160 + close(fd); 2161 + } 2162 + 2163 + if (fd < 0) { 2164 + attr->exclude_guest = 1; 2165 + 2166 + fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, /*cpu=*/-1, 2167 + /*group_fd=*/-1, flags); 2168 + close(fd); 2169 + } 2170 + 2171 + attr->exclude_kernel = 0; 2172 + attr->exclude_guest = 0; 2173 + attr->exclude_hv = 0; 2174 + 2175 + return fd >= 0; 2176 + } 2177 + 2178 + static void evsel__detect_missing_pmu_features(struct evsel *evsel) 2179 + { 2180 + struct perf_event_attr attr = { 2181 + .type = evsel->core.attr.type, 2182 + .config = evsel->core.attr.config, 2183 + .disabled = 1, 2184 + }; 2185 + struct perf_pmu *pmu = evsel->pmu; 2186 + int old_errno; 2187 + 2188 + old_errno = errno; 2189 + 2190 + if (pmu == NULL) 2191 + pmu = evsel->pmu = evsel__find_pmu(evsel); 2192 + 2193 + if (pmu == NULL || pmu->missing_features.checked) 2194 + goto out; 2195 + 2095 2196 /* 2096 2197 * Must probe features in the order they were added to the 2097 - * perf_event_attr interface. 2198 + * perf_event_attr interface. These are kernel core limitation but 2199 + * specific to PMUs with branch stack. So we can detect with the given 2200 + * hardware event and stop on the first one succeeded. 2098 2201 */ 2099 - if (!perf_missing_features.branch_counters && 2100 - (evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_COUNTERS)) { 2101 - perf_missing_features.branch_counters = true; 2102 - pr_debug2("switching off branch counters support\n"); 2202 + 2203 + /* Please add new feature detection here. */ 2204 + 2205 + attr.exclude_guest = 1; 2206 + if (has_attr_feature(&attr, /*flags=*/0)) 2207 + goto found; 2208 + pmu->missing_features.exclude_guest = true; 2209 + pr_debug2("switching off exclude_guest for PMU %s\n", pmu->name); 2210 + 2211 + found: 2212 + pmu->missing_features.checked = true; 2213 + out: 2214 + errno = old_errno; 2215 + } 2216 + 2217 + static void evsel__detect_missing_brstack_features(struct evsel *evsel) 2218 + { 2219 + static bool detection_done = false; 2220 + struct perf_event_attr attr = { 2221 + .type = evsel->core.attr.type, 2222 + .config = evsel->core.attr.config, 2223 + .disabled = 1, 2224 + .sample_type = PERF_SAMPLE_BRANCH_STACK, 2225 + .sample_period = 1000, 2226 + }; 2227 + int old_errno; 2228 + 2229 + if (detection_done) 2230 + return; 2231 + 2232 + old_errno = errno; 2233 + 2234 + /* 2235 + * Must probe features in the order they were added to the 2236 + * perf_event_attr interface. These are PMU specific limitation 2237 + * so we can detect with the given hardware event and stop on the 2238 + * first one succeeded. 2239 + */ 2240 + 2241 + /* Please add new feature detection here. */ 2242 + 2243 + attr.branch_sample_type = PERF_SAMPLE_BRANCH_COUNTERS; 2244 + if (has_attr_feature(&attr, /*flags=*/0)) 2245 + goto found; 2246 + perf_missing_features.branch_counters = true; 2247 + pr_debug2("switching off branch counters support\n"); 2248 + 2249 + attr.branch_sample_type = PERF_SAMPLE_BRANCH_HW_INDEX; 2250 + if (has_attr_feature(&attr, /*flags=*/0)) 2251 + goto found; 2252 + perf_missing_features.branch_hw_idx = true; 2253 + pr_debug2("switching off branch HW index support\n"); 2254 + 2255 + attr.branch_sample_type = PERF_SAMPLE_BRANCH_NO_CYCLES | PERF_SAMPLE_BRANCH_NO_FLAGS; 2256 + if (has_attr_feature(&attr, /*flags=*/0)) 2257 + goto found; 2258 + perf_missing_features.lbr_flags = true; 2259 + pr_debug2_peo("switching off branch sample type no (cycles/flags)\n"); 2260 + 2261 + found: 2262 + detection_done = true; 2263 + errno = old_errno; 2264 + } 2265 + 2266 + static bool evsel__detect_missing_features(struct evsel *evsel) 2267 + { 2268 + static bool detection_done = false; 2269 + struct perf_event_attr attr = { 2270 + .type = PERF_TYPE_SOFTWARE, 2271 + .config = PERF_COUNT_SW_TASK_CLOCK, 2272 + .disabled = 1, 2273 + }; 2274 + int old_errno; 2275 + 2276 + evsel__detect_missing_pmu_features(evsel); 2277 + 2278 + if (evsel__has_br_stack(evsel)) 2279 + evsel__detect_missing_brstack_features(evsel); 2280 + 2281 + if (detection_done) 2282 + goto check; 2283 + 2284 + old_errno = errno; 2285 + 2286 + /* 2287 + * Must probe features in the order they were added to the 2288 + * perf_event_attr interface. These are kernel core limitation 2289 + * not PMU-specific so we can detect with a software event and 2290 + * stop on the first one succeeded. 2291 + */ 2292 + 2293 + /* Please add new feature detection here. */ 2294 + 2295 + attr.inherit = true; 2296 + attr.sample_type = PERF_SAMPLE_READ; 2297 + if (has_attr_feature(&attr, /*flags=*/0)) 2298 + goto found; 2299 + perf_missing_features.inherit_sample_read = true; 2300 + pr_debug2("Using PERF_SAMPLE_READ / :S modifier is not compatible with inherit, falling back to no-inherit.\n"); 2301 + attr.inherit = false; 2302 + attr.sample_type = 0; 2303 + 2304 + attr.read_format = PERF_FORMAT_LOST; 2305 + if (has_attr_feature(&attr, /*flags=*/0)) 2306 + goto found; 2307 + perf_missing_features.read_lost = true; 2308 + pr_debug2("switching off PERF_FORMAT_LOST support\n"); 2309 + attr.read_format = 0; 2310 + 2311 + attr.sample_type = PERF_SAMPLE_WEIGHT_STRUCT; 2312 + if (has_attr_feature(&attr, /*flags=*/0)) 2313 + goto found; 2314 + perf_missing_features.weight_struct = true; 2315 + pr_debug2("switching off weight struct support\n"); 2316 + attr.sample_type = 0; 2317 + 2318 + attr.sample_type = PERF_SAMPLE_CODE_PAGE_SIZE; 2319 + if (has_attr_feature(&attr, /*flags=*/0)) 2320 + goto found; 2321 + perf_missing_features.code_page_size = true; 2322 + pr_debug2_peo("Kernel has no PERF_SAMPLE_CODE_PAGE_SIZE support\n"); 2323 + attr.sample_type = 0; 2324 + 2325 + attr.sample_type = PERF_SAMPLE_DATA_PAGE_SIZE; 2326 + if (has_attr_feature(&attr, /*flags=*/0)) 2327 + goto found; 2328 + perf_missing_features.data_page_size = true; 2329 + pr_debug2_peo("Kernel has no PERF_SAMPLE_DATA_PAGE_SIZE support\n"); 2330 + attr.sample_type = 0; 2331 + 2332 + attr.cgroup = 1; 2333 + if (has_attr_feature(&attr, /*flags=*/0)) 2334 + goto found; 2335 + perf_missing_features.cgroup = true; 2336 + pr_debug2_peo("Kernel has no cgroup sampling support\n"); 2337 + attr.cgroup = 0; 2338 + 2339 + attr.aux_output = 1; 2340 + if (has_attr_feature(&attr, /*flags=*/0)) 2341 + goto found; 2342 + perf_missing_features.aux_output = true; 2343 + pr_debug2_peo("Kernel has no attr.aux_output support\n"); 2344 + attr.aux_output = 0; 2345 + 2346 + attr.bpf_event = 1; 2347 + if (has_attr_feature(&attr, /*flags=*/0)) 2348 + goto found; 2349 + perf_missing_features.bpf = true; 2350 + pr_debug2_peo("switching off bpf_event\n"); 2351 + attr.bpf_event = 0; 2352 + 2353 + attr.ksymbol = 1; 2354 + if (has_attr_feature(&attr, /*flags=*/0)) 2355 + goto found; 2356 + perf_missing_features.ksymbol = true; 2357 + pr_debug2_peo("switching off ksymbol\n"); 2358 + attr.ksymbol = 0; 2359 + 2360 + attr.write_backward = 1; 2361 + if (has_attr_feature(&attr, /*flags=*/0)) 2362 + goto found; 2363 + perf_missing_features.write_backward = true; 2364 + pr_debug2_peo("switching off write_backward\n"); 2365 + attr.write_backward = 0; 2366 + 2367 + attr.use_clockid = 1; 2368 + attr.clockid = CLOCK_MONOTONIC; 2369 + if (has_attr_feature(&attr, /*flags=*/0)) 2370 + goto found; 2371 + perf_missing_features.clockid = true; 2372 + pr_debug2_peo("switching off clockid\n"); 2373 + attr.use_clockid = 0; 2374 + attr.clockid = 0; 2375 + 2376 + if (has_attr_feature(&attr, /*flags=*/PERF_FLAG_FD_CLOEXEC)) 2377 + goto found; 2378 + perf_missing_features.cloexec = true; 2379 + pr_debug2_peo("switching off cloexec flag\n"); 2380 + 2381 + attr.mmap2 = 1; 2382 + if (has_attr_feature(&attr, /*flags=*/0)) 2383 + goto found; 2384 + perf_missing_features.mmap2 = true; 2385 + pr_debug2_peo("switching off mmap2\n"); 2386 + attr.mmap2 = 0; 2387 + 2388 + /* set this unconditionally? */ 2389 + perf_missing_features.sample_id_all = true; 2390 + pr_debug2_peo("switching off sample_id_all\n"); 2391 + 2392 + attr.inherit = 1; 2393 + attr.read_format = PERF_FORMAT_GROUP; 2394 + if (has_attr_feature(&attr, /*flags=*/0)) 2395 + goto found; 2396 + perf_missing_features.group_read = true; 2397 + pr_debug2_peo("switching off group read\n"); 2398 + attr.inherit = 0; 2399 + attr.read_format = 0; 2400 + 2401 + found: 2402 + detection_done = true; 2403 + errno = old_errno; 2404 + 2405 + check: 2406 + if (evsel->core.attr.inherit && 2407 + (evsel->core.attr.sample_type & PERF_SAMPLE_READ) && 2408 + perf_missing_features.inherit_sample_read) 2103 2409 return true; 2104 - } else if (!perf_missing_features.read_lost && 2105 - (evsel->core.attr.read_format & PERF_FORMAT_LOST)) { 2106 - perf_missing_features.read_lost = true; 2107 - pr_debug2("switching off PERF_FORMAT_LOST support\n"); 2410 + 2411 + if ((evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_COUNTERS) && 2412 + perf_missing_features.branch_counters) 2108 2413 return true; 2109 - } else if (!perf_missing_features.weight_struct && 2110 - (evsel->core.attr.sample_type & PERF_SAMPLE_WEIGHT_STRUCT)) { 2111 - perf_missing_features.weight_struct = true; 2112 - pr_debug2("switching off weight struct support\n"); 2414 + 2415 + if ((evsel->core.attr.read_format & PERF_FORMAT_LOST) && 2416 + perf_missing_features.read_lost) 2113 2417 return true; 2114 - } else if (!perf_missing_features.code_page_size && 2115 - (evsel->core.attr.sample_type & PERF_SAMPLE_CODE_PAGE_SIZE)) { 2116 - perf_missing_features.code_page_size = true; 2117 - pr_debug2_peo("Kernel has no PERF_SAMPLE_CODE_PAGE_SIZE support, bailing out\n"); 2118 - return false; 2119 - } else if (!perf_missing_features.data_page_size && 2120 - (evsel->core.attr.sample_type & PERF_SAMPLE_DATA_PAGE_SIZE)) { 2121 - perf_missing_features.data_page_size = true; 2122 - pr_debug2_peo("Kernel has no PERF_SAMPLE_DATA_PAGE_SIZE support, bailing out\n"); 2123 - return false; 2124 - } else if (!perf_missing_features.cgroup && evsel->core.attr.cgroup) { 2125 - perf_missing_features.cgroup = true; 2126 - pr_debug2_peo("Kernel has no cgroup sampling support, bailing out\n"); 2127 - return false; 2128 - } else if (!perf_missing_features.branch_hw_idx && 2129 - (evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX)) { 2130 - perf_missing_features.branch_hw_idx = true; 2131 - pr_debug2("switching off branch HW index support\n"); 2418 + 2419 + if ((evsel->core.attr.sample_type & PERF_SAMPLE_WEIGHT_STRUCT) && 2420 + perf_missing_features.weight_struct) 2132 2421 return true; 2133 - } else if (!perf_missing_features.aux_output && evsel->core.attr.aux_output) { 2134 - perf_missing_features.aux_output = true; 2135 - pr_debug2_peo("Kernel has no attr.aux_output support, bailing out\n"); 2136 - return false; 2137 - } else if (!perf_missing_features.bpf && evsel->core.attr.bpf_event) { 2138 - perf_missing_features.bpf = true; 2139 - pr_debug2_peo("switching off bpf_event\n"); 2140 - return true; 2141 - } else if (!perf_missing_features.ksymbol && evsel->core.attr.ksymbol) { 2142 - perf_missing_features.ksymbol = true; 2143 - pr_debug2_peo("switching off ksymbol\n"); 2144 - return true; 2145 - } else if (!perf_missing_features.write_backward && evsel->core.attr.write_backward) { 2146 - perf_missing_features.write_backward = true; 2147 - pr_debug2_peo("switching off write_backward\n"); 2148 - return false; 2149 - } else if (!perf_missing_features.clockid_wrong && evsel->core.attr.use_clockid) { 2422 + 2423 + if (evsel->core.attr.use_clockid && evsel->core.attr.clockid != CLOCK_MONOTONIC && 2424 + !perf_missing_features.clockid) { 2150 2425 perf_missing_features.clockid_wrong = true; 2151 - pr_debug2_peo("switching off clockid\n"); 2152 2426 return true; 2153 - } else if (!perf_missing_features.clockid && evsel->core.attr.use_clockid) { 2154 - perf_missing_features.clockid = true; 2155 - pr_debug2_peo("switching off use_clockid\n"); 2156 - return true; 2157 - } else if (!perf_missing_features.cloexec && (evsel->open_flags & PERF_FLAG_FD_CLOEXEC)) { 2158 - perf_missing_features.cloexec = true; 2159 - pr_debug2_peo("switching off cloexec flag\n"); 2160 - return true; 2161 - } else if (!perf_missing_features.mmap2 && evsel->core.attr.mmap2) { 2162 - perf_missing_features.mmap2 = true; 2163 - pr_debug2_peo("switching off mmap2\n"); 2164 - return true; 2165 - } else if (evsel->core.attr.exclude_guest || evsel->core.attr.exclude_host) { 2166 - if (evsel->pmu == NULL) 2167 - evsel->pmu = evsel__find_pmu(evsel); 2168 - 2169 - if (evsel->pmu) 2170 - evsel->pmu->missing_features.exclude_guest = true; 2171 - else { 2172 - /* we cannot find PMU, disable attrs now */ 2173 - evsel->core.attr.exclude_host = false; 2174 - evsel->core.attr.exclude_guest = false; 2175 - } 2176 - 2177 - if (evsel->exclude_GH) { 2178 - pr_debug2_peo("PMU has no exclude_host/guest support, bailing out\n"); 2179 - return false; 2180 - } 2181 - if (!perf_missing_features.exclude_guest) { 2182 - perf_missing_features.exclude_guest = true; 2183 - pr_debug2_peo("switching off exclude_guest, exclude_host\n"); 2184 - } 2185 - return true; 2186 - } else if (!perf_missing_features.sample_id_all) { 2187 - perf_missing_features.sample_id_all = true; 2188 - pr_debug2_peo("switching off sample_id_all\n"); 2189 - return true; 2190 - } else if (!perf_missing_features.lbr_flags && 2191 - (evsel->core.attr.branch_sample_type & 2192 - (PERF_SAMPLE_BRANCH_NO_CYCLES | 2193 - PERF_SAMPLE_BRANCH_NO_FLAGS))) { 2194 - perf_missing_features.lbr_flags = true; 2195 - pr_debug2_peo("switching off branch sample type no (cycles/flags)\n"); 2196 - return true; 2197 - } else if (!perf_missing_features.group_read && 2198 - evsel->core.attr.inherit && 2199 - (evsel->core.attr.read_format & PERF_FORMAT_GROUP) && 2200 - evsel__is_group_leader(evsel)) { 2201 - perf_missing_features.group_read = true; 2202 - pr_debug2_peo("switching off group read\n"); 2203 - return true; 2204 - } else { 2205 - return false; 2206 2427 } 2428 + 2429 + if (evsel->core.attr.use_clockid && perf_missing_features.clockid) 2430 + return true; 2431 + 2432 + if ((evsel->open_flags & PERF_FLAG_FD_CLOEXEC) && 2433 + perf_missing_features.cloexec) 2434 + return true; 2435 + 2436 + if (evsel->core.attr.mmap2 && perf_missing_features.mmap2) 2437 + return true; 2438 + 2439 + if ((evsel->core.attr.branch_sample_type & (PERF_SAMPLE_BRANCH_NO_FLAGS | 2440 + PERF_SAMPLE_BRANCH_NO_CYCLES)) && 2441 + perf_missing_features.lbr_flags) 2442 + return true; 2443 + 2444 + if (evsel->core.attr.inherit && (evsel->core.attr.read_format & PERF_FORMAT_GROUP) && 2445 + perf_missing_features.group_read) 2446 + return true; 2447 + 2448 + if (evsel->core.attr.ksymbol && perf_missing_features.ksymbol) 2449 + return true; 2450 + 2451 + if (evsel->core.attr.bpf_event && perf_missing_features.bpf) 2452 + return true; 2453 + 2454 + if ((evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_HW_INDEX) && 2455 + perf_missing_features.branch_hw_idx) 2456 + return true; 2457 + 2458 + if (evsel->core.attr.sample_id_all && perf_missing_features.sample_id_all) 2459 + return true; 2460 + 2461 + return false; 2462 + } 2463 + 2464 + static bool evsel__handle_error_quirks(struct evsel *evsel, int error) 2465 + { 2466 + /* 2467 + * AMD core PMU tries to forward events with precise_ip to IBS PMU 2468 + * implicitly. But IBS PMU has more restrictions so it can fail with 2469 + * supported event attributes. Let's forward it back to the core PMU 2470 + * by clearing precise_ip only if it's from precise_max (:P). 2471 + */ 2472 + if ((error == -EINVAL || error == -ENOENT) && x86__is_amd_cpu() && 2473 + evsel->core.attr.precise_ip && evsel->precise_max) { 2474 + evsel->core.attr.precise_ip = 0; 2475 + pr_debug2_peo("removing precise_ip on AMD\n"); 2476 + display_attr(&evsel->core.attr); 2477 + return true; 2478 + } 2479 + 2480 + return false; 2207 2481 } 2208 2482 2209 2483 static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus, ··· 2439 2261 int idx, thread, nthreads; 2440 2262 int pid = -1, err, old_errno; 2441 2263 enum rlimit_action set_rlimit = NO_CHANGE; 2442 - 2443 - if (evsel__tool_event(evsel) == PERF_TOOL_DURATION_TIME) { 2444 - if (evsel->core.attr.sample_period) /* no sampling */ 2445 - return -EINVAL; 2446 - evsel->start_time = rdclock(); 2447 - return 0; 2448 - } 2449 2264 2450 2265 if (evsel__is_retire_lat(evsel)) 2451 2266 return tpebs_start(evsel->evlist); ··· 2464 2293 pr_debug3("Opening: %s\n", evsel__name(evsel)); 2465 2294 display_attr(&evsel->core.attr); 2466 2295 2296 + if (evsel__is_tool(evsel)) { 2297 + return evsel__tool_pmu_open(evsel, threads, 2298 + start_cpu_map_idx, 2299 + end_cpu_map_idx); 2300 + } 2301 + if (evsel__is_hwmon(evsel)) { 2302 + return evsel__hwmon_pmu_open(evsel, threads, 2303 + start_cpu_map_idx, 2304 + end_cpu_map_idx); 2305 + } 2306 + 2467 2307 for (idx = start_cpu_map_idx; idx < end_cpu_map_idx; idx++) { 2468 2308 2469 2309 for (thread = 0; thread < nthreads; thread++) { ··· 2486 2304 if (!evsel->cgrp && !evsel->core.system_wide) 2487 2305 pid = perf_thread_map__pid(threads, thread); 2488 2306 2489 - if (evsel__tool_event(evsel) == PERF_TOOL_USER_TIME || 2490 - evsel__tool_event(evsel) == PERF_TOOL_SYSTEM_TIME) { 2491 - bool system = evsel__tool_event(evsel) == PERF_TOOL_SYSTEM_TIME; 2492 - __u64 *start_time = NULL; 2493 - 2494 - if (evsel->core.attr.sample_period) { 2495 - /* no sampling */ 2496 - err = -EINVAL; 2497 - goto out_close; 2498 - } 2499 - if (pid > -1) { 2500 - char buf[64]; 2501 - 2502 - snprintf(buf, sizeof(buf), "/proc/%d/stat", pid); 2503 - fd = open(buf, O_RDONLY); 2504 - evsel->pid_stat = true; 2505 - } else { 2506 - fd = open("/proc/stat", O_RDONLY); 2507 - } 2508 - FD(evsel, idx, thread) = fd; 2509 - if (fd < 0) { 2510 - err = -errno; 2511 - goto out_close; 2512 - } 2513 - start_time = xyarray__entry(evsel->start_times, idx, thread); 2514 - if (pid > -1) { 2515 - err = read_pid_stat_field(fd, system ? 15 : 14, 2516 - start_time); 2517 - } else { 2518 - struct perf_cpu cpu; 2519 - 2520 - cpu = perf_cpu_map__cpu(evsel->core.cpus, idx); 2521 - err = read_stat_field(fd, cpu, system ? 3 : 1, 2522 - start_time); 2523 - } 2524 - if (err) 2525 - goto out_close; 2526 - continue; 2527 - } 2528 - 2529 2307 group_fd = get_group_fd(evsel, idx, thread); 2530 2308 2531 2309 if (group_fd == -2) { ··· 2493 2351 err = -EINVAL; 2494 2352 goto out_close; 2495 2353 } 2496 - 2497 - test_attr__ready(); 2498 2354 2499 2355 /* Debug message used by test scripts */ 2500 2356 pr_debug2_peo("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx", ··· 2514 2374 2515 2375 bpf_counter__install_pe(evsel, idx, fd); 2516 2376 2517 - if (unlikely(test_attr__enabled)) { 2377 + if (unlikely(test_attr__enabled())) { 2518 2378 test_attr__open(&evsel->core.attr, pid, 2519 2379 perf_cpu_map__cpu(cpus, idx), 2520 2380 fd, group_fd, evsel->open_flags); ··· 2555 2415 return 0; 2556 2416 2557 2417 try_fallback: 2558 - if (evsel__precise_ip_fallback(evsel)) 2559 - goto retry_open; 2560 - 2561 2418 if (evsel__ignore_missing_thread(evsel, perf_cpu_map__nr(cpus), 2562 2419 idx, threads, thread, err)) { 2563 2420 /* We just removed 1 thread, so lower the upper nthreads limit. */ ··· 2571 2434 if (err == -EMFILE && rlimit__increase_nofile(&set_rlimit)) 2572 2435 goto retry_open; 2573 2436 2574 - if (err != -EINVAL || idx > 0 || thread > 0) 2575 - goto out_close; 2437 + if (err == -EOPNOTSUPP && evsel__precise_ip_fallback(evsel)) 2438 + goto retry_open; 2576 2439 2577 - if (evsel__detect_missing_features(evsel)) 2440 + if (err == -EINVAL && evsel__detect_missing_features(evsel)) 2578 2441 goto fallback_missing_features; 2442 + 2443 + if (evsel__handle_error_quirks(evsel, err)) 2444 + goto retry_open; 2445 + 2579 2446 out_close: 2580 2447 if (err) 2581 2448 threads->err_thread = thread; ··· 3386 3245 evsel->core.attr.exclude_hv = 1; 3387 3246 3388 3247 return true; 3248 + } else if (err == EOPNOTSUPP && !evsel->core.attr.exclude_guest && 3249 + !evsel->exclude_GH) { 3250 + const char *name = evsel__name(evsel); 3251 + char *new_name; 3252 + const char *sep = ":"; 3253 + 3254 + /* Is there already the separator in the name. */ 3255 + if (strchr(name, '/') || 3256 + (strchr(name, ':') && !evsel->is_libpfm_event)) 3257 + sep = ""; 3258 + 3259 + if (asprintf(&new_name, "%s%sH", name, sep) < 0) 3260 + return false; 3261 + 3262 + free(evsel->name); 3263 + evsel->name = new_name; 3264 + /* Apple M1 requires exclude_guest */ 3265 + scnprintf(msg, msgsize, "trying to fall back to excluding guest samples"); 3266 + evsel->core.attr.exclude_guest = 1; 3267 + 3268 + return true; 3389 3269 } 3390 3270 3391 3271 return false; ··· 3577 3415 3578 3416 return scnprintf(msg, size, 3579 3417 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" 3580 - "/bin/dmesg | grep -i perf may provide additional information.\n", 3418 + "\"dmesg | grep -i perf\" may provide additional information.\n", 3581 3419 err, str_error_r(err, sbuf, sizeof(sbuf)), evsel__name(evsel)); 3582 3420 } 3583 3421
+5 -47
tools/perf/util/evsel.h
··· 11 11 #include <perf/evsel.h> 12 12 #include "symbol_conf.h" 13 13 #include "pmus.h" 14 + #include "pmu.h" 14 15 15 16 struct bpf_object; 16 17 struct cgroup; ··· 23 22 struct hashmap; 24 23 struct bperf_leader_bpf; 25 24 struct bperf_follower_bpf; 26 - struct perf_pmu; 27 25 28 26 typedef int (evsel__sb_cb_t)(union perf_event *event, void *data); 29 - 30 - enum perf_tool_event { 31 - PERF_TOOL_NONE = 0, 32 - PERF_TOOL_DURATION_TIME = 1, 33 - PERF_TOOL_USER_TIME = 2, 34 - PERF_TOOL_SYSTEM_TIME = 3, 35 - 36 - PERF_TOOL_MAX, 37 - }; 38 - 39 - const char *perf_tool_event__to_str(enum perf_tool_event ev); 40 - enum perf_tool_event perf_tool_event__from_str(const char *str); 41 - 42 - #define perf_tool_event__for_each_event(ev) \ 43 - for ((ev) = PERF_TOOL_DURATION_TIME; (ev) < PERF_TOOL_MAX; ev++) 44 27 45 28 /** struct evsel - event selector 46 29 * ··· 57 72 struct { 58 73 char *name; 59 74 char *group_name; 60 - const char *pmu_name; 61 75 const char *group_pmu_name; 62 76 #ifdef HAVE_LIBTRACEEVENT 63 77 struct tep_event *tp_format; ··· 67 83 const char *unit; 68 84 struct cgroup *cgrp; 69 85 const char *metric_id; 70 - enum perf_tool_event tool_event; 71 86 /* parse modifier helper */ 72 87 int exclude_GH; 73 88 int sample_read; ··· 85 102 int bpf_fd; 86 103 struct bpf_object *bpf_obj; 87 104 struct list_head config_terms; 105 + u64 alternate_hw_config; 88 106 }; 89 107 90 108 /* ··· 167 183 unsigned long open_flags; 168 184 int precise_ip_original; 169 185 170 - /* for missing_features */ 186 + /* The PMU the event is from. Used for missing_features, PMU name, etc. */ 171 187 struct perf_pmu *pmu; 172 188 173 189 /* For tool events */ ··· 205 221 bool weight_struct; 206 222 bool read_lost; 207 223 bool branch_counters; 224 + bool inherit_sample_read; 208 225 }; 209 226 210 227 extern struct perf_missing_features perf_missing_features; ··· 305 320 bool evsel__name_is(struct evsel *evsel, const char *name); 306 321 const char *evsel__metric_id(const struct evsel *evsel); 307 322 308 - static inline bool evsel__is_tool(const struct evsel *evsel) 309 - { 310 - return evsel->tool_event != PERF_TOOL_NONE; 311 - } 312 - 313 323 static inline bool evsel__is_retire_lat(const struct evsel *evsel) 314 324 { 315 325 return evsel->retire_lat; 316 - } 317 - 318 - static inline enum perf_tool_event evsel__tool_event(const struct evsel *evsel) 319 - { 320 - return evsel->tool_event; 321 326 } 322 327 323 328 const char *evsel__group_name(struct evsel *evsel); ··· 343 368 void evsel__close(struct evsel *evsel); 344 369 int evsel__prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus, 345 370 struct perf_thread_map *threads); 346 - bool evsel__detect_missing_features(struct evsel *evsel); 347 371 348 372 bool evsel__precise_ip_fallback(struct evsel *evsel); 349 373 ··· 367 393 struct tep_format_field *evsel__field(struct evsel *evsel, const char *name); 368 394 struct tep_format_field *evsel__common_field(struct evsel *evsel, const char *name); 369 395 370 - static inline bool __evsel__match(const struct evsel *evsel, u32 type, u64 config) 371 - { 372 - if (evsel->core.attr.type != type) 373 - return false; 374 - 375 - if ((type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE) && 376 - perf_pmus__supports_extended_type()) 377 - return (evsel->core.attr.config & PERF_HW_EVENT_MASK) == config; 378 - 379 - return evsel->core.attr.config == config; 380 - } 396 + bool __evsel__match(const struct evsel *evsel, u32 type, u64 config); 381 397 382 398 #define evsel__match(evsel, t, c) __evsel__match(evsel, PERF_TYPE_##t, PERF_COUNT_##c) 383 - 384 - static inline bool evsel__match2(struct evsel *e1, struct evsel *e2) 385 - { 386 - return (e1->core.attr.type == e2->core.attr.type) && 387 - (e1->core.attr.config == e2->core.attr.config); 388 - } 389 399 390 400 int evsel__read_counter(struct evsel *evsel, int cpu_map_idx, int thread); 391 401
+1 -1
tools/perf/util/evsel_fprintf.c
··· 14 14 #include "dso.h" 15 15 16 16 #ifdef HAVE_LIBTRACEEVENT 17 - #include <traceevent/event-parse.h> 17 + #include <event-parse.h> 18 18 #endif 19 19 20 20 static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
+15 -82
tools/perf/util/expr.c
··· 5 5 #include <stdlib.h> 6 6 #include <string.h> 7 7 #include "metricgroup.h" 8 - #include "cpumap.h" 9 - #include "cputopo.h" 10 8 #include "debug.h" 11 9 #include "evlist.h" 12 10 #include "expr.h" 11 + #include "smt.h" 12 + #include "tool_pmu.h" 13 13 #include <util/expr-bison.h> 14 14 #include <util/expr-flex.h> 15 15 #include "util/hashmap.h" 16 16 #include "util/header.h" 17 17 #include "util/pmu.h" 18 - #include "smt.h" 19 - #include "tsc.h" 20 - #include <api/fs/fs.h> 18 + #include <perf/cpumap.h> 21 19 #include <linux/err.h> 22 20 #include <linux/kernel.h> 23 21 #include <linux/zalloc.h> 24 22 #include <ctype.h> 25 23 #include <math.h> 26 - #include "pmu.h" 27 24 28 25 struct expr_id_data { 29 26 union { ··· 390 393 return data->val.source_count; 391 394 } 392 395 393 - #if !defined(__i386__) && !defined(__x86_64__) 394 - double arch_get_tsc_freq(void) 395 - { 396 - return 0.0; 397 - } 398 - #endif 399 - 400 - static double has_pmem(void) 401 - { 402 - static bool has_pmem, cached; 403 - const char *sysfs = sysfs__mountpoint(); 404 - char path[PATH_MAX]; 405 - 406 - if (!cached) { 407 - snprintf(path, sizeof(path), "%s/firmware/acpi/tables/NFIT", sysfs); 408 - has_pmem = access(path, F_OK) == 0; 409 - cached = true; 410 - } 411 - return has_pmem ? 1.0 : 0.0; 412 - } 413 - 414 396 double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx) 415 397 { 416 - const struct cpu_topology *topology; 417 398 double result = NAN; 399 + enum tool_pmu_event ev = tool_pmu__str_to_event(literal + 1); 418 400 419 - if (!strcmp("#num_cpus", literal)) { 420 - result = cpu__max_present_cpu().cpu; 421 - goto out; 422 - } 423 - if (!strcmp("#num_cpus_online", literal)) { 424 - struct perf_cpu_map *online = cpu_map__online(); 401 + if (ev != TOOL_PMU__EVENT_NONE) { 402 + u64 count; 425 403 426 - if (online) 427 - result = perf_cpu_map__nr(online); 428 - goto out; 429 - } 404 + if (tool_pmu__read_event(ev, &count)) 405 + result = count; 406 + else 407 + pr_err("Failure to read '%s'", literal); 430 408 431 - if (!strcasecmp("#system_tsc_freq", literal)) { 432 - result = arch_get_tsc_freq(); 433 - goto out; 434 - } 435 - 436 - /* 437 - * Assume that topology strings are consistent, such as CPUs "0-1" 438 - * wouldn't be listed as "0,1", and so after deduplication the number of 439 - * these strings gives an indication of the number of packages, dies, 440 - * etc. 441 - */ 442 - if (!strcasecmp("#smt_on", literal)) { 443 - result = smt_on() ? 1.0 : 0.0; 444 - goto out; 445 - } 446 - if (!strcmp("#core_wide", literal)) { 409 + } else if (!strcmp("#core_wide", literal)) { 447 410 result = core_wide(ctx->system_wide, ctx->user_requested_cpu_list) 448 411 ? 1.0 : 0.0; 449 - goto out; 450 - } 451 - if (!strcmp("#num_packages", literal)) { 452 - topology = online_topology(); 453 - result = topology->package_cpus_lists; 454 - goto out; 455 - } 456 - if (!strcmp("#num_dies", literal)) { 457 - topology = online_topology(); 458 - result = topology->die_cpus_lists; 459 - goto out; 460 - } 461 - if (!strcmp("#num_cores", literal)) { 462 - topology = online_topology(); 463 - result = topology->core_cpus_lists; 464 - goto out; 465 - } 466 - if (!strcmp("#slots", literal)) { 467 - result = perf_pmu__cpu_slots_per_cycle(); 468 - goto out; 469 - } 470 - if (!strcmp("#has_pmem", literal)) { 471 - result = has_pmem(); 472 - goto out; 412 + } else { 413 + pr_err("Unrecognized literal '%s'", literal); 473 414 } 474 415 475 - pr_err("Unrecognized literal '%s'", literal); 476 - out: 477 416 pr_debug2("literal: %s = %f\n", literal, result); 478 417 return result; 479 418 } ··· 456 523 bool compute_ids __maybe_unused, const char *test_id) 457 524 { 458 525 double ret; 459 - struct perf_pmu *pmu = perf_pmus__find_core_pmu(); 460 - char *cpuid = perf_pmu__getcpuid(pmu); 526 + struct perf_cpu cpu = {-1}; 527 + char *cpuid = get_cpuid_allow_env_override(cpu); 461 528 462 529 if (!cpuid) 463 530 return NAN;
+2 -2
tools/perf/util/genelf.c
··· 16 16 #include <inttypes.h> 17 17 #include <fcntl.h> 18 18 #include <err.h> 19 - #ifdef HAVE_DWARF_SUPPORT 19 + #ifdef HAVE_LIBDW_SUPPORT 20 20 #include <dwarf.h> 21 21 #endif 22 22 ··· 499 499 shdr->sh_size = sizeof(bnote); 500 500 shdr->sh_entsize = 0; 501 501 502 - #ifdef HAVE_DWARF_SUPPORT 502 + #ifdef HAVE_LIBDW_SUPPORT 503 503 if (debug && nr_debug_entries) { 504 504 retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries); 505 505 if (retval)
+1 -1
tools/perf/util/genelf.h
··· 8 8 int jit_write_elf(int fd, uint64_t code_addr, const char *sym, 9 9 const void *code, int csize, void *debug, int nr_debug_entries, 10 10 void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size); 11 - #ifdef HAVE_DWARF_SUPPORT 11 + #ifdef HAVE_LIBDW_SUPPORT 12 12 /* genelf_debug.c */ 13 13 int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries); 14 14 #endif
+10 -10
tools/perf/util/hashmap.h
··· 166 166 * @bkt: integer used as a bucket loop cursor 167 167 */ 168 168 #define hashmap__for_each_entry(map, cur, bkt) \ 169 - for (bkt = 0; bkt < map->cap; bkt++) \ 170 - for (cur = map->buckets[bkt]; cur; cur = cur->next) 169 + for (bkt = 0; bkt < (map)->cap; bkt++) \ 170 + for (cur = (map)->buckets[bkt]; cur; cur = cur->next) 171 171 172 172 /* 173 173 * hashmap__for_each_entry_safe - iterate over all entries in hashmap, safe ··· 178 178 * @bkt: integer used as a bucket loop cursor 179 179 */ 180 180 #define hashmap__for_each_entry_safe(map, cur, tmp, bkt) \ 181 - for (bkt = 0; bkt < map->cap; bkt++) \ 182 - for (cur = map->buckets[bkt]; \ 181 + for (bkt = 0; bkt < (map)->cap; bkt++) \ 182 + for (cur = (map)->buckets[bkt]; \ 183 183 cur && ({tmp = cur->next; true; }); \ 184 184 cur = tmp) 185 185 ··· 190 190 * @key: key to iterate entries for 191 191 */ 192 192 #define hashmap__for_each_key_entry(map, cur, _key) \ 193 - for (cur = map->buckets \ 194 - ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \ 193 + for (cur = (map)->buckets \ 194 + ? (map)->buckets[hash_bits((map)->hash_fn((_key), (map)->ctx), (map)->cap_bits)] \ 195 195 : NULL; \ 196 196 cur; \ 197 197 cur = cur->next) \ 198 - if (map->equal_fn(cur->key, (_key), map->ctx)) 198 + if ((map)->equal_fn(cur->key, (_key), (map)->ctx)) 199 199 200 200 #define hashmap__for_each_key_entry_safe(map, cur, tmp, _key) \ 201 - for (cur = map->buckets \ 202 - ? map->buckets[hash_bits(map->hash_fn((_key), map->ctx), map->cap_bits)] \ 201 + for (cur = (map)->buckets \ 202 + ? (map)->buckets[hash_bits((map)->hash_fn((_key), (map)->ctx), (map)->cap_bits)] \ 203 203 : NULL; \ 204 204 cur && ({ tmp = cur->next; true; }); \ 205 205 cur = tmp) \ 206 - if (map->equal_fn(cur->key, (_key), map->ctx)) 206 + if ((map)->equal_fn(cur->key, (_key), (map)->ctx)) 207 207 208 208 #endif /* __LIBBPF_HASHMAP_H */
+27 -57
tools/perf/util/header.c
··· 58 58 #include <internal/lib.h> 59 59 60 60 #ifdef HAVE_LIBTRACEEVENT 61 - #include <traceevent/event-parse.h> 61 + #include <event-parse.h> 62 62 #endif 63 63 64 64 /* ··· 819 819 * Each architecture should provide a more precise id string that 820 820 * can be use to match the architecture's "mapfile". 821 821 */ 822 - char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused) 822 + char * __weak get_cpuid_str(struct perf_cpu cpu __maybe_unused) 823 823 { 824 824 return NULL; 825 + } 826 + 827 + char *get_cpuid_allow_env_override(struct perf_cpu cpu) 828 + { 829 + char *cpuid; 830 + static bool printed; 831 + 832 + cpuid = getenv("PERF_CPUID"); 833 + if (cpuid) 834 + cpuid = strdup(cpuid); 835 + if (!cpuid) 836 + cpuid = get_cpuid_str(cpu); 837 + if (!cpuid) 838 + return NULL; 839 + 840 + if (!printed) { 841 + pr_debug("Using CPUID %s\n", cpuid); 842 + printed = true; 843 + } 844 + return cpuid; 825 845 } 826 846 827 847 /* Return zero when the cpuid from the mapfile.csv matches the ··· 876 856 * default get_cpuid(): nothing gets recorded 877 857 * actual implementation must be in arch/$(SRCARCH)/util/header.c 878 858 */ 879 - int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused) 859 + int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused, 860 + struct perf_cpu cpu __maybe_unused) 880 861 { 881 862 return ENOSYS; /* Not implemented */ 882 863 } 883 864 884 - static int write_cpuid(struct feat_fd *ff, 885 - struct evlist *evlist __maybe_unused) 865 + static int write_cpuid(struct feat_fd *ff, struct evlist *evlist) 886 866 { 867 + struct perf_cpu cpu = perf_cpu_map__min(evlist->core.all_cpus); 887 868 char buffer[64]; 888 869 int ret; 889 870 890 - ret = get_cpuid(buffer, sizeof(buffer)); 871 + ret = get_cpuid(buffer, sizeof(buffer), cpu); 891 872 if (ret) 892 873 return -1; 893 874 ··· 1006 985 return -1; 1007 986 1008 987 return do_write(ff, &data->dir.version, sizeof(data->dir.version)); 1009 - } 1010 - 1011 - /* 1012 - * Check whether a CPU is online 1013 - * 1014 - * Returns: 1015 - * 1 -> if CPU is online 1016 - * 0 -> if CPU is offline 1017 - * -1 -> error case 1018 - */ 1019 - int is_cpu_online(unsigned int cpu) 1020 - { 1021 - char *str; 1022 - size_t strlen; 1023 - char buf[256]; 1024 - int status = -1; 1025 - struct stat statbuf; 1026 - 1027 - snprintf(buf, sizeof(buf), 1028 - "/sys/devices/system/cpu/cpu%d", cpu); 1029 - if (stat(buf, &statbuf) != 0) 1030 - return 0; 1031 - 1032 - /* 1033 - * Check if /sys/devices/system/cpu/cpux/online file 1034 - * exists. Some cases cpu0 won't have online file since 1035 - * it is not expected to be turned off generally. 1036 - * In kernels without CONFIG_HOTPLUG_CPU, this 1037 - * file won't exist 1038 - */ 1039 - snprintf(buf, sizeof(buf), 1040 - "/sys/devices/system/cpu/cpu%d/online", cpu); 1041 - if (stat(buf, &statbuf) != 0) 1042 - return 1; 1043 - 1044 - /* 1045 - * Read online file using sysfs__read_str. 1046 - * If read or open fails, return -1. 1047 - * If read succeeds, return value from file 1048 - * which gets stored in "str" 1049 - */ 1050 - snprintf(buf, sizeof(buf), 1051 - "devices/system/cpu/cpu%d/online", cpu); 1052 - 1053 - if (sysfs__read_str(buf, &str, &strlen) < 0) 1054 - return status; 1055 - 1056 - status = atoi(str); 1057 - 1058 - free(str); 1059 - return status; 1060 988 } 1061 989 1062 990 #ifdef HAVE_LIBBPF_SUPPORT
+12 -11
tools/perf/util/header.h
··· 10 10 #include <linux/bitmap.h> 11 11 #include <linux/types.h> 12 12 #include "env.h" 13 - #include "pmu.h" 13 + #include <perf/cpumap.h> 14 + 15 + struct evlist; 16 + union perf_event; 17 + struct perf_header; 18 + struct perf_session; 19 + struct perf_tool; 14 20 15 21 enum { 16 22 HEADER_RESERVED = 0, /* always cleared */ ··· 97 91 u64 size; 98 92 }; 99 93 100 - struct perf_header; 101 - 102 94 int perf_file_header__read(struct perf_file_header *header, 103 95 struct perf_header *ph, int fd); 104 96 ··· 127 123 bool full_only; 128 124 bool synthesize; 129 125 }; 130 - 131 - struct evlist; 132 - struct perf_session; 133 - struct perf_tool; 134 - union perf_event; 135 126 136 127 extern const char perf_version_string[]; 137 128 ··· 195 196 196 197 #define MAX_CACHE_LVL 4 197 198 198 - int is_cpu_online(unsigned int cpu); 199 199 int build_caches_for_cpu(u32 cpu, struct cpu_cache_level caches[], u32 *cntp); 200 200 201 201 /* 202 202 * arch specific callback 203 203 */ 204 - int get_cpuid(char *buffer, size_t sz); 204 + int get_cpuid(char *buffer, size_t sz, struct perf_cpu cpu); 205 205 206 - char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused); 206 + char *get_cpuid_str(struct perf_cpu cpu); 207 + 208 + char *get_cpuid_allow_env_override(struct perf_cpu cpu); 209 + 207 210 int strcmp_cpuid_str(const char *s1, const char *s2); 208 211 #endif /* __PERF_HEADER_H */
+3
tools/perf/util/hist.c
··· 218 218 hists__new_col_len(hists, HISTC_LOCAL_P_STAGE_CYC, 13); 219 219 hists__new_col_len(hists, HISTC_GLOBAL_P_STAGE_CYC, 13); 220 220 hists__new_col_len(hists, HISTC_ADDR, BITS_PER_LONG / 4 + 2); 221 + hists__new_col_len(hists, HISTC_CALLCHAIN_BRANCH_PREDICTED, 9); 222 + hists__new_col_len(hists, HISTC_CALLCHAIN_BRANCH_ABORT, 5); 223 + hists__new_col_len(hists, HISTC_CALLCHAIN_BRANCH_CYCLES, 6); 221 224 222 225 if (symbol_conf.nanosecs) 223 226 hists__new_col_len(hists, HISTC_TIME, 16);
+3
tools/perf/util/hist.h
··· 87 87 HISTC_TYPE_OFFSET, 88 88 HISTC_SYMBOL_OFFSET, 89 89 HISTC_TYPE_CACHELINE, 90 + HISTC_CALLCHAIN_BRANCH_PREDICTED, 91 + HISTC_CALLCHAIN_BRANCH_ABORT, 92 + HISTC_CALLCHAIN_BRANCH_CYCLES, 90 93 HISTC_NR_COLS, /* Last entry */ 91 94 }; 92 95
+832
tools/perf/util/hwmon_pmu.c
··· 1 + // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 + #include "counts.h" 3 + #include "debug.h" 4 + #include "evsel.h" 5 + #include "hashmap.h" 6 + #include "hwmon_pmu.h" 7 + #include "pmu.h" 8 + #include <internal/xyarray.h> 9 + #include <internal/threadmap.h> 10 + #include <perf/threadmap.h> 11 + #include <sys/types.h> 12 + #include <assert.h> 13 + #include <ctype.h> 14 + #include <dirent.h> 15 + #include <fcntl.h> 16 + #include <stddef.h> 17 + #include <stdlib.h> 18 + #include <string.h> 19 + #include <api/fs/fs.h> 20 + #include <api/io.h> 21 + #include <linux/kernel.h> 22 + #include <linux/string.h> 23 + #include <linux/zalloc.h> 24 + 25 + /** Strings that correspond to enum hwmon_type. */ 26 + static const char * const hwmon_type_strs[HWMON_TYPE_MAX] = { 27 + NULL, 28 + "cpu", 29 + "curr", 30 + "energy", 31 + "fan", 32 + "humidity", 33 + "in", 34 + "intrusion", 35 + "power", 36 + "pwm", 37 + "temp", 38 + }; 39 + #define LONGEST_HWMON_TYPE_STR "intrusion" 40 + 41 + /** Strings that correspond to enum hwmon_item. */ 42 + static const char * const hwmon_item_strs[HWMON_ITEM__MAX] = { 43 + NULL, 44 + "accuracy", 45 + "alarm", 46 + "auto_channels_temp", 47 + "average", 48 + "average_highest", 49 + "average_interval", 50 + "average_interval_max", 51 + "average_interval_min", 52 + "average_lowest", 53 + "average_max", 54 + "average_min", 55 + "beep", 56 + "cap", 57 + "cap_hyst", 58 + "cap_max", 59 + "cap_min", 60 + "crit", 61 + "crit_hyst", 62 + "div", 63 + "emergency", 64 + "emergency_hist", 65 + "enable", 66 + "fault", 67 + "freq", 68 + "highest", 69 + "input", 70 + "label", 71 + "lcrit", 72 + "lcrit_hyst", 73 + "lowest", 74 + "max", 75 + "max_hyst", 76 + "min", 77 + "min_hyst", 78 + "mod", 79 + "offset", 80 + "pulses", 81 + "rated_max", 82 + "rated_min", 83 + "reset_history", 84 + "target", 85 + "type", 86 + "vid", 87 + }; 88 + #define LONGEST_HWMON_ITEM_STR "average_interval_max" 89 + 90 + static const char *const hwmon_units[HWMON_TYPE_MAX] = { 91 + NULL, 92 + "V", /* cpu */ 93 + "A", /* curr */ 94 + "J", /* energy */ 95 + "rpm", /* fan */ 96 + "%", /* humidity */ 97 + "V", /* in */ 98 + "", /* intrusion */ 99 + "W", /* power */ 100 + "Hz", /* pwm */ 101 + "'C", /* temp */ 102 + }; 103 + 104 + struct hwmon_pmu { 105 + struct perf_pmu pmu; 106 + struct hashmap events; 107 + int hwmon_dir_fd; 108 + }; 109 + 110 + /** 111 + * union hwmon_pmu_event_key: Key for hwmon_pmu->events as such each key 112 + * represents an event. 113 + * 114 + * Related hwmon files start <type><number> that this key represents. 115 + */ 116 + union hwmon_pmu_event_key { 117 + long type_and_num; 118 + struct { 119 + int num :16; 120 + enum hwmon_type type :8; 121 + }; 122 + }; 123 + 124 + /** 125 + * struct hwmon_pmu_event_value: Value in hwmon_pmu->events. 126 + * 127 + * Hwmon files are of the form <type><number>_<item> and may have a suffix 128 + * _alarm. 129 + */ 130 + struct hwmon_pmu_event_value { 131 + /** @items: which item files are present. */ 132 + DECLARE_BITMAP(items, HWMON_ITEM__MAX); 133 + /** @alarm_items: which item files are present. */ 134 + DECLARE_BITMAP(alarm_items, HWMON_ITEM__MAX); 135 + /** @label: contents of <type><number>_label if present. */ 136 + char *label; 137 + /** @name: name computed from label of the form <type>_<label>. */ 138 + char *name; 139 + }; 140 + 141 + bool perf_pmu__is_hwmon(const struct perf_pmu *pmu) 142 + { 143 + return pmu && pmu->type >= PERF_PMU_TYPE_HWMON_START && 144 + pmu->type <= PERF_PMU_TYPE_HWMON_END; 145 + } 146 + 147 + bool evsel__is_hwmon(const struct evsel *evsel) 148 + { 149 + return perf_pmu__is_hwmon(evsel->pmu); 150 + } 151 + 152 + static size_t hwmon_pmu__event_hashmap_hash(long key, void *ctx __maybe_unused) 153 + { 154 + return ((union hwmon_pmu_event_key)key).type_and_num; 155 + } 156 + 157 + static bool hwmon_pmu__event_hashmap_equal(long key1, long key2, void *ctx __maybe_unused) 158 + { 159 + return ((union hwmon_pmu_event_key)key1).type_and_num == 160 + ((union hwmon_pmu_event_key)key2).type_and_num; 161 + } 162 + 163 + static int hwmon_strcmp(const void *a, const void *b) 164 + { 165 + const char *sa = a; 166 + const char * const *sb = b; 167 + 168 + return strcmp(sa, *sb); 169 + } 170 + 171 + bool parse_hwmon_filename(const char *filename, 172 + enum hwmon_type *type, 173 + int *number, 174 + enum hwmon_item *item, 175 + bool *alarm) 176 + { 177 + char fn_type[24]; 178 + const char **elem; 179 + const char *fn_item = NULL; 180 + size_t fn_item_len; 181 + 182 + assert(strlen(LONGEST_HWMON_TYPE_STR) < sizeof(fn_type)); 183 + strlcpy(fn_type, filename, sizeof(fn_type)); 184 + for (size_t i = 0; fn_type[i] != '\0'; i++) { 185 + if (fn_type[i] >= '0' && fn_type[i] <= '9') { 186 + fn_type[i] = '\0'; 187 + *number = strtoul(&filename[i], (char **)&fn_item, 10); 188 + if (*fn_item == '_') 189 + fn_item++; 190 + break; 191 + } 192 + if (fn_type[i] == '_') { 193 + fn_type[i] = '\0'; 194 + *number = -1; 195 + fn_item = &filename[i + 1]; 196 + break; 197 + } 198 + } 199 + if (fn_item == NULL || fn_type[0] == '\0' || (item != NULL && fn_item[0] == '\0')) { 200 + pr_debug3("hwmon_pmu: not a hwmon file '%s'\n", filename); 201 + return false; 202 + } 203 + elem = bsearch(&fn_type, hwmon_type_strs + 1, ARRAY_SIZE(hwmon_type_strs) - 1, 204 + sizeof(hwmon_type_strs[0]), hwmon_strcmp); 205 + if (!elem) { 206 + pr_debug3("hwmon_pmu: not a hwmon type '%s' in file name '%s'\n", 207 + fn_type, filename); 208 + return false; 209 + } 210 + 211 + *type = elem - &hwmon_type_strs[0]; 212 + if (!item) 213 + return true; 214 + 215 + *alarm = false; 216 + fn_item_len = strlen(fn_item); 217 + if (fn_item_len > 6 && !strcmp(&fn_item[fn_item_len - 6], "_alarm")) { 218 + assert(strlen(LONGEST_HWMON_ITEM_STR) < sizeof(fn_type)); 219 + strlcpy(fn_type, fn_item, fn_item_len - 5); 220 + fn_item = fn_type; 221 + *alarm = true; 222 + } 223 + elem = bsearch(fn_item, hwmon_item_strs + 1, ARRAY_SIZE(hwmon_item_strs) - 1, 224 + sizeof(hwmon_item_strs[0]), hwmon_strcmp); 225 + if (!elem) { 226 + pr_debug3("hwmon_pmu: not a hwmon item '%s' in file name '%s'\n", 227 + fn_item, filename); 228 + return false; 229 + } 230 + *item = elem - &hwmon_item_strs[0]; 231 + return true; 232 + } 233 + 234 + static void fix_name(char *p) 235 + { 236 + char *s = strchr(p, '\n'); 237 + 238 + if (s) 239 + *s = '\0'; 240 + 241 + while (*p != '\0') { 242 + if (strchr(" :,/\n\t", *p)) 243 + *p = '_'; 244 + else 245 + *p = tolower(*p); 246 + p++; 247 + } 248 + } 249 + 250 + static int hwmon_pmu__read_events(struct hwmon_pmu *pmu) 251 + { 252 + DIR *dir; 253 + struct dirent *ent; 254 + int dup_fd, err = 0; 255 + struct hashmap_entry *cur, *tmp; 256 + size_t bkt; 257 + 258 + if (pmu->pmu.sysfs_aliases_loaded) 259 + return 0; 260 + 261 + /* Use a dup-ed fd as closedir will close it. */ 262 + dup_fd = dup(pmu->hwmon_dir_fd); 263 + if (dup_fd == -1) 264 + return -ENOMEM; 265 + 266 + dir = fdopendir(dup_fd); 267 + if (!dir) { 268 + close(dup_fd); 269 + return -ENOMEM; 270 + } 271 + 272 + while ((ent = readdir(dir)) != NULL) { 273 + enum hwmon_type type; 274 + int number; 275 + enum hwmon_item item; 276 + bool alarm; 277 + union hwmon_pmu_event_key key = { .type_and_num = 0 }; 278 + struct hwmon_pmu_event_value *value; 279 + 280 + if (ent->d_type != DT_REG) 281 + continue; 282 + 283 + if (!parse_hwmon_filename(ent->d_name, &type, &number, &item, &alarm)) { 284 + pr_debug3("Not a hwmon file '%s'\n", ent->d_name); 285 + continue; 286 + } 287 + key.num = number; 288 + key.type = type; 289 + if (!hashmap__find(&pmu->events, key.type_and_num, &value)) { 290 + value = zalloc(sizeof(*value)); 291 + if (!value) { 292 + err = -ENOMEM; 293 + goto err_out; 294 + } 295 + err = hashmap__add(&pmu->events, key.type_and_num, value); 296 + if (err) { 297 + free(value); 298 + err = -ENOMEM; 299 + goto err_out; 300 + } 301 + } 302 + __set_bit(item, alarm ? value->alarm_items : value->items); 303 + if (item == HWMON_ITEM_LABEL) { 304 + char buf[128]; 305 + int fd = openat(pmu->hwmon_dir_fd, ent->d_name, O_RDONLY); 306 + ssize_t read_len; 307 + 308 + if (fd < 0) 309 + continue; 310 + 311 + read_len = read(fd, buf, sizeof(buf)); 312 + 313 + while (read_len > 0 && buf[read_len - 1] == '\n') 314 + read_len--; 315 + 316 + if (read_len > 0) 317 + buf[read_len] = '\0'; 318 + 319 + if (buf[0] == '\0') { 320 + pr_debug("hwmon_pmu: empty label file %s %s\n", 321 + pmu->pmu.name, ent->d_name); 322 + close(fd); 323 + continue; 324 + } 325 + value->label = strdup(buf); 326 + if (!value->label) { 327 + pr_debug("hwmon_pmu: memory allocation failure\n"); 328 + close(fd); 329 + continue; 330 + } 331 + snprintf(buf, sizeof(buf), "%s_%s", hwmon_type_strs[type], value->label); 332 + fix_name(buf); 333 + value->name = strdup(buf); 334 + if (!value->name) 335 + pr_debug("hwmon_pmu: memory allocation failure\n"); 336 + close(fd); 337 + } 338 + } 339 + hashmap__for_each_entry_safe((&pmu->events), cur, tmp, bkt) { 340 + union hwmon_pmu_event_key key = { 341 + .type_and_num = cur->key, 342 + }; 343 + struct hwmon_pmu_event_value *value = cur->pvalue; 344 + 345 + if (!test_bit(HWMON_ITEM_INPUT, value->items)) { 346 + pr_debug("hwmon_pmu: removing event '%s%d' that has no input file\n", 347 + hwmon_type_strs[key.type], key.num); 348 + hashmap__delete(&pmu->events, key.type_and_num, &key, &value); 349 + zfree(&value->label); 350 + zfree(&value->name); 351 + free(value); 352 + } 353 + } 354 + pmu->pmu.sysfs_aliases_loaded = true; 355 + 356 + err_out: 357 + closedir(dir); 358 + return err; 359 + } 360 + 361 + struct perf_pmu *hwmon_pmu__new(struct list_head *pmus, int hwmon_dir, const char *sysfs_name, const char *name) 362 + { 363 + char buf[32]; 364 + struct hwmon_pmu *hwm; 365 + 366 + hwm = zalloc(sizeof(*hwm)); 367 + if (!hwm) 368 + return NULL; 369 + 370 + hwm->hwmon_dir_fd = hwmon_dir; 371 + hwm->pmu.type = PERF_PMU_TYPE_HWMON_START + strtoul(sysfs_name + 5, NULL, 10); 372 + if (hwm->pmu.type > PERF_PMU_TYPE_HWMON_END) { 373 + pr_err("Unable to encode hwmon type from %s in valid PMU type\n", sysfs_name); 374 + goto err_out; 375 + } 376 + snprintf(buf, sizeof(buf), "hwmon_%s", name); 377 + fix_name(buf + 6); 378 + hwm->pmu.name = strdup(buf); 379 + if (!hwm->pmu.name) 380 + goto err_out; 381 + hwm->pmu.alias_name = strdup(sysfs_name); 382 + if (!hwm->pmu.alias_name) 383 + goto err_out; 384 + hwm->pmu.cpus = perf_cpu_map__new("0"); 385 + if (!hwm->pmu.cpus) 386 + goto err_out; 387 + INIT_LIST_HEAD(&hwm->pmu.format); 388 + INIT_LIST_HEAD(&hwm->pmu.aliases); 389 + INIT_LIST_HEAD(&hwm->pmu.caps); 390 + hashmap__init(&hwm->events, hwmon_pmu__event_hashmap_hash, 391 + hwmon_pmu__event_hashmap_equal, /*ctx=*/NULL); 392 + 393 + list_add_tail(&hwm->pmu.list, pmus); 394 + return &hwm->pmu; 395 + err_out: 396 + free((char *)hwm->pmu.name); 397 + free(hwm->pmu.alias_name); 398 + free(hwm); 399 + close(hwmon_dir); 400 + return NULL; 401 + } 402 + 403 + void hwmon_pmu__exit(struct perf_pmu *pmu) 404 + { 405 + struct hwmon_pmu *hwm = container_of(pmu, struct hwmon_pmu, pmu); 406 + struct hashmap_entry *cur, *tmp; 407 + size_t bkt; 408 + 409 + hashmap__for_each_entry_safe((&hwm->events), cur, tmp, bkt) { 410 + struct hwmon_pmu_event_value *value = cur->pvalue; 411 + 412 + zfree(&value->label); 413 + zfree(&value->name); 414 + free(value); 415 + } 416 + hashmap__clear(&hwm->events); 417 + close(hwm->hwmon_dir_fd); 418 + } 419 + 420 + static size_t hwmon_pmu__describe_items(struct hwmon_pmu *hwm, char *out_buf, size_t out_buf_len, 421 + union hwmon_pmu_event_key key, 422 + const unsigned long *items, bool is_alarm) 423 + { 424 + size_t bit; 425 + char buf[64]; 426 + size_t len = 0; 427 + 428 + for_each_set_bit(bit, items, HWMON_ITEM__MAX) { 429 + int fd; 430 + 431 + if (bit == HWMON_ITEM_LABEL || bit == HWMON_ITEM_INPUT) 432 + continue; 433 + 434 + snprintf(buf, sizeof(buf), "%s%d_%s%s", 435 + hwmon_type_strs[key.type], 436 + key.num, 437 + hwmon_item_strs[bit], 438 + is_alarm ? "_alarm" : ""); 439 + fd = openat(hwm->hwmon_dir_fd, buf, O_RDONLY); 440 + if (fd > 0) { 441 + ssize_t read_len = read(fd, buf, sizeof(buf)); 442 + 443 + while (read_len > 0 && buf[read_len - 1] == '\n') 444 + read_len--; 445 + 446 + if (read_len > 0) { 447 + long long val; 448 + 449 + buf[read_len] = '\0'; 450 + val = strtoll(buf, /*endptr=*/NULL, 10); 451 + len += snprintf(out_buf + len, out_buf_len - len, "%s%s%s=%g%s", 452 + len == 0 ? " " : ", ", 453 + hwmon_item_strs[bit], 454 + is_alarm ? "_alarm" : "", 455 + (double)val / 1000.0, 456 + hwmon_units[key.type]); 457 + } 458 + close(fd); 459 + } 460 + } 461 + return len; 462 + } 463 + 464 + int hwmon_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb) 465 + { 466 + struct hwmon_pmu *hwm = container_of(pmu, struct hwmon_pmu, pmu); 467 + struct hashmap_entry *cur; 468 + size_t bkt; 469 + 470 + if (hwmon_pmu__read_events(hwm)) 471 + return false; 472 + 473 + hashmap__for_each_entry((&hwm->events), cur, bkt) { 474 + static const char *const hwmon_scale_units[HWMON_TYPE_MAX] = { 475 + NULL, 476 + "0.001V", /* cpu */ 477 + "0.001A", /* curr */ 478 + "0.001J", /* energy */ 479 + "1rpm", /* fan */ 480 + "0.001%", /* humidity */ 481 + "0.001V", /* in */ 482 + NULL, /* intrusion */ 483 + "0.001W", /* power */ 484 + "1Hz", /* pwm */ 485 + "0.001'C", /* temp */ 486 + }; 487 + static const char *const hwmon_desc[HWMON_TYPE_MAX] = { 488 + NULL, 489 + "CPU core reference voltage", /* cpu */ 490 + "Current", /* curr */ 491 + "Cumulative energy use", /* energy */ 492 + "Fan", /* fan */ 493 + "Humidity", /* humidity */ 494 + "Voltage", /* in */ 495 + "Chassis intrusion detection", /* intrusion */ 496 + "Power use", /* power */ 497 + "Pulse width modulation fan control", /* pwm */ 498 + "Temperature", /* temp */ 499 + }; 500 + char alias_buf[64]; 501 + char desc_buf[256]; 502 + char encoding_buf[128]; 503 + union hwmon_pmu_event_key key = { 504 + .type_and_num = cur->key, 505 + }; 506 + struct hwmon_pmu_event_value *value = cur->pvalue; 507 + struct pmu_event_info info = { 508 + .pmu = pmu, 509 + .name = value->name, 510 + .alias = alias_buf, 511 + .scale_unit = hwmon_scale_units[key.type], 512 + .desc = desc_buf, 513 + .long_desc = NULL, 514 + .encoding_desc = encoding_buf, 515 + .topic = "hwmon", 516 + .pmu_name = pmu->name, 517 + .event_type_desc = "Hwmon event", 518 + }; 519 + int ret; 520 + size_t len; 521 + 522 + len = snprintf(alias_buf, sizeof(alias_buf), "%s%d", 523 + hwmon_type_strs[key.type], key.num); 524 + if (!info.name) { 525 + info.name = info.alias; 526 + info.alias = NULL; 527 + } 528 + 529 + len = snprintf(desc_buf, sizeof(desc_buf), "%s in unit %s named %s.", 530 + hwmon_desc[key.type], 531 + pmu->name + 6, 532 + value->label ?: info.name); 533 + 534 + len += hwmon_pmu__describe_items(hwm, desc_buf + len, sizeof(desc_buf) - len, 535 + key, value->items, /*is_alarm=*/false); 536 + 537 + len += hwmon_pmu__describe_items(hwm, desc_buf + len, sizeof(desc_buf) - len, 538 + key, value->alarm_items, /*is_alarm=*/true); 539 + 540 + snprintf(encoding_buf, sizeof(encoding_buf), "%s/config=0x%lx/", 541 + pmu->name, cur->key); 542 + 543 + ret = cb(state, &info); 544 + if (ret) 545 + return ret; 546 + } 547 + return 0; 548 + } 549 + 550 + size_t hwmon_pmu__num_events(struct perf_pmu *pmu) 551 + { 552 + struct hwmon_pmu *hwm = container_of(pmu, struct hwmon_pmu, pmu); 553 + 554 + hwmon_pmu__read_events(hwm); 555 + return hashmap__size(&hwm->events); 556 + } 557 + 558 + bool hwmon_pmu__have_event(struct perf_pmu *pmu, const char *name) 559 + { 560 + struct hwmon_pmu *hwm = container_of(pmu, struct hwmon_pmu, pmu); 561 + enum hwmon_type type; 562 + int number; 563 + union hwmon_pmu_event_key key = { .type_and_num = 0 }; 564 + struct hashmap_entry *cur; 565 + size_t bkt; 566 + 567 + if (!parse_hwmon_filename(name, &type, &number, /*item=*/NULL, /*is_alarm=*/NULL)) 568 + return false; 569 + 570 + if (hwmon_pmu__read_events(hwm)) 571 + return false; 572 + 573 + key.type = type; 574 + key.num = number; 575 + if (hashmap_find(&hwm->events, key.type_and_num, /*value=*/NULL)) 576 + return true; 577 + if (key.num != -1) 578 + return false; 579 + /* Item is of form <type>_ which means we should match <type>_<label>. */ 580 + hashmap__for_each_entry((&hwm->events), cur, bkt) { 581 + struct hwmon_pmu_event_value *value = cur->pvalue; 582 + 583 + key.type_and_num = cur->key; 584 + if (key.type == type && value->name && !strcasecmp(name, value->name)) 585 + return true; 586 + } 587 + return false; 588 + } 589 + 590 + static int hwmon_pmu__config_term(const struct hwmon_pmu *hwm, 591 + struct perf_event_attr *attr, 592 + struct parse_events_term *term, 593 + struct parse_events_error *err) 594 + { 595 + if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) { 596 + enum hwmon_type type; 597 + int number; 598 + 599 + if (parse_hwmon_filename(term->config, &type, &number, 600 + /*item=*/NULL, /*is_alarm=*/NULL)) { 601 + if (number == -1) { 602 + /* 603 + * Item is of form <type>_ which means we should 604 + * match <type>_<label>. 605 + */ 606 + struct hashmap_entry *cur; 607 + size_t bkt; 608 + 609 + attr->config = 0; 610 + hashmap__for_each_entry((&hwm->events), cur, bkt) { 611 + union hwmon_pmu_event_key key = { 612 + .type_and_num = cur->key, 613 + }; 614 + struct hwmon_pmu_event_value *value = cur->pvalue; 615 + 616 + if (key.type == type && value->name && 617 + !strcasecmp(term->config, value->name)) { 618 + attr->config = key.type_and_num; 619 + break; 620 + } 621 + } 622 + if (attr->config == 0) 623 + return -EINVAL; 624 + } else { 625 + union hwmon_pmu_event_key key = { 626 + .type_and_num = 0, 627 + }; 628 + 629 + key.type = type; 630 + key.num = number; 631 + attr->config = key.type_and_num; 632 + } 633 + return 0; 634 + } 635 + } 636 + if (err) { 637 + char *err_str; 638 + 639 + parse_events_error__handle(err, term->err_val, 640 + asprintf(&err_str, 641 + "unexpected hwmon event term (%s) %s", 642 + parse_events__term_type_str(term->type_term), 643 + term->config) < 0 644 + ? strdup("unexpected hwmon event term") 645 + : err_str, 646 + NULL); 647 + } 648 + return -EINVAL; 649 + } 650 + 651 + int hwmon_pmu__config_terms(const struct perf_pmu *pmu, 652 + struct perf_event_attr *attr, 653 + struct parse_events_terms *terms, 654 + struct parse_events_error *err) 655 + { 656 + struct hwmon_pmu *hwm = container_of(pmu, struct hwmon_pmu, pmu); 657 + struct parse_events_term *term; 658 + int ret; 659 + 660 + ret = hwmon_pmu__read_events(hwm); 661 + if (ret) 662 + return ret; 663 + 664 + list_for_each_entry(term, &terms->terms, list) { 665 + if (hwmon_pmu__config_term(hwm, attr, term, err)) 666 + return -EINVAL; 667 + } 668 + 669 + return 0; 670 + 671 + } 672 + 673 + int hwmon_pmu__check_alias(struct parse_events_terms *terms, struct perf_pmu_info *info, 674 + struct parse_events_error *err) 675 + { 676 + struct parse_events_term *term = 677 + list_first_entry(&terms->terms, struct parse_events_term, list); 678 + 679 + if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) { 680 + enum hwmon_type type; 681 + int number; 682 + 683 + if (parse_hwmon_filename(term->config, &type, &number, 684 + /*item=*/NULL, /*is_alarm=*/NULL)) { 685 + info->unit = hwmon_units[type]; 686 + if (type == HWMON_TYPE_FAN || type == HWMON_TYPE_PWM || 687 + type == HWMON_TYPE_INTRUSION) 688 + info->scale = 1; 689 + else 690 + info->scale = 0.001; 691 + } 692 + return 0; 693 + } 694 + if (err) { 695 + char *err_str; 696 + 697 + parse_events_error__handle(err, term->err_val, 698 + asprintf(&err_str, 699 + "unexpected hwmon event term (%s) %s", 700 + parse_events__term_type_str(term->type_term), 701 + term->config) < 0 702 + ? strdup("unexpected hwmon event term") 703 + : err_str, 704 + NULL); 705 + } 706 + return -EINVAL; 707 + } 708 + 709 + int perf_pmus__read_hwmon_pmus(struct list_head *pmus) 710 + { 711 + char *line = NULL; 712 + DIR *class_hwmon_dir; 713 + struct dirent *class_hwmon_ent; 714 + char buf[PATH_MAX]; 715 + const char *sysfs = sysfs__mountpoint(); 716 + 717 + if (!sysfs) 718 + return 0; 719 + 720 + scnprintf(buf, sizeof(buf), "%s/class/hwmon/", sysfs); 721 + class_hwmon_dir = opendir(buf); 722 + if (!class_hwmon_dir) 723 + return 0; 724 + 725 + while ((class_hwmon_ent = readdir(class_hwmon_dir)) != NULL) { 726 + size_t line_len; 727 + int hwmon_dir, name_fd; 728 + struct io io; 729 + 730 + if (class_hwmon_ent->d_type != DT_LNK) 731 + continue; 732 + 733 + scnprintf(buf, sizeof(buf), "%s/class/hwmon/%s", sysfs, class_hwmon_ent->d_name); 734 + hwmon_dir = open(buf, O_DIRECTORY); 735 + if (hwmon_dir == -1) { 736 + pr_debug("hwmon_pmu: not a directory: '%s/class/hwmon/%s'\n", 737 + sysfs, class_hwmon_ent->d_name); 738 + continue; 739 + } 740 + name_fd = openat(hwmon_dir, "name", O_RDONLY); 741 + if (name_fd == -1) { 742 + pr_debug("hwmon_pmu: failure to open '%s/class/hwmon/%s/name'\n", 743 + sysfs, class_hwmon_ent->d_name); 744 + close(hwmon_dir); 745 + continue; 746 + } 747 + io__init(&io, name_fd, buf, sizeof(buf)); 748 + io__getline(&io, &line, &line_len); 749 + if (line_len > 0 && line[line_len - 1] == '\n') 750 + line[line_len - 1] = '\0'; 751 + hwmon_pmu__new(pmus, hwmon_dir, class_hwmon_ent->d_name, line); 752 + close(name_fd); 753 + } 754 + free(line); 755 + closedir(class_hwmon_dir); 756 + return 0; 757 + } 758 + 759 + #define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y)) 760 + 761 + int evsel__hwmon_pmu_open(struct evsel *evsel, 762 + struct perf_thread_map *threads, 763 + int start_cpu_map_idx, int end_cpu_map_idx) 764 + { 765 + struct hwmon_pmu *hwm = container_of(evsel->pmu, struct hwmon_pmu, pmu); 766 + union hwmon_pmu_event_key key = { 767 + .type_and_num = evsel->core.attr.config, 768 + }; 769 + int idx = 0, thread = 0, nthreads, err = 0; 770 + 771 + nthreads = perf_thread_map__nr(threads); 772 + for (idx = start_cpu_map_idx; idx < end_cpu_map_idx; idx++) { 773 + for (thread = 0; thread < nthreads; thread++) { 774 + char buf[64]; 775 + int fd; 776 + 777 + snprintf(buf, sizeof(buf), "%s%d_input", 778 + hwmon_type_strs[key.type], key.num); 779 + 780 + fd = openat(hwm->hwmon_dir_fd, buf, O_RDONLY); 781 + FD(evsel, idx, thread) = fd; 782 + if (fd < 0) { 783 + err = -errno; 784 + goto out_close; 785 + } 786 + } 787 + } 788 + return 0; 789 + out_close: 790 + if (err) 791 + threads->err_thread = thread; 792 + 793 + do { 794 + while (--thread >= 0) { 795 + if (FD(evsel, idx, thread) >= 0) 796 + close(FD(evsel, idx, thread)); 797 + FD(evsel, idx, thread) = -1; 798 + } 799 + thread = nthreads; 800 + } while (--idx >= 0); 801 + return err; 802 + } 803 + 804 + int evsel__hwmon_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) 805 + { 806 + char buf[32]; 807 + int fd; 808 + ssize_t len; 809 + struct perf_counts_values *count, *old_count = NULL; 810 + 811 + if (evsel->prev_raw_counts) 812 + old_count = perf_counts(evsel->prev_raw_counts, cpu_map_idx, thread); 813 + 814 + count = perf_counts(evsel->counts, cpu_map_idx, thread); 815 + fd = FD(evsel, cpu_map_idx, thread); 816 + len = pread(fd, buf, sizeof(buf), 0); 817 + if (len <= 0) { 818 + count->lost++; 819 + return -EINVAL; 820 + } 821 + buf[len] = '\0'; 822 + if (old_count) { 823 + count->val = old_count->val + strtoll(buf, NULL, 10); 824 + count->run = old_count->run + 1; 825 + count->ena = old_count->ena + 1; 826 + } else { 827 + count->val = strtoll(buf, NULL, 10); 828 + count->run++; 829 + count->ena++; 830 + } 831 + return 0; 832 + }
+151
tools/perf/util/hwmon_pmu.h
··· 1 + /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 2 + #ifndef __HWMON_PMU_H 3 + #define __HWMON_PMU_H 4 + 5 + #include "pmu.h" 6 + #include <stdbool.h> 7 + 8 + struct list_head; 9 + struct perf_thread_map; 10 + 11 + /** 12 + * enum hwmon_type: 13 + * 14 + * As described in Documentation/hwmon/sysfs-interface.rst hwmon events are 15 + * defined over multiple files of the form <type><num>_<item>. This enum 16 + * captures potential <type> values. 17 + * 18 + * This enum is exposed for testing. 19 + */ 20 + enum hwmon_type { 21 + HWMON_TYPE_NONE, 22 + 23 + HWMON_TYPE_CPU, 24 + HWMON_TYPE_CURR, 25 + HWMON_TYPE_ENERGY, 26 + HWMON_TYPE_FAN, 27 + HWMON_TYPE_HUMIDITY, 28 + HWMON_TYPE_IN, 29 + HWMON_TYPE_INTRUSION, 30 + HWMON_TYPE_POWER, 31 + HWMON_TYPE_PWM, 32 + HWMON_TYPE_TEMP, 33 + 34 + HWMON_TYPE_MAX 35 + }; 36 + 37 + /** 38 + * enum hwmon_item: 39 + * 40 + * Similar to enum hwmon_type but describes the item part of a a sysfs filename. 41 + * 42 + * This enum is exposed for testing. 43 + */ 44 + enum hwmon_item { 45 + HWMON_ITEM_NONE, 46 + 47 + HWMON_ITEM_ACCURACY, 48 + HWMON_ITEM_ALARM, 49 + HWMON_ITEM_AUTO_CHANNELS_TEMP, 50 + HWMON_ITEM_AVERAGE, 51 + HWMON_ITEM_AVERAGE_HIGHEST, 52 + HWMON_ITEM_AVERAGE_INTERVAL, 53 + HWMON_ITEM_AVERAGE_INTERVAL_MAX, 54 + HWMON_ITEM_AVERAGE_INTERVAL_MIN, 55 + HWMON_ITEM_AVERAGE_LOWEST, 56 + HWMON_ITEM_AVERAGE_MAX, 57 + HWMON_ITEM_AVERAGE_MIN, 58 + HWMON_ITEM_BEEP, 59 + HWMON_ITEM_CAP, 60 + HWMON_ITEM_CAP_HYST, 61 + HWMON_ITEM_CAP_MAX, 62 + HWMON_ITEM_CAP_MIN, 63 + HWMON_ITEM_CRIT, 64 + HWMON_ITEM_CRIT_HYST, 65 + HWMON_ITEM_DIV, 66 + HWMON_ITEM_EMERGENCY, 67 + HWMON_ITEM_EMERGENCY_HIST, 68 + HWMON_ITEM_ENABLE, 69 + HWMON_ITEM_FAULT, 70 + HWMON_ITEM_FREQ, 71 + HWMON_ITEM_HIGHEST, 72 + HWMON_ITEM_INPUT, 73 + HWMON_ITEM_LABEL, 74 + HWMON_ITEM_LCRIT, 75 + HWMON_ITEM_LCRIT_HYST, 76 + HWMON_ITEM_LOWEST, 77 + HWMON_ITEM_MAX, 78 + HWMON_ITEM_MAX_HYST, 79 + HWMON_ITEM_MIN, 80 + HWMON_ITEM_MIN_HYST, 81 + HWMON_ITEM_MOD, 82 + HWMON_ITEM_OFFSET, 83 + HWMON_ITEM_PULSES, 84 + HWMON_ITEM_RATED_MAX, 85 + HWMON_ITEM_RATED_MIN, 86 + HWMON_ITEM_RESET_HISTORY, 87 + HWMON_ITEM_TARGET, 88 + HWMON_ITEM_TYPE, 89 + HWMON_ITEM_VID, 90 + 91 + HWMON_ITEM__MAX, 92 + }; 93 + 94 + bool perf_pmu__is_hwmon(const struct perf_pmu *pmu); 95 + bool evsel__is_hwmon(const struct evsel *evsel); 96 + 97 + /** 98 + * parse_hwmon_filename() - Parse filename into constituent parts. 99 + * 100 + * @filename: To be parsed, of the form <type><number>_<item>. 101 + * @type: The type defined from the parsed file name. 102 + * @number: The number of the type, for example there may be more than 1 fan. 103 + * @item: A hwmon <type><number> may have multiple associated items. 104 + * @alarm: Is the filename for an alarm value? 105 + * 106 + * An example of a hwmon filename is "temp1_input". The type is temp for a 107 + * temperature value. The number is 1. The item within the file is an input 108 + * value - the temperature itself. This file doesn't contain an alarm value. 109 + * 110 + * Exposed for testing. 111 + */ 112 + bool parse_hwmon_filename(const char *filename, 113 + enum hwmon_type *type, 114 + int *number, 115 + enum hwmon_item *item, 116 + bool *alarm); 117 + 118 + /** 119 + * hwmon_pmu__new() - Allocate and construct a hwmon PMU. 120 + * 121 + * @pmus: The list of PMUs to be added to. 122 + * @hwmon_dir: An O_DIRECTORY file descriptor for a hwmon directory. 123 + * @sysfs_name: Name of the hwmon sysfs directory like hwmon0. 124 + * @name: The contents of the "name" file in the hwmon directory. 125 + * 126 + * Exposed for testing. Regular construction should happen via 127 + * perf_pmus__read_hwmon_pmus. 128 + */ 129 + struct perf_pmu *hwmon_pmu__new(struct list_head *pmus, int hwmon_dir, 130 + const char *sysfs_name, const char *name); 131 + void hwmon_pmu__exit(struct perf_pmu *pmu); 132 + 133 + int hwmon_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb); 134 + size_t hwmon_pmu__num_events(struct perf_pmu *pmu); 135 + bool hwmon_pmu__have_event(struct perf_pmu *pmu, const char *name); 136 + int hwmon_pmu__config_terms(const struct perf_pmu *pmu, 137 + struct perf_event_attr *attr, 138 + struct parse_events_terms *terms, 139 + struct parse_events_error *err); 140 + int hwmon_pmu__check_alias(struct parse_events_terms *terms, struct perf_pmu_info *info, 141 + struct parse_events_error *err); 142 + 143 + int perf_pmus__read_hwmon_pmus(struct list_head *pmus); 144 + 145 + 146 + int evsel__hwmon_pmu_open(struct evsel *evsel, 147 + struct perf_thread_map *threads, 148 + int start_cpu_map_idx, int end_cpu_map_idx); 149 + int evsel__hwmon_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread); 150 + 151 + #endif /* __HWMON_PMU_H */
+103 -23
tools/perf/util/include/dwarf-regs.h
··· 2 2 #ifndef _PERF_DWARF_REGS_H_ 3 3 #define _PERF_DWARF_REGS_H_ 4 4 #include "annotate.h" 5 + #include <elf.h> 6 + 7 + #ifndef EM_AARCH64 8 + #define EM_AARCH64 183 /* ARM 64 bit */ 9 + #endif 10 + 11 + #ifndef EM_CSKY 12 + #define EM_CSKY 252 /* C-SKY */ 13 + #endif 14 + #ifndef EF_CSKY_ABIV1 15 + #define EF_CSKY_ABIV1 0X10000000 16 + #endif 17 + #ifndef EF_CSKY_ABIV2 18 + #define EF_CSKY_ABIV2 0X20000000 19 + #endif 20 + 21 + #ifndef EM_LOONGARCH 22 + #define EM_LOONGARCH 258 /* LoongArch */ 23 + #endif 24 + 25 + /* EM_HOST gives the ELF machine for host, EF_HOST gives additional flags. */ 26 + #if defined(__x86_64__) 27 + #define EM_HOST EM_X86_64 28 + #elif defined(__i386__) 29 + #define EM_HOST EM_386 30 + #elif defined(__aarch64__) 31 + #define EM_HOST EM_AARCH64 32 + #elif defined(__arm__) 33 + #define EM_HOST EM_ARM 34 + #elif defined(__alpha__) 35 + #define EM_HOST EM_ALPHA 36 + #elif defined(__arc__) 37 + #define EM_HOST EM_ARC 38 + #elif defined(__AVR__) 39 + #define EM_HOST EM_AVR 40 + #elif defined(__AVR32__) 41 + #define EM_HOST EM_AVR32 42 + #elif defined(__bfin__) 43 + #define EM_HOST EM_BLACKFIN 44 + #elif defined(__csky__) 45 + #define EM_HOST EM_CSKY 46 + #if defined(__CSKYABIV2__) 47 + #define EF_HOST EF_CSKY_ABIV2 48 + #else 49 + #define EF_HOST EF_CSKY_ABIV1 50 + #endif 51 + #elif defined(__cris__) 52 + #define EM_HOST EM_CRIS 53 + #elif defined(__hppa__) // HP PA-RISC 54 + #define EM_HOST EM_PARISC 55 + #elif defined(__loongarch__) 56 + #define EM_HOST EM_LOONGARCH 57 + #elif defined(__mips__) 58 + #define EM_HOST EM_MIPS 59 + #elif defined(__m32r__) 60 + #define EM_HOST EM_M32R 61 + #elif defined(__microblaze__) 62 + #define EM_HOST EM_MICROBLAZE 63 + #elif defined(__MSP430__) 64 + #define EM_HOST EM_MSP430 65 + #elif defined(__powerpc64__) 66 + #define EM_HOST EM_PPC64 67 + #elif defined(__powerpc__) 68 + #define EM_HOST EM_PPC 69 + #elif defined(__riscv) 70 + #define EM_HOST EM_RISCV 71 + #elif defined(__s390x__) 72 + #define EM_HOST EM_S390 73 + #elif defined(__sh__) 74 + #define EM_HOST EM_SH 75 + #elif defined(__sparc64__) || defined(__sparc__) 76 + #define EM_HOST EM_SPARC 77 + #elif defined(__xtensa__) 78 + #define EM_HOST EM_XTENSA 79 + #else 80 + /* Unknown host ELF machine type. */ 81 + #define EM_HOST EM_NONE 82 + #endif 83 + 84 + #if !defined(EF_HOST) 85 + #define EF_HOST 0 86 + #endif 5 87 6 88 #define DWARF_REG_PC 0xd3af9c /* random number */ 7 89 #define DWARF_REG_FB 0xd3affb /* random number */ 8 90 9 - #ifdef HAVE_DWARF_SUPPORT 10 - const char *get_arch_regstr(unsigned int n); 11 - /* 12 - * get_dwarf_regstr - Returns ftrace register string from DWARF regnum 13 - * n: DWARF register number 14 - * machine: ELF machine signature (EM_*) 15 - */ 16 - const char *get_dwarf_regstr(unsigned int n, unsigned int machine); 91 + #ifdef HAVE_LIBDW_SUPPORT 92 + const char *get_csky_regstr(unsigned int n, unsigned int flags); 17 93 94 + /** 95 + * get_dwarf_regstr() - Returns ftrace register string from DWARF regnum. 96 + * @n: DWARF register number. 97 + * @machine: ELF machine signature (EM_*). 98 + * @flags: ELF flags for things like ABI differences. 99 + */ 100 + const char *get_dwarf_regstr(unsigned int n, unsigned int machine, unsigned int flags); 101 + 102 + int get_x86_regnum(const char *name); 103 + 104 + #if !defined(__x86_64__) && !defined(__i386__) 18 105 int get_arch_regnum(const char *name); 106 + #endif 107 + 19 108 /* 20 109 * get_dwarf_regnum - Returns DWARF regnum from register name 21 110 * name: architecture register name 22 111 * machine: ELF machine signature (EM_*) 23 112 */ 24 - int get_dwarf_regnum(const char *name, unsigned int machine); 113 + int get_dwarf_regnum(const char *name, unsigned int machine, unsigned int flags); 25 114 26 - #else /* HAVE_DWARF_SUPPORT */ 115 + void get_powerpc_regs(u32 raw_insn, int is_source, struct annotated_op_loc *op_loc); 116 + 117 + #else /* HAVE_LIBDW_SUPPORT */ 27 118 28 119 static inline int get_dwarf_regnum(const char *name __maybe_unused, 29 - unsigned int machine __maybe_unused) 120 + unsigned int machine __maybe_unused, 121 + unsigned int flags __maybe_unused) 30 122 { 31 123 return -1; 32 124 } 33 - #endif 34 125 35 - #if !defined(__powerpc__) || !defined(HAVE_DWARF_SUPPORT) 36 126 static inline void get_powerpc_regs(u32 raw_insn __maybe_unused, int is_source __maybe_unused, 37 127 struct annotated_op_loc *op_loc __maybe_unused) 38 128 { 39 129 return; 40 130 } 41 - #else 42 - void get_powerpc_regs(u32 raw_insn, int is_source, struct annotated_op_loc *op_loc); 43 131 #endif 44 132 45 - #ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET 46 - /* 47 - * Arch should support fetching the offset of a register in pt_regs 48 - * by its name. See kernel's regs_query_register_offset in 49 - * arch/xxx/kernel/ptrace.c. 50 - */ 51 - int regs_query_register_offset(const char *name); 52 - #endif 53 133 #endif
+2 -2
tools/perf/util/intel-bts.c
··· 100 100 else 101 101 sz = len; 102 102 printf("."); 103 - color_fprintf(stdout, color, " %08x: ", pos); 103 + color_fprintf(stdout, color, " %08zx: ", pos); 104 104 for (i = 0; i < sz; i++) 105 105 color_fprintf(stdout, color, " %02x", buf[i]); 106 106 for (; i < br_sz; i++) ··· 808 808 static const char * const intel_bts_info_fmts[] = { 809 809 [INTEL_BTS_PMU_TYPE] = " PMU Type %"PRId64"\n", 810 810 [INTEL_BTS_TIME_SHIFT] = " Time Shift %"PRIu64"\n", 811 - [INTEL_BTS_TIME_MULT] = " Time Muliplier %"PRIu64"\n", 811 + [INTEL_BTS_TIME_MULT] = " Time Multiplier %"PRIu64"\n", 812 812 [INTEL_BTS_TIME_ZERO] = " Time Zero %"PRIu64"\n", 813 813 [INTEL_BTS_CAP_USER_TIME_ZERO] = " Cap Time Zero %"PRId64"\n", 814 814 [INTEL_BTS_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n",
+2 -2
tools/perf/util/intel-pt.c
··· 249 249 else 250 250 pkt_len = 1; 251 251 printf("."); 252 - color_fprintf(stdout, color, " %08x: ", pos); 252 + color_fprintf(stdout, color, " %08zx: ", pos); 253 253 for (i = 0; i < pkt_len; i++) 254 254 color_fprintf(stdout, color, " %02x", buf[i]); 255 255 for (; i < 16; i++) ··· 4110 4110 static const char * const intel_pt_info_fmts[] = { 4111 4111 [INTEL_PT_PMU_TYPE] = " PMU Type %"PRId64"\n", 4112 4112 [INTEL_PT_TIME_SHIFT] = " Time Shift %"PRIu64"\n", 4113 - [INTEL_PT_TIME_MULT] = " Time Muliplier %"PRIu64"\n", 4113 + [INTEL_PT_TIME_MULT] = " Time Multiplier %"PRIu64"\n", 4114 4114 [INTEL_PT_TIME_ZERO] = " Time Zero %"PRIu64"\n", 4115 4115 [INTEL_PT_CAP_USER_TIME_ZERO] = " Cap Time Zero %"PRId64"\n", 4116 4116 [INTEL_PT_TSC_BIT] = " TSC bit %#"PRIx64"\n",
+1 -1
tools/perf/util/machine.c
··· 1343 1343 * we need to update the symtab_type if needed. 1344 1344 */ 1345 1345 if (m->comp && is_kmod_dso(dso)) { 1346 - dso__set_symtab_type(dso, dso__symtab_type(dso)); 1346 + dso__set_symtab_type(dso, dso__symtab_type(dso)+1); 1347 1347 dso__set_comp(dso, m->comp); 1348 1348 } 1349 1349 map__put(map);
+7 -1
tools/perf/util/mem-events.c
··· 366 366 }; 367 367 368 368 static const char * const mem_lvlnum[] = { 369 + [PERF_MEM_LVLNUM_L1] = "L1", 370 + [PERF_MEM_LVLNUM_L2] = "L2", 371 + [PERF_MEM_LVLNUM_L3] = "L3", 372 + [PERF_MEM_LVLNUM_L4] = "L4", 373 + [PERF_MEM_LVLNUM_L2_MHB] = "L2 MHB", 374 + [PERF_MEM_LVLNUM_MSC] = "Memory-side Cache", 369 375 [PERF_MEM_LVLNUM_UNC] = "Uncached", 370 376 [PERF_MEM_LVLNUM_CXL] = "CXL", 371 377 [PERF_MEM_LVLNUM_IO] = "I/O", ··· 454 448 if (mem_lvlnum[lvl]) 455 449 l += scnprintf(out + l, sz - l, mem_lvlnum[lvl]); 456 450 else 457 - l += scnprintf(out + l, sz - l, "L%d", lvl); 451 + l += scnprintf(out + l, sz - l, "Unknown level %d", lvl); 458 452 459 453 l += scnprintf(out + l, sz - l, " %s", hit_miss); 460 454 return l;
+20 -19
tools/perf/util/metricgroup.c
··· 14 14 #include "pmus.h" 15 15 #include "print-events.h" 16 16 #include "smt.h" 17 + #include "tool_pmu.h" 17 18 #include "expr.h" 18 19 #include "rblist.h" 19 20 #include <string.h> ··· 298 297 struct expr_id_data *val_ptr; 299 298 300 299 /* Don't match events for the wrong hybrid PMU. */ 301 - if (!all_pmus && ev->pmu_name && evsel__is_hybrid(ev) && 302 - strcmp(ev->pmu_name, pmu)) 300 + if (!all_pmus && ev->pmu && evsel__is_hybrid(ev) && 301 + strcmp(ev->pmu->name, pmu)) 303 302 continue; 304 303 /* 305 304 * Check for duplicate events with the same name. For ··· 674 673 struct hashmap_entry *cur; 675 674 size_t bkt; 676 675 bool no_group = true, has_tool_events = false; 677 - bool tool_events[PERF_TOOL_MAX] = {false}; 676 + bool tool_events[TOOL_PMU__EVENT_MAX] = {false}; 678 677 int ret = 0; 679 678 680 679 #define RETURN_IF_NON_ZERO(x) do { if (x) return x; } while (0) 681 680 682 681 hashmap__for_each_entry(ctx->ids, cur, bkt) { 683 682 const char *sep, *rsep, *id = cur->pkey; 684 - enum perf_tool_event ev; 683 + enum tool_pmu_event ev; 685 684 686 685 pr_debug("found event %s\n", id); 687 686 688 687 /* Always move tool events outside of the group. */ 689 - ev = perf_tool_event__from_str(id); 690 - if (ev != PERF_TOOL_NONE) { 688 + ev = tool_pmu__str_to_event(id); 689 + if (ev != TOOL_PMU__EVENT_NONE) { 691 690 has_tool_events = true; 692 691 tool_events[ev] = true; 693 692 continue; ··· 755 754 if (has_tool_events) { 756 755 int i; 757 756 758 - perf_tool_event__for_each_event(i) { 757 + tool_pmu__for_each_event(i) { 759 758 if (tool_events[i]) { 760 759 if (!no_group) { 761 760 ret = strbuf_addch(events, ','); 762 761 RETURN_IF_NON_ZERO(ret); 763 762 } 764 763 no_group = false; 765 - ret = strbuf_addstr(events, perf_tool_event__to_str(i)); 764 + ret = strbuf_addstr(events, tool_pmu__event_to_str(i)); 766 765 RETURN_IF_NON_ZERO(ret); 767 766 } 768 767 } ··· 1148 1147 int i, left_count, right_count; 1149 1148 1150 1149 left_count = hashmap__size(left->pctx->ids); 1151 - perf_tool_event__for_each_event(i) { 1152 - if (!expr__get_id(left->pctx, perf_tool_event__to_str(i), &data)) 1150 + tool_pmu__for_each_event(i) { 1151 + if (!expr__get_id(left->pctx, tool_pmu__event_to_str(i), &data)) 1153 1152 left_count--; 1154 1153 } 1155 1154 1156 1155 right_count = hashmap__size(right->pctx->ids); 1157 - perf_tool_event__for_each_event(i) { 1158 - if (!expr__get_id(right->pctx, perf_tool_event__to_str(i), &data)) 1156 + tool_pmu__for_each_event(i) { 1157 + if (!expr__get_id(right->pctx, tool_pmu__event_to_str(i), &data)) 1159 1158 right_count--; 1160 1159 } 1161 1160 ··· 1375 1374 * to true if tool event is found. 1376 1375 */ 1377 1376 static void find_tool_events(const struct list_head *metric_list, 1378 - bool tool_events[PERF_TOOL_MAX]) 1377 + bool tool_events[TOOL_PMU__EVENT_MAX]) 1379 1378 { 1380 1379 struct metric *m; 1381 1380 1382 1381 list_for_each_entry(m, metric_list, nd) { 1383 1382 int i; 1384 1383 1385 - perf_tool_event__for_each_event(i) { 1384 + tool_pmu__for_each_event(i) { 1386 1385 struct expr_id_data *data; 1387 1386 1388 1387 if (!tool_events[i] && 1389 - !expr__get_id(m->pctx, perf_tool_event__to_str(i), &data)) 1388 + !expr__get_id(m->pctx, tool_pmu__event_to_str(i), &data)) 1390 1389 tool_events[i] = true; 1391 1390 } 1392 1391 } ··· 1447 1446 */ 1448 1447 static int parse_ids(bool metric_no_merge, bool fake_pmu, 1449 1448 struct expr_parse_ctx *ids, const char *modifier, 1450 - bool group_events, const bool tool_events[PERF_TOOL_MAX], 1449 + bool group_events, const bool tool_events[TOOL_PMU__EVENT_MAX], 1451 1450 struct evlist **out_evlist) 1452 1451 { 1453 1452 struct parse_events_error parse_error; ··· 1472 1471 * event1 if #smt_on else 0 1473 1472 * Add a tool event to avoid a parse error on an empty string. 1474 1473 */ 1475 - perf_tool_event__for_each_event(i) { 1474 + tool_pmu__for_each_event(i) { 1476 1475 if (tool_events[i]) { 1477 - char *tmp = strdup(perf_tool_event__to_str(i)); 1476 + char *tmp = strdup(tool_pmu__event_to_str(i)); 1478 1477 1479 1478 if (!tmp) 1480 1479 return -ENOMEM; ··· 1536 1535 struct evlist *combined_evlist = NULL; 1537 1536 LIST_HEAD(metric_list); 1538 1537 struct metric *m; 1539 - bool tool_events[PERF_TOOL_MAX] = {false}; 1538 + bool tool_events[TOOL_PMU__EVENT_MAX] = {false}; 1540 1539 bool is_default = !strcmp(str, "Default"); 1541 1540 int ret; 1542 1541
+50 -75
tools/perf/util/parse-events.c
··· 228 228 bool init_attr, 229 229 const char *name, const char *metric_id, struct perf_pmu *pmu, 230 230 struct list_head *config_terms, bool auto_merge_stats, 231 - struct perf_cpu_map *cpu_list) 231 + struct perf_cpu_map *cpu_list, u64 alternate_hw_config) 232 232 { 233 233 struct evsel *evsel; 234 234 struct perf_cpu_map *cpus = perf_cpu_map__is_empty(cpu_list) && pmu ? pmu->cpus : cpu_list; ··· 263 263 evsel->core.is_pmu_core = pmu ? pmu->is_core : false; 264 264 evsel->auto_merge_stats = auto_merge_stats; 265 265 evsel->pmu = pmu; 266 - evsel->pmu_name = pmu ? strdup(pmu->name) : NULL; 266 + evsel->alternate_hw_config = alternate_hw_config; 267 267 268 268 if (name) 269 269 evsel->name = strdup(name); ··· 286 286 { 287 287 return __add_event(/*list=*/NULL, &idx, attr, /*init_attr=*/false, name, 288 288 metric_id, pmu, /*config_terms=*/NULL, 289 - /*auto_merge_stats=*/false, /*cpu_list=*/NULL); 289 + /*auto_merge_stats=*/false, /*cpu_list=*/NULL, 290 + /*alternate_hw_config=*/PERF_COUNT_HW_MAX); 290 291 } 291 292 292 293 static int add_event(struct list_head *list, int *idx, 293 294 struct perf_event_attr *attr, const char *name, 294 - const char *metric_id, struct list_head *config_terms) 295 + const char *metric_id, struct list_head *config_terms, 296 + u64 alternate_hw_config) 295 297 { 296 298 return __add_event(list, idx, attr, /*init_attr*/true, name, metric_id, 297 299 /*pmu=*/NULL, config_terms, 298 - /*auto_merge_stats=*/false, /*cpu_list=*/NULL) ? 0 : -ENOMEM; 299 - } 300 - 301 - static int add_event_tool(struct list_head *list, int *idx, 302 - enum perf_tool_event tool_event) 303 - { 304 - struct evsel *evsel; 305 - struct perf_event_attr attr = { 306 - .type = PERF_TYPE_SOFTWARE, 307 - .config = PERF_COUNT_SW_DUMMY, 308 - }; 309 - struct perf_cpu_map *cpu_list = NULL; 310 - 311 - if (tool_event == PERF_TOOL_DURATION_TIME) { 312 - /* Duration time is gathered globally, pretend it is only on CPU0. */ 313 - cpu_list = perf_cpu_map__new("0"); 314 - } 315 - evsel = __add_event(list, idx, &attr, /*init_attr=*/true, /*name=*/NULL, 316 - /*metric_id=*/NULL, /*pmu=*/NULL, 317 - /*config_terms=*/NULL, /*auto_merge_stats=*/false, 318 - cpu_list); 319 - perf_cpu_map__put(cpu_list); 320 - if (!evsel) 321 - return -ENOMEM; 322 - evsel->tool_event = tool_event; 323 - if (tool_event == PERF_TOOL_DURATION_TIME 324 - || tool_event == PERF_TOOL_USER_TIME 325 - || tool_event == PERF_TOOL_SYSTEM_TIME) { 326 - free((char *)evsel->unit); 327 - evsel->unit = strdup("ns"); 328 - } 329 - return 0; 300 + /*auto_merge_stats=*/false, /*cpu_list=*/NULL, 301 + alternate_hw_config) ? 0 : -ENOMEM; 330 302 } 331 303 332 304 /** ··· 422 450 static int parse_events_add_pmu(struct parse_events_state *parse_state, 423 451 struct list_head *list, struct perf_pmu *pmu, 424 452 const struct parse_events_terms *const_parsed_terms, 425 - bool auto_merge_stats); 453 + bool auto_merge_stats, u64 alternate_hw_config); 426 454 427 455 int parse_events_add_cache(struct list_head *list, int *idx, const char *name, 428 456 struct parse_events_state *parse_state, ··· 448 476 */ 449 477 ret = parse_events_add_pmu(parse_state, list, pmu, 450 478 parsed_terms, 451 - perf_pmu__auto_merge_stats(pmu)); 479 + perf_pmu__auto_merge_stats(pmu), 480 + /*alternate_hw_config=*/PERF_COUNT_HW_MAX); 452 481 if (ret) 453 482 return ret; 454 483 continue; ··· 480 507 481 508 if (__add_event(list, idx, &attr, /*init_attr*/true, config_name ?: name, 482 509 metric_id, pmu, &config_terms, /*auto_merge_stats=*/false, 483 - /*cpu_list=*/NULL) == NULL) 510 + /*cpu_list=*/NULL, 511 + /*alternate_hw_config=*/PERF_COUNT_HW_MAX) == NULL) 484 512 return -ENOMEM; 485 513 486 514 free_config_terms(&config_terms); ··· 746 772 name = get_config_name(head_config); 747 773 748 774 return add_event(list, &parse_state->idx, &attr, name, /*mertic_id=*/NULL, 749 - &config_terms); 775 + &config_terms, /*alternate_hw_config=*/PERF_COUNT_HW_MAX); 750 776 } 751 777 752 778 static int check_type_val(struct parse_events_term *term, ··· 768 794 769 795 static bool config_term_shrinked; 770 796 771 - static const char *config_term_name(enum parse_events__term_type term_type) 797 + const char *parse_events__term_type_str(enum parse_events__term_type term_type) 772 798 { 773 799 /* 774 800 * Update according to parse-events.l ··· 854 880 855 881 /* term_type is validated so indexing is safe */ 856 882 if (asprintf(&err_str, "'%s' is not usable in 'perf stat'", 857 - config_term_name(term_type)) >= 0) 883 + parse_events__term_type_str(term_type)) >= 0) 858 884 parse_events_error__handle(err, -1, err_str, NULL); 859 885 return false; 860 886 } ··· 978 1004 case PARSE_EVENTS__TERM_TYPE_HARDWARE: 979 1005 default: 980 1006 parse_events_error__handle(err, term->err_term, 981 - strdup(config_term_name(term->type_term)), 1007 + strdup(parse_events__term_type_str(term->type_term)), 982 1008 parse_events_formats_error_string(NULL)); 983 1009 return -EINVAL; 984 1010 } ··· 1046 1072 if (perf_pmu__have_event(pmu, term->config)) { 1047 1073 term->type_term = PARSE_EVENTS__TERM_TYPE_USER; 1048 1074 term->no_value = true; 1075 + term->alternate_hw_config = true; 1049 1076 } else { 1050 1077 attr->type = PERF_TYPE_HARDWARE; 1051 1078 attr->config = term->val.num; ··· 1102 1127 default: 1103 1128 if (err) { 1104 1129 parse_events_error__handle(err, term->err_term, 1105 - strdup(config_term_name(term->type_term)), 1106 - strdup("valid terms: call-graph,stack-size\n")); 1130 + strdup(parse_events__term_type_str(term->type_term)), 1131 + strdup("valid terms: call-graph,stack-size\n") 1132 + ); 1107 1133 } 1108 1134 return -EINVAL; 1109 1135 } ··· 1360 1384 name = get_config_name(head_config); 1361 1385 metric_id = get_config_metric_id(head_config); 1362 1386 ret = __add_event(list, &parse_state->idx, &attr, /*init_attr*/true, name, 1363 - metric_id, pmu, &config_terms, /*auto_merge_stats=*/false, 1364 - /*cpu_list=*/NULL) ? 0 : -ENOMEM; 1387 + metric_id, pmu, &config_terms, /*auto_merge_stats=*/false, 1388 + /*cpu_list=*/NULL, /*alternate_hw_config=*/PERF_COUNT_HW_MAX 1389 + ) == NULL ? -ENOMEM : 0; 1365 1390 free_config_terms(&config_terms); 1366 1391 return ret; 1367 1392 } ··· 1398 1421 type, /*extended_type=*/0, config, head_config); 1399 1422 } 1400 1423 1401 - int parse_events_add_tool(struct parse_events_state *parse_state, 1402 - struct list_head *list, 1403 - int tool_event) 1404 - { 1405 - return add_event_tool(list, &parse_state->idx, tool_event); 1406 - } 1407 - 1408 1424 static bool config_term_percore(struct list_head *config_terms) 1409 1425 { 1410 1426 struct evsel_config_term *term; ··· 1413 1443 static int parse_events_add_pmu(struct parse_events_state *parse_state, 1414 1444 struct list_head *list, struct perf_pmu *pmu, 1415 1445 const struct parse_events_terms *const_parsed_terms, 1416 - bool auto_merge_stats) 1446 + bool auto_merge_stats, u64 alternate_hw_config) 1417 1447 { 1418 1448 struct perf_event_attr attr; 1419 1449 struct perf_pmu_info info; ··· 1450 1480 /*init_attr=*/true, /*name=*/NULL, 1451 1481 /*metric_id=*/NULL, pmu, 1452 1482 /*config_terms=*/NULL, auto_merge_stats, 1453 - /*cpu_list=*/NULL); 1483 + /*cpu_list=*/NULL, alternate_hw_config); 1454 1484 return evsel ? 0 : -ENOMEM; 1455 1485 } 1456 1486 ··· 1471 1501 1472 1502 /* Look for event names in the terms and rewrite into format based terms. */ 1473 1503 if (perf_pmu__check_alias(pmu, &parsed_terms, 1474 - &info, &alias_rewrote_terms, err)) { 1504 + &info, &alias_rewrote_terms, 1505 + &alternate_hw_config, err)) { 1475 1506 parse_events_terms__exit(&parsed_terms); 1476 1507 return -EINVAL; 1477 1508 } ··· 1508 1537 return -ENOMEM; 1509 1538 } 1510 1539 1511 - if (perf_pmu__config(pmu, &attr, &parsed_terms, parse_state->error)) { 1540 + /* Skip configuring hard coded terms that were applied by config_attr. */ 1541 + if (perf_pmu__config(pmu, &attr, &parsed_terms, /*apply_hardcoded=*/false, 1542 + parse_state->error)) { 1512 1543 free_config_terms(&config_terms); 1513 1544 parse_events_terms__exit(&parsed_terms); 1514 1545 return -EINVAL; ··· 1519 1546 evsel = __add_event(list, &parse_state->idx, &attr, /*init_attr=*/true, 1520 1547 get_config_name(&parsed_terms), 1521 1548 get_config_metric_id(&parsed_terms), pmu, 1522 - &config_terms, auto_merge_stats, /*cpu_list=*/NULL); 1549 + &config_terms, auto_merge_stats, /*cpu_list=*/NULL, 1550 + alternate_hw_config); 1523 1551 if (!evsel) { 1524 1552 parse_events_terms__exit(&parsed_terms); 1525 1553 return -ENOMEM; ··· 1541 1567 } 1542 1568 1543 1569 int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 1544 - const char *event_name, 1570 + const char *event_name, u64 hw_config, 1545 1571 const struct parse_events_terms *const_parsed_terms, 1546 1572 struct list_head **listp, void *loc_) 1547 1573 { ··· 1594 1620 1595 1621 auto_merge_stats = perf_pmu__auto_merge_stats(pmu); 1596 1622 if (!parse_events_add_pmu(parse_state, list, pmu, 1597 - &parsed_terms, auto_merge_stats)) { 1623 + &parsed_terms, auto_merge_stats, hw_config)) { 1598 1624 struct strbuf sb; 1599 1625 1600 1626 strbuf_init(&sb, /*hint=*/ 0); ··· 1607 1633 1608 1634 if (parse_state->fake_pmu) { 1609 1635 if (!parse_events_add_pmu(parse_state, list, perf_pmus__fake_pmu(), &parsed_terms, 1610 - /*auto_merge_stats=*/true)) { 1636 + /*auto_merge_stats=*/true, hw_config)) { 1611 1637 struct strbuf sb; 1612 1638 1613 1639 strbuf_init(&sb, /*hint=*/ 0); ··· 1648 1674 /* Attempt to add to list assuming event_or_pmu is a PMU name. */ 1649 1675 pmu = perf_pmus__find(event_or_pmu); 1650 1676 if (pmu && !parse_events_add_pmu(parse_state, *listp, pmu, const_parsed_terms, 1651 - /*auto_merge_stats=*/false)) 1677 + /*auto_merge_stats=*/false, 1678 + /*alternate_hw_config=*/PERF_COUNT_HW_MAX)) 1652 1679 return 0; 1653 1680 1654 1681 if (parse_state->fake_pmu) { 1655 1682 if (!parse_events_add_pmu(parse_state, *listp, perf_pmus__fake_pmu(), 1656 1683 const_parsed_terms, 1657 - /*auto_merge_stats=*/false)) 1684 + /*auto_merge_stats=*/false, 1685 + /*alternate_hw_config=*/PERF_COUNT_HW_MAX)) 1658 1686 return 0; 1659 1687 } 1660 1688 ··· 1669 1693 1670 1694 if (!parse_events_add_pmu(parse_state, *listp, pmu, 1671 1695 const_parsed_terms, 1672 - auto_merge_stats)) { 1696 + auto_merge_stats, 1697 + /*alternate_hw_config=*/PERF_COUNT_HW_MAX)) { 1673 1698 ok++; 1674 1699 parse_state->wild_card_pmus = true; 1675 1700 } ··· 1681 1704 1682 1705 /* Failure to add, assume event_or_pmu is an event name. */ 1683 1706 zfree(listp); 1684 - if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, const_parsed_terms, listp, loc)) 1707 + if (!parse_events_multi_pmu_add(parse_state, event_or_pmu, PERF_COUNT_HW_MAX, 1708 + const_parsed_terms, listp, loc)) 1685 1709 return 0; 1686 1710 1687 1711 if (asprintf(&help, "Unable to find PMU or event on a PMU of '%s'", event_or_pmu) < 0) ··· 1733 1755 int exclude = eu | ek | eh; 1734 1756 int exclude_GH = group ? evsel->exclude_GH : 0; 1735 1757 1736 - if (mod.precise) { 1737 - /* use of precise requires exclude_guest */ 1738 - eG = 1; 1739 - } 1740 1758 if (mod.user) { 1741 1759 if (!exclude) 1742 1760 exclude = eu = ek = eh = 1; 1743 - if (!exclude_GH && !perf_guest) 1761 + if (!exclude_GH && !perf_guest && exclude_GH_default) 1744 1762 eG = 1; 1745 1763 eu = 0; 1746 1764 } ··· 2540 2566 struct parse_events_term temp = { 2541 2567 .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 2542 2568 .type_term = type_term, 2543 - .config = config ? : strdup(config_term_name(type_term)), 2569 + .config = config ? : strdup(parse_events__term_type_str(type_term)), 2544 2570 .no_value = no_value, 2545 2571 .err_term = loc_term ? loc_term->first_column : 0, 2546 2572 .err_val = loc_val ? loc_val->first_column : 0, ··· 2574 2600 void *loc_term, void *loc_val) 2575 2601 { 2576 2602 return parse_events_term__str(term, term_lhs, NULL, 2577 - strdup(config_term_name(term_rhs)), 2603 + strdup(parse_events__term_type_str(term_rhs)), 2578 2604 loc_term, loc_val); 2579 2605 } 2580 2606 ··· 2681 2707 if (ret < 0) 2682 2708 return ret; 2683 2709 } else if ((unsigned int)term->type_term < __PARSE_EVENTS__TERM_TYPE_NR) { 2684 - ret = strbuf_addf(sb, "%s=", config_term_name(term->type_term)); 2710 + ret = strbuf_addf(sb, "%s=", 2711 + parse_events__term_type_str(term->type_term)); 2685 2712 if (ret < 0) 2686 2713 return ret; 2687 2714 } ··· 2702 2727 2703 2728 buf[0] = '\0'; 2704 2729 for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) { 2705 - const char *name = config_term_name(i); 2730 + const char *name = parse_events__term_type_str(i); 2706 2731 2707 2732 if (!config_term_avail(i, NULL)) 2708 2733 continue;
+9 -4
tools/perf/util/parse-events.h
··· 127 127 * value is assumed to be 1. An event name also has no value. 128 128 */ 129 129 bool no_value; 130 + /** 131 + * @alternate_hw_config: config is the event name but num is an 132 + * alternate PERF_TYPE_HARDWARE config value which is often nice for the 133 + * sake of quick matching. 134 + */ 135 + bool alternate_hw_config; 130 136 }; 131 137 132 138 struct parse_events_error { ··· 167 161 /* Were multiple PMUs scanned to find events? */ 168 162 bool wild_card_pmus; 169 163 }; 164 + 165 + const char *parse_events__term_type_str(enum parse_events__term_type term_type); 170 166 171 167 bool parse_events__filter_pmu(const struct parse_events_state *parse_state, 172 168 const struct perf_pmu *pmu); ··· 229 221 u32 type, u64 config, 230 222 const struct parse_events_terms *head_config, 231 223 bool wildcard); 232 - int parse_events_add_tool(struct parse_events_state *parse_state, 233 - struct list_head *list, 234 - int tool_event); 235 224 int parse_events_add_cache(struct list_head *list, int *idx, const char *name, 236 225 struct parse_events_state *parse_state, 237 226 struct parse_events_terms *parsed_terms); ··· 243 238 struct perf_pmu *pmu); 244 239 245 240 int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 246 - const char *event_name, 241 + const char *event_name, u64 hw_config, 247 242 const struct parse_events_terms *const_parsed_terms, 248 243 struct list_head **listp, void *loc); 249 244
-11
tools/perf/util/parse-events.l
··· 121 121 return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW; 122 122 } 123 123 124 - static int tool(yyscan_t scanner, enum perf_tool_event event) 125 - { 126 - YYSTYPE *yylval = parse_events_get_lval(scanner); 127 - 128 - yylval->num = event; 129 - return PE_VALUE_SYM_TOOL; 130 - } 131 - 132 124 static int term(yyscan_t scanner, enum parse_events__term_type type) 133 125 { 134 126 YYSTYPE *yylval = parse_events_get_lval(scanner); ··· 396 404 alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } 397 405 emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 398 406 dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } 399 - duration_time { return tool(yyscanner, PERF_TOOL_DURATION_TIME); } 400 - user_time { return tool(yyscanner, PERF_TOOL_USER_TIME); } 401 - system_time { return tool(yyscanner, PERF_TOOL_SYSTEM_TIME); } 402 407 bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); } 403 408 cgroup-switches { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); } 404 409
+1 -17
tools/perf/util/parse-events.y
··· 56 56 57 57 %token PE_START_EVENTS PE_START_TERMS 58 58 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM 59 - %token PE_VALUE_SYM_TOOL 60 59 %token PE_EVENT_NAME 61 60 %token PE_RAW PE_NAME 62 61 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH ··· 67 68 %type <num> PE_VALUE 68 69 %type <num> PE_VALUE_SYM_HW 69 70 %type <num> PE_VALUE_SYM_SW 70 - %type <num> PE_VALUE_SYM_TOOL 71 71 %type <mod> PE_MODIFIER_EVENT 72 72 %type <term_type> PE_TERM 73 73 %type <num> value_sym ··· 290 292 struct list_head *list; 291 293 int err; 292 294 293 - err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1); 295 + err = parse_events_multi_pmu_add(_parse_state, $1, PERF_COUNT_HW_MAX, NULL, &list, &@1); 294 296 if (err < 0) { 295 297 struct parse_events_state *parse_state = _parse_state; 296 298 struct parse_events_error *error = parse_state->error; ··· 346 348 err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard); 347 349 if (err) 348 350 PE_ABORT(err); 349 - $$ = list; 350 - } 351 - | 352 - PE_VALUE_SYM_TOOL sep_slash_slash_dc 353 - { 354 - struct list_head *list; 355 - int err; 356 - 357 - list = alloc_list(); 358 - if (!list) 359 - YYNOMEM; 360 - err = parse_events_add_tool(_parse_state, list, $1); 361 - if (err) 362 - YYNOMEM; 363 351 $$ = list; 364 352 } 365 353
+2 -2
tools/perf/util/pfm.c
··· 233 233 } 234 234 235 235 if (is_libpfm_event_supported(name, cpus, threads)) { 236 - print_cb->print_event(print_state, pinfo->name, topic, 236 + print_cb->print_event(print_state, topic, pinfo->name, 237 237 name, info->equiv, 238 238 /*scale_unit=*/NULL, 239 239 /*deprecated=*/NULL, "PFM event", ··· 267 267 continue; 268 268 269 269 print_cb->print_event(print_state, 270 - pinfo->name, 271 270 topic, 271 + pinfo->name, 272 272 name, /*alias=*/NULL, 273 273 /*scale_unit=*/NULL, 274 274 /*deprecated=*/NULL, "PFM event",
+90 -47
tools/perf/util/pmu.c
··· 18 18 #include "debug.h" 19 19 #include "evsel.h" 20 20 #include "pmu.h" 21 + #include "hwmon_pmu.h" 21 22 #include "pmus.h" 23 + #include "tool_pmu.h" 22 24 #include <util/pmu-bison.h> 23 25 #include <util/pmu-flex.h> 24 26 #include "parse-events.h" ··· 819 817 return file_available(path); 820 818 } 821 819 822 - char *perf_pmu__getcpuid(struct perf_pmu *pmu) 823 - { 824 - char *cpuid; 825 - static bool printed; 826 - 827 - cpuid = getenv("PERF_CPUID"); 828 - if (cpuid) 829 - cpuid = strdup(cpuid); 830 - if (!cpuid) 831 - cpuid = get_cpuid_str(pmu); 832 - if (!cpuid) 833 - return NULL; 834 - 835 - if (!printed) { 836 - pr_debug("Using CPUID %s\n", cpuid); 837 - printed = true; 838 - } 839 - return cpuid; 840 - } 841 - 842 - __weak const struct pmu_metrics_table *pmu_metrics_table__find(void) 843 - { 844 - return perf_pmu__find_metrics_table(NULL); 845 - } 846 - 847 820 /** 848 821 * Return the length of the PMU name not including the suffix for uncore PMUs. 849 822 * ··· 1145 1168 return pmu; 1146 1169 } 1147 1170 1148 - static bool perf_pmu__is_fake(const struct perf_pmu *pmu) 1171 + bool perf_pmu__is_fake(const struct perf_pmu *pmu) 1149 1172 { 1150 1173 return pmu->type == PERF_PMU_TYPE_FAKE; 1151 1174 } ··· 1343 1366 struct perf_event_attr *attr, 1344 1367 struct parse_events_term *term, 1345 1368 struct parse_events_terms *head_terms, 1346 - bool zero, struct parse_events_error *err) 1369 + bool zero, bool apply_hardcoded, 1370 + struct parse_events_error *err) 1347 1371 { 1348 1372 struct perf_pmu_format *format; 1349 1373 __u64 *vp; ··· 1358 1380 return 0; 1359 1381 1360 1382 /* 1361 - * Hardcoded terms should be already in, so nothing 1362 - * to be done for them. 1383 + * Hardcoded terms are generally handled in event parsing, which 1384 + * traditionally have had to handle not having a PMU. An alias may 1385 + * have hard coded config values, optionally apply them below. 1363 1386 */ 1364 - if (parse_events__is_hardcoded_term(term)) 1387 + if (parse_events__is_hardcoded_term(term)) { 1388 + /* Config terms set all bits in the config. */ 1389 + DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); 1390 + 1391 + if (!apply_hardcoded) 1392 + return 0; 1393 + 1394 + bitmap_fill(bits, PERF_PMU_FORMAT_BITS); 1395 + 1396 + switch (term->type_term) { 1397 + case PARSE_EVENTS__TERM_TYPE_CONFIG: 1398 + assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); 1399 + pmu_format_value(bits, term->val.num, &attr->config, zero); 1400 + break; 1401 + case PARSE_EVENTS__TERM_TYPE_CONFIG1: 1402 + assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); 1403 + pmu_format_value(bits, term->val.num, &attr->config1, zero); 1404 + break; 1405 + case PARSE_EVENTS__TERM_TYPE_CONFIG2: 1406 + assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); 1407 + pmu_format_value(bits, term->val.num, &attr->config2, zero); 1408 + break; 1409 + case PARSE_EVENTS__TERM_TYPE_CONFIG3: 1410 + assert(term->type_val == PARSE_EVENTS__TERM_TYPE_NUM); 1411 + pmu_format_value(bits, term->val.num, &attr->config3, zero); 1412 + break; 1413 + case PARSE_EVENTS__TERM_TYPE_USER: /* Not hardcoded. */ 1414 + return -EINVAL; 1415 + case PARSE_EVENTS__TERM_TYPE_NAME ... PARSE_EVENTS__TERM_TYPE_HARDWARE: 1416 + /* Skip non-config terms. */ 1417 + break; 1418 + default: 1419 + break; 1420 + } 1365 1421 return 0; 1422 + } 1366 1423 1367 1424 format = pmu_find_format(&pmu->format, term->config); 1368 1425 if (!format) { ··· 1479 1466 if (err) { 1480 1467 char *err_str; 1481 1468 1482 - parse_events_error__handle(err, term->err_val, 1483 - asprintf(&err_str, 1484 - "value too big for format (%s), maximum is %llu", 1485 - format->name, (unsigned long long)max_val) < 0 1486 - ? strdup("value too big for format") 1487 - : err_str, 1488 - NULL); 1469 + if (asprintf(&err_str, 1470 + "value too big for format (%s), maximum is %llu", 1471 + format->name, (unsigned long long)max_val) < 0) { 1472 + err_str = strdup("value too big for format"); 1473 + } 1474 + parse_events_error__handle(err, term->err_val, err_str, /*help=*/NULL); 1489 1475 return -EINVAL; 1490 1476 } 1491 1477 /* ··· 1500 1488 int perf_pmu__config_terms(const struct perf_pmu *pmu, 1501 1489 struct perf_event_attr *attr, 1502 1490 struct parse_events_terms *terms, 1503 - bool zero, struct parse_events_error *err) 1491 + bool zero, bool apply_hardcoded, 1492 + struct parse_events_error *err) 1504 1493 { 1505 1494 struct parse_events_term *term; 1506 1495 1496 + if (perf_pmu__is_hwmon(pmu)) 1497 + return hwmon_pmu__config_terms(pmu, attr, terms, err); 1498 + 1507 1499 list_for_each_entry(term, &terms->terms, list) { 1508 - if (pmu_config_term(pmu, attr, term, terms, zero, err)) 1500 + if (pmu_config_term(pmu, attr, term, terms, zero, apply_hardcoded, err)) 1509 1501 return -EINVAL; 1510 1502 } 1511 1503 ··· 1523 1507 */ 1524 1508 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 1525 1509 struct parse_events_terms *head_terms, 1510 + bool apply_hardcoded, 1526 1511 struct parse_events_error *err) 1527 1512 { 1528 1513 bool zero = !!pmu->perf_event_attr_init_default; ··· 1532 1515 if (perf_pmu__is_fake(pmu)) 1533 1516 return 0; 1534 1517 1535 - return perf_pmu__config_terms(pmu, attr, head_terms, zero, err); 1518 + return perf_pmu__config_terms(pmu, attr, head_terms, zero, apply_hardcoded, err); 1536 1519 } 1537 1520 1538 1521 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, ··· 1623 1606 */ 1624 1607 int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms, 1625 1608 struct perf_pmu_info *info, bool *rewrote_terms, 1626 - struct parse_events_error *err) 1609 + u64 *alternate_hw_config, struct parse_events_error *err) 1627 1610 { 1628 1611 struct parse_events_term *term, *h; 1629 1612 struct perf_pmu_alias *alias; ··· 1640 1623 info->scale = 0.0; 1641 1624 info->snapshot = false; 1642 1625 1626 + if (perf_pmu__is_hwmon(pmu)) { 1627 + ret = hwmon_pmu__check_alias(head_terms, info, err); 1628 + goto out; 1629 + } 1630 + 1643 1631 /* Fake PMU doesn't rewrite terms. */ 1644 1632 if (perf_pmu__is_fake(pmu)) 1645 1633 goto out; ··· 1660 1638 NULL); 1661 1639 return ret; 1662 1640 } 1641 + 1663 1642 *rewrote_terms = true; 1664 1643 ret = check_info_data(pmu, alias, info, err, term->err_term); 1665 1644 if (ret) ··· 1668 1645 1669 1646 if (alias->per_pkg) 1670 1647 info->per_pkg = true; 1648 + 1649 + if (term->alternate_hw_config) 1650 + *alternate_hw_config = term->val.num; 1671 1651 1672 1652 list_del_init(&term->list); 1673 1653 parse_events_term__delete(term); ··· 1816 1790 { 1817 1791 if (!name) 1818 1792 return false; 1793 + if (perf_pmu__is_tool(pmu) && tool_pmu__skip_event(name)) 1794 + return false; 1795 + if (perf_pmu__is_hwmon(pmu)) 1796 + return hwmon_pmu__have_event(pmu, name); 1819 1797 if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL) 1820 1798 return true; 1821 1799 if (pmu->cpu_aliases_added || !pmu->events_table) ··· 1831 1801 { 1832 1802 size_t nr; 1833 1803 1804 + if (perf_pmu__is_hwmon(pmu)) 1805 + return hwmon_pmu__num_events(pmu); 1806 + 1834 1807 pmu_aliases_parse(pmu); 1835 1808 nr = pmu->sysfs_aliases + pmu->sys_json_aliases; 1836 1809 ··· 1843 1810 nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->cpu_json_aliases; 1844 1811 else 1845 1812 assert(pmu->cpu_json_aliases == 0); 1813 + 1814 + if (perf_pmu__is_tool(pmu)) 1815 + nr -= tool_pmu__num_skip_events(); 1846 1816 1847 1817 return pmu->selectable ? nr + 1 : nr; 1848 1818 } ··· 1897 1861 int ret = 0; 1898 1862 struct strbuf sb; 1899 1863 1864 + if (perf_pmu__is_hwmon(pmu)) 1865 + return hwmon_pmu__for_each_event(pmu, state, cb); 1866 + 1900 1867 strbuf_init(&sb, /*hint=*/ 0); 1901 1868 pmu_aliases_parse(pmu); 1902 1869 pmu_add_cpu_aliases(pmu); 1903 1870 list_for_each_entry(event, &pmu->aliases, list) { 1904 1871 size_t buf_used, pmu_name_len; 1872 + 1873 + if (perf_pmu__is_tool(pmu) && tool_pmu__skip_event(event->name)) 1874 + continue; 1905 1875 1906 1876 info.pmu_name = event->pmu_name ?: pmu->name; 1907 1877 pmu_name_len = pmu_deduped_name_len(pmu, info.pmu_name, ··· 1991 1949 case PERF_TYPE_HW_CACHE: return false; 1992 1950 case PERF_TYPE_RAW: return false; 1993 1951 case PERF_TYPE_BREAKPOINT: return true; 1952 + case PERF_PMU_TYPE_TOOL: return true; 1994 1953 default: break; 1995 1954 } 1996 1955 for (size_t i = 0; i < ARRAY_SIZE(known_sw_pmus); i++) { ··· 2243 2200 (need_fnmatch && !fnmatch(tok, name, 0)); 2244 2201 } 2245 2202 2246 - double __weak perf_pmu__cpu_slots_per_cycle(void) 2247 - { 2248 - return NAN; 2249 - } 2250 - 2251 2203 int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size) 2252 2204 { 2253 2205 const char *sysfs = sysfs__mountpoint(); ··· 2295 2257 2296 2258 void perf_pmu__delete(struct perf_pmu *pmu) 2297 2259 { 2260 + if (perf_pmu__is_hwmon(pmu)) 2261 + hwmon_pmu__exit(pmu); 2262 + 2298 2263 perf_pmu__del_formats(&pmu->format); 2299 2264 perf_pmu__del_aliases(pmu); 2300 2265 perf_pmu__del_caps(pmu); ··· 2321 2280 pmu_add_cpu_aliases(pmu); 2322 2281 list_for_each_entry(event, &pmu->aliases, list) { 2323 2282 struct perf_event_attr attr = {.config = 0,}; 2324 - int ret = perf_pmu__config(pmu, &attr, &event->terms, NULL); 2283 + 2284 + int ret = perf_pmu__config(pmu, &attr, &event->terms, /*apply_hardcoded=*/true, 2285 + /*err=*/NULL); 2325 2286 2326 2287 if (ret == 0 && config == attr.config) 2327 2288 return event->name;
+13 -5
tools/perf/util/pmu.h
··· 37 37 }; 38 38 39 39 enum { 40 + PERF_PMU_TYPE_HWMON_START = 0xFFFF0000, 41 + PERF_PMU_TYPE_HWMON_END = 0xFFFFFFFD, 42 + PERF_PMU_TYPE_TOOL = 0xFFFFFFFE, 40 43 PERF_PMU_TYPE_FAKE = 0xFFFFFFFF, 41 44 }; 42 45 ··· 172 169 * exclude_host. 173 170 */ 174 171 bool exclude_guest; 172 + /** 173 + * @checked: Are the missing features checked? 174 + */ 175 + bool checked; 175 176 } missing_features; 176 177 177 178 /** ··· 213 206 void pmu_add_sys_aliases(struct perf_pmu *pmu); 214 207 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 215 208 struct parse_events_terms *head_terms, 209 + bool apply_hardcoded, 216 210 struct parse_events_error *error); 217 211 int perf_pmu__config_terms(const struct perf_pmu *pmu, 218 212 struct perf_event_attr *attr, 219 213 struct parse_events_terms *terms, 220 - bool zero, struct parse_events_error *error); 214 + bool zero, bool apply_hardcoded, 215 + struct parse_events_error *error); 221 216 __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name); 222 217 int perf_pmu__format_type(struct perf_pmu *pmu, const char *name); 223 218 int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms, 224 219 struct perf_pmu_info *info, bool *rewrote_terms, 225 - struct parse_events_error *err); 220 + u64 *alternate_hw_config, struct parse_events_error *err); 226 221 int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb); 227 222 228 223 void perf_pmu_format__set_value(void *format, int config, unsigned long *bits); ··· 262 253 void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, 263 254 const struct pmu_events_table *table); 264 255 265 - char *perf_pmu__getcpuid(struct perf_pmu *pmu); 266 - const struct pmu_metrics_table *pmu_metrics_table__find(void); 267 256 bool pmu_uncore_identifier_match(const char *compat, const char *id); 268 257 269 258 int perf_pmu__convert_scale(const char *scale, char **end, double *sval); ··· 275 268 276 269 bool perf_pmu__match(const struct perf_pmu *pmu, const char *tok); 277 270 278 - double perf_pmu__cpu_slots_per_cycle(void); 279 271 int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size); 280 272 int perf_pmu__pathname_scnprintf(char *buf, size_t size, 281 273 const char *pmu_name, const char *filename); ··· 286 280 struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus); 287 281 void perf_pmu__delete(struct perf_pmu *pmu); 288 282 struct perf_pmu *perf_pmus__find_core_pmu(void); 283 + 289 284 const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config); 285 + bool perf_pmu__is_fake(const struct perf_pmu *pmu); 290 286 291 287 #endif /* __PMU_H */
+17 -1
tools/perf/util/pmus.c
··· 15 15 #include "evsel.h" 16 16 #include "pmus.h" 17 17 #include "pmu.h" 18 + #include "hwmon_pmu.h" 19 + #include "tool_pmu.h" 18 20 #include "print-events.h" 19 21 #include "strbuf.h" 20 22 ··· 202 200 int fd; 203 201 DIR *dir; 204 202 struct dirent *dent; 203 + struct perf_pmu *tool_pmu; 205 204 206 205 if (read_sysfs_all_pmus || (core_only && read_sysfs_core_pmus)) 207 206 return; ··· 232 229 pr_err("Failure to set up any core PMUs\n"); 233 230 } 234 231 list_sort(NULL, &core_pmus, pmus_cmp); 232 + if (!core_only) { 233 + tool_pmu = perf_pmus__tool_pmu(); 234 + list_add_tail(&tool_pmu->list, &other_pmus); 235 + perf_pmus__read_hwmon_pmus(&other_pmus); 236 + } 235 237 list_sort(NULL, &other_pmus, pmus_cmp); 236 238 if (!list_empty(&core_pmus)) { 237 239 read_sysfs_core_pmus = true; ··· 442 434 pr_err("Unexpected event %s/%s/\n", info->pmu->name, info->name); 443 435 return 1; 444 436 } 437 + assert(info->pmu != NULL || info->name != NULL); 445 438 s = &state->aliases[state->index]; 446 439 s->pmu = info->pmu; 447 440 #define COPY_STR(str) s->str = info->str ? strdup(info->str) : NULL ··· 503 494 goto free; 504 495 505 496 print_cb->print_event(print_state, 506 - aliases[j].pmu_name, 507 497 aliases[j].topic, 498 + aliases[j].pmu_name, 508 499 aliases[j].name, 509 500 aliases[j].alias, 510 501 aliases[j].scale_unit, ··· 731 722 * format files. 732 723 */ 733 724 return perf_pmu__lookup(&other_pmus, test_sysfs_dirfd, name, /*eager_load=*/true); 725 + } 726 + 727 + struct perf_pmu *perf_pmus__add_test_hwmon_pmu(int hwmon_dir, 728 + const char *sysfs_name, 729 + const char *name) 730 + { 731 + return hwmon_pmu__new(&other_pmus, hwmon_dir, sysfs_name, name); 734 732 } 735 733 736 734 struct perf_pmu *perf_pmus__fake_pmu(void)
+3
tools/perf/util/pmus.h
··· 30 30 char *perf_pmus__default_pmu_name(void); 31 31 32 32 struct perf_pmu *perf_pmus__add_test_pmu(int test_sysfs_dirfd, const char *name); 33 + struct perf_pmu *perf_pmus__add_test_hwmon_pmu(int hwmon_dir, 34 + const char *sysfs_name, 35 + const char *name); 33 36 struct perf_pmu *perf_pmus__fake_pmu(void); 34 37 35 38 #endif /* __PMUS_H */
+1 -35
tools/perf/util/print-events.c
··· 29 29 #include "tracepoint.h" 30 30 #include "pfm.h" 31 31 #include "thread_map.h" 32 + #include "tool_pmu.h" 32 33 #include "util.h" 33 34 34 35 #define MAX_NAME_LEN 100 ··· 42 41 "Hardware cache event", 43 42 "Raw event descriptor", 44 43 "Hardware breakpoint", 45 - }; 46 - 47 - static const struct event_symbol event_symbols_tool[PERF_TOOL_MAX] = { 48 - [PERF_TOOL_DURATION_TIME] = { 49 - .symbol = "duration_time", 50 - .alias = "", 51 - }, 52 - [PERF_TOOL_USER_TIME] = { 53 - .symbol = "user_time", 54 - .alias = "", 55 - }, 56 - [PERF_TOOL_SYSTEM_TIME] = { 57 - .symbol = "system_time", 58 - .alias = "", 59 - }, 60 44 }; 61 45 62 46 /* ··· 327 341 return 0; 328 342 } 329 343 330 - void print_tool_events(const struct print_callbacks *print_cb, void *print_state) 331 - { 332 - // Start at 1 because the first enum entry means no tool event. 333 - for (int i = 1; i < PERF_TOOL_MAX; ++i) { 334 - print_cb->print_event(print_state, 335 - "tool", 336 - /*pmu_name=*/NULL, 337 - event_symbols_tool[i].symbol, 338 - event_symbols_tool[i].alias, 339 - /*scale_unit=*/NULL, 340 - /*deprecated=*/false, 341 - "Tool event", 342 - /*desc=*/NULL, 343 - /*long_desc=*/NULL, 344 - /*encoding_desc=*/NULL); 345 - } 346 - } 347 - 348 344 void print_symbol_events(const struct print_callbacks *print_cb, void *print_state, 349 345 unsigned int type, const struct event_symbol *syms, 350 346 unsigned int max) ··· 389 421 event_symbols_hw, PERF_COUNT_HW_MAX); 390 422 print_symbol_events(print_cb, print_state, PERF_TYPE_SOFTWARE, 391 423 event_symbols_sw, PERF_COUNT_SW_MAX); 392 - 393 - print_tool_events(print_cb, print_state); 394 424 395 425 print_hwcache_events(print_cb, print_state); 396 426
-1
tools/perf/util/print-events.h
··· 36 36 void print_symbol_events(const struct print_callbacks *print_cb, void *print_state, 37 37 unsigned int type, const struct event_symbol *syms, 38 38 unsigned int max); 39 - void print_tool_events(const struct print_callbacks *print_cb, void *print_state); 40 39 void print_tracepoint_events(const struct print_callbacks *print_cb, void *print_state); 41 40 bool is_event_supported(u8 type, u64 config); 42 41
+89 -93
tools/perf/util/probe-event.c
··· 40 40 #include "session.h" 41 41 #include "string2.h" 42 42 #include "strbuf.h" 43 + #include "parse-events.h" 43 44 44 45 #include <subcmd/pager.h> 45 46 #include <linux/ctype.h> ··· 51 50 #endif 52 51 53 52 #define PERFPROBE_GROUP "probe" 53 + 54 + /* Defined in kernel/trace/trace.h */ 55 + #define MAX_EVENT_NAME_LEN 64 54 56 55 57 bool probe_event_dry_run; /* Dry run flag */ 56 58 struct probe_conf probe_conf = { .magic_num = DEFAULT_PROBE_MAGIC_NUM }; ··· 346 342 return mod_name; 347 343 } 348 344 349 - #ifdef HAVE_DWARF_SUPPORT 345 + #ifdef HAVE_LIBDW_SUPPORT 350 346 351 347 static int kernel_get_module_dso(const char *module, struct dso **pdso) 352 348 { ··· 1040 1036 return rv; 1041 1037 } 1042 1038 1039 + static int sprint_line_description(char *sbuf, size_t size, struct line_range *lr) 1040 + { 1041 + if (!lr->function) 1042 + return snprintf(sbuf, size, "file: %s, line: %d", lr->file, lr->start); 1043 + 1044 + if (lr->file) 1045 + return snprintf(sbuf, size, "function: %s, file:%s, line: %d", lr->function, lr->file, lr->start); 1046 + 1047 + return snprintf(sbuf, size, "function: %s, line:%d", lr->function, lr->start); 1048 + } 1049 + 1043 1050 #define show_one_line_with_num(f,l) _show_one_line(f,l,false,true) 1044 1051 #define show_one_line(f,l) _show_one_line(f,l,false,false) 1045 1052 #define skip_one_line(f,l) _show_one_line(f,l,true,false) ··· 1080 1065 1081 1066 ret = debuginfo__find_line_range(dinfo, lr); 1082 1067 if (!ret) { /* Not found, retry with an alternative */ 1068 + pr_debug2("Failed to find line range in debuginfo. Fallback to alternative\n"); 1083 1069 ret = get_alternative_line_range(dinfo, lr, module, user); 1084 1070 if (!ret) 1085 1071 ret = debuginfo__find_line_range(dinfo, lr); 1072 + else /* Ignore error, we just failed to find it. */ 1073 + ret = -ENOENT; 1086 1074 } 1087 1075 if (dinfo->build_id) { 1088 1076 build_id__init(&bid, dinfo->build_id, BUILD_ID_SIZE); ··· 1093 1075 } 1094 1076 debuginfo__delete(dinfo); 1095 1077 if (ret == 0 || ret == -ENOENT) { 1096 - pr_warning("Specified source line is not found.\n"); 1078 + sprint_line_description(sbuf, sizeof(sbuf), lr); 1079 + pr_warning("Specified source line(%s) is not found.\n", sbuf); 1097 1080 return -ENOENT; 1098 1081 } else if (ret < 0) { 1099 1082 pr_warning("Debuginfo analysis failed.\n"); ··· 1269 1250 return ret; 1270 1251 } 1271 1252 1272 - #else /* !HAVE_DWARF_SUPPORT */ 1253 + #else /* !HAVE_LIBDW_SUPPORT */ 1273 1254 1274 1255 static void debuginfo_cache__exit(void) 1275 1256 { ··· 1362 1343 * 1363 1344 * SRC[:SLN[+NUM|-ELN]] 1364 1345 * FNC[@SRC][:SLN[+NUM|-ELN]] 1346 + * 1347 + * FNC@SRC accepts `FNC@*` which forcibly specify FNC as function name. 1348 + * SRC and FUNC can be quoted by double/single quotes. 1365 1349 */ 1366 1350 int parse_line_range_desc(const char *arg, struct line_range *lr) 1367 1351 { 1368 - char *range, *file, *name = strdup(arg); 1352 + char *buf = strdup(arg); 1353 + char *p; 1369 1354 int err; 1370 1355 1371 - if (!name) 1356 + if (!buf) 1372 1357 return -ENOMEM; 1373 1358 1374 1359 lr->start = 0; 1375 1360 lr->end = INT_MAX; 1376 1361 1377 - range = strchr(name, ':'); 1378 - if (range) { 1379 - *range++ = '\0'; 1362 + p = strpbrk_esq(buf, ":"); 1363 + if (p) { 1364 + if (p == buf) { 1365 + semantic_error("No file/function name in '%s'.\n", p); 1366 + err = -EINVAL; 1367 + goto err; 1368 + } 1369 + *(p++) = '\0'; 1380 1370 1381 - err = parse_line_num(&range, &lr->start, "start line"); 1371 + err = parse_line_num(&p, &lr->start, "start line"); 1382 1372 if (err) 1383 1373 goto err; 1384 1374 1385 - if (*range == '+' || *range == '-') { 1386 - const char c = *range++; 1375 + if (*p == '+' || *p == '-') { 1376 + const char c = *(p++); 1387 1377 1388 - err = parse_line_num(&range, &lr->end, "end line"); 1378 + err = parse_line_num(&p, &lr->end, "end line"); 1389 1379 if (err) 1390 1380 goto err; 1391 1381 ··· 1418 1390 " than end line.\n"); 1419 1391 goto err; 1420 1392 } 1421 - if (*range != '\0') { 1422 - semantic_error("Tailing with invalid str '%s'.\n", range); 1393 + if (*p != '\0') { 1394 + semantic_error("Tailing with invalid str '%s'.\n", p); 1423 1395 goto err; 1424 1396 } 1425 1397 } 1426 1398 1427 - file = strchr(name, '@'); 1428 - if (file) { 1429 - *file = '\0'; 1430 - lr->file = strdup(++file); 1431 - if (lr->file == NULL) { 1432 - err = -ENOMEM; 1399 + p = strpbrk_esq(buf, "@"); 1400 + if (p) { 1401 + *p++ = '\0'; 1402 + if (strcmp(p, "*")) { 1403 + lr->file = strdup_esq(p); 1404 + if (lr->file == NULL) { 1405 + err = -ENOMEM; 1406 + goto err; 1407 + } 1408 + } 1409 + if (*buf != '\0') 1410 + lr->function = strdup_esq(buf); 1411 + if (!lr->function && !lr->file) { 1412 + semantic_error("Only '@*' is not allowed.\n"); 1413 + err = -EINVAL; 1433 1414 goto err; 1434 1415 } 1435 - lr->function = name; 1436 - } else if (strchr(name, '/') || strchr(name, '.')) 1437 - lr->file = name; 1438 - else if (is_c_func_name(name))/* We reuse it for checking funcname */ 1439 - lr->function = name; 1416 + } else if (strpbrk_esq(buf, "/.")) 1417 + lr->file = strdup_esq(buf); 1418 + else if (is_c_func_name(buf))/* We reuse it for checking funcname */ 1419 + lr->function = strdup_esq(buf); 1440 1420 else { /* Invalid name */ 1441 - semantic_error("'%s' is not a valid function name.\n", name); 1421 + semantic_error("'%s' is not a valid function name.\n", buf); 1442 1422 err = -EINVAL; 1443 1423 goto err; 1444 1424 } 1445 1425 1446 - return 0; 1447 1426 err: 1448 - free(name); 1427 + free(buf); 1449 1428 return err; 1450 1429 } 1451 1430 ··· 1460 1425 { 1461 1426 char *ptr; 1462 1427 1463 - ptr = strpbrk_esc(*arg, ":"); 1428 + ptr = strpbrk_esq(*arg, ":"); 1464 1429 if (ptr) { 1465 1430 *ptr = '\0'; 1466 1431 if (!pev->sdt && !is_c_func_name(*arg)) 1467 1432 goto ng_name; 1468 - pev->group = strdup_esc(*arg); 1433 + pev->group = strdup_esq(*arg); 1469 1434 if (!pev->group) 1470 1435 return -ENOMEM; 1471 1436 *arg = ptr + 1; 1472 1437 } else 1473 1438 pev->group = NULL; 1474 1439 1475 - pev->event = strdup_esc(*arg); 1440 + pev->event = strdup_esq(*arg); 1476 1441 if (pev->event == NULL) 1477 1442 return -ENOMEM; 1478 1443 ··· 1511 1476 arg++; 1512 1477 } 1513 1478 1514 - ptr = strpbrk_esc(arg, ";=@+%"); 1479 + ptr = strpbrk_esq(arg, ";=@+%"); 1515 1480 if (pev->sdt) { 1516 1481 if (ptr) { 1517 1482 if (*ptr != '@') { ··· 1525 1490 pev->target = build_id_cache__origname(tmp); 1526 1491 free(tmp); 1527 1492 } else 1528 - pev->target = strdup_esc(ptr + 1); 1493 + pev->target = strdup_esq(ptr + 1); 1529 1494 if (!pev->target) 1530 1495 return -ENOMEM; 1531 1496 *ptr = '\0'; ··· 1566 1531 file_spec = true; 1567 1532 } 1568 1533 1569 - ptr = strpbrk_esc(arg, ";:+@%"); 1534 + ptr = strpbrk_esq(arg, ";:+@%"); 1570 1535 if (ptr) { 1571 1536 nc = *ptr; 1572 1537 *ptr++ = '\0'; ··· 1575 1540 if (arg[0] == '\0') 1576 1541 tmp = NULL; 1577 1542 else { 1578 - tmp = strdup_esc(arg); 1543 + tmp = strdup_esq(arg); 1579 1544 if (tmp == NULL) 1580 1545 return -ENOMEM; 1581 1546 } ··· 1613 1578 return -ENOMEM; 1614 1579 break; 1615 1580 } 1616 - ptr = strpbrk_esc(arg, ";:+@%"); 1581 + ptr = strpbrk_esq(arg, ";:+@%"); 1617 1582 if (ptr) { 1618 1583 nc = *ptr; 1619 1584 *ptr++ = '\0'; ··· 1640 1605 semantic_error("SRC@SRC is not allowed.\n"); 1641 1606 return -EINVAL; 1642 1607 } 1643 - pp->file = strdup_esc(arg); 1608 + if (!strcmp(arg, "*")) 1609 + break; 1610 + pp->file = strdup_esq(arg); 1644 1611 if (pp->file == NULL) 1645 1612 return -ENOMEM; 1646 1613 break; ··· 2794 2757 /* Try no suffix number */ 2795 2758 ret = e_snprintf(buf, len, "%s%s", nbase, ret_event ? "__return" : ""); 2796 2759 if (ret < 0) { 2797 - pr_warning("snprintf() failed: %d; the event name nbase='%s' is too long\n", ret, nbase); 2760 + pr_warning("snprintf() failed: %d; the event name '%s' is too long\n" 2761 + " Hint: Set a shorter event with syntax \"EVENT=PROBEDEF\"\n" 2762 + " EVENT: Event name (max length: %d bytes).\n", 2763 + ret, nbase, MAX_EVENT_NAME_LEN); 2798 2764 goto out; 2799 2765 } 2800 2766 if (!strlist__has_entry(namelist, buf)) ··· 2817 2777 for (i = 1; i < MAX_EVENT_INDEX; i++) { 2818 2778 ret = e_snprintf(buf, len, "%s_%d", nbase, i); 2819 2779 if (ret < 0) { 2820 - pr_debug("snprintf() failed: %d\n", ret); 2780 + pr_warning("Add suffix failed: %d; the event name '%s' is too long\n" 2781 + " Hint: Set a shorter event with syntax \"EVENT=PROBEDEF\"\n" 2782 + " EVENT: Event name (max length: %d bytes).\n", 2783 + ret, nbase, MAX_EVENT_NAME_LEN); 2821 2784 goto out; 2822 2785 } 2823 2786 if (!strlist__has_entry(namelist, buf)) ··· 2884 2841 bool allow_suffix) 2885 2842 { 2886 2843 const char *event, *group; 2887 - char buf[64]; 2844 + char buf[MAX_EVENT_NAME_LEN]; 2888 2845 int ret; 2889 2846 2890 2847 /* If probe_event or trace_event already have the name, reuse it */ ··· 2907 2864 group = tev->group; 2908 2865 else 2909 2866 group = PERFPROBE_GROUP; 2867 + 2868 + if (strlen(group) >= MAX_EVENT_NAME_LEN) { 2869 + pr_err("Probe group string='%s' is too long (>= %d bytes)\n", 2870 + group, MAX_EVENT_NAME_LEN); 2871 + return -ENOMEM; 2872 + } 2910 2873 2911 2874 /* Get an unused new event name */ 2912 2875 ret = get_new_event_name(buf, sizeof(buf), event, namelist, ··· 3752 3703 nsinfo__zput(pev->nsi); 3753 3704 clear_perf_probe_event(&pevs[i]); 3754 3705 } 3755 - } 3756 - 3757 - int add_perf_probe_events(struct perf_probe_event *pevs, int npevs) 3758 - { 3759 - int ret; 3760 - 3761 - ret = init_probe_symbol_maps(pevs->uprobes); 3762 - if (ret < 0) 3763 - return ret; 3764 - 3765 - ret = convert_perf_probe_events(pevs, npevs); 3766 - if (ret == 0) 3767 - ret = apply_perf_probe_events(pevs, npevs); 3768 - 3769 - cleanup_perf_probe_events(pevs, npevs); 3770 - 3771 - exit_probe_symbol_maps(); 3772 - return ret; 3773 - } 3774 - 3775 - int del_perf_probe_events(struct strfilter *filter) 3776 - { 3777 - int ret, ret2, ufd = -1, kfd = -1; 3778 - char *str = strfilter__string(filter); 3779 - 3780 - if (!str) 3781 - return -EINVAL; 3782 - 3783 - /* Get current event names */ 3784 - ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); 3785 - if (ret < 0) 3786 - goto out; 3787 - 3788 - ret = probe_file__del_events(kfd, filter); 3789 - if (ret < 0 && ret != -ENOENT) 3790 - goto error; 3791 - 3792 - ret2 = probe_file__del_events(ufd, filter); 3793 - if (ret2 < 0 && ret2 != -ENOENT) { 3794 - ret = ret2; 3795 - goto error; 3796 - } 3797 - ret = 0; 3798 - 3799 - error: 3800 - if (kfd >= 0) 3801 - close(kfd); 3802 - if (ufd >= 0) 3803 - close(ufd); 3804 - out: 3805 - free(str); 3806 - 3807 - return ret; 3808 3706 } 3809 3707 3810 3708 int show_available_funcs(const char *target, struct nsinfo *nsi,
-3
tools/perf/util/probe-event.h
··· 159 159 /* Initialize line range */ 160 160 int line_range__init(struct line_range *lr); 161 161 162 - int add_perf_probe_events(struct perf_probe_event *pevs, int npevs); 163 162 int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs); 164 163 int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs); 165 164 int show_probe_trace_events(struct perf_probe_event *pevs, int npevs); ··· 166 167 void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs); 167 168 168 169 struct strfilter; 169 - 170 - int del_perf_probe_events(struct strfilter *filter); 171 170 172 171 int show_perf_probe_event(const char *group, const char *event, 173 172 struct perf_probe_event *pev,
-19
tools/perf/util/probe-file.c
··· 366 366 return ret; 367 367 } 368 368 369 - int probe_file__del_events(int fd, struct strfilter *filter) 370 - { 371 - struct strlist *namelist; 372 - int ret; 373 - 374 - namelist = strlist__new(NULL, NULL); 375 - if (!namelist) 376 - return -ENOMEM; 377 - 378 - ret = probe_file__get_events(fd, filter, namelist); 379 - if (ret < 0) 380 - goto out; 381 - 382 - ret = probe_file__del_strlist(fd, namelist); 383 - out: 384 - strlist__delete(namelist); 385 - return ret; 386 - } 387 - 388 369 /* Caller must ensure to remove this entry from list */ 389 370 static void probe_cache_entry__delete(struct probe_cache_entry *entry) 390 371 {
-1
tools/perf/util/probe-file.h
··· 44 44 struct strlist *probe_file__get_rawlist(int fd); 45 45 int probe_file__add_event(int fd, struct probe_trace_event *tev); 46 46 47 - int probe_file__del_events(int fd, struct strfilter *filter); 48 47 int probe_file__get_events(int fd, struct strfilter *filter, 49 48 struct strlist *plist); 50 49 int probe_file__del_strlist(int fd, struct strlist *namelist);
+29 -13
tools/perf/util/probe-finder.c
··· 56 56 */ 57 57 static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, 58 58 Dwarf_Op *fb_ops, Dwarf_Die *sp_die, 59 - unsigned int machine, 59 + const struct probe_finder *pf, 60 60 struct probe_trace_arg *tvar) 61 61 { 62 62 Dwarf_Attribute attr; ··· 166 166 if (!tvar) 167 167 return ret2; 168 168 169 - regs = get_dwarf_regstr(regn, machine); 169 + regs = get_dwarf_regstr(regn, pf->e_machine, pf->e_flags); 170 170 if (!regs) { 171 171 /* This should be a bug in DWARF or this tool */ 172 172 pr_warning("Mapping for the register number %u " ··· 451 451 dwarf_diename(vr_die)); 452 452 453 453 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, 454 - &pf->sp_die, pf->machine, pf->tvar); 454 + &pf->sp_die, pf, pf->tvar); 455 455 if (ret == -ENOENT && pf->skip_empty_arg) 456 456 /* This can be found in other place. skip it */ 457 457 return 0; ··· 602 602 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); 603 603 if (ret <= 0 || nops == 0) { 604 604 pf->fb_ops = NULL; 605 - #ifdef HAVE_DWARF_CFI_SUPPORT 606 605 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && 607 606 (pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) { 608 607 if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 && ··· 612 613 free(frame); 613 614 return -ENOENT; 614 615 } 615 - #endif /* HAVE_DWARF_CFI_SUPPORT */ 616 616 } 617 617 618 618 /* Call finder's callback handler */ ··· 1134 1136 if (gelf_getehdr(elf, &ehdr) == NULL) 1135 1137 return -EINVAL; 1136 1138 1137 - pf->machine = ehdr.e_machine; 1139 + pf->e_machine = ehdr.e_machine; 1140 + pf->e_flags = ehdr.e_flags; 1138 1141 1139 - #ifdef HAVE_DWARF_CFI_SUPPORT 1140 1142 do { 1141 1143 GElf_Shdr shdr; 1142 1144 ··· 1146 1148 1147 1149 pf->cfi_dbg = dwarf_getcfi(dbg->dbg); 1148 1150 } while (0); 1149 - #endif /* HAVE_DWARF_CFI_SUPPORT */ 1150 1151 1151 1152 ret = debuginfo__find_probe_location(dbg, pf); 1152 1153 return ret; ··· 1172 1175 (tag == DW_TAG_variable && vf->vars)) { 1173 1176 if (convert_variable_location(die_mem, vf->pf->addr, 1174 1177 vf->pf->fb_ops, &pf->sp_die, 1175 - pf->machine, NULL) == 0) { 1178 + pf, /*tvar=*/NULL) == 0) { 1176 1179 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem); 1177 1180 if (vf->args[vf->nargs].var == NULL) { 1178 1181 vf->ret = -ENOMEM; ··· 1376 1379 if (ret >= 0 && tf.pf.skip_empty_arg) 1377 1380 ret = fill_empty_trace_arg(pev, tf.tevs, tf.ntevs); 1378 1381 1382 + dwarf_cfi_end(tf.pf.cfi_eh); 1383 + 1379 1384 if (ret < 0 || tf.ntevs == 0) { 1380 1385 for (i = 0; i < tf.ntevs; i++) 1381 1386 clear_probe_trace_event(&tf.tevs[i]); ··· 1403 1404 tag == DW_TAG_variable) { 1404 1405 ret = convert_variable_location(die_mem, af->pf.addr, 1405 1406 af->pf.fb_ops, &af->pf.sp_die, 1406 - af->pf.machine, NULL); 1407 + &af->pf, /*tvar=*/NULL); 1407 1408 if (ret == 0 || ret == -ERANGE) { 1408 1409 int ret2; 1409 1410 bool externs = !af->child; ··· 1582 1583 1583 1584 /* Find a corresponding function (name, baseline and baseaddr) */ 1584 1585 if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) { 1585 - /* Get function entry information */ 1586 - func = basefunc = dwarf_diename(&spdie); 1586 + /* 1587 + * Get function entry information. 1588 + * 1589 + * As described in the document DWARF Debugging Information 1590 + * Format Version 5, section 2.22 Linkage Names, "mangled names, 1591 + * are used in various ways, ... to distinguish multiple 1592 + * entities that have the same name". 1593 + * 1594 + * Firstly try to get distinct linkage name, if fail then 1595 + * rollback to get associated name in DIE. 1596 + */ 1597 + func = basefunc = die_get_linkage_name(&spdie); 1598 + if (!func) 1599 + func = basefunc = dwarf_diename(&spdie); 1600 + 1587 1601 if (!func || 1588 1602 die_entrypc(&spdie, &baseaddr) != 0 || 1589 1603 dwarf_decl_line(&spdie, &baseline) != 0) { ··· 1875 1863 const char *prefix = symbol_conf.source_prefix; 1876 1864 1877 1865 if (sbuild_id && !prefix) { 1878 - if (!get_source_from_debuginfod(raw_path, sbuild_id, new_path)) 1866 + char prefixed_raw_path[PATH_MAX]; 1867 + 1868 + path__join(prefixed_raw_path, sizeof(prefixed_raw_path), comp_dir, raw_path); 1869 + 1870 + if (!get_source_from_debuginfod(prefixed_raw_path, sbuild_id, new_path)) 1879 1871 return 0; 1880 1872 } 1881 1873
+6 -7
tools/perf/util/probe-finder.h
··· 21 21 return isalpha(name[0]) || name[0] == '_'; 22 22 } 23 23 24 - #ifdef HAVE_DWARF_SUPPORT 24 + #ifdef HAVE_LIBDW_SUPPORT 25 25 26 26 #include "dwarf-aux.h" 27 27 #include "debuginfo.h" ··· 63 63 struct intlist *lcache; /* Line cache for lazy match */ 64 64 65 65 /* For variable searching */ 66 - #if _ELFUTILS_PREREQ(0, 142) 67 - /* Call Frame Information from .eh_frame */ 66 + /* Call Frame Information from .eh_frame. Owned by this struct. */ 68 67 Dwarf_CFI *cfi_eh; 69 - /* Call Frame Information from .debug_frame */ 68 + /* Call Frame Information from .debug_frame. Not owned. */ 70 69 Dwarf_CFI *cfi_dbg; 71 - #endif 72 70 Dwarf_Op *fb_ops; /* Frame base attribute */ 73 - unsigned int machine; /* Target machine arch */ 71 + unsigned int e_machine; /* ELF target machine arch */ 72 + unsigned int e_flags; /* ELF target machine flags */ 74 73 struct perf_probe_arg *pvar; /* Current target variable */ 75 74 struct probe_trace_arg *tvar; /* Current result variable */ 76 75 bool skip_empty_arg; /* Skip non-exist args */ ··· 103 104 int found; 104 105 }; 105 106 106 - #endif /* HAVE_DWARF_SUPPORT */ 107 + #endif /* HAVE_LIBDW_SUPPORT */ 107 108 108 109 #endif /*_PROBE_FINDER_H */
+1 -1
tools/perf/util/python.c
··· 6 6 #include <linux/err.h> 7 7 #include <perf/cpumap.h> 8 8 #ifdef HAVE_LIBTRACEEVENT 9 - #include <traceevent/event-parse.h> 9 + #include <event-parse.h> 10 10 #endif 11 11 #include <perf/mmap.h> 12 12 #include "evlist.h"
+1 -1
tools/perf/util/s390-cpumsf.c
··· 345 345 } 346 346 color_fprintf(stdout, color, " [%#08zx] Trailer %c%c%c bsdes:%d" 347 347 " dsdes:%d Overflow:%lld Time:%#llx\n" 348 - "\t\tC:%d TOD:%#lx\n", 348 + "\t\tC:%d TOD:%#llx\n", 349 349 pos, 350 350 te->f ? 'F' : ' ', 351 351 te->a ? 'A' : ' ',
+4 -4
tools/perf/util/s390-sample-raw.c
··· 98 98 te.res2 = be32_to_cpu(tep->res2); 99 99 100 100 color_fprintf(stdout, color, " [%#08zx] Trailer:%c%c%c%c%c" 101 - " Cfvn:%d Csvn:%d Speed:%d TOD:%#llx\n", 101 + " Cfvn:%d Csvn:%d Speed:%d TOD:%#lx\n", 102 102 offset, te.clock_base ? 'T' : ' ', 103 103 te.speed ? 'S' : ' ', te.mtda ? 'M' : ' ', 104 104 te.caca ? 'C' : ' ', te.lcda ? 'L' : ' ', 105 105 te.cfvn, te.csvn, te.cpu_speed, te.timestamp); 106 - color_fprintf(stdout, color, "\t\t1:%lx 2:%lx 3:%lx TOD-Base:%#llx" 106 + color_fprintf(stdout, color, "\t\t1:%lx 2:%lx 3:%lx TOD-Base:%#lx" 107 107 " Type:%x\n\n", 108 108 te.progusage1, te.progusage2, te.progusage3, 109 109 te.tod_base, te.mach_type); ··· 205 205 char *ev_name = get_counter_name(ce.set, i, pmu); 206 206 207 207 color_fprintf(stdout, color, 208 - "\tCounter:%03d %s Value:%#018lx\n", i, 208 + "\tCounter:%03zd %s Value:%#018"PRIx64"\n", i, 209 209 ev_name ?: "<unknown>", be64_to_cpu(*p)); 210 210 free(ev_name); 211 211 } ··· 260 260 261 261 ev_name = get_counter_name(evsel->core.attr.config, 262 262 pai_data.event_nr, evsel->pmu); 263 - color_fprintf(stdout, color, "\tCounter:%03d %s Value:%#018lx\n", 263 + color_fprintf(stdout, color, "\tCounter:%03d %s Value:%#018"PRIx64"\n", 264 264 pai_data.event_nr, ev_name ?: "<unknown>", 265 265 pai_data.event_val); 266 266 free(ev_name);
+1 -1
tools/perf/util/scripting-engines/trace-event-perl.c
··· 27 27 #include <errno.h> 28 28 #include <linux/bitmap.h> 29 29 #include <linux/time64.h> 30 - #include <traceevent/event-parse.h> 30 + #include <event-parse.h> 31 31 32 32 #include <stdbool.h> 33 33 /* perl needs the following define, right after including stdbool.h */
+7 -4
tools/perf/util/scripting-engines/trace-event-python.c
··· 31 31 #include <linux/compiler.h> 32 32 #include <linux/time64.h> 33 33 #ifdef HAVE_LIBTRACEEVENT 34 - #include <traceevent/event-parse.h> 34 + #include <event-parse.h> 35 35 #endif 36 36 37 37 #include "../build-id.h" ··· 793 793 static void set_sym_in_dict(PyObject *dict, struct addr_location *al, 794 794 const char *dso_field, const char *dso_bid_field, 795 795 const char *dso_map_start, const char *dso_map_end, 796 - const char *sym_field, const char *symoff_field) 796 + const char *sym_field, const char *symoff_field, 797 + const char *map_pgoff) 797 798 { 798 799 char sbuild_id[SBUILD_ID_SIZE]; 799 800 ··· 810 809 PyLong_FromUnsignedLong(map__start(al->map))); 811 810 pydict_set_item_string_decref(dict, dso_map_end, 812 811 PyLong_FromUnsignedLong(map__end(al->map))); 812 + pydict_set_item_string_decref(dict, map_pgoff, 813 + PyLong_FromUnsignedLongLong(map__pgoff(al->map))); 813 814 } 814 815 if (al->sym) { 815 816 pydict_set_item_string_decref(dict, sym_field, ··· 898 895 pydict_set_item_string_decref(dict, "comm", 899 896 _PyUnicode_FromString(thread__comm_str(al->thread))); 900 897 set_sym_in_dict(dict, al, "dso", "dso_bid", "dso_map_start", "dso_map_end", 901 - "symbol", "symoff"); 898 + "symbol", "symoff", "map_pgoff"); 902 899 903 900 pydict_set_item_string_decref(dict, "callchain", callchain); 904 901 ··· 923 920 PyBool_FromLong(1)); 924 921 set_sym_in_dict(dict_sample, addr_al, "addr_dso", "addr_dso_bid", 925 922 "addr_dso_map_start", "addr_dso_map_end", 926 - "addr_symbol", "addr_symoff"); 923 + "addr_symbol", "addr_symoff", "addr_map_pgoff"); 927 924 } 928 925 929 926 if (sample->flags)
+20 -10
tools/perf/util/session.c
··· 1171 1171 union perf_event *event, 1172 1172 struct perf_sample *sample, 1173 1173 struct sample_read_value *v, 1174 - struct machine *machine) 1174 + struct machine *machine, 1175 + bool per_thread) 1175 1176 { 1176 1177 struct perf_sample_id *sid = evlist__id2sid(evlist, v->id); 1177 1178 struct evsel *evsel; 1179 + u64 *storage = NULL; 1178 1180 1179 1181 if (sid) { 1180 - sample->id = v->id; 1181 - sample->period = v->value - sid->period; 1182 - sid->period = v->value; 1182 + storage = perf_sample_id__get_period_storage(sid, sample->tid, per_thread); 1183 1183 } 1184 1184 1185 - if (!sid || sid->evsel == NULL) { 1185 + if (storage) { 1186 + sample->id = v->id; 1187 + sample->period = v->value - *storage; 1188 + *storage = v->value; 1189 + } 1190 + 1191 + if (!storage || sid->evsel == NULL) { 1186 1192 ++evlist->stats.nr_unknown_id; 1187 1193 return 0; 1188 1194 } ··· 1209 1203 union perf_event *event, 1210 1204 struct perf_sample *sample, 1211 1205 struct machine *machine, 1212 - u64 read_format) 1206 + u64 read_format, 1207 + bool per_thread) 1213 1208 { 1214 1209 int ret = -EINVAL; 1215 1210 struct sample_read_value *v = sample->read.group.values; 1216 1211 1217 1212 if (tool->dont_split_sample_group) 1218 - return deliver_sample_value(evlist, tool, event, sample, v, machine); 1213 + return deliver_sample_value(evlist, tool, event, sample, v, machine, 1214 + per_thread); 1219 1215 1220 1216 sample_read_group__for_each(v, sample->read.group.nr, read_format) { 1221 1217 ret = deliver_sample_value(evlist, tool, event, sample, v, 1222 - machine); 1218 + machine, per_thread); 1223 1219 if (ret) 1224 1220 break; 1225 1221 } ··· 1236 1228 /* We know evsel != NULL. */ 1237 1229 u64 sample_type = evsel->core.attr.sample_type; 1238 1230 u64 read_format = evsel->core.attr.read_format; 1231 + bool per_thread = perf_evsel__attr_has_per_thread_sample_period(&evsel->core); 1239 1232 1240 1233 /* Standard sample delivery. */ 1241 1234 if (!(sample_type & PERF_SAMPLE_READ)) ··· 1245 1236 /* For PERF_SAMPLE_READ we have either single or group mode. */ 1246 1237 if (read_format & PERF_FORMAT_GROUP) 1247 1238 return deliver_sample_group(evlist, tool, event, sample, 1248 - machine, read_format); 1239 + machine, read_format, per_thread); 1249 1240 else 1250 1241 return deliver_sample_value(evlist, tool, event, sample, 1251 - &sample->read.one, machine); 1242 + &sample->read.one, machine, 1243 + per_thread); 1252 1244 } 1253 1245 1254 1246 static int machines__deliver_event(struct machines *machines,
+113 -2
tools/perf/util/sort.c
··· 35 35 #include <linux/string.h> 36 36 37 37 #ifdef HAVE_LIBTRACEEVENT 38 - #include <traceevent/event-parse.h> 38 + #include <event-parse.h> 39 39 #endif 40 40 41 41 regex_t parent_regex; ··· 675 675 .se_cmp = sort__sym_cmp, 676 676 .se_snprintf = hist_entry__sym_ipc_null_snprintf, 677 677 .se_width_idx = HISTC_SYMBOL_IPC, 678 + }; 679 + 680 + /* --sort callchain_branch_predicted */ 681 + 682 + static int64_t 683 + sort__callchain_branch_predicted_cmp(struct hist_entry *left __maybe_unused, 684 + struct hist_entry *right __maybe_unused) 685 + { 686 + return 0; 687 + } 688 + 689 + static int hist_entry__callchain_branch_predicted_snprintf( 690 + struct hist_entry *he, char *bf, size_t size, unsigned int width) 691 + { 692 + u64 branch_count, predicted_count; 693 + double percent = 0.0; 694 + char str[32]; 695 + 696 + callchain_branch_counts(he->callchain, &branch_count, 697 + &predicted_count, NULL, NULL); 698 + 699 + if (branch_count) 700 + percent = predicted_count * 100.0 / branch_count; 701 + 702 + snprintf(str, sizeof(str), "%.1f%%", percent); 703 + return repsep_snprintf(bf, size, "%-*.*s", width, width, str); 704 + } 705 + 706 + struct sort_entry sort_callchain_branch_predicted = { 707 + .se_header = "Predicted", 708 + .se_cmp = sort__callchain_branch_predicted_cmp, 709 + .se_snprintf = hist_entry__callchain_branch_predicted_snprintf, 710 + .se_width_idx = HISTC_CALLCHAIN_BRANCH_PREDICTED, 711 + }; 712 + 713 + /* --sort callchain_branch_abort */ 714 + 715 + static int64_t 716 + sort__callchain_branch_abort_cmp(struct hist_entry *left __maybe_unused, 717 + struct hist_entry *right __maybe_unused) 718 + { 719 + return 0; 720 + } 721 + 722 + static int hist_entry__callchain_branch_abort_snprintf(struct hist_entry *he, 723 + char *bf, size_t size, 724 + unsigned int width) 725 + { 726 + u64 branch_count, abort_count; 727 + char str[32]; 728 + 729 + callchain_branch_counts(he->callchain, &branch_count, 730 + NULL, &abort_count, NULL); 731 + 732 + snprintf(str, sizeof(str), "%" PRId64, abort_count); 733 + return repsep_snprintf(bf, size, "%-*.*s", width, width, str); 734 + } 735 + 736 + struct sort_entry sort_callchain_branch_abort = { 737 + .se_header = "Abort", 738 + .se_cmp = sort__callchain_branch_abort_cmp, 739 + .se_snprintf = hist_entry__callchain_branch_abort_snprintf, 740 + .se_width_idx = HISTC_CALLCHAIN_BRANCH_ABORT, 741 + }; 742 + 743 + /* --sort callchain_branch_cycles */ 744 + 745 + static int64_t 746 + sort__callchain_branch_cycles_cmp(struct hist_entry *left __maybe_unused, 747 + struct hist_entry *right __maybe_unused) 748 + { 749 + return 0; 750 + } 751 + 752 + static int hist_entry__callchain_branch_cycles_snprintf(struct hist_entry *he, 753 + char *bf, size_t size, 754 + unsigned int width) 755 + { 756 + u64 branch_count, cycles_count, cycles = 0; 757 + char str[32]; 758 + 759 + callchain_branch_counts(he->callchain, &branch_count, 760 + NULL, NULL, &cycles_count); 761 + 762 + if (branch_count) 763 + cycles = cycles_count / branch_count; 764 + 765 + snprintf(str, sizeof(str), "%" PRId64 "", cycles); 766 + return repsep_snprintf(bf, size, "%-*.*s", width, width, str); 767 + } 768 + 769 + struct sort_entry sort_callchain_branch_cycles = { 770 + .se_header = "Cycles", 771 + .se_cmp = sort__callchain_branch_cycles_cmp, 772 + .se_snprintf = hist_entry__callchain_branch_cycles_snprintf, 773 + .se_width_idx = HISTC_CALLCHAIN_BRANCH_CYCLES, 678 774 }; 679 775 680 776 /* --sort srcfile */ ··· 2552 2456 DIM(SORT_SYM_IPC, "ipc_lbr", sort_sym_ipc), 2553 2457 DIM(SORT_ADDR_FROM, "addr_from", sort_addr_from), 2554 2458 DIM(SORT_ADDR_TO, "addr_to", sort_addr_to), 2459 + DIM(SORT_CALLCHAIN_BRANCH_PREDICTED, 2460 + "callchain_branch_predicted", 2461 + sort_callchain_branch_predicted), 2462 + DIM(SORT_CALLCHAIN_BRANCH_ABORT, 2463 + "callchain_branch_abort", 2464 + sort_callchain_branch_abort), 2465 + DIM(SORT_CALLCHAIN_BRANCH_CYCLES, 2466 + "callchain_branch_cycles", 2467 + sort_callchain_branch_cycles) 2555 2468 }; 2556 2469 2557 2470 #undef DIM ··· 3589 3484 if (!sd->name || strncasecmp(tok, sd->name, strlen(tok))) 3590 3485 continue; 3591 3486 3592 - if (sort__mode != SORT_MODE__BRANCH) 3487 + if ((sort__mode != SORT_MODE__BRANCH) && 3488 + strncasecmp(tok, "callchain_branch_predicted", 3489 + strlen(tok)) && 3490 + strncasecmp(tok, "callchain_branch_abort", 3491 + strlen(tok)) && 3492 + strncasecmp(tok, "callchain_branch_cycles", 3493 + strlen(tok))) 3593 3494 return -EINVAL; 3594 3495 3595 3496 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
+3
tools/perf/util/sort.h
··· 88 88 SORT_SYM_IPC, 89 89 SORT_ADDR_FROM, 90 90 SORT_ADDR_TO, 91 + SORT_CALLCHAIN_BRANCH_PREDICTED, 92 + SORT_CALLCHAIN_BRANCH_ABORT, 93 + SORT_CALLCHAIN_BRANCH_CYCLES, 91 94 92 95 /* memory mode specific sort keys */ 93 96 __SORT_MEMORY_MODE,
+153 -43
tools/perf/util/stat-display.c
··· 7 7 #include <perf/cpumap.h> 8 8 #include "color.h" 9 9 #include "counts.h" 10 + #include "debug.h" 10 11 #include "evlist.h" 11 12 #include "evsel.h" 12 13 #include "stat.h" ··· 22 21 #include "iostat.h" 23 22 #include "pmu.h" 24 23 #include "pmus.h" 24 + #include "tool_pmu.h" 25 25 26 26 #define CNTR_NOT_SUPPORTED "<not supported>" 27 27 #define CNTR_NOT_COUNTED "<not counted>" ··· 72 70 [AGGR_NODE] = "node", 73 71 [AGGR_GLOBAL] = "" 74 72 }; 73 + 74 + const char *metric_threshold_classify__color(enum metric_threshold_classify thresh) 75 + { 76 + const char * const colors[] = { 77 + "", /* unknown */ 78 + PERF_COLOR_RED, /* bad */ 79 + PERF_COLOR_MAGENTA, /* nearly bad */ 80 + PERF_COLOR_YELLOW, /* less good */ 81 + PERF_COLOR_GREEN, /* good */ 82 + }; 83 + static_assert(ARRAY_SIZE(colors) - 1 == METRIC_THRESHOLD_GOOD, "missing enum value"); 84 + return colors[thresh]; 85 + } 86 + 87 + static const char *metric_threshold_classify__str(enum metric_threshold_classify thresh) 88 + { 89 + const char * const strs[] = { 90 + "unknown", 91 + "bad", 92 + "nearly bad", 93 + "less good", 94 + "good", 95 + }; 96 + static_assert(ARRAY_SIZE(strs) - 1 == METRIC_THRESHOLD_GOOD, "missing enum value"); 97 + return strs[thresh]; 98 + } 75 99 76 100 static void print_running_std(struct perf_stat_config *config, u64 run, u64 ena) 77 101 { ··· 431 403 } 432 404 433 405 static void print_metric_std(struct perf_stat_config *config, 434 - void *ctx, const char *color, const char *fmt, 435 - const char *unit, double val) 406 + void *ctx, enum metric_threshold_classify thresh, 407 + const char *fmt, const char *unit, double val) 436 408 { 437 409 struct outstate *os = ctx; 438 410 FILE *out = os->fh; 439 411 int n; 440 412 bool newline = os->newline; 413 + const char *color = metric_threshold_classify__color(thresh); 441 414 442 415 os->newline = false; 443 416 ··· 470 441 471 442 static void print_metric_csv(struct perf_stat_config *config __maybe_unused, 472 443 void *ctx, 473 - const char *color __maybe_unused, 444 + enum metric_threshold_classify thresh __maybe_unused, 474 445 const char *fmt, const char *unit, double val) 475 446 { 476 447 struct outstate *os = ctx; ··· 491 462 492 463 static void print_metric_json(struct perf_stat_config *config __maybe_unused, 493 464 void *ctx, 494 - const char *color __maybe_unused, 465 + enum metric_threshold_classify thresh, 495 466 const char *fmt __maybe_unused, 496 467 const char *unit, double val) 497 468 { 498 469 struct outstate *os = ctx; 499 470 FILE *out = os->fh; 500 471 501 - fprintf(out, "\"metric-value\" : \"%f\", ", val); 502 - fprintf(out, "\"metric-unit\" : \"%s\"", unit); 472 + if (unit) { 473 + fprintf(out, "\"metric-value\" : \"%f\", \"metric-unit\" : \"%s\"", val, unit); 474 + if (thresh != METRIC_THRESHOLD_UNKNOWN) { 475 + fprintf(out, ", \"metric-threshold\" : \"%s\"", 476 + metric_threshold_classify__str(thresh)); 477 + } 478 + } 503 479 if (!config->metric_only) 504 480 fprintf(out, "}"); 505 481 } ··· 591 557 } 592 558 593 559 static void print_metric_only(struct perf_stat_config *config, 594 - void *ctx, const char *color, const char *fmt, 595 - const char *unit, double val) 560 + void *ctx, enum metric_threshold_classify thresh, 561 + const char *fmt, const char *unit, double val) 596 562 { 597 563 struct outstate *os = ctx; 598 564 FILE *out = os->fh; 599 565 char buf[1024], str[1024]; 600 566 unsigned mlen = config->metric_only_len; 567 + const char *color = metric_threshold_classify__color(thresh); 601 568 602 569 if (!valid_only_metric(unit)) 603 570 return; ··· 615 580 } 616 581 617 582 static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused, 618 - void *ctx, const char *color __maybe_unused, 583 + void *ctx, 584 + enum metric_threshold_classify thresh __maybe_unused, 619 585 const char *fmt, 620 586 const char *unit, double val) 621 587 { ··· 638 602 } 639 603 640 604 static void print_metric_only_json(struct perf_stat_config *config __maybe_unused, 641 - void *ctx, const char *color __maybe_unused, 605 + void *ctx, 606 + enum metric_threshold_classify thresh __maybe_unused, 642 607 const char *fmt, 643 608 const char *unit, double val) 644 609 { 645 610 struct outstate *os = ctx; 646 611 FILE *out = os->fh; 647 - char buf[64], *vals, *ends; 612 + char buf[64], *ends; 648 613 char tbuf[1024]; 614 + const char *vals; 649 615 650 616 if (!valid_only_metric(unit)) 651 617 return; 652 618 unit = fixunit(tbuf, os->evsel, unit); 619 + if (!unit[0]) 620 + return; 653 621 snprintf(buf, sizeof(buf), fmt ?: "", val); 654 - ends = vals = skip_spaces(buf); 622 + vals = ends = skip_spaces(buf); 655 623 while (isdigit(*ends) || *ends == '.') 656 624 ends++; 657 625 *ends = 0; 658 - if (!unit[0] || !vals[0]) 659 - return; 626 + if (!vals[0]) 627 + vals = "none"; 660 628 fprintf(out, "%s\"%s\" : \"%s\"", os->first ? "" : ", ", unit, vals); 661 629 os->first = false; 662 630 } ··· 671 631 } 672 632 673 633 static void print_metric_header(struct perf_stat_config *config, 674 - void *ctx, const char *color __maybe_unused, 634 + void *ctx, 635 + enum metric_threshold_classify thresh __maybe_unused, 675 636 const char *fmt __maybe_unused, 676 637 const char *unit, double val __maybe_unused) 677 638 { ··· 846 805 847 806 if (run == 0 || ena == 0 || counter->counts->scaled == -1) { 848 807 if (config->metric_only) { 849 - pm(config, os, NULL, "", "", 0); 808 + pm(config, os, METRIC_THRESHOLD_UNKNOWN, "", "", 0); 850 809 return; 851 810 } 852 811 ··· 901 860 perf_stat__print_shadow_stats(config, counter, uval, aggr_idx, 902 861 &out, &config->metric_events); 903 862 } else { 904 - pm(config, os, /*color=*/NULL, /*format=*/NULL, /*unit=*/"", /*val=*/0); 863 + pm(config, os, METRIC_THRESHOLD_UNKNOWN, /*format=*/NULL, /*unit=*/"", /*val=*/0); 905 864 } 906 865 907 866 if (!config->metric_only) { ··· 912 871 913 872 static void uniquify_event_name(struct evsel *counter) 914 873 { 915 - char *new_name; 916 - char *config; 917 - int ret = 0; 874 + const char *name, *pmu_name; 875 + char *new_name, *config; 876 + int ret; 918 877 919 - if (counter->uniquified_name || counter->use_config_name || 920 - !counter->pmu_name || !strncmp(evsel__name(counter), counter->pmu_name, 921 - strlen(counter->pmu_name))) 878 + /* The evsel was already uniquified. */ 879 + if (counter->uniquified_name) 922 880 return; 923 881 924 - config = strchr(counter->name, '/'); 882 + /* Avoid checking to uniquify twice. */ 883 + counter->uniquified_name = true; 884 + 885 + /* The evsel has a "name=" config term or is from libpfm. */ 886 + if (counter->use_config_name || counter->is_libpfm_event) 887 + return; 888 + 889 + /* Legacy no PMU event, don't uniquify. */ 890 + if (!counter->pmu || 891 + (counter->pmu->type < PERF_TYPE_MAX && counter->pmu->type != PERF_TYPE_RAW)) 892 + return; 893 + 894 + /* A sysfs or json event replacing a legacy event, don't uniquify. */ 895 + if (counter->pmu->is_core && counter->alternate_hw_config != PERF_COUNT_HW_MAX) 896 + return; 897 + 898 + name = evsel__name(counter); 899 + pmu_name = counter->pmu->name; 900 + /* Already prefixed by the PMU name. */ 901 + if (!strncmp(name, pmu_name, strlen(pmu_name))) 902 + return; 903 + 904 + config = strchr(name, '/'); 925 905 if (config) { 926 - if (asprintf(&new_name, 927 - "%s%s", counter->pmu_name, config) > 0) { 928 - free(counter->name); 929 - counter->name = new_name; 906 + int len = config - name; 907 + 908 + if (config[1] == '/') { 909 + /* case: event// */ 910 + ret = asprintf(&new_name, "%s/%.*s/%s", pmu_name, len, name, config + 2); 911 + } else { 912 + /* case: event/.../ */ 913 + ret = asprintf(&new_name, "%s/%.*s,%s", pmu_name, len, name, config + 1); 930 914 } 931 915 } else { 932 - if (evsel__is_hybrid(counter)) { 933 - ret = asprintf(&new_name, "%s/%s/", 934 - counter->pmu_name, counter->name); 935 - } else { 936 - ret = asprintf(&new_name, "%s [%s]", 937 - counter->name, counter->pmu_name); 938 - } 916 + config = strchr(name, ':'); 917 + if (config) { 918 + /* case: event:.. */ 919 + int len = config - name; 939 920 940 - if (ret) { 941 - free(counter->name); 942 - counter->name = new_name; 921 + ret = asprintf(&new_name, "%s/%.*s/%s", pmu_name, len, name, config + 1); 922 + } else { 923 + /* case: event */ 924 + ret = asprintf(&new_name, "%s/%s/", pmu_name, name); 943 925 } 944 926 } 945 - 946 - counter->uniquified_name = true; 927 + if (ret > 0) { 928 + free(counter->name); 929 + counter->name = new_name; 930 + } else { 931 + /* ENOMEM from asprintf. */ 932 + counter->uniquified_name = false; 933 + } 947 934 } 948 935 949 936 static bool hybrid_uniquify(struct evsel *evsel, struct perf_stat_config *config) ··· 1009 940 int idx; 1010 941 1011 942 /* 943 + * Skip unsupported default events when not verbose. (default events 944 + * are all marked 'skippable'). 945 + */ 946 + if (verbose == 0 && counter->skippable && !counter->supported) 947 + return true; 948 + 949 + /* 1012 950 * Skip value 0 when enabling --per-thread globally, 1013 951 * otherwise it will have too many 0 output. 1014 952 */ 1015 953 if (config->aggr_mode == AGGR_THREAD && config->system_wide) 1016 954 return true; 1017 955 1018 - /* Tool events have the software PMU but are only gathered on 1. */ 1019 - if (evsel__is_tool(counter)) 1020 - return true; 956 + /* 957 + * Many tool events are only gathered on the first index, skip other 958 + * zero values. 959 + */ 960 + if (evsel__is_tool(counter)) { 961 + struct aggr_cpu_id own_id = 962 + config->aggr_get_id(config, (struct perf_cpu){ .cpu = 0 }); 963 + 964 + return !aggr_cpu_id__equal(id, &own_id); 965 + } 1021 966 1022 967 /* 1023 968 * Skip value 0 when it's an uncore event and the given aggr id ··· 1642 1559 print_metric_end(config, os); 1643 1560 } 1644 1561 1562 + static void disable_uniquify(struct evlist *evlist) 1563 + { 1564 + struct evsel *counter; 1565 + struct perf_pmu *last_pmu = NULL; 1566 + bool first = true; 1567 + 1568 + evlist__for_each_entry(evlist, counter) { 1569 + /* If PMUs vary then uniquify can be useful. */ 1570 + if (!first && counter->pmu != last_pmu) 1571 + return; 1572 + first = false; 1573 + if (counter->pmu) { 1574 + /* Allow uniquify for uncore PMUs. */ 1575 + if (!counter->pmu->is_core) 1576 + return; 1577 + /* Keep hybrid event names uniquified for clarity. */ 1578 + if (perf_pmus__num_core_pmus() > 1) 1579 + return; 1580 + } 1581 + } 1582 + evlist__for_each_entry_continue(evlist, counter) { 1583 + counter->uniquified_name = true; 1584 + } 1585 + } 1586 + 1645 1587 void evlist__print_counters(struct evlist *evlist, struct perf_stat_config *config, 1646 1588 struct target *_target, struct timespec *ts, 1647 1589 int argc, const char **argv) ··· 1679 1571 .fh = config->output, 1680 1572 .first = true, 1681 1573 }; 1574 + 1575 + disable_uniquify(evlist); 1682 1576 1683 1577 if (config->iostat_run) 1684 1578 evlist->selected = evlist__first(evlist);
+93 -73
tools/perf/util/stat-shadow.c
··· 15 15 #include <linux/zalloc.h> 16 16 #include "iostat.h" 17 17 #include "util/hashmap.h" 18 + #include "tool_pmu.h" 18 19 19 20 struct stats walltime_nsecs_stats; 20 21 struct rusage_stats ru_stats; ··· 77 76 memset(&ru_stats, 0, sizeof(ru_stats)); 78 77 } 79 78 80 - static enum stat_type evsel__stat_type(const struct evsel *evsel) 79 + static enum stat_type evsel__stat_type(struct evsel *evsel) 81 80 { 82 81 /* Fake perf_hw_cache_op_id values for use with evsel__match. */ 83 82 u64 PERF_COUNT_hw_cache_l1d_miss = PERF_COUNT_HW_CACHE_L1D | ··· 137 136 return STAT_NONE; 138 137 } 139 138 140 - static const char *get_ratio_color(const double ratios[3], double val) 139 + static enum metric_threshold_classify get_ratio_thresh(const double ratios[3], double val) 141 140 { 142 - const char *color = PERF_COLOR_NORMAL; 141 + assert(ratios[0] > ratios[1]); 142 + assert(ratios[1] > ratios[2]); 143 143 144 - if (val > ratios[0]) 145 - color = PERF_COLOR_RED; 146 - else if (val > ratios[1]) 147 - color = PERF_COLOR_MAGENTA; 148 - else if (val > ratios[2]) 149 - color = PERF_COLOR_YELLOW; 150 - 151 - return color; 144 + return val > ratios[1] 145 + ? (val > ratios[0] ? METRIC_THRESHOLD_BAD : METRIC_THRESHOLD_NEARLY_BAD) 146 + : (val > ratios[2] ? METRIC_THRESHOLD_LESS_GOOD : METRIC_THRESHOLD_GOOD); 152 147 } 153 148 154 149 static double find_stat(const struct evsel *evsel, int aggr_idx, enum stat_type type) 155 150 { 156 - const struct evsel *cur; 151 + struct evsel *cur; 157 152 int evsel_ctx = evsel_context(evsel); 158 153 159 154 evlist__for_each_entry(evsel->evlist, cur) { ··· 192 195 const struct evsel *evsel, int aggr_idx, 193 196 double numerator, struct perf_stat_output_ctx *out, 194 197 enum stat_type denominator_type, 195 - const double color_ratios[3], const char *unit) 198 + const double thresh_ratios[3], const char *_unit) 196 199 { 197 200 double denominator = find_stat(evsel, aggr_idx, denominator_type); 201 + double ratio = 0; 202 + enum metric_threshold_classify thresh = METRIC_THRESHOLD_UNKNOWN; 203 + const char *fmt = NULL; 204 + const char *unit = NULL; 198 205 199 206 if (numerator && denominator) { 200 - double ratio = numerator / denominator * 100.0; 201 - const char *color = get_ratio_color(color_ratios, ratio); 202 - 203 - out->print_metric(config, out->ctx, color, "%7.2f%%", unit, ratio); 204 - } else 205 - out->print_metric(config, out->ctx, NULL, NULL, unit, 0); 207 + ratio = numerator / denominator * 100.0; 208 + thresh = get_ratio_thresh(thresh_ratios, ratio); 209 + fmt = "%7.2f%%"; 210 + unit = _unit; 211 + } 212 + out->print_metric(config, out->ctx, thresh, fmt, unit, ratio); 206 213 } 207 214 208 215 static void print_stalled_cycles_front(struct perf_stat_config *config, ··· 214 213 int aggr_idx, double stalled, 215 214 struct perf_stat_output_ctx *out) 216 215 { 217 - static const double color_ratios[3] = {50.0, 30.0, 10.0}; 216 + const double thresh_ratios[3] = {50.0, 30.0, 10.0}; 218 217 219 - print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, color_ratios, 218 + print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, thresh_ratios, 220 219 "frontend cycles idle"); 221 220 } 222 221 ··· 225 224 int aggr_idx, double stalled, 226 225 struct perf_stat_output_ctx *out) 227 226 { 228 - static const double color_ratios[3] = {75.0, 50.0, 20.0}; 227 + const double thresh_ratios[3] = {75.0, 50.0, 20.0}; 229 228 230 - print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, color_ratios, 229 + print_ratio(config, evsel, aggr_idx, stalled, out, STAT_CYCLES, thresh_ratios, 231 230 "backend cycles idle"); 232 231 } 233 232 ··· 236 235 int aggr_idx, double misses, 237 236 struct perf_stat_output_ctx *out) 238 237 { 239 - static const double color_ratios[3] = {20.0, 10.0, 5.0}; 238 + const double thresh_ratios[3] = {20.0, 10.0, 5.0}; 240 239 241 - print_ratio(config, evsel, aggr_idx, misses, out, STAT_BRANCHES, color_ratios, 240 + print_ratio(config, evsel, aggr_idx, misses, out, STAT_BRANCHES, thresh_ratios, 242 241 "of all branches"); 243 242 } 244 243 ··· 247 246 int aggr_idx, double misses, 248 247 struct perf_stat_output_ctx *out) 249 248 { 250 - static const double color_ratios[3] = {20.0, 10.0, 5.0}; 249 + const double thresh_ratios[3] = {20.0, 10.0, 5.0}; 251 250 252 - print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_DCACHE, color_ratios, 251 + print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_DCACHE, thresh_ratios, 253 252 "of all L1-dcache accesses"); 254 253 } 255 254 ··· 258 257 int aggr_idx, double misses, 259 258 struct perf_stat_output_ctx *out) 260 259 { 261 - static const double color_ratios[3] = {20.0, 10.0, 5.0}; 260 + const double thresh_ratios[3] = {20.0, 10.0, 5.0}; 262 261 263 - print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_ICACHE, color_ratios, 262 + print_ratio(config, evsel, aggr_idx, misses, out, STAT_L1_ICACHE, thresh_ratios, 264 263 "of all L1-icache accesses"); 265 264 } 266 265 ··· 269 268 int aggr_idx, double misses, 270 269 struct perf_stat_output_ctx *out) 271 270 { 272 - static const double color_ratios[3] = {20.0, 10.0, 5.0}; 271 + const double thresh_ratios[3] = {20.0, 10.0, 5.0}; 273 272 274 - print_ratio(config, evsel, aggr_idx, misses, out, STAT_LL_CACHE, color_ratios, 273 + print_ratio(config, evsel, aggr_idx, misses, out, STAT_LL_CACHE, thresh_ratios, 275 274 "of all LL-cache accesses"); 276 275 } 277 276 ··· 280 279 int aggr_idx, double misses, 281 280 struct perf_stat_output_ctx *out) 282 281 { 283 - static const double color_ratios[3] = {20.0, 10.0, 5.0}; 282 + const double thresh_ratios[3] = {20.0, 10.0, 5.0}; 284 283 285 - print_ratio(config, evsel, aggr_idx, misses, out, STAT_DTLB_CACHE, color_ratios, 284 + print_ratio(config, evsel, aggr_idx, misses, out, STAT_DTLB_CACHE, thresh_ratios, 286 285 "of all dTLB cache accesses"); 287 286 } 288 287 ··· 291 290 int aggr_idx, double misses, 292 291 struct perf_stat_output_ctx *out) 293 292 { 294 - static const double color_ratios[3] = {20.0, 10.0, 5.0}; 293 + const double thresh_ratios[3] = {20.0, 10.0, 5.0}; 295 294 296 - print_ratio(config, evsel, aggr_idx, misses, out, STAT_ITLB_CACHE, color_ratios, 295 + print_ratio(config, evsel, aggr_idx, misses, out, STAT_ITLB_CACHE, thresh_ratios, 297 296 "of all iTLB cache accesses"); 298 297 } 299 298 ··· 302 301 int aggr_idx, double misses, 303 302 struct perf_stat_output_ctx *out) 304 303 { 305 - static const double color_ratios[3] = {20.0, 10.0, 5.0}; 304 + const double thresh_ratios[3] = {20.0, 10.0, 5.0}; 306 305 307 - print_ratio(config, evsel, aggr_idx, misses, out, STAT_CACHE_REFS, color_ratios, 306 + print_ratio(config, evsel, aggr_idx, misses, out, STAT_CACHE_REFS, thresh_ratios, 308 307 "of all cache refs"); 309 308 } 310 309 ··· 320 319 find_stat(evsel, aggr_idx, STAT_STALLED_CYCLES_BACK)); 321 320 322 321 if (cycles) { 323 - print_metric(config, ctxp, NULL, "%7.2f ", "insn per cycle", 324 - instructions / cycles); 325 - } else 326 - print_metric(config, ctxp, NULL, NULL, "insn per cycle", 0); 327 - 322 + print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%7.2f ", 323 + "insn per cycle", instructions / cycles); 324 + } else { 325 + print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, /*fmt=*/NULL, 326 + "insn per cycle", 0); 327 + } 328 328 if (max_stalled && instructions) { 329 329 out->new_line(config, ctxp); 330 - print_metric(config, ctxp, NULL, "%7.2f ", "stalled cycles per insn", 331 - max_stalled / instructions); 330 + print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%7.2f ", 331 + "stalled cycles per insn", max_stalled / instructions); 332 332 } 333 333 } 334 334 ··· 343 341 if (cycles && nsecs) { 344 342 double ratio = cycles / nsecs; 345 343 346 - out->print_metric(config, out->ctx, NULL, "%8.3f", "GHz", ratio); 347 - } else 348 - out->print_metric(config, out->ctx, NULL, NULL, "GHz", 0); 344 + out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN, "%8.3f", 345 + "GHz", ratio); 346 + } else { 347 + out->print_metric(config, out->ctx, METRIC_THRESHOLD_UNKNOWN, /*fmt=*/NULL, 348 + "GHz", 0); 349 + } 349 350 } 350 351 351 352 static void print_nsecs(struct perf_stat_config *config, ··· 361 356 double wall_time = avg_stats(&walltime_nsecs_stats); 362 357 363 358 if (wall_time) { 364 - print_metric(config, ctxp, NULL, "%8.3f", "CPUs utilized", 359 + print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%8.3f", "CPUs utilized", 365 360 nsecs / (wall_time * evsel->scale)); 366 - } else 367 - print_metric(config, ctxp, NULL, NULL, "CPUs utilized", 0); 361 + } else { 362 + print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, /*fmt=*/NULL, 363 + "CPUs utilized", 0); 364 + } 368 365 } 369 366 370 367 static int prepare_metric(const struct metric_expr *mexp, ··· 388 381 double scale; 389 382 390 383 switch (evsel__tool_event(metric_events[i])) { 391 - case PERF_TOOL_DURATION_TIME: 384 + case TOOL_PMU__EVENT_DURATION_TIME: 392 385 stats = &walltime_nsecs_stats; 393 386 scale = 1e-9; 394 387 break; 395 - case PERF_TOOL_USER_TIME: 388 + case TOOL_PMU__EVENT_USER_TIME: 396 389 stats = &ru_stats.ru_utime_usec_stat; 397 390 scale = 1e-6; 398 391 break; 399 - case PERF_TOOL_SYSTEM_TIME: 392 + case TOOL_PMU__EVENT_SYSTEM_TIME: 400 393 stats = &ru_stats.ru_stime_usec_stat; 401 394 scale = 1e-6; 402 395 break; 403 - case PERF_TOOL_NONE: 396 + case TOOL_PMU__EVENT_NONE: 404 397 pr_err("Invalid tool event 'none'"); 405 398 abort(); 406 - case PERF_TOOL_MAX: 399 + case TOOL_PMU__EVENT_MAX: 407 400 pr_err("Invalid tool event 'max'"); 408 401 abort(); 402 + case TOOL_PMU__EVENT_HAS_PMEM: 403 + case TOOL_PMU__EVENT_NUM_CORES: 404 + case TOOL_PMU__EVENT_NUM_CPUS: 405 + case TOOL_PMU__EVENT_NUM_CPUS_ONLINE: 406 + case TOOL_PMU__EVENT_NUM_DIES: 407 + case TOOL_PMU__EVENT_NUM_PACKAGES: 408 + case TOOL_PMU__EVENT_SLOTS: 409 + case TOOL_PMU__EVENT_SMT_ON: 410 + case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ: 409 411 default: 410 - pr_err("Unknown tool event '%s'", evsel__name(metric_events[i])); 412 + pr_err("Unexpected tool event '%s'", evsel__name(metric_events[i])); 411 413 abort(); 412 414 } 413 415 val = avg_stats(stats) * scale; ··· 499 483 double ratio, scale, threshold; 500 484 int i; 501 485 void *ctxp = out->ctx; 502 - const char *color = NULL; 486 + enum metric_threshold_classify thresh = METRIC_THRESHOLD_UNKNOWN; 503 487 504 488 pctx = expr__ctx_new(); 505 489 if (!pctx) ··· 517 501 if (!metric_events[i]) { 518 502 if (expr__parse(&ratio, pctx, metric_expr) == 0) { 519 503 char *unit; 520 - char metric_bf[64]; 504 + char metric_bf[128]; 521 505 522 506 if (metric_threshold && 523 507 expr__parse(&threshold, pctx, metric_threshold) == 0 && 524 508 !isnan(threshold)) { 525 - color = fpclassify(threshold) == FP_ZERO 526 - ? PERF_COLOR_GREEN : PERF_COLOR_RED; 509 + thresh = fpclassify(threshold) == FP_ZERO 510 + ? METRIC_THRESHOLD_GOOD : METRIC_THRESHOLD_BAD; 527 511 } 528 512 529 513 if (metric_unit && metric_name) { ··· 538 522 scnprintf(metric_bf, sizeof(metric_bf), 539 523 "%s %s", unit, metric_name); 540 524 541 - print_metric(config, ctxp, color, "%8.1f", 525 + print_metric(config, ctxp, thresh, "%8.1f", 542 526 metric_bf, ratio); 543 527 } else { 544 - print_metric(config, ctxp, color, "%8.2f", 528 + print_metric(config, ctxp, thresh, "%8.2f", 545 529 metric_name ? 546 530 metric_name : 547 531 out->force_header ? evsel->name : "", 548 532 ratio); 549 533 } 550 534 } else { 551 - print_metric(config, ctxp, color, /*unit=*/NULL, 535 + print_metric(config, ctxp, thresh, /*fmt=*/NULL, 552 536 out->force_header ? 553 537 (metric_name ?: evsel->name) : "", 0); 554 538 } 555 539 } else { 556 - print_metric(config, ctxp, color, /*unit=*/NULL, 540 + print_metric(config, ctxp, thresh, /*fmt=*/NULL, 557 541 out->force_header ? 558 542 (metric_name ?: evsel->name) : "", 0); 559 543 } ··· 589 573 { 590 574 bool need_full_name = perf_pmus__num_core_pmus() > 1; 591 575 static const char *last_name; 592 - static const char *last_pmu; 576 + static const struct perf_pmu *last_pmu; 593 577 char full_name[64]; 594 578 595 579 /* ··· 600 584 * different metric events. 601 585 */ 602 586 if (last_name && !strcmp(last_name, name)) { 603 - if (!need_full_name || !strcmp(last_pmu, evsel->pmu_name)) { 587 + if (!need_full_name || last_pmu != evsel->pmu) { 604 588 out->print_metricgroup_header(config, ctxp, NULL); 605 589 return; 606 590 } 607 591 } 608 592 609 - if (need_full_name) 610 - scnprintf(full_name, sizeof(full_name), "%s (%s)", name, evsel->pmu_name); 593 + if (need_full_name && evsel->pmu) 594 + scnprintf(full_name, sizeof(full_name), "%s (%s)", name, evsel->pmu->name); 611 595 else 612 596 scnprintf(full_name, sizeof(full_name), "%s", name); 613 597 614 598 out->print_metricgroup_header(config, ctxp, full_name); 615 599 616 600 last_name = name; 617 - last_pmu = evsel->pmu_name; 601 + last_pmu = evsel->pmu; 618 602 } 619 603 620 604 /** ··· 724 708 725 709 if (unit != ' ') 726 710 snprintf(unit_buf, sizeof(unit_buf), "%c/sec", unit); 727 - print_metric(config, ctxp, NULL, "%8.3f", unit_buf, ratio); 728 - } else 711 + print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, "%8.3f", 712 + unit_buf, ratio); 713 + } else { 729 714 num = 0; 715 + } 730 716 } 731 717 } 732 718 733 719 perf_stat__print_shadow_stats_metricgroup(config, evsel, aggr_idx, 734 720 &num, NULL, out, metric_events); 735 721 736 - if (num == 0) 737 - print_metric(config, ctxp, NULL, NULL, NULL, 0); 722 + if (num == 0) { 723 + print_metric(config, ctxp, METRIC_THRESHOLD_UNKNOWN, 724 + /*fmt=*/NULL, /*unit=*/NULL, 0); 725 + } 738 726 } 739 727 740 728 /**
+1 -1
tools/perf/util/stat.c
··· 553 553 if (evsel__is_clock(evsel_a) != evsel__is_clock(evsel_b)) 554 554 return false; 555 555 556 - return !!strcmp(evsel_a->pmu_name, evsel_b->pmu_name); 556 + return evsel_a->pmu != evsel_b->pmu; 557 557 } 558 558 559 559 static void evsel__merge_aliases(struct evsel *evsel)
+14 -2
tools/perf/util/stat.h
··· 154 154 extern struct stats walltime_nsecs_stats; 155 155 extern struct rusage_stats ru_stats; 156 156 157 + enum metric_threshold_classify { 158 + METRIC_THRESHOLD_UNKNOWN, 159 + METRIC_THRESHOLD_BAD, 160 + METRIC_THRESHOLD_NEARLY_BAD, 161 + METRIC_THRESHOLD_LESS_GOOD, 162 + METRIC_THRESHOLD_GOOD, 163 + }; 164 + const char *metric_threshold_classify__color(enum metric_threshold_classify thresh); 165 + 157 166 typedef void (*print_metric_t)(struct perf_stat_config *config, 158 - void *ctx, const char *color, const char *unit, 159 - const char *fmt, double val); 167 + void *ctx, 168 + enum metric_threshold_classify thresh, 169 + const char *fmt, 170 + const char *unit, 171 + double val); 160 172 typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx); 161 173 162 174 /* Used to print the display name of the Default metricgroup for now. */
+100
tools/perf/util/string.c
··· 263 263 return ptr; 264 264 } 265 265 266 + /* Like strpbrk_esc(), but not break if it is quoted with single/double quotes */ 267 + char *strpbrk_esq(char *str, const char *stopset) 268 + { 269 + char *_stopset = NULL; 270 + char *ptr; 271 + const char *squote = "'"; 272 + const char *dquote = "\""; 273 + 274 + if (asprintf(&_stopset, "%s%c%c", stopset, *squote, *dquote) < 0) 275 + return NULL; 276 + 277 + do { 278 + ptr = strpbrk_esc(str, _stopset); 279 + if (!ptr) 280 + break; 281 + if (*ptr == *squote) 282 + ptr = strpbrk_esc(ptr + 1, squote); 283 + else if (*ptr == *dquote) 284 + ptr = strpbrk_esc(ptr + 1, dquote); 285 + else 286 + break; 287 + str = ptr + 1; 288 + } while (ptr); 289 + 290 + free(_stopset); 291 + return ptr; 292 + } 293 + 266 294 /* Like strdup, but do not copy a single backslash */ 267 295 char *strdup_esc(const char *str) 268 296 { ··· 319 291 } while (p); 320 292 321 293 return ret; 294 + } 295 + 296 + /* Remove backslash right before quote and return next quote address. */ 297 + static char *remove_consumed_esc(char *str, int len, int quote) 298 + { 299 + char *ptr = str, *end = str + len; 300 + 301 + while (*ptr != quote && ptr < end) { 302 + if (*ptr == '\\' && *(ptr + 1) == quote) { 303 + memmove(ptr, ptr + 1, end - (ptr + 1)); 304 + /* now *ptr is `quote`. */ 305 + end--; 306 + } 307 + ptr++; 308 + } 309 + 310 + return *ptr == quote ? ptr : NULL; 311 + } 312 + 313 + /* 314 + * Like strdup_esc, but keep quoted string as it is (and single backslash 315 + * before quote is removed). If there is no closed quote, return NULL. 316 + */ 317 + char *strdup_esq(const char *str) 318 + { 319 + char *d, *ret; 320 + 321 + /* If there is no quote, return normal strdup_esc() */ 322 + d = strpbrk_esc((char *)str, "\"'"); 323 + if (!d) 324 + return strdup_esc(str); 325 + 326 + ret = strdup(str); 327 + if (!ret) 328 + return NULL; 329 + 330 + d = ret; 331 + do { 332 + d = strpbrk(d, "\\\"\'"); 333 + if (!d) 334 + break; 335 + 336 + if (*d == '"' || *d == '\'') { 337 + /* This is non-escaped quote */ 338 + int quote = *d; 339 + int len = strlen(d + 1) + 1; 340 + 341 + /* 342 + * Remove the start quote and remove consumed escape (backslash 343 + * before quote) and remove the end quote. If there is no end 344 + * quote, it is the input error. 345 + */ 346 + memmove(d, d + 1, len); 347 + d = remove_consumed_esc(d, len, quote); 348 + if (!d) 349 + goto error; 350 + memmove(d, d + 1, strlen(d + 1) + 1); 351 + } 352 + if (*d == '\\') { 353 + memmove(d, d + 1, strlen(d + 1) + 1); 354 + if (*d == '\\') { 355 + /* double backslash -- keep the second one. */ 356 + d++; 357 + } 358 + } 359 + } while (*d != '\0'); 360 + 361 + return ret; 362 + 363 + error: 364 + free(ret); 365 + return NULL; 322 366 } 323 367 324 368 unsigned int hex(char c)
+2
tools/perf/util/string2.h
··· 37 37 38 38 char *strpbrk_esc(char *str, const char *stopset); 39 39 char *strdup_esc(const char *str); 40 + char *strpbrk_esq(char *str, const char *stopset); 41 + char *strdup_esq(const char *str); 40 42 41 43 unsigned int hex(char c); 42 44 char *strreplace_chars(char needle, const char *haystack, const char *replace);
+1 -1
tools/perf/util/symbol.c
··· 257 257 * like in: 258 258 * ffffffffc1937000 T hdmi_driver_init [snd_hda_codec_hdmi] 259 259 */ 260 - if (prev->end == prev->start) { 260 + if (prev->end == prev->start && prev->type != STT_NOTYPE) { 261 261 const char *prev_mod; 262 262 const char *curr_mod; 263 263
+4
tools/perf/util/syscalltbl.c
··· 46 46 #include <asm/syscalls.c> 47 47 const int syscalltbl_native_max_id = SYSCALLTBL_LOONGARCH_MAX_ID; 48 48 static const char *const *syscalltbl_native = syscalltbl_loongarch; 49 + #elif defined(__riscv) 50 + #include <asm/syscalls.c> 51 + const int syscalltbl_native_max_id = SYSCALLTBL_RISCV_MAX_ID; 52 + static const char *const *syscalltbl_native = syscalltbl_riscv; 49 53 #else 50 54 const int syscalltbl_native_max_id = 0; 51 55 static const char *const syscalltbl_native[] = {
+1
tools/perf/util/target.h
··· 17 17 bool default_per_cpu; 18 18 bool per_thread; 19 19 bool use_bpf; 20 + bool inherit; 20 21 int initial_delay; 21 22 const char *attr_map; 22 23 };
+2 -2
tools/perf/util/threads.c
··· 141 141 142 142 down_write(&table->lock); 143 143 __threads_table_entry__set_last_match(table, NULL); 144 - hashmap__for_each_entry_safe((&table->shard), cur, tmp, bkt) { 144 + hashmap__for_each_entry_safe(&table->shard, cur, tmp, bkt) { 145 145 struct thread *old_value; 146 146 147 147 hashmap__delete(&table->shard, cur->key, /*old_key=*/NULL, &old_value); ··· 175 175 size_t bkt; 176 176 177 177 down_read(&table->lock); 178 - hashmap__for_each_entry((&table->shard), cur, bkt) { 178 + hashmap__for_each_entry(&table->shard, cur, bkt) { 179 179 int rc = fn((struct thread *)cur->pvalue, data); 180 180 181 181 if (rc != 0) {
+505
tools/perf/util/tool_pmu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + #include "cgroup.h" 3 + #include "counts.h" 4 + #include "cputopo.h" 5 + #include "evsel.h" 6 + #include "pmu.h" 7 + #include "print-events.h" 8 + #include "smt.h" 9 + #include "time-utils.h" 10 + #include "tool_pmu.h" 11 + #include "tsc.h" 12 + #include <api/fs/fs.h> 13 + #include <api/io.h> 14 + #include <internal/threadmap.h> 15 + #include <perf/threadmap.h> 16 + #include <fcntl.h> 17 + #include <strings.h> 18 + 19 + static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = { 20 + NULL, 21 + "duration_time", 22 + "user_time", 23 + "system_time", 24 + "has_pmem", 25 + "num_cores", 26 + "num_cpus", 27 + "num_cpus_online", 28 + "num_dies", 29 + "num_packages", 30 + "slots", 31 + "smt_on", 32 + "system_tsc_freq", 33 + }; 34 + 35 + bool tool_pmu__skip_event(const char *name __maybe_unused) 36 + { 37 + #if !defined(__aarch64__) 38 + /* The slots event should only appear on arm64. */ 39 + if (strcasecmp(name, "slots") == 0) 40 + return true; 41 + #endif 42 + #if !defined(__i386__) && !defined(__x86_64__) 43 + /* The system_tsc_freq event should only appear on x86. */ 44 + if (strcasecmp(name, "system_tsc_freq") == 0) 45 + return true; 46 + #endif 47 + return false; 48 + } 49 + 50 + int tool_pmu__num_skip_events(void) 51 + { 52 + int num = 0; 53 + 54 + #if !defined(__aarch64__) 55 + num++; 56 + #endif 57 + #if !defined(__i386__) && !defined(__x86_64__) 58 + num++; 59 + #endif 60 + return num; 61 + } 62 + 63 + const char *tool_pmu__event_to_str(enum tool_pmu_event ev) 64 + { 65 + if (ev > TOOL_PMU__EVENT_NONE && ev < TOOL_PMU__EVENT_MAX) 66 + return tool_pmu__event_names[ev]; 67 + 68 + return NULL; 69 + } 70 + 71 + enum tool_pmu_event tool_pmu__str_to_event(const char *str) 72 + { 73 + int i; 74 + 75 + if (tool_pmu__skip_event(str)) 76 + return TOOL_PMU__EVENT_NONE; 77 + 78 + tool_pmu__for_each_event(i) { 79 + if (!strcasecmp(str, tool_pmu__event_names[i])) 80 + return i; 81 + } 82 + return TOOL_PMU__EVENT_NONE; 83 + } 84 + 85 + bool perf_pmu__is_tool(const struct perf_pmu *pmu) 86 + { 87 + return pmu && pmu->type == PERF_PMU_TYPE_TOOL; 88 + } 89 + 90 + bool evsel__is_tool(const struct evsel *evsel) 91 + { 92 + return perf_pmu__is_tool(evsel->pmu); 93 + } 94 + 95 + enum tool_pmu_event evsel__tool_event(const struct evsel *evsel) 96 + { 97 + if (!evsel__is_tool(evsel)) 98 + return TOOL_PMU__EVENT_NONE; 99 + 100 + return (enum tool_pmu_event)evsel->core.attr.config; 101 + } 102 + 103 + const char *evsel__tool_pmu_event_name(const struct evsel *evsel) 104 + { 105 + return tool_pmu__event_to_str(evsel->core.attr.config); 106 + } 107 + 108 + static bool read_until_char(struct io *io, char e) 109 + { 110 + int c; 111 + 112 + do { 113 + c = io__get_char(io); 114 + if (c == -1) 115 + return false; 116 + } while (c != e); 117 + return true; 118 + } 119 + 120 + static int read_stat_field(int fd, struct perf_cpu cpu, int field, __u64 *val) 121 + { 122 + char buf[256]; 123 + struct io io; 124 + int i; 125 + 126 + io__init(&io, fd, buf, sizeof(buf)); 127 + 128 + /* Skip lines to relevant CPU. */ 129 + for (i = -1; i < cpu.cpu; i++) { 130 + if (!read_until_char(&io, '\n')) 131 + return -EINVAL; 132 + } 133 + /* Skip to "cpu". */ 134 + if (io__get_char(&io) != 'c') return -EINVAL; 135 + if (io__get_char(&io) != 'p') return -EINVAL; 136 + if (io__get_char(&io) != 'u') return -EINVAL; 137 + 138 + /* Skip N of cpuN. */ 139 + if (!read_until_char(&io, ' ')) 140 + return -EINVAL; 141 + 142 + i = 1; 143 + while (true) { 144 + if (io__get_dec(&io, val) != ' ') 145 + break; 146 + if (field == i) 147 + return 0; 148 + i++; 149 + } 150 + return -EINVAL; 151 + } 152 + 153 + static int read_pid_stat_field(int fd, int field, __u64 *val) 154 + { 155 + char buf[256]; 156 + struct io io; 157 + int c, i; 158 + 159 + io__init(&io, fd, buf, sizeof(buf)); 160 + if (io__get_dec(&io, val) != ' ') 161 + return -EINVAL; 162 + if (field == 1) 163 + return 0; 164 + 165 + /* Skip comm. */ 166 + if (io__get_char(&io) != '(' || !read_until_char(&io, ')')) 167 + return -EINVAL; 168 + if (field == 2) 169 + return -EINVAL; /* String can't be returned. */ 170 + 171 + /* Skip state */ 172 + if (io__get_char(&io) != ' ' || io__get_char(&io) == -1) 173 + return -EINVAL; 174 + if (field == 3) 175 + return -EINVAL; /* String can't be returned. */ 176 + 177 + /* Loop over numeric fields*/ 178 + if (io__get_char(&io) != ' ') 179 + return -EINVAL; 180 + 181 + i = 4; 182 + while (true) { 183 + c = io__get_dec(&io, val); 184 + if (c == -1) 185 + return -EINVAL; 186 + if (c == -2) { 187 + /* Assume a -ve was read */ 188 + c = io__get_dec(&io, val); 189 + *val *= -1; 190 + } 191 + if (c != ' ') 192 + return -EINVAL; 193 + if (field == i) 194 + return 0; 195 + i++; 196 + } 197 + return -EINVAL; 198 + } 199 + 200 + int evsel__tool_pmu_prepare_open(struct evsel *evsel, 201 + struct perf_cpu_map *cpus, 202 + int nthreads) 203 + { 204 + if ((evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME || 205 + evsel__tool_event(evsel) == TOOL_PMU__EVENT_USER_TIME) && 206 + !evsel->start_times) { 207 + evsel->start_times = xyarray__new(perf_cpu_map__nr(cpus), 208 + nthreads, 209 + sizeof(__u64)); 210 + if (!evsel->start_times) 211 + return -ENOMEM; 212 + } 213 + return 0; 214 + } 215 + 216 + #define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y)) 217 + 218 + int evsel__tool_pmu_open(struct evsel *evsel, 219 + struct perf_thread_map *threads, 220 + int start_cpu_map_idx, int end_cpu_map_idx) 221 + { 222 + enum tool_pmu_event ev = evsel__tool_event(evsel); 223 + int pid = -1, idx = 0, thread = 0, nthreads, err = 0, old_errno; 224 + 225 + if (ev == TOOL_PMU__EVENT_NUM_CPUS) 226 + return 0; 227 + 228 + if (ev == TOOL_PMU__EVENT_DURATION_TIME) { 229 + if (evsel->core.attr.sample_period) /* no sampling */ 230 + return -EINVAL; 231 + evsel->start_time = rdclock(); 232 + return 0; 233 + } 234 + 235 + if (evsel->cgrp) 236 + pid = evsel->cgrp->fd; 237 + 238 + nthreads = perf_thread_map__nr(threads); 239 + for (idx = start_cpu_map_idx; idx < end_cpu_map_idx; idx++) { 240 + for (thread = 0; thread < nthreads; thread++) { 241 + if (thread >= nthreads) 242 + break; 243 + 244 + if (!evsel->cgrp && !evsel->core.system_wide) 245 + pid = perf_thread_map__pid(threads, thread); 246 + 247 + if (ev == TOOL_PMU__EVENT_USER_TIME || ev == TOOL_PMU__EVENT_SYSTEM_TIME) { 248 + bool system = ev == TOOL_PMU__EVENT_SYSTEM_TIME; 249 + __u64 *start_time = NULL; 250 + int fd; 251 + 252 + if (evsel->core.attr.sample_period) { 253 + /* no sampling */ 254 + err = -EINVAL; 255 + goto out_close; 256 + } 257 + if (pid > -1) { 258 + char buf[64]; 259 + 260 + snprintf(buf, sizeof(buf), "/proc/%d/stat", pid); 261 + fd = open(buf, O_RDONLY); 262 + evsel->pid_stat = true; 263 + } else { 264 + fd = open("/proc/stat", O_RDONLY); 265 + } 266 + FD(evsel, idx, thread) = fd; 267 + if (fd < 0) { 268 + err = -errno; 269 + goto out_close; 270 + } 271 + start_time = xyarray__entry(evsel->start_times, idx, thread); 272 + if (pid > -1) { 273 + err = read_pid_stat_field(fd, system ? 15 : 14, 274 + start_time); 275 + } else { 276 + struct perf_cpu cpu; 277 + 278 + cpu = perf_cpu_map__cpu(evsel->core.cpus, idx); 279 + err = read_stat_field(fd, cpu, system ? 3 : 1, 280 + start_time); 281 + } 282 + if (err) 283 + goto out_close; 284 + } 285 + 286 + } 287 + } 288 + return 0; 289 + out_close: 290 + if (err) 291 + threads->err_thread = thread; 292 + 293 + old_errno = errno; 294 + do { 295 + while (--thread >= 0) { 296 + if (FD(evsel, idx, thread) >= 0) 297 + close(FD(evsel, idx, thread)); 298 + FD(evsel, idx, thread) = -1; 299 + } 300 + thread = nthreads; 301 + } while (--idx >= 0); 302 + errno = old_errno; 303 + return err; 304 + } 305 + 306 + #if !defined(__i386__) && !defined(__x86_64__) 307 + u64 arch_get_tsc_freq(void) 308 + { 309 + return 0; 310 + } 311 + #endif 312 + 313 + #if !defined(__aarch64__) 314 + u64 tool_pmu__cpu_slots_per_cycle(void) 315 + { 316 + return 0; 317 + } 318 + #endif 319 + 320 + static bool has_pmem(void) 321 + { 322 + static bool has_pmem, cached; 323 + const char *sysfs = sysfs__mountpoint(); 324 + char path[PATH_MAX]; 325 + 326 + if (!cached) { 327 + snprintf(path, sizeof(path), "%s/firmware/acpi/tables/NFIT", sysfs); 328 + has_pmem = access(path, F_OK) == 0; 329 + cached = true; 330 + } 331 + return has_pmem; 332 + } 333 + 334 + bool tool_pmu__read_event(enum tool_pmu_event ev, u64 *result) 335 + { 336 + const struct cpu_topology *topology; 337 + 338 + switch (ev) { 339 + case TOOL_PMU__EVENT_HAS_PMEM: 340 + *result = has_pmem() ? 1 : 0; 341 + return true; 342 + 343 + case TOOL_PMU__EVENT_NUM_CORES: 344 + topology = online_topology(); 345 + *result = topology->core_cpus_lists; 346 + return true; 347 + 348 + case TOOL_PMU__EVENT_NUM_CPUS: 349 + *result = cpu__max_present_cpu().cpu; 350 + return true; 351 + 352 + case TOOL_PMU__EVENT_NUM_CPUS_ONLINE: { 353 + struct perf_cpu_map *online = cpu_map__online(); 354 + 355 + if (online) { 356 + *result = perf_cpu_map__nr(online); 357 + return true; 358 + } 359 + return false; 360 + } 361 + case TOOL_PMU__EVENT_NUM_DIES: 362 + topology = online_topology(); 363 + *result = topology->die_cpus_lists; 364 + return true; 365 + 366 + case TOOL_PMU__EVENT_NUM_PACKAGES: 367 + topology = online_topology(); 368 + *result = topology->package_cpus_lists; 369 + return true; 370 + 371 + case TOOL_PMU__EVENT_SLOTS: 372 + *result = tool_pmu__cpu_slots_per_cycle(); 373 + return *result ? true : false; 374 + 375 + case TOOL_PMU__EVENT_SMT_ON: 376 + *result = smt_on() ? 1 : 0; 377 + return true; 378 + 379 + case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ: 380 + *result = arch_get_tsc_freq(); 381 + return true; 382 + 383 + case TOOL_PMU__EVENT_NONE: 384 + case TOOL_PMU__EVENT_DURATION_TIME: 385 + case TOOL_PMU__EVENT_USER_TIME: 386 + case TOOL_PMU__EVENT_SYSTEM_TIME: 387 + case TOOL_PMU__EVENT_MAX: 388 + default: 389 + return false; 390 + } 391 + } 392 + 393 + int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread) 394 + { 395 + __u64 *start_time, cur_time, delta_start; 396 + u64 val; 397 + int fd, err = 0; 398 + struct perf_counts_values *count, *old_count = NULL; 399 + bool adjust = false; 400 + enum tool_pmu_event ev = evsel__tool_event(evsel); 401 + 402 + count = perf_counts(evsel->counts, cpu_map_idx, thread); 403 + 404 + switch (ev) { 405 + case TOOL_PMU__EVENT_HAS_PMEM: 406 + case TOOL_PMU__EVENT_NUM_CORES: 407 + case TOOL_PMU__EVENT_NUM_CPUS: 408 + case TOOL_PMU__EVENT_NUM_CPUS_ONLINE: 409 + case TOOL_PMU__EVENT_NUM_DIES: 410 + case TOOL_PMU__EVENT_NUM_PACKAGES: 411 + case TOOL_PMU__EVENT_SLOTS: 412 + case TOOL_PMU__EVENT_SMT_ON: 413 + case TOOL_PMU__EVENT_SYSTEM_TSC_FREQ: 414 + if (evsel->prev_raw_counts) 415 + old_count = perf_counts(evsel->prev_raw_counts, cpu_map_idx, thread); 416 + val = 0; 417 + if (cpu_map_idx == 0 && thread == 0) { 418 + if (!tool_pmu__read_event(ev, &val)) { 419 + count->lost++; 420 + val = 0; 421 + } 422 + } 423 + if (old_count) { 424 + count->val = old_count->val + val; 425 + count->run = old_count->run + 1; 426 + count->ena = old_count->ena + 1; 427 + } else { 428 + count->val = val; 429 + count->run++; 430 + count->ena++; 431 + } 432 + return 0; 433 + case TOOL_PMU__EVENT_DURATION_TIME: 434 + /* 435 + * Pretend duration_time is only on the first CPU and thread, or 436 + * else aggregation will scale duration_time by the number of 437 + * CPUs/threads. 438 + */ 439 + start_time = &evsel->start_time; 440 + if (cpu_map_idx == 0 && thread == 0) 441 + cur_time = rdclock(); 442 + else 443 + cur_time = *start_time; 444 + break; 445 + case TOOL_PMU__EVENT_USER_TIME: 446 + case TOOL_PMU__EVENT_SYSTEM_TIME: { 447 + bool system = evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME; 448 + 449 + start_time = xyarray__entry(evsel->start_times, cpu_map_idx, thread); 450 + fd = FD(evsel, cpu_map_idx, thread); 451 + lseek(fd, SEEK_SET, 0); 452 + if (evsel->pid_stat) { 453 + /* The event exists solely on 1 CPU. */ 454 + if (cpu_map_idx == 0) 455 + err = read_pid_stat_field(fd, system ? 15 : 14, &cur_time); 456 + else 457 + cur_time = 0; 458 + } else { 459 + /* The event is for all threads. */ 460 + if (thread == 0) { 461 + struct perf_cpu cpu = perf_cpu_map__cpu(evsel->core.cpus, 462 + cpu_map_idx); 463 + 464 + err = read_stat_field(fd, cpu, system ? 3 : 1, &cur_time); 465 + } else { 466 + cur_time = 0; 467 + } 468 + } 469 + adjust = true; 470 + break; 471 + } 472 + case TOOL_PMU__EVENT_NONE: 473 + case TOOL_PMU__EVENT_MAX: 474 + default: 475 + err = -EINVAL; 476 + } 477 + if (err) 478 + return err; 479 + 480 + delta_start = cur_time - *start_time; 481 + if (adjust) { 482 + __u64 ticks_per_sec = sysconf(_SC_CLK_TCK); 483 + 484 + delta_start *= 1000000000 / ticks_per_sec; 485 + } 486 + count->val = delta_start; 487 + count->ena = count->run = delta_start; 488 + count->lost = 0; 489 + return 0; 490 + } 491 + 492 + struct perf_pmu *perf_pmus__tool_pmu(void) 493 + { 494 + static struct perf_pmu tool = { 495 + .name = "tool", 496 + .type = PERF_PMU_TYPE_TOOL, 497 + .aliases = LIST_HEAD_INIT(tool.aliases), 498 + .caps = LIST_HEAD_INIT(tool.caps), 499 + .format = LIST_HEAD_INIT(tool.format), 500 + }; 501 + if (!tool.events_table) 502 + tool.events_table = find_core_events_table("common", "common"); 503 + 504 + return &tool; 505 + }
+56
tools/perf/util/tool_pmu.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __TOOL_PMU_H 3 + #define __TOOL_PMU_H 4 + 5 + #include "pmu.h" 6 + 7 + struct evsel; 8 + struct perf_thread_map; 9 + struct print_callbacks; 10 + 11 + enum tool_pmu_event { 12 + TOOL_PMU__EVENT_NONE = 0, 13 + TOOL_PMU__EVENT_DURATION_TIME, 14 + TOOL_PMU__EVENT_USER_TIME, 15 + TOOL_PMU__EVENT_SYSTEM_TIME, 16 + TOOL_PMU__EVENT_HAS_PMEM, 17 + TOOL_PMU__EVENT_NUM_CORES, 18 + TOOL_PMU__EVENT_NUM_CPUS, 19 + TOOL_PMU__EVENT_NUM_CPUS_ONLINE, 20 + TOOL_PMU__EVENT_NUM_DIES, 21 + TOOL_PMU__EVENT_NUM_PACKAGES, 22 + TOOL_PMU__EVENT_SLOTS, 23 + TOOL_PMU__EVENT_SMT_ON, 24 + TOOL_PMU__EVENT_SYSTEM_TSC_FREQ, 25 + 26 + TOOL_PMU__EVENT_MAX, 27 + }; 28 + 29 + #define tool_pmu__for_each_event(ev) \ 30 + for ((ev) = TOOL_PMU__EVENT_DURATION_TIME; (ev) < TOOL_PMU__EVENT_MAX; ev++) 31 + 32 + const char *tool_pmu__event_to_str(enum tool_pmu_event ev); 33 + enum tool_pmu_event tool_pmu__str_to_event(const char *str); 34 + bool tool_pmu__skip_event(const char *name); 35 + int tool_pmu__num_skip_events(void); 36 + 37 + bool tool_pmu__read_event(enum tool_pmu_event ev, u64 *result); 38 + 39 + u64 tool_pmu__cpu_slots_per_cycle(void); 40 + 41 + bool perf_pmu__is_tool(const struct perf_pmu *pmu); 42 + 43 + bool evsel__is_tool(const struct evsel *evsel); 44 + enum tool_pmu_event evsel__tool_event(const struct evsel *evsel); 45 + const char *evsel__tool_pmu_event_name(const struct evsel *evsel); 46 + int evsel__tool_pmu_prepare_open(struct evsel *evsel, 47 + struct perf_cpu_map *cpus, 48 + int nthreads); 49 + int evsel__tool_pmu_open(struct evsel *evsel, 50 + struct perf_thread_map *threads, 51 + int start_cpu_map_idx, int end_cpu_map_idx); 52 + int evsel__tool_pmu_read(struct evsel *evsel, int cpu_map_idx, int thread); 53 + 54 + struct perf_pmu *perf_pmus__tool_pmu(void); 55 + 56 + #endif /* __TOOL_PMU_H */
+1 -7
tools/perf/util/trace-event-parse.c
··· 12 12 13 13 #include <linux/ctype.h> 14 14 #include <linux/kernel.h> 15 - #include <traceevent/event-parse.h> 15 + #include <event-parse.h> 16 16 17 17 static int get_common_field(struct scripting_context *context, 18 18 int *offset, int *size, const char *type) ··· 114 114 tep_print_event(event->tep, &s, &record, "%s", TEP_PRINT_INFO); 115 115 trace_seq_do_fprintf(&s, fp); 116 116 trace_seq_destroy(&s); 117 - } 118 - 119 - void event_format__print(struct tep_event *event, 120 - int cpu, void *data, int size) 121 - { 122 - return event_format__fprintf(event, cpu, data, size, stdout); 123 117 } 124 118 125 119 /*
+1 -1
tools/perf/util/trace-event-read.c
··· 11 11 #include <sys/stat.h> 12 12 #include <sys/wait.h> 13 13 #include <sys/mman.h> 14 - #include <traceevent/event-parse.h> 14 + #include <event-parse.h> 15 15 #include <fcntl.h> 16 16 #include <unistd.h> 17 17 #include <errno.h>
+1 -1
tools/perf/util/trace-event-scripting.c
··· 10 10 #include <string.h> 11 11 #include <errno.h> 12 12 #ifdef HAVE_LIBTRACEEVENT 13 - #include <traceevent/event-parse.h> 13 + #include <event-parse.h> 14 14 #endif 15 15 16 16 #include "debug.h"
+1 -1
tools/perf/util/trace-event.c
··· 8 8 #include <fcntl.h> 9 9 #include <linux/kernel.h> 10 10 #include <linux/err.h> 11 - #include <traceevent/event-parse.h> 11 + #include <event-parse.h> 12 12 #include <api/fs/tracing_path.h> 13 13 #include <api/fs/fs.h> 14 14 #include "trace-event.h"
+1 -4
tools/perf/util/trace-event.h
··· 42 42 void event_format__fprintf(struct tep_event *event, 43 43 int cpu, void *data, int size, FILE *fp); 44 44 45 - void event_format__print(struct tep_event *event, 46 - int cpu, void *data, int size); 47 - 48 45 int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size); 49 46 int parse_event_file(struct tep_handle *pevent, 50 47 char *buf, unsigned long size, char *sys); ··· 147 150 int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz); 148 151 149 152 #if defined(LIBTRACEEVENT_VERSION) && LIBTRACEEVENT_VERSION >= MAKE_LIBTRACEEVENT_VERSION(1, 5, 0) 150 - #include <traceevent/event-parse.h> 153 + #include <event-parse.h> 151 154 152 155 static inline bool tep_field_is_relative(unsigned long flags) 153 156 {
+1 -1
tools/perf/util/tsc.c
··· 119 119 size_t ret; 120 120 121 121 ret = fprintf(fp, "\n... Time Shift %" PRI_lu64 "\n", tc->time_shift); 122 - ret += fprintf(fp, "... Time Muliplier %" PRI_lu64 "\n", tc->time_mult); 122 + ret += fprintf(fp, "... Time Multiplier %" PRI_lu64 "\n", tc->time_mult); 123 123 ret += fprintf(fp, "... Time Zero %" PRI_lu64 "\n", tc->time_zero); 124 124 125 125 /*
+1 -1
tools/perf/util/tsc.h
··· 25 25 u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); 26 26 u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); 27 27 u64 rdtsc(void); 28 - double arch_get_tsc_freq(void); 28 + u64 arch_get_tsc_freq(void); 29 29 30 30 size_t perf_event__fprintf_time_conv(union perf_event *event, FILE *fp); 31 31
+8 -87
tools/perf/util/util.c
··· 78 78 79 79 bool test_attr__enabled; 80 80 81 + bool exclude_GH_default; 82 + 81 83 bool perf_host = true; 82 84 bool perf_guest = false; 83 85 84 86 void event_attr_init(struct perf_event_attr *attr) 85 87 { 88 + /* to capture ABI version */ 89 + attr->size = sizeof(*attr); 90 + 91 + if (!exclude_GH_default) 92 + return; 93 + 86 94 if (!perf_host) 87 95 attr->exclude_host = 1; 88 96 if (!perf_guest) 89 97 attr->exclude_guest = 1; 90 - /* to capture ABI version */ 91 - attr->size = sizeof(*attr); 92 98 } 93 99 94 100 int mkdir_p(char *path, mode_t mode) ··· 340 334 return true; 341 335 342 336 return perf_event_paranoid() <= max_level; 343 - } 344 - 345 - static int 346 - fetch_ubuntu_kernel_version(unsigned int *puint) 347 - { 348 - ssize_t len; 349 - size_t line_len = 0; 350 - char *ptr, *line = NULL; 351 - int version, patchlevel, sublevel, err; 352 - FILE *vsig; 353 - 354 - if (!puint) 355 - return 0; 356 - 357 - vsig = fopen("/proc/version_signature", "r"); 358 - if (!vsig) { 359 - pr_debug("Open /proc/version_signature failed: %s\n", 360 - strerror(errno)); 361 - return -1; 362 - } 363 - 364 - len = getline(&line, &line_len, vsig); 365 - fclose(vsig); 366 - err = -1; 367 - if (len <= 0) { 368 - pr_debug("Reading from /proc/version_signature failed: %s\n", 369 - strerror(errno)); 370 - goto errout; 371 - } 372 - 373 - ptr = strrchr(line, ' '); 374 - if (!ptr) { 375 - pr_debug("Parsing /proc/version_signature failed: %s\n", line); 376 - goto errout; 377 - } 378 - 379 - err = sscanf(ptr + 1, "%d.%d.%d", 380 - &version, &patchlevel, &sublevel); 381 - if (err != 3) { 382 - pr_debug("Unable to get kernel version from /proc/version_signature '%s'\n", 383 - line); 384 - goto errout; 385 - } 386 - 387 - *puint = (version << 16) + (patchlevel << 8) + sublevel; 388 - err = 0; 389 - errout: 390 - free(line); 391 - return err; 392 - } 393 - 394 - int 395 - fetch_kernel_version(unsigned int *puint, char *str, 396 - size_t str_size) 397 - { 398 - struct utsname utsname; 399 - int version, patchlevel, sublevel, err; 400 - bool int_ver_ready = false; 401 - 402 - if (access("/proc/version_signature", R_OK) == 0) 403 - if (!fetch_ubuntu_kernel_version(puint)) 404 - int_ver_ready = true; 405 - 406 - if (uname(&utsname)) 407 - return -1; 408 - 409 - if (str && str_size) { 410 - strncpy(str, utsname.release, str_size); 411 - str[str_size - 1] = '\0'; 412 - } 413 - 414 - if (!puint || int_ver_ready) 415 - return 0; 416 - 417 - err = sscanf(utsname.release, "%d.%d.%d", 418 - &version, &patchlevel, &sublevel); 419 - 420 - if (err != 3) { 421 - pr_debug("Unable to get kernel version from uname '%s'\n", 422 - utsname.release); 423 - return -1; 424 - } 425 - 426 - *puint = (version << 16) + (patchlevel << 8) + sublevel; 427 - return 0; 428 337 } 429 338 430 339 int perf_tip(char **strp, const char *dirpath)
+3 -15
tools/perf/util/util.h
··· 21 21 22 22 extern const char *input_name; 23 23 24 + /* This will control if perf_{host,guest} will set attr.exclude_{host,guest}. */ 25 + extern bool exclude_GH_default; 26 + 24 27 extern bool perf_host; 25 28 extern bool perf_guest; 26 29 ··· 45 42 int sysctl__max_stack(void); 46 43 47 44 bool sysctl__nmi_watchdog_enabled(void); 48 - 49 - int fetch_kernel_version(unsigned int *puint, 50 - char *str, size_t str_sz); 51 - #define KVER_VERSION(x) (((x) >> 16) & 0xff) 52 - #define KVER_PATCHLEVEL(x) (((x) >> 8) & 0xff) 53 - #define KVER_SUBLEVEL(x) ((x) & 0xff) 54 - #define KVER_FMT "%d.%d.%d" 55 - #define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) 56 45 57 46 int perf_tip(char **strp, const char *dirpath); 58 47 ··· 75 80 #define O_CLOEXEC 02000000 76 81 #endif 77 82 #endif 78 - 79 - extern bool test_attr__enabled; 80 - void test_attr__ready(void); 81 - void test_attr__init(void); 82 - struct perf_event_attr; 83 - void test_attr__open(struct perf_event_attr *attr, pid_t pid, struct perf_cpu cpu, 84 - int fd, int group_fd, unsigned long flags); 85 83 86 84 struct perf_debuginfod { 87 85 const char *urls;