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 15 struct 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 24 int perf_pmu_parse(struct list_head *list, char *name); 25 extern FILE *perf_pmu_in; 26 27 static LIST_HEAD(pmus); 28 29 /* 30 * Parse & process all the sysfs attributes located under 31 * the directory specified in 'dir' parameter. 32 */ 33 int 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 */ 72 static 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 93 static 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; 134 error: 135 close(fd); 136 return ret; 137 } 138 139 static 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; 160 error: 161 close(fd); 162 alias->unit[0] = '\0'; 163 return -1; 164 } 165 166 static int 167 perf_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 184 static 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 201 static 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 241 static 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 */ 262 static int pmu_aliases_parse(char *dir, struct list_head *head) 263 { 264 struct dirent *evt_ent; 265 DIR *event_dir; 266 int ret = 0; 267 268 event_dir = opendir(dir); 269 if (!event_dir) 270 return -EINVAL; 271 272 while (!ret && (evt_ent = readdir(event_dir))) { 273 char path[PATH_MAX]; 274 char *name = evt_ent->d_name; 275 FILE *file; 276 277 if (!strcmp(name, ".") || !strcmp(name, "..")) 278 continue; 279 280 /* 281 * skip info files parsed in perf_pmu__new_alias() 282 */ 283 if (pmu_alias_info_file(name)) 284 continue; 285 286 snprintf(path, PATH_MAX, "%s/%s", dir, name); 287 288 ret = -EINVAL; 289 file = fopen(path, "r"); 290 if (!file) 291 break; 292 293 ret = perf_pmu__new_alias(head, dir, name, file); 294 fclose(file); 295 } 296 297 closedir(event_dir); 298 return ret; 299 } 300 301 /* 302 * Reading the pmu event aliases definition, which should be located at: 303 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 304 */ 305 static int pmu_aliases(const char *name, struct list_head *head) 306 { 307 struct stat st; 308 char path[PATH_MAX]; 309 const char *sysfs = sysfs__mountpoint(); 310 311 if (!sysfs) 312 return -1; 313 314 snprintf(path, PATH_MAX, 315 "%s/bus/event_source/devices/%s/events", sysfs, name); 316 317 if (stat(path, &st) < 0) 318 return 0; /* no error if 'events' does not exist */ 319 320 if (pmu_aliases_parse(path, head)) 321 return -1; 322 323 return 0; 324 } 325 326 static int pmu_alias_terms(struct perf_pmu_alias *alias, 327 struct list_head *terms) 328 { 329 struct parse_events_term *term, *cloned; 330 LIST_HEAD(list); 331 int ret; 332 333 list_for_each_entry(term, &alias->terms, list) { 334 ret = parse_events_term__clone(&cloned, term); 335 if (ret) { 336 parse_events__free_terms(&list); 337 return ret; 338 } 339 list_add_tail(&cloned->list, &list); 340 } 341 list_splice(&list, terms); 342 return 0; 343 } 344 345 /* 346 * Reading/parsing the default pmu type value, which should be 347 * located at: 348 * /sys/bus/event_source/devices/<dev>/type as sysfs attribute. 349 */ 350 static int pmu_type(const char *name, __u32 *type) 351 { 352 struct stat st; 353 char path[PATH_MAX]; 354 FILE *file; 355 int ret = 0; 356 const char *sysfs = sysfs__mountpoint(); 357 358 if (!sysfs) 359 return -1; 360 361 snprintf(path, PATH_MAX, 362 "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name); 363 364 if (stat(path, &st) < 0) 365 return -1; 366 367 file = fopen(path, "r"); 368 if (!file) 369 return -EINVAL; 370 371 if (1 != fscanf(file, "%u", type)) 372 ret = -1; 373 374 fclose(file); 375 return ret; 376 } 377 378 /* Add all pmus in sysfs to pmu list: */ 379 static void pmu_read_sysfs(void) 380 { 381 char path[PATH_MAX]; 382 DIR *dir; 383 struct dirent *dent; 384 const char *sysfs = sysfs__mountpoint(); 385 386 if (!sysfs) 387 return; 388 389 snprintf(path, PATH_MAX, 390 "%s" EVENT_SOURCE_DEVICE_PATH, sysfs); 391 392 dir = opendir(path); 393 if (!dir) 394 return; 395 396 while ((dent = readdir(dir))) { 397 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) 398 continue; 399 /* add to static LIST_HEAD(pmus): */ 400 perf_pmu__find(dent->d_name); 401 } 402 403 closedir(dir); 404 } 405 406 static struct cpu_map *pmu_cpumask(const char *name) 407 { 408 struct stat st; 409 char path[PATH_MAX]; 410 FILE *file; 411 struct cpu_map *cpus; 412 const char *sysfs = sysfs__mountpoint(); 413 414 if (!sysfs) 415 return NULL; 416 417 snprintf(path, PATH_MAX, 418 "%s/bus/event_source/devices/%s/cpumask", sysfs, name); 419 420 if (stat(path, &st) < 0) 421 return NULL; 422 423 file = fopen(path, "r"); 424 if (!file) 425 return NULL; 426 427 cpus = cpu_map__read(file); 428 fclose(file); 429 return cpus; 430 } 431 432 struct perf_event_attr *__attribute__((weak)) 433 perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) 434 { 435 return NULL; 436 } 437 438 static struct perf_pmu *pmu_lookup(const char *name) 439 { 440 struct perf_pmu *pmu; 441 LIST_HEAD(format); 442 LIST_HEAD(aliases); 443 __u32 type; 444 445 /* 446 * The pmu data we store & need consists of the pmu 447 * type value and format definitions. Load both right 448 * now. 449 */ 450 if (pmu_format(name, &format)) 451 return NULL; 452 453 if (pmu_aliases(name, &aliases)) 454 return NULL; 455 456 if (pmu_type(name, &type)) 457 return NULL; 458 459 pmu = zalloc(sizeof(*pmu)); 460 if (!pmu) 461 return NULL; 462 463 pmu->cpus = pmu_cpumask(name); 464 465 INIT_LIST_HEAD(&pmu->format); 466 INIT_LIST_HEAD(&pmu->aliases); 467 list_splice(&format, &pmu->format); 468 list_splice(&aliases, &pmu->aliases); 469 pmu->name = strdup(name); 470 pmu->type = type; 471 list_add_tail(&pmu->list, &pmus); 472 473 pmu->default_config = perf_pmu__get_default_config(pmu); 474 475 return pmu; 476 } 477 478 static struct perf_pmu *pmu_find(const char *name) 479 { 480 struct perf_pmu *pmu; 481 482 list_for_each_entry(pmu, &pmus, list) 483 if (!strcmp(pmu->name, name)) 484 return pmu; 485 486 return NULL; 487 } 488 489 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) 490 { 491 /* 492 * pmu iterator: If pmu is NULL, we start at the begin, 493 * otherwise return the next pmu. Returns NULL on end. 494 */ 495 if (!pmu) { 496 pmu_read_sysfs(); 497 pmu = list_prepare_entry(pmu, &pmus, list); 498 } 499 list_for_each_entry_continue(pmu, &pmus, list) 500 return pmu; 501 return NULL; 502 } 503 504 struct perf_pmu *perf_pmu__find(const char *name) 505 { 506 struct perf_pmu *pmu; 507 508 /* 509 * Once PMU is loaded it stays in the list, 510 * so we keep us from multiple reading/parsing 511 * the pmu format definitions. 512 */ 513 pmu = pmu_find(name); 514 if (pmu) 515 return pmu; 516 517 return pmu_lookup(name); 518 } 519 520 static struct perf_pmu_format * 521 pmu_find_format(struct list_head *formats, char *name) 522 { 523 struct perf_pmu_format *format; 524 525 list_for_each_entry(format, formats, list) 526 if (!strcmp(format->name, name)) 527 return format; 528 529 return NULL; 530 } 531 532 /* 533 * Sets value based on the format definition (format parameter) 534 * and unformated value (value parameter). 535 */ 536 static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, 537 bool zero) 538 { 539 unsigned long fbit, vbit; 540 541 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 542 543 if (!test_bit(fbit, format)) 544 continue; 545 546 if (value & (1llu << vbit++)) 547 *v |= (1llu << fbit); 548 else if (zero) 549 *v &= ~(1llu << fbit); 550 } 551 } 552 553 /* 554 * Term is a string term, and might be a param-term. Try to look up it's value 555 * in the remaining terms. 556 * - We have a term like "base-or-format-term=param-term", 557 * - We need to find the value supplied for "param-term" (with param-term named 558 * in a config string) later on in the term list. 559 */ 560 static int pmu_resolve_param_term(struct parse_events_term *term, 561 struct list_head *head_terms, 562 __u64 *value) 563 { 564 struct parse_events_term *t; 565 566 list_for_each_entry(t, head_terms, list) { 567 if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 568 if (!strcmp(t->config, term->config)) { 569 t->used = true; 570 *value = t->val.num; 571 return 0; 572 } 573 } 574 } 575 576 if (verbose) 577 printf("Required parameter '%s' not specified\n", term->config); 578 579 return -1; 580 } 581 582 static char *formats_error_string(struct list_head *formats) 583 { 584 struct perf_pmu_format *format; 585 char *err, *str; 586 static const char *static_terms = "config,config1,config2,name,period,branch_type\n"; 587 unsigned i = 0; 588 589 if (!asprintf(&str, "valid terms:")) 590 return NULL; 591 592 /* sysfs exported terms */ 593 list_for_each_entry(format, formats, list) { 594 char c = i++ ? ',' : ' '; 595 596 err = str; 597 if (!asprintf(&str, "%s%c%s", err, c, format->name)) 598 goto fail; 599 free(err); 600 } 601 602 /* static terms */ 603 err = str; 604 if (!asprintf(&str, "%s,%s", err, static_terms)) 605 goto fail; 606 607 free(err); 608 return str; 609 fail: 610 free(err); 611 return NULL; 612 } 613 614 /* 615 * Setup one of config[12] attr members based on the 616 * user input data - term parameter. 617 */ 618 static int pmu_config_term(struct list_head *formats, 619 struct perf_event_attr *attr, 620 struct parse_events_term *term, 621 struct list_head *head_terms, 622 bool zero, struct parse_events_error *err) 623 { 624 struct perf_pmu_format *format; 625 __u64 *vp; 626 __u64 val; 627 628 /* 629 * If this is a parameter we've already used for parameterized-eval, 630 * skip it in normal eval. 631 */ 632 if (term->used) 633 return 0; 634 635 /* 636 * Hardcoded terms should be already in, so nothing 637 * to be done for them. 638 */ 639 if (parse_events__is_hardcoded_term(term)) 640 return 0; 641 642 format = pmu_find_format(formats, term->config); 643 if (!format) { 644 if (verbose) 645 printf("Invalid event/parameter '%s'\n", term->config); 646 if (err) { 647 err->idx = term->err_term; 648 err->str = strdup("unknown term"); 649 err->help = formats_error_string(formats); 650 } 651 return -EINVAL; 652 } 653 654 switch (format->value) { 655 case PERF_PMU_FORMAT_VALUE_CONFIG: 656 vp = &attr->config; 657 break; 658 case PERF_PMU_FORMAT_VALUE_CONFIG1: 659 vp = &attr->config1; 660 break; 661 case PERF_PMU_FORMAT_VALUE_CONFIG2: 662 vp = &attr->config2; 663 break; 664 default: 665 return -EINVAL; 666 } 667 668 /* 669 * Either directly use a numeric term, or try to translate string terms 670 * using event parameters. 671 */ 672 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 673 val = term->val.num; 674 else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 675 if (strcmp(term->val.str, "?")) { 676 if (verbose) { 677 pr_info("Invalid sysfs entry %s=%s\n", 678 term->config, term->val.str); 679 } 680 if (err) { 681 err->idx = term->err_val; 682 err->str = strdup("expected numeric value"); 683 } 684 return -EINVAL; 685 } 686 687 if (pmu_resolve_param_term(term, head_terms, &val)) 688 return -EINVAL; 689 } else 690 return -EINVAL; 691 692 pmu_format_value(format->bits, val, vp, zero); 693 return 0; 694 } 695 696 int perf_pmu__config_terms(struct list_head *formats, 697 struct perf_event_attr *attr, 698 struct list_head *head_terms, 699 bool zero, struct parse_events_error *err) 700 { 701 struct parse_events_term *term; 702 703 list_for_each_entry(term, head_terms, list) { 704 if (pmu_config_term(formats, attr, term, head_terms, 705 zero, err)) 706 return -EINVAL; 707 } 708 709 return 0; 710 } 711 712 /* 713 * Configures event's 'attr' parameter based on the: 714 * 1) users input - specified in terms parameter 715 * 2) pmu format definitions - specified by pmu parameter 716 */ 717 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 718 struct list_head *head_terms, 719 struct parse_events_error *err) 720 { 721 bool zero = !!pmu->default_config; 722 723 attr->type = pmu->type; 724 return perf_pmu__config_terms(&pmu->format, attr, head_terms, 725 zero, err); 726 } 727 728 static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 729 struct parse_events_term *term) 730 { 731 struct perf_pmu_alias *alias; 732 char *name; 733 734 if (parse_events__is_hardcoded_term(term)) 735 return NULL; 736 737 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 738 if (term->val.num != 1) 739 return NULL; 740 if (pmu_find_format(&pmu->format, term->config)) 741 return NULL; 742 name = term->config; 743 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 744 if (strcasecmp(term->config, "event")) 745 return NULL; 746 name = term->val.str; 747 } else { 748 return NULL; 749 } 750 751 list_for_each_entry(alias, &pmu->aliases, list) { 752 if (!strcasecmp(alias->name, name)) 753 return alias; 754 } 755 return NULL; 756 } 757 758 759 static int check_info_data(struct perf_pmu_alias *alias, 760 struct perf_pmu_info *info) 761 { 762 /* 763 * Only one term in event definition can 764 * define unit, scale and snapshot, fail 765 * if there's more than one. 766 */ 767 if ((info->unit && alias->unit) || 768 (info->scale && alias->scale) || 769 (info->snapshot && alias->snapshot)) 770 return -EINVAL; 771 772 if (alias->unit) 773 info->unit = alias->unit; 774 775 if (alias->scale) 776 info->scale = alias->scale; 777 778 if (alias->snapshot) 779 info->snapshot = alias->snapshot; 780 781 return 0; 782 } 783 784 /* 785 * Find alias in the terms list and replace it with the terms 786 * defined for the alias 787 */ 788 int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 789 struct perf_pmu_info *info) 790 { 791 struct parse_events_term *term, *h; 792 struct perf_pmu_alias *alias; 793 int ret; 794 795 info->per_pkg = false; 796 797 /* 798 * Mark unit and scale as not set 799 * (different from default values, see below) 800 */ 801 info->unit = NULL; 802 info->scale = 0.0; 803 info->snapshot = false; 804 805 list_for_each_entry_safe(term, h, head_terms, list) { 806 alias = pmu_find_alias(pmu, term); 807 if (!alias) 808 continue; 809 ret = pmu_alias_terms(alias, &term->list); 810 if (ret) 811 return ret; 812 813 ret = check_info_data(alias, info); 814 if (ret) 815 return ret; 816 817 if (alias->per_pkg) 818 info->per_pkg = true; 819 820 list_del(&term->list); 821 free(term); 822 } 823 824 /* 825 * if no unit or scale foundin aliases, then 826 * set defaults as for evsel 827 * unit cannot left to NULL 828 */ 829 if (info->unit == NULL) 830 info->unit = ""; 831 832 if (info->scale == 0.0) 833 info->scale = 1.0; 834 835 return 0; 836 } 837 838 int perf_pmu__new_format(struct list_head *list, char *name, 839 int config, unsigned long *bits) 840 { 841 struct perf_pmu_format *format; 842 843 format = zalloc(sizeof(*format)); 844 if (!format) 845 return -ENOMEM; 846 847 format->name = strdup(name); 848 format->value = config; 849 memcpy(format->bits, bits, sizeof(format->bits)); 850 851 list_add_tail(&format->list, list); 852 return 0; 853 } 854 855 void perf_pmu__set_format(unsigned long *bits, long from, long to) 856 { 857 long b; 858 859 if (!to) 860 to = from; 861 862 memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS)); 863 for (b = from; b <= to; b++) 864 set_bit(b, bits); 865 } 866 867 static int sub_non_neg(int a, int b) 868 { 869 if (b > a) 870 return 0; 871 return a - b; 872 } 873 874 static char *format_alias(char *buf, int len, struct perf_pmu *pmu, 875 struct perf_pmu_alias *alias) 876 { 877 struct parse_events_term *term; 878 int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); 879 880 list_for_each_entry(term, &alias->terms, list) { 881 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 882 used += snprintf(buf + used, sub_non_neg(len, used), 883 ",%s=%s", term->config, 884 term->val.str); 885 } 886 887 if (sub_non_neg(len, used) > 0) { 888 buf[used] = '/'; 889 used++; 890 } 891 if (sub_non_neg(len, used) > 0) { 892 buf[used] = '\0'; 893 used++; 894 } else 895 buf[len - 1] = '\0'; 896 897 return buf; 898 } 899 900 static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu, 901 struct perf_pmu_alias *alias) 902 { 903 snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name); 904 return buf; 905 } 906 907 static int cmp_string(const void *a, const void *b) 908 { 909 const char * const *as = a; 910 const char * const *bs = b; 911 return strcmp(*as, *bs); 912 } 913 914 void print_pmu_events(const char *event_glob, bool name_only) 915 { 916 struct perf_pmu *pmu; 917 struct perf_pmu_alias *alias; 918 char buf[1024]; 919 int printed = 0; 920 int len, j; 921 char **aliases; 922 923 pmu = NULL; 924 len = 0; 925 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 926 list_for_each_entry(alias, &pmu->aliases, list) 927 len++; 928 if (pmu->selectable) 929 len++; 930 } 931 aliases = zalloc(sizeof(char *) * len); 932 if (!aliases) 933 goto out_enomem; 934 pmu = NULL; 935 j = 0; 936 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 937 list_for_each_entry(alias, &pmu->aliases, list) { 938 char *name = format_alias(buf, sizeof(buf), pmu, alias); 939 bool is_cpu = !strcmp(pmu->name, "cpu"); 940 941 if (event_glob != NULL && 942 !(strglobmatch(name, event_glob) || 943 (!is_cpu && strglobmatch(alias->name, 944 event_glob)))) 945 continue; 946 947 if (is_cpu && !name_only) 948 name = format_alias_or(buf, sizeof(buf), pmu, alias); 949 950 aliases[j] = strdup(name); 951 if (aliases[j] == NULL) 952 goto out_enomem; 953 j++; 954 } 955 if (pmu->selectable) { 956 char *s; 957 if (asprintf(&s, "%s//", pmu->name) < 0) 958 goto out_enomem; 959 aliases[j] = s; 960 j++; 961 } 962 } 963 len = j; 964 qsort(aliases, len, sizeof(char *), cmp_string); 965 for (j = 0; j < len; j++) { 966 if (name_only) { 967 printf("%s ", aliases[j]); 968 continue; 969 } 970 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 971 printed++; 972 } 973 if (printed) 974 printf("\n"); 975 out_free: 976 for (j = 0; j < len; j++) 977 zfree(&aliases[j]); 978 zfree(&aliases); 979 return; 980 981 out_enomem: 982 printf("FATAL: not enough memory to print PMU events\n"); 983 if (aliases) 984 goto out_free; 985 } 986 987 bool pmu_have_event(const char *pname, const char *name) 988 { 989 struct perf_pmu *pmu; 990 struct perf_pmu_alias *alias; 991 992 pmu = NULL; 993 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 994 if (strcmp(pname, pmu->name)) 995 continue; 996 list_for_each_entry(alias, &pmu->aliases, list) 997 if (!strcmp(alias->name, name)) 998 return true; 999 } 1000 return false; 1001 } 1002 1003 static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) 1004 { 1005 struct stat st; 1006 char path[PATH_MAX]; 1007 const char *sysfs; 1008 1009 sysfs = sysfs__mountpoint(); 1010 if (!sysfs) 1011 return NULL; 1012 1013 snprintf(path, PATH_MAX, 1014 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name); 1015 1016 if (stat(path, &st) < 0) 1017 return NULL; 1018 1019 return fopen(path, "r"); 1020 } 1021 1022 int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 1023 ...) 1024 { 1025 va_list args; 1026 FILE *file; 1027 int ret = EOF; 1028 1029 va_start(args, fmt); 1030 file = perf_pmu__open_file(pmu, name); 1031 if (file) { 1032 ret = vfscanf(file, fmt, args); 1033 fclose(file); 1034 } 1035 va_end(args); 1036 return ret; 1037 } 1038