diff options
Diffstat (limited to 'tools/perf/tests/pmu.c')
-rw-r--r-- | tools/perf/tests/pmu.c | 199 |
1 files changed, 196 insertions, 3 deletions
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c index 06cc0e46cb28..40132655ccd1 100644 --- a/tools/perf/tests/pmu.c +++ b/tools/perf/tests/pmu.c @@ -3,6 +3,7 @@ #include "evsel.h" #include "parse-events.h" #include "pmu.h" +#include "pmus.h" #include "tests.h" #include "debug.h" #include "fncache.h" @@ -259,26 +260,42 @@ err_out: static bool permitted_event_name(const char *name) { bool has_lower = false, has_upper = false; + __u64 config; for (size_t i = 0; i < strlen(name); i++) { char c = name[i]; if (islower(c)) { if (has_upper) - return false; + goto check_legacy; has_lower = true; continue; } if (isupper(c)) { if (has_lower) - return false; + goto check_legacy; has_upper = true; continue; } if (!isdigit(c) && c != '.' && c != '_' && c != '-') - return false; + goto check_legacy; } return true; +check_legacy: + /* + * If the event name matches a legacy cache name the legacy encoding + * will still be used. This isn't quite WAI as sysfs events should take + * priority, but this case happens on PowerPC and matches the behavior + * in older perf tools where legacy events were the priority. Be + * permissive and assume later PMU drivers will use all lower or upper + * case names. + */ + if (parse_events__decode_legacy_cache(name, /*extended_pmu_type=*/0, &config) == 0) { + pr_warning("sysfs event '%s' should be all lower/upper case, it will be matched using legacy encoding.", + name); + return true; + } + return false; } static int test__pmu_event_names(struct test_suite *test __maybe_unused, @@ -340,10 +357,186 @@ static int test__pmu_event_names(struct test_suite *test __maybe_unused, return ret; } +static const char * const uncore_chas[] = { + "uncore_cha_0", + "uncore_cha_1", + "uncore_cha_2", + "uncore_cha_3", + "uncore_cha_4", + "uncore_cha_5", + "uncore_cha_6", + "uncore_cha_7", + "uncore_cha_8", + "uncore_cha_9", + "uncore_cha_10", + "uncore_cha_11", + "uncore_cha_12", + "uncore_cha_13", + "uncore_cha_14", + "uncore_cha_15", + "uncore_cha_16", + "uncore_cha_17", + "uncore_cha_18", + "uncore_cha_19", + "uncore_cha_20", + "uncore_cha_21", + "uncore_cha_22", + "uncore_cha_23", + "uncore_cha_24", + "uncore_cha_25", + "uncore_cha_26", + "uncore_cha_27", + "uncore_cha_28", + "uncore_cha_29", + "uncore_cha_30", + "uncore_cha_31", +}; + +static const char * const mrvl_ddrs[] = { + "mrvl_ddr_pmu_87e1b0000000", + "mrvl_ddr_pmu_87e1b1000000", + "mrvl_ddr_pmu_87e1b2000000", + "mrvl_ddr_pmu_87e1b3000000", + "mrvl_ddr_pmu_87e1b4000000", + "mrvl_ddr_pmu_87e1b5000000", + "mrvl_ddr_pmu_87e1b6000000", + "mrvl_ddr_pmu_87e1b7000000", + "mrvl_ddr_pmu_87e1b8000000", + "mrvl_ddr_pmu_87e1b9000000", + "mrvl_ddr_pmu_87e1ba000000", + "mrvl_ddr_pmu_87e1bb000000", + "mrvl_ddr_pmu_87e1bc000000", + "mrvl_ddr_pmu_87e1bd000000", + "mrvl_ddr_pmu_87e1be000000", + "mrvl_ddr_pmu_87e1bf000000", +}; + +static int test__name_len(struct test_suite *test __maybe_unused, int subtest __maybe_unused) +{ + TEST_ASSERT_VAL("cpu", pmu_name_len_no_suffix("cpu") == strlen("cpu")); + TEST_ASSERT_VAL("i915", pmu_name_len_no_suffix("i915") == strlen("i915")); + TEST_ASSERT_VAL("cpum_cf", pmu_name_len_no_suffix("cpum_cf") == strlen("cpum_cf")); + for (size_t i = 0; i < ARRAY_SIZE(uncore_chas); i++) { + TEST_ASSERT_VAL("Strips uncore_cha suffix", + pmu_name_len_no_suffix(uncore_chas[i]) == + strlen("uncore_cha")); + } + for (size_t i = 0; i < ARRAY_SIZE(mrvl_ddrs); i++) { + TEST_ASSERT_VAL("Strips mrvl_ddr_pmu suffix", + pmu_name_len_no_suffix(mrvl_ddrs[i]) == + strlen("mrvl_ddr_pmu")); + } + return TEST_OK; +} + +static int test__name_cmp(struct test_suite *test __maybe_unused, int subtest __maybe_unused) +{ + TEST_ASSERT_EQUAL("cpu", pmu_name_cmp("cpu", "cpu"), 0); + TEST_ASSERT_EQUAL("i915", pmu_name_cmp("i915", "i915"), 0); + TEST_ASSERT_EQUAL("cpum_cf", pmu_name_cmp("cpum_cf", "cpum_cf"), 0); + TEST_ASSERT_VAL("i915", pmu_name_cmp("cpu", "i915") < 0); + TEST_ASSERT_VAL("i915", pmu_name_cmp("i915", "cpu") > 0); + TEST_ASSERT_VAL("cpum_cf", pmu_name_cmp("cpum_cf", "cpum_ce") > 0); + TEST_ASSERT_VAL("cpum_cf", pmu_name_cmp("cpum_cf", "cpum_d0") < 0); + for (size_t i = 1; i < ARRAY_SIZE(uncore_chas); i++) { + TEST_ASSERT_VAL("uncore_cha suffixes ordered lt", + pmu_name_cmp(uncore_chas[i-1], uncore_chas[i]) < 0); + TEST_ASSERT_VAL("uncore_cha suffixes ordered gt", + pmu_name_cmp(uncore_chas[i], uncore_chas[i-1]) > 0); + } + for (size_t i = 1; i < ARRAY_SIZE(mrvl_ddrs); i++) { + TEST_ASSERT_VAL("mrvl_ddr_pmu suffixes ordered lt", + pmu_name_cmp(mrvl_ddrs[i-1], mrvl_ddrs[i]) < 0); + TEST_ASSERT_VAL("mrvl_ddr_pmu suffixes ordered gt", + pmu_name_cmp(mrvl_ddrs[i], mrvl_ddrs[i-1]) > 0); + } + return TEST_OK; +} + +/** + * Test perf_pmu__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. + */ +static int test__pmu_match(struct test_suite *test __maybe_unused, int subtest __maybe_unused) +{ + struct perf_pmu test_pmu; + + test_pmu.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); + + 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.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.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.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); + + /* + * 2 hex chars or less are not considered suffixes so it shouldn't be + * possible to wildcard by skipping the suffix. Therefore there are more + * 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); + /* + * 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 + * a normal decimal suffix following text. And we want to match on any + * 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.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); + + return TEST_OK; +} + static struct test_case tests__pmu[] = { TEST_CASE("Parsing with PMU format directory", pmu_format), TEST_CASE("Parsing with PMU event", pmu_events), TEST_CASE("PMU event names", pmu_event_names), + TEST_CASE("PMU name combining", name_len), + TEST_CASE("PMU name comparison", name_cmp), + TEST_CASE("PMU cmdline match", pmu_match), { .name = NULL, } }; |