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