blob: 93a41ca96b8e0c6f0f927b20209c58c676a98384 [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
Stephane Eranian410136f2013-11-12 17:58:49 +010015#define UNIT_MAX_LEN 31 /* max length for event unit name */
16
Arnaldo Carvalho de Meloab1bf6532013-01-18 17:05:09 -030017struct perf_pmu_alias {
18 char *name;
Cody P Schafer885b5932014-08-15 00:26:14 -070019 struct list_head terms; /* HEAD struct parse_events_term -> list */
20 struct list_head list; /* ELEM */
Stephane Eranian410136f2013-11-12 17:58:49 +010021 char unit[UNIT_MAX_LEN+1];
22 double scale;
Arnaldo Carvalho de Meloab1bf6532013-01-18 17:05:09 -030023};
24
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
Robert Richter50a96672012-08-16 21:10:24 +020032#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
33
Jiri Olsacd82a322012-03-15 20:09:17 +010034int 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 */
Jiri Olsacff7f952012-11-10 01:46:50 +010043int perf_pmu__format_parse(char *dir, struct list_head *head)
Jiri Olsacd82a322012-03-15 20:09:17 +010044{
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 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +030082static int pmu_format(const char *name, struct list_head *format)
Jiri Olsacd82a322012-03-15 20:09:17 +010083{
84 struct stat st;
85 char path[PATH_MAX];
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -030086 const char *sysfs = sysfs__mountpoint();
Jiri Olsacd82a322012-03-15 20:09:17 +010087
Jiri Olsacd82a322012-03-15 20:09:17 +010088 if (!sysfs)
89 return -1;
90
91 snprintf(path, PATH_MAX,
Robert Richter50a96672012-08-16 21:10:24 +020092 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
Jiri Olsacd82a322012-03-15 20:09:17 +010093
94 if (stat(path, &st) < 0)
Robert Richter9bc8f9f2012-06-14 22:38:37 +020095 return 0; /* no error if format does not exist */
Jiri Olsacd82a322012-03-15 20:09:17 +010096
Jiri Olsacff7f952012-11-10 01:46:50 +010097 if (perf_pmu__format_parse(path, format))
Jiri Olsacd82a322012-03-15 20:09:17 +010098 return -1;
99
100 return 0;
101}
102
Stephane Eranian410136f2013-11-12 17:58:49 +0100103static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
104{
105 struct stat st;
106 ssize_t sret;
107 char scale[128];
108 int fd, ret = -1;
109 char path[PATH_MAX];
Stephane Eranian8a398892014-01-17 16:34:05 +0100110 const char *lc;
Stephane Eranian410136f2013-11-12 17:58:49 +0100111
112 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
113
114 fd = open(path, O_RDONLY);
115 if (fd == -1)
116 return -1;
117
118 if (fstat(fd, &st) < 0)
119 goto error;
120
121 sret = read(fd, scale, sizeof(scale)-1);
122 if (sret < 0)
123 goto error;
124
125 scale[sret] = '\0';
126 /*
127 * save current locale
128 */
129 lc = setlocale(LC_NUMERIC, NULL);
130
131 /*
132 * force to C locale to ensure kernel
133 * scale string is converted correctly.
134 * kernel uses default C locale.
135 */
136 setlocale(LC_NUMERIC, "C");
137
138 alias->scale = strtod(scale, NULL);
139
140 /* restore locale */
141 setlocale(LC_NUMERIC, lc);
142
143 ret = 0;
144error:
145 close(fd);
146 return ret;
147}
148
149static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
150{
151 char path[PATH_MAX];
152 ssize_t sret;
153 int fd;
154
155 snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
156
157 fd = open(path, O_RDONLY);
158 if (fd == -1)
159 return -1;
160
161 sret = read(fd, alias->unit, UNIT_MAX_LEN);
162 if (sret < 0)
163 goto error;
164
165 close(fd);
166
167 alias->unit[sret] = '\0';
168
169 return 0;
170error:
171 close(fd);
172 alias->unit[0] = '\0';
173 return -1;
174}
175
176static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
Zheng Yana6146d52012-06-15 14:31:41 +0800177{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300178 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800179 char buf[256];
180 int ret;
181
182 ret = fread(buf, 1, sizeof(buf), file);
183 if (ret == 0)
184 return -EINVAL;
185 buf[ret] = 0;
186
187 alias = malloc(sizeof(*alias));
188 if (!alias)
189 return -ENOMEM;
190
191 INIT_LIST_HEAD(&alias->terms);
Stephane Eranian410136f2013-11-12 17:58:49 +0100192 alias->scale = 1.0;
193 alias->unit[0] = '\0';
194
Zheng Yana6146d52012-06-15 14:31:41 +0800195 ret = parse_events_terms(&alias->terms, buf);
196 if (ret) {
197 free(alias);
198 return ret;
199 }
200
201 alias->name = strdup(name);
Stephane Eranian410136f2013-11-12 17:58:49 +0100202 /*
203 * load unit name and scale if available
204 */
205 perf_pmu__parse_unit(alias, dir, name);
206 perf_pmu__parse_scale(alias, dir, name);
207
Zheng Yana6146d52012-06-15 14:31:41 +0800208 list_add_tail(&alias->list, list);
Stephane Eranian410136f2013-11-12 17:58:49 +0100209
Zheng Yana6146d52012-06-15 14:31:41 +0800210 return 0;
211}
212
Matt Fleming46441bd2014-09-24 15:04:06 +0100213static inline bool pmu_alias_info_file(char *name)
214{
215 size_t len;
216
217 len = strlen(name);
218 if (len > 5 && !strcmp(name + len - 5, ".unit"))
219 return true;
220 if (len > 6 && !strcmp(name + len - 6, ".scale"))
221 return true;
222
223 return false;
224}
225
Zheng Yana6146d52012-06-15 14:31:41 +0800226/*
227 * Process all the sysfs attributes located under the directory
228 * specified in 'dir' parameter.
229 */
230static int pmu_aliases_parse(char *dir, struct list_head *head)
231{
232 struct dirent *evt_ent;
233 DIR *event_dir;
234 int ret = 0;
235
236 event_dir = opendir(dir);
237 if (!event_dir)
238 return -EINVAL;
239
240 while (!ret && (evt_ent = readdir(event_dir))) {
241 char path[PATH_MAX];
242 char *name = evt_ent->d_name;
243 FILE *file;
244
245 if (!strcmp(name, ".") || !strcmp(name, ".."))
246 continue;
247
Stephane Eranian410136f2013-11-12 17:58:49 +0100248 /*
Matt Fleming46441bd2014-09-24 15:04:06 +0100249 * skip info files parsed in perf_pmu__new_alias()
Stephane Eranian410136f2013-11-12 17:58:49 +0100250 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100251 if (pmu_alias_info_file(name))
Stephane Eranian410136f2013-11-12 17:58:49 +0100252 continue;
253
Zheng Yana6146d52012-06-15 14:31:41 +0800254 snprintf(path, PATH_MAX, "%s/%s", dir, name);
255
256 ret = -EINVAL;
257 file = fopen(path, "r");
258 if (!file)
259 break;
Stephane Eranian410136f2013-11-12 17:58:49 +0100260
261 ret = perf_pmu__new_alias(head, dir, name, file);
Zheng Yana6146d52012-06-15 14:31:41 +0800262 fclose(file);
263 }
264
265 closedir(event_dir);
266 return ret;
267}
268
269/*
270 * Reading the pmu event aliases definition, which should be located at:
271 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
272 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300273static int pmu_aliases(const char *name, struct list_head *head)
Zheng Yana6146d52012-06-15 14:31:41 +0800274{
275 struct stat st;
276 char path[PATH_MAX];
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300277 const char *sysfs = sysfs__mountpoint();
Zheng Yana6146d52012-06-15 14:31:41 +0800278
Zheng Yana6146d52012-06-15 14:31:41 +0800279 if (!sysfs)
280 return -1;
281
282 snprintf(path, PATH_MAX,
283 "%s/bus/event_source/devices/%s/events", sysfs, name);
284
285 if (stat(path, &st) < 0)
Jiri Olsa3fded962012-10-10 14:53:16 +0200286 return 0; /* no error if 'events' does not exist */
Zheng Yana6146d52012-06-15 14:31:41 +0800287
288 if (pmu_aliases_parse(path, head))
289 return -1;
290
291 return 0;
292}
293
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300294static int pmu_alias_terms(struct perf_pmu_alias *alias,
Zheng Yana6146d52012-06-15 14:31:41 +0800295 struct list_head *terms)
296{
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200297 struct parse_events_term *term, *cloned;
Zheng Yana6146d52012-06-15 14:31:41 +0800298 LIST_HEAD(list);
299 int ret;
300
301 list_for_each_entry(term, &alias->terms, list) {
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200302 ret = parse_events_term__clone(&cloned, term);
Zheng Yana6146d52012-06-15 14:31:41 +0800303 if (ret) {
304 parse_events__free_terms(&list);
305 return ret;
306 }
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200307 list_add_tail(&cloned->list, &list);
Zheng Yana6146d52012-06-15 14:31:41 +0800308 }
309 list_splice(&list, terms);
310 return 0;
311}
312
Jiri Olsacd82a322012-03-15 20:09:17 +0100313/*
314 * Reading/parsing the default pmu type value, which should be
315 * located at:
316 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
317 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300318static int pmu_type(const char *name, __u32 *type)
Jiri Olsacd82a322012-03-15 20:09:17 +0100319{
320 struct stat st;
321 char path[PATH_MAX];
Jiri Olsacd82a322012-03-15 20:09:17 +0100322 FILE *file;
323 int ret = 0;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300324 const char *sysfs = sysfs__mountpoint();
Jiri Olsacd82a322012-03-15 20:09:17 +0100325
Jiri Olsacd82a322012-03-15 20:09:17 +0100326 if (!sysfs)
327 return -1;
328
329 snprintf(path, PATH_MAX,
Robert Richter50a96672012-08-16 21:10:24 +0200330 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
Jiri Olsacd82a322012-03-15 20:09:17 +0100331
332 if (stat(path, &st) < 0)
333 return -1;
334
335 file = fopen(path, "r");
336 if (!file)
337 return -EINVAL;
338
339 if (1 != fscanf(file, "%u", type))
340 ret = -1;
341
342 fclose(file);
343 return ret;
344}
345
Robert Richter50a96672012-08-16 21:10:24 +0200346/* Add all pmus in sysfs to pmu list: */
347static void pmu_read_sysfs(void)
348{
349 char path[PATH_MAX];
Robert Richter50a96672012-08-16 21:10:24 +0200350 DIR *dir;
351 struct dirent *dent;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300352 const char *sysfs = sysfs__mountpoint();
Robert Richter50a96672012-08-16 21:10:24 +0200353
Robert Richter50a96672012-08-16 21:10:24 +0200354 if (!sysfs)
355 return;
356
357 snprintf(path, PATH_MAX,
358 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
359
360 dir = opendir(path);
361 if (!dir)
362 return;
363
364 while ((dent = readdir(dir))) {
365 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
366 continue;
367 /* add to static LIST_HEAD(pmus): */
368 perf_pmu__find(dent->d_name);
369 }
370
371 closedir(dir);
372}
373
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300374static struct cpu_map *pmu_cpumask(const char *name)
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800375{
376 struct stat st;
377 char path[PATH_MAX];
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800378 FILE *file;
379 struct cpu_map *cpus;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300380 const char *sysfs = sysfs__mountpoint();
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800381
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800382 if (!sysfs)
383 return NULL;
384
385 snprintf(path, PATH_MAX,
386 "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
387
388 if (stat(path, &st) < 0)
389 return NULL;
390
391 file = fopen(path, "r");
392 if (!file)
393 return NULL;
394
395 cpus = cpu_map__read(file);
396 fclose(file);
397 return cpus;
398}
399
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300400struct perf_event_attr *__attribute__((weak))
401perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
402{
403 return NULL;
404}
405
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300406static struct perf_pmu *pmu_lookup(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100407{
408 struct perf_pmu *pmu;
409 LIST_HEAD(format);
Zheng Yana6146d52012-06-15 14:31:41 +0800410 LIST_HEAD(aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100411 __u32 type;
412
413 /*
414 * The pmu data we store & need consists of the pmu
415 * type value and format definitions. Load both right
416 * now.
417 */
418 if (pmu_format(name, &format))
419 return NULL;
420
Jiri Olsa3fded962012-10-10 14:53:16 +0200421 if (pmu_aliases(name, &aliases))
422 return NULL;
423
Jiri Olsacd82a322012-03-15 20:09:17 +0100424 if (pmu_type(name, &type))
425 return NULL;
426
427 pmu = zalloc(sizeof(*pmu));
428 if (!pmu)
429 return NULL;
430
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800431 pmu->cpus = pmu_cpumask(name);
432
Jiri Olsacd82a322012-03-15 20:09:17 +0100433 INIT_LIST_HEAD(&pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800434 INIT_LIST_HEAD(&pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100435 list_splice(&format, &pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800436 list_splice(&aliases, &pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100437 pmu->name = strdup(name);
438 pmu->type = type;
Robert Richter9bc8f9f2012-06-14 22:38:37 +0200439 list_add_tail(&pmu->list, &pmus);
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300440
441 pmu->default_config = perf_pmu__get_default_config(pmu);
442
Jiri Olsacd82a322012-03-15 20:09:17 +0100443 return pmu;
444}
445
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300446static struct perf_pmu *pmu_find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100447{
448 struct perf_pmu *pmu;
449
450 list_for_each_entry(pmu, &pmus, list)
451 if (!strcmp(pmu->name, name))
452 return pmu;
453
454 return NULL;
455}
456
Robert Richter50a96672012-08-16 21:10:24 +0200457struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
458{
459 /*
460 * pmu iterator: If pmu is NULL, we start at the begin,
461 * otherwise return the next pmu. Returns NULL on end.
462 */
463 if (!pmu) {
464 pmu_read_sysfs();
465 pmu = list_prepare_entry(pmu, &pmus, list);
466 }
467 list_for_each_entry_continue(pmu, &pmus, list)
468 return pmu;
469 return NULL;
470}
471
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300472struct perf_pmu *perf_pmu__find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100473{
474 struct perf_pmu *pmu;
475
476 /*
477 * Once PMU is loaded it stays in the list,
478 * so we keep us from multiple reading/parsing
479 * the pmu format definitions.
480 */
481 pmu = pmu_find(name);
482 if (pmu)
483 return pmu;
484
485 return pmu_lookup(name);
486}
487
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300488static struct perf_pmu_format *
Jiri Olsacd82a322012-03-15 20:09:17 +0100489pmu_find_format(struct list_head *formats, char *name)
490{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300491 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100492
493 list_for_each_entry(format, formats, list)
494 if (!strcmp(format->name, name))
495 return format;
496
497 return NULL;
498}
499
500/*
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300501 * Sets value based on the format definition (format parameter)
Jiri Olsacd82a322012-03-15 20:09:17 +0100502 * and unformated value (value parameter).
Jiri Olsacd82a322012-03-15 20:09:17 +0100503 */
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300504static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
505 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100506{
507 unsigned long fbit, vbit;
Jiri Olsacd82a322012-03-15 20:09:17 +0100508
509 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
510
511 if (!test_bit(fbit, format))
512 continue;
513
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300514 if (value & (1llu << vbit++))
515 *v |= (1llu << fbit);
516 else if (zero)
517 *v &= ~(1llu << fbit);
Jiri Olsacd82a322012-03-15 20:09:17 +0100518 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100519}
520
521/*
522 * Setup one of config[12] attr members based on the
Cody P Schafer88aca8d2014-01-08 08:43:51 -0800523 * user input data - term parameter.
Jiri Olsacd82a322012-03-15 20:09:17 +0100524 */
525static int pmu_config_term(struct list_head *formats,
526 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300527 struct parse_events_term *term,
528 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100529{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300530 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100531 __u64 *vp;
532
533 /*
534 * Support only for hardcoded and numnerial terms.
535 * Hardcoded terms should be already in, so nothing
536 * to be done for them.
537 */
538 if (parse_events__is_hardcoded_term(term))
539 return 0;
540
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200541 if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
Jiri Olsacd82a322012-03-15 20:09:17 +0100542 return -EINVAL;
543
544 format = pmu_find_format(formats, term->config);
545 if (!format)
546 return -EINVAL;
547
548 switch (format->value) {
549 case PERF_PMU_FORMAT_VALUE_CONFIG:
550 vp = &attr->config;
551 break;
552 case PERF_PMU_FORMAT_VALUE_CONFIG1:
553 vp = &attr->config1;
554 break;
555 case PERF_PMU_FORMAT_VALUE_CONFIG2:
556 vp = &attr->config2;
557 break;
558 default:
559 return -EINVAL;
560 }
561
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200562 /*
563 * XXX If we ever decide to go with string values for
564 * non-hardcoded terms, here's the place to translate
565 * them into value.
566 */
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300567 pmu_format_value(format->bits, term->val.num, vp, zero);
Jiri Olsacd82a322012-03-15 20:09:17 +0100568 return 0;
569}
570
Jiri Olsacff7f952012-11-10 01:46:50 +0100571int perf_pmu__config_terms(struct list_head *formats,
572 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300573 struct list_head *head_terms,
574 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100575{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300576 struct parse_events_term *term;
Jiri Olsacd82a322012-03-15 20:09:17 +0100577
Jiri Olsa6b5fc392012-05-21 09:12:53 +0200578 list_for_each_entry(term, head_terms, list)
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300579 if (pmu_config_term(formats, attr, term, zero))
Jiri Olsacd82a322012-03-15 20:09:17 +0100580 return -EINVAL;
581
582 return 0;
583}
584
585/*
586 * Configures event's 'attr' parameter based on the:
587 * 1) users input - specified in terms parameter
588 * 2) pmu format definitions - specified by pmu parameter
589 */
590int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
591 struct list_head *head_terms)
592{
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300593 bool zero = !!pmu->default_config;
594
Jiri Olsacd82a322012-03-15 20:09:17 +0100595 attr->type = pmu->type;
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300596 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
Jiri Olsacd82a322012-03-15 20:09:17 +0100597}
598
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300599static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
600 struct parse_events_term *term)
Zheng Yana6146d52012-06-15 14:31:41 +0800601{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300602 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800603 char *name;
604
605 if (parse_events__is_hardcoded_term(term))
606 return NULL;
607
608 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
609 if (term->val.num != 1)
610 return NULL;
611 if (pmu_find_format(&pmu->format, term->config))
612 return NULL;
613 name = term->config;
614 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
615 if (strcasecmp(term->config, "event"))
616 return NULL;
617 name = term->val.str;
618 } else {
619 return NULL;
620 }
621
622 list_for_each_entry(alias, &pmu->aliases, list) {
623 if (!strcasecmp(alias->name, name))
624 return alias;
625 }
626 return NULL;
627}
628
Stephane Eranian410136f2013-11-12 17:58:49 +0100629
630static int check_unit_scale(struct perf_pmu_alias *alias,
Stephane Eranian8a398892014-01-17 16:34:05 +0100631 const char **unit, double *scale)
Stephane Eranian410136f2013-11-12 17:58:49 +0100632{
633 /*
634 * Only one term in event definition can
635 * define unit and scale, fail if there's
636 * more than one.
637 */
638 if ((*unit && alias->unit) ||
639 (*scale && alias->scale))
640 return -EINVAL;
641
642 if (alias->unit)
643 *unit = alias->unit;
644
645 if (alias->scale)
646 *scale = alias->scale;
647
648 return 0;
649}
650
Zheng Yana6146d52012-06-15 14:31:41 +0800651/*
652 * Find alias in the terms list and replace it with the terms
653 * defined for the alias
654 */
Stephane Eranian410136f2013-11-12 17:58:49 +0100655int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
Matt Fleming46441bd2014-09-24 15:04:06 +0100656 struct perf_pmu_info *info)
Zheng Yana6146d52012-06-15 14:31:41 +0800657{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300658 struct parse_events_term *term, *h;
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300659 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800660 int ret;
661
Stephane Eranian8a398892014-01-17 16:34:05 +0100662 /*
663 * Mark unit and scale as not set
664 * (different from default values, see below)
665 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100666 info->unit = NULL;
667 info->scale = 0.0;
Stephane Eranian410136f2013-11-12 17:58:49 +0100668
Zheng Yana6146d52012-06-15 14:31:41 +0800669 list_for_each_entry_safe(term, h, head_terms, list) {
670 alias = pmu_find_alias(pmu, term);
671 if (!alias)
672 continue;
673 ret = pmu_alias_terms(alias, &term->list);
674 if (ret)
675 return ret;
Stephane Eranian410136f2013-11-12 17:58:49 +0100676
Matt Fleming46441bd2014-09-24 15:04:06 +0100677 ret = check_unit_scale(alias, &info->unit, &info->scale);
Stephane Eranian410136f2013-11-12 17:58:49 +0100678 if (ret)
679 return ret;
680
Zheng Yana6146d52012-06-15 14:31:41 +0800681 list_del(&term->list);
682 free(term);
683 }
Stephane Eranian8a398892014-01-17 16:34:05 +0100684
685 /*
686 * if no unit or scale foundin aliases, then
687 * set defaults as for evsel
688 * unit cannot left to NULL
689 */
Matt Fleming46441bd2014-09-24 15:04:06 +0100690 if (info->unit == NULL)
691 info->unit = "";
Stephane Eranian8a398892014-01-17 16:34:05 +0100692
Matt Fleming46441bd2014-09-24 15:04:06 +0100693 if (info->scale == 0.0)
694 info->scale = 1.0;
Stephane Eranian8a398892014-01-17 16:34:05 +0100695
Zheng Yana6146d52012-06-15 14:31:41 +0800696 return 0;
697}
698
Jiri Olsacd82a322012-03-15 20:09:17 +0100699int perf_pmu__new_format(struct list_head *list, char *name,
700 int config, unsigned long *bits)
701{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300702 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100703
704 format = zalloc(sizeof(*format));
705 if (!format)
706 return -ENOMEM;
707
708 format->name = strdup(name);
709 format->value = config;
710 memcpy(format->bits, bits, sizeof(format->bits));
711
712 list_add_tail(&format->list, list);
713 return 0;
714}
715
716void perf_pmu__set_format(unsigned long *bits, long from, long to)
717{
718 long b;
719
720 if (!to)
721 to = from;
722
Sukadev Bhattiprolu15268132013-01-17 09:11:30 -0800723 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
Jiri Olsacd82a322012-03-15 20:09:17 +0100724 for (b = from; b <= to; b++)
725 set_bit(b, bits);
726}
Andi Kleendc098b32013-04-20 11:02:29 -0700727
728static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
729 struct perf_pmu_alias *alias)
730{
731 snprintf(buf, len, "%s/%s/", pmu->name, alias->name);
732 return buf;
733}
734
735static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
736 struct perf_pmu_alias *alias)
737{
738 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
739 return buf;
740}
741
742static int cmp_string(const void *a, const void *b)
743{
744 const char * const *as = a;
745 const char * const *bs = b;
746 return strcmp(*as, *bs);
747}
748
749void print_pmu_events(const char *event_glob, bool name_only)
750{
751 struct perf_pmu *pmu;
752 struct perf_pmu_alias *alias;
753 char buf[1024];
754 int printed = 0;
755 int len, j;
756 char **aliases;
757
758 pmu = NULL;
759 len = 0;
760 while ((pmu = perf_pmu__scan(pmu)) != NULL)
761 list_for_each_entry(alias, &pmu->aliases, list)
762 len++;
763 aliases = malloc(sizeof(char *) * len);
764 if (!aliases)
765 return;
766 pmu = NULL;
767 j = 0;
768 while ((pmu = perf_pmu__scan(pmu)) != NULL)
769 list_for_each_entry(alias, &pmu->aliases, list) {
770 char *name = format_alias(buf, sizeof(buf), pmu, alias);
771 bool is_cpu = !strcmp(pmu->name, "cpu");
772
773 if (event_glob != NULL &&
774 !(strglobmatch(name, event_glob) ||
775 (!is_cpu && strglobmatch(alias->name,
776 event_glob))))
777 continue;
778 aliases[j] = name;
779 if (is_cpu && !name_only)
780 aliases[j] = format_alias_or(buf, sizeof(buf),
781 pmu, alias);
782 aliases[j] = strdup(aliases[j]);
783 j++;
784 }
785 len = j;
786 qsort(aliases, len, sizeof(char *), cmp_string);
787 for (j = 0; j < len; j++) {
788 if (name_only) {
789 printf("%s ", aliases[j]);
790 continue;
791 }
792 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300793 zfree(&aliases[j]);
Andi Kleendc098b32013-04-20 11:02:29 -0700794 printed++;
795 }
796 if (printed)
797 printf("\n");
798 free(aliases);
799}
Andi Kleen4cabc3d2013-08-21 16:47:26 -0700800
801bool pmu_have_event(const char *pname, const char *name)
802{
803 struct perf_pmu *pmu;
804 struct perf_pmu_alias *alias;
805
806 pmu = NULL;
807 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
808 if (strcmp(pname, pmu->name))
809 continue;
810 list_for_each_entry(alias, &pmu->aliases, list)
811 if (!strcmp(alias->name, name))
812 return true;
813 }
814 return false;
815}
Adrian Hunter7d4bdab2014-07-31 09:00:50 +0300816
817static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
818{
819 struct stat st;
820 char path[PATH_MAX];
821 const char *sysfs;
822
823 sysfs = sysfs__mountpoint();
824 if (!sysfs)
825 return NULL;
826
827 snprintf(path, PATH_MAX,
828 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
829
830 if (stat(path, &st) < 0)
831 return NULL;
832
833 return fopen(path, "r");
834}
835
836int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
837 ...)
838{
839 va_list args;
840 FILE *file;
841 int ret = EOF;
842
843 va_start(args, fmt);
844 file = perf_pmu__open_file(pmu, name);
845 if (file) {
846 ret = vfscanf(file, fmt, args);
847 fclose(file);
848 }
849 va_end(args);
850 return ret;
851}