1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2cd82a32eSJiri Olsa #include <linux/list.h> 3c5de47f2SSukadev Bhattiprolu #include <linux/compiler.h> 432858480SArnaldo Carvalho de Melo #include <linux/string.h> 57f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h> 6c47a5599SJin Yao #include <linux/ctype.h> 7cd82a32eSJiri Olsa #include <sys/types.h> 8c23c2a0fSArnaldo Carvalho de Melo #include <fcntl.h> 97a8ef4c4SArnaldo Carvalho de Melo #include <sys/stat.h> 10cd82a32eSJiri Olsa #include <unistd.h> 11cd82a32eSJiri Olsa #include <stdio.h> 12dc0a6202SAdrian Hunter #include <stdbool.h> 13cd82a32eSJiri Olsa #include <dirent.h> 14cd0cfad7SBorislav Petkov #include <api/fs/fs.h> 15410136f5SStephane Eranian #include <locale.h> 16c47a5599SJin Yao #include <fnmatch.h> 17acef233bSJing Zhang #include <math.h> 185e51b0bbSArnaldo Carvalho de Melo #include "debug.h" 19e12ee9f7SAdrian Hunter #include "evsel.h" 20cd82a32eSJiri Olsa #include "pmu.h" 21336b92daSRavi Bangoria #include "pmus.h" 22c7e97f21SNamhyung Kim #include <util/pmu-bison.h> 23c7e97f21SNamhyung Kim #include <util/pmu-flex.h> 24cd82a32eSJiri Olsa #include "parse-events.h" 25e5c6109fSIan Rogers #include "print-events.h" 26933f82ffSSukadev Bhattiprolu #include "header.h" 27a067558eSArnaldo Carvalho de Melo #include "string2.h" 28fa0d9846SArnaldo Carvalho de Melo #include "strbuf.h" 29d9664582SAndi Kleen #include "fncache.h" 306593f019SJames Clark #include "util/evsel_config.h" 31cd82a32eSJiri Olsa 32c091ee90SIan Rogers struct perf_pmu perf_pmu__fake = { 33c091ee90SIan Rogers .name = "fake", 34c091ee90SIan Rogers }; 35e46fc8d9SArnaldo Carvalho de Melo 36c3245d20SIan Rogers #define UNIT_MAX_LEN 31 /* max length for event unit name */ 37c3245d20SIan Rogers 38c3245d20SIan Rogers /** 39c3245d20SIan Rogers * struct perf_pmu_alias - An event either read from sysfs or builtin in 40c3245d20SIan Rogers * pmu-events.c, created by parsing the pmu-events json files. 41c3245d20SIan Rogers */ 42c3245d20SIan Rogers struct perf_pmu_alias { 43c3245d20SIan Rogers /** @name: Name of the event like "mem-loads". */ 44c3245d20SIan Rogers char *name; 45c3245d20SIan Rogers /** @desc: Optional short description of the event. */ 46c3245d20SIan Rogers char *desc; 47c3245d20SIan Rogers /** @long_desc: Optional long description. */ 48c3245d20SIan Rogers char *long_desc; 49c3245d20SIan Rogers /** 50c3245d20SIan Rogers * @topic: Optional topic such as cache or pipeline, particularly for 51c3245d20SIan Rogers * json events. 52c3245d20SIan Rogers */ 53c3245d20SIan Rogers char *topic; 54c3245d20SIan Rogers /** 55c3245d20SIan Rogers * @str: Comma separated parameter list like 56c3245d20SIan Rogers * "event=0xcd,umask=0x1,ldlat=0x3". 57c3245d20SIan Rogers */ 58c3245d20SIan Rogers char *str; 59c3245d20SIan Rogers /** @terms: Owned list of the original parsed parameters. */ 60c3245d20SIan Rogers struct list_head terms; 61c3245d20SIan Rogers /** @list: List element of struct perf_pmu aliases. */ 62c3245d20SIan Rogers struct list_head list; 637b723dbbSIan Rogers /** 647b723dbbSIan Rogers * @pmu_name: The name copied from the json struct pmu_event. This can 657b723dbbSIan Rogers * differ from the PMU name as it won't have suffixes. 667b723dbbSIan Rogers */ 677b723dbbSIan Rogers char *pmu_name; 68c3245d20SIan Rogers /** @unit: Units for the event, such as bytes or cache lines. */ 69c3245d20SIan Rogers char unit[UNIT_MAX_LEN+1]; 70c3245d20SIan Rogers /** @scale: Value to scale read counter values by. */ 71c3245d20SIan Rogers double scale; 72c3245d20SIan Rogers /** 73c3245d20SIan Rogers * @per_pkg: Does the file 74c3245d20SIan Rogers * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.per-pkg or 75c3245d20SIan Rogers * equivalent json value exist and have the value 1. 76c3245d20SIan Rogers */ 77c3245d20SIan Rogers bool per_pkg; 78c3245d20SIan Rogers /** 79c3245d20SIan Rogers * @snapshot: Does the file 80c3245d20SIan Rogers * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.snapshot 81c3245d20SIan Rogers * exist and have the value 1. 82c3245d20SIan Rogers */ 83c3245d20SIan Rogers bool snapshot; 84c3245d20SIan Rogers /** 85c3245d20SIan Rogers * @deprecated: Is the event hidden and so not shown in perf list by 86c3245d20SIan Rogers * default. 87c3245d20SIan Rogers */ 88c3245d20SIan Rogers bool deprecated; 897b723dbbSIan Rogers /** @from_sysfs: Was the alias from sysfs or a json event? */ 907b723dbbSIan Rogers bool from_sysfs; 917b723dbbSIan Rogers /** @info_loaded: Have the scale, unit and other values been read from disk? */ 927b723dbbSIan Rogers bool info_loaded; 93c3245d20SIan Rogers }; 94c3245d20SIan Rogers 95fe13d43dSIan Rogers /** 96fe13d43dSIan Rogers * struct perf_pmu_format - Values from a format file read from 97fe13d43dSIan Rogers * <sysfs>/devices/cpu/format/ held in struct perf_pmu. 98fe13d43dSIan Rogers * 99fe13d43dSIan Rogers * For example, the contents of <sysfs>/devices/cpu/format/event may be 100fe13d43dSIan Rogers * "config:0-7" and will be represented here as name="event", 101fe13d43dSIan Rogers * value=PERF_PMU_FORMAT_VALUE_CONFIG and bits 0 to 7 will be set. 102fe13d43dSIan Rogers */ 103ab1bf653SArnaldo Carvalho de Melo struct perf_pmu_format { 10450402641SIan Rogers /** @list: Element on list within struct perf_pmu. */ 10550402641SIan Rogers struct list_head list; 10650402641SIan Rogers /** @bits: Which config bits are set by this format value. */ 10750402641SIan Rogers DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); 108fe13d43dSIan Rogers /** @name: The modifier/file name. */ 109ab1bf653SArnaldo Carvalho de Melo char *name; 110fe13d43dSIan Rogers /** 111fe13d43dSIan Rogers * @value : Which config value the format relates to. Supported values 112fe13d43dSIan Rogers * are from PERF_PMU_FORMAT_VALUE_CONFIG to 113fe13d43dSIan Rogers * PERF_PMU_FORMAT_VALUE_CONFIG_END. 114fe13d43dSIan Rogers */ 11550402641SIan Rogers u16 value; 11650402641SIan Rogers /** @loaded: Has the contents been loaded/parsed. */ 11750402641SIan Rogers bool loaded; 118ab1bf653SArnaldo Carvalho de Melo }; 119ab1bf653SArnaldo Carvalho de Melo 1208d4b6d37SIan Rogers static int pmu_aliases_parse(struct perf_pmu *pmu); 1218d4b6d37SIan Rogers 12250402641SIan Rogers static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name) 12350402641SIan Rogers { 12450402641SIan Rogers struct perf_pmu_format *format; 12550402641SIan Rogers 12650402641SIan Rogers format = zalloc(sizeof(*format)); 12750402641SIan Rogers if (!format) 12850402641SIan Rogers return NULL; 12950402641SIan Rogers 13050402641SIan Rogers format->name = strdup(name); 13150402641SIan Rogers if (!format->name) { 13250402641SIan Rogers free(format); 13350402641SIan Rogers return NULL; 13450402641SIan Rogers } 13550402641SIan Rogers list_add_tail(&format->list, list); 13650402641SIan Rogers return format; 13750402641SIan Rogers } 13850402641SIan Rogers 13950402641SIan Rogers /* Called at the end of parsing a format. */ 14050402641SIan Rogers void perf_pmu_format__set_value(void *vformat, int config, unsigned long *bits) 14150402641SIan Rogers { 14250402641SIan Rogers struct perf_pmu_format *format = vformat; 14350402641SIan Rogers 14450402641SIan Rogers format->value = config; 14550402641SIan Rogers memcpy(format->bits, bits, sizeof(format->bits)); 14650402641SIan Rogers } 14750402641SIan Rogers 14850402641SIan Rogers static void __perf_pmu_format__load(struct perf_pmu_format *format, FILE *file) 14950402641SIan Rogers { 15050402641SIan Rogers void *scanner; 15150402641SIan Rogers int ret; 15250402641SIan Rogers 15350402641SIan Rogers ret = perf_pmu_lex_init(&scanner); 15450402641SIan Rogers if (ret) 15550402641SIan Rogers return; 15650402641SIan Rogers 15750402641SIan Rogers perf_pmu_set_in(file, scanner); 15850402641SIan Rogers ret = perf_pmu_parse(format, scanner); 15950402641SIan Rogers perf_pmu_lex_destroy(scanner); 16050402641SIan Rogers format->loaded = true; 16150402641SIan Rogers } 16250402641SIan Rogers 16350402641SIan Rogers static void perf_pmu_format__load(struct perf_pmu *pmu, struct perf_pmu_format *format) 16450402641SIan Rogers { 16550402641SIan Rogers char path[PATH_MAX]; 16650402641SIan Rogers FILE *file = NULL; 16750402641SIan Rogers 16850402641SIan Rogers if (format->loaded) 16950402641SIan Rogers return; 17050402641SIan Rogers 17150402641SIan Rogers if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, "format")) 17250402641SIan Rogers return; 17350402641SIan Rogers 17450402641SIan Rogers assert(strlen(path) + strlen(format->name) + 2 < sizeof(path)); 17550402641SIan Rogers strcat(path, "/"); 17650402641SIan Rogers strcat(path, format->name); 17750402641SIan Rogers 17850402641SIan Rogers file = fopen(path, "r"); 17950402641SIan Rogers if (!file) 18050402641SIan Rogers return; 18150402641SIan Rogers __perf_pmu_format__load(format, file); 18250402641SIan Rogers fclose(file); 18350402641SIan Rogers } 18450402641SIan Rogers 185cd82a32eSJiri Olsa /* 186cd82a32eSJiri Olsa * Parse & process all the sysfs attributes located under 187cd82a32eSJiri Olsa * the directory specified in 'dir' parameter. 188cd82a32eSJiri Olsa */ 18950402641SIan Rogers int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load) 190cd82a32eSJiri Olsa { 191cd82a32eSJiri Olsa struct dirent *evt_ent; 192cd82a32eSJiri Olsa DIR *format_dir; 193cd82a32eSJiri Olsa int ret = 0; 194cd82a32eSJiri Olsa 195e293a5e8SNamhyung Kim format_dir = fdopendir(dirfd); 196cd82a32eSJiri Olsa if (!format_dir) 197cd82a32eSJiri Olsa return -EINVAL; 198cd82a32eSJiri Olsa 19950402641SIan Rogers while ((evt_ent = readdir(format_dir)) != NULL) { 20050402641SIan Rogers struct perf_pmu_format *format; 201cd82a32eSJiri Olsa char *name = evt_ent->d_name; 202cd82a32eSJiri Olsa 203cd82a32eSJiri Olsa if (!strcmp(name, ".") || !strcmp(name, "..")) 204cd82a32eSJiri Olsa continue; 205cd82a32eSJiri Olsa 20650402641SIan Rogers format = perf_pmu__new_format(&pmu->format, name); 20750402641SIan Rogers if (!format) { 20850402641SIan Rogers ret = -ENOMEM; 209cd82a32eSJiri Olsa break; 21050402641SIan Rogers } 211cd82a32eSJiri Olsa 21250402641SIan Rogers if (eager_load) { 21350402641SIan Rogers FILE *file; 21450402641SIan Rogers int fd = openat(dirfd, name, O_RDONLY); 21550402641SIan Rogers 21650402641SIan Rogers if (fd < 0) { 21750402641SIan Rogers ret = -errno; 21850402641SIan Rogers break; 21950402641SIan Rogers } 2203d88aec0SIan Rogers file = fdopen(fd, "r"); 2213d88aec0SIan Rogers if (!file) { 2223d88aec0SIan Rogers close(fd); 2233d88aec0SIan Rogers break; 2243d88aec0SIan Rogers } 22550402641SIan Rogers __perf_pmu_format__load(format, file); 2263d88aec0SIan Rogers fclose(file); 2273d88aec0SIan Rogers } 228cd82a32eSJiri Olsa } 229cd82a32eSJiri Olsa 230cd82a32eSJiri Olsa closedir(format_dir); 231cd82a32eSJiri Olsa return ret; 232cd82a32eSJiri Olsa } 233cd82a32eSJiri Olsa 234cd82a32eSJiri Olsa /* 235cd82a32eSJiri Olsa * Reading/parsing the default pmu format definition, which should be 236cd82a32eSJiri Olsa * located at: 237cd82a32eSJiri Olsa * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. 238cd82a32eSJiri Olsa */ 239838a8c5fSIan Rogers static int pmu_format(struct perf_pmu *pmu, int dirfd, const char *name) 240cd82a32eSJiri Olsa { 241e293a5e8SNamhyung Kim int fd; 242cd82a32eSJiri Olsa 243e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "format", O_DIRECTORY); 244e293a5e8SNamhyung Kim if (fd < 0) 245d9664582SAndi Kleen return 0; 246cd82a32eSJiri Olsa 247e293a5e8SNamhyung Kim /* it'll close the fd */ 24850402641SIan Rogers if (perf_pmu__format_parse(pmu, fd, /*eager_load=*/false)) 249cd82a32eSJiri Olsa return -1; 250cd82a32eSJiri Olsa 251cd82a32eSJiri Olsa return 0; 252cd82a32eSJiri Olsa } 253cd82a32eSJiri Olsa 254a55ab7c4SJin Yao int perf_pmu__convert_scale(const char *scale, char **end, double *sval) 255d02fc6bcSAndi Kleen { 256d02fc6bcSAndi Kleen char *lc; 257d02fc6bcSAndi Kleen int ret = 0; 258d02fc6bcSAndi Kleen 259d02fc6bcSAndi Kleen /* 260d02fc6bcSAndi Kleen * save current locale 261d02fc6bcSAndi Kleen */ 262d02fc6bcSAndi Kleen lc = setlocale(LC_NUMERIC, NULL); 263d02fc6bcSAndi Kleen 264d02fc6bcSAndi Kleen /* 265d02fc6bcSAndi Kleen * The lc string may be allocated in static storage, 266d02fc6bcSAndi Kleen * so get a dynamic copy to make it survive setlocale 267d02fc6bcSAndi Kleen * call below. 268d02fc6bcSAndi Kleen */ 269d02fc6bcSAndi Kleen lc = strdup(lc); 270d02fc6bcSAndi Kleen if (!lc) { 271d02fc6bcSAndi Kleen ret = -ENOMEM; 272d02fc6bcSAndi Kleen goto out; 273d02fc6bcSAndi Kleen } 274d02fc6bcSAndi Kleen 275d02fc6bcSAndi Kleen /* 276d02fc6bcSAndi Kleen * force to C locale to ensure kernel 277d02fc6bcSAndi Kleen * scale string is converted correctly. 278d02fc6bcSAndi Kleen * kernel uses default C locale. 279d02fc6bcSAndi Kleen */ 280d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, "C"); 281d02fc6bcSAndi Kleen 282d02fc6bcSAndi Kleen *sval = strtod(scale, end); 283d02fc6bcSAndi Kleen 284d02fc6bcSAndi Kleen out: 285d02fc6bcSAndi Kleen /* restore locale */ 286d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, lc); 287d02fc6bcSAndi Kleen free(lc); 288d02fc6bcSAndi Kleen return ret; 289d02fc6bcSAndi Kleen } 290d02fc6bcSAndi Kleen 2917b723dbbSIan Rogers static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 292410136f5SStephane Eranian { 293410136f5SStephane Eranian struct stat st; 294410136f5SStephane Eranian ssize_t sret; 2957b723dbbSIan Rogers size_t len; 296410136f5SStephane Eranian char scale[128]; 297410136f5SStephane Eranian int fd, ret = -1; 298410136f5SStephane Eranian char path[PATH_MAX]; 299410136f5SStephane Eranian 3007b723dbbSIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 3017b723dbbSIan Rogers if (!len) 3027b723dbbSIan Rogers return 0; 3037b723dbbSIan Rogers scnprintf(path + len, sizeof(path) - len, "%s/%s.scale", pmu->name, alias->name); 304410136f5SStephane Eranian 3057b723dbbSIan Rogers fd = open(path, O_RDONLY); 306410136f5SStephane Eranian if (fd == -1) 307410136f5SStephane Eranian return -1; 308410136f5SStephane Eranian 309410136f5SStephane Eranian if (fstat(fd, &st) < 0) 310410136f5SStephane Eranian goto error; 311410136f5SStephane Eranian 312410136f5SStephane Eranian sret = read(fd, scale, sizeof(scale)-1); 313410136f5SStephane Eranian if (sret < 0) 314410136f5SStephane Eranian goto error; 315410136f5SStephane Eranian 3169ecae065SMadhavan Srinivasan if (scale[sret - 1] == '\n') 3179ecae065SMadhavan Srinivasan scale[sret - 1] = '\0'; 3189ecae065SMadhavan Srinivasan else 319410136f5SStephane Eranian scale[sret] = '\0'; 3209ecae065SMadhavan Srinivasan 321a55ab7c4SJin Yao ret = perf_pmu__convert_scale(scale, NULL, &alias->scale); 322410136f5SStephane Eranian error: 323410136f5SStephane Eranian close(fd); 324410136f5SStephane Eranian return ret; 325410136f5SStephane Eranian } 326410136f5SStephane Eranian 3277b723dbbSIan Rogers static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 328410136f5SStephane Eranian { 329410136f5SStephane Eranian char path[PATH_MAX]; 3307b723dbbSIan Rogers size_t len; 331410136f5SStephane Eranian ssize_t sret; 332410136f5SStephane Eranian int fd; 333410136f5SStephane Eranian 334410136f5SStephane Eranian 3357b723dbbSIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 3367b723dbbSIan Rogers if (!len) 3377b723dbbSIan Rogers return 0; 3387b723dbbSIan Rogers scnprintf(path + len, sizeof(path) - len, "%s/%s.unit", pmu->name, alias->name); 3397b723dbbSIan Rogers 3407b723dbbSIan Rogers fd = open(path, O_RDONLY); 341410136f5SStephane Eranian if (fd == -1) 342410136f5SStephane Eranian return -1; 343410136f5SStephane Eranian 344410136f5SStephane Eranian sret = read(fd, alias->unit, UNIT_MAX_LEN); 345410136f5SStephane Eranian if (sret < 0) 346410136f5SStephane Eranian goto error; 347410136f5SStephane Eranian 348410136f5SStephane Eranian close(fd); 349410136f5SStephane Eranian 3509ecae065SMadhavan Srinivasan if (alias->unit[sret - 1] == '\n') 3519ecae065SMadhavan Srinivasan alias->unit[sret - 1] = '\0'; 3529ecae065SMadhavan Srinivasan else 353410136f5SStephane Eranian alias->unit[sret] = '\0'; 354410136f5SStephane Eranian 355410136f5SStephane Eranian return 0; 356410136f5SStephane Eranian error: 357410136f5SStephane Eranian close(fd); 358410136f5SStephane Eranian alias->unit[0] = '\0'; 359410136f5SStephane Eranian return -1; 360410136f5SStephane Eranian } 361410136f5SStephane Eranian 362044330c1SMatt Fleming static int 3637b723dbbSIan Rogers perf_pmu__parse_per_pkg(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 364044330c1SMatt Fleming { 365044330c1SMatt Fleming char path[PATH_MAX]; 3667b723dbbSIan Rogers size_t len; 367044330c1SMatt Fleming int fd; 368044330c1SMatt Fleming 3697b723dbbSIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 3707b723dbbSIan Rogers if (!len) 3717b723dbbSIan Rogers return 0; 3727b723dbbSIan Rogers scnprintf(path + len, sizeof(path) - len, "%s/%s.per-pkg", pmu->name, alias->name); 373044330c1SMatt Fleming 3747b723dbbSIan Rogers fd = open(path, O_RDONLY); 375044330c1SMatt Fleming if (fd == -1) 376044330c1SMatt Fleming return -1; 377044330c1SMatt Fleming 378044330c1SMatt Fleming close(fd); 379044330c1SMatt Fleming 380044330c1SMatt Fleming alias->per_pkg = true; 381044330c1SMatt Fleming return 0; 382044330c1SMatt Fleming } 383044330c1SMatt Fleming 3847b723dbbSIan Rogers static int perf_pmu__parse_snapshot(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 3851d9e446bSJiri Olsa { 3861d9e446bSJiri Olsa char path[PATH_MAX]; 3877b723dbbSIan Rogers size_t len; 3881d9e446bSJiri Olsa int fd; 3891d9e446bSJiri Olsa 3907b723dbbSIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 3917b723dbbSIan Rogers if (!len) 3927b723dbbSIan Rogers return 0; 3937b723dbbSIan Rogers scnprintf(path + len, sizeof(path) - len, "%s/%s.snapshot", pmu->name, alias->name); 3941d9e446bSJiri Olsa 3957b723dbbSIan Rogers fd = open(path, O_RDONLY); 3961d9e446bSJiri Olsa if (fd == -1) 3971d9e446bSJiri Olsa return -1; 3981d9e446bSJiri Olsa 3991d9e446bSJiri Olsa alias->snapshot = true; 4001d9e446bSJiri Olsa close(fd); 4011d9e446bSJiri Olsa return 0; 4021d9e446bSJiri Olsa } 4031d9e446bSJiri Olsa 4046dde6429SThomas Richter /* Delete an alias entry. */ 405c3245d20SIan Rogers static void perf_pmu_free_alias(struct perf_pmu_alias *newalias) 4066dde6429SThomas Richter { 4076dde6429SThomas Richter zfree(&newalias->name); 4086dde6429SThomas Richter zfree(&newalias->desc); 4096dde6429SThomas Richter zfree(&newalias->long_desc); 4106dde6429SThomas Richter zfree(&newalias->topic); 4116dde6429SThomas Richter zfree(&newalias->str); 41232705de7SJin Yao zfree(&newalias->pmu_name); 4136dde6429SThomas Richter parse_events_terms__purge(&newalias->terms); 4146dde6429SThomas Richter free(newalias); 4156dde6429SThomas Richter } 4166dde6429SThomas Richter 417eec11310SNamhyung Kim static void perf_pmu__del_aliases(struct perf_pmu *pmu) 418eec11310SNamhyung Kim { 419eec11310SNamhyung Kim struct perf_pmu_alias *alias, *tmp; 420eec11310SNamhyung Kim 421eec11310SNamhyung Kim list_for_each_entry_safe(alias, tmp, &pmu->aliases, list) { 422eec11310SNamhyung Kim list_del(&alias->list); 423eec11310SNamhyung Kim perf_pmu_free_alias(alias); 424eec11310SNamhyung Kim } 425eec11310SNamhyung Kim } 426eec11310SNamhyung Kim 4278d4b6d37SIan Rogers static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, 4288d4b6d37SIan Rogers const char *name, 4298d4b6d37SIan Rogers bool load) 4306dde6429SThomas Richter { 431f63a536fSIan Rogers struct perf_pmu_alias *alias; 4326dde6429SThomas Richter 4338d4b6d37SIan Rogers if (load && !pmu->sysfs_aliases_loaded) 4348d4b6d37SIan Rogers pmu_aliases_parse(pmu); 4358d4b6d37SIan Rogers 436f63a536fSIan Rogers list_for_each_entry(alias, &pmu->aliases, list) { 437f63a536fSIan Rogers if (!strcasecmp(alias->name, name)) 438f63a536fSIan Rogers return alias; 43932705de7SJin Yao } 440f63a536fSIan Rogers return NULL; 441f63a536fSIan Rogers } 442f63a536fSIan Rogers 443f63a536fSIan Rogers static bool assign_str(const char *name, const char *field, char **old_str, 444f63a536fSIan Rogers const char *new_str) 445f63a536fSIan Rogers { 446f63a536fSIan Rogers if (!*old_str && new_str) { 447f63a536fSIan Rogers *old_str = strdup(new_str); 4486dde6429SThomas Richter return true; 4496dde6429SThomas Richter } 450f63a536fSIan Rogers 451f63a536fSIan Rogers if (!new_str || !strcasecmp(*old_str, new_str)) 452f63a536fSIan Rogers return false; /* Nothing to update. */ 453f63a536fSIan Rogers 454f63a536fSIan Rogers pr_debug("alias %s differs in field '%s' ('%s' != '%s')\n", 455f63a536fSIan Rogers name, field, *old_str, new_str); 456f63a536fSIan Rogers zfree(old_str); 457f63a536fSIan Rogers *old_str = strdup(new_str); 458f63a536fSIan Rogers return true; 4596dde6429SThomas Richter } 460f63a536fSIan Rogers 4617b723dbbSIan Rogers static void read_alias_info(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 4627b723dbbSIan Rogers { 4637b723dbbSIan Rogers if (!alias->from_sysfs || alias->info_loaded) 4647b723dbbSIan Rogers return; 4657b723dbbSIan Rogers 4667b723dbbSIan Rogers /* 4677b723dbbSIan Rogers * load unit name and scale if available 4687b723dbbSIan Rogers */ 4697b723dbbSIan Rogers perf_pmu__parse_unit(pmu, alias); 4707b723dbbSIan Rogers perf_pmu__parse_scale(pmu, alias); 4717b723dbbSIan Rogers perf_pmu__parse_per_pkg(pmu, alias); 4727b723dbbSIan Rogers perf_pmu__parse_snapshot(pmu, alias); 4737b723dbbSIan Rogers } 4747b723dbbSIan Rogers 4757b723dbbSIan Rogers struct update_alias_data { 4767b723dbbSIan Rogers struct perf_pmu *pmu; 4777b723dbbSIan Rogers struct perf_pmu_alias *alias; 4787b723dbbSIan Rogers }; 4797b723dbbSIan Rogers 480f63a536fSIan Rogers static int update_alias(const struct pmu_event *pe, 481f63a536fSIan Rogers const struct pmu_events_table *table __maybe_unused, 482f63a536fSIan Rogers void *vdata) 483f63a536fSIan Rogers { 4847b723dbbSIan Rogers struct update_alias_data *data = vdata; 485f63a536fSIan Rogers int ret = 0; 486f63a536fSIan Rogers 4877b723dbbSIan Rogers read_alias_info(data->pmu, data->alias); 4887b723dbbSIan Rogers assign_str(pe->name, "desc", &data->alias->desc, pe->desc); 4897b723dbbSIan Rogers assign_str(pe->name, "long_desc", &data->alias->long_desc, pe->long_desc); 4907b723dbbSIan Rogers assign_str(pe->name, "topic", &data->alias->topic, pe->topic); 4917b723dbbSIan Rogers data->alias->per_pkg = pe->perpkg; 4927b723dbbSIan Rogers if (assign_str(pe->name, "value", &data->alias->str, pe->event)) { 4937b723dbbSIan Rogers parse_events_terms__purge(&data->alias->terms); 4947b723dbbSIan Rogers ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL); 495f63a536fSIan Rogers } 496f63a536fSIan Rogers if (!ret && pe->unit) { 497f63a536fSIan Rogers char *unit; 498f63a536fSIan Rogers 4997b723dbbSIan Rogers ret = perf_pmu__convert_scale(pe->unit, &unit, &data->alias->scale); 500f63a536fSIan Rogers if (!ret) 5017b723dbbSIan Rogers snprintf(data->alias->unit, sizeof(data->alias->unit), "%s", unit); 502f63a536fSIan Rogers } 503f63a536fSIan Rogers return ret; 5046dde6429SThomas Richter } 5056dde6429SThomas Richter 5067b723dbbSIan Rogers static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, 507edb217ffSIan Rogers const char *desc, const char *val, FILE *val_fd, 508edb217ffSIan Rogers const struct pmu_event *pe) 509a6146d50SZheng Yan { 5100c24d6fbSThomas Richter struct parse_events_term *term; 5115c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 512a6146d50SZheng Yan int ret; 5130c24d6fbSThomas Richter char newval[256]; 514330f40a0SIan Rogers const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL; 515bd680861SIan Rogers bool deprecated = false, perpkg = false; 516eab35953SJin Yao 5178d4b6d37SIan Rogers if (perf_pmu__find_alias(pmu, name, /*load=*/ false)) { 518f63a536fSIan Rogers /* Alias was already created/loaded. */ 519f63a536fSIan Rogers return 0; 520f63a536fSIan Rogers } 521f63a536fSIan Rogers 522eab35953SJin Yao if (pe) { 523330f40a0SIan Rogers long_desc = pe->long_desc; 524330f40a0SIan Rogers topic = pe->topic; 525330f40a0SIan Rogers unit = pe->unit; 526bd680861SIan Rogers perpkg = pe->perpkg; 5279ed8b7dcSIan Rogers deprecated = pe->deprecated; 528330f40a0SIan Rogers pmu_name = pe->pmu; 529eab35953SJin Yao } 530a6146d50SZheng Yan 531a6146d50SZheng Yan alias = malloc(sizeof(*alias)); 532a6146d50SZheng Yan if (!alias) 533a6146d50SZheng Yan return -ENOMEM; 534a6146d50SZheng Yan 535a6146d50SZheng Yan INIT_LIST_HEAD(&alias->terms); 536410136f5SStephane Eranian alias->scale = 1.0; 537410136f5SStephane Eranian alias->unit[0] = '\0'; 538bd680861SIan Rogers alias->per_pkg = perpkg; 53984530920SStephane Eranian alias->snapshot = false; 5409ed8b7dcSIan Rogers alias->deprecated = deprecated; 541410136f5SStephane Eranian 542edb217ffSIan Rogers ret = parse_events_terms(&alias->terms, val, val_fd); 543a6146d50SZheng Yan if (ret) { 54470c646e0SSukadev Bhattiprolu pr_err("Cannot parse alias %s: %d\n", val, ret); 545a6146d50SZheng Yan free(alias); 546a6146d50SZheng Yan return ret; 547a6146d50SZheng Yan } 548a6146d50SZheng Yan 549a6146d50SZheng Yan alias->name = strdup(name); 55008e60ed1SAndi Kleen alias->desc = desc ? strdup(desc) : NULL; 551c8d6828aSSukadev Bhattiprolu alias->long_desc = long_desc ? strdup(long_desc) : 552c8d6828aSSukadev Bhattiprolu desc ? strdup(desc) : NULL; 553dd5f1036SAndi Kleen alias->topic = topic ? strdup(topic) : NULL; 554f63a536fSIan Rogers alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL; 555fedb2b51SAndi Kleen if (unit) { 556f63a536fSIan Rogers if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0) { 557f63a536fSIan Rogers perf_pmu_free_alias(alias); 558fedb2b51SAndi Kleen return -1; 559f63a536fSIan Rogers } 560fedb2b51SAndi Kleen snprintf(alias->unit, sizeof(alias->unit), "%s", unit); 561fedb2b51SAndi Kleen } 562f63a536fSIan Rogers if (!pe) { 563f63a536fSIan Rogers /* Update an event from sysfs with json data. */ 5647b723dbbSIan Rogers struct update_alias_data data = { 5657b723dbbSIan Rogers .pmu = pmu, 5667b723dbbSIan Rogers .alias = alias, 5677b723dbbSIan Rogers }; 5687b723dbbSIan Rogers 5697b723dbbSIan Rogers alias->from_sysfs = true; 5707c52f10cSIan Rogers if (pmu->events_table) { 571e6ff1eedSIan Rogers if (pmu_events_table__find_event(pmu->events_table, pmu, name, 5727b723dbbSIan Rogers update_alias, &data) == 0) 573e6ff1eedSIan Rogers pmu->loaded_json_aliases++; 5747c52f10cSIan Rogers } 575f63a536fSIan Rogers } 576f63a536fSIan Rogers 577f63a536fSIan Rogers /* Scan event and remove leading zeroes, spaces, newlines, some 578f63a536fSIan Rogers * platforms have terms specified as 579f63a536fSIan Rogers * event=0x0091 (read from files ../<PMU>/events/<FILE> 580f63a536fSIan Rogers * and terms specified as event=0x91 (read from JSON files). 581f63a536fSIan Rogers * 582f63a536fSIan Rogers * Rebuild string to make alias->str member comparable. 583f63a536fSIan Rogers */ 584f63a536fSIan Rogers ret = 0; 585f63a536fSIan Rogers list_for_each_entry(term, &alias->terms, list) { 586f63a536fSIan Rogers if (ret) 587f63a536fSIan Rogers ret += scnprintf(newval + ret, sizeof(newval) - ret, 588f63a536fSIan Rogers ","); 589f63a536fSIan Rogers if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 590f63a536fSIan Rogers ret += scnprintf(newval + ret, sizeof(newval) - ret, 591f63a536fSIan Rogers "%s=%#x", term->config, term->val.num); 592f63a536fSIan Rogers else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 593f63a536fSIan Rogers ret += scnprintf(newval + ret, sizeof(newval) - ret, 594f63a536fSIan Rogers "%s=%s", term->config, term->val.str); 595f63a536fSIan Rogers } 5960c24d6fbSThomas Richter alias->str = strdup(newval); 597e6ff1eedSIan Rogers if (!pe) 598e6ff1eedSIan Rogers pmu->sysfs_aliases++; 599e6ff1eedSIan Rogers else 600e6ff1eedSIan Rogers pmu->loaded_json_aliases++; 601f26d22f1SIan Rogers list_add_tail(&alias->list, &pmu->aliases); 602a6146d50SZheng Yan return 0; 603a6146d50SZheng Yan } 604a6146d50SZheng Yan 60546441bdcSMatt Fleming static inline bool pmu_alias_info_file(char *name) 60646441bdcSMatt Fleming { 60746441bdcSMatt Fleming size_t len; 60846441bdcSMatt Fleming 60946441bdcSMatt Fleming len = strlen(name); 61046441bdcSMatt Fleming if (len > 5 && !strcmp(name + len - 5, ".unit")) 61146441bdcSMatt Fleming return true; 61246441bdcSMatt Fleming if (len > 6 && !strcmp(name + len - 6, ".scale")) 61346441bdcSMatt Fleming return true; 614044330c1SMatt Fleming if (len > 8 && !strcmp(name + len - 8, ".per-pkg")) 615044330c1SMatt Fleming return true; 6161d9e446bSJiri Olsa if (len > 9 && !strcmp(name + len - 9, ".snapshot")) 6171d9e446bSJiri Olsa return true; 61846441bdcSMatt Fleming 61946441bdcSMatt Fleming return false; 62046441bdcSMatt Fleming } 62146441bdcSMatt Fleming 622a6146d50SZheng Yan /* 6238d4b6d37SIan Rogers * Reading the pmu event aliases definition, which should be located at: 6248d4b6d37SIan Rogers * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 625a6146d50SZheng Yan */ 6268d4b6d37SIan Rogers static int pmu_aliases_parse(struct perf_pmu *pmu) 627a6146d50SZheng Yan { 6288d4b6d37SIan Rogers char path[PATH_MAX]; 629a6146d50SZheng Yan struct dirent *evt_ent; 630a6146d50SZheng Yan DIR *event_dir; 6318d4b6d37SIan Rogers size_t len; 6328d4b6d37SIan Rogers int fd, dir_fd; 633a6146d50SZheng Yan 6348d4b6d37SIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 6358d4b6d37SIan Rogers if (!len) 6368d4b6d37SIan Rogers return 0; 6378d4b6d37SIan Rogers scnprintf(path + len, sizeof(path) - len, "%s/events", pmu->name); 6388d4b6d37SIan Rogers 6398d4b6d37SIan Rogers dir_fd = open(path, O_DIRECTORY); 6408d4b6d37SIan Rogers if (dir_fd == -1) { 6418d4b6d37SIan Rogers pmu->sysfs_aliases_loaded = true; 6428d4b6d37SIan Rogers return 0; 6438d4b6d37SIan Rogers } 6448d4b6d37SIan Rogers 6458d4b6d37SIan Rogers event_dir = fdopendir(dir_fd); 6468d4b6d37SIan Rogers if (!event_dir){ 6478d4b6d37SIan Rogers close (dir_fd); 648a6146d50SZheng Yan return -EINVAL; 6498d4b6d37SIan Rogers } 650a6146d50SZheng Yan 651940db6dcSAndi Kleen while ((evt_ent = readdir(event_dir))) { 652a6146d50SZheng Yan char *name = evt_ent->d_name; 653a6146d50SZheng Yan FILE *file; 654a6146d50SZheng Yan 655a6146d50SZheng Yan if (!strcmp(name, ".") || !strcmp(name, "..")) 656a6146d50SZheng Yan continue; 657a6146d50SZheng Yan 658410136f5SStephane Eranian /* 65946441bdcSMatt Fleming * skip info files parsed in perf_pmu__new_alias() 660410136f5SStephane Eranian */ 66146441bdcSMatt Fleming if (pmu_alias_info_file(name)) 662410136f5SStephane Eranian continue; 663410136f5SStephane Eranian 6648d4b6d37SIan Rogers fd = openat(dir_fd, name, O_RDONLY); 6650ea8920eSIan Rogers if (fd == -1) { 6660ea8920eSIan Rogers pr_debug("Cannot open %s\n", name); 6670ea8920eSIan Rogers continue; 6680ea8920eSIan Rogers } 669e293a5e8SNamhyung Kim file = fdopen(fd, "r"); 670940db6dcSAndi Kleen if (!file) { 6710ea8920eSIan Rogers close(fd); 672940db6dcSAndi Kleen continue; 673940db6dcSAndi Kleen } 674410136f5SStephane Eranian 6757b723dbbSIan Rogers if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL, 676edb217ffSIan Rogers /*val=*/ NULL, file, /*pe=*/ NULL) < 0) 677940db6dcSAndi Kleen pr_debug("Cannot set up %s\n", name); 678a6146d50SZheng Yan fclose(file); 679a6146d50SZheng Yan } 680a6146d50SZheng Yan 681a6146d50SZheng Yan closedir(event_dir); 6828d4b6d37SIan Rogers close (dir_fd); 6838d4b6d37SIan Rogers pmu->sysfs_aliases_loaded = true; 684a6146d50SZheng Yan return 0; 685a6146d50SZheng Yan } 686a6146d50SZheng Yan 6875c6ccc37SArnaldo Carvalho de Melo static int pmu_alias_terms(struct perf_pmu_alias *alias, 688a6146d50SZheng Yan struct list_head *terms) 689a6146d50SZheng Yan { 6907c2f8164SJiri Olsa struct parse_events_term *term, *cloned; 691a6146d50SZheng Yan LIST_HEAD(list); 692a6146d50SZheng Yan int ret; 693a6146d50SZheng Yan 694a6146d50SZheng Yan list_for_each_entry(term, &alias->terms, list) { 6957c2f8164SJiri Olsa ret = parse_events_term__clone(&cloned, term); 696a6146d50SZheng Yan if (ret) { 697682dc24cSArnaldo Carvalho de Melo parse_events_terms__purge(&list); 698a6146d50SZheng Yan return ret; 699a6146d50SZheng Yan } 700c2f1ceadSAndi Kleen /* 701c2f1ceadSAndi Kleen * Weak terms don't override command line options, 702c2f1ceadSAndi Kleen * which we don't want for implicit terms in aliases. 703c2f1ceadSAndi Kleen */ 704c2f1ceadSAndi Kleen cloned->weak = true; 7057c2f8164SJiri Olsa list_add_tail(&cloned->list, &list); 706a6146d50SZheng Yan } 707a6146d50SZheng Yan list_splice(&list, terms); 708a6146d50SZheng Yan return 0; 709a6146d50SZheng Yan } 710a6146d50SZheng Yan 71166ec1191SMark Rutland /* 71266ec1191SMark Rutland * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) 71366ec1191SMark Rutland * may have a "cpus" file. 71466ec1191SMark Rutland */ 715d06593aaSIan Rogers static struct perf_cpu_map *pmu_cpumask(int dirfd, const char *name, bool is_core) 7167ae92e74SYan, Zheng { 717f854839bSJiri Olsa struct perf_cpu_map *cpus; 7187e3fcffeSMark Rutland const char *templates[] = { 719d50a79cdSJames Clark "cpumask", 720d50a79cdSJames Clark "cpus", 7217e3fcffeSMark Rutland NULL 7227e3fcffeSMark Rutland }; 7237e3fcffeSMark Rutland const char **template; 724d50a79cdSJames Clark char pmu_name[PATH_MAX]; 725d50a79cdSJames Clark struct perf_pmu pmu = {.name = pmu_name}; 726d50a79cdSJames Clark FILE *file; 7277ae92e74SYan, Zheng 728d50a79cdSJames Clark strlcpy(pmu_name, name, sizeof(pmu_name)); 7297e3fcffeSMark Rutland for (template = templates; *template; template++) { 7303a69672eSNamhyung Kim file = perf_pmu__open_file_at(&pmu, dirfd, *template); 731d50a79cdSJames Clark if (!file) 732d50a79cdSJames Clark continue; 733d50a79cdSJames Clark cpus = perf_cpu_map__read(file); 7343a69672eSNamhyung Kim fclose(file); 73566ec1191SMark Rutland if (cpus) 73666ec1191SMark Rutland return cpus; 7377e3fcffeSMark Rutland } 7387ae92e74SYan, Zheng 739d06593aaSIan Rogers /* Nothing found, for core PMUs assume this means all CPUs. */ 740d06593aaSIan Rogers return is_core ? perf_cpu_map__get(cpu_map__online()) : NULL; 74166ec1191SMark Rutland } 7427ae92e74SYan, Zheng 7433a69672eSNamhyung Kim static bool pmu_is_uncore(int dirfd, const char *name) 74466ec1191SMark Rutland { 7453a69672eSNamhyung Kim int fd; 7467ae92e74SYan, Zheng 7473a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "cpumask", O_PATH); 7483a69672eSNamhyung Kim if (fd < 0) 7493a69672eSNamhyung Kim return false; 7503a69672eSNamhyung Kim 7513a69672eSNamhyung Kim close(fd); 7523a69672eSNamhyung Kim return true; 7537ae92e74SYan, Zheng } 7547ae92e74SYan, Zheng 75551d54847SJohn Garry static char *pmu_id(const char *name) 75651d54847SJohn Garry { 75751d54847SJohn Garry char path[PATH_MAX], *str; 75851d54847SJohn Garry size_t len; 75951d54847SJohn Garry 7605f2c8efaSJames Clark perf_pmu__pathname_scnprintf(path, sizeof(path), name, "identifier"); 76151d54847SJohn Garry 7625f2c8efaSJames Clark if (filename__read_str(path, &str, &len) < 0) 76351d54847SJohn Garry return NULL; 76451d54847SJohn Garry 76551d54847SJohn Garry str[len - 1] = 0; /* remove line feed */ 76651d54847SJohn Garry 76751d54847SJohn Garry return str; 76851d54847SJohn Garry } 76951d54847SJohn Garry 7704bf7e81aSIan Rogers /** 7714bf7e81aSIan Rogers * is_sysfs_pmu_core() - PMU CORE devices have different name other than cpu in 7724bf7e81aSIan Rogers * sysfs on some platforms like ARM or Intel hybrid. Looking for 7734bf7e81aSIan Rogers * possible the cpus file in sysfs files to identify whether this is a 7744bf7e81aSIan Rogers * core device. 7754bf7e81aSIan Rogers * @name: The PMU name such as "cpu_atom". 77614b22ae0SGanapatrao Kulkarni */ 7774bf7e81aSIan Rogers static int is_sysfs_pmu_core(const char *name) 77814b22ae0SGanapatrao Kulkarni { 77914b22ae0SGanapatrao Kulkarni char path[PATH_MAX]; 78014b22ae0SGanapatrao Kulkarni 781f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), name, "cpus")) 78214b22ae0SGanapatrao Kulkarni return 0; 783d9664582SAndi Kleen return file_available(path); 78414b22ae0SGanapatrao Kulkarni } 78514b22ae0SGanapatrao Kulkarni 78629be2fe0SIan Rogers char *perf_pmu__getcpuid(struct perf_pmu *pmu) 787d77ade9fSAndi Kleen { 788d77ade9fSAndi Kleen char *cpuid; 789d77ade9fSAndi Kleen static bool printed; 790d77ade9fSAndi Kleen 791d77ade9fSAndi Kleen cpuid = getenv("PERF_CPUID"); 792d77ade9fSAndi Kleen if (cpuid) 793d77ade9fSAndi Kleen cpuid = strdup(cpuid); 794d77ade9fSAndi Kleen if (!cpuid) 79554e32dc0SGanapatrao Kulkarni cpuid = get_cpuid_str(pmu); 796d77ade9fSAndi Kleen if (!cpuid) 797d77ade9fSAndi Kleen return NULL; 798d77ade9fSAndi Kleen 799d77ade9fSAndi Kleen if (!printed) { 800d77ade9fSAndi Kleen pr_debug("Using CPUID %s\n", cpuid); 801d77ade9fSAndi Kleen printed = true; 802d77ade9fSAndi Kleen } 803d77ade9fSAndi Kleen return cpuid; 804d77ade9fSAndi Kleen } 805d77ade9fSAndi Kleen 8061ba3752aSIan Rogers __weak const struct pmu_events_table *pmu_events_table__find(void) 807e126bef5SJohn Garry { 80896d2a746SIan Rogers return perf_pmu__find_events_table(NULL); 809e126bef5SJohn Garry } 810e126bef5SJohn Garry 811f8ea2c15SIan Rogers __weak const struct pmu_metrics_table *pmu_metrics_table__find(void) 812f8ea2c15SIan Rogers { 813f8ea2c15SIan Rogers return perf_pmu__find_metrics_table(NULL); 814f8ea2c15SIan Rogers } 815f8ea2c15SIan Rogers 816240e6fd0SIan Rogers /** 817240e6fd0SIan Rogers * perf_pmu__match_ignoring_suffix - Does the pmu_name match tok ignoring any 818240e6fd0SIan Rogers * trailing suffix? The Suffix must be in form 819240e6fd0SIan Rogers * tok_{digits}, or tok{digits}. 820240e6fd0SIan Rogers * @pmu_name: The pmu_name with possible suffix. 821240e6fd0SIan Rogers * @tok: The possible match to pmu_name without suffix. 822c07d5c92SJohn Garry */ 823240e6fd0SIan Rogers static bool perf_pmu__match_ignoring_suffix(const char *pmu_name, const char *tok) 824c47a5599SJin Yao { 825c07d5c92SJohn Garry const char *p; 826c47a5599SJin Yao 827c47a5599SJin Yao if (strncmp(pmu_name, tok, strlen(tok))) 828c47a5599SJin Yao return false; 829c47a5599SJin Yao 830c47a5599SJin Yao p = pmu_name + strlen(tok); 831c47a5599SJin Yao if (*p == 0) 832c47a5599SJin Yao return true; 833c47a5599SJin Yao 834c07d5c92SJohn Garry if (*p == '_') 835c47a5599SJin Yao ++p; 836c07d5c92SJohn Garry 837c07d5c92SJohn Garry /* Ensure we end in a number */ 838c07d5c92SJohn Garry while (1) { 839c07d5c92SJohn Garry if (!isdigit(*p)) 840c47a5599SJin Yao return false; 841c07d5c92SJohn Garry if (*(++p) == 0) 842c07d5c92SJohn Garry break; 843c07d5c92SJohn Garry } 844c47a5599SJin Yao 845c47a5599SJin Yao return true; 846c47a5599SJin Yao } 847c47a5599SJin Yao 848240e6fd0SIan Rogers /** 849240e6fd0SIan Rogers * pmu_uncore_alias_match - does name match the PMU name? 850240e6fd0SIan Rogers * @pmu_name: the json struct pmu_event name. This may lack a suffix (which 851240e6fd0SIan Rogers * matches) or be of the form "socket,pmuname" which will match 852240e6fd0SIan Rogers * "socketX_pmunameY". 853240e6fd0SIan Rogers * @name: a real full PMU name as from sysfs. 854240e6fd0SIan Rogers */ 855240e6fd0SIan Rogers static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) 856730670b1SJohn Garry { 857730670b1SJohn Garry char *tmp = NULL, *tok, *str; 858730670b1SJohn Garry bool res; 859730670b1SJohn Garry 860240e6fd0SIan Rogers if (strchr(pmu_name, ',') == NULL) 861240e6fd0SIan Rogers return perf_pmu__match_ignoring_suffix(name, pmu_name); 862240e6fd0SIan Rogers 863730670b1SJohn Garry str = strdup(pmu_name); 864730670b1SJohn Garry if (!str) 865730670b1SJohn Garry return false; 866730670b1SJohn Garry 867730670b1SJohn Garry /* 868730670b1SJohn Garry * uncore alias may be from different PMU with common prefix 869730670b1SJohn Garry */ 870730670b1SJohn Garry tok = strtok_r(str, ",", &tmp); 871730670b1SJohn Garry if (strncmp(pmu_name, tok, strlen(tok))) { 872730670b1SJohn Garry res = false; 873730670b1SJohn Garry goto out; 874730670b1SJohn Garry } 875730670b1SJohn Garry 876730670b1SJohn Garry /* 877730670b1SJohn Garry * Match more complex aliases where the alias name is a comma-delimited 878730670b1SJohn Garry * list of tokens, orderly contained in the matching PMU name. 879730670b1SJohn Garry * 880730670b1SJohn Garry * Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we 881730670b1SJohn Garry * match "socket" in "socketX_pmunameY" and then "pmuname" in 882730670b1SJohn Garry * "pmunameY". 883730670b1SJohn Garry */ 884c07d5c92SJohn Garry while (1) { 885c07d5c92SJohn Garry char *next_tok = strtok_r(NULL, ",", &tmp); 886c07d5c92SJohn Garry 887730670b1SJohn Garry name = strstr(name, tok); 888c07d5c92SJohn Garry if (!name || 889240e6fd0SIan Rogers (!next_tok && !perf_pmu__match_ignoring_suffix(name, tok))) { 890730670b1SJohn Garry res = false; 891730670b1SJohn Garry goto out; 892730670b1SJohn Garry } 893c07d5c92SJohn Garry if (!next_tok) 894c07d5c92SJohn Garry break; 895c07d5c92SJohn Garry tok = next_tok; 896c07d5c92SJohn Garry name += strlen(tok); 897730670b1SJohn Garry } 898730670b1SJohn Garry 899730670b1SJohn Garry res = true; 900730670b1SJohn Garry out: 901730670b1SJohn Garry free(str); 902730670b1SJohn Garry return res; 903730670b1SJohn Garry } 904730670b1SJohn Garry 905660842e4SIan Rogers static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, 9061ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 907660842e4SIan Rogers void *vdata) 908660842e4SIan Rogers { 909f26d22f1SIan Rogers struct perf_pmu *pmu = vdata; 910660842e4SIan Rogers 9117b723dbbSIan Rogers perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe); 912660842e4SIan Rogers return 0; 913660842e4SIan Rogers } 914660842e4SIan Rogers 915933f82ffSSukadev Bhattiprolu /* 916d685819bSIan Rogers * From the pmu_events_table, find the events that correspond to the given 917d685819bSIan Rogers * PMU and add them to the list 'head'. 918933f82ffSSukadev Bhattiprolu */ 919838a8c5fSIan Rogers void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table) 920933f82ffSSukadev Bhattiprolu { 921f26d22f1SIan Rogers pmu_events_table__for_each_event(table, pmu, pmu_add_cpu_aliases_map_callback, pmu); 922933f82ffSSukadev Bhattiprolu } 923933f82ffSSukadev Bhattiprolu 924838a8c5fSIan Rogers static void pmu_add_cpu_aliases(struct perf_pmu *pmu) 925e45ad701SJohn Garry { 9267c52f10cSIan Rogers if (!pmu->events_table) 927e45ad701SJohn Garry return; 928e45ad701SJohn Garry 929e6ff1eedSIan Rogers if (pmu->cpu_aliases_added) 930e6ff1eedSIan Rogers return; 931e6ff1eedSIan Rogers 9327c52f10cSIan Rogers pmu_add_cpu_aliases_table(pmu, pmu->events_table); 933e6ff1eedSIan Rogers pmu->cpu_aliases_added = true; 934e45ad701SJohn Garry } 935e45ad701SJohn Garry 93629be2fe0SIan Rogers static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, 9371ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 938f26d22f1SIan Rogers void *vdata) 9394513c719SJohn Garry { 940f26d22f1SIan Rogers struct perf_pmu *pmu = vdata; 9414513c719SJohn Garry 9424513c719SJohn Garry if (!pe->compat || !pe->pmu) 9434513c719SJohn Garry return 0; 9444513c719SJohn Garry 9454513c719SJohn Garry if (!strcmp(pmu->id, pe->compat) && 9464513c719SJohn Garry pmu_uncore_alias_match(pe->pmu, pmu->name)) { 9477b723dbbSIan Rogers perf_pmu__new_alias(pmu, 948edb217ffSIan Rogers pe->name, 949edb217ffSIan Rogers pe->desc, 950edb217ffSIan Rogers pe->event, 951edb217ffSIan Rogers /*val_fd=*/ NULL, 952eab35953SJin Yao pe); 9534513c719SJohn Garry } 9544513c719SJohn Garry 9554513c719SJohn Garry return 0; 9564513c719SJohn Garry } 9574513c719SJohn Garry 958838a8c5fSIan Rogers void pmu_add_sys_aliases(struct perf_pmu *pmu) 9594513c719SJohn Garry { 9604513c719SJohn Garry if (!pmu->id) 9614513c719SJohn Garry return; 9624513c719SJohn Garry 963f26d22f1SIan Rogers pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, pmu); 9644513c719SJohn Garry } 9654513c719SJohn Garry 966c5de47f2SSukadev Bhattiprolu struct perf_event_attr * __weak 967dc0a6202SAdrian Hunter perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) 968dc0a6202SAdrian Hunter { 969dc0a6202SAdrian Hunter return NULL; 970dc0a6202SAdrian Hunter } 971dc0a6202SAdrian Hunter 972c091ee90SIan Rogers const char * __weak 97313d60ba0SKan Liang pmu_find_real_name(const char *name) 97413d60ba0SKan Liang { 975c091ee90SIan Rogers return name; 97613d60ba0SKan Liang } 97713d60ba0SKan Liang 978c091ee90SIan Rogers const char * __weak 97913d60ba0SKan Liang pmu_find_alias_name(const char *name __maybe_unused) 98013d60ba0SKan Liang { 98113d60ba0SKan Liang return NULL; 98213d60ba0SKan Liang } 98313d60ba0SKan Liang 9843a69672eSNamhyung Kim static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) 98590a86bdeSJiri Olsa { 98690a86bdeSJiri Olsa int max_precise = -1; 98790a86bdeSJiri Olsa 9883a69672eSNamhyung Kim perf_pmu__scan_file_at(pmu, dirfd, "caps/max_precise", "%d", &max_precise); 98990a86bdeSJiri Olsa return max_precise; 99090a86bdeSJiri Olsa } 99190a86bdeSJiri Olsa 9921eaf496eSIan Rogers struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name) 993cd82a32eSJiri Olsa { 994cd82a32eSJiri Olsa struct perf_pmu *pmu; 995cd82a32eSJiri Olsa __u32 type; 996c091ee90SIan Rogers const char *name = pmu_find_real_name(lookup_name); 997c091ee90SIan Rogers const char *alias_name; 99849afa7f6SJin Yao 999cd82a32eSJiri Olsa pmu = zalloc(sizeof(*pmu)); 1000cd82a32eSJiri Olsa if (!pmu) 1001cd82a32eSJiri Olsa return NULL; 1002cd82a32eSJiri Olsa 1003f63a536fSIan Rogers pmu->name = strdup(name); 1004f63a536fSIan Rogers if (!pmu->name) 1005f63a536fSIan Rogers goto err; 100688ed9184SIan Rogers 100788ed9184SIan Rogers /* 100888ed9184SIan Rogers * Read type early to fail fast if a lookup name isn't a PMU. Ensure 100988ed9184SIan Rogers * that type value is successfully assigned (return 1). 101088ed9184SIan Rogers */ 101188ed9184SIan Rogers if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1) 101288ed9184SIan Rogers goto err; 101388ed9184SIan Rogers 101488ed9184SIan Rogers INIT_LIST_HEAD(&pmu->format); 101588ed9184SIan Rogers INIT_LIST_HEAD(&pmu->aliases); 101688ed9184SIan Rogers INIT_LIST_HEAD(&pmu->caps); 101788ed9184SIan Rogers 1018838a8c5fSIan Rogers /* 1019838a8c5fSIan Rogers * The pmu data we store & need consists of the pmu 1020838a8c5fSIan Rogers * type value and format definitions. Load both right 1021838a8c5fSIan Rogers * now. 1022838a8c5fSIan Rogers */ 1023838a8c5fSIan Rogers if (pmu_format(pmu, dirfd, name)) { 1024838a8c5fSIan Rogers free(pmu); 1025838a8c5fSIan Rogers return NULL; 1026838a8c5fSIan Rogers } 1027d06593aaSIan Rogers pmu->is_core = is_pmu_core(name); 1028d06593aaSIan Rogers pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core); 102913d60ba0SKan Liang 103013d60ba0SKan Liang alias_name = pmu_find_alias_name(name); 103113d60ba0SKan Liang if (alias_name) { 103213d60ba0SKan Liang pmu->alias_name = strdup(alias_name); 103313d60ba0SKan Liang if (!pmu->alias_name) 103413d60ba0SKan Liang goto err; 103513d60ba0SKan Liang } 103613d60ba0SKan Liang 103754e32dc0SGanapatrao Kulkarni pmu->type = type; 10383a69672eSNamhyung Kim pmu->is_uncore = pmu_is_uncore(dirfd, name); 103951d54847SJohn Garry if (pmu->is_uncore) 104051d54847SJohn Garry pmu->id = pmu_id(name); 10413a69672eSNamhyung Kim pmu->max_precise = pmu_max_precise(dirfd, pmu); 10427c52f10cSIan Rogers pmu->events_table = perf_pmu__find_events_table(pmu); 1043838a8c5fSIan Rogers pmu_add_sys_aliases(pmu); 10441eaf496eSIan Rogers list_add_tail(&pmu->list, pmus); 1045dc0a6202SAdrian Hunter 1046dc0a6202SAdrian Hunter pmu->default_config = perf_pmu__get_default_config(pmu); 1047dc0a6202SAdrian Hunter 1048cd82a32eSJiri Olsa return pmu; 104913d60ba0SKan Liang err: 1050efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 105113d60ba0SKan Liang free(pmu); 105213d60ba0SKan Liang return NULL; 1053cd82a32eSJiri Olsa } 1054cd82a32eSJiri Olsa 1055628eaa4eSIan Rogers /* Creates the PMU when sysfs scanning fails. */ 1056628eaa4eSIan Rogers struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus) 1057628eaa4eSIan Rogers { 1058628eaa4eSIan Rogers struct perf_pmu *pmu = zalloc(sizeof(*pmu)); 1059628eaa4eSIan Rogers 1060628eaa4eSIan Rogers if (!pmu) 1061628eaa4eSIan Rogers return NULL; 1062628eaa4eSIan Rogers 1063628eaa4eSIan Rogers pmu->name = strdup("cpu"); 1064628eaa4eSIan Rogers if (!pmu->name) { 1065628eaa4eSIan Rogers free(pmu); 1066628eaa4eSIan Rogers return NULL; 1067628eaa4eSIan Rogers } 1068628eaa4eSIan Rogers 1069628eaa4eSIan Rogers pmu->is_core = true; 1070628eaa4eSIan Rogers pmu->type = PERF_TYPE_RAW; 1071628eaa4eSIan Rogers pmu->cpus = cpu_map__online(); 1072628eaa4eSIan Rogers 1073628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->format); 1074628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 1075628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->caps); 1076628eaa4eSIan Rogers list_add_tail(&pmu->list, core_pmus); 1077628eaa4eSIan Rogers return pmu; 1078628eaa4eSIan Rogers } 1079628eaa4eSIan Rogers 1080e552b7beSRob Herring void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu) 1081e552b7beSRob Herring { 1082e552b7beSRob Herring struct perf_pmu_format *format; 1083e552b7beSRob Herring 108468c25043SIan Rogers if (pmu->formats_checked) 108568c25043SIan Rogers return; 108668c25043SIan Rogers 108768c25043SIan Rogers pmu->formats_checked = true; 108868c25043SIan Rogers 1089e552b7beSRob Herring /* fake pmu doesn't have format list */ 1090e552b7beSRob Herring if (pmu == &perf_pmu__fake) 1091e552b7beSRob Herring return; 1092e552b7beSRob Herring 109350402641SIan Rogers list_for_each_entry(format, &pmu->format, list) { 109450402641SIan Rogers perf_pmu_format__load(pmu, format); 1095e552b7beSRob Herring if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) { 1096e552b7beSRob Herring pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'" 1097e552b7beSRob Herring "which is not supported by this version of perf!\n", 1098e552b7beSRob Herring pmu->name, format->name, format->value); 1099e552b7beSRob Herring return; 1100e552b7beSRob Herring } 1101e552b7beSRob Herring } 110250402641SIan Rogers } 1103e552b7beSRob Herring 1104c6d616feSIan Rogers bool evsel__is_aux_event(const struct evsel *evsel) 1105e12ee9f7SAdrian Hunter { 1106e76026bdSArnaldo Carvalho de Melo struct perf_pmu *pmu = evsel__find_pmu(evsel); 1107e12ee9f7SAdrian Hunter 1108e12ee9f7SAdrian Hunter return pmu && pmu->auxtrace; 1109e12ee9f7SAdrian Hunter } 1110e12ee9f7SAdrian Hunter 11116593f019SJames Clark /* 11126593f019SJames Clark * Set @config_name to @val as long as the user hasn't already set or cleared it 11136593f019SJames Clark * by passing a config term on the command line. 11146593f019SJames Clark * 11156593f019SJames Clark * @val is the value to put into the bits specified by @config_name rather than 11166593f019SJames Clark * the bit pattern. It is shifted into position by this function, so to set 11176593f019SJames Clark * something to true, pass 1 for val rather than a pre shifted value. 11186593f019SJames Clark */ 11196593f019SJames Clark #define field_prep(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask)) 11206593f019SJames Clark void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, 11216593f019SJames Clark const char *config_name, u64 val) 11226593f019SJames Clark { 11236593f019SJames Clark u64 user_bits = 0, bits; 11246593f019SJames Clark struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG); 11256593f019SJames Clark 11266593f019SJames Clark if (term) 11276593f019SJames Clark user_bits = term->val.cfg_chg; 11286593f019SJames Clark 1129da6a5afdSIan Rogers bits = perf_pmu__format_bits(pmu, config_name); 11306593f019SJames Clark 11316593f019SJames Clark /* Do nothing if the user changed the value */ 11326593f019SJames Clark if (bits & user_bits) 11336593f019SJames Clark return; 11346593f019SJames Clark 11356593f019SJames Clark /* Otherwise replace it */ 11366593f019SJames Clark evsel->core.attr.config &= ~bits; 11376593f019SJames Clark evsel->core.attr.config |= field_prep(bits, val); 11386593f019SJames Clark } 11396593f019SJames Clark 11405c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_format * 114109ff6071SAdrian Hunter pmu_find_format(struct list_head *formats, const char *name) 1142cd82a32eSJiri Olsa { 11435c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1144cd82a32eSJiri Olsa 1145cd82a32eSJiri Olsa list_for_each_entry(format, formats, list) 1146cd82a32eSJiri Olsa if (!strcmp(format->name, name)) 1147cd82a32eSJiri Olsa return format; 1148cd82a32eSJiri Olsa 1149cd82a32eSJiri Olsa return NULL; 1150cd82a32eSJiri Olsa } 1151cd82a32eSJiri Olsa 1152da6a5afdSIan Rogers __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name) 115309ff6071SAdrian Hunter { 1154da6a5afdSIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 115509ff6071SAdrian Hunter __u64 bits = 0; 115609ff6071SAdrian Hunter int fbit; 115709ff6071SAdrian Hunter 115809ff6071SAdrian Hunter if (!format) 115909ff6071SAdrian Hunter return 0; 116009ff6071SAdrian Hunter 116109ff6071SAdrian Hunter for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS) 116209ff6071SAdrian Hunter bits |= 1ULL << fbit; 116309ff6071SAdrian Hunter 116409ff6071SAdrian Hunter return bits; 116509ff6071SAdrian Hunter } 116609ff6071SAdrian Hunter 11677eb54733SIan Rogers int perf_pmu__format_type(struct perf_pmu *pmu, const char *name) 1168a1ac7de6SAdrian Hunter { 11697eb54733SIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 1170a1ac7de6SAdrian Hunter 1171a1ac7de6SAdrian Hunter if (!format) 1172a1ac7de6SAdrian Hunter return -1; 1173a1ac7de6SAdrian Hunter 117450402641SIan Rogers perf_pmu_format__load(pmu, format); 1175a1ac7de6SAdrian Hunter return format->value; 1176a1ac7de6SAdrian Hunter } 1177a1ac7de6SAdrian Hunter 1178cd82a32eSJiri Olsa /* 1179dc0a6202SAdrian Hunter * Sets value based on the format definition (format parameter) 11804d39c89fSIngo Molnar * and unformatted value (value parameter). 1181cd82a32eSJiri Olsa */ 1182dc0a6202SAdrian Hunter static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, 1183dc0a6202SAdrian Hunter bool zero) 1184cd82a32eSJiri Olsa { 1185cd82a32eSJiri Olsa unsigned long fbit, vbit; 1186cd82a32eSJiri Olsa 1187cd82a32eSJiri Olsa for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 1188cd82a32eSJiri Olsa 1189cd82a32eSJiri Olsa if (!test_bit(fbit, format)) 1190cd82a32eSJiri Olsa continue; 1191cd82a32eSJiri Olsa 1192dc0a6202SAdrian Hunter if (value & (1llu << vbit++)) 1193dc0a6202SAdrian Hunter *v |= (1llu << fbit); 1194dc0a6202SAdrian Hunter else if (zero) 1195dc0a6202SAdrian Hunter *v &= ~(1llu << fbit); 1196cd82a32eSJiri Olsa } 1197cd82a32eSJiri Olsa } 1198cd82a32eSJiri Olsa 11990efe6b67SAdrian Hunter static __u64 pmu_format_max_value(const unsigned long *format) 12000efe6b67SAdrian Hunter { 12011b9caa10SJiri Olsa int w; 12020efe6b67SAdrian Hunter 12031b9caa10SJiri Olsa w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); 12041b9caa10SJiri Olsa if (!w) 12051b9caa10SJiri Olsa return 0; 12061b9caa10SJiri Olsa if (w < 64) 12071b9caa10SJiri Olsa return (1ULL << w) - 1; 12081b9caa10SJiri Olsa return -1; 12090efe6b67SAdrian Hunter } 12100efe6b67SAdrian Hunter 1211cd82a32eSJiri Olsa /* 1212688d4dfcSCody P Schafer * Term is a string term, and might be a param-term. Try to look up it's value 1213688d4dfcSCody P Schafer * in the remaining terms. 1214688d4dfcSCody P Schafer * - We have a term like "base-or-format-term=param-term", 1215688d4dfcSCody P Schafer * - We need to find the value supplied for "param-term" (with param-term named 1216688d4dfcSCody P Schafer * in a config string) later on in the term list. 1217688d4dfcSCody P Schafer */ 1218688d4dfcSCody P Schafer static int pmu_resolve_param_term(struct parse_events_term *term, 1219688d4dfcSCody P Schafer struct list_head *head_terms, 1220688d4dfcSCody P Schafer __u64 *value) 1221688d4dfcSCody P Schafer { 1222688d4dfcSCody P Schafer struct parse_events_term *t; 1223688d4dfcSCody P Schafer 1224688d4dfcSCody P Schafer list_for_each_entry(t, head_terms, list) { 12252a3d252dSIan Rogers if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM && 12262a3d252dSIan Rogers t->config && !strcmp(t->config, term->config)) { 1227688d4dfcSCody P Schafer t->used = true; 1228688d4dfcSCody P Schafer *value = t->val.num; 1229688d4dfcSCody P Schafer return 0; 1230688d4dfcSCody P Schafer } 1231688d4dfcSCody P Schafer } 1232688d4dfcSCody P Schafer 1233bb963e16SNamhyung Kim if (verbose > 0) 1234688d4dfcSCody P Schafer printf("Required parameter '%s' not specified\n", term->config); 1235688d4dfcSCody P Schafer 1236688d4dfcSCody P Schafer return -1; 1237688d4dfcSCody P Schafer } 1238688d4dfcSCody P Schafer 1239ffeb883eSHe Kuang static char *pmu_formats_string(struct list_head *formats) 1240e64b020bSJiri Olsa { 1241e64b020bSJiri Olsa struct perf_pmu_format *format; 124211db4e29SMasami Hiramatsu char *str = NULL; 124311db4e29SMasami Hiramatsu struct strbuf buf = STRBUF_INIT; 1244f1417ceaSXin Gao unsigned int i = 0; 1245e64b020bSJiri Olsa 1246ffeb883eSHe Kuang if (!formats) 1247e64b020bSJiri Olsa return NULL; 1248e64b020bSJiri Olsa 1249e64b020bSJiri Olsa /* sysfs exported terms */ 1250ffeb883eSHe Kuang list_for_each_entry(format, formats, list) 125111db4e29SMasami Hiramatsu if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0) 125211db4e29SMasami Hiramatsu goto error; 1253e64b020bSJiri Olsa 1254ffeb883eSHe Kuang str = strbuf_detach(&buf, NULL); 125511db4e29SMasami Hiramatsu error: 1256ffeb883eSHe Kuang strbuf_release(&buf); 1257e64b020bSJiri Olsa 1258e64b020bSJiri Olsa return str; 1259e64b020bSJiri Olsa } 1260e64b020bSJiri Olsa 1261688d4dfcSCody P Schafer /* 1262cd82a32eSJiri Olsa * Setup one of config[12] attr members based on the 126388aca8d9SCody P Schafer * user input data - term parameter. 1264cd82a32eSJiri Olsa */ 1265804fee5dSIan Rogers static int pmu_config_term(struct perf_pmu *pmu, 1266cd82a32eSJiri Olsa struct perf_event_attr *attr, 1267dc0a6202SAdrian Hunter struct parse_events_term *term, 1268688d4dfcSCody P Schafer struct list_head *head_terms, 1269e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1270cd82a32eSJiri Olsa { 12715c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1272cd82a32eSJiri Olsa __u64 *vp; 12730efe6b67SAdrian Hunter __u64 val, max_val; 1274cd82a32eSJiri Olsa 1275cd82a32eSJiri Olsa /* 1276688d4dfcSCody P Schafer * If this is a parameter we've already used for parameterized-eval, 1277688d4dfcSCody P Schafer * skip it in normal eval. 1278688d4dfcSCody P Schafer */ 1279688d4dfcSCody P Schafer if (term->used) 1280688d4dfcSCody P Schafer return 0; 1281688d4dfcSCody P Schafer 1282688d4dfcSCody P Schafer /* 1283cd82a32eSJiri Olsa * Hardcoded terms should be already in, so nothing 1284cd82a32eSJiri Olsa * to be done for them. 1285cd82a32eSJiri Olsa */ 1286cd82a32eSJiri Olsa if (parse_events__is_hardcoded_term(term)) 1287cd82a32eSJiri Olsa return 0; 1288cd82a32eSJiri Olsa 1289804fee5dSIan Rogers format = pmu_find_format(&pmu->format, term->config); 1290688d4dfcSCody P Schafer if (!format) { 1291804fee5dSIan Rogers char *pmu_term = pmu_formats_string(&pmu->format); 12924ac22b48SIan Rogers char *unknown_term; 12934ac22b48SIan Rogers char *help_msg; 1294ffeb883eSHe Kuang 12954ac22b48SIan Rogers if (asprintf(&unknown_term, 12964ac22b48SIan Rogers "unknown term '%s' for pmu '%s'", 1297804fee5dSIan Rogers term->config, pmu->name) < 0) 12984ac22b48SIan Rogers unknown_term = NULL; 12994ac22b48SIan Rogers help_msg = parse_events_formats_error_string(pmu_term); 13004ac22b48SIan Rogers if (err) { 13016c191289SIan Rogers parse_events_error__handle(err, term->err_term, 13024ac22b48SIan Rogers unknown_term, 13034ac22b48SIan Rogers help_msg); 13044ac22b48SIan Rogers } else { 13054ac22b48SIan Rogers pr_debug("%s (%s)\n", unknown_term, help_msg); 13064ac22b48SIan Rogers free(unknown_term); 1307e64b020bSJiri Olsa } 13084ac22b48SIan Rogers free(pmu_term); 1309cd82a32eSJiri Olsa return -EINVAL; 1310688d4dfcSCody P Schafer } 131150402641SIan Rogers perf_pmu_format__load(pmu, format); 1312cd82a32eSJiri Olsa switch (format->value) { 1313cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG: 1314cd82a32eSJiri Olsa vp = &attr->config; 1315cd82a32eSJiri Olsa break; 1316cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG1: 1317cd82a32eSJiri Olsa vp = &attr->config1; 1318cd82a32eSJiri Olsa break; 1319cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG2: 1320cd82a32eSJiri Olsa vp = &attr->config2; 1321cd82a32eSJiri Olsa break; 1322204e7c49SRob Herring case PERF_PMU_FORMAT_VALUE_CONFIG3: 1323204e7c49SRob Herring vp = &attr->config3; 1324204e7c49SRob Herring break; 1325cd82a32eSJiri Olsa default: 1326cd82a32eSJiri Olsa return -EINVAL; 1327cd82a32eSJiri Olsa } 1328cd82a32eSJiri Olsa 132916fa7e82SJiri Olsa /* 1330688d4dfcSCody P Schafer * Either directly use a numeric term, or try to translate string terms 1331688d4dfcSCody P Schafer * using event parameters. 133216fa7e82SJiri Olsa */ 133399e7138eSJiri Olsa if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 133499e7138eSJiri Olsa if (term->no_value && 133599e7138eSJiri Olsa bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) { 133699e7138eSJiri Olsa if (err) { 13376c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1338448d732cSIan Rogers strdup("no value assigned for term"), 1339448d732cSIan Rogers NULL); 134099e7138eSJiri Olsa } 134199e7138eSJiri Olsa return -EINVAL; 134299e7138eSJiri Olsa } 134399e7138eSJiri Olsa 1344688d4dfcSCody P Schafer val = term->val.num; 134599e7138eSJiri Olsa } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1346688d4dfcSCody P Schafer if (strcmp(term->val.str, "?")) { 1347bb963e16SNamhyung Kim if (verbose > 0) { 1348688d4dfcSCody P Schafer pr_info("Invalid sysfs entry %s=%s\n", 1349688d4dfcSCody P Schafer term->config, term->val.str); 1350e64b020bSJiri Olsa } 1351e64b020bSJiri Olsa if (err) { 13526c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1353448d732cSIan Rogers strdup("expected numeric value"), 1354448d732cSIan Rogers NULL); 1355e64b020bSJiri Olsa } 1356688d4dfcSCody P Schafer return -EINVAL; 1357688d4dfcSCody P Schafer } 1358688d4dfcSCody P Schafer 1359688d4dfcSCody P Schafer if (pmu_resolve_param_term(term, head_terms, &val)) 1360688d4dfcSCody P Schafer return -EINVAL; 1361688d4dfcSCody P Schafer } else 1362688d4dfcSCody P Schafer return -EINVAL; 1363688d4dfcSCody P Schafer 13640efe6b67SAdrian Hunter max_val = pmu_format_max_value(format->bits); 13650efe6b67SAdrian Hunter if (val > max_val) { 13660efe6b67SAdrian Hunter if (err) { 1367448d732cSIan Rogers char *err_str; 1368448d732cSIan Rogers 13696c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1370448d732cSIan Rogers asprintf(&err_str, 13710efe6b67SAdrian Hunter "value too big for format, maximum is %llu", 1372448d732cSIan Rogers (unsigned long long)max_val) < 0 1373448d732cSIan Rogers ? strdup("value too big for format") 1374448d732cSIan Rogers : err_str, 1375448d732cSIan Rogers NULL); 13760efe6b67SAdrian Hunter return -EINVAL; 13770efe6b67SAdrian Hunter } 13780efe6b67SAdrian Hunter /* 13790efe6b67SAdrian Hunter * Assume we don't care if !err, in which case the value will be 13800efe6b67SAdrian Hunter * silently truncated. 13810efe6b67SAdrian Hunter */ 13820efe6b67SAdrian Hunter } 13830efe6b67SAdrian Hunter 1384688d4dfcSCody P Schafer pmu_format_value(format->bits, val, vp, zero); 1385cd82a32eSJiri Olsa return 0; 1386cd82a32eSJiri Olsa } 1387cd82a32eSJiri Olsa 1388804fee5dSIan Rogers int perf_pmu__config_terms(struct perf_pmu *pmu, 1389cff7f956SJiri Olsa struct perf_event_attr *attr, 1390dc0a6202SAdrian Hunter struct list_head *head_terms, 1391e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1392cd82a32eSJiri Olsa { 13936cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 1394cd82a32eSJiri Olsa 1395688d4dfcSCody P Schafer list_for_each_entry(term, head_terms, list) { 1396804fee5dSIan Rogers if (pmu_config_term(pmu, attr, term, head_terms, zero, err)) 1397cd82a32eSJiri Olsa return -EINVAL; 1398688d4dfcSCody P Schafer } 1399cd82a32eSJiri Olsa 1400cd82a32eSJiri Olsa return 0; 1401cd82a32eSJiri Olsa } 1402cd82a32eSJiri Olsa 1403cd82a32eSJiri Olsa /* 1404cd82a32eSJiri Olsa * Configures event's 'attr' parameter based on the: 1405cd82a32eSJiri Olsa * 1) users input - specified in terms parameter 1406cd82a32eSJiri Olsa * 2) pmu format definitions - specified by pmu parameter 1407cd82a32eSJiri Olsa */ 1408cd82a32eSJiri Olsa int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 1409e64b020bSJiri Olsa struct list_head *head_terms, 1410e64b020bSJiri Olsa struct parse_events_error *err) 1411cd82a32eSJiri Olsa { 1412dc0a6202SAdrian Hunter bool zero = !!pmu->default_config; 1413dc0a6202SAdrian Hunter 1414804fee5dSIan Rogers return perf_pmu__config_terms(pmu, attr, head_terms, zero, err); 1415cd82a32eSJiri Olsa } 1416cd82a32eSJiri Olsa 14175c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 14186cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 1419a6146d50SZheng Yan { 1420e6ff1eedSIan Rogers struct perf_pmu_alias *alias; 1421970ef02eSIan Rogers const char *name; 1422a6146d50SZheng Yan 1423a6146d50SZheng Yan if (parse_events__is_hardcoded_term(term)) 1424a6146d50SZheng Yan return NULL; 1425a6146d50SZheng Yan 1426a6146d50SZheng Yan if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 1427a6146d50SZheng Yan if (term->val.num != 1) 1428a6146d50SZheng Yan return NULL; 1429a6146d50SZheng Yan if (pmu_find_format(&pmu->format, term->config)) 1430a6146d50SZheng Yan return NULL; 1431a6146d50SZheng Yan name = term->config; 1432c3245d20SIan Rogers 1433a6146d50SZheng Yan } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1434a6146d50SZheng Yan if (strcasecmp(term->config, "event")) 1435a6146d50SZheng Yan return NULL; 1436a6146d50SZheng Yan name = term->val.str; 1437a6146d50SZheng Yan } else { 1438a6146d50SZheng Yan return NULL; 1439a6146d50SZheng Yan } 1440a6146d50SZheng Yan 14418d4b6d37SIan Rogers alias = perf_pmu__find_alias(pmu, name, /*load=*/ true); 1442e6ff1eedSIan Rogers if (alias || pmu->cpu_aliases_added) 1443e6ff1eedSIan Rogers return alias; 1444e6ff1eedSIan Rogers 1445e6ff1eedSIan Rogers /* Alias doesn't exist, try to get it from the json events. */ 1446e6ff1eedSIan Rogers if (pmu->events_table && 1447e6ff1eedSIan Rogers pmu_events_table__find_event(pmu->events_table, pmu, name, 1448e6ff1eedSIan Rogers pmu_add_cpu_aliases_map_callback, 1449e6ff1eedSIan Rogers pmu) == 0) { 14508d4b6d37SIan Rogers alias = perf_pmu__find_alias(pmu, name, /*load=*/ false); 1451e6ff1eedSIan Rogers } 1452e6ff1eedSIan Rogers return alias; 1453a6146d50SZheng Yan } 1454a6146d50SZheng Yan 1455410136f5SStephane Eranian 14567b723dbbSIan Rogers static int check_info_data(struct perf_pmu *pmu, 14577b723dbbSIan Rogers struct perf_pmu_alias *alias, 14589d31cb93SIan Rogers struct perf_pmu_info *info, 14599d31cb93SIan Rogers struct parse_events_error *err, 14609d31cb93SIan Rogers int column) 1461410136f5SStephane Eranian { 14627b723dbbSIan Rogers read_alias_info(pmu, alias); 1463410136f5SStephane Eranian /* 1464410136f5SStephane Eranian * Only one term in event definition can 14651d9e446bSJiri Olsa * define unit, scale and snapshot, fail 14661d9e446bSJiri Olsa * if there's more than one. 1467410136f5SStephane Eranian */ 14689d31cb93SIan Rogers if (info->unit && alias->unit[0]) { 14699d31cb93SIan Rogers parse_events_error__handle(err, column, 14709d31cb93SIan Rogers strdup("Attempt to set event's unit twice"), 14719d31cb93SIan Rogers NULL); 1472410136f5SStephane Eranian return -EINVAL; 14739d31cb93SIan Rogers } 14749d31cb93SIan Rogers if (info->scale && alias->scale) { 14759d31cb93SIan Rogers parse_events_error__handle(err, column, 14769d31cb93SIan Rogers strdup("Attempt to set event's scale twice"), 14779d31cb93SIan Rogers NULL); 14789d31cb93SIan Rogers return -EINVAL; 14799d31cb93SIan Rogers } 14809d31cb93SIan Rogers if (info->snapshot && alias->snapshot) { 14819d31cb93SIan Rogers parse_events_error__handle(err, column, 14829d31cb93SIan Rogers strdup("Attempt to set event snapshot twice"), 14839d31cb93SIan Rogers NULL); 14849d31cb93SIan Rogers return -EINVAL; 14859d31cb93SIan Rogers } 1486410136f5SStephane Eranian 1487b30a7d1fSArnaldo Carvalho de Melo if (alias->unit[0]) 14881d9e446bSJiri Olsa info->unit = alias->unit; 1489410136f5SStephane Eranian 1490410136f5SStephane Eranian if (alias->scale) 14911d9e446bSJiri Olsa info->scale = alias->scale; 14921d9e446bSJiri Olsa 14931d9e446bSJiri Olsa if (alias->snapshot) 14941d9e446bSJiri Olsa info->snapshot = alias->snapshot; 1495410136f5SStephane Eranian 1496410136f5SStephane Eranian return 0; 1497410136f5SStephane Eranian } 1498410136f5SStephane Eranian 1499a6146d50SZheng Yan /* 1500a6146d50SZheng Yan * Find alias in the terms list and replace it with the terms 1501a6146d50SZheng Yan * defined for the alias 1502a6146d50SZheng Yan */ 1503410136f5SStephane Eranian int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 15049d31cb93SIan Rogers struct perf_pmu_info *info, struct parse_events_error *err) 1505a6146d50SZheng Yan { 15066cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 15075c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1508a6146d50SZheng Yan int ret; 1509a6146d50SZheng Yan 1510044330c1SMatt Fleming info->per_pkg = false; 1511044330c1SMatt Fleming 15128a398897SStephane Eranian /* 15138a398897SStephane Eranian * Mark unit and scale as not set 15148a398897SStephane Eranian * (different from default values, see below) 15158a398897SStephane Eranian */ 151646441bdcSMatt Fleming info->unit = NULL; 151746441bdcSMatt Fleming info->scale = 0.0; 15181d9e446bSJiri Olsa info->snapshot = false; 1519410136f5SStephane Eranian 1520a6146d50SZheng Yan list_for_each_entry_safe(term, h, head_terms, list) { 1521a6146d50SZheng Yan alias = pmu_find_alias(pmu, term); 1522a6146d50SZheng Yan if (!alias) 1523a6146d50SZheng Yan continue; 1524a6146d50SZheng Yan ret = pmu_alias_terms(alias, &term->list); 15259d31cb93SIan Rogers if (ret) { 15269d31cb93SIan Rogers parse_events_error__handle(err, term->err_term, 15279d31cb93SIan Rogers strdup("Failure to duplicate terms"), 15289d31cb93SIan Rogers NULL); 1529a6146d50SZheng Yan return ret; 15309d31cb93SIan Rogers } 1531410136f5SStephane Eranian 15327b723dbbSIan Rogers ret = check_info_data(pmu, alias, info, err, term->err_term); 1533410136f5SStephane Eranian if (ret) 1534410136f5SStephane Eranian return ret; 1535410136f5SStephane Eranian 1536044330c1SMatt Fleming if (alias->per_pkg) 1537044330c1SMatt Fleming info->per_pkg = true; 1538044330c1SMatt Fleming 1539e56fbc9dSArnaldo Carvalho de Melo list_del_init(&term->list); 15401dc92556SIan Rogers parse_events_term__delete(term); 1541a6146d50SZheng Yan } 15428a398897SStephane Eranian 15438a398897SStephane Eranian /* 15448a398897SStephane Eranian * if no unit or scale found in aliases, then 15458a398897SStephane Eranian * set defaults as for evsel 15468a398897SStephane Eranian * unit cannot left to NULL 15478a398897SStephane Eranian */ 154846441bdcSMatt Fleming if (info->unit == NULL) 154946441bdcSMatt Fleming info->unit = ""; 15508a398897SStephane Eranian 155146441bdcSMatt Fleming if (info->scale == 0.0) 155246441bdcSMatt Fleming info->scale = 1.0; 15538a398897SStephane Eranian 1554a6146d50SZheng Yan return 0; 1555a6146d50SZheng Yan } 1556a6146d50SZheng Yan 1557c3245d20SIan Rogers struct find_event_args { 1558c3245d20SIan Rogers const char *event; 1559c3245d20SIan Rogers void *state; 1560c3245d20SIan Rogers pmu_event_callback cb; 1561c3245d20SIan Rogers }; 1562c3245d20SIan Rogers 1563c3245d20SIan Rogers static int find_event_callback(void *state, struct pmu_event_info *info) 1564838a8c5fSIan Rogers { 1565c3245d20SIan Rogers struct find_event_args *args = state; 1566838a8c5fSIan Rogers 1567c3245d20SIan Rogers if (!strcmp(args->event, info->name)) 1568c3245d20SIan Rogers return args->cb(args->state, info); 1569838a8c5fSIan Rogers 1570c3245d20SIan Rogers return 0; 1571838a8c5fSIan Rogers } 1572c3245d20SIan Rogers 1573c3245d20SIan Rogers int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb) 1574c3245d20SIan Rogers { 1575c3245d20SIan Rogers struct find_event_args args = { 1576c3245d20SIan Rogers .event = event, 1577c3245d20SIan Rogers .state = state, 1578c3245d20SIan Rogers .cb = cb, 1579c3245d20SIan Rogers }; 1580c3245d20SIan Rogers 1581c3245d20SIan Rogers return perf_pmu__for_each_event(pmu, &args, find_event_callback); 1582c3245d20SIan Rogers } 1583c3245d20SIan Rogers 1584804fee5dSIan Rogers static void perf_pmu__del_formats(struct list_head *formats) 1585d26383dcSNamhyung Kim { 1586d26383dcSNamhyung Kim struct perf_pmu_format *fmt, *tmp; 1587d26383dcSNamhyung Kim 1588d26383dcSNamhyung Kim list_for_each_entry_safe(fmt, tmp, formats, list) { 1589d26383dcSNamhyung Kim list_del(&fmt->list); 1590efe98a7aSArnaldo Carvalho de Melo zfree(&fmt->name); 1591d26383dcSNamhyung Kim free(fmt); 1592d26383dcSNamhyung Kim } 1593d26383dcSNamhyung Kim } 1594d26383dcSNamhyung Kim 159507d2b820SIan Rogers bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name) 159607d2b820SIan Rogers { 159707d2b820SIan Rogers struct perf_pmu_format *format; 159807d2b820SIan Rogers 159907d2b820SIan Rogers list_for_each_entry(format, &pmu->format, list) { 160007d2b820SIan Rogers if (!strcmp(format->name, name)) 160107d2b820SIan Rogers return true; 160207d2b820SIan Rogers } 160307d2b820SIan Rogers return false; 160407d2b820SIan Rogers } 160507d2b820SIan Rogers 1606d504fae9SJohn Garry bool is_pmu_core(const char *name) 1607d504fae9SJohn Garry { 16086fbd67b0SThomas Richter return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name); 16094bf7e81aSIan Rogers } 16104bf7e81aSIan Rogers 16116fd1e519SIan Rogers bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu) 16126fd1e519SIan Rogers { 1613e20d1f2fSIan Rogers return pmu->is_core; 16146fd1e519SIan Rogers } 16156fd1e519SIan Rogers 161652c7b4d3SIan Rogers bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) 161752c7b4d3SIan Rogers { 1618710dffc9SIan Rogers return !pmu->is_core || perf_pmus__num_core_pmus() == 1; 161952c7b4d3SIan Rogers } 162052c7b4d3SIan Rogers 1621e6ff1eedSIan Rogers bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) 1622abe9544eSIan Rogers { 16238d4b6d37SIan Rogers if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL) 1624e6ff1eedSIan Rogers return true; 1625e6ff1eedSIan Rogers if (pmu->cpu_aliases_added || !pmu->events_table) 1626e6ff1eedSIan Rogers return false; 1627e6ff1eedSIan Rogers return pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0; 16284cabc3d1SAndi Kleen } 1629c3245d20SIan Rogers 1630e6ff1eedSIan Rogers size_t perf_pmu__num_events(struct perf_pmu *pmu) 1631c3245d20SIan Rogers { 16328d4b6d37SIan Rogers size_t nr; 16338d4b6d37SIan Rogers 16348d4b6d37SIan Rogers if (!pmu->sysfs_aliases_loaded) 16358d4b6d37SIan Rogers pmu_aliases_parse(pmu); 16368d4b6d37SIan Rogers 16378d4b6d37SIan Rogers nr = pmu->sysfs_aliases; 1638c3245d20SIan Rogers 1639e6ff1eedSIan Rogers if (pmu->cpu_aliases_added) 1640e6ff1eedSIan Rogers nr += pmu->loaded_json_aliases; 1641e6ff1eedSIan Rogers else if (pmu->events_table) 1642e6ff1eedSIan Rogers nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->loaded_json_aliases; 1643c3245d20SIan Rogers 1644c3245d20SIan Rogers return pmu->selectable ? nr + 1 : nr; 1645c3245d20SIan Rogers } 1646c3245d20SIan Rogers 1647c3245d20SIan Rogers static int sub_non_neg(int a, int b) 1648c3245d20SIan Rogers { 1649c3245d20SIan Rogers if (b > a) 1650c3245d20SIan Rogers return 0; 1651c3245d20SIan Rogers return a - b; 1652c3245d20SIan Rogers } 1653c3245d20SIan Rogers 1654c3245d20SIan Rogers static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, 1655c3245d20SIan Rogers const struct perf_pmu_alias *alias) 1656c3245d20SIan Rogers { 1657c3245d20SIan Rogers struct parse_events_term *term; 1658c3245d20SIan Rogers int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); 1659c3245d20SIan Rogers 1660c3245d20SIan Rogers list_for_each_entry(term, &alias->terms, list) { 1661c3245d20SIan Rogers if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 1662c3245d20SIan Rogers used += snprintf(buf + used, sub_non_neg(len, used), 1663c3245d20SIan Rogers ",%s=%s", term->config, 1664c3245d20SIan Rogers term->val.str); 1665c3245d20SIan Rogers } 1666c3245d20SIan Rogers 1667c3245d20SIan Rogers if (sub_non_neg(len, used) > 0) { 1668c3245d20SIan Rogers buf[used] = '/'; 1669c3245d20SIan Rogers used++; 1670c3245d20SIan Rogers } 1671c3245d20SIan Rogers if (sub_non_neg(len, used) > 0) { 1672c3245d20SIan Rogers buf[used] = '\0'; 1673c3245d20SIan Rogers used++; 1674c3245d20SIan Rogers } else 1675c3245d20SIan Rogers buf[len - 1] = '\0'; 1676c3245d20SIan Rogers 1677c3245d20SIan Rogers return buf; 1678c3245d20SIan Rogers } 1679c3245d20SIan Rogers 1680e6ff1eedSIan Rogers int perf_pmu__for_each_event(struct perf_pmu *pmu, void *state, pmu_event_callback cb) 1681c3245d20SIan Rogers { 1682c3245d20SIan Rogers char buf[1024]; 1683c3245d20SIan Rogers struct perf_pmu_alias *event; 1684c3245d20SIan Rogers struct pmu_event_info info = { 1685c3245d20SIan Rogers .pmu = pmu, 1686c3245d20SIan Rogers }; 1687c3245d20SIan Rogers int ret = 0; 1688c3245d20SIan Rogers 1689e6ff1eedSIan Rogers pmu_add_cpu_aliases(pmu); 1690c3245d20SIan Rogers list_for_each_entry(event, &pmu->aliases, list) { 1691c3245d20SIan Rogers size_t buf_used; 1692c3245d20SIan Rogers 1693c3245d20SIan Rogers info.pmu_name = event->pmu_name ?: pmu->name; 1694c3245d20SIan Rogers info.alias = NULL; 1695c3245d20SIan Rogers if (event->desc) { 1696c3245d20SIan Rogers info.name = event->name; 1697c3245d20SIan Rogers buf_used = 0; 1698c3245d20SIan Rogers } else { 1699c3245d20SIan Rogers info.name = format_alias(buf, sizeof(buf), pmu, event); 1700c3245d20SIan Rogers if (pmu->is_core) { 1701c3245d20SIan Rogers info.alias = info.name; 1702c3245d20SIan Rogers info.name = event->name; 1703c3245d20SIan Rogers } 1704c3245d20SIan Rogers buf_used = strlen(buf) + 1; 1705c3245d20SIan Rogers } 1706c3245d20SIan Rogers info.scale_unit = NULL; 1707c3245d20SIan Rogers if (strlen(event->unit) || event->scale != 1.0) { 1708c3245d20SIan Rogers info.scale_unit = buf + buf_used; 1709c3245d20SIan Rogers buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 1710c3245d20SIan Rogers "%G%s", event->scale, event->unit) + 1; 1711c3245d20SIan Rogers } 1712c3245d20SIan Rogers info.desc = event->desc; 1713c3245d20SIan Rogers info.long_desc = event->long_desc; 1714c3245d20SIan Rogers info.encoding_desc = buf + buf_used; 1715c3245d20SIan Rogers buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 1716c3245d20SIan Rogers "%s/%s/", info.pmu_name, event->str) + 1; 1717c3245d20SIan Rogers info.topic = event->topic; 1718c3245d20SIan Rogers info.str = event->str; 1719c3245d20SIan Rogers info.deprecated = event->deprecated; 1720c3245d20SIan Rogers ret = cb(state, &info); 1721c3245d20SIan Rogers if (ret) 1722c3245d20SIan Rogers return ret; 1723c3245d20SIan Rogers } 1724c3245d20SIan Rogers if (pmu->selectable) { 1725c3245d20SIan Rogers info.name = buf; 1726c3245d20SIan Rogers snprintf(buf, sizeof(buf), "%s//", pmu->name); 1727c3245d20SIan Rogers info.alias = NULL; 1728c3245d20SIan Rogers info.scale_unit = NULL; 1729c3245d20SIan Rogers info.desc = NULL; 1730c3245d20SIan Rogers info.long_desc = NULL; 1731c3245d20SIan Rogers info.encoding_desc = NULL; 1732c3245d20SIan Rogers info.topic = NULL; 1733c3245d20SIan Rogers info.pmu_name = pmu->name; 1734c3245d20SIan Rogers info.deprecated = false; 1735c3245d20SIan Rogers ret = cb(state, &info); 1736c3245d20SIan Rogers } 1737c3245d20SIan Rogers return ret; 17384cabc3d1SAndi Kleen } 17397d4bdab5SAdrian Hunter 1740e3edd6cfSIan Rogers bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name) 1741e3edd6cfSIan Rogers { 1742e3edd6cfSIan Rogers return !strcmp(pmu->name, pmu_name) || 1743e3edd6cfSIan Rogers (pmu->is_uncore && pmu_uncore_alias_match(pmu_name, pmu->name)); 1744e3edd6cfSIan Rogers } 1745e3edd6cfSIan Rogers 1746251aa040SIan Rogers bool perf_pmu__is_software(const struct perf_pmu *pmu) 1747251aa040SIan Rogers { 1748251aa040SIan Rogers if (pmu->is_core || pmu->is_uncore || pmu->auxtrace) 1749251aa040SIan Rogers return false; 1750251aa040SIan Rogers switch (pmu->type) { 1751251aa040SIan Rogers case PERF_TYPE_HARDWARE: return false; 1752251aa040SIan Rogers case PERF_TYPE_SOFTWARE: return true; 1753251aa040SIan Rogers case PERF_TYPE_TRACEPOINT: return true; 1754251aa040SIan Rogers case PERF_TYPE_HW_CACHE: return false; 1755251aa040SIan Rogers case PERF_TYPE_RAW: return false; 1756251aa040SIan Rogers case PERF_TYPE_BREAKPOINT: return true; 1757251aa040SIan Rogers default: break; 1758251aa040SIan Rogers } 1759251aa040SIan Rogers return !strcmp(pmu->name, "kprobe") || !strcmp(pmu->name, "uprobe"); 1760251aa040SIan Rogers } 1761251aa040SIan Rogers 1762d50a79cdSJames Clark FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) 17637d4bdab5SAdrian Hunter { 17647d4bdab5SAdrian Hunter char path[PATH_MAX]; 17657d4bdab5SAdrian Hunter 1766f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name) || 1767f8ad6018SJames Clark !file_available(path)) 17687d4bdab5SAdrian Hunter return NULL; 17697d4bdab5SAdrian Hunter 17707d4bdab5SAdrian Hunter return fopen(path, "r"); 17717d4bdab5SAdrian Hunter } 17727d4bdab5SAdrian Hunter 17733a69672eSNamhyung Kim FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name) 17743a69672eSNamhyung Kim { 17753a69672eSNamhyung Kim int fd; 17763a69672eSNamhyung Kim 17773a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, pmu->name, name, O_RDONLY); 17783a69672eSNamhyung Kim if (fd < 0) 17793a69672eSNamhyung Kim return NULL; 17803a69672eSNamhyung Kim 17813a69672eSNamhyung Kim return fdopen(fd, "r"); 17823a69672eSNamhyung Kim } 17833a69672eSNamhyung Kim 17847d4bdab5SAdrian Hunter int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 17857d4bdab5SAdrian Hunter ...) 17867d4bdab5SAdrian Hunter { 17877d4bdab5SAdrian Hunter va_list args; 17887d4bdab5SAdrian Hunter FILE *file; 17897d4bdab5SAdrian Hunter int ret = EOF; 17907d4bdab5SAdrian Hunter 17917d4bdab5SAdrian Hunter va_start(args, fmt); 17927d4bdab5SAdrian Hunter file = perf_pmu__open_file(pmu, name); 17937d4bdab5SAdrian Hunter if (file) { 17947d4bdab5SAdrian Hunter ret = vfscanf(file, fmt, args); 17957d4bdab5SAdrian Hunter fclose(file); 17967d4bdab5SAdrian Hunter } 17977d4bdab5SAdrian Hunter va_end(args); 17987d4bdab5SAdrian Hunter return ret; 17997d4bdab5SAdrian Hunter } 18009fbc61f8SKan Liang 18013a69672eSNamhyung Kim int perf_pmu__scan_file_at(struct perf_pmu *pmu, int dirfd, const char *name, 18023a69672eSNamhyung Kim const char *fmt, ...) 18033a69672eSNamhyung Kim { 18043a69672eSNamhyung Kim va_list args; 18053a69672eSNamhyung Kim FILE *file; 18063a69672eSNamhyung Kim int ret = EOF; 18073a69672eSNamhyung Kim 18083a69672eSNamhyung Kim va_start(args, fmt); 18093a69672eSNamhyung Kim file = perf_pmu__open_file_at(pmu, dirfd, name); 18103a69672eSNamhyung Kim if (file) { 18113a69672eSNamhyung Kim ret = vfscanf(file, fmt, args); 18123a69672eSNamhyung Kim fclose(file); 18133a69672eSNamhyung Kim } 18143a69672eSNamhyung Kim va_end(args); 18153a69672eSNamhyung Kim return ret; 18163a69672eSNamhyung Kim } 18173a69672eSNamhyung Kim 1818c2b6a896SGerman Gomez bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name) 1819c2b6a896SGerman Gomez { 1820c2b6a896SGerman Gomez char path[PATH_MAX]; 1821c2b6a896SGerman Gomez 1822c2b6a896SGerman Gomez if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name)) 1823c2b6a896SGerman Gomez return false; 1824c2b6a896SGerman Gomez 1825c2b6a896SGerman Gomez return file_available(path); 1826c2b6a896SGerman Gomez } 1827c2b6a896SGerman Gomez 18289fbc61f8SKan Liang static int perf_pmu__new_caps(struct list_head *list, char *name, char *value) 18299fbc61f8SKan Liang { 18309fbc61f8SKan Liang struct perf_pmu_caps *caps = zalloc(sizeof(*caps)); 18319fbc61f8SKan Liang 18329fbc61f8SKan Liang if (!caps) 18339fbc61f8SKan Liang return -ENOMEM; 18349fbc61f8SKan Liang 18359fbc61f8SKan Liang caps->name = strdup(name); 18369fbc61f8SKan Liang if (!caps->name) 18379fbc61f8SKan Liang goto free_caps; 18389fbc61f8SKan Liang caps->value = strndup(value, strlen(value) - 1); 18399fbc61f8SKan Liang if (!caps->value) 18409fbc61f8SKan Liang goto free_name; 18419fbc61f8SKan Liang list_add_tail(&caps->list, list); 18429fbc61f8SKan Liang return 0; 18439fbc61f8SKan Liang 18449fbc61f8SKan Liang free_name: 184557f14b5aSArnaldo Carvalho de Melo zfree(&caps->name); 18469fbc61f8SKan Liang free_caps: 18479fbc61f8SKan Liang free(caps); 18489fbc61f8SKan Liang 18499fbc61f8SKan Liang return -ENOMEM; 18509fbc61f8SKan Liang } 18519fbc61f8SKan Liang 1852eec11310SNamhyung Kim static void perf_pmu__del_caps(struct perf_pmu *pmu) 1853eec11310SNamhyung Kim { 1854eec11310SNamhyung Kim struct perf_pmu_caps *caps, *tmp; 1855eec11310SNamhyung Kim 1856eec11310SNamhyung Kim list_for_each_entry_safe(caps, tmp, &pmu->caps, list) { 1857eec11310SNamhyung Kim list_del(&caps->list); 1858efe98a7aSArnaldo Carvalho de Melo zfree(&caps->name); 1859efe98a7aSArnaldo Carvalho de Melo zfree(&caps->value); 1860eec11310SNamhyung Kim free(caps); 1861eec11310SNamhyung Kim } 1862eec11310SNamhyung Kim } 1863eec11310SNamhyung Kim 18649fbc61f8SKan Liang /* 18659fbc61f8SKan Liang * Reading/parsing the given pmu capabilities, which should be located at: 18669fbc61f8SKan Liang * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes. 18679fbc61f8SKan Liang * Return the number of capabilities 18689fbc61f8SKan Liang */ 18699fbc61f8SKan Liang int perf_pmu__caps_parse(struct perf_pmu *pmu) 18709fbc61f8SKan Liang { 18719fbc61f8SKan Liang struct stat st; 18729fbc61f8SKan Liang char caps_path[PATH_MAX]; 18739fbc61f8SKan Liang DIR *caps_dir; 18749fbc61f8SKan Liang struct dirent *evt_ent; 1875b39094d3SNamhyung Kim int caps_fd; 18763339ec44SRavi Bangoria 18773339ec44SRavi Bangoria if (pmu->caps_initialized) 18783339ec44SRavi Bangoria return pmu->nr_caps; 18793339ec44SRavi Bangoria 18803339ec44SRavi Bangoria pmu->nr_caps = 0; 18819fbc61f8SKan Liang 1882f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(caps_path, sizeof(caps_path), pmu->name, "caps")) 18839fbc61f8SKan Liang return -1; 18849fbc61f8SKan Liang 18853339ec44SRavi Bangoria if (stat(caps_path, &st) < 0) { 18863339ec44SRavi Bangoria pmu->caps_initialized = true; 18879fbc61f8SKan Liang return 0; /* no error if caps does not exist */ 18883339ec44SRavi Bangoria } 18899fbc61f8SKan Liang 18909fbc61f8SKan Liang caps_dir = opendir(caps_path); 18919fbc61f8SKan Liang if (!caps_dir) 18929fbc61f8SKan Liang return -EINVAL; 18939fbc61f8SKan Liang 1894b39094d3SNamhyung Kim caps_fd = dirfd(caps_dir); 1895b39094d3SNamhyung Kim 18969fbc61f8SKan Liang while ((evt_ent = readdir(caps_dir)) != NULL) { 18979fbc61f8SKan Liang char *name = evt_ent->d_name; 18989fbc61f8SKan Liang char value[128]; 18999fbc61f8SKan Liang FILE *file; 1900b39094d3SNamhyung Kim int fd; 19019fbc61f8SKan Liang 19029fbc61f8SKan Liang if (!strcmp(name, ".") || !strcmp(name, "..")) 19039fbc61f8SKan Liang continue; 19049fbc61f8SKan Liang 1905b39094d3SNamhyung Kim fd = openat(caps_fd, name, O_RDONLY); 19060ea8920eSIan Rogers if (fd == -1) 19079fbc61f8SKan Liang continue; 19080ea8920eSIan Rogers file = fdopen(fd, "r"); 19090ea8920eSIan Rogers if (!file) { 19100ea8920eSIan Rogers close(fd); 19110ea8920eSIan Rogers continue; 19120ea8920eSIan Rogers } 19139fbc61f8SKan Liang 19149fbc61f8SKan Liang if (!fgets(value, sizeof(value), file) || 19159fbc61f8SKan Liang (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) { 19169fbc61f8SKan Liang fclose(file); 19179fbc61f8SKan Liang continue; 19189fbc61f8SKan Liang } 19199fbc61f8SKan Liang 19203339ec44SRavi Bangoria pmu->nr_caps++; 19219fbc61f8SKan Liang fclose(file); 19229fbc61f8SKan Liang } 19239fbc61f8SKan Liang 19249fbc61f8SKan Liang closedir(caps_dir); 19259fbc61f8SKan Liang 19263339ec44SRavi Bangoria pmu->caps_initialized = true; 19273339ec44SRavi Bangoria return pmu->nr_caps; 19289fbc61f8SKan Liang } 1929e4064776SJin Yao 1930b9f01032SIan Rogers static void perf_pmu__compute_config_masks(struct perf_pmu *pmu) 1931e4064776SJin Yao { 1932e4064776SJin Yao struct perf_pmu_format *format; 1933b9f01032SIan Rogers 1934b9f01032SIan Rogers if (pmu->config_masks_computed) 1935b9f01032SIan Rogers return; 1936e4064776SJin Yao 1937e4064776SJin Yao list_for_each_entry(format, &pmu->format, list) { 1938b9f01032SIan Rogers unsigned int i; 1939b9f01032SIan Rogers __u64 *mask; 1940b9f01032SIan Rogers 1941b9f01032SIan Rogers if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) 1942e4064776SJin Yao continue; 1943e4064776SJin Yao 1944b9f01032SIan Rogers pmu->config_masks_present = true; 1945b9f01032SIan Rogers mask = &pmu->config_masks[format->value]; 1946b9f01032SIan Rogers 1947e4064776SJin Yao for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS) 1948b9f01032SIan Rogers *mask |= 1ULL << i; 1949e4064776SJin Yao } 1950b9f01032SIan Rogers pmu->config_masks_computed = true; 1951b9f01032SIan Rogers } 1952b9f01032SIan Rogers 1953b9f01032SIan Rogers void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 1954b9f01032SIan Rogers const char *name, int config_num, 1955b9f01032SIan Rogers const char *config_name) 1956b9f01032SIan Rogers { 1957b9f01032SIan Rogers __u64 bits; 1958b9f01032SIan Rogers char buf[100]; 1959b9f01032SIan Rogers 1960b9f01032SIan Rogers perf_pmu__compute_config_masks(pmu); 1961e4064776SJin Yao 1962e4064776SJin Yao /* 1963e4064776SJin Yao * Kernel doesn't export any valid format bits. 1964e4064776SJin Yao */ 1965b9f01032SIan Rogers if (!pmu->config_masks_present) 1966e4064776SJin Yao return; 1967e4064776SJin Yao 1968b9f01032SIan Rogers bits = config & ~pmu->config_masks[config_num]; 1969e4064776SJin Yao if (bits == 0) 1970e4064776SJin Yao return; 1971e4064776SJin Yao 1972e4064776SJin Yao bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf)); 1973e4064776SJin Yao 1974b9f01032SIan Rogers pr_warning("WARNING: event '%s' not valid (bits %s of %s " 1975e4064776SJin Yao "'%llx' not supported by kernel)!\n", 1976b9f01032SIan Rogers name ?: "N/A", buf, config_name, config); 1977e4064776SJin Yao } 1978c5a26ea4SJin Yao 1979c091ee90SIan Rogers int perf_pmu__match(const char *pattern, const char *name, const char *tok) 1980c47a5599SJin Yao { 198113d60ba0SKan Liang if (!name) 198213d60ba0SKan Liang return -1; 198313d60ba0SKan Liang 1984c47a5599SJin Yao if (fnmatch(pattern, name, 0)) 1985c47a5599SJin Yao return -1; 1986c47a5599SJin Yao 1987240e6fd0SIan Rogers if (tok && !perf_pmu__match_ignoring_suffix(name, tok)) 1988c47a5599SJin Yao return -1; 1989c47a5599SJin Yao 1990c47a5599SJin Yao return 0; 1991c47a5599SJin Yao } 19921d3351e6SJin Yao 1993acef233bSJing Zhang double __weak perf_pmu__cpu_slots_per_cycle(void) 1994acef233bSJing Zhang { 1995acef233bSJing Zhang return NAN; 1996acef233bSJing Zhang } 1997f8ad6018SJames Clark 1998f8ad6018SJames Clark int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size) 1999f8ad6018SJames Clark { 2000f8ad6018SJames Clark const char *sysfs = sysfs__mountpoint(); 2001f8ad6018SJames Clark 2002f8ad6018SJames Clark if (!sysfs) 2003f8ad6018SJames Clark return 0; 2004f8ad6018SJames Clark return scnprintf(pathname, size, "%s/bus/event_source/devices/", sysfs); 2005f8ad6018SJames Clark } 2006f8ad6018SJames Clark 2007e293a5e8SNamhyung Kim int perf_pmu__event_source_devices_fd(void) 2008e293a5e8SNamhyung Kim { 2009e293a5e8SNamhyung Kim char path[PATH_MAX]; 2010e293a5e8SNamhyung Kim const char *sysfs = sysfs__mountpoint(); 2011e293a5e8SNamhyung Kim 2012e293a5e8SNamhyung Kim if (!sysfs) 2013e293a5e8SNamhyung Kim return -1; 2014e293a5e8SNamhyung Kim 2015e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs); 2016e293a5e8SNamhyung Kim return open(path, O_DIRECTORY); 2017e293a5e8SNamhyung Kim } 2018e293a5e8SNamhyung Kim 2019f8ad6018SJames Clark /* 2020f8ad6018SJames Clark * Fill 'buf' with the path to a file or folder in 'pmu_name' in 2021f8ad6018SJames Clark * sysfs. For example if pmu_name = "cs_etm" and 'filename' = "format" 2022f8ad6018SJames Clark * then pathname will be filled with 2023f8ad6018SJames Clark * "/sys/bus/event_source/devices/cs_etm/format" 2024f8ad6018SJames Clark * 2025e1a3aad3SIan Rogers * Return 0 if the sysfs mountpoint couldn't be found, if no characters were 2026e1a3aad3SIan Rogers * written or if the buffer size is exceeded. 2027f8ad6018SJames Clark */ 2028f8ad6018SJames Clark int perf_pmu__pathname_scnprintf(char *buf, size_t size, 2029f8ad6018SJames Clark const char *pmu_name, const char *filename) 2030f8ad6018SJames Clark { 2031e1a3aad3SIan Rogers size_t len; 2032f8ad6018SJames Clark 2033e1a3aad3SIan Rogers len = perf_pmu__event_source_devices_scnprintf(buf, size); 2034e1a3aad3SIan Rogers if (!len || (len + strlen(pmu_name) + strlen(filename) + 1) >= size) 2035f8ad6018SJames Clark return 0; 2036e1a3aad3SIan Rogers 2037e1a3aad3SIan Rogers return scnprintf(buf + len, size - len, "%s/%s", pmu_name, filename); 2038f8ad6018SJames Clark } 2039eec11310SNamhyung Kim 2040e293a5e8SNamhyung Kim int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags) 2041e293a5e8SNamhyung Kim { 2042e293a5e8SNamhyung Kim char path[PATH_MAX]; 2043e293a5e8SNamhyung Kim 2044e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/%s", pmu_name, filename); 2045e293a5e8SNamhyung Kim return openat(dirfd, path, flags); 2046e293a5e8SNamhyung Kim } 2047e293a5e8SNamhyung Kim 20481eaf496eSIan Rogers void perf_pmu__delete(struct perf_pmu *pmu) 2049eec11310SNamhyung Kim { 2050eec11310SNamhyung Kim perf_pmu__del_formats(&pmu->format); 2051eec11310SNamhyung Kim perf_pmu__del_aliases(pmu); 2052eec11310SNamhyung Kim perf_pmu__del_caps(pmu); 2053eec11310SNamhyung Kim 2054eec11310SNamhyung Kim perf_cpu_map__put(pmu->cpus); 2055eec11310SNamhyung Kim 2056efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->default_config); 2057efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 2058efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->alias_name); 2059*b7823045SIan Rogers zfree(&pmu->id); 2060eec11310SNamhyung Kim free(pmu); 2061eec11310SNamhyung Kim } 20629d5da30eSJames Clark 20639d5da30eSJames Clark struct perf_pmu *pmu__find_core_pmu(void) 20649d5da30eSJames Clark { 20659d5da30eSJames Clark struct perf_pmu *pmu = NULL; 20669d5da30eSJames Clark 20679d5da30eSJames Clark while ((pmu = perf_pmus__scan_core(pmu))) { 20689d5da30eSJames Clark /* 20699d5da30eSJames Clark * The cpumap should cover all CPUs. Otherwise, some CPUs may 20709d5da30eSJames Clark * not support some events or have different event IDs. 20719d5da30eSJames Clark */ 20729d5da30eSJames Clark if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu) 20739d5da30eSJames Clark return NULL; 20749d5da30eSJames Clark 20759d5da30eSJames Clark return pmu; 20769d5da30eSJames Clark } 20779d5da30eSJames Clark return NULL; 20789d5da30eSJames Clark } 2079