1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2d2709c7cSDavid Howells #include <linux/hw_breakpoint.h> 38dd2a131SJiri Olsa #include <linux/err.h> 47f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h> 576b31a29SArnaldo Carvalho de Melo #include <dirent.h> 6a43783aeSArnaldo Carvalho de Melo #include <errno.h> 786a5e0c2SArnaldo Carvalho de Melo #include <sys/ioctl.h> 8bafae98eSArnaldo Carvalho de Melo #include <sys/types.h> 9bafae98eSArnaldo Carvalho de Melo #include <sys/stat.h> 10bafae98eSArnaldo Carvalho de Melo #include <fcntl.h> 11391e4206SArnaldo Carvalho de Melo #include <sys/param.h> 12b0742e90SArnaldo Carvalho de Melo #include "term.h" 134a3cec84SArnaldo Carvalho de Melo #include "build-id.h" 14361c99a6SArnaldo Carvalho de Melo #include "evlist.h" 1569aad6f1SArnaldo Carvalho de Melo #include "evsel.h" 16fa0d9846SArnaldo Carvalho de Melo #include <subcmd/pager.h> 174b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 1886470930SIngo Molnar #include "parse-events.h" 194b6ab94eSJosh Poimboeuf #include <subcmd/exec-cmd.h> 20a067558eSArnaldo Carvalho de Melo #include "string2.h" 218ec20b17SArnaldo Carvalho de Melo #include "strlist.h" 2284c86ca1SWang Nan #include "bpf-loader.h" 236e81c74cSMasami Hiramatsu #include "debug.h" 24592d5a6bSJiri Olsa #include <api/fs/tracing_path.h> 259c3516d1SJiri Olsa #include <perf/cpumap.h> 26ac20de6fSZheng Yan #include "parse-events-bison.h" 271244a327SJiri Olsa #define YY_EXTRA_TYPE void* 2889812fc8SJiri Olsa #include "parse-events-flex.h" 295f537a26SJiri Olsa #include "pmu.h" 30b41f1cecSNamhyung Kim #include "thread_map.h" 3140218daeSMasami Hiramatsu #include "probe-file.h" 32b39b8393SJiri Olsa #include "asm/bug.h" 33ac12f676SAndi Kleen #include "util/parse-branch-options.h" 3471b0acceSAndi Kleen #include "metricgroup.h" 3595be9d19SArnaldo Carvalho de Melo #include "util/evsel_config.h" 36252a2fdcSArnaldo Carvalho de Melo #include "util/event.h" 3770943490SStephane Eranian #include "util/pfm.h" 389cbfa2f6SJin Yao #include "util/parse-events-hybrid.h" 395e4edd1fSJin Yao #include "util/pmu-hybrid.h" 40943b69acSJin Yao #include "perf.h" 4189812fc8SJiri Olsa 4289812fc8SJiri Olsa #define MAX_NAME_LEN 100 4386470930SIngo Molnar 4482ba1f2fSJiri Olsa #ifdef PARSER_DEBUG 4582ba1f2fSJiri Olsa extern int parse_events_debug; 4682ba1f2fSJiri Olsa #endif 475d9cdc11SArnaldo Carvalho de Melo int parse_events_parse(void *parse_state, void *scanner); 48e637d177SHe Kuang static int get_config_terms(struct list_head *head_config, 49e637d177SHe Kuang struct list_head *head_terms __maybe_unused); 505e4edd1fSJin Yao static int parse_events__with_hybrid_pmu(struct parse_events_state *parse_state, 515e4edd1fSJin Yao const char *str, char *pmu_name, 525e4edd1fSJin Yao struct list_head *list); 53bcd3279fSFrederic Weisbecker 54dcb4e102SKan Liang static struct perf_pmu_event_symbol *perf_pmu_events_list; 55dcb4e102SKan Liang /* 56dcb4e102SKan Liang * The variable indicates the number of supported pmu event symbols. 57dcb4e102SKan Liang * 0 means not initialized and ready to init 58dcb4e102SKan Liang * -1 means failed to init, don't try anymore 59dcb4e102SKan Liang * >0 is the number of supported pmu event symbols 60dcb4e102SKan Liang */ 61dcb4e102SKan Liang static int perf_pmu_events_list_num; 62dcb4e102SKan Liang 63705750f2SYunlong Song struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 641dc12760SJiri Olsa [PERF_COUNT_HW_CPU_CYCLES] = { 651dc12760SJiri Olsa .symbol = "cpu-cycles", 661dc12760SJiri Olsa .alias = "cycles", 671dc12760SJiri Olsa }, 681dc12760SJiri Olsa [PERF_COUNT_HW_INSTRUCTIONS] = { 691dc12760SJiri Olsa .symbol = "instructions", 701dc12760SJiri Olsa .alias = "", 711dc12760SJiri Olsa }, 721dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_REFERENCES] = { 731dc12760SJiri Olsa .symbol = "cache-references", 741dc12760SJiri Olsa .alias = "", 751dc12760SJiri Olsa }, 761dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_MISSES] = { 771dc12760SJiri Olsa .symbol = "cache-misses", 781dc12760SJiri Olsa .alias = "", 791dc12760SJiri Olsa }, 801dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 811dc12760SJiri Olsa .symbol = "branch-instructions", 821dc12760SJiri Olsa .alias = "branches", 831dc12760SJiri Olsa }, 841dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_MISSES] = { 851dc12760SJiri Olsa .symbol = "branch-misses", 861dc12760SJiri Olsa .alias = "", 871dc12760SJiri Olsa }, 881dc12760SJiri Olsa [PERF_COUNT_HW_BUS_CYCLES] = { 891dc12760SJiri Olsa .symbol = "bus-cycles", 901dc12760SJiri Olsa .alias = "", 911dc12760SJiri Olsa }, 921dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = { 931dc12760SJiri Olsa .symbol = "stalled-cycles-frontend", 941dc12760SJiri Olsa .alias = "idle-cycles-frontend", 951dc12760SJiri Olsa }, 961dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = { 971dc12760SJiri Olsa .symbol = "stalled-cycles-backend", 981dc12760SJiri Olsa .alias = "idle-cycles-backend", 991dc12760SJiri Olsa }, 1001dc12760SJiri Olsa [PERF_COUNT_HW_REF_CPU_CYCLES] = { 1011dc12760SJiri Olsa .symbol = "ref-cycles", 1021dc12760SJiri Olsa .alias = "", 1031dc12760SJiri Olsa }, 1041dc12760SJiri Olsa }; 10586470930SIngo Molnar 106705750f2SYunlong Song struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { 1071dc12760SJiri Olsa [PERF_COUNT_SW_CPU_CLOCK] = { 1081dc12760SJiri Olsa .symbol = "cpu-clock", 1091dc12760SJiri Olsa .alias = "", 1101dc12760SJiri Olsa }, 1111dc12760SJiri Olsa [PERF_COUNT_SW_TASK_CLOCK] = { 1121dc12760SJiri Olsa .symbol = "task-clock", 1131dc12760SJiri Olsa .alias = "", 1141dc12760SJiri Olsa }, 1151dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS] = { 1161dc12760SJiri Olsa .symbol = "page-faults", 1171dc12760SJiri Olsa .alias = "faults", 1181dc12760SJiri Olsa }, 1191dc12760SJiri Olsa [PERF_COUNT_SW_CONTEXT_SWITCHES] = { 1201dc12760SJiri Olsa .symbol = "context-switches", 1211dc12760SJiri Olsa .alias = "cs", 1221dc12760SJiri Olsa }, 1231dc12760SJiri Olsa [PERF_COUNT_SW_CPU_MIGRATIONS] = { 1241dc12760SJiri Olsa .symbol = "cpu-migrations", 1251dc12760SJiri Olsa .alias = "migrations", 1261dc12760SJiri Olsa }, 1271dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MIN] = { 1281dc12760SJiri Olsa .symbol = "minor-faults", 1291dc12760SJiri Olsa .alias = "", 1301dc12760SJiri Olsa }, 1311dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = { 1321dc12760SJiri Olsa .symbol = "major-faults", 1331dc12760SJiri Olsa .alias = "", 1341dc12760SJiri Olsa }, 1351dc12760SJiri Olsa [PERF_COUNT_SW_ALIGNMENT_FAULTS] = { 1361dc12760SJiri Olsa .symbol = "alignment-faults", 1371dc12760SJiri Olsa .alias = "", 1381dc12760SJiri Olsa }, 1391dc12760SJiri Olsa [PERF_COUNT_SW_EMULATION_FAULTS] = { 1401dc12760SJiri Olsa .symbol = "emulation-faults", 1411dc12760SJiri Olsa .alias = "", 1421dc12760SJiri Olsa }, 143d22d1a2aSAdrian Hunter [PERF_COUNT_SW_DUMMY] = { 144d22d1a2aSAdrian Hunter .symbol = "dummy", 145d22d1a2aSAdrian Hunter .alias = "", 146d22d1a2aSAdrian Hunter }, 147bae9cc41SArnaldo Carvalho de Melo [PERF_COUNT_SW_BPF_OUTPUT] = { 148bae9cc41SArnaldo Carvalho de Melo .symbol = "bpf-output", 149bae9cc41SArnaldo Carvalho de Melo .alias = "", 150bae9cc41SArnaldo Carvalho de Melo }, 151fb6c79d7SNamhyung Kim [PERF_COUNT_SW_CGROUP_SWITCHES] = { 152fb6c79d7SNamhyung Kim .symbol = "cgroup-switches", 153fb6c79d7SNamhyung Kim .alias = "", 154fb6c79d7SNamhyung Kim }, 15586470930SIngo Molnar }; 15686470930SIngo Molnar 157cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \ 158cdd6c482SIngo Molnar ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 15986470930SIngo Molnar 160cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 161cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 162cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 163cdd6c482SIngo Molnar #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 16486470930SIngo Molnar 16522a9f41bSArnaldo Carvalho de Melo #define for_each_subsystem(sys_dir, sys_dirent) \ 16622a9f41bSArnaldo Carvalho de Melo while ((sys_dirent = readdir(sys_dir)) != NULL) \ 16722a9f41bSArnaldo Carvalho de Melo if (sys_dirent->d_type == DT_DIR && \ 16822a9f41bSArnaldo Carvalho de Melo (strcmp(sys_dirent->d_name, ".")) && \ 16922a9f41bSArnaldo Carvalho de Melo (strcmp(sys_dirent->d_name, ".."))) 170f6bdafefSJason Baron 171c02cab22SArnaldo Carvalho de Melo static int tp_event_has_id(const char *dir_path, struct dirent *evt_dir) 172ae07b63fSPeter Zijlstra { 173ae07b63fSPeter Zijlstra char evt_path[MAXPATHLEN]; 174ae07b63fSPeter Zijlstra int fd; 175ae07b63fSPeter Zijlstra 176c02cab22SArnaldo Carvalho de Melo snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dir->d_name); 177ae07b63fSPeter Zijlstra fd = open(evt_path, O_RDONLY); 178ae07b63fSPeter Zijlstra if (fd < 0) 179ae07b63fSPeter Zijlstra return -EINVAL; 180ae07b63fSPeter Zijlstra close(fd); 181ae07b63fSPeter Zijlstra 182ae07b63fSPeter Zijlstra return 0; 183ae07b63fSPeter Zijlstra } 184ae07b63fSPeter Zijlstra 185c02cab22SArnaldo Carvalho de Melo #define for_each_event(dir_path, evt_dir, evt_dirent) \ 18622a9f41bSArnaldo Carvalho de Melo while ((evt_dirent = readdir(evt_dir)) != NULL) \ 18722a9f41bSArnaldo Carvalho de Melo if (evt_dirent->d_type == DT_DIR && \ 18822a9f41bSArnaldo Carvalho de Melo (strcmp(evt_dirent->d_name, ".")) && \ 18922a9f41bSArnaldo Carvalho de Melo (strcmp(evt_dirent->d_name, "..")) && \ 190c02cab22SArnaldo Carvalho de Melo (!tp_event_has_id(dir_path, evt_dirent))) 191f6bdafefSJason Baron 192270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512 193f6bdafefSJason Baron 1941ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config) 195f6bdafefSJason Baron { 1961ef2ed10SFrederic Weisbecker struct tracepoint_path *path = NULL; 197f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 19822a9f41bSArnaldo Carvalho de Melo struct dirent *sys_dirent, *evt_dirent; 1998aa8a7c8SStephane Eranian char id_buf[24]; 200725b1368SEric Dumazet int fd; 201f6bdafefSJason Baron u64 id; 202f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 20325a7d914SArnaldo Carvalho de Melo char *dir_path; 204f6bdafefSJason Baron 2057014e0e3SArnaldo Carvalho de Melo sys_dir = tracing_events__opendir(); 206f6bdafefSJason Baron if (!sys_dir) 207725b1368SEric Dumazet return NULL; 208f6bdafefSJason Baron 20922a9f41bSArnaldo Carvalho de Melo for_each_subsystem(sys_dir, sys_dirent) { 21025a7d914SArnaldo Carvalho de Melo dir_path = get_events_file(sys_dirent->d_name); 21125a7d914SArnaldo Carvalho de Melo if (!dir_path) 21225a7d914SArnaldo Carvalho de Melo continue; 213725b1368SEric Dumazet evt_dir = opendir(dir_path); 214725b1368SEric Dumazet if (!evt_dir) 21525a7d914SArnaldo Carvalho de Melo goto next; 216725b1368SEric Dumazet 217c02cab22SArnaldo Carvalho de Melo for_each_event(dir_path, evt_dir, evt_dirent) { 218725b1368SEric Dumazet 21977f18153SJiri Olsa scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 22022a9f41bSArnaldo Carvalho de Melo evt_dirent->d_name); 221725b1368SEric Dumazet fd = open(evt_path, O_RDONLY); 222f6bdafefSJason Baron if (fd < 0) 223f6bdafefSJason Baron continue; 224f6bdafefSJason Baron if (read(fd, id_buf, sizeof(id_buf)) < 0) { 225f6bdafefSJason Baron close(fd); 226f6bdafefSJason Baron continue; 227f6bdafefSJason Baron } 228f6bdafefSJason Baron close(fd); 229f6bdafefSJason Baron id = atoll(id_buf); 230f6bdafefSJason Baron if (id == config) { 23125a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 232f6bdafefSJason Baron closedir(evt_dir); 233f6bdafefSJason Baron closedir(sys_dir); 23459b4caebSJulia Lawall path = zalloc(sizeof(*path)); 2355aa365f2STaeung Song if (!path) 2365aa365f2STaeung Song return NULL; 2377125f204SArnaldo Carvalho de Melo if (asprintf(&path->system, "%.*s", MAX_EVENT_LENGTH, sys_dirent->d_name) < 0) { 2381ef2ed10SFrederic Weisbecker free(path); 2391ef2ed10SFrederic Weisbecker return NULL; 2401ef2ed10SFrederic Weisbecker } 2417125f204SArnaldo Carvalho de Melo if (asprintf(&path->name, "%.*s", MAX_EVENT_LENGTH, evt_dirent->d_name) < 0) { 24274cf249dSArnaldo Carvalho de Melo zfree(&path->system); 2431ef2ed10SFrederic Weisbecker free(path); 2441ef2ed10SFrederic Weisbecker return NULL; 2451ef2ed10SFrederic Weisbecker } 2461ef2ed10SFrederic Weisbecker return path; 247f6bdafefSJason Baron } 248f6bdafefSJason Baron } 249f6bdafefSJason Baron closedir(evt_dir); 25025a7d914SArnaldo Carvalho de Melo next: 25125a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 252f6bdafefSJason Baron } 253f6bdafefSJason Baron 254f6bdafefSJason Baron closedir(sys_dir); 2551ef2ed10SFrederic Weisbecker return NULL; 2561ef2ed10SFrederic Weisbecker } 2571ef2ed10SFrederic Weisbecker 258e7c93f09SNamhyung Kim struct tracepoint_path *tracepoint_name_to_path(const char *name) 259e7c93f09SNamhyung Kim { 260e7c93f09SNamhyung Kim struct tracepoint_path *path = zalloc(sizeof(*path)); 261e7c93f09SNamhyung Kim char *str = strchr(name, ':'); 262e7c93f09SNamhyung Kim 263e7c93f09SNamhyung Kim if (path == NULL || str == NULL) { 264e7c93f09SNamhyung Kim free(path); 265e7c93f09SNamhyung Kim return NULL; 266e7c93f09SNamhyung Kim } 267e7c93f09SNamhyung Kim 268e7c93f09SNamhyung Kim path->system = strndup(name, str - name); 269e7c93f09SNamhyung Kim path->name = strdup(str+1); 270e7c93f09SNamhyung Kim 271e7c93f09SNamhyung Kim if (path->system == NULL || path->name == NULL) { 27274cf249dSArnaldo Carvalho de Melo zfree(&path->system); 27374cf249dSArnaldo Carvalho de Melo zfree(&path->name); 274506fde11STaeung Song zfree(&path); 275e7c93f09SNamhyung Kim } 276e7c93f09SNamhyung Kim 277e7c93f09SNamhyung Kim return path; 278e7c93f09SNamhyung Kim } 279e7c93f09SNamhyung Kim 2801424dc96SDavid Ahern const char *event_type(int type) 2811424dc96SDavid Ahern { 2821424dc96SDavid Ahern switch (type) { 2831424dc96SDavid Ahern case PERF_TYPE_HARDWARE: 2841424dc96SDavid Ahern return "hardware"; 2851424dc96SDavid Ahern 2861424dc96SDavid Ahern case PERF_TYPE_SOFTWARE: 2871424dc96SDavid Ahern return "software"; 2881424dc96SDavid Ahern 2891424dc96SDavid Ahern case PERF_TYPE_TRACEPOINT: 2901424dc96SDavid Ahern return "tracepoint"; 2911424dc96SDavid Ahern 2921424dc96SDavid Ahern case PERF_TYPE_HW_CACHE: 2931424dc96SDavid Ahern return "hardware-cache"; 2941424dc96SDavid Ahern 2951424dc96SDavid Ahern default: 2961424dc96SDavid Ahern break; 2971424dc96SDavid Ahern } 2981424dc96SDavid Ahern 2991424dc96SDavid Ahern return "unknown"; 3001424dc96SDavid Ahern } 3011424dc96SDavid Ahern 3022b62b3a6SIan Rogers static char *get_config_str(struct list_head *head_terms, int type_term) 303e814fdddSWang Nan { 304e814fdddSWang Nan struct parse_events_term *term; 305e814fdddSWang Nan 306e814fdddSWang Nan if (!head_terms) 307e814fdddSWang Nan return NULL; 308e814fdddSWang Nan 309e814fdddSWang Nan list_for_each_entry(term, head_terms, list) 3102b62b3a6SIan Rogers if (term->type_term == type_term) 311e814fdddSWang Nan return term->val.str; 312e814fdddSWang Nan 313e814fdddSWang Nan return NULL; 314e814fdddSWang Nan } 3157ae92e74SYan, Zheng 3162b62b3a6SIan Rogers static char *get_config_metric_id(struct list_head *head_terms) 3172b62b3a6SIan Rogers { 3182b62b3a6SIan Rogers return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_METRIC_ID); 3192b62b3a6SIan Rogers } 3202b62b3a6SIan Rogers 3212b62b3a6SIan Rogers static char *get_config_name(struct list_head *head_terms) 3222b62b3a6SIan Rogers { 3232b62b3a6SIan Rogers return get_config_str(head_terms, PARSE_EVENTS__TERM_TYPE_NAME); 3242b62b3a6SIan Rogers } 3252b62b3a6SIan Rogers 32632dcd021SJiri Olsa static struct evsel * 327410136f5SStephane Eranian __add_event(struct list_head *list, int *idx, 3287ae92e74SYan, Zheng struct perf_event_attr *attr, 32970943490SStephane Eranian bool init_attr, 3302b62b3a6SIan Rogers const char *name, const char *metric_id, struct perf_pmu *pmu, 331f0fbb114SAndi Kleen struct list_head *config_terms, bool auto_merge_stats, 332f0fbb114SAndi Kleen const char *cpu_list) 33389812fc8SJiri Olsa { 33432dcd021SJiri Olsa struct evsel *evsel; 3355d680be3SNamhyung Kim struct perf_cpu_map *cpus = pmu ? perf_cpu_map__get(pmu->cpus) : 3369c3516d1SJiri Olsa cpu_list ? perf_cpu_map__new(cpu_list) : NULL; 33789812fc8SJiri Olsa 338e4064776SJin Yao if (pmu && attr->type == PERF_TYPE_RAW) 339e4064776SJin Yao perf_pmu__warn_invalid_config(pmu, attr->config, name); 340e4064776SJin Yao 34170943490SStephane Eranian if (init_attr) 34289812fc8SJiri Olsa event_attr_init(attr); 34389812fc8SJiri Olsa 3448f6725a2SArnaldo Carvalho de Melo evsel = evsel__new_idx(attr, *idx); 3450f1b550eSNamhyung Kim if (!evsel) { 3460f1b550eSNamhyung Kim perf_cpu_map__put(cpus); 347410136f5SStephane Eranian return NULL; 3480f1b550eSNamhyung Kim } 34989812fc8SJiri Olsa 35075fc5ae5STaeung Song (*idx)++; 3515d680be3SNamhyung Kim evsel->core.cpus = cpus; 352fe1f61b3SJiri Olsa evsel->core.own_cpus = perf_cpu_map__get(cpus); 353648b5af3SJiri Olsa evsel->core.system_wide = pmu ? pmu->is_uncore : false; 35463ce8449SArnaldo Carvalho de Melo evsel->auto_merge_stats = auto_merge_stats; 355f30a79b0SJiri Olsa 3569db1763cSArnaldo Carvalho de Melo if (name) 35789812fc8SJiri Olsa evsel->name = strdup(name); 358930a2e29SJiri Olsa 3592b62b3a6SIan Rogers if (metric_id) 3602b62b3a6SIan Rogers evsel->metric_id = strdup(metric_id); 3612b62b3a6SIan Rogers 362930a2e29SJiri Olsa if (config_terms) 36399fc5941SAdrian Hunter list_splice_init(config_terms, &evsel->config_terms); 364930a2e29SJiri Olsa 36570943490SStephane Eranian if (list) 366b27c4eceSJiri Olsa list_add_tail(&evsel->core.node, list); 36770943490SStephane Eranian 368410136f5SStephane Eranian return evsel; 36989812fc8SJiri Olsa } 37089812fc8SJiri Olsa 37170943490SStephane Eranian struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, 3722b62b3a6SIan Rogers const char *name, const char *metric_id, 3732b62b3a6SIan Rogers struct perf_pmu *pmu) 37470943490SStephane Eranian { 3752b62b3a6SIan Rogers return __add_event(/*list=*/NULL, &idx, attr, /*init_attr=*/false, name, 3762b62b3a6SIan Rogers metric_id, pmu, /*config_terms=*/NULL, 3772b62b3a6SIan Rogers /*auto_merge_stats=*/false, /*cpu_list=*/NULL); 37870943490SStephane Eranian } 37970943490SStephane Eranian 380c5cd8ac0SDavid Ahern static int add_event(struct list_head *list, int *idx, 3818e8bbfb3SIan Rogers struct perf_event_attr *attr, const char *name, 3822b62b3a6SIan Rogers const char *metric_id, struct list_head *config_terms) 3837ae92e74SYan, Zheng { 3842b62b3a6SIan Rogers return __add_event(list, idx, attr, /*init_attr*/true, name, metric_id, 3852b62b3a6SIan Rogers /*pmu=*/NULL, config_terms, 3862b62b3a6SIan Rogers /*auto_merge_stats=*/false, /*cpu_list=*/NULL) ? 0 : -ENOMEM; 387f0fbb114SAndi Kleen } 388f0fbb114SAndi Kleen 389f0fbb114SAndi Kleen static int add_event_tool(struct list_head *list, int *idx, 390f0fbb114SAndi Kleen enum perf_tool_event tool_event) 391f0fbb114SAndi Kleen { 39232dcd021SJiri Olsa struct evsel *evsel; 393f0fbb114SAndi Kleen struct perf_event_attr attr = { 394f0fbb114SAndi Kleen .type = PERF_TYPE_SOFTWARE, 395f0fbb114SAndi Kleen .config = PERF_COUNT_SW_DUMMY, 396f0fbb114SAndi Kleen }; 397f0fbb114SAndi Kleen 3982b62b3a6SIan Rogers evsel = __add_event(list, idx, &attr, /*init_attr=*/true, /*name=*/NULL, 3992b62b3a6SIan Rogers /*metric_id=*/NULL, /*pmu=*/NULL, 4002b62b3a6SIan Rogers /*config_terms=*/NULL, /*auto_merge_stats=*/false, 4012b62b3a6SIan Rogers /*cpu_list=*/"0"); 402f0fbb114SAndi Kleen if (!evsel) 403f0fbb114SAndi Kleen return -ENOMEM; 404f0fbb114SAndi Kleen evsel->tool_event = tool_event; 405b194c9cdSIan Rogers if (tool_event == PERF_TOOL_DURATION_TIME) { 406b194c9cdSIan Rogers free((char *)evsel->unit); 407b194c9cdSIan Rogers evsel->unit = strdup("ns"); 408b194c9cdSIan Rogers } 409f0fbb114SAndi Kleen return 0; 4107ae92e74SYan, Zheng } 4117ae92e74SYan, Zheng 412c64e85e1SArnaldo Carvalho de Melo static int parse_aliases(char *str, const char *names[][EVSEL__MAX_ALIASES], int size) 41386470930SIngo Molnar { 41486470930SIngo Molnar int i, j; 41561c45981SPaul Mackerras int n, longest = -1; 41686470930SIngo Molnar 41786470930SIngo Molnar for (i = 0; i < size; i++) { 418c64e85e1SArnaldo Carvalho de Melo for (j = 0; j < EVSEL__MAX_ALIASES && names[i][j]; j++) { 41961c45981SPaul Mackerras n = strlen(names[i][j]); 42089812fc8SJiri Olsa if (n > longest && !strncasecmp(str, names[i][j], n)) 42161c45981SPaul Mackerras longest = n; 42261c45981SPaul Mackerras } 42389812fc8SJiri Olsa if (longest > 0) 42486470930SIngo Molnar return i; 42586470930SIngo Molnar } 42686470930SIngo Molnar 4278953645fSIngo Molnar return -1; 42886470930SIngo Molnar } 42986470930SIngo Molnar 43043d0b978SWang Nan typedef int config_term_func_t(struct perf_event_attr *attr, 43143d0b978SWang Nan struct parse_events_term *term, 43243d0b978SWang Nan struct parse_events_error *err); 43343d0b978SWang Nan static int config_term_common(struct perf_event_attr *attr, 43443d0b978SWang Nan struct parse_events_term *term, 43543d0b978SWang Nan struct parse_events_error *err); 43643d0b978SWang Nan static int config_attr(struct perf_event_attr *attr, 43743d0b978SWang Nan struct list_head *head, 43843d0b978SWang Nan struct parse_events_error *err, 43943d0b978SWang Nan config_term_func_t config_term); 44043d0b978SWang Nan 441c5cd8ac0SDavid Ahern int parse_events_add_cache(struct list_head *list, int *idx, 44243d0b978SWang Nan char *type, char *op_result1, char *op_result2, 4432c97b0d4SArnaldo Carvalho de Melo struct parse_events_error *err, 444c93afadcSJin Yao struct list_head *head_config, 445c93afadcSJin Yao struct parse_events_state *parse_state) 44686470930SIngo Molnar { 44789812fc8SJiri Olsa struct perf_event_attr attr; 44843d0b978SWang Nan LIST_HEAD(config_terms); 4498e8bbfb3SIan Rogers char name[MAX_NAME_LEN]; 4502b62b3a6SIan Rogers const char *config_name, *metric_id; 45161c45981SPaul Mackerras int cache_type = -1, cache_op = -1, cache_result = -1; 45289812fc8SJiri Olsa char *op_result[2] = { op_result1, op_result2 }; 45330def61fSJin Yao int i, n, ret; 45430def61fSJin Yao bool hybrid; 45586470930SIngo Molnar 45686470930SIngo Molnar /* 45786470930SIngo Molnar * No fallback - if we cannot get a clear cache type 45886470930SIngo Molnar * then bail out: 45986470930SIngo Molnar */ 460c64e85e1SArnaldo Carvalho de Melo cache_type = parse_aliases(type, evsel__hw_cache, PERF_COUNT_HW_CACHE_MAX); 46186470930SIngo Molnar if (cache_type == -1) 46289812fc8SJiri Olsa return -EINVAL; 46386470930SIngo Molnar 46443d0b978SWang Nan config_name = get_config_name(head_config); 46589812fc8SJiri Olsa n = snprintf(name, MAX_NAME_LEN, "%s", type); 46689812fc8SJiri Olsa 46789812fc8SJiri Olsa for (i = 0; (i < 2) && (op_result[i]); i++) { 46889812fc8SJiri Olsa char *str = op_result[i]; 46989812fc8SJiri Olsa 470275ef387SJiri Olsa n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str); 47161c45981SPaul Mackerras 47261c45981SPaul Mackerras if (cache_op == -1) { 473c64e85e1SArnaldo Carvalho de Melo cache_op = parse_aliases(str, evsel__hw_cache_op, 47461c45981SPaul Mackerras PERF_COUNT_HW_CACHE_OP_MAX); 47561c45981SPaul Mackerras if (cache_op >= 0) { 476c754c382SArnaldo Carvalho de Melo if (!evsel__is_cache_op_valid(cache_type, cache_op)) 47789812fc8SJiri Olsa return -EINVAL; 47861c45981SPaul Mackerras continue; 47961c45981SPaul Mackerras } 48061c45981SPaul Mackerras } 48161c45981SPaul Mackerras 48261c45981SPaul Mackerras if (cache_result == -1) { 483c64e85e1SArnaldo Carvalho de Melo cache_result = parse_aliases(str, evsel__hw_cache_result, 48461c45981SPaul Mackerras PERF_COUNT_HW_CACHE_RESULT_MAX); 48561c45981SPaul Mackerras if (cache_result >= 0) 48661c45981SPaul Mackerras continue; 48761c45981SPaul Mackerras } 48861c45981SPaul Mackerras } 48961c45981SPaul Mackerras 49086470930SIngo Molnar /* 49186470930SIngo Molnar * Fall back to reads: 49286470930SIngo Molnar */ 4938953645fSIngo Molnar if (cache_op == -1) 4948953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 49586470930SIngo Molnar 49686470930SIngo Molnar /* 49786470930SIngo Molnar * Fall back to accesses: 49886470930SIngo Molnar */ 49986470930SIngo Molnar if (cache_result == -1) 50086470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 50186470930SIngo Molnar 50289812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 50389812fc8SJiri Olsa attr.config = cache_type | (cache_op << 8) | (cache_result << 16); 50489812fc8SJiri Olsa attr.type = PERF_TYPE_HW_CACHE; 50543d0b978SWang Nan 50643d0b978SWang Nan if (head_config) { 5072c97b0d4SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, err, 50843d0b978SWang Nan config_term_common)) 50943d0b978SWang Nan return -EINVAL; 51043d0b978SWang Nan 51143d0b978SWang Nan if (get_config_terms(head_config, &config_terms)) 51243d0b978SWang Nan return -ENOMEM; 51343d0b978SWang Nan } 51430def61fSJin Yao 5152b62b3a6SIan Rogers metric_id = get_config_metric_id(head_config); 51630def61fSJin Yao ret = parse_events__add_cache_hybrid(list, idx, &attr, 5172b62b3a6SIan Rogers config_name ? : name, 5182b62b3a6SIan Rogers metric_id, 5192b62b3a6SIan Rogers &config_terms, 520c93afadcSJin Yao &hybrid, parse_state); 52130def61fSJin Yao if (hybrid) 52299fc5941SAdrian Hunter goto out_free_terms; 52330def61fSJin Yao 5242b62b3a6SIan Rogers ret = add_event(list, idx, &attr, config_name ? : name, metric_id, 5252b62b3a6SIan Rogers &config_terms); 52699fc5941SAdrian Hunter out_free_terms: 52799fc5941SAdrian Hunter free_config_terms(&config_terms); 52899fc5941SAdrian Hunter return ret; 52986470930SIngo Molnar } 53086470930SIngo Molnar 531272ed29aSJiri Olsa static void tracepoint_error(struct parse_events_error *e, int err, 5328c619d6aSWang Nan const char *sys, const char *name) 53319658171SJiri Olsa { 5344584f084SIan Rogers const char *str; 53519658171SJiri Olsa char help[BUFSIZ]; 53619658171SJiri Olsa 537ec183d22SAdrian Hunter if (!e) 538ec183d22SAdrian Hunter return; 539ec183d22SAdrian Hunter 54019658171SJiri Olsa /* 54119658171SJiri Olsa * We get error directly from syscall errno ( > 0), 54219658171SJiri Olsa * or from encoded pointer's error ( < 0). 54319658171SJiri Olsa */ 54419658171SJiri Olsa err = abs(err); 54519658171SJiri Olsa 54619658171SJiri Olsa switch (err) { 54719658171SJiri Olsa case EACCES: 5484584f084SIan Rogers str = "can't access trace events"; 54919658171SJiri Olsa break; 55019658171SJiri Olsa case ENOENT: 5514584f084SIan Rogers str = "unknown tracepoint"; 55219658171SJiri Olsa break; 55319658171SJiri Olsa default: 5544584f084SIan Rogers str = "failed to add tracepoint"; 55519658171SJiri Olsa break; 55619658171SJiri Olsa } 55719658171SJiri Olsa 55819658171SJiri Olsa tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name); 5596c191289SIan Rogers parse_events_error__handle(e, 0, strdup(str), strdup(help)); 56019658171SJiri Olsa } 56119658171SJiri Olsa 562c5cd8ac0SDavid Ahern static int add_tracepoint(struct list_head *list, int *idx, 5638c619d6aSWang Nan const char *sys_name, const char *evt_name, 564272ed29aSJiri Olsa struct parse_events_error *err, 565e637d177SHe Kuang struct list_head *head_config) 566bcd3279fSFrederic Weisbecker { 5678f6725a2SArnaldo Carvalho de Melo struct evsel *evsel = evsel__newtp_idx(sys_name, evt_name, (*idx)++); 568bcd3279fSFrederic Weisbecker 56919658171SJiri Olsa if (IS_ERR(evsel)) { 570272ed29aSJiri Olsa tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name); 5718dd2a131SJiri Olsa return PTR_ERR(evsel); 57219658171SJiri Olsa } 573bcd3279fSFrederic Weisbecker 574e637d177SHe Kuang if (head_config) { 575e637d177SHe Kuang LIST_HEAD(config_terms); 576e637d177SHe Kuang 577e637d177SHe Kuang if (get_config_terms(head_config, &config_terms)) 578e637d177SHe Kuang return -ENOMEM; 579e637d177SHe Kuang list_splice(&config_terms, &evsel->config_terms); 580e637d177SHe Kuang } 581e637d177SHe Kuang 582b27c4eceSJiri Olsa list_add_tail(&evsel->core.node, list); 58382fe1c29SArnaldo Carvalho de Melo return 0; 584bcd3279fSFrederic Weisbecker } 585bcd3279fSFrederic Weisbecker 586c5cd8ac0SDavid Ahern static int add_tracepoint_multi_event(struct list_head *list, int *idx, 5878c619d6aSWang Nan const char *sys_name, const char *evt_name, 588272ed29aSJiri Olsa struct parse_events_error *err, 589e637d177SHe Kuang struct list_head *head_config) 590bcd3279fSFrederic Weisbecker { 59125a7d914SArnaldo Carvalho de Melo char *evt_path; 592bcd3279fSFrederic Weisbecker struct dirent *evt_ent; 593bcd3279fSFrederic Weisbecker DIR *evt_dir; 59427bf90bfSJiri Olsa int ret = 0, found = 0; 595bcd3279fSFrederic Weisbecker 59625a7d914SArnaldo Carvalho de Melo evt_path = get_events_file(sys_name); 59725a7d914SArnaldo Carvalho de Melo if (!evt_path) { 59825a7d914SArnaldo Carvalho de Melo tracepoint_error(err, errno, sys_name, evt_name); 59925a7d914SArnaldo Carvalho de Melo return -1; 60025a7d914SArnaldo Carvalho de Melo } 601bcd3279fSFrederic Weisbecker evt_dir = opendir(evt_path); 602bcd3279fSFrederic Weisbecker if (!evt_dir) { 60325a7d914SArnaldo Carvalho de Melo put_events_file(evt_path); 604272ed29aSJiri Olsa tracepoint_error(err, errno, sys_name, evt_name); 60589812fc8SJiri Olsa return -1; 606bcd3279fSFrederic Weisbecker } 607bcd3279fSFrederic Weisbecker 60889812fc8SJiri Olsa while (!ret && (evt_ent = readdir(evt_dir))) { 609bcd3279fSFrederic Weisbecker if (!strcmp(evt_ent->d_name, ".") 610bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "..") 611bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "enable") 612bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "filter")) 613bcd3279fSFrederic Weisbecker continue; 614bcd3279fSFrederic Weisbecker 61589812fc8SJiri Olsa if (!strglobmatch(evt_ent->d_name, evt_name)) 616fb1d2edfSMasami Hiramatsu continue; 617fb1d2edfSMasami Hiramatsu 61827bf90bfSJiri Olsa found++; 61927bf90bfSJiri Olsa 620e637d177SHe Kuang ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, 621272ed29aSJiri Olsa err, head_config); 622bcd3279fSFrederic Weisbecker } 623bcd3279fSFrederic Weisbecker 62427bf90bfSJiri Olsa if (!found) { 62527bf90bfSJiri Olsa tracepoint_error(err, ENOENT, sys_name, evt_name); 62627bf90bfSJiri Olsa ret = -1; 62727bf90bfSJiri Olsa } 62827bf90bfSJiri Olsa 62925a7d914SArnaldo Carvalho de Melo put_events_file(evt_path); 6300bd3f084SJiri Olsa closedir(evt_dir); 63189812fc8SJiri Olsa return ret; 632bcd3279fSFrederic Weisbecker } 633bcd3279fSFrederic Weisbecker 634c5cd8ac0SDavid Ahern static int add_tracepoint_event(struct list_head *list, int *idx, 6358c619d6aSWang Nan const char *sys_name, const char *evt_name, 636272ed29aSJiri Olsa struct parse_events_error *err, 637e637d177SHe Kuang struct list_head *head_config) 638f35488f9SJiri Olsa { 639f35488f9SJiri Olsa return strpbrk(evt_name, "*?") ? 640e637d177SHe Kuang add_tracepoint_multi_event(list, idx, sys_name, evt_name, 641272ed29aSJiri Olsa err, head_config) : 642e637d177SHe Kuang add_tracepoint(list, idx, sys_name, evt_name, 643272ed29aSJiri Olsa err, head_config); 644f35488f9SJiri Olsa } 645f35488f9SJiri Olsa 646c5cd8ac0SDavid Ahern static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 6478c619d6aSWang Nan const char *sys_name, const char *evt_name, 648272ed29aSJiri Olsa struct parse_events_error *err, 649e637d177SHe Kuang struct list_head *head_config) 650f35488f9SJiri Olsa { 651f35488f9SJiri Olsa struct dirent *events_ent; 652f35488f9SJiri Olsa DIR *events_dir; 653f35488f9SJiri Olsa int ret = 0; 654f35488f9SJiri Olsa 6557014e0e3SArnaldo Carvalho de Melo events_dir = tracing_events__opendir(); 656f35488f9SJiri Olsa if (!events_dir) { 657272ed29aSJiri Olsa tracepoint_error(err, errno, sys_name, evt_name); 658f35488f9SJiri Olsa return -1; 659f35488f9SJiri Olsa } 660f35488f9SJiri Olsa 661f35488f9SJiri Olsa while (!ret && (events_ent = readdir(events_dir))) { 662f35488f9SJiri Olsa if (!strcmp(events_ent->d_name, ".") 663f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "..") 664f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "enable") 665f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_event") 666f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_page")) 667f35488f9SJiri Olsa continue; 668f35488f9SJiri Olsa 669f35488f9SJiri Olsa if (!strglobmatch(events_ent->d_name, sys_name)) 670f35488f9SJiri Olsa continue; 671f35488f9SJiri Olsa 672f35488f9SJiri Olsa ret = add_tracepoint_event(list, idx, events_ent->d_name, 673272ed29aSJiri Olsa evt_name, err, head_config); 674f35488f9SJiri Olsa } 675f35488f9SJiri Olsa 676f35488f9SJiri Olsa closedir(events_dir); 677f35488f9SJiri Olsa return ret; 678f35488f9SJiri Olsa } 679f35488f9SJiri Olsa 680c18cf78dSArnaldo Carvalho de Melo #ifdef HAVE_LIBBPF_SUPPORT 6814edf30e3SWang Nan struct __add_bpf_event_param { 6825d9cdc11SArnaldo Carvalho de Melo struct parse_events_state *parse_state; 6834edf30e3SWang Nan struct list_head *list; 68495088a59SWang Nan struct list_head *head_config; 6854edf30e3SWang Nan }; 6864edf30e3SWang Nan 687af4a0991SArnaldo Carvalho de Melo static int add_bpf_event(const char *group, const char *event, int fd, struct bpf_object *obj, 6884edf30e3SWang Nan void *_param) 6894edf30e3SWang Nan { 6904edf30e3SWang Nan LIST_HEAD(new_evsels); 6914edf30e3SWang Nan struct __add_bpf_event_param *param = _param; 6925d9cdc11SArnaldo Carvalho de Melo struct parse_events_state *parse_state = param->parse_state; 6934edf30e3SWang Nan struct list_head *list = param->list; 69432dcd021SJiri Olsa struct evsel *pos; 6954edf30e3SWang Nan int err; 6962620b7e3SArnaldo Carvalho de Melo /* 6972620b7e3SArnaldo Carvalho de Melo * Check if we should add the event, i.e. if it is a TP but starts with a '!', 6982620b7e3SArnaldo Carvalho de Melo * then don't add the tracepoint, this will be used for something else, like 6992620b7e3SArnaldo Carvalho de Melo * adding to a BPF_MAP_TYPE_PROG_ARRAY. 7002620b7e3SArnaldo Carvalho de Melo * 7012620b7e3SArnaldo Carvalho de Melo * See tools/perf/examples/bpf/augmented_raw_syscalls.c 7022620b7e3SArnaldo Carvalho de Melo */ 7032620b7e3SArnaldo Carvalho de Melo if (group[0] == '!') 7042620b7e3SArnaldo Carvalho de Melo return 0; 7054edf30e3SWang Nan 7064edf30e3SWang Nan pr_debug("add bpf event %s:%s and attach bpf program %d\n", 707cd102d70SWang Nan group, event, fd); 7084edf30e3SWang Nan 7095d369a75SArnaldo Carvalho de Melo err = parse_events_add_tracepoint(&new_evsels, &parse_state->idx, group, 7105d369a75SArnaldo Carvalho de Melo event, parse_state->error, 71195088a59SWang Nan param->head_config); 7124edf30e3SWang Nan if (err) { 71332dcd021SJiri Olsa struct evsel *evsel, *tmp; 7144edf30e3SWang Nan 7154edf30e3SWang Nan pr_debug("Failed to add BPF event %s:%s\n", 716cd102d70SWang Nan group, event); 717b27c4eceSJiri Olsa list_for_each_entry_safe(evsel, tmp, &new_evsels, core.node) { 718b27c4eceSJiri Olsa list_del_init(&evsel->core.node); 7195eb2dd2aSJiri Olsa evsel__delete(evsel); 7204edf30e3SWang Nan } 7214edf30e3SWang Nan return err; 7224edf30e3SWang Nan } 723cd102d70SWang Nan pr_debug("adding %s:%s\n", group, event); 7244edf30e3SWang Nan 725b27c4eceSJiri Olsa list_for_each_entry(pos, &new_evsels, core.node) { 7261f45b1d4SWang Nan pr_debug("adding %s:%s to %p\n", 727cd102d70SWang Nan group, event, pos); 7281f45b1d4SWang Nan pos->bpf_fd = fd; 729af4a0991SArnaldo Carvalho de Melo pos->bpf_obj = obj; 7301f45b1d4SWang Nan } 7314edf30e3SWang Nan list_splice(&new_evsels, list); 7324edf30e3SWang Nan return 0; 7334edf30e3SWang Nan } 7344edf30e3SWang Nan 7355d9cdc11SArnaldo Carvalho de Melo int parse_events_load_bpf_obj(struct parse_events_state *parse_state, 73684c86ca1SWang Nan struct list_head *list, 73795088a59SWang Nan struct bpf_object *obj, 73895088a59SWang Nan struct list_head *head_config) 73984c86ca1SWang Nan { 74084c86ca1SWang Nan int err; 74184c86ca1SWang Nan char errbuf[BUFSIZ]; 7425d9cdc11SArnaldo Carvalho de Melo struct __add_bpf_event_param param = {parse_state, list, head_config}; 743aa3abf30SWang Nan static bool registered_unprobe_atexit = false; 74484c86ca1SWang Nan 74584c86ca1SWang Nan if (IS_ERR(obj) || !obj) { 74684c86ca1SWang Nan snprintf(errbuf, sizeof(errbuf), 74784c86ca1SWang Nan "Internal error: load bpf obj with NULL"); 74884c86ca1SWang Nan err = -EINVAL; 74984c86ca1SWang Nan goto errout; 75084c86ca1SWang Nan } 75184c86ca1SWang Nan 75284c86ca1SWang Nan /* 753aa3abf30SWang Nan * Register atexit handler before calling bpf__probe() so 754aa3abf30SWang Nan * bpf__probe() don't need to unprobe probe points its already 755aa3abf30SWang Nan * created when failure. 756aa3abf30SWang Nan */ 757aa3abf30SWang Nan if (!registered_unprobe_atexit) { 758aa3abf30SWang Nan atexit(bpf__clear); 759aa3abf30SWang Nan registered_unprobe_atexit = true; 760aa3abf30SWang Nan } 761aa3abf30SWang Nan 762aa3abf30SWang Nan err = bpf__probe(obj); 763aa3abf30SWang Nan if (err) { 764aa3abf30SWang Nan bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf)); 765aa3abf30SWang Nan goto errout; 766aa3abf30SWang Nan } 767aa3abf30SWang Nan 7681e5e3ee8SWang Nan err = bpf__load(obj); 7691e5e3ee8SWang Nan if (err) { 7701e5e3ee8SWang Nan bpf__strerror_load(obj, err, errbuf, sizeof(errbuf)); 7711e5e3ee8SWang Nan goto errout; 7721e5e3ee8SWang Nan } 7731e5e3ee8SWang Nan 774cd102d70SWang Nan err = bpf__foreach_event(obj, add_bpf_event, ¶m); 7754edf30e3SWang Nan if (err) { 7764edf30e3SWang Nan snprintf(errbuf, sizeof(errbuf), 7774edf30e3SWang Nan "Attach events in BPF object failed"); 7784edf30e3SWang Nan goto errout; 7794edf30e3SWang Nan } 7804edf30e3SWang Nan 7814edf30e3SWang Nan return 0; 78284c86ca1SWang Nan errout: 7836c191289SIan Rogers parse_events_error__handle(parse_state->error, 0, 7845f634c8eSIan Rogers strdup(errbuf), strdup("(add -v to see detail)")); 78584c86ca1SWang Nan return err; 78684c86ca1SWang Nan } 78784c86ca1SWang Nan 788a34f3be7SWang Nan static int 7895d9cdc11SArnaldo Carvalho de Melo parse_events_config_bpf(struct parse_events_state *parse_state, 790a34f3be7SWang Nan struct bpf_object *obj, 791a34f3be7SWang Nan struct list_head *head_config) 792a34f3be7SWang Nan { 793a34f3be7SWang Nan struct parse_events_term *term; 794a34f3be7SWang Nan int error_pos; 795a34f3be7SWang Nan 796a34f3be7SWang Nan if (!head_config || list_empty(head_config)) 797a34f3be7SWang Nan return 0; 798a34f3be7SWang Nan 799a34f3be7SWang Nan list_for_each_entry(term, head_config, list) { 800a34f3be7SWang Nan int err; 801a34f3be7SWang Nan 802a34f3be7SWang Nan if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) { 8036c191289SIan Rogers parse_events_error__handle(parse_state->error, term->err_term, 8045f634c8eSIan Rogers strdup("Invalid config term for BPF object"), 8055f634c8eSIan Rogers NULL); 806a34f3be7SWang Nan return -EINVAL; 807a34f3be7SWang Nan } 808a34f3be7SWang Nan 8095d9cdc11SArnaldo Carvalho de Melo err = bpf__config_obj(obj, term, parse_state->evlist, &error_pos); 810a34f3be7SWang Nan if (err) { 8115f634c8eSIan Rogers char errbuf[BUFSIZ]; 8125f634c8eSIan Rogers int idx; 8135f634c8eSIan Rogers 8145d9cdc11SArnaldo Carvalho de Melo bpf__strerror_config_obj(obj, term, parse_state->evlist, 815a34f3be7SWang Nan &error_pos, err, errbuf, 816a34f3be7SWang Nan sizeof(errbuf)); 8175f634c8eSIan Rogers 8185f634c8eSIan Rogers if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE) 8195f634c8eSIan Rogers idx = term->err_val; 8205f634c8eSIan Rogers else 8215f634c8eSIan Rogers idx = term->err_term + error_pos; 8225f634c8eSIan Rogers 8236c191289SIan Rogers parse_events_error__handle(parse_state->error, idx, 8245f634c8eSIan Rogers strdup(errbuf), 8255f634c8eSIan Rogers strdup( 8267630b3e2SWang Nan "Hint:\tValid config terms:\n" 827e571e029SWang Nan " \tmap:[<arraymap>].value<indices>=[value]\n" 828e571e029SWang Nan " \tmap:[<eventmap>].event<indices>=[event]\n" 8297630b3e2SWang Nan "\n" 830e571e029SWang Nan " \twhere <indices> is something like [0,3...5] or [all]\n" 8315f634c8eSIan Rogers " \t(add -v to see detail)")); 832a34f3be7SWang Nan return err; 833a34f3be7SWang Nan } 834a34f3be7SWang Nan } 835a34f3be7SWang Nan return 0; 836a34f3be7SWang Nan } 837a34f3be7SWang Nan 83895088a59SWang Nan /* 83995088a59SWang Nan * Split config terms: 84095088a59SWang Nan * perf record -e bpf.c/call-graph=fp,map:array.value[0]=1/ ... 84195088a59SWang Nan * 'call-graph=fp' is 'evt config', should be applied to each 84295088a59SWang Nan * events in bpf.c. 84395088a59SWang Nan * 'map:array.value[0]=1' is 'obj config', should be processed 84495088a59SWang Nan * with parse_events_config_bpf. 84595088a59SWang Nan * 84695088a59SWang Nan * Move object config terms from the first list to obj_head_config. 84795088a59SWang Nan */ 84895088a59SWang Nan static void 84995088a59SWang Nan split_bpf_config_terms(struct list_head *evt_head_config, 85095088a59SWang Nan struct list_head *obj_head_config) 85195088a59SWang Nan { 85295088a59SWang Nan struct parse_events_term *term, *temp; 85395088a59SWang Nan 85495088a59SWang Nan /* 8554d39c89fSIngo Molnar * Currently, all possible user config term 85695088a59SWang Nan * belong to bpf object. parse_events__is_hardcoded_term() 8574d39c89fSIngo Molnar * happens to be a good flag. 85895088a59SWang Nan * 85995088a59SWang Nan * See parse_events_config_bpf() and 86095088a59SWang Nan * config_term_tracepoint(). 86195088a59SWang Nan */ 86295088a59SWang Nan list_for_each_entry_safe(term, temp, evt_head_config, list) 86395088a59SWang Nan if (!parse_events__is_hardcoded_term(term)) 86495088a59SWang Nan list_move_tail(&term->list, obj_head_config); 86595088a59SWang Nan } 86695088a59SWang Nan 8675d9cdc11SArnaldo Carvalho de Melo int parse_events_load_bpf(struct parse_events_state *parse_state, 86884c86ca1SWang Nan struct list_head *list, 869d509db04SWang Nan char *bpf_file_name, 870a34f3be7SWang Nan bool source, 871a34f3be7SWang Nan struct list_head *head_config) 87284c86ca1SWang Nan { 873a34f3be7SWang Nan int err; 87495088a59SWang Nan struct bpf_object *obj; 87595088a59SWang Nan LIST_HEAD(obj_head_config); 87695088a59SWang Nan 87795088a59SWang Nan if (head_config) 87895088a59SWang Nan split_bpf_config_terms(head_config, &obj_head_config); 87984c86ca1SWang Nan 880d509db04SWang Nan obj = bpf__prepare_load(bpf_file_name, source); 8816371ca3bSWang Nan if (IS_ERR(obj)) { 88284c86ca1SWang Nan char errbuf[BUFSIZ]; 88384c86ca1SWang Nan 8846371ca3bSWang Nan err = PTR_ERR(obj); 88584c86ca1SWang Nan 88684c86ca1SWang Nan if (err == -ENOTSUP) 88784c86ca1SWang Nan snprintf(errbuf, sizeof(errbuf), 88884c86ca1SWang Nan "BPF support is not compiled"); 88984c86ca1SWang Nan else 890d3e0ce39SWang Nan bpf__strerror_prepare_load(bpf_file_name, 891d3e0ce39SWang Nan source, 892d3e0ce39SWang Nan -err, errbuf, 893d3e0ce39SWang Nan sizeof(errbuf)); 89484c86ca1SWang Nan 8956c191289SIan Rogers parse_events_error__handle(parse_state->error, 0, 8965f634c8eSIan Rogers strdup(errbuf), strdup("(add -v to see detail)")); 89784c86ca1SWang Nan return err; 89884c86ca1SWang Nan } 89984c86ca1SWang Nan 9005d9cdc11SArnaldo Carvalho de Melo err = parse_events_load_bpf_obj(parse_state, list, obj, head_config); 901a34f3be7SWang Nan if (err) 902a34f3be7SWang Nan return err; 9035d9cdc11SArnaldo Carvalho de Melo err = parse_events_config_bpf(parse_state, obj, &obj_head_config); 90495088a59SWang Nan 90595088a59SWang Nan /* 90695088a59SWang Nan * Caller doesn't know anything about obj_head_config, 9074d39c89fSIngo Molnar * so combine them together again before returning. 90895088a59SWang Nan */ 90995088a59SWang Nan if (head_config) 91095088a59SWang Nan list_splice_tail(&obj_head_config, head_config); 91195088a59SWang Nan return err; 91284c86ca1SWang Nan } 913c18cf78dSArnaldo Carvalho de Melo #else // HAVE_LIBBPF_SUPPORT 914c18cf78dSArnaldo Carvalho de Melo int parse_events_load_bpf_obj(struct parse_events_state *parse_state, 915c18cf78dSArnaldo Carvalho de Melo struct list_head *list __maybe_unused, 916c18cf78dSArnaldo Carvalho de Melo struct bpf_object *obj __maybe_unused, 917c18cf78dSArnaldo Carvalho de Melo struct list_head *head_config __maybe_unused) 918c18cf78dSArnaldo Carvalho de Melo { 9196c191289SIan Rogers parse_events_error__handle(parse_state->error, 0, 920c18cf78dSArnaldo Carvalho de Melo strdup("BPF support is not compiled"), 921c18cf78dSArnaldo Carvalho de Melo strdup("Make sure libbpf-devel is available at build time.")); 922c18cf78dSArnaldo Carvalho de Melo return -ENOTSUP; 923c18cf78dSArnaldo Carvalho de Melo } 924c18cf78dSArnaldo Carvalho de Melo 925c18cf78dSArnaldo Carvalho de Melo int parse_events_load_bpf(struct parse_events_state *parse_state, 926c18cf78dSArnaldo Carvalho de Melo struct list_head *list __maybe_unused, 927c18cf78dSArnaldo Carvalho de Melo char *bpf_file_name __maybe_unused, 928c18cf78dSArnaldo Carvalho de Melo bool source __maybe_unused, 929c18cf78dSArnaldo Carvalho de Melo struct list_head *head_config __maybe_unused) 930c18cf78dSArnaldo Carvalho de Melo { 9316c191289SIan Rogers parse_events_error__handle(parse_state->error, 0, 932c18cf78dSArnaldo Carvalho de Melo strdup("BPF support is not compiled"), 933c18cf78dSArnaldo Carvalho de Melo strdup("Make sure libbpf-devel is available at build time.")); 934c18cf78dSArnaldo Carvalho de Melo return -ENOTSUP; 935c18cf78dSArnaldo Carvalho de Melo } 936c18cf78dSArnaldo Carvalho de Melo #endif // HAVE_LIBBPF_SUPPORT 93784c86ca1SWang Nan 93889812fc8SJiri Olsa static int 93989812fc8SJiri Olsa parse_breakpoint_type(const char *type, struct perf_event_attr *attr) 9401b290d67SFrederic Weisbecker { 9411b290d67SFrederic Weisbecker int i; 9421b290d67SFrederic Weisbecker 9431b290d67SFrederic Weisbecker for (i = 0; i < 3; i++) { 94489812fc8SJiri Olsa if (!type || !type[i]) 9451b290d67SFrederic Weisbecker break; 9461b290d67SFrederic Weisbecker 9477582732fSJiri Olsa #define CHECK_SET_TYPE(bit) \ 9487582732fSJiri Olsa do { \ 9497582732fSJiri Olsa if (attr->bp_type & bit) \ 9507582732fSJiri Olsa return -EINVAL; \ 9517582732fSJiri Olsa else \ 9527582732fSJiri Olsa attr->bp_type |= bit; \ 9537582732fSJiri Olsa } while (0) 9547582732fSJiri Olsa 9551b290d67SFrederic Weisbecker switch (type[i]) { 9561b290d67SFrederic Weisbecker case 'r': 9577582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_R); 9581b290d67SFrederic Weisbecker break; 9591b290d67SFrederic Weisbecker case 'w': 9607582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_W); 9611b290d67SFrederic Weisbecker break; 9621b290d67SFrederic Weisbecker case 'x': 9637582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_X); 9641b290d67SFrederic Weisbecker break; 9651b290d67SFrederic Weisbecker default: 96689812fc8SJiri Olsa return -EINVAL; 9671b290d67SFrederic Weisbecker } 9681b290d67SFrederic Weisbecker } 96989812fc8SJiri Olsa 9707582732fSJiri Olsa #undef CHECK_SET_TYPE 9717582732fSJiri Olsa 9721b290d67SFrederic Weisbecker if (!attr->bp_type) /* Default */ 9731b290d67SFrederic Weisbecker attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 9741b290d67SFrederic Weisbecker 97589812fc8SJiri Olsa return 0; 9761b290d67SFrederic Weisbecker } 9771b290d67SFrederic Weisbecker 978c5cd8ac0SDavid Ahern int parse_events_add_breakpoint(struct list_head *list, int *idx, 979aa98d848SIan Rogers u64 addr, char *type, u64 len) 9801b290d67SFrederic Weisbecker { 98189812fc8SJiri Olsa struct perf_event_attr attr; 9821b290d67SFrederic Weisbecker 98389812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 984aa98d848SIan Rogers attr.bp_addr = addr; 9851b290d67SFrederic Weisbecker 98689812fc8SJiri Olsa if (parse_breakpoint_type(type, &attr)) 98789812fc8SJiri Olsa return -EINVAL; 9881b290d67SFrederic Weisbecker 9893741eb9fSJacob Shin /* Provide some defaults if len is not specified */ 9903741eb9fSJacob Shin if (!len) { 99189812fc8SJiri Olsa if (attr.bp_type == HW_BREAKPOINT_X) 9923741eb9fSJacob Shin len = sizeof(long); 993aa59a485SFrederic Weisbecker else 9943741eb9fSJacob Shin len = HW_BREAKPOINT_LEN_4; 9953741eb9fSJacob Shin } 9963741eb9fSJacob Shin 9973741eb9fSJacob Shin attr.bp_len = len; 998aa59a485SFrederic Weisbecker 99989812fc8SJiri Olsa attr.type = PERF_TYPE_BREAKPOINT; 10004a841d65SJovi Zhang attr.sample_period = 1; 10011b290d67SFrederic Weisbecker 10022b62b3a6SIan Rogers return add_event(list, idx, &attr, /*name=*/NULL, /*mertic_id=*/NULL, 10032b62b3a6SIan Rogers /*config_terms=*/NULL); 10041b290d67SFrederic Weisbecker } 10051b290d67SFrederic Weisbecker 10063b0e371cSJiri Olsa static int check_type_val(struct parse_events_term *term, 10073b0e371cSJiri Olsa struct parse_events_error *err, 10083b0e371cSJiri Olsa int type) 10093b0e371cSJiri Olsa { 10103b0e371cSJiri Olsa if (type == term->type_val) 10113b0e371cSJiri Olsa return 0; 10123b0e371cSJiri Olsa 10133b0e371cSJiri Olsa if (err) { 10146c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1015448d732cSIan Rogers type == PARSE_EVENTS__TERM_TYPE_NUM 1016448d732cSIan Rogers ? strdup("expected numeric value") 1017448d732cSIan Rogers : strdup("expected string value"), 1018448d732cSIan Rogers NULL); 10193b0e371cSJiri Olsa } 10203b0e371cSJiri Olsa return -EINVAL; 10213b0e371cSJiri Olsa } 10223b0e371cSJiri Olsa 102317cb5f84SWang Nan /* 102417cb5f84SWang Nan * Update according to parse-events.l 102517cb5f84SWang Nan */ 102617cb5f84SWang Nan static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = { 102717cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_USER] = "<sysfs term>", 102817cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG] = "config", 102917cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG1] = "config1", 103017cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG2] = "config2", 103117cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_NAME] = "name", 103217cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD] = "period", 103317cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ] = "freq", 103417cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE] = "branch_type", 103517cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_TIME] = "time", 103617cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CALLGRAPH] = "call-graph", 103717cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_STACKSIZE] = "stack-size", 103817cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", 103917cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", 1040792d48b4SArnaldo Carvalho de Melo [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", 10412fda5adaSArnaldo Carvalho de Melo [PARSE_EVENTS__TERM_TYPE_MAX_EVENTS] = "nr", 1042626a6b78SWang Nan [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", 1043626a6b78SWang Nan [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", 1044dd60fba7SMathieu Poirier [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", 1045064b4e82SJin Yao [PARSE_EVENTS__TERM_TYPE_PERCORE] = "percore", 10461b992154SAdrian Hunter [PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT] = "aux-output", 1047eb7a52d4SAdrian Hunter [PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE] = "aux-sample-size", 10482b62b3a6SIan Rogers [PARSE_EVENTS__TERM_TYPE_METRIC_ID] = "metric-id", 104917cb5f84SWang Nan }; 105017cb5f84SWang Nan 10511669e509SWang Nan static bool config_term_shrinked; 10521669e509SWang Nan 10531669e509SWang Nan static bool 10541669e509SWang Nan config_term_avail(int term_type, struct parse_events_error *err) 10551669e509SWang Nan { 1056448d732cSIan Rogers char *err_str; 1057448d732cSIan Rogers 10581669e509SWang Nan if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) { 10596c191289SIan Rogers parse_events_error__handle(err, -1, 1060448d732cSIan Rogers strdup("Invalid term_type"), NULL); 10611669e509SWang Nan return false; 10621669e509SWang Nan } 10631669e509SWang Nan if (!config_term_shrinked) 10641669e509SWang Nan return true; 10651669e509SWang Nan 10661669e509SWang Nan switch (term_type) { 10671669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG: 10681669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG1: 10691669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG2: 10701669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_NAME: 10712b62b3a6SIan Rogers case PARSE_EVENTS__TERM_TYPE_METRIC_ID: 107206835545SSukadev Bhattiprolu case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 1073064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 10741669e509SWang Nan return true; 10751669e509SWang Nan default: 10761669e509SWang Nan if (!err) 10771669e509SWang Nan return false; 10781669e509SWang Nan 10791669e509SWang Nan /* term_type is validated so indexing is safe */ 1080448d732cSIan Rogers if (asprintf(&err_str, "'%s' is not usable in 'perf stat'", 1081448d732cSIan Rogers config_term_names[term_type]) >= 0) 10826c191289SIan Rogers parse_events_error__handle(err, -1, err_str, NULL); 10831669e509SWang Nan return false; 10841669e509SWang Nan } 10851669e509SWang Nan } 10861669e509SWang Nan 10871669e509SWang Nan void parse_events__shrink_config_terms(void) 10881669e509SWang Nan { 10891669e509SWang Nan config_term_shrinked = true; 10901669e509SWang Nan } 10911669e509SWang Nan 10920b8891a8SHe Kuang static int config_term_common(struct perf_event_attr *attr, 10933b0e371cSJiri Olsa struct parse_events_term *term, 10943b0e371cSJiri Olsa struct parse_events_error *err) 10958f707d84SJiri Olsa { 109616fa7e82SJiri Olsa #define CHECK_TYPE_VAL(type) \ 109716fa7e82SJiri Olsa do { \ 10983b0e371cSJiri Olsa if (check_type_val(term, err, PARSE_EVENTS__TERM_TYPE_ ## type)) \ 109916fa7e82SJiri Olsa return -EINVAL; \ 110016fa7e82SJiri Olsa } while (0) 110116fa7e82SJiri Olsa 110216fa7e82SJiri Olsa switch (term->type_term) { 11038f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG: 110416fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 11058f707d84SJiri Olsa attr->config = term->val.num; 11068f707d84SJiri Olsa break; 11078f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG1: 110816fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 11098f707d84SJiri Olsa attr->config1 = term->val.num; 11108f707d84SJiri Olsa break; 11118f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG2: 111216fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 11138f707d84SJiri Olsa attr->config2 = term->val.num; 11148f707d84SJiri Olsa break; 11158f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 111616fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 11178f707d84SJiri Olsa break; 111809af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 111909af2a55SNamhyung Kim CHECK_TYPE_VAL(NUM); 112009af2a55SNamhyung Kim break; 11218f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 1122ac12f676SAndi Kleen CHECK_TYPE_VAL(STR); 1123ac12f676SAndi Kleen if (strcmp(term->val.str, "no") && 1124448d732cSIan Rogers parse_branch_str(term->val.str, 1125448d732cSIan Rogers &attr->branch_sample_type)) { 11266c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1127448d732cSIan Rogers strdup("invalid branch sample type"), 1128448d732cSIan Rogers NULL); 1129ac12f676SAndi Kleen return -EINVAL; 1130ac12f676SAndi Kleen } 11318f707d84SJiri Olsa break; 113232067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 113332067712SKan Liang CHECK_TYPE_VAL(NUM); 113432067712SKan Liang if (term->val.num > 1) { 11356c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1136448d732cSIan Rogers strdup("expected 0 or 1"), 1137448d732cSIan Rogers NULL); 113832067712SKan Liang return -EINVAL; 113932067712SKan Liang } 114032067712SKan Liang break; 1141d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 1142d457c963SKan Liang CHECK_TYPE_VAL(STR); 1143d457c963SKan Liang break; 1144d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1145d457c963SKan Liang CHECK_TYPE_VAL(NUM); 1146d457c963SKan Liang break; 1147374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1148374ce938SWang Nan CHECK_TYPE_VAL(NUM); 1149374ce938SWang Nan break; 1150374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1151374ce938SWang Nan CHECK_TYPE_VAL(NUM); 1152374ce938SWang Nan break; 1153626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1154626a6b78SWang Nan CHECK_TYPE_VAL(NUM); 1155626a6b78SWang Nan break; 1156626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1157626a6b78SWang Nan CHECK_TYPE_VAL(NUM); 1158626a6b78SWang Nan break; 11596b5fc39bSJiri Olsa case PARSE_EVENTS__TERM_TYPE_NAME: 11606b5fc39bSJiri Olsa CHECK_TYPE_VAL(STR); 11616b5fc39bSJiri Olsa break; 11622b62b3a6SIan Rogers case PARSE_EVENTS__TERM_TYPE_METRIC_ID: 11632b62b3a6SIan Rogers CHECK_TYPE_VAL(STR); 11642b62b3a6SIan Rogers break; 1165792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1166792d48b4SArnaldo Carvalho de Melo CHECK_TYPE_VAL(NUM); 1167792d48b4SArnaldo Carvalho de Melo break; 11682fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 11692fda5adaSArnaldo Carvalho de Melo CHECK_TYPE_VAL(NUM); 11702fda5adaSArnaldo Carvalho de Melo break; 1171064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 1172064b4e82SJin Yao CHECK_TYPE_VAL(NUM); 1173064b4e82SJin Yao if ((unsigned int)term->val.num > 1) { 11746c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1175448d732cSIan Rogers strdup("expected 0 or 1"), 1176448d732cSIan Rogers NULL); 1177064b4e82SJin Yao return -EINVAL; 1178064b4e82SJin Yao } 1179064b4e82SJin Yao break; 11801b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 11811b992154SAdrian Hunter CHECK_TYPE_VAL(NUM); 11821b992154SAdrian Hunter break; 1183eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1184eb7a52d4SAdrian Hunter CHECK_TYPE_VAL(NUM); 1185eb7a52d4SAdrian Hunter if (term->val.num > UINT_MAX) { 11866c191289SIan Rogers parse_events_error__handle(err, term->err_val, 1187eb7a52d4SAdrian Hunter strdup("too big"), 1188eb7a52d4SAdrian Hunter NULL); 1189eb7a52d4SAdrian Hunter return -EINVAL; 1190eb7a52d4SAdrian Hunter } 1191eb7a52d4SAdrian Hunter break; 11928f707d84SJiri Olsa default: 11936c191289SIan Rogers parse_events_error__handle(err, term->err_term, 1194448d732cSIan Rogers strdup("unknown term"), 1195448d732cSIan Rogers parse_events_formats_error_string(NULL)); 11968f707d84SJiri Olsa return -EINVAL; 11978f707d84SJiri Olsa } 119816fa7e82SJiri Olsa 11991669e509SWang Nan /* 12004d39c89fSIngo Molnar * Check term availability after basic checking so 12011669e509SWang Nan * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered. 12021669e509SWang Nan * 12034d39c89fSIngo Molnar * If check availability at the entry of this function, 12041669e509SWang Nan * user will see "'<sysfs term>' is not usable in 'perf stat'" 12051669e509SWang Nan * if an invalid config term is provided for legacy events 12061669e509SWang Nan * (for example, instructions/badterm/...), which is confusing. 12071669e509SWang Nan */ 12081669e509SWang Nan if (!config_term_avail(term->type_term, err)) 12091669e509SWang Nan return -EINVAL; 12108f707d84SJiri Olsa return 0; 121116fa7e82SJiri Olsa #undef CHECK_TYPE_VAL 12128f707d84SJiri Olsa } 12138f707d84SJiri Olsa 12140b8891a8SHe Kuang static int config_term_pmu(struct perf_event_attr *attr, 12150b8891a8SHe Kuang struct parse_events_term *term, 12160b8891a8SHe Kuang struct parse_events_error *err) 12170b8891a8SHe Kuang { 1218dd60fba7SMathieu Poirier if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER || 1219dd60fba7SMathieu Poirier term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG) 12200b8891a8SHe Kuang /* 12210b8891a8SHe Kuang * Always succeed for sysfs terms, as we dont know 12220b8891a8SHe Kuang * at this point what type they need to have. 12230b8891a8SHe Kuang */ 12240b8891a8SHe Kuang return 0; 12250b8891a8SHe Kuang else 12260b8891a8SHe Kuang return config_term_common(attr, term, err); 12270b8891a8SHe Kuang } 12280b8891a8SHe Kuang 1229e637d177SHe Kuang static int config_term_tracepoint(struct perf_event_attr *attr, 1230e637d177SHe Kuang struct parse_events_term *term, 1231e637d177SHe Kuang struct parse_events_error *err) 1232e637d177SHe Kuang { 1233e637d177SHe Kuang switch (term->type_term) { 1234e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 1235e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1236374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1237374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1238792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 12392fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1240626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1241626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 12421b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 1243eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1244e637d177SHe Kuang return config_term_common(attr, term, err); 1245e637d177SHe Kuang default: 1246e637d177SHe Kuang if (err) { 12476c191289SIan Rogers parse_events_error__handle(err, term->err_term, 1248448d732cSIan Rogers strdup("unknown term"), 1249448d732cSIan Rogers strdup("valid terms: call-graph,stack-size\n")); 1250e637d177SHe Kuang } 1251e637d177SHe Kuang return -EINVAL; 1252e637d177SHe Kuang } 1253e637d177SHe Kuang 1254e637d177SHe Kuang return 0; 1255e637d177SHe Kuang } 1256e637d177SHe Kuang 12578f707d84SJiri Olsa static int config_attr(struct perf_event_attr *attr, 12583b0e371cSJiri Olsa struct list_head *head, 12590b8891a8SHe Kuang struct parse_events_error *err, 12600b8891a8SHe Kuang config_term_func_t config_term) 12618f707d84SJiri Olsa { 12626cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 12638f707d84SJiri Olsa 12648f707d84SJiri Olsa list_for_each_entry(term, head, list) 12653b0e371cSJiri Olsa if (config_term(attr, term, err)) 12668f707d84SJiri Olsa return -EINVAL; 12678f707d84SJiri Olsa 12688f707d84SJiri Olsa return 0; 12698f707d84SJiri Olsa } 12708f707d84SJiri Olsa 1271930a2e29SJiri Olsa static int get_config_terms(struct list_head *head_config, 1272930a2e29SJiri Olsa struct list_head *head_terms __maybe_unused) 1273930a2e29SJiri Olsa { 127405e54e23SIan Rogers #define ADD_CONFIG_TERM(__type, __weak) \ 127535ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *__t; \ 1276930a2e29SJiri Olsa \ 1277930a2e29SJiri Olsa __t = zalloc(sizeof(*__t)); \ 1278930a2e29SJiri Olsa if (!__t) \ 1279930a2e29SJiri Olsa return -ENOMEM; \ 1280930a2e29SJiri Olsa \ 1281930a2e29SJiri Olsa INIT_LIST_HEAD(&__t->list); \ 128235ac0cadSArnaldo Carvalho de Melo __t->type = EVSEL__CONFIG_TERM_ ## __type; \ 128305e54e23SIan Rogers __t->weak = __weak; \ 1284e884602bSLeo Yan list_add_tail(&__t->list, head_terms) 1285e884602bSLeo Yan 128605e54e23SIan Rogers #define ADD_CONFIG_TERM_VAL(__type, __name, __val, __weak) \ 1287e884602bSLeo Yan do { \ 128805e54e23SIan Rogers ADD_CONFIG_TERM(__type, __weak); \ 1289e884602bSLeo Yan __t->val.__name = __val; \ 1290e884602bSLeo Yan } while (0) 1291e884602bSLeo Yan 129205e54e23SIan Rogers #define ADD_CONFIG_TERM_STR(__type, __val, __weak) \ 1293e884602bSLeo Yan do { \ 129405e54e23SIan Rogers ADD_CONFIG_TERM(__type, __weak); \ 12953220fb8dSLeo Yan __t->val.str = strdup(__val); \ 12963220fb8dSLeo Yan if (!__t->val.str) { \ 12973220fb8dSLeo Yan zfree(&__t); \ 12983220fb8dSLeo Yan return -ENOMEM; \ 12993220fb8dSLeo Yan } \ 13003220fb8dSLeo Yan __t->free_str = true; \ 1301930a2e29SJiri Olsa } while (0) 1302930a2e29SJiri Olsa 1303930a2e29SJiri Olsa struct parse_events_term *term; 1304930a2e29SJiri Olsa 1305930a2e29SJiri Olsa list_for_each_entry(term, head_config, list) { 1306930a2e29SJiri Olsa switch (term->type_term) { 1307ee4c7588SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 130805e54e23SIan Rogers ADD_CONFIG_TERM_VAL(PERIOD, period, term->val.num, term->weak); 130932067712SKan Liang break; 131009af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 131105e54e23SIan Rogers ADD_CONFIG_TERM_VAL(FREQ, freq, term->val.num, term->weak); 131209af2a55SNamhyung Kim break; 131332067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 131405e54e23SIan Rogers ADD_CONFIG_TERM_VAL(TIME, time, term->val.num, term->weak); 131532067712SKan Liang break; 1316d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 131705e54e23SIan Rogers ADD_CONFIG_TERM_STR(CALLGRAPH, term->val.str, term->weak); 1318d457c963SKan Liang break; 1319ac12f676SAndi Kleen case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 132005e54e23SIan Rogers ADD_CONFIG_TERM_STR(BRANCH, term->val.str, term->weak); 1321ac12f676SAndi Kleen break; 1322d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1323e884602bSLeo Yan ADD_CONFIG_TERM_VAL(STACK_USER, stack_user, 132405e54e23SIan Rogers term->val.num, term->weak); 1325d457c963SKan Liang break; 1326374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1327e884602bSLeo Yan ADD_CONFIG_TERM_VAL(INHERIT, inherit, 132805e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 1329374ce938SWang Nan break; 1330374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1331e884602bSLeo Yan ADD_CONFIG_TERM_VAL(INHERIT, inherit, 133205e54e23SIan Rogers term->val.num ? 0 : 1, term->weak); 1333374ce938SWang Nan break; 1334792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1335e884602bSLeo Yan ADD_CONFIG_TERM_VAL(MAX_STACK, max_stack, 133605e54e23SIan Rogers term->val.num, term->weak); 1337792d48b4SArnaldo Carvalho de Melo break; 13382fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1339e884602bSLeo Yan ADD_CONFIG_TERM_VAL(MAX_EVENTS, max_events, 134005e54e23SIan Rogers term->val.num, term->weak); 13412fda5adaSArnaldo Carvalho de Melo break; 1342626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1343e884602bSLeo Yan ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 134405e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 1345626a6b78SWang Nan break; 1346626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1347e884602bSLeo Yan ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 134805e54e23SIan Rogers term->val.num ? 0 : 1, term->weak); 1349626a6b78SWang Nan break; 1350dd60fba7SMathieu Poirier case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 135105e54e23SIan Rogers ADD_CONFIG_TERM_STR(DRV_CFG, term->val.str, term->weak); 1352dd60fba7SMathieu Poirier break; 1353064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 1354e884602bSLeo Yan ADD_CONFIG_TERM_VAL(PERCORE, percore, 135505e54e23SIan Rogers term->val.num ? true : false, term->weak); 1356064b4e82SJin Yao break; 13571b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 1358e884602bSLeo Yan ADD_CONFIG_TERM_VAL(AUX_OUTPUT, aux_output, 135905e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 13601b992154SAdrian Hunter break; 1361eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1362e884602bSLeo Yan ADD_CONFIG_TERM_VAL(AUX_SAMPLE_SIZE, aux_sample_size, 136305e54e23SIan Rogers term->val.num, term->weak); 1364eb7a52d4SAdrian Hunter break; 1365930a2e29SJiri Olsa default: 1366930a2e29SJiri Olsa break; 1367930a2e29SJiri Olsa } 1368930a2e29SJiri Olsa } 1369a1ac7de6SAdrian Hunter return 0; 1370a1ac7de6SAdrian Hunter } 1371a1ac7de6SAdrian Hunter 1372a1ac7de6SAdrian Hunter /* 137335ac0cadSArnaldo Carvalho de Melo * Add EVSEL__CONFIG_TERM_CFG_CHG where cfg_chg will have a bit set for 1374a1ac7de6SAdrian Hunter * each bit of attr->config that the user has changed. 1375a1ac7de6SAdrian Hunter */ 1376a1ac7de6SAdrian Hunter static int get_config_chgs(struct perf_pmu *pmu, struct list_head *head_config, 1377a1ac7de6SAdrian Hunter struct list_head *head_terms) 1378a1ac7de6SAdrian Hunter { 1379a1ac7de6SAdrian Hunter struct parse_events_term *term; 1380a1ac7de6SAdrian Hunter u64 bits = 0; 1381a1ac7de6SAdrian Hunter int type; 1382a1ac7de6SAdrian Hunter 1383a1ac7de6SAdrian Hunter list_for_each_entry(term, head_config, list) { 1384a1ac7de6SAdrian Hunter switch (term->type_term) { 1385a1ac7de6SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_USER: 1386a1ac7de6SAdrian Hunter type = perf_pmu__format_type(&pmu->format, term->config); 1387a1ac7de6SAdrian Hunter if (type != PERF_PMU_FORMAT_VALUE_CONFIG) 1388a1ac7de6SAdrian Hunter continue; 1389a1ac7de6SAdrian Hunter bits |= perf_pmu__format_bits(&pmu->format, term->config); 1390a1ac7de6SAdrian Hunter break; 1391a1ac7de6SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_CONFIG: 1392a1ac7de6SAdrian Hunter bits = ~(u64)0; 1393a1ac7de6SAdrian Hunter break; 1394a1ac7de6SAdrian Hunter default: 1395a1ac7de6SAdrian Hunter break; 1396a1ac7de6SAdrian Hunter } 1397a1ac7de6SAdrian Hunter } 1398a1ac7de6SAdrian Hunter 1399a1ac7de6SAdrian Hunter if (bits) 140005e54e23SIan Rogers ADD_CONFIG_TERM_VAL(CFG_CHG, cfg_chg, bits, false); 1401a1ac7de6SAdrian Hunter 1402a1ac7de6SAdrian Hunter #undef ADD_CONFIG_TERM 1403930a2e29SJiri Olsa return 0; 1404930a2e29SJiri Olsa } 1405930a2e29SJiri Olsa 1406e637d177SHe Kuang int parse_events_add_tracepoint(struct list_head *list, int *idx, 14078c619d6aSWang Nan const char *sys, const char *event, 1408272ed29aSJiri Olsa struct parse_events_error *err, 1409e637d177SHe Kuang struct list_head *head_config) 1410e637d177SHe Kuang { 1411e637d177SHe Kuang if (head_config) { 1412e637d177SHe Kuang struct perf_event_attr attr; 1413e637d177SHe Kuang 1414272ed29aSJiri Olsa if (config_attr(&attr, head_config, err, 1415e637d177SHe Kuang config_term_tracepoint)) 1416e637d177SHe Kuang return -EINVAL; 1417e637d177SHe Kuang } 1418e637d177SHe Kuang 1419e637d177SHe Kuang if (strpbrk(sys, "*?")) 1420e637d177SHe Kuang return add_tracepoint_multi_sys(list, idx, sys, event, 1421272ed29aSJiri Olsa err, head_config); 1422e637d177SHe Kuang else 1423e637d177SHe Kuang return add_tracepoint_event(list, idx, sys, event, 1424272ed29aSJiri Olsa err, head_config); 1425e637d177SHe Kuang } 1426e637d177SHe Kuang 14275d9cdc11SArnaldo Carvalho de Melo int parse_events_add_numeric(struct parse_events_state *parse_state, 142887d650beSJiri Olsa struct list_head *list, 1429b527bab5SRobert Richter u32 type, u64 config, 14308f707d84SJiri Olsa struct list_head *head_config) 143174d5b588SJaswinder Singh Rajput { 143289812fc8SJiri Olsa struct perf_event_attr attr; 1433930a2e29SJiri Olsa LIST_HEAD(config_terms); 14342b62b3a6SIan Rogers const char *name, *metric_id; 14359cbfa2f6SJin Yao bool hybrid; 14369cbfa2f6SJin Yao int ret; 143774d5b588SJaswinder Singh Rajput 143889812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 143989812fc8SJiri Olsa attr.type = type; 144089812fc8SJiri Olsa attr.config = config; 14418f707d84SJiri Olsa 1442930a2e29SJiri Olsa if (head_config) { 14435d9cdc11SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, parse_state->error, 14440b8891a8SHe Kuang config_term_common)) 14458f707d84SJiri Olsa return -EINVAL; 14468f707d84SJiri Olsa 1447930a2e29SJiri Olsa if (get_config_terms(head_config, &config_terms)) 1448930a2e29SJiri Olsa return -ENOMEM; 1449930a2e29SJiri Olsa } 1450930a2e29SJiri Olsa 14512b62b3a6SIan Rogers name = get_config_name(head_config); 14522b62b3a6SIan Rogers metric_id = get_config_metric_id(head_config); 14539cbfa2f6SJin Yao ret = parse_events__add_numeric_hybrid(parse_state, list, &attr, 14542b62b3a6SIan Rogers name, metric_id, 14559cbfa2f6SJin Yao &config_terms, &hybrid); 14569cbfa2f6SJin Yao if (hybrid) 145799fc5941SAdrian Hunter goto out_free_terms; 14589cbfa2f6SJin Yao 14592b62b3a6SIan Rogers ret = add_event(list, &parse_state->idx, &attr, name, metric_id, 14602b62b3a6SIan Rogers &config_terms); 146199fc5941SAdrian Hunter out_free_terms: 146299fc5941SAdrian Hunter free_config_terms(&config_terms); 146399fc5941SAdrian Hunter return ret; 1464b908debdSIngo Molnar } 1465b908debdSIngo Molnar 1466f0fbb114SAndi Kleen int parse_events_add_tool(struct parse_events_state *parse_state, 1467f0fbb114SAndi Kleen struct list_head *list, 14688228e936SIan Rogers int tool_event) 1469f0fbb114SAndi Kleen { 1470f0fbb114SAndi Kleen return add_event_tool(list, &parse_state->idx, tool_event); 1471f0fbb114SAndi Kleen } 1472f0fbb114SAndi Kleen 1473064b4e82SJin Yao static bool config_term_percore(struct list_head *config_terms) 1474064b4e82SJin Yao { 147535ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *term; 1476064b4e82SJin Yao 1477064b4e82SJin Yao list_for_each_entry(term, config_terms, list) { 147835ac0cadSArnaldo Carvalho de Melo if (term->type == EVSEL__CONFIG_TERM_PERCORE) 1479064b4e82SJin Yao return term->val.percore; 1480064b4e82SJin Yao } 1481064b4e82SJin Yao 1482064b4e82SJin Yao return false; 1483064b4e82SJin Yao } 1484064b4e82SJin Yao 14855e4edd1fSJin Yao static int parse_events__inside_hybrid_pmu(struct parse_events_state *parse_state, 14865e4edd1fSJin Yao struct list_head *list, char *name, 14875e4edd1fSJin Yao struct list_head *head_config) 14885e4edd1fSJin Yao { 14895e4edd1fSJin Yao struct parse_events_term *term; 14905e4edd1fSJin Yao int ret = -1; 14915e4edd1fSJin Yao 14925e4edd1fSJin Yao if (parse_state->fake_pmu || !head_config || list_empty(head_config) || 14935e4edd1fSJin Yao !perf_pmu__is_hybrid(name)) { 14945e4edd1fSJin Yao return -1; 14955e4edd1fSJin Yao } 14965e4edd1fSJin Yao 14975e4edd1fSJin Yao /* 14985e4edd1fSJin Yao * More than one term in list. 14995e4edd1fSJin Yao */ 15005e4edd1fSJin Yao if (head_config->next && head_config->next->next != head_config) 15015e4edd1fSJin Yao return -1; 15025e4edd1fSJin Yao 15035e4edd1fSJin Yao term = list_first_entry(head_config, struct parse_events_term, list); 15045e4edd1fSJin Yao if (term && term->config && strcmp(term->config, "event")) { 15055e4edd1fSJin Yao ret = parse_events__with_hybrid_pmu(parse_state, term->config, 15065e4edd1fSJin Yao name, list); 15075e4edd1fSJin Yao } 15085e4edd1fSJin Yao 15095e4edd1fSJin Yao return ret; 15105e4edd1fSJin Yao } 15115e4edd1fSJin Yao 1512c199c11dSAgustin Vega-Frias int parse_events_add_pmu(struct parse_events_state *parse_state, 151336adec85SJiri Olsa struct list_head *list, char *name, 15143cdc5c2cSKan Liang struct list_head *head_config, 15153cdc5c2cSKan Liang bool auto_merge_stats, 15163cdc5c2cSKan Liang bool use_alias) 15175f537a26SJiri Olsa { 15185f537a26SJiri Olsa struct perf_event_attr attr; 151946441bdcSMatt Fleming struct perf_pmu_info info; 15205f537a26SJiri Olsa struct perf_pmu *pmu; 152132dcd021SJiri Olsa struct evsel *evsel; 1522333b5665SAndi Kleen struct parse_events_error *err = parse_state->error; 15233cdc5c2cSKan Liang bool use_uncore_alias; 1524930a2e29SJiri Olsa LIST_HEAD(config_terms); 15255f537a26SJiri Olsa 15264ac22b48SIan Rogers if (verbose > 1) { 15274ac22b48SIan Rogers fprintf(stderr, "Attempting to add event pmu '%s' with '", 15284ac22b48SIan Rogers name); 15294ac22b48SIan Rogers if (head_config) { 15304ac22b48SIan Rogers struct parse_events_term *term; 15314ac22b48SIan Rogers 15324ac22b48SIan Rogers list_for_each_entry(term, head_config, list) { 15334ac22b48SIan Rogers fprintf(stderr, "%s,", term->config); 15344ac22b48SIan Rogers } 15354ac22b48SIan Rogers } 15364ac22b48SIan Rogers fprintf(stderr, "' that may result in non-fatal errors\n"); 15374ac22b48SIan Rogers } 15384ac22b48SIan Rogers 1539387ad33fSJiri Olsa pmu = parse_state->fake_pmu ?: perf_pmu__find(name); 1540333b5665SAndi Kleen if (!pmu) { 1541448d732cSIan Rogers char *err_str; 1542448d732cSIan Rogers 1543448d732cSIan Rogers if (asprintf(&err_str, 1544333b5665SAndi Kleen "Cannot find PMU `%s'. Missing kernel support?", 1545448d732cSIan Rogers name) >= 0) 15466c191289SIan Rogers parse_events_error__handle(err, 0, err_str, NULL); 15475f537a26SJiri Olsa return -EINVAL; 1548333b5665SAndi Kleen } 15495f537a26SJiri Olsa 1550dc0a6202SAdrian Hunter if (pmu->default_config) { 1551dc0a6202SAdrian Hunter memcpy(&attr, pmu->default_config, 1552dc0a6202SAdrian Hunter sizeof(struct perf_event_attr)); 1553dc0a6202SAdrian Hunter } else { 15545f537a26SJiri Olsa memset(&attr, 0, sizeof(attr)); 1555dc0a6202SAdrian Hunter } 15565f537a26SJiri Olsa 15573cdc5c2cSKan Liang use_uncore_alias = (pmu->is_uncore && use_alias); 15583cdc5c2cSKan Liang 1559ad962273SAdrian Hunter if (!head_config) { 1560ad962273SAdrian Hunter attr.type = pmu->type; 15612b62b3a6SIan Rogers evsel = __add_event(list, &parse_state->idx, &attr, 15622b62b3a6SIan Rogers /*init_attr=*/true, /*name=*/NULL, 15632b62b3a6SIan Rogers /*metric_id=*/NULL, pmu, 15642b62b3a6SIan Rogers /*config_terms=*/NULL, auto_merge_stats, 15652b62b3a6SIan Rogers /*cpu_list=*/NULL); 15668c5421c0SAgustin Vega-Frias if (evsel) { 1567d4953f7eSIan Rogers evsel->pmu_name = name ? strdup(name) : NULL; 15683cdc5c2cSKan Liang evsel->use_uncore_alias = use_uncore_alias; 15698c5421c0SAgustin Vega-Frias return 0; 15708c5421c0SAgustin Vega-Frias } else { 15718c5421c0SAgustin Vega-Frias return -ENOMEM; 15728c5421c0SAgustin Vega-Frias } 1573ad962273SAdrian Hunter } 1574ad962273SAdrian Hunter 1575387ad33fSJiri Olsa if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info)) 1576a6146d50SZheng Yan return -EINVAL; 1577a6146d50SZheng Yan 15784ac22b48SIan Rogers if (verbose > 1) { 15794ac22b48SIan Rogers fprintf(stderr, "After aliases, add event pmu '%s' with '", 15804ac22b48SIan Rogers name); 15814ac22b48SIan Rogers if (head_config) { 15824ac22b48SIan Rogers struct parse_events_term *term; 15834ac22b48SIan Rogers 15844ac22b48SIan Rogers list_for_each_entry(term, head_config, list) { 15854ac22b48SIan Rogers fprintf(stderr, "%s,", term->config); 15864ac22b48SIan Rogers } 15874ac22b48SIan Rogers } 15884ac22b48SIan Rogers fprintf(stderr, "' that may result in non-fatal errors\n"); 15894ac22b48SIan Rogers } 15904ac22b48SIan Rogers 15915f537a26SJiri Olsa /* 15925f537a26SJiri Olsa * Configure hardcoded terms first, no need to check 15935f537a26SJiri Olsa * return value when called with fail == 0 ;) 15945f537a26SJiri Olsa */ 15955d9cdc11SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, parse_state->error, config_term_pmu)) 1596c056ba6aSJiri Olsa return -EINVAL; 15975f537a26SJiri Olsa 1598930a2e29SJiri Olsa if (get_config_terms(head_config, &config_terms)) 1599930a2e29SJiri Olsa return -ENOMEM; 1600930a2e29SJiri Olsa 1601a1ac7de6SAdrian Hunter /* 1602a1ac7de6SAdrian Hunter * When using default config, record which bits of attr->config were 1603a1ac7de6SAdrian Hunter * changed by the user. 1604a1ac7de6SAdrian Hunter */ 1605a1ac7de6SAdrian Hunter if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms)) 1606a1ac7de6SAdrian Hunter return -ENOMEM; 1607a1ac7de6SAdrian Hunter 16085e4edd1fSJin Yao if (!parse_events__inside_hybrid_pmu(parse_state, list, name, 16095e4edd1fSJin Yao head_config)) { 16105e4edd1fSJin Yao return 0; 16115e4edd1fSJin Yao } 16125e4edd1fSJin Yao 1613387ad33fSJiri Olsa if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { 1614a7d212fcSAdrian Hunter free_config_terms(&config_terms); 16155f537a26SJiri Olsa return -EINVAL; 161638f2c422SIan Rogers } 16175f537a26SJiri Olsa 16182b62b3a6SIan Rogers evsel = __add_event(list, &parse_state->idx, &attr, /*init_attr=*/true, 16192b62b3a6SIan Rogers get_config_name(head_config), 16202b62b3a6SIan Rogers get_config_metric_id(head_config), pmu, 16212b62b3a6SIan Rogers &config_terms, auto_merge_stats, /*cpu_list=*/NULL); 162233321a06SIan Rogers if (!evsel) 162333321a06SIan Rogers return -ENOMEM; 162433321a06SIan Rogers 162512279429SJin Yao if (evsel->name) 162612279429SJin Yao evsel->use_config_name = true; 162712279429SJin Yao 162833321a06SIan Rogers evsel->pmu_name = name ? strdup(name) : NULL; 162933321a06SIan Rogers evsel->use_uncore_alias = use_uncore_alias; 163033321a06SIan Rogers evsel->percore = config_term_percore(&evsel->config_terms); 163133321a06SIan Rogers 163233321a06SIan Rogers if (parse_state->fake_pmu) 163333321a06SIan Rogers return 0; 163433321a06SIan Rogers 1635b194c9cdSIan Rogers free((char *)evsel->unit); 1636b194c9cdSIan Rogers evsel->unit = strdup(info.unit); 163746441bdcSMatt Fleming evsel->scale = info.scale; 1638044330c1SMatt Fleming evsel->per_pkg = info.per_pkg; 16391d9e446bSJiri Olsa evsel->snapshot = info.snapshot; 164037932c18SAndi Kleen evsel->metric_expr = info.metric_expr; 164196284814SAndi Kleen evsel->metric_name = info.metric_name; 164233321a06SIan Rogers return 0; 16435f537a26SJiri Olsa } 16445f537a26SJiri Olsa 16455d9cdc11SArnaldo Carvalho de Melo int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 1646fb081153SIan Rogers char *str, struct list_head *head, 1647fb081153SIan Rogers struct list_head **listp) 16482073ad33SAndi Kleen { 16492073ad33SAndi Kleen struct parse_events_term *term; 1650fb081153SIan Rogers struct list_head *list = NULL; 16512073ad33SAndi Kleen struct perf_pmu *pmu = NULL; 16522073ad33SAndi Kleen int ok = 0; 1653fb081153SIan Rogers char *config; 16542073ad33SAndi Kleen 16552073ad33SAndi Kleen *listp = NULL; 1656fb081153SIan Rogers 1657fb081153SIan Rogers if (!head) { 1658fb081153SIan Rogers head = malloc(sizeof(struct list_head)); 1659fb081153SIan Rogers if (!head) 1660fb081153SIan Rogers goto out_err; 1661fb081153SIan Rogers 1662fb081153SIan Rogers INIT_LIST_HEAD(head); 1663fb081153SIan Rogers } 1664fb081153SIan Rogers config = strdup(str); 1665fb081153SIan Rogers if (!config) 1666fb081153SIan Rogers goto out_err; 1667fb081153SIan Rogers 1668fb081153SIan Rogers if (parse_events_term__num(&term, 1669fb081153SIan Rogers PARSE_EVENTS__TERM_TYPE_USER, 1670fb081153SIan Rogers config, 1, false, &config, 1671fb081153SIan Rogers NULL) < 0) { 1672fb081153SIan Rogers free(config); 1673fb081153SIan Rogers goto out_err; 1674fb081153SIan Rogers } 1675fb081153SIan Rogers list_add_tail(&term->list, head); 1676fb081153SIan Rogers 1677fb081153SIan Rogers 16782073ad33SAndi Kleen /* Add it for all PMUs that support the alias */ 16792073ad33SAndi Kleen list = malloc(sizeof(struct list_head)); 16802073ad33SAndi Kleen if (!list) 1681fb081153SIan Rogers goto out_err; 1682fb081153SIan Rogers 16832073ad33SAndi Kleen INIT_LIST_HEAD(list); 1684fb081153SIan Rogers 16852073ad33SAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 16862073ad33SAndi Kleen struct perf_pmu_alias *alias; 16872073ad33SAndi Kleen 16882073ad33SAndi Kleen list_for_each_entry(alias, &pmu->aliases, list) { 16892073ad33SAndi Kleen if (!strcasecmp(alias->name, str)) { 1690c199c11dSAgustin Vega-Frias if (!parse_events_add_pmu(parse_state, list, 16913cdc5c2cSKan Liang pmu->name, head, 16923cdc5c2cSKan Liang true, true)) { 1693d4953f7eSIan Rogers pr_debug("%s -> %s/%s/\n", str, 16942073ad33SAndi Kleen pmu->name, alias->str); 16952073ad33SAndi Kleen ok++; 16962073ad33SAndi Kleen } 1697fb081153SIan Rogers } 1698fb081153SIan Rogers } 1699fb081153SIan Rogers } 1700b4a7276cSJohn Garry 1701b4a7276cSJohn Garry if (parse_state->fake_pmu) { 1702b4a7276cSJohn Garry if (!parse_events_add_pmu(parse_state, list, str, head, 1703b4a7276cSJohn Garry true, true)) { 1704b4a7276cSJohn Garry pr_debug("%s -> %s/%s/\n", str, "fake_pmu", str); 1705b4a7276cSJohn Garry ok++; 1706b4a7276cSJohn Garry } 1707b4a7276cSJohn Garry } 1708b4a7276cSJohn Garry 1709fb081153SIan Rogers out_err: 1710fb081153SIan Rogers if (ok) 1711fb081153SIan Rogers *listp = list; 1712fb081153SIan Rogers else 1713fb081153SIan Rogers free(list); 17142073ad33SAndi Kleen 17152073ad33SAndi Kleen parse_events_terms__delete(head); 1716fb081153SIan Rogers return ok ? 0 : -1; 17172073ad33SAndi Kleen } 17182073ad33SAndi Kleen 17196a4bb04cSJiri Olsa int parse_events__modifier_group(struct list_head *list, 17206a4bb04cSJiri Olsa char *event_mod) 172189efb029SJiri Olsa { 17226a4bb04cSJiri Olsa return parse_events__modifier_event(list, event_mod, true); 17236a4bb04cSJiri Olsa } 17246a4bb04cSJiri Olsa 17253cdc5c2cSKan Liang /* 17263cdc5c2cSKan Liang * Check if the two uncore PMUs are from the same uncore block 17273cdc5c2cSKan Liang * The format of the uncore PMU name is uncore_#blockname_#pmuidx 17283cdc5c2cSKan Liang */ 17293cdc5c2cSKan Liang static bool is_same_uncore_block(const char *pmu_name_a, const char *pmu_name_b) 17303cdc5c2cSKan Liang { 17313cdc5c2cSKan Liang char *end_a, *end_b; 17323cdc5c2cSKan Liang 17333cdc5c2cSKan Liang end_a = strrchr(pmu_name_a, '_'); 17343cdc5c2cSKan Liang end_b = strrchr(pmu_name_b, '_'); 17353cdc5c2cSKan Liang 17363cdc5c2cSKan Liang if (!end_a || !end_b) 17373cdc5c2cSKan Liang return false; 17383cdc5c2cSKan Liang 17393cdc5c2cSKan Liang if ((end_a - pmu_name_a) != (end_b - pmu_name_b)) 17403cdc5c2cSKan Liang return false; 17413cdc5c2cSKan Liang 17423cdc5c2cSKan Liang return (strncmp(pmu_name_a, pmu_name_b, end_a - pmu_name_a) == 0); 17433cdc5c2cSKan Liang } 17443cdc5c2cSKan Liang 17453cdc5c2cSKan Liang static int 17463cdc5c2cSKan Liang parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, 17473cdc5c2cSKan Liang struct parse_events_state *parse_state) 17483cdc5c2cSKan Liang { 174932dcd021SJiri Olsa struct evsel *evsel, *leader; 17503cdc5c2cSKan Liang uintptr_t *leaders; 17513cdc5c2cSKan Liang bool is_leader = true; 17523cdc5c2cSKan Liang int i, nr_pmu = 0, total_members, ret = 0; 17533cdc5c2cSKan Liang 1754b27c4eceSJiri Olsa leader = list_first_entry(list, struct evsel, core.node); 1755b27c4eceSJiri Olsa evsel = list_last_entry(list, struct evsel, core.node); 175638fe0e01SJiri Olsa total_members = evsel->core.idx - leader->core.idx + 1; 17573cdc5c2cSKan Liang 17583cdc5c2cSKan Liang leaders = calloc(total_members, sizeof(uintptr_t)); 17593cdc5c2cSKan Liang if (WARN_ON(!leaders)) 17603cdc5c2cSKan Liang return 0; 17613cdc5c2cSKan Liang 17623cdc5c2cSKan Liang /* 17633cdc5c2cSKan Liang * Going through the whole group and doing sanity check. 17643cdc5c2cSKan Liang * All members must use alias, and be from the same uncore block. 17653cdc5c2cSKan Liang * Also, storing the leader events in an array. 17663cdc5c2cSKan Liang */ 17673cdc5c2cSKan Liang __evlist__for_each_entry(list, evsel) { 17683cdc5c2cSKan Liang 17693cdc5c2cSKan Liang /* Only split the uncore group which members use alias */ 17703cdc5c2cSKan Liang if (!evsel->use_uncore_alias) 17713cdc5c2cSKan Liang goto out; 17723cdc5c2cSKan Liang 17733cdc5c2cSKan Liang /* The events must be from the same uncore block */ 17743cdc5c2cSKan Liang if (!is_same_uncore_block(leader->pmu_name, evsel->pmu_name)) 17753cdc5c2cSKan Liang goto out; 17763cdc5c2cSKan Liang 17773cdc5c2cSKan Liang if (!is_leader) 17783cdc5c2cSKan Liang continue; 17793cdc5c2cSKan Liang /* 17803cdc5c2cSKan Liang * If the event's PMU name starts to repeat, it must be a new 17813cdc5c2cSKan Liang * event. That can be used to distinguish the leader from 17823cdc5c2cSKan Liang * other members, even they have the same event name. 17833cdc5c2cSKan Liang */ 17848510895bSJin Yao if ((leader != evsel) && 17858510895bSJin Yao !strcmp(leader->pmu_name, evsel->pmu_name)) { 17863cdc5c2cSKan Liang is_leader = false; 17873cdc5c2cSKan Liang continue; 17883cdc5c2cSKan Liang } 17893cdc5c2cSKan Liang 17903cdc5c2cSKan Liang /* Store the leader event for each PMU */ 17913cdc5c2cSKan Liang leaders[nr_pmu++] = (uintptr_t) evsel; 17923cdc5c2cSKan Liang } 17933cdc5c2cSKan Liang 17943cdc5c2cSKan Liang /* only one event alias */ 17953cdc5c2cSKan Liang if (nr_pmu == total_members) { 17963cdc5c2cSKan Liang parse_state->nr_groups--; 17973cdc5c2cSKan Liang goto handled; 17983cdc5c2cSKan Liang } 17993cdc5c2cSKan Liang 18003cdc5c2cSKan Liang /* 18013cdc5c2cSKan Liang * An uncore event alias is a joint name which means the same event 18023cdc5c2cSKan Liang * runs on all PMUs of a block. 18033cdc5c2cSKan Liang * Perf doesn't support mixed events from different PMUs in the same 18043cdc5c2cSKan Liang * group. The big group has to be split into multiple small groups 18053cdc5c2cSKan Liang * which only include the events from the same PMU. 18063cdc5c2cSKan Liang * 18073cdc5c2cSKan Liang * Here the uncore event aliases must be from the same uncore block. 18083cdc5c2cSKan Liang * The number of PMUs must be same for each alias. The number of new 18093cdc5c2cSKan Liang * small groups equals to the number of PMUs. 18103cdc5c2cSKan Liang * Setting the leader event for corresponding members in each group. 18113cdc5c2cSKan Liang */ 18123cdc5c2cSKan Liang i = 0; 18133cdc5c2cSKan Liang __evlist__for_each_entry(list, evsel) { 18143cdc5c2cSKan Liang if (i >= nr_pmu) 18153cdc5c2cSKan Liang i = 0; 1816fba7c866SJiri Olsa evsel__set_leader(evsel, (struct evsel *) leaders[i++]); 18173cdc5c2cSKan Liang } 18183cdc5c2cSKan Liang 18193cdc5c2cSKan Liang /* The number of members and group name are same for each group */ 18203cdc5c2cSKan Liang for (i = 0; i < nr_pmu; i++) { 182132dcd021SJiri Olsa evsel = (struct evsel *) leaders[i]; 18225643b1a5SJiri Olsa evsel->core.nr_members = total_members / nr_pmu; 18233cdc5c2cSKan Liang evsel->group_name = name ? strdup(name) : NULL; 18243cdc5c2cSKan Liang } 18253cdc5c2cSKan Liang 18263cdc5c2cSKan Liang /* Take the new small groups into account */ 18273cdc5c2cSKan Liang parse_state->nr_groups += nr_pmu - 1; 18283cdc5c2cSKan Liang 18293cdc5c2cSKan Liang handled: 18303cdc5c2cSKan Liang ret = 1; 18313cdc5c2cSKan Liang out: 18323cdc5c2cSKan Liang free(leaders); 18333cdc5c2cSKan Liang return ret; 18343cdc5c2cSKan Liang } 18353cdc5c2cSKan Liang 183694dbfd67SIan Rogers __weak struct evsel *arch_evlist__leader(struct list_head *list) 183794dbfd67SIan Rogers { 183894dbfd67SIan Rogers return list_first_entry(list, struct evsel, core.node); 183994dbfd67SIan Rogers } 184094dbfd67SIan Rogers 18413cdc5c2cSKan Liang void parse_events__set_leader(char *name, struct list_head *list, 18423cdc5c2cSKan Liang struct parse_events_state *parse_state) 18436a4bb04cSJiri Olsa { 184432dcd021SJiri Olsa struct evsel *leader; 18456a4bb04cSJiri Olsa 1846854f7363SWang Nan if (list_empty(list)) { 1847854f7363SWang Nan WARN_ONCE(true, "WARNING: failed to set leader: empty list"); 1848854f7363SWang Nan return; 1849854f7363SWang Nan } 1850854f7363SWang Nan 18513cdc5c2cSKan Liang if (parse_events__set_leader_for_uncore_aliase(name, list, parse_state)) 18523cdc5c2cSKan Liang return; 18533cdc5c2cSKan Liang 185494dbfd67SIan Rogers leader = arch_evlist__leader(list); 1855ecdcf630SIan Rogers __perf_evlist__set_leader(list, &leader->core); 18566a4bb04cSJiri Olsa leader->group_name = name ? strdup(name) : NULL; 185794dbfd67SIan Rogers list_move(&leader->core.node, list); 185889efb029SJiri Olsa } 185989efb029SJiri Olsa 1860c5cd8ac0SDavid Ahern /* list_event is assumed to point to malloc'ed memory */ 18615d7be90eSJiri Olsa void parse_events_update_lists(struct list_head *list_event, 18625d7be90eSJiri Olsa struct list_head *list_all) 18635d7be90eSJiri Olsa { 18645d7be90eSJiri Olsa /* 18655d7be90eSJiri Olsa * Called for single event definition. Update the 186689efb029SJiri Olsa * 'all event' list, and reinit the 'single event' 18675d7be90eSJiri Olsa * list, for next event definition. 18685d7be90eSJiri Olsa */ 18695d7be90eSJiri Olsa list_splice_tail(list_event, list_all); 1870b847cbdcSJiri Olsa free(list_event); 18715d7be90eSJiri Olsa } 18725d7be90eSJiri Olsa 1873f5b1135bSJiri Olsa struct event_modifier { 1874f5b1135bSJiri Olsa int eu; 1875f5b1135bSJiri Olsa int ek; 1876f5b1135bSJiri Olsa int eh; 1877f5b1135bSJiri Olsa int eH; 1878f5b1135bSJiri Olsa int eG; 1879a1e12da4SJiri Olsa int eI; 1880f5b1135bSJiri Olsa int precise; 18817f94af7aSJiri Olsa int precise_max; 1882f5b1135bSJiri Olsa int exclude_GH; 18833c176311SJiri Olsa int sample_read; 1884e9a7c414SMichael Ellerman int pinned; 18855a5dfe4bSAndi Kleen int weak; 18860997a266SAndi Kleen int exclusive; 188701bd8efcSSong Liu int bpf_counter; 1888f5b1135bSJiri Olsa }; 188961c45981SPaul Mackerras 1890f5b1135bSJiri Olsa static int get_event_modifier(struct event_modifier *mod, char *str, 189132dcd021SJiri Olsa struct evsel *evsel) 1892f5b1135bSJiri Olsa { 18931fc632ceSJiri Olsa int eu = evsel ? evsel->core.attr.exclude_user : 0; 18941fc632ceSJiri Olsa int ek = evsel ? evsel->core.attr.exclude_kernel : 0; 18951fc632ceSJiri Olsa int eh = evsel ? evsel->core.attr.exclude_hv : 0; 18961fc632ceSJiri Olsa int eH = evsel ? evsel->core.attr.exclude_host : 0; 18971fc632ceSJiri Olsa int eG = evsel ? evsel->core.attr.exclude_guest : 0; 18981fc632ceSJiri Olsa int eI = evsel ? evsel->core.attr.exclude_idle : 0; 18991fc632ceSJiri Olsa int precise = evsel ? evsel->core.attr.precise_ip : 0; 19007f94af7aSJiri Olsa int precise_max = 0; 19013c176311SJiri Olsa int sample_read = 0; 19021fc632ceSJiri Olsa int pinned = evsel ? evsel->core.attr.pinned : 0; 19030997a266SAndi Kleen int exclusive = evsel ? evsel->core.attr.exclusive : 0; 1904f5b1135bSJiri Olsa 1905f5b1135bSJiri Olsa int exclude = eu | ek | eh; 1906f5b1135bSJiri Olsa int exclude_GH = evsel ? evsel->exclude_GH : 0; 19075a5dfe4bSAndi Kleen int weak = 0; 190801bd8efcSSong Liu int bpf_counter = 0; 1909f5b1135bSJiri Olsa 1910f5b1135bSJiri Olsa memset(mod, 0, sizeof(*mod)); 1911ceb53fbfSIngo Molnar 191261c45981SPaul Mackerras while (*str) { 1913ab608344SPeter Zijlstra if (*str == 'u') { 1914ab608344SPeter Zijlstra if (!exclude) 1915ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 1916943b69acSJin Yao if (!exclude_GH && !perf_guest) 1917943b69acSJin Yao eG = 1; 191861c45981SPaul Mackerras eu = 0; 1919ab608344SPeter Zijlstra } else if (*str == 'k') { 1920ab608344SPeter Zijlstra if (!exclude) 1921ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 192261c45981SPaul Mackerras ek = 0; 1923ab608344SPeter Zijlstra } else if (*str == 'h') { 1924ab608344SPeter Zijlstra if (!exclude) 1925ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 192661c45981SPaul Mackerras eh = 0; 192799320cc8SJoerg Roedel } else if (*str == 'G') { 192899320cc8SJoerg Roedel if (!exclude_GH) 192999320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 193099320cc8SJoerg Roedel eG = 0; 193199320cc8SJoerg Roedel } else if (*str == 'H') { 193299320cc8SJoerg Roedel if (!exclude_GH) 193399320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 193499320cc8SJoerg Roedel eH = 0; 1935a1e12da4SJiri Olsa } else if (*str == 'I') { 1936a1e12da4SJiri Olsa eI = 1; 1937ab608344SPeter Zijlstra } else if (*str == 'p') { 1938ab608344SPeter Zijlstra precise++; 19391342798cSDavid Ahern /* use of precise requires exclude_guest */ 19401342798cSDavid Ahern if (!exclude_GH) 19411342798cSDavid Ahern eG = 1; 19427f94af7aSJiri Olsa } else if (*str == 'P') { 19437f94af7aSJiri Olsa precise_max = 1; 19443c176311SJiri Olsa } else if (*str == 'S') { 19453c176311SJiri Olsa sample_read = 1; 1946e9a7c414SMichael Ellerman } else if (*str == 'D') { 1947e9a7c414SMichael Ellerman pinned = 1; 19480997a266SAndi Kleen } else if (*str == 'e') { 19490997a266SAndi Kleen exclusive = 1; 19505a5dfe4bSAndi Kleen } else if (*str == 'W') { 19515a5dfe4bSAndi Kleen weak = 1; 195201bd8efcSSong Liu } else if (*str == 'b') { 195301bd8efcSSong Liu bpf_counter = 1; 1954ab608344SPeter Zijlstra } else 195561c45981SPaul Mackerras break; 1956ab608344SPeter Zijlstra 195761c45981SPaul Mackerras ++str; 195861c45981SPaul Mackerras } 195974d5b588SJaswinder Singh Rajput 196086470930SIngo Molnar /* 196189812fc8SJiri Olsa * precise ip: 196289812fc8SJiri Olsa * 196389812fc8SJiri Olsa * 0 - SAMPLE_IP can have arbitrary skid 196489812fc8SJiri Olsa * 1 - SAMPLE_IP must have constant skid 196589812fc8SJiri Olsa * 2 - SAMPLE_IP requested to have 0 skid 196689812fc8SJiri Olsa * 3 - SAMPLE_IP must have 0 skid 196789812fc8SJiri Olsa * 196889812fc8SJiri Olsa * See also PERF_RECORD_MISC_EXACT_IP 196986470930SIngo Molnar */ 197089812fc8SJiri Olsa if (precise > 3) 197189812fc8SJiri Olsa return -EINVAL; 197286470930SIngo Molnar 1973f5b1135bSJiri Olsa mod->eu = eu; 1974f5b1135bSJiri Olsa mod->ek = ek; 1975f5b1135bSJiri Olsa mod->eh = eh; 1976f5b1135bSJiri Olsa mod->eH = eH; 1977f5b1135bSJiri Olsa mod->eG = eG; 1978a1e12da4SJiri Olsa mod->eI = eI; 1979f5b1135bSJiri Olsa mod->precise = precise; 19807f94af7aSJiri Olsa mod->precise_max = precise_max; 1981f5b1135bSJiri Olsa mod->exclude_GH = exclude_GH; 19823c176311SJiri Olsa mod->sample_read = sample_read; 1983e9a7c414SMichael Ellerman mod->pinned = pinned; 19845a5dfe4bSAndi Kleen mod->weak = weak; 198501bd8efcSSong Liu mod->bpf_counter = bpf_counter; 19860997a266SAndi Kleen mod->exclusive = exclusive; 1987e9a7c414SMichael Ellerman 1988f5b1135bSJiri Olsa return 0; 1989f5b1135bSJiri Olsa } 1990f5b1135bSJiri Olsa 1991534123f4SJiri Olsa /* 1992534123f4SJiri Olsa * Basic modifier sanity check to validate it contains only one 1993534123f4SJiri Olsa * instance of any modifier (apart from 'p') present. 1994534123f4SJiri Olsa */ 1995534123f4SJiri Olsa static int check_modifier(char *str) 1996534123f4SJiri Olsa { 1997534123f4SJiri Olsa char *p = str; 1998534123f4SJiri Olsa 1999534123f4SJiri Olsa /* The sizeof includes 0 byte as well. */ 200001bd8efcSSong Liu if (strlen(str) > (sizeof("ukhGHpppPSDIWeb") - 1)) 2001534123f4SJiri Olsa return -1; 2002534123f4SJiri Olsa 2003534123f4SJiri Olsa while (*p) { 2004534123f4SJiri Olsa if (*p != 'p' && strchr(p + 1, *p)) 2005534123f4SJiri Olsa return -1; 2006534123f4SJiri Olsa p++; 2007534123f4SJiri Olsa } 2008534123f4SJiri Olsa 2009534123f4SJiri Olsa return 0; 2010534123f4SJiri Olsa } 2011534123f4SJiri Olsa 2012f5b1135bSJiri Olsa int parse_events__modifier_event(struct list_head *list, char *str, bool add) 2013f5b1135bSJiri Olsa { 201432dcd021SJiri Olsa struct evsel *evsel; 2015f5b1135bSJiri Olsa struct event_modifier mod; 2016f5b1135bSJiri Olsa 2017f5b1135bSJiri Olsa if (str == NULL) 2018f5b1135bSJiri Olsa return 0; 2019f5b1135bSJiri Olsa 2020534123f4SJiri Olsa if (check_modifier(str)) 2021534123f4SJiri Olsa return -EINVAL; 2022534123f4SJiri Olsa 2023f5b1135bSJiri Olsa if (!add && get_event_modifier(&mod, str, NULL)) 2024f5b1135bSJiri Olsa return -EINVAL; 2025f5b1135bSJiri Olsa 2026e5cadb93SArnaldo Carvalho de Melo __evlist__for_each_entry(list, evsel) { 2027f5b1135bSJiri Olsa if (add && get_event_modifier(&mod, str, evsel)) 2028f5b1135bSJiri Olsa return -EINVAL; 2029f5b1135bSJiri Olsa 20301fc632ceSJiri Olsa evsel->core.attr.exclude_user = mod.eu; 20311fc632ceSJiri Olsa evsel->core.attr.exclude_kernel = mod.ek; 20321fc632ceSJiri Olsa evsel->core.attr.exclude_hv = mod.eh; 20331fc632ceSJiri Olsa evsel->core.attr.precise_ip = mod.precise; 20341fc632ceSJiri Olsa evsel->core.attr.exclude_host = mod.eH; 20351fc632ceSJiri Olsa evsel->core.attr.exclude_guest = mod.eG; 20361fc632ceSJiri Olsa evsel->core.attr.exclude_idle = mod.eI; 2037f5b1135bSJiri Olsa evsel->exclude_GH = mod.exclude_GH; 20383c176311SJiri Olsa evsel->sample_read = mod.sample_read; 20397f94af7aSJiri Olsa evsel->precise_max = mod.precise_max; 20405a5dfe4bSAndi Kleen evsel->weak_group = mod.weak; 204101bd8efcSSong Liu evsel->bpf_counter = mod.bpf_counter; 2042e9a7c414SMichael Ellerman 20430997a266SAndi Kleen if (evsel__is_group_leader(evsel)) { 20441fc632ceSJiri Olsa evsel->core.attr.pinned = mod.pinned; 20450997a266SAndi Kleen evsel->core.attr.exclusive = mod.exclusive; 20460997a266SAndi Kleen } 2047ceb53fbfSIngo Molnar } 204886470930SIngo Molnar 204989812fc8SJiri Olsa return 0; 205086470930SIngo Molnar } 205186470930SIngo Molnar 20528e8bbfb3SIan Rogers int parse_events_name(struct list_head *list, const char *name) 2053ac2ba9f3SRobert Richter { 205432dcd021SJiri Olsa struct evsel *evsel; 2055ac2ba9f3SRobert Richter 2056e5cadb93SArnaldo Carvalho de Melo __evlist__for_each_entry(list, evsel) { 2057ac2ba9f3SRobert Richter if (!evsel->name) 2058ac2ba9f3SRobert Richter evsel->name = strdup(name); 2059ac2ba9f3SRobert Richter } 2060ac2ba9f3SRobert Richter 2061ac2ba9f3SRobert Richter return 0; 2062ac2ba9f3SRobert Richter } 2063ac2ba9f3SRobert Richter 2064dcb4e102SKan Liang static int 2065dcb4e102SKan Liang comp_pmu(const void *p1, const void *p2) 2066dcb4e102SKan Liang { 2067dcb4e102SKan Liang struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1; 2068dcb4e102SKan Liang struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2; 2069dcb4e102SKan Liang 2070e312bcf1SAndi Kleen return strcasecmp(pmu1->symbol, pmu2->symbol); 2071dcb4e102SKan Liang } 2072dcb4e102SKan Liang 2073dcb4e102SKan Liang static void perf_pmu__parse_cleanup(void) 2074dcb4e102SKan Liang { 2075dcb4e102SKan Liang if (perf_pmu_events_list_num > 0) { 2076dcb4e102SKan Liang struct perf_pmu_event_symbol *p; 2077dcb4e102SKan Liang int i; 2078dcb4e102SKan Liang 2079dcb4e102SKan Liang for (i = 0; i < perf_pmu_events_list_num; i++) { 2080dcb4e102SKan Liang p = perf_pmu_events_list + i; 2081360e071bSTaeung Song zfree(&p->symbol); 2082dcb4e102SKan Liang } 2083506fde11STaeung Song zfree(&perf_pmu_events_list); 2084dcb4e102SKan Liang perf_pmu_events_list_num = 0; 2085dcb4e102SKan Liang } 2086dcb4e102SKan Liang } 2087dcb4e102SKan Liang 2088dcb4e102SKan Liang #define SET_SYMBOL(str, stype) \ 2089dcb4e102SKan Liang do { \ 2090dcb4e102SKan Liang p->symbol = str; \ 2091dcb4e102SKan Liang if (!p->symbol) \ 2092dcb4e102SKan Liang goto err; \ 2093dcb4e102SKan Liang p->type = stype; \ 2094dcb4e102SKan Liang } while (0) 2095dcb4e102SKan Liang 2096dcb4e102SKan Liang /* 2097dcb4e102SKan Liang * Read the pmu events list from sysfs 2098dcb4e102SKan Liang * Save it into perf_pmu_events_list 2099dcb4e102SKan Liang */ 2100dcb4e102SKan Liang static void perf_pmu__parse_init(void) 2101dcb4e102SKan Liang { 2102dcb4e102SKan Liang 2103dcb4e102SKan Liang struct perf_pmu *pmu = NULL; 2104dcb4e102SKan Liang struct perf_pmu_alias *alias; 2105dcb4e102SKan Liang int len = 0; 2106dcb4e102SKan Liang 2107231bb2aaSAndi Kleen pmu = NULL; 2108231bb2aaSAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 2109dcb4e102SKan Liang list_for_each_entry(alias, &pmu->aliases, list) { 2110864bc8c9SJohn Garry char *tmp = strchr(alias->name, '-'); 2111864bc8c9SJohn Garry 2112864bc8c9SJohn Garry if (tmp) { 2113864bc8c9SJohn Garry char *tmp2 = NULL; 2114864bc8c9SJohn Garry 2115864bc8c9SJohn Garry tmp2 = strchr(tmp + 1, '-'); 2116dcb4e102SKan Liang len++; 2117864bc8c9SJohn Garry if (tmp2) 2118864bc8c9SJohn Garry len++; 2119864bc8c9SJohn Garry } 2120864bc8c9SJohn Garry 2121dcb4e102SKan Liang len++; 2122dcb4e102SKan Liang } 2123231bb2aaSAndi Kleen } 2124231bb2aaSAndi Kleen 2125231bb2aaSAndi Kleen if (len == 0) { 2126231bb2aaSAndi Kleen perf_pmu_events_list_num = -1; 2127231bb2aaSAndi Kleen return; 2128231bb2aaSAndi Kleen } 2129dcb4e102SKan Liang perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len); 2130dcb4e102SKan Liang if (!perf_pmu_events_list) 2131dcb4e102SKan Liang return; 2132dcb4e102SKan Liang perf_pmu_events_list_num = len; 2133dcb4e102SKan Liang 2134dcb4e102SKan Liang len = 0; 2135231bb2aaSAndi Kleen pmu = NULL; 2136231bb2aaSAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 2137dcb4e102SKan Liang list_for_each_entry(alias, &pmu->aliases, list) { 2138dcb4e102SKan Liang struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; 2139dcb4e102SKan Liang char *tmp = strchr(alias->name, '-'); 2140864bc8c9SJohn Garry char *tmp2 = NULL; 2141dcb4e102SKan Liang 2142864bc8c9SJohn Garry if (tmp) 2143864bc8c9SJohn Garry tmp2 = strchr(tmp + 1, '-'); 2144864bc8c9SJohn Garry if (tmp2) { 2145864bc8c9SJohn Garry SET_SYMBOL(strndup(alias->name, tmp - alias->name), 2146864bc8c9SJohn Garry PMU_EVENT_SYMBOL_PREFIX); 2147864bc8c9SJohn Garry p++; 2148864bc8c9SJohn Garry tmp++; 2149864bc8c9SJohn Garry SET_SYMBOL(strndup(tmp, tmp2 - tmp), PMU_EVENT_SYMBOL_SUFFIX); 2150864bc8c9SJohn Garry p++; 2151864bc8c9SJohn Garry SET_SYMBOL(strdup(++tmp2), PMU_EVENT_SYMBOL_SUFFIX2); 2152864bc8c9SJohn Garry len += 3; 2153864bc8c9SJohn Garry } else if (tmp) { 2154dcb4e102SKan Liang SET_SYMBOL(strndup(alias->name, tmp - alias->name), 2155dcb4e102SKan Liang PMU_EVENT_SYMBOL_PREFIX); 2156dcb4e102SKan Liang p++; 2157dcb4e102SKan Liang SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX); 2158dcb4e102SKan Liang len += 2; 2159dcb4e102SKan Liang } else { 2160dcb4e102SKan Liang SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL); 2161dcb4e102SKan Liang len++; 2162dcb4e102SKan Liang } 2163dcb4e102SKan Liang } 2164231bb2aaSAndi Kleen } 2165dcb4e102SKan Liang qsort(perf_pmu_events_list, len, 2166dcb4e102SKan Liang sizeof(struct perf_pmu_event_symbol), comp_pmu); 2167dcb4e102SKan Liang 2168dcb4e102SKan Liang return; 2169dcb4e102SKan Liang err: 2170dcb4e102SKan Liang perf_pmu__parse_cleanup(); 2171dcb4e102SKan Liang } 2172dcb4e102SKan Liang 21734929e95aSJiri Olsa /* 21744929e95aSJiri Olsa * This function injects special term in 21754929e95aSJiri Olsa * perf_pmu_events_list so the test code 21764929e95aSJiri Olsa * can check on this functionality. 21774929e95aSJiri Olsa */ 21784929e95aSJiri Olsa int perf_pmu__test_parse_init(void) 21794929e95aSJiri Olsa { 2180b4a7276cSJohn Garry struct perf_pmu_event_symbol *list, *tmp, symbols[] = { 2181b4a7276cSJohn Garry {(char *)"read", PMU_EVENT_SYMBOL}, 2182b4a7276cSJohn Garry {(char *)"event", PMU_EVENT_SYMBOL_PREFIX}, 2183b4a7276cSJohn Garry {(char *)"two", PMU_EVENT_SYMBOL_SUFFIX}, 2184b4a7276cSJohn Garry {(char *)"hyphen", PMU_EVENT_SYMBOL_SUFFIX}, 2185b4a7276cSJohn Garry {(char *)"hyph", PMU_EVENT_SYMBOL_SUFFIX2}, 2186b4a7276cSJohn Garry }; 2187b4a7276cSJohn Garry unsigned long i, j; 21884929e95aSJiri Olsa 2189b4a7276cSJohn Garry tmp = list = malloc(sizeof(*list) * ARRAY_SIZE(symbols)); 21904929e95aSJiri Olsa if (!list) 21914929e95aSJiri Olsa return -ENOMEM; 21924929e95aSJiri Olsa 2193b4a7276cSJohn Garry for (i = 0; i < ARRAY_SIZE(symbols); i++, tmp++) { 2194b4a7276cSJohn Garry tmp->type = symbols[i].type; 2195b4a7276cSJohn Garry tmp->symbol = strdup(symbols[i].symbol); 2196*a7a72631SWeiguo Li if (!tmp->symbol) 2197b4a7276cSJohn Garry goto err_free; 21984929e95aSJiri Olsa } 21994929e95aSJiri Olsa 22004929e95aSJiri Olsa perf_pmu_events_list = list; 2201b4a7276cSJohn Garry perf_pmu_events_list_num = ARRAY_SIZE(symbols); 2202b4a7276cSJohn Garry 2203b4a7276cSJohn Garry qsort(perf_pmu_events_list, ARRAY_SIZE(symbols), 2204b4a7276cSJohn Garry sizeof(struct perf_pmu_event_symbol), comp_pmu); 22054929e95aSJiri Olsa return 0; 2206b4a7276cSJohn Garry 2207b4a7276cSJohn Garry err_free: 2208b4a7276cSJohn Garry for (j = 0, tmp = list; j < i; j++, tmp++) 2209b4a7276cSJohn Garry free(tmp->symbol); 2210b4a7276cSJohn Garry free(list); 2211b4a7276cSJohn Garry return -ENOMEM; 22124929e95aSJiri Olsa } 22134929e95aSJiri Olsa 2214dcb4e102SKan Liang enum perf_pmu_event_symbol_type 2215dcb4e102SKan Liang perf_pmu__parse_check(const char *name) 2216dcb4e102SKan Liang { 2217dcb4e102SKan Liang struct perf_pmu_event_symbol p, *r; 2218dcb4e102SKan Liang 2219dcb4e102SKan Liang /* scan kernel pmu events from sysfs if needed */ 2220dcb4e102SKan Liang if (perf_pmu_events_list_num == 0) 2221dcb4e102SKan Liang perf_pmu__parse_init(); 2222dcb4e102SKan Liang /* 2223dcb4e102SKan Liang * name "cpu" could be prefix of cpu-cycles or cpu// events. 2224dcb4e102SKan Liang * cpu-cycles has been handled by hardcode. 2225dcb4e102SKan Liang * So it must be cpu// events, not kernel pmu event. 2226dcb4e102SKan Liang */ 2227dcb4e102SKan Liang if ((perf_pmu_events_list_num <= 0) || !strcmp(name, "cpu")) 2228dcb4e102SKan Liang return PMU_EVENT_SYMBOL_ERR; 2229dcb4e102SKan Liang 2230dcb4e102SKan Liang p.symbol = strdup(name); 2231dcb4e102SKan Liang r = bsearch(&p, perf_pmu_events_list, 2232dcb4e102SKan Liang (size_t) perf_pmu_events_list_num, 2233dcb4e102SKan Liang sizeof(struct perf_pmu_event_symbol), comp_pmu); 2234360e071bSTaeung Song zfree(&p.symbol); 2235dcb4e102SKan Liang return r ? r->type : PMU_EVENT_SYMBOL_ERR; 2236dcb4e102SKan Liang } 2237dcb4e102SKan Liang 22381244a327SJiri Olsa static int parse_events__scanner(const char *str, 22391244a327SJiri Olsa struct parse_events_state *parse_state) 2240ac20de6fSZheng Yan { 2241ac20de6fSZheng Yan YY_BUFFER_STATE buffer; 2242ac20de6fSZheng Yan void *scanner; 2243ac20de6fSZheng Yan int ret; 2244ac20de6fSZheng Yan 22451244a327SJiri Olsa ret = parse_events_lex_init_extra(parse_state, &scanner); 2246ac20de6fSZheng Yan if (ret) 2247ac20de6fSZheng Yan return ret; 2248ac20de6fSZheng Yan 2249ac20de6fSZheng Yan buffer = parse_events__scan_string(str, scanner); 2250ac20de6fSZheng Yan 2251ac20de6fSZheng Yan #ifdef PARSER_DEBUG 2252ac20de6fSZheng Yan parse_events_debug = 1; 2253ae762641SJiri Olsa parse_events_set_debug(1, scanner); 2254ac20de6fSZheng Yan #endif 22555d9cdc11SArnaldo Carvalho de Melo ret = parse_events_parse(parse_state, scanner); 2256ac20de6fSZheng Yan 2257ac20de6fSZheng Yan parse_events__flush_buffer(buffer, scanner); 2258ac20de6fSZheng Yan parse_events__delete_buffer(buffer, scanner); 2259ac20de6fSZheng Yan parse_events_lex_destroy(scanner); 2260ac20de6fSZheng Yan return ret; 2261ac20de6fSZheng Yan } 2262ac20de6fSZheng Yan 226390e2b22dSJiri Olsa /* 226490e2b22dSJiri Olsa * parse event config string, return a list of event terms. 226590e2b22dSJiri Olsa */ 226690e2b22dSJiri Olsa int parse_events_terms(struct list_head *terms, const char *str) 226790e2b22dSJiri Olsa { 22685d9cdc11SArnaldo Carvalho de Melo struct parse_events_state parse_state = { 226990e2b22dSJiri Olsa .terms = NULL, 22701244a327SJiri Olsa .stoken = PE_START_TERMS, 227190e2b22dSJiri Olsa }; 227290e2b22dSJiri Olsa int ret; 227390e2b22dSJiri Olsa 22741244a327SJiri Olsa ret = parse_events__scanner(str, &parse_state); 22754929e95aSJiri Olsa perf_pmu__parse_cleanup(); 22764929e95aSJiri Olsa 227790e2b22dSJiri Olsa if (!ret) { 22785d9cdc11SArnaldo Carvalho de Melo list_splice(parse_state.terms, terms); 22795d9cdc11SArnaldo Carvalho de Melo zfree(&parse_state.terms); 228090e2b22dSJiri Olsa return 0; 228190e2b22dSJiri Olsa } 228290e2b22dSJiri Olsa 22835d9cdc11SArnaldo Carvalho de Melo parse_events_terms__delete(parse_state.terms); 228490e2b22dSJiri Olsa return ret; 228590e2b22dSJiri Olsa } 228690e2b22dSJiri Olsa 22875e4edd1fSJin Yao static int parse_events__with_hybrid_pmu(struct parse_events_state *parse_state, 22885e4edd1fSJin Yao const char *str, char *pmu_name, 22895e4edd1fSJin Yao struct list_head *list) 22905e4edd1fSJin Yao { 22915e4edd1fSJin Yao struct parse_events_state ps = { 22925e4edd1fSJin Yao .list = LIST_HEAD_INIT(ps.list), 22935e4edd1fSJin Yao .stoken = PE_START_EVENTS, 22945e4edd1fSJin Yao .hybrid_pmu_name = pmu_name, 22955e4edd1fSJin Yao .idx = parse_state->idx, 22965e4edd1fSJin Yao }; 22975e4edd1fSJin Yao int ret; 22985e4edd1fSJin Yao 22995e4edd1fSJin Yao ret = parse_events__scanner(str, &ps); 23005e4edd1fSJin Yao perf_pmu__parse_cleanup(); 23015e4edd1fSJin Yao 23025e4edd1fSJin Yao if (!ret) { 23035e4edd1fSJin Yao if (!list_empty(&ps.list)) { 23045e4edd1fSJin Yao list_splice(&ps.list, list); 23055e4edd1fSJin Yao parse_state->idx = ps.idx; 23065e4edd1fSJin Yao return 0; 23075e4edd1fSJin Yao } else 23085e4edd1fSJin Yao return -1; 23095e4edd1fSJin Yao } 23105e4edd1fSJin Yao 23115e4edd1fSJin Yao return ret; 23125e4edd1fSJin Yao } 23135e4edd1fSJin Yao 23143bf91aa5SArnaldo Carvalho de Melo int __parse_events(struct evlist *evlist, const char *str, 23153bf91aa5SArnaldo Carvalho de Melo struct parse_events_error *err, struct perf_pmu *fake_pmu) 231686470930SIngo Molnar { 23175d9cdc11SArnaldo Carvalho de Melo struct parse_events_state parse_state = { 23185d9cdc11SArnaldo Carvalho de Melo .list = LIST_HEAD_INIT(parse_state.list), 23196484d2f9SJiri Olsa .idx = evlist->core.nr_entries, 2320b39b8393SJiri Olsa .error = err, 23217630b3e2SWang Nan .evlist = evlist, 23221244a327SJiri Olsa .stoken = PE_START_EVENTS, 23233bf91aa5SArnaldo Carvalho de Melo .fake_pmu = fake_pmu, 232446010ab2SJiri Olsa }; 232546010ab2SJiri Olsa int ret; 232686470930SIngo Molnar 23271244a327SJiri Olsa ret = parse_events__scanner(str, &parse_state); 2328dcb4e102SKan Liang perf_pmu__parse_cleanup(); 232915bfd2ccSWang Nan 23308e8714c3SIan Rogers if (!ret && list_empty(&parse_state.list)) { 2331c23080a6SArnaldo Carvalho de Melo WARN_ONCE(true, "WARNING: event parser found nothing\n"); 2332854f7363SWang Nan return -1; 2333854f7363SWang Nan } 2334854f7363SWang Nan 23358e8714c3SIan Rogers /* 23368e8714c3SIan Rogers * Add list to the evlist even with errors to allow callers to clean up. 23378e8714c3SIan Rogers */ 2338e414fd1aSArnaldo Carvalho de Melo evlist__splice_list_tail(evlist, &parse_state.list); 23398e8714c3SIan Rogers 23408e8714c3SIan Rogers if (!ret) { 23418e8714c3SIan Rogers struct evsel *last; 23428e8714c3SIan Rogers 23433a683120SJiri Olsa evlist->core.nr_groups += parse_state.nr_groups; 2344515dbe48SJiri Olsa last = evlist__last(evlist); 234515bfd2ccSWang Nan last->cmdline_group_boundary = true; 234615bfd2ccSWang Nan 234786470930SIngo Molnar return 0; 234886470930SIngo Molnar } 234986470930SIngo Molnar 23505d7be90eSJiri Olsa /* 23515d7be90eSJiri Olsa * There are 2 users - builtin-record and builtin-test objects. 2352c12995a5SJiri Olsa * Both call evlist__delete in case of error, so we dont 23535d7be90eSJiri Olsa * need to bother. 23545d7be90eSJiri Olsa */ 235589812fc8SJiri Olsa return ret; 235689812fc8SJiri Olsa } 235789812fc8SJiri Olsa 235807eafd4eSIan Rogers void parse_events_error__init(struct parse_events_error *err) 235907eafd4eSIan Rogers { 236007eafd4eSIan Rogers bzero(err, sizeof(*err)); 236107eafd4eSIan Rogers } 236207eafd4eSIan Rogers 236307eafd4eSIan Rogers void parse_events_error__exit(struct parse_events_error *err) 236407eafd4eSIan Rogers { 236507eafd4eSIan Rogers zfree(&err->str); 236607eafd4eSIan Rogers zfree(&err->help); 236707eafd4eSIan Rogers zfree(&err->first_str); 236807eafd4eSIan Rogers zfree(&err->first_help); 236907eafd4eSIan Rogers } 237007eafd4eSIan Rogers 23716c191289SIan Rogers void parse_events_error__handle(struct parse_events_error *err, int idx, 23726c191289SIan Rogers char *str, char *help) 23736c191289SIan Rogers { 23746c191289SIan Rogers if (WARN(!str, "WARNING: failed to provide error string\n")) { 23756c191289SIan Rogers free(help); 23766c191289SIan Rogers return; 23776c191289SIan Rogers } 23786c191289SIan Rogers switch (err->num_errors) { 23796c191289SIan Rogers case 0: 23806c191289SIan Rogers err->idx = idx; 23816c191289SIan Rogers err->str = str; 23826c191289SIan Rogers err->help = help; 23836c191289SIan Rogers break; 23846c191289SIan Rogers case 1: 23856c191289SIan Rogers err->first_idx = err->idx; 23866c191289SIan Rogers err->idx = idx; 23876c191289SIan Rogers err->first_str = err->str; 23886c191289SIan Rogers err->str = str; 23896c191289SIan Rogers err->first_help = err->help; 23906c191289SIan Rogers err->help = help; 23916c191289SIan Rogers break; 23926c191289SIan Rogers default: 23936c191289SIan Rogers pr_debug("Multiple errors dropping message: %s (%s)\n", 23946c191289SIan Rogers err->str, err->help); 23956c191289SIan Rogers free(err->str); 23966c191289SIan Rogers err->str = str; 23976c191289SIan Rogers free(err->help); 23986c191289SIan Rogers err->help = help; 23996c191289SIan Rogers break; 24006c191289SIan Rogers } 24016c191289SIan Rogers err->num_errors++; 24026c191289SIan Rogers } 24036c191289SIan Rogers 2404b39b8393SJiri Olsa #define MAX_WIDTH 1000 2405b39b8393SJiri Olsa static int get_term_width(void) 2406b39b8393SJiri Olsa { 2407b39b8393SJiri Olsa struct winsize ws; 2408b39b8393SJiri Olsa 2409b39b8393SJiri Olsa get_term_dimensions(&ws); 2410b39b8393SJiri Olsa return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col; 2411b39b8393SJiri Olsa } 2412b39b8393SJiri Olsa 24136c191289SIan Rogers static void __parse_events_error__print(int err_idx, const char *err_str, 2414a910e466SIan Rogers const char *err_help, const char *event) 2415b39b8393SJiri Olsa { 2416b39b8393SJiri Olsa const char *str = "invalid or unsupported event: "; 2417b39b8393SJiri Olsa char _buf[MAX_WIDTH]; 2418b39b8393SJiri Olsa char *buf = (char *) event; 2419b39b8393SJiri Olsa int idx = 0; 2420a910e466SIan Rogers if (err_str) { 2421b39b8393SJiri Olsa /* -2 for extra '' in the final fprintf */ 2422b39b8393SJiri Olsa int width = get_term_width() - 2; 2423b39b8393SJiri Olsa int len_event = strlen(event); 2424b39b8393SJiri Olsa int len_str, max_len, cut = 0; 2425b39b8393SJiri Olsa 2426b39b8393SJiri Olsa /* 2427b39b8393SJiri Olsa * Maximum error index indent, we will cut 2428b39b8393SJiri Olsa * the event string if it's bigger. 2429b39b8393SJiri Olsa */ 2430141b2d31SAdrian Hunter int max_err_idx = 13; 2431b39b8393SJiri Olsa 2432b39b8393SJiri Olsa /* 2433b39b8393SJiri Olsa * Let's be specific with the message when 2434b39b8393SJiri Olsa * we have the precise error. 2435b39b8393SJiri Olsa */ 2436b39b8393SJiri Olsa str = "event syntax error: "; 2437b39b8393SJiri Olsa len_str = strlen(str); 2438b39b8393SJiri Olsa max_len = width - len_str; 2439b39b8393SJiri Olsa 2440b39b8393SJiri Olsa buf = _buf; 2441b39b8393SJiri Olsa 2442bd1a0be5SAdam Buchbinder /* We're cutting from the beginning. */ 2443a910e466SIan Rogers if (err_idx > max_err_idx) 2444a910e466SIan Rogers cut = err_idx - max_err_idx; 2445b39b8393SJiri Olsa 2446b39b8393SJiri Olsa strncpy(buf, event + cut, max_len); 2447b39b8393SJiri Olsa 2448b39b8393SJiri Olsa /* Mark cut parts with '..' on both sides. */ 2449b39b8393SJiri Olsa if (cut) 2450b39b8393SJiri Olsa buf[0] = buf[1] = '.'; 2451b39b8393SJiri Olsa 2452b39b8393SJiri Olsa if ((len_event - cut) > max_len) { 2453b39b8393SJiri Olsa buf[max_len - 1] = buf[max_len - 2] = '.'; 2454b39b8393SJiri Olsa buf[max_len] = 0; 2455b39b8393SJiri Olsa } 2456b39b8393SJiri Olsa 2457a910e466SIan Rogers idx = len_str + err_idx - cut; 2458b39b8393SJiri Olsa } 2459b39b8393SJiri Olsa 2460b39b8393SJiri Olsa fprintf(stderr, "%s'%s'\n", str, buf); 2461b39b8393SJiri Olsa if (idx) { 2462a910e466SIan Rogers fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err_str); 2463a910e466SIan Rogers if (err_help) 2464a910e466SIan Rogers fprintf(stderr, "\n%s\n", err_help); 2465a910e466SIan Rogers } 2466a910e466SIan Rogers } 2467a910e466SIan Rogers 24686c191289SIan Rogers void parse_events_error__print(struct parse_events_error *err, 2469a910e466SIan Rogers const char *event) 2470a910e466SIan Rogers { 2471a910e466SIan Rogers if (!err->num_errors) 2472a910e466SIan Rogers return; 2473a910e466SIan Rogers 24746c191289SIan Rogers __parse_events_error__print(err->idx, err->str, err->help, event); 2475a910e466SIan Rogers 2476a910e466SIan Rogers if (err->num_errors > 1) { 2477a910e466SIan Rogers fputs("\nInitial error:\n", stderr); 24786c191289SIan Rogers __parse_events_error__print(err->first_idx, err->first_str, 2479a910e466SIan Rogers err->first_help, event); 2480b39b8393SJiri Olsa } 2481b39b8393SJiri Olsa } 2482b39b8393SJiri Olsa 2483b39b8393SJiri Olsa #undef MAX_WIDTH 2484b39b8393SJiri Olsa 2485f120f9d5SJiri Olsa int parse_events_option(const struct option *opt, const char *str, 24861d037ca1SIrina Tirdea int unset __maybe_unused) 2487f120f9d5SJiri Olsa { 248863503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 2489a910e466SIan Rogers struct parse_events_error err; 2490a910e466SIan Rogers int ret; 2491a910e466SIan Rogers 249207eafd4eSIan Rogers parse_events_error__init(&err); 2493a910e466SIan Rogers ret = parse_events(evlist, str, &err); 24949175ce1fSAndi Kleen 2495333b5665SAndi Kleen if (ret) { 24966c191289SIan Rogers parse_events_error__print(&err, str); 2497333b5665SAndi Kleen fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 2498333b5665SAndi Kleen } 249907eafd4eSIan Rogers parse_events_error__exit(&err); 2500b39b8393SJiri Olsa 25019175ce1fSAndi Kleen return ret; 2502f120f9d5SJiri Olsa } 2503f120f9d5SJiri Olsa 2504d0abbc3cSArnaldo Carvalho de Melo int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset) 2505d0abbc3cSArnaldo Carvalho de Melo { 2506d0abbc3cSArnaldo Carvalho de Melo struct evlist **evlistp = opt->value; 2507d0abbc3cSArnaldo Carvalho de Melo int ret; 2508d0abbc3cSArnaldo Carvalho de Melo 2509d0abbc3cSArnaldo Carvalho de Melo if (*evlistp == NULL) { 2510d0abbc3cSArnaldo Carvalho de Melo *evlistp = evlist__new(); 2511d0abbc3cSArnaldo Carvalho de Melo 2512d0abbc3cSArnaldo Carvalho de Melo if (*evlistp == NULL) { 2513d0abbc3cSArnaldo Carvalho de Melo fprintf(stderr, "Not enough memory to create evlist\n"); 2514d0abbc3cSArnaldo Carvalho de Melo return -1; 2515d0abbc3cSArnaldo Carvalho de Melo } 2516d0abbc3cSArnaldo Carvalho de Melo } 2517d0abbc3cSArnaldo Carvalho de Melo 2518d0abbc3cSArnaldo Carvalho de Melo ret = parse_events_option(opt, str, unset); 2519d0abbc3cSArnaldo Carvalho de Melo if (ret) { 2520d0abbc3cSArnaldo Carvalho de Melo evlist__delete(*evlistp); 2521d0abbc3cSArnaldo Carvalho de Melo *evlistp = NULL; 2522d0abbc3cSArnaldo Carvalho de Melo } 2523d0abbc3cSArnaldo Carvalho de Melo 2524d0abbc3cSArnaldo Carvalho de Melo return ret; 2525d0abbc3cSArnaldo Carvalho de Melo } 2526d0abbc3cSArnaldo Carvalho de Melo 25274ba1faa1SWang Nan static int 252863503dbaSJiri Olsa foreach_evsel_in_last_glob(struct evlist *evlist, 252932dcd021SJiri Olsa int (*func)(struct evsel *evsel, 25304ba1faa1SWang Nan const void *arg), 25314ba1faa1SWang Nan const void *arg) 2532c171b552SLi Zefan { 253332dcd021SJiri Olsa struct evsel *last = NULL; 25344ba1faa1SWang Nan int err; 2535c171b552SLi Zefan 2536854f7363SWang Nan /* 2537854f7363SWang Nan * Don't return when list_empty, give func a chance to report 2538854f7363SWang Nan * error when it found last == NULL. 2539854f7363SWang Nan * 2540854f7363SWang Nan * So no need to WARN here, let *func do this. 2541854f7363SWang Nan */ 25426484d2f9SJiri Olsa if (evlist->core.nr_entries > 0) 2543515dbe48SJiri Olsa last = evlist__last(evlist); 254469aad6f1SArnaldo Carvalho de Melo 254515bfd2ccSWang Nan do { 25464ba1faa1SWang Nan err = (*func)(last, arg); 25474ba1faa1SWang Nan if (err) 2548c171b552SLi Zefan return -1; 25494ba1faa1SWang Nan if (!last) 25504ba1faa1SWang Nan return 0; 2551c171b552SLi Zefan 2552ce9036a6SJiri Olsa if (last->core.node.prev == &evlist->core.entries) 255315bfd2ccSWang Nan return 0; 2554b27c4eceSJiri Olsa last = list_entry(last->core.node.prev, struct evsel, core.node); 255515bfd2ccSWang Nan } while (!last->cmdline_group_boundary); 255615bfd2ccSWang Nan 2557c171b552SLi Zefan return 0; 2558c171b552SLi Zefan } 2559c171b552SLi Zefan 256032dcd021SJiri Olsa static int set_filter(struct evsel *evsel, const void *arg) 25614ba1faa1SWang Nan { 25624ba1faa1SWang Nan const char *str = arg; 25631e857484SMathieu Poirier bool found = false; 25641e857484SMathieu Poirier int nr_addr_filters = 0; 25651e857484SMathieu Poirier struct perf_pmu *pmu = NULL; 25664ba1faa1SWang Nan 256749836f78SJack Henschel if (evsel == NULL) { 256849836f78SJack Henschel fprintf(stderr, 256949836f78SJack Henschel "--filter option should follow a -e tracepoint or HW tracer option\n"); 257049836f78SJack Henschel return -1; 257149836f78SJack Henschel } 25724ba1faa1SWang Nan 25731fc632ceSJiri Olsa if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { 2574ad681adfSArnaldo Carvalho de Melo if (evsel__append_tp_filter(evsel, str) < 0) { 25754ba1faa1SWang Nan fprintf(stderr, 25764ba1faa1SWang Nan "not enough memory to hold filter string\n"); 25774ba1faa1SWang Nan return -1; 25784ba1faa1SWang Nan } 25794ba1faa1SWang Nan 25804ba1faa1SWang Nan return 0; 25814ba1faa1SWang Nan } 25824ba1faa1SWang Nan 25831e857484SMathieu Poirier while ((pmu = perf_pmu__scan(pmu)) != NULL) 25841fc632ceSJiri Olsa if (pmu->type == evsel->core.attr.type) { 25851e857484SMathieu Poirier found = true; 25861e857484SMathieu Poirier break; 25871e857484SMathieu Poirier } 25881e857484SMathieu Poirier 25891e857484SMathieu Poirier if (found) 25901e857484SMathieu Poirier perf_pmu__scan_file(pmu, "nr_addr_filters", 25911e857484SMathieu Poirier "%d", &nr_addr_filters); 25921e857484SMathieu Poirier 259349836f78SJack Henschel if (!nr_addr_filters) { 259449836f78SJack Henschel fprintf(stderr, 259549836f78SJack Henschel "This CPU does not support address filtering\n"); 259649836f78SJack Henschel return -1; 259749836f78SJack Henschel } 25981e857484SMathieu Poirier 2599ad681adfSArnaldo Carvalho de Melo if (evsel__append_addr_filter(evsel, str) < 0) { 26001e857484SMathieu Poirier fprintf(stderr, 26011e857484SMathieu Poirier "not enough memory to hold filter string\n"); 26021e857484SMathieu Poirier return -1; 26031e857484SMathieu Poirier } 26041e857484SMathieu Poirier 26051e857484SMathieu Poirier return 0; 26061e857484SMathieu Poirier } 26071e857484SMathieu Poirier 26084ba1faa1SWang Nan int parse_filter(const struct option *opt, const char *str, 26094ba1faa1SWang Nan int unset __maybe_unused) 26104ba1faa1SWang Nan { 261163503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 26124ba1faa1SWang Nan 26134ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, set_filter, 26144ba1faa1SWang Nan (const void *)str); 26154ba1faa1SWang Nan } 26164ba1faa1SWang Nan 261732dcd021SJiri Olsa static int add_exclude_perf_filter(struct evsel *evsel, 26184ba1faa1SWang Nan const void *arg __maybe_unused) 26194ba1faa1SWang Nan { 26204ba1faa1SWang Nan char new_filter[64]; 26214ba1faa1SWang Nan 26221fc632ceSJiri Olsa if (evsel == NULL || evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { 26234ba1faa1SWang Nan fprintf(stderr, 26244ba1faa1SWang Nan "--exclude-perf option should follow a -e tracepoint option\n"); 26254ba1faa1SWang Nan return -1; 26264ba1faa1SWang Nan } 26274ba1faa1SWang Nan 26284ba1faa1SWang Nan snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid()); 26294ba1faa1SWang Nan 2630ad681adfSArnaldo Carvalho de Melo if (evsel__append_tp_filter(evsel, new_filter) < 0) { 26314ba1faa1SWang Nan fprintf(stderr, 26324ba1faa1SWang Nan "not enough memory to hold filter string\n"); 26334ba1faa1SWang Nan return -1; 26344ba1faa1SWang Nan } 26354ba1faa1SWang Nan 26364ba1faa1SWang Nan return 0; 26374ba1faa1SWang Nan } 26384ba1faa1SWang Nan 26394ba1faa1SWang Nan int exclude_perf(const struct option *opt, 26404ba1faa1SWang Nan const char *arg __maybe_unused, 26414ba1faa1SWang Nan int unset __maybe_unused) 26424ba1faa1SWang Nan { 264363503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 26444ba1faa1SWang Nan 26454ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter, 26464ba1faa1SWang Nan NULL); 26474ba1faa1SWang Nan } 26484ba1faa1SWang Nan 264986470930SIngo Molnar static const char * const event_type_descriptors[] = { 265086470930SIngo Molnar "Hardware event", 265186470930SIngo Molnar "Software event", 265286470930SIngo Molnar "Tracepoint event", 265386470930SIngo Molnar "Hardware cache event", 265441bdcb23SLiming Wang "Raw hardware event descriptor", 265541bdcb23SLiming Wang "Hardware breakpoint", 265686470930SIngo Molnar }; 265786470930SIngo Molnar 2658ab0e4800SYunlong Song static int cmp_string(const void *a, const void *b) 2659ab0e4800SYunlong Song { 2660ab0e4800SYunlong Song const char * const *as = a; 2661ab0e4800SYunlong Song const char * const *bs = b; 2662ab0e4800SYunlong Song 2663ab0e4800SYunlong Song return strcmp(*as, *bs); 2664ab0e4800SYunlong Song } 2665ab0e4800SYunlong Song 266686470930SIngo Molnar /* 2667f6bdafefSJason Baron * Print the events from <debugfs_mount_point>/tracing/events 2668f6bdafefSJason Baron */ 2669f6bdafefSJason Baron 2670a3277d2dSFrederic Weisbecker void print_tracepoint_events(const char *subsys_glob, const char *event_glob, 2671a3277d2dSFrederic Weisbecker bool name_only) 2672f6bdafefSJason Baron { 2673f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 267422a9f41bSArnaldo Carvalho de Melo struct dirent *sys_dirent, *evt_dirent; 2675f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 267625a7d914SArnaldo Carvalho de Melo char *dir_path; 2677ab0e4800SYunlong Song char **evt_list = NULL; 2678ab0e4800SYunlong Song unsigned int evt_i = 0, evt_num = 0; 2679ab0e4800SYunlong Song bool evt_num_known = false; 2680f6bdafefSJason Baron 2681ab0e4800SYunlong Song restart: 26827014e0e3SArnaldo Carvalho de Melo sys_dir = tracing_events__opendir(); 2683f6bdafefSJason Baron if (!sys_dir) 2684725b1368SEric Dumazet return; 2685f6bdafefSJason Baron 2686ab0e4800SYunlong Song if (evt_num_known) { 2687ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 2688ab0e4800SYunlong Song if (!evt_list) 2689ab0e4800SYunlong Song goto out_close_sys_dir; 2690ab0e4800SYunlong Song } 2691ab0e4800SYunlong Song 269222a9f41bSArnaldo Carvalho de Melo for_each_subsystem(sys_dir, sys_dirent) { 2693668b8788SArnaldo Carvalho de Melo if (subsys_glob != NULL && 269422a9f41bSArnaldo Carvalho de Melo !strglobmatch(sys_dirent->d_name, subsys_glob)) 2695668b8788SArnaldo Carvalho de Melo continue; 2696725b1368SEric Dumazet 269725a7d914SArnaldo Carvalho de Melo dir_path = get_events_file(sys_dirent->d_name); 269825a7d914SArnaldo Carvalho de Melo if (!dir_path) 269925a7d914SArnaldo Carvalho de Melo continue; 2700725b1368SEric Dumazet evt_dir = opendir(dir_path); 2701725b1368SEric Dumazet if (!evt_dir) 270225a7d914SArnaldo Carvalho de Melo goto next; 2703725b1368SEric Dumazet 2704c02cab22SArnaldo Carvalho de Melo for_each_event(dir_path, evt_dir, evt_dirent) { 2705668b8788SArnaldo Carvalho de Melo if (event_glob != NULL && 270622a9f41bSArnaldo Carvalho de Melo !strglobmatch(evt_dirent->d_name, event_glob)) 2707668b8788SArnaldo Carvalho de Melo continue; 2708668b8788SArnaldo Carvalho de Melo 2709ab0e4800SYunlong Song if (!evt_num_known) { 2710ab0e4800SYunlong Song evt_num++; 2711a3277d2dSFrederic Weisbecker continue; 2712a3277d2dSFrederic Weisbecker } 2713a3277d2dSFrederic Weisbecker 2714f6bdafefSJason Baron snprintf(evt_path, MAXPATHLEN, "%s:%s", 271522a9f41bSArnaldo Carvalho de Melo sys_dirent->d_name, evt_dirent->d_name); 2716ab0e4800SYunlong Song 2717ab0e4800SYunlong Song evt_list[evt_i] = strdup(evt_path); 271825a7d914SArnaldo Carvalho de Melo if (evt_list[evt_i] == NULL) { 271925a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 2720ab0e4800SYunlong Song goto out_close_evt_dir; 272125a7d914SArnaldo Carvalho de Melo } 2722ab0e4800SYunlong Song evt_i++; 2723f6bdafefSJason Baron } 2724f6bdafefSJason Baron closedir(evt_dir); 272525a7d914SArnaldo Carvalho de Melo next: 272625a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 2727f6bdafefSJason Baron } 2728f6bdafefSJason Baron closedir(sys_dir); 2729ab0e4800SYunlong Song 2730ab0e4800SYunlong Song if (!evt_num_known) { 2731ab0e4800SYunlong Song evt_num_known = true; 2732ab0e4800SYunlong Song goto restart; 2733ab0e4800SYunlong Song } 2734ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 2735ab0e4800SYunlong Song evt_i = 0; 2736ab0e4800SYunlong Song while (evt_i < evt_num) { 2737ab0e4800SYunlong Song if (name_only) { 2738ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 2739ab0e4800SYunlong Song continue; 2740ab0e4800SYunlong Song } 2741ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], 2742ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_TRACEPOINT]); 2743ab0e4800SYunlong Song } 2744dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 2745ab0e4800SYunlong Song printf("\n"); 2746ab0e4800SYunlong Song 2747ab0e4800SYunlong Song out_free: 2748ab0e4800SYunlong Song evt_num = evt_i; 2749ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 2750ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 2751ab0e4800SYunlong Song zfree(&evt_list); 2752ab0e4800SYunlong Song return; 2753ab0e4800SYunlong Song 2754ab0e4800SYunlong Song out_close_evt_dir: 2755ab0e4800SYunlong Song closedir(evt_dir); 2756ab0e4800SYunlong Song out_close_sys_dir: 2757ab0e4800SYunlong Song closedir(sys_dir); 2758ab0e4800SYunlong Song 2759ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", 2760ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_TRACEPOINT]); 2761ab0e4800SYunlong Song if (evt_list) 2762ab0e4800SYunlong Song goto out_free; 2763f6bdafefSJason Baron } 2764f6bdafefSJason Baron 2765f6bdafefSJason Baron /* 276620c457b8SThomas Renninger * Check whether event is in <debugfs_mount_point>/tracing/events 276720c457b8SThomas Renninger */ 276820c457b8SThomas Renninger 276920c457b8SThomas Renninger int is_valid_tracepoint(const char *event_string) 277020c457b8SThomas Renninger { 277120c457b8SThomas Renninger DIR *sys_dir, *evt_dir; 277222a9f41bSArnaldo Carvalho de Melo struct dirent *sys_dirent, *evt_dirent; 277320c457b8SThomas Renninger char evt_path[MAXPATHLEN]; 277425a7d914SArnaldo Carvalho de Melo char *dir_path; 277520c457b8SThomas Renninger 27767014e0e3SArnaldo Carvalho de Melo sys_dir = tracing_events__opendir(); 277720c457b8SThomas Renninger if (!sys_dir) 277820c457b8SThomas Renninger return 0; 277920c457b8SThomas Renninger 278022a9f41bSArnaldo Carvalho de Melo for_each_subsystem(sys_dir, sys_dirent) { 278125a7d914SArnaldo Carvalho de Melo dir_path = get_events_file(sys_dirent->d_name); 278225a7d914SArnaldo Carvalho de Melo if (!dir_path) 278325a7d914SArnaldo Carvalho de Melo continue; 278420c457b8SThomas Renninger evt_dir = opendir(dir_path); 278520c457b8SThomas Renninger if (!evt_dir) 278625a7d914SArnaldo Carvalho de Melo goto next; 278720c457b8SThomas Renninger 2788c02cab22SArnaldo Carvalho de Melo for_each_event(dir_path, evt_dir, evt_dirent) { 278920c457b8SThomas Renninger snprintf(evt_path, MAXPATHLEN, "%s:%s", 279022a9f41bSArnaldo Carvalho de Melo sys_dirent->d_name, evt_dirent->d_name); 279120c457b8SThomas Renninger if (!strcmp(evt_path, event_string)) { 279220c457b8SThomas Renninger closedir(evt_dir); 279320c457b8SThomas Renninger closedir(sys_dir); 279420c457b8SThomas Renninger return 1; 279520c457b8SThomas Renninger } 279620c457b8SThomas Renninger } 279720c457b8SThomas Renninger closedir(evt_dir); 279825a7d914SArnaldo Carvalho de Melo next: 279925a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 280020c457b8SThomas Renninger } 280120c457b8SThomas Renninger closedir(sys_dir); 280220c457b8SThomas Renninger return 0; 280320c457b8SThomas Renninger } 280420c457b8SThomas Renninger 28056c93f39fSJin Yao static bool is_event_supported(u8 type, u64 config) 2806b41f1cecSNamhyung Kim { 2807b41f1cecSNamhyung Kim bool ret = true; 280888fee52eSVince Weaver int open_return; 280932dcd021SJiri Olsa struct evsel *evsel; 2810b41f1cecSNamhyung Kim struct perf_event_attr attr = { 2811b41f1cecSNamhyung Kim .type = type, 2812b41f1cecSNamhyung Kim .config = config, 2813b41f1cecSNamhyung Kim .disabled = 1, 2814b41f1cecSNamhyung Kim }; 28159749b90eSJiri Olsa struct perf_thread_map *tmap = thread_map__new_by_tid(0); 281689896051SArnaldo Carvalho de Melo 281789896051SArnaldo Carvalho de Melo if (tmap == NULL) 281889896051SArnaldo Carvalho de Melo return false; 2819b41f1cecSNamhyung Kim 2820365c3ae7SJiri Olsa evsel = evsel__new(&attr); 2821b41f1cecSNamhyung Kim if (evsel) { 28225972d1e0SJiri Olsa open_return = evsel__open(evsel, NULL, tmap); 282388fee52eSVince Weaver ret = open_return >= 0; 282488fee52eSVince Weaver 282588fee52eSVince Weaver if (open_return == -EACCES) { 282688fee52eSVince Weaver /* 282788fee52eSVince Weaver * This happens if the paranoid value 282888fee52eSVince Weaver * /proc/sys/kernel/perf_event_paranoid is set to 2 282988fee52eSVince Weaver * Re-run with exclude_kernel set; we don't do that 283088fee52eSVince Weaver * by default as some ARM machines do not support it. 283188fee52eSVince Weaver * 283288fee52eSVince Weaver */ 28331fc632ceSJiri Olsa evsel->core.attr.exclude_kernel = 1; 28345972d1e0SJiri Olsa ret = evsel__open(evsel, NULL, tmap) >= 0; 283588fee52eSVince Weaver } 28365eb2dd2aSJiri Olsa evsel__delete(evsel); 2837b41f1cecSNamhyung Kim } 2838b41f1cecSNamhyung Kim 28397836e52eSJiri Olsa perf_thread_map__put(tmap); 2840b41f1cecSNamhyung Kim return ret; 2841b41f1cecSNamhyung Kim } 2842b41f1cecSNamhyung Kim 284340218daeSMasami Hiramatsu void print_sdt_events(const char *subsys_glob, const char *event_glob, 284440218daeSMasami Hiramatsu bool name_only) 284540218daeSMasami Hiramatsu { 284640218daeSMasami Hiramatsu struct probe_cache *pcache; 284740218daeSMasami Hiramatsu struct probe_cache_entry *ent; 284840218daeSMasami Hiramatsu struct strlist *bidlist, *sdtlist; 284940218daeSMasami Hiramatsu struct strlist_config cfg = {.dont_dupstr = true}; 285040218daeSMasami Hiramatsu struct str_node *nd, *nd2; 285140218daeSMasami Hiramatsu char *buf, *path, *ptr = NULL; 285240218daeSMasami Hiramatsu bool show_detail = false; 285340218daeSMasami Hiramatsu int ret; 285440218daeSMasami Hiramatsu 285540218daeSMasami Hiramatsu sdtlist = strlist__new(NULL, &cfg); 285640218daeSMasami Hiramatsu if (!sdtlist) { 285740218daeSMasami Hiramatsu pr_debug("Failed to allocate new strlist for SDT\n"); 285840218daeSMasami Hiramatsu return; 285940218daeSMasami Hiramatsu } 286040218daeSMasami Hiramatsu bidlist = build_id_cache__list_all(true); 286140218daeSMasami Hiramatsu if (!bidlist) { 286240218daeSMasami Hiramatsu pr_debug("Failed to get buildids: %d\n", errno); 286340218daeSMasami Hiramatsu return; 286440218daeSMasami Hiramatsu } 286540218daeSMasami Hiramatsu strlist__for_each_entry(nd, bidlist) { 2866f045b8c4SKrister Johansen pcache = probe_cache__new(nd->s, NULL); 286740218daeSMasami Hiramatsu if (!pcache) 286840218daeSMasami Hiramatsu continue; 286940218daeSMasami Hiramatsu list_for_each_entry(ent, &pcache->entries, node) { 287040218daeSMasami Hiramatsu if (!ent->sdt) 287140218daeSMasami Hiramatsu continue; 287240218daeSMasami Hiramatsu if (subsys_glob && 287340218daeSMasami Hiramatsu !strglobmatch(ent->pev.group, subsys_glob)) 287440218daeSMasami Hiramatsu continue; 287540218daeSMasami Hiramatsu if (event_glob && 287640218daeSMasami Hiramatsu !strglobmatch(ent->pev.event, event_glob)) 287740218daeSMasami Hiramatsu continue; 287840218daeSMasami Hiramatsu ret = asprintf(&buf, "%s:%s@%s", ent->pev.group, 287940218daeSMasami Hiramatsu ent->pev.event, nd->s); 288040218daeSMasami Hiramatsu if (ret > 0) 288140218daeSMasami Hiramatsu strlist__add(sdtlist, buf); 288240218daeSMasami Hiramatsu } 288340218daeSMasami Hiramatsu probe_cache__delete(pcache); 288440218daeSMasami Hiramatsu } 288540218daeSMasami Hiramatsu strlist__delete(bidlist); 288640218daeSMasami Hiramatsu 288740218daeSMasami Hiramatsu strlist__for_each_entry(nd, sdtlist) { 288840218daeSMasami Hiramatsu buf = strchr(nd->s, '@'); 288940218daeSMasami Hiramatsu if (buf) 289040218daeSMasami Hiramatsu *(buf++) = '\0'; 289140218daeSMasami Hiramatsu if (name_only) { 289240218daeSMasami Hiramatsu printf("%s ", nd->s); 289340218daeSMasami Hiramatsu continue; 289440218daeSMasami Hiramatsu } 289540218daeSMasami Hiramatsu nd2 = strlist__next(nd); 289640218daeSMasami Hiramatsu if (nd2) { 289740218daeSMasami Hiramatsu ptr = strchr(nd2->s, '@'); 289840218daeSMasami Hiramatsu if (ptr) 289940218daeSMasami Hiramatsu *ptr = '\0'; 290040218daeSMasami Hiramatsu if (strcmp(nd->s, nd2->s) == 0) 290140218daeSMasami Hiramatsu show_detail = true; 290240218daeSMasami Hiramatsu } 290340218daeSMasami Hiramatsu if (show_detail) { 290440218daeSMasami Hiramatsu path = build_id_cache__origname(buf); 290540218daeSMasami Hiramatsu ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf); 290640218daeSMasami Hiramatsu if (ret > 0) { 290740218daeSMasami Hiramatsu printf(" %-50s [%s]\n", buf, "SDT event"); 290840218daeSMasami Hiramatsu free(buf); 290940218daeSMasami Hiramatsu } 29108bde8516SChangbin Du free(path); 291140218daeSMasami Hiramatsu } else 291240218daeSMasami Hiramatsu printf(" %-50s [%s]\n", nd->s, "SDT event"); 291340218daeSMasami Hiramatsu if (nd2) { 291440218daeSMasami Hiramatsu if (strcmp(nd->s, nd2->s) != 0) 291540218daeSMasami Hiramatsu show_detail = false; 291640218daeSMasami Hiramatsu if (ptr) 291740218daeSMasami Hiramatsu *ptr = '@'; 291840218daeSMasami Hiramatsu } 291940218daeSMasami Hiramatsu } 292040218daeSMasami Hiramatsu strlist__delete(sdtlist); 292140218daeSMasami Hiramatsu } 292240218daeSMasami Hiramatsu 2923a3277d2dSFrederic Weisbecker int print_hwcache_events(const char *event_glob, bool name_only) 2924668b8788SArnaldo Carvalho de Melo { 29256c93f39fSJin Yao unsigned int type, op, i, evt_i = 0, evt_num = 0, npmus = 0; 29266c93f39fSJin Yao char name[64], new_name[128]; 29276c93f39fSJin Yao char **evt_list = NULL, **evt_pmus = NULL; 2928ab0e4800SYunlong Song bool evt_num_known = false; 29296c93f39fSJin Yao struct perf_pmu *pmu = NULL; 29306c93f39fSJin Yao 29316c93f39fSJin Yao if (perf_pmu__has_hybrid()) { 29326c93f39fSJin Yao npmus = perf_pmu__hybrid_pmu_num(); 29336c93f39fSJin Yao evt_pmus = zalloc(sizeof(char *) * npmus); 29346c93f39fSJin Yao if (!evt_pmus) 29356c93f39fSJin Yao goto out_enomem; 29366c93f39fSJin Yao } 2937ab0e4800SYunlong Song 2938ab0e4800SYunlong Song restart: 2939ab0e4800SYunlong Song if (evt_num_known) { 2940ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 2941ab0e4800SYunlong Song if (!evt_list) 2942ab0e4800SYunlong Song goto out_enomem; 2943ab0e4800SYunlong Song } 2944668b8788SArnaldo Carvalho de Melo 2945668b8788SArnaldo Carvalho de Melo for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 2946668b8788SArnaldo Carvalho de Melo for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 2947668b8788SArnaldo Carvalho de Melo /* skip invalid cache type */ 2948c754c382SArnaldo Carvalho de Melo if (!evsel__is_cache_op_valid(type, op)) 2949668b8788SArnaldo Carvalho de Melo continue; 2950668b8788SArnaldo Carvalho de Melo 2951668b8788SArnaldo Carvalho de Melo for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 29526c93f39fSJin Yao unsigned int hybrid_supported = 0, j; 29536c93f39fSJin Yao bool supported; 29546c93f39fSJin Yao 29558ab2e96dSArnaldo Carvalho de Melo __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name)); 2956947b4ad1SIngo Molnar if (event_glob != NULL && !strglobmatch(name, event_glob)) 2957668b8788SArnaldo Carvalho de Melo continue; 2958668b8788SArnaldo Carvalho de Melo 29596c93f39fSJin Yao if (!perf_pmu__has_hybrid()) { 2960b41f1cecSNamhyung Kim if (!is_event_supported(PERF_TYPE_HW_CACHE, 29616c93f39fSJin Yao type | (op << 8) | (i << 16))) { 2962b41f1cecSNamhyung Kim continue; 29636c93f39fSJin Yao } 29646c93f39fSJin Yao } else { 29656c93f39fSJin Yao perf_pmu__for_each_hybrid_pmu(pmu) { 29666c93f39fSJin Yao if (!evt_num_known) { 29676c93f39fSJin Yao evt_num++; 29686c93f39fSJin Yao continue; 29696c93f39fSJin Yao } 29706c93f39fSJin Yao 29716c93f39fSJin Yao supported = is_event_supported( 29726c93f39fSJin Yao PERF_TYPE_HW_CACHE, 29736c93f39fSJin Yao type | (op << 8) | (i << 16) | 29746c93f39fSJin Yao ((__u64)pmu->type << PERF_PMU_TYPE_SHIFT)); 29756c93f39fSJin Yao if (supported) { 29766c93f39fSJin Yao snprintf(new_name, sizeof(new_name), "%s/%s/", 29776c93f39fSJin Yao pmu->name, name); 29786c93f39fSJin Yao evt_pmus[hybrid_supported] = strdup(new_name); 29796c93f39fSJin Yao hybrid_supported++; 29806c93f39fSJin Yao } 29816c93f39fSJin Yao } 29826c93f39fSJin Yao 29836c93f39fSJin Yao if (hybrid_supported == 0) 29846c93f39fSJin Yao continue; 29856c93f39fSJin Yao } 2986b41f1cecSNamhyung Kim 2987ab0e4800SYunlong Song if (!evt_num_known) { 2988ab0e4800SYunlong Song evt_num++; 2989ab0e4800SYunlong Song continue; 2990ab0e4800SYunlong Song } 2991ab0e4800SYunlong Song 29926c93f39fSJin Yao if ((hybrid_supported == 0) || 29936c93f39fSJin Yao (hybrid_supported == npmus)) { 2994ab0e4800SYunlong Song evt_list[evt_i] = strdup(name); 29956c93f39fSJin Yao if (npmus > 0) { 29966c93f39fSJin Yao for (j = 0; j < npmus; j++) 29976c93f39fSJin Yao zfree(&evt_pmus[j]); 29986c93f39fSJin Yao } 29996c93f39fSJin Yao } else { 30006c93f39fSJin Yao for (j = 0; j < hybrid_supported; j++) { 30016c93f39fSJin Yao evt_list[evt_i++] = evt_pmus[j]; 30026c93f39fSJin Yao evt_pmus[j] = NULL; 30036c93f39fSJin Yao } 30046c93f39fSJin Yao continue; 30056c93f39fSJin Yao } 30066c93f39fSJin Yao 3007ab0e4800SYunlong Song if (evt_list[evt_i] == NULL) 3008ab0e4800SYunlong Song goto out_enomem; 3009ab0e4800SYunlong Song evt_i++; 3010668b8788SArnaldo Carvalho de Melo } 3011668b8788SArnaldo Carvalho de Melo } 3012668b8788SArnaldo Carvalho de Melo } 3013668b8788SArnaldo Carvalho de Melo 3014ab0e4800SYunlong Song if (!evt_num_known) { 3015ab0e4800SYunlong Song evt_num_known = true; 3016ab0e4800SYunlong Song goto restart; 3017ab0e4800SYunlong Song } 30186c93f39fSJin Yao 30196c93f39fSJin Yao for (evt_i = 0; evt_i < evt_num; evt_i++) { 30206c93f39fSJin Yao if (!evt_list[evt_i]) 30216c93f39fSJin Yao break; 30226c93f39fSJin Yao } 30236c93f39fSJin Yao 30246c93f39fSJin Yao evt_num = evt_i; 3025ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 3026ab0e4800SYunlong Song evt_i = 0; 3027ab0e4800SYunlong Song while (evt_i < evt_num) { 3028ab0e4800SYunlong Song if (name_only) { 3029ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 3030ab0e4800SYunlong Song continue; 3031ab0e4800SYunlong Song } 3032ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], 3033ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_HW_CACHE]); 3034ab0e4800SYunlong Song } 3035dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 3036dc098b35SAndi Kleen printf("\n"); 3037ab0e4800SYunlong Song 3038ab0e4800SYunlong Song out_free: 3039ab0e4800SYunlong Song evt_num = evt_i; 3040ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 3041ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 3042ab0e4800SYunlong Song zfree(&evt_list); 30436c93f39fSJin Yao 30446c93f39fSJin Yao for (evt_i = 0; evt_i < npmus; evt_i++) 30456c93f39fSJin Yao zfree(&evt_pmus[evt_i]); 30466c93f39fSJin Yao zfree(&evt_pmus); 3047ab0e4800SYunlong Song return evt_num; 3048ab0e4800SYunlong Song 3049ab0e4800SYunlong Song out_enomem: 3050ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]); 3051ab0e4800SYunlong Song if (evt_list) 3052ab0e4800SYunlong Song goto out_free; 3053ab0e4800SYunlong Song return evt_num; 3054668b8788SArnaldo Carvalho de Melo } 3055668b8788SArnaldo Carvalho de Melo 30565e0861baSAndi Kleen static void print_tool_event(const char *name, const char *event_glob, 30575e0861baSAndi Kleen bool name_only) 30585e0861baSAndi Kleen { 30595e0861baSAndi Kleen if (event_glob && !strglobmatch(name, event_glob)) 30605e0861baSAndi Kleen return; 30615e0861baSAndi Kleen if (name_only) 30625e0861baSAndi Kleen printf("%s ", name); 30635e0861baSAndi Kleen else 30645e0861baSAndi Kleen printf(" %-50s [%s]\n", name, "Tool event"); 30655e0861baSAndi Kleen 30665e0861baSAndi Kleen } 30675e0861baSAndi Kleen 30685e0861baSAndi Kleen void print_tool_events(const char *event_glob, bool name_only) 30695e0861baSAndi Kleen { 30705e0861baSAndi Kleen print_tool_event("duration_time", event_glob, name_only); 30715e0861baSAndi Kleen if (pager_in_use()) 30725e0861baSAndi Kleen printf("\n"); 30735e0861baSAndi Kleen } 30745e0861baSAndi Kleen 3075705750f2SYunlong Song void print_symbol_events(const char *event_glob, unsigned type, 3076a3277d2dSFrederic Weisbecker struct event_symbol *syms, unsigned max, 3077a3277d2dSFrederic Weisbecker bool name_only) 307886470930SIngo Molnar { 3079ab0e4800SYunlong Song unsigned int i, evt_i = 0, evt_num = 0; 3080947b4ad1SIngo Molnar char name[MAX_NAME_LEN]; 3081ab0e4800SYunlong Song char **evt_list = NULL; 3082ab0e4800SYunlong Song bool evt_num_known = false; 3083ab0e4800SYunlong Song 3084ab0e4800SYunlong Song restart: 3085ab0e4800SYunlong Song if (evt_num_known) { 3086ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 3087ab0e4800SYunlong Song if (!evt_list) 3088ab0e4800SYunlong Song goto out_enomem; 3089ab0e4800SYunlong Song syms -= max; 3090ab0e4800SYunlong Song } 309186470930SIngo Molnar 30921dc12760SJiri Olsa for (i = 0; i < max; i++, syms++) { 30933b2f17adSArnaldo Carvalho de Melo /* 30943b2f17adSArnaldo Carvalho de Melo * New attr.config still not supported here, the latest 30953b2f17adSArnaldo Carvalho de Melo * example was PERF_COUNT_SW_CGROUP_SWITCHES 30963b2f17adSArnaldo Carvalho de Melo */ 30973b2f17adSArnaldo Carvalho de Melo if (syms->symbol == NULL) 30983b2f17adSArnaldo Carvalho de Melo continue; 3099668b8788SArnaldo Carvalho de Melo 31003b2f17adSArnaldo Carvalho de Melo if (event_glob != NULL && !(strglobmatch(syms->symbol, event_glob) || 3101668b8788SArnaldo Carvalho de Melo (syms->alias && strglobmatch(syms->alias, event_glob)))) 3102668b8788SArnaldo Carvalho de Melo continue; 310386470930SIngo Molnar 3104b41f1cecSNamhyung Kim if (!is_event_supported(type, i)) 3105b41f1cecSNamhyung Kim continue; 3106b41f1cecSNamhyung Kim 3107ab0e4800SYunlong Song if (!evt_num_known) { 3108ab0e4800SYunlong Song evt_num++; 3109a3277d2dSFrederic Weisbecker continue; 3110a3277d2dSFrederic Weisbecker } 3111a3277d2dSFrederic Weisbecker 3112ab0e4800SYunlong Song if (!name_only && strlen(syms->alias)) 3113947b4ad1SIngo Molnar snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 311474d5b588SJaswinder Singh Rajput else 3115bd8d57fbSArnaldo Carvalho de Melo strlcpy(name, syms->symbol, MAX_NAME_LEN); 311686470930SIngo Molnar 3117ab0e4800SYunlong Song evt_list[evt_i] = strdup(name); 3118ab0e4800SYunlong Song if (evt_list[evt_i] == NULL) 3119ab0e4800SYunlong Song goto out_enomem; 3120ab0e4800SYunlong Song evt_i++; 312186470930SIngo Molnar } 312286470930SIngo Molnar 3123ab0e4800SYunlong Song if (!evt_num_known) { 3124ab0e4800SYunlong Song evt_num_known = true; 3125ab0e4800SYunlong Song goto restart; 3126ab0e4800SYunlong Song } 3127ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 3128ab0e4800SYunlong Song evt_i = 0; 3129ab0e4800SYunlong Song while (evt_i < evt_num) { 3130ab0e4800SYunlong Song if (name_only) { 3131ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 3132ab0e4800SYunlong Song continue; 3133ab0e4800SYunlong Song } 3134ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); 3135ab0e4800SYunlong Song } 3136dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 3137689d3018SMarti Raudsepp printf("\n"); 3138ab0e4800SYunlong Song 3139ab0e4800SYunlong Song out_free: 3140ab0e4800SYunlong Song evt_num = evt_i; 3141ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 3142ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 3143ab0e4800SYunlong Song zfree(&evt_list); 3144ab0e4800SYunlong Song return; 3145ab0e4800SYunlong Song 3146ab0e4800SYunlong Song out_enomem: 3147ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]); 3148ab0e4800SYunlong Song if (evt_list) 3149ab0e4800SYunlong Song goto out_free; 3150668b8788SArnaldo Carvalho de Melo } 31511dc12760SJiri Olsa 31521dc12760SJiri Olsa /* 31531dc12760SJiri Olsa * Print the help text for the event symbols: 31541dc12760SJiri Olsa */ 3155c8d6828aSSukadev Bhattiprolu void print_events(const char *event_glob, bool name_only, bool quiet_flag, 31560e0ae874SJin Yao bool long_desc, bool details_flag, bool deprecated, 31570e0ae874SJin Yao const char *pmu_name) 31581dc12760SJiri Olsa { 31591dc12760SJiri Olsa print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 3160a3277d2dSFrederic Weisbecker event_symbols_hw, PERF_COUNT_HW_MAX, name_only); 31611dc12760SJiri Olsa 31621dc12760SJiri Olsa print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, 3163a3277d2dSFrederic Weisbecker event_symbols_sw, PERF_COUNT_SW_MAX, name_only); 31645e0861baSAndi Kleen print_tool_events(event_glob, name_only); 31651dc12760SJiri Olsa 3166a3277d2dSFrederic Weisbecker print_hwcache_events(event_glob, name_only); 316773c24cb8SJaswinder Singh Rajput 3168bf874fcfSAndi Kleen print_pmu_events(event_glob, name_only, quiet_flag, long_desc, 31690e0ae874SJin Yao details_flag, deprecated, pmu_name); 3170dc098b35SAndi Kleen 3171668b8788SArnaldo Carvalho de Melo if (event_glob != NULL) 3172668b8788SArnaldo Carvalho de Melo return; 317373c24cb8SJaswinder Singh Rajput 3174a3277d2dSFrederic Weisbecker if (!name_only) { 3175947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 31765f537a26SJiri Olsa "rNNN", 31771cf4a063SArnaldo Carvalho de Melo event_type_descriptors[PERF_TYPE_RAW]); 31785f537a26SJiri Olsa printf(" %-50s [%s]\n", 31795f537a26SJiri Olsa "cpu/t1=v1[,t2=v2,t3 ...]/modifier", 31805f537a26SJiri Olsa event_type_descriptors[PERF_TYPE_RAW]); 3181dfc431cbSArnaldo Carvalho de Melo if (pager_in_use()) 3182dfc431cbSArnaldo Carvalho de Melo printf(" (see 'man perf-list' on how to encode it)\n\n"); 318386470930SIngo Molnar 3184947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 31853741eb9fSJacob Shin "mem:<addr>[/len][:access]", 318641bdcb23SLiming Wang event_type_descriptors[PERF_TYPE_BREAKPOINT]); 3187dfc431cbSArnaldo Carvalho de Melo if (pager_in_use()) 31881b290d67SFrederic Weisbecker printf("\n"); 3189a3277d2dSFrederic Weisbecker } 31901b290d67SFrederic Weisbecker 3191a3277d2dSFrederic Weisbecker print_tracepoint_events(NULL, NULL, name_only); 319240218daeSMasami Hiramatsu 319340218daeSMasami Hiramatsu print_sdt_events(NULL, NULL, name_only); 319471b0acceSAndi Kleen 31950e0ae874SJin Yao metricgroup__print(true, true, NULL, name_only, details_flag, 31960e0ae874SJin Yao pmu_name); 319770943490SStephane Eranian 319870943490SStephane Eranian print_libpfm_events(name_only, long_desc); 319986470930SIngo Molnar } 32008f707d84SJiri Olsa 32016cee6cd3SArnaldo Carvalho de Melo int parse_events__is_hardcoded_term(struct parse_events_term *term) 32028f707d84SJiri Olsa { 320316fa7e82SJiri Olsa return term->type_term != PARSE_EVENTS__TERM_TYPE_USER; 32048f707d84SJiri Olsa } 32058f707d84SJiri Olsa 320667b49b38SJiri Olsa static int new_term(struct parse_events_term **_term, 320767b49b38SJiri Olsa struct parse_events_term *temp, 320867b49b38SJiri Olsa char *str, u64 num) 32098f707d84SJiri Olsa { 32106cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 32118f707d84SJiri Olsa 321267b49b38SJiri Olsa term = malloc(sizeof(*term)); 32138f707d84SJiri Olsa if (!term) 32148f707d84SJiri Olsa return -ENOMEM; 32158f707d84SJiri Olsa 321667b49b38SJiri Olsa *term = *temp; 32178f707d84SJiri Olsa INIT_LIST_HEAD(&term->list); 3218c2f1ceadSAndi Kleen term->weak = false; 32198f707d84SJiri Olsa 322067b49b38SJiri Olsa switch (term->type_val) { 32218f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_NUM: 32228f707d84SJiri Olsa term->val.num = num; 32238f707d84SJiri Olsa break; 32248f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_STR: 32258f707d84SJiri Olsa term->val.str = str; 32268f707d84SJiri Olsa break; 32278f707d84SJiri Olsa default: 32284be8be6bSAdrian Hunter free(term); 32298f707d84SJiri Olsa return -EINVAL; 32308f707d84SJiri Olsa } 32318f707d84SJiri Olsa 32328f707d84SJiri Olsa *_term = term; 32338f707d84SJiri Olsa return 0; 32348f707d84SJiri Olsa } 32358f707d84SJiri Olsa 32366cee6cd3SArnaldo Carvalho de Melo int parse_events_term__num(struct parse_events_term **term, 3237cecf3a2eSJiri Olsa int type_term, char *config, u64 num, 323899e7138eSJiri Olsa bool no_value, 3239bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 324016fa7e82SJiri Olsa { 3241bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 3242bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 3243bb78ce7dSAdrian Hunter 324467b49b38SJiri Olsa struct parse_events_term temp = { 324567b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 324667b49b38SJiri Olsa .type_term = type_term, 32474f9d4f8aSJohn Garry .config = config ? : strdup(config_term_names[type_term]), 324899e7138eSJiri Olsa .no_value = no_value, 324967b49b38SJiri Olsa .err_term = loc_term ? loc_term->first_column : 0, 325067b49b38SJiri Olsa .err_val = loc_val ? loc_val->first_column : 0, 325167b49b38SJiri Olsa }; 325267b49b38SJiri Olsa 325367b49b38SJiri Olsa return new_term(term, &temp, NULL, num); 325416fa7e82SJiri Olsa } 325516fa7e82SJiri Olsa 32566cee6cd3SArnaldo Carvalho de Melo int parse_events_term__str(struct parse_events_term **term, 3257cecf3a2eSJiri Olsa int type_term, char *config, char *str, 3258bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 325916fa7e82SJiri Olsa { 3260bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 3261bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 3262bb78ce7dSAdrian Hunter 326367b49b38SJiri Olsa struct parse_events_term temp = { 326467b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_STR, 326567b49b38SJiri Olsa .type_term = type_term, 326667b49b38SJiri Olsa .config = config, 326767b49b38SJiri Olsa .err_term = loc_term ? loc_term->first_column : 0, 326867b49b38SJiri Olsa .err_val = loc_val ? loc_val->first_column : 0, 326967b49b38SJiri Olsa }; 327067b49b38SJiri Olsa 327167b49b38SJiri Olsa return new_term(term, &temp, str, 0); 327216fa7e82SJiri Olsa } 327316fa7e82SJiri Olsa 32746cee6cd3SArnaldo Carvalho de Melo int parse_events_term__sym_hw(struct parse_events_term **term, 32751d33d6dcSJiri Olsa char *config, unsigned idx) 32761d33d6dcSJiri Olsa { 32771d33d6dcSJiri Olsa struct event_symbol *sym; 3278b6645a72SIan Rogers char *str; 327967b49b38SJiri Olsa struct parse_events_term temp = { 328067b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_STR, 328167b49b38SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 3282b6645a72SIan Rogers .config = config, 328367b49b38SJiri Olsa }; 32841d33d6dcSJiri Olsa 3285b6645a72SIan Rogers if (!temp.config) { 3286b6645a72SIan Rogers temp.config = strdup("event"); 3287b6645a72SIan Rogers if (!temp.config) 3288b6645a72SIan Rogers return -ENOMEM; 3289b6645a72SIan Rogers } 32901d33d6dcSJiri Olsa BUG_ON(idx >= PERF_COUNT_HW_MAX); 32911d33d6dcSJiri Olsa sym = &event_symbols_hw[idx]; 32921d33d6dcSJiri Olsa 3293b6645a72SIan Rogers str = strdup(sym->symbol); 3294b6645a72SIan Rogers if (!str) 3295b6645a72SIan Rogers return -ENOMEM; 3296b6645a72SIan Rogers return new_term(term, &temp, str, 0); 32971d33d6dcSJiri Olsa } 32981d33d6dcSJiri Olsa 32996cee6cd3SArnaldo Carvalho de Melo int parse_events_term__clone(struct parse_events_term **new, 33006cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 3301a6146d50SZheng Yan { 3302b6645a72SIan Rogers char *str; 330367b49b38SJiri Olsa struct parse_events_term temp = { 330467b49b38SJiri Olsa .type_val = term->type_val, 330567b49b38SJiri Olsa .type_term = term->type_term, 3306b6645a72SIan Rogers .config = NULL, 330767b49b38SJiri Olsa .err_term = term->err_term, 330867b49b38SJiri Olsa .err_val = term->err_val, 330967b49b38SJiri Olsa }; 331067b49b38SJiri Olsa 3311b6645a72SIan Rogers if (term->config) { 3312b6645a72SIan Rogers temp.config = strdup(term->config); 3313b6645a72SIan Rogers if (!temp.config) 3314b6645a72SIan Rogers return -ENOMEM; 3315b6645a72SIan Rogers } 3316b6645a72SIan Rogers if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 3317b6645a72SIan Rogers return new_term(new, &temp, NULL, term->val.num); 3318b6645a72SIan Rogers 3319b6645a72SIan Rogers str = strdup(term->val.str); 3320b6645a72SIan Rogers if (!str) 3321b6645a72SIan Rogers return -ENOMEM; 3322b6645a72SIan Rogers return new_term(new, &temp, str, 0); 3323a6146d50SZheng Yan } 3324a6146d50SZheng Yan 33251dc92556SIan Rogers void parse_events_term__delete(struct parse_events_term *term) 33261dc92556SIan Rogers { 33271dc92556SIan Rogers if (term->array.nr_ranges) 33281dc92556SIan Rogers zfree(&term->array.ranges); 33291dc92556SIan Rogers 33301dc92556SIan Rogers if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) 33311dc92556SIan Rogers zfree(&term->val.str); 33321dc92556SIan Rogers 33331dc92556SIan Rogers zfree(&term->config); 33341dc92556SIan Rogers free(term); 33351dc92556SIan Rogers } 33361dc92556SIan Rogers 33378255718fSAndi Kleen int parse_events_copy_term_list(struct list_head *old, 33388255718fSAndi Kleen struct list_head **new) 33398255718fSAndi Kleen { 33408255718fSAndi Kleen struct parse_events_term *term, *n; 33418255718fSAndi Kleen int ret; 33428255718fSAndi Kleen 33438255718fSAndi Kleen if (!old) { 33448255718fSAndi Kleen *new = NULL; 33458255718fSAndi Kleen return 0; 33468255718fSAndi Kleen } 33478255718fSAndi Kleen 33488255718fSAndi Kleen *new = malloc(sizeof(struct list_head)); 33498255718fSAndi Kleen if (!*new) 33508255718fSAndi Kleen return -ENOMEM; 33518255718fSAndi Kleen INIT_LIST_HEAD(*new); 33528255718fSAndi Kleen 33538255718fSAndi Kleen list_for_each_entry (term, old, list) { 33548255718fSAndi Kleen ret = parse_events_term__clone(&n, term); 33558255718fSAndi Kleen if (ret) 33568255718fSAndi Kleen return ret; 33578255718fSAndi Kleen list_add_tail(&n->list, *new); 33588255718fSAndi Kleen } 33598255718fSAndi Kleen return 0; 33608255718fSAndi Kleen } 33618255718fSAndi Kleen 3362fc0a2c1dSArnaldo Carvalho de Melo void parse_events_terms__purge(struct list_head *terms) 33638f707d84SJiri Olsa { 33646cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 33658f707d84SJiri Olsa 3366a8adfcebSWang Nan list_for_each_entry_safe(term, h, terms, list) { 3367a8adfcebSWang Nan list_del_init(&term->list); 33681dc92556SIan Rogers parse_events_term__delete(term); 33698f707d84SJiri Olsa } 3370a8adfcebSWang Nan } 3371b39b8393SJiri Olsa 33722146afc6SArnaldo Carvalho de Melo void parse_events_terms__delete(struct list_head *terms) 3373fc0a2c1dSArnaldo Carvalho de Melo { 33742146afc6SArnaldo Carvalho de Melo if (!terms) 33752146afc6SArnaldo Carvalho de Melo return; 3376fc0a2c1dSArnaldo Carvalho de Melo parse_events_terms__purge(terms); 3377d20a5f2bSWang Nan free(terms); 3378fc0a2c1dSArnaldo Carvalho de Melo } 3379fc0a2c1dSArnaldo Carvalho de Melo 33802d055bf2SWang Nan void parse_events__clear_array(struct parse_events_array *a) 33812d055bf2SWang Nan { 3382360e071bSTaeung Song zfree(&a->ranges); 33832d055bf2SWang Nan } 33842d055bf2SWang Nan 33855d9cdc11SArnaldo Carvalho de Melo void parse_events_evlist_error(struct parse_events_state *parse_state, 3386b39b8393SJiri Olsa int idx, const char *str) 3387b39b8393SJiri Olsa { 3388448d732cSIan Rogers if (!parse_state->error) 3389a6ced2beSAdrian Hunter return; 3390448d732cSIan Rogers 33916c191289SIan Rogers parse_events_error__handle(parse_state->error, idx, strdup(str), NULL); 3392b39b8393SJiri Olsa } 3393ffeb883eSHe Kuang 339417cb5f84SWang Nan static void config_terms_list(char *buf, size_t buf_sz) 339517cb5f84SWang Nan { 339617cb5f84SWang Nan int i; 339717cb5f84SWang Nan bool first = true; 339817cb5f84SWang Nan 339917cb5f84SWang Nan buf[0] = '\0'; 340017cb5f84SWang Nan for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) { 340117cb5f84SWang Nan const char *name = config_term_names[i]; 340217cb5f84SWang Nan 34031669e509SWang Nan if (!config_term_avail(i, NULL)) 34041669e509SWang Nan continue; 340517cb5f84SWang Nan if (!name) 340617cb5f84SWang Nan continue; 340717cb5f84SWang Nan if (name[0] == '<') 340817cb5f84SWang Nan continue; 340917cb5f84SWang Nan 341017cb5f84SWang Nan if (strlen(buf) + strlen(name) + 2 >= buf_sz) 341117cb5f84SWang Nan return; 341217cb5f84SWang Nan 341317cb5f84SWang Nan if (!first) 341417cb5f84SWang Nan strcat(buf, ","); 341517cb5f84SWang Nan else 341617cb5f84SWang Nan first = false; 341717cb5f84SWang Nan strcat(buf, name); 341817cb5f84SWang Nan } 341917cb5f84SWang Nan } 342017cb5f84SWang Nan 3421ffeb883eSHe Kuang /* 3422ffeb883eSHe Kuang * Return string contains valid config terms of an event. 3423ffeb883eSHe Kuang * @additional_terms: For terms such as PMU sysfs terms. 3424ffeb883eSHe Kuang */ 3425ffeb883eSHe Kuang char *parse_events_formats_error_string(char *additional_terms) 3426ffeb883eSHe Kuang { 3427ffeb883eSHe Kuang char *str; 3428626a6b78SWang Nan /* "no-overwrite" is the longest name */ 342917cb5f84SWang Nan char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * 3430626a6b78SWang Nan (sizeof("no-overwrite") - 1)]; 3431ffeb883eSHe Kuang 343217cb5f84SWang Nan config_terms_list(static_terms, sizeof(static_terms)); 3433ffeb883eSHe Kuang /* valid terms */ 3434ffeb883eSHe Kuang if (additional_terms) { 343526dee028SWang Nan if (asprintf(&str, "valid terms: %s,%s", 343626dee028SWang Nan additional_terms, static_terms) < 0) 3437ffeb883eSHe Kuang goto fail; 3438ffeb883eSHe Kuang } else { 343926dee028SWang Nan if (asprintf(&str, "valid terms: %s", static_terms) < 0) 3440ffeb883eSHe Kuang goto fail; 3441ffeb883eSHe Kuang } 3442ffeb883eSHe Kuang return str; 3443ffeb883eSHe Kuang 3444ffeb883eSHe Kuang fail: 3445ffeb883eSHe Kuang return NULL; 3446ffeb883eSHe Kuang } 34479cbfa2f6SJin Yao 34489cbfa2f6SJin Yao struct evsel *parse_events__add_event_hybrid(struct list_head *list, int *idx, 34499cbfa2f6SJin Yao struct perf_event_attr *attr, 34502b62b3a6SIan Rogers const char *name, 34512b62b3a6SIan Rogers const char *metric_id, 34522b62b3a6SIan Rogers struct perf_pmu *pmu, 34539cbfa2f6SJin Yao struct list_head *config_terms) 34549cbfa2f6SJin Yao { 34552b62b3a6SIan Rogers return __add_event(list, idx, attr, /*init_attr=*/true, name, metric_id, 34562b62b3a6SIan Rogers pmu, config_terms, /*auto_merge_stats=*/false, 34572b62b3a6SIan Rogers /*cpu_list=*/NULL); 34589cbfa2f6SJin Yao } 3459