18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include "cpumap.h"
38c2ecf20Sopenharmony_ci#include "debug.h"
48c2ecf20Sopenharmony_ci#include "env.h"
58c2ecf20Sopenharmony_ci#include "util/header.h"
68c2ecf20Sopenharmony_ci#include <linux/ctype.h>
78c2ecf20Sopenharmony_ci#include <linux/zalloc.h>
88c2ecf20Sopenharmony_ci#include "bpf-event.h"
98c2ecf20Sopenharmony_ci#include "cgroup.h"
108c2ecf20Sopenharmony_ci#include <errno.h>
118c2ecf20Sopenharmony_ci#include <sys/utsname.h>
128c2ecf20Sopenharmony_ci#include <bpf/libbpf.h>
138c2ecf20Sopenharmony_ci#include <stdlib.h>
148c2ecf20Sopenharmony_ci#include <string.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistruct perf_env perf_env;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_civoid perf_env__insert_bpf_prog_info(struct perf_env *env,
198c2ecf20Sopenharmony_ci				    struct bpf_prog_info_node *info_node)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	down_write(&env->bpf_progs.lock);
228c2ecf20Sopenharmony_ci	__perf_env__insert_bpf_prog_info(env, info_node);
238c2ecf20Sopenharmony_ci	up_write(&env->bpf_progs.lock);
248c2ecf20Sopenharmony_ci}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_civoid __perf_env__insert_bpf_prog_info(struct perf_env *env, struct bpf_prog_info_node *info_node)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	__u32 prog_id = info_node->info_linear->info.id;
298c2ecf20Sopenharmony_ci	struct bpf_prog_info_node *node;
308c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL;
318c2ecf20Sopenharmony_ci	struct rb_node **p;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	p = &env->bpf_progs.infos.rb_node;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	while (*p != NULL) {
368c2ecf20Sopenharmony_ci		parent = *p;
378c2ecf20Sopenharmony_ci		node = rb_entry(parent, struct bpf_prog_info_node, rb_node);
388c2ecf20Sopenharmony_ci		if (prog_id < node->info_linear->info.id) {
398c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
408c2ecf20Sopenharmony_ci		} else if (prog_id > node->info_linear->info.id) {
418c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
428c2ecf20Sopenharmony_ci		} else {
438c2ecf20Sopenharmony_ci			pr_debug("duplicated bpf prog info %u\n", prog_id);
448c2ecf20Sopenharmony_ci			return;
458c2ecf20Sopenharmony_ci		}
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	rb_link_node(&info_node->rb_node, parent, p);
498c2ecf20Sopenharmony_ci	rb_insert_color(&info_node->rb_node, &env->bpf_progs.infos);
508c2ecf20Sopenharmony_ci	env->bpf_progs.infos_cnt++;
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistruct bpf_prog_info_node *perf_env__find_bpf_prog_info(struct perf_env *env,
548c2ecf20Sopenharmony_ci							__u32 prog_id)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	struct bpf_prog_info_node *node = NULL;
578c2ecf20Sopenharmony_ci	struct rb_node *n;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	down_read(&env->bpf_progs.lock);
608c2ecf20Sopenharmony_ci	n = env->bpf_progs.infos.rb_node;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	while (n) {
638c2ecf20Sopenharmony_ci		node = rb_entry(n, struct bpf_prog_info_node, rb_node);
648c2ecf20Sopenharmony_ci		if (prog_id < node->info_linear->info.id)
658c2ecf20Sopenharmony_ci			n = n->rb_left;
668c2ecf20Sopenharmony_ci		else if (prog_id > node->info_linear->info.id)
678c2ecf20Sopenharmony_ci			n = n->rb_right;
688c2ecf20Sopenharmony_ci		else
698c2ecf20Sopenharmony_ci			goto out;
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci	node = NULL;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ciout:
748c2ecf20Sopenharmony_ci	up_read(&env->bpf_progs.lock);
758c2ecf20Sopenharmony_ci	return node;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cibool perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	bool ret;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	down_write(&env->bpf_progs.lock);
838c2ecf20Sopenharmony_ci	ret = __perf_env__insert_btf(env, btf_node);
848c2ecf20Sopenharmony_ci	up_write(&env->bpf_progs.lock);
858c2ecf20Sopenharmony_ci	return ret;
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cibool __perf_env__insert_btf(struct perf_env *env, struct btf_node *btf_node)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	struct rb_node *parent = NULL;
918c2ecf20Sopenharmony_ci	__u32 btf_id = btf_node->id;
928c2ecf20Sopenharmony_ci	struct btf_node *node;
938c2ecf20Sopenharmony_ci	struct rb_node **p;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	p = &env->bpf_progs.btfs.rb_node;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	while (*p != NULL) {
988c2ecf20Sopenharmony_ci		parent = *p;
998c2ecf20Sopenharmony_ci		node = rb_entry(parent, struct btf_node, rb_node);
1008c2ecf20Sopenharmony_ci		if (btf_id < node->id) {
1018c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
1028c2ecf20Sopenharmony_ci		} else if (btf_id > node->id) {
1038c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
1048c2ecf20Sopenharmony_ci		} else {
1058c2ecf20Sopenharmony_ci			pr_debug("duplicated btf %u\n", btf_id);
1068c2ecf20Sopenharmony_ci			return false;
1078c2ecf20Sopenharmony_ci		}
1088c2ecf20Sopenharmony_ci	}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	rb_link_node(&btf_node->rb_node, parent, p);
1118c2ecf20Sopenharmony_ci	rb_insert_color(&btf_node->rb_node, &env->bpf_progs.btfs);
1128c2ecf20Sopenharmony_ci	env->bpf_progs.btfs_cnt++;
1138c2ecf20Sopenharmony_ci	return true;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistruct btf_node *perf_env__find_btf(struct perf_env *env, __u32 btf_id)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	struct btf_node *res;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	down_read(&env->bpf_progs.lock);
1218c2ecf20Sopenharmony_ci	res = __perf_env__find_btf(env, btf_id);
1228c2ecf20Sopenharmony_ci	up_read(&env->bpf_progs.lock);
1238c2ecf20Sopenharmony_ci	return res;
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistruct btf_node *__perf_env__find_btf(struct perf_env *env, __u32 btf_id)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	struct btf_node *node = NULL;
1298c2ecf20Sopenharmony_ci	struct rb_node *n;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	n = env->bpf_progs.btfs.rb_node;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	while (n) {
1348c2ecf20Sopenharmony_ci		node = rb_entry(n, struct btf_node, rb_node);
1358c2ecf20Sopenharmony_ci		if (btf_id < node->id)
1368c2ecf20Sopenharmony_ci			n = n->rb_left;
1378c2ecf20Sopenharmony_ci		else if (btf_id > node->id)
1388c2ecf20Sopenharmony_ci			n = n->rb_right;
1398c2ecf20Sopenharmony_ci		else
1408c2ecf20Sopenharmony_ci			return node;
1418c2ecf20Sopenharmony_ci	}
1428c2ecf20Sopenharmony_ci	return NULL;
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci/* purge data in bpf_progs.infos tree */
1468c2ecf20Sopenharmony_cistatic void perf_env__purge_bpf(struct perf_env *env)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	struct rb_root *root;
1498c2ecf20Sopenharmony_ci	struct rb_node *next;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	down_write(&env->bpf_progs.lock);
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	root = &env->bpf_progs.infos;
1548c2ecf20Sopenharmony_ci	next = rb_first(root);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	while (next) {
1578c2ecf20Sopenharmony_ci		struct bpf_prog_info_node *node;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci		node = rb_entry(next, struct bpf_prog_info_node, rb_node);
1608c2ecf20Sopenharmony_ci		next = rb_next(&node->rb_node);
1618c2ecf20Sopenharmony_ci		rb_erase(&node->rb_node, root);
1628c2ecf20Sopenharmony_ci		free(node->info_linear);
1638c2ecf20Sopenharmony_ci		free(node);
1648c2ecf20Sopenharmony_ci	}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	env->bpf_progs.infos_cnt = 0;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	root = &env->bpf_progs.btfs;
1698c2ecf20Sopenharmony_ci	next = rb_first(root);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	while (next) {
1728c2ecf20Sopenharmony_ci		struct btf_node *node;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci		node = rb_entry(next, struct btf_node, rb_node);
1758c2ecf20Sopenharmony_ci		next = rb_next(&node->rb_node);
1768c2ecf20Sopenharmony_ci		rb_erase(&node->rb_node, root);
1778c2ecf20Sopenharmony_ci		free(node);
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	env->bpf_progs.btfs_cnt = 0;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	up_write(&env->bpf_progs.lock);
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_civoid perf_env__exit(struct perf_env *env)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	int i;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	perf_env__purge_bpf(env);
1908c2ecf20Sopenharmony_ci	perf_env__purge_cgroups(env);
1918c2ecf20Sopenharmony_ci	zfree(&env->hostname);
1928c2ecf20Sopenharmony_ci	zfree(&env->os_release);
1938c2ecf20Sopenharmony_ci	zfree(&env->version);
1948c2ecf20Sopenharmony_ci	zfree(&env->arch);
1958c2ecf20Sopenharmony_ci	zfree(&env->cpu_desc);
1968c2ecf20Sopenharmony_ci	zfree(&env->cpuid);
1978c2ecf20Sopenharmony_ci	zfree(&env->cmdline);
1988c2ecf20Sopenharmony_ci	zfree(&env->cmdline_argv);
1998c2ecf20Sopenharmony_ci	zfree(&env->sibling_dies);
2008c2ecf20Sopenharmony_ci	zfree(&env->sibling_cores);
2018c2ecf20Sopenharmony_ci	zfree(&env->sibling_threads);
2028c2ecf20Sopenharmony_ci	zfree(&env->pmu_mappings);
2038c2ecf20Sopenharmony_ci	zfree(&env->cpu);
2048c2ecf20Sopenharmony_ci	zfree(&env->cpu_pmu_caps);
2058c2ecf20Sopenharmony_ci	zfree(&env->numa_map);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	for (i = 0; i < env->nr_numa_nodes; i++)
2088c2ecf20Sopenharmony_ci		perf_cpu_map__put(env->numa_nodes[i].map);
2098c2ecf20Sopenharmony_ci	zfree(&env->numa_nodes);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	for (i = 0; i < env->caches_cnt; i++)
2128c2ecf20Sopenharmony_ci		cpu_cache_level__free(&env->caches[i]);
2138c2ecf20Sopenharmony_ci	zfree(&env->caches);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	for (i = 0; i < env->nr_memory_nodes; i++)
2168c2ecf20Sopenharmony_ci		zfree(&env->memory_nodes[i].set);
2178c2ecf20Sopenharmony_ci	zfree(&env->memory_nodes);
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_civoid perf_env__init(struct perf_env *env)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	env->bpf_progs.infos = RB_ROOT;
2238c2ecf20Sopenharmony_ci	env->bpf_progs.btfs = RB_ROOT;
2248c2ecf20Sopenharmony_ci	init_rwsem(&env->bpf_progs.lock);
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ciint perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[])
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	int i;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* do not include NULL termination */
2328c2ecf20Sopenharmony_ci	env->cmdline_argv = calloc(argc, sizeof(char *));
2338c2ecf20Sopenharmony_ci	if (env->cmdline_argv == NULL)
2348c2ecf20Sopenharmony_ci		goto out_enomem;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	/*
2378c2ecf20Sopenharmony_ci	 * Must copy argv contents because it gets moved around during option
2388c2ecf20Sopenharmony_ci	 * parsing:
2398c2ecf20Sopenharmony_ci	 */
2408c2ecf20Sopenharmony_ci	for (i = 0; i < argc ; i++) {
2418c2ecf20Sopenharmony_ci		env->cmdline_argv[i] = argv[i];
2428c2ecf20Sopenharmony_ci		if (env->cmdline_argv[i] == NULL)
2438c2ecf20Sopenharmony_ci			goto out_free;
2448c2ecf20Sopenharmony_ci	}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	env->nr_cmdline = argc;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	return 0;
2498c2ecf20Sopenharmony_ciout_free:
2508c2ecf20Sopenharmony_ci	zfree(&env->cmdline_argv);
2518c2ecf20Sopenharmony_ciout_enomem:
2528c2ecf20Sopenharmony_ci	return -ENOMEM;
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ciint perf_env__read_cpu_topology_map(struct perf_env *env)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	int cpu, nr_cpus;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	if (env->cpu != NULL)
2608c2ecf20Sopenharmony_ci		return 0;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	if (env->nr_cpus_avail == 0)
2638c2ecf20Sopenharmony_ci		env->nr_cpus_avail = cpu__max_present_cpu();
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	nr_cpus = env->nr_cpus_avail;
2668c2ecf20Sopenharmony_ci	if (nr_cpus == -1)
2678c2ecf20Sopenharmony_ci		return -EINVAL;
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	env->cpu = calloc(nr_cpus, sizeof(env->cpu[0]));
2708c2ecf20Sopenharmony_ci	if (env->cpu == NULL)
2718c2ecf20Sopenharmony_ci		return -ENOMEM;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	for (cpu = 0; cpu < nr_cpus; ++cpu) {
2748c2ecf20Sopenharmony_ci		env->cpu[cpu].core_id	= cpu_map__get_core_id(cpu);
2758c2ecf20Sopenharmony_ci		env->cpu[cpu].socket_id	= cpu_map__get_socket_id(cpu);
2768c2ecf20Sopenharmony_ci		env->cpu[cpu].die_id	= cpu_map__get_die_id(cpu);
2778c2ecf20Sopenharmony_ci	}
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	env->nr_cpus_avail = nr_cpus;
2808c2ecf20Sopenharmony_ci	return 0;
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ciint perf_env__read_cpuid(struct perf_env *env)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	char cpuid[128];
2868c2ecf20Sopenharmony_ci	int err = get_cpuid(cpuid, sizeof(cpuid));
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	if (err)
2898c2ecf20Sopenharmony_ci		return err;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	free(env->cpuid);
2928c2ecf20Sopenharmony_ci	env->cpuid = strdup(cpuid);
2938c2ecf20Sopenharmony_ci	if (env->cpuid == NULL)
2948c2ecf20Sopenharmony_ci		return ENOMEM;
2958c2ecf20Sopenharmony_ci	return 0;
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic int perf_env__read_arch(struct perf_env *env)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	struct utsname uts;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (env->arch)
3038c2ecf20Sopenharmony_ci		return 0;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	if (!uname(&uts))
3068c2ecf20Sopenharmony_ci		env->arch = strdup(uts.machine);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	return env->arch ? 0 : -ENOMEM;
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistatic int perf_env__read_nr_cpus_avail(struct perf_env *env)
3128c2ecf20Sopenharmony_ci{
3138c2ecf20Sopenharmony_ci	if (env->nr_cpus_avail == 0)
3148c2ecf20Sopenharmony_ci		env->nr_cpus_avail = cpu__max_present_cpu();
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci	return env->nr_cpus_avail ? 0 : -ENOENT;
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ciconst char *perf_env__raw_arch(struct perf_env *env)
3208c2ecf20Sopenharmony_ci{
3218c2ecf20Sopenharmony_ci	return env && !perf_env__read_arch(env) ? env->arch : "unknown";
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ciint perf_env__nr_cpus_avail(struct perf_env *env)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	return env && !perf_env__read_nr_cpus_avail(env) ? env->nr_cpus_avail : 0;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_civoid cpu_cache_level__free(struct cpu_cache_level *cache)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci	zfree(&cache->type);
3328c2ecf20Sopenharmony_ci	zfree(&cache->map);
3338c2ecf20Sopenharmony_ci	zfree(&cache->size);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci/*
3378c2ecf20Sopenharmony_ci * Return architecture name in a normalized form.
3388c2ecf20Sopenharmony_ci * The conversion logic comes from the Makefile.
3398c2ecf20Sopenharmony_ci */
3408c2ecf20Sopenharmony_cistatic const char *normalize_arch(char *arch)
3418c2ecf20Sopenharmony_ci{
3428c2ecf20Sopenharmony_ci	if (!strcmp(arch, "x86_64"))
3438c2ecf20Sopenharmony_ci		return "x86";
3448c2ecf20Sopenharmony_ci	if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6')
3458c2ecf20Sopenharmony_ci		return "x86";
3468c2ecf20Sopenharmony_ci	if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5))
3478c2ecf20Sopenharmony_ci		return "sparc";
3488c2ecf20Sopenharmony_ci	if (!strncmp(arch, "aarch64", 7) || !strncmp(arch, "arm64", 5))
3498c2ecf20Sopenharmony_ci		return "arm64";
3508c2ecf20Sopenharmony_ci	if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110"))
3518c2ecf20Sopenharmony_ci		return "arm";
3528c2ecf20Sopenharmony_ci	if (!strncmp(arch, "s390", 4))
3538c2ecf20Sopenharmony_ci		return "s390";
3548c2ecf20Sopenharmony_ci	if (!strncmp(arch, "parisc", 6))
3558c2ecf20Sopenharmony_ci		return "parisc";
3568c2ecf20Sopenharmony_ci	if (!strncmp(arch, "powerpc", 7) || !strncmp(arch, "ppc", 3))
3578c2ecf20Sopenharmony_ci		return "powerpc";
3588c2ecf20Sopenharmony_ci	if (!strncmp(arch, "mips", 4))
3598c2ecf20Sopenharmony_ci		return "mips";
3608c2ecf20Sopenharmony_ci	if (!strncmp(arch, "sh", 2) && isdigit(arch[2]))
3618c2ecf20Sopenharmony_ci		return "sh";
3628c2ecf20Sopenharmony_ci	if (!strncmp(arch, "loongarch", 9))
3638c2ecf20Sopenharmony_ci		return "loongarch";
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	return arch;
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ciconst char *perf_env__arch(struct perf_env *env)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	char *arch_name;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	if (!env || !env->arch) { /* Assume local operation */
3738c2ecf20Sopenharmony_ci		static struct utsname uts = { .machine[0] = '\0', };
3748c2ecf20Sopenharmony_ci		if (uts.machine[0] == '\0' && uname(&uts) < 0)
3758c2ecf20Sopenharmony_ci			return NULL;
3768c2ecf20Sopenharmony_ci		arch_name = uts.machine;
3778c2ecf20Sopenharmony_ci	} else
3788c2ecf20Sopenharmony_ci		arch_name = env->arch;
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	return normalize_arch(arch_name);
3818c2ecf20Sopenharmony_ci}
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ciint perf_env__numa_node(struct perf_env *env, int cpu)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	if (!env->nr_numa_map) {
3878c2ecf20Sopenharmony_ci		struct numa_node *nn;
3888c2ecf20Sopenharmony_ci		int i, nr = 0;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci		for (i = 0; i < env->nr_numa_nodes; i++) {
3918c2ecf20Sopenharmony_ci			nn = &env->numa_nodes[i];
3928c2ecf20Sopenharmony_ci			nr = max(nr, perf_cpu_map__max(nn->map));
3938c2ecf20Sopenharmony_ci		}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci		nr++;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci		/*
3988c2ecf20Sopenharmony_ci		 * We initialize the numa_map array to prepare
3998c2ecf20Sopenharmony_ci		 * it for missing cpus, which return node -1
4008c2ecf20Sopenharmony_ci		 */
4018c2ecf20Sopenharmony_ci		env->numa_map = malloc(nr * sizeof(int));
4028c2ecf20Sopenharmony_ci		if (!env->numa_map)
4038c2ecf20Sopenharmony_ci			return -1;
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci		for (i = 0; i < nr; i++)
4068c2ecf20Sopenharmony_ci			env->numa_map[i] = -1;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci		env->nr_numa_map = nr;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci		for (i = 0; i < env->nr_numa_nodes; i++) {
4118c2ecf20Sopenharmony_ci			int tmp, j;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci			nn = &env->numa_nodes[i];
4148c2ecf20Sopenharmony_ci			perf_cpu_map__for_each_cpu(j, tmp, nn->map)
4158c2ecf20Sopenharmony_ci				env->numa_map[j] = i;
4168c2ecf20Sopenharmony_ci		}
4178c2ecf20Sopenharmony_ci	}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	return cpu >= 0 && cpu < env->nr_numa_map ? env->numa_map[cpu] : -1;
4208c2ecf20Sopenharmony_ci}
421