1cd82a32eSJiri Olsa 2cd82a32eSJiri Olsa #include <linux/list.h> 3cd82a32eSJiri Olsa #include <sys/types.h> 4cd82a32eSJiri Olsa #include <sys/stat.h> 5cd82a32eSJiri Olsa #include <unistd.h> 6cd82a32eSJiri Olsa #include <stdio.h> 7cd82a32eSJiri Olsa #include <dirent.h> 8cd82a32eSJiri Olsa #include "sysfs.h" 9cd82a32eSJiri Olsa #include "util.h" 10cd82a32eSJiri Olsa #include "pmu.h" 11cd82a32eSJiri Olsa #include "parse-events.h" 127ae92e74SYan, Zheng #include "cpumap.h" 13cd82a32eSJiri Olsa 1450a9667cSRobert Richter #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" 1550a9667cSRobert Richter 16cd82a32eSJiri Olsa int perf_pmu_parse(struct list_head *list, char *name); 17cd82a32eSJiri Olsa extern FILE *perf_pmu_in; 18cd82a32eSJiri Olsa 19cd82a32eSJiri Olsa static LIST_HEAD(pmus); 20cd82a32eSJiri Olsa 21cd82a32eSJiri Olsa /* 22cd82a32eSJiri Olsa * Parse & process all the sysfs attributes located under 23cd82a32eSJiri Olsa * the directory specified in 'dir' parameter. 24cd82a32eSJiri Olsa */ 25cff7f956SJiri Olsa int perf_pmu__format_parse(char *dir, struct list_head *head) 26cd82a32eSJiri Olsa { 27cd82a32eSJiri Olsa struct dirent *evt_ent; 28cd82a32eSJiri Olsa DIR *format_dir; 29cd82a32eSJiri Olsa int ret = 0; 30cd82a32eSJiri Olsa 31cd82a32eSJiri Olsa format_dir = opendir(dir); 32cd82a32eSJiri Olsa if (!format_dir) 33cd82a32eSJiri Olsa return -EINVAL; 34cd82a32eSJiri Olsa 35cd82a32eSJiri Olsa while (!ret && (evt_ent = readdir(format_dir))) { 36cd82a32eSJiri Olsa char path[PATH_MAX]; 37cd82a32eSJiri Olsa char *name = evt_ent->d_name; 38cd82a32eSJiri Olsa FILE *file; 39cd82a32eSJiri Olsa 40cd82a32eSJiri Olsa if (!strcmp(name, ".") || !strcmp(name, "..")) 41cd82a32eSJiri Olsa continue; 42cd82a32eSJiri Olsa 43cd82a32eSJiri Olsa snprintf(path, PATH_MAX, "%s/%s", dir, name); 44cd82a32eSJiri Olsa 45cd82a32eSJiri Olsa ret = -EINVAL; 46cd82a32eSJiri Olsa file = fopen(path, "r"); 47cd82a32eSJiri Olsa if (!file) 48cd82a32eSJiri Olsa break; 49cd82a32eSJiri Olsa 50cd82a32eSJiri Olsa perf_pmu_in = file; 51cd82a32eSJiri Olsa ret = perf_pmu_parse(head, name); 52cd82a32eSJiri Olsa fclose(file); 53cd82a32eSJiri Olsa } 54cd82a32eSJiri Olsa 55cd82a32eSJiri Olsa closedir(format_dir); 56cd82a32eSJiri Olsa return ret; 57cd82a32eSJiri Olsa } 58cd82a32eSJiri Olsa 59cd82a32eSJiri Olsa /* 60cd82a32eSJiri Olsa * Reading/parsing the default pmu format definition, which should be 61cd82a32eSJiri Olsa * located at: 62cd82a32eSJiri Olsa * /sys/bus/event_source/devices/<dev>/format as sysfs group attributes. 63cd82a32eSJiri Olsa */ 64cd82a32eSJiri Olsa static int pmu_format(char *name, struct list_head *format) 65cd82a32eSJiri Olsa { 66cd82a32eSJiri Olsa struct stat st; 67cd82a32eSJiri Olsa char path[PATH_MAX]; 68cd82a32eSJiri Olsa const char *sysfs; 69cd82a32eSJiri Olsa 70cd82a32eSJiri Olsa sysfs = sysfs_find_mountpoint(); 71cd82a32eSJiri Olsa if (!sysfs) 72cd82a32eSJiri Olsa return -1; 73cd82a32eSJiri Olsa 74cd82a32eSJiri Olsa snprintf(path, PATH_MAX, 7550a9667cSRobert Richter "%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name); 76cd82a32eSJiri Olsa 77cd82a32eSJiri Olsa if (stat(path, &st) < 0) 789bc8f9feSRobert Richter return 0; /* no error if format does not exist */ 79cd82a32eSJiri Olsa 80cff7f956SJiri Olsa if (perf_pmu__format_parse(path, format)) 81cd82a32eSJiri Olsa return -1; 82cd82a32eSJiri Olsa 83cd82a32eSJiri Olsa return 0; 84cd82a32eSJiri Olsa } 85cd82a32eSJiri Olsa 86a6146d50SZheng Yan static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) 87a6146d50SZheng Yan { 88a6146d50SZheng Yan struct perf_pmu__alias *alias; 89a6146d50SZheng Yan char buf[256]; 90a6146d50SZheng Yan int ret; 91a6146d50SZheng Yan 92a6146d50SZheng Yan ret = fread(buf, 1, sizeof(buf), file); 93a6146d50SZheng Yan if (ret == 0) 94a6146d50SZheng Yan return -EINVAL; 95a6146d50SZheng Yan buf[ret] = 0; 96a6146d50SZheng Yan 97a6146d50SZheng Yan alias = malloc(sizeof(*alias)); 98a6146d50SZheng Yan if (!alias) 99a6146d50SZheng Yan return -ENOMEM; 100a6146d50SZheng Yan 101a6146d50SZheng Yan INIT_LIST_HEAD(&alias->terms); 102a6146d50SZheng Yan ret = parse_events_terms(&alias->terms, buf); 103a6146d50SZheng Yan if (ret) { 104a6146d50SZheng Yan free(alias); 105a6146d50SZheng Yan return ret; 106a6146d50SZheng Yan } 107a6146d50SZheng Yan 108a6146d50SZheng Yan alias->name = strdup(name); 109a6146d50SZheng Yan list_add_tail(&alias->list, list); 110a6146d50SZheng Yan return 0; 111a6146d50SZheng Yan } 112a6146d50SZheng Yan 113a6146d50SZheng Yan /* 114a6146d50SZheng Yan * Process all the sysfs attributes located under the directory 115a6146d50SZheng Yan * specified in 'dir' parameter. 116a6146d50SZheng Yan */ 117a6146d50SZheng Yan static int pmu_aliases_parse(char *dir, struct list_head *head) 118a6146d50SZheng Yan { 119a6146d50SZheng Yan struct dirent *evt_ent; 120a6146d50SZheng Yan DIR *event_dir; 121a6146d50SZheng Yan int ret = 0; 122a6146d50SZheng Yan 123a6146d50SZheng Yan event_dir = opendir(dir); 124a6146d50SZheng Yan if (!event_dir) 125a6146d50SZheng Yan return -EINVAL; 126a6146d50SZheng Yan 127a6146d50SZheng Yan while (!ret && (evt_ent = readdir(event_dir))) { 128a6146d50SZheng Yan char path[PATH_MAX]; 129a6146d50SZheng Yan char *name = evt_ent->d_name; 130a6146d50SZheng Yan FILE *file; 131a6146d50SZheng Yan 132a6146d50SZheng Yan if (!strcmp(name, ".") || !strcmp(name, "..")) 133a6146d50SZheng Yan continue; 134a6146d50SZheng Yan 135a6146d50SZheng Yan snprintf(path, PATH_MAX, "%s/%s", dir, name); 136a6146d50SZheng Yan 137a6146d50SZheng Yan ret = -EINVAL; 138a6146d50SZheng Yan file = fopen(path, "r"); 139a6146d50SZheng Yan if (!file) 140a6146d50SZheng Yan break; 141a6146d50SZheng Yan ret = perf_pmu__new_alias(head, name, file); 142a6146d50SZheng Yan fclose(file); 143a6146d50SZheng Yan } 144a6146d50SZheng Yan 145a6146d50SZheng Yan closedir(event_dir); 146a6146d50SZheng Yan return ret; 147a6146d50SZheng Yan } 148a6146d50SZheng Yan 149a6146d50SZheng Yan /* 150a6146d50SZheng Yan * Reading the pmu event aliases definition, which should be located at: 151a6146d50SZheng Yan * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. 152a6146d50SZheng Yan */ 153a6146d50SZheng Yan static int pmu_aliases(char *name, struct list_head *head) 154a6146d50SZheng Yan { 155a6146d50SZheng Yan struct stat st; 156a6146d50SZheng Yan char path[PATH_MAX]; 157a6146d50SZheng Yan const char *sysfs; 158a6146d50SZheng Yan 159a6146d50SZheng Yan sysfs = sysfs_find_mountpoint(); 160a6146d50SZheng Yan if (!sysfs) 161a6146d50SZheng Yan return -1; 162a6146d50SZheng Yan 163a6146d50SZheng Yan snprintf(path, PATH_MAX, 164a6146d50SZheng Yan "%s/bus/event_source/devices/%s/events", sysfs, name); 165a6146d50SZheng Yan 166a6146d50SZheng Yan if (stat(path, &st) < 0) 1673fded963SJiri Olsa return 0; /* no error if 'events' does not exist */ 168a6146d50SZheng Yan 169a6146d50SZheng Yan if (pmu_aliases_parse(path, head)) 170a6146d50SZheng Yan return -1; 171a6146d50SZheng Yan 172a6146d50SZheng Yan return 0; 173a6146d50SZheng Yan } 174a6146d50SZheng Yan 175a6146d50SZheng Yan static int pmu_alias_terms(struct perf_pmu__alias *alias, 176a6146d50SZheng Yan struct list_head *terms) 177a6146d50SZheng Yan { 178*6cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *clone; 179a6146d50SZheng Yan LIST_HEAD(list); 180a6146d50SZheng Yan int ret; 181a6146d50SZheng Yan 182a6146d50SZheng Yan list_for_each_entry(term, &alias->terms, list) { 183*6cee6cd3SArnaldo Carvalho de Melo ret = parse_events_term__clone(&clone, term); 184a6146d50SZheng Yan if (ret) { 185a6146d50SZheng Yan parse_events__free_terms(&list); 186a6146d50SZheng Yan return ret; 187a6146d50SZheng Yan } 188a6146d50SZheng Yan list_add_tail(&clone->list, &list); 189a6146d50SZheng Yan } 190a6146d50SZheng Yan list_splice(&list, terms); 191a6146d50SZheng Yan return 0; 192a6146d50SZheng Yan } 193a6146d50SZheng Yan 194cd82a32eSJiri Olsa /* 195cd82a32eSJiri Olsa * Reading/parsing the default pmu type value, which should be 196cd82a32eSJiri Olsa * located at: 197cd82a32eSJiri Olsa * /sys/bus/event_source/devices/<dev>/type as sysfs attribute. 198cd82a32eSJiri Olsa */ 199cd82a32eSJiri Olsa static int pmu_type(char *name, __u32 *type) 200cd82a32eSJiri Olsa { 201cd82a32eSJiri Olsa struct stat st; 202cd82a32eSJiri Olsa char path[PATH_MAX]; 203cd82a32eSJiri Olsa const char *sysfs; 204cd82a32eSJiri Olsa FILE *file; 205cd82a32eSJiri Olsa int ret = 0; 206cd82a32eSJiri Olsa 207cd82a32eSJiri Olsa sysfs = sysfs_find_mountpoint(); 208cd82a32eSJiri Olsa if (!sysfs) 209cd82a32eSJiri Olsa return -1; 210cd82a32eSJiri Olsa 211cd82a32eSJiri Olsa snprintf(path, PATH_MAX, 21250a9667cSRobert Richter "%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name); 213cd82a32eSJiri Olsa 214cd82a32eSJiri Olsa if (stat(path, &st) < 0) 215cd82a32eSJiri Olsa return -1; 216cd82a32eSJiri Olsa 217cd82a32eSJiri Olsa file = fopen(path, "r"); 218cd82a32eSJiri Olsa if (!file) 219cd82a32eSJiri Olsa return -EINVAL; 220cd82a32eSJiri Olsa 221cd82a32eSJiri Olsa if (1 != fscanf(file, "%u", type)) 222cd82a32eSJiri Olsa ret = -1; 223cd82a32eSJiri Olsa 224cd82a32eSJiri Olsa fclose(file); 225cd82a32eSJiri Olsa return ret; 226cd82a32eSJiri Olsa } 227cd82a32eSJiri Olsa 22850a9667cSRobert Richter /* Add all pmus in sysfs to pmu list: */ 22950a9667cSRobert Richter static void pmu_read_sysfs(void) 23050a9667cSRobert Richter { 23150a9667cSRobert Richter char path[PATH_MAX]; 23250a9667cSRobert Richter const char *sysfs; 23350a9667cSRobert Richter DIR *dir; 23450a9667cSRobert Richter struct dirent *dent; 23550a9667cSRobert Richter 23650a9667cSRobert Richter sysfs = sysfs_find_mountpoint(); 23750a9667cSRobert Richter if (!sysfs) 23850a9667cSRobert Richter return; 23950a9667cSRobert Richter 24050a9667cSRobert Richter snprintf(path, PATH_MAX, 24150a9667cSRobert Richter "%s" EVENT_SOURCE_DEVICE_PATH, sysfs); 24250a9667cSRobert Richter 24350a9667cSRobert Richter dir = opendir(path); 24450a9667cSRobert Richter if (!dir) 24550a9667cSRobert Richter return; 24650a9667cSRobert Richter 24750a9667cSRobert Richter while ((dent = readdir(dir))) { 24850a9667cSRobert Richter if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) 24950a9667cSRobert Richter continue; 25050a9667cSRobert Richter /* add to static LIST_HEAD(pmus): */ 25150a9667cSRobert Richter perf_pmu__find(dent->d_name); 25250a9667cSRobert Richter } 25350a9667cSRobert Richter 25450a9667cSRobert Richter closedir(dir); 25550a9667cSRobert Richter } 25650a9667cSRobert Richter 2577ae92e74SYan, Zheng static struct cpu_map *pmu_cpumask(char *name) 2587ae92e74SYan, Zheng { 2597ae92e74SYan, Zheng struct stat st; 2607ae92e74SYan, Zheng char path[PATH_MAX]; 2617ae92e74SYan, Zheng const char *sysfs; 2627ae92e74SYan, Zheng FILE *file; 2637ae92e74SYan, Zheng struct cpu_map *cpus; 2647ae92e74SYan, Zheng 2657ae92e74SYan, Zheng sysfs = sysfs_find_mountpoint(); 2667ae92e74SYan, Zheng if (!sysfs) 2677ae92e74SYan, Zheng return NULL; 2687ae92e74SYan, Zheng 2697ae92e74SYan, Zheng snprintf(path, PATH_MAX, 2707ae92e74SYan, Zheng "%s/bus/event_source/devices/%s/cpumask", sysfs, name); 2717ae92e74SYan, Zheng 2727ae92e74SYan, Zheng if (stat(path, &st) < 0) 2737ae92e74SYan, Zheng return NULL; 2747ae92e74SYan, Zheng 2757ae92e74SYan, Zheng file = fopen(path, "r"); 2767ae92e74SYan, Zheng if (!file) 2777ae92e74SYan, Zheng return NULL; 2787ae92e74SYan, Zheng 2797ae92e74SYan, Zheng cpus = cpu_map__read(file); 2807ae92e74SYan, Zheng fclose(file); 2817ae92e74SYan, Zheng return cpus; 2827ae92e74SYan, Zheng } 2837ae92e74SYan, Zheng 284cd82a32eSJiri Olsa static struct perf_pmu *pmu_lookup(char *name) 285cd82a32eSJiri Olsa { 286cd82a32eSJiri Olsa struct perf_pmu *pmu; 287cd82a32eSJiri Olsa LIST_HEAD(format); 288a6146d50SZheng Yan LIST_HEAD(aliases); 289cd82a32eSJiri Olsa __u32 type; 290cd82a32eSJiri Olsa 291cd82a32eSJiri Olsa /* 292cd82a32eSJiri Olsa * The pmu data we store & need consists of the pmu 293cd82a32eSJiri Olsa * type value and format definitions. Load both right 294cd82a32eSJiri Olsa * now. 295cd82a32eSJiri Olsa */ 296cd82a32eSJiri Olsa if (pmu_format(name, &format)) 297cd82a32eSJiri Olsa return NULL; 298cd82a32eSJiri Olsa 2993fded963SJiri Olsa if (pmu_aliases(name, &aliases)) 3003fded963SJiri Olsa return NULL; 3013fded963SJiri Olsa 302cd82a32eSJiri Olsa if (pmu_type(name, &type)) 303cd82a32eSJiri Olsa return NULL; 304cd82a32eSJiri Olsa 305cd82a32eSJiri Olsa pmu = zalloc(sizeof(*pmu)); 306cd82a32eSJiri Olsa if (!pmu) 307cd82a32eSJiri Olsa return NULL; 308cd82a32eSJiri Olsa 3097ae92e74SYan, Zheng pmu->cpus = pmu_cpumask(name); 3107ae92e74SYan, Zheng 311cd82a32eSJiri Olsa INIT_LIST_HEAD(&pmu->format); 312a6146d50SZheng Yan INIT_LIST_HEAD(&pmu->aliases); 313cd82a32eSJiri Olsa list_splice(&format, &pmu->format); 314a6146d50SZheng Yan list_splice(&aliases, &pmu->aliases); 315cd82a32eSJiri Olsa pmu->name = strdup(name); 316cd82a32eSJiri Olsa pmu->type = type; 3179bc8f9feSRobert Richter list_add_tail(&pmu->list, &pmus); 318cd82a32eSJiri Olsa return pmu; 319cd82a32eSJiri Olsa } 320cd82a32eSJiri Olsa 321cd82a32eSJiri Olsa static struct perf_pmu *pmu_find(char *name) 322cd82a32eSJiri Olsa { 323cd82a32eSJiri Olsa struct perf_pmu *pmu; 324cd82a32eSJiri Olsa 325cd82a32eSJiri Olsa list_for_each_entry(pmu, &pmus, list) 326cd82a32eSJiri Olsa if (!strcmp(pmu->name, name)) 327cd82a32eSJiri Olsa return pmu; 328cd82a32eSJiri Olsa 329cd82a32eSJiri Olsa return NULL; 330cd82a32eSJiri Olsa } 331cd82a32eSJiri Olsa 33250a9667cSRobert Richter struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) 33350a9667cSRobert Richter { 33450a9667cSRobert Richter /* 33550a9667cSRobert Richter * pmu iterator: If pmu is NULL, we start at the begin, 33650a9667cSRobert Richter * otherwise return the next pmu. Returns NULL on end. 33750a9667cSRobert Richter */ 33850a9667cSRobert Richter if (!pmu) { 33950a9667cSRobert Richter pmu_read_sysfs(); 34050a9667cSRobert Richter pmu = list_prepare_entry(pmu, &pmus, list); 34150a9667cSRobert Richter } 34250a9667cSRobert Richter list_for_each_entry_continue(pmu, &pmus, list) 34350a9667cSRobert Richter return pmu; 34450a9667cSRobert Richter return NULL; 34550a9667cSRobert Richter } 34650a9667cSRobert Richter 347cd82a32eSJiri Olsa struct perf_pmu *perf_pmu__find(char *name) 348cd82a32eSJiri Olsa { 349cd82a32eSJiri Olsa struct perf_pmu *pmu; 350cd82a32eSJiri Olsa 351cd82a32eSJiri Olsa /* 352cd82a32eSJiri Olsa * Once PMU is loaded it stays in the list, 353cd82a32eSJiri Olsa * so we keep us from multiple reading/parsing 354cd82a32eSJiri Olsa * the pmu format definitions. 355cd82a32eSJiri Olsa */ 356cd82a32eSJiri Olsa pmu = pmu_find(name); 357cd82a32eSJiri Olsa if (pmu) 358cd82a32eSJiri Olsa return pmu; 359cd82a32eSJiri Olsa 360cd82a32eSJiri Olsa return pmu_lookup(name); 361cd82a32eSJiri Olsa } 362cd82a32eSJiri Olsa 363cd82a32eSJiri Olsa static struct perf_pmu__format* 364cd82a32eSJiri Olsa pmu_find_format(struct list_head *formats, char *name) 365cd82a32eSJiri Olsa { 366cd82a32eSJiri Olsa struct perf_pmu__format *format; 367cd82a32eSJiri Olsa 368cd82a32eSJiri Olsa list_for_each_entry(format, formats, list) 369cd82a32eSJiri Olsa if (!strcmp(format->name, name)) 370cd82a32eSJiri Olsa return format; 371cd82a32eSJiri Olsa 372cd82a32eSJiri Olsa return NULL; 373cd82a32eSJiri Olsa } 374cd82a32eSJiri Olsa 375cd82a32eSJiri Olsa /* 376cd82a32eSJiri Olsa * Returns value based on the format definition (format parameter) 377cd82a32eSJiri Olsa * and unformated value (value parameter). 378cd82a32eSJiri Olsa * 379cd82a32eSJiri Olsa * TODO maybe optimize a little ;) 380cd82a32eSJiri Olsa */ 381cd82a32eSJiri Olsa static __u64 pmu_format_value(unsigned long *format, __u64 value) 382cd82a32eSJiri Olsa { 383cd82a32eSJiri Olsa unsigned long fbit, vbit; 384cd82a32eSJiri Olsa __u64 v = 0; 385cd82a32eSJiri Olsa 386cd82a32eSJiri Olsa for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 387cd82a32eSJiri Olsa 388cd82a32eSJiri Olsa if (!test_bit(fbit, format)) 389cd82a32eSJiri Olsa continue; 390cd82a32eSJiri Olsa 391cd82a32eSJiri Olsa if (!(value & (1llu << vbit++))) 392cd82a32eSJiri Olsa continue; 393cd82a32eSJiri Olsa 394cd82a32eSJiri Olsa v |= (1llu << fbit); 395cd82a32eSJiri Olsa } 396cd82a32eSJiri Olsa 397cd82a32eSJiri Olsa return v; 398cd82a32eSJiri Olsa } 399cd82a32eSJiri Olsa 400cd82a32eSJiri Olsa /* 401cd82a32eSJiri Olsa * Setup one of config[12] attr members based on the 402cd82a32eSJiri Olsa * user input data - temr parameter. 403cd82a32eSJiri Olsa */ 404cd82a32eSJiri Olsa static int pmu_config_term(struct list_head *formats, 405cd82a32eSJiri Olsa struct perf_event_attr *attr, 406*6cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 407cd82a32eSJiri Olsa { 408cd82a32eSJiri Olsa struct perf_pmu__format *format; 409cd82a32eSJiri Olsa __u64 *vp; 410cd82a32eSJiri Olsa 411cd82a32eSJiri Olsa /* 412cd82a32eSJiri Olsa * Support only for hardcoded and numnerial terms. 413cd82a32eSJiri Olsa * Hardcoded terms should be already in, so nothing 414cd82a32eSJiri Olsa * to be done for them. 415cd82a32eSJiri Olsa */ 416cd82a32eSJiri Olsa if (parse_events__is_hardcoded_term(term)) 417cd82a32eSJiri Olsa return 0; 418cd82a32eSJiri Olsa 41916fa7e82SJiri Olsa if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) 420cd82a32eSJiri Olsa return -EINVAL; 421cd82a32eSJiri Olsa 422cd82a32eSJiri Olsa format = pmu_find_format(formats, term->config); 423cd82a32eSJiri Olsa if (!format) 424cd82a32eSJiri Olsa return -EINVAL; 425cd82a32eSJiri Olsa 426cd82a32eSJiri Olsa switch (format->value) { 427cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG: 428cd82a32eSJiri Olsa vp = &attr->config; 429cd82a32eSJiri Olsa break; 430cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG1: 431cd82a32eSJiri Olsa vp = &attr->config1; 432cd82a32eSJiri Olsa break; 433cd82a32eSJiri Olsa case PERF_PMU_FORMAT_VALUE_CONFIG2: 434cd82a32eSJiri Olsa vp = &attr->config2; 435cd82a32eSJiri Olsa break; 436cd82a32eSJiri Olsa default: 437cd82a32eSJiri Olsa return -EINVAL; 438cd82a32eSJiri Olsa } 439cd82a32eSJiri Olsa 44016fa7e82SJiri Olsa /* 44116fa7e82SJiri Olsa * XXX If we ever decide to go with string values for 44216fa7e82SJiri Olsa * non-hardcoded terms, here's the place to translate 44316fa7e82SJiri Olsa * them into value. 44416fa7e82SJiri Olsa */ 445cd82a32eSJiri Olsa *vp |= pmu_format_value(format->bits, term->val.num); 446cd82a32eSJiri Olsa return 0; 447cd82a32eSJiri Olsa } 448cd82a32eSJiri Olsa 449cff7f956SJiri Olsa int perf_pmu__config_terms(struct list_head *formats, 450cff7f956SJiri Olsa struct perf_event_attr *attr, 451cd82a32eSJiri Olsa struct list_head *head_terms) 452cd82a32eSJiri Olsa { 453*6cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 454cd82a32eSJiri Olsa 4556b5fc39bSJiri Olsa list_for_each_entry(term, head_terms, list) 456cd82a32eSJiri Olsa if (pmu_config_term(formats, attr, term)) 457cd82a32eSJiri Olsa return -EINVAL; 458cd82a32eSJiri Olsa 459cd82a32eSJiri Olsa return 0; 460cd82a32eSJiri Olsa } 461cd82a32eSJiri Olsa 462cd82a32eSJiri Olsa /* 463cd82a32eSJiri Olsa * Configures event's 'attr' parameter based on the: 464cd82a32eSJiri Olsa * 1) users input - specified in terms parameter 465cd82a32eSJiri Olsa * 2) pmu format definitions - specified by pmu parameter 466cd82a32eSJiri Olsa */ 467cd82a32eSJiri Olsa int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 468cd82a32eSJiri Olsa struct list_head *head_terms) 469cd82a32eSJiri Olsa { 470cd82a32eSJiri Olsa attr->type = pmu->type; 471cff7f956SJiri Olsa return perf_pmu__config_terms(&pmu->format, attr, head_terms); 472cd82a32eSJiri Olsa } 473cd82a32eSJiri Olsa 474a6146d50SZheng Yan static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu, 475*6cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 476a6146d50SZheng Yan { 477a6146d50SZheng Yan struct perf_pmu__alias *alias; 478a6146d50SZheng Yan char *name; 479a6146d50SZheng Yan 480a6146d50SZheng Yan if (parse_events__is_hardcoded_term(term)) 481a6146d50SZheng Yan return NULL; 482a6146d50SZheng Yan 483a6146d50SZheng Yan if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) { 484a6146d50SZheng Yan if (term->val.num != 1) 485a6146d50SZheng Yan return NULL; 486a6146d50SZheng Yan if (pmu_find_format(&pmu->format, term->config)) 487a6146d50SZheng Yan return NULL; 488a6146d50SZheng Yan name = term->config; 489a6146d50SZheng Yan } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) { 490a6146d50SZheng Yan if (strcasecmp(term->config, "event")) 491a6146d50SZheng Yan return NULL; 492a6146d50SZheng Yan name = term->val.str; 493a6146d50SZheng Yan } else { 494a6146d50SZheng Yan return NULL; 495a6146d50SZheng Yan } 496a6146d50SZheng Yan 497a6146d50SZheng Yan list_for_each_entry(alias, &pmu->aliases, list) { 498a6146d50SZheng Yan if (!strcasecmp(alias->name, name)) 499a6146d50SZheng Yan return alias; 500a6146d50SZheng Yan } 501a6146d50SZheng Yan return NULL; 502a6146d50SZheng Yan } 503a6146d50SZheng Yan 504a6146d50SZheng Yan /* 505a6146d50SZheng Yan * Find alias in the terms list and replace it with the terms 506a6146d50SZheng Yan * defined for the alias 507a6146d50SZheng Yan */ 508a6146d50SZheng Yan int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) 509a6146d50SZheng Yan { 510*6cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 511a6146d50SZheng Yan struct perf_pmu__alias *alias; 512a6146d50SZheng Yan int ret; 513a6146d50SZheng Yan 514a6146d50SZheng Yan list_for_each_entry_safe(term, h, head_terms, list) { 515a6146d50SZheng Yan alias = pmu_find_alias(pmu, term); 516a6146d50SZheng Yan if (!alias) 517a6146d50SZheng Yan continue; 518a6146d50SZheng Yan ret = pmu_alias_terms(alias, &term->list); 519a6146d50SZheng Yan if (ret) 520a6146d50SZheng Yan return ret; 521a6146d50SZheng Yan list_del(&term->list); 522a6146d50SZheng Yan free(term); 523a6146d50SZheng Yan } 524a6146d50SZheng Yan return 0; 525a6146d50SZheng Yan } 526a6146d50SZheng Yan 527cd82a32eSJiri Olsa int perf_pmu__new_format(struct list_head *list, char *name, 528cd82a32eSJiri Olsa int config, unsigned long *bits) 529cd82a32eSJiri Olsa { 530cd82a32eSJiri Olsa struct perf_pmu__format *format; 531cd82a32eSJiri Olsa 532cd82a32eSJiri Olsa format = zalloc(sizeof(*format)); 533cd82a32eSJiri Olsa if (!format) 534cd82a32eSJiri Olsa return -ENOMEM; 535cd82a32eSJiri Olsa 536cd82a32eSJiri Olsa format->name = strdup(name); 537cd82a32eSJiri Olsa format->value = config; 538cd82a32eSJiri Olsa memcpy(format->bits, bits, sizeof(format->bits)); 539cd82a32eSJiri Olsa 540cd82a32eSJiri Olsa list_add_tail(&format->list, list); 541cd82a32eSJiri Olsa return 0; 542cd82a32eSJiri Olsa } 543cd82a32eSJiri Olsa 544cd82a32eSJiri Olsa void perf_pmu__set_format(unsigned long *bits, long from, long to) 545cd82a32eSJiri Olsa { 546cd82a32eSJiri Olsa long b; 547cd82a32eSJiri Olsa 548cd82a32eSJiri Olsa if (!to) 549cd82a32eSJiri Olsa to = from; 550cd82a32eSJiri Olsa 55115268138SSukadev Bhattiprolu memset(bits, 0, BITS_TO_BYTES(PERF_PMU_FORMAT_BITS)); 552cd82a32eSJiri Olsa for (b = from; b <= to; b++) 553cd82a32eSJiri Olsa set_bit(b, bits); 554cd82a32eSJiri Olsa } 555