2290 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <linux/list.h>3#include <linux/compiler.h>4#include <linux/string.h>5#include <linux/zalloc.h>6#include <linux/ctype.h>7#include <sys/types.h>8#include <fcntl.h>9#include <sys/stat.h>10#include <unistd.h>11#include <stdio.h>12#include <stdbool.h>13#include <dirent.h>14#include <api/fs/fs.h>15#include <locale.h>16#include <fnmatch.h>17#include <math.h>18#include "debug.h"19#include "evsel.h"20#include "pmu.h"21#include "pmus.h"22#include <util/pmu-bison.h>23#include <util/pmu-flex.h>24#include "parse-events.h"25#include "print-events.h"26#include "header.h"27#include "string2.h"28#include "strbuf.h"29#include "fncache.h"30#include "util/evsel_config.h"31#include <regex.h>32 33#define UNIT_MAX_LEN 31 /* max length for event unit name */34 35enum event_source {36 /* An event loaded from /sys/devices/<pmu>/events. */37 EVENT_SRC_SYSFS,38 /* An event loaded from a CPUID matched json file. */39 EVENT_SRC_CPU_JSON,40 /*41 * An event loaded from a /sys/devices/<pmu>/identifier matched json42 * file.43 */44 EVENT_SRC_SYS_JSON,45};46 47/**48 * struct perf_pmu_alias - An event either read from sysfs or builtin in49 * pmu-events.c, created by parsing the pmu-events json files.50 */51struct perf_pmu_alias {52 /** @name: Name of the event like "mem-loads". */53 char *name;54 /** @desc: Optional short description of the event. */55 char *desc;56 /** @long_desc: Optional long description. */57 char *long_desc;58 /**59 * @topic: Optional topic such as cache or pipeline, particularly for60 * json events.61 */62 char *topic;63 /** @terms: Owned list of the original parsed parameters. */64 struct parse_events_terms terms;65 /** @list: List element of struct perf_pmu aliases. */66 struct list_head list;67 /**68 * @pmu_name: The name copied from the json struct pmu_event. This can69 * differ from the PMU name as it won't have suffixes.70 */71 char *pmu_name;72 /** @unit: Units for the event, such as bytes or cache lines. */73 char unit[UNIT_MAX_LEN+1];74 /** @scale: Value to scale read counter values by. */75 double scale;76 /**77 * @per_pkg: Does the file78 * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.per-pkg or79 * equivalent json value exist and have the value 1.80 */81 bool per_pkg;82 /**83 * @snapshot: Does the file84 * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.snapshot85 * exist and have the value 1.86 */87 bool snapshot;88 /**89 * @deprecated: Is the event hidden and so not shown in perf list by90 * default.91 */92 bool deprecated;93 /** @from_sysfs: Was the alias from sysfs or a json event? */94 bool from_sysfs;95 /** @info_loaded: Have the scale, unit and other values been read from disk? */96 bool info_loaded;97};98 99/**100 * struct perf_pmu_format - Values from a format file read from101 * <sysfs>/devices/cpu/format/ held in struct perf_pmu.102 *103 * For example, the contents of <sysfs>/devices/cpu/format/event may be104 * "config:0-7" and will be represented here as name="event",105 * value=PERF_PMU_FORMAT_VALUE_CONFIG and bits 0 to 7 will be set.106 */107struct perf_pmu_format {108 /** @list: Element on list within struct perf_pmu. */109 struct list_head list;110 /** @bits: Which config bits are set by this format value. */111 DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS);112 /** @name: The modifier/file name. */113 char *name;114 /**115 * @value : Which config value the format relates to. Supported values116 * are from PERF_PMU_FORMAT_VALUE_CONFIG to117 * PERF_PMU_FORMAT_VALUE_CONFIG_END.118 */119 u16 value;120 /** @loaded: Has the contents been loaded/parsed. */121 bool loaded;122};123 124static int pmu_aliases_parse(struct perf_pmu *pmu);125 126static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name)127{128 struct perf_pmu_format *format;129 130 format = zalloc(sizeof(*format));131 if (!format)132 return NULL;133 134 format->name = strdup(name);135 if (!format->name) {136 free(format);137 return NULL;138 }139 list_add_tail(&format->list, list);140 return format;141}142 143/* Called at the end of parsing a format. */144void perf_pmu_format__set_value(void *vformat, int config, unsigned long *bits)145{146 struct perf_pmu_format *format = vformat;147 148 format->value = config;149 memcpy(format->bits, bits, sizeof(format->bits));150}151 152static void __perf_pmu_format__load(struct perf_pmu_format *format, FILE *file)153{154 void *scanner;155 int ret;156 157 ret = perf_pmu_lex_init(&scanner);158 if (ret)159 return;160 161 perf_pmu_set_in(file, scanner);162 ret = perf_pmu_parse(format, scanner);163 perf_pmu_lex_destroy(scanner);164 format->loaded = true;165}166 167static void perf_pmu_format__load(const struct perf_pmu *pmu, struct perf_pmu_format *format)168{169 char path[PATH_MAX];170 FILE *file = NULL;171 172 if (format->loaded)173 return;174 175 if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, "format"))176 return;177 178 assert(strlen(path) + strlen(format->name) + 2 < sizeof(path));179 strcat(path, "/");180 strcat(path, format->name);181 182 file = fopen(path, "r");183 if (!file)184 return;185 __perf_pmu_format__load(format, file);186 fclose(file);187}188 189/*190 * Parse & process all the sysfs attributes located under191 * the directory specified in 'dir' parameter.192 */193static int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load)194{195 struct dirent *evt_ent;196 DIR *format_dir;197 int ret = 0;198 199 format_dir = fdopendir(dirfd);200 if (!format_dir)201 return -EINVAL;202 203 while ((evt_ent = readdir(format_dir)) != NULL) {204 struct perf_pmu_format *format;205 char *name = evt_ent->d_name;206 207 if (!strcmp(name, ".") || !strcmp(name, ".."))208 continue;209 210 format = perf_pmu__new_format(&pmu->format, name);211 if (!format) {212 ret = -ENOMEM;213 break;214 }215 216 if (eager_load) {217 FILE *file;218 int fd = openat(dirfd, name, O_RDONLY);219 220 if (fd < 0) {221 ret = -errno;222 break;223 }224 file = fdopen(fd, "r");225 if (!file) {226 close(fd);227 break;228 }229 __perf_pmu_format__load(format, file);230 fclose(file);231 }232 }233 234 closedir(format_dir);235 return ret;236}237 238/*239 * Reading/parsing the default pmu format definition, which should be240 * located at:241 * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes.242 */243static int pmu_format(struct perf_pmu *pmu, int dirfd, const char *name, bool eager_load)244{245 int fd;246 247 fd = perf_pmu__pathname_fd(dirfd, name, "format", O_DIRECTORY);248 if (fd < 0)249 return 0;250 251 /* it'll close the fd */252 if (perf_pmu__format_parse(pmu, fd, eager_load))253 return -1;254 255 return 0;256}257 258int perf_pmu__convert_scale(const char *scale, char **end, double *sval)259{260 char *lc;261 int ret = 0;262 263 /*264 * save current locale265 */266 lc = setlocale(LC_NUMERIC, NULL);267 268 /*269 * The lc string may be allocated in static storage,270 * so get a dynamic copy to make it survive setlocale271 * call below.272 */273 lc = strdup(lc);274 if (!lc) {275 ret = -ENOMEM;276 goto out;277 }278 279 /*280 * force to C locale to ensure kernel281 * scale string is converted correctly.282 * kernel uses default C locale.283 */284 setlocale(LC_NUMERIC, "C");285 286 *sval = strtod(scale, end);287 288out:289 /* restore locale */290 setlocale(LC_NUMERIC, lc);291 free(lc);292 return ret;293}294 295static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *alias)296{297 struct stat st;298 ssize_t sret;299 size_t len;300 char scale[128];301 int fd, ret = -1;302 char path[PATH_MAX];303 304 len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));305 if (!len)306 return 0;307 scnprintf(path + len, sizeof(path) - len, "%s/events/%s.scale", pmu->name, alias->name);308 309 fd = open(path, O_RDONLY);310 if (fd == -1)311 return -1;312 313 if (fstat(fd, &st) < 0)314 goto error;315 316 sret = read(fd, scale, sizeof(scale)-1);317 if (sret < 0)318 goto error;319 320 if (scale[sret - 1] == '\n')321 scale[sret - 1] = '\0';322 else323 scale[sret] = '\0';324 325 ret = perf_pmu__convert_scale(scale, NULL, &alias->scale);326error:327 close(fd);328 return ret;329}330 331static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *alias)332{333 char path[PATH_MAX];334 size_t len;335 ssize_t sret;336 int fd;337 338 339 len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));340 if (!len)341 return 0;342 scnprintf(path + len, sizeof(path) - len, "%s/events/%s.unit", pmu->name, alias->name);343 344 fd = open(path, O_RDONLY);345 if (fd == -1)346 return -1;347 348 sret = read(fd, alias->unit, UNIT_MAX_LEN);349 if (sret < 0)350 goto error;351 352 close(fd);353 354 if (alias->unit[sret - 1] == '\n')355 alias->unit[sret - 1] = '\0';356 else357 alias->unit[sret] = '\0';358 359 return 0;360error:361 close(fd);362 alias->unit[0] = '\0';363 return -1;364}365 366static bool perf_pmu__parse_event_source_bool(const char *pmu_name, const char *event_name,367 const char *suffix)368{369 char path[PATH_MAX];370 size_t len;371 int fd;372 373 len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));374 if (!len)375 return false;376 377 scnprintf(path + len, sizeof(path) - len, "%s/events/%s.%s", pmu_name, event_name, suffix);378 379 fd = open(path, O_RDONLY);380 if (fd == -1)381 return false;382 383#ifndef NDEBUG384 {385 char buf[8];386 387 len = read(fd, buf, sizeof(buf));388 assert(len == 1 || len == 2);389 assert(buf[0] == '1');390 }391#endif392 393 close(fd);394 return true;395}396 397static void perf_pmu__parse_per_pkg(struct perf_pmu *pmu, struct perf_pmu_alias *alias)398{399 alias->per_pkg = perf_pmu__parse_event_source_bool(pmu->name, alias->name, "per-pkg");400}401 402static void perf_pmu__parse_snapshot(struct perf_pmu *pmu, struct perf_pmu_alias *alias)403{404 alias->snapshot = perf_pmu__parse_event_source_bool(pmu->name, alias->name, "snapshot");405}406 407/* Delete an alias entry. */408static void perf_pmu_free_alias(struct perf_pmu_alias *newalias)409{410 zfree(&newalias->name);411 zfree(&newalias->desc);412 zfree(&newalias->long_desc);413 zfree(&newalias->topic);414 zfree(&newalias->pmu_name);415 parse_events_terms__exit(&newalias->terms);416 free(newalias);417}418 419static void perf_pmu__del_aliases(struct perf_pmu *pmu)420{421 struct perf_pmu_alias *alias, *tmp;422 423 list_for_each_entry_safe(alias, tmp, &pmu->aliases, list) {424 list_del(&alias->list);425 perf_pmu_free_alias(alias);426 }427}428 429static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu,430 const char *name,431 bool load)432{433 struct perf_pmu_alias *alias;434 435 if (load && !pmu->sysfs_aliases_loaded) {436 bool has_sysfs_event;437 char event_file_name[FILENAME_MAX + 8];438 439 /*440 * Test if alias/event 'name' exists in the PMU's sysfs/events441 * directory. If not skip parsing the sysfs aliases. Sysfs event442 * name must be all lower or all upper case.443 */444 scnprintf(event_file_name, sizeof(event_file_name), "events/%s", name);445 for (size_t i = 7, n = 7 + strlen(name); i < n; i++)446 event_file_name[i] = tolower(event_file_name[i]);447 448 has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name);449 if (!has_sysfs_event) {450 for (size_t i = 7, n = 7 + strlen(name); i < n; i++)451 event_file_name[i] = toupper(event_file_name[i]);452 453 has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name);454 }455 if (has_sysfs_event)456 pmu_aliases_parse(pmu);457 458 }459 list_for_each_entry(alias, &pmu->aliases, list) {460 if (!strcasecmp(alias->name, name))461 return alias;462 }463 return NULL;464}465 466static bool assign_str(const char *name, const char *field, char **old_str,467 const char *new_str)468{469 if (!*old_str && new_str) {470 *old_str = strdup(new_str);471 return true;472 }473 474 if (!new_str || !strcasecmp(*old_str, new_str))475 return false; /* Nothing to update. */476 477 pr_debug("alias %s differs in field '%s' ('%s' != '%s')\n",478 name, field, *old_str, new_str);479 zfree(old_str);480 *old_str = strdup(new_str);481 return true;482}483 484static void read_alias_info(struct perf_pmu *pmu, struct perf_pmu_alias *alias)485{486 if (!alias->from_sysfs || alias->info_loaded)487 return;488 489 /*490 * load unit name and scale if available491 */492 perf_pmu__parse_unit(pmu, alias);493 perf_pmu__parse_scale(pmu, alias);494 perf_pmu__parse_per_pkg(pmu, alias);495 perf_pmu__parse_snapshot(pmu, alias);496}497 498struct update_alias_data {499 struct perf_pmu *pmu;500 struct perf_pmu_alias *alias;501};502 503static int update_alias(const struct pmu_event *pe,504 const struct pmu_events_table *table __maybe_unused,505 void *vdata)506{507 struct update_alias_data *data = vdata;508 int ret = 0;509 510 read_alias_info(data->pmu, data->alias);511 assign_str(pe->name, "desc", &data->alias->desc, pe->desc);512 assign_str(pe->name, "long_desc", &data->alias->long_desc, pe->long_desc);513 assign_str(pe->name, "topic", &data->alias->topic, pe->topic);514 data->alias->per_pkg = pe->perpkg;515 if (pe->event) {516 parse_events_terms__exit(&data->alias->terms);517 ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL);518 }519 if (!ret && pe->unit) {520 char *unit;521 522 ret = perf_pmu__convert_scale(pe->unit, &unit, &data->alias->scale);523 if (!ret)524 snprintf(data->alias->unit, sizeof(data->alias->unit), "%s", unit);525 }526 return ret;527}528 529static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,530 const char *desc, const char *val, FILE *val_fd,531 const struct pmu_event *pe, enum event_source src)532{533 struct perf_pmu_alias *alias;534 int ret;535 const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL;536 bool deprecated = false, perpkg = false;537 538 if (perf_pmu__find_alias(pmu, name, /*load=*/ false)) {539 /* Alias was already created/loaded. */540 return 0;541 }542 543 if (pe) {544 long_desc = pe->long_desc;545 topic = pe->topic;546 unit = pe->unit;547 perpkg = pe->perpkg;548 deprecated = pe->deprecated;549 if (pe->pmu && strcmp(pe->pmu, "default_core"))550 pmu_name = pe->pmu;551 }552 553 alias = zalloc(sizeof(*alias));554 if (!alias)555 return -ENOMEM;556 557 parse_events_terms__init(&alias->terms);558 alias->scale = 1.0;559 alias->unit[0] = '\0';560 alias->per_pkg = perpkg;561 alias->snapshot = false;562 alias->deprecated = deprecated;563 564 ret = parse_events_terms(&alias->terms, val, val_fd);565 if (ret) {566 pr_err("Cannot parse alias %s: %d\n", val, ret);567 free(alias);568 return ret;569 }570 571 alias->name = strdup(name);572 alias->desc = desc ? strdup(desc) : NULL;573 alias->long_desc = long_desc ? strdup(long_desc) :574 desc ? strdup(desc) : NULL;575 alias->topic = topic ? strdup(topic) : NULL;576 alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL;577 if (unit) {578 if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0) {579 perf_pmu_free_alias(alias);580 return -1;581 }582 snprintf(alias->unit, sizeof(alias->unit), "%s", unit);583 }584 switch (src) {585 default:586 case EVENT_SRC_SYSFS:587 alias->from_sysfs = true;588 if (pmu->events_table) {589 /* Update an event from sysfs with json data. */590 struct update_alias_data data = {591 .pmu = pmu,592 .alias = alias,593 };594 if (pmu_events_table__find_event(pmu->events_table, pmu, name,595 update_alias, &data) == 0)596 pmu->cpu_json_aliases++;597 }598 pmu->sysfs_aliases++;599 break;600 case EVENT_SRC_CPU_JSON:601 pmu->cpu_json_aliases++;602 break;603 case EVENT_SRC_SYS_JSON:604 pmu->sys_json_aliases++;605 break;606 607 }608 list_add_tail(&alias->list, &pmu->aliases);609 return 0;610}611 612static inline bool pmu_alias_info_file(const char *name)613{614 size_t len;615 616 len = strlen(name);617 if (len > 5 && !strcmp(name + len - 5, ".unit"))618 return true;619 if (len > 6 && !strcmp(name + len - 6, ".scale"))620 return true;621 if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))622 return true;623 if (len > 9 && !strcmp(name + len - 9, ".snapshot"))624 return true;625 626 return false;627}628 629/*630 * Reading the pmu event aliases definition, which should be located at:631 * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.632 */633static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)634{635 struct dirent *evt_ent;636 DIR *event_dir;637 638 event_dir = fdopendir(events_dir_fd);639 if (!event_dir)640 return -EINVAL;641 642 while ((evt_ent = readdir(event_dir))) {643 char *name = evt_ent->d_name;644 int fd;645 FILE *file;646 647 if (!strcmp(name, ".") || !strcmp(name, ".."))648 continue;649 650 /*651 * skip info files parsed in perf_pmu__new_alias()652 */653 if (pmu_alias_info_file(name))654 continue;655 656 fd = openat(events_dir_fd, name, O_RDONLY);657 if (fd == -1) {658 pr_debug("Cannot open %s\n", name);659 continue;660 }661 file = fdopen(fd, "r");662 if (!file) {663 close(fd);664 continue;665 }666 667 if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL,668 /*val=*/ NULL, file, /*pe=*/ NULL,669 EVENT_SRC_SYSFS) < 0)670 pr_debug("Cannot set up %s\n", name);671 fclose(file);672 }673 674 closedir(event_dir);675 pmu->sysfs_aliases_loaded = true;676 return 0;677}678 679static int pmu_aliases_parse(struct perf_pmu *pmu)680{681 char path[PATH_MAX];682 size_t len;683 int events_dir_fd, ret;684 685 if (pmu->sysfs_aliases_loaded)686 return 0;687 688 len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));689 if (!len)690 return 0;691 scnprintf(path + len, sizeof(path) - len, "%s/events", pmu->name);692 693 events_dir_fd = open(path, O_DIRECTORY);694 if (events_dir_fd == -1) {695 pmu->sysfs_aliases_loaded = true;696 return 0;697 }698 ret = __pmu_aliases_parse(pmu, events_dir_fd);699 close(events_dir_fd);700 return ret;701}702 703static int pmu_aliases_parse_eager(struct perf_pmu *pmu, int sysfs_fd)704{705 char path[FILENAME_MAX + 7];706 int ret, events_dir_fd;707 708 scnprintf(path, sizeof(path), "%s/events", pmu->name);709 events_dir_fd = openat(sysfs_fd, path, O_DIRECTORY, 0);710 if (events_dir_fd == -1) {711 pmu->sysfs_aliases_loaded = true;712 return 0;713 }714 ret = __pmu_aliases_parse(pmu, events_dir_fd);715 close(events_dir_fd);716 return ret;717}718 719static int pmu_alias_terms(struct perf_pmu_alias *alias, int err_loc, struct list_head *terms)720{721 struct parse_events_term *term, *cloned;722 struct parse_events_terms clone_terms;723 724 parse_events_terms__init(&clone_terms);725 list_for_each_entry(term, &alias->terms.terms, list) {726 int ret = parse_events_term__clone(&cloned, term);727 728 if (ret) {729 parse_events_terms__exit(&clone_terms);730 return ret;731 }732 /*733 * Weak terms don't override command line options,734 * which we don't want for implicit terms in aliases.735 */736 cloned->weak = true;737 cloned->err_term = cloned->err_val = err_loc;738 list_add_tail(&cloned->list, &clone_terms.terms);739 }740 list_splice_init(&clone_terms.terms, terms);741 parse_events_terms__exit(&clone_terms);742 return 0;743}744 745/*746 * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64)747 * may have a "cpus" file.748 */749static struct perf_cpu_map *pmu_cpumask(int dirfd, const char *name, bool is_core)750{751 struct perf_cpu_map *cpus;752 const char *templates[] = {753 "cpumask",754 "cpus",755 NULL756 };757 const char **template;758 char pmu_name[PATH_MAX];759 struct perf_pmu pmu = {.name = pmu_name};760 FILE *file;761 762 strlcpy(pmu_name, name, sizeof(pmu_name));763 for (template = templates; *template; template++) {764 file = perf_pmu__open_file_at(&pmu, dirfd, *template);765 if (!file)766 continue;767 cpus = perf_cpu_map__read(file);768 fclose(file);769 if (cpus)770 return cpus;771 }772 773 /* Nothing found, for core PMUs assume this means all CPUs. */774 return is_core ? perf_cpu_map__get(cpu_map__online()) : NULL;775}776 777static bool pmu_is_uncore(int dirfd, const char *name)778{779 int fd;780 781 fd = perf_pmu__pathname_fd(dirfd, name, "cpumask", O_PATH);782 if (fd < 0)783 return false;784 785 close(fd);786 return true;787}788 789static char *pmu_id(const char *name)790{791 char path[PATH_MAX], *str;792 size_t len;793 794 perf_pmu__pathname_scnprintf(path, sizeof(path), name, "identifier");795 796 if (filename__read_str(path, &str, &len) < 0)797 return NULL;798 799 str[len - 1] = 0; /* remove line feed */800 801 return str;802}803 804/**805 * is_sysfs_pmu_core() - PMU CORE devices have different name other than cpu in806 * sysfs on some platforms like ARM or Intel hybrid. Looking for807 * possible the cpus file in sysfs files to identify whether this is a808 * core device.809 * @name: The PMU name such as "cpu_atom".810 */811static int is_sysfs_pmu_core(const char *name)812{813 char path[PATH_MAX];814 815 if (!perf_pmu__pathname_scnprintf(path, sizeof(path), name, "cpus"))816 return 0;817 return file_available(path);818}819 820char *perf_pmu__getcpuid(struct perf_pmu *pmu)821{822 char *cpuid;823 static bool printed;824 825 cpuid = getenv("PERF_CPUID");826 if (cpuid)827 cpuid = strdup(cpuid);828 if (!cpuid)829 cpuid = get_cpuid_str(pmu);830 if (!cpuid)831 return NULL;832 833 if (!printed) {834 pr_debug("Using CPUID %s\n", cpuid);835 printed = true;836 }837 return cpuid;838}839 840__weak const struct pmu_metrics_table *pmu_metrics_table__find(void)841{842 return perf_pmu__find_metrics_table(NULL);843}844 845/**846 * Return the length of the PMU name not including the suffix for uncore PMUs.847 *848 * We want to deduplicate many similar uncore PMUs by stripping their suffixes,849 * but there are never going to be too many core PMUs and the suffixes might be850 * interesting. "arm_cortex_a53" vs "arm_cortex_a57" or "cpum_cf" for example.851 *852 * @skip_duplicate_pmus: False in verbose mode so all uncore PMUs are visible853 */854static size_t pmu_deduped_name_len(const struct perf_pmu *pmu, const char *name,855 bool skip_duplicate_pmus)856{857 return skip_duplicate_pmus && !pmu->is_core858 ? pmu_name_len_no_suffix(name)859 : strlen(name);860}861 862/**863 * perf_pmu__match_ignoring_suffix - Does the pmu_name match tok ignoring any864 * trailing suffix? The Suffix must be in form865 * tok_{digits}, or tok{digits}.866 * @pmu_name: The pmu_name with possible suffix.867 * @tok: The possible match to pmu_name without suffix.868 */869static bool perf_pmu__match_ignoring_suffix(const char *pmu_name, const char *tok)870{871 const char *p, *suffix;872 bool has_hex = false;873 874 if (strncmp(pmu_name, tok, strlen(tok)))875 return false;876 877 suffix = p = pmu_name + strlen(tok);878 if (*p == 0)879 return true;880 881 if (*p == '_') {882 ++p;883 ++suffix;884 }885 886 /* Ensure we end in a number */887 while (1) {888 if (!isxdigit(*p))889 return false;890 if (!has_hex)891 has_hex = !isdigit(*p);892 if (*(++p) == 0)893 break;894 }895 896 if (has_hex)897 return (p - suffix) > 2;898 899 return true;900}901 902/**903 * pmu_uncore_alias_match - does name match the PMU name?904 * @pmu_name: the json struct pmu_event name. This may lack a suffix (which905 * matches) or be of the form "socket,pmuname" which will match906 * "socketX_pmunameY".907 * @name: a real full PMU name as from sysfs.908 */909static bool pmu_uncore_alias_match(const char *pmu_name, const char *name)910{911 char *tmp = NULL, *tok, *str;912 bool res;913 914 if (strchr(pmu_name, ',') == NULL)915 return perf_pmu__match_ignoring_suffix(name, pmu_name);916 917 str = strdup(pmu_name);918 if (!str)919 return false;920 921 /*922 * uncore alias may be from different PMU with common prefix923 */924 tok = strtok_r(str, ",", &tmp);925 if (strncmp(pmu_name, tok, strlen(tok))) {926 res = false;927 goto out;928 }929 930 /*931 * Match more complex aliases where the alias name is a comma-delimited932 * list of tokens, orderly contained in the matching PMU name.933 *934 * Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we935 * match "socket" in "socketX_pmunameY" and then "pmuname" in936 * "pmunameY".937 */938 while (1) {939 char *next_tok = strtok_r(NULL, ",", &tmp);940 941 name = strstr(name, tok);942 if (!name ||943 (!next_tok && !perf_pmu__match_ignoring_suffix(name, tok))) {944 res = false;945 goto out;946 }947 if (!next_tok)948 break;949 tok = next_tok;950 name += strlen(tok);951 }952 953 res = true;954out:955 free(str);956 return res;957}958 959bool pmu_uncore_identifier_match(const char *compat, const char *id)960{961 regex_t re;962 regmatch_t pmatch[1];963 int match;964 965 if (regcomp(&re, compat, REG_EXTENDED) != 0) {966 /* Warn unable to generate match particular string. */967 pr_info("Invalid regular expression %s\n", compat);968 return false;969 }970 971 match = !regexec(&re, id, 1, pmatch, 0);972 if (match) {973 /* Ensure a full match. */974 match = pmatch[0].rm_so == 0 && (size_t)pmatch[0].rm_eo == strlen(id);975 }976 regfree(&re);977 978 return match;979}980 981static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,982 const struct pmu_events_table *table __maybe_unused,983 void *vdata)984{985 struct perf_pmu *pmu = vdata;986 987 perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL,988 pe, EVENT_SRC_CPU_JSON);989 return 0;990}991 992/*993 * From the pmu_events_table, find the events that correspond to the given994 * PMU and add them to the list 'head'.995 */996void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table)997{998 pmu_events_table__for_each_event(table, pmu, pmu_add_cpu_aliases_map_callback, pmu);999}1000 1001static void pmu_add_cpu_aliases(struct perf_pmu *pmu)1002{1003 if (!pmu->events_table)1004 return;1005 1006 if (pmu->cpu_aliases_added)1007 return;1008 1009 pmu_add_cpu_aliases_table(pmu, pmu->events_table);1010 pmu->cpu_aliases_added = true;1011}1012 1013static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,1014 const struct pmu_events_table *table __maybe_unused,1015 void *vdata)1016{1017 struct perf_pmu *pmu = vdata;1018 1019 if (!pe->compat || !pe->pmu)1020 return 0;1021 1022 if (pmu_uncore_alias_match(pe->pmu, pmu->name) &&1023 pmu_uncore_identifier_match(pe->compat, pmu->id)) {1024 perf_pmu__new_alias(pmu,1025 pe->name,1026 pe->desc,1027 pe->event,1028 /*val_fd=*/ NULL,1029 pe,1030 EVENT_SRC_SYS_JSON);1031 }1032 1033 return 0;1034}1035 1036void pmu_add_sys_aliases(struct perf_pmu *pmu)1037{1038 if (!pmu->id)1039 return;1040 1041 pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, pmu);1042}1043 1044static char *pmu_find_alias_name(struct perf_pmu *pmu, int dirfd)1045{1046 FILE *file = perf_pmu__open_file_at(pmu, dirfd, "alias");1047 char *line = NULL;1048 size_t line_len = 0;1049 ssize_t ret;1050 1051 if (!file)1052 return NULL;1053 1054 ret = getline(&line, &line_len, file);1055 if (ret < 0) {1056 fclose(file);1057 return NULL;1058 }1059 /* Remove trailing newline. */1060 if (ret > 0 && line[ret - 1] == '\n')1061 line[--ret] = '\0';1062 1063 fclose(file);1064 return line;1065}1066 1067static int pmu_max_precise(int dirfd, struct perf_pmu *pmu)1068{1069 int max_precise = -1;1070 1071 perf_pmu__scan_file_at(pmu, dirfd, "caps/max_precise", "%d", &max_precise);1072 return max_precise;1073}1074 1075void __weak1076perf_pmu__arch_init(struct perf_pmu *pmu)1077{1078 if (pmu->is_core)1079 pmu->mem_events = perf_mem_events;1080}1081 1082struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *name,1083 bool eager_load)1084{1085 struct perf_pmu *pmu;1086 __u32 type;1087 1088 pmu = zalloc(sizeof(*pmu));1089 if (!pmu)1090 return NULL;1091 1092 pmu->name = strdup(name);1093 if (!pmu->name)1094 goto err;1095 1096 /*1097 * Read type early to fail fast if a lookup name isn't a PMU. Ensure1098 * that type value is successfully assigned (return 1).1099 */1100 if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1)1101 goto err;1102 1103 INIT_LIST_HEAD(&pmu->format);1104 INIT_LIST_HEAD(&pmu->aliases);1105 INIT_LIST_HEAD(&pmu->caps);1106 1107 /*1108 * The pmu data we store & need consists of the pmu1109 * type value and format definitions. Load both right1110 * now.1111 */1112 if (pmu_format(pmu, dirfd, name, eager_load))1113 goto err;1114 1115 pmu->is_core = is_pmu_core(name);1116 pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core);1117 1118 pmu->type = type;1119 pmu->is_uncore = pmu_is_uncore(dirfd, name);1120 if (pmu->is_uncore)1121 pmu->id = pmu_id(name);1122 pmu->max_precise = pmu_max_precise(dirfd, pmu);1123 pmu->alias_name = pmu_find_alias_name(pmu, dirfd);1124 pmu->events_table = perf_pmu__find_events_table(pmu);1125 /*1126 * Load the sys json events/aliases when loading the PMU as each event1127 * may have a different compat regular expression. We therefore can't1128 * know the number of sys json events/aliases without computing the1129 * regular expressions for them all.1130 */1131 pmu_add_sys_aliases(pmu);1132 list_add_tail(&pmu->list, pmus);1133 1134 perf_pmu__arch_init(pmu);1135 1136 if (eager_load)1137 pmu_aliases_parse_eager(pmu, dirfd);1138 1139 return pmu;1140err:1141 zfree(&pmu->name);1142 free(pmu);1143 return NULL;1144}1145 1146/* Creates the PMU when sysfs scanning fails. */1147struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus)1148{1149 struct perf_pmu *pmu = zalloc(sizeof(*pmu));1150 1151 if (!pmu)1152 return NULL;1153 1154 pmu->name = strdup("cpu");1155 if (!pmu->name) {1156 free(pmu);1157 return NULL;1158 }1159 1160 pmu->is_core = true;1161 pmu->type = PERF_TYPE_RAW;1162 pmu->cpus = cpu_map__online();1163 1164 INIT_LIST_HEAD(&pmu->format);1165 INIT_LIST_HEAD(&pmu->aliases);1166 INIT_LIST_HEAD(&pmu->caps);1167 list_add_tail(&pmu->list, core_pmus);1168 return pmu;1169}1170 1171static bool perf_pmu__is_fake(const struct perf_pmu *pmu)1172{1173 return pmu->type == PERF_PMU_TYPE_FAKE;1174}1175 1176void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu)1177{1178 struct perf_pmu_format *format;1179 1180 if (pmu->formats_checked)1181 return;1182 1183 pmu->formats_checked = true;1184 1185 /* fake pmu doesn't have format list */1186 if (perf_pmu__is_fake(pmu))1187 return;1188 1189 list_for_each_entry(format, &pmu->format, list) {1190 perf_pmu_format__load(pmu, format);1191 if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) {1192 pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'"1193 "which is not supported by this version of perf!\n",1194 pmu->name, format->name, format->value);1195 return;1196 }1197 }1198}1199 1200bool evsel__is_aux_event(const struct evsel *evsel)1201{1202 struct perf_pmu *pmu;1203 1204 if (evsel->needs_auxtrace_mmap)1205 return true;1206 1207 pmu = evsel__find_pmu(evsel);1208 return pmu && pmu->auxtrace;1209}1210 1211/*1212 * Set @config_name to @val as long as the user hasn't already set or cleared it1213 * by passing a config term on the command line.1214 *1215 * @val is the value to put into the bits specified by @config_name rather than1216 * the bit pattern. It is shifted into position by this function, so to set1217 * something to true, pass 1 for val rather than a pre shifted value.1218 */1219#define field_prep(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask))1220void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel,1221 const char *config_name, u64 val)1222{1223 u64 user_bits = 0, bits;1224 struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG);1225 1226 if (term)1227 user_bits = term->val.cfg_chg;1228 1229 bits = perf_pmu__format_bits(pmu, config_name);1230 1231 /* Do nothing if the user changed the value */1232 if (bits & user_bits)1233 return;1234 1235 /* Otherwise replace it */1236 evsel->core.attr.config &= ~bits;1237 evsel->core.attr.config |= field_prep(bits, val);1238}1239 1240static struct perf_pmu_format *1241pmu_find_format(const struct list_head *formats, const char *name)1242{1243 struct perf_pmu_format *format;1244 1245 list_for_each_entry(format, formats, list)1246 if (!strcmp(format->name, name))1247 return format;1248 1249 return NULL;1250}1251 1252__u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name)1253{1254 struct perf_pmu_format *format = pmu_find_format(&pmu->format, name);1255 __u64 bits = 0;1256 int fbit;1257 1258 if (!format)1259 return 0;1260 1261 for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS)1262 bits |= 1ULL << fbit;1263 1264 return bits;1265}1266 1267int perf_pmu__format_type(struct perf_pmu *pmu, const char *name)1268{1269 struct perf_pmu_format *format = pmu_find_format(&pmu->format, name);1270 1271 if (!format)1272 return -1;1273 1274 perf_pmu_format__load(pmu, format);1275 return format->value;1276}1277 1278/*1279 * Sets value based on the format definition (format parameter)1280 * and unformatted value (value parameter).1281 */1282static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,1283 bool zero)1284{1285 unsigned long fbit, vbit;1286 1287 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {1288 1289 if (!test_bit(fbit, format))1290 continue;1291 1292 if (value & (1llu << vbit++))1293 *v |= (1llu << fbit);1294 else if (zero)1295 *v &= ~(1llu << fbit);1296 }1297}1298 1299static __u64 pmu_format_max_value(const unsigned long *format)1300{1301 int w;1302 1303 w = bitmap_weight(format, PERF_PMU_FORMAT_BITS);1304 if (!w)1305 return 0;1306 if (w < 64)1307 return (1ULL << w) - 1;1308 return -1;1309}1310 1311/*1312 * Term is a string term, and might be a param-term. Try to look up it's value1313 * in the remaining terms.1314 * - We have a term like "base-or-format-term=param-term",1315 * - We need to find the value supplied for "param-term" (with param-term named1316 * in a config string) later on in the term list.1317 */1318static int pmu_resolve_param_term(struct parse_events_term *term,1319 struct parse_events_terms *head_terms,1320 __u64 *value)1321{1322 struct parse_events_term *t;1323 1324 list_for_each_entry(t, &head_terms->terms, list) {1325 if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM &&1326 t->config && !strcmp(t->config, term->config)) {1327 t->used = true;1328 *value = t->val.num;1329 return 0;1330 }1331 }1332 1333 if (verbose > 0)1334 printf("Required parameter '%s' not specified\n", term->config);1335 1336 return -1;1337}1338 1339static char *pmu_formats_string(const struct list_head *formats)1340{1341 struct perf_pmu_format *format;1342 char *str = NULL;1343 struct strbuf buf = STRBUF_INIT;1344 unsigned int i = 0;1345 1346 if (!formats)1347 return NULL;1348 1349 /* sysfs exported terms */1350 list_for_each_entry(format, formats, list)1351 if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0)1352 goto error;1353 1354 str = strbuf_detach(&buf, NULL);1355error:1356 strbuf_release(&buf);1357 1358 return str;1359}1360 1361/*1362 * Setup one of config[12] attr members based on the1363 * user input data - term parameter.1364 */1365static int pmu_config_term(const struct perf_pmu *pmu,1366 struct perf_event_attr *attr,1367 struct parse_events_term *term,1368 struct parse_events_terms *head_terms,1369 bool zero, struct parse_events_error *err)1370{1371 struct perf_pmu_format *format;1372 __u64 *vp;1373 __u64 val, max_val;1374 1375 /*1376 * If this is a parameter we've already used for parameterized-eval,1377 * skip it in normal eval.1378 */1379 if (term->used)1380 return 0;1381 1382 /*1383 * Hardcoded terms should be already in, so nothing1384 * to be done for them.1385 */1386 if (parse_events__is_hardcoded_term(term))1387 return 0;1388 1389 format = pmu_find_format(&pmu->format, term->config);1390 if (!format) {1391 char *pmu_term = pmu_formats_string(&pmu->format);1392 char *unknown_term;1393 char *help_msg;1394 1395 if (asprintf(&unknown_term,1396 "unknown term '%s' for pmu '%s'",1397 term->config, pmu->name) < 0)1398 unknown_term = NULL;1399 help_msg = parse_events_formats_error_string(pmu_term);1400 if (err) {1401 parse_events_error__handle(err, term->err_term,1402 unknown_term,1403 help_msg);1404 } else {1405 pr_debug("%s (%s)\n", unknown_term, help_msg);1406 free(unknown_term);1407 }1408 free(pmu_term);1409 return -EINVAL;1410 }1411 perf_pmu_format__load(pmu, format);1412 switch (format->value) {1413 case PERF_PMU_FORMAT_VALUE_CONFIG:1414 vp = &attr->config;1415 break;1416 case PERF_PMU_FORMAT_VALUE_CONFIG1:1417 vp = &attr->config1;1418 break;1419 case PERF_PMU_FORMAT_VALUE_CONFIG2:1420 vp = &attr->config2;1421 break;1422 case PERF_PMU_FORMAT_VALUE_CONFIG3:1423 vp = &attr->config3;1424 break;1425 default:1426 return -EINVAL;1427 }1428 1429 /*1430 * Either directly use a numeric term, or try to translate string terms1431 * using event parameters.1432 */1433 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {1434 if (term->no_value &&1435 bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) {1436 if (err) {1437 parse_events_error__handle(err, term->err_val,1438 strdup("no value assigned for term"),1439 NULL);1440 }1441 return -EINVAL;1442 }1443 1444 val = term->val.num;1445 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {1446 if (strcmp(term->val.str, "?")) {1447 if (verbose > 0) {1448 pr_info("Invalid sysfs entry %s=%s\n",1449 term->config, term->val.str);1450 }1451 if (err) {1452 parse_events_error__handle(err, term->err_val,1453 strdup("expected numeric value"),1454 NULL);1455 }1456 return -EINVAL;1457 }1458 1459 if (pmu_resolve_param_term(term, head_terms, &val))1460 return -EINVAL;1461 } else1462 return -EINVAL;1463 1464 max_val = pmu_format_max_value(format->bits);1465 if (val > max_val) {1466 if (err) {1467 char *err_str;1468 1469 parse_events_error__handle(err, term->err_val,1470 asprintf(&err_str,1471 "value too big for format (%s), maximum is %llu",1472 format->name, (unsigned long long)max_val) < 01473 ? strdup("value too big for format")1474 : err_str,1475 NULL);1476 return -EINVAL;1477 }1478 /*1479 * Assume we don't care if !err, in which case the value will be1480 * silently truncated.1481 */1482 }1483 1484 pmu_format_value(format->bits, val, vp, zero);1485 return 0;1486}1487 1488int perf_pmu__config_terms(const struct perf_pmu *pmu,1489 struct perf_event_attr *attr,1490 struct parse_events_terms *terms,1491 bool zero, struct parse_events_error *err)1492{1493 struct parse_events_term *term;1494 1495 list_for_each_entry(term, &terms->terms, list) {1496 if (pmu_config_term(pmu, attr, term, terms, zero, err))1497 return -EINVAL;1498 }1499 1500 return 0;1501}1502 1503/*1504 * Configures event's 'attr' parameter based on the:1505 * 1) users input - specified in terms parameter1506 * 2) pmu format definitions - specified by pmu parameter1507 */1508int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,1509 struct parse_events_terms *head_terms,1510 struct parse_events_error *err)1511{1512 bool zero = !!pmu->perf_event_attr_init_default;1513 1514 /* Fake PMU doesn't have proper terms so nothing to configure in attr. */1515 if (perf_pmu__is_fake(pmu))1516 return 0;1517 1518 return perf_pmu__config_terms(pmu, attr, head_terms, zero, err);1519}1520 1521static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,1522 struct parse_events_term *term)1523{1524 struct perf_pmu_alias *alias;1525 const char *name;1526 1527 if (parse_events__is_hardcoded_term(term))1528 return NULL;1529 1530 if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {1531 if (!term->no_value)1532 return NULL;1533 if (pmu_find_format(&pmu->format, term->config))1534 return NULL;1535 name = term->config;1536 1537 } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {1538 if (strcasecmp(term->config, "event"))1539 return NULL;1540 name = term->val.str;1541 } else {1542 return NULL;1543 }1544 1545 alias = perf_pmu__find_alias(pmu, name, /*load=*/ true);1546 if (alias || pmu->cpu_aliases_added)1547 return alias;1548 1549 /* Alias doesn't exist, try to get it from the json events. */1550 if (pmu->events_table &&1551 pmu_events_table__find_event(pmu->events_table, pmu, name,1552 pmu_add_cpu_aliases_map_callback,1553 pmu) == 0) {1554 alias = perf_pmu__find_alias(pmu, name, /*load=*/ false);1555 }1556 return alias;1557}1558 1559 1560static int check_info_data(struct perf_pmu *pmu,1561 struct perf_pmu_alias *alias,1562 struct perf_pmu_info *info,1563 struct parse_events_error *err,1564 int column)1565{1566 read_alias_info(pmu, alias);1567 /*1568 * Only one term in event definition can1569 * define unit, scale and snapshot, fail1570 * if there's more than one.1571 */1572 if (info->unit && alias->unit[0]) {1573 parse_events_error__handle(err, column,1574 strdup("Attempt to set event's unit twice"),1575 NULL);1576 return -EINVAL;1577 }1578 if (info->scale && alias->scale) {1579 parse_events_error__handle(err, column,1580 strdup("Attempt to set event's scale twice"),1581 NULL);1582 return -EINVAL;1583 }1584 if (info->snapshot && alias->snapshot) {1585 parse_events_error__handle(err, column,1586 strdup("Attempt to set event snapshot twice"),1587 NULL);1588 return -EINVAL;1589 }1590 1591 if (alias->unit[0])1592 info->unit = alias->unit;1593 1594 if (alias->scale)1595 info->scale = alias->scale;1596 1597 if (alias->snapshot)1598 info->snapshot = alias->snapshot;1599 1600 return 0;1601}1602 1603/*1604 * Find alias in the terms list and replace it with the terms1605 * defined for the alias1606 */1607int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms,1608 struct perf_pmu_info *info, bool *rewrote_terms,1609 struct parse_events_error *err)1610{1611 struct parse_events_term *term, *h;1612 struct perf_pmu_alias *alias;1613 int ret;1614 1615 *rewrote_terms = false;1616 info->per_pkg = false;1617 1618 /*1619 * Mark unit and scale as not set1620 * (different from default values, see below)1621 */1622 info->unit = NULL;1623 info->scale = 0.0;1624 info->snapshot = false;1625 1626 /* Fake PMU doesn't rewrite terms. */1627 if (perf_pmu__is_fake(pmu))1628 goto out;1629 1630 list_for_each_entry_safe(term, h, &head_terms->terms, list) {1631 alias = pmu_find_alias(pmu, term);1632 if (!alias)1633 continue;1634 ret = pmu_alias_terms(alias, term->err_term, &term->list);1635 if (ret) {1636 parse_events_error__handle(err, term->err_term,1637 strdup("Failure to duplicate terms"),1638 NULL);1639 return ret;1640 }1641 *rewrote_terms = true;1642 ret = check_info_data(pmu, alias, info, err, term->err_term);1643 if (ret)1644 return ret;1645 1646 if (alias->per_pkg)1647 info->per_pkg = true;1648 1649 list_del_init(&term->list);1650 parse_events_term__delete(term);1651 }1652out:1653 /*1654 * if no unit or scale found in aliases, then1655 * set defaults as for evsel1656 * unit cannot left to NULL1657 */1658 if (info->unit == NULL)1659 info->unit = "";1660 1661 if (info->scale == 0.0)1662 info->scale = 1.0;1663 1664 return 0;1665}1666 1667struct find_event_args {1668 const char *event;1669 void *state;1670 pmu_event_callback cb;1671};1672 1673static int find_event_callback(void *state, struct pmu_event_info *info)1674{1675 struct find_event_args *args = state;1676 1677 if (!strcmp(args->event, info->name))1678 return args->cb(args->state, info);1679 1680 return 0;1681}1682 1683int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb)1684{1685 struct find_event_args args = {1686 .event = event,1687 .state = state,1688 .cb = cb,1689 };1690 1691 /* Sub-optimal, but function is only used by tests. */1692 return perf_pmu__for_each_event(pmu, /*skip_duplicate_pmus=*/ false,1693 &args, find_event_callback);1694}1695 1696static void perf_pmu__del_formats(struct list_head *formats)1697{1698 struct perf_pmu_format *fmt, *tmp;1699 1700 list_for_each_entry_safe(fmt, tmp, formats, list) {1701 list_del(&fmt->list);1702 zfree(&fmt->name);1703 free(fmt);1704 }1705}1706 1707bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name)1708{1709 struct perf_pmu_format *format;1710 1711 list_for_each_entry(format, &pmu->format, list) {1712 if (!strcmp(format->name, name))1713 return true;1714 }1715 return false;1716}1717 1718int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_callback cb)1719{1720 static const char *const terms[] = {1721 "config=0..0xffffffffffffffff",1722 "config1=0..0xffffffffffffffff",1723 "config2=0..0xffffffffffffffff",1724 "config3=0..0xffffffffffffffff",1725 "name=string",1726 "period=number",1727 "freq=number",1728 "branch_type=(u|k|hv|any|...)",1729 "time",1730 "call-graph=(fp|dwarf|lbr)",1731 "stack-size=number",1732 "max-stack=number",1733 "nr=number",1734 "inherit",1735 "no-inherit",1736 "overwrite",1737 "no-overwrite",1738 "percore",1739 "aux-output",1740 "aux-sample-size=number",1741 };1742 struct perf_pmu_format *format;1743 int ret;1744 1745 /*1746 * max-events and driver-config are missing above as are the internal1747 * types user, metric-id, raw, legacy cache and hardware. Assert against1748 * the enum parse_events__term_type so they are kept in sync.1749 */1750 _Static_assert(ARRAY_SIZE(terms) == __PARSE_EVENTS__TERM_TYPE_NR - 6,1751 "perf_pmu__for_each_format()'s terms must be kept in sync with enum parse_events__term_type");1752 list_for_each_entry(format, &pmu->format, list) {1753 perf_pmu_format__load(pmu, format);1754 ret = cb(state, format->name, (int)format->value, format->bits);1755 if (ret)1756 return ret;1757 }1758 if (!pmu->is_core)1759 return 0;1760 1761 for (size_t i = 0; i < ARRAY_SIZE(terms); i++) {1762 int config = PERF_PMU_FORMAT_VALUE_CONFIG;1763 1764 if (i < PERF_PMU_FORMAT_VALUE_CONFIG_END)1765 config = i;1766 1767 ret = cb(state, terms[i], config, /*bits=*/NULL);1768 if (ret)1769 return ret;1770 }1771 return 0;1772}1773 1774bool is_pmu_core(const char *name)1775{1776 return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name);1777}1778 1779bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu)1780{1781 return pmu->is_core;1782}1783 1784bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu)1785{1786 return !pmu->is_core || perf_pmus__num_core_pmus() == 1;1787}1788 1789bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)1790{1791 if (!name)1792 return false;1793 if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL)1794 return true;1795 if (pmu->cpu_aliases_added || !pmu->events_table)1796 return false;1797 return pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0;1798}1799 1800size_t perf_pmu__num_events(struct perf_pmu *pmu)1801{1802 size_t nr;1803 1804 pmu_aliases_parse(pmu);1805 nr = pmu->sysfs_aliases + pmu->sys_json_aliases;1806 1807 if (pmu->cpu_aliases_added)1808 nr += pmu->cpu_json_aliases;1809 else if (pmu->events_table)1810 nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->cpu_json_aliases;1811 else1812 assert(pmu->cpu_json_aliases == 0);1813 1814 return pmu->selectable ? nr + 1 : nr;1815}1816 1817static int sub_non_neg(int a, int b)1818{1819 if (b > a)1820 return 0;1821 return a - b;1822}1823 1824static char *format_alias(char *buf, int len, const struct perf_pmu *pmu,1825 const struct perf_pmu_alias *alias, bool skip_duplicate_pmus)1826{1827 struct parse_events_term *term;1828 size_t pmu_name_len = pmu_deduped_name_len(pmu, pmu->name,1829 skip_duplicate_pmus);1830 int used = snprintf(buf, len, "%.*s/%s", (int)pmu_name_len, pmu->name, alias->name);1831 1832 list_for_each_entry(term, &alias->terms.terms, list) {1833 if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)1834 used += snprintf(buf + used, sub_non_neg(len, used),1835 ",%s=%s", term->config,1836 term->val.str);1837 }1838 1839 if (sub_non_neg(len, used) > 0) {1840 buf[used] = '/';1841 used++;1842 }1843 if (sub_non_neg(len, used) > 0) {1844 buf[used] = '\0';1845 used++;1846 } else1847 buf[len - 1] = '\0';1848 1849 return buf;1850}1851 1852int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,1853 void *state, pmu_event_callback cb)1854{1855 char buf[1024];1856 struct perf_pmu_alias *event;1857 struct pmu_event_info info = {1858 .pmu = pmu,1859 .event_type_desc = "Kernel PMU event",1860 };1861 int ret = 0;1862 struct strbuf sb;1863 1864 strbuf_init(&sb, /*hint=*/ 0);1865 pmu_aliases_parse(pmu);1866 pmu_add_cpu_aliases(pmu);1867 list_for_each_entry(event, &pmu->aliases, list) {1868 size_t buf_used, pmu_name_len;1869 1870 info.pmu_name = event->pmu_name ?: pmu->name;1871 pmu_name_len = pmu_deduped_name_len(pmu, info.pmu_name,1872 skip_duplicate_pmus);1873 info.alias = NULL;1874 if (event->desc) {1875 info.name = event->name;1876 buf_used = 0;1877 } else {1878 info.name = format_alias(buf, sizeof(buf), pmu, event,1879 skip_duplicate_pmus);1880 if (pmu->is_core) {1881 info.alias = info.name;1882 info.name = event->name;1883 }1884 buf_used = strlen(buf) + 1;1885 }1886 info.scale_unit = NULL;1887 if (strlen(event->unit) || event->scale != 1.0) {1888 info.scale_unit = buf + buf_used;1889 buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,1890 "%G%s", event->scale, event->unit) + 1;1891 }1892 info.desc = event->desc;1893 info.long_desc = event->long_desc;1894 info.encoding_desc = buf + buf_used;1895 parse_events_terms__to_strbuf(&event->terms, &sb);1896 buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used,1897 "%.*s/%s/", (int)pmu_name_len, info.pmu_name, sb.buf) + 1;1898 info.topic = event->topic;1899 info.str = sb.buf;1900 info.deprecated = event->deprecated;1901 ret = cb(state, &info);1902 if (ret)1903 goto out;1904 strbuf_setlen(&sb, /*len=*/ 0);1905 }1906 if (pmu->selectable) {1907 info.name = buf;1908 snprintf(buf, sizeof(buf), "%s//", pmu->name);1909 info.alias = NULL;1910 info.scale_unit = NULL;1911 info.desc = NULL;1912 info.long_desc = NULL;1913 info.encoding_desc = NULL;1914 info.topic = NULL;1915 info.pmu_name = pmu->name;1916 info.deprecated = false;1917 ret = cb(state, &info);1918 }1919out:1920 strbuf_release(&sb);1921 return ret;1922}1923 1924bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name)1925{1926 return !strcmp(pmu->name, pmu_name) ||1927 (pmu->is_uncore && pmu_uncore_alias_match(pmu_name, pmu->name)) ||1928 /*1929 * jevents and tests use default_core as a marker for any core1930 * PMU as the PMU name varies across architectures.1931 */1932 (pmu->is_core && !strcmp(pmu_name, "default_core"));1933}1934 1935bool perf_pmu__is_software(const struct perf_pmu *pmu)1936{1937 const char *known_sw_pmus[] = {1938 "kprobe",1939 "msr",1940 "uprobe",1941 };1942 1943 if (pmu->is_core || pmu->is_uncore || pmu->auxtrace)1944 return false;1945 switch (pmu->type) {1946 case PERF_TYPE_HARDWARE: return false;1947 case PERF_TYPE_SOFTWARE: return true;1948 case PERF_TYPE_TRACEPOINT: return true;1949 case PERF_TYPE_HW_CACHE: return false;1950 case PERF_TYPE_RAW: return false;1951 case PERF_TYPE_BREAKPOINT: return true;1952 default: break;1953 }1954 for (size_t i = 0; i < ARRAY_SIZE(known_sw_pmus); i++) {1955 if (!strcmp(pmu->name, known_sw_pmus[i]))1956 return true;1957 }1958 return false;1959}1960 1961FILE *perf_pmu__open_file(const struct perf_pmu *pmu, const char *name)1962{1963 char path[PATH_MAX];1964 1965 if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name) ||1966 !file_available(path))1967 return NULL;1968 1969 return fopen(path, "r");1970}1971 1972FILE *perf_pmu__open_file_at(const struct perf_pmu *pmu, int dirfd, const char *name)1973{1974 int fd;1975 1976 fd = perf_pmu__pathname_fd(dirfd, pmu->name, name, O_RDONLY);1977 if (fd < 0)1978 return NULL;1979 1980 return fdopen(fd, "r");1981}1982 1983int perf_pmu__scan_file(const struct perf_pmu *pmu, const char *name, const char *fmt,1984 ...)1985{1986 va_list args;1987 FILE *file;1988 int ret = EOF;1989 1990 va_start(args, fmt);1991 file = perf_pmu__open_file(pmu, name);1992 if (file) {1993 ret = vfscanf(file, fmt, args);1994 fclose(file);1995 }1996 va_end(args);1997 return ret;1998}1999 2000int perf_pmu__scan_file_at(const struct perf_pmu *pmu, int dirfd, const char *name,2001 const char *fmt, ...)2002{2003 va_list args;2004 FILE *file;2005 int ret = EOF;2006 2007 va_start(args, fmt);2008 file = perf_pmu__open_file_at(pmu, dirfd, name);2009 if (file) {2010 ret = vfscanf(file, fmt, args);2011 fclose(file);2012 }2013 va_end(args);2014 return ret;2015}2016 2017bool perf_pmu__file_exists(const struct perf_pmu *pmu, const char *name)2018{2019 char path[PATH_MAX];2020 2021 if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name))2022 return false;2023 2024 return file_available(path);2025}2026 2027static int perf_pmu__new_caps(struct list_head *list, char *name, char *value)2028{2029 struct perf_pmu_caps *caps = zalloc(sizeof(*caps));2030 2031 if (!caps)2032 return -ENOMEM;2033 2034 caps->name = strdup(name);2035 if (!caps->name)2036 goto free_caps;2037 caps->value = strndup(value, strlen(value) - 1);2038 if (!caps->value)2039 goto free_name;2040 list_add_tail(&caps->list, list);2041 return 0;2042 2043free_name:2044 zfree(&caps->name);2045free_caps:2046 free(caps);2047 2048 return -ENOMEM;2049}2050 2051static void perf_pmu__del_caps(struct perf_pmu *pmu)2052{2053 struct perf_pmu_caps *caps, *tmp;2054 2055 list_for_each_entry_safe(caps, tmp, &pmu->caps, list) {2056 list_del(&caps->list);2057 zfree(&caps->name);2058 zfree(&caps->value);2059 free(caps);2060 }2061}2062 2063/*2064 * Reading/parsing the given pmu capabilities, which should be located at:2065 * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes.2066 * Return the number of capabilities2067 */2068int perf_pmu__caps_parse(struct perf_pmu *pmu)2069{2070 struct stat st;2071 char caps_path[PATH_MAX];2072 DIR *caps_dir;2073 struct dirent *evt_ent;2074 int caps_fd;2075 2076 if (pmu->caps_initialized)2077 return pmu->nr_caps;2078 2079 pmu->nr_caps = 0;2080 2081 if (!perf_pmu__pathname_scnprintf(caps_path, sizeof(caps_path), pmu->name, "caps"))2082 return -1;2083 2084 if (stat(caps_path, &st) < 0) {2085 pmu->caps_initialized = true;2086 return 0; /* no error if caps does not exist */2087 }2088 2089 caps_dir = opendir(caps_path);2090 if (!caps_dir)2091 return -EINVAL;2092 2093 caps_fd = dirfd(caps_dir);2094 2095 while ((evt_ent = readdir(caps_dir)) != NULL) {2096 char *name = evt_ent->d_name;2097 char value[128];2098 FILE *file;2099 int fd;2100 2101 if (!strcmp(name, ".") || !strcmp(name, ".."))2102 continue;2103 2104 fd = openat(caps_fd, name, O_RDONLY);2105 if (fd == -1)2106 continue;2107 file = fdopen(fd, "r");2108 if (!file) {2109 close(fd);2110 continue;2111 }2112 2113 if (!fgets(value, sizeof(value), file) ||2114 (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) {2115 fclose(file);2116 continue;2117 }2118 2119 pmu->nr_caps++;2120 fclose(file);2121 }2122 2123 closedir(caps_dir);2124 2125 pmu->caps_initialized = true;2126 return pmu->nr_caps;2127}2128 2129static void perf_pmu__compute_config_masks(struct perf_pmu *pmu)2130{2131 struct perf_pmu_format *format;2132 2133 if (pmu->config_masks_computed)2134 return;2135 2136 list_for_each_entry(format, &pmu->format, list) {2137 unsigned int i;2138 __u64 *mask;2139 2140 if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END)2141 continue;2142 2143 pmu->config_masks_present = true;2144 mask = &pmu->config_masks[format->value];2145 2146 for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS)2147 *mask |= 1ULL << i;2148 }2149 pmu->config_masks_computed = true;2150}2151 2152void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,2153 const char *name, int config_num,2154 const char *config_name)2155{2156 __u64 bits;2157 char buf[100];2158 2159 perf_pmu__compute_config_masks(pmu);2160 2161 /*2162 * Kernel doesn't export any valid format bits.2163 */2164 if (!pmu->config_masks_present)2165 return;2166 2167 bits = config & ~pmu->config_masks[config_num];2168 if (bits == 0)2169 return;2170 2171 bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf));2172 2173 pr_warning("WARNING: event '%s' not valid (bits %s of %s "2174 "'%llx' not supported by kernel)!\n",2175 name ?: "N/A", buf, config_name, config);2176}2177 2178bool perf_pmu__match(const struct perf_pmu *pmu, const char *tok)2179{2180 const char *name = pmu->name;2181 bool need_fnmatch = strisglob(tok);2182 2183 if (!strncmp(tok, "uncore_", 7))2184 tok += 7;2185 if (!strncmp(name, "uncore_", 7))2186 name += 7;2187 2188 if (perf_pmu__match_ignoring_suffix(name, tok) ||2189 (need_fnmatch && !fnmatch(tok, name, 0)))2190 return true;2191 2192 name = pmu->alias_name;2193 if (!name)2194 return false;2195 2196 if (!strncmp(name, "uncore_", 7))2197 name += 7;2198 2199 return perf_pmu__match_ignoring_suffix(name, tok) ||2200 (need_fnmatch && !fnmatch(tok, name, 0));2201}2202 2203double __weak perf_pmu__cpu_slots_per_cycle(void)2204{2205 return NAN;2206}2207 2208int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size)2209{2210 const char *sysfs = sysfs__mountpoint();2211 2212 if (!sysfs)2213 return 0;2214 return scnprintf(pathname, size, "%s/bus/event_source/devices/", sysfs);2215}2216 2217int perf_pmu__event_source_devices_fd(void)2218{2219 char path[PATH_MAX];2220 const char *sysfs = sysfs__mountpoint();2221 2222 if (!sysfs)2223 return -1;2224 2225 scnprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs);2226 return open(path, O_DIRECTORY);2227}2228 2229/*2230 * Fill 'buf' with the path to a file or folder in 'pmu_name' in2231 * sysfs. For example if pmu_name = "cs_etm" and 'filename' = "format"2232 * then pathname will be filled with2233 * "/sys/bus/event_source/devices/cs_etm/format"2234 *2235 * Return 0 if the sysfs mountpoint couldn't be found, if no characters were2236 * written or if the buffer size is exceeded.2237 */2238int perf_pmu__pathname_scnprintf(char *buf, size_t size,2239 const char *pmu_name, const char *filename)2240{2241 size_t len;2242 2243 len = perf_pmu__event_source_devices_scnprintf(buf, size);2244 if (!len || (len + strlen(pmu_name) + strlen(filename) + 1) >= size)2245 return 0;2246 2247 return scnprintf(buf + len, size - len, "%s/%s", pmu_name, filename);2248}2249 2250int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags)2251{2252 char path[PATH_MAX];2253 2254 scnprintf(path, sizeof(path), "%s/%s", pmu_name, filename);2255 return openat(dirfd, path, flags);2256}2257 2258void perf_pmu__delete(struct perf_pmu *pmu)2259{2260 perf_pmu__del_formats(&pmu->format);2261 perf_pmu__del_aliases(pmu);2262 perf_pmu__del_caps(pmu);2263 2264 perf_cpu_map__put(pmu->cpus);2265 2266 zfree(&pmu->name);2267 zfree(&pmu->alias_name);2268 zfree(&pmu->id);2269 free(pmu);2270}2271 2272const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config)2273{2274 struct perf_pmu_alias *event;2275 2276 if (!pmu)2277 return NULL;2278 2279 pmu_aliases_parse(pmu);2280 pmu_add_cpu_aliases(pmu);2281 list_for_each_entry(event, &pmu->aliases, list) {2282 struct perf_event_attr attr = {.config = 0,};2283 int ret = perf_pmu__config(pmu, &attr, &event->terms, NULL);2284 2285 if (ret == 0 && config == attr.config)2286 return event->name;2287 }2288 return NULL;2289}2290