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 { 43fe13d43dSIan Rogers /** @name: The modifier/file name. */ 44ab1bf653SArnaldo Carvalho de Melo char *name; 45fe13d43dSIan Rogers /** 46fe13d43dSIan Rogers * @value : Which config value the format relates to. Supported values 47fe13d43dSIan Rogers * are from PERF_PMU_FORMAT_VALUE_CONFIG to 48fe13d43dSIan Rogers * PERF_PMU_FORMAT_VALUE_CONFIG_END. 49fe13d43dSIan Rogers */ 50ab1bf653SArnaldo Carvalho de Melo int value; 51fe13d43dSIan Rogers /** @bits: Which config bits are set by this format value. */ 52ab1bf653SArnaldo Carvalho de Melo DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); 53fe13d43dSIan Rogers /** @list: Element on list within struct perf_pmu. */ 54ab1bf653SArnaldo Carvalho de Melo struct list_head list; 55ab1bf653SArnaldo Carvalho de Melo }; 56ab1bf653SArnaldo Carvalho de Melo 57cd82a32eSJiri Olsa /* 58cd82a32eSJiri Olsa * Parse & process all the sysfs attributes located under 59cd82a32eSJiri Olsa * the directory specified in 'dir' parameter. 60cd82a32eSJiri Olsa */ 61*838a8c5fSIan Rogers int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd) 62cd82a32eSJiri Olsa { 63cd82a32eSJiri Olsa struct dirent *evt_ent; 64cd82a32eSJiri Olsa DIR *format_dir; 65cd82a32eSJiri Olsa int ret = 0; 66cd82a32eSJiri Olsa 67e293a5e8SNamhyung Kim format_dir = fdopendir(dirfd); 68cd82a32eSJiri Olsa if (!format_dir) 69cd82a32eSJiri Olsa return -EINVAL; 70cd82a32eSJiri Olsa 71cd82a32eSJiri Olsa while (!ret && (evt_ent = readdir(format_dir))) { 72cd82a32eSJiri Olsa char *name = evt_ent->d_name; 73e293a5e8SNamhyung Kim int fd; 743d88aec0SIan Rogers void *scanner; 753d88aec0SIan Rogers FILE *file; 76cd82a32eSJiri Olsa 77cd82a32eSJiri Olsa if (!strcmp(name, ".") || !strcmp(name, "..")) 78cd82a32eSJiri Olsa continue; 79cd82a32eSJiri Olsa 80cd82a32eSJiri Olsa 81cd82a32eSJiri Olsa ret = -EINVAL; 82e293a5e8SNamhyung Kim fd = openat(dirfd, name, O_RDONLY); 83e293a5e8SNamhyung Kim if (fd < 0) 84cd82a32eSJiri Olsa break; 85cd82a32eSJiri Olsa 863d88aec0SIan Rogers file = fdopen(fd, "r"); 873d88aec0SIan Rogers if (!file) { 883d88aec0SIan Rogers close(fd); 893d88aec0SIan Rogers break; 903d88aec0SIan Rogers } 913d88aec0SIan Rogers 923d88aec0SIan Rogers ret = perf_pmu_lex_init(&scanner); 933d88aec0SIan Rogers if (ret) { 943d88aec0SIan Rogers fclose(file); 953d88aec0SIan Rogers break; 963d88aec0SIan Rogers } 973d88aec0SIan Rogers 983d88aec0SIan Rogers perf_pmu_set_in(file, scanner); 99*838a8c5fSIan Rogers ret = perf_pmu_parse(&pmu->format, name, scanner); 1003d88aec0SIan Rogers perf_pmu_lex_destroy(scanner); 1013d88aec0SIan Rogers fclose(file); 102cd82a32eSJiri Olsa } 103cd82a32eSJiri Olsa 104cd82a32eSJiri Olsa closedir(format_dir); 105cd82a32eSJiri Olsa return ret; 106cd82a32eSJiri Olsa } 107cd82a32eSJiri Olsa 108cd82a32eSJiri Olsa /* 109cd82a32eSJiri Olsa * Reading/parsing the default pmu format definition, which should be 110cd82a32eSJiri Olsa * located at: 111cd82a32eSJiri Olsa * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. 112cd82a32eSJiri Olsa */ 113*838a8c5fSIan Rogers static int pmu_format(struct perf_pmu *pmu, int dirfd, const char *name) 114cd82a32eSJiri Olsa { 115e293a5e8SNamhyung Kim int fd; 116cd82a32eSJiri Olsa 117e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "format", O_DIRECTORY); 118e293a5e8SNamhyung Kim if (fd < 0) 119d9664582SAndi Kleen return 0; 120cd82a32eSJiri Olsa 121e293a5e8SNamhyung Kim /* it'll close the fd */ 122*838a8c5fSIan Rogers if (perf_pmu__format_parse(pmu, fd)) 123cd82a32eSJiri Olsa return -1; 124cd82a32eSJiri Olsa 125cd82a32eSJiri Olsa return 0; 126cd82a32eSJiri Olsa } 127cd82a32eSJiri Olsa 128a55ab7c4SJin Yao int perf_pmu__convert_scale(const char *scale, char **end, double *sval) 129d02fc6bcSAndi Kleen { 130d02fc6bcSAndi Kleen char *lc; 131d02fc6bcSAndi Kleen int ret = 0; 132d02fc6bcSAndi Kleen 133d02fc6bcSAndi Kleen /* 134d02fc6bcSAndi Kleen * save current locale 135d02fc6bcSAndi Kleen */ 136d02fc6bcSAndi Kleen lc = setlocale(LC_NUMERIC, NULL); 137d02fc6bcSAndi Kleen 138d02fc6bcSAndi Kleen /* 139d02fc6bcSAndi Kleen * The lc string may be allocated in static storage, 140d02fc6bcSAndi Kleen * so get a dynamic copy to make it survive setlocale 141d02fc6bcSAndi Kleen * call below. 142d02fc6bcSAndi Kleen */ 143d02fc6bcSAndi Kleen lc = strdup(lc); 144d02fc6bcSAndi Kleen if (!lc) { 145d02fc6bcSAndi Kleen ret = -ENOMEM; 146d02fc6bcSAndi Kleen goto out; 147d02fc6bcSAndi Kleen } 148d02fc6bcSAndi Kleen 149d02fc6bcSAndi Kleen /* 150d02fc6bcSAndi Kleen * force to C locale to ensure kernel 151d02fc6bcSAndi Kleen * scale string is converted correctly. 152d02fc6bcSAndi Kleen * kernel uses default C locale. 153d02fc6bcSAndi Kleen */ 154d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, "C"); 155d02fc6bcSAndi Kleen 156d02fc6bcSAndi Kleen *sval = strtod(scale, end); 157d02fc6bcSAndi Kleen 158d02fc6bcSAndi Kleen out: 159d02fc6bcSAndi Kleen /* restore locale */ 160d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, lc); 161d02fc6bcSAndi Kleen free(lc); 162d02fc6bcSAndi Kleen return ret; 163d02fc6bcSAndi Kleen } 164d02fc6bcSAndi Kleen 165e293a5e8SNamhyung Kim static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, char *name) 166410136f5SStephane Eranian { 167410136f5SStephane Eranian struct stat st; 168410136f5SStephane Eranian ssize_t sret; 169410136f5SStephane Eranian char scale[128]; 170410136f5SStephane Eranian int fd, ret = -1; 171410136f5SStephane Eranian char path[PATH_MAX]; 172410136f5SStephane Eranian 173e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.scale", name); 174410136f5SStephane Eranian 175e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 176410136f5SStephane Eranian if (fd == -1) 177410136f5SStephane Eranian return -1; 178410136f5SStephane Eranian 179410136f5SStephane Eranian if (fstat(fd, &st) < 0) 180410136f5SStephane Eranian goto error; 181410136f5SStephane Eranian 182410136f5SStephane Eranian sret = read(fd, scale, sizeof(scale)-1); 183410136f5SStephane Eranian if (sret < 0) 184410136f5SStephane Eranian goto error; 185410136f5SStephane Eranian 1869ecae065SMadhavan Srinivasan if (scale[sret - 1] == '\n') 1879ecae065SMadhavan Srinivasan scale[sret - 1] = '\0'; 1889ecae065SMadhavan Srinivasan else 189410136f5SStephane Eranian scale[sret] = '\0'; 1909ecae065SMadhavan Srinivasan 191a55ab7c4SJin Yao ret = perf_pmu__convert_scale(scale, NULL, &alias->scale); 192410136f5SStephane Eranian error: 193410136f5SStephane Eranian close(fd); 194410136f5SStephane Eranian return ret; 195410136f5SStephane Eranian } 196410136f5SStephane Eranian 197e293a5e8SNamhyung Kim static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, char *name) 198410136f5SStephane Eranian { 199410136f5SStephane Eranian char path[PATH_MAX]; 200410136f5SStephane Eranian ssize_t sret; 201410136f5SStephane Eranian int fd; 202410136f5SStephane Eranian 203e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.unit", name); 204410136f5SStephane Eranian 205e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 206410136f5SStephane Eranian if (fd == -1) 207410136f5SStephane Eranian return -1; 208410136f5SStephane Eranian 209410136f5SStephane Eranian sret = read(fd, alias->unit, UNIT_MAX_LEN); 210410136f5SStephane Eranian if (sret < 0) 211410136f5SStephane Eranian goto error; 212410136f5SStephane Eranian 213410136f5SStephane Eranian close(fd); 214410136f5SStephane Eranian 2159ecae065SMadhavan Srinivasan if (alias->unit[sret - 1] == '\n') 2169ecae065SMadhavan Srinivasan alias->unit[sret - 1] = '\0'; 2179ecae065SMadhavan Srinivasan else 218410136f5SStephane Eranian alias->unit[sret] = '\0'; 219410136f5SStephane Eranian 220410136f5SStephane Eranian return 0; 221410136f5SStephane Eranian error: 222410136f5SStephane Eranian close(fd); 223410136f5SStephane Eranian alias->unit[0] = '\0'; 224410136f5SStephane Eranian return -1; 225410136f5SStephane Eranian } 226410136f5SStephane Eranian 227044330c1SMatt Fleming static int 228e293a5e8SNamhyung Kim perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, char *name) 229044330c1SMatt Fleming { 230044330c1SMatt Fleming char path[PATH_MAX]; 231044330c1SMatt Fleming int fd; 232044330c1SMatt Fleming 233e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.per-pkg", name); 234044330c1SMatt Fleming 235e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 236044330c1SMatt Fleming if (fd == -1) 237044330c1SMatt Fleming return -1; 238044330c1SMatt Fleming 239044330c1SMatt Fleming close(fd); 240044330c1SMatt Fleming 241044330c1SMatt Fleming alias->per_pkg = true; 242044330c1SMatt Fleming return 0; 243044330c1SMatt Fleming } 244044330c1SMatt Fleming 2451d9e446bSJiri Olsa static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, 246e293a5e8SNamhyung Kim int dirfd, char *name) 2471d9e446bSJiri Olsa { 2481d9e446bSJiri Olsa char path[PATH_MAX]; 2491d9e446bSJiri Olsa int fd; 2501d9e446bSJiri Olsa 251e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.snapshot", name); 2521d9e446bSJiri Olsa 253e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 2541d9e446bSJiri Olsa if (fd == -1) 2551d9e446bSJiri Olsa return -1; 2561d9e446bSJiri Olsa 2571d9e446bSJiri Olsa alias->snapshot = true; 2581d9e446bSJiri Olsa close(fd); 2591d9e446bSJiri Olsa return 0; 2601d9e446bSJiri Olsa } 2611d9e446bSJiri Olsa 2626dde6429SThomas Richter static void perf_pmu_assign_str(char *name, const char *field, char **old_str, 2636dde6429SThomas Richter char **new_str) 2646dde6429SThomas Richter { 2656dde6429SThomas Richter if (!*old_str) 2666dde6429SThomas Richter goto set_new; 2676dde6429SThomas Richter 2686dde6429SThomas Richter if (*new_str) { /* Have new string, check with old */ 2696dde6429SThomas Richter if (strcasecmp(*old_str, *new_str)) 2706dde6429SThomas Richter pr_debug("alias %s differs in field '%s'\n", 2716dde6429SThomas Richter name, field); 2726dde6429SThomas Richter zfree(old_str); 2736dde6429SThomas Richter } else /* Nothing new --> keep old string */ 2746dde6429SThomas Richter return; 2756dde6429SThomas Richter set_new: 2766dde6429SThomas Richter *old_str = *new_str; 2776dde6429SThomas Richter *new_str = NULL; 2786dde6429SThomas Richter } 2796dde6429SThomas Richter 2806dde6429SThomas Richter static void perf_pmu_update_alias(struct perf_pmu_alias *old, 2816dde6429SThomas Richter struct perf_pmu_alias *newalias) 2826dde6429SThomas Richter { 2836dde6429SThomas Richter perf_pmu_assign_str(old->name, "desc", &old->desc, &newalias->desc); 2846dde6429SThomas Richter perf_pmu_assign_str(old->name, "long_desc", &old->long_desc, 2856dde6429SThomas Richter &newalias->long_desc); 2866dde6429SThomas Richter perf_pmu_assign_str(old->name, "topic", &old->topic, &newalias->topic); 2876dde6429SThomas Richter perf_pmu_assign_str(old->name, "value", &old->str, &newalias->str); 2886dde6429SThomas Richter old->scale = newalias->scale; 2896dde6429SThomas Richter old->per_pkg = newalias->per_pkg; 2906dde6429SThomas Richter old->snapshot = newalias->snapshot; 2916dde6429SThomas Richter memcpy(old->unit, newalias->unit, sizeof(old->unit)); 2926dde6429SThomas Richter } 2936dde6429SThomas Richter 2946dde6429SThomas Richter /* Delete an alias entry. */ 29522fe5a25SNamhyung Kim void perf_pmu_free_alias(struct perf_pmu_alias *newalias) 2966dde6429SThomas Richter { 2976dde6429SThomas Richter zfree(&newalias->name); 2986dde6429SThomas Richter zfree(&newalias->desc); 2996dde6429SThomas Richter zfree(&newalias->long_desc); 3006dde6429SThomas Richter zfree(&newalias->topic); 3016dde6429SThomas Richter zfree(&newalias->str); 30232705de7SJin Yao zfree(&newalias->pmu_name); 3036dde6429SThomas Richter parse_events_terms__purge(&newalias->terms); 3046dde6429SThomas Richter free(newalias); 3056dde6429SThomas Richter } 3066dde6429SThomas Richter 307eec11310SNamhyung Kim static void perf_pmu__del_aliases(struct perf_pmu *pmu) 308eec11310SNamhyung Kim { 309eec11310SNamhyung Kim struct perf_pmu_alias *alias, *tmp; 310eec11310SNamhyung Kim 311eec11310SNamhyung Kim list_for_each_entry_safe(alias, tmp, &pmu->aliases, list) { 312eec11310SNamhyung Kim list_del(&alias->list); 313eec11310SNamhyung Kim perf_pmu_free_alias(alias); 314eec11310SNamhyung Kim } 315eec11310SNamhyung Kim } 316eec11310SNamhyung Kim 3176dde6429SThomas Richter /* Merge an alias, search in alias list. If this name is already 3186dde6429SThomas Richter * present merge both of them to combine all information. 3196dde6429SThomas Richter */ 3206dde6429SThomas Richter static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias, 3216dde6429SThomas Richter struct list_head *alist) 3226dde6429SThomas Richter { 3236dde6429SThomas Richter struct perf_pmu_alias *a; 3246dde6429SThomas Richter 3256dde6429SThomas Richter list_for_each_entry(a, alist, list) { 3266dde6429SThomas Richter if (!strcasecmp(newalias->name, a->name)) { 32732705de7SJin Yao if (newalias->pmu_name && a->pmu_name && 32832705de7SJin Yao !strcasecmp(newalias->pmu_name, a->pmu_name)) { 32932705de7SJin Yao continue; 33032705de7SJin Yao } 3316dde6429SThomas Richter perf_pmu_update_alias(a, newalias); 3326dde6429SThomas Richter perf_pmu_free_alias(newalias); 3336dde6429SThomas Richter return true; 3346dde6429SThomas Richter } 3356dde6429SThomas Richter } 3366dde6429SThomas Richter return false; 3376dde6429SThomas Richter } 3386dde6429SThomas Richter 339e293a5e8SNamhyung Kim static int __perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, 34047f572aaSIan Rogers char *desc, char *val, const struct pmu_event *pe) 341a6146d50SZheng Yan { 3420c24d6fbSThomas Richter struct parse_events_term *term; 3435c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 344a6146d50SZheng Yan int ret; 3450c24d6fbSThomas Richter char newval[256]; 346330f40a0SIan Rogers const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL; 347bd680861SIan Rogers bool deprecated = false, perpkg = false; 348eab35953SJin Yao 349eab35953SJin Yao if (pe) { 350330f40a0SIan Rogers long_desc = pe->long_desc; 351330f40a0SIan Rogers topic = pe->topic; 352330f40a0SIan Rogers unit = pe->unit; 353bd680861SIan Rogers perpkg = pe->perpkg; 3549ed8b7dcSIan Rogers deprecated = pe->deprecated; 355330f40a0SIan Rogers pmu_name = pe->pmu; 356eab35953SJin Yao } 357a6146d50SZheng Yan 358a6146d50SZheng Yan alias = malloc(sizeof(*alias)); 359a6146d50SZheng Yan if (!alias) 360a6146d50SZheng Yan return -ENOMEM; 361a6146d50SZheng Yan 362a6146d50SZheng Yan INIT_LIST_HEAD(&alias->terms); 363410136f5SStephane Eranian alias->scale = 1.0; 364410136f5SStephane Eranian alias->unit[0] = '\0'; 365bd680861SIan Rogers alias->per_pkg = perpkg; 36684530920SStephane Eranian alias->snapshot = false; 3679ed8b7dcSIan Rogers alias->deprecated = deprecated; 368410136f5SStephane Eranian 36970c646e0SSukadev Bhattiprolu ret = parse_events_terms(&alias->terms, val); 370a6146d50SZheng Yan if (ret) { 37170c646e0SSukadev Bhattiprolu pr_err("Cannot parse alias %s: %d\n", val, ret); 372a6146d50SZheng Yan free(alias); 373a6146d50SZheng Yan return ret; 374a6146d50SZheng Yan } 375a6146d50SZheng Yan 3760c24d6fbSThomas Richter /* Scan event and remove leading zeroes, spaces, newlines, some 3770c24d6fbSThomas Richter * platforms have terms specified as 3780c24d6fbSThomas Richter * event=0x0091 (read from files ../<PMU>/events/<FILE> 3790c24d6fbSThomas Richter * and terms specified as event=0x91 (read from JSON files). 3800c24d6fbSThomas Richter * 3810c24d6fbSThomas Richter * Rebuild string to make alias->str member comparable. 3820c24d6fbSThomas Richter */ 3830c24d6fbSThomas Richter memset(newval, 0, sizeof(newval)); 3840c24d6fbSThomas Richter ret = 0; 3850c24d6fbSThomas Richter list_for_each_entry(term, &alias->terms, list) { 3860c24d6fbSThomas Richter if (ret) 3870c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 3880c24d6fbSThomas Richter ","); 3890c24d6fbSThomas Richter if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 3900c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 3910c24d6fbSThomas Richter "%s=%#x", term->config, term->val.num); 3920c24d6fbSThomas Richter else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 3930c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 3940c24d6fbSThomas Richter "%s=%s", term->config, term->val.str); 3950c24d6fbSThomas Richter } 3960c24d6fbSThomas Richter 397a6146d50SZheng Yan alias->name = strdup(name); 398e293a5e8SNamhyung Kim if (dirfd >= 0) { 399410136f5SStephane Eranian /* 400410136f5SStephane Eranian * load unit name and scale if available 401410136f5SStephane Eranian */ 402e293a5e8SNamhyung Kim perf_pmu__parse_unit(alias, dirfd, name); 403e293a5e8SNamhyung Kim perf_pmu__parse_scale(alias, dirfd, name); 404e293a5e8SNamhyung Kim perf_pmu__parse_per_pkg(alias, dirfd, name); 405e293a5e8SNamhyung Kim perf_pmu__parse_snapshot(alias, dirfd, name); 40670c646e0SSukadev Bhattiprolu } 407410136f5SStephane Eranian 40808e60ed1SAndi Kleen alias->desc = desc ? strdup(desc) : NULL; 409c8d6828aSSukadev Bhattiprolu alias->long_desc = long_desc ? strdup(long_desc) : 410c8d6828aSSukadev Bhattiprolu desc ? strdup(desc) : NULL; 411dd5f1036SAndi Kleen alias->topic = topic ? strdup(topic) : NULL; 412fedb2b51SAndi Kleen if (unit) { 413330f40a0SIan Rogers if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0) 414fedb2b51SAndi Kleen return -1; 415fedb2b51SAndi Kleen snprintf(alias->unit, sizeof(alias->unit), "%s", unit); 416fedb2b51SAndi Kleen } 4170c24d6fbSThomas Richter alias->str = strdup(newval); 41832705de7SJin Yao alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL; 419f2361024SAndi Kleen 4206dde6429SThomas Richter if (!perf_pmu_merge_alias(alias, list)) 421a6146d50SZheng Yan list_add_tail(&alias->list, list); 422410136f5SStephane Eranian 423a6146d50SZheng Yan return 0; 424a6146d50SZheng Yan } 425a6146d50SZheng Yan 426e293a5e8SNamhyung Kim static int perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, FILE *file) 42770c646e0SSukadev Bhattiprolu { 42870c646e0SSukadev Bhattiprolu char buf[256]; 42970c646e0SSukadev Bhattiprolu int ret; 43070c646e0SSukadev Bhattiprolu 43170c646e0SSukadev Bhattiprolu ret = fread(buf, 1, sizeof(buf), file); 43270c646e0SSukadev Bhattiprolu if (ret == 0) 43370c646e0SSukadev Bhattiprolu return -EINVAL; 43470c646e0SSukadev Bhattiprolu 43570c646e0SSukadev Bhattiprolu buf[ret] = 0; 43670c646e0SSukadev Bhattiprolu 437ea23ac73SThomas Richter /* Remove trailing newline from sysfs file */ 43813c230abSArnaldo Carvalho de Melo strim(buf); 439ea23ac73SThomas Richter 440e293a5e8SNamhyung Kim return __perf_pmu__new_alias(list, dirfd, name, NULL, buf, NULL); 44170c646e0SSukadev Bhattiprolu } 44270c646e0SSukadev Bhattiprolu 44346441bdcSMatt Fleming static inline bool pmu_alias_info_file(char *name) 44446441bdcSMatt Fleming { 44546441bdcSMatt Fleming size_t len; 44646441bdcSMatt Fleming 44746441bdcSMatt Fleming len = strlen(name); 44846441bdcSMatt Fleming if (len > 5 && !strcmp(name + len - 5, ".unit")) 44946441bdcSMatt Fleming return true; 45046441bdcSMatt Fleming if (len > 6 && !strcmp(name + len - 6, ".scale")) 45146441bdcSMatt Fleming return true; 452044330c1SMatt Fleming if (len > 8 && !strcmp(name + len - 8, ".per-pkg")) 453044330c1SMatt Fleming return true; 4541d9e446bSJiri Olsa if (len > 9 && !strcmp(name + len - 9, ".snapshot")) 4551d9e446bSJiri Olsa return true; 45646441bdcSMatt Fleming 45746441bdcSMatt Fleming return false; 45846441bdcSMatt Fleming } 45946441bdcSMatt Fleming 460a6146d50SZheng Yan /* 461a6146d50SZheng Yan * Process all the sysfs attributes located under the directory 462a6146d50SZheng Yan * specified in 'dir' parameter. 463a6146d50SZheng Yan */ 464e293a5e8SNamhyung Kim static int pmu_aliases_parse(int dirfd, struct list_head *head) 465a6146d50SZheng Yan { 466a6146d50SZheng Yan struct dirent *evt_ent; 467a6146d50SZheng Yan DIR *event_dir; 468e293a5e8SNamhyung Kim int fd; 469a6146d50SZheng Yan 470e293a5e8SNamhyung Kim event_dir = fdopendir(dirfd); 471a6146d50SZheng Yan if (!event_dir) 472a6146d50SZheng Yan return -EINVAL; 473a6146d50SZheng Yan 474940db6dcSAndi Kleen while ((evt_ent = readdir(event_dir))) { 475a6146d50SZheng Yan char *name = evt_ent->d_name; 476a6146d50SZheng Yan FILE *file; 477a6146d50SZheng Yan 478a6146d50SZheng Yan if (!strcmp(name, ".") || !strcmp(name, "..")) 479a6146d50SZheng Yan continue; 480a6146d50SZheng Yan 481410136f5SStephane Eranian /* 48246441bdcSMatt Fleming * skip info files parsed in perf_pmu__new_alias() 483410136f5SStephane Eranian */ 48446441bdcSMatt Fleming if (pmu_alias_info_file(name)) 485410136f5SStephane Eranian continue; 486410136f5SStephane Eranian 487e293a5e8SNamhyung Kim fd = openat(dirfd, name, O_RDONLY); 4880ea8920eSIan Rogers if (fd == -1) { 4890ea8920eSIan Rogers pr_debug("Cannot open %s\n", name); 4900ea8920eSIan Rogers continue; 4910ea8920eSIan Rogers } 492e293a5e8SNamhyung Kim file = fdopen(fd, "r"); 493940db6dcSAndi Kleen if (!file) { 4940ea8920eSIan Rogers close(fd); 495940db6dcSAndi Kleen continue; 496940db6dcSAndi Kleen } 497410136f5SStephane Eranian 498e293a5e8SNamhyung Kim if (perf_pmu__new_alias(head, dirfd, name, file) < 0) 499940db6dcSAndi Kleen pr_debug("Cannot set up %s\n", name); 500a6146d50SZheng Yan fclose(file); 501a6146d50SZheng Yan } 502a6146d50SZheng Yan 503a6146d50SZheng Yan closedir(event_dir); 504940db6dcSAndi Kleen return 0; 505a6146d50SZheng Yan } 506a6146d50SZheng Yan 507a6146d50SZheng Yan /* 508a6146d50SZheng Yan * Reading the pmu event aliases definition, which should be located at: 509a6146d50SZheng Yan * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 510a6146d50SZheng Yan */ 511*838a8c5fSIan Rogers static int pmu_aliases(struct perf_pmu *pmu, int dirfd, const char *name) 512a6146d50SZheng Yan { 513e293a5e8SNamhyung Kim int fd; 514a6146d50SZheng Yan 515e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "events", O_DIRECTORY); 516e293a5e8SNamhyung Kim if (fd < 0) 517d9664582SAndi Kleen return 0; 518a6146d50SZheng Yan 519e293a5e8SNamhyung Kim /* it'll close the fd */ 520*838a8c5fSIan Rogers if (pmu_aliases_parse(fd, &pmu->aliases)) 521a6146d50SZheng Yan return -1; 522a6146d50SZheng Yan 523a6146d50SZheng Yan return 0; 524a6146d50SZheng Yan } 525a6146d50SZheng Yan 5265c6ccc37SArnaldo Carvalho de Melo static int pmu_alias_terms(struct perf_pmu_alias *alias, 527a6146d50SZheng Yan struct list_head *terms) 528a6146d50SZheng Yan { 5297c2f8164SJiri Olsa struct parse_events_term *term, *cloned; 530a6146d50SZheng Yan LIST_HEAD(list); 531a6146d50SZheng Yan int ret; 532a6146d50SZheng Yan 533a6146d50SZheng Yan list_for_each_entry(term, &alias->terms, list) { 5347c2f8164SJiri Olsa ret = parse_events_term__clone(&cloned, term); 535a6146d50SZheng Yan if (ret) { 536682dc24cSArnaldo Carvalho de Melo parse_events_terms__purge(&list); 537a6146d50SZheng Yan return ret; 538a6146d50SZheng Yan } 539c2f1ceadSAndi Kleen /* 540c2f1ceadSAndi Kleen * Weak terms don't override command line options, 541c2f1ceadSAndi Kleen * which we don't want for implicit terms in aliases. 542c2f1ceadSAndi Kleen */ 543c2f1ceadSAndi Kleen cloned->weak = true; 5447c2f8164SJiri Olsa list_add_tail(&cloned->list, &list); 545a6146d50SZheng Yan } 546a6146d50SZheng Yan list_splice(&list, terms); 547a6146d50SZheng Yan return 0; 548a6146d50SZheng Yan } 549a6146d50SZheng Yan 55066ec1191SMark Rutland /* 55166ec1191SMark Rutland * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) 55266ec1191SMark Rutland * may have a "cpus" file. 55366ec1191SMark Rutland */ 554d06593aaSIan Rogers static struct perf_cpu_map *pmu_cpumask(int dirfd, const char *name, bool is_core) 5557ae92e74SYan, Zheng { 556f854839bSJiri Olsa struct perf_cpu_map *cpus; 5577e3fcffeSMark Rutland const char *templates[] = { 558d50a79cdSJames Clark "cpumask", 559d50a79cdSJames Clark "cpus", 5607e3fcffeSMark Rutland NULL 5617e3fcffeSMark Rutland }; 5627e3fcffeSMark Rutland const char **template; 563d50a79cdSJames Clark char pmu_name[PATH_MAX]; 564d50a79cdSJames Clark struct perf_pmu pmu = {.name = pmu_name}; 565d50a79cdSJames Clark FILE *file; 5667ae92e74SYan, Zheng 567d50a79cdSJames Clark strlcpy(pmu_name, name, sizeof(pmu_name)); 5687e3fcffeSMark Rutland for (template = templates; *template; template++) { 5693a69672eSNamhyung Kim file = perf_pmu__open_file_at(&pmu, dirfd, *template); 570d50a79cdSJames Clark if (!file) 571d50a79cdSJames Clark continue; 572d50a79cdSJames Clark cpus = perf_cpu_map__read(file); 5733a69672eSNamhyung Kim fclose(file); 57466ec1191SMark Rutland if (cpus) 57566ec1191SMark Rutland return cpus; 5767e3fcffeSMark Rutland } 5777ae92e74SYan, Zheng 578d06593aaSIan Rogers /* Nothing found, for core PMUs assume this means all CPUs. */ 579d06593aaSIan Rogers return is_core ? perf_cpu_map__get(cpu_map__online()) : NULL; 58066ec1191SMark Rutland } 5817ae92e74SYan, Zheng 5823a69672eSNamhyung Kim static bool pmu_is_uncore(int dirfd, const char *name) 58366ec1191SMark Rutland { 5843a69672eSNamhyung Kim int fd; 5857ae92e74SYan, Zheng 5863a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "cpumask", O_PATH); 5873a69672eSNamhyung Kim if (fd < 0) 5883a69672eSNamhyung Kim return false; 5893a69672eSNamhyung Kim 5903a69672eSNamhyung Kim close(fd); 5913a69672eSNamhyung Kim return true; 5927ae92e74SYan, Zheng } 5937ae92e74SYan, Zheng 59451d54847SJohn Garry static char *pmu_id(const char *name) 59551d54847SJohn Garry { 59651d54847SJohn Garry char path[PATH_MAX], *str; 59751d54847SJohn Garry size_t len; 59851d54847SJohn Garry 5995f2c8efaSJames Clark perf_pmu__pathname_scnprintf(path, sizeof(path), name, "identifier"); 60051d54847SJohn Garry 6015f2c8efaSJames Clark if (filename__read_str(path, &str, &len) < 0) 60251d54847SJohn Garry return NULL; 60351d54847SJohn Garry 60451d54847SJohn Garry str[len - 1] = 0; /* remove line feed */ 60551d54847SJohn Garry 60651d54847SJohn Garry return str; 60751d54847SJohn Garry } 60851d54847SJohn Garry 6094bf7e81aSIan Rogers /** 6104bf7e81aSIan Rogers * is_sysfs_pmu_core() - PMU CORE devices have different name other than cpu in 6114bf7e81aSIan Rogers * sysfs on some platforms like ARM or Intel hybrid. Looking for 6124bf7e81aSIan Rogers * possible the cpus file in sysfs files to identify whether this is a 6134bf7e81aSIan Rogers * core device. 6144bf7e81aSIan Rogers * @name: The PMU name such as "cpu_atom". 61514b22ae0SGanapatrao Kulkarni */ 6164bf7e81aSIan Rogers static int is_sysfs_pmu_core(const char *name) 61714b22ae0SGanapatrao Kulkarni { 61814b22ae0SGanapatrao Kulkarni char path[PATH_MAX]; 61914b22ae0SGanapatrao Kulkarni 620f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), name, "cpus")) 62114b22ae0SGanapatrao Kulkarni return 0; 622d9664582SAndi Kleen return file_available(path); 62314b22ae0SGanapatrao Kulkarni } 62414b22ae0SGanapatrao Kulkarni 62529be2fe0SIan Rogers char *perf_pmu__getcpuid(struct perf_pmu *pmu) 626d77ade9fSAndi Kleen { 627d77ade9fSAndi Kleen char *cpuid; 628d77ade9fSAndi Kleen static bool printed; 629d77ade9fSAndi Kleen 630d77ade9fSAndi Kleen cpuid = getenv("PERF_CPUID"); 631d77ade9fSAndi Kleen if (cpuid) 632d77ade9fSAndi Kleen cpuid = strdup(cpuid); 633d77ade9fSAndi Kleen if (!cpuid) 63454e32dc0SGanapatrao Kulkarni cpuid = get_cpuid_str(pmu); 635d77ade9fSAndi Kleen if (!cpuid) 636d77ade9fSAndi Kleen return NULL; 637d77ade9fSAndi Kleen 638d77ade9fSAndi Kleen if (!printed) { 639d77ade9fSAndi Kleen pr_debug("Using CPUID %s\n", cpuid); 640d77ade9fSAndi Kleen printed = true; 641d77ade9fSAndi Kleen } 642d77ade9fSAndi Kleen return cpuid; 643d77ade9fSAndi Kleen } 644d77ade9fSAndi Kleen 6451ba3752aSIan Rogers __weak const struct pmu_events_table *pmu_events_table__find(void) 646e126bef5SJohn Garry { 64796d2a746SIan Rogers return perf_pmu__find_events_table(NULL); 648e126bef5SJohn Garry } 649e126bef5SJohn Garry 650f8ea2c15SIan Rogers __weak const struct pmu_metrics_table *pmu_metrics_table__find(void) 651f8ea2c15SIan Rogers { 652f8ea2c15SIan Rogers return perf_pmu__find_metrics_table(NULL); 653f8ea2c15SIan Rogers } 654f8ea2c15SIan Rogers 655240e6fd0SIan Rogers /** 656240e6fd0SIan Rogers * perf_pmu__match_ignoring_suffix - Does the pmu_name match tok ignoring any 657240e6fd0SIan Rogers * trailing suffix? The Suffix must be in form 658240e6fd0SIan Rogers * tok_{digits}, or tok{digits}. 659240e6fd0SIan Rogers * @pmu_name: The pmu_name with possible suffix. 660240e6fd0SIan Rogers * @tok: The possible match to pmu_name without suffix. 661c07d5c92SJohn Garry */ 662240e6fd0SIan Rogers static bool perf_pmu__match_ignoring_suffix(const char *pmu_name, const char *tok) 663c47a5599SJin Yao { 664c07d5c92SJohn Garry const char *p; 665c47a5599SJin Yao 666c47a5599SJin Yao if (strncmp(pmu_name, tok, strlen(tok))) 667c47a5599SJin Yao return false; 668c47a5599SJin Yao 669c47a5599SJin Yao p = pmu_name + strlen(tok); 670c47a5599SJin Yao if (*p == 0) 671c47a5599SJin Yao return true; 672c47a5599SJin Yao 673c07d5c92SJohn Garry if (*p == '_') 674c47a5599SJin Yao ++p; 675c07d5c92SJohn Garry 676c07d5c92SJohn Garry /* Ensure we end in a number */ 677c07d5c92SJohn Garry while (1) { 678c07d5c92SJohn Garry if (!isdigit(*p)) 679c47a5599SJin Yao return false; 680c07d5c92SJohn Garry if (*(++p) == 0) 681c07d5c92SJohn Garry break; 682c07d5c92SJohn Garry } 683c47a5599SJin Yao 684c47a5599SJin Yao return true; 685c47a5599SJin Yao } 686c47a5599SJin Yao 687240e6fd0SIan Rogers /** 688240e6fd0SIan Rogers * pmu_uncore_alias_match - does name match the PMU name? 689240e6fd0SIan Rogers * @pmu_name: the json struct pmu_event name. This may lack a suffix (which 690240e6fd0SIan Rogers * matches) or be of the form "socket,pmuname" which will match 691240e6fd0SIan Rogers * "socketX_pmunameY". 692240e6fd0SIan Rogers * @name: a real full PMU name as from sysfs. 693240e6fd0SIan Rogers */ 694240e6fd0SIan Rogers static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) 695730670b1SJohn Garry { 696730670b1SJohn Garry char *tmp = NULL, *tok, *str; 697730670b1SJohn Garry bool res; 698730670b1SJohn Garry 699240e6fd0SIan Rogers if (strchr(pmu_name, ',') == NULL) 700240e6fd0SIan Rogers return perf_pmu__match_ignoring_suffix(name, pmu_name); 701240e6fd0SIan Rogers 702730670b1SJohn Garry str = strdup(pmu_name); 703730670b1SJohn Garry if (!str) 704730670b1SJohn Garry return false; 705730670b1SJohn Garry 706730670b1SJohn Garry /* 707730670b1SJohn Garry * uncore alias may be from different PMU with common prefix 708730670b1SJohn Garry */ 709730670b1SJohn Garry tok = strtok_r(str, ",", &tmp); 710730670b1SJohn Garry if (strncmp(pmu_name, tok, strlen(tok))) { 711730670b1SJohn Garry res = false; 712730670b1SJohn Garry goto out; 713730670b1SJohn Garry } 714730670b1SJohn Garry 715730670b1SJohn Garry /* 716730670b1SJohn Garry * Match more complex aliases where the alias name is a comma-delimited 717730670b1SJohn Garry * list of tokens, orderly contained in the matching PMU name. 718730670b1SJohn Garry * 719730670b1SJohn Garry * Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we 720730670b1SJohn Garry * match "socket" in "socketX_pmunameY" and then "pmuname" in 721730670b1SJohn Garry * "pmunameY". 722730670b1SJohn Garry */ 723c07d5c92SJohn Garry while (1) { 724c07d5c92SJohn Garry char *next_tok = strtok_r(NULL, ",", &tmp); 725c07d5c92SJohn Garry 726730670b1SJohn Garry name = strstr(name, tok); 727c07d5c92SJohn Garry if (!name || 728240e6fd0SIan Rogers (!next_tok && !perf_pmu__match_ignoring_suffix(name, tok))) { 729730670b1SJohn Garry res = false; 730730670b1SJohn Garry goto out; 731730670b1SJohn Garry } 732c07d5c92SJohn Garry if (!next_tok) 733c07d5c92SJohn Garry break; 734c07d5c92SJohn Garry tok = next_tok; 735c07d5c92SJohn Garry name += strlen(tok); 736730670b1SJohn Garry } 737730670b1SJohn Garry 738730670b1SJohn Garry res = true; 739730670b1SJohn Garry out: 740730670b1SJohn Garry free(str); 741730670b1SJohn Garry return res; 742730670b1SJohn Garry } 743730670b1SJohn Garry 744660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data { 745d685819bSIan Rogers /* List being added to. */ 746660842e4SIan Rogers struct list_head *head; 747d685819bSIan Rogers /* If a pmu_event lacks a given PMU the default used. */ 748d685819bSIan Rogers char *default_pmu_name; 749d685819bSIan Rogers /* The PMU that we're searching for events for. */ 750660842e4SIan Rogers struct perf_pmu *pmu; 751660842e4SIan Rogers }; 752660842e4SIan Rogers 753660842e4SIan Rogers static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, 7541ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 755660842e4SIan Rogers void *vdata) 756660842e4SIan Rogers { 757660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data *data = vdata; 758d685819bSIan Rogers const char *pname = pe->pmu ?: data->default_pmu_name; 759660842e4SIan Rogers 760d685819bSIan Rogers if (!strcmp(pname, data->pmu->name) || 761d685819bSIan Rogers (data->pmu->is_uncore && pmu_uncore_alias_match(pname, data->pmu->name))) { 762660842e4SIan Rogers /* need type casts to override 'const' */ 763e293a5e8SNamhyung Kim __perf_pmu__new_alias(data->head, -1, (char *)pe->name, (char *)pe->desc, 764660842e4SIan Rogers (char *)pe->event, pe); 765d685819bSIan Rogers } 766660842e4SIan Rogers return 0; 767660842e4SIan Rogers } 768660842e4SIan Rogers 769933f82ffSSukadev Bhattiprolu /* 770d685819bSIan Rogers * From the pmu_events_table, find the events that correspond to the given 771d685819bSIan Rogers * PMU and add them to the list 'head'. 772933f82ffSSukadev Bhattiprolu */ 773*838a8c5fSIan Rogers void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table) 774933f82ffSSukadev Bhattiprolu { 775660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data data = { 776*838a8c5fSIan Rogers .head = &pmu->aliases, 777d685819bSIan Rogers .default_pmu_name = perf_pmus__default_pmu_name(), 778660842e4SIan Rogers .pmu = pmu, 779660842e4SIan Rogers }; 780fedb2b51SAndi Kleen 781660842e4SIan Rogers pmu_events_table_for_each_event(table, pmu_add_cpu_aliases_map_callback, &data); 782d685819bSIan Rogers free(data.default_pmu_name); 783933f82ffSSukadev Bhattiprolu } 784933f82ffSSukadev Bhattiprolu 785*838a8c5fSIan Rogers static void pmu_add_cpu_aliases(struct perf_pmu *pmu) 786e45ad701SJohn Garry { 7871ba3752aSIan Rogers const struct pmu_events_table *table; 788e45ad701SJohn Garry 78996d2a746SIan Rogers table = perf_pmu__find_events_table(pmu); 790eeac7730SIan Rogers if (!table) 791e45ad701SJohn Garry return; 792e45ad701SJohn Garry 793*838a8c5fSIan Rogers pmu_add_cpu_aliases_table(pmu, table); 794e45ad701SJohn Garry } 795e45ad701SJohn Garry 7964513c719SJohn Garry struct pmu_sys_event_iter_data { 7974513c719SJohn Garry struct list_head *head; 7984513c719SJohn Garry struct perf_pmu *pmu; 7994513c719SJohn Garry }; 8004513c719SJohn Garry 80129be2fe0SIan Rogers static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, 8021ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 80329be2fe0SIan Rogers void *data) 8044513c719SJohn Garry { 8054513c719SJohn Garry struct pmu_sys_event_iter_data *idata = data; 8064513c719SJohn Garry struct perf_pmu *pmu = idata->pmu; 8074513c719SJohn Garry 8084513c719SJohn Garry if (!pe->compat || !pe->pmu) 8094513c719SJohn Garry return 0; 8104513c719SJohn Garry 8114513c719SJohn Garry if (!strcmp(pmu->id, pe->compat) && 8124513c719SJohn Garry pmu_uncore_alias_match(pe->pmu, pmu->name)) { 813e293a5e8SNamhyung Kim __perf_pmu__new_alias(idata->head, -1, 8144513c719SJohn Garry (char *)pe->name, 8154513c719SJohn Garry (char *)pe->desc, 8164513c719SJohn Garry (char *)pe->event, 817eab35953SJin Yao pe); 8184513c719SJohn Garry } 8194513c719SJohn Garry 8204513c719SJohn Garry return 0; 8214513c719SJohn Garry } 8224513c719SJohn Garry 823*838a8c5fSIan Rogers void pmu_add_sys_aliases(struct perf_pmu *pmu) 8244513c719SJohn Garry { 8254513c719SJohn Garry struct pmu_sys_event_iter_data idata = { 826*838a8c5fSIan Rogers .head = &pmu->aliases, 8274513c719SJohn Garry .pmu = pmu, 8284513c719SJohn Garry }; 8294513c719SJohn Garry 8304513c719SJohn Garry if (!pmu->id) 8314513c719SJohn Garry return; 8324513c719SJohn Garry 8334513c719SJohn Garry pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, &idata); 8344513c719SJohn Garry } 8354513c719SJohn Garry 836c5de47f2SSukadev Bhattiprolu struct perf_event_attr * __weak 837dc0a6202SAdrian Hunter perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) 838dc0a6202SAdrian Hunter { 839dc0a6202SAdrian Hunter return NULL; 840dc0a6202SAdrian Hunter } 841dc0a6202SAdrian Hunter 84213d60ba0SKan Liang char * __weak 84313d60ba0SKan Liang pmu_find_real_name(const char *name) 84413d60ba0SKan Liang { 84513d60ba0SKan Liang return (char *)name; 84613d60ba0SKan Liang } 84713d60ba0SKan Liang 84813d60ba0SKan Liang char * __weak 84913d60ba0SKan Liang pmu_find_alias_name(const char *name __maybe_unused) 85013d60ba0SKan Liang { 85113d60ba0SKan Liang return NULL; 85213d60ba0SKan Liang } 85313d60ba0SKan Liang 8543a69672eSNamhyung Kim static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) 85590a86bdeSJiri Olsa { 85690a86bdeSJiri Olsa int max_precise = -1; 85790a86bdeSJiri Olsa 8583a69672eSNamhyung Kim perf_pmu__scan_file_at(pmu, dirfd, "caps/max_precise", "%d", &max_precise); 85990a86bdeSJiri Olsa return max_precise; 86090a86bdeSJiri Olsa } 86190a86bdeSJiri Olsa 8621eaf496eSIan Rogers struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name) 863cd82a32eSJiri Olsa { 864cd82a32eSJiri Olsa struct perf_pmu *pmu; 865cd82a32eSJiri Olsa __u32 type; 86613d60ba0SKan Liang char *name = pmu_find_real_name(lookup_name); 86713d60ba0SKan Liang char *alias_name; 86849afa7f6SJin Yao 869cd82a32eSJiri Olsa pmu = zalloc(sizeof(*pmu)); 870cd82a32eSJiri Olsa if (!pmu) 871cd82a32eSJiri Olsa return NULL; 872cd82a32eSJiri Olsa 873*838a8c5fSIan Rogers INIT_LIST_HEAD(&pmu->format); 874*838a8c5fSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 875*838a8c5fSIan Rogers INIT_LIST_HEAD(&pmu->caps); 876*838a8c5fSIan Rogers /* 877*838a8c5fSIan Rogers * The pmu data we store & need consists of the pmu 878*838a8c5fSIan Rogers * type value and format definitions. Load both right 879*838a8c5fSIan Rogers * now. 880*838a8c5fSIan Rogers */ 881*838a8c5fSIan Rogers if (pmu_format(pmu, dirfd, name)) { 882*838a8c5fSIan Rogers free(pmu); 883*838a8c5fSIan Rogers return NULL; 884*838a8c5fSIan Rogers } 885*838a8c5fSIan Rogers /* 886*838a8c5fSIan Rogers * Check the aliases first to avoid unnecessary work. 887*838a8c5fSIan Rogers */ 888*838a8c5fSIan Rogers if (pmu_aliases(pmu, dirfd, name)) { 889*838a8c5fSIan Rogers free(pmu); 890*838a8c5fSIan Rogers return NULL; 891*838a8c5fSIan Rogers } 892d06593aaSIan Rogers pmu->is_core = is_pmu_core(name); 893d06593aaSIan Rogers pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core); 89454e32dc0SGanapatrao Kulkarni pmu->name = strdup(name); 89513d60ba0SKan Liang if (!pmu->name) 89613d60ba0SKan Liang goto err; 89713d60ba0SKan Liang 898f8ad6018SJames Clark /* Read type, and ensure that type value is successfully assigned (return 1) */ 8993a69672eSNamhyung Kim if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1) 900f8ad6018SJames Clark goto err; 901f8ad6018SJames Clark 90213d60ba0SKan Liang alias_name = pmu_find_alias_name(name); 90313d60ba0SKan Liang if (alias_name) { 90413d60ba0SKan Liang pmu->alias_name = strdup(alias_name); 90513d60ba0SKan Liang if (!pmu->alias_name) 90613d60ba0SKan Liang goto err; 90713d60ba0SKan Liang } 90813d60ba0SKan Liang 90954e32dc0SGanapatrao Kulkarni pmu->type = type; 9103a69672eSNamhyung Kim pmu->is_uncore = pmu_is_uncore(dirfd, name); 91151d54847SJohn Garry if (pmu->is_uncore) 91251d54847SJohn Garry pmu->id = pmu_id(name); 9133a69672eSNamhyung Kim pmu->max_precise = pmu_max_precise(dirfd, pmu); 914*838a8c5fSIan Rogers pmu_add_cpu_aliases(pmu); 915*838a8c5fSIan Rogers pmu_add_sys_aliases(pmu); 9161eaf496eSIan Rogers list_add_tail(&pmu->list, pmus); 917dc0a6202SAdrian Hunter 918dc0a6202SAdrian Hunter pmu->default_config = perf_pmu__get_default_config(pmu); 919dc0a6202SAdrian Hunter 920cd82a32eSJiri Olsa return pmu; 92113d60ba0SKan Liang err: 922efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 92313d60ba0SKan Liang free(pmu); 92413d60ba0SKan Liang return NULL; 925cd82a32eSJiri Olsa } 926cd82a32eSJiri Olsa 927628eaa4eSIan Rogers /* Creates the PMU when sysfs scanning fails. */ 928628eaa4eSIan Rogers struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus) 929628eaa4eSIan Rogers { 930628eaa4eSIan Rogers struct perf_pmu *pmu = zalloc(sizeof(*pmu)); 931628eaa4eSIan Rogers 932628eaa4eSIan Rogers if (!pmu) 933628eaa4eSIan Rogers return NULL; 934628eaa4eSIan Rogers 935628eaa4eSIan Rogers pmu->name = strdup("cpu"); 936628eaa4eSIan Rogers if (!pmu->name) { 937628eaa4eSIan Rogers free(pmu); 938628eaa4eSIan Rogers return NULL; 939628eaa4eSIan Rogers } 940628eaa4eSIan Rogers 941628eaa4eSIan Rogers pmu->is_core = true; 942628eaa4eSIan Rogers pmu->type = PERF_TYPE_RAW; 943628eaa4eSIan Rogers pmu->cpus = cpu_map__online(); 944628eaa4eSIan Rogers 945628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->format); 946628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 947628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->caps); 948628eaa4eSIan Rogers list_add_tail(&pmu->list, core_pmus); 949628eaa4eSIan Rogers return pmu; 950628eaa4eSIan Rogers } 951628eaa4eSIan Rogers 952e552b7beSRob Herring void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu) 953e552b7beSRob Herring { 954e552b7beSRob Herring struct perf_pmu_format *format; 955e552b7beSRob Herring 95668c25043SIan Rogers if (pmu->formats_checked) 95768c25043SIan Rogers return; 95868c25043SIan Rogers 95968c25043SIan Rogers pmu->formats_checked = true; 96068c25043SIan Rogers 961e552b7beSRob Herring /* fake pmu doesn't have format list */ 962e552b7beSRob Herring if (pmu == &perf_pmu__fake) 963e552b7beSRob Herring return; 964e552b7beSRob Herring 965e552b7beSRob Herring list_for_each_entry(format, &pmu->format, list) 966e552b7beSRob Herring if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) { 967e552b7beSRob Herring pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'" 968e552b7beSRob Herring "which is not supported by this version of perf!\n", 969e552b7beSRob Herring pmu->name, format->name, format->value); 970e552b7beSRob Herring return; 971e552b7beSRob Herring } 972e552b7beSRob Herring } 973e552b7beSRob Herring 974c6d616feSIan Rogers bool evsel__is_aux_event(const struct evsel *evsel) 975e12ee9f7SAdrian Hunter { 976e76026bdSArnaldo Carvalho de Melo struct perf_pmu *pmu = evsel__find_pmu(evsel); 977e12ee9f7SAdrian Hunter 978e12ee9f7SAdrian Hunter return pmu && pmu->auxtrace; 979e12ee9f7SAdrian Hunter } 980e12ee9f7SAdrian Hunter 9816593f019SJames Clark /* 9826593f019SJames Clark * Set @config_name to @val as long as the user hasn't already set or cleared it 9836593f019SJames Clark * by passing a config term on the command line. 9846593f019SJames Clark * 9856593f019SJames Clark * @val is the value to put into the bits specified by @config_name rather than 9866593f019SJames Clark * the bit pattern. It is shifted into position by this function, so to set 9876593f019SJames Clark * something to true, pass 1 for val rather than a pre shifted value. 9886593f019SJames Clark */ 9896593f019SJames Clark #define field_prep(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask)) 9906593f019SJames Clark void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, 9916593f019SJames Clark const char *config_name, u64 val) 9926593f019SJames Clark { 9936593f019SJames Clark u64 user_bits = 0, bits; 9946593f019SJames Clark struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG); 9956593f019SJames Clark 9966593f019SJames Clark if (term) 9976593f019SJames Clark user_bits = term->val.cfg_chg; 9986593f019SJames Clark 999da6a5afdSIan Rogers bits = perf_pmu__format_bits(pmu, config_name); 10006593f019SJames Clark 10016593f019SJames Clark /* Do nothing if the user changed the value */ 10026593f019SJames Clark if (bits & user_bits) 10036593f019SJames Clark return; 10046593f019SJames Clark 10056593f019SJames Clark /* Otherwise replace it */ 10066593f019SJames Clark evsel->core.attr.config &= ~bits; 10076593f019SJames Clark evsel->core.attr.config |= field_prep(bits, val); 10086593f019SJames Clark } 10096593f019SJames Clark 10105c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_format * 101109ff6071SAdrian Hunter pmu_find_format(struct list_head *formats, const char *name) 1012cd82a32eSJiri Olsa { 10135c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1014cd82a32eSJiri Olsa 1015cd82a32eSJiri Olsa list_for_each_entry(format, formats, list) 1016cd82a32eSJiri Olsa if (!strcmp(format->name, name)) 1017cd82a32eSJiri Olsa return format; 1018cd82a32eSJiri Olsa 1019cd82a32eSJiri Olsa return NULL; 1020cd82a32eSJiri Olsa } 1021cd82a32eSJiri Olsa 1022da6a5afdSIan Rogers __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name) 102309ff6071SAdrian Hunter { 1024da6a5afdSIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 102509ff6071SAdrian Hunter __u64 bits = 0; 102609ff6071SAdrian Hunter int fbit; 102709ff6071SAdrian Hunter 102809ff6071SAdrian Hunter if (!format) 102909ff6071SAdrian Hunter return 0; 103009ff6071SAdrian Hunter 103109ff6071SAdrian Hunter for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS) 103209ff6071SAdrian Hunter bits |= 1ULL << fbit; 103309ff6071SAdrian Hunter 103409ff6071SAdrian Hunter return bits; 103509ff6071SAdrian Hunter } 103609ff6071SAdrian Hunter 10377eb54733SIan Rogers int perf_pmu__format_type(struct perf_pmu *pmu, const char *name) 1038a1ac7de6SAdrian Hunter { 10397eb54733SIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 1040a1ac7de6SAdrian Hunter 1041a1ac7de6SAdrian Hunter if (!format) 1042a1ac7de6SAdrian Hunter return -1; 1043a1ac7de6SAdrian Hunter 1044a1ac7de6SAdrian Hunter return format->value; 1045a1ac7de6SAdrian Hunter } 1046a1ac7de6SAdrian Hunter 1047cd82a32eSJiri Olsa /* 1048dc0a6202SAdrian Hunter * Sets value based on the format definition (format parameter) 10494d39c89fSIngo Molnar * and unformatted value (value parameter). 1050cd82a32eSJiri Olsa */ 1051dc0a6202SAdrian Hunter static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, 1052dc0a6202SAdrian Hunter bool zero) 1053cd82a32eSJiri Olsa { 1054cd82a32eSJiri Olsa unsigned long fbit, vbit; 1055cd82a32eSJiri Olsa 1056cd82a32eSJiri Olsa for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 1057cd82a32eSJiri Olsa 1058cd82a32eSJiri Olsa if (!test_bit(fbit, format)) 1059cd82a32eSJiri Olsa continue; 1060cd82a32eSJiri Olsa 1061dc0a6202SAdrian Hunter if (value & (1llu << vbit++)) 1062dc0a6202SAdrian Hunter *v |= (1llu << fbit); 1063dc0a6202SAdrian Hunter else if (zero) 1064dc0a6202SAdrian Hunter *v &= ~(1llu << fbit); 1065cd82a32eSJiri Olsa } 1066cd82a32eSJiri Olsa } 1067cd82a32eSJiri Olsa 10680efe6b67SAdrian Hunter static __u64 pmu_format_max_value(const unsigned long *format) 10690efe6b67SAdrian Hunter { 10701b9caa10SJiri Olsa int w; 10710efe6b67SAdrian Hunter 10721b9caa10SJiri Olsa w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); 10731b9caa10SJiri Olsa if (!w) 10741b9caa10SJiri Olsa return 0; 10751b9caa10SJiri Olsa if (w < 64) 10761b9caa10SJiri Olsa return (1ULL << w) - 1; 10771b9caa10SJiri Olsa return -1; 10780efe6b67SAdrian Hunter } 10790efe6b67SAdrian Hunter 1080cd82a32eSJiri Olsa /* 1081688d4dfcSCody P Schafer * Term is a string term, and might be a param-term. Try to look up it's value 1082688d4dfcSCody P Schafer * in the remaining terms. 1083688d4dfcSCody P Schafer * - We have a term like "base-or-format-term=param-term", 1084688d4dfcSCody P Schafer * - We need to find the value supplied for "param-term" (with param-term named 1085688d4dfcSCody P Schafer * in a config string) later on in the term list. 1086688d4dfcSCody P Schafer */ 1087688d4dfcSCody P Schafer static int pmu_resolve_param_term(struct parse_events_term *term, 1088688d4dfcSCody P Schafer struct list_head *head_terms, 1089688d4dfcSCody P Schafer __u64 *value) 1090688d4dfcSCody P Schafer { 1091688d4dfcSCody P Schafer struct parse_events_term *t; 1092688d4dfcSCody P Schafer 1093688d4dfcSCody P Schafer list_for_each_entry(t, head_terms, list) { 10942a3d252dSIan Rogers if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM && 10952a3d252dSIan Rogers t->config && !strcmp(t->config, term->config)) { 1096688d4dfcSCody P Schafer t->used = true; 1097688d4dfcSCody P Schafer *value = t->val.num; 1098688d4dfcSCody P Schafer return 0; 1099688d4dfcSCody P Schafer } 1100688d4dfcSCody P Schafer } 1101688d4dfcSCody P Schafer 1102bb963e16SNamhyung Kim if (verbose > 0) 1103688d4dfcSCody P Schafer printf("Required parameter '%s' not specified\n", term->config); 1104688d4dfcSCody P Schafer 1105688d4dfcSCody P Schafer return -1; 1106688d4dfcSCody P Schafer } 1107688d4dfcSCody P Schafer 1108ffeb883eSHe Kuang static char *pmu_formats_string(struct list_head *formats) 1109e64b020bSJiri Olsa { 1110e64b020bSJiri Olsa struct perf_pmu_format *format; 111111db4e29SMasami Hiramatsu char *str = NULL; 111211db4e29SMasami Hiramatsu struct strbuf buf = STRBUF_INIT; 1113f1417ceaSXin Gao unsigned int i = 0; 1114e64b020bSJiri Olsa 1115ffeb883eSHe Kuang if (!formats) 1116e64b020bSJiri Olsa return NULL; 1117e64b020bSJiri Olsa 1118e64b020bSJiri Olsa /* sysfs exported terms */ 1119ffeb883eSHe Kuang list_for_each_entry(format, formats, list) 112011db4e29SMasami Hiramatsu if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0) 112111db4e29SMasami Hiramatsu goto error; 1122e64b020bSJiri Olsa 1123ffeb883eSHe Kuang str = strbuf_detach(&buf, NULL); 112411db4e29SMasami Hiramatsu error: 1125ffeb883eSHe Kuang strbuf_release(&buf); 1126e64b020bSJiri Olsa 1127e64b020bSJiri Olsa return str; 1128e64b020bSJiri Olsa } 1129e64b020bSJiri Olsa 1130688d4dfcSCody P Schafer /* 1131cd82a32eSJiri Olsa * Setup one of config[12] attr members based on the 113288aca8d9SCody P Schafer * user input data - term parameter. 1133cd82a32eSJiri Olsa */ 1134804fee5dSIan Rogers static int pmu_config_term(struct perf_pmu *pmu, 1135cd82a32eSJiri Olsa struct perf_event_attr *attr, 1136dc0a6202SAdrian Hunter struct parse_events_term *term, 1137688d4dfcSCody P Schafer struct list_head *head_terms, 1138e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1139cd82a32eSJiri Olsa { 11405c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1141cd82a32eSJiri Olsa __u64 *vp; 11420efe6b67SAdrian Hunter __u64 val, max_val; 1143cd82a32eSJiri Olsa 1144cd82a32eSJiri Olsa /* 1145688d4dfcSCody P Schafer * If this is a parameter we've already used for parameterized-eval, 1146688d4dfcSCody P Schafer * skip it in normal eval. 1147688d4dfcSCody P Schafer */ 1148688d4dfcSCody P Schafer if (term->used) 1149688d4dfcSCody P Schafer return 0; 1150688d4dfcSCody P Schafer 1151688d4dfcSCody P Schafer /* 1152cd82a32eSJiri Olsa * Hardcoded terms should be already in, so nothing 1153cd82a32eSJiri Olsa * to be done for them. 1154cd82a32eSJiri Olsa */ 1155cd82a32eSJiri Olsa if (parse_events__is_hardcoded_term(term)) 1156cd82a32eSJiri Olsa return 0; 1157cd82a32eSJiri Olsa 1158804fee5dSIan Rogers format = pmu_find_format(&pmu->format, term->config); 1159688d4dfcSCody P Schafer if (!format) { 1160804fee5dSIan Rogers char *pmu_term = pmu_formats_string(&pmu->format); 11614ac22b48SIan Rogers char *unknown_term; 11624ac22b48SIan Rogers char *help_msg; 1163ffeb883eSHe Kuang 11644ac22b48SIan Rogers if (asprintf(&unknown_term, 11654ac22b48SIan Rogers "unknown term '%s' for pmu '%s'", 1166804fee5dSIan Rogers term->config, pmu->name) < 0) 11674ac22b48SIan Rogers unknown_term = NULL; 11684ac22b48SIan Rogers help_msg = parse_events_formats_error_string(pmu_term); 11694ac22b48SIan Rogers if (err) { 11706c191289SIan Rogers parse_events_error__handle(err, term->err_term, 11714ac22b48SIan Rogers unknown_term, 11724ac22b48SIan Rogers help_msg); 11734ac22b48SIan Rogers } else { 11744ac22b48SIan Rogers pr_debug("%s (%s)\n", unknown_term, help_msg); 11754ac22b48SIan Rogers free(unknown_term); 1176e64b020bSJiri Olsa } 11774ac22b48SIan Rogers free(pmu_term); 1178cd82a32eSJiri Olsa return -EINVAL; 1179688d4dfcSCody P Schafer } 1180cd82a32eSJiri Olsa 1181cd82a32eSJiri Olsa switch (format->value) { 1182cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG: 1183cd82a32eSJiri Olsa vp = &attr->config; 1184cd82a32eSJiri Olsa break; 1185cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG1: 1186cd82a32eSJiri Olsa vp = &attr->config1; 1187cd82a32eSJiri Olsa break; 1188cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG2: 1189cd82a32eSJiri Olsa vp = &attr->config2; 1190cd82a32eSJiri Olsa break; 1191204e7c49SRob Herring case PERF_PMU_FORMAT_VALUE_CONFIG3: 1192204e7c49SRob Herring vp = &attr->config3; 1193204e7c49SRob Herring break; 1194cd82a32eSJiri Olsa default: 1195cd82a32eSJiri Olsa return -EINVAL; 1196cd82a32eSJiri Olsa } 1197cd82a32eSJiri Olsa 119816fa7e82SJiri Olsa /* 1199688d4dfcSCody P Schafer * Either directly use a numeric term, or try to translate string terms 1200688d4dfcSCody P Schafer * using event parameters. 120116fa7e82SJiri Olsa */ 120299e7138eSJiri Olsa if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 120399e7138eSJiri Olsa if (term->no_value && 120499e7138eSJiri Olsa bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) { 120599e7138eSJiri Olsa if (err) { 12066c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1207448d732cSIan Rogers strdup("no value assigned for term"), 1208448d732cSIan Rogers NULL); 120999e7138eSJiri Olsa } 121099e7138eSJiri Olsa return -EINVAL; 121199e7138eSJiri Olsa } 121299e7138eSJiri Olsa 1213688d4dfcSCody P Schafer val = term->val.num; 121499e7138eSJiri Olsa } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1215688d4dfcSCody P Schafer if (strcmp(term->val.str, "?")) { 1216bb963e16SNamhyung Kim if (verbose > 0) { 1217688d4dfcSCody P Schafer pr_info("Invalid sysfs entry %s=%s\n", 1218688d4dfcSCody P Schafer term->config, term->val.str); 1219e64b020bSJiri Olsa } 1220e64b020bSJiri Olsa if (err) { 12216c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1222448d732cSIan Rogers strdup("expected numeric value"), 1223448d732cSIan Rogers NULL); 1224e64b020bSJiri Olsa } 1225688d4dfcSCody P Schafer return -EINVAL; 1226688d4dfcSCody P Schafer } 1227688d4dfcSCody P Schafer 1228688d4dfcSCody P Schafer if (pmu_resolve_param_term(term, head_terms, &val)) 1229688d4dfcSCody P Schafer return -EINVAL; 1230688d4dfcSCody P Schafer } else 1231688d4dfcSCody P Schafer return -EINVAL; 1232688d4dfcSCody P Schafer 12330efe6b67SAdrian Hunter max_val = pmu_format_max_value(format->bits); 12340efe6b67SAdrian Hunter if (val > max_val) { 12350efe6b67SAdrian Hunter if (err) { 1236448d732cSIan Rogers char *err_str; 1237448d732cSIan Rogers 12386c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1239448d732cSIan Rogers asprintf(&err_str, 12400efe6b67SAdrian Hunter "value too big for format, maximum is %llu", 1241448d732cSIan Rogers (unsigned long long)max_val) < 0 1242448d732cSIan Rogers ? strdup("value too big for format") 1243448d732cSIan Rogers : err_str, 1244448d732cSIan Rogers NULL); 12450efe6b67SAdrian Hunter return -EINVAL; 12460efe6b67SAdrian Hunter } 12470efe6b67SAdrian Hunter /* 12480efe6b67SAdrian Hunter * Assume we don't care if !err, in which case the value will be 12490efe6b67SAdrian Hunter * silently truncated. 12500efe6b67SAdrian Hunter */ 12510efe6b67SAdrian Hunter } 12520efe6b67SAdrian Hunter 1253688d4dfcSCody P Schafer pmu_format_value(format->bits, val, vp, zero); 1254cd82a32eSJiri Olsa return 0; 1255cd82a32eSJiri Olsa } 1256cd82a32eSJiri Olsa 1257804fee5dSIan Rogers int perf_pmu__config_terms(struct perf_pmu *pmu, 1258cff7f956SJiri Olsa struct perf_event_attr *attr, 1259dc0a6202SAdrian Hunter struct list_head *head_terms, 1260e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1261cd82a32eSJiri Olsa { 12626cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 1263cd82a32eSJiri Olsa 1264688d4dfcSCody P Schafer list_for_each_entry(term, head_terms, list) { 1265804fee5dSIan Rogers if (pmu_config_term(pmu, attr, term, head_terms, zero, err)) 1266cd82a32eSJiri Olsa return -EINVAL; 1267688d4dfcSCody P Schafer } 1268cd82a32eSJiri Olsa 1269cd82a32eSJiri Olsa return 0; 1270cd82a32eSJiri Olsa } 1271cd82a32eSJiri Olsa 1272cd82a32eSJiri Olsa /* 1273cd82a32eSJiri Olsa * Configures event's 'attr' parameter based on the: 1274cd82a32eSJiri Olsa * 1) users input - specified in terms parameter 1275cd82a32eSJiri Olsa * 2) pmu format definitions - specified by pmu parameter 1276cd82a32eSJiri Olsa */ 1277cd82a32eSJiri Olsa int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 1278e64b020bSJiri Olsa struct list_head *head_terms, 1279e64b020bSJiri Olsa struct parse_events_error *err) 1280cd82a32eSJiri Olsa { 1281dc0a6202SAdrian Hunter bool zero = !!pmu->default_config; 1282dc0a6202SAdrian Hunter 1283804fee5dSIan Rogers return perf_pmu__config_terms(pmu, attr, head_terms, zero, err); 1284cd82a32eSJiri Olsa } 1285cd82a32eSJiri Olsa 12865c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 12876cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 1288a6146d50SZheng Yan { 12895c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1290a6146d50SZheng Yan char *name; 1291a6146d50SZheng Yan 1292a6146d50SZheng Yan if (parse_events__is_hardcoded_term(term)) 1293a6146d50SZheng Yan return NULL; 1294a6146d50SZheng Yan 1295a6146d50SZheng Yan if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 1296a6146d50SZheng Yan if (term->val.num != 1) 1297a6146d50SZheng Yan return NULL; 1298a6146d50SZheng Yan if (pmu_find_format(&pmu->format, term->config)) 1299a6146d50SZheng Yan return NULL; 1300a6146d50SZheng Yan name = term->config; 1301a6146d50SZheng Yan } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1302a6146d50SZheng Yan if (strcasecmp(term->config, "event")) 1303a6146d50SZheng Yan return NULL; 1304a6146d50SZheng Yan name = term->val.str; 1305a6146d50SZheng Yan } else { 1306a6146d50SZheng Yan return NULL; 1307a6146d50SZheng Yan } 1308a6146d50SZheng Yan 1309a6146d50SZheng Yan list_for_each_entry(alias, &pmu->aliases, list) { 1310a6146d50SZheng Yan if (!strcasecmp(alias->name, name)) 1311a6146d50SZheng Yan return alias; 1312a6146d50SZheng Yan } 1313a6146d50SZheng Yan return NULL; 1314a6146d50SZheng Yan } 1315a6146d50SZheng Yan 1316410136f5SStephane Eranian 13171d9e446bSJiri Olsa static int check_info_data(struct perf_pmu_alias *alias, 13181d9e446bSJiri Olsa struct perf_pmu_info *info) 1319410136f5SStephane Eranian { 1320410136f5SStephane Eranian /* 1321410136f5SStephane Eranian * Only one term in event definition can 13221d9e446bSJiri Olsa * define unit, scale and snapshot, fail 13231d9e446bSJiri Olsa * if there's more than one. 1324410136f5SStephane Eranian */ 1325b30a7d1fSArnaldo Carvalho de Melo if ((info->unit && alias->unit[0]) || 13261d9e446bSJiri Olsa (info->scale && alias->scale) || 13271d9e446bSJiri Olsa (info->snapshot && alias->snapshot)) 1328410136f5SStephane Eranian return -EINVAL; 1329410136f5SStephane Eranian 1330b30a7d1fSArnaldo Carvalho de Melo if (alias->unit[0]) 13311d9e446bSJiri Olsa info->unit = alias->unit; 1332410136f5SStephane Eranian 1333410136f5SStephane Eranian if (alias->scale) 13341d9e446bSJiri Olsa info->scale = alias->scale; 13351d9e446bSJiri Olsa 13361d9e446bSJiri Olsa if (alias->snapshot) 13371d9e446bSJiri Olsa info->snapshot = alias->snapshot; 1338410136f5SStephane Eranian 1339410136f5SStephane Eranian return 0; 1340410136f5SStephane Eranian } 1341410136f5SStephane Eranian 1342a6146d50SZheng Yan /* 1343a6146d50SZheng Yan * Find alias in the terms list and replace it with the terms 1344a6146d50SZheng Yan * defined for the alias 1345a6146d50SZheng Yan */ 1346410136f5SStephane Eranian int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 134746441bdcSMatt Fleming struct perf_pmu_info *info) 1348a6146d50SZheng Yan { 13496cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 13505c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1351a6146d50SZheng Yan int ret; 1352a6146d50SZheng Yan 1353044330c1SMatt Fleming info->per_pkg = false; 1354044330c1SMatt Fleming 13558a398897SStephane Eranian /* 13568a398897SStephane Eranian * Mark unit and scale as not set 13578a398897SStephane Eranian * (different from default values, see below) 13588a398897SStephane Eranian */ 135946441bdcSMatt Fleming info->unit = NULL; 136046441bdcSMatt Fleming info->scale = 0.0; 13611d9e446bSJiri Olsa info->snapshot = false; 1362410136f5SStephane Eranian 1363a6146d50SZheng Yan list_for_each_entry_safe(term, h, head_terms, list) { 1364a6146d50SZheng Yan alias = pmu_find_alias(pmu, term); 1365a6146d50SZheng Yan if (!alias) 1366a6146d50SZheng Yan continue; 1367a6146d50SZheng Yan ret = pmu_alias_terms(alias, &term->list); 1368a6146d50SZheng Yan if (ret) 1369a6146d50SZheng Yan return ret; 1370410136f5SStephane Eranian 13711d9e446bSJiri Olsa ret = check_info_data(alias, info); 1372410136f5SStephane Eranian if (ret) 1373410136f5SStephane Eranian return ret; 1374410136f5SStephane Eranian 1375044330c1SMatt Fleming if (alias->per_pkg) 1376044330c1SMatt Fleming info->per_pkg = true; 1377044330c1SMatt Fleming 1378e56fbc9dSArnaldo Carvalho de Melo list_del_init(&term->list); 13791dc92556SIan Rogers parse_events_term__delete(term); 1380a6146d50SZheng Yan } 13818a398897SStephane Eranian 13828a398897SStephane Eranian /* 13838a398897SStephane Eranian * if no unit or scale found in aliases, then 13848a398897SStephane Eranian * set defaults as for evsel 13858a398897SStephane Eranian * unit cannot left to NULL 13868a398897SStephane Eranian */ 138746441bdcSMatt Fleming if (info->unit == NULL) 138846441bdcSMatt Fleming info->unit = ""; 13898a398897SStephane Eranian 139046441bdcSMatt Fleming if (info->scale == 0.0) 139146441bdcSMatt Fleming info->scale = 1.0; 13928a398897SStephane Eranian 1393a6146d50SZheng Yan return 0; 1394a6146d50SZheng Yan } 1395a6146d50SZheng Yan 1396*838a8c5fSIan Rogers struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, const char *event) 1397*838a8c5fSIan Rogers { 1398*838a8c5fSIan Rogers struct perf_pmu_alias *alias; 1399*838a8c5fSIan Rogers 1400*838a8c5fSIan Rogers list_for_each_entry(alias, &pmu->aliases, list) 1401*838a8c5fSIan Rogers if (!strcmp(event, alias->name)) 1402*838a8c5fSIan Rogers return alias; 1403*838a8c5fSIan Rogers 1404*838a8c5fSIan Rogers return NULL; 1405*838a8c5fSIan Rogers } 1406*838a8c5fSIan Rogers 1407cd82a32eSJiri Olsa int perf_pmu__new_format(struct list_head *list, char *name, 1408cd82a32eSJiri Olsa int config, unsigned long *bits) 1409cd82a32eSJiri Olsa { 14105c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1411cd82a32eSJiri Olsa 1412cd82a32eSJiri Olsa format = zalloc(sizeof(*format)); 1413cd82a32eSJiri Olsa if (!format) 1414cd82a32eSJiri Olsa return -ENOMEM; 1415cd82a32eSJiri Olsa 1416cd82a32eSJiri Olsa format->name = strdup(name); 1417cd82a32eSJiri Olsa format->value = config; 1418cd82a32eSJiri Olsa memcpy(format->bits, bits, sizeof(format->bits)); 1419cd82a32eSJiri Olsa 1420cd82a32eSJiri Olsa list_add_tail(&format->list, list); 1421cd82a32eSJiri Olsa return 0; 1422cd82a32eSJiri Olsa } 1423cd82a32eSJiri Olsa 1424804fee5dSIan Rogers static void perf_pmu__del_formats(struct list_head *formats) 1425d26383dcSNamhyung Kim { 1426d26383dcSNamhyung Kim struct perf_pmu_format *fmt, *tmp; 1427d26383dcSNamhyung Kim 1428d26383dcSNamhyung Kim list_for_each_entry_safe(fmt, tmp, formats, list) { 1429d26383dcSNamhyung Kim list_del(&fmt->list); 1430efe98a7aSArnaldo Carvalho de Melo zfree(&fmt->name); 1431d26383dcSNamhyung Kim free(fmt); 1432d26383dcSNamhyung Kim } 1433d26383dcSNamhyung Kim } 1434d26383dcSNamhyung Kim 143507d2b820SIan Rogers bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name) 143607d2b820SIan Rogers { 143707d2b820SIan Rogers struct perf_pmu_format *format; 143807d2b820SIan Rogers 143907d2b820SIan Rogers list_for_each_entry(format, &pmu->format, list) { 144007d2b820SIan Rogers if (!strcmp(format->name, name)) 144107d2b820SIan Rogers return true; 144207d2b820SIan Rogers } 144307d2b820SIan Rogers return false; 144407d2b820SIan Rogers } 144507d2b820SIan Rogers 1446d504fae9SJohn Garry bool is_pmu_core(const char *name) 1447d504fae9SJohn Garry { 14486fbd67b0SThomas Richter return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name); 14494bf7e81aSIan Rogers } 14504bf7e81aSIan Rogers 14516fd1e519SIan Rogers bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu) 14526fd1e519SIan Rogers { 1453e20d1f2fSIan Rogers return pmu->is_core; 14546fd1e519SIan Rogers } 14556fd1e519SIan Rogers 145652c7b4d3SIan Rogers bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) 145752c7b4d3SIan Rogers { 1458710dffc9SIan Rogers return !pmu->is_core || perf_pmus__num_core_pmus() == 1; 145952c7b4d3SIan Rogers } 146052c7b4d3SIan Rogers 14611eaf496eSIan Rogers bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name) 1462abe9544eSIan Rogers { 14634cabc3d1SAndi Kleen struct perf_pmu_alias *alias; 14644cabc3d1SAndi Kleen 14651eaf496eSIan Rogers list_for_each_entry(alias, &pmu->aliases, list) { 14664cabc3d1SAndi Kleen if (!strcmp(alias->name, name)) 14674cabc3d1SAndi Kleen return true; 14684cabc3d1SAndi Kleen } 14694cabc3d1SAndi Kleen return false; 14704cabc3d1SAndi Kleen } 14717d4bdab5SAdrian Hunter 1472251aa040SIan Rogers bool perf_pmu__is_software(const struct perf_pmu *pmu) 1473251aa040SIan Rogers { 1474251aa040SIan Rogers if (pmu->is_core || pmu->is_uncore || pmu->auxtrace) 1475251aa040SIan Rogers return false; 1476251aa040SIan Rogers switch (pmu->type) { 1477251aa040SIan Rogers case PERF_TYPE_HARDWARE: return false; 1478251aa040SIan Rogers case PERF_TYPE_SOFTWARE: return true; 1479251aa040SIan Rogers case PERF_TYPE_TRACEPOINT: return true; 1480251aa040SIan Rogers case PERF_TYPE_HW_CACHE: return false; 1481251aa040SIan Rogers case PERF_TYPE_RAW: return false; 1482251aa040SIan Rogers case PERF_TYPE_BREAKPOINT: return true; 1483251aa040SIan Rogers default: break; 1484251aa040SIan Rogers } 1485251aa040SIan Rogers return !strcmp(pmu->name, "kprobe") || !strcmp(pmu->name, "uprobe"); 1486251aa040SIan Rogers } 1487251aa040SIan Rogers 1488d50a79cdSJames Clark FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) 14897d4bdab5SAdrian Hunter { 14907d4bdab5SAdrian Hunter char path[PATH_MAX]; 14917d4bdab5SAdrian Hunter 1492f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name) || 1493f8ad6018SJames Clark !file_available(path)) 14947d4bdab5SAdrian Hunter return NULL; 14957d4bdab5SAdrian Hunter 14967d4bdab5SAdrian Hunter return fopen(path, "r"); 14977d4bdab5SAdrian Hunter } 14987d4bdab5SAdrian Hunter 14993a69672eSNamhyung Kim FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name) 15003a69672eSNamhyung Kim { 15013a69672eSNamhyung Kim int fd; 15023a69672eSNamhyung Kim 15033a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, pmu->name, name, O_RDONLY); 15043a69672eSNamhyung Kim if (fd < 0) 15053a69672eSNamhyung Kim return NULL; 15063a69672eSNamhyung Kim 15073a69672eSNamhyung Kim return fdopen(fd, "r"); 15083a69672eSNamhyung Kim } 15093a69672eSNamhyung Kim 15107d4bdab5SAdrian Hunter int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 15117d4bdab5SAdrian Hunter ...) 15127d4bdab5SAdrian Hunter { 15137d4bdab5SAdrian Hunter va_list args; 15147d4bdab5SAdrian Hunter FILE *file; 15157d4bdab5SAdrian Hunter int ret = EOF; 15167d4bdab5SAdrian Hunter 15177d4bdab5SAdrian Hunter va_start(args, fmt); 15187d4bdab5SAdrian Hunter file = perf_pmu__open_file(pmu, name); 15197d4bdab5SAdrian Hunter if (file) { 15207d4bdab5SAdrian Hunter ret = vfscanf(file, fmt, args); 15217d4bdab5SAdrian Hunter fclose(file); 15227d4bdab5SAdrian Hunter } 15237d4bdab5SAdrian Hunter va_end(args); 15247d4bdab5SAdrian Hunter return ret; 15257d4bdab5SAdrian Hunter } 15269fbc61f8SKan Liang 15273a69672eSNamhyung Kim int perf_pmu__scan_file_at(struct perf_pmu *pmu, int dirfd, const char *name, 15283a69672eSNamhyung Kim const char *fmt, ...) 15293a69672eSNamhyung Kim { 15303a69672eSNamhyung Kim va_list args; 15313a69672eSNamhyung Kim FILE *file; 15323a69672eSNamhyung Kim int ret = EOF; 15333a69672eSNamhyung Kim 15343a69672eSNamhyung Kim va_start(args, fmt); 15353a69672eSNamhyung Kim file = perf_pmu__open_file_at(pmu, dirfd, name); 15363a69672eSNamhyung Kim if (file) { 15373a69672eSNamhyung Kim ret = vfscanf(file, fmt, args); 15383a69672eSNamhyung Kim fclose(file); 15393a69672eSNamhyung Kim } 15403a69672eSNamhyung Kim va_end(args); 15413a69672eSNamhyung Kim return ret; 15423a69672eSNamhyung Kim } 15433a69672eSNamhyung Kim 1544c2b6a896SGerman Gomez bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name) 1545c2b6a896SGerman Gomez { 1546c2b6a896SGerman Gomez char path[PATH_MAX]; 1547c2b6a896SGerman Gomez 1548c2b6a896SGerman Gomez if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name)) 1549c2b6a896SGerman Gomez return false; 1550c2b6a896SGerman Gomez 1551c2b6a896SGerman Gomez return file_available(path); 1552c2b6a896SGerman Gomez } 1553c2b6a896SGerman Gomez 15549fbc61f8SKan Liang static int perf_pmu__new_caps(struct list_head *list, char *name, char *value) 15559fbc61f8SKan Liang { 15569fbc61f8SKan Liang struct perf_pmu_caps *caps = zalloc(sizeof(*caps)); 15579fbc61f8SKan Liang 15589fbc61f8SKan Liang if (!caps) 15599fbc61f8SKan Liang return -ENOMEM; 15609fbc61f8SKan Liang 15619fbc61f8SKan Liang caps->name = strdup(name); 15629fbc61f8SKan Liang if (!caps->name) 15639fbc61f8SKan Liang goto free_caps; 15649fbc61f8SKan Liang caps->value = strndup(value, strlen(value) - 1); 15659fbc61f8SKan Liang if (!caps->value) 15669fbc61f8SKan Liang goto free_name; 15679fbc61f8SKan Liang list_add_tail(&caps->list, list); 15689fbc61f8SKan Liang return 0; 15699fbc61f8SKan Liang 15709fbc61f8SKan Liang free_name: 157157f14b5aSArnaldo Carvalho de Melo zfree(&caps->name); 15729fbc61f8SKan Liang free_caps: 15739fbc61f8SKan Liang free(caps); 15749fbc61f8SKan Liang 15759fbc61f8SKan Liang return -ENOMEM; 15769fbc61f8SKan Liang } 15779fbc61f8SKan Liang 1578eec11310SNamhyung Kim static void perf_pmu__del_caps(struct perf_pmu *pmu) 1579eec11310SNamhyung Kim { 1580eec11310SNamhyung Kim struct perf_pmu_caps *caps, *tmp; 1581eec11310SNamhyung Kim 1582eec11310SNamhyung Kim list_for_each_entry_safe(caps, tmp, &pmu->caps, list) { 1583eec11310SNamhyung Kim list_del(&caps->list); 1584efe98a7aSArnaldo Carvalho de Melo zfree(&caps->name); 1585efe98a7aSArnaldo Carvalho de Melo zfree(&caps->value); 1586eec11310SNamhyung Kim free(caps); 1587eec11310SNamhyung Kim } 1588eec11310SNamhyung Kim } 1589eec11310SNamhyung Kim 15909fbc61f8SKan Liang /* 15919fbc61f8SKan Liang * Reading/parsing the given pmu capabilities, which should be located at: 15929fbc61f8SKan Liang * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes. 15939fbc61f8SKan Liang * Return the number of capabilities 15949fbc61f8SKan Liang */ 15959fbc61f8SKan Liang int perf_pmu__caps_parse(struct perf_pmu *pmu) 15969fbc61f8SKan Liang { 15979fbc61f8SKan Liang struct stat st; 15989fbc61f8SKan Liang char caps_path[PATH_MAX]; 15999fbc61f8SKan Liang DIR *caps_dir; 16009fbc61f8SKan Liang struct dirent *evt_ent; 1601b39094d3SNamhyung Kim int caps_fd; 16023339ec44SRavi Bangoria 16033339ec44SRavi Bangoria if (pmu->caps_initialized) 16043339ec44SRavi Bangoria return pmu->nr_caps; 16053339ec44SRavi Bangoria 16063339ec44SRavi Bangoria pmu->nr_caps = 0; 16079fbc61f8SKan Liang 1608f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(caps_path, sizeof(caps_path), pmu->name, "caps")) 16099fbc61f8SKan Liang return -1; 16109fbc61f8SKan Liang 16113339ec44SRavi Bangoria if (stat(caps_path, &st) < 0) { 16123339ec44SRavi Bangoria pmu->caps_initialized = true; 16139fbc61f8SKan Liang return 0; /* no error if caps does not exist */ 16143339ec44SRavi Bangoria } 16159fbc61f8SKan Liang 16169fbc61f8SKan Liang caps_dir = opendir(caps_path); 16179fbc61f8SKan Liang if (!caps_dir) 16189fbc61f8SKan Liang return -EINVAL; 16199fbc61f8SKan Liang 1620b39094d3SNamhyung Kim caps_fd = dirfd(caps_dir); 1621b39094d3SNamhyung Kim 16229fbc61f8SKan Liang while ((evt_ent = readdir(caps_dir)) != NULL) { 16239fbc61f8SKan Liang char *name = evt_ent->d_name; 16249fbc61f8SKan Liang char value[128]; 16259fbc61f8SKan Liang FILE *file; 1626b39094d3SNamhyung Kim int fd; 16279fbc61f8SKan Liang 16289fbc61f8SKan Liang if (!strcmp(name, ".") || !strcmp(name, "..")) 16299fbc61f8SKan Liang continue; 16309fbc61f8SKan Liang 1631b39094d3SNamhyung Kim fd = openat(caps_fd, name, O_RDONLY); 16320ea8920eSIan Rogers if (fd == -1) 16339fbc61f8SKan Liang continue; 16340ea8920eSIan Rogers file = fdopen(fd, "r"); 16350ea8920eSIan Rogers if (!file) { 16360ea8920eSIan Rogers close(fd); 16370ea8920eSIan Rogers continue; 16380ea8920eSIan Rogers } 16399fbc61f8SKan Liang 16409fbc61f8SKan Liang if (!fgets(value, sizeof(value), file) || 16419fbc61f8SKan Liang (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) { 16429fbc61f8SKan Liang fclose(file); 16439fbc61f8SKan Liang continue; 16449fbc61f8SKan Liang } 16459fbc61f8SKan Liang 16463339ec44SRavi Bangoria pmu->nr_caps++; 16479fbc61f8SKan Liang fclose(file); 16489fbc61f8SKan Liang } 16499fbc61f8SKan Liang 16509fbc61f8SKan Liang closedir(caps_dir); 16519fbc61f8SKan Liang 16523339ec44SRavi Bangoria pmu->caps_initialized = true; 16533339ec44SRavi Bangoria return pmu->nr_caps; 16549fbc61f8SKan Liang } 1655e4064776SJin Yao 1656b9f01032SIan Rogers static void perf_pmu__compute_config_masks(struct perf_pmu *pmu) 1657e4064776SJin Yao { 1658e4064776SJin Yao struct perf_pmu_format *format; 1659b9f01032SIan Rogers 1660b9f01032SIan Rogers if (pmu->config_masks_computed) 1661b9f01032SIan Rogers return; 1662e4064776SJin Yao 1663e4064776SJin Yao list_for_each_entry(format, &pmu->format, list) { 1664b9f01032SIan Rogers unsigned int i; 1665b9f01032SIan Rogers __u64 *mask; 1666b9f01032SIan Rogers 1667b9f01032SIan Rogers if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) 1668e4064776SJin Yao continue; 1669e4064776SJin Yao 1670b9f01032SIan Rogers pmu->config_masks_present = true; 1671b9f01032SIan Rogers mask = &pmu->config_masks[format->value]; 1672b9f01032SIan Rogers 1673e4064776SJin Yao for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS) 1674b9f01032SIan Rogers *mask |= 1ULL << i; 1675e4064776SJin Yao } 1676b9f01032SIan Rogers pmu->config_masks_computed = true; 1677b9f01032SIan Rogers } 1678b9f01032SIan Rogers 1679b9f01032SIan Rogers void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 1680b9f01032SIan Rogers const char *name, int config_num, 1681b9f01032SIan Rogers const char *config_name) 1682b9f01032SIan Rogers { 1683b9f01032SIan Rogers __u64 bits; 1684b9f01032SIan Rogers char buf[100]; 1685b9f01032SIan Rogers 1686b9f01032SIan Rogers perf_pmu__compute_config_masks(pmu); 1687e4064776SJin Yao 1688e4064776SJin Yao /* 1689e4064776SJin Yao * Kernel doesn't export any valid format bits. 1690e4064776SJin Yao */ 1691b9f01032SIan Rogers if (!pmu->config_masks_present) 1692e4064776SJin Yao return; 1693e4064776SJin Yao 1694b9f01032SIan Rogers bits = config & ~pmu->config_masks[config_num]; 1695e4064776SJin Yao if (bits == 0) 1696e4064776SJin Yao return; 1697e4064776SJin Yao 1698e4064776SJin Yao bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf)); 1699e4064776SJin Yao 1700b9f01032SIan Rogers pr_warning("WARNING: event '%s' not valid (bits %s of %s " 1701e4064776SJin Yao "'%llx' not supported by kernel)!\n", 1702b9f01032SIan Rogers name ?: "N/A", buf, config_name, config); 1703e4064776SJin Yao } 1704c5a26ea4SJin Yao 1705c47a5599SJin Yao int perf_pmu__match(char *pattern, char *name, char *tok) 1706c47a5599SJin Yao { 170713d60ba0SKan Liang if (!name) 170813d60ba0SKan Liang return -1; 170913d60ba0SKan Liang 1710c47a5599SJin Yao if (fnmatch(pattern, name, 0)) 1711c47a5599SJin Yao return -1; 1712c47a5599SJin Yao 1713240e6fd0SIan Rogers if (tok && !perf_pmu__match_ignoring_suffix(name, tok)) 1714c47a5599SJin Yao return -1; 1715c47a5599SJin Yao 1716c47a5599SJin Yao return 0; 1717c47a5599SJin Yao } 17181d3351e6SJin Yao 1719acef233bSJing Zhang double __weak perf_pmu__cpu_slots_per_cycle(void) 1720acef233bSJing Zhang { 1721acef233bSJing Zhang return NAN; 1722acef233bSJing Zhang } 1723f8ad6018SJames Clark 1724f8ad6018SJames Clark int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size) 1725f8ad6018SJames Clark { 1726f8ad6018SJames Clark const char *sysfs = sysfs__mountpoint(); 1727f8ad6018SJames Clark 1728f8ad6018SJames Clark if (!sysfs) 1729f8ad6018SJames Clark return 0; 1730f8ad6018SJames Clark return scnprintf(pathname, size, "%s/bus/event_source/devices/", sysfs); 1731f8ad6018SJames Clark } 1732f8ad6018SJames Clark 1733e293a5e8SNamhyung Kim int perf_pmu__event_source_devices_fd(void) 1734e293a5e8SNamhyung Kim { 1735e293a5e8SNamhyung Kim char path[PATH_MAX]; 1736e293a5e8SNamhyung Kim const char *sysfs = sysfs__mountpoint(); 1737e293a5e8SNamhyung Kim 1738e293a5e8SNamhyung Kim if (!sysfs) 1739e293a5e8SNamhyung Kim return -1; 1740e293a5e8SNamhyung Kim 1741e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs); 1742e293a5e8SNamhyung Kim return open(path, O_DIRECTORY); 1743e293a5e8SNamhyung Kim } 1744e293a5e8SNamhyung Kim 1745f8ad6018SJames Clark /* 1746f8ad6018SJames Clark * Fill 'buf' with the path to a file or folder in 'pmu_name' in 1747f8ad6018SJames Clark * sysfs. For example if pmu_name = "cs_etm" and 'filename' = "format" 1748f8ad6018SJames Clark * then pathname will be filled with 1749f8ad6018SJames Clark * "/sys/bus/event_source/devices/cs_etm/format" 1750f8ad6018SJames Clark * 1751e1a3aad3SIan Rogers * Return 0 if the sysfs mountpoint couldn't be found, if no characters were 1752e1a3aad3SIan Rogers * written or if the buffer size is exceeded. 1753f8ad6018SJames Clark */ 1754f8ad6018SJames Clark int perf_pmu__pathname_scnprintf(char *buf, size_t size, 1755f8ad6018SJames Clark const char *pmu_name, const char *filename) 1756f8ad6018SJames Clark { 1757e1a3aad3SIan Rogers size_t len; 1758f8ad6018SJames Clark 1759e1a3aad3SIan Rogers len = perf_pmu__event_source_devices_scnprintf(buf, size); 1760e1a3aad3SIan Rogers if (!len || (len + strlen(pmu_name) + strlen(filename) + 1) >= size) 1761f8ad6018SJames Clark return 0; 1762e1a3aad3SIan Rogers 1763e1a3aad3SIan Rogers return scnprintf(buf + len, size - len, "%s/%s", pmu_name, filename); 1764f8ad6018SJames Clark } 1765eec11310SNamhyung Kim 1766e293a5e8SNamhyung Kim int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags) 1767e293a5e8SNamhyung Kim { 1768e293a5e8SNamhyung Kim char path[PATH_MAX]; 1769e293a5e8SNamhyung Kim 1770e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/%s", pmu_name, filename); 1771e293a5e8SNamhyung Kim return openat(dirfd, path, flags); 1772e293a5e8SNamhyung Kim } 1773e293a5e8SNamhyung Kim 17741eaf496eSIan Rogers void perf_pmu__delete(struct perf_pmu *pmu) 1775eec11310SNamhyung Kim { 1776eec11310SNamhyung Kim perf_pmu__del_formats(&pmu->format); 1777eec11310SNamhyung Kim perf_pmu__del_aliases(pmu); 1778eec11310SNamhyung Kim perf_pmu__del_caps(pmu); 1779eec11310SNamhyung Kim 1780eec11310SNamhyung Kim perf_cpu_map__put(pmu->cpus); 1781eec11310SNamhyung Kim 1782efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->default_config); 1783efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 1784efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->alias_name); 1785eec11310SNamhyung Kim free(pmu); 1786eec11310SNamhyung Kim } 17879d5da30eSJames Clark 17889d5da30eSJames Clark struct perf_pmu *pmu__find_core_pmu(void) 17899d5da30eSJames Clark { 17909d5da30eSJames Clark struct perf_pmu *pmu = NULL; 17919d5da30eSJames Clark 17929d5da30eSJames Clark while ((pmu = perf_pmus__scan_core(pmu))) { 17939d5da30eSJames Clark /* 17949d5da30eSJames Clark * The cpumap should cover all CPUs. Otherwise, some CPUs may 17959d5da30eSJames Clark * not support some events or have different event IDs. 17969d5da30eSJames Clark */ 17979d5da30eSJames Clark if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu) 17989d5da30eSJames Clark return NULL; 17999d5da30eSJames Clark 18009d5da30eSJames Clark return pmu; 18019d5da30eSJames Clark } 18029d5da30eSJames Clark return NULL; 18039d5da30eSJames Clark } 1804