1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2cd82a32eSJiri Olsa #include <linux/list.h> 3c5de47f2SSukadev Bhattiprolu #include <linux/compiler.h> 432858480SArnaldo Carvalho de Melo #include <linux/string.h> 57f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h> 6c47a5599SJin Yao #include <linux/ctype.h> 7cd82a32eSJiri Olsa #include <sys/types.h> 8c23c2a0fSArnaldo Carvalho de Melo #include <fcntl.h> 97a8ef4c4SArnaldo Carvalho de Melo #include <sys/stat.h> 10cd82a32eSJiri Olsa #include <unistd.h> 11cd82a32eSJiri Olsa #include <stdio.h> 12dc0a6202SAdrian Hunter #include <stdbool.h> 13cd82a32eSJiri Olsa #include <dirent.h> 14cd0cfad7SBorislav Petkov #include <api/fs/fs.h> 15410136f5SStephane Eranian #include <locale.h> 16c47a5599SJin Yao #include <fnmatch.h> 17acef233bSJing Zhang #include <math.h> 185e51b0bbSArnaldo Carvalho de Melo #include "debug.h" 19e12ee9f7SAdrian Hunter #include "evsel.h" 20cd82a32eSJiri Olsa #include "pmu.h" 21336b92daSRavi Bangoria #include "pmus.h" 22c7e97f21SNamhyung Kim #include <util/pmu-bison.h> 23c7e97f21SNamhyung Kim #include <util/pmu-flex.h> 24cd82a32eSJiri Olsa #include "parse-events.h" 25e5c6109fSIan Rogers #include "print-events.h" 26933f82ffSSukadev Bhattiprolu #include "header.h" 27a067558eSArnaldo Carvalho de Melo #include "string2.h" 28fa0d9846SArnaldo Carvalho de Melo #include "strbuf.h" 29d9664582SAndi Kleen #include "fncache.h" 306593f019SJames Clark #include "util/evsel_config.h" 312879ff36SJing Zhang #include <regex.h> 32cd82a32eSJiri Olsa 33c091ee90SIan Rogers struct perf_pmu perf_pmu__fake = { 34c091ee90SIan Rogers .name = "fake", 35c091ee90SIan Rogers }; 36e46fc8d9SArnaldo Carvalho de Melo 37c3245d20SIan Rogers #define UNIT_MAX_LEN 31 /* max length for event unit name */ 38c3245d20SIan Rogers 39d9c5f5f9SIan Rogers enum event_source { 40d9c5f5f9SIan Rogers /* An event loaded from /sys/devices/<pmu>/events. */ 41d9c5f5f9SIan Rogers EVENT_SRC_SYSFS, 42d9c5f5f9SIan Rogers /* An event loaded from a CPUID matched json file. */ 43d9c5f5f9SIan Rogers EVENT_SRC_CPU_JSON, 44d9c5f5f9SIan Rogers /* 45d9c5f5f9SIan Rogers * An event loaded from a /sys/devices/<pmu>/identifier matched json 46d9c5f5f9SIan Rogers * file. 47d9c5f5f9SIan Rogers */ 48d9c5f5f9SIan Rogers EVENT_SRC_SYS_JSON, 49d9c5f5f9SIan Rogers }; 50d9c5f5f9SIan Rogers 51c3245d20SIan Rogers /** 52c3245d20SIan Rogers * struct perf_pmu_alias - An event either read from sysfs or builtin in 53c3245d20SIan Rogers * pmu-events.c, created by parsing the pmu-events json files. 54c3245d20SIan Rogers */ 55c3245d20SIan Rogers struct perf_pmu_alias { 56c3245d20SIan Rogers /** @name: Name of the event like "mem-loads". */ 57c3245d20SIan Rogers char *name; 58c3245d20SIan Rogers /** @desc: Optional short description of the event. */ 59c3245d20SIan Rogers char *desc; 60c3245d20SIan Rogers /** @long_desc: Optional long description. */ 61c3245d20SIan Rogers char *long_desc; 62c3245d20SIan Rogers /** 63c3245d20SIan Rogers * @topic: Optional topic such as cache or pipeline, particularly for 64c3245d20SIan Rogers * json events. 65c3245d20SIan Rogers */ 66c3245d20SIan Rogers char *topic; 67c3245d20SIan Rogers /** @terms: Owned list of the original parsed parameters. */ 680d3f0e6fSIan Rogers struct parse_events_terms terms; 69c3245d20SIan Rogers /** @list: List element of struct perf_pmu aliases. */ 70c3245d20SIan Rogers struct list_head list; 717b723dbbSIan Rogers /** 727b723dbbSIan Rogers * @pmu_name: The name copied from the json struct pmu_event. This can 737b723dbbSIan Rogers * differ from the PMU name as it won't have suffixes. 747b723dbbSIan Rogers */ 757b723dbbSIan Rogers char *pmu_name; 76c3245d20SIan Rogers /** @unit: Units for the event, such as bytes or cache lines. */ 77c3245d20SIan Rogers char unit[UNIT_MAX_LEN+1]; 78c3245d20SIan Rogers /** @scale: Value to scale read counter values by. */ 79c3245d20SIan Rogers double scale; 80c3245d20SIan Rogers /** 81c3245d20SIan Rogers * @per_pkg: Does the file 82c3245d20SIan Rogers * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.per-pkg or 83c3245d20SIan Rogers * equivalent json value exist and have the value 1. 84c3245d20SIan Rogers */ 85c3245d20SIan Rogers bool per_pkg; 86c3245d20SIan Rogers /** 87c3245d20SIan Rogers * @snapshot: Does the file 88c3245d20SIan Rogers * <sysfs>/bus/event_source/devices/<pmu_name>/events/<name>.snapshot 89c3245d20SIan Rogers * exist and have the value 1. 90c3245d20SIan Rogers */ 91c3245d20SIan Rogers bool snapshot; 92c3245d20SIan Rogers /** 93c3245d20SIan Rogers * @deprecated: Is the event hidden and so not shown in perf list by 94c3245d20SIan Rogers * default. 95c3245d20SIan Rogers */ 96c3245d20SIan Rogers bool deprecated; 977b723dbbSIan Rogers /** @from_sysfs: Was the alias from sysfs or a json event? */ 987b723dbbSIan Rogers bool from_sysfs; 997b723dbbSIan Rogers /** @info_loaded: Have the scale, unit and other values been read from disk? */ 1007b723dbbSIan Rogers bool info_loaded; 101c3245d20SIan Rogers }; 102c3245d20SIan Rogers 103fe13d43dSIan Rogers /** 104fe13d43dSIan Rogers * struct perf_pmu_format - Values from a format file read from 105fe13d43dSIan Rogers * <sysfs>/devices/cpu/format/ held in struct perf_pmu. 106fe13d43dSIan Rogers * 107fe13d43dSIan Rogers * For example, the contents of <sysfs>/devices/cpu/format/event may be 108fe13d43dSIan Rogers * "config:0-7" and will be represented here as name="event", 109fe13d43dSIan Rogers * value=PERF_PMU_FORMAT_VALUE_CONFIG and bits 0 to 7 will be set. 110fe13d43dSIan Rogers */ 111ab1bf653SArnaldo Carvalho de Melo struct perf_pmu_format { 11250402641SIan Rogers /** @list: Element on list within struct perf_pmu. */ 11350402641SIan Rogers struct list_head list; 11450402641SIan Rogers /** @bits: Which config bits are set by this format value. */ 11550402641SIan Rogers DECLARE_BITMAP(bits, PERF_PMU_FORMAT_BITS); 116fe13d43dSIan Rogers /** @name: The modifier/file name. */ 117ab1bf653SArnaldo Carvalho de Melo char *name; 118fe13d43dSIan Rogers /** 119fe13d43dSIan Rogers * @value : Which config value the format relates to. Supported values 120fe13d43dSIan Rogers * are from PERF_PMU_FORMAT_VALUE_CONFIG to 121fe13d43dSIan Rogers * PERF_PMU_FORMAT_VALUE_CONFIG_END. 122fe13d43dSIan Rogers */ 12350402641SIan Rogers u16 value; 12450402641SIan Rogers /** @loaded: Has the contents been loaded/parsed. */ 12550402641SIan Rogers bool loaded; 126ab1bf653SArnaldo Carvalho de Melo }; 127ab1bf653SArnaldo Carvalho de Melo 1288d4b6d37SIan Rogers static int pmu_aliases_parse(struct perf_pmu *pmu); 1298d4b6d37SIan Rogers 13050402641SIan Rogers static struct perf_pmu_format *perf_pmu__new_format(struct list_head *list, char *name) 13150402641SIan Rogers { 13250402641SIan Rogers struct perf_pmu_format *format; 13350402641SIan Rogers 13450402641SIan Rogers format = zalloc(sizeof(*format)); 13550402641SIan Rogers if (!format) 13650402641SIan Rogers return NULL; 13750402641SIan Rogers 13850402641SIan Rogers format->name = strdup(name); 13950402641SIan Rogers if (!format->name) { 14050402641SIan Rogers free(format); 14150402641SIan Rogers return NULL; 14250402641SIan Rogers } 14350402641SIan Rogers list_add_tail(&format->list, list); 14450402641SIan Rogers return format; 14550402641SIan Rogers } 14650402641SIan Rogers 14750402641SIan Rogers /* Called at the end of parsing a format. */ 14850402641SIan Rogers void perf_pmu_format__set_value(void *vformat, int config, unsigned long *bits) 14950402641SIan Rogers { 15050402641SIan Rogers struct perf_pmu_format *format = vformat; 15150402641SIan Rogers 15250402641SIan Rogers format->value = config; 15350402641SIan Rogers memcpy(format->bits, bits, sizeof(format->bits)); 15450402641SIan Rogers } 15550402641SIan Rogers 15650402641SIan Rogers static void __perf_pmu_format__load(struct perf_pmu_format *format, FILE *file) 15750402641SIan Rogers { 15850402641SIan Rogers void *scanner; 15950402641SIan Rogers int ret; 16050402641SIan Rogers 16150402641SIan Rogers ret = perf_pmu_lex_init(&scanner); 16250402641SIan Rogers if (ret) 16350402641SIan Rogers return; 16450402641SIan Rogers 16550402641SIan Rogers perf_pmu_set_in(file, scanner); 16650402641SIan Rogers ret = perf_pmu_parse(format, scanner); 16750402641SIan Rogers perf_pmu_lex_destroy(scanner); 16850402641SIan Rogers format->loaded = true; 16950402641SIan Rogers } 17050402641SIan Rogers 17163883cb0SIan Rogers static void perf_pmu_format__load(const struct perf_pmu *pmu, struct perf_pmu_format *format) 17250402641SIan Rogers { 17350402641SIan Rogers char path[PATH_MAX]; 17450402641SIan Rogers FILE *file = NULL; 17550402641SIan Rogers 17650402641SIan Rogers if (format->loaded) 17750402641SIan Rogers return; 17850402641SIan Rogers 17950402641SIan Rogers if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, "format")) 18050402641SIan Rogers return; 18150402641SIan Rogers 18250402641SIan Rogers assert(strlen(path) + strlen(format->name) + 2 < sizeof(path)); 18350402641SIan Rogers strcat(path, "/"); 18450402641SIan Rogers strcat(path, format->name); 18550402641SIan Rogers 18650402641SIan Rogers file = fopen(path, "r"); 18750402641SIan Rogers if (!file) 18850402641SIan Rogers return; 18950402641SIan Rogers __perf_pmu_format__load(format, file); 19050402641SIan Rogers fclose(file); 19150402641SIan Rogers } 19250402641SIan Rogers 193cd82a32eSJiri Olsa /* 194cd82a32eSJiri Olsa * Parse & process all the sysfs attributes located under 195cd82a32eSJiri Olsa * the directory specified in 'dir' parameter. 196cd82a32eSJiri Olsa */ 197aa1551f2SIan Rogers static int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load) 198cd82a32eSJiri Olsa { 199cd82a32eSJiri Olsa struct dirent *evt_ent; 200cd82a32eSJiri Olsa DIR *format_dir; 201cd82a32eSJiri Olsa int ret = 0; 202cd82a32eSJiri Olsa 203e293a5e8SNamhyung Kim format_dir = fdopendir(dirfd); 204cd82a32eSJiri Olsa if (!format_dir) 205cd82a32eSJiri Olsa return -EINVAL; 206cd82a32eSJiri Olsa 20750402641SIan Rogers while ((evt_ent = readdir(format_dir)) != NULL) { 20850402641SIan Rogers struct perf_pmu_format *format; 209cd82a32eSJiri Olsa char *name = evt_ent->d_name; 210cd82a32eSJiri Olsa 211cd82a32eSJiri Olsa if (!strcmp(name, ".") || !strcmp(name, "..")) 212cd82a32eSJiri Olsa continue; 213cd82a32eSJiri Olsa 21450402641SIan Rogers format = perf_pmu__new_format(&pmu->format, name); 21550402641SIan Rogers if (!format) { 21650402641SIan Rogers ret = -ENOMEM; 217cd82a32eSJiri Olsa break; 21850402641SIan Rogers } 219cd82a32eSJiri Olsa 22050402641SIan Rogers if (eager_load) { 22150402641SIan Rogers FILE *file; 22250402641SIan Rogers int fd = openat(dirfd, name, O_RDONLY); 22350402641SIan Rogers 22450402641SIan Rogers if (fd < 0) { 22550402641SIan Rogers ret = -errno; 22650402641SIan Rogers break; 22750402641SIan Rogers } 2283d88aec0SIan Rogers file = fdopen(fd, "r"); 2293d88aec0SIan Rogers if (!file) { 2303d88aec0SIan Rogers close(fd); 2313d88aec0SIan Rogers break; 2323d88aec0SIan Rogers } 23350402641SIan Rogers __perf_pmu_format__load(format, file); 2343d88aec0SIan Rogers fclose(file); 2353d88aec0SIan Rogers } 236cd82a32eSJiri Olsa } 237cd82a32eSJiri Olsa 238cd82a32eSJiri Olsa closedir(format_dir); 239cd82a32eSJiri Olsa return ret; 240cd82a32eSJiri Olsa } 241cd82a32eSJiri Olsa 242cd82a32eSJiri Olsa /* 243cd82a32eSJiri Olsa * Reading/parsing the default pmu format definition, which should be 244cd82a32eSJiri Olsa * located at: 245cd82a32eSJiri Olsa * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. 246cd82a32eSJiri Olsa */ 247aa1551f2SIan Rogers static int pmu_format(struct perf_pmu *pmu, int dirfd, const char *name, bool eager_load) 248cd82a32eSJiri Olsa { 249e293a5e8SNamhyung Kim int fd; 250cd82a32eSJiri Olsa 251e293a5e8SNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "format", O_DIRECTORY); 252e293a5e8SNamhyung Kim if (fd < 0) 253d9664582SAndi Kleen return 0; 254cd82a32eSJiri Olsa 255e293a5e8SNamhyung Kim /* it'll close the fd */ 256aa1551f2SIan Rogers if (perf_pmu__format_parse(pmu, fd, eager_load)) 257cd82a32eSJiri Olsa return -1; 258cd82a32eSJiri Olsa 259cd82a32eSJiri Olsa return 0; 260cd82a32eSJiri Olsa } 261cd82a32eSJiri Olsa 262a55ab7c4SJin Yao int perf_pmu__convert_scale(const char *scale, char **end, double *sval) 263d02fc6bcSAndi Kleen { 264d02fc6bcSAndi Kleen char *lc; 265d02fc6bcSAndi Kleen int ret = 0; 266d02fc6bcSAndi Kleen 267d02fc6bcSAndi Kleen /* 268d02fc6bcSAndi Kleen * save current locale 269d02fc6bcSAndi Kleen */ 270d02fc6bcSAndi Kleen lc = setlocale(LC_NUMERIC, NULL); 271d02fc6bcSAndi Kleen 272d02fc6bcSAndi Kleen /* 273d02fc6bcSAndi Kleen * The lc string may be allocated in static storage, 274d02fc6bcSAndi Kleen * so get a dynamic copy to make it survive setlocale 275d02fc6bcSAndi Kleen * call below. 276d02fc6bcSAndi Kleen */ 277d02fc6bcSAndi Kleen lc = strdup(lc); 278d02fc6bcSAndi Kleen if (!lc) { 279d02fc6bcSAndi Kleen ret = -ENOMEM; 280d02fc6bcSAndi Kleen goto out; 281d02fc6bcSAndi Kleen } 282d02fc6bcSAndi Kleen 283d02fc6bcSAndi Kleen /* 284d02fc6bcSAndi Kleen * force to C locale to ensure kernel 285d02fc6bcSAndi Kleen * scale string is converted correctly. 286d02fc6bcSAndi Kleen * kernel uses default C locale. 287d02fc6bcSAndi Kleen */ 288d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, "C"); 289d02fc6bcSAndi Kleen 290d02fc6bcSAndi Kleen *sval = strtod(scale, end); 291d02fc6bcSAndi Kleen 292d02fc6bcSAndi Kleen out: 293d02fc6bcSAndi Kleen /* restore locale */ 294d02fc6bcSAndi Kleen setlocale(LC_NUMERIC, lc); 295d02fc6bcSAndi Kleen free(lc); 296d02fc6bcSAndi Kleen return ret; 297d02fc6bcSAndi Kleen } 298d02fc6bcSAndi Kleen 2997b723dbbSIan Rogers static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 300410136f5SStephane Eranian { 301410136f5SStephane Eranian struct stat st; 302410136f5SStephane Eranian ssize_t sret; 3037b723dbbSIan Rogers size_t len; 304410136f5SStephane Eranian char scale[128]; 305410136f5SStephane Eranian int fd, ret = -1; 306410136f5SStephane Eranian char path[PATH_MAX]; 307410136f5SStephane Eranian 3087b723dbbSIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 3097b723dbbSIan Rogers if (!len) 3107b723dbbSIan Rogers return 0; 31148a3adcfSWyes Karny scnprintf(path + len, sizeof(path) - len, "%s/events/%s.scale", pmu->name, alias->name); 312410136f5SStephane Eranian 3137b723dbbSIan Rogers fd = open(path, O_RDONLY); 314410136f5SStephane Eranian if (fd == -1) 315410136f5SStephane Eranian return -1; 316410136f5SStephane Eranian 317410136f5SStephane Eranian if (fstat(fd, &st) < 0) 318410136f5SStephane Eranian goto error; 319410136f5SStephane Eranian 320410136f5SStephane Eranian sret = read(fd, scale, sizeof(scale)-1); 321410136f5SStephane Eranian if (sret < 0) 322410136f5SStephane Eranian goto error; 323410136f5SStephane Eranian 3249ecae065SMadhavan Srinivasan if (scale[sret - 1] == '\n') 3259ecae065SMadhavan Srinivasan scale[sret - 1] = '\0'; 3269ecae065SMadhavan Srinivasan else 327410136f5SStephane Eranian scale[sret] = '\0'; 3289ecae065SMadhavan Srinivasan 329a55ab7c4SJin Yao ret = perf_pmu__convert_scale(scale, NULL, &alias->scale); 330410136f5SStephane Eranian error: 331410136f5SStephane Eranian close(fd); 332410136f5SStephane Eranian return ret; 333410136f5SStephane Eranian } 334410136f5SStephane Eranian 3357b723dbbSIan Rogers static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 336410136f5SStephane Eranian { 337410136f5SStephane Eranian char path[PATH_MAX]; 3387b723dbbSIan Rogers size_t len; 339410136f5SStephane Eranian ssize_t sret; 340410136f5SStephane Eranian int fd; 341410136f5SStephane Eranian 342410136f5SStephane Eranian 3437b723dbbSIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 3447b723dbbSIan Rogers if (!len) 3457b723dbbSIan Rogers return 0; 34648a3adcfSWyes Karny scnprintf(path + len, sizeof(path) - len, "%s/events/%s.unit", pmu->name, alias->name); 3477b723dbbSIan Rogers 3487b723dbbSIan Rogers fd = open(path, O_RDONLY); 349410136f5SStephane Eranian if (fd == -1) 350410136f5SStephane Eranian return -1; 351410136f5SStephane Eranian 352410136f5SStephane Eranian sret = read(fd, alias->unit, UNIT_MAX_LEN); 353410136f5SStephane Eranian if (sret < 0) 354410136f5SStephane Eranian goto error; 355410136f5SStephane Eranian 356410136f5SStephane Eranian close(fd); 357410136f5SStephane Eranian 3589ecae065SMadhavan Srinivasan if (alias->unit[sret - 1] == '\n') 3599ecae065SMadhavan Srinivasan alias->unit[sret - 1] = '\0'; 3609ecae065SMadhavan Srinivasan else 361410136f5SStephane Eranian alias->unit[sret] = '\0'; 362410136f5SStephane Eranian 363410136f5SStephane Eranian return 0; 364410136f5SStephane Eranian error: 365410136f5SStephane Eranian close(fd); 366410136f5SStephane Eranian alias->unit[0] = '\0'; 367410136f5SStephane Eranian return -1; 368410136f5SStephane Eranian } 369410136f5SStephane Eranian 370044330c1SMatt Fleming static int 3717b723dbbSIan Rogers perf_pmu__parse_per_pkg(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 372044330c1SMatt Fleming { 373044330c1SMatt Fleming char path[PATH_MAX]; 3747b723dbbSIan Rogers size_t len; 375044330c1SMatt Fleming int fd; 376044330c1SMatt Fleming 3777b723dbbSIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 3787b723dbbSIan Rogers if (!len) 3797b723dbbSIan Rogers return 0; 38048a3adcfSWyes Karny scnprintf(path + len, sizeof(path) - len, "%s/events/%s.per-pkg", pmu->name, alias->name); 381044330c1SMatt Fleming 3827b723dbbSIan Rogers fd = open(path, O_RDONLY); 383044330c1SMatt Fleming if (fd == -1) 384044330c1SMatt Fleming return -1; 385044330c1SMatt Fleming 386044330c1SMatt Fleming close(fd); 387044330c1SMatt Fleming 388044330c1SMatt Fleming alias->per_pkg = true; 389044330c1SMatt Fleming return 0; 390044330c1SMatt Fleming } 391044330c1SMatt Fleming 3927b723dbbSIan Rogers static int perf_pmu__parse_snapshot(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 3931d9e446bSJiri Olsa { 3941d9e446bSJiri Olsa char path[PATH_MAX]; 3957b723dbbSIan Rogers size_t len; 3961d9e446bSJiri Olsa int fd; 3971d9e446bSJiri Olsa 3987b723dbbSIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 3997b723dbbSIan Rogers if (!len) 4007b723dbbSIan Rogers return 0; 40148a3adcfSWyes Karny scnprintf(path + len, sizeof(path) - len, "%s/events/%s.snapshot", pmu->name, alias->name); 4021d9e446bSJiri Olsa 4037b723dbbSIan Rogers fd = open(path, O_RDONLY); 4041d9e446bSJiri Olsa if (fd == -1) 4051d9e446bSJiri Olsa return -1; 4061d9e446bSJiri Olsa 4071d9e446bSJiri Olsa alias->snapshot = true; 4081d9e446bSJiri Olsa close(fd); 4091d9e446bSJiri Olsa return 0; 4101d9e446bSJiri Olsa } 4111d9e446bSJiri Olsa 4126dde6429SThomas Richter /* Delete an alias entry. */ 413c3245d20SIan Rogers static void perf_pmu_free_alias(struct perf_pmu_alias *newalias) 4146dde6429SThomas Richter { 4156dde6429SThomas Richter zfree(&newalias->name); 4166dde6429SThomas Richter zfree(&newalias->desc); 4176dde6429SThomas Richter zfree(&newalias->long_desc); 4186dde6429SThomas Richter zfree(&newalias->topic); 41932705de7SJin Yao zfree(&newalias->pmu_name); 4200d3f0e6fSIan Rogers parse_events_terms__exit(&newalias->terms); 4216dde6429SThomas Richter free(newalias); 4226dde6429SThomas Richter } 4236dde6429SThomas Richter 424eec11310SNamhyung Kim static void perf_pmu__del_aliases(struct perf_pmu *pmu) 425eec11310SNamhyung Kim { 426eec11310SNamhyung Kim struct perf_pmu_alias *alias, *tmp; 427eec11310SNamhyung Kim 428eec11310SNamhyung Kim list_for_each_entry_safe(alias, tmp, &pmu->aliases, list) { 429eec11310SNamhyung Kim list_del(&alias->list); 430eec11310SNamhyung Kim perf_pmu_free_alias(alias); 431eec11310SNamhyung Kim } 432eec11310SNamhyung Kim } 433eec11310SNamhyung Kim 4348d4b6d37SIan Rogers static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu, 4358d4b6d37SIan Rogers const char *name, 4368d4b6d37SIan Rogers bool load) 4376dde6429SThomas Richter { 438f63a536fSIan Rogers struct perf_pmu_alias *alias; 4396dde6429SThomas Richter 4407b6dd7a9SIan Rogers if (load && !pmu->sysfs_aliases_loaded) { 4417b6dd7a9SIan Rogers bool has_sysfs_event; 4427b6dd7a9SIan Rogers char event_file_name[FILENAME_MAX + 8]; 4437b6dd7a9SIan Rogers 4447b6dd7a9SIan Rogers /* 4457b6dd7a9SIan Rogers * Test if alias/event 'name' exists in the PMU's sysfs/events 4467b6dd7a9SIan Rogers * directory. If not skip parsing the sysfs aliases. Sysfs event 4477b6dd7a9SIan Rogers * name must be all lower or all upper case. 4487b6dd7a9SIan Rogers */ 4497b6dd7a9SIan Rogers scnprintf(event_file_name, sizeof(event_file_name), "events/%s", name); 4507b6dd7a9SIan Rogers for (size_t i = 7, n = 7 + strlen(name); i < n; i++) 4517b6dd7a9SIan Rogers event_file_name[i] = tolower(event_file_name[i]); 4527b6dd7a9SIan Rogers 4537b6dd7a9SIan Rogers has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name); 4547b6dd7a9SIan Rogers if (!has_sysfs_event) { 4557b6dd7a9SIan Rogers for (size_t i = 7, n = 7 + strlen(name); i < n; i++) 4567b6dd7a9SIan Rogers event_file_name[i] = toupper(event_file_name[i]); 4577b6dd7a9SIan Rogers 4587b6dd7a9SIan Rogers has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name); 4597b6dd7a9SIan Rogers } 4607b6dd7a9SIan Rogers if (has_sysfs_event) 4618d4b6d37SIan Rogers pmu_aliases_parse(pmu); 4628d4b6d37SIan Rogers 4637b6dd7a9SIan Rogers } 464f63a536fSIan Rogers list_for_each_entry(alias, &pmu->aliases, list) { 465f63a536fSIan Rogers if (!strcasecmp(alias->name, name)) 466f63a536fSIan Rogers return alias; 46732705de7SJin Yao } 468f63a536fSIan Rogers return NULL; 469f63a536fSIan Rogers } 470f63a536fSIan Rogers 471f63a536fSIan Rogers static bool assign_str(const char *name, const char *field, char **old_str, 472f63a536fSIan Rogers const char *new_str) 473f63a536fSIan Rogers { 474f63a536fSIan Rogers if (!*old_str && new_str) { 475f63a536fSIan Rogers *old_str = strdup(new_str); 4766dde6429SThomas Richter return true; 4776dde6429SThomas Richter } 478f63a536fSIan Rogers 479f63a536fSIan Rogers if (!new_str || !strcasecmp(*old_str, new_str)) 480f63a536fSIan Rogers return false; /* Nothing to update. */ 481f63a536fSIan Rogers 482f63a536fSIan Rogers pr_debug("alias %s differs in field '%s' ('%s' != '%s')\n", 483f63a536fSIan Rogers name, field, *old_str, new_str); 484f63a536fSIan Rogers zfree(old_str); 485f63a536fSIan Rogers *old_str = strdup(new_str); 486f63a536fSIan Rogers return true; 4876dde6429SThomas Richter } 488f63a536fSIan Rogers 4897b723dbbSIan Rogers static void read_alias_info(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 4907b723dbbSIan Rogers { 4917b723dbbSIan Rogers if (!alias->from_sysfs || alias->info_loaded) 4927b723dbbSIan Rogers return; 4937b723dbbSIan Rogers 4947b723dbbSIan Rogers /* 4957b723dbbSIan Rogers * load unit name and scale if available 4967b723dbbSIan Rogers */ 4977b723dbbSIan Rogers perf_pmu__parse_unit(pmu, alias); 4987b723dbbSIan Rogers perf_pmu__parse_scale(pmu, alias); 4997b723dbbSIan Rogers perf_pmu__parse_per_pkg(pmu, alias); 5007b723dbbSIan Rogers perf_pmu__parse_snapshot(pmu, alias); 5017b723dbbSIan Rogers } 5027b723dbbSIan Rogers 5037b723dbbSIan Rogers struct update_alias_data { 5047b723dbbSIan Rogers struct perf_pmu *pmu; 5057b723dbbSIan Rogers struct perf_pmu_alias *alias; 5067b723dbbSIan Rogers }; 5077b723dbbSIan Rogers 508f63a536fSIan Rogers static int update_alias(const struct pmu_event *pe, 509f63a536fSIan Rogers const struct pmu_events_table *table __maybe_unused, 510f63a536fSIan Rogers void *vdata) 511f63a536fSIan Rogers { 5127b723dbbSIan Rogers struct update_alias_data *data = vdata; 513f63a536fSIan Rogers int ret = 0; 514f63a536fSIan Rogers 5157b723dbbSIan Rogers read_alias_info(data->pmu, data->alias); 5167b723dbbSIan Rogers assign_str(pe->name, "desc", &data->alias->desc, pe->desc); 5177b723dbbSIan Rogers assign_str(pe->name, "long_desc", &data->alias->long_desc, pe->long_desc); 5187b723dbbSIan Rogers assign_str(pe->name, "topic", &data->alias->topic, pe->topic); 5197b723dbbSIan Rogers data->alias->per_pkg = pe->perpkg; 52030f0b435SIan Rogers if (pe->event) { 5210d3f0e6fSIan Rogers parse_events_terms__exit(&data->alias->terms); 5227b723dbbSIan Rogers ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL); 523f63a536fSIan Rogers } 524f63a536fSIan Rogers if (!ret && pe->unit) { 525f63a536fSIan Rogers char *unit; 526f63a536fSIan Rogers 5277b723dbbSIan Rogers ret = perf_pmu__convert_scale(pe->unit, &unit, &data->alias->scale); 528f63a536fSIan Rogers if (!ret) 5297b723dbbSIan Rogers snprintf(data->alias->unit, sizeof(data->alias->unit), "%s", unit); 530f63a536fSIan Rogers } 531f63a536fSIan Rogers return ret; 5326dde6429SThomas Richter } 5336dde6429SThomas Richter 5347b723dbbSIan Rogers static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, 535edb217ffSIan Rogers const char *desc, const char *val, FILE *val_fd, 536d9c5f5f9SIan Rogers const struct pmu_event *pe, enum event_source src) 537a6146d50SZheng Yan { 5385c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 539a6146d50SZheng Yan int ret; 540330f40a0SIan Rogers const char *long_desc = NULL, *topic = NULL, *unit = NULL, *pmu_name = NULL; 541bd680861SIan Rogers bool deprecated = false, perpkg = false; 542eab35953SJin Yao 5438d4b6d37SIan Rogers if (perf_pmu__find_alias(pmu, name, /*load=*/ false)) { 544f63a536fSIan Rogers /* Alias was already created/loaded. */ 545f63a536fSIan Rogers return 0; 546f63a536fSIan Rogers } 547f63a536fSIan Rogers 548eab35953SJin Yao if (pe) { 549330f40a0SIan Rogers long_desc = pe->long_desc; 550330f40a0SIan Rogers topic = pe->topic; 551330f40a0SIan Rogers unit = pe->unit; 552bd680861SIan Rogers perpkg = pe->perpkg; 5539ed8b7dcSIan Rogers deprecated = pe->deprecated; 55439aa4ff6SIan Rogers if (pe->pmu && strcmp(pe->pmu, "default_core")) 555330f40a0SIan Rogers pmu_name = pe->pmu; 556eab35953SJin Yao } 557a6146d50SZheng Yan 558eaaebb01SIan Rogers alias = zalloc(sizeof(*alias)); 559a6146d50SZheng Yan if (!alias) 560a6146d50SZheng Yan return -ENOMEM; 561a6146d50SZheng Yan 5620d3f0e6fSIan Rogers parse_events_terms__init(&alias->terms); 563410136f5SStephane Eranian alias->scale = 1.0; 564410136f5SStephane Eranian alias->unit[0] = '\0'; 565bd680861SIan Rogers alias->per_pkg = perpkg; 56684530920SStephane Eranian alias->snapshot = false; 5679ed8b7dcSIan Rogers alias->deprecated = deprecated; 568410136f5SStephane Eranian 569edb217ffSIan Rogers ret = parse_events_terms(&alias->terms, val, val_fd); 570a6146d50SZheng Yan if (ret) { 57170c646e0SSukadev Bhattiprolu pr_err("Cannot parse alias %s: %d\n", val, ret); 572a6146d50SZheng Yan free(alias); 573a6146d50SZheng Yan return ret; 574a6146d50SZheng Yan } 575a6146d50SZheng Yan 576a6146d50SZheng Yan alias->name = strdup(name); 57708e60ed1SAndi Kleen alias->desc = desc ? strdup(desc) : NULL; 578c8d6828aSSukadev Bhattiprolu alias->long_desc = long_desc ? strdup(long_desc) : 579c8d6828aSSukadev Bhattiprolu desc ? strdup(desc) : NULL; 580dd5f1036SAndi Kleen alias->topic = topic ? strdup(topic) : NULL; 581f63a536fSIan Rogers alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL; 582fedb2b51SAndi Kleen if (unit) { 583f63a536fSIan Rogers if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0) { 584f63a536fSIan Rogers perf_pmu_free_alias(alias); 585fedb2b51SAndi Kleen return -1; 586f63a536fSIan Rogers } 587fedb2b51SAndi Kleen snprintf(alias->unit, sizeof(alias->unit), "%s", unit); 588fedb2b51SAndi Kleen } 589d9c5f5f9SIan Rogers switch (src) { 590d9c5f5f9SIan Rogers default: 591d9c5f5f9SIan Rogers case EVENT_SRC_SYSFS: 592d9c5f5f9SIan Rogers alias->from_sysfs = true; 593d9c5f5f9SIan Rogers if (pmu->events_table) { 594f63a536fSIan Rogers /* Update an event from sysfs with json data. */ 5957b723dbbSIan Rogers struct update_alias_data data = { 5967b723dbbSIan Rogers .pmu = pmu, 5977b723dbbSIan Rogers .alias = alias, 5987b723dbbSIan Rogers }; 599e6ff1eedSIan Rogers if (pmu_events_table__find_event(pmu->events_table, pmu, name, 6007b723dbbSIan Rogers update_alias, &data) == 0) 601d9c5f5f9SIan Rogers pmu->cpu_json_aliases++; 6027c52f10cSIan Rogers } 603e6ff1eedSIan Rogers pmu->sysfs_aliases++; 604d9c5f5f9SIan Rogers break; 605d9c5f5f9SIan Rogers case EVENT_SRC_CPU_JSON: 606d9c5f5f9SIan Rogers pmu->cpu_json_aliases++; 607d9c5f5f9SIan Rogers break; 608d9c5f5f9SIan Rogers case EVENT_SRC_SYS_JSON: 609d9c5f5f9SIan Rogers pmu->sys_json_aliases++; 610d9c5f5f9SIan Rogers break; 611d9c5f5f9SIan Rogers 612d9c5f5f9SIan Rogers } 613f26d22f1SIan Rogers list_add_tail(&alias->list, &pmu->aliases); 614a6146d50SZheng Yan return 0; 615a6146d50SZheng Yan } 616a6146d50SZheng Yan 6173a42f4c7SIan Rogers static inline bool pmu_alias_info_file(const char *name) 61846441bdcSMatt Fleming { 61946441bdcSMatt Fleming size_t len; 62046441bdcSMatt Fleming 62146441bdcSMatt Fleming len = strlen(name); 62246441bdcSMatt Fleming if (len > 5 && !strcmp(name + len - 5, ".unit")) 62346441bdcSMatt Fleming return true; 62446441bdcSMatt Fleming if (len > 6 && !strcmp(name + len - 6, ".scale")) 62546441bdcSMatt Fleming return true; 626044330c1SMatt Fleming if (len > 8 && !strcmp(name + len - 8, ".per-pkg")) 627044330c1SMatt Fleming return true; 6281d9e446bSJiri Olsa if (len > 9 && !strcmp(name + len - 9, ".snapshot")) 6291d9e446bSJiri Olsa return true; 63046441bdcSMatt Fleming 63146441bdcSMatt Fleming return false; 63246441bdcSMatt Fleming } 63346441bdcSMatt Fleming 634a6146d50SZheng Yan /* 6358d4b6d37SIan Rogers * Reading the pmu event aliases definition, which should be located at: 6368d4b6d37SIan Rogers * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 637a6146d50SZheng Yan */ 63818eb2ca8SIan Rogers static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd) 639a6146d50SZheng Yan { 640a6146d50SZheng Yan struct dirent *evt_ent; 641a6146d50SZheng Yan DIR *event_dir; 642a6146d50SZheng Yan 64318eb2ca8SIan Rogers event_dir = fdopendir(events_dir_fd); 64418eb2ca8SIan Rogers if (!event_dir) 645a6146d50SZheng Yan return -EINVAL; 646a6146d50SZheng Yan 647940db6dcSAndi Kleen while ((evt_ent = readdir(event_dir))) { 648a6146d50SZheng Yan char *name = evt_ent->d_name; 64918eb2ca8SIan Rogers int fd; 650a6146d50SZheng Yan FILE *file; 651a6146d50SZheng Yan 652a6146d50SZheng Yan if (!strcmp(name, ".") || !strcmp(name, "..")) 653a6146d50SZheng Yan continue; 654a6146d50SZheng Yan 655410136f5SStephane Eranian /* 65646441bdcSMatt Fleming * skip info files parsed in perf_pmu__new_alias() 657410136f5SStephane Eranian */ 65846441bdcSMatt Fleming if (pmu_alias_info_file(name)) 659410136f5SStephane Eranian continue; 660410136f5SStephane Eranian 66118eb2ca8SIan Rogers fd = openat(events_dir_fd, name, O_RDONLY); 6620ea8920eSIan Rogers if (fd == -1) { 6630ea8920eSIan Rogers pr_debug("Cannot open %s\n", name); 6640ea8920eSIan Rogers continue; 6650ea8920eSIan Rogers } 666e293a5e8SNamhyung Kim file = fdopen(fd, "r"); 667940db6dcSAndi Kleen if (!file) { 6680ea8920eSIan Rogers close(fd); 669940db6dcSAndi Kleen continue; 670940db6dcSAndi Kleen } 671410136f5SStephane Eranian 6727b723dbbSIan Rogers if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL, 673d9c5f5f9SIan Rogers /*val=*/ NULL, file, /*pe=*/ NULL, 674d9c5f5f9SIan Rogers EVENT_SRC_SYSFS) < 0) 675940db6dcSAndi Kleen pr_debug("Cannot set up %s\n", name); 676a6146d50SZheng Yan fclose(file); 677a6146d50SZheng Yan } 678a6146d50SZheng Yan 679a6146d50SZheng Yan closedir(event_dir); 6808d4b6d37SIan Rogers pmu->sysfs_aliases_loaded = true; 681a6146d50SZheng Yan return 0; 682a6146d50SZheng Yan } 683a6146d50SZheng Yan 68418eb2ca8SIan Rogers static int pmu_aliases_parse(struct perf_pmu *pmu) 68518eb2ca8SIan Rogers { 68618eb2ca8SIan Rogers char path[PATH_MAX]; 68718eb2ca8SIan Rogers size_t len; 68818eb2ca8SIan Rogers int events_dir_fd, ret; 68918eb2ca8SIan Rogers 69018eb2ca8SIan Rogers if (pmu->sysfs_aliases_loaded) 69118eb2ca8SIan Rogers return 0; 69218eb2ca8SIan Rogers 69318eb2ca8SIan Rogers len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 69418eb2ca8SIan Rogers if (!len) 69518eb2ca8SIan Rogers return 0; 69618eb2ca8SIan Rogers scnprintf(path + len, sizeof(path) - len, "%s/events", pmu->name); 69718eb2ca8SIan Rogers 69818eb2ca8SIan Rogers events_dir_fd = open(path, O_DIRECTORY); 69918eb2ca8SIan Rogers if (events_dir_fd == -1) { 70018eb2ca8SIan Rogers pmu->sysfs_aliases_loaded = true; 70118eb2ca8SIan Rogers return 0; 70218eb2ca8SIan Rogers } 70318eb2ca8SIan Rogers ret = __pmu_aliases_parse(pmu, events_dir_fd); 70418eb2ca8SIan Rogers close(events_dir_fd); 70518eb2ca8SIan Rogers return ret; 70618eb2ca8SIan Rogers } 70718eb2ca8SIan Rogers 70818eb2ca8SIan Rogers static int pmu_aliases_parse_eager(struct perf_pmu *pmu, int sysfs_fd) 70918eb2ca8SIan Rogers { 71018eb2ca8SIan Rogers char path[FILENAME_MAX + 7]; 71118eb2ca8SIan Rogers int ret, events_dir_fd; 71218eb2ca8SIan Rogers 71318eb2ca8SIan Rogers scnprintf(path, sizeof(path), "%s/events", pmu->name); 71418eb2ca8SIan Rogers events_dir_fd = openat(sysfs_fd, path, O_DIRECTORY, 0); 71518eb2ca8SIan Rogers if (events_dir_fd == -1) { 71618eb2ca8SIan Rogers pmu->sysfs_aliases_loaded = true; 71718eb2ca8SIan Rogers return 0; 71818eb2ca8SIan Rogers } 71918eb2ca8SIan Rogers ret = __pmu_aliases_parse(pmu, events_dir_fd); 72018eb2ca8SIan Rogers close(events_dir_fd); 72118eb2ca8SIan Rogers return ret; 72218eb2ca8SIan Rogers } 72318eb2ca8SIan Rogers 724f5144ecaSIan Rogers static int pmu_alias_terms(struct perf_pmu_alias *alias, int err_loc, struct list_head *terms) 725a6146d50SZheng Yan { 7267c2f8164SJiri Olsa struct parse_events_term *term, *cloned; 7270d3f0e6fSIan Rogers struct parse_events_terms clone_terms; 728a6146d50SZheng Yan 7290d3f0e6fSIan Rogers parse_events_terms__init(&clone_terms); 7300d3f0e6fSIan Rogers list_for_each_entry(term, &alias->terms.terms, list) { 7310d3f0e6fSIan Rogers int ret = parse_events_term__clone(&cloned, term); 7320d3f0e6fSIan Rogers 733a6146d50SZheng Yan if (ret) { 7340d3f0e6fSIan Rogers parse_events_terms__exit(&clone_terms); 735a6146d50SZheng Yan return ret; 736a6146d50SZheng Yan } 737c2f1ceadSAndi Kleen /* 738c2f1ceadSAndi Kleen * Weak terms don't override command line options, 739c2f1ceadSAndi Kleen * which we don't want for implicit terms in aliases. 740c2f1ceadSAndi Kleen */ 741c2f1ceadSAndi Kleen cloned->weak = true; 742f5144ecaSIan Rogers cloned->err_term = cloned->err_val = err_loc; 7430d3f0e6fSIan Rogers list_add_tail(&cloned->list, &clone_terms.terms); 744a6146d50SZheng Yan } 7450d3f0e6fSIan Rogers list_splice_init(&clone_terms.terms, terms); 7460d3f0e6fSIan Rogers parse_events_terms__exit(&clone_terms); 747a6146d50SZheng Yan return 0; 748a6146d50SZheng Yan } 749a6146d50SZheng Yan 75066ec1191SMark Rutland /* 75166ec1191SMark Rutland * Uncore PMUs have a "cpumask" file under sysfs. CPU PMUs (e.g. on arm/arm64) 75266ec1191SMark Rutland * may have a "cpus" file. 75366ec1191SMark Rutland */ 754d06593aaSIan Rogers static struct perf_cpu_map *pmu_cpumask(int dirfd, const char *name, bool is_core) 7557ae92e74SYan, Zheng { 756f854839bSJiri Olsa struct perf_cpu_map *cpus; 7577e3fcffeSMark Rutland const char *templates[] = { 758d50a79cdSJames Clark "cpumask", 759d50a79cdSJames Clark "cpus", 7607e3fcffeSMark Rutland NULL 7617e3fcffeSMark Rutland }; 7627e3fcffeSMark Rutland const char **template; 763d50a79cdSJames Clark char pmu_name[PATH_MAX]; 764d50a79cdSJames Clark struct perf_pmu pmu = {.name = pmu_name}; 765d50a79cdSJames Clark FILE *file; 7667ae92e74SYan, Zheng 767d50a79cdSJames Clark strlcpy(pmu_name, name, sizeof(pmu_name)); 7687e3fcffeSMark Rutland for (template = templates; *template; template++) { 7693a69672eSNamhyung Kim file = perf_pmu__open_file_at(&pmu, dirfd, *template); 770d50a79cdSJames Clark if (!file) 771d50a79cdSJames Clark continue; 772d50a79cdSJames Clark cpus = perf_cpu_map__read(file); 7733a69672eSNamhyung Kim fclose(file); 77466ec1191SMark Rutland if (cpus) 77566ec1191SMark Rutland return cpus; 7767e3fcffeSMark Rutland } 7777ae92e74SYan, Zheng 778d06593aaSIan Rogers /* Nothing found, for core PMUs assume this means all CPUs. */ 779d06593aaSIan Rogers return is_core ? perf_cpu_map__get(cpu_map__online()) : NULL; 78066ec1191SMark Rutland } 7817ae92e74SYan, Zheng 7823a69672eSNamhyung Kim static bool pmu_is_uncore(int dirfd, const char *name) 78366ec1191SMark Rutland { 7843a69672eSNamhyung Kim int fd; 7857ae92e74SYan, Zheng 7863a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, name, "cpumask", O_PATH); 7873a69672eSNamhyung Kim if (fd < 0) 7883a69672eSNamhyung Kim return false; 7893a69672eSNamhyung Kim 7903a69672eSNamhyung Kim close(fd); 7913a69672eSNamhyung Kim return true; 7927ae92e74SYan, Zheng } 7937ae92e74SYan, Zheng 79451d54847SJohn Garry static char *pmu_id(const char *name) 79551d54847SJohn Garry { 79651d54847SJohn Garry char path[PATH_MAX], *str; 79751d54847SJohn Garry size_t len; 79851d54847SJohn Garry 7995f2c8efaSJames Clark perf_pmu__pathname_scnprintf(path, sizeof(path), name, "identifier"); 80051d54847SJohn Garry 8015f2c8efaSJames Clark if (filename__read_str(path, &str, &len) < 0) 80251d54847SJohn Garry return NULL; 80351d54847SJohn Garry 80451d54847SJohn Garry str[len - 1] = 0; /* remove line feed */ 80551d54847SJohn Garry 80651d54847SJohn Garry return str; 80751d54847SJohn Garry } 80851d54847SJohn Garry 8094bf7e81aSIan Rogers /** 8104bf7e81aSIan Rogers * is_sysfs_pmu_core() - PMU CORE devices have different name other than cpu in 8114bf7e81aSIan Rogers * sysfs on some platforms like ARM or Intel hybrid. Looking for 8124bf7e81aSIan Rogers * possible the cpus file in sysfs files to identify whether this is a 8134bf7e81aSIan Rogers * core device. 8144bf7e81aSIan Rogers * @name: The PMU name such as "cpu_atom". 81514b22ae0SGanapatrao Kulkarni */ 8164bf7e81aSIan Rogers static int is_sysfs_pmu_core(const char *name) 81714b22ae0SGanapatrao Kulkarni { 81814b22ae0SGanapatrao Kulkarni char path[PATH_MAX]; 81914b22ae0SGanapatrao Kulkarni 820f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), name, "cpus")) 82114b22ae0SGanapatrao Kulkarni return 0; 822d9664582SAndi Kleen return file_available(path); 82314b22ae0SGanapatrao Kulkarni } 82414b22ae0SGanapatrao Kulkarni 82529be2fe0SIan Rogers char *perf_pmu__getcpuid(struct perf_pmu *pmu) 826d77ade9fSAndi Kleen { 827d77ade9fSAndi Kleen char *cpuid; 828d77ade9fSAndi Kleen static bool printed; 829d77ade9fSAndi Kleen 830d77ade9fSAndi Kleen cpuid = getenv("PERF_CPUID"); 831d77ade9fSAndi Kleen if (cpuid) 832d77ade9fSAndi Kleen cpuid = strdup(cpuid); 833d77ade9fSAndi Kleen if (!cpuid) 83454e32dc0SGanapatrao Kulkarni cpuid = get_cpuid_str(pmu); 835d77ade9fSAndi Kleen if (!cpuid) 836d77ade9fSAndi Kleen return NULL; 837d77ade9fSAndi Kleen 838d77ade9fSAndi Kleen if (!printed) { 839d77ade9fSAndi Kleen pr_debug("Using CPUID %s\n", cpuid); 840d77ade9fSAndi Kleen printed = true; 841d77ade9fSAndi Kleen } 842d77ade9fSAndi Kleen return cpuid; 843d77ade9fSAndi Kleen } 844d77ade9fSAndi Kleen 845f8ea2c15SIan Rogers __weak const struct pmu_metrics_table *pmu_metrics_table__find(void) 846f8ea2c15SIan Rogers { 847f8ea2c15SIan Rogers return perf_pmu__find_metrics_table(NULL); 848f8ea2c15SIan Rogers } 849f8ea2c15SIan Rogers 850240e6fd0SIan Rogers /** 8517afbf90eSJames Clark * Return the length of the PMU name not including the suffix for uncore PMUs. 8527afbf90eSJames Clark * 8537afbf90eSJames Clark * We want to deduplicate many similar uncore PMUs by stripping their suffixes, 8547afbf90eSJames Clark * but there are never going to be too many core PMUs and the suffixes might be 8557afbf90eSJames Clark * interesting. "arm_cortex_a53" vs "arm_cortex_a57" or "cpum_cf" for example. 8567afbf90eSJames Clark * 8577afbf90eSJames Clark * @skip_duplicate_pmus: False in verbose mode so all uncore PMUs are visible 8587afbf90eSJames Clark */ 8597afbf90eSJames Clark static size_t pmu_deduped_name_len(const struct perf_pmu *pmu, const char *name, 8607afbf90eSJames Clark bool skip_duplicate_pmus) 8617afbf90eSJames Clark { 8627afbf90eSJames Clark return skip_duplicate_pmus && !pmu->is_core 8637afbf90eSJames Clark ? pmu_name_len_no_suffix(name) 8647afbf90eSJames Clark : strlen(name); 8657afbf90eSJames Clark } 8667afbf90eSJames Clark 8677afbf90eSJames Clark /** 868240e6fd0SIan Rogers * perf_pmu__match_ignoring_suffix - Does the pmu_name match tok ignoring any 869240e6fd0SIan Rogers * trailing suffix? The Suffix must be in form 870240e6fd0SIan Rogers * tok_{digits}, or tok{digits}. 871240e6fd0SIan Rogers * @pmu_name: The pmu_name with possible suffix. 872240e6fd0SIan Rogers * @tok: The possible match to pmu_name without suffix. 873c07d5c92SJohn Garry */ 874240e6fd0SIan Rogers static bool perf_pmu__match_ignoring_suffix(const char *pmu_name, const char *tok) 875c47a5599SJin Yao { 8763241d46fSIan Rogers const char *p, *suffix; 8773241d46fSIan Rogers bool has_hex = false; 878c47a5599SJin Yao 879c47a5599SJin Yao if (strncmp(pmu_name, tok, strlen(tok))) 880c47a5599SJin Yao return false; 881c47a5599SJin Yao 8823241d46fSIan Rogers suffix = p = pmu_name + strlen(tok); 883c47a5599SJin Yao if (*p == 0) 884c47a5599SJin Yao return true; 885c47a5599SJin Yao 8863241d46fSIan Rogers if (*p == '_') { 887c47a5599SJin Yao ++p; 8883241d46fSIan Rogers ++suffix; 8893241d46fSIan Rogers } 890c07d5c92SJohn Garry 891c07d5c92SJohn Garry /* Ensure we end in a number */ 892c07d5c92SJohn Garry while (1) { 8933241d46fSIan Rogers if (!isxdigit(*p)) 894c47a5599SJin Yao return false; 8953241d46fSIan Rogers if (!has_hex) 8963241d46fSIan Rogers has_hex = !isdigit(*p); 897c07d5c92SJohn Garry if (*(++p) == 0) 898c07d5c92SJohn Garry break; 899c07d5c92SJohn Garry } 900c47a5599SJin Yao 9013241d46fSIan Rogers if (has_hex) 9023241d46fSIan Rogers return (p - suffix) > 2; 9033241d46fSIan Rogers 904c47a5599SJin Yao return true; 905c47a5599SJin Yao } 906c47a5599SJin Yao 907240e6fd0SIan Rogers /** 908240e6fd0SIan Rogers * pmu_uncore_alias_match - does name match the PMU name? 909240e6fd0SIan Rogers * @pmu_name: the json struct pmu_event name. This may lack a suffix (which 910240e6fd0SIan Rogers * matches) or be of the form "socket,pmuname" which will match 911240e6fd0SIan Rogers * "socketX_pmunameY". 912240e6fd0SIan Rogers * @name: a real full PMU name as from sysfs. 913240e6fd0SIan Rogers */ 914240e6fd0SIan Rogers static bool pmu_uncore_alias_match(const char *pmu_name, const char *name) 915730670b1SJohn Garry { 916730670b1SJohn Garry char *tmp = NULL, *tok, *str; 917730670b1SJohn Garry bool res; 918730670b1SJohn Garry 919240e6fd0SIan Rogers if (strchr(pmu_name, ',') == NULL) 920240e6fd0SIan Rogers return perf_pmu__match_ignoring_suffix(name, pmu_name); 921240e6fd0SIan Rogers 922730670b1SJohn Garry str = strdup(pmu_name); 923730670b1SJohn Garry if (!str) 924730670b1SJohn Garry return false; 925730670b1SJohn Garry 926730670b1SJohn Garry /* 927730670b1SJohn Garry * uncore alias may be from different PMU with common prefix 928730670b1SJohn Garry */ 929730670b1SJohn Garry tok = strtok_r(str, ",", &tmp); 930730670b1SJohn Garry if (strncmp(pmu_name, tok, strlen(tok))) { 931730670b1SJohn Garry res = false; 932730670b1SJohn Garry goto out; 933730670b1SJohn Garry } 934730670b1SJohn Garry 935730670b1SJohn Garry /* 936730670b1SJohn Garry * Match more complex aliases where the alias name is a comma-delimited 937730670b1SJohn Garry * list of tokens, orderly contained in the matching PMU name. 938730670b1SJohn Garry * 939730670b1SJohn Garry * Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we 940730670b1SJohn Garry * match "socket" in "socketX_pmunameY" and then "pmuname" in 941730670b1SJohn Garry * "pmunameY". 942730670b1SJohn Garry */ 943c07d5c92SJohn Garry while (1) { 944c07d5c92SJohn Garry char *next_tok = strtok_r(NULL, ",", &tmp); 945c07d5c92SJohn Garry 946730670b1SJohn Garry name = strstr(name, tok); 947c07d5c92SJohn Garry if (!name || 948240e6fd0SIan Rogers (!next_tok && !perf_pmu__match_ignoring_suffix(name, tok))) { 949730670b1SJohn Garry res = false; 950730670b1SJohn Garry goto out; 951730670b1SJohn Garry } 952c07d5c92SJohn Garry if (!next_tok) 953c07d5c92SJohn Garry break; 954c07d5c92SJohn Garry tok = next_tok; 955c07d5c92SJohn Garry name += strlen(tok); 956730670b1SJohn Garry } 957730670b1SJohn Garry 958730670b1SJohn Garry res = true; 959730670b1SJohn Garry out: 960730670b1SJohn Garry free(str); 961730670b1SJohn Garry return res; 962730670b1SJohn Garry } 963730670b1SJohn Garry 9642879ff36SJing Zhang bool pmu_uncore_identifier_match(const char *compat, const char *id) 9652879ff36SJing Zhang { 9662879ff36SJing Zhang regex_t re; 9672879ff36SJing Zhang regmatch_t pmatch[1]; 9682879ff36SJing Zhang int match; 9692879ff36SJing Zhang 9702879ff36SJing Zhang if (regcomp(&re, compat, REG_EXTENDED) != 0) { 9712879ff36SJing Zhang /* Warn unable to generate match particular string. */ 9722879ff36SJing Zhang pr_info("Invalid regular expression %s\n", compat); 9732879ff36SJing Zhang return false; 9742879ff36SJing Zhang } 9752879ff36SJing Zhang 9762879ff36SJing Zhang match = !regexec(&re, id, 1, pmatch, 0); 9772879ff36SJing Zhang if (match) { 9782879ff36SJing Zhang /* Ensure a full match. */ 9792879ff36SJing Zhang match = pmatch[0].rm_so == 0 && (size_t)pmatch[0].rm_eo == strlen(id); 9802879ff36SJing Zhang } 9812879ff36SJing Zhang regfree(&re); 9822879ff36SJing Zhang 9832879ff36SJing Zhang return match; 9842879ff36SJing Zhang } 9852879ff36SJing Zhang 986660842e4SIan Rogers static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, 9871ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 988660842e4SIan Rogers void *vdata) 989660842e4SIan Rogers { 990f26d22f1SIan Rogers struct perf_pmu *pmu = vdata; 991660842e4SIan Rogers 992d9c5f5f9SIan Rogers perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, 993d9c5f5f9SIan Rogers pe, EVENT_SRC_CPU_JSON); 994660842e4SIan Rogers return 0; 995660842e4SIan Rogers } 996660842e4SIan Rogers 997933f82ffSSukadev Bhattiprolu /* 998d685819bSIan Rogers * From the pmu_events_table, find the events that correspond to the given 999d685819bSIan Rogers * PMU and add them to the list 'head'. 1000933f82ffSSukadev Bhattiprolu */ 1001838a8c5fSIan Rogers void pmu_add_cpu_aliases_table(struct perf_pmu *pmu, const struct pmu_events_table *table) 1002933f82ffSSukadev Bhattiprolu { 1003f26d22f1SIan Rogers pmu_events_table__for_each_event(table, pmu, pmu_add_cpu_aliases_map_callback, pmu); 1004933f82ffSSukadev Bhattiprolu } 1005933f82ffSSukadev Bhattiprolu 1006838a8c5fSIan Rogers static void pmu_add_cpu_aliases(struct perf_pmu *pmu) 1007e45ad701SJohn Garry { 10087c52f10cSIan Rogers if (!pmu->events_table) 1009e45ad701SJohn Garry return; 1010e45ad701SJohn Garry 1011e6ff1eedSIan Rogers if (pmu->cpu_aliases_added) 1012e6ff1eedSIan Rogers return; 1013e6ff1eedSIan Rogers 10147c52f10cSIan Rogers pmu_add_cpu_aliases_table(pmu, pmu->events_table); 1015e6ff1eedSIan Rogers pmu->cpu_aliases_added = true; 1016e45ad701SJohn Garry } 1017e45ad701SJohn Garry 101829be2fe0SIan Rogers static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, 10191ba3752aSIan Rogers const struct pmu_events_table *table __maybe_unused, 1020f26d22f1SIan Rogers void *vdata) 10214513c719SJohn Garry { 1022f26d22f1SIan Rogers struct perf_pmu *pmu = vdata; 10234513c719SJohn Garry 10244513c719SJohn Garry if (!pe->compat || !pe->pmu) 10254513c719SJohn Garry return 0; 10264513c719SJohn Garry 10272879ff36SJing Zhang if (pmu_uncore_alias_match(pe->pmu, pmu->name) && 10282879ff36SJing Zhang pmu_uncore_identifier_match(pe->compat, pmu->id)) { 10297b723dbbSIan Rogers perf_pmu__new_alias(pmu, 1030edb217ffSIan Rogers pe->name, 1031edb217ffSIan Rogers pe->desc, 1032edb217ffSIan Rogers pe->event, 1033edb217ffSIan Rogers /*val_fd=*/ NULL, 1034d9c5f5f9SIan Rogers pe, 1035d9c5f5f9SIan Rogers EVENT_SRC_SYS_JSON); 10364513c719SJohn Garry } 10374513c719SJohn Garry 10384513c719SJohn Garry return 0; 10394513c719SJohn Garry } 10404513c719SJohn Garry 1041838a8c5fSIan Rogers void pmu_add_sys_aliases(struct perf_pmu *pmu) 10424513c719SJohn Garry { 10434513c719SJohn Garry if (!pmu->id) 10444513c719SJohn Garry return; 10454513c719SJohn Garry 1046f26d22f1SIan Rogers pmu_for_each_sys_event(pmu_add_sys_aliases_iter_fn, pmu); 10474513c719SJohn Garry } 10484513c719SJohn Garry 1049b1f05622SIan Rogers static char *pmu_find_alias_name(struct perf_pmu *pmu, int dirfd) 105013d60ba0SKan Liang { 1051b1f05622SIan Rogers FILE *file = perf_pmu__open_file_at(pmu, dirfd, "alias"); 1052b1f05622SIan Rogers char *line = NULL; 1053b1f05622SIan Rogers size_t line_len = 0; 1054b1f05622SIan Rogers ssize_t ret; 105513d60ba0SKan Liang 1056b1f05622SIan Rogers if (!file) 105713d60ba0SKan Liang return NULL; 1058b1f05622SIan Rogers 1059b1f05622SIan Rogers ret = getline(&line, &line_len, file); 1060b1f05622SIan Rogers if (ret < 0) { 1061b1f05622SIan Rogers fclose(file); 1062b1f05622SIan Rogers return NULL; 1063b1f05622SIan Rogers } 1064b1f05622SIan Rogers /* Remove trailing newline. */ 1065b1f05622SIan Rogers if (ret > 0 && line[ret - 1] == '\n') 1066b1f05622SIan Rogers line[--ret] = '\0'; 1067b1f05622SIan Rogers 1068b1f05622SIan Rogers fclose(file); 1069b1f05622SIan Rogers return line; 107013d60ba0SKan Liang } 107113d60ba0SKan Liang 10723a69672eSNamhyung Kim static int pmu_max_precise(int dirfd, struct perf_pmu *pmu) 107390a86bdeSJiri Olsa { 107490a86bdeSJiri Olsa int max_precise = -1; 107590a86bdeSJiri Olsa 10763a69672eSNamhyung Kim perf_pmu__scan_file_at(pmu, dirfd, "caps/max_precise", "%d", &max_precise); 107790a86bdeSJiri Olsa return max_precise; 107890a86bdeSJiri Olsa } 107990a86bdeSJiri Olsa 1080aa613601SIan Rogers void __weak 1081bb65acdcSKan Liang perf_pmu__arch_init(struct perf_pmu *pmu) 1082aa613601SIan Rogers { 1083bb65acdcSKan Liang if (pmu->is_core) 1084bb65acdcSKan Liang pmu->mem_events = perf_mem_events; 1085aa613601SIan Rogers } 1086aa613601SIan Rogers 1087aa1551f2SIan Rogers struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char *name, 1088aa1551f2SIan Rogers bool eager_load) 1089cd82a32eSJiri Olsa { 1090cd82a32eSJiri Olsa struct perf_pmu *pmu; 1091cd82a32eSJiri Olsa __u32 type; 109249afa7f6SJin Yao 1093cd82a32eSJiri Olsa pmu = zalloc(sizeof(*pmu)); 1094cd82a32eSJiri Olsa if (!pmu) 1095cd82a32eSJiri Olsa return NULL; 1096cd82a32eSJiri Olsa 1097f63a536fSIan Rogers pmu->name = strdup(name); 1098f63a536fSIan Rogers if (!pmu->name) 1099f63a536fSIan Rogers goto err; 110088ed9184SIan Rogers 110188ed9184SIan Rogers /* 110288ed9184SIan Rogers * Read type early to fail fast if a lookup name isn't a PMU. Ensure 110388ed9184SIan Rogers * that type value is successfully assigned (return 1). 110488ed9184SIan Rogers */ 110588ed9184SIan Rogers if (perf_pmu__scan_file_at(pmu, dirfd, "type", "%u", &type) != 1) 110688ed9184SIan Rogers goto err; 110788ed9184SIan Rogers 110888ed9184SIan Rogers INIT_LIST_HEAD(&pmu->format); 110988ed9184SIan Rogers INIT_LIST_HEAD(&pmu->aliases); 111088ed9184SIan Rogers INIT_LIST_HEAD(&pmu->caps); 111188ed9184SIan Rogers 1112838a8c5fSIan Rogers /* 1113838a8c5fSIan Rogers * The pmu data we store & need consists of the pmu 1114838a8c5fSIan Rogers * type value and format definitions. Load both right 1115838a8c5fSIan Rogers * now. 1116838a8c5fSIan Rogers */ 1117aa1551f2SIan Rogers if (pmu_format(pmu, dirfd, name, eager_load)) 1118ef5de161SChristophe JAILLET goto err; 1119ef5de161SChristophe JAILLET 1120d06593aaSIan Rogers pmu->is_core = is_pmu_core(name); 1121d06593aaSIan Rogers pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core); 112213d60ba0SKan Liang 112354e32dc0SGanapatrao Kulkarni pmu->type = type; 11243a69672eSNamhyung Kim pmu->is_uncore = pmu_is_uncore(dirfd, name); 112551d54847SJohn Garry if (pmu->is_uncore) 112651d54847SJohn Garry pmu->id = pmu_id(name); 11273a69672eSNamhyung Kim pmu->max_precise = pmu_max_precise(dirfd, pmu); 1128b1f05622SIan Rogers pmu->alias_name = pmu_find_alias_name(pmu, dirfd); 11297c52f10cSIan Rogers pmu->events_table = perf_pmu__find_events_table(pmu); 1130d9c5f5f9SIan Rogers /* 1131d9c5f5f9SIan Rogers * Load the sys json events/aliases when loading the PMU as each event 1132d9c5f5f9SIan Rogers * may have a different compat regular expression. We therefore can't 1133d9c5f5f9SIan Rogers * know the number of sys json events/aliases without computing the 1134d9c5f5f9SIan Rogers * regular expressions for them all. 1135d9c5f5f9SIan Rogers */ 1136838a8c5fSIan Rogers pmu_add_sys_aliases(pmu); 11371eaf496eSIan Rogers list_add_tail(&pmu->list, pmus); 1138dc0a6202SAdrian Hunter 1139aa613601SIan Rogers perf_pmu__arch_init(pmu); 1140dc0a6202SAdrian Hunter 114118eb2ca8SIan Rogers if (eager_load) 114218eb2ca8SIan Rogers pmu_aliases_parse_eager(pmu, dirfd); 114318eb2ca8SIan Rogers 1144cd82a32eSJiri Olsa return pmu; 114513d60ba0SKan Liang err: 1146efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 114713d60ba0SKan Liang free(pmu); 114813d60ba0SKan Liang return NULL; 1149cd82a32eSJiri Olsa } 1150cd82a32eSJiri Olsa 1151628eaa4eSIan Rogers /* Creates the PMU when sysfs scanning fails. */ 1152628eaa4eSIan Rogers struct perf_pmu *perf_pmu__create_placeholder_core_pmu(struct list_head *core_pmus) 1153628eaa4eSIan Rogers { 1154628eaa4eSIan Rogers struct perf_pmu *pmu = zalloc(sizeof(*pmu)); 1155628eaa4eSIan Rogers 1156628eaa4eSIan Rogers if (!pmu) 1157628eaa4eSIan Rogers return NULL; 1158628eaa4eSIan Rogers 1159628eaa4eSIan Rogers pmu->name = strdup("cpu"); 1160628eaa4eSIan Rogers if (!pmu->name) { 1161628eaa4eSIan Rogers free(pmu); 1162628eaa4eSIan Rogers return NULL; 1163628eaa4eSIan Rogers } 1164628eaa4eSIan Rogers 1165628eaa4eSIan Rogers pmu->is_core = true; 1166628eaa4eSIan Rogers pmu->type = PERF_TYPE_RAW; 1167628eaa4eSIan Rogers pmu->cpus = cpu_map__online(); 1168628eaa4eSIan Rogers 1169628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->format); 1170628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->aliases); 1171628eaa4eSIan Rogers INIT_LIST_HEAD(&pmu->caps); 1172628eaa4eSIan Rogers list_add_tail(&pmu->list, core_pmus); 1173628eaa4eSIan Rogers return pmu; 1174628eaa4eSIan Rogers } 1175628eaa4eSIan Rogers 1176e552b7beSRob Herring void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu) 1177e552b7beSRob Herring { 1178e552b7beSRob Herring struct perf_pmu_format *format; 1179e552b7beSRob Herring 118068c25043SIan Rogers if (pmu->formats_checked) 118168c25043SIan Rogers return; 118268c25043SIan Rogers 118368c25043SIan Rogers pmu->formats_checked = true; 118468c25043SIan Rogers 1185e552b7beSRob Herring /* fake pmu doesn't have format list */ 1186e552b7beSRob Herring if (pmu == &perf_pmu__fake) 1187e552b7beSRob Herring return; 1188e552b7beSRob Herring 118950402641SIan Rogers list_for_each_entry(format, &pmu->format, list) { 119050402641SIan Rogers perf_pmu_format__load(pmu, format); 1191e552b7beSRob Herring if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) { 1192e552b7beSRob Herring pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'" 1193e552b7beSRob Herring "which is not supported by this version of perf!\n", 1194e552b7beSRob Herring pmu->name, format->name, format->value); 1195e552b7beSRob Herring return; 1196e552b7beSRob Herring } 1197e552b7beSRob Herring } 119850402641SIan Rogers } 1199e552b7beSRob Herring 1200c6d616feSIan Rogers bool evsel__is_aux_event(const struct evsel *evsel) 1201e12ee9f7SAdrian Hunter { 1202e76026bdSArnaldo Carvalho de Melo struct perf_pmu *pmu = evsel__find_pmu(evsel); 1203e12ee9f7SAdrian Hunter 1204e12ee9f7SAdrian Hunter return pmu && pmu->auxtrace; 1205e12ee9f7SAdrian Hunter } 1206e12ee9f7SAdrian Hunter 12076593f019SJames Clark /* 12086593f019SJames Clark * Set @config_name to @val as long as the user hasn't already set or cleared it 12096593f019SJames Clark * by passing a config term on the command line. 12106593f019SJames Clark * 12116593f019SJames Clark * @val is the value to put into the bits specified by @config_name rather than 12126593f019SJames Clark * the bit pattern. It is shifted into position by this function, so to set 12136593f019SJames Clark * something to true, pass 1 for val rather than a pre shifted value. 12146593f019SJames Clark */ 12156593f019SJames Clark #define field_prep(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask)) 12166593f019SJames Clark void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, 12176593f019SJames Clark const char *config_name, u64 val) 12186593f019SJames Clark { 12196593f019SJames Clark u64 user_bits = 0, bits; 12206593f019SJames Clark struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG); 12216593f019SJames Clark 12226593f019SJames Clark if (term) 12236593f019SJames Clark user_bits = term->val.cfg_chg; 12246593f019SJames Clark 1225da6a5afdSIan Rogers bits = perf_pmu__format_bits(pmu, config_name); 12266593f019SJames Clark 12276593f019SJames Clark /* Do nothing if the user changed the value */ 12286593f019SJames Clark if (bits & user_bits) 12296593f019SJames Clark return; 12306593f019SJames Clark 12316593f019SJames Clark /* Otherwise replace it */ 12326593f019SJames Clark evsel->core.attr.config &= ~bits; 12336593f019SJames Clark evsel->core.attr.config |= field_prep(bits, val); 12346593f019SJames Clark } 12356593f019SJames Clark 12365c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_format * 123763883cb0SIan Rogers pmu_find_format(const struct list_head *formats, const char *name) 1238cd82a32eSJiri Olsa { 12395c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1240cd82a32eSJiri Olsa 1241cd82a32eSJiri Olsa list_for_each_entry(format, formats, list) 1242cd82a32eSJiri Olsa if (!strcmp(format->name, name)) 1243cd82a32eSJiri Olsa return format; 1244cd82a32eSJiri Olsa 1245cd82a32eSJiri Olsa return NULL; 1246cd82a32eSJiri Olsa } 1247cd82a32eSJiri Olsa 1248da6a5afdSIan Rogers __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name) 124909ff6071SAdrian Hunter { 1250da6a5afdSIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 125109ff6071SAdrian Hunter __u64 bits = 0; 125209ff6071SAdrian Hunter int fbit; 125309ff6071SAdrian Hunter 125409ff6071SAdrian Hunter if (!format) 125509ff6071SAdrian Hunter return 0; 125609ff6071SAdrian Hunter 125709ff6071SAdrian Hunter for_each_set_bit(fbit, format->bits, PERF_PMU_FORMAT_BITS) 125809ff6071SAdrian Hunter bits |= 1ULL << fbit; 125909ff6071SAdrian Hunter 126009ff6071SAdrian Hunter return bits; 126109ff6071SAdrian Hunter } 126209ff6071SAdrian Hunter 12637eb54733SIan Rogers int perf_pmu__format_type(struct perf_pmu *pmu, const char *name) 1264a1ac7de6SAdrian Hunter { 12657eb54733SIan Rogers struct perf_pmu_format *format = pmu_find_format(&pmu->format, name); 1266a1ac7de6SAdrian Hunter 1267a1ac7de6SAdrian Hunter if (!format) 1268a1ac7de6SAdrian Hunter return -1; 1269a1ac7de6SAdrian Hunter 127050402641SIan Rogers perf_pmu_format__load(pmu, format); 1271a1ac7de6SAdrian Hunter return format->value; 1272a1ac7de6SAdrian Hunter } 1273a1ac7de6SAdrian Hunter 1274cd82a32eSJiri Olsa /* 1275dc0a6202SAdrian Hunter * Sets value based on the format definition (format parameter) 12764d39c89fSIngo Molnar * and unformatted value (value parameter). 1277cd82a32eSJiri Olsa */ 1278dc0a6202SAdrian Hunter static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, 1279dc0a6202SAdrian Hunter bool zero) 1280cd82a32eSJiri Olsa { 1281cd82a32eSJiri Olsa unsigned long fbit, vbit; 1282cd82a32eSJiri Olsa 1283cd82a32eSJiri Olsa for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 1284cd82a32eSJiri Olsa 1285cd82a32eSJiri Olsa if (!test_bit(fbit, format)) 1286cd82a32eSJiri Olsa continue; 1287cd82a32eSJiri Olsa 1288dc0a6202SAdrian Hunter if (value & (1llu << vbit++)) 1289dc0a6202SAdrian Hunter *v |= (1llu << fbit); 1290dc0a6202SAdrian Hunter else if (zero) 1291dc0a6202SAdrian Hunter *v &= ~(1llu << fbit); 1292cd82a32eSJiri Olsa } 1293cd82a32eSJiri Olsa } 1294cd82a32eSJiri Olsa 12950efe6b67SAdrian Hunter static __u64 pmu_format_max_value(const unsigned long *format) 12960efe6b67SAdrian Hunter { 12971b9caa10SJiri Olsa int w; 12980efe6b67SAdrian Hunter 12991b9caa10SJiri Olsa w = bitmap_weight(format, PERF_PMU_FORMAT_BITS); 13001b9caa10SJiri Olsa if (!w) 13011b9caa10SJiri Olsa return 0; 13021b9caa10SJiri Olsa if (w < 64) 13031b9caa10SJiri Olsa return (1ULL << w) - 1; 13041b9caa10SJiri Olsa return -1; 13050efe6b67SAdrian Hunter } 13060efe6b67SAdrian Hunter 1307cd82a32eSJiri Olsa /* 1308688d4dfcSCody P Schafer * Term is a string term, and might be a param-term. Try to look up it's value 1309688d4dfcSCody P Schafer * in the remaining terms. 1310688d4dfcSCody P Schafer * - We have a term like "base-or-format-term=param-term", 1311688d4dfcSCody P Schafer * - We need to find the value supplied for "param-term" (with param-term named 1312688d4dfcSCody P Schafer * in a config string) later on in the term list. 1313688d4dfcSCody P Schafer */ 1314688d4dfcSCody P Schafer static int pmu_resolve_param_term(struct parse_events_term *term, 13150d3f0e6fSIan Rogers struct parse_events_terms *head_terms, 1316688d4dfcSCody P Schafer __u64 *value) 1317688d4dfcSCody P Schafer { 1318688d4dfcSCody P Schafer struct parse_events_term *t; 1319688d4dfcSCody P Schafer 13200d3f0e6fSIan Rogers list_for_each_entry(t, &head_terms->terms, list) { 13212a3d252dSIan Rogers if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM && 13222a3d252dSIan Rogers t->config && !strcmp(t->config, term->config)) { 1323688d4dfcSCody P Schafer t->used = true; 1324688d4dfcSCody P Schafer *value = t->val.num; 1325688d4dfcSCody P Schafer return 0; 1326688d4dfcSCody P Schafer } 1327688d4dfcSCody P Schafer } 1328688d4dfcSCody P Schafer 1329bb963e16SNamhyung Kim if (verbose > 0) 1330688d4dfcSCody P Schafer printf("Required parameter '%s' not specified\n", term->config); 1331688d4dfcSCody P Schafer 1332688d4dfcSCody P Schafer return -1; 1333688d4dfcSCody P Schafer } 1334688d4dfcSCody P Schafer 133563883cb0SIan Rogers static char *pmu_formats_string(const struct list_head *formats) 1336e64b020bSJiri Olsa { 1337e64b020bSJiri Olsa struct perf_pmu_format *format; 133811db4e29SMasami Hiramatsu char *str = NULL; 133911db4e29SMasami Hiramatsu struct strbuf buf = STRBUF_INIT; 1340f1417ceaSXin Gao unsigned int i = 0; 1341e64b020bSJiri Olsa 1342ffeb883eSHe Kuang if (!formats) 1343e64b020bSJiri Olsa return NULL; 1344e64b020bSJiri Olsa 1345e64b020bSJiri Olsa /* sysfs exported terms */ 1346ffeb883eSHe Kuang list_for_each_entry(format, formats, list) 134711db4e29SMasami Hiramatsu if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0) 134811db4e29SMasami Hiramatsu goto error; 1349e64b020bSJiri Olsa 1350ffeb883eSHe Kuang str = strbuf_detach(&buf, NULL); 135111db4e29SMasami Hiramatsu error: 1352ffeb883eSHe Kuang strbuf_release(&buf); 1353e64b020bSJiri Olsa 1354e64b020bSJiri Olsa return str; 1355e64b020bSJiri Olsa } 1356e64b020bSJiri Olsa 1357688d4dfcSCody P Schafer /* 1358cd82a32eSJiri Olsa * Setup one of config[12] attr members based on the 135988aca8d9SCody P Schafer * user input data - term parameter. 1360cd82a32eSJiri Olsa */ 136163883cb0SIan Rogers static int pmu_config_term(const struct perf_pmu *pmu, 1362cd82a32eSJiri Olsa struct perf_event_attr *attr, 1363dc0a6202SAdrian Hunter struct parse_events_term *term, 13640d3f0e6fSIan Rogers struct parse_events_terms *head_terms, 1365e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1366cd82a32eSJiri Olsa { 13675c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_format *format; 1368cd82a32eSJiri Olsa __u64 *vp; 13690efe6b67SAdrian Hunter __u64 val, max_val; 1370cd82a32eSJiri Olsa 1371cd82a32eSJiri Olsa /* 1372688d4dfcSCody P Schafer * If this is a parameter we've already used for parameterized-eval, 1373688d4dfcSCody P Schafer * skip it in normal eval. 1374688d4dfcSCody P Schafer */ 1375688d4dfcSCody P Schafer if (term->used) 1376688d4dfcSCody P Schafer return 0; 1377688d4dfcSCody P Schafer 1378688d4dfcSCody P Schafer /* 1379cd82a32eSJiri Olsa * Hardcoded terms should be already in, so nothing 1380cd82a32eSJiri Olsa * to be done for them. 1381cd82a32eSJiri Olsa */ 1382cd82a32eSJiri Olsa if (parse_events__is_hardcoded_term(term)) 1383cd82a32eSJiri Olsa return 0; 1384cd82a32eSJiri Olsa 1385804fee5dSIan Rogers format = pmu_find_format(&pmu->format, term->config); 1386688d4dfcSCody P Schafer if (!format) { 1387804fee5dSIan Rogers char *pmu_term = pmu_formats_string(&pmu->format); 13884ac22b48SIan Rogers char *unknown_term; 13894ac22b48SIan Rogers char *help_msg; 1390ffeb883eSHe Kuang 13914ac22b48SIan Rogers if (asprintf(&unknown_term, 13924ac22b48SIan Rogers "unknown term '%s' for pmu '%s'", 1393804fee5dSIan Rogers term->config, pmu->name) < 0) 13944ac22b48SIan Rogers unknown_term = NULL; 13954ac22b48SIan Rogers help_msg = parse_events_formats_error_string(pmu_term); 13964ac22b48SIan Rogers if (err) { 13976c191289SIan Rogers parse_events_error__handle(err, term->err_term, 13984ac22b48SIan Rogers unknown_term, 13994ac22b48SIan Rogers help_msg); 14004ac22b48SIan Rogers } else { 14014ac22b48SIan Rogers pr_debug("%s (%s)\n", unknown_term, help_msg); 14024ac22b48SIan Rogers free(unknown_term); 1403e64b020bSJiri Olsa } 14044ac22b48SIan Rogers free(pmu_term); 1405cd82a32eSJiri Olsa return -EINVAL; 1406688d4dfcSCody P Schafer } 140750402641SIan Rogers perf_pmu_format__load(pmu, format); 1408cd82a32eSJiri Olsa switch (format->value) { 1409cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG: 1410cd82a32eSJiri Olsa vp = &attr->config; 1411cd82a32eSJiri Olsa break; 1412cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG1: 1413cd82a32eSJiri Olsa vp = &attr->config1; 1414cd82a32eSJiri Olsa break; 1415cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG2: 1416cd82a32eSJiri Olsa vp = &attr->config2; 1417cd82a32eSJiri Olsa break; 1418204e7c49SRob Herring case PERF_PMU_FORMAT_VALUE_CONFIG3: 1419204e7c49SRob Herring vp = &attr->config3; 1420204e7c49SRob Herring break; 1421cd82a32eSJiri Olsa default: 1422cd82a32eSJiri Olsa return -EINVAL; 1423cd82a32eSJiri Olsa } 1424cd82a32eSJiri Olsa 142516fa7e82SJiri Olsa /* 1426688d4dfcSCody P Schafer * Either directly use a numeric term, or try to translate string terms 1427688d4dfcSCody P Schafer * using event parameters. 142816fa7e82SJiri Olsa */ 142999e7138eSJiri Olsa if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 143099e7138eSJiri Olsa if (term->no_value && 143199e7138eSJiri Olsa bitmap_weight(format->bits, PERF_PMU_FORMAT_BITS) > 1) { 143299e7138eSJiri Olsa if (err) { 14336c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1434448d732cSIan Rogers strdup("no value assigned for term"), 1435448d732cSIan Rogers NULL); 143699e7138eSJiri Olsa } 143799e7138eSJiri Olsa return -EINVAL; 143899e7138eSJiri Olsa } 143999e7138eSJiri Olsa 1440688d4dfcSCody P Schafer val = term->val.num; 144199e7138eSJiri Olsa } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1442688d4dfcSCody P Schafer if (strcmp(term->val.str, "?")) { 1443bb963e16SNamhyung Kim if (verbose > 0) { 1444688d4dfcSCody P Schafer pr_info("Invalid sysfs entry %s=%s\n", 1445688d4dfcSCody P Schafer term->config, term->val.str); 1446e64b020bSJiri Olsa } 1447e64b020bSJiri Olsa if (err) { 14486c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1449448d732cSIan Rogers strdup("expected numeric value"), 1450448d732cSIan Rogers NULL); 1451e64b020bSJiri Olsa } 1452688d4dfcSCody P Schafer return -EINVAL; 1453688d4dfcSCody P Schafer } 1454688d4dfcSCody P Schafer 1455688d4dfcSCody P Schafer if (pmu_resolve_param_term(term, head_terms, &val)) 1456688d4dfcSCody P Schafer return -EINVAL; 1457688d4dfcSCody P Schafer } else 1458688d4dfcSCody P Schafer return -EINVAL; 1459688d4dfcSCody P Schafer 14600efe6b67SAdrian Hunter max_val = pmu_format_max_value(format->bits); 14610efe6b67SAdrian Hunter if (val > max_val) { 14620efe6b67SAdrian Hunter if (err) { 1463448d732cSIan Rogers char *err_str; 1464448d732cSIan Rogers 14656c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1466448d732cSIan Rogers asprintf(&err_str, 1467f5144ecaSIan Rogers "value too big for format (%s), maximum is %llu", 1468f5144ecaSIan Rogers format->name, (unsigned long long)max_val) < 0 1469448d732cSIan Rogers ? strdup("value too big for format") 1470448d732cSIan Rogers : err_str, 1471448d732cSIan Rogers NULL); 14720efe6b67SAdrian Hunter return -EINVAL; 14730efe6b67SAdrian Hunter } 14740efe6b67SAdrian Hunter /* 14750efe6b67SAdrian Hunter * Assume we don't care if !err, in which case the value will be 14760efe6b67SAdrian Hunter * silently truncated. 14770efe6b67SAdrian Hunter */ 14780efe6b67SAdrian Hunter } 14790efe6b67SAdrian Hunter 1480688d4dfcSCody P Schafer pmu_format_value(format->bits, val, vp, zero); 1481cd82a32eSJiri Olsa return 0; 1482cd82a32eSJiri Olsa } 1483cd82a32eSJiri Olsa 148463883cb0SIan Rogers int perf_pmu__config_terms(const struct perf_pmu *pmu, 1485cff7f956SJiri Olsa struct perf_event_attr *attr, 14860d3f0e6fSIan Rogers struct parse_events_terms *terms, 1487e64b020bSJiri Olsa bool zero, struct parse_events_error *err) 1488cd82a32eSJiri Olsa { 14896cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 1490cd82a32eSJiri Olsa 14910d3f0e6fSIan Rogers list_for_each_entry(term, &terms->terms, list) { 14920d3f0e6fSIan Rogers if (pmu_config_term(pmu, attr, term, terms, zero, err)) 1493cd82a32eSJiri Olsa return -EINVAL; 1494688d4dfcSCody P Schafer } 1495cd82a32eSJiri Olsa 1496cd82a32eSJiri Olsa return 0; 1497cd82a32eSJiri Olsa } 1498cd82a32eSJiri Olsa 1499cd82a32eSJiri Olsa /* 1500cd82a32eSJiri Olsa * Configures event's 'attr' parameter based on the: 1501cd82a32eSJiri Olsa * 1) users input - specified in terms parameter 1502cd82a32eSJiri Olsa * 2) pmu format definitions - specified by pmu parameter 1503cd82a32eSJiri Olsa */ 1504cd82a32eSJiri Olsa int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 15050d3f0e6fSIan Rogers struct parse_events_terms *head_terms, 1506e64b020bSJiri Olsa struct parse_events_error *err) 1507cd82a32eSJiri Olsa { 15080197da7aSIan Rogers bool zero = !!pmu->perf_event_attr_init_default; 1509dc0a6202SAdrian Hunter 1510804fee5dSIan Rogers return perf_pmu__config_terms(pmu, attr, head_terms, zero, err); 1511cd82a32eSJiri Olsa } 1512cd82a32eSJiri Olsa 15135c6ccc37SArnaldo Carvalho de Melo static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 15146cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 1515a6146d50SZheng Yan { 1516e6ff1eedSIan Rogers struct perf_pmu_alias *alias; 1517970ef02eSIan Rogers const char *name; 1518a6146d50SZheng Yan 1519a6146d50SZheng Yan if (parse_events__is_hardcoded_term(term)) 1520a6146d50SZheng Yan return NULL; 1521a6146d50SZheng Yan 1522a6146d50SZheng Yan if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 152364199ae4SIan Rogers if (!term->no_value) 1524a6146d50SZheng Yan return NULL; 1525a6146d50SZheng Yan if (pmu_find_format(&pmu->format, term->config)) 1526a6146d50SZheng Yan return NULL; 1527a6146d50SZheng Yan name = term->config; 1528c3245d20SIan Rogers 1529a6146d50SZheng Yan } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 1530a6146d50SZheng Yan if (strcasecmp(term->config, "event")) 1531a6146d50SZheng Yan return NULL; 1532a6146d50SZheng Yan name = term->val.str; 1533a6146d50SZheng Yan } else { 1534a6146d50SZheng Yan return NULL; 1535a6146d50SZheng Yan } 1536a6146d50SZheng Yan 15378d4b6d37SIan Rogers alias = perf_pmu__find_alias(pmu, name, /*load=*/ true); 1538e6ff1eedSIan Rogers if (alias || pmu->cpu_aliases_added) 1539e6ff1eedSIan Rogers return alias; 1540e6ff1eedSIan Rogers 1541e6ff1eedSIan Rogers /* Alias doesn't exist, try to get it from the json events. */ 1542e6ff1eedSIan Rogers if (pmu->events_table && 1543e6ff1eedSIan Rogers pmu_events_table__find_event(pmu->events_table, pmu, name, 1544e6ff1eedSIan Rogers pmu_add_cpu_aliases_map_callback, 1545e6ff1eedSIan Rogers pmu) == 0) { 15468d4b6d37SIan Rogers alias = perf_pmu__find_alias(pmu, name, /*load=*/ false); 1547e6ff1eedSIan Rogers } 1548e6ff1eedSIan Rogers return alias; 1549a6146d50SZheng Yan } 1550a6146d50SZheng Yan 1551410136f5SStephane Eranian 15527b723dbbSIan Rogers static int check_info_data(struct perf_pmu *pmu, 15537b723dbbSIan Rogers struct perf_pmu_alias *alias, 15549d31cb93SIan Rogers struct perf_pmu_info *info, 15559d31cb93SIan Rogers struct parse_events_error *err, 15569d31cb93SIan Rogers int column) 1557410136f5SStephane Eranian { 15587b723dbbSIan Rogers read_alias_info(pmu, alias); 1559410136f5SStephane Eranian /* 1560410136f5SStephane Eranian * Only one term in event definition can 15611d9e446bSJiri Olsa * define unit, scale and snapshot, fail 15621d9e446bSJiri Olsa * if there's more than one. 1563410136f5SStephane Eranian */ 15649d31cb93SIan Rogers if (info->unit && alias->unit[0]) { 15659d31cb93SIan Rogers parse_events_error__handle(err, column, 15669d31cb93SIan Rogers strdup("Attempt to set event's unit twice"), 15679d31cb93SIan Rogers NULL); 1568410136f5SStephane Eranian return -EINVAL; 15699d31cb93SIan Rogers } 15709d31cb93SIan Rogers if (info->scale && alias->scale) { 15719d31cb93SIan Rogers parse_events_error__handle(err, column, 15729d31cb93SIan Rogers strdup("Attempt to set event's scale twice"), 15739d31cb93SIan Rogers NULL); 15749d31cb93SIan Rogers return -EINVAL; 15759d31cb93SIan Rogers } 15769d31cb93SIan Rogers if (info->snapshot && alias->snapshot) { 15779d31cb93SIan Rogers parse_events_error__handle(err, column, 15789d31cb93SIan Rogers strdup("Attempt to set event snapshot twice"), 15799d31cb93SIan Rogers NULL); 15809d31cb93SIan Rogers return -EINVAL; 15819d31cb93SIan Rogers } 1582410136f5SStephane Eranian 1583b30a7d1fSArnaldo Carvalho de Melo if (alias->unit[0]) 15841d9e446bSJiri Olsa info->unit = alias->unit; 1585410136f5SStephane Eranian 1586410136f5SStephane Eranian if (alias->scale) 15871d9e446bSJiri Olsa info->scale = alias->scale; 15881d9e446bSJiri Olsa 15891d9e446bSJiri Olsa if (alias->snapshot) 15901d9e446bSJiri Olsa info->snapshot = alias->snapshot; 1591410136f5SStephane Eranian 1592410136f5SStephane Eranian return 0; 1593410136f5SStephane Eranian } 1594410136f5SStephane Eranian 1595a6146d50SZheng Yan /* 1596a6146d50SZheng Yan * Find alias in the terms list and replace it with the terms 1597a6146d50SZheng Yan * defined for the alias 1598a6146d50SZheng Yan */ 15990d3f0e6fSIan Rogers int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms, 1600a24d9d9dSIan Rogers struct perf_pmu_info *info, bool *rewrote_terms, 1601a24d9d9dSIan Rogers struct parse_events_error *err) 1602a6146d50SZheng Yan { 16036cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 16045c6ccc37SArnaldo Carvalho de Melo struct perf_pmu_alias *alias; 1605a6146d50SZheng Yan int ret; 1606a6146d50SZheng Yan 1607a24d9d9dSIan Rogers *rewrote_terms = false; 1608044330c1SMatt Fleming info->per_pkg = false; 1609044330c1SMatt Fleming 16108a398897SStephane Eranian /* 16118a398897SStephane Eranian * Mark unit and scale as not set 16128a398897SStephane Eranian * (different from default values, see below) 16138a398897SStephane Eranian */ 161446441bdcSMatt Fleming info->unit = NULL; 161546441bdcSMatt Fleming info->scale = 0.0; 16161d9e446bSJiri Olsa info->snapshot = false; 1617410136f5SStephane Eranian 16180d3f0e6fSIan Rogers list_for_each_entry_safe(term, h, &head_terms->terms, list) { 1619a6146d50SZheng Yan alias = pmu_find_alias(pmu, term); 1620a6146d50SZheng Yan if (!alias) 1621a6146d50SZheng Yan continue; 1622f5144ecaSIan Rogers ret = pmu_alias_terms(alias, term->err_term, &term->list); 16239d31cb93SIan Rogers if (ret) { 16249d31cb93SIan Rogers parse_events_error__handle(err, term->err_term, 16259d31cb93SIan Rogers strdup("Failure to duplicate terms"), 16269d31cb93SIan Rogers NULL); 1627a6146d50SZheng Yan return ret; 16289d31cb93SIan Rogers } 1629a24d9d9dSIan Rogers *rewrote_terms = true; 16307b723dbbSIan Rogers ret = check_info_data(pmu, alias, info, err, term->err_term); 1631410136f5SStephane Eranian if (ret) 1632410136f5SStephane Eranian return ret; 1633410136f5SStephane Eranian 1634044330c1SMatt Fleming if (alias->per_pkg) 1635044330c1SMatt Fleming info->per_pkg = true; 1636044330c1SMatt Fleming 1637e56fbc9dSArnaldo Carvalho de Melo list_del_init(&term->list); 16381dc92556SIan Rogers parse_events_term__delete(term); 1639a6146d50SZheng Yan } 16408a398897SStephane Eranian 16418a398897SStephane Eranian /* 16428a398897SStephane Eranian * if no unit or scale found in aliases, then 16438a398897SStephane Eranian * set defaults as for evsel 16448a398897SStephane Eranian * unit cannot left to NULL 16458a398897SStephane Eranian */ 164646441bdcSMatt Fleming if (info->unit == NULL) 164746441bdcSMatt Fleming info->unit = ""; 16488a398897SStephane Eranian 164946441bdcSMatt Fleming if (info->scale == 0.0) 165046441bdcSMatt Fleming info->scale = 1.0; 16518a398897SStephane Eranian 1652a6146d50SZheng Yan return 0; 1653a6146d50SZheng Yan } 1654a6146d50SZheng Yan 1655c3245d20SIan Rogers struct find_event_args { 1656c3245d20SIan Rogers const char *event; 1657c3245d20SIan Rogers void *state; 1658c3245d20SIan Rogers pmu_event_callback cb; 1659c3245d20SIan Rogers }; 1660c3245d20SIan Rogers 1661c3245d20SIan Rogers static int find_event_callback(void *state, struct pmu_event_info *info) 1662838a8c5fSIan Rogers { 1663c3245d20SIan Rogers struct find_event_args *args = state; 1664838a8c5fSIan Rogers 1665c3245d20SIan Rogers if (!strcmp(args->event, info->name)) 1666c3245d20SIan Rogers return args->cb(args->state, info); 1667838a8c5fSIan Rogers 1668c3245d20SIan Rogers return 0; 1669838a8c5fSIan Rogers } 1670c3245d20SIan Rogers 1671c3245d20SIan Rogers int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb) 1672c3245d20SIan Rogers { 1673c3245d20SIan Rogers struct find_event_args args = { 1674c3245d20SIan Rogers .event = event, 1675c3245d20SIan Rogers .state = state, 1676c3245d20SIan Rogers .cb = cb, 1677c3245d20SIan Rogers }; 1678c3245d20SIan Rogers 1679cd4e1efbSIan Rogers /* Sub-optimal, but function is only used by tests. */ 1680cd4e1efbSIan Rogers return perf_pmu__for_each_event(pmu, /*skip_duplicate_pmus=*/ false, 1681cd4e1efbSIan Rogers &args, find_event_callback); 1682c3245d20SIan Rogers } 1683c3245d20SIan Rogers 1684804fee5dSIan Rogers static void perf_pmu__del_formats(struct list_head *formats) 1685d26383dcSNamhyung Kim { 1686d26383dcSNamhyung Kim struct perf_pmu_format *fmt, *tmp; 1687d26383dcSNamhyung Kim 1688d26383dcSNamhyung Kim list_for_each_entry_safe(fmt, tmp, formats, list) { 1689d26383dcSNamhyung Kim list_del(&fmt->list); 1690efe98a7aSArnaldo Carvalho de Melo zfree(&fmt->name); 1691d26383dcSNamhyung Kim free(fmt); 1692d26383dcSNamhyung Kim } 1693d26383dcSNamhyung Kim } 1694d26383dcSNamhyung Kim 169507d2b820SIan Rogers bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name) 169607d2b820SIan Rogers { 169707d2b820SIan Rogers struct perf_pmu_format *format; 169807d2b820SIan Rogers 169907d2b820SIan Rogers list_for_each_entry(format, &pmu->format, list) { 170007d2b820SIan Rogers if (!strcmp(format->name, name)) 170107d2b820SIan Rogers return true; 170207d2b820SIan Rogers } 170307d2b820SIan Rogers return false; 170407d2b820SIan Rogers } 170507d2b820SIan Rogers 17064ccf3bb7SIan Rogers int perf_pmu__for_each_format(struct perf_pmu *pmu, void *state, pmu_format_callback cb) 17074ccf3bb7SIan Rogers { 17084ccf3bb7SIan Rogers static const char *const terms[] = { 17094ccf3bb7SIan Rogers "config=0..0xffffffffffffffff", 17104ccf3bb7SIan Rogers "config1=0..0xffffffffffffffff", 17114ccf3bb7SIan Rogers "config2=0..0xffffffffffffffff", 17124ccf3bb7SIan Rogers "config3=0..0xffffffffffffffff", 17134ccf3bb7SIan Rogers "name=string", 17144ccf3bb7SIan Rogers "period=number", 17154ccf3bb7SIan Rogers "freq=number", 17164ccf3bb7SIan Rogers "branch_type=(u|k|hv|any|...)", 17174ccf3bb7SIan Rogers "time", 17184ccf3bb7SIan Rogers "call-graph=(fp|dwarf|lbr)", 17194ccf3bb7SIan Rogers "stack-size=number", 17204ccf3bb7SIan Rogers "max-stack=number", 17214ccf3bb7SIan Rogers "nr=number", 17224ccf3bb7SIan Rogers "inherit", 17234ccf3bb7SIan Rogers "no-inherit", 17244ccf3bb7SIan Rogers "overwrite", 17254ccf3bb7SIan Rogers "no-overwrite", 17264ccf3bb7SIan Rogers "percore", 17274ccf3bb7SIan Rogers "aux-output", 17284ccf3bb7SIan Rogers "aux-sample-size=number", 17294ccf3bb7SIan Rogers }; 17304ccf3bb7SIan Rogers struct perf_pmu_format *format; 17314ccf3bb7SIan Rogers int ret; 17324ccf3bb7SIan Rogers 17334ccf3bb7SIan Rogers /* 17344ccf3bb7SIan Rogers * max-events and driver-config are missing above as are the internal 17354ccf3bb7SIan Rogers * types user, metric-id, raw, legacy cache and hardware. Assert against 17364ccf3bb7SIan Rogers * the enum parse_events__term_type so they are kept in sync. 17374ccf3bb7SIan Rogers */ 17384ccf3bb7SIan Rogers _Static_assert(ARRAY_SIZE(terms) == __PARSE_EVENTS__TERM_TYPE_NR - 6, 17394ccf3bb7SIan Rogers "perf_pmu__for_each_format()'s terms must be kept in sync with enum parse_events__term_type"); 17404ccf3bb7SIan Rogers list_for_each_entry(format, &pmu->format, list) { 17414ccf3bb7SIan Rogers perf_pmu_format__load(pmu, format); 17424ccf3bb7SIan Rogers ret = cb(state, format->name, (int)format->value, format->bits); 17434ccf3bb7SIan Rogers if (ret) 17444ccf3bb7SIan Rogers return ret; 17454ccf3bb7SIan Rogers } 17464ccf3bb7SIan Rogers if (!pmu->is_core) 17474ccf3bb7SIan Rogers return 0; 17484ccf3bb7SIan Rogers 17494ccf3bb7SIan Rogers for (size_t i = 0; i < ARRAY_SIZE(terms); i++) { 17504ccf3bb7SIan Rogers int config = PERF_PMU_FORMAT_VALUE_CONFIG; 17514ccf3bb7SIan Rogers 17524ccf3bb7SIan Rogers if (i < PERF_PMU_FORMAT_VALUE_CONFIG_END) 17534ccf3bb7SIan Rogers config = i; 17544ccf3bb7SIan Rogers 17554ccf3bb7SIan Rogers ret = cb(state, terms[i], config, /*bits=*/NULL); 17564ccf3bb7SIan Rogers if (ret) 17574ccf3bb7SIan Rogers return ret; 17584ccf3bb7SIan Rogers } 17594ccf3bb7SIan Rogers return 0; 17604ccf3bb7SIan Rogers } 17614ccf3bb7SIan Rogers 1762d504fae9SJohn Garry bool is_pmu_core(const char *name) 1763d504fae9SJohn Garry { 17646fbd67b0SThomas Richter return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name); 17654bf7e81aSIan Rogers } 17664bf7e81aSIan Rogers 17676fd1e519SIan Rogers bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu) 17686fd1e519SIan Rogers { 1769e20d1f2fSIan Rogers return pmu->is_core; 17706fd1e519SIan Rogers } 17716fd1e519SIan Rogers 177252c7b4d3SIan Rogers bool perf_pmu__auto_merge_stats(const struct perf_pmu *pmu) 177352c7b4d3SIan Rogers { 1774710dffc9SIan Rogers return !pmu->is_core || perf_pmus__num_core_pmus() == 1; 177552c7b4d3SIan Rogers } 177652c7b4d3SIan Rogers 1777e6ff1eedSIan Rogers bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) 1778abe9544eSIan Rogers { 1779a24d9d9dSIan Rogers if (!name) 1780a24d9d9dSIan Rogers return false; 17818d4b6d37SIan Rogers if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL) 1782e6ff1eedSIan Rogers return true; 1783e6ff1eedSIan Rogers if (pmu->cpu_aliases_added || !pmu->events_table) 1784e6ff1eedSIan Rogers return false; 1785e6ff1eedSIan Rogers return pmu_events_table__find_event(pmu->events_table, pmu, name, NULL, NULL) == 0; 17864cabc3d1SAndi Kleen } 1787c3245d20SIan Rogers 1788e6ff1eedSIan Rogers size_t perf_pmu__num_events(struct perf_pmu *pmu) 1789c3245d20SIan Rogers { 17908d4b6d37SIan Rogers size_t nr; 17918d4b6d37SIan Rogers 17928d4b6d37SIan Rogers pmu_aliases_parse(pmu); 1793*5484fd27SYang Li nr = pmu->sysfs_aliases + pmu->sys_json_aliases; 1794c3245d20SIan Rogers 1795e6ff1eedSIan Rogers if (pmu->cpu_aliases_added) 1796d9c5f5f9SIan Rogers nr += pmu->cpu_json_aliases; 1797e6ff1eedSIan Rogers else if (pmu->events_table) 1798d9c5f5f9SIan Rogers nr += pmu_events_table__num_events(pmu->events_table, pmu) - pmu->cpu_json_aliases; 1799d9c5f5f9SIan Rogers else 1800d9c5f5f9SIan Rogers assert(pmu->cpu_json_aliases == 0); 1801c3245d20SIan Rogers 1802c3245d20SIan Rogers return pmu->selectable ? nr + 1 : nr; 1803c3245d20SIan Rogers } 1804c3245d20SIan Rogers 1805c3245d20SIan Rogers static int sub_non_neg(int a, int b) 1806c3245d20SIan Rogers { 1807c3245d20SIan Rogers if (b > a) 1808c3245d20SIan Rogers return 0; 1809c3245d20SIan Rogers return a - b; 1810c3245d20SIan Rogers } 1811c3245d20SIan Rogers 1812c3245d20SIan Rogers static char *format_alias(char *buf, int len, const struct perf_pmu *pmu, 1813cd4e1efbSIan Rogers const struct perf_pmu_alias *alias, bool skip_duplicate_pmus) 1814c3245d20SIan Rogers { 1815c3245d20SIan Rogers struct parse_events_term *term; 18167afbf90eSJames Clark size_t pmu_name_len = pmu_deduped_name_len(pmu, pmu->name, 18177afbf90eSJames Clark skip_duplicate_pmus); 18183241d46fSIan Rogers int used = snprintf(buf, len, "%.*s/%s", (int)pmu_name_len, pmu->name, alias->name); 1819c3245d20SIan Rogers 18200d3f0e6fSIan Rogers list_for_each_entry(term, &alias->terms.terms, list) { 1821c3245d20SIan Rogers if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) 1822c3245d20SIan Rogers used += snprintf(buf + used, sub_non_neg(len, used), 1823c3245d20SIan Rogers ",%s=%s", term->config, 1824c3245d20SIan Rogers term->val.str); 1825c3245d20SIan Rogers } 1826c3245d20SIan Rogers 1827c3245d20SIan Rogers if (sub_non_neg(len, used) > 0) { 1828c3245d20SIan Rogers buf[used] = '/'; 1829c3245d20SIan Rogers used++; 1830c3245d20SIan Rogers } 1831c3245d20SIan Rogers if (sub_non_neg(len, used) > 0) { 1832c3245d20SIan Rogers buf[used] = '\0'; 1833c3245d20SIan Rogers used++; 1834c3245d20SIan Rogers } else 1835c3245d20SIan Rogers buf[len - 1] = '\0'; 1836c3245d20SIan Rogers 1837c3245d20SIan Rogers return buf; 1838c3245d20SIan Rogers } 1839c3245d20SIan Rogers 1840cd4e1efbSIan Rogers int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus, 1841cd4e1efbSIan Rogers void *state, pmu_event_callback cb) 1842c3245d20SIan Rogers { 1843c3245d20SIan Rogers char buf[1024]; 1844c3245d20SIan Rogers struct perf_pmu_alias *event; 1845c3245d20SIan Rogers struct pmu_event_info info = { 1846c3245d20SIan Rogers .pmu = pmu, 1847c3245d20SIan Rogers }; 1848c3245d20SIan Rogers int ret = 0; 184930f0b435SIan Rogers struct strbuf sb; 1850c3245d20SIan Rogers 185130f0b435SIan Rogers strbuf_init(&sb, /*hint=*/ 0); 18527b6dd7a9SIan Rogers pmu_aliases_parse(pmu); 1853e6ff1eedSIan Rogers pmu_add_cpu_aliases(pmu); 1854c3245d20SIan Rogers list_for_each_entry(event, &pmu->aliases, list) { 18553241d46fSIan Rogers size_t buf_used, pmu_name_len; 1856c3245d20SIan Rogers 1857c3245d20SIan Rogers info.pmu_name = event->pmu_name ?: pmu->name; 18587afbf90eSJames Clark pmu_name_len = pmu_deduped_name_len(pmu, info.pmu_name, 18597afbf90eSJames Clark skip_duplicate_pmus); 1860c3245d20SIan Rogers info.alias = NULL; 1861c3245d20SIan Rogers if (event->desc) { 1862c3245d20SIan Rogers info.name = event->name; 1863c3245d20SIan Rogers buf_used = 0; 1864c3245d20SIan Rogers } else { 1865cd4e1efbSIan Rogers info.name = format_alias(buf, sizeof(buf), pmu, event, 1866cd4e1efbSIan Rogers skip_duplicate_pmus); 1867c3245d20SIan Rogers if (pmu->is_core) { 1868c3245d20SIan Rogers info.alias = info.name; 1869c3245d20SIan Rogers info.name = event->name; 1870c3245d20SIan Rogers } 1871c3245d20SIan Rogers buf_used = strlen(buf) + 1; 1872c3245d20SIan Rogers } 1873c3245d20SIan Rogers info.scale_unit = NULL; 1874c3245d20SIan Rogers if (strlen(event->unit) || event->scale != 1.0) { 1875c3245d20SIan Rogers info.scale_unit = buf + buf_used; 1876c3245d20SIan Rogers buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 1877c3245d20SIan Rogers "%G%s", event->scale, event->unit) + 1; 1878c3245d20SIan Rogers } 1879c3245d20SIan Rogers info.desc = event->desc; 1880c3245d20SIan Rogers info.long_desc = event->long_desc; 1881c3245d20SIan Rogers info.encoding_desc = buf + buf_used; 18820d3f0e6fSIan Rogers parse_events_terms__to_strbuf(&event->terms, &sb); 1883c3245d20SIan Rogers buf_used += snprintf(buf + buf_used, sizeof(buf) - buf_used, 18843241d46fSIan Rogers "%.*s/%s/", (int)pmu_name_len, info.pmu_name, sb.buf) + 1; 1885c3245d20SIan Rogers info.topic = event->topic; 188630f0b435SIan Rogers info.str = sb.buf; 1887c3245d20SIan Rogers info.deprecated = event->deprecated; 1888c3245d20SIan Rogers ret = cb(state, &info); 1889c3245d20SIan Rogers if (ret) 189030f0b435SIan Rogers goto out; 189130f0b435SIan Rogers strbuf_setlen(&sb, /*len=*/ 0); 1892c3245d20SIan Rogers } 1893c3245d20SIan Rogers if (pmu->selectable) { 1894c3245d20SIan Rogers info.name = buf; 1895c3245d20SIan Rogers snprintf(buf, sizeof(buf), "%s//", pmu->name); 1896c3245d20SIan Rogers info.alias = NULL; 1897c3245d20SIan Rogers info.scale_unit = NULL; 1898c3245d20SIan Rogers info.desc = NULL; 1899c3245d20SIan Rogers info.long_desc = NULL; 1900c3245d20SIan Rogers info.encoding_desc = NULL; 1901c3245d20SIan Rogers info.topic = NULL; 1902c3245d20SIan Rogers info.pmu_name = pmu->name; 1903c3245d20SIan Rogers info.deprecated = false; 1904c3245d20SIan Rogers ret = cb(state, &info); 1905c3245d20SIan Rogers } 190630f0b435SIan Rogers out: 190730f0b435SIan Rogers strbuf_release(&sb); 1908c3245d20SIan Rogers return ret; 19094cabc3d1SAndi Kleen } 19107d4bdab5SAdrian Hunter 1911e3edd6cfSIan Rogers bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name) 1912e3edd6cfSIan Rogers { 1913e3edd6cfSIan Rogers return !strcmp(pmu->name, pmu_name) || 1914d2045f87SIan Rogers (pmu->is_uncore && pmu_uncore_alias_match(pmu_name, pmu->name)) || 1915d2045f87SIan Rogers /* 1916d2045f87SIan Rogers * jevents and tests use default_core as a marker for any core 1917d2045f87SIan Rogers * PMU as the PMU name varies across architectures. 1918d2045f87SIan Rogers */ 1919d2045f87SIan Rogers (pmu->is_core && !strcmp(pmu_name, "default_core")); 1920e3edd6cfSIan Rogers } 1921e3edd6cfSIan Rogers 1922251aa040SIan Rogers bool perf_pmu__is_software(const struct perf_pmu *pmu) 1923251aa040SIan Rogers { 192424852ef2SIan Rogers const char *known_sw_pmus[] = { 192524852ef2SIan Rogers "kprobe", 192624852ef2SIan Rogers "msr", 192724852ef2SIan Rogers "uprobe", 192824852ef2SIan Rogers }; 192924852ef2SIan Rogers 1930251aa040SIan Rogers if (pmu->is_core || pmu->is_uncore || pmu->auxtrace) 1931251aa040SIan Rogers return false; 1932251aa040SIan Rogers switch (pmu->type) { 1933251aa040SIan Rogers case PERF_TYPE_HARDWARE: return false; 1934251aa040SIan Rogers case PERF_TYPE_SOFTWARE: return true; 1935251aa040SIan Rogers case PERF_TYPE_TRACEPOINT: return true; 1936251aa040SIan Rogers case PERF_TYPE_HW_CACHE: return false; 1937251aa040SIan Rogers case PERF_TYPE_RAW: return false; 1938251aa040SIan Rogers case PERF_TYPE_BREAKPOINT: return true; 1939251aa040SIan Rogers default: break; 1940251aa040SIan Rogers } 194124852ef2SIan Rogers for (size_t i = 0; i < ARRAY_SIZE(known_sw_pmus); i++) { 194224852ef2SIan Rogers if (!strcmp(pmu->name, known_sw_pmus[i])) 194324852ef2SIan Rogers return true; 194424852ef2SIan Rogers } 194524852ef2SIan Rogers return false; 1946251aa040SIan Rogers } 1947251aa040SIan Rogers 19483a42f4c7SIan Rogers FILE *perf_pmu__open_file(const struct perf_pmu *pmu, const char *name) 19497d4bdab5SAdrian Hunter { 19507d4bdab5SAdrian Hunter char path[PATH_MAX]; 19517d4bdab5SAdrian Hunter 1952f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name) || 1953f8ad6018SJames Clark !file_available(path)) 19547d4bdab5SAdrian Hunter return NULL; 19557d4bdab5SAdrian Hunter 19567d4bdab5SAdrian Hunter return fopen(path, "r"); 19577d4bdab5SAdrian Hunter } 19587d4bdab5SAdrian Hunter 19593a42f4c7SIan Rogers FILE *perf_pmu__open_file_at(const struct perf_pmu *pmu, int dirfd, const char *name) 19603a69672eSNamhyung Kim { 19613a69672eSNamhyung Kim int fd; 19623a69672eSNamhyung Kim 19633a69672eSNamhyung Kim fd = perf_pmu__pathname_fd(dirfd, pmu->name, name, O_RDONLY); 19643a69672eSNamhyung Kim if (fd < 0) 19653a69672eSNamhyung Kim return NULL; 19663a69672eSNamhyung Kim 19673a69672eSNamhyung Kim return fdopen(fd, "r"); 19683a69672eSNamhyung Kim } 19693a69672eSNamhyung Kim 19703a42f4c7SIan Rogers int perf_pmu__scan_file(const struct perf_pmu *pmu, const char *name, const char *fmt, 19717d4bdab5SAdrian Hunter ...) 19727d4bdab5SAdrian Hunter { 19737d4bdab5SAdrian Hunter va_list args; 19747d4bdab5SAdrian Hunter FILE *file; 19757d4bdab5SAdrian Hunter int ret = EOF; 19767d4bdab5SAdrian Hunter 19777d4bdab5SAdrian Hunter va_start(args, fmt); 19787d4bdab5SAdrian Hunter file = perf_pmu__open_file(pmu, name); 19797d4bdab5SAdrian Hunter if (file) { 19807d4bdab5SAdrian Hunter ret = vfscanf(file, fmt, args); 19817d4bdab5SAdrian Hunter fclose(file); 19827d4bdab5SAdrian Hunter } 19837d4bdab5SAdrian Hunter va_end(args); 19847d4bdab5SAdrian Hunter return ret; 19857d4bdab5SAdrian Hunter } 19869fbc61f8SKan Liang 19873a42f4c7SIan Rogers int perf_pmu__scan_file_at(const struct perf_pmu *pmu, int dirfd, const char *name, 19883a69672eSNamhyung Kim const char *fmt, ...) 19893a69672eSNamhyung Kim { 19903a69672eSNamhyung Kim va_list args; 19913a69672eSNamhyung Kim FILE *file; 19923a69672eSNamhyung Kim int ret = EOF; 19933a69672eSNamhyung Kim 19943a69672eSNamhyung Kim va_start(args, fmt); 19953a69672eSNamhyung Kim file = perf_pmu__open_file_at(pmu, dirfd, name); 19963a69672eSNamhyung Kim if (file) { 19973a69672eSNamhyung Kim ret = vfscanf(file, fmt, args); 19983a69672eSNamhyung Kim fclose(file); 19993a69672eSNamhyung Kim } 20003a69672eSNamhyung Kim va_end(args); 20013a69672eSNamhyung Kim return ret; 20023a69672eSNamhyung Kim } 20033a69672eSNamhyung Kim 20043a42f4c7SIan Rogers bool perf_pmu__file_exists(const struct perf_pmu *pmu, const char *name) 2005c2b6a896SGerman Gomez { 2006c2b6a896SGerman Gomez char path[PATH_MAX]; 2007c2b6a896SGerman Gomez 2008c2b6a896SGerman Gomez if (!perf_pmu__pathname_scnprintf(path, sizeof(path), pmu->name, name)) 2009c2b6a896SGerman Gomez return false; 2010c2b6a896SGerman Gomez 2011c2b6a896SGerman Gomez return file_available(path); 2012c2b6a896SGerman Gomez } 2013c2b6a896SGerman Gomez 20149fbc61f8SKan Liang static int perf_pmu__new_caps(struct list_head *list, char *name, char *value) 20159fbc61f8SKan Liang { 20169fbc61f8SKan Liang struct perf_pmu_caps *caps = zalloc(sizeof(*caps)); 20179fbc61f8SKan Liang 20189fbc61f8SKan Liang if (!caps) 20199fbc61f8SKan Liang return -ENOMEM; 20209fbc61f8SKan Liang 20219fbc61f8SKan Liang caps->name = strdup(name); 20229fbc61f8SKan Liang if (!caps->name) 20239fbc61f8SKan Liang goto free_caps; 20249fbc61f8SKan Liang caps->value = strndup(value, strlen(value) - 1); 20259fbc61f8SKan Liang if (!caps->value) 20269fbc61f8SKan Liang goto free_name; 20279fbc61f8SKan Liang list_add_tail(&caps->list, list); 20289fbc61f8SKan Liang return 0; 20299fbc61f8SKan Liang 20309fbc61f8SKan Liang free_name: 203157f14b5aSArnaldo Carvalho de Melo zfree(&caps->name); 20329fbc61f8SKan Liang free_caps: 20339fbc61f8SKan Liang free(caps); 20349fbc61f8SKan Liang 20359fbc61f8SKan Liang return -ENOMEM; 20369fbc61f8SKan Liang } 20379fbc61f8SKan Liang 2038eec11310SNamhyung Kim static void perf_pmu__del_caps(struct perf_pmu *pmu) 2039eec11310SNamhyung Kim { 2040eec11310SNamhyung Kim struct perf_pmu_caps *caps, *tmp; 2041eec11310SNamhyung Kim 2042eec11310SNamhyung Kim list_for_each_entry_safe(caps, tmp, &pmu->caps, list) { 2043eec11310SNamhyung Kim list_del(&caps->list); 2044efe98a7aSArnaldo Carvalho de Melo zfree(&caps->name); 2045efe98a7aSArnaldo Carvalho de Melo zfree(&caps->value); 2046eec11310SNamhyung Kim free(caps); 2047eec11310SNamhyung Kim } 2048eec11310SNamhyung Kim } 2049eec11310SNamhyung Kim 20509fbc61f8SKan Liang /* 20519fbc61f8SKan Liang * Reading/parsing the given pmu capabilities, which should be located at: 20529fbc61f8SKan Liang * /sys/bus/event_source/devices/<dev>/caps as sysfs group attributes. 20539fbc61f8SKan Liang * Return the number of capabilities 20549fbc61f8SKan Liang */ 20559fbc61f8SKan Liang int perf_pmu__caps_parse(struct perf_pmu *pmu) 20569fbc61f8SKan Liang { 20579fbc61f8SKan Liang struct stat st; 20589fbc61f8SKan Liang char caps_path[PATH_MAX]; 20599fbc61f8SKan Liang DIR *caps_dir; 20609fbc61f8SKan Liang struct dirent *evt_ent; 2061b39094d3SNamhyung Kim int caps_fd; 20623339ec44SRavi Bangoria 20633339ec44SRavi Bangoria if (pmu->caps_initialized) 20643339ec44SRavi Bangoria return pmu->nr_caps; 20653339ec44SRavi Bangoria 20663339ec44SRavi Bangoria pmu->nr_caps = 0; 20679fbc61f8SKan Liang 2068f8ad6018SJames Clark if (!perf_pmu__pathname_scnprintf(caps_path, sizeof(caps_path), pmu->name, "caps")) 20699fbc61f8SKan Liang return -1; 20709fbc61f8SKan Liang 20713339ec44SRavi Bangoria if (stat(caps_path, &st) < 0) { 20723339ec44SRavi Bangoria pmu->caps_initialized = true; 20739fbc61f8SKan Liang return 0; /* no error if caps does not exist */ 20743339ec44SRavi Bangoria } 20759fbc61f8SKan Liang 20769fbc61f8SKan Liang caps_dir = opendir(caps_path); 20779fbc61f8SKan Liang if (!caps_dir) 20789fbc61f8SKan Liang return -EINVAL; 20799fbc61f8SKan Liang 2080b39094d3SNamhyung Kim caps_fd = dirfd(caps_dir); 2081b39094d3SNamhyung Kim 20829fbc61f8SKan Liang while ((evt_ent = readdir(caps_dir)) != NULL) { 20839fbc61f8SKan Liang char *name = evt_ent->d_name; 20849fbc61f8SKan Liang char value[128]; 20859fbc61f8SKan Liang FILE *file; 2086b39094d3SNamhyung Kim int fd; 20879fbc61f8SKan Liang 20889fbc61f8SKan Liang if (!strcmp(name, ".") || !strcmp(name, "..")) 20899fbc61f8SKan Liang continue; 20909fbc61f8SKan Liang 2091b39094d3SNamhyung Kim fd = openat(caps_fd, name, O_RDONLY); 20920ea8920eSIan Rogers if (fd == -1) 20939fbc61f8SKan Liang continue; 20940ea8920eSIan Rogers file = fdopen(fd, "r"); 20950ea8920eSIan Rogers if (!file) { 20960ea8920eSIan Rogers close(fd); 20970ea8920eSIan Rogers continue; 20980ea8920eSIan Rogers } 20999fbc61f8SKan Liang 21009fbc61f8SKan Liang if (!fgets(value, sizeof(value), file) || 21019fbc61f8SKan Liang (perf_pmu__new_caps(&pmu->caps, name, value) < 0)) { 21029fbc61f8SKan Liang fclose(file); 21039fbc61f8SKan Liang continue; 21049fbc61f8SKan Liang } 21059fbc61f8SKan Liang 21063339ec44SRavi Bangoria pmu->nr_caps++; 21079fbc61f8SKan Liang fclose(file); 21089fbc61f8SKan Liang } 21099fbc61f8SKan Liang 21109fbc61f8SKan Liang closedir(caps_dir); 21119fbc61f8SKan Liang 21123339ec44SRavi Bangoria pmu->caps_initialized = true; 21133339ec44SRavi Bangoria return pmu->nr_caps; 21149fbc61f8SKan Liang } 2115e4064776SJin Yao 2116b9f01032SIan Rogers static void perf_pmu__compute_config_masks(struct perf_pmu *pmu) 2117e4064776SJin Yao { 2118e4064776SJin Yao struct perf_pmu_format *format; 2119b9f01032SIan Rogers 2120b9f01032SIan Rogers if (pmu->config_masks_computed) 2121b9f01032SIan Rogers return; 2122e4064776SJin Yao 2123e4064776SJin Yao list_for_each_entry(format, &pmu->format, list) { 2124b9f01032SIan Rogers unsigned int i; 2125b9f01032SIan Rogers __u64 *mask; 2126b9f01032SIan Rogers 2127b9f01032SIan Rogers if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) 2128e4064776SJin Yao continue; 2129e4064776SJin Yao 2130b9f01032SIan Rogers pmu->config_masks_present = true; 2131b9f01032SIan Rogers mask = &pmu->config_masks[format->value]; 2132b9f01032SIan Rogers 2133e4064776SJin Yao for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS) 2134b9f01032SIan Rogers *mask |= 1ULL << i; 2135e4064776SJin Yao } 2136b9f01032SIan Rogers pmu->config_masks_computed = true; 2137b9f01032SIan Rogers } 2138b9f01032SIan Rogers 2139b9f01032SIan Rogers void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 2140b9f01032SIan Rogers const char *name, int config_num, 2141b9f01032SIan Rogers const char *config_name) 2142b9f01032SIan Rogers { 2143b9f01032SIan Rogers __u64 bits; 2144b9f01032SIan Rogers char buf[100]; 2145b9f01032SIan Rogers 2146b9f01032SIan Rogers perf_pmu__compute_config_masks(pmu); 2147e4064776SJin Yao 2148e4064776SJin Yao /* 2149e4064776SJin Yao * Kernel doesn't export any valid format bits. 2150e4064776SJin Yao */ 2151b9f01032SIan Rogers if (!pmu->config_masks_present) 2152e4064776SJin Yao return; 2153e4064776SJin Yao 2154b9f01032SIan Rogers bits = config & ~pmu->config_masks[config_num]; 2155e4064776SJin Yao if (bits == 0) 2156e4064776SJin Yao return; 2157e4064776SJin Yao 2158e4064776SJin Yao bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf)); 2159e4064776SJin Yao 2160b9f01032SIan Rogers pr_warning("WARNING: event '%s' not valid (bits %s of %s " 2161e4064776SJin Yao "'%llx' not supported by kernel)!\n", 2162b9f01032SIan Rogers name ?: "N/A", buf, config_name, config); 2163e4064776SJin Yao } 2164c5a26ea4SJin Yao 2165f91fa2aeSIan Rogers bool perf_pmu__match(const struct perf_pmu *pmu, const char *tok) 2166c47a5599SJin Yao { 2167f91fa2aeSIan Rogers const char *name = pmu->name; 21683e0bf9fdSJames Clark bool need_fnmatch = strisglob(tok); 2169f91fa2aeSIan Rogers 2170f91fa2aeSIan Rogers if (!strncmp(tok, "uncore_", 7)) 2171f91fa2aeSIan Rogers tok += 7; 2172f91fa2aeSIan Rogers if (!strncmp(name, "uncore_", 7)) 2173f91fa2aeSIan Rogers name += 7; 2174f91fa2aeSIan Rogers 2175f91fa2aeSIan Rogers if (perf_pmu__match_ignoring_suffix(name, tok) || 2176f91fa2aeSIan Rogers (need_fnmatch && !fnmatch(tok, name, 0))) 2177f91fa2aeSIan Rogers return true; 2178f91fa2aeSIan Rogers 2179f91fa2aeSIan Rogers name = pmu->alias_name; 218013d60ba0SKan Liang if (!name) 2181f91fa2aeSIan Rogers return false; 218213d60ba0SKan Liang 2183f91fa2aeSIan Rogers if (!strncmp(name, "uncore_", 7)) 2184f91fa2aeSIan Rogers name += 7; 2185c47a5599SJin Yao 2186f91fa2aeSIan Rogers return perf_pmu__match_ignoring_suffix(name, tok) || 2187f91fa2aeSIan Rogers (need_fnmatch && !fnmatch(tok, name, 0)); 2188c47a5599SJin Yao } 21891d3351e6SJin Yao 2190acef233bSJing Zhang double __weak perf_pmu__cpu_slots_per_cycle(void) 2191acef233bSJing Zhang { 2192acef233bSJing Zhang return NAN; 2193acef233bSJing Zhang } 2194f8ad6018SJames Clark 2195f8ad6018SJames Clark int perf_pmu__event_source_devices_scnprintf(char *pathname, size_t size) 2196f8ad6018SJames Clark { 2197f8ad6018SJames Clark const char *sysfs = sysfs__mountpoint(); 2198f8ad6018SJames Clark 2199f8ad6018SJames Clark if (!sysfs) 2200f8ad6018SJames Clark return 0; 2201f8ad6018SJames Clark return scnprintf(pathname, size, "%s/bus/event_source/devices/", sysfs); 2202f8ad6018SJames Clark } 2203f8ad6018SJames Clark 2204e293a5e8SNamhyung Kim int perf_pmu__event_source_devices_fd(void) 2205e293a5e8SNamhyung Kim { 2206e293a5e8SNamhyung Kim char path[PATH_MAX]; 2207e293a5e8SNamhyung Kim const char *sysfs = sysfs__mountpoint(); 2208e293a5e8SNamhyung Kim 2209e293a5e8SNamhyung Kim if (!sysfs) 2210e293a5e8SNamhyung Kim return -1; 2211e293a5e8SNamhyung Kim 2212e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/bus/event_source/devices/", sysfs); 2213e293a5e8SNamhyung Kim return open(path, O_DIRECTORY); 2214e293a5e8SNamhyung Kim } 2215e293a5e8SNamhyung Kim 2216f8ad6018SJames Clark /* 2217f8ad6018SJames Clark * Fill 'buf' with the path to a file or folder in 'pmu_name' in 2218f8ad6018SJames Clark * sysfs. For example if pmu_name = "cs_etm" and 'filename' = "format" 2219f8ad6018SJames Clark * then pathname will be filled with 2220f8ad6018SJames Clark * "/sys/bus/event_source/devices/cs_etm/format" 2221f8ad6018SJames Clark * 2222e1a3aad3SIan Rogers * Return 0 if the sysfs mountpoint couldn't be found, if no characters were 2223e1a3aad3SIan Rogers * written or if the buffer size is exceeded. 2224f8ad6018SJames Clark */ 2225f8ad6018SJames Clark int perf_pmu__pathname_scnprintf(char *buf, size_t size, 2226f8ad6018SJames Clark const char *pmu_name, const char *filename) 2227f8ad6018SJames Clark { 2228e1a3aad3SIan Rogers size_t len; 2229f8ad6018SJames Clark 2230e1a3aad3SIan Rogers len = perf_pmu__event_source_devices_scnprintf(buf, size); 2231e1a3aad3SIan Rogers if (!len || (len + strlen(pmu_name) + strlen(filename) + 1) >= size) 2232f8ad6018SJames Clark return 0; 2233e1a3aad3SIan Rogers 2234e1a3aad3SIan Rogers return scnprintf(buf + len, size - len, "%s/%s", pmu_name, filename); 2235f8ad6018SJames Clark } 2236eec11310SNamhyung Kim 2237e293a5e8SNamhyung Kim int perf_pmu__pathname_fd(int dirfd, const char *pmu_name, const char *filename, int flags) 2238e293a5e8SNamhyung Kim { 2239e293a5e8SNamhyung Kim char path[PATH_MAX]; 2240e293a5e8SNamhyung Kim 2241e293a5e8SNamhyung Kim scnprintf(path, sizeof(path), "%s/%s", pmu_name, filename); 2242e293a5e8SNamhyung Kim return openat(dirfd, path, flags); 2243e293a5e8SNamhyung Kim } 2244e293a5e8SNamhyung Kim 22451eaf496eSIan Rogers void perf_pmu__delete(struct perf_pmu *pmu) 2246eec11310SNamhyung Kim { 2247eec11310SNamhyung Kim perf_pmu__del_formats(&pmu->format); 2248eec11310SNamhyung Kim perf_pmu__del_aliases(pmu); 2249eec11310SNamhyung Kim perf_pmu__del_caps(pmu); 2250eec11310SNamhyung Kim 2251eec11310SNamhyung Kim perf_cpu_map__put(pmu->cpus); 2252eec11310SNamhyung Kim 2253efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->name); 2254efe98a7aSArnaldo Carvalho de Melo zfree(&pmu->alias_name); 2255b7823045SIan Rogers zfree(&pmu->id); 2256eec11310SNamhyung Kim free(pmu); 2257eec11310SNamhyung Kim } 225867ee8e71SIan Rogers 225967ee8e71SIan Rogers const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config) 226067ee8e71SIan Rogers { 226167ee8e71SIan Rogers struct perf_pmu_alias *event; 226267ee8e71SIan Rogers 226367ee8e71SIan Rogers if (!pmu) 226467ee8e71SIan Rogers return NULL; 226567ee8e71SIan Rogers 22667b6dd7a9SIan Rogers pmu_aliases_parse(pmu); 226767ee8e71SIan Rogers pmu_add_cpu_aliases(pmu); 226867ee8e71SIan Rogers list_for_each_entry(event, &pmu->aliases, list) { 226967ee8e71SIan Rogers struct perf_event_attr attr = {.config = 0,}; 227067ee8e71SIan Rogers int ret = perf_pmu__config(pmu, &attr, &event->terms, NULL); 227167ee8e71SIan Rogers 227267ee8e71SIan Rogers if (ret == 0 && config == attr.config) 227367ee8e71SIan Rogers return event->name; 227467ee8e71SIan Rogers } 227567ee8e71SIan Rogers return NULL; 227667ee8e71SIan Rogers } 2277