1 // SPDX-License-Identifier: GPL-2.0 2 #include "cpumap.h" 3 #include "env.h" 4 #include "sane_ctype.h" 5 #include "util.h" 6 #include <errno.h> 7 #include <sys/utsname.h> 8 9 struct perf_env perf_env; 10 11 void perf_env__exit(struct perf_env *env) 12 { 13 int i; 14 15 zfree(&env->hostname); 16 zfree(&env->os_release); 17 zfree(&env->version); 18 zfree(&env->arch); 19 zfree(&env->cpu_desc); 20 zfree(&env->cpuid); 21 zfree(&env->cmdline); 22 zfree(&env->cmdline_argv); 23 zfree(&env->sibling_cores); 24 zfree(&env->sibling_threads); 25 zfree(&env->pmu_mappings); 26 zfree(&env->cpu); 27 28 for (i = 0; i < env->nr_numa_nodes; i++) 29 cpu_map__put(env->numa_nodes[i].map); 30 zfree(&env->numa_nodes); 31 32 for (i = 0; i < env->caches_cnt; i++) 33 cpu_cache_level__free(&env->caches[i]); 34 zfree(&env->caches); 35 } 36 37 int perf_env__set_cmdline(struct perf_env *env, int argc, const char *argv[]) 38 { 39 int i; 40 41 /* do not include NULL termination */ 42 env->cmdline_argv = calloc(argc, sizeof(char *)); 43 if (env->cmdline_argv == NULL) 44 goto out_enomem; 45 46 /* 47 * Must copy argv contents because it gets moved around during option 48 * parsing: 49 */ 50 for (i = 0; i < argc ; i++) { 51 env->cmdline_argv[i] = argv[i]; 52 if (env->cmdline_argv[i] == NULL) 53 goto out_free; 54 } 55 56 env->nr_cmdline = argc; 57 58 return 0; 59 out_free: 60 zfree(&env->cmdline_argv); 61 out_enomem: 62 return -ENOMEM; 63 } 64 65 int perf_env__read_cpu_topology_map(struct perf_env *env) 66 { 67 int cpu, nr_cpus; 68 69 if (env->cpu != NULL) 70 return 0; 71 72 if (env->nr_cpus_avail == 0) 73 env->nr_cpus_avail = cpu__max_present_cpu(); 74 75 nr_cpus = env->nr_cpus_avail; 76 if (nr_cpus == -1) 77 return -EINVAL; 78 79 env->cpu = calloc(nr_cpus, sizeof(env->cpu[0])); 80 if (env->cpu == NULL) 81 return -ENOMEM; 82 83 for (cpu = 0; cpu < nr_cpus; ++cpu) { 84 env->cpu[cpu].core_id = cpu_map__get_core_id(cpu); 85 env->cpu[cpu].socket_id = cpu_map__get_socket_id(cpu); 86 } 87 88 env->nr_cpus_avail = nr_cpus; 89 return 0; 90 } 91 92 void cpu_cache_level__free(struct cpu_cache_level *cache) 93 { 94 free(cache->type); 95 free(cache->map); 96 free(cache->size); 97 } 98 99 /* 100 * Return architecture name in a normalized form. 101 * The conversion logic comes from the Makefile. 102 */ 103 static const char *normalize_arch(char *arch) 104 { 105 if (!strcmp(arch, "x86_64")) 106 return "x86"; 107 if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6') 108 return "x86"; 109 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5)) 110 return "sparc"; 111 if (!strcmp(arch, "aarch64") || !strcmp(arch, "arm64")) 112 return "arm64"; 113 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110")) 114 return "arm"; 115 if (!strncmp(arch, "s390", 4)) 116 return "s390"; 117 if (!strncmp(arch, "parisc", 6)) 118 return "parisc"; 119 if (!strncmp(arch, "powerpc", 7) || !strncmp(arch, "ppc", 3)) 120 return "powerpc"; 121 if (!strncmp(arch, "mips", 4)) 122 return "mips"; 123 if (!strncmp(arch, "sh", 2) && isdigit(arch[2])) 124 return "sh"; 125 126 return arch; 127 } 128 129 const char *perf_env__arch(struct perf_env *env) 130 { 131 struct utsname uts; 132 char *arch_name; 133 134 if (!env) { /* Assume local operation */ 135 if (uname(&uts) < 0) 136 return NULL; 137 arch_name = uts.machine; 138 } else 139 arch_name = env->arch; 140 141 return normalize_arch(arch_name); 142 } 143