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> 7fa0d9846SArnaldo Carvalho de Melo #include <subcmd/pager.h> 8cd82a32eSJiri Olsa #include <sys/types.h> 9a43783aeSArnaldo Carvalho de Melo #include <errno.h> 10c23c2a0fSArnaldo Carvalho de Melo #include <fcntl.h> 117a8ef4c4SArnaldo Carvalho de Melo #include <sys/stat.h> 12cd82a32eSJiri Olsa #include <unistd.h> 13cd82a32eSJiri Olsa #include <stdio.h> 14dc0a6202SAdrian Hunter #include <stdbool.h> 157d4bdab5SAdrian Hunter #include <stdarg.h> 16cd82a32eSJiri Olsa #include <dirent.h> 17cd0cfad7SBorislav Petkov #include <api/fs/fs.h> 18410136f5SStephane Eranian #include <locale.h> 19fbc2844eSWilliam Cohen #include <regex.h> 209c3516d1SJiri Olsa #include <perf/cpumap.h> 21c47a5599SJin Yao #include <fnmatch.h> 22acef233bSJing Zhang #include <math.h> 235e51b0bbSArnaldo Carvalho de Melo #include "debug.h" 24e12ee9f7SAdrian Hunter #include "evsel.h" 25cd82a32eSJiri Olsa #include "pmu.h" 26336b92daSRavi Bangoria #include "pmus.h" 273d88aec0SIan Rogers #include "pmu-bison.h" 283d88aec0SIan Rogers #include "pmu-flex.h" 29cd82a32eSJiri Olsa #include "parse-events.h" 30e5c6109fSIan Rogers #include "print-events.h" 31933f82ffSSukadev Bhattiprolu #include "header.h" 32a067558eSArnaldo Carvalho de Melo #include "string2.h" 33fa0d9846SArnaldo Carvalho de Melo #include "strbuf.h" 34d9664582SAndi Kleen #include "fncache.h" 3544462430SJin Yao #include "pmu-hybrid.h" 366593f019SJames Clark #include "util/evsel_config.h" 37cd82a32eSJiri Olsa 38e46fc8d9SArnaldo Carvalho de Melo struct perf_pmu perf_pmu__fake; 39e46fc8d9SArnaldo Carvalho de Melo 40fe13d43dSIan Rogers /** 41fe13d43dSIan Rogers * struct perf_pmu_format - Values from a format file read from 42fe13d43dSIan Rogers * <sysfs>/devices/cpu/format/ held in struct perf_pmu. 43fe13d43dSIan Rogers * 44fe13d43dSIan Rogers * For example, the contents of <sysfs>/devices/cpu/format/event may be 45fe13d43dSIan Rogers * "config:0-7" and will be represented here as name="event", 46fe13d43dSIan Rogers * value=PERF_PMU_FORMAT_VALUE_CONFIG and bits 0 to 7 will be set. 47fe13d43dSIan Rogers */ 48ab1bf653SArnaldo Carvalho de Melo struct perf_pmu_format { 49fe13d43dSIan Rogers /** @name: The modifier/file name. */ 50ab1bf653SArnaldo Carvalho de Melo char *name; 51fe13d43dSIan Rogers /** 52fe13d43dSIan Rogers * @value : Which config value the format relates to. Supported values 53fe13d43dSIan Rogers * are from PERF_PMU_FORMAT_VALUE_CONFIG to 54fe13d43dSIan Rogers * PERF_PMU_FORMAT_VALUE_CONFIG_END. 55fe13d43dSIan Rogers */ 56ab1bf653SArnaldo Carvalho de Melo int value; 57fe13d43dSIan Rogers /** @bits: Which config bits are set by this format value. */ 58ab1bf653SArnaldo Carvalho de Melo DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); 59fe13d43dSIan Rogers /** @list: Element on list within struct perf_pmu. */ 60ab1bf653SArnaldo Carvalho de Melo struct list_head list; 61ab1bf653SArnaldo Carvalho de Melo }; 62ab1bf653SArnaldo Carvalho de Melo 63c5a26ea4SJin Yao static bool hybrid_scanned; 64cd82a32eSJiri Olsa 65e293a5e8SNamhyung Kim static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name); 66e293a5e8SNamhyung Kim 67cd82a32eSJiri Olsa /* 68cd82a32eSJiri Olsa * Parse & process all the sysfs attributes located under 69cd82a32eSJiri Olsa * the directory specified in 'dir' parameter. 70cd82a32eSJiri Olsa */ 71e293a5e8SNamhyung Kim int perf_pmu__format_parse(int dirfd, struct list_head *head) 72cd82a32eSJiri Olsa { 73cd82a32eSJiri Olsa struct dirent *evt_ent; 74cd82a32eSJiri Olsa DIR *format_dir; 75cd82a32eSJiri Olsa int ret = 0; 76cd82a32eSJiri Olsa 77e293a5e8SNamhyung Kim format_dir = fdopendir(dirfd); 78cd82a32eSJiri Olsa if (!format_dir) 79cd82a32eSJiri Olsa return -EINVAL; 80cd82a32eSJiri Olsa 81cd82a32eSJiri Olsa while (!ret && (evt_ent = readdir(format_dir))) { 82cd82a32eSJiri Olsa char *name = evt_ent->d_name; 83e293a5e8SNamhyung Kim int fd; 843d88aec0SIan Rogers void *scanner; 853d88aec0SIan Rogers FILE *file; 86cd82a32eSJiri Olsa 87cd82a32eSJiri Olsa if (!strcmp(name, ".") || !strcmp(name, "..")) 88cd82a32eSJiri Olsa continue; 89cd82a32eSJiri Olsa 90cd82a32eSJiri Olsa 91cd82a32eSJiri Olsa ret = -EINVAL; 92e293a5e8SNamhyung Kim fd = openat(dirfd, name, O_RDONLY); 93e293a5e8SNamhyung Kim if (fd < 0) 94cd82a32eSJiri Olsa break; 95cd82a32eSJiri Olsa 963d88aec0SIan Rogers file = fdopen(fd, "r"); 973d88aec0SIan Rogers if (!file) { 983d88aec0SIan Rogers close(fd); 993d88aec0SIan Rogers break; 1003d88aec0SIan Rogers } 1013d88aec0SIan Rogers 1023d88aec0SIan Rogers ret = perf_pmu_lex_init(&scanner); 1033d88aec0SIan Rogers if (ret) { 1043d88aec0SIan Rogers fclose(file); 1053d88aec0SIan Rogers break; 1063d88aec0SIan Rogers } 1073d88aec0SIan Rogers 1083d88aec0SIan Rogers perf_pmu_set_in(file, scanner); 1093d88aec0SIan Rogers ret = perf_pmu_parse(head, name, scanner); 1103d88aec0SIan Rogers perf_pmu_lex_destroy(scanner); 1113d88aec0SIan Rogers fclose(file); 112cd82a32eSJiri Olsa } 113cd82a32eSJiri Olsa 114cd82a32eSJiri Olsa closedir(format_dir); 115cd82a32eSJiri Olsa return ret; 116cd82a32eSJiri Olsa } 117cd82a32eSJiri Olsa 118cd82a32eSJiri Olsa /* 119cd82a32eSJiri Olsa * Reading/parsing the default pmu format definition, which should be 120cd82a32eSJiri Olsa * located at: 121cd82a32eSJiri Olsa * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. 122cd82a32eSJiri Olsa */ 123e293a5e8SNamhyung Kim static int pmu_format(int dirfd, const char *name, struct list_head *format) 124cd82a32eSJiri Olsa { 125e293a5e8SNamhyung Kim int fd; 126cd82a32eSJiri Olsa 127e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "format", O_DIRECTORY); 128e293a5e8SNamhyung Kim if (fd < 0) 129d9664582SAndi Kleen return 0; 130cd82a32eSJiri Olsa 131e293a5e8SNamhyung Kim /* it'll close the fd */ 132e293a5e8SNamhyung Kim if (perf_pmu__format_parse(fd, format)) 133cd82a32eSJiri Olsa return -1; 134cd82a32eSJiri Olsa 135cd82a32eSJiri Olsa return 0; 136cd82a32eSJiri Olsa } 137cd82a32eSJiri Olsa 138a55ab7c4SJin Yao int perf_pmu__convert_scale(const char *scale, char **end, double *sval) 139d02fc6bcSAndi Kleen { 140d02fc6bcSAndi Kleen char *lc; 141d02fc6bcSAndi Kleen int ret = 0; 142d02fc6bcSAndi Kleen 143d02fc6bcSAndi Kleen /* 144d02fc6bcSAndi Kleen * save current locale 145d02fc6bcSAndi Kleen */ 146d02fc6bcSAndi Kleen lc = setlocale(LC_NUMERIC, NULL); 147d02fc6bcSAndi Kleen 148d02fc6bcSAndi Kleen /* 149d02fc6bcSAndi Kleen * The lc string may be allocated in static storage, 150d02fc6bcSAndi Kleen * so get a dynamic copy to make it survive setlocale 151d02fc6bcSAndi Kleen * call below. 152d02fc6bcSAndi Kleen */ 153d02fc6bcSAndi Kleen lc = strdup(lc); 154d02fc6bcSAndi Kleen if (!lc) { 155d02fc6bcSAndi Kleen ret = -ENOMEM; 156d02fc6bcSAndi Kleen goto out; 157d02fc6bcSAndi Kleen } 158d02fc6bcSAndi Kleen 159d02fc6bcSAndi Kleen /* 160d02fc6bcSAndi Kleen * force to C locale to ensure kernel 161d02fc6bcSAndi Kleen * scale string is converted correctly. 162d02fc6bcSAndi Kleen * kernel uses default C locale. 163d02fc6bcSAndi Kleen */ 164d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, "C"); 165d02fc6bcSAndi Kleen 166d02fc6bcSAndi Kleen *sval = strtod(scale, end); 167d02fc6bcSAndi Kleen 168d02fc6bcSAndi Kleen out: 169d02fc6bcSAndi Kleen /* restore locale */ 170d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, lc); 171d02fc6bcSAndi Kleen free(lc); 172d02fc6bcSAndi Kleen return ret; 173d02fc6bcSAndi Kleen } 174d02fc6bcSAndi Kleen 175e293a5e8SNamhyung Kim static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, char *name) 176410136f5SStephane Eranian { 177410136f5SStephane Eranian struct stat st; 178410136f5SStephane Eranian ssize_t sret; 179410136f5SStephane Eranian char scale[128]; 180410136f5SStephane Eranian int fd, ret = -1; 181410136f5SStephane Eranian char path[PATH_MAX]; 182410136f5SStephane Eranian 183e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.scale", name); 184410136f5SStephane Eranian 185e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 186410136f5SStephane Eranian if (fd == -1) 187410136f5SStephane Eranian return -1; 188410136f5SStephane Eranian 189410136f5SStephane Eranian if (fstat(fd, &st) < 0) 190410136f5SStephane Eranian goto error; 191410136f5SStephane Eranian 192410136f5SStephane Eranian sret = read(fd, scale, sizeof(scale)-1); 193410136f5SStephane Eranian if (sret < 0) 194410136f5SStephane Eranian goto error; 195410136f5SStephane Eranian 1969ecae065SMadhavan Srinivasan if (scale[sret - 1] == '\n') 1979ecae065SMadhavan Srinivasan scale[sret - 1] = '\0'; 1989ecae065SMadhavan Srinivasan else 199410136f5SStephane Eranian scale[sret] = '\0'; 2009ecae065SMadhavan Srinivasan 201a55ab7c4SJin Yao ret = perf_pmu__convert_scale(scale, NULL, &alias->scale); 202410136f5SStephane Eranian error: 203410136f5SStephane Eranian close(fd); 204410136f5SStephane Eranian return ret; 205410136f5SStephane Eranian } 206410136f5SStephane Eranian 207e293a5e8SNamhyung Kim static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, char *name) 208410136f5SStephane Eranian { 209410136f5SStephane Eranian char path[PATH_MAX]; 210410136f5SStephane Eranian ssize_t sret; 211410136f5SStephane Eranian int fd; 212410136f5SStephane Eranian 213e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.unit", name); 214410136f5SStephane Eranian 215e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 216410136f5SStephane Eranian if (fd == -1) 217410136f5SStephane Eranian return -1; 218410136f5SStephane Eranian 219410136f5SStephane Eranian sret = read(fd, alias->unit, UNIT_MAX_LEN); 220410136f5SStephane Eranian if (sret < 0) 221410136f5SStephane Eranian goto error; 222410136f5SStephane Eranian 223410136f5SStephane Eranian close(fd); 224410136f5SStephane Eranian 2259ecae065SMadhavan Srinivasan if (alias->unit[sret - 1] == '\n') 2269ecae065SMadhavan Srinivasan alias->unit[sret - 1] = '\0'; 2279ecae065SMadhavan Srinivasan else 228410136f5SStephane Eranian alias->unit[sret] = '\0'; 229410136f5SStephane Eranian 230410136f5SStephane Eranian return 0; 231410136f5SStephane Eranian error: 232410136f5SStephane Eranian close(fd); 233410136f5SStephane Eranian alias->unit[0] = '\0'; 234410136f5SStephane Eranian return -1; 235410136f5SStephane Eranian } 236410136f5SStephane Eranian 237044330c1SMatt Fleming static int 238e293a5e8SNamhyung Kim perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, char *name) 239044330c1SMatt Fleming { 240044330c1SMatt Fleming char path[PATH_MAX]; 241044330c1SMatt Fleming int fd; 242044330c1SMatt Fleming 243e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.per-pkg", name); 244044330c1SMatt Fleming 245e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 246044330c1SMatt Fleming if (fd == -1) 247044330c1SMatt Fleming return -1; 248044330c1SMatt Fleming 249044330c1SMatt Fleming close(fd); 250044330c1SMatt Fleming 251044330c1SMatt Fleming alias->per_pkg = true; 252044330c1SMatt Fleming return 0; 253044330c1SMatt Fleming } 254044330c1SMatt Fleming 2551d9e446bSJiri Olsa static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, 256e293a5e8SNamhyung Kim int dirfd, char *name) 2571d9e446bSJiri Olsa { 2581d9e446bSJiri Olsa char path[PATH_MAX]; 2591d9e446bSJiri Olsa int fd; 2601d9e446bSJiri Olsa 261e293a5e8SNamhyung Kim scnprintf(path, PATH_MAX, "%s.snapshot", name); 2621d9e446bSJiri Olsa 263e293a5e8SNamhyung Kim fd = openat(dirfd, path, O_RDONLY); 2641d9e446bSJiri Olsa if (fd == -1) 2651d9e446bSJiri Olsa return -1; 2661d9e446bSJiri Olsa 2671d9e446bSJiri Olsa alias->snapshot = true; 2681d9e446bSJiri Olsa close(fd); 2691d9e446bSJiri Olsa return 0; 2701d9e446bSJiri Olsa } 2711d9e446bSJiri Olsa 2726dde6429SThomas Richter static void perf_pmu_assign_str(char *name, const char *field, char **old_str, 2736dde6429SThomas Richter char **new_str) 2746dde6429SThomas Richter { 2756dde6429SThomas Richter if (!*old_str) 2766dde6429SThomas Richter goto set_new; 2776dde6429SThomas Richter 2786dde6429SThomas Richter if (*new_str) { /* Have new string, check with old */ 2796dde6429SThomas Richter if (strcasecmp(*old_str, *new_str)) 2806dde6429SThomas Richter pr_debug("alias %s differs in field '%s'\n", 2816dde6429SThomas Richter name, field); 2826dde6429SThomas Richter zfree(old_str); 2836dde6429SThomas Richter } else /* Nothing new --> keep old string */ 2846dde6429SThomas Richter return; 2856dde6429SThomas Richter set_new: 2866dde6429SThomas Richter *old_str = *new_str; 2876dde6429SThomas Richter *new_str = NULL; 2886dde6429SThomas Richter } 2896dde6429SThomas Richter 2906dde6429SThomas Richter static void perf_pmu_update_alias(struct perf_pmu_alias *old, 2916dde6429SThomas Richter struct perf_pmu_alias *newalias) 2926dde6429SThomas Richter { 2936dde6429SThomas Richter perf_pmu_assign_str(old->name, "desc", &old->desc, &newalias->desc); 2946dde6429SThomas Richter perf_pmu_assign_str(old->name, "long_desc", &old->long_desc, 2956dde6429SThomas Richter &newalias->long_desc); 2966dde6429SThomas Richter perf_pmu_assign_str(old->name, "topic", &old->topic, &newalias->topic); 2976dde6429SThomas Richter perf_pmu_assign_str(old->name, "value", &old->str, &newalias->str); 2986dde6429SThomas Richter old->scale = newalias->scale; 2996dde6429SThomas Richter old->per_pkg = newalias->per_pkg; 3006dde6429SThomas Richter old->snapshot = newalias->snapshot; 3016dde6429SThomas Richter memcpy(old->unit, newalias->unit, sizeof(old->unit)); 3026dde6429SThomas Richter } 3036dde6429SThomas Richter 3046dde6429SThomas Richter /* Delete an alias entry. */ 30522fe5a25SNamhyung Kim void perf_pmu_free_alias(struct perf_pmu_alias *newalias) 3066dde6429SThomas Richter { 3076dde6429SThomas Richter zfree(&newalias->name); 3086dde6429SThomas Richter zfree(&newalias->desc); 3096dde6429SThomas Richter zfree(&newalias->long_desc); 3106dde6429SThomas Richter zfree(&newalias->topic); 3116dde6429SThomas Richter zfree(&newalias->str); 31232705de7SJin Yao zfree(&newalias->pmu_name); 3136dde6429SThomas Richter parse_events_terms__purge(&newalias->terms); 3146dde6429SThomas Richter free(newalias); 3156dde6429SThomas Richter } 3166dde6429SThomas Richter 317eec11310SNamhyung Kim static void perf_pmu__del_aliases(struct perf_pmu *pmu) 318eec11310SNamhyung Kim { 319eec11310SNamhyung Kim struct perf_pmu_alias *alias, *tmp; 320eec11310SNamhyung Kim 321eec11310SNamhyung Kim list_for_each_entry_safe(alias, tmp, &pmu->aliases, list) { 322eec11310SNamhyung Kim list_del(&alias->list); 323eec11310SNamhyung Kim perf_pmu_free_alias(alias); 324eec11310SNamhyung Kim } 325eec11310SNamhyung Kim } 326eec11310SNamhyung Kim 3276dde6429SThomas Richter /* Merge an alias, search in alias list. If this name is already 3286dde6429SThomas Richter * present merge both of them to combine all information. 3296dde6429SThomas Richter */ 3306dde6429SThomas Richter static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias, 3316dde6429SThomas Richter struct list_head *alist) 3326dde6429SThomas Richter { 3336dde6429SThomas Richter struct perf_pmu_alias *a; 3346dde6429SThomas Richter 3356dde6429SThomas Richter list_for_each_entry(a, alist, list) { 3366dde6429SThomas Richter if (!strcasecmp(newalias->name, a->name)) { 33732705de7SJin Yao if (newalias->pmu_name && a->pmu_name && 33832705de7SJin Yao !strcasecmp(newalias->pmu_name, a->pmu_name)) { 33932705de7SJin Yao continue; 34032705de7SJin Yao } 3416dde6429SThomas Richter perf_pmu_update_alias(a, newalias); 3426dde6429SThomas Richter perf_pmu_free_alias(newalias); 3436dde6429SThomas Richter return true; 3446dde6429SThomas Richter } 3456dde6429SThomas Richter } 3466dde6429SThomas Richter return false; 3476dde6429SThomas Richter } 3486dde6429SThomas Richter 349e293a5e8SNamhyung Kim static int __perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, 35047f572aaSIan Rogers char *desc, char *val, const struct pmu_event *pe) 351a6146d50SZheng Yan { 3520c24d6fbSThomas Richter struct parse_events_term *term; 3535c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 354a6146d50SZheng Yan int ret; 3550c24d6fbSThomas Richter char newval[256]; 356330f40a0SIan Rogers const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL; 357bd680861SIan Rogers bool deprecated = false, perpkg = false; 358eab35953SJin Yao 359eab35953SJin Yao if (pe) { 360330f40a0SIan Rogers long_desc = pe->long_desc; 361330f40a0SIan Rogers topic = pe->topic; 362330f40a0SIan Rogers unit = pe->unit; 363bd680861SIan Rogers perpkg = pe->perpkg; 3649ed8b7dcSIan Rogers deprecated = pe->deprecated; 365330f40a0SIan Rogers pmu_name = pe->pmu; 366eab35953SJin Yao } 367a6146d50SZheng Yan 368a6146d50SZheng Yan alias = malloc(sizeof(*alias)); 369a6146d50SZheng Yan if (!alias) 370a6146d50SZheng Yan return -ENOMEM; 371a6146d50SZheng Yan 372a6146d50SZheng Yan INIT_LIST_HEAD(&alias->terms); 373410136f5SStephane Eranian alias->scale = 1.0; 374410136f5SStephane Eranian alias->unit[0] = '\0'; 375bd680861SIan Rogers alias->per_pkg = perpkg; 37684530920SStephane Eranian alias->snapshot = false; 3779ed8b7dcSIan Rogers alias->deprecated = deprecated; 378410136f5SStephane Eranian 37970c646e0SSukadev Bhattiprolu ret = parse_events_terms(&alias->terms, val); 380a6146d50SZheng Yan if (ret) { 38170c646e0SSukadev Bhattiprolu pr_err("Cannot parse alias %s: %d\n", val, ret); 382a6146d50SZheng Yan free(alias); 383a6146d50SZheng Yan return ret; 384a6146d50SZheng Yan } 385a6146d50SZheng Yan 3860c24d6fbSThomas Richter /* Scan event and remove leading zeroes, spaces, newlines, some 3870c24d6fbSThomas Richter * platforms have terms specified as 3880c24d6fbSThomas Richter * event=0x0091 (read from files ../<PMU>/events/<FILE> 3890c24d6fbSThomas Richter * and terms specified as event=0x91 (read from JSON files). 3900c24d6fbSThomas Richter * 3910c24d6fbSThomas Richter * Rebuild string to make alias->str member comparable. 3920c24d6fbSThomas Richter */ 3930c24d6fbSThomas Richter memset(newval, 0, sizeof(newval)); 3940c24d6fbSThomas Richter ret = 0; 3950c24d6fbSThomas Richter list_for_each_entry(term, &alias->terms, list) { 3960c24d6fbSThomas Richter if (ret) 3970c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 3980c24d6fbSThomas Richter ","); 3990c24d6fbSThomas Richter if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 4000c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 4010c24d6fbSThomas Richter "%s=%#x", term->config, term->val.num); 4020c24d6fbSThomas Richter else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 4030c24d6fbSThomas Richter ret += scnprintf(newval + ret, sizeof(newval) - ret, 4040c24d6fbSThomas Richter "%s=%s", term->config, term->val.str); 4050c24d6fbSThomas Richter } 4060c24d6fbSThomas Richter 407a6146d50SZheng Yan alias->name = strdup(name); 408e293a5e8SNamhyung Kim if (dirfd >= 0) { 409410136f5SStephane Eranian /* 410410136f5SStephane Eranian * load unit name and scale if available 411410136f5SStephane Eranian */ 412e293a5e8SNamhyung Kim perf_pmu__parse_unit(alias, dirfd, name); 413e293a5e8SNamhyung Kim perf_pmu__parse_scale(alias, dirfd, name); 414e293a5e8SNamhyung Kim perf_pmu__parse_per_pkg(alias, dirfd, name); 415e293a5e8SNamhyung Kim perf_pmu__parse_snapshot(alias, dirfd, name); 41670c646e0SSukadev Bhattiprolu } 417410136f5SStephane Eranian 41808e60ed1SAndi Kleen alias->desc = desc ? strdup(desc) : NULL; 419c8d6828aSSukadev Bhattiprolu alias->long_desc = long_desc ? strdup(long_desc) : 420c8d6828aSSukadev Bhattiprolu desc ? strdup(desc) : NULL; 421dd5f1036SAndi Kleen alias->topic = topic ? strdup(topic) : NULL; 422fedb2b51SAndi Kleen if (unit) { 423330f40a0SIan Rogers if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0) 424fedb2b51SAndi Kleen return -1; 425fedb2b51SAndi Kleen snprintf(alias->unit, sizeof(alias->unit), "%s", unit); 426fedb2b51SAndi Kleen } 4270c24d6fbSThomas Richter alias->str = strdup(newval); 42832705de7SJin Yao alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL; 429f2361024SAndi Kleen 4306dde6429SThomas Richter if (!perf_pmu_merge_alias(alias, list)) 431a6146d50SZheng Yan list_add_tail(&alias->list, list); 432410136f5SStephane Eranian 433a6146d50SZheng Yan return 0; 434a6146d50SZheng Yan } 435a6146d50SZheng Yan 436e293a5e8SNamhyung Kim static int perf_pmu__new_alias(struct list_head *list, int dirfd, char *name, FILE *file) 43770c646e0SSukadev Bhattiprolu { 43870c646e0SSukadev Bhattiprolu char buf[256]; 43970c646e0SSukadev Bhattiprolu int ret; 44070c646e0SSukadev Bhattiprolu 44170c646e0SSukadev Bhattiprolu ret = fread(buf, 1, sizeof(buf), file); 44270c646e0SSukadev Bhattiprolu if (ret == 0) 44370c646e0SSukadev Bhattiprolu return -EINVAL; 44470c646e0SSukadev Bhattiprolu 44570c646e0SSukadev Bhattiprolu buf[ret] = 0; 44670c646e0SSukadev Bhattiprolu 447ea23ac73SThomas Richter /* Remove trailing newline from sysfs file */ 44813c230abSArnaldo Carvalho de Melo strim(buf); 449ea23ac73SThomas Richter 450e293a5e8SNamhyung Kim return __perf_pmu__new_alias(list, dirfd, name, NULL, buf, NULL); 45170c646e0SSukadev Bhattiprolu } 45270c646e0SSukadev Bhattiprolu 45346441bdcSMatt Fleming static inline bool pmu_alias_info_file(char *name) 45446441bdcSMatt Fleming { 45546441bdcSMatt Fleming size_t len; 45646441bdcSMatt Fleming 45746441bdcSMatt Fleming len = strlen(name); 45846441bdcSMatt Fleming if (len > 5 && !strcmp(name + len - 5, ".unit")) 45946441bdcSMatt Fleming return true; 46046441bdcSMatt Fleming if (len > 6 && !strcmp(name + len - 6, ".scale")) 46146441bdcSMatt Fleming return true; 462044330c1SMatt Fleming if (len > 8 && !strcmp(name + len - 8, ".per-pkg")) 463044330c1SMatt Fleming return true; 4641d9e446bSJiri Olsa if (len > 9 && !strcmp(name + len - 9, ".snapshot")) 4651d9e446bSJiri Olsa return true; 46646441bdcSMatt Fleming 46746441bdcSMatt Fleming return false; 46846441bdcSMatt Fleming } 46946441bdcSMatt Fleming 470a6146d50SZheng Yan /* 471a6146d50SZheng Yan * Process all the sysfs attributes located under the directory 472a6146d50SZheng Yan * specified in 'dir' parameter. 473a6146d50SZheng Yan */ 474e293a5e8SNamhyung Kim static int pmu_aliases_parse(int dirfd, struct list_head *head) 475a6146d50SZheng Yan { 476a6146d50SZheng Yan struct dirent *evt_ent; 477a6146d50SZheng Yan DIR *event_dir; 478e293a5e8SNamhyung Kim int fd; 479a6146d50SZheng Yan 480e293a5e8SNamhyung Kim event_dir = fdopendir(dirfd); 481a6146d50SZheng Yan if (!event_dir) 482a6146d50SZheng Yan return -EINVAL; 483a6146d50SZheng Yan 484940db6dcSAndi Kleen while ((evt_ent = readdir(event_dir))) { 485a6146d50SZheng Yan char *name = evt_ent->d_name; 486a6146d50SZheng Yan FILE *file; 487a6146d50SZheng Yan 488a6146d50SZheng Yan if (!strcmp(name, ".") || !strcmp(name, "..")) 489a6146d50SZheng Yan continue; 490a6146d50SZheng Yan 491410136f5SStephane Eranian /* 49246441bdcSMatt Fleming * skip info files parsed in perf_pmu__new_alias() 493410136f5SStephane Eranian */ 49446441bdcSMatt Fleming if (pmu_alias_info_file(name)) 495410136f5SStephane Eranian continue; 496410136f5SStephane Eranian 497e293a5e8SNamhyung Kim fd = openat(dirfd, name, O_RDONLY); 4980ea8920eSIan Rogers if (fd == -1) { 4990ea8920eSIan Rogers pr_debug("Cannot open %s\n", name); 5000ea8920eSIan Rogers continue; 5010ea8920eSIan Rogers } 502e293a5e8SNamhyung Kim file = fdopen(fd, "r"); 503940db6dcSAndi Kleen if (!file) { 5040ea8920eSIan Rogers close(fd); 505940db6dcSAndi Kleen continue; 506940db6dcSAndi Kleen } 507410136f5SStephane Eranian 508e293a5e8SNamhyung Kim if (perf_pmu__new_alias(head, dirfd, name, file) < 0) 509940db6dcSAndi Kleen pr_debug("Cannot set up %s\n", name); 510a6146d50SZheng Yan fclose(file); 511a6146d50SZheng Yan } 512a6146d50SZheng Yan 513a6146d50SZheng Yan closedir(event_dir); 514940db6dcSAndi Kleen return 0; 515a6146d50SZheng Yan } 516a6146d50SZheng Yan 517a6146d50SZheng Yan /* 518a6146d50SZheng Yan * Reading the pmu event aliases definition, which should be located at: 519a6146d50SZheng Yan * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 520a6146d50SZheng Yan */ 521e293a5e8SNamhyung Kim static int pmu_aliases(int dirfd, const char *name, struct list_head *head) 522a6146d50SZheng Yan { 523e293a5e8SNamhyung Kim int fd; 524a6146d50SZheng Yan 525e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "events", O_DIRECTORY); 526e293a5e8SNamhyung Kim if (fd < 0) 527d9664582SAndi Kleen return 0; 528a6146d50SZheng Yan 529e293a5e8SNamhyung Kim /* it'll close the fd */ 530e293a5e8SNamhyung Kim if (pmu_aliases_parse(fd, head)) 531a6146d50SZheng Yan return -1; 532a6146d50SZheng Yan 533a6146d50SZheng Yan return 0; 534a6146d50SZheng Yan } 535a6146d50SZheng Yan 5365c6ccc37SArnaldo Carvalho de Melo static int pmu_alias_terms(struct perf_pmu_alias *alias, 537a6146d50SZheng Yan struct list_head *terms) 538a6146d50SZheng Yan { 5397c2f8164SJiri Olsa struct parse_events_term *term, *cloned; 540a6146d50SZheng Yan LIST_HEAD(list); 541a6146d50SZheng Yan int ret; 542a6146d50SZheng Yan 543a6146d50SZheng Yan list_for_each_entry(term, &alias->terms, list) { 5447c2f8164SJiri Olsa ret = parse_events_term__clone(&cloned, term); 545a6146d50SZheng Yan if (ret) { 546682dc24cSArnaldo Carvalho de Melo parse_events_terms__purge(&list); 547a6146d50SZheng Yan return ret; 548a6146d50SZheng Yan } 549c2f1ceadSAndi Kleen /* 550c2f1ceadSAndi Kleen * Weak terms don't override command line options, 551c2f1ceadSAndi Kleen * which we don't want for implicit terms in aliases. 552c2f1ceadSAndi Kleen */ 553c2f1ceadSAndi Kleen cloned->weak = true; 5547c2f8164SJiri Olsa list_add_tail(&cloned->list, &list); 555a6146d50SZheng Yan } 556a6146d50SZheng Yan list_splice(&list, terms); 557a6146d50SZheng Yan return 0; 558a6146d50SZheng Yan } 559a6146d50SZheng Yan 56050a9667cSRobert Richter /* Add all pmus in sysfs to pmu list: */ 56150a9667cSRobert Richter static void pmu_read_sysfs(void) 56250a9667cSRobert Richter { 563e293a5e8SNamhyung Kim int fd; 56450a9667cSRobert Richter DIR *dir; 56550a9667cSRobert Richter struct dirent *dent; 56650a9667cSRobert Richter 567e293a5e8SNamhyung Kim fd = perf_pmu__event_source_devices_fd(); 568e293a5e8SNamhyung Kim if (fd < 0) 56950a9667cSRobert Richter return; 57050a9667cSRobert Richter 571e293a5e8SNamhyung Kim dir = fdopendir(fd); 57250a9667cSRobert Richter if (!dir) 57350a9667cSRobert Richter return; 57450a9667cSRobert Richter 57550a9667cSRobert Richter while ((dent = readdir(dir))) { 57650a9667cSRobert Richter if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) 57750a9667cSRobert Richter continue; 57850a9667cSRobert Richter /* add to static LIST_HEAD(pmus): */ 579e293a5e8SNamhyung Kim perf_pmu__find2(fd, dent->d_name); 58050a9667cSRobert Richter } 58150a9667cSRobert Richter 58250a9667cSRobert Richter closedir(dir); 58350a9667cSRobert Richter } 58450a9667cSRobert Richter 58566ec1191SMark Rutland /* 58666ec1191SMark Rutland * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) 58766ec1191SMark Rutland * may have a "cpus" file. 58866ec1191SMark Rutland */ 5893a69672eSNamhyung Kim static struct perf_cpu_map *pmu_cpumask(int dirfd, const char *name) 5907ae92e74SYan, Zheng { 591f854839bSJiri Olsa struct perf_cpu_map *cpus; 5927e3fcffeSMark Rutland const char *templates[] = { 593d50a79cdSJames Clark "cpumask", 594d50a79cdSJames Clark "cpus", 5957e3fcffeSMark Rutland NULL 5967e3fcffeSMark Rutland }; 5977e3fcffeSMark Rutland const char **template; 598d50a79cdSJames Clark char pmu_name[PATH_MAX]; 599d50a79cdSJames Clark struct perf_pmu pmu = {.name = pmu_name}; 600d50a79cdSJames Clark FILE *file; 6017ae92e74SYan, Zheng 602d50a79cdSJames Clark strlcpy(pmu_name, name, sizeof(pmu_name)); 6037e3fcffeSMark Rutland for (template = templates; *template; template++) { 6043a69672eSNamhyung Kim file = perf_pmu__open_file_at(&pmu, dirfd, *template); 605d50a79cdSJames Clark if (!file) 606d50a79cdSJames Clark continue; 607d50a79cdSJames Clark cpus = perf_cpu_map__read(file); 6083a69672eSNamhyung Kim fclose(file); 60966ec1191SMark Rutland if (cpus) 61066ec1191SMark Rutland return cpus; 6117e3fcffeSMark Rutland } 6127ae92e74SYan, Zheng 6137ae92e74SYan, Zheng return NULL; 61466ec1191SMark Rutland } 6157ae92e74SYan, Zheng 6163a69672eSNamhyung Kim static bool pmu_is_uncore(int dirfd, const char *name) 61766ec1191SMark Rutland { 6183a69672eSNamhyung Kim int fd; 6197ae92e74SYan, Zheng 62044462430SJin Yao if (perf_pmu__hybrid_mounted(name)) 62144462430SJin Yao return false; 62244462430SJin Yao 6233a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "cpumask", O_PATH); 6243a69672eSNamhyung Kim if (fd < 0) 6253a69672eSNamhyung Kim return false; 6263a69672eSNamhyung Kim 6273a69672eSNamhyung Kim close(fd); 6283a69672eSNamhyung Kim return true; 6297ae92e74SYan, Zheng } 6307ae92e74SYan, Zheng 63151d54847SJohn Garry static char *pmu_id(const char *name) 63251d54847SJohn Garry { 63351d54847SJohn Garry char path[PATH_MAX], *str; 63451d54847SJohn Garry size_t len; 63551d54847SJohn Garry 6365f2c8efaSJames Clark perf_pmu__pathname_scnprintf(path, sizeof(path), name, "identifier"); 63751d54847SJohn Garry 6385f2c8efaSJames Clark if (filename__read_str(path, &str, &len) < 0) 63951d54847SJohn Garry return NULL; 64051d54847SJohn Garry 64151d54847SJohn Garry str[len - 1] = 0; /* remove line feed */ 64251d54847SJohn Garry 64351d54847SJohn Garry return str; 64451d54847SJohn Garry } 64551d54847SJohn Garry 6464bf7e81aSIan Rogers /** 6474bf7e81aSIan Rogers * is_sysfs_pmu_core() - PMU CORE devices have different name other than cpu in 6484bf7e81aSIan Rogers * sysfs on some platforms like ARM or Intel hybrid. Looking for 6494bf7e81aSIan Rogers * possible the cpus file in sysfs files to identify whether this is a 6504bf7e81aSIan Rogers * core device. 6514bf7e81aSIan Rogers * @name: The PMU name such as "cpu_atom". 65214b22ae0SGanapatrao Kulkarni */ 6534bf7e81aSIan Rogers static int is_sysfs_pmu_core(const char *name) 65414b22ae0SGanapatrao Kulkarni { 65514b22ae0SGanapatrao Kulkarni char path[PATH_MAX]; 65614b22ae0SGanapatrao Kulkarni 657f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), name, "cpus")) 65814b22ae0SGanapatrao Kulkarni return 0; 659d9664582SAndi Kleen return file_available(path); 66014b22ae0SGanapatrao Kulkarni } 66114b22ae0SGanapatrao Kulkarni 66229be2fe0SIan Rogers char *perf_pmu__getcpuid(struct perf_pmu *pmu) 663d77ade9fSAndi Kleen { 664d77ade9fSAndi Kleen char *cpuid; 665d77ade9fSAndi Kleen static bool printed; 666d77ade9fSAndi Kleen 667d77ade9fSAndi Kleen cpuid = getenv("PERF_CPUID"); 668d77ade9fSAndi Kleen if (cpuid) 669d77ade9fSAndi Kleen cpuid = strdup(cpuid); 670d77ade9fSAndi Kleen if (!cpuid) 67154e32dc0SGanapatrao Kulkarni cpuid = get_cpuid_str(pmu); 672d77ade9fSAndi Kleen if (!cpuid) 673d77ade9fSAndi Kleen return NULL; 674d77ade9fSAndi Kleen 675d77ade9fSAndi Kleen if (!printed) { 676d77ade9fSAndi Kleen pr_debug("Using CPUID %s\n", cpuid); 677d77ade9fSAndi Kleen printed = true; 678d77ade9fSAndi Kleen } 679d77ade9fSAndi Kleen return cpuid; 680d77ade9fSAndi Kleen } 681d77ade9fSAndi Kleen 6821ba3752aSIan Rogers __weak const struct pmu_events_table *pmu_events_table__find(void) 683e126bef5SJohn Garry { 68496d2a746SIan Rogers return perf_pmu__find_events_table(NULL); 685e126bef5SJohn Garry } 686e126bef5SJohn Garry 687f8ea2c15SIan Rogers __weak const struct pmu_metrics_table *pmu_metrics_table__find(void) 688f8ea2c15SIan Rogers { 689f8ea2c15SIan Rogers return perf_pmu__find_metrics_table(NULL); 690f8ea2c15SIan Rogers } 691f8ea2c15SIan Rogers 692240e6fd0SIan Rogers /** 693240e6fd0SIan Rogers * perf_pmu__match_ignoring_suffix - Does the pmu_name match tok ignoring any 694240e6fd0SIan Rogers * trailing suffix? The Suffix must be in form 695240e6fd0SIan Rogers * tok_{digits}, or tok{digits}. 696240e6fd0SIan Rogers * @pmu_name: The pmu_name with possible suffix. 697240e6fd0SIan Rogers * @tok: The possible match to pmu_name without suffix. 698c07d5c92SJohn Garry */ 699240e6fd0SIan Rogers static bool perf_pmu__match_ignoring_suffix(const char *pmu_name, const char *tok) 700c47a5599SJin Yao { 701c07d5c92SJohn Garry const char *p; 702c47a5599SJin Yao 703c47a5599SJin Yao if (strncmp(pmu_name, tok, strlen(tok))) 704c47a5599SJin Yao return false; 705c47a5599SJin Yao 706c47a5599SJin Yao p = pmu_name + strlen(tok); 707c47a5599SJin Yao if (*p == 0) 708c47a5599SJin Yao return true; 709c47a5599SJin Yao 710c07d5c92SJohn Garry if (*p == '_') 711c47a5599SJin Yao ++p; 712c07d5c92SJohn Garry 713c07d5c92SJohn Garry /* Ensure we end in a number */ 714c07d5c92SJohn Garry while (1) { 715c07d5c92SJohn Garry if (!isdigit(*p)) 716c47a5599SJin Yao return false; 717c07d5c92SJohn Garry if (*(++p) == 0) 718c07d5c92SJohn Garry break; 719c07d5c92SJohn Garry } 720c47a5599SJin Yao 721c47a5599SJin Yao return true; 722c47a5599SJin Yao } 723c47a5599SJin Yao 724240e6fd0SIan Rogers /** 725240e6fd0SIan Rogers * pmu_uncore_alias_match - does name match the PMU name? 726240e6fd0SIan Rogers * @pmu_name: the json struct pmu_event name. This may lack a suffix (which 727240e6fd0SIan Rogers * matches) or be of the form "socket,pmuname" which will match 728240e6fd0SIan Rogers * "socketX_pmunameY". 729240e6fd0SIan Rogers * @name: a real full PMU name as from sysfs. 730240e6fd0SIan Rogers */ 731240e6fd0SIan Rogers static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) 732730670b1SJohn Garry { 733730670b1SJohn Garry char *tmp = NULL, *tok, *str; 734730670b1SJohn Garry bool res; 735730670b1SJohn Garry 736240e6fd0SIan Rogers if (strchr(pmu_name, ',') == NULL) 737240e6fd0SIan Rogers return perf_pmu__match_ignoring_suffix(name, pmu_name); 738240e6fd0SIan Rogers 739730670b1SJohn Garry str = strdup(pmu_name); 740730670b1SJohn Garry if (!str) 741730670b1SJohn Garry return false; 742730670b1SJohn Garry 743730670b1SJohn Garry /* 744730670b1SJohn Garry * uncore alias may be from different PMU with common prefix 745730670b1SJohn Garry */ 746730670b1SJohn Garry tok = strtok_r(str, ",", &tmp); 747730670b1SJohn Garry if (strncmp(pmu_name, tok, strlen(tok))) { 748730670b1SJohn Garry res = false; 749730670b1SJohn Garry goto out; 750730670b1SJohn Garry } 751730670b1SJohn Garry 752730670b1SJohn Garry /* 753730670b1SJohn Garry * Match more complex aliases where the alias name is a comma-delimited 754730670b1SJohn Garry * list of tokens, orderly contained in the matching PMU name. 755730670b1SJohn Garry * 756730670b1SJohn Garry * Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we 757730670b1SJohn Garry * match "socket" in "socketX_pmunameY" and then "pmuname" in 758730670b1SJohn Garry * "pmunameY". 759730670b1SJohn Garry */ 760c07d5c92SJohn Garry while (1) { 761c07d5c92SJohn Garry char *next_tok = strtok_r(NULL, ",", &tmp); 762c07d5c92SJohn Garry 763730670b1SJohn Garry name = strstr(name, tok); 764c07d5c92SJohn Garry if (!name || 765240e6fd0SIan Rogers (!next_tok && !perf_pmu__match_ignoring_suffix(name, tok))) { 766730670b1SJohn Garry res = false; 767730670b1SJohn Garry goto out; 768730670b1SJohn Garry } 769c07d5c92SJohn Garry if (!next_tok) 770c07d5c92SJohn Garry break; 771c07d5c92SJohn Garry tok = next_tok; 772c07d5c92SJohn Garry name += strlen(tok); 773730670b1SJohn Garry } 774730670b1SJohn Garry 775730670b1SJohn Garry res = true; 776730670b1SJohn Garry out: 777730670b1SJohn Garry free(str); 778730670b1SJohn Garry return res; 779730670b1SJohn Garry } 780730670b1SJohn Garry 781660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data { 782660842e4SIan Rogers struct list_head *head; 783660842e4SIan Rogers const char *name; 784660842e4SIan Rogers const char *cpu_name; 785660842e4SIan Rogers struct perf_pmu *pmu; 786660842e4SIan Rogers }; 787660842e4SIan Rogers 788660842e4SIan Rogers static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, 7891ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 790660842e4SIan Rogers void *vdata) 791660842e4SIan Rogers { 792660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data *data = vdata; 793660842e4SIan Rogers const char *pname = pe->pmu ? pe->pmu : data->cpu_name; 794660842e4SIan Rogers 795660842e4SIan Rogers if (data->pmu->is_uncore && pmu_uncore_alias_match(pname, data->name)) 796660842e4SIan Rogers goto new_alias; 797660842e4SIan Rogers 798660842e4SIan Rogers if (strcmp(pname, data->name)) 799660842e4SIan Rogers return 0; 800660842e4SIan Rogers 801660842e4SIan Rogers new_alias: 802660842e4SIan Rogers /* need type casts to override 'const' */ 803e293a5e8SNamhyung Kim __perf_pmu__new_alias(data->head, -1, (char *)pe->name, (char *)pe->desc, 804660842e4SIan Rogers (char *)pe->event, pe); 805660842e4SIan Rogers return 0; 806660842e4SIan Rogers } 807660842e4SIan Rogers 808933f82ffSSukadev Bhattiprolu /* 809933f82ffSSukadev Bhattiprolu * From the pmu_events_map, find the table of PMU events that corresponds 810933f82ffSSukadev Bhattiprolu * to the current running CPU. Then, add all PMU events from that table 811933f82ffSSukadev Bhattiprolu * as aliases. 812933f82ffSSukadev Bhattiprolu */ 813eeac7730SIan Rogers void pmu_add_cpu_aliases_table(struct list_head *head, struct perf_pmu *pmu, 8141ba3752aSIan Rogers const struct pmu_events_table *table) 815933f82ffSSukadev Bhattiprolu { 816660842e4SIan Rogers struct pmu_add_cpu_aliases_map_data data = { 817660842e4SIan Rogers .head = head, 818660842e4SIan Rogers .name = pmu->name, 8194bf7e81aSIan Rogers .cpu_name = is_sysfs_pmu_core(pmu->name) ? pmu->name : "cpu", 820660842e4SIan Rogers .pmu = pmu, 821660842e4SIan Rogers }; 822fedb2b51SAndi Kleen 823660842e4SIan Rogers pmu_events_table_for_each_event(table, pmu_add_cpu_aliases_map_callback, &data); 824933f82ffSSukadev Bhattiprolu } 825933f82ffSSukadev Bhattiprolu 826e45ad701SJohn Garry static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) 827e45ad701SJohn Garry { 8281ba3752aSIan Rogers const struct pmu_events_table *table; 829e45ad701SJohn Garry 83096d2a746SIan Rogers table = perf_pmu__find_events_table(pmu); 831eeac7730SIan Rogers if (!table) 832e45ad701SJohn Garry return; 833e45ad701SJohn Garry 834eeac7730SIan Rogers pmu_add_cpu_aliases_table(head, pmu, table); 835e45ad701SJohn Garry } 836e45ad701SJohn Garry 8374513c719SJohn Garry struct pmu_sys_event_iter_data { 8384513c719SJohn Garry struct list_head *head; 8394513c719SJohn Garry struct perf_pmu *pmu; 8404513c719SJohn Garry }; 8414513c719SJohn Garry 84229be2fe0SIan Rogers static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, 8431ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 84429be2fe0SIan Rogers void *data) 8454513c719SJohn Garry { 8464513c719SJohn Garry struct pmu_sys_event_iter_data *idata = data; 8474513c719SJohn Garry struct perf_pmu *pmu = idata->pmu; 8484513c719SJohn Garry 8494513c719SJohn Garry if (!pe->compat || !pe->pmu) 8504513c719SJohn Garry return 0; 8514513c719SJohn Garry 8524513c719SJohn Garry if (!strcmp(pmu->id, pe->compat) && 8534513c719SJohn Garry pmu_uncore_alias_match(pe->pmu, pmu->name)) { 854e293a5e8SNamhyung Kim __perf_pmu__new_alias(idata->head, -1, 8554513c719SJohn Garry (char *)pe->name, 8564513c719SJohn Garry (char *)pe->desc, 8574513c719SJohn Garry (char *)pe->event, 858eab35953SJin Yao pe); 8594513c719SJohn Garry } 8604513c719SJohn Garry 8614513c719SJohn Garry return 0; 8624513c719SJohn Garry } 8634513c719SJohn Garry 864e199f47fSJohn Garry void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu) 8654513c719SJohn Garry { 8664513c719SJohn Garry struct pmu_sys_event_iter_data idata = { 8674513c719SJohn Garry .head = head, 8684513c719SJohn Garry .pmu = pmu, 8694513c719SJohn Garry }; 8704513c719SJohn Garry 8714513c719SJohn Garry if (!pmu->id) 8724513c719SJohn Garry return; 8734513c719SJohn Garry 8744513c719SJohn Garry pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, &idata); 8754513c719SJohn Garry } 8764513c719SJohn Garry 877c5de47f2SSukadev Bhattiprolu struct perf_event_attr * __weak 878dc0a6202SAdrian Hunter perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) 879dc0a6202SAdrian Hunter { 880dc0a6202SAdrian Hunter return NULL; 881dc0a6202SAdrian Hunter } 882dc0a6202SAdrian Hunter 88313d60ba0SKan Liang char * __weak 88413d60ba0SKan Liang pmu_find_real_name(const char *name) 88513d60ba0SKan Liang { 88613d60ba0SKan Liang return (char *)name; 88713d60ba0SKan Liang } 88813d60ba0SKan Liang 88913d60ba0SKan Liang char * __weak 89013d60ba0SKan Liang pmu_find_alias_name(const char *name __maybe_unused) 89113d60ba0SKan Liang { 89213d60ba0SKan Liang return NULL; 89313d60ba0SKan Liang } 89413d60ba0SKan Liang 8953a69672eSNamhyung Kim static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) 89690a86bdeSJiri Olsa { 89790a86bdeSJiri Olsa int max_precise = -1; 89890a86bdeSJiri Olsa 8993a69672eSNamhyung Kim perf_pmu__scan_file_at(pmu, dirfd, "caps/max_precise", "%d", &max_precise); 90090a86bdeSJiri Olsa return max_precise; 90190a86bdeSJiri Olsa } 90290a86bdeSJiri Olsa 903e293a5e8SNamhyung Kim static struct perf_pmu *pmu_lookup(int dirfd, const char *lookup_name) 904cd82a32eSJiri Olsa { 905cd82a32eSJiri Olsa struct perf_pmu *pmu; 906cd82a32eSJiri Olsa LIST_HEAD(format); 907a6146d50SZheng Yan LIST_HEAD(aliases); 908cd82a32eSJiri Olsa __u32 type; 90913d60ba0SKan Liang char *name = pmu_find_real_name(lookup_name); 91049afa7f6SJin Yao bool is_hybrid = perf_pmu__hybrid_mounted(name); 91113d60ba0SKan Liang char *alias_name; 91249afa7f6SJin Yao 91349afa7f6SJin Yao /* 91449afa7f6SJin Yao * Check pmu name for hybrid and the pmu may be invalid in sysfs 91549afa7f6SJin Yao */ 91649afa7f6SJin Yao if (!strncmp(name, "cpu_", 4) && !is_hybrid) 91749afa7f6SJin Yao return NULL; 918cd82a32eSJiri Olsa 919cd82a32eSJiri Olsa /* 920cd82a32eSJiri Olsa * The pmu data we store & need consists of the pmu 921cd82a32eSJiri Olsa * type value and format definitions. Load both right 922cd82a32eSJiri Olsa * now. 923cd82a32eSJiri Olsa */ 924e293a5e8SNamhyung Kim if (pmu_format(dirfd, name, &format)) 925cd82a32eSJiri Olsa return NULL; 926cd82a32eSJiri Olsa 92715b22ed3SAndi Kleen /* 928f8ad6018SJames Clark * Check the aliases first to avoid unnecessary work. 92915b22ed3SAndi Kleen */ 930e293a5e8SNamhyung Kim if (pmu_aliases(dirfd, name, &aliases)) 9313fded963SJiri Olsa return NULL; 9323fded963SJiri Olsa 933cd82a32eSJiri Olsa pmu = zalloc(sizeof(*pmu)); 934cd82a32eSJiri Olsa if (!pmu) 935cd82a32eSJiri Olsa return NULL; 936cd82a32eSJiri Olsa 9373a69672eSNamhyung Kim pmu->cpus = pmu_cpumask(dirfd, name); 93854e32dc0SGanapatrao Kulkarni pmu->name = strdup(name); 939f8ad6018SJames Clark 94013d60ba0SKan Liang if (!pmu->name) 94113d60ba0SKan Liang goto err; 94213d60ba0SKan Liang 943f8ad6018SJames Clark /* Read type, and ensure that type value is successfully assigned (return 1) */ 9443a69672eSNamhyung Kim if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1) 945f8ad6018SJames Clark goto err; 946f8ad6018SJames Clark 94713d60ba0SKan Liang alias_name = pmu_find_alias_name(name); 94813d60ba0SKan Liang if (alias_name) { 94913d60ba0SKan Liang pmu->alias_name = strdup(alias_name); 95013d60ba0SKan Liang if (!pmu->alias_name) 95113d60ba0SKan Liang goto err; 95213d60ba0SKan Liang } 95313d60ba0SKan Liang 95454e32dc0SGanapatrao Kulkarni pmu->type = type; 955*e20d1f2fSIan Rogers pmu->is_core = is_pmu_core(name); 9563a69672eSNamhyung Kim pmu->is_uncore = pmu_is_uncore(dirfd, name); 95751d54847SJohn Garry if (pmu->is_uncore) 95851d54847SJohn Garry pmu->id = pmu_id(name); 9593a69672eSNamhyung Kim pmu->max_precise = pmu_max_precise(dirfd, pmu); 96054e32dc0SGanapatrao Kulkarni pmu_add_cpu_aliases(&aliases, pmu); 9614513c719SJohn Garry pmu_add_sys_aliases(&aliases, pmu); 96266ec1191SMark Rutland 963cd82a32eSJiri Olsa INIT_LIST_HEAD(&pmu->format); 964a6146d50SZheng Yan INIT_LIST_HEAD(&pmu->aliases); 9659fbc61f8SKan Liang INIT_LIST_HEAD(&pmu->caps); 966cd82a32eSJiri Olsa list_splice(&format, &pmu->format); 967a6146d50SZheng Yan list_splice(&aliases, &pmu->aliases); 9689bc8f9feSRobert Richter list_add_tail(&pmu->list, &pmus); 969dc0a6202SAdrian Hunter 970e5f4afbeSIan Rogers if (is_hybrid) 97144462430SJin Yao list_add_tail(&pmu->hybrid_list, &perf_pmu__hybrid_pmus); 972eec11310SNamhyung Kim else 973eec11310SNamhyung Kim INIT_LIST_HEAD(&pmu->hybrid_list); 97444462430SJin Yao 975dc0a6202SAdrian Hunter pmu->default_config = perf_pmu__get_default_config(pmu); 976dc0a6202SAdrian Hunter 977cd82a32eSJiri Olsa return pmu; 97813d60ba0SKan Liang err: 979efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 98013d60ba0SKan Liang free(pmu); 98113d60ba0SKan Liang return NULL; 982cd82a32eSJiri Olsa } 983cd82a32eSJiri Olsa 984e552b7beSRob Herring void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu) 985e552b7beSRob Herring { 986e552b7beSRob Herring struct perf_pmu_format *format; 987e552b7beSRob Herring 988e552b7beSRob Herring /* fake pmu doesn't have format list */ 989e552b7beSRob Herring if (pmu == &perf_pmu__fake) 990e552b7beSRob Herring return; 991e552b7beSRob Herring 992e552b7beSRob Herring list_for_each_entry(format, &pmu->format, list) 993e552b7beSRob Herring if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) { 994e552b7beSRob Herring pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'" 995e552b7beSRob Herring "which is not supported by this version of perf!\n", 996e552b7beSRob Herring pmu->name, format->name, format->value); 997e552b7beSRob Herring return; 998e552b7beSRob Herring } 999e552b7beSRob Herring } 1000e552b7beSRob Herring 1001b6b96fb4SAdrian Hunter static struct perf_pmu *pmu_find(const char *name) 1002cd82a32eSJiri Olsa { 1003cd82a32eSJiri Olsa struct perf_pmu *pmu; 1004cd82a32eSJiri Olsa 100513d60ba0SKan Liang list_for_each_entry(pmu, &pmus, list) { 100613d60ba0SKan Liang if (!strcmp(pmu->name, name) || 100713d60ba0SKan Liang (pmu->alias_name && !strcmp(pmu->alias_name, name))) 1008cd82a32eSJiri Olsa return pmu; 100913d60ba0SKan Liang } 1010cd82a32eSJiri Olsa 1011cd82a32eSJiri Olsa return NULL; 1012cd82a32eSJiri Olsa } 1013cd82a32eSJiri Olsa 10143a50dc76SStephane Eranian struct perf_pmu *perf_pmu__find_by_type(unsigned int type) 10153a50dc76SStephane Eranian { 10163a50dc76SStephane Eranian struct perf_pmu *pmu; 10173a50dc76SStephane Eranian 10183a50dc76SStephane Eranian list_for_each_entry(pmu, &pmus, list) 10193a50dc76SStephane Eranian if (pmu->type == type) 10203a50dc76SStephane Eranian return pmu; 10213a50dc76SStephane Eranian 10223a50dc76SStephane Eranian return NULL; 10233a50dc76SStephane Eranian } 10243a50dc76SStephane Eranian 102550a9667cSRobert Richter struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) 102650a9667cSRobert Richter { 102750a9667cSRobert Richter /* 102850a9667cSRobert Richter * pmu iterator: If pmu is NULL, we start at the begin, 102950a9667cSRobert Richter * otherwise return the next pmu. Returns NULL on end. 103050a9667cSRobert Richter */ 103150a9667cSRobert Richter if (!pmu) { 103250a9667cSRobert Richter pmu_read_sysfs(); 103350a9667cSRobert Richter pmu = list_prepare_entry(pmu, &pmus, list); 103450a9667cSRobert Richter } 103550a9667cSRobert Richter list_for_each_entry_continue(pmu, &pmus, list) 103650a9667cSRobert Richter return pmu; 103750a9667cSRobert Richter return NULL; 103850a9667cSRobert Richter } 103950a9667cSRobert Richter 1040c6d616feSIan Rogers struct perf_pmu *evsel__find_pmu(const struct evsel *evsel) 1041e12ee9f7SAdrian Hunter { 1042e12ee9f7SAdrian Hunter struct perf_pmu *pmu = NULL; 1043e12ee9f7SAdrian Hunter 1044f7400262SNamhyung Kim if (evsel->pmu) 1045f7400262SNamhyung Kim return evsel->pmu; 1046f7400262SNamhyung Kim 1047e12ee9f7SAdrian Hunter while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1048e12ee9f7SAdrian Hunter if (pmu->type == evsel->core.attr.type) 1049e12ee9f7SAdrian Hunter break; 1050e12ee9f7SAdrian Hunter } 1051e12ee9f7SAdrian Hunter 1052c6d616feSIan Rogers ((struct evsel *)evsel)->pmu = pmu; 1053e12ee9f7SAdrian Hunter return pmu; 1054e12ee9f7SAdrian Hunter } 1055e12ee9f7SAdrian Hunter 1056c6d616feSIan Rogers bool evsel__is_aux_event(const struct evsel *evsel) 1057e12ee9f7SAdrian Hunter { 1058e76026bdSArnaldo Carvalho de Melo struct perf_pmu *pmu = evsel__find_pmu(evsel); 1059e12ee9f7SAdrian Hunter 1060e12ee9f7SAdrian Hunter return pmu && pmu->auxtrace; 1061e12ee9f7SAdrian Hunter } 1062e12ee9f7SAdrian Hunter 10636593f019SJames Clark /* 10646593f019SJames Clark * Set @config_name to @val as long as the user hasn't already set or cleared it 10656593f019SJames Clark * by passing a config term on the command line. 10666593f019SJames Clark * 10676593f019SJames Clark * @val is the value to put into the bits specified by @config_name rather than 10686593f019SJames Clark * the bit pattern. It is shifted into position by this function, so to set 10696593f019SJames Clark * something to true, pass 1 for val rather than a pre shifted value. 10706593f019SJames Clark */ 10716593f019SJames Clark #define field_prep(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask)) 10726593f019SJames Clark void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, 10736593f019SJames Clark const char *config_name, u64 val) 10746593f019SJames Clark { 10756593f019SJames Clark u64 user_bits = 0, bits; 10766593f019SJames Clark struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG); 10776593f019SJames Clark 10786593f019SJames Clark if (term) 10796593f019SJames Clark user_bits = term->val.cfg_chg; 10806593f019SJames Clark 10816593f019SJames Clark bits = perf_pmu__format_bits(&pmu->format, config_name); 10826593f019SJames Clark 10836593f019SJames Clark /* Do nothing if the user changed the value */ 10846593f019SJames Clark if (bits & user_bits) 10856593f019SJames Clark return; 10866593f019SJames Clark 10876593f019SJames Clark /* Otherwise replace it */ 10886593f019SJames Clark evsel->core.attr.config &= ~bits; 10896593f019SJames Clark evsel->core.attr.config |= field_prep(bits, val); 10906593f019SJames Clark } 10916593f019SJames Clark 1092b6b96fb4SAdrian Hunter struct perf_pmu *perf_pmu__find(const char *name) 1093cd82a32eSJiri Olsa { 1094cd82a32eSJiri Olsa struct perf_pmu *pmu; 1095e293a5e8SNamhyung Kim int dirfd; 1096cd82a32eSJiri Olsa 1097cd82a32eSJiri Olsa /* 1098cd82a32eSJiri Olsa * Once PMU is loaded it stays in the list, 1099cd82a32eSJiri Olsa * so we keep us from multiple reading/parsing 1100cd82a32eSJiri Olsa * the pmu format definitions. 1101cd82a32eSJiri Olsa */ 1102cd82a32eSJiri Olsa pmu = pmu_find(name); 1103cd82a32eSJiri Olsa if (pmu) 1104cd82a32eSJiri Olsa return pmu; 1105cd82a32eSJiri Olsa 1106e293a5e8SNamhyung Kim dirfd = perf_pmu__event_source_devices_fd(); 1107e293a5e8SNamhyung Kim pmu = pmu_lookup(dirfd, name); 1108e293a5e8SNamhyung Kim close(dirfd); 1109e293a5e8SNamhyung Kim 1110e293a5e8SNamhyung Kim return pmu; 1111e293a5e8SNamhyung Kim } 1112e293a5e8SNamhyung Kim 1113e293a5e8SNamhyung Kim static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name) 1114e293a5e8SNamhyung Kim { 1115e293a5e8SNamhyung Kim struct perf_pmu *pmu; 1116e293a5e8SNamhyung Kim 1117e293a5e8SNamhyung Kim /* 1118e293a5e8SNamhyung Kim * Once PMU is loaded it stays in the list, 1119e293a5e8SNamhyung Kim * so we keep us from multiple reading/parsing 1120e293a5e8SNamhyung Kim * the pmu format definitions. 1121e293a5e8SNamhyung Kim */ 1122e293a5e8SNamhyung Kim pmu = pmu_find(name); 1123e293a5e8SNamhyung Kim if (pmu) 1124e293a5e8SNamhyung Kim return pmu; 1125e293a5e8SNamhyung Kim 1126e293a5e8SNamhyung Kim return pmu_lookup(dirfd, name); 1127cd82a32eSJiri Olsa } 1128cd82a32eSJiri Olsa 11295c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_format * 113009ff6071SAdrian Hunter pmu_find_format(struct list_head *formats, const char *name) 1131cd82a32eSJiri Olsa { 11325c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1133cd82a32eSJiri Olsa 1134cd82a32eSJiri Olsa list_for_each_entry(format, formats, list) 1135cd82a32eSJiri Olsa if (!strcmp(format->name, name)) 1136cd82a32eSJiri Olsa return format; 1137cd82a32eSJiri Olsa 1138cd82a32eSJiri Olsa return NULL; 1139cd82a32eSJiri Olsa } 1140cd82a32eSJiri Olsa 114109ff6071SAdrian Hunter __u64 perf_pmu__format_bits(struct list_head *formats, const char *name) 114209ff6071SAdrian Hunter { 114309ff6071SAdrian Hunter struct perf_pmu_format *format = pmu_find_format(formats, name); 114409ff6071SAdrian Hunter __u64 bits = 0; 114509ff6071SAdrian Hunter int fbit; 114609ff6071SAdrian Hunter 114709ff6071SAdrian Hunter if (!format) 114809ff6071SAdrian Hunter return 0; 114909ff6071SAdrian Hunter 115009ff6071SAdrian Hunter for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS) 115109ff6071SAdrian Hunter bits |= 1ULL << fbit; 115209ff6071SAdrian Hunter 115309ff6071SAdrian Hunter return bits; 115409ff6071SAdrian Hunter } 115509ff6071SAdrian Hunter 1156a1ac7de6SAdrian Hunter int perf_pmu__format_type(struct list_head *formats, const char *name) 1157a1ac7de6SAdrian Hunter { 1158a1ac7de6SAdrian Hunter struct perf_pmu_format *format = pmu_find_format(formats, name); 1159a1ac7de6SAdrian Hunter 1160a1ac7de6SAdrian Hunter if (!format) 1161a1ac7de6SAdrian Hunter return -1; 1162a1ac7de6SAdrian Hunter 1163a1ac7de6SAdrian Hunter return format->value; 1164a1ac7de6SAdrian Hunter } 1165a1ac7de6SAdrian Hunter 1166cd82a32eSJiri Olsa /* 1167dc0a6202SAdrian Hunter * Sets value based on the format definition (format parameter) 11684d39c89fSIngo Molnar * and unformatted value (value parameter). 1169cd82a32eSJiri Olsa */ 1170dc0a6202SAdrian Hunter static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, 1171dc0a6202SAdrian Hunter bool zero) 1172cd82a32eSJiri Olsa { 1173cd82a32eSJiri Olsa unsigned long fbit, vbit; 1174cd82a32eSJiri Olsa 1175cd82a32eSJiri Olsa for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 1176cd82a32eSJiri Olsa 1177cd82a32eSJiri Olsa if (!test_bit(fbit, format)) 1178cd82a32eSJiri Olsa continue; 1179cd82a32eSJiri Olsa 1180dc0a6202SAdrian Hunter if (value & (1llu << vbit++)) 1181dc0a6202SAdrian Hunter *v |= (1llu << fbit); 1182dc0a6202SAdrian Hunter else if (zero) 1183dc0a6202SAdrian Hunter *v &= ~(1llu << fbit); 1184cd82a32eSJiri Olsa } 1185cd82a32eSJiri Olsa } 1186cd82a32eSJiri Olsa 11870efe6b67SAdrian Hunter static __u64 pmu_format_max_value(const unsigned long *format) 11880efe6b67SAdrian Hunter { 11891b9caa10SJiri Olsa int w; 11900efe6b67SAdrian Hunter 11911b9caa10SJiri Olsa w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); 11921b9caa10SJiri Olsa if (!w) 11931b9caa10SJiri Olsa return 0; 11941b9caa10SJiri Olsa if (w < 64) 11951b9caa10SJiri Olsa return (1ULL << w) - 1; 11961b9caa10SJiri Olsa return -1; 11970efe6b67SAdrian Hunter } 11980efe6b67SAdrian Hunter 1199cd82a32eSJiri Olsa /* 1200688d4dfcSCody P Schafer * Term is a string term, and might be a param-term. Try to look up it's value 1201688d4dfcSCody P Schafer * in the remaining terms. 1202688d4dfcSCody P Schafer * - We have a term like "base-or-format-term=param-term", 1203688d4dfcSCody P Schafer * - We need to find the value supplied for "param-term" (with param-term named 1204688d4dfcSCody P Schafer * in a config string) later on in the term list. 1205688d4dfcSCody P Schafer */ 1206688d4dfcSCody P Schafer static int pmu_resolve_param_term(struct parse_events_term *term, 1207688d4dfcSCody P Schafer struct list_head *head_terms, 1208688d4dfcSCody P Schafer __u64 *value) 1209688d4dfcSCody P Schafer { 1210688d4dfcSCody P Schafer struct parse_events_term *t; 1211688d4dfcSCody P Schafer 1212688d4dfcSCody P Schafer list_for_each_entry(t, head_terms, list) { 12132a3d252dSIan Rogers if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM && 12142a3d252dSIan Rogers t->config && !strcmp(t->config, term->config)) { 1215688d4dfcSCody P Schafer t->used = true; 1216688d4dfcSCody P Schafer *value = t->val.num; 1217688d4dfcSCody P Schafer return 0; 1218688d4dfcSCody P Schafer } 1219688d4dfcSCody P Schafer } 1220688d4dfcSCody P Schafer 1221bb963e16SNamhyung Kim if (verbose > 0) 1222688d4dfcSCody P Schafer printf("Required parameter '%s' not specified\n", term->config); 1223688d4dfcSCody P Schafer 1224688d4dfcSCody P Schafer return -1; 1225688d4dfcSCody P Schafer } 1226688d4dfcSCody P Schafer 1227ffeb883eSHe Kuang static char *pmu_formats_string(struct list_head *formats) 1228e64b020bSJiri Olsa { 1229e64b020bSJiri Olsa struct perf_pmu_format *format; 123011db4e29SMasami Hiramatsu char *str = NULL; 123111db4e29SMasami Hiramatsu struct strbuf buf = STRBUF_INIT; 1232f1417ceaSXin Gao unsigned int i = 0; 1233e64b020bSJiri Olsa 1234ffeb883eSHe Kuang if (!formats) 1235e64b020bSJiri Olsa return NULL; 1236e64b020bSJiri Olsa 1237e64b020bSJiri Olsa /* sysfs exported terms */ 1238ffeb883eSHe Kuang list_for_each_entry(format, formats, list) 123911db4e29SMasami Hiramatsu if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0) 124011db4e29SMasami Hiramatsu goto error; 1241e64b020bSJiri Olsa 1242ffeb883eSHe Kuang str = strbuf_detach(&buf, NULL); 124311db4e29SMasami Hiramatsu error: 1244ffeb883eSHe Kuang strbuf_release(&buf); 1245e64b020bSJiri Olsa 1246e64b020bSJiri Olsa return str; 1247e64b020bSJiri Olsa } 1248e64b020bSJiri Olsa 1249688d4dfcSCody P Schafer /* 1250cd82a32eSJiri Olsa * Setup one of config[12] attr members based on the 125188aca8d9SCody P Schafer * user input data - term parameter. 1252cd82a32eSJiri Olsa */ 12534ac22b48SIan Rogers static int pmu_config_term(const char *pmu_name, 12544ac22b48SIan Rogers struct list_head *formats, 1255cd82a32eSJiri Olsa struct perf_event_attr *attr, 1256dc0a6202SAdrian Hunter struct parse_events_term *term, 1257688d4dfcSCody P Schafer struct list_head *head_terms, 1258e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1259cd82a32eSJiri Olsa { 12605c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1261cd82a32eSJiri Olsa __u64 *vp; 12620efe6b67SAdrian Hunter __u64 val, max_val; 1263cd82a32eSJiri Olsa 1264cd82a32eSJiri Olsa /* 1265688d4dfcSCody P Schafer * If this is a parameter we've already used for parameterized-eval, 1266688d4dfcSCody P Schafer * skip it in normal eval. 1267688d4dfcSCody P Schafer */ 1268688d4dfcSCody P Schafer if (term->used) 1269688d4dfcSCody P Schafer return 0; 1270688d4dfcSCody P Schafer 1271688d4dfcSCody P Schafer /* 1272cd82a32eSJiri Olsa * Hardcoded terms should be already in, so nothing 1273cd82a32eSJiri Olsa * to be done for them. 1274cd82a32eSJiri Olsa */ 1275cd82a32eSJiri Olsa if (parse_events__is_hardcoded_term(term)) 1276cd82a32eSJiri Olsa return 0; 1277cd82a32eSJiri Olsa 1278cd82a32eSJiri Olsa format = pmu_find_format(formats, term->config); 1279688d4dfcSCody P Schafer if (!format) { 1280ffeb883eSHe Kuang char *pmu_term = pmu_formats_string(formats); 12814ac22b48SIan Rogers char *unknown_term; 12824ac22b48SIan Rogers char *help_msg; 1283ffeb883eSHe Kuang 12844ac22b48SIan Rogers if (asprintf(&unknown_term, 12854ac22b48SIan Rogers "unknown term '%s' for pmu '%s'", 12864ac22b48SIan Rogers term->config, pmu_name) < 0) 12874ac22b48SIan Rogers unknown_term = NULL; 12884ac22b48SIan Rogers help_msg = parse_events_formats_error_string(pmu_term); 12894ac22b48SIan Rogers if (err) { 12906c191289SIan Rogers parse_events_error__handle(err, term->err_term, 12914ac22b48SIan Rogers unknown_term, 12924ac22b48SIan Rogers help_msg); 12934ac22b48SIan Rogers } else { 12944ac22b48SIan Rogers pr_debug("%s (%s)\n", unknown_term, help_msg); 12954ac22b48SIan Rogers free(unknown_term); 1296e64b020bSJiri Olsa } 12974ac22b48SIan Rogers free(pmu_term); 1298cd82a32eSJiri Olsa return -EINVAL; 1299688d4dfcSCody P Schafer } 1300cd82a32eSJiri Olsa 1301cd82a32eSJiri Olsa switch (format->value) { 1302cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG: 1303cd82a32eSJiri Olsa vp = &attr->config; 1304cd82a32eSJiri Olsa break; 1305cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG1: 1306cd82a32eSJiri Olsa vp = &attr->config1; 1307cd82a32eSJiri Olsa break; 1308cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG2: 1309cd82a32eSJiri Olsa vp = &attr->config2; 1310cd82a32eSJiri Olsa break; 1311204e7c49SRob Herring case PERF_PMU_FORMAT_VALUE_CONFIG3: 1312204e7c49SRob Herring vp = &attr->config3; 1313204e7c49SRob Herring break; 1314cd82a32eSJiri Olsa default: 1315cd82a32eSJiri Olsa return -EINVAL; 1316cd82a32eSJiri Olsa } 1317cd82a32eSJiri Olsa 131816fa7e82SJiri Olsa /* 1319688d4dfcSCody P Schafer * Either directly use a numeric term, or try to translate string terms 1320688d4dfcSCody P Schafer * using event parameters. 132116fa7e82SJiri Olsa */ 132299e7138eSJiri Olsa if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 132399e7138eSJiri Olsa if (term->no_value && 132499e7138eSJiri Olsa bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) { 132599e7138eSJiri Olsa if (err) { 13266c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1327448d732cSIan Rogers strdup("no value assigned for term"), 1328448d732cSIan Rogers NULL); 132999e7138eSJiri Olsa } 133099e7138eSJiri Olsa return -EINVAL; 133199e7138eSJiri Olsa } 133299e7138eSJiri Olsa 1333688d4dfcSCody P Schafer val = term->val.num; 133499e7138eSJiri Olsa } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1335688d4dfcSCody P Schafer if (strcmp(term->val.str, "?")) { 1336bb963e16SNamhyung Kim if (verbose > 0) { 1337688d4dfcSCody P Schafer pr_info("Invalid sysfs entry %s=%s\n", 1338688d4dfcSCody P Schafer term->config, term->val.str); 1339e64b020bSJiri Olsa } 1340e64b020bSJiri Olsa if (err) { 13416c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1342448d732cSIan Rogers strdup("expected numeric value"), 1343448d732cSIan Rogers NULL); 1344e64b020bSJiri Olsa } 1345688d4dfcSCody P Schafer return -EINVAL; 1346688d4dfcSCody P Schafer } 1347688d4dfcSCody P Schafer 1348688d4dfcSCody P Schafer if (pmu_resolve_param_term(term, head_terms, &val)) 1349688d4dfcSCody P Schafer return -EINVAL; 1350688d4dfcSCody P Schafer } else 1351688d4dfcSCody P Schafer return -EINVAL; 1352688d4dfcSCody P Schafer 13530efe6b67SAdrian Hunter max_val = pmu_format_max_value(format->bits); 13540efe6b67SAdrian Hunter if (val > max_val) { 13550efe6b67SAdrian Hunter if (err) { 1356448d732cSIan Rogers char *err_str; 1357448d732cSIan Rogers 13586c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1359448d732cSIan Rogers asprintf(&err_str, 13600efe6b67SAdrian Hunter "value too big for format, maximum is %llu", 1361448d732cSIan Rogers (unsigned long long)max_val) < 0 1362448d732cSIan Rogers ? strdup("value too big for format") 1363448d732cSIan Rogers : err_str, 1364448d732cSIan Rogers NULL); 13650efe6b67SAdrian Hunter return -EINVAL; 13660efe6b67SAdrian Hunter } 13670efe6b67SAdrian Hunter /* 13680efe6b67SAdrian Hunter * Assume we don't care if !err, in which case the value will be 13690efe6b67SAdrian Hunter * silently truncated. 13700efe6b67SAdrian Hunter */ 13710efe6b67SAdrian Hunter } 13720efe6b67SAdrian Hunter 1373688d4dfcSCody P Schafer pmu_format_value(format->bits, val, vp, zero); 1374cd82a32eSJiri Olsa return 0; 1375cd82a32eSJiri Olsa } 1376cd82a32eSJiri Olsa 13774ac22b48SIan Rogers int perf_pmu__config_terms(const char *pmu_name, struct list_head *formats, 1378cff7f956SJiri Olsa struct perf_event_attr *attr, 1379dc0a6202SAdrian Hunter struct list_head *head_terms, 1380e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1381cd82a32eSJiri Olsa { 13826cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 1383cd82a32eSJiri Olsa 1384688d4dfcSCody P Schafer list_for_each_entry(term, head_terms, list) { 13854ac22b48SIan Rogers if (pmu_config_term(pmu_name, formats, attr, term, head_terms, 1386e64b020bSJiri Olsa zero, err)) 1387cd82a32eSJiri Olsa return -EINVAL; 1388688d4dfcSCody P Schafer } 1389cd82a32eSJiri Olsa 1390cd82a32eSJiri Olsa return 0; 1391cd82a32eSJiri Olsa } 1392cd82a32eSJiri Olsa 1393cd82a32eSJiri Olsa /* 1394cd82a32eSJiri Olsa * Configures event's 'attr' parameter based on the: 1395cd82a32eSJiri Olsa * 1) users input - specified in terms parameter 1396cd82a32eSJiri Olsa * 2) pmu format definitions - specified by pmu parameter 1397cd82a32eSJiri Olsa */ 1398cd82a32eSJiri Olsa int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 1399e64b020bSJiri Olsa struct list_head *head_terms, 1400e64b020bSJiri Olsa struct parse_events_error *err) 1401cd82a32eSJiri Olsa { 1402dc0a6202SAdrian Hunter bool zero = !!pmu->default_config; 1403dc0a6202SAdrian Hunter 14044ac22b48SIan Rogers return perf_pmu__config_terms(pmu->name, &pmu->format, attr, 14054ac22b48SIan Rogers head_terms, zero, err); 1406cd82a32eSJiri Olsa } 1407cd82a32eSJiri Olsa 14085c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 14096cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 1410a6146d50SZheng Yan { 14115c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1412a6146d50SZheng Yan char *name; 1413a6146d50SZheng Yan 1414a6146d50SZheng Yan if (parse_events__is_hardcoded_term(term)) 1415a6146d50SZheng Yan return NULL; 1416a6146d50SZheng Yan 1417a6146d50SZheng Yan if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 1418a6146d50SZheng Yan if (term->val.num != 1) 1419a6146d50SZheng Yan return NULL; 1420a6146d50SZheng Yan if (pmu_find_format(&pmu->format, term->config)) 1421a6146d50SZheng Yan return NULL; 1422a6146d50SZheng Yan name = term->config; 1423a6146d50SZheng Yan } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1424a6146d50SZheng Yan if (strcasecmp(term->config, "event")) 1425a6146d50SZheng Yan return NULL; 1426a6146d50SZheng Yan name = term->val.str; 1427a6146d50SZheng Yan } else { 1428a6146d50SZheng Yan return NULL; 1429a6146d50SZheng Yan } 1430a6146d50SZheng Yan 1431a6146d50SZheng Yan list_for_each_entry(alias, &pmu->aliases, list) { 1432a6146d50SZheng Yan if (!strcasecmp(alias->name, name)) 1433a6146d50SZheng Yan return alias; 1434a6146d50SZheng Yan } 1435a6146d50SZheng Yan return NULL; 1436a6146d50SZheng Yan } 1437a6146d50SZheng Yan 1438410136f5SStephane Eranian 14391d9e446bSJiri Olsa static int check_info_data(struct perf_pmu_alias *alias, 14401d9e446bSJiri Olsa struct perf_pmu_info *info) 1441410136f5SStephane Eranian { 1442410136f5SStephane Eranian /* 1443410136f5SStephane Eranian * Only one term in event definition can 14441d9e446bSJiri Olsa * define unit, scale and snapshot, fail 14451d9e446bSJiri Olsa * if there's more than one. 1446410136f5SStephane Eranian */ 1447b30a7d1fSArnaldo Carvalho de Melo if ((info->unit && alias->unit[0]) || 14481d9e446bSJiri Olsa (info->scale && alias->scale) || 14491d9e446bSJiri Olsa (info->snapshot && alias->snapshot)) 1450410136f5SStephane Eranian return -EINVAL; 1451410136f5SStephane Eranian 1452b30a7d1fSArnaldo Carvalho de Melo if (alias->unit[0]) 14531d9e446bSJiri Olsa info->unit = alias->unit; 1454410136f5SStephane Eranian 1455410136f5SStephane Eranian if (alias->scale) 14561d9e446bSJiri Olsa info->scale = alias->scale; 14571d9e446bSJiri Olsa 14581d9e446bSJiri Olsa if (alias->snapshot) 14591d9e446bSJiri Olsa info->snapshot = alias->snapshot; 1460410136f5SStephane Eranian 1461410136f5SStephane Eranian return 0; 1462410136f5SStephane Eranian } 1463410136f5SStephane Eranian 1464a6146d50SZheng Yan /* 1465a6146d50SZheng Yan * Find alias in the terms list and replace it with the terms 1466a6146d50SZheng Yan * defined for the alias 1467a6146d50SZheng Yan */ 1468410136f5SStephane Eranian int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 146946441bdcSMatt Fleming struct perf_pmu_info *info) 1470a6146d50SZheng Yan { 14716cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 14725c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1473a6146d50SZheng Yan int ret; 1474a6146d50SZheng Yan 1475044330c1SMatt Fleming info->per_pkg = false; 1476044330c1SMatt Fleming 14778a398897SStephane Eranian /* 14788a398897SStephane Eranian * Mark unit and scale as not set 14798a398897SStephane Eranian * (different from default values, see below) 14808a398897SStephane Eranian */ 148146441bdcSMatt Fleming info->unit = NULL; 148246441bdcSMatt Fleming info->scale = 0.0; 14831d9e446bSJiri Olsa info->snapshot = false; 1484410136f5SStephane Eranian 1485a6146d50SZheng Yan list_for_each_entry_safe(term, h, head_terms, list) { 1486a6146d50SZheng Yan alias = pmu_find_alias(pmu, term); 1487a6146d50SZheng Yan if (!alias) 1488a6146d50SZheng Yan continue; 1489a6146d50SZheng Yan ret = pmu_alias_terms(alias, &term->list); 1490a6146d50SZheng Yan if (ret) 1491a6146d50SZheng Yan return ret; 1492410136f5SStephane Eranian 14931d9e446bSJiri Olsa ret = check_info_data(alias, info); 1494410136f5SStephane Eranian if (ret) 1495410136f5SStephane Eranian return ret; 1496410136f5SStephane Eranian 1497044330c1SMatt Fleming if (alias->per_pkg) 1498044330c1SMatt Fleming info->per_pkg = true; 1499044330c1SMatt Fleming 1500e56fbc9dSArnaldo Carvalho de Melo list_del_init(&term->list); 15011dc92556SIan Rogers parse_events_term__delete(term); 1502a6146d50SZheng Yan } 15038a398897SStephane Eranian 15048a398897SStephane Eranian /* 15058a398897SStephane Eranian * if no unit or scale found in aliases, then 15068a398897SStephane Eranian * set defaults as for evsel 15078a398897SStephane Eranian * unit cannot left to NULL 15088a398897SStephane Eranian */ 150946441bdcSMatt Fleming if (info->unit == NULL) 151046441bdcSMatt Fleming info->unit = ""; 15118a398897SStephane Eranian 151246441bdcSMatt Fleming if (info->scale == 0.0) 151346441bdcSMatt Fleming info->scale = 1.0; 15148a398897SStephane Eranian 1515a6146d50SZheng Yan return 0; 1516a6146d50SZheng Yan } 1517a6146d50SZheng Yan 1518cd82a32eSJiri Olsa int perf_pmu__new_format(struct list_head *list, char *name, 1519cd82a32eSJiri Olsa int config, unsigned long *bits) 1520cd82a32eSJiri Olsa { 15215c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1522cd82a32eSJiri Olsa 1523cd82a32eSJiri Olsa format = zalloc(sizeof(*format)); 1524cd82a32eSJiri Olsa if (!format) 1525cd82a32eSJiri Olsa return -ENOMEM; 1526cd82a32eSJiri Olsa 1527cd82a32eSJiri Olsa format->name = strdup(name); 1528cd82a32eSJiri Olsa format->value = config; 1529cd82a32eSJiri Olsa memcpy(format->bits, bits, sizeof(format->bits)); 1530cd82a32eSJiri Olsa 1531cd82a32eSJiri Olsa list_add_tail(&format->list, list); 1532cd82a32eSJiri Olsa return 0; 1533cd82a32eSJiri Olsa } 1534cd82a32eSJiri Olsa 1535cd82a32eSJiri Olsa void perf_pmu__set_format(unsigned long *bits, long from, long to) 1536cd82a32eSJiri Olsa { 1537cd82a32eSJiri Olsa long b; 1538cd82a32eSJiri Olsa 1539cd82a32eSJiri Olsa if (!to) 1540cd82a32eSJiri Olsa to = from; 1541cd82a32eSJiri Olsa 154215268138SSukadev Bhattiprolu memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS)); 1543cd82a32eSJiri Olsa for (b = from; b <= to; b++) 154449bd97c2SSean Christopherson __set_bit(b, bits); 1545cd82a32eSJiri Olsa } 1546dc098b35SAndi Kleen 1547d26383dcSNamhyung Kim void perf_pmu__del_formats(struct list_head *formats) 1548d26383dcSNamhyung Kim { 1549d26383dcSNamhyung Kim struct perf_pmu_format *fmt, *tmp; 1550d26383dcSNamhyung Kim 1551d26383dcSNamhyung Kim list_for_each_entry_safe(fmt, tmp, formats, list) { 1552d26383dcSNamhyung Kim list_del(&fmt->list); 1553efe98a7aSArnaldo Carvalho de Melo zfree(&fmt->name); 1554d26383dcSNamhyung Kim free(fmt); 1555d26383dcSNamhyung Kim } 1556d26383dcSNamhyung Kim } 1557d26383dcSNamhyung Kim 1558aaea3617SCody P Schafer static int sub_non_neg(int a, int b) 1559aaea3617SCody P Schafer { 1560aaea3617SCody P Schafer if (b > a) 1561aaea3617SCody P Schafer return 0; 1562aaea3617SCody P Schafer return a - b; 1563aaea3617SCody P Schafer } 1564aaea3617SCody P Schafer 1565eb2d4514SIan Rogers static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, 1566eb2d4514SIan Rogers const struct perf_pmu_alias *alias) 1567dc098b35SAndi Kleen { 1568aaea3617SCody P Schafer struct parse_events_term *term; 1569aaea3617SCody P Schafer int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name); 1570aaea3617SCody P Schafer 1571aaea3617SCody P Schafer list_for_each_entry(term, &alias->terms, list) { 1572aaea3617SCody P Schafer if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 1573aaea3617SCody P Schafer used += snprintf(buf + used, sub_non_neg(len, used), 1574aaea3617SCody P Schafer ",%s=%s", term->config, 1575aaea3617SCody P Schafer term->val.str); 1576aaea3617SCody P Schafer } 1577aaea3617SCody P Schafer 1578aaea3617SCody P Schafer if (sub_non_neg(len, used) > 0) { 1579aaea3617SCody P Schafer buf[used] = '/'; 1580aaea3617SCody P Schafer used++; 1581aaea3617SCody P Schafer } 1582aaea3617SCody P Schafer if (sub_non_neg(len, used) > 0) { 1583aaea3617SCody P Schafer buf[used] = '\0'; 1584aaea3617SCody P Schafer used++; 1585aaea3617SCody P Schafer } else 1586aaea3617SCody P Schafer buf[len - 1] = '\0'; 1587aaea3617SCody P Schafer 1588dc098b35SAndi Kleen return buf; 1589dc098b35SAndi Kleen } 1590dc098b35SAndi Kleen 1591eb2d4514SIan Rogers /** Struct for ordering events as output in perf list. */ 1592dd5f1036SAndi Kleen struct sevent { 1593eb2d4514SIan Rogers /** PMU for event. */ 1594eb2d4514SIan Rogers const struct perf_pmu *pmu; 1595eb2d4514SIan Rogers /** 1596eb2d4514SIan Rogers * Optional event for name, desc, etc. If not present then this is a 1597eb2d4514SIan Rogers * selectable PMU and the event name is shown as "//". 1598eb2d4514SIan Rogers */ 1599eb2d4514SIan Rogers const struct perf_pmu_alias *event; 1600eb2d4514SIan Rogers /** Is the PMU for the CPU? */ 1601eb2d4514SIan Rogers bool is_cpu; 160208e60ed1SAndi Kleen }; 160308e60ed1SAndi Kleen 1604dd5f1036SAndi Kleen static int cmp_sevent(const void *a, const void *b) 1605dc098b35SAndi Kleen { 1606dd5f1036SAndi Kleen const struct sevent *as = a; 1607dd5f1036SAndi Kleen const struct sevent *bs = b; 16083f980eabSIan Rogers const char *a_pmu_name = NULL, *b_pmu_name = NULL; 1609eb2d4514SIan Rogers const char *a_name = "//", *a_desc = NULL, *a_topic = ""; 1610eb2d4514SIan Rogers const char *b_name = "//", *b_desc = NULL, *b_topic = ""; 16110e0ae874SJin Yao int ret; 161208e60ed1SAndi Kleen 1613eb2d4514SIan Rogers if (as->event) { 1614eb2d4514SIan Rogers a_name = as->event->name; 1615eb2d4514SIan Rogers a_desc = as->event->desc; 1616eb2d4514SIan Rogers a_topic = as->event->topic ?: ""; 16173f980eabSIan Rogers a_pmu_name = as->event->pmu_name; 1618dd5f1036SAndi Kleen } 1619eb2d4514SIan Rogers if (bs->event) { 1620eb2d4514SIan Rogers b_name = bs->event->name; 1621eb2d4514SIan Rogers b_desc = bs->event->desc; 1622eb2d4514SIan Rogers b_topic = bs->event->topic ?: ""; 16233f980eabSIan Rogers b_pmu_name = bs->event->pmu_name; 1624eb2d4514SIan Rogers } 1625eb2d4514SIan Rogers /* Put extra events last. */ 1626eb2d4514SIan Rogers if (!!a_desc != !!b_desc) 1627eb2d4514SIan Rogers return !!a_desc - !!b_desc; 1628eb2d4514SIan Rogers 1629eb2d4514SIan Rogers /* Order by topics. */ 1630eb2d4514SIan Rogers ret = strcmp(a_topic, b_topic); 1631eb2d4514SIan Rogers if (ret) 1632eb2d4514SIan Rogers return ret; 1633ce0dc7d2SJohn Garry 1634ce0dc7d2SJohn Garry /* Order CPU core events to be first */ 1635ce0dc7d2SJohn Garry if (as->is_cpu != bs->is_cpu) 1636e5c6109fSIan Rogers return as->is_cpu ? -1 : 1; 1637ce0dc7d2SJohn Garry 1638eb2d4514SIan Rogers /* Order by PMU name. */ 16393f980eabSIan Rogers if (as->pmu != bs->pmu) { 16403f980eabSIan Rogers a_pmu_name = a_pmu_name ?: (as->pmu->name ?: ""); 16413f980eabSIan Rogers b_pmu_name = b_pmu_name ?: (bs->pmu->name ?: ""); 1642eb2d4514SIan Rogers ret = strcmp(a_pmu_name, b_pmu_name); 1643eb2d4514SIan Rogers if (ret) 16440e0ae874SJin Yao return ret; 16453f980eabSIan Rogers } 1646eb2d4514SIan Rogers 1647eb2d4514SIan Rogers /* Order by event name. */ 1648eb2d4514SIan Rogers return strcmp(a_name, b_name); 164908e60ed1SAndi Kleen } 165008e60ed1SAndi Kleen 1651d504fae9SJohn Garry bool is_pmu_core(const char *name) 1652d504fae9SJohn Garry { 16534bf7e81aSIan Rogers return !strcmp(name, "cpu") || is_sysfs_pmu_core(name); 16544bf7e81aSIan Rogers } 16554bf7e81aSIan Rogers 16564bf7e81aSIan Rogers bool is_pmu_hybrid(const char *name) 16574bf7e81aSIan Rogers { 16584bf7e81aSIan Rogers return !strcmp(name, "cpu_atom") || !strcmp(name, "cpu_core"); 1659d504fae9SJohn Garry } 1660d504fae9SJohn Garry 16616fd1e519SIan Rogers bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu) 16626fd1e519SIan Rogers { 1663*e20d1f2fSIan Rogers return pmu->is_core; 16646fd1e519SIan Rogers } 16656fd1e519SIan Rogers 16668bc75f69SIan Rogers bool perf_pmu__supports_wildcard_numeric(const struct perf_pmu *pmu) 16678bc75f69SIan Rogers { 1668*e20d1f2fSIan Rogers return pmu->is_core; 16698bc75f69SIan Rogers } 16708bc75f69SIan Rogers 167152c7b4d3SIan Rogers bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) 167252c7b4d3SIan Rogers { 16734bf7e81aSIan Rogers return !is_pmu_hybrid(pmu->name); 167452c7b4d3SIan Rogers } 167552c7b4d3SIan Rogers 1676e0257a01SJohn Garry static bool pmu_alias_is_duplicate(struct sevent *alias_a, 1677e0257a01SJohn Garry struct sevent *alias_b) 1678e0257a01SJohn Garry { 16793f980eabSIan Rogers const char *a_pmu_name = NULL, *b_pmu_name = NULL; 16803f980eabSIan Rogers const char *a_name = "//", *b_name = "//"; 16813f980eabSIan Rogers 16823f980eabSIan Rogers 16833f980eabSIan Rogers if (alias_a->event) { 16843f980eabSIan Rogers a_name = alias_a->event->name; 16853f980eabSIan Rogers a_pmu_name = alias_a->event->pmu_name; 16863f980eabSIan Rogers } 16873f980eabSIan Rogers if (alias_b->event) { 16883f980eabSIan Rogers b_name = alias_b->event->name; 16893f980eabSIan Rogers b_pmu_name = alias_b->event->pmu_name; 16903f980eabSIan Rogers } 1691eb2d4514SIan Rogers 1692e0257a01SJohn Garry /* Different names -> never duplicates */ 1693eb2d4514SIan Rogers if (strcmp(a_name, b_name)) 1694e0257a01SJohn Garry return false; 1695e0257a01SJohn Garry 1696eb2d4514SIan Rogers /* Don't remove duplicates for different PMUs */ 16973f980eabSIan Rogers a_pmu_name = a_pmu_name ?: (alias_a->pmu->name ?: ""); 16983f980eabSIan Rogers b_pmu_name = b_pmu_name ?: (alias_b->pmu->name ?: ""); 1699eb2d4514SIan Rogers return strcmp(a_pmu_name, b_pmu_name) == 0; 1700e0257a01SJohn Garry } 1701e0257a01SJohn Garry 1702e5c6109fSIan Rogers void print_pmu_events(const struct print_callbacks *print_cb, void *print_state) 1703dc098b35SAndi Kleen { 1704dc098b35SAndi Kleen struct perf_pmu *pmu; 1705e5c6109fSIan Rogers struct perf_pmu_alias *event; 1706dc098b35SAndi Kleen char buf[1024]; 1707dc098b35SAndi Kleen int printed = 0; 1708dc098b35SAndi Kleen int len, j; 1709dd5f1036SAndi Kleen struct sevent *aliases; 1710dc098b35SAndi Kleen 1711dc098b35SAndi Kleen pmu = NULL; 1712dc098b35SAndi Kleen len = 0; 171342634bc7SAdrian Hunter while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1714e5c6109fSIan Rogers list_for_each_entry(event, &pmu->aliases, list) 1715dc098b35SAndi Kleen len++; 171642634bc7SAdrian Hunter if (pmu->selectable) 171742634bc7SAdrian Hunter len++; 171842634bc7SAdrian Hunter } 1719dd5f1036SAndi Kleen aliases = zalloc(sizeof(struct sevent) * len); 1720eb2d4514SIan Rogers if (!aliases) { 1721eb2d4514SIan Rogers pr_err("FATAL: not enough memory to print PMU events\n"); 1722eb2d4514SIan Rogers return; 1723eb2d4514SIan Rogers } 1724dc098b35SAndi Kleen pmu = NULL; 1725dc098b35SAndi Kleen j = 0; 172642634bc7SAdrian Hunter while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1727*e20d1f2fSIan Rogers bool is_cpu = pmu->is_core; 1728eb2d4514SIan Rogers 1729e5c6109fSIan Rogers list_for_each_entry(event, &pmu->aliases, list) { 1730e5c6109fSIan Rogers aliases[j].event = event; 1731eb2d4514SIan Rogers aliases[j].pmu = pmu; 1732ce0dc7d2SJohn Garry aliases[j].is_cpu = is_cpu; 1733dc098b35SAndi Kleen j++; 1734dc098b35SAndi Kleen } 1735e5c6109fSIan Rogers if (pmu->selectable) { 1736eb2d4514SIan Rogers aliases[j].event = NULL; 1737eb2d4514SIan Rogers aliases[j].pmu = pmu; 1738eb2d4514SIan Rogers aliases[j].is_cpu = is_cpu; 173942634bc7SAdrian Hunter j++; 174042634bc7SAdrian Hunter } 174142634bc7SAdrian Hunter } 1742dc098b35SAndi Kleen len = j; 1743dd5f1036SAndi Kleen qsort(aliases, len, sizeof(struct sevent), cmp_sevent); 1744dc098b35SAndi Kleen for (j = 0; j < len; j++) { 1745e5c6109fSIan Rogers const char *name, *alias = NULL, *scale_unit = NULL, 1746e5c6109fSIan Rogers *desc = NULL, *long_desc = NULL, 17473f980eabSIan Rogers *encoding_desc = NULL, *topic = NULL, 17483f980eabSIan Rogers *pmu_name = NULL; 1749e5c6109fSIan Rogers bool deprecated = false; 1750e5c6109fSIan Rogers size_t buf_used; 1751eb2d4514SIan Rogers 175215b22ed3SAndi Kleen /* Skip duplicates */ 1753e0257a01SJohn Garry if (j > 0 && pmu_alias_is_duplicate(&aliases[j], &aliases[j - 1])) 175415b22ed3SAndi Kleen continue; 17550e0ae874SJin Yao 1756eb2d4514SIan Rogers if (!aliases[j].event) { 1757eb2d4514SIan Rogers /* A selectable event. */ 17583f980eabSIan Rogers pmu_name = aliases[j].pmu->name; 17593f980eabSIan Rogers buf_used = snprintf(buf, sizeof(buf), "%s//", pmu_name) + 1; 1760eb2d4514SIan Rogers name = buf; 1761eb2d4514SIan Rogers } else { 1762e5c6109fSIan Rogers if (aliases[j].event->desc) { 1763e5c6109fSIan Rogers name = aliases[j].event->name; 1764e5c6109fSIan Rogers buf_used = 0; 1765eb2d4514SIan Rogers } else { 1766eb2d4514SIan Rogers name = format_alias(buf, sizeof(buf), aliases[j].pmu, 1767eb2d4514SIan Rogers aliases[j].event); 1768e5c6109fSIan Rogers if (aliases[j].is_cpu) { 1769e5c6109fSIan Rogers alias = name; 1770e5c6109fSIan Rogers name = aliases[j].event->name; 1771eb2d4514SIan Rogers } 1772e5c6109fSIan Rogers buf_used = strlen(buf) + 1; 1773eb2d4514SIan Rogers } 17743f980eabSIan Rogers pmu_name = aliases[j].event->pmu_name ?: (aliases[j].pmu->name ?: ""); 1775e5c6109fSIan Rogers if (strlen(aliases[j].event->unit) || aliases[j].event->scale != 1.0) { 1776e5c6109fSIan Rogers scale_unit = buf + buf_used; 1777e5c6109fSIan Rogers buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 1778e5c6109fSIan Rogers "%G%s", aliases[j].event->scale, 1779e5c6109fSIan Rogers aliases[j].event->unit) + 1; 1780dc098b35SAndi Kleen } 1781e5c6109fSIan Rogers desc = aliases[j].event->desc; 1782e5c6109fSIan Rogers long_desc = aliases[j].event->long_desc; 1783eb2d4514SIan Rogers topic = aliases[j].event->topic; 1784e5c6109fSIan Rogers encoding_desc = buf + buf_used; 1785e5c6109fSIan Rogers buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 17863f980eabSIan Rogers "%s/%s/", pmu_name, aliases[j].event->str) + 1; 1787e5c6109fSIan Rogers deprecated = aliases[j].event->deprecated; 1788dd5f1036SAndi Kleen } 1789e5c6109fSIan Rogers print_cb->print_event(print_state, 17903f980eabSIan Rogers pmu_name, 1791e5c6109fSIan Rogers topic, 1792e5c6109fSIan Rogers name, 1793e5c6109fSIan Rogers alias, 1794e5c6109fSIan Rogers scale_unit, 1795e5c6109fSIan Rogers deprecated, 1796e5c6109fSIan Rogers "Kernel PMU event", 1797e5c6109fSIan Rogers desc, 1798e5c6109fSIan Rogers long_desc, 1799d9dc8874SIan Rogers encoding_desc); 1800dc098b35SAndi Kleen } 1801dfc431cbSArnaldo Carvalho de Melo if (printed && pager_in_use()) 1802dc098b35SAndi Kleen printf("\n"); 1803eb2d4514SIan Rogers 18047e4772dcSArnaldo Carvalho de Melo zfree(&aliases); 18057e4772dcSArnaldo Carvalho de Melo return; 1806dc098b35SAndi Kleen } 18074cabc3d1SAndi Kleen 18084cabc3d1SAndi Kleen bool pmu_have_event(const char *pname, const char *name) 18094cabc3d1SAndi Kleen { 18104cabc3d1SAndi Kleen struct perf_pmu *pmu; 18114cabc3d1SAndi Kleen struct perf_pmu_alias *alias; 18124cabc3d1SAndi Kleen 18134cabc3d1SAndi Kleen pmu = NULL; 18144cabc3d1SAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 18154cabc3d1SAndi Kleen if (strcmp(pname, pmu->name)) 18164cabc3d1SAndi Kleen continue; 18174cabc3d1SAndi Kleen list_for_each_entry(alias, &pmu->aliases, list) 18184cabc3d1SAndi Kleen if (!strcmp(alias->name, name)) 18194cabc3d1SAndi Kleen return true; 18204cabc3d1SAndi Kleen } 18214cabc3d1SAndi Kleen return false; 18224cabc3d1SAndi Kleen } 18237d4bdab5SAdrian Hunter 1824d50a79cdSJames Clark FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) 18257d4bdab5SAdrian Hunter { 18267d4bdab5SAdrian Hunter char path[PATH_MAX]; 18277d4bdab5SAdrian Hunter 1828f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name) || 1829f8ad6018SJames Clark !file_available(path)) 18307d4bdab5SAdrian Hunter return NULL; 18317d4bdab5SAdrian Hunter 18327d4bdab5SAdrian Hunter return fopen(path, "r"); 18337d4bdab5SAdrian Hunter } 18347d4bdab5SAdrian Hunter 18353a69672eSNamhyung Kim FILE *perf_pmu__open_file_at(struct perf_pmu *pmu, int dirfd, const char *name) 18363a69672eSNamhyung Kim { 18373a69672eSNamhyung Kim int fd; 18383a69672eSNamhyung Kim 18393a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, pmu->name, name, O_RDONLY); 18403a69672eSNamhyung Kim if (fd < 0) 18413a69672eSNamhyung Kim return NULL; 18423a69672eSNamhyung Kim 18433a69672eSNamhyung Kim return fdopen(fd, "r"); 18443a69672eSNamhyung Kim } 18453a69672eSNamhyung Kim 18467d4bdab5SAdrian Hunter int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 18477d4bdab5SAdrian Hunter ...) 18487d4bdab5SAdrian Hunter { 18497d4bdab5SAdrian Hunter va_list args; 18507d4bdab5SAdrian Hunter FILE *file; 18517d4bdab5SAdrian Hunter int ret = EOF; 18527d4bdab5SAdrian Hunter 18537d4bdab5SAdrian Hunter va_start(args, fmt); 18547d4bdab5SAdrian Hunter file = perf_pmu__open_file(pmu, name); 18557d4bdab5SAdrian Hunter if (file) { 18567d4bdab5SAdrian Hunter ret = vfscanf(file, fmt, args); 18577d4bdab5SAdrian Hunter fclose(file); 18587d4bdab5SAdrian Hunter } 18597d4bdab5SAdrian Hunter va_end(args); 18607d4bdab5SAdrian Hunter return ret; 18617d4bdab5SAdrian Hunter } 18629fbc61f8SKan Liang 18633a69672eSNamhyung Kim int perf_pmu__scan_file_at(struct perf_pmu *pmu, int dirfd, const char *name, 18643a69672eSNamhyung Kim const char *fmt, ...) 18653a69672eSNamhyung Kim { 18663a69672eSNamhyung Kim va_list args; 18673a69672eSNamhyung Kim FILE *file; 18683a69672eSNamhyung Kim int ret = EOF; 18693a69672eSNamhyung Kim 18703a69672eSNamhyung Kim va_start(args, fmt); 18713a69672eSNamhyung Kim file = perf_pmu__open_file_at(pmu, dirfd, name); 18723a69672eSNamhyung Kim if (file) { 18733a69672eSNamhyung Kim ret = vfscanf(file, fmt, args); 18743a69672eSNamhyung Kim fclose(file); 18753a69672eSNamhyung Kim } 18763a69672eSNamhyung Kim va_end(args); 18773a69672eSNamhyung Kim return ret; 18783a69672eSNamhyung Kim } 18793a69672eSNamhyung Kim 1880c2b6a896SGerman Gomez bool perf_pmu__file_exists(struct perf_pmu *pmu, const char *name) 1881c2b6a896SGerman Gomez { 1882c2b6a896SGerman Gomez char path[PATH_MAX]; 1883c2b6a896SGerman Gomez 1884c2b6a896SGerman Gomez if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name)) 1885c2b6a896SGerman Gomez return false; 1886c2b6a896SGerman Gomez 1887c2b6a896SGerman Gomez return file_available(path); 1888c2b6a896SGerman Gomez } 1889c2b6a896SGerman Gomez 18909fbc61f8SKan Liang static int perf_pmu__new_caps(struct list_head *list, char *name, char *value) 18919fbc61f8SKan Liang { 18929fbc61f8SKan Liang struct perf_pmu_caps *caps = zalloc(sizeof(*caps)); 18939fbc61f8SKan Liang 18949fbc61f8SKan Liang if (!caps) 18959fbc61f8SKan Liang return -ENOMEM; 18969fbc61f8SKan Liang 18979fbc61f8SKan Liang caps->name = strdup(name); 18989fbc61f8SKan Liang if (!caps->name) 18999fbc61f8SKan Liang goto free_caps; 19009fbc61f8SKan Liang caps->value = strndup(value, strlen(value) - 1); 19019fbc61f8SKan Liang if (!caps->value) 19029fbc61f8SKan Liang goto free_name; 19039fbc61f8SKan Liang list_add_tail(&caps->list, list); 19049fbc61f8SKan Liang return 0; 19059fbc61f8SKan Liang 19069fbc61f8SKan Liang free_name: 190757f14b5aSArnaldo Carvalho de Melo zfree(&caps->name); 19089fbc61f8SKan Liang free_caps: 19099fbc61f8SKan Liang free(caps); 19109fbc61f8SKan Liang 19119fbc61f8SKan Liang return -ENOMEM; 19129fbc61f8SKan Liang } 19139fbc61f8SKan Liang 1914eec11310SNamhyung Kim static void perf_pmu__del_caps(struct perf_pmu *pmu) 1915eec11310SNamhyung Kim { 1916eec11310SNamhyung Kim struct perf_pmu_caps *caps, *tmp; 1917eec11310SNamhyung Kim 1918eec11310SNamhyung Kim list_for_each_entry_safe(caps, tmp, &pmu->caps, list) { 1919eec11310SNamhyung Kim list_del(&caps->list); 1920efe98a7aSArnaldo Carvalho de Melo zfree(&caps->name); 1921efe98a7aSArnaldo Carvalho de Melo zfree(&caps->value); 1922eec11310SNamhyung Kim free(caps); 1923eec11310SNamhyung Kim } 1924eec11310SNamhyung Kim } 1925eec11310SNamhyung Kim 19269fbc61f8SKan Liang /* 19279fbc61f8SKan Liang * Reading/parsing the given pmu capabilities, which should be located at: 19289fbc61f8SKan Liang * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes. 19299fbc61f8SKan Liang * Return the number of capabilities 19309fbc61f8SKan Liang */ 19319fbc61f8SKan Liang int perf_pmu__caps_parse(struct perf_pmu *pmu) 19329fbc61f8SKan Liang { 19339fbc61f8SKan Liang struct stat st; 19349fbc61f8SKan Liang char caps_path[PATH_MAX]; 19359fbc61f8SKan Liang DIR *caps_dir; 19369fbc61f8SKan Liang struct dirent *evt_ent; 1937b39094d3SNamhyung Kim int caps_fd; 19383339ec44SRavi Bangoria 19393339ec44SRavi Bangoria if (pmu->caps_initialized) 19403339ec44SRavi Bangoria return pmu->nr_caps; 19413339ec44SRavi Bangoria 19423339ec44SRavi Bangoria pmu->nr_caps = 0; 19439fbc61f8SKan Liang 1944f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(caps_path, sizeof(caps_path), pmu->name, "caps")) 19459fbc61f8SKan Liang return -1; 19469fbc61f8SKan Liang 19473339ec44SRavi Bangoria if (stat(caps_path, &st) < 0) { 19483339ec44SRavi Bangoria pmu->caps_initialized = true; 19499fbc61f8SKan Liang return 0; /* no error if caps does not exist */ 19503339ec44SRavi Bangoria } 19519fbc61f8SKan Liang 19529fbc61f8SKan Liang caps_dir = opendir(caps_path); 19539fbc61f8SKan Liang if (!caps_dir) 19549fbc61f8SKan Liang return -EINVAL; 19559fbc61f8SKan Liang 1956b39094d3SNamhyung Kim caps_fd = dirfd(caps_dir); 1957b39094d3SNamhyung Kim 19589fbc61f8SKan Liang while ((evt_ent = readdir(caps_dir)) != NULL) { 19599fbc61f8SKan Liang char *name = evt_ent->d_name; 19609fbc61f8SKan Liang char value[128]; 19619fbc61f8SKan Liang FILE *file; 1962b39094d3SNamhyung Kim int fd; 19639fbc61f8SKan Liang 19649fbc61f8SKan Liang if (!strcmp(name, ".") || !strcmp(name, "..")) 19659fbc61f8SKan Liang continue; 19669fbc61f8SKan Liang 1967b39094d3SNamhyung Kim fd = openat(caps_fd, name, O_RDONLY); 19680ea8920eSIan Rogers if (fd == -1) 19699fbc61f8SKan Liang continue; 19700ea8920eSIan Rogers file = fdopen(fd, "r"); 19710ea8920eSIan Rogers if (!file) { 19720ea8920eSIan Rogers close(fd); 19730ea8920eSIan Rogers continue; 19740ea8920eSIan Rogers } 19759fbc61f8SKan Liang 19769fbc61f8SKan Liang if (!fgets(value, sizeof(value), file) || 19779fbc61f8SKan Liang (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) { 19789fbc61f8SKan Liang fclose(file); 19799fbc61f8SKan Liang continue; 19809fbc61f8SKan Liang } 19819fbc61f8SKan Liang 19823339ec44SRavi Bangoria pmu->nr_caps++; 19839fbc61f8SKan Liang fclose(file); 19849fbc61f8SKan Liang } 19859fbc61f8SKan Liang 19869fbc61f8SKan Liang closedir(caps_dir); 19879fbc61f8SKan Liang 19883339ec44SRavi Bangoria pmu->caps_initialized = true; 19893339ec44SRavi Bangoria return pmu->nr_caps; 19909fbc61f8SKan Liang } 1991e4064776SJin Yao 1992e4064776SJin Yao void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 19938e8bbfb3SIan Rogers const char *name) 1994e4064776SJin Yao { 1995e4064776SJin Yao struct perf_pmu_format *format; 1996e4064776SJin Yao __u64 masks = 0, bits; 1997e4064776SJin Yao char buf[100]; 1998e4064776SJin Yao unsigned int i; 1999e4064776SJin Yao 2000e4064776SJin Yao list_for_each_entry(format, &pmu->format, list) { 2001e4064776SJin Yao if (format->value != PERF_PMU_FORMAT_VALUE_CONFIG) 2002e4064776SJin Yao continue; 2003e4064776SJin Yao 2004e4064776SJin Yao for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS) 2005e4064776SJin Yao masks |= 1ULL << i; 2006e4064776SJin Yao } 2007e4064776SJin Yao 2008e4064776SJin Yao /* 2009e4064776SJin Yao * Kernel doesn't export any valid format bits. 2010e4064776SJin Yao */ 2011e4064776SJin Yao if (masks == 0) 2012e4064776SJin Yao return; 2013e4064776SJin Yao 2014e4064776SJin Yao bits = config & ~masks; 2015e4064776SJin Yao if (bits == 0) 2016e4064776SJin Yao return; 2017e4064776SJin Yao 2018e4064776SJin Yao bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf)); 2019e4064776SJin Yao 2020e4064776SJin Yao pr_warning("WARNING: event '%s' not valid (bits %s of config " 2021e4064776SJin Yao "'%llx' not supported by kernel)!\n", 2022e4064776SJin Yao name ?: "N/A", buf, config); 2023e4064776SJin Yao } 2024c5a26ea4SJin Yao 2025c5a26ea4SJin Yao bool perf_pmu__has_hybrid(void) 2026c5a26ea4SJin Yao { 2027c5a26ea4SJin Yao if (!hybrid_scanned) { 2028c5a26ea4SJin Yao hybrid_scanned = true; 2029c5a26ea4SJin Yao perf_pmu__scan(NULL); 2030c5a26ea4SJin Yao } 2031c5a26ea4SJin Yao 2032c5a26ea4SJin Yao return !list_empty(&perf_pmu__hybrid_pmus); 2033c5a26ea4SJin Yao } 2034c47a5599SJin Yao 2035c47a5599SJin Yao int perf_pmu__match(char *pattern, char *name, char *tok) 2036c47a5599SJin Yao { 203713d60ba0SKan Liang if (!name) 203813d60ba0SKan Liang return -1; 203913d60ba0SKan Liang 2040c47a5599SJin Yao if (fnmatch(pattern, name, 0)) 2041c47a5599SJin Yao return -1; 2042c47a5599SJin Yao 2043240e6fd0SIan Rogers if (tok && !perf_pmu__match_ignoring_suffix(name, tok)) 2044c47a5599SJin Yao return -1; 2045c47a5599SJin Yao 2046c47a5599SJin Yao return 0; 2047c47a5599SJin Yao } 20481d3351e6SJin Yao 20491d3351e6SJin Yao int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus, 20501d3351e6SJin Yao struct perf_cpu_map **mcpus_ptr, 20511d3351e6SJin Yao struct perf_cpu_map **ucpus_ptr) 20521d3351e6SJin Yao { 20531d3351e6SJin Yao struct perf_cpu_map *pmu_cpus = pmu->cpus; 20541d3351e6SJin Yao struct perf_cpu_map *matched_cpus, *unmatched_cpus; 20556a12a63eSIan Rogers struct perf_cpu cpu; 20566a12a63eSIan Rogers int i, matched_nr = 0, unmatched_nr = 0; 20571d3351e6SJin Yao 20581d3351e6SJin Yao matched_cpus = perf_cpu_map__default_new(); 20591d3351e6SJin Yao if (!matched_cpus) 20601d3351e6SJin Yao return -1; 20611d3351e6SJin Yao 20621d3351e6SJin Yao unmatched_cpus = perf_cpu_map__default_new(); 20631d3351e6SJin Yao if (!unmatched_cpus) { 20641d3351e6SJin Yao perf_cpu_map__put(matched_cpus); 20651d3351e6SJin Yao return -1; 20661d3351e6SJin Yao } 20671d3351e6SJin Yao 20686a12a63eSIan Rogers perf_cpu_map__for_each_cpu(cpu, i, cpus) { 20696a12a63eSIan Rogers if (!perf_cpu_map__has(pmu_cpus, cpu)) 2070da885a0eSIan Rogers RC_CHK_ACCESS(unmatched_cpus)->map[unmatched_nr++] = cpu; 20711d3351e6SJin Yao else 2072da885a0eSIan Rogers RC_CHK_ACCESS(matched_cpus)->map[matched_nr++] = cpu; 20731d3351e6SJin Yao } 20741d3351e6SJin Yao 20759efe423eSArnaldo Carvalho de Melo perf_cpu_map__set_nr(unmatched_cpus, unmatched_nr); 20769efe423eSArnaldo Carvalho de Melo perf_cpu_map__set_nr(matched_cpus, matched_nr); 20771d3351e6SJin Yao *mcpus_ptr = matched_cpus; 20781d3351e6SJin Yao *ucpus_ptr = unmatched_cpus; 20791d3351e6SJin Yao return 0; 20801d3351e6SJin Yao } 2081acef233bSJing Zhang 2082acef233bSJing Zhang double __weak perf_pmu__cpu_slots_per_cycle(void) 2083acef233bSJing Zhang { 2084acef233bSJing Zhang return NAN; 2085acef233bSJing Zhang } 2086f8ad6018SJames Clark 2087f8ad6018SJames Clark int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size) 2088f8ad6018SJames Clark { 2089f8ad6018SJames Clark const char *sysfs = sysfs__mountpoint(); 2090f8ad6018SJames Clark 2091f8ad6018SJames Clark if (!sysfs) 2092f8ad6018SJames Clark return 0; 2093f8ad6018SJames Clark return scnprintf(pathname, size, "%s/bus/event_source/devices/", sysfs); 2094f8ad6018SJames Clark } 2095f8ad6018SJames Clark 2096e293a5e8SNamhyung Kim int perf_pmu__event_source_devices_fd(void) 2097e293a5e8SNamhyung Kim { 2098e293a5e8SNamhyung Kim char path[PATH_MAX]; 2099e293a5e8SNamhyung Kim const char *sysfs = sysfs__mountpoint(); 2100e293a5e8SNamhyung Kim 2101e293a5e8SNamhyung Kim if (!sysfs) 2102e293a5e8SNamhyung Kim return -1; 2103e293a5e8SNamhyung Kim 2104e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs); 2105e293a5e8SNamhyung Kim return open(path, O_DIRECTORY); 2106e293a5e8SNamhyung Kim } 2107e293a5e8SNamhyung Kim 2108f8ad6018SJames Clark /* 2109f8ad6018SJames Clark * Fill 'buf' with the path to a file or folder in 'pmu_name' in 2110f8ad6018SJames Clark * sysfs. For example if pmu_name = "cs_etm" and 'filename' = "format" 2111f8ad6018SJames Clark * then pathname will be filled with 2112f8ad6018SJames Clark * "/sys/bus/event_source/devices/cs_etm/format" 2113f8ad6018SJames Clark * 2114f8ad6018SJames Clark * Return 0 if the sysfs mountpoint couldn't be found or if no 2115f8ad6018SJames Clark * characters were written. 2116f8ad6018SJames Clark */ 2117f8ad6018SJames Clark int perf_pmu__pathname_scnprintf(char *buf, size_t size, 2118f8ad6018SJames Clark const char *pmu_name, const char *filename) 2119f8ad6018SJames Clark { 2120f8ad6018SJames Clark char base_path[PATH_MAX]; 2121f8ad6018SJames Clark 2122f8ad6018SJames Clark if (!perf_pmu__event_source_devices_scnprintf(base_path, sizeof(base_path))) 2123f8ad6018SJames Clark return 0; 2124f8ad6018SJames Clark return scnprintf(buf, size, "%s%s/%s", base_path, pmu_name, filename); 2125f8ad6018SJames Clark } 2126eec11310SNamhyung Kim 2127e293a5e8SNamhyung Kim int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags) 2128e293a5e8SNamhyung Kim { 2129e293a5e8SNamhyung Kim char path[PATH_MAX]; 2130e293a5e8SNamhyung Kim 2131e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/%s", pmu_name, filename); 2132e293a5e8SNamhyung Kim return openat(dirfd, path, flags); 2133e293a5e8SNamhyung Kim } 2134e293a5e8SNamhyung Kim 2135eec11310SNamhyung Kim static void perf_pmu__delete(struct perf_pmu *pmu) 2136eec11310SNamhyung Kim { 2137eec11310SNamhyung Kim perf_pmu__del_formats(&pmu->format); 2138eec11310SNamhyung Kim perf_pmu__del_aliases(pmu); 2139eec11310SNamhyung Kim perf_pmu__del_caps(pmu); 2140eec11310SNamhyung Kim 2141eec11310SNamhyung Kim perf_cpu_map__put(pmu->cpus); 2142eec11310SNamhyung Kim 2143efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->default_config); 2144efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 2145efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->alias_name); 2146eec11310SNamhyung Kim free(pmu); 2147eec11310SNamhyung Kim } 2148eec11310SNamhyung Kim 2149eec11310SNamhyung Kim void perf_pmu__destroy(void) 2150eec11310SNamhyung Kim { 2151eec11310SNamhyung Kim struct perf_pmu *pmu, *tmp; 2152eec11310SNamhyung Kim 2153eec11310SNamhyung Kim list_for_each_entry_safe(pmu, tmp, &pmus, list) { 2154eec11310SNamhyung Kim list_del(&pmu->list); 2155eec11310SNamhyung Kim list_del(&pmu->hybrid_list); 2156eec11310SNamhyung Kim 2157eec11310SNamhyung Kim perf_pmu__delete(pmu); 2158eec11310SNamhyung Kim } 2159eec11310SNamhyung Kim } 2160