Skip to content

Commit 18eb2ca

Browse files
captain5050acmel
authored andcommitted
perf test pmu: Add an eagerly loaded event test
Allow events/aliases to be eagerly loaded for a PMU. Factor out the pmu_aliases_parse to allow this. Parse a test event and check it configures the attribute as expected. There is overlap with the parse-events tests, but this test is done with a PMU created in a temp directory and doesn't rely on PMUs in sysfs. Reviewed-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Ian Rogers <irogers@google.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@arm.com> Cc: Jing Zhang <renyu.zj@linux.alibaba.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Link: https://lore.kernel.org/r/20240502213507.2339733-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent aa1551f commit 18eb2ca

2 files changed

Lines changed: 124 additions & 21 deletions

File tree

tools/perf/tests/pmu.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// SPDX-License-Identifier: GPL-2.0
2+
#include "evlist.h"
3+
#include "evsel.h"
24
#include "parse-events.h"
35
#include "pmu.h"
46
#include "tests.h"
@@ -54,6 +56,9 @@ static struct perf_pmu *test_pmu_get(char *dir, size_t sz)
5456
{ "krava22", "config2:8,18,48,58\n", },
5557
{ "krava23", "config2:28-29,38\n", },
5658
};
59+
const char *test_event = "krava01=15,krava02=170,krava03=1,krava11=27,krava12=1,"
60+
"krava13=2,krava21=119,krava22=11,krava23=2\n";
61+
5762
char name[PATH_MAX];
5863
int dirfd, file;
5964
struct perf_pmu *pmu = NULL;
@@ -116,6 +121,24 @@ static struct perf_pmu *test_pmu_get(char *dir, size_t sz)
116121
close(file);
117122
}
118123

124+
/* Create test event. */
125+
if (mkdirat(dirfd, "perf-pmu-test/events", 0755) < 0) {
126+
pr_err("Failed to mkdir PMU events directory\n");
127+
goto err_out;
128+
}
129+
file = openat(dirfd, "perf-pmu-test/events/test-event", O_WRONLY | O_CREAT, 0600);
130+
if (!file) {
131+
pr_err("Failed to open for writing file \"type\"\n");
132+
goto err_out;
133+
}
134+
len = strlen(test_event);
135+
if (write(file, test_event, len) < len) {
136+
close(file);
137+
pr_err("Failed to write to 'test-event' file\n");
138+
goto err_out;
139+
}
140+
close(file);
141+
119142
/* Make the PMU reading the files created above. */
120143
pmu = perf_pmus__add_test_pmu(dirfd, "perf-pmu-test");
121144
if (!pmu)
@@ -176,8 +199,61 @@ static int test__pmu_format(struct test_suite *test __maybe_unused, int subtest
176199
return ret;
177200
}
178201

202+
static int test__pmu_events(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
203+
{
204+
char dir[PATH_MAX];
205+
struct parse_events_error err;
206+
struct evlist *evlist;
207+
struct evsel *evsel;
208+
struct perf_event_attr *attr;
209+
int ret = TEST_FAIL;
210+
struct perf_pmu *pmu = test_pmu_get(dir, sizeof(dir));
211+
const char *event = "perf-pmu-test/test-event/";
212+
213+
214+
if (!pmu)
215+
return TEST_FAIL;
216+
217+
evlist = evlist__new();
218+
if (evlist == NULL) {
219+
pr_err("Failed allocation");
220+
goto err_out;
221+
}
222+
parse_events_error__init(&err);
223+
ret = parse_events(evlist, event, &err);
224+
if (ret) {
225+
pr_debug("failed to parse event '%s', err %d\n", event, ret);
226+
parse_events_error__print(&err, event);
227+
if (parse_events_error__contains(&err, "can't access trace events"))
228+
ret = TEST_SKIP;
229+
goto err_out;
230+
}
231+
evsel = evlist__first(evlist);
232+
attr = &evsel->core.attr;
233+
if (attr->config != 0xc00000000002a823) {
234+
pr_err("Unexpected config value %llx\n", attr->config);
235+
goto err_out;
236+
}
237+
if (attr->config1 != 0x8000400000000145) {
238+
pr_err("Unexpected config1 value %llx\n", attr->config1);
239+
goto err_out;
240+
}
241+
if (attr->config2 != 0x0400000020041d07) {
242+
pr_err("Unexpected config2 value %llx\n", attr->config2);
243+
goto err_out;
244+
}
245+
246+
ret = TEST_OK;
247+
err_out:
248+
parse_events_error__exit(&err);
249+
evlist__delete(evlist);
250+
test_pmu_put(dir, pmu);
251+
return ret;
252+
}
253+
179254
static struct test_case tests__pmu[] = {
180255
TEST_CASE("Parsing with PMU format directory", pmu_format),
256+
TEST_CASE("Parsing with PMU event", pmu_events),
181257
{ .name = NULL, }
182258
};
183259

tools/perf/util/pmu.c

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -597,33 +597,18 @@ static inline bool pmu_alias_info_file(const char *name)
597597
* Reading the pmu event aliases definition, which should be located at:
598598
* /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
599599
*/
600-
static int pmu_aliases_parse(struct perf_pmu *pmu)
600+
static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)
601601
{
602-
char path[PATH_MAX];
603602
struct dirent *evt_ent;
604603
DIR *event_dir;
605-
size_t len;
606-
int fd, dir_fd;
607604

608-
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
609-
if (!len)
610-
return 0;
611-
scnprintf(path + len, sizeof(path) - len, "%s/events", pmu->name);
612-
613-
dir_fd = open(path, O_DIRECTORY);
614-
if (dir_fd == -1) {
615-
pmu->sysfs_aliases_loaded = true;
616-
return 0;
617-
}
618-
619-
event_dir = fdopendir(dir_fd);
620-
if (!event_dir){
621-
close (dir_fd);
605+
event_dir = fdopendir(events_dir_fd);
606+
if (!event_dir)
622607
return -EINVAL;
623-
}
624608

625609
while ((evt_ent = readdir(event_dir))) {
626610
char *name = evt_ent->d_name;
611+
int fd;
627612
FILE *file;
628613

629614
if (!strcmp(name, ".") || !strcmp(name, ".."))
@@ -635,7 +620,7 @@ static int pmu_aliases_parse(struct perf_pmu *pmu)
635620
if (pmu_alias_info_file(name))
636621
continue;
637622

638-
fd = openat(dir_fd, name, O_RDONLY);
623+
fd = openat(events_dir_fd, name, O_RDONLY);
639624
if (fd == -1) {
640625
pr_debug("Cannot open %s\n", name);
641626
continue;
@@ -653,11 +638,50 @@ static int pmu_aliases_parse(struct perf_pmu *pmu)
653638
}
654639

655640
closedir(event_dir);
656-
close (dir_fd);
657641
pmu->sysfs_aliases_loaded = true;
658642
return 0;
659643
}
660644

645+
static int pmu_aliases_parse(struct perf_pmu *pmu)
646+
{
647+
char path[PATH_MAX];
648+
size_t len;
649+
int events_dir_fd, ret;
650+
651+
if (pmu->sysfs_aliases_loaded)
652+
return 0;
653+
654+
len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
655+
if (!len)
656+
return 0;
657+
scnprintf(path + len, sizeof(path) - len, "%s/events", pmu->name);
658+
659+
events_dir_fd = open(path, O_DIRECTORY);
660+
if (events_dir_fd == -1) {
661+
pmu->sysfs_aliases_loaded = true;
662+
return 0;
663+
}
664+
ret = __pmu_aliases_parse(pmu, events_dir_fd);
665+
close(events_dir_fd);
666+
return ret;
667+
}
668+
669+
static int pmu_aliases_parse_eager(struct perf_pmu *pmu, int sysfs_fd)
670+
{
671+
char path[FILENAME_MAX + 7];
672+
int ret, events_dir_fd;
673+
674+
scnprintf(path, sizeof(path), "%s/events", pmu->name);
675+
events_dir_fd = openat(sysfs_fd, path, O_DIRECTORY, 0);
676+
if (events_dir_fd == -1) {
677+
pmu->sysfs_aliases_loaded = true;
678+
return 0;
679+
}
680+
ret = __pmu_aliases_parse(pmu, events_dir_fd);
681+
close(events_dir_fd);
682+
return ret;
683+
}
684+
661685
static int pmu_alias_terms(struct perf_pmu_alias *alias, int err_loc, struct list_head *terms)
662686
{
663687
struct parse_events_term *term, *cloned;
@@ -1042,6 +1066,9 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
10421066

10431067
perf_pmu__arch_init(pmu);
10441068

1069+
if (eager_load)
1070+
pmu_aliases_parse_eager(pmu, dirfd);
1071+
10451072
return pmu;
10461073
err:
10471074
zfree(&pmu->name);

0 commit comments

Comments
 (0)