]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - tools/perf/util/pmu.c
perf alias: Remove trailing newline when reading sysfs files
[mirror_ubuntu-eoan-kernel.git] / tools / perf / util / pmu.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
cd82a32e 2#include <linux/list.h>
c5de47f2 3#include <linux/compiler.h>
cd82a32e 4#include <sys/types.h>
a43783ae 5#include <errno.h>
c23c2a0f 6#include <fcntl.h>
7a8ef4c4 7#include <sys/stat.h>
cd82a32e
JO
8#include <unistd.h>
9#include <stdio.h>
dc0a6202 10#include <stdbool.h>
7d4bdab5 11#include <stdarg.h>
cd82a32e 12#include <dirent.h>
cd0cfad7 13#include <api/fs/fs.h>
410136f5 14#include <locale.h>
fbc2844e 15#include <regex.h>
cd82a32e
JO
16#include "util.h"
17#include "pmu.h"
18#include "parse-events.h"
7ae92e74 19#include "cpumap.h"
933f82ff
SB
20#include "header.h"
21#include "pmu-events/pmu-events.h"
61eb2eb4 22#include "cache.h"
a067558e 23#include "string2.h"
cd82a32e 24
ab1bf653
ACM
25struct perf_pmu_format {
26 char *name;
27 int value;
28 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
29 struct list_head list;
30};
31
50a9667c
RR
32#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
33
cd82a32e
JO
34int perf_pmu_parse(struct list_head *list, char *name);
35extern FILE *perf_pmu_in;
36
37static LIST_HEAD(pmus);
38
39/*
40 * Parse & process all the sysfs attributes located under
41 * the directory specified in 'dir' parameter.
42 */
cff7f956 43int perf_pmu__format_parse(char *dir, struct list_head *head)
cd82a32e
JO
44{
45 struct dirent *evt_ent;
46 DIR *format_dir;
47 int ret = 0;
48
49 format_dir = opendir(dir);
50 if (!format_dir)
51 return -EINVAL;
52
53 while (!ret && (evt_ent = readdir(format_dir))) {
54 char path[PATH_MAX];
55 char *name = evt_ent->d_name;
56 FILE *file;
57
58 if (!strcmp(name, ".") || !strcmp(name, ".."))
59 continue;
60
61 snprintf(path, PATH_MAX, "%s/%s", dir, name);
62
63 ret = -EINVAL;
64 file = fopen(path, "r");
65 if (!file)
66 break;
67
68 perf_pmu_in = file;
69 ret = perf_pmu_parse(head, name);
70 fclose(file);
71 }
72
73 closedir(format_dir);
74 return ret;
75}
76
77/*
78 * Reading/parsing the default pmu format definition, which should be
79 * located at:
80 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
81 */
b6b96fb4 82static int pmu_format(const char *name, struct list_head *format)
cd82a32e
JO
83{
84 struct stat st;
85 char path[PATH_MAX];
cf38fada 86 const char *sysfs = sysfs__mountpoint();
cd82a32e 87
cd82a32e
JO
88 if (!sysfs)
89 return -1;
90
91 snprintf(path, PATH_MAX,
50a9667c 92 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
cd82a32e
JO
93
94 if (stat(path, &st) < 0)
9bc8f9fe 95 return 0; /* no error if format does not exist */
cd82a32e 96
cff7f956 97 if (perf_pmu__format_parse(path, format))
cd82a32e
JO
98 return -1;
99
100 return 0;
101}
102
d02fc6bc 103static int convert_scale(const char *scale, char **end, double *sval)
410136f5 104{
ea8f75f9 105 char *lc;
d02fc6bc 106 int ret = 0;
9ecae065 107
410136f5
SE
108 /*
109 * save current locale
110 */
111 lc = setlocale(LC_NUMERIC, NULL);
112
f9a5978a
JO
113 /*
114 * The lc string may be allocated in static storage,
115 * so get a dynamic copy to make it survive setlocale
116 * call below.
117 */
118 lc = strdup(lc);
119 if (!lc) {
120 ret = -ENOMEM;
d02fc6bc 121 goto out;
f9a5978a
JO
122 }
123
410136f5
SE
124 /*
125 * force to C locale to ensure kernel
126 * scale string is converted correctly.
127 * kernel uses default C locale.
128 */
129 setlocale(LC_NUMERIC, "C");
130
d02fc6bc 131 *sval = strtod(scale, end);
410136f5 132
d02fc6bc 133out:
410136f5
SE
134 /* restore locale */
135 setlocale(LC_NUMERIC, lc);
ea8f75f9 136 free(lc);
d02fc6bc
AK
137 return ret;
138}
139
140static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
141{
142 struct stat st;
143 ssize_t sret;
144 char scale[128];
145 int fd, ret = -1;
146 char path[PATH_MAX];
147
148 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
149
150 fd = open(path, O_RDONLY);
151 if (fd == -1)
152 return -1;
153
154 if (fstat(fd, &st) < 0)
155 goto error;
156
157 sret = read(fd, scale, sizeof(scale)-1);
158 if (sret < 0)
159 goto error;
160
161 if (scale[sret - 1] == '\n')
162 scale[sret - 1] = '\0';
163 else
164 scale[sret] = '\0';
f9a5978a 165
d02fc6bc 166 ret = convert_scale(scale, NULL, &alias->scale);
410136f5
SE
167error:
168 close(fd);
169 return ret;
170}
171
172static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
173{
174 char path[PATH_MAX];
175 ssize_t sret;
176 int fd;
177
178 snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
179
180 fd = open(path, O_RDONLY);
181 if (fd == -1)
182 return -1;
183
d85ce830 184 sret = read(fd, alias->unit, UNIT_MAX_LEN);
410136f5
SE
185 if (sret < 0)
186 goto error;
187
188 close(fd);
189
9ecae065
MS
190 if (alias->unit[sret - 1] == '\n')
191 alias->unit[sret - 1] = '\0';
192 else
193 alias->unit[sret] = '\0';
410136f5
SE
194
195 return 0;
196error:
197 close(fd);
198 alias->unit[0] = '\0';
199 return -1;
200}
201
044330c1
MF
202static int
203perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
204{
205 char path[PATH_MAX];
206 int fd;
207
208 snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
209
210 fd = open(path, O_RDONLY);
211 if (fd == -1)
212 return -1;
213
214 close(fd);
215
216 alias->per_pkg = true;
217 return 0;
218}
219
1d9e446b
JO
220static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
221 char *dir, char *name)
222{
223 char path[PATH_MAX];
224 int fd;
225
226 snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
227
228 fd = open(path, O_RDONLY);
229 if (fd == -1)
230 return -1;
231
232 alias->snapshot = true;
233 close(fd);
234 return 0;
235}
236
70c646e0 237static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
fedb2b51
AK
238 char *desc, char *val,
239 char *long_desc, char *topic,
00636c3b 240 char *unit, char *perpkg,
96284814
AK
241 char *metric_expr,
242 char *metric_name)
a6146d50 243{
5c6ccc37 244 struct perf_pmu_alias *alias;
a6146d50 245 int ret;
fedb2b51 246 int num;
a6146d50 247
a6146d50
ZY
248 alias = malloc(sizeof(*alias));
249 if (!alias)
250 return -ENOMEM;
251
252 INIT_LIST_HEAD(&alias->terms);
410136f5
SE
253 alias->scale = 1.0;
254 alias->unit[0] = '\0';
044330c1 255 alias->per_pkg = false;
84530920 256 alias->snapshot = false;
410136f5 257
70c646e0 258 ret = parse_events_terms(&alias->terms, val);
a6146d50 259 if (ret) {
70c646e0 260 pr_err("Cannot parse alias %s: %d\n", val, ret);
a6146d50
ZY
261 free(alias);
262 return ret;
263 }
264
265 alias->name = strdup(name);
70c646e0
SB
266 if (dir) {
267 /*
268 * load unit name and scale if available
269 */
270 perf_pmu__parse_unit(alias, dir, name);
271 perf_pmu__parse_scale(alias, dir, name);
272 perf_pmu__parse_per_pkg(alias, dir, name);
273 perf_pmu__parse_snapshot(alias, dir, name);
274 }
410136f5 275
00636c3b 276 alias->metric_expr = metric_expr ? strdup(metric_expr) : NULL;
96284814 277 alias->metric_name = metric_name ? strdup(metric_name): NULL;
08e60ed1 278 alias->desc = desc ? strdup(desc) : NULL;
c8d6828a
SB
279 alias->long_desc = long_desc ? strdup(long_desc) :
280 desc ? strdup(desc) : NULL;
dd5f1036 281 alias->topic = topic ? strdup(topic) : NULL;
fedb2b51
AK
282 if (unit) {
283 if (convert_scale(unit, &unit, &alias->scale) < 0)
284 return -1;
285 snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
286 }
287 alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1;
f2361024
AK
288 alias->str = strdup(val);
289
a6146d50 290 list_add_tail(&alias->list, list);
410136f5 291
a6146d50
ZY
292 return 0;
293}
294
70c646e0
SB
295static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
296{
297 char buf[256];
298 int ret;
299
300 ret = fread(buf, 1, sizeof(buf), file);
301 if (ret == 0)
302 return -EINVAL;
303
304 buf[ret] = 0;
305
ea23ac73
TR
306 /* Remove trailing newline from sysfs file */
307 rtrim(buf);
308
fedb2b51 309 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
96284814 310 NULL, NULL, NULL);
70c646e0
SB
311}
312
46441bdc
MF
313static inline bool pmu_alias_info_file(char *name)
314{
315 size_t len;
316
317 len = strlen(name);
318 if (len > 5 && !strcmp(name + len - 5, ".unit"))
319 return true;
320 if (len > 6 && !strcmp(name + len - 6, ".scale"))
321 return true;
044330c1
MF
322 if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
323 return true;
1d9e446b
JO
324 if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
325 return true;
46441bdc
MF
326
327 return false;
328}
329
a6146d50
ZY
330/*
331 * Process all the sysfs attributes located under the directory
332 * specified in 'dir' parameter.
333 */
334static int pmu_aliases_parse(char *dir, struct list_head *head)
335{
336 struct dirent *evt_ent;
337 DIR *event_dir;
a6146d50
ZY
338
339 event_dir = opendir(dir);
340 if (!event_dir)
341 return -EINVAL;
342
940db6dc 343 while ((evt_ent = readdir(event_dir))) {
a6146d50
ZY
344 char path[PATH_MAX];
345 char *name = evt_ent->d_name;
346 FILE *file;
347
348 if (!strcmp(name, ".") || !strcmp(name, ".."))
349 continue;
350
410136f5 351 /*
46441bdc 352 * skip info files parsed in perf_pmu__new_alias()
410136f5 353 */
46441bdc 354 if (pmu_alias_info_file(name))
410136f5
SE
355 continue;
356
77f18153 357 scnprintf(path, PATH_MAX, "%s/%s", dir, name);
a6146d50 358
a6146d50 359 file = fopen(path, "r");
940db6dc
AK
360 if (!file) {
361 pr_debug("Cannot open %s\n", path);
362 continue;
363 }
410136f5 364
940db6dc
AK
365 if (perf_pmu__new_alias(head, dir, name, file) < 0)
366 pr_debug("Cannot set up %s\n", name);
a6146d50
ZY
367 fclose(file);
368 }
369
370 closedir(event_dir);
940db6dc 371 return 0;
a6146d50
ZY
372}
373
374/*
375 * Reading the pmu event aliases definition, which should be located at:
376 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
377 */
b6b96fb4 378static int pmu_aliases(const char *name, struct list_head *head)
a6146d50
ZY
379{
380 struct stat st;
381 char path[PATH_MAX];
cf38fada 382 const char *sysfs = sysfs__mountpoint();
a6146d50 383
a6146d50
ZY
384 if (!sysfs)
385 return -1;
386
387 snprintf(path, PATH_MAX,
388 "%s/bus/event_source/devices/%s/events", sysfs, name);
389
390 if (stat(path, &st) < 0)
3fded963 391 return 0; /* no error if 'events' does not exist */
a6146d50
ZY
392
393 if (pmu_aliases_parse(path, head))
394 return -1;
395
396 return 0;
397}
398
5c6ccc37 399static int pmu_alias_terms(struct perf_pmu_alias *alias,
a6146d50
ZY
400 struct list_head *terms)
401{
7c2f8164 402 struct parse_events_term *term, *cloned;
a6146d50
ZY
403 LIST_HEAD(list);
404 int ret;
405
406 list_for_each_entry(term, &alias->terms, list) {
7c2f8164 407 ret = parse_events_term__clone(&cloned, term);
a6146d50 408 if (ret) {
682dc24c 409 parse_events_terms__purge(&list);
a6146d50
ZY
410 return ret;
411 }
c2f1cead
AK
412 /*
413 * Weak terms don't override command line options,
414 * which we don't want for implicit terms in aliases.
415 */
416 cloned->weak = true;
7c2f8164 417 list_add_tail(&cloned->list, &list);
a6146d50
ZY
418 }
419 list_splice(&list, terms);
420 return 0;
421}
422
cd82a32e
JO
423/*
424 * Reading/parsing the default pmu type value, which should be
425 * located at:
426 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
427 */
b6b96fb4 428static int pmu_type(const char *name, __u32 *type)
cd82a32e
JO
429{
430 struct stat st;
431 char path[PATH_MAX];
cd82a32e
JO
432 FILE *file;
433 int ret = 0;
cf38fada 434 const char *sysfs = sysfs__mountpoint();
cd82a32e 435
cd82a32e
JO
436 if (!sysfs)
437 return -1;
438
439 snprintf(path, PATH_MAX,
50a9667c 440 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
cd82a32e
JO
441
442 if (stat(path, &st) < 0)
443 return -1;
444
445 file = fopen(path, "r");
446 if (!file)
447 return -EINVAL;
448
449 if (1 != fscanf(file, "%u", type))
450 ret = -1;
451
452 fclose(file);
453 return ret;
454}
455
50a9667c
RR
456/* Add all pmus in sysfs to pmu list: */
457static void pmu_read_sysfs(void)
458{
459 char path[PATH_MAX];
50a9667c
RR
460 DIR *dir;
461 struct dirent *dent;
cf38fada 462 const char *sysfs = sysfs__mountpoint();
50a9667c 463
50a9667c
RR
464 if (!sysfs)
465 return;
466
467 snprintf(path, PATH_MAX,
468 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
469
470 dir = opendir(path);
471 if (!dir)
472 return;
473
474 while ((dent = readdir(dir))) {
475 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
476 continue;
477 /* add to static LIST_HEAD(pmus): */
478 perf_pmu__find(dent->d_name);
479 }
480
481 closedir(dir);
482}
483
66ec1191
MR
484static struct cpu_map *__pmu_cpumask(const char *path)
485{
486 FILE *file;
487 struct cpu_map *cpus;
488
489 file = fopen(path, "r");
490 if (!file)
491 return NULL;
492
493 cpus = cpu_map__read(file);
494 fclose(file);
495 return cpus;
496}
497
498/*
499 * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64)
500 * may have a "cpus" file.
501 */
502#define CPUS_TEMPLATE_UNCORE "%s/bus/event_source/devices/%s/cpumask"
503#define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus"
504
b6b96fb4 505static struct cpu_map *pmu_cpumask(const char *name)
7ae92e74 506{
7ae92e74 507 char path[PATH_MAX];
7ae92e74 508 struct cpu_map *cpus;
cf38fada 509 const char *sysfs = sysfs__mountpoint();
7e3fcffe 510 const char *templates[] = {
66ec1191
MR
511 CPUS_TEMPLATE_UNCORE,
512 CPUS_TEMPLATE_CPU,
513 NULL
7e3fcffe
MR
514 };
515 const char **template;
7ae92e74 516
7ae92e74
YZ
517 if (!sysfs)
518 return NULL;
519
7e3fcffe
MR
520 for (template = templates; *template; template++) {
521 snprintf(path, PATH_MAX, *template, sysfs, name);
66ec1191
MR
522 cpus = __pmu_cpumask(path);
523 if (cpus)
524 return cpus;
7e3fcffe 525 }
7ae92e74 526
66ec1191
MR
527 return NULL;
528}
7ae92e74 529
66ec1191
MR
530static bool pmu_is_uncore(const char *name)
531{
532 char path[PATH_MAX];
533 struct cpu_map *cpus;
534 const char *sysfs = sysfs__mountpoint();
7ae92e74 535
66ec1191
MR
536 snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
537 cpus = __pmu_cpumask(path);
538 cpu_map__put(cpus);
539
540 return !!cpus;
7ae92e74
YZ
541}
542
14b22ae0
GK
543/*
544 * PMU CORE devices have different name other than cpu in sysfs on some
292c34c1
KL
545 * platforms.
546 * Looking for possible sysfs files to identify the arm core device.
14b22ae0 547 */
292c34c1 548static int is_arm_pmu_core(const char *name)
14b22ae0
GK
549{
550 struct stat st;
551 char path[PATH_MAX];
552 const char *sysfs = sysfs__mountpoint();
553
554 if (!sysfs)
555 return 0;
556
14b22ae0
GK
557 /* Look for cpu sysfs (specific to arm) */
558 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/cpus",
559 sysfs, name);
560 if (stat(path, &st) == 0)
561 return 1;
562
038586c3
TR
563 /* Look for cpu sysfs (specific to s390) */
564 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s",
565 sysfs, name);
566 if (stat(path, &st) == 0 && !strncmp(name, "cpum_", 5))
567 return 1;
568
14b22ae0
GK
569 return 0;
570}
571
933f82ff
SB
572/*
573 * Return the CPU id as a raw string.
574 *
575 * Each architecture should provide a more precise id string that
576 * can be use to match the architecture's "mapfile".
577 */
54e32dc0 578char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
933f82ff
SB
579{
580 return NULL;
581}
582
4cb7d3ec
TR
583/* Return zero when the cpuid from the mapfile.csv matches the
584 * cpuid string generated on this platform.
585 * Otherwise return non-zero.
586 */
ce04abfb 587int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
4cb7d3ec
TR
588{
589 regex_t re;
590 regmatch_t pmatch[1];
591 int match;
592
593 if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
594 /* Warn unable to generate match particular string. */
595 pr_info("Invalid regular expression %s\n", mapcpuid);
596 return 1;
597 }
598
599 match = !regexec(&re, cpuid, 1, pmatch, 0);
600 regfree(&re);
601 if (match) {
602 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
603
604 /* Verify the entire string matched. */
605 if (match_len == strlen(cpuid))
606 return 0;
607 }
608 return 1;
609}
610
54e32dc0 611static char *perf_pmu__getcpuid(struct perf_pmu *pmu)
933f82ff 612{
933f82ff 613 char *cpuid;
fb967063 614 static bool printed;
933f82ff 615
fc06e2a5
AK
616 cpuid = getenv("PERF_CPUID");
617 if (cpuid)
618 cpuid = strdup(cpuid);
619 if (!cpuid)
54e32dc0 620 cpuid = get_cpuid_str(pmu);
933f82ff 621 if (!cpuid)
d77ade9f 622 return NULL;
933f82ff 623
fb967063
AK
624 if (!printed) {
625 pr_debug("Using CPUID %s\n", cpuid);
626 printed = true;
627 }
d77ade9f
AK
628 return cpuid;
629}
630
54e32dc0 631struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
d77ade9f
AK
632{
633 struct pmu_events_map *map;
54e32dc0 634 char *cpuid = perf_pmu__getcpuid(pmu);
d77ade9f 635 int i;
fc06e2a5 636
de3d0f12
GK
637 /* on some platforms which uses cpus map, cpuid can be NULL for
638 * PMUs other than CORE PMUs.
639 */
640 if (!cpuid)
641 return NULL;
642
933f82ff 643 i = 0;
d77ade9f 644 for (;;) {
933f82ff 645 map = &pmu_events_map[i++];
d77ade9f
AK
646 if (!map->table) {
647 map = NULL;
648 break;
649 }
933f82ff 650
4cb7d3ec 651 if (!strcmp_cpuid_str(map->cpuid, cpuid))
933f82ff
SB
652 break;
653 }
d77ade9f
AK
654 free(cpuid);
655 return map;
656}
657
658/*
659 * From the pmu_events_map, find the table of PMU events that corresponds
660 * to the current running CPU. Then, add all PMU events from that table
661 * as aliases.
662 */
54e32dc0 663static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
d77ade9f
AK
664{
665 int i;
666 struct pmu_events_map *map;
667 struct pmu_event *pe;
54e32dc0 668 const char *name = pmu->name;
292c34c1 669 const char *pname;
d77ade9f 670
54e32dc0 671 map = perf_pmu__find_map(pmu);
d77ade9f
AK
672 if (!map)
673 return;
933f82ff
SB
674
675 /*
676 * Found a matching PMU events table. Create aliases
677 */
678 i = 0;
679 while (1) {
fedb2b51 680
933f82ff 681 pe = &map->table[i++];
b18f3e36
AK
682 if (!pe->name) {
683 if (pe->metric_group || pe->metric_name)
684 continue;
933f82ff 685 break;
b18f3e36 686 }
933f82ff 687
292c34c1
KL
688 if (!is_arm_pmu_core(name)) {
689 pname = pe->pmu ? pe->pmu : "cpu";
690 if (strncmp(pname, name, strlen(pname)))
14b22ae0
GK
691 continue;
692 }
fedb2b51 693
933f82ff
SB
694 /* need type casts to override 'const' */
695 __perf_pmu__new_alias(head, NULL, (char *)pe->name,
c8d6828a 696 (char *)pe->desc, (char *)pe->event,
fedb2b51 697 (char *)pe->long_desc, (char *)pe->topic,
00636c3b 698 (char *)pe->unit, (char *)pe->perpkg,
96284814
AK
699 (char *)pe->metric_expr,
700 (char *)pe->metric_name);
933f82ff 701 }
933f82ff
SB
702}
703
c5de47f2 704struct perf_event_attr * __weak
dc0a6202
AH
705perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
706{
707 return NULL;
708}
709
b6b96fb4 710static struct perf_pmu *pmu_lookup(const char *name)
cd82a32e
JO
711{
712 struct perf_pmu *pmu;
713 LIST_HEAD(format);
a6146d50 714 LIST_HEAD(aliases);
cd82a32e
JO
715 __u32 type;
716
717 /*
718 * The pmu data we store & need consists of the pmu
719 * type value and format definitions. Load both right
720 * now.
721 */
722 if (pmu_format(name, &format))
723 return NULL;
724
15b22ed3
AK
725 /*
726 * Check the type first to avoid unnecessary work.
727 */
728 if (pmu_type(name, &type))
3fded963
JO
729 return NULL;
730
15b22ed3 731 if (pmu_aliases(name, &aliases))
cd82a32e
JO
732 return NULL;
733
734 pmu = zalloc(sizeof(*pmu));
735 if (!pmu)
736 return NULL;
737
7ae92e74 738 pmu->cpus = pmu_cpumask(name);
54e32dc0
GK
739 pmu->name = strdup(name);
740 pmu->type = type;
66ec1191 741 pmu->is_uncore = pmu_is_uncore(name);
54e32dc0 742 pmu_add_cpu_aliases(&aliases, pmu);
66ec1191 743
cd82a32e 744 INIT_LIST_HEAD(&pmu->format);
a6146d50 745 INIT_LIST_HEAD(&pmu->aliases);
cd82a32e 746 list_splice(&format, &pmu->format);
a6146d50 747 list_splice(&aliases, &pmu->aliases);
9bc8f9fe 748 list_add_tail(&pmu->list, &pmus);
dc0a6202
AH
749
750 pmu->default_config = perf_pmu__get_default_config(pmu);
751
cd82a32e
JO
752 return pmu;
753}
754
b6b96fb4 755static struct perf_pmu *pmu_find(const char *name)
cd82a32e
JO
756{
757 struct perf_pmu *pmu;
758
759 list_for_each_entry(pmu, &pmus, list)
760 if (!strcmp(pmu->name, name))
761 return pmu;
762
763 return NULL;
764}
765
50a9667c
RR
766struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
767{
768 /*
769 * pmu iterator: If pmu is NULL, we start at the begin,
770 * otherwise return the next pmu. Returns NULL on end.
771 */
772 if (!pmu) {
773 pmu_read_sysfs();
774 pmu = list_prepare_entry(pmu, &pmus, list);
775 }
776 list_for_each_entry_continue(pmu, &pmus, list)
777 return pmu;
778 return NULL;
779}
780
b6b96fb4 781struct perf_pmu *perf_pmu__find(const char *name)
cd82a32e
JO
782{
783 struct perf_pmu *pmu;
784
785 /*
786 * Once PMU is loaded it stays in the list,
787 * so we keep us from multiple reading/parsing
788 * the pmu format definitions.
789 */
790 pmu = pmu_find(name);
791 if (pmu)
792 return pmu;
793
794 return pmu_lookup(name);
795}
796
5c6ccc37 797static struct perf_pmu_format *
09ff6071 798pmu_find_format(struct list_head *formats, const char *name)
cd82a32e 799{
5c6ccc37 800 struct perf_pmu_format *format;
cd82a32e
JO
801
802 list_for_each_entry(format, formats, list)
803 if (!strcmp(format->name, name))
804 return format;
805
806 return NULL;
807}
808
09ff6071
AH
809__u64 perf_pmu__format_bits(struct list_head *formats, const char *name)
810{
811 struct perf_pmu_format *format = pmu_find_format(formats, name);
812 __u64 bits = 0;
813 int fbit;
814
815 if (!format)
816 return 0;
817
818 for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS)
819 bits |= 1ULL << fbit;
820
821 return bits;
822}
823
cd82a32e 824/*
dc0a6202 825 * Sets value based on the format definition (format parameter)
cd82a32e 826 * and unformated value (value parameter).
cd82a32e 827 */
dc0a6202
AH
828static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
829 bool zero)
cd82a32e
JO
830{
831 unsigned long fbit, vbit;
cd82a32e
JO
832
833 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
834
835 if (!test_bit(fbit, format))
836 continue;
837
dc0a6202
AH
838 if (value & (1llu << vbit++))
839 *v |= (1llu << fbit);
840 else if (zero)
841 *v &= ~(1llu << fbit);
cd82a32e 842 }
cd82a32e
JO
843}
844
0efe6b67
AH
845static __u64 pmu_format_max_value(const unsigned long *format)
846{
ac0e2cd5
KL
847 __u64 w = 0;
848 int fbit;
0efe6b67 849
ac0e2cd5
KL
850 for_each_set_bit(fbit, format, PERF_PMU_FORMAT_BITS)
851 w |= (1ULL << fbit);
852
853 return w;
0efe6b67
AH
854}
855
688d4dfc
CS
856/*
857 * Term is a string term, and might be a param-term. Try to look up it's value
858 * in the remaining terms.
859 * - We have a term like "base-or-format-term=param-term",
860 * - We need to find the value supplied for "param-term" (with param-term named
861 * in a config string) later on in the term list.
862 */
863static int pmu_resolve_param_term(struct parse_events_term *term,
864 struct list_head *head_terms,
865 __u64 *value)
866{
867 struct parse_events_term *t;
868
869 list_for_each_entry(t, head_terms, list) {
870 if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
871 if (!strcmp(t->config, term->config)) {
872 t->used = true;
873 *value = t->val.num;
874 return 0;
875 }
876 }
877 }
878
bb963e16 879 if (verbose > 0)
688d4dfc
CS
880 printf("Required parameter '%s' not specified\n", term->config);
881
882 return -1;
883}
884
ffeb883e 885static char *pmu_formats_string(struct list_head *formats)
e64b020b
JO
886{
887 struct perf_pmu_format *format;
11db4e29
MH
888 char *str = NULL;
889 struct strbuf buf = STRBUF_INIT;
e64b020b
JO
890 unsigned i = 0;
891
ffeb883e 892 if (!formats)
e64b020b
JO
893 return NULL;
894
895 /* sysfs exported terms */
ffeb883e 896 list_for_each_entry(format, formats, list)
11db4e29
MH
897 if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0)
898 goto error;
e64b020b 899
ffeb883e 900 str = strbuf_detach(&buf, NULL);
11db4e29 901error:
ffeb883e 902 strbuf_release(&buf);
e64b020b 903
e64b020b 904 return str;
e64b020b
JO
905}
906
cd82a32e
JO
907/*
908 * Setup one of config[12] attr members based on the
88aca8d9 909 * user input data - term parameter.
cd82a32e
JO
910 */
911static int pmu_config_term(struct list_head *formats,
912 struct perf_event_attr *attr,
dc0a6202 913 struct parse_events_term *term,
688d4dfc 914 struct list_head *head_terms,
e64b020b 915 bool zero, struct parse_events_error *err)
cd82a32e 916{
5c6ccc37 917 struct perf_pmu_format *format;
cd82a32e 918 __u64 *vp;
0efe6b67 919 __u64 val, max_val;
688d4dfc
CS
920
921 /*
922 * If this is a parameter we've already used for parameterized-eval,
923 * skip it in normal eval.
924 */
925 if (term->used)
926 return 0;
cd82a32e
JO
927
928 /*
cd82a32e
JO
929 * Hardcoded terms should be already in, so nothing
930 * to be done for them.
931 */
932 if (parse_events__is_hardcoded_term(term))
933 return 0;
934
cd82a32e 935 format = pmu_find_format(formats, term->config);
688d4dfc 936 if (!format) {
bb963e16 937 if (verbose > 0)
688d4dfc 938 printf("Invalid event/parameter '%s'\n", term->config);
e64b020b 939 if (err) {
ffeb883e
HK
940 char *pmu_term = pmu_formats_string(formats);
941
e64b020b
JO
942 err->idx = term->err_term;
943 err->str = strdup("unknown term");
ffeb883e
HK
944 err->help = parse_events_formats_error_string(pmu_term);
945 free(pmu_term);
e64b020b 946 }
cd82a32e 947 return -EINVAL;
688d4dfc 948 }
cd82a32e
JO
949
950 switch (format->value) {
951 case PERF_PMU_FORMAT_VALUE_CONFIG:
952 vp = &attr->config;
953 break;
954 case PERF_PMU_FORMAT_VALUE_CONFIG1:
955 vp = &attr->config1;
956 break;
957 case PERF_PMU_FORMAT_VALUE_CONFIG2:
958 vp = &attr->config2;
959 break;
960 default:
961 return -EINVAL;
962 }
963
16fa7e82 964 /*
688d4dfc
CS
965 * Either directly use a numeric term, or try to translate string terms
966 * using event parameters.
16fa7e82 967 */
99e7138e
JO
968 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
969 if (term->no_value &&
970 bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) {
971 if (err) {
972 err->idx = term->err_val;
973 err->str = strdup("no value assigned for term");
974 }
975 return -EINVAL;
976 }
977
688d4dfc 978 val = term->val.num;
99e7138e 979 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
688d4dfc 980 if (strcmp(term->val.str, "?")) {
bb963e16 981 if (verbose > 0) {
688d4dfc
CS
982 pr_info("Invalid sysfs entry %s=%s\n",
983 term->config, term->val.str);
e64b020b
JO
984 }
985 if (err) {
986 err->idx = term->err_val;
987 err->str = strdup("expected numeric value");
988 }
688d4dfc
CS
989 return -EINVAL;
990 }
991
992 if (pmu_resolve_param_term(term, head_terms, &val))
993 return -EINVAL;
994 } else
995 return -EINVAL;
996
0efe6b67
AH
997 max_val = pmu_format_max_value(format->bits);
998 if (val > max_val) {
999 if (err) {
1000 err->idx = term->err_val;
1001 if (asprintf(&err->str,
1002 "value too big for format, maximum is %llu",
1003 (unsigned long long)max_val) < 0)
1004 err->str = strdup("value too big for format");
1005 return -EINVAL;
1006 }
1007 /*
1008 * Assume we don't care if !err, in which case the value will be
1009 * silently truncated.
1010 */
1011 }
1012
688d4dfc 1013 pmu_format_value(format->bits, val, vp, zero);
cd82a32e
JO
1014 return 0;
1015}
1016
cff7f956
JO
1017int perf_pmu__config_terms(struct list_head *formats,
1018 struct perf_event_attr *attr,
dc0a6202 1019 struct list_head *head_terms,
e64b020b 1020 bool zero, struct parse_events_error *err)
cd82a32e 1021{
6cee6cd3 1022 struct parse_events_term *term;
cd82a32e 1023
688d4dfc 1024 list_for_each_entry(term, head_terms, list) {
e64b020b
JO
1025 if (pmu_config_term(formats, attr, term, head_terms,
1026 zero, err))
cd82a32e 1027 return -EINVAL;
688d4dfc 1028 }
cd82a32e
JO
1029
1030 return 0;
1031}
1032
1033/*
1034 * Configures event's 'attr' parameter based on the:
1035 * 1) users input - specified in terms parameter
1036 * 2) pmu format definitions - specified by pmu parameter
1037 */
1038int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
e64b020b
JO
1039 struct list_head *head_terms,
1040 struct parse_events_error *err)
cd82a32e 1041{
dc0a6202
AH
1042 bool zero = !!pmu->default_config;
1043
cd82a32e 1044 attr->type = pmu->type;
e64b020b
JO
1045 return perf_pmu__config_terms(&pmu->format, attr, head_terms,
1046 zero, err);
cd82a32e
JO
1047}
1048
5c6ccc37
ACM
1049static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
1050 struct parse_events_term *term)
a6146d50 1051{
5c6ccc37 1052 struct perf_pmu_alias *alias;
a6146d50
ZY
1053 char *name;
1054
1055 if (parse_events__is_hardcoded_term(term))
1056 return NULL;
1057
1058 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
1059 if (term->val.num != 1)
1060 return NULL;
1061 if (pmu_find_format(&pmu->format, term->config))
1062 return NULL;
1063 name = term->config;
1064 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
1065 if (strcasecmp(term->config, "event"))
1066 return NULL;
1067 name = term->val.str;
1068 } else {
1069 return NULL;
1070 }
1071
1072 list_for_each_entry(alias, &pmu->aliases, list) {
1073 if (!strcasecmp(alias->name, name))
1074 return alias;
1075 }
1076 return NULL;
1077}
1078
410136f5 1079
1d9e446b
JO
1080static int check_info_data(struct perf_pmu_alias *alias,
1081 struct perf_pmu_info *info)
410136f5
SE
1082{
1083 /*
1084 * Only one term in event definition can
1d9e446b
JO
1085 * define unit, scale and snapshot, fail
1086 * if there's more than one.
410136f5 1087 */
b30a7d1f 1088 if ((info->unit && alias->unit[0]) ||
1d9e446b
JO
1089 (info->scale && alias->scale) ||
1090 (info->snapshot && alias->snapshot))
410136f5
SE
1091 return -EINVAL;
1092
b30a7d1f 1093 if (alias->unit[0])
1d9e446b 1094 info->unit = alias->unit;
410136f5
SE
1095
1096 if (alias->scale)
1d9e446b
JO
1097 info->scale = alias->scale;
1098
1099 if (alias->snapshot)
1100 info->snapshot = alias->snapshot;
410136f5
SE
1101
1102 return 0;
1103}
1104
a6146d50
ZY
1105/*
1106 * Find alias in the terms list and replace it with the terms
1107 * defined for the alias
1108 */
410136f5 1109int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
46441bdc 1110 struct perf_pmu_info *info)
a6146d50 1111{
6cee6cd3 1112 struct parse_events_term *term, *h;
5c6ccc37 1113 struct perf_pmu_alias *alias;
a6146d50
ZY
1114 int ret;
1115
044330c1
MF
1116 info->per_pkg = false;
1117
8a398897
SE
1118 /*
1119 * Mark unit and scale as not set
1120 * (different from default values, see below)
1121 */
1d9e446b
JO
1122 info->unit = NULL;
1123 info->scale = 0.0;
1124 info->snapshot = false;
37932c18 1125 info->metric_expr = NULL;
96284814 1126 info->metric_name = NULL;
410136f5 1127
a6146d50
ZY
1128 list_for_each_entry_safe(term, h, head_terms, list) {
1129 alias = pmu_find_alias(pmu, term);
1130 if (!alias)
1131 continue;
1132 ret = pmu_alias_terms(alias, &term->list);
1133 if (ret)
1134 return ret;
410136f5 1135
1d9e446b 1136 ret = check_info_data(alias, info);
410136f5
SE
1137 if (ret)
1138 return ret;
1139
044330c1
MF
1140 if (alias->per_pkg)
1141 info->per_pkg = true;
37932c18 1142 info->metric_expr = alias->metric_expr;
96284814 1143 info->metric_name = alias->metric_name;
044330c1 1144
a6146d50
ZY
1145 list_del(&term->list);
1146 free(term);
1147 }
8a398897
SE
1148
1149 /*
1150 * if no unit or scale foundin aliases, then
1151 * set defaults as for evsel
1152 * unit cannot left to NULL
1153 */
46441bdc
MF
1154 if (info->unit == NULL)
1155 info->unit = "";
8a398897 1156
46441bdc
MF
1157 if (info->scale == 0.0)
1158 info->scale = 1.0;
8a398897 1159
a6146d50
ZY
1160 return 0;
1161}
1162
cd82a32e
JO
1163int perf_pmu__new_format(struct list_head *list, char *name,
1164 int config, unsigned long *bits)
1165{
5c6ccc37 1166 struct perf_pmu_format *format;
cd82a32e
JO
1167
1168 format = zalloc(sizeof(*format));
1169 if (!format)
1170 return -ENOMEM;
1171
1172 format->name = strdup(name);
1173 format->value = config;
1174 memcpy(format->bits, bits, sizeof(format->bits));
1175
1176 list_add_tail(&format->list, list);
1177 return 0;
1178}
1179
1180void perf_pmu__set_format(unsigned long *bits, long from, long to)
1181{
1182 long b;
1183
1184 if (!to)
1185 to = from;
1186
15268138 1187 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
cd82a32e
JO
1188 for (b = from; b <= to; b++)
1189 set_bit(b, bits);
1190}
dc098b35 1191
aaea3617
CS
1192static int sub_non_neg(int a, int b)
1193{
1194 if (b > a)
1195 return 0;
1196 return a - b;
1197}
1198
dc098b35
AK
1199static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
1200 struct perf_pmu_alias *alias)
1201{
aaea3617
CS
1202 struct parse_events_term *term;
1203 int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
1204
1205 list_for_each_entry(term, &alias->terms, list) {
1206 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
1207 used += snprintf(buf + used, sub_non_neg(len, used),
1208 ",%s=%s", term->config,
1209 term->val.str);
1210 }
1211
1212 if (sub_non_neg(len, used) > 0) {
1213 buf[used] = '/';
1214 used++;
1215 }
1216 if (sub_non_neg(len, used) > 0) {
1217 buf[used] = '\0';
1218 used++;
1219 } else
1220 buf[len - 1] = '\0';
1221
dc098b35
AK
1222 return buf;
1223}
1224
1225static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
1226 struct perf_pmu_alias *alias)
1227{
1228 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
1229 return buf;
1230}
1231
dd5f1036 1232struct sevent {
08e60ed1
AK
1233 char *name;
1234 char *desc;
dd5f1036 1235 char *topic;
f2361024
AK
1236 char *str;
1237 char *pmu;
7f372a63 1238 char *metric_expr;
96284814 1239 char *metric_name;
08e60ed1
AK
1240};
1241
dd5f1036 1242static int cmp_sevent(const void *a, const void *b)
08e60ed1 1243{
dd5f1036
AK
1244 const struct sevent *as = a;
1245 const struct sevent *bs = b;
08e60ed1
AK
1246
1247 /* Put extra events last */
1248 if (!!as->desc != !!bs->desc)
1249 return !!as->desc - !!bs->desc;
dd5f1036
AK
1250 if (as->topic && bs->topic) {
1251 int n = strcmp(as->topic, bs->topic);
1252
1253 if (n)
1254 return n;
1255 }
08e60ed1
AK
1256 return strcmp(as->name, bs->name);
1257}
1258
1259static void wordwrap(char *s, int start, int max, int corr)
dc098b35 1260{
08e60ed1
AK
1261 int column = start;
1262 int n;
1263
1264 while (*s) {
1265 int wlen = strcspn(s, " \t");
1266
1267 if (column + wlen >= max && column > start) {
1268 printf("\n%*s", start, "");
1269 column = start + corr;
1270 }
1271 n = printf("%s%.*s", column > start ? " " : "", wlen, s);
1272 if (n <= 0)
1273 break;
1274 s += wlen;
1275 column += n;
aa4beb10 1276 s = ltrim(s);
08e60ed1 1277 }
dc098b35
AK
1278}
1279
c8d6828a 1280void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
bf874fcf 1281 bool long_desc, bool details_flag)
dc098b35
AK
1282{
1283 struct perf_pmu *pmu;
1284 struct perf_pmu_alias *alias;
1285 char buf[1024];
1286 int printed = 0;
1287 int len, j;
dd5f1036 1288 struct sevent *aliases;
08e60ed1 1289 int numdesc = 0;
61eb2eb4 1290 int columns = pager_get_columns();
dd5f1036 1291 char *topic = NULL;
dc098b35
AK
1292
1293 pmu = NULL;
1294 len = 0;
42634bc7 1295 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
dc098b35
AK
1296 list_for_each_entry(alias, &pmu->aliases, list)
1297 len++;
42634bc7
AH
1298 if (pmu->selectable)
1299 len++;
1300 }
dd5f1036 1301 aliases = zalloc(sizeof(struct sevent) * len);
dc098b35 1302 if (!aliases)
7e4772dc 1303 goto out_enomem;
dc098b35
AK
1304 pmu = NULL;
1305 j = 0;
42634bc7 1306 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
dc098b35 1307 list_for_each_entry(alias, &pmu->aliases, list) {
08e60ed1
AK
1308 char *name = alias->desc ? alias->name :
1309 format_alias(buf, sizeof(buf), pmu, alias);
dc098b35
AK
1310 bool is_cpu = !strcmp(pmu->name, "cpu");
1311
1312 if (event_glob != NULL &&
38d14f0c
AK
1313 !(strglobmatch_nocase(name, event_glob) ||
1314 (!is_cpu && strglobmatch_nocase(alias->name,
67bdc35f
AK
1315 event_glob)) ||
1316 (alias->topic &&
1317 strglobmatch_nocase(alias->topic, event_glob))))
dc098b35 1318 continue;
7e4772dc 1319
08e60ed1 1320 if (is_cpu && !name_only && !alias->desc)
7e4772dc
ACM
1321 name = format_alias_or(buf, sizeof(buf), pmu, alias);
1322
08e60ed1
AK
1323 aliases[j].name = name;
1324 if (is_cpu && !name_only && !alias->desc)
1325 aliases[j].name = format_alias_or(buf,
1326 sizeof(buf),
1327 pmu, alias);
1328 aliases[j].name = strdup(aliases[j].name);
1329 if (!aliases[j].name)
7e4772dc 1330 goto out_enomem;
08e60ed1 1331
c8d6828a
SB
1332 aliases[j].desc = long_desc ? alias->long_desc :
1333 alias->desc;
dd5f1036 1334 aliases[j].topic = alias->topic;
f2361024
AK
1335 aliases[j].str = alias->str;
1336 aliases[j].pmu = pmu->name;
7f372a63 1337 aliases[j].metric_expr = alias->metric_expr;
96284814 1338 aliases[j].metric_name = alias->metric_name;
dc098b35
AK
1339 j++;
1340 }
fa52ceab
ACM
1341 if (pmu->selectable &&
1342 (event_glob == NULL || strglobmatch(pmu->name, event_glob))) {
7e4772dc
ACM
1343 char *s;
1344 if (asprintf(&s, "%s//", pmu->name) < 0)
1345 goto out_enomem;
08e60ed1 1346 aliases[j].name = s;
42634bc7
AH
1347 j++;
1348 }
1349 }
dc098b35 1350 len = j;
dd5f1036 1351 qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
dc098b35 1352 for (j = 0; j < len; j++) {
15b22ed3
AK
1353 /* Skip duplicates */
1354 if (j > 0 && !strcmp(aliases[j].name, aliases[j - 1].name))
1355 continue;
dc098b35 1356 if (name_only) {
08e60ed1 1357 printf("%s ", aliases[j].name);
dc098b35
AK
1358 continue;
1359 }
1c5f01fe 1360 if (aliases[j].desc && !quiet_flag) {
08e60ed1
AK
1361 if (numdesc++ == 0)
1362 printf("\n");
dd5f1036
AK
1363 if (aliases[j].topic && (!topic ||
1364 strcmp(topic, aliases[j].topic))) {
1365 printf("%s%s:\n", topic ? "\n" : "",
1366 aliases[j].topic);
1367 topic = aliases[j].topic;
1368 }
08e60ed1
AK
1369 printf(" %-50s\n", aliases[j].name);
1370 printf("%*s", 8, "[");
1371 wordwrap(aliases[j].desc, 8, columns, 0);
1372 printf("]\n");
bf874fcf 1373 if (details_flag) {
7f372a63 1374 printf("%*s%s/%s/ ", 8, "", aliases[j].pmu, aliases[j].str);
96284814
AK
1375 if (aliases[j].metric_name)
1376 printf(" MetricName: %s", aliases[j].metric_name);
7f372a63
AK
1377 if (aliases[j].metric_expr)
1378 printf(" MetricExpr: %s", aliases[j].metric_expr);
1379 putchar('\n');
1380 }
08e60ed1
AK
1381 } else
1382 printf(" %-50s [Kernel PMU event]\n", aliases[j].name);
dc098b35
AK
1383 printed++;
1384 }
dfc431cb 1385 if (printed && pager_in_use())
dc098b35 1386 printf("\n");
7e4772dc
ACM
1387out_free:
1388 for (j = 0; j < len; j++)
08e60ed1 1389 zfree(&aliases[j].name);
7e4772dc
ACM
1390 zfree(&aliases);
1391 return;
1392
1393out_enomem:
1394 printf("FATAL: not enough memory to print PMU events\n");
1395 if (aliases)
1396 goto out_free;
dc098b35 1397}
4cabc3d1
AK
1398
1399bool pmu_have_event(const char *pname, const char *name)
1400{
1401 struct perf_pmu *pmu;
1402 struct perf_pmu_alias *alias;
1403
1404 pmu = NULL;
1405 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1406 if (strcmp(pname, pmu->name))
1407 continue;
1408 list_for_each_entry(alias, &pmu->aliases, list)
1409 if (!strcmp(alias->name, name))
1410 return true;
1411 }
1412 return false;
1413}
7d4bdab5
AH
1414
1415static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
1416{
1417 struct stat st;
1418 char path[PATH_MAX];
1419 const char *sysfs;
1420
1421 sysfs = sysfs__mountpoint();
1422 if (!sysfs)
1423 return NULL;
1424
1425 snprintf(path, PATH_MAX,
1426 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
1427
1428 if (stat(path, &st) < 0)
1429 return NULL;
1430
1431 return fopen(path, "r");
1432}
1433
1434int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
1435 ...)
1436{
1437 va_list args;
1438 FILE *file;
1439 int ret = EOF;
1440
1441 va_start(args, fmt);
1442 file = perf_pmu__open_file(pmu, name);
1443 if (file) {
1444 ret = vfscanf(file, fmt, args);
1445 fclose(file);
1446 }
1447 va_end(args);
1448 return ret;
1449}