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" 225aab621bSArnaldo Carvalho de Melo #include "symbol.h" 238755a8f2SArjan van de Ven #include "header.h" 2484c86ca1SWang Nan #include "bpf-loader.h" 256e81c74cSMasami Hiramatsu #include "debug.h" 26592d5a6bSJiri Olsa #include <api/fs/tracing_path.h> 279c3516d1SJiri Olsa #include <perf/cpumap.h> 28ac20de6fSZheng Yan #include "parse-events-bison.h" 291244a327SJiri Olsa #define YY_EXTRA_TYPE void* 3089812fc8SJiri Olsa #include "parse-events-flex.h" 315f537a26SJiri Olsa #include "pmu.h" 32b41f1cecSNamhyung Kim #include "thread_map.h" 3340218daeSMasami Hiramatsu #include "probe-file.h" 34b39b8393SJiri Olsa #include "asm/bug.h" 35ac12f676SAndi Kleen #include "util/parse-branch-options.h" 3671b0acceSAndi Kleen #include "metricgroup.h" 3795be9d19SArnaldo Carvalho de Melo #include "util/evsel_config.h" 38252a2fdcSArnaldo Carvalho de Melo #include "util/event.h" 3970943490SStephane Eranian #include "util/pfm.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); 50bcd3279fSFrederic Weisbecker 51dcb4e102SKan Liang static struct perf_pmu_event_symbol *perf_pmu_events_list; 52dcb4e102SKan Liang /* 53dcb4e102SKan Liang * The variable indicates the number of supported pmu event symbols. 54dcb4e102SKan Liang * 0 means not initialized and ready to init 55dcb4e102SKan Liang * -1 means failed to init, don't try anymore 56dcb4e102SKan Liang * >0 is the number of supported pmu event symbols 57dcb4e102SKan Liang */ 58dcb4e102SKan Liang static int perf_pmu_events_list_num; 59dcb4e102SKan Liang 60705750f2SYunlong Song struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 611dc12760SJiri Olsa [PERF_COUNT_HW_CPU_CYCLES] = { 621dc12760SJiri Olsa .symbol = "cpu-cycles", 631dc12760SJiri Olsa .alias = "cycles", 641dc12760SJiri Olsa }, 651dc12760SJiri Olsa [PERF_COUNT_HW_INSTRUCTIONS] = { 661dc12760SJiri Olsa .symbol = "instructions", 671dc12760SJiri Olsa .alias = "", 681dc12760SJiri Olsa }, 691dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_REFERENCES] = { 701dc12760SJiri Olsa .symbol = "cache-references", 711dc12760SJiri Olsa .alias = "", 721dc12760SJiri Olsa }, 731dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_MISSES] = { 741dc12760SJiri Olsa .symbol = "cache-misses", 751dc12760SJiri Olsa .alias = "", 761dc12760SJiri Olsa }, 771dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 781dc12760SJiri Olsa .symbol = "branch-instructions", 791dc12760SJiri Olsa .alias = "branches", 801dc12760SJiri Olsa }, 811dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_MISSES] = { 821dc12760SJiri Olsa .symbol = "branch-misses", 831dc12760SJiri Olsa .alias = "", 841dc12760SJiri Olsa }, 851dc12760SJiri Olsa [PERF_COUNT_HW_BUS_CYCLES] = { 861dc12760SJiri Olsa .symbol = "bus-cycles", 871dc12760SJiri Olsa .alias = "", 881dc12760SJiri Olsa }, 891dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = { 901dc12760SJiri Olsa .symbol = "stalled-cycles-frontend", 911dc12760SJiri Olsa .alias = "idle-cycles-frontend", 921dc12760SJiri Olsa }, 931dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = { 941dc12760SJiri Olsa .symbol = "stalled-cycles-backend", 951dc12760SJiri Olsa .alias = "idle-cycles-backend", 961dc12760SJiri Olsa }, 971dc12760SJiri Olsa [PERF_COUNT_HW_REF_CPU_CYCLES] = { 981dc12760SJiri Olsa .symbol = "ref-cycles", 991dc12760SJiri Olsa .alias = "", 1001dc12760SJiri Olsa }, 1011dc12760SJiri Olsa }; 10286470930SIngo Molnar 103705750f2SYunlong Song struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { 1041dc12760SJiri Olsa [PERF_COUNT_SW_CPU_CLOCK] = { 1051dc12760SJiri Olsa .symbol = "cpu-clock", 1061dc12760SJiri Olsa .alias = "", 1071dc12760SJiri Olsa }, 1081dc12760SJiri Olsa [PERF_COUNT_SW_TASK_CLOCK] = { 1091dc12760SJiri Olsa .symbol = "task-clock", 1101dc12760SJiri Olsa .alias = "", 1111dc12760SJiri Olsa }, 1121dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS] = { 1131dc12760SJiri Olsa .symbol = "page-faults", 1141dc12760SJiri Olsa .alias = "faults", 1151dc12760SJiri Olsa }, 1161dc12760SJiri Olsa [PERF_COUNT_SW_CONTEXT_SWITCHES] = { 1171dc12760SJiri Olsa .symbol = "context-switches", 1181dc12760SJiri Olsa .alias = "cs", 1191dc12760SJiri Olsa }, 1201dc12760SJiri Olsa [PERF_COUNT_SW_CPU_MIGRATIONS] = { 1211dc12760SJiri Olsa .symbol = "cpu-migrations", 1221dc12760SJiri Olsa .alias = "migrations", 1231dc12760SJiri Olsa }, 1241dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MIN] = { 1251dc12760SJiri Olsa .symbol = "minor-faults", 1261dc12760SJiri Olsa .alias = "", 1271dc12760SJiri Olsa }, 1281dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = { 1291dc12760SJiri Olsa .symbol = "major-faults", 1301dc12760SJiri Olsa .alias = "", 1311dc12760SJiri Olsa }, 1321dc12760SJiri Olsa [PERF_COUNT_SW_ALIGNMENT_FAULTS] = { 1331dc12760SJiri Olsa .symbol = "alignment-faults", 1341dc12760SJiri Olsa .alias = "", 1351dc12760SJiri Olsa }, 1361dc12760SJiri Olsa [PERF_COUNT_SW_EMULATION_FAULTS] = { 1371dc12760SJiri Olsa .symbol = "emulation-faults", 1381dc12760SJiri Olsa .alias = "", 1391dc12760SJiri Olsa }, 140d22d1a2aSAdrian Hunter [PERF_COUNT_SW_DUMMY] = { 141d22d1a2aSAdrian Hunter .symbol = "dummy", 142d22d1a2aSAdrian Hunter .alias = "", 143d22d1a2aSAdrian Hunter }, 144bae9cc41SArnaldo Carvalho de Melo [PERF_COUNT_SW_BPF_OUTPUT] = { 145bae9cc41SArnaldo Carvalho de Melo .symbol = "bpf-output", 146bae9cc41SArnaldo Carvalho de Melo .alias = "", 147bae9cc41SArnaldo Carvalho de Melo }, 14886470930SIngo Molnar }; 14986470930SIngo Molnar 150cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \ 151cdd6c482SIngo Molnar ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 15286470930SIngo Molnar 153cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 154cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 155cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 156cdd6c482SIngo Molnar #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 15786470930SIngo Molnar 15822a9f41bSArnaldo Carvalho de Melo #define for_each_subsystem(sys_dir, sys_dirent) \ 15922a9f41bSArnaldo Carvalho de Melo while ((sys_dirent = readdir(sys_dir)) != NULL) \ 16022a9f41bSArnaldo Carvalho de Melo if (sys_dirent->d_type == DT_DIR && \ 16122a9f41bSArnaldo Carvalho de Melo (strcmp(sys_dirent->d_name, ".")) && \ 16222a9f41bSArnaldo Carvalho de Melo (strcmp(sys_dirent->d_name, ".."))) 163f6bdafefSJason Baron 164c02cab22SArnaldo Carvalho de Melo static int tp_event_has_id(const char *dir_path, struct dirent *evt_dir) 165ae07b63fSPeter Zijlstra { 166ae07b63fSPeter Zijlstra char evt_path[MAXPATHLEN]; 167ae07b63fSPeter Zijlstra int fd; 168ae07b63fSPeter Zijlstra 169c02cab22SArnaldo Carvalho de Melo snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dir->d_name); 170ae07b63fSPeter Zijlstra fd = open(evt_path, O_RDONLY); 171ae07b63fSPeter Zijlstra if (fd < 0) 172ae07b63fSPeter Zijlstra return -EINVAL; 173ae07b63fSPeter Zijlstra close(fd); 174ae07b63fSPeter Zijlstra 175ae07b63fSPeter Zijlstra return 0; 176ae07b63fSPeter Zijlstra } 177ae07b63fSPeter Zijlstra 178c02cab22SArnaldo Carvalho de Melo #define for_each_event(dir_path, evt_dir, evt_dirent) \ 17922a9f41bSArnaldo Carvalho de Melo while ((evt_dirent = readdir(evt_dir)) != NULL) \ 18022a9f41bSArnaldo Carvalho de Melo if (evt_dirent->d_type == DT_DIR && \ 18122a9f41bSArnaldo Carvalho de Melo (strcmp(evt_dirent->d_name, ".")) && \ 18222a9f41bSArnaldo Carvalho de Melo (strcmp(evt_dirent->d_name, "..")) && \ 183c02cab22SArnaldo Carvalho de Melo (!tp_event_has_id(dir_path, evt_dirent))) 184f6bdafefSJason Baron 185270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512 186f6bdafefSJason Baron 187448d732cSIan Rogers void parse_events__handle_error(struct parse_events_error *err, int idx, 188448d732cSIan Rogers char *str, char *help) 189448d732cSIan Rogers { 190448d732cSIan Rogers if (WARN(!str, "WARNING: failed to provide error string\n")) { 191448d732cSIan Rogers free(help); 192448d732cSIan Rogers return; 193448d732cSIan Rogers } 194a910e466SIan Rogers switch (err->num_errors) { 195a910e466SIan Rogers case 0: 196448d732cSIan Rogers err->idx = idx; 197a910e466SIan Rogers err->str = str; 198a910e466SIan Rogers err->help = help; 199a910e466SIan Rogers break; 200a910e466SIan Rogers case 1: 201a910e466SIan Rogers err->first_idx = err->idx; 202a910e466SIan Rogers err->idx = idx; 203a910e466SIan Rogers err->first_str = err->str; 204a910e466SIan Rogers err->str = str; 205a910e466SIan Rogers err->first_help = err->help; 206a910e466SIan Rogers err->help = help; 207a910e466SIan Rogers break; 208a910e466SIan Rogers default: 2094ac22b48SIan Rogers pr_debug("Multiple errors dropping message: %s (%s)\n", 2104ac22b48SIan Rogers err->str, err->help); 211448d732cSIan Rogers free(err->str); 212448d732cSIan Rogers err->str = str; 213448d732cSIan Rogers free(err->help); 214448d732cSIan Rogers err->help = help; 215a910e466SIan Rogers break; 216a910e466SIan Rogers } 217a910e466SIan Rogers err->num_errors++; 218448d732cSIan Rogers } 219f6bdafefSJason Baron 2201ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config) 221f6bdafefSJason Baron { 2221ef2ed10SFrederic Weisbecker struct tracepoint_path *path = NULL; 223f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 22422a9f41bSArnaldo Carvalho de Melo struct dirent *sys_dirent, *evt_dirent; 2258aa8a7c8SStephane Eranian char id_buf[24]; 226725b1368SEric Dumazet int fd; 227f6bdafefSJason Baron u64 id; 228f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 22925a7d914SArnaldo Carvalho de Melo char *dir_path; 230f6bdafefSJason Baron 2317014e0e3SArnaldo Carvalho de Melo sys_dir = tracing_events__opendir(); 232f6bdafefSJason Baron if (!sys_dir) 233725b1368SEric Dumazet return NULL; 234f6bdafefSJason Baron 23522a9f41bSArnaldo Carvalho de Melo for_each_subsystem(sys_dir, sys_dirent) { 23625a7d914SArnaldo Carvalho de Melo dir_path = get_events_file(sys_dirent->d_name); 23725a7d914SArnaldo Carvalho de Melo if (!dir_path) 23825a7d914SArnaldo Carvalho de Melo continue; 239725b1368SEric Dumazet evt_dir = opendir(dir_path); 240725b1368SEric Dumazet if (!evt_dir) 24125a7d914SArnaldo Carvalho de Melo goto next; 242725b1368SEric Dumazet 243c02cab22SArnaldo Carvalho de Melo for_each_event(dir_path, evt_dir, evt_dirent) { 244725b1368SEric Dumazet 24577f18153SJiri Olsa scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 24622a9f41bSArnaldo Carvalho de Melo evt_dirent->d_name); 247725b1368SEric Dumazet fd = open(evt_path, O_RDONLY); 248f6bdafefSJason Baron if (fd < 0) 249f6bdafefSJason Baron continue; 250f6bdafefSJason Baron if (read(fd, id_buf, sizeof(id_buf)) < 0) { 251f6bdafefSJason Baron close(fd); 252f6bdafefSJason Baron continue; 253f6bdafefSJason Baron } 254f6bdafefSJason Baron close(fd); 255f6bdafefSJason Baron id = atoll(id_buf); 256f6bdafefSJason Baron if (id == config) { 25725a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 258f6bdafefSJason Baron closedir(evt_dir); 259f6bdafefSJason Baron closedir(sys_dir); 26059b4caebSJulia Lawall path = zalloc(sizeof(*path)); 2615aa365f2STaeung Song if (!path) 2625aa365f2STaeung Song return NULL; 2637125f204SArnaldo Carvalho de Melo if (asprintf(&path->system, "%.*s", MAX_EVENT_LENGTH, sys_dirent->d_name) < 0) { 2641ef2ed10SFrederic Weisbecker free(path); 2651ef2ed10SFrederic Weisbecker return NULL; 2661ef2ed10SFrederic Weisbecker } 2677125f204SArnaldo Carvalho de Melo if (asprintf(&path->name, "%.*s", MAX_EVENT_LENGTH, evt_dirent->d_name) < 0) { 26874cf249dSArnaldo Carvalho de Melo zfree(&path->system); 2691ef2ed10SFrederic Weisbecker free(path); 2701ef2ed10SFrederic Weisbecker return NULL; 2711ef2ed10SFrederic Weisbecker } 2721ef2ed10SFrederic Weisbecker return path; 273f6bdafefSJason Baron } 274f6bdafefSJason Baron } 275f6bdafefSJason Baron closedir(evt_dir); 27625a7d914SArnaldo Carvalho de Melo next: 27725a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 278f6bdafefSJason Baron } 279f6bdafefSJason Baron 280f6bdafefSJason Baron closedir(sys_dir); 2811ef2ed10SFrederic Weisbecker return NULL; 2821ef2ed10SFrederic Weisbecker } 2831ef2ed10SFrederic Weisbecker 284e7c93f09SNamhyung Kim struct tracepoint_path *tracepoint_name_to_path(const char *name) 285e7c93f09SNamhyung Kim { 286e7c93f09SNamhyung Kim struct tracepoint_path *path = zalloc(sizeof(*path)); 287e7c93f09SNamhyung Kim char *str = strchr(name, ':'); 288e7c93f09SNamhyung Kim 289e7c93f09SNamhyung Kim if (path == NULL || str == NULL) { 290e7c93f09SNamhyung Kim free(path); 291e7c93f09SNamhyung Kim return NULL; 292e7c93f09SNamhyung Kim } 293e7c93f09SNamhyung Kim 294e7c93f09SNamhyung Kim path->system = strndup(name, str - name); 295e7c93f09SNamhyung Kim path->name = strdup(str+1); 296e7c93f09SNamhyung Kim 297e7c93f09SNamhyung Kim if (path->system == NULL || path->name == NULL) { 29874cf249dSArnaldo Carvalho de Melo zfree(&path->system); 29974cf249dSArnaldo Carvalho de Melo zfree(&path->name); 300506fde11STaeung Song zfree(&path); 301e7c93f09SNamhyung Kim } 302e7c93f09SNamhyung Kim 303e7c93f09SNamhyung Kim return path; 304e7c93f09SNamhyung Kim } 305e7c93f09SNamhyung Kim 3061424dc96SDavid Ahern const char *event_type(int type) 3071424dc96SDavid Ahern { 3081424dc96SDavid Ahern switch (type) { 3091424dc96SDavid Ahern case PERF_TYPE_HARDWARE: 3101424dc96SDavid Ahern return "hardware"; 3111424dc96SDavid Ahern 3121424dc96SDavid Ahern case PERF_TYPE_SOFTWARE: 3131424dc96SDavid Ahern return "software"; 3141424dc96SDavid Ahern 3151424dc96SDavid Ahern case PERF_TYPE_TRACEPOINT: 3161424dc96SDavid Ahern return "tracepoint"; 3171424dc96SDavid Ahern 3181424dc96SDavid Ahern case PERF_TYPE_HW_CACHE: 3191424dc96SDavid Ahern return "hardware-cache"; 3201424dc96SDavid Ahern 3211424dc96SDavid Ahern default: 3221424dc96SDavid Ahern break; 3231424dc96SDavid Ahern } 3241424dc96SDavid Ahern 3251424dc96SDavid Ahern return "unknown"; 3261424dc96SDavid Ahern } 3271424dc96SDavid Ahern 328e814fdddSWang Nan static int parse_events__is_name_term(struct parse_events_term *term) 329e814fdddSWang Nan { 330e814fdddSWang Nan return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME; 331e814fdddSWang Nan } 3327ae92e74SYan, Zheng 333e814fdddSWang Nan static char *get_config_name(struct list_head *head_terms) 334e814fdddSWang Nan { 335e814fdddSWang Nan struct parse_events_term *term; 336e814fdddSWang Nan 337e814fdddSWang Nan if (!head_terms) 338e814fdddSWang Nan return NULL; 339e814fdddSWang Nan 340e814fdddSWang Nan list_for_each_entry(term, head_terms, list) 341e814fdddSWang Nan if (parse_events__is_name_term(term)) 342e814fdddSWang Nan return term->val.str; 343e814fdddSWang Nan 344e814fdddSWang Nan return NULL; 345e814fdddSWang Nan } 3467ae92e74SYan, Zheng 34732dcd021SJiri Olsa static struct evsel * 348410136f5SStephane Eranian __add_event(struct list_head *list, int *idx, 3497ae92e74SYan, Zheng struct perf_event_attr *attr, 35070943490SStephane Eranian bool init_attr, 35166ec1191SMark Rutland char *name, struct perf_pmu *pmu, 352f0fbb114SAndi Kleen struct list_head *config_terms, bool auto_merge_stats, 353f0fbb114SAndi Kleen const char *cpu_list) 35489812fc8SJiri Olsa { 35532dcd021SJiri Olsa struct evsel *evsel; 3565d680be3SNamhyung Kim struct perf_cpu_map *cpus = pmu ? perf_cpu_map__get(pmu->cpus) : 3579c3516d1SJiri Olsa cpu_list ? perf_cpu_map__new(cpu_list) : NULL; 35889812fc8SJiri Olsa 35970943490SStephane Eranian if (init_attr) 36089812fc8SJiri Olsa event_attr_init(attr); 36189812fc8SJiri Olsa 3628f6725a2SArnaldo Carvalho de Melo evsel = evsel__new_idx(attr, *idx); 3630f1b550eSNamhyung Kim if (!evsel) { 3640f1b550eSNamhyung Kim perf_cpu_map__put(cpus); 365410136f5SStephane Eranian return NULL; 3660f1b550eSNamhyung Kim } 36789812fc8SJiri Olsa 36875fc5ae5STaeung Song (*idx)++; 3695d680be3SNamhyung Kim evsel->core.cpus = cpus; 370fe1f61b3SJiri Olsa evsel->core.own_cpus = perf_cpu_map__get(cpus); 371648b5af3SJiri Olsa evsel->core.system_wide = pmu ? pmu->is_uncore : false; 37263ce8449SArnaldo Carvalho de Melo evsel->auto_merge_stats = auto_merge_stats; 373f30a79b0SJiri Olsa 3749db1763cSArnaldo Carvalho de Melo if (name) 37589812fc8SJiri Olsa evsel->name = strdup(name); 376930a2e29SJiri Olsa 377930a2e29SJiri Olsa if (config_terms) 378930a2e29SJiri Olsa list_splice(config_terms, &evsel->config_terms); 379930a2e29SJiri Olsa 38070943490SStephane Eranian if (list) 381b27c4eceSJiri Olsa list_add_tail(&evsel->core.node, list); 38270943490SStephane Eranian 383410136f5SStephane Eranian return evsel; 38489812fc8SJiri Olsa } 38589812fc8SJiri Olsa 38670943490SStephane Eranian struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, 38770943490SStephane Eranian char *name, struct perf_pmu *pmu) 38870943490SStephane Eranian { 38970943490SStephane Eranian return __add_event(NULL, &idx, attr, false, name, pmu, NULL, false, 39070943490SStephane Eranian NULL); 39170943490SStephane Eranian } 39270943490SStephane Eranian 393c5cd8ac0SDavid Ahern static int add_event(struct list_head *list, int *idx, 394930a2e29SJiri Olsa struct perf_event_attr *attr, char *name, 395930a2e29SJiri Olsa struct list_head *config_terms) 3967ae92e74SYan, Zheng { 39770943490SStephane Eranian return __add_event(list, idx, attr, true, name, NULL, config_terms, 39870943490SStephane Eranian false, NULL) ? 0 : -ENOMEM; 399f0fbb114SAndi Kleen } 400f0fbb114SAndi Kleen 401f0fbb114SAndi Kleen static int add_event_tool(struct list_head *list, int *idx, 402f0fbb114SAndi Kleen enum perf_tool_event tool_event) 403f0fbb114SAndi Kleen { 40432dcd021SJiri Olsa struct evsel *evsel; 405f0fbb114SAndi Kleen struct perf_event_attr attr = { 406f0fbb114SAndi Kleen .type = PERF_TYPE_SOFTWARE, 407f0fbb114SAndi Kleen .config = PERF_COUNT_SW_DUMMY, 408f0fbb114SAndi Kleen }; 409f0fbb114SAndi Kleen 41070943490SStephane Eranian evsel = __add_event(list, idx, &attr, true, NULL, NULL, NULL, false, 41170943490SStephane Eranian "0"); 412f0fbb114SAndi Kleen if (!evsel) 413f0fbb114SAndi Kleen return -ENOMEM; 414f0fbb114SAndi Kleen evsel->tool_event = tool_event; 415f0fbb114SAndi Kleen if (tool_event == PERF_TOOL_DURATION_TIME) 416b12eea5aSNamhyung Kim evsel->unit = "ns"; 417f0fbb114SAndi Kleen return 0; 4187ae92e74SYan, Zheng } 4197ae92e74SYan, Zheng 420c64e85e1SArnaldo Carvalho de Melo static int parse_aliases(char *str, const char *names[][EVSEL__MAX_ALIASES], int size) 42186470930SIngo Molnar { 42286470930SIngo Molnar int i, j; 42361c45981SPaul Mackerras int n, longest = -1; 42486470930SIngo Molnar 42586470930SIngo Molnar for (i = 0; i < size; i++) { 426c64e85e1SArnaldo Carvalho de Melo for (j = 0; j < EVSEL__MAX_ALIASES && names[i][j]; j++) { 42761c45981SPaul Mackerras n = strlen(names[i][j]); 42889812fc8SJiri Olsa if (n > longest && !strncasecmp(str, names[i][j], n)) 42961c45981SPaul Mackerras longest = n; 43061c45981SPaul Mackerras } 43189812fc8SJiri Olsa if (longest > 0) 43286470930SIngo Molnar return i; 43386470930SIngo Molnar } 43486470930SIngo Molnar 4358953645fSIngo Molnar return -1; 43686470930SIngo Molnar } 43786470930SIngo Molnar 43843d0b978SWang Nan typedef int config_term_func_t(struct perf_event_attr *attr, 43943d0b978SWang Nan struct parse_events_term *term, 44043d0b978SWang Nan struct parse_events_error *err); 44143d0b978SWang Nan static int config_term_common(struct perf_event_attr *attr, 44243d0b978SWang Nan struct parse_events_term *term, 44343d0b978SWang Nan struct parse_events_error *err); 44443d0b978SWang Nan static int config_attr(struct perf_event_attr *attr, 44543d0b978SWang Nan struct list_head *head, 44643d0b978SWang Nan struct parse_events_error *err, 44743d0b978SWang Nan config_term_func_t config_term); 44843d0b978SWang Nan 449c5cd8ac0SDavid Ahern int parse_events_add_cache(struct list_head *list, int *idx, 45043d0b978SWang Nan char *type, char *op_result1, char *op_result2, 4512c97b0d4SArnaldo Carvalho de Melo struct parse_events_error *err, 45243d0b978SWang Nan struct list_head *head_config) 45386470930SIngo Molnar { 45489812fc8SJiri Olsa struct perf_event_attr attr; 45543d0b978SWang Nan LIST_HEAD(config_terms); 45643d0b978SWang Nan char name[MAX_NAME_LEN], *config_name; 45761c45981SPaul Mackerras int cache_type = -1, cache_op = -1, cache_result = -1; 45889812fc8SJiri Olsa char *op_result[2] = { op_result1, op_result2 }; 45989812fc8SJiri Olsa int i, n; 46086470930SIngo Molnar 46186470930SIngo Molnar /* 46286470930SIngo Molnar * No fallback - if we cannot get a clear cache type 46386470930SIngo Molnar * then bail out: 46486470930SIngo Molnar */ 465c64e85e1SArnaldo Carvalho de Melo cache_type = parse_aliases(type, evsel__hw_cache, PERF_COUNT_HW_CACHE_MAX); 46686470930SIngo Molnar if (cache_type == -1) 46789812fc8SJiri Olsa return -EINVAL; 46886470930SIngo Molnar 46943d0b978SWang Nan config_name = get_config_name(head_config); 47089812fc8SJiri Olsa n = snprintf(name, MAX_NAME_LEN, "%s", type); 47189812fc8SJiri Olsa 47289812fc8SJiri Olsa for (i = 0; (i < 2) && (op_result[i]); i++) { 47389812fc8SJiri Olsa char *str = op_result[i]; 47489812fc8SJiri Olsa 475275ef387SJiri Olsa n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str); 47661c45981SPaul Mackerras 47761c45981SPaul Mackerras if (cache_op == -1) { 478c64e85e1SArnaldo Carvalho de Melo cache_op = parse_aliases(str, evsel__hw_cache_op, 47961c45981SPaul Mackerras PERF_COUNT_HW_CACHE_OP_MAX); 48061c45981SPaul Mackerras if (cache_op >= 0) { 481c754c382SArnaldo Carvalho de Melo if (!evsel__is_cache_op_valid(cache_type, cache_op)) 48289812fc8SJiri Olsa return -EINVAL; 48361c45981SPaul Mackerras continue; 48461c45981SPaul Mackerras } 48561c45981SPaul Mackerras } 48661c45981SPaul Mackerras 48761c45981SPaul Mackerras if (cache_result == -1) { 488c64e85e1SArnaldo Carvalho de Melo cache_result = parse_aliases(str, evsel__hw_cache_result, 48961c45981SPaul Mackerras PERF_COUNT_HW_CACHE_RESULT_MAX); 49061c45981SPaul Mackerras if (cache_result >= 0) 49161c45981SPaul Mackerras continue; 49261c45981SPaul Mackerras } 49361c45981SPaul Mackerras } 49461c45981SPaul Mackerras 49586470930SIngo Molnar /* 49686470930SIngo Molnar * Fall back to reads: 49786470930SIngo Molnar */ 4988953645fSIngo Molnar if (cache_op == -1) 4998953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 50086470930SIngo Molnar 50186470930SIngo Molnar /* 50286470930SIngo Molnar * Fall back to accesses: 50386470930SIngo Molnar */ 50486470930SIngo Molnar if (cache_result == -1) 50586470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 50686470930SIngo Molnar 50789812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 50889812fc8SJiri Olsa attr.config = cache_type | (cache_op << 8) | (cache_result << 16); 50989812fc8SJiri Olsa attr.type = PERF_TYPE_HW_CACHE; 51043d0b978SWang Nan 51143d0b978SWang Nan if (head_config) { 5122c97b0d4SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, err, 51343d0b978SWang Nan config_term_common)) 51443d0b978SWang Nan return -EINVAL; 51543d0b978SWang Nan 51643d0b978SWang Nan if (get_config_terms(head_config, &config_terms)) 51743d0b978SWang Nan return -ENOMEM; 51843d0b978SWang Nan } 51943d0b978SWang Nan return add_event(list, idx, &attr, config_name ? : name, &config_terms); 52086470930SIngo Molnar } 52186470930SIngo Molnar 522272ed29aSJiri Olsa static void tracepoint_error(struct parse_events_error *e, int err, 5238c619d6aSWang Nan const char *sys, const char *name) 52419658171SJiri Olsa { 5254584f084SIan Rogers const char *str; 52619658171SJiri Olsa char help[BUFSIZ]; 52719658171SJiri Olsa 528ec183d22SAdrian Hunter if (!e) 529ec183d22SAdrian Hunter return; 530ec183d22SAdrian Hunter 53119658171SJiri Olsa /* 53219658171SJiri Olsa * We get error directly from syscall errno ( > 0), 53319658171SJiri Olsa * or from encoded pointer's error ( < 0). 53419658171SJiri Olsa */ 53519658171SJiri Olsa err = abs(err); 53619658171SJiri Olsa 53719658171SJiri Olsa switch (err) { 53819658171SJiri Olsa case EACCES: 5394584f084SIan Rogers str = "can't access trace events"; 54019658171SJiri Olsa break; 54119658171SJiri Olsa case ENOENT: 5424584f084SIan Rogers str = "unknown tracepoint"; 54319658171SJiri Olsa break; 54419658171SJiri Olsa default: 5454584f084SIan Rogers str = "failed to add tracepoint"; 54619658171SJiri Olsa break; 54719658171SJiri Olsa } 54819658171SJiri Olsa 54919658171SJiri Olsa tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name); 5504584f084SIan Rogers parse_events__handle_error(e, 0, strdup(str), strdup(help)); 55119658171SJiri Olsa } 55219658171SJiri Olsa 553c5cd8ac0SDavid Ahern static int add_tracepoint(struct list_head *list, int *idx, 5548c619d6aSWang Nan const char *sys_name, const char *evt_name, 555272ed29aSJiri Olsa struct parse_events_error *err, 556e637d177SHe Kuang struct list_head *head_config) 557bcd3279fSFrederic Weisbecker { 5588f6725a2SArnaldo Carvalho de Melo struct evsel *evsel = evsel__newtp_idx(sys_name, evt_name, (*idx)++); 559bcd3279fSFrederic Weisbecker 56019658171SJiri Olsa if (IS_ERR(evsel)) { 561272ed29aSJiri Olsa tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name); 5628dd2a131SJiri Olsa return PTR_ERR(evsel); 56319658171SJiri Olsa } 564bcd3279fSFrederic Weisbecker 565e637d177SHe Kuang if (head_config) { 566e637d177SHe Kuang LIST_HEAD(config_terms); 567e637d177SHe Kuang 568e637d177SHe Kuang if (get_config_terms(head_config, &config_terms)) 569e637d177SHe Kuang return -ENOMEM; 570e637d177SHe Kuang list_splice(&config_terms, &evsel->config_terms); 571e637d177SHe Kuang } 572e637d177SHe Kuang 573b27c4eceSJiri Olsa list_add_tail(&evsel->core.node, list); 57482fe1c29SArnaldo Carvalho de Melo return 0; 575bcd3279fSFrederic Weisbecker } 576bcd3279fSFrederic Weisbecker 577c5cd8ac0SDavid Ahern static int add_tracepoint_multi_event(struct list_head *list, int *idx, 5788c619d6aSWang Nan const char *sys_name, const char *evt_name, 579272ed29aSJiri Olsa struct parse_events_error *err, 580e637d177SHe Kuang struct list_head *head_config) 581bcd3279fSFrederic Weisbecker { 58225a7d914SArnaldo Carvalho de Melo char *evt_path; 583bcd3279fSFrederic Weisbecker struct dirent *evt_ent; 584bcd3279fSFrederic Weisbecker DIR *evt_dir; 58527bf90bfSJiri Olsa int ret = 0, found = 0; 586bcd3279fSFrederic Weisbecker 58725a7d914SArnaldo Carvalho de Melo evt_path = get_events_file(sys_name); 58825a7d914SArnaldo Carvalho de Melo if (!evt_path) { 58925a7d914SArnaldo Carvalho de Melo tracepoint_error(err, errno, sys_name, evt_name); 59025a7d914SArnaldo Carvalho de Melo return -1; 59125a7d914SArnaldo Carvalho de Melo } 592bcd3279fSFrederic Weisbecker evt_dir = opendir(evt_path); 593bcd3279fSFrederic Weisbecker if (!evt_dir) { 59425a7d914SArnaldo Carvalho de Melo put_events_file(evt_path); 595272ed29aSJiri Olsa tracepoint_error(err, errno, sys_name, evt_name); 59689812fc8SJiri Olsa return -1; 597bcd3279fSFrederic Weisbecker } 598bcd3279fSFrederic Weisbecker 59989812fc8SJiri Olsa while (!ret && (evt_ent = readdir(evt_dir))) { 600bcd3279fSFrederic Weisbecker if (!strcmp(evt_ent->d_name, ".") 601bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "..") 602bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "enable") 603bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "filter")) 604bcd3279fSFrederic Weisbecker continue; 605bcd3279fSFrederic Weisbecker 60689812fc8SJiri Olsa if (!strglobmatch(evt_ent->d_name, evt_name)) 607fb1d2edfSMasami Hiramatsu continue; 608fb1d2edfSMasami Hiramatsu 60927bf90bfSJiri Olsa found++; 61027bf90bfSJiri Olsa 611e637d177SHe Kuang ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, 612272ed29aSJiri Olsa err, head_config); 613bcd3279fSFrederic Weisbecker } 614bcd3279fSFrederic Weisbecker 61527bf90bfSJiri Olsa if (!found) { 61627bf90bfSJiri Olsa tracepoint_error(err, ENOENT, sys_name, evt_name); 61727bf90bfSJiri Olsa ret = -1; 61827bf90bfSJiri Olsa } 61927bf90bfSJiri Olsa 62025a7d914SArnaldo Carvalho de Melo put_events_file(evt_path); 6210bd3f084SJiri Olsa closedir(evt_dir); 62289812fc8SJiri Olsa return ret; 623bcd3279fSFrederic Weisbecker } 624bcd3279fSFrederic Weisbecker 625c5cd8ac0SDavid Ahern static int add_tracepoint_event(struct list_head *list, int *idx, 6268c619d6aSWang Nan const char *sys_name, const char *evt_name, 627272ed29aSJiri Olsa struct parse_events_error *err, 628e637d177SHe Kuang struct list_head *head_config) 629f35488f9SJiri Olsa { 630f35488f9SJiri Olsa return strpbrk(evt_name, "*?") ? 631e637d177SHe Kuang add_tracepoint_multi_event(list, idx, sys_name, evt_name, 632272ed29aSJiri Olsa err, head_config) : 633e637d177SHe Kuang add_tracepoint(list, idx, sys_name, evt_name, 634272ed29aSJiri Olsa err, head_config); 635f35488f9SJiri Olsa } 636f35488f9SJiri Olsa 637c5cd8ac0SDavid Ahern static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 6388c619d6aSWang Nan const char *sys_name, const char *evt_name, 639272ed29aSJiri Olsa struct parse_events_error *err, 640e637d177SHe Kuang struct list_head *head_config) 641f35488f9SJiri Olsa { 642f35488f9SJiri Olsa struct dirent *events_ent; 643f35488f9SJiri Olsa DIR *events_dir; 644f35488f9SJiri Olsa int ret = 0; 645f35488f9SJiri Olsa 6467014e0e3SArnaldo Carvalho de Melo events_dir = tracing_events__opendir(); 647f35488f9SJiri Olsa if (!events_dir) { 648272ed29aSJiri Olsa tracepoint_error(err, errno, sys_name, evt_name); 649f35488f9SJiri Olsa return -1; 650f35488f9SJiri Olsa } 651f35488f9SJiri Olsa 652f35488f9SJiri Olsa while (!ret && (events_ent = readdir(events_dir))) { 653f35488f9SJiri Olsa if (!strcmp(events_ent->d_name, ".") 654f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "..") 655f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "enable") 656f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_event") 657f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_page")) 658f35488f9SJiri Olsa continue; 659f35488f9SJiri Olsa 660f35488f9SJiri Olsa if (!strglobmatch(events_ent->d_name, sys_name)) 661f35488f9SJiri Olsa continue; 662f35488f9SJiri Olsa 663f35488f9SJiri Olsa ret = add_tracepoint_event(list, idx, events_ent->d_name, 664272ed29aSJiri Olsa evt_name, err, head_config); 665f35488f9SJiri Olsa } 666f35488f9SJiri Olsa 667f35488f9SJiri Olsa closedir(events_dir); 668f35488f9SJiri Olsa return ret; 669f35488f9SJiri Olsa } 670f35488f9SJiri Olsa 671c18cf78dSArnaldo Carvalho de Melo #ifdef HAVE_LIBBPF_SUPPORT 6724edf30e3SWang Nan struct __add_bpf_event_param { 6735d9cdc11SArnaldo Carvalho de Melo struct parse_events_state *parse_state; 6744edf30e3SWang Nan struct list_head *list; 67595088a59SWang Nan struct list_head *head_config; 6764edf30e3SWang Nan }; 6774edf30e3SWang Nan 678af4a0991SArnaldo Carvalho de Melo static int add_bpf_event(const char *group, const char *event, int fd, struct bpf_object *obj, 6794edf30e3SWang Nan void *_param) 6804edf30e3SWang Nan { 6814edf30e3SWang Nan LIST_HEAD(new_evsels); 6824edf30e3SWang Nan struct __add_bpf_event_param *param = _param; 6835d9cdc11SArnaldo Carvalho de Melo struct parse_events_state *parse_state = param->parse_state; 6844edf30e3SWang Nan struct list_head *list = param->list; 68532dcd021SJiri Olsa struct evsel *pos; 6864edf30e3SWang Nan int err; 6872620b7e3SArnaldo Carvalho de Melo /* 6882620b7e3SArnaldo Carvalho de Melo * Check if we should add the event, i.e. if it is a TP but starts with a '!', 6892620b7e3SArnaldo Carvalho de Melo * then don't add the tracepoint, this will be used for something else, like 6902620b7e3SArnaldo Carvalho de Melo * adding to a BPF_MAP_TYPE_PROG_ARRAY. 6912620b7e3SArnaldo Carvalho de Melo * 6922620b7e3SArnaldo Carvalho de Melo * See tools/perf/examples/bpf/augmented_raw_syscalls.c 6932620b7e3SArnaldo Carvalho de Melo */ 6942620b7e3SArnaldo Carvalho de Melo if (group[0] == '!') 6952620b7e3SArnaldo Carvalho de Melo return 0; 6964edf30e3SWang Nan 6974edf30e3SWang Nan pr_debug("add bpf event %s:%s and attach bpf program %d\n", 698cd102d70SWang Nan group, event, fd); 6994edf30e3SWang Nan 7005d369a75SArnaldo Carvalho de Melo err = parse_events_add_tracepoint(&new_evsels, &parse_state->idx, group, 7015d369a75SArnaldo Carvalho de Melo event, parse_state->error, 70295088a59SWang Nan param->head_config); 7034edf30e3SWang Nan if (err) { 70432dcd021SJiri Olsa struct evsel *evsel, *tmp; 7054edf30e3SWang Nan 7064edf30e3SWang Nan pr_debug("Failed to add BPF event %s:%s\n", 707cd102d70SWang Nan group, event); 708b27c4eceSJiri Olsa list_for_each_entry_safe(evsel, tmp, &new_evsels, core.node) { 709b27c4eceSJiri Olsa list_del_init(&evsel->core.node); 7105eb2dd2aSJiri Olsa evsel__delete(evsel); 7114edf30e3SWang Nan } 7124edf30e3SWang Nan return err; 7134edf30e3SWang Nan } 714cd102d70SWang Nan pr_debug("adding %s:%s\n", group, event); 7154edf30e3SWang Nan 716b27c4eceSJiri Olsa list_for_each_entry(pos, &new_evsels, core.node) { 7171f45b1d4SWang Nan pr_debug("adding %s:%s to %p\n", 718cd102d70SWang Nan group, event, pos); 7191f45b1d4SWang Nan pos->bpf_fd = fd; 720af4a0991SArnaldo Carvalho de Melo pos->bpf_obj = obj; 7211f45b1d4SWang Nan } 7224edf30e3SWang Nan list_splice(&new_evsels, list); 7234edf30e3SWang Nan return 0; 7244edf30e3SWang Nan } 7254edf30e3SWang Nan 7265d9cdc11SArnaldo Carvalho de Melo int parse_events_load_bpf_obj(struct parse_events_state *parse_state, 72784c86ca1SWang Nan struct list_head *list, 72895088a59SWang Nan struct bpf_object *obj, 72995088a59SWang Nan struct list_head *head_config) 73084c86ca1SWang Nan { 73184c86ca1SWang Nan int err; 73284c86ca1SWang Nan char errbuf[BUFSIZ]; 7335d9cdc11SArnaldo Carvalho de Melo struct __add_bpf_event_param param = {parse_state, list, head_config}; 734aa3abf30SWang Nan static bool registered_unprobe_atexit = false; 73584c86ca1SWang Nan 73684c86ca1SWang Nan if (IS_ERR(obj) || !obj) { 73784c86ca1SWang Nan snprintf(errbuf, sizeof(errbuf), 73884c86ca1SWang Nan "Internal error: load bpf obj with NULL"); 73984c86ca1SWang Nan err = -EINVAL; 74084c86ca1SWang Nan goto errout; 74184c86ca1SWang Nan } 74284c86ca1SWang Nan 74384c86ca1SWang Nan /* 744aa3abf30SWang Nan * Register atexit handler before calling bpf__probe() so 745aa3abf30SWang Nan * bpf__probe() don't need to unprobe probe points its already 746aa3abf30SWang Nan * created when failure. 747aa3abf30SWang Nan */ 748aa3abf30SWang Nan if (!registered_unprobe_atexit) { 749aa3abf30SWang Nan atexit(bpf__clear); 750aa3abf30SWang Nan registered_unprobe_atexit = true; 751aa3abf30SWang Nan } 752aa3abf30SWang Nan 753aa3abf30SWang Nan err = bpf__probe(obj); 754aa3abf30SWang Nan if (err) { 755aa3abf30SWang Nan bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf)); 756aa3abf30SWang Nan goto errout; 757aa3abf30SWang Nan } 758aa3abf30SWang Nan 7591e5e3ee8SWang Nan err = bpf__load(obj); 7601e5e3ee8SWang Nan if (err) { 7611e5e3ee8SWang Nan bpf__strerror_load(obj, err, errbuf, sizeof(errbuf)); 7621e5e3ee8SWang Nan goto errout; 7631e5e3ee8SWang Nan } 7641e5e3ee8SWang Nan 765cd102d70SWang Nan err = bpf__foreach_event(obj, add_bpf_event, ¶m); 7664edf30e3SWang Nan if (err) { 7674edf30e3SWang Nan snprintf(errbuf, sizeof(errbuf), 7684edf30e3SWang Nan "Attach events in BPF object failed"); 7694edf30e3SWang Nan goto errout; 7704edf30e3SWang Nan } 7714edf30e3SWang Nan 7724edf30e3SWang Nan return 0; 77384c86ca1SWang Nan errout: 7745f634c8eSIan Rogers parse_events__handle_error(parse_state->error, 0, 7755f634c8eSIan Rogers strdup(errbuf), strdup("(add -v to see detail)")); 77684c86ca1SWang Nan return err; 77784c86ca1SWang Nan } 77884c86ca1SWang Nan 779a34f3be7SWang Nan static int 7805d9cdc11SArnaldo Carvalho de Melo parse_events_config_bpf(struct parse_events_state *parse_state, 781a34f3be7SWang Nan struct bpf_object *obj, 782a34f3be7SWang Nan struct list_head *head_config) 783a34f3be7SWang Nan { 784a34f3be7SWang Nan struct parse_events_term *term; 785a34f3be7SWang Nan int error_pos; 786a34f3be7SWang Nan 787a34f3be7SWang Nan if (!head_config || list_empty(head_config)) 788a34f3be7SWang Nan return 0; 789a34f3be7SWang Nan 790a34f3be7SWang Nan list_for_each_entry(term, head_config, list) { 791a34f3be7SWang Nan int err; 792a34f3be7SWang Nan 793a34f3be7SWang Nan if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) { 7945f634c8eSIan Rogers parse_events__handle_error(parse_state->error, term->err_term, 7955f634c8eSIan Rogers strdup("Invalid config term for BPF object"), 7965f634c8eSIan Rogers NULL); 797a34f3be7SWang Nan return -EINVAL; 798a34f3be7SWang Nan } 799a34f3be7SWang Nan 8005d9cdc11SArnaldo Carvalho de Melo err = bpf__config_obj(obj, term, parse_state->evlist, &error_pos); 801a34f3be7SWang Nan if (err) { 8025f634c8eSIan Rogers char errbuf[BUFSIZ]; 8035f634c8eSIan Rogers int idx; 8045f634c8eSIan Rogers 8055d9cdc11SArnaldo Carvalho de Melo bpf__strerror_config_obj(obj, term, parse_state->evlist, 806a34f3be7SWang Nan &error_pos, err, errbuf, 807a34f3be7SWang Nan sizeof(errbuf)); 8085f634c8eSIan Rogers 8095f634c8eSIan Rogers if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE) 8105f634c8eSIan Rogers idx = term->err_val; 8115f634c8eSIan Rogers else 8125f634c8eSIan Rogers idx = term->err_term + error_pos; 8135f634c8eSIan Rogers 8145f634c8eSIan Rogers parse_events__handle_error(parse_state->error, idx, 8155f634c8eSIan Rogers strdup(errbuf), 8165f634c8eSIan Rogers strdup( 8177630b3e2SWang Nan "Hint:\tValid config terms:\n" 818e571e029SWang Nan " \tmap:[<arraymap>].value<indices>=[value]\n" 819e571e029SWang Nan " \tmap:[<eventmap>].event<indices>=[event]\n" 8207630b3e2SWang Nan "\n" 821e571e029SWang Nan " \twhere <indices> is something like [0,3...5] or [all]\n" 8225f634c8eSIan Rogers " \t(add -v to see detail)")); 823a34f3be7SWang Nan return err; 824a34f3be7SWang Nan } 825a34f3be7SWang Nan } 826a34f3be7SWang Nan return 0; 827a34f3be7SWang Nan } 828a34f3be7SWang Nan 82995088a59SWang Nan /* 83095088a59SWang Nan * Split config terms: 83195088a59SWang Nan * perf record -e bpf.c/call-graph=fp,map:array.value[0]=1/ ... 83295088a59SWang Nan * 'call-graph=fp' is 'evt config', should be applied to each 83395088a59SWang Nan * events in bpf.c. 83495088a59SWang Nan * 'map:array.value[0]=1' is 'obj config', should be processed 83595088a59SWang Nan * with parse_events_config_bpf. 83695088a59SWang Nan * 83795088a59SWang Nan * Move object config terms from the first list to obj_head_config. 83895088a59SWang Nan */ 83995088a59SWang Nan static void 84095088a59SWang Nan split_bpf_config_terms(struct list_head *evt_head_config, 84195088a59SWang Nan struct list_head *obj_head_config) 84295088a59SWang Nan { 84395088a59SWang Nan struct parse_events_term *term, *temp; 84495088a59SWang Nan 84595088a59SWang Nan /* 846*4d39c89fSIngo Molnar * Currently, all possible user config term 84795088a59SWang Nan * belong to bpf object. parse_events__is_hardcoded_term() 848*4d39c89fSIngo Molnar * happens to be a good flag. 84995088a59SWang Nan * 85095088a59SWang Nan * See parse_events_config_bpf() and 85195088a59SWang Nan * config_term_tracepoint(). 85295088a59SWang Nan */ 85395088a59SWang Nan list_for_each_entry_safe(term, temp, evt_head_config, list) 85495088a59SWang Nan if (!parse_events__is_hardcoded_term(term)) 85595088a59SWang Nan list_move_tail(&term->list, obj_head_config); 85695088a59SWang Nan } 85795088a59SWang Nan 8585d9cdc11SArnaldo Carvalho de Melo int parse_events_load_bpf(struct parse_events_state *parse_state, 85984c86ca1SWang Nan struct list_head *list, 860d509db04SWang Nan char *bpf_file_name, 861a34f3be7SWang Nan bool source, 862a34f3be7SWang Nan struct list_head *head_config) 86384c86ca1SWang Nan { 864a34f3be7SWang Nan int err; 86595088a59SWang Nan struct bpf_object *obj; 86695088a59SWang Nan LIST_HEAD(obj_head_config); 86795088a59SWang Nan 86895088a59SWang Nan if (head_config) 86995088a59SWang Nan split_bpf_config_terms(head_config, &obj_head_config); 87084c86ca1SWang Nan 871d509db04SWang Nan obj = bpf__prepare_load(bpf_file_name, source); 8726371ca3bSWang Nan if (IS_ERR(obj)) { 87384c86ca1SWang Nan char errbuf[BUFSIZ]; 87484c86ca1SWang Nan 8756371ca3bSWang Nan err = PTR_ERR(obj); 87684c86ca1SWang Nan 87784c86ca1SWang Nan if (err == -ENOTSUP) 87884c86ca1SWang Nan snprintf(errbuf, sizeof(errbuf), 87984c86ca1SWang Nan "BPF support is not compiled"); 88084c86ca1SWang Nan else 881d3e0ce39SWang Nan bpf__strerror_prepare_load(bpf_file_name, 882d3e0ce39SWang Nan source, 883d3e0ce39SWang Nan -err, errbuf, 884d3e0ce39SWang Nan sizeof(errbuf)); 88584c86ca1SWang Nan 8865f634c8eSIan Rogers parse_events__handle_error(parse_state->error, 0, 8875f634c8eSIan Rogers strdup(errbuf), strdup("(add -v to see detail)")); 88884c86ca1SWang Nan return err; 88984c86ca1SWang Nan } 89084c86ca1SWang Nan 8915d9cdc11SArnaldo Carvalho de Melo err = parse_events_load_bpf_obj(parse_state, list, obj, head_config); 892a34f3be7SWang Nan if (err) 893a34f3be7SWang Nan return err; 8945d9cdc11SArnaldo Carvalho de Melo err = parse_events_config_bpf(parse_state, obj, &obj_head_config); 89595088a59SWang Nan 89695088a59SWang Nan /* 89795088a59SWang Nan * Caller doesn't know anything about obj_head_config, 898*4d39c89fSIngo Molnar * so combine them together again before returning. 89995088a59SWang Nan */ 90095088a59SWang Nan if (head_config) 90195088a59SWang Nan list_splice_tail(&obj_head_config, head_config); 90295088a59SWang Nan return err; 90384c86ca1SWang Nan } 904c18cf78dSArnaldo Carvalho de Melo #else // HAVE_LIBBPF_SUPPORT 905c18cf78dSArnaldo Carvalho de Melo int parse_events_load_bpf_obj(struct parse_events_state *parse_state, 906c18cf78dSArnaldo Carvalho de Melo struct list_head *list __maybe_unused, 907c18cf78dSArnaldo Carvalho de Melo struct bpf_object *obj __maybe_unused, 908c18cf78dSArnaldo Carvalho de Melo struct list_head *head_config __maybe_unused) 909c18cf78dSArnaldo Carvalho de Melo { 910c18cf78dSArnaldo Carvalho de Melo parse_events__handle_error(parse_state->error, 0, 911c18cf78dSArnaldo Carvalho de Melo strdup("BPF support is not compiled"), 912c18cf78dSArnaldo Carvalho de Melo strdup("Make sure libbpf-devel is available at build time.")); 913c18cf78dSArnaldo Carvalho de Melo return -ENOTSUP; 914c18cf78dSArnaldo Carvalho de Melo } 915c18cf78dSArnaldo Carvalho de Melo 916c18cf78dSArnaldo Carvalho de Melo int parse_events_load_bpf(struct parse_events_state *parse_state, 917c18cf78dSArnaldo Carvalho de Melo struct list_head *list __maybe_unused, 918c18cf78dSArnaldo Carvalho de Melo char *bpf_file_name __maybe_unused, 919c18cf78dSArnaldo Carvalho de Melo bool source __maybe_unused, 920c18cf78dSArnaldo Carvalho de Melo struct list_head *head_config __maybe_unused) 921c18cf78dSArnaldo Carvalho de Melo { 922c18cf78dSArnaldo Carvalho de Melo parse_events__handle_error(parse_state->error, 0, 923c18cf78dSArnaldo Carvalho de Melo strdup("BPF support is not compiled"), 924c18cf78dSArnaldo Carvalho de Melo strdup("Make sure libbpf-devel is available at build time.")); 925c18cf78dSArnaldo Carvalho de Melo return -ENOTSUP; 926c18cf78dSArnaldo Carvalho de Melo } 927c18cf78dSArnaldo Carvalho de Melo #endif // HAVE_LIBBPF_SUPPORT 92884c86ca1SWang Nan 92989812fc8SJiri Olsa static int 93089812fc8SJiri Olsa parse_breakpoint_type(const char *type, struct perf_event_attr *attr) 9311b290d67SFrederic Weisbecker { 9321b290d67SFrederic Weisbecker int i; 9331b290d67SFrederic Weisbecker 9341b290d67SFrederic Weisbecker for (i = 0; i < 3; i++) { 93589812fc8SJiri Olsa if (!type || !type[i]) 9361b290d67SFrederic Weisbecker break; 9371b290d67SFrederic Weisbecker 9387582732fSJiri Olsa #define CHECK_SET_TYPE(bit) \ 9397582732fSJiri Olsa do { \ 9407582732fSJiri Olsa if (attr->bp_type & bit) \ 9417582732fSJiri Olsa return -EINVAL; \ 9427582732fSJiri Olsa else \ 9437582732fSJiri Olsa attr->bp_type |= bit; \ 9447582732fSJiri Olsa } while (0) 9457582732fSJiri Olsa 9461b290d67SFrederic Weisbecker switch (type[i]) { 9471b290d67SFrederic Weisbecker case 'r': 9487582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_R); 9491b290d67SFrederic Weisbecker break; 9501b290d67SFrederic Weisbecker case 'w': 9517582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_W); 9521b290d67SFrederic Weisbecker break; 9531b290d67SFrederic Weisbecker case 'x': 9547582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_X); 9551b290d67SFrederic Weisbecker break; 9561b290d67SFrederic Weisbecker default: 95789812fc8SJiri Olsa return -EINVAL; 9581b290d67SFrederic Weisbecker } 9591b290d67SFrederic Weisbecker } 96089812fc8SJiri Olsa 9617582732fSJiri Olsa #undef CHECK_SET_TYPE 9627582732fSJiri Olsa 9631b290d67SFrederic Weisbecker if (!attr->bp_type) /* Default */ 9641b290d67SFrederic Weisbecker attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 9651b290d67SFrederic Weisbecker 96689812fc8SJiri Olsa return 0; 9671b290d67SFrederic Weisbecker } 9681b290d67SFrederic Weisbecker 969c5cd8ac0SDavid Ahern int parse_events_add_breakpoint(struct list_head *list, int *idx, 970aa98d848SIan Rogers u64 addr, char *type, u64 len) 9711b290d67SFrederic Weisbecker { 97289812fc8SJiri Olsa struct perf_event_attr attr; 9731b290d67SFrederic Weisbecker 97489812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 975aa98d848SIan Rogers attr.bp_addr = addr; 9761b290d67SFrederic Weisbecker 97789812fc8SJiri Olsa if (parse_breakpoint_type(type, &attr)) 97889812fc8SJiri Olsa return -EINVAL; 9791b290d67SFrederic Weisbecker 9803741eb9fSJacob Shin /* Provide some defaults if len is not specified */ 9813741eb9fSJacob Shin if (!len) { 98289812fc8SJiri Olsa if (attr.bp_type == HW_BREAKPOINT_X) 9833741eb9fSJacob Shin len = sizeof(long); 984aa59a485SFrederic Weisbecker else 9853741eb9fSJacob Shin len = HW_BREAKPOINT_LEN_4; 9863741eb9fSJacob Shin } 9873741eb9fSJacob Shin 9883741eb9fSJacob Shin attr.bp_len = len; 989aa59a485SFrederic Weisbecker 99089812fc8SJiri Olsa attr.type = PERF_TYPE_BREAKPOINT; 9914a841d65SJovi Zhang attr.sample_period = 1; 9921b290d67SFrederic Weisbecker 993930a2e29SJiri Olsa return add_event(list, idx, &attr, NULL, NULL); 9941b290d67SFrederic Weisbecker } 9951b290d67SFrederic Weisbecker 9963b0e371cSJiri Olsa static int check_type_val(struct parse_events_term *term, 9973b0e371cSJiri Olsa struct parse_events_error *err, 9983b0e371cSJiri Olsa int type) 9993b0e371cSJiri Olsa { 10003b0e371cSJiri Olsa if (type == term->type_val) 10013b0e371cSJiri Olsa return 0; 10023b0e371cSJiri Olsa 10033b0e371cSJiri Olsa if (err) { 1004448d732cSIan Rogers parse_events__handle_error(err, term->err_val, 1005448d732cSIan Rogers type == PARSE_EVENTS__TERM_TYPE_NUM 1006448d732cSIan Rogers ? strdup("expected numeric value") 1007448d732cSIan Rogers : strdup("expected string value"), 1008448d732cSIan Rogers NULL); 10093b0e371cSJiri Olsa } 10103b0e371cSJiri Olsa return -EINVAL; 10113b0e371cSJiri Olsa } 10123b0e371cSJiri Olsa 101317cb5f84SWang Nan /* 101417cb5f84SWang Nan * Update according to parse-events.l 101517cb5f84SWang Nan */ 101617cb5f84SWang Nan static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = { 101717cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_USER] = "<sysfs term>", 101817cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG] = "config", 101917cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG1] = "config1", 102017cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG2] = "config2", 102117cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_NAME] = "name", 102217cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD] = "period", 102317cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ] = "freq", 102417cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE] = "branch_type", 102517cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_TIME] = "time", 102617cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CALLGRAPH] = "call-graph", 102717cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_STACKSIZE] = "stack-size", 102817cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", 102917cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", 1030792d48b4SArnaldo Carvalho de Melo [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", 10312fda5adaSArnaldo Carvalho de Melo [PARSE_EVENTS__TERM_TYPE_MAX_EVENTS] = "nr", 1032626a6b78SWang Nan [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", 1033626a6b78SWang Nan [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", 1034dd60fba7SMathieu Poirier [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", 1035064b4e82SJin Yao [PARSE_EVENTS__TERM_TYPE_PERCORE] = "percore", 10361b992154SAdrian Hunter [PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT] = "aux-output", 1037eb7a52d4SAdrian Hunter [PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE] = "aux-sample-size", 103817cb5f84SWang Nan }; 103917cb5f84SWang Nan 10401669e509SWang Nan static bool config_term_shrinked; 10411669e509SWang Nan 10421669e509SWang Nan static bool 10431669e509SWang Nan config_term_avail(int term_type, struct parse_events_error *err) 10441669e509SWang Nan { 1045448d732cSIan Rogers char *err_str; 1046448d732cSIan Rogers 10471669e509SWang Nan if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) { 1048448d732cSIan Rogers parse_events__handle_error(err, -1, 1049448d732cSIan Rogers strdup("Invalid term_type"), NULL); 10501669e509SWang Nan return false; 10511669e509SWang Nan } 10521669e509SWang Nan if (!config_term_shrinked) 10531669e509SWang Nan return true; 10541669e509SWang Nan 10551669e509SWang Nan switch (term_type) { 10561669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG: 10571669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG1: 10581669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG2: 10591669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_NAME: 106006835545SSukadev Bhattiprolu case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 1061064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 10621669e509SWang Nan return true; 10631669e509SWang Nan default: 10641669e509SWang Nan if (!err) 10651669e509SWang Nan return false; 10661669e509SWang Nan 10671669e509SWang Nan /* term_type is validated so indexing is safe */ 1068448d732cSIan Rogers if (asprintf(&err_str, "'%s' is not usable in 'perf stat'", 1069448d732cSIan Rogers config_term_names[term_type]) >= 0) 1070448d732cSIan Rogers parse_events__handle_error(err, -1, err_str, NULL); 10711669e509SWang Nan return false; 10721669e509SWang Nan } 10731669e509SWang Nan } 10741669e509SWang Nan 10751669e509SWang Nan void parse_events__shrink_config_terms(void) 10761669e509SWang Nan { 10771669e509SWang Nan config_term_shrinked = true; 10781669e509SWang Nan } 10791669e509SWang Nan 10800b8891a8SHe Kuang static int config_term_common(struct perf_event_attr *attr, 10813b0e371cSJiri Olsa struct parse_events_term *term, 10823b0e371cSJiri Olsa struct parse_events_error *err) 10838f707d84SJiri Olsa { 108416fa7e82SJiri Olsa #define CHECK_TYPE_VAL(type) \ 108516fa7e82SJiri Olsa do { \ 10863b0e371cSJiri Olsa if (check_type_val(term, err, PARSE_EVENTS__TERM_TYPE_ ## type)) \ 108716fa7e82SJiri Olsa return -EINVAL; \ 108816fa7e82SJiri Olsa } while (0) 108916fa7e82SJiri Olsa 109016fa7e82SJiri Olsa switch (term->type_term) { 10918f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG: 109216fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 10938f707d84SJiri Olsa attr->config = term->val.num; 10948f707d84SJiri Olsa break; 10958f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG1: 109616fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 10978f707d84SJiri Olsa attr->config1 = term->val.num; 10988f707d84SJiri Olsa break; 10998f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG2: 110016fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 11018f707d84SJiri Olsa attr->config2 = term->val.num; 11028f707d84SJiri Olsa break; 11038f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 110416fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 11058f707d84SJiri Olsa break; 110609af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 110709af2a55SNamhyung Kim CHECK_TYPE_VAL(NUM); 110809af2a55SNamhyung Kim break; 11098f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 1110ac12f676SAndi Kleen CHECK_TYPE_VAL(STR); 1111ac12f676SAndi Kleen if (strcmp(term->val.str, "no") && 1112448d732cSIan Rogers parse_branch_str(term->val.str, 1113448d732cSIan Rogers &attr->branch_sample_type)) { 1114448d732cSIan Rogers parse_events__handle_error(err, term->err_val, 1115448d732cSIan Rogers strdup("invalid branch sample type"), 1116448d732cSIan Rogers NULL); 1117ac12f676SAndi Kleen return -EINVAL; 1118ac12f676SAndi Kleen } 11198f707d84SJiri Olsa break; 112032067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 112132067712SKan Liang CHECK_TYPE_VAL(NUM); 112232067712SKan Liang if (term->val.num > 1) { 1123448d732cSIan Rogers parse_events__handle_error(err, term->err_val, 1124448d732cSIan Rogers strdup("expected 0 or 1"), 1125448d732cSIan Rogers NULL); 112632067712SKan Liang return -EINVAL; 112732067712SKan Liang } 112832067712SKan Liang break; 1129d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 1130d457c963SKan Liang CHECK_TYPE_VAL(STR); 1131d457c963SKan Liang break; 1132d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1133d457c963SKan Liang CHECK_TYPE_VAL(NUM); 1134d457c963SKan Liang break; 1135374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1136374ce938SWang Nan CHECK_TYPE_VAL(NUM); 1137374ce938SWang Nan break; 1138374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1139374ce938SWang Nan CHECK_TYPE_VAL(NUM); 1140374ce938SWang Nan break; 1141626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1142626a6b78SWang Nan CHECK_TYPE_VAL(NUM); 1143626a6b78SWang Nan break; 1144626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1145626a6b78SWang Nan CHECK_TYPE_VAL(NUM); 1146626a6b78SWang Nan break; 11476b5fc39bSJiri Olsa case PARSE_EVENTS__TERM_TYPE_NAME: 11486b5fc39bSJiri Olsa CHECK_TYPE_VAL(STR); 11496b5fc39bSJiri Olsa break; 1150792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1151792d48b4SArnaldo Carvalho de Melo CHECK_TYPE_VAL(NUM); 1152792d48b4SArnaldo Carvalho de Melo break; 11532fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 11542fda5adaSArnaldo Carvalho de Melo CHECK_TYPE_VAL(NUM); 11552fda5adaSArnaldo Carvalho de Melo break; 1156064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 1157064b4e82SJin Yao CHECK_TYPE_VAL(NUM); 1158064b4e82SJin Yao if ((unsigned int)term->val.num > 1) { 1159448d732cSIan Rogers parse_events__handle_error(err, term->err_val, 1160448d732cSIan Rogers strdup("expected 0 or 1"), 1161448d732cSIan Rogers NULL); 1162064b4e82SJin Yao return -EINVAL; 1163064b4e82SJin Yao } 1164064b4e82SJin Yao break; 11651b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 11661b992154SAdrian Hunter CHECK_TYPE_VAL(NUM); 11671b992154SAdrian Hunter break; 1168eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1169eb7a52d4SAdrian Hunter CHECK_TYPE_VAL(NUM); 1170eb7a52d4SAdrian Hunter if (term->val.num > UINT_MAX) { 1171eb7a52d4SAdrian Hunter parse_events__handle_error(err, term->err_val, 1172eb7a52d4SAdrian Hunter strdup("too big"), 1173eb7a52d4SAdrian Hunter NULL); 1174eb7a52d4SAdrian Hunter return -EINVAL; 1175eb7a52d4SAdrian Hunter } 1176eb7a52d4SAdrian Hunter break; 11778f707d84SJiri Olsa default: 1178448d732cSIan Rogers parse_events__handle_error(err, term->err_term, 1179448d732cSIan Rogers strdup("unknown term"), 1180448d732cSIan Rogers parse_events_formats_error_string(NULL)); 11818f707d84SJiri Olsa return -EINVAL; 11828f707d84SJiri Olsa } 118316fa7e82SJiri Olsa 11841669e509SWang Nan /* 1185*4d39c89fSIngo Molnar * Check term availability after basic checking so 11861669e509SWang Nan * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered. 11871669e509SWang Nan * 1188*4d39c89fSIngo Molnar * If check availability at the entry of this function, 11891669e509SWang Nan * user will see "'<sysfs term>' is not usable in 'perf stat'" 11901669e509SWang Nan * if an invalid config term is provided for legacy events 11911669e509SWang Nan * (for example, instructions/badterm/...), which is confusing. 11921669e509SWang Nan */ 11931669e509SWang Nan if (!config_term_avail(term->type_term, err)) 11941669e509SWang Nan return -EINVAL; 11958f707d84SJiri Olsa return 0; 119616fa7e82SJiri Olsa #undef CHECK_TYPE_VAL 11978f707d84SJiri Olsa } 11988f707d84SJiri Olsa 11990b8891a8SHe Kuang static int config_term_pmu(struct perf_event_attr *attr, 12000b8891a8SHe Kuang struct parse_events_term *term, 12010b8891a8SHe Kuang struct parse_events_error *err) 12020b8891a8SHe Kuang { 1203dd60fba7SMathieu Poirier if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER || 1204dd60fba7SMathieu Poirier term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG) 12050b8891a8SHe Kuang /* 12060b8891a8SHe Kuang * Always succeed for sysfs terms, as we dont know 12070b8891a8SHe Kuang * at this point what type they need to have. 12080b8891a8SHe Kuang */ 12090b8891a8SHe Kuang return 0; 12100b8891a8SHe Kuang else 12110b8891a8SHe Kuang return config_term_common(attr, term, err); 12120b8891a8SHe Kuang } 12130b8891a8SHe Kuang 1214e637d177SHe Kuang static int config_term_tracepoint(struct perf_event_attr *attr, 1215e637d177SHe Kuang struct parse_events_term *term, 1216e637d177SHe Kuang struct parse_events_error *err) 1217e637d177SHe Kuang { 1218e637d177SHe Kuang switch (term->type_term) { 1219e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 1220e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1221374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1222374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1223792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 12242fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1225626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1226626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 12271b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 1228eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1229e637d177SHe Kuang return config_term_common(attr, term, err); 1230e637d177SHe Kuang default: 1231e637d177SHe Kuang if (err) { 1232448d732cSIan Rogers parse_events__handle_error(err, term->err_term, 1233448d732cSIan Rogers strdup("unknown term"), 1234448d732cSIan Rogers strdup("valid terms: call-graph,stack-size\n")); 1235e637d177SHe Kuang } 1236e637d177SHe Kuang return -EINVAL; 1237e637d177SHe Kuang } 1238e637d177SHe Kuang 1239e637d177SHe Kuang return 0; 1240e637d177SHe Kuang } 1241e637d177SHe Kuang 12428f707d84SJiri Olsa static int config_attr(struct perf_event_attr *attr, 12433b0e371cSJiri Olsa struct list_head *head, 12440b8891a8SHe Kuang struct parse_events_error *err, 12450b8891a8SHe Kuang config_term_func_t config_term) 12468f707d84SJiri Olsa { 12476cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 12488f707d84SJiri Olsa 12498f707d84SJiri Olsa list_for_each_entry(term, head, list) 12503b0e371cSJiri Olsa if (config_term(attr, term, err)) 12518f707d84SJiri Olsa return -EINVAL; 12528f707d84SJiri Olsa 12538f707d84SJiri Olsa return 0; 12548f707d84SJiri Olsa } 12558f707d84SJiri Olsa 1256930a2e29SJiri Olsa static int get_config_terms(struct list_head *head_config, 1257930a2e29SJiri Olsa struct list_head *head_terms __maybe_unused) 1258930a2e29SJiri Olsa { 125905e54e23SIan Rogers #define ADD_CONFIG_TERM(__type, __weak) \ 126035ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *__t; \ 1261930a2e29SJiri Olsa \ 1262930a2e29SJiri Olsa __t = zalloc(sizeof(*__t)); \ 1263930a2e29SJiri Olsa if (!__t) \ 1264930a2e29SJiri Olsa return -ENOMEM; \ 1265930a2e29SJiri Olsa \ 1266930a2e29SJiri Olsa INIT_LIST_HEAD(&__t->list); \ 126735ac0cadSArnaldo Carvalho de Melo __t->type = EVSEL__CONFIG_TERM_ ## __type; \ 126805e54e23SIan Rogers __t->weak = __weak; \ 1269e884602bSLeo Yan list_add_tail(&__t->list, head_terms) 1270e884602bSLeo Yan 127105e54e23SIan Rogers #define ADD_CONFIG_TERM_VAL(__type, __name, __val, __weak) \ 1272e884602bSLeo Yan do { \ 127305e54e23SIan Rogers ADD_CONFIG_TERM(__type, __weak); \ 1274e884602bSLeo Yan __t->val.__name = __val; \ 1275e884602bSLeo Yan } while (0) 1276e884602bSLeo Yan 127705e54e23SIan Rogers #define ADD_CONFIG_TERM_STR(__type, __val, __weak) \ 1278e884602bSLeo Yan do { \ 127905e54e23SIan Rogers ADD_CONFIG_TERM(__type, __weak); \ 12803220fb8dSLeo Yan __t->val.str = strdup(__val); \ 12813220fb8dSLeo Yan if (!__t->val.str) { \ 12823220fb8dSLeo Yan zfree(&__t); \ 12833220fb8dSLeo Yan return -ENOMEM; \ 12843220fb8dSLeo Yan } \ 12853220fb8dSLeo Yan __t->free_str = true; \ 1286930a2e29SJiri Olsa } while (0) 1287930a2e29SJiri Olsa 1288930a2e29SJiri Olsa struct parse_events_term *term; 1289930a2e29SJiri Olsa 1290930a2e29SJiri Olsa list_for_each_entry(term, head_config, list) { 1291930a2e29SJiri Olsa switch (term->type_term) { 1292ee4c7588SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 129305e54e23SIan Rogers ADD_CONFIG_TERM_VAL(PERIOD, period, term->val.num, term->weak); 129432067712SKan Liang break; 129509af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 129605e54e23SIan Rogers ADD_CONFIG_TERM_VAL(FREQ, freq, term->val.num, term->weak); 129709af2a55SNamhyung Kim break; 129832067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 129905e54e23SIan Rogers ADD_CONFIG_TERM_VAL(TIME, time, term->val.num, term->weak); 130032067712SKan Liang break; 1301d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 130205e54e23SIan Rogers ADD_CONFIG_TERM_STR(CALLGRAPH, term->val.str, term->weak); 1303d457c963SKan Liang break; 1304ac12f676SAndi Kleen case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 130505e54e23SIan Rogers ADD_CONFIG_TERM_STR(BRANCH, term->val.str, term->weak); 1306ac12f676SAndi Kleen break; 1307d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1308e884602bSLeo Yan ADD_CONFIG_TERM_VAL(STACK_USER, stack_user, 130905e54e23SIan Rogers term->val.num, term->weak); 1310d457c963SKan Liang break; 1311374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1312e884602bSLeo Yan ADD_CONFIG_TERM_VAL(INHERIT, inherit, 131305e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 1314374ce938SWang Nan break; 1315374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1316e884602bSLeo Yan ADD_CONFIG_TERM_VAL(INHERIT, inherit, 131705e54e23SIan Rogers term->val.num ? 0 : 1, term->weak); 1318374ce938SWang Nan break; 1319792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1320e884602bSLeo Yan ADD_CONFIG_TERM_VAL(MAX_STACK, max_stack, 132105e54e23SIan Rogers term->val.num, term->weak); 1322792d48b4SArnaldo Carvalho de Melo break; 13232fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1324e884602bSLeo Yan ADD_CONFIG_TERM_VAL(MAX_EVENTS, max_events, 132505e54e23SIan Rogers term->val.num, term->weak); 13262fda5adaSArnaldo Carvalho de Melo break; 1327626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1328e884602bSLeo Yan ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 132905e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 1330626a6b78SWang Nan break; 1331626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1332e884602bSLeo Yan ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 133305e54e23SIan Rogers term->val.num ? 0 : 1, term->weak); 1334626a6b78SWang Nan break; 1335dd60fba7SMathieu Poirier case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 133605e54e23SIan Rogers ADD_CONFIG_TERM_STR(DRV_CFG, term->val.str, term->weak); 1337dd60fba7SMathieu Poirier break; 1338064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 1339e884602bSLeo Yan ADD_CONFIG_TERM_VAL(PERCORE, percore, 134005e54e23SIan Rogers term->val.num ? true : false, term->weak); 1341064b4e82SJin Yao break; 13421b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 1343e884602bSLeo Yan ADD_CONFIG_TERM_VAL(AUX_OUTPUT, aux_output, 134405e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 13451b992154SAdrian Hunter break; 1346eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1347e884602bSLeo Yan ADD_CONFIG_TERM_VAL(AUX_SAMPLE_SIZE, aux_sample_size, 134805e54e23SIan Rogers term->val.num, term->weak); 1349eb7a52d4SAdrian Hunter break; 1350930a2e29SJiri Olsa default: 1351930a2e29SJiri Olsa break; 1352930a2e29SJiri Olsa } 1353930a2e29SJiri Olsa } 1354a1ac7de6SAdrian Hunter return 0; 1355a1ac7de6SAdrian Hunter } 1356a1ac7de6SAdrian Hunter 1357a1ac7de6SAdrian Hunter /* 135835ac0cadSArnaldo Carvalho de Melo * Add EVSEL__CONFIG_TERM_CFG_CHG where cfg_chg will have a bit set for 1359a1ac7de6SAdrian Hunter * each bit of attr->config that the user has changed. 1360a1ac7de6SAdrian Hunter */ 1361a1ac7de6SAdrian Hunter static int get_config_chgs(struct perf_pmu *pmu, struct list_head *head_config, 1362a1ac7de6SAdrian Hunter struct list_head *head_terms) 1363a1ac7de6SAdrian Hunter { 1364a1ac7de6SAdrian Hunter struct parse_events_term *term; 1365a1ac7de6SAdrian Hunter u64 bits = 0; 1366a1ac7de6SAdrian Hunter int type; 1367a1ac7de6SAdrian Hunter 1368a1ac7de6SAdrian Hunter list_for_each_entry(term, head_config, list) { 1369a1ac7de6SAdrian Hunter switch (term->type_term) { 1370a1ac7de6SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_USER: 1371a1ac7de6SAdrian Hunter type = perf_pmu__format_type(&pmu->format, term->config); 1372a1ac7de6SAdrian Hunter if (type != PERF_PMU_FORMAT_VALUE_CONFIG) 1373a1ac7de6SAdrian Hunter continue; 1374a1ac7de6SAdrian Hunter bits |= perf_pmu__format_bits(&pmu->format, term->config); 1375a1ac7de6SAdrian Hunter break; 1376a1ac7de6SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_CONFIG: 1377a1ac7de6SAdrian Hunter bits = ~(u64)0; 1378a1ac7de6SAdrian Hunter break; 1379a1ac7de6SAdrian Hunter default: 1380a1ac7de6SAdrian Hunter break; 1381a1ac7de6SAdrian Hunter } 1382a1ac7de6SAdrian Hunter } 1383a1ac7de6SAdrian Hunter 1384a1ac7de6SAdrian Hunter if (bits) 138505e54e23SIan Rogers ADD_CONFIG_TERM_VAL(CFG_CHG, cfg_chg, bits, false); 1386a1ac7de6SAdrian Hunter 1387a1ac7de6SAdrian Hunter #undef ADD_CONFIG_TERM 1388930a2e29SJiri Olsa return 0; 1389930a2e29SJiri Olsa } 1390930a2e29SJiri Olsa 1391e637d177SHe Kuang int parse_events_add_tracepoint(struct list_head *list, int *idx, 13928c619d6aSWang Nan const char *sys, const char *event, 1393272ed29aSJiri Olsa struct parse_events_error *err, 1394e637d177SHe Kuang struct list_head *head_config) 1395e637d177SHe Kuang { 1396e637d177SHe Kuang if (head_config) { 1397e637d177SHe Kuang struct perf_event_attr attr; 1398e637d177SHe Kuang 1399272ed29aSJiri Olsa if (config_attr(&attr, head_config, err, 1400e637d177SHe Kuang config_term_tracepoint)) 1401e637d177SHe Kuang return -EINVAL; 1402e637d177SHe Kuang } 1403e637d177SHe Kuang 1404e637d177SHe Kuang if (strpbrk(sys, "*?")) 1405e637d177SHe Kuang return add_tracepoint_multi_sys(list, idx, sys, event, 1406272ed29aSJiri Olsa err, head_config); 1407e637d177SHe Kuang else 1408e637d177SHe Kuang return add_tracepoint_event(list, idx, sys, event, 1409272ed29aSJiri Olsa err, head_config); 1410e637d177SHe Kuang } 1411e637d177SHe Kuang 14125d9cdc11SArnaldo Carvalho de Melo int parse_events_add_numeric(struct parse_events_state *parse_state, 141387d650beSJiri Olsa struct list_head *list, 1414b527bab5SRobert Richter u32 type, u64 config, 14158f707d84SJiri Olsa struct list_head *head_config) 141674d5b588SJaswinder Singh Rajput { 141789812fc8SJiri Olsa struct perf_event_attr attr; 1418930a2e29SJiri Olsa LIST_HEAD(config_terms); 141974d5b588SJaswinder Singh Rajput 142089812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 142189812fc8SJiri Olsa attr.type = type; 142289812fc8SJiri Olsa attr.config = config; 14238f707d84SJiri Olsa 1424930a2e29SJiri Olsa if (head_config) { 14255d9cdc11SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, parse_state->error, 14260b8891a8SHe Kuang config_term_common)) 14278f707d84SJiri Olsa return -EINVAL; 14288f707d84SJiri Olsa 1429930a2e29SJiri Olsa if (get_config_terms(head_config, &config_terms)) 1430930a2e29SJiri Olsa return -ENOMEM; 1431930a2e29SJiri Olsa } 1432930a2e29SJiri Olsa 14335d9cdc11SArnaldo Carvalho de Melo return add_event(list, &parse_state->idx, &attr, 143410bf358aSWang Nan get_config_name(head_config), &config_terms); 1435b908debdSIngo Molnar } 1436b908debdSIngo Molnar 1437f0fbb114SAndi Kleen int parse_events_add_tool(struct parse_events_state *parse_state, 1438f0fbb114SAndi Kleen struct list_head *list, 1439f0fbb114SAndi Kleen enum perf_tool_event tool_event) 1440f0fbb114SAndi Kleen { 1441f0fbb114SAndi Kleen return add_event_tool(list, &parse_state->idx, tool_event); 1442f0fbb114SAndi Kleen } 1443f0fbb114SAndi Kleen 1444064b4e82SJin Yao static bool config_term_percore(struct list_head *config_terms) 1445064b4e82SJin Yao { 144635ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *term; 1447064b4e82SJin Yao 1448064b4e82SJin Yao list_for_each_entry(term, config_terms, list) { 144935ac0cadSArnaldo Carvalho de Melo if (term->type == EVSEL__CONFIG_TERM_PERCORE) 1450064b4e82SJin Yao return term->val.percore; 1451064b4e82SJin Yao } 1452064b4e82SJin Yao 1453064b4e82SJin Yao return false; 1454064b4e82SJin Yao } 1455064b4e82SJin Yao 1456c199c11dSAgustin Vega-Frias int parse_events_add_pmu(struct parse_events_state *parse_state, 145736adec85SJiri Olsa struct list_head *list, char *name, 14583cdc5c2cSKan Liang struct list_head *head_config, 14593cdc5c2cSKan Liang bool auto_merge_stats, 14603cdc5c2cSKan Liang bool use_alias) 14615f537a26SJiri Olsa { 14625f537a26SJiri Olsa struct perf_event_attr attr; 146346441bdcSMatt Fleming struct perf_pmu_info info; 14645f537a26SJiri Olsa struct perf_pmu *pmu; 146532dcd021SJiri Olsa struct evsel *evsel; 1466333b5665SAndi Kleen struct parse_events_error *err = parse_state->error; 14673cdc5c2cSKan Liang bool use_uncore_alias; 1468930a2e29SJiri Olsa LIST_HEAD(config_terms); 14695f537a26SJiri Olsa 14704ac22b48SIan Rogers if (verbose > 1) { 14714ac22b48SIan Rogers fprintf(stderr, "Attempting to add event pmu '%s' with '", 14724ac22b48SIan Rogers name); 14734ac22b48SIan Rogers if (head_config) { 14744ac22b48SIan Rogers struct parse_events_term *term; 14754ac22b48SIan Rogers 14764ac22b48SIan Rogers list_for_each_entry(term, head_config, list) { 14774ac22b48SIan Rogers fprintf(stderr, "%s,", term->config); 14784ac22b48SIan Rogers } 14794ac22b48SIan Rogers } 14804ac22b48SIan Rogers fprintf(stderr, "' that may result in non-fatal errors\n"); 14814ac22b48SIan Rogers } 14824ac22b48SIan Rogers 1483387ad33fSJiri Olsa pmu = parse_state->fake_pmu ?: perf_pmu__find(name); 1484333b5665SAndi Kleen if (!pmu) { 1485448d732cSIan Rogers char *err_str; 1486448d732cSIan Rogers 1487448d732cSIan Rogers if (asprintf(&err_str, 1488333b5665SAndi Kleen "Cannot find PMU `%s'. Missing kernel support?", 1489448d732cSIan Rogers name) >= 0) 1490a910e466SIan Rogers parse_events__handle_error(err, 0, err_str, NULL); 14915f537a26SJiri Olsa return -EINVAL; 1492333b5665SAndi Kleen } 14935f537a26SJiri Olsa 1494dc0a6202SAdrian Hunter if (pmu->default_config) { 1495dc0a6202SAdrian Hunter memcpy(&attr, pmu->default_config, 1496dc0a6202SAdrian Hunter sizeof(struct perf_event_attr)); 1497dc0a6202SAdrian Hunter } else { 14985f537a26SJiri Olsa memset(&attr, 0, sizeof(attr)); 1499dc0a6202SAdrian Hunter } 15005f537a26SJiri Olsa 15013cdc5c2cSKan Liang use_uncore_alias = (pmu->is_uncore && use_alias); 15023cdc5c2cSKan Liang 1503ad962273SAdrian Hunter if (!head_config) { 1504ad962273SAdrian Hunter attr.type = pmu->type; 150570943490SStephane Eranian evsel = __add_event(list, &parse_state->idx, &attr, true, NULL, 150670943490SStephane Eranian pmu, NULL, auto_merge_stats, NULL); 15078c5421c0SAgustin Vega-Frias if (evsel) { 1508d4953f7eSIan Rogers evsel->pmu_name = name ? strdup(name) : NULL; 15093cdc5c2cSKan Liang evsel->use_uncore_alias = use_uncore_alias; 15108c5421c0SAgustin Vega-Frias return 0; 15118c5421c0SAgustin Vega-Frias } else { 15128c5421c0SAgustin Vega-Frias return -ENOMEM; 15138c5421c0SAgustin Vega-Frias } 1514ad962273SAdrian Hunter } 1515ad962273SAdrian Hunter 1516387ad33fSJiri Olsa if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, head_config, &info)) 1517a6146d50SZheng Yan return -EINVAL; 1518a6146d50SZheng Yan 15194ac22b48SIan Rogers if (verbose > 1) { 15204ac22b48SIan Rogers fprintf(stderr, "After aliases, add event pmu '%s' with '", 15214ac22b48SIan Rogers name); 15224ac22b48SIan Rogers if (head_config) { 15234ac22b48SIan Rogers struct parse_events_term *term; 15244ac22b48SIan Rogers 15254ac22b48SIan Rogers list_for_each_entry(term, head_config, list) { 15264ac22b48SIan Rogers fprintf(stderr, "%s,", term->config); 15274ac22b48SIan Rogers } 15284ac22b48SIan Rogers } 15294ac22b48SIan Rogers fprintf(stderr, "' that may result in non-fatal errors\n"); 15304ac22b48SIan Rogers } 15314ac22b48SIan Rogers 15325f537a26SJiri Olsa /* 15335f537a26SJiri Olsa * Configure hardcoded terms first, no need to check 15345f537a26SJiri Olsa * return value when called with fail == 0 ;) 15355f537a26SJiri Olsa */ 15365d9cdc11SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, parse_state->error, config_term_pmu)) 1537c056ba6aSJiri Olsa return -EINVAL; 15385f537a26SJiri Olsa 1539930a2e29SJiri Olsa if (get_config_terms(head_config, &config_terms)) 1540930a2e29SJiri Olsa return -ENOMEM; 1541930a2e29SJiri Olsa 1542a1ac7de6SAdrian Hunter /* 1543a1ac7de6SAdrian Hunter * When using default config, record which bits of attr->config were 1544a1ac7de6SAdrian Hunter * changed by the user. 1545a1ac7de6SAdrian Hunter */ 1546a1ac7de6SAdrian Hunter if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms)) 1547a1ac7de6SAdrian Hunter return -ENOMEM; 1548a1ac7de6SAdrian Hunter 1549387ad33fSJiri Olsa if (!parse_state->fake_pmu && perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { 155035ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *pos, *tmp; 155138f2c422SIan Rogers 155238f2c422SIan Rogers list_for_each_entry_safe(pos, tmp, &config_terms, list) { 155338f2c422SIan Rogers list_del_init(&pos->list); 15547fcdccd4SArnaldo Carvalho de Melo if (pos->free_str) 1555e8dfb818SIan Rogers zfree(&pos->val.str); 155638f2c422SIan Rogers free(pos); 155738f2c422SIan Rogers } 15585f537a26SJiri Olsa return -EINVAL; 155938f2c422SIan Rogers } 15605f537a26SJiri Olsa 156170943490SStephane Eranian evsel = __add_event(list, &parse_state->idx, &attr, true, 156266ec1191SMark Rutland get_config_name(head_config), pmu, 1563f0fbb114SAndi Kleen &config_terms, auto_merge_stats, NULL); 156433321a06SIan Rogers if (!evsel) 156533321a06SIan Rogers return -ENOMEM; 156633321a06SIan Rogers 156733321a06SIan Rogers evsel->pmu_name = name ? strdup(name) : NULL; 156833321a06SIan Rogers evsel->use_uncore_alias = use_uncore_alias; 156933321a06SIan Rogers evsel->percore = config_term_percore(&evsel->config_terms); 157033321a06SIan Rogers 157133321a06SIan Rogers if (parse_state->fake_pmu) 157233321a06SIan Rogers return 0; 157333321a06SIan Rogers 157446441bdcSMatt Fleming evsel->unit = info.unit; 157546441bdcSMatt Fleming evsel->scale = info.scale; 1576044330c1SMatt Fleming evsel->per_pkg = info.per_pkg; 15771d9e446bSJiri Olsa evsel->snapshot = info.snapshot; 157837932c18SAndi Kleen evsel->metric_expr = info.metric_expr; 157996284814SAndi Kleen evsel->metric_name = info.metric_name; 158033321a06SIan Rogers return 0; 15815f537a26SJiri Olsa } 15825f537a26SJiri Olsa 15835d9cdc11SArnaldo Carvalho de Melo int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 15842073ad33SAndi Kleen char *str, struct list_head **listp) 15852073ad33SAndi Kleen { 15862073ad33SAndi Kleen struct parse_events_term *term; 15872073ad33SAndi Kleen struct list_head *list; 15882073ad33SAndi Kleen struct perf_pmu *pmu = NULL; 15892073ad33SAndi Kleen int ok = 0; 15902073ad33SAndi Kleen 15912073ad33SAndi Kleen *listp = NULL; 15922073ad33SAndi Kleen /* Add it for all PMUs that support the alias */ 15932073ad33SAndi Kleen list = malloc(sizeof(struct list_head)); 15942073ad33SAndi Kleen if (!list) 15952073ad33SAndi Kleen return -1; 15962073ad33SAndi Kleen INIT_LIST_HEAD(list); 15972073ad33SAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 15982073ad33SAndi Kleen struct perf_pmu_alias *alias; 15992073ad33SAndi Kleen 16002073ad33SAndi Kleen list_for_each_entry(alias, &pmu->aliases, list) { 16012073ad33SAndi Kleen if (!strcasecmp(alias->name, str)) { 1602b6645a72SIan Rogers struct list_head *head; 1603b6645a72SIan Rogers char *config; 1604b6645a72SIan Rogers 16052073ad33SAndi Kleen head = malloc(sizeof(struct list_head)); 16062073ad33SAndi Kleen if (!head) 16072073ad33SAndi Kleen return -1; 16082073ad33SAndi Kleen INIT_LIST_HEAD(head); 1609b6645a72SIan Rogers config = strdup(str); 1610b6645a72SIan Rogers if (!config) 16112073ad33SAndi Kleen return -1; 1612b6645a72SIan Rogers if (parse_events_term__num(&term, 1613b6645a72SIan Rogers PARSE_EVENTS__TERM_TYPE_USER, 1614b6645a72SIan Rogers config, 1, false, &config, 1615b6645a72SIan Rogers NULL) < 0) { 1616b6645a72SIan Rogers free(list); 1617b6645a72SIan Rogers free(config); 1618b6645a72SIan Rogers return -1; 1619b6645a72SIan Rogers } 16202073ad33SAndi Kleen list_add_tail(&term->list, head); 16212073ad33SAndi Kleen 1622c199c11dSAgustin Vega-Frias if (!parse_events_add_pmu(parse_state, list, 16233cdc5c2cSKan Liang pmu->name, head, 16243cdc5c2cSKan Liang true, true)) { 1625d4953f7eSIan Rogers pr_debug("%s -> %s/%s/\n", str, 16262073ad33SAndi Kleen pmu->name, alias->str); 16272073ad33SAndi Kleen ok++; 16282073ad33SAndi Kleen } 16292073ad33SAndi Kleen 16302073ad33SAndi Kleen parse_events_terms__delete(head); 16312073ad33SAndi Kleen } 16322073ad33SAndi Kleen } 16332073ad33SAndi Kleen } 1634b6645a72SIan Rogers if (!ok) { 1635b6645a72SIan Rogers free(list); 16362073ad33SAndi Kleen return -1; 1637b6645a72SIan Rogers } 16382073ad33SAndi Kleen *listp = list; 16392073ad33SAndi Kleen return 0; 16402073ad33SAndi Kleen } 16412073ad33SAndi Kleen 16426a4bb04cSJiri Olsa int parse_events__modifier_group(struct list_head *list, 16436a4bb04cSJiri Olsa char *event_mod) 164489efb029SJiri Olsa { 16456a4bb04cSJiri Olsa return parse_events__modifier_event(list, event_mod, true); 16466a4bb04cSJiri Olsa } 16476a4bb04cSJiri Olsa 16483cdc5c2cSKan Liang /* 16493cdc5c2cSKan Liang * Check if the two uncore PMUs are from the same uncore block 16503cdc5c2cSKan Liang * The format of the uncore PMU name is uncore_#blockname_#pmuidx 16513cdc5c2cSKan Liang */ 16523cdc5c2cSKan Liang static bool is_same_uncore_block(const char *pmu_name_a, const char *pmu_name_b) 16533cdc5c2cSKan Liang { 16543cdc5c2cSKan Liang char *end_a, *end_b; 16553cdc5c2cSKan Liang 16563cdc5c2cSKan Liang end_a = strrchr(pmu_name_a, '_'); 16573cdc5c2cSKan Liang end_b = strrchr(pmu_name_b, '_'); 16583cdc5c2cSKan Liang 16593cdc5c2cSKan Liang if (!end_a || !end_b) 16603cdc5c2cSKan Liang return false; 16613cdc5c2cSKan Liang 16623cdc5c2cSKan Liang if ((end_a - pmu_name_a) != (end_b - pmu_name_b)) 16633cdc5c2cSKan Liang return false; 16643cdc5c2cSKan Liang 16653cdc5c2cSKan Liang return (strncmp(pmu_name_a, pmu_name_b, end_a - pmu_name_a) == 0); 16663cdc5c2cSKan Liang } 16673cdc5c2cSKan Liang 16683cdc5c2cSKan Liang static int 16693cdc5c2cSKan Liang parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, 16703cdc5c2cSKan Liang struct parse_events_state *parse_state) 16713cdc5c2cSKan Liang { 167232dcd021SJiri Olsa struct evsel *evsel, *leader; 16733cdc5c2cSKan Liang uintptr_t *leaders; 16743cdc5c2cSKan Liang bool is_leader = true; 16753cdc5c2cSKan Liang int i, nr_pmu = 0, total_members, ret = 0; 16763cdc5c2cSKan Liang 1677b27c4eceSJiri Olsa leader = list_first_entry(list, struct evsel, core.node); 1678b27c4eceSJiri Olsa evsel = list_last_entry(list, struct evsel, core.node); 16793cdc5c2cSKan Liang total_members = evsel->idx - leader->idx + 1; 16803cdc5c2cSKan Liang 16813cdc5c2cSKan Liang leaders = calloc(total_members, sizeof(uintptr_t)); 16823cdc5c2cSKan Liang if (WARN_ON(!leaders)) 16833cdc5c2cSKan Liang return 0; 16843cdc5c2cSKan Liang 16853cdc5c2cSKan Liang /* 16863cdc5c2cSKan Liang * Going through the whole group and doing sanity check. 16873cdc5c2cSKan Liang * All members must use alias, and be from the same uncore block. 16883cdc5c2cSKan Liang * Also, storing the leader events in an array. 16893cdc5c2cSKan Liang */ 16903cdc5c2cSKan Liang __evlist__for_each_entry(list, evsel) { 16913cdc5c2cSKan Liang 16923cdc5c2cSKan Liang /* Only split the uncore group which members use alias */ 16933cdc5c2cSKan Liang if (!evsel->use_uncore_alias) 16943cdc5c2cSKan Liang goto out; 16953cdc5c2cSKan Liang 16963cdc5c2cSKan Liang /* The events must be from the same uncore block */ 16973cdc5c2cSKan Liang if (!is_same_uncore_block(leader->pmu_name, evsel->pmu_name)) 16983cdc5c2cSKan Liang goto out; 16993cdc5c2cSKan Liang 17003cdc5c2cSKan Liang if (!is_leader) 17013cdc5c2cSKan Liang continue; 17023cdc5c2cSKan Liang /* 17033cdc5c2cSKan Liang * If the event's PMU name starts to repeat, it must be a new 17043cdc5c2cSKan Liang * event. That can be used to distinguish the leader from 17053cdc5c2cSKan Liang * other members, even they have the same event name. 17063cdc5c2cSKan Liang */ 17078510895bSJin Yao if ((leader != evsel) && 17088510895bSJin Yao !strcmp(leader->pmu_name, evsel->pmu_name)) { 17093cdc5c2cSKan Liang is_leader = false; 17103cdc5c2cSKan Liang continue; 17113cdc5c2cSKan Liang } 17123cdc5c2cSKan Liang 17133cdc5c2cSKan Liang /* Store the leader event for each PMU */ 17143cdc5c2cSKan Liang leaders[nr_pmu++] = (uintptr_t) evsel; 17153cdc5c2cSKan Liang } 17163cdc5c2cSKan Liang 17173cdc5c2cSKan Liang /* only one event alias */ 17183cdc5c2cSKan Liang if (nr_pmu == total_members) { 17193cdc5c2cSKan Liang parse_state->nr_groups--; 17203cdc5c2cSKan Liang goto handled; 17213cdc5c2cSKan Liang } 17223cdc5c2cSKan Liang 17233cdc5c2cSKan Liang /* 17243cdc5c2cSKan Liang * An uncore event alias is a joint name which means the same event 17253cdc5c2cSKan Liang * runs on all PMUs of a block. 17263cdc5c2cSKan Liang * Perf doesn't support mixed events from different PMUs in the same 17273cdc5c2cSKan Liang * group. The big group has to be split into multiple small groups 17283cdc5c2cSKan Liang * which only include the events from the same PMU. 17293cdc5c2cSKan Liang * 17303cdc5c2cSKan Liang * Here the uncore event aliases must be from the same uncore block. 17313cdc5c2cSKan Liang * The number of PMUs must be same for each alias. The number of new 17323cdc5c2cSKan Liang * small groups equals to the number of PMUs. 17333cdc5c2cSKan Liang * Setting the leader event for corresponding members in each group. 17343cdc5c2cSKan Liang */ 17353cdc5c2cSKan Liang i = 0; 17363cdc5c2cSKan Liang __evlist__for_each_entry(list, evsel) { 17373cdc5c2cSKan Liang if (i >= nr_pmu) 17383cdc5c2cSKan Liang i = 0; 173932dcd021SJiri Olsa evsel->leader = (struct evsel *) leaders[i++]; 17403cdc5c2cSKan Liang } 17413cdc5c2cSKan Liang 17423cdc5c2cSKan Liang /* The number of members and group name are same for each group */ 17433cdc5c2cSKan Liang for (i = 0; i < nr_pmu; i++) { 174432dcd021SJiri Olsa evsel = (struct evsel *) leaders[i]; 17455643b1a5SJiri Olsa evsel->core.nr_members = total_members / nr_pmu; 17463cdc5c2cSKan Liang evsel->group_name = name ? strdup(name) : NULL; 17473cdc5c2cSKan Liang } 17483cdc5c2cSKan Liang 17493cdc5c2cSKan Liang /* Take the new small groups into account */ 17503cdc5c2cSKan Liang parse_state->nr_groups += nr_pmu - 1; 17513cdc5c2cSKan Liang 17523cdc5c2cSKan Liang handled: 17533cdc5c2cSKan Liang ret = 1; 17543cdc5c2cSKan Liang out: 17553cdc5c2cSKan Liang free(leaders); 17563cdc5c2cSKan Liang return ret; 17573cdc5c2cSKan Liang } 17583cdc5c2cSKan Liang 17593cdc5c2cSKan Liang void parse_events__set_leader(char *name, struct list_head *list, 17603cdc5c2cSKan Liang struct parse_events_state *parse_state) 17616a4bb04cSJiri Olsa { 176232dcd021SJiri Olsa struct evsel *leader; 17636a4bb04cSJiri Olsa 1764854f7363SWang Nan if (list_empty(list)) { 1765854f7363SWang Nan WARN_ONCE(true, "WARNING: failed to set leader: empty list"); 1766854f7363SWang Nan return; 1767854f7363SWang Nan } 1768854f7363SWang Nan 17693cdc5c2cSKan Liang if (parse_events__set_leader_for_uncore_aliase(name, list, parse_state)) 17703cdc5c2cSKan Liang return; 17713cdc5c2cSKan Liang 1772a622eafaSArnaldo Carvalho de Melo __evlist__set_leader(list); 1773b27c4eceSJiri Olsa leader = list_entry(list->next, struct evsel, core.node); 17746a4bb04cSJiri Olsa leader->group_name = name ? strdup(name) : NULL; 177589efb029SJiri Olsa } 177689efb029SJiri Olsa 1777c5cd8ac0SDavid Ahern /* list_event is assumed to point to malloc'ed memory */ 17785d7be90eSJiri Olsa void parse_events_update_lists(struct list_head *list_event, 17795d7be90eSJiri Olsa struct list_head *list_all) 17805d7be90eSJiri Olsa { 17815d7be90eSJiri Olsa /* 17825d7be90eSJiri Olsa * Called for single event definition. Update the 178389efb029SJiri Olsa * 'all event' list, and reinit the 'single event' 17845d7be90eSJiri Olsa * list, for next event definition. 17855d7be90eSJiri Olsa */ 17865d7be90eSJiri Olsa list_splice_tail(list_event, list_all); 1787b847cbdcSJiri Olsa free(list_event); 17885d7be90eSJiri Olsa } 17895d7be90eSJiri Olsa 1790f5b1135bSJiri Olsa struct event_modifier { 1791f5b1135bSJiri Olsa int eu; 1792f5b1135bSJiri Olsa int ek; 1793f5b1135bSJiri Olsa int eh; 1794f5b1135bSJiri Olsa int eH; 1795f5b1135bSJiri Olsa int eG; 1796a1e12da4SJiri Olsa int eI; 1797f5b1135bSJiri Olsa int precise; 17987f94af7aSJiri Olsa int precise_max; 1799f5b1135bSJiri Olsa int exclude_GH; 18003c176311SJiri Olsa int sample_read; 1801e9a7c414SMichael Ellerman int pinned; 18025a5dfe4bSAndi Kleen int weak; 18030997a266SAndi Kleen int exclusive; 1804f5b1135bSJiri Olsa }; 180561c45981SPaul Mackerras 1806f5b1135bSJiri Olsa static int get_event_modifier(struct event_modifier *mod, char *str, 180732dcd021SJiri Olsa struct evsel *evsel) 1808f5b1135bSJiri Olsa { 18091fc632ceSJiri Olsa int eu = evsel ? evsel->core.attr.exclude_user : 0; 18101fc632ceSJiri Olsa int ek = evsel ? evsel->core.attr.exclude_kernel : 0; 18111fc632ceSJiri Olsa int eh = evsel ? evsel->core.attr.exclude_hv : 0; 18121fc632ceSJiri Olsa int eH = evsel ? evsel->core.attr.exclude_host : 0; 18131fc632ceSJiri Olsa int eG = evsel ? evsel->core.attr.exclude_guest : 0; 18141fc632ceSJiri Olsa int eI = evsel ? evsel->core.attr.exclude_idle : 0; 18151fc632ceSJiri Olsa int precise = evsel ? evsel->core.attr.precise_ip : 0; 18167f94af7aSJiri Olsa int precise_max = 0; 18173c176311SJiri Olsa int sample_read = 0; 18181fc632ceSJiri Olsa int pinned = evsel ? evsel->core.attr.pinned : 0; 18190997a266SAndi Kleen int exclusive = evsel ? evsel->core.attr.exclusive : 0; 1820f5b1135bSJiri Olsa 1821f5b1135bSJiri Olsa int exclude = eu | ek | eh; 1822f5b1135bSJiri Olsa int exclude_GH = evsel ? evsel->exclude_GH : 0; 18235a5dfe4bSAndi Kleen int weak = 0; 1824f5b1135bSJiri Olsa 1825f5b1135bSJiri Olsa memset(mod, 0, sizeof(*mod)); 1826ceb53fbfSIngo Molnar 182761c45981SPaul Mackerras while (*str) { 1828ab608344SPeter Zijlstra if (*str == 'u') { 1829ab608344SPeter Zijlstra if (!exclude) 1830ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 1831943b69acSJin Yao if (!exclude_GH && !perf_guest) 1832943b69acSJin Yao eG = 1; 183361c45981SPaul Mackerras eu = 0; 1834ab608344SPeter Zijlstra } else if (*str == 'k') { 1835ab608344SPeter Zijlstra if (!exclude) 1836ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 183761c45981SPaul Mackerras ek = 0; 1838ab608344SPeter Zijlstra } else if (*str == 'h') { 1839ab608344SPeter Zijlstra if (!exclude) 1840ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 184161c45981SPaul Mackerras eh = 0; 184299320cc8SJoerg Roedel } else if (*str == 'G') { 184399320cc8SJoerg Roedel if (!exclude_GH) 184499320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 184599320cc8SJoerg Roedel eG = 0; 184699320cc8SJoerg Roedel } else if (*str == 'H') { 184799320cc8SJoerg Roedel if (!exclude_GH) 184899320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 184999320cc8SJoerg Roedel eH = 0; 1850a1e12da4SJiri Olsa } else if (*str == 'I') { 1851a1e12da4SJiri Olsa eI = 1; 1852ab608344SPeter Zijlstra } else if (*str == 'p') { 1853ab608344SPeter Zijlstra precise++; 18541342798cSDavid Ahern /* use of precise requires exclude_guest */ 18551342798cSDavid Ahern if (!exclude_GH) 18561342798cSDavid Ahern eG = 1; 18577f94af7aSJiri Olsa } else if (*str == 'P') { 18587f94af7aSJiri Olsa precise_max = 1; 18593c176311SJiri Olsa } else if (*str == 'S') { 18603c176311SJiri Olsa sample_read = 1; 1861e9a7c414SMichael Ellerman } else if (*str == 'D') { 1862e9a7c414SMichael Ellerman pinned = 1; 18630997a266SAndi Kleen } else if (*str == 'e') { 18640997a266SAndi Kleen exclusive = 1; 18655a5dfe4bSAndi Kleen } else if (*str == 'W') { 18665a5dfe4bSAndi Kleen weak = 1; 1867ab608344SPeter Zijlstra } else 186861c45981SPaul Mackerras break; 1869ab608344SPeter Zijlstra 187061c45981SPaul Mackerras ++str; 187161c45981SPaul Mackerras } 187274d5b588SJaswinder Singh Rajput 187386470930SIngo Molnar /* 187489812fc8SJiri Olsa * precise ip: 187589812fc8SJiri Olsa * 187689812fc8SJiri Olsa * 0 - SAMPLE_IP can have arbitrary skid 187789812fc8SJiri Olsa * 1 - SAMPLE_IP must have constant skid 187889812fc8SJiri Olsa * 2 - SAMPLE_IP requested to have 0 skid 187989812fc8SJiri Olsa * 3 - SAMPLE_IP must have 0 skid 188089812fc8SJiri Olsa * 188189812fc8SJiri Olsa * See also PERF_RECORD_MISC_EXACT_IP 188286470930SIngo Molnar */ 188389812fc8SJiri Olsa if (precise > 3) 188489812fc8SJiri Olsa return -EINVAL; 188586470930SIngo Molnar 1886f5b1135bSJiri Olsa mod->eu = eu; 1887f5b1135bSJiri Olsa mod->ek = ek; 1888f5b1135bSJiri Olsa mod->eh = eh; 1889f5b1135bSJiri Olsa mod->eH = eH; 1890f5b1135bSJiri Olsa mod->eG = eG; 1891a1e12da4SJiri Olsa mod->eI = eI; 1892f5b1135bSJiri Olsa mod->precise = precise; 18937f94af7aSJiri Olsa mod->precise_max = precise_max; 1894f5b1135bSJiri Olsa mod->exclude_GH = exclude_GH; 18953c176311SJiri Olsa mod->sample_read = sample_read; 1896e9a7c414SMichael Ellerman mod->pinned = pinned; 18975a5dfe4bSAndi Kleen mod->weak = weak; 18980997a266SAndi Kleen mod->exclusive = exclusive; 1899e9a7c414SMichael Ellerman 1900f5b1135bSJiri Olsa return 0; 1901f5b1135bSJiri Olsa } 1902f5b1135bSJiri Olsa 1903534123f4SJiri Olsa /* 1904534123f4SJiri Olsa * Basic modifier sanity check to validate it contains only one 1905534123f4SJiri Olsa * instance of any modifier (apart from 'p') present. 1906534123f4SJiri Olsa */ 1907534123f4SJiri Olsa static int check_modifier(char *str) 1908534123f4SJiri Olsa { 1909534123f4SJiri Olsa char *p = str; 1910534123f4SJiri Olsa 1911534123f4SJiri Olsa /* The sizeof includes 0 byte as well. */ 19120997a266SAndi Kleen if (strlen(str) > (sizeof("ukhGHpppPSDIWe") - 1)) 1913534123f4SJiri Olsa return -1; 1914534123f4SJiri Olsa 1915534123f4SJiri Olsa while (*p) { 1916534123f4SJiri Olsa if (*p != 'p' && strchr(p + 1, *p)) 1917534123f4SJiri Olsa return -1; 1918534123f4SJiri Olsa p++; 1919534123f4SJiri Olsa } 1920534123f4SJiri Olsa 1921534123f4SJiri Olsa return 0; 1922534123f4SJiri Olsa } 1923534123f4SJiri Olsa 1924f5b1135bSJiri Olsa int parse_events__modifier_event(struct list_head *list, char *str, bool add) 1925f5b1135bSJiri Olsa { 192632dcd021SJiri Olsa struct evsel *evsel; 1927f5b1135bSJiri Olsa struct event_modifier mod; 1928f5b1135bSJiri Olsa 1929f5b1135bSJiri Olsa if (str == NULL) 1930f5b1135bSJiri Olsa return 0; 1931f5b1135bSJiri Olsa 1932534123f4SJiri Olsa if (check_modifier(str)) 1933534123f4SJiri Olsa return -EINVAL; 1934534123f4SJiri Olsa 1935f5b1135bSJiri Olsa if (!add && get_event_modifier(&mod, str, NULL)) 1936f5b1135bSJiri Olsa return -EINVAL; 1937f5b1135bSJiri Olsa 1938e5cadb93SArnaldo Carvalho de Melo __evlist__for_each_entry(list, evsel) { 1939f5b1135bSJiri Olsa if (add && get_event_modifier(&mod, str, evsel)) 1940f5b1135bSJiri Olsa return -EINVAL; 1941f5b1135bSJiri Olsa 19421fc632ceSJiri Olsa evsel->core.attr.exclude_user = mod.eu; 19431fc632ceSJiri Olsa evsel->core.attr.exclude_kernel = mod.ek; 19441fc632ceSJiri Olsa evsel->core.attr.exclude_hv = mod.eh; 19451fc632ceSJiri Olsa evsel->core.attr.precise_ip = mod.precise; 19461fc632ceSJiri Olsa evsel->core.attr.exclude_host = mod.eH; 19471fc632ceSJiri Olsa evsel->core.attr.exclude_guest = mod.eG; 19481fc632ceSJiri Olsa evsel->core.attr.exclude_idle = mod.eI; 1949f5b1135bSJiri Olsa evsel->exclude_GH = mod.exclude_GH; 19503c176311SJiri Olsa evsel->sample_read = mod.sample_read; 19517f94af7aSJiri Olsa evsel->precise_max = mod.precise_max; 19525a5dfe4bSAndi Kleen evsel->weak_group = mod.weak; 1953e9a7c414SMichael Ellerman 19540997a266SAndi Kleen if (evsel__is_group_leader(evsel)) { 19551fc632ceSJiri Olsa evsel->core.attr.pinned = mod.pinned; 19560997a266SAndi Kleen evsel->core.attr.exclusive = mod.exclusive; 19570997a266SAndi Kleen } 1958ceb53fbfSIngo Molnar } 195986470930SIngo Molnar 196089812fc8SJiri Olsa return 0; 196186470930SIngo Molnar } 196286470930SIngo Molnar 1963ac2ba9f3SRobert Richter int parse_events_name(struct list_head *list, char *name) 1964ac2ba9f3SRobert Richter { 196532dcd021SJiri Olsa struct evsel *evsel; 1966ac2ba9f3SRobert Richter 1967e5cadb93SArnaldo Carvalho de Melo __evlist__for_each_entry(list, evsel) { 1968ac2ba9f3SRobert Richter if (!evsel->name) 1969ac2ba9f3SRobert Richter evsel->name = strdup(name); 1970ac2ba9f3SRobert Richter } 1971ac2ba9f3SRobert Richter 1972ac2ba9f3SRobert Richter return 0; 1973ac2ba9f3SRobert Richter } 1974ac2ba9f3SRobert Richter 1975dcb4e102SKan Liang static int 1976dcb4e102SKan Liang comp_pmu(const void *p1, const void *p2) 1977dcb4e102SKan Liang { 1978dcb4e102SKan Liang struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1; 1979dcb4e102SKan Liang struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2; 1980dcb4e102SKan Liang 1981e312bcf1SAndi Kleen return strcasecmp(pmu1->symbol, pmu2->symbol); 1982dcb4e102SKan Liang } 1983dcb4e102SKan Liang 1984dcb4e102SKan Liang static void perf_pmu__parse_cleanup(void) 1985dcb4e102SKan Liang { 1986dcb4e102SKan Liang if (perf_pmu_events_list_num > 0) { 1987dcb4e102SKan Liang struct perf_pmu_event_symbol *p; 1988dcb4e102SKan Liang int i; 1989dcb4e102SKan Liang 1990dcb4e102SKan Liang for (i = 0; i < perf_pmu_events_list_num; i++) { 1991dcb4e102SKan Liang p = perf_pmu_events_list + i; 1992360e071bSTaeung Song zfree(&p->symbol); 1993dcb4e102SKan Liang } 1994506fde11STaeung Song zfree(&perf_pmu_events_list); 1995dcb4e102SKan Liang perf_pmu_events_list_num = 0; 1996dcb4e102SKan Liang } 1997dcb4e102SKan Liang } 1998dcb4e102SKan Liang 1999dcb4e102SKan Liang #define SET_SYMBOL(str, stype) \ 2000dcb4e102SKan Liang do { \ 2001dcb4e102SKan Liang p->symbol = str; \ 2002dcb4e102SKan Liang if (!p->symbol) \ 2003dcb4e102SKan Liang goto err; \ 2004dcb4e102SKan Liang p->type = stype; \ 2005dcb4e102SKan Liang } while (0) 2006dcb4e102SKan Liang 2007dcb4e102SKan Liang /* 2008dcb4e102SKan Liang * Read the pmu events list from sysfs 2009dcb4e102SKan Liang * Save it into perf_pmu_events_list 2010dcb4e102SKan Liang */ 2011dcb4e102SKan Liang static void perf_pmu__parse_init(void) 2012dcb4e102SKan Liang { 2013dcb4e102SKan Liang 2014dcb4e102SKan Liang struct perf_pmu *pmu = NULL; 2015dcb4e102SKan Liang struct perf_pmu_alias *alias; 2016dcb4e102SKan Liang int len = 0; 2017dcb4e102SKan Liang 2018231bb2aaSAndi Kleen pmu = NULL; 2019231bb2aaSAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 2020dcb4e102SKan Liang list_for_each_entry(alias, &pmu->aliases, list) { 2021dcb4e102SKan Liang if (strchr(alias->name, '-')) 2022dcb4e102SKan Liang len++; 2023dcb4e102SKan Liang len++; 2024dcb4e102SKan Liang } 2025231bb2aaSAndi Kleen } 2026231bb2aaSAndi Kleen 2027231bb2aaSAndi Kleen if (len == 0) { 2028231bb2aaSAndi Kleen perf_pmu_events_list_num = -1; 2029231bb2aaSAndi Kleen return; 2030231bb2aaSAndi Kleen } 2031dcb4e102SKan Liang perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len); 2032dcb4e102SKan Liang if (!perf_pmu_events_list) 2033dcb4e102SKan Liang return; 2034dcb4e102SKan Liang perf_pmu_events_list_num = len; 2035dcb4e102SKan Liang 2036dcb4e102SKan Liang len = 0; 2037231bb2aaSAndi Kleen pmu = NULL; 2038231bb2aaSAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 2039dcb4e102SKan Liang list_for_each_entry(alias, &pmu->aliases, list) { 2040dcb4e102SKan Liang struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; 2041dcb4e102SKan Liang char *tmp = strchr(alias->name, '-'); 2042dcb4e102SKan Liang 2043dcb4e102SKan Liang if (tmp != NULL) { 2044dcb4e102SKan Liang SET_SYMBOL(strndup(alias->name, tmp - alias->name), 2045dcb4e102SKan Liang PMU_EVENT_SYMBOL_PREFIX); 2046dcb4e102SKan Liang p++; 2047dcb4e102SKan Liang SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX); 2048dcb4e102SKan Liang len += 2; 2049dcb4e102SKan Liang } else { 2050dcb4e102SKan Liang SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL); 2051dcb4e102SKan Liang len++; 2052dcb4e102SKan Liang } 2053dcb4e102SKan Liang } 2054231bb2aaSAndi Kleen } 2055dcb4e102SKan Liang qsort(perf_pmu_events_list, len, 2056dcb4e102SKan Liang sizeof(struct perf_pmu_event_symbol), comp_pmu); 2057dcb4e102SKan Liang 2058dcb4e102SKan Liang return; 2059dcb4e102SKan Liang err: 2060dcb4e102SKan Liang perf_pmu__parse_cleanup(); 2061dcb4e102SKan Liang } 2062dcb4e102SKan Liang 20634929e95aSJiri Olsa /* 20644929e95aSJiri Olsa * This function injects special term in 20654929e95aSJiri Olsa * perf_pmu_events_list so the test code 20664929e95aSJiri Olsa * can check on this functionality. 20674929e95aSJiri Olsa */ 20684929e95aSJiri Olsa int perf_pmu__test_parse_init(void) 20694929e95aSJiri Olsa { 20704929e95aSJiri Olsa struct perf_pmu_event_symbol *list; 20714929e95aSJiri Olsa 20724929e95aSJiri Olsa list = malloc(sizeof(*list) * 1); 20734929e95aSJiri Olsa if (!list) 20744929e95aSJiri Olsa return -ENOMEM; 20754929e95aSJiri Olsa 20764929e95aSJiri Olsa list->type = PMU_EVENT_SYMBOL; 20774929e95aSJiri Olsa list->symbol = strdup("read"); 20784929e95aSJiri Olsa 20794929e95aSJiri Olsa if (!list->symbol) { 20804929e95aSJiri Olsa free(list); 20814929e95aSJiri Olsa return -ENOMEM; 20824929e95aSJiri Olsa } 20834929e95aSJiri Olsa 20844929e95aSJiri Olsa perf_pmu_events_list = list; 20854929e95aSJiri Olsa perf_pmu_events_list_num = 1; 20864929e95aSJiri Olsa return 0; 20874929e95aSJiri Olsa } 20884929e95aSJiri Olsa 2089dcb4e102SKan Liang enum perf_pmu_event_symbol_type 2090dcb4e102SKan Liang perf_pmu__parse_check(const char *name) 2091dcb4e102SKan Liang { 2092dcb4e102SKan Liang struct perf_pmu_event_symbol p, *r; 2093dcb4e102SKan Liang 2094dcb4e102SKan Liang /* scan kernel pmu events from sysfs if needed */ 2095dcb4e102SKan Liang if (perf_pmu_events_list_num == 0) 2096dcb4e102SKan Liang perf_pmu__parse_init(); 2097dcb4e102SKan Liang /* 2098dcb4e102SKan Liang * name "cpu" could be prefix of cpu-cycles or cpu// events. 2099dcb4e102SKan Liang * cpu-cycles has been handled by hardcode. 2100dcb4e102SKan Liang * So it must be cpu// events, not kernel pmu event. 2101dcb4e102SKan Liang */ 2102dcb4e102SKan Liang if ((perf_pmu_events_list_num <= 0) || !strcmp(name, "cpu")) 2103dcb4e102SKan Liang return PMU_EVENT_SYMBOL_ERR; 2104dcb4e102SKan Liang 2105dcb4e102SKan Liang p.symbol = strdup(name); 2106dcb4e102SKan Liang r = bsearch(&p, perf_pmu_events_list, 2107dcb4e102SKan Liang (size_t) perf_pmu_events_list_num, 2108dcb4e102SKan Liang sizeof(struct perf_pmu_event_symbol), comp_pmu); 2109360e071bSTaeung Song zfree(&p.symbol); 2110dcb4e102SKan Liang return r ? r->type : PMU_EVENT_SYMBOL_ERR; 2111dcb4e102SKan Liang } 2112dcb4e102SKan Liang 21131244a327SJiri Olsa static int parse_events__scanner(const char *str, 21141244a327SJiri Olsa struct parse_events_state *parse_state) 2115ac20de6fSZheng Yan { 2116ac20de6fSZheng Yan YY_BUFFER_STATE buffer; 2117ac20de6fSZheng Yan void *scanner; 2118ac20de6fSZheng Yan int ret; 2119ac20de6fSZheng Yan 21201244a327SJiri Olsa ret = parse_events_lex_init_extra(parse_state, &scanner); 2121ac20de6fSZheng Yan if (ret) 2122ac20de6fSZheng Yan return ret; 2123ac20de6fSZheng Yan 2124ac20de6fSZheng Yan buffer = parse_events__scan_string(str, scanner); 2125ac20de6fSZheng Yan 2126ac20de6fSZheng Yan #ifdef PARSER_DEBUG 2127ac20de6fSZheng Yan parse_events_debug = 1; 2128ae762641SJiri Olsa parse_events_set_debug(1, scanner); 2129ac20de6fSZheng Yan #endif 21305d9cdc11SArnaldo Carvalho de Melo ret = parse_events_parse(parse_state, scanner); 2131ac20de6fSZheng Yan 2132ac20de6fSZheng Yan parse_events__flush_buffer(buffer, scanner); 2133ac20de6fSZheng Yan parse_events__delete_buffer(buffer, scanner); 2134ac20de6fSZheng Yan parse_events_lex_destroy(scanner); 2135ac20de6fSZheng Yan return ret; 2136ac20de6fSZheng Yan } 2137ac20de6fSZheng Yan 213890e2b22dSJiri Olsa /* 213990e2b22dSJiri Olsa * parse event config string, return a list of event terms. 214090e2b22dSJiri Olsa */ 214190e2b22dSJiri Olsa int parse_events_terms(struct list_head *terms, const char *str) 214290e2b22dSJiri Olsa { 21435d9cdc11SArnaldo Carvalho de Melo struct parse_events_state parse_state = { 214490e2b22dSJiri Olsa .terms = NULL, 21451244a327SJiri Olsa .stoken = PE_START_TERMS, 214690e2b22dSJiri Olsa }; 214790e2b22dSJiri Olsa int ret; 214890e2b22dSJiri Olsa 21491244a327SJiri Olsa ret = parse_events__scanner(str, &parse_state); 21504929e95aSJiri Olsa perf_pmu__parse_cleanup(); 21514929e95aSJiri Olsa 215290e2b22dSJiri Olsa if (!ret) { 21535d9cdc11SArnaldo Carvalho de Melo list_splice(parse_state.terms, terms); 21545d9cdc11SArnaldo Carvalho de Melo zfree(&parse_state.terms); 215590e2b22dSJiri Olsa return 0; 215690e2b22dSJiri Olsa } 215790e2b22dSJiri Olsa 21585d9cdc11SArnaldo Carvalho de Melo parse_events_terms__delete(parse_state.terms); 215990e2b22dSJiri Olsa return ret; 216090e2b22dSJiri Olsa } 216190e2b22dSJiri Olsa 21623bf91aa5SArnaldo Carvalho de Melo int __parse_events(struct evlist *evlist, const char *str, 21633bf91aa5SArnaldo Carvalho de Melo struct parse_events_error *err, struct perf_pmu *fake_pmu) 216486470930SIngo Molnar { 21655d9cdc11SArnaldo Carvalho de Melo struct parse_events_state parse_state = { 21665d9cdc11SArnaldo Carvalho de Melo .list = LIST_HEAD_INIT(parse_state.list), 21676484d2f9SJiri Olsa .idx = evlist->core.nr_entries, 2168b39b8393SJiri Olsa .error = err, 21697630b3e2SWang Nan .evlist = evlist, 21701244a327SJiri Olsa .stoken = PE_START_EVENTS, 21713bf91aa5SArnaldo Carvalho de Melo .fake_pmu = fake_pmu, 217246010ab2SJiri Olsa }; 217346010ab2SJiri Olsa int ret; 217486470930SIngo Molnar 21751244a327SJiri Olsa ret = parse_events__scanner(str, &parse_state); 2176dcb4e102SKan Liang perf_pmu__parse_cleanup(); 217715bfd2ccSWang Nan 21788e8714c3SIan Rogers if (!ret && list_empty(&parse_state.list)) { 2179c23080a6SArnaldo Carvalho de Melo WARN_ONCE(true, "WARNING: event parser found nothing\n"); 2180854f7363SWang Nan return -1; 2181854f7363SWang Nan } 2182854f7363SWang Nan 21838e8714c3SIan Rogers /* 21848e8714c3SIan Rogers * Add list to the evlist even with errors to allow callers to clean up. 21858e8714c3SIan Rogers */ 2186e414fd1aSArnaldo Carvalho de Melo evlist__splice_list_tail(evlist, &parse_state.list); 21878e8714c3SIan Rogers 21888e8714c3SIan Rogers if (!ret) { 21898e8714c3SIan Rogers struct evsel *last; 21908e8714c3SIan Rogers 21915d9cdc11SArnaldo Carvalho de Melo evlist->nr_groups += parse_state.nr_groups; 2192515dbe48SJiri Olsa last = evlist__last(evlist); 219315bfd2ccSWang Nan last->cmdline_group_boundary = true; 219415bfd2ccSWang Nan 219586470930SIngo Molnar return 0; 219686470930SIngo Molnar } 219786470930SIngo Molnar 21985d7be90eSJiri Olsa /* 21995d7be90eSJiri Olsa * There are 2 users - builtin-record and builtin-test objects. 2200c12995a5SJiri Olsa * Both call evlist__delete in case of error, so we dont 22015d7be90eSJiri Olsa * need to bother. 22025d7be90eSJiri Olsa */ 220389812fc8SJiri Olsa return ret; 220489812fc8SJiri Olsa } 220589812fc8SJiri Olsa 2206b39b8393SJiri Olsa #define MAX_WIDTH 1000 2207b39b8393SJiri Olsa static int get_term_width(void) 2208b39b8393SJiri Olsa { 2209b39b8393SJiri Olsa struct winsize ws; 2210b39b8393SJiri Olsa 2211b39b8393SJiri Olsa get_term_dimensions(&ws); 2212b39b8393SJiri Olsa return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col; 2213b39b8393SJiri Olsa } 2214b39b8393SJiri Olsa 2215a910e466SIan Rogers static void __parse_events_print_error(int err_idx, const char *err_str, 2216a910e466SIan Rogers const char *err_help, const char *event) 2217b39b8393SJiri Olsa { 2218b39b8393SJiri Olsa const char *str = "invalid or unsupported event: "; 2219b39b8393SJiri Olsa char _buf[MAX_WIDTH]; 2220b39b8393SJiri Olsa char *buf = (char *) event; 2221b39b8393SJiri Olsa int idx = 0; 2222a910e466SIan Rogers if (err_str) { 2223b39b8393SJiri Olsa /* -2 for extra '' in the final fprintf */ 2224b39b8393SJiri Olsa int width = get_term_width() - 2; 2225b39b8393SJiri Olsa int len_event = strlen(event); 2226b39b8393SJiri Olsa int len_str, max_len, cut = 0; 2227b39b8393SJiri Olsa 2228b39b8393SJiri Olsa /* 2229b39b8393SJiri Olsa * Maximum error index indent, we will cut 2230b39b8393SJiri Olsa * the event string if it's bigger. 2231b39b8393SJiri Olsa */ 2232141b2d31SAdrian Hunter int max_err_idx = 13; 2233b39b8393SJiri Olsa 2234b39b8393SJiri Olsa /* 2235b39b8393SJiri Olsa * Let's be specific with the message when 2236b39b8393SJiri Olsa * we have the precise error. 2237b39b8393SJiri Olsa */ 2238b39b8393SJiri Olsa str = "event syntax error: "; 2239b39b8393SJiri Olsa len_str = strlen(str); 2240b39b8393SJiri Olsa max_len = width - len_str; 2241b39b8393SJiri Olsa 2242b39b8393SJiri Olsa buf = _buf; 2243b39b8393SJiri Olsa 2244bd1a0be5SAdam Buchbinder /* We're cutting from the beginning. */ 2245a910e466SIan Rogers if (err_idx > max_err_idx) 2246a910e466SIan Rogers cut = err_idx - max_err_idx; 2247b39b8393SJiri Olsa 2248b39b8393SJiri Olsa strncpy(buf, event + cut, max_len); 2249b39b8393SJiri Olsa 2250b39b8393SJiri Olsa /* Mark cut parts with '..' on both sides. */ 2251b39b8393SJiri Olsa if (cut) 2252b39b8393SJiri Olsa buf[0] = buf[1] = '.'; 2253b39b8393SJiri Olsa 2254b39b8393SJiri Olsa if ((len_event - cut) > max_len) { 2255b39b8393SJiri Olsa buf[max_len - 1] = buf[max_len - 2] = '.'; 2256b39b8393SJiri Olsa buf[max_len] = 0; 2257b39b8393SJiri Olsa } 2258b39b8393SJiri Olsa 2259a910e466SIan Rogers idx = len_str + err_idx - cut; 2260b39b8393SJiri Olsa } 2261b39b8393SJiri Olsa 2262b39b8393SJiri Olsa fprintf(stderr, "%s'%s'\n", str, buf); 2263b39b8393SJiri Olsa if (idx) { 2264a910e466SIan Rogers fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err_str); 2265a910e466SIan Rogers if (err_help) 2266a910e466SIan Rogers fprintf(stderr, "\n%s\n", err_help); 2267a910e466SIan Rogers } 2268a910e466SIan Rogers } 2269a910e466SIan Rogers 2270a910e466SIan Rogers void parse_events_print_error(struct parse_events_error *err, 2271a910e466SIan Rogers const char *event) 2272a910e466SIan Rogers { 2273a910e466SIan Rogers if (!err->num_errors) 2274a910e466SIan Rogers return; 2275a910e466SIan Rogers 2276a910e466SIan Rogers __parse_events_print_error(err->idx, err->str, err->help, event); 2277360e071bSTaeung Song zfree(&err->str); 2278360e071bSTaeung Song zfree(&err->help); 2279a910e466SIan Rogers 2280a910e466SIan Rogers if (err->num_errors > 1) { 2281a910e466SIan Rogers fputs("\nInitial error:\n", stderr); 2282a910e466SIan Rogers __parse_events_print_error(err->first_idx, err->first_str, 2283a910e466SIan Rogers err->first_help, event); 2284a910e466SIan Rogers zfree(&err->first_str); 2285a910e466SIan Rogers zfree(&err->first_help); 2286b39b8393SJiri Olsa } 2287b39b8393SJiri Olsa } 2288b39b8393SJiri Olsa 2289b39b8393SJiri Olsa #undef MAX_WIDTH 2290b39b8393SJiri Olsa 2291f120f9d5SJiri Olsa int parse_events_option(const struct option *opt, const char *str, 22921d037ca1SIrina Tirdea int unset __maybe_unused) 2293f120f9d5SJiri Olsa { 229463503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 2295a910e466SIan Rogers struct parse_events_error err; 2296a910e466SIan Rogers int ret; 2297a910e466SIan Rogers 2298a910e466SIan Rogers bzero(&err, sizeof(err)); 2299a910e466SIan Rogers ret = parse_events(evlist, str, &err); 23009175ce1fSAndi Kleen 2301333b5665SAndi Kleen if (ret) { 2302b39b8393SJiri Olsa parse_events_print_error(&err, str); 2303333b5665SAndi Kleen fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 2304333b5665SAndi Kleen } 2305b39b8393SJiri Olsa 23069175ce1fSAndi Kleen return ret; 2307f120f9d5SJiri Olsa } 2308f120f9d5SJiri Olsa 2309d0abbc3cSArnaldo Carvalho de Melo int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset) 2310d0abbc3cSArnaldo Carvalho de Melo { 2311d0abbc3cSArnaldo Carvalho de Melo struct evlist **evlistp = opt->value; 2312d0abbc3cSArnaldo Carvalho de Melo int ret; 2313d0abbc3cSArnaldo Carvalho de Melo 2314d0abbc3cSArnaldo Carvalho de Melo if (*evlistp == NULL) { 2315d0abbc3cSArnaldo Carvalho de Melo *evlistp = evlist__new(); 2316d0abbc3cSArnaldo Carvalho de Melo 2317d0abbc3cSArnaldo Carvalho de Melo if (*evlistp == NULL) { 2318d0abbc3cSArnaldo Carvalho de Melo fprintf(stderr, "Not enough memory to create evlist\n"); 2319d0abbc3cSArnaldo Carvalho de Melo return -1; 2320d0abbc3cSArnaldo Carvalho de Melo } 2321d0abbc3cSArnaldo Carvalho de Melo } 2322d0abbc3cSArnaldo Carvalho de Melo 2323d0abbc3cSArnaldo Carvalho de Melo ret = parse_events_option(opt, str, unset); 2324d0abbc3cSArnaldo Carvalho de Melo if (ret) { 2325d0abbc3cSArnaldo Carvalho de Melo evlist__delete(*evlistp); 2326d0abbc3cSArnaldo Carvalho de Melo *evlistp = NULL; 2327d0abbc3cSArnaldo Carvalho de Melo } 2328d0abbc3cSArnaldo Carvalho de Melo 2329d0abbc3cSArnaldo Carvalho de Melo return ret; 2330d0abbc3cSArnaldo Carvalho de Melo } 2331d0abbc3cSArnaldo Carvalho de Melo 23324ba1faa1SWang Nan static int 233363503dbaSJiri Olsa foreach_evsel_in_last_glob(struct evlist *evlist, 233432dcd021SJiri Olsa int (*func)(struct evsel *evsel, 23354ba1faa1SWang Nan const void *arg), 23364ba1faa1SWang Nan const void *arg) 2337c171b552SLi Zefan { 233832dcd021SJiri Olsa struct evsel *last = NULL; 23394ba1faa1SWang Nan int err; 2340c171b552SLi Zefan 2341854f7363SWang Nan /* 2342854f7363SWang Nan * Don't return when list_empty, give func a chance to report 2343854f7363SWang Nan * error when it found last == NULL. 2344854f7363SWang Nan * 2345854f7363SWang Nan * So no need to WARN here, let *func do this. 2346854f7363SWang Nan */ 23476484d2f9SJiri Olsa if (evlist->core.nr_entries > 0) 2348515dbe48SJiri Olsa last = evlist__last(evlist); 234969aad6f1SArnaldo Carvalho de Melo 235015bfd2ccSWang Nan do { 23514ba1faa1SWang Nan err = (*func)(last, arg); 23524ba1faa1SWang Nan if (err) 2353c171b552SLi Zefan return -1; 23544ba1faa1SWang Nan if (!last) 23554ba1faa1SWang Nan return 0; 2356c171b552SLi Zefan 2357ce9036a6SJiri Olsa if (last->core.node.prev == &evlist->core.entries) 235815bfd2ccSWang Nan return 0; 2359b27c4eceSJiri Olsa last = list_entry(last->core.node.prev, struct evsel, core.node); 236015bfd2ccSWang Nan } while (!last->cmdline_group_boundary); 236115bfd2ccSWang Nan 2362c171b552SLi Zefan return 0; 2363c171b552SLi Zefan } 2364c171b552SLi Zefan 236532dcd021SJiri Olsa static int set_filter(struct evsel *evsel, const void *arg) 23664ba1faa1SWang Nan { 23674ba1faa1SWang Nan const char *str = arg; 23681e857484SMathieu Poirier bool found = false; 23691e857484SMathieu Poirier int nr_addr_filters = 0; 23701e857484SMathieu Poirier struct perf_pmu *pmu = NULL; 23714ba1faa1SWang Nan 237249836f78SJack Henschel if (evsel == NULL) { 237349836f78SJack Henschel fprintf(stderr, 237449836f78SJack Henschel "--filter option should follow a -e tracepoint or HW tracer option\n"); 237549836f78SJack Henschel return -1; 237649836f78SJack Henschel } 23774ba1faa1SWang Nan 23781fc632ceSJiri Olsa if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { 2379ad681adfSArnaldo Carvalho de Melo if (evsel__append_tp_filter(evsel, str) < 0) { 23804ba1faa1SWang Nan fprintf(stderr, 23814ba1faa1SWang Nan "not enough memory to hold filter string\n"); 23824ba1faa1SWang Nan return -1; 23834ba1faa1SWang Nan } 23844ba1faa1SWang Nan 23854ba1faa1SWang Nan return 0; 23864ba1faa1SWang Nan } 23874ba1faa1SWang Nan 23881e857484SMathieu Poirier while ((pmu = perf_pmu__scan(pmu)) != NULL) 23891fc632ceSJiri Olsa if (pmu->type == evsel->core.attr.type) { 23901e857484SMathieu Poirier found = true; 23911e857484SMathieu Poirier break; 23921e857484SMathieu Poirier } 23931e857484SMathieu Poirier 23941e857484SMathieu Poirier if (found) 23951e857484SMathieu Poirier perf_pmu__scan_file(pmu, "nr_addr_filters", 23961e857484SMathieu Poirier "%d", &nr_addr_filters); 23971e857484SMathieu Poirier 239849836f78SJack Henschel if (!nr_addr_filters) { 239949836f78SJack Henschel fprintf(stderr, 240049836f78SJack Henschel "This CPU does not support address filtering\n"); 240149836f78SJack Henschel return -1; 240249836f78SJack Henschel } 24031e857484SMathieu Poirier 2404ad681adfSArnaldo Carvalho de Melo if (evsel__append_addr_filter(evsel, str) < 0) { 24051e857484SMathieu Poirier fprintf(stderr, 24061e857484SMathieu Poirier "not enough memory to hold filter string\n"); 24071e857484SMathieu Poirier return -1; 24081e857484SMathieu Poirier } 24091e857484SMathieu Poirier 24101e857484SMathieu Poirier return 0; 24111e857484SMathieu Poirier } 24121e857484SMathieu Poirier 24134ba1faa1SWang Nan int parse_filter(const struct option *opt, const char *str, 24144ba1faa1SWang Nan int unset __maybe_unused) 24154ba1faa1SWang Nan { 241663503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 24174ba1faa1SWang Nan 24184ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, set_filter, 24194ba1faa1SWang Nan (const void *)str); 24204ba1faa1SWang Nan } 24214ba1faa1SWang Nan 242232dcd021SJiri Olsa static int add_exclude_perf_filter(struct evsel *evsel, 24234ba1faa1SWang Nan const void *arg __maybe_unused) 24244ba1faa1SWang Nan { 24254ba1faa1SWang Nan char new_filter[64]; 24264ba1faa1SWang Nan 24271fc632ceSJiri Olsa if (evsel == NULL || evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { 24284ba1faa1SWang Nan fprintf(stderr, 24294ba1faa1SWang Nan "--exclude-perf option should follow a -e tracepoint option\n"); 24304ba1faa1SWang Nan return -1; 24314ba1faa1SWang Nan } 24324ba1faa1SWang Nan 24334ba1faa1SWang Nan snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid()); 24344ba1faa1SWang Nan 2435ad681adfSArnaldo Carvalho de Melo if (evsel__append_tp_filter(evsel, new_filter) < 0) { 24364ba1faa1SWang Nan fprintf(stderr, 24374ba1faa1SWang Nan "not enough memory to hold filter string\n"); 24384ba1faa1SWang Nan return -1; 24394ba1faa1SWang Nan } 24404ba1faa1SWang Nan 24414ba1faa1SWang Nan return 0; 24424ba1faa1SWang Nan } 24434ba1faa1SWang Nan 24444ba1faa1SWang Nan int exclude_perf(const struct option *opt, 24454ba1faa1SWang Nan const char *arg __maybe_unused, 24464ba1faa1SWang Nan int unset __maybe_unused) 24474ba1faa1SWang Nan { 244863503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 24494ba1faa1SWang Nan 24504ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter, 24514ba1faa1SWang Nan NULL); 24524ba1faa1SWang Nan } 24534ba1faa1SWang Nan 245486470930SIngo Molnar static const char * const event_type_descriptors[] = { 245586470930SIngo Molnar "Hardware event", 245686470930SIngo Molnar "Software event", 245786470930SIngo Molnar "Tracepoint event", 245886470930SIngo Molnar "Hardware cache event", 245941bdcb23SLiming Wang "Raw hardware event descriptor", 246041bdcb23SLiming Wang "Hardware breakpoint", 246186470930SIngo Molnar }; 246286470930SIngo Molnar 2463ab0e4800SYunlong Song static int cmp_string(const void *a, const void *b) 2464ab0e4800SYunlong Song { 2465ab0e4800SYunlong Song const char * const *as = a; 2466ab0e4800SYunlong Song const char * const *bs = b; 2467ab0e4800SYunlong Song 2468ab0e4800SYunlong Song return strcmp(*as, *bs); 2469ab0e4800SYunlong Song } 2470ab0e4800SYunlong Song 247186470930SIngo Molnar /* 2472f6bdafefSJason Baron * Print the events from <debugfs_mount_point>/tracing/events 2473f6bdafefSJason Baron */ 2474f6bdafefSJason Baron 2475a3277d2dSFrederic Weisbecker void print_tracepoint_events(const char *subsys_glob, const char *event_glob, 2476a3277d2dSFrederic Weisbecker bool name_only) 2477f6bdafefSJason Baron { 2478f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 247922a9f41bSArnaldo Carvalho de Melo struct dirent *sys_dirent, *evt_dirent; 2480f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 248125a7d914SArnaldo Carvalho de Melo char *dir_path; 2482ab0e4800SYunlong Song char **evt_list = NULL; 2483ab0e4800SYunlong Song unsigned int evt_i = 0, evt_num = 0; 2484ab0e4800SYunlong Song bool evt_num_known = false; 2485f6bdafefSJason Baron 2486ab0e4800SYunlong Song restart: 24877014e0e3SArnaldo Carvalho de Melo sys_dir = tracing_events__opendir(); 2488f6bdafefSJason Baron if (!sys_dir) 2489725b1368SEric Dumazet return; 2490f6bdafefSJason Baron 2491ab0e4800SYunlong Song if (evt_num_known) { 2492ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 2493ab0e4800SYunlong Song if (!evt_list) 2494ab0e4800SYunlong Song goto out_close_sys_dir; 2495ab0e4800SYunlong Song } 2496ab0e4800SYunlong Song 249722a9f41bSArnaldo Carvalho de Melo for_each_subsystem(sys_dir, sys_dirent) { 2498668b8788SArnaldo Carvalho de Melo if (subsys_glob != NULL && 249922a9f41bSArnaldo Carvalho de Melo !strglobmatch(sys_dirent->d_name, subsys_glob)) 2500668b8788SArnaldo Carvalho de Melo continue; 2501725b1368SEric Dumazet 250225a7d914SArnaldo Carvalho de Melo dir_path = get_events_file(sys_dirent->d_name); 250325a7d914SArnaldo Carvalho de Melo if (!dir_path) 250425a7d914SArnaldo Carvalho de Melo continue; 2505725b1368SEric Dumazet evt_dir = opendir(dir_path); 2506725b1368SEric Dumazet if (!evt_dir) 250725a7d914SArnaldo Carvalho de Melo goto next; 2508725b1368SEric Dumazet 2509c02cab22SArnaldo Carvalho de Melo for_each_event(dir_path, evt_dir, evt_dirent) { 2510668b8788SArnaldo Carvalho de Melo if (event_glob != NULL && 251122a9f41bSArnaldo Carvalho de Melo !strglobmatch(evt_dirent->d_name, event_glob)) 2512668b8788SArnaldo Carvalho de Melo continue; 2513668b8788SArnaldo Carvalho de Melo 2514ab0e4800SYunlong Song if (!evt_num_known) { 2515ab0e4800SYunlong Song evt_num++; 2516a3277d2dSFrederic Weisbecker continue; 2517a3277d2dSFrederic Weisbecker } 2518a3277d2dSFrederic Weisbecker 2519f6bdafefSJason Baron snprintf(evt_path, MAXPATHLEN, "%s:%s", 252022a9f41bSArnaldo Carvalho de Melo sys_dirent->d_name, evt_dirent->d_name); 2521ab0e4800SYunlong Song 2522ab0e4800SYunlong Song evt_list[evt_i] = strdup(evt_path); 252325a7d914SArnaldo Carvalho de Melo if (evt_list[evt_i] == NULL) { 252425a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 2525ab0e4800SYunlong Song goto out_close_evt_dir; 252625a7d914SArnaldo Carvalho de Melo } 2527ab0e4800SYunlong Song evt_i++; 2528f6bdafefSJason Baron } 2529f6bdafefSJason Baron closedir(evt_dir); 253025a7d914SArnaldo Carvalho de Melo next: 253125a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 2532f6bdafefSJason Baron } 2533f6bdafefSJason Baron closedir(sys_dir); 2534ab0e4800SYunlong Song 2535ab0e4800SYunlong Song if (!evt_num_known) { 2536ab0e4800SYunlong Song evt_num_known = true; 2537ab0e4800SYunlong Song goto restart; 2538ab0e4800SYunlong Song } 2539ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 2540ab0e4800SYunlong Song evt_i = 0; 2541ab0e4800SYunlong Song while (evt_i < evt_num) { 2542ab0e4800SYunlong Song if (name_only) { 2543ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 2544ab0e4800SYunlong Song continue; 2545ab0e4800SYunlong Song } 2546ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], 2547ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_TRACEPOINT]); 2548ab0e4800SYunlong Song } 2549dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 2550ab0e4800SYunlong Song printf("\n"); 2551ab0e4800SYunlong Song 2552ab0e4800SYunlong Song out_free: 2553ab0e4800SYunlong Song evt_num = evt_i; 2554ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 2555ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 2556ab0e4800SYunlong Song zfree(&evt_list); 2557ab0e4800SYunlong Song return; 2558ab0e4800SYunlong Song 2559ab0e4800SYunlong Song out_close_evt_dir: 2560ab0e4800SYunlong Song closedir(evt_dir); 2561ab0e4800SYunlong Song out_close_sys_dir: 2562ab0e4800SYunlong Song closedir(sys_dir); 2563ab0e4800SYunlong Song 2564ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", 2565ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_TRACEPOINT]); 2566ab0e4800SYunlong Song if (evt_list) 2567ab0e4800SYunlong Song goto out_free; 2568f6bdafefSJason Baron } 2569f6bdafefSJason Baron 2570f6bdafefSJason Baron /* 257120c457b8SThomas Renninger * Check whether event is in <debugfs_mount_point>/tracing/events 257220c457b8SThomas Renninger */ 257320c457b8SThomas Renninger 257420c457b8SThomas Renninger int is_valid_tracepoint(const char *event_string) 257520c457b8SThomas Renninger { 257620c457b8SThomas Renninger DIR *sys_dir, *evt_dir; 257722a9f41bSArnaldo Carvalho de Melo struct dirent *sys_dirent, *evt_dirent; 257820c457b8SThomas Renninger char evt_path[MAXPATHLEN]; 257925a7d914SArnaldo Carvalho de Melo char *dir_path; 258020c457b8SThomas Renninger 25817014e0e3SArnaldo Carvalho de Melo sys_dir = tracing_events__opendir(); 258220c457b8SThomas Renninger if (!sys_dir) 258320c457b8SThomas Renninger return 0; 258420c457b8SThomas Renninger 258522a9f41bSArnaldo Carvalho de Melo for_each_subsystem(sys_dir, sys_dirent) { 258625a7d914SArnaldo Carvalho de Melo dir_path = get_events_file(sys_dirent->d_name); 258725a7d914SArnaldo Carvalho de Melo if (!dir_path) 258825a7d914SArnaldo Carvalho de Melo continue; 258920c457b8SThomas Renninger evt_dir = opendir(dir_path); 259020c457b8SThomas Renninger if (!evt_dir) 259125a7d914SArnaldo Carvalho de Melo goto next; 259220c457b8SThomas Renninger 2593c02cab22SArnaldo Carvalho de Melo for_each_event(dir_path, evt_dir, evt_dirent) { 259420c457b8SThomas Renninger snprintf(evt_path, MAXPATHLEN, "%s:%s", 259522a9f41bSArnaldo Carvalho de Melo sys_dirent->d_name, evt_dirent->d_name); 259620c457b8SThomas Renninger if (!strcmp(evt_path, event_string)) { 259720c457b8SThomas Renninger closedir(evt_dir); 259820c457b8SThomas Renninger closedir(sys_dir); 259920c457b8SThomas Renninger return 1; 260020c457b8SThomas Renninger } 260120c457b8SThomas Renninger } 260220c457b8SThomas Renninger closedir(evt_dir); 260325a7d914SArnaldo Carvalho de Melo next: 260425a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 260520c457b8SThomas Renninger } 260620c457b8SThomas Renninger closedir(sys_dir); 260720c457b8SThomas Renninger return 0; 260820c457b8SThomas Renninger } 260920c457b8SThomas Renninger 2610b41f1cecSNamhyung Kim static bool is_event_supported(u8 type, unsigned config) 2611b41f1cecSNamhyung Kim { 2612b41f1cecSNamhyung Kim bool ret = true; 261388fee52eSVince Weaver int open_return; 261432dcd021SJiri Olsa struct evsel *evsel; 2615b41f1cecSNamhyung Kim struct perf_event_attr attr = { 2616b41f1cecSNamhyung Kim .type = type, 2617b41f1cecSNamhyung Kim .config = config, 2618b41f1cecSNamhyung Kim .disabled = 1, 2619b41f1cecSNamhyung Kim }; 26209749b90eSJiri Olsa struct perf_thread_map *tmap = thread_map__new_by_tid(0); 262189896051SArnaldo Carvalho de Melo 262289896051SArnaldo Carvalho de Melo if (tmap == NULL) 262389896051SArnaldo Carvalho de Melo return false; 2624b41f1cecSNamhyung Kim 2625365c3ae7SJiri Olsa evsel = evsel__new(&attr); 2626b41f1cecSNamhyung Kim if (evsel) { 26275972d1e0SJiri Olsa open_return = evsel__open(evsel, NULL, tmap); 262888fee52eSVince Weaver ret = open_return >= 0; 262988fee52eSVince Weaver 263088fee52eSVince Weaver if (open_return == -EACCES) { 263188fee52eSVince Weaver /* 263288fee52eSVince Weaver * This happens if the paranoid value 263388fee52eSVince Weaver * /proc/sys/kernel/perf_event_paranoid is set to 2 263488fee52eSVince Weaver * Re-run with exclude_kernel set; we don't do that 263588fee52eSVince Weaver * by default as some ARM machines do not support it. 263688fee52eSVince Weaver * 263788fee52eSVince Weaver */ 26381fc632ceSJiri Olsa evsel->core.attr.exclude_kernel = 1; 26395972d1e0SJiri Olsa ret = evsel__open(evsel, NULL, tmap) >= 0; 264088fee52eSVince Weaver } 26415eb2dd2aSJiri Olsa evsel__delete(evsel); 2642b41f1cecSNamhyung Kim } 2643b41f1cecSNamhyung Kim 26447836e52eSJiri Olsa perf_thread_map__put(tmap); 2645b41f1cecSNamhyung Kim return ret; 2646b41f1cecSNamhyung Kim } 2647b41f1cecSNamhyung Kim 264840218daeSMasami Hiramatsu void print_sdt_events(const char *subsys_glob, const char *event_glob, 264940218daeSMasami Hiramatsu bool name_only) 265040218daeSMasami Hiramatsu { 265140218daeSMasami Hiramatsu struct probe_cache *pcache; 265240218daeSMasami Hiramatsu struct probe_cache_entry *ent; 265340218daeSMasami Hiramatsu struct strlist *bidlist, *sdtlist; 265440218daeSMasami Hiramatsu struct strlist_config cfg = {.dont_dupstr = true}; 265540218daeSMasami Hiramatsu struct str_node *nd, *nd2; 265640218daeSMasami Hiramatsu char *buf, *path, *ptr = NULL; 265740218daeSMasami Hiramatsu bool show_detail = false; 265840218daeSMasami Hiramatsu int ret; 265940218daeSMasami Hiramatsu 266040218daeSMasami Hiramatsu sdtlist = strlist__new(NULL, &cfg); 266140218daeSMasami Hiramatsu if (!sdtlist) { 266240218daeSMasami Hiramatsu pr_debug("Failed to allocate new strlist for SDT\n"); 266340218daeSMasami Hiramatsu return; 266440218daeSMasami Hiramatsu } 266540218daeSMasami Hiramatsu bidlist = build_id_cache__list_all(true); 266640218daeSMasami Hiramatsu if (!bidlist) { 266740218daeSMasami Hiramatsu pr_debug("Failed to get buildids: %d\n", errno); 266840218daeSMasami Hiramatsu return; 266940218daeSMasami Hiramatsu } 267040218daeSMasami Hiramatsu strlist__for_each_entry(nd, bidlist) { 2671f045b8c4SKrister Johansen pcache = probe_cache__new(nd->s, NULL); 267240218daeSMasami Hiramatsu if (!pcache) 267340218daeSMasami Hiramatsu continue; 267440218daeSMasami Hiramatsu list_for_each_entry(ent, &pcache->entries, node) { 267540218daeSMasami Hiramatsu if (!ent->sdt) 267640218daeSMasami Hiramatsu continue; 267740218daeSMasami Hiramatsu if (subsys_glob && 267840218daeSMasami Hiramatsu !strglobmatch(ent->pev.group, subsys_glob)) 267940218daeSMasami Hiramatsu continue; 268040218daeSMasami Hiramatsu if (event_glob && 268140218daeSMasami Hiramatsu !strglobmatch(ent->pev.event, event_glob)) 268240218daeSMasami Hiramatsu continue; 268340218daeSMasami Hiramatsu ret = asprintf(&buf, "%s:%s@%s", ent->pev.group, 268440218daeSMasami Hiramatsu ent->pev.event, nd->s); 268540218daeSMasami Hiramatsu if (ret > 0) 268640218daeSMasami Hiramatsu strlist__add(sdtlist, buf); 268740218daeSMasami Hiramatsu } 268840218daeSMasami Hiramatsu probe_cache__delete(pcache); 268940218daeSMasami Hiramatsu } 269040218daeSMasami Hiramatsu strlist__delete(bidlist); 269140218daeSMasami Hiramatsu 269240218daeSMasami Hiramatsu strlist__for_each_entry(nd, sdtlist) { 269340218daeSMasami Hiramatsu buf = strchr(nd->s, '@'); 269440218daeSMasami Hiramatsu if (buf) 269540218daeSMasami Hiramatsu *(buf++) = '\0'; 269640218daeSMasami Hiramatsu if (name_only) { 269740218daeSMasami Hiramatsu printf("%s ", nd->s); 269840218daeSMasami Hiramatsu continue; 269940218daeSMasami Hiramatsu } 270040218daeSMasami Hiramatsu nd2 = strlist__next(nd); 270140218daeSMasami Hiramatsu if (nd2) { 270240218daeSMasami Hiramatsu ptr = strchr(nd2->s, '@'); 270340218daeSMasami Hiramatsu if (ptr) 270440218daeSMasami Hiramatsu *ptr = '\0'; 270540218daeSMasami Hiramatsu if (strcmp(nd->s, nd2->s) == 0) 270640218daeSMasami Hiramatsu show_detail = true; 270740218daeSMasami Hiramatsu } 270840218daeSMasami Hiramatsu if (show_detail) { 270940218daeSMasami Hiramatsu path = build_id_cache__origname(buf); 271040218daeSMasami Hiramatsu ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf); 271140218daeSMasami Hiramatsu if (ret > 0) { 271240218daeSMasami Hiramatsu printf(" %-50s [%s]\n", buf, "SDT event"); 271340218daeSMasami Hiramatsu free(buf); 271440218daeSMasami Hiramatsu } 27158bde8516SChangbin Du free(path); 271640218daeSMasami Hiramatsu } else 271740218daeSMasami Hiramatsu printf(" %-50s [%s]\n", nd->s, "SDT event"); 271840218daeSMasami Hiramatsu if (nd2) { 271940218daeSMasami Hiramatsu if (strcmp(nd->s, nd2->s) != 0) 272040218daeSMasami Hiramatsu show_detail = false; 272140218daeSMasami Hiramatsu if (ptr) 272240218daeSMasami Hiramatsu *ptr = '@'; 272340218daeSMasami Hiramatsu } 272440218daeSMasami Hiramatsu } 272540218daeSMasami Hiramatsu strlist__delete(sdtlist); 272640218daeSMasami Hiramatsu } 272740218daeSMasami Hiramatsu 2728a3277d2dSFrederic Weisbecker int print_hwcache_events(const char *event_glob, bool name_only) 2729668b8788SArnaldo Carvalho de Melo { 2730ab0e4800SYunlong Song unsigned int type, op, i, evt_i = 0, evt_num = 0; 27310b668bc9SArnaldo Carvalho de Melo char name[64]; 2732ab0e4800SYunlong Song char **evt_list = NULL; 2733ab0e4800SYunlong Song bool evt_num_known = false; 2734ab0e4800SYunlong Song 2735ab0e4800SYunlong Song restart: 2736ab0e4800SYunlong Song if (evt_num_known) { 2737ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 2738ab0e4800SYunlong Song if (!evt_list) 2739ab0e4800SYunlong Song goto out_enomem; 2740ab0e4800SYunlong Song } 2741668b8788SArnaldo Carvalho de Melo 2742668b8788SArnaldo Carvalho de Melo for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 2743668b8788SArnaldo Carvalho de Melo for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 2744668b8788SArnaldo Carvalho de Melo /* skip invalid cache type */ 2745c754c382SArnaldo Carvalho de Melo if (!evsel__is_cache_op_valid(type, op)) 2746668b8788SArnaldo Carvalho de Melo continue; 2747668b8788SArnaldo Carvalho de Melo 2748668b8788SArnaldo Carvalho de Melo for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 27498ab2e96dSArnaldo Carvalho de Melo __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name)); 2750947b4ad1SIngo Molnar if (event_glob != NULL && !strglobmatch(name, event_glob)) 2751668b8788SArnaldo Carvalho de Melo continue; 2752668b8788SArnaldo Carvalho de Melo 2753b41f1cecSNamhyung Kim if (!is_event_supported(PERF_TYPE_HW_CACHE, 2754b41f1cecSNamhyung Kim type | (op << 8) | (i << 16))) 2755b41f1cecSNamhyung Kim continue; 2756b41f1cecSNamhyung Kim 2757ab0e4800SYunlong Song if (!evt_num_known) { 2758ab0e4800SYunlong Song evt_num++; 2759ab0e4800SYunlong Song continue; 2760ab0e4800SYunlong Song } 2761ab0e4800SYunlong Song 2762ab0e4800SYunlong Song evt_list[evt_i] = strdup(name); 2763ab0e4800SYunlong Song if (evt_list[evt_i] == NULL) 2764ab0e4800SYunlong Song goto out_enomem; 2765ab0e4800SYunlong Song evt_i++; 2766668b8788SArnaldo Carvalho de Melo } 2767668b8788SArnaldo Carvalho de Melo } 2768668b8788SArnaldo Carvalho de Melo } 2769668b8788SArnaldo Carvalho de Melo 2770ab0e4800SYunlong Song if (!evt_num_known) { 2771ab0e4800SYunlong Song evt_num_known = true; 2772ab0e4800SYunlong Song goto restart; 2773ab0e4800SYunlong Song } 2774ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 2775ab0e4800SYunlong Song evt_i = 0; 2776ab0e4800SYunlong Song while (evt_i < evt_num) { 2777ab0e4800SYunlong Song if (name_only) { 2778ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 2779ab0e4800SYunlong Song continue; 2780ab0e4800SYunlong Song } 2781ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], 2782ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_HW_CACHE]); 2783ab0e4800SYunlong Song } 2784dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 2785dc098b35SAndi Kleen printf("\n"); 2786ab0e4800SYunlong Song 2787ab0e4800SYunlong Song out_free: 2788ab0e4800SYunlong Song evt_num = evt_i; 2789ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 2790ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 2791ab0e4800SYunlong Song zfree(&evt_list); 2792ab0e4800SYunlong Song return evt_num; 2793ab0e4800SYunlong Song 2794ab0e4800SYunlong Song out_enomem: 2795ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]); 2796ab0e4800SYunlong Song if (evt_list) 2797ab0e4800SYunlong Song goto out_free; 2798ab0e4800SYunlong Song return evt_num; 2799668b8788SArnaldo Carvalho de Melo } 2800668b8788SArnaldo Carvalho de Melo 28015e0861baSAndi Kleen static void print_tool_event(const char *name, const char *event_glob, 28025e0861baSAndi Kleen bool name_only) 28035e0861baSAndi Kleen { 28045e0861baSAndi Kleen if (event_glob && !strglobmatch(name, event_glob)) 28055e0861baSAndi Kleen return; 28065e0861baSAndi Kleen if (name_only) 28075e0861baSAndi Kleen printf("%s ", name); 28085e0861baSAndi Kleen else 28095e0861baSAndi Kleen printf(" %-50s [%s]\n", name, "Tool event"); 28105e0861baSAndi Kleen 28115e0861baSAndi Kleen } 28125e0861baSAndi Kleen 28135e0861baSAndi Kleen void print_tool_events(const char *event_glob, bool name_only) 28145e0861baSAndi Kleen { 28155e0861baSAndi Kleen print_tool_event("duration_time", event_glob, name_only); 28165e0861baSAndi Kleen if (pager_in_use()) 28175e0861baSAndi Kleen printf("\n"); 28185e0861baSAndi Kleen } 28195e0861baSAndi Kleen 2820705750f2SYunlong Song void print_symbol_events(const char *event_glob, unsigned type, 2821a3277d2dSFrederic Weisbecker struct event_symbol *syms, unsigned max, 2822a3277d2dSFrederic Weisbecker bool name_only) 282386470930SIngo Molnar { 2824ab0e4800SYunlong Song unsigned int i, evt_i = 0, evt_num = 0; 2825947b4ad1SIngo Molnar char name[MAX_NAME_LEN]; 2826ab0e4800SYunlong Song char **evt_list = NULL; 2827ab0e4800SYunlong Song bool evt_num_known = false; 2828ab0e4800SYunlong Song 2829ab0e4800SYunlong Song restart: 2830ab0e4800SYunlong Song if (evt_num_known) { 2831ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 2832ab0e4800SYunlong Song if (!evt_list) 2833ab0e4800SYunlong Song goto out_enomem; 2834ab0e4800SYunlong Song syms -= max; 2835ab0e4800SYunlong Song } 283686470930SIngo Molnar 28371dc12760SJiri Olsa for (i = 0; i < max; i++, syms++) { 2838668b8788SArnaldo Carvalho de Melo 2839e37df6c7SArnaldo Carvalho de Melo if (event_glob != NULL && syms->symbol != NULL && 2840668b8788SArnaldo Carvalho de Melo !(strglobmatch(syms->symbol, event_glob) || 2841668b8788SArnaldo Carvalho de Melo (syms->alias && strglobmatch(syms->alias, event_glob)))) 2842668b8788SArnaldo Carvalho de Melo continue; 284386470930SIngo Molnar 2844b41f1cecSNamhyung Kim if (!is_event_supported(type, i)) 2845b41f1cecSNamhyung Kim continue; 2846b41f1cecSNamhyung Kim 2847ab0e4800SYunlong Song if (!evt_num_known) { 2848ab0e4800SYunlong Song evt_num++; 2849a3277d2dSFrederic Weisbecker continue; 2850a3277d2dSFrederic Weisbecker } 2851a3277d2dSFrederic Weisbecker 2852ab0e4800SYunlong Song if (!name_only && strlen(syms->alias)) 2853947b4ad1SIngo Molnar snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 285474d5b588SJaswinder Singh Rajput else 2855bd8d57fbSArnaldo Carvalho de Melo strlcpy(name, syms->symbol, MAX_NAME_LEN); 285686470930SIngo Molnar 2857ab0e4800SYunlong Song evt_list[evt_i] = strdup(name); 2858ab0e4800SYunlong Song if (evt_list[evt_i] == NULL) 2859ab0e4800SYunlong Song goto out_enomem; 2860ab0e4800SYunlong Song evt_i++; 286186470930SIngo Molnar } 286286470930SIngo Molnar 2863ab0e4800SYunlong Song if (!evt_num_known) { 2864ab0e4800SYunlong Song evt_num_known = true; 2865ab0e4800SYunlong Song goto restart; 2866ab0e4800SYunlong Song } 2867ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 2868ab0e4800SYunlong Song evt_i = 0; 2869ab0e4800SYunlong Song while (evt_i < evt_num) { 2870ab0e4800SYunlong Song if (name_only) { 2871ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 2872ab0e4800SYunlong Song continue; 2873ab0e4800SYunlong Song } 2874ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); 2875ab0e4800SYunlong Song } 2876dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 2877689d3018SMarti Raudsepp printf("\n"); 2878ab0e4800SYunlong Song 2879ab0e4800SYunlong Song out_free: 2880ab0e4800SYunlong Song evt_num = evt_i; 2881ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 2882ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 2883ab0e4800SYunlong Song zfree(&evt_list); 2884ab0e4800SYunlong Song return; 2885ab0e4800SYunlong Song 2886ab0e4800SYunlong Song out_enomem: 2887ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]); 2888ab0e4800SYunlong Song if (evt_list) 2889ab0e4800SYunlong Song goto out_free; 2890668b8788SArnaldo Carvalho de Melo } 28911dc12760SJiri Olsa 28921dc12760SJiri Olsa /* 28931dc12760SJiri Olsa * Print the help text for the event symbols: 28941dc12760SJiri Olsa */ 2895c8d6828aSSukadev Bhattiprolu void print_events(const char *event_glob, bool name_only, bool quiet_flag, 2896a7f6c8c8SJin Yao bool long_desc, bool details_flag, bool deprecated) 28971dc12760SJiri Olsa { 28981dc12760SJiri Olsa print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 2899a3277d2dSFrederic Weisbecker event_symbols_hw, PERF_COUNT_HW_MAX, name_only); 29001dc12760SJiri Olsa 29011dc12760SJiri Olsa print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, 2902a3277d2dSFrederic Weisbecker event_symbols_sw, PERF_COUNT_SW_MAX, name_only); 29035e0861baSAndi Kleen print_tool_events(event_glob, name_only); 29041dc12760SJiri Olsa 2905a3277d2dSFrederic Weisbecker print_hwcache_events(event_glob, name_only); 290673c24cb8SJaswinder Singh Rajput 2907bf874fcfSAndi Kleen print_pmu_events(event_glob, name_only, quiet_flag, long_desc, 2908a7f6c8c8SJin Yao details_flag, deprecated); 2909dc098b35SAndi Kleen 2910668b8788SArnaldo Carvalho de Melo if (event_glob != NULL) 2911668b8788SArnaldo Carvalho de Melo return; 291273c24cb8SJaswinder Singh Rajput 2913a3277d2dSFrederic Weisbecker if (!name_only) { 2914947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 29155f537a26SJiri Olsa "rNNN", 29161cf4a063SArnaldo Carvalho de Melo event_type_descriptors[PERF_TYPE_RAW]); 29175f537a26SJiri Olsa printf(" %-50s [%s]\n", 29185f537a26SJiri Olsa "cpu/t1=v1[,t2=v2,t3 ...]/modifier", 29195f537a26SJiri Olsa event_type_descriptors[PERF_TYPE_RAW]); 2920dfc431cbSArnaldo Carvalho de Melo if (pager_in_use()) 2921dfc431cbSArnaldo Carvalho de Melo printf(" (see 'man perf-list' on how to encode it)\n\n"); 292286470930SIngo Molnar 2923947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 29243741eb9fSJacob Shin "mem:<addr>[/len][:access]", 292541bdcb23SLiming Wang event_type_descriptors[PERF_TYPE_BREAKPOINT]); 2926dfc431cbSArnaldo Carvalho de Melo if (pager_in_use()) 29271b290d67SFrederic Weisbecker printf("\n"); 2928a3277d2dSFrederic Weisbecker } 29291b290d67SFrederic Weisbecker 2930a3277d2dSFrederic Weisbecker print_tracepoint_events(NULL, NULL, name_only); 293140218daeSMasami Hiramatsu 293240218daeSMasami Hiramatsu print_sdt_events(NULL, NULL, name_only); 293371b0acceSAndi Kleen 293433bbc571SJiri Olsa metricgroup__print(true, true, NULL, name_only, details_flag); 293570943490SStephane Eranian 293670943490SStephane Eranian print_libpfm_events(name_only, long_desc); 293786470930SIngo Molnar } 29388f707d84SJiri Olsa 29396cee6cd3SArnaldo Carvalho de Melo int parse_events__is_hardcoded_term(struct parse_events_term *term) 29408f707d84SJiri Olsa { 294116fa7e82SJiri Olsa return term->type_term != PARSE_EVENTS__TERM_TYPE_USER; 29428f707d84SJiri Olsa } 29438f707d84SJiri Olsa 294467b49b38SJiri Olsa static int new_term(struct parse_events_term **_term, 294567b49b38SJiri Olsa struct parse_events_term *temp, 294667b49b38SJiri Olsa char *str, u64 num) 29478f707d84SJiri Olsa { 29486cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 29498f707d84SJiri Olsa 295067b49b38SJiri Olsa term = malloc(sizeof(*term)); 29518f707d84SJiri Olsa if (!term) 29528f707d84SJiri Olsa return -ENOMEM; 29538f707d84SJiri Olsa 295467b49b38SJiri Olsa *term = *temp; 29558f707d84SJiri Olsa INIT_LIST_HEAD(&term->list); 2956c2f1ceadSAndi Kleen term->weak = false; 29578f707d84SJiri Olsa 295867b49b38SJiri Olsa switch (term->type_val) { 29598f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_NUM: 29608f707d84SJiri Olsa term->val.num = num; 29618f707d84SJiri Olsa break; 29628f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_STR: 29638f707d84SJiri Olsa term->val.str = str; 29648f707d84SJiri Olsa break; 29658f707d84SJiri Olsa default: 29664be8be6bSAdrian Hunter free(term); 29678f707d84SJiri Olsa return -EINVAL; 29688f707d84SJiri Olsa } 29698f707d84SJiri Olsa 29708f707d84SJiri Olsa *_term = term; 29718f707d84SJiri Olsa return 0; 29728f707d84SJiri Olsa } 29738f707d84SJiri Olsa 29746cee6cd3SArnaldo Carvalho de Melo int parse_events_term__num(struct parse_events_term **term, 2975cecf3a2eSJiri Olsa int type_term, char *config, u64 num, 297699e7138eSJiri Olsa bool no_value, 2977bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 297816fa7e82SJiri Olsa { 2979bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 2980bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 2981bb78ce7dSAdrian Hunter 298267b49b38SJiri Olsa struct parse_events_term temp = { 298367b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 298467b49b38SJiri Olsa .type_term = type_term, 298567b49b38SJiri Olsa .config = config, 298699e7138eSJiri Olsa .no_value = no_value, 298767b49b38SJiri Olsa .err_term = loc_term ? loc_term->first_column : 0, 298867b49b38SJiri Olsa .err_val = loc_val ? loc_val->first_column : 0, 298967b49b38SJiri Olsa }; 299067b49b38SJiri Olsa 299167b49b38SJiri Olsa return new_term(term, &temp, NULL, num); 299216fa7e82SJiri Olsa } 299316fa7e82SJiri Olsa 29946cee6cd3SArnaldo Carvalho de Melo int parse_events_term__str(struct parse_events_term **term, 2995cecf3a2eSJiri Olsa int type_term, char *config, char *str, 2996bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 299716fa7e82SJiri Olsa { 2998bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 2999bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 3000bb78ce7dSAdrian Hunter 300167b49b38SJiri Olsa struct parse_events_term temp = { 300267b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_STR, 300367b49b38SJiri Olsa .type_term = type_term, 300467b49b38SJiri Olsa .config = config, 300567b49b38SJiri Olsa .err_term = loc_term ? loc_term->first_column : 0, 300667b49b38SJiri Olsa .err_val = loc_val ? loc_val->first_column : 0, 300767b49b38SJiri Olsa }; 300867b49b38SJiri Olsa 300967b49b38SJiri Olsa return new_term(term, &temp, str, 0); 301016fa7e82SJiri Olsa } 301116fa7e82SJiri Olsa 30126cee6cd3SArnaldo Carvalho de Melo int parse_events_term__sym_hw(struct parse_events_term **term, 30131d33d6dcSJiri Olsa char *config, unsigned idx) 30141d33d6dcSJiri Olsa { 30151d33d6dcSJiri Olsa struct event_symbol *sym; 3016b6645a72SIan Rogers char *str; 301767b49b38SJiri Olsa struct parse_events_term temp = { 301867b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_STR, 301967b49b38SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 3020b6645a72SIan Rogers .config = config, 302167b49b38SJiri Olsa }; 30221d33d6dcSJiri Olsa 3023b6645a72SIan Rogers if (!temp.config) { 3024b6645a72SIan Rogers temp.config = strdup("event"); 3025b6645a72SIan Rogers if (!temp.config) 3026b6645a72SIan Rogers return -ENOMEM; 3027b6645a72SIan Rogers } 30281d33d6dcSJiri Olsa BUG_ON(idx >= PERF_COUNT_HW_MAX); 30291d33d6dcSJiri Olsa sym = &event_symbols_hw[idx]; 30301d33d6dcSJiri Olsa 3031b6645a72SIan Rogers str = strdup(sym->symbol); 3032b6645a72SIan Rogers if (!str) 3033b6645a72SIan Rogers return -ENOMEM; 3034b6645a72SIan Rogers return new_term(term, &temp, str, 0); 30351d33d6dcSJiri Olsa } 30361d33d6dcSJiri Olsa 30376cee6cd3SArnaldo Carvalho de Melo int parse_events_term__clone(struct parse_events_term **new, 30386cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 3039a6146d50SZheng Yan { 3040b6645a72SIan Rogers char *str; 304167b49b38SJiri Olsa struct parse_events_term temp = { 304267b49b38SJiri Olsa .type_val = term->type_val, 304367b49b38SJiri Olsa .type_term = term->type_term, 3044b6645a72SIan Rogers .config = NULL, 304567b49b38SJiri Olsa .err_term = term->err_term, 304667b49b38SJiri Olsa .err_val = term->err_val, 304767b49b38SJiri Olsa }; 304867b49b38SJiri Olsa 3049b6645a72SIan Rogers if (term->config) { 3050b6645a72SIan Rogers temp.config = strdup(term->config); 3051b6645a72SIan Rogers if (!temp.config) 3052b6645a72SIan Rogers return -ENOMEM; 3053b6645a72SIan Rogers } 3054b6645a72SIan Rogers if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 3055b6645a72SIan Rogers return new_term(new, &temp, NULL, term->val.num); 3056b6645a72SIan Rogers 3057b6645a72SIan Rogers str = strdup(term->val.str); 3058b6645a72SIan Rogers if (!str) 3059b6645a72SIan Rogers return -ENOMEM; 3060b6645a72SIan Rogers return new_term(new, &temp, str, 0); 3061a6146d50SZheng Yan } 3062a6146d50SZheng Yan 30631dc92556SIan Rogers void parse_events_term__delete(struct parse_events_term *term) 30641dc92556SIan Rogers { 30651dc92556SIan Rogers if (term->array.nr_ranges) 30661dc92556SIan Rogers zfree(&term->array.ranges); 30671dc92556SIan Rogers 30681dc92556SIan Rogers if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) 30691dc92556SIan Rogers zfree(&term->val.str); 30701dc92556SIan Rogers 30711dc92556SIan Rogers zfree(&term->config); 30721dc92556SIan Rogers free(term); 30731dc92556SIan Rogers } 30741dc92556SIan Rogers 30758255718fSAndi Kleen int parse_events_copy_term_list(struct list_head *old, 30768255718fSAndi Kleen struct list_head **new) 30778255718fSAndi Kleen { 30788255718fSAndi Kleen struct parse_events_term *term, *n; 30798255718fSAndi Kleen int ret; 30808255718fSAndi Kleen 30818255718fSAndi Kleen if (!old) { 30828255718fSAndi Kleen *new = NULL; 30838255718fSAndi Kleen return 0; 30848255718fSAndi Kleen } 30858255718fSAndi Kleen 30868255718fSAndi Kleen *new = malloc(sizeof(struct list_head)); 30878255718fSAndi Kleen if (!*new) 30888255718fSAndi Kleen return -ENOMEM; 30898255718fSAndi Kleen INIT_LIST_HEAD(*new); 30908255718fSAndi Kleen 30918255718fSAndi Kleen list_for_each_entry (term, old, list) { 30928255718fSAndi Kleen ret = parse_events_term__clone(&n, term); 30938255718fSAndi Kleen if (ret) 30948255718fSAndi Kleen return ret; 30958255718fSAndi Kleen list_add_tail(&n->list, *new); 30968255718fSAndi Kleen } 30978255718fSAndi Kleen return 0; 30988255718fSAndi Kleen } 30998255718fSAndi Kleen 3100fc0a2c1dSArnaldo Carvalho de Melo void parse_events_terms__purge(struct list_head *terms) 31018f707d84SJiri Olsa { 31026cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 31038f707d84SJiri Olsa 3104a8adfcebSWang Nan list_for_each_entry_safe(term, h, terms, list) { 3105a8adfcebSWang Nan list_del_init(&term->list); 31061dc92556SIan Rogers parse_events_term__delete(term); 31078f707d84SJiri Olsa } 3108a8adfcebSWang Nan } 3109b39b8393SJiri Olsa 31102146afc6SArnaldo Carvalho de Melo void parse_events_terms__delete(struct list_head *terms) 3111fc0a2c1dSArnaldo Carvalho de Melo { 31122146afc6SArnaldo Carvalho de Melo if (!terms) 31132146afc6SArnaldo Carvalho de Melo return; 3114fc0a2c1dSArnaldo Carvalho de Melo parse_events_terms__purge(terms); 3115d20a5f2bSWang Nan free(terms); 3116fc0a2c1dSArnaldo Carvalho de Melo } 3117fc0a2c1dSArnaldo Carvalho de Melo 31182d055bf2SWang Nan void parse_events__clear_array(struct parse_events_array *a) 31192d055bf2SWang Nan { 3120360e071bSTaeung Song zfree(&a->ranges); 31212d055bf2SWang Nan } 31222d055bf2SWang Nan 31235d9cdc11SArnaldo Carvalho de Melo void parse_events_evlist_error(struct parse_events_state *parse_state, 3124b39b8393SJiri Olsa int idx, const char *str) 3125b39b8393SJiri Olsa { 3126448d732cSIan Rogers if (!parse_state->error) 3127a6ced2beSAdrian Hunter return; 3128448d732cSIan Rogers 3129448d732cSIan Rogers parse_events__handle_error(parse_state->error, idx, strdup(str), NULL); 3130b39b8393SJiri Olsa } 3131ffeb883eSHe Kuang 313217cb5f84SWang Nan static void config_terms_list(char *buf, size_t buf_sz) 313317cb5f84SWang Nan { 313417cb5f84SWang Nan int i; 313517cb5f84SWang Nan bool first = true; 313617cb5f84SWang Nan 313717cb5f84SWang Nan buf[0] = '\0'; 313817cb5f84SWang Nan for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) { 313917cb5f84SWang Nan const char *name = config_term_names[i]; 314017cb5f84SWang Nan 31411669e509SWang Nan if (!config_term_avail(i, NULL)) 31421669e509SWang Nan continue; 314317cb5f84SWang Nan if (!name) 314417cb5f84SWang Nan continue; 314517cb5f84SWang Nan if (name[0] == '<') 314617cb5f84SWang Nan continue; 314717cb5f84SWang Nan 314817cb5f84SWang Nan if (strlen(buf) + strlen(name) + 2 >= buf_sz) 314917cb5f84SWang Nan return; 315017cb5f84SWang Nan 315117cb5f84SWang Nan if (!first) 315217cb5f84SWang Nan strcat(buf, ","); 315317cb5f84SWang Nan else 315417cb5f84SWang Nan first = false; 315517cb5f84SWang Nan strcat(buf, name); 315617cb5f84SWang Nan } 315717cb5f84SWang Nan } 315817cb5f84SWang Nan 3159ffeb883eSHe Kuang /* 3160ffeb883eSHe Kuang * Return string contains valid config terms of an event. 3161ffeb883eSHe Kuang * @additional_terms: For terms such as PMU sysfs terms. 3162ffeb883eSHe Kuang */ 3163ffeb883eSHe Kuang char *parse_events_formats_error_string(char *additional_terms) 3164ffeb883eSHe Kuang { 3165ffeb883eSHe Kuang char *str; 3166626a6b78SWang Nan /* "no-overwrite" is the longest name */ 316717cb5f84SWang Nan char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * 3168626a6b78SWang Nan (sizeof("no-overwrite") - 1)]; 3169ffeb883eSHe Kuang 317017cb5f84SWang Nan config_terms_list(static_terms, sizeof(static_terms)); 3171ffeb883eSHe Kuang /* valid terms */ 3172ffeb883eSHe Kuang if (additional_terms) { 317326dee028SWang Nan if (asprintf(&str, "valid terms: %s,%s", 317426dee028SWang Nan additional_terms, static_terms) < 0) 3175ffeb883eSHe Kuang goto fail; 3176ffeb883eSHe Kuang } else { 317726dee028SWang Nan if (asprintf(&str, "valid terms: %s", static_terms) < 0) 3178ffeb883eSHe Kuang goto fail; 3179ffeb883eSHe Kuang } 3180ffeb883eSHe Kuang return str; 3181ffeb883eSHe Kuang 3182ffeb883eSHe Kuang fail: 3183ffeb883eSHe Kuang return NULL; 3184ffeb883eSHe Kuang } 3185