• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <linux/list.h>
2 #include <linux/compiler.h>
3 #include <sys/types.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <stdbool.h>
7 #include <stdarg.h>
8 #include <dirent.h>
9 #include <api/fs/fs.h>
10 #include <locale.h>
11 #include "util.h"
12 #include "pmu.h"
13 #include "parse-events.h"
14 #include "cpumap.h"
15 
16 struct perf_pmu_format {
17 	char *name;
18 	int value;
19 	DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);
20 	struct list_head list;
21 };
22 
23 #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
24 
25 int perf_pmu_parse(struct list_head *list, char *name);
26 extern FILE *perf_pmu_in;
27 
28 static LIST_HEAD(pmus);
29 
30 /*
31  * Parse & process all the sysfs attributes located under
32  * the directory specified in 'dir' parameter.
33  */
perf_pmu__format_parse(char * dir,struct list_head * head)34 int perf_pmu__format_parse(char *dir, struct list_head *head)
35 {
36 	struct dirent *evt_ent;
37 	DIR *format_dir;
38 	int ret = 0;
39 
40 	format_dir = opendir(dir);
41 	if (!format_dir)
42 		return -EINVAL;
43 
44 	while (!ret && (evt_ent = readdir(format_dir))) {
45 		char path[PATH_MAX];
46 		char *name = evt_ent->d_name;
47 		FILE *file;
48 
49 		if (!strcmp(name, ".") || !strcmp(name, ".."))
50 			continue;
51 
52 		snprintf(path, PATH_MAX, "%s/%s", dir, name);
53 
54 		ret = -EINVAL;
55 		file = fopen(path, "r");
56 		if (!file)
57 			break;
58 
59 		perf_pmu_in = file;
60 		ret = perf_pmu_parse(head, name);
61 		fclose(file);
62 	}
63 
64 	closedir(format_dir);
65 	return ret;
66 }
67 
68 /*
69  * Reading/parsing the default pmu format definition, which should be
70  * located at:
71  * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.
72  */
pmu_format(const char * name,struct list_head * format)73 static int pmu_format(const char *name, struct list_head *format)
74 {
75 	struct stat st;
76 	char path[PATH_MAX];
77 	const char *sysfs = sysfs__mountpoint();
78 
79 	if (!sysfs)
80 		return -1;
81 
82 	snprintf(path, PATH_MAX,
83 		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);
84 
85 	if (stat(path, &st) < 0)
86 		return 0;	/* no error if format does not exist */
87 
88 	if (perf_pmu__format_parse(path, format))
89 		return -1;
90 
91 	return 0;
92 }
93 
perf_pmu__parse_scale(struct perf_pmu_alias * alias,char * dir,char * name)94 static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
95 {
96 	struct stat st;
97 	ssize_t sret;
98 	char scale[128];
99 	int fd, ret = -1;
100 	char path[PATH_MAX];
101 	const char *lc;
102 
103 	scnprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
104 
105 	fd = open(path, O_RDONLY);
106 	if (fd == -1)
107 		return -1;
108 
109 	if (fstat(fd, &st) < 0)
110 		goto error;
111 
112 	sret = read(fd, scale, sizeof(scale)-1);
113 	if (sret < 0)
114 		goto error;
115 
116 	if (scale[sret - 1] == '\n')
117 		scale[sret - 1] = '\0';
118 	else
119 		scale[sret] = '\0';
120 
121 	/*
122 	 * save current locale
123 	 */
124 	lc = setlocale(LC_NUMERIC, NULL);
125 
126 	/*
127 	 * force to C locale to ensure kernel
128 	 * scale string is converted correctly.
129 	 * kernel uses default C locale.
130 	 */
131 	setlocale(LC_NUMERIC, "C");
132 
133 	alias->scale = strtod(scale, NULL);
134 
135 	/* restore locale */
136 	setlocale(LC_NUMERIC, lc);
137 
138 	ret = 0;
139 error:
140 	close(fd);
141 	return ret;
142 }
143 
perf_pmu__parse_unit(struct perf_pmu_alias * alias,char * dir,char * name)144 static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
145 {
146 	char path[PATH_MAX];
147 	ssize_t sret;
148 	int fd;
149 
150 	scnprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
151 
152 	fd = open(path, O_RDONLY);
153 	if (fd == -1)
154 		return -1;
155 
156 	sret = read(fd, alias->unit, UNIT_MAX_LEN);
157 	if (sret < 0)
158 		goto error;
159 
160 	close(fd);
161 
162 	if (alias->unit[sret - 1] == '\n')
163 		alias->unit[sret - 1] = '\0';
164 	else
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__parse_per_pkg(struct perf_pmu_alias * alias,char * dir,char * name)175 perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
176 {
177 	char path[PATH_MAX];
178 	int fd;
179 
180 	scnprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
181 
182 	fd = open(path, O_RDONLY);
183 	if (fd == -1)
184 		return -1;
185 
186 	close(fd);
187 
188 	alias->per_pkg = true;
189 	return 0;
190 }
191 
perf_pmu__parse_snapshot(struct perf_pmu_alias * alias,char * dir,char * name)192 static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
193 				    char *dir, char *name)
194 {
195 	char path[PATH_MAX];
196 	int fd;
197 
198 	scnprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
199 
200 	fd = open(path, O_RDONLY);
201 	if (fd == -1)
202 		return -1;
203 
204 	alias->snapshot = true;
205 	close(fd);
206 	return 0;
207 }
208 
__perf_pmu__new_alias(struct list_head * list,char * dir,char * name,char * desc __maybe_unused,char * val)209 static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
210 				 char *desc __maybe_unused, char *val)
211 {
212 	struct perf_pmu_alias *alias;
213 	int ret;
214 
215 	alias = malloc(sizeof(*alias));
216 	if (!alias)
217 		return -ENOMEM;
218 
219 	INIT_LIST_HEAD(&alias->terms);
220 	alias->scale = 1.0;
221 	alias->unit[0] = '\0';
222 	alias->per_pkg = false;
223 
224 	ret = parse_events_terms(&alias->terms, val);
225 	if (ret) {
226 		pr_err("Cannot parse alias %s: %d\n", val, ret);
227 		free(alias);
228 		return ret;
229 	}
230 
231 	alias->name = strdup(name);
232 	if (dir) {
233 		/*
234 		 * load unit name and scale if available
235 		 */
236 		perf_pmu__parse_unit(alias, dir, name);
237 		perf_pmu__parse_scale(alias, dir, name);
238 		perf_pmu__parse_per_pkg(alias, dir, name);
239 		perf_pmu__parse_snapshot(alias, dir, name);
240 	}
241 
242 	list_add_tail(&alias->list, list);
243 
244 	return 0;
245 }
246 
perf_pmu__new_alias(struct list_head * list,char * dir,char * name,FILE * file)247 static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
248 {
249 	char buf[256];
250 	int ret;
251 
252 	ret = fread(buf, 1, sizeof(buf), file);
253 	if (ret == 0)
254 		return -EINVAL;
255 
256 	buf[ret] = 0;
257 
258 	return __perf_pmu__new_alias(list, dir, name, NULL, buf);
259 }
260 
pmu_alias_info_file(char * name)261 static inline bool pmu_alias_info_file(char *name)
262 {
263 	size_t len;
264 
265 	len = strlen(name);
266 	if (len > 5 && !strcmp(name + len - 5, ".unit"))
267 		return true;
268 	if (len > 6 && !strcmp(name + len - 6, ".scale"))
269 		return true;
270 	if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
271 		return true;
272 	if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
273 		return true;
274 
275 	return false;
276 }
277 
278 /*
279  * Process all the sysfs attributes located under the directory
280  * specified in 'dir' parameter.
281  */
pmu_aliases_parse(char * dir,struct list_head * head)282 static int pmu_aliases_parse(char *dir, struct list_head *head)
283 {
284 	struct dirent *evt_ent;
285 	DIR *event_dir;
286 
287 	event_dir = opendir(dir);
288 	if (!event_dir)
289 		return -EINVAL;
290 
291 	while ((evt_ent = readdir(event_dir))) {
292 		char path[PATH_MAX];
293 		char *name = evt_ent->d_name;
294 		FILE *file;
295 
296 		if (!strcmp(name, ".") || !strcmp(name, ".."))
297 			continue;
298 
299 		/*
300 		 * skip info files parsed in perf_pmu__new_alias()
301 		 */
302 		if (pmu_alias_info_file(name))
303 			continue;
304 
305 		scnprintf(path, PATH_MAX, "%s/%s", dir, name);
306 
307 		file = fopen(path, "r");
308 		if (!file) {
309 			pr_debug("Cannot open %s\n", path);
310 			continue;
311 		}
312 
313 		if (perf_pmu__new_alias(head, dir, name, file) < 0)
314 			pr_debug("Cannot set up %s\n", name);
315 		fclose(file);
316 	}
317 
318 	closedir(event_dir);
319 	return 0;
320 }
321 
322 /*
323  * Reading the pmu event aliases definition, which should be located at:
324  * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
325  */
pmu_aliases(const char * name,struct list_head * head)326 static int pmu_aliases(const char *name, struct list_head *head)
327 {
328 	struct stat st;
329 	char path[PATH_MAX];
330 	const char *sysfs = sysfs__mountpoint();
331 
332 	if (!sysfs)
333 		return -1;
334 
335 	snprintf(path, PATH_MAX,
336 		 "%s/bus/event_source/devices/%s/events", sysfs, name);
337 
338 	if (stat(path, &st) < 0)
339 		return 0;	 /* no error if 'events' does not exist */
340 
341 	if (pmu_aliases_parse(path, head))
342 		return -1;
343 
344 	return 0;
345 }
346 
pmu_alias_terms(struct perf_pmu_alias * alias,struct list_head * terms)347 static int pmu_alias_terms(struct perf_pmu_alias *alias,
348 			   struct list_head *terms)
349 {
350 	struct parse_events_term *term, *cloned;
351 	LIST_HEAD(list);
352 	int ret;
353 
354 	list_for_each_entry(term, &alias->terms, list) {
355 		ret = parse_events_term__clone(&cloned, term);
356 		if (ret) {
357 			parse_events__free_terms(&list);
358 			return ret;
359 		}
360 		list_add_tail(&cloned->list, &list);
361 	}
362 	list_splice(&list, terms);
363 	return 0;
364 }
365 
366 /*
367  * Reading/parsing the default pmu type value, which should be
368  * located at:
369  * /sys/bus/event_source/devices/<dev>/type as sysfs attribute.
370  */
pmu_type(const char * name,__u32 * type)371 static int pmu_type(const char *name, __u32 *type)
372 {
373 	struct stat st;
374 	char path[PATH_MAX];
375 	FILE *file;
376 	int ret = 0;
377 	const char *sysfs = sysfs__mountpoint();
378 
379 	if (!sysfs)
380 		return -1;
381 
382 	snprintf(path, PATH_MAX,
383 		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);
384 
385 	if (stat(path, &st) < 0)
386 		return -1;
387 
388 	file = fopen(path, "r");
389 	if (!file)
390 		return -EINVAL;
391 
392 	if (1 != fscanf(file, "%u", type))
393 		ret = -1;
394 
395 	fclose(file);
396 	return ret;
397 }
398 
399 /* Add all pmus in sysfs to pmu list: */
pmu_read_sysfs(void)400 static void pmu_read_sysfs(void)
401 {
402 	char path[PATH_MAX];
403 	DIR *dir;
404 	struct dirent *dent;
405 	const char *sysfs = sysfs__mountpoint();
406 
407 	if (!sysfs)
408 		return;
409 
410 	snprintf(path, PATH_MAX,
411 		 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs);
412 
413 	dir = opendir(path);
414 	if (!dir)
415 		return;
416 
417 	while ((dent = readdir(dir))) {
418 		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
419 			continue;
420 		/* add to static LIST_HEAD(pmus): */
421 		perf_pmu__find(dent->d_name);
422 	}
423 
424 	closedir(dir);
425 }
426 
pmu_cpumask(const char * name)427 static struct cpu_map *pmu_cpumask(const char *name)
428 {
429 	struct stat st;
430 	char path[PATH_MAX];
431 	FILE *file;
432 	struct cpu_map *cpus;
433 	const char *sysfs = sysfs__mountpoint();
434 
435 	if (!sysfs)
436 		return NULL;
437 
438 	snprintf(path, PATH_MAX,
439 		 "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
440 
441 	if (stat(path, &st) < 0)
442 		return NULL;
443 
444 	file = fopen(path, "r");
445 	if (!file)
446 		return NULL;
447 
448 	cpus = cpu_map__read(file);
449 	fclose(file);
450 	return cpus;
451 }
452 
453 struct perf_event_attr * __weak
perf_pmu__get_default_config(struct perf_pmu * pmu __maybe_unused)454 perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
455 {
456 	return NULL;
457 }
458 
pmu_lookup(const char * name)459 static struct perf_pmu *pmu_lookup(const char *name)
460 {
461 	struct perf_pmu *pmu;
462 	LIST_HEAD(format);
463 	LIST_HEAD(aliases);
464 	__u32 type;
465 
466 	/*
467 	 * The pmu data we store & need consists of the pmu
468 	 * type value and format definitions. Load both right
469 	 * now.
470 	 */
471 	if (pmu_format(name, &format))
472 		return NULL;
473 
474 	if (pmu_aliases(name, &aliases))
475 		return NULL;
476 
477 	if (pmu_type(name, &type))
478 		return NULL;
479 
480 	pmu = zalloc(sizeof(*pmu));
481 	if (!pmu)
482 		return NULL;
483 
484 	pmu->cpus = pmu_cpumask(name);
485 
486 	INIT_LIST_HEAD(&pmu->format);
487 	INIT_LIST_HEAD(&pmu->aliases);
488 	list_splice(&format, &pmu->format);
489 	list_splice(&aliases, &pmu->aliases);
490 	pmu->name = strdup(name);
491 	pmu->type = type;
492 	list_add_tail(&pmu->list, &pmus);
493 
494 	pmu->default_config = perf_pmu__get_default_config(pmu);
495 
496 	return pmu;
497 }
498 
pmu_find(const char * name)499 static struct perf_pmu *pmu_find(const char *name)
500 {
501 	struct perf_pmu *pmu;
502 
503 	list_for_each_entry(pmu, &pmus, list)
504 		if (!strcmp(pmu->name, name))
505 			return pmu;
506 
507 	return NULL;
508 }
509 
perf_pmu__scan(struct perf_pmu * pmu)510 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
511 {
512 	/*
513 	 * pmu iterator: If pmu is NULL, we start at the begin,
514 	 * otherwise return the next pmu. Returns NULL on end.
515 	 */
516 	if (!pmu) {
517 		pmu_read_sysfs();
518 		pmu = list_prepare_entry(pmu, &pmus, list);
519 	}
520 	list_for_each_entry_continue(pmu, &pmus, list)
521 		return pmu;
522 	return NULL;
523 }
524 
perf_pmu__find(const char * name)525 struct perf_pmu *perf_pmu__find(const char *name)
526 {
527 	struct perf_pmu *pmu;
528 
529 	/*
530 	 * Once PMU is loaded it stays in the list,
531 	 * so we keep us from multiple reading/parsing
532 	 * the pmu format definitions.
533 	 */
534 	pmu = pmu_find(name);
535 	if (pmu)
536 		return pmu;
537 
538 	return pmu_lookup(name);
539 }
540 
541 static struct perf_pmu_format *
pmu_find_format(struct list_head * formats,const char * name)542 pmu_find_format(struct list_head *formats, const char *name)
543 {
544 	struct perf_pmu_format *format;
545 
546 	list_for_each_entry(format, formats, list)
547 		if (!strcmp(format->name, name))
548 			return format;
549 
550 	return NULL;
551 }
552 
perf_pmu__format_bits(struct list_head * formats,const char * name)553 __u64 perf_pmu__format_bits(struct list_head *formats, const char *name)
554 {
555 	struct perf_pmu_format *format = pmu_find_format(formats, name);
556 	__u64 bits = 0;
557 	int fbit;
558 
559 	if (!format)
560 		return 0;
561 
562 	for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS)
563 		bits |= 1ULL << fbit;
564 
565 	return bits;
566 }
567 
568 /*
569  * Sets value based on the format definition (format parameter)
570  * and unformated value (value parameter).
571  */
pmu_format_value(unsigned long * format,__u64 value,__u64 * v,bool zero)572 static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
573 			     bool zero)
574 {
575 	unsigned long fbit, vbit;
576 
577 	for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
578 
579 		if (!test_bit(fbit, format))
580 			continue;
581 
582 		if (value & (1llu << vbit++))
583 			*v |= (1llu << fbit);
584 		else if (zero)
585 			*v &= ~(1llu << fbit);
586 	}
587 }
588 
pmu_format_max_value(const unsigned long * format)589 static __u64 pmu_format_max_value(const unsigned long *format)
590 {
591 	int w;
592 
593 	w = bitmap_weight(format, PERF_PMU_FORMAT_BITS);
594 	if (!w)
595 		return 0;
596 	if (w < 64)
597 		return (1ULL << w) - 1;
598 	return -1;
599 }
600 
601 /*
602  * Term is a string term, and might be a param-term. Try to look up it's value
603  * in the remaining terms.
604  * - We have a term like "base-or-format-term=param-term",
605  * - We need to find the value supplied for "param-term" (with param-term named
606  *   in a config string) later on in the term list.
607  */
pmu_resolve_param_term(struct parse_events_term * term,struct list_head * head_terms,__u64 * value)608 static int pmu_resolve_param_term(struct parse_events_term *term,
609 				  struct list_head *head_terms,
610 				  __u64 *value)
611 {
612 	struct parse_events_term *t;
613 
614 	list_for_each_entry(t, head_terms, list) {
615 		if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
616 			if (!strcmp(t->config, term->config)) {
617 				t->used = true;
618 				*value = t->val.num;
619 				return 0;
620 			}
621 		}
622 	}
623 
624 	if (verbose)
625 		printf("Required parameter '%s' not specified\n", term->config);
626 
627 	return -1;
628 }
629 
pmu_formats_string(struct list_head * formats)630 static char *pmu_formats_string(struct list_head *formats)
631 {
632 	struct perf_pmu_format *format;
633 	char *str;
634 	struct strbuf buf;
635 	unsigned i = 0;
636 
637 	if (!formats)
638 		return NULL;
639 
640 	strbuf_init(&buf, 0);
641 	/* sysfs exported terms */
642 	list_for_each_entry(format, formats, list)
643 		strbuf_addf(&buf, i++ ? ",%s" : "%s",
644 			    format->name);
645 
646 	str = strbuf_detach(&buf, NULL);
647 	strbuf_release(&buf);
648 
649 	return str;
650 }
651 
652 /*
653  * Setup one of config[12] attr members based on the
654  * user input data - term parameter.
655  */
pmu_config_term(struct list_head * formats,struct perf_event_attr * attr,struct parse_events_term * term,struct list_head * head_terms,bool zero,struct parse_events_error * err)656 static int pmu_config_term(struct list_head *formats,
657 			   struct perf_event_attr *attr,
658 			   struct parse_events_term *term,
659 			   struct list_head *head_terms,
660 			   bool zero, struct parse_events_error *err)
661 {
662 	struct perf_pmu_format *format;
663 	__u64 *vp;
664 	__u64 val, max_val;
665 
666 	/*
667 	 * If this is a parameter we've already used for parameterized-eval,
668 	 * skip it in normal eval.
669 	 */
670 	if (term->used)
671 		return 0;
672 
673 	/*
674 	 * Hardcoded terms should be already in, so nothing
675 	 * to be done for them.
676 	 */
677 	if (parse_events__is_hardcoded_term(term))
678 		return 0;
679 
680 	format = pmu_find_format(formats, term->config);
681 	if (!format) {
682 		if (verbose)
683 			printf("Invalid event/parameter '%s'\n", term->config);
684 		if (err) {
685 			char *pmu_term = pmu_formats_string(formats);
686 
687 			err->idx  = term->err_term;
688 			err->str  = strdup("unknown term");
689 			err->help = parse_events_formats_error_string(pmu_term);
690 			free(pmu_term);
691 		}
692 		return -EINVAL;
693 	}
694 
695 	switch (format->value) {
696 	case PERF_PMU_FORMAT_VALUE_CONFIG:
697 		vp = &attr->config;
698 		break;
699 	case PERF_PMU_FORMAT_VALUE_CONFIG1:
700 		vp = &attr->config1;
701 		break;
702 	case PERF_PMU_FORMAT_VALUE_CONFIG2:
703 		vp = &attr->config2;
704 		break;
705 	default:
706 		return -EINVAL;
707 	}
708 
709 	/*
710 	 * Either directly use a numeric term, or try to translate string terms
711 	 * using event parameters.
712 	 */
713 	if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
714 		val = term->val.num;
715 	else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
716 		if (strcmp(term->val.str, "?")) {
717 			if (verbose) {
718 				pr_info("Invalid sysfs entry %s=%s\n",
719 						term->config, term->val.str);
720 			}
721 			if (err) {
722 				err->idx = term->err_val;
723 				err->str = strdup("expected numeric value");
724 			}
725 			return -EINVAL;
726 		}
727 
728 		if (pmu_resolve_param_term(term, head_terms, &val))
729 			return -EINVAL;
730 	} else
731 		return -EINVAL;
732 
733 	max_val = pmu_format_max_value(format->bits);
734 	if (val > max_val) {
735 		if (err) {
736 			err->idx = term->err_val;
737 			if (asprintf(&err->str,
738 				     "value too big for format, maximum is %llu",
739 				     (unsigned long long)max_val) < 0)
740 				err->str = strdup("value too big for format");
741 			return -EINVAL;
742 		}
743 		/*
744 		 * Assume we don't care if !err, in which case the value will be
745 		 * silently truncated.
746 		 */
747 	}
748 
749 	pmu_format_value(format->bits, val, vp, zero);
750 	return 0;
751 }
752 
perf_pmu__config_terms(struct list_head * formats,struct perf_event_attr * attr,struct list_head * head_terms,bool zero,struct parse_events_error * err)753 int perf_pmu__config_terms(struct list_head *formats,
754 			   struct perf_event_attr *attr,
755 			   struct list_head *head_terms,
756 			   bool zero, struct parse_events_error *err)
757 {
758 	struct parse_events_term *term;
759 
760 	list_for_each_entry(term, head_terms, list) {
761 		if (pmu_config_term(formats, attr, term, head_terms,
762 				    zero, err))
763 			return -EINVAL;
764 	}
765 
766 	return 0;
767 }
768 
769 /*
770  * Configures event's 'attr' parameter based on the:
771  * 1) users input - specified in terms parameter
772  * 2) pmu format definitions - specified by pmu parameter
773  */
perf_pmu__config(struct perf_pmu * pmu,struct perf_event_attr * attr,struct list_head * head_terms,struct parse_events_error * err)774 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
775 		     struct list_head *head_terms,
776 		     struct parse_events_error *err)
777 {
778 	bool zero = !!pmu->default_config;
779 
780 	attr->type = pmu->type;
781 	return perf_pmu__config_terms(&pmu->format, attr, head_terms,
782 				      zero, err);
783 }
784 
pmu_find_alias(struct perf_pmu * pmu,struct parse_events_term * term)785 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
786 					     struct parse_events_term *term)
787 {
788 	struct perf_pmu_alias *alias;
789 	char *name;
790 
791 	if (parse_events__is_hardcoded_term(term))
792 		return NULL;
793 
794 	if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
795 		if (term->val.num != 1)
796 			return NULL;
797 		if (pmu_find_format(&pmu->format, term->config))
798 			return NULL;
799 		name = term->config;
800 	} else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
801 		if (strcasecmp(term->config, "event"))
802 			return NULL;
803 		name = term->val.str;
804 	} else {
805 		return NULL;
806 	}
807 
808 	list_for_each_entry(alias, &pmu->aliases, list) {
809 		if (!strcasecmp(alias->name, name))
810 			return alias;
811 	}
812 	return NULL;
813 }
814 
815 
check_info_data(struct perf_pmu_alias * alias,struct perf_pmu_info * info)816 static int check_info_data(struct perf_pmu_alias *alias,
817 			   struct perf_pmu_info *info)
818 {
819 	/*
820 	 * Only one term in event definition can
821 	 * define unit, scale and snapshot, fail
822 	 * if there's more than one.
823 	 */
824 	if ((info->unit && alias->unit) ||
825 	    (info->scale && alias->scale) ||
826 	    (info->snapshot && alias->snapshot))
827 		return -EINVAL;
828 
829 	if (alias->unit)
830 		info->unit = alias->unit;
831 
832 	if (alias->scale)
833 		info->scale = alias->scale;
834 
835 	if (alias->snapshot)
836 		info->snapshot = alias->snapshot;
837 
838 	return 0;
839 }
840 
841 /*
842  * Find alias in the terms list and replace it with the terms
843  * defined for the alias
844  */
perf_pmu__check_alias(struct perf_pmu * pmu,struct list_head * head_terms,struct perf_pmu_info * info)845 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
846 			  struct perf_pmu_info *info)
847 {
848 	struct parse_events_term *term, *h;
849 	struct perf_pmu_alias *alias;
850 	int ret;
851 
852 	info->per_pkg = false;
853 
854 	/*
855 	 * Mark unit and scale as not set
856 	 * (different from default values, see below)
857 	 */
858 	info->unit     = NULL;
859 	info->scale    = 0.0;
860 	info->snapshot = false;
861 
862 	list_for_each_entry_safe(term, h, head_terms, list) {
863 		alias = pmu_find_alias(pmu, term);
864 		if (!alias)
865 			continue;
866 		ret = pmu_alias_terms(alias, &term->list);
867 		if (ret)
868 			return ret;
869 
870 		ret = check_info_data(alias, info);
871 		if (ret)
872 			return ret;
873 
874 		if (alias->per_pkg)
875 			info->per_pkg = true;
876 
877 		list_del(&term->list);
878 		free(term);
879 	}
880 
881 	/*
882 	 * if no unit or scale foundin aliases, then
883 	 * set defaults as for evsel
884 	 * unit cannot left to NULL
885 	 */
886 	if (info->unit == NULL)
887 		info->unit   = "";
888 
889 	if (info->scale == 0.0)
890 		info->scale  = 1.0;
891 
892 	return 0;
893 }
894 
perf_pmu__new_format(struct list_head * list,char * name,int config,unsigned long * bits)895 int perf_pmu__new_format(struct list_head *list, char *name,
896 			 int config, unsigned long *bits)
897 {
898 	struct perf_pmu_format *format;
899 
900 	format = zalloc(sizeof(*format));
901 	if (!format)
902 		return -ENOMEM;
903 
904 	format->name = strdup(name);
905 	format->value = config;
906 	memcpy(format->bits, bits, sizeof(format->bits));
907 
908 	list_add_tail(&format->list, list);
909 	return 0;
910 }
911 
perf_pmu__set_format(unsigned long * bits,long from,long to)912 void perf_pmu__set_format(unsigned long *bits, long from, long to)
913 {
914 	long b;
915 
916 	if (!to)
917 		to = from;
918 
919 	memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS));
920 	for (b = from; b <= to; b++)
921 		set_bit(b, bits);
922 }
923 
perf_pmu__del_formats(struct list_head * formats)924 void perf_pmu__del_formats(struct list_head *formats)
925 {
926 	struct perf_pmu_format *fmt, *tmp;
927 
928 	list_for_each_entry_safe(fmt, tmp, formats, list) {
929 		list_del(&fmt->list);
930 		free(fmt->name);
931 		free(fmt);
932 	}
933 }
934 
sub_non_neg(int a,int b)935 static int sub_non_neg(int a, int b)
936 {
937 	if (b > a)
938 		return 0;
939 	return a - b;
940 }
941 
format_alias(char * buf,int len,struct perf_pmu * pmu,struct perf_pmu_alias * alias)942 static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
943 			  struct perf_pmu_alias *alias)
944 {
945 	struct parse_events_term *term;
946 	int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
947 
948 	list_for_each_entry(term, &alias->terms, list) {
949 		if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
950 			used += snprintf(buf + used, sub_non_neg(len, used),
951 					",%s=%s", term->config,
952 					term->val.str);
953 	}
954 
955 	if (sub_non_neg(len, used) > 0) {
956 		buf[used] = '/';
957 		used++;
958 	}
959 	if (sub_non_neg(len, used) > 0) {
960 		buf[used] = '\0';
961 		used++;
962 	} else
963 		buf[len - 1] = '\0';
964 
965 	return buf;
966 }
967 
format_alias_or(char * buf,int len,struct perf_pmu * pmu,struct perf_pmu_alias * alias)968 static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
969 			     struct perf_pmu_alias *alias)
970 {
971 	snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name);
972 	return buf;
973 }
974 
cmp_string(const void * a,const void * b)975 static int cmp_string(const void *a, const void *b)
976 {
977 	const char * const *as = a;
978 	const char * const *bs = b;
979 	return strcmp(*as, *bs);
980 }
981 
print_pmu_events(const char * event_glob,bool name_only)982 void print_pmu_events(const char *event_glob, bool name_only)
983 {
984 	struct perf_pmu *pmu;
985 	struct perf_pmu_alias *alias;
986 	char buf[1024];
987 	int printed = 0;
988 	int len, j;
989 	char **aliases;
990 
991 	pmu = NULL;
992 	len = 0;
993 	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
994 		list_for_each_entry(alias, &pmu->aliases, list)
995 			len++;
996 		if (pmu->selectable)
997 			len++;
998 	}
999 	aliases = zalloc(sizeof(char *) * len);
1000 	if (!aliases)
1001 		goto out_enomem;
1002 	pmu = NULL;
1003 	j = 0;
1004 	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1005 		list_for_each_entry(alias, &pmu->aliases, list) {
1006 			char *name = format_alias(buf, sizeof(buf), pmu, alias);
1007 			bool is_cpu = !strcmp(pmu->name, "cpu");
1008 
1009 			if (event_glob != NULL &&
1010 			    !(strglobmatch(name, event_glob) ||
1011 			      (!is_cpu && strglobmatch(alias->name,
1012 						       event_glob))))
1013 				continue;
1014 
1015 			if (is_cpu && !name_only)
1016 				name = format_alias_or(buf, sizeof(buf), pmu, alias);
1017 
1018 			aliases[j] = strdup(name);
1019 			if (aliases[j] == NULL)
1020 				goto out_enomem;
1021 			j++;
1022 		}
1023 		if (pmu->selectable &&
1024 		    (event_glob == NULL || strglobmatch(pmu->name, event_glob))) {
1025 			char *s;
1026 			if (asprintf(&s, "%s//", pmu->name) < 0)
1027 				goto out_enomem;
1028 			aliases[j] = s;
1029 			j++;
1030 		}
1031 	}
1032 	len = j;
1033 	qsort(aliases, len, sizeof(char *), cmp_string);
1034 	for (j = 0; j < len; j++) {
1035 		if (name_only) {
1036 			printf("%s ", aliases[j]);
1037 			continue;
1038 		}
1039 		printf("  %-50s [Kernel PMU event]\n", aliases[j]);
1040 		printed++;
1041 	}
1042 	if (printed && pager_in_use())
1043 		printf("\n");
1044 out_free:
1045 	for (j = 0; j < len; j++)
1046 		zfree(&aliases[j]);
1047 	zfree(&aliases);
1048 	return;
1049 
1050 out_enomem:
1051 	printf("FATAL: not enough memory to print PMU events\n");
1052 	if (aliases)
1053 		goto out_free;
1054 }
1055 
pmu_have_event(const char * pname,const char * name)1056 bool pmu_have_event(const char *pname, const char *name)
1057 {
1058 	struct perf_pmu *pmu;
1059 	struct perf_pmu_alias *alias;
1060 
1061 	pmu = NULL;
1062 	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1063 		if (strcmp(pname, pmu->name))
1064 			continue;
1065 		list_for_each_entry(alias, &pmu->aliases, list)
1066 			if (!strcmp(alias->name, name))
1067 				return true;
1068 	}
1069 	return false;
1070 }
1071 
perf_pmu__open_file(struct perf_pmu * pmu,const char * name)1072 static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
1073 {
1074 	struct stat st;
1075 	char path[PATH_MAX];
1076 	const char *sysfs;
1077 
1078 	sysfs = sysfs__mountpoint();
1079 	if (!sysfs)
1080 		return NULL;
1081 
1082 	snprintf(path, PATH_MAX,
1083 		 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
1084 
1085 	if (stat(path, &st) < 0)
1086 		return NULL;
1087 
1088 	return fopen(path, "r");
1089 }
1090 
perf_pmu__scan_file(struct perf_pmu * pmu,const char * name,const char * fmt,...)1091 int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
1092 			...)
1093 {
1094 	va_list args;
1095 	FILE *file;
1096 	int ret = EOF;
1097 
1098 	va_start(args, fmt);
1099 	file = perf_pmu__open_file(pmu, name);
1100 	if (file) {
1101 		ret = vfscanf(file, fmt, args);
1102 		fclose(file);
1103 	}
1104 	va_end(args);
1105 	return ret;
1106 }
1107