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