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