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 */ 61e293a5e8SNamhyung Kim int perf_pmu__format_parse(int dirfd, struct list_head *head) 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); 993d88aec0SIan Rogers ret = perf_pmu_parse(head, 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 */ 113e293a5e8SNamhyung Kim static int pmu_format(int dirfd, const char *name, struct list_head *format) 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 */ 122e293a5e8SNamhyung Kim if (perf_pmu__format_parse(fd, format)) 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 */ 511e293a5e8SNamhyung Kim static int pmu_aliases(int dirfd, const char *name, struct list_head *head) 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 */ 520e293a5e8SNamhyung Kim if (pmu_aliases_parse(fd, head)) 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 */ 773eeac7730SIan Rogers void pmu_add_cpu_aliases_table(struct list_head *head, struct perf_pmu *pmu, 7741ba3752aSIan Rogers const struct pmu_events_table *table) 775933f82ffSSukadev Bhattiprolu { 776660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data data = { 777660842e4SIan Rogers .head = head, 778d685819bSIan Rogers .default_pmu_name = perf_pmus__default_pmu_name(), 779660842e4SIan Rogers .pmu = pmu, 780660842e4SIan Rogers }; 781fedb2b51SAndi Kleen 782660842e4SIan Rogers pmu_events_table_for_each_event(table, pmu_add_cpu_aliases_map_callback, &data); 783d685819bSIan Rogers free(data.default_pmu_name); 784933f82ffSSukadev Bhattiprolu } 785933f82ffSSukadev Bhattiprolu 786e45ad701SJohn Garry static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) 787e45ad701SJohn Garry { 7881ba3752aSIan Rogers const struct pmu_events_table *table; 789e45ad701SJohn Garry 79096d2a746SIan Rogers table = perf_pmu__find_events_table(pmu); 791eeac7730SIan Rogers if (!table) 792e45ad701SJohn Garry return; 793e45ad701SJohn Garry 794eeac7730SIan Rogers pmu_add_cpu_aliases_table(head, pmu, table); 795e45ad701SJohn Garry } 796e45ad701SJohn Garry 7974513c719SJohn Garry struct pmu_sys_event_iter_data { 7984513c719SJohn Garry struct list_head *head; 7994513c719SJohn Garry struct perf_pmu *pmu; 8004513c719SJohn Garry }; 8014513c719SJohn Garry 80229be2fe0SIan Rogers static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, 8031ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 80429be2fe0SIan Rogers void *data) 8054513c719SJohn Garry { 8064513c719SJohn Garry struct pmu_sys_event_iter_data *idata = data; 8074513c719SJohn Garry struct perf_pmu *pmu = idata->pmu; 8084513c719SJohn Garry 8094513c719SJohn Garry if (!pe->compat || !pe->pmu) 8104513c719SJohn Garry return 0; 8114513c719SJohn Garry 8124513c719SJohn Garry if (!strcmp(pmu->id, pe->compat) && 8134513c719SJohn Garry pmu_uncore_alias_match(pe->pmu, pmu->name)) { 814e293a5e8SNamhyung Kim __perf_pmu__new_alias(idata->head, -1, 8154513c719SJohn Garry (char *)pe->name, 8164513c719SJohn Garry (char *)pe->desc, 8174513c719SJohn Garry (char *)pe->event, 818eab35953SJin Yao pe); 8194513c719SJohn Garry } 8204513c719SJohn Garry 8214513c719SJohn Garry return 0; 8224513c719SJohn Garry } 8234513c719SJohn Garry 824e199f47fSJohn Garry void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu) 8254513c719SJohn Garry { 8264513c719SJohn Garry struct pmu_sys_event_iter_data idata = { 8274513c719SJohn Garry .head = head, 8284513c719SJohn Garry .pmu = pmu, 8294513c719SJohn Garry }; 8304513c719SJohn Garry 8314513c719SJohn Garry if (!pmu->id) 8324513c719SJohn Garry return; 8334513c719SJohn Garry 8344513c719SJohn Garry pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, &idata); 8354513c719SJohn Garry } 8364513c719SJohn Garry 837c5de47f2SSukadev Bhattiprolu struct perf_event_attr * __weak 838dc0a6202SAdrian Hunter perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) 839dc0a6202SAdrian Hunter { 840dc0a6202SAdrian Hunter return NULL; 841dc0a6202SAdrian Hunter } 842dc0a6202SAdrian Hunter 84313d60ba0SKan Liang char * __weak 84413d60ba0SKan Liang pmu_find_real_name(const char *name) 84513d60ba0SKan Liang { 84613d60ba0SKan Liang return (char *)name; 84713d60ba0SKan Liang } 84813d60ba0SKan Liang 84913d60ba0SKan Liang char * __weak 85013d60ba0SKan Liang pmu_find_alias_name(const char *name __maybe_unused) 85113d60ba0SKan Liang { 85213d60ba0SKan Liang return NULL; 85313d60ba0SKan Liang } 85413d60ba0SKan Liang 8553a69672eSNamhyung Kim static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) 85690a86bdeSJiri Olsa { 85790a86bdeSJiri Olsa int max_precise = -1; 85890a86bdeSJiri Olsa 8593a69672eSNamhyung Kim perf_pmu__scan_file_at(pmu, dirfd, "caps/max_precise", "%d", &max_precise); 86090a86bdeSJiri Olsa return max_precise; 86190a86bdeSJiri Olsa } 86290a86bdeSJiri Olsa 8631eaf496eSIan Rogers struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *lookup_name) 864cd82a32eSJiri Olsa { 865cd82a32eSJiri Olsa struct perf_pmu *pmu; 866cd82a32eSJiri Olsa LIST_HEAD(format); 867a6146d50SZheng Yan LIST_HEAD(aliases); 868cd82a32eSJiri Olsa __u32 type; 86913d60ba0SKan Liang char *name = pmu_find_real_name(lookup_name); 87013d60ba0SKan Liang char *alias_name; 87149afa7f6SJin Yao 87249afa7f6SJin Yao /* 873cd82a32eSJiri Olsa * The pmu data we store & need consists of the pmu 874cd82a32eSJiri Olsa * type value and format definitions. Load both right 875cd82a32eSJiri Olsa * now. 876cd82a32eSJiri Olsa */ 877e293a5e8SNamhyung Kim if (pmu_format(dirfd, name, &format)) 878cd82a32eSJiri Olsa return NULL; 879cd82a32eSJiri Olsa 88015b22ed3SAndi Kleen /* 881f8ad6018SJames Clark * Check the aliases first to avoid unnecessary work. 88215b22ed3SAndi Kleen */ 883e293a5e8SNamhyung Kim if (pmu_aliases(dirfd, name, &aliases)) 8843fded963SJiri Olsa return NULL; 8853fded963SJiri Olsa 886cd82a32eSJiri Olsa pmu = zalloc(sizeof(*pmu)); 887cd82a32eSJiri Olsa if (!pmu) 888cd82a32eSJiri Olsa return NULL; 889cd82a32eSJiri Olsa 890d06593aaSIan Rogers pmu->is_core = is_pmu_core(name); 891d06593aaSIan Rogers pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core); 89254e32dc0SGanapatrao Kulkarni pmu->name = strdup(name); 89313d60ba0SKan Liang if (!pmu->name) 89413d60ba0SKan Liang goto err; 89513d60ba0SKan Liang 896f8ad6018SJames Clark /* Read type, and ensure that type value is successfully assigned (return 1) */ 8973a69672eSNamhyung Kim if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1) 898f8ad6018SJames Clark goto err; 899f8ad6018SJames Clark 90013d60ba0SKan Liang alias_name = pmu_find_alias_name(name); 90113d60ba0SKan Liang if (alias_name) { 90213d60ba0SKan Liang pmu->alias_name = strdup(alias_name); 90313d60ba0SKan Liang if (!pmu->alias_name) 90413d60ba0SKan Liang goto err; 90513d60ba0SKan Liang } 90613d60ba0SKan Liang 90754e32dc0SGanapatrao Kulkarni pmu->type = type; 9083a69672eSNamhyung Kim pmu->is_uncore = pmu_is_uncore(dirfd, name); 90951d54847SJohn Garry if (pmu->is_uncore) 91051d54847SJohn Garry pmu->id = pmu_id(name); 9113a69672eSNamhyung Kim pmu->max_precise = pmu_max_precise(dirfd, pmu); 91254e32dc0SGanapatrao Kulkarni pmu_add_cpu_aliases(&aliases, pmu); 9134513c719SJohn Garry pmu_add_sys_aliases(&aliases, pmu); 91466ec1191SMark Rutland 915cd82a32eSJiri Olsa INIT_LIST_HEAD(&pmu->format); 916a6146d50SZheng Yan INIT_LIST_HEAD(&pmu->aliases); 9179fbc61f8SKan Liang INIT_LIST_HEAD(&pmu->caps); 918cd82a32eSJiri Olsa list_splice(&format, &pmu->format); 919a6146d50SZheng Yan list_splice(&aliases, &pmu->aliases); 9201eaf496eSIan Rogers list_add_tail(&pmu->list, pmus); 921dc0a6202SAdrian Hunter 922dc0a6202SAdrian Hunter pmu->default_config = perf_pmu__get_default_config(pmu); 923dc0a6202SAdrian Hunter 924cd82a32eSJiri Olsa return pmu; 92513d60ba0SKan Liang err: 926efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 92713d60ba0SKan Liang free(pmu); 92813d60ba0SKan Liang return NULL; 929cd82a32eSJiri Olsa } 930cd82a32eSJiri Olsa 931628eaa4eSIan Rogers /* Creates the PMU when sysfs scanning fails. */ 932628eaa4eSIan Rogers struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus) 933628eaa4eSIan Rogers { 934628eaa4eSIan Rogers struct perf_pmu *pmu = zalloc(sizeof(*pmu)); 935628eaa4eSIan Rogers 936628eaa4eSIan Rogers if (!pmu) 937628eaa4eSIan Rogers return NULL; 938628eaa4eSIan Rogers 939628eaa4eSIan Rogers pmu->name = strdup("cpu"); 940628eaa4eSIan Rogers if (!pmu->name) { 941628eaa4eSIan Rogers free(pmu); 942628eaa4eSIan Rogers return NULL; 943628eaa4eSIan Rogers } 944628eaa4eSIan Rogers 945628eaa4eSIan Rogers pmu->is_core = true; 946628eaa4eSIan Rogers pmu->type = PERF_TYPE_RAW; 947628eaa4eSIan Rogers pmu->cpus = cpu_map__online(); 948628eaa4eSIan Rogers 949628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->format); 950628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 951628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->caps); 952628eaa4eSIan Rogers list_add_tail(&pmu->list, core_pmus); 953628eaa4eSIan Rogers return pmu; 954628eaa4eSIan Rogers } 955628eaa4eSIan Rogers 956e552b7beSRob Herring void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu) 957e552b7beSRob Herring { 958e552b7beSRob Herring struct perf_pmu_format *format; 959e552b7beSRob Herring 96068c25043SIan Rogers if (pmu->formats_checked) 96168c25043SIan Rogers return; 96268c25043SIan Rogers 96368c25043SIan Rogers pmu->formats_checked = true; 96468c25043SIan Rogers 965e552b7beSRob Herring /* fake pmu doesn't have format list */ 966e552b7beSRob Herring if (pmu == &perf_pmu__fake) 967e552b7beSRob Herring return; 968e552b7beSRob Herring 969e552b7beSRob Herring list_for_each_entry(format, &pmu->format, list) 970e552b7beSRob Herring if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) { 971e552b7beSRob Herring pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'" 972e552b7beSRob Herring "which is not supported by this version of perf!\n", 973e552b7beSRob Herring pmu->name, format->name, format->value); 974e552b7beSRob Herring return; 975e552b7beSRob Herring } 976e552b7beSRob Herring } 977e552b7beSRob Herring 978c6d616feSIan Rogers bool evsel__is_aux_event(const struct evsel *evsel) 979e12ee9f7SAdrian Hunter { 980e76026bdSArnaldo Carvalho de Melo struct perf_pmu *pmu = evsel__find_pmu(evsel); 981e12ee9f7SAdrian Hunter 982e12ee9f7SAdrian Hunter return pmu && pmu->auxtrace; 983e12ee9f7SAdrian Hunter } 984e12ee9f7SAdrian Hunter 9856593f019SJames Clark /* 9866593f019SJames Clark * Set @config_name to @val as long as the user hasn't already set or cleared it 9876593f019SJames Clark * by passing a config term on the command line. 9886593f019SJames Clark * 9896593f019SJames Clark * @val is the value to put into the bits specified by @config_name rather than 9906593f019SJames Clark * the bit pattern. It is shifted into position by this function, so to set 9916593f019SJames Clark * something to true, pass 1 for val rather than a pre shifted value. 9926593f019SJames Clark */ 9936593f019SJames Clark #define field_prep(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask)) 9946593f019SJames Clark void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, 9956593f019SJames Clark const char *config_name, u64 val) 9966593f019SJames Clark { 9976593f019SJames Clark u64 user_bits = 0, bits; 9986593f019SJames Clark struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG); 9996593f019SJames Clark 10006593f019SJames Clark if (term) 10016593f019SJames Clark user_bits = term->val.cfg_chg; 10026593f019SJames Clark 10036593f019SJames Clark bits = perf_pmu__format_bits(&pmu->format, config_name); 10046593f019SJames Clark 10056593f019SJames Clark /* Do nothing if the user changed the value */ 10066593f019SJames Clark if (bits & user_bits) 10076593f019SJames Clark return; 10086593f019SJames Clark 10096593f019SJames Clark /* Otherwise replace it */ 10106593f019SJames Clark evsel->core.attr.config &= ~bits; 10116593f019SJames Clark evsel->core.attr.config |= field_prep(bits, val); 10126593f019SJames Clark } 10136593f019SJames Clark 10145c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_format * 101509ff6071SAdrian Hunter pmu_find_format(struct list_head *formats, const char *name) 1016cd82a32eSJiri Olsa { 10175c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1018cd82a32eSJiri Olsa 1019cd82a32eSJiri Olsa list_for_each_entry(format, formats, list) 1020cd82a32eSJiri Olsa if (!strcmp(format->name, name)) 1021cd82a32eSJiri Olsa return format; 1022cd82a32eSJiri Olsa 1023cd82a32eSJiri Olsa return NULL; 1024cd82a32eSJiri Olsa } 1025cd82a32eSJiri Olsa 102609ff6071SAdrian Hunter __u64 perf_pmu__format_bits(struct list_head *formats, const char *name) 102709ff6071SAdrian Hunter { 102809ff6071SAdrian Hunter struct perf_pmu_format *format = pmu_find_format(formats, name); 102909ff6071SAdrian Hunter __u64 bits = 0; 103009ff6071SAdrian Hunter int fbit; 103109ff6071SAdrian Hunter 103209ff6071SAdrian Hunter if (!format) 103309ff6071SAdrian Hunter return 0; 103409ff6071SAdrian Hunter 103509ff6071SAdrian Hunter for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS) 103609ff6071SAdrian Hunter bits |= 1ULL << fbit; 103709ff6071SAdrian Hunter 103809ff6071SAdrian Hunter return bits; 103909ff6071SAdrian Hunter } 104009ff6071SAdrian Hunter 1041a1ac7de6SAdrian Hunter int perf_pmu__format_type(struct list_head *formats, const char *name) 1042a1ac7de6SAdrian Hunter { 1043a1ac7de6SAdrian Hunter struct perf_pmu_format *format = pmu_find_format(formats, name); 1044a1ac7de6SAdrian Hunter 1045a1ac7de6SAdrian Hunter if (!format) 1046a1ac7de6SAdrian Hunter return -1; 1047a1ac7de6SAdrian Hunter 1048a1ac7de6SAdrian Hunter return format->value; 1049a1ac7de6SAdrian Hunter } 1050a1ac7de6SAdrian Hunter 1051cd82a32eSJiri Olsa /* 1052dc0a6202SAdrian Hunter * Sets value based on the format definition (format parameter) 10534d39c89fSIngo Molnar * and unformatted value (value parameter). 1054cd82a32eSJiri Olsa */ 1055dc0a6202SAdrian Hunter static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, 1056dc0a6202SAdrian Hunter bool zero) 1057cd82a32eSJiri Olsa { 1058cd82a32eSJiri Olsa unsigned long fbit, vbit; 1059cd82a32eSJiri Olsa 1060cd82a32eSJiri Olsa for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 1061cd82a32eSJiri Olsa 1062cd82a32eSJiri Olsa if (!test_bit(fbit, format)) 1063cd82a32eSJiri Olsa continue; 1064cd82a32eSJiri Olsa 1065dc0a6202SAdrian Hunter if (value & (1llu << vbit++)) 1066dc0a6202SAdrian Hunter *v |= (1llu << fbit); 1067dc0a6202SAdrian Hunter else if (zero) 1068dc0a6202SAdrian Hunter *v &= ~(1llu << fbit); 1069cd82a32eSJiri Olsa } 1070cd82a32eSJiri Olsa } 1071cd82a32eSJiri Olsa 10720efe6b67SAdrian Hunter static __u64 pmu_format_max_value(const unsigned long *format) 10730efe6b67SAdrian Hunter { 10741b9caa10SJiri Olsa int w; 10750efe6b67SAdrian Hunter 10761b9caa10SJiri Olsa w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); 10771b9caa10SJiri Olsa if (!w) 10781b9caa10SJiri Olsa return 0; 10791b9caa10SJiri Olsa if (w < 64) 10801b9caa10SJiri Olsa return (1ULL << w) - 1; 10811b9caa10SJiri Olsa return -1; 10820efe6b67SAdrian Hunter } 10830efe6b67SAdrian Hunter 1084cd82a32eSJiri Olsa /* 1085688d4dfcSCody P Schafer * Term is a string term, and might be a param-term. Try to look up it's value 1086688d4dfcSCody P Schafer * in the remaining terms. 1087688d4dfcSCody P Schafer * - We have a term like "base-or-format-term=param-term", 1088688d4dfcSCody P Schafer * - We need to find the value supplied for "param-term" (with param-term named 1089688d4dfcSCody P Schafer * in a config string) later on in the term list. 1090688d4dfcSCody P Schafer */ 1091688d4dfcSCody P Schafer static int pmu_resolve_param_term(struct parse_events_term *term, 1092688d4dfcSCody P Schafer struct list_head *head_terms, 1093688d4dfcSCody P Schafer __u64 *value) 1094688d4dfcSCody P Schafer { 1095688d4dfcSCody P Schafer struct parse_events_term *t; 1096688d4dfcSCody P Schafer 1097688d4dfcSCody P Schafer list_for_each_entry(t, head_terms, list) { 10982a3d252dSIan Rogers if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM && 10992a3d252dSIan Rogers t->config && !strcmp(t->config, term->config)) { 1100688d4dfcSCody P Schafer t->used = true; 1101688d4dfcSCody P Schafer *value = t->val.num; 1102688d4dfcSCody P Schafer return 0; 1103688d4dfcSCody P Schafer } 1104688d4dfcSCody P Schafer } 1105688d4dfcSCody P Schafer 1106bb963e16SNamhyung Kim if (verbose > 0) 1107688d4dfcSCody P Schafer printf("Required parameter '%s' not specified\n", term->config); 1108688d4dfcSCody P Schafer 1109688d4dfcSCody P Schafer return -1; 1110688d4dfcSCody P Schafer } 1111688d4dfcSCody P Schafer 1112ffeb883eSHe Kuang static char *pmu_formats_string(struct list_head *formats) 1113e64b020bSJiri Olsa { 1114e64b020bSJiri Olsa struct perf_pmu_format *format; 111511db4e29SMasami Hiramatsu char *str = NULL; 111611db4e29SMasami Hiramatsu struct strbuf buf = STRBUF_INIT; 1117f1417ceaSXin Gao unsigned int i = 0; 1118e64b020bSJiri Olsa 1119ffeb883eSHe Kuang if (!formats) 1120e64b020bSJiri Olsa return NULL; 1121e64b020bSJiri Olsa 1122e64b020bSJiri Olsa /* sysfs exported terms */ 1123ffeb883eSHe Kuang list_for_each_entry(format, formats, list) 112411db4e29SMasami Hiramatsu if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0) 112511db4e29SMasami Hiramatsu goto error; 1126e64b020bSJiri Olsa 1127ffeb883eSHe Kuang str = strbuf_detach(&buf, NULL); 112811db4e29SMasami Hiramatsu error: 1129ffeb883eSHe Kuang strbuf_release(&buf); 1130e64b020bSJiri Olsa 1131e64b020bSJiri Olsa return str; 1132e64b020bSJiri Olsa } 1133e64b020bSJiri Olsa 1134688d4dfcSCody P Schafer /* 1135cd82a32eSJiri Olsa * Setup one of config[12] attr members based on the 113688aca8d9SCody P Schafer * user input data - term parameter. 1137cd82a32eSJiri Olsa */ 1138*804fee5dSIan Rogers static int pmu_config_term(struct perf_pmu *pmu, 1139cd82a32eSJiri Olsa struct perf_event_attr *attr, 1140dc0a6202SAdrian Hunter struct parse_events_term *term, 1141688d4dfcSCody P Schafer struct list_head *head_terms, 1142e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1143cd82a32eSJiri Olsa { 11445c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1145cd82a32eSJiri Olsa __u64 *vp; 11460efe6b67SAdrian Hunter __u64 val, max_val; 1147cd82a32eSJiri Olsa 1148cd82a32eSJiri Olsa /* 1149688d4dfcSCody P Schafer * If this is a parameter we've already used for parameterized-eval, 1150688d4dfcSCody P Schafer * skip it in normal eval. 1151688d4dfcSCody P Schafer */ 1152688d4dfcSCody P Schafer if (term->used) 1153688d4dfcSCody P Schafer return 0; 1154688d4dfcSCody P Schafer 1155688d4dfcSCody P Schafer /* 1156cd82a32eSJiri Olsa * Hardcoded terms should be already in, so nothing 1157cd82a32eSJiri Olsa * to be done for them. 1158cd82a32eSJiri Olsa */ 1159cd82a32eSJiri Olsa if (parse_events__is_hardcoded_term(term)) 1160cd82a32eSJiri Olsa return 0; 1161cd82a32eSJiri Olsa 1162*804fee5dSIan Rogers format = pmu_find_format(&pmu->format, term->config); 1163688d4dfcSCody P Schafer if (!format) { 1164*804fee5dSIan Rogers char *pmu_term = pmu_formats_string(&pmu->format); 11654ac22b48SIan Rogers char *unknown_term; 11664ac22b48SIan Rogers char *help_msg; 1167ffeb883eSHe Kuang 11684ac22b48SIan Rogers if (asprintf(&unknown_term, 11694ac22b48SIan Rogers "unknown term '%s' for pmu '%s'", 1170*804fee5dSIan Rogers term->config, pmu->name) < 0) 11714ac22b48SIan Rogers unknown_term = NULL; 11724ac22b48SIan Rogers help_msg = parse_events_formats_error_string(pmu_term); 11734ac22b48SIan Rogers if (err) { 11746c191289SIan Rogers parse_events_error__handle(err, term->err_term, 11754ac22b48SIan Rogers unknown_term, 11764ac22b48SIan Rogers help_msg); 11774ac22b48SIan Rogers } else { 11784ac22b48SIan Rogers pr_debug("%s (%s)\n", unknown_term, help_msg); 11794ac22b48SIan Rogers free(unknown_term); 1180e64b020bSJiri Olsa } 11814ac22b48SIan Rogers free(pmu_term); 1182cd82a32eSJiri Olsa return -EINVAL; 1183688d4dfcSCody P Schafer } 1184cd82a32eSJiri Olsa 1185cd82a32eSJiri Olsa switch (format->value) { 1186cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG: 1187cd82a32eSJiri Olsa vp = &attr->config; 1188cd82a32eSJiri Olsa break; 1189cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG1: 1190cd82a32eSJiri Olsa vp = &attr->config1; 1191cd82a32eSJiri Olsa break; 1192cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG2: 1193cd82a32eSJiri Olsa vp = &attr->config2; 1194cd82a32eSJiri Olsa break; 1195204e7c49SRob Herring case PERF_PMU_FORMAT_VALUE_CONFIG3: 1196204e7c49SRob Herring vp = &attr->config3; 1197204e7c49SRob Herring break; 1198cd82a32eSJiri Olsa default: 1199cd82a32eSJiri Olsa return -EINVAL; 1200cd82a32eSJiri Olsa } 1201cd82a32eSJiri Olsa 120216fa7e82SJiri Olsa /* 1203688d4dfcSCody P Schafer * Either directly use a numeric term, or try to translate string terms 1204688d4dfcSCody P Schafer * using event parameters. 120516fa7e82SJiri Olsa */ 120699e7138eSJiri Olsa if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 120799e7138eSJiri Olsa if (term->no_value && 120899e7138eSJiri Olsa bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) { 120999e7138eSJiri Olsa if (err) { 12106c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1211448d732cSIan Rogers strdup("no value assigned for term"), 1212448d732cSIan Rogers NULL); 121399e7138eSJiri Olsa } 121499e7138eSJiri Olsa return -EINVAL; 121599e7138eSJiri Olsa } 121699e7138eSJiri Olsa 1217688d4dfcSCody P Schafer val = term->val.num; 121899e7138eSJiri Olsa } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1219688d4dfcSCody P Schafer if (strcmp(term->val.str, "?")) { 1220bb963e16SNamhyung Kim if (verbose > 0) { 1221688d4dfcSCody P Schafer pr_info("Invalid sysfs entry %s=%s\n", 1222688d4dfcSCody P Schafer term->config, term->val.str); 1223e64b020bSJiri Olsa } 1224e64b020bSJiri Olsa if (err) { 12256c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1226448d732cSIan Rogers strdup("expected numeric value"), 1227448d732cSIan Rogers NULL); 1228e64b020bSJiri Olsa } 1229688d4dfcSCody P Schafer return -EINVAL; 1230688d4dfcSCody P Schafer } 1231688d4dfcSCody P Schafer 1232688d4dfcSCody P Schafer if (pmu_resolve_param_term(term, head_terms, &val)) 1233688d4dfcSCody P Schafer return -EINVAL; 1234688d4dfcSCody P Schafer } else 1235688d4dfcSCody P Schafer return -EINVAL; 1236688d4dfcSCody P Schafer 12370efe6b67SAdrian Hunter max_val = pmu_format_max_value(format->bits); 12380efe6b67SAdrian Hunter if (val > max_val) { 12390efe6b67SAdrian Hunter if (err) { 1240448d732cSIan Rogers char *err_str; 1241448d732cSIan Rogers 12426c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1243448d732cSIan Rogers asprintf(&err_str, 12440efe6b67SAdrian Hunter "value too big for format, maximum is %llu", 1245448d732cSIan Rogers (unsigned long long)max_val) < 0 1246448d732cSIan Rogers ? strdup("value too big for format") 1247448d732cSIan Rogers : err_str, 1248448d732cSIan Rogers NULL); 12490efe6b67SAdrian Hunter return -EINVAL; 12500efe6b67SAdrian Hunter } 12510efe6b67SAdrian Hunter /* 12520efe6b67SAdrian Hunter * Assume we don't care if !err, in which case the value will be 12530efe6b67SAdrian Hunter * silently truncated. 12540efe6b67SAdrian Hunter */ 12550efe6b67SAdrian Hunter } 12560efe6b67SAdrian Hunter 1257688d4dfcSCody P Schafer pmu_format_value(format->bits, val, vp, zero); 1258cd82a32eSJiri Olsa return 0; 1259cd82a32eSJiri Olsa } 1260cd82a32eSJiri Olsa 1261*804fee5dSIan Rogers int perf_pmu__config_terms(struct perf_pmu *pmu, 1262cff7f956SJiri Olsa struct perf_event_attr *attr, 1263dc0a6202SAdrian Hunter struct list_head *head_terms, 1264e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1265cd82a32eSJiri Olsa { 12666cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 1267cd82a32eSJiri Olsa 1268688d4dfcSCody P Schafer list_for_each_entry(term, head_terms, list) { 1269*804fee5dSIan Rogers if (pmu_config_term(pmu, attr, term, head_terms, zero, err)) 1270cd82a32eSJiri Olsa return -EINVAL; 1271688d4dfcSCody P Schafer } 1272cd82a32eSJiri Olsa 1273cd82a32eSJiri Olsa return 0; 1274cd82a32eSJiri Olsa } 1275cd82a32eSJiri Olsa 1276cd82a32eSJiri Olsa /* 1277cd82a32eSJiri Olsa * Configures event's 'attr' parameter based on the: 1278cd82a32eSJiri Olsa * 1) users input - specified in terms parameter 1279cd82a32eSJiri Olsa * 2) pmu format definitions - specified by pmu parameter 1280cd82a32eSJiri Olsa */ 1281cd82a32eSJiri Olsa int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 1282e64b020bSJiri Olsa struct list_head *head_terms, 1283e64b020bSJiri Olsa struct parse_events_error *err) 1284cd82a32eSJiri Olsa { 1285dc0a6202SAdrian Hunter bool zero = !!pmu->default_config; 1286dc0a6202SAdrian Hunter 1287*804fee5dSIan Rogers return perf_pmu__config_terms(pmu, attr, head_terms, zero, err); 1288cd82a32eSJiri Olsa } 1289cd82a32eSJiri Olsa 12905c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 12916cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 1292a6146d50SZheng Yan { 12935c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1294a6146d50SZheng Yan char *name; 1295a6146d50SZheng Yan 1296a6146d50SZheng Yan if (parse_events__is_hardcoded_term(term)) 1297a6146d50SZheng Yan return NULL; 1298a6146d50SZheng Yan 1299a6146d50SZheng Yan if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 1300a6146d50SZheng Yan if (term->val.num != 1) 1301a6146d50SZheng Yan return NULL; 1302a6146d50SZheng Yan if (pmu_find_format(&pmu->format, term->config)) 1303a6146d50SZheng Yan return NULL; 1304a6146d50SZheng Yan name = term->config; 1305a6146d50SZheng Yan } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1306a6146d50SZheng Yan if (strcasecmp(term->config, "event")) 1307a6146d50SZheng Yan return NULL; 1308a6146d50SZheng Yan name = term->val.str; 1309a6146d50SZheng Yan } else { 1310a6146d50SZheng Yan return NULL; 1311a6146d50SZheng Yan } 1312a6146d50SZheng Yan 1313a6146d50SZheng Yan list_for_each_entry(alias, &pmu->aliases, list) { 1314a6146d50SZheng Yan if (!strcasecmp(alias->name, name)) 1315a6146d50SZheng Yan return alias; 1316a6146d50SZheng Yan } 1317a6146d50SZheng Yan return NULL; 1318a6146d50SZheng Yan } 1319a6146d50SZheng Yan 1320410136f5SStephane Eranian 13211d9e446bSJiri Olsa static int check_info_data(struct perf_pmu_alias *alias, 13221d9e446bSJiri Olsa struct perf_pmu_info *info) 1323410136f5SStephane Eranian { 1324410136f5SStephane Eranian /* 1325410136f5SStephane Eranian * Only one term in event definition can 13261d9e446bSJiri Olsa * define unit, scale and snapshot, fail 13271d9e446bSJiri Olsa * if there's more than one. 1328410136f5SStephane Eranian */ 1329b30a7d1fSArnaldo Carvalho de Melo if ((info->unit && alias->unit[0]) || 13301d9e446bSJiri Olsa (info->scale && alias->scale) || 13311d9e446bSJiri Olsa (info->snapshot && alias->snapshot)) 1332410136f5SStephane Eranian return -EINVAL; 1333410136f5SStephane Eranian 1334b30a7d1fSArnaldo Carvalho de Melo if (alias->unit[0]) 13351d9e446bSJiri Olsa info->unit = alias->unit; 1336410136f5SStephane Eranian 1337410136f5SStephane Eranian if (alias->scale) 13381d9e446bSJiri Olsa info->scale = alias->scale; 13391d9e446bSJiri Olsa 13401d9e446bSJiri Olsa if (alias->snapshot) 13411d9e446bSJiri Olsa info->snapshot = alias->snapshot; 1342410136f5SStephane Eranian 1343410136f5SStephane Eranian return 0; 1344410136f5SStephane Eranian } 1345410136f5SStephane Eranian 1346a6146d50SZheng Yan /* 1347a6146d50SZheng Yan * Find alias in the terms list and replace it with the terms 1348a6146d50SZheng Yan * defined for the alias 1349a6146d50SZheng Yan */ 1350410136f5SStephane Eranian int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 135146441bdcSMatt Fleming struct perf_pmu_info *info) 1352a6146d50SZheng Yan { 13536cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 13545c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1355a6146d50SZheng Yan int ret; 1356a6146d50SZheng Yan 1357044330c1SMatt Fleming info->per_pkg = false; 1358044330c1SMatt Fleming 13598a398897SStephane Eranian /* 13608a398897SStephane Eranian * Mark unit and scale as not set 13618a398897SStephane Eranian * (different from default values, see below) 13628a398897SStephane Eranian */ 136346441bdcSMatt Fleming info->unit = NULL; 136446441bdcSMatt Fleming info->scale = 0.0; 13651d9e446bSJiri Olsa info->snapshot = false; 1366410136f5SStephane Eranian 1367a6146d50SZheng Yan list_for_each_entry_safe(term, h, head_terms, list) { 1368a6146d50SZheng Yan alias = pmu_find_alias(pmu, term); 1369a6146d50SZheng Yan if (!alias) 1370a6146d50SZheng Yan continue; 1371a6146d50SZheng Yan ret = pmu_alias_terms(alias, &term->list); 1372a6146d50SZheng Yan if (ret) 1373a6146d50SZheng Yan return ret; 1374410136f5SStephane Eranian 13751d9e446bSJiri Olsa ret = check_info_data(alias, info); 1376410136f5SStephane Eranian if (ret) 1377410136f5SStephane Eranian return ret; 1378410136f5SStephane Eranian 1379044330c1SMatt Fleming if (alias->per_pkg) 1380044330c1SMatt Fleming info->per_pkg = true; 1381044330c1SMatt Fleming 1382e56fbc9dSArnaldo Carvalho de Melo list_del_init(&term->list); 13831dc92556SIan Rogers parse_events_term__delete(term); 1384a6146d50SZheng Yan } 13858a398897SStephane Eranian 13868a398897SStephane Eranian /* 13878a398897SStephane Eranian * if no unit or scale found in aliases, then 13888a398897SStephane Eranian * set defaults as for evsel 13898a398897SStephane Eranian * unit cannot left to NULL 13908a398897SStephane Eranian */ 139146441bdcSMatt Fleming if (info->unit == NULL) 139246441bdcSMatt Fleming info->unit = ""; 13938a398897SStephane Eranian 139446441bdcSMatt Fleming if (info->scale == 0.0) 139546441bdcSMatt Fleming info->scale = 1.0; 13968a398897SStephane Eranian 1397a6146d50SZheng Yan return 0; 1398a6146d50SZheng Yan } 1399a6146d50SZheng Yan 1400cd82a32eSJiri Olsa int perf_pmu__new_format(struct list_head *list, char *name, 1401cd82a32eSJiri Olsa int config, unsigned long *bits) 1402cd82a32eSJiri Olsa { 14035c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1404cd82a32eSJiri Olsa 1405cd82a32eSJiri Olsa format = zalloc(sizeof(*format)); 1406cd82a32eSJiri Olsa if (!format) 1407cd82a32eSJiri Olsa return -ENOMEM; 1408cd82a32eSJiri Olsa 1409cd82a32eSJiri Olsa format->name = strdup(name); 1410cd82a32eSJiri Olsa format->value = config; 1411cd82a32eSJiri Olsa memcpy(format->bits, bits, sizeof(format->bits)); 1412cd82a32eSJiri Olsa 1413cd82a32eSJiri Olsa list_add_tail(&format->list, list); 1414cd82a32eSJiri Olsa return 0; 1415cd82a32eSJiri Olsa } 1416cd82a32eSJiri Olsa 1417*804fee5dSIan Rogers static void perf_pmu__del_formats(struct list_head *formats) 1418d26383dcSNamhyung Kim { 1419d26383dcSNamhyung Kim struct perf_pmu_format *fmt, *tmp; 1420d26383dcSNamhyung Kim 1421d26383dcSNamhyung Kim list_for_each_entry_safe(fmt, tmp, formats, list) { 1422d26383dcSNamhyung Kim list_del(&fmt->list); 1423efe98a7aSArnaldo Carvalho de Melo zfree(&fmt->name); 1424d26383dcSNamhyung Kim free(fmt); 1425d26383dcSNamhyung Kim } 1426d26383dcSNamhyung Kim } 1427d26383dcSNamhyung Kim 142807d2b820SIan Rogers bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name) 142907d2b820SIan Rogers { 143007d2b820SIan Rogers struct perf_pmu_format *format; 143107d2b820SIan Rogers 143207d2b820SIan Rogers list_for_each_entry(format, &pmu->format, list) { 143307d2b820SIan Rogers if (!strcmp(format->name, name)) 143407d2b820SIan Rogers return true; 143507d2b820SIan Rogers } 143607d2b820SIan Rogers return false; 143707d2b820SIan Rogers } 143807d2b820SIan Rogers 1439d504fae9SJohn Garry bool is_pmu_core(const char *name) 1440d504fae9SJohn Garry { 14416fbd67b0SThomas Richter return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name); 14424bf7e81aSIan Rogers } 14434bf7e81aSIan Rogers 14446fd1e519SIan Rogers bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu) 14456fd1e519SIan Rogers { 1446e20d1f2fSIan Rogers return pmu->is_core; 14476fd1e519SIan Rogers } 14486fd1e519SIan Rogers 144952c7b4d3SIan Rogers bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) 145052c7b4d3SIan Rogers { 1451710dffc9SIan Rogers return !pmu->is_core || perf_pmus__num_core_pmus() == 1; 145252c7b4d3SIan Rogers } 145352c7b4d3SIan Rogers 14541eaf496eSIan Rogers bool perf_pmu__have_event(const struct perf_pmu *pmu, const char *name) 1455abe9544eSIan Rogers { 14564cabc3d1SAndi Kleen struct perf_pmu_alias *alias; 14574cabc3d1SAndi Kleen 14581eaf496eSIan Rogers list_for_each_entry(alias, &pmu->aliases, list) { 14594cabc3d1SAndi Kleen if (!strcmp(alias->name, name)) 14604cabc3d1SAndi Kleen return true; 14614cabc3d1SAndi Kleen } 14624cabc3d1SAndi Kleen return false; 14634cabc3d1SAndi Kleen } 14647d4bdab5SAdrian Hunter 1465251aa040SIan Rogers bool perf_pmu__is_software(const struct perf_pmu *pmu) 1466251aa040SIan Rogers { 1467251aa040SIan Rogers if (pmu->is_core || pmu->is_uncore || pmu->auxtrace) 1468251aa040SIan Rogers return false; 1469251aa040SIan Rogers switch (pmu->type) { 1470251aa040SIan Rogers case PERF_TYPE_HARDWARE: return false; 1471251aa040SIan Rogers case PERF_TYPE_SOFTWARE: return true; 1472251aa040SIan Rogers case PERF_TYPE_TRACEPOINT: return true; 1473251aa040SIan Rogers case PERF_TYPE_HW_CACHE: return false; 1474251aa040SIan Rogers case PERF_TYPE_RAW: return false; 1475251aa040SIan Rogers case PERF_TYPE_BREAKPOINT: return true; 1476251aa040SIan Rogers default: break; 1477251aa040SIan Rogers } 1478251aa040SIan Rogers return !strcmp(pmu->name, "kprobe") || !strcmp(pmu->name, "uprobe"); 1479251aa040SIan Rogers } 1480251aa040SIan Rogers 1481d50a79cdSJames Clark FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) 14827d4bdab5SAdrian Hunter { 14837d4bdab5SAdrian Hunter char path[PATH_MAX]; 14847d4bdab5SAdrian Hunter 1485f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name) || 1486f8ad6018SJames Clark !file_available(path)) 14877d4bdab5SAdrian Hunter return NULL; 14887d4bdab5SAdrian Hunter 14897d4bdab5SAdrian Hunter return fopen(path, "r"); 14907d4bdab5SAdrian Hunter } 14917d4bdab5SAdrian Hunter 14923a69672eSNamhyung Kim FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name) 14933a69672eSNamhyung Kim { 14943a69672eSNamhyung Kim int fd; 14953a69672eSNamhyung Kim 14963a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, pmu->name, name, O_RDONLY); 14973a69672eSNamhyung Kim if (fd < 0) 14983a69672eSNamhyung Kim return NULL; 14993a69672eSNamhyung Kim 15003a69672eSNamhyung Kim return fdopen(fd, "r"); 15013a69672eSNamhyung Kim } 15023a69672eSNamhyung Kim 15037d4bdab5SAdrian Hunter int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 15047d4bdab5SAdrian Hunter ...) 15057d4bdab5SAdrian Hunter { 15067d4bdab5SAdrian Hunter va_list args; 15077d4bdab5SAdrian Hunter FILE *file; 15087d4bdab5SAdrian Hunter int ret = EOF; 15097d4bdab5SAdrian Hunter 15107d4bdab5SAdrian Hunter va_start(args, fmt); 15117d4bdab5SAdrian Hunter file = perf_pmu__open_file(pmu, name); 15127d4bdab5SAdrian Hunter if (file) { 15137d4bdab5SAdrian Hunter ret = vfscanf(file, fmt, args); 15147d4bdab5SAdrian Hunter fclose(file); 15157d4bdab5SAdrian Hunter } 15167d4bdab5SAdrian Hunter va_end(args); 15177d4bdab5SAdrian Hunter return ret; 15187d4bdab5SAdrian Hunter } 15199fbc61f8SKan Liang 15203a69672eSNamhyung Kim int perf_pmu__scan_file_at(struct perf_pmu *pmu, int dirfd, const char *name, 15213a69672eSNamhyung Kim const char *fmt, ...) 15223a69672eSNamhyung Kim { 15233a69672eSNamhyung Kim va_list args; 15243a69672eSNamhyung Kim FILE *file; 15253a69672eSNamhyung Kim int ret = EOF; 15263a69672eSNamhyung Kim 15273a69672eSNamhyung Kim va_start(args, fmt); 15283a69672eSNamhyung Kim file = perf_pmu__open_file_at(pmu, dirfd, name); 15293a69672eSNamhyung Kim if (file) { 15303a69672eSNamhyung Kim ret = vfscanf(file, fmt, args); 15313a69672eSNamhyung Kim fclose(file); 15323a69672eSNamhyung Kim } 15333a69672eSNamhyung Kim va_end(args); 15343a69672eSNamhyung Kim return ret; 15353a69672eSNamhyung Kim } 15363a69672eSNamhyung Kim 1537c2b6a896SGerman Gomez bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name) 1538c2b6a896SGerman Gomez { 1539c2b6a896SGerman Gomez char path[PATH_MAX]; 1540c2b6a896SGerman Gomez 1541c2b6a896SGerman Gomez if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name)) 1542c2b6a896SGerman Gomez return false; 1543c2b6a896SGerman Gomez 1544c2b6a896SGerman Gomez return file_available(path); 1545c2b6a896SGerman Gomez } 1546c2b6a896SGerman Gomez 15479fbc61f8SKan Liang static int perf_pmu__new_caps(struct list_head *list, char *name, char *value) 15489fbc61f8SKan Liang { 15499fbc61f8SKan Liang struct perf_pmu_caps *caps = zalloc(sizeof(*caps)); 15509fbc61f8SKan Liang 15519fbc61f8SKan Liang if (!caps) 15529fbc61f8SKan Liang return -ENOMEM; 15539fbc61f8SKan Liang 15549fbc61f8SKan Liang caps->name = strdup(name); 15559fbc61f8SKan Liang if (!caps->name) 15569fbc61f8SKan Liang goto free_caps; 15579fbc61f8SKan Liang caps->value = strndup(value, strlen(value) - 1); 15589fbc61f8SKan Liang if (!caps->value) 15599fbc61f8SKan Liang goto free_name; 15609fbc61f8SKan Liang list_add_tail(&caps->list, list); 15619fbc61f8SKan Liang return 0; 15629fbc61f8SKan Liang 15639fbc61f8SKan Liang free_name: 156457f14b5aSArnaldo Carvalho de Melo zfree(&caps->name); 15659fbc61f8SKan Liang free_caps: 15669fbc61f8SKan Liang free(caps); 15679fbc61f8SKan Liang 15689fbc61f8SKan Liang return -ENOMEM; 15699fbc61f8SKan Liang } 15709fbc61f8SKan Liang 1571eec11310SNamhyung Kim static void perf_pmu__del_caps(struct perf_pmu *pmu) 1572eec11310SNamhyung Kim { 1573eec11310SNamhyung Kim struct perf_pmu_caps *caps, *tmp; 1574eec11310SNamhyung Kim 1575eec11310SNamhyung Kim list_for_each_entry_safe(caps, tmp, &pmu->caps, list) { 1576eec11310SNamhyung Kim list_del(&caps->list); 1577efe98a7aSArnaldo Carvalho de Melo zfree(&caps->name); 1578efe98a7aSArnaldo Carvalho de Melo zfree(&caps->value); 1579eec11310SNamhyung Kim free(caps); 1580eec11310SNamhyung Kim } 1581eec11310SNamhyung Kim } 1582eec11310SNamhyung Kim 15839fbc61f8SKan Liang /* 15849fbc61f8SKan Liang * Reading/parsing the given pmu capabilities, which should be located at: 15859fbc61f8SKan Liang * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes. 15869fbc61f8SKan Liang * Return the number of capabilities 15879fbc61f8SKan Liang */ 15889fbc61f8SKan Liang int perf_pmu__caps_parse(struct perf_pmu *pmu) 15899fbc61f8SKan Liang { 15909fbc61f8SKan Liang struct stat st; 15919fbc61f8SKan Liang char caps_path[PATH_MAX]; 15929fbc61f8SKan Liang DIR *caps_dir; 15939fbc61f8SKan Liang struct dirent *evt_ent; 1594b39094d3SNamhyung Kim int caps_fd; 15953339ec44SRavi Bangoria 15963339ec44SRavi Bangoria if (pmu->caps_initialized) 15973339ec44SRavi Bangoria return pmu->nr_caps; 15983339ec44SRavi Bangoria 15993339ec44SRavi Bangoria pmu->nr_caps = 0; 16009fbc61f8SKan Liang 1601f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(caps_path, sizeof(caps_path), pmu->name, "caps")) 16029fbc61f8SKan Liang return -1; 16039fbc61f8SKan Liang 16043339ec44SRavi Bangoria if (stat(caps_path, &st) < 0) { 16053339ec44SRavi Bangoria pmu->caps_initialized = true; 16069fbc61f8SKan Liang return 0; /* no error if caps does not exist */ 16073339ec44SRavi Bangoria } 16089fbc61f8SKan Liang 16099fbc61f8SKan Liang caps_dir = opendir(caps_path); 16109fbc61f8SKan Liang if (!caps_dir) 16119fbc61f8SKan Liang return -EINVAL; 16129fbc61f8SKan Liang 1613b39094d3SNamhyung Kim caps_fd = dirfd(caps_dir); 1614b39094d3SNamhyung Kim 16159fbc61f8SKan Liang while ((evt_ent = readdir(caps_dir)) != NULL) { 16169fbc61f8SKan Liang char *name = evt_ent->d_name; 16179fbc61f8SKan Liang char value[128]; 16189fbc61f8SKan Liang FILE *file; 1619b39094d3SNamhyung Kim int fd; 16209fbc61f8SKan Liang 16219fbc61f8SKan Liang if (!strcmp(name, ".") || !strcmp(name, "..")) 16229fbc61f8SKan Liang continue; 16239fbc61f8SKan Liang 1624b39094d3SNamhyung Kim fd = openat(caps_fd, name, O_RDONLY); 16250ea8920eSIan Rogers if (fd == -1) 16269fbc61f8SKan Liang continue; 16270ea8920eSIan Rogers file = fdopen(fd, "r"); 16280ea8920eSIan Rogers if (!file) { 16290ea8920eSIan Rogers close(fd); 16300ea8920eSIan Rogers continue; 16310ea8920eSIan Rogers } 16329fbc61f8SKan Liang 16339fbc61f8SKan Liang if (!fgets(value, sizeof(value), file) || 16349fbc61f8SKan Liang (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) { 16359fbc61f8SKan Liang fclose(file); 16369fbc61f8SKan Liang continue; 16379fbc61f8SKan Liang } 16389fbc61f8SKan Liang 16393339ec44SRavi Bangoria pmu->nr_caps++; 16409fbc61f8SKan Liang fclose(file); 16419fbc61f8SKan Liang } 16429fbc61f8SKan Liang 16439fbc61f8SKan Liang closedir(caps_dir); 16449fbc61f8SKan Liang 16453339ec44SRavi Bangoria pmu->caps_initialized = true; 16463339ec44SRavi Bangoria return pmu->nr_caps; 16479fbc61f8SKan Liang } 1648e4064776SJin Yao 1649b9f01032SIan Rogers static void perf_pmu__compute_config_masks(struct perf_pmu *pmu) 1650e4064776SJin Yao { 1651e4064776SJin Yao struct perf_pmu_format *format; 1652b9f01032SIan Rogers 1653b9f01032SIan Rogers if (pmu->config_masks_computed) 1654b9f01032SIan Rogers return; 1655e4064776SJin Yao 1656e4064776SJin Yao list_for_each_entry(format, &pmu->format, list) { 1657b9f01032SIan Rogers unsigned int i; 1658b9f01032SIan Rogers __u64 *mask; 1659b9f01032SIan Rogers 1660b9f01032SIan Rogers if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) 1661e4064776SJin Yao continue; 1662e4064776SJin Yao 1663b9f01032SIan Rogers pmu->config_masks_present = true; 1664b9f01032SIan Rogers mask = &pmu->config_masks[format->value]; 1665b9f01032SIan Rogers 1666e4064776SJin Yao for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS) 1667b9f01032SIan Rogers *mask |= 1ULL << i; 1668e4064776SJin Yao } 1669b9f01032SIan Rogers pmu->config_masks_computed = true; 1670b9f01032SIan Rogers } 1671b9f01032SIan Rogers 1672b9f01032SIan Rogers void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 1673b9f01032SIan Rogers const char *name, int config_num, 1674b9f01032SIan Rogers const char *config_name) 1675b9f01032SIan Rogers { 1676b9f01032SIan Rogers __u64 bits; 1677b9f01032SIan Rogers char buf[100]; 1678b9f01032SIan Rogers 1679b9f01032SIan Rogers perf_pmu__compute_config_masks(pmu); 1680e4064776SJin Yao 1681e4064776SJin Yao /* 1682e4064776SJin Yao * Kernel doesn't export any valid format bits. 1683e4064776SJin Yao */ 1684b9f01032SIan Rogers if (!pmu->config_masks_present) 1685e4064776SJin Yao return; 1686e4064776SJin Yao 1687b9f01032SIan Rogers bits = config & ~pmu->config_masks[config_num]; 1688e4064776SJin Yao if (bits == 0) 1689e4064776SJin Yao return; 1690e4064776SJin Yao 1691e4064776SJin Yao bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf)); 1692e4064776SJin Yao 1693b9f01032SIan Rogers pr_warning("WARNING: event '%s' not valid (bits %s of %s " 1694e4064776SJin Yao "'%llx' not supported by kernel)!\n", 1695b9f01032SIan Rogers name ?: "N/A", buf, config_name, config); 1696e4064776SJin Yao } 1697c5a26ea4SJin Yao 1698c47a5599SJin Yao int perf_pmu__match(char *pattern, char *name, char *tok) 1699c47a5599SJin Yao { 170013d60ba0SKan Liang if (!name) 170113d60ba0SKan Liang return -1; 170213d60ba0SKan Liang 1703c47a5599SJin Yao if (fnmatch(pattern, name, 0)) 1704c47a5599SJin Yao return -1; 1705c47a5599SJin Yao 1706240e6fd0SIan Rogers if (tok && !perf_pmu__match_ignoring_suffix(name, tok)) 1707c47a5599SJin Yao return -1; 1708c47a5599SJin Yao 1709c47a5599SJin Yao return 0; 1710c47a5599SJin Yao } 17111d3351e6SJin Yao 1712acef233bSJing Zhang double __weak perf_pmu__cpu_slots_per_cycle(void) 1713acef233bSJing Zhang { 1714acef233bSJing Zhang return NAN; 1715acef233bSJing Zhang } 1716f8ad6018SJames Clark 1717f8ad6018SJames Clark int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size) 1718f8ad6018SJames Clark { 1719f8ad6018SJames Clark const char *sysfs = sysfs__mountpoint(); 1720f8ad6018SJames Clark 1721f8ad6018SJames Clark if (!sysfs) 1722f8ad6018SJames Clark return 0; 1723f8ad6018SJames Clark return scnprintf(pathname, size, "%s/bus/event_source/devices/", sysfs); 1724f8ad6018SJames Clark } 1725f8ad6018SJames Clark 1726e293a5e8SNamhyung Kim int perf_pmu__event_source_devices_fd(void) 1727e293a5e8SNamhyung Kim { 1728e293a5e8SNamhyung Kim char path[PATH_MAX]; 1729e293a5e8SNamhyung Kim const char *sysfs = sysfs__mountpoint(); 1730e293a5e8SNamhyung Kim 1731e293a5e8SNamhyung Kim if (!sysfs) 1732e293a5e8SNamhyung Kim return -1; 1733e293a5e8SNamhyung Kim 1734e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs); 1735e293a5e8SNamhyung Kim return open(path, O_DIRECTORY); 1736e293a5e8SNamhyung Kim } 1737e293a5e8SNamhyung Kim 1738f8ad6018SJames Clark /* 1739f8ad6018SJames Clark * Fill 'buf' with the path to a file or folder in 'pmu_name' in 1740f8ad6018SJames Clark * sysfs. For example if pmu_name = "cs_etm" and 'filename' = "format" 1741f8ad6018SJames Clark * then pathname will be filled with 1742f8ad6018SJames Clark * "/sys/bus/event_source/devices/cs_etm/format" 1743f8ad6018SJames Clark * 1744e1a3aad3SIan Rogers * Return 0 if the sysfs mountpoint couldn't be found, if no characters were 1745e1a3aad3SIan Rogers * written or if the buffer size is exceeded. 1746f8ad6018SJames Clark */ 1747f8ad6018SJames Clark int perf_pmu__pathname_scnprintf(char *buf, size_t size, 1748f8ad6018SJames Clark const char *pmu_name, const char *filename) 1749f8ad6018SJames Clark { 1750e1a3aad3SIan Rogers size_t len; 1751f8ad6018SJames Clark 1752e1a3aad3SIan Rogers len = perf_pmu__event_source_devices_scnprintf(buf, size); 1753e1a3aad3SIan Rogers if (!len || (len + strlen(pmu_name) + strlen(filename) + 1) >= size) 1754f8ad6018SJames Clark return 0; 1755e1a3aad3SIan Rogers 1756e1a3aad3SIan Rogers return scnprintf(buf + len, size - len, "%s/%s", pmu_name, filename); 1757f8ad6018SJames Clark } 1758eec11310SNamhyung Kim 1759e293a5e8SNamhyung Kim int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags) 1760e293a5e8SNamhyung Kim { 1761e293a5e8SNamhyung Kim char path[PATH_MAX]; 1762e293a5e8SNamhyung Kim 1763e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/%s", pmu_name, filename); 1764e293a5e8SNamhyung Kim return openat(dirfd, path, flags); 1765e293a5e8SNamhyung Kim } 1766e293a5e8SNamhyung Kim 17671eaf496eSIan Rogers void perf_pmu__delete(struct perf_pmu *pmu) 1768eec11310SNamhyung Kim { 1769eec11310SNamhyung Kim perf_pmu__del_formats(&pmu->format); 1770eec11310SNamhyung Kim perf_pmu__del_aliases(pmu); 1771eec11310SNamhyung Kim perf_pmu__del_caps(pmu); 1772eec11310SNamhyung Kim 1773eec11310SNamhyung Kim perf_cpu_map__put(pmu->cpus); 1774eec11310SNamhyung Kim 1775efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->default_config); 1776efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 1777efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->alias_name); 1778eec11310SNamhyung Kim free(pmu); 1779eec11310SNamhyung Kim } 17809d5da30eSJames Clark 17819d5da30eSJames Clark struct perf_pmu *pmu__find_core_pmu(void) 17829d5da30eSJames Clark { 17839d5da30eSJames Clark struct perf_pmu *pmu = NULL; 17849d5da30eSJames Clark 17859d5da30eSJames Clark while ((pmu = perf_pmus__scan_core(pmu))) { 17869d5da30eSJames Clark /* 17879d5da30eSJames Clark * The cpumap should cover all CPUs. Otherwise, some CPUs may 17889d5da30eSJames Clark * not support some events or have different event IDs. 17899d5da30eSJames Clark */ 17909d5da30eSJames Clark if (RC_CHK_ACCESS(pmu->cpus)->nr != cpu__max_cpu().cpu) 17919d5da30eSJames Clark return NULL; 17929d5da30eSJames Clark 17939d5da30eSJames Clark return pmu; 17949d5da30eSJames Clark } 17959d5da30eSJames Clark return NULL; 17969d5da30eSJames Clark } 1797