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 32e46fc8d9SArnaldo Carvalho de Melo struct perf_pmu perf_pmu__fake; 33e46fc8d9SArnaldo Carvalho de Melo 34c3245d20SIan Rogers #define UNIT_MAX_LEN 31 /* max length for event unit name */ 35c3245d20SIan Rogers 36c3245d20SIan Rogers /** 37c3245d20SIan Rogers * struct perf_pmu_alias - An event either read from sysfs or builtin in 38c3245d20SIan Rogers * pmu-events.c, created by parsing the pmu-events json files. 39c3245d20SIan Rogers */ 40c3245d20SIan Rogers struct perf_pmu_alias { 41c3245d20SIan Rogers /** @name: Name of the event like "mem-loads". */ 42c3245d20SIan Rogers char *name; 43c3245d20SIan Rogers /** @desc: Optional short description of the event. */ 44c3245d20SIan Rogers char *desc; 45c3245d20SIan Rogers /** @long_desc: Optional long description. */ 46c3245d20SIan Rogers char *long_desc; 47c3245d20SIan Rogers /** 48c3245d20SIan Rogers * @topic: Optional topic such as cache or pipeline, particularly for 49c3245d20SIan Rogers * json events. 50c3245d20SIan Rogers */ 51c3245d20SIan Rogers char *topic; 52c3245d20SIan Rogers /** 53c3245d20SIan Rogers * @str: Comma separated parameter list like 54c3245d20SIan Rogers * "event=0xcd,umask=0x1,ldlat=0x3". 55c3245d20SIan Rogers */ 56c3245d20SIan Rogers char *str; 57c3245d20SIan Rogers /** @terms: Owned list of the original parsed parameters. */ 58c3245d20SIan Rogers struct list_head terms; 59c3245d20SIan Rogers /** @list: List element of struct perf_pmu aliases. */ 60c3245d20SIan Rogers struct list_head list; 61c3245d20SIan Rogers /** @unit: Units for the event, such as bytes or cache lines. */ 62c3245d20SIan Rogers char unit[UNIT_MAX_LEN+1]; 63c3245d20SIan Rogers /** @scale: Value to scale read counter values by. */ 64c3245d20SIan Rogers double scale; 65c3245d20SIan Rogers /** 66c3245d20SIan Rogers * @per_pkg: Does the file 67c3245d20SIan Rogers * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.per-pkg or 68c3245d20SIan Rogers * equivalent json value exist and have the value 1. 69c3245d20SIan Rogers */ 70c3245d20SIan Rogers bool per_pkg; 71c3245d20SIan Rogers /** 72c3245d20SIan Rogers * @snapshot: Does the file 73c3245d20SIan Rogers * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.snapshot 74c3245d20SIan Rogers * exist and have the value 1. 75c3245d20SIan Rogers */ 76c3245d20SIan Rogers bool snapshot; 77c3245d20SIan Rogers /** 78c3245d20SIan Rogers * @deprecated: Is the event hidden and so not shown in perf list by 79c3245d20SIan Rogers * default. 80c3245d20SIan Rogers */ 81c3245d20SIan Rogers bool deprecated; 82c3245d20SIan Rogers /** 83c3245d20SIan Rogers * @pmu_name: The name copied from the json struct pmu_event. This can 84c3245d20SIan Rogers * differ from the PMU name as it won't have suffixes. 85c3245d20SIan Rogers */ 86c3245d20SIan Rogers char *pmu_name; 87c3245d20SIan Rogers }; 88c3245d20SIan Rogers 89fe13d43dSIan Rogers /** 90fe13d43dSIan Rogers * struct perf_pmu_format - Values from a format file read from 91fe13d43dSIan Rogers * <sysfs>/devices/cpu/format/ held in struct perf_pmu. 92fe13d43dSIan Rogers * 93fe13d43dSIan Rogers * For example, the contents of <sysfs>/devices/cpu/format/event may be 94fe13d43dSIan Rogers * "config:0-7" and will be represented here as name="event", 95fe13d43dSIan Rogers * value=PERF_PMU_FORMAT_VALUE_CONFIG and bits 0 to 7 will be set. 96fe13d43dSIan Rogers */ 97ab1bf653SArnaldo Carvalho de Melo struct perf_pmu_format { 9850402641SIan Rogers /** @list: Element on list within struct perf_pmu. */ 9950402641SIan Rogers struct list_head list; 10050402641SIan Rogers /** @bits: Which config bits are set by this format value. */ 10150402641SIan Rogers DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); 102fe13d43dSIan Rogers /** @name: The modifier/file name. */ 103ab1bf653SArnaldo Carvalho de Melo char *name; 104fe13d43dSIan Rogers /** 105fe13d43dSIan Rogers * @value : Which config value the format relates to. Supported values 106fe13d43dSIan Rogers * are from PERF_PMU_FORMAT_VALUE_CONFIG to 107fe13d43dSIan Rogers * PERF_PMU_FORMAT_VALUE_CONFIG_END. 108fe13d43dSIan Rogers */ 10950402641SIan Rogers u16 value; 11050402641SIan Rogers /** @loaded: Has the contents been loaded/parsed. */ 11150402641SIan Rogers bool loaded; 112ab1bf653SArnaldo Carvalho de Melo }; 113ab1bf653SArnaldo Carvalho de Melo 11450402641SIan Rogers static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name) 11550402641SIan Rogers { 11650402641SIan Rogers struct perf_pmu_format *format; 11750402641SIan Rogers 11850402641SIan Rogers format = zalloc(sizeof(*format)); 11950402641SIan Rogers if (!format) 12050402641SIan Rogers return NULL; 12150402641SIan Rogers 12250402641SIan Rogers format->name = strdup(name); 12350402641SIan Rogers if (!format->name) { 12450402641SIan Rogers free(format); 12550402641SIan Rogers return NULL; 12650402641SIan Rogers } 12750402641SIan Rogers list_add_tail(&format->list, list); 12850402641SIan Rogers return format; 12950402641SIan Rogers } 13050402641SIan Rogers 13150402641SIan Rogers /* Called at the end of parsing a format. */ 13250402641SIan Rogers void perf_pmu_format__set_value(void *vformat, int config, unsigned long *bits) 13350402641SIan Rogers { 13450402641SIan Rogers struct perf_pmu_format *format = vformat; 13550402641SIan Rogers 13650402641SIan Rogers format->value = config; 13750402641SIan Rogers memcpy(format->bits, bits, sizeof(format->bits)); 13850402641SIan Rogers } 13950402641SIan Rogers 14050402641SIan Rogers static void __perf_pmu_format__load(struct perf_pmu_format *format, FILE *file) 14150402641SIan Rogers { 14250402641SIan Rogers void *scanner; 14350402641SIan Rogers int ret; 14450402641SIan Rogers 14550402641SIan Rogers ret = perf_pmu_lex_init(&scanner); 14650402641SIan Rogers if (ret) 14750402641SIan Rogers return; 14850402641SIan Rogers 14950402641SIan Rogers perf_pmu_set_in(file, scanner); 15050402641SIan Rogers ret = perf_pmu_parse(format, scanner); 15150402641SIan Rogers perf_pmu_lex_destroy(scanner); 15250402641SIan Rogers format->loaded = true; 15350402641SIan Rogers } 15450402641SIan Rogers 15550402641SIan Rogers static void perf_pmu_format__load(struct perf_pmu *pmu, struct perf_pmu_format *format) 15650402641SIan Rogers { 15750402641SIan Rogers char path[PATH_MAX]; 15850402641SIan Rogers FILE *file = NULL; 15950402641SIan Rogers 16050402641SIan Rogers if (format->loaded) 16150402641SIan Rogers return; 16250402641SIan Rogers 16350402641SIan Rogers if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, "format")) 16450402641SIan Rogers return; 16550402641SIan Rogers 16650402641SIan Rogers assert(strlen(path) + strlen(format->name) + 2 < sizeof(path)); 16750402641SIan Rogers strcat(path, "/"); 16850402641SIan Rogers strcat(path, format->name); 16950402641SIan Rogers 17050402641SIan Rogers file = fopen(path, "r"); 17150402641SIan Rogers if (!file) 17250402641SIan Rogers return; 17350402641SIan Rogers __perf_pmu_format__load(format, file); 17450402641SIan Rogers fclose(file); 17550402641SIan Rogers } 17650402641SIan Rogers 177cd82a32eSJiri Olsa /* 178cd82a32eSJiri Olsa * Parse & process all the sysfs attributes located under 179cd82a32eSJiri Olsa * the directory specified in 'dir' parameter. 180cd82a32eSJiri Olsa */ 18150402641SIan Rogers int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load) 182cd82a32eSJiri Olsa { 183cd82a32eSJiri Olsa struct dirent *evt_ent; 184cd82a32eSJiri Olsa DIR *format_dir; 185cd82a32eSJiri Olsa int ret = 0; 186cd82a32eSJiri Olsa 187e293a5e8SNamhyung Kim format_dir = fdopendir(dirfd); 188cd82a32eSJiri Olsa if (!format_dir) 189cd82a32eSJiri Olsa return -EINVAL; 190cd82a32eSJiri Olsa 19150402641SIan Rogers while ((evt_ent = readdir(format_dir)) != NULL) { 19250402641SIan Rogers struct perf_pmu_format *format; 193cd82a32eSJiri Olsa char *name = evt_ent->d_name; 194cd82a32eSJiri Olsa 195cd82a32eSJiri Olsa if (!strcmp(name, ".") || !strcmp(name, "..")) 196cd82a32eSJiri Olsa continue; 197cd82a32eSJiri Olsa 19850402641SIan Rogers format = perf_pmu__new_format(&pmu->format, name); 19950402641SIan Rogers if (!format) { 20050402641SIan Rogers ret = -ENOMEM; 201cd82a32eSJiri Olsa break; 20250402641SIan Rogers } 203cd82a32eSJiri Olsa 20450402641SIan Rogers if (eager_load) { 20550402641SIan Rogers FILE *file; 20650402641SIan Rogers int fd = openat(dirfd, name, O_RDONLY); 20750402641SIan Rogers 20850402641SIan Rogers if (fd < 0) { 20950402641SIan Rogers ret = -errno; 21050402641SIan Rogers break; 21150402641SIan Rogers } 2123d88aec0SIan Rogers file = fdopen(fd, "r"); 2133d88aec0SIan Rogers if (!file) { 2143d88aec0SIan Rogers close(fd); 2153d88aec0SIan Rogers break; 2163d88aec0SIan Rogers } 21750402641SIan Rogers __perf_pmu_format__load(format, file); 2183d88aec0SIan Rogers fclose(file); 2193d88aec0SIan Rogers } 220cd82a32eSJiri Olsa } 221cd82a32eSJiri Olsa 222cd82a32eSJiri Olsa closedir(format_dir); 223cd82a32eSJiri Olsa return ret; 224cd82a32eSJiri Olsa } 225cd82a32eSJiri Olsa 226cd82a32eSJiri Olsa /* 227cd82a32eSJiri Olsa * Reading/parsing the default pmu format definition, which should be 228cd82a32eSJiri Olsa * located at: 229cd82a32eSJiri Olsa * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. 230cd82a32eSJiri Olsa */ 231838a8c5fSIan Rogers static int pmu_format(struct perf_pmu *pmu, int dirfd, const char *name) 232cd82a32eSJiri Olsa { 233e293a5e8SNamhyung Kim int fd; 234cd82a32eSJiri Olsa 235e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "format", O_DIRECTORY); 236e293a5e8SNamhyung Kim if (fd < 0) 237d9664582SAndi Kleen return 0; 238cd82a32eSJiri Olsa 239e293a5e8SNamhyung Kim /* it'll close the fd */ 24050402641SIan Rogers if (perf_pmu__format_parse(pmu, fd, /*eager_load=*/false)) 241cd82a32eSJiri Olsa return -1; 242cd82a32eSJiri Olsa 243cd82a32eSJiri Olsa return 0; 244cd82a32eSJiri Olsa } 245cd82a32eSJiri Olsa 246a55ab7c4SJin Yao int perf_pmu__convert_scale(const char *scale, char **end, double *sval) 247d02fc6bcSAndi Kleen { 248d02fc6bcSAndi Kleen char *lc; 249d02fc6bcSAndi Kleen int ret = 0; 250d02fc6bcSAndi Kleen 251d02fc6bcSAndi Kleen /* 252d02fc6bcSAndi Kleen * save current locale 253d02fc6bcSAndi Kleen */ 254d02fc6bcSAndi Kleen lc = setlocale(LC_NUMERIC, NULL); 255d02fc6bcSAndi Kleen 256d02fc6bcSAndi Kleen /* 257d02fc6bcSAndi Kleen * The lc string may be allocated in static storage, 258d02fc6bcSAndi Kleen * so get a dynamic copy to make it survive setlocale 259d02fc6bcSAndi Kleen * call below. 260d02fc6bcSAndi Kleen */ 261d02fc6bcSAndi Kleen lc = strdup(lc); 262d02fc6bcSAndi Kleen if (!lc) { 263d02fc6bcSAndi Kleen ret = -ENOMEM; 264d02fc6bcSAndi Kleen goto out; 265d02fc6bcSAndi Kleen } 266d02fc6bcSAndi Kleen 267d02fc6bcSAndi Kleen /* 268d02fc6bcSAndi Kleen * force to C locale to ensure kernel 269d02fc6bcSAndi Kleen * scale string is converted correctly. 270d02fc6bcSAndi Kleen * kernel uses default C locale. 271d02fc6bcSAndi Kleen */ 272d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, "C"); 273d02fc6bcSAndi Kleen 274d02fc6bcSAndi Kleen *sval = strtod(scale, end); 275d02fc6bcSAndi Kleen 276d02fc6bcSAndi Kleen out: 277d02fc6bcSAndi Kleen /* restore locale */ 278d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, lc); 279d02fc6bcSAndi Kleen free(lc); 280d02fc6bcSAndi Kleen return ret; 281d02fc6bcSAndi Kleen } 282d02fc6bcSAndi Kleen 283e293a5e8SNamhyung Kim static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, char *name) 284410136f5SStephane Eranian { 285410136f5SStephane Eranian struct stat st; 286410136f5SStephane Eranian ssize_t sret; 287410136f5SStephane Eranian char scale[128]; 288410136f5SStephane Eranian int fd, ret = -1; 289410136f5SStephane Eranian char path[PATH_MAX]; 290410136f5SStephane Eranian 291e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.scale", name); 292410136f5SStephane Eranian 293e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 294410136f5SStephane Eranian if (fd == -1) 295410136f5SStephane Eranian return -1; 296410136f5SStephane Eranian 297410136f5SStephane Eranian if (fstat(fd, &st) < 0) 298410136f5SStephane Eranian goto error; 299410136f5SStephane Eranian 300410136f5SStephane Eranian sret = read(fd, scale, sizeof(scale)-1); 301410136f5SStephane Eranian if (sret < 0) 302410136f5SStephane Eranian goto error; 303410136f5SStephane Eranian 3049ecae065SMadhavan Srinivasan if (scale[sret - 1] == '\n') 3059ecae065SMadhavan Srinivasan scale[sret - 1] = '\0'; 3069ecae065SMadhavan Srinivasan else 307410136f5SStephane Eranian scale[sret] = '\0'; 3089ecae065SMadhavan Srinivasan 309a55ab7c4SJin Yao ret = perf_pmu__convert_scale(scale, NULL, &alias->scale); 310410136f5SStephane Eranian error: 311410136f5SStephane Eranian close(fd); 312410136f5SStephane Eranian return ret; 313410136f5SStephane Eranian } 314410136f5SStephane Eranian 315e293a5e8SNamhyung Kim static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, char *name) 316410136f5SStephane Eranian { 317410136f5SStephane Eranian char path[PATH_MAX]; 318410136f5SStephane Eranian ssize_t sret; 319410136f5SStephane Eranian int fd; 320410136f5SStephane Eranian 321e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.unit", name); 322410136f5SStephane Eranian 323e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 324410136f5SStephane Eranian if (fd == -1) 325410136f5SStephane Eranian return -1; 326410136f5SStephane Eranian 327410136f5SStephane Eranian sret = read(fd, alias->unit, UNIT_MAX_LEN); 328410136f5SStephane Eranian if (sret < 0) 329410136f5SStephane Eranian goto error; 330410136f5SStephane Eranian 331410136f5SStephane Eranian close(fd); 332410136f5SStephane Eranian 3339ecae065SMadhavan Srinivasan if (alias->unit[sret - 1] == '\n') 3349ecae065SMadhavan Srinivasan alias->unit[sret - 1] = '\0'; 3359ecae065SMadhavan Srinivasan else 336410136f5SStephane Eranian alias->unit[sret] = '\0'; 337410136f5SStephane Eranian 338410136f5SStephane Eranian return 0; 339410136f5SStephane Eranian error: 340410136f5SStephane Eranian close(fd); 341410136f5SStephane Eranian alias->unit[0] = '\0'; 342410136f5SStephane Eranian return -1; 343410136f5SStephane Eranian } 344410136f5SStephane Eranian 345044330c1SMatt Fleming static int 346e293a5e8SNamhyung Kim perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, char *name) 347044330c1SMatt Fleming { 348044330c1SMatt Fleming char path[PATH_MAX]; 349044330c1SMatt Fleming int fd; 350044330c1SMatt Fleming 351e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.per-pkg", name); 352044330c1SMatt Fleming 353e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 354044330c1SMatt Fleming if (fd == -1) 355044330c1SMatt Fleming return -1; 356044330c1SMatt Fleming 357044330c1SMatt Fleming close(fd); 358044330c1SMatt Fleming 359044330c1SMatt Fleming alias->per_pkg = true; 360044330c1SMatt Fleming return 0; 361044330c1SMatt Fleming } 362044330c1SMatt Fleming 3631d9e446bSJiri Olsa static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, 364e293a5e8SNamhyung Kim int dirfd, char *name) 3651d9e446bSJiri Olsa { 3661d9e446bSJiri Olsa char path[PATH_MAX]; 3671d9e446bSJiri Olsa int fd; 3681d9e446bSJiri Olsa 369e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.snapshot", name); 3701d9e446bSJiri Olsa 371e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 3721d9e446bSJiri Olsa if (fd == -1) 3731d9e446bSJiri Olsa return -1; 3741d9e446bSJiri Olsa 3751d9e446bSJiri Olsa alias->snapshot = true; 3761d9e446bSJiri Olsa close(fd); 3771d9e446bSJiri Olsa return 0; 3781d9e446bSJiri Olsa } 3791d9e446bSJiri Olsa 3806dde6429SThomas Richter static void perf_pmu_assign_str(char *name, const char *field, char **old_str, 3816dde6429SThomas Richter char **new_str) 3826dde6429SThomas Richter { 3836dde6429SThomas Richter if (!*old_str) 3846dde6429SThomas Richter goto set_new; 3856dde6429SThomas Richter 3866dde6429SThomas Richter if (*new_str) { /* Have new string, check with old */ 3876dde6429SThomas Richter if (strcasecmp(*old_str, *new_str)) 3886dde6429SThomas Richter pr_debug("alias %s differs in field '%s'\n", 3896dde6429SThomas Richter name, field); 3906dde6429SThomas Richter zfree(old_str); 3916dde6429SThomas Richter } else /* Nothing new --> keep old string */ 3926dde6429SThomas Richter return; 3936dde6429SThomas Richter set_new: 3946dde6429SThomas Richter *old_str = *new_str; 3956dde6429SThomas Richter *new_str = NULL; 3966dde6429SThomas Richter } 3976dde6429SThomas Richter 3986dde6429SThomas Richter static void perf_pmu_update_alias(struct perf_pmu_alias *old, 3996dde6429SThomas Richter struct perf_pmu_alias *newalias) 4006dde6429SThomas Richter { 4016dde6429SThomas Richter perf_pmu_assign_str(old->name, "desc", &old->desc, &newalias->desc); 4026dde6429SThomas Richter perf_pmu_assign_str(old->name, "long_desc", &old->long_desc, 4036dde6429SThomas Richter &newalias->long_desc); 4046dde6429SThomas Richter perf_pmu_assign_str(old->name, "topic", &old->topic, &newalias->topic); 4056dde6429SThomas Richter perf_pmu_assign_str(old->name, "value", &old->str, &newalias->str); 4066dde6429SThomas Richter old->scale = newalias->scale; 4076dde6429SThomas Richter old->per_pkg = newalias->per_pkg; 4086dde6429SThomas Richter old->snapshot = newalias->snapshot; 4096dde6429SThomas Richter memcpy(old->unit, newalias->unit, sizeof(old->unit)); 4106dde6429SThomas Richter } 4116dde6429SThomas Richter 4126dde6429SThomas Richter /* Delete an alias entry. */ 413c3245d20SIan Rogers static void perf_pmu_free_alias(struct perf_pmu_alias *newalias) 4146dde6429SThomas Richter { 4156dde6429SThomas Richter zfree(&newalias->name); 4166dde6429SThomas Richter zfree(&newalias->desc); 4176dde6429SThomas Richter zfree(&newalias->long_desc); 4186dde6429SThomas Richter zfree(&newalias->topic); 4196dde6429SThomas Richter zfree(&newalias->str); 42032705de7SJin Yao zfree(&newalias->pmu_name); 4216dde6429SThomas Richter parse_events_terms__purge(&newalias->terms); 4226dde6429SThomas Richter free(newalias); 4236dde6429SThomas Richter } 4246dde6429SThomas Richter 425eec11310SNamhyung Kim static void perf_pmu__del_aliases(struct perf_pmu *pmu) 426eec11310SNamhyung Kim { 427eec11310SNamhyung Kim struct perf_pmu_alias *alias, *tmp; 428eec11310SNamhyung Kim 429eec11310SNamhyung Kim list_for_each_entry_safe(alias, tmp, &pmu->aliases, list) { 430eec11310SNamhyung Kim list_del(&alias->list); 431eec11310SNamhyung Kim perf_pmu_free_alias(alias); 432eec11310SNamhyung Kim } 433eec11310SNamhyung Kim } 434eec11310SNamhyung Kim 4356dde6429SThomas Richter /* Merge an alias, search in alias list. If this name is already 4366dde6429SThomas Richter * present merge both of them to combine all information. 4376dde6429SThomas Richter */ 4386dde6429SThomas Richter static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias, 4396dde6429SThomas Richter struct list_head *alist) 4406dde6429SThomas Richter { 4416dde6429SThomas Richter struct perf_pmu_alias *a; 4426dde6429SThomas Richter 4436dde6429SThomas Richter list_for_each_entry(a, alist, list) { 4446dde6429SThomas Richter if (!strcasecmp(newalias->name, a->name)) { 44532705de7SJin Yao if (newalias->pmu_name && a->pmu_name && 44632705de7SJin Yao !strcasecmp(newalias->pmu_name, a->pmu_name)) { 44732705de7SJin Yao continue; 44832705de7SJin Yao } 4496dde6429SThomas Richter perf_pmu_update_alias(a, newalias); 4506dde6429SThomas Richter perf_pmu_free_alias(newalias); 4516dde6429SThomas Richter return true; 4526dde6429SThomas Richter } 4536dde6429SThomas Richter } 4546dde6429SThomas Richter return false; 4556dde6429SThomas Richter } 4566dde6429SThomas Richter 457e293a5e8SNamhyung Kim static int __perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, 45847f572aaSIan Rogers char *desc, char *val, const struct pmu_event *pe) 459a6146d50SZheng Yan { 4600c24d6fbSThomas Richter struct parse_events_term *term; 4615c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 462a6146d50SZheng Yan int ret; 4630c24d6fbSThomas Richter char newval[256]; 464330f40a0SIan Rogers const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL; 465bd680861SIan Rogers bool deprecated = false, perpkg = false; 466eab35953SJin Yao 467eab35953SJin Yao if (pe) { 468330f40a0SIan Rogers long_desc = pe->long_desc; 469330f40a0SIan Rogers topic = pe->topic; 470330f40a0SIan Rogers unit = pe->unit; 471bd680861SIan Rogers perpkg = pe->perpkg; 4729ed8b7dcSIan Rogers deprecated = pe->deprecated; 473330f40a0SIan Rogers pmu_name = pe->pmu; 474eab35953SJin Yao } 475a6146d50SZheng Yan 476a6146d50SZheng Yan alias = malloc(sizeof(*alias)); 477a6146d50SZheng Yan if (!alias) 478a6146d50SZheng Yan return -ENOMEM; 479a6146d50SZheng Yan 480a6146d50SZheng Yan INIT_LIST_HEAD(&alias->terms); 481410136f5SStephane Eranian alias->scale = 1.0; 482410136f5SStephane Eranian alias->unit[0] = '\0'; 483bd680861SIan Rogers alias->per_pkg = perpkg; 48484530920SStephane Eranian alias->snapshot = false; 4859ed8b7dcSIan Rogers alias->deprecated = deprecated; 486410136f5SStephane Eranian 48770c646e0SSukadev Bhattiprolu ret = parse_events_terms(&alias->terms, val); 488a6146d50SZheng Yan if (ret) { 48970c646e0SSukadev Bhattiprolu pr_err("Cannot parse alias %s: %d\n", val, ret); 490a6146d50SZheng Yan free(alias); 491a6146d50SZheng Yan return ret; 492a6146d50SZheng Yan } 493a6146d50SZheng Yan 4940c24d6fbSThomas Richter /* Scan event and remove leading zeroes, spaces, newlines, some 4950c24d6fbSThomas Richter * platforms have terms specified as 4960c24d6fbSThomas Richter * event=0x0091 (read from files ../<PMU>/events/<FILE> 4970c24d6fbSThomas Richter * and terms specified as event=0x91 (read from JSON files). 4980c24d6fbSThomas Richter * 4990c24d6fbSThomas Richter * Rebuild string to make alias->str member comparable. 5000c24d6fbSThomas Richter */ 5010c24d6fbSThomas Richter memset(newval, 0, sizeof(newval)); 5020c24d6fbSThomas Richter ret = 0; 5030c24d6fbSThomas Richter list_for_each_entry(term, &alias->terms, list) { 5040c24d6fbSThomas Richter if (ret) 5050c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 5060c24d6fbSThomas Richter ","); 5070c24d6fbSThomas Richter if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 5080c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 5090c24d6fbSThomas Richter "%s=%#x", term->config, term->val.num); 5100c24d6fbSThomas Richter else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 5110c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 5120c24d6fbSThomas Richter "%s=%s", term->config, term->val.str); 5130c24d6fbSThomas Richter } 5140c24d6fbSThomas Richter 515a6146d50SZheng Yan alias->name = strdup(name); 516e293a5e8SNamhyung Kim if (dirfd >= 0) { 517410136f5SStephane Eranian /* 518410136f5SStephane Eranian * load unit name and scale if available 519410136f5SStephane Eranian */ 520e293a5e8SNamhyung Kim perf_pmu__parse_unit(alias, dirfd, name); 521e293a5e8SNamhyung Kim perf_pmu__parse_scale(alias, dirfd, name); 522e293a5e8SNamhyung Kim perf_pmu__parse_per_pkg(alias, dirfd, name); 523e293a5e8SNamhyung Kim perf_pmu__parse_snapshot(alias, dirfd, name); 52470c646e0SSukadev Bhattiprolu } 525410136f5SStephane Eranian 52608e60ed1SAndi Kleen alias->desc = desc ? strdup(desc) : NULL; 527c8d6828aSSukadev Bhattiprolu alias->long_desc = long_desc ? strdup(long_desc) : 528c8d6828aSSukadev Bhattiprolu desc ? strdup(desc) : NULL; 529dd5f1036SAndi Kleen alias->topic = topic ? strdup(topic) : NULL; 530fedb2b51SAndi Kleen if (unit) { 531330f40a0SIan Rogers if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0) 532fedb2b51SAndi Kleen return -1; 533fedb2b51SAndi Kleen snprintf(alias->unit, sizeof(alias->unit), "%s", unit); 534fedb2b51SAndi Kleen } 5350c24d6fbSThomas Richter alias->str = strdup(newval); 53632705de7SJin Yao alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL; 537f2361024SAndi Kleen 5386dde6429SThomas Richter if (!perf_pmu_merge_alias(alias, list)) 539a6146d50SZheng Yan list_add_tail(&alias->list, list); 540410136f5SStephane Eranian 541a6146d50SZheng Yan return 0; 542a6146d50SZheng Yan } 543a6146d50SZheng Yan 544e293a5e8SNamhyung Kim static int perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, FILE *file) 54570c646e0SSukadev Bhattiprolu { 54670c646e0SSukadev Bhattiprolu char buf[256]; 54770c646e0SSukadev Bhattiprolu int ret; 54870c646e0SSukadev Bhattiprolu 54970c646e0SSukadev Bhattiprolu ret = fread(buf, 1, sizeof(buf), file); 55070c646e0SSukadev Bhattiprolu if (ret == 0) 55170c646e0SSukadev Bhattiprolu return -EINVAL; 55270c646e0SSukadev Bhattiprolu 55370c646e0SSukadev Bhattiprolu buf[ret] = 0; 55470c646e0SSukadev Bhattiprolu 555ea23ac73SThomas Richter /* Remove trailing newline from sysfs file */ 55613c230abSArnaldo Carvalho de Melo strim(buf); 557ea23ac73SThomas Richter 558e293a5e8SNamhyung Kim return __perf_pmu__new_alias(list, dirfd, name, NULL, buf, NULL); 55970c646e0SSukadev Bhattiprolu } 56070c646e0SSukadev Bhattiprolu 56146441bdcSMatt Fleming static inline bool pmu_alias_info_file(char *name) 56246441bdcSMatt Fleming { 56346441bdcSMatt Fleming size_t len; 56446441bdcSMatt Fleming 56546441bdcSMatt Fleming len = strlen(name); 56646441bdcSMatt Fleming if (len > 5 && !strcmp(name + len - 5, ".unit")) 56746441bdcSMatt Fleming return true; 56846441bdcSMatt Fleming if (len > 6 && !strcmp(name + len - 6, ".scale")) 56946441bdcSMatt Fleming return true; 570044330c1SMatt Fleming if (len > 8 && !strcmp(name + len - 8, ".per-pkg")) 571044330c1SMatt Fleming return true; 5721d9e446bSJiri Olsa if (len > 9 && !strcmp(name + len - 9, ".snapshot")) 5731d9e446bSJiri Olsa return true; 57446441bdcSMatt Fleming 57546441bdcSMatt Fleming return false; 57646441bdcSMatt Fleming } 57746441bdcSMatt Fleming 578a6146d50SZheng Yan /* 579a6146d50SZheng Yan * Process all the sysfs attributes located under the directory 580a6146d50SZheng Yan * specified in 'dir' parameter. 581a6146d50SZheng Yan */ 582e293a5e8SNamhyung Kim static int pmu_aliases_parse(int dirfd, struct list_head *head) 583a6146d50SZheng Yan { 584a6146d50SZheng Yan struct dirent *evt_ent; 585a6146d50SZheng Yan DIR *event_dir; 586e293a5e8SNamhyung Kim int fd; 587a6146d50SZheng Yan 588e293a5e8SNamhyung Kim event_dir = fdopendir(dirfd); 589a6146d50SZheng Yan if (!event_dir) 590a6146d50SZheng Yan return -EINVAL; 591a6146d50SZheng Yan 592940db6dcSAndi Kleen while ((evt_ent = readdir(event_dir))) { 593a6146d50SZheng Yan char *name = evt_ent->d_name; 594a6146d50SZheng Yan FILE *file; 595a6146d50SZheng Yan 596a6146d50SZheng Yan if (!strcmp(name, ".") || !strcmp(name, "..")) 597a6146d50SZheng Yan continue; 598a6146d50SZheng Yan 599410136f5SStephane Eranian /* 60046441bdcSMatt Fleming * skip info files parsed in perf_pmu__new_alias() 601410136f5SStephane Eranian */ 60246441bdcSMatt Fleming if (pmu_alias_info_file(name)) 603410136f5SStephane Eranian continue; 604410136f5SStephane Eranian 605e293a5e8SNamhyung Kim fd = openat(dirfd, name, O_RDONLY); 6060ea8920eSIan Rogers if (fd == -1) { 6070ea8920eSIan Rogers pr_debug("Cannot open %s\n", name); 6080ea8920eSIan Rogers continue; 6090ea8920eSIan Rogers } 610e293a5e8SNamhyung Kim file = fdopen(fd, "r"); 611940db6dcSAndi Kleen if (!file) { 6120ea8920eSIan Rogers close(fd); 613940db6dcSAndi Kleen continue; 614940db6dcSAndi Kleen } 615410136f5SStephane Eranian 616e293a5e8SNamhyung Kim if (perf_pmu__new_alias(head, dirfd, name, file) < 0) 617940db6dcSAndi Kleen pr_debug("Cannot set up %s\n", name); 618a6146d50SZheng Yan fclose(file); 619a6146d50SZheng Yan } 620a6146d50SZheng Yan 621a6146d50SZheng Yan closedir(event_dir); 622940db6dcSAndi Kleen return 0; 623a6146d50SZheng Yan } 624a6146d50SZheng Yan 625a6146d50SZheng Yan /* 626a6146d50SZheng Yan * Reading the pmu event aliases definition, which should be located at: 627a6146d50SZheng Yan * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 628a6146d50SZheng Yan */ 629838a8c5fSIan Rogers static int pmu_aliases(struct perf_pmu *pmu, int dirfd, const char *name) 630a6146d50SZheng Yan { 631e293a5e8SNamhyung Kim int fd; 632a6146d50SZheng Yan 633e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "events", O_DIRECTORY); 634e293a5e8SNamhyung Kim if (fd < 0) 635d9664582SAndi Kleen return 0; 636a6146d50SZheng Yan 637e293a5e8SNamhyung Kim /* it'll close the fd */ 638838a8c5fSIan Rogers if (pmu_aliases_parse(fd, &pmu->aliases)) 639a6146d50SZheng Yan return -1; 640a6146d50SZheng Yan 641a6146d50SZheng Yan return 0; 642a6146d50SZheng Yan } 643a6146d50SZheng Yan 6445c6ccc37SArnaldo Carvalho de Melo static int pmu_alias_terms(struct perf_pmu_alias *alias, 645a6146d50SZheng Yan struct list_head *terms) 646a6146d50SZheng Yan { 6477c2f8164SJiri Olsa struct parse_events_term *term, *cloned; 648a6146d50SZheng Yan LIST_HEAD(list); 649a6146d50SZheng Yan int ret; 650a6146d50SZheng Yan 651a6146d50SZheng Yan list_for_each_entry(term, &alias->terms, list) { 6527c2f8164SJiri Olsa ret = parse_events_term__clone(&cloned, term); 653a6146d50SZheng Yan if (ret) { 654682dc24cSArnaldo Carvalho de Melo parse_events_terms__purge(&list); 655a6146d50SZheng Yan return ret; 656a6146d50SZheng Yan } 657c2f1ceadSAndi Kleen /* 658c2f1ceadSAndi Kleen * Weak terms don't override command line options, 659c2f1ceadSAndi Kleen * which we don't want for implicit terms in aliases. 660c2f1ceadSAndi Kleen */ 661c2f1ceadSAndi Kleen cloned->weak = true; 6627c2f8164SJiri Olsa list_add_tail(&cloned->list, &list); 663a6146d50SZheng Yan } 664a6146d50SZheng Yan list_splice(&list, terms); 665a6146d50SZheng Yan return 0; 666a6146d50SZheng Yan } 667a6146d50SZheng Yan 66866ec1191SMark Rutland /* 66966ec1191SMark Rutland * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) 67066ec1191SMark Rutland * may have a "cpus" file. 67166ec1191SMark Rutland */ 672d06593aaSIan Rogers static struct perf_cpu_map *pmu_cpumask(int dirfd, const char *name, bool is_core) 6737ae92e74SYan, Zheng { 674f854839bSJiri Olsa struct perf_cpu_map *cpus; 6757e3fcffeSMark Rutland const char *templates[] = { 676d50a79cdSJames Clark "cpumask", 677d50a79cdSJames Clark "cpus", 6787e3fcffeSMark Rutland NULL 6797e3fcffeSMark Rutland }; 6807e3fcffeSMark Rutland const char **template; 681d50a79cdSJames Clark char pmu_name[PATH_MAX]; 682d50a79cdSJames Clark struct perf_pmu pmu = {.name = pmu_name}; 683d50a79cdSJames Clark FILE *file; 6847ae92e74SYan, Zheng 685d50a79cdSJames Clark strlcpy(pmu_name, name, sizeof(pmu_name)); 6867e3fcffeSMark Rutland for (template = templates; *template; template++) { 6873a69672eSNamhyung Kim file = perf_pmu__open_file_at(&pmu, dirfd, *template); 688d50a79cdSJames Clark if (!file) 689d50a79cdSJames Clark continue; 690d50a79cdSJames Clark cpus = perf_cpu_map__read(file); 6913a69672eSNamhyung Kim fclose(file); 69266ec1191SMark Rutland if (cpus) 69366ec1191SMark Rutland return cpus; 6947e3fcffeSMark Rutland } 6957ae92e74SYan, Zheng 696d06593aaSIan Rogers /* Nothing found, for core PMUs assume this means all CPUs. */ 697d06593aaSIan Rogers return is_core ? perf_cpu_map__get(cpu_map__online()) : NULL; 69866ec1191SMark Rutland } 6997ae92e74SYan, Zheng 7003a69672eSNamhyung Kim static bool pmu_is_uncore(int dirfd, const char *name) 70166ec1191SMark Rutland { 7023a69672eSNamhyung Kim int fd; 7037ae92e74SYan, Zheng 7043a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "cpumask", O_PATH); 7053a69672eSNamhyung Kim if (fd < 0) 7063a69672eSNamhyung Kim return false; 7073a69672eSNamhyung Kim 7083a69672eSNamhyung Kim close(fd); 7093a69672eSNamhyung Kim return true; 7107ae92e74SYan, Zheng } 7117ae92e74SYan, Zheng 71251d54847SJohn Garry static char *pmu_id(const char *name) 71351d54847SJohn Garry { 71451d54847SJohn Garry char path[PATH_MAX], *str; 71551d54847SJohn Garry size_t len; 71651d54847SJohn Garry 7175f2c8efaSJames Clark perf_pmu__pathname_scnprintf(path, sizeof(path), name, "identifier"); 71851d54847SJohn Garry 7195f2c8efaSJames Clark if (filename__read_str(path, &str, &len) < 0) 72051d54847SJohn Garry return NULL; 72151d54847SJohn Garry 72251d54847SJohn Garry str[len - 1] = 0; /* remove line feed */ 72351d54847SJohn Garry 72451d54847SJohn Garry return str; 72551d54847SJohn Garry } 72651d54847SJohn Garry 7274bf7e81aSIan Rogers /** 7284bf7e81aSIan Rogers * is_sysfs_pmu_core() - PMU CORE devices have different name other than cpu in 7294bf7e81aSIan Rogers * sysfs on some platforms like ARM or Intel hybrid. Looking for 7304bf7e81aSIan Rogers * possible the cpus file in sysfs files to identify whether this is a 7314bf7e81aSIan Rogers * core device. 7324bf7e81aSIan Rogers * @name: The PMU name such as "cpu_atom". 73314b22ae0SGanapatrao Kulkarni */ 7344bf7e81aSIan Rogers static int is_sysfs_pmu_core(const char *name) 73514b22ae0SGanapatrao Kulkarni { 73614b22ae0SGanapatrao Kulkarni char path[PATH_MAX]; 73714b22ae0SGanapatrao Kulkarni 738f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), name, "cpus")) 73914b22ae0SGanapatrao Kulkarni return 0; 740d9664582SAndi Kleen return file_available(path); 74114b22ae0SGanapatrao Kulkarni } 74214b22ae0SGanapatrao Kulkarni 74329be2fe0SIan Rogers char *perf_pmu__getcpuid(struct perf_pmu *pmu) 744d77ade9fSAndi Kleen { 745d77ade9fSAndi Kleen char *cpuid; 746d77ade9fSAndi Kleen static bool printed; 747d77ade9fSAndi Kleen 748d77ade9fSAndi Kleen cpuid = getenv("PERF_CPUID"); 749d77ade9fSAndi Kleen if (cpuid) 750d77ade9fSAndi Kleen cpuid = strdup(cpuid); 751d77ade9fSAndi Kleen if (!cpuid) 75254e32dc0SGanapatrao Kulkarni cpuid = get_cpuid_str(pmu); 753d77ade9fSAndi Kleen if (!cpuid) 754d77ade9fSAndi Kleen return NULL; 755d77ade9fSAndi Kleen 756d77ade9fSAndi Kleen if (!printed) { 757d77ade9fSAndi Kleen pr_debug("Using CPUID %s\n", cpuid); 758d77ade9fSAndi Kleen printed = true; 759d77ade9fSAndi Kleen } 760d77ade9fSAndi Kleen return cpuid; 761d77ade9fSAndi Kleen } 762d77ade9fSAndi Kleen 7631ba3752aSIan Rogers __weak const struct pmu_events_table *pmu_events_table__find(void) 764e126bef5SJohn Garry { 76596d2a746SIan Rogers return perf_pmu__find_events_table(NULL); 766e126bef5SJohn Garry } 767e126bef5SJohn Garry 768f8ea2c15SIan Rogers __weak const struct pmu_metrics_table *pmu_metrics_table__find(void) 769f8ea2c15SIan Rogers { 770f8ea2c15SIan Rogers return perf_pmu__find_metrics_table(NULL); 771f8ea2c15SIan Rogers } 772f8ea2c15SIan Rogers 773240e6fd0SIan Rogers /** 774240e6fd0SIan Rogers * perf_pmu__match_ignoring_suffix - Does the pmu_name match tok ignoring any 775240e6fd0SIan Rogers * trailing suffix? The Suffix must be in form 776240e6fd0SIan Rogers * tok_{digits}, or tok{digits}. 777240e6fd0SIan Rogers * @pmu_name: The pmu_name with possible suffix. 778240e6fd0SIan Rogers * @tok: The possible match to pmu_name without suffix. 779c07d5c92SJohn Garry */ 780240e6fd0SIan Rogers static bool perf_pmu__match_ignoring_suffix(const char *pmu_name, const char *tok) 781c47a5599SJin Yao { 782c07d5c92SJohn Garry const char *p; 783c47a5599SJin Yao 784c47a5599SJin Yao if (strncmp(pmu_name, tok, strlen(tok))) 785c47a5599SJin Yao return false; 786c47a5599SJin Yao 787c47a5599SJin Yao p = pmu_name + strlen(tok); 788c47a5599SJin Yao if (*p == 0) 789c47a5599SJin Yao return true; 790c47a5599SJin Yao 791c07d5c92SJohn Garry if (*p == '_') 792c47a5599SJin Yao ++p; 793c07d5c92SJohn Garry 794c07d5c92SJohn Garry /* Ensure we end in a number */ 795c07d5c92SJohn Garry while (1) { 796c07d5c92SJohn Garry if (!isdigit(*p)) 797c47a5599SJin Yao return false; 798c07d5c92SJohn Garry if (*(++p) == 0) 799c07d5c92SJohn Garry break; 800c07d5c92SJohn Garry } 801c47a5599SJin Yao 802c47a5599SJin Yao return true; 803c47a5599SJin Yao } 804c47a5599SJin Yao 805240e6fd0SIan Rogers /** 806240e6fd0SIan Rogers * pmu_uncore_alias_match - does name match the PMU name? 807240e6fd0SIan Rogers * @pmu_name: the json struct pmu_event name. This may lack a suffix (which 808240e6fd0SIan Rogers * matches) or be of the form "socket,pmuname" which will match 809240e6fd0SIan Rogers * "socketX_pmunameY". 810240e6fd0SIan Rogers * @name: a real full PMU name as from sysfs. 811240e6fd0SIan Rogers */ 812240e6fd0SIan Rogers static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) 813730670b1SJohn Garry { 814730670b1SJohn Garry char *tmp = NULL, *tok, *str; 815730670b1SJohn Garry bool res; 816730670b1SJohn Garry 817240e6fd0SIan Rogers if (strchr(pmu_name, ',') == NULL) 818240e6fd0SIan Rogers return perf_pmu__match_ignoring_suffix(name, pmu_name); 819240e6fd0SIan Rogers 820730670b1SJohn Garry str = strdup(pmu_name); 821730670b1SJohn Garry if (!str) 822730670b1SJohn Garry return false; 823730670b1SJohn Garry 824730670b1SJohn Garry /* 825730670b1SJohn Garry * uncore alias may be from different PMU with common prefix 826730670b1SJohn Garry */ 827730670b1SJohn Garry tok = strtok_r(str, ",", &tmp); 828730670b1SJohn Garry if (strncmp(pmu_name, tok, strlen(tok))) { 829730670b1SJohn Garry res = false; 830730670b1SJohn Garry goto out; 831730670b1SJohn Garry } 832730670b1SJohn Garry 833730670b1SJohn Garry /* 834730670b1SJohn Garry * Match more complex aliases where the alias name is a comma-delimited 835730670b1SJohn Garry * list of tokens, orderly contained in the matching PMU name. 836730670b1SJohn Garry * 837730670b1SJohn Garry * Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we 838730670b1SJohn Garry * match "socket" in "socketX_pmunameY" and then "pmuname" in 839730670b1SJohn Garry * "pmunameY". 840730670b1SJohn Garry */ 841c07d5c92SJohn Garry while (1) { 842c07d5c92SJohn Garry char *next_tok = strtok_r(NULL, ",", &tmp); 843c07d5c92SJohn Garry 844730670b1SJohn Garry name = strstr(name, tok); 845c07d5c92SJohn Garry if (!name || 846240e6fd0SIan Rogers (!next_tok && !perf_pmu__match_ignoring_suffix(name, tok))) { 847730670b1SJohn Garry res = false; 848730670b1SJohn Garry goto out; 849730670b1SJohn Garry } 850c07d5c92SJohn Garry if (!next_tok) 851c07d5c92SJohn Garry break; 852c07d5c92SJohn Garry tok = next_tok; 853c07d5c92SJohn Garry name += strlen(tok); 854730670b1SJohn Garry } 855730670b1SJohn Garry 856730670b1SJohn Garry res = true; 857730670b1SJohn Garry out: 858730670b1SJohn Garry free(str); 859730670b1SJohn Garry return res; 860730670b1SJohn Garry } 861730670b1SJohn Garry 862660842e4SIan Rogers static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, 8631ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 864660842e4SIan Rogers void *vdata) 865660842e4SIan Rogers { 866*e3edd6cfSIan Rogers struct list_head *head = vdata; 867660842e4SIan Rogers 868660842e4SIan Rogers /* need type casts to override 'const' */ 869*e3edd6cfSIan Rogers __perf_pmu__new_alias(head, -1, (char *)pe->name, (char *)pe->desc, (char *)pe->event, pe); 870660842e4SIan Rogers return 0; 871660842e4SIan Rogers } 872660842e4SIan Rogers 873933f82ffSSukadev Bhattiprolu /* 874d685819bSIan Rogers * From the pmu_events_table, find the events that correspond to the given 875d685819bSIan Rogers * PMU and add them to the list 'head'. 876933f82ffSSukadev Bhattiprolu */ 877838a8c5fSIan Rogers void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table) 878933f82ffSSukadev Bhattiprolu { 879*e3edd6cfSIan Rogers pmu_events_table__for_each_event(table, pmu, pmu_add_cpu_aliases_map_callback, &pmu->aliases); 880933f82ffSSukadev Bhattiprolu } 881933f82ffSSukadev Bhattiprolu 882838a8c5fSIan Rogers static void pmu_add_cpu_aliases(struct perf_pmu *pmu) 883e45ad701SJohn Garry { 8841ba3752aSIan Rogers const struct pmu_events_table *table; 885e45ad701SJohn Garry 88696d2a746SIan Rogers table = perf_pmu__find_events_table(pmu); 887eeac7730SIan Rogers if (!table) 888e45ad701SJohn Garry return; 889e45ad701SJohn Garry 890838a8c5fSIan Rogers pmu_add_cpu_aliases_table(pmu, table); 891e45ad701SJohn Garry } 892e45ad701SJohn Garry 8934513c719SJohn Garry struct pmu_sys_event_iter_data { 8944513c719SJohn Garry struct list_head *head; 8954513c719SJohn Garry struct perf_pmu *pmu; 8964513c719SJohn Garry }; 8974513c719SJohn Garry 89829be2fe0SIan Rogers static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, 8991ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 90029be2fe0SIan Rogers void *data) 9014513c719SJohn Garry { 9024513c719SJohn Garry struct pmu_sys_event_iter_data *idata = data; 9034513c719SJohn Garry struct perf_pmu *pmu = idata->pmu; 9044513c719SJohn Garry 9054513c719SJohn Garry if (!pe->compat || !pe->pmu) 9064513c719SJohn Garry return 0; 9074513c719SJohn Garry 9084513c719SJohn Garry if (!strcmp(pmu->id, pe->compat) && 9094513c719SJohn Garry pmu_uncore_alias_match(pe->pmu, pmu->name)) { 910e293a5e8SNamhyung Kim __perf_pmu__new_alias(idata->head, -1, 9114513c719SJohn Garry (char *)pe->name, 9124513c719SJohn Garry (char *)pe->desc, 9134513c719SJohn Garry (char *)pe->event, 914eab35953SJin Yao pe); 9154513c719SJohn Garry } 9164513c719SJohn Garry 9174513c719SJohn Garry return 0; 9184513c719SJohn Garry } 9194513c719SJohn Garry 920838a8c5fSIan Rogers void pmu_add_sys_aliases(struct perf_pmu *pmu) 9214513c719SJohn Garry { 9224513c719SJohn Garry struct pmu_sys_event_iter_data idata = { 923838a8c5fSIan Rogers .head = &pmu->aliases, 9244513c719SJohn Garry .pmu = pmu, 9254513c719SJohn Garry }; 9264513c719SJohn Garry 9274513c719SJohn Garry if (!pmu->id) 9284513c719SJohn Garry return; 9294513c719SJohn Garry 9304513c719SJohn Garry pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, &idata); 9314513c719SJohn Garry } 9324513c719SJohn Garry 933c5de47f2SSukadev Bhattiprolu struct perf_event_attr * __weak 934dc0a6202SAdrian Hunter perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) 935dc0a6202SAdrian Hunter { 936dc0a6202SAdrian Hunter return NULL; 937dc0a6202SAdrian Hunter } 938dc0a6202SAdrian Hunter 93913d60ba0SKan Liang char * __weak 94013d60ba0SKan Liang pmu_find_real_name(const char *name) 94113d60ba0SKan Liang { 94213d60ba0SKan Liang return (char *)name; 94313d60ba0SKan Liang } 94413d60ba0SKan Liang 94513d60ba0SKan Liang char * __weak 94613d60ba0SKan Liang pmu_find_alias_name(const char *name __maybe_unused) 94713d60ba0SKan Liang { 94813d60ba0SKan Liang return NULL; 94913d60ba0SKan Liang } 95013d60ba0SKan Liang 9513a69672eSNamhyung Kim static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) 95290a86bdeSJiri Olsa { 95390a86bdeSJiri Olsa int max_precise = -1; 95490a86bdeSJiri Olsa 9553a69672eSNamhyung Kim perf_pmu__scan_file_at(pmu, dirfd, "caps/max_precise", "%d", &max_precise); 95690a86bdeSJiri Olsa return max_precise; 95790a86bdeSJiri Olsa } 95890a86bdeSJiri Olsa 9591eaf496eSIan Rogers struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name) 960cd82a32eSJiri Olsa { 961cd82a32eSJiri Olsa struct perf_pmu *pmu; 962cd82a32eSJiri Olsa __u32 type; 96313d60ba0SKan Liang char *name = pmu_find_real_name(lookup_name); 96413d60ba0SKan Liang char *alias_name; 96549afa7f6SJin Yao 966cd82a32eSJiri Olsa pmu = zalloc(sizeof(*pmu)); 967cd82a32eSJiri Olsa if (!pmu) 968cd82a32eSJiri Olsa return NULL; 969cd82a32eSJiri Olsa 970838a8c5fSIan Rogers INIT_LIST_HEAD(&pmu->format); 971838a8c5fSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 972838a8c5fSIan Rogers INIT_LIST_HEAD(&pmu->caps); 973838a8c5fSIan Rogers /* 974838a8c5fSIan Rogers * The pmu data we store & need consists of the pmu 975838a8c5fSIan Rogers * type value and format definitions. Load both right 976838a8c5fSIan Rogers * now. 977838a8c5fSIan Rogers */ 978838a8c5fSIan Rogers if (pmu_format(pmu, dirfd, name)) { 979838a8c5fSIan Rogers free(pmu); 980838a8c5fSIan Rogers return NULL; 981838a8c5fSIan Rogers } 982838a8c5fSIan Rogers /* 983838a8c5fSIan Rogers * Check the aliases first to avoid unnecessary work. 984838a8c5fSIan Rogers */ 985838a8c5fSIan Rogers if (pmu_aliases(pmu, dirfd, name)) { 986838a8c5fSIan Rogers free(pmu); 987838a8c5fSIan Rogers return NULL; 988838a8c5fSIan Rogers } 989d06593aaSIan Rogers pmu->is_core = is_pmu_core(name); 990d06593aaSIan Rogers pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core); 99154e32dc0SGanapatrao Kulkarni pmu->name = strdup(name); 99213d60ba0SKan Liang if (!pmu->name) 99313d60ba0SKan Liang goto err; 99413d60ba0SKan Liang 995f8ad6018SJames Clark /* Read type, and ensure that type value is successfully assigned (return 1) */ 9963a69672eSNamhyung Kim if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1) 997f8ad6018SJames Clark goto err; 998f8ad6018SJames Clark 99913d60ba0SKan Liang alias_name = pmu_find_alias_name(name); 100013d60ba0SKan Liang if (alias_name) { 100113d60ba0SKan Liang pmu->alias_name = strdup(alias_name); 100213d60ba0SKan Liang if (!pmu->alias_name) 100313d60ba0SKan Liang goto err; 100413d60ba0SKan Liang } 100513d60ba0SKan Liang 100654e32dc0SGanapatrao Kulkarni pmu->type = type; 10073a69672eSNamhyung Kim pmu->is_uncore = pmu_is_uncore(dirfd, name); 100851d54847SJohn Garry if (pmu->is_uncore) 100951d54847SJohn Garry pmu->id = pmu_id(name); 10103a69672eSNamhyung Kim pmu->max_precise = pmu_max_precise(dirfd, pmu); 1011838a8c5fSIan Rogers pmu_add_cpu_aliases(pmu); 1012838a8c5fSIan Rogers pmu_add_sys_aliases(pmu); 10131eaf496eSIan Rogers list_add_tail(&pmu->list, pmus); 1014dc0a6202SAdrian Hunter 1015dc0a6202SAdrian Hunter pmu->default_config = perf_pmu__get_default_config(pmu); 1016dc0a6202SAdrian Hunter 1017cd82a32eSJiri Olsa return pmu; 101813d60ba0SKan Liang err: 1019efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 102013d60ba0SKan Liang free(pmu); 102113d60ba0SKan Liang return NULL; 1022cd82a32eSJiri Olsa } 1023cd82a32eSJiri Olsa 1024628eaa4eSIan Rogers /* Creates the PMU when sysfs scanning fails. */ 1025628eaa4eSIan Rogers struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus) 1026628eaa4eSIan Rogers { 1027628eaa4eSIan Rogers struct perf_pmu *pmu = zalloc(sizeof(*pmu)); 1028628eaa4eSIan Rogers 1029628eaa4eSIan Rogers if (!pmu) 1030628eaa4eSIan Rogers return NULL; 1031628eaa4eSIan Rogers 1032628eaa4eSIan Rogers pmu->name = strdup("cpu"); 1033628eaa4eSIan Rogers if (!pmu->name) { 1034628eaa4eSIan Rogers free(pmu); 1035628eaa4eSIan Rogers return NULL; 1036628eaa4eSIan Rogers } 1037628eaa4eSIan Rogers 1038628eaa4eSIan Rogers pmu->is_core = true; 1039628eaa4eSIan Rogers pmu->type = PERF_TYPE_RAW; 1040628eaa4eSIan Rogers pmu->cpus = cpu_map__online(); 1041628eaa4eSIan Rogers 1042628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->format); 1043628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 1044628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->caps); 1045628eaa4eSIan Rogers list_add_tail(&pmu->list, core_pmus); 1046628eaa4eSIan Rogers return pmu; 1047628eaa4eSIan Rogers } 1048628eaa4eSIan Rogers 1049e552b7beSRob Herring void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu) 1050e552b7beSRob Herring { 1051e552b7beSRob Herring struct perf_pmu_format *format; 1052e552b7beSRob Herring 105368c25043SIan Rogers if (pmu->formats_checked) 105468c25043SIan Rogers return; 105568c25043SIan Rogers 105668c25043SIan Rogers pmu->formats_checked = true; 105768c25043SIan Rogers 1058e552b7beSRob Herring /* fake pmu doesn't have format list */ 1059e552b7beSRob Herring if (pmu == &perf_pmu__fake) 1060e552b7beSRob Herring return; 1061e552b7beSRob Herring 106250402641SIan Rogers list_for_each_entry(format, &pmu->format, list) { 106350402641SIan Rogers perf_pmu_format__load(pmu, format); 1064e552b7beSRob Herring if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) { 1065e552b7beSRob Herring pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'" 1066e552b7beSRob Herring "which is not supported by this version of perf!\n", 1067e552b7beSRob Herring pmu->name, format->name, format->value); 1068e552b7beSRob Herring return; 1069e552b7beSRob Herring } 1070e552b7beSRob Herring } 107150402641SIan Rogers } 1072e552b7beSRob Herring 1073c6d616feSIan Rogers bool evsel__is_aux_event(const struct evsel *evsel) 1074e12ee9f7SAdrian Hunter { 1075e76026bdSArnaldo Carvalho de Melo struct perf_pmu *pmu = evsel__find_pmu(evsel); 1076e12ee9f7SAdrian Hunter 1077e12ee9f7SAdrian Hunter return pmu && pmu->auxtrace; 1078e12ee9f7SAdrian Hunter } 1079e12ee9f7SAdrian Hunter 10806593f019SJames Clark /* 10816593f019SJames Clark * Set @config_name to @val as long as the user hasn't already set or cleared it 10826593f019SJames Clark * by passing a config term on the command line. 10836593f019SJames Clark * 10846593f019SJames Clark * @val is the value to put into the bits specified by @config_name rather than 10856593f019SJames Clark * the bit pattern. It is shifted into position by this function, so to set 10866593f019SJames Clark * something to true, pass 1 for val rather than a pre shifted value. 10876593f019SJames Clark */ 10886593f019SJames Clark #define field_prep(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask)) 10896593f019SJames Clark void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, 10906593f019SJames Clark const char *config_name, u64 val) 10916593f019SJames Clark { 10926593f019SJames Clark u64 user_bits = 0, bits; 10936593f019SJames Clark struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG); 10946593f019SJames Clark 10956593f019SJames Clark if (term) 10966593f019SJames Clark user_bits = term->val.cfg_chg; 10976593f019SJames Clark 1098da6a5afdSIan Rogers bits = perf_pmu__format_bits(pmu, config_name); 10996593f019SJames Clark 11006593f019SJames Clark /* Do nothing if the user changed the value */ 11016593f019SJames Clark if (bits & user_bits) 11026593f019SJames Clark return; 11036593f019SJames Clark 11046593f019SJames Clark /* Otherwise replace it */ 11056593f019SJames Clark evsel->core.attr.config &= ~bits; 11066593f019SJames Clark evsel->core.attr.config |= field_prep(bits, val); 11076593f019SJames Clark } 11086593f019SJames Clark 11095c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_format * 111009ff6071SAdrian Hunter pmu_find_format(struct list_head *formats, const char *name) 1111cd82a32eSJiri Olsa { 11125c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1113cd82a32eSJiri Olsa 1114cd82a32eSJiri Olsa list_for_each_entry(format, formats, list) 1115cd82a32eSJiri Olsa if (!strcmp(format->name, name)) 1116cd82a32eSJiri Olsa return format; 1117cd82a32eSJiri Olsa 1118cd82a32eSJiri Olsa return NULL; 1119cd82a32eSJiri Olsa } 1120cd82a32eSJiri Olsa 1121da6a5afdSIan Rogers __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name) 112209ff6071SAdrian Hunter { 1123da6a5afdSIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 112409ff6071SAdrian Hunter __u64 bits = 0; 112509ff6071SAdrian Hunter int fbit; 112609ff6071SAdrian Hunter 112709ff6071SAdrian Hunter if (!format) 112809ff6071SAdrian Hunter return 0; 112909ff6071SAdrian Hunter 113009ff6071SAdrian Hunter for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS) 113109ff6071SAdrian Hunter bits |= 1ULL << fbit; 113209ff6071SAdrian Hunter 113309ff6071SAdrian Hunter return bits; 113409ff6071SAdrian Hunter } 113509ff6071SAdrian Hunter 11367eb54733SIan Rogers int perf_pmu__format_type(struct perf_pmu *pmu, const char *name) 1137a1ac7de6SAdrian Hunter { 11387eb54733SIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 1139a1ac7de6SAdrian Hunter 1140a1ac7de6SAdrian Hunter if (!format) 1141a1ac7de6SAdrian Hunter return -1; 1142a1ac7de6SAdrian Hunter 114350402641SIan Rogers perf_pmu_format__load(pmu, format); 1144a1ac7de6SAdrian Hunter return format->value; 1145a1ac7de6SAdrian Hunter } 1146a1ac7de6SAdrian Hunter 1147cd82a32eSJiri Olsa /* 1148dc0a6202SAdrian Hunter * Sets value based on the format definition (format parameter) 11494d39c89fSIngo Molnar * and unformatted value (value parameter). 1150cd82a32eSJiri Olsa */ 1151dc0a6202SAdrian Hunter static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, 1152dc0a6202SAdrian Hunter bool zero) 1153cd82a32eSJiri Olsa { 1154cd82a32eSJiri Olsa unsigned long fbit, vbit; 1155cd82a32eSJiri Olsa 1156cd82a32eSJiri Olsa for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 1157cd82a32eSJiri Olsa 1158cd82a32eSJiri Olsa if (!test_bit(fbit, format)) 1159cd82a32eSJiri Olsa continue; 1160cd82a32eSJiri Olsa 1161dc0a6202SAdrian Hunter if (value & (1llu << vbit++)) 1162dc0a6202SAdrian Hunter *v |= (1llu << fbit); 1163dc0a6202SAdrian Hunter else if (zero) 1164dc0a6202SAdrian Hunter *v &= ~(1llu << fbit); 1165cd82a32eSJiri Olsa } 1166cd82a32eSJiri Olsa } 1167cd82a32eSJiri Olsa 11680efe6b67SAdrian Hunter static __u64 pmu_format_max_value(const unsigned long *format) 11690efe6b67SAdrian Hunter { 11701b9caa10SJiri Olsa int w; 11710efe6b67SAdrian Hunter 11721b9caa10SJiri Olsa w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); 11731b9caa10SJiri Olsa if (!w) 11741b9caa10SJiri Olsa return 0; 11751b9caa10SJiri Olsa if (w < 64) 11761b9caa10SJiri Olsa return (1ULL << w) - 1; 11771b9caa10SJiri Olsa return -1; 11780efe6b67SAdrian Hunter } 11790efe6b67SAdrian Hunter 1180cd82a32eSJiri Olsa /* 1181688d4dfcSCody P Schafer * Term is a string term, and might be a param-term. Try to look up it's value 1182688d4dfcSCody P Schafer * in the remaining terms. 1183688d4dfcSCody P Schafer * - We have a term like "base-or-format-term=param-term", 1184688d4dfcSCody P Schafer * - We need to find the value supplied for "param-term" (with param-term named 1185688d4dfcSCody P Schafer * in a config string) later on in the term list. 1186688d4dfcSCody P Schafer */ 1187688d4dfcSCody P Schafer static int pmu_resolve_param_term(struct parse_events_term *term, 1188688d4dfcSCody P Schafer struct list_head *head_terms, 1189688d4dfcSCody P Schafer __u64 *value) 1190688d4dfcSCody P Schafer { 1191688d4dfcSCody P Schafer struct parse_events_term *t; 1192688d4dfcSCody P Schafer 1193688d4dfcSCody P Schafer list_for_each_entry(t, head_terms, list) { 11942a3d252dSIan Rogers if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM && 11952a3d252dSIan Rogers t->config && !strcmp(t->config, term->config)) { 1196688d4dfcSCody P Schafer t->used = true; 1197688d4dfcSCody P Schafer *value = t->val.num; 1198688d4dfcSCody P Schafer return 0; 1199688d4dfcSCody P Schafer } 1200688d4dfcSCody P Schafer } 1201688d4dfcSCody P Schafer 1202bb963e16SNamhyung Kim if (verbose > 0) 1203688d4dfcSCody P Schafer printf("Required parameter '%s' not specified\n", term->config); 1204688d4dfcSCody P Schafer 1205688d4dfcSCody P Schafer return -1; 1206688d4dfcSCody P Schafer } 1207688d4dfcSCody P Schafer 1208ffeb883eSHe Kuang static char *pmu_formats_string(struct list_head *formats) 1209e64b020bSJiri Olsa { 1210e64b020bSJiri Olsa struct perf_pmu_format *format; 121111db4e29SMasami Hiramatsu char *str = NULL; 121211db4e29SMasami Hiramatsu struct strbuf buf = STRBUF_INIT; 1213f1417ceaSXin Gao unsigned int i = 0; 1214e64b020bSJiri Olsa 1215ffeb883eSHe Kuang if (!formats) 1216e64b020bSJiri Olsa return NULL; 1217e64b020bSJiri Olsa 1218e64b020bSJiri Olsa /* sysfs exported terms */ 1219ffeb883eSHe Kuang list_for_each_entry(format, formats, list) 122011db4e29SMasami Hiramatsu if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0) 122111db4e29SMasami Hiramatsu goto error; 1222e64b020bSJiri Olsa 1223ffeb883eSHe Kuang str = strbuf_detach(&buf, NULL); 122411db4e29SMasami Hiramatsu error: 1225ffeb883eSHe Kuang strbuf_release(&buf); 1226e64b020bSJiri Olsa 1227e64b020bSJiri Olsa return str; 1228e64b020bSJiri Olsa } 1229e64b020bSJiri Olsa 1230688d4dfcSCody P Schafer /* 1231cd82a32eSJiri Olsa * Setup one of config[12] attr members based on the 123288aca8d9SCody P Schafer * user input data - term parameter. 1233cd82a32eSJiri Olsa */ 1234804fee5dSIan Rogers static int pmu_config_term(struct perf_pmu *pmu, 1235cd82a32eSJiri Olsa struct perf_event_attr *attr, 1236dc0a6202SAdrian Hunter struct parse_events_term *term, 1237688d4dfcSCody P Schafer struct list_head *head_terms, 1238e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1239cd82a32eSJiri Olsa { 12405c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1241cd82a32eSJiri Olsa __u64 *vp; 12420efe6b67SAdrian Hunter __u64 val, max_val; 1243cd82a32eSJiri Olsa 1244cd82a32eSJiri Olsa /* 1245688d4dfcSCody P Schafer * If this is a parameter we've already used for parameterized-eval, 1246688d4dfcSCody P Schafer * skip it in normal eval. 1247688d4dfcSCody P Schafer */ 1248688d4dfcSCody P Schafer if (term->used) 1249688d4dfcSCody P Schafer return 0; 1250688d4dfcSCody P Schafer 1251688d4dfcSCody P Schafer /* 1252cd82a32eSJiri Olsa * Hardcoded terms should be already in, so nothing 1253cd82a32eSJiri Olsa * to be done for them. 1254cd82a32eSJiri Olsa */ 1255cd82a32eSJiri Olsa if (parse_events__is_hardcoded_term(term)) 1256cd82a32eSJiri Olsa return 0; 1257cd82a32eSJiri Olsa 1258804fee5dSIan Rogers format = pmu_find_format(&pmu->format, term->config); 1259688d4dfcSCody P Schafer if (!format) { 1260804fee5dSIan Rogers char *pmu_term = pmu_formats_string(&pmu->format); 12614ac22b48SIan Rogers char *unknown_term; 12624ac22b48SIan Rogers char *help_msg; 1263ffeb883eSHe Kuang 12644ac22b48SIan Rogers if (asprintf(&unknown_term, 12654ac22b48SIan Rogers "unknown term '%s' for pmu '%s'", 1266804fee5dSIan Rogers term->config, pmu->name) < 0) 12674ac22b48SIan Rogers unknown_term = NULL; 12684ac22b48SIan Rogers help_msg = parse_events_formats_error_string(pmu_term); 12694ac22b48SIan Rogers if (err) { 12706c191289SIan Rogers parse_events_error__handle(err, term->err_term, 12714ac22b48SIan Rogers unknown_term, 12724ac22b48SIan Rogers help_msg); 12734ac22b48SIan Rogers } else { 12744ac22b48SIan Rogers pr_debug("%s (%s)\n", unknown_term, help_msg); 12754ac22b48SIan Rogers free(unknown_term); 1276e64b020bSJiri Olsa } 12774ac22b48SIan Rogers free(pmu_term); 1278cd82a32eSJiri Olsa return -EINVAL; 1279688d4dfcSCody P Schafer } 128050402641SIan Rogers perf_pmu_format__load(pmu, format); 1281cd82a32eSJiri Olsa switch (format->value) { 1282cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG: 1283cd82a32eSJiri Olsa vp = &attr->config; 1284cd82a32eSJiri Olsa break; 1285cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG1: 1286cd82a32eSJiri Olsa vp = &attr->config1; 1287cd82a32eSJiri Olsa break; 1288cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG2: 1289cd82a32eSJiri Olsa vp = &attr->config2; 1290cd82a32eSJiri Olsa break; 1291204e7c49SRob Herring case PERF_PMU_FORMAT_VALUE_CONFIG3: 1292204e7c49SRob Herring vp = &attr->config3; 1293204e7c49SRob Herring break; 1294cd82a32eSJiri Olsa default: 1295cd82a32eSJiri Olsa return -EINVAL; 1296cd82a32eSJiri Olsa } 1297cd82a32eSJiri Olsa 129816fa7e82SJiri Olsa /* 1299688d4dfcSCody P Schafer * Either directly use a numeric term, or try to translate string terms 1300688d4dfcSCody P Schafer * using event parameters. 130116fa7e82SJiri Olsa */ 130299e7138eSJiri Olsa if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 130399e7138eSJiri Olsa if (term->no_value && 130499e7138eSJiri Olsa bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) { 130599e7138eSJiri Olsa if (err) { 13066c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1307448d732cSIan Rogers strdup("no value assigned for term"), 1308448d732cSIan Rogers NULL); 130999e7138eSJiri Olsa } 131099e7138eSJiri Olsa return -EINVAL; 131199e7138eSJiri Olsa } 131299e7138eSJiri Olsa 1313688d4dfcSCody P Schafer val = term->val.num; 131499e7138eSJiri Olsa } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1315688d4dfcSCody P Schafer if (strcmp(term->val.str, "?")) { 1316bb963e16SNamhyung Kim if (verbose > 0) { 1317688d4dfcSCody P Schafer pr_info("Invalid sysfs entry %s=%s\n", 1318688d4dfcSCody P Schafer term->config, term->val.str); 1319e64b020bSJiri Olsa } 1320e64b020bSJiri Olsa if (err) { 13216c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1322448d732cSIan Rogers strdup("expected numeric value"), 1323448d732cSIan Rogers NULL); 1324e64b020bSJiri Olsa } 1325688d4dfcSCody P Schafer return -EINVAL; 1326688d4dfcSCody P Schafer } 1327688d4dfcSCody P Schafer 1328688d4dfcSCody P Schafer if (pmu_resolve_param_term(term, head_terms, &val)) 1329688d4dfcSCody P Schafer return -EINVAL; 1330688d4dfcSCody P Schafer } else 1331688d4dfcSCody P Schafer return -EINVAL; 1332688d4dfcSCody P Schafer 13330efe6b67SAdrian Hunter max_val = pmu_format_max_value(format->bits); 13340efe6b67SAdrian Hunter if (val > max_val) { 13350efe6b67SAdrian Hunter if (err) { 1336448d732cSIan Rogers char *err_str; 1337448d732cSIan Rogers 13386c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1339448d732cSIan Rogers asprintf(&err_str, 13400efe6b67SAdrian Hunter "value too big for format, maximum is %llu", 1341448d732cSIan Rogers (unsigned long long)max_val) < 0 1342448d732cSIan Rogers ? strdup("value too big for format") 1343448d732cSIan Rogers : err_str, 1344448d732cSIan Rogers NULL); 13450efe6b67SAdrian Hunter return -EINVAL; 13460efe6b67SAdrian Hunter } 13470efe6b67SAdrian Hunter /* 13480efe6b67SAdrian Hunter * Assume we don't care if !err, in which case the value will be 13490efe6b67SAdrian Hunter * silently truncated. 13500efe6b67SAdrian Hunter */ 13510efe6b67SAdrian Hunter } 13520efe6b67SAdrian Hunter 1353688d4dfcSCody P Schafer pmu_format_value(format->bits, val, vp, zero); 1354cd82a32eSJiri Olsa return 0; 1355cd82a32eSJiri Olsa } 1356cd82a32eSJiri Olsa 1357804fee5dSIan Rogers int perf_pmu__config_terms(struct perf_pmu *pmu, 1358cff7f956SJiri Olsa struct perf_event_attr *attr, 1359dc0a6202SAdrian Hunter struct list_head *head_terms, 1360e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1361cd82a32eSJiri Olsa { 13626cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 1363cd82a32eSJiri Olsa 1364688d4dfcSCody P Schafer list_for_each_entry(term, head_terms, list) { 1365804fee5dSIan Rogers if (pmu_config_term(pmu, attr, term, head_terms, zero, err)) 1366cd82a32eSJiri Olsa return -EINVAL; 1367688d4dfcSCody P Schafer } 1368cd82a32eSJiri Olsa 1369cd82a32eSJiri Olsa return 0; 1370cd82a32eSJiri Olsa } 1371cd82a32eSJiri Olsa 1372cd82a32eSJiri Olsa /* 1373cd82a32eSJiri Olsa * Configures event's 'attr' parameter based on the: 1374cd82a32eSJiri Olsa * 1) users input - specified in terms parameter 1375cd82a32eSJiri Olsa * 2) pmu format definitions - specified by pmu parameter 1376cd82a32eSJiri Olsa */ 1377cd82a32eSJiri Olsa int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 1378e64b020bSJiri Olsa struct list_head *head_terms, 1379e64b020bSJiri Olsa struct parse_events_error *err) 1380cd82a32eSJiri Olsa { 1381dc0a6202SAdrian Hunter bool zero = !!pmu->default_config; 1382dc0a6202SAdrian Hunter 1383804fee5dSIan Rogers return perf_pmu__config_terms(pmu, attr, head_terms, zero, err); 1384cd82a32eSJiri Olsa } 1385cd82a32eSJiri Olsa 1386c3245d20SIan Rogers static struct perf_pmu_alias *perf_pmu__find_alias(const struct perf_pmu *pmu, const char *str) 1387c3245d20SIan Rogers { 1388c3245d20SIan Rogers struct perf_pmu_alias *alias; 1389c3245d20SIan Rogers 1390c3245d20SIan Rogers list_for_each_entry(alias, &pmu->aliases, list) { 1391c3245d20SIan Rogers if (!strcasecmp(alias->name, str)) 1392c3245d20SIan Rogers return alias; 1393c3245d20SIan Rogers } 1394c3245d20SIan Rogers return NULL; 1395c3245d20SIan Rogers } 1396c3245d20SIan Rogers 13975c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 13986cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 1399a6146d50SZheng Yan { 1400a6146d50SZheng Yan char *name; 1401a6146d50SZheng Yan 1402a6146d50SZheng Yan if (parse_events__is_hardcoded_term(term)) 1403a6146d50SZheng Yan return NULL; 1404a6146d50SZheng Yan 1405a6146d50SZheng Yan if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 1406a6146d50SZheng Yan if (term->val.num != 1) 1407a6146d50SZheng Yan return NULL; 1408a6146d50SZheng Yan if (pmu_find_format(&pmu->format, term->config)) 1409a6146d50SZheng Yan return NULL; 1410a6146d50SZheng Yan name = term->config; 1411c3245d20SIan Rogers 1412a6146d50SZheng Yan } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1413a6146d50SZheng Yan if (strcasecmp(term->config, "event")) 1414a6146d50SZheng Yan return NULL; 1415a6146d50SZheng Yan name = term->val.str; 1416a6146d50SZheng Yan } else { 1417a6146d50SZheng Yan return NULL; 1418a6146d50SZheng Yan } 1419a6146d50SZheng Yan 1420c3245d20SIan Rogers return perf_pmu__find_alias(pmu, name); 1421a6146d50SZheng Yan } 1422a6146d50SZheng Yan 1423410136f5SStephane Eranian 14241d9e446bSJiri Olsa static int check_info_data(struct perf_pmu_alias *alias, 14259d31cb93SIan Rogers struct perf_pmu_info *info, 14269d31cb93SIan Rogers struct parse_events_error *err, 14279d31cb93SIan Rogers int column) 1428410136f5SStephane Eranian { 1429410136f5SStephane Eranian /* 1430410136f5SStephane Eranian * Only one term in event definition can 14311d9e446bSJiri Olsa * define unit, scale and snapshot, fail 14321d9e446bSJiri Olsa * if there's more than one. 1433410136f5SStephane Eranian */ 14349d31cb93SIan Rogers if (info->unit && alias->unit[0]) { 14359d31cb93SIan Rogers parse_events_error__handle(err, column, 14369d31cb93SIan Rogers strdup("Attempt to set event's unit twice"), 14379d31cb93SIan Rogers NULL); 1438410136f5SStephane Eranian return -EINVAL; 14399d31cb93SIan Rogers } 14409d31cb93SIan Rogers if (info->scale && alias->scale) { 14419d31cb93SIan Rogers parse_events_error__handle(err, column, 14429d31cb93SIan Rogers strdup("Attempt to set event's scale twice"), 14439d31cb93SIan Rogers NULL); 14449d31cb93SIan Rogers return -EINVAL; 14459d31cb93SIan Rogers } 14469d31cb93SIan Rogers if (info->snapshot && alias->snapshot) { 14479d31cb93SIan Rogers parse_events_error__handle(err, column, 14489d31cb93SIan Rogers strdup("Attempt to set event snapshot twice"), 14499d31cb93SIan Rogers NULL); 14509d31cb93SIan Rogers return -EINVAL; 14519d31cb93SIan Rogers } 1452410136f5SStephane Eranian 1453b30a7d1fSArnaldo Carvalho de Melo if (alias->unit[0]) 14541d9e446bSJiri Olsa info->unit = alias->unit; 1455410136f5SStephane Eranian 1456410136f5SStephane Eranian if (alias->scale) 14571d9e446bSJiri Olsa info->scale = alias->scale; 14581d9e446bSJiri Olsa 14591d9e446bSJiri Olsa if (alias->snapshot) 14601d9e446bSJiri Olsa info->snapshot = alias->snapshot; 1461410136f5SStephane Eranian 1462410136f5SStephane Eranian return 0; 1463410136f5SStephane Eranian } 1464410136f5SStephane Eranian 1465a6146d50SZheng Yan /* 1466a6146d50SZheng Yan * Find alias in the terms list and replace it with the terms 1467a6146d50SZheng Yan * defined for the alias 1468a6146d50SZheng Yan */ 1469410136f5SStephane Eranian int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 14709d31cb93SIan Rogers struct perf_pmu_info *info, struct parse_events_error *err) 1471a6146d50SZheng Yan { 14726cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 14735c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1474a6146d50SZheng Yan int ret; 1475a6146d50SZheng Yan 1476044330c1SMatt Fleming info->per_pkg = false; 1477044330c1SMatt Fleming 14788a398897SStephane Eranian /* 14798a398897SStephane Eranian * Mark unit and scale as not set 14808a398897SStephane Eranian * (different from default values, see below) 14818a398897SStephane Eranian */ 148246441bdcSMatt Fleming info->unit = NULL; 148346441bdcSMatt Fleming info->scale = 0.0; 14841d9e446bSJiri Olsa info->snapshot = false; 1485410136f5SStephane Eranian 1486a6146d50SZheng Yan list_for_each_entry_safe(term, h, head_terms, list) { 1487a6146d50SZheng Yan alias = pmu_find_alias(pmu, term); 1488a6146d50SZheng Yan if (!alias) 1489a6146d50SZheng Yan continue; 1490a6146d50SZheng Yan ret = pmu_alias_terms(alias, &term->list); 14919d31cb93SIan Rogers if (ret) { 14929d31cb93SIan Rogers parse_events_error__handle(err, term->err_term, 14939d31cb93SIan Rogers strdup("Failure to duplicate terms"), 14949d31cb93SIan Rogers NULL); 1495a6146d50SZheng Yan return ret; 14969d31cb93SIan Rogers } 1497410136f5SStephane Eranian 14989d31cb93SIan Rogers ret = check_info_data(alias, info, err, term->err_term); 1499410136f5SStephane Eranian if (ret) 1500410136f5SStephane Eranian return ret; 1501410136f5SStephane Eranian 1502044330c1SMatt Fleming if (alias->per_pkg) 1503044330c1SMatt Fleming info->per_pkg = true; 1504044330c1SMatt Fleming 1505e56fbc9dSArnaldo Carvalho de Melo list_del_init(&term->list); 15061dc92556SIan Rogers parse_events_term__delete(term); 1507a6146d50SZheng Yan } 15088a398897SStephane Eranian 15098a398897SStephane Eranian /* 15108a398897SStephane Eranian * if no unit or scale found in aliases, then 15118a398897SStephane Eranian * set defaults as for evsel 15128a398897SStephane Eranian * unit cannot left to NULL 15138a398897SStephane Eranian */ 151446441bdcSMatt Fleming if (info->unit == NULL) 151546441bdcSMatt Fleming info->unit = ""; 15168a398897SStephane Eranian 151746441bdcSMatt Fleming if (info->scale == 0.0) 151846441bdcSMatt Fleming info->scale = 1.0; 15198a398897SStephane Eranian 1520a6146d50SZheng Yan return 0; 1521a6146d50SZheng Yan } 1522a6146d50SZheng Yan 1523c3245d20SIan Rogers struct find_event_args { 1524c3245d20SIan Rogers const char *event; 1525c3245d20SIan Rogers void *state; 1526c3245d20SIan Rogers pmu_event_callback cb; 1527c3245d20SIan Rogers }; 1528c3245d20SIan Rogers 1529c3245d20SIan Rogers static int find_event_callback(void *state, struct pmu_event_info *info) 1530838a8c5fSIan Rogers { 1531c3245d20SIan Rogers struct find_event_args *args = state; 1532838a8c5fSIan Rogers 1533c3245d20SIan Rogers if (!strcmp(args->event, info->name)) 1534c3245d20SIan Rogers return args->cb(args->state, info); 1535838a8c5fSIan Rogers 1536c3245d20SIan Rogers return 0; 1537838a8c5fSIan Rogers } 1538c3245d20SIan Rogers 1539c3245d20SIan Rogers int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb) 1540c3245d20SIan Rogers { 1541c3245d20SIan Rogers struct find_event_args args = { 1542c3245d20SIan Rogers .event = event, 1543c3245d20SIan Rogers .state = state, 1544c3245d20SIan Rogers .cb = cb, 1545c3245d20SIan Rogers }; 1546c3245d20SIan Rogers 1547c3245d20SIan Rogers return perf_pmu__for_each_event(pmu, &args, find_event_callback); 1548c3245d20SIan Rogers } 1549c3245d20SIan Rogers 1550804fee5dSIan Rogers static void perf_pmu__del_formats(struct list_head *formats) 1551d26383dcSNamhyung Kim { 1552d26383dcSNamhyung Kim struct perf_pmu_format *fmt, *tmp; 1553d26383dcSNamhyung Kim 1554d26383dcSNamhyung Kim list_for_each_entry_safe(fmt, tmp, formats, list) { 1555d26383dcSNamhyung Kim list_del(&fmt->list); 1556efe98a7aSArnaldo Carvalho de Melo zfree(&fmt->name); 1557d26383dcSNamhyung Kim free(fmt); 1558d26383dcSNamhyung Kim } 1559d26383dcSNamhyung Kim } 1560d26383dcSNamhyung Kim 156107d2b820SIan Rogers bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name) 156207d2b820SIan Rogers { 156307d2b820SIan Rogers struct perf_pmu_format *format; 156407d2b820SIan Rogers 156507d2b820SIan Rogers list_for_each_entry(format, &pmu->format, list) { 156607d2b820SIan Rogers if (!strcmp(format->name, name)) 156707d2b820SIan Rogers return true; 156807d2b820SIan Rogers } 156907d2b820SIan Rogers return false; 157007d2b820SIan Rogers } 157107d2b820SIan Rogers 1572d504fae9SJohn Garry bool is_pmu_core(const char *name) 1573d504fae9SJohn Garry { 15746fbd67b0SThomas Richter return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name); 15754bf7e81aSIan Rogers } 15764bf7e81aSIan Rogers 15776fd1e519SIan Rogers bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu) 15786fd1e519SIan Rogers { 1579e20d1f2fSIan Rogers return pmu->is_core; 15806fd1e519SIan Rogers } 15816fd1e519SIan Rogers 158252c7b4d3SIan Rogers bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) 158352c7b4d3SIan Rogers { 1584710dffc9SIan Rogers return !pmu->is_core || perf_pmus__num_core_pmus() == 1; 158552c7b4d3SIan Rogers } 158652c7b4d3SIan Rogers 15871eaf496eSIan Rogers bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name) 1588abe9544eSIan Rogers { 1589c3245d20SIan Rogers return perf_pmu__find_alias(pmu, name) != NULL; 15904cabc3d1SAndi Kleen } 1591c3245d20SIan Rogers 1592c3245d20SIan Rogers size_t perf_pmu__num_events(const struct perf_pmu *pmu) 1593c3245d20SIan Rogers { 1594c3245d20SIan Rogers struct list_head *list; 1595c3245d20SIan Rogers size_t nr = 0; 1596c3245d20SIan Rogers 1597c3245d20SIan Rogers list_for_each(list, &pmu->aliases) 1598c3245d20SIan Rogers nr++; 1599c3245d20SIan Rogers 1600c3245d20SIan Rogers return pmu->selectable ? nr + 1 : nr; 1601c3245d20SIan Rogers } 1602c3245d20SIan Rogers 1603c3245d20SIan Rogers static int sub_non_neg(int a, int b) 1604c3245d20SIan Rogers { 1605c3245d20SIan Rogers if (b > a) 1606c3245d20SIan Rogers return 0; 1607c3245d20SIan Rogers return a - b; 1608c3245d20SIan Rogers } 1609c3245d20SIan Rogers 1610c3245d20SIan Rogers static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, 1611c3245d20SIan Rogers const struct perf_pmu_alias *alias) 1612c3245d20SIan Rogers { 1613c3245d20SIan Rogers struct parse_events_term *term; 1614c3245d20SIan Rogers int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); 1615c3245d20SIan Rogers 1616c3245d20SIan Rogers list_for_each_entry(term, &alias->terms, list) { 1617c3245d20SIan Rogers if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 1618c3245d20SIan Rogers used += snprintf(buf + used, sub_non_neg(len, used), 1619c3245d20SIan Rogers ",%s=%s", term->config, 1620c3245d20SIan Rogers term->val.str); 1621c3245d20SIan Rogers } 1622c3245d20SIan Rogers 1623c3245d20SIan Rogers if (sub_non_neg(len, used) > 0) { 1624c3245d20SIan Rogers buf[used] = '/'; 1625c3245d20SIan Rogers used++; 1626c3245d20SIan Rogers } 1627c3245d20SIan Rogers if (sub_non_neg(len, used) > 0) { 1628c3245d20SIan Rogers buf[used] = '\0'; 1629c3245d20SIan Rogers used++; 1630c3245d20SIan Rogers } else 1631c3245d20SIan Rogers buf[len - 1] = '\0'; 1632c3245d20SIan Rogers 1633c3245d20SIan Rogers return buf; 1634c3245d20SIan Rogers } 1635c3245d20SIan Rogers 1636c3245d20SIan Rogers int perf_pmu__for_each_event(const struct perf_pmu *pmu, void *state, pmu_event_callback cb) 1637c3245d20SIan Rogers { 1638c3245d20SIan Rogers char buf[1024]; 1639c3245d20SIan Rogers struct perf_pmu_alias *event; 1640c3245d20SIan Rogers struct pmu_event_info info = { 1641c3245d20SIan Rogers .pmu = pmu, 1642c3245d20SIan Rogers }; 1643c3245d20SIan Rogers int ret = 0; 1644c3245d20SIan Rogers 1645c3245d20SIan Rogers list_for_each_entry(event, &pmu->aliases, list) { 1646c3245d20SIan Rogers size_t buf_used; 1647c3245d20SIan Rogers 1648c3245d20SIan Rogers info.pmu_name = event->pmu_name ?: pmu->name; 1649c3245d20SIan Rogers info.alias = NULL; 1650c3245d20SIan Rogers if (event->desc) { 1651c3245d20SIan Rogers info.name = event->name; 1652c3245d20SIan Rogers buf_used = 0; 1653c3245d20SIan Rogers } else { 1654c3245d20SIan Rogers info.name = format_alias(buf, sizeof(buf), pmu, event); 1655c3245d20SIan Rogers if (pmu->is_core) { 1656c3245d20SIan Rogers info.alias = info.name; 1657c3245d20SIan Rogers info.name = event->name; 1658c3245d20SIan Rogers } 1659c3245d20SIan Rogers buf_used = strlen(buf) + 1; 1660c3245d20SIan Rogers } 1661c3245d20SIan Rogers info.scale_unit = NULL; 1662c3245d20SIan Rogers if (strlen(event->unit) || event->scale != 1.0) { 1663c3245d20SIan Rogers info.scale_unit = buf + buf_used; 1664c3245d20SIan Rogers buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 1665c3245d20SIan Rogers "%G%s", event->scale, event->unit) + 1; 1666c3245d20SIan Rogers } 1667c3245d20SIan Rogers info.desc = event->desc; 1668c3245d20SIan Rogers info.long_desc = event->long_desc; 1669c3245d20SIan Rogers info.encoding_desc = buf + buf_used; 1670c3245d20SIan Rogers buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 1671c3245d20SIan Rogers "%s/%s/", info.pmu_name, event->str) + 1; 1672c3245d20SIan Rogers info.topic = event->topic; 1673c3245d20SIan Rogers info.str = event->str; 1674c3245d20SIan Rogers info.deprecated = event->deprecated; 1675c3245d20SIan Rogers ret = cb(state, &info); 1676c3245d20SIan Rogers if (ret) 1677c3245d20SIan Rogers return ret; 1678c3245d20SIan Rogers } 1679c3245d20SIan Rogers if (pmu->selectable) { 1680c3245d20SIan Rogers info.name = buf; 1681c3245d20SIan Rogers snprintf(buf, sizeof(buf), "%s//", pmu->name); 1682c3245d20SIan Rogers info.alias = NULL; 1683c3245d20SIan Rogers info.scale_unit = NULL; 1684c3245d20SIan Rogers info.desc = NULL; 1685c3245d20SIan Rogers info.long_desc = NULL; 1686c3245d20SIan Rogers info.encoding_desc = NULL; 1687c3245d20SIan Rogers info.topic = NULL; 1688c3245d20SIan Rogers info.pmu_name = pmu->name; 1689c3245d20SIan Rogers info.deprecated = false; 1690c3245d20SIan Rogers ret = cb(state, &info); 1691c3245d20SIan Rogers } 1692c3245d20SIan Rogers return ret; 16934cabc3d1SAndi Kleen } 16947d4bdab5SAdrian Hunter 1695*e3edd6cfSIan Rogers bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name) 1696*e3edd6cfSIan Rogers { 1697*e3edd6cfSIan Rogers return !strcmp(pmu->name, pmu_name) || 1698*e3edd6cfSIan Rogers (pmu->is_uncore && pmu_uncore_alias_match(pmu_name, pmu->name)); 1699*e3edd6cfSIan Rogers } 1700*e3edd6cfSIan Rogers 1701251aa040SIan Rogers bool perf_pmu__is_software(const struct perf_pmu *pmu) 1702251aa040SIan Rogers { 1703251aa040SIan Rogers if (pmu->is_core || pmu->is_uncore || pmu->auxtrace) 1704251aa040SIan Rogers return false; 1705251aa040SIan Rogers switch (pmu->type) { 1706251aa040SIan Rogers case PERF_TYPE_HARDWARE: return false; 1707251aa040SIan Rogers case PERF_TYPE_SOFTWARE: return true; 1708251aa040SIan Rogers case PERF_TYPE_TRACEPOINT: return true; 1709251aa040SIan Rogers case PERF_TYPE_HW_CACHE: return false; 1710251aa040SIan Rogers case PERF_TYPE_RAW: return false; 1711251aa040SIan Rogers case PERF_TYPE_BREAKPOINT: return true; 1712251aa040SIan Rogers default: break; 1713251aa040SIan Rogers } 1714251aa040SIan Rogers return !strcmp(pmu->name, "kprobe") || !strcmp(pmu->name, "uprobe"); 1715251aa040SIan Rogers } 1716251aa040SIan Rogers 1717d50a79cdSJames Clark FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) 17187d4bdab5SAdrian Hunter { 17197d4bdab5SAdrian Hunter char path[PATH_MAX]; 17207d4bdab5SAdrian Hunter 1721f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name) || 1722f8ad6018SJames Clark !file_available(path)) 17237d4bdab5SAdrian Hunter return NULL; 17247d4bdab5SAdrian Hunter 17257d4bdab5SAdrian Hunter return fopen(path, "r"); 17267d4bdab5SAdrian Hunter } 17277d4bdab5SAdrian Hunter 17283a69672eSNamhyung Kim FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name) 17293a69672eSNamhyung Kim { 17303a69672eSNamhyung Kim int fd; 17313a69672eSNamhyung Kim 17323a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, pmu->name, name, O_RDONLY); 17333a69672eSNamhyung Kim if (fd < 0) 17343a69672eSNamhyung Kim return NULL; 17353a69672eSNamhyung Kim 17363a69672eSNamhyung Kim return fdopen(fd, "r"); 17373a69672eSNamhyung Kim } 17383a69672eSNamhyung Kim 17397d4bdab5SAdrian Hunter int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 17407d4bdab5SAdrian Hunter ...) 17417d4bdab5SAdrian Hunter { 17427d4bdab5SAdrian Hunter va_list args; 17437d4bdab5SAdrian Hunter FILE *file; 17447d4bdab5SAdrian Hunter int ret = EOF; 17457d4bdab5SAdrian Hunter 17467d4bdab5SAdrian Hunter va_start(args, fmt); 17477d4bdab5SAdrian Hunter file = perf_pmu__open_file(pmu, name); 17487d4bdab5SAdrian Hunter if (file) { 17497d4bdab5SAdrian Hunter ret = vfscanf(file, fmt, args); 17507d4bdab5SAdrian Hunter fclose(file); 17517d4bdab5SAdrian Hunter } 17527d4bdab5SAdrian Hunter va_end(args); 17537d4bdab5SAdrian Hunter return ret; 17547d4bdab5SAdrian Hunter } 17559fbc61f8SKan Liang 17563a69672eSNamhyung Kim int perf_pmu__scan_file_at(struct perf_pmu *pmu, int dirfd, const char *name, 17573a69672eSNamhyung Kim const char *fmt, ...) 17583a69672eSNamhyung Kim { 17593a69672eSNamhyung Kim va_list args; 17603a69672eSNamhyung Kim FILE *file; 17613a69672eSNamhyung Kim int ret = EOF; 17623a69672eSNamhyung Kim 17633a69672eSNamhyung Kim va_start(args, fmt); 17643a69672eSNamhyung Kim file = perf_pmu__open_file_at(pmu, dirfd, name); 17653a69672eSNamhyung Kim if (file) { 17663a69672eSNamhyung Kim ret = vfscanf(file, fmt, args); 17673a69672eSNamhyung Kim fclose(file); 17683a69672eSNamhyung Kim } 17693a69672eSNamhyung Kim va_end(args); 17703a69672eSNamhyung Kim return ret; 17713a69672eSNamhyung Kim } 17723a69672eSNamhyung Kim 1773c2b6a896SGerman Gomez bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name) 1774c2b6a896SGerman Gomez { 1775c2b6a896SGerman Gomez char path[PATH_MAX]; 1776c2b6a896SGerman Gomez 1777c2b6a896SGerman Gomez if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name)) 1778c2b6a896SGerman Gomez return false; 1779c2b6a896SGerman Gomez 1780c2b6a896SGerman Gomez return file_available(path); 1781c2b6a896SGerman Gomez } 1782c2b6a896SGerman Gomez 17839fbc61f8SKan Liang static int perf_pmu__new_caps(struct list_head *list, char *name, char *value) 17849fbc61f8SKan Liang { 17859fbc61f8SKan Liang struct perf_pmu_caps *caps = zalloc(sizeof(*caps)); 17869fbc61f8SKan Liang 17879fbc61f8SKan Liang if (!caps) 17889fbc61f8SKan Liang return -ENOMEM; 17899fbc61f8SKan Liang 17909fbc61f8SKan Liang caps->name = strdup(name); 17919fbc61f8SKan Liang if (!caps->name) 17929fbc61f8SKan Liang goto free_caps; 17939fbc61f8SKan Liang caps->value = strndup(value, strlen(value) - 1); 17949fbc61f8SKan Liang if (!caps->value) 17959fbc61f8SKan Liang goto free_name; 17969fbc61f8SKan Liang list_add_tail(&caps->list, list); 17979fbc61f8SKan Liang return 0; 17989fbc61f8SKan Liang 17999fbc61f8SKan Liang free_name: 180057f14b5aSArnaldo Carvalho de Melo zfree(&caps->name); 18019fbc61f8SKan Liang free_caps: 18029fbc61f8SKan Liang free(caps); 18039fbc61f8SKan Liang 18049fbc61f8SKan Liang return -ENOMEM; 18059fbc61f8SKan Liang } 18069fbc61f8SKan Liang 1807eec11310SNamhyung Kim static void perf_pmu__del_caps(struct perf_pmu *pmu) 1808eec11310SNamhyung Kim { 1809eec11310SNamhyung Kim struct perf_pmu_caps *caps, *tmp; 1810eec11310SNamhyung Kim 1811eec11310SNamhyung Kim list_for_each_entry_safe(caps, tmp, &pmu->caps, list) { 1812eec11310SNamhyung Kim list_del(&caps->list); 1813efe98a7aSArnaldo Carvalho de Melo zfree(&caps->name); 1814efe98a7aSArnaldo Carvalho de Melo zfree(&caps->value); 1815eec11310SNamhyung Kim free(caps); 1816eec11310SNamhyung Kim } 1817eec11310SNamhyung Kim } 1818eec11310SNamhyung Kim 18199fbc61f8SKan Liang /* 18209fbc61f8SKan Liang * Reading/parsing the given pmu capabilities, which should be located at: 18219fbc61f8SKan Liang * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes. 18229fbc61f8SKan Liang * Return the number of capabilities 18239fbc61f8SKan Liang */ 18249fbc61f8SKan Liang int perf_pmu__caps_parse(struct perf_pmu *pmu) 18259fbc61f8SKan Liang { 18269fbc61f8SKan Liang struct stat st; 18279fbc61f8SKan Liang char caps_path[PATH_MAX]; 18289fbc61f8SKan Liang DIR *caps_dir; 18299fbc61f8SKan Liang struct dirent *evt_ent; 1830b39094d3SNamhyung Kim int caps_fd; 18313339ec44SRavi Bangoria 18323339ec44SRavi Bangoria if (pmu->caps_initialized) 18333339ec44SRavi Bangoria return pmu->nr_caps; 18343339ec44SRavi Bangoria 18353339ec44SRavi Bangoria pmu->nr_caps = 0; 18369fbc61f8SKan Liang 1837f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(caps_path, sizeof(caps_path), pmu->name, "caps")) 18389fbc61f8SKan Liang return -1; 18399fbc61f8SKan Liang 18403339ec44SRavi Bangoria if (stat(caps_path, &st) < 0) { 18413339ec44SRavi Bangoria pmu->caps_initialized = true; 18429fbc61f8SKan Liang return 0; /* no error if caps does not exist */ 18433339ec44SRavi Bangoria } 18449fbc61f8SKan Liang 18459fbc61f8SKan Liang caps_dir = opendir(caps_path); 18469fbc61f8SKan Liang if (!caps_dir) 18479fbc61f8SKan Liang return -EINVAL; 18489fbc61f8SKan Liang 1849b39094d3SNamhyung Kim caps_fd = dirfd(caps_dir); 1850b39094d3SNamhyung Kim 18519fbc61f8SKan Liang while ((evt_ent = readdir(caps_dir)) != NULL) { 18529fbc61f8SKan Liang char *name = evt_ent->d_name; 18539fbc61f8SKan Liang char value[128]; 18549fbc61f8SKan Liang FILE *file; 1855b39094d3SNamhyung Kim int fd; 18569fbc61f8SKan Liang 18579fbc61f8SKan Liang if (!strcmp(name, ".") || !strcmp(name, "..")) 18589fbc61f8SKan Liang continue; 18599fbc61f8SKan Liang 1860b39094d3SNamhyung Kim fd = openat(caps_fd, name, O_RDONLY); 18610ea8920eSIan Rogers if (fd == -1) 18629fbc61f8SKan Liang continue; 18630ea8920eSIan Rogers file = fdopen(fd, "r"); 18640ea8920eSIan Rogers if (!file) { 18650ea8920eSIan Rogers close(fd); 18660ea8920eSIan Rogers continue; 18670ea8920eSIan Rogers } 18689fbc61f8SKan Liang 18699fbc61f8SKan Liang if (!fgets(value, sizeof(value), file) || 18709fbc61f8SKan Liang (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) { 18719fbc61f8SKan Liang fclose(file); 18729fbc61f8SKan Liang continue; 18739fbc61f8SKan Liang } 18749fbc61f8SKan Liang 18753339ec44SRavi Bangoria pmu->nr_caps++; 18769fbc61f8SKan Liang fclose(file); 18779fbc61f8SKan Liang } 18789fbc61f8SKan Liang 18799fbc61f8SKan Liang closedir(caps_dir); 18809fbc61f8SKan Liang 18813339ec44SRavi Bangoria pmu->caps_initialized = true; 18823339ec44SRavi Bangoria return pmu->nr_caps; 18839fbc61f8SKan Liang } 1884e4064776SJin Yao 1885b9f01032SIan Rogers static void perf_pmu__compute_config_masks(struct perf_pmu *pmu) 1886e4064776SJin Yao { 1887e4064776SJin Yao struct perf_pmu_format *format; 1888b9f01032SIan Rogers 1889b9f01032SIan Rogers if (pmu->config_masks_computed) 1890b9f01032SIan Rogers return; 1891e4064776SJin Yao 1892e4064776SJin Yao list_for_each_entry(format, &pmu->format, list) { 1893b9f01032SIan Rogers unsigned int i; 1894b9f01032SIan Rogers __u64 *mask; 1895b9f01032SIan Rogers 1896b9f01032SIan Rogers if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) 1897e4064776SJin Yao continue; 1898e4064776SJin Yao 1899b9f01032SIan Rogers pmu->config_masks_present = true; 1900b9f01032SIan Rogers mask = &pmu->config_masks[format->value]; 1901b9f01032SIan Rogers 1902e4064776SJin Yao for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS) 1903b9f01032SIan Rogers *mask |= 1ULL << i; 1904e4064776SJin Yao } 1905b9f01032SIan Rogers pmu->config_masks_computed = true; 1906b9f01032SIan Rogers } 1907b9f01032SIan Rogers 1908b9f01032SIan Rogers void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 1909b9f01032SIan Rogers const char *name, int config_num, 1910b9f01032SIan Rogers const char *config_name) 1911b9f01032SIan Rogers { 1912b9f01032SIan Rogers __u64 bits; 1913b9f01032SIan Rogers char buf[100]; 1914b9f01032SIan Rogers 1915b9f01032SIan Rogers perf_pmu__compute_config_masks(pmu); 1916e4064776SJin Yao 1917e4064776SJin Yao /* 1918e4064776SJin Yao * Kernel doesn't export any valid format bits. 1919e4064776SJin Yao */ 1920b9f01032SIan Rogers if (!pmu->config_masks_present) 1921e4064776SJin Yao return; 1922e4064776SJin Yao 1923b9f01032SIan Rogers bits = config & ~pmu->config_masks[config_num]; 1924e4064776SJin Yao if (bits == 0) 1925e4064776SJin Yao return; 1926e4064776SJin Yao 1927e4064776SJin Yao bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf)); 1928e4064776SJin Yao 1929b9f01032SIan Rogers pr_warning("WARNING: event '%s' not valid (bits %s of %s " 1930e4064776SJin Yao "'%llx' not supported by kernel)!\n", 1931b9f01032SIan Rogers name ?: "N/A", buf, config_name, config); 1932e4064776SJin Yao } 1933c5a26ea4SJin Yao 1934c47a5599SJin Yao int perf_pmu__match(char *pattern, char *name, char *tok) 1935c47a5599SJin Yao { 193613d60ba0SKan Liang if (!name) 193713d60ba0SKan Liang return -1; 193813d60ba0SKan Liang 1939c47a5599SJin Yao if (fnmatch(pattern, name, 0)) 1940c47a5599SJin Yao return -1; 1941c47a5599SJin Yao 1942240e6fd0SIan Rogers if (tok && !perf_pmu__match_ignoring_suffix(name, tok)) 1943c47a5599SJin Yao return -1; 1944c47a5599SJin Yao 1945c47a5599SJin Yao return 0; 1946c47a5599SJin Yao } 19471d3351e6SJin Yao 1948acef233bSJing Zhang double __weak perf_pmu__cpu_slots_per_cycle(void) 1949acef233bSJing Zhang { 1950acef233bSJing Zhang return NAN; 1951acef233bSJing Zhang } 1952f8ad6018SJames Clark 1953f8ad6018SJames Clark int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size) 1954f8ad6018SJames Clark { 1955f8ad6018SJames Clark const char *sysfs = sysfs__mountpoint(); 1956f8ad6018SJames Clark 1957f8ad6018SJames Clark if (!sysfs) 1958f8ad6018SJames Clark return 0; 1959f8ad6018SJames Clark return scnprintf(pathname, size, "%s/bus/event_source/devices/", sysfs); 1960f8ad6018SJames Clark } 1961f8ad6018SJames Clark 1962e293a5e8SNamhyung Kim int perf_pmu__event_source_devices_fd(void) 1963e293a5e8SNamhyung Kim { 1964e293a5e8SNamhyung Kim char path[PATH_MAX]; 1965e293a5e8SNamhyung Kim const char *sysfs = sysfs__mountpoint(); 1966e293a5e8SNamhyung Kim 1967e293a5e8SNamhyung Kim if (!sysfs) 1968e293a5e8SNamhyung Kim return -1; 1969e293a5e8SNamhyung Kim 1970e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs); 1971e293a5e8SNamhyung Kim return open(path, O_DIRECTORY); 1972e293a5e8SNamhyung Kim } 1973e293a5e8SNamhyung Kim 1974f8ad6018SJames Clark /* 1975f8ad6018SJames Clark * Fill 'buf' with the path to a file or folder in 'pmu_name' in 1976f8ad6018SJames Clark * sysfs. For example if pmu_name = "cs_etm" and 'filename' = "format" 1977f8ad6018SJames Clark * then pathname will be filled with 1978f8ad6018SJames Clark * "/sys/bus/event_source/devices/cs_etm/format" 1979f8ad6018SJames Clark * 1980e1a3aad3SIan Rogers * Return 0 if the sysfs mountpoint couldn't be found, if no characters were 1981e1a3aad3SIan Rogers * written or if the buffer size is exceeded. 1982f8ad6018SJames Clark */ 1983f8ad6018SJames Clark int perf_pmu__pathname_scnprintf(char *buf, size_t size, 1984f8ad6018SJames Clark const char *pmu_name, const char *filename) 1985f8ad6018SJames Clark { 1986e1a3aad3SIan Rogers size_t len; 1987f8ad6018SJames Clark 1988e1a3aad3SIan Rogers len = perf_pmu__event_source_devices_scnprintf(buf, size); 1989e1a3aad3SIan Rogers if (!len || (len + strlen(pmu_name) + strlen(filename) + 1) >= size) 1990f8ad6018SJames Clark return 0; 1991e1a3aad3SIan Rogers 1992e1a3aad3SIan Rogers return scnprintf(buf + len, size - len, "%s/%s", pmu_name, filename); 1993f8ad6018SJames Clark } 1994eec11310SNamhyung Kim 1995e293a5e8SNamhyung Kim int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags) 1996e293a5e8SNamhyung Kim { 1997e293a5e8SNamhyung Kim char path[PATH_MAX]; 1998e293a5e8SNamhyung Kim 1999e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/%s", pmu_name, filename); 2000e293a5e8SNamhyung Kim return openat(dirfd, path, flags); 2001e293a5e8SNamhyung Kim } 2002e293a5e8SNamhyung Kim 20031eaf496eSIan Rogers void perf_pmu__delete(struct perf_pmu *pmu) 2004eec11310SNamhyung Kim { 2005eec11310SNamhyung Kim perf_pmu__del_formats(&pmu->format); 2006eec11310SNamhyung Kim perf_pmu__del_aliases(pmu); 2007eec11310SNamhyung Kim perf_pmu__del_caps(pmu); 2008eec11310SNamhyung Kim 2009eec11310SNamhyung Kim perf_cpu_map__put(pmu->cpus); 2010eec11310SNamhyung Kim 2011efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->default_config); 2012efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 2013efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->alias_name); 2014eec11310SNamhyung Kim free(pmu); 2015eec11310SNamhyung Kim } 20169d5da30eSJames Clark 20179d5da30eSJames Clark struct perf_pmu *pmu__find_core_pmu(void) 20189d5da30eSJames Clark { 20199d5da30eSJames Clark struct perf_pmu *pmu = NULL; 20209d5da30eSJames Clark 20219d5da30eSJames Clark while ((pmu = perf_pmus__scan_core(pmu))) { 20229d5da30eSJames Clark /* 20239d5da30eSJames Clark * The cpumap should cover all CPUs. Otherwise, some CPUs may 20249d5da30eSJames Clark * not support some events or have different event IDs. 20259d5da30eSJames Clark */ 20269d5da30eSJames Clark if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu) 20279d5da30eSJames Clark return NULL; 20289d5da30eSJames Clark 20299d5da30eSJames Clark return pmu; 20309d5da30eSJames Clark } 20319d5da30eSJames Clark return NULL; 20329d5da30eSJames Clark } 2033