1#include <linux/list.h> 2#include <sys/types.h> 3#include <unistd.h> 4#include <stdio.h> 5#include <stdbool.h> 6#include <stdarg.h> 7#include <dirent.h> 8#include <api/fs/fs.h> 9#include <locale.h> 10#include "util.h" 11#include "pmu.h" 12#include "parse-events.h" 13#include "cpumap.h" 14 15struct perf_pmu_format { 16 char *name; 17 int value; 18 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); 19 struct list_head list; 20}; 21 22#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" 23 24int perf_pmu_parse(struct list_head *list, char *name); 25extern FILE *perf_pmu_in; 26 27static LIST_HEAD(pmus); 28 29/* 30 * Parse & process all the sysfs attributes located under 31 * the directory specified in 'dir' parameter. 32 */ 33int perf_pmu__format_parse(char *dir, struct list_head *head) 34{ 35 struct dirent *evt_ent; 36 DIR *format_dir; 37 int ret = 0; 38 39 format_dir = opendir(dir); 40 if (!format_dir) 41 return -EINVAL; 42 43 while (!ret && (evt_ent = readdir(format_dir))) { 44 char path[PATH_MAX]; 45 char *name = evt_ent->d_name; 46 FILE *file; 47 48 if (!strcmp(name, ".") || !strcmp(name, "..")) 49 continue; 50 51 snprintf(path, PATH_MAX, "%s/%s", dir, name); 52 53 ret = -EINVAL; 54 file = fopen(path, "r"); 55 if (!file) 56 break; 57 58 perf_pmu_in = file; 59 ret = perf_pmu_parse(head, name); 60 fclose(file); 61 } 62 63 closedir(format_dir); 64 return ret; 65} 66 67/* 68 * Reading/parsing the default pmu format definition, which should be 69 * located at: 70 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. 71 */ 72static int pmu_format(const char *name, struct list_head *format) 73{ 74 struct stat st; 75 char path[PATH_MAX]; 76 const char *sysfs = sysfs__mountpoint(); 77 78 if (!sysfs) 79 return -1; 80 81 snprintf(path, PATH_MAX, 82 "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name); 83 84 if (stat(path, &st) < 0) 85 return 0; /* no error if format does not exist */ 86 87 if (perf_pmu__format_parse(path, format)) 88 return -1; 89 90 return 0; 91} 92 93static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name) 94{ 95 struct stat st; 96 ssize_t sret; 97 char scale[128]; 98 int fd, ret = -1; 99 char path[PATH_MAX]; 100 const char *lc; 101 102 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name); 103 104 fd = open(path, O_RDONLY); 105 if (fd == -1) 106 return -1; 107 108 if (fstat(fd, &st) < 0) 109 goto error; 110 111 sret = read(fd, scale, sizeof(scale)-1); 112 if (sret < 0) 113 goto error; 114 115 scale[sret] = '\0'; 116 /* 117 * save current locale 118 */ 119 lc = setlocale(LC_NUMERIC, NULL); 120 121 /* 122 * force to C locale to ensure kernel 123 * scale string is converted correctly. 124 * kernel uses default C locale. 125 */ 126 setlocale(LC_NUMERIC, "C"); 127 128 alias->scale = strtod(scale, NULL); 129 130 /* restore locale */ 131 setlocale(LC_NUMERIC, lc); 132 133 ret = 0; 134error: 135 close(fd); 136 return ret; 137} 138 139static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name) 140{ 141 char path[PATH_MAX]; 142 ssize_t sret; 143 int fd; 144 145 snprintf(path, PATH_MAX, "%s/%s.unit", dir, name); 146 147 fd = open(path, O_RDONLY); 148 if (fd == -1) 149 return -1; 150 151 sret = read(fd, alias->unit, UNIT_MAX_LEN); 152 if (sret < 0) 153 goto error; 154 155 close(fd); 156 157 alias->unit[sret] = '\0'; 158 159 return 0; 160error: 161 close(fd); 162 alias->unit[0] = '\0'; 163 return -1; 164} 165 166static int 167perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name) 168{ 169 char path[PATH_MAX]; 170 int fd; 171 172 snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name); 173 174 fd = open(path, O_RDONLY); 175 if (fd == -1) 176 return -1; 177 178 close(fd); 179 180 alias->per_pkg = true; 181 return 0; 182} 183 184static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, 185 char *dir, char *name) 186{ 187 char path[PATH_MAX]; 188 int fd; 189 190 snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name); 191 192 fd = open(path, O_RDONLY); 193 if (fd == -1) 194 return -1; 195 196 alias->snapshot = true; 197 close(fd); 198 return 0; 199} 200 201static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file) 202{ 203 struct perf_pmu_alias *alias; 204 char buf[256]; 205 int ret; 206 207 ret = fread(buf, 1, sizeof(buf), file); 208 if (ret == 0) 209 return -EINVAL; 210 buf[ret] = 0; 211 212 alias = malloc(sizeof(*alias)); 213 if (!alias) 214 return -ENOMEM; 215 216 INIT_LIST_HEAD(&alias->terms); 217 alias->scale = 1.0; 218 alias->unit[0] = '\0'; 219 alias->per_pkg = false; 220 221 ret = parse_events_terms(&alias->terms, buf); 222 if (ret) { 223 free(alias); 224 return ret; 225 } 226 227 alias->name = strdup(name); 228 /* 229 * load unit name and scale if available 230 */ 231 perf_pmu__parse_unit(alias, dir, name); 232 perf_pmu__parse_scale(alias, dir, name); 233 perf_pmu__parse_per_pkg(alias, dir, name); 234 perf_pmu__parse_snapshot(alias, dir, name); 235 236 list_add_tail(&alias->list, list); 237 238 return 0; 239} 240 241static inline bool pmu_alias_info_file(char *name) 242{ 243 size_t len; 244 245 len = strlen(name); 246 if (len > 5 && !strcmp(name + len - 5, ".unit")) 247 return true; 248 if (len > 6 && !strcmp(name + len - 6, ".scale")) 249 return true; 250 if (len > 8 && !strcmp(name + len - 8, ".per-pkg")) 251 return true; 252 if (len > 9 && !strcmp(name + len - 9, ".snapshot")) 253 return true; 254 255 return false; 256} 257 258/* 259 * Process all the sysfs attributes located under the directory 260 * specified in 'dir' parameter. 261 */ 262static int pmu_aliases_parse(char *dir, struct list_head *head) 263{ 264 struct dirent *evt_ent; 265 DIR *event_dir; 266 267 event_dir = opendir(dir); 268 if (!event_dir) 269 return -EINVAL; 270 271 while ((evt_ent = readdir(event_dir))) { 272 char path[PATH_MAX]; 273 char *name = evt_ent->d_name; 274 FILE *file; 275 276 if (!strcmp(name, ".") || !strcmp(name, "..")) 277 continue; 278 279 /* 280 * skip info files parsed in perf_pmu__new_alias() 281 */ 282 if (pmu_alias_info_file(name)) 283 continue; 284 285 snprintf(path, PATH_MAX, "%s/%s", dir, name); 286 287 file = fopen(path, "r"); 288 if (!file) { 289 pr_debug("Cannot open %s\n", path); 290 continue; 291 } 292 293 if (perf_pmu__new_alias(head, dir, name, file) < 0) 294 pr_debug("Cannot set up %s\n", name); 295 fclose(file); 296 } 297 298 closedir(event_dir); 299 return 0; 300} 301 302/* 303 * Reading the pmu event aliases definition, which should be located at: 304 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 305 */ 306static int pmu_aliases(const char *name, struct list_head *head) 307{ 308 struct stat st; 309 char path[PATH_MAX]; 310 const char *sysfs = sysfs__mountpoint(); 311 312 if (!sysfs) 313 return -1; 314 315 snprintf(path, PATH_MAX, 316 "%s/bus/event_source/devices/%s/events", sysfs, name); 317 318 if (stat(path, &st) < 0) 319 return 0; /* no error if 'events' does not exist */ 320 321 if (pmu_aliases_parse(path, head)) 322 return -1; 323 324 return 0; 325} 326 327static int pmu_alias_terms(struct perf_pmu_alias *alias, 328 struct list_head *terms) 329{ 330 struct parse_events_term *term, *cloned; 331 LIST_HEAD(list); 332 int ret; 333 334 list_for_each_entry(term, &alias->terms, list) { 335 ret = parse_events_term__clone(&cloned, term); 336 if (ret) { 337 parse_events__free_terms(&list); 338 return ret; 339 } 340 list_add_tail(&cloned->list, &list); 341 } 342 list_splice(&list, terms); 343 return 0; 344} 345 346/* 347 * Reading/parsing the default pmu type value, which should be 348 * located at: 349 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute. 350 */ 351static int pmu_type(const char *name, __u32 *type) 352{ 353 struct stat st; 354 char path[PATH_MAX]; 355 FILE *file; 356 int ret = 0; 357 const char *sysfs = sysfs__mountpoint(); 358 359 if (!sysfs) 360 return -1; 361 362 snprintf(path, PATH_MAX, 363 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name); 364 365 if (stat(path, &st) < 0) 366 return -1; 367 368 file = fopen(path, "r"); 369 if (!file) 370 return -EINVAL; 371 372 if (1 != fscanf(file, "%u", type)) 373 ret = -1; 374 375 fclose(file); 376 return ret; 377} 378 379/* Add all pmus in sysfs to pmu list: */ 380static void pmu_read_sysfs(void) 381{ 382 char path[PATH_MAX]; 383 DIR *dir; 384 struct dirent *dent; 385 const char *sysfs = sysfs__mountpoint(); 386 387 if (!sysfs) 388 return; 389 390 snprintf(path, PATH_MAX, 391 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs); 392 393 dir = opendir(path); 394 if (!dir) 395 return; 396 397 while ((dent = readdir(dir))) { 398 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) 399 continue; 400 /* add to static LIST_HEAD(pmus): */ 401 perf_pmu__find(dent->d_name); 402 } 403 404 closedir(dir); 405} 406 407static struct cpu_map *pmu_cpumask(const char *name) 408{ 409 struct stat st; 410 char path[PATH_MAX]; 411 FILE *file; 412 struct cpu_map *cpus; 413 const char *sysfs = sysfs__mountpoint(); 414 415 if (!sysfs) 416 return NULL; 417 418 snprintf(path, PATH_MAX, 419 "%s/bus/event_source/devices/%s/cpumask", sysfs, name); 420 421 if (stat(path, &st) < 0) 422 return NULL; 423 424 file = fopen(path, "r"); 425 if (!file) 426 return NULL; 427 428 cpus = cpu_map__read(file); 429 fclose(file); 430 return cpus; 431} 432 433struct perf_event_attr *__attribute__((weak)) 434perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) 435{ 436 return NULL; 437} 438 439static struct perf_pmu *pmu_lookup(const char *name) 440{ 441 struct perf_pmu *pmu; 442 LIST_HEAD(format); 443 LIST_HEAD(aliases); 444 __u32 type; 445 446 /* 447 * The pmu data we store & need consists of the pmu 448 * type value and format definitions. Load both right 449 * now. 450 */ 451 if (pmu_format(name, &format)) 452 return NULL; 453 454 if (pmu_aliases(name, &aliases)) 455 return NULL; 456 457 if (pmu_type(name, &type)) 458 return NULL; 459 460 pmu = zalloc(sizeof(*pmu)); 461 if (!pmu) 462 return NULL; 463 464 pmu->cpus = pmu_cpumask(name); 465 466 INIT_LIST_HEAD(&pmu->format); 467 INIT_LIST_HEAD(&pmu->aliases); 468 list_splice(&format, &pmu->format); 469 list_splice(&aliases, &pmu->aliases); 470 pmu->name = strdup(name); 471 pmu->type = type; 472 list_add_tail(&pmu->list, &pmus); 473 474 pmu->default_config = perf_pmu__get_default_config(pmu); 475 476 return pmu; 477} 478 479static struct perf_pmu *pmu_find(const char *name) 480{ 481 struct perf_pmu *pmu; 482 483 list_for_each_entry(pmu, &pmus, list) 484 if (!strcmp(pmu->name, name)) 485 return pmu; 486 487 return NULL; 488} 489 490struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) 491{ 492 /* 493 * pmu iterator: If pmu is NULL, we start at the begin, 494 * otherwise return the next pmu. Returns NULL on end. 495 */ 496 if (!pmu) { 497 pmu_read_sysfs(); 498 pmu = list_prepare_entry(pmu, &pmus, list); 499 } 500 list_for_each_entry_continue(pmu, &pmus, list) 501 return pmu; 502 return NULL; 503} 504 505struct perf_pmu *perf_pmu__find(const char *name) 506{ 507 struct perf_pmu *pmu; 508 509 /* 510 * Once PMU is loaded it stays in the list, 511 * so we keep us from multiple reading/parsing 512 * the pmu format definitions. 513 */ 514 pmu = pmu_find(name); 515 if (pmu) 516 return pmu; 517 518 return pmu_lookup(name); 519} 520 521static struct perf_pmu_format * 522pmu_find_format(struct list_head *formats, char *name) 523{ 524 struct perf_pmu_format *format; 525 526 list_for_each_entry(format, formats, list) 527 if (!strcmp(format->name, name)) 528 return format; 529 530 return NULL; 531} 532 533/* 534 * Sets value based on the format definition (format parameter) 535 * and unformated value (value parameter). 536 */ 537static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, 538 bool zero) 539{ 540 unsigned long fbit, vbit; 541 542 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 543 544 if (!test_bit(fbit, format)) 545 continue; 546 547 if (value & (1llu << vbit++)) 548 *v |= (1llu << fbit); 549 else if (zero) 550 *v &= ~(1llu << fbit); 551 } 552} 553 554/* 555 * Term is a string term, and might be a param-term. Try to look up it's value 556 * in the remaining terms. 557 * - We have a term like "base-or-format-term=param-term", 558 * - We need to find the value supplied for "param-term" (with param-term named 559 * in a config string) later on in the term list. 560 */ 561static int pmu_resolve_param_term(struct parse_events_term *term, 562 struct list_head *head_terms, 563 __u64 *value) 564{ 565 struct parse_events_term *t; 566 567 list_for_each_entry(t, head_terms, list) { 568 if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 569 if (!strcmp(t->config, term->config)) { 570 t->used = true; 571 *value = t->val.num; 572 return 0; 573 } 574 } 575 } 576 577 if (verbose) 578 printf("Required parameter '%s' not specified\n", term->config); 579 580 return -1; 581} 582 583/* 584 * Setup one of config[12] attr members based on the 585 * user input data - term parameter. 586 */ 587static int pmu_config_term(struct list_head *formats, 588 struct perf_event_attr *attr, 589 struct parse_events_term *term, 590 struct list_head *head_terms, 591 bool zero) 592{ 593 struct perf_pmu_format *format; 594 __u64 *vp; 595 __u64 val; 596 597 /* 598 * If this is a parameter we've already used for parameterized-eval, 599 * skip it in normal eval. 600 */ 601 if (term->used) 602 return 0; 603 604 /* 605 * Hardcoded terms should be already in, so nothing 606 * to be done for them. 607 */ 608 if (parse_events__is_hardcoded_term(term)) 609 return 0; 610 611 format = pmu_find_format(formats, term->config); 612 if (!format) { 613 if (verbose) 614 printf("Invalid event/parameter '%s'\n", term->config); 615 return -EINVAL; 616 } 617 618 switch (format->value) { 619 case PERF_PMU_FORMAT_VALUE_CONFIG: 620 vp = &attr->config; 621 break; 622 case PERF_PMU_FORMAT_VALUE_CONFIG1: 623 vp = &attr->config1; 624 break; 625 case PERF_PMU_FORMAT_VALUE_CONFIG2: 626 vp = &attr->config2; 627 break; 628 default: 629 return -EINVAL; 630 } 631 632 /* 633 * Either directly use a numeric term, or try to translate string terms 634 * using event parameters. 635 */ 636 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 637 val = term->val.num; 638 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 639 if (strcmp(term->val.str, "?")) { 640 if (verbose) 641 pr_info("Invalid sysfs entry %s=%s\n", 642 term->config, term->val.str); 643 return -EINVAL; 644 } 645 646 if (pmu_resolve_param_term(term, head_terms, &val)) 647 return -EINVAL; 648 } else 649 return -EINVAL; 650 651 pmu_format_value(format->bits, val, vp, zero); 652 return 0; 653} 654 655int perf_pmu__config_terms(struct list_head *formats, 656 struct perf_event_attr *attr, 657 struct list_head *head_terms, 658 bool zero) 659{ 660 struct parse_events_term *term; 661 662 list_for_each_entry(term, head_terms, list) { 663 if (pmu_config_term(formats, attr, term, head_terms, zero)) 664 return -EINVAL; 665 } 666 667 return 0; 668} 669 670/* 671 * Configures event's 'attr' parameter based on the: 672 * 1) users input - specified in terms parameter 673 * 2) pmu format definitions - specified by pmu parameter 674 */ 675int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 676 struct list_head *head_terms) 677{ 678 bool zero = !!pmu->default_config; 679 680 attr->type = pmu->type; 681 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero); 682} 683 684static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 685 struct parse_events_term *term) 686{ 687 struct perf_pmu_alias *alias; 688 char *name; 689 690 if (parse_events__is_hardcoded_term(term)) 691 return NULL; 692 693 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 694 if (term->val.num != 1) 695 return NULL; 696 if (pmu_find_format(&pmu->format, term->config)) 697 return NULL; 698 name = term->config; 699 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 700 if (strcasecmp(term->config, "event")) 701 return NULL; 702 name = term->val.str; 703 } else { 704 return NULL; 705 } 706 707 list_for_each_entry(alias, &pmu->aliases, list) { 708 if (!strcasecmp(alias->name, name)) 709 return alias; 710 } 711 return NULL; 712} 713 714 715static int check_info_data(struct perf_pmu_alias *alias, 716 struct perf_pmu_info *info) 717{ 718 /* 719 * Only one term in event definition can 720 * define unit, scale and snapshot, fail 721 * if there's more than one. 722 */ 723 if ((info->unit && alias->unit) || 724 (info->scale && alias->scale) || 725 (info->snapshot && alias->snapshot)) 726 return -EINVAL; 727 728 if (alias->unit) 729 info->unit = alias->unit; 730 731 if (alias->scale) 732 info->scale = alias->scale; 733 734 if (alias->snapshot) 735 info->snapshot = alias->snapshot; 736 737 return 0; 738} 739 740/* 741 * Find alias in the terms list and replace it with the terms 742 * defined for the alias 743 */ 744int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 745 struct perf_pmu_info *info) 746{ 747 struct parse_events_term *term, *h; 748 struct perf_pmu_alias *alias; 749 int ret; 750 751 info->per_pkg = false; 752 753 /* 754 * Mark unit and scale as not set 755 * (different from default values, see below) 756 */ 757 info->unit = NULL; 758 info->scale = 0.0; 759 info->snapshot = false; 760 761 list_for_each_entry_safe(term, h, head_terms, list) { 762 alias = pmu_find_alias(pmu, term); 763 if (!alias) 764 continue; 765 ret = pmu_alias_terms(alias, &term->list); 766 if (ret) 767 return ret; 768 769 ret = check_info_data(alias, info); 770 if (ret) 771 return ret; 772 773 if (alias->per_pkg) 774 info->per_pkg = true; 775 776 list_del(&term->list); 777 free(term); 778 } 779 780 /* 781 * if no unit or scale foundin aliases, then 782 * set defaults as for evsel 783 * unit cannot left to NULL 784 */ 785 if (info->unit == NULL) 786 info->unit = ""; 787 788 if (info->scale == 0.0) 789 info->scale = 1.0; 790 791 return 0; 792} 793 794int perf_pmu__new_format(struct list_head *list, char *name, 795 int config, unsigned long *bits) 796{ 797 struct perf_pmu_format *format; 798 799 format = zalloc(sizeof(*format)); 800 if (!format) 801 return -ENOMEM; 802 803 format->name = strdup(name); 804 format->value = config; 805 memcpy(format->bits, bits, sizeof(format->bits)); 806 807 list_add_tail(&format->list, list); 808 return 0; 809} 810 811void perf_pmu__set_format(unsigned long *bits, long from, long to) 812{ 813 long b; 814 815 if (!to) 816 to = from; 817 818 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS)); 819 for (b = from; b <= to; b++) 820 set_bit(b, bits); 821} 822 823static int sub_non_neg(int a, int b) 824{ 825 if (b > a) 826 return 0; 827 return a - b; 828} 829 830static char *format_alias(char *buf, int len, struct perf_pmu *pmu, 831 struct perf_pmu_alias *alias) 832{ 833 struct parse_events_term *term; 834 int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); 835 836 list_for_each_entry(term, &alias->terms, list) { 837 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 838 used += snprintf(buf + used, sub_non_neg(len, used), 839 ",%s=%s", term->config, 840 term->val.str); 841 } 842 843 if (sub_non_neg(len, used) > 0) { 844 buf[used] = '/'; 845 used++; 846 } 847 if (sub_non_neg(len, used) > 0) { 848 buf[used] = '\0'; 849 used++; 850 } else 851 buf[len - 1] = '\0'; 852 853 return buf; 854} 855 856static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu, 857 struct perf_pmu_alias *alias) 858{ 859 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name); 860 return buf; 861} 862 863static int cmp_string(const void *a, const void *b) 864{ 865 const char * const *as = a; 866 const char * const *bs = b; 867 return strcmp(*as, *bs); 868} 869 870void print_pmu_events(const char *event_glob, bool name_only) 871{ 872 struct perf_pmu *pmu; 873 struct perf_pmu_alias *alias; 874 char buf[1024]; 875 int printed = 0; 876 int len, j; 877 char **aliases; 878 879 pmu = NULL; 880 len = 0; 881 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 882 list_for_each_entry(alias, &pmu->aliases, list) 883 len++; 884 if (pmu->selectable) 885 len++; 886 } 887 aliases = zalloc(sizeof(char *) * len); 888 if (!aliases) 889 goto out_enomem; 890 pmu = NULL; 891 j = 0; 892 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 893 list_for_each_entry(alias, &pmu->aliases, list) { 894 char *name = format_alias(buf, sizeof(buf), pmu, alias); 895 bool is_cpu = !strcmp(pmu->name, "cpu"); 896 897 if (event_glob != NULL && 898 !(strglobmatch(name, event_glob) || 899 (!is_cpu && strglobmatch(alias->name, 900 event_glob)))) 901 continue; 902 903 if (is_cpu && !name_only) 904 name = format_alias_or(buf, sizeof(buf), pmu, alias); 905 906 aliases[j] = strdup(name); 907 if (aliases[j] == NULL) 908 goto out_enomem; 909 j++; 910 } 911 if (pmu->selectable) { 912 char *s; 913 if (asprintf(&s, "%s//", pmu->name) < 0) 914 goto out_enomem; 915 aliases[j] = s; 916 j++; 917 } 918 } 919 len = j; 920 qsort(aliases, len, sizeof(char *), cmp_string); 921 for (j = 0; j < len; j++) { 922 if (name_only) { 923 printf("%s ", aliases[j]); 924 continue; 925 } 926 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 927 printed++; 928 } 929 if (printed) 930 printf("\n"); 931out_free: 932 for (j = 0; j < len; j++) 933 zfree(&aliases[j]); 934 zfree(&aliases); 935 return; 936 937out_enomem: 938 printf("FATAL: not enough memory to print PMU events\n"); 939 if (aliases) 940 goto out_free; 941} 942 943bool pmu_have_event(const char *pname, const char *name) 944{ 945 struct perf_pmu *pmu; 946 struct perf_pmu_alias *alias; 947 948 pmu = NULL; 949 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 950 if (strcmp(pname, pmu->name)) 951 continue; 952 list_for_each_entry(alias, &pmu->aliases, list) 953 if (!strcmp(alias->name, name)) 954 return true; 955 } 956 return false; 957} 958 959static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) 960{ 961 struct stat st; 962 char path[PATH_MAX]; 963 const char *sysfs; 964 965 sysfs = sysfs__mountpoint(); 966 if (!sysfs) 967 return NULL; 968 969 snprintf(path, PATH_MAX, 970 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name); 971 972 if (stat(path, &st) < 0) 973 return NULL; 974 975 return fopen(path, "r"); 976} 977 978int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 979 ...) 980{ 981 va_list args; 982 FILE *file; 983 int ret = EOF; 984 985 va_start(args, fmt); 986 file = perf_pmu__open_file(pmu, name); 987 if (file) { 988 ret = vfscanf(file, fmt, args); 989 fclose(file); 990 } 991 va_end(args); 992 return ret; 993} 994