1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/list.h>
3 #include <linux/list_sort.h>
4 #include <linux/string.h>
5 #include <linux/zalloc.h>
6 #include <subcmd/pager.h>
7 #include <sys/types.h>
8 #include <ctype.h>
9 #include <dirent.h>
10 #include <pthread.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include "cpumap.h"
14 #include "debug.h"
15 #include "evsel.h"
16 #include "pmus.h"
17 #include "pmu.h"
18 #include "print-events.h"
19 #include "strbuf.h"
20 
21 /*
22  * core_pmus:  A PMU belongs to core_pmus if it's name is "cpu" or it's sysfs
23  *             directory contains "cpus" file. All PMUs belonging to core_pmus
24  *             must have pmu->is_core=1. If there are more than one PMU in
25  *             this list, perf interprets it as a heterogeneous platform.
26  *             (FWIW, certain ARM platforms having heterogeneous cores uses
27  *             homogeneous PMU, and thus they are treated as homogeneous
28  *             platform by perf because core_pmus will have only one entry)
29  * other_pmus: All other PMUs which are not part of core_pmus list. It doesn't
30  *             matter whether PMU is present per SMT-thread or outside of the
31  *             core in the hw. For e.g., an instance of AMD ibs_fetch// and
32  *             ibs_op// PMUs is present in each hw SMT thread, however they
33  *             are captured under other_pmus. PMUs belonging to other_pmus
34  *             must have pmu->is_core=0 but pmu->is_uncore could be 0 or 1.
35  */
36 static LIST_HEAD(core_pmus);
37 static LIST_HEAD(other_pmus);
38 static bool read_sysfs_core_pmus;
39 static bool read_sysfs_all_pmus;
40 
41 static void pmu_read_sysfs(bool core_only);
42 
pmu_name_len_no_suffix(const char * str)43 size_t pmu_name_len_no_suffix(const char *str)
44 {
45 	int orig_len, len;
46 	bool has_hex_digits = false;
47 
48 	orig_len = len = strlen(str);
49 
50 	/* Count trailing digits. */
51 	while (len > 0 && isxdigit(str[len - 1])) {
52 		if (!isdigit(str[len - 1]))
53 			has_hex_digits = true;
54 		len--;
55 	}
56 
57 	if (len > 0 && len != orig_len && str[len - 1] == '_') {
58 		/*
59 		 * There is a '_{num}' suffix. For decimal suffixes any length
60 		 * will do, for hexadecimal ensure more than 2 hex digits so
61 		 * that S390's cpum_cf PMU doesn't match.
62 		 */
63 		if (!has_hex_digits || (orig_len - len) > 2)
64 			return len - 1;
65 	}
66 	/* Use the full length. */
67 	return orig_len;
68 }
69 
pmu_name_cmp(const char * lhs_pmu_name,const char * rhs_pmu_name)70 int pmu_name_cmp(const char *lhs_pmu_name, const char *rhs_pmu_name)
71 {
72 	unsigned long long lhs_num = 0, rhs_num = 0;
73 	size_t lhs_pmu_name_len = pmu_name_len_no_suffix(lhs_pmu_name);
74 	size_t rhs_pmu_name_len = pmu_name_len_no_suffix(rhs_pmu_name);
75 	int ret = strncmp(lhs_pmu_name, rhs_pmu_name,
76 			lhs_pmu_name_len < rhs_pmu_name_len ? lhs_pmu_name_len : rhs_pmu_name_len);
77 
78 	if (lhs_pmu_name_len != rhs_pmu_name_len || ret != 0 || lhs_pmu_name_len == 0)
79 		return ret;
80 
81 	if (lhs_pmu_name_len + 1 < strlen(lhs_pmu_name))
82 		lhs_num = strtoull(&lhs_pmu_name[lhs_pmu_name_len + 1], NULL, 16);
83 	if (rhs_pmu_name_len + 1 < strlen(rhs_pmu_name))
84 		rhs_num = strtoull(&rhs_pmu_name[rhs_pmu_name_len + 1], NULL, 16);
85 
86 	return lhs_num < rhs_num ? -1 : (lhs_num > rhs_num ? 1 : 0);
87 }
88 
perf_pmus__destroy(void)89 void perf_pmus__destroy(void)
90 {
91 	struct perf_pmu *pmu, *tmp;
92 
93 	list_for_each_entry_safe(pmu, tmp, &core_pmus, list) {
94 		list_del(&pmu->list);
95 
96 		perf_pmu__delete(pmu);
97 	}
98 	list_for_each_entry_safe(pmu, tmp, &other_pmus, list) {
99 		list_del(&pmu->list);
100 
101 		perf_pmu__delete(pmu);
102 	}
103 	read_sysfs_core_pmus = false;
104 	read_sysfs_all_pmus = false;
105 }
106 
pmu_find(const char * name)107 static struct perf_pmu *pmu_find(const char *name)
108 {
109 	struct perf_pmu *pmu;
110 
111 	list_for_each_entry(pmu, &core_pmus, list) {
112 		if (!strcmp(pmu->name, name) ||
113 		    (pmu->alias_name && !strcmp(pmu->alias_name, name)))
114 			return pmu;
115 	}
116 	list_for_each_entry(pmu, &other_pmus, list) {
117 		if (!strcmp(pmu->name, name) ||
118 		    (pmu->alias_name && !strcmp(pmu->alias_name, name)))
119 			return pmu;
120 	}
121 
122 	return NULL;
123 }
124 
perf_pmus__find(const char * name)125 struct perf_pmu *perf_pmus__find(const char *name)
126 {
127 	struct perf_pmu *pmu;
128 	int dirfd;
129 	bool core_pmu;
130 
131 	/*
132 	 * Once PMU is loaded it stays in the list,
133 	 * so we keep us from multiple reading/parsing
134 	 * the pmu format definitions.
135 	 */
136 	pmu = pmu_find(name);
137 	if (pmu)
138 		return pmu;
139 
140 	if (read_sysfs_all_pmus)
141 		return NULL;
142 
143 	core_pmu = is_pmu_core(name);
144 	if (core_pmu && read_sysfs_core_pmus)
145 		return NULL;
146 
147 	dirfd = perf_pmu__event_source_devices_fd();
148 	pmu = perf_pmu__lookup(core_pmu ? &core_pmus : &other_pmus, dirfd, name,
149 			       /*eager_load=*/false);
150 	close(dirfd);
151 
152 	if (!pmu) {
153 		/*
154 		 * Looking up an inidividual PMU failed. This may mean name is
155 		 * an alias, so read the PMUs from sysfs and try to find again.
156 		 */
157 		pmu_read_sysfs(core_pmu);
158 		pmu = pmu_find(name);
159 	}
160 	return pmu;
161 }
162 
perf_pmu__find2(int dirfd,const char * name)163 static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name)
164 {
165 	struct perf_pmu *pmu;
166 	bool core_pmu;
167 
168 	/*
169 	 * Once PMU is loaded it stays in the list,
170 	 * so we keep us from multiple reading/parsing
171 	 * the pmu format definitions.
172 	 */
173 	pmu = pmu_find(name);
174 	if (pmu)
175 		return pmu;
176 
177 	if (read_sysfs_all_pmus)
178 		return NULL;
179 
180 	core_pmu = is_pmu_core(name);
181 	if (core_pmu && read_sysfs_core_pmus)
182 		return NULL;
183 
184 	return perf_pmu__lookup(core_pmu ? &core_pmus : &other_pmus, dirfd, name,
185 				/*eager_load=*/false);
186 }
187 
pmus_cmp(void * priv __maybe_unused,const struct list_head * lhs,const struct list_head * rhs)188 static int pmus_cmp(void *priv __maybe_unused,
189 		    const struct list_head *lhs, const struct list_head *rhs)
190 {
191 	struct perf_pmu *lhs_pmu = container_of(lhs, struct perf_pmu, list);
192 	struct perf_pmu *rhs_pmu = container_of(rhs, struct perf_pmu, list);
193 
194 	return pmu_name_cmp(lhs_pmu->name ?: "", rhs_pmu->name ?: "");
195 }
196 
197 /* Add all pmus in sysfs to pmu list: */
pmu_read_sysfs(bool core_only)198 static void pmu_read_sysfs(bool core_only)
199 {
200 	int fd;
201 	DIR *dir;
202 	struct dirent *dent;
203 
204 	if (read_sysfs_all_pmus || (core_only && read_sysfs_core_pmus))
205 		return;
206 
207 	fd = perf_pmu__event_source_devices_fd();
208 	if (fd < 0)
209 		return;
210 
211 	dir = fdopendir(fd);
212 	if (!dir) {
213 		close(fd);
214 		return;
215 	}
216 
217 	while ((dent = readdir(dir))) {
218 		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
219 			continue;
220 		if (core_only && !is_pmu_core(dent->d_name))
221 			continue;
222 		/* add to static LIST_HEAD(core_pmus) or LIST_HEAD(other_pmus): */
223 		perf_pmu__find2(fd, dent->d_name);
224 	}
225 
226 	closedir(dir);
227 	if (list_empty(&core_pmus)) {
228 		if (!perf_pmu__create_placeholder_core_pmu(&core_pmus))
229 			pr_err("Failure to set up any core PMUs\n");
230 	}
231 	list_sort(NULL, &core_pmus, pmus_cmp);
232 	list_sort(NULL, &other_pmus, pmus_cmp);
233 	if (!list_empty(&core_pmus)) {
234 		read_sysfs_core_pmus = true;
235 		if (!core_only)
236 			read_sysfs_all_pmus = true;
237 	}
238 }
239 
__perf_pmus__find_by_type(unsigned int type)240 static struct perf_pmu *__perf_pmus__find_by_type(unsigned int type)
241 {
242 	struct perf_pmu *pmu;
243 
244 	list_for_each_entry(pmu, &core_pmus, list) {
245 		if (pmu->type == type)
246 			return pmu;
247 	}
248 
249 	list_for_each_entry(pmu, &other_pmus, list) {
250 		if (pmu->type == type)
251 			return pmu;
252 	}
253 	return NULL;
254 }
255 
perf_pmus__find_by_type(unsigned int type)256 struct perf_pmu *perf_pmus__find_by_type(unsigned int type)
257 {
258 	struct perf_pmu *pmu = __perf_pmus__find_by_type(type);
259 
260 	if (pmu || read_sysfs_all_pmus)
261 		return pmu;
262 
263 	pmu_read_sysfs(/*core_only=*/false);
264 	pmu = __perf_pmus__find_by_type(type);
265 	return pmu;
266 }
267 
268 /*
269  * pmu iterator: If pmu is NULL, we start at the begin, otherwise return the
270  * next pmu. Returns NULL on end.
271  */
perf_pmus__scan(struct perf_pmu * pmu)272 struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu)
273 {
274 	bool use_core_pmus = !pmu || pmu->is_core;
275 
276 	if (!pmu) {
277 		pmu_read_sysfs(/*core_only=*/false);
278 		pmu = list_prepare_entry(pmu, &core_pmus, list);
279 	}
280 	if (use_core_pmus) {
281 		list_for_each_entry_continue(pmu, &core_pmus, list)
282 			return pmu;
283 
284 		pmu = NULL;
285 		pmu = list_prepare_entry(pmu, &other_pmus, list);
286 	}
287 	list_for_each_entry_continue(pmu, &other_pmus, list)
288 		return pmu;
289 	return NULL;
290 }
291 
perf_pmus__scan_core(struct perf_pmu * pmu)292 struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu)
293 {
294 	if (!pmu) {
295 		pmu_read_sysfs(/*core_only=*/true);
296 		return list_first_entry_or_null(&core_pmus, typeof(*pmu), list);
297 	}
298 	list_for_each_entry_continue(pmu, &core_pmus, list)
299 		return pmu;
300 
301 	return NULL;
302 }
303 
perf_pmus__scan_skip_duplicates(struct perf_pmu * pmu)304 static struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu)
305 {
306 	bool use_core_pmus = !pmu || pmu->is_core;
307 	int last_pmu_name_len = 0;
308 	const char *last_pmu_name = (pmu && pmu->name) ? pmu->name : "";
309 
310 	if (!pmu) {
311 		pmu_read_sysfs(/*core_only=*/false);
312 		pmu = list_prepare_entry(pmu, &core_pmus, list);
313 	} else
314 		last_pmu_name_len = pmu_name_len_no_suffix(pmu->name ?: "");
315 
316 	if (use_core_pmus) {
317 		list_for_each_entry_continue(pmu, &core_pmus, list) {
318 			int pmu_name_len = pmu_name_len_no_suffix(pmu->name ?: "");
319 
320 			if (last_pmu_name_len == pmu_name_len &&
321 			    !strncmp(last_pmu_name, pmu->name ?: "", pmu_name_len))
322 				continue;
323 
324 			return pmu;
325 		}
326 		pmu = NULL;
327 		pmu = list_prepare_entry(pmu, &other_pmus, list);
328 	}
329 	list_for_each_entry_continue(pmu, &other_pmus, list) {
330 		int pmu_name_len = pmu_name_len_no_suffix(pmu->name ?: "");
331 
332 		if (last_pmu_name_len == pmu_name_len &&
333 		    !strncmp(last_pmu_name, pmu->name ?: "", pmu_name_len))
334 			continue;
335 
336 		return pmu;
337 	}
338 	return NULL;
339 }
340 
perf_pmus__pmu_for_pmu_filter(const char * str)341 const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str)
342 {
343 	struct perf_pmu *pmu = NULL;
344 
345 	while ((pmu = perf_pmus__scan(pmu)) != NULL) {
346 		if (!strcmp(pmu->name, str))
347 			return pmu;
348 		/* Ignore "uncore_" prefix. */
349 		if (!strncmp(pmu->name, "uncore_", 7)) {
350 			if (!strcmp(pmu->name + 7, str))
351 				return pmu;
352 		}
353 		/* Ignore "cpu_" prefix on Intel hybrid PMUs. */
354 		if (!strncmp(pmu->name, "cpu_", 4)) {
355 			if (!strcmp(pmu->name + 4, str))
356 				return pmu;
357 		}
358 	}
359 	return NULL;
360 }
361 
362 /** Struct for ordering events as output in perf list. */
363 struct sevent {
364 	/** PMU for event. */
365 	const struct perf_pmu *pmu;
366 	const char *name;
367 	const char* alias;
368 	const char *scale_unit;
369 	const char *desc;
370 	const char *long_desc;
371 	const char *encoding_desc;
372 	const char *topic;
373 	const char *pmu_name;
374 	const char *event_type_desc;
375 	bool deprecated;
376 };
377 
cmp_sevent(const void * a,const void * b)378 static int cmp_sevent(const void *a, const void *b)
379 {
380 	const struct sevent *as = a;
381 	const struct sevent *bs = b;
382 	bool a_iscpu, b_iscpu;
383 	int ret;
384 
385 	/* Put extra events last. */
386 	if (!!as->desc != !!bs->desc)
387 		return !!as->desc - !!bs->desc;
388 
389 	/* Order by topics. */
390 	ret = strcmp(as->topic ?: "", bs->topic ?: "");
391 	if (ret)
392 		return ret;
393 
394 	/* Order CPU core events to be first */
395 	a_iscpu = as->pmu ? as->pmu->is_core : true;
396 	b_iscpu = bs->pmu ? bs->pmu->is_core : true;
397 	if (a_iscpu != b_iscpu)
398 		return a_iscpu ? -1 : 1;
399 
400 	/* Order by PMU name. */
401 	if (as->pmu != bs->pmu) {
402 		ret = strcmp(as->pmu_name ?: "", bs->pmu_name ?: "");
403 		if (ret)
404 			return ret;
405 	}
406 
407 	/* Order by event name. */
408 	return strcmp(as->name, bs->name);
409 }
410 
pmu_alias_is_duplicate(struct sevent * a,struct sevent * b)411 static bool pmu_alias_is_duplicate(struct sevent *a, struct sevent *b)
412 {
413 	/* Different names -> never duplicates */
414 	if (strcmp(a->name ?: "//", b->name ?: "//"))
415 		return false;
416 
417 	/* Don't remove duplicates for different PMUs */
418 	return strcmp(a->pmu_name, b->pmu_name) == 0;
419 }
420 
421 struct events_callback_state {
422 	struct sevent *aliases;
423 	size_t aliases_len;
424 	size_t index;
425 };
426 
perf_pmus__print_pmu_events__callback(void * vstate,struct pmu_event_info * info)427 static int perf_pmus__print_pmu_events__callback(void *vstate,
428 						struct pmu_event_info *info)
429 {
430 	struct events_callback_state *state = vstate;
431 	struct sevent *s;
432 
433 	if (state->index >= state->aliases_len) {
434 		pr_err("Unexpected event %s/%s/\n", info->pmu->name, info->name);
435 		return 1;
436 	}
437 	s = &state->aliases[state->index];
438 	s->pmu = info->pmu;
439 #define COPY_STR(str) s->str = info->str ? strdup(info->str) : NULL
440 	COPY_STR(name);
441 	COPY_STR(alias);
442 	COPY_STR(scale_unit);
443 	COPY_STR(desc);
444 	COPY_STR(long_desc);
445 	COPY_STR(encoding_desc);
446 	COPY_STR(topic);
447 	COPY_STR(pmu_name);
448 	COPY_STR(event_type_desc);
449 #undef COPY_STR
450 	s->deprecated = info->deprecated;
451 	state->index++;
452 	return 0;
453 }
454 
perf_pmus__print_pmu_events(const struct print_callbacks * print_cb,void * print_state)455 void perf_pmus__print_pmu_events(const struct print_callbacks *print_cb, void *print_state)
456 {
457 	struct perf_pmu *pmu;
458 	int printed = 0;
459 	int len;
460 	struct sevent *aliases;
461 	struct events_callback_state state;
462 	bool skip_duplicate_pmus = print_cb->skip_duplicate_pmus(print_state);
463 	struct perf_pmu *(*scan_fn)(struct perf_pmu *);
464 
465 	if (skip_duplicate_pmus)
466 		scan_fn = perf_pmus__scan_skip_duplicates;
467 	else
468 		scan_fn = perf_pmus__scan;
469 
470 	pmu = NULL;
471 	len = 0;
472 	while ((pmu = scan_fn(pmu)) != NULL)
473 		len += perf_pmu__num_events(pmu);
474 
475 	aliases = zalloc(sizeof(struct sevent) * len);
476 	if (!aliases) {
477 		pr_err("FATAL: not enough memory to print PMU events\n");
478 		return;
479 	}
480 	pmu = NULL;
481 	state = (struct events_callback_state) {
482 		.aliases = aliases,
483 		.aliases_len = len,
484 		.index = 0,
485 	};
486 	while ((pmu = scan_fn(pmu)) != NULL) {
487 		perf_pmu__for_each_event(pmu, skip_duplicate_pmus, &state,
488 					 perf_pmus__print_pmu_events__callback);
489 	}
490 	qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
491 	for (int j = 0; j < len; j++) {
492 		/* Skip duplicates */
493 		if (j < len - 1 && pmu_alias_is_duplicate(&aliases[j], &aliases[j + 1]))
494 			goto free;
495 
496 		print_cb->print_event(print_state,
497 				aliases[j].pmu_name,
498 				aliases[j].topic,
499 				aliases[j].name,
500 				aliases[j].alias,
501 				aliases[j].scale_unit,
502 				aliases[j].deprecated,
503 				aliases[j].event_type_desc,
504 				aliases[j].desc,
505 				aliases[j].long_desc,
506 				aliases[j].encoding_desc);
507 free:
508 		zfree(&aliases[j].name);
509 		zfree(&aliases[j].alias);
510 		zfree(&aliases[j].scale_unit);
511 		zfree(&aliases[j].desc);
512 		zfree(&aliases[j].long_desc);
513 		zfree(&aliases[j].encoding_desc);
514 		zfree(&aliases[j].topic);
515 		zfree(&aliases[j].pmu_name);
516 		zfree(&aliases[j].event_type_desc);
517 	}
518 	if (printed && pager_in_use())
519 		printf("\n");
520 
521 	zfree(&aliases);
522 }
523 
524 struct build_format_string_args {
525 	struct strbuf short_string;
526 	struct strbuf long_string;
527 	int num_formats;
528 };
529 
build_format_string(void * state,const char * name,int config,const unsigned long * bits)530 static int build_format_string(void *state, const char *name, int config,
531 			       const unsigned long *bits)
532 {
533 	struct build_format_string_args *args = state;
534 	unsigned int num_bits;
535 	int ret1, ret2 = 0;
536 
537 	(void)config;
538 	args->num_formats++;
539 	if (args->num_formats > 1) {
540 		strbuf_addch(&args->long_string, ',');
541 		if (args->num_formats < 4)
542 			strbuf_addch(&args->short_string, ',');
543 	}
544 	num_bits = bits ? bitmap_weight(bits, PERF_PMU_FORMAT_BITS) : 0;
545 	if (num_bits <= 1) {
546 		ret1 = strbuf_addf(&args->long_string, "%s", name);
547 		if (args->num_formats < 4)
548 			ret2 = strbuf_addf(&args->short_string, "%s", name);
549 	} else if (num_bits > 8) {
550 		ret1 = strbuf_addf(&args->long_string, "%s=0..0x%llx", name,
551 				   ULLONG_MAX >> (64 - num_bits));
552 		if (args->num_formats < 4) {
553 			ret2 = strbuf_addf(&args->short_string, "%s=0..0x%llx", name,
554 					   ULLONG_MAX >> (64 - num_bits));
555 		}
556 	} else {
557 		ret1 = strbuf_addf(&args->long_string, "%s=0..%llu", name,
558 				  ULLONG_MAX >> (64 - num_bits));
559 		if (args->num_formats < 4) {
560 			ret2 = strbuf_addf(&args->short_string, "%s=0..%llu", name,
561 					   ULLONG_MAX >> (64 - num_bits));
562 		}
563 	}
564 	return ret1 < 0 ? ret1 : (ret2 < 0 ? ret2 : 0);
565 }
566 
perf_pmus__print_raw_pmu_events(const struct print_callbacks * print_cb,void * print_state)567 void perf_pmus__print_raw_pmu_events(const struct print_callbacks *print_cb, void *print_state)
568 {
569 	bool skip_duplicate_pmus = print_cb->skip_duplicate_pmus(print_state);
570 	struct perf_pmu *(*scan_fn)(struct perf_pmu *);
571 	struct perf_pmu *pmu = NULL;
572 
573 	if (skip_duplicate_pmus)
574 		scan_fn = perf_pmus__scan_skip_duplicates;
575 	else
576 		scan_fn = perf_pmus__scan;
577 
578 	while ((pmu = scan_fn(pmu)) != NULL) {
579 		struct build_format_string_args format_args = {
580 			.short_string = STRBUF_INIT,
581 			.long_string = STRBUF_INIT,
582 			.num_formats = 0,
583 		};
584 		int len = pmu_name_len_no_suffix(pmu->name);
585 		const char *desc = "(see 'man perf-list' or 'man perf-record' on how to encode it)";
586 
587 		if (!pmu->is_core)
588 			desc = NULL;
589 
590 		strbuf_addf(&format_args.short_string, "%.*s/", len, pmu->name);
591 		strbuf_addf(&format_args.long_string, "%.*s/", len, pmu->name);
592 		perf_pmu__for_each_format(pmu, &format_args, build_format_string);
593 
594 		if (format_args.num_formats > 3)
595 			strbuf_addf(&format_args.short_string, ",.../modifier");
596 		else
597 			strbuf_addf(&format_args.short_string, "/modifier");
598 
599 		strbuf_addf(&format_args.long_string, "/modifier");
600 		print_cb->print_event(print_state,
601 				/*topic=*/NULL,
602 				/*pmu_name=*/NULL,
603 				format_args.short_string.buf,
604 				/*event_alias=*/NULL,
605 				/*scale_unit=*/NULL,
606 				/*deprecated=*/false,
607 				"Raw event descriptor",
608 				desc,
609 				/*long_desc=*/NULL,
610 				format_args.long_string.buf);
611 
612 		strbuf_release(&format_args.short_string);
613 		strbuf_release(&format_args.long_string);
614 	}
615 }
616 
perf_pmus__have_event(const char * pname,const char * name)617 bool perf_pmus__have_event(const char *pname, const char *name)
618 {
619 	struct perf_pmu *pmu = perf_pmus__find(pname);
620 
621 	return pmu && perf_pmu__have_event(pmu, name);
622 }
623 
perf_pmus__num_core_pmus(void)624 int perf_pmus__num_core_pmus(void)
625 {
626 	static int count;
627 
628 	if (!count) {
629 		struct perf_pmu *pmu = NULL;
630 
631 		while ((pmu = perf_pmus__scan_core(pmu)) != NULL)
632 			count++;
633 	}
634 	return count;
635 }
636 
__perf_pmus__supports_extended_type(void)637 static bool __perf_pmus__supports_extended_type(void)
638 {
639 	struct perf_pmu *pmu = NULL;
640 
641 	if (perf_pmus__num_core_pmus() <= 1)
642 		return false;
643 
644 	while ((pmu = perf_pmus__scan_core(pmu)) != NULL) {
645 		if (!is_event_supported(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES | ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT)))
646 			return false;
647 	}
648 
649 	return true;
650 }
651 
652 static bool perf_pmus__do_support_extended_type;
653 
perf_pmus__init_supports_extended_type(void)654 static void perf_pmus__init_supports_extended_type(void)
655 {
656 	perf_pmus__do_support_extended_type = __perf_pmus__supports_extended_type();
657 }
658 
perf_pmus__supports_extended_type(void)659 bool perf_pmus__supports_extended_type(void)
660 {
661 	static pthread_once_t extended_type_once = PTHREAD_ONCE_INIT;
662 
663 	pthread_once(&extended_type_once, perf_pmus__init_supports_extended_type);
664 
665 	return perf_pmus__do_support_extended_type;
666 }
667 
perf_pmus__default_pmu_name(void)668 char *perf_pmus__default_pmu_name(void)
669 {
670 	int fd;
671 	DIR *dir;
672 	struct dirent *dent;
673 	char *result = NULL;
674 
675 	if (!list_empty(&core_pmus))
676 		return strdup(list_first_entry(&core_pmus, struct perf_pmu, list)->name);
677 
678 	fd = perf_pmu__event_source_devices_fd();
679 	if (fd < 0)
680 		return strdup("cpu");
681 
682 	dir = fdopendir(fd);
683 	if (!dir) {
684 		close(fd);
685 		return strdup("cpu");
686 	}
687 
688 	while ((dent = readdir(dir))) {
689 		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
690 			continue;
691 		if (is_pmu_core(dent->d_name)) {
692 			result = strdup(dent->d_name);
693 			break;
694 		}
695 	}
696 
697 	closedir(dir);
698 	return result ?: strdup("cpu");
699 }
700 
evsel__find_pmu(const struct evsel * evsel)701 struct perf_pmu *evsel__find_pmu(const struct evsel *evsel)
702 {
703 	struct perf_pmu *pmu = evsel->pmu;
704 
705 	if (!pmu) {
706 		pmu = perf_pmus__find_by_type(evsel->core.attr.type);
707 		((struct evsel *)evsel)->pmu = pmu;
708 	}
709 	return pmu;
710 }
711 
perf_pmus__find_core_pmu(void)712 struct perf_pmu *perf_pmus__find_core_pmu(void)
713 {
714 	return perf_pmus__scan_core(NULL);
715 }
716 
perf_pmus__add_test_pmu(int test_sysfs_dirfd,const char * name)717 struct perf_pmu *perf_pmus__add_test_pmu(int test_sysfs_dirfd, const char *name)
718 {
719 	/*
720 	 * Some PMU functions read from the sysfs mount point, so care is
721 	 * needed, hence passing the eager_load flag to load things like the
722 	 * format files.
723 	 */
724 	return perf_pmu__lookup(&other_pmus, test_sysfs_dirfd, name, /*eager_load=*/true);
725 }
726 
perf_pmus__fake_pmu(void)727 struct perf_pmu *perf_pmus__fake_pmu(void)
728 {
729 	static struct perf_pmu fake = {
730 		.name = "fake",
731 		.type = PERF_PMU_TYPE_FAKE,
732 		.format = LIST_HEAD_INIT(fake.format),
733 	};
734 
735 	return &fake;
736 }
737