1 // SPDX-License-Identifier: GPL-2.0
4 #include "parse-events.h"
10 #include <api/fs/fs.h>
19 #include <sys/types.h>
21 /* Cleanup test PMU directory. */
22 static int test_pmu_put(const char *dir
, struct perf_pmu
*pmu
)
24 char buf
[PATH_MAX
+ 20];
27 if (scnprintf(buf
, sizeof(buf
), "rm -fr %s", dir
) < 0) {
28 pr_err("Failure to set up buffer for \"%s\"\n", dir
);
33 pr_err("Failure to \"%s\"\n", buf
);
36 perf_pmu__delete(pmu
);
41 * Prepare test PMU directory data, normally exported by kernel at
42 * /sys/bus/event_source/devices/<pmu>/. Give as input a buffer to hold the file
43 * path, the result is PMU loaded using that directory.
45 static struct perf_pmu
*test_pmu_get(char *dir
, size_t sz
)
47 /* Simulated format definitions. */
48 const struct test_format
{
52 { "krava01", "config:0-1,62-63\n", },
53 { "krava02", "config:10-17\n", },
54 { "krava03", "config:5\n", },
55 { "krava11", "config1:0,2,4,6,8,20-28\n", },
56 { "krava12", "config1:63\n", },
57 { "krava13", "config1:45-47\n", },
58 { "krava21", "config2:0-3,10-13,20-23,30-33,40-43,50-53,60-63\n", },
59 { "krava22", "config2:8,18,48,58\n", },
60 { "krava23", "config2:28-29,38\n", },
62 const char *test_event
= "krava01=15,krava02=170,krava03=1,krava11=27,krava12=1,"
63 "krava13=2,krava21=119,krava22=11,krava23=2\n";
67 struct perf_pmu
*pmu
= NULL
;
70 /* Create equivalent of sysfs mount point. */
71 scnprintf(dir
, sz
, "/tmp/perf-pmu-test-XXXXXX");
73 pr_err("mkdtemp failed\n");
77 dirfd
= open(dir
, O_DIRECTORY
);
79 pr_err("Failed to open test directory \"%s\"\n", dir
);
83 /* Create the test PMU directory and give it a perf_event_attr type number. */
84 if (mkdirat(dirfd
, "perf-pmu-test", 0755) < 0) {
85 pr_err("Failed to mkdir PMU directory\n");
88 file
= openat(dirfd
, "perf-pmu-test/type", O_WRONLY
| O_CREAT
, 0600);
90 pr_err("Failed to open for writing file \"type\"\n");
94 if (write(file
, "9999\n", len
) < len
) {
96 pr_err("Failed to write to 'type' file\n");
101 /* Create format directory and files. */
102 if (mkdirat(dirfd
, "perf-pmu-test/format", 0755) < 0) {
103 pr_err("Failed to mkdir PMU format directory\n)");
106 for (size_t i
= 0; i
< ARRAY_SIZE(test_formats
); i
++) {
107 const struct test_format
*format
= &test_formats
[i
];
109 if (scnprintf(name
, PATH_MAX
, "perf-pmu-test/format/%s", format
->name
) < 0) {
110 pr_err("Failure to set up path for \"%s\"\n", format
->name
);
113 file
= openat(dirfd
, name
, O_WRONLY
| O_CREAT
, 0600);
115 pr_err("Failed to open for writing file \"%s\"\n", name
);
119 if (write(file
, format
->value
, strlen(format
->value
)) < 0) {
120 pr_err("Failed to write to file \"%s\"\n", name
);
127 /* Create test event. */
128 if (mkdirat(dirfd
, "perf-pmu-test/events", 0755) < 0) {
129 pr_err("Failed to mkdir PMU events directory\n");
132 file
= openat(dirfd
, "perf-pmu-test/events/test-event", O_WRONLY
| O_CREAT
, 0600);
134 pr_err("Failed to open for writing file \"type\"\n");
137 len
= strlen(test_event
);
138 if (write(file
, test_event
, len
) < len
) {
140 pr_err("Failed to write to 'test-event' file\n");
145 /* Make the PMU reading the files created above. */
146 pmu
= perf_pmus__add_test_pmu(dirfd
, "perf-pmu-test");
148 pr_err("Test PMU creation failed\n");
152 test_pmu_put(dir
, pmu
);
158 static int test__pmu_format(struct test_suite
*test __maybe_unused
, int subtest __maybe_unused
)
161 struct perf_event_attr attr
;
162 struct parse_events_terms terms
;
164 struct perf_pmu
*pmu
= test_pmu_get(dir
, sizeof(dir
));
169 parse_events_terms__init(&terms
);
170 if (parse_events_terms(&terms
,
171 "krava01=15,krava02=170,krava03=1,krava11=27,krava12=1,"
172 "krava13=2,krava21=119,krava22=11,krava23=2",
174 pr_err("Term parsing failed\n");
178 memset(&attr
, 0, sizeof(attr
));
179 ret
= perf_pmu__config_terms(pmu
, &attr
, &terms
, /*zero=*/false,
180 /*apply_hardcoded=*/false, /*err=*/NULL
);
182 pr_err("perf_pmu__config_terms failed");
186 if (attr
.config
!= 0xc00000000002a823) {
187 pr_err("Unexpected config value %llx\n", attr
.config
);
190 if (attr
.config1
!= 0x8000400000000145) {
191 pr_err("Unexpected config1 value %llx\n", attr
.config1
);
194 if (attr
.config2
!= 0x0400000020041d07) {
195 pr_err("Unexpected config2 value %llx\n", attr
.config2
);
201 parse_events_terms__exit(&terms
);
202 test_pmu_put(dir
, pmu
);
206 static int test__pmu_events(struct test_suite
*test __maybe_unused
, int subtest __maybe_unused
)
209 struct parse_events_error err
;
210 struct evlist
*evlist
;
212 struct perf_event_attr
*attr
;
214 struct perf_pmu
*pmu
= test_pmu_get(dir
, sizeof(dir
));
215 const char *event
= "perf-pmu-test/test-event/";
221 evlist
= evlist__new();
222 if (evlist
== NULL
) {
223 pr_err("Failed allocation");
226 parse_events_error__init(&err
);
227 ret
= parse_events(evlist
, event
, &err
);
229 pr_debug("failed to parse event '%s', err %d\n", event
, ret
);
230 parse_events_error__print(&err
, event
);
231 if (parse_events_error__contains(&err
, "can't access trace events"))
235 evsel
= evlist__first(evlist
);
236 attr
= &evsel
->core
.attr
;
237 if (attr
->config
!= 0xc00000000002a823) {
238 pr_err("Unexpected config value %llx\n", attr
->config
);
241 if (attr
->config1
!= 0x8000400000000145) {
242 pr_err("Unexpected config1 value %llx\n", attr
->config1
);
245 if (attr
->config2
!= 0x0400000020041d07) {
246 pr_err("Unexpected config2 value %llx\n", attr
->config2
);
252 parse_events_error__exit(&err
);
253 evlist__delete(evlist
);
254 test_pmu_put(dir
, pmu
);
258 static bool permitted_event_name(const char *name
)
260 bool has_lower
= false, has_upper
= false;
263 for (size_t i
= 0; i
< strlen(name
); i
++) {
278 if (!isdigit(c
) && c
!= '.' && c
!= '_' && c
!= '-')
284 * If the event name matches a legacy cache name the legacy encoding
285 * will still be used. This isn't quite WAI as sysfs events should take
286 * priority, but this case happens on PowerPC and matches the behavior
287 * in older perf tools where legacy events were the priority. Be
288 * permissive and assume later PMU drivers will use all lower or upper
291 if (parse_events__decode_legacy_cache(name
, /*extended_pmu_type=*/0, &config
) == 0) {
292 pr_warning("sysfs event '%s' should be all lower/upper case, it will be matched using legacy encoding.",
299 static int test__pmu_event_names(struct test_suite
*test __maybe_unused
,
300 int subtest __maybe_unused
)
303 DIR *pmu_dir
, *event_dir
;
304 struct dirent
*pmu_dent
, *event_dent
;
305 const char *sysfs
= sysfs__mountpoint();
309 pr_err("Sysfs not mounted\n");
313 snprintf(path
, sizeof(path
), "%s/bus/event_source/devices/", sysfs
);
314 pmu_dir
= opendir(path
);
316 pr_err("Error opening \"%s\"\n", path
);
319 while ((pmu_dent
= readdir(pmu_dir
))) {
320 if (!strcmp(pmu_dent
->d_name
, ".") ||
321 !strcmp(pmu_dent
->d_name
, ".."))
324 snprintf(path
, sizeof(path
), "%s/bus/event_source/devices/%s/type",
325 sysfs
, pmu_dent
->d_name
);
327 /* Does it look like a PMU? */
328 if (!file_available(path
))
331 /* Process events. */
332 snprintf(path
, sizeof(path
), "%s/bus/event_source/devices/%s/events",
333 sysfs
, pmu_dent
->d_name
);
335 event_dir
= opendir(path
);
337 pr_debug("Skipping as no event directory \"%s\"\n", path
);
340 while ((event_dent
= readdir(event_dir
))) {
341 const char *event_name
= event_dent
->d_name
;
343 if (!strcmp(event_name
, ".") || !strcmp(event_name
, ".."))
346 if (!permitted_event_name(event_name
)) {
347 pr_err("Invalid sysfs event name: %s/%s\n",
348 pmu_dent
->d_name
, event_name
);
358 static const char * const uncore_chas
[] = {
393 static const char * const mrvl_ddrs
[] = {
394 "mrvl_ddr_pmu_87e1b0000000",
395 "mrvl_ddr_pmu_87e1b1000000",
396 "mrvl_ddr_pmu_87e1b2000000",
397 "mrvl_ddr_pmu_87e1b3000000",
398 "mrvl_ddr_pmu_87e1b4000000",
399 "mrvl_ddr_pmu_87e1b5000000",
400 "mrvl_ddr_pmu_87e1b6000000",
401 "mrvl_ddr_pmu_87e1b7000000",
402 "mrvl_ddr_pmu_87e1b8000000",
403 "mrvl_ddr_pmu_87e1b9000000",
404 "mrvl_ddr_pmu_87e1ba000000",
405 "mrvl_ddr_pmu_87e1bb000000",
406 "mrvl_ddr_pmu_87e1bc000000",
407 "mrvl_ddr_pmu_87e1bd000000",
408 "mrvl_ddr_pmu_87e1be000000",
409 "mrvl_ddr_pmu_87e1bf000000",
412 static int test__name_len(struct test_suite
*test __maybe_unused
, int subtest __maybe_unused
)
414 TEST_ASSERT_VAL("cpu", pmu_name_len_no_suffix("cpu") == strlen("cpu"));
415 TEST_ASSERT_VAL("i915", pmu_name_len_no_suffix("i915") == strlen("i915"));
416 TEST_ASSERT_VAL("cpum_cf", pmu_name_len_no_suffix("cpum_cf") == strlen("cpum_cf"));
417 for (size_t i
= 0; i
< ARRAY_SIZE(uncore_chas
); i
++) {
418 TEST_ASSERT_VAL("Strips uncore_cha suffix",
419 pmu_name_len_no_suffix(uncore_chas
[i
]) ==
420 strlen("uncore_cha"));
422 for (size_t i
= 0; i
< ARRAY_SIZE(mrvl_ddrs
); i
++) {
423 TEST_ASSERT_VAL("Strips mrvl_ddr_pmu suffix",
424 pmu_name_len_no_suffix(mrvl_ddrs
[i
]) ==
425 strlen("mrvl_ddr_pmu"));
430 static int test__name_cmp(struct test_suite
*test __maybe_unused
, int subtest __maybe_unused
)
432 TEST_ASSERT_EQUAL("cpu", pmu_name_cmp("cpu", "cpu"), 0);
433 TEST_ASSERT_EQUAL("i915", pmu_name_cmp("i915", "i915"), 0);
434 TEST_ASSERT_EQUAL("cpum_cf", pmu_name_cmp("cpum_cf", "cpum_cf"), 0);
435 TEST_ASSERT_VAL("i915", pmu_name_cmp("cpu", "i915") < 0);
436 TEST_ASSERT_VAL("i915", pmu_name_cmp("i915", "cpu") > 0);
437 TEST_ASSERT_VAL("cpum_cf", pmu_name_cmp("cpum_cf", "cpum_ce") > 0);
438 TEST_ASSERT_VAL("cpum_cf", pmu_name_cmp("cpum_cf", "cpum_d0") < 0);
439 for (size_t i
= 1; i
< ARRAY_SIZE(uncore_chas
); i
++) {
440 TEST_ASSERT_VAL("uncore_cha suffixes ordered lt",
441 pmu_name_cmp(uncore_chas
[i
-1], uncore_chas
[i
]) < 0);
442 TEST_ASSERT_VAL("uncore_cha suffixes ordered gt",
443 pmu_name_cmp(uncore_chas
[i
], uncore_chas
[i
-1]) > 0);
445 for (size_t i
= 1; i
< ARRAY_SIZE(mrvl_ddrs
); i
++) {
446 TEST_ASSERT_VAL("mrvl_ddr_pmu suffixes ordered lt",
447 pmu_name_cmp(mrvl_ddrs
[i
-1], mrvl_ddrs
[i
]) < 0);
448 TEST_ASSERT_VAL("mrvl_ddr_pmu suffixes ordered gt",
449 pmu_name_cmp(mrvl_ddrs
[i
], mrvl_ddrs
[i
-1]) > 0);
455 * Test perf_pmu__match() that's used to search for a PMU given a name passed
456 * on the command line. The name that's passed may also be a filename type glob
457 * match. If the name does not match, perf_pmu__match() attempts to match the
458 * alias of the PMU, if provided.
460 static int test__pmu_match(struct test_suite
*test __maybe_unused
, int subtest __maybe_unused
)
462 struct perf_pmu test_pmu
= {
466 TEST_ASSERT_EQUAL("Exact match", perf_pmu__match(&test_pmu
, "pmuname"), true);
467 TEST_ASSERT_EQUAL("Longer token", perf_pmu__match(&test_pmu
, "longertoken"), false);
468 TEST_ASSERT_EQUAL("Shorter token", perf_pmu__match(&test_pmu
, "pmu"), false);
470 test_pmu
.name
= "pmuname_10";
471 TEST_ASSERT_EQUAL("Diff suffix_", perf_pmu__match(&test_pmu
, "pmuname_2"), false);
472 TEST_ASSERT_EQUAL("Sub suffix_", perf_pmu__match(&test_pmu
, "pmuname_1"), true);
473 TEST_ASSERT_EQUAL("Same suffix_", perf_pmu__match(&test_pmu
, "pmuname_10"), true);
474 TEST_ASSERT_EQUAL("No suffix_", perf_pmu__match(&test_pmu
, "pmuname"), true);
475 TEST_ASSERT_EQUAL("Underscore_", perf_pmu__match(&test_pmu
, "pmuname_"), true);
476 TEST_ASSERT_EQUAL("Substring_", perf_pmu__match(&test_pmu
, "pmuna"), false);
478 test_pmu
.name
= "pmuname_ab23";
479 TEST_ASSERT_EQUAL("Diff suffix hex_", perf_pmu__match(&test_pmu
, "pmuname_2"), false);
480 TEST_ASSERT_EQUAL("Sub suffix hex_", perf_pmu__match(&test_pmu
, "pmuname_ab"), true);
481 TEST_ASSERT_EQUAL("Same suffix hex_", perf_pmu__match(&test_pmu
, "pmuname_ab23"), true);
482 TEST_ASSERT_EQUAL("No suffix hex_", perf_pmu__match(&test_pmu
, "pmuname"), true);
483 TEST_ASSERT_EQUAL("Underscore hex_", perf_pmu__match(&test_pmu
, "pmuname_"), true);
484 TEST_ASSERT_EQUAL("Substring hex_", perf_pmu__match(&test_pmu
, "pmuna"), false);
486 test_pmu
.name
= "pmuname10";
487 TEST_ASSERT_EQUAL("Diff suffix", perf_pmu__match(&test_pmu
, "pmuname2"), false);
488 TEST_ASSERT_EQUAL("Sub suffix", perf_pmu__match(&test_pmu
, "pmuname1"), true);
489 TEST_ASSERT_EQUAL("Same suffix", perf_pmu__match(&test_pmu
, "pmuname10"), true);
490 TEST_ASSERT_EQUAL("No suffix", perf_pmu__match(&test_pmu
, "pmuname"), true);
491 TEST_ASSERT_EQUAL("Underscore", perf_pmu__match(&test_pmu
, "pmuname_"), false);
492 TEST_ASSERT_EQUAL("Substring", perf_pmu__match(&test_pmu
, "pmuna"), false);
494 test_pmu
.name
= "pmunameab23";
495 TEST_ASSERT_EQUAL("Diff suffix hex", perf_pmu__match(&test_pmu
, "pmuname2"), false);
496 TEST_ASSERT_EQUAL("Sub suffix hex", perf_pmu__match(&test_pmu
, "pmunameab"), true);
497 TEST_ASSERT_EQUAL("Same suffix hex", perf_pmu__match(&test_pmu
, "pmunameab23"), true);
498 TEST_ASSERT_EQUAL("No suffix hex", perf_pmu__match(&test_pmu
, "pmuname"), true);
499 TEST_ASSERT_EQUAL("Underscore hex", perf_pmu__match(&test_pmu
, "pmuname_"), false);
500 TEST_ASSERT_EQUAL("Substring hex", perf_pmu__match(&test_pmu
, "pmuna"), false);
503 * 2 hex chars or less are not considered suffixes so it shouldn't be
504 * possible to wildcard by skipping the suffix. Therefore there are more
505 * false results here than above.
507 test_pmu
.name
= "pmuname_a3";
508 TEST_ASSERT_EQUAL("Diff suffix 2 hex_", perf_pmu__match(&test_pmu
, "pmuname_2"), false);
510 * This one should be false, but because pmuname_a3 ends in 3 which is
511 * decimal, it's not possible to determine if it's a short hex suffix or
512 * a normal decimal suffix following text. And we want to match on any
513 * length of decimal suffix. Run the test anyway and expect the wrong
514 * result. And slightly fuzzy matching shouldn't do too much harm.
516 TEST_ASSERT_EQUAL("Sub suffix 2 hex_", perf_pmu__match(&test_pmu
, "pmuname_a"), true);
517 TEST_ASSERT_EQUAL("Same suffix 2 hex_", perf_pmu__match(&test_pmu
, "pmuname_a3"), true);
518 TEST_ASSERT_EQUAL("No suffix 2 hex_", perf_pmu__match(&test_pmu
, "pmuname"), false);
519 TEST_ASSERT_EQUAL("Underscore 2 hex_", perf_pmu__match(&test_pmu
, "pmuname_"), false);
520 TEST_ASSERT_EQUAL("Substring 2 hex_", perf_pmu__match(&test_pmu
, "pmuna"), false);
522 test_pmu
.name
= "pmuname_5";
523 TEST_ASSERT_EQUAL("Glob 1", perf_pmu__match(&test_pmu
, "pmu*"), true);
524 TEST_ASSERT_EQUAL("Glob 2", perf_pmu__match(&test_pmu
, "nomatch*"), false);
525 TEST_ASSERT_EQUAL("Seq 1", perf_pmu__match(&test_pmu
, "pmuname_[12345]"), true);
526 TEST_ASSERT_EQUAL("Seq 2", perf_pmu__match(&test_pmu
, "pmuname_[67890]"), false);
527 TEST_ASSERT_EQUAL("? 1", perf_pmu__match(&test_pmu
, "pmuname_?"), true);
528 TEST_ASSERT_EQUAL("? 2", perf_pmu__match(&test_pmu
, "pmuname_1?"), false);
533 static struct test_case tests__pmu
[] = {
534 TEST_CASE("Parsing with PMU format directory", pmu_format
),
535 TEST_CASE("Parsing with PMU event", pmu_events
),
536 TEST_CASE("PMU event names", pmu_event_names
),
537 TEST_CASE("PMU name combining", name_len
),
538 TEST_CASE("PMU name comparison", name_cmp
),
539 TEST_CASE("PMU cmdline match", pmu_match
),
543 struct test_suite suite__pmu
= {
544 .desc
= "Sysfs PMU tests",
545 .test_cases
= tests__pmu
,