blob: 10668b7f5272fa9d1b2497dead79fcc48a9555d8 [file] [log] [blame]
Jiri Olsacd82a322012-03-15 20:09:17 +01001#include <linux/list.h>
Sukadev Bhattiproluc5de47f2015-06-10 00:25:07 -07002#include <linux/compiler.h>
Jiri Olsacd82a322012-03-15 20:09:17 +01003#include <sys/types.h>
Jiri Olsacd82a322012-03-15 20:09:17 +01004#include <unistd.h>
5#include <stdio.h>
Adrian Hunterdc0a6202014-07-31 09:00:49 +03006#include <stdbool.h>
Adrian Hunter7d4bdab2014-07-31 09:00:50 +03007#include <stdarg.h>
Jiri Olsacd82a322012-03-15 20:09:17 +01008#include <dirent.h>
Borislav Petkovcd0cfad2013-12-09 17:14:24 +01009#include <api/fs/fs.h>
Stephane Eranian410136f2013-11-12 17:58:49 +010010#include <locale.h>
Jiri Olsacd82a322012-03-15 20:09:17 +010011#include "util.h"
12#include "pmu.h"
13#include "parse-events.h"
Yan, Zheng7ae92e72012-09-10 15:53:50 +080014#include "cpumap.h"
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -070015#include "header.h"
16#include "pmu-events/pmu-events.h"
Jiri Olsacd82a322012-03-15 20:09:17 +010017
Arnaldo Carvalho de Meloab1bf6532013-01-18 17:05:09 -030018struct perf_pmu_format {
19 char *name;
20 int value;
21 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
22 struct list_head list;
23};
24
Robert Richter50a96672012-08-16 21:10:24 +020025#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
26
Jiri Olsacd82a322012-03-15 20:09:17 +010027int perf_pmu_parse(struct list_head *list, char *name);
28extern FILE *perf_pmu_in;
29
30static LIST_HEAD(pmus);
31
32/*
33 * Parse & process all the sysfs attributes located under
34 * the directory specified in 'dir' parameter.
35 */
Jiri Olsacff7f952012-11-10 01:46:50 +010036int perf_pmu__format_parse(char *dir, struct list_head *head)
Jiri Olsacd82a322012-03-15 20:09:17 +010037{
38 struct dirent *evt_ent;
39 DIR *format_dir;
40 int ret = 0;
41
42 format_dir = opendir(dir);
43 if (!format_dir)
44 return -EINVAL;
45
46 while (!ret && (evt_ent = readdir(format_dir))) {
47 char path[PATH_MAX];
48 char *name = evt_ent->d_name;
49 FILE *file;
50
51 if (!strcmp(name, ".") || !strcmp(name, ".."))
52 continue;
53
54 snprintf(path, PATH_MAX, "%s/%s", dir, name);
55
56 ret = -EINVAL;
57 file = fopen(path, "r");
58 if (!file)
59 break;
60
61 perf_pmu_in = file;
62 ret = perf_pmu_parse(head, name);
63 fclose(file);
64 }
65
66 closedir(format_dir);
67 return ret;
68}
69
70/*
71 * Reading/parsing the default pmu format definition, which should be
72 * located at:
73 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
74 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +030075static int pmu_format(const char *name, struct list_head *format)
Jiri Olsacd82a322012-03-15 20:09:17 +010076{
77 struct stat st;
78 char path[PATH_MAX];
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -030079 const char *sysfs = sysfs__mountpoint();
Jiri Olsacd82a322012-03-15 20:09:17 +010080
Jiri Olsacd82a322012-03-15 20:09:17 +010081 if (!sysfs)
82 return -1;
83
84 snprintf(path, PATH_MAX,
Robert Richter50a96672012-08-16 21:10:24 +020085 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
Jiri Olsacd82a322012-03-15 20:09:17 +010086
87 if (stat(path, &st) < 0)
Robert Richter9bc8f9f2012-06-14 22:38:37 +020088 return 0; /* no error if format does not exist */
Jiri Olsacd82a322012-03-15 20:09:17 +010089
Jiri Olsacff7f952012-11-10 01:46:50 +010090 if (perf_pmu__format_parse(path, format))
Jiri Olsacd82a322012-03-15 20:09:17 +010091 return -1;
92
93 return 0;
94}
95
Stephane Eranian410136f2013-11-12 17:58:49 +010096static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
97{
98 struct stat st;
99 ssize_t sret;
100 char scale[128];
101 int fd, ret = -1;
102 char path[PATH_MAX];
Jiri Olsaea8f75f2016-03-08 19:42:30 +0100103 char *lc;
Stephane Eranian410136f2013-11-12 17:58:49 +0100104
105 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
106
107 fd = open(path, O_RDONLY);
108 if (fd == -1)
109 return -1;
110
111 if (fstat(fd, &st) < 0)
112 goto error;
113
114 sret = read(fd, scale, sizeof(scale)-1);
115 if (sret < 0)
116 goto error;
117
Madhavan Srinivasan9ecae062015-05-31 11:36:23 +0530118 if (scale[sret - 1] == '\n')
119 scale[sret - 1] = '\0';
120 else
121 scale[sret] = '\0';
122
Stephane Eranian410136f2013-11-12 17:58:49 +0100123 /*
124 * save current locale
125 */
126 lc = setlocale(LC_NUMERIC, NULL);
127
128 /*
Jiri Olsaf9a59782016-03-03 10:53:48 +0100129 * The lc string may be allocated in static storage,
130 * so get a dynamic copy to make it survive setlocale
131 * call below.
132 */
133 lc = strdup(lc);
134 if (!lc) {
135 ret = -ENOMEM;
136 goto error;
137 }
138
139 /*
Stephane Eranian410136f2013-11-12 17:58:49 +0100140 * force to C locale to ensure kernel
141 * scale string is converted correctly.
142 * kernel uses default C locale.
143 */
144 setlocale(LC_NUMERIC, "C");
145
146 alias->scale = strtod(scale, NULL);
147
148 /* restore locale */
149 setlocale(LC_NUMERIC, lc);
150
Jiri Olsaea8f75f2016-03-08 19:42:30 +0100151 free(lc);
Jiri Olsaf9a59782016-03-03 10:53:48 +0100152
Stephane Eranian410136f2013-11-12 17:58:49 +0100153 ret = 0;
154error:
155 close(fd);
156 return ret;
157}
158
159static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
160{
161 char path[PATH_MAX];
162 ssize_t sret;
163 int fd;
164
165 snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
166
167 fd = open(path, O_RDONLY);
168 if (fd == -1)
169 return -1;
170
Markus Trippelsdorfd85ce832015-12-14 16:44:40 +0100171 sret = read(fd, alias->unit, UNIT_MAX_LEN);
Stephane Eranian410136f2013-11-12 17:58:49 +0100172 if (sret < 0)
173 goto error;
174
175 close(fd);
176
Madhavan Srinivasan9ecae062015-05-31 11:36:23 +0530177 if (alias->unit[sret - 1] == '\n')
178 alias->unit[sret - 1] = '\0';
179 else
180 alias->unit[sret] = '\0';
Stephane Eranian410136f2013-11-12 17:58:49 +0100181
182 return 0;
183error:
184 close(fd);
185 alias->unit[0] = '\0';
186 return -1;
187}
188
Matt Fleming044330c2014-11-21 10:31:12 +0100189static int
190perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
191{
192 char path[PATH_MAX];
193 int fd;
194
195 snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
196
197 fd = open(path, O_RDONLY);
198 if (fd == -1)
199 return -1;
200
201 close(fd);
202
203 alias->per_pkg = true;
204 return 0;
205}
206
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100207static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
208 char *dir, char *name)
209{
210 char path[PATH_MAX];
211 int fd;
212
213 snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
214
215 fd = open(path, O_RDONLY);
216 if (fd == -1)
217 return -1;
218
219 alias->snapshot = true;
220 close(fd);
221 return 0;
222}
223
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700224static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
225 char *desc __maybe_unused, char *val)
Zheng Yana6146d52012-06-15 14:31:41 +0800226{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300227 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800228 int ret;
229
Zheng Yana6146d52012-06-15 14:31:41 +0800230 alias = malloc(sizeof(*alias));
231 if (!alias)
232 return -ENOMEM;
233
234 INIT_LIST_HEAD(&alias->terms);
Stephane Eranian410136f2013-11-12 17:58:49 +0100235 alias->scale = 1.0;
236 alias->unit[0] = '\0';
Matt Fleming044330c2014-11-21 10:31:12 +0100237 alias->per_pkg = false;
Stephane Eranian84530922016-01-06 19:50:01 +0100238 alias->snapshot = false;
Stephane Eranian410136f2013-11-12 17:58:49 +0100239
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700240 ret = parse_events_terms(&alias->terms, val);
Zheng Yana6146d52012-06-15 14:31:41 +0800241 if (ret) {
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700242 pr_err("Cannot parse alias %s: %d\n", val, ret);
Zheng Yana6146d52012-06-15 14:31:41 +0800243 free(alias);
244 return ret;
245 }
246
247 alias->name = strdup(name);
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700248 if (dir) {
249 /*
250 * load unit name and scale if available
251 */
252 perf_pmu__parse_unit(alias, dir, name);
253 perf_pmu__parse_scale(alias, dir, name);
254 perf_pmu__parse_per_pkg(alias, dir, name);
255 perf_pmu__parse_snapshot(alias, dir, name);
256 }
Stephane Eranian410136f2013-11-12 17:58:49 +0100257
Zheng Yana6146d52012-06-15 14:31:41 +0800258 list_add_tail(&alias->list, list);
Stephane Eranian410136f2013-11-12 17:58:49 +0100259
Zheng Yana6146d52012-06-15 14:31:41 +0800260 return 0;
261}
262
Sukadev Bhattiprolu70c646e2015-06-10 00:25:08 -0700263static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
264{
265 char buf[256];
266 int ret;
267
268 ret = fread(buf, 1, sizeof(buf), file);
269 if (ret == 0)
270 return -EINVAL;
271
272 buf[ret] = 0;
273
274 return __perf_pmu__new_alias(list, dir, name, NULL, buf);
275}
276
Matt Fleming46441bd2014-09-24 15:04:06 +0100277static inline bool pmu_alias_info_file(char *name)
278{
279 size_t len;
280
281 len = strlen(name);
282 if (len > 5 && !strcmp(name + len - 5, ".unit"))
283 return true;
284 if (len > 6 && !strcmp(name + len - 6, ".scale"))
285 return true;
Matt Fleming044330c2014-11-21 10:31:12 +0100286 if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
287 return true;
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100288 if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
289 return true;
Matt Fleming46441bd2014-09-24 15:04:06 +0100290
291 return false;
292}
293
Zheng Yana6146d52012-06-15 14:31:41 +0800294/*
295 * Process all the sysfs attributes located under the directory
296 * specified in 'dir' parameter.
297 */
298static int pmu_aliases_parse(char *dir, struct list_head *head)
299{
300 struct dirent *evt_ent;
301 DIR *event_dir;
Zheng Yana6146d52012-06-15 14:31:41 +0800302
303 event_dir = opendir(dir);
304 if (!event_dir)
305 return -EINVAL;
306
Andi Kleen940db6d2016-02-17 14:44:55 -0800307 while ((evt_ent = readdir(event_dir))) {
Zheng Yana6146d52012-06-15 14:31:41 +0800308 char path[PATH_MAX];
309 char *name = evt_ent->d_name;
310 FILE *file;
311
312 if (!strcmp(name, ".") || !strcmp(name, ".."))
313 continue;
314
Stephane Eranian410136f2013-11-12 17:58:49 +0100315 /*
Matt Fleming46441bd2014-09-24 15:04:06 +0100316 * skip info files parsed in perf_pmu__new_alias()
Stephane Eranian410136f2013-11-12 17:58:49 +0100317 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100318 if (pmu_alias_info_file(name))
Stephane Eranian410136f2013-11-12 17:58:49 +0100319 continue;
320
Zheng Yana6146d52012-06-15 14:31:41 +0800321 snprintf(path, PATH_MAX, "%s/%s", dir, name);
322
Zheng Yana6146d52012-06-15 14:31:41 +0800323 file = fopen(path, "r");
Andi Kleen940db6d2016-02-17 14:44:55 -0800324 if (!file) {
325 pr_debug("Cannot open %s\n", path);
326 continue;
327 }
Stephane Eranian410136f2013-11-12 17:58:49 +0100328
Andi Kleen940db6d2016-02-17 14:44:55 -0800329 if (perf_pmu__new_alias(head, dir, name, file) < 0)
330 pr_debug("Cannot set up %s\n", name);
Zheng Yana6146d52012-06-15 14:31:41 +0800331 fclose(file);
332 }
333
334 closedir(event_dir);
Andi Kleen940db6d2016-02-17 14:44:55 -0800335 return 0;
Zheng Yana6146d52012-06-15 14:31:41 +0800336}
337
338/*
339 * Reading the pmu event aliases definition, which should be located at:
340 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
341 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300342static int pmu_aliases(const char *name, struct list_head *head)
Zheng Yana6146d52012-06-15 14:31:41 +0800343{
344 struct stat st;
345 char path[PATH_MAX];
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300346 const char *sysfs = sysfs__mountpoint();
Zheng Yana6146d52012-06-15 14:31:41 +0800347
Zheng Yana6146d52012-06-15 14:31:41 +0800348 if (!sysfs)
349 return -1;
350
351 snprintf(path, PATH_MAX,
352 "%s/bus/event_source/devices/%s/events", sysfs, name);
353
354 if (stat(path, &st) < 0)
Jiri Olsa3fded962012-10-10 14:53:16 +0200355 return 0; /* no error if 'events' does not exist */
Zheng Yana6146d52012-06-15 14:31:41 +0800356
357 if (pmu_aliases_parse(path, head))
358 return -1;
359
360 return 0;
361}
362
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300363static int pmu_alias_terms(struct perf_pmu_alias *alias,
Zheng Yana6146d52012-06-15 14:31:41 +0800364 struct list_head *terms)
365{
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200366 struct parse_events_term *term, *cloned;
Zheng Yana6146d52012-06-15 14:31:41 +0800367 LIST_HEAD(list);
368 int ret;
369
370 list_for_each_entry(term, &alias->terms, list) {
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200371 ret = parse_events_term__clone(&cloned, term);
Zheng Yana6146d52012-06-15 14:31:41 +0800372 if (ret) {
Arnaldo Carvalho de Melo682dc242016-02-12 16:48:00 -0300373 parse_events_terms__purge(&list);
Zheng Yana6146d52012-06-15 14:31:41 +0800374 return ret;
375 }
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200376 list_add_tail(&cloned->list, &list);
Zheng Yana6146d52012-06-15 14:31:41 +0800377 }
378 list_splice(&list, terms);
379 return 0;
380}
381
Jiri Olsacd82a322012-03-15 20:09:17 +0100382/*
383 * Reading/parsing the default pmu type value, which should be
384 * located at:
385 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
386 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300387static int pmu_type(const char *name, __u32 *type)
Jiri Olsacd82a322012-03-15 20:09:17 +0100388{
389 struct stat st;
390 char path[PATH_MAX];
Jiri Olsacd82a322012-03-15 20:09:17 +0100391 FILE *file;
392 int ret = 0;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300393 const char *sysfs = sysfs__mountpoint();
Jiri Olsacd82a322012-03-15 20:09:17 +0100394
Jiri Olsacd82a322012-03-15 20:09:17 +0100395 if (!sysfs)
396 return -1;
397
398 snprintf(path, PATH_MAX,
Robert Richter50a96672012-08-16 21:10:24 +0200399 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
Jiri Olsacd82a322012-03-15 20:09:17 +0100400
401 if (stat(path, &st) < 0)
402 return -1;
403
404 file = fopen(path, "r");
405 if (!file)
406 return -EINVAL;
407
408 if (1 != fscanf(file, "%u", type))
409 ret = -1;
410
411 fclose(file);
412 return ret;
413}
414
Robert Richter50a96672012-08-16 21:10:24 +0200415/* Add all pmus in sysfs to pmu list: */
416static void pmu_read_sysfs(void)
417{
418 char path[PATH_MAX];
Robert Richter50a96672012-08-16 21:10:24 +0200419 DIR *dir;
420 struct dirent *dent;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300421 const char *sysfs = sysfs__mountpoint();
Robert Richter50a96672012-08-16 21:10:24 +0200422
Robert Richter50a96672012-08-16 21:10:24 +0200423 if (!sysfs)
424 return;
425
426 snprintf(path, PATH_MAX,
427 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
428
429 dir = opendir(path);
430 if (!dir)
431 return;
432
433 while ((dent = readdir(dir))) {
434 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
435 continue;
436 /* add to static LIST_HEAD(pmus): */
437 perf_pmu__find(dent->d_name);
438 }
439
440 closedir(dir);
441}
442
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300443static struct cpu_map *pmu_cpumask(const char *name)
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800444{
445 struct stat st;
446 char path[PATH_MAX];
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800447 FILE *file;
448 struct cpu_map *cpus;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300449 const char *sysfs = sysfs__mountpoint();
Mark Rutland7e3fcffe2016-09-08 11:21:52 +0100450 const char *templates[] = {
451 "%s/bus/event_source/devices/%s/cpumask",
452 "%s/bus/event_source/devices/%s/cpus",
453 NULL
454 };
455 const char **template;
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800456
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800457 if (!sysfs)
458 return NULL;
459
Mark Rutland7e3fcffe2016-09-08 11:21:52 +0100460 for (template = templates; *template; template++) {
461 snprintf(path, PATH_MAX, *template, sysfs, name);
462 if (stat(path, &st) == 0)
463 break;
464 }
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800465
Mark Rutland7e3fcffe2016-09-08 11:21:52 +0100466 if (!*template)
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800467 return NULL;
468
469 file = fopen(path, "r");
470 if (!file)
471 return NULL;
472
473 cpus = cpu_map__read(file);
474 fclose(file);
475 return cpus;
476}
477
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -0700478/*
479 * Return the CPU id as a raw string.
480 *
481 * Each architecture should provide a more precise id string that
482 * can be use to match the architecture's "mapfile".
483 */
484char * __weak get_cpuid_str(void)
485{
486 return NULL;
487}
488
489/*
490 * From the pmu_events_map, find the table of PMU events that corresponds
491 * to the current running CPU. Then, add all PMU events from that table
492 * as aliases.
493 */
494static void pmu_add_cpu_aliases(struct list_head *head)
495{
496 int i;
497 struct pmu_events_map *map;
498 struct pmu_event *pe;
499 char *cpuid;
500
501 cpuid = get_cpuid_str();
502 if (!cpuid)
503 return;
504
505 i = 0;
506 while (1) {
507 map = &pmu_events_map[i++];
508 if (!map->table)
509 goto out;
510
511 if (!strcmp(map->cpuid, cpuid))
512 break;
513 }
514
515 /*
516 * Found a matching PMU events table. Create aliases
517 */
518 i = 0;
519 while (1) {
520 pe = &map->table[i++];
521 if (!pe->name)
522 break;
523
524 /* need type casts to override 'const' */
525 __perf_pmu__new_alias(head, NULL, (char *)pe->name,
526 (char *)pe->desc, (char *)pe->event);
527 }
528
529out:
530 free(cpuid);
531}
532
Sukadev Bhattiproluc5de47f2015-06-10 00:25:07 -0700533struct perf_event_attr * __weak
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300534perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
535{
536 return NULL;
537}
538
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300539static struct perf_pmu *pmu_lookup(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100540{
541 struct perf_pmu *pmu;
542 LIST_HEAD(format);
Zheng Yana6146d52012-06-15 14:31:41 +0800543 LIST_HEAD(aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100544 __u32 type;
545
546 /*
547 * The pmu data we store & need consists of the pmu
548 * type value and format definitions. Load both right
549 * now.
550 */
551 if (pmu_format(name, &format))
552 return NULL;
553
Jiri Olsa3fded962012-10-10 14:53:16 +0200554 if (pmu_aliases(name, &aliases))
555 return NULL;
556
Sukadev Bhattiprolu933f82f2016-09-15 15:24:40 -0700557 if (!strcmp(name, "cpu"))
558 pmu_add_cpu_aliases(&aliases);
559
Jiri Olsacd82a322012-03-15 20:09:17 +0100560 if (pmu_type(name, &type))
561 return NULL;
562
563 pmu = zalloc(sizeof(*pmu));
564 if (!pmu)
565 return NULL;
566
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800567 pmu->cpus = pmu_cpumask(name);
568
Jiri Olsacd82a322012-03-15 20:09:17 +0100569 INIT_LIST_HEAD(&pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800570 INIT_LIST_HEAD(&pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100571 list_splice(&format, &pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800572 list_splice(&aliases, &pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100573 pmu->name = strdup(name);
574 pmu->type = type;
Robert Richter9bc8f9f2012-06-14 22:38:37 +0200575 list_add_tail(&pmu->list, &pmus);
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300576
577 pmu->default_config = perf_pmu__get_default_config(pmu);
578
Jiri Olsacd82a322012-03-15 20:09:17 +0100579 return pmu;
580}
581
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300582static struct perf_pmu *pmu_find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100583{
584 struct perf_pmu *pmu;
585
586 list_for_each_entry(pmu, &pmus, list)
587 if (!strcmp(pmu->name, name))
588 return pmu;
589
590 return NULL;
591}
592
Robert Richter50a96672012-08-16 21:10:24 +0200593struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
594{
595 /*
596 * pmu iterator: If pmu is NULL, we start at the begin,
597 * otherwise return the next pmu. Returns NULL on end.
598 */
599 if (!pmu) {
600 pmu_read_sysfs();
601 pmu = list_prepare_entry(pmu, &pmus, list);
602 }
603 list_for_each_entry_continue(pmu, &pmus, list)
604 return pmu;
605 return NULL;
606}
607
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300608struct perf_pmu *perf_pmu__find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100609{
610 struct perf_pmu *pmu;
611
612 /*
613 * Once PMU is loaded it stays in the list,
614 * so we keep us from multiple reading/parsing
615 * the pmu format definitions.
616 */
617 pmu = pmu_find(name);
618 if (pmu)
619 return pmu;
620
621 return pmu_lookup(name);
622}
623
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300624static struct perf_pmu_format *
Adrian Hunter09ff6072015-07-17 19:33:49 +0300625pmu_find_format(struct list_head *formats, const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100626{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300627 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100628
629 list_for_each_entry(format, formats, list)
630 if (!strcmp(format->name, name))
631 return format;
632
633 return NULL;
634}
635
Adrian Hunter09ff6072015-07-17 19:33:49 +0300636__u64 perf_pmu__format_bits(struct list_head *formats, const char *name)
637{
638 struct perf_pmu_format *format = pmu_find_format(formats, name);
639 __u64 bits = 0;
640 int fbit;
641
642 if (!format)
643 return 0;
644
645 for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS)
646 bits |= 1ULL << fbit;
647
648 return bits;
649}
650
Jiri Olsacd82a322012-03-15 20:09:17 +0100651/*
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300652 * Sets value based on the format definition (format parameter)
Jiri Olsacd82a322012-03-15 20:09:17 +0100653 * and unformated value (value parameter).
Jiri Olsacd82a322012-03-15 20:09:17 +0100654 */
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300655static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
656 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100657{
658 unsigned long fbit, vbit;
Jiri Olsacd82a322012-03-15 20:09:17 +0100659
660 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
661
662 if (!test_bit(fbit, format))
663 continue;
664
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300665 if (value & (1llu << vbit++))
666 *v |= (1llu << fbit);
667 else if (zero)
668 *v &= ~(1llu << fbit);
Jiri Olsacd82a322012-03-15 20:09:17 +0100669 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100670}
671
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300672static __u64 pmu_format_max_value(const unsigned long *format)
673{
Kan Liangac0e2cd2016-03-30 12:16:15 -0700674 __u64 w = 0;
675 int fbit;
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300676
Kan Liangac0e2cd2016-03-30 12:16:15 -0700677 for_each_set_bit(fbit, format, PERF_PMU_FORMAT_BITS)
678 w |= (1ULL << fbit);
679
680 return w;
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300681}
682
Jiri Olsacd82a322012-03-15 20:09:17 +0100683/*
Cody P Schafer688d4df2015-01-07 17:13:50 -0800684 * Term is a string term, and might be a param-term. Try to look up it's value
685 * in the remaining terms.
686 * - We have a term like "base-or-format-term=param-term",
687 * - We need to find the value supplied for "param-term" (with param-term named
688 * in a config string) later on in the term list.
689 */
690static int pmu_resolve_param_term(struct parse_events_term *term,
691 struct list_head *head_terms,
692 __u64 *value)
693{
694 struct parse_events_term *t;
695
696 list_for_each_entry(t, head_terms, list) {
697 if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
698 if (!strcmp(t->config, term->config)) {
699 t->used = true;
700 *value = t->val.num;
701 return 0;
702 }
703 }
704 }
705
706 if (verbose)
707 printf("Required parameter '%s' not specified\n", term->config);
708
709 return -1;
710}
711
He Kuangffeb8832015-09-28 03:52:14 +0000712static char *pmu_formats_string(struct list_head *formats)
Jiri Olsae64b0202015-04-22 21:10:21 +0200713{
714 struct perf_pmu_format *format;
Masami Hiramatsu11db4e22016-05-10 14:47:44 +0900715 char *str = NULL;
716 struct strbuf buf = STRBUF_INIT;
Jiri Olsae64b0202015-04-22 21:10:21 +0200717 unsigned i = 0;
718
He Kuangffeb8832015-09-28 03:52:14 +0000719 if (!formats)
Jiri Olsae64b0202015-04-22 21:10:21 +0200720 return NULL;
721
722 /* sysfs exported terms */
He Kuangffeb8832015-09-28 03:52:14 +0000723 list_for_each_entry(format, formats, list)
Masami Hiramatsu11db4e22016-05-10 14:47:44 +0900724 if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0)
725 goto error;
Jiri Olsae64b0202015-04-22 21:10:21 +0200726
He Kuangffeb8832015-09-28 03:52:14 +0000727 str = strbuf_detach(&buf, NULL);
Masami Hiramatsu11db4e22016-05-10 14:47:44 +0900728error:
He Kuangffeb8832015-09-28 03:52:14 +0000729 strbuf_release(&buf);
Jiri Olsae64b0202015-04-22 21:10:21 +0200730
Jiri Olsae64b0202015-04-22 21:10:21 +0200731 return str;
Jiri Olsae64b0202015-04-22 21:10:21 +0200732}
733
Cody P Schafer688d4df2015-01-07 17:13:50 -0800734/*
Jiri Olsacd82a322012-03-15 20:09:17 +0100735 * Setup one of config[12] attr members based on the
Cody P Schafer88aca8d2014-01-08 08:43:51 -0800736 * user input data - term parameter.
Jiri Olsacd82a322012-03-15 20:09:17 +0100737 */
738static int pmu_config_term(struct list_head *formats,
739 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300740 struct parse_events_term *term,
Cody P Schafer688d4df2015-01-07 17:13:50 -0800741 struct list_head *head_terms,
Jiri Olsae64b0202015-04-22 21:10:21 +0200742 bool zero, struct parse_events_error *err)
Jiri Olsacd82a322012-03-15 20:09:17 +0100743{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300744 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100745 __u64 *vp;
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300746 __u64 val, max_val;
Jiri Olsacd82a322012-03-15 20:09:17 +0100747
748 /*
Cody P Schafer688d4df2015-01-07 17:13:50 -0800749 * If this is a parameter we've already used for parameterized-eval,
750 * skip it in normal eval.
751 */
752 if (term->used)
753 return 0;
754
755 /*
Jiri Olsacd82a322012-03-15 20:09:17 +0100756 * Hardcoded terms should be already in, so nothing
757 * to be done for them.
758 */
759 if (parse_events__is_hardcoded_term(term))
760 return 0;
761
Jiri Olsacd82a322012-03-15 20:09:17 +0100762 format = pmu_find_format(formats, term->config);
Cody P Schafer688d4df2015-01-07 17:13:50 -0800763 if (!format) {
764 if (verbose)
765 printf("Invalid event/parameter '%s'\n", term->config);
Jiri Olsae64b0202015-04-22 21:10:21 +0200766 if (err) {
He Kuangffeb8832015-09-28 03:52:14 +0000767 char *pmu_term = pmu_formats_string(formats);
768
Jiri Olsae64b0202015-04-22 21:10:21 +0200769 err->idx = term->err_term;
770 err->str = strdup("unknown term");
He Kuangffeb8832015-09-28 03:52:14 +0000771 err->help = parse_events_formats_error_string(pmu_term);
772 free(pmu_term);
Jiri Olsae64b0202015-04-22 21:10:21 +0200773 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100774 return -EINVAL;
Cody P Schafer688d4df2015-01-07 17:13:50 -0800775 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100776
777 switch (format->value) {
778 case PERF_PMU_FORMAT_VALUE_CONFIG:
779 vp = &attr->config;
780 break;
781 case PERF_PMU_FORMAT_VALUE_CONFIG1:
782 vp = &attr->config1;
783 break;
784 case PERF_PMU_FORMAT_VALUE_CONFIG2:
785 vp = &attr->config2;
786 break;
787 default:
788 return -EINVAL;
789 }
790
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200791 /*
Cody P Schafer688d4df2015-01-07 17:13:50 -0800792 * Either directly use a numeric term, or try to translate string terms
793 * using event parameters.
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200794 */
Cody P Schafer688d4df2015-01-07 17:13:50 -0800795 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
796 val = term->val.num;
797 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
798 if (strcmp(term->val.str, "?")) {
Jiri Olsae64b0202015-04-22 21:10:21 +0200799 if (verbose) {
Cody P Schafer688d4df2015-01-07 17:13:50 -0800800 pr_info("Invalid sysfs entry %s=%s\n",
801 term->config, term->val.str);
Jiri Olsae64b0202015-04-22 21:10:21 +0200802 }
803 if (err) {
804 err->idx = term->err_val;
805 err->str = strdup("expected numeric value");
806 }
Cody P Schafer688d4df2015-01-07 17:13:50 -0800807 return -EINVAL;
808 }
809
810 if (pmu_resolve_param_term(term, head_terms, &val))
811 return -EINVAL;
812 } else
813 return -EINVAL;
814
Adrian Hunter0efe6b62015-07-17 19:33:50 +0300815 max_val = pmu_format_max_value(format->bits);
816 if (val > max_val) {
817 if (err) {
818 err->idx = term->err_val;
819 if (asprintf(&err->str,
820 "value too big for format, maximum is %llu",
821 (unsigned long long)max_val) < 0)
822 err->str = strdup("value too big for format");
823 return -EINVAL;
824 }
825 /*
826 * Assume we don't care if !err, in which case the value will be
827 * silently truncated.
828 */
829 }
830
Cody P Schafer688d4df2015-01-07 17:13:50 -0800831 pmu_format_value(format->bits, val, vp, zero);
Jiri Olsacd82a322012-03-15 20:09:17 +0100832 return 0;
833}
834
Jiri Olsacff7f952012-11-10 01:46:50 +0100835int perf_pmu__config_terms(struct list_head *formats,
836 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300837 struct list_head *head_terms,
Jiri Olsae64b0202015-04-22 21:10:21 +0200838 bool zero, struct parse_events_error *err)
Jiri Olsacd82a322012-03-15 20:09:17 +0100839{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300840 struct parse_events_term *term;
Jiri Olsacd82a322012-03-15 20:09:17 +0100841
Cody P Schafer688d4df2015-01-07 17:13:50 -0800842 list_for_each_entry(term, head_terms, list) {
Jiri Olsae64b0202015-04-22 21:10:21 +0200843 if (pmu_config_term(formats, attr, term, head_terms,
844 zero, err))
Jiri Olsacd82a322012-03-15 20:09:17 +0100845 return -EINVAL;
Cody P Schafer688d4df2015-01-07 17:13:50 -0800846 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100847
848 return 0;
849}
850
851/*
852 * Configures event's 'attr' parameter based on the:
853 * 1) users input - specified in terms parameter
854 * 2) pmu format definitions - specified by pmu parameter
855 */
856int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
Jiri Olsae64b0202015-04-22 21:10:21 +0200857 struct list_head *head_terms,
858 struct parse_events_error *err)
Jiri Olsacd82a322012-03-15 20:09:17 +0100859{
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300860 bool zero = !!pmu->default_config;
861
Jiri Olsacd82a322012-03-15 20:09:17 +0100862 attr->type = pmu->type;
Jiri Olsae64b0202015-04-22 21:10:21 +0200863 return perf_pmu__config_terms(&pmu->format, attr, head_terms,
864 zero, err);
Jiri Olsacd82a322012-03-15 20:09:17 +0100865}
866
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300867static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
868 struct parse_events_term *term)
Zheng Yana6146d52012-06-15 14:31:41 +0800869{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300870 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800871 char *name;
872
873 if (parse_events__is_hardcoded_term(term))
874 return NULL;
875
876 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
877 if (term->val.num != 1)
878 return NULL;
879 if (pmu_find_format(&pmu->format, term->config))
880 return NULL;
881 name = term->config;
882 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
883 if (strcasecmp(term->config, "event"))
884 return NULL;
885 name = term->val.str;
886 } else {
887 return NULL;
888 }
889
890 list_for_each_entry(alias, &pmu->aliases, list) {
891 if (!strcasecmp(alias->name, name))
892 return alias;
893 }
894 return NULL;
895}
896
Stephane Eranian410136f2013-11-12 17:58:49 +0100897
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100898static int check_info_data(struct perf_pmu_alias *alias,
899 struct perf_pmu_info *info)
Stephane Eranian410136f2013-11-12 17:58:49 +0100900{
901 /*
902 * Only one term in event definition can
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100903 * define unit, scale and snapshot, fail
904 * if there's more than one.
Stephane Eranian410136f2013-11-12 17:58:49 +0100905 */
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100906 if ((info->unit && alias->unit) ||
907 (info->scale && alias->scale) ||
908 (info->snapshot && alias->snapshot))
Stephane Eranian410136f2013-11-12 17:58:49 +0100909 return -EINVAL;
910
911 if (alias->unit)
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100912 info->unit = alias->unit;
Stephane Eranian410136f2013-11-12 17:58:49 +0100913
914 if (alias->scale)
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100915 info->scale = alias->scale;
916
917 if (alias->snapshot)
918 info->snapshot = alias->snapshot;
Stephane Eranian410136f2013-11-12 17:58:49 +0100919
920 return 0;
921}
922
Zheng Yana6146d52012-06-15 14:31:41 +0800923/*
924 * Find alias in the terms list and replace it with the terms
925 * defined for the alias
926 */
Stephane Eranian410136f2013-11-12 17:58:49 +0100927int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
Matt Fleming46441bd2014-09-24 15:04:06 +0100928 struct perf_pmu_info *info)
Zheng Yana6146d52012-06-15 14:31:41 +0800929{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300930 struct parse_events_term *term, *h;
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300931 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800932 int ret;
933
Matt Fleming044330c2014-11-21 10:31:12 +0100934 info->per_pkg = false;
935
Stephane Eranian8a398892014-01-17 16:34:05 +0100936 /*
937 * Mark unit and scale as not set
938 * (different from default values, see below)
939 */
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100940 info->unit = NULL;
941 info->scale = 0.0;
942 info->snapshot = false;
Stephane Eranian410136f2013-11-12 17:58:49 +0100943
Zheng Yana6146d52012-06-15 14:31:41 +0800944 list_for_each_entry_safe(term, h, head_terms, list) {
945 alias = pmu_find_alias(pmu, term);
946 if (!alias)
947 continue;
948 ret = pmu_alias_terms(alias, &term->list);
949 if (ret)
950 return ret;
Stephane Eranian410136f2013-11-12 17:58:49 +0100951
Jiri Olsa1d9e4462014-11-21 10:31:13 +0100952 ret = check_info_data(alias, info);
Stephane Eranian410136f2013-11-12 17:58:49 +0100953 if (ret)
954 return ret;
955
Matt Fleming044330c2014-11-21 10:31:12 +0100956 if (alias->per_pkg)
957 info->per_pkg = true;
958
Zheng Yana6146d52012-06-15 14:31:41 +0800959 list_del(&term->list);
960 free(term);
961 }
Stephane Eranian8a398892014-01-17 16:34:05 +0100962
963 /*
964 * if no unit or scale foundin aliases, then
965 * set defaults as for evsel
966 * unit cannot left to NULL
967 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100968 if (info->unit == NULL)
969 info->unit = "";
Stephane Eranian8a398892014-01-17 16:34:05 +0100970
Matt Fleming46441bd2014-09-24 15:04:06 +0100971 if (info->scale == 0.0)
972 info->scale = 1.0;
Stephane Eranian8a398892014-01-17 16:34:05 +0100973
Zheng Yana6146d52012-06-15 14:31:41 +0800974 return 0;
975}
976
Jiri Olsacd82a322012-03-15 20:09:17 +0100977int perf_pmu__new_format(struct list_head *list, char *name,
978 int config, unsigned long *bits)
979{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300980 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100981
982 format = zalloc(sizeof(*format));
983 if (!format)
984 return -ENOMEM;
985
986 format->name = strdup(name);
987 format->value = config;
988 memcpy(format->bits, bits, sizeof(format->bits));
989
990 list_add_tail(&format->list, list);
991 return 0;
992}
993
994void perf_pmu__set_format(unsigned long *bits, long from, long to)
995{
996 long b;
997
998 if (!to)
999 to = from;
1000
Sukadev Bhattiprolu15268132013-01-17 09:11:30 -08001001 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
Jiri Olsacd82a322012-03-15 20:09:17 +01001002 for (b = from; b <= to; b++)
1003 set_bit(b, bits);
1004}
Andi Kleendc098b32013-04-20 11:02:29 -07001005
Cody P Schaferaaea3612015-01-07 17:13:51 -08001006static int sub_non_neg(int a, int b)
1007{
1008 if (b > a)
1009 return 0;
1010 return a - b;
1011}
1012
Andi Kleendc098b32013-04-20 11:02:29 -07001013static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
1014 struct perf_pmu_alias *alias)
1015{
Cody P Schaferaaea3612015-01-07 17:13:51 -08001016 struct parse_events_term *term;
1017 int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
1018
1019 list_for_each_entry(term, &alias->terms, list) {
1020 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
1021 used += snprintf(buf + used, sub_non_neg(len, used),
1022 ",%s=%s", term->config,
1023 term->val.str);
1024 }
1025
1026 if (sub_non_neg(len, used) > 0) {
1027 buf[used] = '/';
1028 used++;
1029 }
1030 if (sub_non_neg(len, used) > 0) {
1031 buf[used] = '\0';
1032 used++;
1033 } else
1034 buf[len - 1] = '\0';
1035
Andi Kleendc098b32013-04-20 11:02:29 -07001036 return buf;
1037}
1038
1039static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
1040 struct perf_pmu_alias *alias)
1041{
1042 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
1043 return buf;
1044}
1045
1046static int cmp_string(const void *a, const void *b)
1047{
1048 const char * const *as = a;
1049 const char * const *bs = b;
1050 return strcmp(*as, *bs);
1051}
1052
1053void print_pmu_events(const char *event_glob, bool name_only)
1054{
1055 struct perf_pmu *pmu;
1056 struct perf_pmu_alias *alias;
1057 char buf[1024];
1058 int printed = 0;
1059 int len, j;
1060 char **aliases;
1061
1062 pmu = NULL;
1063 len = 0;
Adrian Hunter42634bc2014-10-23 13:45:10 +03001064 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
Andi Kleendc098b32013-04-20 11:02:29 -07001065 list_for_each_entry(alias, &pmu->aliases, list)
1066 len++;
Adrian Hunter42634bc2014-10-23 13:45:10 +03001067 if (pmu->selectable)
1068 len++;
1069 }
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001070 aliases = zalloc(sizeof(char *) * len);
Andi Kleendc098b32013-04-20 11:02:29 -07001071 if (!aliases)
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001072 goto out_enomem;
Andi Kleendc098b32013-04-20 11:02:29 -07001073 pmu = NULL;
1074 j = 0;
Adrian Hunter42634bc2014-10-23 13:45:10 +03001075 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
Andi Kleendc098b32013-04-20 11:02:29 -07001076 list_for_each_entry(alias, &pmu->aliases, list) {
1077 char *name = format_alias(buf, sizeof(buf), pmu, alias);
1078 bool is_cpu = !strcmp(pmu->name, "cpu");
1079
1080 if (event_glob != NULL &&
1081 !(strglobmatch(name, event_glob) ||
1082 (!is_cpu && strglobmatch(alias->name,
1083 event_glob))))
1084 continue;
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001085
Andi Kleendc098b32013-04-20 11:02:29 -07001086 if (is_cpu && !name_only)
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001087 name = format_alias_or(buf, sizeof(buf), pmu, alias);
1088
1089 aliases[j] = strdup(name);
1090 if (aliases[j] == NULL)
1091 goto out_enomem;
Andi Kleendc098b32013-04-20 11:02:29 -07001092 j++;
1093 }
Arnaldo Carvalho de Melofa52cea2015-10-02 15:28:16 -03001094 if (pmu->selectable &&
1095 (event_glob == NULL || strglobmatch(pmu->name, event_glob))) {
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001096 char *s;
1097 if (asprintf(&s, "%s//", pmu->name) < 0)
1098 goto out_enomem;
1099 aliases[j] = s;
Adrian Hunter42634bc2014-10-23 13:45:10 +03001100 j++;
1101 }
1102 }
Andi Kleendc098b32013-04-20 11:02:29 -07001103 len = j;
1104 qsort(aliases, len, sizeof(char *), cmp_string);
1105 for (j = 0; j < len; j++) {
1106 if (name_only) {
1107 printf("%s ", aliases[j]);
1108 continue;
1109 }
1110 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
Andi Kleendc098b32013-04-20 11:02:29 -07001111 printed++;
1112 }
Arnaldo Carvalho de Melodfc431c2015-09-30 17:13:26 -03001113 if (printed && pager_in_use())
Andi Kleendc098b32013-04-20 11:02:29 -07001114 printf("\n");
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -03001115out_free:
1116 for (j = 0; j < len; j++)
1117 zfree(&aliases[j]);
1118 zfree(&aliases);
1119 return;
1120
1121out_enomem:
1122 printf("FATAL: not enough memory to print PMU events\n");
1123 if (aliases)
1124 goto out_free;
Andi Kleendc098b32013-04-20 11:02:29 -07001125}
Andi Kleen4cabc3d2013-08-21 16:47:26 -07001126
1127bool pmu_have_event(const char *pname, const char *name)
1128{
1129 struct perf_pmu *pmu;
1130 struct perf_pmu_alias *alias;
1131
1132 pmu = NULL;
1133 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1134 if (strcmp(pname, pmu->name))
1135 continue;
1136 list_for_each_entry(alias, &pmu->aliases, list)
1137 if (!strcmp(alias->name, name))
1138 return true;
1139 }
1140 return false;
1141}
Adrian Hunter7d4bdab2014-07-31 09:00:50 +03001142
1143static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
1144{
1145 struct stat st;
1146 char path[PATH_MAX];
1147 const char *sysfs;
1148
1149 sysfs = sysfs__mountpoint();
1150 if (!sysfs)
1151 return NULL;
1152
1153 snprintf(path, PATH_MAX,
1154 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
1155
1156 if (stat(path, &st) < 0)
1157 return NULL;
1158
1159 return fopen(path, "r");
1160}
1161
1162int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
1163 ...)
1164{
1165 va_list args;
1166 FILE *file;
1167 int ret = EOF;
1168
1169 va_start(args, fmt);
1170 file = perf_pmu__open_file(pmu, name);
1171 if (file) {
1172 ret = vfscanf(file, fmt, args);
1173 fclose(file);
1174 }
1175 va_end(args);
1176 return ret;
1177}