diff options
Diffstat (limited to 'tools/perf/tests')
28 files changed, 402 insertions, 99 deletions
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 4d15bf6041fb..aa4dc4f5abde 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -62,6 +62,7 @@ perf-y += pfm.o perf-y += parse-metric.o perf-y += pe-file-parsing.o perf-y += expand-cgroup.o +perf-y += perf-time-to-tsc.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir) diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c index 15cea518f5ad..b4b9a9488d51 100644 --- a/tools/perf/tests/backward-ring-buffer.c +++ b/tools/perf/tests/backward-ring-buffer.c @@ -109,7 +109,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m return TEST_FAIL; } - err = perf_evlist__create_maps(evlist, &opts.target); + err = evlist__create_maps(evlist, &opts.target); if (err < 0) { pr_debug("Not enough memory to create thread/cpu maps\n"); goto out_delete_evlist; @@ -127,7 +127,7 @@ int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __m goto out_delete_evlist; } - perf_evlist__config(evlist, &opts, NULL); + evlist__config(evlist, &opts, NULL); err = evlist__open(evlist); if (err < 0) { diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index cd77e334e577..f57e075b0ed2 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -9,12 +9,10 @@ #include <util/util.h> #include <util/bpf-loader.h> #include <util/evlist.h> -#include <linux/bpf.h> #include <linux/filter.h> #include <linux/kernel.h> #include <linux/string.h> #include <api/fs/fs.h> -#include <bpf/bpf.h> #include <perf/mmap.h> #include "tests.h" #include "llvm.h" @@ -25,6 +23,8 @@ #define PERF_TEST_BPF_PATH "/sys/fs/bpf/perf_test" #ifdef HAVE_LIBBPF_SUPPORT +#include <linux/bpf.h> +#include <bpf/bpf.h> static int epoll_pwait_loop(void) { @@ -144,23 +144,23 @@ static int do_test(struct bpf_object *obj, int (*func)(void), pid[sizeof(pid) - 1] = '\0'; opts.target.tid = opts.target.pid = pid; - /* Instead of perf_evlist__new_default, don't add default events */ + /* Instead of evlist__new_default, don't add default events */ evlist = evlist__new(); if (!evlist) { pr_debug("Not enough memory to create evlist\n"); return TEST_FAIL; } - err = perf_evlist__create_maps(evlist, &opts.target); + err = evlist__create_maps(evlist, &opts.target); if (err < 0) { pr_debug("Not enough memory to create thread/cpu maps\n"); goto out_delete_evlist; } - perf_evlist__splice_list_tail(evlist, &parse_state.list); + evlist__splice_list_tail(evlist, &parse_state.list); evlist->nr_groups = parse_state.nr_groups; - perf_evlist__config(evlist, &opts, NULL); + evlist__config(evlist, &opts, NULL); err = evlist__open(evlist); if (err < 0) { diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 132bdb3e6c31..7273823d0d02 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -142,6 +142,7 @@ static struct test generic_tests[] = { .skip_if_fail = false, .get_nr = test__wp_subtest_get_nr, .get_desc = test__wp_subtest_get_desc, + .skip_reason = test__wp_subtest_skip_reason, }, }, { @@ -350,6 +351,11 @@ static struct test generic_tests[] = { .func = test__expand_cgroup_events, }, { + .desc = "Convert perf time to TSC", + .func = test__perf_time_to_tsc, + .is_supported = test__tsc_is_supported, + }, + { .func = NULL, }, }; diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 035c9123549a..7c098d49c77e 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -378,8 +378,8 @@ static int process_sample_event(struct machine *machine, struct thread *thread; int ret; - if (perf_evlist__parse_sample(evlist, event, &sample)) { - pr_debug("perf_evlist__parse_sample failed\n"); + if (evlist__parse_sample(evlist, event, &sample)) { + pr_debug("evlist__parse_sample failed\n"); return -1; } @@ -637,7 +637,7 @@ static int do_test_code_reading(bool try_kcore) evlist = evlist__new(); if (!evlist) { - pr_debug("perf_evlist__new failed\n"); + pr_debug("evlist__new failed\n"); goto out_put; } @@ -651,7 +651,7 @@ static int do_test_code_reading(bool try_kcore) goto out_put; } - perf_evlist__config(evlist, &opts, NULL); + evlist__config(evlist, &opts, NULL); evsel = evlist__first(evlist); diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c index db68894a6f40..04ce4401f775 100644 --- a/tools/perf/tests/event-times.c +++ b/tools/perf/tests/event-times.c @@ -26,13 +26,13 @@ static int attach__enable_on_exec(struct evlist *evlist) pr_debug("attaching to spawned child, enable on exec\n"); - err = perf_evlist__create_maps(evlist, &target); + err = evlist__create_maps(evlist, &target); if (err < 0) { pr_debug("Not enough memory to create thread/cpu maps\n"); return err; } - err = perf_evlist__prepare_workload(evlist, &target, argv, false, NULL); + err = evlist__prepare_workload(evlist, &target, argv, false, NULL); if (err < 0) { pr_debug("Couldn't run the workload!\n"); return err; @@ -47,7 +47,7 @@ static int attach__enable_on_exec(struct evlist *evlist) return err; } - return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL; + return evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL; } static int detach__enable_on_exec(struct evlist *evlist) diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c index bdcf032f8516..656218179222 100644 --- a/tools/perf/tests/event_update.c +++ b/tools/perf/tests/event_update.c @@ -85,11 +85,10 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unused) { - struct evlist *evlist; struct evsel *evsel; struct event_name tmp; + struct evlist *evlist = evlist__new_default(); - evlist = perf_evlist__new_default(); TEST_ASSERT_VAL("failed to get evlist", evlist); evsel = evlist__first(evlist); diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index 0e224a0a55d9..f9e34bd26cf3 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -5,8 +5,7 @@ #include "tests.h" #include "debug.h" -static int perf_evsel__test_field(struct evsel *evsel, const char *name, - int size, bool should_be_signed) +static int evsel__test_field(struct evsel *evsel, const char *name, int size, bool should_be_signed) { struct tep_format_field *field = evsel__field(evsel, name); int is_signed; @@ -43,25 +42,25 @@ int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtes return -1; } - if (perf_evsel__test_field(evsel, "prev_comm", 16, false)) + if (evsel__test_field(evsel, "prev_comm", 16, false)) ret = -1; - if (perf_evsel__test_field(evsel, "prev_pid", 4, true)) + if (evsel__test_field(evsel, "prev_pid", 4, true)) ret = -1; - if (perf_evsel__test_field(evsel, "prev_prio", 4, true)) + if (evsel__test_field(evsel, "prev_prio", 4, true)) ret = -1; - if (perf_evsel__test_field(evsel, "prev_state", sizeof(long), true)) + if (evsel__test_field(evsel, "prev_state", sizeof(long), true)) ret = -1; - if (perf_evsel__test_field(evsel, "next_comm", 16, false)) + if (evsel__test_field(evsel, "next_comm", 16, false)) ret = -1; - if (perf_evsel__test_field(evsel, "next_pid", 4, true)) + if (evsel__test_field(evsel, "next_pid", 4, true)) ret = -1; - if (perf_evsel__test_field(evsel, "next_prio", 4, true)) + if (evsel__test_field(evsel, "next_prio", 4, true)) ret = -1; evsel__delete(evsel); @@ -73,16 +72,16 @@ int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtes return -1; } - if (perf_evsel__test_field(evsel, "comm", 16, false)) + if (evsel__test_field(evsel, "comm", 16, false)) ret = -1; - if (perf_evsel__test_field(evsel, "pid", 4, true)) + if (evsel__test_field(evsel, "pid", 4, true)) ret = -1; - if (perf_evsel__test_field(evsel, "prio", 4, true)) + if (evsel__test_field(evsel, "prio", 4, true)) ret = -1; - if (perf_evsel__test_field(evsel, "target_cpu", 4, true)) + if (evsel__test_field(evsel, "target_cpu", 4, true)) ret = -1; evsel__delete(evsel); diff --git a/tools/perf/tests/expand-cgroup.c b/tools/perf/tests/expand-cgroup.c index d5771e4d094f..0e46aeb843ce 100644 --- a/tools/perf/tests/expand-cgroup.c +++ b/tools/perf/tests/expand-cgroup.c @@ -26,7 +26,7 @@ static int test_expand_events(struct evlist *evlist, char **ev_name; struct evsel *evsel; - TEST_ASSERT_VAL("evlist is empty", !perf_evlist__empty(evlist)); + TEST_ASSERT_VAL("evlist is empty", !evlist__empty(evlist)); nr_events = evlist->core.nr_entries; ev_name = calloc(nr_events, sizeof(*ev_name)); @@ -100,10 +100,9 @@ out: for (i = 0; i < nr_events; i++) static int expand_default_events(void) { int ret; - struct evlist *evlist; struct rblist metric_events; + struct evlist *evlist = evlist__new_default(); - evlist = perf_evlist__new_default(); TEST_ASSERT_VAL("failed to get evlist", evlist); rblist__init(&metric_events); @@ -145,7 +144,7 @@ static int expand_libpfm_events(void) int ret; struct evlist *evlist; struct rblist metric_events; - const char event_str[] = "UNHALTED_CORE_CYCLES"; + const char event_str[] = "CYCLES"; struct option opt = { .value = &evlist, }; @@ -161,7 +160,7 @@ static int expand_libpfm_events(void) event_str, ret); goto out; } - if (perf_evlist__empty(evlist)) { + if (evlist__empty(evlist)) { pr_debug("libpfm was not enabled\n"); goto out; } diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index 50a0c9fcde7d..e6f1b2a38e03 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c @@ -92,7 +92,7 @@ int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_un CHECK__(parse_events(evlist, "dummy:u", NULL)); CHECK__(parse_events(evlist, "cycles:u", NULL)); - perf_evlist__config(evlist, &opts, NULL); + evlist__config(evlist, &opts, NULL); evsel = evlist__first(evlist); diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c index ae6cda81c209..98da8a8757ab 100644 --- a/tools/perf/tests/llvm.c +++ b/tools/perf/tests/llvm.c @@ -2,13 +2,13 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <bpf/libbpf.h> -#include <util/llvm-utils.h> -#include "llvm.h" #include "tests.h" #include "debug.h" #ifdef HAVE_LIBBPF_SUPPORT +#include <bpf/libbpf.h> +#include <util/llvm-utils.h> +#include "llvm.h" static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) { struct bpf_object *obj; @@ -19,14 +19,6 @@ static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) bpf_object__close(obj); return TEST_OK; } -#else -static int test__bpf_parsing(void *obj_buf __maybe_unused, - size_t obj_buf_sz __maybe_unused) -{ - pr_debug("Skip bpf parsing\n"); - return TEST_OK; -} -#endif static struct { const char *source; @@ -170,3 +162,19 @@ const char *test__llvm_subtest_get_desc(int subtest) return bpf_source_table[subtest].desc; } +#else //HAVE_LIBBPF_SUPPORT +int test__llvm(struct test *test __maybe_unused, int subtest __maybe_unused) +{ + return TEST_SKIP; +} + +int test__llvm_subtest_get_nr(void) +{ + return 0; +} + +const char *test__llvm_subtest_get_desc(int subtest __maybe_unused) +{ + return NULL; +} +#endif // HAVE_LIBBPF_SUPPORT diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 7b0dbfc0e17d..57093aeacc6f 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -69,7 +69,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse evlist = evlist__new(); if (evlist == NULL) { - pr_debug("perf_evlist__new\n"); + pr_debug("evlist__new\n"); goto out_free_cpus; } @@ -126,14 +126,14 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse goto out_delete_evlist; } - err = perf_evlist__parse_sample(evlist, event, &sample); + err = evlist__parse_sample(evlist, event, &sample); if (err) { pr_err("Can't parse sample, err = %d\n", err); goto out_delete_evlist; } err = -1; - evsel = perf_evlist__id2evsel(evlist, sample.id); + evsel = evlist__id2evsel(evlist, sample.id); if (evsel == NULL) { pr_debug("event with id %" PRIu64 " doesn't map to an evsel\n", sample.id); diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c index 1f5f5e79ae25..5e4af2f0f14a 100644 --- a/tools/perf/tests/openat-syscall-tp-fields.c +++ b/tools/perf/tests/openat-syscall-tp-fields.c @@ -42,7 +42,7 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest char sbuf[STRERR_BUFSIZE]; if (evlist == NULL) { - pr_debug("%s: perf_evlist__new\n", __func__); + pr_debug("%s: evlist__new\n", __func__); goto out; } @@ -54,9 +54,9 @@ int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest evlist__add(evlist, evsel); - err = perf_evlist__create_maps(evlist, &opts.target); + err = evlist__create_maps(evlist, &opts.target); if (err < 0) { - pr_debug("%s: perf_evlist__create_maps\n", __func__); + pr_debug("%s: evlist__create_maps\n", __func__); goto out_delete_evlist; } diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 611512f22b34..a7f6661e6112 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -115,7 +115,7 @@ static int test__checkevent_symbolic_name_config(struct evlist *evlist) TEST_ASSERT_VAL("wrong config", PERF_COUNT_HW_CPU_CYCLES == evsel->core.attr.config); /* - * The period value gets configured within perf_evlist__config, + * The period value gets configured within evlist__config, * while this test executes only parse events method. */ TEST_ASSERT_VAL("wrong period", @@ -443,7 +443,7 @@ static int test__checkevent_pmu(struct evlist *evlist) TEST_ASSERT_VAL("wrong config1", 1 == evsel->core.attr.config1); TEST_ASSERT_VAL("wrong config2", 3 == evsel->core.attr.config2); /* - * The period value gets configured within perf_evlist__config, + * The period value gets configured within evlist__config, * while this test executes only parse events method. */ TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); @@ -520,8 +520,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 1 == evsel->core.attr.config); /* - * The period, time and callgraph value gets configured - * within perf_evlist__config, + * The period, time and callgraph value gets configured within evlist__config, * while this test executes only parse events method. */ TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); @@ -533,8 +532,7 @@ static int test__checkevent_pmu_partial_time_callgraph(struct evlist *evlist) TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->core.attr.type); TEST_ASSERT_VAL("wrong config", 2 == evsel->core.attr.config); /* - * The period, time and callgraph value gets configured - * within perf_evlist__config, + * The period, time and callgraph value gets configured within evlist__config, * while this test executes only parse events method. */ TEST_ASSERT_VAL("wrong period", 0 == evsel->core.attr.sample_period); diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index 7c1bde01cb50..ce7be37f0d88 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -166,7 +166,7 @@ static int __compute_metric(const char *name, struct value *vals, if (err) goto out; - err = perf_evlist__alloc_stats(evlist, false); + err = evlist__alloc_stats(evlist, false); if (err) goto out; @@ -183,7 +183,7 @@ out: /* ... clenup. */ metricgroup__rblist_exit(&metric_events); runtime_stat__exit(&st); - perf_evlist__free_stats(evlist); + evlist__free_stats(evlist); perf_cpu_map__put(cpus); evlist__delete(evlist); return err; diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c index adf3c9c4a416..471273676701 100644 --- a/tools/perf/tests/parse-no-sample-id-all.c +++ b/tools/perf/tests/parse-no-sample-id-all.c @@ -27,8 +27,8 @@ static int process_event(struct evlist **pevlist, union perf_event *event) if (!*pevlist) return -1; - if (perf_evlist__parse_sample(*pevlist, event, &sample)) { - pr_debug("perf_evlist__parse_sample failed\n"); + if (evlist__parse_sample(*pevlist, event, &sample)) { + 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 67d3f5aad016..0df471bf1590 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c @@ -53,7 +53,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus }; cpu_set_t cpu_mask; size_t cpu_mask_size = sizeof(cpu_mask); - struct evlist *evlist = perf_evlist__new_dummy(); + struct evlist *evlist = evlist__new_dummy(); struct evsel *evsel; struct perf_sample sample; const char *cmd = "sleep"; @@ -71,7 +71,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus char sbuf[STRERR_BUFSIZE]; if (evlist == NULL) /* Fallback for kernels lacking PERF_COUNT_SW_DUMMY */ - evlist = perf_evlist__new_default(); + evlist = evlist__new_default(); if (evlist == NULL) { pr_debug("Not enough memory to create evlist\n"); @@ -81,10 +81,10 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus /* * Create maps of threads and cpus to monitor. In this case * we start with all threads and cpus (-1, -1) but then in - * perf_evlist__prepare_workload we'll fill in the only thread + * evlist__prepare_workload we'll fill in the only thread * we're monitoring, the one forked there. */ - err = perf_evlist__create_maps(evlist, &opts.target); + err = evlist__create_maps(evlist, &opts.target); if (err < 0) { pr_debug("Not enough memory to create thread/cpu maps\n"); goto out_delete_evlist; @@ -92,11 +92,11 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus /* * Prepare the workload in argv[] to run, it'll fork it, and then wait - * for perf_evlist__start_workload() to exec it. This is done this way + * for evlist__start_workload() to exec it. This is done this way * so that we have time to open the evlist (calling sys_perf_event_open * on all the fds) and then mmap them. */ - err = perf_evlist__prepare_workload(evlist, &opts.target, argv, false, NULL); + err = evlist__prepare_workload(evlist, &opts.target, argv, false, NULL); if (err < 0) { pr_debug("Couldn't run the workload!\n"); goto out_delete_evlist; @@ -109,7 +109,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus evsel__set_sample_bit(evsel, CPU); evsel__set_sample_bit(evsel, TID); evsel__set_sample_bit(evsel, TIME); - perf_evlist__config(evlist, &opts, NULL); + evlist__config(evlist, &opts, NULL); err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); if (err < 0) { @@ -161,7 +161,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus /* * Now! */ - perf_evlist__start_workload(evlist); + evlist__start_workload(evlist); while (1) { int before = total_events; @@ -182,7 +182,7 @@ int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unus if (type < PERF_RECORD_MAX) nr_events[type]++; - err = perf_evlist__parse_sample(evlist, event, &sample); + err = evlist__parse_sample(evlist, event, &sample); if (err < 0) { if (verbose > 0) perf_event__fprintf(event, NULL, stderr); diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c new file mode 100644 index 000000000000..7cff02664d0e --- /dev/null +++ b/tools/perf/tests/perf-time-to-tsc.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <errno.h> +#include <inttypes.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <unistd.h> +#include <linux/types.h> +#include <sys/prctl.h> +#include <perf/cpumap.h> +#include <perf/evlist.h> +#include <perf/mmap.h> + +#include "debug.h" +#include "parse-events.h" +#include "evlist.h" +#include "evsel.h" +#include "thread_map.h" +#include "record.h" +#include "tsc.h" +#include "mmap.h" +#include "tests.h" + +#define CHECK__(x) { \ + while ((x) < 0) { \ + pr_debug(#x " failed!\n"); \ + goto out_err; \ + } \ +} + +#define CHECK_NOT_NULL__(x) { \ + while ((x) == NULL) { \ + pr_debug(#x " failed!\n"); \ + goto out_err; \ + } \ +} + +/** + * test__perf_time_to_tsc - test converting perf time to TSC. + * + * This function implements a test that checks that the conversion of perf time + * to and from TSC is consistent with the order of events. If the test passes + * %0 is returned, otherwise %-1 is returned. If TSC conversion is not + * supported then then the test passes but " (not supported)" is printed. + */ +int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe_unused) +{ + struct record_opts opts = { + .mmap_pages = UINT_MAX, + .user_freq = UINT_MAX, + .user_interval = ULLONG_MAX, + .target = { + .uses_mmap = true, + }, + .sample_time = true, + }; + struct perf_thread_map *threads = NULL; + struct perf_cpu_map *cpus = NULL; + struct evlist *evlist = NULL; + struct evsel *evsel = NULL; + int err = -1, ret, i; + const char *comm1, *comm2; + struct perf_tsc_conversion tc; + struct perf_event_mmap_page *pc; + union perf_event *event; + u64 test_tsc, comm1_tsc, comm2_tsc; + u64 test_time, comm1_time = 0, comm2_time = 0; + struct mmap *md; + + threads = thread_map__new(-1, getpid(), UINT_MAX); + CHECK_NOT_NULL__(threads); + + cpus = perf_cpu_map__new(NULL); + CHECK_NOT_NULL__(cpus); + + evlist = evlist__new(); + CHECK_NOT_NULL__(evlist); + + perf_evlist__set_maps(&evlist->core, cpus, threads); + + CHECK__(parse_events(evlist, "cycles:u", NULL)); + + evlist__config(evlist, &opts, NULL); + + evsel = evlist__first(evlist); + + evsel->core.attr.comm = 1; + evsel->core.attr.disabled = 1; + evsel->core.attr.enable_on_exec = 0; + + CHECK__(evlist__open(evlist)); + + CHECK__(evlist__mmap(evlist, UINT_MAX)); + + pc = evlist->mmap[0].core.base; + ret = perf_read_tsc_conversion(pc, &tc); + if (ret) { + if (ret == -EOPNOTSUPP) { + fprintf(stderr, " (not supported)"); + return 0; + } + goto out_err; + } + + evlist__enable(evlist); + + comm1 = "Test COMM 1"; + CHECK__(prctl(PR_SET_NAME, (unsigned long)comm1, 0, 0, 0)); + + test_tsc = rdtsc(); + + comm2 = "Test COMM 2"; + CHECK__(prctl(PR_SET_NAME, (unsigned long)comm2, 0, 0, 0)); + + evlist__disable(evlist); + + for (i = 0; i < evlist->core.nr_mmaps; i++) { + md = &evlist->mmap[i]; + if (perf_mmap__read_init(&md->core) < 0) + continue; + + while ((event = perf_mmap__read_event(&md->core)) != NULL) { + struct perf_sample sample; + + if (event->header.type != PERF_RECORD_COMM || + (pid_t)event->comm.pid != getpid() || + (pid_t)event->comm.tid != getpid()) + goto next_event; + + if (strcmp(event->comm.comm, comm1) == 0) { + CHECK__(evsel__parse_sample(evsel, event, &sample)); + comm1_time = sample.time; + } + if (strcmp(event->comm.comm, comm2) == 0) { + CHECK__(evsel__parse_sample(evsel, event, &sample)); + comm2_time = sample.time; + } +next_event: + perf_mmap__consume(&md->core); + } + perf_mmap__read_done(&md->core); + } + + if (!comm1_time || !comm2_time) + goto out_err; + + test_time = tsc_to_perf_time(test_tsc, &tc); + comm1_tsc = perf_time_to_tsc(comm1_time, &tc); + comm2_tsc = perf_time_to_tsc(comm2_time, &tc); + + pr_debug("1st event perf time %"PRIu64" tsc %"PRIu64"\n", + comm1_time, comm1_tsc); + pr_debug("rdtsc time %"PRIu64" tsc %"PRIu64"\n", + test_time, test_tsc); + pr_debug("2nd event perf time %"PRIu64" tsc %"PRIu64"\n", + comm2_time, comm2_tsc); + + if (test_time <= comm1_time || + test_time >= comm2_time) + goto out_err; + + if (test_tsc <= comm1_tsc || + test_tsc >= comm2_tsc) + goto out_err; + + err = 0; + +out_err: + evlist__delete(evlist); + return err; +} + +bool test__tsc_is_supported(void) +{ + /* + * Except x86_64/i386 and Arm64, other archs don't support TSC in perf. + * Just enable the test for x86_64/i386 and Arm64 archs. + */ +#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) + return true; +#else + return false; +#endif +} diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index d3517a74d95e..0ca6a5a53523 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -14,8 +14,10 @@ #include "util/parse-events.h" struct perf_pmu_test_event { + /* used for matching against events from generated pmu-events.c */ struct pmu_event event; + /* used for matching against event aliases */ /* extra events for aliases */ const char *alias_str; @@ -78,6 +80,17 @@ static struct perf_pmu_test_event test_cpu_events[] = { .alias_str = "umask=0,(null)=0x30d40,event=0x3a", .alias_long_desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", }, + { + .event = { + .name = "l3_cache_rd", + .event = "event=0x40", + .desc = "L3 cache access, read", + .long_desc = "Attributable Level 3 cache access, read", + .topic = "cache", + }, + .alias_str = "event=0x40", + .alias_long_desc = "Attributable Level 3 cache access, read", + }, { /* sentinel */ .event = { .name = NULL, @@ -357,6 +370,7 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) } +/* Test that aliases generated are as expected */ static int test_aliases(void) { struct perf_pmu *pmu = NULL; @@ -561,7 +575,7 @@ static int metric_parse_fake(const char *str) } } - if (expr__parse(&result, &ctx, str, 1)) + if (expr__parse(&result, &ctx, str, 0)) pr_err("expr__parse failed\n"); else ret = 0; diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index a0bdaf390ac8..2393916f6128 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -154,6 +154,9 @@ static bool samples_same(const struct perf_sample *s1, if (type & PERF_SAMPLE_CGROUP) COMP(cgroup); + if (type & PERF_SAMPLE_DATA_PAGE_SIZE) + COMP(data_page_size); + if (type & PERF_SAMPLE_AUX) { COMP(aux_sample.size); if (memcmp(s1->aux_sample.data, s2->aux_sample.data, @@ -234,6 +237,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) }, .phys_addr = 113, .cgroup = 114, + .data_page_size = 115, .aux_sample = { .size = sizeof(aux_data), .data = (void *)aux_data, @@ -340,7 +344,7 @@ int test__sample_parsing(struct test *test __maybe_unused, int subtest __maybe_u * were added. Please actually update the test rather than just change * the condition below. */ - if (PERF_SAMPLE_MAX > PERF_SAMPLE_CGROUP << 1) { + if (PERF_SAMPLE_MAX > PERF_SAMPLE_CODE_PAGE_SIZE << 1) { pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n"); return -1; } diff --git a/tools/perf/tests/shell/stat+shadow_stat.sh b/tools/perf/tests/shell/stat+shadow_stat.sh new file mode 100755 index 000000000000..249dfe48cf6a --- /dev/null +++ b/tools/perf/tests/shell/stat+shadow_stat.sh @@ -0,0 +1,80 @@ +#!/bin/sh +# perf stat metrics (shadow stat) test +# SPDX-License-Identifier: GPL-2.0 + +set -e + +# skip if system-wide mode is forbidden +perf stat -a true > /dev/null 2>&1 || exit 2 + +test_global_aggr() +{ + local cyc + + perf stat -a --no-big-num -e cycles,instructions sleep 1 2>&1 | \ + grep -e cycles -e instructions | \ + while read num evt hash ipc rest + do + # skip not counted events + if [[ $num == "<not" ]]; then + continue + fi + + # save cycles count + if [[ $evt == "cycles" ]]; then + cyc=$num + continue + fi + + # skip if no cycles + if [[ -z $cyc ]]; then + continue + fi + + # use printf for rounding and a leading zero + local res=`printf "%.2f" $(echo "scale=6; $num / $cyc" | bc -q)` + if [[ $ipc != $res ]]; then + echo "IPC is different: $res != $ipc ($num / $cyc)" + exit 1 + fi + done +} + +test_no_aggr() +{ + declare -A results + + perf stat -a -A --no-big-num -e cycles,instructions sleep 1 2>&1 | \ + grep ^CPU | \ + while read cpu num evt hash ipc rest + do + # skip not counted events + if [[ $num == "<not" ]]; then + continue + fi + + # save cycles count + if [[ $evt == "cycles" ]]; then + results[$cpu]=$num + continue + fi + + # skip if no cycles + local cyc=${results[$cpu]} + if [[ -z $cyc ]]; then + continue + fi + + # use printf for rounding and a leading zero + local res=`printf "%.2f" $(echo "scale=6; $num / $cyc" | bc -q)` + if [[ $ipc != $res ]]; then + echo "IPC is different for $cpu: $res != $ipc ($num / $cyc)" + exit 1 + fi + done +} + +test_global_aggr +test_no_aggr + +exit 0 diff --git a/tools/perf/tests/shell/trace+probe_vfs_getname.sh b/tools/perf/tests/shell/trace+probe_vfs_getname.sh index 11cc2af13f2b..3d31c1d560d6 100755 --- a/tools/perf/tests/shell/trace+probe_vfs_getname.sh +++ b/tools/perf/tests/shell/trace+probe_vfs_getname.sh @@ -20,7 +20,7 @@ skip_if_no_perf_trace || exit 2 file=$(mktemp /tmp/temporary_file.XXXXX) trace_open_vfs_getname() { - evts=$(echo $(perf list syscalls:sys_enter_open* 2>&1 | egrep 'open(at)? ' | sed -r 's/.*sys_enter_([a-z]+) +\[.*$/\1/') | sed 's/ /,/') + evts=$(echo $(perf list syscalls:sys_enter_open* 2>/dev/null | egrep 'open(at)? ' | sed -r 's/.*sys_enter_([a-z]+) +\[.*$/\1/') | sed 's/ /,/') perf trace -e $evts touch $file 2>&1 | \ egrep " +[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]+$" } diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 4b9b731977c8..a49c9e23053b 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c @@ -109,7 +109,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) if (event->header.type != PERF_RECORD_SAMPLE) goto next_event; - err = perf_evlist__parse_sample(evlist, event, &sample); + err = evlist__parse_sample(evlist, event, &sample); if (err < 0) { pr_debug("Error during parse sample\n"); goto out_delete_evlist; diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index db5e1f70053a..15a2ab765d89 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c @@ -128,12 +128,12 @@ static int process_sample_event(struct evlist *evlist, pid_t next_tid, prev_tid; int cpu, err; - if (perf_evlist__parse_sample(evlist, event, &sample)) { - pr_debug("perf_evlist__parse_sample failed\n"); + if (evlist__parse_sample(evlist, event, &sample)) { + pr_debug("evlist__parse_sample failed\n"); return -1; } - evsel = perf_evlist__id2evsel(evlist, sample.id); + evsel = evlist__id2evsel(evlist, sample.id); if (evsel == switch_tracking->switch_evsel) { next_tid = evsel__intval(evsel, &sample, "next_pid"); prev_tid = evsel__intval(evsel, &sample, "prev_pid"); @@ -223,8 +223,8 @@ static int add_event(struct evlist *evlist, struct list_head *events, node->event = event; list_add(&node->list, events); - if (perf_evlist__parse_sample(evlist, event, &sample)) { - pr_debug("perf_evlist__parse_sample failed\n"); + if (evlist__parse_sample(evlist, event, &sample)) { + pr_debug("evlist__parse_sample failed\n"); return -1; } @@ -380,7 +380,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ cycles_evsel = evlist__last(evlist); /* Third event */ - if (!perf_evlist__can_select_event(evlist, sched_switch)) { + if (!evlist__can_select_event(evlist, sched_switch)) { pr_debug("No sched_switch\n"); err = 0; goto out; @@ -406,7 +406,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ pr_debug("cycles event already at front"); goto out_err; } - perf_evlist__to_front(evlist, cycles_evsel); + evlist__to_front(evlist, cycles_evsel); if (cycles_evsel != evlist__first(evlist)) { pr_debug("Failed to move cycles event to front"); goto out_err; @@ -424,7 +424,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ tracking_evsel = evlist__last(evlist); - perf_evlist__set_tracking_event(evlist, tracking_evsel); + evlist__set_tracking_event(evlist, tracking_evsel); tracking_evsel->core.attr.freq = 0; tracking_evsel->core.attr.sample_period = 1; @@ -432,7 +432,7 @@ int test__switch_tracking(struct test *test __maybe_unused, int subtest __maybe_ evsel__set_sample_bit(tracking_evsel, TIME); /* Config events */ - perf_evlist__config(evlist, &opts, NULL); + evlist__config(evlist, &opts, NULL); /* Check moved event is still at the front */ if (cycles_evsel != evlist__first(evlist)) { diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index adaff9044331..bbf94e4aa145 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c @@ -23,7 +23,7 @@ static void sig_handler(int sig __maybe_unused) } /* - * perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since + * evlist__prepare_workload will send a SIGUSR1 if the fork fails, since * we asked by setting its exec_error to this handler. */ static void workload_exec_failed_signal(int signo __maybe_unused, @@ -58,16 +58,16 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused signal(SIGCHLD, sig_handler); - evlist = perf_evlist__new_default(); + evlist = evlist__new_default(); if (evlist == NULL) { - pr_debug("perf_evlist__new_default\n"); + pr_debug("evlist__new_default\n"); return -1; } /* * Create maps of threads and cpus to monitor. In this case * we start with all threads and cpus (-1, -1) but then in - * perf_evlist__prepare_workload we'll fill in the only thread + * evlist__prepare_workload we'll fill in the only thread * we're monitoring, the one forked there. */ cpus = perf_cpu_map__dummy_new(); @@ -83,8 +83,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused cpus = NULL; threads = NULL; - err = perf_evlist__prepare_workload(evlist, &target, argv, false, - workload_exec_failed_signal); + err = evlist__prepare_workload(evlist, &target, argv, false, workload_exec_failed_signal); if (err < 0) { pr_debug("Couldn't run the workload!\n"); goto out_delete_evlist; @@ -116,7 +115,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused goto out_delete_evlist; } - perf_evlist__start_workload(evlist); + evlist__start_workload(evlist); retry: md = &evlist->mmap[0]; diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index c85a2c08e407..8e24a61fe4c2 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -66,6 +66,7 @@ int test__bp_signal_overflow(struct test *test, int subtest); int test__bp_accounting(struct test *test, int subtest); int test__wp(struct test *test, int subtest); const char *test__wp_subtest_get_desc(int subtest); +const char *test__wp_subtest_skip_reason(int subtest); int test__wp_subtest_get_nr(void); int test__task_exit(struct test *test, int subtest); int test__mem(struct test *test, int subtest); @@ -124,10 +125,12 @@ int test__pfm_subtest_get_nr(void); int test__parse_metric(struct test *test, int subtest); int test__pe_file_parsing(struct test *test, int subtest); int test__expand_cgroup_events(struct test *test, int subtest); +int test__perf_time_to_tsc(struct test *test, int subtest); bool test__bp_signal_is_supported(void); bool test__bp_account_is_supported(void); bool test__wp_is_supported(void); +bool test__tsc_is_supported(void); #if defined(__arm__) || defined(__aarch64__) #ifdef HAVE_DWARF_UNWIND_SUPPORT diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c index 22daf2bdf5fa..165feedc7863 100644 --- a/tools/perf/tests/topology.c +++ b/tools/perf/tests/topology.c @@ -40,7 +40,7 @@ static int session_write_header(char *path) session = perf_session__new(&data, false, NULL); TEST_ASSERT_VAL("can't get session", !IS_ERR(session)); - session->evlist = perf_evlist__new_default(); + session->evlist = evlist__new_default(); TEST_ASSERT_VAL("can't get evlist", session->evlist); perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); diff --git a/tools/perf/tests/wp.c b/tools/perf/tests/wp.c index d262d6639829..9387fa76faa5 100644 --- a/tools/perf/tests/wp.c +++ b/tools/perf/tests/wp.c @@ -174,10 +174,12 @@ static bool wp_ro_supported(void) #endif } -static void wp_ro_skip_msg(void) +static const char *wp_ro_skip_msg(void) { #if defined (__x86_64__) || defined (__i386__) - pr_debug("Hardware does not support read only watchpoints.\n"); + return "missing hardware support"; +#else + return NULL; #endif } @@ -185,7 +187,7 @@ static struct { const char *desc; int (*target_func)(void); bool (*is_supported)(void); - void (*skip_msg)(void); + const char *(*skip_msg)(void); } wp_testcase_table[] = { { .desc = "Read Only Watchpoint", @@ -219,16 +221,23 @@ const char *test__wp_subtest_get_desc(int i) return wp_testcase_table[i].desc; } +const char *test__wp_subtest_skip_reason(int i) +{ + if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table)) + return NULL; + if (!wp_testcase_table[i].skip_msg) + return NULL; + return wp_testcase_table[i].skip_msg(); +} + int test__wp(struct test *test __maybe_unused, int i) { if (i < 0 || i >= (int)ARRAY_SIZE(wp_testcase_table)) return TEST_FAIL; if (wp_testcase_table[i].is_supported && - !wp_testcase_table[i].is_supported()) { - wp_testcase_table[i].skip_msg(); + !wp_testcase_table[i].is_supported()) return TEST_SKIP; - } return !wp_testcase_table[i].target_func() ? TEST_OK : TEST_FAIL; } |