diff options
Diffstat (limited to 'tools/perf/tests')
23 files changed, 353 insertions, 113 deletions
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 90fd1eb317bb..fb9ac5dc4079 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -68,6 +68,7 @@ perf-y += perf-time-to-tsc.o perf-y += dlfilter-test.o perf-y += sigtrap.o perf-y += event_groups.o +perf-y += symbols.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir) diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c index 7981c69ed1b4..b638cc99d5ae 100644 --- a/tools/perf/tests/bpf-script-example.c +++ b/tools/perf/tests/bpf-script-example.c @@ -43,7 +43,7 @@ struct { __type(value, int); } flip_table SEC(".maps"); -SEC("func=do_epoll_wait") +SEC("syscalls:sys_enter_epoll_pwait") int bpf_func__SyS_epoll_pwait(void *ctx) { int ind =0; diff --git a/tools/perf/tests/bpf-script-test-prologue.c b/tools/perf/tests/bpf-script-test-prologue.c index bd83d364cf30..91778b5c6125 100644 --- a/tools/perf/tests/bpf-script-test-prologue.c +++ b/tools/perf/tests/bpf-script-test-prologue.c @@ -20,6 +20,8 @@ # undef if #endif +typedef unsigned int __bitwise fmode_t; + #define FMODE_READ 0x1 #define FMODE_WRITE 0x2 diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index 17c023823713..ae9223f27cfb 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -23,7 +23,7 @@ #define NR_ITERS 111 #define PERF_TEST_BPF_PATH "/sys/fs/bpf/perf_test" -#ifdef HAVE_LIBBPF_SUPPORT +#if defined(HAVE_LIBBPF_SUPPORT) && defined(HAVE_LIBTRACEEVENT) #include <linux/bpf.h> #include <bpf/bpf.h> @@ -126,6 +126,10 @@ static int do_test(struct bpf_object *obj, int (*func)(void), err = parse_events_load_bpf_obj(&parse_state, &parse_state.list, obj, NULL); parse_events_error__exit(&parse_error); + if (err == -ENODATA) { + pr_debug("Failed to add events selected by BPF, debuginfo package not installed\n"); + return TEST_SKIP; + } if (err || list_empty(&parse_state.list)) { pr_debug("Failed to add events selected by BPF\n"); return TEST_FAIL; @@ -330,10 +334,10 @@ static int test__bpf(int i) static int test__basic_bpf_test(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { -#ifdef HAVE_LIBBPF_SUPPORT +#if defined(HAVE_LIBBPF_SUPPORT) && defined(HAVE_LIBTRACEEVENT) return test__bpf(0); #else - pr_debug("Skip BPF test because BPF support is not compiled\n"); + pr_debug("Skip BPF test because BPF or libtraceevent support is not compiled\n"); return TEST_SKIP; #endif } @@ -341,10 +345,10 @@ static int test__basic_bpf_test(struct test_suite *test __maybe_unused, static int test__bpf_pinning(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { -#ifdef HAVE_LIBBPF_SUPPORT +#if defined(HAVE_LIBBPF_SUPPORT) && defined(HAVE_LIBTRACEEVENT) return test__bpf(1); #else - pr_debug("Skip BPF test because BPF support is not compiled\n"); + pr_debug("Skip BPF test because BPF or libtraceevent support is not compiled\n"); return TEST_SKIP; #endif } @@ -352,30 +356,30 @@ static int test__bpf_pinning(struct test_suite *test __maybe_unused, static int test__bpf_prologue_test(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { -#if defined(HAVE_LIBBPF_SUPPORT) && defined(HAVE_BPF_PROLOGUE) +#if defined(HAVE_LIBBPF_SUPPORT) && defined(HAVE_BPF_PROLOGUE) && defined(HAVE_LIBTRACEEVENT) return test__bpf(2); #else - pr_debug("Skip BPF test because BPF support is not compiled\n"); + pr_debug("Skip BPF test because BPF or libtraceevent support is not compiled\n"); return TEST_SKIP; #endif } static struct test_case bpf_tests[] = { -#ifdef HAVE_LIBBPF_SUPPORT +#if defined(HAVE_LIBBPF_SUPPORT) && defined(HAVE_LIBTRACEEVENT) TEST_CASE("Basic BPF filtering", basic_bpf_test), TEST_CASE_REASON("BPF pinning", bpf_pinning, "clang isn't installed or environment missing BPF support"), #ifdef HAVE_BPF_PROLOGUE TEST_CASE_REASON("BPF prologue generation", bpf_prologue_test, - "clang isn't installed or environment missing BPF support"), + "clang/debuginfo isn't installed or environment missing BPF support"), #else TEST_CASE_REASON("BPF prologue generation", bpf_prologue_test, "not compiled in"), #endif #else - TEST_CASE_REASON("Basic BPF filtering", basic_bpf_test, "not compiled in"), - TEST_CASE_REASON("BPF pinning", bpf_pinning, "not compiled in"), - TEST_CASE_REASON("BPF prologue generation", bpf_prologue_test, "not compiled in"), + TEST_CASE_REASON("Basic BPF filtering", basic_bpf_test, "not compiled in or missing libtraceevent support"), + TEST_CASE_REASON("BPF pinning", bpf_pinning, "not compiled in or missing libtraceevent support"), + TEST_CASE_REASON("BPF prologue generation", bpf_prologue_test, "not compiled in or missing libtraceevent support"), #endif { .name = NULL, } }; diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index cfa61493c750..35cc3807cc9e 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -31,6 +31,7 @@ #include "builtin-test-list.h" static bool dont_fork; +const char *dso_to_test; struct test_suite *__weak arch_tests[] = { NULL, @@ -117,6 +118,7 @@ static struct test_suite *generic_tests[] = { &suite__dlfilter, &suite__sigtrap, &suite__event_groups, + &suite__symbols, NULL, }; @@ -521,6 +523,7 @@ int cmd_test(int argc, const char **argv) OPT_BOOLEAN('F', "dont-fork", &dont_fork, "Do not fork for testcase"), OPT_STRING('w', "workload", &workload, "work", "workload to run for testing"), + OPT_STRING(0, "dso", &dso_to_test, "dso", "dso to test"), OPT_END() }; const char * const test_subcommands[] = { "list", NULL }; diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c index afdca7f2959f..ee983b677a6a 100644 --- a/tools/perf/tests/dwarf-unwind.c +++ b/tools/perf/tests/dwarf-unwind.c @@ -67,6 +67,7 @@ int test_dwarf_unwind__compare(void *p1, void *p2); int test_dwarf_unwind__krava_3(struct thread *thread); int test_dwarf_unwind__krava_2(struct thread *thread); int test_dwarf_unwind__krava_1(struct thread *thread); +int test__dwarf_unwind(struct test_suite *test, int subtest); #define MAX_STACK 8 @@ -195,8 +196,8 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_1(struct thread *th return ret; } -static int test__dwarf_unwind(struct test_suite *test __maybe_unused, - int subtest __maybe_unused) +noinline int test__dwarf_unwind(struct test_suite *test __maybe_unused, + int subtest __maybe_unused) { struct machine *machine; struct thread *thread; diff --git a/tools/perf/tests/expand-cgroup.c b/tools/perf/tests/expand-cgroup.c index 51fb5f34c1dd..672a27f37060 100644 --- a/tools/perf/tests/expand-cgroup.c +++ b/tools/perf/tests/expand-cgroup.c @@ -180,13 +180,13 @@ static int expand_metric_events(void) struct evlist *evlist; struct rblist metric_events; const char metric_str[] = "CPI"; - const struct pmu_events_table *pme_test; + const struct pmu_metrics_table *pme_test; evlist = evlist__new(); TEST_ASSERT_VAL("failed to get evlist", evlist); rblist__init(&metric_events); - pme_test = find_core_events_table("testarch", "testcpu"); + pme_test = find_core_metrics_table("testarch", "testcpu"); ret = metricgroup__parse_groups_test(evlist, pme_test, metric_str, false, false, &metric_events); if (ret < 0) { diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 05e818a8bbad..009d6efb673c 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -222,19 +222,7 @@ installed_files_bin := bin/perf installed_files_bin += etc/bash_completion.d/perf installed_files_bin += libexec/perf-core/perf-archive -installed_files_plugins := $(lib)/traceevent/plugins/plugin_cfg80211.so -installed_files_plugins += $(lib)/traceevent/plugins/plugin_scsi.so -installed_files_plugins += $(lib)/traceevent/plugins/plugin_xen.so -installed_files_plugins += $(lib)/traceevent/plugins/plugin_function.so -installed_files_plugins += $(lib)/traceevent/plugins/plugin_sched_switch.so -installed_files_plugins += $(lib)/traceevent/plugins/plugin_mac80211.so -installed_files_plugins += $(lib)/traceevent/plugins/plugin_kvm.so -installed_files_plugins += $(lib)/traceevent/plugins/plugin_kmem.so -installed_files_plugins += $(lib)/traceevent/plugins/plugin_hrtimer.so -installed_files_plugins += $(lib)/traceevent/plugins/plugin_jbd2.so - installed_files_all := $(installed_files_bin) -installed_files_all += $(installed_files_plugins) test_make_install := $(call test_dest_files,$(installed_files_all)) test_make_install_O := $(call test_dest_files,$(installed_files_all)) diff --git a/tools/perf/tests/parse-metric.c b/tools/perf/tests/parse-metric.c index 21b7ac00d798..9fec6040950c 100644 --- a/tools/perf/tests/parse-metric.c +++ b/tools/perf/tests/parse-metric.c @@ -72,7 +72,7 @@ static int __compute_metric(const char *name, struct value *vals, struct rblist metric_events = { .nr_entries = 0, }; - const struct pmu_events_table *pme_test; + const struct pmu_metrics_table *pme_test; struct perf_cpu_map *cpus; struct runtime_stat st; struct evlist *evlist; @@ -96,7 +96,7 @@ static int __compute_metric(const char *name, struct value *vals, runtime_stat__init(&st); /* Parse the metric into metric_events list. */ - pme_test = find_core_events_table("testarch", "testcpu"); + pme_test = find_core_metrics_table("testarch", "testcpu"); err = metricgroup__parse_groups_test(evlist, pme_test, name, false, false, &metric_events); diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index a9f2330f6257..accf44b3d968 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -337,36 +337,12 @@ static int compare_pmu_events(const struct pmu_event *e1, const struct pmu_event return -1; } - if (!is_same(e1->metric_expr, e2->metric_expr)) { - pr_debug2("testing event e1 %s: mismatched metric_expr, %s vs %s\n", - e1->name, e1->metric_expr, e2->metric_expr); - return -1; - } - - if (!is_same(e1->metric_name, e2->metric_name)) { - pr_debug2("testing event e1 %s: mismatched metric_name, %s vs %s\n", - e1->name, e1->metric_name, e2->metric_name); - return -1; - } - - if (!is_same(e1->metric_group, e2->metric_group)) { - pr_debug2("testing event e1 %s: mismatched metric_group, %s vs %s\n", - e1->name, e1->metric_group, e2->metric_group); - return -1; - } - if (!is_same(e1->deprecated, e2->deprecated)) { pr_debug2("testing event e1 %s: mismatched deprecated, %s vs %s\n", e1->name, e1->deprecated, e2->deprecated); return -1; } - if (!is_same(e1->metric_constraint, e2->metric_constraint)) { - pr_debug2("testing event e1 %s: mismatched metric_constant, %s vs %s\n", - e1->name, e1->metric_constraint, e2->metric_constraint); - return -1; - } - return 0; } @@ -432,9 +408,6 @@ static int test__pmu_event_table_core_callback(const struct pmu_event *pe, struct perf_pmu_test_event const **test_event_table; bool found = false; - if (!pe->name) - return 0; - if (pe->pmu) test_event_table = &uncore_events[0]; else @@ -496,7 +469,8 @@ static int test__pmu_event_table_sys_callback(const struct pmu_event *pe, static int test__pmu_event_table(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { - const struct pmu_events_table *sys_event_table = find_sys_events_table("pme_test_soc_sys"); + const struct pmu_events_table *sys_event_table = + find_sys_events_table("pmu_events__test_soc_sys"); const struct pmu_events_table *table = find_core_events_table("testarch", "testcpu"); int map_events = 0, expected_events, err; @@ -840,7 +814,8 @@ struct metric { struct metric_ref metric_ref; }; -static int test__parsing_callback(const struct pmu_event *pe, const struct pmu_events_table *table, +static int test__parsing_callback(const struct pmu_metric *pm, + const struct pmu_metrics_table *table, void *data) { int *failures = data; @@ -854,10 +829,10 @@ static int test__parsing_callback(const struct pmu_event *pe, const struct pmu_e }; int err = 0; - if (!pe->metric_expr) + if (!pm->metric_expr) return 0; - pr_debug("Found metric '%s'\n", pe->metric_name); + pr_debug("Found metric '%s'\n", pm->metric_name); (*failures)++; /* @@ -877,14 +852,14 @@ static int test__parsing_callback(const struct pmu_event *pe, const struct pmu_e perf_evlist__set_maps(&evlist->core, cpus, NULL); runtime_stat__init(&st); - err = metricgroup__parse_groups_test(evlist, table, pe->metric_name, + err = metricgroup__parse_groups_test(evlist, table, pm->metric_name, false, false, &metric_events); if (err) { - if (!strcmp(pe->metric_name, "M1") || !strcmp(pe->metric_name, "M2") || - !strcmp(pe->metric_name, "M3")) { + if (!strcmp(pm->metric_name, "M1") || !strcmp(pm->metric_name, "M2") || + !strcmp(pm->metric_name, "M3")) { (*failures)--; - pr_debug("Expected broken metric %s skipping\n", pe->metric_name); + pr_debug("Expected broken metric %s skipping\n", pm->metric_name); err = 0; } goto out_err; @@ -912,7 +887,7 @@ static int test__parsing_callback(const struct pmu_event *pe, const struct pmu_e struct metric_expr *mexp; list_for_each_entry (mexp, &me->head, nd) { - if (strcmp(mexp->metric_name, pe->metric_name)) + if (strcmp(mexp->metric_name, pm->metric_name)) continue; pr_debug("Result %f\n", test_generic_metric(mexp, 0, &st)); err = 0; @@ -921,11 +896,11 @@ static int test__parsing_callback(const struct pmu_event *pe, const struct pmu_e } } } - pr_debug("Didn't find parsed metric %s", pe->metric_name); + pr_debug("Didn't find parsed metric %s", pm->metric_name); err = 1; out_err: if (err) - pr_debug("Broken metric %s\n", pe->metric_name); + pr_debug("Broken metric %s\n", pm->metric_name); /* ... cleanup. */ metricgroup__rblist_exit(&metric_events); @@ -941,8 +916,8 @@ static int test__parsing(struct test_suite *test __maybe_unused, { int failures = 0; - pmu_for_each_core_event(test__parsing_callback, &failures); - pmu_for_each_sys_event(test__parsing_callback, &failures); + pmu_for_each_core_metric(test__parsing_callback, &failures); + pmu_for_each_sys_metric(test__parsing_callback, &failures); return failures == 0 ? TEST_OK : TEST_FAIL; } @@ -975,6 +950,7 @@ static int metric_parse_fake(const char *metric_name, const char *str) pr_debug("expr__ctx_new failed"); return TEST_FAIL; } + ctx->sctx.is_test = true; if (expr__find_ids(str, NULL, ctx) < 0) { pr_err("expr__find_ids failed\n"); return -1; @@ -1021,14 +997,11 @@ out: return ret; } -static int test__parsing_fake_callback(const struct pmu_event *pe, - const struct pmu_events_table *table __maybe_unused, +static int test__parsing_fake_callback(const struct pmu_metric *pm, + const struct pmu_metrics_table *table __maybe_unused, void *data __maybe_unused) { - if (!pe->metric_expr) - return 0; - - return metric_parse_fake(pe->metric_name, pe->metric_expr); + return metric_parse_fake(pm->metric_name, pm->metric_expr); } /* @@ -1047,11 +1020,11 @@ static int test__parsing_fake(struct test_suite *test __maybe_unused, return err; } - err = pmu_for_each_core_event(test__parsing_fake_callback, NULL); + err = pmu_for_each_core_metric(test__parsing_fake_callback, NULL); if (err) return err; - return pmu_for_each_sys_event(test__parsing_fake_callback, NULL); + return pmu_for_each_sys_metric(test__parsing_fake_callback, NULL); } static struct test_case pmu_events_tests[] = { diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index 927c7f0cc4cc..25a3f6cece50 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -37,7 +37,7 @@ * in branch_stack variable. */ #define BS_EXPECTED_BE 0xa000d00000000000 -#define BS_EXPECTED_LE 0xd5000000 +#define BS_EXPECTED_LE 0x1aa00000000 #define FLAG(s) s->branch_stack->entries[i].flags static bool samples_same(const struct perf_sample *s1, diff --git a/tools/perf/tests/shell/buildid.sh b/tools/perf/tests/shell/buildid.sh index f05670d1e39e..0ce22ea0a7f1 100755 --- a/tools/perf/tests/shell/buildid.sh +++ b/tools/perf/tests/shell/buildid.sh @@ -66,7 +66,9 @@ check() esac echo "build id: ${id}" - link=${build_id_dir}/.build-id/${id:0:2}/${id:2} + id_file=${id#??} + id_dir=${id%$id_file} + link=$build_id_dir/.build-id/$id_dir/$id_file echo "link: ${link}" if [ ! -h $link ]; then @@ -74,10 +76,23 @@ check() exit 1 fi - file=${build_id_dir}/.build-id/${id:0:2}/`readlink ${link}`/elf + file=${build_id_dir}/.build-id/$id_dir/`readlink ${link}`/elf echo "file: ${file}" - if [ ! -x $file ]; then + # Check for file permission of original file + # in case of pe-file.exe file + echo $1 | grep ".exe" + if [ $? -eq 0 ]; then + if [ -x $1 -a ! -x $file ]; then + echo "failed: file ${file} executable does not exist" + exit 1 + fi + + if [ ! -x $file -a ! -e $file ]; then + echo "failed: file ${file} does not exist" + exit 1 + fi + elif [ ! -x $file ]; then echo "failed: file ${file} does not exist" exit 1 fi @@ -117,20 +132,22 @@ test_record() { data=$(mktemp /tmp/perf.data.XXX) build_id_dir=$(mktemp -d /tmp/perf.debug.XXX) - log=$(mktemp /tmp/perf.log.XXX) + log_out=$(mktemp /tmp/perf.log.out.XXX) + log_err=$(mktemp /tmp/perf.log.err.XXX) perf="perf --buildid-dir ${build_id_dir}" echo "running: perf record $@" - ${perf} record --buildid-all -o ${data} $@ &> ${log} + ${perf} record --buildid-all -o ${data} $@ 1>${log_out} 2>${log_err} if [ $? -ne 0 ]; then echo "failed: record $@" - echo "see log: ${log}" + echo "see log: ${log_err}" exit 1 fi - check ${@: -1} + args="$*" + check ${args##* } - rm -f ${log} + rm -f ${log_out} ${log_err} rm -rf ${build_id_dir} rm -rf ${data} } diff --git a/tools/perf/tests/shell/lib/coresight.sh b/tools/perf/tests/shell/lib/coresight.sh index 45a1477256b6..6c3d34ec64d8 100644 --- a/tools/perf/tests/shell/lib/coresight.sh +++ b/tools/perf/tests/shell/lib/coresight.sh @@ -58,9 +58,9 @@ perf_dump_aux_verify() { # compiler may produce different code depending on the compiler and # optimization options, so this is rough just to see if we're # either missing almost all the data or all of it - ATOM_FX_NUM=`grep I_ATOM_F "$DUMP" | wc -l` - ASYNC_NUM=`grep I_ASYNC "$DUMP" | wc -l` - TRACE_INFO_NUM=`grep I_TRACE_INFO "$DUMP" | wc -l` + ATOM_FX_NUM=$(grep -c I_ATOM_F "$DUMP") + ASYNC_NUM=$(grep -c I_ASYNC "$DUMP") + TRACE_INFO_NUM=$(grep -c I_TRACE_INFO "$DUMP") rm -f "$DUMP" # Arguments provide minimums for a pass @@ -96,18 +96,18 @@ perf_dump_aux_tid_verify() { # The TID test tools will print a TID per stdout line that are being # tested - TIDS=`cat "$2"` + TIDS=$(cat "$2") # Scan the perf report to find the TIDs that are actually CID in hex # and build a list of the ones found - FOUND_TIDS=`perf report --stdio --dump -i "$1" | \ + FOUND_TIDS=$(perf report --stdio --dump -i "$1" | \ grep -o "CID=0x[0-9a-z]\+" | sed 's/CID=//g' | \ - uniq | sort | uniq` + uniq | sort | uniq) # No CID=xxx found - maybe your kernel is reporting these as # VMID=xxx so look there if test -z "$FOUND_TIDS"; then - FOUND_TIDS=`perf report --stdio --dump -i "$1" | \ + FOUND_TIDS=$(perf report --stdio --dump -i "$1" | \ grep -o "VMID=0x[0-9a-z]\+" | sed 's/VMID=//g' | \ - uniq | sort | uniq` + uniq | sort | uniq) fi # Iterate over the list of TIDs that the test says it has and find @@ -116,7 +116,7 @@ perf_dump_aux_tid_verify() { for TID2 in $TIDS; do FOUND="" for TIDHEX in $FOUND_TIDS; do - TID=`printf "%i" $TIDHEX` + TID=$(printf "%i" $TIDHEX) if test "$TID" -eq "$TID2"; then FOUND="y" break diff --git a/tools/perf/tests/shell/lib/probe_vfs_getname.sh b/tools/perf/tests/shell/lib/probe_vfs_getname.sh index ed0a3972c4c8..60c5e34f90c4 100644 --- a/tools/perf/tests/shell/lib/probe_vfs_getname.sh +++ b/tools/perf/tests/shell/lib/probe_vfs_getname.sh @@ -22,3 +22,11 @@ skip_if_no_debuginfo() { add_probe_vfs_getname -v 2>&1 | grep -E -q "^(Failed to find the path for the kernel|Debuginfo-analysis is not supported)|(file has no debug information)" && return 2 return 1 } + +# check if perf is compiled with libtraceevent support +skip_no_probe_record_support() { + if [ $had_vfs_getname -eq 1 ] ; then + perf record --dry-run -e $1 2>&1 | grep "libtraceevent is necessary for tracepoint support" && return 2 + return 1 + fi +} diff --git a/tools/perf/tests/shell/lock_contention.sh b/tools/perf/tests/shell/lock_contention.sh index b05f1b1ca6c8..be5fcafb26aa 100755 --- a/tools/perf/tests/shell/lock_contention.sh +++ b/tools/perf/tests/shell/lock_contention.sh @@ -128,7 +128,7 @@ test_type_filter() echo "Testing perf lock contention --type-filter (w/ spinlock)" perf lock contention -i ${perfdata} -Y spinlock -q 2> ${result} if [ $(grep -c -v spinlock "${result}") != "0" ]; then - echo "[Fail] Recorded should not have non-spinlocks:" $(cat "${result}") + echo "[Fail] Recorded result should not have non-spinlocks:" $(cat "${result}") err=1 exit fi @@ -139,7 +139,7 @@ test_type_filter() perf lock con -a -b -Y spinlock -q -- perf bench sched messaging > /dev/null 2> ${result} if [ $(grep -c -v spinlock "${result}") != "0" ]; then - echo "[Fail] Recorded should not have non-spinlocks:" $(cat "${result}") + echo "[Fail] BPF result should not have non-spinlocks:" $(cat "${result}") err=1 exit fi @@ -160,7 +160,7 @@ test_lock_filter() local type=$(head -1 "${result}" | awk '{ print $8 }' | sed -e 's/:.*//') if [ $(grep -c -v "${type}" "${result}") != "0" ]; then - echo "[Fail] Recorded should not have non-${type} locks:" $(cat "${result}") + echo "[Fail] Recorded result should not have non-${type} locks:" $(cat "${result}") err=1 exit fi @@ -171,7 +171,63 @@ test_lock_filter() perf lock con -a -b -L tasklist_lock -q -- perf bench sched messaging > /dev/null 2> ${result} if [ $(grep -c -v "${type}" "${result}") != "0" ]; then - echo "[Fail] Recorded should not have non-${type} locks:" $(cat "${result}") + echo "[Fail] BPF result should not have non-${type} locks:" $(cat "${result}") + err=1 + exit + fi +} + +test_stack_filter() +{ + echo "Testing perf lock contention --callstack-filter (w/ unix_stream)" + perf lock contention -i ${perfdata} -v -q 2> ${result} + if [ $(grep -c unix_stream "${result}") == "0" ]; then + echo "[Skip] Could not find 'unix_stream'" + return + fi + + perf lock contention -i ${perfdata} -E 1 -S unix_stream -q 2> ${result} + if [ $(cat "${result}" | wc -l) != "1" ]; then + echo "[Fail] Recorded result should have a lock from unix_stream:" $(cat "${result}") + err=1 + exit + fi + + if ! perf lock con -b true > /dev/null 2>&1 ; then + return + fi + + perf lock con -a -b -S unix_stream -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result} + if [ $(cat "${result}" | wc -l) != "1" ]; then + echo "[Fail] BPF result should have a lock from unix_stream:" $(cat "${result}") + err=1 + exit + fi +} + +test_aggr_task_stack_filter() +{ + echo "Testing perf lock contention --callstack-filter with task aggregation" + perf lock contention -i ${perfdata} -v -q 2> ${result} + if [ $(grep -c unix_stream "${result}") == "0" ]; then + echo "[Skip] Could not find 'unix_stream'" + return + fi + + perf lock contention -i ${perfdata} -t -E 1 -S unix_stream -q 2> ${result} + if [ $(cat "${result}" | wc -l) != "1" ]; then + echo "[Fail] Recorded result should have a task from unix_stream:" $(cat "${result}") + err=1 + exit + fi + + if ! perf lock con -b true > /dev/null 2>&1 ; then + return + fi + + perf lock con -a -b -t -S unix_stream -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result} + if [ $(cat "${result}" | wc -l) != "1" ]; then + echo "[Fail] BPF result should have a task from unix_stream:" $(cat "${result}") err=1 exit fi @@ -186,5 +242,7 @@ test_aggr_task test_aggr_addr test_type_filter test_lock_filter +test_stack_filter +test_aggr_task_stack_filter exit ${err} 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 34c400ccbe04..b4149b2db4c6 100755 --- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh +++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh @@ -11,6 +11,7 @@ # Arnaldo Carvalho de Melo <acme@kernel.org>, 2017 . $(dirname $0)/lib/probe.sh +. $(dirname $0)/lib/probe_vfs_getname.sh libc=$(grep -w libc /proc/self/maps | head -1 | sed -r 's/.*[[:space:]](\/.*)/\1/g') nm -Dg $libc 2>/dev/null | fgrep -q inet_pton || exit 254 @@ -37,6 +38,7 @@ trace_libc_inet_pton_backtrace() { case "$(uname -m)" in s390x) eventattr='call-graph=dwarf,max-stack=4' + echo "text_to_binary_address.*\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected echo "gaih_inet.*\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected echo "(__GI_)?getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$" >> $expected echo "main\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$" >> $expected @@ -56,8 +58,18 @@ trace_libc_inet_pton_backtrace() { perf_data=`mktemp -u /tmp/perf.data.XXX` perf_script=`mktemp -u /tmp/perf.script.XXX` + + # Check presence of libtraceevent support to run perf record + skip_no_probe_record_support "$event_name/$eventattr/" + [ $? -eq 2 ] && return 2 + perf record -e $event_name/$eventattr/ -o $perf_data ping -6 -c 1 ::1 > /dev/null 2>&1 - perf script -i $perf_data > $perf_script + # check if perf data file got created in above step. + if [ ! -e $perf_data ]; then + printf "FAIL: perf record failed to create \"%s\" \n" "$perf_data" + return 1 + fi + perf script -i $perf_data | tac | grep -m1 ^ping -B9 | tac > $perf_script exec 3<$perf_script exec 4<$expected 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 7f83b2715b9a..1341437e1bd9 100755 --- a/tools/perf/tests/shell/record+script_probe_vfs_getname.sh +++ b/tools/perf/tests/shell/record+script_probe_vfs_getname.sh @@ -17,6 +17,9 @@ skip_if_no_perf_probe || exit 2 record_open_file() { echo "Recording open file:" + # Check presence of libtraceevent support to run perf record + skip_no_probe_record_support "probe:vfs_getname*" + [ $? -eq 2 ] && return 2 perf record -o ${perfdata} -e probe:vfs_getname\* touch $file } diff --git a/tools/perf/tests/shell/stat_all_metrics.sh b/tools/perf/tests/shell/stat_all_metrics.sh index 6e79349e42be..22e9cb294b40 100755 --- a/tools/perf/tests/shell/stat_all_metrics.sh +++ b/tools/perf/tests/shell/stat_all_metrics.sh @@ -11,7 +11,7 @@ for m in $(perf list --raw-dump metrics); do continue fi # Failed so try system wide. - result=$(perf stat -M "$m" -a true 2>&1) + result=$(perf stat -M "$m" -a sleep 0.01 2>&1) if [[ "$result" =~ "${m:0:50}" ]] then continue diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh index 59195eb80052..1c49d8293003 100755 --- a/tools/perf/tests/shell/test_brstack.sh +++ b/tools/perf/tests/shell/test_brstack.sh @@ -30,14 +30,14 @@ test_user_branches() { # brstack_foo+0x14/brstack_bar+0x40/P/-/-/0/CALL set -x - grep -E -m1 "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/IND_CALL$" $TMPDIR/perf.script - grep -E -m1 "^brstack_foo\+[^ ]*/brstack_bar\+[^ ]*/CALL$" $TMPDIR/perf.script - grep -E -m1 "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/CALL$" $TMPDIR/perf.script - grep -E -m1 "^brstack_bench\+[^ ]*/brstack_bar\+[^ ]*/CALL$" $TMPDIR/perf.script - grep -E -m1 "^brstack_bar\+[^ ]*/brstack_foo\+[^ ]*/RET$" $TMPDIR/perf.script - grep -E -m1 "^brstack_foo\+[^ ]*/brstack_bench\+[^ ]*/RET$" $TMPDIR/perf.script - grep -E -m1 "^brstack_bench\+[^ ]*/brstack_bench\+[^ ]*/COND$" $TMPDIR/perf.script - grep -E -m1 "^brstack\+[^ ]*/brstack\+[^ ]*/UNCOND$" $TMPDIR/perf.script + grep -E -m1 "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/IND_CALL/.*$" $TMPDIR/perf.script + grep -E -m1 "^brstack_foo\+[^ ]*/brstack_bar\+[^ ]*/CALL/.*$" $TMPDIR/perf.script + grep -E -m1 "^brstack_bench\+[^ ]*/brstack_foo\+[^ ]*/CALL/.*$" $TMPDIR/perf.script + grep -E -m1 "^brstack_bench\+[^ ]*/brstack_bar\+[^ ]*/CALL/.*$" $TMPDIR/perf.script + grep -E -m1 "^brstack_bar\+[^ ]*/brstack_foo\+[^ ]*/RET/.*$" $TMPDIR/perf.script + grep -E -m1 "^brstack_foo\+[^ ]*/brstack_bench\+[^ ]*/RET/.*$" $TMPDIR/perf.script + grep -E -m1 "^brstack_bench\+[^ ]*/brstack_bench\+[^ ]*/COND/.*$" $TMPDIR/perf.script + grep -E -m1 "^brstack\+[^ ]*/brstack\+[^ ]*/UNCOND/.*$" $TMPDIR/perf.script set +x # some branch types are still not being tested: @@ -57,7 +57,7 @@ test_filter() { # fail if we find any branch type that doesn't match any of the expected ones # also consider UNKNOWN branch types (-) - if grep -E -vm1 "^[^ ]*/($expect|-|( *))$" $TMPDIR/perf.script; then + if grep -E -vm1 "^[^ ]*/($expect|-|( *))/.*$" $TMPDIR/perf.script; then return 1 fi } diff --git a/tools/perf/tests/shell/test_intel_pt.sh b/tools/perf/tests/shell/test_intel_pt.sh index f5ed7b1af419..4ddb17cb83c5 100755 --- a/tools/perf/tests/shell/test_intel_pt.sh +++ b/tools/perf/tests/shell/test_intel_pt.sh @@ -620,6 +620,22 @@ test_event_trace() return 0 } +test_pipe() +{ + echo "--- Test with pipe mode ---" + # Check if it works with pipe + if ! perf_record_no_bpf -o- -e intel_pt//u uname | perf report -q -i- --itrace=i10000 ; then + echo "perf record + report failed with pipe mode" + return 1 + fi + if ! perf_record_no_bpf -o- -e intel_pt//u uname | perf inject -b > /dev/null ; then + echo "perf record + inject failed with pipe mode" + return 1 + fi + echo OK + return 0 +} + count_result() { if [ "$1" -eq 2 ] ; then @@ -647,6 +663,7 @@ test_virtual_lbr || ret=$? ; count_result $ret ; ret=0 test_power_event || ret=$? ; count_result $ret ; ret=0 test_no_tnt || ret=$? ; count_result $ret ; ret=0 test_event_trace || ret=$? ; count_result $ret ; ret=0 +test_pipe || ret=$? ; count_result $ret ; ret=0 cleanup diff --git a/tools/perf/tests/symbols.c b/tools/perf/tests/symbols.c new file mode 100644 index 000000000000..057b16df6416 --- /dev/null +++ b/tools/perf/tests/symbols.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/compiler.h> +#include <linux/string.h> +#include <sys/mman.h> +#include <limits.h> +#include "debug.h" +#include "dso.h" +#include "machine.h" +#include "thread.h" +#include "symbol.h" +#include "map.h" +#include "util.h" +#include "tests.h" + +struct test_info { + struct machine *machine; + struct thread *thread; +}; + +static int init_test_info(struct test_info *ti) +{ + ti->machine = machine__new_host(); + if (!ti->machine) { + pr_debug("machine__new_host() failed!\n"); + return TEST_FAIL; + } + + /* Create a dummy thread */ + ti->thread = machine__findnew_thread(ti->machine, 100, 100); + if (!ti->thread) { + pr_debug("machine__findnew_thread() failed!\n"); + return TEST_FAIL; + } + + return TEST_OK; +} + +static void exit_test_info(struct test_info *ti) +{ + thread__put(ti->thread); + machine__delete(ti->machine); +} + +static void get_test_dso_filename(char *filename, size_t max_sz) +{ + if (dso_to_test) + strlcpy(filename, dso_to_test, max_sz); + else + perf_exe(filename, max_sz); +} + +static int create_map(struct test_info *ti, char *filename, struct map **map_p) +{ + /* Create a dummy map at 0x100000 */ + *map_p = map__new(ti->machine, 0x100000, 0xffffffff, 0, NULL, + PROT_EXEC, 0, NULL, filename, ti->thread); + if (!*map_p) { + pr_debug("Failed to create map!"); + return TEST_FAIL; + } + + return TEST_OK; +} + +static int test_dso(struct dso *dso) +{ + struct symbol *last_sym = NULL; + struct rb_node *nd; + int ret = TEST_OK; + + /* dso__fprintf() prints all the symbols */ + if (verbose > 1) + dso__fprintf(dso, stderr); + + for (nd = rb_first_cached(&dso->symbols); nd; nd = rb_next(nd)) { + struct symbol *sym = rb_entry(nd, struct symbol, rb_node); + + if (sym->type != STT_FUNC && sym->type != STT_GNU_IFUNC) + continue; + + /* Check for overlapping function symbols */ + if (last_sym && sym->start < last_sym->end) { + pr_debug("Overlapping symbols:\n"); + symbol__fprintf(last_sym, stderr); + symbol__fprintf(sym, stderr); + ret = TEST_FAIL; + } + /* Check for zero-length function symbol */ + if (sym->start == sym->end) { + pr_debug("Zero-length symbol:\n"); + symbol__fprintf(sym, stderr); + ret = TEST_FAIL; + } + last_sym = sym; + } + + return ret; +} + +static int test_file(struct test_info *ti, char *filename) +{ + struct map *map = NULL; + int ret, nr; + + pr_debug("Testing %s\n", filename); + + ret = create_map(ti, filename, &map); + if (ret != TEST_OK) + return ret; + + nr = dso__load(map->dso, map); + if (nr < 0) { + pr_debug("dso__load() failed!\n"); + ret = TEST_FAIL; + goto out_put; + } + + if (nr == 0) { + pr_debug("DSO has no symbols!\n"); + ret = TEST_SKIP; + goto out_put; + } + + ret = test_dso(map->dso); +out_put: + map__put(map); + + return ret; +} + +static int test__symbols(struct test_suite *test __maybe_unused, int subtest __maybe_unused) +{ + char filename[PATH_MAX]; + struct test_info ti; + int ret; + + ret = init_test_info(&ti); + if (ret != TEST_OK) + return ret; + + get_test_dso_filename(filename, sizeof(filename)); + + ret = test_file(&ti, filename); + + exit_test_info(&ti); + + return ret; +} + +DEFINE_SUITE("Symbols", symbols); diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index fb4b5ad4dd0f..9a0f3904e53d 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -148,6 +148,7 @@ DECLARE_SUITE(perf_time_to_tsc); DECLARE_SUITE(dlfilter); DECLARE_SUITE(sigtrap); DECLARE_SUITE(event_groups); +DECLARE_SUITE(symbols); /* * PowerPC and S390 do not support creation of instruction breakpoints using the @@ -208,4 +209,6 @@ DECLARE_WORKLOAD(sqrtloop); DECLARE_WORKLOAD(brstack); DECLARE_WORKLOAD(datasym); +extern const char *dso_to_test; + #endif /* TESTS_H */ diff --git a/tools/perf/tests/workloads/thloop.c b/tools/perf/tests/workloads/thloop.c index 29193b75717e..af05269c2eb8 100644 --- a/tools/perf/tests/workloads/thloop.c +++ b/tools/perf/tests/workloads/thloop.c @@ -20,7 +20,7 @@ static void sighandler(int sig __maybe_unused) noinline void test_loop(void) { while (!done) - count++; + __atomic_fetch_add(&count, 1, __ATOMIC_RELAXED); } static void *thfunc(void *arg) |