]> Pileus Git - ~andy/linux/blob - tools/perf/util/pmu.c
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
[~andy/linux] / tools / perf / util / pmu.c
1 #include <linux/list.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <dirent.h>
7 #include "fs.h"
8 #include "util.h"
9 #include "pmu.h"
10 #include "parse-events.h"
11 #include "cpumap.h"
12
13 struct perf_pmu_alias {
14         char *name;
15         struct list_head terms;
16         struct list_head list;
17 };
18
19 struct perf_pmu_format {
20         char *name;
21         int value;
22         DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
23         struct list_head list;
24 };
25
26 #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
27
28 int perf_pmu_parse(struct list_head *list, char *name);
29 extern FILE *perf_pmu_in;
30
31 static LIST_HEAD(pmus);
32
33 /*
34  * Parse & process all the sysfs attributes located under
35  * the directory specified in 'dir' parameter.
36  */
37 int perf_pmu__format_parse(char *dir, struct list_head *head)
38 {
39         struct dirent *evt_ent;
40         DIR *format_dir;
41         int ret = 0;
42
43         format_dir = opendir(dir);
44         if (!format_dir)
45                 return -EINVAL;
46
47         while (!ret && (evt_ent = readdir(format_dir))) {
48                 char path[PATH_MAX];
49                 char *name = evt_ent->d_name;
50                 FILE *file;
51
52                 if (!strcmp(name, ".") || !strcmp(name, ".."))
53                         continue;
54
55                 snprintf(path, PATH_MAX, "%s/%s", dir, name);
56
57                 ret = -EINVAL;
58                 file = fopen(path, "r");
59                 if (!file)
60                         break;
61
62                 perf_pmu_in = file;
63                 ret = perf_pmu_parse(head, name);
64                 fclose(file);
65         }
66
67         closedir(format_dir);
68         return ret;
69 }
70
71 /*
72  * Reading/parsing the default pmu format definition, which should be
73  * located at:
74  * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
75  */
76 static int pmu_format(const char *name, struct list_head *format)
77 {
78         struct stat st;
79         char path[PATH_MAX];
80         const char *sysfs = sysfs__mountpoint();
81
82         if (!sysfs)
83                 return -1;
84
85         snprintf(path, PATH_MAX,
86                  "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
87
88         if (stat(path, &st) < 0)
89                 return 0;       /* no error if format does not exist */
90
91         if (perf_pmu__format_parse(path, format))
92                 return -1;
93
94         return 0;
95 }
96
97 static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
98 {
99         struct perf_pmu_alias *alias;
100         char buf[256];
101         int ret;
102
103         ret = fread(buf, 1, sizeof(buf), file);
104         if (ret == 0)
105                 return -EINVAL;
106         buf[ret] = 0;
107
108         alias = malloc(sizeof(*alias));
109         if (!alias)
110                 return -ENOMEM;
111
112         INIT_LIST_HEAD(&alias->terms);
113         ret = parse_events_terms(&alias->terms, buf);
114         if (ret) {
115                 free(alias);
116                 return ret;
117         }
118
119         alias->name = strdup(name);
120         list_add_tail(&alias->list, list);
121         return 0;
122 }
123
124 /*
125  * Process all the sysfs attributes located under the directory
126  * specified in 'dir' parameter.
127  */
128 static int pmu_aliases_parse(char *dir, struct list_head *head)
129 {
130         struct dirent *evt_ent;
131         DIR *event_dir;
132         int ret = 0;
133
134         event_dir = opendir(dir);
135         if (!event_dir)
136                 return -EINVAL;
137
138         while (!ret && (evt_ent = readdir(event_dir))) {
139                 char path[PATH_MAX];
140                 char *name = evt_ent->d_name;
141                 FILE *file;
142
143                 if (!strcmp(name, ".") || !strcmp(name, ".."))
144                         continue;
145
146                 snprintf(path, PATH_MAX, "%s/%s", dir, name);
147
148                 ret = -EINVAL;
149                 file = fopen(path, "r");
150                 if (!file)
151                         break;
152                 ret = perf_pmu__new_alias(head, name, file);
153                 fclose(file);
154         }
155
156         closedir(event_dir);
157         return ret;
158 }
159
160 /*
161  * Reading the pmu event aliases definition, which should be located at:
162  * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
163  */
164 static int pmu_aliases(const char *name, struct list_head *head)
165 {
166         struct stat st;
167         char path[PATH_MAX];
168         const char *sysfs = sysfs__mountpoint();
169
170         if (!sysfs)
171                 return -1;
172
173         snprintf(path, PATH_MAX,
174                  "%s/bus/event_source/devices/%s/events", sysfs, name);
175
176         if (stat(path, &st) < 0)
177                 return 0;        /* no error if 'events' does not exist */
178
179         if (pmu_aliases_parse(path, head))
180                 return -1;
181
182         return 0;
183 }
184
185 static int pmu_alias_terms(struct perf_pmu_alias *alias,
186                            struct list_head *terms)
187 {
188         struct parse_events_term *term, *clone;
189         LIST_HEAD(list);
190         int ret;
191
192         list_for_each_entry(term, &alias->terms, list) {
193                 ret = parse_events_term__clone(&clone, term);
194                 if (ret) {
195                         parse_events__free_terms(&list);
196                         return ret;
197                 }
198                 list_add_tail(&clone->list, &list);
199         }
200         list_splice(&list, terms);
201         return 0;
202 }
203
204 /*
205  * Reading/parsing the default pmu type value, which should be
206  * located at:
207  * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
208  */
209 static int pmu_type(const char *name, __u32 *type)
210 {
211         struct stat st;
212         char path[PATH_MAX];
213         FILE *file;
214         int ret = 0;
215         const char *sysfs = sysfs__mountpoint();
216
217         if (!sysfs)
218                 return -1;
219
220         snprintf(path, PATH_MAX,
221                  "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
222
223         if (stat(path, &st) < 0)
224                 return -1;
225
226         file = fopen(path, "r");
227         if (!file)
228                 return -EINVAL;
229
230         if (1 != fscanf(file, "%u", type))
231                 ret = -1;
232
233         fclose(file);
234         return ret;
235 }
236
237 /* Add all pmus in sysfs to pmu list: */
238 static void pmu_read_sysfs(void)
239 {
240         char path[PATH_MAX];
241         DIR *dir;
242         struct dirent *dent;
243         const char *sysfs = sysfs__mountpoint();
244
245         if (!sysfs)
246                 return;
247
248         snprintf(path, PATH_MAX,
249                  "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
250
251         dir = opendir(path);
252         if (!dir)
253                 return;
254
255         while ((dent = readdir(dir))) {
256                 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
257                         continue;
258                 /* add to static LIST_HEAD(pmus): */
259                 perf_pmu__find(dent->d_name);
260         }
261
262         closedir(dir);
263 }
264
265 static struct cpu_map *pmu_cpumask(const char *name)
266 {
267         struct stat st;
268         char path[PATH_MAX];
269         FILE *file;
270         struct cpu_map *cpus;
271         const char *sysfs = sysfs__mountpoint();
272
273         if (!sysfs)
274                 return NULL;
275
276         snprintf(path, PATH_MAX,
277                  "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
278
279         if (stat(path, &st) < 0)
280                 return NULL;
281
282         file = fopen(path, "r");
283         if (!file)
284                 return NULL;
285
286         cpus = cpu_map__read(file);
287         fclose(file);
288         return cpus;
289 }
290
291 static struct perf_pmu *pmu_lookup(const char *name)
292 {
293         struct perf_pmu *pmu;
294         LIST_HEAD(format);
295         LIST_HEAD(aliases);
296         __u32 type;
297
298         /*
299          * The pmu data we store & need consists of the pmu
300          * type value and format definitions. Load both right
301          * now.
302          */
303         if (pmu_format(name, &format))
304                 return NULL;
305
306         if (pmu_aliases(name, &aliases))
307                 return NULL;
308
309         if (pmu_type(name, &type))
310                 return NULL;
311
312         pmu = zalloc(sizeof(*pmu));
313         if (!pmu)
314                 return NULL;
315
316         pmu->cpus = pmu_cpumask(name);
317
318         INIT_LIST_HEAD(&pmu->format);
319         INIT_LIST_HEAD(&pmu->aliases);
320         list_splice(&format, &pmu->format);
321         list_splice(&aliases, &pmu->aliases);
322         pmu->name = strdup(name);
323         pmu->type = type;
324         list_add_tail(&pmu->list, &pmus);
325         return pmu;
326 }
327
328 static struct perf_pmu *pmu_find(const char *name)
329 {
330         struct perf_pmu *pmu;
331
332         list_for_each_entry(pmu, &pmus, list)
333                 if (!strcmp(pmu->name, name))
334                         return pmu;
335
336         return NULL;
337 }
338
339 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
340 {
341         /*
342          * pmu iterator: If pmu is NULL, we start at the begin,
343          * otherwise return the next pmu. Returns NULL on end.
344          */
345         if (!pmu) {
346                 pmu_read_sysfs();
347                 pmu = list_prepare_entry(pmu, &pmus, list);
348         }
349         list_for_each_entry_continue(pmu, &pmus, list)
350                 return pmu;
351         return NULL;
352 }
353
354 struct perf_pmu *perf_pmu__find(const char *name)
355 {
356         struct perf_pmu *pmu;
357
358         /*
359          * Once PMU is loaded it stays in the list,
360          * so we keep us from multiple reading/parsing
361          * the pmu format definitions.
362          */
363         pmu = pmu_find(name);
364         if (pmu)
365                 return pmu;
366
367         return pmu_lookup(name);
368 }
369
370 static struct perf_pmu_format *
371 pmu_find_format(struct list_head *formats, char *name)
372 {
373         struct perf_pmu_format *format;
374
375         list_for_each_entry(format, formats, list)
376                 if (!strcmp(format->name, name))
377                         return format;
378
379         return NULL;
380 }
381
382 /*
383  * Returns value based on the format definition (format parameter)
384  * and unformated value (value parameter).
385  *
386  * TODO maybe optimize a little ;)
387  */
388 static __u64 pmu_format_value(unsigned long *format, __u64 value)
389 {
390         unsigned long fbit, vbit;
391         __u64 v = 0;
392
393         for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
394
395                 if (!test_bit(fbit, format))
396                         continue;
397
398                 if (!(value & (1llu << vbit++)))
399                         continue;
400
401                 v |= (1llu << fbit);
402         }
403
404         return v;
405 }
406
407 /*
408  * Setup one of config[12] attr members based on the
409  * user input data - temr parameter.
410  */
411 static int pmu_config_term(struct list_head *formats,
412                            struct perf_event_attr *attr,
413                            struct parse_events_term *term)
414 {
415         struct perf_pmu_format *format;
416         __u64 *vp;
417
418         /*
419          * Support only for hardcoded and numnerial terms.
420          * Hardcoded terms should be already in, so nothing
421          * to be done for them.
422          */
423         if (parse_events__is_hardcoded_term(term))
424                 return 0;
425
426         if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
427                 return -EINVAL;
428
429         format = pmu_find_format(formats, term->config);
430         if (!format)
431                 return -EINVAL;
432
433         switch (format->value) {
434         case PERF_PMU_FORMAT_VALUE_CONFIG:
435                 vp = &attr->config;
436                 break;
437         case PERF_PMU_FORMAT_VALUE_CONFIG1:
438                 vp = &attr->config1;
439                 break;
440         case PERF_PMU_FORMAT_VALUE_CONFIG2:
441                 vp = &attr->config2;
442                 break;
443         default:
444                 return -EINVAL;
445         }
446
447         /*
448          * XXX If we ever decide to go with string values for
449          * non-hardcoded terms, here's the place to translate
450          * them into value.
451          */
452         *vp |= pmu_format_value(format->bits, term->val.num);
453         return 0;
454 }
455
456 int perf_pmu__config_terms(struct list_head *formats,
457                            struct perf_event_attr *attr,
458                            struct list_head *head_terms)
459 {
460         struct parse_events_term *term;
461
462         list_for_each_entry(term, head_terms, list)
463                 if (pmu_config_term(formats, attr, term))
464                         return -EINVAL;
465
466         return 0;
467 }
468
469 /*
470  * Configures event's 'attr' parameter based on the:
471  * 1) users input - specified in terms parameter
472  * 2) pmu format definitions - specified by pmu parameter
473  */
474 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
475                      struct list_head *head_terms)
476 {
477         attr->type = pmu->type;
478         return perf_pmu__config_terms(&pmu->format, attr, head_terms);
479 }
480
481 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
482                                              struct parse_events_term *term)
483 {
484         struct perf_pmu_alias *alias;
485         char *name;
486
487         if (parse_events__is_hardcoded_term(term))
488                 return NULL;
489
490         if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
491                 if (term->val.num != 1)
492                         return NULL;
493                 if (pmu_find_format(&pmu->format, term->config))
494                         return NULL;
495                 name = term->config;
496         } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
497                 if (strcasecmp(term->config, "event"))
498                         return NULL;
499                 name = term->val.str;
500         } else {
501                 return NULL;
502         }
503
504         list_for_each_entry(alias, &pmu->aliases, list) {
505                 if (!strcasecmp(alias->name, name))
506                         return alias;
507         }
508         return NULL;
509 }
510
511 /*
512  * Find alias in the terms list and replace it with the terms
513  * defined for the alias
514  */
515 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
516 {
517         struct parse_events_term *term, *h;
518         struct perf_pmu_alias *alias;
519         int ret;
520
521         list_for_each_entry_safe(term, h, head_terms, list) {
522                 alias = pmu_find_alias(pmu, term);
523                 if (!alias)
524                         continue;
525                 ret = pmu_alias_terms(alias, &term->list);
526                 if (ret)
527                         return ret;
528                 list_del(&term->list);
529                 free(term);
530         }
531         return 0;
532 }
533
534 int perf_pmu__new_format(struct list_head *list, char *name,
535                          int config, unsigned long *bits)
536 {
537         struct perf_pmu_format *format;
538
539         format = zalloc(sizeof(*format));
540         if (!format)
541                 return -ENOMEM;
542
543         format->name = strdup(name);
544         format->value = config;
545         memcpy(format->bits, bits, sizeof(format->bits));
546
547         list_add_tail(&format->list, list);
548         return 0;
549 }
550
551 void perf_pmu__set_format(unsigned long *bits, long from, long to)
552 {
553         long b;
554
555         if (!to)
556                 to = from;
557
558         memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
559         for (b = from; b <= to; b++)
560                 set_bit(b, bits);
561 }
562
563 static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
564                           struct perf_pmu_alias *alias)
565 {
566         snprintf(buf, len, "%s/%s/", pmu->name, alias->name);
567         return buf;
568 }
569
570 static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
571                              struct perf_pmu_alias *alias)
572 {
573         snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
574         return buf;
575 }
576
577 static int cmp_string(const void *a, const void *b)
578 {
579         const char * const *as = a;
580         const char * const *bs = b;
581         return strcmp(*as, *bs);
582 }
583
584 void print_pmu_events(const char *event_glob, bool name_only)
585 {
586         struct perf_pmu *pmu;
587         struct perf_pmu_alias *alias;
588         char buf[1024];
589         int printed = 0;
590         int len, j;
591         char **aliases;
592
593         pmu = NULL;
594         len = 0;
595         while ((pmu = perf_pmu__scan(pmu)) != NULL)
596                 list_for_each_entry(alias, &pmu->aliases, list)
597                         len++;
598         aliases = malloc(sizeof(char *) * len);
599         if (!aliases)
600                 return;
601         pmu = NULL;
602         j = 0;
603         while ((pmu = perf_pmu__scan(pmu)) != NULL)
604                 list_for_each_entry(alias, &pmu->aliases, list) {
605                         char *name = format_alias(buf, sizeof(buf), pmu, alias);
606                         bool is_cpu = !strcmp(pmu->name, "cpu");
607
608                         if (event_glob != NULL &&
609                             !(strglobmatch(name, event_glob) ||
610                               (!is_cpu && strglobmatch(alias->name,
611                                                        event_glob))))
612                                 continue;
613                         aliases[j] = name;
614                         if (is_cpu && !name_only)
615                                 aliases[j] = format_alias_or(buf, sizeof(buf),
616                                                               pmu, alias);
617                         aliases[j] = strdup(aliases[j]);
618                         j++;
619                 }
620         len = j;
621         qsort(aliases, len, sizeof(char *), cmp_string);
622         for (j = 0; j < len; j++) {
623                 if (name_only) {
624                         printf("%s ", aliases[j]);
625                         continue;
626                 }
627                 printf("  %-50s [Kernel PMU event]\n", aliases[j]);
628                 free(aliases[j]);
629                 printed++;
630         }
631         if (printed)
632                 printf("\n");
633         free(aliases);
634 }
635
636 bool pmu_have_event(const char *pname, const char *name)
637 {
638         struct perf_pmu *pmu;
639         struct perf_pmu_alias *alias;
640
641         pmu = NULL;
642         while ((pmu = perf_pmu__scan(pmu)) != NULL) {
643                 if (strcmp(pname, pmu->name))
644                         continue;
645                 list_for_each_entry(alias, &pmu->aliases, list)
646                         if (!strcmp(alias->name, name))
647                                 return true;
648         }
649         return false;
650 }