xref: /linux/tools/perf/util/env.c (revision a77ecea7ced2fef7cc0a8ad0323542f781ad9788)
1 // SPDX-License-Identifier: GPL-2.0
2 #include "cpumap.h"
3 #include "dwarf-regs.h"
4 #include "debug.h"
5 #include "env.h"
6 #include "util/header.h"
7 #include "util/rwsem.h"
8 #include <linux/compiler.h>
9 #include <linux/kernel.h>
10 #include <linux/ctype.h>
11 #include <linux/rbtree.h>
12 #include <linux/string.h>
13 #include <linux/zalloc.h>
14 #include "cgroup.h"
15 #include <errno.h>
16 #include <sys/utsname.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include "pmu.h"
20 #include "pmus.h"
21 #include "strbuf.h"
22 #include "trace/beauty/beauty.h"
23 
24 #ifdef HAVE_LIBBPF_SUPPORT
25 #include "bpf-event.h"
26 #include "bpf-utils.h"
27 #include <bpf/libbpf.h>
28 
29 bool perf_env__insert_bpf_prog_info(struct perf_env *env,
30 				    struct bpf_prog_info_node *info_node)
31 {
32 	bool ret;
33 
34 	down_write(&env->bpf_progs.lock);
35 	ret = __perf_env__insert_bpf_prog_info(env, info_node);
36 	up_write(&env->bpf_progs.lock);
37 
38 	return ret;
39 }
40 
41 bool __perf_env__insert_bpf_prog_info(struct perf_env *env, struct bpf_prog_info_node *info_node)
42 {
43 	__u32 prog_id = info_node->info_linear->info.id;
44 	struct bpf_prog_info_node *node;
45 	struct rb_node *parent = NULL;
46 	struct rb_node **p;
47 
48 	p = &env->bpf_progs.infos.rb_node;
49 
50 	while (*p != NULL) {
51 		parent = *p;
52 		node = rb_entry(parent, struct bpf_prog_info_node, rb_node);
53 		if (prog_id < node->info_linear->info.id) {
54 			p = &(*p)->rb_left;
55 		} else if (prog_id > node->info_linear->info.id) {
56 			p = &(*p)->rb_right;
57 		} else {
58 			pr_debug("duplicated bpf prog info %u\n", prog_id);
59 			return false;
60 		}
61 	}
62 
63 	rb_link_node(&info_node->rb_node, parent, p);
64 	rb_insert_color(&info_node->rb_node, &env->bpf_progs.infos);
65 	env->bpf_progs.infos_cnt++;
66 	return true;
67 }
68 
69 struct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
70 							__u32 prog_id)
71 {
72 	struct bpf_prog_info_node *node = NULL;
73 	struct rb_node *n;
74 
75 	down_read(&env->bpf_progs.lock);
76 	n = env->bpf_progs.infos.rb_node;
77 
78 	while (n) {
79 		node = rb_entry(n, struct bpf_prog_info_node, rb_node);
80 		if (prog_id < node->info_linear->info.id)
81 			n = n->rb_left;
82 		else if (prog_id > node->info_linear->info.id)
83 			n = n->rb_right;
84 		else
85 			goto out;
86 	}
87 	node = NULL;
88 
89 out:
90 	up_read(&env->bpf_progs.lock);
91 	return node;
92 }
93 
94 void perf_env__iterate_bpf_prog_info(struct perf_env *env,
95 				     void (*cb)(struct bpf_prog_info_node *node,
96 						void *data),
97 				     void *data)
98 {
99 	struct rb_node *first;
100 
101 	down_read(&env->bpf_progs.lock);
102 	first = rb_first(&env->bpf_progs.infos);
103 	for (struct rb_node *node = first; node != NULL; node = rb_next(node))
104 		(*cb)(rb_entry(node, struct bpf_prog_info_node, rb_node), data);
105 	up_read(&env->bpf_progs.lock);
106 }
107 
108 bool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
109 {
110 	bool ret;
111 
112 	down_write(&env->bpf_progs.lock);
113 	ret = __perf_env__insert_btf(env, btf_node);
114 	up_write(&env->bpf_progs.lock);
115 	return ret;
116 }
117 
118 bool __perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
119 {
120 	struct rb_node *parent = NULL;
121 	__u32 btf_id = btf_node->id;
122 	struct btf_node *node;
123 	struct rb_node **p;
124 
125 	p = &env->bpf_progs.btfs.rb_node;
126 
127 	while (*p != NULL) {
128 		parent = *p;
129 		node = rb_entry(parent, struct btf_node, rb_node);
130 		if (btf_id < node->id) {
131 			p = &(*p)->rb_left;
132 		} else if (btf_id > node->id) {
133 			p = &(*p)->rb_right;
134 		} else {
135 			pr_debug("duplicated btf %u\n", btf_id);
136 			return false;
137 		}
138 	}
139 
140 	rb_link_node(&btf_node->rb_node, parent, p);
141 	rb_insert_color(&btf_node->rb_node, &env->bpf_progs.btfs);
142 	env->bpf_progs.btfs_cnt++;
143 	return true;
144 }
145 
146 struct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id)
147 {
148 	struct btf_node *res;
149 
150 	down_read(&env->bpf_progs.lock);
151 	res = __perf_env__find_btf(env, btf_id);
152 	up_read(&env->bpf_progs.lock);
153 	return res;
154 }
155 
156 struct btf_node *__perf_env__find_btf(struct perf_env *env, __u32 btf_id)
157 {
158 	struct btf_node *node = NULL;
159 	struct rb_node *n;
160 
161 	n = env->bpf_progs.btfs.rb_node;
162 
163 	while (n) {
164 		node = rb_entry(n, struct btf_node, rb_node);
165 		if (btf_id < node->id)
166 			n = n->rb_left;
167 		else if (btf_id > node->id)
168 			n = n->rb_right;
169 		else
170 			return node;
171 	}
172 	return NULL;
173 }
174 
175 /* purge data in bpf_progs.infos tree */
176 static void perf_env__purge_bpf(struct perf_env *env)
177 {
178 	struct rb_root *root;
179 	struct rb_node *next;
180 
181 	down_write(&env->bpf_progs.lock);
182 
183 	root = &env->bpf_progs.infos;
184 	next = rb_first(root);
185 
186 	while (next) {
187 		struct bpf_prog_info_node *node;
188 
189 		node = rb_entry(next, struct bpf_prog_info_node, rb_node);
190 		next = rb_next(&node->rb_node);
191 		rb_erase(&node->rb_node, root);
192 		zfree(&node->info_linear);
193 		bpf_metadata_free(node->metadata);
194 		free(node);
195 	}
196 
197 	env->bpf_progs.infos_cnt = 0;
198 
199 	root = &env->bpf_progs.btfs;
200 	next = rb_first(root);
201 
202 	while (next) {
203 		struct btf_node *node;
204 
205 		node = rb_entry(next, struct btf_node, rb_node);
206 		next = rb_next(&node->rb_node);
207 		rb_erase(&node->rb_node, root);
208 		free(node);
209 	}
210 
211 	env->bpf_progs.btfs_cnt = 0;
212 
213 	up_write(&env->bpf_progs.lock);
214 }
215 #else // HAVE_LIBBPF_SUPPORT
216 static void perf_env__purge_bpf(struct perf_env *env __maybe_unused)
217 {
218 }
219 #endif // HAVE_LIBBPF_SUPPORT
220 
221 void free_cpu_domain_info(struct cpu_domain_map **cd_map, u32 schedstat_version, u32 nr)
222 {
223 	if (!cd_map)
224 		return;
225 
226 	for (u32 i = 0; i < nr; i++) {
227 		if (!cd_map[i])
228 			continue;
229 
230 		for (u32 j = 0; j < cd_map[i]->nr_domains; j++) {
231 			struct domain_info *d_info = cd_map[i]->domains[j];
232 
233 			if (!d_info)
234 				continue;
235 
236 			if (schedstat_version >= 17)
237 				zfree(&d_info->dname);
238 
239 			zfree(&d_info->cpumask);
240 			zfree(&d_info->cpulist);
241 			zfree(&d_info);
242 		}
243 		zfree(&cd_map[i]->domains);
244 		zfree(&cd_map[i]);
245 	}
246 	zfree(&cd_map);
247 }
248 
249 void perf_env__exit(struct perf_env *env)
250 {
251 	int i, j;
252 
253 	mutex_destroy(&env->lock);
254 
255 	perf_env__purge_bpf(env);
256 	perf_env__purge_cgroups(env);
257 	zfree(&env->hostname);
258 	zfree(&env->os_release);
259 	zfree(&env->version);
260 	zfree(&env->arch);
261 	zfree(&env->cpu_desc);
262 	zfree(&env->cpuid);
263 	zfree(&env->cmdline);
264 	zfree(&env->cmdline_argv);
265 	zfree(&env->sibling_dies);
266 	zfree(&env->sibling_cores);
267 	zfree(&env->sibling_threads);
268 	zfree(&env->pmu_mappings);
269 	zfree(&env->cpu);
270 	for (i = 0; i < env->nr_cpu_pmu_caps; i++)
271 		zfree(&env->cpu_pmu_caps[i]);
272 	zfree(&env->cpu_pmu_caps);
273 	zfree(&env->numa_map);
274 
275 	for (i = 0; i < env->nr_numa_nodes; i++)
276 		perf_cpu_map__put(env->numa_nodes[i].map);
277 	zfree(&env->numa_nodes);
278 
279 	for (i = 0; i < env->caches_cnt; i++)
280 		cpu_cache_level__free(&env->caches[i]);
281 	zfree(&env->caches);
282 
283 	for (i = 0; i < env->nr_memory_nodes; i++)
284 		zfree(&env->memory_nodes[i].set);
285 	zfree(&env->memory_nodes);
286 
287 	for (i = 0; i < env->nr_hybrid_nodes; i++) {
288 		zfree(&env->hybrid_nodes[i].pmu_name);
289 		zfree(&env->hybrid_nodes[i].cpus);
290 	}
291 	zfree(&env->hybrid_nodes);
292 
293 	for (i = 0; i < env->nr_pmus_with_caps; i++) {
294 		for (j = 0; j < env->pmu_caps[i].nr_caps; j++)
295 			zfree(&env->pmu_caps[i].caps[j]);
296 		zfree(&env->pmu_caps[i].caps);
297 		zfree(&env->pmu_caps[i].pmu_name);
298 	}
299 	zfree(&env->pmu_caps);
300 	free_cpu_domain_info(env->cpu_domain, env->schedstat_version, env->nr_cpus_avail);
301 }
302 
303 void perf_env__init(struct perf_env *env)
304 {
305 	memset(env, 0, sizeof(*env));
306 #ifdef HAVE_LIBBPF_SUPPORT
307 	env->bpf_progs.infos = RB_ROOT;
308 	env->bpf_progs.btfs = RB_ROOT;
309 	init_rwsem(&env->bpf_progs.lock);
310 #endif
311 	env->kernel_is_64_bit = -1;
312 	mutex_init(&env->lock);
313 }
314 
315 static void perf_env__init_kernel_mode(struct perf_env *env)
316 {
317 	const char *arch = env->arch;
318 
319 	if (!arch) {
320 		static struct utsname uts = { .machine[0] = '\0', };
321 
322 		if (uts.machine[0] == '\0')
323 			uname(&uts);
324 		if (uts.machine[0] != '\0')
325 			arch = uts.machine;
326 	}
327 
328 	if (arch) {
329 		if (strstr(arch, "64") || strstr(arch, "s390x"))
330 			env->kernel_is_64_bit = 1;
331 		else
332 			env->kernel_is_64_bit = 0;
333 		return;
334 	}
335 
336 	/* Fallback if completely unresolvable (assume host-bitness) */
337 	env->kernel_is_64_bit = (sizeof(void *) == 8) ? 1 : 0;
338 }
339 
340 int perf_env__kernel_is_64_bit(struct perf_env *env)
341 {
342 	if (env->kernel_is_64_bit == -1)
343 		perf_env__init_kernel_mode(env);
344 
345 	return env->kernel_is_64_bit;
346 }
347 
348 bool perf_arch_is_big_endian(const char *arch)
349 {
350 	if (!arch)
351 		return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;
352 
353 	if (str_ends_with(arch, "_be") || !strcmp(arch, "sparc") || !strcmp(arch, "sparc64") ||
354 	    !strcmp(arch, "s390") || !strcmp(arch, "s390x") || !strcmp(arch, "powerpc") ||
355 	    !strcmp(arch, "ppc") || !strcmp(arch, "ppc64") ||
356 	    !strcmp(arch, "mips") || !strcmp(arch, "mips64") || !strcmp(arch, "parisc") ||
357 	    !strcmp(arch, "parisc64") || !strcmp(arch, "m68k") ||
358 	    !strcmp(arch, "armeb") || !strcmp(arch, "mipseb") || !strcmp(arch, "mips64eb"))
359 		return true;
360 
361 	return false;
362 }
363 
364 const char *perf_env__os_release(struct perf_env *env)
365 {
366 	struct utsname uts;
367 	int ret;
368 	const char *release;
369 
370 	if (!env)
371 		return perf_version_string;
372 
373 	mutex_lock(&env->lock);
374 	if (env->os_release) {
375 		release = env->os_release;
376 		goto out;
377 	}
378 
379 	/*
380 	 * If env->arch is set, this is an offline target environment.
381 	 * If the os_release is not populated in the file, we do not want
382 	 * to poison it with the host's release which would break guest checks.
383 	 */
384 	if (env->arch) {
385 		release = NULL;
386 		goto out;
387 	}
388 
389 	/*
390 	 * The os_release is being accessed but wasn't initialized from a data
391 	 * file, assume this is 'live' mode and use the release from uname. If
392 	 * uname or strdup fails then use the current perf tool version.
393 	 */
394 	ret = uname(&uts);
395 	env->os_release = strdup(ret < 0 ? perf_version_string : uts.release);
396 	release = env->os_release ?: perf_version_string;
397 out:
398 	mutex_unlock(&env->lock);
399 	return release;
400 }
401 
402 int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
403 {
404 	int i;
405 
406 	/* do not include NULL termination */
407 	env->cmdline_argv = calloc(argc, sizeof(char *));
408 	if (env->cmdline_argv == NULL)
409 		goto out_enomem;
410 
411 	/*
412 	 * Must copy argv contents because it gets moved around during option
413 	 * parsing:
414 	 */
415 	for (i = 0; i < argc ; i++) {
416 		env->cmdline_argv[i] = argv[i];
417 		if (env->cmdline_argv[i] == NULL)
418 			goto out_free;
419 	}
420 
421 	env->nr_cmdline = argc;
422 
423 	return 0;
424 out_free:
425 	zfree(&env->cmdline_argv);
426 out_enomem:
427 	return -ENOMEM;
428 }
429 
430 int perf_env__read_cpu_topology_map(struct perf_env *env)
431 {
432 	int idx, nr_cpus;
433 
434 	if (env->cpu != NULL)
435 		return 0;
436 
437 	if (env->nr_cpus_avail == 0)
438 		env->nr_cpus_avail = cpu__max_present_cpu().cpu;
439 
440 	nr_cpus = env->nr_cpus_avail;
441 	if (nr_cpus == -1)
442 		return -EINVAL;
443 
444 	env->cpu = calloc(nr_cpus, sizeof(env->cpu[0]));
445 	if (env->cpu == NULL)
446 		return -ENOMEM;
447 
448 	for (idx = 0; idx < nr_cpus; ++idx) {
449 		struct perf_cpu cpu = { .cpu = idx };
450 		int core_id   = cpu__get_core_id(cpu);
451 		int socket_id = cpu__get_socket_id(cpu);
452 		int die_id    = cpu__get_die_id(cpu);
453 
454 		env->cpu[idx].core_id	= core_id >= 0 ? core_id : -1;
455 		env->cpu[idx].socket_id	= socket_id >= 0 ? socket_id : -1;
456 		env->cpu[idx].die_id	= die_id >= 0 ? die_id : -1;
457 	}
458 
459 	env->nr_cpus_avail = nr_cpus;
460 	return 0;
461 }
462 
463 int perf_env__read_pmu_mappings(struct perf_env *env)
464 {
465 	struct perf_pmu *pmu = NULL;
466 	u32 pmu_num = 0;
467 	struct strbuf sb;
468 
469 	while ((pmu = perf_pmus__scan(pmu)))
470 		pmu_num++;
471 
472 	if (!pmu_num) {
473 		pr_debug("pmu mappings not available\n");
474 		return -ENOENT;
475 	}
476 	env->nr_pmu_mappings = pmu_num;
477 
478 	if (strbuf_init(&sb, 128 * pmu_num) < 0)
479 		return -ENOMEM;
480 
481 	while ((pmu = perf_pmus__scan(pmu))) {
482 		if (strbuf_addf(&sb, "%u:%s", pmu->type, pmu->name) < 0)
483 			goto error;
484 		/* include a NULL character at the end */
485 		if (strbuf_add(&sb, "", 1) < 0)
486 			goto error;
487 	}
488 
489 	env->pmu_mappings = strbuf_detach(&sb, NULL);
490 
491 	return 0;
492 
493 error:
494 	strbuf_release(&sb);
495 	return -1;
496 }
497 
498 int perf_env__read_cpuid(struct perf_env *env)
499 {
500 	char cpuid[128];
501 	struct perf_cpu cpu = {-1};
502 	int err = get_cpuid(cpuid, sizeof(cpuid), cpu);
503 
504 	if (err)
505 		return err;
506 
507 	free(env->cpuid);
508 	env->cpuid = strdup(cpuid);
509 	if (env->cpuid == NULL)
510 		return ENOMEM;
511 	return 0;
512 }
513 
514 static int perf_env__read_nr_cpus_avail(struct perf_env *env)
515 {
516 	if (env->nr_cpus_avail == 0)
517 		env->nr_cpus_avail = cpu__max_present_cpu().cpu;
518 
519 	return env->nr_cpus_avail ? 0 : -ENOENT;
520 }
521 
522 static int __perf_env__read_core_pmu_caps(const struct perf_pmu *pmu,
523 					  int *nr_caps, char ***caps,
524 					  unsigned int *max_branches,
525 					  unsigned int *br_cntr_nr,
526 					  unsigned int *br_cntr_width)
527 {
528 	struct perf_pmu_caps *pcaps = NULL;
529 	char *ptr, **tmp;
530 	int ret = 0;
531 
532 	*nr_caps = 0;
533 	*caps = NULL;
534 
535 	if (!pmu->nr_caps)
536 		return 0;
537 
538 	*caps = calloc(pmu->nr_caps, sizeof(char *));
539 	if (!*caps)
540 		return -ENOMEM;
541 
542 	tmp = *caps;
543 	list_for_each_entry(pcaps, &pmu->caps, list) {
544 		if (asprintf(&ptr, "%s=%s", pcaps->name, pcaps->value) < 0) {
545 			ret = -ENOMEM;
546 			goto error;
547 		}
548 
549 		*tmp++ = ptr;
550 
551 		if (!strcmp(pcaps->name, "branches"))
552 			*max_branches = atoi(pcaps->value);
553 		else if (!strcmp(pcaps->name, "branch_counter_nr"))
554 			*br_cntr_nr = atoi(pcaps->value);
555 		else if (!strcmp(pcaps->name, "branch_counter_width"))
556 			*br_cntr_width = atoi(pcaps->value);
557 	}
558 	*nr_caps = pmu->nr_caps;
559 	return 0;
560 error:
561 	while (tmp-- != *caps)
562 		zfree(tmp);
563 	zfree(caps);
564 	*nr_caps = 0;
565 	return ret;
566 }
567 
568 int perf_env__read_core_pmu_caps(struct perf_env *env)
569 {
570 	struct pmu_caps *pmu_caps;
571 	struct perf_pmu *pmu = NULL;
572 	int nr_pmu, i = 0, j;
573 	int ret;
574 
575 	nr_pmu = perf_pmus__num_core_pmus();
576 
577 	if (!nr_pmu)
578 		return -ENODEV;
579 
580 	if (nr_pmu == 1) {
581 		pmu = perf_pmus__find_core_pmu();
582 		if (!pmu)
583 			return -ENODEV;
584 		ret = perf_pmu__caps_parse(pmu);
585 		if (ret < 0)
586 			return ret;
587 		return __perf_env__read_core_pmu_caps(pmu, &env->nr_cpu_pmu_caps,
588 						      &env->cpu_pmu_caps,
589 						      &env->max_branches,
590 						      &env->br_cntr_nr,
591 						      &env->br_cntr_width);
592 	}
593 
594 	pmu_caps = calloc(nr_pmu, sizeof(*pmu_caps));
595 	if (!pmu_caps)
596 		return -ENOMEM;
597 
598 	while ((pmu = perf_pmus__scan_core(pmu)) != NULL) {
599 		if (perf_pmu__caps_parse(pmu) <= 0)
600 			continue;
601 		ret = __perf_env__read_core_pmu_caps(pmu, &pmu_caps[i].nr_caps,
602 						     &pmu_caps[i].caps,
603 						     &pmu_caps[i].max_branches,
604 						     &pmu_caps[i].br_cntr_nr,
605 						     &pmu_caps[i].br_cntr_width);
606 		if (ret)
607 			goto error;
608 
609 		pmu_caps[i].pmu_name = strdup(pmu->name);
610 		if (!pmu_caps[i].pmu_name) {
611 			ret = -ENOMEM;
612 			goto error;
613 		}
614 		i++;
615 	}
616 
617 	env->nr_pmus_with_caps = nr_pmu;
618 	env->pmu_caps = pmu_caps;
619 
620 	return 0;
621 error:
622 	for (i = 0; i < nr_pmu; i++) {
623 		for (j = 0; j < pmu_caps[i].nr_caps; j++)
624 			zfree(&pmu_caps[i].caps[j]);
625 		zfree(&pmu_caps[i].caps);
626 		zfree(&pmu_caps[i].pmu_name);
627 	}
628 	zfree(&pmu_caps);
629 	return ret;
630 }
631 
632 int perf_env__nr_cpus_avail(struct perf_env *env)
633 {
634 	return env && !perf_env__read_nr_cpus_avail(env) ? env->nr_cpus_avail : 0;
635 }
636 
637 void cpu_cache_level__free(struct cpu_cache_level *cache)
638 {
639 	zfree(&cache->type);
640 	zfree(&cache->map);
641 	zfree(&cache->size);
642 }
643 
644 struct arch_to_e_machine {
645 	const char *prefix;
646 	uint16_t e_machine;
647 };
648 
649 /*
650  * A mapping from an arch prefix string to an ELF machine that can be used in a
651  * bsearch. Some arch prefixes are shared an need additional processing as
652  * marked next to the architecture. The prefixes handle both perf's architecture
653  * naming and those from uname.
654  */
655 static const struct arch_to_e_machine prefix_to_e_machine[] = {
656 	{"aarch64", EM_AARCH64},
657 	{"alpha", EM_ALPHA},
658 	{"arc", EM_ARC},
659 	{"arm", EM_ARM}, /* Check also for EM_AARCH64. */
660 	{"avr", EM_AVR},  /* Check also for EM_AVR32. */
661 	{"bfin", EM_BLACKFIN},
662 	{"blackfin", EM_BLACKFIN},
663 	{"cris", EM_CRIS},
664 	{"csky", EM_CSKY},
665 	{"hppa", EM_PARISC},
666 	{"i386", EM_386},
667 	{"i486", EM_386},
668 	{"i586", EM_386},
669 	{"i686", EM_386},
670 	{"loongarch", EM_LOONGARCH},
671 	{"m32r", EM_M32R},
672 	{"m68k", EM_68K},
673 	{"microblaze", EM_MICROBLAZE},
674 	{"mips", EM_MIPS},
675 	{"msp430", EM_MSP430},
676 	{"parisc", EM_PARISC},
677 	{"powerpc", EM_PPC}, /* Check also for EM_PPC64. */
678 	{"ppc", EM_PPC}, /* Check also for EM_PPC64. */
679 	{"riscv", EM_RISCV},
680 	{"s390", EM_S390},
681 	{"sa110", EM_ARM},
682 	{"sh", EM_SH},
683 	{"sparc", EM_SPARC}, /* Check also for EM_SPARCV9. */
684 	{"sun4u", EM_SPARC},
685 	{"x86", EM_X86_64}, /* Check also for EM_386. */
686 	{"xtensa", EM_XTENSA},
687 };
688 
689 static int compare_prefix(const void *key, const void *element)
690 {
691 	const char *search_key = key;
692 	const struct arch_to_e_machine *map_element = element;
693 	size_t prefix_len = strlen(map_element->prefix);
694 
695 	return strncmp(search_key, map_element->prefix, prefix_len);
696 }
697 
698 static uint16_t perf_arch_to_e_machine(const char *perf_arch, int is_64_bit)
699 {
700 	/* Binary search for a matching prefix. */
701 	const struct arch_to_e_machine *result;
702 
703 	if (!perf_arch)
704 		return EM_HOST;
705 
706 	result = bsearch(perf_arch,
707 			 prefix_to_e_machine, ARRAY_SIZE(prefix_to_e_machine),
708 			 sizeof(prefix_to_e_machine[0]),
709 			 compare_prefix);
710 
711 	if (!result) {
712 		pr_debug("Unknown perf arch for ELF machine mapping: %s\n", perf_arch);
713 		return EM_NONE;
714 	}
715 
716 	/*
717 	 * Handle conflicting prefixes. If the is_64_bit is unknown (-1) then
718 	 * assume 64-bit. We can't use perf_env__kernel_is_64_bit as that
719 	 * depends on the arch string.
720 	 */
721 	switch (result->e_machine) {
722 	case EM_ARM:
723 		return !strcmp(perf_arch, "arm64") || !strcmp(perf_arch, "aarch64")
724 			? EM_AARCH64 : EM_ARM;
725 	case EM_AVR:
726 		return !strcmp(perf_arch, "avr32") ? EM_AVR32 : EM_AVR;
727 	case EM_PPC:
728 		if (is_64_bit == 1)
729 			return EM_PPC64;
730 		if (is_64_bit == 0)
731 			return EM_PPC;
732 		return strstarts(perf_arch, "ppc64") ? EM_PPC64 : EM_PPC;
733 	case EM_SPARC:
734 		if (is_64_bit == 1)
735 			return EM_SPARCV9;
736 		if (is_64_bit == 0)
737 			return EM_SPARC;
738 		return !strcmp(perf_arch, "sparc64") || !strcmp(perf_arch, "sun4u")
739 			? EM_SPARCV9 : EM_SPARC;
740 	case EM_X86_64:
741 		if (is_64_bit == 1)
742 			return EM_X86_64;
743 		if (is_64_bit == 0)
744 			return EM_386;
745 		return !strcmp(perf_arch, "x86_64") || !strcmp(perf_arch, "x86")
746 			? EM_X86_64 : EM_386;
747 	default:
748 		return result->e_machine;
749 	}
750 }
751 
752 static const char *e_machine_to_perf_arch(uint16_t e_machine)
753 {
754 	/*
755 	 * Table for if either the perf arch string differs from uname or there
756 	 * are >1 ELF machine with the prefix.
757 	 */
758 	static const struct arch_to_e_machine extras[] = {
759 		{"arm64", EM_AARCH64},
760 		{"avr32", EM_AVR32},
761 		{"powerpc", EM_PPC},
762 		{"powerpc", EM_PPC64},
763 		{"sparc", EM_SPARCV9},
764 		{"x86", EM_386},
765 		{"x86", EM_X86_64},
766 		{"none", EM_NONE},
767 	};
768 
769 	for (size_t i = 0; i < ARRAY_SIZE(extras); i++) {
770 		if (extras[i].e_machine == e_machine)
771 			return extras[i].prefix;
772 	}
773 
774 	for (size_t i = 0; i < ARRAY_SIZE(prefix_to_e_machine); i++) {
775 		if (prefix_to_e_machine[i].e_machine == e_machine)
776 			return prefix_to_e_machine[i].prefix;
777 
778 	}
779 	return "unknown";
780 }
781 
782 uint16_t perf_env__e_machine_nocache(struct perf_env *env, uint32_t *e_flags)
783 {
784 	uint16_t e_machine = EM_NONE;
785 	const char *arch = NULL;
786 	int is_64_bit = -1;
787 
788 	if (e_flags)
789 		*e_flags = 0;
790 
791 	if (env) {
792 		arch = env->arch;
793 		is_64_bit = env->kernel_is_64_bit;
794 	}
795 
796 	if (!arch) {
797 		static struct utsname uts = { .machine[0] = '\0', };
798 
799 		if (uts.machine[0] == '\0')
800 			uname(&uts);
801 		if (uts.machine[0] != '\0')
802 			arch = uts.machine;
803 	}
804 
805 	e_machine = perf_arch_to_e_machine(arch, is_64_bit);
806 
807 	if (e_flags)
808 		*e_flags = (e_machine == EM_HOST) ? EF_HOST : 0;
809 
810 	return e_machine;
811 }
812 
813 uint16_t perf_env__e_machine(struct perf_env *env, uint32_t *e_flags)
814 {
815 	uint16_t e_machine;
816 	uint32_t local_e_flags = 0;
817 
818 	if (env && env->e_machine != EM_NONE) {
819 		if (e_flags)
820 			*e_flags = env->e_flags;
821 
822 		return env->e_machine;
823 	}
824 	e_machine = perf_env__e_machine_nocache(env, &local_e_flags);
825 	/*
826 	 * Only cache the e_machine in perf_env if env->arch is not NULL.
827 	 * If env->arch is NULL, the e_machine is just a fallback to EM_HOST.
828 	 * Caching it permanently would prevent dynamic, more accurate
829 	 * thread-based session e_machine scanning later in
830 	 * perf_session__e_machine().
831 	 */
832 	if (env && env->arch) {
833 		env->e_machine = e_machine;
834 		env->e_flags = local_e_flags;
835 	}
836 	if (e_flags)
837 		*e_flags = local_e_flags;
838 
839 	return e_machine;
840 }
841 
842 const char *perf_env__arch(struct perf_env *env)
843 {
844 	uint16_t e_machine;
845 	const char *arch;
846 
847 	if (!env) {
848 		static struct utsname uts = { .machine[0] = '\0', };
849 		uint16_t host_e_machine;
850 
851 		if (uts.machine[0] == '\0')
852 			uname(&uts);
853 		if (uts.machine[0] != '\0') {
854 			host_e_machine = perf_arch_to_e_machine(uts.machine, -1);
855 			return e_machine_to_perf_arch(host_e_machine);
856 		}
857 		return e_machine_to_perf_arch(EM_HOST);
858 	}
859 
860 	/*
861 	 * Lazily compute/allocate arch. The e_machine may have been
862 	 * read from a data file and so may not be EM_HOST.
863 	 */
864 	e_machine = perf_env__e_machine(env, /*e_flags=*/NULL);
865 	arch = e_machine_to_perf_arch(e_machine);
866 
867 	if (e_machine == EM_RISCV && perf_env__kernel_is_64_bit(env) == 1)
868 		arch = "riscv64";
869 	else if (e_machine == EM_MIPS && perf_env__kernel_is_64_bit(env) == 1)
870 		arch = "mips64";
871 	else if (e_machine == EM_PARISC && perf_env__kernel_is_64_bit(env) == 1)
872 		arch = "parisc64";
873 
874 	return arch;
875 }
876 
877 const char *arch_syscalls__strerrno(uint16_t e_machine, int err);
878 
879 const char *perf_env__arch_strerrno(uint16_t e_machine, int err)
880 {
881 	return arch_syscalls__strerrno(e_machine, err);
882 }
883 
884 const char *perf_env__cpuid(struct perf_env *env)
885 {
886 	int status;
887 
888 	if (!env->cpuid) { /* Assume local operation */
889 		status = perf_env__read_cpuid(env);
890 		if (status)
891 			return NULL;
892 	}
893 
894 	return env->cpuid;
895 }
896 
897 int perf_env__nr_pmu_mappings(struct perf_env *env)
898 {
899 	int status;
900 
901 	if (!env->nr_pmu_mappings) { /* Assume local operation */
902 		status = perf_env__read_pmu_mappings(env);
903 		if (status)
904 			return 0;
905 	}
906 
907 	return env->nr_pmu_mappings;
908 }
909 
910 const char *perf_env__pmu_mappings(struct perf_env *env)
911 {
912 	int status;
913 
914 	if (!env->pmu_mappings) { /* Assume local operation */
915 		status = perf_env__read_pmu_mappings(env);
916 		if (status)
917 			return NULL;
918 	}
919 
920 	return env->pmu_mappings;
921 }
922 
923 int perf_env__numa_node(struct perf_env *env, struct perf_cpu cpu)
924 {
925 	if (!env->nr_numa_map) {
926 		struct numa_node *nn;
927 		int i, nr = 0;
928 
929 		for (i = 0; i < env->nr_numa_nodes; i++) {
930 			nn = &env->numa_nodes[i];
931 			nr = max(nr, (int)perf_cpu_map__max(nn->map).cpu);
932 		}
933 
934 		nr++;
935 
936 		/*
937 		 * We initialize the numa_map array to prepare
938 		 * it for missing cpus, which return node -1
939 		 */
940 		env->numa_map = malloc(nr * sizeof(int));
941 		if (!env->numa_map)
942 			return -1;
943 
944 		for (i = 0; i < nr; i++)
945 			env->numa_map[i] = -1;
946 
947 		env->nr_numa_map = nr;
948 
949 		for (i = 0; i < env->nr_numa_nodes; i++) {
950 			struct perf_cpu tmp;
951 			unsigned int j;
952 
953 			nn = &env->numa_nodes[i];
954 			perf_cpu_map__for_each_cpu(tmp, j, nn->map)
955 				env->numa_map[tmp.cpu] = i;
956 		}
957 	}
958 
959 	return cpu.cpu >= 0 && cpu.cpu < env->nr_numa_map ? env->numa_map[cpu.cpu] : -1;
960 }
961 
962 bool perf_env__has_pmu_mapping(struct perf_env *env, const char *pmu_name)
963 {
964 	char *pmu_mapping = env->pmu_mappings, *colon;
965 
966 	for (int i = 0; i < env->nr_pmu_mappings; ++i) {
967 		if (strtoul(pmu_mapping, &colon, 0) == ULONG_MAX || *colon != ':')
968 			goto out_error;
969 
970 		pmu_mapping = colon + 1;
971 		if (strcmp(pmu_mapping, pmu_name) == 0)
972 			return true;
973 
974 		pmu_mapping += strlen(pmu_mapping) + 1;
975 	}
976 out_error:
977 	return false;
978 }
979 
980 char *perf_env__find_pmu_cap(struct perf_env *env, const char *pmu_name,
981 			     const char *cap)
982 {
983 	char *cap_eq;
984 	int cap_size;
985 	char **ptr;
986 	int i, j;
987 
988 	if (!pmu_name || !cap)
989 		return NULL;
990 
991 	cap_size = strlen(cap);
992 	cap_eq = zalloc(cap_size + 2);
993 	if (!cap_eq)
994 		return NULL;
995 
996 	memcpy(cap_eq, cap, cap_size);
997 	cap_eq[cap_size] = '=';
998 
999 	if (!strcmp(pmu_name, "cpu")) {
1000 		for (i = 0; i < env->nr_cpu_pmu_caps; i++) {
1001 			if (!strncmp(env->cpu_pmu_caps[i], cap_eq, cap_size + 1)) {
1002 				free(cap_eq);
1003 				return &env->cpu_pmu_caps[i][cap_size + 1];
1004 			}
1005 		}
1006 		goto out;
1007 	}
1008 
1009 	for (i = 0; i < env->nr_pmus_with_caps; i++) {
1010 		if (strcmp(env->pmu_caps[i].pmu_name, pmu_name))
1011 			continue;
1012 
1013 		ptr = env->pmu_caps[i].caps;
1014 
1015 		for (j = 0; j < env->pmu_caps[i].nr_caps; j++) {
1016 			if (!strncmp(ptr[j], cap_eq, cap_size + 1)) {
1017 				free(cap_eq);
1018 				return &ptr[j][cap_size + 1];
1019 			}
1020 		}
1021 	}
1022 
1023 out:
1024 	free(cap_eq);
1025 	return NULL;
1026 }
1027 
1028 void perf_env__find_br_cntr_info(struct perf_env *env,
1029 				 unsigned int *nr,
1030 				 unsigned int *width)
1031 {
1032 	if (nr) {
1033 		*nr = env->cpu_pmu_caps ? env->br_cntr_nr :
1034 					  env->pmu_caps->br_cntr_nr;
1035 	}
1036 
1037 	if (width) {
1038 		*width = env->cpu_pmu_caps ? env->br_cntr_width :
1039 					     env->pmu_caps->br_cntr_width;
1040 	}
1041 }
1042 
1043 bool perf_env__is_x86_amd_cpu(struct perf_env *env)
1044 {
1045 	static int is_amd; /* 0: Uninitialized, 1: Yes, -1: No */
1046 
1047 	if (is_amd == 0)
1048 		is_amd = env->cpuid && strstarts(env->cpuid, "AuthenticAMD") ? 1 : -1;
1049 
1050 	return is_amd >= 1 ? true : false;
1051 }
1052 
1053 bool x86__is_amd_cpu(void)
1054 {
1055 	struct perf_env env = { .total_mem = 0, };
1056 	bool is_amd;
1057 
1058 	perf_env__init(&env);
1059 	perf_env__cpuid(&env);
1060 	is_amd = perf_env__is_x86_amd_cpu(&env);
1061 	perf_env__exit(&env);
1062 
1063 	return is_amd;
1064 }
1065 
1066 bool perf_env__is_x86_intel_cpu(struct perf_env *env)
1067 {
1068 	static int is_intel; /* 0: Uninitialized, 1: Yes, -1: No */
1069 
1070 	if (is_intel == 0)
1071 		is_intel = env->cpuid && strstarts(env->cpuid, "GenuineIntel") ? 1 : -1;
1072 
1073 	return is_intel >= 1 ? true : false;
1074 }
1075 
1076 bool x86__is_intel_cpu(void)
1077 {
1078 	struct perf_env env = { .total_mem = 0, };
1079 	bool is_intel;
1080 
1081 	perf_env__init(&env);
1082 	perf_env__cpuid(&env);
1083 	is_intel = perf_env__is_x86_intel_cpu(&env);
1084 	perf_env__exit(&env);
1085 
1086 	return is_intel;
1087 }
1088