blob: f003b5a9e059c4981f083f77b09b70a82b97eff8 [file] [log] [blame]
Jiri Olsacd82a322012-03-15 20:09:17 +01001#include <linux/list.h>
2#include <sys/types.h>
Jiri Olsacd82a322012-03-15 20:09:17 +01003#include <unistd.h>
4#include <stdio.h>
Adrian Hunterdc0a6202014-07-31 09:00:49 +03005#include <stdbool.h>
Adrian Hunter7d4bdab2014-07-31 09:00:50 +03006#include <stdarg.h>
Jiri Olsacd82a322012-03-15 20:09:17 +01007#include <dirent.h>
Borislav Petkovcd0cfad2013-12-09 17:14:24 +01008#include <api/fs/fs.h>
Stephane Eranian410136f2013-11-12 17:58:49 +01009#include <locale.h>
Jiri Olsacd82a322012-03-15 20:09:17 +010010#include "util.h"
11#include "pmu.h"
12#include "parse-events.h"
Yan, Zheng7ae92e72012-09-10 15:53:50 +080013#include "cpumap.h"
Jiri Olsacd82a322012-03-15 20:09:17 +010014
Arnaldo Carvalho de Meloab1bf6532013-01-18 17:05:09 -030015struct perf_pmu_format {
16 char *name;
17 int value;
18 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
19 struct list_head list;
20};
21
Robert Richter50a96672012-08-16 21:10:24 +020022#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
23
Jiri Olsacd82a322012-03-15 20:09:17 +010024int perf_pmu_parse(struct list_head *list, char *name);
25extern FILE *perf_pmu_in;
26
27static LIST_HEAD(pmus);
28
29/*
30 * Parse & process all the sysfs attributes located under
31 * the directory specified in 'dir' parameter.
32 */
Jiri Olsacff7f952012-11-10 01:46:50 +010033int perf_pmu__format_parse(char *dir, struct list_head *head)
Jiri Olsacd82a322012-03-15 20:09:17 +010034{
35 struct dirent *evt_ent;
36 DIR *format_dir;
37 int ret = 0;
38
39 format_dir = opendir(dir);
40 if (!format_dir)
41 return -EINVAL;
42
43 while (!ret && (evt_ent = readdir(format_dir))) {
44 char path[PATH_MAX];
45 char *name = evt_ent->d_name;
46 FILE *file;
47
48 if (!strcmp(name, ".") || !strcmp(name, ".."))
49 continue;
50
51 snprintf(path, PATH_MAX, "%s/%s", dir, name);
52
53 ret = -EINVAL;
54 file = fopen(path, "r");
55 if (!file)
56 break;
57
58 perf_pmu_in = file;
59 ret = perf_pmu_parse(head, name);
60 fclose(file);
61 }
62
63 closedir(format_dir);
64 return ret;
65}
66
67/*
68 * Reading/parsing the default pmu format definition, which should be
69 * located at:
70 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
71 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +030072static int pmu_format(const char *name, struct list_head *format)
Jiri Olsacd82a322012-03-15 20:09:17 +010073{
74 struct stat st;
75 char path[PATH_MAX];
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -030076 const char *sysfs = sysfs__mountpoint();
Jiri Olsacd82a322012-03-15 20:09:17 +010077
Jiri Olsacd82a322012-03-15 20:09:17 +010078 if (!sysfs)
79 return -1;
80
81 snprintf(path, PATH_MAX,
Robert Richter50a96672012-08-16 21:10:24 +020082 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
Jiri Olsacd82a322012-03-15 20:09:17 +010083
84 if (stat(path, &st) < 0)
Robert Richter9bc8f9f2012-06-14 22:38:37 +020085 return 0; /* no error if format does not exist */
Jiri Olsacd82a322012-03-15 20:09:17 +010086
Jiri Olsacff7f952012-11-10 01:46:50 +010087 if (perf_pmu__format_parse(path, format))
Jiri Olsacd82a322012-03-15 20:09:17 +010088 return -1;
89
90 return 0;
91}
92
Stephane Eranian410136f2013-11-12 17:58:49 +010093static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
94{
95 struct stat st;
96 ssize_t sret;
97 char scale[128];
98 int fd, ret = -1;
99 char path[PATH_MAX];
Stephane Eranian8a398892014-01-17 16:34:05 +0100100 const char *lc;
Stephane Eranian410136f2013-11-12 17:58:49 +0100101
102 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
103
104 fd = open(path, O_RDONLY);
105 if (fd == -1)
106 return -1;
107
108 if (fstat(fd, &st) < 0)
109 goto error;
110
111 sret = read(fd, scale, sizeof(scale)-1);
112 if (sret < 0)
113 goto error;
114
115 scale[sret] = '\0';
116 /*
117 * save current locale
118 */
119 lc = setlocale(LC_NUMERIC, NULL);
120
121 /*
122 * force to C locale to ensure kernel
123 * scale string is converted correctly.
124 * kernel uses default C locale.
125 */
126 setlocale(LC_NUMERIC, "C");
127
128 alias->scale = strtod(scale, NULL);
129
130 /* restore locale */
131 setlocale(LC_NUMERIC, lc);
132
133 ret = 0;
134error:
135 close(fd);
136 return ret;
137}
138
139static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
140{
141 char path[PATH_MAX];
142 ssize_t sret;
143 int fd;
144
145 snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
146
147 fd = open(path, O_RDONLY);
148 if (fd == -1)
149 return -1;
150
151 sret = read(fd, alias->unit, UNIT_MAX_LEN);
152 if (sret < 0)
153 goto error;
154
155 close(fd);
156
157 alias->unit[sret] = '\0';
158
159 return 0;
160error:
161 close(fd);
162 alias->unit[0] = '\0';
163 return -1;
164}
165
Matt Fleming044330c2014-11-21 10:31:12 +0100166static int
167perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
168{
169 char path[PATH_MAX];
170 int fd;
171
172 snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
173
174 fd = open(path, O_RDONLY);
175 if (fd == -1)
176 return -1;
177
178 close(fd);
179
180 alias->per_pkg = true;
181 return 0;
182}
183
Stephane Eranian410136f2013-11-12 17:58:49 +0100184static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
Zheng Yana6146d52012-06-15 14:31:41 +0800185{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300186 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800187 char buf[256];
188 int ret;
189
190 ret = fread(buf, 1, sizeof(buf), file);
191 if (ret == 0)
192 return -EINVAL;
193 buf[ret] = 0;
194
195 alias = malloc(sizeof(*alias));
196 if (!alias)
197 return -ENOMEM;
198
199 INIT_LIST_HEAD(&alias->terms);
Stephane Eranian410136f2013-11-12 17:58:49 +0100200 alias->scale = 1.0;
201 alias->unit[0] = '\0';
Matt Fleming044330c2014-11-21 10:31:12 +0100202 alias->per_pkg = false;
Stephane Eranian410136f2013-11-12 17:58:49 +0100203
Zheng Yana6146d52012-06-15 14:31:41 +0800204 ret = parse_events_terms(&alias->terms, buf);
205 if (ret) {
206 free(alias);
207 return ret;
208 }
209
210 alias->name = strdup(name);
Stephane Eranian410136f2013-11-12 17:58:49 +0100211 /*
212 * load unit name and scale if available
213 */
214 perf_pmu__parse_unit(alias, dir, name);
215 perf_pmu__parse_scale(alias, dir, name);
Matt Fleming044330c2014-11-21 10:31:12 +0100216 perf_pmu__parse_per_pkg(alias, dir, name);
Stephane Eranian410136f2013-11-12 17:58:49 +0100217
Zheng Yana6146d52012-06-15 14:31:41 +0800218 list_add_tail(&alias->list, list);
Stephane Eranian410136f2013-11-12 17:58:49 +0100219
Zheng Yana6146d52012-06-15 14:31:41 +0800220 return 0;
221}
222
Matt Fleming46441bd2014-09-24 15:04:06 +0100223static inline bool pmu_alias_info_file(char *name)
224{
225 size_t len;
226
227 len = strlen(name);
228 if (len > 5 && !strcmp(name + len - 5, ".unit"))
229 return true;
230 if (len > 6 && !strcmp(name + len - 6, ".scale"))
231 return true;
Matt Fleming044330c2014-11-21 10:31:12 +0100232 if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
233 return true;
Matt Fleming46441bd2014-09-24 15:04:06 +0100234
235 return false;
236}
237
Zheng Yana6146d52012-06-15 14:31:41 +0800238/*
239 * Process all the sysfs attributes located under the directory
240 * specified in 'dir' parameter.
241 */
242static int pmu_aliases_parse(char *dir, struct list_head *head)
243{
244 struct dirent *evt_ent;
245 DIR *event_dir;
246 int ret = 0;
247
248 event_dir = opendir(dir);
249 if (!event_dir)
250 return -EINVAL;
251
252 while (!ret && (evt_ent = readdir(event_dir))) {
253 char path[PATH_MAX];
254 char *name = evt_ent->d_name;
255 FILE *file;
256
257 if (!strcmp(name, ".") || !strcmp(name, ".."))
258 continue;
259
Stephane Eranian410136f2013-11-12 17:58:49 +0100260 /*
Matt Fleming46441bd2014-09-24 15:04:06 +0100261 * skip info files parsed in perf_pmu__new_alias()
Stephane Eranian410136f2013-11-12 17:58:49 +0100262 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100263 if (pmu_alias_info_file(name))
Stephane Eranian410136f2013-11-12 17:58:49 +0100264 continue;
265
Zheng Yana6146d52012-06-15 14:31:41 +0800266 snprintf(path, PATH_MAX, "%s/%s", dir, name);
267
268 ret = -EINVAL;
269 file = fopen(path, "r");
270 if (!file)
271 break;
Stephane Eranian410136f2013-11-12 17:58:49 +0100272
273 ret = perf_pmu__new_alias(head, dir, name, file);
Zheng Yana6146d52012-06-15 14:31:41 +0800274 fclose(file);
275 }
276
277 closedir(event_dir);
278 return ret;
279}
280
281/*
282 * Reading the pmu event aliases definition, which should be located at:
283 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
284 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300285static int pmu_aliases(const char *name, struct list_head *head)
Zheng Yana6146d52012-06-15 14:31:41 +0800286{
287 struct stat st;
288 char path[PATH_MAX];
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300289 const char *sysfs = sysfs__mountpoint();
Zheng Yana6146d52012-06-15 14:31:41 +0800290
Zheng Yana6146d52012-06-15 14:31:41 +0800291 if (!sysfs)
292 return -1;
293
294 snprintf(path, PATH_MAX,
295 "%s/bus/event_source/devices/%s/events", sysfs, name);
296
297 if (stat(path, &st) < 0)
Jiri Olsa3fded962012-10-10 14:53:16 +0200298 return 0; /* no error if 'events' does not exist */
Zheng Yana6146d52012-06-15 14:31:41 +0800299
300 if (pmu_aliases_parse(path, head))
301 return -1;
302
303 return 0;
304}
305
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300306static int pmu_alias_terms(struct perf_pmu_alias *alias,
Zheng Yana6146d52012-06-15 14:31:41 +0800307 struct list_head *terms)
308{
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200309 struct parse_events_term *term, *cloned;
Zheng Yana6146d52012-06-15 14:31:41 +0800310 LIST_HEAD(list);
311 int ret;
312
313 list_for_each_entry(term, &alias->terms, list) {
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200314 ret = parse_events_term__clone(&cloned, term);
Zheng Yana6146d52012-06-15 14:31:41 +0800315 if (ret) {
316 parse_events__free_terms(&list);
317 return ret;
318 }
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200319 list_add_tail(&cloned->list, &list);
Zheng Yana6146d52012-06-15 14:31:41 +0800320 }
321 list_splice(&list, terms);
322 return 0;
323}
324
Jiri Olsacd82a322012-03-15 20:09:17 +0100325/*
326 * Reading/parsing the default pmu type value, which should be
327 * located at:
328 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
329 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300330static int pmu_type(const char *name, __u32 *type)
Jiri Olsacd82a322012-03-15 20:09:17 +0100331{
332 struct stat st;
333 char path[PATH_MAX];
Jiri Olsacd82a322012-03-15 20:09:17 +0100334 FILE *file;
335 int ret = 0;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300336 const char *sysfs = sysfs__mountpoint();
Jiri Olsacd82a322012-03-15 20:09:17 +0100337
Jiri Olsacd82a322012-03-15 20:09:17 +0100338 if (!sysfs)
339 return -1;
340
341 snprintf(path, PATH_MAX,
Robert Richter50a96672012-08-16 21:10:24 +0200342 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
Jiri Olsacd82a322012-03-15 20:09:17 +0100343
344 if (stat(path, &st) < 0)
345 return -1;
346
347 file = fopen(path, "r");
348 if (!file)
349 return -EINVAL;
350
351 if (1 != fscanf(file, "%u", type))
352 ret = -1;
353
354 fclose(file);
355 return ret;
356}
357
Robert Richter50a96672012-08-16 21:10:24 +0200358/* Add all pmus in sysfs to pmu list: */
359static void pmu_read_sysfs(void)
360{
361 char path[PATH_MAX];
Robert Richter50a96672012-08-16 21:10:24 +0200362 DIR *dir;
363 struct dirent *dent;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300364 const char *sysfs = sysfs__mountpoint();
Robert Richter50a96672012-08-16 21:10:24 +0200365
Robert Richter50a96672012-08-16 21:10:24 +0200366 if (!sysfs)
367 return;
368
369 snprintf(path, PATH_MAX,
370 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
371
372 dir = opendir(path);
373 if (!dir)
374 return;
375
376 while ((dent = readdir(dir))) {
377 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
378 continue;
379 /* add to static LIST_HEAD(pmus): */
380 perf_pmu__find(dent->d_name);
381 }
382
383 closedir(dir);
384}
385
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300386static struct cpu_map *pmu_cpumask(const char *name)
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800387{
388 struct stat st;
389 char path[PATH_MAX];
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800390 FILE *file;
391 struct cpu_map *cpus;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300392 const char *sysfs = sysfs__mountpoint();
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800393
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800394 if (!sysfs)
395 return NULL;
396
397 snprintf(path, PATH_MAX,
398 "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
399
400 if (stat(path, &st) < 0)
401 return NULL;
402
403 file = fopen(path, "r");
404 if (!file)
405 return NULL;
406
407 cpus = cpu_map__read(file);
408 fclose(file);
409 return cpus;
410}
411
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300412struct perf_event_attr *__attribute__((weak))
413perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
414{
415 return NULL;
416}
417
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300418static struct perf_pmu *pmu_lookup(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100419{
420 struct perf_pmu *pmu;
421 LIST_HEAD(format);
Zheng Yana6146d52012-06-15 14:31:41 +0800422 LIST_HEAD(aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100423 __u32 type;
424
425 /*
426 * The pmu data we store & need consists of the pmu
427 * type value and format definitions. Load both right
428 * now.
429 */
430 if (pmu_format(name, &format))
431 return NULL;
432
Jiri Olsa3fded962012-10-10 14:53:16 +0200433 if (pmu_aliases(name, &aliases))
434 return NULL;
435
Jiri Olsacd82a322012-03-15 20:09:17 +0100436 if (pmu_type(name, &type))
437 return NULL;
438
439 pmu = zalloc(sizeof(*pmu));
440 if (!pmu)
441 return NULL;
442
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800443 pmu->cpus = pmu_cpumask(name);
444
Jiri Olsacd82a322012-03-15 20:09:17 +0100445 INIT_LIST_HEAD(&pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800446 INIT_LIST_HEAD(&pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100447 list_splice(&format, &pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800448 list_splice(&aliases, &pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100449 pmu->name = strdup(name);
450 pmu->type = type;
Robert Richter9bc8f9f2012-06-14 22:38:37 +0200451 list_add_tail(&pmu->list, &pmus);
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300452
453 pmu->default_config = perf_pmu__get_default_config(pmu);
454
Jiri Olsacd82a322012-03-15 20:09:17 +0100455 return pmu;
456}
457
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300458static struct perf_pmu *pmu_find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100459{
460 struct perf_pmu *pmu;
461
462 list_for_each_entry(pmu, &pmus, list)
463 if (!strcmp(pmu->name, name))
464 return pmu;
465
466 return NULL;
467}
468
Robert Richter50a96672012-08-16 21:10:24 +0200469struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
470{
471 /*
472 * pmu iterator: If pmu is NULL, we start at the begin,
473 * otherwise return the next pmu. Returns NULL on end.
474 */
475 if (!pmu) {
476 pmu_read_sysfs();
477 pmu = list_prepare_entry(pmu, &pmus, list);
478 }
479 list_for_each_entry_continue(pmu, &pmus, list)
480 return pmu;
481 return NULL;
482}
483
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300484struct perf_pmu *perf_pmu__find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100485{
486 struct perf_pmu *pmu;
487
488 /*
489 * Once PMU is loaded it stays in the list,
490 * so we keep us from multiple reading/parsing
491 * the pmu format definitions.
492 */
493 pmu = pmu_find(name);
494 if (pmu)
495 return pmu;
496
497 return pmu_lookup(name);
498}
499
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300500static struct perf_pmu_format *
Jiri Olsacd82a322012-03-15 20:09:17 +0100501pmu_find_format(struct list_head *formats, char *name)
502{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300503 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100504
505 list_for_each_entry(format, formats, list)
506 if (!strcmp(format->name, name))
507 return format;
508
509 return NULL;
510}
511
512/*
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300513 * Sets value based on the format definition (format parameter)
Jiri Olsacd82a322012-03-15 20:09:17 +0100514 * and unformated value (value parameter).
Jiri Olsacd82a322012-03-15 20:09:17 +0100515 */
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300516static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
517 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100518{
519 unsigned long fbit, vbit;
Jiri Olsacd82a322012-03-15 20:09:17 +0100520
521 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
522
523 if (!test_bit(fbit, format))
524 continue;
525
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300526 if (value & (1llu << vbit++))
527 *v |= (1llu << fbit);
528 else if (zero)
529 *v &= ~(1llu << fbit);
Jiri Olsacd82a322012-03-15 20:09:17 +0100530 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100531}
532
533/*
534 * Setup one of config[12] attr members based on the
Cody P Schafer88aca8d2014-01-08 08:43:51 -0800535 * user input data - term parameter.
Jiri Olsacd82a322012-03-15 20:09:17 +0100536 */
537static int pmu_config_term(struct list_head *formats,
538 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300539 struct parse_events_term *term,
540 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100541{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300542 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100543 __u64 *vp;
544
545 /*
546 * Support only for hardcoded and numnerial terms.
547 * Hardcoded terms should be already in, so nothing
548 * to be done for them.
549 */
550 if (parse_events__is_hardcoded_term(term))
551 return 0;
552
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200553 if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
Jiri Olsacd82a322012-03-15 20:09:17 +0100554 return -EINVAL;
555
556 format = pmu_find_format(formats, term->config);
557 if (!format)
558 return -EINVAL;
559
560 switch (format->value) {
561 case PERF_PMU_FORMAT_VALUE_CONFIG:
562 vp = &attr->config;
563 break;
564 case PERF_PMU_FORMAT_VALUE_CONFIG1:
565 vp = &attr->config1;
566 break;
567 case PERF_PMU_FORMAT_VALUE_CONFIG2:
568 vp = &attr->config2;
569 break;
570 default:
571 return -EINVAL;
572 }
573
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200574 /*
575 * XXX If we ever decide to go with string values for
576 * non-hardcoded terms, here's the place to translate
577 * them into value.
578 */
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300579 pmu_format_value(format->bits, term->val.num, vp, zero);
Jiri Olsacd82a322012-03-15 20:09:17 +0100580 return 0;
581}
582
Jiri Olsacff7f952012-11-10 01:46:50 +0100583int perf_pmu__config_terms(struct list_head *formats,
584 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300585 struct list_head *head_terms,
586 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100587{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300588 struct parse_events_term *term;
Jiri Olsacd82a322012-03-15 20:09:17 +0100589
Jiri Olsa6b5fc392012-05-21 09:12:53 +0200590 list_for_each_entry(term, head_terms, list)
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300591 if (pmu_config_term(formats, attr, term, zero))
Jiri Olsacd82a322012-03-15 20:09:17 +0100592 return -EINVAL;
593
594 return 0;
595}
596
597/*
598 * Configures event's 'attr' parameter based on the:
599 * 1) users input - specified in terms parameter
600 * 2) pmu format definitions - specified by pmu parameter
601 */
602int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
603 struct list_head *head_terms)
604{
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300605 bool zero = !!pmu->default_config;
606
Jiri Olsacd82a322012-03-15 20:09:17 +0100607 attr->type = pmu->type;
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300608 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
Jiri Olsacd82a322012-03-15 20:09:17 +0100609}
610
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300611static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
612 struct parse_events_term *term)
Zheng Yana6146d52012-06-15 14:31:41 +0800613{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300614 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800615 char *name;
616
617 if (parse_events__is_hardcoded_term(term))
618 return NULL;
619
620 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
621 if (term->val.num != 1)
622 return NULL;
623 if (pmu_find_format(&pmu->format, term->config))
624 return NULL;
625 name = term->config;
626 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
627 if (strcasecmp(term->config, "event"))
628 return NULL;
629 name = term->val.str;
630 } else {
631 return NULL;
632 }
633
634 list_for_each_entry(alias, &pmu->aliases, list) {
635 if (!strcasecmp(alias->name, name))
636 return alias;
637 }
638 return NULL;
639}
640
Stephane Eranian410136f2013-11-12 17:58:49 +0100641
642static int check_unit_scale(struct perf_pmu_alias *alias,
Stephane Eranian8a398892014-01-17 16:34:05 +0100643 const char **unit, double *scale)
Stephane Eranian410136f2013-11-12 17:58:49 +0100644{
645 /*
646 * Only one term in event definition can
647 * define unit and scale, fail if there's
648 * more than one.
649 */
650 if ((*unit && alias->unit) ||
651 (*scale && alias->scale))
652 return -EINVAL;
653
654 if (alias->unit)
655 *unit = alias->unit;
656
657 if (alias->scale)
658 *scale = alias->scale;
659
660 return 0;
661}
662
Zheng Yana6146d52012-06-15 14:31:41 +0800663/*
664 * Find alias in the terms list and replace it with the terms
665 * defined for the alias
666 */
Stephane Eranian410136f2013-11-12 17:58:49 +0100667int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
Matt Fleming46441bd2014-09-24 15:04:06 +0100668 struct perf_pmu_info *info)
Zheng Yana6146d52012-06-15 14:31:41 +0800669{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300670 struct parse_events_term *term, *h;
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300671 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800672 int ret;
673
Matt Fleming044330c2014-11-21 10:31:12 +0100674 info->per_pkg = false;
675
Stephane Eranian8a398892014-01-17 16:34:05 +0100676 /*
677 * Mark unit and scale as not set
678 * (different from default values, see below)
679 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100680 info->unit = NULL;
681 info->scale = 0.0;
Stephane Eranian410136f2013-11-12 17:58:49 +0100682
Zheng Yana6146d52012-06-15 14:31:41 +0800683 list_for_each_entry_safe(term, h, head_terms, list) {
684 alias = pmu_find_alias(pmu, term);
685 if (!alias)
686 continue;
687 ret = pmu_alias_terms(alias, &term->list);
688 if (ret)
689 return ret;
Stephane Eranian410136f2013-11-12 17:58:49 +0100690
Matt Fleming46441bd2014-09-24 15:04:06 +0100691 ret = check_unit_scale(alias, &info->unit, &info->scale);
Stephane Eranian410136f2013-11-12 17:58:49 +0100692 if (ret)
693 return ret;
694
Matt Fleming044330c2014-11-21 10:31:12 +0100695 if (alias->per_pkg)
696 info->per_pkg = true;
697
Zheng Yana6146d52012-06-15 14:31:41 +0800698 list_del(&term->list);
699 free(term);
700 }
Stephane Eranian8a398892014-01-17 16:34:05 +0100701
702 /*
703 * if no unit or scale foundin aliases, then
704 * set defaults as for evsel
705 * unit cannot left to NULL
706 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100707 if (info->unit == NULL)
708 info->unit = "";
Stephane Eranian8a398892014-01-17 16:34:05 +0100709
Matt Fleming46441bd2014-09-24 15:04:06 +0100710 if (info->scale == 0.0)
711 info->scale = 1.0;
Stephane Eranian8a398892014-01-17 16:34:05 +0100712
Zheng Yana6146d52012-06-15 14:31:41 +0800713 return 0;
714}
715
Jiri Olsacd82a322012-03-15 20:09:17 +0100716int perf_pmu__new_format(struct list_head *list, char *name,
717 int config, unsigned long *bits)
718{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300719 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100720
721 format = zalloc(sizeof(*format));
722 if (!format)
723 return -ENOMEM;
724
725 format->name = strdup(name);
726 format->value = config;
727 memcpy(format->bits, bits, sizeof(format->bits));
728
729 list_add_tail(&format->list, list);
730 return 0;
731}
732
733void perf_pmu__set_format(unsigned long *bits, long from, long to)
734{
735 long b;
736
737 if (!to)
738 to = from;
739
Sukadev Bhattiprolu15268132013-01-17 09:11:30 -0800740 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
Jiri Olsacd82a322012-03-15 20:09:17 +0100741 for (b = from; b <= to; b++)
742 set_bit(b, bits);
743}
Andi Kleendc098b32013-04-20 11:02:29 -0700744
745static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
746 struct perf_pmu_alias *alias)
747{
748 snprintf(buf, len, "%s/%s/", pmu->name, alias->name);
749 return buf;
750}
751
752static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
753 struct perf_pmu_alias *alias)
754{
755 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
756 return buf;
757}
758
759static int cmp_string(const void *a, const void *b)
760{
761 const char * const *as = a;
762 const char * const *bs = b;
763 return strcmp(*as, *bs);
764}
765
766void print_pmu_events(const char *event_glob, bool name_only)
767{
768 struct perf_pmu *pmu;
769 struct perf_pmu_alias *alias;
770 char buf[1024];
771 int printed = 0;
772 int len, j;
773 char **aliases;
774
775 pmu = NULL;
776 len = 0;
Adrian Hunter42634bc2014-10-23 13:45:10 +0300777 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
Andi Kleendc098b32013-04-20 11:02:29 -0700778 list_for_each_entry(alias, &pmu->aliases, list)
779 len++;
Adrian Hunter42634bc2014-10-23 13:45:10 +0300780 if (pmu->selectable)
781 len++;
782 }
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -0300783 aliases = zalloc(sizeof(char *) * len);
Andi Kleendc098b32013-04-20 11:02:29 -0700784 if (!aliases)
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -0300785 goto out_enomem;
Andi Kleendc098b32013-04-20 11:02:29 -0700786 pmu = NULL;
787 j = 0;
Adrian Hunter42634bc2014-10-23 13:45:10 +0300788 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
Andi Kleendc098b32013-04-20 11:02:29 -0700789 list_for_each_entry(alias, &pmu->aliases, list) {
790 char *name = format_alias(buf, sizeof(buf), pmu, alias);
791 bool is_cpu = !strcmp(pmu->name, "cpu");
792
793 if (event_glob != NULL &&
794 !(strglobmatch(name, event_glob) ||
795 (!is_cpu && strglobmatch(alias->name,
796 event_glob))))
797 continue;
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -0300798
Andi Kleendc098b32013-04-20 11:02:29 -0700799 if (is_cpu && !name_only)
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -0300800 name = format_alias_or(buf, sizeof(buf), pmu, alias);
801
802 aliases[j] = strdup(name);
803 if (aliases[j] == NULL)
804 goto out_enomem;
Andi Kleendc098b32013-04-20 11:02:29 -0700805 j++;
806 }
Adrian Hunter42634bc2014-10-23 13:45:10 +0300807 if (pmu->selectable) {
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -0300808 char *s;
809 if (asprintf(&s, "%s//", pmu->name) < 0)
810 goto out_enomem;
811 aliases[j] = s;
Adrian Hunter42634bc2014-10-23 13:45:10 +0300812 j++;
813 }
814 }
Andi Kleendc098b32013-04-20 11:02:29 -0700815 len = j;
816 qsort(aliases, len, sizeof(char *), cmp_string);
817 for (j = 0; j < len; j++) {
818 if (name_only) {
819 printf("%s ", aliases[j]);
820 continue;
821 }
822 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
Andi Kleendc098b32013-04-20 11:02:29 -0700823 printed++;
824 }
825 if (printed)
826 printf("\n");
Arnaldo Carvalho de Melo7e4772d2014-10-24 10:25:09 -0300827out_free:
828 for (j = 0; j < len; j++)
829 zfree(&aliases[j]);
830 zfree(&aliases);
831 return;
832
833out_enomem:
834 printf("FATAL: not enough memory to print PMU events\n");
835 if (aliases)
836 goto out_free;
Andi Kleendc098b32013-04-20 11:02:29 -0700837}
Andi Kleen4cabc3d2013-08-21 16:47:26 -0700838
839bool pmu_have_event(const char *pname, const char *name)
840{
841 struct perf_pmu *pmu;
842 struct perf_pmu_alias *alias;
843
844 pmu = NULL;
845 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
846 if (strcmp(pname, pmu->name))
847 continue;
848 list_for_each_entry(alias, &pmu->aliases, list)
849 if (!strcmp(alias->name, name))
850 return true;
851 }
852 return false;
853}
Adrian Hunter7d4bdab2014-07-31 09:00:50 +0300854
855static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
856{
857 struct stat st;
858 char path[PATH_MAX];
859 const char *sysfs;
860
861 sysfs = sysfs__mountpoint();
862 if (!sysfs)
863 return NULL;
864
865 snprintf(path, PATH_MAX,
866 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
867
868 if (stat(path, &st) < 0)
869 return NULL;
870
871 return fopen(path, "r");
872}
873
874int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
875 ...)
876{
877 va_list args;
878 FILE *file;
879 int ret = EOF;
880
881 va_start(args, fmt);
882 file = perf_pmu__open_file(pmu, name);
883 if (file) {
884 ret = vfscanf(file, fmt, args);
885 fclose(file);
886 }
887 va_end(args);
888 return ret;
889}