summaryrefslogtreecommitdiff
path: root/tools/perf/tests
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-03-31 08:52:33 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2025-03-31 08:52:33 -0700
commit802f0d58d52e8e34e08718479475ccdff0caffa0 (patch)
tree305f3be98d12b0c6881a6c59eb92e795e6088e51 /tools/perf/tests
parent4e82c87058f45e79eeaa4d5bcc3b38dd3dce7209 (diff)
parent35d13f841a3d8159ef20d5e32a9ed3faa27875bc (diff)
Merge tag 'perf-tools-for-v6.15-2025-03-27' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools
Pull perf tools updates from Namhyung Kim: "perf record: - Introduce latency profiling using scheduler information. The latency profiling is to show impacts on wall-time rather than cpu-time. By tracking context switches, it can weight samples and find which part of the code contributed more to the execution latency. The value (period) of the sample is weighted by dividing it by the number of parallel execution at the moment. The parallelism is tracked in perf report with sched-switch records. This will reduce the portion that are run in parallel and in turn increase the portion of serial executions. For now, it's limited to profile processes, IOW system-wide profiling is not supported. You can add --latency option to enable this. $ perf record --latency -- make -C tools/perf I've run the above command for perf build which adds -j option to make with the number of CPUs in the system internally. Normally it'd show something like below: $ perf report -F overhead,comm ... # # Overhead Command # ........ ............... # 78.97% cc1 6.54% python3 4.21% shellcheck 3.28% ld 1.80% as 1.37% cc1plus 0.80% sh 0.62% clang 0.56% gcc 0.44% perl 0.39% make ... The cc1 takes around 80% of the overhead as it's the actual compiler. However it runs in parallel so its contribution to latency may be less than that. Now, perf report will show both overhead and latency (if --latency was given at record time) like below: $ perf report -s comm ... # # Overhead Latency Command # ........ ........ ............... # 78.97% 48.66% cc1 6.54% 25.68% python3 4.21% 0.39% shellcheck 3.28% 13.70% ld 1.80% 2.56% as 1.37% 3.08% cc1plus 0.80% 0.98% sh 0.62% 0.61% clang 0.56% 0.33% gcc 0.44% 1.71% perl 0.39% 0.83% make ... You can see latency of cc1 goes down to around 50% and python3 and ld contribute a lot more than their overhead. You can use --latency option in perf report to get the same result but ordered by latency. $ perf report --latency -s comm perf report: - As a side effect of the latency profiling work, it adds a new output field 'latency' and a sort key 'parallelism'. The below is a result from my system with 64 CPUs. The build was well-parallelized but contained some serial portions. $ perf report -s parallelism ... # # Overhead Latency Parallelism # ........ ........ ........... # 16.95% 1.54% 62 13.38% 1.24% 61 12.50% 70.47% 1 11.81% 1.06% 63 7.59% 0.71% 60 4.33% 12.20% 2 3.41% 0.33% 59 2.05% 0.18% 64 1.75% 1.09% 9 1.64% 1.85% 5 ... - Support Feodra mini-debuginfo which is a LZMA compressed symbol table inside ".gnu_debugdata" ELF section. perf annotate: - Add --code-with-type option to enable data-type profiling with the usual annotate output. Instead of focusing on data structure, it shows code annotation together with data type it accesses in case the instruction refers to a memory location (and it was able to resolve the target data type). Currently it only works with --stdio. $ perf annotate --stdio --code-with-type ... Percent | Source code & Disassembly of vmlinux for cpu/mem-loads,ldlat=30/pp (18 samples, percent: local period) ---------------------------------------------------------------------------------------------------------------------- : 0 0xffffffff81050610 <__fdget>: 0.00 : ffffffff81050610: callq 0xffffffff81c01b80 <__fentry__> # data-type: (stack operation) 0.00 : ffffffff81050615: pushq %rbp # data-type: (stack operation) 0.00 : ffffffff81050616: movq %rsp, %rbp 0.00 : ffffffff81050619: pushq %r15 # data-type: (stack operation) 0.00 : ffffffff8105061b: pushq %r14 # data-type: (stack operation) 0.00 : ffffffff8105061d: pushq %rbx # data-type: (stack operation) 0.00 : ffffffff8105061e: subq $0x10, %rsp 0.00 : ffffffff81050622: movl %edi, %ebx 0.00 : ffffffff81050624: movq %gs:0x7efc4814(%rip), %rax # 0x14e40 <current_task> # data-type: struct task_struct* +0 0.00 : ffffffff8105062c: movq 0x8d0(%rax), %r14 # data-type: struct task_struct +0x8d0 (files) 0.00 : ffffffff81050633: movl (%r14), %eax # data-type: struct files_struct +0 (count.counter) 0.00 : ffffffff81050636: cmpl $0x1, %eax 0.00 : ffffffff81050639: je 0xffffffff810506a9 <__fdget+0x99> 0.00 : ffffffff8105063b: movq 0x20(%r14), %rcx # data-type: struct files_struct +0x20 (fdt) 0.00 : ffffffff8105063f: movl (%rcx), %eax # data-type: struct fdtable +0 (max_fds) 0.00 : ffffffff81050641: cmpl %ebx, %eax 0.00 : ffffffff81050643: jbe 0xffffffff810506ef <__fdget+0xdf> 0.00 : ffffffff81050649: movl %ebx, %r15d 5.56 : ffffffff8105064c: movq 0x8(%rcx), %rdx # data-type: struct fdtable +0x8 (fd) ... The "# data-type:" part was added with this change. The first few entries are not very interesting. But later you can it accesses a couple of fields in the task_struct, files_struct and fdtable. perf trace: - Support syscall tracing for different ABI. For example it can trace system calls for 32-bit applications on 64-bit kernel transparently. - Add --summary-mode=total option to show global syscall summary. The default is 'thread' to show per-thread syscall summary. Python support: - Add more interfaces to 'perf' module to parse events, and config, enable or disable the event list properly so that it can implement basic functionalities purely in Python. There is an example code for these new interfaces in python/tracepoint.py. - Add mypy and pylint support to enable build time checking. Fix some code based on the findings from these tools. Internals: - Introduce io_dir__readdir() API to make directory traveral (usually for proc or sysfs) efficient with less memory footprint. JSON vendor events: - Add events and metrics for ARM Neoverse N3 and V3 - Update events and metrics on various Intel CPUs - Add/update events for a number of SiFive processors" * tag 'perf-tools-for-v6.15-2025-03-27' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools: (229 commits) perf bpf-filter: Fix a parsing error with comma perf report: Fix a memory leak for perf_env on AMD perf trace: Fix wrong size to bpf_map__update_elem call perf tools: annotate asm_pure_loop.S perf python: Fix setup.py mypy errors perf test: Address attr.py mypy error perf build: Add pylint build tests perf build: Add mypy build tests perf build: Rename TEST_LOGS to SHELL_TEST_LOGS tools/build: Don't pass test log files to linker perf bench sched pipe: fix enforced blocking reads in worker_thread perf tools: Fix is_compat_mode build break in ppc64 perf build: filter all combinations of -flto for libperl perf vendor events arm64 AmpereOneX: Fix frontend_bound calculation perf vendor events arm64: AmpereOne/AmpereOneX: Mark LD_RETIRED impacted by errata perf trace: Fix evlist memory leak perf trace: Fix BTF memory leak perf trace: Make syscall table stable perf syscalltbl: Mask off ABI type for MIPS system calls perf build: Remove Makefile.syscalls ...
Diffstat (limited to 'tools/perf/tests')
-rw-r--r--tools/perf/tests/Build32
-rw-r--r--tools/perf/tests/code-reading.c12
-rw-r--r--tools/perf/tests/dso-data.c28
-rw-r--r--tools/perf/tests/dwarf-unwind.c6
-rw-r--r--tools/perf/tests/event_update.c1
-rw-r--r--tools/perf/tests/hwmon_pmu.c16
-rw-r--r--tools/perf/tests/mmap-basic.c3
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c4
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c4
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c6
-rw-r--r--tools/perf/tests/perf-record.c2
-rw-r--r--tools/perf/tests/perf-time-to-tsc.c2
-rw-r--r--tools/perf/tests/pmu.c85
-rw-r--r--tools/perf/tests/sample-parsing.c62
-rwxr-xr-xtools/perf/tests/shell/annotate.sh56
-rwxr-xr-xtools/perf/tests/shell/base_report/setup.sh18
-rwxr-xr-xtools/perf/tests/shell/base_report/test_basic.sh52
-rw-r--r--tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S2
-rwxr-xr-xtools/perf/tests/shell/diff.sh12
-rw-r--r--tools/perf/tests/shell/lib/attr.py8
-rw-r--r--tools/perf/tests/shell/lib/perf_json_output_lint.py7
-rw-r--r--tools/perf/tests/shell/lib/stat_output.sh8
-rwxr-xr-xtools/perf/tests/shell/perftool-testsuite_probe.sh1
-rwxr-xr-xtools/perf/tests/shell/probe_vfs_getname.sh1
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh1
-rwxr-xr-xtools/perf/tests/shell/record+script_probe_vfs_getname.sh1
-rwxr-xr-xtools/perf/tests/shell/record.sh53
-rwxr-xr-xtools/perf/tests/shell/record_bpf_filter.sh4
-rwxr-xr-xtools/perf/tests/shell/stat+csv_output.sh2
-rwxr-xr-xtools/perf/tests/shell/stat+json_output.sh9
-rwxr-xr-xtools/perf/tests/shell/stat+std_output.sh8
-rwxr-xr-xtools/perf/tests/shell/stat.sh83
-rwxr-xr-xtools/perf/tests/shell/stat_all_metrics.sh8
-rwxr-xr-xtools/perf/tests/shell/stat_all_pmu.sh48
-rwxr-xr-xtools/perf/tests/shell/test_data_symbol.sh32
-rwxr-xr-xtools/perf/tests/shell/test_stat_intel_tpebs.sh89
-rwxr-xr-xtools/perf/tests/shell/test_uprobe_from_different_cu.sh11
-rwxr-xr-xtools/perf/tests/shell/trace+probe_vfs_getname.sh1
-rwxr-xr-xtools/perf/tests/shell/trace_btf_enum.sh1
-rwxr-xr-xtools/perf/tests/shell/trace_btf_general.sh1
-rwxr-xr-xtools/perf/tests/shell/trace_exit_race.sh1
-rwxr-xr-xtools/perf/tests/shell/trace_record_replay.sh21
-rw-r--r--tools/perf/tests/sw-clock.c3
-rw-r--r--tools/perf/tests/switch-tracking.c14
-rw-r--r--tools/perf/tests/tool_pmu.c4
-rw-r--r--tools/perf/tests/workloads/datasym.c34
46 files changed, 603 insertions, 254 deletions
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 4bf8d3f5eae7..934f32090553 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -80,14 +80,40 @@ perf-test-y += workloads/
ifdef SHELLCHECK
SHELL_TESTS := $(shell find tests/shell -executable -type f -name '*.sh')
- TEST_LOGS := $(SHELL_TESTS:tests/shell/%=shell/%.shellcheck_log)
+ SHELL_TEST_LOGS := $(SHELL_TESTS:tests/shell/%=shell/%.shellcheck_log)
else
SHELL_TESTS :=
- TEST_LOGS :=
+ SHELL_TEST_LOGS :=
endif
$(OUTPUT)%.shellcheck_log: %
$(call rule_mkdir)
$(Q)$(call echo-cmd,test)shellcheck -a -S warning "$<" > $@ || (cat $@ && rm $@ && false)
-perf-test-y += $(TEST_LOGS)
+perf-test-y += $(SHELL_TEST_LOGS)
+
+ifdef MYPY
+ PY_TESTS := $(shell find tests/shell -type f -name '*.py')
+ MYPY_TEST_LOGS := $(PY_TESTS:tests/shell/%=shell/%.mypy_log)
+else
+ MYPY_TEST_LOGS :=
+endif
+
+$(OUTPUT)%.mypy_log: %
+ $(call rule_mkdir)
+ $(Q)$(call echo-cmd,test)mypy "$<" > $@ || (cat $@ && rm $@ && false)
+
+perf-test-y += $(MYPY_TEST_LOGS)
+
+ifdef PYLINT
+ PY_TESTS := $(shell find tests/shell -type f -name '*.py')
+ PYLINT_TEST_LOGS := $(PY_TESTS:tests/shell/%=shell/%.pylint_log)
+else
+ PYLINT_TEST_LOGS :=
+endif
+
+$(OUTPUT)%.pylint_log: %
+ $(call rule_mkdir)
+ $(Q)$(call echo-cmd,test)pylint "$<" > $@ || (cat $@ && rm $@ && false)
+
+perf-test-y += $(PYLINT_TEST_LOGS)
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index b1abb34d7818..cf6edbe697b2 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -479,19 +479,25 @@ static int process_sample_event(struct machine *machine,
struct thread *thread;
int ret;
- if (evlist__parse_sample(evlist, event, &sample)) {
+ perf_sample__init(&sample, /*all=*/false);
+ ret = evlist__parse_sample(evlist, event, &sample);
+ if (ret) {
pr_debug("evlist__parse_sample failed\n");
- return -1;
+ ret = -1;
+ goto out;
}
thread = machine__findnew_thread(machine, sample.pid, sample.tid);
if (!thread) {
pr_debug("machine__findnew_thread failed\n");
- return -1;
+ ret = -1;
+ goto out;
}
ret = read_object_code(sample.ip, READLEN, sample.cpumode, thread, state);
thread__put(thread);
+out:
+ perf_sample__exit(&sample);
return ret;
}
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index 5286ae8bd2d7..a1fff4203b75 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -106,14 +106,25 @@ struct test_data_offset offsets[] = {
/* move it from util/dso.c for compatibility */
static int dso__data_fd(struct dso *dso, struct machine *machine)
{
- int fd = dso__data_get_fd(dso, machine);
+ int fd = -1;
- if (fd >= 0)
+ if (dso__data_get_fd(dso, machine, &fd))
dso__data_put_fd(dso);
return fd;
}
+static void dsos__delete(struct dsos *dsos)
+{
+ for (unsigned int i = 0; i < dsos->cnt; i++) {
+ struct dso *dso = dsos->dsos[i];
+
+ dso__data_close(dso);
+ unlink(dso__name(dso));
+ }
+ dsos__exit(dsos);
+}
+
static int test__dso_data(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct machine machine;
@@ -172,7 +183,7 @@ static int test__dso_data(struct test_suite *test __maybe_unused, int subtest __
}
dso__put(dso);
- dsos__exit(&machine.dsos);
+ dsos__delete(&machine.dsos);
unlink(file);
return 0;
}
@@ -222,17 +233,6 @@ static int dsos__create(int cnt, int size, struct dsos *dsos)
return 0;
}
-static void dsos__delete(struct dsos *dsos)
-{
- for (unsigned int i = 0; i < dsos->cnt; i++) {
- struct dso *dso = dsos->dsos[i];
-
- dso__data_close(dso);
- unlink(dso__name(dso));
- }
- dsos__exit(dsos);
-}
-
static int set_fd_limit(int n)
{
struct rlimit rlim;
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index f85d391ced98..4803ab2d97ba 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -115,8 +115,7 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__thread(struct thread *thr
unsigned long cnt = 0;
int err = -1;
- memset(&sample, 0, sizeof(sample));
-
+ perf_sample__init(&sample, /*all=*/true);
if (test__arch_unwind_sample(&sample, thread)) {
pr_debug("failed to get unwind sample\n");
goto out;
@@ -134,7 +133,8 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__thread(struct thread *thr
out:
zfree(&sample.user_stack.data);
- zfree(&sample.user_regs.regs);
+ zfree(&sample.user_regs->regs);
+ perf_sample__exit(&sample);
return err;
}
diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index d6b4ce3ef4ee..9301fde11366 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -109,6 +109,7 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
TEST_ASSERT_VAL("failed to synthesize attr update name",
!perf_event__synthesize_event_update_name(&tmp.tool, evsel, process_event_name));
+ perf_cpu_map__put(evsel->core.own_cpus);
evsel->core.own_cpus = perf_cpu_map__new("1,2,3");
TEST_ASSERT_VAL("failed to synthesize attr update cpus",
diff --git a/tools/perf/tests/hwmon_pmu.c b/tools/perf/tests/hwmon_pmu.c
index d2b066a2b557..0837aca1cdfa 100644
--- a/tools/perf/tests/hwmon_pmu.c
+++ b/tools/perf/tests/hwmon_pmu.c
@@ -13,17 +13,23 @@
static const struct test_event {
const char *name;
const char *alias;
- long config;
+ union hwmon_pmu_event_key key;
} test_events[] = {
{
"temp_test_hwmon_event1",
"temp1",
- 0xA0001,
+ .key = {
+ .num = 1,
+ .type = 10
+ },
},
{
"temp_test_hwmon_event2",
"temp2",
- 0xA0002,
+ .key = {
+ .num = 2,
+ .type = 10
+ },
},
};
@@ -183,11 +189,11 @@ static int do_test(size_t i, bool with_pmu, bool with_alias)
strcmp(evsel->pmu->name, "hwmon_a_test_hwmon_pmu"))
continue;
- if (evsel->core.attr.config != (u64)test_events[i].config) {
+ if (evsel->core.attr.config != (u64)test_events[i].key.type_and_num) {
pr_debug("FAILED %s:%d Unexpected config for '%s', %lld != %ld\n",
__FILE__, __LINE__, str,
evsel->core.attr.config,
- test_events[i].config);
+ test_events[i].key.type_and_num);
ret = TEST_FAIL;
goto out;
}
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 012c8ae439fd..bd2106628b34 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -130,14 +130,17 @@ static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest
goto out_delete_evlist;
}
+ perf_sample__init(&sample, /*all=*/false);
err = evlist__parse_sample(evlist, event, &sample);
if (err) {
pr_err("Can't parse sample, err = %d\n", err);
+ perf_sample__exit(&sample);
goto out_delete_evlist;
}
err = -1;
evsel = evlist__id2evsel(evlist, sample.id);
+ perf_sample__exit(&sample);
if (evsel == NULL) {
pr_debug("event with id %" PRIu64
" doesn't map to an evsel\n", sample.id);
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index ddd1da9a4ba9..446a3615d720 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -229,11 +229,11 @@ static int mmap_events(synth_cb synth)
static int test__mmap_thread_lookup(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
/* perf_event__synthesize_threads synthesize */
- TEST_ASSERT_VAL("failed with sythesizing all",
+ TEST_ASSERT_VAL("failed with synthesizing all",
!mmap_events(synth_all));
/* perf_event__synthesize_thread_map synthesize */
- TEST_ASSERT_VAL("failed with sythesizing process",
+ TEST_ASSERT_VAL("failed with synthesizing process",
!mmap_events(synth_process));
return 0;
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 3943da441979..0ef4ba7c1571 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -111,14 +111,16 @@ static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused
continue;
}
+ perf_sample__init(&sample, /*all=*/false);
err = evsel__parse_sample(evsel, event, &sample);
if (err) {
pr_debug("Can't parse sample, err = %d\n", err);
+ perf_sample__exit(&sample);
goto out_delete_evlist;
}
tp_flags = evsel__intval(evsel, &sample, "flags");
-
+ perf_sample__exit(&sample);
if (flags != tp_flags) {
pr_debug("%s: Expected flags=%#x, got %#x\n",
__func__, flags, tp_flags);
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c
index 202f0a9a6796..50e68b7d43aa 100644
--- a/tools/perf/tests/parse-no-sample-id-all.c
+++ b/tools/perf/tests/parse-no-sample-id-all.c
@@ -13,6 +13,7 @@
static int process_event(struct evlist **pevlist, union perf_event *event)
{
struct perf_sample sample;
+ int ret;
if (event->header.type == PERF_RECORD_HEADER_ATTR) {
if (perf_event__process_attr(NULL, event, pevlist)) {
@@ -28,7 +29,10 @@ static int process_event(struct evlist **pevlist, union perf_event *event)
if (!*pevlist)
return -1;
- if (evlist__parse_sample(*pevlist, event, &sample)) {
+ perf_sample__init(&sample, /*all=*/false);
+ ret = evlist__parse_sample(*pevlist, event, &sample);
+ perf_sample__exit(&sample);
+ if (ret) {
pr_debug("evlist__parse_sample failed\n");
return -1;
}
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 1c4feec1adff..0958c7c8995f 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -70,6 +70,7 @@ static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest
int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
char sbuf[STRERR_BUFSIZE];
+ perf_sample__init(&sample, /*all=*/false);
if (evlist == NULL) /* Fallback for kernels lacking PERF_COUNT_SW_DUMMY */
evlist = evlist__new_default();
@@ -330,6 +331,7 @@ found_exit:
out_delete_evlist:
evlist__delete(evlist);
out:
+ perf_sample__exit(&sample);
if (err == -EACCES)
return TEST_SKIP;
if (err < 0 || errs != 0)
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
index bbe2ddeb9b74..d3e40fa5482c 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -153,6 +153,7 @@ static int test__perf_time_to_tsc(struct test_suite *test __maybe_unused, int su
while ((event = perf_mmap__read_event(&md->core)) != NULL) {
struct perf_sample sample;
+ perf_sample__init(&sample, /*all=*/false);
if (event->header.type != PERF_RECORD_COMM ||
(pid_t)event->comm.pid != getpid() ||
(pid_t)event->comm.tid != getpid())
@@ -170,6 +171,7 @@ static int test__perf_time_to_tsc(struct test_suite *test __maybe_unused, int su
}
next_event:
perf_mmap__consume(&md->core);
+ perf_sample__exit(&sample);
}
perf_mmap__read_done(&md->core);
}
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 6a681e3fb552..4a9f8e090cf4 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -452,9 +452,9 @@ static int test__name_cmp(struct test_suite *test __maybe_unused, int subtest __
}
/**
- * Test perf_pmu__match() that's used to search for a PMU given a name passed
+ * Test perf_pmu__wildcard_match() that's used to search for a PMU given a name passed
* on the command line. The name that's passed may also be a filename type glob
- * match. If the name does not match, perf_pmu__match() attempts to match the
+ * match. If the name does not match, perf_pmu__wildcard_match() attempts to match the
* alias of the PMU, if provided.
*/
static int test__pmu_match(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
@@ -463,41 +463,44 @@ static int test__pmu_match(struct test_suite *test __maybe_unused, int subtest _
.name = "pmuname",
};
- TEST_ASSERT_EQUAL("Exact match", perf_pmu__match(&test_pmu, "pmuname"), true);
- TEST_ASSERT_EQUAL("Longer token", perf_pmu__match(&test_pmu, "longertoken"), false);
- TEST_ASSERT_EQUAL("Shorter token", perf_pmu__match(&test_pmu, "pmu"), false);
+#define TEST_PMU_MATCH(msg, to_match, expect) \
+ TEST_ASSERT_EQUAL(msg, perf_pmu__wildcard_match(&test_pmu, to_match), expect)
+
+ TEST_PMU_MATCH("Exact match", "pmuname", true);
+ TEST_PMU_MATCH("Longer token", "longertoken", false);
+ TEST_PMU_MATCH("Shorter token", "pmu", false);
test_pmu.name = "pmuname_10";
- TEST_ASSERT_EQUAL("Diff suffix_", perf_pmu__match(&test_pmu, "pmuname_2"), false);
- TEST_ASSERT_EQUAL("Sub suffix_", perf_pmu__match(&test_pmu, "pmuname_1"), true);
- TEST_ASSERT_EQUAL("Same suffix_", perf_pmu__match(&test_pmu, "pmuname_10"), true);
- TEST_ASSERT_EQUAL("No suffix_", perf_pmu__match(&test_pmu, "pmuname"), true);
- TEST_ASSERT_EQUAL("Underscore_", perf_pmu__match(&test_pmu, "pmuname_"), true);
- TEST_ASSERT_EQUAL("Substring_", perf_pmu__match(&test_pmu, "pmuna"), false);
+ TEST_PMU_MATCH("Diff suffix_", "pmuname_2", false);
+ TEST_PMU_MATCH("Sub suffix_", "pmuname_1", true);
+ TEST_PMU_MATCH("Same suffix_", "pmuname_10", true);
+ TEST_PMU_MATCH("No suffix_", "pmuname", true);
+ TEST_PMU_MATCH("Underscore_", "pmuname_", true);
+ TEST_PMU_MATCH("Substring_", "pmuna", false);
test_pmu.name = "pmuname_ab23";
- TEST_ASSERT_EQUAL("Diff suffix hex_", perf_pmu__match(&test_pmu, "pmuname_2"), false);
- TEST_ASSERT_EQUAL("Sub suffix hex_", perf_pmu__match(&test_pmu, "pmuname_ab"), true);
- TEST_ASSERT_EQUAL("Same suffix hex_", perf_pmu__match(&test_pmu, "pmuname_ab23"), true);
- TEST_ASSERT_EQUAL("No suffix hex_", perf_pmu__match(&test_pmu, "pmuname"), true);
- TEST_ASSERT_EQUAL("Underscore hex_", perf_pmu__match(&test_pmu, "pmuname_"), true);
- TEST_ASSERT_EQUAL("Substring hex_", perf_pmu__match(&test_pmu, "pmuna"), false);
+ TEST_PMU_MATCH("Diff suffix hex_", "pmuname_2", false);
+ TEST_PMU_MATCH("Sub suffix hex_", "pmuname_ab", true);
+ TEST_PMU_MATCH("Same suffix hex_", "pmuname_ab23", true);
+ TEST_PMU_MATCH("No suffix hex_", "pmuname", true);
+ TEST_PMU_MATCH("Underscore hex_", "pmuname_", true);
+ TEST_PMU_MATCH("Substring hex_", "pmuna", false);
test_pmu.name = "pmuname10";
- TEST_ASSERT_EQUAL("Diff suffix", perf_pmu__match(&test_pmu, "pmuname2"), false);
- TEST_ASSERT_EQUAL("Sub suffix", perf_pmu__match(&test_pmu, "pmuname1"), true);
- TEST_ASSERT_EQUAL("Same suffix", perf_pmu__match(&test_pmu, "pmuname10"), true);
- TEST_ASSERT_EQUAL("No suffix", perf_pmu__match(&test_pmu, "pmuname"), true);
- TEST_ASSERT_EQUAL("Underscore", perf_pmu__match(&test_pmu, "pmuname_"), false);
- TEST_ASSERT_EQUAL("Substring", perf_pmu__match(&test_pmu, "pmuna"), false);
+ TEST_PMU_MATCH("Diff suffix", "pmuname2", false);
+ TEST_PMU_MATCH("Sub suffix", "pmuname1", true);
+ TEST_PMU_MATCH("Same suffix", "pmuname10", true);
+ TEST_PMU_MATCH("No suffix", "pmuname", true);
+ TEST_PMU_MATCH("Underscore", "pmuname_", false);
+ TEST_PMU_MATCH("Substring", "pmuna", false);
test_pmu.name = "pmunameab23";
- TEST_ASSERT_EQUAL("Diff suffix hex", perf_pmu__match(&test_pmu, "pmuname2"), false);
- TEST_ASSERT_EQUAL("Sub suffix hex", perf_pmu__match(&test_pmu, "pmunameab"), true);
- TEST_ASSERT_EQUAL("Same suffix hex", perf_pmu__match(&test_pmu, "pmunameab23"), true);
- TEST_ASSERT_EQUAL("No suffix hex", perf_pmu__match(&test_pmu, "pmuname"), true);
- TEST_ASSERT_EQUAL("Underscore hex", perf_pmu__match(&test_pmu, "pmuname_"), false);
- TEST_ASSERT_EQUAL("Substring hex", perf_pmu__match(&test_pmu, "pmuna"), false);
+ TEST_PMU_MATCH("Diff suffix hex", "pmuname2", false);
+ TEST_PMU_MATCH("Sub suffix hex", "pmunameab", true);
+ TEST_PMU_MATCH("Same suffix hex", "pmunameab23", true);
+ TEST_PMU_MATCH("No suffix hex", "pmuname", true);
+ TEST_PMU_MATCH("Underscore hex", "pmuname_", false);
+ TEST_PMU_MATCH("Substring hex", "pmuna", false);
/*
* 2 hex chars or less are not considered suffixes so it shouldn't be
@@ -505,7 +508,7 @@ static int test__pmu_match(struct test_suite *test __maybe_unused, int subtest _
* false results here than above.
*/
test_pmu.name = "pmuname_a3";
- TEST_ASSERT_EQUAL("Diff suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname_2"), false);
+ TEST_PMU_MATCH("Diff suffix 2 hex_", "pmuname_2", false);
/*
* This one should be false, but because pmuname_a3 ends in 3 which is
* decimal, it's not possible to determine if it's a short hex suffix or
@@ -513,19 +516,19 @@ static int test__pmu_match(struct test_suite *test __maybe_unused, int subtest _
* length of decimal suffix. Run the test anyway and expect the wrong
* result. And slightly fuzzy matching shouldn't do too much harm.
*/
- TEST_ASSERT_EQUAL("Sub suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname_a"), true);
- TEST_ASSERT_EQUAL("Same suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname_a3"), true);
- TEST_ASSERT_EQUAL("No suffix 2 hex_", perf_pmu__match(&test_pmu, "pmuname"), false);
- TEST_ASSERT_EQUAL("Underscore 2 hex_", perf_pmu__match(&test_pmu, "pmuname_"), false);
- TEST_ASSERT_EQUAL("Substring 2 hex_", perf_pmu__match(&test_pmu, "pmuna"), false);
+ TEST_PMU_MATCH("Sub suffix 2 hex_", "pmuname_a", true);
+ TEST_PMU_MATCH("Same suffix 2 hex_", "pmuname_a3", true);
+ TEST_PMU_MATCH("No suffix 2 hex_", "pmuname", false);
+ TEST_PMU_MATCH("Underscore 2 hex_", "pmuname_", false);
+ TEST_PMU_MATCH("Substring 2 hex_", "pmuna", false);
test_pmu.name = "pmuname_5";
- TEST_ASSERT_EQUAL("Glob 1", perf_pmu__match(&test_pmu, "pmu*"), true);
- TEST_ASSERT_EQUAL("Glob 2", perf_pmu__match(&test_pmu, "nomatch*"), false);
- TEST_ASSERT_EQUAL("Seq 1", perf_pmu__match(&test_pmu, "pmuname_[12345]"), true);
- TEST_ASSERT_EQUAL("Seq 2", perf_pmu__match(&test_pmu, "pmuname_[67890]"), false);
- TEST_ASSERT_EQUAL("? 1", perf_pmu__match(&test_pmu, "pmuname_?"), true);
- TEST_ASSERT_EQUAL("? 2", perf_pmu__match(&test_pmu, "pmuname_1?"), false);
+ TEST_PMU_MATCH("Glob 1", "pmu*", true);
+ TEST_PMU_MATCH("Glob 2", "nomatch*", false);
+ TEST_PMU_MATCH("Seq 1", "pmuname_[12345]", true);
+ TEST_PMU_MATCH("Seq 2", "pmuname_[67890]", false);
+ TEST_PMU_MATCH("? 1", "pmuname_?", true);
+ TEST_PMU_MATCH("? 2", "pmuname_1?", false);
return TEST_OK;
}
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 25a3f6cece50..72411580f869 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -40,8 +40,8 @@
#define BS_EXPECTED_LE 0x1aa00000000
#define FLAG(s) s->branch_stack->entries[i].flags
-static bool samples_same(const struct perf_sample *s1,
- const struct perf_sample *s2,
+static bool samples_same(struct perf_sample *s1,
+ struct perf_sample *s2,
u64 type, u64 read_format, bool needs_swap)
{
size_t i;
@@ -126,13 +126,15 @@ static bool samples_same(const struct perf_sample *s1,
}
if (type & PERF_SAMPLE_REGS_USER) {
- size_t sz = hweight_long(s1->user_regs.mask) * sizeof(u64);
-
- COMP(user_regs.mask);
- COMP(user_regs.abi);
- if (s1->user_regs.abi &&
- (!s1->user_regs.regs || !s2->user_regs.regs ||
- memcmp(s1->user_regs.regs, s2->user_regs.regs, sz))) {
+ struct regs_dump *s1_regs = perf_sample__user_regs(s1);
+ struct regs_dump *s2_regs = perf_sample__user_regs(s2);
+ size_t sz = hweight_long(s1_regs->mask) * sizeof(u64);
+
+ COMP(user_regs->mask);
+ COMP(user_regs->abi);
+ if (s1_regs->abi &&
+ (!s1_regs->regs || !s2_regs->regs ||
+ memcmp(s1_regs->regs, s2_regs->regs, sz))) {
pr_debug("Samples differ at 'user_regs'\n");
return false;
}
@@ -157,13 +159,15 @@ static bool samples_same(const struct perf_sample *s1,
COMP(transaction);
if (type & PERF_SAMPLE_REGS_INTR) {
- size_t sz = hweight_long(s1->intr_regs.mask) * sizeof(u64);
-
- COMP(intr_regs.mask);
- COMP(intr_regs.abi);
- if (s1->intr_regs.abi &&
- (!s1->intr_regs.regs || !s2->intr_regs.regs ||
- memcmp(s1->intr_regs.regs, s2->intr_regs.regs, sz))) {
+ struct regs_dump *s1_regs = perf_sample__intr_regs(s1);
+ struct regs_dump *s2_regs = perf_sample__intr_regs(s2);
+ size_t sz = hweight_long(s1_regs->mask) * sizeof(u64);
+
+ COMP(intr_regs->mask);
+ COMP(intr_regs->abi);
+ if (s1_regs->abi &&
+ (!s1_regs->regs || !s2_regs->regs ||
+ memcmp(s1_regs->regs, s2_regs->regs, sz))) {
pr_debug("Samples differ at 'intr_regs'\n");
return false;
}
@@ -223,6 +227,16 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
const u32 raw_data[] = {0x12345678, 0x0a0b0c0d, 0x11020304, 0x05060708, 0 };
const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL};
const u64 aux_data[] = {0xa55a, 0, 0xeeddee, 0x0282028202820282};
+ struct regs_dump user_regs = {
+ .abi = PERF_SAMPLE_REGS_ABI_64,
+ .mask = sample_regs,
+ .regs = regs,
+ };
+ struct regs_dump intr_regs = {
+ .abi = PERF_SAMPLE_REGS_ABI_64,
+ .mask = sample_regs,
+ .regs = regs,
+ };
struct perf_sample sample = {
.ip = 101,
.pid = 102,
@@ -241,11 +255,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
.callchain = &callchain.callchain,
.no_hw_idx = false,
.branch_stack = &branch_stack.branch_stack,
- .user_regs = {
- .abi = PERF_SAMPLE_REGS_ABI_64,
- .mask = sample_regs,
- .regs = regs,
- },
+ .user_regs = &user_regs,
.user_stack = {
.size = sizeof(data),
.data = (void *)data,
@@ -254,11 +264,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
.time_enabled = 0x030a59d664fca7deULL,
.time_running = 0x011b6ae553eb98edULL,
},
- .intr_regs = {
- .abi = PERF_SAMPLE_REGS_ABI_64,
- .mask = sample_regs,
- .regs = regs,
- },
+ .intr_regs = &intr_regs,
.phys_addr = 113,
.cgroup = 114,
.data_page_size = 115,
@@ -273,6 +279,8 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
size_t i, sz, bufsz;
int err, ret = -1;
+ perf_sample__init(&sample_out, /*all=*/false);
+ perf_sample__init(&sample_out_endian, /*all=*/false);
if (sample_type & PERF_SAMPLE_REGS_USER)
evsel.core.attr.sample_regs_user = sample_regs;
@@ -361,6 +369,8 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
ret = 0;
out_free:
free(event);
+ perf_sample__exit(&sample_out_endian);
+ perf_sample__exit(&sample_out);
if (ret && read_format)
pr_debug("read_format %#"PRIx64"\n", read_format);
return ret;
diff --git a/tools/perf/tests/shell/annotate.sh b/tools/perf/tests/shell/annotate.sh
index 1590a37363de..16a1ccd06089 100755
--- a/tools/perf/tests/shell/annotate.sh
+++ b/tools/perf/tests/shell/annotate.sh
@@ -35,54 +35,78 @@ trap_cleanup() {
trap trap_cleanup EXIT TERM INT
test_basic() {
- echo "Basic perf annotate test"
- if ! perf record -o "${perfdata}" ${testprog} 2> /dev/null
+ mode=$1
+ echo "${mode} perf annotate test"
+ if [ "x${mode}" == "xBasic" ]
then
- echo "Basic annotate [Failed: perf record]"
+ perf record -o "${perfdata}" ${testprog} 2> /dev/null
+ else
+ perf record -o - ${testprog} 2> /dev/null > "${perfdata}"
+ fi
+ if [ "x$?" != "x0" ]
+ then
+ echo "${mode} annotate [Failed: perf record]"
err=1
return
fi
# Generate the annotated output file
- perf annotate --no-demangle -i "${perfdata}" --stdio 2> /dev/null | head -250 > "${perfout}"
+ if [ "x${mode}" == "xBasic" ]
+ then
+ perf annotate --no-demangle -i "${perfdata}" --stdio 2> /dev/null > "${perfout}"
+ else
+ perf annotate --no-demangle -i - --stdio 2> /dev/null < "${perfdata}" > "${perfout}"
+ fi
# check if it has the target symbol
- if ! grep "${testsym}" "${perfout}"
+ if ! head -250 "${perfout}" | grep -q "${testsym}"
then
- echo "Basic annotate [Failed: missing target symbol]"
+ echo "${mode} annotate [Failed: missing target symbol]"
err=1
return
fi
# check if it has the disassembly lines
- if ! grep "${disasm_regex}" "${perfout}"
+ if ! head -250 "${perfout}" | grep -q "${disasm_regex}"
then
- echo "Basic annotate [Failed: missing disasm output from default disassembler]"
+ echo "${mode} annotate [Failed: missing disasm output from default disassembler]"
err=1
return
fi
# check again with a target symbol name
- if ! perf annotate --no-demangle -i "${perfdata}" "${testsym}" 2> /dev/null | \
- head -250 | grep -m 3 "${disasm_regex}"
+ if [ "x${mode}" == "xBasic" ]
then
- echo "Basic annotate [Failed: missing disasm output when specifying the target symbol]"
+ perf annotate --no-demangle -i "${perfdata}" "${testsym}" 2> /dev/null > "${perfout}"
+ else
+ perf annotate --no-demangle -i - "${testsym}" 2> /dev/null < "${perfdata}" > "${perfout}"
+ fi
+
+ if ! head -250 "${perfout}"| grep -q -m 3 "${disasm_regex}"
+ then
+ echo "${mode} annotate [Failed: missing disasm output when specifying the target symbol]"
err=1
return
fi
# check one more with external objdump tool (forced by --objdump option)
- if ! perf annotate --no-demangle -i "${perfdata}" --objdump=objdump 2> /dev/null | \
- head -250 | grep -m 3 "${disasm_regex}"
+ if [ "x${mode}" == "xBasic" ]
+ then
+ perf annotate --no-demangle -i "${perfdata}" --objdump=objdump 2> /dev/null > "${perfout}"
+ else
+ perf annotate --no-demangle -i - "${testsym}" 2> /dev/null < "${perfdata}" > "${perfout}"
+ fi
+ if ! head -250 "${perfout}" | grep -q -m 3 "${disasm_regex}"
then
- echo "Basic annotate [Failed: missing disasm output from non default disassembler (using --objdump)]"
+ echo "${mode} annotate [Failed: missing disasm output from non default disassembler (using --objdump)]"
err=1
return
fi
- echo "Basic annotate test [Success]"
+ echo "${mode} annotate test [Success]"
}
-test_basic
+test_basic Basic
+test_basic Pipe
cleanup
exit $err
diff --git a/tools/perf/tests/shell/base_report/setup.sh b/tools/perf/tests/shell/base_report/setup.sh
index b03501b2e8fc..8634e7e0dda6 100755
--- a/tools/perf/tests/shell/base_report/setup.sh
+++ b/tools/perf/tests/shell/base_report/setup.sh
@@ -15,6 +15,8 @@
# include working environment
. ../common/init.sh
+TEST_RESULT=0
+
test -d "$HEADER_TAR_DIR" || mkdir -p "$HEADER_TAR_DIR"
SW_EVENT="cpu-clock"
@@ -26,7 +28,21 @@ PERF_EXIT_CODE=$?
CHECK_EXIT_CODE=$?
print_results $PERF_EXIT_CODE $CHECK_EXIT_CODE "prepare the perf.data file"
-TEST_RESULT=$?
+(( TEST_RESULT += $? ))
+
+# Some minimal parallel workload.
+$CMD_PERF record --latency -o $CURRENT_TEST_DIR/perf.data.1 bash -c "for i in {1..100} ; do cat /proc/cpuinfo 1> /dev/null & done; sleep 1" 2> $LOGS_DIR/setup-latency.log
+PERF_EXIT_CODE=$?
+
+echo ==================
+cat $LOGS_DIR/setup-latency.log
+echo ==================
+
+../common/check_all_patterns_found.pl "$RE_LINE_RECORD1" "$RE_LINE_RECORD2" < $LOGS_DIR/setup-latency.log
+CHECK_EXIT_CODE=$?
+
+print_results $PERF_EXIT_CODE $CHECK_EXIT_CODE "prepare the perf.data.1 file"
+(( TEST_RESULT += $? ))
print_overall_results $TEST_RESULT
exit $?
diff --git a/tools/perf/tests/shell/base_report/test_basic.sh b/tools/perf/tests/shell/base_report/test_basic.sh
index 2398eba4d3fd..adfd8713b8f8 100755
--- a/tools/perf/tests/shell/base_report/test_basic.sh
+++ b/tools/perf/tests/shell/base_report/test_basic.sh
@@ -183,6 +183,58 @@ print_results $PERF_EXIT_CODE $CHECK_EXIT_CODE "symbol filter"
(( TEST_RESULT += $? ))
+### latency and parallelism
+
+# Record with --latency should record with context switches.
+$CMD_PERF report -i $CURRENT_TEST_DIR/perf.data.1 --stdio --header-only > $LOGS_DIR/latency_header.log
+PERF_EXIT_CODE=$?
+
+../common/check_all_patterns_found.pl ", context_switch = 1, " < $LOGS_DIR/latency_header.log
+CHECK_EXIT_CODE=$?
+
+print_results $PERF_EXIT_CODE $CHECK_EXIT_CODE "latency header"
+(( TEST_RESULT += $? ))
+
+
+# The default report for latency profile should show Overhead and Latency fields (in that order).
+$CMD_PERF report --stdio -i $CURRENT_TEST_DIR/perf.data.1 > $LOGS_DIR/latency_default.log 2> $LOGS_DIR/latency_default.err
+PERF_EXIT_CODE=$?
+
+../common/check_all_patterns_found.pl "# Overhead Latency Command" < $LOGS_DIR/latency_default.log
+CHECK_EXIT_CODE=$?
+../common/check_errors_whitelisted.pl "stderr-whitelist.txt" < $LOGS_DIR/latency_default.err
+(( CHECK_EXIT_CODE += $? ))
+
+print_results $PERF_EXIT_CODE $CHECK_EXIT_CODE "default report for latency profile"
+(( TEST_RESULT += $? ))
+
+
+# The latency report for latency profile should show Latency and Overhead fields (in that order).
+$CMD_PERF report --latency --stdio -i $CURRENT_TEST_DIR/perf.data.1 > $LOGS_DIR/latency_latency.log 2> $LOGS_DIR/latency_latency.err
+PERF_EXIT_CODE=$?
+
+../common/check_all_patterns_found.pl "# Latency Overhead Command" < $LOGS_DIR/latency_latency.log
+CHECK_EXIT_CODE=$?
+../common/check_errors_whitelisted.pl "stderr-whitelist.txt" < $LOGS_DIR/latency_latency.err
+(( CHECK_EXIT_CODE += $? ))
+
+print_results $PERF_EXIT_CODE $CHECK_EXIT_CODE "latency report for latency profile"
+(( TEST_RESULT += $? ))
+
+
+# Ensure parallelism histogram with parallelism filter does not fail/crash.
+$CMD_PERF report --hierarchy --sort latency,parallelism,comm,symbol --parallelism=1,2 --stdio -i $CURRENT_TEST_DIR/perf.data.1 > $LOGS_DIR/parallelism_hierarchy.log 2> $LOGS_DIR/parallelism_hierarchy.err
+PERF_EXIT_CODE=$?
+
+../common/check_all_patterns_found.pl "# Latency Parallelism / Command / Symbol" < $LOGS_DIR/parallelism_hierarchy.log
+CHECK_EXIT_CODE=$?
+../common/check_errors_whitelisted.pl "stderr-whitelist.txt" < $LOGS_DIR/parallelism_hierarchy.err
+(( CHECK_EXIT_CODE += $? ))
+
+print_results $PERF_EXIT_CODE $CHECK_EXIT_CODE "parallelism histogram"
+(( TEST_RESULT += $? ))
+
+
# TODO: $CMD_PERF report -n --showcpuutilization -TUxDg 2> 01.log
# print overall results
diff --git a/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S b/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S
index 75cf084a927d..577760046772 100644
--- a/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S
+++ b/tools/perf/tests/shell/coresight/asm_pure_loop/asm_pure_loop.S
@@ -26,3 +26,5 @@ skip:
mov x0, #0
mov x8, #93 // __NR_exit syscall
svc #0
+
+.section .note.GNU-stack, "", @progbits
diff --git a/tools/perf/tests/shell/diff.sh b/tools/perf/tests/shell/diff.sh
index 14b87af88703..e05a5dc49479 100755
--- a/tools/perf/tests/shell/diff.sh
+++ b/tools/perf/tests/shell/diff.sh
@@ -39,13 +39,13 @@ make_data() {
file="$1"
if ! perf record -o "${file}" ${testprog} 2> /dev/null
then
- echo "Workload record [Failed record]"
+ echo "Workload record [Failed record]" >&2
echo 1
return
fi
if ! perf report -i "${file}" -q | grep -q "${testsym}"
then
- echo "Workload record [Failed missing output]"
+ echo "Workload record [Failed missing output]" >&2
echo 1
return
fi
@@ -55,12 +55,12 @@ make_data() {
test_two_files() {
echo "Basic two file diff test"
err=$(make_data "${perfdata1}")
- if [ $err != 0 ]
+ if [ "$err" != 0 ]
then
return
fi
err=$(make_data "${perfdata2}")
- if [ $err != 0 ]
+ if [ "$err" != 0 ]
then
return
fi
@@ -77,12 +77,12 @@ test_two_files() {
test_three_files() {
echo "Basic three file diff test"
err=$(make_data "${perfdata1}")
- if [ $err != 0 ]
+ if [ "$err" != 0 ]
then
return
fi
err=$(make_data "${perfdata2}")
- if [ $err != 0 ]
+ if [ "$err" != 0 ]
then
return
fi
diff --git a/tools/perf/tests/shell/lib/attr.py b/tools/perf/tests/shell/lib/attr.py
index 3db9a7d78715..bfccc727d9b2 100644
--- a/tools/perf/tests/shell/lib/attr.py
+++ b/tools/perf/tests/shell/lib/attr.py
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-from __future__ import print_function
-
+import configparser
import os
import sys
import glob
@@ -13,11 +12,6 @@ import re
import shutil
import subprocess
-try:
- import configparser
-except ImportError:
- import ConfigParser as configparser
-
def data_equal(a, b):
# Allow multiple values in assignment separated by '|'
a_list = a.split('|')
diff --git a/tools/perf/tests/shell/lib/perf_json_output_lint.py b/tools/perf/tests/shell/lib/perf_json_output_lint.py
index b066d721f897..9e772a89ce38 100644
--- a/tools/perf/tests/shell/lib/perf_json_output_lint.py
+++ b/tools/perf/tests/shell/lib/perf_json_output_lint.py
@@ -19,6 +19,7 @@ ap.add_argument('--per-cluster', action='store_true')
ap.add_argument('--per-die', action='store_true')
ap.add_argument('--per-node', action='store_true')
ap.add_argument('--per-socket', action='store_true')
+ap.add_argument('--metric-only', action='store_true')
ap.add_argument('--file', type=argparse.FileType('r'), default=sys.stdin)
args = ap.parse_args()
@@ -64,6 +65,8 @@ def check_json_output(expected_items):
'socket': lambda x: True,
'thread': lambda x: True,
'unit': lambda x: True,
+ 'insn per cycle': lambda x: isfloat(x),
+ 'GHz': lambda x: True, # FIXME: it seems unintended for --metric-only
}
input = '[\n' + ','.join(Lines) + '\n]'
for item in json.loads(input):
@@ -78,6 +81,8 @@ def check_json_output(expected_items):
pass
elif count - 1 in expected_items and 'metric-threshold' in item:
pass
+ elif count in expected_items and 'insn per cycle' in item:
+ pass
elif count not in expected_items:
raise RuntimeError(f'wrong number of fields. counted {count} expected {expected_items}'
f' in \'{item}\'')
@@ -95,6 +100,8 @@ try:
expected_items = [6, 8]
elif args.per_core or args.per_socket or args.per_node or args.per_die or args.per_cluster or args.per_cache:
expected_items = [7, 9]
+ elif args.metric_only:
+ expected_items = [1, 2]
else:
# If no option is specified, don't check the number of items.
expected_items = -1
diff --git a/tools/perf/tests/shell/lib/stat_output.sh b/tools/perf/tests/shell/lib/stat_output.sh
index 9a176ceae4a3..4d4aac547f01 100644
--- a/tools/perf/tests/shell/lib/stat_output.sh
+++ b/tools/perf/tests/shell/lib/stat_output.sh
@@ -148,6 +148,14 @@ check_per_socket()
echo "[Success]"
}
+check_metric_only()
+{
+ echo -n "Checking $1 output: metric only "
+ perf stat --metric-only $2 -e instructions,cycles true
+ commachecker --metric-only
+ echo "[Success]"
+}
+
# The perf stat options for per-socket, per-core, per-die
# and -A ( no_aggr mode ) uses the info fetched from this
# directory: "/sys/devices/system/cpu/cpu*/topology". For
diff --git a/tools/perf/tests/shell/perftool-testsuite_probe.sh b/tools/perf/tests/shell/perftool-testsuite_probe.sh
index 7b1bfd0f888f..3863df16c19b 100755
--- a/tools/perf/tests/shell/perftool-testsuite_probe.sh
+++ b/tools/perf/tests/shell/perftool-testsuite_probe.sh
@@ -2,6 +2,7 @@
# perftool-testsuite_probe (exclusive)
# SPDX-License-Identifier: GPL-2.0
+[ "$(id -u)" = 0 ] || exit 2
test -d "$(dirname "$0")/base_probe" || exit 2
cd "$(dirname "$0")/base_probe" || exit 2
status=0
diff --git a/tools/perf/tests/shell/probe_vfs_getname.sh b/tools/perf/tests/shell/probe_vfs_getname.sh
index 0c5aacc446b3..c51a32931af6 100755
--- a/tools/perf/tests/shell/probe_vfs_getname.sh
+++ b/tools/perf/tests/shell/probe_vfs_getname.sh
@@ -8,6 +8,7 @@
. "$(dirname $0)"/lib/probe.sh
skip_if_no_perf_probe || exit 2
+[ "$(id -u)" = 0 ] || exit 2
# shellcheck source=lib/probe_vfs_getname.sh
. "$(dirname $0)"/lib/probe_vfs_getname.sh
diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index d5e5193cceb6..c4bab5b5cc59 100755
--- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -105,6 +105,7 @@ delete_libc_inet_pton_event() {
# Check for IPv6 interface existence
ip a sh lo | grep -F -q inet6 || exit 2
+[ "$(id -u)" = 0 ] || exit 2
skip_if_no_perf_probe && \
add_libc_inet_pton_event && \
diff --git a/tools/perf/tests/shell/record+script_probe_vfs_getname.sh b/tools/perf/tests/shell/record+script_probe_vfs_getname.sh
index 5940fdc1df37..fd5b10d46915 100755
--- a/tools/perf/tests/shell/record+script_probe_vfs_getname.sh
+++ b/tools/perf/tests/shell/record+script_probe_vfs_getname.sh
@@ -13,6 +13,7 @@
. "$(dirname "$0")/lib/probe.sh"
skip_if_no_perf_probe || exit 2
+[ "$(id -u)" = 0 ] || exit 2
# shellcheck source=lib/probe_vfs_getname.sh
. "$(dirname "$0")/lib/probe_vfs_getname.sh"
diff --git a/tools/perf/tests/shell/record.sh b/tools/perf/tests/shell/record.sh
index 0fc7a909ae9b..ba8d873d3ca7 100755
--- a/tools/perf/tests/shell/record.sh
+++ b/tools/perf/tests/shell/record.sh
@@ -231,7 +231,7 @@ test_cgroup() {
test_leader_sampling() {
echo "Basic leader sampling test"
- if ! perf record -o "${perfdata}" -e "{instructions,instructions}:Su" -- \
+ if ! perf record -o "${perfdata}" -e "{cycles,cycles}:Su" -- \
perf test -w brstack 2> /dev/null
then
echo "Leader sampling [Failed record]"
@@ -243,15 +243,15 @@ test_leader_sampling() {
while IFS= read -r line
do
# Check if the two instruction counts are equal in each record
- instructions=$(echo $line | awk '{for(i=1;i<=NF;i++) if($i=="instructions:") print $(i-1)}')
- if [ $(($index%2)) -ne 0 ] && [ ${instructions}x != ${prev_instructions}x ]
+ cycles=$(echo $line | awk '{for(i=1;i<=NF;i++) if($i=="cycles:") print $(i-1)}')
+ if [ $(($index%2)) -ne 0 ] && [ ${cycles}x != ${prev_cycles}x ]
then
- echo "Leader sampling [Failed inconsistent instructions count]"
+ echo "Leader sampling [Failed inconsistent cycles count]"
err=1
return
fi
index=$(($index+1))
- prev_instructions=$instructions
+ prev_cycles=$cycles
done < $script_output
echo "Basic leader sampling test [Success]"
}
@@ -273,27 +273,42 @@ test_topdown_leader_sampling() {
}
test_precise_max() {
+ local -i skipped=0
+
echo "precise_max attribute test"
- if ! perf stat -e "cycles,instructions" true 2> /dev/null
+ # Just to make sure event cycles is supported for sampling
+ if perf record -o "${perfdata}" -e "cycles" true 2> /dev/null
then
- echo "precise_max attribute [Skipped no hardware events]"
- return
+ if ! perf record -o "${perfdata}" -e "cycles:P" true 2> /dev/null
+ then
+ echo "precise_max attribute [Failed cycles:P event]"
+ err=1
+ return
+ fi
+ else
+ echo "precise_max attribute [Skipped no cycles:P event]"
+ ((skipped+=1))
fi
- # Just to make sure it doesn't fail
- if ! perf record -o "${perfdata}" -e "cycles:P" true 2> /dev/null
+ # On s390 event instructions is not supported for perf record
+ if perf record -o "${perfdata}" -e "instructions" true 2> /dev/null
then
- echo "precise_max attribute [Failed cycles:P event]"
- err=1
- return
+ # On AMD, cycles and instructions events are treated differently
+ if ! perf record -o "${perfdata}" -e "instructions:P" true 2> /dev/null
+ then
+ echo "precise_max attribute [Failed instructions:P event]"
+ err=1
+ return
+ fi
+ else
+ echo "precise_max attribute [Skipped no instructions:P event]"
+ ((skipped+=1))
fi
- # On AMD, cycles and instructions events are treated differently
- if ! perf record -o "${perfdata}" -e "instructions:P" true 2> /dev/null
+ if [ $skipped -eq 2 ]
then
- echo "precise_max attribute [Failed instructions:P event]"
- err=1
- return
+ echo "precise_max attribute [Skipped no hardware events]"
+ else
+ echo "precise_max attribute test [Success]"
fi
- echo "precise_max attribute test [Success]"
}
# raise the limit of file descriptors to minimum
diff --git a/tools/perf/tests/shell/record_bpf_filter.sh b/tools/perf/tests/shell/record_bpf_filter.sh
index 1b58ccc1fd88..4d6c3c1b7fb9 100755
--- a/tools/perf/tests/shell/record_bpf_filter.sh
+++ b/tools/perf/tests/shell/record_bpf_filter.sh
@@ -89,7 +89,7 @@ test_bpf_filter_fail() {
test_bpf_filter_group() {
echo "Group bpf-filter test"
- if ! perf record -e task-clock --filter 'period > 1000 || ip > 0' \
+ if ! perf record -e task-clock --filter 'period > 1000, ip > 0' \
-o /dev/null true 2>/dev/null
then
echo "Group bpf-filter test [Failed should succeed]"
@@ -97,7 +97,7 @@ test_bpf_filter_group() {
return
fi
- if ! perf record -e task-clock --filter 'cpu > 0 || ip > 0' \
+ if ! perf record -e task-clock --filter 'period > 1000 , cpu > 0 || ip > 0' \
-o /dev/null true 2>&1 | grep -q PERF_SAMPLE_CPU
then
echo "Group bpf-filter test [Failed forbidden CPU]"
diff --git a/tools/perf/tests/shell/stat+csv_output.sh b/tools/perf/tests/shell/stat+csv_output.sh
index fc2d8cc6e5e0..7a6f6e177402 100755
--- a/tools/perf/tests/shell/stat+csv_output.sh
+++ b/tools/perf/tests/shell/stat+csv_output.sh
@@ -44,6 +44,7 @@ function commachecker()
;; "--per-die") exp=8
;; "--per-cluster") exp=8
;; "--per-cache") exp=8
+ ;; "--metric-only") exp=2
esac
while read line
@@ -75,6 +76,7 @@ check_interval "CSV" "$perf_cmd"
check_event "CSV" "$perf_cmd"
check_per_thread "CSV" "$perf_cmd"
check_per_node "CSV" "$perf_cmd"
+check_metric_only "CSV" "$perf_cmd"
if [ $skip_test -ne 1 ]
then
check_system_wide_no_aggr "CSV" "$perf_cmd"
diff --git a/tools/perf/tests/shell/stat+json_output.sh b/tools/perf/tests/shell/stat+json_output.sh
index 6b630d33c328..a4f257ea839e 100755
--- a/tools/perf/tests/shell/stat+json_output.sh
+++ b/tools/perf/tests/shell/stat+json_output.sh
@@ -173,6 +173,14 @@ check_per_socket()
echo "[Success]"
}
+check_metric_only()
+{
+ echo -n "Checking json output: metric only "
+ perf stat -j --metric-only -e instructions,cycles -o "${stat_output}" true
+ $PYTHON $pythonchecker --metric-only --file "${stat_output}"
+ echo "[Success]"
+}
+
# The perf stat options for per-socket, per-core, per-die
# and -A ( no_aggr mode ) uses the info fetched from this
# directory: "/sys/devices/system/cpu/cpu*/topology". For
@@ -207,6 +215,7 @@ check_interval
check_event
check_per_thread
check_per_node
+check_metric_only
if [ $skip_test -ne 1 ]
then
check_system_wide_no_aggr
diff --git a/tools/perf/tests/shell/stat+std_output.sh b/tools/perf/tests/shell/stat+std_output.sh
index 0f7967be60af..6fee67693ba7 100755
--- a/tools/perf/tests/shell/stat+std_output.sh
+++ b/tools/perf/tests/shell/stat+std_output.sh
@@ -30,6 +30,7 @@ trap trap_cleanup EXIT TERM INT
function commachecker()
{
local prefix=1
+ local -i metric_only=0
case "$1"
in "--interval") prefix=2
@@ -41,6 +42,7 @@ function commachecker()
;; "--per-die") prefix=3
;; "--per-cache") prefix=3
;; "--per-cluster") prefix=3
+ ;; "--metric-only") metric_only=1
esac
while read line
@@ -60,6 +62,9 @@ function commachecker()
x=${main_body%#*}
[ "$x" = "" ] && continue
+ # Check metric only - if it has a non-empty result
+ [ $metric_only -eq 1 ] && return 0
+
# Skip metrics without event name
y=${main_body#*#}
for i in "${!skip_metric[@]}"; do
@@ -84,6 +89,8 @@ function commachecker()
exit 1;
}
done < "${stat_output}"
+
+ [ $metric_only -eq 1 ] && exit 1
return 0
}
@@ -95,6 +102,7 @@ check_system_wide "STD" "$perf_cmd"
check_interval "STD" "$perf_cmd"
check_per_thread "STD" "$perf_cmd"
check_per_node "STD" "$perf_cmd"
+check_metric_only "STD" "$perf_cmd"
if [ $skip_test -ne 1 ]
then
check_system_wide_no_aggr "STD" "$perf_cmd"
diff --git a/tools/perf/tests/shell/stat.sh b/tools/perf/tests/shell/stat.sh
index 68323d636fb7..8a100a7f2dc1 100755
--- a/tools/perf/tests/shell/stat.sh
+++ b/tools/perf/tests/shell/stat.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
# perf stat tests
# SPDX-License-Identifier: GPL-2.0
@@ -67,43 +67,54 @@ test_topdown_groups() {
echo "Topdown event group test [Skipped event parsing failed]"
return
fi
- if perf stat -e '{slots,topdown-retiring}' true 2>&1 | grep -E -q "<not supported>"
- then
- echo "Topdown event group test [Failed events not supported]"
- err=1
- return
- fi
- if perf stat -e 'instructions,topdown-retiring,slots' true 2>&1 | grep -E -q "<not supported>"
- then
- echo "Topdown event group test [Failed slots not reordered first in no-group case]"
- err=1
- return
- fi
- if perf stat -e '{instructions,topdown-retiring,slots}' true 2>&1 | grep -E -q "<not supported>"
- then
- echo "Topdown event group test [Failed slots not reordered first in single group case]"
- err=1
- return
- fi
- if perf stat -e '{instructions,slots},topdown-retiring' true 2>&1 | grep -E -q "<not supported>"
- then
- echo "Topdown event group test [Failed topdown metrics event not move into slots group]"
- err=1
- return
- fi
- if perf stat -e '{instructions,slots},{topdown-retiring}' true 2>&1 | grep -E -q "<not supported>"
- then
- echo "Topdown event group test [Failed topdown metrics group not merge into slots group]"
- err=1
- return
- fi
- if perf stat -e '{instructions,r400,r8000}' true 2>&1 | grep -E -q "<not supported>"
+ td_err=0
+ do_topdown_group_test() {
+ events=$1
+ failure=$2
+ if perf stat -e "$events" true 2>&1 | grep -E -q "<not supported>"
+ then
+ echo "Topdown event group test [Failed $failure for '$events']"
+ td_err=1
+ return
+ fi
+ }
+ do_topdown_group_test "{slots,topdown-retiring}" "events not supported"
+ do_topdown_group_test "{instructions,r400,r8000}" "raw format slots not reordered first"
+ filler_events=("instructions" "cycles"
+ "context-switches" "faults")
+ for ((i = 0; i < ${#filler_events[@]}; i+=2))
+ do
+ filler1=${filler_events[i]}
+ filler2=${filler_events[i+1]}
+ do_topdown_group_test "$filler1,topdown-retiring,slots" \
+ "slots not reordered first in no-group case"
+ do_topdown_group_test "slots,$filler1,topdown-retiring" \
+ "topdown metrics event not reordered in no-group case"
+ do_topdown_group_test "{$filler1,topdown-retiring,slots}" \
+ "slots not reordered first in single group case"
+ do_topdown_group_test "{$filler1,slots},topdown-retiring" \
+ "topdown metrics event not move into slots group"
+ do_topdown_group_test "topdown-retiring,{$filler1,slots}" \
+ "topdown metrics event not move into slots group last"
+ do_topdown_group_test "{$filler1,slots},{topdown-retiring}" \
+ "topdown metrics group not merge into slots group"
+ do_topdown_group_test "{topdown-retiring},{$filler1,slots}" \
+ "topdown metrics group not merge into slots group last"
+ do_topdown_group_test "{$filler1,slots},$filler2,topdown-retiring" \
+ "non-adjacent topdown metrics group not move into slots group"
+ do_topdown_group_test "$filler2,topdown-retiring,{$filler1,slots}" \
+ "non-adjacent topdown metrics group not move into slots group last"
+ do_topdown_group_test "{$filler1,slots},{$filler2,topdown-retiring}" \
+ "metrics group not merge into slots group"
+ do_topdown_group_test "{$filler1,topdown-retiring},{$filler2,slots}" \
+ "metrics group not merge into slots group last"
+ done
+ if test "$td_err" -eq 0
then
- echo "Topdown event group test [Failed raw format slots not reordered first]"
- err=1
- return
+ echo "Topdown event group test [Success]"
+ else
+ err="$td_err"
fi
- echo "Topdown event group test [Success]"
}
test_topdown_weak_groups() {
diff --git a/tools/perf/tests/shell/stat_all_metrics.sh b/tools/perf/tests/shell/stat_all_metrics.sh
index 73e9347e88a9..ee817c66da06 100755
--- a/tools/perf/tests/shell/stat_all_metrics.sh
+++ b/tools/perf/tests/shell/stat_all_metrics.sh
@@ -20,7 +20,13 @@ for m in $(perf list --raw-dump metrics); do
result_err=$?
if [[ $result_err -gt 0 ]]
then
- if [[ "$result" =~ \
+ if [[ "$result" =~ "Cannot resolve IDs for" ]]
+ then
+ echo "Metric contains missing events"
+ echo $result
+ err=1 # Fail
+ continue
+ elif [[ "$result" =~ \
"Access to performance monitoring and observability operations is limited" ]]
then
echo "Permission failure"
diff --git a/tools/perf/tests/shell/stat_all_pmu.sh b/tools/perf/tests/shell/stat_all_pmu.sh
index 8b148b300be1..9c466c0efa85 100755
--- a/tools/perf/tests/shell/stat_all_pmu.sh
+++ b/tools/perf/tests/shell/stat_all_pmu.sh
@@ -2,7 +2,6 @@
# perf all PMU test (exclusive)
# SPDX-License-Identifier: GPL-2.0
-set -e
err=0
result=""
@@ -16,34 +15,55 @@ trap trap_cleanup EXIT TERM INT
# Test all PMU events; however exclude parameterized ones (name contains '?')
for p in $(perf list --raw-dump pmu | sed 's/[[:graph:]]\+?[[:graph:]]\+[[:space:]]//g')
do
- echo "Testing $p"
- result=$(perf stat -e "$p" true 2>&1)
- if echo "$result" | grep -q "$p"
+ echo -n "Testing $p -- "
+ output=$(perf stat -e "$p" true 2>&1)
+ stat_result=$?
+ if echo "$output" | grep -q "$p"
then
# Event seen in output.
- continue
- fi
- if echo "$result" | grep -q "<not supported>"
- then
- # Event not supported, so ignore.
- continue
+ if [ $stat_result -eq 0 ] && ! echo "$output" | grep -q "<not supported>"
+ then
+ # Event supported.
+ echo "supported"
+ continue
+ elif echo "$output" | grep -q "<not supported>"
+ then
+ # Event not supported, so ignore.
+ echo "not supported"
+ continue
+ elif echo "$output" | grep -q "No permission to enable"
+ then
+ # No permissions, so ignore.
+ echo "no permission to enable"
+ continue
+ elif echo "$output" | grep -q "Bad event name"
+ then
+ # Non-existent event.
+ echo "Error: Bad event name"
+ echo "$output"
+ err=1
+ continue
+ fi
fi
- if echo "$result" | grep -q "Access to performance monitoring and observability operations is limited."
+
+ if echo "$output" | grep -q "Access to performance monitoring and observability operations is limited."
then
# Access is limited, so ignore.
+ echo "access limited"
continue
fi
# We failed to see the event and it is supported. Possibly the workload was
# too small so retry with something longer.
- result=$(perf stat -e "$p" perf bench internals synthesize 2>&1)
- if echo "$result" | grep -q "$p"
+ output=$(perf stat -e "$p" perf bench internals synthesize 2>&1)
+ if echo "$output" | grep -q "$p"
then
# Event seen in output.
+ echo "supported"
continue
fi
echo "Error: event '$p' not printed in:"
- echo "$result"
+ echo "$output"
err=1
done
diff --git a/tools/perf/tests/shell/test_data_symbol.sh b/tools/perf/tests/shell/test_data_symbol.sh
index c86da0235059..bbe8277496ae 100755
--- a/tools/perf/tests/shell/test_data_symbol.sh
+++ b/tools/perf/tests/shell/test_data_symbol.sh
@@ -5,8 +5,6 @@
# Leo Yan <leo.yan@linaro.org>, 2022
shelldir=$(dirname "$0")
-# shellcheck source=lib/waiting.sh
-. "${shelldir}"/lib/waiting.sh
# shellcheck source=lib/perf_has_symbol.sh
. "${shelldir}"/lib/perf_has_symbol.sh
@@ -18,7 +16,7 @@ skip_if_no_mem_event() {
skip_if_no_mem_event || exit 2
-skip_test_missing_symbol buf1
+skip_test_missing_symbol workload_datasym_buf1
TEST_PROGRAM="perf test -w datasym"
PERF_DATA=$(mktemp /tmp/__perf_test.perf.data.XXXXX)
@@ -26,18 +24,19 @@ ERR_FILE=$(mktemp /tmp/__perf_test.stderr.XXXXX)
check_result() {
# The memory report format is as below:
- # 99.92% ... [.] buf1+0x38
+ # 99.92% ... [.] workload_datasym_buf1+0x38
result=$(perf mem report -i ${PERF_DATA} -s symbol_daddr -q 2>&1 |
- awk '/buf1/ { print $4 }')
+ awk '/workload_datasym_buf1/ { print $4 }')
- # Testing is failed if has no any sample for "buf1"
+ # Testing is failed if has no any sample for "workload_datasym_buf1"
[ -z "$result" ] && return 1
while IFS= read -r line; do
- # The "data1" and "data2" fields in structure "buf1" have
- # offset "0x0" and "0x38", returns failure if detect any
- # other offset value.
- if [ "$line" != "buf1+0x0" ] && [ "$line" != "buf1+0x38" ]; then
+ # The "data1" and "data2" fields in structure
+ # "workload_datasym_buf1" have offset "0x0" and "0x38", returns
+ # failure if detect any other offset value.
+ if [ "$line" != "workload_datasym_buf1+0x0" ] && \
+ [ "$line" != "workload_datasym_buf1+0x38" ]; then
return 1
fi
done <<< "$result"
@@ -60,19 +59,10 @@ echo "Recording workload..."
# specific CPU and test in per-CPU mode.
is_amd=$(grep -E -c 'vendor_id.*AuthenticAMD' /proc/cpuinfo)
if (($is_amd >= 1)); then
- perf mem record -vvv -o ${PERF_DATA} -C 0 -- taskset -c 0 $TEST_PROGRAM 2>"${ERR_FILE}" &
+ perf mem record -vvv -o ${PERF_DATA} -C 0 -- taskset -c 0 $TEST_PROGRAM 2>"${ERR_FILE}"
else
- perf mem record -vvv --all-user -o ${PERF_DATA} -- $TEST_PROGRAM 2>"${ERR_FILE}" &
+ perf mem record -vvv --all-user -o ${PERF_DATA} -- $TEST_PROGRAM 2>"${ERR_FILE}"
fi
-PERFPID=$!
-
-wait_for_perf_to_start ${PERFPID} "${ERR_FILE}"
-
-sleep 1
-
-kill $PERFPID
-wait $PERFPID
-
check_result
exit $?
diff --git a/tools/perf/tests/shell/test_stat_intel_tpebs.sh b/tools/perf/tests/shell/test_stat_intel_tpebs.sh
index f95fc64bf0a7..a330ecdb7ba5 100755
--- a/tools/perf/tests/shell/test_stat_intel_tpebs.sh
+++ b/tools/perf/tests/shell/test_stat_intel_tpebs.sh
@@ -3,20 +3,83 @@
# SPDX-License-Identifier: GPL-2.0
set -e
-grep -q GenuineIntel /proc/cpuinfo || { echo Skipping non-Intel; exit 2; }
-# Use this event for testing because it should exist in all platforms
-event=cache-misses:R
+ParanoidAndNotRoot() {
+ [ "$(id -u)" != 0 ] && [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt $1 ]
+}
-# Hybrid platforms output like "cpu_atom/cache-misses/R", rather than as above
-alt_name=/cache-misses/R
+if ! grep -q GenuineIntel /proc/cpuinfo
+then
+ echo "Skipping non-Intel"
+ exit 2
+fi
-# Without this cmd option, default value or zero is returned
-#echo "Testing without --record-tpebs"
-#result=$(perf stat -e "$event" true 2>&1)
-#[[ "$result" =~ $event || "$result" =~ $alt_name ]] || exit 1
+if ParanoidAndNotRoot 0
+then
+ echo "Skipping paranoid >0 and not root"
+ exit 2
+fi
-# In platforms that do not support TPEBS, it should execute without error.
-echo "Testing with --record-tpebs"
-result=$(perf stat -e "$event" --record-tpebs -a sleep 0.01 2>&1)
-[[ "$result" =~ "perf record" && "$result" =~ $event || "$result" =~ $alt_name ]] || exit 1
+stat_output=$(mktemp /tmp/__perf_stat_tpebs_output.XXXXX)
+
+cleanup() {
+ rm -rf "${stat_output}"
+ trap - EXIT TERM INT
+}
+
+trap_cleanup() {
+ echo "Unexpected signal in ${FUNCNAME[1]}"
+ cat "${stat_output}"
+ cleanup
+ exit 1
+}
+trap trap_cleanup EXIT TERM INT
+
+# Event to be used in tests
+event=cache-misses
+
+if ! perf record -e "${event}:p" -a -o /dev/null sleep 0.01 > "${stat_output}" 2>&1
+then
+ echo "Missing ${event} support"
+ cleanup
+ exit 2
+fi
+
+test_with_record_tpebs() {
+ echo "Testing with --record-tpebs"
+ if ! perf stat -e "${event}:R" --record-tpebs -a sleep 0.01 > "${stat_output}" 2>&1
+ then
+ echo "Testing with --record-tpebs [Failed perf stat]"
+ cat "${stat_output}"
+ exit 1
+ fi
+
+ # Expected output:
+ # $ perf stat --record-tpebs -e cache-misses:R -a sleep 0.01
+ # Events enabled
+ # [ perf record: Woken up 2 times to write data ]
+ # [ perf record: Captured and wrote 0.056 MB - ]
+ #
+ # Performance counter stats for 'system wide':
+ #
+ # 0 cache-misses:R
+ #
+ # 0.013963299 seconds time elapsed
+ if ! grep "perf record" "${stat_output}"
+ then
+ echo "Testing with --record-tpebs [Failed missing perf record]"
+ cat "${stat_output}"
+ exit 1
+ fi
+ if ! grep "${event}:R" "${stat_output}" && ! grep "/${event}/R" "${stat_output}"
+ then
+ echo "Testing with --record-tpebs [Failed missing event name]"
+ cat "${stat_output}"
+ exit 1
+ fi
+ echo "Testing with --record-tpebs [Success]"
+}
+
+test_with_record_tpebs
+cleanup
+exit 0
diff --git a/tools/perf/tests/shell/test_uprobe_from_different_cu.sh b/tools/perf/tests/shell/test_uprobe_from_different_cu.sh
index 33387c329f92..7adf9755d6de 100755
--- a/tools/perf/tests/shell/test_uprobe_from_different_cu.sh
+++ b/tools/perf/tests/shell/test_uprobe_from_different_cu.sh
@@ -4,12 +4,11 @@
set -e
-# Skip if there's no probe command.
-if ! perf | grep probe
-then
- echo "Skip: probe command isn't present"
- exit 2
-fi
+# shellcheck source=lib/probe.sh
+. "$(dirname $0)"/lib/probe.sh
+
+skip_if_no_perf_probe || exit 2
+[ "$(id -u)" == 0 ] || exit 2
# skip if there's no gcc
if ! [ -x "$(command -v gcc)" ]; then
diff --git a/tools/perf/tests/shell/trace+probe_vfs_getname.sh b/tools/perf/tests/shell/trace+probe_vfs_getname.sh
index 708a13f00635..60fccb62c540 100755
--- a/tools/perf/tests/shell/trace+probe_vfs_getname.sh
+++ b/tools/perf/tests/shell/trace+probe_vfs_getname.sh
@@ -15,6 +15,7 @@
skip_if_no_perf_probe || exit 2
skip_if_no_perf_trace || exit 2
+[ "$(id -u)" = 0 ] || exit 2
. "$(dirname $0)"/lib/probe_vfs_getname.sh
diff --git a/tools/perf/tests/shell/trace_btf_enum.sh b/tools/perf/tests/shell/trace_btf_enum.sh
index 8d1e6bbeac90..60b3fa254cf6 100755
--- a/tools/perf/tests/shell/trace_btf_enum.sh
+++ b/tools/perf/tests/shell/trace_btf_enum.sh
@@ -13,6 +13,7 @@ TESTPROG="perf test -w landlock"
# shellcheck source=lib/probe.sh
. "$(dirname $0)"/lib/probe.sh
skip_if_no_perf_trace || exit 2
+[ "$(id -u)" = 0 ] || exit 2
check_vmlinux() {
echo "Checking if vmlinux exists"
diff --git a/tools/perf/tests/shell/trace_btf_general.sh b/tools/perf/tests/shell/trace_btf_general.sh
index e9ee727f3433..a25d8744695e 100755
--- a/tools/perf/tests/shell/trace_btf_general.sh
+++ b/tools/perf/tests/shell/trace_btf_general.sh
@@ -76,6 +76,7 @@ trace_config() {
skip_if_no_perf_trace || exit 2
check_vmlinux || exit 2
+[ "$(id -u)" = 0 ] || exit 2
trace_config
diff --git a/tools/perf/tests/shell/trace_exit_race.sh b/tools/perf/tests/shell/trace_exit_race.sh
index fbb0adc33a88..1e247693e756 100755
--- a/tools/perf/tests/shell/trace_exit_race.sh
+++ b/tools/perf/tests/shell/trace_exit_race.sh
@@ -10,6 +10,7 @@
. "$(dirname $0)"/lib/probe.sh
skip_if_no_perf_trace || exit 2
+[ "$(id -u)" = 0 ] || exit 2
if [ "$1" = "-v" ]; then
verbose="1"
diff --git a/tools/perf/tests/shell/trace_record_replay.sh b/tools/perf/tests/shell/trace_record_replay.sh
new file mode 100755
index 000000000000..6b4ed863c1ef
--- /dev/null
+++ b/tools/perf/tests/shell/trace_record_replay.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+# perf trace record and replay
+# SPDX-License-Identifier: GPL-2.0
+
+# Check that perf trace works with record and replay
+
+# shellcheck source=lib/probe.sh
+. "$(dirname $0)"/lib/probe.sh
+
+skip_if_no_perf_trace || exit 2
+[ "$(id -u)" = 0 ] || exit 2
+
+file=$(mktemp /tmp/temporary_file.XXXXX)
+
+perf trace record -o ${file} sleep 1 || exit 1
+if ! perf trace -i ${file} 2>&1 | grep nanosleep; then
+ echo "Failed: cannot find *nanosleep syscall"
+ exit 1
+fi
+
+rm -f ${file}
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 290716783ac6..4a2ad7176fa0 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -104,12 +104,14 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
while ((event = perf_mmap__read_event(&md->core)) != NULL) {
struct perf_sample sample;
+ perf_sample__init(&sample, /*all=*/false);
if (event->header.type != PERF_RECORD_SAMPLE)
goto next_event;
err = evlist__parse_sample(evlist, event, &sample);
if (err < 0) {
pr_debug("Error during parse sample\n");
+ perf_sample__exit(&sample);
goto out_delete_evlist;
}
@@ -117,6 +119,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
nr_samples++;
next_event:
perf_mmap__consume(&md->core);
+ perf_sample__exit(&sample);
}
perf_mmap__read_done(&md->core);
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 576f82a15015..8df3f9d9ffd2 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -131,9 +131,11 @@ static int process_sample_event(struct evlist *evlist,
pid_t next_tid, prev_tid;
int cpu, err;
+ perf_sample__init(&sample, /*all=*/false);
if (evlist__parse_sample(evlist, event, &sample)) {
pr_debug("evlist__parse_sample failed\n");
- return -1;
+ err = -1;
+ goto out;
}
evsel = evlist__id2evsel(evlist, sample.id);
@@ -145,7 +147,7 @@ static int process_sample_event(struct evlist *evlist,
cpu, prev_tid, next_tid);
err = check_cpu(switch_tracking, cpu);
if (err)
- return err;
+ goto out;
/*
* Check for no missing sched_switch events i.e. that the
* evsel->core.system_wide flag has worked.
@@ -153,7 +155,8 @@ static int process_sample_event(struct evlist *evlist,
if (switch_tracking->tids[cpu] != -1 &&
switch_tracking->tids[cpu] != prev_tid) {
pr_debug("Missing sched_switch events\n");
- return -1;
+ err = -1;
+ goto out;
}
switch_tracking->tids[cpu] = next_tid;
}
@@ -169,7 +172,10 @@ static int process_sample_event(struct evlist *evlist,
switch_tracking->cycles_after_comm_4 = 1;
}
- return 0;
+ err = 0;
+out:
+ perf_sample__exit(&sample);
+ return err;
}
static int process_event(struct evlist *evlist, union perf_event *event,
diff --git a/tools/perf/tests/tool_pmu.c b/tools/perf/tests/tool_pmu.c
index 187942b749b7..1e900ef92e37 100644
--- a/tools/perf/tests/tool_pmu.c
+++ b/tools/perf/tests/tool_pmu.c
@@ -27,7 +27,7 @@ static int do_test(enum tool_pmu_event ev, bool with_pmu)
parse_events_error__init(&err);
ret = parse_events(evlist, str, &err);
if (ret) {
- if (tool_pmu__skip_event(tool_pmu__event_to_str(ev))) {
+ if (!tool_pmu__event_to_str(ev)) {
ret = TEST_OK;
goto out;
}
@@ -59,7 +59,7 @@ static int do_test(enum tool_pmu_event ev, bool with_pmu)
}
}
- if (!found && !tool_pmu__skip_event(tool_pmu__event_to_str(ev))) {
+ if (!found && tool_pmu__event_to_str(ev)) {
pr_debug("FAILED %s:%d Didn't find tool event '%s' in parsed evsels\n",
__FILE__, __LINE__, str);
ret = TEST_FAIL;
diff --git a/tools/perf/tests/workloads/datasym.c b/tools/perf/tests/workloads/datasym.c
index 8e08fc75a973..1d0b7d64e1ba 100644
--- a/tools/perf/tests/workloads/datasym.c
+++ b/tools/perf/tests/workloads/datasym.c
@@ -1,3 +1,6 @@
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
#include <linux/compiler.h>
#include "../tests.h"
@@ -7,16 +10,33 @@ typedef struct _buf {
char data2;
} buf __attribute__((aligned(64)));
-static buf buf1 = {
+/* volatile to try to avoid the compiler seeing reserved as unused. */
+static volatile buf workload_datasym_buf1 = {
/* to have this in the data section */
.reserved[0] = 1,
};
-static int datasym(int argc __maybe_unused, const char **argv __maybe_unused)
+static volatile sig_atomic_t done;
+
+static void sighandler(int sig __maybe_unused)
+{
+ done = 1;
+}
+
+static int datasym(int argc, const char **argv)
{
- for (;;) {
- buf1.data1++;
- if (buf1.data1 == 123) {
+ int sec = 1;
+
+ if (argc > 0)
+ sec = atoi(argv[0]);
+
+ signal(SIGINT, sighandler);
+ signal(SIGALRM, sighandler);
+ alarm(sec);
+
+ while (!done) {
+ workload_datasym_buf1.data1++;
+ if (workload_datasym_buf1.data1 == 123) {
/*
* Add some 'noise' in the loop to work around errata
* 1694299 on Arm N1.
@@ -30,9 +50,9 @@ static int datasym(int argc __maybe_unused, const char **argv __maybe_unused)
* longer a continuous repeating pattern that interacts
* badly with the bias.
*/
- buf1.data1++;
+ workload_datasym_buf1.data1++;
}
- buf1.data2 += buf1.data1;
+ workload_datasym_buf1.data2 += workload_datasym_buf1.data1;
}
return 0;
}