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