blob: 22a4ad5a927a02e87b95c69716230100d1d18931 [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
213/*
214 * Process all the sysfs attributes located under the directory
215 * specified in 'dir' parameter.
216 */
217static int pmu_aliases_parse(char *dir, struct list_head *head)
218{
219 struct dirent *evt_ent;
220 DIR *event_dir;
Stephane Eranian410136f2013-11-12 17:58:49 +0100221 size_t len;
Zheng Yana6146d52012-06-15 14:31:41 +0800222 int ret = 0;
223
224 event_dir = opendir(dir);
225 if (!event_dir)
226 return -EINVAL;
227
228 while (!ret && (evt_ent = readdir(event_dir))) {
229 char path[PATH_MAX];
230 char *name = evt_ent->d_name;
231 FILE *file;
232
233 if (!strcmp(name, ".") || !strcmp(name, ".."))
234 continue;
235
Stephane Eranian410136f2013-11-12 17:58:49 +0100236 /*
237 * skip .unit and .scale info files
238 * parsed in perf_pmu__new_alias()
239 */
240 len = strlen(name);
241 if (len > 5 && !strcmp(name + len - 5, ".unit"))
242 continue;
243 if (len > 6 && !strcmp(name + len - 6, ".scale"))
244 continue;
245
Zheng Yana6146d52012-06-15 14:31:41 +0800246 snprintf(path, PATH_MAX, "%s/%s", dir, name);
247
248 ret = -EINVAL;
249 file = fopen(path, "r");
250 if (!file)
251 break;
Stephane Eranian410136f2013-11-12 17:58:49 +0100252
253 ret = perf_pmu__new_alias(head, dir, name, file);
Zheng Yana6146d52012-06-15 14:31:41 +0800254 fclose(file);
255 }
256
257 closedir(event_dir);
258 return ret;
259}
260
261/*
262 * Reading the pmu event aliases definition, which should be located at:
263 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
264 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300265static int pmu_aliases(const char *name, struct list_head *head)
Zheng Yana6146d52012-06-15 14:31:41 +0800266{
267 struct stat st;
268 char path[PATH_MAX];
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300269 const char *sysfs = sysfs__mountpoint();
Zheng Yana6146d52012-06-15 14:31:41 +0800270
Zheng Yana6146d52012-06-15 14:31:41 +0800271 if (!sysfs)
272 return -1;
273
274 snprintf(path, PATH_MAX,
275 "%s/bus/event_source/devices/%s/events", sysfs, name);
276
277 if (stat(path, &st) < 0)
Jiri Olsa3fded962012-10-10 14:53:16 +0200278 return 0; /* no error if 'events' does not exist */
Zheng Yana6146d52012-06-15 14:31:41 +0800279
280 if (pmu_aliases_parse(path, head))
281 return -1;
282
283 return 0;
284}
285
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300286static int pmu_alias_terms(struct perf_pmu_alias *alias,
Zheng Yana6146d52012-06-15 14:31:41 +0800287 struct list_head *terms)
288{
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200289 struct parse_events_term *term, *cloned;
Zheng Yana6146d52012-06-15 14:31:41 +0800290 LIST_HEAD(list);
291 int ret;
292
293 list_for_each_entry(term, &alias->terms, list) {
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200294 ret = parse_events_term__clone(&cloned, term);
Zheng Yana6146d52012-06-15 14:31:41 +0800295 if (ret) {
296 parse_events__free_terms(&list);
297 return ret;
298 }
Jiri Olsa7c2f8162014-04-16 20:49:02 +0200299 list_add_tail(&cloned->list, &list);
Zheng Yana6146d52012-06-15 14:31:41 +0800300 }
301 list_splice(&list, terms);
302 return 0;
303}
304
Jiri Olsacd82a322012-03-15 20:09:17 +0100305/*
306 * Reading/parsing the default pmu type value, which should be
307 * located at:
308 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
309 */
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300310static int pmu_type(const char *name, __u32 *type)
Jiri Olsacd82a322012-03-15 20:09:17 +0100311{
312 struct stat st;
313 char path[PATH_MAX];
Jiri Olsacd82a322012-03-15 20:09:17 +0100314 FILE *file;
315 int ret = 0;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300316 const char *sysfs = sysfs__mountpoint();
Jiri Olsacd82a322012-03-15 20:09:17 +0100317
Jiri Olsacd82a322012-03-15 20:09:17 +0100318 if (!sysfs)
319 return -1;
320
321 snprintf(path, PATH_MAX,
Robert Richter50a96672012-08-16 21:10:24 +0200322 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
Jiri Olsacd82a322012-03-15 20:09:17 +0100323
324 if (stat(path, &st) < 0)
325 return -1;
326
327 file = fopen(path, "r");
328 if (!file)
329 return -EINVAL;
330
331 if (1 != fscanf(file, "%u", type))
332 ret = -1;
333
334 fclose(file);
335 return ret;
336}
337
Robert Richter50a96672012-08-16 21:10:24 +0200338/* Add all pmus in sysfs to pmu list: */
339static void pmu_read_sysfs(void)
340{
341 char path[PATH_MAX];
Robert Richter50a96672012-08-16 21:10:24 +0200342 DIR *dir;
343 struct dirent *dent;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300344 const char *sysfs = sysfs__mountpoint();
Robert Richter50a96672012-08-16 21:10:24 +0200345
Robert Richter50a96672012-08-16 21:10:24 +0200346 if (!sysfs)
347 return;
348
349 snprintf(path, PATH_MAX,
350 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
351
352 dir = opendir(path);
353 if (!dir)
354 return;
355
356 while ((dent = readdir(dir))) {
357 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
358 continue;
359 /* add to static LIST_HEAD(pmus): */
360 perf_pmu__find(dent->d_name);
361 }
362
363 closedir(dir);
364}
365
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300366static struct cpu_map *pmu_cpumask(const char *name)
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800367{
368 struct stat st;
369 char path[PATH_MAX];
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800370 FILE *file;
371 struct cpu_map *cpus;
Arnaldo Carvalho de Melocf38fad2013-11-05 14:48:50 -0300372 const char *sysfs = sysfs__mountpoint();
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800373
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800374 if (!sysfs)
375 return NULL;
376
377 snprintf(path, PATH_MAX,
378 "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
379
380 if (stat(path, &st) < 0)
381 return NULL;
382
383 file = fopen(path, "r");
384 if (!file)
385 return NULL;
386
387 cpus = cpu_map__read(file);
388 fclose(file);
389 return cpus;
390}
391
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300392struct perf_event_attr *__attribute__((weak))
393perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
394{
395 return NULL;
396}
397
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300398static struct perf_pmu *pmu_lookup(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100399{
400 struct perf_pmu *pmu;
401 LIST_HEAD(format);
Zheng Yana6146d52012-06-15 14:31:41 +0800402 LIST_HEAD(aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100403 __u32 type;
404
405 /*
406 * The pmu data we store & need consists of the pmu
407 * type value and format definitions. Load both right
408 * now.
409 */
410 if (pmu_format(name, &format))
411 return NULL;
412
Jiri Olsa3fded962012-10-10 14:53:16 +0200413 if (pmu_aliases(name, &aliases))
414 return NULL;
415
Jiri Olsacd82a322012-03-15 20:09:17 +0100416 if (pmu_type(name, &type))
417 return NULL;
418
419 pmu = zalloc(sizeof(*pmu));
420 if (!pmu)
421 return NULL;
422
Yan, Zheng7ae92e72012-09-10 15:53:50 +0800423 pmu->cpus = pmu_cpumask(name);
424
Jiri Olsacd82a322012-03-15 20:09:17 +0100425 INIT_LIST_HEAD(&pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800426 INIT_LIST_HEAD(&pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100427 list_splice(&format, &pmu->format);
Zheng Yana6146d52012-06-15 14:31:41 +0800428 list_splice(&aliases, &pmu->aliases);
Jiri Olsacd82a322012-03-15 20:09:17 +0100429 pmu->name = strdup(name);
430 pmu->type = type;
Robert Richter9bc8f9f2012-06-14 22:38:37 +0200431 list_add_tail(&pmu->list, &pmus);
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300432
433 pmu->default_config = perf_pmu__get_default_config(pmu);
434
Jiri Olsacd82a322012-03-15 20:09:17 +0100435 return pmu;
436}
437
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300438static struct perf_pmu *pmu_find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100439{
440 struct perf_pmu *pmu;
441
442 list_for_each_entry(pmu, &pmus, list)
443 if (!strcmp(pmu->name, name))
444 return pmu;
445
446 return NULL;
447}
448
Robert Richter50a96672012-08-16 21:10:24 +0200449struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
450{
451 /*
452 * pmu iterator: If pmu is NULL, we start at the begin,
453 * otherwise return the next pmu. Returns NULL on end.
454 */
455 if (!pmu) {
456 pmu_read_sysfs();
457 pmu = list_prepare_entry(pmu, &pmus, list);
458 }
459 list_for_each_entry_continue(pmu, &pmus, list)
460 return pmu;
461 return NULL;
462}
463
Adrian Hunterb6b96fb2013-07-04 16:20:25 +0300464struct perf_pmu *perf_pmu__find(const char *name)
Jiri Olsacd82a322012-03-15 20:09:17 +0100465{
466 struct perf_pmu *pmu;
467
468 /*
469 * Once PMU is loaded it stays in the list,
470 * so we keep us from multiple reading/parsing
471 * the pmu format definitions.
472 */
473 pmu = pmu_find(name);
474 if (pmu)
475 return pmu;
476
477 return pmu_lookup(name);
478}
479
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300480static struct perf_pmu_format *
Jiri Olsacd82a322012-03-15 20:09:17 +0100481pmu_find_format(struct list_head *formats, char *name)
482{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300483 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100484
485 list_for_each_entry(format, formats, list)
486 if (!strcmp(format->name, name))
487 return format;
488
489 return NULL;
490}
491
492/*
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300493 * Sets value based on the format definition (format parameter)
Jiri Olsacd82a322012-03-15 20:09:17 +0100494 * and unformated value (value parameter).
Jiri Olsacd82a322012-03-15 20:09:17 +0100495 */
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300496static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
497 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100498{
499 unsigned long fbit, vbit;
Jiri Olsacd82a322012-03-15 20:09:17 +0100500
501 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
502
503 if (!test_bit(fbit, format))
504 continue;
505
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300506 if (value & (1llu << vbit++))
507 *v |= (1llu << fbit);
508 else if (zero)
509 *v &= ~(1llu << fbit);
Jiri Olsacd82a322012-03-15 20:09:17 +0100510 }
Jiri Olsacd82a322012-03-15 20:09:17 +0100511}
512
513/*
514 * Setup one of config[12] attr members based on the
Cody P Schafer88aca8d2014-01-08 08:43:51 -0800515 * user input data - term parameter.
Jiri Olsacd82a322012-03-15 20:09:17 +0100516 */
517static int pmu_config_term(struct list_head *formats,
518 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300519 struct parse_events_term *term,
520 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100521{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300522 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100523 __u64 *vp;
524
525 /*
526 * Support only for hardcoded and numnerial terms.
527 * Hardcoded terms should be already in, so nothing
528 * to be done for them.
529 */
530 if (parse_events__is_hardcoded_term(term))
531 return 0;
532
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200533 if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
Jiri Olsacd82a322012-03-15 20:09:17 +0100534 return -EINVAL;
535
536 format = pmu_find_format(formats, term->config);
537 if (!format)
538 return -EINVAL;
539
540 switch (format->value) {
541 case PERF_PMU_FORMAT_VALUE_CONFIG:
542 vp = &attr->config;
543 break;
544 case PERF_PMU_FORMAT_VALUE_CONFIG1:
545 vp = &attr->config1;
546 break;
547 case PERF_PMU_FORMAT_VALUE_CONFIG2:
548 vp = &attr->config2;
549 break;
550 default:
551 return -EINVAL;
552 }
553
Jiri Olsa16fa7e82012-04-25 18:24:57 +0200554 /*
555 * XXX If we ever decide to go with string values for
556 * non-hardcoded terms, here's the place to translate
557 * them into value.
558 */
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300559 pmu_format_value(format->bits, term->val.num, vp, zero);
Jiri Olsacd82a322012-03-15 20:09:17 +0100560 return 0;
561}
562
Jiri Olsacff7f952012-11-10 01:46:50 +0100563int perf_pmu__config_terms(struct list_head *formats,
564 struct perf_event_attr *attr,
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300565 struct list_head *head_terms,
566 bool zero)
Jiri Olsacd82a322012-03-15 20:09:17 +0100567{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300568 struct parse_events_term *term;
Jiri Olsacd82a322012-03-15 20:09:17 +0100569
Jiri Olsa6b5fc392012-05-21 09:12:53 +0200570 list_for_each_entry(term, head_terms, list)
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300571 if (pmu_config_term(formats, attr, term, zero))
Jiri Olsacd82a322012-03-15 20:09:17 +0100572 return -EINVAL;
573
574 return 0;
575}
576
577/*
578 * Configures event's 'attr' parameter based on the:
579 * 1) users input - specified in terms parameter
580 * 2) pmu format definitions - specified by pmu parameter
581 */
582int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
583 struct list_head *head_terms)
584{
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300585 bool zero = !!pmu->default_config;
586
Jiri Olsacd82a322012-03-15 20:09:17 +0100587 attr->type = pmu->type;
Adrian Hunterdc0a6202014-07-31 09:00:49 +0300588 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
Jiri Olsacd82a322012-03-15 20:09:17 +0100589}
590
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300591static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
592 struct parse_events_term *term)
Zheng Yana6146d52012-06-15 14:31:41 +0800593{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300594 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800595 char *name;
596
597 if (parse_events__is_hardcoded_term(term))
598 return NULL;
599
600 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
601 if (term->val.num != 1)
602 return NULL;
603 if (pmu_find_format(&pmu->format, term->config))
604 return NULL;
605 name = term->config;
606 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
607 if (strcasecmp(term->config, "event"))
608 return NULL;
609 name = term->val.str;
610 } else {
611 return NULL;
612 }
613
614 list_for_each_entry(alias, &pmu->aliases, list) {
615 if (!strcasecmp(alias->name, name))
616 return alias;
617 }
618 return NULL;
619}
620
Stephane Eranian410136f2013-11-12 17:58:49 +0100621
622static int check_unit_scale(struct perf_pmu_alias *alias,
Stephane Eranian8a398892014-01-17 16:34:05 +0100623 const char **unit, double *scale)
Stephane Eranian410136f2013-11-12 17:58:49 +0100624{
625 /*
626 * Only one term in event definition can
627 * define unit and scale, fail if there's
628 * more than one.
629 */
630 if ((*unit && alias->unit) ||
631 (*scale && alias->scale))
632 return -EINVAL;
633
634 if (alias->unit)
635 *unit = alias->unit;
636
637 if (alias->scale)
638 *scale = alias->scale;
639
640 return 0;
641}
642
Zheng Yana6146d52012-06-15 14:31:41 +0800643/*
644 * Find alias in the terms list and replace it with the terms
645 * defined for the alias
646 */
Stephane Eranian410136f2013-11-12 17:58:49 +0100647int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
Stephane Eranian8a398892014-01-17 16:34:05 +0100648 const char **unit, double *scale)
Zheng Yana6146d52012-06-15 14:31:41 +0800649{
Arnaldo Carvalho de Melo6cee6cd2013-01-18 16:29:49 -0300650 struct parse_events_term *term, *h;
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300651 struct perf_pmu_alias *alias;
Zheng Yana6146d52012-06-15 14:31:41 +0800652 int ret;
653
Stephane Eranian8a398892014-01-17 16:34:05 +0100654 /*
655 * Mark unit and scale as not set
656 * (different from default values, see below)
657 */
Stephane Eranian410136f2013-11-12 17:58:49 +0100658 *unit = NULL;
Stephane Eranian8a398892014-01-17 16:34:05 +0100659 *scale = 0.0;
Stephane Eranian410136f2013-11-12 17:58:49 +0100660
Zheng Yana6146d52012-06-15 14:31:41 +0800661 list_for_each_entry_safe(term, h, head_terms, list) {
662 alias = pmu_find_alias(pmu, term);
663 if (!alias)
664 continue;
665 ret = pmu_alias_terms(alias, &term->list);
666 if (ret)
667 return ret;
Stephane Eranian410136f2013-11-12 17:58:49 +0100668
669 ret = check_unit_scale(alias, unit, scale);
670 if (ret)
671 return ret;
672
Zheng Yana6146d52012-06-15 14:31:41 +0800673 list_del(&term->list);
674 free(term);
675 }
Stephane Eranian8a398892014-01-17 16:34:05 +0100676
677 /*
678 * if no unit or scale foundin aliases, then
679 * set defaults as for evsel
680 * unit cannot left to NULL
681 */
682 if (*unit == NULL)
683 *unit = "";
684
685 if (*scale == 0.0)
686 *scale = 1.0;
687
Zheng Yana6146d52012-06-15 14:31:41 +0800688 return 0;
689}
690
Jiri Olsacd82a322012-03-15 20:09:17 +0100691int perf_pmu__new_format(struct list_head *list, char *name,
692 int config, unsigned long *bits)
693{
Arnaldo Carvalho de Melo5c6ccc32013-01-18 16:54:00 -0300694 struct perf_pmu_format *format;
Jiri Olsacd82a322012-03-15 20:09:17 +0100695
696 format = zalloc(sizeof(*format));
697 if (!format)
698 return -ENOMEM;
699
700 format->name = strdup(name);
701 format->value = config;
702 memcpy(format->bits, bits, sizeof(format->bits));
703
704 list_add_tail(&format->list, list);
705 return 0;
706}
707
708void perf_pmu__set_format(unsigned long *bits, long from, long to)
709{
710 long b;
711
712 if (!to)
713 to = from;
714
Sukadev Bhattiprolu15268132013-01-17 09:11:30 -0800715 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
Jiri Olsacd82a322012-03-15 20:09:17 +0100716 for (b = from; b <= to; b++)
717 set_bit(b, bits);
718}
Andi Kleendc098b32013-04-20 11:02:29 -0700719
720static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
721 struct perf_pmu_alias *alias)
722{
723 snprintf(buf, len, "%s/%s/", pmu->name, alias->name);
724 return buf;
725}
726
727static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
728 struct perf_pmu_alias *alias)
729{
730 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
731 return buf;
732}
733
734static int cmp_string(const void *a, const void *b)
735{
736 const char * const *as = a;
737 const char * const *bs = b;
738 return strcmp(*as, *bs);
739}
740
741void print_pmu_events(const char *event_glob, bool name_only)
742{
743 struct perf_pmu *pmu;
744 struct perf_pmu_alias *alias;
745 char buf[1024];
746 int printed = 0;
747 int len, j;
748 char **aliases;
749
750 pmu = NULL;
751 len = 0;
752 while ((pmu = perf_pmu__scan(pmu)) != NULL)
753 list_for_each_entry(alias, &pmu->aliases, list)
754 len++;
755 aliases = malloc(sizeof(char *) * len);
756 if (!aliases)
757 return;
758 pmu = NULL;
759 j = 0;
760 while ((pmu = perf_pmu__scan(pmu)) != NULL)
761 list_for_each_entry(alias, &pmu->aliases, list) {
762 char *name = format_alias(buf, sizeof(buf), pmu, alias);
763 bool is_cpu = !strcmp(pmu->name, "cpu");
764
765 if (event_glob != NULL &&
766 !(strglobmatch(name, event_glob) ||
767 (!is_cpu && strglobmatch(alias->name,
768 event_glob))))
769 continue;
770 aliases[j] = name;
771 if (is_cpu && !name_only)
772 aliases[j] = format_alias_or(buf, sizeof(buf),
773 pmu, alias);
774 aliases[j] = strdup(aliases[j]);
775 j++;
776 }
777 len = j;
778 qsort(aliases, len, sizeof(char *), cmp_string);
779 for (j = 0; j < len; j++) {
780 if (name_only) {
781 printf("%s ", aliases[j]);
782 continue;
783 }
784 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300785 zfree(&aliases[j]);
Andi Kleendc098b32013-04-20 11:02:29 -0700786 printed++;
787 }
788 if (printed)
789 printf("\n");
790 free(aliases);
791}
Andi Kleen4cabc3d2013-08-21 16:47:26 -0700792
793bool pmu_have_event(const char *pname, const char *name)
794{
795 struct perf_pmu *pmu;
796 struct perf_pmu_alias *alias;
797
798 pmu = NULL;
799 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
800 if (strcmp(pname, pmu->name))
801 continue;
802 list_for_each_entry(alias, &pmu->aliases, list)
803 if (!strcmp(alias->name, name))
804 return true;
805 }
806 return false;
807}
Adrian Hunter7d4bdab2014-07-31 09:00:50 +0300808
809static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
810{
811 struct stat st;
812 char path[PATH_MAX];
813 const char *sysfs;
814
815 sysfs = sysfs__mountpoint();
816 if (!sysfs)
817 return NULL;
818
819 snprintf(path, PATH_MAX,
820 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
821
822 if (stat(path, &st) < 0)
823 return NULL;
824
825 return fopen(path, "r");
826}
827
828int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
829 ...)
830{
831 va_list args;
832 FILE *file;
833 int ret = EOF;
834
835 va_start(args, fmt);
836 file = perf_pmu__open_file(pmu, name);
837 if (file) {
838 ret = vfscanf(file, fmt, args);
839 fclose(file);
840 }
841 va_end(args);
842 return ret;
843}