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" 39*70943490SStephane Eranian #include "util/pfm.h" 4089812fc8SJiri Olsa 4189812fc8SJiri Olsa #define MAX_NAME_LEN 100 4286470930SIngo Molnar 4382ba1f2fSJiri Olsa #ifdef PARSER_DEBUG 4482ba1f2fSJiri Olsa extern int parse_events_debug; 4582ba1f2fSJiri Olsa #endif 465d9cdc11SArnaldo Carvalho de Melo int parse_events_parse(void *parse_state, void *scanner); 47e637d177SHe Kuang static int get_config_terms(struct list_head *head_config, 48e637d177SHe Kuang struct list_head *head_terms __maybe_unused); 49bcd3279fSFrederic Weisbecker 50dcb4e102SKan Liang static struct perf_pmu_event_symbol *perf_pmu_events_list; 51dcb4e102SKan Liang /* 52dcb4e102SKan Liang * The variable indicates the number of supported pmu event symbols. 53dcb4e102SKan Liang * 0 means not initialized and ready to init 54dcb4e102SKan Liang * -1 means failed to init, don't try anymore 55dcb4e102SKan Liang * >0 is the number of supported pmu event symbols 56dcb4e102SKan Liang */ 57dcb4e102SKan Liang static int perf_pmu_events_list_num; 58dcb4e102SKan Liang 59705750f2SYunlong Song struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 601dc12760SJiri Olsa [PERF_COUNT_HW_CPU_CYCLES] = { 611dc12760SJiri Olsa .symbol = "cpu-cycles", 621dc12760SJiri Olsa .alias = "cycles", 631dc12760SJiri Olsa }, 641dc12760SJiri Olsa [PERF_COUNT_HW_INSTRUCTIONS] = { 651dc12760SJiri Olsa .symbol = "instructions", 661dc12760SJiri Olsa .alias = "", 671dc12760SJiri Olsa }, 681dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_REFERENCES] = { 691dc12760SJiri Olsa .symbol = "cache-references", 701dc12760SJiri Olsa .alias = "", 711dc12760SJiri Olsa }, 721dc12760SJiri Olsa [PERF_COUNT_HW_CACHE_MISSES] = { 731dc12760SJiri Olsa .symbol = "cache-misses", 741dc12760SJiri Olsa .alias = "", 751dc12760SJiri Olsa }, 761dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 771dc12760SJiri Olsa .symbol = "branch-instructions", 781dc12760SJiri Olsa .alias = "branches", 791dc12760SJiri Olsa }, 801dc12760SJiri Olsa [PERF_COUNT_HW_BRANCH_MISSES] = { 811dc12760SJiri Olsa .symbol = "branch-misses", 821dc12760SJiri Olsa .alias = "", 831dc12760SJiri Olsa }, 841dc12760SJiri Olsa [PERF_COUNT_HW_BUS_CYCLES] = { 851dc12760SJiri Olsa .symbol = "bus-cycles", 861dc12760SJiri Olsa .alias = "", 871dc12760SJiri Olsa }, 881dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = { 891dc12760SJiri Olsa .symbol = "stalled-cycles-frontend", 901dc12760SJiri Olsa .alias = "idle-cycles-frontend", 911dc12760SJiri Olsa }, 921dc12760SJiri Olsa [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = { 931dc12760SJiri Olsa .symbol = "stalled-cycles-backend", 941dc12760SJiri Olsa .alias = "idle-cycles-backend", 951dc12760SJiri Olsa }, 961dc12760SJiri Olsa [PERF_COUNT_HW_REF_CPU_CYCLES] = { 971dc12760SJiri Olsa .symbol = "ref-cycles", 981dc12760SJiri Olsa .alias = "", 991dc12760SJiri Olsa }, 1001dc12760SJiri Olsa }; 10186470930SIngo Molnar 102705750f2SYunlong Song struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { 1031dc12760SJiri Olsa [PERF_COUNT_SW_CPU_CLOCK] = { 1041dc12760SJiri Olsa .symbol = "cpu-clock", 1051dc12760SJiri Olsa .alias = "", 1061dc12760SJiri Olsa }, 1071dc12760SJiri Olsa [PERF_COUNT_SW_TASK_CLOCK] = { 1081dc12760SJiri Olsa .symbol = "task-clock", 1091dc12760SJiri Olsa .alias = "", 1101dc12760SJiri Olsa }, 1111dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS] = { 1121dc12760SJiri Olsa .symbol = "page-faults", 1131dc12760SJiri Olsa .alias = "faults", 1141dc12760SJiri Olsa }, 1151dc12760SJiri Olsa [PERF_COUNT_SW_CONTEXT_SWITCHES] = { 1161dc12760SJiri Olsa .symbol = "context-switches", 1171dc12760SJiri Olsa .alias = "cs", 1181dc12760SJiri Olsa }, 1191dc12760SJiri Olsa [PERF_COUNT_SW_CPU_MIGRATIONS] = { 1201dc12760SJiri Olsa .symbol = "cpu-migrations", 1211dc12760SJiri Olsa .alias = "migrations", 1221dc12760SJiri Olsa }, 1231dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MIN] = { 1241dc12760SJiri Olsa .symbol = "minor-faults", 1251dc12760SJiri Olsa .alias = "", 1261dc12760SJiri Olsa }, 1271dc12760SJiri Olsa [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = { 1281dc12760SJiri Olsa .symbol = "major-faults", 1291dc12760SJiri Olsa .alias = "", 1301dc12760SJiri Olsa }, 1311dc12760SJiri Olsa [PERF_COUNT_SW_ALIGNMENT_FAULTS] = { 1321dc12760SJiri Olsa .symbol = "alignment-faults", 1331dc12760SJiri Olsa .alias = "", 1341dc12760SJiri Olsa }, 1351dc12760SJiri Olsa [PERF_COUNT_SW_EMULATION_FAULTS] = { 1361dc12760SJiri Olsa .symbol = "emulation-faults", 1371dc12760SJiri Olsa .alias = "", 1381dc12760SJiri Olsa }, 139d22d1a2aSAdrian Hunter [PERF_COUNT_SW_DUMMY] = { 140d22d1a2aSAdrian Hunter .symbol = "dummy", 141d22d1a2aSAdrian Hunter .alias = "", 142d22d1a2aSAdrian Hunter }, 143bae9cc41SArnaldo Carvalho de Melo [PERF_COUNT_SW_BPF_OUTPUT] = { 144bae9cc41SArnaldo Carvalho de Melo .symbol = "bpf-output", 145bae9cc41SArnaldo Carvalho de Melo .alias = "", 146bae9cc41SArnaldo Carvalho de Melo }, 14786470930SIngo Molnar }; 14886470930SIngo Molnar 149cdd6c482SIngo Molnar #define __PERF_EVENT_FIELD(config, name) \ 150cdd6c482SIngo Molnar ((config & PERF_EVENT_##name##_MASK) >> PERF_EVENT_##name##_SHIFT) 15186470930SIngo Molnar 152cdd6c482SIngo Molnar #define PERF_EVENT_RAW(config) __PERF_EVENT_FIELD(config, RAW) 153cdd6c482SIngo Molnar #define PERF_EVENT_CONFIG(config) __PERF_EVENT_FIELD(config, CONFIG) 154cdd6c482SIngo Molnar #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE) 155cdd6c482SIngo Molnar #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT) 15686470930SIngo Molnar 15722a9f41bSArnaldo Carvalho de Melo #define for_each_subsystem(sys_dir, sys_dirent) \ 15822a9f41bSArnaldo Carvalho de Melo while ((sys_dirent = readdir(sys_dir)) != NULL) \ 15922a9f41bSArnaldo Carvalho de Melo if (sys_dirent->d_type == DT_DIR && \ 16022a9f41bSArnaldo Carvalho de Melo (strcmp(sys_dirent->d_name, ".")) && \ 16122a9f41bSArnaldo Carvalho de Melo (strcmp(sys_dirent->d_name, ".."))) 162f6bdafefSJason Baron 163c02cab22SArnaldo Carvalho de Melo static int tp_event_has_id(const char *dir_path, struct dirent *evt_dir) 164ae07b63fSPeter Zijlstra { 165ae07b63fSPeter Zijlstra char evt_path[MAXPATHLEN]; 166ae07b63fSPeter Zijlstra int fd; 167ae07b63fSPeter Zijlstra 168c02cab22SArnaldo Carvalho de Melo snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dir->d_name); 169ae07b63fSPeter Zijlstra fd = open(evt_path, O_RDONLY); 170ae07b63fSPeter Zijlstra if (fd < 0) 171ae07b63fSPeter Zijlstra return -EINVAL; 172ae07b63fSPeter Zijlstra close(fd); 173ae07b63fSPeter Zijlstra 174ae07b63fSPeter Zijlstra return 0; 175ae07b63fSPeter Zijlstra } 176ae07b63fSPeter Zijlstra 177c02cab22SArnaldo Carvalho de Melo #define for_each_event(dir_path, evt_dir, evt_dirent) \ 17822a9f41bSArnaldo Carvalho de Melo while ((evt_dirent = readdir(evt_dir)) != NULL) \ 17922a9f41bSArnaldo Carvalho de Melo if (evt_dirent->d_type == DT_DIR && \ 18022a9f41bSArnaldo Carvalho de Melo (strcmp(evt_dirent->d_name, ".")) && \ 18122a9f41bSArnaldo Carvalho de Melo (strcmp(evt_dirent->d_name, "..")) && \ 182c02cab22SArnaldo Carvalho de Melo (!tp_event_has_id(dir_path, evt_dirent))) 183f6bdafefSJason Baron 184270bbbe8SLi Zefan #define MAX_EVENT_LENGTH 512 185f6bdafefSJason Baron 186448d732cSIan Rogers void parse_events__handle_error(struct parse_events_error *err, int idx, 187448d732cSIan Rogers char *str, char *help) 188448d732cSIan Rogers { 189448d732cSIan Rogers if (WARN(!str, "WARNING: failed to provide error string\n")) { 190448d732cSIan Rogers free(help); 191448d732cSIan Rogers return; 192448d732cSIan Rogers } 193a910e466SIan Rogers switch (err->num_errors) { 194a910e466SIan Rogers case 0: 195448d732cSIan Rogers err->idx = idx; 196a910e466SIan Rogers err->str = str; 197a910e466SIan Rogers err->help = help; 198a910e466SIan Rogers break; 199a910e466SIan Rogers case 1: 200a910e466SIan Rogers err->first_idx = err->idx; 201a910e466SIan Rogers err->idx = idx; 202a910e466SIan Rogers err->first_str = err->str; 203a910e466SIan Rogers err->str = str; 204a910e466SIan Rogers err->first_help = err->help; 205a910e466SIan Rogers err->help = help; 206a910e466SIan Rogers break; 207a910e466SIan Rogers default: 2084ac22b48SIan Rogers pr_debug("Multiple errors dropping message: %s (%s)\n", 2094ac22b48SIan Rogers err->str, err->help); 210448d732cSIan Rogers free(err->str); 211448d732cSIan Rogers err->str = str; 212448d732cSIan Rogers free(err->help); 213448d732cSIan Rogers err->help = help; 214a910e466SIan Rogers break; 215a910e466SIan Rogers } 216a910e466SIan Rogers err->num_errors++; 217448d732cSIan Rogers } 218f6bdafefSJason Baron 2191ef2ed10SFrederic Weisbecker struct tracepoint_path *tracepoint_id_to_path(u64 config) 220f6bdafefSJason Baron { 2211ef2ed10SFrederic Weisbecker struct tracepoint_path *path = NULL; 222f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 22322a9f41bSArnaldo Carvalho de Melo struct dirent *sys_dirent, *evt_dirent; 2248aa8a7c8SStephane Eranian char id_buf[24]; 225725b1368SEric Dumazet int fd; 226f6bdafefSJason Baron u64 id; 227f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 22825a7d914SArnaldo Carvalho de Melo char *dir_path; 229f6bdafefSJason Baron 2307014e0e3SArnaldo Carvalho de Melo sys_dir = tracing_events__opendir(); 231f6bdafefSJason Baron if (!sys_dir) 232725b1368SEric Dumazet return NULL; 233f6bdafefSJason Baron 23422a9f41bSArnaldo Carvalho de Melo for_each_subsystem(sys_dir, sys_dirent) { 23525a7d914SArnaldo Carvalho de Melo dir_path = get_events_file(sys_dirent->d_name); 23625a7d914SArnaldo Carvalho de Melo if (!dir_path) 23725a7d914SArnaldo Carvalho de Melo continue; 238725b1368SEric Dumazet evt_dir = opendir(dir_path); 239725b1368SEric Dumazet if (!evt_dir) 24025a7d914SArnaldo Carvalho de Melo goto next; 241725b1368SEric Dumazet 242c02cab22SArnaldo Carvalho de Melo for_each_event(dir_path, evt_dir, evt_dirent) { 243725b1368SEric Dumazet 24477f18153SJiri Olsa scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 24522a9f41bSArnaldo Carvalho de Melo evt_dirent->d_name); 246725b1368SEric Dumazet fd = open(evt_path, O_RDONLY); 247f6bdafefSJason Baron if (fd < 0) 248f6bdafefSJason Baron continue; 249f6bdafefSJason Baron if (read(fd, id_buf, sizeof(id_buf)) < 0) { 250f6bdafefSJason Baron close(fd); 251f6bdafefSJason Baron continue; 252f6bdafefSJason Baron } 253f6bdafefSJason Baron close(fd); 254f6bdafefSJason Baron id = atoll(id_buf); 255f6bdafefSJason Baron if (id == config) { 25625a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 257f6bdafefSJason Baron closedir(evt_dir); 258f6bdafefSJason Baron closedir(sys_dir); 25959b4caebSJulia Lawall path = zalloc(sizeof(*path)); 2605aa365f2STaeung Song if (!path) 2615aa365f2STaeung Song return NULL; 2627125f204SArnaldo Carvalho de Melo if (asprintf(&path->system, "%.*s", MAX_EVENT_LENGTH, sys_dirent->d_name) < 0) { 2631ef2ed10SFrederic Weisbecker free(path); 2641ef2ed10SFrederic Weisbecker return NULL; 2651ef2ed10SFrederic Weisbecker } 2667125f204SArnaldo Carvalho de Melo if (asprintf(&path->name, "%.*s", MAX_EVENT_LENGTH, evt_dirent->d_name) < 0) { 26774cf249dSArnaldo Carvalho de Melo zfree(&path->system); 2681ef2ed10SFrederic Weisbecker free(path); 2691ef2ed10SFrederic Weisbecker return NULL; 2701ef2ed10SFrederic Weisbecker } 2711ef2ed10SFrederic Weisbecker return path; 272f6bdafefSJason Baron } 273f6bdafefSJason Baron } 274f6bdafefSJason Baron closedir(evt_dir); 27525a7d914SArnaldo Carvalho de Melo next: 27625a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 277f6bdafefSJason Baron } 278f6bdafefSJason Baron 279f6bdafefSJason Baron closedir(sys_dir); 2801ef2ed10SFrederic Weisbecker return NULL; 2811ef2ed10SFrederic Weisbecker } 2821ef2ed10SFrederic Weisbecker 283e7c93f09SNamhyung Kim struct tracepoint_path *tracepoint_name_to_path(const char *name) 284e7c93f09SNamhyung Kim { 285e7c93f09SNamhyung Kim struct tracepoint_path *path = zalloc(sizeof(*path)); 286e7c93f09SNamhyung Kim char *str = strchr(name, ':'); 287e7c93f09SNamhyung Kim 288e7c93f09SNamhyung Kim if (path == NULL || str == NULL) { 289e7c93f09SNamhyung Kim free(path); 290e7c93f09SNamhyung Kim return NULL; 291e7c93f09SNamhyung Kim } 292e7c93f09SNamhyung Kim 293e7c93f09SNamhyung Kim path->system = strndup(name, str - name); 294e7c93f09SNamhyung Kim path->name = strdup(str+1); 295e7c93f09SNamhyung Kim 296e7c93f09SNamhyung Kim if (path->system == NULL || path->name == NULL) { 29774cf249dSArnaldo Carvalho de Melo zfree(&path->system); 29874cf249dSArnaldo Carvalho de Melo zfree(&path->name); 299506fde11STaeung Song zfree(&path); 300e7c93f09SNamhyung Kim } 301e7c93f09SNamhyung Kim 302e7c93f09SNamhyung Kim return path; 303e7c93f09SNamhyung Kim } 304e7c93f09SNamhyung Kim 3051424dc96SDavid Ahern const char *event_type(int type) 3061424dc96SDavid Ahern { 3071424dc96SDavid Ahern switch (type) { 3081424dc96SDavid Ahern case PERF_TYPE_HARDWARE: 3091424dc96SDavid Ahern return "hardware"; 3101424dc96SDavid Ahern 3111424dc96SDavid Ahern case PERF_TYPE_SOFTWARE: 3121424dc96SDavid Ahern return "software"; 3131424dc96SDavid Ahern 3141424dc96SDavid Ahern case PERF_TYPE_TRACEPOINT: 3151424dc96SDavid Ahern return "tracepoint"; 3161424dc96SDavid Ahern 3171424dc96SDavid Ahern case PERF_TYPE_HW_CACHE: 3181424dc96SDavid Ahern return "hardware-cache"; 3191424dc96SDavid Ahern 3201424dc96SDavid Ahern default: 3211424dc96SDavid Ahern break; 3221424dc96SDavid Ahern } 3231424dc96SDavid Ahern 3241424dc96SDavid Ahern return "unknown"; 3251424dc96SDavid Ahern } 3261424dc96SDavid Ahern 327e814fdddSWang Nan static int parse_events__is_name_term(struct parse_events_term *term) 328e814fdddSWang Nan { 329e814fdddSWang Nan return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME; 330e814fdddSWang Nan } 3317ae92e74SYan, Zheng 332e814fdddSWang Nan static char *get_config_name(struct list_head *head_terms) 333e814fdddSWang Nan { 334e814fdddSWang Nan struct parse_events_term *term; 335e814fdddSWang Nan 336e814fdddSWang Nan if (!head_terms) 337e814fdddSWang Nan return NULL; 338e814fdddSWang Nan 339e814fdddSWang Nan list_for_each_entry(term, head_terms, list) 340e814fdddSWang Nan if (parse_events__is_name_term(term)) 341e814fdddSWang Nan return term->val.str; 342e814fdddSWang Nan 343e814fdddSWang Nan return NULL; 344e814fdddSWang Nan } 3457ae92e74SYan, Zheng 34632dcd021SJiri Olsa static struct evsel * 347410136f5SStephane Eranian __add_event(struct list_head *list, int *idx, 3487ae92e74SYan, Zheng struct perf_event_attr *attr, 349*70943490SStephane Eranian bool init_attr, 35066ec1191SMark Rutland char *name, struct perf_pmu *pmu, 351f0fbb114SAndi Kleen struct list_head *config_terms, bool auto_merge_stats, 352f0fbb114SAndi Kleen const char *cpu_list) 35389812fc8SJiri Olsa { 35432dcd021SJiri Olsa struct evsel *evsel; 355f854839bSJiri Olsa struct perf_cpu_map *cpus = pmu ? pmu->cpus : 3569c3516d1SJiri Olsa cpu_list ? perf_cpu_map__new(cpu_list) : NULL; 35789812fc8SJiri Olsa 358*70943490SStephane Eranian if (init_attr) 35989812fc8SJiri Olsa event_attr_init(attr); 36089812fc8SJiri Olsa 3618f6725a2SArnaldo Carvalho de Melo evsel = evsel__new_idx(attr, *idx); 362c5cd8ac0SDavid Ahern if (!evsel) 363410136f5SStephane Eranian return NULL; 36489812fc8SJiri Olsa 36575fc5ae5STaeung Song (*idx)++; 366d400bd3aSJiri Olsa evsel->core.cpus = perf_cpu_map__get(cpus); 367fe1f61b3SJiri Olsa evsel->core.own_cpus = perf_cpu_map__get(cpus); 368648b5af3SJiri Olsa evsel->core.system_wide = pmu ? pmu->is_uncore : false; 36963ce8449SArnaldo Carvalho de Melo evsel->auto_merge_stats = auto_merge_stats; 370f30a79b0SJiri Olsa 3719db1763cSArnaldo Carvalho de Melo if (name) 37289812fc8SJiri Olsa evsel->name = strdup(name); 373930a2e29SJiri Olsa 374930a2e29SJiri Olsa if (config_terms) 375930a2e29SJiri Olsa list_splice(config_terms, &evsel->config_terms); 376930a2e29SJiri Olsa 377*70943490SStephane Eranian if (list) 378b27c4eceSJiri Olsa list_add_tail(&evsel->core.node, list); 379*70943490SStephane Eranian 380410136f5SStephane Eranian return evsel; 38189812fc8SJiri Olsa } 38289812fc8SJiri Olsa 383*70943490SStephane Eranian struct evsel *parse_events__add_event(int idx, struct perf_event_attr *attr, 384*70943490SStephane Eranian char *name, struct perf_pmu *pmu) 385*70943490SStephane Eranian { 386*70943490SStephane Eranian return __add_event(NULL, &idx, attr, false, name, pmu, NULL, false, 387*70943490SStephane Eranian NULL); 388*70943490SStephane Eranian } 389*70943490SStephane Eranian 390c5cd8ac0SDavid Ahern static int add_event(struct list_head *list, int *idx, 391930a2e29SJiri Olsa struct perf_event_attr *attr, char *name, 392930a2e29SJiri Olsa struct list_head *config_terms) 3937ae92e74SYan, Zheng { 394*70943490SStephane Eranian return __add_event(list, idx, attr, true, name, NULL, config_terms, 395*70943490SStephane Eranian false, NULL) ? 0 : -ENOMEM; 396f0fbb114SAndi Kleen } 397f0fbb114SAndi Kleen 398f0fbb114SAndi Kleen static int add_event_tool(struct list_head *list, int *idx, 399f0fbb114SAndi Kleen enum perf_tool_event tool_event) 400f0fbb114SAndi Kleen { 40132dcd021SJiri Olsa struct evsel *evsel; 402f0fbb114SAndi Kleen struct perf_event_attr attr = { 403f0fbb114SAndi Kleen .type = PERF_TYPE_SOFTWARE, 404f0fbb114SAndi Kleen .config = PERF_COUNT_SW_DUMMY, 405f0fbb114SAndi Kleen }; 406f0fbb114SAndi Kleen 407*70943490SStephane Eranian evsel = __add_event(list, idx, &attr, true, NULL, NULL, NULL, false, 408*70943490SStephane Eranian "0"); 409f0fbb114SAndi Kleen if (!evsel) 410f0fbb114SAndi Kleen return -ENOMEM; 411f0fbb114SAndi Kleen evsel->tool_event = tool_event; 412f0fbb114SAndi Kleen if (tool_event == PERF_TOOL_DURATION_TIME) 413f0fbb114SAndi Kleen evsel->unit = strdup("ns"); 414f0fbb114SAndi Kleen return 0; 4157ae92e74SYan, Zheng } 4167ae92e74SYan, Zheng 417c64e85e1SArnaldo Carvalho de Melo static int parse_aliases(char *str, const char *names[][EVSEL__MAX_ALIASES], int size) 41886470930SIngo Molnar { 41986470930SIngo Molnar int i, j; 42061c45981SPaul Mackerras int n, longest = -1; 42186470930SIngo Molnar 42286470930SIngo Molnar for (i = 0; i < size; i++) { 423c64e85e1SArnaldo Carvalho de Melo for (j = 0; j < EVSEL__MAX_ALIASES && names[i][j]; j++) { 42461c45981SPaul Mackerras n = strlen(names[i][j]); 42589812fc8SJiri Olsa if (n > longest && !strncasecmp(str, names[i][j], n)) 42661c45981SPaul Mackerras longest = n; 42761c45981SPaul Mackerras } 42889812fc8SJiri Olsa if (longest > 0) 42986470930SIngo Molnar return i; 43086470930SIngo Molnar } 43186470930SIngo Molnar 4328953645fSIngo Molnar return -1; 43386470930SIngo Molnar } 43486470930SIngo Molnar 43543d0b978SWang Nan typedef int config_term_func_t(struct perf_event_attr *attr, 43643d0b978SWang Nan struct parse_events_term *term, 43743d0b978SWang Nan struct parse_events_error *err); 43843d0b978SWang Nan static int config_term_common(struct perf_event_attr *attr, 43943d0b978SWang Nan struct parse_events_term *term, 44043d0b978SWang Nan struct parse_events_error *err); 44143d0b978SWang Nan static int config_attr(struct perf_event_attr *attr, 44243d0b978SWang Nan struct list_head *head, 44343d0b978SWang Nan struct parse_events_error *err, 44443d0b978SWang Nan config_term_func_t config_term); 44543d0b978SWang Nan 446c5cd8ac0SDavid Ahern int parse_events_add_cache(struct list_head *list, int *idx, 44743d0b978SWang Nan char *type, char *op_result1, char *op_result2, 4482c97b0d4SArnaldo Carvalho de Melo struct parse_events_error *err, 44943d0b978SWang Nan struct list_head *head_config) 45086470930SIngo Molnar { 45189812fc8SJiri Olsa struct perf_event_attr attr; 45243d0b978SWang Nan LIST_HEAD(config_terms); 45343d0b978SWang Nan char name[MAX_NAME_LEN], *config_name; 45461c45981SPaul Mackerras int cache_type = -1, cache_op = -1, cache_result = -1; 45589812fc8SJiri Olsa char *op_result[2] = { op_result1, op_result2 }; 45689812fc8SJiri Olsa int i, n; 45786470930SIngo Molnar 45886470930SIngo Molnar /* 45986470930SIngo Molnar * No fallback - if we cannot get a clear cache type 46086470930SIngo Molnar * then bail out: 46186470930SIngo Molnar */ 462c64e85e1SArnaldo Carvalho de Melo cache_type = parse_aliases(type, evsel__hw_cache, PERF_COUNT_HW_CACHE_MAX); 46386470930SIngo Molnar if (cache_type == -1) 46489812fc8SJiri Olsa return -EINVAL; 46586470930SIngo Molnar 46643d0b978SWang Nan config_name = get_config_name(head_config); 46789812fc8SJiri Olsa n = snprintf(name, MAX_NAME_LEN, "%s", type); 46889812fc8SJiri Olsa 46989812fc8SJiri Olsa for (i = 0; (i < 2) && (op_result[i]); i++) { 47089812fc8SJiri Olsa char *str = op_result[i]; 47189812fc8SJiri Olsa 472275ef387SJiri Olsa n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str); 47361c45981SPaul Mackerras 47461c45981SPaul Mackerras if (cache_op == -1) { 475c64e85e1SArnaldo Carvalho de Melo cache_op = parse_aliases(str, evsel__hw_cache_op, 47661c45981SPaul Mackerras PERF_COUNT_HW_CACHE_OP_MAX); 47761c45981SPaul Mackerras if (cache_op >= 0) { 478c754c382SArnaldo Carvalho de Melo if (!evsel__is_cache_op_valid(cache_type, cache_op)) 47989812fc8SJiri Olsa return -EINVAL; 48061c45981SPaul Mackerras continue; 48161c45981SPaul Mackerras } 48261c45981SPaul Mackerras } 48361c45981SPaul Mackerras 48461c45981SPaul Mackerras if (cache_result == -1) { 485c64e85e1SArnaldo Carvalho de Melo cache_result = parse_aliases(str, evsel__hw_cache_result, 48661c45981SPaul Mackerras PERF_COUNT_HW_CACHE_RESULT_MAX); 48761c45981SPaul Mackerras if (cache_result >= 0) 48861c45981SPaul Mackerras continue; 48961c45981SPaul Mackerras } 49061c45981SPaul Mackerras } 49161c45981SPaul Mackerras 49286470930SIngo Molnar /* 49386470930SIngo Molnar * Fall back to reads: 49486470930SIngo Molnar */ 4958953645fSIngo Molnar if (cache_op == -1) 4968953645fSIngo Molnar cache_op = PERF_COUNT_HW_CACHE_OP_READ; 49786470930SIngo Molnar 49886470930SIngo Molnar /* 49986470930SIngo Molnar * Fall back to accesses: 50086470930SIngo Molnar */ 50186470930SIngo Molnar if (cache_result == -1) 50286470930SIngo Molnar cache_result = PERF_COUNT_HW_CACHE_RESULT_ACCESS; 50386470930SIngo Molnar 50489812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 50589812fc8SJiri Olsa attr.config = cache_type | (cache_op << 8) | (cache_result << 16); 50689812fc8SJiri Olsa attr.type = PERF_TYPE_HW_CACHE; 50743d0b978SWang Nan 50843d0b978SWang Nan if (head_config) { 5092c97b0d4SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, err, 51043d0b978SWang Nan config_term_common)) 51143d0b978SWang Nan return -EINVAL; 51243d0b978SWang Nan 51343d0b978SWang Nan if (get_config_terms(head_config, &config_terms)) 51443d0b978SWang Nan return -ENOMEM; 51543d0b978SWang Nan } 51643d0b978SWang Nan return add_event(list, idx, &attr, config_name ? : name, &config_terms); 51786470930SIngo Molnar } 51886470930SIngo Molnar 519272ed29aSJiri Olsa static void tracepoint_error(struct parse_events_error *e, int err, 5208c619d6aSWang Nan const char *sys, const char *name) 52119658171SJiri Olsa { 5224584f084SIan Rogers const char *str; 52319658171SJiri Olsa char help[BUFSIZ]; 52419658171SJiri Olsa 525ec183d22SAdrian Hunter if (!e) 526ec183d22SAdrian Hunter return; 527ec183d22SAdrian Hunter 52819658171SJiri Olsa /* 52919658171SJiri Olsa * We get error directly from syscall errno ( > 0), 53019658171SJiri Olsa * or from encoded pointer's error ( < 0). 53119658171SJiri Olsa */ 53219658171SJiri Olsa err = abs(err); 53319658171SJiri Olsa 53419658171SJiri Olsa switch (err) { 53519658171SJiri Olsa case EACCES: 5364584f084SIan Rogers str = "can't access trace events"; 53719658171SJiri Olsa break; 53819658171SJiri Olsa case ENOENT: 5394584f084SIan Rogers str = "unknown tracepoint"; 54019658171SJiri Olsa break; 54119658171SJiri Olsa default: 5424584f084SIan Rogers str = "failed to add tracepoint"; 54319658171SJiri Olsa break; 54419658171SJiri Olsa } 54519658171SJiri Olsa 54619658171SJiri Olsa tracing_path__strerror_open_tp(err, help, sizeof(help), sys, name); 5474584f084SIan Rogers parse_events__handle_error(e, 0, strdup(str), strdup(help)); 54819658171SJiri Olsa } 54919658171SJiri Olsa 550c5cd8ac0SDavid Ahern static int add_tracepoint(struct list_head *list, int *idx, 5518c619d6aSWang Nan const char *sys_name, const char *evt_name, 552272ed29aSJiri Olsa struct parse_events_error *err, 553e637d177SHe Kuang struct list_head *head_config) 554bcd3279fSFrederic Weisbecker { 5558f6725a2SArnaldo Carvalho de Melo struct evsel *evsel = evsel__newtp_idx(sys_name, evt_name, (*idx)++); 556bcd3279fSFrederic Weisbecker 55719658171SJiri Olsa if (IS_ERR(evsel)) { 558272ed29aSJiri Olsa tracepoint_error(err, PTR_ERR(evsel), sys_name, evt_name); 5598dd2a131SJiri Olsa return PTR_ERR(evsel); 56019658171SJiri Olsa } 561bcd3279fSFrederic Weisbecker 562e637d177SHe Kuang if (head_config) { 563e637d177SHe Kuang LIST_HEAD(config_terms); 564e637d177SHe Kuang 565e637d177SHe Kuang if (get_config_terms(head_config, &config_terms)) 566e637d177SHe Kuang return -ENOMEM; 567e637d177SHe Kuang list_splice(&config_terms, &evsel->config_terms); 568e637d177SHe Kuang } 569e637d177SHe Kuang 570b27c4eceSJiri Olsa list_add_tail(&evsel->core.node, list); 57182fe1c29SArnaldo Carvalho de Melo return 0; 572bcd3279fSFrederic Weisbecker } 573bcd3279fSFrederic Weisbecker 574c5cd8ac0SDavid Ahern static int add_tracepoint_multi_event(struct list_head *list, int *idx, 5758c619d6aSWang Nan const char *sys_name, const char *evt_name, 576272ed29aSJiri Olsa struct parse_events_error *err, 577e637d177SHe Kuang struct list_head *head_config) 578bcd3279fSFrederic Weisbecker { 57925a7d914SArnaldo Carvalho de Melo char *evt_path; 580bcd3279fSFrederic Weisbecker struct dirent *evt_ent; 581bcd3279fSFrederic Weisbecker DIR *evt_dir; 58227bf90bfSJiri Olsa int ret = 0, found = 0; 583bcd3279fSFrederic Weisbecker 58425a7d914SArnaldo Carvalho de Melo evt_path = get_events_file(sys_name); 58525a7d914SArnaldo Carvalho de Melo if (!evt_path) { 58625a7d914SArnaldo Carvalho de Melo tracepoint_error(err, errno, sys_name, evt_name); 58725a7d914SArnaldo Carvalho de Melo return -1; 58825a7d914SArnaldo Carvalho de Melo } 589bcd3279fSFrederic Weisbecker evt_dir = opendir(evt_path); 590bcd3279fSFrederic Weisbecker if (!evt_dir) { 59125a7d914SArnaldo Carvalho de Melo put_events_file(evt_path); 592272ed29aSJiri Olsa tracepoint_error(err, errno, sys_name, evt_name); 59389812fc8SJiri Olsa return -1; 594bcd3279fSFrederic Weisbecker } 595bcd3279fSFrederic Weisbecker 59689812fc8SJiri Olsa while (!ret && (evt_ent = readdir(evt_dir))) { 597bcd3279fSFrederic Weisbecker if (!strcmp(evt_ent->d_name, ".") 598bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "..") 599bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "enable") 600bcd3279fSFrederic Weisbecker || !strcmp(evt_ent->d_name, "filter")) 601bcd3279fSFrederic Weisbecker continue; 602bcd3279fSFrederic Weisbecker 60389812fc8SJiri Olsa if (!strglobmatch(evt_ent->d_name, evt_name)) 604fb1d2edfSMasami Hiramatsu continue; 605fb1d2edfSMasami Hiramatsu 60627bf90bfSJiri Olsa found++; 60727bf90bfSJiri Olsa 608e637d177SHe Kuang ret = add_tracepoint(list, idx, sys_name, evt_ent->d_name, 609272ed29aSJiri Olsa err, head_config); 610bcd3279fSFrederic Weisbecker } 611bcd3279fSFrederic Weisbecker 61227bf90bfSJiri Olsa if (!found) { 61327bf90bfSJiri Olsa tracepoint_error(err, ENOENT, sys_name, evt_name); 61427bf90bfSJiri Olsa ret = -1; 61527bf90bfSJiri Olsa } 61627bf90bfSJiri Olsa 61725a7d914SArnaldo Carvalho de Melo put_events_file(evt_path); 6180bd3f084SJiri Olsa closedir(evt_dir); 61989812fc8SJiri Olsa return ret; 620bcd3279fSFrederic Weisbecker } 621bcd3279fSFrederic Weisbecker 622c5cd8ac0SDavid Ahern static int add_tracepoint_event(struct list_head *list, int *idx, 6238c619d6aSWang Nan const char *sys_name, const char *evt_name, 624272ed29aSJiri Olsa struct parse_events_error *err, 625e637d177SHe Kuang struct list_head *head_config) 626f35488f9SJiri Olsa { 627f35488f9SJiri Olsa return strpbrk(evt_name, "*?") ? 628e637d177SHe Kuang add_tracepoint_multi_event(list, idx, sys_name, evt_name, 629272ed29aSJiri Olsa err, head_config) : 630e637d177SHe Kuang add_tracepoint(list, idx, sys_name, evt_name, 631272ed29aSJiri Olsa err, head_config); 632f35488f9SJiri Olsa } 633f35488f9SJiri Olsa 634c5cd8ac0SDavid Ahern static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 6358c619d6aSWang Nan const char *sys_name, const char *evt_name, 636272ed29aSJiri Olsa struct parse_events_error *err, 637e637d177SHe Kuang struct list_head *head_config) 638f35488f9SJiri Olsa { 639f35488f9SJiri Olsa struct dirent *events_ent; 640f35488f9SJiri Olsa DIR *events_dir; 641f35488f9SJiri Olsa int ret = 0; 642f35488f9SJiri Olsa 6437014e0e3SArnaldo Carvalho de Melo events_dir = tracing_events__opendir(); 644f35488f9SJiri Olsa if (!events_dir) { 645272ed29aSJiri Olsa tracepoint_error(err, errno, sys_name, evt_name); 646f35488f9SJiri Olsa return -1; 647f35488f9SJiri Olsa } 648f35488f9SJiri Olsa 649f35488f9SJiri Olsa while (!ret && (events_ent = readdir(events_dir))) { 650f35488f9SJiri Olsa if (!strcmp(events_ent->d_name, ".") 651f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "..") 652f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "enable") 653f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_event") 654f35488f9SJiri Olsa || !strcmp(events_ent->d_name, "header_page")) 655f35488f9SJiri Olsa continue; 656f35488f9SJiri Olsa 657f35488f9SJiri Olsa if (!strglobmatch(events_ent->d_name, sys_name)) 658f35488f9SJiri Olsa continue; 659f35488f9SJiri Olsa 660f35488f9SJiri Olsa ret = add_tracepoint_event(list, idx, events_ent->d_name, 661272ed29aSJiri Olsa evt_name, err, head_config); 662f35488f9SJiri Olsa } 663f35488f9SJiri Olsa 664f35488f9SJiri Olsa closedir(events_dir); 665f35488f9SJiri Olsa return ret; 666f35488f9SJiri Olsa } 667f35488f9SJiri Olsa 6684edf30e3SWang Nan struct __add_bpf_event_param { 6695d9cdc11SArnaldo Carvalho de Melo struct parse_events_state *parse_state; 6704edf30e3SWang Nan struct list_head *list; 67195088a59SWang Nan struct list_head *head_config; 6724edf30e3SWang Nan }; 6734edf30e3SWang Nan 674af4a0991SArnaldo Carvalho de Melo static int add_bpf_event(const char *group, const char *event, int fd, struct bpf_object *obj, 6754edf30e3SWang Nan void *_param) 6764edf30e3SWang Nan { 6774edf30e3SWang Nan LIST_HEAD(new_evsels); 6784edf30e3SWang Nan struct __add_bpf_event_param *param = _param; 6795d9cdc11SArnaldo Carvalho de Melo struct parse_events_state *parse_state = param->parse_state; 6804edf30e3SWang Nan struct list_head *list = param->list; 68132dcd021SJiri Olsa struct evsel *pos; 6824edf30e3SWang Nan int err; 6832620b7e3SArnaldo Carvalho de Melo /* 6842620b7e3SArnaldo Carvalho de Melo * Check if we should add the event, i.e. if it is a TP but starts with a '!', 6852620b7e3SArnaldo Carvalho de Melo * then don't add the tracepoint, this will be used for something else, like 6862620b7e3SArnaldo Carvalho de Melo * adding to a BPF_MAP_TYPE_PROG_ARRAY. 6872620b7e3SArnaldo Carvalho de Melo * 6882620b7e3SArnaldo Carvalho de Melo * See tools/perf/examples/bpf/augmented_raw_syscalls.c 6892620b7e3SArnaldo Carvalho de Melo */ 6902620b7e3SArnaldo Carvalho de Melo if (group[0] == '!') 6912620b7e3SArnaldo Carvalho de Melo return 0; 6924edf30e3SWang Nan 6934edf30e3SWang Nan pr_debug("add bpf event %s:%s and attach bpf program %d\n", 694cd102d70SWang Nan group, event, fd); 6954edf30e3SWang Nan 6965d369a75SArnaldo Carvalho de Melo err = parse_events_add_tracepoint(&new_evsels, &parse_state->idx, group, 6975d369a75SArnaldo Carvalho de Melo event, parse_state->error, 69895088a59SWang Nan param->head_config); 6994edf30e3SWang Nan if (err) { 70032dcd021SJiri Olsa struct evsel *evsel, *tmp; 7014edf30e3SWang Nan 7024edf30e3SWang Nan pr_debug("Failed to add BPF event %s:%s\n", 703cd102d70SWang Nan group, event); 704b27c4eceSJiri Olsa list_for_each_entry_safe(evsel, tmp, &new_evsels, core.node) { 705b27c4eceSJiri Olsa list_del_init(&evsel->core.node); 7065eb2dd2aSJiri Olsa evsel__delete(evsel); 7074edf30e3SWang Nan } 7084edf30e3SWang Nan return err; 7094edf30e3SWang Nan } 710cd102d70SWang Nan pr_debug("adding %s:%s\n", group, event); 7114edf30e3SWang Nan 712b27c4eceSJiri Olsa list_for_each_entry(pos, &new_evsels, core.node) { 7131f45b1d4SWang Nan pr_debug("adding %s:%s to %p\n", 714cd102d70SWang Nan group, event, pos); 7151f45b1d4SWang Nan pos->bpf_fd = fd; 716af4a0991SArnaldo Carvalho de Melo pos->bpf_obj = obj; 7171f45b1d4SWang Nan } 7184edf30e3SWang Nan list_splice(&new_evsels, list); 7194edf30e3SWang Nan return 0; 7204edf30e3SWang Nan } 7214edf30e3SWang Nan 7225d9cdc11SArnaldo Carvalho de Melo int parse_events_load_bpf_obj(struct parse_events_state *parse_state, 72384c86ca1SWang Nan struct list_head *list, 72495088a59SWang Nan struct bpf_object *obj, 72595088a59SWang Nan struct list_head *head_config) 72684c86ca1SWang Nan { 72784c86ca1SWang Nan int err; 72884c86ca1SWang Nan char errbuf[BUFSIZ]; 7295d9cdc11SArnaldo Carvalho de Melo struct __add_bpf_event_param param = {parse_state, list, head_config}; 730aa3abf30SWang Nan static bool registered_unprobe_atexit = false; 73184c86ca1SWang Nan 73284c86ca1SWang Nan if (IS_ERR(obj) || !obj) { 73384c86ca1SWang Nan snprintf(errbuf, sizeof(errbuf), 73484c86ca1SWang Nan "Internal error: load bpf obj with NULL"); 73584c86ca1SWang Nan err = -EINVAL; 73684c86ca1SWang Nan goto errout; 73784c86ca1SWang Nan } 73884c86ca1SWang Nan 73984c86ca1SWang Nan /* 740aa3abf30SWang Nan * Register atexit handler before calling bpf__probe() so 741aa3abf30SWang Nan * bpf__probe() don't need to unprobe probe points its already 742aa3abf30SWang Nan * created when failure. 743aa3abf30SWang Nan */ 744aa3abf30SWang Nan if (!registered_unprobe_atexit) { 745aa3abf30SWang Nan atexit(bpf__clear); 746aa3abf30SWang Nan registered_unprobe_atexit = true; 747aa3abf30SWang Nan } 748aa3abf30SWang Nan 749aa3abf30SWang Nan err = bpf__probe(obj); 750aa3abf30SWang Nan if (err) { 751aa3abf30SWang Nan bpf__strerror_probe(obj, err, errbuf, sizeof(errbuf)); 752aa3abf30SWang Nan goto errout; 753aa3abf30SWang Nan } 754aa3abf30SWang Nan 7551e5e3ee8SWang Nan err = bpf__load(obj); 7561e5e3ee8SWang Nan if (err) { 7571e5e3ee8SWang Nan bpf__strerror_load(obj, err, errbuf, sizeof(errbuf)); 7581e5e3ee8SWang Nan goto errout; 7591e5e3ee8SWang Nan } 7601e5e3ee8SWang Nan 761cd102d70SWang Nan err = bpf__foreach_event(obj, add_bpf_event, ¶m); 7624edf30e3SWang Nan if (err) { 7634edf30e3SWang Nan snprintf(errbuf, sizeof(errbuf), 7644edf30e3SWang Nan "Attach events in BPF object failed"); 7654edf30e3SWang Nan goto errout; 7664edf30e3SWang Nan } 7674edf30e3SWang Nan 7684edf30e3SWang Nan return 0; 76984c86ca1SWang Nan errout: 7705d9cdc11SArnaldo Carvalho de Melo parse_state->error->help = strdup("(add -v to see detail)"); 7715d9cdc11SArnaldo Carvalho de Melo parse_state->error->str = strdup(errbuf); 77284c86ca1SWang Nan return err; 77384c86ca1SWang Nan } 77484c86ca1SWang Nan 775a34f3be7SWang Nan static int 7765d9cdc11SArnaldo Carvalho de Melo parse_events_config_bpf(struct parse_events_state *parse_state, 777a34f3be7SWang Nan struct bpf_object *obj, 778a34f3be7SWang Nan struct list_head *head_config) 779a34f3be7SWang Nan { 780a34f3be7SWang Nan struct parse_events_term *term; 781a34f3be7SWang Nan int error_pos; 782a34f3be7SWang Nan 783a34f3be7SWang Nan if (!head_config || list_empty(head_config)) 784a34f3be7SWang Nan return 0; 785a34f3be7SWang Nan 786a34f3be7SWang Nan list_for_each_entry(term, head_config, list) { 787a34f3be7SWang Nan char errbuf[BUFSIZ]; 788a34f3be7SWang Nan int err; 789a34f3be7SWang Nan 790a34f3be7SWang Nan if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) { 791a34f3be7SWang Nan snprintf(errbuf, sizeof(errbuf), 792a34f3be7SWang Nan "Invalid config term for BPF object"); 793a34f3be7SWang Nan errbuf[BUFSIZ - 1] = '\0'; 794a34f3be7SWang Nan 7955d9cdc11SArnaldo Carvalho de Melo parse_state->error->idx = term->err_term; 7965d9cdc11SArnaldo Carvalho de Melo parse_state->error->str = strdup(errbuf); 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) { 8025d9cdc11SArnaldo Carvalho de Melo bpf__strerror_config_obj(obj, term, parse_state->evlist, 803a34f3be7SWang Nan &error_pos, err, errbuf, 804a34f3be7SWang Nan sizeof(errbuf)); 8055d9cdc11SArnaldo Carvalho de Melo parse_state->error->help = strdup( 8067630b3e2SWang Nan "Hint:\tValid config terms:\n" 807e571e029SWang Nan " \tmap:[<arraymap>].value<indices>=[value]\n" 808e571e029SWang Nan " \tmap:[<eventmap>].event<indices>=[event]\n" 8097630b3e2SWang Nan "\n" 810e571e029SWang Nan " \twhere <indices> is something like [0,3...5] or [all]\n" 811a34f3be7SWang Nan " \t(add -v to see detail)"); 8125d9cdc11SArnaldo Carvalho de Melo parse_state->error->str = strdup(errbuf); 813a34f3be7SWang Nan if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE) 8145d9cdc11SArnaldo Carvalho de Melo parse_state->error->idx = term->err_val; 815a34f3be7SWang Nan else 8165d9cdc11SArnaldo Carvalho de Melo parse_state->error->idx = term->err_term + error_pos; 817a34f3be7SWang Nan return err; 818a34f3be7SWang Nan } 819a34f3be7SWang Nan } 820a34f3be7SWang Nan return 0; 821a34f3be7SWang Nan } 822a34f3be7SWang Nan 82395088a59SWang Nan /* 82495088a59SWang Nan * Split config terms: 82595088a59SWang Nan * perf record -e bpf.c/call-graph=fp,map:array.value[0]=1/ ... 82695088a59SWang Nan * 'call-graph=fp' is 'evt config', should be applied to each 82795088a59SWang Nan * events in bpf.c. 82895088a59SWang Nan * 'map:array.value[0]=1' is 'obj config', should be processed 82995088a59SWang Nan * with parse_events_config_bpf. 83095088a59SWang Nan * 83195088a59SWang Nan * Move object config terms from the first list to obj_head_config. 83295088a59SWang Nan */ 83395088a59SWang Nan static void 83495088a59SWang Nan split_bpf_config_terms(struct list_head *evt_head_config, 83595088a59SWang Nan struct list_head *obj_head_config) 83695088a59SWang Nan { 83795088a59SWang Nan struct parse_events_term *term, *temp; 83895088a59SWang Nan 83995088a59SWang Nan /* 84095088a59SWang Nan * Currectly, all possible user config term 84195088a59SWang Nan * belong to bpf object. parse_events__is_hardcoded_term() 84295088a59SWang Nan * happends to be a good flag. 84395088a59SWang Nan * 84495088a59SWang Nan * See parse_events_config_bpf() and 84595088a59SWang Nan * config_term_tracepoint(). 84695088a59SWang Nan */ 84795088a59SWang Nan list_for_each_entry_safe(term, temp, evt_head_config, list) 84895088a59SWang Nan if (!parse_events__is_hardcoded_term(term)) 84995088a59SWang Nan list_move_tail(&term->list, obj_head_config); 85095088a59SWang Nan } 85195088a59SWang Nan 8525d9cdc11SArnaldo Carvalho de Melo int parse_events_load_bpf(struct parse_events_state *parse_state, 85384c86ca1SWang Nan struct list_head *list, 854d509db04SWang Nan char *bpf_file_name, 855a34f3be7SWang Nan bool source, 856a34f3be7SWang Nan struct list_head *head_config) 85784c86ca1SWang Nan { 858a34f3be7SWang Nan int err; 85995088a59SWang Nan struct bpf_object *obj; 86095088a59SWang Nan LIST_HEAD(obj_head_config); 86195088a59SWang Nan 86295088a59SWang Nan if (head_config) 86395088a59SWang Nan split_bpf_config_terms(head_config, &obj_head_config); 86484c86ca1SWang Nan 865d509db04SWang Nan obj = bpf__prepare_load(bpf_file_name, source); 8666371ca3bSWang Nan if (IS_ERR(obj)) { 86784c86ca1SWang Nan char errbuf[BUFSIZ]; 86884c86ca1SWang Nan 8696371ca3bSWang Nan err = PTR_ERR(obj); 87084c86ca1SWang Nan 87184c86ca1SWang Nan if (err == -ENOTSUP) 87284c86ca1SWang Nan snprintf(errbuf, sizeof(errbuf), 87384c86ca1SWang Nan "BPF support is not compiled"); 87484c86ca1SWang Nan else 875d3e0ce39SWang Nan bpf__strerror_prepare_load(bpf_file_name, 876d3e0ce39SWang Nan source, 877d3e0ce39SWang Nan -err, errbuf, 878d3e0ce39SWang Nan sizeof(errbuf)); 87984c86ca1SWang Nan 8805d9cdc11SArnaldo Carvalho de Melo parse_state->error->help = strdup("(add -v to see detail)"); 8815d9cdc11SArnaldo Carvalho de Melo parse_state->error->str = strdup(errbuf); 88284c86ca1SWang Nan return err; 88384c86ca1SWang Nan } 88484c86ca1SWang Nan 8855d9cdc11SArnaldo Carvalho de Melo err = parse_events_load_bpf_obj(parse_state, list, obj, head_config); 886a34f3be7SWang Nan if (err) 887a34f3be7SWang Nan return err; 8885d9cdc11SArnaldo Carvalho de Melo err = parse_events_config_bpf(parse_state, obj, &obj_head_config); 88995088a59SWang Nan 89095088a59SWang Nan /* 89195088a59SWang Nan * Caller doesn't know anything about obj_head_config, 89295088a59SWang Nan * so combine them together again before returnning. 89395088a59SWang Nan */ 89495088a59SWang Nan if (head_config) 89595088a59SWang Nan list_splice_tail(&obj_head_config, head_config); 89695088a59SWang Nan return err; 89784c86ca1SWang Nan } 89884c86ca1SWang Nan 89989812fc8SJiri Olsa static int 90089812fc8SJiri Olsa parse_breakpoint_type(const char *type, struct perf_event_attr *attr) 9011b290d67SFrederic Weisbecker { 9021b290d67SFrederic Weisbecker int i; 9031b290d67SFrederic Weisbecker 9041b290d67SFrederic Weisbecker for (i = 0; i < 3; i++) { 90589812fc8SJiri Olsa if (!type || !type[i]) 9061b290d67SFrederic Weisbecker break; 9071b290d67SFrederic Weisbecker 9087582732fSJiri Olsa #define CHECK_SET_TYPE(bit) \ 9097582732fSJiri Olsa do { \ 9107582732fSJiri Olsa if (attr->bp_type & bit) \ 9117582732fSJiri Olsa return -EINVAL; \ 9127582732fSJiri Olsa else \ 9137582732fSJiri Olsa attr->bp_type |= bit; \ 9147582732fSJiri Olsa } while (0) 9157582732fSJiri Olsa 9161b290d67SFrederic Weisbecker switch (type[i]) { 9171b290d67SFrederic Weisbecker case 'r': 9187582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_R); 9191b290d67SFrederic Weisbecker break; 9201b290d67SFrederic Weisbecker case 'w': 9217582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_W); 9221b290d67SFrederic Weisbecker break; 9231b290d67SFrederic Weisbecker case 'x': 9247582732fSJiri Olsa CHECK_SET_TYPE(HW_BREAKPOINT_X); 9251b290d67SFrederic Weisbecker break; 9261b290d67SFrederic Weisbecker default: 92789812fc8SJiri Olsa return -EINVAL; 9281b290d67SFrederic Weisbecker } 9291b290d67SFrederic Weisbecker } 93089812fc8SJiri Olsa 9317582732fSJiri Olsa #undef CHECK_SET_TYPE 9327582732fSJiri Olsa 9331b290d67SFrederic Weisbecker if (!attr->bp_type) /* Default */ 9341b290d67SFrederic Weisbecker attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W; 9351b290d67SFrederic Weisbecker 93689812fc8SJiri Olsa return 0; 9371b290d67SFrederic Weisbecker } 9381b290d67SFrederic Weisbecker 939c5cd8ac0SDavid Ahern int parse_events_add_breakpoint(struct list_head *list, int *idx, 9403741eb9fSJacob Shin void *ptr, char *type, u64 len) 9411b290d67SFrederic Weisbecker { 94289812fc8SJiri Olsa struct perf_event_attr attr; 9431b290d67SFrederic Weisbecker 94489812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 9459fafd98fSJiri Olsa attr.bp_addr = (unsigned long) ptr; 9461b290d67SFrederic Weisbecker 94789812fc8SJiri Olsa if (parse_breakpoint_type(type, &attr)) 94889812fc8SJiri Olsa return -EINVAL; 9491b290d67SFrederic Weisbecker 9503741eb9fSJacob Shin /* Provide some defaults if len is not specified */ 9513741eb9fSJacob Shin if (!len) { 95289812fc8SJiri Olsa if (attr.bp_type == HW_BREAKPOINT_X) 9533741eb9fSJacob Shin len = sizeof(long); 954aa59a485SFrederic Weisbecker else 9553741eb9fSJacob Shin len = HW_BREAKPOINT_LEN_4; 9563741eb9fSJacob Shin } 9573741eb9fSJacob Shin 9583741eb9fSJacob Shin attr.bp_len = len; 959aa59a485SFrederic Weisbecker 96089812fc8SJiri Olsa attr.type = PERF_TYPE_BREAKPOINT; 9614a841d65SJovi Zhang attr.sample_period = 1; 9621b290d67SFrederic Weisbecker 963930a2e29SJiri Olsa return add_event(list, idx, &attr, NULL, NULL); 9641b290d67SFrederic Weisbecker } 9651b290d67SFrederic Weisbecker 9663b0e371cSJiri Olsa static int check_type_val(struct parse_events_term *term, 9673b0e371cSJiri Olsa struct parse_events_error *err, 9683b0e371cSJiri Olsa int type) 9693b0e371cSJiri Olsa { 9703b0e371cSJiri Olsa if (type == term->type_val) 9713b0e371cSJiri Olsa return 0; 9723b0e371cSJiri Olsa 9733b0e371cSJiri Olsa if (err) { 974448d732cSIan Rogers parse_events__handle_error(err, term->err_val, 975448d732cSIan Rogers type == PARSE_EVENTS__TERM_TYPE_NUM 976448d732cSIan Rogers ? strdup("expected numeric value") 977448d732cSIan Rogers : strdup("expected string value"), 978448d732cSIan Rogers NULL); 9793b0e371cSJiri Olsa } 9803b0e371cSJiri Olsa return -EINVAL; 9813b0e371cSJiri Olsa } 9823b0e371cSJiri Olsa 98317cb5f84SWang Nan /* 98417cb5f84SWang Nan * Update according to parse-events.l 98517cb5f84SWang Nan */ 98617cb5f84SWang Nan static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = { 98717cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_USER] = "<sysfs term>", 98817cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG] = "config", 98917cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG1] = "config1", 99017cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CONFIG2] = "config2", 99117cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_NAME] = "name", 99217cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD] = "period", 99317cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ] = "freq", 99417cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE] = "branch_type", 99517cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_TIME] = "time", 99617cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_CALLGRAPH] = "call-graph", 99717cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_STACKSIZE] = "stack-size", 99817cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", 99917cb5f84SWang Nan [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", 1000792d48b4SArnaldo Carvalho de Melo [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack", 10012fda5adaSArnaldo Carvalho de Melo [PARSE_EVENTS__TERM_TYPE_MAX_EVENTS] = "nr", 1002626a6b78SWang Nan [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite", 1003626a6b78SWang Nan [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite", 1004dd60fba7SMathieu Poirier [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config", 1005064b4e82SJin Yao [PARSE_EVENTS__TERM_TYPE_PERCORE] = "percore", 10061b992154SAdrian Hunter [PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT] = "aux-output", 1007eb7a52d4SAdrian Hunter [PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE] = "aux-sample-size", 100817cb5f84SWang Nan }; 100917cb5f84SWang Nan 10101669e509SWang Nan static bool config_term_shrinked; 10111669e509SWang Nan 10121669e509SWang Nan static bool 10131669e509SWang Nan config_term_avail(int term_type, struct parse_events_error *err) 10141669e509SWang Nan { 1015448d732cSIan Rogers char *err_str; 1016448d732cSIan Rogers 10171669e509SWang Nan if (term_type < 0 || term_type >= __PARSE_EVENTS__TERM_TYPE_NR) { 1018448d732cSIan Rogers parse_events__handle_error(err, -1, 1019448d732cSIan Rogers strdup("Invalid term_type"), NULL); 10201669e509SWang Nan return false; 10211669e509SWang Nan } 10221669e509SWang Nan if (!config_term_shrinked) 10231669e509SWang Nan return true; 10241669e509SWang Nan 10251669e509SWang Nan switch (term_type) { 10261669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG: 10271669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG1: 10281669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_CONFIG2: 10291669e509SWang Nan case PARSE_EVENTS__TERM_TYPE_NAME: 103006835545SSukadev Bhattiprolu case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 1031064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 10321669e509SWang Nan return true; 10331669e509SWang Nan default: 10341669e509SWang Nan if (!err) 10351669e509SWang Nan return false; 10361669e509SWang Nan 10371669e509SWang Nan /* term_type is validated so indexing is safe */ 1038448d732cSIan Rogers if (asprintf(&err_str, "'%s' is not usable in 'perf stat'", 1039448d732cSIan Rogers config_term_names[term_type]) >= 0) 1040448d732cSIan Rogers parse_events__handle_error(err, -1, err_str, NULL); 10411669e509SWang Nan return false; 10421669e509SWang Nan } 10431669e509SWang Nan } 10441669e509SWang Nan 10451669e509SWang Nan void parse_events__shrink_config_terms(void) 10461669e509SWang Nan { 10471669e509SWang Nan config_term_shrinked = true; 10481669e509SWang Nan } 10491669e509SWang Nan 10500b8891a8SHe Kuang static int config_term_common(struct perf_event_attr *attr, 10513b0e371cSJiri Olsa struct parse_events_term *term, 10523b0e371cSJiri Olsa struct parse_events_error *err) 10538f707d84SJiri Olsa { 105416fa7e82SJiri Olsa #define CHECK_TYPE_VAL(type) \ 105516fa7e82SJiri Olsa do { \ 10563b0e371cSJiri Olsa if (check_type_val(term, err, PARSE_EVENTS__TERM_TYPE_ ## type)) \ 105716fa7e82SJiri Olsa return -EINVAL; \ 105816fa7e82SJiri Olsa } while (0) 105916fa7e82SJiri Olsa 106016fa7e82SJiri Olsa switch (term->type_term) { 10618f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG: 106216fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 10638f707d84SJiri Olsa attr->config = term->val.num; 10648f707d84SJiri Olsa break; 10658f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG1: 106616fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 10678f707d84SJiri Olsa attr->config1 = term->val.num; 10688f707d84SJiri Olsa break; 10698f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_CONFIG2: 107016fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 10718f707d84SJiri Olsa attr->config2 = term->val.num; 10728f707d84SJiri Olsa break; 10738f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 107416fa7e82SJiri Olsa CHECK_TYPE_VAL(NUM); 10758f707d84SJiri Olsa break; 107609af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 107709af2a55SNamhyung Kim CHECK_TYPE_VAL(NUM); 107809af2a55SNamhyung Kim break; 10798f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 1080ac12f676SAndi Kleen CHECK_TYPE_VAL(STR); 1081ac12f676SAndi Kleen if (strcmp(term->val.str, "no") && 1082448d732cSIan Rogers parse_branch_str(term->val.str, 1083448d732cSIan Rogers &attr->branch_sample_type)) { 1084448d732cSIan Rogers parse_events__handle_error(err, term->err_val, 1085448d732cSIan Rogers strdup("invalid branch sample type"), 1086448d732cSIan Rogers NULL); 1087ac12f676SAndi Kleen return -EINVAL; 1088ac12f676SAndi Kleen } 10898f707d84SJiri Olsa break; 109032067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 109132067712SKan Liang CHECK_TYPE_VAL(NUM); 109232067712SKan Liang if (term->val.num > 1) { 1093448d732cSIan Rogers parse_events__handle_error(err, term->err_val, 1094448d732cSIan Rogers strdup("expected 0 or 1"), 1095448d732cSIan Rogers NULL); 109632067712SKan Liang return -EINVAL; 109732067712SKan Liang } 109832067712SKan Liang break; 1099d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 1100d457c963SKan Liang CHECK_TYPE_VAL(STR); 1101d457c963SKan Liang break; 1102d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1103d457c963SKan Liang CHECK_TYPE_VAL(NUM); 1104d457c963SKan Liang break; 1105374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1106374ce938SWang Nan CHECK_TYPE_VAL(NUM); 1107374ce938SWang Nan break; 1108374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1109374ce938SWang Nan CHECK_TYPE_VAL(NUM); 1110374ce938SWang Nan break; 1111626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1112626a6b78SWang Nan CHECK_TYPE_VAL(NUM); 1113626a6b78SWang Nan break; 1114626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1115626a6b78SWang Nan CHECK_TYPE_VAL(NUM); 1116626a6b78SWang Nan break; 11176b5fc39bSJiri Olsa case PARSE_EVENTS__TERM_TYPE_NAME: 11186b5fc39bSJiri Olsa CHECK_TYPE_VAL(STR); 11196b5fc39bSJiri Olsa break; 1120792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1121792d48b4SArnaldo Carvalho de Melo CHECK_TYPE_VAL(NUM); 1122792d48b4SArnaldo Carvalho de Melo break; 11232fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 11242fda5adaSArnaldo Carvalho de Melo CHECK_TYPE_VAL(NUM); 11252fda5adaSArnaldo Carvalho de Melo break; 1126064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 1127064b4e82SJin Yao CHECK_TYPE_VAL(NUM); 1128064b4e82SJin Yao if ((unsigned int)term->val.num > 1) { 1129448d732cSIan Rogers parse_events__handle_error(err, term->err_val, 1130448d732cSIan Rogers strdup("expected 0 or 1"), 1131448d732cSIan Rogers NULL); 1132064b4e82SJin Yao return -EINVAL; 1133064b4e82SJin Yao } 1134064b4e82SJin Yao break; 11351b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 11361b992154SAdrian Hunter CHECK_TYPE_VAL(NUM); 11371b992154SAdrian Hunter break; 1138eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1139eb7a52d4SAdrian Hunter CHECK_TYPE_VAL(NUM); 1140eb7a52d4SAdrian Hunter if (term->val.num > UINT_MAX) { 1141eb7a52d4SAdrian Hunter parse_events__handle_error(err, term->err_val, 1142eb7a52d4SAdrian Hunter strdup("too big"), 1143eb7a52d4SAdrian Hunter NULL); 1144eb7a52d4SAdrian Hunter return -EINVAL; 1145eb7a52d4SAdrian Hunter } 1146eb7a52d4SAdrian Hunter break; 11478f707d84SJiri Olsa default: 1148448d732cSIan Rogers parse_events__handle_error(err, term->err_term, 1149448d732cSIan Rogers strdup("unknown term"), 1150448d732cSIan Rogers parse_events_formats_error_string(NULL)); 11518f707d84SJiri Olsa return -EINVAL; 11528f707d84SJiri Olsa } 115316fa7e82SJiri Olsa 11541669e509SWang Nan /* 11551669e509SWang Nan * Check term availbility after basic checking so 11561669e509SWang Nan * PARSE_EVENTS__TERM_TYPE_USER can be found and filtered. 11571669e509SWang Nan * 11581669e509SWang Nan * If check availbility at the entry of this function, 11591669e509SWang Nan * user will see "'<sysfs term>' is not usable in 'perf stat'" 11601669e509SWang Nan * if an invalid config term is provided for legacy events 11611669e509SWang Nan * (for example, instructions/badterm/...), which is confusing. 11621669e509SWang Nan */ 11631669e509SWang Nan if (!config_term_avail(term->type_term, err)) 11641669e509SWang Nan return -EINVAL; 11658f707d84SJiri Olsa return 0; 116616fa7e82SJiri Olsa #undef CHECK_TYPE_VAL 11678f707d84SJiri Olsa } 11688f707d84SJiri Olsa 11690b8891a8SHe Kuang static int config_term_pmu(struct perf_event_attr *attr, 11700b8891a8SHe Kuang struct parse_events_term *term, 11710b8891a8SHe Kuang struct parse_events_error *err) 11720b8891a8SHe Kuang { 1173dd60fba7SMathieu Poirier if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER || 1174dd60fba7SMathieu Poirier term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG) 11750b8891a8SHe Kuang /* 11760b8891a8SHe Kuang * Always succeed for sysfs terms, as we dont know 11770b8891a8SHe Kuang * at this point what type they need to have. 11780b8891a8SHe Kuang */ 11790b8891a8SHe Kuang return 0; 11800b8891a8SHe Kuang else 11810b8891a8SHe Kuang return config_term_common(attr, term, err); 11820b8891a8SHe Kuang } 11830b8891a8SHe Kuang 1184e637d177SHe Kuang static int config_term_tracepoint(struct perf_event_attr *attr, 1185e637d177SHe Kuang struct parse_events_term *term, 1186e637d177SHe Kuang struct parse_events_error *err) 1187e637d177SHe Kuang { 1188e637d177SHe Kuang switch (term->type_term) { 1189e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 1190e637d177SHe Kuang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1191374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1192374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1193792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 11942fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1195626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1196626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 11971b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 1198eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1199e637d177SHe Kuang return config_term_common(attr, term, err); 1200e637d177SHe Kuang default: 1201e637d177SHe Kuang if (err) { 1202448d732cSIan Rogers parse_events__handle_error(err, term->err_term, 1203448d732cSIan Rogers strdup("unknown term"), 1204448d732cSIan Rogers strdup("valid terms: call-graph,stack-size\n")); 1205e637d177SHe Kuang } 1206e637d177SHe Kuang return -EINVAL; 1207e637d177SHe Kuang } 1208e637d177SHe Kuang 1209e637d177SHe Kuang return 0; 1210e637d177SHe Kuang } 1211e637d177SHe Kuang 12128f707d84SJiri Olsa static int config_attr(struct perf_event_attr *attr, 12133b0e371cSJiri Olsa struct list_head *head, 12140b8891a8SHe Kuang struct parse_events_error *err, 12150b8891a8SHe Kuang config_term_func_t config_term) 12168f707d84SJiri Olsa { 12176cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 12188f707d84SJiri Olsa 12198f707d84SJiri Olsa list_for_each_entry(term, head, list) 12203b0e371cSJiri Olsa if (config_term(attr, term, err)) 12218f707d84SJiri Olsa return -EINVAL; 12228f707d84SJiri Olsa 12238f707d84SJiri Olsa return 0; 12248f707d84SJiri Olsa } 12258f707d84SJiri Olsa 1226930a2e29SJiri Olsa static int get_config_terms(struct list_head *head_config, 1227930a2e29SJiri Olsa struct list_head *head_terms __maybe_unused) 1228930a2e29SJiri Olsa { 122905e54e23SIan Rogers #define ADD_CONFIG_TERM(__type, __weak) \ 123035ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *__t; \ 1231930a2e29SJiri Olsa \ 1232930a2e29SJiri Olsa __t = zalloc(sizeof(*__t)); \ 1233930a2e29SJiri Olsa if (!__t) \ 1234930a2e29SJiri Olsa return -ENOMEM; \ 1235930a2e29SJiri Olsa \ 1236930a2e29SJiri Olsa INIT_LIST_HEAD(&__t->list); \ 123735ac0cadSArnaldo Carvalho de Melo __t->type = EVSEL__CONFIG_TERM_ ## __type; \ 123805e54e23SIan Rogers __t->weak = __weak; \ 1239e884602bSLeo Yan list_add_tail(&__t->list, head_terms) 1240e884602bSLeo Yan 124105e54e23SIan Rogers #define ADD_CONFIG_TERM_VAL(__type, __name, __val, __weak) \ 1242e884602bSLeo Yan do { \ 124305e54e23SIan Rogers ADD_CONFIG_TERM(__type, __weak); \ 1244e884602bSLeo Yan __t->val.__name = __val; \ 1245e884602bSLeo Yan } while (0) 1246e884602bSLeo Yan 124705e54e23SIan Rogers #define ADD_CONFIG_TERM_STR(__type, __val, __weak) \ 1248e884602bSLeo Yan do { \ 124905e54e23SIan Rogers ADD_CONFIG_TERM(__type, __weak); \ 12503220fb8dSLeo Yan __t->val.str = strdup(__val); \ 12513220fb8dSLeo Yan if (!__t->val.str) { \ 12523220fb8dSLeo Yan zfree(&__t); \ 12533220fb8dSLeo Yan return -ENOMEM; \ 12543220fb8dSLeo Yan } \ 12553220fb8dSLeo Yan __t->free_str = true; \ 1256930a2e29SJiri Olsa } while (0) 1257930a2e29SJiri Olsa 1258930a2e29SJiri Olsa struct parse_events_term *term; 1259930a2e29SJiri Olsa 1260930a2e29SJiri Olsa list_for_each_entry(term, head_config, list) { 1261930a2e29SJiri Olsa switch (term->type_term) { 1262ee4c7588SJiri Olsa case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: 126305e54e23SIan Rogers ADD_CONFIG_TERM_VAL(PERIOD, period, term->val.num, term->weak); 126432067712SKan Liang break; 126509af2a55SNamhyung Kim case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ: 126605e54e23SIan Rogers ADD_CONFIG_TERM_VAL(FREQ, freq, term->val.num, term->weak); 126709af2a55SNamhyung Kim break; 126832067712SKan Liang case PARSE_EVENTS__TERM_TYPE_TIME: 126905e54e23SIan Rogers ADD_CONFIG_TERM_VAL(TIME, time, term->val.num, term->weak); 127032067712SKan Liang break; 1271d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_CALLGRAPH: 127205e54e23SIan Rogers ADD_CONFIG_TERM_STR(CALLGRAPH, term->val.str, term->weak); 1273d457c963SKan Liang break; 1274ac12f676SAndi Kleen case PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE: 127505e54e23SIan Rogers ADD_CONFIG_TERM_STR(BRANCH, term->val.str, term->weak); 1276ac12f676SAndi Kleen break; 1277d457c963SKan Liang case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1278e884602bSLeo Yan ADD_CONFIG_TERM_VAL(STACK_USER, stack_user, 127905e54e23SIan Rogers term->val.num, term->weak); 1280d457c963SKan Liang break; 1281374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_INHERIT: 1282e884602bSLeo Yan ADD_CONFIG_TERM_VAL(INHERIT, inherit, 128305e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 1284374ce938SWang Nan break; 1285374ce938SWang Nan case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1286e884602bSLeo Yan ADD_CONFIG_TERM_VAL(INHERIT, inherit, 128705e54e23SIan Rogers term->val.num ? 0 : 1, term->weak); 1288374ce938SWang Nan break; 1289792d48b4SArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_STACK: 1290e884602bSLeo Yan ADD_CONFIG_TERM_VAL(MAX_STACK, max_stack, 129105e54e23SIan Rogers term->val.num, term->weak); 1292792d48b4SArnaldo Carvalho de Melo break; 12932fda5adaSArnaldo Carvalho de Melo case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS: 1294e884602bSLeo Yan ADD_CONFIG_TERM_VAL(MAX_EVENTS, max_events, 129505e54e23SIan Rogers term->val.num, term->weak); 12962fda5adaSArnaldo Carvalho de Melo break; 1297626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_OVERWRITE: 1298e884602bSLeo Yan ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 129905e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 1300626a6b78SWang Nan break; 1301626a6b78SWang Nan case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE: 1302e884602bSLeo Yan ADD_CONFIG_TERM_VAL(OVERWRITE, overwrite, 130305e54e23SIan Rogers term->val.num ? 0 : 1, term->weak); 1304626a6b78SWang Nan break; 1305dd60fba7SMathieu Poirier case PARSE_EVENTS__TERM_TYPE_DRV_CFG: 130605e54e23SIan Rogers ADD_CONFIG_TERM_STR(DRV_CFG, term->val.str, term->weak); 1307dd60fba7SMathieu Poirier break; 1308064b4e82SJin Yao case PARSE_EVENTS__TERM_TYPE_PERCORE: 1309e884602bSLeo Yan ADD_CONFIG_TERM_VAL(PERCORE, percore, 131005e54e23SIan Rogers term->val.num ? true : false, term->weak); 1311064b4e82SJin Yao break; 13121b992154SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: 1313e884602bSLeo Yan ADD_CONFIG_TERM_VAL(AUX_OUTPUT, aux_output, 131405e54e23SIan Rogers term->val.num ? 1 : 0, term->weak); 13151b992154SAdrian Hunter break; 1316eb7a52d4SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: 1317e884602bSLeo Yan ADD_CONFIG_TERM_VAL(AUX_SAMPLE_SIZE, aux_sample_size, 131805e54e23SIan Rogers term->val.num, term->weak); 1319eb7a52d4SAdrian Hunter break; 1320930a2e29SJiri Olsa default: 1321930a2e29SJiri Olsa break; 1322930a2e29SJiri Olsa } 1323930a2e29SJiri Olsa } 1324a1ac7de6SAdrian Hunter return 0; 1325a1ac7de6SAdrian Hunter } 1326a1ac7de6SAdrian Hunter 1327a1ac7de6SAdrian Hunter /* 132835ac0cadSArnaldo Carvalho de Melo * Add EVSEL__CONFIG_TERM_CFG_CHG where cfg_chg will have a bit set for 1329a1ac7de6SAdrian Hunter * each bit of attr->config that the user has changed. 1330a1ac7de6SAdrian Hunter */ 1331a1ac7de6SAdrian Hunter static int get_config_chgs(struct perf_pmu *pmu, struct list_head *head_config, 1332a1ac7de6SAdrian Hunter struct list_head *head_terms) 1333a1ac7de6SAdrian Hunter { 1334a1ac7de6SAdrian Hunter struct parse_events_term *term; 1335a1ac7de6SAdrian Hunter u64 bits = 0; 1336a1ac7de6SAdrian Hunter int type; 1337a1ac7de6SAdrian Hunter 1338a1ac7de6SAdrian Hunter list_for_each_entry(term, head_config, list) { 1339a1ac7de6SAdrian Hunter switch (term->type_term) { 1340a1ac7de6SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_USER: 1341a1ac7de6SAdrian Hunter type = perf_pmu__format_type(&pmu->format, term->config); 1342a1ac7de6SAdrian Hunter if (type != PERF_PMU_FORMAT_VALUE_CONFIG) 1343a1ac7de6SAdrian Hunter continue; 1344a1ac7de6SAdrian Hunter bits |= perf_pmu__format_bits(&pmu->format, term->config); 1345a1ac7de6SAdrian Hunter break; 1346a1ac7de6SAdrian Hunter case PARSE_EVENTS__TERM_TYPE_CONFIG: 1347a1ac7de6SAdrian Hunter bits = ~(u64)0; 1348a1ac7de6SAdrian Hunter break; 1349a1ac7de6SAdrian Hunter default: 1350a1ac7de6SAdrian Hunter break; 1351a1ac7de6SAdrian Hunter } 1352a1ac7de6SAdrian Hunter } 1353a1ac7de6SAdrian Hunter 1354a1ac7de6SAdrian Hunter if (bits) 135505e54e23SIan Rogers ADD_CONFIG_TERM_VAL(CFG_CHG, cfg_chg, bits, false); 1356a1ac7de6SAdrian Hunter 1357a1ac7de6SAdrian Hunter #undef ADD_CONFIG_TERM 1358930a2e29SJiri Olsa return 0; 1359930a2e29SJiri Olsa } 1360930a2e29SJiri Olsa 1361e637d177SHe Kuang int parse_events_add_tracepoint(struct list_head *list, int *idx, 13628c619d6aSWang Nan const char *sys, const char *event, 1363272ed29aSJiri Olsa struct parse_events_error *err, 1364e637d177SHe Kuang struct list_head *head_config) 1365e637d177SHe Kuang { 1366e637d177SHe Kuang if (head_config) { 1367e637d177SHe Kuang struct perf_event_attr attr; 1368e637d177SHe Kuang 1369272ed29aSJiri Olsa if (config_attr(&attr, head_config, err, 1370e637d177SHe Kuang config_term_tracepoint)) 1371e637d177SHe Kuang return -EINVAL; 1372e637d177SHe Kuang } 1373e637d177SHe Kuang 1374e637d177SHe Kuang if (strpbrk(sys, "*?")) 1375e637d177SHe Kuang return add_tracepoint_multi_sys(list, idx, sys, event, 1376272ed29aSJiri Olsa err, head_config); 1377e637d177SHe Kuang else 1378e637d177SHe Kuang return add_tracepoint_event(list, idx, sys, event, 1379272ed29aSJiri Olsa err, head_config); 1380e637d177SHe Kuang } 1381e637d177SHe Kuang 13825d9cdc11SArnaldo Carvalho de Melo int parse_events_add_numeric(struct parse_events_state *parse_state, 138387d650beSJiri Olsa struct list_head *list, 1384b527bab5SRobert Richter u32 type, u64 config, 13858f707d84SJiri Olsa struct list_head *head_config) 138674d5b588SJaswinder Singh Rajput { 138789812fc8SJiri Olsa struct perf_event_attr attr; 1388930a2e29SJiri Olsa LIST_HEAD(config_terms); 138974d5b588SJaswinder Singh Rajput 139089812fc8SJiri Olsa memset(&attr, 0, sizeof(attr)); 139189812fc8SJiri Olsa attr.type = type; 139289812fc8SJiri Olsa attr.config = config; 13938f707d84SJiri Olsa 1394930a2e29SJiri Olsa if (head_config) { 13955d9cdc11SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, parse_state->error, 13960b8891a8SHe Kuang config_term_common)) 13978f707d84SJiri Olsa return -EINVAL; 13988f707d84SJiri Olsa 1399930a2e29SJiri Olsa if (get_config_terms(head_config, &config_terms)) 1400930a2e29SJiri Olsa return -ENOMEM; 1401930a2e29SJiri Olsa } 1402930a2e29SJiri Olsa 14035d9cdc11SArnaldo Carvalho de Melo return add_event(list, &parse_state->idx, &attr, 140410bf358aSWang Nan get_config_name(head_config), &config_terms); 1405b908debdSIngo Molnar } 1406b908debdSIngo Molnar 1407f0fbb114SAndi Kleen int parse_events_add_tool(struct parse_events_state *parse_state, 1408f0fbb114SAndi Kleen struct list_head *list, 1409f0fbb114SAndi Kleen enum perf_tool_event tool_event) 1410f0fbb114SAndi Kleen { 1411f0fbb114SAndi Kleen return add_event_tool(list, &parse_state->idx, tool_event); 1412f0fbb114SAndi Kleen } 1413f0fbb114SAndi Kleen 1414064b4e82SJin Yao static bool config_term_percore(struct list_head *config_terms) 1415064b4e82SJin Yao { 141635ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *term; 1417064b4e82SJin Yao 1418064b4e82SJin Yao list_for_each_entry(term, config_terms, list) { 141935ac0cadSArnaldo Carvalho de Melo if (term->type == EVSEL__CONFIG_TERM_PERCORE) 1420064b4e82SJin Yao return term->val.percore; 1421064b4e82SJin Yao } 1422064b4e82SJin Yao 1423064b4e82SJin Yao return false; 1424064b4e82SJin Yao } 1425064b4e82SJin Yao 1426c199c11dSAgustin Vega-Frias int parse_events_add_pmu(struct parse_events_state *parse_state, 142736adec85SJiri Olsa struct list_head *list, char *name, 14283cdc5c2cSKan Liang struct list_head *head_config, 14293cdc5c2cSKan Liang bool auto_merge_stats, 14303cdc5c2cSKan Liang bool use_alias) 14315f537a26SJiri Olsa { 14325f537a26SJiri Olsa struct perf_event_attr attr; 143346441bdcSMatt Fleming struct perf_pmu_info info; 14345f537a26SJiri Olsa struct perf_pmu *pmu; 143532dcd021SJiri Olsa struct evsel *evsel; 1436333b5665SAndi Kleen struct parse_events_error *err = parse_state->error; 14373cdc5c2cSKan Liang bool use_uncore_alias; 1438930a2e29SJiri Olsa LIST_HEAD(config_terms); 14395f537a26SJiri Olsa 14404ac22b48SIan Rogers if (verbose > 1) { 14414ac22b48SIan Rogers fprintf(stderr, "Attempting to add event pmu '%s' with '", 14424ac22b48SIan Rogers name); 14434ac22b48SIan Rogers if (head_config) { 14444ac22b48SIan Rogers struct parse_events_term *term; 14454ac22b48SIan Rogers 14464ac22b48SIan Rogers list_for_each_entry(term, head_config, list) { 14474ac22b48SIan Rogers fprintf(stderr, "%s,", term->config); 14484ac22b48SIan Rogers } 14494ac22b48SIan Rogers } 14504ac22b48SIan Rogers fprintf(stderr, "' that may result in non-fatal errors\n"); 14514ac22b48SIan Rogers } 14524ac22b48SIan Rogers 14535f537a26SJiri Olsa pmu = perf_pmu__find(name); 1454333b5665SAndi Kleen if (!pmu) { 1455448d732cSIan Rogers char *err_str; 1456448d732cSIan Rogers 1457448d732cSIan Rogers if (asprintf(&err_str, 1458333b5665SAndi Kleen "Cannot find PMU `%s'. Missing kernel support?", 1459448d732cSIan Rogers name) >= 0) 1460a910e466SIan Rogers parse_events__handle_error(err, 0, err_str, NULL); 14615f537a26SJiri Olsa return -EINVAL; 1462333b5665SAndi Kleen } 14635f537a26SJiri Olsa 1464dc0a6202SAdrian Hunter if (pmu->default_config) { 1465dc0a6202SAdrian Hunter memcpy(&attr, pmu->default_config, 1466dc0a6202SAdrian Hunter sizeof(struct perf_event_attr)); 1467dc0a6202SAdrian Hunter } else { 14685f537a26SJiri Olsa memset(&attr, 0, sizeof(attr)); 1469dc0a6202SAdrian Hunter } 14705f537a26SJiri Olsa 14713cdc5c2cSKan Liang use_uncore_alias = (pmu->is_uncore && use_alias); 14723cdc5c2cSKan Liang 1473ad962273SAdrian Hunter if (!head_config) { 1474ad962273SAdrian Hunter attr.type = pmu->type; 1475*70943490SStephane Eranian evsel = __add_event(list, &parse_state->idx, &attr, true, NULL, 1476*70943490SStephane Eranian pmu, NULL, auto_merge_stats, NULL); 14778c5421c0SAgustin Vega-Frias if (evsel) { 1478d4953f7eSIan Rogers evsel->pmu_name = name ? strdup(name) : NULL; 14793cdc5c2cSKan Liang evsel->use_uncore_alias = use_uncore_alias; 14808c5421c0SAgustin Vega-Frias return 0; 14818c5421c0SAgustin Vega-Frias } else { 14828c5421c0SAgustin Vega-Frias return -ENOMEM; 14838c5421c0SAgustin Vega-Frias } 1484ad962273SAdrian Hunter } 1485ad962273SAdrian Hunter 148646441bdcSMatt Fleming if (perf_pmu__check_alias(pmu, head_config, &info)) 1487a6146d50SZheng Yan return -EINVAL; 1488a6146d50SZheng Yan 14894ac22b48SIan Rogers if (verbose > 1) { 14904ac22b48SIan Rogers fprintf(stderr, "After aliases, add event pmu '%s' with '", 14914ac22b48SIan Rogers name); 14924ac22b48SIan Rogers if (head_config) { 14934ac22b48SIan Rogers struct parse_events_term *term; 14944ac22b48SIan Rogers 14954ac22b48SIan Rogers list_for_each_entry(term, head_config, list) { 14964ac22b48SIan Rogers fprintf(stderr, "%s,", term->config); 14974ac22b48SIan Rogers } 14984ac22b48SIan Rogers } 14994ac22b48SIan Rogers fprintf(stderr, "' that may result in non-fatal errors\n"); 15004ac22b48SIan Rogers } 15014ac22b48SIan Rogers 15025f537a26SJiri Olsa /* 15035f537a26SJiri Olsa * Configure hardcoded terms first, no need to check 15045f537a26SJiri Olsa * return value when called with fail == 0 ;) 15055f537a26SJiri Olsa */ 15065d9cdc11SArnaldo Carvalho de Melo if (config_attr(&attr, head_config, parse_state->error, config_term_pmu)) 1507c056ba6aSJiri Olsa return -EINVAL; 15085f537a26SJiri Olsa 1509930a2e29SJiri Olsa if (get_config_terms(head_config, &config_terms)) 1510930a2e29SJiri Olsa return -ENOMEM; 1511930a2e29SJiri Olsa 1512a1ac7de6SAdrian Hunter /* 1513a1ac7de6SAdrian Hunter * When using default config, record which bits of attr->config were 1514a1ac7de6SAdrian Hunter * changed by the user. 1515a1ac7de6SAdrian Hunter */ 1516a1ac7de6SAdrian Hunter if (pmu->default_config && get_config_chgs(pmu, head_config, &config_terms)) 1517a1ac7de6SAdrian Hunter return -ENOMEM; 1518a1ac7de6SAdrian Hunter 151938f2c422SIan Rogers if (perf_pmu__config(pmu, &attr, head_config, parse_state->error)) { 152035ac0cadSArnaldo Carvalho de Melo struct evsel_config_term *pos, *tmp; 152138f2c422SIan Rogers 152238f2c422SIan Rogers list_for_each_entry_safe(pos, tmp, &config_terms, list) { 152338f2c422SIan Rogers list_del_init(&pos->list); 15247fcdccd4SArnaldo Carvalho de Melo if (pos->free_str) 1525e8dfb818SIan Rogers zfree(&pos->val.str); 152638f2c422SIan Rogers free(pos); 152738f2c422SIan Rogers } 15285f537a26SJiri Olsa return -EINVAL; 152938f2c422SIan Rogers } 15305f537a26SJiri Olsa 1531*70943490SStephane Eranian evsel = __add_event(list, &parse_state->idx, &attr, true, 153266ec1191SMark Rutland get_config_name(head_config), pmu, 1533f0fbb114SAndi Kleen &config_terms, auto_merge_stats, NULL); 1534410136f5SStephane Eranian if (evsel) { 153546441bdcSMatt Fleming evsel->unit = info.unit; 153646441bdcSMatt Fleming evsel->scale = info.scale; 1537044330c1SMatt Fleming evsel->per_pkg = info.per_pkg; 15381d9e446bSJiri Olsa evsel->snapshot = info.snapshot; 153937932c18SAndi Kleen evsel->metric_expr = info.metric_expr; 154096284814SAndi Kleen evsel->metric_name = info.metric_name; 1541d4953f7eSIan Rogers evsel->pmu_name = name ? strdup(name) : NULL; 15423cdc5c2cSKan Liang evsel->use_uncore_alias = use_uncore_alias; 1543064b4e82SJin Yao evsel->percore = config_term_percore(&evsel->config_terms); 1544410136f5SStephane Eranian } 1545410136f5SStephane Eranian 1546410136f5SStephane Eranian return evsel ? 0 : -ENOMEM; 15475f537a26SJiri Olsa } 15485f537a26SJiri Olsa 15495d9cdc11SArnaldo Carvalho de Melo int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 15502073ad33SAndi Kleen char *str, struct list_head **listp) 15512073ad33SAndi Kleen { 15522073ad33SAndi Kleen struct parse_events_term *term; 15532073ad33SAndi Kleen struct list_head *list; 15542073ad33SAndi Kleen struct perf_pmu *pmu = NULL; 15552073ad33SAndi Kleen int ok = 0; 15562073ad33SAndi Kleen 15572073ad33SAndi Kleen *listp = NULL; 15582073ad33SAndi Kleen /* Add it for all PMUs that support the alias */ 15592073ad33SAndi Kleen list = malloc(sizeof(struct list_head)); 15602073ad33SAndi Kleen if (!list) 15612073ad33SAndi Kleen return -1; 15622073ad33SAndi Kleen INIT_LIST_HEAD(list); 15632073ad33SAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 15642073ad33SAndi Kleen struct perf_pmu_alias *alias; 15652073ad33SAndi Kleen 15662073ad33SAndi Kleen list_for_each_entry(alias, &pmu->aliases, list) { 15672073ad33SAndi Kleen if (!strcasecmp(alias->name, str)) { 1568b6645a72SIan Rogers struct list_head *head; 1569b6645a72SIan Rogers char *config; 1570b6645a72SIan Rogers 15712073ad33SAndi Kleen head = malloc(sizeof(struct list_head)); 15722073ad33SAndi Kleen if (!head) 15732073ad33SAndi Kleen return -1; 15742073ad33SAndi Kleen INIT_LIST_HEAD(head); 1575b6645a72SIan Rogers config = strdup(str); 1576b6645a72SIan Rogers if (!config) 15772073ad33SAndi Kleen return -1; 1578b6645a72SIan Rogers if (parse_events_term__num(&term, 1579b6645a72SIan Rogers PARSE_EVENTS__TERM_TYPE_USER, 1580b6645a72SIan Rogers config, 1, false, &config, 1581b6645a72SIan Rogers NULL) < 0) { 1582b6645a72SIan Rogers free(list); 1583b6645a72SIan Rogers free(config); 1584b6645a72SIan Rogers return -1; 1585b6645a72SIan Rogers } 15862073ad33SAndi Kleen list_add_tail(&term->list, head); 15872073ad33SAndi Kleen 1588c199c11dSAgustin Vega-Frias if (!parse_events_add_pmu(parse_state, list, 15893cdc5c2cSKan Liang pmu->name, head, 15903cdc5c2cSKan Liang true, true)) { 1591d4953f7eSIan Rogers pr_debug("%s -> %s/%s/\n", str, 15922073ad33SAndi Kleen pmu->name, alias->str); 15932073ad33SAndi Kleen ok++; 15942073ad33SAndi Kleen } 15952073ad33SAndi Kleen 15962073ad33SAndi Kleen parse_events_terms__delete(head); 15972073ad33SAndi Kleen } 15982073ad33SAndi Kleen } 15992073ad33SAndi Kleen } 1600b6645a72SIan Rogers if (!ok) { 1601b6645a72SIan Rogers free(list); 16022073ad33SAndi Kleen return -1; 1603b6645a72SIan Rogers } 16042073ad33SAndi Kleen *listp = list; 16052073ad33SAndi Kleen return 0; 16062073ad33SAndi Kleen } 16072073ad33SAndi Kleen 16086a4bb04cSJiri Olsa int parse_events__modifier_group(struct list_head *list, 16096a4bb04cSJiri Olsa char *event_mod) 161089efb029SJiri Olsa { 16116a4bb04cSJiri Olsa return parse_events__modifier_event(list, event_mod, true); 16126a4bb04cSJiri Olsa } 16136a4bb04cSJiri Olsa 16143cdc5c2cSKan Liang /* 16153cdc5c2cSKan Liang * Check if the two uncore PMUs are from the same uncore block 16163cdc5c2cSKan Liang * The format of the uncore PMU name is uncore_#blockname_#pmuidx 16173cdc5c2cSKan Liang */ 16183cdc5c2cSKan Liang static bool is_same_uncore_block(const char *pmu_name_a, const char *pmu_name_b) 16193cdc5c2cSKan Liang { 16203cdc5c2cSKan Liang char *end_a, *end_b; 16213cdc5c2cSKan Liang 16223cdc5c2cSKan Liang end_a = strrchr(pmu_name_a, '_'); 16233cdc5c2cSKan Liang end_b = strrchr(pmu_name_b, '_'); 16243cdc5c2cSKan Liang 16253cdc5c2cSKan Liang if (!end_a || !end_b) 16263cdc5c2cSKan Liang return false; 16273cdc5c2cSKan Liang 16283cdc5c2cSKan Liang if ((end_a - pmu_name_a) != (end_b - pmu_name_b)) 16293cdc5c2cSKan Liang return false; 16303cdc5c2cSKan Liang 16313cdc5c2cSKan Liang return (strncmp(pmu_name_a, pmu_name_b, end_a - pmu_name_a) == 0); 16323cdc5c2cSKan Liang } 16333cdc5c2cSKan Liang 16343cdc5c2cSKan Liang static int 16353cdc5c2cSKan Liang parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list, 16363cdc5c2cSKan Liang struct parse_events_state *parse_state) 16373cdc5c2cSKan Liang { 163832dcd021SJiri Olsa struct evsel *evsel, *leader; 16393cdc5c2cSKan Liang uintptr_t *leaders; 16403cdc5c2cSKan Liang bool is_leader = true; 16413cdc5c2cSKan Liang int i, nr_pmu = 0, total_members, ret = 0; 16423cdc5c2cSKan Liang 1643b27c4eceSJiri Olsa leader = list_first_entry(list, struct evsel, core.node); 1644b27c4eceSJiri Olsa evsel = list_last_entry(list, struct evsel, core.node); 16453cdc5c2cSKan Liang total_members = evsel->idx - leader->idx + 1; 16463cdc5c2cSKan Liang 16473cdc5c2cSKan Liang leaders = calloc(total_members, sizeof(uintptr_t)); 16483cdc5c2cSKan Liang if (WARN_ON(!leaders)) 16493cdc5c2cSKan Liang return 0; 16503cdc5c2cSKan Liang 16513cdc5c2cSKan Liang /* 16523cdc5c2cSKan Liang * Going through the whole group and doing sanity check. 16533cdc5c2cSKan Liang * All members must use alias, and be from the same uncore block. 16543cdc5c2cSKan Liang * Also, storing the leader events in an array. 16553cdc5c2cSKan Liang */ 16563cdc5c2cSKan Liang __evlist__for_each_entry(list, evsel) { 16573cdc5c2cSKan Liang 16583cdc5c2cSKan Liang /* Only split the uncore group which members use alias */ 16593cdc5c2cSKan Liang if (!evsel->use_uncore_alias) 16603cdc5c2cSKan Liang goto out; 16613cdc5c2cSKan Liang 16623cdc5c2cSKan Liang /* The events must be from the same uncore block */ 16633cdc5c2cSKan Liang if (!is_same_uncore_block(leader->pmu_name, evsel->pmu_name)) 16643cdc5c2cSKan Liang goto out; 16653cdc5c2cSKan Liang 16663cdc5c2cSKan Liang if (!is_leader) 16673cdc5c2cSKan Liang continue; 16683cdc5c2cSKan Liang /* 16693cdc5c2cSKan Liang * If the event's PMU name starts to repeat, it must be a new 16703cdc5c2cSKan Liang * event. That can be used to distinguish the leader from 16713cdc5c2cSKan Liang * other members, even they have the same event name. 16723cdc5c2cSKan Liang */ 16738510895bSJin Yao if ((leader != evsel) && 16748510895bSJin Yao !strcmp(leader->pmu_name, evsel->pmu_name)) { 16753cdc5c2cSKan Liang is_leader = false; 16763cdc5c2cSKan Liang continue; 16773cdc5c2cSKan Liang } 16783cdc5c2cSKan Liang 16793cdc5c2cSKan Liang /* Store the leader event for each PMU */ 16803cdc5c2cSKan Liang leaders[nr_pmu++] = (uintptr_t) evsel; 16813cdc5c2cSKan Liang } 16823cdc5c2cSKan Liang 16833cdc5c2cSKan Liang /* only one event alias */ 16843cdc5c2cSKan Liang if (nr_pmu == total_members) { 16853cdc5c2cSKan Liang parse_state->nr_groups--; 16863cdc5c2cSKan Liang goto handled; 16873cdc5c2cSKan Liang } 16883cdc5c2cSKan Liang 16893cdc5c2cSKan Liang /* 16903cdc5c2cSKan Liang * An uncore event alias is a joint name which means the same event 16913cdc5c2cSKan Liang * runs on all PMUs of a block. 16923cdc5c2cSKan Liang * Perf doesn't support mixed events from different PMUs in the same 16933cdc5c2cSKan Liang * group. The big group has to be split into multiple small groups 16943cdc5c2cSKan Liang * which only include the events from the same PMU. 16953cdc5c2cSKan Liang * 16963cdc5c2cSKan Liang * Here the uncore event aliases must be from the same uncore block. 16973cdc5c2cSKan Liang * The number of PMUs must be same for each alias. The number of new 16983cdc5c2cSKan Liang * small groups equals to the number of PMUs. 16993cdc5c2cSKan Liang * Setting the leader event for corresponding members in each group. 17003cdc5c2cSKan Liang */ 17013cdc5c2cSKan Liang i = 0; 17023cdc5c2cSKan Liang __evlist__for_each_entry(list, evsel) { 17033cdc5c2cSKan Liang if (i >= nr_pmu) 17043cdc5c2cSKan Liang i = 0; 170532dcd021SJiri Olsa evsel->leader = (struct evsel *) leaders[i++]; 17063cdc5c2cSKan Liang } 17073cdc5c2cSKan Liang 17083cdc5c2cSKan Liang /* The number of members and group name are same for each group */ 17093cdc5c2cSKan Liang for (i = 0; i < nr_pmu; i++) { 171032dcd021SJiri Olsa evsel = (struct evsel *) leaders[i]; 17115643b1a5SJiri Olsa evsel->core.nr_members = total_members / nr_pmu; 17123cdc5c2cSKan Liang evsel->group_name = name ? strdup(name) : NULL; 17133cdc5c2cSKan Liang } 17143cdc5c2cSKan Liang 17153cdc5c2cSKan Liang /* Take the new small groups into account */ 17163cdc5c2cSKan Liang parse_state->nr_groups += nr_pmu - 1; 17173cdc5c2cSKan Liang 17183cdc5c2cSKan Liang handled: 17193cdc5c2cSKan Liang ret = 1; 17203cdc5c2cSKan Liang out: 17213cdc5c2cSKan Liang free(leaders); 17223cdc5c2cSKan Liang return ret; 17233cdc5c2cSKan Liang } 17243cdc5c2cSKan Liang 17253cdc5c2cSKan Liang void parse_events__set_leader(char *name, struct list_head *list, 17263cdc5c2cSKan Liang struct parse_events_state *parse_state) 17276a4bb04cSJiri Olsa { 172832dcd021SJiri Olsa struct evsel *leader; 17296a4bb04cSJiri Olsa 1730854f7363SWang Nan if (list_empty(list)) { 1731854f7363SWang Nan WARN_ONCE(true, "WARNING: failed to set leader: empty list"); 1732854f7363SWang Nan return; 1733854f7363SWang Nan } 1734854f7363SWang Nan 17353cdc5c2cSKan Liang if (parse_events__set_leader_for_uncore_aliase(name, list, parse_state)) 17363cdc5c2cSKan Liang return; 17373cdc5c2cSKan Liang 173863dab225SArnaldo Carvalho de Melo __perf_evlist__set_leader(list); 1739b27c4eceSJiri Olsa leader = list_entry(list->next, struct evsel, core.node); 17406a4bb04cSJiri Olsa leader->group_name = name ? strdup(name) : NULL; 174189efb029SJiri Olsa } 174289efb029SJiri Olsa 1743c5cd8ac0SDavid Ahern /* list_event is assumed to point to malloc'ed memory */ 17445d7be90eSJiri Olsa void parse_events_update_lists(struct list_head *list_event, 17455d7be90eSJiri Olsa struct list_head *list_all) 17465d7be90eSJiri Olsa { 17475d7be90eSJiri Olsa /* 17485d7be90eSJiri Olsa * Called for single event definition. Update the 174989efb029SJiri Olsa * 'all event' list, and reinit the 'single event' 17505d7be90eSJiri Olsa * list, for next event definition. 17515d7be90eSJiri Olsa */ 17525d7be90eSJiri Olsa list_splice_tail(list_event, list_all); 1753b847cbdcSJiri Olsa free(list_event); 17545d7be90eSJiri Olsa } 17555d7be90eSJiri Olsa 1756f5b1135bSJiri Olsa struct event_modifier { 1757f5b1135bSJiri Olsa int eu; 1758f5b1135bSJiri Olsa int ek; 1759f5b1135bSJiri Olsa int eh; 1760f5b1135bSJiri Olsa int eH; 1761f5b1135bSJiri Olsa int eG; 1762a1e12da4SJiri Olsa int eI; 1763f5b1135bSJiri Olsa int precise; 17647f94af7aSJiri Olsa int precise_max; 1765f5b1135bSJiri Olsa int exclude_GH; 17663c176311SJiri Olsa int sample_read; 1767e9a7c414SMichael Ellerman int pinned; 17685a5dfe4bSAndi Kleen int weak; 1769f5b1135bSJiri Olsa }; 177061c45981SPaul Mackerras 1771f5b1135bSJiri Olsa static int get_event_modifier(struct event_modifier *mod, char *str, 177232dcd021SJiri Olsa struct evsel *evsel) 1773f5b1135bSJiri Olsa { 17741fc632ceSJiri Olsa int eu = evsel ? evsel->core.attr.exclude_user : 0; 17751fc632ceSJiri Olsa int ek = evsel ? evsel->core.attr.exclude_kernel : 0; 17761fc632ceSJiri Olsa int eh = evsel ? evsel->core.attr.exclude_hv : 0; 17771fc632ceSJiri Olsa int eH = evsel ? evsel->core.attr.exclude_host : 0; 17781fc632ceSJiri Olsa int eG = evsel ? evsel->core.attr.exclude_guest : 0; 17791fc632ceSJiri Olsa int eI = evsel ? evsel->core.attr.exclude_idle : 0; 17801fc632ceSJiri Olsa int precise = evsel ? evsel->core.attr.precise_ip : 0; 17817f94af7aSJiri Olsa int precise_max = 0; 17823c176311SJiri Olsa int sample_read = 0; 17831fc632ceSJiri Olsa int pinned = evsel ? evsel->core.attr.pinned : 0; 1784f5b1135bSJiri Olsa 1785f5b1135bSJiri Olsa int exclude = eu | ek | eh; 1786f5b1135bSJiri Olsa int exclude_GH = evsel ? evsel->exclude_GH : 0; 17875a5dfe4bSAndi Kleen int weak = 0; 1788f5b1135bSJiri Olsa 1789f5b1135bSJiri Olsa memset(mod, 0, sizeof(*mod)); 1790ceb53fbfSIngo Molnar 179161c45981SPaul Mackerras while (*str) { 1792ab608344SPeter Zijlstra if (*str == 'u') { 1793ab608344SPeter Zijlstra if (!exclude) 1794ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 179561c45981SPaul Mackerras eu = 0; 1796ab608344SPeter Zijlstra } else if (*str == 'k') { 1797ab608344SPeter Zijlstra if (!exclude) 1798ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 179961c45981SPaul Mackerras ek = 0; 1800ab608344SPeter Zijlstra } else if (*str == 'h') { 1801ab608344SPeter Zijlstra if (!exclude) 1802ab608344SPeter Zijlstra exclude = eu = ek = eh = 1; 180361c45981SPaul Mackerras eh = 0; 180499320cc8SJoerg Roedel } else if (*str == 'G') { 180599320cc8SJoerg Roedel if (!exclude_GH) 180699320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 180799320cc8SJoerg Roedel eG = 0; 180899320cc8SJoerg Roedel } else if (*str == 'H') { 180999320cc8SJoerg Roedel if (!exclude_GH) 181099320cc8SJoerg Roedel exclude_GH = eG = eH = 1; 181199320cc8SJoerg Roedel eH = 0; 1812a1e12da4SJiri Olsa } else if (*str == 'I') { 1813a1e12da4SJiri Olsa eI = 1; 1814ab608344SPeter Zijlstra } else if (*str == 'p') { 1815ab608344SPeter Zijlstra precise++; 18161342798cSDavid Ahern /* use of precise requires exclude_guest */ 18171342798cSDavid Ahern if (!exclude_GH) 18181342798cSDavid Ahern eG = 1; 18197f94af7aSJiri Olsa } else if (*str == 'P') { 18207f94af7aSJiri Olsa precise_max = 1; 18213c176311SJiri Olsa } else if (*str == 'S') { 18223c176311SJiri Olsa sample_read = 1; 1823e9a7c414SMichael Ellerman } else if (*str == 'D') { 1824e9a7c414SMichael Ellerman pinned = 1; 18255a5dfe4bSAndi Kleen } else if (*str == 'W') { 18265a5dfe4bSAndi Kleen weak = 1; 1827ab608344SPeter Zijlstra } else 182861c45981SPaul Mackerras break; 1829ab608344SPeter Zijlstra 183061c45981SPaul Mackerras ++str; 183161c45981SPaul Mackerras } 183274d5b588SJaswinder Singh Rajput 183386470930SIngo Molnar /* 183489812fc8SJiri Olsa * precise ip: 183589812fc8SJiri Olsa * 183689812fc8SJiri Olsa * 0 - SAMPLE_IP can have arbitrary skid 183789812fc8SJiri Olsa * 1 - SAMPLE_IP must have constant skid 183889812fc8SJiri Olsa * 2 - SAMPLE_IP requested to have 0 skid 183989812fc8SJiri Olsa * 3 - SAMPLE_IP must have 0 skid 184089812fc8SJiri Olsa * 184189812fc8SJiri Olsa * See also PERF_RECORD_MISC_EXACT_IP 184286470930SIngo Molnar */ 184389812fc8SJiri Olsa if (precise > 3) 184489812fc8SJiri Olsa return -EINVAL; 184586470930SIngo Molnar 1846f5b1135bSJiri Olsa mod->eu = eu; 1847f5b1135bSJiri Olsa mod->ek = ek; 1848f5b1135bSJiri Olsa mod->eh = eh; 1849f5b1135bSJiri Olsa mod->eH = eH; 1850f5b1135bSJiri Olsa mod->eG = eG; 1851a1e12da4SJiri Olsa mod->eI = eI; 1852f5b1135bSJiri Olsa mod->precise = precise; 18537f94af7aSJiri Olsa mod->precise_max = precise_max; 1854f5b1135bSJiri Olsa mod->exclude_GH = exclude_GH; 18553c176311SJiri Olsa mod->sample_read = sample_read; 1856e9a7c414SMichael Ellerman mod->pinned = pinned; 18575a5dfe4bSAndi Kleen mod->weak = weak; 1858e9a7c414SMichael Ellerman 1859f5b1135bSJiri Olsa return 0; 1860f5b1135bSJiri Olsa } 1861f5b1135bSJiri Olsa 1862534123f4SJiri Olsa /* 1863534123f4SJiri Olsa * Basic modifier sanity check to validate it contains only one 1864534123f4SJiri Olsa * instance of any modifier (apart from 'p') present. 1865534123f4SJiri Olsa */ 1866534123f4SJiri Olsa static int check_modifier(char *str) 1867534123f4SJiri Olsa { 1868534123f4SJiri Olsa char *p = str; 1869534123f4SJiri Olsa 1870534123f4SJiri Olsa /* The sizeof includes 0 byte as well. */ 18715a5dfe4bSAndi Kleen if (strlen(str) > (sizeof("ukhGHpppPSDIW") - 1)) 1872534123f4SJiri Olsa return -1; 1873534123f4SJiri Olsa 1874534123f4SJiri Olsa while (*p) { 1875534123f4SJiri Olsa if (*p != 'p' && strchr(p + 1, *p)) 1876534123f4SJiri Olsa return -1; 1877534123f4SJiri Olsa p++; 1878534123f4SJiri Olsa } 1879534123f4SJiri Olsa 1880534123f4SJiri Olsa return 0; 1881534123f4SJiri Olsa } 1882534123f4SJiri Olsa 1883f5b1135bSJiri Olsa int parse_events__modifier_event(struct list_head *list, char *str, bool add) 1884f5b1135bSJiri Olsa { 188532dcd021SJiri Olsa struct evsel *evsel; 1886f5b1135bSJiri Olsa struct event_modifier mod; 1887f5b1135bSJiri Olsa 1888f5b1135bSJiri Olsa if (str == NULL) 1889f5b1135bSJiri Olsa return 0; 1890f5b1135bSJiri Olsa 1891534123f4SJiri Olsa if (check_modifier(str)) 1892534123f4SJiri Olsa return -EINVAL; 1893534123f4SJiri Olsa 1894f5b1135bSJiri Olsa if (!add && get_event_modifier(&mod, str, NULL)) 1895f5b1135bSJiri Olsa return -EINVAL; 1896f5b1135bSJiri Olsa 1897e5cadb93SArnaldo Carvalho de Melo __evlist__for_each_entry(list, evsel) { 1898f5b1135bSJiri Olsa if (add && get_event_modifier(&mod, str, evsel)) 1899f5b1135bSJiri Olsa return -EINVAL; 1900f5b1135bSJiri Olsa 19011fc632ceSJiri Olsa evsel->core.attr.exclude_user = mod.eu; 19021fc632ceSJiri Olsa evsel->core.attr.exclude_kernel = mod.ek; 19031fc632ceSJiri Olsa evsel->core.attr.exclude_hv = mod.eh; 19041fc632ceSJiri Olsa evsel->core.attr.precise_ip = mod.precise; 19051fc632ceSJiri Olsa evsel->core.attr.exclude_host = mod.eH; 19061fc632ceSJiri Olsa evsel->core.attr.exclude_guest = mod.eG; 19071fc632ceSJiri Olsa evsel->core.attr.exclude_idle = mod.eI; 1908f5b1135bSJiri Olsa evsel->exclude_GH = mod.exclude_GH; 19093c176311SJiri Olsa evsel->sample_read = mod.sample_read; 19107f94af7aSJiri Olsa evsel->precise_max = mod.precise_max; 19115a5dfe4bSAndi Kleen evsel->weak_group = mod.weak; 1912e9a7c414SMichael Ellerman 1913c754c382SArnaldo Carvalho de Melo if (evsel__is_group_leader(evsel)) 19141fc632ceSJiri Olsa evsel->core.attr.pinned = mod.pinned; 1915ceb53fbfSIngo Molnar } 191686470930SIngo Molnar 191789812fc8SJiri Olsa return 0; 191886470930SIngo Molnar } 191986470930SIngo Molnar 1920ac2ba9f3SRobert Richter int parse_events_name(struct list_head *list, char *name) 1921ac2ba9f3SRobert Richter { 192232dcd021SJiri Olsa struct evsel *evsel; 1923ac2ba9f3SRobert Richter 1924e5cadb93SArnaldo Carvalho de Melo __evlist__for_each_entry(list, evsel) { 1925ac2ba9f3SRobert Richter if (!evsel->name) 1926ac2ba9f3SRobert Richter evsel->name = strdup(name); 1927ac2ba9f3SRobert Richter } 1928ac2ba9f3SRobert Richter 1929ac2ba9f3SRobert Richter return 0; 1930ac2ba9f3SRobert Richter } 1931ac2ba9f3SRobert Richter 1932dcb4e102SKan Liang static int 1933dcb4e102SKan Liang comp_pmu(const void *p1, const void *p2) 1934dcb4e102SKan Liang { 1935dcb4e102SKan Liang struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1; 1936dcb4e102SKan Liang struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2; 1937dcb4e102SKan Liang 1938e312bcf1SAndi Kleen return strcasecmp(pmu1->symbol, pmu2->symbol); 1939dcb4e102SKan Liang } 1940dcb4e102SKan Liang 1941dcb4e102SKan Liang static void perf_pmu__parse_cleanup(void) 1942dcb4e102SKan Liang { 1943dcb4e102SKan Liang if (perf_pmu_events_list_num > 0) { 1944dcb4e102SKan Liang struct perf_pmu_event_symbol *p; 1945dcb4e102SKan Liang int i; 1946dcb4e102SKan Liang 1947dcb4e102SKan Liang for (i = 0; i < perf_pmu_events_list_num; i++) { 1948dcb4e102SKan Liang p = perf_pmu_events_list + i; 1949360e071bSTaeung Song zfree(&p->symbol); 1950dcb4e102SKan Liang } 1951506fde11STaeung Song zfree(&perf_pmu_events_list); 1952dcb4e102SKan Liang perf_pmu_events_list_num = 0; 1953dcb4e102SKan Liang } 1954dcb4e102SKan Liang } 1955dcb4e102SKan Liang 1956dcb4e102SKan Liang #define SET_SYMBOL(str, stype) \ 1957dcb4e102SKan Liang do { \ 1958dcb4e102SKan Liang p->symbol = str; \ 1959dcb4e102SKan Liang if (!p->symbol) \ 1960dcb4e102SKan Liang goto err; \ 1961dcb4e102SKan Liang p->type = stype; \ 1962dcb4e102SKan Liang } while (0) 1963dcb4e102SKan Liang 1964dcb4e102SKan Liang /* 1965dcb4e102SKan Liang * Read the pmu events list from sysfs 1966dcb4e102SKan Liang * Save it into perf_pmu_events_list 1967dcb4e102SKan Liang */ 1968dcb4e102SKan Liang static void perf_pmu__parse_init(void) 1969dcb4e102SKan Liang { 1970dcb4e102SKan Liang 1971dcb4e102SKan Liang struct perf_pmu *pmu = NULL; 1972dcb4e102SKan Liang struct perf_pmu_alias *alias; 1973dcb4e102SKan Liang int len = 0; 1974dcb4e102SKan Liang 1975231bb2aaSAndi Kleen pmu = NULL; 1976231bb2aaSAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1977dcb4e102SKan Liang list_for_each_entry(alias, &pmu->aliases, list) { 1978dcb4e102SKan Liang if (strchr(alias->name, '-')) 1979dcb4e102SKan Liang len++; 1980dcb4e102SKan Liang len++; 1981dcb4e102SKan Liang } 1982231bb2aaSAndi Kleen } 1983231bb2aaSAndi Kleen 1984231bb2aaSAndi Kleen if (len == 0) { 1985231bb2aaSAndi Kleen perf_pmu_events_list_num = -1; 1986231bb2aaSAndi Kleen return; 1987231bb2aaSAndi Kleen } 1988dcb4e102SKan Liang perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len); 1989dcb4e102SKan Liang if (!perf_pmu_events_list) 1990dcb4e102SKan Liang return; 1991dcb4e102SKan Liang perf_pmu_events_list_num = len; 1992dcb4e102SKan Liang 1993dcb4e102SKan Liang len = 0; 1994231bb2aaSAndi Kleen pmu = NULL; 1995231bb2aaSAndi Kleen while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1996dcb4e102SKan Liang list_for_each_entry(alias, &pmu->aliases, list) { 1997dcb4e102SKan Liang struct perf_pmu_event_symbol *p = perf_pmu_events_list + len; 1998dcb4e102SKan Liang char *tmp = strchr(alias->name, '-'); 1999dcb4e102SKan Liang 2000dcb4e102SKan Liang if (tmp != NULL) { 2001dcb4e102SKan Liang SET_SYMBOL(strndup(alias->name, tmp - alias->name), 2002dcb4e102SKan Liang PMU_EVENT_SYMBOL_PREFIX); 2003dcb4e102SKan Liang p++; 2004dcb4e102SKan Liang SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX); 2005dcb4e102SKan Liang len += 2; 2006dcb4e102SKan Liang } else { 2007dcb4e102SKan Liang SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL); 2008dcb4e102SKan Liang len++; 2009dcb4e102SKan Liang } 2010dcb4e102SKan Liang } 2011231bb2aaSAndi Kleen } 2012dcb4e102SKan Liang qsort(perf_pmu_events_list, len, 2013dcb4e102SKan Liang sizeof(struct perf_pmu_event_symbol), comp_pmu); 2014dcb4e102SKan Liang 2015dcb4e102SKan Liang return; 2016dcb4e102SKan Liang err: 2017dcb4e102SKan Liang perf_pmu__parse_cleanup(); 2018dcb4e102SKan Liang } 2019dcb4e102SKan Liang 2020dcb4e102SKan Liang enum perf_pmu_event_symbol_type 2021dcb4e102SKan Liang perf_pmu__parse_check(const char *name) 2022dcb4e102SKan Liang { 2023dcb4e102SKan Liang struct perf_pmu_event_symbol p, *r; 2024dcb4e102SKan Liang 2025dcb4e102SKan Liang /* scan kernel pmu events from sysfs if needed */ 2026dcb4e102SKan Liang if (perf_pmu_events_list_num == 0) 2027dcb4e102SKan Liang perf_pmu__parse_init(); 2028dcb4e102SKan Liang /* 2029dcb4e102SKan Liang * name "cpu" could be prefix of cpu-cycles or cpu// events. 2030dcb4e102SKan Liang * cpu-cycles has been handled by hardcode. 2031dcb4e102SKan Liang * So it must be cpu// events, not kernel pmu event. 2032dcb4e102SKan Liang */ 2033dcb4e102SKan Liang if ((perf_pmu_events_list_num <= 0) || !strcmp(name, "cpu")) 2034dcb4e102SKan Liang return PMU_EVENT_SYMBOL_ERR; 2035dcb4e102SKan Liang 2036dcb4e102SKan Liang p.symbol = strdup(name); 2037dcb4e102SKan Liang r = bsearch(&p, perf_pmu_events_list, 2038dcb4e102SKan Liang (size_t) perf_pmu_events_list_num, 2039dcb4e102SKan Liang sizeof(struct perf_pmu_event_symbol), comp_pmu); 2040360e071bSTaeung Song zfree(&p.symbol); 2041dcb4e102SKan Liang return r ? r->type : PMU_EVENT_SYMBOL_ERR; 2042dcb4e102SKan Liang } 2043dcb4e102SKan Liang 20441244a327SJiri Olsa static int parse_events__scanner(const char *str, 20451244a327SJiri Olsa struct parse_events_state *parse_state) 2046ac20de6fSZheng Yan { 2047ac20de6fSZheng Yan YY_BUFFER_STATE buffer; 2048ac20de6fSZheng Yan void *scanner; 2049ac20de6fSZheng Yan int ret; 2050ac20de6fSZheng Yan 20511244a327SJiri Olsa ret = parse_events_lex_init_extra(parse_state, &scanner); 2052ac20de6fSZheng Yan if (ret) 2053ac20de6fSZheng Yan return ret; 2054ac20de6fSZheng Yan 2055ac20de6fSZheng Yan buffer = parse_events__scan_string(str, scanner); 2056ac20de6fSZheng Yan 2057ac20de6fSZheng Yan #ifdef PARSER_DEBUG 2058ac20de6fSZheng Yan parse_events_debug = 1; 2059ae762641SJiri Olsa parse_events_set_debug(1, scanner); 2060ac20de6fSZheng Yan #endif 20615d9cdc11SArnaldo Carvalho de Melo ret = parse_events_parse(parse_state, scanner); 2062ac20de6fSZheng Yan 2063ac20de6fSZheng Yan parse_events__flush_buffer(buffer, scanner); 2064ac20de6fSZheng Yan parse_events__delete_buffer(buffer, scanner); 2065ac20de6fSZheng Yan parse_events_lex_destroy(scanner); 2066ac20de6fSZheng Yan return ret; 2067ac20de6fSZheng Yan } 2068ac20de6fSZheng Yan 206990e2b22dSJiri Olsa /* 207090e2b22dSJiri Olsa * parse event config string, return a list of event terms. 207190e2b22dSJiri Olsa */ 207290e2b22dSJiri Olsa int parse_events_terms(struct list_head *terms, const char *str) 207390e2b22dSJiri Olsa { 20745d9cdc11SArnaldo Carvalho de Melo struct parse_events_state parse_state = { 207590e2b22dSJiri Olsa .terms = NULL, 20761244a327SJiri Olsa .stoken = PE_START_TERMS, 207790e2b22dSJiri Olsa }; 207890e2b22dSJiri Olsa int ret; 207990e2b22dSJiri Olsa 20801244a327SJiri Olsa ret = parse_events__scanner(str, &parse_state); 208190e2b22dSJiri Olsa if (!ret) { 20825d9cdc11SArnaldo Carvalho de Melo list_splice(parse_state.terms, terms); 20835d9cdc11SArnaldo Carvalho de Melo zfree(&parse_state.terms); 208490e2b22dSJiri Olsa return 0; 208590e2b22dSJiri Olsa } 208690e2b22dSJiri Olsa 20875d9cdc11SArnaldo Carvalho de Melo parse_events_terms__delete(parse_state.terms); 208890e2b22dSJiri Olsa return ret; 208990e2b22dSJiri Olsa } 209090e2b22dSJiri Olsa 209163503dbaSJiri Olsa int parse_events(struct evlist *evlist, const char *str, 2092b39b8393SJiri Olsa struct parse_events_error *err) 209386470930SIngo Molnar { 20945d9cdc11SArnaldo Carvalho de Melo struct parse_events_state parse_state = { 20955d9cdc11SArnaldo Carvalho de Melo .list = LIST_HEAD_INIT(parse_state.list), 20966484d2f9SJiri Olsa .idx = evlist->core.nr_entries, 2097b39b8393SJiri Olsa .error = err, 20987630b3e2SWang Nan .evlist = evlist, 20991244a327SJiri Olsa .stoken = PE_START_EVENTS, 210046010ab2SJiri Olsa }; 210146010ab2SJiri Olsa int ret; 210286470930SIngo Molnar 21031244a327SJiri Olsa ret = parse_events__scanner(str, &parse_state); 2104dcb4e102SKan Liang perf_pmu__parse_cleanup(); 210515bfd2ccSWang Nan 21068e8714c3SIan Rogers if (!ret && list_empty(&parse_state.list)) { 2107c23080a6SArnaldo Carvalho de Melo WARN_ONCE(true, "WARNING: event parser found nothing\n"); 2108854f7363SWang Nan return -1; 2109854f7363SWang Nan } 2110854f7363SWang Nan 21118e8714c3SIan Rogers /* 21128e8714c3SIan Rogers * Add list to the evlist even with errors to allow callers to clean up. 21138e8714c3SIan Rogers */ 21145d9cdc11SArnaldo Carvalho de Melo perf_evlist__splice_list_tail(evlist, &parse_state.list); 21158e8714c3SIan Rogers 21168e8714c3SIan Rogers if (!ret) { 21178e8714c3SIan Rogers struct evsel *last; 21188e8714c3SIan Rogers 21195d9cdc11SArnaldo Carvalho de Melo evlist->nr_groups += parse_state.nr_groups; 2120515dbe48SJiri Olsa last = evlist__last(evlist); 212115bfd2ccSWang Nan last->cmdline_group_boundary = true; 212215bfd2ccSWang Nan 212386470930SIngo Molnar return 0; 212486470930SIngo Molnar } 212586470930SIngo Molnar 21265d7be90eSJiri Olsa /* 21275d7be90eSJiri Olsa * There are 2 users - builtin-record and builtin-test objects. 2128c12995a5SJiri Olsa * Both call evlist__delete in case of error, so we dont 21295d7be90eSJiri Olsa * need to bother. 21305d7be90eSJiri Olsa */ 213189812fc8SJiri Olsa return ret; 213289812fc8SJiri Olsa } 213389812fc8SJiri Olsa 2134b39b8393SJiri Olsa #define MAX_WIDTH 1000 2135b39b8393SJiri Olsa static int get_term_width(void) 2136b39b8393SJiri Olsa { 2137b39b8393SJiri Olsa struct winsize ws; 2138b39b8393SJiri Olsa 2139b39b8393SJiri Olsa get_term_dimensions(&ws); 2140b39b8393SJiri Olsa return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col; 2141b39b8393SJiri Olsa } 2142b39b8393SJiri Olsa 2143a910e466SIan Rogers static void __parse_events_print_error(int err_idx, const char *err_str, 2144a910e466SIan Rogers const char *err_help, const char *event) 2145b39b8393SJiri Olsa { 2146b39b8393SJiri Olsa const char *str = "invalid or unsupported event: "; 2147b39b8393SJiri Olsa char _buf[MAX_WIDTH]; 2148b39b8393SJiri Olsa char *buf = (char *) event; 2149b39b8393SJiri Olsa int idx = 0; 2150a910e466SIan Rogers if (err_str) { 2151b39b8393SJiri Olsa /* -2 for extra '' in the final fprintf */ 2152b39b8393SJiri Olsa int width = get_term_width() - 2; 2153b39b8393SJiri Olsa int len_event = strlen(event); 2154b39b8393SJiri Olsa int len_str, max_len, cut = 0; 2155b39b8393SJiri Olsa 2156b39b8393SJiri Olsa /* 2157b39b8393SJiri Olsa * Maximum error index indent, we will cut 2158b39b8393SJiri Olsa * the event string if it's bigger. 2159b39b8393SJiri Olsa */ 2160141b2d31SAdrian Hunter int max_err_idx = 13; 2161b39b8393SJiri Olsa 2162b39b8393SJiri Olsa /* 2163b39b8393SJiri Olsa * Let's be specific with the message when 2164b39b8393SJiri Olsa * we have the precise error. 2165b39b8393SJiri Olsa */ 2166b39b8393SJiri Olsa str = "event syntax error: "; 2167b39b8393SJiri Olsa len_str = strlen(str); 2168b39b8393SJiri Olsa max_len = width - len_str; 2169b39b8393SJiri Olsa 2170b39b8393SJiri Olsa buf = _buf; 2171b39b8393SJiri Olsa 2172bd1a0be5SAdam Buchbinder /* We're cutting from the beginning. */ 2173a910e466SIan Rogers if (err_idx > max_err_idx) 2174a910e466SIan Rogers cut = err_idx - max_err_idx; 2175b39b8393SJiri Olsa 2176b39b8393SJiri Olsa strncpy(buf, event + cut, max_len); 2177b39b8393SJiri Olsa 2178b39b8393SJiri Olsa /* Mark cut parts with '..' on both sides. */ 2179b39b8393SJiri Olsa if (cut) 2180b39b8393SJiri Olsa buf[0] = buf[1] = '.'; 2181b39b8393SJiri Olsa 2182b39b8393SJiri Olsa if ((len_event - cut) > max_len) { 2183b39b8393SJiri Olsa buf[max_len - 1] = buf[max_len - 2] = '.'; 2184b39b8393SJiri Olsa buf[max_len] = 0; 2185b39b8393SJiri Olsa } 2186b39b8393SJiri Olsa 2187a910e466SIan Rogers idx = len_str + err_idx - cut; 2188b39b8393SJiri Olsa } 2189b39b8393SJiri Olsa 2190b39b8393SJiri Olsa fprintf(stderr, "%s'%s'\n", str, buf); 2191b39b8393SJiri Olsa if (idx) { 2192a910e466SIan Rogers fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err_str); 2193a910e466SIan Rogers if (err_help) 2194a910e466SIan Rogers fprintf(stderr, "\n%s\n", err_help); 2195a910e466SIan Rogers } 2196a910e466SIan Rogers } 2197a910e466SIan Rogers 2198a910e466SIan Rogers void parse_events_print_error(struct parse_events_error *err, 2199a910e466SIan Rogers const char *event) 2200a910e466SIan Rogers { 2201a910e466SIan Rogers if (!err->num_errors) 2202a910e466SIan Rogers return; 2203a910e466SIan Rogers 2204a910e466SIan Rogers __parse_events_print_error(err->idx, err->str, err->help, event); 2205360e071bSTaeung Song zfree(&err->str); 2206360e071bSTaeung Song zfree(&err->help); 2207a910e466SIan Rogers 2208a910e466SIan Rogers if (err->num_errors > 1) { 2209a910e466SIan Rogers fputs("\nInitial error:\n", stderr); 2210a910e466SIan Rogers __parse_events_print_error(err->first_idx, err->first_str, 2211a910e466SIan Rogers err->first_help, event); 2212a910e466SIan Rogers zfree(&err->first_str); 2213a910e466SIan Rogers zfree(&err->first_help); 2214b39b8393SJiri Olsa } 2215b39b8393SJiri Olsa } 2216b39b8393SJiri Olsa 2217b39b8393SJiri Olsa #undef MAX_WIDTH 2218b39b8393SJiri Olsa 2219f120f9d5SJiri Olsa int parse_events_option(const struct option *opt, const char *str, 22201d037ca1SIrina Tirdea int unset __maybe_unused) 2221f120f9d5SJiri Olsa { 222263503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 2223a910e466SIan Rogers struct parse_events_error err; 2224a910e466SIan Rogers int ret; 2225a910e466SIan Rogers 2226a910e466SIan Rogers bzero(&err, sizeof(err)); 2227a910e466SIan Rogers ret = parse_events(evlist, str, &err); 22289175ce1fSAndi Kleen 2229333b5665SAndi Kleen if (ret) { 2230b39b8393SJiri Olsa parse_events_print_error(&err, str); 2231333b5665SAndi Kleen fprintf(stderr, "Run 'perf list' for a list of valid events\n"); 2232333b5665SAndi Kleen } 2233b39b8393SJiri Olsa 22349175ce1fSAndi Kleen return ret; 2235f120f9d5SJiri Olsa } 2236f120f9d5SJiri Olsa 2237d0abbc3cSArnaldo Carvalho de Melo int parse_events_option_new_evlist(const struct option *opt, const char *str, int unset) 2238d0abbc3cSArnaldo Carvalho de Melo { 2239d0abbc3cSArnaldo Carvalho de Melo struct evlist **evlistp = opt->value; 2240d0abbc3cSArnaldo Carvalho de Melo int ret; 2241d0abbc3cSArnaldo Carvalho de Melo 2242d0abbc3cSArnaldo Carvalho de Melo if (*evlistp == NULL) { 2243d0abbc3cSArnaldo Carvalho de Melo *evlistp = evlist__new(); 2244d0abbc3cSArnaldo Carvalho de Melo 2245d0abbc3cSArnaldo Carvalho de Melo if (*evlistp == NULL) { 2246d0abbc3cSArnaldo Carvalho de Melo fprintf(stderr, "Not enough memory to create evlist\n"); 2247d0abbc3cSArnaldo Carvalho de Melo return -1; 2248d0abbc3cSArnaldo Carvalho de Melo } 2249d0abbc3cSArnaldo Carvalho de Melo } 2250d0abbc3cSArnaldo Carvalho de Melo 2251d0abbc3cSArnaldo Carvalho de Melo ret = parse_events_option(opt, str, unset); 2252d0abbc3cSArnaldo Carvalho de Melo if (ret) { 2253d0abbc3cSArnaldo Carvalho de Melo evlist__delete(*evlistp); 2254d0abbc3cSArnaldo Carvalho de Melo *evlistp = NULL; 2255d0abbc3cSArnaldo Carvalho de Melo } 2256d0abbc3cSArnaldo Carvalho de Melo 2257d0abbc3cSArnaldo Carvalho de Melo return ret; 2258d0abbc3cSArnaldo Carvalho de Melo } 2259d0abbc3cSArnaldo Carvalho de Melo 22604ba1faa1SWang Nan static int 226163503dbaSJiri Olsa foreach_evsel_in_last_glob(struct evlist *evlist, 226232dcd021SJiri Olsa int (*func)(struct evsel *evsel, 22634ba1faa1SWang Nan const void *arg), 22644ba1faa1SWang Nan const void *arg) 2265c171b552SLi Zefan { 226632dcd021SJiri Olsa struct evsel *last = NULL; 22674ba1faa1SWang Nan int err; 2268c171b552SLi Zefan 2269854f7363SWang Nan /* 2270854f7363SWang Nan * Don't return when list_empty, give func a chance to report 2271854f7363SWang Nan * error when it found last == NULL. 2272854f7363SWang Nan * 2273854f7363SWang Nan * So no need to WARN here, let *func do this. 2274854f7363SWang Nan */ 22756484d2f9SJiri Olsa if (evlist->core.nr_entries > 0) 2276515dbe48SJiri Olsa last = evlist__last(evlist); 227769aad6f1SArnaldo Carvalho de Melo 227815bfd2ccSWang Nan do { 22794ba1faa1SWang Nan err = (*func)(last, arg); 22804ba1faa1SWang Nan if (err) 2281c171b552SLi Zefan return -1; 22824ba1faa1SWang Nan if (!last) 22834ba1faa1SWang Nan return 0; 2284c171b552SLi Zefan 2285ce9036a6SJiri Olsa if (last->core.node.prev == &evlist->core.entries) 228615bfd2ccSWang Nan return 0; 2287b27c4eceSJiri Olsa last = list_entry(last->core.node.prev, struct evsel, core.node); 228815bfd2ccSWang Nan } while (!last->cmdline_group_boundary); 228915bfd2ccSWang Nan 2290c171b552SLi Zefan return 0; 2291c171b552SLi Zefan } 2292c171b552SLi Zefan 229332dcd021SJiri Olsa static int set_filter(struct evsel *evsel, const void *arg) 22944ba1faa1SWang Nan { 22954ba1faa1SWang Nan const char *str = arg; 22961e857484SMathieu Poirier bool found = false; 22971e857484SMathieu Poirier int nr_addr_filters = 0; 22981e857484SMathieu Poirier struct perf_pmu *pmu = NULL; 22994ba1faa1SWang Nan 230049836f78SJack Henschel if (evsel == NULL) { 230149836f78SJack Henschel fprintf(stderr, 230249836f78SJack Henschel "--filter option should follow a -e tracepoint or HW tracer option\n"); 230349836f78SJack Henschel return -1; 230449836f78SJack Henschel } 23054ba1faa1SWang Nan 23061fc632ceSJiri Olsa if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { 2307ad681adfSArnaldo Carvalho de Melo if (evsel__append_tp_filter(evsel, str) < 0) { 23084ba1faa1SWang Nan fprintf(stderr, 23094ba1faa1SWang Nan "not enough memory to hold filter string\n"); 23104ba1faa1SWang Nan return -1; 23114ba1faa1SWang Nan } 23124ba1faa1SWang Nan 23134ba1faa1SWang Nan return 0; 23144ba1faa1SWang Nan } 23154ba1faa1SWang Nan 23161e857484SMathieu Poirier while ((pmu = perf_pmu__scan(pmu)) != NULL) 23171fc632ceSJiri Olsa if (pmu->type == evsel->core.attr.type) { 23181e857484SMathieu Poirier found = true; 23191e857484SMathieu Poirier break; 23201e857484SMathieu Poirier } 23211e857484SMathieu Poirier 23221e857484SMathieu Poirier if (found) 23231e857484SMathieu Poirier perf_pmu__scan_file(pmu, "nr_addr_filters", 23241e857484SMathieu Poirier "%d", &nr_addr_filters); 23251e857484SMathieu Poirier 232649836f78SJack Henschel if (!nr_addr_filters) { 232749836f78SJack Henschel fprintf(stderr, 232849836f78SJack Henschel "This CPU does not support address filtering\n"); 232949836f78SJack Henschel return -1; 233049836f78SJack Henschel } 23311e857484SMathieu Poirier 2332ad681adfSArnaldo Carvalho de Melo if (evsel__append_addr_filter(evsel, str) < 0) { 23331e857484SMathieu Poirier fprintf(stderr, 23341e857484SMathieu Poirier "not enough memory to hold filter string\n"); 23351e857484SMathieu Poirier return -1; 23361e857484SMathieu Poirier } 23371e857484SMathieu Poirier 23381e857484SMathieu Poirier return 0; 23391e857484SMathieu Poirier } 23401e857484SMathieu Poirier 23414ba1faa1SWang Nan int parse_filter(const struct option *opt, const char *str, 23424ba1faa1SWang Nan int unset __maybe_unused) 23434ba1faa1SWang Nan { 234463503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 23454ba1faa1SWang Nan 23464ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, set_filter, 23474ba1faa1SWang Nan (const void *)str); 23484ba1faa1SWang Nan } 23494ba1faa1SWang Nan 235032dcd021SJiri Olsa static int add_exclude_perf_filter(struct evsel *evsel, 23514ba1faa1SWang Nan const void *arg __maybe_unused) 23524ba1faa1SWang Nan { 23534ba1faa1SWang Nan char new_filter[64]; 23544ba1faa1SWang Nan 23551fc632ceSJiri Olsa if (evsel == NULL || evsel->core.attr.type != PERF_TYPE_TRACEPOINT) { 23564ba1faa1SWang Nan fprintf(stderr, 23574ba1faa1SWang Nan "--exclude-perf option should follow a -e tracepoint option\n"); 23584ba1faa1SWang Nan return -1; 23594ba1faa1SWang Nan } 23604ba1faa1SWang Nan 23614ba1faa1SWang Nan snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid()); 23624ba1faa1SWang Nan 2363ad681adfSArnaldo Carvalho de Melo if (evsel__append_tp_filter(evsel, new_filter) < 0) { 23644ba1faa1SWang Nan fprintf(stderr, 23654ba1faa1SWang Nan "not enough memory to hold filter string\n"); 23664ba1faa1SWang Nan return -1; 23674ba1faa1SWang Nan } 23684ba1faa1SWang Nan 23694ba1faa1SWang Nan return 0; 23704ba1faa1SWang Nan } 23714ba1faa1SWang Nan 23724ba1faa1SWang Nan int exclude_perf(const struct option *opt, 23734ba1faa1SWang Nan const char *arg __maybe_unused, 23744ba1faa1SWang Nan int unset __maybe_unused) 23754ba1faa1SWang Nan { 237663503dbaSJiri Olsa struct evlist *evlist = *(struct evlist **)opt->value; 23774ba1faa1SWang Nan 23784ba1faa1SWang Nan return foreach_evsel_in_last_glob(evlist, add_exclude_perf_filter, 23794ba1faa1SWang Nan NULL); 23804ba1faa1SWang Nan } 23814ba1faa1SWang Nan 238286470930SIngo Molnar static const char * const event_type_descriptors[] = { 238386470930SIngo Molnar "Hardware event", 238486470930SIngo Molnar "Software event", 238586470930SIngo Molnar "Tracepoint event", 238686470930SIngo Molnar "Hardware cache event", 238741bdcb23SLiming Wang "Raw hardware event descriptor", 238841bdcb23SLiming Wang "Hardware breakpoint", 238986470930SIngo Molnar }; 239086470930SIngo Molnar 2391ab0e4800SYunlong Song static int cmp_string(const void *a, const void *b) 2392ab0e4800SYunlong Song { 2393ab0e4800SYunlong Song const char * const *as = a; 2394ab0e4800SYunlong Song const char * const *bs = b; 2395ab0e4800SYunlong Song 2396ab0e4800SYunlong Song return strcmp(*as, *bs); 2397ab0e4800SYunlong Song } 2398ab0e4800SYunlong Song 239986470930SIngo Molnar /* 2400f6bdafefSJason Baron * Print the events from <debugfs_mount_point>/tracing/events 2401f6bdafefSJason Baron */ 2402f6bdafefSJason Baron 2403a3277d2dSFrederic Weisbecker void print_tracepoint_events(const char *subsys_glob, const char *event_glob, 2404a3277d2dSFrederic Weisbecker bool name_only) 2405f6bdafefSJason Baron { 2406f6bdafefSJason Baron DIR *sys_dir, *evt_dir; 240722a9f41bSArnaldo Carvalho de Melo struct dirent *sys_dirent, *evt_dirent; 2408f6bdafefSJason Baron char evt_path[MAXPATHLEN]; 240925a7d914SArnaldo Carvalho de Melo char *dir_path; 2410ab0e4800SYunlong Song char **evt_list = NULL; 2411ab0e4800SYunlong Song unsigned int evt_i = 0, evt_num = 0; 2412ab0e4800SYunlong Song bool evt_num_known = false; 2413f6bdafefSJason Baron 2414ab0e4800SYunlong Song restart: 24157014e0e3SArnaldo Carvalho de Melo sys_dir = tracing_events__opendir(); 2416f6bdafefSJason Baron if (!sys_dir) 2417725b1368SEric Dumazet return; 2418f6bdafefSJason Baron 2419ab0e4800SYunlong Song if (evt_num_known) { 2420ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 2421ab0e4800SYunlong Song if (!evt_list) 2422ab0e4800SYunlong Song goto out_close_sys_dir; 2423ab0e4800SYunlong Song } 2424ab0e4800SYunlong Song 242522a9f41bSArnaldo Carvalho de Melo for_each_subsystem(sys_dir, sys_dirent) { 2426668b8788SArnaldo Carvalho de Melo if (subsys_glob != NULL && 242722a9f41bSArnaldo Carvalho de Melo !strglobmatch(sys_dirent->d_name, subsys_glob)) 2428668b8788SArnaldo Carvalho de Melo continue; 2429725b1368SEric Dumazet 243025a7d914SArnaldo Carvalho de Melo dir_path = get_events_file(sys_dirent->d_name); 243125a7d914SArnaldo Carvalho de Melo if (!dir_path) 243225a7d914SArnaldo Carvalho de Melo continue; 2433725b1368SEric Dumazet evt_dir = opendir(dir_path); 2434725b1368SEric Dumazet if (!evt_dir) 243525a7d914SArnaldo Carvalho de Melo goto next; 2436725b1368SEric Dumazet 2437c02cab22SArnaldo Carvalho de Melo for_each_event(dir_path, evt_dir, evt_dirent) { 2438668b8788SArnaldo Carvalho de Melo if (event_glob != NULL && 243922a9f41bSArnaldo Carvalho de Melo !strglobmatch(evt_dirent->d_name, event_glob)) 2440668b8788SArnaldo Carvalho de Melo continue; 2441668b8788SArnaldo Carvalho de Melo 2442ab0e4800SYunlong Song if (!evt_num_known) { 2443ab0e4800SYunlong Song evt_num++; 2444a3277d2dSFrederic Weisbecker continue; 2445a3277d2dSFrederic Weisbecker } 2446a3277d2dSFrederic Weisbecker 2447f6bdafefSJason Baron snprintf(evt_path, MAXPATHLEN, "%s:%s", 244822a9f41bSArnaldo Carvalho de Melo sys_dirent->d_name, evt_dirent->d_name); 2449ab0e4800SYunlong Song 2450ab0e4800SYunlong Song evt_list[evt_i] = strdup(evt_path); 245125a7d914SArnaldo Carvalho de Melo if (evt_list[evt_i] == NULL) { 245225a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 2453ab0e4800SYunlong Song goto out_close_evt_dir; 245425a7d914SArnaldo Carvalho de Melo } 2455ab0e4800SYunlong Song evt_i++; 2456f6bdafefSJason Baron } 2457f6bdafefSJason Baron closedir(evt_dir); 245825a7d914SArnaldo Carvalho de Melo next: 245925a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 2460f6bdafefSJason Baron } 2461f6bdafefSJason Baron closedir(sys_dir); 2462ab0e4800SYunlong Song 2463ab0e4800SYunlong Song if (!evt_num_known) { 2464ab0e4800SYunlong Song evt_num_known = true; 2465ab0e4800SYunlong Song goto restart; 2466ab0e4800SYunlong Song } 2467ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 2468ab0e4800SYunlong Song evt_i = 0; 2469ab0e4800SYunlong Song while (evt_i < evt_num) { 2470ab0e4800SYunlong Song if (name_only) { 2471ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 2472ab0e4800SYunlong Song continue; 2473ab0e4800SYunlong Song } 2474ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], 2475ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_TRACEPOINT]); 2476ab0e4800SYunlong Song } 2477dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 2478ab0e4800SYunlong Song printf("\n"); 2479ab0e4800SYunlong Song 2480ab0e4800SYunlong Song out_free: 2481ab0e4800SYunlong Song evt_num = evt_i; 2482ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 2483ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 2484ab0e4800SYunlong Song zfree(&evt_list); 2485ab0e4800SYunlong Song return; 2486ab0e4800SYunlong Song 2487ab0e4800SYunlong Song out_close_evt_dir: 2488ab0e4800SYunlong Song closedir(evt_dir); 2489ab0e4800SYunlong Song out_close_sys_dir: 2490ab0e4800SYunlong Song closedir(sys_dir); 2491ab0e4800SYunlong Song 2492ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", 2493ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_TRACEPOINT]); 2494ab0e4800SYunlong Song if (evt_list) 2495ab0e4800SYunlong Song goto out_free; 2496f6bdafefSJason Baron } 2497f6bdafefSJason Baron 2498f6bdafefSJason Baron /* 249920c457b8SThomas Renninger * Check whether event is in <debugfs_mount_point>/tracing/events 250020c457b8SThomas Renninger */ 250120c457b8SThomas Renninger 250220c457b8SThomas Renninger int is_valid_tracepoint(const char *event_string) 250320c457b8SThomas Renninger { 250420c457b8SThomas Renninger DIR *sys_dir, *evt_dir; 250522a9f41bSArnaldo Carvalho de Melo struct dirent *sys_dirent, *evt_dirent; 250620c457b8SThomas Renninger char evt_path[MAXPATHLEN]; 250725a7d914SArnaldo Carvalho de Melo char *dir_path; 250820c457b8SThomas Renninger 25097014e0e3SArnaldo Carvalho de Melo sys_dir = tracing_events__opendir(); 251020c457b8SThomas Renninger if (!sys_dir) 251120c457b8SThomas Renninger return 0; 251220c457b8SThomas Renninger 251322a9f41bSArnaldo Carvalho de Melo for_each_subsystem(sys_dir, sys_dirent) { 251425a7d914SArnaldo Carvalho de Melo dir_path = get_events_file(sys_dirent->d_name); 251525a7d914SArnaldo Carvalho de Melo if (!dir_path) 251625a7d914SArnaldo Carvalho de Melo continue; 251720c457b8SThomas Renninger evt_dir = opendir(dir_path); 251820c457b8SThomas Renninger if (!evt_dir) 251925a7d914SArnaldo Carvalho de Melo goto next; 252020c457b8SThomas Renninger 2521c02cab22SArnaldo Carvalho de Melo for_each_event(dir_path, evt_dir, evt_dirent) { 252220c457b8SThomas Renninger snprintf(evt_path, MAXPATHLEN, "%s:%s", 252322a9f41bSArnaldo Carvalho de Melo sys_dirent->d_name, evt_dirent->d_name); 252420c457b8SThomas Renninger if (!strcmp(evt_path, event_string)) { 252520c457b8SThomas Renninger closedir(evt_dir); 252620c457b8SThomas Renninger closedir(sys_dir); 252720c457b8SThomas Renninger return 1; 252820c457b8SThomas Renninger } 252920c457b8SThomas Renninger } 253020c457b8SThomas Renninger closedir(evt_dir); 253125a7d914SArnaldo Carvalho de Melo next: 253225a7d914SArnaldo Carvalho de Melo put_events_file(dir_path); 253320c457b8SThomas Renninger } 253420c457b8SThomas Renninger closedir(sys_dir); 253520c457b8SThomas Renninger return 0; 253620c457b8SThomas Renninger } 253720c457b8SThomas Renninger 2538b41f1cecSNamhyung Kim static bool is_event_supported(u8 type, unsigned config) 2539b41f1cecSNamhyung Kim { 2540b41f1cecSNamhyung Kim bool ret = true; 254188fee52eSVince Weaver int open_return; 254232dcd021SJiri Olsa struct evsel *evsel; 2543b41f1cecSNamhyung Kim struct perf_event_attr attr = { 2544b41f1cecSNamhyung Kim .type = type, 2545b41f1cecSNamhyung Kim .config = config, 2546b41f1cecSNamhyung Kim .disabled = 1, 2547b41f1cecSNamhyung Kim }; 25489749b90eSJiri Olsa struct perf_thread_map *tmap = thread_map__new_by_tid(0); 254989896051SArnaldo Carvalho de Melo 255089896051SArnaldo Carvalho de Melo if (tmap == NULL) 255189896051SArnaldo Carvalho de Melo return false; 2552b41f1cecSNamhyung Kim 2553365c3ae7SJiri Olsa evsel = evsel__new(&attr); 2554b41f1cecSNamhyung Kim if (evsel) { 25555972d1e0SJiri Olsa open_return = evsel__open(evsel, NULL, tmap); 255688fee52eSVince Weaver ret = open_return >= 0; 255788fee52eSVince Weaver 255888fee52eSVince Weaver if (open_return == -EACCES) { 255988fee52eSVince Weaver /* 256088fee52eSVince Weaver * This happens if the paranoid value 256188fee52eSVince Weaver * /proc/sys/kernel/perf_event_paranoid is set to 2 256288fee52eSVince Weaver * Re-run with exclude_kernel set; we don't do that 256388fee52eSVince Weaver * by default as some ARM machines do not support it. 256488fee52eSVince Weaver * 256588fee52eSVince Weaver */ 25661fc632ceSJiri Olsa evsel->core.attr.exclude_kernel = 1; 25675972d1e0SJiri Olsa ret = evsel__open(evsel, NULL, tmap) >= 0; 256888fee52eSVince Weaver } 25695eb2dd2aSJiri Olsa evsel__delete(evsel); 2570b41f1cecSNamhyung Kim } 2571b41f1cecSNamhyung Kim 25727836e52eSJiri Olsa perf_thread_map__put(tmap); 2573b41f1cecSNamhyung Kim return ret; 2574b41f1cecSNamhyung Kim } 2575b41f1cecSNamhyung Kim 257640218daeSMasami Hiramatsu void print_sdt_events(const char *subsys_glob, const char *event_glob, 257740218daeSMasami Hiramatsu bool name_only) 257840218daeSMasami Hiramatsu { 257940218daeSMasami Hiramatsu struct probe_cache *pcache; 258040218daeSMasami Hiramatsu struct probe_cache_entry *ent; 258140218daeSMasami Hiramatsu struct strlist *bidlist, *sdtlist; 258240218daeSMasami Hiramatsu struct strlist_config cfg = {.dont_dupstr = true}; 258340218daeSMasami Hiramatsu struct str_node *nd, *nd2; 258440218daeSMasami Hiramatsu char *buf, *path, *ptr = NULL; 258540218daeSMasami Hiramatsu bool show_detail = false; 258640218daeSMasami Hiramatsu int ret; 258740218daeSMasami Hiramatsu 258840218daeSMasami Hiramatsu sdtlist = strlist__new(NULL, &cfg); 258940218daeSMasami Hiramatsu if (!sdtlist) { 259040218daeSMasami Hiramatsu pr_debug("Failed to allocate new strlist for SDT\n"); 259140218daeSMasami Hiramatsu return; 259240218daeSMasami Hiramatsu } 259340218daeSMasami Hiramatsu bidlist = build_id_cache__list_all(true); 259440218daeSMasami Hiramatsu if (!bidlist) { 259540218daeSMasami Hiramatsu pr_debug("Failed to get buildids: %d\n", errno); 259640218daeSMasami Hiramatsu return; 259740218daeSMasami Hiramatsu } 259840218daeSMasami Hiramatsu strlist__for_each_entry(nd, bidlist) { 2599f045b8c4SKrister Johansen pcache = probe_cache__new(nd->s, NULL); 260040218daeSMasami Hiramatsu if (!pcache) 260140218daeSMasami Hiramatsu continue; 260240218daeSMasami Hiramatsu list_for_each_entry(ent, &pcache->entries, node) { 260340218daeSMasami Hiramatsu if (!ent->sdt) 260440218daeSMasami Hiramatsu continue; 260540218daeSMasami Hiramatsu if (subsys_glob && 260640218daeSMasami Hiramatsu !strglobmatch(ent->pev.group, subsys_glob)) 260740218daeSMasami Hiramatsu continue; 260840218daeSMasami Hiramatsu if (event_glob && 260940218daeSMasami Hiramatsu !strglobmatch(ent->pev.event, event_glob)) 261040218daeSMasami Hiramatsu continue; 261140218daeSMasami Hiramatsu ret = asprintf(&buf, "%s:%s@%s", ent->pev.group, 261240218daeSMasami Hiramatsu ent->pev.event, nd->s); 261340218daeSMasami Hiramatsu if (ret > 0) 261440218daeSMasami Hiramatsu strlist__add(sdtlist, buf); 261540218daeSMasami Hiramatsu } 261640218daeSMasami Hiramatsu probe_cache__delete(pcache); 261740218daeSMasami Hiramatsu } 261840218daeSMasami Hiramatsu strlist__delete(bidlist); 261940218daeSMasami Hiramatsu 262040218daeSMasami Hiramatsu strlist__for_each_entry(nd, sdtlist) { 262140218daeSMasami Hiramatsu buf = strchr(nd->s, '@'); 262240218daeSMasami Hiramatsu if (buf) 262340218daeSMasami Hiramatsu *(buf++) = '\0'; 262440218daeSMasami Hiramatsu if (name_only) { 262540218daeSMasami Hiramatsu printf("%s ", nd->s); 262640218daeSMasami Hiramatsu continue; 262740218daeSMasami Hiramatsu } 262840218daeSMasami Hiramatsu nd2 = strlist__next(nd); 262940218daeSMasami Hiramatsu if (nd2) { 263040218daeSMasami Hiramatsu ptr = strchr(nd2->s, '@'); 263140218daeSMasami Hiramatsu if (ptr) 263240218daeSMasami Hiramatsu *ptr = '\0'; 263340218daeSMasami Hiramatsu if (strcmp(nd->s, nd2->s) == 0) 263440218daeSMasami Hiramatsu show_detail = true; 263540218daeSMasami Hiramatsu } 263640218daeSMasami Hiramatsu if (show_detail) { 263740218daeSMasami Hiramatsu path = build_id_cache__origname(buf); 263840218daeSMasami Hiramatsu ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf); 263940218daeSMasami Hiramatsu if (ret > 0) { 264040218daeSMasami Hiramatsu printf(" %-50s [%s]\n", buf, "SDT event"); 264140218daeSMasami Hiramatsu free(buf); 264240218daeSMasami Hiramatsu } 26438bde8516SChangbin Du free(path); 264440218daeSMasami Hiramatsu } else 264540218daeSMasami Hiramatsu printf(" %-50s [%s]\n", nd->s, "SDT event"); 264640218daeSMasami Hiramatsu if (nd2) { 264740218daeSMasami Hiramatsu if (strcmp(nd->s, nd2->s) != 0) 264840218daeSMasami Hiramatsu show_detail = false; 264940218daeSMasami Hiramatsu if (ptr) 265040218daeSMasami Hiramatsu *ptr = '@'; 265140218daeSMasami Hiramatsu } 265240218daeSMasami Hiramatsu } 265340218daeSMasami Hiramatsu strlist__delete(sdtlist); 265440218daeSMasami Hiramatsu } 265540218daeSMasami Hiramatsu 2656a3277d2dSFrederic Weisbecker int print_hwcache_events(const char *event_glob, bool name_only) 2657668b8788SArnaldo Carvalho de Melo { 2658ab0e4800SYunlong Song unsigned int type, op, i, evt_i = 0, evt_num = 0; 26590b668bc9SArnaldo Carvalho de Melo char name[64]; 2660ab0e4800SYunlong Song char **evt_list = NULL; 2661ab0e4800SYunlong Song bool evt_num_known = false; 2662ab0e4800SYunlong Song 2663ab0e4800SYunlong Song restart: 2664ab0e4800SYunlong Song if (evt_num_known) { 2665ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 2666ab0e4800SYunlong Song if (!evt_list) 2667ab0e4800SYunlong Song goto out_enomem; 2668ab0e4800SYunlong Song } 2669668b8788SArnaldo Carvalho de Melo 2670668b8788SArnaldo Carvalho de Melo for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 2671668b8788SArnaldo Carvalho de Melo for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 2672668b8788SArnaldo Carvalho de Melo /* skip invalid cache type */ 2673c754c382SArnaldo Carvalho de Melo if (!evsel__is_cache_op_valid(type, op)) 2674668b8788SArnaldo Carvalho de Melo continue; 2675668b8788SArnaldo Carvalho de Melo 2676668b8788SArnaldo Carvalho de Melo for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) { 26778ab2e96dSArnaldo Carvalho de Melo __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name)); 2678947b4ad1SIngo Molnar if (event_glob != NULL && !strglobmatch(name, event_glob)) 2679668b8788SArnaldo Carvalho de Melo continue; 2680668b8788SArnaldo Carvalho de Melo 2681b41f1cecSNamhyung Kim if (!is_event_supported(PERF_TYPE_HW_CACHE, 2682b41f1cecSNamhyung Kim type | (op << 8) | (i << 16))) 2683b41f1cecSNamhyung Kim continue; 2684b41f1cecSNamhyung Kim 2685ab0e4800SYunlong Song if (!evt_num_known) { 2686ab0e4800SYunlong Song evt_num++; 2687ab0e4800SYunlong Song continue; 2688ab0e4800SYunlong Song } 2689ab0e4800SYunlong Song 2690ab0e4800SYunlong Song evt_list[evt_i] = strdup(name); 2691ab0e4800SYunlong Song if (evt_list[evt_i] == NULL) 2692ab0e4800SYunlong Song goto out_enomem; 2693ab0e4800SYunlong Song evt_i++; 2694668b8788SArnaldo Carvalho de Melo } 2695668b8788SArnaldo Carvalho de Melo } 2696668b8788SArnaldo Carvalho de Melo } 2697668b8788SArnaldo Carvalho de Melo 2698ab0e4800SYunlong Song if (!evt_num_known) { 2699ab0e4800SYunlong Song evt_num_known = true; 2700ab0e4800SYunlong Song goto restart; 2701ab0e4800SYunlong Song } 2702ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 2703ab0e4800SYunlong Song evt_i = 0; 2704ab0e4800SYunlong Song while (evt_i < evt_num) { 2705ab0e4800SYunlong Song if (name_only) { 2706ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 2707ab0e4800SYunlong Song continue; 2708ab0e4800SYunlong Song } 2709ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], 2710ab0e4800SYunlong Song event_type_descriptors[PERF_TYPE_HW_CACHE]); 2711ab0e4800SYunlong Song } 2712dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 2713dc098b35SAndi Kleen printf("\n"); 2714ab0e4800SYunlong Song 2715ab0e4800SYunlong Song out_free: 2716ab0e4800SYunlong Song evt_num = evt_i; 2717ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 2718ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 2719ab0e4800SYunlong Song zfree(&evt_list); 2720ab0e4800SYunlong Song return evt_num; 2721ab0e4800SYunlong Song 2722ab0e4800SYunlong Song out_enomem: 2723ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]); 2724ab0e4800SYunlong Song if (evt_list) 2725ab0e4800SYunlong Song goto out_free; 2726ab0e4800SYunlong Song return evt_num; 2727668b8788SArnaldo Carvalho de Melo } 2728668b8788SArnaldo Carvalho de Melo 27295e0861baSAndi Kleen static void print_tool_event(const char *name, const char *event_glob, 27305e0861baSAndi Kleen bool name_only) 27315e0861baSAndi Kleen { 27325e0861baSAndi Kleen if (event_glob && !strglobmatch(name, event_glob)) 27335e0861baSAndi Kleen return; 27345e0861baSAndi Kleen if (name_only) 27355e0861baSAndi Kleen printf("%s ", name); 27365e0861baSAndi Kleen else 27375e0861baSAndi Kleen printf(" %-50s [%s]\n", name, "Tool event"); 27385e0861baSAndi Kleen 27395e0861baSAndi Kleen } 27405e0861baSAndi Kleen 27415e0861baSAndi Kleen void print_tool_events(const char *event_glob, bool name_only) 27425e0861baSAndi Kleen { 27435e0861baSAndi Kleen print_tool_event("duration_time", event_glob, name_only); 27445e0861baSAndi Kleen if (pager_in_use()) 27455e0861baSAndi Kleen printf("\n"); 27465e0861baSAndi Kleen } 27475e0861baSAndi Kleen 2748705750f2SYunlong Song void print_symbol_events(const char *event_glob, unsigned type, 2749a3277d2dSFrederic Weisbecker struct event_symbol *syms, unsigned max, 2750a3277d2dSFrederic Weisbecker bool name_only) 275186470930SIngo Molnar { 2752ab0e4800SYunlong Song unsigned int i, evt_i = 0, evt_num = 0; 2753947b4ad1SIngo Molnar char name[MAX_NAME_LEN]; 2754ab0e4800SYunlong Song char **evt_list = NULL; 2755ab0e4800SYunlong Song bool evt_num_known = false; 2756ab0e4800SYunlong Song 2757ab0e4800SYunlong Song restart: 2758ab0e4800SYunlong Song if (evt_num_known) { 2759ab0e4800SYunlong Song evt_list = zalloc(sizeof(char *) * evt_num); 2760ab0e4800SYunlong Song if (!evt_list) 2761ab0e4800SYunlong Song goto out_enomem; 2762ab0e4800SYunlong Song syms -= max; 2763ab0e4800SYunlong Song } 276486470930SIngo Molnar 27651dc12760SJiri Olsa for (i = 0; i < max; i++, syms++) { 2766668b8788SArnaldo Carvalho de Melo 2767e37df6c7SArnaldo Carvalho de Melo if (event_glob != NULL && syms->symbol != NULL && 2768668b8788SArnaldo Carvalho de Melo !(strglobmatch(syms->symbol, event_glob) || 2769668b8788SArnaldo Carvalho de Melo (syms->alias && strglobmatch(syms->alias, event_glob)))) 2770668b8788SArnaldo Carvalho de Melo continue; 277186470930SIngo Molnar 2772b41f1cecSNamhyung Kim if (!is_event_supported(type, i)) 2773b41f1cecSNamhyung Kim continue; 2774b41f1cecSNamhyung Kim 2775ab0e4800SYunlong Song if (!evt_num_known) { 2776ab0e4800SYunlong Song evt_num++; 2777a3277d2dSFrederic Weisbecker continue; 2778a3277d2dSFrederic Weisbecker } 2779a3277d2dSFrederic Weisbecker 2780ab0e4800SYunlong Song if (!name_only && strlen(syms->alias)) 2781947b4ad1SIngo Molnar snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 278274d5b588SJaswinder Singh Rajput else 2783bd8d57fbSArnaldo Carvalho de Melo strlcpy(name, syms->symbol, MAX_NAME_LEN); 278486470930SIngo Molnar 2785ab0e4800SYunlong Song evt_list[evt_i] = strdup(name); 2786ab0e4800SYunlong Song if (evt_list[evt_i] == NULL) 2787ab0e4800SYunlong Song goto out_enomem; 2788ab0e4800SYunlong Song evt_i++; 278986470930SIngo Molnar } 279086470930SIngo Molnar 2791ab0e4800SYunlong Song if (!evt_num_known) { 2792ab0e4800SYunlong Song evt_num_known = true; 2793ab0e4800SYunlong Song goto restart; 2794ab0e4800SYunlong Song } 2795ab0e4800SYunlong Song qsort(evt_list, evt_num, sizeof(char *), cmp_string); 2796ab0e4800SYunlong Song evt_i = 0; 2797ab0e4800SYunlong Song while (evt_i < evt_num) { 2798ab0e4800SYunlong Song if (name_only) { 2799ab0e4800SYunlong Song printf("%s ", evt_list[evt_i++]); 2800ab0e4800SYunlong Song continue; 2801ab0e4800SYunlong Song } 2802ab0e4800SYunlong Song printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]); 2803ab0e4800SYunlong Song } 2804dfc431cbSArnaldo Carvalho de Melo if (evt_num && pager_in_use()) 2805689d3018SMarti Raudsepp printf("\n"); 2806ab0e4800SYunlong Song 2807ab0e4800SYunlong Song out_free: 2808ab0e4800SYunlong Song evt_num = evt_i; 2809ab0e4800SYunlong Song for (evt_i = 0; evt_i < evt_num; evt_i++) 2810ab0e4800SYunlong Song zfree(&evt_list[evt_i]); 2811ab0e4800SYunlong Song zfree(&evt_list); 2812ab0e4800SYunlong Song return; 2813ab0e4800SYunlong Song 2814ab0e4800SYunlong Song out_enomem: 2815ab0e4800SYunlong Song printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]); 2816ab0e4800SYunlong Song if (evt_list) 2817ab0e4800SYunlong Song goto out_free; 2818668b8788SArnaldo Carvalho de Melo } 28191dc12760SJiri Olsa 28201dc12760SJiri Olsa /* 28211dc12760SJiri Olsa * Print the help text for the event symbols: 28221dc12760SJiri Olsa */ 2823c8d6828aSSukadev Bhattiprolu void print_events(const char *event_glob, bool name_only, bool quiet_flag, 2824a7f6c8c8SJin Yao bool long_desc, bool details_flag, bool deprecated) 28251dc12760SJiri Olsa { 28261dc12760SJiri Olsa print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 2827a3277d2dSFrederic Weisbecker event_symbols_hw, PERF_COUNT_HW_MAX, name_only); 28281dc12760SJiri Olsa 28291dc12760SJiri Olsa print_symbol_events(event_glob, PERF_TYPE_SOFTWARE, 2830a3277d2dSFrederic Weisbecker event_symbols_sw, PERF_COUNT_SW_MAX, name_only); 28315e0861baSAndi Kleen print_tool_events(event_glob, name_only); 28321dc12760SJiri Olsa 2833a3277d2dSFrederic Weisbecker print_hwcache_events(event_glob, name_only); 283473c24cb8SJaswinder Singh Rajput 2835bf874fcfSAndi Kleen print_pmu_events(event_glob, name_only, quiet_flag, long_desc, 2836a7f6c8c8SJin Yao details_flag, deprecated); 2837dc098b35SAndi Kleen 2838668b8788SArnaldo Carvalho de Melo if (event_glob != NULL) 2839668b8788SArnaldo Carvalho de Melo return; 284073c24cb8SJaswinder Singh Rajput 2841a3277d2dSFrederic Weisbecker if (!name_only) { 2842947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 28435f537a26SJiri Olsa "rNNN", 28441cf4a063SArnaldo Carvalho de Melo event_type_descriptors[PERF_TYPE_RAW]); 28455f537a26SJiri Olsa printf(" %-50s [%s]\n", 28465f537a26SJiri Olsa "cpu/t1=v1[,t2=v2,t3 ...]/modifier", 28475f537a26SJiri Olsa event_type_descriptors[PERF_TYPE_RAW]); 2848dfc431cbSArnaldo Carvalho de Melo if (pager_in_use()) 2849dfc431cbSArnaldo Carvalho de Melo printf(" (see 'man perf-list' on how to encode it)\n\n"); 285086470930SIngo Molnar 2851947b4ad1SIngo Molnar printf(" %-50s [%s]\n", 28523741eb9fSJacob Shin "mem:<addr>[/len][:access]", 285341bdcb23SLiming Wang event_type_descriptors[PERF_TYPE_BREAKPOINT]); 2854dfc431cbSArnaldo Carvalho de Melo if (pager_in_use()) 28551b290d67SFrederic Weisbecker printf("\n"); 2856a3277d2dSFrederic Weisbecker } 28571b290d67SFrederic Weisbecker 2858a3277d2dSFrederic Weisbecker print_tracepoint_events(NULL, NULL, name_only); 285940218daeSMasami Hiramatsu 286040218daeSMasami Hiramatsu print_sdt_events(NULL, NULL, name_only); 286171b0acceSAndi Kleen 286233bbc571SJiri Olsa metricgroup__print(true, true, NULL, name_only, details_flag); 2863*70943490SStephane Eranian 2864*70943490SStephane Eranian print_libpfm_events(name_only, long_desc); 286586470930SIngo Molnar } 28668f707d84SJiri Olsa 28676cee6cd3SArnaldo Carvalho de Melo int parse_events__is_hardcoded_term(struct parse_events_term *term) 28688f707d84SJiri Olsa { 286916fa7e82SJiri Olsa return term->type_term != PARSE_EVENTS__TERM_TYPE_USER; 28708f707d84SJiri Olsa } 28718f707d84SJiri Olsa 287267b49b38SJiri Olsa static int new_term(struct parse_events_term **_term, 287367b49b38SJiri Olsa struct parse_events_term *temp, 287467b49b38SJiri Olsa char *str, u64 num) 28758f707d84SJiri Olsa { 28766cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term; 28778f707d84SJiri Olsa 287867b49b38SJiri Olsa term = malloc(sizeof(*term)); 28798f707d84SJiri Olsa if (!term) 28808f707d84SJiri Olsa return -ENOMEM; 28818f707d84SJiri Olsa 288267b49b38SJiri Olsa *term = *temp; 28838f707d84SJiri Olsa INIT_LIST_HEAD(&term->list); 2884c2f1ceadSAndi Kleen term->weak = false; 28858f707d84SJiri Olsa 288667b49b38SJiri Olsa switch (term->type_val) { 28878f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_NUM: 28888f707d84SJiri Olsa term->val.num = num; 28898f707d84SJiri Olsa break; 28908f707d84SJiri Olsa case PARSE_EVENTS__TERM_TYPE_STR: 28918f707d84SJiri Olsa term->val.str = str; 28928f707d84SJiri Olsa break; 28938f707d84SJiri Olsa default: 28944be8be6bSAdrian Hunter free(term); 28958f707d84SJiri Olsa return -EINVAL; 28968f707d84SJiri Olsa } 28978f707d84SJiri Olsa 28988f707d84SJiri Olsa *_term = term; 28998f707d84SJiri Olsa return 0; 29008f707d84SJiri Olsa } 29018f707d84SJiri Olsa 29026cee6cd3SArnaldo Carvalho de Melo int parse_events_term__num(struct parse_events_term **term, 2903cecf3a2eSJiri Olsa int type_term, char *config, u64 num, 290499e7138eSJiri Olsa bool no_value, 2905bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 290616fa7e82SJiri Olsa { 2907bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 2908bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 2909bb78ce7dSAdrian Hunter 291067b49b38SJiri Olsa struct parse_events_term temp = { 291167b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_NUM, 291267b49b38SJiri Olsa .type_term = type_term, 291367b49b38SJiri Olsa .config = config, 291499e7138eSJiri Olsa .no_value = no_value, 291567b49b38SJiri Olsa .err_term = loc_term ? loc_term->first_column : 0, 291667b49b38SJiri Olsa .err_val = loc_val ? loc_val->first_column : 0, 291767b49b38SJiri Olsa }; 291867b49b38SJiri Olsa 291967b49b38SJiri Olsa return new_term(term, &temp, NULL, num); 292016fa7e82SJiri Olsa } 292116fa7e82SJiri Olsa 29226cee6cd3SArnaldo Carvalho de Melo int parse_events_term__str(struct parse_events_term **term, 2923cecf3a2eSJiri Olsa int type_term, char *config, char *str, 2924bb78ce7dSAdrian Hunter void *loc_term_, void *loc_val_) 292516fa7e82SJiri Olsa { 2926bb78ce7dSAdrian Hunter YYLTYPE *loc_term = loc_term_; 2927bb78ce7dSAdrian Hunter YYLTYPE *loc_val = loc_val_; 2928bb78ce7dSAdrian Hunter 292967b49b38SJiri Olsa struct parse_events_term temp = { 293067b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_STR, 293167b49b38SJiri Olsa .type_term = type_term, 293267b49b38SJiri Olsa .config = config, 293367b49b38SJiri Olsa .err_term = loc_term ? loc_term->first_column : 0, 293467b49b38SJiri Olsa .err_val = loc_val ? loc_val->first_column : 0, 293567b49b38SJiri Olsa }; 293667b49b38SJiri Olsa 293767b49b38SJiri Olsa return new_term(term, &temp, str, 0); 293816fa7e82SJiri Olsa } 293916fa7e82SJiri Olsa 29406cee6cd3SArnaldo Carvalho de Melo int parse_events_term__sym_hw(struct parse_events_term **term, 29411d33d6dcSJiri Olsa char *config, unsigned idx) 29421d33d6dcSJiri Olsa { 29431d33d6dcSJiri Olsa struct event_symbol *sym; 2944b6645a72SIan Rogers char *str; 294567b49b38SJiri Olsa struct parse_events_term temp = { 294667b49b38SJiri Olsa .type_val = PARSE_EVENTS__TERM_TYPE_STR, 294767b49b38SJiri Olsa .type_term = PARSE_EVENTS__TERM_TYPE_USER, 2948b6645a72SIan Rogers .config = config, 294967b49b38SJiri Olsa }; 29501d33d6dcSJiri Olsa 2951b6645a72SIan Rogers if (!temp.config) { 2952b6645a72SIan Rogers temp.config = strdup("event"); 2953b6645a72SIan Rogers if (!temp.config) 2954b6645a72SIan Rogers return -ENOMEM; 2955b6645a72SIan Rogers } 29561d33d6dcSJiri Olsa BUG_ON(idx >= PERF_COUNT_HW_MAX); 29571d33d6dcSJiri Olsa sym = &event_symbols_hw[idx]; 29581d33d6dcSJiri Olsa 2959b6645a72SIan Rogers str = strdup(sym->symbol); 2960b6645a72SIan Rogers if (!str) 2961b6645a72SIan Rogers return -ENOMEM; 2962b6645a72SIan Rogers return new_term(term, &temp, str, 0); 29631d33d6dcSJiri Olsa } 29641d33d6dcSJiri Olsa 29656cee6cd3SArnaldo Carvalho de Melo int parse_events_term__clone(struct parse_events_term **new, 29666cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term) 2967a6146d50SZheng Yan { 2968b6645a72SIan Rogers char *str; 296967b49b38SJiri Olsa struct parse_events_term temp = { 297067b49b38SJiri Olsa .type_val = term->type_val, 297167b49b38SJiri Olsa .type_term = term->type_term, 2972b6645a72SIan Rogers .config = NULL, 297367b49b38SJiri Olsa .err_term = term->err_term, 297467b49b38SJiri Olsa .err_val = term->err_val, 297567b49b38SJiri Olsa }; 297667b49b38SJiri Olsa 2977b6645a72SIan Rogers if (term->config) { 2978b6645a72SIan Rogers temp.config = strdup(term->config); 2979b6645a72SIan Rogers if (!temp.config) 2980b6645a72SIan Rogers return -ENOMEM; 2981b6645a72SIan Rogers } 2982b6645a72SIan Rogers if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) 2983b6645a72SIan Rogers return new_term(new, &temp, NULL, term->val.num); 2984b6645a72SIan Rogers 2985b6645a72SIan Rogers str = strdup(term->val.str); 2986b6645a72SIan Rogers if (!str) 2987b6645a72SIan Rogers return -ENOMEM; 2988b6645a72SIan Rogers return new_term(new, &temp, str, 0); 2989a6146d50SZheng Yan } 2990a6146d50SZheng Yan 29911dc92556SIan Rogers void parse_events_term__delete(struct parse_events_term *term) 29921dc92556SIan Rogers { 29931dc92556SIan Rogers if (term->array.nr_ranges) 29941dc92556SIan Rogers zfree(&term->array.ranges); 29951dc92556SIan Rogers 29961dc92556SIan Rogers if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) 29971dc92556SIan Rogers zfree(&term->val.str); 29981dc92556SIan Rogers 29991dc92556SIan Rogers zfree(&term->config); 30001dc92556SIan Rogers free(term); 30011dc92556SIan Rogers } 30021dc92556SIan Rogers 30038255718fSAndi Kleen int parse_events_copy_term_list(struct list_head *old, 30048255718fSAndi Kleen struct list_head **new) 30058255718fSAndi Kleen { 30068255718fSAndi Kleen struct parse_events_term *term, *n; 30078255718fSAndi Kleen int ret; 30088255718fSAndi Kleen 30098255718fSAndi Kleen if (!old) { 30108255718fSAndi Kleen *new = NULL; 30118255718fSAndi Kleen return 0; 30128255718fSAndi Kleen } 30138255718fSAndi Kleen 30148255718fSAndi Kleen *new = malloc(sizeof(struct list_head)); 30158255718fSAndi Kleen if (!*new) 30168255718fSAndi Kleen return -ENOMEM; 30178255718fSAndi Kleen INIT_LIST_HEAD(*new); 30188255718fSAndi Kleen 30198255718fSAndi Kleen list_for_each_entry (term, old, list) { 30208255718fSAndi Kleen ret = parse_events_term__clone(&n, term); 30218255718fSAndi Kleen if (ret) 30228255718fSAndi Kleen return ret; 30238255718fSAndi Kleen list_add_tail(&n->list, *new); 30248255718fSAndi Kleen } 30258255718fSAndi Kleen return 0; 30268255718fSAndi Kleen } 30278255718fSAndi Kleen 3028fc0a2c1dSArnaldo Carvalho de Melo void parse_events_terms__purge(struct list_head *terms) 30298f707d84SJiri Olsa { 30306cee6cd3SArnaldo Carvalho de Melo struct parse_events_term *term, *h; 30318f707d84SJiri Olsa 3032a8adfcebSWang Nan list_for_each_entry_safe(term, h, terms, list) { 3033a8adfcebSWang Nan list_del_init(&term->list); 30341dc92556SIan Rogers parse_events_term__delete(term); 30358f707d84SJiri Olsa } 3036a8adfcebSWang Nan } 3037b39b8393SJiri Olsa 30382146afc6SArnaldo Carvalho de Melo void parse_events_terms__delete(struct list_head *terms) 3039fc0a2c1dSArnaldo Carvalho de Melo { 30402146afc6SArnaldo Carvalho de Melo if (!terms) 30412146afc6SArnaldo Carvalho de Melo return; 3042fc0a2c1dSArnaldo Carvalho de Melo parse_events_terms__purge(terms); 3043d20a5f2bSWang Nan free(terms); 3044fc0a2c1dSArnaldo Carvalho de Melo } 3045fc0a2c1dSArnaldo Carvalho de Melo 30462d055bf2SWang Nan void parse_events__clear_array(struct parse_events_array *a) 30472d055bf2SWang Nan { 3048360e071bSTaeung Song zfree(&a->ranges); 30492d055bf2SWang Nan } 30502d055bf2SWang Nan 30515d9cdc11SArnaldo Carvalho de Melo void parse_events_evlist_error(struct parse_events_state *parse_state, 3052b39b8393SJiri Olsa int idx, const char *str) 3053b39b8393SJiri Olsa { 3054448d732cSIan Rogers if (!parse_state->error) 3055a6ced2beSAdrian Hunter return; 3056448d732cSIan Rogers 3057448d732cSIan Rogers parse_events__handle_error(parse_state->error, idx, strdup(str), NULL); 3058b39b8393SJiri Olsa } 3059ffeb883eSHe Kuang 306017cb5f84SWang Nan static void config_terms_list(char *buf, size_t buf_sz) 306117cb5f84SWang Nan { 306217cb5f84SWang Nan int i; 306317cb5f84SWang Nan bool first = true; 306417cb5f84SWang Nan 306517cb5f84SWang Nan buf[0] = '\0'; 306617cb5f84SWang Nan for (i = 0; i < __PARSE_EVENTS__TERM_TYPE_NR; i++) { 306717cb5f84SWang Nan const char *name = config_term_names[i]; 306817cb5f84SWang Nan 30691669e509SWang Nan if (!config_term_avail(i, NULL)) 30701669e509SWang Nan continue; 307117cb5f84SWang Nan if (!name) 307217cb5f84SWang Nan continue; 307317cb5f84SWang Nan if (name[0] == '<') 307417cb5f84SWang Nan continue; 307517cb5f84SWang Nan 307617cb5f84SWang Nan if (strlen(buf) + strlen(name) + 2 >= buf_sz) 307717cb5f84SWang Nan return; 307817cb5f84SWang Nan 307917cb5f84SWang Nan if (!first) 308017cb5f84SWang Nan strcat(buf, ","); 308117cb5f84SWang Nan else 308217cb5f84SWang Nan first = false; 308317cb5f84SWang Nan strcat(buf, name); 308417cb5f84SWang Nan } 308517cb5f84SWang Nan } 308617cb5f84SWang Nan 3087ffeb883eSHe Kuang /* 3088ffeb883eSHe Kuang * Return string contains valid config terms of an event. 3089ffeb883eSHe Kuang * @additional_terms: For terms such as PMU sysfs terms. 3090ffeb883eSHe Kuang */ 3091ffeb883eSHe Kuang char *parse_events_formats_error_string(char *additional_terms) 3092ffeb883eSHe Kuang { 3093ffeb883eSHe Kuang char *str; 3094626a6b78SWang Nan /* "no-overwrite" is the longest name */ 309517cb5f84SWang Nan char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * 3096626a6b78SWang Nan (sizeof("no-overwrite") - 1)]; 3097ffeb883eSHe Kuang 309817cb5f84SWang Nan config_terms_list(static_terms, sizeof(static_terms)); 3099ffeb883eSHe Kuang /* valid terms */ 3100ffeb883eSHe Kuang if (additional_terms) { 310126dee028SWang Nan if (asprintf(&str, "valid terms: %s,%s", 310226dee028SWang Nan additional_terms, static_terms) < 0) 3103ffeb883eSHe Kuang goto fail; 3104ffeb883eSHe Kuang } else { 310526dee028SWang Nan if (asprintf(&str, "valid terms: %s", static_terms) < 0) 3106ffeb883eSHe Kuang goto fail; 3107ffeb883eSHe Kuang } 3108ffeb883eSHe Kuang return str; 3109ffeb883eSHe Kuang 3110ffeb883eSHe Kuang fail: 3111ffeb883eSHe Kuang return NULL; 3112ffeb883eSHe Kuang } 3113