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 34fe13d43dSIan Rogers /** 35fe13d43dSIan Rogers * struct perf_pmu_format - Values from a format file read from 36fe13d43dSIan Rogers * <sysfs>/devices/cpu/format/ held in struct perf_pmu. 37fe13d43dSIan Rogers * 38fe13d43dSIan Rogers * For example, the contents of <sysfs>/devices/cpu/format/event may be 39fe13d43dSIan Rogers * "config:0-7" and will be represented here as name="event", 40fe13d43dSIan Rogers * value=PERF_PMU_FORMAT_VALUE_CONFIG and bits 0 to 7 will be set. 41fe13d43dSIan Rogers */ 42ab1bf653SArnaldo Carvalho de Melo struct perf_pmu_format { 43*50402641SIan Rogers /** @list: Element on list within struct perf_pmu. */ 44*50402641SIan Rogers struct list_head list; 45*50402641SIan Rogers /** @bits: Which config bits are set by this format value. */ 46*50402641SIan Rogers DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); 47fe13d43dSIan Rogers /** @name: The modifier/file name. */ 48ab1bf653SArnaldo Carvalho de Melo char *name; 49fe13d43dSIan Rogers /** 50fe13d43dSIan Rogers * @value : Which config value the format relates to. Supported values 51fe13d43dSIan Rogers * are from PERF_PMU_FORMAT_VALUE_CONFIG to 52fe13d43dSIan Rogers * PERF_PMU_FORMAT_VALUE_CONFIG_END. 53fe13d43dSIan Rogers */ 54*50402641SIan Rogers u16 value; 55*50402641SIan Rogers /** @loaded: Has the contents been loaded/parsed. */ 56*50402641SIan Rogers bool loaded; 57ab1bf653SArnaldo Carvalho de Melo }; 58ab1bf653SArnaldo Carvalho de Melo 59*50402641SIan Rogers static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name) 60*50402641SIan Rogers { 61*50402641SIan Rogers struct perf_pmu_format *format; 62*50402641SIan Rogers 63*50402641SIan Rogers format = zalloc(sizeof(*format)); 64*50402641SIan Rogers if (!format) 65*50402641SIan Rogers return NULL; 66*50402641SIan Rogers 67*50402641SIan Rogers format->name = strdup(name); 68*50402641SIan Rogers if (!format->name) { 69*50402641SIan Rogers free(format); 70*50402641SIan Rogers return NULL; 71*50402641SIan Rogers } 72*50402641SIan Rogers list_add_tail(&format->list, list); 73*50402641SIan Rogers return format; 74*50402641SIan Rogers } 75*50402641SIan Rogers 76*50402641SIan Rogers /* Called at the end of parsing a format. */ 77*50402641SIan Rogers void perf_pmu_format__set_value(void *vformat, int config, unsigned long *bits) 78*50402641SIan Rogers { 79*50402641SIan Rogers struct perf_pmu_format *format = vformat; 80*50402641SIan Rogers 81*50402641SIan Rogers format->value = config; 82*50402641SIan Rogers memcpy(format->bits, bits, sizeof(format->bits)); 83*50402641SIan Rogers } 84*50402641SIan Rogers 85*50402641SIan Rogers static void __perf_pmu_format__load(struct perf_pmu_format *format, FILE *file) 86*50402641SIan Rogers { 87*50402641SIan Rogers void *scanner; 88*50402641SIan Rogers int ret; 89*50402641SIan Rogers 90*50402641SIan Rogers ret = perf_pmu_lex_init(&scanner); 91*50402641SIan Rogers if (ret) 92*50402641SIan Rogers return; 93*50402641SIan Rogers 94*50402641SIan Rogers perf_pmu_set_in(file, scanner); 95*50402641SIan Rogers ret = perf_pmu_parse(format, scanner); 96*50402641SIan Rogers perf_pmu_lex_destroy(scanner); 97*50402641SIan Rogers format->loaded = true; 98*50402641SIan Rogers } 99*50402641SIan Rogers 100*50402641SIan Rogers static void perf_pmu_format__load(struct perf_pmu *pmu, struct perf_pmu_format *format) 101*50402641SIan Rogers { 102*50402641SIan Rogers char path[PATH_MAX]; 103*50402641SIan Rogers FILE *file = NULL; 104*50402641SIan Rogers 105*50402641SIan Rogers if (format->loaded) 106*50402641SIan Rogers return; 107*50402641SIan Rogers 108*50402641SIan Rogers if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, "format")) 109*50402641SIan Rogers return; 110*50402641SIan Rogers 111*50402641SIan Rogers assert(strlen(path) + strlen(format->name) + 2 < sizeof(path)); 112*50402641SIan Rogers strcat(path, "/"); 113*50402641SIan Rogers strcat(path, format->name); 114*50402641SIan Rogers 115*50402641SIan Rogers file = fopen(path, "r"); 116*50402641SIan Rogers if (!file) 117*50402641SIan Rogers return; 118*50402641SIan Rogers __perf_pmu_format__load(format, file); 119*50402641SIan Rogers fclose(file); 120*50402641SIan Rogers } 121*50402641SIan Rogers 122cd82a32eSJiri Olsa /* 123cd82a32eSJiri Olsa * Parse & process all the sysfs attributes located under 124cd82a32eSJiri Olsa * the directory specified in 'dir' parameter. 125cd82a32eSJiri Olsa */ 126*50402641SIan Rogers int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load) 127cd82a32eSJiri Olsa { 128cd82a32eSJiri Olsa struct dirent *evt_ent; 129cd82a32eSJiri Olsa DIR *format_dir; 130cd82a32eSJiri Olsa int ret = 0; 131cd82a32eSJiri Olsa 132e293a5e8SNamhyung Kim format_dir = fdopendir(dirfd); 133cd82a32eSJiri Olsa if (!format_dir) 134cd82a32eSJiri Olsa return -EINVAL; 135cd82a32eSJiri Olsa 136*50402641SIan Rogers while ((evt_ent = readdir(format_dir)) != NULL) { 137*50402641SIan Rogers struct perf_pmu_format *format; 138cd82a32eSJiri Olsa char *name = evt_ent->d_name; 139cd82a32eSJiri Olsa 140cd82a32eSJiri Olsa if (!strcmp(name, ".") || !strcmp(name, "..")) 141cd82a32eSJiri Olsa continue; 142cd82a32eSJiri Olsa 143*50402641SIan Rogers format = perf_pmu__new_format(&pmu->format, name); 144*50402641SIan Rogers if (!format) { 145*50402641SIan Rogers ret = -ENOMEM; 146cd82a32eSJiri Olsa break; 147*50402641SIan Rogers } 148cd82a32eSJiri Olsa 149*50402641SIan Rogers if (eager_load) { 150*50402641SIan Rogers FILE *file; 151*50402641SIan Rogers int fd = openat(dirfd, name, O_RDONLY); 152*50402641SIan Rogers 153*50402641SIan Rogers if (fd < 0) { 154*50402641SIan Rogers ret = -errno; 155*50402641SIan Rogers break; 156*50402641SIan Rogers } 1573d88aec0SIan Rogers file = fdopen(fd, "r"); 1583d88aec0SIan Rogers if (!file) { 1593d88aec0SIan Rogers close(fd); 1603d88aec0SIan Rogers break; 1613d88aec0SIan Rogers } 162*50402641SIan Rogers __perf_pmu_format__load(format, file); 1633d88aec0SIan Rogers fclose(file); 1643d88aec0SIan Rogers } 165cd82a32eSJiri Olsa } 166cd82a32eSJiri Olsa 167cd82a32eSJiri Olsa closedir(format_dir); 168cd82a32eSJiri Olsa return ret; 169cd82a32eSJiri Olsa } 170cd82a32eSJiri Olsa 171cd82a32eSJiri Olsa /* 172cd82a32eSJiri Olsa * Reading/parsing the default pmu format definition, which should be 173cd82a32eSJiri Olsa * located at: 174cd82a32eSJiri Olsa * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. 175cd82a32eSJiri Olsa */ 176838a8c5fSIan Rogers static int pmu_format(struct perf_pmu *pmu, int dirfd, const char *name) 177cd82a32eSJiri Olsa { 178e293a5e8SNamhyung Kim int fd; 179cd82a32eSJiri Olsa 180e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "format", O_DIRECTORY); 181e293a5e8SNamhyung Kim if (fd < 0) 182d9664582SAndi Kleen return 0; 183cd82a32eSJiri Olsa 184e293a5e8SNamhyung Kim /* it'll close the fd */ 185*50402641SIan Rogers if (perf_pmu__format_parse(pmu, fd, /*eager_load=*/false)) 186cd82a32eSJiri Olsa return -1; 187cd82a32eSJiri Olsa 188cd82a32eSJiri Olsa return 0; 189cd82a32eSJiri Olsa } 190cd82a32eSJiri Olsa 191a55ab7c4SJin Yao int perf_pmu__convert_scale(const char *scale, char **end, double *sval) 192d02fc6bcSAndi Kleen { 193d02fc6bcSAndi Kleen char *lc; 194d02fc6bcSAndi Kleen int ret = 0; 195d02fc6bcSAndi Kleen 196d02fc6bcSAndi Kleen /* 197d02fc6bcSAndi Kleen * save current locale 198d02fc6bcSAndi Kleen */ 199d02fc6bcSAndi Kleen lc = setlocale(LC_NUMERIC, NULL); 200d02fc6bcSAndi Kleen 201d02fc6bcSAndi Kleen /* 202d02fc6bcSAndi Kleen * The lc string may be allocated in static storage, 203d02fc6bcSAndi Kleen * so get a dynamic copy to make it survive setlocale 204d02fc6bcSAndi Kleen * call below. 205d02fc6bcSAndi Kleen */ 206d02fc6bcSAndi Kleen lc = strdup(lc); 207d02fc6bcSAndi Kleen if (!lc) { 208d02fc6bcSAndi Kleen ret = -ENOMEM; 209d02fc6bcSAndi Kleen goto out; 210d02fc6bcSAndi Kleen } 211d02fc6bcSAndi Kleen 212d02fc6bcSAndi Kleen /* 213d02fc6bcSAndi Kleen * force to C locale to ensure kernel 214d02fc6bcSAndi Kleen * scale string is converted correctly. 215d02fc6bcSAndi Kleen * kernel uses default C locale. 216d02fc6bcSAndi Kleen */ 217d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, "C"); 218d02fc6bcSAndi Kleen 219d02fc6bcSAndi Kleen *sval = strtod(scale, end); 220d02fc6bcSAndi Kleen 221d02fc6bcSAndi Kleen out: 222d02fc6bcSAndi Kleen /* restore locale */ 223d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, lc); 224d02fc6bcSAndi Kleen free(lc); 225d02fc6bcSAndi Kleen return ret; 226d02fc6bcSAndi Kleen } 227d02fc6bcSAndi Kleen 228e293a5e8SNamhyung Kim static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, char *name) 229410136f5SStephane Eranian { 230410136f5SStephane Eranian struct stat st; 231410136f5SStephane Eranian ssize_t sret; 232410136f5SStephane Eranian char scale[128]; 233410136f5SStephane Eranian int fd, ret = -1; 234410136f5SStephane Eranian char path[PATH_MAX]; 235410136f5SStephane Eranian 236e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.scale", name); 237410136f5SStephane Eranian 238e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 239410136f5SStephane Eranian if (fd == -1) 240410136f5SStephane Eranian return -1; 241410136f5SStephane Eranian 242410136f5SStephane Eranian if (fstat(fd, &st) < 0) 243410136f5SStephane Eranian goto error; 244410136f5SStephane Eranian 245410136f5SStephane Eranian sret = read(fd, scale, sizeof(scale)-1); 246410136f5SStephane Eranian if (sret < 0) 247410136f5SStephane Eranian goto error; 248410136f5SStephane Eranian 2499ecae065SMadhavan Srinivasan if (scale[sret - 1] == '\n') 2509ecae065SMadhavan Srinivasan scale[sret - 1] = '\0'; 2519ecae065SMadhavan Srinivasan else 252410136f5SStephane Eranian scale[sret] = '\0'; 2539ecae065SMadhavan Srinivasan 254a55ab7c4SJin Yao ret = perf_pmu__convert_scale(scale, NULL, &alias->scale); 255410136f5SStephane Eranian error: 256410136f5SStephane Eranian close(fd); 257410136f5SStephane Eranian return ret; 258410136f5SStephane Eranian } 259410136f5SStephane Eranian 260e293a5e8SNamhyung Kim static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, char *name) 261410136f5SStephane Eranian { 262410136f5SStephane Eranian char path[PATH_MAX]; 263410136f5SStephane Eranian ssize_t sret; 264410136f5SStephane Eranian int fd; 265410136f5SStephane Eranian 266e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.unit", name); 267410136f5SStephane Eranian 268e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 269410136f5SStephane Eranian if (fd == -1) 270410136f5SStephane Eranian return -1; 271410136f5SStephane Eranian 272410136f5SStephane Eranian sret = read(fd, alias->unit, UNIT_MAX_LEN); 273410136f5SStephane Eranian if (sret < 0) 274410136f5SStephane Eranian goto error; 275410136f5SStephane Eranian 276410136f5SStephane Eranian close(fd); 277410136f5SStephane Eranian 2789ecae065SMadhavan Srinivasan if (alias->unit[sret - 1] == '\n') 2799ecae065SMadhavan Srinivasan alias->unit[sret - 1] = '\0'; 2809ecae065SMadhavan Srinivasan else 281410136f5SStephane Eranian alias->unit[sret] = '\0'; 282410136f5SStephane Eranian 283410136f5SStephane Eranian return 0; 284410136f5SStephane Eranian error: 285410136f5SStephane Eranian close(fd); 286410136f5SStephane Eranian alias->unit[0] = '\0'; 287410136f5SStephane Eranian return -1; 288410136f5SStephane Eranian } 289410136f5SStephane Eranian 290044330c1SMatt Fleming static int 291e293a5e8SNamhyung Kim perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, char *name) 292044330c1SMatt Fleming { 293044330c1SMatt Fleming char path[PATH_MAX]; 294044330c1SMatt Fleming int fd; 295044330c1SMatt Fleming 296e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.per-pkg", name); 297044330c1SMatt Fleming 298e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 299044330c1SMatt Fleming if (fd == -1) 300044330c1SMatt Fleming return -1; 301044330c1SMatt Fleming 302044330c1SMatt Fleming close(fd); 303044330c1SMatt Fleming 304044330c1SMatt Fleming alias->per_pkg = true; 305044330c1SMatt Fleming return 0; 306044330c1SMatt Fleming } 307044330c1SMatt Fleming 3081d9e446bSJiri Olsa static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, 309e293a5e8SNamhyung Kim int dirfd, char *name) 3101d9e446bSJiri Olsa { 3111d9e446bSJiri Olsa char path[PATH_MAX]; 3121d9e446bSJiri Olsa int fd; 3131d9e446bSJiri Olsa 314e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.snapshot", name); 3151d9e446bSJiri Olsa 316e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 3171d9e446bSJiri Olsa if (fd == -1) 3181d9e446bSJiri Olsa return -1; 3191d9e446bSJiri Olsa 3201d9e446bSJiri Olsa alias->snapshot = true; 3211d9e446bSJiri Olsa close(fd); 3221d9e446bSJiri Olsa return 0; 3231d9e446bSJiri Olsa } 3241d9e446bSJiri Olsa 3256dde6429SThomas Richter static void perf_pmu_assign_str(char *name, const char *field, char **old_str, 3266dde6429SThomas Richter char **new_str) 3276dde6429SThomas Richter { 3286dde6429SThomas Richter if (!*old_str) 3296dde6429SThomas Richter goto set_new; 3306dde6429SThomas Richter 3316dde6429SThomas Richter if (*new_str) { /* Have new string, check with old */ 3326dde6429SThomas Richter if (strcasecmp(*old_str, *new_str)) 3336dde6429SThomas Richter pr_debug("alias %s differs in field '%s'\n", 3346dde6429SThomas Richter name, field); 3356dde6429SThomas Richter zfree(old_str); 3366dde6429SThomas Richter } else /* Nothing new --> keep old string */ 3376dde6429SThomas Richter return; 3386dde6429SThomas Richter set_new: 3396dde6429SThomas Richter *old_str = *new_str; 3406dde6429SThomas Richter *new_str = NULL; 3416dde6429SThomas Richter } 3426dde6429SThomas Richter 3436dde6429SThomas Richter static void perf_pmu_update_alias(struct perf_pmu_alias *old, 3446dde6429SThomas Richter struct perf_pmu_alias *newalias) 3456dde6429SThomas Richter { 3466dde6429SThomas Richter perf_pmu_assign_str(old->name, "desc", &old->desc, &newalias->desc); 3476dde6429SThomas Richter perf_pmu_assign_str(old->name, "long_desc", &old->long_desc, 3486dde6429SThomas Richter &newalias->long_desc); 3496dde6429SThomas Richter perf_pmu_assign_str(old->name, "topic", &old->topic, &newalias->topic); 3506dde6429SThomas Richter perf_pmu_assign_str(old->name, "value", &old->str, &newalias->str); 3516dde6429SThomas Richter old->scale = newalias->scale; 3526dde6429SThomas Richter old->per_pkg = newalias->per_pkg; 3536dde6429SThomas Richter old->snapshot = newalias->snapshot; 3546dde6429SThomas Richter memcpy(old->unit, newalias->unit, sizeof(old->unit)); 3556dde6429SThomas Richter } 3566dde6429SThomas Richter 3576dde6429SThomas Richter /* Delete an alias entry. */ 35822fe5a25SNamhyung Kim void perf_pmu_free_alias(struct perf_pmu_alias *newalias) 3596dde6429SThomas Richter { 3606dde6429SThomas Richter zfree(&newalias->name); 3616dde6429SThomas Richter zfree(&newalias->desc); 3626dde6429SThomas Richter zfree(&newalias->long_desc); 3636dde6429SThomas Richter zfree(&newalias->topic); 3646dde6429SThomas Richter zfree(&newalias->str); 36532705de7SJin Yao zfree(&newalias->pmu_name); 3666dde6429SThomas Richter parse_events_terms__purge(&newalias->terms); 3676dde6429SThomas Richter free(newalias); 3686dde6429SThomas Richter } 3696dde6429SThomas Richter 370eec11310SNamhyung Kim static void perf_pmu__del_aliases(struct perf_pmu *pmu) 371eec11310SNamhyung Kim { 372eec11310SNamhyung Kim struct perf_pmu_alias *alias, *tmp; 373eec11310SNamhyung Kim 374eec11310SNamhyung Kim list_for_each_entry_safe(alias, tmp, &pmu->aliases, list) { 375eec11310SNamhyung Kim list_del(&alias->list); 376eec11310SNamhyung Kim perf_pmu_free_alias(alias); 377eec11310SNamhyung Kim } 378eec11310SNamhyung Kim } 379eec11310SNamhyung Kim 3806dde6429SThomas Richter /* Merge an alias, search in alias list. If this name is already 3816dde6429SThomas Richter * present merge both of them to combine all information. 3826dde6429SThomas Richter */ 3836dde6429SThomas Richter static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias, 3846dde6429SThomas Richter struct list_head *alist) 3856dde6429SThomas Richter { 3866dde6429SThomas Richter struct perf_pmu_alias *a; 3876dde6429SThomas Richter 3886dde6429SThomas Richter list_for_each_entry(a, alist, list) { 3896dde6429SThomas Richter if (!strcasecmp(newalias->name, a->name)) { 39032705de7SJin Yao if (newalias->pmu_name && a->pmu_name && 39132705de7SJin Yao !strcasecmp(newalias->pmu_name, a->pmu_name)) { 39232705de7SJin Yao continue; 39332705de7SJin Yao } 3946dde6429SThomas Richter perf_pmu_update_alias(a, newalias); 3956dde6429SThomas Richter perf_pmu_free_alias(newalias); 3966dde6429SThomas Richter return true; 3976dde6429SThomas Richter } 3986dde6429SThomas Richter } 3996dde6429SThomas Richter return false; 4006dde6429SThomas Richter } 4016dde6429SThomas Richter 402e293a5e8SNamhyung Kim static int __perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, 40347f572aaSIan Rogers char *desc, char *val, const struct pmu_event *pe) 404a6146d50SZheng Yan { 4050c24d6fbSThomas Richter struct parse_events_term *term; 4065c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 407a6146d50SZheng Yan int ret; 4080c24d6fbSThomas Richter char newval[256]; 409330f40a0SIan Rogers const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL; 410bd680861SIan Rogers bool deprecated = false, perpkg = false; 411eab35953SJin Yao 412eab35953SJin Yao if (pe) { 413330f40a0SIan Rogers long_desc = pe->long_desc; 414330f40a0SIan Rogers topic = pe->topic; 415330f40a0SIan Rogers unit = pe->unit; 416bd680861SIan Rogers perpkg = pe->perpkg; 4179ed8b7dcSIan Rogers deprecated = pe->deprecated; 418330f40a0SIan Rogers pmu_name = pe->pmu; 419eab35953SJin Yao } 420a6146d50SZheng Yan 421a6146d50SZheng Yan alias = malloc(sizeof(*alias)); 422a6146d50SZheng Yan if (!alias) 423a6146d50SZheng Yan return -ENOMEM; 424a6146d50SZheng Yan 425a6146d50SZheng Yan INIT_LIST_HEAD(&alias->terms); 426410136f5SStephane Eranian alias->scale = 1.0; 427410136f5SStephane Eranian alias->unit[0] = '\0'; 428bd680861SIan Rogers alias->per_pkg = perpkg; 42984530920SStephane Eranian alias->snapshot = false; 4309ed8b7dcSIan Rogers alias->deprecated = deprecated; 431410136f5SStephane Eranian 43270c646e0SSukadev Bhattiprolu ret = parse_events_terms(&alias->terms, val); 433a6146d50SZheng Yan if (ret) { 43470c646e0SSukadev Bhattiprolu pr_err("Cannot parse alias %s: %d\n", val, ret); 435a6146d50SZheng Yan free(alias); 436a6146d50SZheng Yan return ret; 437a6146d50SZheng Yan } 438a6146d50SZheng Yan 4390c24d6fbSThomas Richter /* Scan event and remove leading zeroes, spaces, newlines, some 4400c24d6fbSThomas Richter * platforms have terms specified as 4410c24d6fbSThomas Richter * event=0x0091 (read from files ../<PMU>/events/<FILE> 4420c24d6fbSThomas Richter * and terms specified as event=0x91 (read from JSON files). 4430c24d6fbSThomas Richter * 4440c24d6fbSThomas Richter * Rebuild string to make alias->str member comparable. 4450c24d6fbSThomas Richter */ 4460c24d6fbSThomas Richter memset(newval, 0, sizeof(newval)); 4470c24d6fbSThomas Richter ret = 0; 4480c24d6fbSThomas Richter list_for_each_entry(term, &alias->terms, list) { 4490c24d6fbSThomas Richter if (ret) 4500c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 4510c24d6fbSThomas Richter ","); 4520c24d6fbSThomas Richter if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 4530c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 4540c24d6fbSThomas Richter "%s=%#x", term->config, term->val.num); 4550c24d6fbSThomas Richter else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 4560c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 4570c24d6fbSThomas Richter "%s=%s", term->config, term->val.str); 4580c24d6fbSThomas Richter } 4590c24d6fbSThomas Richter 460a6146d50SZheng Yan alias->name = strdup(name); 461e293a5e8SNamhyung Kim if (dirfd >= 0) { 462410136f5SStephane Eranian /* 463410136f5SStephane Eranian * load unit name and scale if available 464410136f5SStephane Eranian */ 465e293a5e8SNamhyung Kim perf_pmu__parse_unit(alias, dirfd, name); 466e293a5e8SNamhyung Kim perf_pmu__parse_scale(alias, dirfd, name); 467e293a5e8SNamhyung Kim perf_pmu__parse_per_pkg(alias, dirfd, name); 468e293a5e8SNamhyung Kim perf_pmu__parse_snapshot(alias, dirfd, name); 46970c646e0SSukadev Bhattiprolu } 470410136f5SStephane Eranian 47108e60ed1SAndi Kleen alias->desc = desc ? strdup(desc) : NULL; 472c8d6828aSSukadev Bhattiprolu alias->long_desc = long_desc ? strdup(long_desc) : 473c8d6828aSSukadev Bhattiprolu desc ? strdup(desc) : NULL; 474dd5f1036SAndi Kleen alias->topic = topic ? strdup(topic) : NULL; 475fedb2b51SAndi Kleen if (unit) { 476330f40a0SIan Rogers if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0) 477fedb2b51SAndi Kleen return -1; 478fedb2b51SAndi Kleen snprintf(alias->unit, sizeof(alias->unit), "%s", unit); 479fedb2b51SAndi Kleen } 4800c24d6fbSThomas Richter alias->str = strdup(newval); 48132705de7SJin Yao alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL; 482f2361024SAndi Kleen 4836dde6429SThomas Richter if (!perf_pmu_merge_alias(alias, list)) 484a6146d50SZheng Yan list_add_tail(&alias->list, list); 485410136f5SStephane Eranian 486a6146d50SZheng Yan return 0; 487a6146d50SZheng Yan } 488a6146d50SZheng Yan 489e293a5e8SNamhyung Kim static int perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, FILE *file) 49070c646e0SSukadev Bhattiprolu { 49170c646e0SSukadev Bhattiprolu char buf[256]; 49270c646e0SSukadev Bhattiprolu int ret; 49370c646e0SSukadev Bhattiprolu 49470c646e0SSukadev Bhattiprolu ret = fread(buf, 1, sizeof(buf), file); 49570c646e0SSukadev Bhattiprolu if (ret == 0) 49670c646e0SSukadev Bhattiprolu return -EINVAL; 49770c646e0SSukadev Bhattiprolu 49870c646e0SSukadev Bhattiprolu buf[ret] = 0; 49970c646e0SSukadev Bhattiprolu 500ea23ac73SThomas Richter /* Remove trailing newline from sysfs file */ 50113c230abSArnaldo Carvalho de Melo strim(buf); 502ea23ac73SThomas Richter 503e293a5e8SNamhyung Kim return __perf_pmu__new_alias(list, dirfd, name, NULL, buf, NULL); 50470c646e0SSukadev Bhattiprolu } 50570c646e0SSukadev Bhattiprolu 50646441bdcSMatt Fleming static inline bool pmu_alias_info_file(char *name) 50746441bdcSMatt Fleming { 50846441bdcSMatt Fleming size_t len; 50946441bdcSMatt Fleming 51046441bdcSMatt Fleming len = strlen(name); 51146441bdcSMatt Fleming if (len > 5 && !strcmp(name + len - 5, ".unit")) 51246441bdcSMatt Fleming return true; 51346441bdcSMatt Fleming if (len > 6 && !strcmp(name + len - 6, ".scale")) 51446441bdcSMatt Fleming return true; 515044330c1SMatt Fleming if (len > 8 && !strcmp(name + len - 8, ".per-pkg")) 516044330c1SMatt Fleming return true; 5171d9e446bSJiri Olsa if (len > 9 && !strcmp(name + len - 9, ".snapshot")) 5181d9e446bSJiri Olsa return true; 51946441bdcSMatt Fleming 52046441bdcSMatt Fleming return false; 52146441bdcSMatt Fleming } 52246441bdcSMatt Fleming 523a6146d50SZheng Yan /* 524a6146d50SZheng Yan * Process all the sysfs attributes located under the directory 525a6146d50SZheng Yan * specified in 'dir' parameter. 526a6146d50SZheng Yan */ 527e293a5e8SNamhyung Kim static int pmu_aliases_parse(int dirfd, struct list_head *head) 528a6146d50SZheng Yan { 529a6146d50SZheng Yan struct dirent *evt_ent; 530a6146d50SZheng Yan DIR *event_dir; 531e293a5e8SNamhyung Kim int fd; 532a6146d50SZheng Yan 533e293a5e8SNamhyung Kim event_dir = fdopendir(dirfd); 534a6146d50SZheng Yan if (!event_dir) 535a6146d50SZheng Yan return -EINVAL; 536a6146d50SZheng Yan 537940db6dcSAndi Kleen while ((evt_ent = readdir(event_dir))) { 538a6146d50SZheng Yan char *name = evt_ent->d_name; 539a6146d50SZheng Yan FILE *file; 540a6146d50SZheng Yan 541a6146d50SZheng Yan if (!strcmp(name, ".") || !strcmp(name, "..")) 542a6146d50SZheng Yan continue; 543a6146d50SZheng Yan 544410136f5SStephane Eranian /* 54546441bdcSMatt Fleming * skip info files parsed in perf_pmu__new_alias() 546410136f5SStephane Eranian */ 54746441bdcSMatt Fleming if (pmu_alias_info_file(name)) 548410136f5SStephane Eranian continue; 549410136f5SStephane Eranian 550e293a5e8SNamhyung Kim fd = openat(dirfd, name, O_RDONLY); 5510ea8920eSIan Rogers if (fd == -1) { 5520ea8920eSIan Rogers pr_debug("Cannot open %s\n", name); 5530ea8920eSIan Rogers continue; 5540ea8920eSIan Rogers } 555e293a5e8SNamhyung Kim file = fdopen(fd, "r"); 556940db6dcSAndi Kleen if (!file) { 5570ea8920eSIan Rogers close(fd); 558940db6dcSAndi Kleen continue; 559940db6dcSAndi Kleen } 560410136f5SStephane Eranian 561e293a5e8SNamhyung Kim if (perf_pmu__new_alias(head, dirfd, name, file) < 0) 562940db6dcSAndi Kleen pr_debug("Cannot set up %s\n", name); 563a6146d50SZheng Yan fclose(file); 564a6146d50SZheng Yan } 565a6146d50SZheng Yan 566a6146d50SZheng Yan closedir(event_dir); 567940db6dcSAndi Kleen return 0; 568a6146d50SZheng Yan } 569a6146d50SZheng Yan 570a6146d50SZheng Yan /* 571a6146d50SZheng Yan * Reading the pmu event aliases definition, which should be located at: 572a6146d50SZheng Yan * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 573a6146d50SZheng Yan */ 574838a8c5fSIan Rogers static int pmu_aliases(struct perf_pmu *pmu, int dirfd, const char *name) 575a6146d50SZheng Yan { 576e293a5e8SNamhyung Kim int fd; 577a6146d50SZheng Yan 578e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "events", O_DIRECTORY); 579e293a5e8SNamhyung Kim if (fd < 0) 580d9664582SAndi Kleen return 0; 581a6146d50SZheng Yan 582e293a5e8SNamhyung Kim /* it'll close the fd */ 583838a8c5fSIan Rogers if (pmu_aliases_parse(fd, &pmu->aliases)) 584a6146d50SZheng Yan return -1; 585a6146d50SZheng Yan 586a6146d50SZheng Yan return 0; 587a6146d50SZheng Yan } 588a6146d50SZheng Yan 5895c6ccc37SArnaldo Carvalho de Melo static int pmu_alias_terms(struct perf_pmu_alias *alias, 590a6146d50SZheng Yan struct list_head *terms) 591a6146d50SZheng Yan { 5927c2f8164SJiri Olsa struct parse_events_term *term, *cloned; 593a6146d50SZheng Yan LIST_HEAD(list); 594a6146d50SZheng Yan int ret; 595a6146d50SZheng Yan 596a6146d50SZheng Yan list_for_each_entry(term, &alias->terms, list) { 5977c2f8164SJiri Olsa ret = parse_events_term__clone(&cloned, term); 598a6146d50SZheng Yan if (ret) { 599682dc24cSArnaldo Carvalho de Melo parse_events_terms__purge(&list); 600a6146d50SZheng Yan return ret; 601a6146d50SZheng Yan } 602c2f1ceadSAndi Kleen /* 603c2f1ceadSAndi Kleen * Weak terms don't override command line options, 604c2f1ceadSAndi Kleen * which we don't want for implicit terms in aliases. 605c2f1ceadSAndi Kleen */ 606c2f1ceadSAndi Kleen cloned->weak = true; 6077c2f8164SJiri Olsa list_add_tail(&cloned->list, &list); 608a6146d50SZheng Yan } 609a6146d50SZheng Yan list_splice(&list, terms); 610a6146d50SZheng Yan return 0; 611a6146d50SZheng Yan } 612a6146d50SZheng Yan 61366ec1191SMark Rutland /* 61466ec1191SMark Rutland * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) 61566ec1191SMark Rutland * may have a "cpus" file. 61666ec1191SMark Rutland */ 617d06593aaSIan Rogers static struct perf_cpu_map *pmu_cpumask(int dirfd, const char *name, bool is_core) 6187ae92e74SYan, Zheng { 619f854839bSJiri Olsa struct perf_cpu_map *cpus; 6207e3fcffeSMark Rutland const char *templates[] = { 621d50a79cdSJames Clark "cpumask", 622d50a79cdSJames Clark "cpus", 6237e3fcffeSMark Rutland NULL 6247e3fcffeSMark Rutland }; 6257e3fcffeSMark Rutland const char **template; 626d50a79cdSJames Clark char pmu_name[PATH_MAX]; 627d50a79cdSJames Clark struct perf_pmu pmu = {.name = pmu_name}; 628d50a79cdSJames Clark FILE *file; 6297ae92e74SYan, Zheng 630d50a79cdSJames Clark strlcpy(pmu_name, name, sizeof(pmu_name)); 6317e3fcffeSMark Rutland for (template = templates; *template; template++) { 6323a69672eSNamhyung Kim file = perf_pmu__open_file_at(&pmu, dirfd, *template); 633d50a79cdSJames Clark if (!file) 634d50a79cdSJames Clark continue; 635d50a79cdSJames Clark cpus = perf_cpu_map__read(file); 6363a69672eSNamhyung Kim fclose(file); 63766ec1191SMark Rutland if (cpus) 63866ec1191SMark Rutland return cpus; 6397e3fcffeSMark Rutland } 6407ae92e74SYan, Zheng 641d06593aaSIan Rogers /* Nothing found, for core PMUs assume this means all CPUs. */ 642d06593aaSIan Rogers return is_core ? perf_cpu_map__get(cpu_map__online()) : NULL; 64366ec1191SMark Rutland } 6447ae92e74SYan, Zheng 6453a69672eSNamhyung Kim static bool pmu_is_uncore(int dirfd, const char *name) 64666ec1191SMark Rutland { 6473a69672eSNamhyung Kim int fd; 6487ae92e74SYan, Zheng 6493a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "cpumask", O_PATH); 6503a69672eSNamhyung Kim if (fd < 0) 6513a69672eSNamhyung Kim return false; 6523a69672eSNamhyung Kim 6533a69672eSNamhyung Kim close(fd); 6543a69672eSNamhyung Kim return true; 6557ae92e74SYan, Zheng } 6567ae92e74SYan, Zheng 65751d54847SJohn Garry static char *pmu_id(const char *name) 65851d54847SJohn Garry { 65951d54847SJohn Garry char path[PATH_MAX], *str; 66051d54847SJohn Garry size_t len; 66151d54847SJohn Garry 6625f2c8efaSJames Clark perf_pmu__pathname_scnprintf(path, sizeof(path), name, "identifier"); 66351d54847SJohn Garry 6645f2c8efaSJames Clark if (filename__read_str(path, &str, &len) < 0) 66551d54847SJohn Garry return NULL; 66651d54847SJohn Garry 66751d54847SJohn Garry str[len - 1] = 0; /* remove line feed */ 66851d54847SJohn Garry 66951d54847SJohn Garry return str; 67051d54847SJohn Garry } 67151d54847SJohn Garry 6724bf7e81aSIan Rogers /** 6734bf7e81aSIan Rogers * is_sysfs_pmu_core() - PMU CORE devices have different name other than cpu in 6744bf7e81aSIan Rogers * sysfs on some platforms like ARM or Intel hybrid. Looking for 6754bf7e81aSIan Rogers * possible the cpus file in sysfs files to identify whether this is a 6764bf7e81aSIan Rogers * core device. 6774bf7e81aSIan Rogers * @name: The PMU name such as "cpu_atom". 67814b22ae0SGanapatrao Kulkarni */ 6794bf7e81aSIan Rogers static int is_sysfs_pmu_core(const char *name) 68014b22ae0SGanapatrao Kulkarni { 68114b22ae0SGanapatrao Kulkarni char path[PATH_MAX]; 68214b22ae0SGanapatrao Kulkarni 683f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), name, "cpus")) 68414b22ae0SGanapatrao Kulkarni return 0; 685d9664582SAndi Kleen return file_available(path); 68614b22ae0SGanapatrao Kulkarni } 68714b22ae0SGanapatrao Kulkarni 68829be2fe0SIan Rogers char *perf_pmu__getcpuid(struct perf_pmu *pmu) 689d77ade9fSAndi Kleen { 690d77ade9fSAndi Kleen char *cpuid; 691d77ade9fSAndi Kleen static bool printed; 692d77ade9fSAndi Kleen 693d77ade9fSAndi Kleen cpuid = getenv("PERF_CPUID"); 694d77ade9fSAndi Kleen if (cpuid) 695d77ade9fSAndi Kleen cpuid = strdup(cpuid); 696d77ade9fSAndi Kleen if (!cpuid) 69754e32dc0SGanapatrao Kulkarni cpuid = get_cpuid_str(pmu); 698d77ade9fSAndi Kleen if (!cpuid) 699d77ade9fSAndi Kleen return NULL; 700d77ade9fSAndi Kleen 701d77ade9fSAndi Kleen if (!printed) { 702d77ade9fSAndi Kleen pr_debug("Using CPUID %s\n", cpuid); 703d77ade9fSAndi Kleen printed = true; 704d77ade9fSAndi Kleen } 705d77ade9fSAndi Kleen return cpuid; 706d77ade9fSAndi Kleen } 707d77ade9fSAndi Kleen 7081ba3752aSIan Rogers __weak const struct pmu_events_table *pmu_events_table__find(void) 709e126bef5SJohn Garry { 71096d2a746SIan Rogers return perf_pmu__find_events_table(NULL); 711e126bef5SJohn Garry } 712e126bef5SJohn Garry 713f8ea2c15SIan Rogers __weak const struct pmu_metrics_table *pmu_metrics_table__find(void) 714f8ea2c15SIan Rogers { 715f8ea2c15SIan Rogers return perf_pmu__find_metrics_table(NULL); 716f8ea2c15SIan Rogers } 717f8ea2c15SIan Rogers 718240e6fd0SIan Rogers /** 719240e6fd0SIan Rogers * perf_pmu__match_ignoring_suffix - Does the pmu_name match tok ignoring any 720240e6fd0SIan Rogers * trailing suffix? The Suffix must be in form 721240e6fd0SIan Rogers * tok_{digits}, or tok{digits}. 722240e6fd0SIan Rogers * @pmu_name: The pmu_name with possible suffix. 723240e6fd0SIan Rogers * @tok: The possible match to pmu_name without suffix. 724c07d5c92SJohn Garry */ 725240e6fd0SIan Rogers static bool perf_pmu__match_ignoring_suffix(const char *pmu_name, const char *tok) 726c47a5599SJin Yao { 727c07d5c92SJohn Garry const char *p; 728c47a5599SJin Yao 729c47a5599SJin Yao if (strncmp(pmu_name, tok, strlen(tok))) 730c47a5599SJin Yao return false; 731c47a5599SJin Yao 732c47a5599SJin Yao p = pmu_name + strlen(tok); 733c47a5599SJin Yao if (*p == 0) 734c47a5599SJin Yao return true; 735c47a5599SJin Yao 736c07d5c92SJohn Garry if (*p == '_') 737c47a5599SJin Yao ++p; 738c07d5c92SJohn Garry 739c07d5c92SJohn Garry /* Ensure we end in a number */ 740c07d5c92SJohn Garry while (1) { 741c07d5c92SJohn Garry if (!isdigit(*p)) 742c47a5599SJin Yao return false; 743c07d5c92SJohn Garry if (*(++p) == 0) 744c07d5c92SJohn Garry break; 745c07d5c92SJohn Garry } 746c47a5599SJin Yao 747c47a5599SJin Yao return true; 748c47a5599SJin Yao } 749c47a5599SJin Yao 750240e6fd0SIan Rogers /** 751240e6fd0SIan Rogers * pmu_uncore_alias_match - does name match the PMU name? 752240e6fd0SIan Rogers * @pmu_name: the json struct pmu_event name. This may lack a suffix (which 753240e6fd0SIan Rogers * matches) or be of the form "socket,pmuname" which will match 754240e6fd0SIan Rogers * "socketX_pmunameY". 755240e6fd0SIan Rogers * @name: a real full PMU name as from sysfs. 756240e6fd0SIan Rogers */ 757240e6fd0SIan Rogers static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) 758730670b1SJohn Garry { 759730670b1SJohn Garry char *tmp = NULL, *tok, *str; 760730670b1SJohn Garry bool res; 761730670b1SJohn Garry 762240e6fd0SIan Rogers if (strchr(pmu_name, ',') == NULL) 763240e6fd0SIan Rogers return perf_pmu__match_ignoring_suffix(name, pmu_name); 764240e6fd0SIan Rogers 765730670b1SJohn Garry str = strdup(pmu_name); 766730670b1SJohn Garry if (!str) 767730670b1SJohn Garry return false; 768730670b1SJohn Garry 769730670b1SJohn Garry /* 770730670b1SJohn Garry * uncore alias may be from different PMU with common prefix 771730670b1SJohn Garry */ 772730670b1SJohn Garry tok = strtok_r(str, ",", &tmp); 773730670b1SJohn Garry if (strncmp(pmu_name, tok, strlen(tok))) { 774730670b1SJohn Garry res = false; 775730670b1SJohn Garry goto out; 776730670b1SJohn Garry } 777730670b1SJohn Garry 778730670b1SJohn Garry /* 779730670b1SJohn Garry * Match more complex aliases where the alias name is a comma-delimited 780730670b1SJohn Garry * list of tokens, orderly contained in the matching PMU name. 781730670b1SJohn Garry * 782730670b1SJohn Garry * Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we 783730670b1SJohn Garry * match "socket" in "socketX_pmunameY" and then "pmuname" in 784730670b1SJohn Garry * "pmunameY". 785730670b1SJohn Garry */ 786c07d5c92SJohn Garry while (1) { 787c07d5c92SJohn Garry char *next_tok = strtok_r(NULL, ",", &tmp); 788c07d5c92SJohn Garry 789730670b1SJohn Garry name = strstr(name, tok); 790c07d5c92SJohn Garry if (!name || 791240e6fd0SIan Rogers (!next_tok && !perf_pmu__match_ignoring_suffix(name, tok))) { 792730670b1SJohn Garry res = false; 793730670b1SJohn Garry goto out; 794730670b1SJohn Garry } 795c07d5c92SJohn Garry if (!next_tok) 796c07d5c92SJohn Garry break; 797c07d5c92SJohn Garry tok = next_tok; 798c07d5c92SJohn Garry name += strlen(tok); 799730670b1SJohn Garry } 800730670b1SJohn Garry 801730670b1SJohn Garry res = true; 802730670b1SJohn Garry out: 803730670b1SJohn Garry free(str); 804730670b1SJohn Garry return res; 805730670b1SJohn Garry } 806730670b1SJohn Garry 807660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data { 808d685819bSIan Rogers /* List being added to. */ 809660842e4SIan Rogers struct list_head *head; 810d685819bSIan Rogers /* If a pmu_event lacks a given PMU the default used. */ 811d685819bSIan Rogers char *default_pmu_name; 812d685819bSIan Rogers /* The PMU that we're searching for events for. */ 813660842e4SIan Rogers struct perf_pmu *pmu; 814660842e4SIan Rogers }; 815660842e4SIan Rogers 816660842e4SIan Rogers static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, 8171ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 818660842e4SIan Rogers void *vdata) 819660842e4SIan Rogers { 820660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data *data = vdata; 821d685819bSIan Rogers const char *pname = pe->pmu ?: data->default_pmu_name; 822660842e4SIan Rogers 823d685819bSIan Rogers if (!strcmp(pname, data->pmu->name) || 824d685819bSIan Rogers (data->pmu->is_uncore && pmu_uncore_alias_match(pname, data->pmu->name))) { 825660842e4SIan Rogers /* need type casts to override 'const' */ 826e293a5e8SNamhyung Kim __perf_pmu__new_alias(data->head, -1, (char *)pe->name, (char *)pe->desc, 827660842e4SIan Rogers (char *)pe->event, pe); 828d685819bSIan Rogers } 829660842e4SIan Rogers return 0; 830660842e4SIan Rogers } 831660842e4SIan Rogers 832933f82ffSSukadev Bhattiprolu /* 833d685819bSIan Rogers * From the pmu_events_table, find the events that correspond to the given 834d685819bSIan Rogers * PMU and add them to the list 'head'. 835933f82ffSSukadev Bhattiprolu */ 836838a8c5fSIan Rogers void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table) 837933f82ffSSukadev Bhattiprolu { 838660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data data = { 839838a8c5fSIan Rogers .head = &pmu->aliases, 840d685819bSIan Rogers .default_pmu_name = perf_pmus__default_pmu_name(), 841660842e4SIan Rogers .pmu = pmu, 842660842e4SIan Rogers }; 843fedb2b51SAndi Kleen 844660842e4SIan Rogers pmu_events_table_for_each_event(table, pmu_add_cpu_aliases_map_callback, &data); 845d685819bSIan Rogers free(data.default_pmu_name); 846933f82ffSSukadev Bhattiprolu } 847933f82ffSSukadev Bhattiprolu 848838a8c5fSIan Rogers static void pmu_add_cpu_aliases(struct perf_pmu *pmu) 849e45ad701SJohn Garry { 8501ba3752aSIan Rogers const struct pmu_events_table *table; 851e45ad701SJohn Garry 85296d2a746SIan Rogers table = perf_pmu__find_events_table(pmu); 853eeac7730SIan Rogers if (!table) 854e45ad701SJohn Garry return; 855e45ad701SJohn Garry 856838a8c5fSIan Rogers pmu_add_cpu_aliases_table(pmu, table); 857e45ad701SJohn Garry } 858e45ad701SJohn Garry 8594513c719SJohn Garry struct pmu_sys_event_iter_data { 8604513c719SJohn Garry struct list_head *head; 8614513c719SJohn Garry struct perf_pmu *pmu; 8624513c719SJohn Garry }; 8634513c719SJohn Garry 86429be2fe0SIan Rogers static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, 8651ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 86629be2fe0SIan Rogers void *data) 8674513c719SJohn Garry { 8684513c719SJohn Garry struct pmu_sys_event_iter_data *idata = data; 8694513c719SJohn Garry struct perf_pmu *pmu = idata->pmu; 8704513c719SJohn Garry 8714513c719SJohn Garry if (!pe->compat || !pe->pmu) 8724513c719SJohn Garry return 0; 8734513c719SJohn Garry 8744513c719SJohn Garry if (!strcmp(pmu->id, pe->compat) && 8754513c719SJohn Garry pmu_uncore_alias_match(pe->pmu, pmu->name)) { 876e293a5e8SNamhyung Kim __perf_pmu__new_alias(idata->head, -1, 8774513c719SJohn Garry (char *)pe->name, 8784513c719SJohn Garry (char *)pe->desc, 8794513c719SJohn Garry (char *)pe->event, 880eab35953SJin Yao pe); 8814513c719SJohn Garry } 8824513c719SJohn Garry 8834513c719SJohn Garry return 0; 8844513c719SJohn Garry } 8854513c719SJohn Garry 886838a8c5fSIan Rogers void pmu_add_sys_aliases(struct perf_pmu *pmu) 8874513c719SJohn Garry { 8884513c719SJohn Garry struct pmu_sys_event_iter_data idata = { 889838a8c5fSIan Rogers .head = &pmu->aliases, 8904513c719SJohn Garry .pmu = pmu, 8914513c719SJohn Garry }; 8924513c719SJohn Garry 8934513c719SJohn Garry if (!pmu->id) 8944513c719SJohn Garry return; 8954513c719SJohn Garry 8964513c719SJohn Garry pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, &idata); 8974513c719SJohn Garry } 8984513c719SJohn Garry 899c5de47f2SSukadev Bhattiprolu struct perf_event_attr * __weak 900dc0a6202SAdrian Hunter perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) 901dc0a6202SAdrian Hunter { 902dc0a6202SAdrian Hunter return NULL; 903dc0a6202SAdrian Hunter } 904dc0a6202SAdrian Hunter 90513d60ba0SKan Liang char * __weak 90613d60ba0SKan Liang pmu_find_real_name(const char *name) 90713d60ba0SKan Liang { 90813d60ba0SKan Liang return (char *)name; 90913d60ba0SKan Liang } 91013d60ba0SKan Liang 91113d60ba0SKan Liang char * __weak 91213d60ba0SKan Liang pmu_find_alias_name(const char *name __maybe_unused) 91313d60ba0SKan Liang { 91413d60ba0SKan Liang return NULL; 91513d60ba0SKan Liang } 91613d60ba0SKan Liang 9173a69672eSNamhyung Kim static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) 91890a86bdeSJiri Olsa { 91990a86bdeSJiri Olsa int max_precise = -1; 92090a86bdeSJiri Olsa 9213a69672eSNamhyung Kim perf_pmu__scan_file_at(pmu, dirfd, "caps/max_precise", "%d", &max_precise); 92290a86bdeSJiri Olsa return max_precise; 92390a86bdeSJiri Olsa } 92490a86bdeSJiri Olsa 9251eaf496eSIan Rogers struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name) 926cd82a32eSJiri Olsa { 927cd82a32eSJiri Olsa struct perf_pmu *pmu; 928cd82a32eSJiri Olsa __u32 type; 92913d60ba0SKan Liang char *name = pmu_find_real_name(lookup_name); 93013d60ba0SKan Liang char *alias_name; 93149afa7f6SJin Yao 932cd82a32eSJiri Olsa pmu = zalloc(sizeof(*pmu)); 933cd82a32eSJiri Olsa if (!pmu) 934cd82a32eSJiri Olsa return NULL; 935cd82a32eSJiri Olsa 936838a8c5fSIan Rogers INIT_LIST_HEAD(&pmu->format); 937838a8c5fSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 938838a8c5fSIan Rogers INIT_LIST_HEAD(&pmu->caps); 939838a8c5fSIan Rogers /* 940838a8c5fSIan Rogers * The pmu data we store & need consists of the pmu 941838a8c5fSIan Rogers * type value and format definitions. Load both right 942838a8c5fSIan Rogers * now. 943838a8c5fSIan Rogers */ 944838a8c5fSIan Rogers if (pmu_format(pmu, dirfd, name)) { 945838a8c5fSIan Rogers free(pmu); 946838a8c5fSIan Rogers return NULL; 947838a8c5fSIan Rogers } 948838a8c5fSIan Rogers /* 949838a8c5fSIan Rogers * Check the aliases first to avoid unnecessary work. 950838a8c5fSIan Rogers */ 951838a8c5fSIan Rogers if (pmu_aliases(pmu, dirfd, name)) { 952838a8c5fSIan Rogers free(pmu); 953838a8c5fSIan Rogers return NULL; 954838a8c5fSIan Rogers } 955d06593aaSIan Rogers pmu->is_core = is_pmu_core(name); 956d06593aaSIan Rogers pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core); 95754e32dc0SGanapatrao Kulkarni pmu->name = strdup(name); 95813d60ba0SKan Liang if (!pmu->name) 95913d60ba0SKan Liang goto err; 96013d60ba0SKan Liang 961f8ad6018SJames Clark /* Read type, and ensure that type value is successfully assigned (return 1) */ 9623a69672eSNamhyung Kim if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1) 963f8ad6018SJames Clark goto err; 964f8ad6018SJames Clark 96513d60ba0SKan Liang alias_name = pmu_find_alias_name(name); 96613d60ba0SKan Liang if (alias_name) { 96713d60ba0SKan Liang pmu->alias_name = strdup(alias_name); 96813d60ba0SKan Liang if (!pmu->alias_name) 96913d60ba0SKan Liang goto err; 97013d60ba0SKan Liang } 97113d60ba0SKan Liang 97254e32dc0SGanapatrao Kulkarni pmu->type = type; 9733a69672eSNamhyung Kim pmu->is_uncore = pmu_is_uncore(dirfd, name); 97451d54847SJohn Garry if (pmu->is_uncore) 97551d54847SJohn Garry pmu->id = pmu_id(name); 9763a69672eSNamhyung Kim pmu->max_precise = pmu_max_precise(dirfd, pmu); 977838a8c5fSIan Rogers pmu_add_cpu_aliases(pmu); 978838a8c5fSIan Rogers pmu_add_sys_aliases(pmu); 9791eaf496eSIan Rogers list_add_tail(&pmu->list, pmus); 980dc0a6202SAdrian Hunter 981dc0a6202SAdrian Hunter pmu->default_config = perf_pmu__get_default_config(pmu); 982dc0a6202SAdrian Hunter 983cd82a32eSJiri Olsa return pmu; 98413d60ba0SKan Liang err: 985efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 98613d60ba0SKan Liang free(pmu); 98713d60ba0SKan Liang return NULL; 988cd82a32eSJiri Olsa } 989cd82a32eSJiri Olsa 990628eaa4eSIan Rogers /* Creates the PMU when sysfs scanning fails. */ 991628eaa4eSIan Rogers struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus) 992628eaa4eSIan Rogers { 993628eaa4eSIan Rogers struct perf_pmu *pmu = zalloc(sizeof(*pmu)); 994628eaa4eSIan Rogers 995628eaa4eSIan Rogers if (!pmu) 996628eaa4eSIan Rogers return NULL; 997628eaa4eSIan Rogers 998628eaa4eSIan Rogers pmu->name = strdup("cpu"); 999628eaa4eSIan Rogers if (!pmu->name) { 1000628eaa4eSIan Rogers free(pmu); 1001628eaa4eSIan Rogers return NULL; 1002628eaa4eSIan Rogers } 1003628eaa4eSIan Rogers 1004628eaa4eSIan Rogers pmu->is_core = true; 1005628eaa4eSIan Rogers pmu->type = PERF_TYPE_RAW; 1006628eaa4eSIan Rogers pmu->cpus = cpu_map__online(); 1007628eaa4eSIan Rogers 1008628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->format); 1009628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 1010628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->caps); 1011628eaa4eSIan Rogers list_add_tail(&pmu->list, core_pmus); 1012628eaa4eSIan Rogers return pmu; 1013628eaa4eSIan Rogers } 1014628eaa4eSIan Rogers 1015e552b7beSRob Herring void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu) 1016e552b7beSRob Herring { 1017e552b7beSRob Herring struct perf_pmu_format *format; 1018e552b7beSRob Herring 101968c25043SIan Rogers if (pmu->formats_checked) 102068c25043SIan Rogers return; 102168c25043SIan Rogers 102268c25043SIan Rogers pmu->formats_checked = true; 102368c25043SIan Rogers 1024e552b7beSRob Herring /* fake pmu doesn't have format list */ 1025e552b7beSRob Herring if (pmu == &perf_pmu__fake) 1026e552b7beSRob Herring return; 1027e552b7beSRob Herring 1028*50402641SIan Rogers list_for_each_entry(format, &pmu->format, list) { 1029*50402641SIan Rogers perf_pmu_format__load(pmu, format); 1030e552b7beSRob Herring if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) { 1031e552b7beSRob Herring pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'" 1032e552b7beSRob Herring "which is not supported by this version of perf!\n", 1033e552b7beSRob Herring pmu->name, format->name, format->value); 1034e552b7beSRob Herring return; 1035e552b7beSRob Herring } 1036e552b7beSRob Herring } 1037*50402641SIan Rogers } 1038e552b7beSRob Herring 1039c6d616feSIan Rogers bool evsel__is_aux_event(const struct evsel *evsel) 1040e12ee9f7SAdrian Hunter { 1041e76026bdSArnaldo Carvalho de Melo struct perf_pmu *pmu = evsel__find_pmu(evsel); 1042e12ee9f7SAdrian Hunter 1043e12ee9f7SAdrian Hunter return pmu && pmu->auxtrace; 1044e12ee9f7SAdrian Hunter } 1045e12ee9f7SAdrian Hunter 10466593f019SJames Clark /* 10476593f019SJames Clark * Set @config_name to @val as long as the user hasn't already set or cleared it 10486593f019SJames Clark * by passing a config term on the command line. 10496593f019SJames Clark * 10506593f019SJames Clark * @val is the value to put into the bits specified by @config_name rather than 10516593f019SJames Clark * the bit pattern. It is shifted into position by this function, so to set 10526593f019SJames Clark * something to true, pass 1 for val rather than a pre shifted value. 10536593f019SJames Clark */ 10546593f019SJames Clark #define field_prep(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask)) 10556593f019SJames Clark void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, 10566593f019SJames Clark const char *config_name, u64 val) 10576593f019SJames Clark { 10586593f019SJames Clark u64 user_bits = 0, bits; 10596593f019SJames Clark struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG); 10606593f019SJames Clark 10616593f019SJames Clark if (term) 10626593f019SJames Clark user_bits = term->val.cfg_chg; 10636593f019SJames Clark 1064da6a5afdSIan Rogers bits = perf_pmu__format_bits(pmu, config_name); 10656593f019SJames Clark 10666593f019SJames Clark /* Do nothing if the user changed the value */ 10676593f019SJames Clark if (bits & user_bits) 10686593f019SJames Clark return; 10696593f019SJames Clark 10706593f019SJames Clark /* Otherwise replace it */ 10716593f019SJames Clark evsel->core.attr.config &= ~bits; 10726593f019SJames Clark evsel->core.attr.config |= field_prep(bits, val); 10736593f019SJames Clark } 10746593f019SJames Clark 10755c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_format * 107609ff6071SAdrian Hunter pmu_find_format(struct list_head *formats, const char *name) 1077cd82a32eSJiri Olsa { 10785c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1079cd82a32eSJiri Olsa 1080cd82a32eSJiri Olsa list_for_each_entry(format, formats, list) 1081cd82a32eSJiri Olsa if (!strcmp(format->name, name)) 1082cd82a32eSJiri Olsa return format; 1083cd82a32eSJiri Olsa 1084cd82a32eSJiri Olsa return NULL; 1085cd82a32eSJiri Olsa } 1086cd82a32eSJiri Olsa 1087da6a5afdSIan Rogers __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name) 108809ff6071SAdrian Hunter { 1089da6a5afdSIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 109009ff6071SAdrian Hunter __u64 bits = 0; 109109ff6071SAdrian Hunter int fbit; 109209ff6071SAdrian Hunter 109309ff6071SAdrian Hunter if (!format) 109409ff6071SAdrian Hunter return 0; 109509ff6071SAdrian Hunter 109609ff6071SAdrian Hunter for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS) 109709ff6071SAdrian Hunter bits |= 1ULL << fbit; 109809ff6071SAdrian Hunter 109909ff6071SAdrian Hunter return bits; 110009ff6071SAdrian Hunter } 110109ff6071SAdrian Hunter 11027eb54733SIan Rogers int perf_pmu__format_type(struct perf_pmu *pmu, const char *name) 1103a1ac7de6SAdrian Hunter { 11047eb54733SIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 1105a1ac7de6SAdrian Hunter 1106a1ac7de6SAdrian Hunter if (!format) 1107a1ac7de6SAdrian Hunter return -1; 1108a1ac7de6SAdrian Hunter 1109*50402641SIan Rogers perf_pmu_format__load(pmu, format); 1110a1ac7de6SAdrian Hunter return format->value; 1111a1ac7de6SAdrian Hunter } 1112a1ac7de6SAdrian Hunter 1113cd82a32eSJiri Olsa /* 1114dc0a6202SAdrian Hunter * Sets value based on the format definition (format parameter) 11154d39c89fSIngo Molnar * and unformatted value (value parameter). 1116cd82a32eSJiri Olsa */ 1117dc0a6202SAdrian Hunter static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, 1118dc0a6202SAdrian Hunter bool zero) 1119cd82a32eSJiri Olsa { 1120cd82a32eSJiri Olsa unsigned long fbit, vbit; 1121cd82a32eSJiri Olsa 1122cd82a32eSJiri Olsa for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 1123cd82a32eSJiri Olsa 1124cd82a32eSJiri Olsa if (!test_bit(fbit, format)) 1125cd82a32eSJiri Olsa continue; 1126cd82a32eSJiri Olsa 1127dc0a6202SAdrian Hunter if (value & (1llu << vbit++)) 1128dc0a6202SAdrian Hunter *v |= (1llu << fbit); 1129dc0a6202SAdrian Hunter else if (zero) 1130dc0a6202SAdrian Hunter *v &= ~(1llu << fbit); 1131cd82a32eSJiri Olsa } 1132cd82a32eSJiri Olsa } 1133cd82a32eSJiri Olsa 11340efe6b67SAdrian Hunter static __u64 pmu_format_max_value(const unsigned long *format) 11350efe6b67SAdrian Hunter { 11361b9caa10SJiri Olsa int w; 11370efe6b67SAdrian Hunter 11381b9caa10SJiri Olsa w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); 11391b9caa10SJiri Olsa if (!w) 11401b9caa10SJiri Olsa return 0; 11411b9caa10SJiri Olsa if (w < 64) 11421b9caa10SJiri Olsa return (1ULL << w) - 1; 11431b9caa10SJiri Olsa return -1; 11440efe6b67SAdrian Hunter } 11450efe6b67SAdrian Hunter 1146cd82a32eSJiri Olsa /* 1147688d4dfcSCody P Schafer * Term is a string term, and might be a param-term. Try to look up it's value 1148688d4dfcSCody P Schafer * in the remaining terms. 1149688d4dfcSCody P Schafer * - We have a term like "base-or-format-term=param-term", 1150688d4dfcSCody P Schafer * - We need to find the value supplied for "param-term" (with param-term named 1151688d4dfcSCody P Schafer * in a config string) later on in the term list. 1152688d4dfcSCody P Schafer */ 1153688d4dfcSCody P Schafer static int pmu_resolve_param_term(struct parse_events_term *term, 1154688d4dfcSCody P Schafer struct list_head *head_terms, 1155688d4dfcSCody P Schafer __u64 *value) 1156688d4dfcSCody P Schafer { 1157688d4dfcSCody P Schafer struct parse_events_term *t; 1158688d4dfcSCody P Schafer 1159688d4dfcSCody P Schafer list_for_each_entry(t, head_terms, list) { 11602a3d252dSIan Rogers if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM && 11612a3d252dSIan Rogers t->config && !strcmp(t->config, term->config)) { 1162688d4dfcSCody P Schafer t->used = true; 1163688d4dfcSCody P Schafer *value = t->val.num; 1164688d4dfcSCody P Schafer return 0; 1165688d4dfcSCody P Schafer } 1166688d4dfcSCody P Schafer } 1167688d4dfcSCody P Schafer 1168bb963e16SNamhyung Kim if (verbose > 0) 1169688d4dfcSCody P Schafer printf("Required parameter '%s' not specified\n", term->config); 1170688d4dfcSCody P Schafer 1171688d4dfcSCody P Schafer return -1; 1172688d4dfcSCody P Schafer } 1173688d4dfcSCody P Schafer 1174ffeb883eSHe Kuang static char *pmu_formats_string(struct list_head *formats) 1175e64b020bSJiri Olsa { 1176e64b020bSJiri Olsa struct perf_pmu_format *format; 117711db4e29SMasami Hiramatsu char *str = NULL; 117811db4e29SMasami Hiramatsu struct strbuf buf = STRBUF_INIT; 1179f1417ceaSXin Gao unsigned int i = 0; 1180e64b020bSJiri Olsa 1181ffeb883eSHe Kuang if (!formats) 1182e64b020bSJiri Olsa return NULL; 1183e64b020bSJiri Olsa 1184e64b020bSJiri Olsa /* sysfs exported terms */ 1185ffeb883eSHe Kuang list_for_each_entry(format, formats, list) 118611db4e29SMasami Hiramatsu if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0) 118711db4e29SMasami Hiramatsu goto error; 1188e64b020bSJiri Olsa 1189ffeb883eSHe Kuang str = strbuf_detach(&buf, NULL); 119011db4e29SMasami Hiramatsu error: 1191ffeb883eSHe Kuang strbuf_release(&buf); 1192e64b020bSJiri Olsa 1193e64b020bSJiri Olsa return str; 1194e64b020bSJiri Olsa } 1195e64b020bSJiri Olsa 1196688d4dfcSCody P Schafer /* 1197cd82a32eSJiri Olsa * Setup one of config[12] attr members based on the 119888aca8d9SCody P Schafer * user input data - term parameter. 1199cd82a32eSJiri Olsa */ 1200804fee5dSIan Rogers static int pmu_config_term(struct perf_pmu *pmu, 1201cd82a32eSJiri Olsa struct perf_event_attr *attr, 1202dc0a6202SAdrian Hunter struct parse_events_term *term, 1203688d4dfcSCody P Schafer struct list_head *head_terms, 1204e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1205cd82a32eSJiri Olsa { 12065c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1207cd82a32eSJiri Olsa __u64 *vp; 12080efe6b67SAdrian Hunter __u64 val, max_val; 1209cd82a32eSJiri Olsa 1210cd82a32eSJiri Olsa /* 1211688d4dfcSCody P Schafer * If this is a parameter we've already used for parameterized-eval, 1212688d4dfcSCody P Schafer * skip it in normal eval. 1213688d4dfcSCody P Schafer */ 1214688d4dfcSCody P Schafer if (term->used) 1215688d4dfcSCody P Schafer return 0; 1216688d4dfcSCody P Schafer 1217688d4dfcSCody P Schafer /* 1218cd82a32eSJiri Olsa * Hardcoded terms should be already in, so nothing 1219cd82a32eSJiri Olsa * to be done for them. 1220cd82a32eSJiri Olsa */ 1221cd82a32eSJiri Olsa if (parse_events__is_hardcoded_term(term)) 1222cd82a32eSJiri Olsa return 0; 1223cd82a32eSJiri Olsa 1224804fee5dSIan Rogers format = pmu_find_format(&pmu->format, term->config); 1225688d4dfcSCody P Schafer if (!format) { 1226804fee5dSIan Rogers char *pmu_term = pmu_formats_string(&pmu->format); 12274ac22b48SIan Rogers char *unknown_term; 12284ac22b48SIan Rogers char *help_msg; 1229ffeb883eSHe Kuang 12304ac22b48SIan Rogers if (asprintf(&unknown_term, 12314ac22b48SIan Rogers "unknown term '%s' for pmu '%s'", 1232804fee5dSIan Rogers term->config, pmu->name) < 0) 12334ac22b48SIan Rogers unknown_term = NULL; 12344ac22b48SIan Rogers help_msg = parse_events_formats_error_string(pmu_term); 12354ac22b48SIan Rogers if (err) { 12366c191289SIan Rogers parse_events_error__handle(err, term->err_term, 12374ac22b48SIan Rogers unknown_term, 12384ac22b48SIan Rogers help_msg); 12394ac22b48SIan Rogers } else { 12404ac22b48SIan Rogers pr_debug("%s (%s)\n", unknown_term, help_msg); 12414ac22b48SIan Rogers free(unknown_term); 1242e64b020bSJiri Olsa } 12434ac22b48SIan Rogers free(pmu_term); 1244cd82a32eSJiri Olsa return -EINVAL; 1245688d4dfcSCody P Schafer } 1246*50402641SIan Rogers perf_pmu_format__load(pmu, format); 1247cd82a32eSJiri Olsa switch (format->value) { 1248cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG: 1249cd82a32eSJiri Olsa vp = &attr->config; 1250cd82a32eSJiri Olsa break; 1251cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG1: 1252cd82a32eSJiri Olsa vp = &attr->config1; 1253cd82a32eSJiri Olsa break; 1254cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG2: 1255cd82a32eSJiri Olsa vp = &attr->config2; 1256cd82a32eSJiri Olsa break; 1257204e7c49SRob Herring case PERF_PMU_FORMAT_VALUE_CONFIG3: 1258204e7c49SRob Herring vp = &attr->config3; 1259204e7c49SRob Herring break; 1260cd82a32eSJiri Olsa default: 1261cd82a32eSJiri Olsa return -EINVAL; 1262cd82a32eSJiri Olsa } 1263cd82a32eSJiri Olsa 126416fa7e82SJiri Olsa /* 1265688d4dfcSCody P Schafer * Either directly use a numeric term, or try to translate string terms 1266688d4dfcSCody P Schafer * using event parameters. 126716fa7e82SJiri Olsa */ 126899e7138eSJiri Olsa if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 126999e7138eSJiri Olsa if (term->no_value && 127099e7138eSJiri Olsa bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) { 127199e7138eSJiri Olsa if (err) { 12726c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1273448d732cSIan Rogers strdup("no value assigned for term"), 1274448d732cSIan Rogers NULL); 127599e7138eSJiri Olsa } 127699e7138eSJiri Olsa return -EINVAL; 127799e7138eSJiri Olsa } 127899e7138eSJiri Olsa 1279688d4dfcSCody P Schafer val = term->val.num; 128099e7138eSJiri Olsa } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1281688d4dfcSCody P Schafer if (strcmp(term->val.str, "?")) { 1282bb963e16SNamhyung Kim if (verbose > 0) { 1283688d4dfcSCody P Schafer pr_info("Invalid sysfs entry %s=%s\n", 1284688d4dfcSCody P Schafer term->config, term->val.str); 1285e64b020bSJiri Olsa } 1286e64b020bSJiri Olsa if (err) { 12876c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1288448d732cSIan Rogers strdup("expected numeric value"), 1289448d732cSIan Rogers NULL); 1290e64b020bSJiri Olsa } 1291688d4dfcSCody P Schafer return -EINVAL; 1292688d4dfcSCody P Schafer } 1293688d4dfcSCody P Schafer 1294688d4dfcSCody P Schafer if (pmu_resolve_param_term(term, head_terms, &val)) 1295688d4dfcSCody P Schafer return -EINVAL; 1296688d4dfcSCody P Schafer } else 1297688d4dfcSCody P Schafer return -EINVAL; 1298688d4dfcSCody P Schafer 12990efe6b67SAdrian Hunter max_val = pmu_format_max_value(format->bits); 13000efe6b67SAdrian Hunter if (val > max_val) { 13010efe6b67SAdrian Hunter if (err) { 1302448d732cSIan Rogers char *err_str; 1303448d732cSIan Rogers 13046c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1305448d732cSIan Rogers asprintf(&err_str, 13060efe6b67SAdrian Hunter "value too big for format, maximum is %llu", 1307448d732cSIan Rogers (unsigned long long)max_val) < 0 1308448d732cSIan Rogers ? strdup("value too big for format") 1309448d732cSIan Rogers : err_str, 1310448d732cSIan Rogers NULL); 13110efe6b67SAdrian Hunter return -EINVAL; 13120efe6b67SAdrian Hunter } 13130efe6b67SAdrian Hunter /* 13140efe6b67SAdrian Hunter * Assume we don't care if !err, in which case the value will be 13150efe6b67SAdrian Hunter * silently truncated. 13160efe6b67SAdrian Hunter */ 13170efe6b67SAdrian Hunter } 13180efe6b67SAdrian Hunter 1319688d4dfcSCody P Schafer pmu_format_value(format->bits, val, vp, zero); 1320cd82a32eSJiri Olsa return 0; 1321cd82a32eSJiri Olsa } 1322cd82a32eSJiri Olsa 1323804fee5dSIan Rogers int perf_pmu__config_terms(struct perf_pmu *pmu, 1324cff7f956SJiri Olsa struct perf_event_attr *attr, 1325dc0a6202SAdrian Hunter struct list_head *head_terms, 1326e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1327cd82a32eSJiri Olsa { 13286cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 1329cd82a32eSJiri Olsa 1330688d4dfcSCody P Schafer list_for_each_entry(term, head_terms, list) { 1331804fee5dSIan Rogers if (pmu_config_term(pmu, attr, term, head_terms, zero, err)) 1332cd82a32eSJiri Olsa return -EINVAL; 1333688d4dfcSCody P Schafer } 1334cd82a32eSJiri Olsa 1335cd82a32eSJiri Olsa return 0; 1336cd82a32eSJiri Olsa } 1337cd82a32eSJiri Olsa 1338cd82a32eSJiri Olsa /* 1339cd82a32eSJiri Olsa * Configures event's 'attr' parameter based on the: 1340cd82a32eSJiri Olsa * 1) users input - specified in terms parameter 1341cd82a32eSJiri Olsa * 2) pmu format definitions - specified by pmu parameter 1342cd82a32eSJiri Olsa */ 1343cd82a32eSJiri Olsa int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 1344e64b020bSJiri Olsa struct list_head *head_terms, 1345e64b020bSJiri Olsa struct parse_events_error *err) 1346cd82a32eSJiri Olsa { 1347dc0a6202SAdrian Hunter bool zero = !!pmu->default_config; 1348dc0a6202SAdrian Hunter 1349804fee5dSIan Rogers return perf_pmu__config_terms(pmu, attr, head_terms, zero, err); 1350cd82a32eSJiri Olsa } 1351cd82a32eSJiri Olsa 13525c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 13536cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 1354a6146d50SZheng Yan { 13555c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1356a6146d50SZheng Yan char *name; 1357a6146d50SZheng Yan 1358a6146d50SZheng Yan if (parse_events__is_hardcoded_term(term)) 1359a6146d50SZheng Yan return NULL; 1360a6146d50SZheng Yan 1361a6146d50SZheng Yan if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 1362a6146d50SZheng Yan if (term->val.num != 1) 1363a6146d50SZheng Yan return NULL; 1364a6146d50SZheng Yan if (pmu_find_format(&pmu->format, term->config)) 1365a6146d50SZheng Yan return NULL; 1366a6146d50SZheng Yan name = term->config; 1367a6146d50SZheng Yan } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1368a6146d50SZheng Yan if (strcasecmp(term->config, "event")) 1369a6146d50SZheng Yan return NULL; 1370a6146d50SZheng Yan name = term->val.str; 1371a6146d50SZheng Yan } else { 1372a6146d50SZheng Yan return NULL; 1373a6146d50SZheng Yan } 1374a6146d50SZheng Yan 1375a6146d50SZheng Yan list_for_each_entry(alias, &pmu->aliases, list) { 1376a6146d50SZheng Yan if (!strcasecmp(alias->name, name)) 1377a6146d50SZheng Yan return alias; 1378a6146d50SZheng Yan } 1379a6146d50SZheng Yan return NULL; 1380a6146d50SZheng Yan } 1381a6146d50SZheng Yan 1382410136f5SStephane Eranian 13831d9e446bSJiri Olsa static int check_info_data(struct perf_pmu_alias *alias, 13841d9e446bSJiri Olsa struct perf_pmu_info *info) 1385410136f5SStephane Eranian { 1386410136f5SStephane Eranian /* 1387410136f5SStephane Eranian * Only one term in event definition can 13881d9e446bSJiri Olsa * define unit, scale and snapshot, fail 13891d9e446bSJiri Olsa * if there's more than one. 1390410136f5SStephane Eranian */ 1391b30a7d1fSArnaldo Carvalho de Melo if ((info->unit && alias->unit[0]) || 13921d9e446bSJiri Olsa (info->scale && alias->scale) || 13931d9e446bSJiri Olsa (info->snapshot && alias->snapshot)) 1394410136f5SStephane Eranian return -EINVAL; 1395410136f5SStephane Eranian 1396b30a7d1fSArnaldo Carvalho de Melo if (alias->unit[0]) 13971d9e446bSJiri Olsa info->unit = alias->unit; 1398410136f5SStephane Eranian 1399410136f5SStephane Eranian if (alias->scale) 14001d9e446bSJiri Olsa info->scale = alias->scale; 14011d9e446bSJiri Olsa 14021d9e446bSJiri Olsa if (alias->snapshot) 14031d9e446bSJiri Olsa info->snapshot = alias->snapshot; 1404410136f5SStephane Eranian 1405410136f5SStephane Eranian return 0; 1406410136f5SStephane Eranian } 1407410136f5SStephane Eranian 1408a6146d50SZheng Yan /* 1409a6146d50SZheng Yan * Find alias in the terms list and replace it with the terms 1410a6146d50SZheng Yan * defined for the alias 1411a6146d50SZheng Yan */ 1412410136f5SStephane Eranian int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 141346441bdcSMatt Fleming struct perf_pmu_info *info) 1414a6146d50SZheng Yan { 14156cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 14165c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1417a6146d50SZheng Yan int ret; 1418a6146d50SZheng Yan 1419044330c1SMatt Fleming info->per_pkg = false; 1420044330c1SMatt Fleming 14218a398897SStephane Eranian /* 14228a398897SStephane Eranian * Mark unit and scale as not set 14238a398897SStephane Eranian * (different from default values, see below) 14248a398897SStephane Eranian */ 142546441bdcSMatt Fleming info->unit = NULL; 142646441bdcSMatt Fleming info->scale = 0.0; 14271d9e446bSJiri Olsa info->snapshot = false; 1428410136f5SStephane Eranian 1429a6146d50SZheng Yan list_for_each_entry_safe(term, h, head_terms, list) { 1430a6146d50SZheng Yan alias = pmu_find_alias(pmu, term); 1431a6146d50SZheng Yan if (!alias) 1432a6146d50SZheng Yan continue; 1433a6146d50SZheng Yan ret = pmu_alias_terms(alias, &term->list); 1434a6146d50SZheng Yan if (ret) 1435a6146d50SZheng Yan return ret; 1436410136f5SStephane Eranian 14371d9e446bSJiri Olsa ret = check_info_data(alias, info); 1438410136f5SStephane Eranian if (ret) 1439410136f5SStephane Eranian return ret; 1440410136f5SStephane Eranian 1441044330c1SMatt Fleming if (alias->per_pkg) 1442044330c1SMatt Fleming info->per_pkg = true; 1443044330c1SMatt Fleming 1444e56fbc9dSArnaldo Carvalho de Melo list_del_init(&term->list); 14451dc92556SIan Rogers parse_events_term__delete(term); 1446a6146d50SZheng Yan } 14478a398897SStephane Eranian 14488a398897SStephane Eranian /* 14498a398897SStephane Eranian * if no unit or scale found in aliases, then 14508a398897SStephane Eranian * set defaults as for evsel 14518a398897SStephane Eranian * unit cannot left to NULL 14528a398897SStephane Eranian */ 145346441bdcSMatt Fleming if (info->unit == NULL) 145446441bdcSMatt Fleming info->unit = ""; 14558a398897SStephane Eranian 145646441bdcSMatt Fleming if (info->scale == 0.0) 145746441bdcSMatt Fleming info->scale = 1.0; 14588a398897SStephane Eranian 1459a6146d50SZheng Yan return 0; 1460a6146d50SZheng Yan } 1461a6146d50SZheng Yan 1462838a8c5fSIan Rogers struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, const char *event) 1463838a8c5fSIan Rogers { 1464838a8c5fSIan Rogers struct perf_pmu_alias *alias; 1465838a8c5fSIan Rogers 1466838a8c5fSIan Rogers list_for_each_entry(alias, &pmu->aliases, list) 1467838a8c5fSIan Rogers if (!strcmp(event, alias->name)) 1468838a8c5fSIan Rogers return alias; 1469838a8c5fSIan Rogers 1470838a8c5fSIan Rogers return NULL; 1471838a8c5fSIan Rogers } 1472804fee5dSIan Rogers static void perf_pmu__del_formats(struct list_head *formats) 1473d26383dcSNamhyung Kim { 1474d26383dcSNamhyung Kim struct perf_pmu_format *fmt, *tmp; 1475d26383dcSNamhyung Kim 1476d26383dcSNamhyung Kim list_for_each_entry_safe(fmt, tmp, formats, list) { 1477d26383dcSNamhyung Kim list_del(&fmt->list); 1478efe98a7aSArnaldo Carvalho de Melo zfree(&fmt->name); 1479d26383dcSNamhyung Kim free(fmt); 1480d26383dcSNamhyung Kim } 1481d26383dcSNamhyung Kim } 1482d26383dcSNamhyung Kim 148307d2b820SIan Rogers bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name) 148407d2b820SIan Rogers { 148507d2b820SIan Rogers struct perf_pmu_format *format; 148607d2b820SIan Rogers 148707d2b820SIan Rogers list_for_each_entry(format, &pmu->format, list) { 148807d2b820SIan Rogers if (!strcmp(format->name, name)) 148907d2b820SIan Rogers return true; 149007d2b820SIan Rogers } 149107d2b820SIan Rogers return false; 149207d2b820SIan Rogers } 149307d2b820SIan Rogers 1494d504fae9SJohn Garry bool is_pmu_core(const char *name) 1495d504fae9SJohn Garry { 14966fbd67b0SThomas Richter return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name); 14974bf7e81aSIan Rogers } 14984bf7e81aSIan Rogers 14996fd1e519SIan Rogers bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu) 15006fd1e519SIan Rogers { 1501e20d1f2fSIan Rogers return pmu->is_core; 15026fd1e519SIan Rogers } 15036fd1e519SIan Rogers 150452c7b4d3SIan Rogers bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) 150552c7b4d3SIan Rogers { 1506710dffc9SIan Rogers return !pmu->is_core || perf_pmus__num_core_pmus() == 1; 150752c7b4d3SIan Rogers } 150852c7b4d3SIan Rogers 15091eaf496eSIan Rogers bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name) 1510abe9544eSIan Rogers { 15114cabc3d1SAndi Kleen struct perf_pmu_alias *alias; 15124cabc3d1SAndi Kleen 15131eaf496eSIan Rogers list_for_each_entry(alias, &pmu->aliases, list) { 15144cabc3d1SAndi Kleen if (!strcmp(alias->name, name)) 15154cabc3d1SAndi Kleen return true; 15164cabc3d1SAndi Kleen } 15174cabc3d1SAndi Kleen return false; 15184cabc3d1SAndi Kleen } 15197d4bdab5SAdrian Hunter 1520251aa040SIan Rogers bool perf_pmu__is_software(const struct perf_pmu *pmu) 1521251aa040SIan Rogers { 1522251aa040SIan Rogers if (pmu->is_core || pmu->is_uncore || pmu->auxtrace) 1523251aa040SIan Rogers return false; 1524251aa040SIan Rogers switch (pmu->type) { 1525251aa040SIan Rogers case PERF_TYPE_HARDWARE: return false; 1526251aa040SIan Rogers case PERF_TYPE_SOFTWARE: return true; 1527251aa040SIan Rogers case PERF_TYPE_TRACEPOINT: return true; 1528251aa040SIan Rogers case PERF_TYPE_HW_CACHE: return false; 1529251aa040SIan Rogers case PERF_TYPE_RAW: return false; 1530251aa040SIan Rogers case PERF_TYPE_BREAKPOINT: return true; 1531251aa040SIan Rogers default: break; 1532251aa040SIan Rogers } 1533251aa040SIan Rogers return !strcmp(pmu->name, "kprobe") || !strcmp(pmu->name, "uprobe"); 1534251aa040SIan Rogers } 1535251aa040SIan Rogers 1536d50a79cdSJames Clark FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) 15377d4bdab5SAdrian Hunter { 15387d4bdab5SAdrian Hunter char path[PATH_MAX]; 15397d4bdab5SAdrian Hunter 1540f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name) || 1541f8ad6018SJames Clark !file_available(path)) 15427d4bdab5SAdrian Hunter return NULL; 15437d4bdab5SAdrian Hunter 15447d4bdab5SAdrian Hunter return fopen(path, "r"); 15457d4bdab5SAdrian Hunter } 15467d4bdab5SAdrian Hunter 15473a69672eSNamhyung Kim FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name) 15483a69672eSNamhyung Kim { 15493a69672eSNamhyung Kim int fd; 15503a69672eSNamhyung Kim 15513a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, pmu->name, name, O_RDONLY); 15523a69672eSNamhyung Kim if (fd < 0) 15533a69672eSNamhyung Kim return NULL; 15543a69672eSNamhyung Kim 15553a69672eSNamhyung Kim return fdopen(fd, "r"); 15563a69672eSNamhyung Kim } 15573a69672eSNamhyung Kim 15587d4bdab5SAdrian Hunter int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 15597d4bdab5SAdrian Hunter ...) 15607d4bdab5SAdrian Hunter { 15617d4bdab5SAdrian Hunter va_list args; 15627d4bdab5SAdrian Hunter FILE *file; 15637d4bdab5SAdrian Hunter int ret = EOF; 15647d4bdab5SAdrian Hunter 15657d4bdab5SAdrian Hunter va_start(args, fmt); 15667d4bdab5SAdrian Hunter file = perf_pmu__open_file(pmu, name); 15677d4bdab5SAdrian Hunter if (file) { 15687d4bdab5SAdrian Hunter ret = vfscanf(file, fmt, args); 15697d4bdab5SAdrian Hunter fclose(file); 15707d4bdab5SAdrian Hunter } 15717d4bdab5SAdrian Hunter va_end(args); 15727d4bdab5SAdrian Hunter return ret; 15737d4bdab5SAdrian Hunter } 15749fbc61f8SKan Liang 15753a69672eSNamhyung Kim int perf_pmu__scan_file_at(struct perf_pmu *pmu, int dirfd, const char *name, 15763a69672eSNamhyung Kim const char *fmt, ...) 15773a69672eSNamhyung Kim { 15783a69672eSNamhyung Kim va_list args; 15793a69672eSNamhyung Kim FILE *file; 15803a69672eSNamhyung Kim int ret = EOF; 15813a69672eSNamhyung Kim 15823a69672eSNamhyung Kim va_start(args, fmt); 15833a69672eSNamhyung Kim file = perf_pmu__open_file_at(pmu, dirfd, name); 15843a69672eSNamhyung Kim if (file) { 15853a69672eSNamhyung Kim ret = vfscanf(file, fmt, args); 15863a69672eSNamhyung Kim fclose(file); 15873a69672eSNamhyung Kim } 15883a69672eSNamhyung Kim va_end(args); 15893a69672eSNamhyung Kim return ret; 15903a69672eSNamhyung Kim } 15913a69672eSNamhyung Kim 1592c2b6a896SGerman Gomez bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name) 1593c2b6a896SGerman Gomez { 1594c2b6a896SGerman Gomez char path[PATH_MAX]; 1595c2b6a896SGerman Gomez 1596c2b6a896SGerman Gomez if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name)) 1597c2b6a896SGerman Gomez return false; 1598c2b6a896SGerman Gomez 1599c2b6a896SGerman Gomez return file_available(path); 1600c2b6a896SGerman Gomez } 1601c2b6a896SGerman Gomez 16029fbc61f8SKan Liang static int perf_pmu__new_caps(struct list_head *list, char *name, char *value) 16039fbc61f8SKan Liang { 16049fbc61f8SKan Liang struct perf_pmu_caps *caps = zalloc(sizeof(*caps)); 16059fbc61f8SKan Liang 16069fbc61f8SKan Liang if (!caps) 16079fbc61f8SKan Liang return -ENOMEM; 16089fbc61f8SKan Liang 16099fbc61f8SKan Liang caps->name = strdup(name); 16109fbc61f8SKan Liang if (!caps->name) 16119fbc61f8SKan Liang goto free_caps; 16129fbc61f8SKan Liang caps->value = strndup(value, strlen(value) - 1); 16139fbc61f8SKan Liang if (!caps->value) 16149fbc61f8SKan Liang goto free_name; 16159fbc61f8SKan Liang list_add_tail(&caps->list, list); 16169fbc61f8SKan Liang return 0; 16179fbc61f8SKan Liang 16189fbc61f8SKan Liang free_name: 161957f14b5aSArnaldo Carvalho de Melo zfree(&caps->name); 16209fbc61f8SKan Liang free_caps: 16219fbc61f8SKan Liang free(caps); 16229fbc61f8SKan Liang 16239fbc61f8SKan Liang return -ENOMEM; 16249fbc61f8SKan Liang } 16259fbc61f8SKan Liang 1626eec11310SNamhyung Kim static void perf_pmu__del_caps(struct perf_pmu *pmu) 1627eec11310SNamhyung Kim { 1628eec11310SNamhyung Kim struct perf_pmu_caps *caps, *tmp; 1629eec11310SNamhyung Kim 1630eec11310SNamhyung Kim list_for_each_entry_safe(caps, tmp, &pmu->caps, list) { 1631eec11310SNamhyung Kim list_del(&caps->list); 1632efe98a7aSArnaldo Carvalho de Melo zfree(&caps->name); 1633efe98a7aSArnaldo Carvalho de Melo zfree(&caps->value); 1634eec11310SNamhyung Kim free(caps); 1635eec11310SNamhyung Kim } 1636eec11310SNamhyung Kim } 1637eec11310SNamhyung Kim 16389fbc61f8SKan Liang /* 16399fbc61f8SKan Liang * Reading/parsing the given pmu capabilities, which should be located at: 16409fbc61f8SKan Liang * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes. 16419fbc61f8SKan Liang * Return the number of capabilities 16429fbc61f8SKan Liang */ 16439fbc61f8SKan Liang int perf_pmu__caps_parse(struct perf_pmu *pmu) 16449fbc61f8SKan Liang { 16459fbc61f8SKan Liang struct stat st; 16469fbc61f8SKan Liang char caps_path[PATH_MAX]; 16479fbc61f8SKan Liang DIR *caps_dir; 16489fbc61f8SKan Liang struct dirent *evt_ent; 1649b39094d3SNamhyung Kim int caps_fd; 16503339ec44SRavi Bangoria 16513339ec44SRavi Bangoria if (pmu->caps_initialized) 16523339ec44SRavi Bangoria return pmu->nr_caps; 16533339ec44SRavi Bangoria 16543339ec44SRavi Bangoria pmu->nr_caps = 0; 16559fbc61f8SKan Liang 1656f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(caps_path, sizeof(caps_path), pmu->name, "caps")) 16579fbc61f8SKan Liang return -1; 16589fbc61f8SKan Liang 16593339ec44SRavi Bangoria if (stat(caps_path, &st) < 0) { 16603339ec44SRavi Bangoria pmu->caps_initialized = true; 16619fbc61f8SKan Liang return 0; /* no error if caps does not exist */ 16623339ec44SRavi Bangoria } 16639fbc61f8SKan Liang 16649fbc61f8SKan Liang caps_dir = opendir(caps_path); 16659fbc61f8SKan Liang if (!caps_dir) 16669fbc61f8SKan Liang return -EINVAL; 16679fbc61f8SKan Liang 1668b39094d3SNamhyung Kim caps_fd = dirfd(caps_dir); 1669b39094d3SNamhyung Kim 16709fbc61f8SKan Liang while ((evt_ent = readdir(caps_dir)) != NULL) { 16719fbc61f8SKan Liang char *name = evt_ent->d_name; 16729fbc61f8SKan Liang char value[128]; 16739fbc61f8SKan Liang FILE *file; 1674b39094d3SNamhyung Kim int fd; 16759fbc61f8SKan Liang 16769fbc61f8SKan Liang if (!strcmp(name, ".") || !strcmp(name, "..")) 16779fbc61f8SKan Liang continue; 16789fbc61f8SKan Liang 1679b39094d3SNamhyung Kim fd = openat(caps_fd, name, O_RDONLY); 16800ea8920eSIan Rogers if (fd == -1) 16819fbc61f8SKan Liang continue; 16820ea8920eSIan Rogers file = fdopen(fd, "r"); 16830ea8920eSIan Rogers if (!file) { 16840ea8920eSIan Rogers close(fd); 16850ea8920eSIan Rogers continue; 16860ea8920eSIan Rogers } 16879fbc61f8SKan Liang 16889fbc61f8SKan Liang if (!fgets(value, sizeof(value), file) || 16899fbc61f8SKan Liang (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) { 16909fbc61f8SKan Liang fclose(file); 16919fbc61f8SKan Liang continue; 16929fbc61f8SKan Liang } 16939fbc61f8SKan Liang 16943339ec44SRavi Bangoria pmu->nr_caps++; 16959fbc61f8SKan Liang fclose(file); 16969fbc61f8SKan Liang } 16979fbc61f8SKan Liang 16989fbc61f8SKan Liang closedir(caps_dir); 16999fbc61f8SKan Liang 17003339ec44SRavi Bangoria pmu->caps_initialized = true; 17013339ec44SRavi Bangoria return pmu->nr_caps; 17029fbc61f8SKan Liang } 1703e4064776SJin Yao 1704b9f01032SIan Rogers static void perf_pmu__compute_config_masks(struct perf_pmu *pmu) 1705e4064776SJin Yao { 1706e4064776SJin Yao struct perf_pmu_format *format; 1707b9f01032SIan Rogers 1708b9f01032SIan Rogers if (pmu->config_masks_computed) 1709b9f01032SIan Rogers return; 1710e4064776SJin Yao 1711e4064776SJin Yao list_for_each_entry(format, &pmu->format, list) { 1712b9f01032SIan Rogers unsigned int i; 1713b9f01032SIan Rogers __u64 *mask; 1714b9f01032SIan Rogers 1715b9f01032SIan Rogers if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) 1716e4064776SJin Yao continue; 1717e4064776SJin Yao 1718b9f01032SIan Rogers pmu->config_masks_present = true; 1719b9f01032SIan Rogers mask = &pmu->config_masks[format->value]; 1720b9f01032SIan Rogers 1721e4064776SJin Yao for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS) 1722b9f01032SIan Rogers *mask |= 1ULL << i; 1723e4064776SJin Yao } 1724b9f01032SIan Rogers pmu->config_masks_computed = true; 1725b9f01032SIan Rogers } 1726b9f01032SIan Rogers 1727b9f01032SIan Rogers void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 1728b9f01032SIan Rogers const char *name, int config_num, 1729b9f01032SIan Rogers const char *config_name) 1730b9f01032SIan Rogers { 1731b9f01032SIan Rogers __u64 bits; 1732b9f01032SIan Rogers char buf[100]; 1733b9f01032SIan Rogers 1734b9f01032SIan Rogers perf_pmu__compute_config_masks(pmu); 1735e4064776SJin Yao 1736e4064776SJin Yao /* 1737e4064776SJin Yao * Kernel doesn't export any valid format bits. 1738e4064776SJin Yao */ 1739b9f01032SIan Rogers if (!pmu->config_masks_present) 1740e4064776SJin Yao return; 1741e4064776SJin Yao 1742b9f01032SIan Rogers bits = config & ~pmu->config_masks[config_num]; 1743e4064776SJin Yao if (bits == 0) 1744e4064776SJin Yao return; 1745e4064776SJin Yao 1746e4064776SJin Yao bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf)); 1747e4064776SJin Yao 1748b9f01032SIan Rogers pr_warning("WARNING: event '%s' not valid (bits %s of %s " 1749e4064776SJin Yao "'%llx' not supported by kernel)!\n", 1750b9f01032SIan Rogers name ?: "N/A", buf, config_name, config); 1751e4064776SJin Yao } 1752c5a26ea4SJin Yao 1753c47a5599SJin Yao int perf_pmu__match(char *pattern, char *name, char *tok) 1754c47a5599SJin Yao { 175513d60ba0SKan Liang if (!name) 175613d60ba0SKan Liang return -1; 175713d60ba0SKan Liang 1758c47a5599SJin Yao if (fnmatch(pattern, name, 0)) 1759c47a5599SJin Yao return -1; 1760c47a5599SJin Yao 1761240e6fd0SIan Rogers if (tok && !perf_pmu__match_ignoring_suffix(name, tok)) 1762c47a5599SJin Yao return -1; 1763c47a5599SJin Yao 1764c47a5599SJin Yao return 0; 1765c47a5599SJin Yao } 17661d3351e6SJin Yao 1767acef233bSJing Zhang double __weak perf_pmu__cpu_slots_per_cycle(void) 1768acef233bSJing Zhang { 1769acef233bSJing Zhang return NAN; 1770acef233bSJing Zhang } 1771f8ad6018SJames Clark 1772f8ad6018SJames Clark int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size) 1773f8ad6018SJames Clark { 1774f8ad6018SJames Clark const char *sysfs = sysfs__mountpoint(); 1775f8ad6018SJames Clark 1776f8ad6018SJames Clark if (!sysfs) 1777f8ad6018SJames Clark return 0; 1778f8ad6018SJames Clark return scnprintf(pathname, size, "%s/bus/event_source/devices/", sysfs); 1779f8ad6018SJames Clark } 1780f8ad6018SJames Clark 1781e293a5e8SNamhyung Kim int perf_pmu__event_source_devices_fd(void) 1782e293a5e8SNamhyung Kim { 1783e293a5e8SNamhyung Kim char path[PATH_MAX]; 1784e293a5e8SNamhyung Kim const char *sysfs = sysfs__mountpoint(); 1785e293a5e8SNamhyung Kim 1786e293a5e8SNamhyung Kim if (!sysfs) 1787e293a5e8SNamhyung Kim return -1; 1788e293a5e8SNamhyung Kim 1789e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs); 1790e293a5e8SNamhyung Kim return open(path, O_DIRECTORY); 1791e293a5e8SNamhyung Kim } 1792e293a5e8SNamhyung Kim 1793f8ad6018SJames Clark /* 1794f8ad6018SJames Clark * Fill 'buf' with the path to a file or folder in 'pmu_name' in 1795f8ad6018SJames Clark * sysfs. For example if pmu_name = "cs_etm" and 'filename' = "format" 1796f8ad6018SJames Clark * then pathname will be filled with 1797f8ad6018SJames Clark * "/sys/bus/event_source/devices/cs_etm/format" 1798f8ad6018SJames Clark * 1799e1a3aad3SIan Rogers * Return 0 if the sysfs mountpoint couldn't be found, if no characters were 1800e1a3aad3SIan Rogers * written or if the buffer size is exceeded. 1801f8ad6018SJames Clark */ 1802f8ad6018SJames Clark int perf_pmu__pathname_scnprintf(char *buf, size_t size, 1803f8ad6018SJames Clark const char *pmu_name, const char *filename) 1804f8ad6018SJames Clark { 1805e1a3aad3SIan Rogers size_t len; 1806f8ad6018SJames Clark 1807e1a3aad3SIan Rogers len = perf_pmu__event_source_devices_scnprintf(buf, size); 1808e1a3aad3SIan Rogers if (!len || (len + strlen(pmu_name) + strlen(filename) + 1) >= size) 1809f8ad6018SJames Clark return 0; 1810e1a3aad3SIan Rogers 1811e1a3aad3SIan Rogers return scnprintf(buf + len, size - len, "%s/%s", pmu_name, filename); 1812f8ad6018SJames Clark } 1813eec11310SNamhyung Kim 1814e293a5e8SNamhyung Kim int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags) 1815e293a5e8SNamhyung Kim { 1816e293a5e8SNamhyung Kim char path[PATH_MAX]; 1817e293a5e8SNamhyung Kim 1818e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/%s", pmu_name, filename); 1819e293a5e8SNamhyung Kim return openat(dirfd, path, flags); 1820e293a5e8SNamhyung Kim } 1821e293a5e8SNamhyung Kim 18221eaf496eSIan Rogers void perf_pmu__delete(struct perf_pmu *pmu) 1823eec11310SNamhyung Kim { 1824eec11310SNamhyung Kim perf_pmu__del_formats(&pmu->format); 1825eec11310SNamhyung Kim perf_pmu__del_aliases(pmu); 1826eec11310SNamhyung Kim perf_pmu__del_caps(pmu); 1827eec11310SNamhyung Kim 1828eec11310SNamhyung Kim perf_cpu_map__put(pmu->cpus); 1829eec11310SNamhyung Kim 1830efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->default_config); 1831efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 1832efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->alias_name); 1833eec11310SNamhyung Kim free(pmu); 1834eec11310SNamhyung Kim } 18359d5da30eSJames Clark 18369d5da30eSJames Clark struct perf_pmu *pmu__find_core_pmu(void) 18379d5da30eSJames Clark { 18389d5da30eSJames Clark struct perf_pmu *pmu = NULL; 18399d5da30eSJames Clark 18409d5da30eSJames Clark while ((pmu = perf_pmus__scan_core(pmu))) { 18419d5da30eSJames Clark /* 18429d5da30eSJames Clark * The cpumap should cover all CPUs. Otherwise, some CPUs may 18439d5da30eSJames Clark * not support some events or have different event IDs. 18449d5da30eSJames Clark */ 18459d5da30eSJames Clark if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu) 18469d5da30eSJames Clark return NULL; 18479d5da30eSJames Clark 18489d5da30eSJames Clark return pmu; 18499d5da30eSJames Clark } 18509d5da30eSJames Clark return NULL; 18519d5da30eSJames Clark } 1852